Ventana móvil vectorizada en matriz 2D en números

Estoy aplicando una operación en una ventana móvil de tamaño constante a través de una matriz 2D. ¿Existe una operación eficiente de vectorización que pueda implementar para hacer esto sin hacer un bucle en Python? Mi estructura actual se ve algo como esto

for i in range(1,xmax-1): for j in range(1,ymax-1): out[i][j] = f(in[i][j],in[i+1][j],in[i-1][j],in[i][j+1],in[i][j-1],...) 

Los comentarios que se dejan en esta pregunta aluden a la posibilidad de vectorizar esta operación, pero sin más detalles, la indexación / rebanado vectorizado en números y caracteres?

Si puedes express la función.

 f(in[i][j],in[i+1][j],in[i-1][j],in[i][j+1],in[i][j-1],…) 

como operador lineal, puede usar la función signal.convolve2d de scipy para hacer exactamente eso. Por ejemplo, supongamos que tiene una matriz 50×50, A, y desea calcular una segunda matriz B donde cada uno de sus elementos b[ij] es el promedio de a[i,j], a[(i-1),j], a[i,(j-1)], a[(i-1),(j-1)] de la matriz A. Puedes hacer eso simplemente haciendo:

 A = # your first array B = numpy.ones((2,2))/4 C = scipy.signal.convolve2d(A,B, 'valid') 

Cuando se realiza la convolución, la matriz B “se desliza” a través de A, multiplicando los elementos correspondientes y resumiendo el resultado. Debido a los efectos de borde, debe tener cuidado al usar la matriz resultante C. Aquí, C tiene la forma 49×49, debido al argumento 'valid' en convolve2d , para descartar la primera fila y columna ya que contienen efectos de borde. Si quisiera tener una matriz de 50×50, sin descartarla, intercambiaría ese argumento por 'same'

EDITAR : Tal vez si pudiera decirme más acerca de la función que necesita, podría ayudarlo más específicamente a convertirla en una matriz que se usaría para hacer la convolución 2D.

¡Espero que ayude!

Puede utilizar la técnica de ventana móvil como se explica aquí , aquí y aquí , pero para la matriz 2D. El código fuente de la ventana móvil 2D en NumPy:

 # Rolling window for 2D arrays in NumPy import numpy as np def rolling_window(a, shape): # rolling window for 2D array s = (a.shape[0] - shape[0] + 1,) + (a.shape[1] - shape[1] + 1,) + shape strides = a.strides + a.strides return np.lib.stride_tricks.as_strided(a, shape=s, strides=strides) a = np.array([[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 7, 8], [18, 19, 20, 21, 13, 14], [24, 25, 26, 27, 19, 20], [30, 31, 32, 33, 34, 35]], dtype=np.int) b = np.arange(36, dtype=np.float).reshape(6,6) present = np.array([[7,8],[13,14],[19,20]], dtype=np.int) absent = np.array([[7,8],[42,14],[19,20]], dtype=np.int) found = np.all(np.all(rolling_window(a, present.shape) == present, axis=2), axis=2) print(np.transpose(found.nonzero())) found = np.all(np.all(rolling_window(b, present.shape) == present, axis=2), axis=2) print(np.transpose(found.nonzero())) found = np.all(np.all(rolling_window(a, absent.shape) == absent, axis=2), axis=2) print(np.transpose(found.nonzero())) 

La matriz present se produce en la matriz dos veces en [1,1] y [2,4].