【问题标题】:Sum of Square Differences (SSD) in numpy/scipynumpy/scipy 中的平方差总和 (SSD)
【发布时间】:2011-01-18 01:58:44
【问题描述】:

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

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

如何加快速度?谢谢。

【问题讨论】:

    标签: python image-processing numpy scipy


    【解决方案1】:

    只是

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

    (如果形状始终为 (,,3),我预计可能只是 sum((A-B)**2)

    也可以使用求和法:((A-B)**2).sum()

    对吗?

    【讨论】:

    • 砰。我过得很慢。我的跑步时间减半。
    • 值得注意的是,为此您必须使用numpy.sum,而不是内置的sum,它将在第一个维度上找到总和并返回一个新的一维数组.
    • ((A-B)**2).sum(-1) 如果只想在最后一个轴上添加,则需要指定轴参数。只需使用 sum() 添加数组的所有条目(首先解开)
    【解决方案2】:

    顺便提一下,也可以使用np.dot

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

    这可能比使用np.sum**2 的替代方法更快并且可能更准确,但如果您想沿指定轴计算ssd,则不起作用。在这种情况下,可能会有一个神奇的下标公式使用np.einsum

    【讨论】:

      【解决方案3】:

      我很困惑你为什么选择i in range(3)。那应该是整个阵列,还是只是一部分?

      总的来说,您可以用 numpy 中定义的操作替换其中的大部分内容:

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

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

      【讨论】:

      • +1 scipy.stats.stats.ss(平方和)就是这样做的。
      【解决方案4】:

      不知道 power 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
      

      【讨论】:

      • A-B 乘法中缺少括号。
      【解决方案5】:

      Ritsaert Hornstra 的回答得到了 2 个否定分数(诚然,我没有看到它的原始形式......)

      这是真的。

      对于大量迭代,使用 '**' 运算符或 pow(x,y) 方法所花费的时间通常是手动将这些对相乘的两倍。如果有必要使用 math.fabs() 方法,如果它抛出 NaN(有时尤其是在使用 int16s 等时会这样做),它仍然只需要给定两个函数的大约一半时间。

      对于我知道的原始问题并不重要,但绝对值得知道。

      【讨论】:

        【解决方案6】:

        你可以试试这个:

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

        可以在此处找到更多详细信息(“k-Nearest Neighbors”示例): https://jakevdp.github.io/PythonDataScienceHandbook/02.08-sorting.html

        【讨论】:

          【解决方案7】:

          在 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
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-12-24
            • 2016-08-13
            • 2021-08-18
            • 2015-01-27
            • 2014-03-12
            • 2019-03-22
            • 2022-07-23
            • 2020-03-28
            相关资源
            最近更新 更多