Opencv學習筆記4: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對結果進行轉換,以確保它為有效值。

效果圖:

 

三、實例

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/imgproc/imgproc.hpp"

using namespace std;
using namespace cv;

static void ContrastAndBright(int, void *);
int g_nContrastValue; //對比度值
int g_nBrightValue;  //亮度值
Mat g_srcImage, g_dstImage;

int main()
{
    // 讀入用戶提供的圖像
    g_srcImage = imread("0004.bmp");

    g_dstImage = Mat::zeros(g_srcImage.size(), g_srcImage.type());

    //設定對比度和亮度的初值
    g_nContrastValue = 80;
    g_nBrightValue = 80;

    //創建窗口
    namedWindow("【效果圖窗口】", 1);

    //創建軌跡條
    createTrackbar("對比度:", "【效果圖窗口】", &g_nContrastValue, 300, ContrastAndBright);
    createTrackbar("亮   度:", "【效果圖窗口】", &g_nBrightValue, 200, ContrastAndBright);

    //調用回調函數
    ContrastAndBright(g_nContrastValue, 0);
    ContrastAndBright(g_nBrightValue, 0);

    waitKey(0);
    //輸出一些幫助信息
    return 0;
}

//-----------------------------【ContrastAndBright( )函數】------------------------------------
//    描述:改變圖像對比度和亮度值的回調函數
//-----------------------------------------------------------------------------------------------
static 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_nContrastValue*0.01)*(g_srcImage.at<Vec3b>(y, x)[c]) + g_nBrightValue);
            }
        }
    }
    // 顯示圖像
    imshow("【原始圖窗口】", g_srcImage);
    imshow("【效果圖窗口】", g_dstImage);
}

注意:

saturate_cast:

功能:防止數據溢出,因為無論是加是減,乘除,都會超出一個像素灰度值的范圍(0~255)。所以,所以當運算完之后,結果為負,則轉為0,結果超出255,則為255。

四、改進

這樣已經完成了更改亮度和對比度的需求,但是用for循環執行效率有點低,圖像處理起來也不是特別流暢,opencv給出了非常合適的函數。

 

函數原型
void Mat::convertTo( Mat& m, int rtype, double alpha=1, double beta=0 )const;
 
輸入參數:
m  目標矩陣。如果m的大小與原矩陣不一樣,或者數據類型與參數不匹配,那么在函數convertTo內部會先給m重新分配空間。
rtype 指定從原矩陣進行轉換后的數據類型,即目標矩陣m的數據類型。當然,矩陣m的通道數應該與原矩陣一樣的。如果rtype是負數,那么m矩陣的數據類型應該與原矩陣一樣。
alpha 縮放因子。默認值是1。即把原矩陣中的每一個元素都乘以alpha。
beta 增量。默認值是0。即把原矩陣中的每一個元素都乘以alpha,再加上beta。

功能
把一個矩陣從一種數據類型轉換到另一種數據類型,同時可以帶上縮放因子和增量,公式如下:
m(x,y)=saturate_cast<rType>(alpha*(*this)(x,y)+beta);
由於有數據類型的轉換,所以需要用saturate_cast<rType>來處理數據的溢出。
 
所以上述代碼可以寫為,通過簡單拉動進度條可以看出這個速度上提升比較大
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/imgproc/imgproc.hpp"

using namespace std;
using namespace cv;

static void ContrastAndBright(int, void *);
int g_nContrastValue; //對比度值
int g_nBrightValue;  //亮度值
Mat g_srcImage, g_dstImage;

int main()
{
    // 讀入用戶提供的圖像
    g_srcImage = imread("0004.bmp");

    g_dstImage = Mat::zeros(g_srcImage.size(), g_srcImage.type());

    //設定對比度和亮度的初值
    g_nContrastValue = 80;
    g_nBrightValue = 80;

    //創建窗口
    namedWindow("【效果圖窗口】", 1);

    //創建軌跡條
    createTrackbar("對比度:", "【效果圖窗口】", &g_nContrastValue, 300, ContrastAndBright);
    createTrackbar("亮   度:", "【效果圖窗口】", &g_nBrightValue, 200, ContrastAndBright);

    //調用回調函數
    ContrastAndBright(g_nContrastValue, 0);
    ContrastAndBright(g_nBrightValue, 0);

    waitKey(0);
    //輸出一些幫助信息
    return 0;
}

//-----------------------------【ContrastAndBright( )函數】------------------------------------
//    描述:改變圖像對比度和亮度值的回調函數
//-----------------------------------------------------------------------------------------------
static 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_nContrastValue*0.01)*(g_srcImage.at<Vec3b>(y, x)[c]) + g_nBrightValue);
    //        }
    //    }
    //}
    g_srcImage.convertTo(g_dstImage, -1, g_nContrastValue*0.01, g_nBrightValue);
    // 顯示圖像
    imshow("【原始圖窗口】", g_srcImage);
    imshow("【效果圖窗口】", g_dstImage);
}

 


免責聲明!

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



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