RAW域预处理:坏点校正、黑电平校正、镜头阴影校正、绿色平衡
各位好,欢迎来到第二章。上一章我们聊了RAW数据长什么样,这一章我们直接动手——把RAW数据里那些“脏东西”先清理掉。
RAW域预处理,说白了就是给传感器原始数据“洗脸”。传感器不是完美的,它会有坏点、有暗电流、有镜头带来的亮度不均、还有Bayer阵列本身的失衡。这四个问题不解决,后面的所有处理都是白搭。我个人的习惯是:先做BLC,再做DPC,然后LSC,最后GB。这个顺序不是随便定的,后面我会解释为什么。
2.1 黑电平校正(BLC)
先讲BLC,因为它最简单,也最基础。
传感器在没有光照的情况下,像素依然会输出一个非零值。这个值叫黑电平,来源是暗电流和电路噪声。如果不减掉它,整个图像的暗部会发灰,而且会影响后续所有增益计算的准确性。
BLC的做法通常有两种:
- OB(Optical Black)像素法:传感器边缘有一圈被遮挡的像素,它们永远不感光。取这些像素的平均值作为黑电平,然后从每个有效像素中减去这个值。
- 固定值法:有些传感器厂商会给出一个固定的黑电平值(比如64/1023),直接减掉就行。
我个人更推荐OB法,因为它能跟随温度变化。我记得有一次在户外测试,温度从25度升到50度,黑电平漂了将近10个DN(数字码值)。如果用固定值,暗部直接就偏色了。
代码实现很简单,但要注意数据类型溢出:
// 假设RAW数据是10bit,黑电平为64
for (int i = 0; i < width * height; i++) {
raw[i] = (raw[i] > black_level) ? (raw[i] - black_level) : 0;
}
2.2 坏点校正(DPC)
坏点,就是传感器上那些“不听话”的像素。它们要么永远亮着(亮点),要么永远暗着(暗点),要么响应异常。如果不校正,最终图像上就会出现一个个刺眼的“星星”或“黑洞”。
坏点校正分两步:检测和替换。
2.2.1 坏点检测
检测方法有很多,我常用的是邻域比较法。原理很简单:如果一个像素的值和它周围8个邻居的差异超过某个阈值,那它大概率是坏点。
具体做法:
- 取当前像素P,以及它周围8个同色通道的像素(因为Bayer阵列,同色通道间隔一个像素)。
- 计算这9个像素的均值μ和标准差σ。
- 如果|P - μ| > k * σ(k通常取3-5),则判定为坏点。
阈值k怎么选?我踩过坑。有一次为了追求“干净”,把k设成了2,结果正常像素被误判了一大片,图像变得模糊。后来我改成k=4,配合一个动态阈值——在暗区用大阈值,亮区用小阈值,效果就好多了。
2.2.2 坏点替换
检测到坏点后,不能直接扔掉,得用合理的值替换。常用方法:
- 中值替换:取周围同色像素的中值。抗噪性好,但会损失细节。
- 均值替换:取周围同色像素的均值。简单,但容易被其他坏点污染。
- 梯度导向替换:先判断边缘方向,然后沿边缘方向取均值。效果最好,计算量也最大。
我一般用中值替换,性价比最高。只有在高端项目中才会用梯度导向替换。
2.3 镜头阴影校正(LSC)
镜头阴影,也叫“暗角”。就是图像中心亮、四周暗的现象。原因是镜头的光学特性——边缘光线入射角大,到达传感器的光量少。
LSC的原理很简单:给每个像素乘一个增益系数,让四周的亮度补回来。但这个系数怎么来?
2.3.1 增益网格
通常的做法是:在实验室拍一张均匀的灰卡(或白墙),然后计算每个像素位置需要的增益。但像素太多,不可能存下每个像素的系数。所以实际用的是网格增益——把图像分成M×N个网格,每个网格存一个增益值,其他位置的增益通过插值得到。
| 网格大小 | 精度 | 存储开销 | 适用场景 |
|---|---|---|---|
| 16×16 | 低 | 小 | 低端芯片、实时性要求高 |
| 32×32 | 中 | 中 | 主流手机、安防 |
| 64×64 | 高 | 大 | 高端相机、医疗影像 |
我个人习惯用32×32网格,配合双线性插值。精度够用,存储也合理。
2.3.2 颜色通道独立校正
这里有个关键点:不同颜色的光,镜头阴影程度不一样。红光波长长,穿透力强,阴影轻;蓝光波长短,阴影重。所以R、G、B三个通道要分别计算增益网格。
如果不分开校正,会出现什么情况?我遇到过:校正完暗角,图像中心偏蓝、四周偏红。这就是因为用了同一套增益系数,没考虑色差。
2.4 绿色平衡(GB)
绿色平衡,是Bayer RAW特有的一个步骤。Bayer阵列里绿色像素有两组——Gr(跟R同行)和Gb(跟B同行)。理论上它们应该一样,但实际上因为工艺差异,Gr和Gb的响应会有偏差。
这个偏差会导致什么?在均匀灰色区域,会出现棋盘格状的纹理,俗称“格子噪声”。
2.4.1 校正方法
GB的做法是:在局部窗口内,计算Gr和Gb的均值,然后调整其中一个通道,使两者相等。
具体步骤:
- 取一个N×N的窗口(通常16×16或32×32)。
- 分别计算窗口内Gr像素的均值μ_gr和Gb像素的均值μ_gb。
- 计算增益gain = μ_gb / μ_gr(或者反过来)。
- 用gain调整Gr通道的值。
但要注意:不能在全图用一个增益。因为Gr和Gb的偏差可能随位置变化。我一般用滑动窗口,每个像素的增益由它周围的局部窗口决定。
2.5 本章知识体系
下面这张图总结了RAW域预处理的四个步骤及其关系:
2.6 总结与避坑清单
好了,四个步骤都讲完了。最后我列一个避坑清单,都是我在项目中真实遇到过的:
| 步骤 | 常见错误 | 后果 | 正确做法 |
|---|---|---|---|
| BLC | 用固定值不更新 | 暗部偏色、增益不准 | 用OB像素实时更新 |
| DPC | 跨通道检测坏点 | 条纹伪影 | 同色通道内检测 |
| LSC | 所有通道用同一增益 | 中心偏蓝、四周偏红 | R/G/B独立校正 |
| GB | 在LSC之前做 | 校正结果被破坏 | LSC之后再做 |