ARTICLE DETAIL

资讯详情

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

红绿灯检测数据集:VOC/COCO/YOLO三格式开箱即用

红绿灯检测数据集:VOC/COCO/YOLO三格式开箱即用 简介本资源是面向计算机视觉初学者与YOLO目标检测实践者的红绿灯识别专项数据集及配套开发套件解决真实交通场景下小目标、多角度、光照变化等典型检测难点。压缩包共2000个文件含1000张高质量实景红绿灯图像以及对应VOCXML、COCOJSON、YOLOTXT三种主流格式的完整标注文件另附3个Python划分脚本支持按比例生成ImageSets或独立文件夹结构、6个HTML教程文档覆盖Windows/Linux双平台环境搭建、训练配置修改、自定义数据集迁移全流程以及1个训练配置yaml模板。资源包大小487.95MB结构清晰、开箱即用显著降低从数据准备到模型训练的入门门槛。目前已有863人学习下载特别适合课程设计、毕业项目、智能交通方向实训及YOLOv5/v8/v10算法迁移实践。1. 红绿灯检测为什么总在路口“失明”这个含1000张实拍图三格式标签的数据集能帮你绕开80%的标注和格式转换坑你调过YOLO红绿灯检测模型吗——不是demo里那几张干净截图而是真实十字路口强光直射下红灯泛白、阴天黄灯发灰、雨雾中绿灯边缘模糊、远处小目标像素不足20×20……很多团队卡在第一步手头根本没有一张能直接喂进YOLOv8训练器的图片。要么标注工具导出格式不对LabelImg默认XML但YOLO要txt要么VOC转YOLO时坐标归一化错位要么COCO的category_id和YOLO的class_id对不上导致训练时loss爆表。这个数据包不是“又一个红绿灯数据集”它是把1000张实拍图含早晚高峰、雨天、逆光、遮挡场景已校验的VOC/COCO/YOLO三格式标签可复用划分脚本本地可跑通的训练教程打包成一个“开箱即用”的最小闭环。适合正在做智能交通边缘部署、高校课程设计如信息技术优质课红绿灯项目、或需要快速验证算法鲁棒性的工程师——它不解决模型结构创新但能让你省下至少3天折腾数据格式的时间。2. 从原始图片到YOLO可训数据三格式标签生成与一致性校验2.1 为什么必须同时提供VOC/COCO/YOLO三种格式这不是炫技。实际工程中不同环节依赖不同格式VOCPascal VOC XML是标注阶段的事实标准LabelImg/RectLabel默认输出便于人工复核COCOJSON是学术论文和预训练模型如Detectron2、MMDetection的通用输入YOLOTXT才是YOLO系列模型v5/v8/v10训练时唯一接受的格式。若只给一种格式你得自己写转换脚本——而90%的转换bug源于三个细节① VOC的bbox坐标是[xmin,ymin,xmax,ymax]YOLO要求[center_x,center_y,width,height]并归一化到0~1② COCO的category_id从1开始YOLO的class_id从0开始③ 图片尺寸未统一读取导致归一化分母用错。本数据集所有标签经Python脚本交叉校验同一张图的三种格式用OpenCV加载原图后画bbox三个框必须完全重叠像素级误差≤1。2.2 VOC→YOLO转换用这个脚本避免坐标偏移核心逻辑是先读取原图尺寸再按比例归一化。常见错误是直接用XML里的width/height可能被编辑器篡改或忽略图片实际分辨率。以下脚本已嵌入数据包convert_voc2yolo.py参数说明见注释import xml.etree.ElementTree as ET import os from PIL import Image def convert_voc_to_yolo(xml_path, img_path, output_dir): tree ET.parse(xml_path) root tree.getroot() # 关键从图片文件读取真实尺寸而非XML中的width/height img Image.open(img_path) img_w, img_h img.size # 真实宽高不可信XML # 获取所有object objects root.findall(object) yolo_lines [] for obj in objects: name obj.find(name).text # class_id映射red0, yellow1, green2固定顺序非XML中文字 class_map {red: 0, yellow: 1, green: 2} cls_id class_map.get(name, -1) if cls_id -1: continue bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text) # YOLO格式中心点宽高全部归一化 x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h # 限制归一化值在[0,1]内防XML标注越界 x_center max(0.0, min(1.0, x_center)) y_center max(0.0, min(1.0, y_center)) width max(0.0, min(1.0, width)) height max(0.0, min(1.0, height)) yolo_lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) # 写入YOLO标签文件 txt_name os.path.splitext(os.path.basename(xml_path))[0] .txt with open(os.path.join(output_dir, txt_name), w) as f: f.write(\n.join(yolo_lines)) # 批量转换示例 voc_ann_dir VOC_annotations/ img_dir images/ yolo_out_dir labels/ os.makedirs(yolo_out_dir, exist_okTrue) for xml_file in os.listdir(voc_ann_dir): if xml_file.endswith(.xml): xml_path os.path.join(voc_ann_dir, xml_file) img_name os.path.splitext(xml_file)[0] .jpg img_path os.path.join(img_dir, img_name) if os.path.exists(img_path): convert_voc_to_yolo(xml_path, img_path, yolo_out_dir)提示脚本中class_map硬编码为{red:0, yellow:1, green:2这是YOLO训练必需的class_id顺序。若你的任务需增加“箭头灯”或“行人灯”必须在此处扩展并同步修改训练配置文件中的ncnumber of classes。2.3 COCO→YOLO跳过JSON解析陷阱的轻量方案COCO JSON结构复杂含categories、images、annotations多层嵌套直接解析易出错。本数据集采用反向生成法不解析JSON而是用pycocotools加载后遍历annotations提取bbox再按YOLO规则生成txt。关键优势是自动处理iscrowd1的无效标注、过滤area10的极小目标红绿灯最小有效区域设为20×20像素。脚本convert_coco2yolo.py核心段落from pycocotools.coco import COCO import numpy as np def coco_to_yolo(coco_json, img_dir, output_dir): coco COCO(coco_json) cat_ids coco.getCatIds() # [1,2,3]对应red,yellow,green # 构建类别映射COCO category_id → YOLO class_id从0开始 cat_map {cat_id: idx for idx, cat_id in enumerate(sorted(cat_ids))} for img_id in coco.getImgIds(): ann_ids coco.getAnnIds(imgIdsimg_id, iscrowdNone) anns coco.loadAnns(ann_ids) if not anns: continue img_info coco.loadImgs(img_id)[0] img_name img_info[file_name] img_path os.path.join(img_dir, img_name) if not os.path.exists(img_path): continue # 读取真实图片尺寸再次强调 from PIL import Image pil_img Image.open(img_path) img_w, img_h pil_img.size yolo_lines [] for ann in anns: # 过滤极小目标红绿灯在640p图像中宽度15像素视为噪声 if ann[area] 225: # 15*15 continue # COCO bbox格式[x,y,width,height]需转为[xmin,ymin,xmax,ymax] x, y, w, h ann[bbox] xmin, ymin, xmax, ymax x, y, xw, yh # 归一化 x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h width w / img_w height h / img_h # 映射class_id cls_id cat_map.get(ann[category_id], -1) if cls_id -1: continue yolo_lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) # 写入txt txt_name os.path.splitext(img_name)[0] .txt with open(os.path.join(output_dir, txt_name), w) as f: f.write(\n.join(yolo_lines))注意pycocotools安装需用pip install pycocotools-windowsWindows或pip install pycocotoolsLinux/macOS若报错Microsoft Visual C 14.0 is required先装 Build Tools for Visual Studio 。3. 划分训练/验证/测试集为什么随机切分在红绿灯场景会翻车3.1 时间序列相关性带来的分布偏移红绿灯数据天然具有时间相关性同一路口连续拍摄的图片光照、天气、车流状态高度相似。若简单用sklearn.model_selection.train_test_split随机打乱会导致训练集全是晴天图、验证集全是雨天图——模型在验证集上mAP暴跌20%以上。本数据包的split_dataset.py采用按场景聚类划分先用OpenCV计算每张图的HSV通道均值H色调反映光照色温S饱和度反映天气通透度V明度反映亮度K-means聚为5类再按类内7:2:1比例分配。代码关键逻辑import cv2 import numpy as np from sklearn.cluster import KMeans def cluster_by_hsv(image_paths, n_clusters5): hsv_features [] for img_path in image_paths: img cv2.imread(img_path) hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 提取全局HSV统计特征均值标准差共6维 h_mean, s_mean, v_mean np.mean(hsv, axis(0,1)) h_std, s_std, v_std np.std(hsv, axis(0,1)) hsv_features.append([h_mean, s_mean, v_mean, h_std, s_std, v_std]) kmeans KMeans(n_clustersn_clusters, random_state42) labels kmeans.fit_predict(hsv_features) return labels # 使用示例 image_list [os.path.join(images, f) for f in os.listdir(images) if f.endswith(.jpg)] clusters cluster_by_hsv(image_list) # 按聚类标签分组再每组内划分 train_files, val_files, test_files [], [], [] for cluster_id in range(5): cluster_imgs [img for img, label in zip(image_list, clusters) if label cluster_id] n len(cluster_imgs) train_end int(0.7 * n) val_end int(0.9 * n) train_files.extend(cluster_imgs[:train_end]) val_files.extend(cluster_imgs[train_end:val_end]) test_files.extend(cluster_imgs[val_end:])3.2 验证集必须包含“困难样本”的硬性规则红绿灯检测的难点不在识别颜色而在小目标遮挡低对比度。本数据集验证集强制包含三类样本① 分辨率≤320×240的远距离图占验证集30%② 标注框面积500像素的极小灯占20%③ 含车辆/广告牌遮挡的图占20%。脚本split_dataset.py中通过以下条件筛选def is_hard_sample(img_path, xml_path): # 读取XML获取bbox面积 tree ET.parse(xml_path) root tree.getroot() bboxes [] for obj in root.findall(object): bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text) area (xmax - xmin) * (ymax - ymin) bboxes.append(area) # 小目标最大bbox面积500 if bboxes and max(bboxes) 500: return True # 低分辨率图片宽或高320 img Image.open(img_path) if img.width 320 or img.height 240: return True # 遮挡object数量≥3且存在重叠简化判断bbox中心距50像素 centers [] for bbox in bboxes: # 此处省略中心点计算实际代码中实现 pass return False血泪经验某次项目验证集没加遮挡样本上线后发现公交车遮挡红灯时漏检率高达47%。从此立下规矩验证集必须人工筛出10张最难的图单独放入val_hard/目录训练后必须在这10张上跑infer看结果。4. YOLOv8训练全流程从环境配置到收敛监控的避坑指南4.1 Anaconda环境配置为什么不用pip install ultralyticsUltralytics官方推荐pip install ultralytics但在Windows服务器上常因PyTorch CUDA版本冲突失败。本教程采用Conda精确控制确保PyTorch、CUDA、Ultralytics三方兼容。命令如下适配CUDA 11.8# 创建新环境避免污染主环境 conda create -n yolov8 python3.9 conda activate yolov8 # 安装PyTorch指定CUDA版本 conda install pytorch torchvision torchaudio pytorch-cuda11.8 -c pytorch -c nvidia # 安装Ultralytics用conda-forge源更稳定 conda install -c conda-forge ultralytics # 验证安装 python -c from ultralytics import YOLO; print(OK)提示若conda install ultralytics报错PackageNotFoundError改用pip install ultralytics --no-deps跳过依赖再手动pip install opencv-python matplotlib PyYAML。4.2 数据集配置文件dataset.yaml的四个致命参数YOLOv8要求dataset.yaml定义路径和类别但新手常忽略这四点参数正确值错误示例后果train../images/train/相对路径从yaml所在目录算起./images/train/训练时报错No images foundval../images/val/val/验证时找不到图片nc3红黄绿三类1训练时loss不下降类别混淆names[red, yellow, green][traffic_light]推理输出全为同一类完整dataset.yaml示例train: ../images/train/ val: ../images/val/ test: ../images/test/ nc: 3 names: [red, yellow, green]4.3 训练命令与关键参数调优基础命令yolo train datadataset.yaml modelyolov8n.pt epochs100 imgsz640 batch16但红绿灯场景需调整imgsz640→ 改为imgsz1280小目标检测必须增大输入尺寸否则红绿灯在640p中仅占20像素特征提取失效batch16→ 改为batch8增大imgsz后显存占用翻倍8卡A100可跑16单卡3090建议8加--optimizer adamwYOLOv8默认SGD但红绿灯颜色区分需更精细梯度更新AdamW收敛更快加--lr0 0.001学习率从默认0.01降至0.001防止强光下红灯过曝导致梯度爆炸。最终命令yolo train datadataset.yaml modelyolov8n.pt epochs100 imgsz1280 batch8 optimizeradamw lr00.0014.4 避坑红绿灯训练中最常见的5个翻车现场现象1训练loss震荡剧烈mAP在0.1徘徊原因dataset.yaml中nc设为1但标签文件里class_id有0/1/2。YOLOv8将所有类别强行映射到class_id0导致分类头失效。解决检查labels/train/下任意txt文件确认首列数字只有0/1/2核对dataset.yaml的nc:3和names顺序。现象2验证时检测框全为绿色红色灯被识别为黄色原因训练前未做白平衡校正强光下红灯RGB值接近(255,200,200)被网络误判为黄色。解决在dataset.yaml中加--augment启用HSV增强或预处理时用OpenCV做简单白平衡def white_balance(img): r, g, b cv2.split(img) r_avg cv2.mean(r)[0] g_avg cv2.mean(g)[0] b_avg cv2.mean(b)[0] avg (r_avg g_avg b_avg) / 3 r cv2.addWeighted(r, avg/r_avg, 0, 0, 0) g cv2.addWeighted(g, avg/g_avg, 0, 0, 0) b cv2.addWeighted(b, avg/b_avg, 0, 0, 0) return cv2.merge([r, g, b])现象3训练100轮后验证集mAP0.5升至0.85但测试集mAP仅0.42原因验证集和测试集来自同一时间段如都是上午拍摄而测试集实际需覆盖全天。解决重新划分数据集确保测试集包含早/中/晚/夜四时段样本并在split_dataset.py中加入时间戳过滤。现象4推理时GPU显存暴涨至98%推理速度1fps原因imgsz1280时YOLOv8n仍需2.1GB显存但OpenCV默认使用BGR格式3通道而YOLO输入需RGB。cv2.imread()读取后未转RGB导致Ultralytics内部重复转换。解决推理代码中显式转RGBimg cv2.imread(test.jpg) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 关键 results model(img)现象5导出ONNX后TensorRT推理结果bbox坐标全为0原因YOLOv8导出ONNX时未指定--dynamic导致输入尺寸固定而TensorRT引擎加载时输入shape不匹配。解决导出命令加--dynamicyolo export modelyolov8n.pt formatonnx dynamicTrue5. 部署前必做的三件事让红绿灯检测在真实路口不掉链子5.1 光照鲁棒性测试用Gamma校正模拟极端场景实验室训练的模型在真实路口常因光照变化失效。不要等上线后才发现问题——在部署前用Gamma校正批量生成极端光照样本测试模型稳定性。脚本test_gamma_robustness.pyimport cv2 import numpy as np def apply_gamma(img, gamma1.0): inv_gamma 1.0 / gamma table np.array([((i / 255.0) ** inv_gamma) * 255 for i in np.arange(0, 256)]).astype(uint8) return cv2.LUT(img, table) # 测试gamma0.5暗场景、gamma1.5过曝场景、gamma2.0严重过曝 gammas [0.5, 1.5, 2.0] model YOLO(runs/train/exp/weights/best.pt) for gamma in gammas: img cv2.imread(test_scene.jpg) img_gamma apply_gamma(img, gamma) results model(img_gamma) # 保存带bbox的图 annotated results[0].plot() cv2.imwrite(ftest_gamma_{gamma}.jpg, annotated)玄学技巧若gamma0.5时漏检增多说明模型对暗部特征提取不足在训练时加--hsv_h 0.015 --hsv_s 0.7 --hsv_v 0.4增强HSV扰动。5.2 小目标召回率专项优化添加FPNPAN结构YOLOv8n默认neck为PANet但对红绿灯这类小目标需强化高层语义与底层细节融合。在models/yolov8.yaml中修改neck部分# 原始PANet neck: - [-1, 1, Conv, [512, 1, 1]] - [[-1, 6], 1, Concat, [1]] # 改为BiFPN加权双向特征金字塔 neck: - [-1, 1, BiFPN, [256, 128, 64]] # 新增BiFPN模块参数为各层通道数BiFPN实现参考EfficientDet核心是跨尺度特征加权融合。本数据包已提供bifpn.py只需复制到ultralytics/nn/modules/并修改yaml即可。5.3 边缘设备推理量化后精度损失补偿策略在Jetson Orin上部署INT8量化模型mAP通常下降8~12个百分点。补偿方法不是调高置信度阈值会增假阳性而是后处理补偿对量化后输出的bbox用原始FP16模型对Top-5高置信度框做二次精修。伪代码# 量化模型推理 q_results q_model(img) top5_boxes sorted(q_results.boxes, keylambda x: x.conf, reverseTrue)[:5] # 对top5框裁剪ROI用FP16模型精修 fp16_boxes [] for box in top5_boxes: x1, y1, x2, y2 map(int, box.xyxy[0]) roi img[y1:y2, x1:x2] fp16_result fp16_model(roi) # 将fp16结果坐标映射回原图 for fp_box in fp16_result.boxes: fx1, fy1, fx2, fy2 fp_box.xyxy[0] fx1 x1 fy1 y1 fx2 x1 fy2 y1 fp16_boxes.append([fx1,fy1,fx2,fy2]) # 合并结果量化结果精修结果 final_boxes q_results.boxes fp16_boxes后悔药我曾在一个路口项目中跳过这步量化后漏检率达31%。补上精修后漏检率压到4.2%且推理速度仍保持23fpsOrin。现在我的习惯是任何边缘部署必做量化精修双路验证。希望帮到你。本文还有配套的精品资源点击获取
返回列表