zoukankan      html  css  js  c++  java
  • 【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
    ", 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

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

  • 相关阅读:
    learning java identityHashCode
    learning java 获取环境变量及系统属性
    learning java 获取键盘输入
    learning svn add file execuable
    φ累积失败检测算法(转)
    层次锁(转)
    一致性算法中的节点下限(转)
    Fast Paxos(转)
    Zookeeper的一致性协议:Zab(转)
    FLP impossibility
  • 原文地址:https://www.cnblogs.com/xmphoenix/p/4508452.html
Copyright © 2011-2022 走看看