图像复原(只存在噪声的复原)之空间滤波
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
在上一节中我们讲到了图像的退化模型以及图像复原之空间滤波中的均值滤波,这一节我们继续图像复原之空间滤波中的统计排序滤波器。
统计排序滤波器是空间滤波器,其响应应基于滤波器所围邻域中的像素值的顺序,排序结果决定了滤波器的响应。
1. 统计排序滤波
1.1 中值滤波器
图像处理中最著名的统计排序滤波器是中值滤波器。令:
S
x
y
表示中心为
(
x
,
y
)
、大小为
m
×
n
的邻域
S_{xy}表示中心为(x,y)、大小为m\times n的邻域
Sxy表示中心为(x,y)、大小为m×n的邻域则复原的图像 :
f
^
(
x
,
y
)
=
m
e
d
i
a
n
(
r
,
c
)
∈
S
x
y
{
g
(
r
,
c
)
}
\hat{f}(x,y)=\underset{(r,c)\in S_{xy}}{median}\{g(r,c)\}
f^(x,y)=(r,c)∈Sxymedian{g(r,c)}用白话来说就是使用
(
x
,
y
)
(x,y)
(x,y) 的
m
×
n
m\times n
m×n 邻域的像素值的中值作为复原图像的像素值
。
中值滤波器实现图像复原的代码如下:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def MedianFilter(src, kernel):
"""
图像复原-中值滤波器
:param src: 需要复原的原图像
:param kernel: 卷积核大小
:return: 返回复原图像
"""
img = cv.medianBlur(src, kernel)
return img
if __name__ == '__main__':
img = cv.imread('Image/Fig0705.tif', 0)
img1 = MedianFilter(img, 3)
img2 = MedianFilter(img1, 3)
img3 = MedianFilter(img2, 3)
# 图像显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.size'] = 20
plt.figure(figsize=(20, 20))
titleList = ["Original Image", "Median Filter 3*3", "Median Filter 3*3", "Median Filter 3*3"]
imageList = [img, img1, img2, img3]
for i in range(4):
plt.subplot(2, 2, i + 1), plt.title(titleList[i]), plt.axis('off')
plt.imshow(imageList[i], vmin=0, vmax=255, cmap='gray')
plt.tight_layout()
plt.savefig("Image/tmp.png")
plt.show()
结果分析:
上图原图像中既有胡椒噪声,又有盐粒噪声:
图2是使用3*3大小的中值滤波器对原图进行处理后的效果
图3是使用3*3大小的中值滤波器对图2进行处理后的效果
图4是使用3*3大小的中值滤波器对图3进行处理后的效果
从上图可以看出,中值滤波对噪声的处理效果非常好,且不会产生太严重的模糊效果
1.2 最大值滤波器和最小值滤波器
最大最小值滤波器,顾名思义,用邻域的像素值的最大或最小值作为复原图像的像素值
,其公式如下:令:
S
x
y
表示中心为
(
x
,
y
)
、大小为
m
×
n
的邻域
S_{xy}表示中心为(x,y)、大小为m\times n的邻域
Sxy表示中心为(x,y)、大小为m×n的邻域则复原的图像 :
最小值滤波器
:
f
^
(
x
,
y
)
=
m
i
n
(
r
,
c
)
∈
S
x
y
{
g
(
r
,
c
)
}
最大值滤波器
:
f
^
(
x
,
y
)
=
m
a
x
(
r
,
c
)
∈
S
x
y
{
g
(
r
,
c
)
}
最小值滤波器: \quad \hat{f}(x,y)=\underset{(r,c)\in S_{xy}}{min}\{g(r,c)\} \\最大值滤波器: \quad\hat{f}(x,y)=\underset{(r,c)\in S_{xy}}{max}\{g(r,c)\}
最小值滤波器:f^(x,y)=(r,c)∈Sxymin{g(r,c)}最大值滤波器:f^(x,y)=(r,c)∈Sxymax{g(r,c)}
最大值滤波器和最小值滤波器实现图像复原的代码如下:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def MinFilter(src, size):
"""
图像复原-最小值滤波器
:param src: 需要复原的原图像
:param size: 卷积核大小
:return: 返回复原图像
"""
# 使用腐蚀操作实现最小值滤波
kernel = np.ones((size, size), np.uint8)
img = cv.erode(src, kernel)
return img
def MaxFilter(src, size):
"""
图像复原-最大值滤波器
:param src: 需要复原的原图像
:param size: 卷积核大小
:return: 返回复原图像
"""
# 使用膨胀操作实现最小值滤波
kernel = np.ones((size, size), np.uint8)
img = cv.dilate(src, kernel)
return img
if __name__ == '__main__':
img01 = cv.imread('Image/Fig0703.tif', 0)
img02 = cv.imread('Image/Fig0704.tif', 0)
img1 = MaxFilter(img01, 3)
img2 = MaxFilter(img01, 9)
img3 = MinFilter(img02, 3)
img4 = MinFilter(img02, 9)
# 图像显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.size'] = 20
plt.figure(figsize=(30, 20))
titleList = ["Original Image", "Max Filter 3*3", "Max Filter 9*9", "Original Image", "Min Filter 3*3", "Min Filter 9*9"]
imageList = [img01, img1, img2, img02, img3, img4]
for i in range(6):
plt.subplot(2, 3, i + 1), plt.title(titleList[i]), plt.axis('off')
plt.imshow(imageList[i], vmin=0, vmax=255, cmap='gray')
plt.tight_layout()
plt.savefig("Image/tmp.png")
plt.show()
结果分析:
上图中第一行的原图像是胡椒噪声图像,第二行的原图像是盐粒噪声图像,我们对胡椒噪声图像使用最小值滤波器进行降噪处理,对盐粒噪声图像使用最大值滤波器进行降噪处理,从上图中我们看可以看出:
最小值滤波器
:可以用于找到图像中的最暗点
。可以用于消弱与暗色区域相邻的明亮区域
。可以用于降低盐粒噪声
。
最大值滤波器
:可以用于找到图像中的最亮点
。可以用于消弱与明亮区域相邻的暗色区域
。可以用于降低胡椒噪声
。
1.3 中点滤波器
中点滤波器,取邻域内像素值的最大和最小值的中点(最大值与最小值的平均值)作为复原图像的像素值
,其公式如下:令:
S
x
y
表示中心为
(
x
,
y
)
、大小为
m
×
n
的邻域
S_{xy}表示中心为(x,y)、大小为m\times n的邻域
Sxy表示中心为(x,y)、大小为m×n的邻域则复原的图像 :
中点滤波器
:
f
^
(
x
,
y
)
=
1
2
(
m
i
n
(
r
,
c
)
∈
S
x
y
{
g
(
r
,
c
)
}
+
m
a
x
(
r
,
c
)
∈
S
x
y
{
g
(
r
,
c
)
}
)
中点滤波器: \quad \hat{f}(x,y)=\frac{1}{2}{(\underset{(r,c)\in S_{xy}}{min}\{g(r,c)\}+\underset{(r,c)\in S_{xy}}{max}\{g(r,c)\})}
中点滤波器:f^(x,y)=21((r,c)∈Sxymin{g(r,c)}+(r,c)∈Sxymax{g(r,c)})
中点滤波器实现图像复原的代码如下:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def MiddleFilter(src, kernel):
"""
图像复原-中点滤波器
:param src: 需要复原的原图像
:param kernel: 卷积核大小
:return: 返回复原图像
"""
output = np.zeros_like(src)
# 进行中点计算时,边缘像素会无法处理,因此需要对边缘像素进行填充
pad_size = kernel // 2
padded_image = np.pad(src, pad_size, mode='reflect')
# 遍历图像的每个像素,进行中点值的计算
rows, cols = src.shape
for i in range(rows):
for j in range(cols):
# 获取当前窗口
region = padded_image[i:i + kernel, j:j + kernel]
# 计算窗口内的最大值和最小值
min_val = np.min(region)
max_val = np.max(region)
# 计算中点(最小值和最大值的平均值)
output[i, j] = int(min_val/2) + int(max_val/2)
return output
if __name__ == '__main__':
img = cv.imread('Image/Fig0702.tif', 0)
img1 = MiddleFilter(img, 3)
img2 = MiddleFilter(img, 9)
# 图像显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.size'] = 20
plt.figure(figsize=(30, 10))
titleList = ["Original Image", "Middle Filter 3*3", "Middle Filter 9*9"]
imageList = [img, img1, img2]
for i in range(3):
plt.subplot(1, 3, i + 1), plt.title(titleList[i]), plt.axis('off')
plt.imshow(imageList[i], vmin=0, vmax=255, cmap='gray')
plt.tight_layout()
plt.savefig("Image/tmp.png")
plt.show()
结果分析:
各位自己看吧,这里就不分析了
1.4 修正阿尔法均值滤波器
令: S x y 表示中心为 ( x , y ) 、大小为 m × n 的邻域 S_{xy}表示中心为(x,y)、大小为m\times n的邻域 Sxy表示中心为(x,y)、大小为m×n的邻域假设我们要在领域 S x y S_{xy} Sxy 内删除 g ( x , y ) g(x,y) g(x,y) 的 d d d 个最低灰度值和 d d d 个最高灰度值。令 g R ( r , c ) g_R(r,c) gR(r,c) 表示 S x y S_{xy} Sxy 中剩下的 m n − 2 d mn-2d mn−2d 个像素。通过平均这些剩余像素所形成的滤波器,称为修正阿尔法均值滤波器,其形式为 : f ^ ( x , y ) = 1 m n − 2 d ∑ ( r , c ) ∈ S x y g R ( r , c ) \hat{f}(x,y)=\frac {1} {mn-2d}\sum_{(r,c)\in S_{xy}}g_R(r,c) f^(x,y)=mn−2d1(r,c)∈Sxy∑gR(r,c)
修正阿尔法均值滤波器实现图像复原的代码如下:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def ModifiedAlphaMeanFilter(src, kernel, d):
"""
图像复原-修正阿尔法滤波器
:param src: 需要复原的原图像
:param kernel: 卷积核大小
:return: 返回复原图像
"""
output = np.zeros_like(src)
# 进行中点计算时,边缘像素会无法处理,因此需要对边缘像素进行填充
pad_size = kernel // 2
padded_image = np.pad(src, pad_size, mode='reflect')
# 遍历图像的每个像素,进行中点值的计算
rows, cols = src.shape
for i in range(rows):
for j in range(cols):
# 获取当前窗口
region = padded_image[i:i + kernel, j:j + kernel]
# 进行排序操作,以便删除d个最低灰度值和d个最高灰度值
region_sort = np.sort(region.flatten())
# 对剩余的像素值进行求和
sumAlpha = np.sum(region_sort[d:kernel*kernel-d-1])
# 计算修正阿尔法平均值
output[i, j] = sumAlpha / (kernel*kernel-2*d)
return output
if __name__ == '__main__':
img = cv.imread('Image/Fig0705.tif', 0)
img1 = ModifiedAlphaMeanFilter(img, 5, 1)
img2 = ModifiedAlphaMeanFilter(img, 5, 5)
img3 = ModifiedAlphaMeanFilter(img, 5, 10)
# 图像显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['font.size'] = 20
plt.figure(figsize=(20, 20))
titleList = ["Original Image", "5*5 d=1", "5*5 d=5", "5*5 d=10"]
imageList = [img, img1, img2, img3]
for i in range(4):
plt.subplot(2, 2, i + 1), plt.title(titleList[i]), plt.axis('off')
plt.imshow(imageList[i], vmin=0, vmax=255, cmap='gray')
plt.tight_layout()
plt.savefig("Image/tmp.png")
plt.show()
结果分析:
从上图来看,其降噪效果还算可以。
好好思考一下可以发现:
当 d 特别小时,修正阿尔法滤波器等同于算术平均滤波器,当d特别大时,修正阿尔法滤波器等同于中值滤波器,因此修正阿尔法滤波器介于算术平均滤波器和中值滤波器中间
。
总结
滤波器类型 | 去噪效果 | 适用噪声类型 | 优点 | 缺点 |
---|---|---|---|---|
中值滤波器 | 对椒盐噪声效果好 | 主要是椒盐噪声 | 对椒盐噪声有很好的去除效果,能保留边缘细节 | 对高斯噪声去噪效果不如均值滤波,计算量较大 |
最小值滤波器 | 对椒盐噪声“椒”部分有效 | 主要是椒盐噪声 | 对椒盐噪声的“椒”部分有效,去亮点噪声 | 图像亮度降低,细节丢失 |
最大值滤波器 | 对椒盐噪声“盐”部分有效 | 主要是椒盐噪声 | 对椒盐噪声的“盐”部分有效,去暗点噪声 | 图像亮度增加,细节丢失 |
中点滤波器 | 对椒盐噪声效果好 | 主要是椒盐噪声 | 去除椒盐噪声同时保留更多细节 | 对高斯噪声去噪效果较差,可能导致平滑 |
修正阿尔法均值滤波器 | 对椒盐噪声和高斯噪声有效 | 高斯噪声,椒盐噪声 | 能够平衡去噪和细节保留,适用于多种噪声类型 | 计算复杂,需合理调整 α \alpha α 参数 |