CV - 8: 双目立体视觉 (Stereo Vision)
8.1 双目立体视觉概述
8.1.1 问题定义
Two-View Stereo(双目立体视觉):
- 输入:一对已标定的立体图像对(calibrated stereo pair)
- 输出:密集深度图(dense depth map)
双目立体视觉通过模拟人类双眼视觉系统,利用两个不同位置拍摄的图像来重建场景的三维信息。
8.1.2 基本原理
3D重建 = 对应关系(Correspondence) + 三角测量(Triangulation)
基本流程:
- 对于第一张图像中的每个像素
- 找到第二张图像中的对应极线(epipolar line)
- 在极线上搜索最佳匹配点
- 通过三角测量计算深度信息
8.2 简单立体系统
8.2.1 平行立体配置
最简单的情况:极线 = 对应的扫描线
配置要求:
- 两相机的图像平面相互平行
- 图像平面与基线(baseline)平行
- 两相机中心位于同一高度
- 焦距相同
结果:极线沿着图像的水平扫描线排列
8.2.2 简单立体系统的本质矩阵
对于简单立体系统,本质矩阵\(\mathbf{E}\)可以简化:
\[\mathbf{R} = \mathbf{I}, \quad \mathbf{t} = (t, 0, 0)\] \[\mathbf{E} = [\mathbf{t}]_{\times}\mathbf{R} = \begin{bmatrix} 0 & 0 & 0 \\ 0 & 0 & -t \\ 0 & t & 0 \end{bmatrix}\]由对极约束 \(\mathbf{x}'^T\mathbf{E}\mathbf{x} = 0\):
\[(u' \ v' \ 1) \begin{bmatrix} 0 & 0 & 0 \\ 0 & 0 & -t \\ 0 & t & 0 \end{bmatrix} \begin{pmatrix} u \\ v \\ 1 \end{pmatrix} = 0\]可得:\(v = v'\)
结论:对应点的\(v\)坐标相同!
8.3 立体图像校正
8.3.1 校正的必要性
对于一般的立体系统,图像平面通常不平行。我们可以使用立体校正(Stereo Rectification)将图像投影到平行于基线的公共平面上。
8.3.2 校正算法
步骤:
- 从本质矩阵或基础矩阵计算\(R_1\)
- 旋转右相机\(R_1\)以对齐两相机的方向
- 旋转两相机\(R_{rect}\)使图像平面平行于基线(即将原始极点映射到无穷远)
- 缩放图像\(H\)以减少畸变
8.3.3 计算校正旋转矩阵
计算极点\(e_1\):
- 使用SVD分解,因为\(\mathbf{F}e_1 = 0\)
构造\(R_{rect} = (r_1, r_2, r_3)^T\):
\[r_1 = \frac{e_1}{\|e_1\|}\] \[r_2 = \frac{[0,0,1]^T \times r_1}{\|[0,0,1]^T \times r_1\|}\] \[r_3 = r_1 \times r_2\]结果:\(R_{rect}e_1 = (\|e_1\|, 0, 0)^T\),这是一个无穷远点
8.4 视差与深度
8.4.1 视差(Disparity)
视差:对应点在两幅图像中的水平位置差
\[d = x - x'\]8.4.2 深度计算
对于简单立体系统,通过相似三角形:
\[\frac{x}{f} = \frac{B_1}{z}, \quad \frac{-x'}{f} = \frac{B_2}{z}\] \[\frac{x - x'}{f} = \frac{B_1 + B_2}{z} = \frac{B}{z}\]深度公式:
\[\boxed{z = \frac{fB}{x - x'} = \frac{fB}{d}}\]其中:
- \(f\):焦距
- \(B\):基线长度
- \(d = x - x'\):视差
重要性质:视差与深度成反比!
8.4.3 基线的影响
较大基线:
- ✅ 较小的三角测量误差(更精确)
- ❌ 匹配更困难(视角差异大)
较小基线:
- ❌ 较大的三角测量误差
- ✅ 匹配更容易
8.5 局部立体匹配
8.5.1 相似性度量
考虑两个\(K \times K\)窗口的像素展平为向量\(\mathbf{w}_L, \mathbf{w}_R \in \mathbb{R}^{K^2}\)
平方差之和(SSD):
\[\text{SSD}(x, y, d) = \|\mathbf{w}_L(x, y) - \mathbf{w}_R(x - d, y)\|_2^2\]零均值归一化互相关(ZNCC):
\[\text{ZNCC}(x, y, d) = \frac{(\mathbf{w}_L(x, y) - \bar{w}_L(x, y))^T (\mathbf{w}_R(x - d, y) - \bar{w}_R(x - d, y))}{\|\mathbf{w}_L(x, y) - \bar{w}_L(x, y)\|_2 \|\mathbf{w}_R(x - d, y) - \bar{w}_R(x - d, y)\|_2}\]其中\(\bar{w}\)是向量的均值。
8.5.2 算法流程
- 选择视差范围\([0, D]\)
- 对于每个像素\(x = (x, y)\),计算最佳视差: \(d^*(x, y) = \arg\min_{d \in [0,D]} C(x, y, d)\)
- 对两幅图像都执行匹配
- 应用左右一致性检查去除异常值
8.5.3 窗口大小的影响
小窗口(如5×5):
- ✅ 更多细节
- ❌ 更多噪声
大窗口(如11×11):
- ✅ 更平滑的结果
- ❌ 细节丢失
8.5.4 半遮挡
半遮挡(Half Occlusions):某些区域在一幅图像中可见,但在另一幅图像中不可见。
影响:在输出深度图中产生裂缝或空洞。
8.5.5 失败情况
- 无纹理区域:平坦区域难以找到可靠的对应关系
- 重复模式:周期性纹理导致歧义
- 非朗伯表面:镜面反射导致在不同视角下外观变化
8.6 全局立体匹配
8.6.1 非局部约束
局部立体匹配独立地为每个窗口找到最佳匹配。需要引入非局部约束进行全局优化。
常见约束:
-
唯一性(Uniqueness):一幅图像中的每个点最多匹配另一幅图像中的一个点
-
顺序性(Ordering):对应点应以相同的顺序出现
-
平滑性(Smoothness):相邻点应有相似的视差值
8.6.2 能量函数
\[E(d) = E_d(d) + \lambda E_s(d)\]数据项(Data term):
\[E_d(d) = \sum_{(x,y) \in I} C(x, y, d(x, y))\]测量窗口匹配的质量(如SSD)
平滑项(Smoothness term):
\[E_s(d) = \sum_{(p,q) \in \mathcal{E}} V(d_p, d_q)\]其中\(\mathcal{E}\)是相邻像素的集合(4连通或8连通)
目标:最小化总能量\(E(d)\)
8.6.3 视差空间图像
Disparity Space Image (DSI):
- 将对角线上的有效值重新排列成矩形数组
- 每条路径对应一个立体匹配
- 寻找最低代价路径
8.6.4 动态规划求解
对应类型:
- 匹配:添加匹配代价(小代价如果强度一致)
- 遮挡:添加无匹配代价(大代价)
递推公式:
\[C(i,j) = \min \begin{cases} C(i-1, j-1) + e(i, j) & \text{匹配} \\ C(i-1, j) + \text{occlusion} & \text{左图遮挡} \\ C(i, j-1) + \text{occlusion} & \text{右图遮挡} \end{cases}\]复杂度:\(O(MN)\),其中\(M\)和\(N\)是图像尺寸
Python实现示例:
import numpy as np
# 初始化
n, m = 5, 7
C = np.full((n, m), float('inf'))
e = np.random.rand(n, m)
# 基础情况:初始化第一列
for i in range(n):
C[i][0] = 0
# 填充代价表
for j in range(1, m):
for i in range(n):
for k in range(n):
C[i][j] = min(C[i][j], e[k][j] + C[k][j - 1])
8.6.5 遮挡填充
左遮挡像素填充:用扫描线中前面最近的有效像素值填充
右遮挡像素填充:用扫描线中后面最近的有效像素值填充
8.7 动态规划的应用:接缝裁剪
8.7.1 Seam Carving算法
动态规划不仅用于立体匹配,还用于接缝裁剪(Seam Carving)实现内容感知的图像缩放。
算法:找到最小能量的接缝(seam)
\[s^* = \min_s E(s) = \min_s \sum_{i=1}^n e(\mathbf{I}(s_i))\]其中能量函数\(e_1(\mathbf{I})\)可以是梯度:
\[e_1(\mathbf{I}) = \left|\frac{\partial}{\partial x}\mathbf{I}\right| + \left|\frac{\partial}{\partial y}\mathbf{I}\right|\]递推公式:
\[M(i,j) = e(i,j) + \min(M(i-1,j-1), M(i-1,j), M(i-1,j+1))\]应用:
- 图像缩放(保持重要内容)
- 全景图像矩形化
8.8 深度学习方法
8.8.1 监督学习
MC-CNN (CVPR 2015):使用CNN学习匹配代价
网络结构:
- 输入:两个图像块\(x\)和\(x'\)
- 使用Siamese网络(共享权重)提取特征
- 输出:归一化特征向量
- 计算相似度:\(x^T x'\)
- 损失函数:SVM/Hinge loss
8.8.2 无监督学习
思想:利用几何约束作为监督信号
流程:
- 左图像\(I_l(x)\)通过深度CNN预测逆深度\(D(x) = fB/d(x)\)
- 使用视差进行逆向扭曲:\(I_w(x) = I_r(x + D(x))\)
- 重建误差作为损失:\(\|I_w(x) - I_l(x)\|\)
优点:不需要标注的深度真值
8.9 主动立体视觉
8.9.1 结构光
Active Stereo with Structured Light:
- 投射”结构化”光模式到物体上
- 简化对应问题
- 使用一个相机和一个投影仪
常见模式:
- 彩色条纹
- 编码图案
- 点阵模式
8.9.2 Kinect
Microsoft Kinect:
- 使用红外结构光
- 投射红外点阵图案
- 通过模式匹配计算深度
组件:
- 红外投影仪(IR Projector)
- 左/右红外相机(IR Imagers)
- RGB相机
8.9.3 Apple TrueDepth
组件:
- 红外相机
- 泛光照明器
- 点阵投影仪
- 接近传感器
应用:Face ID、AR表情、人像模式
8.9.4 激光扫描
光学三角测量:结构光扫描的高精度版本
- 投射单条激光光带
- 在物体表面扫描
- 高精度重建
著名应用:Digital Michelangelo Project(数字米开朗基罗计划)
- 扫描大卫像等艺术品
- 亚毫米级精度
- 生成数十亿三角面片的模型
8.10 立体数据集
8.10.1 Middlebury Stereo Dataset
经典的立体视觉基准数据集,包含:
- 精确标定的立体图像对
- 结构光扫描的真值深度
- 多种场景(室内物体、复杂纹理)
8.10.2 KITTI Dataset
自动驾驶立体数据集:
- 真实道路场景
- 激光雷达深度真值
- 相机标定参数
- 多种天气和光照条件
8.10.3 合成数据
优势:
- 完美的真值深度
- 可控的场景参数
- 大规模数据生成
8.11 现代3D重建技术
8.11.1 KinectFusion (2011)
特点:
- 实时密集3D重建
- 使用体素表示(TSDF)
- GPU加速
- 相机跟踪与重建同步
8.11.2 DynamicFusion (2015)
扩展:
- 非刚性场景重建
- 实时人体捕捉
- 变形跟踪
- 规范空间表示
8.12 总结
8.12.1 双目立体视觉管线
- 立体校正:使极线对齐到扫描线
- 匹配代价计算:SSD、ZNCC等相似性度量
- 代价聚合:窗口匹配或全局优化
- 视差计算:最小化匹配代价
- 视差后处理:左右一致性检查、遮挡填充
- 深度计算:\(z = fB/d\)
8.12.2 方法对比
| 方法 | 优点 | 缺点 |
|---|---|---|
| 局部立体匹配 | 快速、易实现 | 噪声多、边界模糊 |
| 全局优化 | 平滑结果、边界清晰 | 计算量大 |
| 深度学习 | 性能最优 | 需要大量数据 |
| 主动立体 | 鲁棒、适用无纹理 | 需要额外硬件 |
8.12.3 挑战与未来方向
当前挑战:
- 无纹理区域
- 重复纹理
- 透明/反射物体
- 遮挡处理
未来方向:
- 端到端深度学习
- 多视图立体
- 动态场景重建
- 神经隐式表示(NeRF等)
参考资料
- 教材:Computer Vision: Algorithms and Applications (2nd Edition), Chapter 12
- 论文:
- Y. Boykov, O. Veksler, R. Zabih. “Fast Approximate Energy Minimization via Graph Cuts.” PAMI 2001
- J. Zbontar, Y. LeCun. “Computing the Stereo Matching Cost with a Convolutional Neural Network.” CVPR 2015
- R. Garg et al. “Unsupervised CNN for Single View Depth Estimation: Geometry to the Rescue.” ECCV 2016
Enjoy Reading This Article?
Here are some more articles you might like to read next: