Вы можете добиться этого с помощью комбинации np.reshape
и < href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.swapaxes.html" rel="noreferrer">np.swapaxes
вот так -
def extract_blocks(a, blocksize, keep_as_view=False):
M,N = a.shape
b0, b1 = blocksize
if keep_as_view==0:
return a.reshape(M//b0,b0,N//b1,b1).swapaxes(1,2).reshape(-1,b0,b1)
else:
return a.reshape(M//b0,b0,N//b1,b1).swapaxes(1,2)
Как видно, есть два способа его использования - с выключенным флагом keep_as_view
(по умолчанию) или включенным. С keep_as_view = False
мы изменяем форму переставленных осей до конечного результата 3D
, а с keep_as_view = True
мы сохраняем его 4D, и это будет представление во входной массив и, следовательно, практически бесплатно во время выполнения. Позже мы проверим это на тестовом примере.
Примеры случаев
Давайте используем образец входного массива, например:
In [94]: a
Out[94]:
array([[2, 2, 6, 1, 3, 6],
[1, 0, 1, 0, 0, 3],
[4, 0, 0, 4, 1, 7],
[3, 2, 4, 7, 2, 4],
[8, 0, 7, 3, 4, 6],
[1, 5, 6, 2, 1, 8]])
Теперь давайте используем некоторые размеры блоков для тестирования. Давайте использовать размер блока (2,3)
с выключенным и включенным флагом просмотра -
In [95]: extract_blocks(a, (2,3)) # Blocksize : (2,3)
Out[95]:
array([[[2, 2, 6],
[1, 0, 1]],
[[1, 3, 6],
[0, 0, 3]],
[[4, 0, 0],
[3, 2, 4]],
[[4, 1, 7],
[7, 2, 4]],
[[8, 0, 7],
[1, 5, 6]],
[[3, 4, 6],
[2, 1, 8]]])
In [48]: extract_blocks(a, (2,3), keep_as_view=True)
Out[48]:
array([[[[2, 2, 6],
[1, 0, 1]],
[[1, 3, 6],
[0, 0, 3]]],
[[[4, 0, 0],
[3, 2, 4]],
[[4, 1, 7],
[7, 2, 4]]],
[[[8, 0, 7],
[1, 5, 6]],
[[3, 4, 6],
[2, 1, 8]]]])
Подтвердить view
с помощью keep_as_view=True
In [20]: np.shares_memory(a, extract_blocks(a, (2,3), keep_as_view=True))
Out[20]: True
Давайте проверим производительность на большом массиве и проверим утверждение о практически бесплатном времени выполнения, как обсуждалось ранее.
In [42]: a = np.random.rand(2000,3000)
In [43]: %timeit extract_blocks(a, (2,3), keep_as_view=True)
1000000 loops, best of 3: 801 ns per loop
In [44]: %timeit extract_blocks(a, (2,3), keep_as_view=False)
10 loops, best of 3: 29.1 ms per loop
person
Divakar
schedule
21.07.2015
y
— это массив патчей. Чтобы получить доступ к патчу, используйтеy[j, :, k, :]
. В вашем случае исходного массива с формой (36, 72)j
будет варьироваться от 0 до 17, аk
будет варьироваться от 0 до 35. - person Warren Weckesser   schedule 21.07.2015a
, вы можете просто использоватьa[2*j:2*j+2, 2*k:2*k+2]
. Это то, что вы имели ввиду? - person Warren Weckesser   schedule 21.07.2015y
в другом ответе можно интерпретировать как двумерный массив двумерных патчей. Если это не сработает для вас, не могли бы вы изменить вопрос, чтобы более четко указать желаемую структуру данных, которую вы хотите получить в конце? Может быть, список 2-мерных массивов Python? Что-то другое? Что вы собираетесь делать с этой коллекцией патчей? (Желательно, чтобы вы отредактировали вопрос, чтобы уточнить, а не объяснять его здесь, в комментариях.) - person Warren Weckesser   schedule 21.07.2015