[TOC]

预备知识

最近在学习CV相关的双目相机立体匹配Stereo Matching,本文是关于GwcNet的一些学习和思考。开始之前,先需要理解几个概念:视差、双目相机匹配、代价体。

RGB像素

图像由像素组成,一张 1920x1080 分辨率的屏幕就代表有1920x1080个像素。RGB代表光的三原色。R=Red,G=Green,B=Blue。这三种颜色通过不同的亮度组合可以形成各种颜色。计算机给每种颜色的亮度划分了 0 ~ 255 共 256 个等级。

可以计算出,三种原色,256种亮度,可以组合出$256^3≈1677万$中颜色。

每一个彩色图像的像素点都由红、绿、蓝三个发光的子像素(Sub-pixels,可以理解为三个微型 LED 灯)紧挨着组成的,可以看成一个三维向量:(R, G, B),比如 (255, 0, 0) 代表纯红。这是原始像素

像素的高维特征向量

一个图像有1024个像素,理论上特征向量也有1024个,一一对应,相当于给每一个像素发一张“高维身份证”。但在工程上,使用 CNN 提取高维特征向量十分消耗显存,如果像素和特征向量 1:1 很容易爆显存。

所以要降采样 : 使用“步长卷积(Stride Convolution)”或“池化(Pooling)”将图像缩小(降采样)。比如在比如 GwcNet 中,特征图的宽和高都被缩小到了原来的 $1/4$。

假设原本像素为$32×32$,降采样1/4后得到 $8*8=64$个特征向量。此时这 64 个特征向量里的每一个,代表的不再是单个像素,而是一小块区域(感受野)的特征汇总。

视差

定义

有一个理想的双目相机系统,两个相机的成像平面是共面和行对齐的,左图中某个点,与对应右图中的匹配点在同一个水平线上。

如果空间中有一个三维点 $P$,它在左图的像素坐标是 $(u_L, v)$,在右图的对应坐标是 $(u_R, v)$ (注意纵坐标 $v$ 是一样的),那么这个点的视差 $d$ 就是它们在水平方向上的坐标差:

这就是视差。它是一个标量,单位是像素(Pixel)

应用

视差可以用来求一个像素点的深度(Depth),就是像素点对应的物体实际离相机的距离。具体公式为:

Z为深度,f为相机焦距,B为基线(左右两个相机光心之间的物理距离),d为视差

视差

学术

当前有一些立体匹配网络,基于代价体构建的GwcNet、IGEV,基于循环迭代的RAFT-Stereo。这些网络本质都是求视差d,即为左图的一个像素点,在右图如何寻找最准确的对应点求出视差

简而言之,视差是连接2D图像特征和3D几何物理世界的桥梁。

双目相机的匹配

核心任务

在左右两张图像中,把显示中同一个物理点的像素点找出来。(寻找同名点

这里举一个实例

使用双目相机拍摄一个苹果。苹果的果梗在左相机,在右相机的。使用人眼很容易根据经验找出两幅图像的相同像素点。但是计算机需要一种算法,当它拿到左图果梗的像素时,能去右图里精确地“匹配”到对应的那个像素。

事先要对相机做极线校正,使双目向机成像水平,这样找一点在另一图像中像素点,只需要沿着水平方向滑动搜索。

代价体

介绍

Cost Volume,一种为了求解视差定值的数据结构,他是三维张量。

在刚才的苹果匹配例子中,实际采用的是穷举法打分:对于左图的一个像素点,在右图中把所有可能的视差偏移量(比如0~192像素)穷举一遍,每次都计算出左右两个像素块的相似度或者差异度(代价)。当这个代价最小,即两个像素块差异最小时,可以认为找到了匹配像素点。

有一些传统方法:

  • 传统方法:计算两个像素快的绝对误差和 SAD
  • 深度学习:提取左右图的高维特征矩阵,计算内积,相似度越高越好

把左图所有的像素 $(H \times W)$,针对所有可能的视差搜索范围 $(D)$,全部算出一个匹配得分后,把这些得分堆叠在一起,就形成了一个三维的张量(Tensor)—— 这就是代价体(Cost Volume)。

它的维度通常是:最大视差数 $(D) \times$ 图像高度 $(H) \times$ 图像宽度 $(W)$

代价体

  • 关于这个坐标D ($D$ / Disparity),被称为通道维度或深度维度,它代表了所有的候选视差值

  • 关于坐标$(x, y, d)$的含义,每一个坐标存放一个数值(打分),这个数值代表了:左图的坐标 $(x, y)$ 这个像素,如果去和右图的坐标 $(x-d, y)$ 这个像素匹配,它们的“差异度(Cost)”或“相似度(Correlation)”有多大。

作用

有了这个存满打分值的三维张量,即可以求视差。

如果这个数值$f(x_0, y_0, d_0)$是相似度,那么这个数值的最大值$f_m(x_0, y_0, d_0)$,对应的$(x_0, y_0, d_0)$点,这个$d_0$即为像素$(x_0, y_0)$实际视差。

为什么要把它做成一个完整的三维张量? 如果只看单个像素,很容易受噪声干扰(比如一块纯白色的墙,右图哪个位置看起来都很像)。把所有像素的匹配得分整合到一个宏大的 3D 张量中后,现代深度学习模型(比如 3D CNN 或 3D 堆叠沙漏网络)就可以在这个大张量里进行空间维度的平滑和上下文信息聚合。它可以参考周围像素的信息,把原本不明显的极值变得更加突出和准确。

求视差的基本流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
graph TD
%% 定义样式
classDef inputNode fill:#f9f9f9,stroke:#333,stroke-width:2px;
classDef processNode fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px;
classDef tensorNode fill:#fff3e0,stroke:#ff9800,stroke-width:2px,stroke-dasharray: 5 5;
classDef outputNode fill:#e8f5e9,stroke:#4caf50,stroke-width:2px;
classDef highlightNode fill:#ffebee,stroke:#f44336,stroke-width:3px;

subgraph step1 ["Step 1: 输入 (Input)"]
IL[/"左图 (Left Image)\nTensor: (3, H, W)"/]
IR[/"右图 (Right Image)\nTensor: (3, H, W)"/]
end

subgraph step2 ["Step 2: 特征提取 (Feature Extraction)"]
CNN("共享权重 2D CNN\n(如 ResNet 提特征)")
FL[/"左图特征 (Left Features)\nTensor: (C, H, W)"/]
FR[/"右图特征 (Right Features)\nTensor: (C, H, W)"/]

IL --> CNN
IR --> CNN
CNN --> FL
CNN --> FR
end

subgraph step3 ["Step 3: 代价体构建 (Cost Volume Construction)"]
GWC{"匹配度计算\n(核心:分组相关)"}
CV1[/"初始代价体 (Initial Cost Volume)\nTensor: (Groups, D, H, W)"/]

FL -->|滑窗搜索| GWC
FR -->|同源比对| GWC
GWC -->|"打包匹配得分"| CV1
end

subgraph step4 ["Step 4: 代价聚合 (Cost Aggregation)"]
AGG("3D 卷积神经网络\n(如 3D Stacked Hourglass)")
CV2[/"精炼代价体 (Refined Cost Volume)\nTensor: (1, D, H, W)"/]

CV1 -->|"上下文过滤去噪"| AGG
AGG -->|"输出所有视差概率分布"| CV2
end

subgraph step5 ["Step 5: 视差回归 (Disparity Regression)"]
SARG("Soft-argmin 操作\n(概率加权求和)")
OUT[/"终极输出:视差图 (Disparity Map)\nTensor: (1, H, W)"/]

CV2 -->|"将概率转为连续数值"| SARG
SARG --> OUT
end

%% ==========================================
%% 统一分配样式 (兼容 Typora 10.9+ 的最安全写法)
%% ==========================================
class IL,IR inputNode;
class CNN,AGG,SARG processNode;
class FL,FR,CV1,CV2 tensorNode;
class OUT outputNode;
class GWC highlightNode;

关于这个流程

这个流程本质上是计算机在做信号搜索与解码。

Step1 RGB像素输入

系统接收到左右图,为许多RGB像素点。但不能直接使用RGB原始像素去匹配,因为左右图相同颜色的点可能不止一对,引发歧义。

Step2 特征提取

为解决歧义,使用2D CNN卷积神经网络,将原本单薄的 RGB 像素被编码成了一个高维的特征向量(比如64维度),,然后Pooling进行降采样,这个特征向量包含了一个像素点高级征信息(如是否处于边缘、材质),是他的“指纹”。

Step3 构建Cost Volume

根据特征向量,在右图的同一行寻找左图像素的对应点,假设最大视差范围是 192 个像素。系统会把左图的特征,与右图平移 0 到 192 个位置的特征分别进行比对(GwcNet 采用了分组相关,按特征子空间分别计算相似度)。

计算完毕构成了巨大的张亮 — 代价体。

像素提取特征向量,经历了降采样的步骤,这时特征向量数量小于RGB像素数量,这时是怎么根据特征向量来构建代价体的?能够根据它直接对比吗?

  1. 代价体是由“降采样”后的少量特征向量构成的

  2. 数学上比较高维向量的手段非常优雅

    在CV领域,比较两个高维特征向量(比如左右图都是320维的向量)相似度,向量内积。如果两个向量相似度高,方向指向相似,那么内积值会很大。如果积出来是复数或者是0,那么关系很微弱。

 Step4 代价聚合

刚建好的代价体是非常嘈杂的,使用3D卷积神经网络CNN把代价体进行精炼,使其变成干净的概率分布体。

Step5 视差回归

针对左图的某一个像素,我们沿着代价体的视差维度看过去,会得到一条平滑的概率曲线。理论上直接找最高点,即视差。但实际上要构建视差图:不直接取最高点(Argmax),而是使用 Soft-argmin 操作。它会对这条概率曲线进行加权求和(算期望值)。这样不仅能输出连续的、平滑的视差图,还能让整个网络保持“可微”状态,从而支持端到端的反向传播训练。

GwcNet

这篇论文的核心贡献在Step3,提取出图像特征后构建代价体。


GwcNet

Group-wise Correlation Stereo Network (GwcNet)

这篇论文属于双目立体匹配领域Stereo Matching,是2019CVPR的会议论文。它提出了一种构建代价体的高效方法(GwcNet),方便求解视差。

背景 - 构建代价体的两难

极端一:全相关

极端二:直接拼接

折中解法:分组相关

核心贡献

分组相关 Group Wise Correlation

该方法将左右图提取的两组特征向量,沿着维度通道channel dimension 划分成多个组。然后每一组的对应特征之间独立计算相关性。

c723c552-9b39-4627-88f8-957f917c3667

改进的 3D 堆叠沙漏聚合网络

c583c125-535a-420d-8dfd-5cb20ca70c5c

混合代价体(Combined Volume)的互补设计