
简介本资源为自动驾驶场景下的多类别交通物体检测数据集面向从事目标检测算法研发、模型训练与课程实践的开发者及学生可解决复杂道路环境中多目标识别与标注数据匮乏的问题。数据集共含1154张训练图像覆盖动物、行人、汽车、公交车、卡车、自行车、摩托车、三轮车、交通灯、停车标志、道路标牌、消防栓、护栏、反光锥、坑洞、斑马线、盲道、检票闸机等28类目标兼顾车辆、行人、交通设施与道路缺陷等典型场景。压缩包共2000个文件以1154个YOLO格式txt标注、844张jpg图像为主另含1个yaml配置文件与1份docx说明文档整体约72.82MB标注包含边界框坐标与类别标签可直接用于YOLO系列模型训练。目前已有87人学习下载适合快速搭建自动驾驶感知实验、验证多类别检测效果并开展模型调优。1. 自动驾驶多类别交通物体检测数据集一个压缩包背后到底装了什么拿到「自动驾驶多类别交通物体检测数据集7.zip」这个标题多数人第一反应是解压、看目录、数图片然后直接丢进 YOLO 开训。但真正决定这个数据集能不能用的不是图片数量而是它的标注体系和你下游任务是否对得上。自动驾驶场景下的交通物体检测核心诉求是让模型在车载视角下同时识别车、人、骑行者、交通标志、信号灯等多类目标且要处理遮挡、截断、小目标和极端光照。这个数据集面向的就是这类需求多类别、交通场景、检测任务。它适合三类人想快速验证检测模型在交通场景下表现的算法工程师、需要做数据增强和类别平衡实验的研究者、以及拿它当预训练或蒸馏底料的落地开发者。但先别急着训标注格式、类别映射、坐标越界这三件事没搞清楚后面全是返工。2. 先搞懂多类别交通物体检测的数据组织逻辑2.1 检测数据集的三层结构图像、标注、类别表一个能直接开训的检测数据集本质上是三样东西的绑定关系图像文件、每张图对应的标注文件、以及全局的类别定义表。图像负责提供像素标注负责告诉模型「哪里有什么」类别表负责把标注里的类别 ID 映射成人类可读的名字。三者任何一处对不上训练就会出问题。交通物体检测的特殊性在于类别之间的视觉差异和共现关系。车和卡车在远距离下几乎无法区分行人和骑行者只差一个是否骑车交通标志和信号灯在夜间都变成发光斑块。所以这个数据集的类别表设计直接决定了模型要学的是「粗粒度交通物体」还是「细粒度交通参与者」。常见做法是分成 vehicle、pedestrian、cyclist、traffic_sign、traffic_light 这几大类再在 vehicle 下细分 car、truck、bus、motorcycle。你拿到压缩包后第一件事不是解压看图而是找到类别定义文件确认它到底是几类、每类叫什么。标注格式方面检测任务主流是三种Pascal VOC 的 XML、COCO 的 JSON、YOLO 的 txt。VOC 和 COCO 是绝对坐标YOLO 是归一化后的中心点加宽高。这个数据集如果是从真实采集流程来的大概率是 VOC 或 COCO 格式因为标注工具默认导出这两种。你需要先确认格式再决定是直接转 YOLO 还是用原生格式训练。2.2 为什么交通场景的类别不平衡是常态而不是缺陷交通物体检测数据集里车辆类别的样本量通常是行人的几倍甚至十几倍交通标志和信号灯更少。这不是标注失误而是真实道路场景的分布就是如此。如果你用这个数据集训练发现模型对行人召回率低先别怀疑模型结构先看类别分布。处理类别不平衡的常见做法有三种重采样、损失加权、数据增强。重采样是让稀有类别在训练时被更频繁地采样损失加权是给稀有类别的分类损失更高权重数据增强是对稀有类别做更多的随机裁剪、缩放、色彩抖动。我一般会先统计每个类别的实例数如果最多和最少差超过 20 倍就必须做处理否则模型会退化成只检测车辆。提示统计类别分布时要按实例数而不是图片数来算。一张图里可能有 10 辆车但只有 1 个行人按图片数统计会严重低估不平衡程度。2.3 从压缩包到可训练集目录结构的标准做法一个规范的检测数据集目录通常长这样images 放原图labels 放标注train 和 val 各一份再加一个 data.yaml 描述路径和类别。但很多数据集压缩包不是这个结构可能是所有图片和标注混在一起或者按场景分文件夹。你需要先把它整理成训练框架能直接读的结构。整理的核心原则是图像和标注文件名必须一一对应只差扩展名。比如 images/0001.jpg 对应 labels/0001.txt。如果标注是 XML文件名也要对应。做不到一一对应训练时就会找不到标注报错或者静默跳过。3. 把数据集接进 YOLOv8 训练流程的完整操作3.1 解压后先做三件事看类别、看格式、看坐标拿到压缩包后不要直接开训。先解压然后做三件检查。第一找到类别定义文件确认类别数和类别名。第二打开几个标注文件确认格式是 XML、JSON 还是 txt。第三随机抽 20 张图把标注框画出来看坐标有没有越界、框有没有明显错位。这三件事做完你才知道后面要不要转格式、要不要清洗。我见过太多人跳过这一步训了半天发现类别名对不上或者标注框全是错的。# 解压并查看目录结构 unzip 自动驾驶多类别交通物体检测数据集7.zip -d traffic_dataset cd traffic_dataset find . -maxdepth 2 -type d | head -30 # 统计图片数量 find . -name *.jpg -o -name *.png | wc -l # 查看标注文件样例 find . -name *.xml | head -3 find . -name *.json | head -3 find . -name *.txt | head -3这段命令的作用是先摸清数据集的物理结构。find按扩展名统计图片和标注数量如果图片数和标注数差很多说明有缺失。head -3看标注文件样例能快速判断格式。参数上-maxdepth 2限制目录深度避免输出太多无关目录。3.2 标注格式转换VOC 转 YOLO 的脚本与边界处理如果标注是 VOC XML需要转成 YOLO txt。转换的核心是把绝对坐标的 xmin、ymin、xmax、ymax 转成归一化的中心点 cx、cy 和宽高 w、h。公式是cx (xmin xmax) / 2 / img_wcy (ymin ymax) / 2 / img_hw (xmax - xmin) / img_wh (ymax - ymin) / img_h。import os import xml.etree.ElementTree as ET from PIL import Image # 类别映射按你的数据集实际类别修改 CLASS_MAP { car: 0, truck: 1, bus: 2, motorcycle: 3, pedestrian: 4, cyclist: 5, traffic_sign: 6, traffic_light: 7 } def voc_to_yolo(xml_path, img_dir, out_dir): tree ET.parse(xml_path) root tree.getroot() img_name root.find(filename).text img_path os.path.join(img_dir, img_name) # 用实际图片尺寸不用 XML 里的 size避免标注工具写错 with Image.open(img_path) as im: img_w, img_h im.size lines [] for obj in root.findall(object): cls_name obj.find(name).text.strip() if cls_name not in CLASS_MAP: continue # 跳过未定义类别避免训练时报错 cls_id CLASS_MAP[cls_name] bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 坐标裁剪到图像范围内处理越界标注 xmin max(0, min(xmin, img_w)) xmax max(0, min(xmax, img_w)) ymin max(0, min(ymin, img_h)) ymax max(0, min(ymax, img_h)) if xmax xmin or ymax ymin: continue # 跳过无效框 cx (xmin xmax) / 2 / img_w cy (ymin ymax) / 2 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) out_path os.path.join(out_dir, os.path.splitext(img_name)[0] .txt) with open(out_path, w) as f: f.write(\n.join(lines)) # 批量转换 for xml_file in os.listdir(annotations): if xml_file.endswith(.xml): voc_to_yolo(os.path.join(annotations, xml_file), images, labels)这段脚本的关键处理点有三个。第一用 PIL 读实际图片尺寸而不是 XML 里的 size 字段因为标注工具经常写错尺寸。第二坐标裁剪到图像范围内处理标注越界。第三跳过无效框和未定义类别避免训练时出现 NaN 或索引错误。参数上CLASS_MAP 必须和你的数据集类别完全一致类别 ID 从 0 开始连续。3.3 划分训练集验证集与 data.yaml 配置转换完成后按 8:2 或 7:3 划分训练集和验证集。划分时要保证类别分布大致均衡不能随机分完发现验证集里没有行人。常见做法是按类别分层抽样或者至少打乱后划分。import os import random import shutil random.seed(42) # 固定随机种子保证可复现 img_dir images lbl_dir labels pairs [] for f in os.listdir(img_dir): if f.endswith(.jpg): lbl os.path.splitext(f)[0] .txt if os.path.exists(os.path.join(lbl_dir, lbl)): pairs.append(f) random.shuffle(pairs) split int(len(pairs) * 0.8) for phase, data in [(train, pairs[:split]), (val, pairs[split:])]: os.makedirs(fdataset/images/{phase}, exist_okTrue) os.makedirs(fdataset/labels/{phase}, exist_okTrue) for f in data: shutil.copy(os.path.join(img_dir, f), fdataset/images/{phase}/{f}) lbl os.path.splitext(f)[0] .txt shutil.copy(os.path.join(lbl_dir, lbl), fdataset/labels/{phase}/{lbl})划分脚本的核心是固定随机种子和检查标注存在性。random.seed(42)保证每次划分结果一致方便复现。检查标注文件存在是为了避免图片没有对应标注却被分进训练集。data.yaml 是 YOLOv8 读取数据集配置的文件内容如下path: ./dataset train: images/train val: images/val nc: 8 names: [car, truck, bus, motorcycle, pedestrian, cyclist, traffic_sign, traffic_light]nc是类别数必须和 CLASS_MAP 的长度一致。names的顺序必须和类别 ID 对应否则模型学到的类别会错位。3.4 启动训练与关键参数设置配置好后就可以启动 YOLOv8 训练。关键参数包括 imgsz、batch、epochs、lr0。交通物体检测中小目标多imgsz 建议不低于 640如果显存够可以上 1280。batch 根据显存调8 到 32 之间。epochs 一般 100 到 300看验证集指标是否收敛。yolo detect train \ datadataset/data.yaml \ modelyolov8n.pt \ imgsz640 \ batch16 \ epochs150 \ lr00.01 \ patience30 \ projectruns/traffic \ nameexp1patience30表示验证集指标 30 轮不提升就早停避免过拟合。lr00.01是初始学习率YOLOv8 默认会用余弦退火一般不用改。modelyolov8n.pt是最小模型适合先跑通流程确认数据没问题后再换更大的模型。4. 训练前后最容易翻车的几个地方4.1 类别名对不上导致模型学错类别现象训练 loss 正常下降但推理时类别全是乱的车被识别成行人。原因data.yaml 里的 names 顺序和标注文件里的类别 ID 不对应。比如标注里 car 是 0但 names 里第一个是 pedestrian。解决转换标注时就用统一的 CLASS_MAPdata.yaml 的 names 直接从这个 map 生成不要手写。4.2 标注坐标越界导致训练出现 NaN现象训练几个 epoch 后 loss 变成 NaN。原因标注框坐标超出图像范围归一化后出现负值或大于 1 的值导致损失计算异常。解决转换脚本里做坐标裁剪把 xmin、ymin、xmax、ymax 限制在 [0, img_w] 和 [0, img_h] 内无效框直接跳过。4.3 图片和标注文件名不对应导致静默跳过现象训练时提示找到的图片数远少于实际数量或者某些类别样本数为 0。原因图片是 0001.jpg标注是 0001.xml 转出来的 0001.txt但中间有大小写或前缀不一致。解决转换后统一检查一遍用脚本比对 images 和 labels 目录的文件名集合找出差集。4.4 验证集类别缺失导致指标虚高现象验证集 mAP 很高但实际测试效果差。原因随机划分时验证集里没有稀有类别模型在这些类别上没被验证到。解决划分时按类别分层抽样确保每个类别在验证集里至少有几十个实例。如果某个类别实例太少考虑合并类别或做数据增强。4.5 直接拿压缩包里的图片尺寸训练导致显存爆炸现象训练启动就 OOM。原因数据集里图片分辨率差异很大有的 4K 有的 480pYOLO 会按最大尺寸对齐。解决训练前统一 resize 到固定尺寸或者用 imgsz 参数强制缩放。但要注意强制缩放会改变小目标的相对大小交通标志这类小目标可能缩到几个像素建议先统计尺寸分布再决定。5. 用类别分布统计和可视化验证数据集质量训练之前我习惯先做一轮数据质量验证而不是等训完再看指标。具体做法是统计每个类别的实例数、每张图的平均目标数、目标尺寸分布然后把标注框画到图上抽查。这一步能提前发现类别不平衡、标注错位、图片损坏等问题。import os from collections import Counter from PIL import Image, ImageDraw def analyze_labels(label_dir, img_dir, sample_n10): cls_counter Counter() obj_per_img [] sizes [] files [f for f in os.listdir(label_dir) if f.endswith(.txt)] for f in files: with open(os.path.join(label_dir, f)) as fp: lines [l.strip() for l in fp if l.strip()] obj_per_img.append(len(lines)) for line in lines: parts line.split() cls_counter[int(parts[0])] 1 sizes.append((float(parts[3]), float(parts[4]))) print(类别实例数:, dict(cls_counter)) print(每图平均目标数:, sum(obj_per_img) / len(obj_per_img)) print(宽高均值:, sum(s[0] for s in sizes) / len(sizes), sum(s[1] for s in sizes) / len(sizes)) # 抽样画框 for f in files[:sample_n]: img_name os.path.splitext(f)[0] .jpg img_path os.path.join(img_dir, img_name) if not os.path.exists(img_path): continue im Image.open(img_path).convert(RGB) draw ImageDraw.Draw(im) w, h im.size with open(os.path.join(label_dir, f)) as fp: for line in fp: parts line.split() if len(parts) 5: continue cx, cy, bw, bh map(float, parts[1:5]) x1 (cx - bw / 2) * w y1 (cy - bh / 2) * h x2 (cx bw / 2) * w y2 (cy bh / 2) * h draw.rectangle([x1, y1, x2, y2], outlinered, width2) im.save(fcheck_{f}.jpg) analyze_labels(dataset/labels/train, dataset/images/train)这段脚本输出三个关键指标类别实例数、每图平均目标数、目标宽高均值。类别实例数直接反映不平衡程度如果最多和最少差 20 倍以上就要做重采样或损失加权。每图平均目标数反映场景密度交通场景一般 5 到 15 个目标太少说明图片可能是空场景太多可能是标注重复。宽高均值反映目标尺度如果均值小于 0.05说明小目标占比高需要调大 imgsz 或加 P2 检测层。抽样画框是最后一道保险。我一般会看 10 到 20 张重点看三类问题框有没有明显偏移、有没有漏标、有没有把背景框进去。这一步花 10 分钟能省后面几小时的排查。提示画框时用红色宽线在复杂交通场景下更容易看清。如果发现某张图框特别多或特别少单独拿出来看可能是标注异常。验证通过后再启动训练。训练过程中重点看三个指标box_loss 是否稳定下降、mAP50 是否持续提升、各类别 AP 是否均衡。如果某个类别 AP 一直是 0回去查这个类别的实例数和标注质量。如果 box_loss 震荡严重检查学习率和 batch 是否匹配。我自己的习惯是任何新数据集到手先跑一遍这个分析脚本把类别分布和抽样画框做完再开训。这个习惯帮我避过好几次翻车有一次发现某个类别的标注全是错的框在图像外还有一次发现验证集里根本没有稀有类别指标虚高。数据集的质量决定模型的上限训练技巧只是逼近这个上限。希望帮到你。本文还有配套的精品资源点击获取