Mahotas 简明教程

Mahotas - Watershed

在图像处理中,分水岭算法用于图像分割,这是一个将图像分割为不同区域的过程。分水岭算法特别适合分割区域不均匀或边界不清晰的图像。

分水岭算法的灵感来自于水文学中分水岭的概念,在其中,水流从高地沿着山脊流向低地,直到它到达最低点,形成盆地。

同样,在图像处理中,该算法将图像的灰度值视为地形表面,高强度值表示山峰,低强度值表示山谷。

Working of Watershed Algorithm

下面是分水岭算法在图像处理中如何工作的一般概述 −

  1. Image Preprocessing :将输入图像转换为灰度图像(如果它不是灰度图像)。执行任何必要的预处理步骤,例如消噪或平滑,以提高效果。

  2. Gradient Calculation :计算图像的梯度以识别强度转换。这可以通过使用梯度算子(例如此处是 Sobel 算子)来完成,突出显示边缘。

  3. Marker Generation :标识将用于启动分水岭算法的标记。这些标记通常对应图像中的感兴趣区域。它们可以由用户手动指定,也可以根据特定标准(如局部极小值或聚类算法)自动生成。

  4. Marker Labeling :用不同的整数值标记图像中的标记,表示不同的区域。

  5. Watershed Transformation :使用标记标记计算图像的分水岭转换。这是通过模拟洪水过程来完成的,在这个过程中强度值从标记向外扩展,填满图像,直到它们在不同区域的边界处相遇。结果是灰度图像,其中区域之间的边界被突出显示。

  6. Post−processing :分水岭变换可能会产生过度分割的区域。后处理步骤,例如合并或平滑,可以用来改善分割结果并获得最终分割的图像。

Watershed in Mahotas

Mahotas 库没有直接用于对图像应用传统分水岭算法的函数。但是,Mahotas 提供了一种名为 conditional watershed 的类似技术,我们将在后面的章节中深入探讨和讨论它。

为了更好地理解传统分水岭算法,让我们举一个使用 cv2 库通过分水岭算法执行图像分割的示例。

Example

在以下示例中,我们应用 Otsu 的阈值处理、形态运算和距离变换来预处理图像并获取前景和背景区域。

然后我们使用基于标记的分水岭分割来标记区域并用红色标记分割图像中的边界。

import cv2
import numpy as np
from matplotlib import pyplot as plt
image = cv2.imread('tree.tiff')
# Convert the image to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Apply Otsu's thresholding
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV +
cv2.THRESH_OTSU)
# Perform morphological opening for noise removal
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
# Perform distance transform
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
# Threshold the distance transform to obtain sure foreground
_, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
sure_fg = np.uint8(sure_fg)
# Determine the sure background region
sure_bg = cv2.dilate(opening, kernel, iterations=3)
# Determine the unknown region
unknown = cv2.subtract(sure_bg, sure_fg)
# Label the markers for watershed
_, markers = cv2.connectedComponents(sure_fg)
markers = markers + 1
markers[unknown == 255] = 0
# Apply watershed algorithm
markers = cv2.watershed(image, markers)
image[markers == -1] = [255, 0, 0]
# Create a figure with subplots
fig, axes = plt.subplots(1, 2, figsize=(7,5 ))
# Display the original image
axes[0].imshow(image)
axes[0].set_title('Original Image')
axes[0].axis('off')
# Display the watershed image
axes[1].imshow(markers)
axes[1].set_title('Watershed Image')
axes[1].axis('off')
# Adjust the layout and display the plot
plt.tight_layout()
plt.show()

以下是上面代码的输出: -

watershed image