ORB-SLAM3 SearchByBoW 1
int ORBmatcher::SearchByBoW(KeyFrame* pKF, Frame &F, vector<MapPoint*> &vpMapPointMatches)是ORB-SLAM3中一个核心的特征匹配函数,它利用词袋模型(BoW)加速当前帧F与关键帧pKF之间的特征点匹配,为后续的位姿优化提供高质量的3D-2D对应关系。
该函数通过只比较属于同一“视觉单词”(节点)的特征点,避免了全局的暴力搜索,从而在保证匹配质量的同时大幅提升了效率。它普遍应用于跟踪参考关键帧、重定位和闭环检测等多个关键环节。
🧠 函数工作原理:五大核心步骤
下面是该函数实现匹配的详细步骤流程:
步骤1:数据准备与对齐
函数首先会获取关键帧pKF中每个特征点对应的地图点(vpMapPointsKF),并为待匹配的当前帧F初始化一个空的匹配结果容器(vpMapPointMatches)。此处的关键数据是特征向量(FeatureVector):pKF->mFeatVec和F.mFeatVec,这是一个按词汇树节点ID(NodeId)索引特征点索引(vector<unsigned int>)的映射表。
步骤2:遍历相同节点内的特征点
通过同步遍历两个FeatureVector(KFit和Fit),算法只对那些拥有相同节点ID的组进行比较。这利用了词袋模型的核心思想:属于同一节点的特征点在视觉上是相似的,因此它们之间最可能产生正确匹配,从而排除了大量无关的组合。
步骤3:在节点内寻找最佳匹配
对于关键帧中一个有效的特征点,算法会在当前帧属于该节点的所有特征点中,计算它们ORB描述子之间的汉明距离。通过遍历,它会找出与关键帧特征点距离最近(bestDist1)和次近(bestDist2)的两个当前帧特征点。
步骤4:双重检验与接受匹配
一个候选匹配需要经过两重检验才能被接受,这能有效剔除误匹配:
距离阈值检验:最佳距离(
bestDist1)必须小于一个预先设定的低阈值(TH_LOW)。这确保了特征点在描述子层面足够相似。最近邻比率检验:最佳距离必须显著小于次佳距离,即满足
bestDist1 < mfNNratio * bestDist2。这确保了该匹配是“独特”的,没有其他模糊的候选点。
步骤5:旋转一致性检验(粗筛)
为了进一步剔除不符合物理规律(图像旋转)的误匹配,函数会统计所有通过上述检验的匹配对的特征点主方向角度差,并构建一个30 bin的直方图(rotHist)。在步骤的最后,函数会找出直方图中数量最多的三个bin(代表主流旋转方向),然后剔除所有不落在这三个bin内的匹配对。
💻 核心代码逻辑框架
cpp
int ORBmatcher::SearchByBoW(KeyFrame* pKF, Frame &F, vector<MapPoint*> &vpMapPointMatches) { // 1. 获取关键帧的地图点和特征向量 const vector<MapPoint*> vpMapPointsKF = pKF->GetMapPointMatches(); const DBoW2::FeatureVector &vFeatVecKF = pKF->mFeatVec; vpMapPointMatches = vector<MapPoint*>(F.N, nullptr); // 初始化直方图用于旋转一致性检验 vector<int> rotHist[30]; // ... // 2. 同步遍历两个特征向量 (FeatureVector) DBoW2::FeatureVector::const_iterator KFit = vFeatVecKF.begin(), Fit = F.mFeatVec.begin(); while (KFit != vFeatVecKF.end() && Fit != F.mFeatVec.end()) { if (KFit->first == Fit->first) { // 属于同一节点 // 3. 在该节点内部进行特征点匹配 for (size_t iKF=0; iKF<vIndicesKF.size(); iKF++) { // 提取关键帧特征点对应的地图点和描述子 // 在当前帧的同一节点内遍历,寻找最佳匹配 (bestDist1) 和次佳匹配 (bestDist2) // 4. 决策:如果 bestDist1 满足阈值和比率检验,则接受匹配 if (bestDist1 <= TH_LOW && bestDist1 < mfNNratio * bestDist2) { // 记录匹配,并记录角度差到直方图 } } KFit++; Fit++; } else if (KFit->first < Fit->first) { KFit = vFeatVecKF.lower_bound(Fit->first); } else { Fit = F.mFeatVec.lower_bound(KFit->first); } } // 5. 利用直方图进行旋转一致性检验,剔除不符合主流旋转的匹配 // ... return nmatches; // 返回成功匹配的数量 }🎯 应用场景
TrackReferenceKeyFrame:在恒速模型跟踪失效时,通过此函数匹配当前帧和参考关键帧,以估计当前帧位姿。
Relocalization:在系统跟踪丢失时,利用此函数将当前帧与
DetectRelocalizationCandidates找到的候选关键帧进行匹配,为MLPnP等位姿估计算法提供初始3D-2D对应关系。Loop Closing:在闭环检测中,用于匹配当前关键帧和候选闭环关键帧,验证闭环的正确性。
💎 总结
该函数是ORB-SLAM3系统高效运行的关键。它通过词袋模型的索引能力,将复杂的特征匹配问题简化为仅在视觉相似的局部节点内进行的快速搜索,并配以比率检验和旋转一致性检验来保证匹配质量,为系统在各种严苛条件下保持稳健的跟踪和建图能力提供了坚实基础。