(二)ORB描述子提取源码思路与实现

ORBSLAM2中ORB特征提取的特点


    ORBSLAM2中通过对OpenCV中的ORB特征点提取类进行修改,对图像进行分块提取,而后划分节点,使得每个节点中保存的特征点性能是该节点所有特征点中最好的。

  可能按照上面说的方式,大家不太能理解。

  这么说吧。将铺满苹果的桌子进行画格子,然后每个格子中就会有不同数量的苹果,在每个格子中选出最好吃的苹果,格子中其他的苹果全部扔掉。(虽然有点可惜,但是大局为重嘛),那么原先摆满苹果的桌子(如图1所示),现在就剩下每个格子一个苹果的桌子,尽管苹果少了很多,但是剩下的都是精英,极品(如图2所示)。

  

       

  根据上面的类比,还有我那抽象派的苹果,应该可以对ORBSLAM2中的ORB特征提取做的事情有个大概的了解。

  这里需要提一下的是原生态的ORB特征提取的方法,他主要是通过阈值条件选出所有满足条件的ORB描述子,然后计算所有描述子的响应强度并排序M,根据输入要求的特征点数量N,取M中前N个描述子,即响应值最大的前N个描述子。显然,这种提取的方法会导致特征点的分布非常不均匀。而这也会影响到SLAM系统中定位的精度。文末在实现源码的时候会给大家看看两种方法提取特征的结果。


 ORB特征提取的源码流程

  ORB描述子的提取流程:

  1. 输入图像,并对输入图像进行预处理,将其转换成灰度图像;

  2. 初始化参数,包括特征点数量nfeatures,尺度scaleFactor,金字塔层数nlevel,初始阈值iniThFAST,最小阈值minThFAST等参数;

  3. 计算金字塔图像,源码中使用8层金字塔,尺度因子为1.2,则通过对原图像进行不同层次的resize,可以获得8层金字塔的图像;

  4. 计算特征点:

    1)将图像分割成网格,每个网格大小为W*W=30*30像素;

    2)遍历每个网格;

    3)对每个网格提取FAST关键点,先用初始阈值iniThFAST提取,若提取不到关键点,则改用最小阈值minThFAST提取。(注意,初始阈值一般比最小阈值大)

  5. 对所有提取到的关键点利用八叉树的形式进行划分:

    1)按照像素宽和像素高的比值作为初始的节点数量,并将关键点坐标落在对应节点内的关键点分配入节点中;

    2)根据每个节点中存在的特征点数量作为判断依据,如果当前节点只有1个关键点,则停止分割。否则继续等分成4份;

    3)按照上述方法不断划分下去,如图3所示,可见出现一个八叉树的结构,终止条件是节点的数目Lnode大于等于要求的特征点数量nfeatures;

    4)对满足条件的节点进行遍历,在每个节点中保存响应值最大的关键点,保证特征点的高性能;

  6. 对上述所保存的所有节点中的特征点计算主方向,利用灰度质心的方法计算主方向,上一讲中我们已经讲解过方法,这讲就不再赘述了;

  7. 对图像中每个关键点计算其描述子,值得注意的是,为了将主方向融入BRIEF中,在计算描述子时,ORB将pattern进行旋转,使得其具备旋转不变性;

    

  综上,ORB描述子提取的方法已经讲解完毕了。现在就是上源码了。由于许多人都对源码进行过注释,本文就直接上github:https://github.com/yepeichu123/orbslam2_learn的链接给大家,笔者是在ubuntu14.04 + opencv3.2的环境下运行的,已经实测可以运行。另外,本文还对比了ORB分网格提取和原始方法提取的异同,具体如图4所示。可以看见,分网格提取,特征点质量更好,分布也更均匀,对于SLAM问题的跟踪和三角化等能实现更鲁邦的效果。

 


 总结

  这一讲我们讲解了ORBSLAM2中,ORB的分块提取源码是如何实现的,并且分析了分块提取和原生态的ORB之间的对比;

  另外,本文还将源码进行单独实现,提供了一个github的源码,给大家练手。

 PS:

  如果您觉得我的博客对您有所帮助,欢迎关注我的博客。此外,欢迎转载我的文章,但请注明出处链接。

  对本文有任何问题可以在留言区进行评论,也可以在泡泡机器人论坛:http://paopaorobot.org/bbs/index.php?c=cate&fid=1中的SLAM技术交流模块发帖提问。

  

  

 

posted @ 2018-12-08 14:50  小C酱油兵  阅读(4292)  评论(0编辑  收藏  举报