数字图像处理(四)空域低通滤波器

低通滤波器在我们的日常生活中很有用,图像模糊,图像去噪以及图像识别都需要低通滤波器的处理。低通滤波即滤除图像中的高频部分(变化很快的部分),留下低频部分(变化不明显得到部分)。滤波器的实现有空域和频域两种:空域滤波器是直接在空间图像上进行操作,图像矩阵和滤波器算子进行卷积得到滤波后的输出;频域滤波器是将图像经过傅里叶变换到频域上再与滤波器做乘法得到输出。

这一篇文章主要介绍空域低通滤波器及其实现。

常用的空域滤波器有平均滤波,中值滤波和高斯滤波。这里主要介绍中值滤波和高斯滤波。

中值滤波

中值滤波,顾名思义,是一种基于统计方法的滤波器。具体的实现方法为:对于一个n*n的中值滤波器,输出图像的像素点(x,y)的像素值等于输入图像中以(x,y)为中心的n*n大小的图像区域中所有像素值的中位数。

滤波器的大小可以根据不同的需要进行选取。

中值滤波器得到的效果如下:

依次分别为原图像,3*3中值滤波,5*5中值滤波,7*7中值滤波。

原始图片
3*3中值
5*5中值
7*7中值

原图中有很多分布不规律的噪声,其中有一部分是盐噪声,但大部分是一些突然的脉冲噪声。在使用3*3的中值滤波时,盐噪声已经很好的去除掉了,但脉冲噪声依然很明显。使用5*5的中值时,脉冲噪声情况有了很大的改善。7*7的滤波器几乎完全去除了噪声,但图像的模糊也很严重。

高斯滤波

高斯滤波是一些图形处理软件中经常使用的模糊方法,由二维正态分布函数:\(p(x,y)=\frac1{2\pi\sigma^2}e^{-\frac{x^2+y^2}{2\sigma^2}}\)产生,具体做法如下:

  • 若要产生n*n的高斯滤波器,将该n阶仿真的中心置为(0,0),生成矩阵中其他位置的坐标;
  • 将该n*n矩阵中的每个位置的坐标带入二维正态分布函数得到每个位置的数值;
  • 以矩阵左上角置1为标准等比缩放矩阵中数值大小;
  • 对矩阵进行取整得到的结果就是n*n的高斯滤波器

生成高斯滤波器的函数如下

1
2
3
4
5
6
7
8
9
10
11
12
import numpy as np
sigma=1.5 #高斯滤波器的参数
def f(x,y): #定义二维正态分布函数
return 1/(math.pi*sigma**2)*math.exp(-(x**2+y**2)/(2*sigma**2))

def gauss(n): #生成n*n的高斯滤波器
mid=n//2
filt=np.zeros((n,n))
for i in range(n):
for j in range(n):
filt[i][j]=f(i-mid,j-mid)/f(-mid,-mid)
return filt.astype(np.uint8)

3*3,5*5,7*7的高斯滤波器如下:

其在二维坐标系中的图像如下:

在得到了高斯滤波器的算子之后,使用该算子与输入图像进行卷积即可得到高斯滤波器滤波后的结果。

其效果如下:

依次为原图,3*3,5*5,7*7高斯滤波的结果:

原始图片
3*3高斯
5*5高斯
7*7高斯

高斯模糊对于图像中的盐噪声去除效果较好,但对于脉冲噪声的去除显得颇为吃力,7*7的高斯滤波依然无法滤除掉图像中的脉冲噪声。另一方面,高斯模糊相较于终止模糊图像的信息保留较为完全,细节保留较多。

附录

参考文献

[1]数字图像处理[M]:第三版/(美)拉斐尔·C·冈萨雷斯(Rafael C.Gonzalez),(美)理查德·E·伍兹(Richard E. Woods)著;阮秋琦等译,—北京:电子工业出版社,2017.5

[2]Brook_icv.图像处理基础(4):高斯滤波器详解[G/OL].博客园: 2017-02-16 [2020-03-23].https://www.cnblogs.com/wangguchangqing/p/6407717.html#autoid-4-1-0

[3]予你心安.Numpy求均值、中位数、众数的方法[G/OL].博客园: 2018-11-04 [2020-03-23].https://www.cnblogs.com/lijinze-tsinghua/p/9905882.html

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import cv2 as cv
import numpy as np
import math
img=cv.imread("test1.pgm")

sigma=1.5 #高斯滤波器的参数
def f(x,y): #定义二维正态分布函数
return 1/(math.pi*sigma**2)*math.exp(-(x**2+y**2)/(2*sigma**2))

def gauss(n): #生成n*n的高斯滤波器
mid=n//2
filt=np.zeros((n,n))
for i in range(n):
for j in range(n):
filt[i][j]=f(i-mid,j-mid)/f(-mid,-mid)
return filt.astype(np.uint8)

def gauss_filter(img,n): #对图像img进行n*n卷积块的高斯滤波
filt=gauss(n)
con=1/np.sum(filt)
shape=img.shape
mid=n//2
temp=np.zeros((shape[0]+n-1,shape[1]+n-1)) #对边缘进行补0操作
for i in range(shape[0]):
for j in range(shape[1]):
temp[i+mid][j+mid]=img[i][j][0]
result=np.zeros((shape[0],shape[1]))
for i in range(shape[0]):
for j in range(shape[1]):
tmp=0
for k in range(n):
for l in range(n):
tmp+=filt[k][l]*temp[i+k][j+l]
result[i][j]=con*tmp
return result.astype(np.uint8)

def center_filter(img, n): #使用n*n的中值滤波器对图像进行低通滤波
mid=n//2
shape=img.shape
temp=np.zeros((shape[0]+n-1,shape[1]+n-1))
for i in range(shape[0]):
for j in range(shape[1]):
temp[i+mid][j+mid]=img[i][j][0]
result=np.zeros((shape[0],shape[1]))
tmp=np.zeros(n*n)
for i in range (shape[0]):
for j in range(shape[1]):
for k in range(n):
for l in range(n):
tmp[k*n+l]=temp[i+k][j+l]
result[i][j]=np.median(tmp)
return result.astype(np.uint8)

filename=["test1.pgm","test2.tif"]
size=[3,5,7]
for i in filename:
img=cv.imread(i)
for j in size:
cv.imwrite(i+'gauss-'+str(j)+'.bmp',gauss_filter(img,j))
cv.imwrite(i+'center-'+str(j)+'.bmp',center_filter(img,j))