как выполнить обратную корреляцию / свертку в python - PullRequest
0 голосов
/ 23 января 2020

Я пытаюсь выполнить обратную корреляцию (по крайней мере, так я думаю, это называется) для 2 матриц, чтобы получить результирующую матрицу.

Примечание: обратная свертка тоже работает, потому что я применяю это к CNN.

У меня есть следующие две матрицы:

vals:

[[ 2  1 -3 -4 -4]
 [ 2 -3  3  1  2]
 [ 2  5 -6  6 -2]
 [-5  4  1  5  4]
 [ 0  0  1 -3 -4]]

w0:

[[[0,  1, -1],
  [1, -1,  0],
  [0,  0,  0]],

 [[1,  0,  0],
  [0, -1,  1],
  [1,  0,  1]],

 [[ 1, -1,  0],
  [-1,  0, -1],
  [-1,  0,  1]]]

Я по существу хотите применить скользящее окно, за исключением того, что в этом случае все значения w0 умножаются на скалярное значение в каждой точке в vals, а затем добавляются со смежными значениями.

При условии шага 1 и заполнение того же (wrt vals), следующий код дает желаемый результат:

concat = np.zeros((3,7,7))
for k in range(len(w0)):
    for i in range(len(vals)):
        for j in range(len(vals[i])):
            v = w0[k] * vals[i][j]
            concat[k][i:i+v.shape[0], j:j+v.shape[1]] += v
print(concat)

В результате:

[[[  0.   2.  -1.  -4.  -1.   0.   4.]
  [  2.   1.  -9.   5.  -2.   5.  -2.]
  [  2.  -3.   9. -13.  13. -10.   2.]
  [  2.  -2.  -2.   9.  -4.   1.  -4.]
  [ -5.   9.  -3.   5.  -5.  -5.   4.]
  [  0.   0.   1.  -4.  -1.   4.   0.]
  [  0.   0.   0.   0.   0.   0.   0.]]

 [[  2.   1.  -3.  -4.  -4.   0.   0.]
  [  2.  -5.   4.   5.   3.   0.  -4.]
  [  4.   4.  -2.  -3.  -7.  -5.  -2.]
  [ -3.  -1.   3.  14.  -3.   9.   0.]
  [  2.  10. -12.  11. -16.   7.   2.]
  [ -5.   4.  -4.   8.   9.   6.   0.]
  [  0.   0.   1.  -3.  -3.  -3.  -4.]]

 [[  2.  -1.  -4.  -1.   0.   4.   0.]
  [  0.  -6.   7.   1.   8.   2.   4.]
  [ -2.   5. -11.  19. -12.  -3.  -6.]
  [ -9.   7.   0. -11.   8.  -9.   4.]
  [  3.  -9.  13. -14. -10.   5.  -6.]
  [  5.  -4.  -7.   2.   0.   8.   8.]
  [  0.   0.  -1.   3.   5.  -3.  -4.]]]

, который я бы затем уменьшил, чтобы исключить заполнение , так:

print(concat[:,1:-1, 1:-1])

>>> [[[  1.  -9.   5.  -2.   5.]
      [ -3.   9. -13.  13. -10.]
      [ -2.  -2.   9.  -4.   1.]
      [  9.  -3.   5.  -5.  -5.]
      [  0.   1.  -4.  -1.   4.]]

     [[ -5.   4.   5.   3.   0.]
      [  4.  -2.  -3.  -7.  -5.]
      [ -1.   3.  14.  -3.   9.]
      [ 10. -12.  11. -16.   7.]
      [  4.  -4.   8.   9.   6.]]

     [[ -6.   7.   1.   8.   2.]
      [  5. -11.  19. -12.  -3.]
      [  7.   0. -11.   8.  -9.]
      [ -9.  13. -14. -10.   5.]
      [ -4.  -7.   2.   0.   8.]]]

Подойдет любой из двух результатов для concat, но желательно тот, который включает отступы.

Кто-нибудь знает способ сделать это без используя python петли? Я бы предпочел использовать numpy или какую-либо другую библиотеку, поскольку она должна выполнять те же вычисления быстрее, чем мой код.

РЕДАКТИРОВАТЬ:

Я также хочу выполнить тот же вид обратная корреляция на w0, поэтому снова используется vals, но вместо этого:

a:

[[[2, 0, 2, 2, 2],
  [1, 1, 0, 2, 0],
  [0, 0, 1, 2, 2],
  [2, 2, 2, 0, 0],
  [1, 0, 1, 2, 0]],

 [[1, 2, 1, 0, 1],
  [0, 2, 0, 0, 1],
  [0, 0, 2, 2, 1],
  [2, 0, 1, 0, 2],
  [0, 1, 2, 2, 2]],

 [[0, 0, 2, 2, 2],
  [0, 1, 2, 1, 0],
  [0, 0, 0, 2, 0],
  [0, 2, 0, 0, 2],
  [0, 0, 2, 2, 1]]]

И в этом случае выполняется скользящее окно 3x3 вдоль a с заполнение 1, и умножение всех значений в скользящем окне на связанный индекс скалярного значения в vals, и, наконец, получение вывода того же размера, что и w0. Следующий код достигает этого:

concat = np.zeros((3,3,3))
for k in range(len(w0)):
    f = np.pad(a[k], 1)
    for i in range(len(vals)):
        for j in range(len(vals[i])):
            v = f[i:i+w0.shape[1], j:j+w0.shape[2]] * vals[i][j]
            concat[k] += v

с:

print(concat)
>>>[[[  4.  56.   8.]
     [  1. -20.   1.]
     [ 22.  12.  21.]]

    [[  7.  18.  21.]
     [  5. -22.  20.]
     [ 35.  26.  33.]]

    [[ 20.  13.   4.]
     [-25.   2. -26.]
     [ -5.  15.  38.]]]

Ответы [ 2 ]

1 голос
/ 04 февраля 2020

scipy.signal s convolve на самом деле то, что вы хотите:

from scipy.signal import convolve

convolve(vals[None, :, :], w0)[:, 1:-1, 1:-1]
Out[]: 
array([[[  1,  -9,   5,  -2,   5],
        [ -3,   9, -13,  13, -10],
        [ -2,  -2,   9,  -4,   1],
        [  9,  -3,   5,  -5,  -5],
        [  0,   1,  -4,  -1,   4]],

       [[ -5,   4,   5,   3,   0],
        [  4,  -2,  -3,  -7,  -5],
        [ -1,   3,  14,  -3,   9],
        [ 10, -12,  11, -16,   7],
        [  4,  -4,   8,   9,   6]],

       [[ -6,   7,   1,   8,   2],
        [  5, -11,  19, -12,  -3],
        [  7,   0, -11,   8,  -9],
        [ -9,  13, -14, -10,   5],
        [ -4,  -7,   2,   0,   8]]])
0 голосов
/ 04 февраля 2020

Вы можете взглянуть на scipy.ndimage.filters.convolve

Например:

>>> a = np.array([[1, 2, 0, 0],
....    [5, 3, 0, 4],
....    [0, 0, 0, 7],
....    [9, 3, 0, 0]])
>>> k = np.array([[1,1,1],[1,1,0],[1,0,0]])
>>> from scipy import ndimage
>>> ndimage.convolve(a, k, mode='constant', cval=0.0)
array([[11, 10,  7,  4],
       [10,  3, 11, 11],
       [15, 12, 14,  7],
       [12,  3,  7,  0]])
...