ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

YOLO红绿灯检测数据集:5000张图与三格式标签实战指南

YOLO红绿灯检测数据集:5000张图与三格式标签实战指南 简介本资源为面向目标检测学习者的YOLO红绿灯检测数据集适用于智能交通、自动驾驶感知等场景的模型训练与课程实践可帮助读者快速获得高质量标注数据省去自行采集与标注的成本。压缩包共约2000个文件以1986个xml标注文件为主另含少量html说明文档、txt列表与py脚本整体约946.4MB涵盖voc、coco和yolo三种格式标签分别存放于不同文件夹可直接接入YOLO系列模型训练。资源同时附赠环境搭建与训练案例教程覆盖Windows与Linux版本并提供训练集、验证集、测试集划分脚本可按需生成ImageSets下的txt划分文件方便复现实验流程。目前已有757人学习下载适合具备一定深度学习基础、希望快速上手红绿灯检测任务的读者参考使用。1. 红绿灯检测数据集怎么选5000 张图 三格式标签到底省了哪些事做交通场景目标检测的同行大概率都经历过这个阶段模型结构调了半天mAP 死活上不去最后发现是数据集的坑。红绿灯检测尤其典型——目标小、遮挡多、逆光过曝、夜间偏色随便一个因素就能让训练曲线变成玄学。这份 YOLO 红绿灯目标检测数据集核心价值不在于 5000 张图片这个数字本身而在于它把 VOC、COCO、YOLO 三种标签格式和划分脚本一起打包了。这意味着你拿到手之后不需要再花两三天写格式转换脚本、检查标注对齐、手动切分训练验证集直接进入模型训练环节。适合刚入门 YOLO 目标检测、想跑通完整流程的开发者也适合需要快速验证改进算法效果、不想在数据准备上耗时间的老手。下面从数据组织、格式转换、训练配置到踩坑排查把这份资源拆开讲清楚。2. 数据集结构与三种标签格式的对应关系2.1 5000 张图片的目录组织与划分逻辑拿到压缩包解压后常见的目录结构是这样的dataset/ ├── images/ │ ├── 000001.jpg │ ├── 000002.jpg │ └── ... ├── labels_voc/ │ ├── 000001.xml │ └── ... ├── labels_coco/ │ └── annotations.json ├── labels_yolo/ │ ├── 000001.txt │ └── ... └── split.py图片统一放在images/下三种标签格式各自独立目录。VOC 格式是每张图对应一个 XML 文件COCO 格式是一个大的 JSON 文件YOLO 格式是每张图对应一个 TXT 文件。划分脚本split.py负责按比例生成train.txt、val.txt、test.txt三个索引文件。这里有个容易忽略的点图片文件名和标签文件名必须严格一一对应。VOC 和 YOLO 格式下000001.jpg对应000001.xml或000001.txt差一个字符就会在训练时被跳过而且 YOLO 默认不报错只是静默丢弃。我一般会在训练前跑一遍文件名匹配检查确认没有孤儿图片或孤儿标签。提示解压后先别急着改目录结构划分脚本里的路径是按默认结构写死的改了路径就要同步改脚本里的img_dir和label_dir变量。2.2 VOC、COCO、YOLO 三种格式的字段差异三种格式的本质区别在于坐标表示方式和文件组织粒度。VOC 用绝对像素坐标COCO 也用绝对像素坐标但统一存一个 JSONYOLO 用归一化后的中心点坐标加宽高。具体对比如下维度VOC (XML)COCO (JSON)YOLO (TXT)坐标格式xmin, ymin, xmax, ymaxx, y, width, heightcx, cy, w, h归一化坐标单位像素绝对值像素绝对值0~1 相对值文件粒度每图一个 XML全部图片一个 JSON每图一个 TXT类别字段name标签categories数组行首数字索引是否含图像尺寸含 width/height含 image width/height不含需从图片读取YOLO 格式最精简但代价是丢失了图像尺寸信息。如果你后续要把 YOLO 标签转回 VOC 做可视化验证必须从图片文件重新读取宽高否则坐标会全错。常见做法是用 OpenCV 或 PIL 读图获取尺寸再乘以归一化坐标还原。COCO 格式的 JSON 结构相对复杂包含images、annotations、categories三个顶层字段。annotations里的image_id关联到images里的idcategory_id关联到categories里的id。很多格式转换脚本翻车就翻在这个关联关系上——image_id从 0 开始还是从 1 开始不同脚本实现不一样对不上就全乱。2.3 划分脚本的参数配置与执行划分脚本通常支持按比例切分核心参数是训练集、验证集、测试集的比例。常见做法是 7:2:1 或 8:1:1。执行方式python split.py \ --img_dir ./images \ --label_dir ./labels_yolo \ --train_ratio 0.7 \ --val_ratio 0.2 \ --test_ratio 0.1 \ --output_dir ./splits \ --seed 42参数说明--img_dir指向图片目录--label_dir指向 YOLO 格式标签目录划分脚本一般只处理 YOLO 格式因为训练时用的是这个--seed固定随机种子保证可复现。脚本执行后会生成train.txt、val.txt、test.txt每行是一个图片的绝对路径或相对路径。这里有个血泪经验划分脚本默认可能只按图片切分不检查对应标签是否存在。如果某张图没有标签文件切进训练集后 YOLO 会把它当负样本处理如果负样本比例过高模型会偏向预测背景。我一般会在划分后统计一下三个集合的标签文件数量确认和图片数量一致。import os def check_label_match(img_dir, label_dir, split_file): with open(split_file, r) as f: img_paths [line.strip() for line in f if line.strip()] missing [] for img_path in img_paths: base os.path.splitext(os.path.basename(img_path))[0] label_path os.path.join(label_dir, base .txt) if not os.path.exists(label_path): missing.append(base) print(f缺失标签的图片数量: {len(missing)}) if missing: print(前10个:, missing[:10]) return missing check_label_match(./images, ./labels_yolo, ./splits/train.txt)这段代码遍历划分文件里的每张图片检查对应 TXT 标签是否存在。输出缺失列表后可以选择补标、删除或移到单独目录。别小看这一步5000 张图里混进几十张无标签图训练时 loss 曲线会莫名其妙抖动。3. 从零跑通 YOLO 训练配置文件与关键参数3.1 数据配置文件 data.yaml 的写法YOLO 系列v5/v8/v11 等训练时需要一个 YAML 文件描述数据集路径和类别信息。典型写法path: /home/user/dataset train: splits/train.txt val: splits/val.txt test: splits/test.txt nc: 3 names: 0: red 1: green 2: yellowpath是数据集根目录train/val/test是相对于根目录的索引文件路径。nc是类别数names是类别名到索引的映射。红绿灯检测通常分三类红灯、绿灯、黄灯。如果数据集只标了红绿两类nc改成 2names同步删掉 yellow。容易翻车的地方names的顺序必须和标签文件里的类别索引一致。YOLO 标签每行第一个数字是类别索引如果训练时names写反了模型会把红灯学成绿灯。我一般会从标签文件里统计一下类别分布确认索引和名称的对应关系。import os from collections import Counter def count_classes(label_dir): counter Counter() for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue with open(os.path.join(label_dir, fname), r) as f: for line in f: parts line.strip().split() if parts: counter[int(parts[0])] 1 print(类别分布:, dict(counter)) return counter count_classes(./labels_yolo)输出类似{0: 3200, 1: 2800, 2: 900}说明索引 0 的类别样本最多索引 2 最少。如果黄灯样本只有 900 个训练时可以考虑过采样或调整 loss 权重否则黄灯检测效果会明显偏弱。3.2 训练命令与超参数设置以 YOLOv8 为例训练命令yolo detect train \ data./data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ device0 \ project./runs/traffic_light \ nameexp1参数逐个说modelyolov8n.pt用 nano 版本做基线速度快、显存占用低适合先跑通流程imgsz640是输入分辨率红绿灯目标偏小如果显存够可以提到 1280但训练时间会翻倍batch16根据显存调整8G 显存跑 640 分辨率一般能到 16跑 1280 可能只能到 4lr00.01是初始学习率YOLOv8 默认用 SGD 时这个值比较稳用 Adam 的话建议降到 0.001patience20是早停耐心值20 个 epoch 验证指标不提升就停。注意如果从 COCO 预训练权重开始微调lr0可以设小一点0.001~0.005避免把预训练特征打散。如果从头训练0.01 是常见起点。训练过程中重点看三个指标box_loss是否稳定下降、mAP50是否持续上升、precision和recall是否平衡。如果box_loss下降但mAP不涨大概率是过拟合需要加数据增强或减模型复杂度。如果mAP震荡剧烈检查学习率是否过大或 batch size 是否太小。3.3 用 COCO 预训练权重做迁移学习的配置差异如果不想从头训可以用 COCO 预训练权重做迁移学习。YOLOv8 的yolov8n.pt本身就是 COCO 预训练权重直接加载即可。但要注意类别数不匹配的问题COCO 有 80 类红绿灯只有 3 类加载时 YOLO 会自动替换检测头只保留 backbone 和 neck 的权重。如果想用更大的模型比如yolov8m.pt或yolov8l.pt显存占用会明显增加。以 640 分辨率、batch16 为例nano 版本大概占 4G 显存medium 版本占 8G 左右large 版本可能超过 12G。选模型的原则是先跑通 nano确认数据和流程没问题再逐步换大模型看收益。from ultralytics import YOLO model YOLO(yolov8n.pt) results model.train( data./data.yaml, epochs100, imgsz640, batch16, lr00.01, patience20, device0, pretrainedTrue, optimizerSGD, cos_lrTrue, close_mosaic10 )close_mosaic10表示最后 10 个 epoch 关闭 Mosaic 数据增强让模型在更接近真实分布的图像上微调通常能涨 1~2 个点 mAP。cos_lrTrue启用余弦学习率调度比阶梯下降更平滑。这些是 YOLOv8 训练红绿灯数据的常用配置不是必须但加上去大概率有收益。4. 避坑与排查红绿灯数据集训练中的五个高频问题4.1 训练 loss 不下降或直接变 NaN现象启动训练后box_loss一直是nan或者前几个 epoch 就爆掉。原因最常见的是标签坐标越界。YOLO 格式要求归一化坐标在 0~1 之间如果标注时框超出了图像边界转换后可能出现负值或大于 1 的值。另一个原因是学习率过大尤其是从头训练时。解决先跑一遍标签合法性检查把所有坐标 clamp 到 [0,1]。然后降低初始学习率到 0.001 再试。如果还不行检查图片是否有损坏文件用 PIL 逐张打开验证。from PIL import Image import os def validate_images(img_dir): bad [] for fname in os.listdir(img_dir): if not fname.lower().endswith((.jpg, .png, .jpeg)): continue try: img Image.open(os.path.join(img_dir, fname)) img.verify() except Exception as e: bad.append((fname, str(e))) print(f损坏图片数量: {len(bad)}) for item in bad[:10]: print(item) return bad validate_images(./images)4.2 mAP 虚高但实际检测效果差现象验证集mAP50跑到 0.9 以上但拿真实路测视频跑漏检和误检都很严重。原因训练集和验证集分布太接近甚至可能来自同一段视频的连续帧。连续帧之间差异极小模型相当于在“背答案”。另外如果验证集里红灯样本占绝大多数mAP会被红灯拉高绿灯和黄灯的实际表现被掩盖。解决划分数据集时按视频来源或时间段切分确保验证集和训练集来自不同场景。同时看每个类别的 AP不要只看总体 mAP。YOLO 训练日志里会输出每个类别的AP如果某一类明显偏低针对性地补样本。4.3 小目标漏检严重现象远处红绿灯或者画面中占比很小的灯模型基本检测不到。原因640 分辨率下小目标经过 backbone 多次下采样后特征图上的响应区域可能只有几个像素。YOLO 的 P3 检测头负责小目标但如果目标小于 8x8 像素P3 也很吃力。解决提高输入分辨率到 1280或者用带 P2 检测头的 YOLO 变体如 YOLOv8-p2。另一个办法是切片推理SAHI把大图切成小块分别检测再合并对小目标效果明显。如果显存不够优先保证分辨率batch 降到 4 或 2 也能跑。4.4 类别不平衡导致黄灯几乎检不到现象红灯绿灯检测正常黄灯几乎全部漏检。原因黄灯样本数量远少于红灯绿灯且黄灯持续时间短标注时容易漏标。损失函数被多数类主导少数类梯度被淹没。解决过采样黄灯样本或者在 loss 里给黄灯更高权重。YOLOv8 支持通过cls_pw参数调整类别权重但更直接的办法是在数据集层面做平衡。我一般会把黄灯样本复制 2~3 份加入训练集同时确保验证集里黄灯样本足够评估。4.5 格式转换后标注框整体偏移现象用转换脚本把 VOC 转 YOLO 后可视化发现框整体偏移或缩放不对。原因VOC 的xmin, ymin, xmax, ymax转 YOLO 的cx, cy, w, h时忘记除以图像宽高或者宽高读错了比如把 height 和 width 搞反。另一个常见错误是坐标原点理解不一致VOC 是左上角原点YOLO 也是左上角原点但有些脚本会误用中心点原点。解决转换后随机抽 20 张图做可视化把 YOLO 标签画回原图肉眼确认框是否对齐。这一步不能省我见过太多人转换完直接训练跑了半天发现框全是偏的。import cv2 def visualize_yolo_label(img_path, label_path, save_path): img cv2.imread(img_path) h, w img.shape[:2] with open(label_path, r) as f: for line in f: parts line.strip().split() if len(parts) 5: continue cls, cx, cy, bw, bh map(float, parts[:5]) x1 int((cx - bw / 2) * w) y1 int((cy - bh / 2) * h) x2 int((cx bw / 2) * w) y2 int((cy bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, str(int(cls)), (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.imwrite(save_path, img) visualize_yolo_label(./images/000001.jpg, ./labels_yolo/000001.txt, ./vis_000001.jpg)这段代码把 YOLO 归一化坐标还原成像素坐标并画框保存可视化结果。抽几张不同场景的图跑一遍确认框的位置和类别都对。5. 进阶技巧用验证集反推数据质量与模型边界训练跑通之后真正拉开差距的是对验证结果的细粒度分析。我习惯在训练结束后做三件事按类别看 AP、按目标尺寸看召回、按场景看误检。按类别看 AP 直接读 YOLO 输出的results.csv或val日志找到每个类别的AP50和AP50-95。如果红灯 AP 0.95、绿灯 AP 0.93、黄灯 AP 0.45那问题就很明确——黄灯数据不够或标注质量差。这时候补黄灯样本比调模型结构有效得多。按目标尺寸看召回需要自己写脚本把验证集里的标注框按面积分成小、中、大三档分别统计每档的召回率。红绿灯检测里小目标通常是远处路口的灯如果小目标召回明显低于中大型目标说明输入分辨率不够或者 P3 检测头容量不足。常见做法是把imgsz从 640 提到 1024 或 1280或者换用带 P2 的模型。按场景看误检更依赖人工从验证集里挑出误检样本按场景归类夜间过曝、逆光、雨雾、遮挡、多灯并列。如果误检集中在夜间检查训练集里夜间样本比例如果集中在多灯并列检查标注时是否把多个灯标成了一个框。这些分析做完下一轮迭代的方向就清楚了比盲目调参高效得多。还有一个容易被忽略的点验证集本身的质量。我遇到过验证集里标注框偏移的情况导致模型明明检对了却被判为误检mAP 被拉低。从那以后我每次拿到新数据集都强制走一遍可视化验证——随机抽 50 张验证集图片把标注框画出来逐张确认。这个习惯帮我省了至少两次“模型没问题但指标上不去”的排查时间。希望帮到你。本文还有配套的精品资源点击获取
返回列表