opencv-图像处理-3-添加噪声和滤波去噪

一、图像噪声的添加与理解

1.1 椒盐噪声的添加与特点

椒盐噪声是图像处理中常见的一种噪声,因其呈现出随机的黑白像素点,类似撒在图像上的盐和胡椒而得名。通过以下代码,我实现了向图像添加椒盐噪声的功能:

import cv2
import numpy as np
import matplotlib.pyplot as plt

def add_salt_pepper_noise(image, salt_vs_pepper=0.5, amount=0.01):
    """
    添加椒盐噪声到图像
    参数:
    image: 输入的图像(numpy数组)
    salt_vs_pepper: 椒盐比例,0.5表示盐和椒的数量相等
    amount: 噪声数量占总像素的比例
    返回:
    添加噪声后的图像
    """
    # 创建图像副本以避免修改原图
    noisy_image = np.copy(image)
    # 获取图像尺寸
    rows, cols = noisy_image.shape[:2]
    # 计算要添加的噪声像素总数
    num_salt = np.ceil(amount * rows * cols * salt_vs_pepper)
    num_pepper = np.ceil(amount * rows * cols * (1.0 - salt_vs_pepper))
    # 添加盐噪声(白色像素)
    coords = [np.random.randint(0, i - 1, int(num_salt)) for i in (rows, cols)]
    noisy_image[coords[0], coords[1]] = 255
    # 添加椒噪声(黑色像素)
    coords = [np.random.randint(0, i - 1, int(num_pepper)) for i in (rows, cols)]
    noisy_image[coords[0], coords[1]] = 0
    return noisy_image

# 读取图像
image = cv2.imread('lena.jpg', 0)  # 以灰度模式读取图像

# 检查图像是否成功读取
if image is None:
    print("无法读取图像,请检查文件路径")
else:
    # 添加椒盐噪声(2%的像素被添加噪声,盐椒比例1:1)
    noisy_image = add_salt_pepper_noise(image, salt_vs_pepper=0.5, amount=0.02)
    
    # 显示原图和添加噪声后的图像
    plt.figure(figsize=(8, 5))
    plt.subplot(121)
    plt.title('原始图像')
    plt.imshow(image, cmap='gray')
    plt.axis('off')
    
    plt.subplot(122)
    plt.title('添加椒盐噪声后的图像')
    plt.imshow(noisy_image, cmap='gray')
    plt.axis('off')
    
    plt.tight_layout()
    plt.show()
    
    # 保存添加噪声后的图像
    cv2.imwrite('qiaoyan_nosiy_lena.jpg', noisy_image)

实现原理

  • 首先计算需要添加的盐噪声(白色像素)和椒噪声(黑色像素)的数量
  • 使用np.random.randint随机生成噪声像素的位置
  • 将对应位置的像素值设为 255(盐噪声)或 0(椒噪声)

关键参数

  • salt_vs_pepper:控制盐噪声与椒噪声的比例,0.5 表示两者数量相等
  • amount:控制噪声强度,0.02 表示 2% 的像素会被添加噪声

1.2 高斯噪声的添加与特点

高斯噪声是另一种常见噪声,其像素值分布符合高斯分布,在实际场景中(如相机传感器噪声)较为常见。以下是添加高斯噪声的实现代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt

def add_gaussian_noise(image, mean=0, sigma=25):
    """
    添加高斯噪声到图像
    参数:
    image: 输入的图像(numpy数组)
    mean: 高斯分布的均值
    sigma: 高斯分布的标准差,控制噪声强度
    返回:
    添加噪声后的图像
    """
    # 创建与输入图像形状相同的高斯噪声
    gaussian = np.random.normal(mean, sigma, image.shape)
    # 将噪声添加到图像
    noisy_image = image + gaussian
    # 将像素值裁剪到0-255范围
    noisy_image = np.clip(noisy_image, 0, 255)
    # 转换回uint8类型
    noisy_image = noisy_image.astype(np.uint8)
    return noisy_image

# 读取图像
image = cv2.imread('lena.jpg', 0)  # 以灰度模式读取图像

# 检查图像是否成功读取
if image is None:
    print("无法读取图像,请检查文件路径")
else:
    # 添加高斯噪声(均值0,标准差30)
    noisy_image = add_gaussian_noise(image, mean=0, sigma=30)
    
    # 显示原图和添加噪声后的图像
    plt.figure(figsize=(10, 5))
    
    plt.subplot(121)
    plt.title('原始图像')
    plt.imshow(image, cmap='gray')
    plt.axis('off')
    
    plt.subplot(122)
    plt.title('添加高斯噪声后的图像')
    plt.imshow(noisy_image, cmap='gray')
    plt.axis('off')
    
    plt.tight_layout()
    plt.show()
    
    # 保存添加噪声后的图像
    cv2.imwrite('gaosi_nosiy_lena.jpg', noisy_image)

实现原理

  • 使用np.random.normal生成符合高斯分布的噪声矩阵
  • 将噪声矩阵与原始图像相加
  • 使用np.clip将像素值限制在 0-255 范围内
  • 转换回uint8类型以便显示和保存

关键参数

  • mean:高斯分布的均值,控制噪声的中心位置
  • sigma:标准差,控制噪声的强度和分布范围

二、图像滤波去噪实践

2.1 均值滤波:简单有效的线性滤波

均值滤波是最基础的线性滤波方法,通过计算像素邻域的平均值来平滑图像:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

# 1 图像读取
img = cv.imread('dogsp.jpeg')

# 2 均值滤波(5x5卷积核)
blur = cv.blur(img, (5, 5))

# 3 图像显示
plt.figure(figsize=(8, 5), dpi=100)
plt.subplot(121), plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB)), plt.title('原图')
plt.xticks([]), plt.yticks([])

plt.subplot(122), plt.imshow(cv.cvtColor(blur, cv.COLOR_BGR2RGB)), plt.title('均值滤波后结果')
plt.xticks([]), plt.yticks([])
plt.show()

实现原理

  • 使用cv.blur函数实现均值滤波
  • 卷积核大小(5, 5)表示使用 5x5 的窗口计算平均值

特点

  • 优点:算法简单,计算速度快
  • 缺点:会模糊图像细节,对椒盐噪声效果不佳

2.2 高斯滤波:保留边缘的平滑方法

高斯滤波利用高斯核进行加权平均,对高斯噪声有很好的抑制作用:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

# 1 图像读取
img = cv.imread('dogGauss.jpeg')

# 2 高斯滤波(3x3核,X方向标准差1)
blur = cv.GaussianBlur(img, (3, 3), 1)

# 3 图像显示
plt.figure(figsize=(8, 5), dpi=100)
plt.subplot(121), plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB)), plt.title('原图')
plt.xticks([]), plt.yticks([])

plt.subplot(122), plt.imshow(cv.cvtColor(blur, cv.COLOR_BGR2RGB)), plt.title('高斯滤波后结果')
plt.xticks([]), plt.yticks([])
plt.show()

实现原理

  • cv.GaussianBlur使用高斯核进行卷积
  • 核大小(3, 3),X 方向标准差为 1,Y 方向标准差默认与 X 相同

特点

  • 对高斯噪声效果显著
  • 相比均值滤波,能更好地保留图像边缘
  • 高斯核的权重分布使得中心像素影响更大

2.3 中值滤波:椒盐噪声的克星

中值滤波是一种非线性滤波方法,特别适合去除椒盐噪声:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

# 1 图像读取
img = cv.imread('dogsp.jpeg')

# 2 中值滤波(5x5窗口)
blur = cv.medianBlur(img, 5)

# 3 图像展示
plt.figure(figsize=(10, 8), dpi=100)
plt.subplot(121), plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB)), plt.title('原图')
plt.xticks([]), plt.yticks([])

plt.subplot(122), plt.imshow(cv.cvtColor(blur, cv.COLOR_BGR2RGB)), plt.title('中值滤波后结果')
plt.xticks([]), plt.yticks([])
plt.show()

实现原理

  • cv.medianBlur将窗口内的像素值排序后取中值
  • 5x5 窗口表示每次取 25 个像素的中值作为中心像素值

特点

  • 对椒盐噪声有极佳的去除效果
  • 能有效保护图像边缘
  • 非线性操作使其在处理极端像素值时更有效

三、学习总结与实践心得

3.1 噪声与滤波方法的匹配

通过实践,我总结出不同噪声与滤波方法的匹配关系:

  • 椒盐噪声:中值滤波效果最佳,因为它能有效去除极端像素值而不模糊边缘
  • 高斯噪声:高斯滤波最为合适,因为其原理与噪声分布匹配

3.2 滤波参数的影响

  1. 核大小

    • 较大的核会产生更强的平滑效果,但会丢失更多细节
    • 建议从 3x3 开始尝试,根据效果逐步调整
  2. 标准差(高斯滤波):

    • 标准差越大,高斯核越宽,平滑效果越强
    • 通常设为 5-30,根据噪声强度调整
  3. 噪声比例(添加噪声时):

    • 小比例 (0.01-0.05) 适用于模拟轻微噪声
    • 大比例 (0.1 以上) 用于测试算法鲁棒性

3.3 实践中的注意事项

  1. 图像读取与显示

    • OpenCV 以 BGR 模式读取图像,matplotlib 使用 RGB,需注意转换
    • 始终检查图像是否成功读取,避免空指针错误
  2. 数据类型转换

    • 添加噪声时需注意保持图像数据类型一致
    • 浮点型图像在显示前需转换为 uint8

3.4总结

  1. 图像噪声

    • 椒盐噪声:图像中随机出现的白点或者黑点
    • 高斯噪声:噪声的概率密度分布是正态分布
  2. 图像平滑

    • 均值滤波:算法简单,计算速度快,在去噪的同时去除了很多细节部分,将图像变得模糊

      cv.blur()

    • 高斯滤波: 去除高斯噪声

      cv.GaussianBlur()

    • 中值滤波: 去除椒盐噪声

      cv.medianBlur()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值