2. Sensor与RAW数据:Sensor工作原理、Bayer Pattern、RAW数据格式、黑电平校正

各位好,我是老周。在安防ISP这条路上摸爬滚打了十几年,今天咱们来聊聊整个图像链路最源头的东西——Sensor和RAW数据。

你想想看,镜头把光收进来,Sensor把光转成电,ADC再把电转成数字。这一连串动作做完,我们手里拿到的第一手数据,就是RAW。说白了,RAW就是Sensor的“原生语言”,后面所有的调优工作,都是在这个基础上“翻译”和“美化”。

我个人习惯把Sensor比作相机的“视网膜”。它好不好,直接决定了你能调出什么样的图像。很多新手一上来就猛调3A、猛拉锐度,结果发现底子不行,怎么调都别扭。嗯,这就是没把Sensor吃透。

2.1 Sensor工作原理:从光子到数字

Sensor的核心工作流程,其实就三步:

  1. 光电转换:每个像素点上的感光二极管吸收光子,产生电子。光越强,电子越多。
  2. 电荷积累与读出:电子被存储在像素的电容里,然后通过行选、列选的方式,一行一行地读出来。
  3. 模数转换(ADC):读出的模拟电压信号,被转换成数字值。这个数字值,就是RAW数据的原始码值。

这里有个关键参数——满阱容量(Full Well Capacity)。它决定了每个像素最多能装多少电子。我在项目中遇到过一款低照Sensor,满阱容量只有8000e-,结果一到强光场景就过曝,怎么压都压不住。后来换了颗满阱容量18000e-的Sensor,动态范围一下子就上来了。

核心指标速查表

参数 含义 对图像的影响
满阱容量 像素能存储的最大电子数 决定高光过曝阈值
量子效率 光子转化为电子的比例 决定低照灵敏度
读出噪声 读出电路引入的噪声 决定暗部信噪比
暗电流 无光照时产生的电子 决定暗部偏色和热噪点

2.2 Bayer Pattern:为什么是RGGB?

你可能要问:Sensor的每个像素只能感知光的强弱,那颜色信息从哪来?

答案就是Bayer Pattern。在Sensor的感光面上,每个像素前面都覆盖了一层微小的滤色片。最常见的排列就是RGGB——一个红色、两个绿色、一个蓝色,组成一个2x2的单元。

为什么绿色要占两个?因为人眼对绿色最敏感。安防监控里,绿色通道的信噪比通常也是最好的。我记得有一次调一个IPC的偏色问题,怎么调白平衡都偏紫。后来一查,是Bayer Pattern的G通道增益配错了。你想想看,两个G通道的权重没算对,整个颜色矩阵就歪了。

避坑指南

我曾经在切换Sensor型号时,没注意Bayer Pattern的排列顺序。原厂是RGGB,新Sensor是BGGR。结果图像出来一片紫红色,我还以为是硬件坏了。后来花了半天才排查出来——Bayer顺序没改。所以,拿到新Sensor,第一件事就是确认Bayer Pattern的排列。

常见的Bayer Pattern有四种:

  • RGGB:最主流,索尼、OV大部分Sensor用这个
  • BGGR:部分安森美Sensor用
  • GRBG:少数老款Sensor用
  • GBRG:比较少见

下面这张图,是我自己画的一个Bayer Pattern结构示意,帮你直观理解:

Bayer Pattern 2x2 单元结构 R G G B 排列规则 奇数行:R G R G... 偶数行:G B G B... G通道占50% 常见变体 RGGB / BGGR GRBG / GBRG

2.3 RAW数据格式:你拿到的是什么?

Sensor输出的RAW数据,通常就是Bayer格式的原始码值。常见的位深有10bit、12bit、14bit。安防监控里,12bit最主流。

我建议你拿到RAW文件后,先做三件事:

  1. 确认位深:是10bit还是12bit?这决定了你的数据范围是0-1023还是0-4095。
  2. 确认Bayer顺序:用软件打开看看,是不是你预期的RGGB。
  3. 确认黑电平:这个我们下一节细说。

下面是一个典型的12bit RAW数据片段,我随便写了个例子:

// 假设Bayer顺序为RGGB,12bit数据
// 第一行(R、G交替)
Pixel[0][0] = 1024  // R
Pixel[0][1] = 2048  // G
Pixel[0][2] = 1030  // R
Pixel[0][3] = 2050  // G

// 第二行(G、B交替)
Pixel[1][0] = 2000  // G
Pixel[1][1] = 512   // B
Pixel[1][2] = 2010  // G
Pixel[1][3] = 520   // B

你看,每个像素只有一个颜色通道的值。后面要做Demosaic(去马赛克),才能把RGB三个通道补全。这个我们后面章节会讲。

2.4 黑电平校正:把“零”找回来

黑电平校正,是ISP Pipeline里第一个要做的处理。为什么?

理想情况下,Sensor在全黑环境下应该输出0。但实际不是这样。由于暗电流、电路偏置等因素,Sensor在全黑时也会输出一个非零值。这个值,就是黑电平(Black Level)。

我举个例子。假设Sensor的黑电平是64(12bit数据),那么你拍一张全黑的图,RAW值不是0,而是64左右。如果不做校正,后面所有处理都会带着这个64的偏移量。结果就是:暗部发灰,对比度下降,颜色也不准。

注意

黑电平校正不是简单的减去一个固定值。不同Sensor、不同增益下,黑电平会漂移。我曾经遇到一个案子,Sensor在低增益下黑电平是64,高增益下漂到了80。如果只用一个固定值去减,高增益下暗部就会偏绿。后来我改用逐帧统计黑电平的方法,才把这个问题解决。

黑电平校正的标准流程:

  1. 采集黑帧:盖上镜头盖,拍一张全黑图。
  2. 统计均值:计算全图或局部区域的RAW值均值。
  3. 确定校正值:这个均值就是黑电平。
  4. 逐像素减去:每个像素的RAW值减去黑电平,得到校正后的数据。

代码实现很简单:

// 黑电平校正示例(C语言风格)
#define BLACK_LEVEL 64  // 假设黑电平为64

uint16_t raw_data[1920][1080];  // 原始RAW数据
uint16_t corrected_data[1920][1080];

for (int y = 0; y < 1080; y++) {
    for (int x = 0; x < 1920; x++) {
        if (raw_data[y][x] > BLACK_LEVEL) {
            corrected_data[y][x] = raw_data[y][x] - BLACK_LEVEL;
        } else {
            corrected_data[y][x] = 0;  // 防止下溢
        }
    }
}

经验之谈

我建议你在做黑电平校正时,不要只用一个全局值。可以分区域统计,比如把画面分成4x4的块,每个块单独算黑电平。这样能有效消除Sensor的暗部不均匀性。另外,黑电平校正一定要放在Gain之前做,否则增益会把黑电平误差一起放大。

好了,这一节的内容就到这。Sensor和RAW数据是整个ISP Pipeline的基石,你把这些搞透了,后面调3A、调颜色、调降噪,都会顺手很多。