☰
双目视觉SLAM实战:标定、立体匹配与位姿估计全解析
2026/9/29 14:01:24 网站建设 项目流程

1. 双目视觉SLAM的底层逻辑与方案选型

双目相机在SLAM和三维建图这个圈子里,一直是个很特殊的存在。它不像单目那样存在尺度漂移和初始化问题,也不像RGB-D那样受限于室内和光照条件,更不像激光雷达那样成本高、体积大。但真正把双目用好的团队并不多,原因在于双目系统的标定、同步、匹配和融合环节,每一步都有大量细节需要打磨。

我最早接触双目是在一个室内移动机器人项目上,当时用单目跑ORB-SLAM,跑着跑着尺度就飘了,回环之后地图整体缩放,机器人定位直接崩掉。后来换成双目,尺度问题从原理上就解决了——双目通过左右目视差可以直接恢复深度,深度值乘以基线就是真实的物理尺度,不需要像单目那样靠三角化或者IMU来估计尺度。这个特性对于需要真实尺度输出的场景,比如机器人导航、三维重建、AR/VR中的虚实遮挡,是刚需。

双目SLAM的核心思路其实不复杂:左右目图像分别提取特征点,进行立体匹配得到视差图,视差转深度,深度转三维点云,然后把这些三维点拿去做帧间位姿估计和地图构建。但实际工程中,从标定到同步到匹配到优化,每个环节都有坑。比如标定不准会导致极线校正后左右目对不齐,匹配就会大量误匹配;比如左右目曝光不一致会导致特征点描述子差异大,匹配率骤降;比如基线选择不当会导致远距离深度精度极差,近处又容易超出视场。

方案选型上,双目SLAM目前主流的有几条路线。一条是基于特征点法的,比如ORB-SLAM2/3的双目模式,优点是成熟稳定、回环检测完善、支持重定位,缺点是稀疏点云、纹理缺失场景容易丢。另一条是基于直接法的,比如SVO、DSO的双目扩展,优点是能利用像素梯度、在弱纹理场景表现更好,缺点是对光照变化敏感、计算量大。还有一条是最近比较热的双目+IMU融合,比如VINS-Fusion、ORB-SLAM3的双目惯性模式,通过IMU提供高频运动先验,解决双目在快速运动或短暂遮挡时的跟踪丢失问题。

选哪条路线,取决于你的应用场景。如果是室内机器人导航,环境纹理丰富、运动平稳,ORB-SLAM3的双目模式就够用,社区资源多、调试方便。如果是无人机或者手持设备,运动剧烈、光照变化大,VINS-Fusion的双目+IMU方案更稳。如果是做三维重建,需要稠密点云,那可能得在ORB-SLAM的稀疏地图基础上接一个稠密重建模块,比如用双目立体匹配生成深度图再融合,或者用最近比较火的3DGS做场景表示。

这里有个经验:不要一上来就追求端到端的深度学习方案。双目SLAM的几何基础非常扎实,传统方法在大多数场景下已经足够可靠,而且可解释性强、调试手段多。深度学习可以在特征提取、立体匹配、深度补全这些环节做增强,但整体框架还是几何为主、学习为辅比较稳妥。

2. 双目相机标定与极线校正的实操细节

标定是双目系统的地基,地基没打好,后面所有环节都会出问题。我见过太多团队在标定上偷懒,直接用厂家给的参数,结果跑出来的点云全是重影,深度值误差大到没法用。

双目标定的核心是获取左右目的内参、畸变系数,以及左右目之间的外参——旋转矩阵R和平移向量T。平移向量的模长就是基线,基线的精度直接影响深度精度。深度误差和基线的关系是:深度误差与距离的平方成正比,与基线和焦距的乘积成反比。也就是说,基线越大,远距离深度精度越好,但近处盲区也越大。一般室内机器人基线选6cm到12cm,无人机选10cm到20cm,根据你的工作距离来定。

标定流程我一般用ROS的camera_calibration包或者Kalibr。Kalibr的好处是支持多相机+IMU联合标定,而且对时间同步有建模,适合做双目+IMU的系统。用Kalibr标定时,需要准备一个AprilTag或者棋盘格标定板,以不同姿态在相机视野内缓慢移动,采集足够多的图像。注意采集时标定板要覆盖整个视野,包括边缘区域,否则畸变系数估计不准。另外左右目要同时采集,保证时间戳对齐。

标定完成后,一定要做极线校正验证。极线校正的目的是让左右目图像的对应点在同一水平线上,这样立体匹配只需要在水平方向搜索,大大降低计算量。验证方法是:用标定参数对左右目图像做remap,然后叠加显示,看同一物体的边缘是否在同一水平线上。如果上下错位明显,说明外参标定有问题,需要重新标定。

注意:标定时的光照条件要和实际使用场景接近。如果在暗光下标定,亮光下使用,畸变系数可能会有偏差。另外标定板要平整,打印精度要够,否则角点检测会有亚像素误差。

极线校正之后,还有一个容易被忽略的环节:左右目图像的同步。如果是硬件同步,左右目相机共享同一个触发信号,时间戳天然对齐。如果是软件同步,靠ROS的message_filters做时间戳近似对齐,那就要注意左右目图像的曝光时间是否一致。曝光时间不一致会导致同一时刻左右目图像的亮度差异大,特征点匹配率下降。解决办法是关闭自动曝光,手动设置相同的曝光时间和增益,或者用硬件同步触发。

还有一个细节:双目相机的镜头畸变。广角镜头畸变大,校正后边缘区域会被拉伸,有效像素减少。如果视场角要求不高,尽量选畸变小的镜头,比如低畸变工业镜头。如果必须用广角,那校正后要做裁剪,把无效区域去掉,否则边缘的深度值不可靠。

标定参数不是一劳永逸的。相机受到震动、温度变化后,外参可能会漂移。我一般会在系统运行前做一个在线自标定检查:用当前图像做极线校正,看左右目匹配点的垂直视差是否在阈值内。如果垂直视差均值超过1个像素,就提示需要重新标定。这个检查可以做成定期自动执行,比如每运行24小时检查一次。

3. 双目立体匹配与深度图生成的关键参数

立体匹配是双目SLAM里计算量最大的环节,也是深度图质量的决定性因素。匹配算法分两大类:局部方法和全局方法。局部方法比如BM、SGBM,速度快但深度图有噪声和空洞;全局方法比如GC、BP,效果好但慢,不适合实时。SLAM里一般用SGBM,因为它在速度和效果之间平衡得比较好。

SGBM的关键参数有几个:视差范围、块大小、唯一性比率、 speckle窗口大小和滤波强度。视差范围决定了能测到的最近和最远距离。视差范围越大,计算量越大。一般根据你的工作距离来设:如果最近工作距离是0.5米,基线是0.1米,焦距是500像素,那最大视差大约是焦距乘以基线除以最近距离,也就是500乘以0.1除以0.5等于100像素。所以视差范围设0到128就够了。如果设太小,近处物体会超出视差范围,深度图出现大片空洞;设太大,计算量浪费,而且远处视差小,量化误差大。

块大小影响匹配的鲁棒性和深度图的平滑度。块太小,噪声大;块太大,边缘模糊,细小物体深度不准。一般设5到11之间,纹理丰富设小一点,纹理弱设大一点。唯一性比率用来剔除误匹配,一般设10%到15%,值越大越严格,但也会导致更多空洞。speckle窗口用来过滤小的噪声斑块,一般设50到200,滤波强度设1到2。

实操心得:SGBM的参数没有万能值,必须根据你的场景调。我一般先用默认参数跑一遍,看深度图的空洞率和噪声水平,然后逐步调块大小和唯一性比率。如果空洞太多,先检查视差范围是否覆盖了最近距离;如果噪声太多,增大speckle窗口和滤波强度。

深度图生成之后,不是直接拿去做SLAM。原始深度图有很多噪声和空洞,需要做滤波。常用的滤波有:中值滤波去椒盐噪声,双边滤波保边去噪,形态学闭运算填小空洞。但滤波会损失细节,所以滤波强度要适中。我一般用双边滤波,参数设小一点,保留边缘的同时去掉大部分噪声。

还有一个重要环节:深度图转点云。深度图上的每个像素,根据内参和深度值,可以反投影到三维空间。公式是:X等于(u减cx)乘以Z除以fx,Y等于(v减cy)乘以Z除以fy,Z就是深度值。这里要注意,深度值是沿着相机光轴的距离,不是欧氏距离。如果相机有畸变,反投影前要先做去畸变。转成点云后,可以做体素滤波降采样,减少点云数量,提高后续处理的效率。

深度图的精度和距离的关系很大。近距离精度高,远距离精度差。一般来说,深度误差和距离的平方成正比。比如基线0.1米,焦距500像素,视差精度0.5像素,那在1米处的深度误差大约是1乘以1除以(500乘以0.1)再乘以0.5,等于0.01米,也就是1厘米。在5米处,误差就是25厘米。所以双目在远距离的深度精度是有限的,做三维建图时要注意这个限制。

如果场景纹理弱,比如白墙、玻璃,立体匹配会失败,深度图出现大片空洞。解决办法有几个:一是用主动光源投射纹理,比如红外散斑,这就是RGB-D相机的思路;二是用深度学习做深度补全,比如用单目深度估计网络补全空洞区域;三是融合其他传感器,比如激光雷达或者IMU,在空洞区域用其他传感器的数据。

4. 双目SLAM的位姿估计与地图融合方法

位姿估计是SLAM的核心,双目SLAM的位姿估计一般分两步:先做帧间跟踪,再做局部优化。帧间跟踪用特征点匹配或者直接法,得到当前帧相对于上一帧的位姿变换。局部优化用滑动窗口或者关键帧,把多帧的观测联合起来优化,减少漂移。

特征点法的帧间跟踪,一般用ORB特征。左右目分别提取ORB特征,然后做立体匹配,得到带深度的三维特征点。当前帧和上一帧做特征匹配,用3D-2D的PnP或者3D-3D的ICP估计位姿。PnP需要至少4个匹配点,ICP需要至少3个。实际中匹配点远多于这个数,用RANSAC剔除误匹配,然后最小化重投影误差求解位姿。

这里有个关键点:双目特征点的深度精度直接影响位姿估计精度。如果深度误差大,3D点位置不准,PnP的解就会偏。所以立体匹配的质量很重要。另外,特征点的深度值要做滤波,比如用多帧观测做深度滤波,收敛后再用于位姿估计。ORB-SLAM2里有一个深度滤波的模块,对每个特征点维护一个深度分布,用多帧观测更新,收敛后深度精度会提高很多。

局部优化一般用BA(Bundle Adjustment),把滑动窗口内的所有帧的位姿和地图点联合优化。BA的代价函数是重投影误差,双目的话,左右目的重投影误差都要算进去。优化用g2o或者Ceres,一般用LM算法。BA的计算量比较大,所以滑动窗口不能太大,一般5到10帧。关键帧的选择策略也很重要,不能太密也不能太稀。太密计算量大,太稀跟踪容易丢。ORB-SLAM2的策略是:当前帧和上一关键帧的共视点少于一定比例,或者当前帧跟踪到的地图点少于一定数量,就插入关键帧。

回环检测是消除累积漂移的关键。双目SLAM的回环检测一般用词袋模型,比如DBoW2。把关键帧的特征描述子转成词袋向量,在数据库中检索相似的关键帧。如果相似度超过阈值,就认为检测到回环,然后做回环优化。回环优化用位姿图优化,把回环约束加进去,全局调整所有关键帧的位姿。

注意:回环检测的阈值不能设太低,否则误回环会导致地图扭曲。我一般设0.7到0.8,同时要求回环候选帧和当前帧的共视点数量超过一定值,才认为是真回环。

地图融合是双目SLAM里比较高级的话题。如果你有多个机器人或者多次建图,需要把多个地图融合成一个。融合的关键是找到地图之间的重叠区域,然后做位姿对齐。重叠区域可以用特征匹配找,也可以用回环检测找。对齐用ICP或者位姿图优化。融合后的地图要做一致性检查,把重复的地图点合并,冲突的地图点剔除。

双目和IMU的融合是另一个重要方向。IMU提供高频的角速度和加速度,可以在双目跟踪丢失时维持位姿估计,也可以在双目初始化时提供尺度信息。融合方法一般用紧耦合的VIO,把IMU的预积分和双目的重投影误差联合优化。VINS-Fusion和ORB-SLAM3都支持双目+IMU的紧耦合。紧耦合的优点是精度高、鲁棒性好,缺点是计算量大、初始化复杂。

双目和激光雷达的融合,一般是松耦合的。激光雷达提供精确的深度和结构信息,双目提供纹理和颜色信息。融合方法有几种:一是用激光雷达的点云做深度图,和双目深度图做融合,提高深度精度;二是用激光雷达做位姿估计,双目做回环检测和地图纹理;三是用激光雷达的点云做地图骨架,双目点云做补充。松耦合的优点是实现简单,缺点是精度不如紧耦合。

5. 常见问题排查与避坑经验实录

双目SLAM在实际调试中会遇到各种问题,我整理了一些典型问题和排查思路,做成速查表方便参考。

问题现象可能原因排查方法解决方案
深度图大片空洞纹理弱、视差范围不够、曝光不一致检查原始图像纹理、视差范围、左右目亮度增加纹理、调大视差范围、手动曝光
点云重影标定不准、极线校正错误叠加左右目图像看边缘对齐重新标定、检查外参
跟踪丢失快速运动、遮挡、纹理弱看跟踪特征点数量、IMU数据融合IMU、增加特征点、降低运动速度
尺度漂移双目深度误差累积对比真实距离和估计距离优化立体匹配、融合IMU
回环误检阈值太低、场景重复看回环候选帧的共视点提高阈值、增加几何验证
地图扭曲回环优化失败、位姿图错误看优化后的残差检查回环约束、重新优化
实时性差立体匹配计算量大、BA窗口太大看各模块耗时降采样、减小窗口、用GPU加速

标定不准是最常见的问题。我见过一个团队,标定的时候标定板只放在视野中央,边缘区域没覆盖,结果畸变系数估计不准,校正后边缘区域深度误差特别大。后来重新标定,标定板覆盖整个视野,问题就解决了。所以标定时一定要让标定板出现在视野的各个位置,包括四个角和边缘。

左右目曝光不一致是另一个常见问题。自动曝光下,左右目相机独立调整曝光时间,导致同一时刻左右目图像亮度差异大,特征点匹配率下降。解决办法是关闭自动曝光,手动设置相同的曝光时间和增益。如果光照变化大,可以用自动曝光但限制曝光范围,或者用硬件同步触发保证同时曝光。

快速运动导致跟踪丢失,在无人机和手持设备上很常见。双目相机的帧率一般30到60帧,快速运动时帧间位移大,特征点匹配不上。解决办法是融合IMU,用IMU的高频数据做运动补偿,或者提高相机帧率,或者降低运动速度。如果必须快速运动,那双目+IMU的紧耦合方案是必须的。

纹理弱场景,比如白墙、玻璃、水面,立体匹配会失败。解决办法有几个:一是用主动光源投射纹理,比如红外散斑;二是用深度学习做深度补全;三是融合激光雷达。我试过用单目深度估计网络补全双目深度图的空洞,效果还可以,但精度不如原始双目深度,只能做补充。

实操心得:双目SLAM的调试,一定要可视化。把深度图、点云、特征点、轨迹都可视化出来,一眼就能看出问题在哪。我一般用RViz看点云和轨迹,用OpenCV看深度图和特征点。可视化工具用好了,调试效率能提高好几倍。

还有一个坑:时间同步。如果左右目时间戳不对齐,立体匹配就会匹配到不同时刻的图像,深度图全是错的。硬件同步最可靠,但需要相机支持触发信号。软件同步用message_filters的ApproximateTime策略,但要求时间戳精度高。如果时间戳精度不够,可以用ROS的TimeSynchronizer做精确同步,但要求左右目时间戳完全一致,实际中很难做到。所以如果对精度要求高,还是用硬件同步。

最后说一个经验:双目SLAM的参数不要一次调太多。每次只调一个参数,看效果,再调下一个。因为参数之间会相互影响,一次调多个,出了问题不知道是哪个参数导致的。我一般先调立体匹配的参数,把深度图调好,再调SLAM的参数,把轨迹调好。这样分步调,效率高,问题也好定位。

6. 双目与3DGS结合的前沿探索

最近3DGS(3D Gaussian Splatting)很火,它用高斯椭球表示场景,渲染质量高、速度快。双目和3DGS结合,是一个很有意思的方向。双目提供多视角图像和深度,3DGS用这些数据做场景表示和渲染。相比传统的点云或者网格,3DGS的渲染质量更好,而且支持实时渲染。

双目做3DGS的流程大概是:先用双目SLAM得到相机位姿和稀疏点云,然后用这些位姿和图像做3DGS的训练,优化高斯椭球的参数。训练完成后,可以从任意视角渲染场景。双目提供的深度信息可以用来初始化高斯椭球的位置和尺度,加速训练收敛。

这个方向目前还在早期,有几个问题需要解决。一是双目的深度精度有限,远距离深度误差大,导致高斯椭球的位置不准。二是3DGS的训练需要大量视角,双目只有两个视角,需要移动相机采集多视角数据。三是3DGS的渲染和SLAM的实时性有冲突,SLAM需要实时,3DGS训练需要离线。

不过这个方向的前景很好。如果能把3DGS的渲染和SLAM的跟踪结合起来,用3DGS做地图表示,SLAM的跟踪精度和鲁棒性可能会提高。因为3DGS的渲染可以生成高质量的图像,用于特征匹配和位姿估计。而且3DGS的地图可以用于路径规划和避障,比稀疏点云更直观。

我最近在尝试用双目SLAM的位姿和深度图做3DGS的初始化,发现深度图的噪声对高斯椭球的影响很大。深度噪声大的区域,高斯椭球会拉得很长,渲染出来有拖影。解决办法是对深度图做滤波,或者用多帧深度做融合,提高深度精度。另外,高斯椭球的尺度初始化也很重要,初始化太大,渲染模糊;初始化太小,渲染有空洞。我一般根据深度值来初始化尺度,深度大尺度大,深度小尺度小。

这个方向还有很多可以探索的地方,比如用双目+IMU做3DGS的位姿估计,用3DGS做回环检测,用3DGS做语义建图。如果你对3DGS感兴趣,可以从双目SLAM的位姿和深度图入手,先跑通一个简单的3DGS重建,再逐步优化。

我个人在实际操作中的体会是,双目SLAM的门槛在标定和立体匹配,这两步做好了,后面的位姿估计和地图融合就顺了。标定要耐心,立体匹配要调参,没有捷径。另外,不要忽视可视化和日志,出了问题,可视化和日志是最好的排查工具。最后,双目不是万能的,纹理弱、远距离、快速运动这些场景,双目单独搞不定,融合IMU或者激光雷达是必要的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询