圖像拼接(十三):OpenCV拼接多幅圖像(以中間圖像爲參考)

圖像拼接(七):OpenCV單應變換模型拼接多幅圖像 這篇博客中實現了用單應變換模型拼接多幅圖像,圖像拼接使用的OpenCV庫函數warpPerspective()

因爲這個函數只有在右側圖像變換到左側圖像時才能完整顯示,所以拼接過程選擇了以最左側圖像爲參考幀。由於累加誤差,最右側的圖像出現嚴重的變形。如下所示:

這裏寫圖片描述

在這篇博客中,我們以中間幅圖像爲參考圖像,實現多幅拼接。圖像數量爲4張,從左到右分別爲img4img4img3img3img2img2img1img1。以左側第2幅圖像,即img3img3爲參考圖像。

從右到左,img2img2img1img1的單應變形仍可直接使用warpPerspective(),那麼從左到右,img4img4img3img3怎麼辦呢?

解決的辦法是對img3img3添加一個向右距離爲img3.width的平移變換。這樣變形後的img4img4即可顯示在畫布中了。

這個平移變換矩陣爲:

Tx=[10img3.cols010001]Tx=\begin{bmatrix} 1&0&img3.cols\\0&1&0\\0&0&1\end{bmatrix}

img3img3 點座標設爲XX'img4img4點座標設爲XX,則他們之間的關係爲:
TxX=TxH43XTx*X'=Tx*H_{43}*X

所以img4img4img3img3變換後的圖像如下,注意img3img3的原點向右位移至中間。在之後的拼接中要考慮這一點。

img4img4->img3img3
這裏寫圖片描述

其它圖像之間的變換:

img2img2->img3img3
這裏寫圖片描述

img1img1->img3img3
這裏寫圖片描述

所有的4幅圖像的拼接結果爲:

這裏寫圖片描述

整體觀感相比圖像拼接(七):OpenCV單應變換模型拼接多幅圖像的結果提升不少,最右側圖像變形失真減輕。

代碼

#include"Homography.h"

int main()
{
	//從右向左升序
	string imgPath1 = "trees_003.jpg";
	string imgPath2 = "trees_002.jpg";
	string imgPath3 = "trees_001.jpg";
	string imgPath4 = "trees_000.jpg";

	Mat img1 = imread(imgPath1, CV_LOAD_IMAGE_GRAYSCALE);
	Mat img2 = imread(imgPath2, CV_LOAD_IMAGE_GRAYSCALE);
	Mat img3 = imread(imgPath3, CV_LOAD_IMAGE_GRAYSCALE);
	Mat img4 = imread(imgPath4, CV_LOAD_IMAGE_GRAYSCALE);

	Mat img1_color = imread(imgPath1, CV_LOAD_IMAGE_COLOR);
	Mat img2_color = imread(imgPath2, CV_LOAD_IMAGE_COLOR);
	Mat img3_color = imread(imgPath3, CV_LOAD_IMAGE_COLOR);
	Mat img4_color = imread(imgPath4, CV_LOAD_IMAGE_COLOR);

	Homography homo12(img1, img2);
	Homography homo23(img2, img3);
	Homography homo34(img3, img4);

	Mat h12 = homo12.getHomography();
	Mat h23 = homo23.getHomography();
	Mat h34 = homo34.getHomography();

	/*homo12.drawMatches();
	homo23.drawMatches();
	homo34.drawMatches();*/

	//以從左至右第2幅圖像爲參考,即img3
	Mat h13 = h23*h12;
	Mat h43 = h34.inv(DECOMP_LU);

	double scale_h13 = h13.at<double>(2, 2);
	h13 = h13 / scale_h13;
	double scale_h43 = h43.at<double>(2, 2);
	h43 = h43 / scale_h43;

	Mat warp1;
	warpPerspective(img1_color, warp1, h13, Size(img3.cols * 4, img3.rows));
	Mat warp2;
	warpPerspective(img2_color, warp2, h23, Size(img3.cols * 4, img3.rows));
	Mat warp4;
	Mat Tx = (Mat_<double>(3, 3) << 1, 0, img3.cols, 0, 1, 0, 0, 0, 1);
	warpPerspective(img4_color, warp4, Tx*h43, Size(img3.cols * 2, img3.rows));

	imshow("warp1", warp1);
	imshow("warp2", warp2);
	imshow("warp4", warp4);

	imwrite("warp1.jpg", warp1);
	imwrite("warp2.jpg", warp2);
	imwrite("warp4.jpg", warp4);

	int d = img3.cols * 2 / 5;
	int x2 = h23.at<double>(0, 2) + d;
	int x1 = x2 + h12.at<double>(0, 2);

	Mat canvas(img3.rows, img3.cols * 4, CV_8UC3);
	img3_color.copyTo(canvas(Range::all(), Range(img3.cols, img3.cols*2)));
	warp2(Range::all(), Range(x2, x1)).copyTo(canvas(Range::all(), Range(x2 + img3.cols, x1 + img3.cols)));
	warp1(Range::all(), Range(x1, x1+img3.cols)).copyTo(canvas(Range::all(), Range(x1 + img3.cols, x1+img3.cols*2)));
	warp4(Range::all(), Range(0, img3.cols)).copyTo(canvas(Range::all(), Range(0, img3.cols)));

	canvas(Range::all(), Range(x1 + img3.cols * 2, img3.cols * 4)) = Scalar::all(0);

	imwrite("canvas.jpg", canvas);
	imshow("canvas", canvas);

	waitKey(0);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章