图像混合

1.首先是copyTo的使用

Mat image;//原图像;
Mat logoimage;//logo的图像,想要将此logo图像粘贴在原图像的一个特定位置上;
Mat imageROI= image(Rect(0,250,logoimage.cols,logoimage.rows));//在原图像上框选感兴趣的区域

定义一个Mat类型的ROI图像。此图像是在原图像上进行部分的框选,其中0,250是左上角的坐标,logoimage.cols与logoimage.rows代表所取区域的列与行的长度;,所以这样一个感兴趣区域就选取完了;

首先大家都知道的是:

copyTo有两种使用形式;

最基础的也就是logoimage.copyTo(imageROI);的形式;也就是把logoimage的内容复制粘贴到imageROI上;

另外一种格式:

logoimage.copyTo(imageROI,mask);大家普遍的理解是:把mask和logoimage重叠以后把mask中像素值为0(black)的点对应的logoimage中的点变为透明,而保留其他点。

其中imageROI为我们所要复制粘贴到的image上的区域,因为imageROI并不是我们从image克隆来的,imageROI的数据与原图像image共享存储区域,所以在imageROI上进行的操作也会作用在原图image上;

使用第一种image.copyTo的方式得到的图像:

使用第二种image.copyTo(imageROI,mask)的方式得到的图像:

2.addWeighted的使用

addweighted的格式:(InputArray src1,double alpha,InputArray src2,double beta,double gramma,OutputArray dst,int dype=-1)

·第一个参数,InputArray类型的src1,表示需要加权的第一个数组,常常填写一个Mat;

·第二个参数,double类型的alpha,表示第一个数组的权重;

·第三个参数,InputArray类型的src2,表示第二个数组,他需要和第一个数组拥有相同的尺寸和通道数;

·第四个参数,double类型的gamma,一个加权到权重总和上的标量值,其含义通过接下来列出的式子自然就会理解;

·第六个参数,OutputArray类型的dst,输出的数组,它和输入的两个数组拥有相同的尺寸和通道数;

·第七个数组,int类型的dtype,输出阵列的可选深度,有默认值-1,当两个输入数组具有相同深度的时候,这个参数设置为-1(默认值),即等同于src1.depth();

下面的数学公式表示:用addWeighted函数计算以下两个数组(srel 和sre2)的加权和,得到结果输出给第四个参数,也就是addWeighted函数的作用的矩阵

dst=src1[I]*alpha+ src2[I] *beta + gamma;
其中1是多维数组元素的索引值。而且,在遇到多通道数组的时候,每个通道都需要独立地进行处理。另外需要注意的是,当输出数组的深度为CV_ 32S时,这个函数就不适用了,这时候就会内存溢出或者算出的结果压根不对。

附上来自《OpenCV3编程入门》一书的实例:

//---------------------------------【头文件、命名空间包含部分】-------------------------------
//      描述:包含程序所使用的头文件和命名空间
//------------------------------------------------------------------------------------------------
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>using namespace cv;
using namespace std;//-----------------------------------【全局函数声明部分】--------------------------------------
//  描述:全局函数声明
//-----------------------------------------------------------------------------------------------
bool  ROI_AddImage();
bool  LinearBlending();
bool  ROI_LinearBlending();
void   ShowHelpText();//-----------------------------------【main( )函数】--------------------------------------------
//  描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main(   )
{system("color 6F");ShowHelpText();if(ROI_AddImage( )&& LinearBlending( )&&ROI_LinearBlending( )){cout<<endl<<"\n运行成功,得出了需要的图像";}waitKey(0);return 0;
}//-----------------------------------【ShowHelpText( )函数】----------------------------------
//       描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
void ShowHelpText()
{printf("\n\n  ----------------------------------------------------------------------------\n");
}//----------------------------------【ROI_AddImage( )函数】----------------------------------
// 函数名:ROI_AddImage()
//  描述:利用感兴趣区域ROI实现图像叠加
//----------------------------------------------------------------------------------------------
bool  ROI_AddImage()
{// 【1】读入图像Mat srcImage1= imread("../dota_pa.jpg");Mat logoImage= imread("../2.png");if( !srcImage1.data ) { printf("读取srcImage1错误~! \n"); return false; }if( !logoImage.data ) { printf("读取logoImage错误~! \n"); return false; }// 【2】定义一个Mat类型并给其设定ROI区域Mat imageROI= srcImage1(Rect(0,250,logoImage.cols,logoImage.rows));// 【3】加载掩模(必须是灰度图)Mat mask= imread("../2.png",0);//【4】将掩膜拷贝到ROIlogoImage.copyTo(imageROI,mask);
//    logoImage.copyTo(imageROI);// 【5】显示结果namedWindow("<1>利用ROI实现图像叠加示例窗口");imshow("<1>利用ROI实现图像叠加示例窗口",srcImage1);return true;
}//---------------------------------【LinearBlending()函数】-------------------------------------
// 函数名:LinearBlending()
// 描述:利用cv::addWeighted()函数实现图像线性混合
//--------------------------------------------------------------------------------------------
bool  LinearBlending()
{//【0】定义一些局部变量double alphaValue = 0.4;double betaValue;Mat srcImage2, srcImage3, dstImage;// 【1】读取图像 ( 两幅图片需为同样的类型和尺寸 )srcImage2 = imread("../1.jpg");srcImage3 = imread("../51.jpg");if( !srcImage2.data ) { printf("读取srcImage2错误! \n"); return false; }if( !srcImage3.data ) { printf("读取srcImage3错误! \n"); return false; }// 【2】进行图像混合加权操作betaValue = ( 1.0 - alphaValue );addWeighted( srcImage2, alphaValue, srcImage3, betaValue, 0.0, dstImage);// 【3】显示原图窗口imshow( "<2>线性混合示例窗口【原图】", srcImage2 );imshow( "<3>线性混合示例窗口【效果图】", dstImage );return true;}//---------------------------------【ROI_LinearBlending()】-------------------------------------
// 函数名:ROI_LinearBlending()
// 描述:线性混合实现函数,指定区域线性图像混合.利用cv::addWeighted()函数结合定义
//            感兴趣区域ROI,实现自定义区域的线性混合
//--------------------------------------------------------------------------------------------
bool  ROI_LinearBlending()
{//【1】读取图像Mat srcImage4= imread("../dota_pa.jpg",1);Mat logoImage= imread("../2.png");if( !srcImage4.data ) { printf("读取srcImage4错误~! \n"); return false; }if( !logoImage.data ) { printf("读取logoImage错误~! \n"); return false; }//【2】定义一个Mat类型并给其设定ROI区域Mat imageROI;//方法一imageROI= srcImage4(Rect(200,250,logoImage.cols,logoImage.rows));//方法二//imageROI= srcImage4(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));//【3】将logo加到原图上addWeighted(imageROI,0.5,logoImage,0.3,0.,imageROI);//【4】显示结果imshow("<4>区域线性图像混合示例窗口",srcImage4);return true;
}

我们需要注意的是:因为我们是对srcImage1和srcImage2进行求和,所以他们必须有相同的尺寸(宽度和高度)和类型,不然多余的部分没有对应的伴,肯定就会出问题;

颜色通道分离,多通道图像混合

对于三通道或四通道图像,有时要对某一通道的像素值进行修改或展示,这就需要进行通道分离操作。修改后,若要进行结果展示,就需要重新将各通道合并。

通道分离:split()函数

void split (InputArray m, OutputArrayOfArrays mv);

  • m ,需要进行分离的多通道矩阵,一般为 Mat 类型。
  • mv ,用来存储分离后的多个矩阵,可用 vector 容器来存储。

通道合并:merge()函数

void merge(InputArrayOfArrays mv,OutputArray dst);

  • mv ,需要被合并的多个矩阵,多使用 vector 容器存储,mv 中所有矩阵必须有着一样的尺寸和深度。
  • dst ,输出矩阵,和 m[0] 拥有一样的尺寸和深度,并且通道的数量是矩阵阵列中的通道数总和。

附上来自《OpenCV3编程入门》一书的实例:

//-----------------------------------【头文件包含部分】---------------------------------------
//  描述:包含程序所依赖的头文件
//------------------------------------------------------------------------------------------------
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>//-----------------------------------【命名空间声明部分】---------------------------------------
//  描述:包含程序所使用的命名空间
//-------------------------------------------------------------------------------------------------
using namespace cv;
using namespace std;//-----------------------------------【全局函数声明部分】--------------------------------------
//  描述:全局函数声明
//-----------------------------------------------------------------------------------------------
bool  MultiChannelBlending();
void ShowHelpText();//-----------------------------------【main( )函数】------------------------------------------
//  描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main(   )
{system("color 9F");ShowHelpText( );if(MultiChannelBlending( )){cout<<endl<<"\n运行成功,得出了需要的图像~! ";}waitKey(0);return 0;
}//-----------------------------------【ShowHelpText( )函数】----------------------------------
//       描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
void ShowHelpText()
{printf("\n\n  ----------------------------------------------------------------------------\n");
}//-----------------------------【MultiChannelBlending( )函数】--------------------------------
//  描述:多通道混合的实现函数
//-----------------------------------------------------------------------------------------------
bool  MultiChannelBlending()
{//【0】定义相关变量Mat srcImage;Mat logoImage;vector<Mat> channels;Mat  imageBlueChannel;//=================【蓝色通道部分】=================//    描述:多通道混合-蓝色分量部分//============================================// 【1】读入图片logoImage= imread("../dota_logo.jpg",0);srcImage= imread("../dota_jugg.jpg");if( !logoImage.data ) { printf("Oh,no,读取logoImage错误~! \n"); return false; }if( !srcImage.data ) { printf("Oh,no,读取srcImage错误~! \n"); return false; }//【2】把一个3通道图像转换成3个单通道图像split(srcImage,channels);//分离色彩通道//【3】将原图的蓝色通道引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变imageBlueChannel= channels.at(0);//    namedWindow("zhy");
//    imshow("zhy",imageBlueChannel);//【4】将原图的蓝色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageBlueChannel中addWeighted(imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,0,imageBlueChannel(Rect(500,250,logoImage.cols,logoImage.rows)));//【5】将三个单通道重新合并成一个三通道merge(channels,srcImage);//【6】显示效果图namedWindow(" <1>游戏原画+logo蓝色通道");imshow(" <1>游戏原画+logo蓝色通道",srcImage);//=================【绿色通道部分】=================// 描述:多通道混合-绿色分量部分//============================================//【0】定义相关变量Mat  imageGreenChannel;//【1】重新读入图片logoImage= imread("../dota_logo.jpg",0);srcImage= imread("../dota_jugg.jpg");if( !logoImage.data ) { printf("读取logoImage错误~! \n"); return false; }if( !srcImage.data ) { printf("读取srcImage错误~! \n"); return false; }//【2】将一个三通道图像转换成三个单通道图像split(srcImage,channels);//分离色彩通道//【3】将原图的绿色通道的引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变imageGreenChannel= channels.at(1);//【4】将原图的绿色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageGreenChannel中addWeighted(imageGreenChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,0.,imageGreenChannel(Rect(500,250,logoImage.cols,logoImage.rows)));//【5】将三个独立的单通道重新合并成一个三通道merge(channels,srcImage);//【6】显示效果图namedWindow("<2>游戏原画+logo绿色通道");imshow("<2>游戏原画+logo绿色通道",srcImage);//=================【红色通道部分】=================//   描述:多通道混合-红色分量部分//============================================//【0】定义相关变量Mat  imageRedChannel;//【1】重新读入图片logoImage= imread("dota_logo.jpg",0);srcImage= imread("dota_jugg.jpg");if( !logoImage.data ) { printf("Oh,no,读取logoImage错误~! \n"); return false; }if( !srcImage.data ) { printf("Oh,no,读取srcImage错误~! \n"); return false; }//【2】将一个三通道图像转换成三个单通道图像split(srcImage,channels);//分离色彩通道//【3】将原图的红色通道引用返回给imageBlueChannel,注意是引用,相当于两者等价,修改其中一个另一个跟着变imageRedChannel= channels.at(2);//【4】将原图的红色通道的(500,250)坐标处右下方的一块区域和logo图进行加权操作,将得到的混合结果存到imageRedChannel中addWeighted(imageRedChannel(Rect(500,250,logoImage.cols,logoImage.rows)),1.0,logoImage,0.5,0.,imageRedChannel(Rect(500,250,logoImage.cols,logoImage.rows)));//【5】将三个独立的单通道重新合并成一个三通道merge(channels,srcImage);//【6】显示效果图namedWindow("<3>游戏原画+logo红色通道 ");imshow("<3>游戏原画+logo红色通道 ",srcImage);return true;
}

对分离通道的理解:

因为是将三个通道分离了,所以得到的分离出来的单独一个通道的图像其像素值只是一个了,最终呈现出来的也就是灰度图像,而不是彩色的了,在使用merge融合的时候,融合的是对应通道的像素值,譬如分离出来的R通道的图片,那么logo图片与所分离出来的图片进行融合的时候,融合的也就是R通道的像素值,虽然此时看到的依旧是灰度图像,这是因为此时只有一个通道,将三个通道融合后,R通道的数值由于加上了logoR通道的数值,所以logo处在最终图片上变为红色;

opencv3中的图像混合操作相关推荐

  1. Java中的图像锐化操作

    ** Java中的图像锐化操作 ** 一.该图像锐化的思想: 本文的图像锐化是将图像中的R,G,B的值分别从原图像中提出,然后将分别将这三个R,G,B的值分别与卷积核进行卷积,最终再将最后的三个卷积的 ...

  2. opencv感兴趣区域ROI的图像混合操作

    AddWeighted( const CvArr* src1, double alpha,const CvArr* src2, double beta,double gamma, CvArr* dst ...

  3. 【Unity3D Shader编程】之五 圣诞夜篇 Unity中Shader的三种形态对比 混合操作合辑

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...

  4. 独家 | 在PyTorch中用图像混合(Mixup)增强神经网络(附链接)

    作者:Ta-Ying Cheng翻译:陈之炎校对:车前子本文约2000字,建议阅读5分钟随机混合图像,效果是不是会更好? 标签:神经网络.图像混合 一直以来,在深度学习领域,图像分类是呈指数级增长的课 ...

  5. 转载:【OpenCV入门教程之五】 分离颜色通道多通道图像混合

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/21176257 作者:毛星云(浅墨) ...

  6. 转载:【OpenCV入门教程之四】 ROI区域图像叠加初级图像混合 全剖析

    [OpenCV入门教程之四] ROI区域图像叠加&初级图像混合 全剖析 浅墨_毛星云 2014-03-10 12:48:05 157425 收藏 19 最后发布:2014-03-10 12:4 ...

  7. 【OpenCV入门教程之五】 分离颜色通道多通道图像混合(转)

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/21176257 作者:毛星云(浅墨) ...

  8. 【OpenCV C++】分离颜色通道多通道图像混合

    分离颜色通道&多通道图像混合 一.分离颜色通道 <1>split函数详解 <2>merge函数详解 二.多通道图像混合示例程序 本系列文章由@浅墨_毛星云 出品,转载请 ...

  9. Python Imaging Library: ImageChops Module(图像通道操作模块)

    Python Imaging Library: ImageChops Module(图像通道操作模块) ImageChops模块包含一定数量的算术图像操作.目前,大多数通道操作只支持8位图像(如&qu ...

  10. 图像翻转操作:深入了解cv::flip函数

    文章目录 引言: 1. cv::flip函数概述: 2. 代码示例: 3. 结果分析: 4. 总结: 引言: 在图像处理中,图像翻转是一种常见的操作,它可以在水平.垂直或同时水平和垂直方向改变图像的方 ...

最新文章

  1. 12c表空间不存在_一文看懂Oracle查询表空间的每日增长量和历史情况统计
  2. Mars的mp3实例
  3. oracle查询学生人数语句,Oracle期末复习题-带答案
  4. PHP学习总结(13)——PHP入门篇之常量
  5. ZOJ 1709 Oil Deposits
  6. mysql maratadb_Mysql/Mairadb主从复制
  7. 如何从命令行删除MongoDB数据库?
  8. 油猴脚本Tampermonkey初体验
  9. 证明n次根号下n阶乘等价于n/e
  10. php留言板示例,php留言板完整实例源码
  11. unity实现mmd功能(跳舞)
  12. Akka-CQRS(4)- CQRS Writer Actor 示范
  13. Android MP3播放器MediaPlayer
  14. 4.名词性从句的起源与本质
  15. 从win10回退到win7的苦逼经历
  16. GOOGLE搜索秘籍--高级搜索:site,link,inurl,allinurl,intitle,allintitle
  17. 魔法少女小圆计算机音乐,求魔法少女小圆一些背景音乐的名字
  18. 【文献学习】Complex-Valued Convolutions for Modulation Recognition using Deep Learning
  19. Linux网络服务-----测试网络命令与DHCP服务
  20. 最新公司级 OKRs 案例

热门文章

  1. CSS 排版与正常流 —— 重学CSS
  2. BugTracker配置
  3. 月夜无声,谁与我醉今宵
  4. 无服务器搭建Artalk评论系统后端
  5. Epic安装不成功/启动失败“必要的先决条件安装失败“
  6. 安卓手机里的“其他”为何占用如此多?我用adb+excel来处理
  7. 【React】React全家桶(八)React Router 6
  8. spring学期总结
  9. 微型计算机的显示器是,微型计算机显示器.doc
  10. 【​观察】做好数据到介质的连接者 新数据时代浪潮存储的行与思