图像处理基础(2):自适应中值滤波器(基于OpenCV实现)

本文深入探讨自适应中值滤波器,介绍其原理和OpenCV实现,通过对比分析展示其在椒盐噪声过滤上的优势,尤其是对于高概率噪声的处理效果。
摘要由CSDN通过智能技术生成

本文主要介绍了自适应的中值滤波器,并基于OpenCV实现了该滤波器,并且将自适应的中值滤波器和常规的中值滤波器对不同概率的椒盐噪声的过滤效果进行了对比。最后,对中值滤波器的优缺点了进行了总结。

空间滤波器

一个空间滤波器包括两个部分:

  • 一个邻域,滤波器进行操作的像素集合,通常是一个矩形区域
  • 对邻域中像素进行的操作

一个滤波器就是在选定的邻域像素上执行预先定义好的操作产生新的像素,并用新的像素替换掉原来像素形成新的图像。
通常,也可以将滤波器称之为核(kernel),模板(template)或者窗口(window)

根据预定义的操作,可以将滤波器分为:

  • 线性滤波器
  • 非线性滤波器

而根据滤波器最终对图像造成的影响,可以将滤波器分为:

  • 平滑滤波器 ,通常用于模糊图像或者去除图像中的噪声
  • 锐化滤波器,突出图像中的边缘细节部分

中值滤波器 Median Filter

中值滤波器是一种常用的非线性滤波器,其基本原理是选择待处理像素的一个邻域中各像素值的中值来代替待处理的像素,其主要功能是像素的灰度值与周围像素比较接近,从而消除孤立的噪声点,所以中值滤波器能够很好的消除椒盐噪声。不仅如此,中值滤波器在消除噪声的同时,还能有效的保护图像的边界信息,不会对图像造成很大的模糊(相比于均值滤波器)。

中值滤波器的效果受滤波窗口尺寸的影响较大,在消除噪声和保护图像的细节存在着矛盾:滤波窗口较小,则能很好的保护图像中的某些细节,但对噪声的过滤效果就不是很好;反之,窗口尺寸较大有较好的噪声过滤效果,但是会对图像造成一定的模糊。另外,根据中值滤波器原理,如果在滤波窗口内的噪声点的个数大于整个窗口内像素的个数,则中值滤波就不能很好的过滤掉噪声。

自适应中值滤波器 Adaptive Median Filter

上面提到常规的中值滤波器,在噪声的密度不是很大的情况下(根据经验,噪声的出现的概率小于0.2),效果不错。但是当概率出现的概率较高时,常规的中值滤波的效果就不是很好了。有一个选择就是增大滤波器的窗口大小,这虽然在一定程度上能解决上述的问题,但是会给图像造成较大的模糊。

常规的中值滤波器的窗口尺寸是固定大小不变的,就不能同时兼顾去噪和保护图像的细节。这时就要寻求一种改变,根据预先设定好的条件,在滤波的过程中,动态的改变滤波器的窗口尺寸大小,这就是自适应中值滤波器 Adaptive Median Filter。在滤波的过程中,自适应中值滤波器会根据预先设定好的条件,改变滤波窗口的尺寸大小,同时还会根据一定的条件判断当前像素是不是噪声,如果是则用邻域中值替换掉当前像素;不是,则不作改变。

自适应中值滤波器有三个目的:

  • 滤除椒盐噪声
  • 平滑其他非脉冲噪声
  • 尽可能的保护图像中细节信息,避免图像边缘的细化或者粗化。

自使用中值滤波算法描述

自适应滤波器不但能够滤除概率较大的椒盐噪声,而且能够更好的保护图像的细节,这是常规的中值滤波器做不到的。自适应的中值滤波器也需要一个矩形的窗口 Sxy ,和常规中值滤波器不同的是这个窗口的大小会在滤波处理的过程中进行改变(增大)。需要注意的是,滤波器的输出是一个像素值,该值用来替换点 (x,y) 处的像素值,点 (x,y) 是滤波窗口的中心位置。

在描述自适应中值滤波器时需要用到如下的符号:

  • Zmin=Sxy 中的最小灰度值
  • Zmax=Sxy 中的最大灰度值
  • Zmed=Sxy 中的灰度值的中值
以下是使用Python实现自适应中值滤波去除椒盐噪声的示例代码: ```python import numpy as np from scipy.signal import medfilt2d def adaptive_median_filter(image, kernel_size=3, max_kernel_size=7): """ 自适应中值滤波 :param image: 输入图像 :param kernel_size: 初始核大小 :param max_kernel_size: 最大核大小 :return: 滤波后的图像 """ height, width = image.shape[:2] filtered_image = np.zeros((height, width), dtype=np.uint8) for i in range(height): for j in range(width): # 当前像素点的领域范围 kernel_half_size = kernel_size // 2 kernel_range = range(-kernel_half_size, kernel_half_size + 1) kernel_pixels = [] for k in kernel_range: for l in kernel_range: # 越界处理 if i + k < 0 or i + k >= height or j + l < 0 or j + l >= width: continue kernel_pixels.append(image[i + k, j + l]) # 中值滤波 kernel_pixels.sort() median_value = kernel_pixels[len(kernel_pixels) // 2] # 判断是否是椒盐噪声 if median_value == 0 or median_value == 255: # 滑动窗口扩大 kernel_size += 2 # 达到最大核大小时停止扩大 if kernel_size > max_kernel_size: filtered_image[i, j] = median_value else: continue else: # 中值滤波 filtered_image[i, j] = median_value return filtered_image # 测试 import cv2 # 读取图像 image = cv2.imread('lena.png', cv2.IMREAD_GRAYSCALE) # 添加椒盐噪声 noise_image = image.copy() noise_density = 0.05 noise_num = int(noise_density * image.shape[0] * image.shape[1]) for i in range(noise_num): x, y = np.random.randint(0, image.shape[0]), np.random.randint(0, image.shape[1]) noise_image[x, y] = 255 if np.random.rand() > 0.5 else 0 # 自适应中值滤波 filtered_image = adaptive_median_filter(noise_image) # 中值滤波 median_filtered_image = medfilt2d(noise_image, kernel_size=3) # 显示结果 cv2.imshow('Original image', image) cv2.imshow('Noisy image', noise_image) cv2.imshow('Filtered image', filtered_image) cv2.imshow('Median filtered image', median_filtered_image) cv2.waitKey(0) cv2.destroyAllWindows() ``` 注意:在实现过程中,当中值滤波结果为0或255时,需要将滑动窗口扩大,直到达到最大核大小时停止扩大。这个过程需要注意边界判断和核大小的变化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值