ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

第247篇 ORB-SLAM2深度解析——经典视觉SLAM的完整架构

2026/8/24 16:04:54 拓冰建站 浏览量
第247篇 ORB-SLAM2深度解析——经典视觉SLAM的完整架构 从这篇开始我们进入经典SLAM系统解析。ORB-SLAM2是视觉SLAM领域最具影响力的系统之一面试中被问到的频率极高。不管你做不做视觉SLAM面试官都可能问你ORB-SLAM2的架构细节。能讲清楚ORB-SLAM2的三个线程、关键帧策略、回环检测流程基本就能证明你对SLAM有深入理解。ORB-SLAM2由Zaragoza大学的Raúl Mur-Artal开发支持单目、双目和RGB-D三种相机模式。它的精度和鲁棒性在当时的视觉SLAM系统中是最好的代码质量也很高是学习SLAM架构的最佳范本。在TUM、EuRoC等标准数据集上ORB-SLAM2的精度比同时期的其他系统高出至少一个量级。三大线程架构ORB-SLAM2的核心架构是三个并行线程跟踪线程Tracking处理每一帧图像。提取ORB特征和地图中的路标点匹配用PnP求解当前帧的位姿。决定是否插入关键帧。这个线程必须实时运行每帧的处理时间不能超过相机帧间隔。局部建图线程LocalMapping处理新插入的关键帧。为关键帧的新特征点三角化出3D路标点用局部BA优化关键帧及其共视帧的位姿和路标点剔除冗余的关键帧和路标点。回环检测线程LoopClosing检测是否回到了之前经过的地方。如果检测到回环计算当前帧和回环帧之间的Sim3变换带尺度的相似变换然后做全局位姿图优化消除累积误差。# 三大线程的协作伪代码 class ORBSLAM2: def run(self): while True: frame camera.get_frame() # 跟踪线程 pose tracking.track(frame) if is_keyframe(frame): local_mapping.insert_keyframe(frame) # 局部建图线程异步 local_mapping.process_new_keyframe() local_mapping.cull_redundant_keyframes() # 回环检测线程异步 if loop_closing.detect_loop(): loop_closing.correct_loop()三个线程通过关键帧队列和位姿队列来通信。跟踪线程把新关键帧放入队列局部建图线程从队列取出处理。回环检测线程独立运行只在检测到回环时通知其他线程。这种多线程设计的好处是跟踪线程不会被耗时的建图和优化操作阻塞保证了实时性。代价是线程之间需要 careful 的同步ORB-SLAM2用mutex来保护共享数据地图、关键帧队列等。如果线程同步没做好会出现数据竞争和死锁问题。关键帧选择策略不是每帧都是关键帧。关键帧太多会增加计算量太少会导致跟踪丢失。合理的关键帧选择是SLAM系统稳定运行的关键。ORB-SLAM2的关键帧选择策略局部建图线程忙还没处理完上一个关键帧时不插入新关键帧。距离上一个关键帧过了20帧以上必须插入一个。回环检测线程刚做完回环校正不插入。当前帧能观测到的路标点数量少于参考关键帧的90%插入。这个策略保证了关键帧的密度适中既不会太密浪费计算资源也不会太稀疏导致跟踪丢失。实际运行中ORB-SLAM2的关键帧频率大约是5-10Hz取决于场景的运动速度和纹理丰富度。运动快的时候关键帧更密运动慢的时候更稀。这个自适应的策略比固定帧率插入关键帧要合理得多。共视图和本质图ORB-SLAM2用共视图Covisibility Graph来组织关键帧之间的空间关系。两个关键帧如果观测到了同一个路标点它们之间就有一条边边的权重就是共视路标点的数量。本质图Essential Graph是共视图的简化版本只保留权重超过阈值通常100个共视点的边和生成树边。回环检测触发后位姿图优化在本质图上进行计算量比在完整共视图上小得多。地图结构ORB-SLAM2的地图由关键帧和路标点组成。每个关键帧存储ORB特征点带描述子、位姿、共视关系。每个路标点存储3D坐标、观测方向、描述子、被哪些关键帧观测到。路标点的质量管理很重要。ORB-SLAM2会剔除那些被太少关键帧观测到的路标点观测次数3以及投影误差大的路标点。这些冗余的路标点如果不及时剔除会拖慢BA的速度还可能引入错误约束。地图的规模控制也很关键。ORB-SLAM2的地图会随着运行时间不断增大。虽然局部BA只优化局部变量但地图的路标点数量增长会影响匹配搜索的效率。ORB-SLAM3引入了多地图管理来解决这个问题后面会详细讲。初始化过程ORB-SLAM2的初始化是一个精心设计的流程。对于单目相机它同时计算本质矩阵E和单应矩阵H用RANSAC分别评估两者的内点数量选择内点更多的那个。然后从选中的矩阵中分解出R和t做三角化得到初始路标点。为什么同时计算E和H因为E在平面场景下不稳定H在非平面场景下不稳定。同时计算两者并选择效果更好的那个保证了在各种场景下都能成功初始化。双目和RGB-D相机的初始化更简单每个特征点都有深度信息直接三角化就行不需要E/H分解。所以双目和RGB-D的SLAM启动更快、更稳定这也是为什么实际产品中更倾向于用双目或RGB-D而不是单目。这一点在面试中经常被追问。面试高频追问ORB-SLAM2的跟踪线程有哪些模式 共三种模型跟踪有运动模型时用上一帧的速度预测当前位姿、共视关键帧跟踪模型跟踪失败时搜索共视关键帧的特征做匹配、重定位所有跟踪都失败时在全部关键帧中搜索匹配来重新定位。局部BA优化哪些变量 优化当前关键帧、它的共视关键帧、以及这些关键帧观测到的所有路标点。不优化不相关的历史帧这样计算量可控。为什么需要Sim3变换 单目SLAM的地图尺度不确定。回环检测发现回到原来的地方时两段轨迹的尺度可能不同。Sim3变换共7个自由度旋转3平移3尺度1能同时校正旋转、平移和尺度。ORB-SLAM2的缺点是什么 计算量比较大嵌入式平台跑起来吃力。地图是稀疏的只有特征点不能用于稠密避障。纯视觉方案在快速运动和光照变化下容易跟踪丢失。不支持地图的保存和加载ORB-SLAM3解决了这个问题。没有IMU融合纯视觉方案在尺度漂移方面表现不好。ORB-SLAM2的回环检测用的什么方法 用DBoW2词袋模型。每个ORB描述子被量化成视觉单词关键帧用视觉单词的集合来表示。回环检测就是找当前帧和哪些历史关键帧的视觉单词集合最相似。如果相似度得分超过阈值就认为是候选回环。然后用几何验证计算Sim3变换来确认。关键帧的共视关系怎么建立 当一个关键帧被插入时它会和所有观测到相同路标点的历史关键帧建立共视关系。共视路标点的数量就是边的权重。随着更多关键帧的插入共视关系会不断更新。ORB-SLAM2怎么处理动态物体 它不处理。ORB-SLAM2假设场景是静态的。动态物体会产生误匹配导致跟踪失败。这是所有传统视觉SLAM的共同问题后来出现了很多动态SLAM的改进方案比如DynaSLAM用语义分割来剔除动态物体。ORB-SLAM2是视觉SLAM的里程碑理解了它的架构面试中关于SLAM系统的问题基本都能应对。建议你先下载ORB-SLAM2的源码在TUM数据集上跑一遍然后对着源码看三个线程的实现。阅读源码是理解SLAM系统最有效的方式比看论文和博客都管用。学习建议先看Tracking.cc理解跟踪线程的流程。然后看LocalMapping.cc理解局部BA和关键帧管理。最后看LoopClosing.cc理解回环检测和全局优化。每个文件大概1000-2000行C代码花两三天能通读一遍。上一篇第246篇 视觉SLAM后端之GTSAM——因子图优化的另一种方案下一篇我们聊ORB-SLAM3的新特性——多地图和多传感器融合。ORB-SLAM3在ORB-SLAM2的基础上做了很多重要改进是目前功能最完整的视觉SLAM系统支持视觉惯性融合、鱼眼相机模型和多地图管理。如果这篇文章对你有帮助欢迎点赞支持一下你的鼓励是我持续更新的最大动力