☰
摩托车与行人目标检测:从YOLO数据集拆包到部署全流程
2026/10/5 3:56:47 网站建设 项目流程

简介:这是一份面向目标检测、智能交通及自动驾驶方向的行业数据集,聚焦道路监控场景中的摩托车与行人两类关键目标。资源共包含1095张实际道路场景图片(训练集937张、验证集158张),并配套YOLO格式的归一化边界框标注,可直接用于YOLOv5/v7/v8等主流框架的训练与验证。压缩包共2000个文件,以txt标注文件、jpg道路原图为主,另有yaml配置文件与docx数据说明文档,整体约62.91MB,目录结构清晰,便于快速导入项目。数据覆盖多种光照与视角条件,适合交通流量统计、危险行为预警、智慧城市安防及车路协同感知等应用场景,也可支撑摩托车-行人互动行为的学术研究。目前已有125人学习下载,对于需要快速构建交通场景检测模型的研究者或开发者而言,是一份标注规范、场景针对性强的高性价比数据资源。

1. 摩托车与行人目标检测数据集:拆包、标注、训练到部署的一次性走通

道路监控画面里,摩托车和行人是最容易被漏检的两类目标。它们体积小、骑行姿态多样、经常并行在人车混行的路口,行人检测做得好不代表摩托车检测也能做好,反过来也一样。这份数据集的 zip 包价值在于同时提供两类目标的原始图像和标注,让你用一个检测模型输出两类检测框。它适合智能交通、城市安防、辅助驾驶场景下的从业者和学生,搭配 YOLO 系列框架就能直接训练。你真正要投入的时间不在解压,而在把 zip 里的素材用对、把训练参数调到贴合实际路口,这部分才是决定模型上线后能不能用的关键。

2. 拆开这份 zip 先别急着训练:目录结构、标注格式与数据体检

2.1 读懂 YOLO 标注格式:五个字段还原一个目标框

绝大多数目标检测数据集打包时会附带 txt 格式标签,而不是 XML 或 JSON。这种 txt 每一行代表一个目标,共五个字段:类别编号、归一化中心点 x 坐标、归一化中心点 y 坐标、归一化宽度、归一化高度。前四个取值都在 0 到 1 之间,除以图像宽或高得到像素值。先写一段小脚本把标签还原成像素坐标,直观确认标注是否合理。

import os from PIL import Image def read_yolo_label(label_path, img_path): img = Image.open(img_path) w_img, h_img = img.size boxes = [] with open(label_path, 'r') as f: for line in f: parts = line.strip().split() if len(parts) != 5: print(f"标注行格式错误: {label_path}: {line.strip()}") continue cls_id = int(parts[0]) cx, cy, bw, bh = map(float, parts[1:]) # 反归一化:yolo 存的是中心点,需转回左上角和右下角 x1 = (cx - bw / 2) * w_img y1 = (cy - bh / 2) * h_img x2 = (cx + bw / 2) * w_img y2 = (cy + bh / 2) * h_img boxes.append((cls_id, x1, y1, x2, y2)) return boxes

这段脚本是最常用的检查手段。类别编号从 0 开始计,如果发现类别编号超过数据集的类别总数减一,说明标签文件写错或类别映射没对齐。另外有些数据集在标注时会把无效小目标写成宽高为 0,这类行要直接过滤,否则训练时 loss 会异常。读出来的坐标还能顺手转成 VOC 格式或 COCO 格式,方便和其他工具链对接。

2.2 数据体检脚本:核对图像编号与标注文件是否一一对应

拿到 zip 后先解压,然后做一次文件清单核对。很多数据集原始样本里有大量不存在标注的图片,或者标注文件对应的图像被误删,直接拿去训练会浪费大量时间。常见的做法是遍历整个目录,按文件名前缀对齐图像和标签,找出缺失标注和孤儿标签。

import os def scan_dataset(root): image_exts = {".jpg", ".jpeg", ".png", ".bmp"} images, labels = [], [] for dirpath, _, files in os.walk(root): for f in files: p = os.path.join(dirpath, f) ext = os.path.splitext(f)[1].lower() if ext in image_exts: images.append(os.path.splitext(p)[0]) elif ext == ".txt": labels.append(os.path.splitext(p)[0]) img_set, lbl_set = set(images), set(labels) print(f"图像总数: {len(img_set)}") print(f"标签总数: {len(lbl_set)}") print(f"缺失标签的图像: {len(img_set - lbl_set)}") print(f"没有图像对应的孤儿标签: {len(lbl_set - img_set)}") return img_set, lbl_set img_set, lbl_set = scan_dataset("./extracted_dataset")

这个脚本跑完,重点看两个数:缺失标签的图像数量,以及孤儿标签数量。缺失标签的图在 YOLO 训练时会被自动跳过,但会浪费 epoch;孤儿标签意味着对应图被作者遗漏在别的目录,找到后补回来可能多出几百个有效样本。血缘经验是,目标检测数据集里真正能用的样本数往往比文件名显示的要少 10% 到 15%,这一步能提前止损。

2.3 按 8:2 拆出 train/val,重组成 YOLOv8 约定目录

YOLOv8 默认读取 images/train、images/val 和 labels/train、labels/val 四个目录,标签和图像分别放在同名子目录下。手头 zip 里的目录结构大概率不是这个约定,所以建议按统一流程重新整理,保留一份干净副本。拆分时注意按图像粒度切分,避免同一张图的多个目标被拆散导致验证集信息泄露。

import os import random import shutil random.seed(42) src_img = "./extracted_dataset/images" src_lbl = "./extracted_dataset/labels" dst_root = "./moto_ped_dataset" image_files = [f for f in os.listdir(src_img) if f.lower().endswith((".jpg", ".jpeg", ".png"))] random.shuffle(image_files) val_num = max(1, int(len(image_files) * 0.2)) val_files = set(image_files[:val_num]) for split in ["train", "val"]: os.makedirs(os.path.join(dst_root, "images", split), exist_ok=True) os.makedirs(os.path.join(dst_root, "labels", split), exist_ok=True) for f in image_files: stem = os.path.splitext(f)[0] label_path = os.path.join(src_lbl, stem + ".txt") # 跳过没有标签的图像,避免训练时报空标注 if not os.path.exists(label_path): continue split = "val" if f in val_files else "train" shutil.copy2(os.path.join(src_img, f), os.path.join(dst_root, "images", split, f)) shutil.copy2(label_path, os.path.join(dst_root, "labels", split, stem + ".txt"))

这里的 random.seed(42) 保证每次运行拆分结果一致。val 比例 20% 是目标检测任务的常见取值,样本量小时可以降到 15%,但不要低于 10%,否则验证集的 mAP 波动会很大。重新整理这一步看起来繁琐,却是后续踩坑最少的基础,比直接改 data.yaml 指向原目录更可控。

3. 环境配置与首轮训练:用 Ultralytics 跑出第一版模型

3.1 环境配置:先把 torch 的 CUDA 版本对齐再装 ultralytics

如果你是第一次从零配置检测环境,最省事的路线是 conda 建一个独立 Python 3.10 环境,再按 CUDA 驱动版本安装对应 torch。不要一上来就装最新版 torch,很多坑都是 CUDA 运行时和 torch 编译版本不匹配引起的。先做环境对齐,具体命令如下。

# 查看显卡驱动支持的 CUDA 版本,注意这决定 torch 的 wheel 版本 nvidia-smi # 创建独立环境,Python 3.10 兼容性最稳 conda create -n yolo python=3.10 -y conda activate yolo # 以 CUDA 11.8 为例,指定 index-url 安装对应 torch pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 最后再安装 ultralytics,它会自动拉上 opencv、numpy 等依赖 pip install ultralytics

nvidia-smi 显示的 CUDA 版本是驱动支持的上限,不是实际运行版本。安装完 torch 后用 python -c "import torch; print(torch.cuda.is_available())" 确认输出为 True,再做训练。Ultralytics 这个包同时维护了 YOLOv8 和 YOLOv11 的训练入口,代码兼容性较好,所以后面所有命令在两种模型上都能用。

3.2 写 data.yaml:路径、类别名与编号必须一致

YOLO 训练需要一份 yaml 配置文件,告诉框架数据集绝对路径、训练和验证子目录、类别数量与类别名称。类别名只影响日志阅读和可视化,真正决定类别映射的是标注文件第一行的编号,所以编号顺序必须和标注文件一致。下面这份配置对应摩托车和行人两类目标。

# 建议写绝对路径,避免工作目录不同导致路径解析失败 path: /home/user/moto_ped_dataset train: images/train val: images/val nc: 2 names: 0: motorcycle 1: pedestrian

写完后可以先跑一条检查命令,让框架帮你验证 yaml 和标签是否配对。yolo detect train data=moto_ped.yaml model=yolov8s.pt epochs=1 imgsz=640。如果这一条能正常开始跑,再停掉,进入正式训练。一定要确认标注里的类别编号最大值为 1,否则会出现“class index out of range”之类的报错,这类报错往往在第一个 epoch 快结束时才出现,白白浪费几分钟。

3.3 首轮训练命令与日志判读:这些参数别照抄

首轮训练建议用 s 规格的预训练权重起步,先看数据质量再谈精度。直接上 xl 模型会在你还没排查完数据问题时耗费十倍的算力。基础命令如下。

yolo detect train \ data=moto_ped.yaml \ model=yolov8s.pt \ epochs=100 \ imgsz=640 \ batch=16 \ patience=30 \ workers=4

imgsz 默认 640,如果图像原始分辨率差异大,需要先统一缩放策略。batch 大小受显存限制,8G 显存用 16 可能溢出,降到 8 即可。patience 是早停参数,连续多少轮验证集 mAP 不提升就提前结束,设 30 通常足够。训练日志里重点看两行指标:box_loss 和 cls_loss 是否平滑下降,以及每轮末尾的 mAP50、mAP50-95。

首轮训练的目标不是拿到最高精度,而是判断标注是否整齐、类别是否均衡。如果第一个 epoch 的 loss 出现剧烈抖动,大概率是标签里有错误框或超大目标。此时应停止训练回到第 2 章做数据体检,不要硬等 100 个 epoch 结束。

4. 难例挖掘与数据增强:让摩托车和行人从“能检出”到“检得稳”

4.1 类别实例统计:样本不均衡直接拉低摩托车这一类的 mAP

摩托车和行人这两类目标在实际路口数据里往往不成比例,行人样本可能是摩托车的三到五倍。如果直接训练,模型会偏向行人,摩托车的召回率会明显落后。训练前统计每类目标的实例数,能提前预判这个问题。

from collections import Counter import os names = {0: "motorcycle", 1: "pedestrian"} def count_instances(label_dir): cnt = Counter() for f in os.listdir(label_dir): if not f.endswith(".txt"): continue with open(os.path.join(label_dir, f)) as fh: for line in fh: parts = line.strip().split() if len(parts) < 5: continue cls_id = int(parts[0]) cnt[cls_id] += 1 return cnt train_cnt = count_instances("./moto_ped_dataset/labels/train") for cls_id, c in sorted(train_cnt.items()): print(f"{names[cls_id]}: {c} 实例")

如果两者比例超过 5:1,常见做法有几条。一是对少数类样本做过采样,也就是在训练集里重复包含摩托车多的图像;二是对少数类的标签做小幅复制增强,让它在训练中被更多次看到;三是增大数据增强强度,让摩托车在旋转、缩放下出现更多形态。另外建议在验证集上分开查看两个类别的 AP 值,只看总体 mAP 会掩盖单类性能塌陷的问题。

人群密集路口的场景和 CrowdHuman 数据集很像,但骑摩托的人往往混在行人堆里,外观被遮挡严重。此时建议检查类别之间是否存在标注混淆,比如骑手坐在摩托车上时,标注框是否把骑手和车身框在一起,这会直接产生语义重叠,后面会专门说这一类坑。

4.2 框尺寸统计与切片策略:移动小目标检测的关键干预

摩托车和行人在远距离监控画面里经常只占几十个像素,属于典型的移动小目标检测场景。YOLOv8 默认的 640 输入尺寸对这类目标不友好,因为小目标缩放到 640 后可能只剩几个像素,特征完全丢失。先用脚本统计标注框的归一化面积分布。

import os import numpy as np names = {0: "motorcycle", 1: "pedestrian"} areas = {0: [], 1: []} for f in os.listdir("./moto_ped_dataset/labels/train"): if not f.endswith(".txt"): continue with open(os.path.join("./moto_ped_dataset/labels/train", f)) as fh: for line in fh: parts = line.strip().split() cls_id = int(parts[0]) w = float(parts[3]) h = float(parts[4]) areas[cls_id].append(w * h) for cls_id, vals in areas.items(): vals = np.array(vals) print(f"{names[cls_id]}: 框数={len(vals)}, 面积中位数={np.median(vals):.5f}, " f"<0.01占比={np.mean(vals < 0.01):.1%}")

归一化面积小于 0.01 意味着目标在原图上占不到 1% 的像素区域,这部分就是小目标。处理手段主要有三种:第一种是把 imgsz 从 640 调到 960 或 1280,增加输入分辨率,但这会同时增加显存消耗和推理耗时;第二种是对原始图像做切片,把大图切成四块或九块分别训练,推理时也切成对应块然后合并结果;第三种是直接用 SAHI 这类切片推理框架做部署,训练端不动,推理端自动切片。大多数监控场景下,imgsz 用 960 加 SAHI 切片足够。

4.3 增强参数调节:mosaic、mixup 与颜色抖动的取舍

YOLOv8 默认开启的增强已经很强,但要针对交通场景微调。默认的 mosaic 增强会把四张图拼成一张,对拥挤场景有效,但小目标会被稀释。mixup 会把两张图透明叠加,虽然能提升泛化能力,但在摩托车和行人重叠时容易产生重影噪声。根据实际场景做取舍,我的常见参数组合如下。

yolo detect train \ data=moto_ped.yaml \ model=yolov8s.pt \ epochs=100 imgsz=960 batch=8 \ hsv_h=0.02 hsv_s=0.6 hsv_v=0.5 \ degrees=10 translate=0.15 scale=0.4 shear=5 \ fliplr=0.5 mosaic=0.8 mixup=0.2

hsv 三个参数负责颜色抖动,交通场景在阴雨天和夜间颜色差异大,适度增强有帮助。degrees 设为 10,因为摩托车有倾斜姿态但不会完全翻转。fliplr 水平翻转对交通数据安全,颠倒翻转一般人不开。mosaic 保留但降到 0.8,避免四图拼接比例过高导致小目标消失。mixup 降到 0.2,主要面向半遮挡场景的鲁棒性。

这一组参数的核心思路是:让模型见到的摩托车姿态和光线更多,但不让拼接噪声毁掉目标边界。具体数值要根据你的数据微调,如果验证集 mAP 在 50 轮后不再上升,优先检查是不是增强过强导致模型看不到干净目标。

5. 避坑:训练与部署中我踩过的五个具体问题

5.1 现象一:loss 降得很顺,val mAP 一直在低位徘徊

训练日志里 box_loss 每轮都在下降,但 val mAP 始终在 0.4 到 0.5 之间不动。原因多数是标注框质量差,比如部分摩托车框只包住了车身没包住骑手,或者行人框把路障也包含进去。模型学到的是不一致的目标边界。

解决方法是抽 30 到 50 张训练图像,用模型预测结果和 GT 框画在一起人工检查。常见做法是直接把 val 里预测错的图导出,看预测框和真实框的偏离方向。如果偏离方向杂乱,就是标注噪声;如果总是漏掉小目标,回到第 4 章做切片或调 imgsz。

5.2 现象二:摩托车和行人紧贴着走,模型只出一个框

路口停车等待时,骑手和行人并肩距离极近,NMS 后两个框被合并成一个。这类现象的本质是标注框高度重叠,模型把重叠区域识别为一个目标。

解决思路是给这两个类别调整 NMS 策略。YOLO 默认 NMS 的 IoU 阈值是 0.5,可以在训练参数里设置 iou=0.4 降低合并概率。另外在标注时确认骑手和摩托车是否被标成同一个框。如果数据集把骑手和车身标成一个摩托车框,行人紧贴时必然产生冲突,此时宁可把摩托车框缩小到车身,让骑手身体轮廓露出更多边缘。

5.3 现象三:白天 mAP 还行,夜间或逆光场景漏检严重

训练集里白天正常光照图像占比过高,夜间图像不足,模型相当于只学会了白天的外观。逆光场景下行人轮廓和背景融为一体,摩托车头灯又会产生过曝光晕。

解决方法是做亮度增强合成。常见做法是使用 Albumentations 的 RandomBrightnessContrast 配合 HueSaturationValue 做低照度模拟,生成一批亮度更低、对比度更高的训练样本。还可以专门收集夜间监控截图加入训练集。数据增强只能补一部分,真实夜间数据才是提高夜间 mAP 的根本,两者叠加通常能把夜间 mAP 提高 8 到 12 个点。

5.4 现象四:前几个 epoch loss 波动特别大甚至出现 NaN

开箱跑通后 loss 在第一个 epoch 冲到 20 以上,后面也没降下来,检查发现是标签里有归一化坐标越界。比如某个标注的 cx 是 1.2,表示中心点超出图像右边界,模型根本无法学会这种目标。

解决方法是清洗标签,把 cx 或 cy 小于 0 或大于 1 的行删除,把 bw 或 bh 小于等于 0 的行删除。范围检查脚本和 2.2 节的体检脚本合并执行,训练前过滤一遍。另外学习率过大也会导致 loss 跳变,ultralytics 默认 lr0=0.01 在大多数场景是安全的,如果自己改了 lr0,先恢复默认再排查。

5.5 现象五:导出 ONNX 后在推理端精度下降明显

训练时 mAP 不错,导出 ONNX 交给推理框架后,检测框位置偏移或者小目标消失。原因通常是导出时没有固定输入尺寸,或者推理框架做了半精度优化,而模型对小目标本来就不稳定。

解决方式是导出时固定 imgsz,并使用 NMS 集成导出。常见命令如下。

yolo export \ model=runs/detect/train/weights/best.pt \ format=onnx \ imgsz=960 \ half=True \ simplify=True

half 开启半精度会显著缩小模型体积,但如果精度下滑,改成 half=False 对比一次。simplify 会做图优化,减少算子数量,对推理性能有帮助。导出后使用 onnxruntime 加载,对比同一张图在 PyTorch 和 ONNX 下的输出框差异,如果差异超过 2 个像素,就要关闭 half。

6. 双指标验收模型质量,再落到实际视频流的部署门槛

训练完成后不要只看 val mAP 一个数字。我习惯同时看 mAP@0.5 和 mAP@0.5:0.95,前者代表粗定位能力,后者代表精细定位能力。对摩托车和行人检测来说,两者差距过大说明框的边界不稳定。在验证集上分别查看两个类别的 PR 曲线,曲线往右上角靠得越近越好,如果某个类别的曲线中段明显凹陷,说明存在系统性的漏检或误检。

落地到监控设备前还要过三关:第一关是推理速度,笔记本上 20ms 一帧不等于监控盒子上也能跑,要直接在实际设备上量化。第二关是检测稳定性,视频流里单帧偶发跳动可以接受,但连续几十帧丢同一目标不能接受,这种问题通常出在帧间目标被遮挡或光照突变。第三关是类别误用,行人检测框套到电动自行车上这类场景,在交通管理场景里会产生很差的业务体验。

我现在的习惯是每次训练完都保留一份完整的数据增强配置和随机种子记录,三个月后回看模型效果下降时,能快速定位是数据变了还是参数漂了。从数据集 zip 到可部署模型,80% 的工作量在数据清洗和难例挖掘,真正敲训练命令只占很小一部分。希望这份从拆包到验收的路线能帮你在摩托车和行人检测项目上少走弯路,把时间花在真正影响精度的环节上。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询