2010-02-17 5 views
7

Sto cercando di utilizzare Python e Numpy/Scipy per implementare un algoritmo di elaborazione delle immagini. Il profiler mi dice un sacco di tempo viene speso nella seguente funzione (chiamata spesso), che mi dice che la somma delle differenze tra due immagini quadratiSomma delle differenze quadrate (SSD) in numpy/scipy

def ssd(A,B): 
    s = 0 
    for i in range(3): 
     s += sum(pow(A[:,:,i] - B[:,:,i],2)) 
    return s 

Come posso accelerare questo? Grazie.

risposta

27

Proprio

s = numpy.sum((A[:,:,0:3]-B[:,:,0:3])**2) 

(che mi aspetto è probabile che solo sum((A-B)**2) se la forma è sempre (,, 3))

È inoltre possibile utilizzare il metodo sum: ((A-B)**2).sum()

Destra?

+2

Bang. Sto passando una giornata lenta. Dimezza il mio tempo di esecuzione. –

+0

Vale la pena notare che per questo si dovrà usare 'numpy.sum', non la' somma' incorporata, che troverà la somma sulla prima dimensione e restituirà una nuova matrice di una dimensione inferiore. –

+0

((A-B) ** 2) .sum (-1) Se si desidera aggiungere solo l'ultimo asse, è necessario specificare l'argomento dell'asse. Basta usare sum() per aggiungere tutte le voci dell'array (ravelled first) – user333700

1

Non so se la funzione pow() con alimentazione 2 sarà veloce. Prova:

def ssd(A,B): 
    s = 0 
    for i in range(3): 
     s += sum((A[:,:,i] - B[:,:,i])*A[:,:,i] - B[:,:,i]) 
    return s 
1

Sono confuso perché si sta assumendo i in range(3). Dovrebbe essere l'intero array o solo una parte?

In generale, è possibile sostituire la maggior parte di questo con operazioni definite nel NumPy:

def ssd(A,B): 
    squares = (A[:,:,:3] - B[:,:,:3]) ** 2 
    return numpy.sum(squares) 

In questo modo è possibile effettuare un'operazione invece di tre e l'utilizzo di numpy.sum può essere in grado di ottimizzare l'aggiunta migliore del incorporato sum .

+2

+1 Questo è come 'scipy.stats.stats.ss' (somma di quadrati) lo fa. – unutbu

1

seguito alla risposta del Ritsaert Hornstra che ha ottenuto 2 segni negativi (certo non ho visto che nella sua forma originale ...)

Questo è effettivamente vero.

Per un numero elevato di iterazioni può spesso impiegare il doppio del tempo per utilizzare l'operatore '**' o il metodo pow (x, y) in modo da moltiplicare manualmente manualmente le coppie. Se necessario, usa il metodo math.fabs() se butta via NaN (cosa che a volte fa specialmente quando usi int16s ecc.), E richiede solo circa la metà del tempo delle due funzioni date.

Non è così importante per la domanda originale che conosco, ma sicuramente vale la pena conoscere.

-3

Nel linguaggio Ruby è possibile raggiungere questo obiettivo in questo modo

def diff_btw_sum_of_squars_and_squar_of_sum(from=1,to=100) # use default values from 1..100. 
((1..100).inject(:+)**2) -(1..100).map {|num| num ** 2}.inject(:+) 
end 

diff_btw_sum_of_squars_and_squar_of_sum #call for above method 
Problemi correlati