【问题标题】:Scikit image: proper way of counting cells in the objects of an imageScikit 图像:计算图像对象中细胞的正确方法
【发布时间】:2017-02-22 15:44:18
【问题描述】:

假设您有一个numpy.array 形式的图像:

vals=numpy.array([[3,24,25,6,2],[8,7,6,3,2],[1,4,23,23,1],[45,4,6,7,8],[17,11,2,86,84]])

如果阈值为17(示例),您想计算每个对象内部有多少个单元格:

from scipy import ndimage
from skimage.measure import regionprops

blobs = numpy.where(vals>17, 1, 0)
labels, no_objects = ndimage.label(blobs)
props = regionprops(blobs)

如果你检查,这会给出一个超过阈值的 4 个不同对象的图像:

In[1]: blobs
Out[1]: 
array([[0, 1, 1, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 1, 1, 0],
       [1, 0, 0, 0, 0],
       [0, 0, 0, 1, 1]])

事实上:

In[2]: no_objects
Out[2]: 4

我想计算每个对象的单元格(或面积)数。预期的结果是具有object ID: number of cells 格式的字典:

size={0:2,1:2,2:1,3:2}

我的尝试:

size={}
for label in props:
    size[label]=props[label].area

返回错误:

Traceback (most recent call last):

  File "<ipython-input-76-e7744547aa17>", line 3, in <module>
    size[label]=props[label].area

TypeError: list indices must be integers, not _RegionProperties

我知道我错误地使用了label,但其目的是迭代对象。 如何做到这一点?

【问题讨论】:

    标签: python numpy image-processing scikit-image


    【解决方案1】:

    一些测试和研究有时会有很长的路要走。

    问题在于blobs,因为它没有携带不同的标签,而只有0,1 值,还有label,需要用循环range(0,no_objects) 的迭代器替换。

    这个解决方案似乎有效:

    import skimage.measure as measure
    import numpy
    from scipy import ndimage
    from skimage.measure import regionprops
    
    vals=numpy.array([[3,24,25,6,2],[8,7,6,3,2],[1,4,23,23,1],[45,4,6,7,8],[17,11,2,86,84]])
    
    blobs = numpy.where(vals>17, 1, 0) 
    labels, no_objects = ndimage.label(blobs)
    
    #blobs is not in an amicable type to be processed right now, so:
    labelled=ndimage.label(blobs)
    resh_labelled=labelled[0].reshape((vals.shape[0],vals.shape[1])) #labelled is a tuple: only the first element matters
    
    #here come the props
    props=measure.regionprops(resh_labelled) 
    
    #here come the sought-after areas
    size={i:props[i].area for i in range (0, no_objects)}
    

    结果:

    In[1]: size
    Out[1]: {0: 2, 1: 2, 2: 1, 3: 2}
    

    如果有人想检查labels

    In[2]: labels
    Out[2]: 
    array([[0, 1, 1, 0, 0],
           [0, 0, 0, 0, 0],
           [0, 0, 2, 2, 0],
           [3, 0, 0, 0, 0],
           [0, 0, 0, 4, 4]])
    

    如果有人想绘制找到的 4 个对象:

    import matplotlib.pyplot as plt
    plt.set_cmap('OrRd')
    plt.imshow(labels,origin='upper')
    

    【讨论】:

      【解决方案2】:

      回答原来的问题:

      • 您必须将 regionprops 应用于标记的图像:props = regionprops(labels)

      • 然后您可以使用以下方法构建字典:

        size = {r.label: r.area for r in props}

        产生

        {1: 2, 2: 2, 3: 1, 4: 2}

      【讨论】:

        【解决方案3】:

        regionprops 将生成比每个 blob 的区域更多的信息。因此,如果您只是想获取 blob 的像素数,作为替代方案并关注性能,我们可以在使用 ndimage.label 获得的 labels 上使用 np.bincount,就像这样 -

        np.bincount(labels.ravel())[1:]
        

        因此,对于给定的样本 -

        In [53]: labeled_areas = np.bincount(labels.ravel())[1:]
        
        In [54]: labeled_areas
        Out[54]: array([2, 2, 1, 2])
        

        要将这些结果放入字典中,还需要一个额外的步骤是 -

        In [55]: dict(zip(range(no_objects), labeled_areas))
        Out[55]: {0: 2, 1: 2, 2: 1, 3: 2}
        

        【讨论】:

        • 我喜欢这个,谢谢。我的解决方案只是为了解决这个问题,但我们知道性能是关键。
        • 我认为regionprops使用了惰性求值,所以性能差异应该不会很大。
        猜你喜欢
        • 1970-01-01
        • 2010-10-10
        • 1970-01-01
        • 2017-07-26
        • 2021-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多