使用高斯模糊滤波器去除椒盐噪声

1,253 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第34天,点击查看活动详情

前言

尽管移动平均滤波器 (moving average filter) 的计算非常方便快捷,但它具有以下两个缺点,因此可能导致滤波图像中产生伪影:

  • 它并不是各向同性的(即圆形对称的),沿着对角线比沿着行和列更平滑
  • 权重间的变化非常突兀,而不是逐渐衰减至零,这会使平滑图像中的产生不连续性

为了克服这些缺点,可以计算近似于圆形而不是正方形邻域的平均值。为了实现此目的,我们通常可以使用高斯滤波器实现,高斯过滤器是唯一可分解的滤波器,可以将高斯滤波器分解表示为两个 1D 高斯滤波器的乘积,并且至少是近似圆形对称。从核中心到核边缘的权重会逐渐过渡衰减为零。以下表达式展示了高斯滤波器核,并给出了两个高斯核示例,核尺寸大小分别为 3x35x5

高斯滤波器核权重:

wkl=12πσ2exp{(k2+l2)2σ2}w_{kl}=\frac 1 {2\pi \sigma ^2}exp\{\frac {-(k^2+l^2)} {2\sigma ^2}\}

3×33\times3 高斯滤波器如下:

116[121242121]\frac 1 {16} \left[ \begin{array}{ccc} 1 & 2 & 1\\ 2 & 4 & 2\\ 1 & 2 & 1\\ \end{array} \right]

5×55\times5 高斯滤波器如下:

1256[1464141624164624362464162416414641]\frac 1 {256} \left[ \begin{array}{ccc} 1 & 4 & 6 & 4 & 1\\ 4 & 16 & 24 & 16 & 4\\ 6 & 24 & 36 & 24 & 6\\ 4 & 16 & 24 & 16 & 4\\ 1 & 4 & 6 & 4 & 1\\ \end{array} \right]

使用高斯模糊滤波器去除椒盐噪声

(1) 首先读取输入 RGB 彩色图像,并添加固定比例 (20%) 的脉冲噪声:

import numpy as np
import matplotlib.pylab as plt
from PIL import Image, ImageFilter
from copy import deepcopy

def plot_image(image, title=None, sz=10):
    plt.imshow(image)
    plt.title(title, size=sz)
    plt.axis('off')

def add_noise(im, prop_noise, salt=True, pepper=True):
    im = deepcopy(im)
    n = int(im.width * im.height * prop_noise)
    x, y = np.random.randint(0, im.width, n), np.random.randint(0, im.height, n)
    for (x,y) in zip(x,y):
        im.putpixel((x, y),         # generate salt-and-pepper noise
        ((0,0,0) if np.random.rand() < 0.5 else (255,255,255)) if salt and pepper \
        else (255,255,255) if salt \
        else (0, 0, 0)) # if pepper
    return im

im = Image.open('1.png')
im = add_noise(im, prop_noise = 0.2)

(2) 使用 PIL 中的 image.filter() 方法,使用 imageFilter.gaussianblur 实例化具有不同的半径参数值(从 1 开始到 3 )的高斯滤波器,并绘制输出图像:

plt.figure(figsize=(20,15))
i = 1
for radius in np.linspace(1, 3, 12):
    im1 = im.filter(ImageFilter.GaussianBlur(radius))
    plt.subplot(3,4,i)
    plot_image(im1, 'radius = ' + str(round(radius,2)))
    i += 1
plt.suptitle('PIL Gaussian Blur with different Radius', size=13)
plt.show()

Figure_2.png

上图显示了代码的执行结果。可以看出,在使用高斯滤波器执行去噪任务时,半径越大,图像就会变得更加平滑,可以消除更多的噪声,但同时会使图像逐渐模糊,丢失细节。