圖2中左圖為原圖,中圖為gamma = 1/2.2在校正結果,原圖中左半側的灰度值較高,右半側的灰度值較低,經過gamma = 1/2.2校正后(中圖),左側的對比度降低(見胡須),右側在對比度提高(明顯可以看清面容),同時圖像在的整體灰度值提高。
右圖為gamma = 2.2在校正結果,校正后,左側的對比度提高(見胡須),右側在對比度降低(面容更不清楚了),同時圖像在的整體灰度值降低。
值得一提的是,人眼是按照gamma < 1的曲線對輸入圖像進行處理的。
參考資料:
[1] http://en.wikipedia.org/wiki/Gamma_correction
[2] http://www.cambridgeincolour.com/tutorials/gamma-correction.htm
[3] https://github.com/bytefish/opencv/blob/master/misc/tan_triggs.cpp
代碼:
#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;
}