1.7【OpenCV圖像處理】 調整圖像亮度與對比度

(b * alpha + beta)

(1)理論

圖像變換可以看作如下:

1)像素變換 – 點操作,用在調整圖像亮度和對比度等操作上。

2)鄰域操作 – 區域,用在圖像卷積、特徵提取、梯度計算、模式匹配識別、角點檢測、模糊、平滑等操作上。

調整圖像亮度和對比度(contrast and brightness change)屬於像素變換-點操作,公式為:

float alpha = 1.2; //對比度係數,小於1變暗,大於1變亮nfloat beta = 30; //亮度增益nMat m1;nsrc.convertTo(m1, CV_32F); //src數據類型轉變為m1的32位,切換成浮點型nfloat b = m1.at<Vec3f>(row, col)[0];//讀三通道像素,不能直接用Vec3f,要用Vec3b,因為是opencv是8UC的數據,除非提前src.convertTo轉換類型ndst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b * alpha + beta); //寫像素,修改亮度和對比度,確保值在0-255內n

亮度:增益變數就是在前面基礎上再加多少,亮度表示0-255之間的像素值大小,越亮越向白的靠攏,像素值就該越大,整體要提高亮度就要擴大增益變數beta;

對比度:提高對比度就是擴大兩圖像像素的差值,增大alpha。提高對比度就是增大差值,大的越大,小的越小。對比度係數alpha,小於1變暗,大於1變亮。

f(i,j)、g(i,j)表示輸入、輸出圖像的一個像素點;圖像就是數據,數據可以千變萬化,可以是浮點double等各種類型的數據。RGB是最常見的圖像的數據,必須是正數取值範圍0~255,而TIF的數據格式可能有負數。

(2)重要的API

空白圖像

Mat new_image = Mat::zeros( image.size(), image.type() ); 創建一張跟原圖像大小和類型一致的空白圖像、像素值初始化為0

dst = Mat::zeros(src.size(), src.type());n

確保值:

saturate_cast<uchar>(value); 確保值大小範圍為0~255之間

dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b*alpha + beta); //寫像素,修改亮度和對比度n

寫像素:

Mat.at<Vec3b>(y,x)[index]=value; 給每個像素點每個通道賦值。


完整程序:

/*1.7 亮度和對比度*/n#include <opencv2/opencv.hpp>n#include <iostream> nusing namespace cv; //使用cv命名空間nnint main(int argc, char** argv) { //argc 表示命令行輸入參數的個數(以空白符分隔),argv中存儲了所有的命令行參數nMat src, dst;n src = imread("E:/OpenCV/testimage/test5.jpg"); //輸入圖像默認讀進來的方式RGB,但是三個通道的排序是BGRnif (src.empty()) { n printf("could not load image...n");nreturn -1;n }nchar input_win[] = "input image"; //字元命名n// cvtColor(src, src, CV_BGR2GRAY);//灰度n namedWindow(input_win,CV_WINDOW_AUTOSIZE);n imshow(input_win, src);nn/*亮度和對比度修改 contrast and brightness change*/nint height = src.rows;nint width = src.cols;n dst = Mat::zeros(src.size(), src.type());nfloat alpha = 1.2; //對比度係數,小於1變暗,大於1變亮nfloat beta = 30; //亮度增益nMat m1;n src.convertTo(m1, CV_32F); //src數據類型轉變為m1的32位,切換成浮點型nfor (int row = 0; row < height; row++) {nfor (int col = 0; col < width; col++) {nif (src.channels() == 3) {nfloat b = m1.at<Vec3f>(row, col)[0];//讀三通道像素,不能直接用Vec3f,要用Vec3b,因為是opencv是8UC的數據,除非提前src.convertTo轉換類型nfloat g = m1.at<Vec3f>(row, col)[1];//greennfloat r = m1.at<Vec3f>(row, col)[2];//redn dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b*alpha + beta); //寫像素,修改亮度和對比度n dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g*alpha + beta);n dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r*alpha + beta);n }nelse if (src.channels() == 1) {nfloat v = src.at<uchar>(row, col); //讀一通道像素n dst.at<uchar>(row, col) = saturate_cast<uchar>(v * alpha + beta);n }n }n }nchar output_title[] = "contrast and brightness change demo";n namedWindow(output_title, CV_WINDOW_AUTOSIZE);n imshow(output_title, dst);nn waitKey(0); nreturn 0;n}n

運行結果:


推薦閱讀:

到底Resnet在解決一個什麼問題呢?
1.19【OpenCV圖像處理】Canny邊緣檢測
圖像分割中的自動求閾值法
我的CUDA學習之旅——啟程

TAG:OpenCV | 图像处理 | 图像分割 |