第5章 Python 数字图像处理(DIP) - 图像复原与重建10 - 空间滤波 - 统计排序滤波器 - 中值、最大值、最小值、中点、修正阿尔法均值滤波器

统计排序滤波器

中值、最大值、最小值、中点 滤波器

f ^ ( x , y ) = median { g ( r , c ) } (5.27) \hat{f}(x, y) = \text{median} \{g(r,c)\} \tag{5.27} f^(x,y)=median{g(r,c)}(5.27)
f ^ ( x , y ) ) = max { g ( r , c ) } (5.28) \hat{f}(x, y)) = \text{max} \{g(r,c)\} \tag{5.28} f^(x,y))=max{g(r,c)}(5.28)
f ^ ( x , y ) = min { g ( r , c ) } (5.29) \hat{f}(x, y) = \text{min} \{g(r,c)\} \tag{5.29} f^(x,y)=min{g(r,c)}(5.29)
f ^ ( x , y ) = 1 2 [ max { g ( r , c ) } + min { g ( r , c ) } ] (5.30) \hat{f}(x, y) = \frac{1}{2}\big[\text{max}\{g(r,c)\} + \text{min}\{g(r,c)\} \big] \tag{5.30} f^(x,y)=21[max{g(r,c)}+min{g(r,c)}](5.30)

中值滤波器应用广泛,因为与大小相同的线性平滑滤波器相比,它能有效地降低某些随机噪声,且模糊度要小得多。对于单极和双极冲激噪声,中值滤波器的效果更好,但多次使用中值滤波器会使用图像模糊。

最大值滤波器可用于找到图像中的最亮点,或用于消弱与明亮区域相信的暗色区域。此外由于胡椒噪声的值很低,因此可用这种滤波器来降低胡椒噪声

最小值滤波器用于找到图像中的最暗点,或用于削弱与暗色区域的明亮区域。此外,还可通过最小运算降低盐粒噪声

中点滤波器是统计排序滤波器与平均滤波器的结合。它最适合于处理随机分布的噪声,如高斯噪声或均匀噪声

修正阿尔法均值滤波器

f ^ ( x , y ) = 1 m n − d ∑ g ( r , c ) (5.31) \hat{f}(x, y) = \frac{1}{mn - d} \sum g(r,c) \tag{5.31} f^(x,y)=mnd1g(r,c)(5.31)

d的取值范围是从 0 到 m n − 1 0到mn - 1 0mn1。 当 d = 0 d=0 d=0时,简化为算术平均滤波器。当 d = m n − 1 d=mn-1 d=mn1,那么为中值滤波器。 d d d取其它值时,修正阿尔法滤波器适合于处理多种混合噪声,如高斯噪声和椒盐噪声。

使用时需要选取合适的 d d d值,才能得到比较好的结果,不同的值差别也很大。

# 中值、最大值、最小值、中点 滤波器
def median_filter(image, kernel):
    """
    median filter, math: $$\hat{f}(x, y) = \text{median} \{g(r,c)\}$$
    param: image:  input image for denoising
    param: kernel: input kernel, actually only use kernel shape, just want to keep the format as mean filter
    return: image after median filter
    """
    height, width = image.shape[:2]
    m, n = kernel.shape[:2]

    padding_h = int((m -1)/2)
    padding_w = int((n -1)/2)
    
    # 这样的填充方式,可以奇数核或者偶数核都能正确填充
    image_pad = np.pad(image, ((padding_h, m - 1 - padding_h), \
                                  (padding_w, n - 1 - padding_w)), mode="edge")
    
    image_result = np.zeros(image.shape)
    for i in range(height):
        for j in range(width):
            temp = image_pad[i:i + m, j:j + n]
            image_result[i, j] = np.median(temp)
    return image_result

def max_filter(image, kernel):
    """
    max filter, math: $$\hat{f}(x, y)) = \text{max} \{g(r,c)\}$$
    param: image:  input image for denoising
    param: kernel: input kernel, actually only use kernel shape, just want to keep the format as mean filter
    return: image after max filter
    """
    height, width = image.shape[:2]
    m, n = kernel.shape[:2]

    padding_h = int((m -1)/2)
    padding_w = int((n -1)/2)
    # 这样的填充方式,可以奇数核或者偶数核都能正确填充
    image_pad = np.pad(image, ((padding_h, m - 1 - padding_h), \
                                  (padding_w, n - 1 - padding_w)), mode="constant", constant_values=0)
    
    img_result = np.zeros(image.shape)
    for i in range(height):
        for j in range(width):
            temp = image_pad[i:i + m, j:j + n]
            img_result[i, j] = np.max(temp)
    return img_result

def min_filter(image, kernel):
    """
    min filter, math: $$\hat{f}(x, y) = \text{min} \{g(r,c)\}$$
    param: image:  input image for denoising
    param: kernel: input kernel, actually only use kernel shape, just want to keep the format as mean filter
    return: image after min filter
    """
    height, width = image.shape[:2]
    m, n = kernel.shape[:2]

    padding_h = int((m -1)/2)
    padding_w = int((n -1)/2)
    
    # 这样的填充方式,可以奇数核或者偶数核都能正确填充
    image_pad = np.pad(image, ((padding_h, m - 1 - padding_h), \
                                  (padding_w, n - 1 - padding_w)), mode="edge", )
    
    img_result = np.zeros(image.shape)
    for i in range(height):
        for j in range(width):
            temp = image_pad[i:i + m, j:j + n]
            img_result[i, j] = np.min(temp)
    return img_result

def middle_filter(image, kernel):
    """
    middle filter, math: $$\hat{f}(x, y) = \frac{1}{2}\big[\text{max}\{g(r,c)\} + \text{min}\{g(r,c)\} \big]$$
    param: image:  input image for denoising
    param: kernel: input kernel, actually only use kernel shape, just want to keep the format as mean filter
    return: image after middle filter
    """
    height, width = image.shape[:2]
    m, n = kernel.shape[:2]

    padding_h = int((m -1)/2)
    padding_w = int((n -1)/2)
    
    # 这样的填充方式,可以奇数核或者偶数核都能正确填充
    image_pad = np.pad(image, ((padding_h, m - 1 - padding_h), \
                                  (padding_w, n - 1 - padding_w)), mode="edge")
    
    img_result = np.zeros(image.shape)
    for i in range(height):
        for j in range(width):
            temp = image_pad[i:i + m, j:j + n]
            img_result[i, j] = int(temp.max()/2 + temp.min()/2)
    return img_result
# 中值、最大值、最小值、中点 滤波器处理胡椒噪声
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0508(a)(circuit-board-pepper-prob-pt1).tif', 0) #直接读为灰度图像

kernel = np.ones([3, 3])
img_median = median_filter(img_ori, kernel=kernel)
img_max = max_filter(img_ori, kernel=kernel)
img_min = min_filter(img_ori, kernel=kernel)
img_middle = middle_filter(img_ori, kernel=kernel)

plt.figure(figsize=(15, 10))

plt.subplot(231), plt.imshow(img_ori, 'gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(232), plt.imshow(img_median, 'gray'), plt.title('Median filter'), plt.xticks([]), plt.yticks([])
plt.subplot(233), plt.imshow(img_max, 'gray'), plt.title('Max filter'), plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.imshow(img_min, 'gray'), plt.title('Min filter'), plt.xticks([]), plt.yticks([])
plt.subplot(235), plt.imshow(img_middle, 'gray'), plt.title('Middle filter'), plt.xticks([]), plt.yticks([])
plt.tight_layout()
plt.show()

在这里插入图片描述

# 中值、最大值、最小值、中点 滤波器处理盐粒噪声
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0508(b)(circuit-board-salt-prob-pt1).tif', 0) #直接读为灰度图像

kernel = np.ones([3, 3])
img_median = median_filter(img_ori, kernel=kernel)
img_max = max_filter(img_ori, kernel=kernel)
img_min = min_filter(img_ori, kernel=kernel)
img_middle = middle_filter(img_ori, kernel=kernel)

plt.figure(figsize=(15, 10))

plt.subplot(231), plt.imshow(img_ori, 'gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(232), plt.imshow(img_median, 'gray'), plt.title('Median filter'), plt.xticks([]), plt.yticks([])
plt.subplot(233), plt.imshow(img_max, 'gray'), plt.title('Max filter'), plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.imshow(img_min, 'gray'), plt.title('Min filter'), plt.xticks([]), plt.yticks([])
plt.subplot(235), plt.imshow(img_middle, 'gray'), plt.title('Middle filter'), plt.xticks([]), plt.yticks([])
plt.tight_layout()
plt.show()

在这里插入图片描述

# 中值、最大值、最小值、中点 滤波器处理高斯噪声
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0507(b)(ckt-board-gauss-var-400).tif', 0) #直接读为灰度图像

kernel = np.ones([3, 3])
img_median = median_filter(img_ori, kernel=kernel)
img_max = max_filter(img_ori, kernel=kernel)
img_min = min_filter(img_ori, kernel=kernel)
img_middle = middle_filter(img_ori, kernel=kernel)

plt.figure(figsize=(15, 10))

plt.subplot(231), plt.imshow(img_ori, 'gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(232), plt.imshow(img_median, 'gray'), plt.title('Median filter'), plt.xticks([]), plt.yticks([])
plt.subplot(233), plt.imshow(img_max, 'gray'), plt.title('Max filter'), plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.imshow(img_min, 'gray'), plt.title('Min filter'), plt.xticks([]), plt.yticks([])
plt.subplot(235), plt.imshow(img_middle, 'gray'), plt.title('Middle filter'), plt.xticks([]), plt.yticks([])
plt.tight_layout()
plt.show()

在这里插入图片描述

# 多次中值滤波器处理椒盐噪声
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0507(a)(ckt-board-orig).tif', 0) #直接读为灰度图像

img_salt_pepper = add_salt_pepper(img_ori, ps=0.1, pp=0.1)

kernel = np.ones([3, 3])
img_median_1 = median_filter(img_salt_pepper, kernel=kernel)
img_median_2 = median_filter(img_median_1, kernel=kernel)
img_median_3 = median_filter(img_median_2, kernel=kernel)

plt.figure(figsize=(15, 10))
plt.subplot(231), plt.imshow(img_ori, 'gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(232), plt.imshow(img_salt_pepper, 'gray'), plt.title('With salt pepper 0.1'), plt.xticks([]), plt.yticks([])
plt.subplot(233), plt.imshow(img_median_1, 'gray'), plt.title('1 time Median filter'), plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.imshow(img_median_2, 'gray'), plt.title('2 times Median filter'), plt.xticks([]), plt.yticks([])
plt.subplot(235), plt.imshow(img_median_3, 'gray'), plt.title('3 times Median filter'), plt.xticks([]), plt.yticks([])
plt.tight_layout()
plt.show()

在这里插入图片描述

def modified_alpha_mean(image, kernel, d=0):
    """
    modified alpha filter, math: $$$$\hat{f}(x, y) = \frac{1}{mn - d} \sum g(r,c)$$
    param: image:  input image for denoising
    param: kernel: input kernel, actually only use kernel shape, just want to keep the format as mean filter
    param: d     : input int, which is from 0 to m * n
    return: image after modified alpha filter
    """
    height, width = image.shape[:2]
    m, n = kernel.shape[:2]

    padding_h = int((m -1)/2)
    padding_w = int((n -1)/2)
    
    # 这样的填充方式,可以奇数核或者偶数核都能正确填充
    image_pad = np.pad(image, ((padding_h, m - 1 - padding_h), \
                                  (padding_w, n - 1 - padding_w)), mode="edge")
    
    img_result = np.zeros(image.shape)
    for i in range(height):
        for j in range(width):
            temp = np.sum(image_pad[i:i + m, j:j + n] * 1)
            img_result[i, j] = temp / (m * n - d)
    return img_result
# 修正阿尔法滤波器处理高斯噪声
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0507(b)(ckt-board-gauss-var-400).tif', 0) #直接读为灰度图像

kernel = np.ones([3, 3])

img_median = median_filter(img_ori, kernel=kernel)
img_max = max_filter(img_ori, kernel=kernel)
img_min = min_filter(img_ori, kernel=kernel)
img_alpha_d_1 = modified_alpha_mean(img_ori, kernel, d=1)
img_alpha_d_05 = modified_alpha_mean(img_ori, kernel, d=0.5)

plt.figure(figsize=(15, 10))
plt.subplot(231), plt.imshow(img_ori, 'gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(232), plt.imshow(img_median, 'gray'), plt.title('Median filter'), plt.xticks([]), plt.yticks([])
plt.subplot(233), plt.imshow(img_max, 'gray'), plt.title('Max filter'), plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.imshow(img_min, 'gray'), plt.title('Min filter'), plt.xticks([]), plt.yticks([])
plt.subplot(235), plt.imshow(img_alpha_d_1, 'gray'), plt.title('Modified alpha d=1'), plt.xticks([]), plt.yticks([])
plt.subplot(236), plt.imshow(img_alpha_d_05, 'gray'), plt.title('Modified alpha d=0.5'), plt.xticks([]), plt.yticks([])
plt.tight_layout()
plt.show()

在这里插入图片描述

# 修正阿尔法滤波器处理高斯噪声+椒盐噪声
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0507(a)(ckt-board-orig).tif', 0) #直接读为灰度图像

img_uniform = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0512(a)(ckt-uniform-var-800).tif', 0) 
img_salt_pepper = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH05/Fig0512(b)(ckt-uniform-plus-saltpepr-prob-pt1).tif', 0) 

kernel = np.ones([5, 5])

img_geometric_mean = geometric_mean(img_salt_pepper, kernel=kernel)
img_dst = img_salt_pepper - img_geometric_mean
img_median = median_filter(img_salt_pepper, kernel=kernel)
img_modified_alpha = modified_alpha_mean(img_salt_pepper, kernel=kernel, d=1)

plt.figure(figsize=(15, 10))

plt.subplot(231), plt.imshow(img_ori, 'gray'), plt.title('Original'), plt.xticks([]),plt.yticks([])
plt.subplot(232), plt.imshow(img_uniform, 'gray'), plt.title('Uniform noise'), plt.xticks([]),plt.yticks([])
plt.subplot(233), plt.imshow(img_salt_pepper, 'gray'), plt.title('Uniform plus salt pepper'), plt.xticks([]),plt.yticks([])
plt.subplot(234), plt.imshow(img_dst, 'gray'), plt.title('Geometric mean'), plt.xticks([]),plt.yticks([])
plt.subplot(235), plt.imshow(img_median, 'gray'), plt.title('1 time Median filter'), plt.xticks([]),plt.yticks([])
plt.subplot(236), plt.imshow(img_modified_alpha, 'gray'), plt.title('Modified alpha mean d=6'), plt.xticks([]),plt.yticks([])
plt.tight_layout()
plt.show()

在这里插入图片描述

  • 0
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jasneik

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值