3. RAW域去噪:空间域去噪与边缘保留滤波

RAW域去噪,说白了就是传感器读出数据后、做任何彩色处理之前的第一道降噪工序。这个位置很特殊——噪声还没被插值、增益、颜色校正放大,信噪比最原始,也最好处理。我做了这么多年ISP调试,可以负责任地说:RAW域去噪做得好,后面所有模块都会轻松很多。

核心观点:RAW域去噪不是简单的“模糊一下”,而是在保留真实细节的前提下,把传感器引入的读出噪声、光子散粒噪声、暗电流噪声尽可能干净地分离出去。

3.1 空间域去噪:三种基础滤波器的本质差异

空间域滤波,就是直接在像素的二维平面上做操作。我习惯把它们分成两类:线性滤波和非线性滤波。均值和高斯是线性,中值是非线性。别看它们简单,理解透了才能用好。

3.1.1 均值滤波

均值滤波的原理太直观了——取邻域内所有像素的平均值替代中心像素。公式很简单:

// 3x3均值滤波核
kernel = 1/9 * [
  [1, 1, 1],
  [1, 1, 1],
  [1, 1, 1]
]

但它的代价也很明显:所有边缘都被模糊了。我在一个手机项目里试过用均值滤波做预处理,结果拍出来的文字边缘像水彩画一样糊。为什么?因为均值滤波把边缘两侧的像素差异直接抹平了。

滤波器 噪声抑制能力 边缘保留能力 计算复杂度
均值滤波 中等(均匀噪声) 差 低
高斯滤波 较好(高斯噪声) 较差 低
中值滤波 优秀(椒盐噪声) 较好 中等

3.1.2 高斯滤波

高斯滤波比均值滤波聪明一点——它给中心附近的像素更高的权重,离中心越远权重越低。核函数长这样:

// 5x5高斯核,σ=1.0
kernel = [
  [1,  4,  7,  4, 1],
  [4, 16, 26, 16, 4],
  [7, 26, 41, 26, 7],
  [4, 16, 26, 16, 4],
  [1,  4,  7,  4, 1]
] / 273

高斯滤波对高斯噪声效果不错,但边缘保留依然不行。你想想看,它本质上还是加权平均,边缘处的像素差异照样被拉平了。我一般只在做下采样前的抗混叠滤波时才用高斯,纯去噪场景很少单独用。

3.1.3 中值滤波

中值滤波是个异类——它取邻域内所有像素的中位数,而不是平均值。这个特性让它对椒盐噪声(也就是那种黑白点噪声)有奇效。

我的经验:在RAW域中,如果传感器有坏点或者ADC读出异常导致孤立噪点,中值滤波是首选。但要注意——中值滤波会抹掉细线、尖角这类高频细节。我曾经在拍星轨的项目里用过中值滤波,结果星星的亮度峰值被削平了,后期怎么拉都拉不回来。

3.2 边缘保留滤波:双边滤波与NLM

基础滤波器的通病是“一刀切”——不管是不是边缘,统统模糊。那有没有办法只平滑平坦区域、保留边缘呢?有,这就是边缘保留滤波。

3.2.1 双边滤波

双边滤波的核心思想是:不仅考虑空间距离,还考虑像素值差异。两个权重相乘:

// 双边滤波权重公式
w(i,j) = exp(-(x²+y²)/(2σ_s²)) * exp(-(I(i)-I(j))²/(2σ_r²))
// 前一项:空间高斯权重
// 后一项:值域高斯权重

说白了,就是颜色相近的像素才参与平均。边缘两侧的像素值差异大,值域权重接近0,所以边缘不会被模糊。

我在一个夜景项目中用过双边滤波做RAW域去噪。效果确实好——暗部噪声被压得很干净,但高亮边缘依然锐利。不过有个坑:σ_r(值域标准差)很难调。调小了去噪不够,调大了边缘开始糊。我当时的做法是:先统计整帧图像的噪声标准差,把σ_r设为噪声标准差的2-3倍。

注意:双边滤波的计算量很大。如果核大小是5x5,每个像素要计算25次指数函数。在移动端ISP里,我一般只用3x3或5x5的双边滤波,再大就扛不住了。

3.2.2 NLM(非局部均值)

NLM的思路更激进——它不只在邻域内找相似像素,而是在整张图像里找相似的图像块。你想想看,一张图像里有很多重复纹理(比如草地、砖墙),这些块之间的噪声是独立的,平均之后噪声就消掉了。

// NLM核心思想(伪代码)
for each pixel p:
    weight_sum = 0
    result = 0
    for each search window pixel q:
        // 计算p周围块和q周围块的相似度
        d = block_distance(patch_p, patch_q)
        w = exp(-d / h)
        result += w * I(q)
        weight_sum += w
    I_denoised(p) = result / weight_sum

NLM的去噪效果确实好,但代价也大——计算量是双边滤波的几十倍。我在做安防摄像头项目时用过NLM,因为安防场景对实时性要求没那么高(15fps就行),而且暗光下噪声确实重。但手机ISP里基本不用,功耗扛不住。

3.3 RAW域去噪的挑战与策略

RAW域去噪和RGB域去噪不一样,有几个特有的坑。我踩过不少,今天一并说出来。

3.3.1 挑战一:Bayer模式下的去噪

RAW数据是Bayer格式的——每个像素只记录R、G、B中的一个通道。如果直接对Bayer数据做空间滤波,会引入颜色混叠。比如一个R像素的邻域里有G和B像素,直接平均就会产生假色。

我的策略:

  • 同通道滤波:只对相同颜色的像素做滤波。比如R像素只参考周围R像素,G像素只参考G像素。这样不会引入颜色串扰。
  • 先插值再去噪:先把Bayer数据插值成RGB,再做去噪。但这样噪声会被插值放大,效果不如在RAW域做。
  • 自适应核:根据当前像素的颜色,动态调整滤波核的形状。比如G像素多,就用菱形核;R/B像素少,就用十字核。

3.3.2 挑战二:噪声的非均匀性

RAW域的噪声不是均匀的——暗区噪声大,亮区噪声小。这是因为光子散粒噪声服从泊松分布,信号越强噪声越大(但信噪比也越高)。如果对整个图像用同一个滤波强度,暗区去不干净,亮区又被过度平滑。

我的策略:

  • 噪声水平估计:先根据ISO、增益、曝光时间估计每个像素的噪声标准差。
  • 自适应滤波强度:滤波参数(比如双边滤波的σ_r)根据噪声水平动态调整。暗区用强滤波,亮区用弱滤波。
  • 多尺度分解:把图像分解成低频和高频,只对高频成分做去噪。低频成分保留不动。

3.3.3 挑战三:实时性与功耗

ISP是硬件流水线,每一帧的处理时间是有严格预算的。RAW域去噪通常只有几毫秒的时间窗口。双边滤波和NLM在软件上跑得欢,但硬件实现就难了。

我的策略:

  • 查表法:把指数函数、高斯权重预先算好存成查找表,运行时直接查表,省掉大量计算。
  • 降采样去噪:先在低分辨率上做去噪,再上采样回原分辨率。细节损失可控,但速度提升明显。
  • 分块处理:把图像分成小块,每块独立去噪。块与块之间做重叠处理,避免块效应。
总结一下我的调试经验:RAW域去噪没有银弹。均值滤波太粗糙,中值滤波适合坏点,双边滤波是性价比之选,NLM是效果天花板但代价高。实际项目中,我通常用双边滤波 + 噪声自适应 + 同通道处理的组合,效果和性能都能兼顾。
RAW域去噪知识体系 RAW域去噪 空间域去噪 边缘保留滤波 挑战与策略 均值滤波 高斯滤波 中值滤波 双边滤波(空间+值域) NLM(非局部均值) Bayer模式 噪声非均匀 实时性/功耗 调试建议 • 基础去噪:中值滤波处理坏点 → 双边滤波处理高斯噪声 • 参数调优:σ_r = 2~3倍噪声标准差,σ_s = 1.5~2.0 • 性能优化:查表法 + 降采样 + 分块处理 • 避坑:Bayer域必须同通道滤波,避免颜色混叠 • 效果验证:用MTF(调制传递函数)评估细节保留,用SNR评估去噪效果
一个小技巧:调试时别只看主观效果。我习惯同时看MTF曲线和SNR曲线。MTF下降超过10%说明细节损失太大,SNR提升低于3dB说明去噪力度不够。两个指标要平衡,不能偏废。