byteTracker中因为目标检测和行人跟踪是解耦的,因此这里主要分析的是byteTracker中的代码。
也即是分析当给定一帧图片frame_id,给定这帧中的box列表,行人跟踪类是怎么跟踪每条轨迹的。
也就是https://github.com/ifzhang/ByteTrack中位于目录tutorials/trades/byte_tracker中的代码。
首先这个代码中最重要的两个类,一个是轨迹类STrack,一个是跟踪类BYTETracker类。
前者是每条轨迹,后者管理目前视频流中的所有轨迹,并在新的一帧到来之后通过调用类方法update更新当前视频流中的轨迹状态(可能有新的轨迹,可能有旧的轨迹失去跟踪目标框,可能有目标框匹配成功,可能有之前丢失目标框的轨迹重新匹配成功)。
之所以写这个代码解读,是因为每次重新捡起来阅读的时候都被各种参数搞得晕头转向,很容易混淆不同参数的含义。索性写个详细的笔记记录一下。
一、轨迹类STrack
这里面保存的都是轨迹自身的状态。跟踪类BYTETracker类通过调用轨迹的属性和方法来进行轨迹状态的管理。
1 属性集合
属性名称 | 类型 | 含义 |
---|---|---|
self._tlwh | 列表 | 保存目标框属性 |
self.is_activated | bool | 该轨迹是否是激活状态(也就是保持追踪中),如果是视频流的第一帧,那么第一次update的时候,该属性就是True,如果不是第一帧,那么需要第二次匹配成功的时候才会设置为True(考虑一下误识别的情况,这就可以理解了,只有当连续两帧都匹配成功,才认为这个轨迹可靠)。 |
self.kalman_filter | 类实例 | 在第一次调用activate()函数时,设置卡尔曼滤波器 |
self.mean, self.covariance | ndarray | 保存卡尔曼滤波对于这个轨迹的mean和convariance.其中len(mean)=8(x,y,a,h,va,vy,va,vh),v表示速度,covariance为[8,8]。在第一次调用activate()函数时进行初始化,初始化根据目标框的坐标进行估计 |
self.tlbr | ndarray | 如果self.is_activated=True,那么就是根据卡尔曼滤波预测的左上角和右下角坐标,如果self.is_activated=False,那么就是当前检测框观测值的左上角和右下角坐标 |
self.tlwh | ndarray | 如果self.is_activated=True,那么就是根据卡尔曼滤波预测的左上角和宽高,如果self.is_activated=False,那么就是当前检测框观测值的左上角和宽高 |
self.score | float | 轨迹分数,采用当前帧的目标框分数作为轨迹分数 |
self.tracklet_len | int | 轨迹追踪的帧数,初始为0,后面每追踪成功(调用update方法),则+1 |
self.state | TrackState | TrackState.New,Tracked,Lost |