文中内容大多来自大神浅墨_毛星云 所著【OpenCV3编程入门】,在此基础上加入了自己的理解和补充内容。
本节中主要是ROI(region of interest) 感兴趣区域以及 addWeighted函数实现图像混合操作
ROI
从图像中圈定一块区域,作为图像分析的重点,节省处理时间增加精度。主要有两种方式实现:
/**
* ROI region of interest 感兴趣区域
* 图像混合操作
*/
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
void ROI_AddImage();
void LinearBlending();
void ROI_LinearBlending();
int main() {
ROI_AddImage();
LinearBlending();
ROI_LinearBlending();
waitKey(0);
return 0;
}
/**
*掩膜实现ROI图像
*/
void ROI_AddImage() {
//读入图像
Mat srcImage = imread("/Users/*/Pictures/timg.jpeg");
Mat logoImage = imread("/Users/*/Pictures/img/OnePiece.png");
if (!srcImage.data) {
printf("读取srcImage错误\n");
return;
}
if (!logoImage.data) {
printf("读取logoImage错误\n");
return;
}
//定义一个Mat类型并给其设定ROI区域 矩形左上角坐标+长宽
//error:libc++abi.dylib: terminating with uncaught exception of type cv::Exception: OpenCV(4.3.0) /Users/ing/opencv-4.3.0/modules/core/src/matrix.cpp:466: error: (-215:Assertion failed) 0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= m.rows in function 'Mat'
Mat imageROI = srcImage(Rect(10, 10, logoImage.cols, logoImage.rows));
//加载掩膜(0 表示必须是单通道灰度图)
Mat mask = imread("/Users/*/Pictures/img/OnePiece.png", 0);
//将掩膜复制到ROI
logoImage.copyTo(imageROI, mask);
//显示结果
namedWindow("利用ROI实现图像叠加示例窗口");
imshow("利用ROI实现图像叠加示例窗口", srcImage);
}
/**
* 线性混合
*/
void LinearBlending() {
//定义一些局部变量
double alphaValue = 0.5;
double betaValue;
Mat srcImage1, srcImage2, dstImage;
//读取图像--【两幅图片必须为同样的类型和尺寸】
srcImage2 = imread("/Users/*/Pictures/sea.jpeg");
srcImage1 = imread("/Users/*/Pictures/flower.jpeg");
if (!srcImage1.data) {
printf("读取srcImage3错误\n");
return;
}
if (!srcImage2.data) {
printf("读取srcImage2错误\n");
return;
}
//做图像混合加权操作
betaValue = (1.0 - alphaValue);
addWeighted(srcImage1, alphaValue, srcImage2, betaValue, 0.0, dstImage);
//创建并显示原图窗口
namedWindow("线性混合示例窗口[原图]", 1);
imshow("线性混合示例窗口[原图]", srcImage1);
namedWindow("线性混合示例窗口[效果图]", 1);
imshow("线性混合示例窗口[效果图]", dstImage);
}
/**
* ROI区域图像叠加&图像混合
*/
void ROI_LinearBlending() {
Mat srcImage = imread("/Users/*/Pictures/timg.jpeg");
Mat logoImage = imread("/Users/*/Pictures/img/OnePiece.png");
if (!srcImage.data) {
printf("读取srcImage错误\n");
}
if (!logoImage.data) {
printf("读取logoImage错误\n");
}
Mat imageROI;
//方法一
imageROI = srcImage(Rect(10, 10, logoImage.cols, logoImage.rows));
//方法二
//imageROI= srcImage(Range(10,10+logoImage.rows),Range(10,10+logoImage.cols));
//将logo加到原图上
addWeighted(imageROI, 0.8, logoImage, 0.2, 0.0, imageROI);
namedWindow("区域线性图像混合示例窗口", 1);
imshow("区域线性图像混合示例窗口", srcImage);
}
对应的三种运行结果:

掩膜实现ROI图像.png

线性混合.png

ROI区域图像叠加&图像混合.png
补充:
图像加权和,就是在计算两幅图像的像素值之和时,将每幅图像的权重考虑进来,可以用公式表示为
dst= saturate(srcl * α + src2 * β + γ)
式中, saturate(表示取饱和值(最大值)。图像进行加权和计算时,要求 srcl和 src2 必须大小,类型相同,但是对具体是什么类型和通道没有特殊限制,它们可以是任意数据类型,也可以有任意数量的通道(灰度图像或者彩色图像),只要二者相同即可
OpenCv 中提供了函数 cv2.addWeighted,用来实现图像的加权和(混合、融合),该函数的语法格式为
dst=cv2.addWeighted(srcl,alpha,src2,beta, gamma)
参数 alpha和 beta是 srcl 和 src2所对应的系数,它们的和可以等于 1,也可以不等于1
函数实现的功能是 dst= srcl * alpha+src2 * beta +gamma 需要注意,式中参数 gamma 的值
可以是0 但是该参数是必选参数,不能省略。
可以将上式理解为
“结果图像=图像 1×系数1+图像2×系数2+ 亮度调节量”