分水岭分割总是return黑色图像

watershed segmentation always return black image

我最近一直在研究角膜的分割过程 内皮细胞,我发现了一篇相当不错的论文,它描述了执行它并取得良好结果的方法。我一直在尝试遵循那篇论文并使用 scikit-image 和 openCV 实现它,但我被困在分水岭分割上。

我简单描述一下流程应该是怎样的:

首先,你有原始的内皮细胞图像 original image

然后,他们指导你进行形态学灰度重建,使图像的灰度稍微平整一点(但是他们没有解释如何获得灰度的标记,所以我一直四处闲逛并尝试以自己的方式获得一些)

重建后的图像应该是这样的: desired reconstruction

这是我重建的图像(我们将其标记为 r)的样子: my reconstruction

目的是利用重建后的图像得到分水岭分割的标记,具体怎么做呢?!我们得到原始图像(让我们将其标记为 f),并在 (f - r) 中执行阈值以提取细胞,即我们的标记。

hdomes 图像应该是这样的: desired hdomes

这是我的 hdomes 图像的样子: my hdomes

我相信我得到的hdomes和他们的一样好,所以,最后一步是最终对原始图像进行分水岭分割,使用我们一直努力得到的hdomes!

作为输入图像,我们将使用反转的原始图像,作为标记,我们的标记。

这是被嘲笑的输出:

desired output

但是,我只得到一个黑色图像,每个像素都是黑色的,我不知道发生了什么......我也尝试过使用他们的标记和倒置图像,但是,也得到黑色图像。我一直在使用的论文是 Luc M. Vincent, Barry R. Masters, "Morphological image processing and network analysis of cornea endothelial cell images", Proc. SPIE 1769

对于冗长的文字,我深表歉意,但我真的很想详细解释我目前的理解,顺便说一句,我已经尝试从 scikit-image 和 opencv 进行分水岭分割,都给了我黑色图片。

下面是我一直在使用的代码

img = cv2.imread('input.png',0)
mask = img


marker = cv2.erode(mask, cv2.getStructuringElement(cv2.MORPH_ERODE,(3,3)), iterations = 3)
reconstructedImage = reconstruction(marker, mask)


hdomes = img - reconstructedImage
cell_markers = cv2.threshold(hdomes, 0, 255, cv2.THRESH_BINARY)[1]


inverted = (255 - img)
labels = watershed(inverted, cell_markers)

cv2.imwrite('test.png', labels)


plt.figure()
plt.imshow(labels)
plt.show()

谢谢!

这是一个使用 scikit-image 对图像进行分水岭分割的粗略示例。

您的脚本中缺少的是计算欧氏距离(参见 here and here)并从中提取局部最大值。

请注意,分水岭算法输出一个分段恒定图像,其中相同区域中的像素被分配相同的值。 'desired output' 面板 (e) 中显示的是区域之间的边缘。

import numpy as np
import cv2
import matplotlib.pyplot as plt
from skimage.morphology import watershed
from scipy import ndimage as ndi
from skimage.feature import peak_local_max
from skimage.filters import  threshold_local

img = cv2.imread('input.jpg',0)

'''Adaptive thersholding 
   calculates thresholds in regions of size block_size surrounding each pixel
   to handle the non-uniform background'''
block_size = 41
adaptive_thresh = threshold_local(img, block_size)#, offset=10)
binary_adaptive = img > adaptive_thresh

# Calculate Euclidean distance
distance = ndi.distance_transform_edt(binary_adaptive)

# Find local maxima of the distance map 
local_maxi = peak_local_max(distance, labels=binary_adaptive, footprint=np.ones((3, 3)), indices=False)
# Label the maxima
markers = ndi.label(local_maxi)[0]

''' Watershed algorithm
    The option watershed_line=True leave a one-pixel wide line 
    with label 0 separating the regions obtained by the watershed algorithm '''
labels = watershed(-distance, markers, watershed_line=True)

# Plot the result
plt.imshow(img, cmap='gray')
plt.imshow(labels==0,alpha=.3, cmap='Reds')
plt.show()