2

I'm working with 3D boolean arrays that mask a volume. My goal is to take a mask and reduce the area of the mask by some margin, m, in all dimensions.

Is there an easy way to do this using some common libraries (numpy, scipy, pandas, etc..)?

I found some code online that uses multiple for loops to expand a mask by one dimension. This works for the expansion case but I feel like there is a more compact way out there.

Here is a minimum example of what I am looking for in 2D.

Original

array([[0., 0., 1., 0., 0.],
       [0., 1., 1., 1., 0.],
       [1., 1., 1., 1., 1.],
       [0., 1., 1., 1., 0.],
       [0., 0., 1., 0., 0.]])

Uniform reduction by 1 pixel

array([[0., 0., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 1., 1., 1., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 0., 0.]])

But I want this to be in 3D space. Thank you for any input.

piRSquared
  • 285,575
  • 57
  • 475
  • 624
ar6
  • 23
  • 5

1 Answers1

2

You might be looking for scipy.ndimage.binary_erosion(a):

a = np.array([
    [0., 0., 1., 0., 0.],
    [0., 1., 1., 1., 0.],
    [1., 1., 1., 1., 1.],
    [0., 1., 1., 1., 0.],
    [0., 0., 1., 0., 0.]
])
b = scipy.ndimage.binary_erosion(a)  # returns an array of bool

Note that this will erode internal surfaces too

Eric
  • 95,302
  • 53
  • 242
  • 374