继续学习core模块下面的《使用OpenCV对两幅图像求和(求混合(blending))》部分:
这个功能有什么用呢?如果想做一个纯色的图片加上一个有东西的图片,想达到像在幻灯片翻页时可以设置为前后页缓慢过渡以产生叠加效果,电影中经常在情节过渡时出现画面叠加效果。
线性混合操作 也是一种典型的二元(两个输入)的 像素操作 :
通过在范围 内改变 ,这个操可以用来对两幅图像或两段视频产生时间上的 画面叠化 (cross-dissolve)效果。主要是在第一幅图片中提取一定权重的像素值,在第二幅图片中提取一定权重的像素值,然后相加赋值给最后的图片,就这么简单。
我们主要运用了OpenCV中addWeighted函数,我们来全面的了解一下它:
addWeighted函数
这个函数的作用是,计算两个数组(图像阵列)的加权和。原型如下:
void addWeighted(InputArray src1, doublealpha, InputArray src2, double beta, double gamma, OutputArray dst, intdtype=-1);
- 第一个参数,InputArray类型的src1,表示需要加权的第一个数组,常常填一个Mat。
- 第二个参数,alpha,表示第一个数组的权重
- 第三个参数,src2,表示第二个数组,它需要和第一个数组拥有相同的尺寸和通道数。
- 第四个参数,beta,表示第二个数组的权重值。
- 第五个参数,dst,输出的数组,它和输入的两个数组拥有相同的尺寸和通道数。
- 第六个参数,gamma, 一个加到权重总和上的标量值。看下面的式子自然会理解。
- 第七个参数,dtype,输出阵列的可选深度,有默认值-1。;当两个输入数组具有相同的深度时,这个参数设置为-1(默认值),即等同于src1.depth()。
如果用数学公式来表达,addWeighted函数计算如下两个数组(src1和src2)的加权和,得到结果输出给第四个参数。即addWeighted函数的作用可以被表示为为如下的矩阵表达式为:
dst = src1[I]*alpha+ src2[I]*beta + gamma;
其中的I,是多维数组元素的索引值。而且,在遇到多通道数组的时候,每个通道都需要独立地进行处理。 另外需要注意的是,当输出数组的深度为CV_32S时,这个函数就不适用了,这时候就会内存溢出或者算出的结果压根不对。
如何实现一张图片然后加到另一张图片上呢?记得图片大小要一致。实现:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
int main(int argc, char** argv)
{
double alpha = 0.5; double beta; double input;
Mat src1, src2, dst;
/// Ask the user enter alpha
std::cout << " Simple 科比+手 " << std::endl;
std::cout << "-----------------------" << std::endl;
std::cout << "* Enter alpha [0-1]: ";
std::cin >> input;
/// We use the alpha provided by the user iff it is between 0 and 1
if (alpha >= 0 && alpha <= 1)
{
alpha = input;
}
/// Read image ( same size, same type )
src1 = imread("C:\\Users\\Administrator\\Desktop\\1.jpg");
src2 = imread("C:\\Users\\Administrator\\Desktop\\kb.jpg");
if (!src1.data) { printf("Error loading src1 \n"); return -1; }
if (!src2.data) { printf("Error loading src2 \n"); return -1; }
/// Create Windows
namedWindow("科比+手", 1);
beta = (1.0 - alpha);
addWeighted(src1, alpha, src2, beta, 0.0, dst);
imshow("科比+手", dst);
waitKey(0);
return 0;
}
结果:
如何能将自己想要的小图片加到一个大图上呢?刚好看到一篇博文,here,感谢浅墨_毛星云。后面会更详细的做一些小功能。
#include <cv.h>
#include <highgui.h>
#include <iostream>
using namespace cv;
using namespace std;
bool ROI_LinearBlending();
int main()
{
system("color 1E");
if (ROI_LinearBlending())
{
cout << endl << "需要的图像:";
}
waitKey(0);
return 0;
}
bool ROI_LinearBlending()
{
//【1】读取图像
Mat srcImage = imread("C:\\Users\\Administrator\\Desktop\\1.jpg", 1);
Mat logoImage = imread("C:\\Users\\Administrator\\Desktop\\2.jpg");
if (!srcImage.data) { printf("读取srcImage错误~! \n"); return false; }
if (!logoImage.data) { printf("读取logoImage错误~! \n"); return false; }
//【2】定义一个Mat类型并给其设定ROI区域
Mat imageROI;
//方法一
imageROI = srcImage(Rect(200, 10, logoImage.cols, logoImage.rows));
//方法二
//imageROI=srcImage4(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));
//【3】将logo加到原图上
addWeighted(imageROI, 0.4, logoImage, 0.7, 0., imageROI);
//【4】显示结果
namedWindow("区域图像叠加");
imshow("区域图像叠加", srcImage);
return true;
}