ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLOv5行人检测数据集:目录结构、标签格式与训练避坑指南

YOLOv5行人检测数据集:目录结构、标签格式与训练避坑指南 简介面向行人目标检测任务的数据集资源采用YOLOV5标准目录格式可直接用于模型训练与验证。数据集仅含person一个类别划分训练集3000张图像及对应txt标注、测试集300张图像及对应txt标注并附带类别字典txt文件覆盖日常多种生活场景适合目标检测方向研究者、算法工程师及YOLO初学者使用。压缩包共2000个文件以txt标注文件为主另含1个Python可视化脚本可随机传入图片绘制边界框并保存结果便于快速预览标注效果压缩包整体约523MB目录结构清晰无需额外处理即可投入训练流程。目前已有356人学习下载。资源提供完整的YOLOV5格式标注、可视化脚本及科学的数据集划分免去自建数据集和格式转换的繁琐步骤为行人检测实验与项目落地提供开箱即用的数据基础。1. 拿到就能训的行人检测数据集YOLOv5 目录格式到底省了什么事做目标检测的人都知道找数据集最烦的不是下载而是格式转换。很多公开数据集是 COCO 的 JSON 或 VOC 的 XML拿回来先要写脚本转 YOLO 的 txt再拆训练集和验证集一折腾就是半天。这份行人目标检测数据集把这一步省了526MB单类 person训练集 3000 张图配 3000 个标签 txt验证集 300 张图配 300 个标签目录按 YOLOv5 的 images/labels 约定排好附带类别字典 classes.txt 和可视化脚本 show.py。适合刚接触 YOLOv5 想跑通完整训练流程的新手也适合想快速验证行人检测效果、不想在数据清洗上花时间的老手。数据只有 person 一类标签体系简单训练时不会遇到类别不平衡问题拿来做迁移学习的基础数据也很顺手。下文从目录结构讲到训练接入中间给可视化校验和五个实战翻车点看完你就知道这份资源怎么用、坑在哪。2. 目录结构与标注格式看懂 labels 里 txt 的五个数字2.1 目录骨架images 与 labels 的对应规则下载解压后的目录排布是这个样子datasets/ ├── images/ │ ├── train/ # 3000 张 jpg │ │ ├── 000000004259.jpg │ │ ├── 000000005587.jpg │ │ └── ... │ └── val/ # 300 张 jpg ├── labels/ │ ├── train/ # 3000 个 txt │ │ ├── 000000004259.txt │ │ └── ... │ └── val/ # 300 个 txt ├── classes.txt # 类别字典内容只有 person └── show.py # 可视化脚本YOLOv5 的数据加载逻辑是images 下按 train/val 分目录labels 保持同样的子目录结构txt 与 jpg 同名。训练时 DataLoader 会自动把图片路径里的 /images/ 替换成 /labels/再把后缀 .jpg 换成 .txt所以两者必须严格同名同构。名字对不上那张图就会被当成「无标签」直接跳过训练。项目正文里列出的一串 txt 文件名000000014056.txt、000000005587.txt 这些就是 labels/train 和 labels/val 下的标注文件编号沿用了 COCO 图片命名习惯但内容已经是 YOLO 格式不需要额外转换。2.2 标签 txt 的格式五个数字与归一化坐标打开任意一个 txt每一行对应一个目标框。这份数据集只有 person 一类所以每行是五个数字0 0.482903 0.530902 0.184211 0.471667五个字段的含义如下表字段含义取值范围第 1 个类别 idperson 固定为 00第 2 个框中心点 x 坐标归一化0 ~ 1第 3 个框中心点 y 坐标归一化0 ~ 1第 4 个框宽度归一化0 ~ 1第 5 个框高度归一化0 ~ 1比如上面这行框中心在图片横向 48.3%、纵向 53.1% 的位置宽度占整张图 18.4%高度占 47.2%。归一化坐标是用像素值除以图片宽高得到的所以不关心原图是 640×480 还是 1920×1080训练时输入分辨率随便换标注天然适配。想人眼核对标注我习惯先换算回像素坐标再打印import cv2 img cv2.imread(datasets/images/train/000000014056.jpg) h, w img.shape[:2] with open(datasets/labels/train/000000014056.txt) as f: lines f.readlines() for line in lines: cls_id, cx, cy, bw, bh map(float, line.strip().split()) x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) print(fclass{int(cls_id)}, box({x1}, {y1}) - ({x2}, {y2}))这里 map(float, ...) 把五个字段全转成浮点数再用中心点加减宽高的一半得到左上角和右下角像素坐标。注意 class 打印时需要 int() 转回整数否则 YOLOv5 训练时类别判定会出偏差。2.3 单类别的取舍与 classes.txt 的用途classes.txt 里只有一行 person对应 YOLOv5 的 nc1。单类别的好处是标签体系干净不会出现某个类样本太少导致的训练失衡代价是只能做「人 vs 背景」的检测后续要识别狗、车就得在别的基础模型上微调。classes.txt 在训练时不是必需文件但它是给人看的类别字典转 COCO 或 VOC 格式、做类别统计时用处很大。我一般先读一遍确认类别 id 顺序with open(classes.txt) as f: names [line.strip() for line in f.readlines()] print(names) # [person]列表索引就是标注文件里的 id后续如果扩类names 顺序必须和标注第一列严格对应顺序错了检测结果就会张冠李戴这一点在避坑章节会再展开。3. 可视化与质量校验show.py 之外的自检脚本3.1 先读 show.py随机选图与画框逻辑下载包里附带的 show.py 作用很直接从训练集随机挑一张图读取同名 txt把每个框画出来保存到当前目录脚本不用改任何参数就能跑。它的核心逻辑和下面这段等价import cv2 import glob import random import os img_dir datasets/images/train label_dir datasets/labels/train img_list glob.glob(os.path.join(img_dir, *.jpg)) img_path random.choice(img_list) basename os.path.splitext(os.path.basename(img_path))[0] label_path os.path.join(label_dir, basename .txt) img cv2.imread(img_path) h, w img.shape[:2] with open(label_path) as f: for line in f: cls_id, cx, cy, bw, bh map(float, line.strip().split()) x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, fperson {int(cls_id)}, (x1, max(0, y1 - 8)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) out_path visual_check.jpg cv2.imwrite(out_path, img) print(f{img_path} - {out_path})关键点有三个用 os.path.splitext 摘出图片名再拼标签路径保证同名对应画框坐标必须乘回图片宽高因为标注是归一化的putText 的 y 坐标用 max(0, y1 - 8)防止框贴近上边缘时文字画到画面外。如果想抽 val 的图把前两个目录变量改成 val 路径就行。我一般连着跑五六次多抽几张看两个东西框是否贴合行人轮廓有没有明显漏检。数据集的标注质量只有肉眼抽查过才敢放心交给训练脚本。3.2 批量自检扫描越界、空文件与坏格式可视化只能抽查想全量确认 3000 个标签没有坏数据得写扫描脚本。常见问题三类txt 是空文件、行内字段数不是 5、归一化坐标越界。一段脚本一次扫完import glob label_dir datasets/labels/train issues {empty: [], bad_fields: [], out_of_range: []} for txt_path in glob.glob(label_dir /*.txt): with open(txt_path) as f: lines f.readlines() if not lines or all(not l.strip() for l in lines): issues[empty].append(txt_path) continue for line in lines: parts line.strip().split() if len(parts) ! 5: issues[bad_fields].append(txt_path) break try: cls_id, cx, cy, bw, bh map(float, parts) except ValueError: issues[bad_fields].append(txt_path) break if not (0 cx 1 and 0 cy 1 and 0 bw 1 and 0 bh 1): issues[out_of_range].append(txt_path) break for k, v in issues.items(): print(f{k}: {len(v)} files) for p in v[:10]: print( , p)脚本对每个文件逐行检查发现第一个问题就 break 跳出当前文件避免重复记账。empty 和 bad_fields 会导致训练时图片被跳过或解析报错out_of_range 是最阴的训练不会报错但 loss 会出现异常波动排查费时间。跑一遍把问题文件挑出来决定删掉还是补标比事后查损失曲线省事得多。4. 接入 YOLOv5 训练写 data.yaml 与一条命令起步4.1 写 data.yaml把目录结构翻译成训练入口YOLOv5 的 train.py 不直接认识你的数据只认一个 data.yaml。这份目录已经按约定排好yaml 里只需要三件事训练图片路径、验证图片路径、类别数量与名称。我的写法train: /mnt/data/person_datasets/images/train val: /mnt/data/person_datasets/images/val nc: 1 names: [person]train 和 val 指向 images 下的子目录即可YOLOv5 会自动把 images 替换成 labels 去找对应 txt不用在 yaml 里写标签路径。路径建议写绝对路径相对路径在切换工作目录或跨机器拷贝时容易失效如果放 Docker 里训练务必确认路径是容器内可见的挂载路径。如果你用的是 YOLOv8 或 YOLOv11 的训练入口这套目录格式同样兼容只是命令换成 yolo train dataperson.yamllabels 的定位逻辑和 YOLOv5 完全一致。4.2 训练命令与超参3000 张单类数据怎么起步3000 张单类图属于小数据集从头训练效果一般。常见做法是加载 COCO 预训练权重做迁移学习person 类在 COCO 里是主力类别微调几轮就能收敛cd yolov5 python train.py \ --data /mnt/data/person_datasets/person.yaml \ --weights yolov5s.pt \ --img 640 \ --batch-size 16 \ --epochs 100 \ --workers 8 \ --project runs/person参数逐个说--img 640 是训练输入尺寸行人属于中大型目标640 足够不必上 1280显存和时间成本都会翻倍--batch-size 16 在单卡 12GB 显存左右比较稳显存小就降到 8--weights 用官方 yolov5s.pt会自动下载--project 指定输出目录权重和曲线都落在 runs/person 下。如果只有 CPU把 batch-size 降到 4、epochs 降到 10 先跑通流程验证阶段会慢但能跑完。4.3 自定义拆分与目录重排脚本如果不想用现成的 3000/300 划分想按 8:2 重切一套目录就得自己重排图片和标签必须同步移动。下面这段把训练集按 2400/600 重拆import os import shutil import random random.seed(42) src_img datasets/images/train src_lab datasets/labels/train dst_root datasets_rebuilt img_files [f for f in os.listdir(src_img) if f.endswith(.jpg)] random.shuffle(img_files) val_files set(img_files[:600]) train_files set(img_files[600:]) for split, files in [(train, train_files), (val, val_files)]: os.makedirs(f{dst_root}/images/{split}, exist_okTrue) os.makedirs(f{dst_root}/labels/{split}, exist_okTrue) for name in files: shutil.copy(os.path.join(src_img, name), f{dst_root}/images/{split}/{name}) txt os.path.splitext(name)[0] .txt shutil.copy(os.path.join(src_lab, txt), f{dst_root}/labels/{split}/{txt})random.seed(42) 固定随机种子保证不同机器切出来的划分一致别人复现实验时不会因划分不同产生偏差。val_files 用 set 存文件名查找是 O(1)比列表快得多。切完记得把 yaml 的 train/val 路径指向 datasets_rebuilt否则用的还是旧划分。5. 避坑指南训练前的五个高频翻车点5.1 类别 id 与 data.yaml 的 names 顺序错位现象训练正常启动loss 也在降但用训练好的权重检测时person 类不显示或者框框乱飞。原因标注 txt 第一列是数字 idYOLOv5 拿它和 names 列表的索引对应。如果 names 写成 [human] 而 classes.txt 定义的是 person或者你把别的任务里的 names 文件直接套用id 0 就指到了别的类上。解决单类数据集严格保持 nc1、names[person]。如果要扩类必须回头把所有 txt 第一列改成新 idclasses.txt 同步更新三者txt 第一列、classes.txt、data.yaml 的 names永远保持一致。5.2 OpenCV 读图失败中文路径与特殊字符现象show.py 或自检脚本报 cv2.errorimg 为 None画不出框。原因cv2.imread 对中文路径和特殊字符支持不好Windows 下最常见。解压到「C:\用户\下载\行人数据集」这类路径脚本必然读不到图。解决把数据集挪到纯英文路径下比如 D:\datasets\person_yolo。这是 OpenCV 生态的老坑换用 PIL 的 Image.open 在部分版本上也会踩同样的雷不是脚本本身的问题。5.3 归一化坐标越界引发训练警告现象训练日志里出现大量坐标裁剪警告或者 loss 曲线骤升后不再下降。原因第 3 章扫描脚本能查出的越界标签坐标不在 0-1 区间会在预处理时触发 anchor 裁剪产生无效回归样本。解决先跑 3.2 的批量扫描把越界文件单独挑出来排查。偶尔一两张可以直接删掉对应图片和标签YOLOv5 对没有标签的图会跳过数量多的话就得人工复核原始标注可能是某批图片尺寸不一致导致的系统性偏差。5.4 val 集只有 300 张评估指标波动大现象验证集 mAP 每次训练都差 0.02~0.05换个随机种子差更多。原因300 张的验证集样本量太小评估时随机采样顺序的变化都会造成统计波动不是模型没训好。解决训练前固定验证集为同一批图用 random.seed 固定取样序列或者按 4.3 重排成 2400/600之后所有实验都在同一划分上对比。数据量允许的话我一般把 val 提到 600 张以上指标才稳。5.5 show.py 输出文件被覆盖现象多次运行 show.pyvisual_check.jpg 永远只有最后一张前面抽到的样本全丢了。原因脚本固定输出一个文件名第二次运行直接覆盖。解决把输出路径改成带原图名的形式比如 fcheck_{basename}.jpg。改两行代码的事但能保留多次抽样的结果回看检查记录时不丢现场。6. 快速验证与进阶十个 epoch 的 smoke test 值得养成习惯拿到新数据集的第一天我不建议直接跑 100 个 epoch。正确顺序是先跑一个 10 epoch 的 smoke test确认数据加载、loss 计算、验证评估全链路没问题再开正式训练。命令和正式训练只差 epochspython train.py --data person.yaml --weights yolov5s.pt --img 640 --batch-size 16 --epochs 1010 个 epoch 在单张消费级显卡上通常十几分钟到半小时跑完足以暴露九成以上的数据问题。跑完看 runs/person/exp 下的 results.png如果 val loss 在下行、train loss 也在降数据管道基本健康如果第一个 epoch 就出 NaN优先回头查标签解析而不是调学习率。smoke test 通过后再用 detect.py 推理几张 val 图做双确认python detect.py --weights runs/person/exp/weights/best.pt --source datasets/images/val --conf 0.25这一步验证的是「数据 权重 预处理」整条链路。只训了 10 个 epoch 的权重会比较粗糙框有偏差是正常的重点看「能框出人」而不是「框得准」。损失曲线侧单类任务的痛点不是分类而是回归当 box_loss 在验证集上不再下降而 obj_loss 还在波动时说明数据接近当前模型容量上限加数据比加大模型更划算。这套「固定划分 → 全量扫描标签 → smoke test → detect 抽查」的流程我每次接新数据集都会完整走一遍。有一次图省事跳过了标签扫描结果训练到 60 个 epoch 发现有个 txt 里混进了一行没有类别的脏数据loss 曲线异常上升重训浪费了四个多小时。从那以后数据校验的顺序再也没变过先扫标签、再跑 smoke test、最后才开正式训练。希望帮到你。本文还有配套的精品资源点击获取
返回列表