SORT4 SORT项目代码解析
创始人
2024-03-20 03:56:43
0

SORT系列

SORT-1 项目配置运行-WINDOWS
SORT-2 卡尔曼滤波推导和示例
SORT-3 匈牙利算法和SORT类
SORT-4 SORT项目代码解析
本项目地址

SORT项目逐层详解

main

if __name__ == '__main__'# 设置交互模式、参数、文件路径|# 创建 SORT 对象mot_tracker = Sort(max_age=, min_hits=,iou_threshold) |# "循环"读取每一个文件(每一帧)for frame in range(...):# 参数准备frame += 1 	# 帧数+1dets[] = .. # 存放 检测框total_frames += 1|# 获取检测框dets[] = ...|# 用检测框 dets 做一次更新; 返回满足条件可显示的trackers([x1,y1,x2,y2,ID])trackers = mot_tracker.update(dets)|# 作画for d in trakcers:fig.canvas.flush_events()...

1.SORT 类

class Sort(object):def __init__(self, max_age=1, min_hits=3, iou_threshold=0.3):# Sets key parameters for SORTself.max_age = max_age		# tracker 的最大寿命self.min_hits = min_hits	# 最小匹配次数self.iou_threshold = iou_threshold	# 匹配阈值self.trackers = []        	# 存放跟踪器类 KalmanBoxTracker 对象self.frame_count = 0def update(self, dets=np.empty((0, 5))):# 使用 检测框 做一次更新; dets:[x1,y1,x2,y2,ID]# 0.参数准备trks = np.zeros(len(self,trackers),5)	# to_del = []			# 待删除的 预测框ret = []			# 可显示的 tracker|# 1.现有的跟踪器全部做一次更新预测,获得预测框for t,trk in enumerate(trks):pos = self.trackers[t].predict()[0]      	# 已有跟踪器上做一次预测trk[:]=[pos[0], pos[1], pos[2], pos[3], 0]  # 获得 "预测框" 的坐标|# 去除非法的预测框trks = np.ma.compress_rows(np.ma.masked_invalid(trks))|# 删除 to_del 中待删除的 trackerfor t in reversed(to_del):self.trackers.pop(t)|# 2.预测框和 检测框 做一次匹配matched, unmatched_dets, unmatched_trks = \associate_detections_to_trackers(dets,trks, self.iou_threshold)|# 3.根据匹配结果 分别更新三类 trakcer# 3.1 更新匹配成功的跟踪器for m in matched:self.trackers[m[1]].update(dets[m[0], :])# 3.2 为未匹配到的检测框创建一个新的跟踪器for i in unmatched_dets:trk = KalmanBoxTracker(dets[i,:])self.trackers.append(trk)|# 3.3 根据跟踪器的存在时间、匹配次数等决定是否加入显示列表

1.1卡尔曼跟踪器

卡尔曼滤波器系统如下图所示。

输入
状态量初始值 xk−1{x_{k-1}}xk−1​和状态量协方差初始值 Pk−1{P_{k-1}}Pk−1​
卡尔曼滤波器中的参数设置: 状态转移矩阵 FFF,映射矩阵(或称测量矩阵)HHH等
迭代输入每一步的 观测值 ZkZ_kZk​
输出
每一步的状态预测 xkx_kxk​

在这里插入图片描述
在SORT项目中,观测量 来自 YOLO 的检测结果 bbox([x1,y1,x2,y2])bbox([x1,y1,x2,y2])bbox([x1,y1,x2,y2]) 的转化形式 Z([u,v,s,r])Z([u,v,s,r])Z([u,v,s,r])。其中 [u,v][u,v][u,v] 是中心点的坐标,sss 是面积,rrr 是面积宽高比。这样四个量将是独立的变量,减弱了 bbox 四个变量之间的相关性。

由此可以定义状态量 [x,y,s,r,x˙,y˙,s˙]T[x,y,s,r,\dot x,\dot y,\dot s]^T[x,y,s,r,x˙,y˙​,s˙]T,其中 x˙,y˙,s˙\dot x,\dot y,\dot sx˙,y˙​,s˙ 分别是 x,y,sx,y,sx,y,s 的一阶微分 dx,dy,dsdx,dy,dsdx,dy,ds。
在线性模型中,可将其视为 距离-速度 模型,即 xk=xk−1+dxdtx_k=x_{k-1}+dxdtxk​=xk−1​+dxdt,由此可得状态转移矩阵 FFF:
F=[1,0,0,0,1,0,00,1,0,0,0,1,00,0,1,0,0,0,10,0,0,1,0,0,00,0,0,0,1,0,00,0,0,0,0,1,00,0,0,0,0,0,1]F=\begin{bmatrix}1,0,0,0,1,0,0\\0,1,0,0,0,1,0\\0,0,1,0,0,0,1\\0,0,0,1,0,0,0\\0,0,0,0,1,0,0\\0,0,0,0,0,1,0\\0,0,0,0,0,0,1 \end{bmatrix}F=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡​1,0,0,0,1,0,00,1,0,0,0,1,00,0,1,0,0,0,10,0,0,1,0,0,00,0,0,0,1,0,00,0,0,0,0,1,00,0,0,0,0,0,1​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤​
xk=F⋅xk−1=[1,0,0,0,1,0,00,1,0,0,0,1,00,0,1,0,0,0,10,0,0,1,0,0,00,0,0,0,1,0,00,0,0,0,0,1,00,0,0,0,0,0,1][xysrx˙y˙s˙]x_k=F\cdot x_{k-1}=\begin{bmatrix}1,0,0,0,1,0,0\\0,1,0,0,0,1,0\\0,0,1,0,0,0,1\\0,0,0,1,0,0,0\\0,0,0,0,1,0,0\\0,0,0,0,0,1,0\\0,0,0,0,0,0,1 \end{bmatrix}\begin{bmatrix} x\\y\\s\\r\\\dot x\\\dot y\\\dot s\end{bmatrix}xk​=F⋅xk−1​=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡​1,0,0,0,1,0,00,1,0,0,0,1,00,0,1,0,0,0,10,0,0,1,0,0,00,0,0,0,1,0,00,0,0,0,0,1,00,0,0,0,0,0,1​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤​⎣⎢⎢⎢⎢⎢⎢⎢⎢⎡​xysrx˙y˙​s˙​⎦⎥⎥⎥⎥⎥⎥⎥⎥⎤​

即可得到 xk=xk−1+x˙x_k=x_{k-1}+\dot xxk​=xk−1​+x˙ (y,sy,sy,s同理),x˙=x˙\dot x=\dot xx˙=x˙ (r,y˙r,\dot yr,y˙​同理)。这就是卡尔曼滤波器是线性滤波器原因

class KalmanBoxTracker(object):count = 0		# 跟踪器的存在数量,staticdef __init__(self,bbox):# 卡尔曼滤波器的主要参数设置self.kf = KalmanFilter(dim_x=7, dim_z=4)  # 定义状态空间和观测空间维度,解释见下self.kf.F = np.array([[1,0,0,0,1,0,0],[0,1,0,0,0,1,0],[0,0,1,0,0,0,1],			[0,0,0,1,0,0,0],  [0,0,0,0,1,0,0],[0,0,0,0,0,1,0],[0,0,0,0,0,0,1]])self.kf.H = np.array([[1,0,0,0,0,0,0],[0,1,0,0,0,0,0],[0,0,1,0,0,0,0],			[0,0,0,1,0,0,0]])self.kf.R[2:,2:] *= 10.self.kf.P[4:,4:] *= 1000. self.kf.P *= 10.self.kf.Q[-1,-1] *= 0.01self.kf.Q[4:,4:] *= 0.01self.kf.x[:4] = convert_bbox_to_z(bbox)     # [u,v,s,r,u',v',s']self.time_since_update = 0self.id = KalmanBoxTracker.countKalmanBoxTracker.count += 1self.history = []self.hits = 0self.hit_streak = 0self.age = 0
    def update(self,bbox):# 用检测框更新 tracker(kalman filter update)self.time_since_update = 0  # 自第一次 update(创建) 的匹配次数self.history = []			# 保存历次的self.hits += 1self.hit_streak += 1        # 与检测框成功匹配的次数self.kf.update(convert_bbox_to_z(bbox))	# 调用库函数的 updatedef predict(self):if((self.kf.x[6]+self.kf.x[2])<=0):self.kf.x[6] *= 0.0self.kf.predict()self.age += 1if(self.time_since_update>0):self.hit_streak = 0self.time_since_update += 1self.history.append(convert_x_to_bbox(self.kf.x))return self.history[-1]     # 返回最后(新)一个 bbox

1.2检测框与预测框的关联

def associate_detections_to_trackers(detections,trackers,iou_threshold = 0.3):

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...