简介:这份资源面向计算机视觉目标检测的学习者与开发者,提供底特律街景场景的六分类数据集,可直接用于YOLO系列模型的训练与验证,省去自行标注与格式转换的环节。类别覆盖汽车、交通标志、车道线、行人、摩托车手与骑行者,贴近自动驾驶与城市道路感知的典型任务。压缩包共2000个文件,以1999个txt标注文件和1个Python可视化脚本为主,整体约472.5MB;数据按训练集1575张、验证集450张、测试集225张划分,图片与标签一一对应,并附类别文件。配套的show.py只需传入一张图片即可绘制边界框并保存到当前目录,便于快速检查标注质量。目前已有143人学习下载,适合入门目标检测流程、验证模型效果或开展街景感知相关实验的读者使用。
1. 底特律街景 6 分类数据集:为什么它比 COCO 更适合练 YOLO 落地
如果你正在搜「目标检测数据集下载」,大概率已经翻过一圈 COCO、VOC、KITTI,然后发现一个尴尬的事实:这些数据集要么类别太多、标注太杂,要么场景太干净,跑出来的模型一放到真实街景里就翻车。底特律街景目标检测数据集(6 分类,YOLO 标注格式的 txt 文件)正好卡在一个很舒服的位置——它只保留街景里最常出现的 6 类目标,标注直接是 YOLO 的归一化 txt,拿到手不用转格式就能开训。
这个数据集解决的核心问题是「从通用检测到场景检测的过渡」。COCO 有 80 类,你训完模型,它认识猫认识狗,但未必认识街边的消防栓和交通标志;底特律街景把类别收敛到 6 类,每一类都是自动驾驶和城市视频分析里真正要用的目标。适合谁?适合已经跑通过 YOLOv8 官方 demo、想拿一个真实场景数据集练「数据检查 → 训练 → 评估 → 部署」完整链路的人,也适合做计算机视觉大作业、需要一份标注干净、类别可控的数据的学生。
YOLO 标注格式的 txt 文件意味着什么?每张图对应一个同名 txt,每行是class_id x_center y_center width height,坐标全部归一化到 0~1。这个格式的好处是解析极快、和 YOLOv5/v8/v11 的训练管线天然兼容,坏处是它不存图像尺寸、不存类别名,类别名要你自己在data.yaml里对齐。很多人第一次拿到这种数据集,直接train.py一跑,结果 loss 不降,回头才发现 txt 里的 class_id 从 1 开始,而 YOLO 默认从 0 开始——这就是后面避坑章节要展开的血泪经验。
2. 拆开一份 YOLO txt 数据集:目录结构、类别映射与标注校验
2.1 标准目录长什么样,以及为什么不能随便改
一份能直接喂给 YOLO 的街景数据集,目录结构通常是这样的:
detroit_street/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamlimages和labels必须严格平行:images/train/xxx.jpg对应labels/train/xxx.txt。YOLO 在加载时会用图片路径替换images为labels、替换扩展名为.txt去找标签,找不到就当作负样本(背景图)处理。所以如果你把某张图的 txt 漏了,模型会把图里所有目标当背景学,这是最隐蔽的污染之一。
常见做法是先把原始压缩包解压到一个临时目录,确认 images 和 labels 数量一致,再按 8:1:1 或 7:2:1 划分。我一般会写个脚本先做一致性检查,而不是直接开训。
2.2 用 Python 做一次标注体检:越界、空标签、类别越界
拿到数据集第一件事不是训练,是体检。下面这段脚本检查四类高频问题:图片与标签是否配对、坐标是否越界、是否有空 txt、class_id 是否超出预期范围。
import os from pathlib import Path from PIL import Image IMG_DIR = Path("detroit_street/images/train") LBL_DIR = Path("detroit_street/labels/train") NUM_CLASSES = 6 # 6 分类,合法 id 应为 0~5 problems = {"missing_label": [], "empty_label": [], "bad_coord": [], "bad_class": []} for img_path in IMG_DIR.glob("*.jpg"): lbl_path = LBL_DIR / (img_path.stem + ".txt") if not lbl_path.exists(): problems["missing_label"].append(img_path.name) continue lines = lbl_path.read_text().strip().splitlines() if not lines: problems["empty_label"].append(lbl_path.name) continue for ln, line in enumerate(lines): parts = line.split() if len(parts) != 5: problems["bad_coord"].append(f"{lbl_path.name}:{ln} 字段数={len(parts)}") continue cid = int(parts[0]) x, y, w, h = map(float, parts[1:]) if cid < 0 or cid >= NUM_CLASSES: problems["bad_class"].append(f"{lbl_path.name}:{ln} id={cid}") # 归一化坐标必须落在 (0,1],且宽高不能为 0 if not (0 < w <= 1 and 0 < h <= 1 and 0 <= x <= 1 and 0 <= y <= 1): problems["bad_coord"].append(f"{lbl_path.name}:{ln} {x},{y},{w},{h}") for k, v in problems.items(): print(k, len(v), v[:5])逻辑说明:missing_label是图片没有对应标签,会被当负样本;empty_label是空 txt,YOLO 会跳过但容易和漏标混淆;bad_coord里最常见的是宽高写成像素值而不是归一化值,或者中心点越界;bad_class就是类别 id 越界,6 分类里出现 6、7 甚至 80 都是典型的「从别的数据集抄过来没改干净」。
参数说明:NUM_CLASSES必须和你data.yaml里的nc一致。如果你不确定类别数,先cat所有 txt 的第一列做sort | uniq -c,看实际出现的 id 集合,再决定nc。这一步做完,你才知道这份数据集到底能不能直接用。
2.3 data.yaml 怎么写,路径和类别名一个都不能错
data.yaml是 YOLO 训练的唯一入口配置,写错一个字段就是几小时白跑:
path: /home/user/detroit_street # 数据集根目录,绝对路径最稳 train: images/train val: images/val test: images/test nc: 6 names: 0: pedestrian 1: vehicle 2: traffic_light 3: traffic_sign 4: bicycle 5: motorcyclepath用绝对路径能避免「在 A 目录能跑、换到 B 目录就找不到图」的玄学问题。names的顺序必须和 txt 里的 class_id 严格对应,顺序错了模型照样训,但评估时所有类别指标会张冠李戴。如果你拿到的数据集没有给类别名,只有 0~5 的数字,那就按你业务里最合理的语义去命名,并在文档里固定下来,别中途改。
3. 从零跑通 YOLOv8 训练:命令行、参数与第一次收敛判断
3.1 环境准备与最小训练命令
假设你已经装好 ultralytics,最简训练命令如下:
pip install ultralytics yolo detect train \ data=/home/user/detroit_street/data.yaml \ model=yolov8n.pt \ epochs=100 \ imgsz=640 \ batch=16 \ device=0 \ project=runs/detroit \ name=exp1逻辑说明:model=yolov8n.pt是从官方预训练权重起步,小模型先跑通再换 s/m/l;imgsz=640是街景检测的常用输入尺寸,显存不够就降到 512 或 416;batch=16在 8G 显存上跑 640 一般够用,OOM 就减半;device=0指定第一块 GPU,CPU 训练会慢到怀疑人生。project和name决定权重和日志落在哪,建议每次实验换name,别覆盖。
第一次跑,重点看三件事:box_loss是否在前 10 个 epoch 明显下降、mAP50是否在 30 epoch 后开始爬、cls_loss是否稳定。如果box_loss一直横盘,八成是标签坐标有问题,回到 2.2 的体检脚本。
3.2 关键参数怎么调:imgsz、batch、学习率与数据增强
街景数据集的调参有几个经验值:
| 参数 | 推荐值 | 说明 |
|---|---|---|
| imgsz | 640 | 小目标多可上 768,显存吃紧降到 512 |
| batch | 16 | 与显存强相关,8~32 之间试 |
| lr0 | 0.01 | 默认即可,微调预训练模型可降到 0.001 |
| epochs | 100~300 | 小数据集 100 起步,看 mAP 曲线决定是否加 |
| mosaic | 1.0 | 默认开启,小目标友好,最后 10 epoch 可关 |
| hsv_h/v/s | 0.015/0.7/0.4 | 街景光照变化大,颜色增强别关 |
学习率是最容易翻车的地方:lr0太大,loss 会震荡甚至 NaN;太小,100 epoch 都看不到收敛。我一般先用默认lr0=0.01跑 20 epoch 看趋势,再决定是否用cos_lr余弦退火。数据增强里mosaic对小目标和遮挡场景帮助明显,但如果你发现验证集 mAP 一直低于训练集很多,可以在最后阶段关掉 mosaic 让模型适应真实分布。
3.3 训练过程怎么读:loss 曲线、mAP 与混淆矩阵
训练日志里最该盯的是metrics/mAP50-95和metrics/mAP50。mAP50 到 0.6 以上说明基本可用,0.8 以上算不错。如果 mAP50 高但 mAP50-95 低,说明框的位置不够准,通常是标注框偏大或偏小。
混淆矩阵(confusion_matrix.png)能告诉你类别之间是否互相误判。街景里traffic_light和traffic_sign容易混,bicycle和motorcycle也容易混。如果某一类 recall 特别低,先去看这一类是不是样本太少,或者标注里把远距离小目标漏标了。YOLO 的混淆矩阵有时会出现「总合不唯一」的显示问题,那是归一化方式导致的,看绝对数值趋势即可,别被数字吓到。
4. 避坑与排查:6 分类街景数据集最容易踩的 5 个坑
4.1 现象:训练 loss 正常但 mAP 始终为 0
原因:data.yaml里names的 key 和 txt 里的 class_id 对不上,或者nc写成了别的数字。YOLO 不会报错,只会把所有预测都算错类。
解决:用 2.2 的脚本打印实际出现的 class_id 集合,和data.yaml逐一对齐。改完重新训练,别在旧权重上继续。
4.2 现象:图片和标签数量对不上,训练时警告「No labels found」
原因:images/train和labels/train文件名不一致,常见于图片是.jpeg而标签是.txt但 stem 带了后缀,或者划分时只复制了图片没复制标签。
解决:写一行comm对比两个目录的 stem 列表,把差集找出来。缺失标签的图片要么补标,要么移到单独的background目录当负样本,别直接留在训练集里。
4.3 现象:坐标越界导致框画到图外,训练不稳定
原因:标注工具导出时用了像素坐标没归一化,或者归一化时除以了错误的宽高。YOLO 对越界坐标不会自动裁剪,会直接参与 loss 计算。
解决:体检脚本里加0 <= x <= 1判断,越界的行直接打印出来人工修。批量修复可以用x = min(max(x, 0), 1)裁剪,但裁剪会改变框的语义,最好回标注工具重标。
4.4 现象:显存 OOM,batch 降到 4 还是崩
原因:imgsz太大,或者workers开太多导致内存爆。街景图分辨率高时,640 的输入在 8G 卡上 batch=16 可能就顶不住。
解决:先降imgsz到 512,再降batch到 8,workers设 4。如果还崩,检查是不是cache=True把整个数据集缓存进内存了,小内存机器关掉。
4.5 现象:验证集 mAP 远低于训练集,怀疑过拟合
原因:数据集太小、类别不均衡,或者验证集和训练集分布差异大(比如训练集全是白天,验证集全是夜晚)。
解决:先看每类样本数,少的类做 oversample 或加增强;再检查划分是否随机,别按文件名顺序切。如果确实是场景差异,考虑用close_mosaic在最后阶段关掉强增强,或者补一批验证集同分布的图。
5. 把 6 分类模型推到可用:评估、导出与一个提点技巧
训练完不是终点,能不能用要看评估和导出。先用yolo detect val在测试集上跑一遍:
yolo detect val \ model=runs/detroit/exp1/weights/best.pt \ data=/home/user/detroit_street/data.yaml \ split=test \ imgsz=640重点看每类的P、R、mAP50。如果某一类 recall 低于 0.5,说明漏检严重,优先补这类样本。街景里traffic_sign和pedestrian通常是小目标,漏检多半是分辨率不够,可以试试imgsz=768再训一版对比。
导出部署格式:
yolo export model=best.pt format=onnx opset=12 simplify=True yolo export model=best.pt format=engine half=True # TensorRT,需 GPUONNX 适合跨平台推理,TensorRT 在 NVIDIA 卡上延迟最低。导出后一定用几张测试图跑一遍,确认预处理(letterbox)和后处理(NMS)和训练时一致,否则精度会掉。
一个提点技巧:如果 6 类里有一两类样本特别少,别急着上复杂方法,先把这类图复制一份做针对性增强(亮度、裁剪、缩放),再配合copy_paste或mixup,往往比调网络结构见效快。我自己做街景项目时,traffic_light一开始 recall 只有 0.4,补了 200 张夜间和远距离样本后直接到 0.72,比换模型省事得多。
最后说个习惯:每次实验的data.yaml、训练命令、权重路径都记在一个experiments.md里,别信自己的记忆。我翻过一次车,三天后想复现最好那版结果,发现忘了当时用的是哪个imgsz,只能重跑。希望帮到你。
本文还有配套的精品资源,点击获取