OpenCV之图像特征提取与检测(十七) AKAZE局部特征检测与匹配

KAZE局部特征检测与匹配       KAZE是日语音译过来的
    AOS 构造尺度空间(非线性方式构造,得到的keypoints也就更准确)   尺度不变性
    Hessian矩阵特征点检测
    方向指定,基于一阶微分图像   旋转不变性
    描述子生成   归一化处理,光照不变性
AKAZE局部特征检测与匹配      A表示Accelerated(加速的)

与SIFT、 SUFR比较:
    更加稳定
    非线性尺度空间
    AKAZE速度更加快

代码

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

    void main(int argc, char** argv)
    {
        Mat src = imread(getCVImagesPath("images/test1_3.png"), IMREAD_GRAYSCALE);
        imshow("src2-23", src);

        // kaze detection
        Ptr<KAZE> detector_kaze = KAZE::create(); // KAZE局部特征检测类
        vector<KeyPoint> keypoints_kaze; // 保存检测到的特征点
        double t1 = getTickCount();
        detector_kaze->detect(src, keypoints_kaze, Mat()); // AKAZE局部特征检测
        double t2 = getTickCount();
        double tkaze = 1000 * (t2 - t1) / getTickFrequency(); // 乘以1000,转换成毫秒
        printf("KAZE Time consume(ms) : %f\n", tkaze); // KAZE Time consume(ms) : 1523.385317
        Mat keypointImg_kaze;
        drawKeypoints(src, keypoints_kaze, keypointImg_kaze, Scalar::all(-1), DrawMatchesFlags::DEFAULT); // 绘制显示
        imshow("kaze key points", keypointImg_kaze);

        // akaze detection
        Ptr<AKAZE> detector_akaze = AKAZE::create(); // AKAZE局部特征检测类,比KAZE速度要快
        vector<KeyPoint> keypoints_akaze; // 保存检测到的特征点
        t1 = getTickCount();
        detector_akaze->detect(src, keypoints_akaze, Mat()); // AKAZE局部特征检测
        t2 = getTickCount();
        tkaze = 1000 * (t2 - t1) / getTickFrequency(); // 乘以1000,转换成毫秒
        printf("AKAZE Time consume(ms) : %f\n", tkaze); // AKAZE Time consume(ms) : 665.136977
        Mat keypointImg_akaze;
        drawKeypoints(src, keypoints_akaze, keypointImg_akaze, Scalar::all(-1), DrawMatchesFlags::DEFAULT); // 绘制显示
        imshow("akaze key points", keypointImg_akaze);

        waitKey(0);
    }

效果图

这里写图片描述

代码

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

    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("box image", img1);
        imshow("scene image", img2);

        // extract akaze features
        Ptr<AKAZE> detector = AKAZE::create(); // AKAZE局部特征检测类
        vector<KeyPoint> keypoints_obj; // 保存检测到的特征点
        vector<KeyPoint> keypoints_scene;
        Mat descriptor_obj, descriptor_scene; // 保存生成的特征描述子
        double t1 = getTickCount();
        detector->detectAndCompute(img1, Mat(), keypoints_obj, descriptor_obj); // AKAZE特征检测,并且计算生成特征描述子
        detector->detectAndCompute(img2, Mat(), keypoints_scene, descriptor_scene);
        cout << "keypoints_obj.size=" << keypoints_obj.size() << endl; // keypoints_obj.size=460
        cout << "keypoints_scene.size=" << keypoints_scene.size() << endl; // keypoints_scene.size = 970
        // descriptor_obj depth = 0, type = 0, size = [61 x 460]   CV_8U 单通道   每个关键点用61来描述?
        cout << "descriptor_obj depth=" << descriptor_obj.depth() << ", type=" << descriptor_obj.type() << ", size=" << descriptor_obj.size() << endl;
        // descriptor_scene depth = 0, type = 0, size = [61 x 970]
        cout << "descriptor_scene depth=" << descriptor_scene.depth() << ", type=" << descriptor_scene.type() << ", size=" << descriptor_scene.size() << endl;
        double t2 = getTickCount();
        double tkaze = 1000 * (t2 - t1) / getTickFrequency(); // 乘以1000,转换成毫秒
        printf("AKAZE Time consume(ms) : %f\n", tkaze); // AKAZE Time consume(ms) : 2205.513233

        // matching  还可以使用BFMatcher matcher(NORM_L2);
        // 如果直接使用 FlannBasedMatcher matcher; 会报错,因为其默认方式支持的特征描述子的数据类型是float型,而AKAZE的特征描述子的数据类型为uchar
        FlannBasedMatcher matcher(new flann::LshIndexParams(20, 10, 2)); // new flann::LshIndexParams(20, 10, 2) 使Flann支持uchar类型的特征匹配
        //BFMatcher matcher(NORM_L2);
        vector<DMatch> matches;
        matcher.match(descriptor_obj, descriptor_scene, matches);
        cout << "matches.size=" << matches.size() << endl; // matches.size=460  长度与要查询的特征描述子一致

        // draw matches(key points)
        Mat akazeMatchesImg;
        drawMatches(img1, keypoints_obj, img2, keypoints_scene, matches, akazeMatchesImg);
        imshow("akaze match result", akazeMatchesImg);

        // 筛选匹配都高的匹配值
        vector<DMatch> goodMatches;
        double minDist = 100000, maxDist = 0;
        for (int i = 0; i < descriptor_obj.rows; i++) {
            double dist = matches[i].distance;
            if (dist < minDist) {
                minDist = dist;
            }
            if (dist > maxDist) {
                maxDist = dist;
            }
        }
        printf("min distance : %f\n", minDist); // min distance : 37.000000
        printf("max distance : %f\n", maxDist); // max distance : 168.000000
        for (int i = 0; i < descriptor_obj.rows; i++) {
            double dist = matches[i].distance;
            if (dist < max(1.5*minDist, 0.02)) {
                goodMatches.push_back(matches[i]);
            }
        }
        cout << "goodMatches.size=" << goodMatches.size() << endl; // goodMatches.size=11
        drawMatches(img1, keypoints_obj, img2, keypoints_scene, goodMatches, akazeMatchesImg, Scalar::all(-1), 
            Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS); // 不绘制单独的点
        imshow("good match result", akazeMatchesImg);
        Mat drawSinglePoints;
        drawMatches(img1, keypoints_obj, img2, keypoints_scene, goodMatches, akazeMatchesImg);
        imshow("drawSinglePoints", akazeMatchesImg);

        waitKey(0);
    }

效果图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/huanghuangjin/article/details/81292230