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传感器在低光照下,既有高斯热噪声,又有泊松散粒噪声。这时候就别想着用一个模型去完美拟合了——抓住主要矛盾,选对主导噪声类型,你的滤波器就成功了一半。