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 <opencv2corecore.hpp> 4 #include <opencv2highguihighgui.hpp> 5 #include <opencv2imgprocimgproc.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... "); 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
其他: