收入囊中

  • 了解线性混合
  • 会使用addWeighted进行任意混合
葵花宝典
Computer Vision:Algorithm and Application(以后我简称CVAA)的3.1.3提到: C=(1−α)B+αF. 
B是背景色,F是前景色,这是一个万能公式(其实越万能的公式使用起来越不方便,这个公式貌似什么都没说)
CVAA的这一小节是讲抠图与合成,抠图难度比较大
初识API

下面我进入Sample文件夹下的ImgProc子目录,首先研究下AddingImages.cpp,下面是源代码

#include "opencv2/highgui/highgui.hpp"
#include <iostream>using namespace cv;int main( void )
{double alpha = 0.5; double beta; double input;Mat src1, src2, dst;/// Ask the user enter alphastd::cout<<" Simple Linear Blender "<<std::endl;std::cout<<"-----------------------"<<std::endl;std::cout<<"* Enter alpha [0-1]: ";std::cin>>input;// We use the alpha provided by the user iff it is between 0 and 1if( alpha >= 0 && alpha <= 1 ){ alpha = input; }/// Read image ( same size, same type )src1 = imread("../images/LinuxLogo.jpg");src2 = imread("../images/WindowsLogo.jpg");if( !src1.data ) { std::cout<< "Error loading src1"<<std::endl; return -1; }if( !src2.data ) { std::cout<< "Error loading src2"<<std::endl; return -1; }/// Create WindowsnamedWindow("Linear Blend", 1);beta = ( 1.0 - alpha );addWeighted( src1, alpha, src2, beta, 0.0, dst);imshow( "Linear Blend", dst );waitKey(0);return 0;
}

代码很简单,第一幅图像占的比例是alpha,第二幅是1-alpha

dst = src1[I]*alpha+ src2[I]*beta + gamma;

下面我们看下addWeighted的源代码,在arithm.cpp中

void cv::addWeighted( InputArray src1, double alpha, InputArray src2,double beta, double gamma, OutputArray dst, int dtype )
{double scalars[] = {alpha, beta, gamma};arithm_op(src1, src2, dst, noArray(), dtype, getAddWeightedTab(), true, scalars);
}
  • 第一个参数,InputArray类型的src1,表示需要加权的第一个数组,常常填一个Mat。
  • 第二个参数,alpha,表示第一个数组的权重
  • 第三个参数,src2,表示第二个数组,它需要和第一个数组拥有相同的尺寸和通道数。
  • 第四个参数,beta,表示第二个数组的权重值。
  • 第五个参数,dst,输出的数组,它和输入的两个数组拥有相同的尺寸和通道数。
  • 第六个参数,gamma,一个加到权重总和上的标量值。看下面的式子自然会理解。
  • 第七个参数,dtype,输出阵列的可选深度,有默认值-1。;当两个输入数组具有相同的深度时,这个参数设置为-1(默认值),即等同于src1.depth()。
下面我们要仔细来看看arithm_op这个函数了
static void arithm_op(InputArray _src1, InputArray _src2, OutputArray _dst,InputArray _mask, int dtype, BinaryFunc* tab, bool muldiv=false, void* usrdata=0)

我们发现 addWeighted中传了一个noArray(),就是没有掩码了,还有个tab参数,这是什么呢,看名字好像是一个函数指针?往上看,我发现了

static BinaryFunc* getAddWeightedTab()
{static BinaryFunc addWeightedTab[] ={(BinaryFunc)GET_OPTIMIZED(addWeighted8u), (BinaryFunc)GET_OPTIMIZED(addWeighted8s), (BinaryFunc)GET_OPTIMIZED(addWeighted16u),(BinaryFunc)GET_OPTIMIZED(addWeighted16s), (BinaryFunc)GET_OPTIMIZED(addWeighted32s), (BinaryFunc)addWeighted32f,(BinaryFunc)addWeighted64f, 0};return addWeightedTab;
}

看样子这些事函数指针的数组,那么GET_OPTIMIZED又是什么呢

#define GET_OPTIMIZED(func) (func)

很多定义都来不及细看,下次有需要再细细研究,这些addWeighted8u等函数都在同个cpp下面定义了,我们的tab就是一系列函数指针。在arithm_op有一行函数是这样的,

BinaryFunc func = tab[CV_MAT_DEPTH(wtype)];

根据数据类型拿到相应的加权函数

arithm_op中的函数大多都是数据类型,掩码的这种判断,主要操作都是在这个func里进行的,而里面又调用了addWeighted_这个模版函数
template<typename T, typename WT> static void
addWeighted_( const T* src1, size_t step1, const T* src2, size_t step2,T* dst, size_t step, Size size, void* _scalars )
{const double* scalars = (const double*)_scalars;WT alpha = (WT)scalars[0], beta = (WT)scalars[1], gamma = (WT)scalars[2];step1 /= sizeof(src1[0]);step2 /= sizeof(src2[0]);step /= sizeof(dst[0]);for( ; size.height--; src1 += step1, src2 += step2, dst += step ){int x = 0;#if CV_ENABLE_UNROLLEDfor( ; x <= size.width - 4; x += 4 ){T t0 = saturate_cast<T>(src1[x]*alpha + src2[x]*beta + gamma);T t1 = saturate_cast<T>(src1[x+1]*alpha + src2[x+1]*beta + gamma);dst[x] = t0; dst[x+1] = t1;t0 = saturate_cast<T>(src1[x+2]*alpha + src2[x+2]*beta + gamma);t1 = saturate_cast<T>(src1[x+3]*alpha + src2[x+3]*beta + gamma);dst[x+2] = t0; dst[x+3] = t1;}#endiffor( ; x < size.width; x++ )dst[x] = saturate_cast<T>(src1[x]*alpha + src2[x]*beta + gamma);}
}

这个函数就是我们的算法所在,可以很清晰看到

dst = src1[I]*alpha+ src2[I]*beta + gamma;

举一反三

addWeighted函数要求我们两个矩阵大小必须相同,那如果我想要不一样怎么办?

其实非常非常简单,要知道在OpenCV2中,只有clone和copyto两个函数才是复制数据的,其他的都是只是新建Mat的Header(包括行列等信息),数据却还是指向原来的地方,ref count增加了1次.

因此,只要我们能取到矩阵的一部分,进行混合不就可以了么。

假设src1是1000*1000,而src是100*100的小人头,我们想把小人头和src1的(500,500)坐标处进行混合

方法1:blendimg = src1(Range(500, 500 + src2.rows), Range(500, 500 + src2.cols));

方法2:blendimg = src1(Rect(500, 500, src2.cols, src2.rows));

再使用addWeighted函数即可

计算机视觉讨论群162501053
转载请注明:http://blog.csdn.net/abcd1992719g

OpenCV2马拉松第4圈——图片混合相关推荐

  1. OpenCV2马拉松第2圈——读写图片

    收入囊中 用imread读取图片 用nameWindow和imshow展示图片 cvtColor彩色图像灰度化 imwrite写图像 Luv色彩空间转换 初识API 图像读取接口 image = im ...

  2. OpenCV2马拉松第22圈——Hough变换直线检測原理与实现

    计算机视觉讨论群162501053 转载请注明:http://blog.csdn.net/abcd1992719g/article/details/27220445 收入囊中 Hough变换 概率Ho ...

  3. OpenCV2马拉松第1圈——纵观全局

    前话 我会结合计算机视觉算法与应用,冈萨雷斯图像处理,以及CVPR,ICCV等论文深入原理,不仅会用OpenCV,还要懂原理. Version1和Version2的主要差别 OpenCV2和OpenC ...

  4. 【s操作】轻松优雅的保存微信群图片和朋友圈图片

    上次聊了一下锤子手机的使用体验:锤子手机使用2年,聊聊锤子手机,坚果手机功能使用体验,主要介绍了几个软件上的使用技巧.最近几年越来越重视软件的使用体验,主要因为软件更亲民,硬件上从835又到845又到 ...

  5. Android 视频图片 轮播,详解android 视频图片混合轮播实现

    循环添加视频view  图片view for (int i = 0 ;i if (beansarraylist.get(i).gettype()==1){ videoplayer = new nice ...

  6. 模仿微信朋友圈 图片浏览 js javascript 支持图片预览,滑动切换,双指缩放,图片缓存

    模仿微信朋友圈 图片浏览 js javascript 支持图片预览,滑动切换,双指缩放,图片缓存 2017年08月10日 12:11:38 阅读数:2311 previewImage-mobile 仿 ...

  7. 微信小程序实现朋友圈图片展现形式

    朋友圈图片展现形式: 1.一张宽图:宽度100%,高度自适应 2.一张长图:高度全部展示,有最大高度,宽度自适应 3.多张图片:除去一张,两张和四张的时候是一排两张,其他都是一排三张,依次向后累加 4 ...

  8. PC微信自动保存朋友圈图片

    微信3.3版本开始支持查看朋友圈,通过微信接口可以自动保存朋友圈图片,下面看一下接口推送的朋友圈数据的JSON结构: 朋友圈推送的接口API为 1012,默认登陆时会更新10条记录,微信每间隔5分钟也 ...

  9. ImageMagick将多张图片拼接成一张图片_高逼格九宫格图片,2020年朋友圈图片,自己做不求人...

    元旦快乐!! 2019年过去了,2020年你的计划里不知道还有没有2018年的待完成事项呢?(拖延症的话,经常是拖着拖着就没了吧= =)无论如何在许下愿望列下清单的那一刻我们也是斗志满分阿! 今天给大 ...

最新文章

  1. opencv滤波美颜
  2. 《时间简史》(评论一)(转载)
  3. ABAddressBookSave关于保存到通讯录失败的问题
  4. 使用junit-drools进行JBoss Drools单元测试
  5. (2,1,3)卷积码与一种QC-LDPC码的译码性能对比
  6. #Pragma Pack(n)与内存分配 pragma pack(push,1)与#pragma pack(1)的区别
  7. “七大属性加持,三个全新升级组件”这个高性能利器有点厉害
  8. 用 :focus-within 实现纯 CSS 下拉框组件
  9. 如何使用gcc编译器
  10. ANSYS静力学分析的主要操作步骤
  11. 查看elasticserc版本_Elasticsearch版本和客户端介绍
  12. win10输入法看不见选字框_Win10更新后微软拼音输入法没有选字框怎么办?
  13. 项目协作管理平台-teambition和tapd--深度体验
  14. mysql 异常码1903_Mysql 异常。 寻求帮助
  15. USACO-Preface Numbering
  16. c语言程序设计在哪讲,《C语言程序设计》讲.doc
  17. VUE项目报错Error Cannot find module ‘webpacklibRuleSet‘_解决
  18. 曾经爱过你试听,歌曲曾经爱过你mp3下载,歌词 - 郑源
  19. pthread_cancel引起程序段错误
  20. PPT结束语有哪些?

热门文章

  1. springboot + EasyExcel 实现操作Excel文件
  2. H5案例课—5点连线画一个爱-岑远科-专题视频课程
  3. 七年级计算机教室管理员解说词,完美教室解说词
  4. Vue项目打包后不能正常显示页面
  5. 【论文笔记】ICNet:用于无监督医学图像配准的逆一致性模型
  6. 怎么用计算机属性打开文件,电脑桌面上的文件打开的时候都是显示属性没法打开 了解原因所在...
  7. 【Linux】Mysql忘记密码怎么办?
  8. 炒股Java_炒股Java
  9. 图像锐化 边缘检测的一些基础知识
  10. Java程序的运行过程(执行流程)分析