3. 相机标定原理:张正友标定法详解,内参、外参、畸变系数的物理意义

说到双目测距,有个坎儿你绕不过去——相机标定。

我刚开始做双目的时候,觉得标定就是个“拍棋盘、跑代码”的流程。直到有一次,我拿着标定好的相机去测一个1米外的目标,结果误差直接飙到了5厘米。排查了半天,发现是标定板没放平,畸变参数全偏了。嗯,从那以后,我再也不敢小看标定这一步了。

说白了,相机标定就是给相机“量体裁衣”。你得知道它内部长什么样(内参),它放在什么位置(外参),以及它有没有“近视散光”(畸变)。今天我们就来拆解张正友标定法——这个在计算机视觉界被用到烂、但依然经典的方法。

3.1 为什么要标定?

你想想看,相机把三维世界投影到二维图像上,这个过程是有损失的。我们做双目测距,本质上是想从两张二维图里反推出三维信息。如果不知道相机本身的“脾气”,那反推出来的结果肯定不准。

标定的目的就两个:

  • 建立数学模型:把现实世界的点 (X, Y, Z) 和图像上的像素 (u, v) 对应起来
  • 消除畸变:镜头不是完美的,边缘会扭曲,得校正回来

我个人习惯,每次换镜头或者重新拧紧相机,都会重新标定一次。别偷懒,机械结构稍微动一下,参数就变了。

3.2 张正友标定法核心思想

张正友在1998年提出的这个方法,厉害在哪?它只需要你拍几张棋盘格照片,不需要知道相机运动轨迹,也不需要精密的3D标定物。一张打印的棋盘纸就够了。

核心逻辑是这样的:

  1. 假设棋盘格在三维空间中是平面(Z=0)
  2. 通过角点检测,找到棋盘格上每个角点在图像中的位置
  3. 利用单应性矩阵(Homography)建立世界坐标和图像坐标的关系
  4. 从多张不同角度的照片中,解算出内参和外参
  5. 最后用最小二乘法优化畸变系数

关键点:张正友标定法不需要知道相机在拍摄每张照片时的具体位置,它通过多张照片之间的几何约束来“自洽”地求解参数。这就是它为什么这么流行的原因——操作简单,结果可靠。

下面这张图是我自己画的,帮你理清整个标定的知识脉络:

张正友标定法知识结构图 输入:多张不同角度的棋盘格照片 步骤1:角点检测 提取棋盘格内角点的像素坐标 (u, v) 步骤2:计算单应性矩阵 H 建立世界坐标 (X, Y, 0) 与像素坐标的映射 步骤3:求解内参矩阵 K 利用多张 H 的约束,解出 fx, fy, cx, cy 输出结果 内参 (fx, fy, cx, cy) 外参 (R, t) 每张照片不同 畸变系数 (k1, k2, p1, p2, k3) ↓ 最终用于双目极线校正和三维重建

3.3 内参的物理意义

内参矩阵长这样:

K = [fx   0   cx
     0   fy   cy
     0    0    1]

每个参数都有实实在在的物理含义:

  • fx, fy:焦距在像素单位下的值。fx = F / dx,其中 F 是物理焦距(毫米),dx 是每个像素的物理宽度(毫米/像素)。说白了,fx 越大,说明同样距离的物体在图像上占的像素越多,也就是“放大倍数”越大。
  • cx, cy:主点坐标,也就是光轴与成像平面的交点。理想情况下应该在图像正中心,但实际装配总有偏差。我遇到过一台相机,cx 偏了20多个像素,如果不校正,测距误差直接偏了3%。

我的经验:标定完一定要看一眼 cx, cy 的值。如果它们偏离图像中心太多(比如超过图像宽度的5%),说明镜头安装可能有偏心,建议重新固定相机再标一次。

3.4 外参的物理意义

外参描述的是相机坐标系和世界坐标系之间的变换关系:

[R | t]  其中 R 是 3x3 旋转矩阵,t 是 3x1 平移向量

在双目系统中,外参有两层含义:

  1. 单张照片的外参:相机相对于棋盘格的位置和朝向。这个在张正友标定中每张照片都不同,我们其实不关心它,只是用它来辅助求解内参。
  2. 双目系统的外参:左相机相对于右相机的位置和朝向。这才是我们真正需要的!它描述了左右相机之间的“基线”长度和旋转关系。

我记得有一次做双目测距,基线长度标出来是120mm,但我实际量出来是119.5mm。差了0.5mm,测10米外的目标误差就大了将近4厘米。所以外参的精度直接影响测距精度,这一点怎么强调都不过分。

3.5 畸变系数的物理意义

镜头不是完美的,光线经过透镜会发生弯曲。畸变主要分两类:

畸变类型 参数 物理表现
径向畸变 k1, k2, k3 图像边缘的直线变弯。k1 控制主要畸变量,k2 控制边缘更远处的畸变,k3 用于高畸变镜头(比如鱼眼)。
切向畸变 p1, p2 镜头和成像平面不平行导致的畸变。表现为图像中的矩形变成梯形。

畸变校正的公式是这样的:

x_distorted = x * (1 + k1*r^2 + k2*r^4 + k3*r^6) + 2*p1*x*y + p2*(r^2 + 2*x^2)
y_distorted = y * (1 + k1*r^2 + k2*r^4 + k3*r^6) + p1*(r^2 + 2*y^2) + 2*p2*x*y

其中 r^2 = x^2 + y^2,x, y 是归一化平面上的坐标。

避坑指南:我曾经用一张畸变很大的照片去标定,结果 k1 跑到了 -0.8 以上。校正后图像边缘出现了严重的“枕形”扭曲。后来发现是标定板太靠近图像边缘了。记住:标定板要覆盖画面的各个区域,尤其是四个角和中心,这样才能准确估计畸变参数。

3.6 标定流程中的实操要点

说了这么多理论,最后给几个实操建议:

  • 棋盘格尺寸要准:每个格子的物理尺寸(比如30mm)必须精确测量。我见过有人随便写个25mm,结果标定出来的焦距全偏了。
  • 照片数量要够:至少15-20张。角度要丰富——左右倾斜、上下倾斜、旋转,都要有。别全拍正面的,那样解不出内参。
  • 重投影误差:标定完成后,看看重投影误差。一般小于0.5像素就算不错,超过1像素就要检查了。
  • 双目标定要同步:左右相机同时拍摄同一块棋盘格,这样才能解出左右相机之间的外参。

嗯,标定这部分就讲到这里。参数的意义搞清楚了,你才知道标定程序在算什么,出了问题也知道往哪个方向排查。下一节我们会把这些参数用起来,做极线校正和立体匹配。


公众号:蓝海资料掘金营,微信deep3321