python - ¿Cuál es la diferencia entre scipy.ndimage.filters.convolve y scipy.signal.convolve?
multidimensional-array convolution (2)
Hasta donde he visto, estos métodos se implementan como funciones C en las respectivas DLL, y parece que la versión ndimage
es más rápida (ninguna implementación usa código paralelizado, como llamadas a blas o MKL).
Además, cuando intenté comprobar que devuelven los mismos resultados ejecutando el siguiente código, la afirmación de igualdad falló. No pude deducir de la documentación cuáles serían exactamente las diferencias funcionales entre los dos métodos (la documentación no es muy clara acerca de qué significa 0
relación con la ubicación del origen del kernel; de los ejemplos, deduje que está en el centro, pero podría estar equivocado).
from numpy import random, allclose
from scipy.ndimage.filters import convolve as convolveim
from scipy.signal import convolve as convolvesig
a = random.random((100, 100, 100))
b = random.random((10,10,10))
conv1 = convolveim(a,b, mode = ''constant'')
conv2 = convolvesig(a,b, mode = ''same'')
assert(allclose(conv1,conv2))
¡Gracias!
Las dos funciones tienen diferentes convenciones para tratar con el límite. Para que sus llamadas sean funcionalmente iguales, agregue el argumento origin=-1
u origin=(-1,-1,-1)
a la llamada a convolveim
:
In [46]: a = random.random((100,100,100))
In [47]: b = random.random((10,10,10))
In [48]: c1 = convolveim(a, b, mode=''constant'', origin=-1)
In [49]: c2 = convolvesig(a, b, mode=''same'')
In [50]: allclose(c1,c2)
Out[50]: True
Solo cambie el origen cuando las dimensiones de b
sean pares. Cuando son impares, las funciones coinciden cuando se usa el origin=0
predeterminado origin=0
:
In [88]: b = random.random((11,11,11))
In [89]: c1 = convolveim(a, b, mode=''constant'')
In [90]: c2 = convolvesig(a, b, mode=''same'')
In [91]: allclose(c1,c2)
Out[91]: True
Hay una diferencia muy importante La implementación en el paquete de imágenes parece ser la versión restringida típica utilizada en el procesamiento de imágenes para lograr el "mismo" tamaño de la imagen después de la convolución. Por lo tanto, coincide con la "misma" opción en el paquete de procesamiento de señal si usamos el modo = ''constante'', como en los ejemplos anteriores. El paquete de procesamiento de señales parece implementar la definición estricta real del operador de convolución. Quizás por esta razón es más lento. Encuentra encerrado algunos ejemplos con resultados completamente diferentes.
In [13]: a=array([[1,2,1]])
In [14]: b=array([[1],[2],[1]])
In [17]: convolveim(a,b)
Out[17]: array([[4, 8, 4]])
In [18]: convolveim(b,a)
Out[18]:
array([[4],
[8],
[4]])
In [19]: convolvesig(a,b)
Out[19]:
array([[1, 2, 1],
[2, 4, 2],
[1, 2, 1]])
In [20]: convolvesig(b,a)
Out[20]:
array([[1, 2, 1],
[2, 4, 2],
[1, 2, 1]])
Tenga en cuenta que la implementación del paquete de procesamiento de señal es conmutativa, como se esperaba para una convolución correcta. Sin embargo, la implementación en el paquete de imágenes no lo es y proporciona una solución con las ''mismas'' dimensiones que el primer parámetro.