ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

图像形成物理:计算机视觉的底层逻辑与工程避坑指南

图像形成物理:计算机视觉的底层逻辑与工程避坑指南

我最早翻到《图像处理、分析与机器视觉(第四版)》的"图像形成物理"这一章时,第一反应是直接跳过。直觉告诉我,前面几章才是重头戏,图像形成不过是点物理常识,无非就是"光打到物体上、镜头收进来、传感器变成电信号"而已。直到后来做真实项目时被连续打脸——先是在不均匀光照下算法全部失效,又因为没搞懂透视投影和相机内参的关系,标定浪费了整整三天。我才不得不回头把这一章老老实实啃了一遍。

啃完之后必须说:这章是整个计算机视觉体系的地基。滤波器、特征检测、立体匹配、运动分析,所有算法模型都在假设"图像是这样形成的"之上展开。如果对图像形成过程的理解是模糊的,那对后续算法的理解就永远是悬空的。这篇笔记不是对教材目录的复述,而是我结合跨平台开发、相机标定、图像增强等实际场景后,对这一章核心知识点的重组和体会。内容严格跟着教材的知识框架走,但组织方式会更贴近"一个踩过坑的从业者回头看这些概念"的视角,希望能帮你少走几步弯路。

1. 成像这件事,本质上是一次"降维打击"

1.1 三维世界的点是怎么变成二维像素的

图像形成物理要回答的第一个问题,是三维世界中的一个点,最终落在传感器哪个位置。教材开始引入的针孔相机模型,就是把现实中复杂的光学系统简化成一个谁都能理解的结构:光线从场景中的某一点出发,穿过一个小孔,投射到后面的成像平面上。

这里最反直觉、也最关键的一点是"倒像"——光线沿直线传播,穿过小孔后上方的点会落在成像平面下方,左右也互换。数学上用相似三角形就能写清楚:

焦距为 f,某点在世界坐标中的深度为 Z,水平偏移为 X,它落在成像平面上的位置横坐标 x = -f·X / Z。负号就是倒像的来源。实际相机为了得到正立图像,内部做了额外处理,但从物理模型角度看,这层"翻转"理解透彻了,后面理解相机内参里的主点偏移、图像坐标系定义都会顺畅很多。

多数入门资料会直接给你 x = f·X / Z(不带负号),因为反正坐标轴翻转后从背面看是正的。但我建议你推一遍带负号的形式,它能把"成像平面为什么要倒着看""像素行坐标为什么要从左上角开始"这类后续疑惑一次讲清。

1.2 针孔模型的局限和透镜的必要性

针孔模型理想但低效——孔太小进光量就小,需要很长的曝光时间;孔稍微放大,模糊就立刻出现。真实相机必须用透镜来"聚光"。透镜的引入带来了新的物理量:焦距不再是小孔到平面的距离那么简单,而是由透镜曲率和材料折射率决定的参数,薄透镜公式 1/f = 1/u + 1/v(物距 u、相距 v)把物平面和像平面的关系精确化了。

这里有个许多人没意识到的问题:透镜只能对一个物距平面精确对焦。物体不在这个平面上,像就会模糊,形成弥散圆。景深这个概念就是由允许的最大弥散圆直径反推出来的。做视觉系统设计时,景深往往比像素数更重要,比如流水线上的工件高度有波动,你要求 10 cm 景深范围都清晰,那光圈和焦距的选择就完全不一样了。教材在这个位置引出透镜模型,正是为了给后面讨论模糊、失焦、光学像差做铺垫。

1.3 齐次坐标与投影矩阵:把几何写成分数,把分数化成矩阵

针孔模型虽然直观,但工程实现里没有谁会真的手算 x = -f·X / Z,因为除法在矩阵运算里不便处理。教材在这里做了一个非常漂亮的抽象:引入齐次坐标,把三维点的坐标(X, Y, Z)变成(X, Y, Z, 1),再把除法巧妙地吸收到矩阵乘法里。

推导思路是这样:任何将三维点变换到二维像素点 (u, v) 的映射,在齐次坐标下都可以写成 3×4 的投影矩阵 P。矩阵里的物理含义一共三层:

  • 第一层是内参矩阵 K,包含焦距、主点位置、像素在 x/y 方向的物理尺寸比例;
  • 第二层是外参矩阵 [R | t],即相机在世界坐标系里的旋转和平移;
  • 第三层是透视除法本身,也就是那个"除以 Z"的动作,被处理成齐次坐标归一化。

我当年学到这里最大的感触是:分数形式下的几何直觉很清晰,但矩阵形式下的工程能力很强大。OpenCV 里的 calibrateCamera、solvePnP,甚至后续章节的极线几何,本质上都是在和这个投影矩阵的不同层打交道。如果你只停留在 x = f·X / Z 的层面,那么看双目标定、外参估计的代码会非常吃力。

2. 从光到灰度值,中间隔着一整套辐射度量学

2.1 教材为什么突然开始讲"辐射通量"这种物理名词

几何成像解决的是"像在哪"的问题,接下来要解决的是"像有多亮"。教材在这里进入辐射度量学(radiometry),上来就是辐射通量(radiant flux)、辐照度(irradiance)、辐射强度(radiant intensity)、辐射亮度(radiance)这一串术语。

这些词看着吓人,但它们的核心逻辑是:光是一种能量,描述"有多少光"必须同时说清楚"从哪来、到哪去、面积多大、方向范围多宽"。用大白话拆一下:

  • 辐射通量是单位时间内通过某个面的总光能量,单位是瓦特;
  • 辐照度是单位面积上接受到的辐射通量,单位是瓦特每平方米;
  • 辐射强度是单位立体角内的辐射通量;
  • 辐射亮度则是单位面积、单位立体角内的辐射通量,是最"精细"的一个描述。

为什么教材要把这套物理量完整搬进来?因为图像传感器的每个像素记录的不是"颜色",而是入射光的能量密度。弄清楚"像素值和辐射亮度近似成正比"这层关系,后面做光照校正、HDR、多曝光融合时才知道自己在调整什么物理量。

2.2 立体角是从二维到三维的"视角大小"

立体角(solid angle)是辐射度量学里一个容易卡住的概念。平面角用弧度表示"射线张开的程度",立体角则用球面度(steradian)表示"锥形从球心张开的程度"。整个球面围成的立体角是 4π 球面度。

这个概念生活化的类比是:你用手电筒照墙,在距墙 1 米处光斑半径变大,单位面积上的光变弱,但手电筒发出的总光能没变。辐照度随距离平方衰减的根源,不是光"累了",而是同一个立体角对应的球面面积随半径平方增长,能量被摊薄了。教材里光源点模型光强随距离平方衰减的公式,就从这里来的。很多人在调光照仿真时总觉得"平方衰减"是人为设定的参数,其实它是几何的必然结果。

2.3 朗伯余弦定律:为什么斜着看会觉得暗

朗伯余弦定律说,一个理想漫反射面在某方向的辐射亮度与观察方向和表面法线夹角的余弦成正比。换句话说,正对着看最亮,斜着看变暗。

这个定律是理解宏观光照最重要的一个杠杆点。举个例子,中午太阳几乎在头顶,地面吸收的光照最强;傍晚太阳贴近地平线,同样一片地面接收到的能量就弱很多——不是太阳变暗了,而是有效接收面积变大了。放在图像处理里,这直接决定了表面朝向与光源方向的相对几何关系如何在像素值上体现。Shape from Shading、光度立体视觉这些技术,全部建立在这个物理规律上。

顺带提一个容易混淆的点:朗伯面(Lambertian surface)的"亮度不随观察方向变化",和朗伯余弦定律的"接收能量随入射角度变化",是两个不同的问题。前者是说:一个完全漫反射面,你把眼睛移到左边或右边看,看到的亮度一样;后者是说:光源斜着照过来,单位面积接收到的能量比垂直照要少。理解这个区别后,看反射模型那一节会轻松得多。

3. 材质决定反射,也决定图像处理的难度

3.1 教材的反射模型分类,就是现实世界材质的抽象

从辐射度量学的角度看,光打到物体表面后会分成几路:一部分被吸收,一部分反射,一部分透射。对视觉系统而言,反射部分决定了我们能看到什么。教材从理想漫反射讲到理想镜面反射,再到 Phong 模型和 BRDF,这一整套本质上是在回答同一个问题:"一束光沿某个方向打到一个点上,观察者站在另一个方向,到底能看到多少反射光?"

朗伯反射模型假设反射在所有方向均匀,数学表达式简洁漂亮,因此大量视觉算法(比如多数立体匹配、光度学方法)都默认物体是朗伯面。镜面反射则严格遵从反射定律,入射角等于反射角,观察方向只有非常接近反射方向时才能看到高光。现实世界的物体基本是二者的混合:苹果皮既有漫反射的底色,又有表面一层油膜带来的镜面高光。

3.2 Phong 模型为什么是"工程折中"的典范

Phong 模型不追求物理精确,它用一个漫反射项加一个镜面反射项的组合模拟观感。镜面项里有个指数 n,控制高光的集中程度——n 越大,高光越锐利,表面越像抛了光。这个 n 在物理上没有严格对应物,但在工程上非常好使,OpenGL 里的材质参数就是这套思路。

学习时建议拿一张塑料卡片和一个不锈钢杯放在窗边对比观察。塑料卡片的颜色在不同角度下变化不大,不锈钢杯上的高光会随着视线稍微移动就剧烈变形。你一旦建立起这种直觉,就会明白为什么许多视觉算法对高光物体失效——因为高光区域的像素值完全由观察角度决定,与物体本身材质颜色几乎无关,任何假设"亮度反映材质"的算法在这类区域都会失灵。

3.3 BRDF 是把反射从"模型"升维到"测量"

如果要从物理上严格描述反射,就需要双向反射分布函数(BRDF)。它的输入是入射方向和观察方向,输出是反射辐射亮度与入射辐照度的比值。这是四维函数,做实验测量时需要对每个入射方向、每个观察方向扫一遍,数据量巨大。

教材为什么只给概念而没有给完整公式?因为 BRDF 本质上没有普适的解析表达式,真实世界的每种材质都不同。这个知识点的意义不在于你会算,而在于你认识到:所有反射模型都只是 BRDF 的近似。有了这层意识,你在做图像合成、光照估计时会清醒很多:任何模型都有适用范围,朗伯假设不行时就上 Phong 或者 BRDF 测量数据,但复杂度代价要自己权衡。

4. 从光子到数字:传感器物理与像素的形成

4.1 数字传感器怎么把光子变成二进制

教材这一部分从 CCD 讲到 CMOS,核心流程是:光子打到感光元件上,通过光电效应激发出电子,电子积累形成电压,电压经模数转换变成数字值。这里每个环节都有物理噪声参与,最终像素值 = 光子数 × 增益 + 暗电流 + 读噪声。这一行公式解释了图像处理里几乎所有"质量"问题的根源。

光电效应有一个泊松过程属性:单位时间到达的光子数不是恒定的,而是围绕平均值波动的。即便用完全均匀的光源照射,同一传感器同一曝光参数下,每个像素读到的电荷量也有差异,这就是光子散粒噪声(shot noise),它随信号增强而增强,且无法通过提高传感器质量消除——因为它是光的量子本质决定的。所有降噪算法本质上都在和这个底层噪声博弈。

4.2 暗电流与读出噪声,是"拍黑图"能看出的门道

温度升高时,即便没有入射光,传感器晶体里的热激发也会产生电子,这就是暗电流。把镜头盖严实了拍一张全黑照片,画面不会是全 0,而是有亮度底噪,这就是暗电流加读出噪声的直观体现。

做长曝光摄影或者天文图像处理的人对暗电流感受最深:曝光时间越长,暗电流积累越多,黑图越亮。科学级相机会用制冷方式降低温度来抑制暗电流,工业视觉相机通常不做制冷,但算法里常用暗帧减法——拍一张同曝光时间的暗场,再用有光照的图减去它。这是一个非常经典且容易实现的操作,如果你在做高动态范围成像(多曝光融合),暗帧校正属于做不做有明显区别的步骤。

4.3 动态范围、位深和线性响应

传感器响应的核心指标是动态范围,即最大可检测信号与噪声本底的比值,通常用分贝或档位(EV)表示。位深(8bit、10bit、12bit)决定的是量化层数,别把动态范围和位深画等号:一个动态范围很高的传感器配上 8bit 量化,高光到阴影的过渡也会因为量化精度不足出现带状条带;反之动态范围不够,就算有 16bit 也表示不了真实差异。

线性响应意味着像素值与入射光能量成正比,这给图像处理带来了极大便利:曝光时间加倍,像素值近似加倍(前提没饱和)。做多曝光 HDR 合成时,不同曝光时间的图像就是靠这个线性关系映射到同一辐照度域的。实践中我建议做相机特性曲线标定,拍一组灰阶色卡,把像素值和已知反射率的关系画出来,能看到传感器在大约哪个区间偏离线性。

5. 颜色视觉与彩色成像:像素值并不等于"颜色"

5.1 为什么教材把颜色感知和成像物理放在一起

在许多入门教程里,颜色被当作图像的三个通道数值直接处理,但在物理层面,颜色是"光的光谱功率分布"经过人眼三种视锥细胞响应后的感知结果。教材把颜色视觉放进图像形成这一章,是因为彩色相机的设计必须同时理解"光的物理属性"和"人的感知属性"。

人眼有 S、M、L 三种视锥细胞,分别对短波(蓝)、中波(绿)、长波(红)敏感。值得强调的是,它们的响应曲线在波长轴上高度重叠,没有哪个细胞只响应一种"纯色"。所以颜色不是光波本身的属性,而是人脑对三路响应的编码结果。一个橙子反射的光谱分布,和红绿两种光按一定比例混合产生的光谱分布,只要使三种视锥细胞产生相同响应,人看到的颜色就一样,这就是"同色异谱"现象。

5.2 彩色相机的核心是"牺牲分辨率换颜色"

数字相机拍彩色图像的常规方案是 Bayer 阵列:每个像素只覆盖一种颜色滤镜(通常是 R、G、B 按 1:2:1 排布,绿色多一倍是为了模拟人眼对绿色更敏感的特性)。这样每个像素都缺失了另外两种颜色的信息,需要插值算法去猜,这个猜的过程叫去马赛克(demosaicing)。

很多人第一次知道"相机每个像素只记录一个颜色通道"时会很惊讶。这意味着你拿到的一幅彩色图,是算法重建的结果,不是物理真实。去马赛克算法会在边缘产生彩色伪影、在纹理密集区域产生摩尔纹。工业应用中,很多检查场景会故意选用黑白相机,正是为了绕开彩色滤镜带来的分辨率损失和伪影问题——这属于典型的"理解图像形成物理后做的正确工程决策"。

5.3 白平衡与色彩校正的物理含义

不同光源的光谱功率分布差异极大:白炽灯偏红、日光灯偏绿、正午日光偏蓝。相机在 D65 标准光源下标定出的 RGB 响应,如果直接用于钨丝灯场景,画面会严重偏橙。白平衡的本质,是通过乘以一组通道增益,把"感知上应为白色"的物体在数值上恢复为 R=G=B。

更严格的工业做法是色彩校正矩阵(CCM):因为传感器滤镜的响应曲线和人眼视锥细胞曲线不完全匹配,简单调增益无法保证所有颜色都准,必须用 3×3 矩阵把传感器 RGB 空间映射到标准色彩空间。这些实践冲洗了物理成像和感知色度学之间的落差,也解释了为什么同一张 Raw 文件在 Lightroom 里换一个相机配置文件,颜色会明显不同。

6. 采样与混叠:连续世界进入离散像素时的"翻译误差"

6.1 奈奎斯特不是音频专属,图像同样逃不掉

图像进入计算机之前,必须从连续的光场变成离散的像素阵列,这一步就是采样。教材在这部分引入采样定理:要从采样信号中无失真重建原信号,采样频率必须大于信号最高频率的两倍。这里信号的"频率"指空间频率——单位长度内亮度变化的周期数。一张纹理细密的布料照片,空间频率就高。

如果采样频率不足,高频细节会折叠成低频伪图案,这就是混叠(aliasing)。最经典的例子是拍风扇叶片时出现的"倒转"或"慢转"错觉,以及穿细条纹衬衫拍视频时条纹像波浪一样扭动。这些现象在图像形成时就已经发生,后期算法无法完美恢复。理解这一点会让你在拍摄时下意识检查:场景中的高频纹理会不会超过传感器的采样能力。

6.2 光学低通滤波器与摩尔纹的实际处理

消费相机和部分工业相机在传感器前会加一块光学低通滤波器(OLPF),本质上是一个轻微的模糊片,把超过采样极限的高频信息在到达传感器之前就衰减掉。代价是画面整体会变软一点点,所以高像素机型慢慢倾向于取消 OLPF 来换锐度,结果是摩尔纹风险上升。

做工业视觉时我的建议是:优先从光学端解决混叠问题,而不是指望算法。给镜头加上合适的光圈和距离控制,让最小可分辨细节大于两个像素尺寸,往往比事后滤波更有效。教材里关于采样网格的讨论看起来偏理论,但它是很多人花了很久才理解的一条真理:离散化是有代价的,而这个代价在采样那一刻就确定了,后面能弥补的非常有限。

6.3 分辨率不是越高越好,匹配才是关键

传感器的像素尺寸和镜头的光学分辨率必须匹配。如果镜头分辨率低,换上再高像素的传感器也只是把模糊放大;反之,镜头分辨率很高但传感器像素太大,则镜头的解析力被浪费。这个匹配关系可以用系统的调制传递函数(MTF)来定量评估,但实践中更简单的做法是:在目标工作距离拍分辨率测试卡,观察眼睛能看到的最细线对,再换算到传感器上的空间频率。

我见过不少项目盲目追求"更大像素数",最后发现问题不是像素不够而是镜头喂不饱,或者景深小到没法用。图像形成物理这一段的学习价值正在于此:它把采样当作一个有物理约束的系统行为来看待,而不是一个规格参数。

7. 教材为什么在成像物理里塞了那么多"插曲"

7.1 从影像增强器到彩色 CRT,读历史能加深原理理解

第四版教材在这一章里保留了若干看似"过时"的器件讨论,比如影像增强管、彩色显像管原理。我第一次读到这些内容时,也觉得它们属于应该删掉的历史遗留。但后来我意识到,这些"过时技术"恰恰是成像链路的极佳教学工具:影像增强管把微弱的光子转换成电子、加速后再转回光子,把一个物理量(光子数量)经过多次物理变换的链路展示得淋漓尽致。

现在做视觉的人大量接触的都是数字域处理,对"光子-电子-电压-数字"这条链路的物理感知越来越弱。花点时间看这些老技术,实际上是在补充"图像从哪来"的直觉。有了这类直觉,你在判断低照度噪声来源时、在决定是否使用外部光源时、在评估相机灵敏度规格时,都比只看参数表的人多了一层判断力。

7.2 图像形成物理和后续章节的真正接口

这本书后面紧跟着的就是滤波、边缘检测、特征提取。如果你回到图像形成物理再看这些算法,会发现很多细节是有来路的:

  • 高斯滤波器的尺度参数对应着采样和模糊的物理过程;
  • 边缘检测算子的微分近似对应着光照变化的几何假设;
  • 特征点检测的尺度不变性设计,本质上对抗的是投影造成的缩放变化;
  • 去雾、低光增强算法则直接建立在对大气散射和光照物理的建模上。

所以这一章真正的作用不是让你记住几条公式,而是让你理解:图像处理算法处理的对象不是"真实世界",而是一串已经经过投影、采样、量化、加噪的信号。算法要取得好效果,要么对信号做出正确假设,要么直接补偿形成环节的失真。这种思考方式,比多会两个滤波算子有价值得多。

8. 学习这章时,我踩过的几个具体的坑

8.1 以为"焦距"只是镜头上的那个数

第一次拿相机做标定时,我被一个尴尬的事实困住了:镜头焦距明明是固定的,但标定结果里的焦距参数却有两个数值,而且和镜头标记的焦距对不上。后来才明白,标定得到的 f 是内参矩阵里的等效焦距,单位是像素,它等于物理焦距除以像素物理尺寸。物理焦距 25 mm 的镜头配某个传感器,等效焦距可能是 5000 像素;换一个像素更密的传感器,等效焦距就会变大。从一开始就建立"物理焦距/像素尺寸/等效焦距"这三者的换算关系,后面处理相机模型时才不会犯混。

8.2 忽略主点偏移,投影矩阵差出好大一截

教材内参矩阵里有个不起眼的参数:主点(principal point),也就是光轴与成像平面的交点坐标。很多简化模型直接假设主点就是图像中心,但实际装配过程中,传感器芯片和光轴的对准不可能完美,主点往往偏离中心几像素到几十像素。如果项目要求高精度测量(比如机械臂视觉引导),主点偏移不校正,结果会随视角变化产生系统性偏置。写代码时顺手在标定结果里把 cx、cy 打出来看一眼,养成习惯。

8.3 用 JPEG 做光照分析,等于把测量数据先压坏了

传感器的线性响应是光照分析的基础,但 JPEG 存储过程中会应用 gamma 曲线、白平衡、饱和度调整和压缩等不可逆操作,把线性物理量变成了感知编码量。我在一个光度立体项目中踩过这个坑:用 JPEG 图算表面法向,结果怎么调参数都对不齐,根源就是非线性的 gamma 编码让反射模型的前提失效了。后来全部切回 raw 线性数据,问题立刻消失。教材里讲传感器线性响应时你可能觉得是废话,但这恰恰是实际项目里最容易被牺牲掉的前提。

8.4 高光处理不是靠算法,而是靠第一性原理

遇到强镜面反射物体,很多人第一反应是上算法,比如高光去除、偏振处理。但如果你回到图像形成物理去思考,会发现更优的方案往往在物理端:改变光源角度让反射光偏离相机视场,使用偏振滤镜滤掉镜面反射成分,或者干脆选择漫反射更好的打光方式。物理端解决一件事的成本,通常低于算法端。这条经验在工业视觉项目中反复被验证,也是我理解"图像形成物理"后最大的收获之一。

9. 一点学习方法上的个人体会

最后说说我自己重读这一章时觉得比较有效的学习方式,供参考。

首先是"三遍阅读法"。第一遍只建立直觉,不求甚解地翻完,知道这章讲了哪些主题:几何成像、辐射度量、反射模型、传感器、颜色、采样。第二遍对着公式推导,重点把投影矩阵、朗伯余弦、泊松噪声这几条主线理清。第三遍回到实际问题,每学一个概念就想想"这能解释我工作中遇到的哪个现象"。

其次是做小实验。教材里的知识点几乎都可以拿身边设备验证:用手机在白天和夜晚各拍一张灰卡,对比噪声水平;把镜头拧到不同光圈,看景深变化;用屏幕显示细条纹图案,再用另一台设备翻拍,观察摩尔纹。这些实验每个只需要几分钟,但比看十遍书更深刻地理解"图像形成"这件事。

如果工作中涉及相机选型或光学系统设计,我建议读完后立刻实践一次相机标定加图像采集流程,把内参矩阵的元素逐个对应到教材公式上。写代码本身不是目的,这个过程会让你建立起从物理世界到像素世界的完整通路。

图像形成这一章,你看的时候可能觉得庞杂琐碎,但它会有意无意地影响你在每一个后续工程决策里的判断。希望这篇笔记能帮你在第一次读它时就少踩几个我踩过的坑。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进