
简介针对yolo系列算法的行人目标检测数据集专为模型训练与验证设计适合目标检测学习者快速上手也适合开发者直接替换到yolov5/yolov7/yolov8/yolov9/yolov10/yolo11等项目中调优。资源包大小约233.76MB共2000个文件以XML标注文件为主并附带数据集配置文件data.yaml及VOC、YOLO两种标签格式说明能适配不同训练框架的输入要求。目前已有138人学习/下载数据集已完成训练集与验证集划分目录结构清晰省去手动标注与格式转换的流程。YOLO标签采用class、x_center、y_center、width、height的归一化坐标TXT文件可直接交给yolo训练脚本VOC格式的XML文件则可用labelImg等工具打开复核。整体设计兼顾训练效率与可读性能有效帮助读者在较短时间完成模型训练、验证与测试。1. 行人检测数据集落地7203张带标签图像从yolov5到yolo11一条路跑通训练YOLO行人检测很多人卡在第一步不是模型选型而是数据集。自己标注几百张图费时费力网上找的散图格式五花八门标签还得手动转。这份行人检测数据集一共7203张图像每张都带yolo格式txt和voc格式xml两份标签已经按train/val/test划分好配好了data.yaml直接丢给yolov5、yolov7、yolov8、yolov9、yolov10、yolo11任何一个版本都能开训。对刚入门目标检测的学生、做安防或行人计数的工程师、想快速验证yolo训练流程的人来说这是能省掉一到两周数据准备时间的现成资源。下面我从标签格式、配置路径、跨版本适配到踩坑记录把它拆开讲清楚。2. 数据集结构与两种标签格式yolo txt与voc xml并存的设计逻辑2.1 目录结构与文件清单拿到压缩包先看什么解压后第一件事不是急着训练而是先摸清目录结构。这份数据集的根目录下会有images和labels两个大目录labels里又区分了yolo格式和voc格式两个子目录。用tree命令扫一眼整体层次大致是这样├── images/ │ ├── train/ # 训练集图像 │ ├── val/ # 验证集图像 │ └── test/ # 测试集图像 ├── labels/ │ ├── yolo/ # txt标签按train/val/test分 │ └── voc/ # xml标签按train/val/test分 ├── data.yaml # 数据集配置文件 └── README.md # 数据说明这里有个关键设计图像只存一份但标签同时保留yolo和voc两份。为什么这么做因为训练时yolo系列算法直接读txt而voc格式的xml用于可视化检查、格式转换、或者喂给其他需要voc标注的框架。我一般会把xml当作“原始标注存档”txt当作“训练用产物”两者对照着看能快速发现标签丢没丢、坐标对不对。每个图像文件名对应同名的txt和xml比如img_0380_418.jpg对应img_0380_418.txt和img_0380_418.xml。如果某个图像只有图像没有标签训练时会被跳过但数量多了会明显影响mAP。拿到资源后建议先跑一遍脚本统计每个图像是否都有对应标签这个脚本我在第6章给出。2.2 yolo格式解析归一化坐标的可复现验证yolo格式的txt每一行代表一个目标框标准写法是class x_center y_center width height其中class是类别索引行人检测里通常就是0x_center和y_center是目标框中心点的x、y坐标width和height是框的宽高这四个值全部是相对于图像宽度和高度的比例范围在0到1之间。换句话说标签不存像素值存的是比例值这样无论训练时输入图像resize到416还是640标签都不用改。打开一个txt文件看实际内容cat labels/yolo/train/img_0380_418.txt输出类似0 0.521875 0.383333 0.093750 0.180000 0 0.389063 0.758889 0.106250 0.151111这两行表示图像里检测到两个行人。第一行类别是0中心点在图像宽度的52.19%位置、高度的38.33%位置框宽占图像宽度9.375%、高占图像高度18%。这种归一化表示的好处是即使图像原始分辨率是1920×1080你换成1280×720去训练标签依旧有效。缺点也有——比例值不好直观感知目标在图像中的实际位置所以排查标签错误时我习惯配合xml的绝对像素值做对照。2.3 voc格式解析xml里藏着什么信息voc格式的xml把标注信息完整记录在object节点里包括类别名、bounding box的绝对像素坐标以及difficult等附加标记。看一个典型结构annotation filenameimg_0380_418.jpg/filename size width640/width height480/height depth3/depth /size object nameperson/name bndbox xmin301/xmin ymin106/ymin xmax361/xmax ymax192/ymax /bndbox /object /annotation这里size记录了图像宽高bndbox给出目标框的左上角(xmin, ymin)和右下角(xmax, ymax)像素坐标。把xml转成yolo txt的公式是x_center (xmin xmax) / 2 / widthy_center (ymin ymax) / 2 / heightwidth (xmax - xmin) / widthheight (ymax - ymin) / height。我把上面这组数值代入算一下中心x是(301361)/2331除以640得0.5172和txt里第一个目标接近但不完全一致——说明txt和xml不是同一份标注自动转的可能是先后标注的版本差异。这个现象在真实数据集里很常见稍后避坑章节会展开说。3. data.yaml与训练配置从零把模型跑起来3.1 data.yaml的字段与路径写法data.yaml是yolo系列算法读取数据集信息的入口。这份数据集自带的yaml内容大致如下path: /path/to/your/dataset # 数据集根目录必改 train: images/train # 训练图像相对路径 val: images/val # 验证图像相对路径 test: images/test # 测试图像相对路径 nc: 1 # 类别数行人只有1类 names: [person] # 类别名称列表path字段是绝对路径拿到资源后第一件事就是把/path/to/your/dataset改成你自己机器上的实际路径。train、val、test三项是相对path的目录注意这里指向的是images下的子目录不需要指向labels目录。yolo训练时会根据图像路径自动找同名的txt标签查找逻辑是把images替换成labelsjpg替换成txt。所以标签目录的层级必须和图像目录保持镜像否则训练时报“found no labels”错。nc: 1是类别总数names: [person]是类别名列表索引从0开始。如果你后面想加入骑车人、婴儿车等其他类别需要同步修改nc和names且names里第n个名字对应类别索引n。3.2 在yolov8上跑一次完整训练拿到数据集先跑yolov8是阻力最小的路径。确保你已经装好ultralytics包pip install ultralytics然后用一条命令启动训练yolo train modelyolov8n.pt datadata.yaml epochs100 imgsz640 batch16 device0如果不习惯yolo命令行也可以在Python脚本里写from ultralytics import YOLO model YOLO(yolov8n.pt) results model.train( data/absolute/path/to/data.yaml, epochs100, imgsz640, batch16, device0, patience20, projectruns/train, nameperson_det )yolov8n.pt是yolov8的nano版本预训练权重用它对训练集合中的相同分布图像做迁移学习收敛速度比从零训练快很多。epochs100是训练轮数行人检测这类单类任务100轮足够imgsz640是把输入图像resize到640×640yolo系列默认推理尺寸就是640batch16看显卡显存定12GB显存跑nano模型没问题如果换yolov8l或yolov8xbatch要降到8或4。patience20是早停轮数连续20轮验证集指标不提升就自动停止省时间。3.3 训练参数怎么设imgsz、epochs、batch的推荐值参数设置没有万能答案但有几个经验值可以参考。imgsz建议在640到1280之间选行人属于小目标偏多的场景原图行人占比往往低于10%用640分辨率训练能平衡显存开销和检测精度如果部署设备是Jetson或者嵌入式训练时用640部署推理时还得对应到640不要训练用1280推理用416那会明显掉点。epochs受数据量和预训练权重双重影响7203张图像的单类数据集配合coco预训练权重训练到80到120轮基本收敛。观察results.csv里的val/box_loss曲线如果连续30轮在0.03上下波动不再下降就是收敛了。batch的设定以“显卡利用率跑到90%以上、不爆显存”为准。8GB显存的卡跑yolov8n和yolov8s可以上batch16跑yolov8m就要降到8。workers参数在Windows上注意设为0或2设大了容易报DataLoader worker进程崩溃。训练完成后runs/train/person_det/weights/best.pt就是验证集上表现最好的权重后面验证和推理都用这个文件。4. 跨版本适配yolov5/v7/v9/v10/yolo11的通用与差异4.1 不同版本对数据集格式的要求差异这份数据集在yolov5到yolo11之间跨版本通用背后的核心原因是所有版本都沿用同一套标签规范归一化的txt标签加上按目录划分的数据组织方式。但细节上有差异主要体现在三处data.yaml字段兼容性、预训练权重文件名、和训练命令的写法差异。yolov5用的是yolov5仓库自己的训练入口要求data.yaml里的字段名是train、val、test和这份数据集自带的yaml一致可以直接用。yolov8及之后的ultralytics版本兼容性更好train.py或yolo命令都能读同一份yaml。yolov6是美团开源的独立于ultralytics体系它的yaml规范略有不同需要把names写成class_names才能识别这个数据集没有针对v6优化建议优先跑v5/v8/v9/v10/yolo11。4.2 版本迁移时yaml文件的写法变化如果从yolov8切到yolov5yaml本身不动但train.py路径不同。yolov5的官方仓库训练命令是cd yolov5 python train.py --data /path/to/data.yaml --weights yolov5s.pt --img 640 --epochs 100 --batch-size 16yolov5会自动读取yaml里的path字段拼接出图像和标签的绝对路径。有一个不一致值得注意yolov5对val字段是必读的而test字段在yolov5的train.py里不会读取只有在跑val.py做纯推理验证时才用到。所以如果后续要评估测试集指标yolov5里要手动指定--data路径和--task val时的数据集划分。yolov9和yolo11都属于ultralytics体系命令基本一致只把model参数换成对应权重yolo train modelyolov9s.pt datadata.yaml epochs100 imgsz640 batch16 yolo train modelyolo11s.pt datadata.yaml epochs100 imgsz640 batch16yolov10的训练入口稍有不同它官方推荐用yolov10的独立训练脚本from ultralytics import YOLOv10 model YOLOv10(yolov10s.pt) model.train(datadata.yaml, epochs100, imgsz640, batch16)4.3 训练结果验证混淆矩阵与mAP怎么看训练完后怎么确认模型真的能用不能只看loss曲线。yolo系列训练完会在runs/train/person_det/下生成confusion_matrix.png和results.png重点看三处验证集mAP50的目标值单类行人检测任务7203张数据训练100轮后mAP50至少应该到0.85以上低于0.7说明训练有问题混淆矩阵里person这一行的数值代表真实行人被正确检出的比例正常应该在0.9以上val/box_loss曲线是否在训练末期继续下降如果还在降说明epochs不够如果已经走平说明模型学不到新东西了。如果用了这份数据集自带的划分images/test目录里还有一批训练时完全没见过的图像。用yolo predict或model.val指定data.yaml里的test路径可以看模型在完全陌生数据上的泛化表现。测试集mAP50通常比验证集低2到5个点这是正常现象。5. 避坑与排查行人数据集训练中的五个高频问题5.1 标签坐标越界与空标签文件现象训练日志提示WARNING ⚠️ labels with zero size或produced corrupted boxes但训练没有中断最终mAP异常低。原因部分txt文件里的width或height为0或者x_center、y_center超出0到1范围。可能是在标注后处理时坐标归一化除错了分母也可能是标注工具导出了空目标框。解决用脚本遍历所有txt凡是width或height小于0.001的行直接删除坐标不在0到1区间的行打印出来人工判断。写一个简单的Python命令import os for split in [train, val]: folder flabels/yolo/{split} for f in os.listdir(folder): path os.path.join(folder, f) lines open(path).readlines() clean [] for line in lines: parts line.split() if len(parts) ! 5: continue c, x, y, w, h map(float, parts) if 0 x 1 and 0 y 1 and w 0 and h 0: clean.append(line) if len(clean) ! len(lines): open(path, w).writelines(clean)这段代码遍历train和val两个划分把每行解析成5个数值用区间判断过滤掉非法坐标和零宽高的框改写回原文件。注意它会直接覆盖原文件执行前最好先备份labels目录。5.2 data.yaml路径写错导致数据集找不到现象训练命令一切正常但tqdm进度条显示图像数远低于7203日志里出现Dataset not found或found 0 images。原因data.yaml里的path用的是相对路径或写错了绝对路径。常见坑是Windows下路径分隔符用反斜杠yaml解析时被当成转义符导致路径拼接失败。解决把path写成纯正斜杠绝对路径开头带盘符也没关系。例如path: D:/datasets/person_det如果出现found 0 images先在Python里验证路径能读到图像from pathlib import Path root Path(D:/datasets/person_det) print(list((root / images/train).glob(*.jpg))[:5])这一步能直接区分是yaml解析问题还是目录镜像问题。5.3 类别索引不对齐现象训练能跑通但可视化预测结果时发现所有预测框的置信度不低框却全部偏到图像某个角落。原因txt标签里class写成了非0值或xml里的name转换时映射错了索引。行人检测只有1类正确索引应该是0如果标注转换脚本把person映射成了1yolo读到类别1会因为nc1报错或者在训练时直接把该框忽略。解决全量检查txt里的第一列是否只有0awk {print $1} labels/yolo/train/*.txt | sort | uniq输出只有0就是正常的。如果出现其他数字把非0行统一改成0。同时检查xml里所有name的取值grep -h name labels/voc/train/*.xml | sort | uniq -c正常应只有person且数量接近7203。5.4 图像尺寸与imgsz不匹配引发显存溢出现象epochs100 imgsz640训练到中途直接OOM进程被系统杀掉显卡是12GB显存也扛不住。原因数据集里部分图像分辨率超大比如4000×3000。ultralytics在预处理时会先把图像按最长边缩放到imgsz但如果原始标签里坐标是像素值且没有被正确归一化resize后目标框会大幅偏移同时超大原始图上的动态batch计算可能导致临时显存峰值翻倍。解决先确认所有标签是归一化的第2章已经覆盖再把imgsz降到640以下并缩小batchyolo train modelyolov8n.pt datadata.yaml epochs100 imgsz512 batch8同样数据量下从640降到512显存占用能下降约35%。如果必须用640把batch设为4并开启ampTrue混合精度训练。5.5 数据集划分不均衡导致验证指标虚高现象验证集mAP50高达0.95测试集却只有0.7两者差距过大。原因train/val/test三个划分不是按场景或时间段随机抽的可能把同一时间段拍的行人图像大量分进训练集验证集里恰好都是和训练集相似的样本。解决重新划分前先看图像文件名前缀如果发现img_era01到img_era03这类带时间特征的命名规律按前缀分组后再做群组划分。用scikit-learn的GroupShuffleSplit可以按文件名前缀分组切分。这份数据集的划分设计思路是“随机但按目录均衡”实测train/val/test的图像来源较分散泛化差距在正常范围内。6. 进阶一次脚本校验全部标签合法性避免训练中途翻车训练前的标签体检值得养成习惯尤其是接手他人标注的数据集时。我每次拿到新的数据集都会先跑一遍综合校验脚本把第5章提的五个问题一次性扫出来import os from collections import Counter root labels/yolo errors Counter() total_boxes 0 for split in [train, val, test]: folder os.path.join(root, split) for fname in os.listdir(folder): path os.path.join(folder, fname) lines open(path).readlines() if len(lines) 0: errors[empty_file] 1 continue for line in lines: parts line.split() if len(parts) ! 5: errors[bad_format] 1 continue cls, x, y, w, h map(float, parts) total_boxes 1 if cls ! 0: errors[bad_cls] 1 if not (0 x 1 and 0 y 1): errors[center_out_of_range] 1 if w 0 or h 0 or w 1 or h 1: errors[size_out_of_range] 1 print(errors) print(total boxes:, total_boxes)这段脚本把yolo标签逐行拆成五个字段按五类常见错误做累加统计空文件、字段数不够、类别索引错误、中心点越界、宽高异常。输出里每项都是0才说明标签质量可靠。我习惯把errors的每一项设成0当作训练前的上线标准其中empty_file如果超过10个就直接联系标注方确认而不是自己删掉硬训。标签体检通过后再跑一次预热训练验证数据链路完整性用5个epochs加上imgsz320能跑通才上完整训练。这套流程救过我很多次。以前有一次训练到第40轮才发现val集里混进了200多张没有缩略图的损坏jpg白烧了两块显卡一周多的电费。从那以后我每次换数据集都强制先走标签校验和预热训练两步再谈调参。标签干活参数才有意义。希望帮到你。本文还有配套的精品资源点击获取