加速矩阵中每个 x,y 点的角度计算

Vis*_*hal 1 python performance numpy vectorization scipy

我有一个 3-d Numpy 数组flow,如下所示:

flow = np.random.uniform(low=-1.0, high=1.0, size=(720,1280,2))
# Suppose flow[0] are x-coordinates. flow[1] are y-coordinates.
Run Code Online (Sandbox Code Playgroud)

需要计算每个 x,y 点的角度。这是我如何实施它:

def calcAngle(a):
    assert(len(a) == 2)
    (x, y) = a
    # angle_deg = 0
    angle_deg = np.angle(x + y * 1j, deg=True)
    return angle_deg

fangle = np.apply_along_axis(calcAngle, axis=2, arr=flow) 
# The above statement takes 14.0389318466 to execute
Run Code Online (Sandbox Code Playgroud)

每个点的角度计算需要14.0389318466 seconds在我的 Macbook Pro 上执行。

有没有一种方法可以加快速度,可能是通过使用一些矩阵运算,而不是一次处理一个像素。

War*_*ser 5

您可以使用numpy.arctan2()以弧度为单位获取角度,然后使用以下方法转换为度数numpy.rad2deg()

fangle = np.rad2deg(np.arctan2(flow[:,:,1], flow[:,:,0]))
Run Code Online (Sandbox Code Playgroud)

在我的电脑上,这比 Divakar 的版本快一点:

In [17]: %timeit np.angle(flow[...,0] + flow[...,1] * 1j, deg=True)
10 loops, best of 3: 44.5 ms per loop

In [18]: %timeit np.rad2deg(np.arctan2(flow[:,:,1], flow[:,:,0]))
10 loops, best of 3: 35.4 ms per loop
Run Code Online (Sandbox Code Playgroud)

更有效的使用方法np.angle()是创建flow. 如果flow是一个np.float64shape类型的数组(m, n, 2),那么flow.view(np.complex128)[:,:,0]将是一个np.complex128shape类型的数组(m, n)

fangle = np.angle(flow.view(np.complex128)[:,:,0], deg=True)
Run Code Online (Sandbox Code Playgroud)

这似乎比使用arctan2后跟要快一点rad2deg(但差异并不远高于 的测量噪声timeit):

In [47]: %timeit np.angle(flow.view(np.complex128)[:,:,0], deg=True)
10 loops, best of 3: 35 ms per loop
Run Code Online (Sandbox Code Playgroud)

请注意,如果flow是作为其他数组的转置创建,或者作为使用大于 1 的步长的另一个数组的切片创建,这可能不起作用。