图像融合之金字塔


这篇文章呢,主要是看了上篇金字塔在图像分割的应用之后,知道了金字塔的主要应用还在于图像融合,所以就又看了相关的内容,


用金字塔进行图像融合的主要步骤如下:

1,有两张原图像,还有一张模板图(用来确定用左边图像的哪部分,右边图像的哪部分来组合成最终的结果);

	Mat_<Vec3f> left,right;
	Mat_<float> mask;

2,有了原图之后就要进行分割求金字塔图像了

vector<Mat_<Vec3f>> leftpyr,rightpyr,maskpyr;
不过leftpyr和right保存的是拉普拉斯金字塔,mask保存的是高斯金字塔,我们知道图下采样之后是DOG,图减去DOG上采样之后是LOG,所以如果对最顶层的图不断上采样并加上LOG,最终会得到原图下采样的结果。

对左右原图进行拉普拉斯金字塔就是为了能够获得每层的细节信息,并且使用mask高斯金字塔每层对应的模板 进行融合,这就相当于得到了一系列的LOG,那对这些LOG不断的上采样就得到了最后的逼近真实的融合图。

另外一个原因就是在采样的过程中有模糊处理,所以融合的边缘不会是突兀的,而是很自然的呈现。

3, 分别得到了两图的LOG之后,就要通过maskpyr得到融合之后的LOG了。

vector<Mat_<Vec3f>> resultpyr;
4,然后就是不断的上采样这个pyr,得到最后的结果图。

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;


class pyr_blend{

private:
	Mat_<Vec3f> left,right;
	Mat_<float> mask;
	int level;
	vector<Mat_<Vec3f>> leftpyr,rightpyr,maskpyr;
	vector<Mat_<Vec3f>> resultpyr;

public:
	void calclogpyr(const Mat& img,vector<Mat_<Vec3f>> &logpyr){
		logpyr.clear();
		Mat currentimg = img;
		Mat down,up,logimg;
		for(int k=0;k<level;k++){
			pyrDown(currentimg,down);
			pyrUp(down,up,currentimg.size());
			logimg = currentimg - up;
			logpyr.push_back(logimg);
			currentimg = down;
		}
		logpyr.push_back(currentimg);

	}
	void calcdogpyr(){
		assert(leftpyr.size()>0);
		maskpyr.clear();

		Mat mask_3;
		cvtColor(mask,mask_3,CV_GRAY2BGR);
		maskpyr.push_back(mask_3);

		Mat currentimg = mask;
		for (int k=1;k<level+1;k++){
			Mat down;
			pyrDown(currentimg,down,leftpyr[k].size());
			
			cvtColor(down,mask_3,CV_GRAY2BGR);
			maskpyr.push_back(mask_3);
			currentimg = down;
		}

	}
	void calcpyr(){
		calclogpyr(left,leftpyr);
		calclogpyr(right,rightpyr);
		calcdogpyr();
	}

	void calcblend(){
		Mat ll ,rr;
		Mat_<Vec3f> blend;

		for (int k=0;k<level;k++){
			ll = leftpyr[k].mul(maskpyr[k]);
			rr = rightpyr[k].mul(Scalar(1.0,1.0,1.0) - maskpyr[k]);
			blend = ll + rr;
			resultpyr.push_back(blend);
		}
		
		Mat resulthighest = leftpyr.back().mul(maskpyr.back()) + rightpyr.back().mul(Scalar(1.0,1.0,1.0) - maskpyr.back());
		resultpyr.push_back(resulthighest);



	}

	
	pyr_blend(const Mat_<Vec3f>& _left,const Mat_<Vec3f>& _right,const Mat_<float>& _mask,const int _level):left(_left),right(_right),mask(_mask),level(_level){
		assert(_left.size == _right.size);
		assert(_left.size == _mask.size);
		calcpyr();
		calcblend();
		
	}
	Mat_<Vec3f> calcresult(){
		Mat current,up;
		current = resultpyr.back();

		for (int k=level-1;k>=0;k--){
			pyrUp(current,up,resultpyr[k].size());
			current = up + resultpyr[k];
		}

		return current;
	}


};
int main(){

	Mat l8u = imread("apple.jpg");
	Mat r8u = imread("orange.jpg");

	Mat_<Vec3f> l,r;
	l8u.convertTo(l,CV_32F,1.0/255.0);
	r8u.convertTo(r,CV_32F,1.0/255.0);

	Mat_<float> mask(l.rows,l.cols,0.0);
	mask(Range::all(),Range(0,mask.cols/2))=1.0;


	pyr_blend pyr_blend_two(l,r,mask,4);
	Mat_<Vec3f> result = pyr_blend_two.calcresult();

	imshow("l",l);
	imshow("r",r);
	imshow("result",result);
	waitKey(0);
	return 0;
}

这里跟美女学霸学了几个很好的细节http://blog.csdn.net/abcjennifer/article/details/7628655   

1,一个就是对mask的处理,因为我们知道通常的mask都是二值图像,所以这里把mask转换成跟原图一样的类型,是为了能够在计算左右两图的权重的时候直接使用而计算简便,

2,就是C++再一次的佩服啊,果然很好很强大啊。O(∩_∩)O哈哈~,fighting哦,向偶像学习。


结果如图:




  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值