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學習之旅——啟程