python - 在python中生成定向光流(HOOF)直方图的最有效方法
问题描述
我有一个 498 帧长的图像序列,我使用 cv2.calcOpticalFlowFarneback 计算了光流。因此,现在我有 497 个矢量图来表示我的运动矢量,这些矢量由幅度和方向描述。
我需要做的是生成一个直方图,在 x 轴上我有角度范围(以度为单位)。更具体地说,我有 12 个 bin,其中第一个 bin 包含所有带有 direction 的向量0 < angle < 30
,第二个bin30 < angle < 60
以此类推。相反,在 y 轴上,我需要得到每个 bin 中包含的那些向量的模的总和。
这里的问题是使用简单的for
循环和if
语句完成所有这些需要很长时间:
#magnitude and angle are two np.array of shape (497, 506, 1378)
bins = [1,2,3,4,5,6,7,8,9,10,11,12]
sum = np.zeros_like(bins)
for idx in range(np.array(magnitude).shape[0]): # for each flow map, i.e. for each image pair
for mag, ang in zip(magnitude[idx].reshape(-1), angle[idx].reshape(-1)):
if ang >= 0 and ang <= 30:
sum[0] += mag
elif ang > 30 and ang <= 60:
sum[1] += mag
elif ang > 60 and ang <= 90:
sum[2] += mag
elif ang > 90 and ang <= 120:
sum[3] += mag
elif ang > 120 and ang <= 150:
sum[4] += mag
elif ang > 150 and ang <= 180:
sum[5] += mag
elif ang > 180 and ang <= 210:
sum[6] += mag
elif ang > 210 and ang <= 240:
sum[7] += mag
elif ang > 240 and ang <= 270:
sum[8] += mag
elif ang > 270 and ang <= 300:
sum[9] += mag
elif ang > 300 and ang <= 330:
sum[10] += mag
elif ang > 330 and ang <= 360:
sum[11] += mag
计算大约需要 3 小时。有人可以建议一种更好、更有效的方法来执行此计算吗?
提前致谢。
编辑
摆脱了条件句并使用 Numba 进一步加快了速度。以下代码需要不到 10 秒的时间来计算:
import numpy as np
from numba import jit
@jit(nopython=True) # Set "nopython" mode for best performance, equivalent to @njit
def hoof(magnitude, angle):
sum = np.zeros(13)
for idx in range(magnitude.shape[0]): # for each flow map, i.e. for each image pair
for mag, ang in zip(magnitude[idx].reshape(-1), angle[idx].reshape(-1)):
sum[int((ang)//30)] += mag
sum[11] += sum[12]
return sum[0:12]
解决方案
条件很慢。你应该尽可能避免它们。此外, Numpy 矢量化和Numba JIT有助于大幅加快此类代码的速度。这是一个未经测试的示例:
import numba as nb
@nb.jit
def compute(magnitude, angle):
s = np.zeros(12)
for idx in range(magnitude.shape[0]):
for mag, ang in zip(magnitude[idx].reshape(-1), angle[idx].reshape(-1)):
if ang == 0:
s[0] += mag
elif ang > 0 and ang <= 360: # The condition can be removed if always true
s[(ang-1)//30] += mag
return s
# Assume both are Numpy array and angle is of type int.
# Note that the first call will be slower unless you precise the types.
compute(magnitude, angle)
推荐阅读
- java - javax.mail.AuthenticationFailedException:534-5.7.14,而我尝试使用 java 从 Jenkins 作业发送电子邮件
- javascript - JavaScript:无法在 IE 浏览器中修改 java 脚本中的名称属性
- android - 暗模式下的 Android Spinner 文本颜色
- c# - 在表 'XY' 上引入 FOREIGN KEY 约束 'FK_XY' 可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION
- html - 我如何正确对齐我的导航栏项目(ul)
- ssl - 带有通配符证书的错误 ERR_CERT_COMMON_NAME_INVALID
- php - 让 PHP7 和 PHP 8 共存
- javascript - 如何遍历对象 - JavaScript
- azure - Azure 中的真实 MTLS(使用客户端私钥验证)
- vue.js - 从 rootState vuex 获取对象而不是数字