目录

一、图像线性混合

1、原理及函数介绍

2、代码

 3、图像

二、亮度和对比度增强

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

2、原理

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

代码: 

效果:

4、多通道处理(彩图)

代码:

效果:

5、代码(自实现)

三、线性变换API

 代码

 线性变换总代码

四、图像的加减乘除

1、加

2、相减

3、相乘

4、相除

图像的加减乘除总代码

五、图像的逻辑与或非

1、逻辑与

2、逻辑或

3、逻辑非

逻辑与或非总代码

参考资料:


一、图像线性混合

1、原理及函数介绍

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

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

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

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

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

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

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

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

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

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

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

C++:

addWeighted(img1, 0.5,      img2, (1 - 0.5), 0.0,   dst);		//把img1和img2混合(img1:0.5;img2:(1-0.5)
	//		图1   图1权重    图2    图2权重   常数   对象

python:

dst = cv2.addWeighted(img1, 0.5,   img2, 0.5,   0)
    #                     图1   图1权重  图2  图2权重  常数

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;
}

四、图像的加减乘除

1、加

API:

dst = cv2.add(img1, img2)           #图像相加

相加:实际上就是把img1和img2按照1:1的比例线性混合。 

# 图像相加
def Add():
    dst = cv2.add(img1, img2)
    cv2.imshow("dst", dst)

 

2、相减

API:

dst = cv2.subtract(img1, img2)      #图片相减
# 图像相减
def Subtract():
    dst = cv2.subtract(img1, img2)      #图像相减
    cv2.imshow("dst", dst)

 

3、相乘

API:

dst = cv2.multiply(img1, img2)      #图像相乘
# 图像相乘
def Multiply():
    dst = cv2.multiply(img1, img2)      #图像相乘
    cv2.imshow("dst", dst)

 

4、相除

 API:

dst = cv2.divide(img1, img2)      #图像相除
# 图像相除
def Divide():
    dst = cv2.divide(img1, img2)      #图像相除
    cv2.imshow("dst", dst)

 

图像的加减乘除总代码

# 图像加减乘除
import cv2

# 线性混合
def AddWeight():
    dst = cv2.addWeighted(img1, 0.5,   img2, 0.5,   0)      #线性混合
    #                     图1   图1权重  图2  图2权重  常数
    cv2.imshow("dst", dst)


# 图像相加
def Add():
    add = cv2.add(img1, img2)           #图像相加
    cv2.imshow("add", add)


# 图像相减
def Subtract():
    sub = cv2.subtract(img1, img2)      #图像相减
    cv2.imshow("substract", sub)


# 图像相乘
def Multiply():
    mul = cv2.multiply(img1, img2)      #图像相乘
    cv2.imshow("multiply", mul)


# 图像相除
def Divide():
    div = cv2.divide(img1, img2)      #图像相除
    cv2.imshow("divide", div)


if __name__ == '__main__':
    img1 = cv2.imread('Resource/test17.jpg')
    cv2.imshow('img1', img1)
    img2 = cv2.imread('Resource/words.jpg')
    cv2.imshow('img2', img2)

    AddWeight()     #线性混合
    Add()           #线性相加
    Subtract()      #图像相减
    Multiply()      #图像相乘
    Divide()        #图像相除

    cv2.waitKey(0)

五、图像的逻辑与或非

1、逻辑与

API:

dst = cv2.bitwise_and(img1, img2)  # 图像逻辑与
# 逻辑与
def logic_and():
    dst = cv2.bitwise_and(img1, img2)  # 图像逻辑与
    cv2.imshow("dst", dst)

 

2、逻辑或

API:

dst = cv2.bitwise_or(img1, img2)  # 图像逻辑或
# 逻辑或
def logic_or():
    dst = cv2.bitwise_or(img1, img2)  # 图像逻辑或
    cv2.imshow("dst", dst)

 

3、逻辑非

API:

dst = cv2.bitwise_not(img1)  # 图像逻辑非
# 逻辑非
def logic_not():
    dst = cv2.bitwise_not(img1)  # 图像逻辑非
    cv2.imshow("dst", dst)

 

逻辑与或非总代码

# 图像逻辑运算(与或非)
import cv2

# 逻辑与
def logic_and():
    And = cv2.bitwise_and(img1, img2)  # 图像逻辑与
    cv2.imshow("And", And)


# 逻辑或
def logic_or():
    Or = cv2.bitwise_or(img1, img2)  # 图像逻辑或
    cv2.imshow("Or", Or)


# 逻辑非
def logic_not():
    Not = cv2.bitwise_not(img2)  # 图像逻辑非
    cv2.imshow("Not", Not)


if __name__ == '__main__':
    img1 = cv2.imread('Resource/test17.jpg')
    cv2.imshow('img1', img1)
    img2 = cv2.imread('Resource/words.jpg')
    cv2.imshow('img2', img2)

    logic_and()     #图像逻辑与
    logic_or()      #图像逻辑或
    logic_not()     #图像逻辑非

    cv2.waitKey(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

https://iamarookie.blog.csdn.net/article/details/119078371

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐