当前位置: 首页 > news >正文

DeepDriving | 多目标跟踪算法之SORT

本文来源公众号“DeepDriving”,仅用于学术分享,侵权删,干货满满。

原文链接:多目标跟踪算法之SORT

1 简介

SORT2016年发表的一篇文章Simple Online and Realtime Tracking中提出的一个经典的多目标跟踪算法,该算法结合常用的卡尔曼滤波器和匈牙利匹配算法实现了一个简单的在线多目标跟踪框架。由于其超简单的设计,SORT可以以260 Hz的更新速率实现多目标跟踪,远超当时其它的目标跟踪算法。

论文地址:https://arxiv.org/abs/1602.00763

代码地址:https://github.com/abewley/sort

2 具体实现

2.1 目标检测

SORT是一种采用Tracking-by-Detection策略的目标跟踪算法,也就是说算法的输入数据来源于目标检测器,其本身是不参与目标检测过程的。作者在论文里对比了以Faster-RCNNACFPASCAL VOC数据集上的行人检测结果作为MDPSORT跟踪算法的输入,得出的结论是目标检测结果的好坏直接决定了目标跟踪的性能,使用最好的目标检测器会得到最好的跟踪效果

这也告诉我们一个道理:解决问题要从源头开始。如果不从源头提升目标检测算法的性能,花再多时间去提升目标跟踪的性能可能都是徒劳。

2.2 状态估计模型

如果对卡尔曼滤波器不了解,可以看一下我之前整理的资料,里面有卡尔曼滤波器的详细推导过程:(后续文章介绍)。

2.3 数据关联

给已存在的目标分配当前帧检测到的边界框时,目标在当前帧中的边界框是基于之前的状态预测出来的。所有当前帧检测的边界框与已存在目标做预测得到的边界框通过计算它们之间的IOU来求代价矩阵,然后用匈牙利算法求解最优匹配结果。如果检测边界框与预测边界框匹配成功且它们之间的IOU值大于阈值IOU_min,那么就认为它们是一对有效的匹配对,否则是无效的。匹配成功后,就可以基于检测的边界框对目标状态进行更新了。

作者发现采用IOU作为距离度量进行匹配可以隐式地解决由于传递目标引起的短期遮挡的问题。具体来说,当一个目标被另一个物体覆盖时,检测器只能检测到这个遮挡物体而检测不到被遮挡物体,因为IOU距离有利于具有相似比例的检测框。这样的话遮挡物体可以正常被分配检测框去更新状态,而被遮挡物体则不会受误分配带来的影响,因为当前没有检测框会分配给它。

2.4 跟踪标识的创建和删除

当一个目标出现在图像中的时候,我们需要为其创建一个全局唯一的身份标识(ID);反之,当目标消失的时候就要销毁它的跟踪信息。

3 代码分析

3.1 算法整体流程

SORT算法的处理流程非常简单,感兴趣的可以去看源码。下图是我整理的算法流程图:

对当前帧的检测结果Detections和已存在的目标Tracker使用匈牙利算法进行匹配会出现三种情况:

  1. 检测结果Detection未匹配成功,那么就以该边界框的几何信息为初始状态去创建一个Tracker;

  2. 检测结果DetectionTracker匹配成功,那么就以该检测结果为观测值更新Tracker的状态;

  3. 未匹配的Tracker,前面说到T_Lost设置为1,也就是只要一帧没匹配上该Tracker就会被删除。

3.2 卡尔曼滤波器

SORT的代码里创建了一个类KalmanBoxTracker用于对卡尔曼滤波器的状态进行管理,卡尔曼滤波器使用的是filterpy.kalman包中的KalmanFilter,官方文档地址为:https://filterpy.readthedocs.io/en/latest/kalman/KalmanFilter.html。

3.2.1. 滤波器初始化

 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.01self.kf.Q[4:,4:] *= 0.01#状态向量前面四个值用bbox初始化,变化率设置为0self.kf.x[:4] = convert_bbox_to_z(bbox)
3.2.2. 滤波器生命周期管理

滤波器生命周期的管理是通过几个变量来实现的,KalmanBoxTracker创建的时候会初始化几个变量:

self.time_since_update = 0
self.hits = 0
self.hit_streak = 0

如果Tracker匹配成功,就会更新这几个变量的状态:

def update(self, bbox):self.time_since_update = 0self.hit_streak += 1

如果Tracker做了一次预测,同样会更新这几个变量的状态:

def predict(self):if (self.time_since_update > 0):self.hit_streak = 0self.time_since_update += 1

time_since_update表示距离上一次带观测值更新滤波器状态过去了多久,hit_streak表示Tracker连续匹配成功并更新的次数,一旦调用predict()函数对当前帧做了预测,time_since_update就加一,表示其已经对当前帧做过一次预测了。

在算法的处理类Sort中,会对Tracker的这几个变量做判断:

  1. 一个匹配成功的Tracker,需要判断其是否还在“试用期”,只有连续几帧都匹配成功才能使用它的跟踪信息:

if (trk.time_since_update < 1) and (trk.hit_streak >= self.min_hits or self.frame_count <= self.min_hits):ret.append(np.concatenate((d, [trk.id+1])).reshape(1, -1))
  1. 如果下一帧Tracker未匹配成功,该Tracker就会被删除:

if (trk.time_since_update > self.max_age):self.trackers.pop(i)

4 总结

SORT目标跟踪算法仅使用卡尔曼滤波器和匈牙利算法解决帧与帧之间的状态预测和数据关联问题,跟踪的效果高度依赖于目标检测结果的好坏,算法整体设计非常简单,在速度和精度上取得较好的平衡,主要体现一个“快”字。当然,速度提升必然导致精度损失,SORT的缺点在于仅仅使用物体的边界框进行跟踪而忽略其表面特征,在复杂的场景中效果会比较差。另外,SORT没有目标重识别过程,一旦目标丢失就需要重新创建跟踪器去更新状态(一帧未匹配成功就需要重新跟踪),导致同一目标的ID频繁变换。

THE END !

文章结束,感谢阅读。您的点赞,收藏,评论是我继续更新的动力。大家有推荐的公众号可以评论区留言,共同学习,一起进步。

相关文章:

DeepDriving | 多目标跟踪算法之SORT

本文来源公众号“DeepDriving”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;多目标跟踪算法之SORT 1 简介 SORT是2016年发表的一篇文章《Simple Online and Realtime Tracking》中提出的一个经典的多目标跟踪算法&#xff0c;…...

实验演示方波是由正弦波叠加而成的

方波可以看成是由N个正弦波叠加而成&#xff0c;在数学上&#xff0c;方波可以写成这个式子&#xff0c;大家可以看到这个式子里面包含了无数个奇数次的正弦波。 下面通过运放构成的反相求和电路来看一下&#xff0c;正弦波叠加成方波 对于这个反相求和电路&#xff1a; Ui1是…...

进口电动流量调节阀的选型-美国品牌

进口电动流量调节阀的选型需要综合考虑多个因素&#xff0c;以确保所选阀门能够满足实际应用需求。以下是选型时需要考虑的主要方面&#xff1a; 一、明确应用需求 工作介质&#xff1a;了解介质的性质&#xff0c;包括流体类型、温度、压力以及是否具有腐蚀性或特殊性质。流…...

【人工智能】流行且重要的智能算法整理

✍&#x1f3fb;记录学习过程中的输出&#xff0c;坚持每天学习一点点~ ❤️希望能给大家提供帮助~欢迎点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;指点&#x1f64f; 小记&#xff1a; 今天在看之前写的文档时&#xff0c;发现有人工智能十大算法的内容&#xf…...

webrtc客户端测试和arm平台测试(待补充)

一、关于API的使用研究 二、遇到的一些问题 1、snd_write Broken pipe 写音频数据到缓存不及时导致&#xff0c;codec没有数据可以播放。 alsa总结 WebRTC源码研究&#xff08;1&#xff09;WebRTC架构 WebRTC 中的基本音频处理操作...

Unity ShaderGraph 扭曲

需要注意的是&#xff1a; HDRP ShaderGraph中 你不能扭曲UI&#xff0c;所以假如你要扭曲视频&#xff0c;请把视频在材质上渲染 播放&#xff0c;这样就可以扭曲视频了喔&#xff0c; ShaderGraph扭曲...

鸿蒙Ability Kit(程序框架服务)【应用启动框架AppStartup】

应用启动框架AppStartup 概述 AppStartup提供了一种更加简单高效的初始化组件的方式&#xff0c;支持异步初始化组件加速应用的启动时间。使用启动框架应用开发者只需要分别为待初始化的组件实现AppStartup提供的[StartupTask]接口&#xff0c;并在[startup_config]中配置App…...

DBeaver添加DM8驱动(maven下载和jar包下载配置)

DBeaver 24.0.3添加DM8驱动 下载DBeaver下载DM达梦驱动下载 安装配置使用自带Dameng自行添加达梦驱动 因为最近公司项目有信创要求&#xff0c;所以下载了达梦数据库。使用自带的达梦管理工具不是很方便&#xff0c;于是换了DBeaver。 哼哧哼哧安装好后&#xff0c;创建数据库连…...

EXCEL多sheet添加目录跳转

EXCEL多sheet添加目录跳转 背景 excel中有几十个sheet&#xff0c;点下方左右切换sheet太耗时&#xff0c;希望可以有根据sheet名超链接跳转相应sheet&#xff0c;处理完后再跳回原sheet。 方案一 新建目录sheet&#xff0c;在A1写sheet名&#xff0c;右键选择最下方超链接…...

MySQL之查询性能优化(十)

查询性能优化 MySQL查询优化器的局限性 松散索引扫描 由于历史原因&#xff0c;MySQL并不支持松散索引扫描&#xff0c;也就无法按照不连续的方式扫描一个索引。通常&#xff0c;MySQL的索引扫描需要先定义一个起点和终点&#xff0c;即使需要的数据只是这段索引中很少数的几…...

短视频矩阵源码----如何做正规开发规则分享:

一、什么是SaaS化服务技术开发&#xff1f; &#xff08;短视频矩阵系统是源头开发的应该分为3个端口---- 总后台控制端、总代理端口&#xff0c;总商户后台&#xff09; SaaS是软件即服务&#xff08;Software as a Service&#xff09;的缩写。它是一种通过互联网提供软件应…...

4. JavaScript 循环与迭代

JavaScript 中提供了这些循环语句&#xff1a; for 语句do … while 语句while 语句label 语句 跳出多级循环 var num 0; outPoint: for (var i 0; i < 10; i) {for (var j 0; j < 10; j) {if (i 5 && j 5) {break outPoint; // 在 i 5&#xff0c;j 5 …...

智能视频监控平台LntonCVS视频融合共享平台保障露营安全解决方案

在当今社会&#xff0c;都市生活的快节奏和压力使得越来越多的人渴望逃离城市的喧嚣&#xff0c;寻求一种短暂的慢生活体验。他们向往在壮丽的山河之间或宁静的乡村中露营&#xff0c;享受大自然的宁静与美好。随着露营活动的普及&#xff0c;露营地的场景也变得更加丰富多样&a…...

python如何画函数图像

通过图像可以直观地学习函数变化、分布等规律&#xff0c;在学习函数、概率分布等方面效果显著。下面我们尝试用Python的2D绘图库matplotlib来绘制函数图像。 下面我们来实现一个简单的函数&#xff1a; 首先&#xff0c;调用matplotlib库和numpy库 import matplotlib.pyplot …...

zeppelin(kylin的可视化界面安装)(从头到尾安装)

zeppelin(kylin的可视化界面安装) 1、zeppelin安装前的准备工作&#xff1a; 1、虚拟机安装配置好jdk&#xff0c; 2、虚拟机安装配置好Hadoop&#xff0c; 3、虚拟机安装配置好Hive 4、虚拟机安装配置了hbase 5、安装了kylin&#xff08;麒麟&#xff09; 6、下载了zeppelin…...

python词云生成库-wordcloud

内容目录 一、模块介绍二、WordCloud常用的方法1. generate(self, text)2. generate_from_frequencies(frequencies)3. fit_words(frequencies)4. generate_from_text(text) 三、进阶技巧1. 设置蒙版2. 设置过滤词 WordCloud 是一个用于生成词云的 Python 库&#xff0c;它可以…...

鸿蒙开发接口数据管理:【@ohos.data.rdb (关系型数据库)】

关系型数据库 关系型数据库&#xff08;Relational Database&#xff0c;RDB&#xff09;是一种基于关系模型来管理数据的数据库。关系型数据库基于SQLite组件提供了一套完整的对本地数据库进行管理的机制&#xff0c;对外提供了一系列的增、删、改、查等接口&#xff0c;也可…...

Java返回前端Bigdecimal类型数据时“0E-8“及小数点多余0的问题

目录 问题描述: 解决方法: 重要代码&#xff1a; 问题描述: 项目中oracle数据库需要转换为mysql&#xff0c;Oracle中的表字段定义为number(36,16)类型的工具自动转换为mysql的decimal(36,16)。在Oracle数据库中&#xff0c;number(36,16)类型的字段&#xff0c;使用BigDeci…...

标题:深入探索Linux中的`ausyscall`

标题&#xff1a;深入探索Linux中的ausyscall&#xff08;注意&#xff1a;ausyscall并非Linux内核标准命令&#xff0c;但我们可以探讨类似的概念&#xff09; 在Linux系统中&#xff0c;系统调用&#xff08;syscall&#xff09;是用户空间程序与内核空间进行交互的一种重要…...

CorelDRAW2024发布更新啦!设计师们的得力助手

在数字化的今天&#xff0c;视觉设计已经成为我们生活中不可或缺的一部分。从手机界面到广告海报&#xff0c;从网页布局到包装设计&#xff0c;每一个细节都离不开设计师们的专业与创意。然而&#xff0c;面对日益增长的设计需求和不断提升的审美标准&#xff0c;许多设计师开…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...

Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合

无论是python&#xff0c;或者java 的大型项目中&#xff0c;都会涉及到 自身平台微服务之间的相互调用&#xff0c;以及和第三发平台的 接口对接&#xff0c;那在python 中是怎么实现的呢&#xff1f; 在 Python Web 开发中&#xff0c;FastAPI 和 Django 是两个重要但定位不…...

【深尚想】TPS54618CQRTERQ1汽车级同步降压转换器电源芯片全面解析

1. 元器件定义与技术特点 TPS54618CQRTERQ1 是德州仪器&#xff08;TI&#xff09;推出的一款 汽车级同步降压转换器&#xff08;DC-DC开关稳压器&#xff09;&#xff0c;属于高性能电源管理芯片。核心特性包括&#xff1a; 输入电压范围&#xff1a;2.95V–6V&#xff0c;输…...

Qwen系列之Qwen3解读:最强开源模型的细节拆解

文章目录 1.1分钟快览2.模型架构2.1.Dense模型2.2.MoE模型 3.预训练阶段3.1.数据3.2.训练3.3.评估 4.后训练阶段S1: 长链思维冷启动S2: 推理强化学习S3: 思考模式融合S4: 通用强化学习 5.全家桶中的小模型训练评估评估数据集评估细节评估效果弱智评估和民间Arena 分析展望 如果…...

el-amap-bezier-curve运用及线弧度设置

文章目录 简介示例线弧度属性主要弧度相关属性其他相关样式属性完整示例链接简介 ‌el-amap-bezier-curve 是 Vue-Amap 组件库中的一个组件,用于在 高德地图 上绘制贝塞尔曲线。‌ 基本用法属性path定义曲线的路径,可以是多个弧线段的组合。stroke-weight线条的宽度。stroke…...