ISP Pipeline基础:从RAW图到RGB图像的经典流程

做图像处理的工程师,没人能绕过ISP Pipeline。说白了,它就是相机从“看见”到“看懂”之间的那套工序。我刚开始接触ISP时,以为就是把RAW数据直接转成RGB就完事了——后来被项目狠狠教育了一顿,才发现这里面门道深得很。

今天咱们就捋一遍经典ISP流程。你想想看,一块CMOS传感器拍下来的原始数据,其实啥也不是——就是一堆电荷值,连颜色都没有。怎么变成你手机里那张漂亮的照片?全靠Pipeline里这些模块接力。

核心认知: ISP Pipeline不是可选项,是必选项。没有它,RAW图就是一堆“色盲”数据。

2.1 经典ISP Pipeline全景图

先给个全局视角。下面这张图是我自己画的标准ISP流程,每个框都是一个独立模块。我在不同芯片平台(高通、联发科、海思)上都见过类似的架构,顺序可能微调,但核心逻辑不变。

经典ISP Pipeline流程图 RAW输入 黑电平校正 Lens Shading 坏点校正 去马赛克 白平衡 色彩校正矩阵 Gamma校正 色调映射 RGB输出 关键说明: • 去马赛克是RAW到RGB的分水岭——之前全是单通道,之后才有三通道 • 白平衡和色彩校正矩阵决定了“颜色准不准”,我调过最头疼的就是这俩 • Gamma校正和色调映射负责“好不好看”,主观感受全看这里 • 深度学习降噪可以插在多个位置,但最常见的是放在去马赛克之后 • 不同芯片厂商的Pipeline顺序有差异,但核心模块一个不少

2.2 前置处理:把RAW数据“洗干净”

RAW数据进Pipeline,第一件事不是做颜色,而是做校正。我见过不少新手直接跳过这步,结果后面怎么调都调不对——因为底子就是脏的。

2.2.1 黑电平校正

CMOS传感器有暗电流,即使完全遮光,像素也会读出非零值。这个值就是黑电平。校正很简单:pixel_out = pixel_raw - black_level。但要注意——不同增益下的黑电平不一样。我曾经在项目里吃过这个亏,用了固定黑电平,结果高ISO下暗部偏紫,查了两天才发现是黑电平没跟着增益走。

2.2.2 Lens Shading校正

镜头边缘进光量天生比中心少,拍出来四角发暗。校正方法是用一张均匀灰板拍出增益图,然后逐像素乘回去。公式:pixel_corrected = pixel_raw × gain(x, y)。嗯,这里要注意——增益图需要做平滑,不然会引入网格噪声。

2.2.3 坏点校正

传感器上总有那么几个“死像素”或“亮点”。我习惯用中值滤波做动态检测:如果一个像素和周围8邻域差异超过阈值,就替换成邻域中值。阈值怎么设?看噪声水平——低ISO设小点,高ISO设大点,不然容易误判。

我的经验: 坏点校正最好做两遍——第一遍在RAW域做静态坏点(查表),第二遍在去马赛克后做动态坏点(算法检测)。两遍配合,基本能覆盖99%的情况。

2.3 核心处理:从单通道到三通道

前置处理完,数据还是单通道的Bayer格式。接下来这一步,是整个Pipeline的分水岭。

2.3.1 去马赛克

Bayer格式每个像素只有一个颜色分量(R/G/B之一),去马赛克就是通过插值把缺失的两个颜色补回来。最经典的是双线性插值,但效果一般——边缘容易有锯齿和伪色。我推荐用自适应插值:先判断边缘方向,再沿边缘方向插值。代码大概长这样:

// 简化版自适应去马赛克(G通道插值)
if (abs(G_left - G_right) < abs(G_up - G_down)) {
    // 水平边缘,沿水平方向插值
    G_out = (G_left + G_right) / 2;
} else {
    // 垂直边缘,沿垂直方向插值
    G_out = (G_up + G_down) / 2;
}

当然,现在高端ISP都用深度学习做去马赛克了,效果确实好,但计算量也大。工程落地时得权衡——你是做手机还是做安防?帧率要求多少?这些直接决定算法选型。

2.3.2 白平衡

人眼有色彩恒常性——白纸在日光下是白的,在钨丝灯下看着还是白的。但传感器没这本事,得靠算法校正。经典方法是灰度世界假设:R_gain = G_avg / R_avg,B_gain = G_avg / B_avg。但这个方法在纯色场景下会翻车——你想想看,拍一片红玫瑰,灰度世界假设会把红色压下去,结果花变灰了。

避坑指南: 我曾经在室内暖光灯场景下用灰度世界法,结果白平衡把整个画面拉蓝了。后来加了色温估计和场景分类,才稳住。记住——没有万能的AWB算法,场景检测是必须的。

2.3.3 色彩校正矩阵

传感器的色彩响应和人眼不一样,得用一个3×3矩阵把传感器RGB映射到标准RGB空间。这个矩阵怎么来的?拍24色卡,最小二乘法拟合。我调过很多次,发现矩阵系数对噪声很敏感——系数大了,颜色鲜艳但噪声也放大;系数小了,噪声小但颜色发灰。这是个典型的trade-off。

2.4 后处理:让图像“好看”

颜色准了,但看着可能还是灰蒙蒙的。后处理就是干这个的——让图像符合人眼审美。

2.4.1 Gamma校正

人眼对暗部变化敏感,对亮部变化不敏感。Gamma校正就是把线性光强映射到感知均匀空间。标准Gamma是2.2:out = in^(1/2.2)。但注意——这个操作会放大暗部噪声。我一般在Gamma之前加一层降噪,不然暗部噪点会被Gamma“提亮”,特别难看。

2.4.2 色调映射

真实场景的动态范围可能超过100dB,但显示设备只有60dB左右。色调映射就是把高动态范围压缩到低动态范围,同时保留细节。经典方法有直方图均衡化、自适应对数映射。我个人的习惯是:先做全局映射保证整体亮度,再做局部映射保留细节——两步走,效果最稳。

2.5 各模块的工程权衡

做工程不是做学术——不能只看效果,还得看算力和功耗。下面这个表是我自己整理的,每个模块的算力占比和优化空间:

模块 算力占比(典型) 优化空间 我的建议
黑电平校正 <1% 几乎无 查表实现,别做实时计算
Lens Shading 2-3% 中等 用降采样增益图,双线性插值
坏点校正 3-5% 较大 静态查表+动态检测,别全量跑
去马赛克 15-25% 较大 自适应插值性价比最高
白平衡 2-5% 中等 场景分类+多算法融合
色彩校正矩阵 <1% 几乎无 固定矩阵,别动态更新
Gamma校正 1-2% 较小 LUT实现,256级足够
色调映射 10-15% 较大 全局+局部两步走,别一步到位
工程落地核心原则: 每个模块都要问自己三个问题——1)能不能查表?2)能不能降采样?3)能不能只在关键帧跑?这三个问题想清楚,算力至少省30%。

2.6 深度学习降噪的插入位置

咱们这门课的核心是深度学习降噪,那它该插在Pipeline的哪个位置?我见过三种主流方案:

  • 方案A:放在去马赛克之前(RAW域)——好处是噪声模型简单(传感器噪声),坏处是数据量小(单通道),网络设计受限。
  • 方案B:放在去马赛克之后(RGB域)——好处是数据丰富(三通道),坏处是噪声模型复杂(经过了插值和校正)。
  • 方案C:放在Gamma之后(sRGB域)——好处是和人眼感知对齐,坏处是噪声已经被Gamma放大了,降噪难度大。

我个人倾向方案B。为什么?因为去马赛克之后,数据已经变成RGB三通道,网络可以充分利用色彩信息做联合降噪。而且这个位置离最终输出近,降噪效果能直接体现在最终图像上。当然,具体选哪个还得看你的硬件平台和帧率要求——没有银弹。

好了,这一章就到这儿。ISP Pipeline的每个模块都值得深挖,但咱们后面会重点讲深度学习降噪怎么和这些模块配合。记住——理解经典流程,才能知道AI该往哪儿发力。