opencv學習筆記-圖像對比度、亮度調節


在數學中我們學過線性理論,在圖像亮度和對比度調節中同樣適用,看下面這個公式:

在圖像像素中其中:

  • 參數f(x)表示源圖像像素。
  • 參數g(x) 表示輸出圖像像素。
  • 參數a(需要滿足a>0)被稱為增益(gain),常常被用來控制圖像的對比度。
  • 參數b通常被稱為偏置(bias),常常被用來控制圖像的亮度。

一、獲取圖像像素

在opencv中圖像數據是存放在Mat數據類型中,我們知道一個像素有rgb構成,所以Mat是個三維數組,一下就是簡單的獲取mat中圖像像素。

//三個for循環,執行運算 new_image(i,j) =a*image(i,j) + b
       for(int y = 0; y < image.rows; y++ )
       {
              for(int x = 0; x < image.cols; x++ )
              {
                     for(int c = 0; c < 3; c++ )
                     {
                            new_image.at<Vec3b>(y,x)[c]= saturate_cast<uchar>( (g_nContrastValue*0.01)*(image.at<Vec3b>(y,x)[c] ) + g_nBrightValue );
                     }
              }
       }

上述代碼中image.at<Vec3b>(y,x)[c] 其中,y是像素所在的行, x是像素所在的列, c是R、G、B(對應0、1、2)其中之一。

saturate_cast為了安全轉換,運算結果可能超出像素取值范圍(溢出),還可能是非整數(如果是浮點數的話),用saturate_cast對結果進行轉換,以確保它為有效值。

二、實例程序

tatic void ContrastAndBright(int, void *);  
//-----------------------------------【main( )函數】--------------------------------------------
//    描述:控制台應用程序的入口函數,我們的程序從這里開始
//-----------------------------------------------------------------------------------------------
string strWindowName = "對比度亮度效果圖";
string strTraName = "對比度";
string strTraName1 = "亮度";
int g_nContraValue = 0;
int g_nBrightValue = 0;
Mat g_srcImage,g_dstImage;  
int main(   )
{
    system("color 5E");
    g_srcImage= imread("dota_jugg.jpg");
    if(!g_srcImage.data ) { printf("Oh,no,讀取g_srcImage圖片錯誤~!\n"); return -1; }  
    g_dstImage= Mat::zeros( g_srcImage.size(), g_srcImage.type() );
    //創建窗口  
    namedWindow("【原始圖窗口】", 1);  
    //顯示圖像  
    imshow("【原始圖窗口】", g_srcImage);  
    namedWindow(strWindowName);
    createTrackbar(strTraName,strWindowName,&g_nContraValue,100,ContrastAndBright);
    createTrackbar(strTraName1,strWindowName,&g_nBrightValue,100,ContrastAndBright);
    /*if(MultiChannelBlending( ))
    {
        cout<<endl<<"嗯。好了,得出了你需要的混合值圖像~";
    }*/
    //調用回調函數  
 
    
    waitKey(0);
    return 0;
}
void ContrastAndBright(int, void *)
{
    

    //三個for循環,執行運算 g_dstImage(i,j) =a*g_srcImage(i,j) + b  
    for(int y = 0; y < g_srcImage.rows; y++ )  
    {  
        for(int x = 0; x < g_srcImage.cols; x++ )  
        {  
            for(int c = 0; c < 3; c++ )  
            {  
                g_dstImage.at<Vec3b>(y,x)[c]= saturate_cast<uchar>( (g_nContraValue*0.01)*(g_srcImage.at<Vec3b>(y,x)[c] ) + g_nBrightValue );  
            }  
        }  
    }  

    imshow(strWindowName, g_dstImage); 
}

imageimageimage

三、代碼分析

上述代碼中流程為:

1、獲取源圖像srcImage

2、創建以個目標圖像dstImage,全是0,所以是黑色圖像。

3、創建圖像窗口

4、創建軌跡條(Trackbar),更改對比度和亮度的值,同時函數有回調函數,當移動bar函數調用。

5、對比度、亮度修改函數。

6、顯示圖像

四、軌跡條(Trackbar)的創建和使用

C++: int createTrackbar(conststring& trackbarname, conststring& winname,
 int* value, int count, TrackbarCallback onChange=0,void* userdata=0);
//第一個參數,const string&類型的trackbarname,表示軌跡條的名字,用來代表我們創建的軌跡條。
//第二個參數,const string&類型的winname,填窗口的名字,表示這個軌跡條會依附到哪個窗口上,即對應namedWindow()創建窗口時填的某一個窗口名。
///第三個參數,int* 類型的value,一個指向整型的指針,表示滑塊的位置。並且在創建時,滑塊的初始位置就是該變量當前的值。
//第四個參數,int類型的count,表示滑塊可以達到的最大位置的值。PS:滑塊最小的位置的值始終為0。
//第五個參數,TrackbarCallback類型的onChange,首先注意他有默認值0。這是一個指向回調函數的指針,每次滑塊位置改變時,這個函數都會進行回調。並且這個函數的原型必須為void XXXX(int,void*);其中第一個參數是軌跡條的位置,第二個參數是用戶數據(看下面的第六個參數)。如果回調是NULL指針,表示沒有回調函數的調用,僅第三個參數value有變化。
//第六個參數,void*類型的userdata,他也有默認值0。這個參數是用戶傳給回調函數的數據,用來處理軌跡條事件。如果使用的第三個參數value實參是全局變量的話,完全可以不去管這個userdata參數。

這個createTrackbar函數,為我們創建一個具有特定名稱和范圍的軌跡條(Trackbar,或者說是滑塊范圍控制工具),指定一個和軌跡條位置同步的變量。而且要指定回調函數onChange(第五個參數),在軌跡條位置改變的時候來調用這個回調函數。並且我們知道,創建的軌跡條顯示在指定的winname(第二個參數)所代表的窗口上。

C++: int getTrackbarPos(conststring& trackbarname, conststring& winname);
//第一個參數,const string&類型的trackbarname,表示軌跡條的名字。
//第二個參數,const string&類型的winname,表示軌跡條的父窗口的名稱。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM