2010-02-17 6 views
7

J'essaie d'utiliser Python et Numpy/Scipy pour implémenter un algorithme de traitement d'image. Le profileur me dit beaucoup de temps est consacré à la fonction suivante (souvent appelé), qui me dit la somme des différences entre deux images carréesSomme des différences carrées (SSD) dans numpy/scipy

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

Comment puis-je accélérer ce? Merci.

Répondre

27

Juste

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

(qui je pense est probablement juste sum((A-B)**2) si la forme est toujours (,, 3))

Vous pouvez également utiliser la méthode de la somme: ((A-B)**2).sum()

Droite?

+2

Bang. Je passe une journée lente. Réduit de moitié mon temps de course. –

+0

Il est à noter que pour cela, vous devrez utiliser 'numpy.sum', pas la somme interne, qui trouvera la somme sur la première dimension et retournera un nouveau tableau de dimension inférieure. –

+0

((A-B) ** 2) .sum (-1) Si vous voulez seulement ajouter le dernier axe, alors l'argument de l'axe doit être spécifié. Le simple fait d'utiliser sum() ajoute toutes les entrées du tableau (en premier). – user333700

1

Je ne sais pas si la fonction pow() avec l'alimentation 2 sera rapide. Essayez:

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

Je suis confus pourquoi vous prenez i in range(3). Est-ce censé être tout le tableau, ou juste une partie?

Dans l'ensemble, vous pouvez remplacer la plupart de cela avec les opérations définies dans numpy:

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

De cette façon, vous pouvez faire une seule opération au lieu de trois et en utilisant numpy.sum peut-être en mesure d'optimiser l'ajout mieux que le builtin sum .

+2

+1 Voici comment 'scipy.stats.stats.ss' (somme des carrés) le fait. – unutbu

1

Suite à la réponse de Ritsaert Hornstra qui a obtenu 2 points négatifs (il est vrai que je ne l'ai pas vu dans sa forme originale ...)

Ceci est en fait vrai.

Pour un grand nombre d'itérations, il faut souvent deux fois plus de temps pour utiliser l'opérateur '**' ou la méthode pow (x, y) que pour multiplier manuellement les paires. Si nécessaire, utilisez la méthode math.fabs() si elle rejette des NaN (ce qui est parfois le cas surtout lorsque vous utilisez int16s, etc.), et cela prend seulement environ la moitié du temps des deux fonctions données.

Pas si important pour la question initiale que je connais, mais ça vaut vraiment la peine d'être connu.

-3

Dans le langage Ruby vous pouvez y parvenir de cette manière

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