OpenCV 图像混合
Posted 流楚丶格念
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV 图像混合相关的知识,希望对你有一定的参考价值。
理论-线性混合操作原理公式
图像线性混合的数学原理:
G(x)=(1-a)F(x)+aQ(x)
注意事项:
- a的取值范围为0到1之间
- F(x)和Q(x)为参与混合的两幅图像,G(x)表示输出图像
- 通过对两幅图像的每个像素值做线性加权得到最终的输出图像
- 两幅图像的大小和类型必须完全一致,如果把图像当成一个矩阵则两个矩阵相加的前提是维度必须一致,否则没有相加的意义。
相关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()