理论:
调整图像亮度和对比度属于像素变换-点操作,数学公式:g(i,j)=a*f(i,j)+b其中a>0,b是增益变量。
API:
Mat image=Mat::zeros(image,size(),image.type())-创建一张和image大小和类型一致的空白图像、像素点初始值为0。
image.at<Vec3b>(x,y)[index]=value-给通道的像素点赋值,其中x,y代表像素点的坐标,Index代表第几通道。
saturate_cast<uchar>(value)-确保像素值的大小范围在0~255之间。
代码演示:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
int main(int argc, char** argv) {
Mat src, dst;
src = imread("D:/test.png");
if (!src.data) {
printf("could not load image...\n");
return -1;
}
char input_win[] = "input image";
cvtColor(src, src, CV_BGR2GRAY);//将图像转换成灰度图像
namedWindow(input_win, CV_WINDOW_AUTOSIZE);
imshow(input_win, src);
// contrast and brigthtness changes
int height = src.rows;
int width = src.cols;
dst = Mat::zeros(src.size(), src.type());//创建一个和src大小、类型一样的初始值为0的Mat
float alpha = 1.2;
float beta = 30;
Mat m1;
src.convertTo(m1, CV_32F);//将图像转换成CV_32F格式
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
//如果图像是3通道的彩色图像
if (src.channels() == 3) {
float b = m1.at<Vec3f>(row, col)[0];// blue,blue通道在(row,col)处的像素值赋给b
float g = m1.at<Vec3f>(row, col)[1]; // green
float r = m1.at<Vec3f>(row, col)[2]; // red
// output
dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b*alpha + beta);//将b*alpha + beta的值转换到0~255范围内之后赋给dst的相应位置
dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g*alpha + beta);
dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r*alpha + beta);
}
//图像为单通道时
else if (src.channels() == 1) {
float v = src.at<uchar>(row, col);
dst.at<uchar>(row, col) = saturate_cast<uchar>(v*alpha + beta);
}
}
}
char output_title[] = "contrast and brightness change demo";
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
imshow(output_title, dst);
waitKey(0);
return 0;
}
运行结果对比图:
原图
结果图