RAW域预处理:黑电平校正、LSC校正、坏点校正、RAW域去噪

各位同学,欢迎来到第三章。前两章我们聊了夜景多帧的整体架构和RAW域的基础知识。今天要讲的这四个模块——黑电平校正、LSC校正、坏点校正、RAW域去噪——是ISP Pipeline里最靠前的几个环节。

说白了,它们就是「把传感器送来的原始数据,变成一块干净、均匀、可用的画布」。你后面所有的多帧对齐、融合、Tone Mapping,都建立在这块画布上。画布脏了,后面再怎么调也是白搭。

核心观点: RAW域预处理的质量,直接决定了夜景多帧合成的天花板。我见过太多项目,算法模型调得天花乱坠,结果一查,黑电平没扣干净,暗部偏色严重——这种问题,后面根本救不回来。
RAW域预处理 Pipeline 传感器 RAW 10/12/14bit 黑电平校正 BLC LSC 校正 镜头阴影校正 坏点校正 DPC RAW 域去噪 NR 💡 处理顺序为什么是这样? 1. 先扣黑电平,让数据从「有偏置」变成「真实信号」 2. 再做LSC,消除镜头带来的亮度不均匀 3. 坏点校正和去噪的顺序,不同平台有争议——我后面会讲

1. 黑电平校正(BLC)——把「零」找回来

先问一个问题:传感器在完全无光的情况下,输出是不是0?

不是。实际上,由于传感器电路本身的暗电流、ADC的偏置,即使盖上镜头盖,输出也会有一个固定的偏移量。这个偏移量,就是黑电平(Black Level)。

校正方法很简单:P_out = P_raw - black_level。但坑在哪里?

  • 不同通道的黑电平可能不同:R、Gr、Gb、B四个通道,暗电流特性不一样。我见过某款三星传感器,R通道黑电平是64,B通道是66,差了2个DN。如果不分开处理,暗部就会出现偏色。
  • 黑电平会随温度变化:夜景模式通常曝光时间长,传感器发热,黑电平会漂移。我建议在长曝光帧前后各采一次OB(Optical Black)区域,取平均做动态校正。
  • 多帧处理时要注意:每一帧的黑电平可能不一样。如果你用同一个值去扣所有帧,融合后暗部会闪烁。
我的习惯: 在项目初期,我会先抓一帧全黑数据,把每个通道的直方图拉出来看看。如果发现黑电平不是整数,或者不同通道差异超过1个DN,就要考虑逐通道校正了。

2. LSC校正——让画面亮度均匀

镜头的光学特性决定了:画面中心亮,四周暗。这就是Lens Shading,也叫暗角。在夜景模式下,暗角会被放大——因为四周信号本来就弱,再被镜头衰减一下,信噪比就更差了。

LSC校正的原理是:对每个像素位置,乘上一个增益系数。这个系数通常来自一个预先标定好的Gain Map。

网格尺寸 适用场景 优缺点
9×7 低端平台,实时性要求高 速度快,但校正精度一般
17×13 主流高通平台 平衡了精度和性能
33×25 高端旗舰,夜景模式 精度高,但标定和存储成本大

这里有个关键点:Gain Map是在特定色温下标定的。不同色温下,镜头的光学特性会有细微变化。我建议在D65和A光源下各标一套,运行时根据AWB结果做插值。

曾经踩过的坑: 有一次,夜景模式拍出来的照片,中心偏绿,四周偏紫。查了两天,发现是LSC Gain Map的R/B通道增益在低温下发生了偏移。后来我们在标定流程里加了一个温度补偿项,问题才解决。

3. 坏点校正(DPC)——别让一个像素毁了整张照片

传感器生产过程中,难免会有一些像素点「坏掉」——要么一直亮(白点),要么一直暗(黑点),要么响应异常。在夜景长曝光下,这些坏点会特别明显。

坏点校正分两步:

  1. 静态坏点校正:工厂标定时,记录下坏点的坐标,生成一张坏点Map。运行时直接查表替换。
  2. 动态坏点校正:实时检测当前帧中出现的异常点。比如某个像素的亮度比周围8个邻居都高很多,就判定为坏点。

动态校正的算法,我常用的是基于梯度的检测:

// 简化的动态坏点检测逻辑
for each pixel (x, y):
    // 计算四个方向的梯度
    grad_h = abs(P(x,y) - P(x-1,y)) + abs(P(x,y) - P(x+1,y))
    grad_v = abs(P(x,y) - P(x,y-1)) + abs(P(x,y) - P(x,y+1))
    grad_d1 = abs(P(x,y) - P(x-1,y-1)) + abs(P(x,y) - P(x+1,y+1))
    grad_d2 = abs(P(x,y) - P(x-1,y+1)) + abs(P(x,y) - P(x+1,y-1))
    
    min_grad = min(grad_h, grad_v, grad_d1, grad_d2)
    
    if min_grad > threshold:
        // 标记为坏点,用中值替换
        P_out(x,y) = median(neighbors)

阈值怎么设?我一般取当前局部区域的噪声标准差乘以一个系数。夜景模式下噪声大,阈值要适当放宽,否则会把正常像素误判为坏点。

4. RAW域去噪——在「保细节」和「去噪」之间走钢丝

终于到了重头戏。RAW域去噪和RGB域去噪最大的区别是什么?

RAW域的数据是Bayer格式的,每个像素只包含一个颜色通道的信息。你不能直接用RGB的算法,因为相邻像素的颜色不同,直接滤波会引入颜色混叠。

常用的RAW域去噪方法:

  • Bilateral Filter(双边滤波):考虑像素值差异和空间距离,保边效果好。但计算量大,夜景多帧场景下要优化。
  • Non-local Means(非局部均值):在全图找相似块做加权平均。效果很好,但速度慢——我一般只在关键帧上用。
  • 小波域去噪:在频域上做阈值处理。对高斯噪声效果好,但容易产生振铃效应。

在高通平台上,我推荐用多帧联合去噪的思路。夜景模式本身就有多帧数据,为什么不利用帧间的冗余信息呢?

实战经验: 我在一个项目中,把单帧的Bilateral Filter改成「多帧引导滤波」——用短曝光帧的细节信息,去引导长曝光帧的去噪。信噪比提升了约3dB,而细节损失几乎不可见。

5. 四个模块的联动调优

这四个模块不是孤立的。我列一个调优时的检查清单:

问题现象 可能原因 排查方向
暗部偏色 黑电平校正不准 检查OB区域,确认逐通道BLC
四周偏暗/偏色 LSC增益不准 重新标定Gain Map,检查色温补偿
画面有孤立亮点 坏点校正没覆盖到 更新坏点Map,调低动态检测阈值
去噪后细节模糊 去噪强度过大 降低强度,或改用边缘保护更强的算法
多帧融合后闪烁 各帧预处理参数不一致 统一BLC/LSC参数,或做帧间参数平滑

嗯,这里要注意:调优的顺序很重要。我建议先把BLC和LSC调准,再做坏点校正,最后调去噪。前面的环节不准,后面的调优都是白费功夫。

一个小技巧: 在调试阶段,可以写一个简单的「RAW域可视化工具」——把每个预处理步骤前后的数据都dump出来,用伪彩色显示。这样一眼就能看出哪个环节出了问题。