资讯动态

视觉里程计三十年发展史:从VO原理到SLAM工程实践详解

发布时间:2026/10/16 11:52:31 来源:尧图企业网站定制
做视觉定位这些年我发现自己被问得最多的一个问题不是“怎么标定相机”也不是“换哪种特征点”而是“VO到底是什么它和SLAM到底哪里不一样”。很多刚入门的同学抱着“我要做一个SLAM”的心态来找我结果折腾了半天真正落地的其实只是VO加了一个回环检测的外壳。这篇关于视觉里程计三十年发展史的综述把VO的定义、数学基础、技术演变和未来方向都梳理得很清楚。我读的时候做了不少批注后来在室内机器人、无人机悬停这些实际项目里反复验证过其中的结论现在把这份笔记整理出来。不管你是刚接触视觉定位的新手还是已经在SLAM领域写了不少代码的工程师这篇笔记应该都能帮你把VO这块的根基看得更透。1. 到底什么是视觉里程计它与SLAM差在哪1.1 里程计这个词是哪里来的“里程计”这个词最早是从轮式机器人那边借来的。轮式机器人想知道自己走了多远最简单的办法就是在轮子上装编码器数轮子转了多少圈再结合轮径算出行进距离。但这套方案在地面打滑、轮胎变形的时候就完全不可靠了。后来有人想既然人走路的时候可以靠眼睛判断自己移动了多少为什么机器人不能用相机来做同样的事于是就有了视觉里程计通过分析连续图像帧之间的变化估计相机也就是机器人本体的运动轨迹。它只关心短时间内的增量运动换句话说它解决的是“我从上一刻到现在到底往哪个方向动了多少”这个问题。论文里对这种增量式的运动估计做了明确界定——VO是连续帧之间的位姿估计而不是一次性对所有图像做联合优化。1.2 VO、SFM和SLAM的边界很多人会把VO和运动恢复结构SFM、SLAM混在一起说但它们的关注点其实完全不同SFM的目标是从一堆无序图像里重建出三维结构和相机位姿属于离线处理可以反复迭代优化追求全局最优。VO的目标是实时地、增量地估计相邻时间点之间的运动不要求全局一致性只要求局部准确。SLAM则是在VO的基础上往前再走一步不仅要估计轨迹还要维护一个全局一致的地图并且通过回环检测来修正累积漂移。所以从实现角度看VO完全可以当作SLAM的前端模块来用。很多SLAM系统里跑的那套帧间匹配和位姿估计本质上就是VO。那么问题来了既然SLAM更强论文为什么还要花几十页篇幅专门讲VO因为VO是SLAM里最基础、最容易出问题的部分——如果前端给的位姿就是偏的后面再怎么回环优化都救不回来。1.3 一个容易被忽略的边界条件论文里反复强调一个点VO的关键假设是相邻帧之间有足够的视差和重叠区域。这个假设看起来简单但在实际工程中它决定了一个VO系统能不能跑起来。比如相机做纯旋转运动时没有平移三角化条件失效单目VO直接“失灵”又比如机器人原地快速打转帧间重叠太小特征匹配全部失败系统跟丢。这些边界条件不是一个“性能问题”而是“能不能用”的问题。提示如果你只是在做实验Demo跑通VO可能只要一下午。但如果在做实际系统一定要把“纯旋转”“低纹理”“快速运动”这些极端场景列进需求里否则现场表现会很难看。2. 标准VO流水线从图像到轨迹的四步拆解2.1 特征提取选角点还是选描述子经典的VO系统几乎都是特征法的天下。第一步是从图像里挑出稳定的特征点。论文里提到的特征包括早期的角点检测器、尺度不变特征SIFT类、以及后来更适合实时系统的二进制描述子ORB类。选择的标准其实就两条重复检测率要高计算速度要快。我个人的经验是在做VO实验时最喜欢用角点加金字塔光流来跟踪。角点响应值选得合适一帧图像抽出几百个点连续帧之间的跟踪效果非常稳。如果场景光照变化剧烈或者需要做大规模匹配重用才考虑用二进制描述子。2.2 帧间匹配描述子匹配与光流跟踪之争帧间匹配是VO性能的分水岭。两种主流做法描述子匹配提取当前帧特征点的描述子和上一帧的特征描述子做最近邻匹配。优点是重定位能力强不怕大位移缺点是计算量大、耗时帧率一高就会成为瓶颈。稀疏光流跟踪假设像素亮度在连续帧间不变用金字塔光流算法直接跟踪上一帧的特征点。优点是速度快一帧几十个点用几百微秒就能跑完缺点是对亮度变化和快速运动敏感。论文从历史角度回顾了这两种路线但我可以给一个非常工程化的建议如果你的相机运动是平滑的、帧率稳定在30帧以上优先选KLT光流如果跳变较大比如关键帧式采集帧率不稳定优先选描述子匹配。实测下来在大多数室内机器人平台上KLT的表现比描述子匹配更稳而且不容易出现“匹配跳线”的情况。2.3 运动估计2D-2D、3D-2D、3D-3D分别怎么选拿到匹配点对之后接下来要估计相机的旋转和平移。论文把运动估计分成了三大类每类的适用场景完全不同2D-2D两张图像上匹配到的都是二维像素坐标。此时用对极几何求本质矩阵或者单应矩阵再分解出旋转和平移。适合单目相机的起始帧也就是还没有任何三维信息的时候。3D-2D已知空间点三维坐标同时知道它在图像上的二维投影。用PnP算法求解相机位姿。单目VO在初始化后后续每一帧都可以用上一帧三角化出来的三维点来解PnP所以这是单目系统在正常跟踪阶段的惯用做法。3D-3D两个传感器比如双目相机左右目或者连续两帧由深度相机直接给出深度分别重建出三维点云用迭代最近点ICP求两个点云之间的刚体变换。立体相机系统常用这种方案。2.4 局部优化为什么VO也要做Bundle Adjustment很多人以为VO只是帧间递推算完一帧就把结果丢掉。实际上成熟VO系统都会保留一个滑动的局部窗口里面装着最近N帧的位姿和它们看到的路标点然后做局部的光束平差法Bundle AdjustmentBA优化。优化目标是最小化所有路标点的重投影误差总和。这样做的好处是局部噪声会被约束在窗口范围内平滑掉而不是全部污染到下一帧。论文里对BA的评价很高认为它是让VO从“能跑”变成“跑得准”的关键一步。我在工程里的理解是没有BA的VO短期内看不出问题跑了几十米后轨迹就开始飘了加了局部BA之后误差累积会明显变慢尤其在转弯和加减速时位姿的跳变会平滑很多。注意局部窗口的尺寸不是越大越好。窗口太大计算量上去而且远处的路标点质量下降窗口太小平滑效果不足。我常用的窗口大小是10到15个关键帧在精度和实时性之间比较平衡。3. 几何基础与实现细节对极约束、PnP、三角化和局部BA3.1 对极几何为什么两帧就能求出运动假设同一个空间点P在相邻两帧图像中分别成像为p1和p2。当这两个相机位姿存在旋转和平移关系时p1和p2之间存在一个被称为极线约束的几何关系用基础矩阵F可以写成p2^T F p1 0如果相机已经标定可以进一步把像素坐标转换到归一化平面上这时约束化简为本质矩阵E的关系x2^T E x1 0本质矩阵E包含旋转R和平移t的信息。解出E之后再做一次SVD分解就能恢复出R和t。这个过程在论文里属于VO的基础数学部分但实际编码时会遇到几个坑。首先是E的尺度不确定性E乘上任意非零常数依然满足约束所以从E分解出来的t只有方向没有尺度——这正是单目VO没有绝对尺度的数学根源。其次是分解出的R和t有四个组合解必须用“点在两个相机前方”的约束筛选出唯一正确的一组。我用PyTorch风格写下过一个简洁的八点法实现核心逻辑如下import numpy as np def eight_point_essential(x1, x2): x1, x2: 归一化平面坐标, shape (N, 2) 返回本质矩阵 E N x1.shape[0] ones np.ones((N, 1)) X1 np.hstack([x1, ones]) X2 np.hstack([x2, ones]) # 构造线性方程组 A * e 0 A np.zeros((N, 9)) for i in range(N): u1, v1 X1[i] u2, v2 X2[i] A[i] [ u2 * u1, u2 * v1, u2, v2 * u1, v2 * v1, v2, u1, v1, 1 ] # 最小二乘解对应最小奇异值的右奇异向量 _, _, Vt np.linalg.svd(A) E Vt[-1].reshape(3, 3) # 强制本质矩阵的奇异值约束: [1, 1, 0] U, _, Vt np.linalg.svd(E) S np.diag([1.0, 1.0, 0.0]) E U S Vt return E3.2 三角化从两帧匹配点恢复三维点有了两帧的位姿之后匹配到的点可以反向投影出去通过三角化得到三维坐标。论文里提到线性三角化方法实际上就是构造一个包含两帧投影矩阵的齐次线性方程组用SVD求解。数学上很简洁但工程上有一个致命问题当两帧之间的平移很小时也就是“短基线”条件下三角化的深度估计会非常不稳定误差随噪声急剧放大。这就是为什么我在实际项目中会要求VO系统尽量保持足够的运动速度避免长时间停滞或者极小位移的抖动。另一个工程小技巧是不要用三角化出来的所有点去做下一帧的PnP要过滤掉反投影误差过大的点同时剔除深度为负或深度接近无穷远的点。这个过滤步骤往往比换一种求解算法更能提升精度。3.3 PnP单目系统真正的主角单目VO完成了初始化通常是前两帧通过2D-2D运动估计加三角化建立了初始三维点之后后续每一帧都有了一个可靠的先验上一帧的关键帧有位姿三维点也有粗略坐标。于是运动估计就自然地转化为PnP问题——已知一系列三维点及其在当前图像上的投影求相机的旋转和平移。PnP的线性解法很多论文里主要讲述的是直接用DLT求解以及利用RANSAC剔除误匹配的思路。在我的实践中更推荐先跑RANSAC PnP筛掉外点之后再对全部内点做一次非线性优化这样即使在特征匹配有少量错误的情况下系统的鲁棒性也能保持得很好。PnP里面有一个现成的工程实现细节把像素坐标和三维点坐标都做归一化处理可以显著改善数值稳定性。具体做法是把三维点平移到以质心为中心、再缩放到平均距离为1的尺度像素坐标也做类似的操作。很多调试时“为什么SVD解出来是NaN”的问题根源就在数值条件太差。3.4 局部BA用非线性优化把轨迹“磨平”论文里的“fundamentals”部分对BA着墨甚多。BA的核心是构造一个重投影误差函数E(位姿, 路标) Σ || z_ij - project(T_i, X_j) || ^ 2其中z_ij是路标点X_j在第i帧图像上的实际观测像素坐标project是相机投影模型。优化变量包括所有关键帧的位姿和所有路标点的三维坐标目标是把误差总和降到最低。求解BA的标准算法是Levenberg-Marquardt法它结合了高斯牛顿法和梯度下降法的优点。实际框架里很难手写全套BA工程上都是直接调现成优化库。论文的贡献在于明确告诉读者BA不仅是为了SLAM后端服务的在VO阶段就开始用BA能有效把误匹配和噪声导致的跳变拉住不至于让误差滚雪球。4. 这30年发生了什么从滤波器时代到优化时代的演变4.1 早期从载具导航需求出发的研究论文对“第一个30年”的回顾起点可以追溯到20世纪80年代初的视觉运动估计研究。那时候的研究动机主要来自车辆导航能不能不依赖GPS仅凭车上的相机就估算出车的位置和姿态当时计算机视觉领域的核心工具是特征匹配加线性代数整个系统跑起来很慢但思路已经成形。90年代中后期行星探测漫游车的研究推动着VO走向实战。当时的小型行星车在野外环境测试视觉测程技术用立体视觉加特征跟踪来实现六自由度运动估计。为什么行星车这么需要VO因为火星上没有GPS轮子容易在松软地面打滑传统的轮式里程计基本不可靠。这一阶段的研究把VO从“能用”推向了“在恶劣环境下也必须能用”对鲁棒性的要求明显提高。4.2 从滤波器到关键帧优化范式转换大约2000年前后实时视觉定位出现了一个重要的转折状态估计从基于扩展卡尔曼滤波EKF的滤波框架逐渐转向了基于关键帧和BA的优化框架。EKF的做法是把相机位姿和路标点都放进一个巨大的状态向量里每次来一帧图像就更新一遍。理论上很漂亮但计算量随路标点数量急剧增长而且系统的线性化误差会累积导致长期运行的精度受限。后来的关键帧方案完全不同不追求每一帧都更新全局状态而是抽取出若干质量好的关键帧只在这些关键帧上做局部BA。这样既保持了精度又把计算量控制在了可以实时运行的范围。很多后来的单目SLAM系统采用的就是这一套思路。论文把这种转变评价为VO走向实用的关键一步我也是这么理解滤波方法在数学上更“完整”但优化方法在工程上更“实用”。4.3 特征法与直接法的路线分野最后一个重要的历史脉络是特征法与直接法的分化。特征法先提取角点、描述子再进行匹配直接法跳过特征提取直接用图像的像素灰度值构造误差函数。早期VO大多沿特征法的路线走因为特征点匹配天然地能容忍一定的光照变化和几何变形而且误匹配可以通过RANSAC剔除。直接法在后来因为其低纹理场景下的优势重新受到重视但它对灰度不变假设要求极高一旦光照变化剧烈误差函数很容易出现大量局部极小。论文对这两种路线的对比非常客观各有优势也各有软肋。在我做过的项目里如果场景纹理丰富、光照稳定直接法也能跑得很好但只要场景一变特征法的稳定性优势立刻就体现出来了。5. 从论文走向工程常见坑位与排查建议5.1 工程中一定会踩的七个坑理论讲得再多最后还是要落到真机上。下面这张表是我把论文结论和自身项目经历结合后总结出的高频问题速查表按出现的频率从高到低排列现象根因建议方案轨迹越来越短或越来越长单目尺度漂移累积增加局部BA引入深度传感器或IMU约束尺度快速旋转时跟丢帧间重叠不足特征匹配失败提高帧率降低运动角速度增加短暂“回正”动作纯旋转时位置不动轨迹发飘单目纯旋转无视差三角化失效检测纯旋转状态停止更新位置用IMU补偿旋转阳光下或灯光变化时特征点大量丢失光照变化使亮度假设或特征检测失效改用描述子匹配做图像增强提高曝光自适应速度低纹理走廊特征点数量不足墙面天花板缺乏角点融合结构光/深度相机减小特征点响应阈值并启用边缘点运动模糊导致特征检测抖动曝光时间过长或运动过猛提高快门速度增加光源降低底盘速度动态行人经过时轨迹被拉偏移动物体特征点干扰本质矩阵求解用语义分割剔除动态区域或用鲁棒核函数降低外点影响5.2 我的参数调试心得很多刚上手的同学总想找到一套“万能参数”这个思路在实践中行不通。以帧率为例VO的基础假设是相邻帧视差不能太大也不能太小。视差太大匹配失败多视差太小三角化不稳定。我之前在一个室内机器人项目里试过低帧率采集比如10帧每秒结果机器人稍微转快点系统就彻底丢失。后来把帧率提到30帧以上同样的算法代码几乎没怎么改稳定性立刻改善。另一个容易被忽略的参数是特征点的数量与分布。之前有同学问我“是不是特征点越多越准”答案是否定的。特征点太多一方面拖慢速度另一方面大量分布集中的点并不会带来多少信息增益反而可能让优化陷入局部极小。我常用的策略是每帧抽出200到500个点同时强制在图像上分区域均匀抽取避免所有点都堆在纹理丰富的物体上。实践下来均匀分布对旋转运动时的估计精度提升非常明显。5.3 关于单目尺度问题的持久战单目VO有一个绕不过去的问题无法获知真实的绝对尺度。平移向量t从本质矩阵分解出来时天然地丢失了长度信息。后续帧的运动估计继承了这一不确定性最终整个轨迹会被“拉伸”或“压缩”。局部BA可以抑制短期的尺度抖动但无法根治长距离的尺度漂移。在实际工程里要根治尺度问题通常有三种方案一是加IMU用加速度计信息约束尺度二是加深度摄像头或激光雷达直接给深度三是利用已知大小的物体比如环境中固定高度的路标提供尺度先验。论文里虽然没有详细展开这些融合方案但它把“尺度不可观测”这个源头讲清楚了理解这一点之后你会明白单目VO的尺度问题不是代码bug而是几何意义上的固有性质只能靠信息融合来补。5.4 动态环境下的实用对策动态物体一直是很现实的麻烦。某次测试时我特意让一个人从镜头前走过结果系统输出的轨迹直接被拉偏了一个角度这个偏差后来通过回环才勉强校正回来。原因很简单本质矩阵求解时用了最小二乘动态点作为外点没有被妥善剔除。推荐的排查路径分三步先检查RANSAC的阈值设置能否筛掉大部分动态点再检查特征点提取的区域分布如果动态行人占据了图像大部分区域单纯靠RANSAC也挡不住最后是上语义分割模型把行人、车辆这类动态目标在特征提取阶段就排除掉。论文不会教你这些工程经验但这恰恰是让VO系统真正落地的关键。6. 给后来者的阅读建议与我的读后体会6.1 这篇论文应该怎么读这篇综述信息密度很高如果从头到尾逐字读很容易在数学推导部分耗尽耐心。我建议按下面这个顺序来读先读引言和第二章的问题定义搞明白VO到底解决什么问题和SFM、SLAM的边界在哪里。接着读特征提取与匹配的部分这部分是工程入门基础。然后读运动估计的几何基础重点看本质矩阵、PnP、三角化和BA的关系。最后浏览历史回顾章节这部分更像是技术编年史读起来比较轻松但能帮你建立对领域发展的整体认知。如果时间充裕再回到数学推导部分把公式自己推一遍。6.2 一些读完之后的个人体会这篇论文我断断续续读了三遍每一遍的感受都不一样。第一遍觉得内容太多、太散第二遍开始意识到“增量式运动估计”这个定义是整个领域的锚点第三遍带着实际项目中遇到的问题再读才发现每一个看似简单的结论背后都是从无数次实验失败里提炼出来的。如果要我用一句话总结这篇综述的价值我会说它系统性地回答了一个核心问题——在单目、双目乃至多目配置下如何把图像中的二维运动信息一步步转化为稳定的三维运动轨迹以及这个过程在数学和工程上分别受制于什么。理解了这些你再看各种新的VO/VIO/SLAM论文会发现它们大多是在这条主线上做了局部增强。技术进步很快但这套根基值得你花时间夯实。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑