Sliding Windows on Numpy Arrays

Iterating over Numpy arrays is non-idiomatic and quite slow. In all cases, a vectorized approach is preferred if possible, and it is often possible.

For instance, on common situation is a sliding window, such as setting each pixel in an image to the average of the values of the pixels around it. Then name “sliding window” brings up the image of iteratively moving a window around the array, and a double for loop over the 2D indices:

   for i in range(1, lenX):
        for j in range(1, lenY):
            arr[i, j] = 0.25 * (arr[i+1][j] + arr[i-1][j] + arr[i][j+1] + arr[i][j-1])

(there is a subtle bug here, discussed below)

Fortunately this can be accomplished with Numpy vectorized operations, which will be literally 100 times faster.

Notice that the region that is affected is arr[1:-1,1:-1]. The array that is the same shape as this and is every element to the left is arr[:-2,1:-1]. Arrays of the same shape that are above, below and to the right can be defined in a similar way. So, the vectorized solution is:

    arr[1:-1,1:-1] = .25 * (arr[:-2,1:-1] + arr[2:,1:-1] + arr[1:-1,:-2] + a[1:-1,2:])

An important note is that the operation on the right side requires the creation of an intermediate array (which Numpy handles quietly) so arr is not modified during the process, but just updated at the end. In the iterative solution, arr is modified during the operation, so for each point, the point above and to the left have already been averaged, and the points to the right and below have not yet been averaged. This is not likely what one wants. If it is, using numba or cython would be a good route to avoid a Python for loop over the array.

Leave a Reply

Your email address will not be published. Required fields are marked *