zoukankan      html  css  js  c++  java
  • OpenCV之cvAddWeighted直接C语言实现版addWeighted,应对上下平滑融合拼接

    关于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不存在,效果明显。

  • 相关阅读:
    Idea创建Hibernate bean类和.xml文件
    Hibernate 一对多,多对多,多对一检索策略
    Hibernate 性能优化一对一关联映射
    HashSet 与TreeSet和LinkedHashSet的区别
    使用LinkedList模拟一个堆栈或者队列数据结构
    设计模式------工厂模式和抽象工厂模式
    悟透JavaScript
    JS产生随机数的几个用法!
    防盗链
    nigin配置安全:三个案例看Nginx配置安全(转)
  • 原文地址:https://www.cnblogs.com/xingrun/p/3507933.html
Copyright © 2011-2022 走看看