1、感兴趣区域:ROI
说明:在图像处理领域,设置感兴趣区域来专注或者简化工作过程。从图像中选择的一个图像区域,这个区域是图像分析所关注的重点,圈出这个区域,以便进一步处理。使用ROI指定想要读入的目标,可以减少处理时间,增加精度,给图像处理带来便利。
(1)定义ROI(Rect)
-
使用表示矩形区域的Rect。他指定矩形的左上角坐标(构造函数的前两个参数)和矩形的长宽(构造函数的后两个参数)
Mat imageROI; imageROI=image(Rect(500,250,logo.cols,logo.rows));
-
指定感兴趣行和列的范围(Range)。Range是指从起始索引到终止索引(不包含终止索引)的一连段连续序列。cRange可以用来定义Range
imageROI=image(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));
2、线性混合操作
说明:线性混合操作就是一种典型的二元(两个输入)的像素操作,它的理论公式如下:
g
(
x
)
=
(
1
−
a
)
f
a
(
x
)
+
a
f
3
(
x
)
g(x)=(1-a)fa(x)+af3(x)
g(x)=(1−a)fa(x)+af3(x)
我们通过在范围0-1之间改变alpha值,来对两幅图像(f0(x)、f1(x))或者两段视频(f0(x)、f1(x))产生时间上的画面叠化效果,就像幻灯片放映和电影制作中的那样,也就是在幻灯片翻页时设置前后页缓慢过渡叠加效果以及电影情节过渡经常出现的画面叠加效果。
3、计算数组加权和:addWeighted()函数
函数原型:
void(InputArray src1,double alpha,InputArray src2,double beta,double gamma,OutputArray dst,int dtype=-1);
- 第一个参数:InputArray类型的 src1,表示需要加权的第一个数组,常常填一个Mat。
- 第二个参数:表示第一个数组的权重
- 第三个参数:表示第二个数组,它需要和第一个数组拥有相同的尺寸和通道数
- 第四个参数:表示第二个数组的权重
- 第五个参数:一个加到权重总和上的标量值。
- 第六个参数:输出数组,它和输入的两个数组有相同的尺寸和通道数
- 第七个参数:输出阵列的可选深度,有默认值-1.当两个输入值具有相同的深度时,参数设置-1,即等同于src1.depth().
d s t = s r c 1 [ I ] ∗ a l p h a + s r c 2 [ I ] ∗ b e t a + g a m m a dst=src1[I]*alpha+src2[I]*beta+gamma dst=src1[I]∗alpha+src2[I]∗beta+gamma
说明:I是多维数组元素的索引值。在遇到多通道数组的时候,每个通道都需要独立地进行处理
代码示例:两个图片,一个是下雨天,另一个是蘑菇图片,产生叠化效果
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
//全局函数声明
bool LinearBlending();
int main()
{
system("color 5E");
if ( LinearBlending() )
{
printf("运行成功,得到需要的图像~:");
}
waitKey(0);
}
/*
利用cv:addWeighted()函数实现图像线性混合
*/
bool LinearBlending()
{
//定义一些局部变量
double alphaValue = 0.5;
double betaValue;
Mat srcImage2, srcImage3, dstImage;
//读取图像(两幅图像同样大小)
srcImage2 = imread("D:\\23.jpg");
srcImage3 = imread("D:\\24.jpg");
if (!srcImage2.data) {
printf("读取srcImage2错误~!\n");
return false;
}
if (!srcImage3.data) {
printf("读取srcImage2错误~!\n");
return false;
}
//图像混合加权操作
betaValue = (1.0 - alphaValue);
addWeighted(srcImage2, alphaValue, srcImage3, betaValue, 0.0, dstImage);
//创建并显示原窗口
namedWindow("<2>线性混合示例窗口", 1);
imshow("<2>线性混合示例窗口", srcImage2);
imshow("【rain】", srcImage3);
namedWindow("<3>线性混合示例窗口", 1);
imshow("<3>线性混合示例窗口", dstImage);
return true;
}
4、初级图像混合示例
说明:前面已经介绍感兴趣区域ROI和使用addWeighted函数进行图像线性混合的基础上,我们还可以将二者结合起来使用,也就是指定ROI区域,再用addWeighted函数对指定的ROI区域的图像进行混合操作。
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
//全局函数声明
bool ROI_AddImage();
bool ROI_LinearBlending();
int main()
{
system("color 5E");
if (ROI_AddImage() && ROI_LinearBlending())
{
printf("运行成功,得到需要的图像~:");
}
waitKey(0);
}
/*
利用感兴趣区域ROI实现图像叠加
*/
bool ROI_AddImage()
{
//读入图像
Mat srcImage1 = imread("D:\\dota_pa.jpg");
Mat logoImage = imread("D:\\dota_logo1.jpg");
if (!srcImage1.data) {
printf("读取srcImage1错误~!\n");
return false;
}
if (!logoImage.data) {
printf("读取logoImage错误~!\n");
return false;
}
//定义一个Mat类型并给其设定的ROI区域
Mat imageROI = srcImage1(Rect(200, 50, logoImage.cols, logoImage.rows));
//加载掩膜
Mat mask = imread("dota_logo1.jpg", 0);
//将掩膜复制到ROI
logoImage.copyTo(imageROI, mask);
//显示结果
namedWindow("<1>利用ROI实现图像叠加");
imshow("<1>利用ROI实现图像叠加", srcImage1);
return true;
}
/*
线性混合实现函数,指定区域线性图像混合,利用cv::addWeighted()函数结合定义
*/
bool ROI_LinearBlending()
{
//读取图像
Mat srcImage4 = imread("D:\\dota_pa.jpg", 1);
Mat logoImage = imread("D:\\dota_logo1.jpg");
if (!srcImage4.data) {
printf("读取srcImage4错误~!\n");
return false;
}
if (!logoImage.data) {
printf("读取logoImage错误~!\n");
return false;
}
//定义一个Mat类型并给其设置ROI区域
Mat imageROI;
imageROI = srcImage4(Rect(200, 50, logoImage.cols, logoImage.rows));
//将logo加到原图上
addWeighted(imageROI, 0.5, logoImage, 0.3, 0., imageROI);
//显示结果
namedWindow("<4>区域线性图像混合示例");
imshow("<4>区域线性图像混合", srcImage4);
imshow("logo图", logoImage);
return true;
}
利用ROI实现图像叠加效果图
区域性线性混合示例图