C++ OpenCV4.5版本SIFT特征检测及匹配

学更好的别人,

做更好的自己。

——《微卡智享》

本文长度为2739,预计阅读6分钟

前言

关于SIFT的特征点检测在《C++ OpenCV特征提取之SIFT特征检测》有介绍过,在OpenCV4.5版本中SIFT做是算法优化,也移到主仓库中了,并且有朋友也留言问了4.5版本下的DEMO。

6dc0ff7c16d0ba3760b6fc9ad895dbf1.png

所以这篇就做一下OpenCV4.5版本的SIFT特征点检测及匹配。

53b637e169b0b661ba41fa1e37e77512.png

实现效果

e3e8aba0fbae1b194ac74e8182f0f451.png

两张原图

fc3c407d1b718265f6f9699742cd8a32.png

匹配的效果

代码实现

cfa6fab57a5e55517673354816508e02.png

微卡智享

 

#实现流程
1定义检测的特征点个数,用SIFT进行特征检测
2对检测完的两个图做特征向量的提取
3使用BFMatch进行匹配,筛选出好的结果
4画出匹配的特征点

 

01

SIFT特征检测

以前版本中使用SIFT需要引入xfeatures2d.hpp,而现在就不用了。

684abdc636eb2c545cf0e4a8aad94d98.png

旧版本

09b1c30124c5bf2edc533ff2c6fefa7e.png

新版本

02

特征向量的提取

接下来就是计算特征点描述符,特征向量的提取

bd3feda514dcf6aefe1adac769353606.png

特征向量提取

03

使用BFMatch匹配

提取完特征向量后,对两个特征向量进行匹配,然后通过匹配的结果计算出向量的最大和最小距离。

aa73f052372ba09818e2378c4a0d38a0.png

特征匹配及计算最大最小距离

04

筛选好的匹配结果

最后就是根据最大最小的距离,从匹配的点中筛选出好的结果,再展示出来。

a00d63b16d0181487113460df4d888ed.png

筛选结果绘制图像

完整代码

#include<iostream>
#include<opencv2/opencv.hpp>
#include"CvUtils.h"


using namespace std;
using namespace cv;


int main(int argc, char** argv) {


  Mat src = imread("E:/DCIM/hrd/h1.jpg");
  CvUtils::MatResize(src);
  CvUtils::SetShowWindow(src, "src", 10, 20);
  imshow("src", src);


  Mat src2 = imread("E:/DCIM/hrd/h3.jpg");
  CvUtils::MatResize(src2);
  CvUtils::SetShowWindow(src2, "src2", 300, 20);
  imshow("src2", src2);


  //定义Sift的基本参数
  int numFeatures = 500;
  //创建detector存放到KeyPoints中
  Ptr<SIFT> detector = SIFT::create(numFeatures);
  vector<KeyPoint> keypoints, keypoints2;
  detector->detect(src, keypoints);
  detector->detect(src2, keypoints2);
  //打印Keypoints
  cout << "Keypoints:" << keypoints.size() << endl;
  cout << "Keypoints2:" << keypoints2.size() << endl;


  Mat drawsrc, drawsrc2;
  drawKeypoints(src, keypoints, drawsrc);
  CvUtils::SetShowWindow(drawsrc, "drawsrc", 10, 20);
  imshow("drawsrc", drawsrc);
  drawKeypoints(src2, keypoints2, drawsrc2);
  CvUtils::SetShowWindow(drawsrc2, "drawsrc2", 300, 20);
  imshow("drawsrc2", drawsrc2);


  //计算特征点描述符,特征向量提取
  Mat dstSIFT, dstSIFT2;
  Ptr<SiftDescriptorExtractor> descriptor = SiftDescriptorExtractor::create();
  descriptor->compute(src, keypoints, dstSIFT);
  descriptor->compute(src2, keypoints2, dstSIFT2);
  cout << dstSIFT.cols << endl;
  cout << dstSIFT2.rows << endl;


  //进行BFMatch暴力匹配
  BFMatcher matcher(NORM_L2);
  //定义匹配结果变量
  vector<DMatch> matches;
  //实现描述符之间的匹配
  matcher.match(dstSIFT, dstSIFT2, matches);


  //定义向量距离的最大值与最小值
  double max_dist = 0;
  double min_dist = 1000;
  for (int i = 1; i < dstSIFT.rows; ++i)
  {
    //通过循环更新距离,距离越小越匹配
    double dist = matches[i].distance;
    if (dist > max_dist)
      max_dist = dist;
    if (dist < min_dist)
      min_dist = dist;
  }
  cout << "min_dist=" << min_dist << endl;
  cout << "max_dist=" << max_dist << endl;
  //匹配结果筛选    
  vector<DMatch> goodMatches;
  for (int i = 0; i < matches.size(); ++i)
  {
    double dist = matches[i].distance;
    if (dist < 2 * min_dist)
      goodMatches.push_back(matches[i]);
  }
  cout << "goodMatches:" << goodMatches.size() << endl;


  Mat result;
  //匹配特征点天蓝色,单一特征点颜色随机
  drawMatches(src, keypoints, src2, keypoints2, goodMatches, result, 
    Scalar(255, 255, 0), Scalar::all(-1));
  CvUtils::SetShowWindow(result, "Result", 100, 20);
  imshow("Result", result);




  waitKey(0);
  return 0;
}

源码地址

https://github.com/Vaccae/OpenCVDemoCpp.git

这个Demo我也整合到OpenCV练习Demo中了,GitHub上不去的朋友,可以击下方的原文链接跳转到码云的地址,关注【微卡智享】公众号,回复【源码】可以下载我的所有开源项目。

565de6626b7ab0d835d2c5909ca5903a.png

扫描二维码

获取更多精彩

微卡智享

57694b676eac07859a36477a1106f1b2.png

「 往期文章 」

趣玩算法--OpenCV华容道AI自动解题

整活!我是如何用OpenCV做了数字华容道游戏!(附源码)

C++ OpenCV去燥函数fastNlMeansDenoising的使用

 

  • 17
    点赞
  • 174
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 20
    评论
好的,下面是一个基于 SIFT 算法的特征匹配的 C++ OpenCV 实现。 首先,我们需要导入必要的头文件和命名空间: ```cpp #include <opencv2/opencv.hpp> using namespace cv; ``` 然后,我们可以定义一个函数来执行 SIFT 特征提取和匹配: ```cpp void siftMatch(const Mat &img1, const Mat &img2, std::vector<DMatch> &matches) { // 创建 SIFT 特征检测器和描述符提取器 Ptr<Feature2D> detector = SIFT::create(); // 检测关键点,并计算描述符 std::vector<KeyPoint> keypoints1, keypoints2; Mat descriptors1, descriptors2; detector->detectAndCompute(img1, Mat(), keypoints1, descriptors1); detector->detectAndCompute(img2, Mat(), keypoints2, descriptors2); // 创建暴力匹配器 BFMatcher matcher(NORM_L2); // 匹配描述符 matcher.match(descriptors1, descriptors2, matches); } ``` 在这个函数中,我们首先创建了 SIFT 特征检测器和描述符提取器,然后使用它们检测关键点并计算描述符。接下来,我们创建了一个暴力匹配器,并使用它来匹配描述符。 最后,我们可以在主函数中调用这个函数,如下所示: ```cpp int main() { // 读取图像 Mat img1 = imread("img1.jpg"); Mat img2 = imread("img2.jpg"); // 匹配特征点 std::vector<DMatch> matches; siftMatch(img1, img2, matches); // 绘制匹配结果 Mat imgMatches; drawMatches(img1, keypoints1, img2, keypoints2, matches, imgMatches); imshow("Matches", imgMatches); waitKey(0); return 0; } ``` 在这个示例中,我们首先读取了两张图像。然后,我们调用 `siftMatch` 函数来提取关键点并匹配。最后,我们使用 OpenCV 的 `drawMatches` 函数来绘制匹配结果,并显示在窗口中。 注意,在实际使用中,我们可能需要对提取的关键点进行筛选和优化,以提高匹配的准确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vaccae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值