简介:这份资源面向从事目标检测算法学习与工程落地的开发者,提供雾天场景下的行人、车辆检测数据集,可直接用于YOLOv5训练,省去格式转换与标注整理环节。数据涵盖人、轿车、公交车、自行车、摩托车共5个类别,图像为400至1000分辨率的RGB图片,取自雾天马路上的常见车辆与人群,适合做恶劣天气下的检测鲁棒性研究与模型对比实验。资源包共约2000个文件,以1999个txt标注文件和1个Python可视化脚本为主,压缩包大小约123.5MB,其中训练集含4320张图片及对应标签,验证集含100张图片及对应标签,并附有类别说明文本。可视化脚本随机传入一张图片即可绘制边界框并保存到当前目录,无需修改即可运行,便于快速核验标注质量。目前已有405人学习下载,适合需要现成雾天数据做训练、验证与效果展示的读者。
1. 雾天行人车辆检测数据集:5 类目标、4420 张图,YOLOv5 目录直接开训
雾天场景的目标检测一直是落地里比较别扭的一类需求。正常天气下训好的模型,一遇到雾天马路、能见度下降、目标边缘发灰,召回率掉得很难看。这次拆的这份资源,就是冲着这个场景来的:雾天下的行人、车辆目标检测数据集,5 个类别——人、轿车、公交车、自行车、摩托车,图像分辨率在 400 到 1000 之间的 RGB 图片,全部按 YOLOv5 的目录格式组织好,训练集 4320 张图配 4320 个 txt 标签,验证集 100 张图配 100 个标签,总大小 130MB。它解决的不是"从零标注"的问题,而是让你跳过清洗、划分、格式转换这几步,直接把 datasets 目录丢进 YOLOv5 就能跑起来。适合做雾天感知、交通监控、自动驾驶感知预研,或者单纯想拿一份现成的多类别交通场景数据练手 YOLOv5 训练流程的人。
2. 目录结构与类别定义:先看清这份数据集长什么样
拿到一份数据集,我习惯先不急着训,先把目录结构和标签格式过一遍。这一步花十分钟,能省掉后面几个小时的报错排查。这份资源的价值很大程度上就体现在"结构已经规整"上,所以先把它讲透。
2.1 YOLOv5 标准目录长什么样
YOLOv5 对数据集的目录组织有比较固定的约定,核心是 images 和 labels 两个文件夹平行放置,且内部文件名一一对应。这份数据集按训练集、验证集拆开,结构大致是这样:
datasets/ ├── images/ │ ├── train/ # 4320 张雾天图片 │ └── val/ # 100 张雾天图片 ├── labels/ │ ├── train/ # 4320 个 txt 标签 │ └── val/ # 100 个 txt 标签 └── QC_Bing_515.txt # 类别名称文件这里有个容易忽略的点:YOLOv5 默认会去 images 路径里找图片,然后把路径里的/images/替换成/labels/再去找同名 txt。所以 images 和 labels 的层级必须严格对应,train 对 train、val 对 val,文件名(不含扩展名)也必须一致。这份数据集的 4320 对、100 对文件就是按这个规则配好的,省去了自己写脚本对齐的麻烦。
2.2 五个类别与标签文件格式
类别一共 5 个:人、轿车、公交车、自行车、摩托车。类别定义写在QC_Bing_515.txt这类文本文件里,一行一个类别名,行号(从 0 开始)就是类别 id。txt 标签文件里每一行的格式是 YOLO 标准:
<class_id> <x_center> <y_center> <width> <height>其中后四个值都是归一化到 0 到 1 之间的相对坐标,不是像素值。举个例子,一张 800×600 的图里有个轿车框在 (100, 200) 到 (300, 400),那么中心点是 (200, 300),宽 200、高 200,归一化后就是1 0.25 0.5 0.25 0.333(假设轿车 id 是 1)。这个格式是 YOLOv5 直接吃的,不需要再做 VOC 到 YOLO 的转换。
提示:如果你拿到的标签是 VOC 的 xml 或者 COCO 的 json,那才需要转换脚本;这份资源已经是 txt,跳过那一步。
2.3 用可视化脚本先验证一遍
数据集里带了一个show.py,作用是随机传入一张图片,把边界框画出来并保存到当前目录。这个脚本不用改就能跑,是我拿到任何 YOLO 数据集后的第一道验证工序——先确认标签和图片对得上,再谈训练。
import cv2 import random import os # 类别名,顺序必须和 QC_Bing_515.txt 一致 classes = ['person', 'car', 'bus', 'bicycle', 'motorcycle'] img_dir = 'datasets/images/train' label_dir = 'datasets/labels/train' # 随机抽一张图 img_name = random.choice(os.listdir(img_dir)) img_path = os.path.join(img_dir, img_name) label_path = os.path.join(label_dir, img_name.replace('.jpg', '.txt')) img = cv2.imread(img_path) h, w = img.shape[:2] with open(label_path, 'r') as f: for line in f.readlines(): cid, xc, yc, bw, bh = map(float, line.split()) # 反归一化回像素坐标 x1 = int((xc - bw / 2) * w) y1 = int((yc - bh / 2) * h) x2 = int((xc + bw / 2) * w) y2 = int((yc + bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, classes[int(cid)], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.imwrite('vis_result.jpg', img) print('saved vis_result.jpg')逻辑说明:脚本先随机抽一张训练图,再按同名规则找到对应 txt,逐行解析归一化坐标,反算回像素坐标后画框。参数上,classes列表的顺序必须和类别文件严格一致,否则框上的文字会张冠李戴;img_name.replace('.jpg', '.txt')这行假设图片是 jpg,如果你的图是 png,这里要跟着改。跑完看vis_result.jpg,框贴合目标、类别文字正确,说明这份数据是干净的,可以进入训练。
3. 接入 YOLOv5 训练:data.yaml 配置与首轮跑通
结构确认没问题,接下来就是把它接进 YOLOv5 的训练流程。这一步的核心是写对 data.yaml,然后确认路径、类别数、缓存策略这几个参数。很多人第一次训自己的数据集翻车,八成栽在 yaml 路径上。
3.1 写一份能直接用的 data.yaml
YOLOv5 通过一个 yaml 文件告诉训练脚本去哪里找数据、有几个类别、类别叫什么。针对这份数据集,配置如下:
# fog_person_vehicle.yaml path: ./datasets # 数据集根目录 train: images/train # 相对 path 的训练图路径 val: images/val # 相对 path 的验证图路径 nc: 5 # 类别数 names: ['person', 'car', 'bus', 'bicycle', 'motorcycle']参数说明:path是根目录,train和val是相对它的子路径,YOLOv5 会自动把images替换成labels去找标签。nc必须等于 names 的长度,写错了训练会在算 loss 时直接报维度不匹配。names 的顺序要和QC_Bing_515.txt完全一致,因为标签里的 class_id 是按这个顺序索引的。
注意:
path用相对路径时,是相对于你执行训练命令的工作目录,不是相对于 yaml 文件。我一般直接写绝对路径,省得来回 cd 出问题。
3.2 启动训练与关键参数
配置写好,训练命令本身不复杂,但几个参数值得说清楚:
python train.py \ --data fog_person_vehicle.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --cache逻辑说明:--weights yolov5s.pt表示从官方预训练权重开始微调,比从头训收敛快得多,雾天这种域偏移场景尤其推荐。--img 640是输入尺寸,这份数据原图 400 到 1000,统一缩到 640 是常规做法,显存吃紧可以降到 416。--batch 16按显存调,8G 显存跑 yolov5s 加 640 尺寸,16 一般稳。--cache把图片缓存到内存,4420 张 130MB 的数据集完全放得下,能明显加快每个 epoch 的读取速度。
跑起来后重点看几个输出:train/box_loss、val/box_loss是否稳定下降,metrics/mAP_0.5是否在涨。如果 box_loss 一开始就很大且不降,多半是标签坐标有问题;如果 mAP 一直上不去,先怀疑类别不平衡——这份数据里公交车、自行车、摩托车的样本量大概率远少于人和轿车,后面会讲怎么处理。
3.3 验证集只有 100 张,评估怎么看
验证集 100 张,说实话偏小,评估结果的波动会比较明显。我的做法是:不要只盯最后一个 epoch 的 mAP,而是看results.csv里 mAP 的整体趋势,取一个稳定区间而不是单点。另外可以自己从训练集里再切一小部分出来做二次验证,交叉确认模型没有过拟合到那 100 张上。
# 训练结束后用验证脚本单独跑一遍 python val.py \ --data fog_person_vehicle.yaml \ --weights runs/train/exp/weights/best.pt \ --img 640 \ --task val参数说明:--task val只做评估不保存预测图,速度快;想看具体预测效果就换成--task test并加--save-txt。best.pt是训练过程中验证指标最好的权重,通常比last.pt更适合部署。
4. 避坑与排查:雾天数据集训练最容易栽的五个地方
这一章是我自己踩过、也见过别人踩的坑,按"现象 → 原因 → 解决"整理。雾天数据本身有它的特殊性,很多在清晰数据集上不明显的毛病,在这里会被放大。
4.1 训练 loss 正常但 mAP 极低
现象:box_loss 一路下降看着很健康,但 mAP_0.5 始终在 0.1 以下。
原因:最常见的是类别顺序错位。标签里的 class_id 是按QC_Bing_515.txt的顺序编的,但你在 data.yaml 的 names 里换了顺序,模型学到的类别和评估时对不上。
解决:把 data.yaml 的 names 和类别文件逐行比对,确保第 0 行对应第 0 类。改完重新训,别在旧权重上接着训。
4.2 报错 "No labels found"
现象:训练启动时报找不到标签,或者警告大量图片没有对应 label。
原因:images 和 labels 的目录层级没对齐,或者文件名扩展名不一致(图是 .png,标签按 .jpg 去替换找)。
解决:检查 images/train 和 labels/train 是否同级对应,用脚本批量核对文件名(去掉扩展名后)是否一一匹配。这份资源是配好的,但如果你自己挪动过目录,很容易破坏这个对应关系。
4.3 显存溢出 OOM
现象:训练几个 batch 后报 CUDA out of memory。
原因:--img或--batch设太大,或者没开--cache却用了大 batch。
解决:先把 batch 降到 8 试,再不行把 img 降到 416。开了--cache的话,内存占用会上去,但显存主要受 batch 和 img 影响。8G 卡跑 yolov5s + 640 + batch 16 是安全线。
4.4 小目标漏检严重
现象:远处的小轿车、小摩托车基本检不出来。
原因:雾天本身对比度低,小目标特征更弱,加上统一缩到 640 后小目标像素更少。
解决:把--img提到 960 或 1280(显存允许的话),或者用 yolov5m/l 这种更大 backbone。另一个办法是在数据层面做 mosaic 增强,YOLOv5 默认就开,确认没被关掉。
4.5 类别不平衡导致稀有类几乎不召回
现象:人和轿车 mAP 还行,公交车、自行车、摩托车几乎检不出。
原因:这 5 类在雾天马路场景里分布天然不均,稀有类样本少,模型倾向于忽略它们。
解决:先统计每类框数量,确认不平衡程度;然后可以用--cls加权,或者对稀有类做复制过采样。更彻底的是在 loss 里给稀有类更高权重,但这要改代码,属于进阶操作。
5. 进阶技巧:从跑通到跑好,几个我固定会做的动作
数据集能训起来只是及格线,真正决定这份资源值不值得反复用的,是你能不能把它调到一个可用的精度。这一章讲几个我每次拿到新数据集都会走的动作,尤其是雾天这种域偏移明显的场景。
第一个动作是先做一次类别分布统计,别凭感觉猜。写个小脚本数一遍每类的框数量,心里有数才知道后面要不要做重采样。
import os from collections import Counter label_dir = 'datasets/labels/train' counter = Counter() for fname in os.listdir(label_dir): with open(os.path.join(label_dir, fname)) as f: for line in f: cid = int(line.split()[0]) counter[cid] += 1 names = ['person', 'car', 'bus', 'bicycle', 'motorcycle'] for cid, cnt in sorted(counter.items()): print(f'{names[cid]}: {cnt}')跑完你会看到类似 person 和 car 占大头、bus 和 bicycle 偏少的分布。这个结果直接决定你要不要对稀有类做增强。我一般如果某类占比低于 5%,就会考虑过采样或者调 loss 权重。
第二个动作是固定一套评估基线,别每次换参数就重新猜。我的习惯是:yolov5s + img 640 + batch 16 + 100 epoch 作为基线,记下 mAP_0.5 和每类 AP,之后任何改动都跟这个基线比。雾天数据上,基线 mAP 通常在 0.5 到 0.7 之间浮动,低于 0.4 基本说明配置或数据有问题。
第三个动作是拿真实雾天视频抽帧做一次推理验证。训练集的 mAP 再高,也不代表实际场景能用。我会用detect.py跑一段没参与训练的雾天素材,看框的稳定性和漏检情况:
python detect.py \ --weights runs/train/exp/weights/best.pt \ --source test_fog_video.mp4 \ --img 640 \ --conf 0.25 \ --save-txt参数上,--conf 0.25是置信度阈值,雾天场景我一般会调到 0.2 到 0.3 之间,太低误检多,太高漏检多,得按实际画面权衡。--save-txt把检测结果存下来,方便后续做统计或者接下游逻辑。
最后一个习惯是:每次训完都把 data.yaml、训练命令、关键超参和最终指标记在一个小本子上。雾天数据集这种域偏移场景,参数敏感度比常规数据高,今天调好的配置过两周就忘了细节,没有记录等于白调。从那以后我每次动数据集,都强制先跑一遍可视化脚本确认标签、再统计类别分布、最后才开训,这三步走完基本不会出大问题。希望这份雾天行人车辆数据集能帮你把雾天感知这条线快速跑起来。
本文还有配套的精品资源,点击获取