开发环境:Ubuntu 18.04 LTS + ROS Melodic + ViSP 3.3.1
文章内容主要参考ViSP官方教学文档:https://visp-doc.inria.fr/doxygen/visp-daily/tutorial_mainpage.html

  本文主要介绍了如何使用ViSP实现关键特征点的检测以及匹配,文中使用了ORB特征提取算法在参考图像中寻找关键点,并采用BruteForce-Hamming算法实现关键点的匹配,即从视频中寻找到与参考图像中相匹配的关键点。本文主要参考了detection/matching中的 tutorial-matching-keypoint.cpp例程。首先要获取这个例程文件并编译它

svn export https://github.com/lagadic/visp.git/trunk/tutorial/detection/matching
cd matching/
mkdir build
cd build 
cmake .. -DCMAKE_BUILD_TYPE=Release -DVISP_DIR=$VISP_WS/visp-build
make 

  执行例程,查看效果

./tutorial-matching-keypoint

  左图为参考图像,右图是视频中的实时图像,绿线连接的就是两幅图像中相互匹配的关键点
在这里插入图片描述
  下面介绍一下代码实现过程

#include <visp3/gui/vpDisplayOpenCV.h>
#include <visp3/io/vpImageIo.h>
#include <visp3/io/vpVideoReader.h>
#include <visp3/vision/vpKeyPoint.h>
int main()
{
#if (VISP_HAVE_OPENCV_VERSION >= 0x020101)
  vpImage<unsigned char> I;
  vpVideoReader reader;
  reader.setFileName("video-postcard.mp4");
  reader.acquire(I);
  const std::string detectorName = "ORB";//选择关键点检测算法
  const std::string extractorName = "ORB";//选择特征提取算法
  // Hamming distance must be used with ORB
  const std::string matcherName = "BruteForce-Hamming";//选择关键点匹配算法
  vpKeyPoint::vpFilterMatchingType filterType = vpKeyPoint::ratioDistanceThreshold;
  vpKeyPoint keypoint(detectorName, extractorName, matcherName, filterType);//新建关键点容器
  std::cout << "Reference keypoints=" << keypoint.buildReference(I) << std::endl;
  vpImage<unsigned char> Idisp;
  Idisp.resize(I.getHeight(), 2 * I.getWidth());//准备一个宽度为I两倍的图像用于展示结果
  Idisp.insert(I, vpImagePoint(0, 0)); //左图放置参考图像
  Idisp.insert(I, vpImagePoint(0, I.getWidth())); //右图放置视频实时图像
  vpDisplayOpenCV d(Idisp, 0, 0, "Matching keypoints with ORB keypoints");
  vpDisplay::display(Idisp);
  vpDisplay::flush(Idisp);
  while (!reader.end()) {
    reader.acquire(I);//获取视频当前帧
    Idisp.insert(I, vpImagePoint(0, I.getWidth()));//放置到右图位置
    vpDisplay::display(Idisp);
    vpDisplay::displayLine(Idisp, vpImagePoint(0, I.getWidth()), vpImagePoint(I.getHeight(), I.getWidth()),
                           vpColor::white, 2);//绘制一条白线将左右图分隔开
    unsigned int nbMatch = keypoint.matchPoint(I);//计算图像I中关键点的数量
    std::cout << "Matches=" << nbMatch << std::endl;
    vpImagePoint iPref, iPcur;
    for (unsigned int i = 0; i < nbMatch; i++) {
      keypoint.getMatchedPoints(i, iPref, iPcur);//获取匹配点的坐标
      vpDisplay::displayLine(Idisp, iPref, iPcur + vpImagePoint(0, I.getWidth()), vpColor::green);//将左右两图的匹配点连接起来
    }
    vpDisplay::flush(Idisp);
    if (vpDisplay::getClick(Idisp, false))
      break;
  }
  vpDisplay::getClick(Idisp);
#endif
  return 0;
}

如果大家对于深度学习与计算机视觉领域感兴趣,希望获得更多的知识分享与最新的论文解读,欢迎关注我的个人公众号“深视”。

在这里插入图片描述