
简介面向道路监控与自动驾驶感知场景摩托车与行人目标检测数据集按训练集937张、验证集158张划分聚焦摩托车和行人两类关键目标可服务于交通流量统计、危险行为预警、智慧城市安防及交通行为研究等AI应用有较高的实用价值。压缩包共2000个文件包含1095个YOLO格式txt标注、903张JPEG图片、1个yaml配置文件及1份说明文档整体体积62.91MB标注采用归一化边界框和类别标签便于直接接入YOLOv5/v7/v8等主流框架训练。目前已有124人学习浏览。数据覆盖多种光照和视角条件目标定位精准、场景针对性强省去开发者自行采集与标注的时间可快速投入模型训练迭代同时兼容主流YOLO框架无论是初学目标检测的开发者还是需要快速验证的中高级算法工程师、竞赛选手都能依托这份工业数据集缩短研发周期。1. 摩托车与行人目标检测数据集交通场景先拿它开刀做交通监控或自动驾驶感知的人应该都有同感模型框架已经不是瓶颈缺的是贴着自己场景的标注数据。网上公开数据集要么场景不符要么标注格式要转半天要么类别太杂根本没法直接用。这份摩托车与行人目标检测数据集就是为“道路监控场景下快速跑通 YOLO 训练”准备的。1095 张真实道路监控 JPEG 图片训练集 937 张、验证集 158 张标注成 YOLO 格式 txt 文件只有两个类别motorcycle 和 pedestrian。对于正在用 YOLOv5/v7/v8 做交通场景目标检测、或者想验证自己数据 pipeline 的人来说解压即用省掉大量数据清洗和格式转换时间。2. YOLO 标注格式与数据校验先搞清楚 txt 里那五个数字拿到数据集第一步不是急着训练而是把标注文件读明白。这个数据集的标注是 YOLO 格式也就是每个图片对应一个同名的 txt 文件txt 里每一行代表一个目标框。解压后你会看到典型的 Roboflow 导出结构图片在 images/train 和 images/valid 下标签在 labels/train 和 labels/valid 下文件名带了 .rf. 加一串哈希后缀这是 Roboflow 导出的特征不要手工改文件名图片和标签靠同名关联改了名就找不到了。2.1 目录结构与标签文件的读取规则打开任意一个 txt 文件每行格式是固定的class_id x_center y_center width height以 0 1 0.234 0.456 0.123 0.067 为例0 是类别编号后面四个数分别是边界框中心点的 x、y 坐标、框的宽度、框的高度。这四个值全部做了归一化范围在 0 到 1 之间是相对于图片宽高的比例。所以要还原成像素坐标需要知道原图的宽高 W 和 Hx_min_pixel (x_center - width/2) * W y_min_pixel (y_center - height/2) * H box_width_pixel width * W box_height_pixel height * H类别编号的顺序以压缩包里的 classes.txt 为准Roboflow 导出时会自动生成这个文件。这个数据集的 classes.txt 内容一般是 pedestrian 在前、motorcycle 在后对应编号 0 和 1但你拿到手后务必自己打开确认一遍。因为后续写 data.yaml 时names 列表的顺序必须和 txt 里的编号严格一致否则训练能跑通预测结果类别全错位。2.2 标签可视化与非法标注过滤脚本我拿到任何 YOLO 数据集第一件事永远是写脚本画框可视化抽查几十张图。这一步能发现八成以上的标注问题坐标越界、框太小、类别标错、宽高为 0。下面是我常用的一个检查脚本import cv2 import os import glob img_dir images/train label_dir labels/train img_paths glob.glob(os.path.join(img_dir, *.jpg))[:30] names {0: pedestrian, 1: motorcycle} colors {0: (0, 255, 0), 1: (0, 0, 255)} for img_path in img_paths: label_path os.path.join(label_dir, os.path.basename(img_path).replace(.jpg, .txt)) if not os.path.exists(label_path): print(f[警告] 缺少标签文件: {label_path}) continue img cv2.imread(img_path) H, W img.shape[:2] with open(label_path, r) as f: lines f.readlines() for line in lines: parts line.strip().split() if len(parts) ! 5: print(f[警告] 非法行: {img_path} - {line.strip()}) continue c, cx, cy, bw, bh map(float, parts) x int((cx - bw / 2) * W) y int((cy - bh / 2) * H) w int(bw * W) h int(bh * H) if w 0 or h 0: print(f[警告] 宽高为0: {img_path} - {line.strip()}) continue cv2.rectangle(img, (x, y), (x w, y h), colors[int(c)], 2) cv2.putText(img, names[int(c)], (x, max(0, y - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, colors[int(c)], 1) out_path os.path.join(check_vis, os.path.basename(img_path)) os.makedirs(check_vis, exist_okTrue) cv2.imwrite(out_path, img) print(f已保存: {out_path})这段脚本的逻辑很简单遍历训练集前 30 张图读取同名标签把归一化坐标还原成像素框用 OpenCV 画在原图上。画框前先检查标签文件是否存在、字段数和数值是否合法。我一般会顺带把标注框面积小于图片面积 0.5% 的目标打印出来这种小目标在训练时容易被当成背景忽略后面调参时要特别关注。除了可视化我还会跑一个全量扫描过滤掉所有可能让训练崩溃的非法标注import os label_dir labels/train bad_count 0 for f in os.listdir(label_dir): if not f.endswith(.txt): continue path os.path.join(label_dir, f) with open(path, r) as fp: lines fp.readlines() for line in lines: parts line.strip().split() if len(parts) ! 5: print(f[错误] {f}: 字段数不对 - {line.strip()}) bad_count 1 continue try: c, cx, cy, bw, bh map(float, parts) except ValueError: print(f[错误] {f}: 数值转换失败 - {line.strip()}) bad_count 1 continue if not (0 cx 1 and 0 cy 1): print(f[错误] {f}: 中心点越界 - {line.strip()}) bad_count 1 if bw 0 or bh 0 or bw 1 or bh 1: print(f[错误] {f}: 宽高异常 - {line.strip()}) bad_count 1 print(f扫描完成发现 {bad_count} 个问题标注)重点检查两类问题中心点是否落在 0 到 1 区间内宽高是否非零且不超过 1。YOLO 训练时如果读到 center 坐标越界损失函数里的宽高对数项会算出来 NaN表现为训练到一半 loss 突然变乱。这个脚本跑一遍只要几秒钟能省掉后面一晚上的排查时间。3. 用 YOLOv8 训练这套数据yaml 配置、训练命令与监控指标数据校验完毕就可以进入训练环节。这个数据集标注的是 YOLO 格式所以 YOLOv5、YOLOv7、YOLOv8 都能直接吃不需要额外转格式。我习惯用 YOLOv8因为命令行交互更简洁训练日志也更直观。如果你的环境已经装好 ultralytics 包下面这套流程可以直接跑。3.1 数据集配置文件 data.yaml 的写法YOLOv8 训练前需要一个 yaml 文件描述数据路径和类别信息。新建一个 motorcycle_pedestrian.yaml内容如下# 数据集配置文件摩托车与行人目标检测 path: /home/user/datasets/motorcycle_pedestrian # 数据集根目录改成你解压的绝对路径 train: images/train val: images/valid nc: 2 names: 0: pedestrian 1: motorcycle这个文件有几个容易踩的坑。path 必须写绝对路径相对路径在不同工作目录下运行很容易失效。train 和 val 是相对于 path 的路径这里的数据集解压后目录结构是 images/train所以直接写 images/train。最关键的还是 names 的顺序必须和 classes.txt 里的编号对上。如果你解压后发现 classes.txt 里顺序是 motorcycle 在前、pedestrian 在后那 names 就要相应调换否则模型会拿行人标签去拟合摩托车框训练过程看起来正常实测全是错位预测。3.2 训练命令与关键超参数说明配置写好之后直接用命令行启动训练yolo detect train \ datamotorcycle_pedestrian.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ patience20 \ device0参数含义逐个说明。modelyolov8s.pt 是 COCO 预训练权重YOLOv8s 是 small 版本速度与精度比较均衡。为什么不用 yolov8x因为这套数据集只有 1095 张图参数量过大的模型在小数据集上很容易过拟合训练集 loss 漂亮、验证集 mAP 上不去。epochs 设 100配合 patience20 做早停如果连续 20 轮验证集指标没有提升就自动停止省时间。imgsz640 是训练分辨率和数据集中图片的原始分辨率接近不需要强行拉高。batch16 取决于显存6G 显存建议降到 8。device0 指定第一张显卡没有 GPU 就改成 devicecpu但训练时间会明显变长。第一次训练时模型会自动下载 COCO 预训练权重到当前目录如果网络受限下载失败可以先用 CPU 模式跑通数据 pipeline再考虑权重问题。COCO 预训练里包含 person 类和这里的 pedestrian 语义高度接近迁移学习时行人检测的初始权重是有效的但 COCO 里没有 motorcycle 这个类别所以摩托车分支基本是从零学起这也是为什么训练初期的 loss 下降会比较慢不必焦虑。3.3 训练输出里的几个关键指标怎么看训练结束后结果在 runs/detect/train 目录下。我最先看三个文件按顺序排优先级。第一个是 results.png里面包含训练集 loss、验证集 loss、mAP50、mAP50-95 四条曲线的变化趋势。mAP50 是指 IoU 阈值 0.5 下的平均精度mAP50-95 是 0.5 到 0.95 的均值后者更严格。交通场景检测一般先盯 mAP50能上 0.8 就算不错。第二个是 confusion_matrix.png横轴是真实类别纵轴是预测类别对角线越亮越好。这个文件能直观看出摩托车和行人之间有没有互相误检以及背景被误检成目标的比例。第三个是 labels_correlogram.jpg它展示标注框的中心点分布和宽高分布如果中心点散落成均匀格子说明标注整体没大问题如果某个点特别密集可能训练集里某个位置重复出现了大量目标需要留意场景单一性。关注一下 val 阶段的 mAP 曲线和训练阶段的 loss 曲线是否同步。如果训练 loss 一路下降但 val loss 从某轮开始反弹说明过拟合开始patience 早停会在这种时候帮你兜底。4. 小目标与类别不均衡数据增强参数和损失权重的实测调整这套数据集的场景是道路监控意味着有大量远距离目标行人可能只有十几个像素高摩托车在画面远端也很小。小目标检测是这类数据集的硬骨头训练时不做针对性调整mAP 会被小目标拉低一大截。同时摩托车和行人的数量大概率不均衡监控场景里行人出现的频率通常高于摩托车这就带来类别不平衡问题。这一章讲我实际调参的做法。4.1 小目标漏检从 mosaic 到多尺度训练的参数调整YOLOv8 默认开了 mosaic 增强它会随机拼 4 张图组成一张训练图相当于把不同场景的目标拼在一起对小目标检测帮助很大。但 mosaic 不能一路开到结束训练后期如果还开着模型会被这种“非自然”的图片干扰难以收敛到真实分布。常见做法是在最后 10 个 epoch 关闭 mosaic让模型在近似真实分布的图片上做微调。YOLOv8 里用这个参数控制yolo detect train \ datamotorcycle_pedestrian.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ close_mosaic10close_mosaic10 表示最后 10 个 epoch 自动禁用 mosaic。另一个对小目标友好的做法是提高训练分辨率把 imgsz 从 640 提到 960。原理很简单输入分辨率越高小目标占的像素越多模型能提取到的特征就越丰富。但代价是显存占用变成原来的两倍以上训练时间也明显拉长8G 显存级别建议先试 640 或 736显存充裕再上 960。此外我还会修改增强超参数。YOLOv8 的增强参数集中在 hyp 文件里复制默认 hyp 文件后改这几个值# hyp_custom.yaml 片段 hsv_h: 0.015 hsv_s: 0.7 hsv_v: 0.4 degrees: 5.0 translate: 0.2 scale: 0.5 mosaic: 1.0 mixup: 0.0degrees 我只给了 5 度。行人横平竖直地站着摩托车也是水平行驶旋转过大会把目标形变调成不合理的姿态模型反而学不到稳定的特征。translate 是平移增强0.2 表示图片在水平和垂直方向最多平移 20%这个对小目标有帮助。scale 缩放 0.5 也很关键它会随机把目标缩小等效于模拟远距离视角。mixup 我直接关掉因为行人叠加摩托车会产生语义混乱的混合体和监控场景的真实分布差太远。训练时用 --hyp hyp_custom.yaml 指定这个文件即可。4.2 类别不平衡先统计再决定策略调整类别不平衡前必须先量化各类目标的数量差距。写一个统计脚本import os label_dir labels/train class_count {} for f in os.listdir(label_dir): if not f.endswith(.txt): continue with open(os.path.join(label_dir, f), r) as fp: for line in fp: parts line.strip().split() if len(parts) 1: continue c int(float(parts[0])) class_count[c] class_count.get(c, 0) 1 total sum(class_count.values()) for c in sorted(class_count.keys()): print(f类别 {c}: {class_count[c]} 个目标, 占比 {class_count[c]/total:.1%})脚本会统计每个类别在整个训练集中的目标总数。假如 pedestrian 有 4000 个目标而 motorcycle 只有 1500 个比例接近 3:1这种差距在 YOLO 里通常还能接受不太会导致某一类彻底学不出来。但如果差距超过 5:1就要干预了。我实践下来最稳妥的做法不是改损失函数而是数据级层面做平衡。把包含摩托车目标的图片路径收集起来在训练时多采样几轮等效于让摩托车类别的学习次数变多。具体操作生成一份训练列表把含摩托车的图片路径重复写入 2 到 3 遍然后用这份列表训练。YOLOv8 支持用 txt 文件指定训练集# train_balanced.txt /path/to/datasets/images/train/image_a.jpg /path/to/datasets/images/train/image_b.jpg /path/to/datasets/images/train/image_a.jpg配合 data.yaml 里把 train 改为这个 txt 文件的路径。这样做的代价是单个 epoch 变长但模型对少数类的召回率提升很明显。另外一个思路是调整损失权重让模型对少数类的分类错误更敏感但 YOLOv8 的默认 cls loss 权重在多数场景下已经够用数据层面的平衡更容易控制也不容易引入新的过拟合。5. 训练翻车排查标签错位、Loss 为 NaN 与验证高分的假象这一章集中写我在类似数据集上真实遇到过的踩坑记录。每一条都是“现象 → 原因 → 解决”的完整链路训练前花五分钟扫一遍能少走不少弯路。5.1 图片与标签文件名不匹配训练时目标全丢现象训练日志里每张图显示的 targets 数量为 0loss 一直降不下去甚至从一开始就震荡。原因数据集图片是 JPEG 格式但 Roboflow 导出的文件名后缀不统一有的图片是 .jpg标签却是 .txt。一开始我把图片处理后重新保存成 .png导致图片名变成了 image.png而标签还是 image.txt名称对不上YOLO 就认为这张图没有目标。解决训练前写一个校验脚本遍历 images 和 labels 目录找出所有“有图无标”和“有标无图”的文件。如果确实需要批量改名用 os.rename 统一后缀前提是只改后缀、不改变主体部分。5.2 训练中 Loss 变 NaN多轮重启无效现象训练正常跑了几十个 epoch突然某一步 loss 变成 nan之后再也恢复不了重启训练还是会在类似位置崩溃。原因标签文件里有非法数值。最常见的是 width 或 height 为 0也有中心点越界导致 IoU 计算异常。归一化坐标理论上是 0 到 1但标注工具某些情况下会打出 1.2 这种越界值训练到那个样本时梯度爆炸。解决用第 2 章的全量扫描脚本先过滤一遍把所有宽度或高度小于等于 0 的标注行删掉。注意删除时要保留原文件的其它行只移除问题行不要整文件删除。另外如果用的是随机初始化权重而不是预训练权重学习率过高也容易 NaN把 lr0 从默认 0.01 降到 0.001 再试一次。5.3 验证集 mAP 高但实际视频漏检严重现象训练结束验证集 mAP50 有 0.85看起来不错。拿到真实监控视频去跑结果画面远端的小目标大量漏检摩托车过弯时也经常丢掉。原因这是典型的训练集与推理场景分布不一致。验证集的图片大部分来自和训练集相同的时间段和机位模型相当于“背题”了。实际视频里机位角度变化、阳光方向不同、目标距离更远模型没见过这些形态于是漏检。还有一个隐藏原因默认推理 conf 阈值是 0.25监控场景下模型对远距离目标的置信度只有 0.1 到 0.2 之间全被滤掉了。解决分两步。第一步把推理阈值降低conf0.1 跑一遍看漏检是否有明显改善这一步零成本可以先试。第二步对比实测视频帧和训练集图片的亮度直方图如果差异巨大训练时把 hsv_v 增强从 0.4 提到 0.8让模型见过更宽的亮度分布。不要盲目加大训练集先确认是阈值问题还是分布问题大部分情况阈值就能解决一半漏检。5.4 显存溢出训练中途直接退出现象batch16、imgsz640 的训练在第二个 epoch 直接报 CUDA out of memory进程退出。原因显存占用峰值并不仅取决于 batch 和 imgsz还和 mosaic 增强有关。mosaic 每步要拼 4 张图峰值显存比理论计算高不少。如果显卡只有 8Gbatch16 在 YOLOv8s 下确实紧张。解决把 batch 降到 8imgsz 降到 640再跑一次。如果还是 OOMbatch 再减半到 4。注意 YOLOv8 的 batch 是总 batch 数不是单卡 batch多卡训练时 batch 会自动除以卡数。验证场景也一样推理时显存不够就把 imgsz 调低或改用 compile 后的模型。5.5 类别编号顺序写错预测框类别全错位现象训练和验证都正常mAP 看起来正常但部署后预测结果里所有摩托车都标成了行人行人标成了摩托车。原因txt 标注里的类别编号和 data.yaml 的 names 顺序对不上。比如数据集原始 classes.txt 是 motorcycle0、pedestrian1但抄 yaml 时手滑写成了 pedestrian0、motorcycle1模型学到的特征是对的但输出层映射的标签名错了。解决无解只能重新训练。避免的办法是训练前用脚本读 classes.txt 自动生成 names 列表而不是手工抄写。我现在每次训练前都会把 classes.txt 的内容原样贴进 data.yaml并且用第 2 章的可视化脚本抽查 10 张图确认画出来的框对应的类别名正确再开始训练。这个习惯帮我避免了好几次白跑几个小时的训练。6. 验收不只看 mAP用混淆矩阵与逐图预测检查漏检误检模型训练完最忌只看一个 mAP 数值就宣称“效果不错”。我一般会做三层验收每一层都可能发现 mAP 掩盖的问题。第一层是跑验证集的 per-class 指标。在训练完的目录下执行yolo detect val \ modelruns/detect/train/weights/best.pt \ datamotorcycle_pedestrian.yaml \ imgsz640输出表格里会分别列出 pedestrian 和 motorcycle 的 precision、recall、mAP50、mAP50-95。重点看 recall也就是“真实目标有没有被找出来”。如果摩托车类别的 recall 明显低于行人说明小目标漏检集中在摩托车上。这个结论单独看 mAP 是看不出来的mAP 是 precision 和 recall 的综合一个类别的低召回会被另一个类别的高精度掩盖。第二层是看混淆矩阵。训练目录里会自动生成 confusion_matrix.png直接打开它。我关心两个位置一是摩托车和行人之间的互相混淆监控场景里骑行人经常和摩托车重叠模型容易把骑手的上半身单独检测成行人漏掉下面的摩托车二是背景那一列如果非对角线有明显的亮点说明模型在误报。看到这类问题后针对性补样本比盲目加数据更有效。第三层是逐图预测抽查。从验证集里随机选 20 张图用 best.pt 跑一遍推理打开标注好的预测图逐张看yolo detect predict \ modelruns/detect/train/weights/best.pt \ source/path/to/val_images/ \ conf0.10 \ iou0.45 \ saveTrue这里我用 conf0.10 而不是默认的 0.25故意把阈值调低看看模型在低置信度下能检出多少真实目标。如果低阈值下出现大量误检说明模型的置信度校准有问题如果低阈值下能检出之前漏掉的目标说明只是推理阈值设置偏高部署时调低即可。从那以后我每次拿到任何新数据集都会强制自己按这个流程走一遍先跑标签校验脚本再做可视化抽查然后才配置训练。训练完先看 per-class 指标和混淆矩阵最后用低阈值推理抽查预测图。这一套流程帮我挡掉了大部分“训练崩了、效果拉胯”的夜间加班。希望帮到你。本文还有配套的精品资源点击获取