11  立体匹配与深度估计

11.1 引言:从双目视觉到深度感知

当我们用双眼观察世界时,左右眼看到的图像存在微小差异。大脑正是利用这种差异来感知深度,判断物体的远近。立体匹配算法正是模拟了人类双目视觉的这一机制:通过计算两幅图像中对应点的视差(位置差异),恢复场景的深度信息。

随着深度学习的发展,深度估计技术已经从传统的几何方法扩展到基于神经网络的端到端学习方法。现代深度估计系统不仅能处理标准的双目图像对,还能从单目图像直接预测深度,在自动驾驶、机器人导航、增强现实等领域发挥着关键作用。

11.2 核心概念

传统立体匹配基于几何约束和相似性度量。双目立体视觉系统通常由两个平行放置的相机组成,相机之间的距离称为基线(baseline)。传统方法通过在极线约束下搜索对应点,计算视差来恢复深度。这类方法计算效率高,但在弱纹理、遮挡区域容易失效。

深度学习方法则将深度估计视为回归问题,通过端到端训练学习从图像到深度的映射关系。现代深度网络如PSMNet能够处理复杂场景,在准确性和鲁棒性方面显著超越传统方法。这类方法能够利用语义信息和全局上下文,在困难区域也能给出合理的深度估计。

Code
graph TD
    subgraph 双目相机系统
        A["左相机<br/>Camera_L"]
        B["右相机<br/>Camera_R"]
    end
    
    subgraph 图像获取
        C["左图像<br/>Image_L"]
        D["右图像<br/>Image_R"]
    end
    
    subgraph 立体匹配
        E["视差计算<br/>Disparity Map"]
    end
    
    subgraph 深度重建
        F["深度图<br/>Depth Map"]
    end
    
    A --> C
    B --> D
    C --> E
    D --> E
    E --> F
    
    classDef cameraNode fill:#42a5f5,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    classDef imageNode fill:#66bb6a,stroke:#2e7d32,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    classDef disparityNode fill:#ffb74d,stroke:#e65100,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    classDef depthNode fill:#ef5350,stroke:#c62828,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    
    classDef cameraSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold
    classDef imageSubgraph fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20,font-weight:bold
    classDef disparitySubgraph fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#bf360c,font-weight:bold
    classDef depthSubgraph fill:#ffebee,stroke:#c62828,stroke-width:2px,color:#b71c1c,font-weight:bold
    
    class A,B cameraNode
    class C,D imageNode
    class E disparityNode
    class F depthNode
    
    class 双目相机系统 cameraSubgraph
    class 图像获取 imageSubgraph
    class 立体匹配 disparitySubgraph
    class 深度重建 depthSubgraph
    
    linkStyle 0,1 stroke:#1565c0,stroke-width:2px
    linkStyle 2,3 stroke:#2e7d32,stroke-width:2px
    linkStyle 4 stroke:#e65100,stroke-width:2px

graph TD
    subgraph 双目相机系统
        A["左相机<br/>Camera_L"]
        B["右相机<br/>Camera_R"]
    end
    
    subgraph 图像获取
        C["左图像<br/>Image_L"]
        D["右图像<br/>Image_R"]
    end
    
    subgraph 立体匹配
        E["视差计算<br/>Disparity Map"]
    end
    
    subgraph 深度重建
        F["深度图<br/>Depth Map"]
    end
    
    A --> C
    B --> D
    C --> E
    D --> E
    E --> F
    
    classDef cameraNode fill:#42a5f5,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    classDef imageNode fill:#66bb6a,stroke:#2e7d32,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    classDef disparityNode fill:#ffb74d,stroke:#e65100,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    classDef depthNode fill:#ef5350,stroke:#c62828,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    
    classDef cameraSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold
    classDef imageSubgraph fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20,font-weight:bold
    classDef disparitySubgraph fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#bf360c,font-weight:bold
    classDef depthSubgraph fill:#ffebee,stroke:#c62828,stroke-width:2px,color:#b71c1c,font-weight:bold
    
    class A,B cameraNode
    class C,D imageNode
    class E disparityNode
    class F depthNode
    
    class 双目相机系统 cameraSubgraph
    class 图像获取 imageSubgraph
    class 立体匹配 disparitySubgraph
    class 深度重建 depthSubgraph
    
    linkStyle 0,1 stroke:#1565c0,stroke-width:2px
    linkStyle 2,3 stroke:#2e7d32,stroke-width:2px
    linkStyle 4 stroke:#e65100,stroke-width:2px

图11.6:双目立体视觉系统的基本工作流程

视差(Disparity)是立体匹配的核心概念。它指的是同一物体在左右图像中对应点的水平位置差异。视差与深度成反比关系:距离相机越近的物体,其视差越大;距离相机越远的物体,其视差越小。无穷远处的物体(如天空)视差接近于零。

对应点问题是立体匹配的核心挑战。给定左图中的一个点,如何在右图中找到与之对应的点?这个看似简单的问题实际上非常复杂,尤其是在纹理缺乏、重复模式、遮挡区域等情况下。立体匹配算法的主要差异就在于如何解决这个对应点问题。

Code
graph LR
    subgraph 左图像
        A["参考点<br/>(x, y)"]
    end
    
    subgraph 右图像
        B["匹配点<br/>(x-d, y)"]
        C["非匹配点"]
    end
    
    A -->|"匹配搜索"| B
    A -.->|"错误匹配"| C
    
    subgraph 匹配约束
        D["极线约束"]
        E["唯一性约束"]
        F["顺序一致性约束"]
        G["视差平滑约束"]
    end
    
    D --> A
    E --> A
    F --> A
    G --> A
    
    classDef leftNode fill:#42a5f5,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    classDef rightNode fill:#66bb6a,stroke:#2e7d32,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    classDef wrongNode fill:#ef5350,stroke:#c62828,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    classDef constraintNode fill:#ba68c8,stroke:#7b1fa2,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    
    classDef leftSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold
    classDef rightSubgraph fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20,font-weight:bold
    classDef constraintSubgraph fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#4a148c,font-weight:bold
    
    class A leftNode
    class B rightNode
    class C wrongNode
    class D,E,F,G constraintNode
    
    class 左图像 leftSubgraph
    class 右图像 rightSubgraph
    class 匹配约束 constraintSubgraph
    
    linkStyle 0 stroke:#4caf50,stroke-width:2px
    linkStyle 1 stroke:#f44336,stroke-width:2px,stroke-dasharray:5 5
    linkStyle 2,3,4,5 stroke:#9c27b0,stroke-width:1.5px

graph LR
    subgraph 左图像
        A["参考点<br/>(x, y)"]
    end
    
    subgraph 右图像
        B["匹配点<br/>(x-d, y)"]
        C["非匹配点"]
    end
    
    A -->|"匹配搜索"| B
    A -.->|"错误匹配"| C
    
    subgraph 匹配约束
        D["极线约束"]
        E["唯一性约束"]
        F["顺序一致性约束"]
        G["视差平滑约束"]
    end
    
    D --> A
    E --> A
    F --> A
    G --> A
    
    classDef leftNode fill:#42a5f5,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    classDef rightNode fill:#66bb6a,stroke:#2e7d32,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    classDef wrongNode fill:#ef5350,stroke:#c62828,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    classDef constraintNode fill:#ba68c8,stroke:#7b1fa2,color:white,stroke-width:2px,font-weight:bold,font-size:14px,border-radius:8px
    
    classDef leftSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold
    classDef rightSubgraph fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20,font-weight:bold
    classDef constraintSubgraph fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#4a148c,font-weight:bold
    
    class A leftNode
    class B rightNode
    class C wrongNode
    class D,E,F,G constraintNode
    
    class 左图像 leftSubgraph
    class 右图像 rightSubgraph
    class 匹配约束 constraintSubgraph
    
    linkStyle 0 stroke:#4caf50,stroke-width:2px
    linkStyle 1 stroke:#f44336,stroke-width:2px,stroke-dasharray:5 5
    linkStyle 2,3,4,5 stroke:#9c27b0,stroke-width:1.5px

图11.7:立体匹配中的对应点问题与匹配约束

11.3 理论基础:从几何约束到深度学习

立体匹配与深度估计的理论基础可以分为传统几何方法和现代深度学习方法两大类。

11.3.1 传统几何方法的理论基础

1. 立体相机几何关系

在标准立体配置中,两个相机的光轴平行,图像平面共面。设左右相机的光心分别为O_LO_R,它们之间的距离(基线长度)为b。对于空间中的点P(X,Y,Z),其在左右图像中的投影点分别为p_L(x_L,y_L)p_R(x_R,y_R)。根据相似三角形原理:

\frac{x_L - x_R}{b} = \frac{f}{Z}

定义视差d = x_L - x_R,则深度与视差成反比关系:

Z = \frac{f \cdot b}{d}

2. 传统视差计算方法

传统方法主要基于匹配代价计算和优化:

  • 局部方法:使用窗口匹配,计算相似性度量如SAD、SSD或NCC:

\text{SAD}(x,y,d) = \sum_{(i,j) \in W} |I_L(i,j) - I_R(i-d,j)|

  • 全局方法:将视差计算视为能量最小化问题:

E(D) = E_{data}(D) + \lambda \cdot E_{smooth}(D)

  • 半全局方法(SGM):通过多方向路径聚合匹配代价,平衡局部和全局信息:

L_r(p,d) = C(p,d) + \min \begin{cases} L_r(p-r,d) \\ L_r(p-r,d-1) + P_1 \\ L_r(p-r,d+1) + P_1 \\ \min_i L_r(p-r,i) + P_2 \end{cases}

其中L_r(p,d)是沿方向r的路径代价,C(p,d)是像素p处视差为d的匹配代价,P_1P_2是平滑性惩罚参数。

11.3.2 深度学习方法的理论基础

1. 端到端深度估计框架

深度学习方法将立体匹配视为一个端到端的回归问题,网络架构通常包含四个关键组件:

  • 特征提取:使用CNN提取左右图像的特征表示
  • 代价体积构建:通过特征匹配或拼接构建4D代价体积
  • 代价聚合:使用3D CNN或GNN进行代价聚合
  • 视差回归:通过软argmin操作回归连续视差值

2. PSMNet的核心理论

PSMNet是深度学习立体匹配的代表性网络,其核心理论包括:

  • 空间金字塔池化(SPP):捕获多尺度上下文信息:

F_{SPP}(x) = \text{Concat}[F(x), P_1(F(x)), P_2(F(x)), ..., P_n(F(x))]

其中P_i表示不同尺度的池化操作。

  • 3D代价体积滤波:使用3D CNN进行代价聚合:

C_{out} = \text{3DCNN}(C_{in})

  • 视差回归:通过软argmin操作实现亚像素精度:

\hat{d} = \sum_{d=0}^{D_{max}} d \cdot \sigma(-C_d)

其中\sigma是softmax函数,C_d是代价体积中视差为d的代价值。

3. 单目深度估计理论

单目深度估计直接从单张图像预测深度,其理论基础是:

  • 编码器-解码器架构:通过多尺度特征提取和逐步上采样恢复分辨率
  • 深度回归:直接回归深度值或视差值
  • 自监督学习:利用时序一致性或立体一致性作为监督信号:

L_{photo} = \alpha \frac{1-\text{SSIM}(I, \hat{I})}{2} + (1-\alpha)||I-\hat{I}||_1

其中\hat{I}是通过预测的深度图和相机位姿重投影得到的图像。

这些理论方法的核心区别在于:传统方法依赖手工设计的特征和几何约束,而深度学习方法能够自动学习特征表示和匹配策略,特别是在复杂场景中表现出更强的鲁棒性。

11.4 算法实现

立体匹配与深度估计的实现可以分为传统几何方法和现代深度学习方法两大类。

传统SGBM算法核心

import cv2
import numpy as np

def sgbm_stereo_matching(left_img, right_img):
    """
    SGBM立体匹配核心算法
    核心思想:通过多方向路径聚合优化匹配代价
    """
    # 核心参数设置
    stereo = cv2.StereoSGBM_create(
        minDisparity=0,
        numDisparities=64,          # 视差搜索范围
        blockSize=5,                # 匹配窗口大小
        P1=8 * 3 * 5**2,           # 平滑性惩罚参数1
        P2=32 * 3 * 5**2,          # 平滑性惩罚参数2
        uniquenessRatio=10,         # 唯一性比率
        speckleWindowSize=100,      # 斑点滤波窗口
        speckleRange=32             # 斑点滤波范围
    )

    # 计算视差图
    disparity = stereo.compute(left_img, right_img)
    return disparity.astype(np.float32) / 16.0  # 转换为真实视差值

def disparity_to_depth(disparity, focal_length, baseline):
    """视差转深度的核心公式"""
    return (focal_length * baseline) / (disparity + 1e-6)

现代PSMNet深度网络

import torch
import torch.nn as nn
import torch.nn.functional as F

class PSMNet(nn.Module):
    """
    PSMNet核心架构
    核心思想:构建4D代价体积,通过3D CNN进行代价聚合
    """
    def __init__(self, maxdisp=192):
        super(PSMNet, self).__init__()
        self.maxdisp = maxdisp

        # 特征提取网络
        self.feature_extraction = self._make_feature_extractor()

        # 代价体积构建
        self.cost_volume_filter = self._make_cost_volume_filter()

        # 视差回归
        self.disparity_regression = self._make_disparity_regression()

    def forward(self, left, right):
        # 1. 特征提取
        left_features = self.feature_extraction(left)
        right_features = self.feature_extraction(right)

        # 2. 构建代价体积
        cost_volume = self.build_cost_volume(left_features, right_features)

        # 3. 代价聚合
        cost_volume = self.cost_volume_filter(cost_volume)

        # 4. 视差回归
        disparity = self.disparity_regression(cost_volume)

        return disparity

    def build_cost_volume(self, left_feat, right_feat):
        """构建4D代价体积的核心逻辑"""
        B, C, H, W = left_feat.shape
        cost_volume = torch.zeros(B, C*2, self.maxdisp//4, H, W)

        for i in range(self.maxdisp//4):
            if i > 0:
                cost_volume[:, :C, i, :, i:] = left_feat[:, :, :, i:]
                cost_volume[:, C:, i, :, i:] = right_feat[:, :, :, :-i]
            else:
                cost_volume[:, :C, i, :, :] = left_feat
                cost_volume[:, C:, i, :, :] = right_feat

        return cost_volume

单目深度估计核心

class MonoDepthNet(nn.Module):
    """
    单目深度估计网络核心
    核心思想:从单张图像直接回归深度图
    """
    def __init__(self):
        super(MonoDepthNet, self).__init__()
        # 编码器:提取多尺度特征
        self.encoder = self._make_encoder()
        # 解码器:逐步上采样恢复分辨率
        self.decoder = self._make_decoder()

    def forward(self, x):
        # 多尺度特征提取
        features = self.encoder(x)
        # 深度图回归
        depth = self.decoder(features)
        return depth

这些算法的核心区别在于:SGBM基于几何约束和手工特征,PSMNet通过学习特征和代价聚合,单目方法则完全依赖语义理解。现代方法在复杂场景下表现更佳,但计算成本也更高。

Code
flowchart TD
    A["输入立体图像对"] --> B["图像预处理<br/>灰度转换、滤波"]
    B --> C["特征提取<br/>梯度、Census变换等"]
    C --> D["代价计算<br/>SAD/SSD/Census等"]
    D --> E["代价聚合<br/>窗口聚合/路径聚合"]
    E --> F["视差优化<br/>赢家通吃/动态规划"]
    F --> G["视差细化<br/>亚像素插值、滤波"]
    G --> H["深度转换<br/>Z = f·b/d"]

    subgraph 预处理阶段
        A
        B
    end

    subgraph 匹配代价阶段
        C
        D
    end

    subgraph 优化阶段
        E
        F
        G
    end

    subgraph 后处理阶段
        H
    end

    classDef prepNode fill:#42a5f5,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,border-radius:8px
    classDef costNode fill:#ffb74d,stroke:#e65100,color:white,stroke-width:2px,font-weight:bold,border-radius:8px
    classDef optNode fill:#66bb6a,stroke:#2e7d32,color:white,stroke-width:2px,font-weight:bold,border-radius:8px
    classDef postNode fill:#ef5350,stroke:#c62828,color:white,stroke-width:2px,font-weight:bold,border-radius:8px

    classDef prepSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold
    classDef costSubgraph fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#bf360c,font-weight:bold
    classDef optSubgraph fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20,font-weight:bold
    classDef postSubgraph fill:#ffebee,stroke:#c62828,stroke-width:2px,color:#b71c1c,font-weight:bold

    class A,B prepNode
    class C,D costNode
    class E,F,G optNode
    class H postNode

    class 预处理阶段 prepSubgraph
    class 匹配代价阶段 costSubgraph
    class 优化阶段 optSubgraph
    class 后处理阶段 postSubgraph

    linkStyle 0,1,2,3,4,5,6 stroke-width:2px

flowchart TD
    A["输入立体图像对"] --> B["图像预处理<br/>灰度转换、滤波"]
    B --> C["特征提取<br/>梯度、Census变换等"]
    C --> D["代价计算<br/>SAD/SSD/Census等"]
    D --> E["代价聚合<br/>窗口聚合/路径聚合"]
    E --> F["视差优化<br/>赢家通吃/动态规划"]
    F --> G["视差细化<br/>亚像素插值、滤波"]
    G --> H["深度转换<br/>Z = f·b/d"]

    subgraph 预处理阶段
        A
        B
    end

    subgraph 匹配代价阶段
        C
        D
    end

    subgraph 优化阶段
        E
        F
        G
    end

    subgraph 后处理阶段
        H
    end

    classDef prepNode fill:#42a5f5,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,border-radius:8px
    classDef costNode fill:#ffb74d,stroke:#e65100,color:white,stroke-width:2px,font-weight:bold,border-radius:8px
    classDef optNode fill:#66bb6a,stroke:#2e7d32,color:white,stroke-width:2px,font-weight:bold,border-radius:8px
    classDef postNode fill:#ef5350,stroke:#c62828,color:white,stroke-width:2px,font-weight:bold,border-radius:8px

    classDef prepSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold
    classDef costSubgraph fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#bf360c,font-weight:bold
    classDef optSubgraph fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20,font-weight:bold
    classDef postSubgraph fill:#ffebee,stroke:#c62828,stroke-width:2px,color:#b71c1c,font-weight:bold

    class A,B prepNode
    class C,D costNode
    class E,F,G optNode
    class H postNode

    class 预处理阶段 prepSubgraph
    class 匹配代价阶段 costSubgraph
    class 优化阶段 optSubgraph
    class 后处理阶段 postSubgraph

    linkStyle 0,1,2,3,4,5,6 stroke-width:2px

图11.8:立体匹配算法的通用流程

11.5 性能对比分析

深度估计算法的效果可以通过视差图和深度图的质量来评估。下面我们分析传统方法和深度学习方法在不同场景下的表现。

算法性能对比

Code
graph TD
    subgraph 传统方法
        A["块匹配(BM)<br/>速度: 快<br/>精度: 低<br/>内存: 低"]
        B["半全局匹配(SGBM)<br/>速度: 中<br/>精度: 中<br/>内存: 低"]
        C["全局匹配(GC/BP)<br/>速度: 慢<br/>精度: 高<br/>内存: 中"]
    end

    subgraph 深度学习方法
        D["PSMNet<br/>速度: 慢<br/>精度: 很高<br/>内存: 高"]
        E["GANet<br/>速度: 很慢<br/>精度: 最高<br/>内存: 很高"]
        F["单目深度估计<br/>速度: 中<br/>精度: 中<br/>内存: 中"]
    end

    subgraph 性能指标
        G["KITTI 3px错误率"]
        H["Middlebury平均误差"]
        I["ETH3D完整性"]
    end

    A --> G
    B --> G
    C --> G
    D --> G
    E --> G
    F --> G

    G --> J["传统: 5-15%<br/>深度学习: 2-5%"]
    H --> K["传统: 1-3px<br/>深度学习: 0.5-1px"]
    I --> L["传统: 70-90%<br/>深度学习: 90-98%"]

    classDef tradNode fill:#64b5f6,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
    classDef dlNode fill:#ba68c8,stroke:#7b1fa2,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
    classDef metricNode fill:#66bb6a,stroke:#2e7d32,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
    classDef resultNode fill:#ffb74d,stroke:#e65100,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px

    classDef tradSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold
    classDef dlSubgraph fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#4a148c,font-weight:bold
    classDef metricSubgraph fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20,font-weight:bold

    class A,B,C tradNode
    class D,E,F dlNode
    class G,H,I metricNode
    class J,K,L resultNode

    class 传统方法 tradSubgraph
    class 深度学习方法 dlSubgraph
    class 性能指标 metricSubgraph

    linkStyle 0,1,2,3,4,5 stroke:#1565c0,stroke-width:1.5px
    linkStyle 6,7,8 stroke:#4caf50,stroke-width:1.5px

graph TD
    subgraph 传统方法
        A["块匹配(BM)<br/>速度: 快<br/>精度: 低<br/>内存: 低"]
        B["半全局匹配(SGBM)<br/>速度: 中<br/>精度: 中<br/>内存: 低"]
        C["全局匹配(GC/BP)<br/>速度: 慢<br/>精度: 高<br/>内存: 中"]
    end

    subgraph 深度学习方法
        D["PSMNet<br/>速度: 慢<br/>精度: 很高<br/>内存: 高"]
        E["GANet<br/>速度: 很慢<br/>精度: 最高<br/>内存: 很高"]
        F["单目深度估计<br/>速度: 中<br/>精度: 中<br/>内存: 中"]
    end

    subgraph 性能指标
        G["KITTI 3px错误率"]
        H["Middlebury平均误差"]
        I["ETH3D完整性"]
    end

    A --> G
    B --> G
    C --> G
    D --> G
    E --> G
    F --> G

    G --> J["传统: 5-15%<br/>深度学习: 2-5%"]
    H --> K["传统: 1-3px<br/>深度学习: 0.5-1px"]
    I --> L["传统: 70-90%<br/>深度学习: 90-98%"]

    classDef tradNode fill:#64b5f6,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
    classDef dlNode fill:#ba68c8,stroke:#7b1fa2,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
    classDef metricNode fill:#66bb6a,stroke:#2e7d32,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
    classDef resultNode fill:#ffb74d,stroke:#e65100,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px

    classDef tradSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold
    classDef dlSubgraph fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#4a148c,font-weight:bold
    classDef metricSubgraph fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20,font-weight:bold

    class A,B,C tradNode
    class D,E,F dlNode
    class G,H,I metricNode
    class J,K,L resultNode

    class 传统方法 tradSubgraph
    class 深度学习方法 dlSubgraph
    class 性能指标 metricSubgraph

    linkStyle 0,1,2,3,4,5 stroke:#1565c0,stroke-width:1.5px
    linkStyle 6,7,8 stroke:#4caf50,stroke-width:1.5px

图11.9:传统方法与深度学习方法的性能对比

场景适应性分析

Code
graph TD
    subgraph 场景特征
        A["纹理丰富<br/>结构清晰"]
        B["弱纹理区域<br/>重复模式"]
        C["反光表面<br/>透明物体"]
        D["遮挡区域<br/>边界不连续"]
    end

    subgraph 传统方法表现
        E["SGBM<br/>准确度: 高<br/>鲁棒性: 中"]
        F["BM<br/>准确度: 中<br/>鲁棒性: 低"]
        G["GC<br/>准确度: 高<br/>鲁棒性: 中"]
    end

    subgraph 深度学习方法表现
        H["PSMNet<br/>准确度: 很高<br/>鲁棒性: 高"]
        I["GANet<br/>准确度: 最高<br/>鲁棒性: 很高"]
        J["单目深度<br/>准确度: 中<br/>鲁棒性: 高"]
    end

    A --> E
    A --> H
    B --> G
    B --> I
    C --> F
    C --> J
    D --> G
    D --> I

    classDef sceneNode fill:#4db6ac,stroke:#00796b,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
    classDef tradNode fill:#64b5f6,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
    classDef dlNode fill:#ba68c8,stroke:#7b1fa2,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px

    classDef sceneSubgraph fill:#e0f2f1,stroke:#00796b,stroke-width:2px,color:#004d40,font-weight:bold
    classDef tradSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold
    classDef dlSubgraph fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#4a148c,font-weight:bold

    class A,B,C,D sceneNode
    class E,F,G tradNode
    class H,I,J dlNode

    class 场景特征 sceneSubgraph
    class 传统方法表现 tradSubgraph
    class 深度学习方法表现 dlSubgraph

    linkStyle 0,1,2,3,4,5,6,7 stroke-width:1.5px

graph TD
    subgraph 场景特征
        A["纹理丰富<br/>结构清晰"]
        B["弱纹理区域<br/>重复模式"]
        C["反光表面<br/>透明物体"]
        D["遮挡区域<br/>边界不连续"]
    end

    subgraph 传统方法表现
        E["SGBM<br/>准确度: 高<br/>鲁棒性: 中"]
        F["BM<br/>准确度: 中<br/>鲁棒性: 低"]
        G["GC<br/>准确度: 高<br/>鲁棒性: 中"]
    end

    subgraph 深度学习方法表现
        H["PSMNet<br/>准确度: 很高<br/>鲁棒性: 高"]
        I["GANet<br/>准确度: 最高<br/>鲁棒性: 很高"]
        J["单目深度<br/>准确度: 中<br/>鲁棒性: 高"]
    end

    A --> E
    A --> H
    B --> G
    B --> I
    C --> F
    C --> J
    D --> G
    D --> I

    classDef sceneNode fill:#4db6ac,stroke:#00796b,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
    classDef tradNode fill:#64b5f6,stroke:#1565c0,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
    classDef dlNode fill:#ba68c8,stroke:#7b1fa2,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px

    classDef sceneSubgraph fill:#e0f2f1,stroke:#00796b,stroke-width:2px,color:#004d40,font-weight:bold
    classDef tradSubgraph fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1,font-weight:bold
    classDef dlSubgraph fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#4a148c,font-weight:bold

    class A,B,C,D sceneNode
    class E,F,G tradNode
    class H,I,J dlNode

    class 场景特征 sceneSubgraph
    class 传统方法表现 tradSubgraph
    class 深度学习方法表现 dlSubgraph

    linkStyle 0,1,2,3,4,5,6,7 stroke-width:1.5px

图11.10:不同方法在各类场景中的适应性分析

深度学习方法的进展

Code
graph LR
    subgraph 网络架构演进
        A["2D CNN<br/>(DispNet, 2016)"]
        B["3D CNN<br/>(PSMNet, 2018)"]
        C["GNN<br/>(GwcNet, 2019)"]
        D["Transformer<br/>(STTR, 2021)"]
    end

    subgraph 关键技术创新
        E["代价体积构建"]
        F["多尺度特征融合"]
        G["注意力机制"]
        H["自监督学习"]
    end

    A --> B
    B --> C
    C --> D

    A --> E
    B --> F
    C --> G
    D --> H

    classDef archNode fill:#ef5350,stroke:#c62828,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
    classDef techNode fill:#66bb6a,stroke:#2e7d32,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px

    classDef archSubgraph fill:#ffebee,stroke:#c62828,stroke-width:2px,color:#b71c1c,font-weight:bold
    classDef techSubgraph fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20,font-weight:bold

    class A,B,C,D archNode
    class E,F,G,H techNode

    class 网络架构演进 archSubgraph
    class 关键技术创新 techSubgraph

    linkStyle 0,1,2 stroke:#f44336,stroke-width:1.5px
    linkStyle 3,4,5,6 stroke:#4caf50,stroke-width:1.5px

graph LR
    subgraph 网络架构演进
        A["2D CNN<br/>(DispNet, 2016)"]
        B["3D CNN<br/>(PSMNet, 2018)"]
        C["GNN<br/>(GwcNet, 2019)"]
        D["Transformer<br/>(STTR, 2021)"]
    end

    subgraph 关键技术创新
        E["代价体积构建"]
        F["多尺度特征融合"]
        G["注意力机制"]
        H["自监督学习"]
    end

    A --> B
    B --> C
    C --> D

    A --> E
    B --> F
    C --> G
    D --> H

    classDef archNode fill:#ef5350,stroke:#c62828,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px
    classDef techNode fill:#66bb6a,stroke:#2e7d32,color:white,stroke-width:2px,font-weight:bold,font-size:13px,border-radius:8px

    classDef archSubgraph fill:#ffebee,stroke:#c62828,stroke-width:2px,color:#b71c1c,font-weight:bold
    classDef techSubgraph fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1b5e20,font-weight:bold

    class A,B,C,D archNode
    class E,F,G,H techNode

    class 网络架构演进 archSubgraph
    class 关键技术创新 techSubgraph

    linkStyle 0,1,2 stroke:#f44336,stroke-width:1.5px
    linkStyle 3,4,5,6 stroke:#4caf50,stroke-width:1.5px

图11.11:深度学习立体匹配方法的技术演进

11.6 小结

立体匹配与深度估计是三维视觉的核心技术,经历了从传统几何方法到深度学习方法的重要演进。传统方法如SGBM基于几何约束和手工特征,计算效率高但在复杂场景下容易失效。现代深度学习方法如PSMNet通过端到端学习,在准确性和鲁棒性方面显著超越传统方法。

本节的核心贡献在于:理论层面,阐述了从视差计算到深度回归的算法演进逻辑;技术层面,对比了传统方法和深度学习方法的核心差异;应用层面,分析了不同方法在各类场景中的适应性。

深度估计技术与相机标定紧密相连:准确的相机标定是高质量深度估计的前提。同时,深度估计也为后续的三维重建和点云处理提供了基础数据。随着Transformer等新架构的引入,深度估计正朝着更高精度、更强泛化能力的方向发展,在自动驾驶、机器人等领域发挥着越来越重要的作用。