在图像处理或信号处理中,模拟不同类型的噪声是常见的需求。以下是使用 Python(主要基于 NumPy 和 OpenCV)模拟 八种常见噪声类型 的完整代码,包括:

  1. 均匀噪声(Uniform Noise)
  2. 高斯噪声(Gaussian Noise)
  3. 椒盐噪声(Salt-and-Pepper Noise)
  4. 泊松噪声(Poisson Noise)
  5. 瑞利噪声(Rayleigh Noise)
  6. 伽马噪声(Gamma Noise)
  7. 斑点噪声(Speckle Noise)
  8. 脉冲噪声(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()

📌 输出说明

序号噪声类型特点描述
1Original原图(无噪声)
2Uniform均匀分布噪声,图像整体亮度微变
3Gaussian高斯白噪声,图像随机抖动
4Salt & Pepper黑白点噪声
5Poisson强度相关噪声,低亮度区域影响小
6Rayleigh偏右的分布,更亮的背景噪声偏多
7Gamma长尾分布,产生较多亮度突变
8Speckle乘性噪声,常见于雷达图像
9Impulse随机强烈脉冲型噪声