Python 为我的代码矢量化ndimage函数

Python 为我的代码矢量化ndimage函数,python,python-2.7,numpy,scipy,Python,Python 2.7,Numpy,Scipy,我希望能够将此代码矢量化: 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')

我希望能够将此代码矢量化:

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返回(10241024,20)

以下是使用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两次。其优点是
渐变
以三维方式运行。可以忽略第三个中的分量,只取前两个中的hypot。这看起来很浪费,但实际上在我的测试中速度更快

对于各种随机生成的图像,
r=np.random.rand(10241024,20)+np.random.rand(10241024,20)*1j
,这会给出与代码相同的答案,但要测试它以确保正确,并可能会修改

使用此代码计时:

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

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

矢量化是什么意思?如中所述,请摆脱for loop,即使是原样(没有矢量化),不要使用
abs
,然后将其平方。。。不带abs的方形应该做同样的事情。另外,只需将其平方一次,然后保存平方矩阵。这只节省了大约20%的时间,所以真正的矢量化当然会更好:PI接受了在我把它放入循环之前进行平方运算的建议,但是因为我在这个矩阵中有复杂的值,我必须在平方之前进行abs运算。从数学上讲,这是没有意义的,但是在python中测试它,如果我不使用abs,然后将其平方,那么复杂的值将保持不变。例:(2+2j)**2#打印8j abs(2+2j)**2#打印8j abs,但我可以只取abs,而不是将其平方。对于索引,答案仍然相同。基本上只是图像中的一个比例因子。所以,用我的图像测试,这些函数都可以为同一图像提供不同的值。我的图像是全息图的再现。我想用这个函数做的基本上是找到图像的焦点,即最清晰的位置。我甚至会用正确的方法来处理这件事?到目前为止,原始函数与我每次都会选择的函数最接近。我并不感到惊讶,这些方法对方法和输入中的微小差异非常敏感,尽管
sobHypot\u clean
与原始的
sobHypot
不同似乎很奇怪。第一个函数,
sobHypt_vec
是对您的问题最直接的回答,理论上应该给出相同的结果,除非我遗漏了什么。你可以试着把
**2
放回去,看看这是否真的有用
grad_max
明显不同,但更简单,运行速度更快。
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