2017-02-22 10 views
2

Скажем у вас есть изображение в виде numpy.array:Scikit изображение: правильный способ подсчета клеток в объектах изображения

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

И вы хотите, чтобы вычислить, сколько ячеек внутри каждого объекта, учитывая пороговое значение (пример):

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 неправильно, но цель это перебирать объекты. Как это сделать?

ответ

1

Это regionprops будет генерировать гораздо больше информации, чем просто площадь каждого сгустка.Так что, если вы просто хотите, чтобы получить количество пикселей для сгустков, в качестве альтернативы, и с акцентом на производительность, мы можем использовать np.bincount на labels, полученный с ndimage.label, как так -

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

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

enter image description here

1

Чтобы ответить на ориг Инал вопрос:

  • Вы должны применить regionprops маркированного изображения: props = regionprops(labels)

  • Вы можете построить словарь с помощью:

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

    , который дает

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