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

问题描述:已知两幅图像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 }

其中,多边形求交集可参考:http://www.cnblogs.com/dwdxdy/p/3232110.html

最终,程序运行的示意图如下:

时间: 2024-10-25 11:44:12

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

计算两幅图像的重叠区域

http://www.cnblogs.com/dwdxdy/p/3232331.html 随笔- 87  文章- 0  评论- 81 [OpenCV学习]计算两幅图像的重叠区域 问题描述:已知两幅图像Image1和Image2,计算出两幅图像的重叠区域,并在Image1和Image2标识出重叠区域. 算法思想: 若两幅图像存在重叠区域,则进行图像匹配后,会得到一张完整的全景图,因而可以转换成图像匹配问题. 图像匹配问题,可以融合两幅图像,得到全景图,但无法标识出在原图像的重叠区域. 将两幅图像都

OpenCV,计算两幅图像的单应矩阵

平面射影变换是关于其次3维矢量的一种线性变换,可以使用一个非奇异的$3 \times 3$矩阵H表示,$X' = HX$,射影变换也叫做单应(Homography).计算出两幅图像之间的单应矩阵H,那么应用这个关系可以将一个视图中的 所有点变换到另一个视图中. 上图,最右边图像是将最左边图像进行了一次射影变换,变换到中间图像视图后的图像. 使用OpenCV可以调用库函数findHomography计算两幅图像的单应矩阵,其声明如下 Mat findHomography(InputArray sr

OpenCV笔记(四)——两幅图像线性混合、改变图像的亮度和对比度

一.两幅图像线性混合 线性混合,就是g(x) = a*f1(x) + b*f2(x).其中g为输出,f1.f2为输入.a+b=1. 作用1:线性混合可以用于去噪,假设噪声的产生符合均值为零.标准差的独立分布.多个高斯分布求平均值,即可去除噪声. 作用2:用于两张图片的切换.a从大到小变化,b从小到大变化.g就渐渐从f1变到f2. OpenCV提供了addWeighted函数,完成上述功能: C++: void addWeighted(InputArray src1, double alpha,

OpenCv实现两幅图像的拼接

直接贴上源码 来源:http://www.myexception.cn/image/1498389.html 实验效果 Left.jpg???????????????????????????? right.jpg ImageMatch.jpg ? #include <iostream> #include <iomanip> #include "opencv2/core/core.hpp" #include "opencv2/objdetect/objd

相机位姿估计3:根据两幅图像的位姿估计结果求某点的世界坐标

关键词:相机位姿估计,单目尺寸测量,环境探知 用途:基于相机的环境测量,SLAM,单目尺寸测量 文章类型:原理说明.Demo展示 @Author:VShawn @Date:2016-11-28 @Lab: [email protected] 目录 <相机位姿估计0:基本原理之如何解PNP问题> <相机位姿估计1:根据四个特征点估计相机姿态> <相机位姿估计1_1:OpenCV:solvePnP二次封装与性能测试> <相机位姿估计2:[应用]实时位姿估计与三维重建相

大家来找茬 两幅图像相减 其它好的实现? 美女找茬

http://blog.csdn.net/merlin_q/article/details/7024798 大家来找茬 两幅图像相减 其它好的实现? 标签: imageinclude 2011-11-29 20:29 4701人阅读 评论(2) 收藏 举报  分类: Opencv学习(16)  C++(18)  版权声明:本文为博主原创文章,未经博主允许不得转载. #include <opencv2/core/core.hpp>#include <opencv2/highgui/high

衡量两幅图像相似度的指标SNR(signal to noise ratio)和PSNR(peak signal to noise ratio)SSIM(structural similarity in

官方网站:https://ece.uwaterloo.ca/~z70wang/research/ssim/ 1.SSIM structural similarity index 一种衡量两幅图像相似度的新指标,其值越大越好,最大为1, 经常用到图像处理中,特别在图像去噪处理中在图像相似度评价上全面超越SNR(signal to noise ratio)和PSNR(peak signal to noise ratio). 具体原理见 Z. Wang, A. C. Bovik, H. R. Shei

两幅图像的融合与叠加

假设两幅图像的大小完全一致,对应的像素数组分别为A与B,对应的任意单个像素值分别是a与b,混合后的像素值为c 几种典型图像叠加操作: 1.乘法叠加 c=(ab)/255 public int modeOne(int v1,int v2){ return (v1v2)/255; } 2.加法叠加 c=(a+b)/2 public int modeTwo(int v1,int v2){ return (v1+v2)/2; } 3.减法叠加 c=|a-b| public int modeThree(i

opencv学习(5)图像像素的访问、颜色通道的分离和融合

代码都是源于毛星云的<opencv3.0编程入门> 1.计时函数 getTickCount()和getTickFrequency()函数: getTickCount()函数返回CPU自某个事件以来走过的时钟周期: getTickFrequency()函数 返回CPU一秒所走的周期数: 事例: double time0=static_cast< double>(getTickCount()); //记录起始时间 // 事件的处理操作 time0=((double)getTickCou