【opencv学习笔记】007之图像亮度与对比度

版权声明:本文由 水亦心 出品,转载请注明出处。 https://blog.csdn.net/shuiyixin/article/details/89390239

目录

一、前言

二、访问像素

1、什么是访问像素

2、Vec3b与Vec3f

三、图像亮度与对比度

1、算子

2、点操作-亮度与对比度

四、全部代码及结果展示

1、代码

2、运行效果图


一、前言

今天不废话了,因为吃一堑,长一智,现在已经养成了定期完善博客的习惯,等坚持不下去的时候,再用鸡汤来鞭策自己。

今天要讲的是图像对比度与亮度的调整。

如果想看其他有关于OpenCV学习方法介绍、学习教程、代码实战、常见报错及解决方案等相关内容,可以直接看我的OpenCV分类:

【OpenCV系列】:https://blog.csdn.net/shuiyixin/article/category/7581855

二、访问像素

1、什么是访问像素

我们之前有教程专门讲过图像像素的访问,与操作,在这里再次说明是为了强调其重要性。因为我们对图像的处理就是对像素点的处理,所以如何获取像素点,如何修改像素点非常重要。

如果大家对访问像素以及像素操作了解不是很深,可以看下面两篇博客:

图像像素基本操作及掩膜操作:https://blog.csdn.net/shuiyixin/article/details/88825549

读写像素:https://blog.csdn.net/shuiyixin/article/details/89304084

 

2、Vec3b与Vec3f

这里讲访问图像主要是讲Vec3b与Vec3f。

我们经常会在代码中看到Vec3b与Vec3f,特别是在获取图像像素时候,获取图像像素点信息的时候,Vec3b与Vec3f几乎就是常客了。

所以在这里着重给大家说一下:

Vec3b :对应三通道的顺序是blue、green、red的uchar类型数据。

Vec3f :对应三通道的float类型数据

例如我们这个博客中用到的例子:

        float b = m1.at<Vec3f>(row, col)[0];// blue
	float g = m1.at<Vec3f>(row, col)[1]; // green
	float r = m1.at<Vec3f>(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);

 

三、图像亮度与对比度

1、算子

首先我们先拓展一个概念叫算子。我们可以把算子当做一个函数,通过算子,我们可以修改图像,合并图像等,可以将多个图像经过一系列操作得到新的图像。

一个输入图像
多个输入图像

 

2、点操作-亮度与对比度

点操作是比较简单的算子,需要获取到图像的像素值,并对像素值作相应修改就可以了。

亮度与对比度是比较基础,也是比较常用的算子,我们经常可以在美颜相机上见到这两个算子的应用,我们经常用它来美白,提高图像的对比度。

我们知道,RGB的值越大,图像越接近白色,在视觉效果来看,亮度越大,RGB的值越小,图像越接近黑色,在视觉效果来看,亮度越小,所以我们通过添加两个系数来设置图像的亮度与对比度:

系数1:增益(gain),用来控制图像的对比度,用alpha(α)表示,α>0;

系数2:偏置(bias),用来控制图像的亮度,用beta(β)表示。

我们设置两个函数,一个表示输入图像,一个表示输出图像:

函数1:f(x),输入图像;

函数2:g(x),输出图像。

由此我们可以得到调整亮度与对比度的公式:

亮度与对比度公式

这个是数学公式,在图像处理里面,因为我们是对像素点修改,像素点是有坐标的,调整第i行,第j列的像素值的公式如下:

图像的亮度与对比度公式

剩下的废话不多说,让我们上代码。

四、全部代码及结果展示

1、代码

代码比较简单,就不分块讲解了。直接分享给大家:

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
int main(int argc, char** argv) {
	Mat src, dst;
	src = imread("E:/image/Girl.png");
	if (!src.data) {
		printf("could not load image...\n");
		return -1;
	}

	imshow("【before】", src);

	// contrast and brigthtness changes 
	int height = src.rows;
	int width = src.cols;
	dst = Mat::zeros(src.size(), src.type());
	float alpha = 0.9; //1.1  设置对比度
	float beta = -3;   //3  设置亮度

	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];// blue
				float g = m1.at<Vec3f>(row, col)[1]; // green
				float r = m1.at<Vec3f>(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 v = src.at<uchar>(row, col);
				dst.at<uchar>(row, col) = saturate_cast<uchar>(v*alpha + beta);
			}
		}
	}

	imshow("【after】", dst);

	waitKey(0);
	return 0;
}

2、运行效果图

因为α和β取不同类型值时,得到的结果不一样,我分别取(α<1、β<0)和(α>1、β>0)分别做测试。

运行结果如下图,前面是原图,后面是处理后的图像:

(α = 0.9、β = -3)
(α = 1.1、β = 3)

效果还是蛮不错的。以后P图,大家都可以自己写代码P啦,比使用美图软件高级不少呢!

今天的内容就讲到这里啦,有什么问题,大家可以在下面留言哦!

猜你喜欢

转载自blog.csdn.net/shuiyixin/article/details/89390239