【问题标题】:watershed segmentation always return black image分水岭分割总是返回黑色图像
【发布时间】:2018-05-12 07:46:52
【问题描述】:

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

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

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

然后,他们指示您执行形态灰度重建,以便稍微调整图像的灰度(但是,他们没有解释如何获取灰度的标记,所以我一直在胡闹并试图以我自己的方式得到一些)

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

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

目的是使用重建的图像来获得分水岭分割的标记,我们如何做到这一点?!我们得到原始图像(让我们将其标记为 f),并在 (f - r) 中执行阈值以提取单元格的 h-dome,即我们的标记。

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

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

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

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

这是被嘲笑的输出:

desired output

但是,我只得到黑色图像,每个像素都是黑色的,我不知道发生了什么......我也尝试使用他们的标记和倒置图像,但是,也得到黑色图像。我一直在使用的论文是 Luc M. Vincent, Barry R. Masters,“角膜内皮细胞图像的形态图像处理和网络分析”,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()

谢谢!

【问题讨论】:

  • 我认为这个问题应该很容易解决,但你必须给我们一些实际的代码和数据才能使用。
  • 所以cv2.watershed() 需要确定的前景和确定的背景。你已经展示了你确定的前景……确定的背景在哪里?我建议看一下我的答案here,这是一个类似类型的问题,并成功使用了 OpenCV 分水岭。另请参阅 OpenCV watershed 教程。您可以轻松地使用新的阈值图像,仅将图像的暗部分作为确定背景。
  • 另外我不明白为什么使用倒置图像或标记? OpenCV 期望标记在黑色背景上为白色,而不是相反(如所需结果所示)。而且我看不出反转原始图像有什么好处?
  • 我已经更新了我的代码 :) 天哪,Silencer,你到底是怎么得到这些结果的!?你有代码吗?增强后的 img 看起来与我的 grayReconstruction 有很大不同。Alexander Reynolds,我也尝试过使用倒置标记...只得到黑色图像..顺便说一句,“期望的结果”给了我们非常不同的分割,看起来就像所有的细胞都相互结合,你知道吗?

标签: opencv image-segmentation scikit-image watershed image-thresholding


【解决方案1】:

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

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

请注意,分水岭算法会输出一个分段常数图像,其中相同区域中的像素被分配相同的值。您的“所需输出”面板 (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()

【讨论】:

    猜你喜欢
    • 2019-08-06
    • 1970-01-01
    • 2012-07-11
    • 2020-07-27
    • 1970-01-01
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    相关资源
    最近更新 更多