返回专辑
·Johan·4 分钟阅读

关键帧剔除与共视图:地图膨胀的刹车机制

讲清共视关系、冗余关键帧判定与局部 BA 窗口维护,避免地图无限膨胀拖垮后端实时性与回环路径完整性。

关键帧剔除与共视图:地图膨胀的刹车机制

1. 关键帧不是越多越好

机器人原地转圈 5 分钟,关键帧堆到 800 帧,Local BA 从 5 ms 涨到 200 ms,跟踪开始掉帧——这是我跑 ORB-SLAM 长轨迹时的教训。共视图与 keyframe culling 是视觉 SLAM 控制计算复杂度的核心机制,也是约束多样性 vs 冗余的杠杆。插入太松 → 算力爆炸;剔除太狠 → 重定位失败。

2. 关键帧插入条件

不是每一帧都进地图。插入通常需同时满足:距上一关键帧足够远(平移/旋转阈值);当前帧跟踪 OK(足够特征、足够内点);与已有共视关键帧的视差足够(保证三角化质量)。ORB-SLAM 的 NeedNewKeyFrame() 综合这些条件——参数 (maxFrames, minFrames, thStereo, thDepth) 决定插入频率。原地转圈时旋转阈值太小,共视帧大量冗余——这是 culling 要处理的典型场景。

3. 共视图(Covisibility Graph)

关键帧之间连边:共享 ≥ N 个地图点的关键帧对(N 通常 15)。共视图用于:

  • Local BA 窗口:当前帧的共视邻居 + 它们的邻居(2-hop)
  • Essential Graph:共视边 + 生成树边 + 回环边,用于 PGO
  • 重定位:在共视图中传播匹配

Local BA 不是「最近 N 帧」,而是共视邻域——时间上旧但共视多的帧仍参与优化。Essential Graph 是共视边的稀疏子集 + 生成树 + 回环边,PGO 在此稀疏图上跑,比全共视 BA 快一个量级。

4. 冗余关键帧判定与剔除

插入新关键帧后,检查已有帧是否可被「覆盖」。概念上冗余条件:

  1. 该帧 90%+ 地图点仍被 ≥3 其他关键帧观测
  2. 该帧与邻居的相对位姿变化 < 阈值
  3. 不在生成树的关键节点上(或剔除后仍连通)

ORB-SLAM 的 KeyFrameCulling() 在 Local BA 后执行——遍历 local keyframes,标记冗余并删除。删除不是简单 erase:更新地图点观测关系(只剩 1 个观测 → 删点);重连生成树(Spanning Tree);更新 Essential Graph 边;DBoW 数据库移除对应 entry——否则重定位 retrieve 到已删 frame 的 ghost id。

生成树断裂 → 回环/PGO 路径不完整 → 全局一致性退化。LOST 状态不要 aggressive cull——可能删掉重定位唯一依赖的老 keyframe;ORB-SLAM 在 LOST 时 essentially 停止 cull,fork 代码时确认 culling 与 tracking 状态机联动。

5. 真机调参与失败模式

参数影响
插入阈值松关键帧多 → 精度好但慢
插入阈值紧关键帧少 → 快但三角化弱
culling 激进可能删掉重定位需要的帧
culling 保守地图膨胀

插入和剔除阈值分开调——不要用一个参数两头堵。800 帧不 cull,DBoW 检索变慢、回环候选变多、误召回上升——culling 与回环召回是联动问题。

失败模式:误删导致重定位失败;从不剔除 → Local BA 窗口无限涨;剔除不更新 DBoW → ghost entry;原地转圈堆帧 → 关键帧数 vs 时间应 sublinear(不是线性涨)。

6. Local BA 窗口大小的定量关系

共视 2-hop 窗口大小 近似与当前场景可见地图点数成正比,Local BA 复杂度约 。插入阈值松 10%, 可能涨 30%——延迟非线性。我会画「运行时间 vs 关键帧总数」曲线:healthy 系统应 sublinear;线性涨说明 culling 失效或未启用。

VINS-Mono 的关键帧策略更保守(稀疏插入),ORB-SLAM 更密——选型时把 culling 行为算进算力预算,不是只看前端 FPS。

7. 验收

  • 关键帧总数 vs 运行时间(应 sublinear)
  • Local BA 耗时 vs 窗口大小
  • 被剔除关键帧数 / 原因分布
  • 平均每个地图点的观测关键帧数
  • 剔除后跟踪丢失率变化(A/B 对比)
  • Essential Graph 连通性(PGO 后无 islands)
  • DBoW entry 数与 keyframe 数一致(无 ghost)

关键帧管理是前端与后端的契约:插入保证约束足够,剔除保证算力可控,共视图决定 Local BA 优化谁。三者失衡,长轨迹要么算不动,要么丢跟踪。

← 全部文章

johan's blog