获取两幅图重叠区域
程序员文章站
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;
}
原图:
|
|
最后结果图:
参考: