4. 传统深度估计方法:SGM、BM与特征点深度恢复

说到深度估计,很多人一上来就聊深度学习。但说实话,在实际工程项目里,传统方法依然有它的用武之地。我做过不少嵌入式视觉项目,算力有限,深度学习模型跑不动,最后还是靠传统方法解决问题。

这一章,我们就聊聊三种经典的传统方法:SGM(半全局匹配)BM(块匹配),以及基于特征点的深度恢复。它们虽然“老”,但核心思想至今仍在很多工业场景中发光发热。

4.1 块匹配(BM)—— 最朴素的思路

块匹配,说白了就是“找相似”。

你想想看,左右两张图,同一个物体在左图和右图的位置不一样。我们只要找到左图某个像素点在右图的对应位置,就能算出视差,进而得到深度。

BM的做法很简单:

  • 在左图取一个固定大小的窗口(比如 7×7)
  • 在右图沿着同一行滑动这个窗口
  • 计算两个窗口的相似度(通常用SAD或SSD)
  • 相似度最高的位置,就是匹配点

核心公式(SAD):

SAD(x, y, d) = Σ|I_left(x+i, y+j) - I_right(x+i-d, y+j)|

其中 d 是视差,i、j 是窗口内的偏移。

我的经验:窗口大小很关键。窗口太小,噪声大;窗口太大,容易在深度不连续的地方“糊掉”。我个人习惯在纹理丰富的区域用 5×5,在弱纹理区域用 9×9 或 11×11。

BM的优点是快,真的快。我在一个ARM Cortex-A7的板子上跑过,640×480的图像,视差范围64,能做到实时。但缺点也很明显——对噪声敏感,在弱纹理区域几乎失效。

避坑指南:我曾经在一个户外项目里直接用BM,结果晴天效果还行,一到阴天就全崩了。后来发现是光照变化导致左右图亮度不一致。解决办法是先用直方图均衡化做预处理。

4.2 半全局匹配(SGM)—— 更聪明的选择

BM的问题在于它只考虑局部信息,没有全局视野。SGM就是在这个基础上做了改进。

SGM的核心思想是:在多个方向上做动态规划,然后把这些方向的结果融合起来

具体来说,SGM会沿着8个或16个方向分别计算匹配代价,然后累加。这样做的好处是:

  • 保留了局部匹配的细节
  • 引入了平滑性约束(相邻像素的视差应该接近)
  • 对噪声和弱纹理有更好的鲁棒性

SGM代价聚合公式(简化版):

L_r(p, d) = C(p, d) + min(
    L_r(p-r, d),
    L_r(p-r, d-1) + P1,
    L_r(p-r, d+1) + P1,
    min_k L_r(p-r, k) + P2
) - min_k L_r(p-r, k)

其中 P1 和 P2 是惩罚项,P2 > P1。

嗯,这里要注意:P1和P2的取值直接影响结果。P1太小,视差图会“碎”;P2太大,会过度平滑,丢失细节。

我的调参经验:P1 一般取 8~16,P2 取 100~200。但这不是绝对的。我在一个室内场景的项目里,P2 调到 300 效果反而更好,因为室内纹理少,需要更强的平滑约束。

SGM的精度比BM高一个档次,但计算量也大了不少。不过好在有优化方法——比如用Census变换代替原始像素值做匹配代价计算,对光照变化更鲁棒,而且计算更快。

4.3 基于特征点的深度恢复

前面两种方法都是基于像素的密集匹配。但有时候我们不需要每个像素的深度,只需要几个关键点的深度就够了——比如在SLAM或三维重建中。

基于特征点的方法流程是这样的:

  1. 特征提取:用SIFT、ORB、FAST等算法提取左右图的特征点
  2. 特征匹配:用描述子(如BRIEF、ORB描述子)找到左右图的对应点
  3. 三角化:根据匹配点和相机参数,用三角测量法计算深度

三角化公式:

Z = (f * B) / d

其中 Z 是深度,f 是焦距,B 是基线长度,d 是视差。

这里有个关键点:特征匹配的质量直接决定深度精度。我见过不少新手直接用暴力匹配,结果一堆误匹配,深度图惨不忍睹。

我曾经踩过的坑:在一个室外大场景的项目里,用ORB特征做匹配,结果远处建筑物的匹配点全是错的。后来加了RANSAC做外点剔除,才把精度提上来。RANSAC的迭代次数我一般设 1000 次,阈值 3 个像素。

基于特征点的方法优点是速度快、对光照变化鲁棒,但缺点是只能得到稀疏的深度信息。如果你需要稠密深度图,还得用插值或扩散的方法把稀疏点变成稠密图。

4.4 三种方法的对比

方法 精度 速度 适用场景 缺点
BM 实时性要求高、纹理丰富的场景 对噪声敏感,弱纹理失效
SGM 中高 中等 室内、中等纹理场景 参数调优较麻烦
特征点法 高(稀疏) SLAM、三维重建、大场景 只能得到稀疏深度

4.5 本章知识体系

下面这张图总结了三种方法的核心逻辑和关系:

传统深度估计方法知识体系 双目图像对 BM 块匹配 SGM 半全局匹配 特征点法 SAD/SSD 代价计算 多方向代价聚合 特征提取+匹配 稠密视差图(噪声多) 稠密视差图(平滑) 稀疏深度点云

从这张图可以看得很清楚:三种方法从同一个输入出发,走的是完全不同的技术路线。BM最简单粗暴,SGM在中间加了一层“全局思考”,特征点法则走了另一条路——先找关键点再算深度。

实际项目中怎么选?我的建议是:

  • 如果你做的是嵌入式实时系统,纹理丰富,选BM
  • 如果你需要较好的稠密深度图,算力也够,选SGM
  • 如果你做的是SLAM或稀疏重建,选特征点法

当然,也可以组合使用。我在一个项目中就用SGM生成稠密深度图,然后用特征点法做位姿估计,两者互补,效果不错。


公众号:蓝海资料掘金营,微信deep3321