I want to filter the indices whose footprint (3,3) consists of 1s.
import numpy as np
data = np.array([[1, 1 , 0 , 0 , 0 , 0 , 1 , 0],
[1, 1 , 1 , 0 , 0 , 1 , 1 , 0],
[1, 1 , 1 , 1 , 1 , 0 , 0 , 0],
[0, 0 , 1 , 1 , 1 , 0 , 0 , 0],
[0, 0 , 1 , 1 , 1 , 1 , 0 , 1],
[1, 1 , 0 , 0 , 0 , 1 , 1 , 1],
[1, 1 , 0 , 0 , 0 , 1 , 1 , 1]])
The expected answer is below, unwanted positions are set to 0s:
answer = np.array([[0, 0 , 0 , 0 , 0 , 0 , 0 , 0],
[0, 0 , 0 , 0 , 0 , 0 , 0 , 0],
[0, 0 , 1 , 1 , 1 , 0 , 0 , 0],
[0, 0 , 1 , 1 , 1 , 0 , 0 , 0],
[0, 0 , 1 , 1 , 1 , 0 , 0 , 0],
[0, 0 , 0 , 0 , 0 , 0 , 0 , 0],
[0, 0 , 0 , 0 , 0 , 0 , 0 , 0]])
I'm basing this answer on a very similar answer I wrote just a few hours ago.
The result (in
data
) is as you've shown.The way this works is as follows: the function
extract_patches
generates a view into the arraydata
, which means it is not a copy of the actual data but uses the strides to generate a seemingly different array. In this case, it will generate all possible 3x3 submatrices (which can be overlapping) of the arraydata
. Then, by writingpatches.all(axis=-1).all(axis=-1)
, you are first checking if the elements in the rows of the submatrices are all True (or equivalent to True in a boolean sense, so not 0, empty lists, empty dictionaries, empty tuples and a few other special cases), thereby collapsing one of the axes of this array and then with the second.all(axis=-1)
the columns are being checked to see if they're all True.Small example of this paragraph to clarify visually:
So this array
dual
now has a "1" (True actually) for every 3x3 submatrix that was full of ones. Those submatrices are overlapping however, so you first want to set the patches all to 0 whenevery any of these 3x3 submatrices was not all ones (that's the one-to-last line in the first code block:patches[dual==False] = 0
) and then you can apply the ones again in each 3x3 submatrix that originally had all ones. The alternatives are to correlate with akernel = np.ones((3,3))
or to take multiple bitwise operations into account (like in the other answer), but that last method becomes very difficult to write when the array's dimensions grow beyond simply(2,2)
.