[英]Speed up angle calculation for each x,y point in a matrix
I have a 3-d Numpy array flow
as follows: 我有一个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.
Need to calculate the angle for each x,y point. 需要计算每个x,y点的角度。 Here is how I have implemented it:
这是我的实现方式:
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
The calculation of angle at each point takes 14.0389318466 seconds
to execute on my Macbook Pro. 在Macbook Pro上执行每个点的角度计算需要
14.0389318466 seconds
。
Is there a way I could speed this up, probably by using some matrix operation, rather than processing each pixel one at a time. 有没有一种方法可以加快速度,可能是通过使用某些矩阵运算,而不是一次处理每个像素。
numpy.angle
supports vectorized operation. numpy.angle
支持矢量化操作。 So, just feed in the first and second column slices to it for the final output, like so - 因此,只需将第一列和第二列的切片输入其中以得到最终输出,就像这样-
fangle = np.angle(flow[...,0] + flow[...,1] * 1j, deg=True)
Verification - 验证-
In [9]: flow = np.random.uniform(low=-1.0, high=1.0, size=(720,1280,2))
In [17]: out1 = np.apply_along_axis(calcAngle, axis=2, arr=flow)
In [18]: out2 = np.angle(flow[...,0] + flow[...,1] * 1j, deg=True)
In [19]: np.allclose(out1, out2)
Out[19]: True
Runtime test - 运行时测试-
In [10]: %timeit np.apply_along_axis(calcAngle, axis=2, arr=flow)
1 loop, best of 3: 8.27 s per loop
In [11]: %timeit np.angle(flow[...,0] + flow[...,1] * 1j, deg=True)
10 loops, best of 3: 47.6 ms per loop
In [12]: 8270/47.6
Out[12]: 173.73949579831933
173x+
speedup! 173x+
加速!
You can use numpy.arctan2()
to get the angle in radians, and then convert to degrees with numpy.rad2deg()
: 您可以使用
numpy.arctan2()
获取以弧度为单位的角度,然后使用numpy.rad2deg()
转换为度数:
fangle = np.rad2deg(np.arctan2(flow[:,:,1], flow[:,:,0]))
On my computer, this is a little faster than Divakar's version: 在我的计算机上,这比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
A more efficient way to use np.angle()
is to create a complex view of flow
. 使用
np.angle()
一种更有效的方法是创建flow
的复杂视图。 If flow
is an array of type np.float64
with shape (m, n, 2)
, then flow.view(np.complex128)[:,:,0]
will be an array of type np.complex128
with shape (m, n)
: 如果
flow
是类型的数组np.float64
具有形状(m, n, 2)
然后flow.view(np.complex128)[:,:,0]
将是类型的数组np.complex128
具有形状(m, n)
:
fangle = np.angle(flow.view(np.complex128)[:,:,0], deg=True)
This appears to be a smidge faster than using arctan2
followed by rad2deg
(but the difference is not far above the measurement noise of timeit
): 这似乎比使用
arctan2
和rad2deg
(但差异不远于timeit
的测量噪声):
In [47]: %timeit np.angle(flow.view(np.complex128)[:,:,0], deg=True)
10 loops, best of 3: 35 ms per loop
Note that this might not work if flow
was creating as the tranpose of some other array, or as a slice of another array using steps bigger than 1. 请注意,如果
flow
是作为其他数组的转置或作为另一个数组的切片使用大于1的步长创建的,则此方法可能不起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.