转载:【OpenCV入门教程之四】 ROI区域图像叠加初级图像混合 全剖析
【OpenCV入门教程之四】 ROI区域图像叠加&初级图像混合 全剖析
本系列文章由@浅墨_毛星云 出品,转载请注明出处。
文章链接: http://blog.csdn.net/poem_qianmo/article/details/20911629
作者:毛星云(浅墨) 邮箱: happylifemxy@163.com
一、设定感兴趣区域——ROI(region of interest)
ROI区域定义的两种方法
//定义一个Mat类型并给其设定ROI区域 Mat imageROI; //方法一 imageROI=image(Rect(500,250,logo.cols,logo.rows));另一种定义ROI的方式是指定感兴趣行或列的范围(Range)。Range是指从起始索引到终止索引(不包括终止索引)的一连段连续序列。cv::Range可以用来定义Range。如果使用cv::Range来定义ROI,那么前例中定义ROI的代码可以重写为:
//方法二 imageROI=srcImage3(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));好了,下面我们来看一个实例,显示如何利用ROI将一幅图加到另一幅图的指定位置。大家如果需要拷贝如下的函数中的代码直接运行的话,自己建一个基于console的程序,然后把函数体中的内容拷贝到main函数中,然后找两幅大小合适的图片,加入到工程目录下,并和代码中读取的文件名一致即可。
在下面的代码中,我们通过一个图像掩膜(mask),直接将插入处的像素设置为logo图像的像素值,这样效果会很赞很逼真:
//----------------------------------【ROI_AddImage( )函数】---------------------------------- // 函数名:ROI_AddImage() // 描述:利用感兴趣区域ROI实现图像叠加 //---------------------------------------------------------------------------------------------- bool ROI_AddImage() { //【1】读入图像 Mat srcImage1= imread("dota_pa.jpg"); Mat logoImage= imread("dota_logo.jpg"); if(!srcImage1.data ) { printf("你妹,读取srcImage1错误~! \n"); return false; } if(!logoImage.data ) { printf("你妹,读取logoImage错误~! \n"); return false; } //【2】定义一个Mat类型并给其设定ROI区域 Mat imageROI= srcImage1(Rect(200,250,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); return true; }这个函数首先是载入了两张jpg图片到srcImage1和logoImage中,然后定义了一个Mat类型的imageROI,并使用cv::Rect设置其感兴趣区域为srcImage1中的一块区域,将imageROI和srcImage1关联起来。接着定义了一个Mat类型的的mask并读入dota_logo.jpg,顺势使用Mat:: copyTo把mask中的内容拷贝到imageROI中,于是就得到了最终的效果图,namedWindow和imshow配合使用,显示出最终的结果。
运行结果如下:
这里白色的dota2 logo,就是通过操作之后加上去的图像。
二、初级图像混合——线性混合操作
线性混合操作是一种典型的二元(两个输入)的像素操作,它的理论公式是这样的:
如果看过我之前写的游戏编程Alpha混合那篇文章的朋友们应该有些熟悉,其实他们是差不多的:
【Visual C++】游戏开发五十五浅墨 DirectX教程二十二水乳交融的美学:alpha混合技术
我们通过在范围0到1之间改变alpha值,来对两幅图像(f0(x)和f1(x))或两段视频(同样为(f0(x)和f1(x))产生时间上的画面叠化(cross-dissolve)效果,就像幻灯片放映和电影制作中的那样。即在幻灯片翻页时设置的前后页缓慢过渡叠加效果,以及电影情节过渡时经常出现的画面叠加效果。
实现方面,我们主要运用了OpenCV中addWeighted函数,我们来全面的了解一下它:
addWeighted函数
这个函数的作用是,计算两个数组(图像阵列)的加权和。原型如下:
void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1);
- 第一个参数,InputArray类型的src1,表示需要加权的第一个数组,常常填一个Mat。
- 第二个参数,alpha,表示第一个数组的权重
- 第三个参数,src2,表示第二个数组,它需要和第一个数组拥有相同的尺寸和通道数。
- 第四个参数,beta,表示第二个数组的权重值。
- 第五个参数,dst,输出的数组,它和输入的两个数组拥有相同的尺寸和通道数。
- 第六个参数,gamma,一个加到权重总和上的标量值。看下面的式子自然会理解。
- 第七个参数,dtype,输出阵列的可选深度,有默认值-1。;当两个输入数组具有相同的深度时,这个参数设置为-1(默认值),即等同于src1.depth()。
如果用数学公式来表达,addWeighted函数计算如下两个数组(src1和src2)的加权和,得到结果输出给第四个参数。即addWeighted函数的作用可以被表示为为如下的矩阵表达式为:
dst = src1[I]*alpha+ src2[I]*beta + gamma;
其中的I,是多维数组元素的索引值。而且,在遇到多通道数组的时候,每个通道都需要独立地进行处理。另外需要注意的是,当输出数组的深度为CV_32S时,这个函数就不适用了,这时候就会内存溢出或者算出的结果压根不对。
理论和函数的讲解就是上面这些,接着我们来看代码实例,以融会贯通。
//---------------------------------【LinearBlending()函数】------------------------------------- // 函数名:LinearBlending() // 描述:利用cv::addWeighted()函数实现图像线性混合 //-------------------------------------------------------------------------------------------- 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错误~! \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】创建并显示原图窗口 namedWindow("<2>线性混合示例窗口【原图】 by浅墨", 1); imshow("<2>线性混合示例窗口【原图】 by浅墨", srcImage2 ); namedWindow("<3>线性混合示例窗口【效果图】 by浅墨", 1); imshow("<3>线性混合示例窗口【效果图】 by浅墨", dstImage ); return true; }代码解析:
<0>首先当然是定义一些局部变量,alpha值beta值,三个Mat类型的变量。
//【0】定义一些局部变量 double alphaValue = 0.5; double betaValue; Mat srcImage2, srcImage3, dstImage;在这里我们设置alpha值为0.5。
<1>读取两幅图像并作错误处理
这步很简单,直接上代码:
//读取图像 ( 两幅图片需为同样的类型和尺寸 ) srcImage2= imread("mogu.jpg"); srcImage3= imread("rain.jpg"); if(!srcImage2.data ) { printf("你妹,读取srcImage2错误~! \n"); return false; } if(!srcImage3.data ) { printf("你妹,读取srcImage3错误~! \n"); return false; }在这里需要注意的是,因为我们是对 srcImage1和srcImage2求和,所以它们必须要有相同的尺寸(宽度和高度)和类型,不然多余的部分没有对应的“伴”,肯定会出问题。
<2> 进行图像混合加权操作
载入图像后,我们就可以来生成混合图像,也就是之前公式中的g(x)。为此目的,使用函数 addWeighted 可以很方便地实现,也就是因为 addWeighted 进行了如下计算:
这里的对应于addWeighted的第2个参数alpha
这里的对应于addWeighted的第4个参数beta
这里的对应于addWeighted的第5个参数,在上面代码中被我们设为0.0。
代码其实很简单,就是这样:
//【2】进行图像混合加权操作 betaValue = ( 1.0 - alphaValue ); addWeighted( srcImage2, alphaValue, srcImage3,betaValue, 0.0, dstImage); 其中beta值为1-alpha,gamma值为0。<3>创建显示窗口,显示图像。
// 【3】创建并显示原图窗口 namedWindow("<2>线性混合示例窗口【原图】 by浅墨", 1); imshow("<2>线性混合示例窗口【原图】 by浅墨", srcImage2 ); namedWindow("<3>线性混合示例窗口【效果图】 by浅墨", 1); imshow("<3>线性混合示例窗口【效果图】 by浅墨", dstImage );接着来看一下运行效果图,首先是原图:
然后是效果图:
三、综合示例
在前面分别介绍的设定感兴趣区域ROI和使用addWeighted函数进行图像线性混合的基础上,我们还将他们两者中和起来使用,也就是先指定ROI,并用addWeighted函数对我们指定的ROI区域的图像进行混合操作,我们将其封装在了一个名为ROI_LinearBlending的函数中,方便大家分块学习。
//---------------------------------【ROI_LinearBlending()】------------------------------------- // 函数名:ROI_LinearBlending() // 描述:线性混合实现函数,指定区域线性图像混合.利用cv::addWeighted()函数结合定义 // 感兴趣区域ROI,实现自定义区域的线性混合 //-------------------------------------------------------------------------------------------- bool ROI_LinearBlending() { //【1】读取图像 Mat srcImage4= imread("dota_pa.jpg",1); Mat logoImage= imread("dota_logo.jpg"); 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】显示结果 namedWindow("<4>区域线性图像混合示例窗口 by浅墨"); imshow("<4>区域线性图像混合示例窗口 by浅墨",srcImage4); return true; }从这篇文章开始,如果不出意外的话,为了方便大家分块各个击破学习,每讲一个部分,示例代码都将封装在一个函数中,免得大家像学习各种不是特别地道的OpenCV教程时一样,看到代码全放在main函数中,心都碎了。
好了,下面放出详细注释的本篇文章的全部示例源代码:
//-----------------------------------【程序说明】---------------------------------------------- // 程序名称::【OpenCV入门教程之四】 ROI区域图像叠加&初级图像混合 全剖析 配套源码 // VS2010版 OpenCV版本:2.4.8 // 2014年3月10日 Create by 浅墨 // 图片素材出处:dota2原画 dota2logo // 浅墨的微博:@浅墨_毛星云 //------------------------------------------------------------------------------------------------ //-----------------------------------【头文件包含部分】--------------------------------------- // 描述:包含程序所依赖的头文件 //---------------------------------------------------------------------------------------------- #include <cv.h> #include <highgui.h> #include <iostream> //-----------------------------------【命名空间声明部分】--------------------------------------- // 描述:包含程序所使用的命名空间 //----------------------------------------------------------------------------------------------- using namespace cv; using namespace std; //-----------------------------------【全局函数声明部分】-------------------------------------- // 描述:全局函数声明 //----------------------------------------------------------------------------------------------- bool ROI_AddImage(); bool LinearBlending(); bool ROI_LinearBlending(); //-----------------------------------【main( )函数】-------------------------------------------- // 描述:控制台应用程序的入口函数,我们的程序从这里开始 //----------------------------------------------------------------------------------------------- int main( ) { system("color 5E"); if(ROI_AddImage()&& LinearBlending( )&&ROI_LinearBlending( )) { cout<<endl<<"嗯。好了,得出了你需要的图像~! : )"; } waitKey(0); return 0; } //----------------------------------【ROI_AddImage( )函数】---------------------------------- // 函数名:ROI_AddImage() // 描述:利用感兴趣区域ROI实现图像叠加 //---------------------------------------------------------------------------------------------- bool ROI_AddImage() { //【1】读入图像 Mat srcImage1= imread("dota_pa.jpg"); Mat logoImage= imread("dota_logo.jpg"); if(!srcImage1.data ) { printf("你妹,读取srcImage1错误~! \n"); return false; } if(!logoImage.data ) { printf("你妹,读取logoImage错误~! \n"); return false; } //【2】定义一个Mat类型并给其设定ROI区域 Mat imageROI= srcImage1(Rect(200,250,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); return true; } //---------------------------------【LinearBlending()函数】------------------------------------- // 函数名:LinearBlending() // 描述:利用cv::addWeighted()函数实现图像线性混合 //-------------------------------------------------------------------------------------------- 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错误~! \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】创建并显示原图窗口 namedWindow("<2>线性混合示例窗口【原图】 by浅墨", 1); imshow("<2>线性混合示例窗口【原图】 by浅墨", srcImage2 ); namedWindow("<3>线性混合示例窗口【效果图】 by浅墨", 1); imshow("<3>线性混合示例窗口【效果图】 by浅墨", dstImage ); return true; } //---------------------------------【ROI_LinearBlending()】------------------------------------- // 函数名:ROI_LinearBlending() // 描述:线性混合实现函数,指定区域线性图像混合.利用cv::addWeighted()函数结合定义 // 感兴趣区域ROI,实现自定义区域的线性混合 //-------------------------------------------------------------------------------------------- bool ROI_LinearBlending() { //【1】读取图像 Mat srcImage4= imread("dota_pa.jpg",1); Mat logoImage= imread("dota_logo.jpg"); 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】显示结果 namedWindow("<4>区域线性图像混合示例窗口 by浅墨"); imshow("<4>区域线性图像混合示例窗口 by浅墨",srcImage4); return true; }最后看一下整体的运行效果图。
首先是经过背景颜色修改的console窗口:
然后依次是四张效果图:
嗯,本篇文章到这里就基本结束了,最后放出本篇文章配套示例程序的下载地址。
本篇文章的配套源代码请点击这里下载:
【浅墨OpenCV入门教程之四】配套源代码下载
OK,本节的内容大概就是这些,我们下篇文章见:)
<div class="person-messagebox"><div class="left-message"><a href="https://blog.csdn.net/zhmxy555"><img src="https://profile.csdnimg.cn/0/4/9/3_zhmxy555" class="avatar_pic" username="zhmxy555"></a></div><div class="middle-message"><div class="title"><span class="tit "><a href="https://blog.csdn.net/zhmxy555" data-report-click="{"mod":"popu_379","ab":"new"}" target="_blank">浅墨_毛星云</a></span><!-- 等级,level --><img class="identity-icon" src="https://csdnimg.cn/identity/blog8.png"> <span class="flag expert"><a href="https://blog.csdn.net/home/help.html#classicfication" target="_blank"><img src="https://csdnimg.cn/release/phoenix/template/new_img/identityExpert.png" alt="">博客专家</a></span></div><div class="text"><span>原创文章 159</span><span>获赞 9891</span><span>访问量 755万+</span></div></div><div class="right-message"><a class="btn btn-sm attented bt-button personal-watch" data-report-click="{"mod":"popu_379","ab":"new","extend1":"个人信息已关注"}">已关注</a><a href="https://bbs.csdn.net/topics/395528843" target="_blank" class="btn btn-sm bt-button personal-messageboard">他的留言板</a></div></div></div>
</article>
http://www.taodudu.cc/news/show-620654.html
相关文章:
- 转载:opencv错误rect错误
- 转载:opencv:关于vs opencv每次都要配置的解决方案
- 转载:矩阵的掩膜操作实现图像对比度调整
- 转载:掩膜矩阵操作数学解释(权重表,锐化)
- 【OpenCV入门学习笔记1】:Mat对象的指针操作和掩膜操作
- 【OpenCV入门学习笔记2】:Mat对象
- 转载:【OpenCV入门教程之五】 分离颜色通道多通道图像混合
- 转载:【opencv入门教程之六】创建Trackbar图片对比度、亮度值调整
- #转载:十大排序方法,动图展示
- #转载:杨辉三角形实现过程详解-c语言基础
- 转载:socket通信基础
- 学习笔记:linuxsocket通信基础
- 学习笔记:二叉搜索树的验证
- 学习笔记:验证对称二叉树
- 转载:如何将一个新函数加到MATLAB函数库中
- 转载:VMware Workstation 无法连接到虚拟机。
- 大一阶段性总结
- windows下的文本文件在linux下查看,中文显示乱码
- make警告:检测到时钟错误。您的创建可能是不完整的
- 《实用》secureCRT远程连接linux虚拟机-突然连接不上-解决办法
- 关于文件描述符的问题的解决
- 库函数设计:关于文件类打开操作函数不自动创建不存在的父目录问题
- 忽略所有信号导致的程序Ctrl+c和Ctrl+z无法退出问题,以及信号表详解
- qxidc项目/crtsurfdata程序 杀青总结
- 映射递归循环-约瑟夫环问题递归解法的一点理解
- 转载:二叉树的前中后和层序遍历详细图解(递归和非递归写法)
- 新建虚拟机update时出现不能得到锁问题
- 新建虚拟机Ubuntu16.4安装搜狗输入法的问题
- ubuntu安装搜狗输入法-全面版
- centos7花里胡哨之终端美化
转载:【OpenCV入门教程之四】 ROI区域图像叠加初级图像混合 全剖析相关推荐
- 转载:【OpenCV入门教程之五】 分离颜色通道多通道图像混合
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/21176257 作者:毛星云(浅墨) ...
- 【OpenCV入门教程之五】 分离颜色通道多通道图像混合(转)
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/21176257 作者:毛星云(浅墨) ...
- 转载:【opencv入门教程之三】:图片的载入|显示|输出
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/20537737 作者:毛星云(浅墨) ...
- 转载:【opencv入门教程之三】:组件结构
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/19925819 作者:毛星 ...
- 转载:【opencv入门教程之一】:配置
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/19809337 作者:毛星云(浅 ...
- 转载:【opencv入门教程之六】创建Trackbar图片对比度、亮度值调整
[OpenCV入门教程之六] 创建Trackbar & 图像对比度.亮度值调整 浅墨_毛星云 2014-03-18 21:43:18 103746 收藏 21 最后发布:2014-03-18 ...
- 【OpenCV入门教程之十三】OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/26157633 作者:毛星云(浅墨) ...
- 【OpenCV入门教程之三】 图像的载入,显示和输出 一站式完全解析
[-] 一开胃菜之一 关于OpenCV的命名空间 二开胃菜之二 关于Mat类型 三图像的载入和显示 imread函数 namedWindow函数 imshow函数 四输出图像到文件imwrite函 ...
- 【OpenCV入门教程之十一】 形态学图像处理(二):开运算、闭运算、形态学梯度、顶帽、黑帽合辑
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/23184547 作者:毛星云(浅墨) ...
最新文章
- 牛客网-剑指offer 第二题(字符替换)
- 【Flink】Flink on RocksDB 参数调优指南
- 第12章[12.10.1] Ext JS + CKEditor+Spring Boot 实现编辑器图片上传
- 63. 无阻塞加载脚本
- 搞懂Java代理和反射一篇就够了
- 我是如何次次《头脑王者》获得满分的
- C语言之求两个数的最大公因数和最小公倍数
- 218分照样可以成为同声传译研究生3
- 制作AppStore预览:在 iPhone 上截屏或录制屏幕15秒以上的视频;iPhone日常使用技巧(一直弹出登录iCloud的解决方法、不自动弹出询问是否允许使用蜂窝数据的解决方法)
- ESP8266串口透传+WiFi储存+OTA+smartconfig/airkiss
- 基于S-FFT的相息图
- 运动无线耳机哪个品牌比较好、口碑最好的运动蓝牙耳机
- escape在sql语句中的作用
- strncasecmp与strcasecmp用法
- ESP8266 Arduino Hard resetting via RTS pin...
- 中国城市人口排名(最新版)
- Hibernate 注解 实现一对多
- 苹果13系统锁屏延迟_iPhone锁屏有延迟怎么办 锁屏延迟问题解决方法
- 【算法练习】罗马数字转整数与整数转罗马数字
- 今天是我的生日,写篇文章庆祝一下
热门文章
- zigbee绑定 使用_遇见-果加智能锁F2——使用体验
- BZOJ-3505-数三角形-CQOI2014
- ECCV 2020《TRRNet: Tiered Relation Reasoning for Compositional Visual Question Answering》论文笔记
- 2020-07-08 CVPR2020 表示学习论文讨论(3) 笔记
- 【五校联考7day1】游戏
- java在td中怎么用if_不在Java中使用if语句
- linuxpython23同时_linux上安装python3同时保留python2
- Excel中文字换行
- cxf客户端访问方式
- 天猫11.11:手机淘宝 521 性能优化项目揭秘