Сумма разностей квадратов (SSD) в numy / scipy - PullRequest
7 голосов
/ 18 февраля 2010

Я пытаюсь использовать Python и Numpy / Scipy для реализации алгоритма обработки изображений. Профилировщик говорит мне, что много времени тратится на следующую функцию (часто вызываемую), которая сообщает мне сумму разностей квадратов между двумя изображениями

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

Как я могу ускорить это? Спасибо.

Ответы [ 6 ]

35 голосов
/ 18 февраля 2010

Just

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

(что, скорее всего, просто sum((A-B)**2), если форма всегда (, , 3))

Вы также можете использовать метод суммы: ((A-B)**2).sum()

правый

1 голос
/ 23 февраля 2010

В дополнение к ответу Рицерта Хорнстры, который получил 2 отрицательных оценки (по общему признанию, я не видел его в его оригинальной форме ...)

Это действительно так.

Для большого количества итераций часто может потребоваться вдвое больше времени, чтобы использовать оператор ** или метод pow (x, y), чтобы просто вручную умножить пары вместе. Если необходимо, используйте метод math.fabs (), если он выбрасывает NaN (что иногда бывает особенно при использовании int16s и т. Д.), И он все еще занимает примерно половину времени двух указанных функций.

Не так важно для первоначального вопроса, который я знаю, но определенно стоит знать.

1 голос
/ 18 февраля 2010

Я запутался, почему вы принимаете i in range(3). Это должен быть весь массив или только часть?

В целом, вы можете заменить большинство из них операциями, определенными в numpy:

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

Таким образом, вы можете выполнить одну операцию вместо трех, а numpy.sum может оптимизировать добавление лучше, чем встроенный sum.

1 голос
/ 18 февраля 2010

Я не знаю, будет ли функция pow () с мощностью 2 работать быстро. Попробуйте:

def ssd(A,B):
    s = 0
    for i in  range(3):
        s += sum((A[:,:,i] - B[:,:,i])*A[:,:,i] - B[:,:,i])
    return s
0 голосов
/ 27 апреля 2018

Вы можете попробовать это:

dist_sq = np.sum((A[:, np.newaxis, :] - B[np.newaxis, :, :]) ** 2, axis=-1)

Более подробную информацию можно найти здесь (пример «k-Nearest Neighbours»): https://jakevdp.github.io/PythonDataScienceHandbook/02.08-sorting.html

0 голосов
/ 29 января 2015

На языке Ruby вы можете достичь этого следующим образом

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