尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

550张实拍交通标志数据集:txt与xml双格式YOLO训练指南

550张实拍交通标志数据集:txt与xml双格式YOLO训练指南 简介这是一份面向深度学习与计算机视觉方向的实拍交通标志已标注数据集适合使用YOLO系列算法开展目标检测训练与验证的开发者、学生及算法工程师。数据集聚焦停止、提示、等待三类常见交通标志图像以真实道路场景实拍为主标注精度较高作者实测在100轮训练后检测精度可达98%可用于课程设计、毕业项目或算法对比实验。压缩包共1643个文件包含547张jpg原图、547个xml标注文件与548个txt标注文件并附带1个cache缓存文件txt与xml两种格式均已转换完毕可按需直接接入不同训练框架整体约705.56MB。目前已有1055人学习下载资源同时提供两种标注格式省去自行转换与整理的环节便于快速搭建训练流程、复现检测效果并验证模型精度。1. 550 张实拍交通标志数据集txt 与 xml 双版本到底怎么选手上有个红绿灯路口的小项目客户催着要 demo模型精度还得能看。这时候最缺的不是网络结构而是一份标注干净、格式对得上、拿来就能跑的数据。这份实拍交通标志数据集一共 550 张覆盖停止、提示、等待三类标志最省事的地方在于 txt 和 xml 两套标注都给你转好了YOLO 系直接吃 txt想用 VOC 那套流程就走 xml不用自己再写转换脚本。它适合两类人一类是刚接触目标检测、想跑通训练闭环的新手另一类是手上有现成框架、只缺一份小规模实拍数据做验证的从业者。550 张不算大但胜在是实拍场景光照、角度、遮挡都带一点比纯合成图更接近真实路况这也是它检测精度能上来的原因。2. 数据集结构与标注格式txt 和 xml 分别对应什么2.1 目录组织与文件命名拿到压缩包解压后常见的组织方式是图片放一个目录、标注放另一个目录或者图片和同名标注并排。从项目正文里那串文件名能看出来图片是03015.jpg、03430.jpg这种纯数字命名标注文件跟图片同名只是后缀不同——txt 版就是03015.txtxml 版就是03015.xml。这种同名对应关系是后面所有脚本能跑通的前提一旦名字对不上训练时就会报找不到标签。我一般拿到数据集先干一件事确认图片数量和标注数量是否一致。550 张图理论上应该有 550 个 txt 或 550 个 xml。数量对不上要么是漏标要么是转换时丢了文件这两种情况都会让训练结果莫名其妙地差。# 统计图片数量 ls images/*.jpg | wc -l # 统计 txt 标注数量 ls labels/*.txt | wc -l # 统计 xml 标注数量 ls annotations/*.xml | wc -l这三条命令跑完三个数字应该都是 550。如果 txt 和 xml 数量不一致说明其中一套转换有问题优先用数量对得上的那套。labels.cache这个文件是 YOLO 训练时自动生成的缓存里面存的是标签路径和形状信息第一次训练会自动重建不用手动管它但如果换了数据集路径最好把它删掉重新生成否则可能读到旧缓存。2.2 txt 格式YOLO 系的归一化坐标txt 版本是给 YOLO 系列用的每张图对应一个 txt每行代表一个目标格式是类别索引 中心x 中心y 宽度 高度这四个坐标值都是归一化到 0 到 1 之间的浮点数不是像素值。这一点是新手最容易翻车的地方——直接把像素坐标填进去训练时 loss 会大得离谱模型根本学不动。归一化的意思是中心 x 除以图片宽度中心 y 除以图片高度宽度除以图片宽度高度除以图片高度。# 读取一个 txt 标注验证坐标是否在 0-1 之间 with open(labels/03015.txt, r) as f: for line in f: cls, cx, cy, w, h line.strip().split() cx, cy, w, h map(float, (cx, cy, w, h)) # 正常情况四个值都应该在 0 到 1 之间 assert 0 cx 1 and 0 cy 1, f坐标越界: {line} assert 0 w 1 and 0 h 1, f宽高异常: {line} print(f类别 {cls}, 中心 ({cx:.3f}, {cy:.3f}), 尺寸 ({w:.3f}, {h:.3f}))这段脚本的作用是快速体检。如果断言失败说明这份 txt 不是标准 YOLO 格式可能是像素坐标没归一化或者坐标写成了左上角加右下角。类别索引从 0 开始停止、提示、等待三类分别对应 0、1、2具体哪个是哪个得看数据集附带的类别说明文件或者自己打开几张图对照标注确认别想当然。2.3 xml 格式VOC 风格的绝对坐标xml 版本走的是 Pascal VOC 那套每个 xml 文件描述一张图里面包含图片尺寸和若干目标框。关键字段是size里的width、height以及每个object里的name和bndbox。bndbox里的xmin、ymin、xmax、ymax是像素绝对坐标左上角和右下角。import xml.etree.ElementTree as ET tree ET.parse(annotations/03015.xml) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) print(f图片尺寸: {img_w}x{img_h}) for obj in root.findall(object): name obj.find(name).text box obj.find(bndbox) xmin int(box.find(xmin).text) ymin int(box.find(ymin).text) xmax int(box.find(xmax).text) ymax int(box.find(ymax).text) print(f类别 {name}, 框 ({xmin},{ymin})-({xmax},{ymax}))xml 的好处是可读性强用浏览器或文本编辑器直接打开就能看改起来也直观。缺点是文件体积比 txt 大不少550 张图的 xml 加起来可能比图片本身还占地方。如果你用的是 YOLOv5 或 YOLOv8训练时读的是 txtxml 只是留作备份或给其他框架用。两套都留着的好处是哪天想换框架不用回头重新标。3. 用这份数据跑 YOLO 训练从配置到出结果3.1 目录结构整理与 data.yaml 配置YOLO 训练对目录结构有约定常见做法是分成images/train、images/val、labels/train、labels/val四个目录。550 张按 8:2 切训练集 440 张验证集 110 张。切分脚本要保证图片和标注同步移动不能只挪图片不挪标签。import os, shutil, random random.seed(42) # 固定随机种子保证每次切分结果一致 img_dir images lbl_dir labels pairs [(f, f.replace(.jpg, .txt)) for f in os.listdir(img_dir) if f.endswith(.jpg)] random.shuffle(pairs) split int(len(pairs) * 0.8) for phase, subset in [(train, pairs[:split]), (val, pairs[split:])]: os.makedirs(fimages/{phase}, exist_okTrue) os.makedirs(flabels/{phase}, exist_okTrue) for img, lbl in subset: shutil.copy(os.path.join(img_dir, img), fimages/{phase}/{img}) shutil.copy(os.path.join(lbl_dir, lbl), flabels/{phase}/{lbl}) print(f{phase}: {len(subset)} 张)random.seed(42)这行别省不固定种子的话每次切分结果不同实验没法复现。切完之后检查一下images/train和labels/train里的文件名是否一一对应数量是否都是 440。然后是data.yaml这是 YOLO 训练的数据描述文件path: ./traffic_sign_data train: images/train val: images/val nc: 3 names: [stop, warning, wait]nc是类别数这里是 3。names的顺序必须和 txt 里的类别索引严格对应索引 0 对应names列表第一个元素索引 1 对应第二个以此类推。顺序搞反了模型会把停止标志认成等待精度再高也没用。path写数据集根目录train和val写相对路径。3.2 训练命令与关键参数YOLOv8 的训练命令很简洁yolo detect train \ datatraffic_sign_data/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/traffic \ nameexp1modelyolov8n.pt用的是 nano 版本550 张图这个量级nano 或 small 就够了上大模型容易过拟合。epochs100和项目里说的 100 轮对得上patience20表示 20 轮没提升就早停省时间。imgsz640是输入尺寸如果原图分辨率远大于 640训练时会自动缩放。batch16看显存8G 显存跑 nano 加 640 尺寸16 一般没问题爆显存就降到 8。训练过程中重点看两个指标mAP50和mAP50-95。前者是 IoU 阈值 0.5 时的平均精度后者是 0.5 到 0.95 多个阈值下的平均后者更严格。项目里说的 98% 精度大概率指的是mAP50。如果mAP50到 98 但mAP50-95只有六七十说明框的位置还不够准但对分类和粗略定位来说够用了。3.3 验证与推理确认模型真的能用训练完在runs/traffic/exp1/weights/下会有best.pt和last.ptbest.pt是验证集表现最好的那轮推理用它。yolo detect predict \ modelruns/traffic/exp1/weights/best.pt \ sourcetest_images/ \ conf0.25 \ saveTrueconf0.25是置信度阈值低于这个值的框不显示。交通标志场景建议先设 0.25 看效果如果漏检多就降到 0.1误检多就升到 0.4。推理结果会存到runs/detect/predict/下打开图看框的位置和类别对不对。验证集上的混淆矩阵也值得看在runs/traffic/exp1/下有个confusion_matrix.png。如果停止和等待两类互相混淆严重说明这两类在视觉上太像或者标注时边界没统一得回头检查标注。4. 避坑与排查标注和训练里最容易翻车的几件事4.1 现象训练 loss 一直不降mAP 接近 0原因通常是标注格式不对。最常见的是 txt 里坐标没归一化还是像素值或者类别索引从 1 开始而不是 0。YOLO 要求类别索引从 0 开始如果标注工具默认从 1 开始就会全部错位。解决跑一遍 2.2 节那个断言脚本确认坐标都在 0 到 1 之间。再看类别索引的最大值如果出现 3 而nc是 3说明索引越界了要么改标注要么把nc改成 4 但这样会多一个空类。正确做法是把索引统一减 1。4.2 现象训练报错「找不到标签文件」原因图片和标注文件名不一致或者目录结构不符合 YOLO 约定。YOLO 找标签的逻辑是把图片路径里的images替换成labels后缀换成.txt。如果图片叫03015.jpg标签必须叫03015.txt放在对应的labels/train下。解决用脚本批量检查对应关系。import os for phase in [train, val]: imgs {f.replace(.jpg, ) for f in os.listdir(fimages/{phase})} lbls {f.replace(.txt, ) for f in os.listdir(flabels/{phase})} missing imgs - lbls if missing: print(f{phase} 缺少标签: {missing}) else: print(f{phase} 对应正常)4.3 现象labels.cache导致换了数据集后结果异常原因YOLO 第一次训练会在标签目录下生成labels.cache缓存标签路径和形状。如果换了数据集但没删缓存训练时读的还是旧缓存里的路径轻则报错重则静默用错标签。解决每次换数据集或改了标签文件手动删掉所有labels.cache让它重新生成。这个文件是黑匣子出问题时第一反应就是删它。4.4 现象验证集精度很高但实际图片检测效果差原因550 张图切分时如果按顺序切而不是随机切可能出现训练集和验证集场景高度相似验证集精度虚高。另外如果实拍图里某些光照条件只在训练集出现验证集没有模型泛化就差。解决切分时固定随机种子并打乱确保两个集合场景分布均匀。实际部署前找几张完全没参与训练的图测一下这才是真实水平。项目里说的 98% 是在验证集上换到全新场景可能会掉几个点心里要有数。4.5 现象xml 转 txt 后框位置偏移原因xml 里bndbox是绝对坐标转 YOLO 格式时要先归一化。常见错误是用了错误的图片宽高比如 xml 里写的尺寸和实际图片尺寸不一致或者转换时把xmax和ymax当成了宽高而不是右下角坐标。解决转换时以实际图片的尺寸为准用 PIL 或 OpenCV 读图拿宽高不要信 xml 里的size字段有些标注工具写进去的尺寸是错的。转换公式是cx (xmin xmax) / 2 / img_ww (xmax - xmin) / img_wy 方向同理。5. 把 550 张用到极致小数据集的增强与迁移技巧550 张对深度学习来说不算多但交通标志这个任务本身类别少、目标特征明显用对方法完全能出可用模型。我一般会做两件事一是开 YOLO 自带的增强二是用预训练权重做迁移。YOLOv8 默认就开了 mosaic、HSV 抖动、随机翻转这些增强。mosaic 是把四张图拼成一张变相增加 batch 内的多样性对小数据集特别有用。但要注意交通标志里有些标志是有方向性的比如某些提示标志翻转后语义就变了所以flipud上下翻转建议关掉fliplr左右翻转看类别停止标志左右翻转还是停止问题不大但如果有文字类标志就得谨慎。# 在 data.yaml 同级加一个增强配置或在训练命令里覆盖 hsv_h: 0.015 # 色调抖动模拟不同光照 hsv_s: 0.7 # 饱和度抖动 hsv_v: 0.4 # 亮度抖动 degrees: 10 # 随机旋转角度交通标志一般不会大角度倾斜 translate: 0.1 # 平移 scale: 0.5 # 缩放 flipud: 0.0 # 关掉上下翻转 fliplr: 0.5 # 左右翻转保留 mosaic: 1.0 # 开启 mosaic迁移学习这块yolov8n.pt本身就是在 COCO 上预训练过的已经学到了边缘、纹理这些底层特征拿来微调比从零训练收敛快得多。100 轮能到 98%预训练权重功不可没。如果换成从零初始化同样 100 轮大概率到不了这个数。还有一个技巧是冻结 backbone 先训几轮。前 10 轮把 backbone 冻住只训检测头让检测头先适应新类别然后再解冻全量微调。这样能防止预训练权重被小数据集带偏。# 前 10 轮冻结 backbone yolo detect train datatraffic_sign_data/data.yaml modelyolov8n.pt \ epochs10 freeze10 lr00.001 namewarmup # 再解冻全量训练 yolo detect train datatraffic_sign_data/data.yaml \ modelruns/detect/warmup/weights/last.pt \ epochs90 lr00.01 namefinetune验证模型是否真的学到东西除了看 mAP我习惯抽几张验证集的图把预测框和真实框画在一起对比。如果预测框和真实框贴合度高类别也对那才是真稳。只看数字容易被虚高的验证集精度骗到。从那以后我每次拿到新数据集都强制先跑一遍数量核对和坐标断言再切分、再训练这三步不走完不开工。希望帮到你。本文还有配套的精品资源点击获取
返回列表