2

I have a numpy array with a size of 240 x 320 x 3 and I want to use a window (window size ws=5) to slide over each pixel and crop out the subarray centered at that pixel. The final output dimension should be 240 x 320 x ws x ws x 3. So I pad the original array with window size and use for loop to do so.

height = 240
width = 320
image = np.random.rand((height, width, 3))
image = np.pad(image, ((ws//2, ws//2), (ws//2, ws//2), (0, 0)), mode='reflect')
patches = np.zeros((height, width, ws, ws, 3))
for i in range(height):
    for j in range(width):
        patches[i, j] = image[i:i+ws, j:j+ws]

Are there any ways to do the cropping of each pixel at the sample time? Like without using the for loop over each pixel?

Divakar
  • 218,885
  • 19
  • 262
  • 358
Qimin Chen
  • 197
  • 8

1 Answers1

2

You are basically getting sliding windows across the image. We can leverage np.lib.stride_tricks.as_strided based scikit-image's view_as_windows to get sliding windows. More info on use of as_strided based view_as_windows.

from skimage.util.shape import view_as_windows

out = view_as_windows(image,(ws,ws,1)).transpose(0,1,4,3,2,5)[:-1,:-1,...,0]

# Alternatively :
out = view_as_windows(image,(ws,ws,1))[:-1,:-1,...,0].transpose(0,1,4,3,2)

Also note that you are missing out on the last possible window, if you had for i in range(height+1) and for j in range(width+1). To get the same result with our solution, the last indexing step would modify to [...,0] in place of [:-1,:-1,...,0], thus giving us -

out = view_as_windows(image,(ws,ws,1))[...,0].transpose(0,1,4,3,2)
Divakar
  • 218,885
  • 19
  • 262
  • 358