欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenCV3.2 ORB特征点 FLANN BruteForceMatcher匹配

程序员文章站 2022-03-13 22:30:55
...
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;
}

运行结果:
OpenCV3.2 ORB特征点 FLANN BruteForceMatcher匹配
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;
}
相关标签: opencv ORB