OpenCV 图像混合

Posted 流楚丶格念

tags:

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

理论-线性混合操作原理公式

图像线性混合的数学原理:

G(x)=(1-a)F(x)+aQ(x)

注意事项:

  1. a的取值范围为0到1之间
  2. F(x)和Q(x)为参与混合的两幅图像,G(x)表示输出图像
  3. 通过对两幅图像的每个像素值做线性加权得到最终的输出图像
  4. 两幅图像的大小和类型必须完全一致,如果把图像当成一个矩阵则两个矩阵相加的前提是维度必须一致,否则没有相加的意义。

相关API (addWeighted)

在OpenCV里面我们使用的API是addWeighted()函数:

void addWeighted(
	InputArray src1, 
	double alpha, 
	InputArray src2, 
	double beta, 
	double gamma, 
	OutputArray dst, 
	int dtype=-1
);  
 
  • InputArray,类型的src1,表示需要加权的第一个数组,常常填一个Mat。
  • alpha,表示第一个数组的权重
  • src2,表示第二个数组,它需要和第一个数组拥有相同的尺寸和通道数。
  • beta,表示第二个数组的权重值。
  • dst,输出的数组,它和输入的两个数组拥有相同的尺寸和通道数。
  • gamma,一个加到权重总和上的标量值。看下面的式子自然会理解。
  • dtype,输出阵列的可选深度,有默认值-1。;当两个输入数组具有相同的深度时,这个参数设置为-1(默认值),即等同于src1.depth()。
    通过这个函数进行加权叠加就可以制造出一些奇特的画面叠加效果,下面这个这个实验我选的图不是很好,没有理想的效果,大家可以自行选取图片实验。程序里面另一个函数是选取ROI后再进行叠加的效果;

代码示例

#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>  

using namespace std;
using namespace cv;

int main(int argv, char** argc) {
	Mat src1, src2, dst;
	src1 = imread("./test.jpg");
	src2 = imread("./test2.jpg");
	if (!src1.data || !src2.data) {
		cout << "图片读取不到" << endl;
		return -1;
	}
	imshow("nv1 Pic", src1);
	imshow("nv2 Pic", src2);

	if (src1.size() == src2.size() && src1.type() == src2.type()) {

		Mat dst1, dst2, dst3, dst4, dst5, dst6;
		double alpha = 0.5;
		//理论-线性混合操作: g(x) = (1-α)*f0(x) + α*f1(x)  其中α的取值范围为0~1之间,f0(x)表示一张图像x位置像素点的颜色数据,f1(x)表示另一张
		//输出的混合图像计算公式 : dst(I) = saturate_cast(src1(I)*alpha + src2(I)*beta + gamma)  这里计算的是两张图像对应位置像素点的颜色数据
		//参数:输入图像1、图像1的比重、输入图像2、图像2的比重、gamma值(如果混合的图像较暗,可以使其变量)、输出混合图像。  两张图像的大小和类型必须一致才可以
		addWeighted(src1, alpha, src2, 1 - alpha, 0.0, dst1);//由计算公式可以看出dst是由src1、src2个一半合成的
		add(src1, src2, dst2, Mat());// dst(I) = saturate_cast(src1(I) + src2(I))  将对应位置像素点颜色数据直接相加
		add(src1, Scalar(0, 0, 55), dst3);// dst(I) = saturate_cast(src1(I) + Scalar(I))  将对应位置像素点颜色数据直接加上固定颜色像素值,这里src是三通道的RGB,所以Scalar也是3
		subtract(src1, src2, dst4, Mat());// dst(I) = saturate_cast(src1(I) - src2(I))  将对应位置像素点颜色数据直接相减,同add一样,也可以减Scalar
		multiply(src1, src2, dst5, 1.0);// dst(I) = saturate_cast(src1(I) * src2(I) * scale)  将对应位置像素点颜色数据相乘再乘scale,同add一样,也可以乘Scalar
		divide(src2, src1, dst6, 2.0);// dst(I) = saturate_cast((src1(I)/src2(I)) * scale)  将对应位置像素点颜色数据相除再乘scale,同add一样,也可以除Scalar

		imshow("addWeighted", dst1);
		imshow("add_src2", dst2);
		imshow("add_scalar", dst3);
		imshow("subtract", dst4);
		imshow("multiply", dst5);
		imshow("divide", dst6);
	}
	else {
		cout << "两张图片大小不一致" << endl;
		return -1;
	}

	waitKey(0);
	return 0;
}

以上是关于OpenCV 图像混合的主要内容,如果未能解决你的问题,请参考以下文章

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

opencv4opencv视频教程 C++ 6图像混合线性混合混合权重相加addWeighted()混合加add()混合乘multiply()

opencv图像混合,分离颜色通道多通道图像混合

opencv学习-图像混合

Opencv 图像拼接混合(Multiband blending)

opencv 图像的线性混合