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文件不是简单的像素矩阵。它通常包含:
- 图像数据区:Bayer排列的原始像素值
- 元数据区:传感器型号、增益、曝光时间、白平衡参数等
- 校验信息:部分格式包含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的来龙去脉有个整体把握:
这张图把整个链路串起来了。从传感器到CFA,再到Bayer排列,然后分叉到位宽和存储格式,最后汇合成RAW数据。你写ISP算法时,每一步都可能成为瓶颈。
7. 小结:RAW域AI ISP的起点
这一章的内容,说白了就是让你明白——RAW数据不是一张“没处理好的照片”,而是一个精心设计的、包含传感器物理特性的原始信号。Bayer阵列决定了颜色采样的空间分布,位宽决定了动态范围和噪声底限,存储格式决定了硬件接口的带宽和解析方式。
我个人的习惯是:拿到一个新传感器,先做三件事——确认Bayer pattern起始位置、测量有效位宽、写一个MIPI RAW unpack验证程序。这三步走完,后面算法落地才有底气。
一句话总结:RAW是传感器和算法之间的契约。不懂RAW,AI ISP就是空中楼阁。