在图像处理或信号处理中,模拟不同类型的噪声是常见的需求。以下是使用 Python(主要基于 NumPy 和 OpenCV)模拟 八种常见噪声类型 的完整代码,包括:
- 均匀噪声(Uniform Noise)
- 高斯噪声(Gaussian Noise)
- 椒盐噪声(Salt-and-Pepper Noise)
- 泊松噪声(Poisson Noise)
- 瑞利噪声(Rayleigh Noise)
- 伽马噪声(Gamma Noise)
- 斑点噪声(Speckle Noise)
- 脉冲噪声(Impulse Noise)
🔧 准备工作:导入库
import cv2
import numpy as np
import matplotlib.pyplot as plt
你可以先加载一张灰度图像,或生成一个测试图:
# 生成一个灰度测试图像
image = np.ones((256, 256), dtype=np.uint8) * 128 # 灰度图(中等亮度)
1. 均匀噪声(Uniform Noise)
def add_uniform_noise(image, low=-20, high=20):
noise = np.random.uniform(low, high, image.shape).astype(np.int16)
noisy_image = np.clip(image.astype(np.int16) + noise, 0, 255).astype(np.uint8)
return noisy_image
2. 高斯噪声(Gaussian Noise)
def add_gaussian_noise(image, mean=0, std=20):
noise = np.random.normal(mean, std, image.shape).astype(np.int16)
noisy_image = np.clip(image.astype(np.int16) + noise, 0, 255).astype(np.uint8)
return noisy_image
3. 椒盐噪声(Salt-and-Pepper Noise)
def add_salt_and_pepper_noise(image, amount=0.05, salt_vs_pepper=0.5):
noisy_image = image.copy()
num_pixels = image.size
num_salt = int(amount * num_pixels * salt_vs_pepper)
num_pepper = int(amount * num_pixels * (1.0 - salt_vs_pepper))
# Salt
coords = [np.random.randint(0, i, num_salt) for i in image.shape]
noisy_image[tuple(coords)] = 255
# Pepper
coords = [np.random.randint(0, i, num_pepper) for i in image.shape]
noisy_image[tuple(coords)] = 0
return noisy_image
4. 泊松噪声(Poisson Noise)
def add_poisson_noise(image):
noise = np.random.poisson(image.astype(np.uint8)).astype(np.uint8)
return np.clip(noise, 0, 255)
5. 瑞利噪声(Rayleigh Noise)
def add_rayleigh_noise(image, scale=30):
noise = np.random.rayleigh(scale, image.shape).astype(np.int16)
noisy_image = np.clip(image.astype(np.int16) + noise, 0, 255).astype(np.uint8)
return noisy_image
6. 伽马噪声(Gamma Noise)
def add_gamma_noise(image, shape=2.0, scale=20.0):
noise = np.random.gamma(shape, scale, image.shape).astype(np.int16)
noisy_image = np.clip(image.astype(np.int16) + noise, 0, 255).astype(np.uint8)
return noisy_image
7. 斑点噪声(Speckle Noise)
def add_speckle_noise(image):
noise = np.random.randn(*image.shape)
noisy_image = image + image * noise
return np.clip(noisy_image, 0, 255).astype(np.uint8)
8. 脉冲噪声(Impulse Noise,通常与椒盐噪声类似)
def add_impulse_noise(image, probability=0.01):
noisy_image = image.copy()
rand_matrix = np.random.rand(*image.shape)
noisy_image[rand_matrix < (probability / 2)] = 0 # Impulse black
noisy_image[rand_matrix > 1 - (probability / 2)] = 255 # Impulse white
return noisy_image
📷 显示效果(以高斯噪声为例)
noisy = add_gaussian_noise(image)
plt.subplot(1, 2, 1), plt.imshow(image, cmap='gray'), plt.title("Original")
plt.subplot(1, 2, 2), plt.imshow(noisy, cmap='gray'), plt.title("Gaussian Noise")
plt.show()
以下是一个完整的 Python 脚本,可以一键将八种常见噪声添加到灰度图像,并以 3×3 网格形式显示原图及其不同噪声效果:
✅ 一键测试所有噪声效果的脚本
import cv2
import numpy as np
import matplotlib.pyplot as plt
# ==== 1. 创建一张灰度测试图 ====
image = np.ones((256, 256), dtype=np.uint8) * 128 # 中灰图像
# ==== 2. 定义八种噪声函数 ====
def add_uniform_noise(image, low=-20, high=20):
noise = np.random.uniform(low, high, image.shape).astype(np.int16)
return np.clip(image.astype(np.int16) + noise, 0, 255).astype(np.uint8)
def add_gaussian_noise(image, mean=0, std=20):
noise = np.random.normal(mean, std, image.shape).astype(np.int16)
return np.clip(image.astype(np.int16) + noise, 0, 255).astype(np.uint8)
def add_salt_and_pepper_noise(image, amount=0.05, salt_vs_pepper=0.5):
noisy_image = image.copy()
num_salt = int(amount * image.size * salt_vs_pepper)
num_pepper = int(amount * image.size * (1.0 - salt_vs_pepper))
coords = [np.random.randint(0, i, num_salt) for i in image.shape]
noisy_image[tuple(coords)] = 255
coords = [np.random.randint(0, i, num_pepper) for i in image.shape]
noisy_image[tuple(coords)] = 0
return noisy_image
def add_poisson_noise(image):
vals = len(np.unique(image))
vals = 2 ** np.ceil(np.log2(vals))
noisy = np.random.poisson(image * vals / 255.0) * (255.0 / vals)
return np.clip(noisy, 0, 255).astype(np.uint8)
def add_rayleigh_noise(image, scale=30):
noise = np.random.rayleigh(scale, image.shape).astype(np.int16)
return np.clip(image.astype(np.int16) + noise, 0, 255).astype(np.uint8)
def add_gamma_noise(image, shape=2.0, scale=20.0):
noise = np.random.gamma(shape, scale, image.shape).astype(np.int16)
return np.clip(image.astype(np.int16) + noise, 0, 255).astype(np.uint8)
def add_speckle_noise(image):
noise = np.random.randn(*image.shape)
noisy = image + image * noise
return np.clip(noisy, 0, 255).astype(np.uint8)
def add_impulse_noise(image, probability=0.01):
noisy = image.copy()
rand = np.random.rand(*image.shape)
noisy[rand < probability / 2] = 0
noisy[rand > 1 - probability / 2] = 255
return noisy
# ==== 3. 生成所有带噪图像 ====
images = {
'Original': image,
'Uniform': add_uniform_noise(image),
'Gaussian': add_gaussian_noise(image),
'Salt & Pepper': add_salt_and_pepper_noise(image),
'Poisson': add_poisson_noise(image),
'Rayleigh': add_rayleigh_noise(image),
'Gamma': add_gamma_noise(image),
'Speckle': add_speckle_noise(image),
'Impulse': add_impulse_noise(image)
}
# ==== 4. 显示九宫格图像 ====
plt.figure(figsize=(12, 10))
for idx, (title, img) in enumerate(images.items()):
plt.subplot(3, 3, idx + 1)
plt.imshow(img, cmap='gray', vmin=0, vmax=255)
plt.title(title)
plt.axis('off')
plt.tight_layout()
plt.show()
📌 输出说明
序号 | 噪声类型 | 特点描述 |
---|---|---|
1 | Original | 原图(无噪声) |
2 | Uniform | 均匀分布噪声,图像整体亮度微变 |
3 | Gaussian | 高斯白噪声,图像随机抖动 |
4 | Salt & Pepper | 黑白点噪声 |
5 | Poisson | 强度相关噪声,低亮度区域影响小 |
6 | Rayleigh | 偏右的分布,更亮的背景噪声偏多 |
7 | Gamma | 长尾分布,产生较多亮度突变 |
8 | Speckle | 乘性噪声,常见于雷达图像 |
9 | Impulse | 随机强烈脉冲型噪声 |
发表回复