opencv学习笔记六(调整图像亮度与对比度)

opencv学习笔记六(调整图像亮度与对比度)

理论

图像变换可以看作如下:

  • 像素变换 – 点操作
  • 邻域操作 – 区域
  1. 做图像的卷积,整体的特征的提取或者图像梯度的计算,图像的模式识别,匹配等前期处理,焦点检测,模糊,平滑等操作是需要邻域操作
  2. 调整图像亮度和对比度属于像素变换-点操作
  3. 下方是对像素点进行操作的数学表达式,用来调整图像亮度与对比度
    g(i,j) = a*f(i,j) + b;
    其中,f(i,j)表示输入图像的像素点的值;g(i,j)为输出图像的像素点的值;a>0,b是增益变量,通过调整a、b的值就可以调整图像对比度和亮度(a调整对比度,b调整亮度)

相关函数API

opencv自带函数

  1. Mat new_image = Mat::zeros( image.size(), image.type() );
    创建一张跟原图像大小和类型一致的空白图像、像素值初始化为0
  2. saturate_cast(value)
    确保值大小范围为0~255之间
  3. Mat.at(y,x)[index]=value
    给每个像素点每个通道赋值
  4. 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,用来调节亮度

代码实现效果

  1. 原始的三通道彩色rgb图像
    在这里插入图片描述
  2. rgb图像经过changeContrast(src, dst_rgb, 1.2, 10);处理过的图像
    在这里插入图片描述
  3. rgb图像经过cvtColor(src, gray, COLOR_BGR2GRAY);处理后的单通道灰度图像
    在这里插入图片描述
  4. 灰度图像经过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);
			}
		}
	}

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吾名招财

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值