修改图像的对比度和亮度
目标
- 获取像素值
- 初始化零矩阵
- 学习使用cv::saturate_cast和作用“
- 学习一些比较酷的像素转换
原理
图像处理
通常图像处理操作就是一个函数,包含一个或者多个输入图像然后产生一个输出结果。
图像转化可以看成两种操作,一种是像素点的操作,第二种就是临域的操作(就是图像的一个区域内的操作)
像素点转化
这种图像处理每一个输出像素点的值依赖于相对应的输入像素点的值的加减处理。做这些处理的两个基本的例子就是图像的亮度和对比度的调节。
亮度和对比度调节
通常的图像处理的公式如下:
g(x)=αf(x)+β
参数alpha>0,alpha叫增益因子和beta叫偏移因子。alpha控制对比度,beta控制亮度。
下面的公式更符合图像处理,g(i,j)表示输出点,f(i,j)表示输入点基本i,j代表图像中的行和列位置。
g(i,j)=α⋅f(i,j)+β
代码
下面的代码执行的是g(i,j)=α⋅f(i,j)+β的操作。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
double alpha; /*< Simple contrast control */
int beta; /*< Simple brightness control */
int main( int argc, char** argv )
{
Mat image = imread( argv[1] );
Mat new_image = Mat::zeros( image.size(), image.type() );
std::cout<<" Basic Linear Transforms "<<std::endl;
std::cout<<"-------------------------"<<std::endl;
std::cout<<"* Enter the alpha value [1.0-3.0]: ";std::cin>>alpha;
std::cout<<"* Enter the beta value [0-100]: "; std::cin>>beta;
for( int y = 0; y < image.rows; y++ ) {
for( int x = 0; x < image.cols; x++ ) {
for( int c = 0; c < 3; c++ ) {
new_image.at<Vec3b>(y,x)[c] =
saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta );
}
}
}
namedWindow("Original Image", 1);
namedWindow("New Image", 1);
imshow("Original Image", image);
imshow("New Image", new_image);
waitKey();
return 0;
}
程序说明
- 我们开始创建两个参数alpha和beta,然后通用用户输入。
double alpha;
double beta;
2.使用cv::imread读取一张图片
Mat image = imread(argv[1]);
3.创建一张图片矩阵,初始化矩阵为0,并且与image同样大小和同样的通道数。
Mat new_image = Mat::zeros(image.size(),image.type());
4.下面执行操作g(i,j)=α⋅f(i,j)+β ,我们将会遍历每一个像素。因为图像的格式是BGR,我们每个像素需要操作三个值(BGR)。我们需要分别操作它们。
for( int y = 0; y < image.rows; y++ ) {
for( int x = 0; x < image.cols; x++ ) {
for( int c = 0; c < 3; c++ ) {
new_image.at<Vec3b>(y,x)[c] =
saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta );
}
}
}
这里遍历每一个像素使用image.at(y,x)[c]。
由于计算结果可能会超出范围或者不是整数,我们使用cv::saturate_cast来确保计算结果可用。
5.最后,我们创建一个窗口来显示图像。
namedWindow("Original Image", 1);
namedWindow("New Image", 1);
imshow("Original Image", image);
imshow("New Image", new_image);
waitKey(0);
其实可以使用cv::Mat::convertTo会更高效。
image.convertT(new_image,-1,aplha,beta);
函数原型:
void cv::Mat::convertTo ( OutputArray m,
int rtype,
double alpha = 1,
double beta = 0
) const
函数执行公式如下:
m(x,y)=saturate_cast(α(∗this)(x,y)+β)
参数说明:
m是输出矩阵。
rtype期望输出矩阵类型。
运行结果
使用alpha=2.2 beta=50。然后得到运行结果
***** VIDEOINPUT LIBRARY - 0.1995 - TFW07 *****
Basic Linear Transforms
-------------------------
* Enter the alpha value [1.0-3.0]: 2.2
* Enter the beta value [0-100]: 50
*