【问题标题】:Vectorizing ndimage functions for my code为我的代码矢量化 ndimage 函数
【发布时间】:2013-10-11 12:36:24
【问题描述】:

我希望能够对这段代码进行矢量化处理:

def sobHypot(rec):
    a, b, c = rec.shape
    hype = np.ones((a,b,c))

    for i in xrange(c):
        x=ndimage.sobel(abs(rec[...,i])**2,axis=0, mode='constant')
        y=ndimage.sobel(abs(rec[...,i])**2,axis=1, mode='constant')
        hype[...,i] = np.hypot(x,y)
        hype[...,i] = hype[...,i].mean()

    index = hype.argmax()
    return index

rec,shape 返回 (1024,1024,20) 的位置

【问题讨论】:

  • 矢量化是什么意思?
  • 如中,去掉 for 循环
  • 即使是原样(没有矢量化),也不要取abs 然后平方它......没有abs 的平方应该做同样的事情。此外,只需将其平方一次并保存平方矩阵。这只节省了大约 20% 的时间,所以真正的矢量化当然会更好:P
  • 我接受了在将其放入循环之前进行平方的建议,但是因为我在这个矩阵中有复杂的值,所以我必须在平方之前做 abs。从数学上讲,这是没有意义的,但是在python中测试它,如果我不取abs然后平方它,复杂的值会留在里面。例如:(2+2j)**2 #prints 8j abs(2+2j) **2 #prints 8
  • 我可以,但是,只拿它的腹肌,而不是平方它。索引的答案仍然相同。基本上只是图像中的一个缩放因子。

标签: python python-2.7 numpy scipy


【解决方案1】:

以下是使用 sobel 过滤器避免 for 循环的方法:

import numpy as np
from scipy.ndimage import sobel

def sobHypot_vec(rec):
    r = np.abs(rec)
    x = sobel(r, 0, mode='constant')
    y = sobel(r, 1, mode='constant')
    h = np.hypot(x, y)
    h = np.apply_over_axes(np.mean, h, [0,1])
    return h.argmax()

我不确定 sobel 过滤器在您的应用程序中是否特别需要,如果没有您特定的 20 层“图像”,这很难测试,但您可以尝试使用 np.gradient 而不是运行两次 sobel。优点是gradient 在三个维度上运行。您可以忽略第三个组件,只假设前两个。这看起来很浪费,但在我的测试中实际上仍然更快。

对于各种随机生成的图像,r = np.random.rand(1024,1024,20) + np.random.rand(1024,1024,20)*1j,这给出了与您的代码相同的答案,但要对其进行测试以确保,并且可能会摆弄np.gradientdx, dy 参数

def grad_max(rec):
    g = np.gradient(np.abs(rec))[:2]  # ignore derivative in third dimension
    h = np.hypot(*g)
    h = np.apply_over_axes(np.mean, h, [0,1]) # mean along first and second dimension 
    return h.argmax()

使用此代码进行计时:

def sobHypot_clean(rec):
    rs = rec.shape
    hype = np.ones(rs)
    r = np.abs(rec)
    for i in xrange(rs[-1]):
        ri = r[...,i]
        x = sobel(ri, 0, mode='constant')
        y = sobel(ri, 1, mode='constant')
        hype[...,i] = np.hypot(x,y).mean()
    return hype.argmax()

时间:

In [1]: r = np.random.rand(1024,1024,20) + np.random.rand(1024,1024,20)*1j

# Original Post
In [2]: timeit sobHypot(r)
1 loops, best of 3: 9.85 s per loop

#cleaned up a bit:
In [3]: timeit sobHypot_clean(r)
1 loops, best of 3: 7.64 s per loop

# vectorized:
In [4]: timeit sobHypot_vec(r)
1 loops, best of 3: 5.98 s per loop

# using np.gradient:
In [5]: timeit grad_max(r)
1 loops, best of 3: 4.12 s per loop

请在您自己的图像上测试这些函数中的任何一个,以确保它们提供所需的输出,因为不同类型的数组的反应可能与我所做的简单随机测试不同。

【讨论】:

  • 因此,使用我的图像进行测试,这些函数都可以为同一图像提供不同的值。我的图像是全息图的重建。我试图用这个功能做的基本上是找到图像焦点所在的位置,即最清晰的位置。我什至会以正确的方式解决这个问题?到目前为止,原始函数与我每次选择的函数最接近。
  • 我并不感到惊讶,这些方法对方法和输入的微小差异非常敏感,尽管sobHypot_clean 与您原来的sobHypot 不同似乎很奇怪。第一个函数sobHypot_vec 是您问题的最直接答案,理论上应该给出相同的结果,除非我遗漏了什么。您可以尝试将**2 放回原处,看看是否真的有帮助。 grad_max 明显不同,但更简单,运行速度更快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-10
相关资源
最近更新 更多