Mahotas 简明教程

Mahotas - Watershed

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

In image processing, a watershed algorithm is used for image segmentation, which is the process of dividing an image into distinct regions. The watershed algorithm is particularly useful for segmenting images with uneven regions or regions with unclear boundaries.

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

The watershed algorithm is inspired by the concept of a watershed in hydrology, where water flows from high to low areas along ridges until it reaches the lowest points, forming basins.

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

Similarly, in image processing, the algorithm treats the grayscale values of an image as a topographic surface, where high intensity values represent the peaks and low intensity values represent the valleys.

Working of Watershed Algorithm

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

Here’s a general overview of how the watershed algorithm works in image processing −

  1. Image Preprocessing : Convert the input image to a grayscale image (if it is not in grayscale). Perform any necessary preprocessing steps, such as noise removal or smoothing, to improve the results.

  2. Gradient Calculation : Calculate the gradient of the image to identify the intensity transitions. This can be done by using gradient operators, such as the Sobel operator, to highlight the edges.

  3. Marker Generation : Identify the markers that will be used to initiate the watershed algorithm. These markers generally correspond to the regions of interest in the image. They can be manually specified by the user or automatically generated based on certain criteria, such as local minima or a clustering algorithm.

  4. Marker Labeling : Label the markers in the image with different integer values, representing different regions.

  5. Watershed Transformation : Calculate the watershed transformation of the image using the labeled markers. This is done by simulating a flooding process, where the intensity values propagate from the markers and fill the image until they meet at the boundaries of different regions. The result is a grayscale image where the boundaries between regions are highlighted.

  6. Post−processing : The watershed transform may produce over−segmented regions. Post−processing steps, such as merging or smoothing, can be applied to refine the segmentation results and obtain the final segmented image.

Watershed in Mahotas

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

The Mahotas library does not have a direct function for applying traditional watershed algorithm on an image. However, Mahotas does offer a similar technique called conditional watershed, which we will explore and discuss in more detail in our further chapter.

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

To have a better understanding on traditional watershed algorithm, let us see an example of performing image segmentation using watershed algorithm with the help of the cv2 library.

Example

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

In the following example, we are applying Otsu’s thresholding, morphological operations, and distance transform to preprocess the image and obtain the foreground and background regions.

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

We are then using marker−based watershed segmentation to label the regions and mark the boundaries as red in the segmented image.

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()

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

Following is the output of the above code −

watershed image