📷 第4章 · 摄像头成像原理、CMOS噪声与运动模糊

—— 从光子到像素,传感器工程师的“眼底”世界

摄像头是自动驾驶的“眼睛”。但说实话,这颗眼睛远没有人类视觉那么可靠。我在项目里见过太多因为噪声或模糊导致感知失灵的案例——嗯,这一章我们就来拆解摄像头从成像到噪声的完整链路。

📸 摄像头噪声与成像知识体系 成像原理 · 光路 镜头 & 光圈 CMOS 像素阵列 ADC / 量化 散粒噪声 读出噪声 固定模式噪声 运动模糊 硬件/光路 噪声源 退化效应

1. 摄像头成像 · 光信号如何变成数字图像

摄像头成像说白了就是“光子计数”。外界光线穿过镜头,经过光圈、滤光片,最后落在CMOS感光阵列上。每个像素把光子转换成电子,再通过ADC变成数字值。我习惯把这个过程拆成三步:光电转换 → 电荷积累 → 量化输出。

你想想看,每个像素其实就是一个微型“水桶”。光子落进来,电子越积越多,电压就越高。但水桶总会漏、会溢,这就是噪声的源头。

💡 核心公式(理想情况)

像素输出 DN = (Φ · QE · A · tint) / (e-/DN) + 暗信号

其中 Φ 是光子通量,QE 是量子效率,A 是像素面积,tint 是积分时间。我在调参时经常用这个公式估算信噪比下限。

2. CMOS 噪声模型 · 三大“暗箭”

CMOS传感器里的噪声,我把它归为三类。每一类我都吃过亏,咱们一个一个说。

噪声类型来源特性我的避坑经验
散粒噪声 (Shot noise)光子到达的随机性√信号,泊松分布低照度下尤其明显,别指望降噪算法能完全消除
读出噪声 (Read noise)像素复位、放大器、ADC近似高斯,与信号无关我曾经因为PCB走线干扰把读出噪声放大了3倍……后来加了屏蔽
固定模式噪声 (FPN)像素工艺偏差空间固定,列/行条纹标定后减掉均值能干掉80%,但温度漂移后又会冒出来

🔧 个人习惯:我在仿真中通常用 shot = np.random.poisson(signal) 模拟散粒噪声,再用 np.random.normal(0, sigma_read) 叠加读出噪声。FPN 则用固定增益偏差图。

3. 运动模糊 · 自动驾驶的“动态梦魇”

运动模糊不是噪声,但比噪声更头疼。车辆一加速或转弯,像素积分时间内场景移动,图像就拖尾了。我见过一个极端案例——高速上的锥桶因为运动模糊直接“消失”在图像里。

为什么会这样?因为CMOS是逐行曝光的(rolling shutter),每一行曝光起始时间不同。如果车在动,物体就会倾斜、变形。嗯,这里要注意:全局快门(global shutter)能缓解,但动态范围会下降。

⚠️ 曾经踩过的坑:有一次我们做仿真验证,只加了高斯噪声,没加运动模糊。结果实车测试时感知模块在匝道上疯狂漏检。从那以后,我的仿真管线里必加 基于速度场的运动模糊核。

运动模糊的建模其实不复杂。假设曝光时间 T,像素速度 v,模糊核就是一个长度为 v·T 的线段。我常用下面的代码生成模糊核:

def motion_blur_kernel(length, angle):
    # length: 模糊像素长度, angle: 运动方向(弧度)
    kernel = np.zeros((length, length))
    center = length // 2
    for i in range(length):
        x = int(center + (i - center) * np.cos(angle))
        y = int(center + (i - center) * np.sin(angle))
        if 0 <= x < length and 0 <= y < length:
            kernel[y, x] = 1.0
    return kernel / kernel.sum()

然后对图像做卷积。注意边界处理——我习惯用 scipy.signal.convolve2d 的 'same' 模式。

4. 综合噪声仿真管线建议

在实际项目中,我不会把噪声一个个单独加。而是构建一个串行管线:

  1. 原始辐射量 → 加入散粒噪声(泊松采样)
  2. 电子信号 → 加入读出噪声(高斯) & FPN(乘性偏差)
  3. 量化前 → 应用运动模糊(空间可变核)
  4. ADC量化 → 加量化噪声(均匀分布 ±0.5 LSB)

你想想看,如果跳过第一步,低照度下的信噪比会乐观很多,实车就露馅了。我个人习惯在仿真中保留每一步的中间输出,方便调试。

📌 关键参数速查表(典型车载摄像头)

参数典型值说明
量子效率 (QE)0.5 ~ 0.7背照式CMOS更高
读出噪声2 ~ 6 e⁻越低越好,高端传感器 <2 e⁻
满阱容量10k ~ 30k e⁻决定动态范围
暗电流0.1 ~ 1 e⁻/s @25°C温度每升10°C翻倍
曝光时间10 ~ 40 ms太长容易运动模糊

最后说一句:摄像头仿真不是越复杂越好。我见过有人堆了十几个噪声项,结果主要矛盾反而被淹没了。抓住散粒噪声、读出噪声、运动模糊这三板斧,就能覆盖90%的退化场景。剩下的,等实车测试回来再迭代。