「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战」
图像滤波
图像处理技术是计算机视觉项目的核心,通常是计算机视觉项目中的关键工具,可以使用它们来完成各种计算机视觉任务。在本文中,将介绍计算机视觉项目中常见的图像处理技术——图像滤波,首先介绍如何模糊和锐化图像,然后应用自定义核。此外,还将介绍一些用于执行其他图像处理功能的常见核。
应用滤波器(卷积核或简称为核)
OpenCV 提供了 cv2.filter2D() 函数,以将任意核应用于图像,将图像与提供的核进行卷积操作。为了使用此函数,首先需要构建将使用的核:
# 使用 5 x 5 核
kernel_averaging_5_5 = np.array([[0.04, 0.04, 0.04, 0.04, 0.04], [0.04,
0.04, 0.04, 0.04, 0.04], [0.04, 0.04, 0.04, 0.04, 0.04],[0.04, 0.04, 0.04,
0.04, 0.04], [0.04, 0.04, 0.04, 0.04, 0.04]])
以上示例创建了 5 x 5 平均卷积核,也可以使用以下方式创建卷积核核:
kernel_averaging_5_5 = np.ones((5, 5), np.float32) / 25
然后将应用 cv2.filter2D() 函数将核应用于源图像:
smooth_image_f2D = cv2.filter2D(image, -1, kernel_averaging_5_5)
上述方法可以将任意核应用于图像。示例中,创建了一个平均卷积核来平滑图像。或者,我们也可以使用 OpenCV 内置的函数,从而在无需创建核的情况下执行图像平滑(也称为图像模糊)。
图像平滑
平滑技术通常用于减少噪声,此外,这些技术还可用于减少低分辨率图像中的像素化。
均值滤波
可以使用 cv2.blur() 或 cv2.boxFilter() 通过将图像与核卷积来执行均值滤波,在使用 cv2.boxFilter() 时可以不执行规范化,只是取核区域下所有像素的平均值,并用这个平均值替换中心元素,可以控制核大小和锚点位置(默认情况下锚点位于核中心)。当 cv2.boxFilter() 的 normalize 参数等于 True 时,两个函数完全等价。两个函数都使用如下核平滑图像:
cv2.boxFilter() 函数:
在 cv2.blur() 函数的情况下:
换句话说, cv2.blur() 是使用归一化的 boxFilter():
# 以下两行代码是等价的
smooth_image_b = cv2.blur(image, (10, 10))
smooth_image_bfi = cv2.boxFilter(image, -1, (10, 10), normalize=True)
均值滤波后的图像如下所示:
高斯滤波
OpenCV 提供了 cv2.GaussianBlur() 函数用于高斯滤波,该函数使用高斯核对图像进行模糊处理。可以使用以下参数控制高斯核:ksize (核大小)、sigmaX (高斯核 x 方向的标准差) 和 sigmaY (高斯核 y 方向的标准差)。为了获取所应用的高斯核,可以使用 cv2.getGaussianKernel() 函数构建高斯核:
# (9, 9)表示高斯矩阵的长与宽都是5,标准差取0
smooth_image_gb = cv2.GaussianBlur(image, (9, 9), 0)
# 标准差取0.3
smooth_image_gb_2 = cv2.GaussianBlur(image, (9, 9), 0.3)
# 构建高斯核
print(cv2.getGaussianKernel(9,0))
高斯滤波后的图像如下所示:
中值滤波
OpenCV 提供了 cv2.medianBlur() 函数用于中值滤波,该函数使用中值核对图像进行模糊处理:
smooth_image_mb = cv2.medianBlur(image, 9)
smooth_image_mb_2 = cv2.medianBlur(image, 3)
此滤波器可用于减少图像中的椒盐噪声,效果如下:
双边滤波
cv2.bilateralFilter() 函数应用于输入图像可以执行双边滤波。与上述所有平滑滤波器倾向于全局平滑不同,此函数可用于在保持边缘锐利的同时减少噪声:
smooth_image_bf = cv2.bilateralFilter(image, 5, 10, 10)
双边滤波效果如下图所示:
图像锐化
锐化图像的边缘的一种简单方法是执行非锐化蒙版 (unsharp masking),即从原始图像中减去图像的非锐化或平滑版本。在以下示例中,首先应用了高斯平滑滤波器,然后从原始图像中减去生成的图像:
smoothed = cv2.GaussianBlur(img, (9, 9), 10)
unsharped = cv2.addWeighted(img, 1.5, smoothed, -0.5, 0)
另一种方法是使用特定的核来锐化边缘,然后应用 cv2.filter2D() 函数:
kernel_sharpen_1 = np.array([[0, -1, 0],
[-1, 5, -1],
[0, -1, 0]])
kernel_sharpen_2 = np.array([[-1, -1, -1],
[-1, 9, -1],
[-1, -1, -1]])
kernel_sharpen_3 = np.array([[1, 1, 1],
[1, -7, 1],
[1, 1, 1]])
kernel_sharpen_4 = np.array([[-1, -1, -1, -1, -1],
[-1, 2, 2, 2, -1],
[-1, 2, 8, 2, -1],
[-1, 2, 2, 2, -1],
[-1, -1, -1, -1, -1]]) / 8.0
sharp_image_1 = cv2.filter2D(image, -1, kernel_sharpen_1)
sharp_image_2 = cv2.filter2D(image, -1, kernel_sharpen_2)
sharp_image_3 = cv2.filter2D(image, -1, kernel_sharpen_3)
sharp_image_4 = cv2.filter2D(image, -1, kernel_sharpen_4)
锐化后图像输出如下所示:
图像处理中的常用滤波器
还可以定义了一些用于不同目的的通用核,例如:边缘检测、平滑、锐化或浮雕等,定义内核后,可以使用 cv2.filter2D() 函数:
image = cv2.imread('sigonghuiye.jpeg')
kernel_identity = np.array([[0, 0, 0],
[0, 1, 0],
[0, 0, 0]])
# 边缘检测
kernel_edge_detection_1 = np.array([[1, 0, -1],
[0, 0, 0],
[-1, 0, 1]])
kernel_edge_detection_2 = np.array([[0, 1, 0],
[1, -4, 1],
[0, 1, 0]])
kernel_edge_detection_3 = np.array([[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]])
# 锐化
kernel_sharpen = np.array([[0, -1, 0],
[-1, 5, -1],
[0, -1, 0]])
kernel_unsharp_masking = -1 / 256 * np.array([[1, 4, 6, 4, 1],
[4, 16, 24, 16, 4],
[6, 24, -476, 24, 6],
[4, 16, 24, 16, 4],
[1, 4, 6, 4, 1]])
# 模糊
kernel_blur = 1 / 9 * np.array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])
gaussian_blur = 1 / 16 * np.array([[1, 2, 1],
[2, 4, 2],
[1, 2, 1]])
# 浮雕
kernel_emboss = np.array([[-2, -1, 0],
[-1, 1, 1],
[0, 1, 2]])
# 边缘检测
sobel_x_kernel = np.array([[1, 0, -1],
[2, 0, -2],
[1, 0, -1]])
sobel_y_kernel = np.array([[1, 2, 1],
[0, 0, 0],
[-1, -2, -1]])
outline_kernel = np.array([[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]])
# 应用卷积核
original_image = cv2.filter2D(image, -1, kernel_identity)
edge_image_1 = cv2.filter2D(image, -1, kernel_edge_detection_1)
edge_image_2 = cv2.filter2D(image, -1, kernel_edge_detection_2)
edge_image_3 = cv2.filter2D(image, -1, kernel_edge_detection_3)
sharpen_image = cv2.filter2D(image, -1, kernel_sharpen)
unsharp_masking_image = cv2.filter2D(image, -1, kernel_unsharp_masking)
blur_image = cv2.filter2D(image, -1, kernel_blur)
gaussian_blur_image = cv2.filter2D(image, -1, gaussian_blur)
emboss_image = cv2.filter2D(image, -1, kernel_emboss)
sobel_x_image = cv2.filter2D(image, -1, sobel_x_kernel)
sobel_y_image = cv2.filter2D(image, -1, sobel_y_kernel)
outline_image = cv2.filter2D(image, -1, outline_kernel)