RAW图像基础:Bayer阵列、CFA原理与数据格式

做AI ISP这几年,我越来越觉得——不懂RAW,就别谈算法落地。很多刚入行的朋友上来就调RGB图,调得漂漂亮亮,一上硬件全崩。为什么?因为你根本不知道传感器给了你什么。

这一章,咱们就把RAW的底裤扒干净。Bayer阵列怎么排的?CFA到底在干什么?位宽和存储格式又有什么坑?我用自己的项目经验,一个一个说清楚。

1. 从传感器到RAW:光是怎么变成数字的

先捋一下链路。图像传感器(CMOS/CCD)的每个像素,本质上是一个光电二极管。光子打上去,产生电荷,电荷被转换成电压,再经过ADC变成数字值。这个数字值,就是RAW数据。

但有个关键问题:传感器本身是色盲的。它只感知光的强度,不感知颜色。那彩色照片怎么来的?

答案就是——在传感器表面盖一层彩色滤光片阵列,也就是CFA(Color Filter Array)。每个像素只允许特定波长的光通过。最常见的,就是Bayer阵列。

核心理解:RAW数据 = 每个像素只记录一种颜色的亮度值。颜色信息由CFA的空间排列决定。后续的插值(Demosaic)算法,就是根据相邻像素猜出缺失的颜色。

2. Bayer阵列模式:RGGB为什么是主流

Bayer阵列是1976年柯达的Bryce Bayer发明的。它的基本单元是2x2的像素块:

  • R(红)在左上角
  • G(绿)在右上角和左下角
  • B(蓝)在右下角

为什么绿色有两个?因为人眼对绿色最敏感。说白了,就是让绿色通道有更高的采样率,模拟人眼的亮度感知。我做过一个对比实验:把RGGB改成RGRG(绿只占一半),出来的图噪点直接翻倍,尤其是暗部。

常见的Bayer变种有这些:

模式 排列(2x2) 典型应用
RGGB R G / G B 最主流,90%的传感器
BGGR B G / G R Sony部分传感器
GRBG G R / B G OmniVision常用
GBRG G B / R G 部分安防传感器

嗯,这里要注意:不同厂家的Bayer起始偏移不一样。我踩过一个坑——算法在RGGB上跑得好好的,换了个BGGR的模组,整张图偏色到没法看。所以做ISP算法,第一件事就是确认Bayer pattern的起始位置。

3. CFA原理:不只是滤光片

CFA不只是一张彩色膜。它的光学特性直接影响信噪比和色彩还原。

每个滤光片的透过率曲线,决定了这个通道能接收到多少光。举个例子:红色滤光片会让红光通过,但绿光和蓝光会被大幅衰减。这就导致红色通道的信噪比天然低于绿色通道——因为进来的光子少。

我做过一个测试:在同样光照下,绿色通道的RAW值大约是红色通道的1.5倍,蓝色通道的1.2倍。这意味着什么?意味着做AI ISP时,不同通道的噪声模型必须分开训练。你不能用一个统一的降噪网络去处理所有通道,否则红色通道会过平滑,绿色通道又欠降噪。

实战技巧:在硬件设计时,CFA的微透镜(Microlens)和滤光片之间会有光串扰(Optical Crosstalk)。相邻像素的光会互相渗透。这个效应在Bayer插值时必须补偿,否则边缘会出现彩色伪影。我一般会在RAW域先做一个crosstalk校正矩阵,再进Demosaic。

4. RAW数据的位宽:10bit、12bit、14bit、16bit

传感器的ADC精度决定了RAW数据的位宽。常见的有:

  • 10bit:老款手机传感器、低端安防
  • 12bit:主流手机、消费级相机
  • 14bit:专业相机、工业相机
  • 16bit:科学级、医疗级传感器

位宽越高,动态范围越大,但数据量也越大。我算过一笔账:一个1200万像素的传感器,10bit RAW是15MB,14bit就是21MB。在硬件ISP的Line Buffer里,这个差距直接决定了SRAM的尺寸和成本。

还有一个容易被忽略的点:有效位宽 vs 存储位宽。很多传感器标称12bit,但实际有效位宽可能只有11.5bit——因为ADC的线性度不够,低几位是噪声。我在做算法时,习惯先做一个位宽有效性分析,把无效的低位直接截掉,能省不少计算量。

避坑指南:我曾经接手过一个项目,算法团队在PC上用16bit RAW训练,效果很好。移植到硬件时发现,传感器只输出10bit。结果模型在低光下完全失效——因为训练时的量化噪声分布和实际硬件不匹配。从那以后,我要求所有算法训练必须用目标硬件的实际位宽。

5. 存储格式:RAW文件到底长什么样?

RAW文件不是简单的像素矩阵。它通常包含:

  1. 图像数据区:Bayer排列的原始像素值
  2. 元数据区:传感器型号、增益、曝光时间、白平衡参数等
  3. 校验信息:部分格式包含ECC校验

常见的RAW存储格式:

格式 特点 典型后缀
DNG Adobe开放格式,带元数据,可压缩 .dng
MIPI RAW 硬件接口格式,无头,纯数据 .raw
Bayer RAW 最简单的格式,像素按行排列 .raw, .bay
Packed RAW 10bit/12bit打包成16bit对齐 .raw

在硬件ISP里,最常用的是MIPI RAW格式。它没有文件头,直接就是像素流。每个像素的位宽按MIPI协议打包。比如10bit RAW,每4个像素打包成5个字节。你想想看,如果解析不对,整个图像就错位了。

我写过一个解析函数,专门处理MIPI RAW的unpack。核心逻辑就是按位宽对齐,把打包的数据拆成独立的像素值。这里给个简化的示例:

// 10bit MIPI RAW unpack示例
// 输入:packed_data[5] 包含4个10bit像素
// 输出:pixel[4] 每个值范围0-1023

void unpack_10bit_raw(uint8_t *packed, uint16_t *pixel) {
    pixel[0] = (packed[0] << 2) | (packed[1] >> 6);
    pixel[1] = ((packed[1] & 0x3F) << 4) | (packed[2] >> 4);
    pixel[2] = ((packed[2] & 0x0F) << 6) | (packed[3] >> 2);
    pixel[3] = ((packed[3] & 0x03) << 8) | packed[4];
}

这段代码我用了好几年,从FPGA验证到ASIC量产都没出过问题。但要注意:不同传感器厂商的打包顺序可能不同,有的是LSB对齐,有的是MSB对齐。拿到新模组,第一件事就是拿示波器抓MIPI波形,确认bit顺序。

6. 知识结构总览

我把这一章的核心逻辑画成了一张图。你看完应该能对RAW的来龙去脉有个整体把握:

RAW图像基础:从传感器到存储 RAW图像基础:从传感器到存储 图像传感器 CFA彩色滤光片阵列 Bayer阵列模式 位宽:10/12/14/16bit 存储格式:DNG/MIPI RAW RAW数据(给ISP处理) 关键:RAW数据 = 传感器原始输出 + CFA空间采样 + 量化位宽 + 存储打包

这张图把整个链路串起来了。从传感器到CFA,再到Bayer排列,然后分叉到位宽和存储格式,最后汇合成RAW数据。你写ISP算法时,每一步都可能成为瓶颈。

7. 小结:RAW域AI ISP的起点

这一章的内容,说白了就是让你明白——RAW数据不是一张“没处理好的照片”,而是一个精心设计的、包含传感器物理特性的原始信号。Bayer阵列决定了颜色采样的空间分布,位宽决定了动态范围和噪声底限,存储格式决定了硬件接口的带宽和解析方式。

我个人的习惯是:拿到一个新传感器,先做三件事——确认Bayer pattern起始位置、测量有效位宽、写一个MIPI RAW unpack验证程序。这三步走完,后面算法落地才有底气。

一句话总结:RAW是传感器和算法之间的契约。不懂RAW,AI ISP就是空中楼阁。