图像识别之高丝滤波
高斯滤波(Gaussian filter)是一种常用的线性平滑滤波方法,其主要思想是在空间域中采用高斯核函数对图像进行卷积,实现图像的平滑处理。高斯滤波可以有效地消除噪声,平滑图像,同时保持图像的边缘和细节信息。在图像处理中,高斯滤波通常作为预处理或者后处理的一部分,用于去除噪声或者模糊图像。
高斯滤波的核函数可以表示为:
其中,(x,y)(x,y)(x,y)是核函数的坐标,σ\sigmaσ是高斯函数的标准差。高斯函数的标准差决定了滤波器的模糊程度,标准差越大,滤波器的模糊程度越高。
高斯滤波的核函数通常是一个正方形或者圆形的二维矩阵,矩阵的大小通常是奇数。以一个 5×55\times55×5 的核函数为例,可以使用以下代码生成:
import numpy as np
def gaussian_kernel(size, sigma):
x, y = np.meshgrid(np.linspace(-1, 1, size), np.linspace(-1, 1, size))
d = np.sqrt(x * x + y * y)
kernel = np.exp(-((d ** 2) / (2.0 * sigma ** 2))) / (2.0 * np.pi * sigma ** 2)
kernel = kernel / np.sum(kernel)
return kernel
kernel = gaussian_kernel(5, 1)
print(kernel)
以上代码使用了NumPy库生成了一个 5×55\times55×5 的高斯核函数,标准差为1。
下面是使用OpenCV库实现高斯滤波的示例代码:
import cv2
# 加载图像
img = cv2.imread('image.jpg')
# 高斯滤波
blur = cv2.GaussianBlur(img, (5, 5), 1)
# 可视化结果
cv2.imshow('image', img)
cv2.imshow('blur', blur)
cv2.waitKey()
cv2.destroyAllWindows()
以上代码使用了OpenCV库中的 cv2.GaussianBlur() 函数实现高斯滤波,核函数大小为 5×55\times55×5,标准差为1。可以根据具体需求调整核函数大小和标准差以获得更好的效果。
总的来说,高斯滤波是一种常用的图像平滑方法,可以有效地去除噪声和平滑图像。在实际应用中,需要根据具体需求调整核函数大小和标准差以获得更好的效果。
平滑效果好
平滑效果好是高斯滤波的一个显著特点,这主要得益于高斯函数的形状。高斯函数在中心点处取得最大值,随着距离的增加,函数值逐渐减小。这种函数形状使得高斯滤波可以在去除噪声的同时保留图像的细节信息。
运算速度快
高斯滤波的运算速度快是由于高斯滤波的核函数具有可分离性。即一维高斯函数与另一维高斯函数的卷积结果等价于一个二维高斯函数与一维高斯函数的卷积结果。因此,可以将二维高斯滤波分解为两个一维高斯滤波,分别对图像的行和列进行滤波。这样就可以大大减少计算量,提高运算速度。
具体来说,一维高斯函数的表达式为:
其中,xxx 表示距离中心点的距离,σ\sigmaσ 表示标准差。高斯核函数的表达式为:
其中,xxx 和 yyy 分别表示距离中心点的距离,G(x)G(x)G(x) 和 G(y)G(y)G(y) 分别表示对应的一维高斯函数。
对于一个大小为 n×nn \times nn×n 的高斯核,其一维高斯函数的长度为 nnn,因此,对于一个大小为 M×NM \times NM×N 的图像,进行二维高斯滤波需要进行 M×N×n×nM \times N \times n \times nM×N×n×n 次乘法和加法运算,计算成本较高。而将二维高斯滤波分解为两个一维高斯滤波后,需要进行的运算次数为 2M×N×n2M \times N \times n2M×N×n,大大减少了计算成本,提高了运算速度。
以下是使用 Python 实现的一维高斯函数和二维高斯滤波的示例代码:
import numpy as np
import cv2
def gauss_1d(sigma, x):
return 1 / (np.sqrt(2 * np.pi) * sigma) * np.exp(-x**2 / (2 * sigma**2))
def gauss_2d(sigma, x, y):
return gauss_1d(sigma, x) * gauss_1d(sigma, y)
def gaussian_filter(img, sigma):
n = int(2 * np.ceil(3 * sigma) + 1)
kernel = np.zeros((n, n))
for i in range(n):
for j in range(n):
x = i - n // 2
y = j - n // 2
kernel[i, j] = gauss_2d(sigma, x, y)
kernel = kernel / np.sum(kernel)
filtered_img = cv2.filter2D(img, -1, kernel)
return filtered_img
其中,gauss_1d 函数实现了一维高斯函数的计算,gauss_2d 函数实现了二维高斯函数的计算,gaussian_filter 函数实现了二维高斯滤波的过程,通过计算得到高斯核,并对图像进行卷积操作,最终得到滤波后的图像。具体来说,gaussian_filter 函数首先根据给定的标准差 sigma 计算出高斯核的大小 n,然后循环遍历高斯核的每一个像素,计算出其对应的二维高斯函数值,最终将高斯核归一化后,使用 OpenCV 提供的 filter2D 函数对输入图像 img 进行卷积操作,得到滤波后的图像 filtered_img。
需要注意的是,以上代码实现的是不可分离的二维高斯滤波,运算速度较慢。如果要实现可分离的高斯滤波,可以先对图像的行进行一维高斯滤波,再对滤波后的图像的列进行一维高斯滤波,这样可以大大提高运算速度。
总之,高斯滤波具有运算速度快的特点,这是由于其核函数具有可分离性,可以将二维高斯滤波分解为两个一维高斯滤波,从而大大减少计算量。
可控性好
高斯滤波的可控性好是指可以通过调整标准差和核函数大小来控制滤波效果。
核函数的大小决定了滤波的范围,即在进行滤波时取多少个像素点进行计算。核函数越大,滤波的范围就越大,处理的图像就越模糊。相反,核函数越小,滤波的范围就越小,处理的图像就越清晰。
标准差决定了像素点之间的权重,即距离越远的像素点权重越小。标准差越小,像素点之间的权重越相近,处理后的图像就越清晰。相反,标准差越大,像素点之间的权重越分散,处理后的图像就越模糊。
下面是高斯滤波的公式:
其中,xxx 和 yyy 表示像素点与中心点的距离,σ\sigmaσ 表示标准差,G(x,y)G(x,y)G(x,y) 表示高斯核函数。
高斯滤波的代码如下(使用Python和OpenCV库):
import cv2
import numpy as np
def gaussian_filter(image, kernel_size=3, sigma=1):
# 根据kernel_size生成高斯核函数
kernel = np.zeros((kernel_size, kernel_size))
center = kernel_size // 2
s = 2 * sigma ** 2
for i in range(kernel_size):
for j in range(kernel_size):
x, y = i - center, j - center
kernel[i, j] = np.exp(-(x ** 2 + y ** 2) / s)
kernel /= kernel.sum()
# 进行滤波操作
filtered_image = cv2.filter2D(image, -1, kernel)
return filtered_image
在该函数中,首先根据传入的参数生成高斯核函数,然后使用OpenCV库中的filter2D函数对输入图像进行滤波操作。在实际使用时,可以通过调整kernel_size和sigma参数来控制滤波效果。
适用性强
适用性强是高斯滤波的一个重要特点,它适用于各种类型的图像,如灰度图像、彩色图像、二值图像等。
在灰度图像处理中,高斯滤波可以用以下公式表示:
其中,III 表示输入的灰度图像,Ii,jI_{i,j}Ii,j 表示像素点 (i,j)(i,j)(i,j) 的灰度值,wk,lw_{k,l}wk,l 是一个大小为 (2n+1)×(2n+1)(2n+1) \times (2n+1)(2n+1)×(2n+1) 的权值矩阵,表示在 (i,j)(i,j)(i,j) 周围的 nnn 个像素点内,每个像素点的权值,其计算公式为:
其中,σ\sigmaσ 表示高斯函数的标准差。
在彩色图像处理中,可以对 R、G、B 三个通道分别进行高斯滤波,最后将三个通道的结果合成为一张图像。具体来说,设 IrI_rIr、IgI_gIg、IbI_bIb 分别表示原图的 R、G、B 通道,Ir′I_r'Ir′、Ig′I_g'Ig′、Ib′I_b'Ib′ 分别表示对应通道的高斯滤波结果,则可以用以下公式表示:
在二值图像处理中,可以将原始二值图像转换为灰度图像,然后进行高斯滤波处理,最后再将处理后的灰度图像转换回二值图像。
下面是使用 Python 代码实现灰度图像的高斯滤波过程:
import cv2
import numpy as np
def gaussian_filter(img, ksize, sigma):
# 计算权值矩阵
kernel = np.zeros((ksize, ksize), dtype=np.float32)
center = ksize // 2
s = 2 * sigma * sigma
for i in range(ksize):
for j in range(ksize):
x, y = i - center, j - center
kernel[i, j] = np.exp(-(x * x + y * y) / s) / (np.pi * s)
kernel /= np.sum(kernel)
# 对图像进行滤波处理
img_pad = cv2.copyMakeBorder(img, center, center, center, center, cv2.BORDER_REFLECT)
img_filter = np.zeros_like(img, dtype=np.float32)
for i in range(img.shape[0]):
for j in range(img.shape[1]):
img_filter[i, j] = np.sum(kernel * img_pad[i:i+ksize, j:j+ksize])
img_filter = np.clip(img_filter, 0, 255).astype(np.uint8)
return img_filter
在上述代码中,使用 np.zeros_like
创建一个与输入图像相同大小的数组,用于存储滤波结果。使用 cv2.copyMakeBorder
函数对输入图像进行边缘填充,以确保滤波操作能够在边缘处正常进行。然后,遍历图像中的每个像素点,计算权值矩阵和该像素点周围的像素值的加权平均值,得到该像素点的滤波结果。最后,使用 np.clip
函数将滤波结果限制在 [0,255][0, 255][0,255] 的范围内,并转换为 uint8
类型。
使用以下代码调用上述函数并显示滤波结果:
img = cv2.imread('lena.png', cv2.IMREAD_GRAYSCALE)
img_filter = gaussian_filter(img, 5, 1)
cv2.imshow('Filtered', img_filter)
cv2.waitKey(0)
cv2.destroyAllWindows()
上述代码将灰度图像 lena.png 读入,然后使用 gaussian_filter 函数对其进行高斯滤波处理,滤波器的大小为 5×55 \times 55×5,标准差为 1。最后,使用 cv2.imshow 函数显示滤波结果。
在彩色图像处理中,可以使用类似的方法对 R、G、B 三个通道分别进行高斯滤波处理,然后将三个通道的结果合成为一张图像。在二值图像处理中,可以使用类似的方法将原始二值图像转换为灰度图像,然后进行高斯滤波处理,最后再将处理后的灰度图像转换回二值图像。
转载自:https://juejin.cn/post/7225848846785904695