圖像融合之金字塔


這篇文章呢,主要是看了上篇金字塔在圖像分割的應用之後,知道了金字塔的主要應用還在於圖像融合,所以就又看了相關的內容,


用金字塔進行圖像融合的主要步驟如下:

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哦,向偶像學習。


結果如圖:




發佈了33 篇原創文章 · 獲贊 9 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章