Skimage中分水嶺算法的一些理解


根據官方文檔中的描述,本文參考https://github.com/scikit-image/scikit-image/blob/v0.13.1/skimage/morphology/watershed.py#L134

分水嶺算法主要是用於切割存在重復的圖像的切割。

Examples
    --------
    The watershed algorithm is useful to separate ‎重疊‎ objects.
    We first 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)
    Next, we want to separate the two circles. We generate markers at the
    maxima of the distance to the background:
    >>> from scipy import ndimage as ndi
    >>> distance = ndi.distance_transform_edt(image)
    >>> from skimage.feature import peak_local_max
    >>> local_maxi = peak_local_max(distance, labels=image,
    ...                             footprint=np.ones((3, 3)),
    ...                             indices=False)
    >>> markers = ndi.label(local_maxi)[0]
    Finally, we run the watershed on the image and markers:
    >>> labels = watershed(-distance, markers, mask=image)
    The algorithm works also for 3-D images, and can be used for example to
    separate overlapping spheres.
    """
    image, markers, mask = _validate_inputs(image, markers, mask)
    connectivity, offset = _validate_connectivity(image.ndim, connectivity,
                                                  offset)

    # pad the image, markers, and mask so that we can use the mask to
    # keep from running off the edges
    pad_width = [(p, p) for p in offset]
    image = np.pad(image, pad_width, mode='constant')
    mask = np.pad(mask, pad_width, mode='constant').ravel()
    output = np.pad(markers, pad_width, mode='constant')

    flat_neighborhood = _compute_neighbors(image, connectivity, offset)
    marker_locations = np.flatnonzero(output).astype(np.int32)
    image_strides = np.array(image.strides, dtype=np.int32) // image.itemsize

    _watershed.watershed_raveled(image.ravel(),
                                 marker_locations, flat_neighborhood,
                                 mask, image_strides, compactness,
                                 output.ravel(),
                                 watershed_line)

    output = crop(output, pad_width, copy=True)

    if watershed_line:
        min_val = output.min()
        output[output == min_val] = 0

    return output

這里先插入一段官方給的例子來說明。

首先采用了np.indice()函數來生成切片索引序列。其函數的具體實現功能,在這篇文章中可以看到。https://blog.csdn.net/daimashiren/article/details/111127432。

對生成的切片索引進行判別,確定出兩個重疊的圓的布爾值索引集合,並對兩個集合進行與操作,從而得到存在重疊區域的兩個圓的布爾值索引集合。

生成圓的工作已經完成,接下來我們需要對兩個圓進行分割操作。

首先,我們需要找到我們所需要的markers點,標記點,不過我更喜歡把它叫做注水點。可以用該函數ndi.distance_transform_edt進行尋找,函數作用參考https://blog.csdn.net/weixin_43508499/article/details/106609901。總結一下,就是計算每個像素點到最鄰近的背景點(0值點)的距離,從而完成對整個圖像的重新賦值。

在此例子中,我們要分離兩個圓,找的注水點就是兩個圓的圓心。簡單分析可得,最佳的注水點應該是圖像中值最高的兩個點。

利用peak_local_max對距離圖像進行遍歷,返回一個和圖像相同形狀的數組,對其中的峰值點進行標記為True。

然后通過ndi.label()對峰值檢測數組進行遍歷,對其進行遍歷操作,類似區域生長的算法在此都能夠得到實現,標記類別。用途就是可以對二值圖進行類別標記,默認是四連通區域檢測,如果需要八連通區域則需要自己定義卷積核。

最后進行區域的分水嶺算法。

以原始圖像的前景區域為邊界進行填充,輸入地勢條件-distance,數值越低表示地勢越低,markers為注水點標記,后期注水時會以注水點標記為數值,以相應的類別值為水值進行注水。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM