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

145 阅读2分钟

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

前言

移动均值或方形滤波器是所有滤波器中最简单的,它用以像素为中心的正方形中的像素值的平均值替换像素中心值。我们可以使用以下公式定义通用线性滤波器,方形滤波器是线性滤波器的一种特殊情况:

(2m+1)×(2m+1)(2m+1)\times(2m+1) 线性滤波器:

gij=k=mml=mmwklfi+k,j+lg_{ij}=\sum ^m _{k=-m} \sum ^m _{l=-m} wkl \cdot f_{i+k,j+l}

m=1m=1 时表示 3×33\times 3 滤波器,在方形滤波器中 wkl=1(2m+1)2w_{kl}=\frac 1 {(2m+1)^2}。将以上滤波器展开,可得:

gij=w1,1fi1,j1+w1,0fi1,j+w1,1fi1,j+1+w0,1fi,j1+w0,0fi,j+w0,1fi,j+1+w1,1fi+1,j1+w1,0fi+1,j+w1,1fi+1,j+1g_{ij}=w_{-1,-1}f_{i-1,j-1}+w_{-1,0}f_{i-1,j}+w_{-1,1}f_{i-1,j+1}+w_{0,-1}f_{i,j-1}+w_{0,0}f_{i,j}+w_{0,1}f_{i,j+1}+w_{1,-1}f_{i+1,j-1}+w_{1,0}f_{i+1,j}+w_{1,1}f_{i+1,j+1}

在本节中,我们将使用 PILfilter() 函数将方形模糊滤波器应用于带有噪声的输入 RGB 图像,并观察不同噪声水平的平滑度。

去除椒盐噪声

(1) 首先代码导入所需库:

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

(2) 定义函数 plot_image() 使用 matlplotlib.pyplot 模块的 imshow() 函数显示图像如下:

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

(3) 定义函数 add_noise() 在图像中添加椒盐(脉冲)噪声。除了输入图像外,该函数还可以接受三个参数,其中 prop_noise 参数用于定义输入像素的噪声比例,参数 saltpepper 用于控制图像应用盐噪声(白像素)还是椒噪声(黑像素),令函数更加通用,默认情况下,同时使用两种类型的噪声像素:

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

(4) 读取输入图像。对于不同的噪声级别/比例,在输入图像中添加脉冲噪声,然后使用 image.filter() 方法应用模糊滤波器以平滑带有噪声的图像,绘制每种情况下获得的输出图像。

如前所述,模糊滤波器通过将每个像素设置为方形核窗口中像素的平均值来模糊图像,从而在每个方向上延伸半径像素。支持任意大小的浮点类型半径,默认使用 3x3` 方形模糊滤波器。

orig = Image.open('1.png')
i = 1
plt.figure(figsize=(12,35))

for prop_noise in np.linspace(0.05,0.3,6):
    # choose random locations inside image
    im = add_noise(orig, prop_noise)
    plt.subplot(6,2,i), plot_image(im, 'Original Image with ' + str(int(100*prop_noise)) + '% added noise')
    im1 = im.filter(ImageFilter.BLUR)
    plt.subplot(6,2,i+1), plot_image(im1, 'Blurred Image')
    i += 2

plt.show()

Figure_1.png

从以上图像可以看出,噪声比例越少,降噪和平滑效果越好(模糊程度越低)。