尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

行人检测数据集转换与YOLO11一键训练:VOC/COCO/YOLO格式实战指南

发布时间:2026/9/29 20:34:14

资讯中心
01
ARTICLE

行人检测数据集转换与YOLO11一键训练:VOC/COCO/YOLO格式实战指南

行人检测数据集转换与YOLO11一键训练:VOC/COCO/YOLO格式实战指南
简介这是一份面向行人目标检测任务的数据集配套资料共包含1000张真实场景高质量行人图片覆盖校园行人、街景行人、道路行人、遮挡行人及严重遮挡行人等丰富场景适合公共场所监控场景下的行人检测项目以及作为监控场景通用行人检测数据集的补充。标签基于labelimg工具精细标注同时提供VOCxml、COCOjson、YOLOtxt三种常见目标检测数据集格式可直接用于YOLO等算法训练省去格式转换的额外工作。资源本身为PDF文档共1个文件大小约4.17MB文档内完整介绍数据集基本情况、标注示例与百度网盘获取方式。随资料另附YOLO11一键训练脚本支持GPUGPUs、CPU和MacM芯片三平台运行并配有博主训练日志供参考方便使用者快速搭建训练环境、对比不同平台效果。目前已有1043人浏览学习适合需要快速获取行人数据并开展模型训练的研究者与工程师尤其适用于算法验证和监控类项目落地。1. 这是能直接跑起来的行人检测最小闭环不是又一个“标注好就完事”的仓库一个1000张图的“行人目标检测数据集”配上VOC/COCO/YOLO三种格式标签再加一个能在GPU、CPU、Mac三台不同设备上直接启动的YOLO11一键训练脚本——它要解决的正是目标检测入门最常见的两个问题三套标注格式互相转不明白以及官方Demo在自己电脑上一步一报错。这个组合适合动手验证行人检测方案、做课程项目、或手里只有Mac/核显也要跑通YOLO训练的开发者。注意1000张图不等于生产级规模它的价值在于让你用半天时间把“数据-标签-训练-评估”整条链路跑通后面换数据集也只是换路径。2. 三种标注格式转换VOC/COCO/YOLO 各自的坐标与 ID 陷阱2.1 数据集不是自己画1000个框公开来源筛选和统一底稿在真正开始转格式之前先决定“原始格式”。实践中最好把VOC XML当唯一底稿因为VOC是树状结构人眼可读也最容易做校验。我从CityPersons、BDD100K、Open Images V7这类公开源里筛行人图标准是行人占画面主体的比例不低于30%并且场景尽量贴近实际街道/园区。筛选后统一重命名成ped_000001.jpg到ped_001000.jpg每张图必须确保有至少一个行人标注否则训练时会当作背景负样本。1000张图按8:1:1切分约800训练、100验证、100测试。切分时不能随机乱切要按时间段或视频片段切否则同一人的连续帧同时出现在训练和验证里mAP会虚高。VOC XML作为底稿需要先写一个校验脚本检查xminxmax、yminymax框不超出图像边界类别名在允许列表里。这些边界问题在公开数据里非常常见不修的话后面转出的YOLO标签全是垃圾。下面这个函数把“读XML”和“校验”放在一起比一张张看省力得多import xml.etree.ElementTree as ET import os def validate_voc(xml_path, img_dir): 解析VOC XML并做边界校验返回统一字典。 tree ET.parse(xml_path) root tree.getroot() name root.find(filename).text w int(root.find(size/width).text) h int(root.find(size/height).text) img_path os.path.join(img_dir, name) if not os.path.exists(img_path): return None boxes, valid [], True for obj in root.findall(object): cls obj.find(name).text.strip().lower() if cls not in (person, pedestrian): continue box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) if xmin 0 or ymin 0 or xmax w or ymax h or xmin xmax or ymin ymax: print(f非法框: {xml_path} - {xmin},{ymin},{xmax},{ymax}) valid False continue boxes.append((xmin, ymin, xmax, ymax)) if not valid: # 越界框clip到图像边界宽高为负的框直接丢弃 pass return {filename: name, width: w, height: h, boxes: boxes}这段代码里有一个关键习惯root.find(size/width)直接用XPath取值避免多写两行临时变量。很多人习惯用在线转换工具但行人数一多在线工具不报告具体哪张图哪一行有错转完之后训练直接崩。自写脚本的好处是每个非法框都能打印到日志你能知道是数据源的问题还是转换逻辑写错了。我的处理策略是越界框clip到0和宽高宽高为负直接丢弃不硬留。三种标签文件的最终形态差异可以用一张表说清楚格式文件组织坐标值类别ID从几开始主要用途VOC每张图一个XML像素绝对值(xmin,ymin,xmax,ymax)字符串类别名原始标注、可视化COCO整个数据集一个JSON像素绝对值(x,y,w,h)1Detectron2、MMDetection、实例分割YOLO每张图一个TXT归一化(x_center,y_center,w,h)0Ultralytics YOLO系列这张表建议贴在你工作目录的墙上。你后面报错“class index out of range”基本就是ID起始值的问题。2.2 先建统一字典中间层再向COCO与YOLO两边生成不要写两个独立脚本分别处理VOC到COCO、VOC到YOLO那是重复劳动。先解析VOC得到统一字典然后一个函数生成COCO JSON一个函数生成YOLO txt。这样新增第三种格式时只写一个方向转换不用改解析逻辑。COCO的annotations数组里每个框是[x, y, width, height]x/y是左上角宽度高度为绝对像素。YOLO的txt每行是class x_center y_center width height全部除以图片宽高变成0~1之间的小数。最容易翻车的是把COCO的x/y当作YOLO中心点或者忘了把x_center减去宽度一半。下面是核心转换代码import json def to_coco_and_yolo(anns, image_id1): coco_imgs, coco_anns, yolo_lines [], [], [] for i, ann in enumerate(anns): x, y, xm, ym ann[bbox] w, h xm - x, ym - y # COCO绝对像素x,y为左上角category_id从1开始 coco_imgs.append({id: i, file_name: ann[filename], width: ann[width], height: ann[height]}) coco_anns.append({id: i, image_id: i, category_id: 1, bbox: [x, y, w, h], area: w * h, iscrowd: 0}) # YOLO归一化中心点 归一化宽高class id从0开始 cx (x w / 2) / ann[width] cy (y h / 2) / ann[height] nw, nh w / ann[width], h / ann[height] yolo_lines.append(f0 {cx:.6f} {cy:.6f} {nw:.6f} {nh:.6f}\n) coco {images: coco_imgs, annotations: coco_anns, categories: [{id: 1, name: person}]} return coco, yolo_lines这个函数有两个必须记住的约定COCO的category得从1开始YOLO的class从0开始。如果VOC里只有person一个类别那COCO categories是[{id: 1, name: person}]YOLO每行开头就是0。如果之后加类别“rider”就要重新分配ID不能沿用VOC里的字符串顺序这也是多类别项目里改标签最容易乱的地方。还有一点COCO JSON是整个数据集只有一个文件所有图片的标注都在里面YOLO则是每张图一个txt文件名和图片名对齐。千万不要把COCO JSON拆成1000个小JSON再硬说“COCO格式”YOLO的val/目录下也必须单独有对应txt否则验证阶段读不到标签。2.3 目录结构决定脚本能少写二十行训练脚本里最讨厌的就是到处找路径。我一般把数据固定成下面这种结构后续所有脚本只用三个变量IMAGES_DIR、VOC_DIR、YOLO_DIR。datasets/pedestrian/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── voc_xml/ │ ├── train/ │ ├── val/ │ └── test/ ├── yolo_labels/ │ ├── train/ │ ├── val/ │ └── test/ └── coco_annotations.json这里有一个细节VOC的XML目录和YOLO的txt目录都按train/val/test分开但COCO JSON是整个数据集一个文件内部靠image_id区分划分。你如果自己写数据划分要在生成COCO JSON时额外加一个split字段或者直接按文件名前缀判断。Ultralytics训练时只需要YAML里的images和yolo_labels路径COCO JSON更多是给其他框架用的。3. 用YOLO11一键训练脚本跑通GPU/CPU/Mac核心是设备选择与路径处理3.1 三平台差异不是“Python脚本能跑”而是底层算子能在对应设备上跑很多人把“一键训练”理解为把训练命令封装成一个bat脚本但在GPU、CPU、Mac三平台同时跑通难点在设备判定和依赖差异。GPU机器上要用cuda:0CPU机器上只能硬怼cpuMac上如果是Apple Silicon可以用mps但Intel Mac大概率只能退到CPU。Ultralytics其实已经封装了这些设备但它的自动选择不一定准在部分Mac上它会尝试用mps可某些上采样算子在MPS后端还没实现训练到一半直接抛异常。所以脚本里必须自己写一个设备选择函数并且允许用户用--device手动覆盖。另外NVIDIA GPU的识别依赖PyTorch是否装了CUDA版本。经常遇到的情况是torch.cuda.is_available()返回False但电脑明明有RTX 4060 Laptop GPU。原因大概率是装PyTorch时装成了CPU版或者显卡驱动版本太老。这个不是代码能解决的要在环境安装阶段就检查。3.2 一键训练脚本自动生成data.yaml并调度设备以下是常见做法里最精简的一键训练脚本。它做三件事生成data.yaml、选择设备、调用YOLO11训练。import argparse import sys import platform from pathlib import Path from ultralytics import YOLO def pick_device(): 按平台返回默认设备用户可用参数覆盖。 if sys.platform darwin: # Apple Silicon用mpsIntel Mac用cpu更稳 return mps if platform.processor() arm else cpu try: import torch if torch.cuda.is_available(): return cuda:0 except Exception: pass return cpu def make_data_yaml(root: Path) - Path: yaml_path root / data.yaml yaml_path.write_text(f path: {root.resolve()} train: images/train val: images/val names: 0: person ) return yaml_path def main(): parser argparse.ArgumentParser(add_helpTrue) parser.add_argument(--data, typePath, defaultdatasets/pedestrian) parser.add_argument(--weights, typestr, defaultyolo11n.pt) parser.add_argument(--epochs, typeint, default80) parser.add_argument(--batch, typeint, default8) parser.add_argument(--imgsz, typeint, default640) parser.add_argument(--device, typestr, default) args parser.parse_args() yaml_file make_data_yaml(args.data) device args.device if args.device else pick_device() print(f使用设备: {device}) model YOLO(args.weights) # 本地没有权重时Ultralytics会自动下载 model.train(datastr(yaml_file), epochsargs.epochs, batchargs.batch, imgszargs.imgsz, devicedevice, projectruns/pedestrian, nametrain, exist_okTrue) if __name__ __main__: main()这里有三个参数值得单独说。--batch决定单次前向传播的图片数量显存不够时从8降到4是首选--imgsz是输入分辨率行人检测建议640不要为了速度降太多小行人会漏检--weights指定预训练权重没有传时默认使用yolo11n.pt。device参数留空时脚本自动判断但遇到MPS不支持的算子你仍然可以手动改成--device cpu这是最直接的后悔药。跑通最小命令只需要一行python train.py --data datasets/pedestrian --weights yolo11n.pt --epochs 80 --batch 8 --imgsz 640训练启动后日志里会打印类似GPU: 0, memory: 6.2/12GB的信息。如果你看到的是CPU说明设备选择没走GPU或者PyTorch没检测到CUDA。训练结束后的产物在runs/pedestrian/train/weights/下best.pt和last.pt分别代表验证集最优和最后一轮的权重。用best.pt做后续推理不要用last.pt。3.3 为什么我建议你先别追“yolov26”这类新变体热词里经常有“yolov26目标检测项目源码”“YOLOv8数据集处理”但真正到落地阶段Ultralytics对YOLO11的支持最稳定API和YOLOv8几乎一致。追新变体的问题在于预训练权重、损失函数实现、导出ONNX的算子支持都可能有变动1000张图的数据集不值得为这些不确定性买单。先把YOLO11的官方接口吃透后面换新模型只是改一行YOLO(yolo11s.pt)的事。4. 训练参数怎么调到“能看”预训练权重、损失函数与混淆矩阵4.1 预训练权重不是越大越好1000张图选n还是s很多人拿到带GPU的机器就直接上yolo11x.pt结果一个epoch跑几分钟损失还乱跳。1000张图的行人数据集最佳起点是yolo11n.pt它是nano版本显存占用小训练速度快。先用它把数据链路跑通再看验证集mAP50能不能到0.8以上。如果n版本已经接近0.8换yolo11s.pt可以让mAP再涨两三个点但训练时间翻倍。至于medium和large在千图规模下几乎必然过拟合。预训练模型下载的问题也要说一句Ultralytics会在第一次运行时自动拉取yolo11n.pt但这个下载依赖网络环境。网络不稳定时你会看到卡在Downloading步骤。更稳妥的做法是提前把权重放到当前目录让YOLO(yolo11n.pt)直接读取本地文件。手动下载时只看官方来源第三方站点传的可能被改动过训练时表现异常且无法排查。4.2 训练日志里的三个损失box_loss、cls_loss、dfl_loss怎么读YOLO11的训练日志里每轮会打印一行类似这样的数据Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 1/80 6.2G 1.245 1.733 1.112 79 640 50/80 5.9G 0.801 0.422 0.688 88 640box_loss是边界框回归损失越小代表预测框的位置越准cls_loss是分类损失行人检测只有一类它更多在区分“行人”和“背景”dfl_loss是Distribution Focal Loss负责边界框边长分布的精细调整。这三个loss在训练集上持续下降是正常的但要注意验证集上的对应指标。如果训练集的box_loss一路降到0.3验证却没有同步下降说明开始过拟合。对于1000张图我一般只设置80个epoch。前30个epoch损失下降明显后面20个epoch缓慢收敛。如果到第80个epoch验证集的mAP50还在涨可以延长到120但不要超过150。更长的训练只会让模型记住1000张图里的噪声而不是泛化规律。4.3 混淆矩阵右上角出现“漏检”先调conf还是先补数据训练完成后运行验证命令yolo detect val modelruns/pedestrian/train/weights/best.pt datadatasets/pedestrian/data.yamlUltralytics会输出precision、recall、mAP50、mAP50-95同时保存confusion_matrix.png。混淆矩阵的横轴是预测类别纵轴是真实类别。行人检测的只有person一类所以你主要看两个格子对角线的person-person是正确检测数最右上角紧挨着background的格子代表“真实是行人但没检测到”。如果这个格子的数字超过0.2说明有20%的行人被漏掉这时候不用急着调conf阈值——先检查是不是验证集里的行人有大量遮挡或小目标。1000张图里如果很多行人只有几十像素模型学不到完整特征唯一有效的方法是补充更多近距离或中距离的行人图。另外一个被忽略的问题是“混淆矩阵总合不唯一”。验证集里一张图可能同时有多个行人矩阵里的数字是归一化后的比例不是原始计数。看到百分比不要惊讶重点看对角线相对大小。5. 避坑从GPU显存到Mac的MPS我踩过的5个坑5.1 GPU训练爆显存batch size和imgsz不是越大越好现象训练启动后没几秒脚本报CUDA out of memory或者Ubuntu上直接OOM kill。原因RTX系列显卡虽然有12GB或24GB显存但YOLO11在640分辨率下默认会缓存图片batch16时显存占用轻松超过10GB。笔记本GPU和独显共享内存时更容易触发。解决把batch降到4imgsz从640降到480二者选一个调整即可。Ultralytics也支持batch-1自动根据显存计算batch size但我更推荐手动固定一个值方便复现。如果显存只有6GB建议batch4, imgsz640。5.2 Mac训练报错“MPS backend not supported”或卡死现象在Apple Silicon Mac上跑训练前几个epoch正常中途抛出MPS backend out of memory或某算子不支持Intel Mac则可能直接卡在第一个epoch。原因MPS对部分YOLO算子实现不全尤其是一些自定义的注意力模块。torch.cuda.is_available()在Mac上返回False脚本自动选mps但模型里的某些计算不支持MPS。解决在pick_device里增加判断如果训练中出现MPS异常可以设置环境变量PYTORCH_ENABLE_MPS_FALLBACK1强制不支持的算子回退到CPU。更省事的方案是直接--device cpu1000张图用CPU跑80个epoch大约需要4到6个小时虽然慢但不会半路崩。5.3 标签坐标跑到图片外loss打印出nan现象训练loss出现nan或验证时所有检测框都堆在图片边缘。原因VOC标注里某些框的xmax超过图片width转换时没有clipYOLO的归一化中心点大于1模型学到一个超出边界的框梯度爆炸。解决在做VOC校验时就把所有框clip到图像范围内xmin/ymin小于0设为0xmax/ymax大于width/height设为width/height。转换后还要加一层断言检查YOLO的txt里每行四个数都在0到1之间。下面这段代码可以加在转换脚本末尾for line in yolo_lines: parts line.strip().split() if len(parts) ! 5: print(YOLO行格式错误:, line) continue vals [float(v) for v in parts[1:]] if not all(0 v 1 for v in vals): print(标签越界:, line)5.4 VOC格式里图片尺寸读错导致检测框整体偏移现象训练时loss正常但推理出来的框明显偏右上或偏下不是乱跑但整体不对。原因有的VOC XML里size节点和图片真实像素不一致。比如标注工具写的是960x540但图片经过压缩后是640x360。YOLO的归一化标签是以XML里的size为分母算的图片实际尺寸和它不一致框自然整体偏移。解决转换时不要直接信任XML里的size用PIL读一下真实图片尺寸from PIL import Image img Image.open(img_path) real_w, real_h img.size # 如果与XML差异超过5%以真实尺寸为准并重新计算归一化坐标实际我遇到过一次标注工具把宽高反过来生成的YOLO标签里宽高比完全颠倒训练出来的框全是竖着的矩形贴在地上。加上这个检查能快速暴露问题。5.5 1000张图训练结果过拟合这时候别再加epochs现象验证集mAP50在某个epoch达到0.85后不再上涨训练集loss还在下降混淆矩阵里person-background那个格子开始变大。原因模型开始记住训练集里的特定行人姿态和背景纹理验证集上反而更不稳定。1000张图只有单一场景时过拟合来得比想象中快。解决停止加epochs回调最佳验证结果。优先做数据增强Ultralytics默认有mosaic、翻转、色彩抖动可以打开hsv_h和hsv_s增强颜色扰动模拟不同光线更有效的是补充不同场景的行人图或者用现有的预训练权重冻结前10层只训练检测头。用freeze10参数可以让模型保留原先的通用特征缓解过拟合。6. 用best.pt实测视频素材再用ONNX导出做跨平台部署训练完成后你得到的best.pt只能在有PyTorch环境里跑。实际项目里经常要把模型交给另一个团队对方只有onnxruntime这时建议导出一份ONNX文件。使用Ultralytics的导出命令yolo export modelruns/pedestrian/train/weights/best.pt formatonnx dynamicTrue opset13dynamicTrue让输入的宽高不固定方便推理不同分辨率的视频素材。导出后在命令行里拿一段行人视频测一下yolo predict modelruns/pedestrian/train/weights/best.pt sourcetest_video.mp4 saveTrue如果输出结果里行人的框稳定跟随没有频繁跳变说明模型基本可用。跳变明显时可以适当调高视频预测时的conf阈值到0.35过滤掉低置信度的误检框。我自己的习惯是每一版模型都同时保留best.pt和导出的best.onnx。pt文件用于继续训练或微调onnx文件用于快速部署。在Mac上导出ONNX时如果MPS报算子不支持可以先切到CPU导出输出结果一致。这个流程帮我省下过好多次“换个机器就重训”的麻烦希望也能帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。