ORBSLAM2的匹配器ORBmatcher
主要是记录下相对容易忘的内容,不会写的很细
匹配器ORBmatcher
匹配器的目的是将A帧中的特征点与B帧中的特征点进行匹配,这样才能确定位姿与三角化地图点。除此之外,匹配器还负责融合地图点,这主要是在LocalMapping过程中融合重复地图点以及闭环后融合重复地图点。
最理想的匹配方式是暴力匹配,但是这过于耗时。为了降低开销,ORBSLAM2使用了多种方法来降低搜索范围,比如通过词袋、投影等方法来筛选区域。
另外,匹配基于目的还可以分为两类:
- 搜索匹配:两帧之间没有任何匹配点,比如初始化时以及当一个新的普通帧到达时
- 扩大匹配:两帧之间已经有了一些匹配点,但是为了后续优化准确性,需要把共视帧的地图点通过投影(sim3或pose)到当前帧,从而进一步得到更多的匹配点
搜索匹配
SearchByProjection(Frame &CurrentFrame, const Frame &LastFrame ...)
:一个普通帧到达,且恒速模型可用,用恒速模型预测当前普通帧的位姿,并基于此预测的位姿把前一阵匹配点对应的地图点投影到当前帧并在一定范围内搜索
SearchByBoW(KeyFrame *pKF, Frame &F ...)
:一个普通帧到达,但恒速模型不可用,转而使用关键帧跟踪或重定位,使用词袋匹配当前普通帧与关键帧的特征点SearchByBoW(KeyFrame *pKF1, KeyFrame *pKF2 ...)
:闭环矫正时,通过词袋搜索两个关键帧之间的匹配点,以用于初始计算两帧之间的Sim3
SearchForInitialization(Frame &F1, Frame &F2 ...
:单目初始化,与SearchByProjection
类似,但是由于不知道初始两帧的位姿,缺少了投影的步骤,转而在搜索时使用了一个较大区域来尽可能多的匹配特征点
扩大匹配
SearchByProjection(Frame &F, const std::vector<MapPoint *> &vpMapPoints ...)
:Tracking中用局部关键帧中的局部地图点投影到当前普通帧来扩大匹配SearchByProjection(Frame &CurrentFrame, KeyFrame *pKF ...)
:重定位时,将重定位候选关键帧的地图点投影到当前普通帧以扩大匹配SearchByProjection(KeyFrame *pKF, cv::Mat Scw, const std::vector<MapPoint *> &vpPoints ...)
:回环计算Sim3时,用已经粗略计算出来的Sim3把共视帧的地图点投影到当前帧,以扩大匹配来进行优化
SearchForTriangulation(KeyFrame *pKF1, KeyFrame *pKF2 ...)
:LocalMapping中为了三角化更多地图点,使用基础矩阵的极线约束,来进一步扩大匹配
SearchBySim3(KeyFrame *pKF1, KeyFrame *pKF2 ...)
:回环计算Sim3时,用计算好的Sim3把闭环候选关键帧的地图点投影到当前关键帧以扩大匹配
匹配步骤
用于匹配的函数虽然有很多,但是基本上大同小异,主要就是一些约束条件不一样,这里就以SearchByProjection
为例来简述匹配流程

1 | /** |
地图点融合
在LocalMapping会融合相邻帧中重复地图点,而在LoopClosing中,则需要融合闭环后潜在重复地图点。融合时需要比较两个地图点的相似性,所以这项任务也交给匹配器来完成。
融合思路其实比较简单:
- 首先判断地图点投影后是否在当前帧视野内,(与
isInFrustum
函数类似)主要涉及相机坐标系深度为正、像素坐标系在校正后有效区域内、地图点与光心的距离在有效区域内以及地图点方向与光心夹角小于一定阈值 - 然后判断当前地图点可能出现在金字塔的哪些层中,从而确定特征点的搜索范围
- 遍历匹配该区域内的特征点,并使用描述子距离和卡方检验来排除潜在的误匹配
- 通过上述步骤的特征点如果有地图点,则选一个较好的(被观测到次数更多的地图点);否则则为该特征点添加地图点
1 | /** |