欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

获取两幅图重叠区域

程序员文章站 2022-05-20 22:30:51
...
#include <iostream>
#include "opencv2/opencv.hpp"
#include "opencv2/xfeatures2d.hpp"

using namespace std;
typedef struct
{
	cv::Point2f left_top;
	cv::Point2f left_bottom;
	cv::Point2f right_top;
	cv::Point2f right_bottom;
}four_corners_t;

void CalcCorners(const cv::Mat& H, const cv::Mat& src, four_corners_t& corners)
{
	double v2[] = { 0, 0, 1 };//左上角
	double v1[3];//变换后的坐标值
	cv::Mat V2 = cv::Mat(3, 1, CV_64FC1, v2);  //列向量
	cv::Mat V1 = cv::Mat(3, 1, CV_64FC1, v1);  //列向量

	V1 = H * V2;
	//左上角(0,0,1)
	//cout << "V2: " << V2 << endl;
	//cout << "V1: " << V1 << endl;
	corners.left_top.x = v1[0] / v1[2];
	corners.left_top.y = v1[1] / v1[2];

	//左下角(0,src.rows,1)
	v2[0] = 0;
	v2[1] = src.rows;
	v2[2] = 1;
	V2 = cv::Mat(3, 1, CV_64FC1, v2);  //列向量
	V1 = cv::Mat(3, 1, CV_64FC1, v1);  //列向量
	V1 = H * V2;
	corners.left_bottom.x = v1[0] / v1[2];
	corners.left_bottom.y = v1[1] / v1[2];

	//右上角(src.cols,0,1)
	v2[0] = src.cols;
	v2[1] = 0;
	v2[2] = 1;
	V2 = cv::Mat(3, 1, CV_64FC1, v2);  //列向量
	V1 = cv::Mat(3, 1, CV_64FC1, v1);  //列向量
	V1 = H * V2;
	corners.right_top.x = v1[0] / v1[2];
	corners.right_top.y = v1[1] / v1[2];

	//右下角(src.cols,src.rows,1)
	v2[0] = src.cols;
	v2[1] = src.rows;
	v2[2] = 1;
	V2 = cv::Mat(3, 1, CV_64FC1, v2);  //列向量
	V1 = cv::Mat(3, 1, CV_64FC1, v1);  //列向量
	V1 = H * V2;
	corners.right_bottom.x = v1[0] / v1[2];
	corners.right_bottom.y = v1[1] / v1[2];

}

bool ImageOverlap(cv::Mat &img1, cv::Mat &img2, cv::Mat &dst, std::vector<cv::Point>& vPoint1, std::vector<cv::Point>& vPoint2)
{
	cv::Mat g1(img1, cv::Rect(0, 0, img1.cols, img1.rows));
	cv::Mat g2(img2, cv::Rect(0, 0, img2.cols, img2.rows));

	cv::cvtColor(g1, g1, CV_BGR2GRAY);
	cv::cvtColor(g2, g2, CV_BGR2GRAY);

	std::vector<cv::KeyPoint> keypoints_roi, keypoints_img;  /* keypoints found using SIFT */
	cv::Mat descriptor_roi, descriptor_img;                  /* Descriptors for SIFT */
	cv::FlannBasedMatcher matcher;                           /* FLANN based matcher to match keypoints */
	std::vector<cv::DMatch> matches, good_matches;

	cv::Ptr<cv::Feature2D> f2d = cv::xfeatures2d::SIFT::create();
	f2d->detect(g1, keypoints_roi);                          /* get keypoints of ROI image */
	f2d->detect(g2, keypoints_img);                          /* get keypoints of the image */
	f2d->compute(g1, keypoints_roi, descriptor_roi);
	f2d->compute(g2, keypoints_img, descriptor_img);
	matcher.match(descriptor_roi, descriptor_img, matches);

	double max_dist = 0; double min_dist = 1000;
	int i, dist = 80;

	//-- Quick calculation of max and min distances between keypoints
	for (int i = 0; i < descriptor_roi.rows; i++)
	{
		double dist = matches[i].distance;
		if (dist < min_dist) min_dist = dist;
		if (dist > max_dist) max_dist = dist;
	}

	for (i = 0; i < descriptor_roi.rows; i++)
	{
		if (matches[i].distance < 3 * min_dist)
		{
			good_matches.push_back(matches[i]);
		}
	}

	/*if (good_matches.size() < 10) {
		return false;
	}*/

	//cout << "matched keypoints numbers in right image:"<<good_matches.size() << endl;
	/* Draw matched keypoints */
	/*cv::Mat img_matches;
	drawMatches(img1, keypoints_roi, img2, keypoints_img,
		good_matches, img_matches, cv::Scalar::all(-1),
		cv::Scalar::all(-1), vector<char>(),
		cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
	imshow("matches", img_matches);
	cv::waitKey(1);*/

	vector<cv::Point2f> keypoints1, keypoints2;
	for (i = 0; i<good_matches.size(); i++)
	{
		keypoints1.push_back(keypoints_img[good_matches[i].trainIdx].pt);
		keypoints2.push_back(keypoints_roi[good_matches[i].queryIdx].pt);
	}

	//计算单应矩阵
	cv::Mat H = findHomography(keypoints1, keypoints2, CV_RANSAC);
	cv::Mat H2 = findHomography(keypoints2, keypoints1, CV_RANSAC);

	// 获取图一的交叠区域
	four_corners_t corners_1;
	four_corners_t corners_2;
	CalcCorners(H, img1, corners_1);
	CalcCorners(H2, img2, corners_2);

	// 返回显示
	int mRows = img2.rows;
	if (img1.rows> img2.rows) {
		mRows = img1.rows;
	}
	dst = cv::Mat::zeros(mRows, MAX(corners_1.right_top.x, corners_1.right_bottom.x), CV_8UC3);
	warpPerspective(img2, dst, H, cv::Size(MAX(corners_1.right_top.x, corners_1.right_bottom.x), mRows));
	cv::Mat half(dst, cv::Rect(0, 0, img1.cols, img1.rows));
	img1.copyTo(half);

	vPoint1.push_back(cv::Point((int)corners_1.left_top.x, (int)corners_1.left_top.y));
	vPoint1.push_back(cv::Point((int)corners_1.right_top.x, (int)corners_1.right_top.y));
	vPoint1.push_back(cv::Point((int)corners_1.right_bottom.x, (int)corners_1.right_bottom.y));
	vPoint1.push_back(cv::Point((int)corners_1.left_bottom.x, (int)corners_1.left_bottom.y));

	vPoint2.push_back(cv::Point((int)corners_2.left_top.x, (int)corners_2.left_top.y));
	vPoint2.push_back(cv::Point((int)corners_2.right_top.x, (int)corners_2.right_top.y));
	vPoint2.push_back(cv::Point((int)corners_2.right_bottom.x, (int)corners_2.right_bottom.y));
	vPoint2.push_back(cv::Point((int)corners_2.left_bottom.x, (int)corners_2.left_bottom.y));

	return true;
}
void drawingLine(cv::Mat& img, std::vector<cv::Point>& vPoints) {
	for (int i = 0; i < vPoints.size(); i++)
	{
		if (i == (vPoints.size() - 1))
		{
			line(img, vPoints[0], vPoints[i], cv::Scalar(0, 0, 255), 2);
		}
		else
		{
			line(img, vPoints[i], vPoints[i + 1], cv::Scalar(0, 0, 255), 2);
		}

	}
}

int main() {

	cv::Mat img1 = cv::imread("1.png");
	cv::Mat img2 = cv::imread("2.png");
	std::vector<cv::Point> vPoint1;
	std::vector<cv::Point> vPoint2;
	cv::Mat dst;
	if (ImageOverlap(img1, img2, dst, vPoint1, vPoint2)) {
		drawingLine(img1, vPoint1);
		drawingLine(img2, vPoint2);
	}
	cv::imshow("dst", dst);
	cv::imshow("img1", img1);
	cv::imshow("img2", img2);
	cv::waitKey(0);

	int a;
	cin >> a;
}

原图:

获取两幅图重叠区域

 

获取两幅图重叠区域

 

最后结果图:

获取两幅图重叠区域

参考:

https://www.cnblogs.com/skyfsm/p/7411961.html

https://blog.csdn.net/qq_15295565/article/details/89402644

相关标签: opencv 图像处理