昊虹AI笔记网

 找回密码
 立即注册
搜索
查看: 832|回复: 0
收起左侧

图像Gamma(伽玛)校正的原理及OpenCV代码实现

[复制链接]

238

主题

241

帖子

931

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
931
昊虹君 发表于 2023-3-6 12:03 | 显示全部楼层 |阅读模式
什么是Gamma校正?

Gamma校正是对输入图像灰度值进行的非线性操作,使输出图像灰度值与输入图像灰度值呈指数关系。

Gamma校正的原理表达式如下:


上面中的指数γ即为Gamma。这就是Gamma校正的名称来历。

其中的取值范围是0~1,最重要的参数就是式子中的参数γ。

γ的值决定了输入图像和输出图像之间的灰度映射方式,即决定了是增强低灰度值区域还是增高灰度值区域。
γ>1时,即下图中的红色曲线,图像的高灰度区域对比度得到增强,直观效果是一幅偏亮的图变暗了下来。
γ<1时,即下图中的蓝色曲线,图像的低灰度区域对比度得到增强,直观效果是一幅偏暗的图变亮了起来。
γ=1时,不改变原图像。

Gamma校正表达式的曲线图如下:


横坐标是输入灰度值,纵坐标是输出灰度值,蓝色曲线是gamma值小于1时的输入输出关系,红色曲线是gamma值大于1时的输入输出关系。
可以观察到,当gamma值小于1时(蓝色曲线),图像的整体亮度值得到提升,同时低灰度处的对比度增加,高灰度处的对比度降低,更利于分辩低灰度值时的图像细节;
当gamma值大于1时(红色曲线),图像的整体亮度值得到减小,同时低灰度处的对比度降低,高灰度处的对比度增加,更利于分辩高灰度值时的图像细节。

为什么要进行Gamma校正?
一个典型的例子:人眼对外界光源的感光值与输入光强不是呈线性关系的,而是呈指数型关系的。在低照度下,人眼更容易分辨出亮度的变化,随着照度的增加,人眼不易分辨出亮度的变化。而相机感光与输入光强呈线性关系。为了适应我们人眼的特性,我们就需要对相机拍摄得到的原始图像作Gamma校正。

在OpenCV环境下实现的Gamma校正代码如下:
[C++] 纯文本查看 复制代码
//出处:昊虹AI笔记网(hhai.cc)
//用心记录计算机视觉和AI技术

//博主微信/QQ 2487872782
//QQ群 271891601
//欢迎技术交流与咨询

//OpenCV版本 OpenCV3.0

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

 
void MyGammaCorrection(Mat& src, Mat& dst, float fGamma)  
{  
 
    // build look up table  
    unsigned char lut[256];  
    for( int i = 0; i < 256; i++ )  
    {  
        lut[i] = saturate_cast<uchar>(pow((float)(i/255.0), fGamma) * 255.0f);  
    }  
 
    dst = src.clone();  
    const int channels = dst.channels();  
    switch(channels)  
    {  
        case 1:   //灰度图的情况
            {  
 
                MatIterator_<uchar> it, end;  
                for( it = dst.begin<uchar>(), end = dst.end<uchar>(); it != end; it++ )  
                    //*it = pow((float)(((*it))/255.0), fGamma) * 255.0;  
                    *it = lut[(*it)];  
 
                break;  
            }  
        case 3:  //彩色图的情况
            {  
 
                MatIterator_<Vec3b> it, end;  
                for( it = dst.begin<Vec3b>(), end = dst.end<Vec3b>(); it != end; it++ )  
                {  
                    //(*it)[0] = pow((float)(((*it)[0])/255.0), fGamma) * 255.0;  
                    //(*it)[1] = pow((float)(((*it)[1])/255.0), fGamma) * 255.0;  
                    //(*it)[2] = pow((float)(((*it)[2])/255.0), fGamma) * 255.0;  
                    (*it)[0] = lut[((*it)[0])];  
                    (*it)[1] = lut[((*it)[1])];  
                    (*it)[2] = lut[((*it)[2])];  
                }  
 
                break;  
 
            }  
    }  
}  
 
int main()
{
         Mat image = imread("E:/material/images/P0034-Gamma-correction.jpg");
        if (image.empty())
        {
                cout << "Error: Could not load image" << endl;
                return 0;
        }
 
        Mat dst1;
		Mat dst2;
        float fGamma1=1/2.2;
		float fGamma2=2;
        MyGammaCorrection(image, dst1, fGamma1);
		MyGammaCorrection(image, dst2, fGamma2);

		cv::namedWindow("Source Image", WINDOW_NORMAL);
		cv::namedWindow("Gamma=1/2.2", WINDOW_NORMAL);
		cv::namedWindow("Gamma=2", WINDOW_NORMAL);
 
        imshow("Source Image", image);
        imshow("Gamma=1/2.2", dst1);
		imshow("Gamma=2", dst2);

 
        waitKey();
 
        return 0;
}

运行结果如下:

从上面的结果中我们可以看出,当γ值小于1时,图像的低灰度区域对比度得到了增强,这样就使得一幅偏暗的图变得明亮了起来;而当γ值大于1时,图像的高灰度区域对比度得到了增强,这就会使得一幅偏亮的图暗下来。

接下来再测试下彩色图片的效果。

用下面这张图进行测试:


上面这张图的百度网盘下载链接:
链接:https://pan.baidu.com/s/1FPaoTbFRKITnVtvFIoL1Yw?pwd=eq8i

运行效果如下图所示:

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|昊虹AI笔记网 ( 蜀ICP备2024076726 )

GMT+8, 2024-5-19 10:42 , Processed in 0.024997 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表