4. 匹配代价计算(下):互信息(MI)、梯度匹配代价、多代价融合策略、代价计算的开销分析
好,咱们接着聊匹配代价计算。上一节我们把绝对值差、平方差、Census变换这些基础方法讲透了。这一节,我打算聊聊几个更“高级”的玩法——互信息、梯度代价,以及怎么把多个代价融合起来。最后,咱们再算一笔账,看看这些代价计算到底有多“贵”。
4.1 互信息(MI)代价:当光照不配合的时候
先说说互信息。这玩意儿在立体匹配里,说白了就是衡量左右图像对应像素之间“信息相关性”的指标。你想想看,如果左右图拍的是同一个物体,那它们的灰度分布应该是有某种内在联系的——哪怕光照变了,这种联系也不会完全消失。
我在项目中遇到过最头疼的场景,就是户外双目系统。大太阳底下,左图亮得刺眼,右图被树荫遮了一半。这时候你用SAD或者Census?效果直接崩盘。但互信息能扛住,因为它不直接比灰度值,而是比灰度分布的“熵”。
互信息的计算公式长这样:
MI(I1, I2) = H(I1) + H(I2) - H(I1, I2)
其中H是信息熵。H(I1)是左图的熵,H(I2)是右图的熵,H(I1, I2)是联合熵。联合熵越小,说明两张图越“相关”。
嗯,这里要注意:互信息计算量很大。为什么呢?因为你要统计整张图的灰度直方图,还要算联合直方图。我早期做实验时,一张640×480的图,光算MI就花了将近200毫秒——这还没开始做代价聚合呢。
4.2 梯度匹配代价:边缘才是王道
接下来聊梯度匹配代价。这个思路其实很直观:人眼看立体,最敏感的是哪里?是边缘,是纹理变化剧烈的地方。平坦区域?人眼也看不准。
梯度代价就是利用图像的梯度信息——通常是x方向和y方向的梯度——来计算匹配代价。公式很简单:
C_grad(p, d) = |∇x_left(p) - ∇x_right(p-d)| + |∇y_left(p) - ∇y_right(p-d)|
说白了,就是左右图对应像素的梯度差。梯度差越小,匹配越好。
我个人习惯把梯度代价和Census代价结合起来用。为什么呢?因为Census对光照变化鲁棒,但对弱纹理区域表现一般;梯度代价正好能补上边缘区域的匹配精度。两者一结合,效果立竿见影。
4.3 多代价融合策略:1+1 > 2
好,现在你手里有好几种代价了:SAD、Census、MI、梯度……怎么把它们揉到一起?
常见的融合策略有三种:
- 加权求和: 给每个代价一个权重,然后加起来。比如 C_total = α * C_census + β * C_grad。α和β怎么定?我一般用网格搜索或者交叉验证。
- 归一化后求和: 先把每个代价归一化到[0,1]区间,再求和。这样能避免某个代价的数值范围太大,把其他代价淹没了。
- 自适应融合: 根据局部图像特征动态调整权重。比如纹理丰富的地方,梯度代价权重大一些;光照变化大的地方,Census权重大一些。
我在实际项目中,最常用的是第二种——归一化后求和。简单、稳定、不容易翻车。自适应融合听起来很美好,但调参调到你怀疑人生。
| 融合策略 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 加权求和 | 实现简单,可解释性强 | 权重需要手动调,泛化性差 | 固定场景、离线调参 |
| 归一化后求和 | 数值稳定,不需要调权重 | 可能丢失某些代价的区分度 | 大多数通用场景 |
| 自适应融合 | 理论上最优,适应性强 | 实现复杂,计算量大 | 高精度需求、研究场景 |
4.4 代价计算的开销分析:算力都去哪儿了?
最后,咱们来算一笔账。代价计算是整个立体匹配流程中,计算量最大的环节之一。你想想看,对于一张VGA分辨率(640×480)的图像,视差范围假设是128,那你要计算大约640×480×128 ≈ 3900万个像素对的代价。每个像素对的计算,哪怕只花1微秒,总时间也要39秒——这显然不现实。
所以,实际工程中我们得精打细算:
- SAD/SSD: 计算量最小,每个像素对只需要一次减法和一次加法。适合实时系统。
- Census变换: 需要先做局部二值化编码,然后算汉明距离。计算量比SAD大一些,但硬件友好。
- 梯度代价: 需要先算梯度图,然后做差分。计算量中等。
- 互信息: 计算量最大,需要统计全局直方图和联合直方图。不适合实时系统。
我个人习惯在项目初期,先用SAD或者Census跑通整个流程,确保算法框架没问题。然后再根据实际需求,逐步替换成更复杂的代价函数。千万别一上来就上MI,否则你调试一次要等半小时,心态直接崩了。
好了,这一节的内容就到这里。匹配代价计算是整个立体匹配的基石,选对了代价函数,后面的聚合和优化才能事半功倍。下一节,咱们进入代价聚合环节——那才是真正拉开算法差距的地方。