基于YOLOv8与ByteTrack实现多目标跟踪——算法原理与代码实践
概述
在目标检测中,有许多经算法如Faster RCNN、SSD和YOLO的各种版本,这些算法利用深度学习技术,特别是卷积神经网络(CNN),能够高效地在图像中定位和识别不同类别的目标。Faster RCNN是一种基于区域提议的目标检测算法,通过引入区域建议网络(RPN)来生成候选框,然后使用分类器和回归器来识别和精确定位目标。SSD(Single Shot MultiBox Detector)是一种单阶段的目标检测算法,它在单个卷积网络中同时进行目标分类和定位,具有较快的速度和较高的准确性。而YOLO(You Only Look Once)则是一种端到端的目标检测算法,通过将图像分割为网格并预测每个网格中的目标类别和边界框来实现目标检测,具有实时性的优势。
但这里有一个问题是,在目标检测上,所检测到的目标是一帧帧的,同一个目标在帧与帧之间并没有关联起来,这个时候,如果要确定上一帧的A_1目标是不是下一帧的A_2目标,这里就要用到多目标跟踪。多目标追踪传输的是一个视频流,对于每一帧,需要检测目标并分配一个“对象 ID”,在下一帧中,如果检测到相同的对象,则需要分配相同的对象 ID。有许多算法用于 MOT,如 SORT(简单在线实时跟踪)、DeepSort、StrongSort 等。
-
SORT(Simple Online and Realtime Tracking):这是一种简单而高效的在线多目标跟踪算法,它结合了卡尔曼滤波和匈牙利算法来实现目标跟踪。SORT适用于实时应用,并且在计算资源有限的情况下表现良好。
-
DeepSort:这是在SORT基础上发展而来的算法,它引入了深度学习技术,特别是卷积神经网络(CNN),用于提取目标的特征表示。DeepSort在目标跟踪的准确性和鲁棒性方面相对于传统方法有所提升。
-
StrongSort:这是另一种基于深度学习的多目标跟踪算法,它通过设计更强大的特征提取网络和更精细的跟踪策略来提高目标跟踪的性能。
目标跟踪可分为下面几种:
基于特征的跟踪:这涉及基于其特征(如颜色、形状、纹理等)进行跟踪。
模板匹配:顾名思义,这种方法使用预定义的模板在每个视频序列中进行匹配。
基于相关性的跟踪:这种方法用于计算目标对象与后续帧中候选区域之间的相似性。
基于深度学习的跟踪:这种方法使用在大型数据集上训练的神经网络实时检测和跟踪对象。
ByteSort
其他MOT算法中移除低置信度检测框的问题主要源于对检测框置信度的阈值设置以及对检测框的筛选策略。因为低置信度的检测框被认为可能是误检测或者不可靠的检测结果,因此会被丢弃以提高跟踪的准确性。然而,这种策略可能会带来一些问题:
-
遮挡目标: 低置信度的检测框有时确实可以指示目标的存在,尤其是在目标被部分遮挡或者遮挡物很大时。丢弃这些低置信度的检测框可能会导致漏检目标,因为算法无法正确地识别被遮挡的目标。
-
轨迹断裂: 移除低置信度的检测框可能导致轨迹的不连续性,因为目标在一帧中被识别出来,在另一帧中却被移除了。这可能会导致跟踪算法无法正确地维持目标的标识符,从而产生碎片化的轨迹,使跟踪结果不连贯。
ByteTrack考虑低置信度的检测框的原因在于:
-
避免漏检: ByteTrack意识到低置信度的检测框可能是有价值的目标信息,尤其是在目标被遮挡的情况下。因此,保留这些检测框有助于避免目标漏检的情况,提高跟踪的完整性。
-
减少轨迹断裂: 通过保留低置信度的检测框,ByteTrack可以减少轨迹的不连续性,从而提高了多目标跟踪的连贯性和准确性。这有助于跟踪算法更好地维持目标的标识符,减少碎片化轨迹的出现。
可以从下面的例子说明这个问题,如下图1:

在帧 t1 中,初始化了三个不同的轨迹,因为它们的置信度都高于 0.5。但在帧 t2 和 t3 中,置信度从 0.8 下降到 0.4,然后从 0.4 下降到 0.1。
图2:

这些检测框将被阈值机制消除,相应的红色轨迹也会相应消失,如上图所示。但如果考虑所有的检测框,更多的误报率将会被引入,例如图1中右most的框。这带来了第二个问题。
图3:

例如,如图3所示,两个低分检测框通过运动预测框(虚线)与轨迹匹配,因此对象被正确恢复。背景框被移除,因为它没有匹配的轨迹。
因此,使用高分到低分检测框在匹配过程中。这种简单而有效的关联方法称为 BYTE,因为每个检测框都是轨迹的基本单位。首先,它根据运动或外观相似性将高分检测框匹配到轨迹。然后,它采用卡尔曼滤波器来预测下一帧中轨迹的位置。然后可以使用 IoU 或 Re-ID 特征距离计算预测框和检测框之间的相似性。在第二次匹配步骤中,低分检测和未匹配的轨迹,即红色框中的轨迹,使用相同的运动相似性进行匹配。
数据关联
数据关联是多目标跟踪的核心之一,它涉及计算轨迹和检测框之间的相似性,并根据相似性应用不同的策略进行匹配。
在相似性度量方面,位置、运动和外观是三个重要的线索。SORT算法通常简单地利用位置和运动线索。它使用卡尔曼滤波器来预测下一帧中的轨迹,并计算检测框和预测框之间的IoU作为相似性度量。然而,位置和运动线索更适用于短距离匹配。对于长距离匹配,外观相似性则变得更加重要。例如,长时间被遮挡的对象可能会通过外观相似性进行识别。外观相似性通常通过计算Re-ID特征的余弦相似性来衡量。与此类似,DeepSort采用了独立的深度学习模型来处理外观相似性。
在匹配策略方面,不同的算法使用不同的方法为对象分配ID。SORT通常通过一次匹配将检测框与轨迹匹配,而DeepSort则采用级联匹配策略。这种策略首先将检测框与最近的跟踪器匹配,然后与丢失的跟踪器进行匹配。
BYTE 算法
BYTE算法的输入是视频序列和检测器,以及一个检测阈值值。该算法的输出是视频的每一帧中的轨迹T,其中包含对象的边界框和ID。
对于视频中的每一帧,首先使用检测器(Det)预测检测框和相应的预测分数。然后,根据设定的检测分数阈值,将检测框分为高分(Det(high))和低分(Det(low))两部分。
分离检测框后,BYTE算法将卡尔曼滤波器应用于预测当前帧中每个轨迹T的新位置。首先对高分检测框进行关联,然后再处理剩余的低分检测框。
BYTE算法的主要亮点在于其非常灵活,能够与不同的关联方法兼容。这意味着它可以根据特定的应用场景选择最合适的关联方法,从而提高多目标跟踪的性能和效果。
性能测试
在同一个数据集上的表现,ByteTrack算法的性能优于SORT和DeepSORT算法,这表明它在多目标跟踪任务上具有较好的表现。,ByteTrack的MOTA达到了76.6,而SORT和DeepSORT的性能分别为74.6和75.4。
ByteTrack在算法架构上相对简单,但其性能却十分可观。这种性能提升可能源于它在关联过程中的灵活性以及对外观相似性的更好处理。
ByteTrack 与 YOLOv8 示例
多目标追踪场景中,大部分遮挡物体的检测结果都是低分框,ByteTrack 非常简洁地从低分检测框中寻找遮挡的物体,对遮挡非常鲁棒。ByteTrack 同时也为如何最大程度利用检测结果来帮助 MOT 提供了启发,下面提供了 ByteTrack 的部署代码和模型:
import supervision as sv
from ultralytics import YOLO
from tqdm import tqdm
import argparse
import numpy as nptracker = sv.ByteTrack()
def process_video(source_weights_path: str, source_video_path: str,target_video_path: str, confidence_threshold: float = 0.3,iou_threshold: float = 0.7
) -> None:model = YOLO(source_weights_path) # Load YOLO model classes = list(model.names.values()) # Class names LINE_STARTS = sv.Point(0,500) # Line start point for count in/out vehicleLINE_END = sv.Point(1280, 500) # Line end point for count in/out vehicletracker = sv.ByteTrack() # Bytetracker instance box_annotator = sv.BoundingBoxAnnotator() # BondingBox annotator instance label_annotator = sv.LabelAnnotator() # Label annotator instance frame_generator = sv.get_video_frames_generator(source_path=source_video_path) # for generating frames from videovideo_info = sv.VideoInfo.from_video_path(video_path=source_video_path)line_counter = sv.LineZone(start=LINE_STARTS, end = LINE_END)line_annotator = sv.LineZoneAnnotator(thickness=2, text_thickness=2, text_scale= 0.5)with sv.VideoSink(target_path=target_video_path, video_info=video_info) as sink:for frame in tqdm(frame_generator, total= video_info.total_frames):# Getting result from modelresults = model(frame, verbose=False, conf= confidence_threshold, iou = iou_threshold)[0] detections = sv.Detections.from_ultralytics(results) # Getting detections#Filtering classes for car and truck only instead of all COCO classes.detections = detections[np.where((detections.class_id==2)|(detections.class_id==7))]detections = tracker.update_with_detections(detections) # Updating detection to Bytetracker# Annotating detection boxesannotated_frame = box_annotator.annotate(scene = frame.copy(), detections= detections) #Prepare labelslabels = []for index in range(len(detections.class_id)):# creating labels as per required.labels.append("#" + str(detections.tracker_id[index]) + " " + classes[detections.class_id[index]] + " "+ str(round(detections.confidence[index],2)) )# Line counter in/out triggerline_counter.trigger(detections=detections)# Annotating labelsannotated_label_frame = label_annotator.annotate(scene=annotated_frame, detections=detections, labels=labels)# Annotating line labelsline_annotate_frame = line_annotator.annotate(frame=annotated_label_frame, line_counter=line_counter)sink.write_frame(frame = line_annotate_frame)if __name__ == "__main__":parser = argparse.ArgumentParser("video processing with YOLO and ByteTrack") parser.add_argument("--source_weights_path",required=True,help="Path to the source weights file",type=str)parser.add_argument("--source_video_path",required=True, help="Path to the source video file",type = str)parser.add_argument("--target_video_path",required=True,help="Path to the target video file",type= str)parser.add_argument("--confidence_threshold",default = 0.3,help= "Confidence threshold for the model",type=float)parser.add_argument("--iou_threshold",default=0.7,help="Iou threshold for the model",type= float)args = parser.parse_args() process_video(source_weights_path=args.source_weights_path, source_video_path= args.source_video_path,target_video_path=args.target_video_path, confidence_threshold=args.confidence_threshold,iou_threshold=args.iou_threshold)

完整代码带GUI界面代码和代码部署可参考《YOLOv8项目实践——目标检测、实例分割、姿态估计、目标追踪算法原理及模型部署(Python实现带界面)》
源码下载地址:https://download.csdn.net/download/matt45m/89036361?spm=1001.2014.3001.5503
模型下载地址链接:https://pan.baidu.com/s/1-t5TwKzdRuHF3dL7POk1dA
提取码:3r1v
相关文章:
基于YOLOv8与ByteTrack实现多目标跟踪——算法原理与代码实践
概述 在目标检测中,有许多经算法如Faster RCNN、SSD和YOLO的各种版本,这些算法利用深度学习技术,特别是卷积神经网络(CNN),能够高效地在图像中定位和识别不同类别的目标。Faster RCNN是一种基于区域提议的…...
C语言——函数练习程序
1.从终端接收一个数,封装一个函数判断该数是否为素数 #include <stdio.h>int pri(int num) {int i 0;for (i 2; i < num; i){if (num % i 0){return 0;break;}}if (i num-1){return 1;} }int main(void) {int num 0;int ret 0;scanf("%d", &num);…...
ssh 启动 docker 中 app, docker logs 无日志
ssh 启动 app, 标准输出被重定向 ssh 客户端,而不是 docker 容器的标准输出。只需要在启动时把app 标准输出重定向到 docker标准输出。 测试如下: 1.启动 docker docker run -it -p 60022:22 --name test test:v4 bash -c "service ssh restart;…...
WPF---1.入门学习
🎈个人主页:靓仔很忙i 💻B 站主页:👉B站👈 🎉欢迎 👍点赞✍评论⭐收藏 🤗收录专栏:WPF 🤝希望本文对您有所裨益,如有不足之处…...
Vue3 + Vite + TS + Element-Plus + Pinia项目(5)对axios进行封装
1、在src文件夹下新建config文件夹后,新建baseURL.ts文件,用来配置http主链接 2、在src文件夹下新建http文件夹后,新建request.ts文件,内容如下 import axios from "axios" import { ElMessage } from element-plus im…...
【Rust】——编写自动化测试(一)
🎃个人专栏: 🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客 🐳Java基础:Java基础_IT闫的博客-CSDN博客 🐋c语言:c语言_IT闫的博客-CSDN博客 🐟MySQL:…...
第十二章 微服务核心(一)
一、Spring Boot 1.1 SpringBoot 构建方式 1.1.1 通过官网自动生成 进入官网:https://spring.io/,点击 Projects --> Spring Framework; 拖动滚动条到中间位置,点击 Spring Initializr 或者直接通过 https://start.spring…...
MySQL索引18连问,谁能顶住
前言 过完这个节,就要进入金银季,准备了 18 道 MySQL 索引题,一定用得上。 作者:感谢每一个支持: github 1. 索引是什么 索引是一种数据结构,用来帮助提升查询和检索数据速度。可以理解为一本书的目录&…...
[flink 实时流基础系列]揭开flink的什么面纱基础一
Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行,并能以内存速度和任意规模进行计算。 文章目录 0. 处理无界和有界数据无界流有界流 1. Flink程序和数据流图2. 为什么一定要…...
开放平台 - 互动玩法演进之路
本期作者 1. 背景 随着直播业务和用户规模日益壮大,如何丰富直播间内容、增强直播间内用户互动效果,提升营收数据变得更加关键。为此,直播互动玩法应运而生。通过弹幕、礼物、点赞、大航海等方式,用户可以参与主播的直播内容。B站…...
Linux之进程控制进程终止进程等待进程的程序替换替换函数实现简易shell
文章目录 一、进程创建1.1 fork的使用 二、进程终止2.1 终止是在做什么?2.2 终止的3种情况&&退出码的理解2.3 进程常见退出方法 三、进程等待3.1 为什么要进行进程等待?3.2 取子进程退出信息status3.3 宏WIFEXITED和WEXITSTATUS(获取…...
RegSeg 学习笔记(待完善)
论文阅读 解决的问题 引用别的论文的内容 可以用 controlf 寻找想要的内容 PPM 空间金字塔池化改进 SPP / SPPF / SimSPPF / ASPP / RFB / SPPCSPC / SPPFCSPC / SPPELAN  ASPP STDC:short-term dense concatenate module 和 DDRNet SE-ResNeXt …...
Qt中常用宏定义
Qt中常用宏定义 一、Q_DECLARE_PRIVATE(Class)二、Q_DECLARE_PRIVATE_D(Dptr, Class)三、Q_DECLARE_PUBLIC(Class)四、Q_D(Class) 和 Q_Q(Class) 一、Q_DECLARE_PRIVATE(Class) #define Q_DECLARE_PRIVATE(Class) inline Class##Private* d_func() { # 此处的 d_ptr 是属于QOb…...
【计算机网络】第 9 问:四种信道划分介质访问控制?
目录 正文什么是信道划分介质访问控制?什么是多路复用技术?四种信道划分介质访问控制1. 频分多路复用 FDM2. 时分多路复用 TDM3. 波分多路复用 WDM4. 码分多路复用 CDM 正文 什么是信道划分介质访问控制? 信道划分介质访问控制(…...
Rust编程(五)终章:查漏补缺
闭包 & 迭代器 闭包(Closure)通常是指词法闭包,是一个持有外部环境变量的函数。外部环境是指闭包定义时所在的词法作用域。外部环境变量,在函数式编程范式中也被称为自由变量,是指并不是在闭包内定义的变量。将自…...
LLM漫谈(五)| 从q star视角解密OpenAI 2027年实现AGI计划
最近,网上疯传OpenAI2027年关于AGI的计划。在本文,我们将针对部分细节以第一人称进行分享。 摘要:OpenAI于2022年8月开始训练一个125万亿参数的多模态模型。第一个阶段是Arrakis,也叫Q*,该模型于2023年12月完成训练&…...
【echart】数据可视化+vue+vite遇到问题
1、vue3使用echars图表报错:"Initialize failed:invalid dom" 原因是因为:Dom没有完成加载时,echarts.init() 就已经开始执行了,获取不到Dom,无法进行操作 解决:加个延时 onMounted(async () …...
mac m1安装和使用nvm的问题
mac m1安装和使用nvm的问题 使用nvm管理多版本node 每个项目可能用的node版本不同,所以需要多个版本node来回切换 但是最近遇到安装v14.19.0时一直安装失败的问题。 首先说明一下,用的电脑是mac M1芯片 Downloading and installing node v14.19.0... …...
git泄露
git泄露 CTFHub技能树-Web-信息泄露-备份文件下载 当前大量开发人员使用git进行版本控制,对站点自动部署。如果配置不当,可能会将.git文件夹直接部署到线上环境。这就引起了git泄露漏洞。 工具GitHack使用:python2 GitHack.py URL地址/.git/ git命令…...
Java项目:78 springboot学生宿舍管理系统的设计与开发
作者主页:源码空间codegym 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 系统的角色:管理员、宿管、学生 管理员管理宿管员,管理学生,修改密码,维护个人信息。 宿管员…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
