多目标跟踪sort的加速思路

此帖记录一下在视觉感知项目中的一些曲折经历。

机子是NVIDIA Jetson AGX,具体型号未知。

单独启用一个ros结点做目标跟踪,因为deepsort多了一个网络,延时可能比较高,遂用了更简单的sort

第一次在agx上跑了一下,发现延迟非常高,纯sort的耗时在30ms以上,有些帧甚至达到60+ms,这肯定不正常啊。

首先分析各模块耗时:

主机 agx
kf_predict 0.46 4.04
assignment 0.15 1.27
kf_update 0.24 30.05
pop 0.11 1.89

note: 以上结果统计的不够严谨,但是大体能表征一下趋势。

  • kf_predict:使用卡尔曼滤波根据上一帧的位置来预测当前帧的位置
  • assignment:使用匈牙利匹配分配检测框和轨迹框
  • kf_update:对匹配框使用卡尔曼滤波做更新
  • pop:删掉未匹配的轨迹框

对新出现的检测框我忘了统计了,就是一个初始化的时间,应该不是sort时间长的主要原因(次要原因应该都称不上)。

通过对比,发现agx的耗时正常来说应该是我用的主机的10倍左右,但是kf_update时间异常,查了一下self.kf这个类,发现都是用的filterpy这个库,遂点进去查看。

from filterpy.kalman import KalmanFilter

发现主机和agx上的kalman类文件竟然不完全一样,推测可能是python版本的问题导致库不同(主机上是py3.8,agx上是py3.6)。
注意观察py3.6上的库多了一部分计算,尝试删去这部分之后kf_update部分节约了十几ms,后来我直接把py3.8的类复制到agx上调用,kf_update部分直接从30.05 -> 11.6ms,这只是第一步

多目标跟踪sort的加速思路_第1张图片
虽然速度有了大大提升,但是有时仍然会因为cpu性能或者其他原因导致每帧延迟掉到15fps以下(这是/neuvition的发布频率),虽然我设置了接收器消息队列长度为1,但仍然不能及时接收到最新消息,导致图像持续滞后(不知道为啥,希望大佬指教一番),这次的主要原因仍然是kf_update。

我又分析了一下kf_update内部的计算过程,除了一次求逆外都是矩阵乘法,按理说不应该这么慢。重点来了,问题恰恰出在了求逆矩阵上,源码里直接用 np.linalg.inv() 求逆矩阵,在一次KalmanFilter.update 中占了足足三分之一的时间(罪大恶极)。

找到问题就好解决了,想到deepsort中KalmanFilter.update用了cholesky矩阵分解加快求解,把 S^T K^T =(PHT)T 通过求S的逆,变成了AX=B的问题,可以显著提高速度。

self.SI = self.inv(self.S)
self.K = dot(PHT, self.SI)

改为

chol_factor, lower = scipy.linalg.cho_factor(
            self.S, lower=True, check_finite=False)
        
self.K = scipy.linalg.cho_solve(
     (chol_factor, lower), PHT.T,
     check_finite=False).T

单个track的kf_update不便于比较,这里我直接放整个sort的结果:

  • 20.69ms -> 9.86ms

速度有了质的飞跃,这就是第二步

后记

该说不说,deepsort相比于sort在KalmanFilter上有了很大改进,自带一个类文件,不用担心因为python自带的filterpy.kalman库版本不一样导致的效率不同,同时逆运算通过trick获得了极大的速度提升。

经过前两步的加速,sort结点已经完全达到了使用要求,于是没有采用其他加速方法,设想中可以再利用numba来加速kalmanfilter的矩阵运算或者是sort中的iou计算。

此外,若sort中需要夹杂其他任务,如车牌检测,则最好用多线程并行处理,以此保证sort的速度,详情可参见我的另一篇博客python threading多线程实例。

你可能感兴趣的:(经验教训,多目标跟踪,Ros,目标跟踪,人工智能,计算机视觉)