У меня есть начальный массив (а), и я использую циклы для создания новой матрицы (б), где каждый элемент представляет собой сумму каждого уникального подмассива n*n (0+1+5+6=12, 1+2+ 6+7=16, ...). Могу ли я добиться того же результата без использования циклов с помощью встроенных методов Numpy? Я попробовал np.reshape, но не могу посчитать с его помощью пересекающиеся подмассивы.
Код с использованием циклов:
import numpy as np
a = np.array([[ 0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19], [15, 16, 17, 18, 20]])
n = 2
b = np.empty([0, np.size(a[0])-n+1], int)
for row in range(0, np.size(a[0])-n+1):
temp_list = []
for col in range(0, np.size(a[0])-n+1):
temp_list.append(np.sum(a[row:row+n, col:col+n]))
b = np.vstack([b, [np.array(temp_list)]])
print('Input (a):')
print(a)
print('Output (b):')
print(b)
Результат:
Input (a):
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]
[15 16 17 18 20]]
Output (b):
[[12 16 20 24]
[32 36 40 44]
[52 56 60 64]
[62 66 70 75]]
По сути, это двумерная свертка с квадратным фильтром:
import numpy as np
from scipy.signal import convolve2d
a = np.array([[ 0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19], [15, 16, 17, 18, 20]])
n = 2
f = np.ones((n,n))
convolve2d(a, f, mode='valid')
выход:
array([[12., 16., 20., 24.],
[32., 36., 40., 44.],
[52., 56., 60., 64.],
[62., 66., 70., 75.]])
Если вас волнует целочисленный вывод, просто используйте его f = np.ones((n,n), dtype=int)
Если вы хотите сделать все это с помощью numpy, вы можете использовать скользящий_оконный_вид , например,
a = np.array([[ 0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19], [15, 16, 17, 18, 20]])
n = 2
x = np.lib.stride_tricks.sliding_window_view(a, (n, n))
x = x.reshape(x.shape[0:2] + (-1,)) # flatten last two dimensions
x = np.sum(x, axis=-1) # sum final dimension
print(x)
[[12 16 20 24]
[32 36 40 44]
[52 56 60 64]
[62 66 70 75]]
Спасибо! Есть ли способ сделать то же самое, используя только numpy?