RAW域预处理:坏点校正、黑电平校正、镜头阴影校正、绿色平衡

各位好,欢迎来到第二章。上一章我们聊了RAW数据长什么样,这一章我们直接动手——把RAW数据里那些“脏东西”先清理掉。

RAW域预处理,说白了就是给传感器原始数据“洗脸”。传感器不是完美的,它会有坏点、有暗电流、有镜头带来的亮度不均、还有Bayer阵列本身的失衡。这四个问题不解决,后面的所有处理都是白搭。我个人的习惯是:先做BLC,再做DPC,然后LSC,最后GB。这个顺序不是随便定的,后面我会解释为什么。

核心观点:RAW域预处理是ISP Pipeline的基石。这四步做不好,后面的AWB、Demosaic、去噪都会放大错误。宁可花80%的时间调好这四步,也不要急着去看最终图像。

2.1 黑电平校正(BLC)

先讲BLC,因为它最简单,也最基础。

传感器在没有光照的情况下,像素依然会输出一个非零值。这个值叫黑电平,来源是暗电流和电路噪声。如果不减掉它,整个图像的暗部会发灰,而且会影响后续所有增益计算的准确性。

BLC的做法通常有两种:

  • OB(Optical Black)像素法:传感器边缘有一圈被遮挡的像素,它们永远不感光。取这些像素的平均值作为黑电平,然后从每个有效像素中减去这个值。
  • 固定值法:有些传感器厂商会给出一个固定的黑电平值(比如64/1023),直接减掉就行。

我个人更推荐OB法,因为它能跟随温度变化。我记得有一次在户外测试,温度从25度升到50度,黑电平漂了将近10个DN(数字码值)。如果用固定值,暗部直接就偏色了。

小技巧:OB像素通常分布在传感器四周,取中间区域的平均值更稳定,避开边缘可能漏光的OB像素。

代码实现很简单,但要注意数据类型溢出:

// 假设RAW数据是10bit,黑电平为64
for (int i = 0; i < width * height; i++) {
    raw[i] = (raw[i] > black_level) ? (raw[i] - black_level) : 0;
}
注意:减完黑电平后,数据范围会变小。比如10bit RAW从0-1023变成0-959。后续的增益和校正要考虑这个变化,否则会过曝。

2.2 坏点校正(DPC)

坏点,就是传感器上那些“不听话”的像素。它们要么永远亮着(亮点),要么永远暗着(暗点),要么响应异常。如果不校正,最终图像上就会出现一个个刺眼的“星星”或“黑洞”。

坏点校正分两步:检测和替换。

2.2.1 坏点检测

检测方法有很多,我常用的是邻域比较法。原理很简单:如果一个像素的值和它周围8个邻居的差异超过某个阈值,那它大概率是坏点。

具体做法:

  1. 取当前像素P,以及它周围8个同色通道的像素(因为Bayer阵列,同色通道间隔一个像素)。
  2. 计算这9个像素的均值μ和标准差σ。
  3. 如果|P - μ| > k * σ(k通常取3-5),则判定为坏点。

阈值k怎么选?我踩过坑。有一次为了追求“干净”,把k设成了2,结果正常像素被误判了一大片,图像变得模糊。后来我改成k=4,配合一个动态阈值——在暗区用大阈值,亮区用小阈值,效果就好多了。

2.2.2 坏点替换

检测到坏点后,不能直接扔掉,得用合理的值替换。常用方法:

  • 中值替换:取周围同色像素的中值。抗噪性好,但会损失细节。
  • 均值替换:取周围同色像素的均值。简单,但容易被其他坏点污染。
  • 梯度导向替换:先判断边缘方向,然后沿边缘方向取均值。效果最好,计算量也最大。

我一般用中值替换,性价比最高。只有在高端项目中才会用梯度导向替换。

避坑指南:我曾经在调试一款手机传感器时,发现DPC之后图像上出现了一条条的“条纹”。查了两天才发现,是因为坏点检测时没有考虑Bayer格式,把不同颜色的像素混在一起比较了。记住:DPC必须在同色通道内进行。

2.3 镜头阴影校正(LSC)

镜头阴影,也叫“暗角”。就是图像中心亮、四周暗的现象。原因是镜头的光学特性——边缘光线入射角大,到达传感器的光量少。

LSC的原理很简单:给每个像素乘一个增益系数,让四周的亮度补回来。但这个系数怎么来?

2.3.1 增益网格

通常的做法是:在实验室拍一张均匀的灰卡(或白墙),然后计算每个像素位置需要的增益。但像素太多,不可能存下每个像素的系数。所以实际用的是网格增益——把图像分成M×N个网格,每个网格存一个增益值,其他位置的增益通过插值得到。

网格大小 精度 存储开销 适用场景
16×16 低 小 低端芯片、实时性要求高
32×32 中 中 主流手机、安防
64×64 高 大 高端相机、医疗影像

我个人习惯用32×32网格,配合双线性插值。精度够用,存储也合理。

2.3.2 颜色通道独立校正

这里有个关键点:不同颜色的光,镜头阴影程度不一样。红光波长长,穿透力强,阴影轻;蓝光波长短,阴影重。所以R、G、B三个通道要分别计算增益网格。

如果不分开校正,会出现什么情况?我遇到过:校正完暗角,图像中心偏蓝、四周偏红。这就是因为用了同一套增益系数,没考虑色差。

经验之谈:LSC的增益不要超过4倍。如果某个角落需要4倍以上的增益才能补回来,说明镜头和传感器的匹配有问题,靠算法硬拉会引入大量噪声。这时候应该回头改光学设计,而不是死磕ISP。

2.4 绿色平衡(GB)

绿色平衡,是Bayer RAW特有的一个步骤。Bayer阵列里绿色像素有两组——Gr(跟R同行)和Gb(跟B同行)。理论上它们应该一样,但实际上因为工艺差异,Gr和Gb的响应会有偏差。

这个偏差会导致什么?在均匀灰色区域,会出现棋盘格状的纹理,俗称“格子噪声”。

2.4.1 校正方法

GB的做法是:在局部窗口内,计算Gr和Gb的均值,然后调整其中一个通道,使两者相等。

具体步骤:

  1. 取一个N×N的窗口(通常16×16或32×32)。
  2. 分别计算窗口内Gr像素的均值μ_gr和Gb像素的均值μ_gb。
  3. 计算增益gain = μ_gb / μ_gr(或者反过来)。
  4. 用gain调整Gr通道的值。

但要注意:不能在全图用一个增益。因为Gr和Gb的偏差可能随位置变化。我一般用滑动窗口,每个像素的增益由它周围的局部窗口决定。

重要提醒:GB校正必须在LSC之后做。因为LSC会改变不同位置的亮度,如果在LSC之前做GB,校正结果会被LSC破坏。这也是为什么我一开始说顺序很重要。

2.5 本章知识体系

下面这张图总结了RAW域预处理的四个步骤及其关系:

RAW域预处理流程 RAW域预处理流程 RAW Sensor Data ① 黑电平校正 (BLC) ② 坏点校正 (DPC) ③ 镜头阴影校正 (LSC) ④ 绿色平衡 (GB) Clean RAW Data 为什么是这个顺序? • BLC先做:后续校正需要准确的黑电平 • DPC其次:坏点会影响LSC的增益计算 • LSC第三:改变亮度后做GB更准确 • GB最后:平衡Gr/Gb差异 常见问题 • 顺序颠倒 → 图像偏色/噪声放大 • 参数过强 → 细节丢失/伪影

2.6 总结与避坑清单

好了,四个步骤都讲完了。最后我列一个避坑清单,都是我在项目中真实遇到过的:

步骤 常见错误 后果 正确做法
BLC 用固定值不更新 暗部偏色、增益不准 用OB像素实时更新
DPC 跨通道检测坏点 条纹伪影 同色通道内检测
LSC 所有通道用同一增益 中心偏蓝、四周偏红 R/G/B独立校正
GB 在LSC之前做 校正结果被破坏 LSC之后再做