3. RAW域去噪:空间域去噪与边缘保留滤波
RAW域去噪,说白了就是传感器读出数据后、做任何彩色处理之前的第一道降噪工序。这个位置很特殊——噪声还没被插值、增益、颜色校正放大,信噪比最原始,也最好处理。我做了这么多年ISP调试,可以负责任地说: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 中值滤波
中值滤波是个异类——它取邻域内所有像素的中位数,而不是平均值。这个特性让它对椒盐噪声(也就是那种黑白点噪声)有奇效。
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倍。
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在软件上跑得欢,但硬件实现就难了。
我的策略:
- 查表法:把指数函数、高斯权重预先算好存成查找表,运行时直接查表,省掉大量计算。
- 降采样去噪:先在低分辨率上做去噪,再上采样回原分辨率。细节损失可控,但速度提升明显。
- 分块处理:把图像分成小块,每块独立去噪。块与块之间做重叠处理,避免块效应。