OpenCV常用图像滤波

1,295 阅读4分钟

「这是我参与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 时,两个函数完全等价。两个函数都使用如下核平滑图像:

K=α[111111111]K=\alpha\begin{bmatrix} 1 & 1 & \cdots & 1 \\ 1 & 1 & \cdots & 1\\ \vdots&\vdots&\ddots&\vdots \\ 1 & 1 & \cdots & 1 \end{bmatrix}

cv2.boxFilter() 函数:

α={ksize.widthksize.height,if normalize=true1,otherwise\alpha = \begin{cases} ksize.width\cdot ksize.height, & \text{if normalize=true} \\[2ex] 1, & \text{otherwise} \end{cases}

在 cv2.blur() 函数的情况下: α=ksize.widthksize.height \alpha = ksize.width\cdot ksize.height 换句话说, 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)

图像处理中的常用滤波器

相关链接

OpenCV实现图像的几何变换