SORT4 SORT项目代码解析

news2024/12/23 22:13:37

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 	# 帧数+1
        dets[] = .. # 存放 检测框
        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 SORT
    self.max_age = max_age		# tracker 的最大寿命
    self.min_hits = min_hits	# 最小匹配次数
    self.iou_threshold = iou_threshold	# 匹配阈值
    self.trackers = []        	# 存放跟踪器类 KalmanBoxTracker 对象
    self.frame_count = 0
    
    
	def 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 中待删除的 tracker
        for 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卡尔曼跟踪器

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

输入
状态量初始值 x k − 1 {x_{k-1}} xk1和状态量协方差初始值 P k − 1 {P_{k-1}} Pk1
卡尔曼滤波器中的参数设置: 状态转移矩阵 F F F,映射矩阵(或称测量矩阵) H H H
迭代输入每一步的 观测值 Z k Z_k Zk
输出
每一步的状态预测 x k x_k xk

在这里插入图片描述
在SORT项目中,观测量 来自 YOLO 的检测结果 b b o x ( [ x 1 , y 1 , x 2 , y 2 ] ) 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] 是中心点的坐标, s s s 是面积, r r r 是面积宽高比。这样四个量将是独立的变量,减弱了 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 s x˙,y˙,s˙ 分别是 x , y , s x,y,s x,y,s 的一阶微分 d x , d y , d s dx,dy,ds dx,dy,ds
在线性模型中,可将其视为 距离-速度 模型,即 x k = x k − 1 + d x d t x_k=x_{k-1}+dxdt xk=xk1+dxdt,由此可得状态转移矩阵 F F F
F = [ 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 ] 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
x k = F ⋅ x k − 1 = [ 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 ] [ x y s r x ˙ 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=Fxk1=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,1xysrx˙y˙s˙

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

class KalmanBoxTracker(object):
    
    count = 0		# 跟踪器的存在数量,static
    
    def __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.01
    self.kf.Q[4:,4:] *= 0.01

    self.kf.x[:4] = convert_bbox_to_z(bbox)     # [u,v,s,r,u',v',s']
    self.time_since_update = 0
    self.id = KalmanBoxTracker.count

    KalmanBoxTracker.count += 1

    self.history = []
    self.hits = 0
    self.hit_streak = 0
    self.age = 0

    def update(self,bbox):
    # 用检测框更新 tracker(kalman filter update)
    self.time_since_update = 0  # 自第一次 update(创建) 的匹配次数
    self.history = []			# 保存历次的
    self.hits += 1
    self.hit_streak += 1        # 与检测框成功匹配的次数
    self.kf.update(convert_bbox_to_z(bbox))	# 调用库函数的 update
    
    def predict(self):
     	if((self.kf.x[6]+self.kf.x[2])<=0):
      		self.kf.x[6] *= 0.0
        
    	self.kf.predict()
    
        self.age += 1
        if(self.time_since_update>0):
          self.hit_streak = 0
        self.time_since_update += 1
        self.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):
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/64100.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python学习基础笔记二十七——内置函数

内置函数的概念&#xff1a;就是python直接提供给你使用的所有函数。 1、作用域相关&#xff1a; 1&#xff09;globals()&#xff1a; 获取全局变量的字典&#xff1b; 2&#xff09;locals()&#xff1a;获取执行本方法所在命名空间内局部变量的字典&#xff1b; 2、迭代器…

(二)SpringCloud+Security+Oauth2 微服务初步集成

一 引言 本文主要好介绍了SpringCloudSecurityOauth2 的初步集成,项目源码地址oauth2.0集成案例,以下案例主要是核心源码的解释,案例源码请查看案例源码 二 项目结构说明 oauth-server oauth认证中心 oauth-client oauth客户端 oauth-nacos 注册中心和配置中心 oauth-common …

IDM究竟有哪些优势 IDM的几种超实用功能

作为一款体积只有10M的下载软件&#xff0c;IDM却常年霸占着各软件评测榜的前列。它的界面简洁清爽&#xff0c;使用过程中无弹窗、无广告&#xff0c;小小的体积竟能将下载速度提升5倍&#xff01;该软件一进入中国市场&#xff0c;便受到了广大用户的追捧&#xff0c;被大家亲…

谁说Python只能用来敲代码,用Python来制作游戏你了解吗?

前言 Python的热度现在一直高居不下&#xff0c;比如&#xff0c;完成同一个任务&#xff0c;C语言要写1000行代码&#xff0c;Java只需要写100行&#xff0c;而Python可能只要20行。 那python还可以用来干什么&#xff1f;你知道哪些呢&#xff1f; &#xff08;文末送读者…

HTML静态网页作业——基于html+css+javascript+jquery+bootstarp响应式成都家乡介绍网页

家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法&#xff0c;如盒子的嵌套、浮动、margin、border、background等属性的使用&#xff0c;外部大盒子设定居中&#xff0c;内部左中右布局&#xff0c;下方横向浮动排列&#xff0c;大学学习的前端知识点和布局方式都有…

Python采集电商平台数据信息

环境介绍 python 3.8pycharm 2021专业版selenium >>> pip install selenium3.141.0 Python当中的模块 操作 浏览器的驱动Chrome浏览器Chromedriver 浏览器驱动 操作浏览器 让 浏览器帮助我们去执行一些操作 模块准备 from selenium import webdriver # 操作浏…

数钥科技遭用户投诉:“招集令”被指息费高,曾有助贷平台被处罚

融资难、融资贵&#xff0c;一直世界性难题。在此背后&#xff0c;是信息不对称的问题。 而利用信息不对称&#xff0c;不少助贷机构游走其中&#xff0c;也带来了一些新的问题&#xff0c;比如高额服务费、砍头息等&#xff0c;侵害消费者个人信息也是另外一个问题。此前&…

SQL——基础查询

查看列 查看特定列 select 姓名 from 学生表select 姓名,性别,家庭住址 from 学生表查看所有列 select * from 学生表使用计算列 求和 select sum(price) from fruit求个数 select count(price) from fruit求价格提升 select price*1.05 from fruit求库存数量 select (…

useState源码解读 及 手撕 useState 实现

文章目录useState源码解读 及 手撕 useState 实现useState源码分析逻辑图源码解读mountStatemountWorkInProgressHook 函数updateStateupdateReducer 函数实现对比图实现效果只声明一个 hook重复调用同一个 hook声明多个不同的 hooks体验收获useState源码解读 及 手撕 useState…

MySQL分区表对NULL值的处理

GreatSQL社区原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本&#xff0c;使用上与MySQL一致。作者&#xff1a;王权富贵 1.概述 MySQL的分区表没有禁止NULL值作为分区表达式的值&#xff0c;无论它是列值还是用户提供的表…

CPP 核心编程4-重载递增运算符

#include "iostream"using namespace std;//递增运算符重载 //自定义整型 class MyInteger {friend ostream &operator<<(ostream &cout, MyInteger mi);public:MyInteger() {m_Num 0;}//重置前置运算符 返回引用是为了对同一个数进行操作MyInteger …

LSTM内部结构及前向传播原理——LSTM从零实现系列(1)

一、前言 作为专注于时间序列分析的玩家&#xff0c;虽然LSTM用了很久但一直没有写过一篇自己的LSTM原理详解&#xff0c;所以这次要写一个LSTM的从0到1的系列&#xff0c;从模型原理讲解到最后不借助三方框架自己手写代码来实现LSTM模型。本文本身没有特别独到之处&#xff0c…

Vue学习:el 与data的两种写法

el两种写法 法一&#xff1a;建立了联系 <!-- 准备容器 --><div id"root"><h1>hello,{{name}} </h1> <!-- {{插值语法}} --></div><script>new Vue({ el: #root,data: {name:Amy},});</script> 法二&#xff1a…

论文投稿指南——中国(中文EI)期刊推荐(第1期)

&#x1f680; EI是国际知名三大检索系统之一&#xff0c;在学术界的知名度和认可度仅次于SCI&#xff01;&#x1f384;&#x1f388; 【前言】 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊。其中&#xf…

java计算机毕业设计ssm特大城市地铁站卫生防疫系统5i80c(附源码、数据库)

java计算机毕业设计ssm特大城市地铁站卫生防疫系统5i80c&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持…

UDS服务基础篇之14

前言 你知道如果系统产生了DTC&#xff0c;应当如何清除呢&#xff1f;14服务具体的执行流程如何&#xff1f;14服务在使用过程中的常见bug又有哪些&#xff1f; 这篇&#xff0c;我们来一起探索并回答这些问题。为了便于大家理解&#xff0c;以下是本文的主题大纲&#xff1…

相控阵天线(十二):天线校准技术仿真介绍之旋转矢量法

目录简介旋转矢量法算法介绍旋转矢量法校准对方向图的影响旋转矢量法算法仿真移相器位数对旋转矢量法的影响多通道旋转矢量法算法仿真分区旋转矢量法算法仿真简介 由于制造公差和天线互耦的影响&#xff0c;天线各通道会呈现出较大的幅相误差&#xff0c;因此需对天线进行校准…

光阑,像差和成像光学仪器

人眼 人眼成像过程 空气-角膜 水状液-晶状体 晶状体-玻璃体 三个界面的折射成像 瞳孔 2-8mm 可变光阑,调节入射光强弱 睫状肌 改变晶状体曲率---调焦 人眼的调节 远点—眼睛完全松弛状态下看清楚的最远点&#xff0c;正常眼的远点在无穷远 近点—睫状肌最大收缩(焦…

【Redis】解决全局唯一 id 问题

永远要记得坚持的意义 一、全局唯一 id 场景 概念&#xff1a; 以订单表的 id 为例 使用自增 id 会产生的问题&#xff1a; id 的规律性太明显&#xff0c;容易让用户猜测到一些信息受表单数据量的限制 —— 分布式存储时&#xff0c;会产生问题 &#xff08;自增长&#x…

讲理论,重实战!阿里内部SpringBoot王者晋级之路全彩小册开源

大家都知道&#xff0c;Spring Boot框架目前不仅是微服务框架的最佳选择之一&#xff0c;还是现在企业招聘人才肯定会考察的点&#xff1b;很多公司甚至已经将SpringBoot作为了必备技能。但&#xff0c;现在面试这么卷的情况下&#xff0c;很多人面试时还只是背背面试题&#x…