2013-06-03 11 views
6

Per quanto ho visto, questi metodi sono entrambi implementati come funzioni C nelle rispettive DLL e sembra che la versione ndimage sia più veloce (nessuna implementazione usa codice parallelizzato, come le chiamate a blas o MKL).Qual è la differenza tra scipy.ndimage.filters.convolve e scipy.signal.convolve?

Inoltre, quando ho provato a verificare che restituiscano gli stessi risultati eseguendo il seguente codice, l'asserzione di uguaglianza non è riuscita. Non sono riuscito a capire dalla documentazione quali sarebbero esattamente le differenze funzionali tra i due metodi (la documentazione non è molto chiara su cosa sia 0 in relazione alla posizione dell'origine del kernel, dagli esempi, ho dedotto che è nel centro, ma potrei sbagliarmi).

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)) 

Grazie!

+1

Non conosco le implementazioni, ma probabilmente l'implementazione da ndimage utilizza il teorema della convoluzione, cioè la convoluzione è uguale alla moltiplicazione nello spazio di Fourier. Questo è ciò che scipy.signal.fftconvolve fa. Ma anche quando si usa questo metodo invece di convolve, l'asserzione fallisce. –

+1

Mi sembra che entrambi stiano usando le implementazioni dirette. Credo che il codice che viene chiamato alla fine sia [qui] (https://github.com/scipy/scipy/blob/master/scipy/signal/correlate_nd.c.src#L105) e [qui] (https : //github.com/scipy/scipy/blob/master/scipy/ndimage/src/ni_filters.c#L132), rispettivamente. Ho provato a chiamare i metodi su array interi per escludere errori di arrotondamento ecc., Ma l'asserzione fallisce pure. – bbudescu

+1

L'asserzione fallisce anche sugli array 2d, ma solo se il kernel è maggiore di una certa dimensione, ad es. 'a = random.random_integers (0,10, (100, 100)); b = random.random_integers (0,10, (7, 7))' non fallisce, ma quando 'b = random.random_integers (0 , 10, (8, 8)) ', lo fa. qualche idea? – bbudescu

risposta

9

Le due funzioni hanno diverse convenzioni per gestire il confine. Per effettuare le chiamate funzionalmente lo stesso, aggiungere l'argomento origin=-1 o origin=(-1,-1,-1) per la chiamata 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 

sposta solo l'origine, quando le dimensioni del b sono ancora. Quando sono dispari, le funzioni sono d'accordo quando si utilizza il default 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 
+0

Se a e b hanno dimensioni diverse (modulo 2), ad es. se una ha dimensione (100,100) e b ha dimensione (11,11), la soluzione di cui sopra non è corretta. In questo caso l'origine dovrebbe essere (0,0) per le due funzioni da concordare –

+0

@JensMunk Che cosa hai testato esattamente? Se convolvi una matrice (1000,1000) con una matrice (11,11) con 'origine = 0', i risultati sono molto vicini (essenzialmente la stessa esatta precisione numerica). Questo è ciò che la risposta dice di fare se 'b' è dispari. – user3731622

+0

Proprio così.Se hanno le stesse dimensioni del modulo 2, l'origine dovrebbe essere (1,1) per quanto mi ricordo. –

3

c'è una differenza molto importante. L'implementazione nel pacchetto di immagini sembra essere la tipica versione limitata utilizzata nell'elaborazione delle immagini per ottenere la "stessa" dimensione dell'immagine dopo la convoluzione. Quindi coincide con la 'stessa' opzione nel pacchetto di elaborazione del segnale se usiamo la modalità = 'costante', come negli esempi sopra. Il pacchetto di elaborazione del segnale sembra implementare la vera definizione rigorosa dell'operatore di convoluzione. Forse per questo motivo è più lento. Trova racchiusi alcuni esempi con risultati completamente diversi.

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]]) 

Si noti che l'implementazione del pacchetto di elaborazione del segnale è conmutativa, come previsto per una convoluzione corretta. Tuttavia, l'implementazione nel pacchetto immagine non lo è e fornisce una soluzione con le stesse dimensioni del primo parametro.

Problemi correlati