1. RAW域基础

各位同学,欢迎来到《从RAW域到YUV域的图像处理全链路》的第一章。我是你们这门课的主讲工程师。在正式开始之前,我想先聊聊为什么我们要从RAW域讲起。

你想想看,我们平时用手机或相机拍一张照片,按下快门后,传感器捕捉到的原始数据到底是什么?其实,它既不是我们看到的彩色图片,也不是一个完整的RGB图像。它是一堆“偏色”的、马赛克状的灰度值。这就是RAW数据。

我个人习惯把RAW域比作“食材的原始状态”。你从菜市场买回来的新鲜蔬菜,未经清洗、切割、烹饪,这就是RAW。而后面我们讲到的YUV图像,就是经过精心烹饪后的成品菜。不懂食材,怎么做菜?所以,这一章我们先把“食材”研究透。

1.1 为什么传感器不能直接输出彩色?——Bayer阵列的由来

图像传感器(CMOS/CCD)的每个像素点,本质上只能感知光的强度,也就是亮度信息。它天生是“色盲”,分不清红绿蓝。

那怎么得到彩色图像呢?一个很朴素的想法:在每个像素前面盖一个彩色滤光片(Color Filter Array, CFA),只让特定颜色的光通过。最常见的滤光片排列方式,就是1976年由柯达公司的Bryce Bayer发明的Bayer阵列。

核心概念: Bayer阵列的核心思想是“人眼对绿色最敏感,所以绿色像素数量是红蓝的两倍”。

标准的Bayer模式是2x2的单元重复排列。在这个单元里,有1个红色(R)像素、1个蓝色(B)像素、2个绿色(G)像素。为什么绿色多?因为人眼对550nm左右的黄绿光最敏感,多采样绿色可以模拟人眼的视觉特性。我在项目中遇到过,有些同学不理解为什么绿色多,其实你想想看,黑白照片转彩色时,绿色通道的细节往往最丰富,就是这个道理。

1.2 四种常见的Bayer排列模式

虽然都是2x2的RGGB单元,但传感器厂商在布局上会有细微差别。这直接影响了后续ISP(图像信号处理器)中demosaic(去马赛克)算法的方向。常见的四种模式如下:

模式名称 第一行 第二行 常见应用
RGGB R G R G ... G B G B ... Sony、OmniVision 多数传感器
GRBG G R G R ... B G B G ... 部分安森美、三星传感器
BGGR B G B G ... G R G R ... 部分CCD传感器、老款相机
GBRG G B G B ... R G R G ... 部分安霸、海思平台

避坑指南: 我曾经在一个项目中,因为忽略了传感器手册里标注的Bayer顺序,直接用默认的RGGB去处理,结果出来的图像颜色完全错乱,红色变成了蓝色。后来花了半天时间才定位到问题。所以,拿到一款新传感器,第一件事就是确认它的Bayer排列模式,千万别想当然。

1.3 RAW数据的位深:RAW10、RAW12、RAW16

说完了排列,我们聊聊“精度”。RAW数据是用二进制数来表示每个像素的亮度值。这个二进制数的位数,就是位深(Bit Depth)。

位深决定了动态范围和量化精度。常见的位深有:

  • RAW8:每个像素8bit,范围0-255。现在基本只在低端摄像头或预览流中使用。
  • RAW10:每个像素10bit,范围0-1023。这是目前手机和安防摄像头的主流。
  • RAW12:每个像素12bit,范围0-4095。常见于高端手机、微单和工业相机。
  • RAW14/RAW16:每个像素14bit或16bit,范围更大。主要用于专业电影机、天文摄影或医疗影像。

为什么需要更高的位深?说白了,就是为了给后期处理留出“余量”。你想想看,如果我用RAW8去拍一个明暗对比强烈的场景,高光部分可能直接过曝成255,暗部细节则淹没在0附近。但如果是RAW12,同样的场景,高光可能只到3500,暗部在100左右,后期通过曲线拉伸,就能把细节拉回来。

个人经验: 我建议,在做ISP调试时,如果条件允许,尽量用RAW12或RAW16作为输入。虽然数据量大了,但处理过程中的量化噪声会小很多。特别是做HDR(高动态范围)合成时,位深不够,合成出来的图像很容易出现色阶断层。

1.4 RAW数据在内存中的存储格式

这里有个容易混淆的点:位深和存储格式。比如RAW10,每个像素10bit,但计算机内存的最小寻址单位是1字节(8bit)。那多出来的2bit怎么存?

常见的存储方式有两种:

  • 高位对齐(Left Justified):将10bit数据放在16bit空间的高10位,低6位补0。这样每个像素占用2字节,处理方便,但浪费空间。
  • 紧凑打包(Packed):将4个10bit像素打包成5个字节(40bit)。这样节省带宽,但需要额外的解包逻辑。

举个例子,假设我们有4个RAW10像素值:

像素1: 0x3FF (10bit)
像素2: 0x155 (10bit)
像素3: 0x2AA (10bit)
像素4: 0x000 (10bit)

紧凑打包后(5字节):
字节0: 0xFF (像素1的低8位)
字节1: 0x03 (像素1的高2位) | (像素2的低6位 >> 4)
字节2: 0x55 (像素2的低4位 << 4) | (像素3的低4位 >> 4)
字节3: 0xAA (像素3的低8位 >> 2)
字节4: 0x02 (像素3的高2位) | (像素4的低8位 << 0)

嗯,这里要注意,不同的传感器厂商,打包方式可能略有不同。有的用MSB对齐,有的用LSB对齐。我建议你在写驱动时,一定要仔细阅读传感器的datasheet,或者直接用厂商提供的SDK来验证。

1.5 本章知识体系总览

为了让你对本章内容有个整体印象,我画了一张结构图。它把Bayer阵列、排列模式、位深和存储格式串在了一起。

RAW域基础知识体系 RAW域基础知识体系 RAW 原始数据 Bayer 阵列原理 4种排列模式 位深与存储格式 人眼视觉特性 CFA滤光片 RGGB / GRBG BGGR / GBRG RAW10 / RAW12 RAW16 / Packed 💡 核心要点:Bayer阵列决定了颜色采样的空间分布,位深决定了量化精度,排列模式决定了demosaic方向。 三者共同构成了RAW域数据的基础属性,是后续所有ISP处理的前提。

1.6 小结与思考

这一章我们讲了三个核心点:

  • Bayer阵列:为什么绿色像素多?因为人眼对绿色敏感。
  • 四种排列模式:RGGB、GRBG、BGGR、GBRG,搞错了颜色就乱了。
  • 位深与存储:RAW10/12/16的区别,以及紧凑打包的坑。

我个人觉得,理解RAW域是ISP工程师的基本功。很多后期处理中的疑难杂症,比如偏色、摩尔纹、伪色,根源都在RAW域。你如果能把这一章吃透,后面学demosaic、去噪、白平衡就会轻松很多。

课后建议: 找一张你手头设备的RAW文件(.dng或.raw),用Python的numpy或rawpy库读出来,打印一下它的shape和dtype。看看它是哪种Bayer排列,位深是多少。动手实践比看十遍书都管用。