I'm trying to extract rectangular groups of non-zero values from a numpy array. The array may look like this (but much bigger):
a = np.array([
[0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,1,1,1,1,1,0],
[0,0,0,0,6,1,1,1,3,1,0],
[0,0,0,0,0,1,1,1,1,1,0],
[0,0,0,0,2,2,2,0,1,0,0],
[0,0,0,0,2,2,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0,0,0],
[1,1,1,1,0,0,0,0,0,0,0],
[1,1,1,1,0,0,0,0,7,2,0],
[1,1,1,1,0,0,0,0,0,0,0]])
and I want to extract groups/blocks of non zero values bigger than a given size (e.g. bigger than 3x3), i.e. the coordinates of the min and max corners of those blocks. In this example, I should get the following:
res = [[(7,0), (10,4)],
[(1,5), (4,10)]]
so that
In [12]: xmin, ymin = res[0][0]
In [13]: xmax, ymax = res[0][1]
In [14]: a[xmin:xmax, ymin:ymax]
Out[14]:
array([[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]])
In [15]: xmin, ymin = res[1][0]
In [16]: xmax, ymax = res[1][1]
In [17]: a[xmin:xmax, ymin:ymax]
Out[17]:
array([[1, 1, 1, 1, 1],
[1, 1, 1, 3, 1],
[1, 1, 1, 1, 1]])
I've tried looking at each non-zero value of the array and growing a shape of the wanted size from this point until it does contain a zero. It works but it is quite slow. For this example array, it takes aroud 1.17 ms, It takes aroung 18 seconds in real applications (i.e. 600x1000 arrays), which is way too slow. Is there a numpy or OpenCV function or trick to perform this in a quicker way?


