2. Sensor与RAW数据
各位好,我是老周。在安防ISP这条路上摸爬滚打了十几年,今天咱们来聊聊整个图像链路最源头的东西——Sensor和RAW数据。
你想想看,镜头把光收进来,Sensor把光转成电,ADC再把电转成数字。这一连串动作做完,我们手里拿到的第一手数据,就是RAW。说白了,RAW就是Sensor的“原生语言”,后面所有的调优工作,都是在这个基础上“翻译”和“美化”。
我个人习惯把Sensor比作相机的“视网膜”。它好不好,直接决定了你能调出什么样的图像。很多新手一上来就猛调3A、猛拉锐度,结果发现底子不行,怎么调都别扭。嗯,这就是没把Sensor吃透。
2.1 Sensor工作原理:从光子到数字
Sensor的核心工作流程,其实就三步:
- 光电转换:每个像素点上的感光二极管吸收光子,产生电子。光越强,电子越多。
- 电荷积累与读出:电子被存储在像素的电容里,然后通过行选、列选的方式,一行一行地读出来。
- 模数转换(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结构示意,帮你直观理解:
2.3 RAW数据格式:你拿到的是什么?
Sensor输出的RAW数据,通常就是Bayer格式的原始码值。常见的位深有10bit、12bit、14bit。安防监控里,12bit最主流。
我建议你拿到RAW文件后,先做三件事:
- 确认位深:是10bit还是12bit?这决定了你的数据范围是0-1023还是0-4095。
- 确认Bayer顺序:用软件打开看看,是不是你预期的RGGB。
- 确认黑电平:这个我们下一节细说。
下面是一个典型的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。如果只用一个固定值去减,高增益下暗部就会偏绿。后来我改用逐帧统计黑电平的方法,才把这个问题解决。
黑电平校正的标准流程:
- 采集黑帧:盖上镜头盖,拍一张全黑图。
- 统计均值:计算全图或局部区域的RAW值均值。
- 确定校正值:这个均值就是黑电平。
- 逐像素减去:每个像素的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、调颜色、调降噪,都会顺手很多。