Как создать несколько изображений из одного изображения, используя шаги?

#python #image-processing #sliding-window

Вопрос:

У меня есть изображение, и я хочу разделить его на несколько изображений, используя вертикальные и горизонтальные шаги, такие как скользящее окно, и все полученные изображения будут иметь одинаковое разрешение. Как я могу сделать это эффективно в Python? Я сделал так много:

 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
 

но этот код требует слишком много оперативной памяти и отнимает слишком много времени. Пожалуйста, помогите.

Пример :

Пример кода : img = sliding_window(im, 200, 300)

Следующее изображение имеет размер 800*800.

Оригинальное Изображение

Выход :

Пример вывода

Комментарии:

1. Пожалуйста, покажите минимальный пример того, что вы хотите. Действительно ли код, который вы показываете, работает?

2. вы отображаете его с помощью matplotlib, чтобы вы могли загружать изображение как numpy.array и просто использовать img[y:y 200, x:x 200] , чтобы получить часть изображения и отобразить его — и это должно работать быстрее. Он не дублирует изображение, но использует данные из исходного массива. В конечном итоге вы можете скопировать его с помощью img[y:y 200, x:x 200].copy()

3. если вы сделали только некоторые clculation без отображения, то, возможно, вам следует сделать это непосредственно внутри sliding_window , не сохраняя изображения в списке. Таким образом, он должен использовать меньше памяти

4. @furas Я хочу вернуть массив numpy, содержащий все возможные изображения в указанном выше формате, у меня есть несколько изображений для выполнения одного и того же действия. Спасибо за помощь.

Ответ №1:

Как вы правильно догадались, есть способ сделать это с окнами, которые просматривают исходные данные без их копирования. Самый простой способ, вероятно, заключается в использовании относительно новой sliding_window_view функции:

 from numpy.lib.stride_tricks import sliding_window_view

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

Вам не нужен явный axis для 2D-изображений, но это не повредит и избавит вас от некоторых проблем в случае 3D. Если вы хотите скорректировать шаги, вы можете просто подмножествовать результат. Например, для шага (3, 4) :

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

Поскольку оси окон должны (должны) располагаться последними в порядке C, на 3D-изображениях каналы будут перемещены на среднюю ось. Чтобы получить доступ к правильной форме, вы можете использовать что-то вроде np.moveaxis или transpose :

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

или

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