How to create multiple images from a single image using strides?

Viewed 664

I have an image and I want to split it into multiple images using vertical and horizontal strides like a sliding window and the resultant images will all be of same resolution. How can I do that efficiently in Python? I have done this much:

from PIL import Image

def sliding_window(image, stride, imgSize):
    width, height = image.size
    img = []
    for y in range(0, height-imgSize, stride):
        for x in range(0, width-imgSize, stride):
            # Setting the points for cropped image
            left = x
            top = y
            right = x + imgSize
            bottom = y + imgSize
            im1 = image.crop((left, top, right, bottom))
            img.append(im1)
    return img
file = "/home/xxxxxx/yyyyyy.png"
im = Image.open(file)
img = sliding_window(im, 1, 838) # Strides of 1 takes too much time

but this code requires too much RAM and is too time consuming. Please help.

Example :

Sample code : img = sliding_window(im, 200, 300)

The following image is of 800*800 size.

Original Image

Output :

Sample output

1 Answers

As you correcly surmised, there is a way to do this with windows that view the original data without copying it. The simplest way is probably to use the relatively new sliding_window_view function:

from numpy.lib.stride_tricks import sliding_window_view

window = sliding_window_view(image, (838, 838), axis=(0, 1))

You don't need an explicit axis for 2D images, but it doesn't hurt and saves you some trouble in the 3D case. If you wanted to adjust the strides, you can just subset the result. For example, for a stride of (3, 4):

window = window[::3, ::4]

Since the window axes must (should) come last in C order, 3D images will have the channels moved to the middle axis. To access the correct shape, you can use something like np.moveaxis or transpose:

np.moveaxis(window[80, 70], 0, -1)

OR

window[80, 70].transpose(1, 2, 0).shape
Related