сумма квадратов (4 значения, формирующие квадрат) в 2d массиве numpy. Python

#python #numpy

#python #numpy

Вопрос:

Я хочу суммировать каждую комбинацию из 4 точек в 2d-массиве, который образует квадраты внутри матрицы

 in4x4 = np.array(([1,2,3,4],[2,3,4,1],[3,4,1,2],[4,3,1,2]))
print(in4x4)
array([[1, 2, 3, 4],
       [2, 3, 4, 1],
       [3, 4, 1, 2],
       [4, 3, 1, 2]])
 

Ожидаемый результат:

 print(out3x3)
array([[ 8, 12, 12],
       [12, 12,  8],
       [14,  9,  6]]
 

В настоящее время я использую numpy.diff в несколько этапов процесса. Чувствую, что должен быть более чистый подход. Пример вычисления, которое я сейчас делаю:

 diff3x4 = np.diff(a4x4,axis=0)
a3x4 = a4x4[0:3,:] * 2   d3x4
d3x3 = np.diff(a3x4)
a3x3 = a3x4[:,0:3] * 2   d3x3
 

Существует ли чистый, возможно, векторизованный подход? Скорость вызывает беспокойство. Посмотрел scipy.convolve , но, похоже, не соответствует моим целям, но, возможно, я просто неправильно настраиваю ядро.

Ответ №1:

Вы можете выполнить 2-мерную свертку с несколькими единицами для достижения желаемого результата.

Простой код, который реализует 2D-свертку и проверяет введенные вами данные:

 import numpy as np

def conv2d(a, f):
    s = f.shape   tuple(np.subtract(a.shape, f.shape)   1)
    strd = np.lib.stride_tricks.as_strided
    subM = strd(a, shape = s, strides = a.strides * 2)
    return np.einsum('ij,ijkl->kl', f, subM)

in4x4 = np.array(([1,2,3,4],[2,3,4,1],[3,4,1,2],[4,3,1,2]))
k = np.ones((2,2))

print(conv2d(in4x4, k))
 

вывод:

 [[ 8. 12. 12.]
 [12. 12.  8.]
 [14.  9.  6.]]
 

В случае, если вы можете использовать встроенную функцию, вы можете использовать, как показано ниже:

 import numpy as np
from scipy import signal
in4x4 = np.array(([1,2,3,4],[2,3,4,1],[3,4,1,2],[4,3,1,2]))
k = np.ones((2,2))
signal.convolve2d(in4x4, k, 'valid')
 

Какой вывод:

 array([[ 8., 12., 12.],
       [12., 12.,  8.],
       [14.,  9.,  6.]])
 

signal.convolve2d(in4x4, k, ‘valid’)

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

1. Спасибо, что это на 95%. Но как мне выразить форму k программно. Если это половина размеров in4x4, то это будет работать только для четных числовых фигур? например: k = np.ones((int(in4x4.shape[0]/ 2),int(in4x4.shape[1]/2))). ?? Говоря о 2-м подходе

2. Что значит определять k программно? Вам все равно потребуется свернуть, но, возможно, потребуется поиграть с параметром convolve2d

3. Я имел в виду, что в моем реальном приложении это не массив 4×4, поэтому мне нужно вычислить k на основе фактической формы, которая может измениться. np.ones((int(in4x4.shape[0]/ 2),int(in4x4.shape[1] / 2))). это казалось неуклюжим, но, похоже, работает с массивами разного размера.