Curlew
Curlew

Reputation: 1034

Isolate greatest/smallest labeled patches from numpy array

i have a large numpy array and labeled it with the connected component labeling in scipy. Now i want to create subsets of this array, where only the biggest or smallest labels in size are left. Both extrema can of course occur several times.

import numpy
from scipy import ndimage
....
# Loaded in my image file here. To big to paste
....
s = ndimage.generate_binary_structure(2,2) # iterate structure
labeled_array, numpatches = ndimage.label(array,s) # labeling
# get the area (nr. of pixels) of each labeled patch
sizes = ndimage.sum(array,labeled_array,range(1,numpatches+1)) 

# To get the indices of all the min/max patches. Is this the correct label id?
map = numpy.where(sizes==sizes.max()) 
mip = numpy.where(sizes==sizes.min())

# This here doesn't work! Now i want to create a copy of the array and fill only those cells
# inside the largest, respecitively the smallest labeled patches with values
feature = numpy.zeros_like(array, dtype=int)
feature[labeled_array == map] = 1

Someone can give me hint how to move on?

Upvotes: 3

Views: 3224

Answers (2)

weiyixie
weiyixie

Reputation: 581

first you need a labeled mask, given a mask with only 0(background) and 1(foreground):

labeled_mask, cc_num = ndimage.label(mask)

then find the largest connected component:

largest_cc_mask = (labeled_mask == (np.bincount(labeled_mask.flat)[1:].argmax() + 1))

you can deduce the smallest object finding by using argmin()..

Upvotes: 3

HYRY
HYRY

Reputation: 97291

Here is the full code:

import numpy
from scipy import ndimage

array = numpy.zeros((100, 100), dtype=np.uint8)
x = np.random.randint(0, 100, 2000)
y = np.random.randint(0, 100, 2000)
array[x, y] = 1

pl.imshow(array, cmap="gray", interpolation="nearest")

s = ndimage.generate_binary_structure(2,2) # iterate structure
labeled_array, numpatches = ndimage.label(array,s) # labeling

sizes = ndimage.sum(array,labeled_array,range(1,numpatches+1)) 
# To get the indices of all the min/max patches. Is this the correct label id?
map = numpy.where(sizes==sizes.max())[0] + 1 
mip = numpy.where(sizes==sizes.min())[0] + 1

# inside the largest, respecitively the smallest labeled patches with values
max_index = np.zeros(numpatches + 1, np.uint8)
max_index[map] = 1
max_feature = max_index[labeled_array]

min_index = np.zeros(numpatches + 1, np.uint8)
min_index[mip] = 1
min_feature = min_index[labeled_array]

Notes:

  • numpy.where returns a tuple
  • the size of label 1 is sizes[0], so you need to add 1 to the result of numpy.where
  • To get a mask array with multiple labels, you can use labeled_array as the index of a label mask array.

The results:

enter image description here

enter image description here

enter image description here

Upvotes: 6

Related Questions