'Finding location of subarray in numpy array

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



Solution 1:[1]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Daniel F