Gamma校正是對輸入圖像灰度值進行的非線性操作,使輸出圖像灰度值與輸入圖像灰度值呈指數關系:
A是一個常數,通常取1,這個指數即為Gamma。
Gamma校正的原理很簡單,就一個很簡單的表達式,如下圖所示:
其中V_in的取值范圍是0~1,最重要的參數就是公式中的γ參數!
γ的值決定了輸入圖像和輸出圖像之間的灰度映射方式,即決定了是增強低灰度值區域還是增高灰度值區域。
γ>1時,圖像的高灰度區域對比度得到增強。
γ<1時,圖像的低灰度區域對比度得到增強。
γ=1時,不改變原圖像。
伽馬變換對於圖像對比度偏低,並且整體亮度值偏高(對於於相機過曝)情況下的圖像增強效果明顯。

1 #include <opencv2/highgui/highgui.hpp> 2 #include <opencv2/imgproc/imgproc.hpp> 3 4 using namespace cv; 5 6 int main(int argc, char *argv[]) 7 { 8 Mat image = imread("D:\\Gamma校正.jpg"); 9 Mat imageGamma(image.size(), CV_32FC3); 10 for (int i = 0; i < image.rows; i++) 11 { 12 for (int j = 0; j < image.cols; j++) 13 { 14 imageGamma.at<Vec3f>(i, j)[0] = (image.at<Vec3b>(i, j)[0])*(image.at<Vec3b>(i, j)[0])*(image.at<Vec3b>(i, j)[0]); 15 imageGamma.at<Vec3f>(i, j)[1] = (image.at<Vec3b>(i, j)[1])*(image.at<Vec3b>(i, j)[1])*(image.at<Vec3b>(i, j)[1]); 16 imageGamma.at<Vec3f>(i, j)[2] = (image.at<Vec3b>(i, j)[2])*(image.at<Vec3b>(i, j)[2])*(image.at<Vec3b>(i, j)[2]); 17 } 18 } 19 //歸一化到0~255 20 normalize(imageGamma, imageGamma, 0, 255, CV_MINMAX); 21 //轉換成8bit圖像顯示 22 convertScaleAbs(imageGamma, imageGamma); 23 imshow("原圖", image); 24 imshow("伽馬變換圖像增強效果", imageGamma); 25 waitKey(); 26 return 0; 27 }

1 //////朱偉opencv圖像處理編程實例 2 #include <iostream> 3 #include <opencv2\core\core.hpp> 4 #include <opencv2\highgui\highgui.hpp> 5 #include <opencv2\imgproc\imgproc.hpp> 6 #include<cmath> 7 using namespace cv; 8 9 Mat gammaTransform(Mat &srcImage, float kFactor) 10 { 11 12 unsigned char LUT[256]; 13 for (int i = 0; i < 256; i++) 14 { 15 float f = (i + 0.5f) / 255; 16 f = (float)(pow(f, kFactor)); 17 LUT[i] = saturate_cast<uchar>(f*255.0f - 0.5f); 18 } 19 Mat resultImage = srcImage.clone(); 20 21 if (srcImage.channels() == 1) 22 { 23 24 MatIterator_<uchar> iterator = resultImage.begin<uchar>(); 25 MatIterator_<uchar> iteratorEnd = resultImage.end<uchar>(); 26 for (; iterator != iteratorEnd; iterator++) 27 { 28 *iterator = LUT[(*iterator)]; 29 } 30 } 31 else 32 { 33 34 35 MatIterator_<Vec3b> iterator = resultImage.begin<Vec3b>(); 36 MatIterator_<Vec3b> iteratorEnd = resultImage.end<Vec3b>(); 37 for (; iterator != iteratorEnd; iterator++) 38 { 39 (*iterator)[0] = LUT[((*iterator)[0])];//b 40 (*iterator)[1] = LUT[((*iterator)[1])];//g 41 (*iterator)[2] = LUT[((*iterator)[2])];//r 42 } 43 } 44 return resultImage; 45 } 46 int main() 47 { 48 Mat srcImage = imread("D:\\小女孩與熊.jpg"); 49 if (!srcImage.data) 50 { 51 printf("could not load image...\n"); 52 return -1; 53 } 54 //取兩種不同的gamma值 55 float gamma1 = 3.33f; 56 float gamma2 = 0.33f; 57 float kFactor1 = 1 / gamma1; 58 float kFactor2 = 1 / gamma2; 59 Mat result1 = gammaTransform(srcImage, kFactor1); 60 Mat result2 = gammaTransform(srcImage, kFactor2); 61 imshow("srcImage", srcImage); 62 imshow("res1", result1); 63 imshow("res2", result2); 64 waitKey(0); 65 return 0; 66 }
對數Log變換:
對數變換對於整體對比度偏低並且灰度值偏低的圖像增強效果較好。

1 /////////////////////////////////////對數Log變換//////////////////////////////////////// 2 ////https://blog.csdn.net/dcrmg/article/details/53677739 3 #include <opencv2/highgui/highgui.hpp> 4 #include <opencv2/imgproc/imgproc.hpp> 5 6 using namespace cv; 7 8 int main(int argc, char *argv[]) 9 { 10 Mat image = imread("D:\\對數Log變換.jpg"); 11 Mat imageLog(image.size(), CV_32FC3); 12 for (int i = 0; i < image.rows; i++) 13 { 14 for (int j = 0; j < image.cols; j++) 15 { 16 imageLog.at<Vec3f>(i, j)[0] = log(1 + image.at<Vec3b>(i, j)[0]); 17 imageLog.at<Vec3f>(i, j)[1] = log(1 + image.at<Vec3b>(i, j)[1]); 18 imageLog.at<Vec3f>(i, j)[2] = log(1 + image.at<Vec3b>(i, j)[2]); 19 } 20 } 21 //歸一化到0~255 22 normalize(imageLog, imageLog, 0, 255, CV_MINMAX); 23 //轉換成8bit圖像顯示 24 convertScaleAbs(imageLog, imageLog); 25 imshow("Soure", image); 26 imshow("after", imageLog); 27 waitKey(); 28 return 0; 29 }
參考鏈接:
https://blog.csdn.net/linqianbi/article/details/78617615
https://blog.csdn.net/dcrmg/article/details/53677739
https://blog.csdn.net/lxy201700/article/details/24929013
其他: