I want to find the location of a subarray in an numpy array.
For example, if the large array is of shape (10000, 10, 10, 10)
, namely 10000 arrays of shape (10,10,10) and I want to find the location of the subarray of shape (3,3,3)
as follows:
subarray = array(
[[[0., 0., 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.]]])
So I will know that at the location of n, i, j, k
I will get:
largearray[n, i:i subarray.shape[0], j:j subarray.shape[1], k:k subarray.shape[2]] == subarray
CodePudding user response:
Long ago I made a numpy
-only function for this, but skimage.util.view_as_windows
is a bit easier to implement.
import numpy as np
from skimage.util import view_as_windows as winview
test = np.random.choice((0, 1), p = (.75, .25), size = (5,10,10,10)) #smaller test array
subarray = np.zeros((3,3,3)) #what we're looking for
view = winview(test, (1,3,3,3)) #a view over 3x3x3 windows
out = np.all((view == subarray[None, ...]), (-4, -3, -2, -1)) #out=1 where the windows match
print(np.nonzero(out)) #output coordinates
Out[]: array([0, 1], dtype=int64), array([2, 7], dtype=int64), array([4, 4], dtype=int64), array([1, 1], dtype=int64))
That gives coordinates for 2 locations with the 3x3x3 zeros box in my random input.
Why do this as windows? Because looping takes forever in python and making the windows as a copy will kill your RAM. view
is just another way to address memory in test
that is more useful for this type of comparison.