前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用C++的OpenCV进行SIFT特征检测与匹配

使用C++的OpenCV进行SIFT特征检测与匹配

作者头像
小锋学长生活大爆炸
发布2022-05-09 16:08:36
2.3K0
发布2022-05-09 16:08:36
举报
文章被收录于专栏:小锋学长生活大爆炸

目录

demo.c

CMakeLists.txt

效果

直接上代码吧:

demo.c

代码语言:javascript
复制
#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>
#include <opencv2/xfeatures2d.hpp>

int main() {
    int64 t1, t2;
    double tkpt, tdes, tmatch_bf, tmatch_knn;

    // 1. 读取图片
    const cv::Mat image1 = cv::imread("../../images/1.png", 0); //Load as grayscale
    const cv::Mat image2 = cv::imread("../../images/2.png", 0); //Load as grayscale
    std::vector<cv::KeyPoint> keypoints1;
    std::vector<cv::KeyPoint> keypoints2;

    cv::Ptr<cv::SiftFeatureDetector> sift = cv::SiftFeatureDetector::create();
    // 2. 计算特征点
    t1 = cv::getTickCount();
    sift->detect(image1, keypoints1);
    t2 = cv::getTickCount();
    tkpt = 1000.0*(t2-t1) / cv::getTickFrequency();
    sift->detect(image2, keypoints2);


    // 3. 计算特征描述符
    cv::Mat descriptors1, descriptors2;
    t1 = cv::getTickCount();
    sift->compute(image1, keypoints1, descriptors1);
    t2 = cv::getTickCount();
    tdes = 1000.0*(t2-t1) / cv::getTickFrequency();
    sift->compute(image2, keypoints2, descriptors2);


    // 4. 特征匹配
    cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create(cv::DescriptorMatcher::BRUTEFORCE);
    // cv::BFMatcher matcher(cv::NORM_L2);

    // (1) 直接暴力匹配
    std::vector<cv::DMatch> matches;
    t1 = cv::getTickCount();
    matcher->match(descriptors1, descriptors2, matches);
    t2 = cv::getTickCount();
    tmatch_bf = 1000.0*(t2-t1) / cv::getTickFrequency();
    // 画匹配图
    cv::Mat img_matches_bf;
    drawMatches(image1, keypoints1, image2, keypoints2, matches, img_matches_bf);
    imshow("bf_matches", img_matches_bf);

    // (2) KNN-NNDR匹配法
    std::vector<std::vector<cv::DMatch> > knn_matches;
    const float ratio_thresh = 0.7f;
    std::vector<cv::DMatch> good_matches;
    t1 = cv::getTickCount();
    matcher->knnMatch( descriptors1, descriptors2, knn_matches, 2);
    for (auto & knn_matche : knn_matches) {
        if (knn_matche[0].distance < ratio_thresh * knn_matche[1].distance) {
            good_matches.push_back(knn_matche[0]);
        }
    }
    t2 = cv::getTickCount();
    tmatch_knn = 1000.0*(t2-t1) / cv::getTickFrequency();

    // 画匹配图
    cv::Mat img_matches_knn;
    drawMatches( image1, keypoints1, image2, keypoints2, good_matches, img_matches_knn, cv::Scalar::all(-1),
                 cv::Scalar::all(-1), std::vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
    cv::imshow("knn_matches", img_matches_knn);
    cv::waitKey(0);



    cv::Mat output;
    cv::drawKeypoints(image1, keypoints1, output);
    cv::imwrite("sift_image1_keypoints.jpg", output);
    cv::drawKeypoints(image2, keypoints2, output);
    cv::imwrite("sift_image2_keypoints.jpg", output);


    std::cout << "图1特征点检测耗时(ms):" << tkpt << std::endl;
    std::cout << "图1特征描述符耗时(ms):" << tdes << std::endl;
    std::cout << "BF特征匹配耗时(ms):" << tmatch_bf << std::endl;
    std::cout << "KNN-NNDR特征匹配耗时(ms):" << tmatch_knn << std::endl;
    return 0;
}

CMakeLists.txt

代码语言:javascript
复制
cmake_minimum_required(VERSION 3.22)
project(demo)
find_package(OpenCV REQUIRED)

IF(UNIX)
    SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g -O0  -Wall -Wextra -Wunused-variable -DDEBUG -D_DEBUG")
    SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -O0 -g  -Wall -Wextra -Wunused-variable -DDEBUG -D_DEBUG")
ENDIF(UNIX)


set(CMAKE_CXX_STANDARD 20)

add_executable(demo main.cpp)
target_link_libraries(demo ${OpenCV_LIBS})

效果

其他算法如SURF、AKAZE等可类似修改,但注意SIFT这些是浮点数特征描述符,而ORB这些是二进制特征描述符,因此在特征匹配时注意区分是L2还是Hamming。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-04-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • demo.c
  • CMakeLists.txt
  • 效果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档