尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

YOLOv8+ByteTrack实时目标跟踪实战:从环境配置到RK3588部署

YOLOv8+ByteTrack实时目标跟踪实战:从环境配置到RK3588部署 简介本资源为基于YOLOv8与ByteTrack的实时多目标跟踪完整实现方案面向人工智能、计算机视觉方向的初学者与工程实践者解决视频流中目标检测与跨帧稳定跟踪的技术集成难题适用于智能监控、运动分析及边缘端部署等实际场景。压缩包共10个文件含2个核心Python脚本takip.py与PythonApplication5.py实现检测-跟踪流水线2张测试图像telefon_takip.png、şişe_takip.png用于效果验证1个YOLOv8轻量级预训练模型yolov8n.pt1个Visual Studio解决方案.sln及配套项目文件.pyproj辅以README.md说明、Git版本控制配置.gitattributes/.gitignore等开发支持文件整体大小6.48MB。已有50人学习下载提供开箱即用的代码结构、可直接运行的跟踪流程、典型场景下的可视化结果示例以及适配嵌入式与服务器平台的轻量化部署基础是理解现代检测跟踪协同架构的优质实践素材。 去年我拿到了一份名为“YOLOv8与ByteTrack实时目标跟踪.zip”的项目资源里面是打包好的检测加跟踪工程正好我手头有个城市路口车流统计的小需求就直接用这套方案做了验证。先说结论YOLOv8做目标检测、ByteTrack做跨帧关联这套组合在GTX1660Ti这种中端显卡上就能跑到实时帧率而且工程上比我想象中省心得多。但省心的前提是你得把两个模块的接口逻辑吃透否则代码一跑起来全是莫名其妙的问题比如ID乱跳、轨迹断断续续、甚至跟踪框完全不动。这篇文章我就按自己实际跑这套代码包的顺序来写从原理、环境、代码对接、实测调优到嵌入式部署RK3588以及训练自己场景的模型基本涵盖了从拿到资源到真正落地会用到的所有关键环节。内容会比较长但每个部分都是我实测过的不是网上复制粘贴的结论。1. 检测和跟踪解耦为什么是YOLOv8加上ByteTrack1.1 检测器干检测跟踪器干关联先说一个很多人一开始没想明白的问题既然YOLOv8每一帧都能把目标框出来那为什么还要再加一个跟踪器我们可以把YOLOv8想象成一个视力非常好的观察员它每秒钟能看24次、30次甚至更多次画面每次都能准确指出来“这里有个人那里有辆车”。但问题是这个观察员不记人——它每一帧看到的人和上一帧看到的人在它眼里只是两个互不相关的检测结果。它不知道画面左边这个“人框”和5帧前画面右侧那个“人框”是不是同一个人。ByteTrack解决的就是“跨帧身份关联”这个事。它接收YOLOv8每帧输出的检测框然后用卡尔曼滤波预测每个目标在下一帧可能出现的位置再把当前帧的检测框和上一帧已有的“轨迹”做匹配匹配上就给同一个ID匹配不上就开一条新轨迹。这样输出的结果就是带稳定ID的框ID 1一直跟着左边的行人走ID 7一直跟着右边那辆白色轿车跑从头到尾不变。所以整个系统的关系是YOLOv8负责“每帧找目标”ByteTrack负责“把目标串成轨迹”两者解耦但必须串行工作。这也是这套方案在工程上最大的优势——两个模块可以单独调试、单独替换检测器不行了换检测器关联逻辑不行了换关联逻辑互不拖累。1.2 为什么非要跟踪纯检测不行吗我遇到过不少朋友说我要统计一个路口过了多少人直接每帧检测然后数框不就行了还真不行。拿真实场景来说一个行人走在路上中间被电线杆挡住两三帧或者走进一团树荫里导致检测置信度骤降这时候纯检测模式的输出是什么这一帧没有框了。等他从遮挡后面走出来检测器又重新给他一个框。在你的业务统计里这就成了“两个人”一个消失在电线杆后面一个从电线杆后面冒出来。如果是车流统计那误差就更离谱了一辆车因为收费站栏杆遮挡就被记成两次通过。这就是跟踪器最大的价值它有轨迹记忆。哪怕当前帧检测器漏检了或者被遮挡了ByteTrack会根据卡尔曼滤波预测目标的位置维持这条轨迹继续存续一段时间默认30帧。等目标重新出现在画面里检测框和预测位置吻合轨迹直接接上ID不变。这种鲁棒性是纯检测方案给不了的。所以做实时多目标跟踪的应用比如车流统计、人流密度、无人机视角目标定位、安防巡逻等检测加跟踪是标配架构这套代码包的定位也正好卡在这个需求上。1.3 和DeepSORT对比ByteTrack的取舍逻辑市面上的跟踪算法不少老牌的是DeepSORTByteTrack算后起之秀。很多人问为什么选ByteTrack不选DeepSORT我当时的对比逻辑是这样的。DeepSORT在卡尔曼滤波加匈牙利匹配的基础上额外引入了一个ReID行人重识别特征提取网络用外观特征辅助数据关联。好处是在目标遮挡、交叉、运动突变时靠“人长什么样”也能关联上坏处是每个目标都要过一个ReID模型提取特征这非常吃算力。跑在服务器上还好想部署到RK3588这类嵌入式设备上帧率直接腰斩。ByteTrack的论文核心观点是高帧率视频里检测器已经足够好运动预测和位置匹配就已经足够可靠不需要额外的外观特征。它用了一个“两步匹配”策略先和高置信度检测框做匹配再用剩下的低置信度检测框做二次匹配把那些被遮挡但是轨迹还在的目标尽量捞回来。这个设计在算力成本和关联效果之间取了一个非常务实的中点。所以如果你跑在PC上、画面目标密度不大、对ID稳定性要求极高DeepSORT仍有价值但如果你追求实时性、想往嵌入式设备搬、目标也不算特别密集ByteTrack明显更合适。这套代码包选择了后者是非常明智的方案选型。需要说明的是ByteTrack官方仓库是基于YOLOX的代码包里拿到的基本就是把跟踪器部分抽取出来嫁接到YOLOv8上的版本这个我们在下一章细说。2. 拿到代码包后的第一道坎环境版本匹配目标跟踪这种项目最劝退人的永远不是算法本身而是环境装了一整天最后仍然跑不起来。尤其是手头显卡还是GTX1660Ti这种上一代中端卡的走的弯路比新卡用户多得多。我直接给出我实测过、能稳定跑通的版本组合。2.1 GTX1660Ti上的CUDA、PyTorch、YOLOv8版本选型GTX1660Ti是图灵架构、6GB显存不支持很多新特性但跑YOLOv8轻量模型完全没问题。最稳的组合如下组件实测稳定版本说明操作系统Ubuntu 20.04 / Windows 10两个都试过Ubuntu下部署到板子更顺Python3.8 或 3.103.9也可但3.8和3.10踩坑最少CUDA11.7 / 11.8不要装12.x老卡兼容性反而不稳cuDNN8.6 系列与CUDA11.x配套PyTorch1.13.1 或 2.0.0建议2.0.0YOLOv8官方支持度高torchvision0.14.1 或 0.15.1和PyTorch版本严格对应YOLOv86.x 以上即可推理接口变化不大推理后端onnxruntime-gpu 2.x如果走ONNX路线效率更高我这里特别提一句网上大量教程默认你用的是RTX 30系或40系显卡一上来就给你装CUDA 12.x加PyTorch 2.1以上看起来没问题但GTX1660Ti驱动对版本极其敏感装上之后经常出现“CUDA driver version is insufficient”或者训练时直接OOM。我的建议不要追求最新稳定性优先上面这套组合是反复试过的。安装命令我贴一下# 先卸载自带的老版本 sudo apt remove --purge cuda* sudo apt remove --purge nvidia* # 安装驱动和CUDA 11.8如果你用Ubuntu wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda_11.8.0_520.61.05_linux.run sudo sh cuda_11.8.0_520.61.05_linux.run # 配置环境变量 echo export PATH/usr/local/cuda-11.8/bin:$PATH ~/.bashrc echo export LD_LIBRARY_PATH/usr/local/cuda-11.8/lib64:$LD_LIBRARY_PATH ~/.bashrc source ~/.bashrc # 验证 nvcc -V # 创建虚拟环境 conda create -n yolotrack python3.8 conda activate yolotrack # 安装对应版本PyTorch pip install torch2.0.0 torchvision0.15.1 torchaudio2.0.0 --index-url https://download.pytorch.org/whl/cu118Windows上操作类似只是CUDA安装走exe安装包pyTorch安装命令不变。装完建议跑一句import torch print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0))输出True和GTX 1660 Ti就说明GPU环境OK。2.2 ByteTrack依赖的裁剪与接入ByteTrack因为是从YOLOX移植来的原仓库自带一堆追踪无关的代码。这个代码包里已经把跟踪部分抽出来了但依赖还是要理清楚。我看了下核心文件基本是文件作用依赖kalman_filter.py卡尔曼滤波实现维护每个轨迹的运动状态和预测框numpymatching.py匈牙利匹配、IoU距离计算、二次匹配逻辑lap, scipybyte_tracker.py跟踪器主类STrack轨迹管理、帧间更新numpybasetrack.pySTrack基类定义了轨迹状态的转换numpyvisualization.py可视化跟踪框和IDopencv-python对于只想把跟踪器用起来的人来说这些文件拷贝到你的项目里然后补装scipy和lap两个包就行pip install scipy laplap包是求解线性分配问题的匈牙利匹配那一层用到它。Windows上如果pip装lap报错可以用pip install lapx替代接口基本一致我实测是兼容的。2.3 验证安装成功的最小Demo环境搭好之后别急着跑完整项目先跑一个最小链路验证加载YOLOv8模型读一帧视频输出检测框喂给ByteTrack打印每个目标的ID。我当时的验证代码大致是这样的import cv2 import torch from ultralytics import YOLO from byte_tracker import BYTETracker # 加载检测模型 model YOLO(yolov8n.pt) # 初始化跟踪器 tracker BYTETracker(args, frame_rate30) cap cv2.VideoCapture(test.mp4) while cap.isOpened(): ret, frame cap.read() if not ret: break # 检测 results model(frame, verboseFalse) dets [] for r in results: for box in r.boxes: x1, y1, x2, y2 box.xyxy[0].tolist() score box.conf[0].item() cls int(box.cls[0].item()) dets.append([x1, y1, x2, y2, score, cls]) # 跟踪 online_targets tracker.update(dets, (frame.shape[0], frame.shape[1])) # 打印每个目标ID信息 for t in online_targets: print(fID: {t.track_id}, bbox: {t.tlwh}, score: {t.score})如果你看到每一帧输出的ID在视频里连续出现、同一个行人在左右移动时ID不变说明环境和接入都没问题可以进入下一步优化了。3. 推理管线的真实对接从检测输出到跟踪ID环境跑通只代表“没报错”不代表“逻辑正确”。我见过太多人把视频跑起来看到框在动就觉得成功了实际上跟踪ID可能每帧都在跳。这节讲清楚YOLOv8输出和ByteTrack输入之间的桥是怎么搭的。3.1 YOLOv8的输出张量切面YOLOv8推理返回的是一组结果对象但如果我们走onnxruntime或者直接拿原始tensor会看到一个形状类似(1, 84, 8400)或者(1, 4num_classes, 8400)的张量。这个形状的含义是8400个候选框每个框有84个通道前4个是框坐标剩下80个是COCO类别置信度。在Ultralytics的Python接口里这些已经封装好了你直接访问box.xyxy、box.conf、box.cls就行。但如果要自己走onnx推理或者做c部署必须手动切这个张量# 假设pred的shape是(1, 84, 8400) pred pred[0].transpose(1, 0) # (8400, 84) boxes pred[:, :4] # cx, cy, w, h conf pred[:, 4:].max(dim1) # 类别置信度YOLOv8的框坐标是中心点加宽高的形式cx, cy, w, h需要转成左上角右下角x1, y1, x2, y2再喂给后续模块。转换公式很简单x1 cx - w / 2 y1 cy - h / 2 x2 cx w / 2 y2 cy h / 2这一步不做后面ByteTrack的框坐标会全部错位跟踪轨迹会像鬼画符一样乱飘。3.2 后处理置信度过滤、NMS、坐标映射YOLOv8输出的8400个候选框不可能全用大部分是背景和重叠框必须先做后处理。标准三步走置信度过滤保留score大于阈值的框一般建议0.5左右。设太高容易漏检设太低会引入大量噪声检测跟踪器会被假目标干扰。NMS非极大值抑制把IoU超过阈值的重叠框合并成最优的一个。YOLOv8的python接口里自带NMS但如果走onnx推理需要自己调torchvision.ops.nms或者cv2.dnn.NMSBoxes。我习惯用torchvision的一行代码import torchvision keep torchvision.ops.nms(boxes, scores, iou_threshold0.45)坐标映射如果原始图像经过了letterbox等比缩放加灰边检测框的坐标是相对于缩放后图像的必须按缩放比例和填充偏移还原回原图坐标。这个坑非常隐蔽很多人图省事不做反向映射导致跟踪框和实际目标位置始终偏一点一旦画面里目标快速移动跟踪就彻底跟不上。3.3 tracker.update()前需要什么数据ByteTrack的update函数接收的数据格式非常朴素就是一个列表列表里每个元素是[x1, y1, x2, y2, score, cls]。注意这里score和cls分别指检测置信度和类别编号比直接喂一个结构体还简单。但朴素不意味着可以随便填有两条硬性要求坐标必须是原图坐标系不能是letterbox后的坐标系否则跟踪框会系统性偏移。score值必须是0到1之间的浮点数不能是0到100的整数ByteTrack内部会用score做置信度分层值域不对会让高低置信度匹配逻辑全部失效。我之前踩过一次坑检测模块用的置信度是百分比形式0到100忘了除以100就喂给跟踪器结果所有目标都被当成低置信度处理每个目标最多跟两帧就丢ID跳得惨不忍睹。排查了半天才发现是这个原因教训很深刻。3.4 第一帧为什么没有轨迹刚把跟踪器接好那会儿我第一帧运行完去看输出发现online_targets是空的吓得以为自己接错了。后来看了ByteTrack源码才明白这是正常的ByteTrack里所有目标初始状态都是tentative待确认只有连续若干帧都成功匹配上的目标才会变成confirmed已确认状态并出现在online_targets里。这背后其实是一个非常合理的设计逻辑单个帧的高置信度检测不足以证明这是一个稳定的目标。可能是误检、可能是反光、可能是贴图等多帧匹配通过之后再给ID能把假轨迹的数量降一个量级。所以如果你看到前几帧没有轨迹输出别怀疑代码坏了继续跑。一般第3到5帧之后稳定的目标就开始有ID了。4. GTX1660Ti实测帧率瓶颈与调优4.1 基准测试数据我把这套YOLOv8ByteTrack完整跑起来之后先测了一轮基准。显卡是GTX1660Ti 6GBCPU是i7-9750H内存16GB视频是1080p的交通监控片段。结果如下模型输入尺寸检测FPS检测跟踪FPS备注YOLOv8n640约52约34跟踪线程约35% CPU占用YOLOv8n960约25约19大目标更多小目标召回略好YOLOv8s640约33约24精度提升明显帧率仍可接受YOLOv8s1280约8约7基本不能实时注意这个FPS是包含跟踪开销的不是裸检测FPS。ByteTrack本身虽然计算量不大但Python的循环调度和对象创建销毁在每一帧都要做实际上还是会吃掉5到10帧的性能这是在意料之内的。结论是在GTX1660Ti上YOLOv8n配合640分辨率是能稳定跑30fps以上的组合如果对精度有更高要求YOLOv8s在640下也能维持在20fps以上对很多监控场景够用了。4.2 保帧率还是保精度这是每个人都会面临的取舍问题我的思路是分场景定策略如果做车流统计、早高峰人流量分析目标量小、画面变化慢YOLOv8s加640完全够用还兼顾了检测精度。如果做无人机视角、运动目标的实时追击那优先保证帧率YOLOv8n加640甚至480都行帧率越高跟踪越稳定——因为相邻两帧之间目标位移越小卡尔曼滤波预测和IOU匹配就越可靠。跑在嵌入式设备上时输入分辨率往往得降到320或416YOLOv8n才能勉强实时这时候精度损失大头不在模型本身而是小目标的检测能力。小目标本身就几十像素降到320就彻底糊了这类场景只能靠提高采集设备分辨率来补。还有一个很实用的技巧尽量保持输入帧率稳定。如果你的视频源是30fps就固定用30fps喂给跟踪器不要一会儿20fps一会儿10fps。ByteTrack的Kalman滤波参数是基于帧率初始化的帧率波动大时轨迹预测的噪声协方差估计会不准ID丢失率会明显上升。这个在代码里对应的是tracker初始化时的frame_rate参数实测下来这个参数设错了影响确实很大。4.3 跟踪器参数调整的心得ByteTrack的参数不多但每个都直接影响跟踪行为我列一下常用参数和作用参数默认值作用我的建议track_buffer30轨迹丢失后存活帧数遮挡频繁场景调到60match_thresh0.8匹配阈值值越低越严格目标密集场景调低到0.7min_box_area10过滤面积过小的框小目标场景调低到1det_thresh0.5检测器的初始阈值可以比检测后处理阈值低一点我实际使用中最常调的是track_buffer。行人场景里一个人走到柱子后面再走出来通常需要不到1秒30帧对应1秒其实够。但如果人走到广告牌后面、被完全遮挡更久ID就断了等出来时重新开一条轨迹。这种场景把track_buffer调到60效果立竿见影。但track_buffer不是越大越好设得太大有一个副作用目标确实已经离开了画面比如走出了摄像头视野范围轨迹却还在内存里驻留而且如果画面里恰好有一个新目标出现在预测位置附近它可能误继承一个该消失的ID。这个在人群密集时确实会发生所以要结合场景权衡。match_thresh这个参数也值得说。它控制的是当前位置匹配和新轨迹开启之间的松紧度。默认0.8的时候新目标很容易就开启新轨迹ID容易飘调低到0.5匹配要求更严格但某些新目标可能要好几帧才能确认轨迹出现得更慢。我的习惯是先跑一段看效果如果ID不停跳就降match_thresh如果轨迹迟迟不出现就升一点。它其实比det_thresh对跟踪体验的影响更直接。4.4 跟踪和批量推理的冲突很多人想把性能榨干会用batch推理同时处理多路视频流每个batch里放4帧不同摄像头的画面。这里有个容易被忽略的点ByteTrack的update逻辑是强单帧、强串行的。它内部维护的轨迹状态本质上是上一帧匹配完的结果你如果同时对4帧图像调用update没有天然的顺序关系状态就乱了。正确的做法是多路视频流各自维护一个独立的tracker实例每个tracker只处理自己这一路的帧。模型部分可以共享一个batch推理检测结果按路拆回去分别喂给对应的tracker做update。代码上不复杂但性能差别很大。我一开始图省事共享一个tracker结果两路视频的ID互相串车A的轨迹跑到了车B头上调了好几天才反应过来是共享状态导致的。5. 往嵌入式设备搬RK3588部署落地代码在PC上跑通只是第一步很多项目最终要落到嵌入式设备上。我自己在RK3588上完整部署过一次踩了不少坑这里把关键步骤和要注意的事都写了。5.1 ONNX导出时要注意的细节从YOLOv8导出ONNX其实很简单Ultralytics官方API一行就完成了from ultralytics import YOLO model YOLO(yolov8n.pt) model.export(formatonnx, opset12, simplifyTrue, dynamicFalse)但有几个细节必须处理否则后面RKNN转换会非常难受opset版本不要太新。RKNN工具链对opset 12到15支持最好opset 17以上的新算子经常报“不支持的op”。建议加上simplifyTrue用onnxsim对计算图做一轮常量折叠和结构优化减小体积还经常能把一些不支持的算子消除掉。如果不需要动态输入动态分辨率dynamic参数设FalseRKNN工具链对动态shape支持不友好可能转换出来只是名义上支持实际推理慢很多。导出后务必用onnxruntime加载一遍推理一张图确认输出shape正确。这一步能筛掉90%的“导出出错但没报错”的暗坑。如果想要更高的推理性能可以半精度FP16导出ONNX但RK3588的NPU对FP16的支持取决于固件版本实测下来很多情况下RKNN工具链会把FP16自动转回FP32收益不明显不如在RKNN量化阶段做INT8。5.2 RKNN转换流程和量化细节RKNN转换我用的rknn-toolkit2。整个流程是ONNX → 读取 → 配置量化 → 生成.rknn → 板端加载推理。核心代码大致是from rknn.api import RKNN rknn RKNN() rknn.config(mean_values[[0, 0, 0]], std_values[[255, 255, 255]], target_platformrk3588) rknn.load_onnx(modelyolov8n.onnx) rknn.build(do_quantizationTrue, datasetcalib.txt) rknn.export_rknn(yolov8n.rknn)几个关键点mean_values和std_values必须和训练时的预处理一致。YOLOv8训练时用的是0到1的归一化所以RKNN这边mean填0、std填255其实等价于除255顺序别搞错。我们当时搞反了一次所有输出框的置信度全变成0排查到最后一头雾水。量化数据集dataset文件里每行放一张图片路径建议放50到100张和实际场景相近的真实图片。我建议拿你实际要处理的监控画面做校准集别用COCO数据集随便抽几张那样量化误差会大不少。如果量化后精度下降太过离谱比如mAP掉了10个点以上先检查校准图片的质量够不够、目标分布覆盖够不够全。通常校准集覆盖好YOLOv8n量化后掉0.5到1个点基本可用。量化之后一定要跑板端验证看看实际输出的置信度分布和PC上是否一致。RKNN里默认的ANCHOR等配置对YOLOv8可能不匹配但Ultralytics导出的ONNX自带解码层正常情况下转换成RKNN后输出格式不变不需要额外配置。这句话可能有点绕翻译成人话就是不管用不用RKNN你的后处理代码应该和PC端完全一样。5.3 板端推理的工程要点RK3588上部署完帧率其实比我想象的好。用YOLOv8n加INT8量化输入640分辨率NPU纯推理大概在20到30毫秒一帧也就是30fps上下。加上后处理和ByteTrack整体还能稳定在25fps左右。这个结果对嵌入式设备来说相当不错了。但工程上还是有几件事必须处理NPU推理和Python后处理之间不要频繁拷贝内存。从NPU拿到输出tensor后一次性拷到CPU再解析不要每取一个字段就拷一次延迟会翻倍。在板端ByteTrack的Python实现够用但要把det_thresh和match_thresh重新调一遍因为量化后的置信度分布和浮点版本有轻微偏移直接用PC端的阈值会丢目标。如果想更进一步建议把后处理和跟踪都用C重写板端的Python启动开销和GC开销在长时间运行时会被放大C版本延迟更稳。我当时保留了Python管线做验证正式版本换成了C跑24小时无压力。RK3588的CPU是大核加小核混搭建议用taskset把推理线程绑定在A76大核上否则线程可能在A55小核上被调度帧率直接砍半。这个小技巧当时帮我们白捡了将近10帧。6. 想跑自己的场景数据标注与模型再训练用预训练模型跑通整个链路只是开始真正要落地到自己的场景必然要有自己的数据、训练自己的模型。很多刚上手的朋友在这块会卡很久这节把关键流程和常见误区都梳理一遍。6.1 标注工具和最小数据集数据标注工具我用得比较多的是LabelImg和LabelStudio。LabelImg更轻量适合快速标一批小数据集LabelStudio支持多种格式、多人协作适合正式量产数据。YOLOv8训练自己的数据集目录结构要符合它的规范dataset/ images/ train/ val/ labels/ train/ val/ data.yaml标注文件必须跟对应的训练图片同名且是txt格式每行内容是类别编号 归一化中心坐标 归一化宽高。建议第一次试点类别可以少一点。比如我当年做车牌检测只用CCPD2020数据集里的三万个样本先跑通再扩数据。不要一上来就想要一万张图的完美数据集——先拿100张图把一个类标出来训练一把看看整个闭环跑通没有再往里堆数据。CCPD2020这类公开数据集在下载的时候要注意它的目录结构和你自己标注的格式不一定一样可能需要写脚本转换一下。当时我写了一个格式转换脚本放在项目里后面用起来就方便多了。6.2 训练配置和损失曲线判断训练命令不复杂yolo detect train datadataset/data.yaml modelyolov8n.yaml pretrainedyolov8n.pt epochs100 batch8 img640关键参数解释一下model参数用yolov8n.yaml这个yaml文件定义的是网络结构根据你的类别数自动确定输出维度。pretrained参数给预训练权重强烈建议用。从零训练一个检测器收敛太慢用预训练权重做迁移学习几百张图也能快速见到效果。batch的大小取决于显存。6GB显存跑YOLOv8nbatch设8到16比较稳设太大会OOM。epochs建议先跑100观察结果再决定。训练的时候终端会每轮打印一堆指标核心要盯着的是box_loss、cls_loss和dfd_loss这几个损失值。我个人的判断经验是如果train loss下降但val loss也在下降正常。继续跑。如果train loss持续下降而val loss开始回弹过拟合了要加数据增强或者调低epoch。如果train loss和val loss都挂在原地不动多半是学习率太高或者数据有问题先检查标注文件是否正常比如有没有标出画面范围的外框。6.3 损失函数曲线怎么画训练过程中YOLOv8默认会在run/expN目录下生成results.csv里面记录了每一轮的loss和各项指标。想画成曲线图我通常直接用小工具脚本import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/detect/train/results.csv) plt.figure(figsize(12, 6)) plt.plot(df[ epoch], df[ train/box_loss], labelbox_loss) plt.plot(df[ epoch], df[ val/box_loss], labelval_box_loss) plt.legend() plt.savefig(loss_curve.png)注意results.csv里列名的空格很多直接用pandas读取后建议先print(df.columns)看下精确列名再写代码。6.4 从训练到推理的闭环验证训练完会生成best.pt和last.pt。best.pt是验证集表现最好的一般用它做推理。替换掉原始yolov8n.pt后重新跑检测跟踪注意一个细节如果你的数据集类别数不是80YOLOv8输出张量的维度就变了从84变成4你的类别数。我记得第一次用自己训练的车牌检测模型接ByteTrack的时候忘了这一层直接拿新模型喂给原跟踪管线前几帧看着正常但每次输出解析都报数组越界后来发现是后处理里硬编码了类别数80。改成dynamic从模型输出维度推断之后就好了。所以接自己训练的模型时务必检查后处理代码里的类别数是不是和训练配置保持一致否则看着能跑实际逻辑已经错了帧率再高也是白搭。6.5 YOLOv8-pose和注意力机制改进的扩展方向如果你的应用需要看人的姿态比如判断摔倒、统计动作次数可以在同一套代码架构上从detect任务换成pose任务。Ultralytics官方有YOLOv8pose的预训练模型输出从目标框变成17个关键点标注阶段就需要做关键点标注而不是普通的框标注。数据标注操作上比目标检测多一步每个目标的每个关键点都要点工具还是LabelStudio但配置方式不一样需要导入关键点模板。另外很多人在YOLOv8的C2f模块里集成注意力机制做改进比如把ECA模块加到backbone后理论上小目标和遮挡场景的检测精度会提升。这类改进我们自己也试过效果有但不是每次都能稳定涨点。如果刚接触建议先跑通baseline再记录精度数据再去加模块对比不要上来就各种魔改不然出了问题都不知道是哪个环节引起的。7. 一套完整的多目标跟踪Demo拿来就能抄最后贴一个整合好的最小Demo代码从视频读取到跟踪结果可视化输出可以直接复制到你的工程里跑。这个版本是PC端版本模型可用官方yolov8n.pt也支持换成自己训练好的权重。import cv2 import torch from ultralytics import YOLO from byte_tracker import BYTETracker class Args: track_buffer 30 match_thresh 0.8 min_box_area 1 det_thresh 0.5 frame_rate 30 def process_frame(frame, model, tracker, classes_of_interestNone): results model(frame, verboseFalse) dets [] for r in results: for box in r.boxes: cls int(box.cls[0].item()) if classes_of_interest is not None and cls not in classes_of_interest: continue x1, y1, x2, y2 box.xyxy[0].tolist() score box.conf[0].item() dets.append([x1, y1, x2, y2, score, cls]) online_targets tracker.update(dets, (frame.shape[0], frame.shape[1])) for t in online_targets: x, y, w, h t.tlwh x, y, w, h int(x), int(y), int(w), int(h) # 过滤掉面积过小的轨迹 if w * h args.min_box_area: continue cv2.rectangle(frame, (x, y), (x w, y h), (0, 255, 0), 2) cv2.putText(frame, f{t.track_id}, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) return frame if __name__ __main__: args Args() model YOLO(yolov8n.pt) tracker BYTETracker(args, frame_rateargs.frame_rate) cap cv2.VideoCapture(test.mp4) while cap.isOpened(): ret, frame cap.read() if not ret: break frame process_frame(frame, model, tracker) cv2.imshow(YOLOv8 ByteTrack, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这个Demo里我没有加NMS是因为Ultralytics的model推理结果默认已经做过NMS了。但如果你改成onnxruntime推理NMS记得要自己加回来否则重叠框会非常多跟踪ID会乱套。如果视频分辨率很高2K以上建议先做缩放再进模型否则检测耗时和显存占用会成倍增长跟踪本身也没必要在这么高分辨率下做——跟踪器的匹配精度主要靠检测框位置的相对关系而不是绝对像素数量。这套代码我实际跑下来在GTX1660Ti上yolov8n接这个管线1080p视频能稳定维持在30fps以上CPU占用也不高。如果你在PC上调试可以先从这段代码起手把整个流程跑通后再考虑性能优化。在RDMA实时处理多路视频的场景下把这段逻辑封装成类、每个视频流创建独立实例扩展性会更好。8. 一点个人体会YOLOv8和ByteTrack这套组合原理上并不复杂但因为它是两个独立模块拼起来的真正的坑基本都在接口对接、参数匹配和版本兼容这类工程细节上。不要指望把代码下载下来直接就能满帧跑先花半天时间把检测输出和跟踪器输入对齐后面的事情就会顺利很多。我自己的习惯是不管别人给的项目代码多完整拿到手先花一点时间看一眼ByteTrack的update函数输入输出格式跟着跑通一个最小demo再逐步加功能。这样出现问题的时候你清楚地知道问题出在检测模块、跟踪模块还是后处理模块而不是一边看日志一边猜。如果你对某些细节有疑问比如卡尔曼滤波的预测公式、ByteTrack两步匹配的完整流程或者RKNN量化的具体参数建议拿到代码之后直接从代码里阅读一遍。它的实现比论文里的描述要直观得多读完你会有一种“原来就这么简单”的顿悟感。祝大家跑通顺利。本文还有配套的精品资源点击获取
返回列表