VSLAM系列原创05讲 | 单目初始化中如何进行特征匹配?原理+代码
原文链接:https://mp.weixin.qq.com/s/1jX5cfvMHLzuXsX7DB7Qdg
本文系ORB-SLAM2原理+代码实战系列原创文章,对应的视频课程见:
如何真正搞透视觉SLAM?
大家好,从今天开始我们陆续更新ORB-SLAM2/3系列的原创文章,以小白和师兄对话的形式阐述背景原理+代码解析,喜欢的点个赞分享,支持的人越多,更新越有动力!如有错误欢迎留言指正!
代码注释地址:
https://github.com/electech6/ORB_SLAM2_detailed_comments
VSLAM系列原创01讲 | 深入理解ORB关键点提取:原理+代码
VSLAM系列原创02讲 | ORB描述子如何实现旋转不变性?原理+代码
VSLAM系列原创03讲 | 为什么需要ORB特征点均匀化?
VSLAM系列原创04讲 | 四叉树实现ORB特征点均匀化分布:原理+代码
接上回继续。。。
ORBSLAM2中的特征匹配
小白:师兄,ORB-SLAM2里有很多种特征匹配函数,看的我眼花缭乱,为什么有这么多种呢?怎么决定什么时候用哪一种特征匹配方法呢?
师兄:确实是比较多,但是基本思想是类似的,而且很多函数多次重载。我把特征匹配的几个重要函数都列出来,做了说明,见下:
下面选择几个典型代码进行分析。
单目初始化中的特征匹配
师兄:单目初始化时,没有任何的先验信息如何进行特征匹配呢?
小白:我能想到的就是暴力匹配了。。。
师兄:暴力匹配缺点太多了,比如:
效率极低。单目初始化时提取的特征点是平时跟踪的好几倍,ORB-SLAM2里是2倍,ORB-SLAM2里最高达到了5倍,若采用暴力匹配计算量会指数级上升,无法接受。
效果不好。花那么大的代价去匹配,如果效果好也就忍了,可事与愿违,因为是“毫无目的”的匹配,所以误匹配非常多。
因此用“吃力不讨好”来形容暴力匹配太适合不过了。如果我们能找到一些先验信息,哪怕不那么准确的先验信息,加以利用,就能大大缓解上述情况。
在ORB-SLAM2的单目纯视觉初始化里的思路是这样的,参与初始化的两帧我们默认是比较接近的,也就是说,我们在第1帧提取的特征点坐标对应的第2帧里的位置附近画一个圆,匹配点应该就落在这个圆里。
如下图所示,假设第1帧中提取到的某个特征点坐标为,我们在第2帧同样坐标(圆心)附近画一个半径为的圆,所有在这个圆内的特征点(圆内红色的点)都是候选的匹配特征点,然后再用和所有的候选匹配点进行匹配,找到满足如下条件的特征点就认为是完成了特征匹配:
条件1:遍历候选匹配点里最优和次优的匹配,最优匹配对应的描述子距离比次优匹配对应的描述子距离小于设定的比例。
条件2:最优匹配对应的描述子距离小于设定的阈值。
条件3:经过方向一致性检验。
如何快速确定候选匹配点?
师兄:上面提到了需要先确定候选匹配点,由于初始化时无法知晓相机的运动大小,所以确定候选匹配点时搜索圆半径会设置的相对比较大(代码里半径为100个像素)。你算下大概有多少像素?
小白:我简单算了下,约有 个像素,哇!这个区域挺大了啊!
师兄:是的,这样虽然比暴力匹配缩小了范围,但是索引的像素区域也是比较大的,如果逐像素匹配代价也非常大。
小白:ORB-SLAM2肯定采取了什么方法来加速吧?
师兄:是的,方法就是划分网格。这个在提取完特征点后就已经顺手将特征点划分为不同的网格并记录在mGrid里。在这里就派上了用场。如下图所示,搜索的时候是以网格为单位进行搜索的,代码里网格尺寸默认是,这样圆里包含的网格数目就大大减少。具体过程如下:
我们先根据圆的范围确定圆的上下左右边界分别在哪个网格内。图中圆的边界在水平坐标轴上的坐标范围是mMinCellX~mMaxCellX,在垂直坐标轴上的坐标范围是mMinCellY~mMaxCellY。mnMinX是图像的左侧边界对应的像素坐标。
遍历圆形区域内所有的网格。如果某个网格内没有特征点,那么直接跳过;如果某个网格内有特征点(见下图中绿色方框),遍历这些特征点,判断这些特征点是否符合要求的金字塔层级,是否在圆内,如果满足条件会把该特征点作为候选特征点。这种方式大大提高了搜索效率。

快速搜索候选匹配点的代码见:
(左右滑动看完整代码)
方向一致性检验
师兄:经过上面条件1、2的检验后,我们还要做方向一致性检验。因为通过特征点匹配后的结果仍然可能不一定准确,我们需要剔除掉其中的错误匹配。原理是统计两张图像所有匹配对中两个特征点主方向的差,构建一个直方图。由于两张图像整体发了运动,所以特征点匹配对主方向整体会有一个统一一致的变化,我们认为直方图里前三个最大的格子(代码里称为bin)里就是正常的匹配点对,那些误匹配的特征点对此时就会暴露了,会落在直方图上述之外的其他格子里,这些就是需要剔除的错误匹配。
我们举个可能不是很恰当的例子来类比一下,军训时所有人都站的笔直,教官下令“向左转”,此时大部分人都能正确的向左转90°左右,当然大家转动的幅度可能不同,但基本都朝着同一个方向旋转了80°~100°左右,这就相当于我们前面说的直方图里前三个最大的格子。但可能会有少量分不清左右的人向右转或者干脆不转,此时他们相对之前的旋转角度可能是-90°或0°,因为这样的人很少,对应直方图频率就很低,角度变化就不在直方图前三大的格子里,就是需要剔除的对象。
下图(a)是初始的特征匹配对,(b)是经过方向一致性验证后删除的特征匹配对。我们可以看到明显错误匹配对被剔除了。

源码解析
这部分代码见:
(左右滑动看完整代码)
欢迎支持独家视频课程:如何真正搞透视觉SLAM?
微信扫描二维码查看、购买、学习课程:

如果想要求拼团,或对课程有任何疑问,欢迎加入咨询群!

专辑:计算机视觉方向简介
专辑:视觉SLAM入门
专辑:最新SLAM/三维视觉论文/开源
专辑:三维视觉/SLAM公开课
专辑:深度相机原理及应用
专辑:手机双摄头技术解析与应用
专辑:相机标定
专辑:全景相机