3. 立体匹配基础:匹配代价计算与视差图生成

立体匹配,说白了就是给左图的每个像素,在右图上找个「双胞胎兄弟」。这个找兄弟的过程,核心就三步:算代价、做聚合、选最优。今天咱们就把第一步「匹配代价计算」彻底讲透,顺便聊聊全局匹配和局部匹配的区别。

核心逻辑图:立体匹配的完整流程

输入图像对 左图 + 右图 匹配代价计算 SAD / SSD / NCC 代价聚合 局部 / 全局策略 视差图生成 WTA 赢家通吃 极线校正后 窗口 / 全局 聚合策略 代价体

3.1 匹配代价计算:三个经典方法

匹配代价,就是衡量两个像素块「长得像不像」的分数。分数越低,说明越可能是同一个点。我最早接触双目视觉时,第一个学的就是 SAD,因为它简单到令人发指。

3.1.1 SAD(绝对差值和)

SAD 就是把两个窗口内对应像素的灰度值相减,取绝对值,然后求和。公式长这样:

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

其中 d 是视差,i、j 是窗口内的偏移。嗯,就这么简单。

我的经验:SAD 在纹理丰富的区域效果不错,但在弱纹理区域(比如白墙)会直接崩掉。我曾经在一个室内场景数据集上跑 SAD,结果视差图上一片「雪花」——全是误匹配。后来加了 Census 变换才稳住。

3.1.2 SSD(差平方和)

SSD 和 SAD 很像,只是把绝对值换成了平方:

C(x, y, d) = Σ(I_left - I_right)²

平方操作会放大差异。说白了,它对噪声更敏感,但对边缘区域的区分度也更高。我个人习惯在光照变化不大的场景用 SSD,因为它计算简单,硬件实现也方便。

3.1.3 NCC(归一化互相关)

NCC 就高级一些了。它先对窗口做均值归一化,再算相关性:

C(x, y, d) = Σ[(I_left - μ_left) * (I_right - μ_right)] / (σ_left * σ_right)

NCC 的值在 -1 到 1 之间,越接近 1 说明越匹配。它最大的优点是抗光照变化——你想想看,如果左图亮一点、右图暗一点,SAD 和 SSD 直接就炸了,但 NCC 依然稳如老狗。

注意:NCC 计算量是 SAD 的 5-10 倍。我在嵌入式设备上做过测试,640×480 的图像用 NCC 做全图匹配,一帧要 200 多毫秒——根本跑不动。所以实际项目中,我通常只在关键区域用 NCC,其他地方用 SAD 快速过一遍。

3.2 局部匹配 vs 全局匹配

算完代价之后,怎么用这些代价来得到最终的视差?这就引出了两个流派。

3.2.1 局部匹配

局部匹配的思路很简单:每个像素只看自己周围一个小窗口,窗口内做代价聚合,然后选最小的那个视差。常见的窗口有固定窗口、自适应窗口、引导滤波窗口等。

  • 优点:速度快,适合实时系统
  • 缺点:在弱纹理、重复纹理区域容易出错
  • 典型算法:BM(Block Matching)、SGBM(半全局匹配)

我记得第一次用 OpenCV 的 BM 算法时,看到视差图上那些「黑洞」——其实就是匹配失败的区域——当时还以为是代码写错了。后来才知道,这是局部匹配的通病。

3.2.2 全局匹配

全局匹配就不一样了。它把整张图看作一个能量函数,通过优化这个函数来得到每个像素的视差。能量函数通常包含两项:数据项(匹配代价)和平滑项(相邻像素视差应该相近)。

E(d) = ΣC(x, y, d) + λ * Σ|d(x,y) - d(x+1,y)|

优化方法有图割(Graph Cut)、置信传播(Belief Propagation)、动态规划等。

  • 优点:精度高,边缘清晰,空洞少
  • 缺点:慢,非常慢。一张图可能要跑几秒甚至几分钟

我的建议:做产品选局部匹配,做科研选全局匹配。如果你既想要精度又想要速度,试试 SGBM——它用多个方向的动态规划来近似全局优化,效果介于两者之间。我在一个机器人避障项目里就用 SGBM,帧率能到 30fps,精度也够用。

3.3 视差图生成与 WTA 策略

不管用局部还是全局,最后一步都是「选最优」。WTA(Winner-Take-All)就是最简单粗暴的方法:对于每个像素,在所有可能的视差中,选代价最小的那个。

d(x, y) = argmin C(x, y, d)  其中 d ∈ [d_min, d_max]

举个例子:假设视差范围是 0 到 64,对于像素 (100, 200),我们计算了 65 个代价,其中 d=23 时代价最小,那么视差就是 23。

WTA 的问题也很明显——它只考虑局部最优,不考虑邻域一致性。所以直接 WTA 出来的视差图往往有很多「椒盐噪声」。解决办法就是在 WTA 之前做好代价聚合,或者在 WTA 之后加一个中值滤波。

避坑指南:我曾经在一个项目中直接用 WTA 出图,结果视差图惨不忍睹。后来加了一个 5×5 的中值滤波,效果立刻好了很多。但要注意,滤波窗口太大会抹掉细节——这个度需要根据实际场景调。

3.4 三种代价方法的对比

方法 计算速度 抗光照变化 精度 适用场景
SAD 一般 光照稳定、实时系统
SSD 稍好于 SAD 边缘检测、硬件实现
NCC 光照变化大、离线处理

你可能会问:有没有又快又好的方法?嗯,这就是后面章节要讲的内容了——比如 Census 变换、AD-Census、以及基于深度学习的匹配代价。但今天先把基础打牢,后面的路才好走。


专注资料整理