opencv学习笔记六(调整图像亮度与对比度)
opencv学习笔记六(调整图像亮度与对比度)理论相关函数API自定义函数代码实现效果理论图像变换可以看作如下:像素变换 – 点操作邻域操作 – 区域做图像的卷积,整体的特征的提取或者图像梯度的计算,图像的模式识别,匹配等前期处理,焦点检测,模糊,平滑等操作是需要邻域操作调整图像亮度和对比度属于像素变换-点操作下方是对像素点进行操作的数学表达式,用来调整图像亮度与对比度g(i,j) = a*f(i
·
理论
图像变换可以看作如下:
- 像素变换 – 点操作
- 邻域操作 – 区域
- 做图像的卷积,整体的特征的提取或者图像梯度的计算,图像的模式识别,匹配等前期处理,焦点检测,模糊,平滑等操作是需要邻域操作
- 调整图像亮度和对比度属于像素变换-点操作
- 下方是对像素点进行操作的数学表达式,用来调整图像亮度与对比度
g(i,j) = a*f(i,j) + b;
其中,f(i,j)表示输入图像的像素点的值;g(i,j)为输出图像的像素点的值;a>0,b是增益变量,通过调整a、b的值就可以调整图像对比度和亮度(a调整对比度,b调整亮度)
相关函数API
opencv自带函数
- Mat new_image = Mat::zeros( image.size(), image.type() );
创建一张跟原图像大小和类型一致的空白图像、像素值初始化为0 - saturate_cast(value)
确保值大小范围为0~255之间 - Mat.at(y,x)[index]=value
给每个像素点每个通道赋值 - void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;
参数1: m – 目标矩阵。如果m在运算前没有合适的尺寸或类型,将被重新分配。
参数2:rtype – 目标矩阵的类型。因为目标矩阵的通道数与源矩阵一样,所以rtype也可以看做是目标矩阵的位深度。如果rtype为负值,目标矩阵和源矩阵将使用同样的类型。
参数3:alpha – 尺度变换因子(可选)。
参数4:beta – 附加到尺度变换后的值上的偏移量(可选)。
自定义函数
void changeContrast(Mat &src, Mat &dst,float alpha, float beta);
参数1:输入需要调整的图像
参数2:输出对比度和亮度调整后的图像
参数3:输入浮点型的数值alpha,用来调节对比度
参数4:输入浮点型的数值beta,用来调节亮度
代码实现效果
- 原始的三通道彩色rgb图像
- rgb图像经过changeContrast(src, dst_rgb, 1.2, 10);处理过的图像
- rgb图像经过cvtColor(src, gray, COLOR_BGR2GRAY);处理后的单通道灰度图像
- 灰度图像经过changeContrast(gray, dst_gray, 1.2, 10);处理后的图像
具体代码实现
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
void changeContrast(Mat &src, Mat &dst,float alpha, float beta);//输入src;输出dst;alpha用来调节对比度;beta用来调节亮度
int main(){
Mat src = imread("1.jpg",IMREAD_UNCHANGED);//读取原始图像,此处的图像是三通道彩色rgb图像
if (!src.data){
cout << "could not load image ..." << endl;
getchar();//此处若使用waitKey(0);不能实现暂停状态
return -1;
}
imshow("src image", src);//展示原始图像
//调整rgb图像的对比度和亮度
Mat dst_rgb;//定义一个输出图像,下面调用函数时使用
changeContrast(src, dst_rgb, 1.2, 10);
imshow("dst_rgb image", dst_rgb);//展示调整对比度和亮度后的rgb图像
//imwrite("dst_rgb.jpg", dst);
//将上面的rgb转换成灰度图像
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);//此处用来将三通道彩色rgb图像转换成单通道灰度图像
imshow("gray image", gray);//展示灰度化后的图像
//imwrite("gray.jpg", gray);
//调整gray图像的对比度和亮度
Mat dst_gray;//定义一个输出图像,下面调用函数时使用
changeContrast(gray, dst_gray, 1.2, 10);
imshow("dst_gray image", dst_gray);//展示调整对比度和亮度后的rgb图像
//imwrite("dst_gray.jpg", dst2);
waitKey(0);//此处不能使用getchar来暂停,否则会导致图片无法显示
return 0;
}
void changeContrast(Mat &src, Mat &dst, float alpha, float beta){ //定义alpha用来调节对比度,beta用来调节亮度
dst = Mat::zeros(src.size(), src.type());//创建一个背景图像dst,与原始图像src类型相同
Mat m1;
src.convertTo(m1, CV_32F);//convertTo用来改变图像的位深度,此处将src的中的数据类型变为float类型,为了后面使用Vec3f来读取其中的像素值,否则用Vec3f读取uchar类型的数据会报错
for (int row = 0; row < src.rows; row++){
for (int col = 0; col < src.cols; col++){
if (src.channels() == 1){ //判断如果图像是单通道的(单通道和三通道读取像素不同)
float v = src.at<uchar>(row, col);
dst.at<uchar>(row, col) = saturate_cast<uchar>(alpha*v + beta);//saturate_cast将里面的值保持在0~255之间
}
else if (src.channels() == 3){ //判断如果图像是三通道的
float b = m1.at<Vec3f>(row, col)[0]; //此处使用at<Vec3f>进行像素读取操作时,图像的像素值的类型必须为float型的,否则类型不匹配无法读取。
float g = m1.at<Vec3f>(row, col)[1]; //一般读取的数据类型是8位无符号整型的数值,使用at<Vec3b>即可读取(前面的convertTo便可直接去掉)
float r = m1.at<Vec3f>(row, col)[2];
dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(alpha*b + beta);//此处就是针对像素点的值的操作,对应数学理论g(i,j) = a*f(i,j) + b;
dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(alpha*g + beta);//saturate_cast<uchar>(value)确保值大小范围为0~255之间
dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(alpha*r + beta);
}
}
}
}
更多推荐
已为社区贡献3条内容
所有评论(0)