平滑处理是指在某些数学和统计分析中,对于原始数据做出拟合,并生成更平滑的数据。这通常是为了抑制原始数据中的离群点或噪声,使得数据更具可读性和可解释性。
在图像处理中常用于模糊处理和降低噪声。平滑滤波器使用给定邻域内的像素平均灰度值或逻辑运算值代替原始图像中像素的灰度值,这种处理降低了图像灰度的“尖锐”变化。但图像边缘也是图像灰度尖锐变化带来的特性,因此平滑空间滤波器有边缘模糊化的负面效应。
平滑滤波器可分为平滑线性滤波器和平滑非线性滤波器。
平滑线性空间滤波器
平滑线性空间滤波器的优点是,它们可以在保留图像细节的同时去除噪声。但是,这种方法也有一个缺点,就是它可能会模糊图像中的细节。因此,在使用平滑线性空间滤波器时,需要权衡保留图像细节和去除噪声之间的平衡。平滑线性空间滤波器的输出是给定邻域像素灰度值的简单平均或加权值。
平滑线性空间滤波器 又称均值滤波器。主要降低图像中噪声,同时去除不相关细节,使不相关细节与背景糅合在一起,从而使感兴趣目标更易于检测,此时模板大小与不相关细节的尺寸有关。(举个栗子:将一滴白色颜料滴入一桶黑色颜料中,搅拌搅拌,虽然颜色可能稍微有点变淡,却依然是黑色颜料。白色颜料在黑色颜料桶中产生的影响无足轻重)。
如上图,3*3盒状滤波器模板。滤波器响应式:
R是由m*n大小模板定义的均值滤波器响应,模板中所有系数均为1/mn,这种滤波器叫盒状滤波器,是最简单的均值滤波器。
下面是盒状滤波器代码,使用不同盒状滤波器对图像进行滤波:
import numpy as np
from scipy import signal
from skimage import io
from matplotlib import pyplot as plt
# 定义二维灰度图像空间滤波函数:
def filter2d(img, window):
s = signal.correlate2d(img, window, mode='same', boundary='fill') # fill 滤波前用常值填充图像边缘,默认为0
return s.astype(np.uint8) # 可以将数组的数据类型转换为无符号 8 位整
img = io.imread("demo.jpg")
# 3*3盒装模型
win1 = np.ones((3, 3)) / (3 ** 2)
# 5*5
win2 = np.ones((5, 5)) / (5 ** 2)
# 9*9
win3 = np.ones((9, 9)) / (9 ** 2)
# 生成滤波结果
img1 = filter2d(img, win1)
img2 = filter2d(img, win2)
img3 = filter2d(img, win3)
# 显示图像
plt.subplot(121)
plt.title("gray")
plt.imshow(img, cmap='gray')
plt.subplot(122)
plt.title("3*3")
plt.imshow(img1, cmap='gray')
plt.show()
plt.subplot(121)
plt.title("5*5")
plt.imshow(img2, cmap='gray')
plt.subplot(122)
plt.title("9*9")
plt.imshow(img3, cmap='gray')
plt.show()
观察图像,发现3*3滤波结果比原始灰度图的花瓣更加平滑。与原始灰度图相比,5*5也使得花瓣变平滑,但背景稍微有点模糊,9*9滤波结果更模糊。随着滤波模板的增大,将图像的花瓣和任务也模糊化了。
常用的均值滤波器是加权平均的,距离越近的像素点权重越大,越远的像素点权重越小。高斯分布显然是一种可取的权重配模式。高斯分布是一种钟形曲线,越接近中心,却只越大,越远离中心,取值越小。高斯滤波器是一类根据高斯函数的形状选择权重的线性平滑滤波器。高斯平滑滤波器对抑制服从正态分布的噪声非常有效。
二维高斯函数
import numpy as np
import matplotlib.pyplot as plt
# 创建x,y轴值
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
# 计算高斯方程
mu = np.array([0, 0]) # 平均
sigma = np.array([[1, 0], [0, 1]]) # 方差矩阵
Z = np.exp(-0.5 * np.sum((np.dstack([X, Y]) - mu) @ np.linalg.inv(sigma) * (np.dstack([X, Y]) - mu), axis=2))
plt.imshow(Z, extent=(-5, 5, -5, 5))
plt.colorbar()
plt.show()
二维高斯图像:
上式中,标准差,二维高斯滤波模板,模板系数和为1,滤波器系数为:
import math
import numpy as np
from scipy import signal
from skimage import io
from matplotlib import pyplot as plt
# 定义二维灰度图像空间滤波函数:
def filter2d(img, window):
s = signal.correlate2d(img, window, mode='same', boundary='fill') # fill 滤波前用常值填充图像边缘,默认为0
return s.astype(np.uint8) # 可以将数组的数据类型转换为无符号 8 位整
# 定义二维高斯函数
def gauss(i, j, sigma):
return 1 / (2 * math.pi * sigma ** 2) * math.exp(-(i ** 2 + j ** 2) / (2 * sigma ** 2))
# 定义r*r高斯模板
def gauss_win(r, sigma):
win = np.zeros((r * 2 + 1, r * 2 + 1))
for i in range(-r, r + 1):
for j in range(-r, r + 1):
win[i + r][j + r] = gauss(i, j, sigma)
return win / np.sum(win)
img = io.imread("demo.jpg")
# 3*3高斯平滑模型
win1 = gauss_win(3, 1.0)
# 5*5
win2 = gauss_win(5, 1.0)
# 9*9
win3 = gauss_win(9, 1.0)
# 生成滤波结果
img1 = filter2d(img, win1)
img2 = filter2d(img, win2)
img3 = filter2d(img, win3)
# 显示图像
plt.subplot(121)
plt.title("gray")
plt.imshow(img, cmap='gray')
plt.subplot(122)
plt.title("3*3")
plt.imshow(img1, cmap='gray')
plt.show()
plt.subplot(121)
plt.title("5*5")
plt.imshow(img2, cmap='gray')
plt.subplot(122)
plt.title("9*9")
plt.imshow(img3, cmap='gray')
plt.show()
主要理解思想,代码理解即可。
随着高斯滤波模板增大,滤波结果越来越平滑。与盒状滤波模板相比,高斯滤波平滑效果更加柔和,不容易产生模糊效果。
您也可以使用skimage自带库函数:
from skimage import filters,io
# 读取图像
image = io.imread("demo.jpg")
# 高斯滤波,标准差为 1.0
filtered_image = filters.gaussian(image, sigma=1.0)
# 保存滤波后的图像
io.imsave("filtered_image.jpg", filtered_image)
统计排序滤波器
统计排序滤波器是一种非线性的图像滤波器,它的工作原理是对图像的每个像素周围的像素值进行排序,然后选择一个中间值(通常是中位数)作为输出像素的值(中值滤波)。
这种方法可以有效地去除图像中的噪声,因为噪声的值通常不会在图像的像素值分布中心,所以选择中位数可以有效地把噪声排除在外。
统计排序滤波器常用于去除椒盐噪声。椒盐噪声是一种很常见的图像噪声,它是由若干个随机的黑点或白点组成的,这些点的值通常比周围的像素值要大或小得多。
中值滤波使图像中突出的亮点(暗点)更像周围的值,以消除孤立的亮点(暗点),达到平滑的目的。
中值滤波:
from scipy import ndimage
from skimage import io, util
import matplotlib.pyplot as plt
img = io.imread("demo.jpg")
# 加入椒盐噪声
noise = util.random_noise(img, mode='s&p', seed=None, clip=True)
# 中值滤波
n = 3
new_img = ndimage.median_filter(noise, (n, n))
# 显示图像
plt.figure()
plt.imshow(img, cmap='gray')
plt.figure()
plt.imshow(noise, cmap='gray')
plt.figure()
plt.imshow(new_img, cmap='gray')
plt.show()
原图:
加噪:
中值滤波:
也可以对彩色图像进行空间滤波。对RGB图像空间滤波相当于分别对R,G,B三通道图像进行空间滤波。
import numpy as np
from skimage import util ,io
from matplotlib import pyplot as plt
from scipy import ndimage as ndi
#原始RGB
img=io.imread("D1.jpg")
noise=np.zeros(img.shape)
img1=np.zeros(img.shape)
for i in range(3):
gray=img[:,:,i]
#加噪
noise[:,:,i]=util.random_noise(gray,mode='s&p',seed=None,clip=True)
#中值滤波
n=3
img1[:,:,i]=ndi.median_filter(noise[:,:,i],(n,n))
plt.figure()
plt.imshow(img)
plt.show()
plt.figure()
plt.imshow(noise)
plt.show()
plt.figure()
plt.imshow(img1)
plt.show()
原图:
加噪:
滤波:
排序滤波器里还有最大值滤波器和最小值滤波器。最大值滤波器和最小值滤波器是图像处理和计算机视觉中经常使用的操作。
最大值滤波器会在输入图像的每个像素周围的一个区域中找到最大值,并将这个最大值赋给输入图像的对应像素。这个区域通常被称为滤波器的窗口或内核。
最小值滤波器也是类似的,它会在输入图像的每个像素周围的一个区域中找到最小值,并将这个最小值赋给输入图像的对应像素。
最大值滤波器和最小值滤波器通常用于去除图像噪声或者提升图像对比度。它们也可以用于找到图像中的边缘或者关键点。
下面是最大值和最小值滤波结果:
from skimage import util, io
from matplotlib import pyplot as plt
from scipy import ndimage as ndi
# 原始RGB
img = io.imread("D1.jpg")[:, :, 0]
# 加入胡椒噪声
pepper = util.random_noise(img, mode='pepper', seed=None, clip=True)
# 加入盐粒噪声
salt = util.random_noise(img, mode='salt', seed=None, clip=True)
n = 3
# 最大值滤波
max_img = ndi.maximum_filter(pepper, (n, n))
# 最小值滤波
min_img = ndi.minimum_filter(salt, (n, n))
# 显示
plt.subplot(121)
plt.title("demo")
plt.imshow(img, cmap='gray')
plt.subplot(122)
plt.title("pepper")
plt.imshow(pepper, cmap='gray')
plt.show()
plt.subplot(121)
plt.title("salt")
plt.imshow(salt, cmap='gray')
plt.subplot(122)
plt.title("max")
plt.imshow(max_img, cmap='gray')
plt.show()
plt.figure()
plt.title("min")
plt.imshow(min_img, cmap='gray')
plt.show()
原图和加胡椒噪声图像:
加盐粒噪声图像和最大值滤波图像:
最小值滤波图像:
观察上述图像,可以看到最大值滤波图像比原图更亮,最小最滤波图像比原图更暗。最大值滤波对去除胡椒噪声非常有效,最小值滤波对去除盐粒噪声很有效。