opencv3.1 surf特征匹配


 #include <vector>  
#include <iostream>
#include <opencv2/core/core.hpp>     
#include "opencv2/xfeatures2d.hpp"   
#include "opencv2/xfeatures2d/nonfree.hpp"  //SURF
#include "opencv2/xfeatures2d/cuda.hpp"  
#include <opencv2/highgui/highgui.hpp>    
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

void getMatchPoint(Mat src1, Mat src2)

{

    vector<KeyPoint> keys1;  
   vector<KeyPoint> keys2;

   Ptr<xfeatures2d::SURF> detector = xfeatures2d::SURF::create(800);
   cv::BFMatcher matcher;
   Mat descriptorMat1, descriptorMat2;
   std::vector<DMatch> mathces;
 
   detector->detectAndCompute(src1, Mat(), keys1, descriptorMat1);
   detector->detectAndCompute(src2, Mat(), keys2, descriptorMat2);
   matcher.match(descriptorMat1, descriptorMat2, mathces);

   drawKeypoints(src1, keys1, src1, cv::Scalar::all(255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
   drawKeypoints(src2, keys2, src2, cv::Scalar::all(255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
  

   Mat matchMat;
   drawMatches(src1, keys1, src2, keys2, mathces, matchMat);
   cv::imshow("Mathces", matchMat);

   imshow("image1", src1);      
   imshow("image2", src2); 


  #if 1 
    double max_dist = 0; double min_dist = 100;
    //-- Quick calculation of max and min distances between keypoints  
    for (int i=0; i<descriptorMat1.rows; i++)
    {
        double dist = mathces[i].distance;
        if (dist < min_dist) min_dist = dist;
        if (dist > max_dist) max_dist = dist;
    }
    cout<<"-- Max dist :"<< max_dist<<endl;
    cout<<"-- Min dist :"<< min_dist<<endl;

     //-- Draw only "good" matches (i.e. whose distance is less than 0.6*max_dist )  
    //-- PS.- radiusMatch can also be used here.  
    vector< DMatch > good_matches;
    for (int i=0; i<descriptorMat1.rows; i++)
    {
        if (mathces[i].distance < 0.6*max_dist)
        {
            good_matches.push_back(mathces[i]);
        }
    }

    Mat img_matches;
    drawMatches(src1, keys1, src2, keys2,
    good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
    vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);

    imwrite("FASTResult.jpg", img_matches);
    imshow("goodMatch", img_matches);  
#endif

#if 1
    // 分配空间
    int ptCount = (int)mathces.size();
    Mat p1(ptCount, 2, CV_32F);
    Mat p2(ptCount, 2, CV_32F);

    // 把Keypoint转换为Mat
    Point2f pt;
    for (int i=0; i<ptCount; i++)
    {
        pt = keys1[mathces[i].queryIdx].pt;
        p1.at<float>(i, 0) = pt.x;
        p1.at<float>(i, 1) = pt.y;

        pt = keys2[mathces[i].trainIdx].pt;
        p2.at<float>(i, 0) = pt.x;
        p2.at<float>(i, 1) = pt.y;
    }


    // 用RANSAC方法计算 基本矩阵F
    Mat fundamental;
    vector<uchar> RANSACStatus;

    fundamental = findFundamentalMat(p1, p2, RANSACStatus, FM_RANSAC);
    // 计算野点个数
    int OutlinerCount = 0;
    for (int i=0; i<ptCount; i++)
    {
        if (RANSACStatus[i] == 0) // 状态为0表示野点
        {
            OutlinerCount++;
        }
    }
   
      // 计算内点
    vector<Point2f> Inlier1;
    vector<Point2f> Inlier2;
    vector<DMatch> InlierMatches;
    // 上面三个变量用于保存内点和匹配关系
    int InlinerCount = ptCount - OutlinerCount;
    InlierMatches.resize(InlinerCount);
    Inlier1.resize(InlinerCount);
    Inlier2.resize(InlinerCount);
    InlinerCount = 0;
    for (int i=0; i<ptCount; i++)
    {
        if (RANSACStatus[i] != 0)
        {
            Inlier1[InlinerCount].x = p1.at<float>(i, 0);
            Inlier1[InlinerCount].y = p1.at<float>(i, 1);
            Inlier2[InlinerCount].x = p2.at<float>(i, 0);
            Inlier2[InlinerCount].y = p2.at<float>(i, 1);
            InlierMatches[InlinerCount].queryIdx = InlinerCount;
            InlierMatches[InlinerCount].trainIdx = InlinerCount;
            cout<<"index = "<<i<<", distance="<<mathces.at(i).distance<<endl;
            InlinerCount++;
        }
    }

    // 把内点转换为drawMatches可以使用的格式
    vector<KeyPoint> key1(InlinerCount);
    vector<KeyPoint> key2(InlinerCount);
    KeyPoint::convert(Inlier1, key1);
    KeyPoint::convert(Inlier2, key2);

    // 显示计算F过后的内点匹配
     //Mat m_matLeftImage;
     //Mat m_matRightImage;
    // 以上两个变量保存的是左右两幅图像
    Mat OutImage;
    drawMatches(src1, key1, src2, key2, InlierMatches, OutImage);
    imwrite("FmatrixResult.jpg", OutImage);
    imshow("FMatch", OutImage);
#endif

 

}

结果图:


//good_matches.jpg


// FmatrixResult.jpg




 知识点补充:

DMATCH 数据结构:

struct DMatch
{ //三个构造函数
DMatch():
queryIdx(-1),trainIdx(-1),imgIdx(-1),distance(std::numeric_limits::max()) {}

DMatch(int _queryIdx, int _trainIdx, float _distance ) :
queryIdx( _queryIdx),trainIdx( _trainIdx), imgIdx(-1),distance( _distance) {}

DMatch(int _queryIdx, int _trainIdx, int _imgIdx, float _distance ) :
queryIdx(_queryIdx), trainIdx( _trainIdx), imgIdx( _imgIdx),distance( _distance) {}
int queryIdx; //此匹配对应的查询图像的特征描述子索引(输入图1)
int trainIdx; //此匹配对应的训练(模板)图像的特征描述子索引(输入图2)
int imgIdx; //训练图像的索引(若有多个)
float distance; //两个特征向量之间的欧氏距离,越小表明匹配度越高。
booloperator < (const DMatch &m) const;
};


参考文献:

http://blog.csdn.net/ikerpeng/article/details/47972959



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值