OpenCV图像线性变换(图像线性混合亮度和对比度增强线性变换API)

Posted _睿智_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV图像线性变换(图像线性混合亮度和对比度增强线性变换API)相关的知识,希望对你有一定的参考价值。

目录

一、图像线性混合

1、原理及函数介绍

2、代码

 3、图像

二、亮度和对比度增强

1、概念(亮度和对比度)

2、原理

3、单通道处理(灰度图)

代码: 

效果:

4、多通道处理(彩图)

代码:

效果:

5、代码

三、线性变换API

 代码

总代码

参考资料:


 

一、图像线性混合

1、原理及函数介绍

 原理(公式):             dst(r, c) =  * src1(r, c) +  * src2(r, c) + 

本质:        ​​线性变换 (O(r, c) = a * I(r, c) + b

 (src1:图1        src2:图2       :图1权重        :图2权重 )(r为行,c为列)

注:融合的图片需要大小和类型均相同!!!

 第一个参数,InputArray类型的src1,表示需要加权的第一个数组,常常填一个Mat。(图1

 第二个参数,alpha,表示第一个数组的权重。(图1权重

 第三个参数,src2,表示第二个数组,它需要和第一个数组拥有相同的尺寸和通道数。(图2

 第四个参数,beta,表示第二个数组的权重值。(图2权重

 第五个参数,gamma,一个加到权重总和上的标量值。看上面的式子自然会理解。

 第六个参数,dst输出的数组,它和输入的两个数组拥有相同的尺寸和通道数。(输出的图像

 第七个参数,dtype,输出阵列的可选深度,有默认值-1。;当两个输入数组具有相同的深度时,这个参数设置为-1(默认值),即等同于src1.depth()。

2、代码

//图像线性混合
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

Mat img1, img2, dst;

//图像初始化
void Image_Init()
{
	img1 = imread("Resource/test.jpg");
	img2 = imread("Resource/Airplane.jpg");

	if (img1.empty() || img2.empty())
	{
		printf("图像加载失败");
		exit(0);
	}
}

//线性混合
void LinearBlend()
{
	if (img1.rows == img2.rows && img1.cols == img2.cols && img1.type() == img2.type())
	{
		imshow("图片一", img1);
		imshow("图片二", img2);
		addWeighted(img1, 0.5, img2, (1 - 0.5), 0.0, dst);		//把img1和img2混合(img1:0.5;img2:(1-0.5)
		imshow("混合图片", dst);
	}
	else
	{
		printf("待混合的图片不满足要求!\\n");
	}
}

int main()
{
	Image_Init();				//图像初始化

	LinearBlend();			//线性混合

	waitKey(0);

	return 0;
}

 

 3、图像

 

二、亮度和对比度增强

1、概念(亮度和对比度)

亮度: 显示器的亮度定义为全白颜色下亮度值

对比度:对比度指的是一幅图像中明暗区域最亮的白最暗的黑之间不同亮度层级的测量,差异范围越大代表对比越大,差异范围越小代表对比越小。

2、原理

        图像对比度是通过灰度级范围来度量的,而灰度级范围可通过观察灰度直方图得到,灰度级范围越大代表对比度越高;反之,对比度越低,低对比度的图像在视觉上给人的感觉是看起来不够清晰的,所以通过算法调整图像的灰度值,从而调整图像的对比度是有必要的。最简单的一种对比度增强方法是通过灰度值的线性变换来实现的。

公式:        O(r, c) = a * I(r, c) + b,     (0<=r<H, 0<=c<W)

 a改变对比度,b改变亮度。(输入图像为I,宽为W、高为H,输出图像记为O。)

 1、当时,的一个副本;

2、如果,则输出图像相比对比度增大;

3、如果, 则输出图像相比对比度减小。

值的改变,影响的是输出图像的亮度,1、当时,亮度增加;2、时,亮度减小。

         

1、假设图像的灰度级范围是[50,100],通过的线性变换,可以将输出图像的灰度级拉伸到[100,200],灰度级范围有所增加,从而提高了对比度;

2、而如果令,则输出图像的灰度级会压缩到[25,50],灰度级范围有所减小,则降低了对比度。

(这就是为什么我们拿到彩色图像以后往往会转化为灰度图进行处理,这位这样相当于只要处理一个通道。如果是三通道,原理是一样的)

3、单通道处理(灰度图)

单通道at类型 :<uchar>

代码: 

//单通道处理
	if( img2.channels() == 1)
		for (int i = 0; i < img2.rows; i++)
		{
			for (int j = 0; j < img2.cols; j++)
			{
				dst2.at<uchar>(i, j) = saturate_cast<uchar>((float)img2.at<uchar>(i, j) * alpha + beta);
				//注:单通道是<uchar>类型
			}
		}

效果:

 

4、多通道处理(彩图)

多通道at类型 :<Vec3b>

代码:

//多通道处理
	if (img1.channels() == 3)
		for (int i = 0; i < img1.rows; i++)
		{
			for (int j = 0; j < img1.cols; j++)
			{
				//1、获取原图的BGR(RGB)
				float b = img1.at<Vec3b>(i, j)[0];			//b
				float g = img1.at<Vec3b>(i, j)[1];			//g
				float r = img1.at<Vec3b>(i, j)[2];				//r
				//2、代入公式运算得到新图BGR(RGB)
				dst1.at<Vec3b>(i, j)[0] = saturate_cast<uchar>(b * alpha + beta); 
				dst1.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(g * alpha + beta);
				dst1.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(r * alpha + beta);
				//注:三通道是<Vec3b>类型
			}
		}

效果:

5、代码

//亮度和对比度增强(彩图与灰图)
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

Mat img1, img2, dst1, dst2;

//图像初始化
void Image_Init()
{
	img1 = imread("Resource/test.jpg");
	cvtColor(img1, img2,  COLOR_RGB2GRAY);			//颜色转换函数
	//			原图		新图			RGB转GRAY
	//创建新图
	dst1 = Mat::zeros(img1.size(), img1.type());	
	dst2 = Mat::zeros(img2.size(), img2.type());
	
	if (img1.empty() || img2.empty())
	{
		printf("图像加载失败");
		exit(0);
	}
}

//亮度和对比度变化
void Brightness_and_Contrast()
{
	float alpha = 1.5, beta = 30;			//对比度参数、亮度参数
	//单通道处理
	if( img2.channels() == 1)
		for (int i = 0; i < img2.rows; i++)
		{
			for (int j = 0; j < img2.cols; j++)
			{
				dst2.at<uchar>(i, j) = saturate_cast<uchar>((float)img2.at<uchar>(i, j) * alpha + beta);
				//注:单通道是<uchar>类型
			}
		}
	//多通道处理
	if (img1.channels() == 3)
		for (int i = 0; i < img1.rows; i++)
		{
			for (int j = 0; j < img1.cols; j++)
			{
				//1、获取原图的BGR(RGB)
				float b = img1.at<Vec3b>(i, j)[0];			//b
				float g = img1.at<Vec3b>(i, j)[1];			//g
				float r = img1.at<Vec3b>(i, j)[2];				//r
				//2、代入公式运算得到新图BGR(RGB)
				dst1.at<Vec3b>(i, j)[0] = saturate_cast<uchar>(b * alpha + beta); 
				dst1.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(g * alpha + beta);
				dst1.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(r * alpha + beta);
				//注:三通道是<Vec3b>类型
			}
		}
}

//显示图像
void Show()
{
	imshow("彩色原图", img1);
	imshow("彩色新图", dst1);
	imshow("灰度原图", img2);
	imshow("灰度新图", dst2);
}

int main()
{
	Image_Init();								//图像初始化

	Brightness_and_Contrast();		//亮度和对比度增强

	Show();										//显示图像

	waitKey(0);

	return 0;
}

三、线性变换API

src:原图;        dst:新图;        alpha:对比度参数;        beta:亮度参数 

 公式: (O(r, c) = a * I(r, c) + b)                (线性变换,和上面一样)

 代码

//线性变换API
void Linear_API()
{
	float alpha = 1.5, beta = 30;				//对比度参数、亮度参数

	convertScaleAbs(img1, dst1, alpha, beta);  //调用API接口(彩图)
	convertScaleAbs(img2, dst2, alpha, beta);  //调用API接口(灰图)
}

效果和上面一样

总代码

//亮度和对比度增强(彩图与灰图)
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

Mat img1, img2, dst1, dst2;

//图像初始化
void Image_Init()
{
	img1 = imread("Resource/test.jpg");
	cvtColor(img1, img2,  COLOR_RGB2GRAY);			//颜色转换函数
	//			原图		新图			RGB转GRAY
	//创建新图
	dst1 = Mat::zeros(img1.size(), img1.type());	
	dst2 = Mat::zeros(img2.size(), img2.type());
	
	if (img1.empty() || img2.empty())
	{
		printf("图像加载失败");
		exit(0);
	}
}

//亮度和对比度变化
void Brightness_and_Contrast()
{
	float alpha = 1.5, beta = 30;			//对比度参数、亮度参数
	//单通道处理
	if( img2.channels() == 1)
		for (int i = 0; i < img2.rows; i++)
		{
			for (int j = 0; j < img2.cols; j++)
			{
				dst2.at<uchar>(i, j) = saturate_cast<uchar>((float)img2.at<uchar>(i, j) * alpha + beta);
				//注:单通道是<uchar>类型
			}
		}
	//多通道处理
	if (img1.channels() == 3)
		for (int i = 0; i < img1.rows; i++)
		{
			for (int j = 0; j < img1.cols; j++)
			{
				//1、获取原图的BGR(RGB)
				float b = img1.at<Vec3b>(i, j)[0];			//b
				float g = img1.at<Vec3b>(i, j)[1];			//g
				float r = img1.at<Vec3b>(i, j)[2];				//r
				//2、代入公式运算得到新图BGR(RGB)
				dst1.at<Vec3b>(i, j)[0] = saturate_cast<uchar>(b * alpha + beta); 
				dst1.at<Vec3b>(i, j)[1] = saturate_cast<uchar>(g * alpha + beta);
				dst1.at<Vec3b>(i, j)[2] = saturate_cast<uchar>(r * alpha + beta);
				//注:三通道是<Vec3b>类型
			}
		}
}

//线性变换API
void Linear_API()
{
	float alpha = 1.5, beta = 30;				//对比度参数、亮度参数

	convertScaleAbs(img1, dst1, alpha, beta);  //调用API接口(彩图)
	convertScaleAbs(img2, dst2, alpha, beta);  //调用API接口(灰图)
}

//显示图像
void Show()
{
	imshow("彩色原图", img1);
	imshow("彩色新图", dst1);
	imshow("灰度原图", img2);
	imshow("灰度新图", dst2);
}

int main()
{
	Image_Init();							//图像初始化

	//Brightness_and_Contrast();		    //亮度和对比度增强

	Linear_API();							//线性变换API

	Show();									//显示图像

	waitKey(0);

	return 0;
}

 

参考资料:

https://blog.csdn.net/weixin_41695564/article/details/79912840

https://blog.csdn.net/fanjiule/article/details/81607873

https://blog.csdn.net/lu_cuger/article/details/80516237?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162830853716780262546042%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162830853716780262546042&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-2-80516237.pc_search_result_control_group&utm_term=Opencv%E4%BA%AE%E5%BA%A6%E5%92%8C%E5%AF%B9%E6%AF%94%E5%BA%A6%E5%A2%9E%E5%BC%BA&spm=1018.2226.3001.4187

以上是关于OpenCV图像线性变换(图像线性混合亮度和对比度增强线性变换API)的主要内容,如果未能解决你的问题,请参考以下文章

数字图像处理OpenCV3 学习笔记

OpenCV 完整例程39. 图像灰度的线性变换

OpenCV——图像灰度变换

opencv4opencv视频教程 C++ 7手动调整图像亮度与对比度 g(i, j) = αf(i, j) + β(点操作与邻域操作概念)

图像处理 灰度的线性变换

图像处理 灰度的线性变换