2010-02-17 10 views
7

Estoy tratando de usar Python y Numpy/Scipy para implementar un algoritmo de procesamiento de imágenes. El perfilador me dice que se gasta mucho tiempo en la función siguiente (llamado a menudo), que me dice que la suma de las diferencias cuadradas entre dos imágenesSuma de diferencias cuadradas (SSD) en numpy/scipy

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

¿Cómo puedo acelerar esto verdad? Gracias.

Respuesta

27

Sólo

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

(que espero es probable que sólo sum((A-B)**2) si la forma es siempre (,, 3))

También puede utilizar el método de la suma: ((A-B)**2).sum()

¿Derecha?

+2

Bang. Estoy teniendo un día lento. Reduce a la mitad mi tiempo de ejecución. –

+0

Vale la pena señalar que para esto tendrá que usar 'numpy.sum', no la suma incorporada', que encontrará la suma sobre la primera dimensión y devolverá una nueva matriz de una dimensión inferior. –

+0

((A-B) ** 2) .sum (-1) Si solo desea agregar el último eje, entonces se debe especificar el argumento del eje. El uso de suma() agrega todas las entradas de la matriz (raveled primero) – user333700

1

No sé si la función pow() con la potencia 2 será rápida. Proveedores:

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

Estoy confundido por qué está tomando i in range(3). Se supone que es todo el conjunto, o simplemente parte?

En general, puede reemplazar la mayor parte de esto con las operaciones definidas en numpy:

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

De esta manera se puede realizar una operación en lugar de tres y utilizando numpy.sum puede ser capaz de optimizar la adición mejor que la orden interna sum .

+2

+1 Así es como 'scipy.stats.stats.ss' (suma de cuadrados) lo hace. – unutbu

1

con la respuesta de Ritsaert Hornstra que consiguió 2 puntos negativos (la verdad es que no lo vi en su forma original ...)

esto es realmente cierto.

Para una gran cantidad de iteraciones, a menudo puede tomar el doble de tiempo usar el operador '**' o el método pow (x, y) para simplemente multiplicar manualmente los pares. Si es necesario, utilice el método math.fabs() si está eliminando los NaN (que a veces lo hace especialmente cuando se usa int16s, etc.), y solo tardará aproximadamente la mitad del tiempo de las dos funciones dadas.

No es tan importante para la pregunta original que conozco, pero definitivamente vale la pena saberlo.

-3

En lenguaje Ruby se puede lograr esto de esta manera

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