伽马校正(Gamma correction) 又叫伽马非线性化(gamma nonlinearity)、伽马编码(gamma encoding) 或是就只单纯叫伽马(gamma)。是用来针对影片或是影像系统里对于光线的(luminance)或是三色刺激值(tristimulus values)所进行非线性的运算或反运算。
维基百科
1、公式
其中A是一个常量,输入和输出的值都为非负实数值。一般地来说在A=1的通常情况下,输入输出的值的范围都是在0到1之间。伽马值γ < 1的情况有时被称作编码伽马值(encoding gamma),而执行这个编码运算所使用上述的过程也叫做伽马压缩(gamma compression);相对地,伽马值γ > 1的情况有时也被称作解码伽马值(decoding gamma),而执行这个解码运算所使用上述的过程也叫做“伽马展开(gamma expansion)”。
2、解释
3、详解
1、什么是Gamma曲线矫正?
Gamma曲线矫正是什么意思?Gamma曲线是一种特殊的色调曲线,当Gamma值等于1的时候,曲线为与坐标轴成45°的直线,这个时候表示输入和输出密度相同。高于1的Gamma值将会造成输出亮化,低于1的Gamma值将会造成输出暗化。总之,我们的要求是输入和输出比率尽可能地接近于1。在显示器、扫描仪、打印机等输入、输出设备中这是一个相当常见并且比较重要的概念。在计算机系统中,由于显卡或者显示器的原因会出现实际输出的图像在亮度上有偏差,而Gamma曲线矫正就是通过一定的方法来矫正图像的这种偏差的方法。一般情况下,当用于Gamma矫正的值大于1时,图像的高光部分被压缩而暗调部分被扩展,当Gamma矫正的值小于1时,图像的高光部分被扩展而暗调部分被压缩,Gamma矫正一般用于平滑的扩展暗调的细节。
2、Gamma 矫正代码
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 10 using namespace cv;11 using namespace std;12 13 void GammaCorrection(Mat& src, Mat& dst, float fGamma)14 {15 unsigned char lut[256];16 for (int i = 0; i < 256; i++)17 {18 lut[i] = saturate_cast (pow((float)(i / 255.0), fGamma) * 255.0f);19 }20 21 dst = src.clone();22 const int channels = dst.channels();23 switch (channels)24 {25 case 1: 26 {27 28 MatIterator_ it, end;29 for (it = dst.begin (), end = dst.end (); it != end; it++)30 * it = lut[(*it)];31 32 break;33 }34 case 3:35 {36 37 MatIterator_ it, end;38 for (it = dst.begin (), end = dst.end (); it != end; it++)39 {40 (*it)[0] = lut[((*it)[0])];41 (*it)[1] = lut[((*it)[1])];42 (*it)[2] = lut[((*it)[2])];43 }44 45 break;46 47 }48 default:49 break;50 }51 }52 53 int main()54 {55 Mat image = imread("D://Images/wrong/2.jpg");56 if (image.empty())57 {58 cout << "Error: Could not load image" << endl;59 return 0;60 }61 Mat dst;62 float fGamma = 1 / 1.8;63 GammaCorrection(image, dst, fGamma);64 imwrite("D://Images/wrong/24.jpg", dst);65 waitKey();66 67 return 0;68 }
1 package org.jaiken.tools; 2 3 import org.opencv.core.Core; 4 import org.opencv.core.CvType; 5 import org.opencv.core.Mat; 6 import org.opencv.imgcodecs.Imgcodecs; 7 8 public class GammaCorrection { 9 // 伽马校正10 public Mat gamma(Mat src) {11 Mat x = new Mat();12 src.convertTo(x, CvType.CV_32FC3);13 Mat i = new Mat();14 15 Core.pow(x, 1/1.8, i);16 Mat dst = new Mat();17 // 归一化18 Core.normalize(i, dst, 0, 255, Core.NORM_MINMAX, 0);19 Imgcodecs.imwrite("D://Images/wrong/22.jpg", dst);20 return dst;21 }22 23 public static void main(String[] args) {24 System.load("D://Export/opencv_java320.dll");25 Mat src = Imgcodecs.imread("D://Images/wrong/2.jpg",0);26 if (src.empty()) {27 System.err.println("The picture doesn't exist");28 return;29 }30 GammaCorrection gammaCorrection = new GammaCorrection();31 gammaCorrection.gamma(src);32 }33 34 }
效果图
这样还仅能看出图像亮度上的变化,体会不到细节上的变化,这样用阈值化和Blob 分析的方法检测下两张图像,结果图如下。
结果很明显的第四列,第五行的图像细节上更加清楚,处理结果更加的的好,而没有了图像上"线"的干扰。