DIP 数字图像处理实验 第三课

图像空域滤波

日期:2025.4.9

前言:

    在上一节课中,我们详细学习了图像的灰度变换和直方图,包括线性点运算、非线性点运算、代数运算(加减乘除)以及图像灰度直方图的均衡化。这节课我们来学习一下图像的空域滤波。

实验目的:

1.掌握图像空域滤波原理

2.理解并分析平滑滤波与锐化滤波的区别和联系

空域滤波:

按照功能来分类,空域滤波可以分为平滑滤波和锐化滤波。
空域滤波通过模板对图像进行处理,达到图像增强的目的。空域滤波器以模板中心像素点为 参考,逐像素进行移动,并通过计算获得新的像素值,即模板中心所处像素点的值。当模板遍历过 所有像素后,滤波完成,得到增强后的图像。简单的空域滤波可用公式表示如下:

其中,f(x,y)表示输入的图片,g(x,y)表示输出的过滤图像,w(s,t)表示m×n 的空域滤波器。 空域滤波的过程就是不断地用一个卷积核在图像上与同样大小的局部作用,作用结果更新在中心 点上,所以需要m 和n为奇数,通常情况下使用的模板大小为3×3、5×5或者7×7。

实验内容:

1.均值滤波:

均值滤波是最简单的空域平滑滤波方法,旨在消除图像中的噪声,让图像更平滑。

原理:

对于图像中的每个像素,取以它为中心的一个邻域内像素值的平均值,来替换该像素原来的值。比如在一个 3×3 的邻域内,将 9 个像素值相加后除以 9,得到的均值就是中心像素的新值。

优缺点:

均值滤波计算简单,能有效降低高斯噪声。但它也有缺点,过度使用会模糊图像细节,边缘信息也会被削弱。在实际应用中,常用于对图像质量要求不太高,仅需初步降噪的场景,像对监控视频做预处理,以减少噪点干扰 。

实验代码如下:

import skimage
import cv2
import matplotlib.pylab as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
img = cv2.imread('dog.jpg', 0)

img = img / 255
img_g = skimage.util.random_noise(img, 'gaussian', mean=0, var=0.05)
img_s = skimage.util.random_noise(img, 's&p')#salt

img_g_l = cv2.blur(img_g, (3, 3))
img_s_l = cv2.blur(img_s, (3, 3))
img_g_l1 = cv2.blur(img_g, (5, 5))
img_s_l1 = cv2.blur(img_s, (5, 5))
plt.subplot(231)
plt.imshow(img_g, 'gray')
plt.title('带高斯噪声图片')
plt.subplot(234)
plt.imshow(img_s, 'gray')
plt.title('带椒盐噪声图片')
plt.subplot(232)
plt.imshow(img_g_l, 'gray')
plt.title('均值滤波后图像(3*3)')
plt.subplot(233)
plt.imshow(img_g_l1, 'gray')
plt.title('均值滤波后图像(5*5)')
plt.subplot(235)
plt.imshow(img_s_l, 'gray')
plt.title('均值滤波后图像(3*3)')
plt.subplot(236)
plt.imshow(img_s_l1, 'gray')
plt.title('均值滤波后图像(5*5)')
plt.show()

代码运行结果如下:

从实验结果可以看出,两种噪声在均值滤波后都一定程度上减少了噪声。但是也带来了模糊效应。同时也可以看出,随着滤波器变大,虽然去噪效果更好,但是模糊程度也更大。

2.高斯滤波:

高斯滤波是一种数字图像处理技术。它主要用于图像去噪,通过对图像中的每个像素点及其邻域进行加权平均来实现。

原理:利用高斯函数生成一个二维的滤波模板,模板中的系数与像素点到中心的距离有关,距离越近权重越大。这样可以在去除噪声的同时,尽可能地保留图像的细节信息。

特点:在实际应用中,它对于服从正态分布的噪声有很好的抑制效果,广泛应用于计算机视觉、医学图像处理等领域,能有效提高图像质量,为后续的图像分析和处理提供更好的基础。

实验代码如下:

import skimage
import cv2
import matplotlib.pylab as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
img = cv2.imread('dog.jpg', 0)

img = img / 255
img_g = skimage.util.random_noise(img, 'gaussian', mean=0, var=0.05)
img_s = skimage.util.random_noise( mg, 's&p')

img_g_l=cv2.GaussianBlur(img_g,(3,3),0,5)
img_s_l=cv2.GaussianBlur(img_s,(3,3),0,5)
img_g_l1=cv2.GaussianBlur(img_g,(5,5),0,5)
img_s_l1=cv2.GaussianBlur(img_s,(5,5),0,5)
plt.subplot(231)
plt.imshow(img_g,'gray')
plt.title('带高斯噪声图片')
plt.subplot(234)
plt.imshow(img_s,'gray')
plt.title('带椒盐噪声图片')
plt.subplot(232)
plt.imshow(img_g_l,'gray')
plt.title('高斯滤波后图像(3*3)')
plt.subplot(233)
plt.imshow(img_g_l1,'gray')
plt.title('高斯滤波后图像(5*5)')
plt.subplot(235)
plt.imshow(img_s_l,'gray')
plt.title('高斯滤波后图像(3*3)')
plt.subplot(236)
plt.imshow(img_s_l1,'gray')
plt.title('高斯滤波后图像(5*5)')
plt.show()

代码运行结果如下:

从实验结果可以得出和均值滤波类似的结论,同时也可发现高斯滤波后图像的清晰度要比均值滤波的高。

3.中值滤波:

中值滤波是一种非线性数字滤波技术,在图像处理等领域应用广泛。

原理:对一个以当前像素为中心的邻域窗口内像素值进行排序,取中间值来替换当前像素值。例如在3×3窗口中,对9个像素值排序,用第5大的值更新中心像素。

特点:相比均值滤波,它能更好地保留图像边缘信息,有效去除椒盐噪声等脉冲干扰。在图像去噪过程中,若采用均值滤波,边缘可能会模糊;而中值滤波能让边缘清晰,使图像在去除噪声的同时,保持原本的轮廓和细节,维持图像质量。

实验代码如下:

import skimage
import cv2
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
img = cv2.imread('dog.jpg', 0)

img = img / 255.0
img_g = skimage.util.random_noise(img, 'gaussian', mean=0, var=0.05)
img_s = skimage.util.random_noise(img, 's&p')

img_g_uint8 = (img_g * 255).astype(np.uint8)
img_s_uint8 = (img_s * 255).astype(np.uint8)

img_g_l = cv2.medianBlur(img_g_uint8, 3)
img_s_l = cv2.medianBlur(img_s_uint8, 3)
img_g_l1 = cv2.medianBlur(img_g_uint8, 5)
img_s_l1 = cv2.medianBlur(img_s_uint8, 5)
plt.subplot(231)
plt.imshow(img_g,'gray')
plt.title('带高斯噪声图片')
plt.subplot(234)
plt.imshow(img_s,'gray')
plt.title('带椒盐噪声图片')
plt.subplot(232)
plt.imshow(img_g_l,'gray')
plt.title('中值滤波后图像(3*3)')
plt.subplot(233)
plt.imshow(img_g_l1,'gray')
plt.title('中值滤波后图像(5*5)')
plt.subplot(235)
plt.imshow(img_s_l,'gray')
plt.title('中值滤波后图像(3*3)')
plt.subplot(236)
plt.imshow(img_s_l1,'gray')
plt.title('中值滤波后图像(5*5)')
plt.show()

代码运行结果如下:

中值滤波对椒盐噪声有更好的滤波效果。

4.锐化滤波:

锐化滤波是一种在数字图像处理中广泛应用的技术,用于增强图像的边缘和细节,使图像看起来更加清晰。

原理:图像的锐化滤波主要是通过增强图像中的高频成分来实现的。在频域中,图像的边缘和细节信息通常对应着高频分量,而低频分量则主要对应图像的平滑区域。锐化滤波器通过对图像的高频分量进行加权放大,相对抑制低频分量,从而突出图像的边缘和细节,达到锐化的效果。

三种常见算子:

(1)拉普拉斯算子:这是一种常用的二阶微分算子,对图像中的阶跃变化(如边缘)非常敏感。它通过计算图像在水平和垂直方向上的二阶导数来增强边缘。其模板通常有多种形式,例如经典的 3×3 模板,中心系数为 4,周围系数为 - 1。拉普拉斯算子能很好地突出图像中的细节,但对噪声也较为敏感,可能会放大噪声。
(2)索贝尔算子:主要用于检测图像中的边缘。它结合了图像的一阶导数信息,通过在水平和垂直方向上分别使用不同的模板进行卷积运算,然后将两个方向的结果组合起来得到边缘强度。索贝尔算子对噪声有一定的抑制作用,同时能够较好地检测出图像中的水平和垂直边缘。
(3)罗伯特算子:是一种简单的一阶差分算子,通过计算图像中相邻像素之间的灰度差异来检测边缘。它使用两个 2×2 的模板,分别检测水平和垂直方向上的边缘。罗伯特算子计算速度快,但对噪声的鲁棒性相对较差。

实验代码如下:

import skimage
import cv2
import matplotlib.pylab as plt
import numpy as np
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
img = cv2.imread('dog.jpg', 0)
# Roberts
Robertx=np.array([[-1,0],[0,1]])
Roberty=np.array([[0,-1],[1,0]])
img_x=cv2.filter2D(img,-1,Robertx)
img_y=cv2.filter2D(img,-1,Roberty)
img_r=abs(img_x)+abs(img_y)
# Prewitt
Prewittx=np.array([[1,1,1],[0,0,0],[-1,-1,-1]])
Prewitty=np.array([[-1,0,1],[-1,0,1],[-1,0,1]])
img_x=cv2.filter2D(img,-1,Prewittx)
img_y=cv2.filter2D(img,-1,Prewitty)
img_p=abs(img_x)+abs(img_y)
# Sobel
img_s=cv2.Sobel(img,-1,1,1)
plt.subplot(141)
plt.imshow(img,'gray')
plt.title('原图')
plt.subplot(142)
plt.imshow(img_r,'gray')
plt.title('Roberts 算子滤波后图')
plt.subplot(143)
plt.imshow(img_p,'gray')
plt.title('Prewitt 算子滤波后图')
plt.subplot(144)
plt.imshow(img_s,'gray')
plt.title('Sobel 算子滤波后图')
plt.show()

代码运行结果如下:

5.改写代码:

实现分别对一幅被均匀噪声和椒盐噪声污染的图像,用均值滤波、高斯滤波和中值滤波器处理,对比分析结果。

实验代码如下:

import cv2
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 读取均匀噪声与椒盐噪声
img_g = cv2.imread('average2.bmp', 0)
img_s = cv2.imread('salt.bmp', 0)

# 均值滤波
img_g_1 = cv2.blur(img_g, (3, 3))
img_s_1 = cv2.blur(img_s, (3, 3))

# 高斯滤波
img_g_2 = cv2.GaussianBlur(img_g, (3, 3), 0, 5)
img_s_2 = cv2.GaussianBlur(img_s, (3, 3), 0, 5)

# 中值滤波
img_g_3 = cv2.medianBlur(img_g, 3)
img_s_3 = cv2.medianBlur(img_s, 3)

plt.subplot(2, 4, 1)
plt.imshow(img_g, 'gray')
plt.title('带均匀噪声图片')

plt.subplot(2, 4, 2)
plt.imshow(img_g_1, 'gray')
plt.title('均值滤波后图像(3*3)')

plt.subplot(2, 4, 3)
plt.imshow(img_g_2, 'gray')
plt.title('高斯滤波后图像(3*3)')

plt.subplot(2, 4, 4)
plt.imshow(img_g_3, 'gray')
plt.title('中值滤波后图像(3*3)')

# 第二行:椒盐噪声图片及滤波结果
plt.subplot(2, 4, 5)
plt.imshow(img_s, 'gray')
plt.title('带椒盐噪声图片')

plt.subplot(2, 4, 6)
plt.imshow(img_s_1, 'gray')
plt.title('均值滤波后图像(3*3)')

plt.subplot(2, 4, 7)
plt.imshow(img_s_2, 'gray')
plt.title('高斯滤波后图像(3*3)')

plt.subplot(2, 4, 8)
plt.imshow(img_s_3, 'gray')
plt.title('中值滤波后图像(3*3)')

plt.show()

代码运行结果如下:

6.OpenCV实现底层代码:

import cv2
import numpy as np
def mean_filter_manual(img, kernel_size=5):
    rows, cols = img.shape
    pad = kernel_size // 2
    img_padded = cv2.copyMakeBorder(img, pad, pad, pad, pad, cv2.BORDER_REPLICATE)
    img_filtered = np.zeros_like(img)
    kernel = np.ones((kernel_size, kernel_size), dtype=np.float32) / (kernel_size ** 2)

    for i in range(rows):
        for j in range(cols):
            window = img_padded[i:i + kernel_size, j:j + kernel_size]
            img_filtered[i, j] = np.sum(window * kernel)

    return img_filtered.astype(np.uint8)
def median_filter_manual(img, kernel_size=5):
    rows, cols = img.shape
    pad = kernel_size // 2
    img_padded = cv2.copyMakeBorder(img, pad, pad, pad, pad, cv2.BORDER_REPLICATE)
    img_filtered = np.zeros_like(img)

    for i in range(rows):
        for j in range(cols):
            window = img_padded[i:i + kernel_size, j:j + kernel_size]
            median = np.median(window)
            img_filtered[i, j] = median

    return img_filtered.astype(np.uint8)
# 读取图像
img_path = 'salt.bmp'  # 请确保图像文件位于当前工作目录或提供完整路径
img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)

if img is None:
    print(f"无法加载图像,请检查路径是否正确。图像路径: {img_path}")
    exit()

# 应用自定义均值滤波器
img_mean_manual = mean_filter_manual(img, 5)

# 应用自定义中值滤波器
img_median_manual = median_filter_manual(img, 5)

# 应用 OpenCV 内置的均值滤波器
img_mean_cv = cv2.blur(img, (5, 5))

# 应用 OpenCV 内置的中值滤波器
img_median_cv = cv2.medianBlur(img, 5)

# 显示结果
# 创建窗口
cv2.imshow('原图', img)
cv2.imshow('自定义均值滤波', img_mean_manual)
cv2.imshow('OpenCV 均值滤波', img_mean_cv)
cv2.imshow('自定义中值滤波', img_median_manual)
cv2.imshow('OpenCV 中值滤波', img_median_cv)

# 等待按键
cv2.waitKey(0)
# 销毁所有窗口
cv2.destroyAllWindows()

代码运行结果如下:

以上就是本次实验课的全部内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值