3. 深度估计基础:三角测量原理与视差公式

深度估计,说白了就是让计算机知道物体离我们有多远。在3D显示里,这是最核心的一步。没有深度,就没有立体感。

我个人习惯把深度估计比作「人眼测距」。你想想看,我们两只眼睛看东西,为什么能判断远近?因为左右眼看到的画面不一样。这个「不一样」,就是视差。而视差和深度之间的关系,全靠三角测量来算。

3.1 三角测量:老祖宗的智慧

三角测量不是什么新鲜事。几百年前的测绘员就在用。原理很简单:已知两个点之间的距离,再测出两个角度,就能算出第三个点的位置。

在3D视觉里,两个点就是左右摄像头(或者你的左右眼),第三个点就是目标物体。我刚开始做双目视觉时,总觉得这原理太简单,能有多准?后来在项目里踩过坑才明白——原理简单,但工程实现全是细节。

核心思想:已知基线长度 B 和两个视角的夹角,通过相似三角形计算深度 Z。

来看一个标准模型。左右两个相机光心距离为 B(基线),目标点 P 在左相机成像点为 xL,在右相机成像点为 xR。焦距为 f。

三角测量原理图 L R 基线 B P 成像平面 xL xR f Z 视差 d = xL - xR

3.2 深度与视差的数学推导

好,现在我们来推公式。别怕,就是初中几何。

从上面的图可以看出,两个三角形是相似的:

  • 左相机光心、目标点 P、左成像点 xL 构成一个三角形
  • 右相机光心、目标点 P、右成像点 xR 构成另一个三角形

根据相似三角形关系:

Z / f = B / (xL - xR)

这里 xL - xR 就是视差 d。所以:

深度公式:Z = (f × B) / d

这个公式太重要了。我建议你把它刻在脑子里。它告诉我们三件事:

  1. 深度与视差成反比——视差越大,物体越近
  2. 深度与基线成正比——两只眼分得越开,测距越准
  3. 深度与焦距成正比——长焦镜头看得更远,但视野窄

我的经验:实际项目中,基线 B 不是越大越好。基线太大,左右视图差异过大,匹配会失败。我做过一个户外测距项目,基线设了 30cm,结果近处物体匹配全崩了。后来改成 10cm,效果反而更好。

3.3 视差与深度的数值关系

我们来看一组典型数据。假设焦距 f = 1000 像素,基线 B = 10cm:

深度 Z (m) 视差 d (像素) 深度变化 1cm 对应的视差变化
0.5 200.0 3.92 像素
1.0 100.0 0.99 像素
2.0 50.0 0.25 像素
5.0 20.0 0.04 像素
10.0 10.0 0.01 像素

看到问题了吗?距离越远,视差越小。到了 10 米,深度变化 1cm 只带来 0.01 像素的视差变化。普通相机根本分辨不出来。

避坑指南:我曾经在一个自动驾驶项目里用双目测距,要求测到 100 米。算了一下,视差只有 1 个像素。1 个像素的误差,深度误差就是 100 米。这根本没法用。后来我们换成了激光雷达。记住:双目视觉的精度随距离平方衰减。

3.4 亚像素精度:突破像素限制

既然像素精度不够,怎么办?用亚像素。说白了,就是在一个像素内部再插值。

常用的方法有:

  • 抛物线拟合:用匹配代价的峰值附近三个点拟合抛物线,找到亚像素极值点
  • 二次曲线插值:类似,但用更多点做曲线拟合
  • 相位相关:在频域做亚像素位移估计

我一般用抛物线拟合,简单够用。代码大概长这样:

// 抛物线拟合求亚像素视差
// c0, c1, c2 是三个相邻像素的匹配代价
float subpixel_disparity(float c0, float c1, float c2) {
    float denom = c0 + c2 - 2.0f * c1;
    if (fabs(denom) < 1e-6f) return 0.0f;
    return (c0 - c2) / (2.0f * denom);
}

这个函数返回的是相对于中心像素的偏移量,范围在 [-0.5, 0.5] 之间。加上整数视差,就是亚像素视差。

我的建议:亚像素精度能做到 0.1 像素就不错了。别指望 0.01 像素,那需要信噪比极高的图像,现实中很难达到。

3.5 深度估计的误差来源

公式 Z = fB/d 看起来很完美,但实际用起来全是坑。我列几个最常见的:

误差来源 影响 缓解方法
相机标定误差 f 和 B 不准,深度整体偏移 用棋盘格做高精度标定
匹配误差 视差 d 找错 用更鲁棒的匹配算法
量化误差 像素离散化导致精度损失 亚像素插值
镜头畸变 图像变形导致视差偏移 畸变校正
光照变化 左右图亮度不一致 直方图匹配或归一化

嗯,这里要注意。标定误差是系统性的,一旦标定好就固定了。匹配误差是随机的,每帧都可能不一样。我做过一个项目,标定完觉得精度还行,一换场景全废了。后来发现是温度变化导致相机光心偏移了。所以工业级应用要加温控。

3.6 本章小结

深度估计的核心就一句话:Z = fB/d。但这个公式背后,是三角测量的几何原理、亚像素的工程技巧、以及对各种误差的清醒认识。

我个人觉得,理解深度估计最好的方式就是动手算一遍。拿尺子量一下你的两眼距离(大概 6-7cm),再估算一下你看手机时的视差。你会发现,公式虽然简单,但每个参数的选择都有讲究。

记住三个关键点:

  • 深度与视差成反比——近处物体视差大,远处视差小
  • 精度随距离平方衰减——双目视觉不适合远距离测距
  • 亚像素是工程必备——没有亚像素,深度图全是锯齿