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或三维重建中。
基于特征点的方法流程是这样的:
- 特征提取:用SIFT、ORB、FAST等算法提取左右图的特征点
- 特征匹配:用描述子(如BRIEF、ORB描述子)找到左右图的对应点
- 三角化:根据匹配点和相机参数,用三角测量法计算深度
三角化公式:
Z = (f * B) / d
其中 Z 是深度,f 是焦距,B 是基线长度,d 是视差。
这里有个关键点:特征匹配的质量直接决定深度精度。我见过不少新手直接用暴力匹配,结果一堆误匹配,深度图惨不忍睹。
我曾经踩过的坑:在一个室外大场景的项目里,用ORB特征做匹配,结果远处建筑物的匹配点全是错的。后来加了RANSAC做外点剔除,才把精度提上来。RANSAC的迭代次数我一般设 1000 次,阈值 3 个像素。
基于特征点的方法优点是速度快、对光照变化鲁棒,但缺点是只能得到稀疏的深度信息。如果你需要稠密深度图,还得用插值或扩散的方法把稀疏点变成稠密图。
4.4 三种方法的对比
| 方法 | 精度 | 速度 | 适用场景 | 缺点 |
|---|---|---|---|---|
| BM | 低 | 快 | 实时性要求高、纹理丰富的场景 | 对噪声敏感,弱纹理失效 |
| SGM | 中高 | 中等 | 室内、中等纹理场景 | 参数调优较麻烦 |
| 特征点法 | 高(稀疏) | 快 | SLAM、三维重建、大场景 | 只能得到稀疏深度 |
4.5 本章知识体系
下面这张图总结了三种方法的核心逻辑和关系:
从这张图可以看得很清楚:三种方法从同一个输入出发,走的是完全不同的技术路线。BM最简单粗暴,SGM在中间加了一层“全局思考”,特征点法则走了另一条路——先找关键点再算深度。
实际项目中怎么选?我的建议是:
- 如果你做的是嵌入式实时系统,纹理丰富,选BM
- 如果你需要较好的稠密深度图,算力也够,选SGM
- 如果你做的是SLAM或稀疏重建,选特征点法
当然,也可以组合使用。我在一个项目中就用SGM生成稠密深度图,然后用特征点法做位姿估计,两者互补,效果不错。
公众号:蓝海资料掘金营,微信deep3321