六、调整图片亮度和对比度
1、理论
图像变换可以看作如下:
- 像素变换—点操作
- 邻域操作—区域
调整图像的亮度和对比度属于像素变换—点操作
g(i , j) = α \alpha α* f(i , j) + β \beta β 其中 α \alpha α > 0, β \beta β是增益变量
α \alpha α > 1会扩大两个像素值之间的差值,从而提高了图像的对比度,反之降低图像对比度; β \beta β值可以用来增大图片的亮度,值越大,图片亮度增加越明显。
2、对比度,与亮度提高代码实现
单通道灰度图像
float v = src.at<uchar>(row, col);
dst.at<uchar>(row, col) = saturate_cast<uchar>(v * alpha + beta);
三通道RGB图像
float b = src.at<Vec3b>(row, col)[0];//获取图片各个像素值
float g = src.at<Vec3b>(row, col)[1];
float r = src.at<Vec3b>(row, col)[2];
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);
若想进一步提高精度,可以使使读取的像素的数据类型都为float类型,即Vec3f,这里需要一个转换函数
src.convertTo(m1, CV_32F);
接下来便可以使用浮点类型
float b = m1.at<Vec3f>(row, col)[0];//Vec3f,读取数据类型为float型,需要用到convertTo函数
float g = m1.at<Vec3f>(row, col)[1];
float r = m1.at<Vec3f>(row, col)[2];
示例代码(改变图像的亮度和对比度):
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src, dst;
src = imread("C:/Users/26839/Pictures/测试.png");
if (src.empty()) {
cout << "could not load image...\n" << endl;
return -1;
}
//cvtColor(dst, src, COLOR_BGR2GRAY);//测试灰度图像
imshow("input", src);
int height = src.rows;
int width = src.cols;
dst = Mat::zero(src.size(), src.type());
float alpha = 1.2;//提高对比度
float beta = 30;//提高亮度
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 = m1.at<Vec3f>(row, col)[0];
float g = m1.at<Vec3f>(row, col)[1];
float r = m1.at<Vec3f>(row, col)[2];
dst.at<Vec3f>(row, col)[0] = saturate_cast<uchar>(b * alpha + beta);
dst.at<Vec3f>(row, col)[1] = saturate_cast<uchar>(g * alpha + beta);
dst.at<Vec3f>(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);
}
}
}
imshow("output", dst);
waitKey(0);
dstroyAllWindows();
return 0;
}
运行输出结果如下:
单通道测试结果:
三通道测试结果