建立ROI初级图像融合

初级图像融合介绍两种方法:

1、加权和操作

2、掩模操作

掩模操作效果优于加权和。

因为是很简单的代码,刚好我电脑有浅墨大大的讲解代码,拷贝做了些修改用于讲解 了。

加权和:

  公式: 

输出图像 = 融合占比1 * 输入图像1 +  融合占比2 * 输入图像2

1 = 融合占比 + 融合占比

cvAddWeighted函数定义

CVAPI(void) cvAddWeighted( const CvArr* src1, double alpha,
              const CvArr* src2, double beta,
                 double gamma, CvArr* dst );

作用:计算两个数组(图像阵列)的加权和

参数1:const类的输入图像1

参数2:图像1的融合占比

参数3:const类的输入图像2

参数4:图像2的融合占比

参数5:误差,一般为0

参数6:输出图像

Rect函数定义

template<typename _Tp> inline
Rect_<_Tp>::Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height)
: x(_x), y(_y), width(_width), height(_height) {}

是一个内联类模版的构造函数并做初始化,前面看不懂可以省略,主要看Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height)

参数1:x参数

参数2:y参数

参数3:宽度

参数4:长度

注意:x,y参数是以左上角为原点,x,y参数为正数

ROI(感兴趣区域)

方法一:选取原图像设定矩形区域为ROI;

//定义一个Mat类型并给其设定ROI区域  
Mat imageROI;  
//方法一  
imageROI=image(Rect(500,250,logo.cols,logo.rows)); 

方法二:利用索引,起始索引到终止索引

//方法二  
imageROI=srcImage3(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols)); 

行索引 为 行250 到 行(250+logo的行)

列索引 为 列200 到 列(200+logo的列)

这样就完成了坐标系中点(250,200)对整个logo图的索引,ROI也确定

注意:ROI和源图像指向同一内存缓冲区,因此对ROI的操作会直接影响到源图像

加权和操作源代码:

bool LinearBlending()  
{  
       //【0】定义一些局部变量  
       double alphaValue = 0.5;  
       double betaValue;  
       Mat srcImage2, srcImage3, dstImage;  
   
       //【1】读取图像 ( 两幅图片需为同样的类型和尺寸 )  
       srcImage2= imread("mogu.jpg");  
       srcImage3= imread("rain.jpg");  
   
       if(!srcImage2.data ) { printf("你妹,读取srcImage2错误~! 
"); return false; }  
       if(!srcImage3.data ) { printf("你妹,读取srcImage3错误~! 
"); return false; }  
   
       //【2】做图像混合加权操作  
       betaValue= ( 1.0 - alphaValue );  
       addWeighted(srcImage2, alphaValue, srcImage3, betaValue, 0.0, dstImage);  
   
       //【3】创建并显示原图窗口  
       namedWindow("<2>线性混合示例窗口【原图】 by浅墨", 1);  
       imshow("<2>线性混合示例窗口【原图】 by浅墨", srcImage2 );  
   
       namedWindow("<3>线性混合示例窗口【效果图】 by浅墨", 1);  
       imshow("<3>线性混合示例窗口【效果图】 by浅墨", dstImage );  
   
       return true;  
        
}  

思路:

加权和操作缺点:可能伴随像素饱和,如果源图像ROI未与logo图融合之前就已经为最大像素值,把logo图与ROI融合便会超过最大像素值,造成像素饱和

因此采用掩模操作更好

掩模操作源代码:

#include<iostream>
#include<opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>

using namespace std;
using namespace cv;

int main(int argc, char** argv[])
{
    //【1】读入图像  
    Mat srcImage1 = imread("dota_pa.jpg");
    Mat logoImage = imread("dota_logo.jpg");
    if (!srcImage1.data) { printf("你妹,读取srcImage1错误~! 
"); return false; }
    if (!logoImage.data) { printf("你妹,读取logoImage错误~! 
"); return false; }
    cout << srcImage1.cols << " " << srcImage1.rows << endl;
    cout << logoImage.cols << " " << logoImage.rows << endl;

    //【2】定义一个Mat类型并给其设定ROI区域  
    Mat imageROI = srcImage1(Rect(600, 0, logoImage.cols, logoImage.rows));

    //【3】加载掩膜(必须是灰度图)  
    Mat mask = imread("dota_logo.jpg", 0);

    //【4】将掩膜拷贝到ROI  
    logoImage.copyTo(imageROI, mask);

    //【5】显示结果  
    namedWindow("<1>利用ROI实现图像叠加示例窗口");
    imshow("<1>利用ROI实现图像叠加示例窗口", srcImage1);
    //【6】将融合图像以设定文件路径写入,注意路径后面加上融合图像的自定义的(名字和格式),但是格式得是opencv所支持的
    imwrite("E:\18_List_Code\Opencv_code_puls\ROI\ROI\add.jpg", srcImage1);
    waitKey(0);
    return true;
}

效果图:

写入的图像:

 思路:

copyTo函数定义:

void GpuMat::copyTo(OutputArray dst, InputArray mask) const
{
  copyTo(dst, mask, Stream::Null());
}

例子中便是把logo图像的掩模复制到ROI

 logoImage.copyTo(imageROI, mask);

加载掩模过程:定义Mat类变量 以 灰度图格式读取logo图像,并用copyTo函数进行掩模拷贝。

讲解就到这里了,个人认为讲解已经十分详细了,如果还有不懂,请私信我,如果有发现错误,我回及时改正。2017-12-20 22:09:01

http://www.cnblogs.com/Fsiswo/p/8076076.html 

本文由作者原创,如需转载注明出处!
原文地址:https://www.cnblogs.com/Fsiswo/p/8076076.html