http://blog.csdn.net/u013286409/article/details/50239377

圖2中左圖為原圖,中圖為gamma = 1/2.2在校正結果,原圖中左半側的灰度值較高,右半側的灰度值較低,經過gamma = 1/2.2校正后(中圖),左側的對比度降低(見胡須),右側在對比度提高(明顯可以看清面容),同時圖像在的整體灰度值提高。
右圖為gamma = 2.2在校正結果,校正后,左側的對比度提高(見胡須),右側在對比度降低(面容更不清楚了),同時圖像在的整體灰度值降低。
值得一提的是,人眼是按照gamma < 1的曲線對輸入圖像進行處理的。
- #include <opencv2/core/core.hpp>
- #include <opencv2/imgproc/imgproc.hpp>
- #include <opencv2/highgui/highgui.hpp>
- #include <iostream>
- using namespace cv;
- using namespace std;
- // Normalizes a given image into a value range between 0 and 255.
- Mat norm_0_255(const Mat& src) {
- // Create and return normalized image:
- Mat dst;
- switch(src.channels()) {
- case 1:
- cv::normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
- break;
- case 3:
- cv::normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC3);
- break;
- default:
- src.copyTo(dst);
- break;
- }
- return dst;
- }
- int main(int argc, const char *argv[]) {
- // Get filename to the source image:
- if (argc != 2) {
- cout << "usage: " << argv[0] << " <image.ext>" << endl;
- exit(1);
- }
- // Load image & get skin proportions:
- //Mat image = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
- Mat image = imread(argv[1], CV_LOAD_IMAGE_COLOR);
- // Convert to floating point:
- Mat X;
- image.convertTo(X, CV_32FC1);
- //image.convertTo(X, CV_32F);
- // Start preprocessing:
- Mat I;
- float gamma = 1/2.2;
- pow(X, gamma, I);
- // Draw it on screen:
- imshow("Original Image", image);
- imshow("Gamma correction image", norm_0_255(I));
- //imwrite("origin.jpg", image);
- imwrite("gamma_inv2.2.jpg", norm_0_255(I));
- // Show the images:
- waitKey(0);
- // Success!
- return 0;
- }
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
// Normalizes a given image into a value range between 0 and 255.
Mat norm_0_255(const Mat& src) {
// Create and return normalized image:
Mat dst;
switch(src.channels()) {
case 1:
cv::normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
break;
case 3:
cv::normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC3);
break;
default:
src.copyTo(dst);
break;
}
return dst;
}
int main(int argc, const char *argv[]) {
// Get filename to the source image:
if (argc != 2) {
cout << "usage: " << argv[0] << " <image.ext>" << endl;
exit(1);
}
// Load image & get skin proportions:
//Mat image = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
Mat image = imread(argv[1], CV_LOAD_IMAGE_COLOR);
// Convert to floating point:
Mat X;
image.convertTo(X, CV_32FC1);
//image.convertTo(X, CV_32F);
// Start preprocessing:
Mat I;
float gamma = 1/2.2;
pow(X, gamma, I);
// Draw it on screen:
imshow("Original Image", image);
imshow("Gamma correction image", norm_0_255(I));
//imwrite("origin.jpg", image);
imwrite("gamma_inv2.2.jpg", norm_0_255(I));
// Show the images:
waitKey(0);
// Success!
return 0;
}
Gamma 校正
問題:什么是Gamma曲線矯正?Gamma曲線矯正是什么意思?
Gamma曲線是一種特殊的色調曲線,當Gamma值等於1的時候,曲線為與坐標軸成45°的直線,這個時候表示輸入和輸出密度相同。高於1的Gamma值將會造成輸出亮化,低於1的Gamma值將會造成輸出暗化。總之,我們的要求是輸入和輸出比率盡可能地接近於1。在顯示器、掃描儀、打印機等輸入、輸出設備中這是一個相當常見並且比較重要的概念。在計算機系統中,由於顯卡或者顯示器的原因會出現實際輸出的圖像在亮度上有偏差,而Gamma曲線矯正就是通過一定的方法來矯正圖像的這種偏差的方法。一般情況下,當用於Gamma矯正的值大於1時,圖像的高光部分被壓縮而暗調部分被擴展,當Gamma矯正的值小於1時,圖像的高光部分被擴展而暗調部分被壓縮,Gamma矯正一般用於平滑的擴展暗調的細節。
圖1顯示的是一般CRT顯示器的亮度響應曲線,可以看到其輸入電壓提高一倍,亮度輸出並不是提高一倍,而是接近於兩倍,顯然這樣輸出的圖像同原來的圖像相比就發生了輸出亮化的現象,也就是說未經過Gamma矯正的CRT顯示器其Gamma值是小於1的。
沒有經過Gamma矯正的設備會影響最終輸出圖像的顏色亮度,比如一種顏色由紅色和綠色組成,紅色的亮度為50%,綠色的亮度為25%,如果一個未經過Gamma矯正的CRT顯示器的Gamma值是2.5,那么輸出結果的亮度將分別為18%和3%,其亮度大大的降低了。
圖2 按圖進行曲線補償
為了補償這方面的不足,我們需要使用反效果補償曲線來讓顯示器盡可能地輸出同輸入圖像相同的圖像,所以這個時候顯示器的輸入信號應該按照圖2所示的曲線進行補償,這樣才能在顯示器上得到比較理想的輸出結果。
一般的反效果可以直接被賦予存儲在幀緩存中的圖像,使之Gamma曲線呈非線性,也可以通過RAMDAC進行這種反效果補償(或者說是Gamma曲線矯正)。這樣我們就可以在顯示器上看到同我們輸入的圖像接近的圖像了(如圖3)。當然圖3所示的曲線只是理想狀態下的情況,在實際應用中我們並不可能得到如此完美的曲線,所以不同的廠商之間所競爭的就是誰能做到最接近於這個效果。
顯示器的gamma值是用於定義一個顯示器的顯示特性的數學方法,是決定顯示器從黑色到白色的值。簡單的說,當顯示一個顏色從黑到白時(也就是0到1),顯示器的電壓也要隨之變化,但這個變化不是線性的。因為顯示器的物理特性決定了如果電壓的變化是線性的,顯示出來的亮度就不是線性的,這時,顯示的亮度就會很暗。所以,為了保整顯示出來的亮度是正常(線性)的,就需要對顯示器的電壓變化加以校正,這個值就是我們通常所說的gamma值。通常情況只有在調整HDRI圖片時和在做動畫渲染時會用到。
γ校正(Gamma Correction,伽瑪校正):所 謂伽瑪校正就是對圖像的伽瑪曲線進行編輯,以對圖像進行非線性色調編輯的方法,檢出圖像信號中的深色部分和淺色部分,並使兩者比例增大,從而提高圖像對比 度效果。計算機繪圖領域慣以此屏幕輸出電壓與對應亮度的轉換關系曲線,稱為伽瑪曲線(Gamma Curve)。以傳統CRT(Cathode Ray Tube)屏幕的特性而言,該曲線通常是一個乘冪函數,Y=(X+e)γ,其中,Y為亮度、X為輸出電壓、e為補償系數、乘冪值(γ)為伽瑪值,改變乘冪 值(γ)的大小,就能改變CRT的伽瑪曲線。典型的Gamma值是0.45,它會使CRT的影像亮度呈現線性。使用CRT的電視機等顯示器屏幕,由於對於 輸入信號的發光灰度,不是線性函數,而是指數函數,因此必需校正。
在電視和圖形監視器中,顯像管發生的電子束及其生成的圖像亮度並不是隨顯像管的輸入電壓線性變化,電子流與輸入電壓相比是按照指數曲線變化的,輸入 電壓的指數要大於電子束的指數。這說明暗區的信號要比實際情況更暗,而亮區要比實際情況更高。所以,要重現攝像機拍攝的畫面,電視和監視器必須進行伽瑪補 償。這種伽瑪校正也可以由攝像機完成。我們對整個電視系統進行伽瑪補償的目的,是使攝像機根據入射光亮度與顯像管的亮度對稱而產生的輸出信號,所以應對圖 像信號引入一個相反的非線性失真,即與電視系統的伽瑪曲線對應的攝像機伽瑪曲線,它的值應為1/γ,我們稱為攝像機的伽瑪值。電視系統的伽瑪值約為 2.2,所以電視系統的攝像機非線性補償伽瑪值為0.45。彩色顯像管的伽瑪值為2.8,它的圖像信號校正指數應為1/2.8=0.35,但由於顯像管內 外雜散光的影響,重現圖像的對比度和飽和度均有所降低,所以現在的彩色攝像機的伽瑪值仍多采用0.45。在實際應用中,我們可以根據實際情況在一定范圍內 調整伽瑪值,以獲得最佳效果。
今天有個朋友問γ校正的用處,這里簡單說一下:
伽馬校正最初是由於顯示器的陰極現象管(也就是物理上所說的示波管的陰極射線版)的成像扭曲引起的,為了不使畫面失真所以就用先特殊算法進行校正,此之謂γ校正。
γ校正的原理是修改顯示系統的配色方案,本來顯示系統輸出的r g b電子槍線性的根據顯存中的各個顏色值輸出對應的控制電壓,但是通過伽碼校正可以把某個顏色值對應的輸出電壓調整高或調整低。達到校正顯示系統色澤的目的。同時可以用軟件的方法校正,就是對一副圖片設定某個顏色的顏色值變換成新的顏色值的對照表,然后用新的顏色值取代原來圖片中對應的顏色就行了呀。比如你先編寫一個控制rgb各個分量對應關系的曲線調節器,在曲線調節器里面調整控制曲線設置原來顏色多少對應目標顏色多少,然后根據設定的關系,修改要調整色澤的圖片每一個像素的顏色就可以了。
數學公式可以深刻和精確的把握一個概念,卻不能表達概念的物理意義和本質含義,本貼試圖擺脫數學公式的陳述和推導,用言語來解釋gamma的本質含義。
原文鏈接:
http://blog.csdn.net/lichengyu/article/details/20840135
http://www.downhot.com/show/dnjc/160420120603552393894.html



