2

I have a 2D numpy array input_array and two lists of indices (x_coords and y_coords). Id like to slice a 3x3 subarray for each x,y pair centered around the x,y coordinates. The end result will be an array of 3x3 subarrays where the number of subarrays is equal to the number of coordinate pairs I have.

Preferably by avoiding for loops. Currently I use a modification of game of life strides from the scipy cookbook: http://wiki.scipy.org/Cookbook/GameOfLifeStrides

shape = (input_array.shape[0] - 2, input_array.shape[0] - 2, 3, 3)
strides = input_array.strides + input_array.strides
strided = np.lib.stride_trics.as_strided(input_array, shape=shape, strides=strides).\
    reshape(shape[0]*shape[1], shape[2], shape[3])

This creates a view of the original array as a (flattened) array of all possible 3x3 subarrays. I then convert the x,y coordinate pairs to be able to select the subarrays I want from strided:

coords = x_coords - 1 + (y_coords - 1)*shape[1]
sub_arrays = strided[coords]

Although this works perfectly fine, I do feel it is a bit cumbersome. Is there a more direct approach to do this? Also, in the future I would like to extend this to the 3D case; slicing nx3x3 subarrays from a nxmxk array. It might also be possible using strides but so far I haven't been able to make it work in 3D

2 Answers 2

3

Here is a method that use array broadcast:

x = np.random.randint(1, 63, 10)
y = np.random.randint(1, 63, 10)

dy, dx = [grid.astype(int) for grid in np.mgrid[-1:1:3j, -1:1:3j]]
Y = dy[None, :, :] + y[:, None, None]
X = dx[None, :, :] + x[:, None, None]

then you can use a[Y, X] to select blocks from a. Here is an example code:

img = np.zeros((64, 64))
img[Y, X] = 1

Here is graph ploted by pyplot.imshow():

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

0

A very straight forward solution would be a list comprehension and itertools.product:

import itertools

sub_arrays = [input_array[x-1:x+2, y-1:y+2] 
              for x, y in itertools.product(x_coords, y_coords)]

This creates all possible tuples of coordinates and then slices the 3x3 arrays from the input_array. But this is sort-of a for loop. And you will have to take care, that x_coords and y_coords are not on the border of the matrix.

1 Comment

x_coords and y_coords are pre-checked and the ones on the border I leave out. Also, I had to replace itertools.product with zip in order to get the desired result.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.