Я вижу два варианта для достижения того, что вы хотите.
- перейти к причудливой индексации
- использовать трюки с шагами
Последний быстрее, нонемного опасно (опечатка в магии настройки размеров может привести к краху вашего скрипта):
Вот пример:
import numpy as np
from numpy.lib.stride_tricks import as_strided
from scipy.misc import face
from timeit import timeit
def fancy_idx():
ino, y, x = np.ogrid[:nim,:yw,:xw]
ywo, xwo = ywoff.reshape(-1,1,1), xwoff.reshape(-1,1,1)
return im[ino, ywo+y, xwo+x]
def stride_trx():
nim, y, x = im.shape
st = im.strides
wins = as_strided(im, (nim, y-yw+1, x-xw+1, yw, xw), (*st, *st[1:]))
return wins[np.arange(nim), ywoff, xwoff]
# set up example
# use the scipy example image
# use the color channels (RGB) as individual images
im = np.ascontiguousarray(np.moveaxis(face(), 2, 0))
nim = len(im)
# set the window height and width
yw, xw = 150, 200
# set the top left corners for window in each image
ywoff, xwoff = np.array([[510,530,520],[700,720,750]])
# test
assert (fancy_idx()==stride_trx()).all()
print(timeit(fancy_idx, number=1000))
print(timeit(stride_trx, number=1000))
Пример выполнения:
0.4873827249975875 # fancy indexing
0.028213004930876195 # stride tricks
Некоторыеобъяснение:
- необычное индексирование: этот метод обращается к каждому пикселю индивидуально, это гибкий и безопасный, но медленный
трюк шага: этот метод быстрее, потому что только верхний левый уголкаждого окна адресуется причудливо, сами окна создаются путем нарезки
как это работает?по сути, мы создаем 5D массив путем дублирования (в админке, а не в данных) осей y и x.Таким образом, мы можем использовать первую копию y и x, чтобы выбрать смещения, и вторую копию y и x, чтобы нарезать