SLAMBook(ch7)视觉里程计特征匹配代码笔记

 1、读取图像

Mat img_1=imread(argv[1],CV_LOAD_IMAGE_COLOR);
//表示以彩色图像形式读取argv中的参数信息,并且存贮于img_1中
Mat img_2=imread(argv[2],CV_LOAD_IMAGE_COLOR);
//imread(const String & 文件名,    int flags = 读取图片方式 )    返回值:Mat类型

Mat(图像矩阵) 为 opencv 中的类 ,无需定义维度 ,自适应。另外,这里img_1和img_2存储了两张图像的颜色信息,其维度为2维,大小为480*640(这里存储数据的矩阵维度并非480*640,而是480*(640*3),因为要存储每个像素点的BGR信息,因此每个像素的信息对应1行和3列)。

 imread函数

#include <opencv2/imgcodecs.hpp>
Mat cv::imread(const String &filename,    int flags = IMREAD_COLOR ) 

imread函数原型非常简单,可以总结为三点

返回值:Mat 类型, 即返回读取的图像,读取图像失败时返回一个空的矩阵对象(Mat::data == NULL)
参数1 filename, 读取的图片文件名,
可以使用相对路径或者绝对路径,但必须带完整的文件扩展名(图片格式后缀)
参数2 flags, 一个读取标记,用于选择读取图片的方式默认值为1,flag值的设定与用什么颜色格式读取图片有关

图像类型有以下几种:

CV_LOAD_IMAGE_UNCHANGED——等价取值为-1,这个标识在新版本中已被废置,可以忽略

CV_LOAD_IMAGE_GRAYSCALE——等价取值为0,返回灰色图像

CV_LOAD_IMAGE_COLOR——等价取值为1,返回彩色图像

CV_LOAD_IMAGE_ANYDEPTH——等价取值为2,若图像深度是16位或者32位,就返回对应深度,否则,返回8位图像

如果输入有冲突的标志,将采用较小的数字值

2、初始化

      std::vector<KeyPoint>keypoints_1,keypoints_2;
      //容器vector类型<keypoint>图片1 -> 关键点1 图片2 -> 关键点2;
      //存储角度 距离 分类 关键点坐标 金字塔层数等关键信息。
      Mat descriptors_1,descriptors_2;
      Ptr<ORB> orb=ORB::create(500,1.2f,8,31,0,2,ORB::HARRIS_SCORE,31,20);

第1步:检测Oriented FAST角点位置

      orb->detect(img_1,keypoints_1);
      orb->detect(img_2,keypoints_2);

第2步:根据角点位置计算BRIEF描述子

      orb->compute(img_1,keypoints_1,descriptors_1);
      orb->compute(img_2,keypoints_2,descriptors_2);
      Mat outimg1;//Mat:图像矩阵构造函数
      drawKeypoints(img_1,keypoints_1,outimg1,Scalar::all(-1),DrawMatchesFlags::DEFAULT);
      imshow("ORB特征点",outimg1);

drawKeypoint函数:绘制图像

cv2.drawKeypoints(image, keypoints, outImage, color=None, flags=None)

image
原始图像,可以使三通道或单通道图像;

keypoints
特征点向量,向量内每一个元素是一个KeyPoint对象,包含了特征点的各种属性信息;
outImage
特征点绘制的画布图像,可以是原图像;
color
绘制的特征点的颜色信息,默认绘制的是随机彩色; Scalar::all(-1) // 颜色随机
flags
特征点的绘制模式,其实就是设置特征点的那些信息需要绘制,那些不需要绘制,有以下几种模式可选:

DEFAULT:只绘制特征点的坐标点,显示在图像上就是一个个小圆点,每个小圆点的圆心坐标都是特征点的坐标。

DRAW_OVER_OUTIMG:函数不创建输出的图像,而是直接在输出图像变量空间绘制,要求本身输出图像变量就是一个初始化好了的,size与type都是已经初始化好的变量
NOT_DRAW_SINGLE_POINTS:单点的特征点不被绘制

DRAW_RICH_KEYPOINTS:绘制特征点的时候绘制的是一个个带有方向的圆,这种方法同时显示图像的坐标,size,和方向,是最能显示特征的一种绘制方式。

第3步:使用Hamming距离进行BRIEF描述子匹配

      vector<DMatch>matches;
      //DMatch是匹配关键点描述子 类, matches用于存放匹配项
      BFMatcher matcher(NORM_HAMMING);
      matcher.match(descriptors_1,descriptors_2,matches);
      // 使用match方法,获取最匹配的两个特征点(匹配的特征点可以有多对,均存放在matche中)

第4步:匹配点筛选

      double min_dist=10000,max_dist=0;
      for(int i=0;i<descriptors_1.rows;i++)
      {
            double dist=matches[i].distance;
            if(dist<min_dist)min_dist=dist;
            if(dist>max_dist)max_dist=dist;
      }
      printf("--Max dist:%f\n",max_dist);
      printf("--Min dist:%f\n",min_dist);
      std::vector<DMatch>good_matches;
      for(int i=0;i<descriptors_1.rows;i++)
      {
            if(matches[i].distance<=max(2*min_dist,30.0))
            {
                  good_matches.push_back(matches[i]);
            }
      }

第5步:绘制匹配结果

      Mat img_match;//存放所有匹配点
      Mat img_goodmatch; //存放好的匹配点
       // drawMatches用于绘制两幅图像的匹配关键点
       // 参数5是两张图像的匹配关键点数组,参数6用于存放函数的绘制结果
      drawMatches(img_1,keypoints_1,img_2,keypoints_2,matches,img_match);
      drawMatches(img_1,keypoints_1,img_2,keypoints_2,good_matches,img_goodmatch);
      imshow("所有匹配点对",img_match);
      imshow("优化后匹配点对",img_goodmatch);
      waitKey(0);
      
      return 0;

drawMatches()函数:绘制两幅图像的匹配关键点

// Draws matches of keypints from two images on output image.
void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
                  const Mat& img2, const vector<KeyPoint>& keypoints2,
                  const vector<vector<DMatch> >& matches1to2, Mat& outImg,
                  const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1),
                  const vector<vector<char> >& matchesMask=vector<vector<char> >(), int flags=DrawMatchesFlags::DEFAULT );

img1 – 源图像1
keypoints1 – 源图像1的特征点.
img2 – 源图像2.
keypoints2 – 源图像2的特征点
matches1to2 – 源图像1的特征点匹配源图像2的特征点[matches[i]] .
outImg – 输出图像具体由flags决定.
matchColor– 匹配的颜色(特征点和连线),若matchColor ==Scalar::all(-1),颜色随机.
singlePointColor – 单个点的颜色,即未配对的特征点,若matchColor ==Scalar::all(-1),颜色随机.
matchesMask –Mask决定哪些点将被画出,若为空,则画出所有匹配点.
flags – Fdefined by DrawMatchesFlags.

waitKey()函数

1.waitKey()与waitKey(0),都代表无限等待,waitKey函数的默认参数就是int delay = 0,故这俩形式本质是一样的。

2.waitKey(n),等待n毫秒后,关闭显示的窗口。

3、编译

make完成后需要在终端键入图像的路径,绝对路径如图所示。

./工程名 绝对路径/1.png 绝对路径/2.png
例如我的工程名为feature_extraction:
./feature_extraction /home/ddd/slam14/feature_extraction/1.png /home/ddd/slam14/feature_extraction/2.png

 参考链接:slambook2(ch7)—— orb_cv.cpp代码详解(ORB特征提取与匹配)_slambook2代码_@曾记否的博客-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值