2、图像传感器基础:CMOS传感器工作原理、Bayer阵列与RAW数据、传感器接口协议

做AI ISP,第一件事不是调算法,而是搞懂传感器。你想想看,整个图像处理管线的源头就是传感器输出的RAW数据。源头如果搞不清楚,后面再怎么调也是白搭。

我个人习惯,拿到一块新的传感器模组,先不看数据手册里的电气参数,而是先搞清楚它的像素结构、输出格式和接口时序。这三样搞明白了,后面写驱动、调ISP心里才有底。

2.1 CMOS传感器工作原理

CMOS传感器,说白了就是一个像素阵列加一套读出电路。每个像素里有一个光电二极管和一个放大器。光打在二极管上产生电荷,电荷量跟光照强度成正比。然后通过行选、列选的方式,把每个像素的电压值依次读出来。

这里有个关键点:曝光方式。CMOS传感器主要分两种:

  • 卷帘快门(Rolling Shutter):逐行曝光,逐行读出。成本低,但拍运动物体会产生果冻效应。
  • 全局快门(Global Shutter):所有像素同时曝光,同时读出。没有果冻效应,但像素结构复杂,填充因子低。

经验之谈:做AI ISP时,如果场景里有高速运动目标(比如自动驾驶、工业检测),尽量选全局快门。我曾在一个人脸识别门禁项目里用了卷帘快门,结果人脸快速转动时图像扭曲,算法直接崩了。后来换成全局快门,问题解决。

还有一个容易被忽略的参数——满阱容量(Full Well Capacity)。它决定了像素能存多少电荷,直接影响动态范围。满阱越大,高光越不容易过曝。

参数 典型值 影响
满阱容量 10k~100k e⁻ 动态范围、信噪比
转换增益 30~150 µV/e⁻ 灵敏度、读出噪声
暗电流 10~100 e⁻/s 暗场噪声、热像素
读出噪声 1~10 e⁻ rms 低光照下的信噪比

2.2 Bayer阵列与RAW数据

CMOS传感器本身只能感知光的强度,分不清颜色。那彩色图像怎么来的?答案是Bayer阵列——在像素表面覆盖一层彩色滤光片(CFA),每个像素只允许一种颜色通过。

最常见的Bayer模式是RGGB:

R  G  R  G  ...
G  B  G  B  ...
R  G  R  G  ...
G  B  G  B  ...
...

为什么绿色像素比红蓝多一倍?因为人眼对绿色最敏感。这个设计是Bryce Bayer在1976年提出的,一直用到现在。

避坑指南:我曾经在调试一个4K传感器时,发现图像偏绿。查了半天,原来是驱动里把Bayer顺序配错了。传感器输出的是BGGR,我按RGGB去解,颜色当然不对。所以拿到新传感器,第一件事就是确认Bayer顺序。

RAW数据就是传感器直接输出的、未经任何处理的像素值。每个像素12bit或10bit,按Bayer排列。RAW数据有几个关键特征:

  • 线性响应:像素值与光照强度成正比(未做伽马校正)
  • 高位深:通常10~14bit,比8bit的JPEG细腻得多
  • 未去马赛克:每个像素只有一种颜色,需要插值才能变成全彩
  • 包含传感器噪声:暗电流、读出噪声、固定模式噪声都在里面

做AI ISP时,我强烈建议直接用RAW数据做训练和推理。为什么?因为RAW保留了完整的传感器信息,没有经过ISP的压缩和失真。AI模型可以从RAW里学到更真实的噪声分布和颜色响应。

注意:不同传感器的RAW格式不通用。Sony的RAW和OmniVision的RAW,位深、排列、黑电平值都不一样。写ISP时一定要按传感器数据手册来解析。

2.3 传感器接口协议

传感器和ISP芯片之间怎么传数据?目前主流的有三种接口:

接口 带宽 线数 典型应用
DVP(并行) ~100 Mbps 10~12根数据线 低分辨率、老平台
MIPI CSI-2(串行) ~10 Gbps 1~4对差分线 手机、车载、安防
LVDS(串行) ~3 Gbps 4~8对差分线 工业、医疗、高速

现在最常用的是MIPI CSI-2。它用差分信号传输,抗干扰能力强,带宽也够。MIPI的物理层叫D-PHY,分1.0、1.2、2.0版本,速率从80 Mbps/lane到4.5 Gbps/lane不等。

MIPI CSI-2的协议层定义了数据包格式:

帧开始(FS) → 行数据包1 → 行数据包2 → ... → 帧结束(FE)

每个行数据包:
  [包首] [RAW像素数据] [包尾]
  包首:数据类型(RAW10/RAW12等)、行号、ECC校验
  包尾:CRC校验

嗯,这里要注意:MIPI的时序要求很严格。差分对的阻抗要控制在100Ω±10%,走线长度要匹配,否则信号质量会下降。我见过一个项目,传感器和ISP之间距离长了5cm,结果图像出现条纹。后来加了均衡器才解决。

个人经验:调试MIPI接口时,先用示波器看差分信号的眼图。眼图张开得越大,信号质量越好。如果眼图闭合,先检查阻抗匹配和走线长度,别急着调软件。

除了物理层,还有控制接口——I²C或SPI。传感器寄存器配置、曝光时间、增益设置都通过这个接口来写。我习惯把传感器初始化流程写成结构体数组,清晰又好维护:

// 传感器初始化序列示例
struct sensor_reg {
    uint16_t addr;
    uint16_t value;
};

const struct sensor_reg init_seq[] = {
    {0x0103, 0x01},  // 软件复位
    {0x0100, 0x00},  // 进入待机
    {0x0305, 0x04},  // PLL配置
    {0x0307, 0x38},  // 分频系数
    {0x0340, 0x07},  // 帧长高字节
    {0x0341, 0xD0},  // 帧长低字节
    {0x0342, 0x0B},  // 行长高字节
    {0x0343, 0xA0},  // 行长低字节
    {0x0100, 0x01},  // 退出待机
};

最后,我把本章的核心知识点画成一张图,方便你理解传感器到ISP的数据流:

CMOS传感器到ISP数据流 CMOS传感器 → ISP 数据流 入射光 像素阵列(光电转换) 卷帘快门 / 全局快门 Bayer彩色滤光片阵列 RGGB / BGGR / GRBG / GBRG RAW数据输出 10bit / 12bit / 14bit 线性数据 接口传输 MIPI CSI-2 / DVP / LVDS 关键参数 • 满阱容量:10k~100k e⁻ • 转换增益:30~150 µV/e⁻ • 暗电流:10~100 e⁻/s • 读出噪声:1~10 e⁻ rms 接口带宽参考 • DVP:~100 Mbps • MIPI:~10 Gbps • LVDS:~3 Gbps

这张图把从光信号到ISP接收的完整链路串起来了。每个环节都有坑,后面章节我会逐个展开讲怎么处理。