理论基础
图像变换中一般有如下两种操作
1,像素变换 对应 点操作
2,,邻域操作 对应 区域
图像亮度与对比度的调整操作属于点操作,点操作的特点:
1,根据输入像素值来计算相应的输出像素值
亮度与对比度调整的数学模型
g(i,j)=a*f(i,j)+b
f(i,j)表示源图像,g(i,j)表示输出图像像素
参数 a (a >0) 被称为增益,用来控制图像的对比度
参数b 被称为偏置,用来控制图像的亮度
i,j表示像素位于第i行和第j列,编写程序时,不管是三通道还是单通道
需要遍历整个图像对每个像素值应用上面的数学公式。
应用的知识点
1,Mat new_image=Mat::zeros(image.size(),image.type())创建一张跟原图大小和类型一致的空白图像,像素值初始化为0
2,saturate_cast<uchar>(value) 防止像素值越界,确保像素值的范围在0-255之间
3,Mat.at<Vec3b>(y,x)[index]=value 给每个像素点通道赋值
效果图
1,原始图像
亮度和对比度变换后的图像
代码实现
#include <opencv2\opencv.hpp> #include <iostream> using namespace cv; int main(int argc, char** argv) { Mat src, dst; src = imread("test.jpg"); if (!src.data) { printf("图片加载错误"); return -1; } char input_win[] = "输入图像"; //cvtColor(src,src,CV_BGR2GRAY); namedWindow(input_win,CV_WINDOW_AUTOSIZE); imshow(input_win,src); int height = src.rows; int width = src.cols; dst = Mat::zeros(src.size(),src.type()); float alpha = 1.8; float beta = 20; //Mat m1; //src.convertTo(m1,CV_32F); for (int row = 0; row < height;row++) { for (int col = 0; col < width;col++) { if (src.channels()==3) { float b = src.at<Vec3b>(row, col)[0];//blue float g = src.at<Vec3b>(row, col)[1];//green float r = src.at<Vec3b>(row, col)[2];//red //output dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b*alpha+beta); 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 gray = src.at<uchar>(row,col); dst.at<uchar>(row, col) = saturate_cast<uchar>(gray*alpha+beta); } } } char output_title[] = "调整图像亮度和对比度后的图像"; imshow(output_title,dst); waitKey(0); return 0; }