2、RAW图数据存储结构:Bayer阵列、CFA原理与线性特性
好,咱们今天聊聊RAW图最底层的那些事。很多工程师调了几年图像,却对传感器出来的原始数据一知半解。我个人觉得,不理解Bayer阵列和CFA原理,后面做去马赛克、白平衡校正,基本就是在碰运气。
2.1 彩色滤波阵列(CFA)原理
说白了,CMOS传感器本身是“色盲”的。每个像素只能感知光的强度,也就是亮度,它分不清红绿蓝。那彩色照片怎么来的?
答案就是在每个像素上盖一层微小的滤色片——这就是CFA(Color Filter Array)。每个像素只允许特定波长的光通过,其他波长的光被吸收或反射。这样一来,传感器就只记录“某一种颜色”的亮度值。
核心概念:CFA的本质是“以空间换色彩”。每个像素只采集一种颜色分量,丢失的另外两种颜色信息,靠后续的插值算法(去马赛克)从相邻像素推算出来。
我刚开始做ISP时,总觉得这设计太浪费了——明明每个像素都能感光,却只让1/3的光进来。但没办法,这是目前成本、工艺和画质之间最平衡的方案。
2.2 Bayer阵列模式
最常见的CFA模式就是Bayer阵列。它用2x2的重复单元排列滤色片。为什么是2x2?因为人眼对绿色最敏感,所以绿色像素占一半,红色和蓝色各占1/4。
常见的Bayer模式有四种:
| 模式名称 | 2x2单元排列 | 常见传感器 |
|---|---|---|
| RGGB | 第一行:R G 第二行:G B |
Sony IMX系列、OmniVision多数型号 |
| GRBG | 第一行:G R 第二行:B G |
部分三星、安森美传感器 |
| GBRG | 第一行:G B 第二行:R G |
某些老款CCD传感器 |
| BGGR | 第一行:B G 第二行:G R |
部分Kodak、Foveon X3(非Bayer) |
避坑指南:我曾经在项目中接过一个第三方模组,默认是RGGB,结果传感器输出的是GRBG。去马赛克算法没改,整张图全是紫色条纹。排查了两天才发现是Bayer模式配错了。所以拿到新传感器,第一件事就是确认Bayer排列顺序。
你可能会问:怎么确认Bayer模式?我一般用两种方法:
- 查datasheet:传感器手册里会明确写Bayer pattern。
- 拍纯色画面:对着均匀白墙拍一张RAW,然后看每个2x2块的像素值分布。哪个通道值最高,对应的就是该颜色的滤色片位置。
2.3 RAW数据的线性特性
这是很多新手容易忽略的点。RAW数据是线性的,什么意思?
传感器输出的数字值(DN值)与入射光强度成正比。也就是说,如果入射光强度翻倍,RAW值也翻倍。这跟人眼的感知完全不同——人眼对亮度的响应是对数的。
举个例子:
- 入射光强度 = 100 lux → RAW值 = 500
- 入射光强度 = 200 lux → RAW值 = 1000
- 入射光强度 = 400 lux → RAW值 = 2000
这个线性关系非常重要。因为后面所有的处理——白平衡增益、颜色校正矩阵、伽马校正——都建立在“数据是线性的”这个前提上。
注意:线性特性只在传感器未饱和时成立。一旦某个像素的电荷超过满阱容量(Full Well Capacity),RAW值就会饱和(通常为4095或16383),线性关系立刻失效。饱和区域的细节永远丢失,后期拉不回来。
我记得有一次调试夜景模式,发现高光区域全是死白。查了半天,发现是曝光时间设得太长,导致部分像素饱和了。所以做HDR或多帧合成时,一定要监控饱和像素的比例。
2.4 黑电平(Black Level)
理想情况下,没有光照射时,传感器应该输出0。但实际不是这样——由于暗电流、电路噪声等因素,即使完全遮光,传感器也会输出一个非零值。这个值就是黑电平。
黑电平的校正公式很简单:
// 黑电平校正
corrected_value = raw_value - black_level
// 如果校正后为负值,通常截断到0
if (corrected_value < 0) corrected_value = 0;
不同传感器的黑电平值不同。常见的有:
- 8-bit RAW:黑电平通常在16~64之间
- 10-bit RAW:黑电平通常在64~256之间
- 12-bit RAW:黑电平通常在256~1024之间
- 14-bit RAW:黑电平通常在1024~4096之间
我的习惯:黑电平不是固定不变的。温度升高,黑电平会漂移。我一般在每帧图像中保留一些“光学黑像素”(Optically Black Pixels),实时计算当前帧的黑电平,而不是用固定值。这样能有效抑制温度引起的暗电流噪声。
2.5 白平衡(White Balance)
白平衡的本质,是在RAW域对R、G、B三个通道施加不同的增益,使得中性灰物体在三个通道上的响应一致。
为什么要在RAW域做?因为RAW数据是线性的,增益直接乘上去就行。如果在非线性域(比如sRGB)做白平衡,结果会非常奇怪。
白平衡的数学表达:
// 假设参考白点的R/G/B值分别为 R_w, G_w, B_w
// 目标是将R和B通道调整到与G通道一致
R_gain = G_w / R_w
B_gain = G_w / B_w
// 应用增益
R_out = R_in * R_gain
G_out = G_in * 1.0 // G通道通常不做增益
B_out = B_in * B_gain
这里有个关键点:白平衡增益不能无限大。增益太大会放大噪声,尤其是蓝色通道——因为蓝色像素的量子效率通常最低,信噪比本来就差。
我曾经踩过的坑:在低色温光源下(比如白炽灯,约2800K),蓝色通道的增益可能达到3~4倍。结果蓝色通道的噪声被放大到肉眼可见的程度,整张图全是蓝色噪点。后来我加了增益上限(最大2.5倍),超出部分用色温混合的方式处理,才解决了这个问题。
2.6 知识结构总览
下面这张图把本章的核心逻辑串起来了。从传感器采集到RAW数据输出,每一步都环环相扣。
从这张图可以看得很清楚:传感器采集 → CFA滤色 → Bayer排列 → 线性RAW数据 → 黑电平校正 → 白平衡增益。每一步都有它的物理意义和数学基础。
我个人建议,拿到一个RAW文件后,先做三件事:确认Bayer模式、测量黑电平、估算白平衡增益。这三步做扎实了,后面的调优才有根基。