关于OpenCV中的cvAddWeighted的介绍可参见《opencv中的cvAddWeighted函数

cvAddWeighted有个问题,它只能实现两张图片的直接融合,往往产生明显的融合边界,这在我的图像操作应用中不能满足要求,特别是那讨厌的边界,所以我准备改进之。下面直接贴上我的addWeighted

/************************************************************************/
// Author:xingrun
// Description:addWeighted自动根据设定参数完成融合,
// 一开始src1,src2的权值分别为1,0,最后权值分别变成0,1,融合效果较好,无明显边界
// Time:2014-1-6 20:50:03
// Param:暂未实现通道为1的图片融合处理
/************************************************************************/
void addWeighted(const IplImage *src1,const IplImage* src2,IplImage* dst,double gama = 0)
{
CV_Assert(src1->depth == src2->depth);
CV_Assert(dst->depth == src2->depth);
CV_Assert(src1->nChannels == src2->nChannels);
CV_Assert(dst->nChannels == src2->nChannels);
CvRect rect1 = cvGetImageROI(src1);
CvRect rect2 = cvGetImageROI(src2);
CvRect dstRect = cvGetImageROI(dst);
CV_Assert(rect1.width == rect2.width && rect1.height == rect2.height);
CV_Assert(rect2.width == dstRect.width && rect2.height == dstRect.height);
int c,r,l;//c--Channel,r-Row,l-coLumn
int val,val1,val2;
double alpha = 0;
double beta = 0;
if(dst->nChannels==3)
{
for (c = 0; c < 3; c++)
for (r = dstRect.y; r < dstRect.y+dstRect.height; r++)
for (l = dstRect.x; l < dstRect.x+dstRect.width; l++)
{
val1 = ((uchar*)(src1->imageData + src1->widthStep*(rect1.y+r-dstRect.y)))[(rect1.x+l-dstRect.x)*3+c];
val2 = ((uchar*)(src2->imageData + src2->widthStep*(rect2.y+r-dstRect.y)))[(rect2.x+l-dstRect.x)*3+c];
alpha = (double)(dstRect.y+dstRect.height-1-r)/(dstRect.height-1);
beta = 1 -alpha;
val = (int)(val1*alpha + val2*beta + gama);
if(val<0)
val=0;
else if(val>255)
val=255;
((uchar*)(dst->imageData + dst->widthStep*r))[l*3+c] = (uchar)val;
}
}
else if(dst->nChannels==1)
{
//留待实现
}
}

上面代码中,参数alpha和beta是根据高度(或row)来自动调整的,所以我的这个函数适合上下融合图片,如果需要左右融合或者特定形状融合的话,可以增加传入参数来扩展功能。  

下面分别使用cvAddWeighted和addWeighted对比一下上下融合的结果。

源图片:

21.jpg

22.jpg

在MFC中使用以下代码:

void CMytestDlg::OnBnClickedBtnAddWeightedComp()
{
IplImage *src1 = cvLoadImage("dataset\\21.jpg");
IplImage *src2 = cvLoadImage("dataset\\22.jpg");
IplImage *dst_cvAddWeighted = NULL;
IplImage *dst_addWeighted = NULL;
IplImage *weightImg = NULL;
if (src1 && src2)
{
dst_cvAddWeighted = cvCreateImage(cvSize(src1->width,src1->height/2+src2->height),src1->depth,src1->nChannels);
dst_addWeighted = cvCreateImage(cvSize(src1->width,src1->height/2+src2->height),src1->depth,src1->nChannels);
weightImg = cvCreateImage(cvSize(src1->width,src1->height/2),src1->depth,src1->nChannels);
if (dst_cvAddWeighted && dst_addWeighted)
{
cvNamedWindow("cvAddWeighted");
cvNamedWindow("addWeighted");
//融合中间部分
cvSetImageROI(src1,cvRect(0,src1->height/2,src1->width,src1->height/2));
cvSetImageROI(src2,cvRect(0,0,src1->width,src1->height/2));
cvSetImageROI(dst_cvAddWeighted,cvRect(0,src1->height/2,src1->width,src1->height/2));
cvSetImageROI(dst_addWeighted,cvRect(0,src1->height/2,src1->width,src1->height/2));
cvAddWeighted(src1,0.5,src2,0.5,0,dst_cvAddWeighted);
addWeighted(src1,src2,dst_addWeighted);
cvResetImageROI(src1);
cvResetImageROI(src2);
cvResetImageROI(dst_cvAddWeighted);
cvResetImageROI(dst_addWeighted);
//拷贝上部分
cvSetImageROI(src1,cvRect(0,0,src1->width,src1->height/2));
cvSetImageROI(dst_cvAddWeighted,cvRect(0,0,src1->width,src1->height/2));
cvSetImageROI(dst_addWeighted,cvRect(0,0,src1->width,src1->height/2));
cvCopy(src1,dst_cvAddWeighted);
cvCopy(src1,dst_addWeighted);
cvResetImageROI(src1);
cvResetImageROI(dst_cvAddWeighted);
cvResetImageROI(dst_addWeighted);
//拷贝下面部分
cvSetImageROI(src2,cvRect(0,src1->height/2,src1->width,src2->height - src1->height/2));
cvSetImageROI(dst_cvAddWeighted,cvRect(0,src1->height,src1->width,src2->height - src1->height/2));
cvSetImageROI(dst_addWeighted,cvRect(0,src1->height,src1->width,src2->height - src1->height/2));
cvCopy(src2,dst_cvAddWeighted);
cvCopy(src2,dst_addWeighted);
cvResetImageROI(src2);
cvResetImageROI(dst_cvAddWeighted);
cvResetImageROI(dst_addWeighted);
//显示
cvShowImage("cvAddWeighted",dst_cvAddWeighted);
cvWaitKey(10);
cvShowImage("addWeighted",dst_addWeighted);
cvWaitKey(10);
//保存
cvSaveImage("cvAddWeighted.jpg",dst_cvAddWeighted);
cvSaveImage("addWeighted.jpg",dst_addWeighted);
//释放内存
cvReleaseImage(&dst_cvAddWeighted);
dst_cvAddWeighted = NULL;
cvReleaseImage(&dst_addWeighted);
dst_addWeighted = NULL;
//cvDestroyAllWindows();
}
cvReleaseImage(&src1);
src1 = NULL;
cvReleaseImage(&src2);
src2 = NULL;
}
}

得到结果:

cvAddWeighted.jpg

addWeighted.jpg

细看结果,可发现cvAddWeighted.jpg中有明显的拼接痕迹,而在addWeighted.jpg不存在,效果明显。

OpenCV之cvAddWeighted直接C语言实现版addWeighted,应对上下平滑融合拼接的更多相关文章

  1. 基于opencv将视频转化为字符串Java版

    基于opencv将视频转化为字符串Java版 opencv java  先上一个效果图吧 首先,弄清一下原理 我们要将视频转化为字符画,那么就需要获取画面的每一帧,也就是每一张图片,然后将图片进行转化 ...

  2. UnifyRemoteManager-多国语言绿色版v1.3-20200315,统一远程连接自动登录软件,欢迎测试

    UnifyRemoteManager-多国语言绿色版v1.3-20200315,统一远程连接自动登录软件,欢迎测试 下载参考: 百度网盘:https://pan.baidu.com/s/15g-oXT ...

  3. Vnc自动登录器-多国语言绿色版

    推荐:介绍一个VNC连接工具:iis7服务器管理工具.IIs7服务器管理工具可以批量连接并管理VNC服务器.作为服务器集成管理器,它最优秀的功能就是批量管理windows与linux系统服务器.vps ...

  4. DM8168 OpenCV尝试与评估(编译ARM版OpenCV)

     交叉编译opencv2.3.1,并在DM8168 cortex A8中执行图像处理. 开发环境: PC:ubuntu12.04LTS.Intel Core 2 Duo CPU  E7200@2. ...

  5. Vnc自动登录器(VncManager)v1.3-多国语言绿色版-Release1-20190215

    Vnc自动登录器 v1.3 (20190215) By: ybmj@vip.163.com , https://www.cnblogs.com/ybmj/ 下载地址:http://bbs.wuyou. ...

  6. go语言 安装版 Windows7安装截图

    这个比较简单的 一路next. 查看:解压版安装go. //http://www.cnblogs.com/osfipin/

  7. c语言 字符版 简易2048

    花了两个多小时,用最蠢的方法写的……最简陋版…… 还不确定这么写逻辑对不对…… #include <iostream> #include <cstdio> #include & ...

  8. Codeblocks + opencv + Cmake + minGW 环境搭建(一劳永逸版)

    应工作开发需要,今天搭建一个codeblocks的C++开发环境,需要配置opencv2.4.4的API协同开发. 1.为了避免不必要的配置编译器,下载codeblocks16.1带mingw编译器版 ...

  9. C++程序设计与语言(特别版) -- 导论

    前言 刚开始的时候只学习了一些简单的C++语法知识,当C++不再是一门学科需要考试的时候,就想重新把C++捡回来,希望从中学习到一点思想性的东西而不再是一些语法性的东西. 下面都是一些参考书目的摘抄或 ...

随机推荐

  1. pig 入门教程(1)

    出处:http://www.codelast.com/ 本文可以让刚接触pig的人对一些基础概念有个初步的了解. 本文大概是互联网上第一篇公开发表的且涵盖大量实际例子的Apache Pig中文教程(由 ...

  2. 15、Linux 文件属性和测试( chgrp,chown,chmod和-e -f -d -s

    一.更改文件属性 1.chgrp:更改文件属组 语法: chgrp [-R] 属组名文件名 参数选项 -R:递归更改文件属组,就是在更改某个目录文件的属组时,如果加上-R的参数,那么该目录下的所有文件 ...

  3. tensorflow session会话控制

    import tensorflow as tf # create two matrixes matrix1 = tf.constant([[3,3]]) matrix2 = tf.constant([ ...

  4. opencv头文件

    转载自:http://blog.csdn.net/aaron121211/article/details/51526901 1. .hpp文件是.h和.cpp文件在一起的2. #include < ...

  5. Ubuntu 与 Windows 共享文件夹

    1. Ubuntu关机后 编辑虚拟机设置->option->共享文件夹->添加->确定 完成! 2.共享文件夹后在/mnt/hgfs/文件夹下无法看到共享的文件夹: 解决方法: ...

  6. java线程并发工具类CyclicBarrier、CountDownLatch及Semaphore

    一.CyclicBarrier   (原文链接:http://www.studyshare.cn/blog-front/blog/index ) 1.定义 CyclicBarrier是线程并发工具类之 ...

  7. [Emacs] Emacs使用介绍

    详细,可参考该文档(转载):Emacs 快速指南 - 原生中文手册 C-x C-c 关闭Emacs会话 C-v/M-v 向前/后翻页 C-n/C-p 光标向下/上移一行 C-f/C-b 光标向前/后移 ...

  8. 洛谷P2580(trie)

    第一行一个整数 n,表示班上人数.接下来 n 行,每行一个字符串表示其名字(互不相同,且只含小写字母,长度不超过 50).第 n+2 行一个整数 m,表示教练报的名字.接下来 m 行,每行一个字符串表 ...

  9. 安装篇:MySQL系列之一

    环境:CentOS6.9系统安装MariaDB-10.2.15 一.yum包管理器安装MariaDB-server ​ 1)配置yum源(MariaDB官方源) [root@centos6 ~]# v ...

  10. POJ1032 Parliament

    题目来源:http://poj.org/problem?id=1032 题目大意:给定一个正整数N(5<=N<=1000),将N拆为若干个不同的数使得它们的乘积最大(找到一组互不相等,和为 ...