Watershed segmentation 分水岭分割
分水岭是用于分割的经典算法,即用于分离图像中的不同对象。
从用户定义的标记开始,分水岭算法将像素值视为局部地形(高程)。该算法从标记中泛洪盆地,直到归因于不同标记的盆地在分水岭线上相遇。在许多情况下,选择标记作为图像的局部最小值,然后从中淹没盆地。
在下面的示例中,两个重叠的圆要分开。为此,您需要计算一张图像,即与背景之间的距离。选择该距离的最大值(即,距离的反方向的最小值)作为标记,并且从此类标记开始的盆地泛滥将两个圆圈沿分水岭线分开。
分水岭算法(watershed)是一种比较基本的数学形态学分割算法,其基本思想是将灰度图像转换为梯度图像,将梯度值看作高低起伏的山岭,将局部极小值及其邻域看作一个“集水盆”。设想一个个“集水盆”中存在积水,且水位不断升高,淹没梯度较低的地方,当水漫过程停止后,就找出了分割线,图像也就可以被分割成几块连通区域。
import numpy as np import matplotlib.pyplot as plt from scipy import ndimage as ndi from skimage.morphology import watershed from skimage.feature import peak_local_max # Generate an initial image with two overlapping circles x, y = np.indices((80, 80)) x1, y1, x2, y2 = 28, 28, 44, 52 r1, r2 = 16, 20 mask_circle1 = (x - x1)**2 + (y - y1)**2 < r1**2 mask_circle2 = (x - x2)**2 + (y - y2)**2 < r2**2 image = 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 background distance = 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秒)