ISP管线基础:从RAW图到RGB图

各位同学,今天我们来聊聊ISP管线里最核心的一段——从RAW图到RGB图的转换。说白了,就是让相机传感器看到的原始数据,变成我们人眼能理解的彩色图像。

我刚开始接触ISP时,总觉得这步很简单,不就是把拜耳阵列转成RGB嘛。后来真做项目才发现,这里面的坑一个接一个。嗯,咱们今天就把这些模块拆开揉碎了讲。

RAW图到底是什么?

先搞清楚一件事:相机传感器拍到的RAW图,不是我们平时看到的照片。它每个像素只记录一种颜色——红、绿或蓝。这就是拜耳阵列(Bayer Pattern)。

关键点:RAW图是单通道的,每个像素只有亮度值,没有颜色信息。颜色是靠相邻像素猜出来的。

常见的拜耳阵列有RGGB、BGGR、GRBG等。我个人习惯用RGGB,因为大部分传感器厂商默认就是这个排列。

拜耳类型 排列顺序 常见传感器
RGGB 红-绿-绿-蓝 Sony IMX系列
BGGR 蓝-绿-绿-红 部分OmniVision
GRBG 绿-红-蓝-绿 三星部分型号

避坑指南:我曾经在项目里搞错过拜耳排列顺序,结果去马赛克后图像全是紫绿色的。排查了两天才发现是配置写反了。所以拿到RAW图第一件事,先确认拜耳类型。

去马赛克(Demosaic)——猜颜色的艺术

去马赛克,说白了就是根据周围像素猜出每个像素缺失的颜色。比如一个红色像素,它缺绿色和蓝色,我们就用相邻的绿色和蓝色像素插值出来。

常用的方法有几种:

  • 双线性插值:最简单,取周围像素的平均值。速度快,但边缘会有锯齿和伪色。
  • 边缘导向插值:先判断边缘方向,再沿边缘插值。效果比双线性好,但计算量翻倍。
  • 自适应插值:根据局部纹理复杂度动态选择插值方式。我项目里常用这个,效果和性能比较平衡。

我的经验:如果你做深度学习降噪,建议去马赛克放在降噪之后做。因为RAW域的噪声是高斯分布的,去马赛克后噪声会变成空间相关的,更难处理。

白平衡(AWB)——让白色真的白

你想想看,同一张白纸,在日光下是白的,在钨丝灯下是黄的,在荧光灯下是蓝的。人眼会自动校正,但相机不会。白平衡就是干这个的。

白平衡的核心是估计光源色温,然后对RGB三个通道分别乘一个增益系数。

// 白平衡增益计算示例
float r_gain = 1.8;   // 红色通道增益
float g_gain = 1.0;   // 绿色通道保持
float b_gain = 1.4;   // 蓝色通道增益

// 应用增益
pixel.r = pixel.r * r_gain;
pixel.g = pixel.g * g_gain;
pixel.b = pixel.b * b_gain;

常见的白平衡算法有:

  • 灰度世界法:假设场景平均颜色是灰色,然后调整增益使RGB均值相等。
  • 完美反射法:找到图像中最亮的点,假设它是白色,然后以此校正。
  • 色温估计法:通过统计R/G和B/G的比值来估计色温。

注意:白平衡做不好,后面Gamma校正和色彩矩阵都会跟着偏。我曾经在一个夜景项目里,白平衡没调好,结果整个画面偏蓝,客户直接打回重做。

Gamma校正——亮度的秘密

Gamma校正,说白了就是做两件事:一是补偿显示器的非线性响应,二是把12bit或14bit的RAW数据压缩到8bit。

人眼对暗部细节更敏感,对亮部不敏感。Gamma曲线就是让暗部保留更多细节,亮部压缩一些。

// Gamma校正标准公式
float gamma = 1.0 / 2.2;
output = pow(input, gamma);

// 实际项目中常用分段函数
if (input <= 0.0031308) {
    output = 12.92 * input;
} else {
    output = 1.055 * pow(input, 1.0/2.4) - 0.055;
}

这里要注意,Gamma校正是在线性域做的。也就是说,去马赛克和白平衡之后,图像还是线性的,然后做Gamma,最后输出到8bit。

重要:如果你要做深度学习降噪,一定要在Gamma校正之前做。因为Gamma会改变噪声的分布,让高斯噪声变成非均匀的,模型很难学。

ISP管线完整流程

好了,我们把这几个模块串起来,看看完整的ISP管线长什么样。

ISP管线核心流程 RAW输入 黑电平校正 去马赛克 白平衡 Gamma校正 色彩矩阵 RGB输出 说明: 1. 深度学习降噪通常放在去马赛克之前(RAW域)或之后(RGB域) 2. 白平衡和Gamma校正会改变噪声分布,降噪应放在它们之前 3. 色彩矩阵是线性变换,对噪声影响较小 4. 实际ISP管线还有更多模块:LSC、CCM、锐化等,这里只列核心

各模块对噪声的影响

做深度学习降噪,必须知道每个模块怎么影响噪声。我整理了一张表,方便大家对照。

模块 对噪声的影响 降噪建议
黑电平校正 基本不影响噪声分布 可放在降噪前或后
去马赛克 使噪声空间相关,产生伪色 建议降噪在去马赛克前做
白平衡 放大某些通道的噪声 降噪必须在白平衡前
Gamma校正 使暗部噪声放大,亮部压缩 降噪必须在Gamma前
色彩矩阵 线性变换,噪声仍保持高斯 可放在降噪后

我的建议:如果你只能选一个位置做降噪,我推荐放在去马赛克之前,也就是RAW域。这时候噪声还是独立同分布的高斯噪声,模型最好学。我曾经在RGB域做过降噪,效果差了一大截,后来改回RAW域才解决问题。

实战中的注意事项

最后聊几个我在项目中踩过的坑:

  • 位宽问题:RAW图通常是12bit或14bit,但深度学习模型一般处理8bit或16bit。我习惯先转成16bit浮点,避免精度损失。
  • 拜耳排列:不同传感器排列不同,模型输入时要做相应处理。我一般把拜耳图拆成4个通道(R、G1、G2、B),这样模型不用关心排列。
  • 黑电平:RAW图的黑电平不是0,一般是64或128。降噪前要先把黑电平减掉,否则模型会学到偏移。
  • 归一化:我习惯把RAW数据归一化到[0,1]再送模型,这样训练更稳定。

再次提醒:ISP管线里的每个模块都不是孤立的。你改了一个模块,后面所有模块的输出都会变。所以做深度学习降噪时,一定要考虑整个管线的耦合关系。我曾经只优化了降噪模型,没调白平衡参数,结果图像整体偏色,客户不认账。