您的位置:首页 > 运维架构

【OpenCV学习】计算两幅图像的重叠区域

2015-05-16 19:26 591 查看
问题描述:已知两幅图像Image1和Image2,计算出两幅图像的重叠区域,并在Image1和Image2标识出重叠区域。 算法思想: 若两幅图像存在重叠区域,则进行图像匹配后,会得到一张完整的全景图,因而可以转换成图像匹配问题。 图像匹配问题,可以融合两幅图像,得到全景图,但无法标识出在原图像的重叠区域。 将两幅图像都理解为多边形,则其重叠区域的计算,相当于求多边形的交集。 通过多边形求交,获取重叠区域的点集,然后利用单应矩阵还原在原始图像的点集信息,从而标识出重叠区域。 算法步骤: 1.图像匹配计算,获取单应矩阵。 2.根据单应矩阵,计算图像2的顶点转换后的点集。 3.由图像1的顶点集合和图像2的转换点集,计算多边形交集。 4.根据单应矩阵的逆,计算多边形的交集在图像2中的原始点集。 代码实现如下所示:



1 bool ImageOverlap(cv::Mat &img1,cv::Mat &img2,std::vector<cv::Point> &vPtsImg1,std::vector<cv::Point> &vPtsImg2)
2 {
3     cv::Mat g1(img1,Rect(0,0,img1.cols,img1.rows));
4     cv::Mat g2(img2,Rect(0,0,img2.cols,img2.rows));
5
6     cv::cvtColor(g1,g1,CV_BGR2GRAY);
7     cv::cvtColor(g2,g2,CV_BGR2GRAY);
8
9     std::vector<cv::KeyPoint> keypoints_roi, keypoints_img;  /* keypoints found using SIFT */
10     cv::Mat descriptor_roi, descriptor_img;             /* Descriptors for SIFT */
11     cv::FlannBasedMatcher matcher;                      /* FLANN based matcher to match keypoints */
12     std::vector<cv::DMatch> matches, good_matches;
13     cv::SIFT sift;
14     int i, dist=80;
15
16     sift(g1, Mat(), keypoints_roi, descriptor_roi);      /* get keypoints of ROI image */
17     sift(g2, Mat(), keypoints_img, descriptor_img);         /* get keypoints of the image */
18     matcher.match(descriptor_roi, descriptor_img, matches);
19
20     double max_dist = 0; double min_dist = 1000;
21
22     //-- Quick calculation of max and min distances between keypoints
23     for( int i = 0; i < descriptor_roi.rows; i++ )
24     {
25         double dist = matches[i].distance;
26         if( dist < min_dist ) min_dist = dist;
27         if( dist > max_dist ) max_dist = dist;
28     }
29
30     for (i=0; i < descriptor_roi.rows; i++)
31     {
32         if (matches[i].distance < 3*min_dist)
33         {
34             good_matches.push_back(matches[i]);
35         }
36     }
37
38     //printf("%ld no. of matched keypoints in right image\n", good_matches.size());
39     /* Draw matched keypoints */
40
41     //Mat img_matches;
42     //drawMatches(img1, keypoints_roi, img2, keypoints_img,
43     //    good_matches, img_matches, Scalar::all(-1),
44     //    Scalar::all(-1), vector<char>(),
45     //    DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
46     //imshow("matches",img_matches);
47
48     vector<Point2f> keypoints1, keypoints2;
49     for (i=0; i<good_matches.size(); i++)
50     {
51         keypoints1.push_back(keypoints_img[good_matches[i].trainIdx].pt);
52         keypoints2.push_back(keypoints_roi[good_matches[i].queryIdx].pt);
53     }
54     //计算单应矩阵
55     Mat H = findHomography( keypoints1, keypoints2, CV_RANSAC );
56
57     //show stitchImage
58     // cv::Mat stitchedImage;
59     // int mRows = img2.rows;
60     // if (img1.rows> img2.rows)
61     // {
62         // mRows = img1.rows;
63     // }
64     // stitchedImage = Mat::zeros(img2.cols+img1.cols, mRows, CV_8UC3);
65     // warpPerspective(img2,stitchedImage,H,Size(img2.cols+img1.cols,mRows));
66     // Mat half(stitchedImage,Rect(0,0,img1.cols,img1.rows));
67     // img1.copyTo(half);
68     // imshow("stitchedImage",stitchedImage);
69
70     std::vector<cv::Point> vSrcPtsImg1;
71     std::vector<cv::Point> vSrcPtsImg2;
72
73     vSrcPtsImg1.push_back(cv::Point(0,0));
74     vSrcPtsImg1.push_back(cv::Point(0,img1.rows));
75     vSrcPtsImg1.push_back(cv::Point(img1.cols,img1.rows));
76     vSrcPtsImg1.push_back(cv::Point(img1.cols,0));
77
78     vSrcPtsImg2.push_back(cv::Point(0,0));
79     vSrcPtsImg2.push_back(cv::Point(0,img2.rows));
80     vSrcPtsImg2.push_back(cv::Point(img2.cols,img2.rows));
81     vSrcPtsImg2.push_back(cv::Point(img2.cols,0));
82
83     //计算图像2在图像1中对应坐标信息
84     std::vector<cv::Point> vWarpPtsImg2;
85     for(int i = 0;i < vSrcPtsImg2.size();i++ )
86     {
87         cv::Mat srcMat = Mat::zeros(3,1,CV_64FC1);
88         srcMat.at<double>(0,0) = vSrcPtsImg2[i].x;
89         srcMat.at<double>(1,0) = vSrcPtsImg2[i].y;
90         srcMat.at<double>(2,0) = 1.0;
91
92         cv::Mat warpMat = H * srcMat;
93         cv::Point warpPt;
94         warpPt.x = cvRound(warpMat.at<double>(0,0)/warpMat.at<double>(2,0));
95         warpPt.y = cvRound(warpMat.at<double>(1,0)/warpMat.at<double>(2,0));
96
97         vWarpPtsImg2.push_back(warpPt);
98     }
99     //计算图像1和转换后的图像2的交点
100     if(!PolygonClip(vSrcPtsImg1,vWarpPtsImg2,vPtsImg1))
101         return false;
102
103     for (int i = 0;i < vPtsImg1.size();i++)
104     {
105         cv::Mat srcMat = Mat::zeros(3,1,CV_64FC1);
106         srcMat.at<double>(0,0) = vPtsImg1[i].x;
107         srcMat.at<double>(1,0) = vPtsImg1[i].y;
108         srcMat.at<double>(2,0) = 1.0;
109
110         cv::Mat warpMat = H.inv() * srcMat;
111         cv::Point warpPt;
112         warpPt.x = cvRound(warpMat.at<double>(0,0)/warpMat.at<double>(2,0));
113         warpPt.y = cvRound(warpMat.at<double>(1,0)/warpMat.at<double>(2,0));
114         vPtsImg2.push_back(warpPt);
115     }
116     return true;
117 }




其中,多边形求交集可参考:/article/4983859.html
最终,程序运行的示意图如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: