3. Bayer RAW数据格式:从传感器到数字图像的起点

说实话,做ISP这么多年,我见过太多工程师一上来就调颜色、调降噪,结果发现图像怎么调都不对。为什么?因为最底层的RAW数据就没搞明白。你想想看,如果原材料都是歪的,后面再好的工艺也救不回来。

这一章,我们就来把Bayer RAW数据彻底讲透。我会结合自己踩过的坑,带你从像素排布、位深存储到黑电平校正,一步步把地基打牢。

3.1 Bayer Pattern详解:为什么是RGGB?

人眼对绿色最敏感,这是生理学事实。所以Bayer阵列里绿色像素占了50%,红色和蓝色各占25%。这个设计不是拍脑袋定的,而是为了模拟人眼的亮度感知特性。

核心概念:Bayer Pattern是单颗CMOS传感器获取彩色图像的基础。每个像素只记录一种颜色分量,其余两种颜色通过插值算法恢复。

常见的Bayer Pattern有四种排列方式:

Pattern名称 第一行 第二行 常见传感器厂商
RGGB R G R G ... G B G B ... Sony、OmniVision(多数)
GRBG G R G R ... B G B G ... Samsung(部分型号)
GBRG G B G B ... R G R G ... On Semiconductor
BGGR B G B G ... G R G R ... 部分老款CCD

我个人习惯在项目初期就确认好Pattern类型。为什么?因为一旦搞错,后面Demosaic出来的图像颜色完全是乱的。我曾经接手过一个项目,前任工程师把GRBG当成了RGGB处理,结果调试了两个月颜色都不对,最后发现是Pattern读错了——这种低级错误,真的让人哭笑不得。

避坑指南:拿到一款新传感器,第一件事就是去读它的datasheet,找到Bayer Pattern的说明。不要相信代码注释里的"默认RGGB",一定要自己验证。我一般会拍一张纯白画面,然后看RAW数据里每个像素的数值分布,哪个通道值最高,哪个就是绿色。

3.2 RAW数据存储格式:10bit、12bit、14bit

传感器输出的RAW数据,位深决定了动态范围的上限。说白了,位深越大,能记录的明暗细节就越多。

目前手机传感器的主流位深是这样的:

  • 10bit:老款传感器、部分低端型号。每个像素1024个灰度级。
  • 12bit:目前主流。每个像素4096个灰度级,够用。
  • 14bit:高端旗舰传感器。每个像素16384个灰度级,后期处理空间大。

但这里有个坑——存储格式。传感器输出的数据不一定是直接对齐到字节边界的。比如10bit数据,如果每个像素都存10bit,那3个像素就是30bit,没法对齐到8bit的字节。所以常见的做法是打包存储:

// 10bit RAW数据打包示例(5个像素占5个字节)
// 像素0: bit[9:2] 占1字节,bit[1:0] 分散到下一个字节的高2位
// 实际存储时,每4个像素打包成5个字节

// 12bit RAW数据打包示例(2个像素占3个字节)
// 像素0: 12bit 占1.5字节
// 像素1: 12bit 占1.5字节
// 合计3字节

// 14bit RAW数据打包示例(4个像素占7个字节)
// 每个像素14bit,4个像素共56bit = 7字节

我记得第一次处理10bit RAW时,直接按16bit去读,结果图像全是条纹。后来才发现,数据是packed格式,需要按bit位拆包。嗯,这个教训挺深刻的。

注意:不同厂商的打包方式可能不同。有的用MSB对齐,有的用LSB对齐。读取RAW数据前,一定要确认传感器的输出格式。我建议写一个通用的RAW解析工具,把常见的打包格式都支持上,省得每次换传感器都要重写。

3.3 黑电平与线性化

传感器在没有光照时,理论上应该输出0。但实际不是这样——由于暗电流、电路噪声等因素,无光照时也会有一个基础输出值,这就是黑电平(Black Level)。

黑电平校正的目的很简单:把这个基础偏移减掉,让黑色真正归零。

校正公式也很直接:

// 黑电平校正
corrected_pixel = raw_pixel - black_level;

// 如果校正后出现负值,需要钳位到0
if (corrected_pixel < 0) {
    corrected_pixel = 0;
}

// 对于12bit RAW,典型黑电平值在64~256之间
// 具体值需要从传感器的OB(Optical Black)区域读取

但光做减法还不够。传感器的光电响应在低照度下往往是非线性的,这就引出了线性化(Linearization)的问题。

关键点:黑电平校正是减法,线性化校正是乘法或查表。两者顺序不能颠倒——必须先减黑电平,再做线性化。

线性化的常见做法有两种:

  1. 分段线性拟合:在不同照度下采集灰阶数据,拟合出校正曲线。适合硬件实现,速度快。
  2. 多项式拟合:用高次多项式拟合整个响应曲线。精度高,但计算量大,一般用于离线标定。

我个人的经验是:对于手机摄像头,分段线性拟合就足够了。因为传感器的非线性区域主要集中在低照度段,用3~5个分段点就能校正得很好。我曾经试过用10阶多项式,结果过拟合严重,反而把正常区域拉偏了。

实战建议:黑电平值不是固定不变的。它会随温度、增益、曝光时间变化。我一般在每一帧的OB区域实时计算黑电平,而不是用固定值。这样能有效避免暗部偏色问题。

3.4 知识结构总览

下面这张图,我把本章的核心逻辑串起来了。你可以把它当作一个快速索引:

Bayer RAW数据格式知识结构 Bayer RAW数据 Bayer Pattern 位深与存储格式 黑电平与线性化 RGGB GRBG GBRG BGGR 10bit 12bit 14bit 黑电平校正 线性化 分段线性拟合 核心流程:Bayer Pattern确认 → RAW数据解析 → 黑电平校正 → 线性化 顺序不可颠倒,否则图像质量会严重受损

这张图把三个核心知识点串在了一起。你从传感器拿到RAW数据后,第一步确认Pattern,第二步按位深正确解析,第三步做黑电平校正和线性化。这三步走完,才算拿到了干净的线性RAW数据,后面才能放心地做Demosaic、白平衡、颜色校正。