Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subregions of boolean 2d array

Say i have a 2 dimensional boolean array. I would like to get a list of slices/or alike, where each slice represents the least (in size) subregions of the array contanining True values while its border contains all False.

I could loop for each row and column and store the indices when such condition is met, but i wonder if you know another way or a library that does this efficiently? You can assume that the boundary of the original boolean array is always False/0.

Example 1

enter image description here

Example 2

enter image description here

Edit ! Added new examples with the correct solutions. Sorry for the confusion.

like image 628
JustANoob Avatar asked Jan 10 '20 10:01

JustANoob


1 Answers

That's connected component analysis, which has been asked and answered before. Adapting the accepted answer from there to your needs, a possible solution is quite short:

import numpy as np
from scipy.ndimage.measurements import label


def analysis(array):
    labeled, _ = label(array, np.ones((3, 3), dtype=np.int))
    for i in np.arange(1, np.max(labeled)+1):
        pixels = np.array(np.where(labeled == i))
        x1 = np.min(pixels[1, :])
        x2 = np.max(pixels[1, :])
        y1 = np.min(pixels[0, :])
        y2 = np.max(pixels[0, :])
        print(str(i) + ' | slice: array[' + str(y1) + ':' + str(y2) + ', ' + str(x1) + ':' + str(x2) + ']')


example1 = np.array([
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
    [0, 0, 0, 0, 0, 0, 1, 1, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]).astype(bool)

example2 = np.array([
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 0, 1, 0, 0],
    [0, 0, 0, 1, 0, 0, 1, 0, 1, 0],
    [0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
    [0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 1, 0, 0, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 1, 1, 0, 0, 1, 0],
    [0, 0, 0, 0, 1, 0, 1, 0, 0, 0],
    [0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]).astype(bool)

for a in [example1, example2]:
    print(a, '\n')
    analysis(a)
    print('\n')

That's the output (without the examples):

[[...]] 

1 | slice: array[1:2, 3:5]
2 | slice: array[4:6, 6:8]
3 | slice: array[8:8, 2:2]

[[...]] 

1 | slice: array[1:3, 5:8]
2 | slice: array[2:2, 3:3]
3 | slice: array[4:5, 1:1]
4 | slice: array[5:8, 3:6]
5 | slice: array[6:6, 8:8]
6 | slice: array[8:8, 8:8]

Hope that helps!

------------------
System information
------------------
Python:  3.8.1
SciPy:   1.4.1
------------------
like image 91
HansHirse Avatar answered Sep 23 '22 11:09

HansHirse