OpenCV3.2 ORB特征点 FLANN BruteForceMatcher匹配

KeyPoint类
class KeyPoint
{
      Point2f pt; //坐标
      float size; //特征点领域直径
      float angle;//特征点的方向,值为(0,360),负值表示不使用
      float response;
      int octave; //特征点所在的图像金字塔的组
       int class_id; //用于聚类的id
}
DMatch类
struct CV_EXPORTS_W_SIMPLE DMatch  
{  
    //默认构造函数,FLT_MAX是无穷大  
    CV_WRAP DMatch() : queryIdx(-1), trainIdx(-1), imgIdx(-1), distance(FLT_MAX) {}  
    //DMatch构造函数  
    CV_WRAP DMatch( int _queryIdx, int _trainIdx, float _distance ) : queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(-1), distance(_distance) {}  
    //DMatch构造函数  
    CV_WRAP DMatch( int _queryIdx, int _trainIdx, int _imgIdx, float _distance ) : queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(_imgIdx),distance(_distance) {}  

    //queryIdx为query描述子的索引,match函数中前面的那个描述子  
    CV_PROP_RW int queryIdx;  
    //trainIdx为train描述子的索引,match函数中后面的那个描述子  
    CV_PROP_RW int trainIdx;  
    //imgIdx为进行匹配图像的索引  
    //例如已知一幅图像的sift描述子,与其他十幅图像的描述子进行匹配,找最相似的图像,则imgIdx此时就有用了。  
    CV_PROP_RW int imgIdx;   
    //distance为两个描述子之间的距离  
    CV_PROP_RW float distance;  
    //DMatch比较运算符重载,比较的是DMatch中的distance,小于为true,否则为false   
    bool operator<( const DMatch &m ) const  
    {  
        return distance < m.distance;  
    }  
};

ORB 特征点 FLANN BruteForceMatcher匹配

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
    Mat img1 = imread("1.png");
    Mat img2 = imread("2.png");
    if(img1.empty()||img2.empty()){
        cout<<"could not load image .."<<endl;
        return -1;
    }

    namedWindow("DMatch");

    vector<KeyPoint> keyPoint1,keyPoint2;
    Mat descriptor1,descriptor2;
    Ptr<ORB> orb = ORB::create(500);

    orb->detectAndCompute(img1,Mat(),keyPoint1,descriptor1);
    orb->detectAndCompute(img2,Mat(),keyPoint2,descriptor2);

    vector<DMatch> match;
    //暴力匹配
    BFMatcher bfMatcher(NORM_HAMMING);
    //快速最近邻逼近搜索函数库
    //FlannBasedMatcher fbMatcher(NORM_HAMMING);
    Mat outImg;
    bfMatcher.match(descriptor1,descriptor2,match,Mat());

    double dist_min = 1000;
    double dist_max = 0;
    for(size_t t = 0;t<match.size();t++){
        double dist = match[t].distance;
        if(dist<dist_min) dist_min = dist;
        if(dist>dist_max) dist_max = dist;
    }

    vector<DMatch> goodMatch;
    for(size_t t = 0;t<match.size();t++){
        double dist = match[t].distance;
        if(dist <= max(2*dist_min,30.0))
            goodMatch.push_back(match[t]);
    }
    drawMatches(img1,keyPoint1,img2,keyPoint2,goodMatch,outImg);
    imshow("DMatch",outImg);
    waitKey(0);

    return 0;
}

运行结果:
这里写图片描述
Good!OK!

另一种定义方法:

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;

int main(int argc, char** argv)
{
    //-- 读取图像
    Mat img_1 = imread("1.png", CV_LOAD_IMAGE_COLOR);
    Mat img_2 = imread("2.png", CV_LOAD_IMAGE_COLOR);

    //-- 初始化
    std::vector<KeyPoint> keypoints_1, keypoints_2;
    Mat descriptors_1, descriptors_2;
    Ptr<FeatureDetector> detector = ORB::create();
    Ptr<DescriptorExtractor> descriptor = ORB::create();
    Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");

    //-- 第一步:检测 Oriented FAST 角点位置
    detector->detect(img_1, keypoints_1);
    detector->detect(img_2, keypoints_2);

    //-- 第二步:根据角点位置计算 BRIEF 描述子
    descriptor->compute(img_1, keypoints_1, descriptors_1);
    descriptor->compute(img_2, keypoints_2, descriptors_2);

    Mat outimg1;
    drawKeypoints(img_1, keypoints_1, outimg1, Scalar::all(-1), DrawMatchesFlags::DEFAULT);
    imshow("ORB特征点", outimg1);

    //-- 第三步:对两幅图像中的BRIEF描述子进行匹配,使用 Hamming 距离
    vector<DMatch> matches;
    //BFMatcher matcher ( NORM_HAMMING );
    matcher->match(descriptors_1, descriptors_2, matches);

    //-- 第四步:匹配点对筛选
    double min_dist = 10000, max_dist = 0;

    //找出所有匹配之间的最小距离和最大距离, 即是最相似的和最不相似的两组点之间的距离
    for (int i = 0; i < descriptors_1.rows; i++)
    {
        double dist = matches[i].distance;
        if (dist < min_dist) min_dist = dist;
        if (dist > max_dist) max_dist = dist;
    }

    // 仅供娱乐的写法
    min_dist = min_element(matches.begin(), matches.end(), [](const DMatch& m1, const DMatch& m2) {return m1.distance<m2.distance;})->distance;
    max_dist = max_element(matches.begin(), matches.end(), [](const DMatch& m1, const DMatch& m2) {return m1.distance<m2.distance;})->distance;

    printf("-- Max dist : %f \n", max_dist);
    printf("-- Min dist : %f \n", min_dist);

    //当描述子之间的距离大于两倍的最小距离时,即认为匹配有误.但有时候最小距离会非常小,设置一个经验值30作为下限.
    std::vector< DMatch > good_matches;
    for (int i = 0; i < descriptors_1.rows; i++)
    {
        if (matches[i].distance <= max(2 * min_dist, 30.0))
        {
            good_matches.push_back(matches[i]);
        }
    }

    //-- 第五步:绘制匹配结果
    Mat img_match;
    Mat img_goodmatch;
    drawMatches(img_1, keypoints_1, img_2, keypoints_2, matches, img_match);
    drawMatches(img_1, keypoints_1, img_2, keypoints_2, good_matches, img_goodmatch);
    imshow("所有匹配点对", img_match);
    imshow("优化后匹配点对", img_goodmatch);
    waitKey(0);

    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值