分水岭是用于分割的经典算法,即用于分离图像中的不同对象。
从用户定义的标记开始,分水岭算法将像素值视为局部地形(高程)。该算法从标记中泛洪盆地,直到归因于不同标记的盆地在分水岭线上相遇。在许多情况下,选择标记作为图像的局部最小值,然后从中淹没盆地。
在下面的示例中,两个重叠的圆要分开。为此,您需要计算一张图像,即与背景之间的距离。选择该距离的最大值(即,距离的反方向的最小值)作为标记,并且从此类标记开始的盆地泛滥将两个圆圈沿分水岭线分开。
分水岭算法(watershed)是一种比较基本的数学形态学分割算法,其基本思想是将灰度图像转换为梯度图像,将梯度值看作高低起伏的山岭,将局部极小值及其邻域看作一个“集水盆”。设想一个个“集水盆”中存在积水,且水位不断升高,淹没梯度较低的地方,当水漫过程停止后,就找出了分割线,图像也就可以被分割成几块连通区域。
import numpy as npimport matplotlib.pyplot as pltfrom scipy import ndimage as ndifrom skimage.morphology import watershedfrom skimage.feature import peak_local_max# Generate an initial image with two overlapping circlesx, y = np.indices((80, 80))x1, y1, x2, y2 = 28, 28, 44, 52r1, r2 = 16, 20mask_circle1 = (x – x1)**2 + (y – y1)**2 < r1**2mask_circle2 = (x – x2)**2 + (可爱的朋友)**2 < r2**2image = np.logical_or(mask_circle1, mask_circle2)# Now we want to separate the two objects in image# Generate the markers as local maxima of the distance to the backgrounddistance = ndi.distance_transform_edt(image)local_maxi = peak_local_max(distance, indices=False, footprint=np.ones((3, 3)), labels=image)markers = ndi.label(local_maxi)[0]labels = watershed(-distance, markers, mask=image)fig, axes = plt.subplots(ncols=3, figsize=(9, 3), sharex=True, sharey=True)ax = axes.ravel()ax[0].imshow(image, cmap=plt.cm.gray)ax[0].set_title(‘Overlapping objects’)ax[1].imshow(-distance, cmap=plt.cm.gray)ax[1].set_title(‘Distances’)ax[2].imshow(labels, cmap=plt.cm.nipy_spectral)ax[2].set_title(‘Separated objects’)for a in ax: a.set_axis_off()fig.tight_layout()plt.show()
脚本的总运行时间:(0分钟0.217秒)
Download Python source code: plot_watershed.py
Download Jupyter notebook: plot_watershed.ipynb