numpy/scipy的方差和(SSD)

p1tboqfb  于 2023-01-05  发布在  其他
关注(0)|答案(7)|浏览(156)

我尝试使用Python和Numpy/Scipy来实现一个图像处理算法,分析器告诉我很多时间都花在了下面的函数(经常调用)上,这个函数告诉我两个图像之间的平方差之和

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

怎么才能快点?谢谢。

yhived7q

yhived7q1#

只是

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

(如果形状总是(,3),我预计可能只是sum((A-B)**2)
也可以使用求和方法:((A-B)**2).sum()
对不对?

uujelgoq

uujelgoq2#

这里只需要说明一下,我们也可以使用np.dot

def ssd(A,B):
  dif = A.ravel() - B.ravel()
  return np.dot( dif, dif )

这可能比使用np.sum**2的替代方法更快,也可能更精确,但是如果你想沿着一个指定的轴计算ssd,这就不起作用了,在这种情况下,可能有一个神奇的下标公式使用np.einsum

6ie5vjzr

6ie5vjzr3#

我很困惑你为什么要取i in range(3)。这应该是整个数组,还是只是部分数组?
总的来说,你可以用numpy中定义的操作来替换其中的大部分:

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

这样你就可以做一个操作而不是三个,并且使用numpy.sum可能比内置的sum更好地优化加法。

nnsrf1az

nnsrf1az4#

除了Ritsaert Hornstra的回答,得到了2个负分(无可否认,我没有看到它的原始形式...)
这是事实。
对于大量的迭代,使用'**'操作符或pow(x,y)方法通常需要两倍的时间,而仅仅是手动地将两个对相乘。如果需要,使用math.fabs()方法,如果它抛出NaN的话(有时候它会抛出NaN,特别是当使用int16等时),它仍然只需要两个函数的大约一半的时间。
对我知道的最初的问题没有那么重要,但绝对值得知道。

jmp7cifd

jmp7cifd5#

我不知道带2次幂的pow()函数是否快。

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

r7xajy2e6#

你可以试试这个:

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

更多细节可以在这里找到('k-最近邻'示例):https://jakevdp.github.io/PythonDataScienceHandbook/02.08-sorting.html

pcrecxhr

pcrecxhr7#

在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

相关问题