OpenCV之图像特征提取与检测(十五) FLANN特征匹配

FLANN特征匹配介绍   算法速度特别快
 快速最近邻逼近搜索函数库(Fast Approximate Nearest Neighbor Search Library)    http://www.cs.ubc.ca/research/flann/ 开源库地址,对高额数据搜索比较快

代码

    #include "../common/common.hpp"

    using namespace cv::xfeatures2d;

    void main(int argc, char** argv)
    {
        Mat img1 = imread(getCVImagesPath("images/box.png"), IMREAD_GRAYSCALE);
        Mat img2 = imread(getCVImagesPath("images/box_in_scene.png"), IMREAD_GRAYSCALE);
        imshow("object image", img1);
        imshow("object in scene", img2);

        // surf featurs extraction
        int minHessian = 400;
        Ptr<SURF> detector = SURF::create(minHessian); // 也可以用 SIFT 特征
        vector<KeyPoint> keypoints_obj; // 保存特征点
        vector<KeyPoint> keypoints_scene;
        Mat descriptor_obj, descriptor_scene; // 特征描述子
        detector->detectAndCompute(img1, Mat(), keypoints_obj, descriptor_obj, false); // SURF特征检测,同时计算生成对应描述子
        detector->detectAndCompute(img2, Mat(), keypoints_scene, descriptor_scene, false);
        cout << "keypoints_obj.size=" << keypoints_obj.size() << endl; // keypoints_obj.size=786
        cout << "keypoints_scene.size=" << keypoints_scene.size() << endl; // keypoints_scene.size = 1040
        // descriptor_obj depth=5, type=5, size=[64 x 786]   CV_32F单通道   每个关键点用64来描述?
        cout << "descriptor_obj depth=" << descriptor_obj.depth() << ", type=" << descriptor_obj.type() << ", size=" << descriptor_obj.size() << endl;
        // descriptor_scene depth = 5, type = 5, size = [64 x 1040]
        cout << "descriptor_scene depth=" << descriptor_scene.depth() << ", type=" << descriptor_scene.type() << ", size=" << descriptor_scene.size() << endl;

        // matching
        FlannBasedMatcher matcher; // Flann 匹配类
        vector<DMatch> matches; // 保存匹配结果
        // 在descriptor_scene中匹配descriptor_obj的特征描述子,结果放到matches中, matches的长度与descriptor_obj的行数一致
        matcher.match(descriptor_obj, descriptor_scene, matches); // descriptor_obj中的特征描述子都会在descriptor_scene找到一个匹配点(不管是否真的准确)
        //descriptor_obj rows=786, cols=64
        cout << "descriptor_obj rows=" << descriptor_obj.rows << ", cols=" << descriptor_obj.cols << endl;
        cout << "matches.size=" << matches.size() << endl; // matches.size = 786

        // find good matched points
        double minDist = 1000;
        double maxDist = 0;
        for (int i = 0; i < descriptor_obj.rows; i++) {
            cout << "matches[" << i << "].queryIdx=" << matches[i].queryIdx << ", "; // matches[i].queryIdx  要查询的特征描述子的下标
            cout << "matches[" << i << "].trainIdx=" << matches[i].trainIdx << ", "; // matches[i].trainIdx  匹配到的要训练的特征描述子的下标
            cout << "matches[" << i << "].distance=" << matches[i].distance << endl; // 这两个描述特征子的距离      匹配度?
            double dist = matches[i].distance; // 要查询的特征描述子与匹配到的要训练的特征描述子之间的距离, 距离越小,匹配的越准确
            if (dist > maxDist) {
                maxDist = dist;
            }
            if (dist < minDist) {
                minDist = dist;
            }
        }
        printf("max distance=%f\n", maxDist); // max distance=0.671626
        printf("min distance=%f\n", minDist); // min distance=0.055168
        vector<DMatch> goodMatches; // 保存匹配度高的匹配点
        for (int i = 0; i < descriptor_obj.rows; i++) {
            double dist = matches[i].distance;
            if (dist < max(3 * minDist, 0.02)) { // 阈值的选取 实际情况实际分析?
                goodMatches.push_back(matches[i]);
            }
        }

        Mat matchesImg; // 显示匹配的结果
        drawMatches(img1, keypoints_obj, img2, keypoints_scene, goodMatches, matchesImg, Scalar::all(-1),
            Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS); // Single keypoints will not be drawn.
        imshow("Flann Matching Result", matchesImg);

        waitKey(0);
    }

效果图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/huanghuangjin/article/details/81288813
今日推荐