3、RAW图预处理流程:黑电平校正、Lens Shading校正、坏点校正、去噪预处理

各位,咱们直接进入正题。RAW图从传感器出来,说白了就是一堆「带噪声的原始电压值」。你不能直接拿它做颜色处理,必须先过一遍预处理流水线。我习惯把这四个步骤叫做「RAW图的四道安检」——黑电平校正、Lens Shading校正、坏点校正、去噪预处理。顺序基本固定,但每家芯片厂商的微调策略不太一样。

核心观点:预处理做不好,后面所有调优都是白费功夫。你想想看,一个坏点没修掉,后面插值完就是一块彩色污渍,再好的AWB也救不回来。

RAW图预处理流水线 RAW输入 Bayer原始数据 黑电平校正 减固定偏置 Lens Shading 亮度/颜色校正 坏点校正 动态/静态修复 去噪预处理 空域/时域滤波 注意:去噪预处理通常放在 Bayer 域进行,避免颜色插值后噪声结构被破坏

3.1 黑电平校正(Black Level Correction)

先说黑电平。传感器在没有光照时,像素并不是输出0,而是有一个固定的偏置电压。这个偏置就是黑电平。我见过不少新手直接忽略这步,结果暗部偏色严重,怎么调都调不回来。

校正公式很简单:

// 黑电平校正
pixel_out = pixel_raw - black_level;
if (pixel_out < 0) pixel_out = 0;

但实际项目里没这么简单。不同传感器、不同增益下的黑电平不一样。我做过一个项目,传感器在低增益下黑电平是64,高增益下漂到了72。你如果只用一个固定值,高ISO下暗部就发紫。

我的经验:建议在产线标定时,至少采集3个不同增益下的黑电平值,做线性插值。有些高端传感器还会逐行变化,那就得做逐行校正。

增益档位 黑电平值(12bit) 备注
ISO 100 64 基准值
ISO 400 68 线性插值
ISO 1600 72 高增益漂移

避坑指南:我曾经在一个项目中,黑电平校正后忘了做clip,导致暗部出现负值,后面插值直接溢出成白色噪点。查了两天才找到原因——从此我养成了校正后立即clip的习惯。

3.2 Lens Shading校正(Lens Shading Correction)

镜头边缘进光量天生比中心少,这就是Lens Shading。说白了就是「中心亮、四周暗」。另外还有颜色shading——边缘偏色。这两个问题必须一起修。

校正原理:预先存一张增益网格图(Gain Map),每个像素位置乘一个对应的增益系数。

// Lens Shading校正
pixel_out = pixel_in * gain_table[row][col];
// 注意:R、Gr、Gb、B四个通道的增益表不同

我个人习惯用 9x13 或 17x25 的网格,然后双线性插值到全分辨率。网格太密浪费内存,太疏校正不平滑。嗯,这里要注意——网格的边界处理,我踩过坑。

关键参数对比:

网格密度 内存占用(12MP) 校正精度 适用场景
9x13 ~4KB 中等 手机摄像头
17x25 ~16KB 良好 车载/安防
33x49 ~64KB 优秀 专业相机

我的建议:颜色shading校正最好在Bayer域做,等插值成RGB后再做,边缘的色差已经被放大,校正效果会打折扣。

3.3 坏点校正(Bad Pixel Correction)

传感器生产过程中难免有坏点。坏点分两种:静态坏点(永远亮或永远暗)和动态坏点(只在特定条件下出现)。

静态坏点校正:产线标定时生成一张坏点坐标表,运行时直接替换。

// 静态坏点替换
if (is_bad_pixel[row][col]) {
    pixel_out = median_filter(raw, row, col, 3x3);
} else {
    pixel_out = raw[row][col];
}

动态坏点检测:实时判断当前像素是否异常。我常用的方法是——比较当前像素与周围8个像素的差值,如果超过阈值,就标记为坏点。

避坑指南:我曾经在一个项目中,动态坏点检测阈值设得太低,结果把正常的纹理细节当成了坏点,画面变得像磨皮过度一样。后来我改用自适应阈值——根据局部方差动态调整检测门限,效果好了很多。

你想想看,坏点校正放在Lens Shading之后是有道理的——因为Lens Shading会放大边缘的噪声和坏点,先校正亮度不均,再做坏点检测,准确率更高。

3.4 去噪预处理(Denoising Preprocessing)

最后一步是去噪。为什么叫「预处理」?因为这里只做轻度去噪,保留细节,后面还有专门的降噪模块做精细处理。

常用的Bayer域去噪方法:

  • 空域滤波:双边滤波、非局部均值(NLM)——效果好但计算量大
  • 时域滤波:多帧叠加、运动补偿——适合视频,静态场景效果极佳
  • 变换域滤波:小波阈值、BM3D——质量最高,但实时性差

我个人在手机项目里最常用的是「自适应双边滤波」。为什么?因为它在边缘保持和噪声抑制之间平衡得最好。而且可以在Bayer域直接操作,不用先插值成RGB,省掉一步开销。

// 自适应双边滤波(简化版)
for each pixel (i, j) {
    weight_sum = 0;
    value_sum = 0;
    for each neighbor (m, n) {
        w_spatial = exp(-((i-m)^2 + (j-n)^2) / (2 * sigma_s^2));
        w_range = exp(-(I(i,j) - I(m,n))^2 / (2 * sigma_r^2));
        weight = w_spatial * w_range;
        value_sum += I(m,n) * weight;
        weight_sum += weight;
    }
    I_out(i,j) = value_sum / weight_sum;
}

去噪参数调优口诀:

  • sigma_s(空间域):越大越模糊,一般取 1.5~3.0
  • sigma_r(值域):越大越保留细节,一般取 10~30(12bit数据)
  • 迭代次数:1次足够,多了细节全丢

我的经验:去噪预处理不要做得太狠。我见过有人把sigma_r设到5,结果暗部噪声是没了,但头发丝纹理也糊了。记住——预处理的目标是「让后面的插值和颜色处理不放大噪声」,不是一步到位降干净。

好了,这四个步骤走完,RAW图才算「干净」了。接下来才能放心地做白平衡、去马赛克、颜色校正。每一步都有坑,但只要你理解了原理,加上项目经验积累,这些都不是问题。