ORB-SLAM学习(一):ORB特征提取

相关知识介绍

图像金字塔

ORB特征点

绪论

ORB-SLAM2中的ORB特征点提取和OpenCV有所不同。在ORB-SLAM2中进行了一系列操作让特征点均匀的分布在图像中,这样对于后面的位姿估计比较好。OpenCV直接提取的特征点可能会出现扎堆,集中等现象,这样很多特征点就没用了。下面对ORB-SLAM2中的ORB特征点提取的过程进行介绍。

构建图像金字塔

  • 首先对图像进行扩展,这一步的目的是为了之后的高斯模糊操作。

    图像扩充示意,这一步是把原图像(最里边的矩形)扩展到最外侧的矩形
  • 进行一个循环,把每一层的图像都在上一层图像的基础上进行扩充(或者叫补边),该过程用到了OpenCV中的copyMakeBorder函数和resize函数,扩充的规则为BORDER_REFLECT_101,扩充的效果如下:

左边是扩充效果,可以看出是一个类似镜像的效果

计算特征点并通过四叉树对特征点进行均匀化操作

这一步又对每一层进行了一次遍历,干了这些事:

  • 把原图像的边扩充3个像素点,这个是为了进行FAST关键点提取预留的计算半径;
  • 把图像均匀划分成了一堆小格子(均匀化);
  • 对这堆小格子进行遍历,在每个小格子中调用OpenCV中的FAST函数通过yaml文件中的设置阈值进行关键点提取,如果这都没采到哪怕是一个关键点,就采用最低的阈值再采一次;
  • 把采取到的关键点坐标进行转换,之前是在小方格中的坐标系,现在要通过一些偏移操作转换到原图像下的坐标系;
  • 调用DistributeOctTree()函数对特征点进行均匀化(ORB-SLAM的精髓之一),关于四叉树均匀化特征点可以通过下面一幅图来表示;
四叉树均匀化特征点
  • 再进行一次坐标转换,这次是把提取到的关键点坐标转换为金字塔划分那一步的扩展图像的坐标;

干完这些事情后,又进行了一次遍历(写到这才发现这么多遍历,难怪速度比OpenCV的库函数慢)

  • 计算特征点的方向信息,调用IC_Angle()函数,通过一些小操作提高了一些速度。

计算描述子并进行金字塔图像特征恢复

这一步一上来又对每层金字塔进行了一次遍历,然后把每层金字塔的特征点个数累加存到了一个变量里,之后根据这个变量设置了描述子矩阵的容量。

再来一次遍历(已经麻了),这一步开始计算描述子

  • 首先对金字塔图像进行高斯模糊,因为BRIEF描述子对噪声敏感,所以要通过高斯模糊消除噪声对描述子的影响,这一步就是用到了之前的图像扩充。高斯模糊方法采用的OpenCV函数GaussianBlur()
  • 然后对每个关键点计算描述子,首先要根据之前计算得到的方向对坐标进行旋转,坐标对齐之后根据描述子模板进行描述子计算,保存到descriptors矩阵中;
  • 对于除第0层的图像(也就是最底下那一层),将所有的特征点乘相应层数的缩放因子,投射到最底层图像中,这样就实现了特征点的提取。

通过内参矩阵对特征点进行去畸变操作

内参系数在yaml文件中都给写好了,直接调用OpenCV的库函数undistortPoints()进行特征点去畸变操作。

将特征点分配到网格中

调用AssignFeaturesToGrid()