本节中我们将介绍诸如 max
和 min
之类的非线性滤波器,与中值滤波器一样,它们根据滑动窗口中像素的顺序统计信息决定像素值。在本节中,我们将学习如何应用 max
、min
和 mode
滤波器去除图像中的噪声。
min
滤波可以将核中央像素替换为邻域滑动窗口中最暗的像素(即最小值像素),该滤波器通常可用于去除图像中的盐噪声 (salt noise
)。
(1) 读取输入图像,并在图像中添加随机盐噪声。由于我们不需要添加胡椒噪声,因此将相应的参数 pepper
设置为 False
:
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
orig = Image.open('2.png')
im = add_noise(orig, prop_noise = 0.2, pepper=False)
(2) 使用 PIL
函数指定 ImageFilter.MinFilter
参数应用 min
滤波器,并初始化不同核尺寸的 min
滤波器,绘制输出图像:
plt.figure(figsize=(20,10))
plt.subplot(1,4,1)
plot_image(im, 'Input noisy image')
i = 2
for sz in [3,7,11]:
im1 = im.filter(ImageFilter.MinFilter(size=sz))
plt.subplot(1,4,i), plot_image(im1, 'Output (Filter size=' + str(sz) + ')')
i += 1
plt.tight_layout()
plt.show()
从上图可以看出,min
滤波器能够从图像中删除盐噪声。
max
滤波器使用最明亮的像素(即最大值的像素)替换核中央像素,该滤波器通常可用于从图像中删除椒噪声。
(1) 添加随机椒噪声到原始输入图像。由于我们不需要添加盐噪声,因此将相应的参数 salt
设置为 False
:
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
orig = Image.open('2.png')
im = add_noise(orig, prop_noise = 0.3, salt=False)
(2) 使用 PIL
函数指定 ImageFilter.Maxfilter
参数应用 max
滤波器,并初始化不同核尺寸的 max
滤波器,绘制输出图像:
plt.figure(figsize=(20,10))
plt.subplot(1,4,1)
plot_image(im, 'Input noisy image')
i = 2
for sz in [3,7,11]:
im1 = im.filter(ImageFilter.MaxFilter(size=sz))
plt.subplot(1,4,i), plot_image(im1, 'Output (Filter size=' + str(sz) + ')')
i += 1
plt.tight_layout()
plt.show()
从上图可以看出,max
滤波器能够从图像中删除胡椒噪声。
mode
滤波器通过使用从特定窗口大小中选择最频繁出现的像素值(像素邻居的模式值)替换中心像素来从图像中去除噪声,mode
滤波器在去除噪声的同时可以保持图像中的清晰边缘。
(1) 读取输入图像,在图像中添加 10%
的椒盐噪声:
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
orig = Image.open('2.png')
im = add_noise(orig, prop_noise = 0.1)
(2) 使用 PIL
函数指定 ImageFilter.ModeFilter
参数应用 mode
滤波器,并初始化不同核尺寸的 mode
滤波器,绘制输出图像:
plt.figure(figsize=(20,10))
plt.subplot(1,4,1)
plot_image(im, 'Input noisy image')
i = 2
for sz in [3,7,11]:
im1 = im.filter(ImageFilter.ModeFilter(size=sz))
plt.subplot(1,4,i), plot_image(im1, 'Output (Filter size=' + str(sz) + ')')
i += 1
plt.tight_layout()
plt.show()
从上图可以看出,mode
滤波器能够在保持输出图中的水平和垂直边缘锐利的同时消除输入图像中的椒盐噪声。
在本节中,我们将逐步将高斯、中值、mode
和 max
滤波器应用于输入图像(对每个滤波器进行四次迭代,每次从输入图像开始,在上一次迭代获得的滤波输出上应用滤波器),对比输出结果。
绘制每个滤波器每次迭代时的图像,以查看每次迭代时的输出结果。第 i i i 行对应于第 2 ∗ i 2*i 2∗i 次应用滤波器获得的输出:
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('2.png')
plt.figure(figsize=(10,15))
plt.subplots_adjust(0,0,1,0.95,0.05,0.05)
im1 = im.copy()
sz = 5
for i in range(8):
im1 = im1.filter(ImageFilter.GaussianBlur(radius=sz))
if i % 2 == 0:
plt.subplot(4,4,4*i//2+1), plot_image(im1, 'Gaussian Blur' if i == 0 else None, 10)
im1 = im.copy()
for i in range(8):
im1 = im1.filter(ImageFilter.MedianFilter(size=sz))
if i % 2 == 0:
plt.subplot(4,4,4*i//2+2), plot_image(im1, 'Median' if i == 0 else None, 10)
im1 = im.copy()
for i in range(8):
im1 = im1.filter(ImageFilter.ModeFilter(size=sz))
if i % 2 == 0:
plt.subplot(4,4,4*i//2+3), plot_image(im1, 'Mode' if i == 0 else None, 10)
im1 = im.copy()
for i in range(8):
im1 = im1.filter(ImageFilter.MaxFilter(size=sz))
if i % 2 == 0:
plt.subplot(4,4,4*i//2+4), plot_image(im1, 'Max' if i == 0 else None, 10)
plt.show()
以及非线性滤波器中值滤波器,
在上图中可以看出,中值滤波器可以产生最佳结果,它不会像高斯模糊那样过分模糊图像,而不会像 mode
滤波器扭曲/像素化图像。mode
滤波器可以更好地保留锐利的边缘,但代价是引入了伪影/像素化。
中值滤波和 mode
滤波器几乎在最后一次迭代时停止改变输出图像,而高斯模糊始终具有模糊效果(最终,它将产生具有均匀颜色/强度的图像)。
噪声是干扰图像正常分析和处理的一个重要因素,一幅图像在实际应用中可能存在各种各样的噪声,噪声可能在拍摄中产生,也可能在传输过程中产生。在本节中,我们学习了几种常见的非线性滤波器包括 min
、max
和 mode
滤波器,并将这些滤波器用于图像降噪,从而提高图像质量,便于后续进行处理与分析,并且对比了不同滤波器在图像去噪方面的不同效果。
Python图像处理【1】图像与视频处理基础
Python图像处理【2】探索Python图像处理库
Python图像处理【3】Python图像处理库应用
Python图像处理【4】图像线性变换
Python图像处理【5】图像扭曲/逆扭曲
Python图像处理【6】通过哈希查找重复和类似的图像
Python图像处理【7】采样、卷积与离散傅里叶变换
Python图像处理【8】使用低通滤波器模糊图像
Python图像处理【9】使用高通滤波器执行边缘检测
Python图像处理【10】基于离散余弦变换的图像压缩
Python图像处理【11】利用反卷积执行图像去模糊
Python图像处理【12】基于小波变换执行图像去噪
Python图像处理【13】使用PIL执行图像降噪