ISP Pipeline概览:移动端ISP架构、RAW域处理、RGB域处理、YUV域处理

各位同学,咱们直接进入正题。移动端ISP(图像信号处理器)的Pipeline,说白了就是一张RAW照片从传感器出来,到最终变成你屏幕上那张能发朋友圈的图,中间经历的一系列“加工工序”。

我刚开始接触这行的时候,觉得ISP就是个黑盒子——RAW进去,好看的图出来。后来自己动手调过几个项目才发现,这里面的门道深着呢。尤其是低光照场景,Pipeline里任何一个环节没处理好,最终效果都会崩。

今天咱们就把这个Pipeline拆开,看看每个域都在干什么。

一、移动端ISP整体架构

先看一张整体流程图,帮你建立全局认知。

核心观点:移动端ISP的Pipeline通常分为三大处理域——RAW域、RGB域、YUV域。每个域解决不同的问题,顺序不能乱。

移动端ISP Pipeline 三大处理域 图像传感器 (RAW) RAW域处理 黑电平校正 · 去噪 · 坏点校正 · 去马赛克 RGB域处理 白平衡 · 颜色校正 · Gamma · 色调映射 YUV域处理 降噪 · 锐化 · 色彩增强 · 编码输出 最终图像 (YUV/RGB)

这张图你应该记在脑子里。每次调低光照算法的时候,都要清楚当前在哪个域、下一步要去哪。

二、RAW域处理

RAW域是Pipeline的第一站。传感器输出的原始数据就是RAW格式——每个像素只记录一种颜色(R、G、B之一),按Bayer阵列排列。

为什么要在RAW域做处理?因为这时候数据还没被“污染”,信噪比最高。说白了,越早做降噪和校正,效果越好。等到了RGB域再做,噪声已经被插值放大了,处理起来事倍功半。

2.1 黑电平校正

传感器在完全无光的情况下,输出并不是0,而是有一个固定的偏移量,这叫黑电平。校正很简单:减去这个偏移值。

// 黑电平校正伪代码
for each pixel in RAW_image:
    pixel = max(pixel - black_level, 0)

我的经验:不同增益下的黑电平可能不一样。低光照场景下增益很高,黑电平会漂移。我建议你在暗电流标定时,至少取3个不同增益点做线性拟合,别只用一个固定值。

2.2 坏点校正

传感器上总有几个“坏点”——要么一直亮(热像素),要么一直暗(死像素)。低光照下这些坏点特别显眼。

我常用的方法是动态坏点检测:

  • 计算当前像素与周围8邻域的差值
  • 如果差值超过阈值,判定为坏点
  • 用中值或均值替换

注意:阈值要随ISO增益动态调整。我曾经在某个项目里用固定阈值,结果高ISO下把正常像素误判为坏点,画面出现大量“斑块”。后来改成ISO自适应阈值才解决。

2.3 去马赛克

这是RAW域最关键的一步。把Bayer格式的每个像素“插值”成完整的R、G、B三个通道。

常见的算法有:

算法 质量 计算量 低光照表现
双线性插值 低 极低 差(伪彩严重)
边缘导向插值 中 低 一般
自适应插值 高 中 较好
深度学习插值 极高 高 优秀(但移动端吃力)

我个人习惯在低光照场景下用边缘导向插值,计算量可控,伪彩也比双线性少很多。

三、RGB域处理

RAW域处理完,数据变成了完整的RGB图像。这时候我们开始处理颜色相关的问题。

3.1 白平衡

低光照下,光源色温往往偏暖(白炽灯)或偏冷(荧光灯/月光)。白平衡就是让白色物体在图像里看起来是白的。

我常用的方法是灰度世界法 + 色温估计:

  1. 统计全图的R、G、B均值
  2. 计算R/G和B/G比值
  3. 根据比值查表得到色温
  4. 应用对应的增益系数

避坑指南:低光照下,大面积的暗区会导致白平衡误判。我曾经遇到一个场景——夜晚的草地,绿色通道占比过高,算法误判为“偏绿”,强行拉高红色,结果草地变成了紫色。后来我加入了“置信度权重”,只统计亮度较高的区域做白平衡,问题就解决了。

3.2 Gamma校正

人眼对暗部细节的敏感度远高于亮部。Gamma校正就是做这件事——把暗部拉开,亮部压缩。

标准Gamma曲线:

// Gamma校正
output = pow(input, 1.0 / gamma)
// gamma通常取2.2

低光照场景下,我建议适当降低Gamma值(比如2.0),让暗部更亮一些。但别降太多,否则亮部会过曝。

四、YUV域处理

RGB转YUV之后,亮度和颜色分开了。Y通道负责亮度,UV通道负责色度。这时候处理起来更灵活。

4.1 亮度降噪

低光照下Y通道的噪声最明显。我通常用空域+时域联合降噪:

  • 空域:双边滤波或NLM(非局部均值),保留边缘的同时去噪
  • 时域:多帧对齐后做时域滤波,对静态区域效果极好

我的经验:时域降噪的强度要跟运动检测联动。运动区域强度降低,否则会出现“鬼影”。我曾经在调试夜景模式时,因为时域强度太高,人走路拖出了半透明的尾巴……

4.2 锐化

降噪之后图像会变“软”,需要锐化找回细节。但低光照下锐化很容易放大噪声。

我推荐使用非锐化掩模(Unsharp Mask)加阈值控制:

// 非锐化掩模
blur = gaussian_filter(Y)
detail = Y - blur
// 只对细节幅度大于阈值的区域做增强
if abs(detail) > threshold:
    Y_enhanced = Y + strength * detail
else:
    Y_enhanced = Y

阈值设得好,既能锐化边缘,又不会把噪声凸显出来。

4.3 色彩增强

低光照下颜色饱和度会下降。在UV通道上适当提升饱和度,能让画面更“生动”。

但注意——别过头。我见过不少算法把夜景调得跟动画片一样,颜色浓得发假。适度增强,保持自然感才是王道。

五、各域处理对比总结

处理域 输入 核心任务 低光照关键点
RAW域 Bayer RAW 黑电平、坏点、去噪、去马赛克 信噪比最高,降噪效果最好
RGB域 完整RGB 白平衡、颜色校正、Gamma 注意暗区白平衡误判
YUV域 YUV 4:2:0/4:4:4 降噪、锐化、色彩增强 亮度和颜色分开处理,灵活性高