上回文章写道opencv_contrib安装,为什么安装呢?为了使用SIFT函数。为什么使用SIFT函数?为了进行特征点检测。为什么进行特征点检测?为了图像拼接。所以呢,这段时间我在学习全景拼接

全景拼接可以分为两张图像拼接张图像拼接(大于两张)。因为每幅图像是相机在不同角度下拍摄得到的,它们并不在同一个投影平面上,如果对重叠部分直接进行拼接,则会破坏实际场景的视觉一致性。所以对于多张图像我们需要在拼接之前,对图像进行投影变换,即对图像进行扭曲变形。

两张图像拼接:可以采用单应性矩阵(cv:: findHomography)。例如以左图为基础将右图进行单应性变换,与左图拼接,这样一来右图就会因为单应性变换分辨率降低变得模糊(详见:运行结果(由于图像上传大小限制,效果不明显))。多张图并不是不可以使用单应性,而是图像越多,拼接扭曲越厉害,惨不忍睹啊。

【开发环境】:

软件版本:OpenCV-4.1.1、opencv_contrib-4.1.1、Visual Studio 2015

操作系统:Win10

【源代码】:

#include <opencv2\opencv.hpp>
#include <vector>
#include <opencv2\xfeatures2d.hpp>
#include <iostream>  
using namespace cv;
using namespace std;

int main()
{
	Mat img1, img2, img_gray1, img_gray2;
	Mat  L_Rmatcher;
	Mat left_view, result;
	img1 = imread("C:\\Users\\Administrator\\Desktop\\p2.jpg", 1);  //右图
	img2 = imread("C:\\Users\\Administrator\\Desktop\\p1.jpg", 1);  //左图
	vector<Mat> pic{ img1,img2 };
 
	//灰度图
	cvtColor(img1, img_gray1, COLOR_BGR2GRAY);
	cvtColor(img2, img_gray2, COLOR_BGR2GRAY);

	//SIFT特征检测器,计算关键点
	Ptr<Feature2D> sift = xfeatures2d::SIFT::create();

	//检测关键点
	vector<KeyPoint> keypoints1, keypoints2;
	sift->detect(img_gray1, keypoints1);
	sift->detect(img_gray2, keypoints2);

	//计算描述子
	Mat descriptors1, descriptors2;
	sift->compute(img_gray1, keypoints1, descriptors1);
	sift->compute(img_gray2, keypoints2, descriptors2);

	//快速近似最邻近 匹配方法寻找匹配点
	FlannBasedMatcher matcher;
	vector<vector<DMatch> > matchePoints;
	vector<DMatch> GoodMatchePoints;

	vector<Mat> train_desc(1, descriptors1);
	matcher.add(train_desc); //添加训练描述符

	matcher.knnMatch(descriptors2, matchePoints, 2);
	cout << "total match points: " << matchePoints.size() << endl;

	// Lowe's algorithm,获取优秀匹配点
	for (int i = 0; i < matchePoints.size(); i++)
	{
		if (matchePoints[i][0].distance < 0.4 * matchePoints[i][1].distance)   //atio=0. 4:对于准确度要求高的匹配; ratio = 0. 6:对于匹配点数目要求比较多的匹配;   ratio = 0. 5:一般情况下。
		{
			GoodMatchePoints.push_back(matchePoints[i][0]);
		}
	}

	//显示关键点
	drawKeypoints(img1, keypoints1, descriptors1, cv::Scalar::all(-1));
	drawKeypoints(img2, keypoints2, descriptors2, cv::Scalar::all(-1));

	//关键点匹配
	drawMatches(img2, keypoints2, img1, keypoints1, GoodMatchePoints, L_Rmatcher, cv::Scalar::all(-1), cv::Scalar(0, 0, 255));

	vector<Point2f>kp1, kp2;
	for (int i = 0; i < GoodMatchePoints.size(); i++)
	{
		kp2.push_back(keypoints2[GoodMatchePoints[i].queryIdx].pt);
		kp1.push_back(keypoints1[GoodMatchePoints[i].trainIdx].pt);
	}
	Mat homography = findHomography(kp1, kp2, cv::noArray(), RANSAC);
	cout << "变换矩阵为:\n" << homography << endl << endl;

	//歪曲右图到左图
	// 右边的图像经过矩阵H转换到stitchedImage中对应的位置
	warpPerspective(img1, result, homography, Size(img2.cols + img1.cols, img2.rows));
	//warpPerspective(输入图像,输出图像,3*3矩阵,最终图像尺寸,)
	imshow("左图视角的有图", result);
	//赋值右图到整幅图像的前半部分
	//把左边的图像放进来
	Mat half(result, Rect(0, 0, img2.cols, img2.rows));
	//复制图2到图1的ROI区域
	img2.copyTo(half);

	imshow("左图-img2", descriptors2);
	imshow("右图-img1", descriptors1);
	imshow("匹配线", L_Rmatcher);
	imshow("Result", result);

	cv::imwrite("Result.jpg", result);

	waitKey(0);
	return 0;
}

【运行结果】

Python opencv如何将两张大小不一样的图片拼在一起 opencv 拼接两张图片_Scala

Python opencv如何将两张大小不一样的图片拼在一起 opencv 拼接两张图片_全景拼接_02

Python opencv如何将两张大小不一样的图片拼在一起 opencv 拼接两张图片_图像拼接_03

You believe in fate?
你相信命运吗?