开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第34天,点击查看活动详情
前言
尽管移动平均滤波器 (moving average filter
) 的计算非常方便快捷,但它具有以下两个缺点,因此可能导致滤波图像中产生伪影:
- 它并不是各向同性的(即圆形对称的),沿着对角线比沿着行和列更平滑
- 权重间的变化非常突兀,而不是逐渐衰减至零,这会使平滑图像中的产生不连续性
为了克服这些缺点,可以计算近似于圆形而不是正方形邻域的平均值。为了实现此目的,我们通常可以使用高斯滤波器实现,高斯过滤器是唯一可分解的滤波器,可以将高斯滤波器分解表示为两个 1D
高斯滤波器的乘积,并且至少是近似圆形对称。从核中心到核边缘的权重会逐渐过渡衰减为零。以下表达式展示了高斯滤波器核,并给出了两个高斯核示例,核尺寸大小分别为 3x3
和 5x5
:
高斯滤波器核权重:
高斯滤波器如下:
高斯滤波器如下:
使用高斯模糊滤波器去除椒盐噪声
(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()
上图显示了代码的执行结果。可以看出,在使用高斯滤波器执行去噪任务时,半径越大,图像就会变得更加平滑,可以消除更多的噪声,但同时会使图像逐渐模糊,丢失细节。