第二章 成像模型:针孔相机模型详解、世界坐标系到像素坐标系的四大变换

聊到单目视觉标定,绕不开的第一个核心概念就是——针孔相机模型。

很多人觉得这东西太理论,上来就想直接调OpenCV的calibrateCamera()。我刚开始做视觉的时候也这么干过,结果标出来的参数怎么都不对,后来才发现是连最基本的成像模型都没吃透。说白了,你连相机怎么把三维世界变成二维图像的都不清楚,标定出来的内参外参你敢用吗?

2.1 针孔相机模型——最朴素的成像原理

针孔相机模型,名字很形象。想象一个密闭的盒子,前面戳一个小孔,光线穿过小孔在后面的感光面上成像。这就是最原始的相机。

数学上,我们用光心(小孔的位置)、成像平面(感光面)、焦距(光心到成像平面的距离)来描述这个过程。

核心假设:针孔模型假设所有光线都直线传播,且只通过光心这一个点。实际镜头有畸变,那是后面章节要处理的事。

这里有个关键点:针孔成像是倒立的。为了数学上方便,我们通常把成像平面“虚拟”地翻到光心前面,这样图像就是正立的,计算也简单很多。这个虚拟平面叫归一化平面。

我的习惯:在推导公式时,我永远用虚拟成像平面。它让坐标系变换变得非常直观,不容易搞混正负号。

2.2 四大坐标系——从世界到像素的“接力赛”

一个三维点怎么变成图像上的像素?中间要经过四次坐标变换。我把它叫做“接力赛”:

  1. 世界坐标系 → 相机坐标系(刚体变换)
  2. 相机坐标系 → 图像物理坐标系(透视投影)
  3. 图像物理坐标系 → 图像像素坐标系(离散化)

等等,题目说四大变换,这里只有三个?别急,第四个其实是畸变校正,它穿插在第二步和第三步之间。我们先把前三步讲透。

2.2.1 世界坐标系 → 相机坐标系(外参登场)

世界坐标系是客观的,相机坐标系是以相机光心为原点的。两者之间差了一个旋转和一个平移。

数学表达:

P_c = R * P_w + t

其中:

  • P_w:世界坐标系下的点 (X, Y, Z)
  • R:3x3 旋转矩阵
  • t:3x1 平移向量
  • P_c:相机坐标系下的点 (X_c, Y_c, Z_c)

我曾经踩过的坑:旋转矩阵有9个参数,但自由度只有3。直接用9个参数去优化,结果矩阵不再正交,标定出来的外参完全不能用。后来我改用旋转向量(Rodrigues)表示,才解决了这个问题。

2.2.2 相机坐标系 → 图像物理坐标系(透视投影)

这一步是真正的“成像”。根据相似三角形原理:

x = f * X_c / Z_c
y = f * Y_c / Z_c

这里 (x, y) 是图像物理坐标,单位是毫米。f 是焦距。

你想想看,这里出现了除法,所以这个变换是非线性的。这也是为什么相机标定不能简单地用线性代数一步求解的原因。

2.2.3 图像物理坐标系 → 图像像素坐标系(离散化)

物理坐标是连续的,像素坐标是离散的。我们需要把毫米转换成像素:

u = x / dx + u0
v = y / dy + v0

其中:

  • dx, dy:每个像素的物理尺寸(毫米/像素)
  • (u0, v0):主点坐标(光心在像素坐标系下的位置)

把上面三步合并,写成齐次坐标形式,就是大名鼎鼎的相机内参矩阵 K:

K = [fx  0  u0
     0  fy  v0
     0   0   1]

其中 fx = f/dx,fy = f/dy。

注意:fx 和 fy 通常不相等,因为像素不是完美的正方形。这也是标定要解的参数之一。

2.3 完整的投影方程

把外参和内参合在一起,一个三维点 P_w 到像素坐标 p 的完整变换是:

p = K * [R | t] * P_w

用齐次坐标展开:

s * [u, v, 1]^T = K * [R | t] * [X, Y, Z, 1]^T

这里的 s 是尺度因子,等于 Z_c。为什么会有它?因为从3D到2D丢失了深度信息,同一个像素点对应的是空间中的一条射线。

2.4 知识结构总览

下面这张图,是我做标定项目时一定会贴在工位上的。它把整个成像模型串起来了:

针孔相机模型:四大坐标系变换流程 世界坐标系 (X, Y, Z) 客观世界 R, t 相机坐标系 (Xc, Yc, Zc) 透视投影 图像物理坐标系 (x, y) 毫米 离散化 像素坐标系 (u, v) 像素 内参矩阵 K fx, fy, u0, v0 畸变系数 k1, k2, p1, p2 外参矩阵 [R | t] 旋转 R(3x3) 平移 t(3x1) 畸变校正(第4步) 径向畸变:桶形/枕形 切向畸变:镜头倾斜 校正 完整投影方程:s * [u, v, 1]^T = K * [R | t] * [X, Y, Z, 1]^T 标定的本质:从多组 (u,v) 和 (X,Y,Z) 的对应关系中,求解 K 和 [R|t]

2.5 畸变——理想模型的“现实修正”

针孔模型是理想情况。实际镜头有加工误差,光线不是完美直线。这就引出了畸变。

畸变主要分两类:

畸变类型 产生原因 数学模型 典型表现
径向畸变 镜头曲率不完美 δr = k1*r^3 + k2*r^5 + k3*r^7 桶形(广角)、枕形(长焦)
切向畸变 镜头与感光面不平行 δx = 2*p1*x*y + p2*(r^2+2*x^2) 图像倾斜、梯形失真

我的经验:对于手机镜头或广角摄像头,径向畸变的前两项(k1, k2)就够用了。但对于鱼眼镜头,必须用到 k3 甚至更高阶项。切向畸变一般很小,p1, p2 通常接近零。

2.6 标定到底在标什么?

现在可以回答这个问题了。相机标定,就是求解:

  • 内参:fx, fy, u0, v0, k1, k2, p1, p2(可能还有 k3)
  • 外参:每张标定图片对应的 R 和 t

你想想看,一个内参加若干外参,少说几十个未知数。怎么解?靠的是多张不同角度的标定板图片,建立超定方程组,然后用最小二乘法优化。

我曾经犯过的错:一开始只拍了3张标定板图片,觉得够了。结果标出来的内参,换一组图片就变。后来才知道,标定板图片至少要10-20张,而且必须覆盖视野的各个区域——中心、边缘、倾斜、旋转,缺一不可。