首页 / 资讯中心 / 文章详情

篮球运动员检测数据集YOLOv5训练实战:从数据格式到模型部署

篮球运动员检测数据集YOLOv5训练实战:从数据格式到模型部署 ★ FEATURED ARTICLE
简介这份资源是面向计算机视觉初学者与目标检测实践者的篮球运动员检测YOLO格式数据集可直接用于PyTorch框架下的模型训练与算法验证。数据采集自篮球比赛视频与图片覆盖不同场景、角度和光照条件并经过人工标注与格式转换标注类别为篮球运动员适合作为目标检测课程作业、毕业设计或算法对比实验的素材。压缩包共2000个文件包含1484个txt标注文件、514张jpg图像以及2个yaml配置文件整体约122.82MB其中txt对应YOLO格式的边界框与类别信息jpg为原始训练图像yaml用于定义数据集路径与类别名称。数据集已按训练、验证、测试划分省去繁琐的预处理环节。目前已有1037人学习下载读者可借此快速搭建检测流程理解标注规范与数据组织方式并在此基础上开展模型微调与性能评估。1. 篮球运动员检测数据集为什么一个 YOLO 格式的 zip 包值得单独讲篮球场景的目标检测和常规行人检测完全不是一回事。球员在高速跑动中频繁遮挡、肢体交叠、姿态剧烈变化加上场边观众、裁判、教练这些干扰目标一个在 COCO 上跑得不错的模型直接拿来用mAP 大概率会掉一大截。Basketball-Players-yolov5pytorch.zip 这个数据集的价值就在于它已经把篮球运动员这个特定类别标注好并且直接整理成了 YOLOv5 和 PyTorch 能吃的格式省掉了从原始标注到训练格式转换这一大段最容易翻车的环节。这个数据集适合三类人一是想跑通 YOLOv5 训练自己数据集流程的新手拿它当练手素材比拿 COCO 子集友好得多二是做体育视频分析、球员追踪、战术统计的从业者需要一个干净的起点三是已经在用 YOLOv5 但想验证自己数据管线是否正确的人用它做端到端 sanity check。下面从数据集的目录结构开始拆一路讲到训练参数怎么调、坑在哪里。2. 拆开这个 zip目录结构、标注格式与数据分布2.1 YOLOv5 数据集的标准目录长什么样拿到 Basketball-Players-yolov5pytorch.zip 之后第一件事不是急着解压训练而是先看清楚它的组织方式。YOLOv5 对数据集的目录结构有约定常见做法是长这样Basketball-Players-yolov5pytorch/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamlimages 下面放 jpg 或 pnglabels 下面放同名的 txt 标注文件。注意是「同名」——images/train/0001.jpg对应labels/train/0001.txt文件名必须严格一致扩展名不同但主名相同。YOLOv5 在加载时会自动做这个映射如果对不上训练时会出现大量「missing labels」警告最终表现为 loss 不下降或者直接报找不到标签。data.yaml 是整个数据集的入口配置文件内容一般包含训练集、验证集路径类别数和类别名。篮球运动员数据集通常只有一个类别但也不排除把裁判、观众单独标出来的版本。先打开 data.yaml 确认 nc 和 names 字段这决定了你后面模型输出头的维度。2.2 标注格式YOLO txt 的五个数字到底怎么读YOLO 格式的标注文件每行代表一个目标格式是class_id x_center y_center width height后四个值全部是归一化到 0~1 之间的浮点数相对于整张图的宽高。举个例子一张 1920×1080 的图里有个球员的框在像素坐标 (400, 300) 到 (600, 700)那么x_center (400600)/2 / 1920 0.2604y_center (300700)/2 / 1080 0.4630width (600-400) / 1920 0.1042height (700-300) / 1080 0.3704所以那一行就是0 0.2604 0.4630 0.1042 0.3704。这里最容易翻车的地方是有人拿到的原始标注是 VOC 的 xml 或者 COCO 的 json自己写脚本转的时候忘了归一化或者把 xmin/ymin 当成了中心点。训练时 loss 会异常大模型学出来全是乱框。用下面这段脚本快速检查标注是否合法import os import numpy as np label_dir Basketball-Players-yolov5pytorch/labels/train bad_files [] for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue path os.path.join(label_dir, fname) with open(path) as f: for i, line in enumerate(f): parts line.strip().split() if len(parts) ! 5: bad_files.append((fname, i, 字段数不对)) continue cls, x, y, w, h parts vals [float(x), float(y), float(w), float(h)] # 归一化值必须在 0~1 之间宽高必须大于 0 if any(v 0 or v 1 for v in vals): bad_files.append((fname, i, 值超出0~1范围)) if float(w) 0 or float(h) 0: bad_files.append((fname, i, 宽高非正)) print(f问题标注数: {len(bad_files)}) for item in bad_files[:20]: print(item)这段脚本做三件事检查每行是否恰好 5 个字段、检查坐标是否在 0~1 之间、检查宽高是否为正。参数上不需要调什么直接跑就行。如果问题标注超过总量的 1%建议先清洗再训练否则模型会学到噪声。2.3 数据分布训练集、验证集、测试集的比例与类别均衡一个整理好的篮球运动员数据集常见划分是 train:val:test 大约 7:2:1 或者 8:1:1。你需要确认三件事训练集和验证集的场景是否同分布比如不要训练集全是室内场、验证集全是室外场、每个子集里球员数量是否足够、有没有空标注文件图片里没有球员但文件存在且为空这是合法的负样本但比例不能太高。用几行命令快速统计# 统计各子集图片数量 for split in train val test; do echo -n $split images: ls Basketball-Players-yolov5pytorch/images/$split | wc -l echo -n $split labels: ls Basketball-Players-yolov5pytorch/labels/$split | wc -l done # 统计标注框总数和空文件数 find Basketball-Players-yolov5pytorch/labels/train -name *.txt -empty | wc -l cat Basketball-Players-yolov5pytorch/labels/train/*.txt | wc -l如果 images 和 labels 数量对不上说明有图片没有对应标注或者反过来。空标注文件如果占比超过 10%要想想是不是标注遗漏而不是真的负样本。这些检查花不了五分钟但能省掉后面几个小时的无效训练。3. 从零跑通 YOLOv5 训练环境、配置与启动命令3.1 PyTorch 环境搭建与 YOLOv5 代码拉取训练之前先把环境弄干净。PyTorch 的安装和显卡驱动、CUDA 版本强相关这一步的玄学最多。我一般会先确认显卡驱动支持的 CUDA 上限再去 PyTorch 官网选对应版本。不要盲目pip install torch那样装到的可能是 CPU 版本训练时你会发现 GPU 利用率一直是 0。# 创建独立环境避免和系统 Python 打架 conda create -n yolo-basketball python3.9 -y conda activate yolo-basketball # 按你的 CUDA 版本选这里以 CUDA 11.8 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 验证 GPU 是否可用 python -c import torch; print(torch.cuda.is_available(), torch.cuda.get_device_name(0))如果输出是True加上你的显卡型号说明环境没问题。如果输出False先别急着往下走检查驱动版本和 CUDA 是否匹配。这一步翻车的人太多了conda 环境里装完发现用的是另一个环境的 torch或者系统里有多个 CUDA 版本冲突。接着拉取 YOLOv5 代码并安装依赖git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txtrequirements.txt 里锁定了各个依赖的版本范围不要随意升级里面的包尤其是 numpy 和 opencv版本不兼容会导致训练中途报奇怪的错。3.2 data.yaml 怎么写路径、类别数与类别名把数据集解压到一个固定位置然后修改或新建 data.yaml。假设解压后路径是/data/Basketball-Players-yolov5pytorch那么 data.yaml 内容如下# 数据集根路径YOLOv5 会基于这个路径拼接 train/val path: /data/Basketball-Players-yolov5pytorch train: images/train val: images/val test: images/test # 类别数篮球运动员数据集通常为 1 nc: 1 # 类别名顺序必须和标注里的 class_id 对应 names: 0: player这里有几个参数必须说清楚。path是根目录train和val是相对路径YOLOv5 会自动拼成/data/Basketball-Players-yolov5pytorch/images/train。如果你写成绝对路径也能跑但换机器就要改不推荐。nc必须和标注里出现的最大 class_id 加一一致如果标注里只有 0那 nc 就是 1。names的顺序不能乱class_id 为 0 的框会被赋予 names 里键为 0 的名字。一个常见错误是 data.yaml 里写了nc: 1但标注文件里出现了 class_id 为 1 的行训练时不会报错但类别 1 会被当成背景或者直接忽略模型学出来的结果莫名其妙。所以前面检查标注那一步不能省。3.3 启动训练命令行参数逐个拆解环境好了、配置对了就可以启动训练。YOLOv5 的训练入口是 train.py最简命令python train.py \ --data /data/Basketball-Players-yolov5pytorch/data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --project runs/train \ --name basketball_yolov5s逐个参数解释。--weights yolov5s.pt表示从预训练权重开始微调这是小数据集能训出效果的关键从零开始训几乎不可能收敛好。--img 640是输入分辨率篮球场景里球员大小差异大640 是速度和精度的平衡点显存够可以上 1280。--batch 16是批大小显存不够就降到 8 或 4但太小会让 BatchNorm 统计不稳定。--epochs 100对篮球数据集通常够用如果验证集 mAP 在 50 轮后还在涨可以加到 200。--project和--name决定输出目录训练日志、权重、混淆矩阵都会存在runs/train/basketball_yolov5s下面。训练启动后重点看几个输出每个 epoch 的 box_loss、obj_loss、cls_loss 是否在下降验证集的 mAP0.5 是否在上升。如果 box_loss 一直不降回去检查标注格式如果 obj_loss 震荡剧烈可能是 batch size 太小或者学习率太高。3.4 训练过程监控与中断恢复训练不是启动完就不管了。YOLOv5 会在 runs/train/ 下生成 results.csv记录每个 epoch 的所有指标。用下面这段脚本画个曲线比盯着终端刷屏直观import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/train/basketball_yolov5s/results.csv) df.columns df.columns.str.strip() # 列名可能带空格 fig, axes plt.subplots(1, 2, figsize(12, 4)) axes[0].plot(df[epoch], df[train/box_loss], labelbox_loss) axes[0].plot(df[epoch], df[train/obj_loss], labelobj_loss) axes[0].set_xlabel(epoch) axes[0].legend() axes[0].set_title(Training Loss) axes[1].plot(df[epoch], df[metrics/mAP_0.5], labelmAP0.5) axes[1].plot(df[epoch], df[metrics/mAP_0.5:0.95], labelmAP0.5:0.95) axes[1].set_xlabel(epoch) axes[1].legend() axes[1].set_title(Validation mAP) plt.tight_layout() plt.savefig(training_curve.png, dpi150)如果训练中途断了不用从头来。YOLOv5 支持--resume参数python train.py --resume runs/train/basketball_yolov5s/weights/last.pt它会从 last.pt 里恢复优化器状态、epoch 数和学习率调度接着上次继续。注意--resume后面跟的是权重文件路径不是目录。这个功能在云服务器按小时计费时特别有用断了重启不用重跑。4. 避坑与排查篮球数据集训练中最容易翻车的五件事4.1 现象训练 loss 正常下降但验证 mAP 始终接近 0原因通常出在 data.yaml 的路径或者类别名上。YOLOv5 在验证时会重新读一遍 val 路径如果路径写错它可能加载到空数据集或者错误的图片导致验证指标无意义。另一个可能是 val 集里的标注文件和图片没有正确对应验证时找不到标签全部按背景处理。解决办法先用python val.py --data your_data.yaml --weights runs/train/exp/weights/best.pt单独跑一次验证看输出里的val: Scanning...那行统计了多少张图、多少个标签。如果标签数为 0就是路径或对应关系的问题。再检查 data.yaml 里 names 的键是否从 0 开始连续。4.2 现象显存溢出报 CUDA out of memory原因可能是 batch size 太大、img size 太大或者没有及时释放缓存。篮球数据集图片分辨率如果很高比如 4K 视频抽帧即使 batch 设成 8 也可能爆显存。解决办法先把--batch降到 4 或 2同时把--img从 640 降到 416 试试。如果还不行用--rect开启矩形训练减少 padding 浪费。另外可以在训练脚本里加torch.cuda.empty_cache()但更根本的是匹配显存和参数。RTX 3060 6G 显存跑 yolov5s 640 batch 8 是安全的再大就要降。4.3 现象模型把观众、裁判也框成球员原因在于数据集的标注策略。如果原始数据集只标了球员但画面里有大量观众模型会把外观相似的观众也学进去。篮球场边观众穿着各异但坐姿和站姿与球员有区别模型没学好边界。解决办法先确认数据集是否真的只标了球员。如果标注里确实只有球员那需要在训练时增加负样本也就是把包含观众但不含球员的图片加入训练集标注文件留空。空标注文件是合法的负样本能让模型学会区分。另外可以调低--conf-thres观察误检来源如果误检集中在观众区就针对性地补负样本。4.4 现象训练到一半 loss 突然变成 nan原因通常是学习率太高、标注里有非法值比如坐标是 nan 或者超出范围、或者某张图片损坏。YOLOv5 默认学习率是 0.01对小数据集可能偏大。解决办法先用前面 2.2 的脚本全量检查标注排除非法值。然后用--lr0 0.001降低初始学习率重跑。如果还是 nan检查图片是否有损坏的用 PIL 批量打开一遍from PIL import Image import os img_dir Basketball-Players-yolov5pytorch/images/train for fname in os.listdir(img_dir): try: img Image.open(os.path.join(img_dir, fname)) img.verify() except Exception as e: print(f损坏图片: {fname}, {e})损坏图片会让数据加载器产生异常值进而污染梯度。删掉或修复这些图片再训练。4.5 现象推理时框的位置整体偏移原因多半是训练时的 img size 和推理时的 img size 不一致或者 letterbox 填充处理有问题。YOLOv5 在推理时会自动做 letterbox但如果你的图片长宽比和训练时差异极大映射回原图时会有偏差。解决办法推理时显式指定和训练一致的--img参数。用detect.py时加上--img 640并且确认--nosave没开。如果还是偏检查是不是自己写了后处理脚本把归一化坐标转像素坐标时用错了宽高基准。YOLOv5 输出的框是相对于 letterbox 后图像的需要减去 padding 再缩放回原图这一步自己实现容易出错建议直接用官方non_max_suppression和scale_coords。5. 进阶技巧用这个数据集验证你的完整推理管线训练出 best.pt 只是第一步真正落地要验证从图片输入到框输出的完整链路。我一般会拿这个数据集里的测试集图片跑一遍 detect.py再手动核对几张确认没有系统性偏移。python detect.py \ --weights runs/train/basketball_yolov5s/weights/best.pt \ --source /data/Basketball-Players-yolov5pytorch/images/test \ --img 640 \ --conf-thres 0.25 \ --iou-thres 0.45 \ --save-txt \ --project runs/detect \ --name basketball_test--save-txt会把检测结果按 YOLO 格式存下来方便和真值对比。--conf-thres 0.25是置信度阈值篮球场景建议不要设太高因为遮挡球员的置信度天然偏低设 0.5 会漏掉很多。--iou-thres 0.45是 NMS 的 IoU 阈值球员密集时适当调高到 0.5 可以减少漏检但太高会导致同一个球员出多个框。跑完之后用下面这段脚本算一下测试集上的简单指标心里有个数import os import numpy as np def load_labels(path): boxes [] if not os.path.exists(path): return boxes with open(path) as f: for line in f: parts line.strip().split() if len(parts) 5: boxes.append([float(x) for x in parts[1:]]) return np.array(boxes) def iou(box1, box2): # box格式: x_center, y_center, w, h b1 [box1[0]-box1[2]/2, box1[1]-box1[3]/2, box1[0]box1[2]/2, box1[1]box1[3]/2] b2 [box2[0]-box2[2]/2, box2[1]-box2[3]/2, box2[0]box2[2]/2, box2[1]box2[3]/2] inter_x1 max(b1[0], b2[0]) inter_y1 max(b1[1], b2[1]) inter_x2 min(b1[2], b2[2]) inter_y2 min(b1[3], b2[3]) if inter_x2 inter_x1 or inter_y2 inter_y1: return 0.0 inter (inter_x2 - inter_x1) * (inter_y2 - inter_y1) area1 (b1[2]-b1[0]) * (b1[3]-b1[1]) area2 (b2[2]-b2[0]) * (b2[3]-b2[1]) return inter / (area1 area2 - inter) gt_dir /data/Basketball-Players-yolov5pytorch/labels/test pred_dir runs/detect/basketball_test/labels total_gt, total_pred, matched 0, 0, 0 for fname in os.listdir(gt_dir): gt load_labels(os.path.join(gt_dir, fname)) pred load_labels(os.path.join(pred_dir, fname)) total_gt len(gt) total_pred len(pred) for g in gt: for p in pred: if iou(g, p) 0.5: matched 1 break print(fGT框数: {total_gt}, 预测框数: {total_pred}, IoU0.5匹配数: {matched}) print(f召回率: {matched/total_gt:.3f}, 精确率: {matched/total_pred:.3f})这段脚本算的是 IoU 0.5 下的匹配情况能快速看出模型是漏检多还是误检多。召回率低就降 conf 阈值或者补训练数据精确率低就升 conf 或者加负样本。最后说一个我自己的习惯每次拿到新数据集先拿 10 张图跑一遍推理肉眼看完再开始训练。这一步花十分钟能提前发现标注错位、类别搞反、图片损坏这些低级问题。训练本身不贵贵的是训完发现数据有问题重来。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站