scipyscipy.ndimage

How to grow a labeled feature in an scipy ndimage


Is there a way to grow a labeled feature in an ndimage? Ideally with a way to specify how the growth should happen by using a structure. I'm using scipy.ndimage.label() for feature detection in an n-dimensional binary image like so:

import numpy as np
from scipy import ndimage

a = np.full((8, 8), 1)
a[2, :] = a[5, :] = 0
a[:, 2] = a[:, 5] = 0

print(a)
>>>>
[[1 1 0 1 1 0 1 1]
 [1 1 0 1 1 0 1 1]
 [0 0 0 0 0 0 0 0]
 [1 1 0 1 1 0 1 1]
 [1 1 0 1 1 0 1 1]
 [0 0 0 0 0 0 0 0]
 [1 1 0 1 1 0 1 1]
 [1 1 0 1 1 0 1 1]]

s = [
    [0, 1, 0],
    [1, 1, 1],
    [0, 1, 0],
]

labeled, num = ndimage.label(a, structure=s)

print(labeled)
>>>>
[[1 1 0 2 2 0 3 3]
 [1 1 0 2 2 0 3 3]
 [0 0 0 0 0 0 0 0]
 [4 4 0 5 5 0 6 6]
 [4 4 0 5 5 0 6 6]
 [0 0 0 0 0 0 0 0]
 [7 7 0 8 8 0 9 9]
 [7 7 0 8 8 0 9 9]]

Now let's say I want to expand the feature with the label 2. Here is some pseudo code and output to illustrate what I want the results to be:

# pseudo code
grown = ndimage.grow(labeled, label=2, structure=s)
print(grown)
[[1 1 2 2 2 2 3 3]
 [1 1 2 2 2 2 3 3]
 [0 0 0 2 2 0 0 0]
 [4 4 0 5 5 0 6 6]
 [4 4 0 5 5 0 6 6]
 [0 0 0 0 0 0 0 0]
 [7 7 0 8 8 0 9 9]
 [7 7 0 8 8 0 9 9]]

Any help would be greatly appreciated! It seems like something scipy should be able to accomplish, but I'm still new to the module and I'm having trouble searching the docs for what I want to do.


Solution

  • I found that scipy.ndimage.binary_dilation does what I need when I filter the array first:

    filtered = np.where(labeled == 2, 1, 0)
    grown = ndimage.binary_dilation(filtered, structure=s).astype(np.int)
    
    print(grown)
    >>>>
    [[0 0 1 1 1 1 0 0]
     [0 0 1 1 1 1 0 0]
     [0 0 0 1 1 0 0 0]
     [0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 0]
     [0 0 0 0 0 0 0 0]]
    

    The output of the pseudo code can be achieved by combing grown and labeled like so:

    print(np.where(grown, 2, labeled))
    >>>>
    [[1 1 2 2 2 2 3 3]
     [1 1 2 2 2 2 3 3]
     [0 0 0 2 2 0 0 0]
     [4 4 0 5 5 0 6 6]
     [4 4 0 5 5 0 6 6]
     [0 0 0 0 0 0 0 0]
     [7 7 0 8 8 0 9 9]
     [7 7 0 8 8 0 9 9]]