2016-03-24 9 views
0

У меня есть матрица трехмерных меток. Использование ndimage.sum Я могу получить размеры помеченных объектов, что отлично подходит для фильтрации по объему. Мой вопрос: могу ли я легко получить размеры объектов вдоль каждой оси, чтобы устранить те, которые находятся только в одной плоскости, например?Размеры объектов по размеру?

Маленький код может быть яснее ...

from scipy import ndimage 
labmat,n = ndimage.label(np.random.rand(30,30,30) > 0.99) 
sizes = ndimage.sum(labmat.astype(bool),labmat,range(n+1)) 

Теперь вместо 1-мерного, представляющих объемов меченых объектов, есть способ иметь 3D-массив, представляющие их поверхность в каждом измерении? 30-мерный массив, представляющий их поверхности в каждой плоскости, также будет в порядке, хотя я бы предпочел первый вариант.

ответ

1

Вы можете использовать ndimage.find_objects, чтобы найти ограничительную прямоугольник для каждой этикетки. Ограничительная коробка задается кортежем ломтиков. Например,

data_slices = ndimage.find_objects(labmat) 
# [(slice(0L, 1L, None), slice(4L, 5L, None), slice(28L, 29L, None)), 
# (slice(0L, 1L, None), slice(25L, 26L, None), slice(19L, 20L, None)), 
# (slice(0L, 1L, None), slice(27L, 28L, None), slice(10L, 11L, None)), 
# (slice(0L, 1L, None), slice(28L, 29L, None), slice(7L, 8L, None)), 
# ... 

Вы могли бы найти размер каждой ограничивающей рамки, используя

sizes = np.array([[s.stop-s.start for s in object_slice] 
        for object_slice in data_slices]) 
# array([[1, 1, 1], 
#  [1, 1, 1], 
#  [1, 1, 1], 
#  [1, 1, 1], 
# ... 

и создать булеву маску, которая верно для каждого ящика, длина которого больше 1 во всех 3-х измерениях:

mask = (sizes > 1).all(axis=1) 

np.flatnonzero Используйте, чтобы найти соответствующие индексы:

idx = np.flatnonzero(mask) 

Вы также можете использовать срезы для выбора области значений от labmat (или исходного массива). Например,

for i in idx: 
    print(labmat[data_slices[i]]) 

import numpy as np 
from scipy import ndimage 
np.random.seed(2016) 

labmat, n = ndimage.label(np.random.rand(30,30,30) > 0.5) 
data_slices = ndimage.find_objects(labmat) 
sizes = np.array([[s.stop-s.start for s in object_slice] 
        for object_slice in data_slices]) 
mask = (sizes > 1).all(axis=1) 
idx = np.flatnonzero(mask) 
for i in idx: 
    print(labmat[data_slices[i]]) 
+0

'find_objects' [игнорирует ярлыки со значением 0] (http://docs.scipy.org/doc/scipy-0.16.1/reference/generated/scipy. ndimage.measurements.find_objects.html # scipy.ndimage.measurements.find_objects). Таким образом, первая строка размеров соответствует значению метки 1. Обязательно удалите/измените 'np.random.seed (2016)' для проверки других случайных входов. 'mask = (размеры> 1) .all (axis = 1)' выбирает поля, которые отображаются в более чем одной плоскости в каждом измерении. Чтобы выбрать поля, которые отображаются в более чем 1 плоскости вдоль только первого измерения, используйте 'mask = (размеры [:, 0]> 1)'. – unutbu

+0

О, ладно, я смутился, потом осознал это и удалил свой комментарий, прежде чем увидеть твое. Благодарю. – nicoco