首页 > 文章列表 > 使用OpenCV Python进行图像分割,使用分水岭算法

使用OpenCV Python进行图像分割,使用分水岭算法

284 2023-09-05

作为热情的计算机视觉爱好者和 Python 程序员,我们一直被 OpenCV 库令人难以置信的功能所吸引。我们特别着迷的一项技术是图像分割,即将图像划分为不同区域的过程。本文将分享我们使用 OpenCV Python 和 Watershed 算法执行图像分割的历程和见解。通过利用物理景观中水流的概念,分水岭算法已成为准确识别边界和分离图像中对象的强大工具。我们将一起深入探讨从预处理图片到应用分水岭算法的逐步过程,同时展示示例和输出。加入我们,一起了解使用 OpenCV Python 和 Watershed 算法进行图像分割的艺术。

第 1 步:导入库并加载图像

为了开始我们的旅程,我们导入两个重要的库:OpenCV 和 NumPy。 OpenCV 广泛用于图像处理,而 NumPy 以其 Python 中的数值计算功能而闻名。有了这些强大的工具,我们就可以继续下一步:加载我们想要分割的图像。下面是一个示例代码:

import cv2
import numpy as np

# Load the image
image = cv2.imread('image.jpg')

第 2 步:预处理图像

现在,我们使用 OpenCV 库中的 cv2.cvtColor() 函数将加载的图像转换为灰度图像。这种转换通过以灰色阴影表示图像来简化图像,使其更易于分析和处理。以下是将图像转换为灰度的示例:

# Convert the image to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

在上面的代码中,图像指的是我们要分割的加载图像。 cv2.cvtColor() 函数有两个参数:图像和转换标志 cv2.COLOR_BGR2GRAY,该标志指定从 BGR 颜色空间到灰度的转换。

第 3 步:应用阈值

阈值处理是图像分割中的一项关键技术,可将灰度图像转换为二值图像。它在将我们感兴趣的物体与背景分开方面起着至关重要的作用。在二值图像中,对象由白色像素表示,而背景由黑色像素表示。对象和背景之间的这种清晰区分简化了分割过程的后续步骤。

为了对步骤 2 中获得的灰度图像应用阈值处理,我们使用 cv2.threshold() 函数。下面是一个示例代码:

# Apply thresholding
ret, threshold = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

第 4 步:通过形态运算消除噪声

第 4 步涉及使用形态学运算从图像中去除噪声。在图像处理中,噪声是指可能影响图像分析的质量和准确性的不需要的随机变化或不规则性。形态学操作是一组修改图像中对象的形状和结构的操作。然后,我们将执行形态学开运算,它结合了腐蚀操作和膨胀操作。此操作有助于去除噪声,同时保留图像中对象的整体形状和大小。

现在,让我们检查一下演示如何使用形态开口消除噪声的代码片段:

# Perform morphological opening to remove noise
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(threshold, cv2.MORPH_OPEN, kernel, iterations=2)

在上面的代码中,我们使用 NumPy 定义一个内核,它是一个 3x3 的矩阵。内核确定形态学操作期间考虑的每个像素周围的邻域。较大的内核尺寸可以帮助消除较大的噪声或不规则性,但也可能使图像模糊。

第 5 步:创建标记图像

在使用分水岭算法的图像分割中,创建标记图像起着至关重要的作用。标记图像用于标记图像中感兴趣的区域,这有助于准确地将图像分割成不同的区域。以下代码片段演示了如何创建标记图像:

# Find background region
sure_bg = cv2.dilate(opening, kernel, iterations=3)

# Find foreground region
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)

# Create marker image
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)

第 6 步:应用分水岭算法

现在是令人兴奋的部分 - 应用分水岭算法进行图像分割。在这一步中,我们将未知区域标记为零,并利用分水岭算法将图像分割成不同的区域。

# Apply Watershed algorithm
ret, markers = cv2.connectedComponents(sure_fg)
markers = markers + 1
markers[unknown == 255] = 0
cv2.watershed(image, markers)

通过执行这些代码行,我们有效地应用分水岭算法根据标记区域分割图像,创建可以进一步可视化和分析的分割图。

第 7 步:可视化分割图像

应用分水岭算法进行图像分割后,是时候可视化分割的图像了。此步骤涉及为每个分割区域分配不同的颜色并将其与原始图像混合。

这是一个示例代码:

# Apply colormap to the markers
colored_markers = np.zeros_like(image)
colored_markers[markers == -1] = [255, 0, 0]  # Boundaries in blue color

# Display the segmented image
segmented_image = cv2.addWeighted(image, 0.7, colored_markers, 0.3, 0)
cv2.imshow("Segmented Image", segmented_image)
cv2.waitKey(0)

最后,我们使用 cv2.imshow() 显示分段图像,而 cv2.waitKey(0) 用于等待按键。现在可以查看分割的图像,并可以检查分水岭算法的结果。

结论

总之,在 OpenCV Python 中使用分水岭算法进行图像分割提供了一种强大且通用的方法,可以将图像划分为有意义的区域。通过利用水流的概念并将其与OpenCV库的功能相结合,我们可以准确地识别图像中的边界并分离对象。

在本文中,我们探索了使用分水岭算法进行图像分割的逐步过程。从加载图像并对其进行预处理以提高分割精度开始,我们介绍了阈值处理、噪声去除、创建标记图像以及应用分水岭算法本身等基本步骤。通过执行以下步骤,我们可以获得可靠且具有视觉吸引力的图像分割结果。