1. 相机成像的数学魔法:从现实世界到数字照片

每次按下快门时,相机都在执行一场精妙的数学魔术。作为计算机视觉开发者,我花了三年时间才真正理解这个过程的优雅之处。想象一下,你站在埃菲尔铁塔前自拍,铁塔的三维结构如何变成手机屏幕上的二维像素?这背后是四个坐标系的接力转换:世界坐标系(铁塔实际位置)、相机坐标系(以镜头为中心的视角)、图像坐标系(镜头后的成像面)、像素坐标系(最终的数字图像)。

我第一次用代码实现这个流程时,在坐标转换环节卡了两周。关键是要理解每个步骤的几何意义:世界到相机的转换是刚体运动(旋转+平移),相机到图像是透视投影(类似人眼的近大远小),图像到像素则是数字化采样。举个例子,当拍摄距离变化时,前两个转换的矩阵会改变,但像素转换参数(由相机传感器决定)通常固定。

2. 世界坐标系到相机坐标系:三维空间的舞蹈

2.1 刚体变换的几何直觉

世界坐标系是固定在地面的绝对参考系,比如用GPS坐标记录埃菲尔铁塔位置。而相机坐标系则以镜头中心为原点,Z轴指向拍摄方向。两者转换就像把整个世界"搬"到相机面前——这需要旋转矩阵R和平移向量T,合称外参矩阵。

我在无人机项目中实测发现,R实际上由三个欧拉角决定:

  • 偏航角(yaw):左右转头
  • 俯仰角(pitch):上下点头
  • 滚动角(roll):侧倾相机
# 生成旋转矩阵的代码示例
import numpy as np
def euler_to_rotation(yaw, pitch, roll):
    Rz = np.array([[np.cos(yaw), -np.sin(yaw), 0],
                   [np.sin(yaw),  np.cos(yaw), 0],
                   [0, 0, 1]])
    Ry = np.array([[np.cos(pitch), 0, np.sin(pitch)],
                   [0, 1, 0],
                   [-np.sin(pitch), 0, np.cos(pitch)]])
    Rx = np.array([[1, 0, 0],
                   [0, np.cos(roll), -np.sin(roll)],
                   [0, np.sin(roll), np.cos(roll)]])
    return Rz @ Ry @ Rx

2.2 齐次坐标的降维打击

这里有个数学技巧:使用齐次坐标将非线性变换转为线性矩阵乘法。我在初学时总困惑为什么要加个"1"在坐标末尾,直到用OpenGL做3D渲染时才明白——这相当于把三维点先提升到四维空间做线性变换,再投影回三维。具体转换公式为:

$$ \begin{bmatrix} X_c \ Y_c \ Z_c \ 1 \end{bmatrix}

\begin{bmatrix} R & T \ 0 & 1 \end{bmatrix} \begin{bmatrix} X_w \ Y_w \ Z_w \ 1 \end{bmatrix} $$

其中R是3×3旋转矩阵,T是3×1平移向量。这个形式在SLAM(同步定位与建图)中至关重要,比如自动驾驶汽车就是通过不断更新R和T来定位自身位置。

3. 相机坐标系到图像坐标系:透视投影的魔法

3.1 小孔成像的现代演绎

镜头本质上是个精密的小孔成像装置。我曾拆解过老式胶片相机,当光线通过镜头中心(光心)时,会在焦平面形成倒立实像。这个过程用相似三角形就能解释:

$$ \frac{x}{X_c} = \frac{f}{Z_c}, \quad \frac{y}{Y_c} = \frac{f}{Z_c} $$

其中f是焦距,Zc是物体到光心的距离。这解释了为什么远山在照片中显得小——当Zc增大时,x和y按比例缩小。在VR设备校准中,这个非线性关系会导致边缘畸变,需要用鱼眼模型校正。

3.2 投影矩阵的降维艺术

将上述关系写成矩阵形式,就得到透视投影矩阵:

$$ s \begin{bmatrix} x \ y \ 1 \end{bmatrix}

\begin{bmatrix} f & 0 & 0 & 0 \ 0 & f & 0 & 0 \ 0 & 0 & 1 & 0 \end{bmatrix} \begin{bmatrix} X_c \ Y_c \ Z_c \ 1 \end{bmatrix} $$

这里的s=Zc是比例因子,体现深度信息。在AR应用中,正是通过逆向这个投影,才能将虚拟物体准确叠加到真实场景。我开发过一个博物馆AR导览,游客用手机扫描展品时,系统会根据当前相机参数实时计算这个矩阵。

4. 图像坐标系到像素坐标系:数字化的最后一公里

4.1 物理尺寸到像素的量子化

图像坐标系的原点在光轴上,单位是毫米;而像素坐标系原点在图像左上角,单位是像素。两者转换需要:

  1. 平移:将原点移到图像角落
  2. 缩放:根据传感器尺寸换算

转换公式为:

$$ \begin{cases} u = \frac{x}{dx} + u_0 \ v = \frac{y}{dy} + v_0 \end{cases} $$

dx和dy表示单个像素的物理尺寸(如0.004mm/pixel),(u0,v0)是主点坐标。我在调试工业相机时发现,不同批次传感器的dx可能有微米级差异,这会导致标定误差。

4.2 内参矩阵的封装智慧

将上述过程合并为内参矩阵K:

$$ K = \begin{bmatrix} f_x & 0 & c_x \ 0 & f_y & c_y \ 0 & 0 & 1 \end{bmatrix} $$

其中fx=f/dx,fy=f/dy,(cx,cy)是主点像素坐标。这个矩阵如此重要,以至于OpenCV专门提供calibrateCamera函数来计算它。去年调试双目摄像头时,我发现左右相机fx相差3%就会导致深度计算错误——这解释了为什么高端相机要单独校准每个镜头。

5. 完整成像链路的数学交响

5.1 从世界到像素的矩阵舞蹈

将三个步骤串联起来,得到完整的成像模型:

$$ s \begin{bmatrix} u \ v \ 1 \end{bmatrix}

K \begin{bmatrix} R & T \end{bmatrix} \begin{bmatrix} X_w \ Y_w \ Z_w \ 1 \end{bmatrix} $$

这个公式支撑着所有基于视觉的AI应用。在开发手势识别系统时,我们正是通过逆向这个过程,从二维像素反推出手部关节的三维位置。

5.2 实际应用中的陷阱与技巧

  • 焦距混淆 :手机标注的"7mm焦距"是物理焦距,而fx是等效焦距像素值
  • 主点偏移 :多数相机主点不在图像正中心,偏差可达5%画幅
  • 非方形像素 :工业线阵相机的dx和dy可能相差10倍

有次我用运动相机做三维重建,结果模型全部扭曲,后来发现是误用了方形像素假设。现在我的团队会强制要求用棋盘格标定每个相机,记录实际的K矩阵参数。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐