Mahotas - 分水岭
在图像处理中,分水岭算法用于图像分割,即将图像划分为不同区域的过程。分水岭算法对于分割区域不均匀或边界不清晰的图像特别有用。
分水岭算法的灵感来自水文学中的分水岭概念,水沿着山脊从高处流向低处,直到到达最低点,形成盆地。
同样,在图像处理中,该算法将图像的灰度值视为地形表面,其中高强度值代表峰顶,低强度值代表谷底。
分水岭算法的工作原理
以下是分水岭算法在图像处理中的工作原理的一般概述 −
图像预处理:将输入图像转换为灰度图像(如果不是灰度图像)。执行任何必要的预处理步骤,如噪声消除或平滑,以改善结果。
梯度计算:计算图像的梯度以识别强度转换。这可以通过使用梯度算子(如 Sobel 算子)来突出显示边缘来完成。
标记生成:识别将用于启动分水岭算法的标记。这些标记通常对应于图像中感兴趣的区域。
它们可以由用户手动指定,也可以根据某些标准(例如局部最小值或聚类算法)自动生成。
标记标记:使用不同的整数值标记图像中的标记,代表不同的区域。
分水岭变换:使用标记的标记计算图像的分水岭变换。这是通过模拟洪水过程来完成的,其中强度值从标记传播并填充图像,直到它们在不同区域的边界相遇。
结果是灰度图像,其中区域之间的边界突出显示。
后处理:分水岭变换可能会产生过度分割的区域。可以应用合并或平滑等后处理步骤来细化分割结果并获得最终的分割图像。
Mahotas 中的分水岭
Mahotas 库没有直接将传统分水岭算法应用于图像的函数。然而,Mahotas 确实提供了一种类似的技术,称为条件分水岭,我们将在后续章节中更详细地探讨和讨论它。
为了更好地理解传统的分水岭算法,让我们看一个在 cv2 库的帮助下使用分水岭算法进行图像分割的示例。
示例
在下面的例子中,我们应用 Otsu 的阈值、形态学操作和距离变换来预处理图像并获得前景和背景区域。
然后我们使用基于 marker− 的分水岭分割来标记区域并在分割图像中将边界标记为红色。
import cv2 import numpy as np from matplotlib import pyplot as plt image = cv2.imread('tree.tiff') # 将图像转换为灰度 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 应用 Otsu 阈值 _, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # 执行形态学开运算以消除噪声 kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2) # 执行距离变换 dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5) # 对距离变换进行阈值处理以获得确定的前景 _, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0) sure_fg = np.uint8(sure_fg) # 确定确定的背景区域 sure_bg = cv2.dilate(opening, kernel, iterations=3) # 确定未知区域 unknown = cv2.subtract(sure_bg, sure_fg) # 标记分水岭的标记 _, markers = cv2.connectedComponents(sure_fg) markers = markers + 1 markers[unknown == 255] = 0 # 应用分水岭算法 markers = cv2.watershed(image, markers) image[markers == -1] = [255, 0, 0] # 创建带有子图的图形 fig, axis = plt.subplots(1, 2, figsize=(7,5 )) # 显示原始图像图像 axes[0].imshow(image) axes[0].set_title('Original Image') axes[0].axis('off') # 显示分水岭图像 axes[1].imshow(markers) axes[1].set_title('Watershed Image') axes[1].axis('off') # 调整布局并显示图 plt.tight_layout() plt.show()
输出
以下是上述代码的输出 −
