3  空域平滑滤波

空域平滑滤波是计算机视觉和图像处理中的基础技术,用于减少图像中的噪声、平滑图像细节,同时保留主要结构信息。本章节将详细介绍三种常见的空域平滑滤波方法:均值滤波、高斯滤波和中值滤波。我们将从基本概念出发,深入探讨它们的数学原理、算法实现、应用场景以及优缺点比较,旨在为研究生提供全面的理论和实践指导。

3.1 空域滤波的基础知识

空域滤波是指直接在图像的像素空间(即空域)上对像素值进行操作的技术。平滑滤波的目标是通过对像素及其邻域的加权或统计操作,降低图像中的噪声(如高斯噪声、椒盐噪声等),同时尽量保留图像的边缘和结构信息。空域滤波通常基于卷积操作或统计方法,主要包括线性滤波(如均值滤波和高斯滤波)和非线性滤波(如中值滤波)。

空域滤波通常通过卷积操作实现。卷积是将一个卷积核(或模板)与图像进行滑动窗口运算,计算输出像素值。对二维于图像 (I(x, y)) 和二维卷积核 (K(m, n)),二维卷积定义为:

[ O(x, y) = {m=-k}^{k} {n=-k}^{k} I(x+m, y+n) K(m, n) ]

其中,(O(x, y)) 是输出图像的像素值,(k) 是滤波核的半径(例如:(3) 核的 (k=1),5\times 5k=2

<img src="./chapter3/tu3-5.gif"  alt="卷积过程" >
<br>
<center style="font-size:16px">图3-2-1 二维卷积过程 </center>

图3-2-1展示了一个二维卷积过程,从图中可以看出,卷积后的图像变小了,因为以原图边界处像素点为中心时,会有一部分权重没有对应像素,因此,若是想要卷积结果与原图保持同大小,我们需要在图像的边界补齐,对于3\times 3卷积核要补1“圈”,对于5\times 5 卷积核要补2“圈”。最常见的方法是补0值,这种方法称作Zero Padding。

卷积核的大小和权重决定了滤波的效果,设置不同的卷积核可以实现多种视觉任务,如图像去噪、图像模糊、边缘检测等等。

3.2 均值滤波

均值滤波(Mean Filtering)是一种简单的线性滤波方法,通过取像素及其邻域的平均值来平滑图像。它假设噪声是随机的,通过平均化可以削弱噪声的影响。均值滤波的滤波核通常是一个归一化的均匀权重矩阵,例如 3x3 核为:

[ K = \begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix}

]

例3.5 对高斯噪声图像采用3\times 3的均值滤波,代码如下,效果如图3-2-2所示。

import numpy as np
import cv2
import matplotlib.pyplot as plt

image = cv2.imread('./imgs/tu3001.png', cv2.IMREAD_COLOR)
image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)

#生成高斯噪声图像
noisy_image = image + np.random.normal(0, 0.1 * 255, image.shape)
noisy_image = np.clip(noisy_image, 0, 255).astype(np.uint8)

#利用OpenCV提供的blur()函数实现均值滤波操作
filter_image = cv2.blur(noisy_image, (3,3))

plt.rcParams['font.sans-serif'] = ['SimHei'] #支持中文显示
plt.subplot(1,3,1)  #显示1行3列子图第1个子图
plt.axis('off')     #关闭子图坐标轴
plt.title('原图')   #子图标题
plt.imshow(image)   #显示图像
plt.subplot(1,3,2)  #显示1行3列子图第2个子图
plt.axis('off')     #关闭子图坐标轴
plt.title('噪声图像')   #子图标题
plt.imshow(noisy_image)   #显示图像
plt.subplot(1,3,3)  #显示1行3列子图第3个子图
plt.axis('off')     #关闭子图坐标轴
plt.title('均值滤波图')  #子图标题
plt.imshow(filter_image)   #显示图像
plt.show()          #显示创建的所有图形/图像
<img src="./chapter3/tu3-6.png" width = 1200 alt="均值滤波" >
<br>
<center style="font-size:16px">图3-2-2 均值滤波</center>

均值滤波的优点在于: - 实现简单,计算效率高; - 对高斯噪声有较好的平滑效果。

缺点是: - 均值滤波对所有像素一视同仁,会导致边缘模糊。 - 对椒盐噪声的抑制效果较差。 - 滤波核越大,平滑效果越强,但图像细节损失越多

3.3 高斯滤波

高斯滤波(Gaussian filter)包含多种类型,包括低通、带通和高通等。我们通常在图像处理中提到的高斯滤波,指的是高斯模糊(Gaussian Blur),是一种高斯低通滤波,过滤掉图像高频成分(图像细节部分),保留图像低频成分(图像平滑区域),因此对图像进行“高斯模糊”后,图像会变得模糊。

与均值滤波不同,高斯滤波根据像素与中心像素的距离分配权重,距离越近的像素权重越高。这种方法能够更好地保留图像边缘,同时平滑噪声。高斯模糊对于抑制高斯噪声(服从高斯分布的噪声)非常有效。

高斯滤波核由二维高斯函数生成(均值\mu通常设为0):

[ G(x, y) = e^{-} ]

其中,() 是高斯分布的标准差,控制平滑程度;卷积核中心为坐标原点,(x,y)是相对于模板中心的坐标。按照二维高斯分布生成后,需要归一化以确保权重之和为 1(避免图像偏亮或偏暗)。例如,均方差为\sigma=1.53\times 3 的高斯卷积模板如下: [ \begin{bmatrix} 0.014 & 0.028 & 0.014 \\ 0.028 & 0.057 & 0.028 \\ 0.014 & 0.028 & 0.014 \end{bmatrix}

]

例3.6 对高斯噪声图像采用5\times 5的高斯滤波,代码如下,效果如图3-2-3所示。

import numpy as np
import cv2
import matplotlib.pyplot as plt

image = cv2.imread('./imgs/tu3001.png', cv2.IMREAD_COLOR)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

#生成高斯噪声图像
noisy_image = image + np.random.normal(0, 0.1 * 255, image.shape)
noisy_image = np.clip(noisy_image, 0, 255).astype(np.uint8)

#利用OpenCV提供的GaussianBlur()函数实施高斯滤波操作
filter_image = cv2.GaussianBlur(noisy_image, (5,5), 1)  

plt.rcParams['font.sans-serif'] = ['SimHei'] #支持中文显示
plt.subplot(1,3,1)  #显示1行3列子图第1个子图
plt.axis('off')     #关闭子图坐标轴
plt.title('原图')   #子图标题
plt.imshow(image)   #显示图像
plt.subplot(1,3,2)  #显示1行3列子图第2个子图
plt.axis('off')     #关闭子图坐标轴
plt.title('噪声图像')   #子图标题
plt.imshow(noisy_image)   #显示图像
plt.subplot(1,3,3)  #显示1行3列子图第3个子图
plt.axis('off')     #关闭子图坐标轴
plt.title('高斯滤波图')  #子图标题
plt.imshow(filter_image)   #显示图像
plt.show()          #显示创建的所有图形/图像
<img src="./chapter3/tu3-7.png" width=1200 alt="高斯滤波" >
<br>
<center style="font-size:16px">图3-2-3 高斯滤波去噪</center>

该例中采用OpenCV提供的GaussianBlur函数实现高斯滤波,它的原型为:

cv2.GaussianBlur(src, ksize, sigmaX[, dst[, borderType[, anchor]]])

主要参数如下: - src:输入图像,即需要进行高斯模糊处理的原始图像。 - ksize:高斯核的大小,必须是一个奇数,且可以有两个、三个或五个元素。例如,(3, 3)、(5, 5)、(3, 5, 5)等。核的大小决定了模糊的程度,核越大,模糊效果越明显。 - sigmaX:高斯核的X方向标准差。这个参数可以根据需要进行调整,以控制模糊的程度。sigmaX的值越大,模糊效果越明显。 - dst:输出图像,即经过高斯模糊处理后的图像。这个参数可以省略,如果省略,函数将返回一个新的图像对象。 - borderType:像素外插法,用于处理图像边界的像素。默认值为cv2.BORDER_DEFAULT。这个参数可以根据需要进行调整,以满足特定的图像处理需求。 - anchor:锚点,即高斯核的中心点坐标。默认值为(-1, -1),表示核的中心点在核的中心位置。这个参数可以根据需要进行调整,以改变核的中心点位置。

高斯滤波的优点是: - 根据距离加权,能更好保留边缘信息。 - 对高斯噪声的平滑效果优于均值滤波。 - 通过调整 (),可以灵活控制平滑程度。

高斯滤波的缺点是: - 计算复杂度高于均值滤波。 - 对椒盐噪声的抑制效果仍然有限。

3.4 中值滤波

中值滤波(Median Filtering)是一种非线性滤波方法,通过取邻域像素值的中值替换中心像素值。与线性滤波不同,中值滤波不依赖于加权平均,而是基于统计排序,能够有效去除椒盐噪声,同时保留边缘信息。

中值滤波的计算公式为:

[ O(x, y) = { I(i, j) (i, j) S } ]

其中,(S) 是滤波核覆盖的邻域,() 表示取中值。

例3.8 采用中值滤波技术对椒盐噪声图像去噪代码如下,去噪效果如图3-2-4所示。

import numpy as np
import cv2
import matplotlib.pyplot as plt

image = cv2.imread('./imgs/tu3001.png', cv2.IMREAD_COLOR)
image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
#生成椒盐噪声图像
salt_pepper_ratio = 0.1 #控制产生椒盐噪声像素点的比例
h, w = image.shape[:2] # 获取图片的高和宽
number_salt_pepper = int(salt_pepper_ratio * h * w) #生成椒盐点总数量

noisy_image = np.copy(image)   
for i in range(number_salt_pepper):    
    x = np.random.randint(1, h)        #在1~h之间随机产生一个数
    y=  np.random.randint(1, w)        #在1~w之间随机产生一个数
    if np.random.randint(0, 2) == 0:    #随机产生0和1,0生成椒噪声,1生成盐噪声,两者产生的概率相同
        noisy_image[x, y] = [0,0,0]
    else:
        noisy_image[x,y] = [255,255,255]

filter_image = cv2.medianBlur(noisy_image, 3) #利用OpenCV提供的medianBlur()函数进行中值滤波操作
plt.rcParams['font.sans-serif'] = ['SimHei'] #支持中文显示
plt.subplot(1,3,1)  #显示1行3列子图第1个子图
plt.axis('off')     #关闭子图坐标轴
plt.title('原图')   #子图标题
plt.imshow(image)   #显示图像
plt.subplot(1,3,2)  #显示1行3列子图第2个子图
plt.axis('off')     #关闭子图坐标轴
plt.title('噪声图像')   #子图标题
plt.imshow(noisy_image)   #显示图像
plt.subplot(1,3,3)  #显示1行3列子图第3个子图
plt.axis('off')     #关闭子图坐标轴
plt.title('中值滤波图')  #子图标题
plt.imshow(filter_image)   #显示图像
plt.show()          #显示创建的所有图形/图像
<img src="./chapter3/tu3-8.png" width=1200 alt="中值滤波" >
<br>
<center style="font-size:16px">图3-2-4 中值滤波</center>

从该例中能看出,中值滤波技术对椒盐噪声的去除效果极佳,能较好保留边缘信息,避免模糊,不受极值像素影响,鲁棒性强。但是计算复杂度较高(需排序),对高斯噪声的平滑效果不如高斯滤波。

3.5 三种滤波方法的比较

(1)数学特性

  • 均值滤波:线性滤波,基于均匀加权平均,计算简单但会模糊边缘。
  • 高斯滤波:线性滤波,基于距离加权,平滑效果更好,边缘保留能力较强。
  • 中值滤波:非线性滤波,基于统计中值,对椒盐噪声鲁棒,边缘保留能力优于均值滤波。

(2)噪声处理能力

滤波方法 高斯噪声 椒盐噪声 边缘保留
均值滤波 良好 较差 较差
高斯滤波 优秀 较差 良好
中值滤波 一般 优秀 优秀

(3)计算复杂度

  • 均值滤波:复杂度为 (O(N)),其中 (N) 是邻域像素数,计算最简单。
  • 高斯滤波:复杂度为 (O(N)),但需额外计算高斯核,略高于均值滤波。
  • 中值滤波:复杂度为 (O(N N)),因涉及排序,计算成本最高。

(4)实际实现与效果分析

以下是一个完整的 Python 示例,展示如何对含噪图像应用三种滤波方法并比较效果:

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 加载图像
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

# 添加椒盐噪声
def add_salt_pepper_noise(image, prob):
    output = image.copy()
    noise = np.random.random(image.shape) < prob
    output[noise] = np.random.choice([0, 255], size=np.sum(noise))
    return output

noisy_image = add_salt_pepper_noise(image, 0.05)

# 应用三种滤波
mean_filtered = mean_filter(noisy_image, kernel_size=3)
gaussian_filtered = gaussian_filter(noisy_image, kernel_size=3, sigma=1.0)
median_filtered = median_filter(noisy_image, kernel_size=3)

# 显示结果
plt.figure(figsize=(12, 8))
plt.subplot(221), plt.imshow(image, cmap='gray'), plt.title('Original Image')
plt.subplot(222), plt.imshow(noisy_image, cmap='gray'), plt.title('Noisy Image')
plt.subplot(223), plt.imshow(mean_filtered, cmap='gray'), plt.title('Mean Filter')
plt.subplot(224), plt.imshow(median_filtered, cmap='gray'), plt.title('Median Filter')
plt.show()

(5)效果分析

  • 均值滤波:能有效降低高斯噪声,但对椒盐噪声效果不佳,且会导致明显边缘模糊。
  • 高斯滤波:在高斯噪声场景下表现最佳,边缘保留能力优于均值滤波。
  • 中值滤波:对椒盐噪声的去除效果显著,边缘细节保留较好,但在高斯噪声场景下效果一般。