
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除以fxY等于(v减cy)乘以Z除以fyZ就是深度值。这里要注意深度值是沿着相机光轴的距离不是欧氏距离。如果相机有畸变反投影前要先做去畸变。转成点云后可以做体素滤波降采样减少点云数量提高后续处理的效率。深度图的精度和距离的关系很大。近距离精度高远距离精度差。一般来说深度误差和距离的平方成正比。比如基线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里有一个深度滤波的模块对每个特征点维护一个深度分布用多帧观测更新收敛后深度精度会提高很多。局部优化一般用BABundle 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结合的前沿探索最近3DGS3D 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或者激光雷达是必要的。