2. Bayer RAW 格式与预处理:Bayer Pattern详解、黑电平校正(BLC)、镜头阴影校正(LSC)
好,我们正式开始 ISP 流水线的第一站——RAW 域预处理。很多刚入行的朋友觉得这步简单,不就是读个数据嘛。其实不然,预处理做不好,后面 3A 算法再牛也救不回来。我见过不少项目,调试几个月发现暗角去不掉,最后追根溯源,是 LSC 的增益表没对齐 Bayer 格式。
这一节,我们把三个最基础也最关键的概念讲透:Bayer Pattern、黑电平校正、镜头阴影校正。
2.1 Bayer Pattern——传感器是怎么“看”颜色的
先问一个问题:一个像素点,能不能同时感知红绿蓝?
答案是:不能。单个像素只能感知光的强度,分不清颜色。
那彩色照片怎么来的?靠滤光片阵列。最经典的就是 Bayer Pattern,由 Kodak 的 Bryce Bayer 在 1976 年发明。说白了,就是在每个像素上盖一层微小的滤色片,只让特定波长的光通过。
2.1.1 标准 RGGB 排列
最常见的 Bayer 格式是 RGGB,也就是 2×2 的单元里,1个R、2个G、1个B。为什么绿色多一倍?因为人眼对绿色最敏感,多采样绿色能提升视觉分辨率。
| 位置 | 像素 (0,0) | 像素 (0,1) | 像素 (1,0) | 像素 (1,1) |
|---|---|---|---|---|
| 颜色 | R | G | G | B |
当然,也有其他排列方式,比如 RCCC(用于安防)、RCCB(用于低照度)、RGBW(用于高动态)。但 ISP 领域,90% 以上的场景还是 RGGB。
2.1.2 Bayer RAW 的数据格式
RAW 数据就是 sensor 直接输出的原始值,没有经过任何处理。每个像素通常用 10bit、12bit 或 14bit 表示。比如 12bit RAW,每个像素的取值范围是 0~4095。
存储时,一般按行排列。以 1920×1080 的 RGGB 为例:
- 第 0 行:R G R G R G ...
- 第 1 行:G B G B G B ...
- 第 2 行:R G R G R G ...
- 以此类推
注意,这里每个像素只存一个值,不是 RGB 三个值。所以 RAW 图看起来是灰蒙蒙的,别担心,那是正常的。
2.2 黑电平校正(BLC)——把“假黑”拉回真黑
你想想看,sensor 在完全无光的情况下,输出值是不是 0?
不是。因为 sensor 本身有暗电流,即使没有光子入射,也会产生少量电荷。这个非零的底噪,就叫黑电平(Black Level)。
黑电平校正的目的很简单:把无光时的输出值减去一个固定的偏移量,让真正的黑色对应 0。
2.2.1 黑电平的测量方法
sensor 通常会在像素阵列的边缘预留一些被遮挡的像素(Optical Black 像素),这些像素永远接收不到光。ISP 会统计这些像素的平均值,作为当前帧的黑电平值。
举个例子:
- OB 像素平均值 = 64(12bit RAW)
- 有效像素原始值 = 100
- 校正后值 = 100 - 64 = 36
2.2.2 BLC 的代码实现(伪代码)
// 假设 raw_data 是 12bit 的 Bayer RAW 数组
// ob_level 是当前帧的黑电平值
for (int i = 0; i < width * height; i++) {
int corrected = raw_data[i] - ob_level;
if (corrected < 0) corrected = 0;
if (corrected > 4095) corrected = 4095; // 12bit 上限
raw_data[i] = corrected;
}
实际工程中,BLC 通常放在 ISP 流水线的最前面,因为后续的 LSC、AWB 等模块都假设黑电平已经被正确移除。
2.3 镜头阴影校正(LSC)——拯救暗角
你有没有拍过一张纯白墙壁的照片,结果发现四角发暗、中间亮?这就是镜头阴影,也叫暗角(Vignetting)。
原因有两个:
- 光学原因:镜头边缘的光线入射角大,到达 sensor 的光强比中心弱。
- 像素原因:边缘像素的微透镜接收效率比中心低。
LSC 的做法就是给边缘像素乘以一个大于 1 的增益,把亮度补回来。
2.3.1 增益表的生成
LSC 的核心是一张增益表(Gain Table)。这张表记录了每个像素位置应该乘多少增益。增益表通常是在模组标定阶段生成的。
标定方法:
- 拍摄一张均匀的灰卡或白板
- 统计每个像素位置的亮度值
- 以中心亮度为基准,计算每个位置的增益 = 中心亮度 / 当前位置亮度
举个例子:
| 位置 | 中心 | 左上角 | 右下角 |
|---|---|---|---|
| 原始亮度 | 2000 | 1600 | 1500 |
| 增益 | 1.0 | 1.25 | 1.33 |
2.3.2 LSC 的实现方式
实际工程中,不会为每个像素都存一个增益值,那样太占内存。常用的做法是:
- 网格增益:把图像分成 16×16 或 32×32 的网格,每个网格存一个增益值。像素点的增益通过双线性插值得到。
- 多项式拟合:用多项式拟合出增益曲面,运行时直接计算。
网格增益是主流方案。比如 1920×1080 的图像,分成 16×16 的网格,只需要 120×68 个增益值,内存占用很小。
2.3.3 LSC 的注意事项
LSC 校正时,不同颜色通道的阴影程度可能不同。所以 R、G、B 通道需要分别使用不同的增益表。有些 sensor 的阴影在红色通道特别严重,如果统一用一张表,会出现颜色偏移。
2.4 本章知识体系
下面这张图展示了 Bayer RAW 预处理的核心流程和三个模块的关系:
从图中可以看到,Bayer RAW 数据先经过 BLC 去除暗电流偏移,再经过 LSC 补偿镜头阴影,最后输出干净的 RAW 数据给后续的 demosaic、AWB 等模块。