2. 噪声模型:高斯噪声、椒盐噪声、泊松噪声、乘性噪声的特性与数学模型

做图像处理的人,每天都要跟噪声打交道。我刚开始接触嵌入式图像系统时,总觉得噪声就是「画面不干净」,后来踩了不少坑才明白——不同噪声的脾气完全不同。你用一个均值滤波去处理椒盐噪声,效果可能还行;但要是拿它去对付高斯噪声,嗯,画面糊了噪声还在。

所以这一节,咱们把四种最常见的噪声模型掰开揉碎讲清楚。你搞懂了它们的数学模型,后面设计滤波器时才能「对症下药」。

2.1 高斯噪声——最「温柔」也最普遍的噪声

高斯噪声,说白了就是传感器在弱光环境下自己产生的热噪声。我做过一个安防摄像头的项目,晚上光线不足时,画面里那种密密麻麻的细小颗粒,十有八九就是高斯噪声。

数学模型:

高斯噪声的概率密度函数服从正态分布:

p(z) = (1 / (σ * √(2π))) * exp(-(z - μ)² / (2σ²))

其中:

  • z 是像素灰度值
  • μ 是均值(通常为0)
  • σ 是标准差,决定了噪声的强度

关键特性:

  • 每个像素点的噪声是独立同分布的
  • 噪声幅度集中在均值附近,越偏离概率越小
  • 在空域上表现为「全图均匀分布」的细小颗粒

我个人的习惯是,在嵌入式平台上用 Box-Muller 变换 来生成高斯噪声样本。为什么?因为它只需要均匀随机数发生器,而大多数MCU都自带硬件随机数模块。

// 嵌入式C代码:Box-Muller生成高斯噪声
float generate_gaussian_noise(float mean, float stddev) {
    float u1 = (float)rand() / RAND_MAX;
    float u2 = (float)rand() / RAND_MAX;
    float z = sqrt(-2.0f * log(u1)) * cos(2.0f * M_PI * u2);
    return mean + stddev * z;
}

避坑指南: 我曾经在STM32上直接用库函数rand()生成高斯噪声,结果发现噪声分布不对称。后来排查发现,rand()的周期太短,导致Box-Muller变换的输入序列相关性太强。建议用梅森旋转算法或硬件TRNG。

2.2 椒盐噪声——最「暴力」的脉冲干扰

椒盐噪声,你想想看,就像有人往你的图像上撒了一把盐和胡椒。它随机地把某些像素变成纯白(255)或纯黑(0)。

我在做工业视觉检测时遇到过这种情况——产线上的传感器偶尔受到电机启停的电磁干扰,图像上就会出现这种黑白点。说白了,椒盐噪声的本质是数据传输过程中的比特翻转

数学模型:

p(z) = 
    Pa,  z = 0    (盐噪声,黑色)
    Pb,  z = 255  (椒噪声,白色)
    1 - Pa - Pb,  z = 原始值

其中 Pa 和 Pb 分别是出现黑点和白点的概率,通常 Pa = Pb。

噪声密度 Pa = Pb 视觉效果
低密度 (0.01) 0.005 几乎看不出
中密度 (0.05) 0.025 明显可见黑白点
高密度 (0.2) 0.1 图像严重受损

注意: 椒盐噪声的密度不是 Pa+Pb,而是「被污染像素占总像素的比例」。比如密度0.05,意味着5%的像素被变成了0或255。

2.3 泊松噪声——与「光」有关的噪声

泊松噪声,也叫散粒噪声。它跟光的量子特性有关——光子到达传感器的过程本身就是一个随机过程。

我记得做天文图像处理时,暗弱星体的图像就受泊松噪声影响很大。为什么?因为星光太弱,到达传感器的光子数量本身就很少,统计涨落就变得明显了。

数学模型:

泊松噪声的特点是:噪声的方差等于信号的强度

P(X = k) = (λ^k * e^(-λ)) / k!

其中 λ 是像素的真实灰度值(光子数),k 是实际观测到的灰度值。

核心特性:

  • 噪声强度与信号强度成正比——亮区噪声大,暗区噪声小
  • 不是加性噪声,而是信号依赖型噪声
  • 在低光照条件下尤为明显

在嵌入式实现中,我建议用 Anscombe 变换 把泊松噪声转换成近似的高斯噪声,然后再用高斯滤波器处理。这样能复用已有的滤波算法库。

// Anscombe变换:将泊松噪声转为高斯噪声
// 输入:原始像素值 x
// 输出:变换后的值 y
float anscombe_transform(float x) {
    return 2.0f * sqrt(x + 3.0f / 8.0f);
}

2.4 乘性噪声——最「难缠」的噪声

乘性噪声,说白了就是噪声跟信号「绑在一起」了。它不像高斯噪声那样独立于信号,而是随着信号强度变化而变化。

我在做超声成像项目时遇到过这种噪声——探头与皮肤接触不良,导致回波信号出现斑点噪声(speckle noise),这就是典型的乘性噪声。

数学模型:

g(x,y) = f(x,y) * n(x,y)

其中 f 是原始图像,n 是乘性噪声,g 是观测到的图像。

更常见的表达方式是取对数后变成加性噪声:

log(g) = log(f) + log(n)

实战技巧: 我处理乘性噪声的惯用套路是——先取对数,再用高斯滤波器,最后取指数还原。这个「对数域滤波」的思路在嵌入式平台上实现起来也不复杂,就是多了一次查表运算。

2.5 四种噪声的对比与选择

好了,四种噪声都讲完了。你可能会问:我该怎么判断图像里是哪种噪声?

我个人有个简单的判断方法:

  • 看直方图:高斯噪声的直方图是钟形曲线;椒盐噪声会在0和255处出现两个尖峰
  • 看局部方差:泊松噪声的方差随亮度变化;乘性噪声的方差与局部均值成正比
  • 看空间分布:高斯噪声全图均匀;椒盐噪声是离散的孤立点
噪声类型 数学模型 与信号关系 典型来源 嵌入式处理难度
高斯噪声 加性 独立 传感器热噪声
椒盐噪声 脉冲 独立 传输干扰
泊松噪声 信号依赖 方差=信号 光子统计涨落
乘性噪声 乘积 成正比 超声/雷达

最后提醒一句: 实际图像中的噪声往往是多种噪声的混合体。比如CMOS传感器在低光照下,既有高斯热噪声,又有泊松散粒噪声。这时候就别想着用一个模型去完美拟合了——抓住主要矛盾,选对主导噪声类型,你的滤波器就成功了一半