K2E-B-S2-2 · Paper Note
ORB-SLAM2
- Description:ORB-SLAM2 论文与源码笔记 — 特征点法 SLAM 标杆,单目/双目/RGB-D 统一框架;三线程架构、近/远点分类、motion-only/local/full BA 残差体系、共视图/本质图、DBoW2 回环;含 KITTI/EuRoC/TUM 完整结果与源码解析
- My Notion Note ID:K2E-B-S2-2
- Created:2021-07-06
- Updated:2026-06-11
- License:转载欢迎:转载请注明作者 Yu Zhang 并附原文出处(yuzhang.io)
Table of Contents
- 1. Summary
- 2. Key Contributions
- 3. Method
- 4. Experiments & Results
- 5. Ablation & Discussion
- 6. Strengths / Limitations / Future Work
- 7. Code Walkthrough
- References
1. Summary
Title: ORB-SLAM2: an Open-Source SLAM System for Monocular, Stereo and RGB-D Cameras Authors: Raúl Mur-Artal, Juan D. Tardós Paper: arXiv:1610.06475 (IEEE T-RO 33(5), 2017) Github: raulmur/ORB_SLAM2
ORB-SLAM2 把初代单目 ORB-SLAM 扩展为单目 / 双目 / RGB-D 统一框架:输入预处理层把三种传感器统一成"立体关键点 + 单目关键点"两类观测,之后整个系统(跟踪、建图、回环)对传感器类型完全透明。全程稀疏特征 + BA,CPU 实时,不需要 GPU。
核心设计:三个并行线程(跟踪 / 局部建图 / 闭环)+ 闭环后第四线程做全局 BA;近点/远点分类(深度 < 40 倍基线为近点)决定一帧能否直接三角化;双目/RGB-D 下尺度可观,回环几何校验与位姿图从单目的 Sim(3) 退化为 SE(3) 刚体变换,没有尺度漂移。
结果上:KITTI 双目大多数序列相对平移误差 < 1%,作者称当时 KITTI 上最佳双目方案;EuRoC 双目 RMSE 厘米级;TUM RGB-D 上以纯稀疏 BA 胜过 ElasticFusion / Kintinuous / DVO-SLAM 等稠密/直接法 — 论文的论点:BA 比直接法或 ICP 更准,而且更省算力。另有轻量仅定位模式(已知地图下纯跟踪)支持长期复用地图。
2. Key Contributions
- 首个面向单目/双目/RGB-D 的开源 SLAM 系统,含回环、重定位、地图复用
- RGB-D 用 BA 而非 ICP/光度深度误差,精度更高且 CPU 即可实时
- 近/远双目点分类 + 利用单目观测:远点多视角三角化只约束旋转,近点单帧三角化给出尺度/平移
- 轻量仅定位模式:利用 VO 匹配 + 地图点匹配,在已建图区域零漂移定位(建图/回环线程停用)
- 双目/RGB-D 下回环用 SE(3) 位姿图(尺度可观,不再需要 Sim(3))
3. Method
3.1 三线程 + 第四线程架构

- 跟踪线程:每帧提 ORB → 双目/深度匹配 → motion-only BA 求位姿 → 局部地图跟踪 → 关键帧判定;跟丢则 DBoW2 重定位
- 局部建图线程:关键帧插入(共视图 + 生成树)→ 地图点剔除 → 三角化新点 → 邻域融合 → local BA → 冗余关键帧剔除
- 闭环线程:DBoW2 查询候选 → 几何校验(双目/RGB-D 用 SE(3))→ 闭环融合 → 本质图位姿图优化 → 启动第四线程
- 全局 BA 线程:闭环后异步全量优化;若期间检测到新回环则中止重启;结束后沿生成树把修正传播到 BA 期间新插入的关键帧
3.2 输入预处理 — 三种传感器统一

- 双目:左右校正图各提 ORB,左目特征沿水平极线在右目找匹配(块相关亚像素精确定位)→ 立体关键点
- RGB-D:RGB 图提 ORB,由深度 合成虚拟右目坐标:
符号: 为特征在 RGB(左)图的横坐标, 为合成的虚拟右目横坐标; 为水平焦距, 为传感器深度值; 为结构光投射器与红外相机的基线(Kinect/Asus Xtion 约取 8 cm)。之后 RGB-D 与双目在系统内完全等价。
- 单目关键点 :无立体匹配或深度无效的特征 — 只能多视角三角化,不提供尺度
近点 / 远点:深度 < 40× 基线 → 近点(单帧即可三角化,约束尺度/平移/旋转);否则远点(需多视角,主要约束旋转)。阈值 40 来自 Paz et al. 的经验结论。

系统自举:双目/RGB-D 首帧直接建关键帧 + 由全部立体点出图 — 不需要单目那套两帧 H/F 初始化。
3.3 BA 残差体系
三个层级共用同一重投影残差,只在优化变量范围上不同。
Motion-only BA(跟踪线程,每帧):只优化当前帧 ,地图点固定:
符号: 为相机位姿; 为世界系 3D 地图点, 为其观测(单目 2 维 / 立体 3 维); 为本帧全部 3D-2D 匹配; 为 Huber 鲁棒核, 按关键点金字塔层级取协方差。投影 按单目/立体二选一:
符号: 为相机系 3D 点; 为焦距, 为主点, 为双目基线; 输出 2 维像素坐标, 额外输出虚拟右目横坐标(第 3 维)。立体观测是 3 维()— 这也是后面卡方阈值单目 5.991(2 自由度)、立体 7.815(3 自由度)的来源。
Local BA(局部建图线程):优化共视窗口 内关键帧与其全部地图点 ;能观测这些点但不在窗口内的关键帧 参与残差但固定不动:
符号: 为当前关键帧的共视窗口(待优化), 为窗口内观测到的全部地图点(待优化); 为窗口外但能观测 的关键帧(固定); 为关键帧 与 的匹配集; 与式 (2) 同形。
Full BA(闭环后):式 (4) 的特例 — 所有关键帧和点都优化,仅固定原点关键帧消除规范自由度。
3.4 共视图 / 生成树 / 本质图 + DBoW2
- 共视图:关键帧为节点,共视地图点 ≥ 15 连边,权重 = 共视点数 — 局部窗口与局部地图都从这取
- 生成树:每帧只连共视最高的父关键帧 — 全局 BA 后修正沿它传播
- 本质图:生成树边 + 闭环边 + 强共视边( 共视点)— 位姿图优化在这上面做,比全共视图稀疏得多
- DBoW2 词袋(ORB 二进制描述子 + TF-IDF):重定位 + 闭环检测两用;闭环候选需连续 3 次共视一致性确认
3.5 闭环 — SE(3) 替代 Sim(3)
单目 ORB-SLAM 闭环要解 Sim(3)(7 DoF,吸收尺度漂移)。ORB-SLAM2 双目/RGB-D 下尺度可观,几何校验与位姿图退化为 SE(3) 刚体变换 — 论文原话:不再需要处理尺度漂移。单目模式下仍走 Sim(3)(公式体系在初代论文中,相似变换见 几何变换层级 §3):
符号: 为尺度因子, 为旋转, 为平移 — Sim(3) 比 SE(3) 多出的正是尺度这 1 个自由度。
本质图位姿图优化(最小化所有边的相对位姿误差):
:约束的帧间相对变换(闭环边或共视边测量,相机坐标系 );:待优化关键帧相机到世界位姿;:SE(3)/Sim(3) 群到李代数的对数映射;双目/RGB-D 用 SE(3)(6 维),单目用 Sim(3)(7 维,含尺度);g2o 求解。
闭环流程:候选检测(BoW 得分 > 共视帧最低分 ,连续性检查)→ BoW 粗匹配 ≥ 20 对才进 Sim3/SE3 RANSAC → 引导投影匹配加边(总匹配 ≥ 40 接受)→ 闭环融合(重复地图点合并)→ 本质图优化 → 全局 BA。
3.6 关键帧策略
- 插入(比初代更激进,"插得快、删得狠"):除常规条件外新增双目/RGB-D 条件 — 跟踪的近点 < 且本帧可新建近点 ≥ → 立即插入。KITTI 01 这类高速远景序列全靠它保住平移精度
- 剔除:某关键帧 ≥ 90% 的地图点能被至少 3 个其他关键帧在相同或更精细金字塔层级观测时,判为冗余并删除
3.7 仅定位模式
建图与闭环线程停用,跟踪线程混用两类匹配:
- VO 匹配:当前 ORB ↔ 上一帧由立体/深度新建的临时 3D 点 — 未建图区域也能跟,但会漂移
- 地图点匹配:当前 ORB ↔ 既有地图 — 零漂移定位
环境无显著变化时可长期复用地图,跟丢用 DBoW2 重定位。
4. Experiments & Results
评测设置:Intel i7-4790 + 16GB,每序列跑 5 次取中位数(补偿多线程不确定性)。
4.1 KITTI 双目(论文 Table I,节选)
指标:相对平移 (%) / 相对旋转 (°/100m) / 绝对平移 RMSE (m),对比 Stereo LSD-SLAM(直接法半稠密双目 SLAM,最小化光度误差,Engel 2015):
| Seq | ORB-SLAM2 | LSD | LSD | ||
|---|---|---|---|---|---|
| 00 | 0.70 | 0.25 | 1.3 | 0.63 | 1.0 |
| 01 (高速) | 1.39 | 0.21 | 10.4 | 2.36 | 9.0 |
| 05 | 0.40 | 0.16 | 0.8 | 0.64 | 1.5 |
| 08 (无回环) | 1.05 | 0.32 | 3.6 | 1.11 | 3.9 |
| 09 | 0.87 | 0.27 | 3.2 | 1.14 | 5.6 |
- 多数序列 ,11 条序列大面积优于 Stereo LSD-SLAM
- 01 高速公路:近点稀缺 → 平移 1.39% 偏弱但旋转 0.21°/100m 仍准(远点撑住旋转);单目版在此序列直接失败,双目版能跑:双目消除尺度漂移的直接证据(KITTI 08 对比图见论文 Fig. 5)
- 回环检出:00/02/05/06/07;09 的回环只在末尾几帧,漏检
4.2 EuRoC 双目(论文 Table II,节选)
绝对平移 RMSE (m):
| Sequence | ORB-SLAM2 | Stereo LSD-SLAM |
|---|---|---|
| V1_01_easy | 0.035 | 0.066 |
| V1_02_medium | 0.020 | 0.074 |
| V1_03_difficult | 0.048 | 0.089 |
| MH_04_difficult | 0.119 | — |
| V2_03_difficult | ✗ 跟丢 | — |
厘米级精度;V2_03 因剧烈运动模糊跟丢(论文注:需 IMU,即后来 ORB-SLAM3 的方向)。
4.3 TUM RGB-D(论文 Table III,节选)
绝对平移 RMSE (m),对比稠密/直接法(ElasticFusion:GPU 稠密面元地图 + 无回环 ICP;Kintinuous:KinectFusion 滚动体素稠密重建;DVO-SLAM:直接视觉里程计 + 图优化):
| Sequence | ORB-SLAM2 | ElasticFusion | Kintinuous | DVO-SLAM |
|---|---|---|---|---|
| fr1/desk | 0.016 | 0.020 | 0.037 | 0.021 |
| fr2/desk | 0.009 | 0.071 | 0.034 | 0.017 |
| fr2/xyz | 0.004 | 0.011 | 0.029 | 0.018 |
| fr3/office | 0.010 | 0.017 | 0.030 | 0.035 |
稀疏 BA 全面胜过稠密方案且不需要 GPU。fr2 序列深度图有 4% 尺度偏差,已补偿。ORB-SLAM2 本身不做深度融合 — 稠密点云仅由关键帧位姿反投影深度图可视化:

4.4 耗时(论文 Table IV,节选)
| 线程/任务 | EuRoC V2_02 (双目 20Hz, 1200 特征) | KITTI 07 (双目 10Hz, 2000 特征) | TUM fr3 (RGB-D 30Hz, 1000 特征) |
|---|---|---|---|
| 跟踪总耗时 | 41.7 ms | 49.5 ms | 25.6 ms |
| 其中 ORB 提取 | 13.5 | 24.8 | 11.5 |
| Local BA | 138 ms | 69 ms | 197 ms |
| 本质图优化 (单次) | 73 ms | 178 ms | 282 ms |
| Full BA (单次) | 349 ms | 1144 ms | 1641 ms |
跟踪均满足实时(< 帧间隔);Local BA 在独立线程不阻塞跟踪;Full BA 秒级但异步。注意 fr3_office 共视图比 KITTI 07 更稠密(室内反复观测),回环融合/BA 反而更贵 — 耗时由图的连接密度而非关键帧数决定。
5. Ablation & Discussion
论文没有正式消融实验:无"去掉近/远点分类/共视图"的对照表。可讨论的设计依据:
- 为什么 BA 赢了直接法/ICP:作者论点 — 稀疏特征 + 多视角 BA 在精度上优于光度/深度稠密对齐,且计算便宜得多(全 CPU);TUM Table III 是直接证据
- 近/远点分类为什么重要:KITTI 01 显示远点只约束旋转;没有 激进插帧,高速场景平移会崩
- SE(3) vs Sim(3):尺度可观时少 1 个自由度,位姿图更稳 — 但这是结构性结论,论文没有定量对比
- 局限场景:剧烈运动模糊(V2_03)、纹理缺失场景 — 特征点法的固有边界
6. Strengths / Limitations / Future Work
Strengths:
- 单目/双目/RGB-D 一套架构,输入预处理后传感器透明
- CPU 实时 + 高精度,三大数据集当时 SOTA
- 完整系统:回环、重定位、地图复用、仅定位模式 — 工程参考价值极高
Limitations:
- 特征点法边界:运动模糊 / 弱纹理跟丢(V2_03 失败)
- 仅稀疏地图,无稠密融合(ElasticFusion 在个别结构化场景反超,如 fr3/nst)
- 仅定位模式要求环境无显著变化
- 无地图序列化 — 地图只活在内存里(官方代码无 Save/Load)
Future Work(论文原文):非重叠多相机、鱼眼/全景支持、大规模稠密融合、协同建图、运动模糊鲁棒性:其中 IMU 与多地图由 ORB-SLAM3(2021)实现。
7. Code Walkthrough
官方 C++ 实现,依赖 OpenCV / Eigen3 / Pangolin / g2o(通用图优化库,用稀疏非线性最小二乘求解位姿/地图点)/ DBoW2(后两者 vendored 在 Thirdparty/)。
7.1 结构与线程
| 文件 | 职责 |
|---|---|
System.cc |
构造并接线全部子系统;暴露 TrackStereo/RGBD/Monocular |
Tracking.cc |
每帧位姿估计状态机(调用线程内运行) |
LocalMapping.cc |
关键帧处理、三角化、Local BA(独立线程) |
LoopClosing.cc |
回环检测、Sim3/SE3、位姿图(独立线程) |
ORBextractor.cc |
金字塔 + FAST + 四叉树均匀化 |
Optimizer.cc |
g2o 封装:PoseOptimization / LocalBA / EssentialGraph / Sim3 / GlobalBA |
KeyFrame.cc / MapPoint.cc / Map.cc |
共视图、生成树、观测管理 |
System 构造:加载词典 → 建 Tracking(主线程)→ new thread(&LocalMapping::Run, ...) → new thread(&LoopClosing::Run, ...);线程间用互斥队列传关键帧,后台线程 usleep 自旋。
7.2 跟踪状态机
// Tracking::Track() 核心分发
if(mState==OK) {
CheckReplacedInLastFrame();
if(mVelocity.empty() || mCurrentFrame.mnId < mnLastRelocFrameId+2)
bOK = TrackReferenceKeyFrame(); // BoW 匹配参考关键帧
else {
bOK = TrackWithMotionModel(); // 恒速模型投影匹配 (首选)
if(!bOK) bOK = TrackReferenceKeyFrame();
}
} else {
bOK = Relocalization(); // DBoW2 候选 + EPnP RANSAC
}
if(bOK) bOK = TrackLocalMap(); // 局部地图投影 + 再优化
- 恒速模型优先;重定位后两帧内速度不可信,退回 BoW 匹配
Relocalization:候选帧 ≥ 15 BoW 匹配后进PnPsolver(EPnP RANSAC,算法见 PnP §4),位姿优化 ≥ 50 内点确认TrackLocalMap:共视关键帧 + 父子帧组成局部地图,投影筛点(视深/视角/尺度)后再做一次 motion-only BA
7.3 PoseOptimization — 4 轮卡方筛选
const float chi2Mono[4] = {5.991, 5.991, 5.991, 5.991}; // χ²(2) 95%
const float chi2Stereo[4] = {7.815, 7.815, 7.815, 7.815}; // χ²(3) 95%
for(size_t it=0; it<4; it++) {
optimizer.optimize(10);
for (每条边) {
if(chi2 > th) { e->setLevel(1); outlier = true; } // 踢出但不删除
else { e->setLevel(0); outlier = false; } // 回到阈内可复活
if(it==2) e->setRobustKernel(0); // 第 3 轮后撤掉 Huber
}
}
工程要点:外点用 setLevel(1) 非破坏性禁用,后续轮次若回到阈值内会被重新启用 — 论文只写"鲁棒优化",这套 4×10 轮 + 复活机制全在代码里。
7.4 ORB 提取 — 四叉树均匀化
- 金字塔 8 层 × 1.2 倍,各层特征数按几何级数分配
- 每层 30×30 px 网格跑 FAST(
iniThFAST=20,失败降到minThFAST=7) DistributeOctTree:不断四分裂节点直到节点数达标,每叶保留响应最大的点 → 空间均匀分布(名字叫 OctTree,实为 2D 四叉树)- 单目初始化阶段用 2× 特征数的专用提取器提高配对成功率(论文未提)
7.5 立体深度与近/远阈值
// Frame::ComputeStereoMatches —— 视差转深度
float disparity = uL - bestuR;
mvDepth[iL] = mbf / disparity; // depth = fx·b / d
// RGB-D:虚拟右目 mvuRight[i] = u - mbf/d (即式 (1))
ThDepth 从 yaml 读入,近/远边界 = mbf/fx × ThDepth(≈ ThDepth 倍基线)。
7.6 关键 yaml 参数
| 参数 | KITTI00-02 | EuRoC (双目) | TUM1 (RGB-D) |
|---|---|---|---|
nFeatures |
2000 | 1200 | 1000 |
scaleFactor / nLevels |
1.2 / 8 | 1.2 / 8 | 1.2 / 8 |
iniThFAST / minThFAST |
20 / 7 | 20 / 7 | 20 / 7 |
ThDepth |
35 | 35 | 40 |
Camera.fps |
10 | 20 | 30 |
DepthMapFactor |
— | — | 5000 (uint16 → m) |
7.7 Paper-vs-Code 差异
| # | 差异 | 说明 |
|---|---|---|
| 1 | 近/远阈值 | 论文写 40× 基线;KITTI yaml 实际 ThDepth=35 |
| 2 | 4 轮卡方 + 外点复活 | 论文只说鲁棒优化,机制全在代码 |
| 3 | 四叉树均匀化 | 论文只说"均匀分布",DistributeOctTree 未描述 |
| 4 | 单目初始化 2× 特征 | 论文未提 |
| 5 | 仅定位模式实现 | mbOnlyTracking + mbVO 回退逻辑,论文只有一段描述 |
| 6 | 无地图保存 | 论文讲"地图复用",官方代码无序列化(社区 fork 补) |
| 7 | GlobalBundleAdjustemnt |
原版代码函数名拼写错误(少个 e),非 fork 引入 |
References
| 资源 | 链接 |
|---|---|
| ORB-SLAM2 论文 | arXiv:1610.06475, IEEE T-RO 2017 |
| 官方代码 | raulmur/ORB_SLAM2 |
| 初代 ORB-SLAM (单目, Sim3/共视图体系) | Mur-Artal, Montiel & Tardós, IEEE T-RO 2015, arXiv:1502.00956 |
| ORB-SLAM3 (+IMU/多地图) | Campos et al., IEEE T-RO 2021 |
| DBoW2 | Gálvez-López & Tardós, IEEE T-RO 2012 |
相关笔记:ORB 特征见 特征描述子;EPnP 见 PnP;三角化见 三角化;Sim3 与尺度漂移见 几何变换层级;与 VINS-Mono(加 IMU 的优化派 VIO)、DSO(直接法)对照阅读。