尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

YOLO11行人检测实战:三种标注格式数据集与多平台训练避坑指南

YOLO11行人检测实战:三种标注格式数据集与多平台训练避坑指南 简介这份资源是面向目标检测学习者和算法工程师的行人检测数据集配套说明聚集1000张真实场景行人图像覆盖校园、街景、道路、遮挡及严重遮挡等丰富样本适用于公共场所监控行人检测项目也可作为通用行人检测数据集的场景补充。因原始数据集体量较大托管于百度网盘本下载包为1个PDF文件约4.17MB内附数据集基本情况、缩略图、labelimg标注截图以及网盘获取方式。已有1045人学习适合需要高质量行人标注数据并希望快速上手YOLO系列训练的读者。PDF中详细说明VOC(xml)、COCO(json)、YOLO(txt)三种标注格式的目录结构与标签规范可直接接入常见目标检测框架同时附赠YOLO11一键训练脚本覆盖GPU(GPUs)、CPU、Mac(M芯片)三平台运行方案并提供博主训练结果日志供对比参考能帮助使用者减少数据集适配与训练配置的重复工作把更多精力放在模型调优和项目落地环节。1. 行人检测数据集与 YOLO11一份能直接开训的监控场景数据集我拿到这份行人目标检测数据集的第一反应是先去翻标注文件而不是急着看训练脚本。1000 张真实场景图覆盖校园行人、街景行人、道路行人、遮挡行人和严重遮挡行人这些正是公共场所监控项目里最头疼的画面。更省事的是同一批图直接给好了 VOC(xml)、COCO(json)、YOLO(txt) 三种标签格式跑 YOLO11 时不用自己拿 labelimg 重新标一遍也不用在格式转换里折腾半天。包里还附了一个支持 GPU(GPUs)、CPU、Mac(M芯片) 三平台的 YOLO11 一键训练脚本以及博主当时的训练日志拿来就能对照着复现。这套资源适合三类人一是要快速出监控场景行人检测 demo 的工程师二是想拿真实数据把 YOLO11 训练流程完整跑一遍的入门者三是被 COCO/VOC/YOLO 格式转换恶心过、只想安心调参的老手。下面我按实际拆包的顺序把三种标签格式怎么选、目录怎么组织、三平台训练怎么跑以及我踩过的几个坑一次说清楚。2. 三种标注格式的差异与选型逻辑VOC、COCO、YOLO 到底该用哪个很多行人检测项目卡住不是因为模型而是因为标签格式不对齐。同一份数据labelimg 默认存 VOC 格式但 YOLO 要 txtMMDetection 系要 COCO json换一个框架就要换一种格式。这份资源把三种都给了反而第一个要解决的问题变成你当前项目到底该用哪一份。2.1 VOC(xml)labelimg 默认产物与目录结构VOC 格式是 labelimg 保存时的默认选择也是这个数据集标注的原生格式。每个 xml 文件对应一张图片里面用annotation包裹整张图信息object节点下记录类别名name和检测框bndbox框坐标是xmin, ymin, xmax, ymax的绝对像素值。这种格式最大的优点是可以直接用 labelimg 打开继续改缺点是你没法把它直接喂给 YOLO 训练。我拿到 VOC 标注后做的第一件事是统计类别和框数量确认数据没标乱。比如这个行人数据集理论上只有一个 person 类别如果统计出来出现 person 和 pedestrian 两种名字转格式时类别编号就会全乱。import glob import xml.etree.ElementTree as ET xmls glob.glob(VOC/Annotations/*.xml) stats {} for p in xmls: root ET.parse(p).getroot() for obj in root.iter(object): name obj.findtext(name) stats[name] stats.get(name, 0) 1 print(stats)这段脚本用ET.parse解析每一个 xmlroot.iter(object)遍历所有目标框findtext(name)取出类别名并累加统计。跑完之后你会看到类似{person: 5100}这样的结果。如果出现两个 key说明标注名称不统一需要先改名再转换。参数上要注意xml.etree.ElementTree是 Python 标准库不需要额外安装但 xml 文件如果是中文编码ET.parse一般能处理手动改文件时反而容易踩编码坑。2.2 COCO(json)统一 annotations 里的 bbox 与 category_idCOCO 格式把整份数据集的所有标注塞进一个 json 文件里核心是images、annotations、categories三块。images里记录每张图的 id、文件名、宽高annotations里记录每个目标框属于哪张图、类别 id 和 bboxcategories负责把 id 映射到类别名。COCO 的 bbox 是[x, y, width, height]注意是左上角坐标加宽高而且单位是像素不是归一化值。这个行人数据集只检测人categories里通常只有一项category_id 一般从 1 开始。这和 YOLO 从 0 开始的习惯不一样是后续转换最容易出错的地方。下面这段脚本用来快速确认 json 是不是完整可读import json with open(COCO/annotations.json, r, encodingutf-8) as f: coco json.load(f) print(images:, len(coco[images])) print(annotations:, len(coco[annotations])) print(categories:, coco[categories])这段代码用json.load读入整个标注文件len(coco[images])应该接近 1000因为资源里有 1000 张图annotations数量会明显大于 1000因为街景中一张图经常有好几个行人。categories打印出来应该是[{id: 1, name: person, supercategory: none}]之类的结构。如果这里的 id 不是 1后面转 YOLO 标签时必须处理偏移否则类别编号错位。2.3 YOLO(txt)归一化坐标与类别编号的对齐问题YOLO 格式每个 txt 文件对应一张图每行一个目标格式是class x_center y_center width height全部是归一化值。归一化意味着x_center和width要除以图片宽度y_center和height要除以图片高度所以同一个目标在不同分辨率图片里的 txt 内容可以直接放进同一批训练。这也是 YOLO 系训练最省事的格式。但坑也在类别编号上。YOLO 的类别编号必须从 0 开始如果这份数据集只有 person 一个类那所有 txt 里的第一列应该全是 0。COCO json 里 person 的 category_id 是 1如果转换工具忘了减一你拿到的 txt 第一列全是 1而data.yaml里nc: 1训练时会直接把编号 1 当不存在最终 mAP 为 0。import glob for p in glob.glob(YOLO/labels/*.txt): for line in open(p, r): parts line.split() cls int(float(parts[0])) if cls ! 0: print(funexpected class{cls} in {p}) if len(parts) ! 5: print(fbad line: {p}: {line})这段脚本遍历所有 YOLO 标签检查每一行是不是 5 列、类别编号是不是 0。parts[0]是第一列类别编号len(parts) ! 5说明坐标列数不对。如果打印出大量行说明这份 txt 的类别编号有问题需要重新做一次 COCO 到 YOLO 的转换。参数上要注意有些工具会用制表符分隔而不是空格split()不传参时会自动按空白切分能兼容两种情况。三种格式的选型逻辑很直接看你的训练框架就行格式后缀bbox 表示类别编号YOLO11 直接用VOC.xmlxmin,ymin,xmax,ymax 像素字符串名不能需转换COCO.jsonx,y,width,height 像素从 1 开始不能需转换YOLO.txt归一化中心坐标宽高从 0 开始能直接用如果你只跑 YOLO11直接用 YOLO txt 就行如果你要对比 DeiM、MMDetection 这类算法COCO json 更通用因为很多检测头支持加载 COCO 预训练权重做初始化如果你还要用 labelimg 继续修标注那就保留 VOC 原版。我的习惯是 YOLO 格式作为训练主格式VOC 留底COCO 给对比实验。3. 把数据集跑进 YOLO11一键训练脚本拆解与关键参数格式看清之后下一步是把这套数据真正跑进 YOLO11。这个环节最容易翻车的不是训练本身而是目录结构和data.yaml对不上。下面按我拆包时的顺序来。3.1 目录组织先理顺 train/val 与 labels 的对应关系解压后不管资源里怎么排建议手动整理成 Ultralytics 默认能识别的结构。常见做法是images/train、images/val、labels/train、labels/val四个目录YOLO 会自动从 images 对应目录下找同名 txt 标签。整理完后先跑一遍统计确认图片和标签数量对得上dataset_root/path/to/person_data echo --- 目录结构 --- find $dataset_root -maxdepth 2 -type d echo --- 图片数量 --- find $dataset_root/images -type f | wc -l echo --- 标签数量 --- find $dataset_root/labels -type f | wc -lfind -maxdepth 2 -type d打印两层目录结构重点看images/train和labels/train是否存在同一层级。wc -l统计文件数如果图片数量是 1000标签数量明显少于 1000说明有一部分图没有标注训练时这些图会被跳过严重时会让验证集缺样本。另外一个常见问题文件名里带空格或中文find输出正常但 YOLO 读图时可能失败。所以解压路径和文件名我建议一律改成英文和数字。3.2 一键训练脚本设备判断、模型选择与 resume 开关资源里那个一键训练脚本的价值不是省去敲命令而是把设备判断做掉了。Windows、Linux、macOS 下训练命令最大的区别是device参数NVIDIA GPU 用cudaMac 用mps没显卡只能用cpu。手动改来改去很烦一键脚本的本质就是自动化这一步。我拆这类脚本时习惯先看三处设备判断逻辑、模型选择、有没有开断点续训。下面是一个合格的一键训练脚本骨架# train_person.py import platform import torch from ultralytics import YOLO def auto_device(): # macOS 并且是 Apple Silicon 芯片走 mps 后端 if platform.system() Darwin and platform.machine().startswith(arm): return mps # Linux/Windows 下优先用 NVIDIA GPU if torch.cuda.is_available(): return 0 return cpu if __name__ __main__: device auto_device() print(device:, device) model YOLO(yolo11n.pt) model.train( dataperson.yaml, epochs100, imgsz640, batch16, devicedevice, projectruns/person, amp(device ! mps), )逻辑说明platform.system()判断操作系统类型platform.machine()判断 CPU 架构Apple Silicon 会返回arm64满足条件就返回mps。torch.cuda.is_available()是 PyTorch 层的 CUDA 可用性检查只有 PyTorch 编译了 CUDA 且驱动可用的机器才返回 True。model.train里的data指向 data.yamlproject指定训练结果输出目录amp自动混合精度在 mps 后端要关掉因为 M 系列芯片上 AMP 容易产生 NaN。参数上要注意batch16不是一个万能值显存只有 6G 时大概率 OOM我会先按这个值跑一个 epoch如果报错就改成 8 或 4。epochs100对 1000 张图不算多但机器是 CPU 的话建议降到 50配合早停也能收敛。yolo11n.pt是最小的 YOLO11 模型如果想要更好精度可以换成yolo11s.pt或yolo11m.pt显存占用也会相应上升。3.3 data.yaml 的写法路径、类别与损失函数的关系data.yaml是 YOLO11 读数据的配置入口写不对的话训练会直接报错。我给这个行人数据集配的最简写法如下# person.yaml path: /datasets/person_data train: images/train val: images/val nc: 1 names: 0: personpath建议写绝对路径且路径中不要带中文和空格。train和val是相对path的子目录YOLO 会先用path拼上train得到图片目录再自动把images换成labels去找标签目录。所以如果你把标签放在labels/train目录命名必须是images和labels成对出现不能出现annotations这种自定义名字。nc是类别总数这里必须是 1。names里的顺序和 txt 标签的类别编号一一对应0: person表示类别编号 0 对应 person。如果 txt 里出现了类别编号 1而nc: 1训练时这个编号会直接越界。前面那种检查脚本跑一遍就能提前发现。从损失函数角度看YOLO11 的分类损失会按类别编号分配正样本编号错位会让模型永远学不对类别映射最终表现就是 mAP 为 0。所以data.yaml和 txt 的对齐比训练参数本身更值得花时间确认。4. 三种训练场景GPU、CPU、Mac(M芯片) 的实操差异同一个训练脚本在不同设备上的差异不只是快慢还有各自的坑。这一章把三条路线分别说清楚你自己对号入座就行。4.1 GPUNVIDIA先确认 PyTorch 是 GPU 版再谈 batch 大小GPU 训练是这条路线上最省心的也是最常见的翻车点。很多人装完 ultralytics 后直接跑发现慢得离谱一看torch.cuda.is_available()是 False其实是 PyTorch 装成了 CPU 版。拿到任何机器第一步都先跑这段检查nvidia-smi python - PY import torch print(torch:, torch.__version__) print(cuda available:, torch.cuda.is_available()) print(gpu:, torch.cuda.get_device_name(0)) PYnvidia-smi看显卡驱动确认机器上有 NVIDIA GPU。Python 检查里torch.cuda.is_available()为 False 就直接说明 PyTorch 没带 CUDA 支持后面训练再怎么调参都白搭。常见做法是重装 PyTorch比如指定 CUDA 12.1 的版本pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121装完再跑一次检查cuda available变成 True 就正常了。GPU 训练时最重要的参数是 batch。显存 8G 以下建议batch816G 以上可以batch16训练中途报CUDA out of memory不要慌直接把 batch 减一半imgsz 从 640 降到 544 也能明显降低显存占用。我给这个行人数据集训练时GPU 场景推荐yolo11s.pt起步精度比 n 模型好训练速度依然很快。4.2 CPU慢但不是不能练关键是控制 epochs很多人一看到 CPU 训练就摇头但 1000 张图的数据量其实不大YOLO11n 在 CPU 上跑单 epoch 的时间是分钟级。问题是训练总时长会拖着走所以 CPU 场景要做三件事换小模型、降 epochs、开早停。model.train( dataperson.yaml, epochs50, batch8, imgsz640, devicecpu, workers0, patience20, )workers0在 Windows 上尤其重要因为多进程 dataloader 在 Windows 下经常触发重复 fork 的报错。patience20表示验证指标连续 20 个 epoch 没提升就提前停CPU 跑本来就慢早停能省下大量无效时间。第一个 epoch 跑完你拿单轮时长乘总 epochs就能估算整个训练要多久。如果接受不了就去租 GPU数据量再小也比 CPU 强几十倍。4.3 MacM芯片mps 能跑但别开 AMPApple Silicon 的 Mac 跑 YOLO11 是可行的靠的是 PyTorch 的 MPS 后端device 填mps或mps:0。但 MPS 相比 CUDA 不算成熟训练时经常遇到算子不支持处理方式是开一个环境变量让不支持的算子自动回退到 CPUexport PYTORCH_ENABLE_MPS_FALLBACK1 python train_person.py训练脚本里auto_device()检测到 arm64 的 Darwin 系统就会返回mps但 AMP 必须关掉前面已经写了ampFalse。原因很简单MPS 后端在 float16 混合精度下容易出现 NaN训练几轮后 loss 变成 nan整个模型直接废掉。Mac 上跑这个行人数据集我建议用yolo11n.ptimgsz 可以保持 640batch 设 8训练速度比 CPU 快不少但别指望和 NVIDIA GPU 比。如果你以后要做大模型训练Mac 这条路只适合临时验证。三种平台的实操参数对比如下平台device 参数推荐模型是否开 AMP关键注意NVIDIA GPU0yolo11s / m开先确认 torch.cuda.is_available()再调 batchCPUcpuyolo11n关workers0epochs 降到 50 左右Mac M 芯片mpsyolo11n关PYTORCH_ENABLE_MPS_FALLBACK15. 避坑与常见问题从标签错位到训练中断的五个坑这套资源我在复现时遇到过不少问题有些是数据集转换的通病有些是 YOLO11 在新设备上的坑。挑五个最典型的写出来每条都是现象加原因加解决你提前看过能省半天时间。5.1 类别编号从 0 还是从 1标签错位会让 mAP 直接归零现象训练过程 loss 在下降验证时 mAP50 一直是 0预测框标签全都不对。原因COCO 格式的 person 类别 id 是 1从 COCO 转 YOLO 时如果没有减 1txt 第一列会变成 1。而 data.yaml 里nc: 1YOLO 期望的类别编号只有 0编号 1 直接越界。另一种情况是 labelimg 标注时多个类别名没统一导致转换出来的类别编号混乱。解决训练前先跑一次标签检查脚本确认所有 txt 第一列最大值小于nc。我一般固定用awk {print $1} labels/train/*.txt | sort -u看一眼全部类别编号输出只有 0 才是正常的。如果发现 1重新做一次数据清洗把类别减 1 后另存。5.2 图片路径带中文YOLO 读图时直接中断现象训练前验证数据时提示image not found或FileNotFoundError但文件明明存在。原因Windows 下中文路径和含空格的目录名会让部分底层图像库读文件失败。YOLO 底层走的是 OpenCV 的imread它对非 ASCII 路径支持一直不稳定这是老问题。解决数据集解压后统一放到纯英文路径下比如D:/datasets/person_data图片和标签文件名也不要带中文。data.yaml 里的path用绝对路径避免用~或相对路径。Mac 和 Linux 对中文支持相对好但既然要跨平台跑不如一开始就改成英文路径省得换台机器就翻车。5.3 Mac 上 AMP 开启后 loss 变成 NaN现象Mac 上用 mps 训练前几个 epoch loss 正常某个 epoch 后直接变成 nan训练曲线断掉。原因MPS 后端对 float16 的支持不完整。YOLO11 默认开 AMP在 CUDA 上没问题在 MPS 上就是高危项某些算子在小数精度上直接溢出。解决训练时显式传ampFalse或者环境变量设PYTORCH_ENABLE_MPS_FALLBACK1。如果是用我前面那个脚本骨架amp(device ! mps)已经做了判断。Mac 上如果用 MPS 还遇到其他算子错误可以把imgsz改成 544有时候 640 下的某些上采样算子会触发更隐蔽的兼容问题。5.4 严重遮挡样本漏检模型小、imgsz 小都扛不住现象单独跑监控画面时正常行人能框住严重遮挡的行人经常漏检背景误检框变多。原因遮挡样本在数据集里的占比低而且遮挡严重时目标框非常小YOLO11n 在 640 分辨率下特征提取不够强。这不是标注格式问题是数据分布和模型容量的问题。解决先把模型换成 yolo11mmAP 会明显回升。还想再提就把imgsz调到 768代价是显存和推理耗时上升。如果重点场景是严重遮挡可以单独把这类样本复制两份利用 mosaic 增强让模型多看几遍。注意不要盲目加 epochs该收敛的早收敛了提升主要靠模型容量和输入分辨率。5.5 训练中断后从头再来resume 开关就是后悔药现象训练到 60 个 epoch 时机器重启重新跑一遍等了一天发现结果还不如第一次。原因很多人不知道 Ultralytics 支持断点续训。训练中断后runs/person/train/weights/last.pt里存着最近的权重直接从断点继续就行。解决model.train(resumeTrue)Ultralytics 会自动读取runs下最近一次训练目录里的last.pt。如果上次训练项目名不是默认的也可以指定resumeruns/person/train/weights/last.pt。从那以后我每次开始训练前都会确认project参数固定不然续训时读错目录等于白折腾。6. 验证训练结果从 val 指标到监控场景推理训练跑完不是结束验证模型能不能在真实监控画面里干活才是重点。6.1 先看 val 指标再看真实画面训练结束后runs/person/train/results.csv里有完整的 epoch 指标。行人检测场景下我最看重 recall 和 mAP50因为漏检比误检严重得多监控场景漏掉一个人可能就出事故。最终模型在weights/best.pt不只是 last。验证时写一段最短推理脚本from ultralytics import YOLO model YOLO(runs/person/train/weights/best.pt) results model.predict(test/street.jpg, conf0.25, imgsz640) for r in results: r.save(output.jpg)conf0.25是置信度阈值低于 0.25 的预测框会被过滤。如果是监控场景我一般会调到 0.2宁可多一点误检也不要漏人。imgsz640要和训练保持一致推理时如果改大分辨率精度可能变化最好先测一下。6.2 导出与轻量化部署如果模型要落地到边缘盒子或者嵌入到现有监控系统可以导出成 ONNX 格式在 CPU 上的推理速度会比 PyTorch 原版快不少model.export(formatonnx, imgsz640)导出会生成best.onnx可以直接用 ONNX Runtime 加载。如果目标设备是 NVIDIA GPU 且看重视延迟还可以继续转 TensorRT。但这个数据集只有 person 一个类别导出前确认names没写错否则部署端显示标签会对不上。我自己每次训练完都会拿一张遮挡最严重的测试图跑一遍确认那个最容易漏检的行人能被框住再决定要不要调整数据增强。希望这个流程能帮你少踩几个坑。本文还有配套的精品资源点击获取
返回列表