1. 程式人生 > >0020-在OpenCV環境下對影象做Gamma校正

0020-在OpenCV環境下對影象做Gamma校正

什麼是Gamma校正
Gamma校正是對輸入影象灰度值進行的非線性操作,使輸出影象灰度值與輸入影象灰度值呈指數關係。

上面中的指數γ即為Gamma.
經過Gamma校正後的輸入和輸出影象灰度值關係如下圖所示:橫座標是輸入灰度值,縱座標是輸出灰度值,藍色曲線是gamma值小於1時的輸入輸出關係,紅色曲線是gamma值大於1時的輸入輸出關係。可以觀察到,當gamma值小於1時(藍色曲線),影象的整體亮度值得到提升,同時低灰度處的對比度增加,高灰度處的對比度降低,更利於分辯低灰度值時的影象細節;當gamma值大於1時(紅色曲線),影象的整體亮度值得到減小,同時低灰度處的對比度降低,高灰度處的對比度增加,更利於分辯高灰度值時的影象細節。

​​
為什麼要進行Gamma校正
人眼對外界光源的感光值與輸入光強不是呈線性關係的,而是呈指數型關係的。在低照度下,人眼更容易分辨出亮度的變化,隨著照度的增加,人眼不易分辨出亮度的變化。而攝像機感光與輸入光強呈線性關係。OpenCV環境下對影象進行Gamma校正的原始碼如下

影象處理開發資料、影象處理開發需求、影象處理接私活掙零花錢,可以搜尋公眾號"qxsf321",並關注!
原始碼中用到的影象下載連結:http://pan.baidu.com/s/1miIGyqW 密碼:bz9r

//opencv版本:OpenCV3.0
//VS版本:VS2013
//Author:qxsf321.net

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>    
#include <opencv2/imgproc/types_c.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>

#include <iostream>

using namespace cv;
using namespace std;

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("gamma_pending.jpg");
        if (image.empty())
        {
                cout << "Error: Could not load image" << endl;
                return 0;
        }

        Mat dst;
        float fGamma=1/2.2;
        MyGammaCorrection(image, dst, fGamma);

        imshow("Source Image", image);
        imshow("Dst", dst);

        waitKey();

        return 0;
}


執行結果截圖如下


從執行結果中我們可以看出
最左邊的圖為原圖,中圖為gamma = 1/2.2時的校正結果,原圖中左半側的灰度值較高,右半側的灰度值較低,經過gamma=1/2.2校正後(中圖),左側的對比度降低(見鬍鬚),右側在對比度提高(明顯可以看清面容),同時影象在的整體灰度值提高。
最右邊的圖為gamma = 2.2在校正結果,校正後,左側的對比度提高(見鬍鬚),右側在對比度降低(面容更不清楚了),同時影象在的整體灰度值降低。

值得一提的是:人眼是按照gamma<1的曲線對自己看到的影象進行校正的