Scikit Image:在图像对象中计算细胞的正确方法

3

假设你有一张图片以 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

我希望计算每个对象的单元格数(或面积)。预期结果是一个字典,格式为对象ID:单元格数

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

My attempt:

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,但目的是迭代对象。该怎么做呢?

3个回答

2
回答原问题:
  • 您需要对标记图像应用regionprops:props = regionprops(labels)

  • 接下来,您可以使用以下代码构建字典:

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

    这将得到

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


2

测试和研究有时候可以收获很大。

问题出在 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}

如果有人想要检查 标签

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')

enter image description here


1

regionprops 会生成比每个 blob 的面积更多的信息。因此,如果您只想获取 blob 的像素计数,并且关注性能,作为替代方案,我们可以使用 np.bincount 在使用 ndimage.label 获得的 labels 上进行操作,如下所示 -

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}

1
我喜欢这个,谢谢。我的解决方案只是为了解决问题,但我们知道性能有多重要。 - FaCoffee
我认为regionprops使用了惰性求值,因此性能差异不应该很大。 - Rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接