【深度学习|目标跟踪】StrongSORT 详解(以及StrongSORT++)
StrongSort详解
- 1、论文及源码
- 2、DeepSORT回顾
- 3、StrongSORT的EMA
- 4、StrongSORT的NSA Kalman
- 5、StrongSORT的MC
- 6、StrongSORT的BOT特征提取器
- 7、StrongSORT++的AFLink
- 8、StrongSORT++的GSI模块
1、论文及源码
论文地址:https://arxiv.org/pdf/2202.13514
源码地址:https://github.com/dyhBUPT/StrongSORT?tab=readme-ov-file
2、DeepSORT回顾
参考此篇博客
3、StrongSORT的EMA
EMA即指数加权移动平均,在StrongSort中,self.track在update时,会将当前提取到的目标特征向量进行如下两步操作:
- 将特征向量归一化
- 指数加权移动平均
在代码中的体现,在track脚本文件中,Track类:
相比较于DeepSort中将每次的匹配上的目标的特征向量直接存储到对应track的gallery中,StrongSort的做法可以有效的平滑视频中间由于遮挡,噪声或其他不利因素导致的目标特征的衰减,使得在特征在匹配时的准确率能够有效提升。
在Tracker类update的最后,我们会更新对应track的特征库:
在nn_matching脚本中的NearestNeighborDistanceMetric类中:
这里的self.budget可以在config.yaml中指定,意思是存储当前帧的前多少帧的特征进特征库。本质上还是和DeepSort一样,给每个track弄了个特征库,只不过特征库中的特征向量是从第一帧开始就进行指数加权移动平均并归一化的特征向量。
4、StrongSORT的NSA Kalman
在DeepSort中使用的是一个普通的kalman filter,即通过状态量直接估计下一时刻的状态,只有位置信息,而StrongSort中融合了目标的置信度信息,在计算噪声的均值和方差时,加入了track对应的检测目标的置信度信息,自适应的调整噪声。自适应计算噪声协方差的公式:
其中,Rk是预设的常数测量噪声协方差,Ck 是状态 k 下的检测置信度分数。即当置信度高时,意味着这次检测的结果有较小的噪声,对下次的状态预测的影响较小。
现在来看一下源码中关于NSA Kalman的流程:
- strong_sort.py中StrongSort类的self.tracker.predict()
- 进入tracker.py中的Tracker类的predict()方法,遍历self.tracks然后进入track的predict()预测,然后进入track.py中的Track类的predict()预测,然后进入kalman_filter.py中的KalmanFilter类中的predict()方法来计算均值和方差。
- 然后回到strong_sort.py中的self.tracker.update(),进入tracker.py的Tracker类的update()方法,经过self._match()匹配完成之后,会得到匹配列表,未匹配的跟踪,未匹配的检测。然后我们遍历匹配列表来,跟新我们已经匹配上的track,进入track.py中的Track类的update()方法,在这里我们会看到加入了检测框的confidence来更新均值和方差:
- 进入kalman_filter.py中的KalmanFilter类中的update()方法,进入self.project()方法计算出融合了confidence后的均值和方差。
这便是代码中NSA Kalman的一个实现过程。
5、StrongSORT的MC
在DeepSort中,虽然说结合了外观特征和运动特征来进行跟踪,但是DeepSort的lambda权重是设置成0或1的,因此并没有真正的结合外观特征追踪和运动特征追踪,只是将他们分成两个阶段分别匹配。而在StrongSort中,在外观特征匹配阶段,引入了一个mc_lambda权重作用在运动特征的门控矩阵上,结合外观代价矩阵来计算得到最后的cost_matrix,公式如下:
代码如下:
这是在_match()方法中的gated_metric()方法中调用。
6、StrongSORT的BOT特征提取器
这是一个关于行人重识别的特征提取网络,具体的还没有深入了解过,我个人觉得这里的特征提取器用什么不是StrongSort的亮点,毕竟这个模块是个即插即用的模块,用不同的分类网络或者孪生网络训练出来的特征提取网络都可以用在这个地方。
7、StrongSORT++的AFLink
AFLink提出将两段30帧(可以自己调整,修改AFLink的分类网络重新训练即可)的时空序列作为输入,这两段tracklets分别是1 * 30 * 3维度的一个特征向量,其中30表示帧数,3分别表示帧数(时间),x,y(空间),即结合了时空的一段序列。网络将会输出这两段tracklets的相似置信度。
- AFLink网络的定义:
"""
@Author: Du Yunhao
@Filename: model.py
@Contact: dyh_bupt@163.com
@Time: 2021/12/28 14:13
@Discription: model
"""
import torch
from torch import nnclass TemporalBlock(nn.Module):def __init__(self, cin, cout):super(TemporalBlock, self).__init__()self.conv = nn.Conv2d(cin, cout, (7, 1), bias=False)self.relu = nn.ReLU(inplace=True)self.bnf = nn.BatchNorm1d(cout)self.bnx = nn.BatchNorm1d(cout)self.bny = nn.BatchNorm1d(cout)def bn(self, x):x[:, :, :, 0] = self.bnf(x[:, :, :, 0])x[:, :, :, 1] = self.bnx(x[:, :, :, 1])x[:, :, :, 2] = self.bny(x[:, :, :, 2])return xdef forward(self, x):x = self.conv(x)x = self.bn(x)x = self.relu(x)return xclass FusionBlock(nn.Module):def __init__(self, cin, cout):super(FusionBlock, self).__init__()self.conv = nn.Conv2d(cin, cout, (1, 3), bias=False)self.bn = nn.BatchNorm2d(cout)self.relu = nn.ReLU(inplace=True)def forward(self, x):x = self.conv(x)x = self.bn(x)x = self.relu(x)return xclass Classifier(nn.Module):def __init__(self, cin):super(Classifier, self).__init__()self.fc1 = nn.Linear(cin*2, cin//2)self.relu = nn.ReLU(inplace=True)self.fc2 = nn.Linear(cin//2, 2)def forward(self, x1, x2):x = torch.cat((x1, x2), dim=1)x = self.fc1(x)x = self.relu(x)x = self.fc2(x)return xclass PostLinker(nn.Module):def __init__(self):super(PostLinker, self).__init__()self.TemporalModule_1 = nn.Sequential(TemporalBlock(1, 32),TemporalBlock(32, 64),TemporalBlock(64, 128),TemporalBlock(128, 256))self.TemporalModule_2 = nn.Sequential(TemporalBlock(1, 32),TemporalBlock(32, 64),TemporalBlock(64, 128),TemporalBlock(128, 256))self.FusionBlock_1 = FusionBlock(256, 256)self.FusionBlock_2 = FusionBlock(256, 256)self.pooling = nn.AdaptiveAvgPool2d((1, 1))self.classifier = Classifier(256)def forward(self, x1, x2):x1 = x1[:, :, :, :3]x2 = x2[:, :, :, :3]x1 = self.TemporalModule_1(x1) # [B,1,30,3] -> [B,256,6,3]x2 = self.TemporalModule_2(x2)x1 = self.FusionBlock_1(x1)x2 = self.FusionBlock_2(x2)x1 = self.pooling(x1).squeeze(-1).squeeze(-1)x2 = self.pooling(x2).squeeze(-1).squeeze(-1)y = self.classifier(x1, x2)if not self.training:y = torch.softmax(y, dim=1)return yif __name__ == '__main__':x1 = torch.ones((3, 1, 30, 3))x2 = torch.ones((3, 1, 30, 3))m = PostLinker()m.eval()# 提取第一个维度的第二个元素作为置信度(0表示第一个维度,1表示该维度的索引)y1 = m(x1, x2)[0, 1].detach().cpu().numpy()print(y1)
输入两个tracklets,维度分别是[1, 1, 30, 3];
||
v
Temporal module: 特征层维度[1, 256, 6, 3];
||
v
Fusion module: 特征层维度[1, 256, 6, 1];
||
v
Pooling + Squeeze:特征层维度[1, 256];
||
v
Classifier:特征层维度[1, 2];
- AFLink的推理:
AFLink是一个离线模块,在目标检测+跟踪推理完成后,将每一帧的track信息(帧数,位置)保存到txt中,然后离线的使用AFLink读取这个txt来得到最终的推理结果,也将序列信息保存到txt中。我们可以根据txt中的帧数和坐标信息来将检测结果可视化在视频中。
8、StrongSORT++的GSI模块
GSI模块即高斯平滑插值,为了弥补跟踪之后的检测结果在帧上不够连续的情况。这一模块个人感觉对于跟踪的结果上没有影响,在完全跟对的情况下,能够改善跟踪的连续性的视觉效果,但是如果跟踪错误的前提下,GSI之后,结果会变得很奇怪(框开始飘来飘去)。
在源码中,大致上分为两步骤:
- 设定一个插帧得阈值,小于这个阈值得两个不连续的帧之间我们会一帧帧插值,而大鱼这个阈值的,我们只插这个阈值数量的帧在中间。
- 高斯平滑,来使得插的帧的跟踪信息显得更加的连续平滑。
相关文章:
【深度学习|目标跟踪】StrongSORT 详解(以及StrongSORT++)
StrongSort详解 1、论文及源码2、DeepSORT回顾3、StrongSORT的EMA4、StrongSORT的NSA Kalman5、StrongSORT的MC6、StrongSORT的BOT特征提取器7、StrongSORT的AFLink8、StrongSORT的GSI模块 1、论文及源码 论文地址:https://arxiv.org/pdf/2202.13514 源码地址&#…...
23种设计模式-原型(Prototype)设计模式
文章目录 一.什么是原型设计模式?二.原型模式的特点三.原型模式的结构四.原型模式的优缺点五.原型模式的 C 实现六.原型模式的 Java 实现七. 代码解析八.总结 类图: 原型设计模式类图 一.什么是原型设计模式? 原型模式(Prototype…...
Qt—QLineEdit 使用总结
文章参考:Qt—QLineEdit 使用总结 一、简述 QLineEdit是一个单行文本编辑控件。 使用者可以通过很多函数,输入和编辑单行文本,比如撤销、恢复、剪切、粘贴以及拖放等。 通过改变 QLineEdit 的 echoMode() ,可以设置其属性,比如以密码的形式输入。 文本的长度可以由 m…...
go-zero使用自定义模板实现统一格式的 body 响应
前提 go环境的配置、goctl的安装、go-zero的基本使用默认都会 需求 go-zero框架中,默认使用goctl命令生成的代码并没有统一响应格式,现在使用自定义模板实现统一响应格式: {"code": 0,"msg": "OK","d…...
BUGKU printf
整体思路 实现循环-->获取libc版本和system函数地址->将strcpy的got表项修改为system并获得shell 第一步:实现循环 从汇编语句可以看出,在每次循环结束时若0x201700处的值是否大于1则会继续循环。 encode1会将编码后的结果保存至0x2015c0处&am…...
深度学习:梯度下降法
损失函数 L:衡量单一训练样例的效果。 成本函数 J:用于衡量 w 和 b 的效果。 如何使用梯度下降法来训练或学习训练集上的参数w和b ? 成本函数J是参数w和b的函数,它被定义为平均值; 损失函数L可以衡量你的算法效果&a…...
`console.log`调试完全指南
大家好,这里是 Geek技术前线。 今天我们来探讨 Console.log() 的一些优点。并分析一些基本概念和实践,这些可以让我们的调试工作变得更加高效。 理解前端 log 与后端 log 的区别 前端 log 与后端 log 有着显著的不同,理解这一点至关重要。…...
ROS VSCode调试方法
VSCode 调试 Ros文档 1.编译参数设置 cd catkin_ws catkin_make -DCMAKE_BUILD_TYPEDebug2.vscode 调试插件安装 可在扩展中安装(Ctrl Shift X): 1.ROS 2.C/C 3.C Intelliense 4.Msg Language Support 5.Txt Syntax 3.导入已有或者新建ROS工作空间 3.1 导入工作…...
16 —— Webpack多页面打包
需求:把 黑马头条登陆页面-内容页面 一起引入打包使用 步骤: 准备源码(html、css、js)放入相应位置,并改用模块化语法导出 原始content.html代码 <!DOCTYPE html> <html lang"en"><head&…...
微服务即时通讯系统的实现(服务端)----(3)
目录 1. 消息存储子服务的实现1.1 功能设计1.2 模块划分1.3 模块功能示意图1.4 数据管理1.4.1 数据库消息管理1.4.2 ES文本消息管理 1.5 接口的实现1.5.1 消息存储子服务所用到的protobuf接口实现1.5.2 最近N条消息获取接口实现1.5.3 指定时间段消息搜索接口实现1.5.4 关键字消…...
.net6.0 mvc 传递 model 实体参数(无法对 null 引用执行运行时绑定)
说一下情况: 代码没问题,能成功从数据库里查到数据,能将数据丢给ViewBag.XXXX, 在View页面也能获取到 ViewBag.XXXX的值,但是发布到线上后报这个错: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 无法对 …...
VUE 入门级教程:开启 Vue.js 编程之旅
一、Vue.js 简介 Vue.js 是一套构建用户界面的渐进式 JavaScript 框架。它专注于视图层的开发,能够轻松地与其他库或现有项目进行整合。Vue.js 的核心库只关注视图层,通过简洁的 API 实现数据绑定和 DOM 操作的响应式更新,让开发者可以高效地…...
Ubantu系统docker运行成功拉取失败【成功解决】
解决docker运行成功拉取失败 失败报错 skysky-Legion-Y7000-IRX9:~$ docker run hello-world docker: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Head “http://%2Fvar%2Frun%2Fdocker.sock/_ping”: dial uni…...
mvn-mac操作小记
1.安装brew 如果报错,Warning: /opt/homebrew/bin is not in your PATH. vim ~/.zshrc,最后一行追加 export PATH“/opt/homebrew/bin:$PATH” source ~/.zshrc 2.安装brew install maven mvn -version查看路径 Maven home: /opt/homebrew/Cellar/mav…...
机器学习——生成对抗网络(GANs):原理、进展与应用前景分析
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一. 生成对抗网络的基本原理二. 使用步骤2.1 对抗性训练2.2 损失函数 三. GAN的变种和进展四. 生成对抗网络的应用五. 持续挑战与未来发展方向六. 小结 前言 生…...
「Mac畅玩鸿蒙与硬件33」UI互动应用篇10 - 数字猜谜游戏
本篇将带你实现一个简单的数字猜谜游戏。用户输入一个数字,应用会判断是否接近目标数字,并提供提示“高一点”或“低一点”,直到用户猜中目标数字。这个小游戏结合状态管理和用户交互,是一个入门级的互动应用示例。 关键词 UI互…...
Ps:存储 Adobe PDF
在 Adobe Photoshop 中,将图像保存为 PDF 文件时, 会弹出“存储 Adobe PDF” Save Adobe PDF对话框。在此对话框中提供了多个选项,用于控制 PDF 文件的输出,包括一般设置(选择预设、兼容性和保留编辑功能)、…...
DDR3保姆级使用教程:ZYNQ 7010
内容:使用DDR3 IP核,向DDR3写入数据,然后再读出数据,通过串口打印。 设备:ZYNQ 7010 xc7z010clg-400-1。软件VIVADO 2018.3 (1)工程模块:一个写FIFO,一个读FIFO。一个ZYNQ IP核&am…...
OpenCV 模板匹配全解析:从单模板到多模板的实战指南
简介:本文深入探讨 OpenCV 中的模板匹配技术。详细介绍构建输入图像与模板图像的步骤,包括读取、截取、滤波与存储等操作。剖析 cv2.matchTemplate 语法及其参数含义,阐述不同匹配方法下结果值的意义。同时讲解 cv2.minMaxLoc 语法࿰…...
【JAVA] 杂谈: java中的拷贝(克隆方法)
这篇文章我们来介绍什么是拷贝,并且实现浅拷贝到深拷贝。 目录 一、浅拷贝 1.1 clone 方法 1.2 实现浅拷贝: 1.2.1 重写 clone方法 1.2.2 实现接口 Cloneable 1.2.3 调用克隆方法 1.2.4 原理图: 1.3 浅拷贝的不足 1.3.1 增加引用…...
使用 PDF API 合并 PDF 文件
内容来源: 如何在 Mac 上合并 PDF 文件 1. 注册与认证 您可以注册一个免费的 ComPDFKit API 帐户,该帐户允许您在 30 天内免费无限制地处理 1,000 多个文档。 ComPDFKit API 使用 JSON Web Tokens 方法进行安全身份验证。从控制面板获取您的公钥和密钥&…...
关于BeanUtils.copyProperties是否能正常复制字段【详细版】
话不多说!先总结: 1、字段相同,类型不同(不复制,也不报错) 2、子类父类 (1)子类传给父类(可以正常复制) (2)父类传给子类(可以正常复制) 3、子类父类&#x…...
爬虫框架快速入门——Scrapy
适用人群:零基础、对网络爬虫有兴趣但不知道从何开始的小白。 什么是 Scrapy? Scrapy 是一个基于 Python 的网络爬虫框架,它能帮助你快速爬取网站上的数据,并将数据保存到文件或数据库中。 特点: 高效:支…...
鸿蒙开发-HMS Kit能力集(应用内支付、推送服务)
1 应用内支付 开发步骤 步骤一:判断当前登录的华为账号所在服务地是否支持应用内支付 在使用应用内支付之前,您的应用需要向IAP Kit发送queryEnvironmentStatus请求,以此判断用户当前登录的华为帐号所在的服务地是否在IAP Kit支持结算的国…...
TYUT设计模式大题
对比简单工厂,工厂方法,抽象工厂模式 比较安全组合模式和透明组合模式 安全组合模式容器节点有管理子部件的方法,而叶子节点没有,防止在用户在叶子节点上调用不适当的方法,保证了的安全性,防止叶子节点暴露…...
Webman中实现定时任务
文章目录 Webman中实现定时任务一、引言二、安装与配置1、安装Crontab组件2、创建进程文件3、配置进程文件随Webman启动4、重启Webman5、Cron表达式(补充)例子 三、使用示例四、总结 Webman中实现定时任务 一、引言 在现代的后端开发中,定时…...
《以 C++破局:人工智能系统可解释性的探索与实现》
在当今科技飞速发展的时代,人工智能已深度融入我们的生活,从医疗诊断到金融决策,从交通管控到司法审判,其影响力无处不在。然而,在这些涉及重大利益和社会影响的关键领域,人工智能系统却面临着严峻的信任危…...
C++:QTableWidget删除选中行(单行,多行即可)
转自博客: Qt C -在QTableWidget中删除行 - 腾讯云开发者社区 - 腾讯云 我的界面: 采集机器人位置和姿态信息并写入QTableWidget控件中 删除代码: 1.获取要删除行的索引 2.删除行 QList<QTableWidgetItem*> items ui->tableW…...
C++类中多线程的编码方式
问题 在C++代码中,一般的代码是需要封装在类里面,比如对象,方法等。否则就不能很好的利用C++面向对象的能力了。 但是这个方式在处理线程时会碰到一个问题。 考虑下面一个简单的场景: class demoC { public:std::thread t;int x;void threadFunc(){std::cout<<x&…...
数据湖的概念(包含数据中台、数据湖、数据仓库、数据集市的区别)--了解数据湖,这一篇就够了
文章目录 一、数据湖概念1、企业对数据的困扰2、什么是数据湖3、数据中台、数据湖、数据仓库、数据集市的区别 网上看了好多有关数据湖的帖子,还有数据中台、数据湖、数据仓库、数据集市的区别的帖子,发现帖子写的都很多,而且专业名词很多&am…...
wordpress网站自动伪原创/品牌推广方式有哪些
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串…...
如何做解析网站/电商热门关键词
//在初始化codec后,接下来就是打开解码器int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options){int ret 0;AVDictionary *tmp NULL;if (avcodec_is_open(avctx)) //返回avctx-》internal,见…...
网站如何做团购/数据分析
layout拼图安卓版是一款典型的拼图应用,可以让我们把各种照片随心所欲地拼起来,也是轻量级应用的模式打造,整个应用程序非常的轻便,虽然在开发商算不上独一无二的,但绝对是实用标准的拼图应用。功能介绍Instagram 全新…...
织梦中英网站怎么做/宁波网站推广公司价格
JMeter和Gatling均用于具有相同目的的不同方法的测试。该界面对于JMeter用户而言技术性较低,并且具有良好的培训生态系统。它具有多个协议和插件,并且用户对该工具做出了许多贡献。加特林主要用于CI / CD管道,并在没有用户界面的情况下创建适…...
免费高清视频会议软件/关键词搜索优化
说明:在List<T>范型集合中提供了一类委托,以确定要寻找集合中的哪些符合条件的单个元素或者集合msdn里描述如下:Predicate 委托,用于定义要搜索的元素应满足的条件。这一点msdn帮助里面说得很简单,只以List<s…...
萝岗网站建设/腾讯企点app
在海底捞、西贝等餐饮企业涨价之后,妹子们用来续命的奶茶也开始涨价了,近一个月内,喜茶、奈雪、CoCo、一点点部分产品都涨价1-4元。奶茶涨价,别拿原材料涨价当借口事实上,从 2月中旬开始,喜茶旗下的豆豆波波…...