「OpenCV」ROI区域叠加&指定区域图像混合

文中内容大多来自大神浅墨_毛星云 所著【OpenCV3编程入门】,在此基础上加入了自己的理解和补充内容。

本节中主要是ROI(region of interest) 感兴趣区域以及 addWeighted函数实现图像混合操作

ROI

从图像中圈定一块区域,作为图像分析的重点,节省处理时间增加精度。主要有两种方式实现:

/**
 * ROI region of interest 感兴趣区域
 * 图像混合操作
 */
#include 
#include 
#include 

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+ 亮度调节量”

参考:https://www.jianshu.com/p/b5c3345de91e

你可能感兴趣的:(「OpenCV」ROI区域叠加&指定区域图像混合)