首页 / 资讯中心 / 文章详情

YOLOV5自动驾驶小车8类交通指示牌数据集与训练部署实践

YOLOV5自动驾驶小车8类交通指示牌数据集与训练部署实践 ★ FEATURED ARTICLE
简介面向智能小车赛道自动驾驶场景提供了一套已标注的交通指示牌目标检测数据集按YOLOv5目录格式整理完毕可直接用于模型训练和验证免去自行采集与标注图像的繁琐过程。整套压缩包共2000个文件以txt标签文件1127个与jpg图像872个为主附带1个可视化Python脚本资源包大小约10.31MB解压后目录结构即符合YOLOv5训练要求。数据划分为训练集和测试集训练集含901张图片及对应标签txt测试集含225张图片及对应标签txt覆盖左转、右转、红灯、绿灯、人行道等8类常见赛道指示牌。图像分辨率为200*120的RGB图片契合智能车竞赛、机器人实训及自动驾驶入门实验场景便于快速进行数据准备与算法验证。另附可直接运行的脚本随机传入图片即可绘制边界框以检查标注效果已有151人浏览学习。1. 自动驾驶小车缺的就是这种数据集200×120、8类指示牌、YOLOV5开箱即用做智能小车的人都有个共同痛点网上能找到的目标检测数据集大多是 COCO、VOC 那种大场景通用图分辨率高、类别杂拿来训练自己的小车模型要么学到的特征跟赛道实际光线完全不搭要么预处理要把大图缩到 tiny损失一堆细节。这份数据集恰恰相反它来自智能小车赛道的真实场景图像分辨率固定在 200×120包含 8 类交通指示牌——左转、右转、红灯、绿灯、人行道等。数据按 YOLOV5 的目录格式整理训练集 901 张图配 901 个标签 txt验证集 225 张配 225 个标签总共 11 MB下载下来不用转换格式直接就能进训练流程。适合正在做自动驾驶小车项目、参加竞赛、或者想用一份「小图小类别」数据集把 YOLOV5 从配置到部署完整跑通的人。2. 拆解YOLOV5目录格式数据组织、标签规范与配套脚本2.1 训练集与验证集901 张与 225 张的目录结构拿到资源先别急着训练先把目录结构看懂。YOLOV5 官方对数据集的目录约定是 images 和 labels 两个分支并行images 里放图片labels 里放同名 txt两张目录下的文件名一一对应。这份资源的组织方式也是这个套路常见的落盘结构是这样的datasets/ ├── images/ │ ├── train/ │ │ ├── 0.jpg │ │ ├── 1.jpg │ │ └── ... │ └── val/ │ ├── 64.jpg │ ├── 75.jpg │ └── ... └── labels/ ├── train/ │ ├── 0.txt │ ├── 1.txt │ └── ... └── val/ ├── 64.txt ├── 75.txt └── ...训练集和验证集的分配比例接近 8:2901 张训练、225 张验证这个配比符合 YOLO 系数据集的常规习惯。需要注意一点原资源描述里写的是「测试集」但在 YOLOV5 的语境下验证集和测试集在训练流程中的作用不同——验证集用来每轮评估 mAP 和 loss测试集是最终部署前才去碰的。这份资源里那个 val 目录实际承担的就是验证集功能训练时 data.yaml 里直接指给它就行不用再手动拆分。还有个小细节值得注意图片和标签的同名对应关系是按文件名去后缀匹配的所以不能出现两张不同格式的图片共用同一个文件名比如0.jpg和0.png同时存在标签0.txt到底归谁就成了说不清的悬案。我拿到任何数据集都会先跑一遍文件名查重这个习惯帮我挡掉了不止一次训练集样本数对不上的问题。2.2 标签 txt 的格式类别 ID 与归一化坐标的约定每个 txt 文件里每一行代表一个检测目标行内容分五列类别 ID、归一化中心 x、归一化中心 y、归一化宽度 w、归一化高度 h。归一化的意思是坐标值除以图片的宽或高所以数值范围在 0 到 1 之间和图片分辨率无关。这个设计让同一份标注可以适配不同输入尺寸——你训练时把图缩到 320 还是 224标注都不需要重新算。写个小脚本就能把一行的含义拆出来。with open(datasets/labels/train/0.txt, r) as f: for line in f: parts line.strip().split() class_id int(parts[0]) # 类别ID从0开始计数 x, y, w, h map(float, parts[1:]) # 归一化中心坐标和宽高 # 换算回 200x120 原图像素坐标 x_px, y_px x * 200, y * 120 w_px, h_px w * 200, h * 120 print(fclass{class_id}, 中心({x_px:.0f},{y_px:.0f}), 宽{w_px:.0f}, 高{h_px:.0f})这段脚本做的事就是把 txt 里的归一化坐标还原成 200×120 图像上的像素坐标方便直接观察标注目标在原图上的实际大小和位置。很多新手拿到数据集不检查标注直接丢给 train.py等训练出来才发现某个类别一个框都没学到回头排查时用这个脚本扫一遍所有 txt能快速发现三类典型错误坐标越界x 或 y 大于 1或宽高加上中心点后超出图像范围、宽高为负值、以及类别 ID 超出 names 列表长度。这三类错误在 YOLOV5 里有些会被跳过有些会直接炸训练进程越早发现越省事。2.3 类别字典文件8 个类别的顺序为什么不能乱资源里附带一个类别字典 txt这个文件很多人会忽略但它是整份数据的「翻译表」。YOLO 标签里的 class_id 是一个整数意思是「第几个类别」而具体是左转还是右转、红灯还是绿灯要靠字典文件把顺序对齐。我的习惯是拿到资源第一件事就是打开这个 txt确认前几个类别是否符合预期比如 0 对应左转、1 对应右转、2 对应红灯、3 对应绿灯、4 对应人行道剩下三个类别以资源里实际写的为准。这个顺序在训练和推理时必须全局一致训练用的 data.yaml 里 names 列表顺序、类别字典文件的顺序、推理结果里类别 ID 的含义三者要一一对应。最常见的翻车方式是在训练的时候把 names 写成另一种顺序推理时又按原来的顺序输出结果模型检测框位置完全正确但标签全部错位——红灯识别成绿灯这在自动驾驶场景里是致命事故。YOLO 的类别 ID 没有任何额外元数据兜底全靠这个顺序对齐所以先读字典文件再写配置是最稳的一步。2.4 可视化脚本先看懂它再决定要不要改项目里附带了一个可视化 py 文件作用是随机取一张图片读取同名 txt把边界框画在图上并保存到当前目录脚本默认配置下可以直接运行。这种脚本在目标检测数据集里属于「验货工具」图片和标签都是文本加像素只有画出来才能确认标注框是否贴合指示牌、类别 ID 是否正确。我通常建议拿到手先跑一遍如果图上框的位置和物体轮廓明显不匹配说明标注质量有问题这种资源需要慎重使用如果框都贴合再进训练流程不迟。脚本的核心逻辑不复杂无非是 cv2 读图、解析 txt、循环画矩形框、cv2.imwrite 保存随机部分用 random 模块从文件列表里取一个文件名。如果后续需要一次导出多张检查图可以把随机取数改成循环遍历再给输出文件加上序号。这个改动很轻量但能大幅提高检查效率——毕竟一张张随机抽抽十次才能覆盖完所有类别循环遍历一次就能把所有带框图画出来。3. 上手实操可视化验货脚本与三项训练前数据体检3.1 目录摆放与第一个验证命令拿到资源后先把整个 datasets 目录放到一个干净的工程路径下。我一般会建一个 yolo_study 工程文件夹里面放 datasets、从官方仓库 clone 下来的 yolov5 目录、以及后面要写的自定义 yaml 配置文件。摆放结构清晰有个好处训练时给 data.yaml 的 path 字段写相对路径不容易出现因为绝对路径写错导致找不到图片的问题。目录放好之后先进入可视化验货环节。python visualize_demo.py这是资源自带可视化脚本默认的运行方式。脚本内部会从图片目录随机选取一张 jpg自动去 labels 目录寻找同名 txt解析出所有边界框用 OpenCV 的 rectangle 函数把框画上去并保存为一个新的图片文件到当前目录。运行完你会得到一张带框的图如果画出来的框和指示牌边缘基本吻合说明这份数据的标注是可用的。如果脚本支持传参指定图片也可以像下面这样定向查看某一个具体样例。python visualize_demo.py 790.jpg3.2 数据体检一图片与标签文件配对检查在正式训练之前我强烈建议做一次「配对检查」遍历 images 和 labels 两个目录找出那些有图片但没有标签、以及有标签但没有图片的文件。YOLOV5 在训练时对缺失标签的处理并不总是报错有时候会默默跳过某些样本导致实际训练图数比预期少而很多人直到训练完看曲线才察觉问题回头查数据已经浪费了好几个小时。import os img_dir datasets/images/train lab_dir datasets/labels/train imgs {f.split(.)[0] for f in os.listdir(img_dir) if f.endswith(.jpg)} labs {f.split(.)[0] for f in os.listdir(lab_dir) if f.endswith(.txt)} print(缺标签的图片:, imgs - labs) print(缺图片的标签:, labs - imgs)这个脚本把两个目录的文件名去掉后缀后取集合差两边各自独有的名字就是问题文件。正常情况应该输出两个空集合因为这份资源在交付时就已经做过配对但下载传输过程中可能丢文件、解压可能出错花十秒钟跑一遍能避免后面所有莫名其妙的训练中断问题。如果你的数据集是别人二次打包过的这个检查就更不能省。3.3 数据体检二空标签与面积过小目标筛查空标签比缺标签更隐蔽文件存在但 txt 里一行都没有代表这张图没有任何目标。训练集里混入少量空标签不致命YOLOV5 有背景样本的概念但比例过高会让模型训练变成「在空图上找鬼」浪费样本也拖慢收敛。面积过小的目标则是老问题图片本身只有 200×120如果某个指示牌标注框只有几个像素宽模型几乎不可能学会它。import os lab_dir datasets/labels/train for name in os.listdir(lab_dir): path os.path.join(lab_dir, name) with open(path, r) as f: lines f.readlines() if len(lines) 0: print(空标签:, name) continue for line in lines: _, _, _, w, h map(float, line.strip().split()) if w * 200 8 or h * 120 8: # 还原为像素后小于8px print(小目标:, name, f{w*200:.0f}x{h*120:.0f}px)这里的 8 像素阈值是我自己定的经验值你可以根据赛道相机的实际成像调整到 5 或 10。小目标识别本来就是 YOLO 系列的相对弱项如果这类样本集中在某一个类别里训练时就要额外关注那个类的 recall 曲线甚至考虑扩充该类别的小图样本来平衡。跑完这段脚本你对这份数据里「哪些类好学、哪些类难搞」就有了一个初步判断这个判断会直接影响后面超参数怎么调。3.4 数据体检三类别分布统计类别分布不均会直接导致模型偏向样本多的类这是目标检测里最常见的玄学之一——不是模型结构有问题是数据本身就不均衡。通过统计所有 txt 中每个 class_id 出现的次数可以很快判断需不需要做类别重加权或者需不需要对某些类别做针对性扩充。from collections import Counter import os lab_dir datasets/labels/train counter Counter() for name in os.listdir(lab_dir): with open(os.path.join(lab_dir, name), r) as f: for line in f: counter[int(line.strip().split()[0])] 1 for cid in sorted(counter): print(f类别{cid}: {counter[cid]}个目标)如果发现某个类别的目标数只有其他类的三分之一训练时可以把这个类别的 loss 权重调高YOLOV5 自带的自适应训练模式也会做部分平衡但自己心里有数更重要。这一步做完这份数据集的「健康状况」基本摸清可以放心进入训练流程了。三份体检脚本跑完不到一分钟比起训练跑一半才发现数据有问题这个时间成本几乎可以忽略。4. 训练自己的8类检测器data.yaml编写、超参数选择与产物解读4.1 写 data.yaml路径、类别数、names 顺序对齐YOLOV5 的训练入口 train.py 需要一个数据配置文件一般命名为一个自定义的 yaml 文件比如 track_signs.yaml。里面包含三类信息数据集路径、类别数量 nc、类别名称列表 names。这里最需要注意的是路径写法YOLOV5 较新版本支持 path 加相对路径的方式train 和 val 可以写成 images/train、images/val 这种相对路径路径的基准是 datasets 所在的目录位置。path: ../datasets train: images/train val: images/val nc: 8 names: 0: left_turn 1: right_turn 2: red_light 3: green_light 4: crosswalk 5: class_5 6: class_6 7: class_7names 列表的 0 到 7 必须和类别字典文件完全一致后面的 class_5、class_6、class_7 只是占位名实际类名要打开资源自带的字典 txt 核对后填进去。很多训练报错源头就在这里字典文件里明明 8 个类yaml 里 nc 却写了 9或者 names 列表长度和 nc 对不上train.py 启动时直接抛标签数量异常。写 yaml 时还有一个容易忽略的点path 要用相对路径时train.py 的工作目录必须在 yolov5 仓库内部否则路径基准变了相对路径就失效。4.2 模型与输入尺寸为什么不要照抄 640YOLOV5 官方默认输入是 640×640那是为 COCO 那种大图准备的而这份数据的原始分辨率只有 200×120。如果直接设置 img640程序会把小图拉伸到六倍面积指示牌上的文字和边缘细节全部糊掉训练出的模型在真实赛道上表现会很差。我建议把训练输入设成 320甚至 224既能保留足够细节又能大幅降低推理耗时——这一点在后期部署到小车上时感受尤其明显。模型体量方面yolov5n 和 yolov5s 是首选。n 是 nano 版本参数量最小适合树莓派、Jetson 这类算力受限设备s 是 small 版本精度略高但对 CPU 推理压力更大。在小车自动驾驶这种实时性要求高、目标本身又不复杂的场景里先跑通 n再酌情升级到 s是性价比最高的路线。这份数据总共只有 1126 张图用 m 或 l 级别的大模型几乎必然过拟合还拖慢训练迭代速度。下面是几个核心超参数的经验区间参数推荐值说明--img320 或 224原图 200×120640 会严重拉伸--batch8 到 16显存不够就调小配合梯度累积--epochs100 起步配合 early stopping不用硬等--mosaic0.3 或 0小图拼贴会干扰目标尺度特征--weightsyolov5n.pt官方预训练权重迁移学习4.3 训练命令与超参数实操链路训练命令需要把数据配置、预训练权重、输入尺寸、轮数、batch 全部串起来。文件夹结构这里我一般会在 datasets 的同级目录放 YOLOV5 官方仓库然后进入仓库目录执行命令。python train.py \ --data ../track_signs.yaml \ --weights yolov5n.pt \ --img 320 \ --epochs 100 \ --batch 16 \ --device 0 \ --mosaic 0.3几个参数的取舍逻辑需要说清楚--weights 用官方预训练权重做迁移学习比从零训练收敛快得多尤其适合小数据集--img 320 是依据原图分辨率定的目标最小边大约 20 像素320 输入下能被有效放大让特征提取器有足够信息可用--epochs 100 是给足训练轮次并配合 early stopping防止过拟合的同时不浪费算力--mosaic 0.3 表示 mosaic 增强的概率降为 30%因为 mosaic 会把四张小图拼成一张对 200×120 的小图来说拼贴后目标尺度更混乱默认的 1.0 概率容易让损失函数震荡。--device 0 表示使用第一张 GPU如果没有 GPU 则改成 --device cpu速度会慢很多但流程完整可跑。从这份数据本身的体量来看100 轮训练在消费级 GPU 上大约半小时到一小时能完成即使只用 CPU只要能等训练流程也能完整跑通。训练过程中可以随时打开 runs/exp 目录里的 results.png 实时查看 loss 和 mAP 曲线不用等全部结束才看结果。如果训练中途断了不用从头再来加一行--resume参数就能从断点继续这是 YOLOV5 一个很实用但总被忽略的功能。4.4 训练产物解读weights、标注图和 results 曲线训练完成后runs/exp 目录里会出现 best.pt 和 last.pt 两个权重文件best.pt 是验证集 mAP 最高的一轮保存的权重last.pt 是最后一轮的权重部署时优先用 best.pt。同目录下的 val_batch0_labels.jpg 是验证集某批图片的标注框预览图能直观看出模型学到的框是否准确贴合目标、类别标签有没有错乱。results.png 则汇总了 box_loss、cls_loss、mAP0.5 等曲线的变化趋势是整个训练过程最浓缩的「体检报告」。一个值得注意的点是YOLOV5 的 loss 曲线不能只盯着 box_loss 的绝对值看因为不同输入尺寸、不同增强策略下 loss 的量级差异很大重点是看它有没有稳定下降并收敛。mAP0.5 曲线在正常训练下应该逐渐趋平如果几十轮后还像过山车一样剧烈波动说明学习率太高或数据里有脏样本需要回头检查第 3 章的三项体检结果。记得把 runs/exp 里的 best.pt 单独复制出来按项目名加日期命名免得后续训练新模型覆盖掉这个好不容易调出来的权重。5. 常见问题排查五个训练与部署翻车场景的血泪记录5.1 翻车场景一训练一启动就报标签类别数越界现象运行 train.py 后立刻报错提示某个标签的 class 值超出范围或者 AssertionError 指出 labels 的维度不对训练进程直接退出。原因有两个可能一是 data.yaml 里 nc 写错8 个类写成了 9导致模型输出通道数与标签不匹配二是标签 txt 里出现了类别 ID 为 8 或更大的行这通常是数据集制作时类别编号写错造成的。解决先打开类别字典文件数一遍类别数再写一个小脚本扫描所有 txt 的第一列找出最大 ID确认它小于 nc。这类报错 90% 是 nc 与 names 数量不一致把配置改对立刻就好。5.2 翻车场景二bbox_loss 高位震荡五六十轮不收敛现象训练 loss 一直稳定在 3 以上震荡没有随轮次逐步下降的趋势results.png 里曲线像锯齿一样。原因常见两个输入尺寸设成 640把 200×120 小图强行拉伸特征完全失真或者 mosaic 增强概率保持默认 1.0四张小图随机拼贴后目标尺度混乱。解决把 --img 降到 320 或 224--mosaic 降到 0.3 甚至 0这两个参数调整后 loss 曲线通常会立刻变得平滑。这类问题属于超参数和数据结构不匹配和模型结构关系不大先动数据增强再考虑换模型排查路径更短。5.3 翻车场景三训练 loss 正常但 val mAP0.5 始终为 0现象训练过程一切正常loss 在下降但验证集 mAP 一直为 0无论训练多少轮都纹丝不动。原因通常不是模型问题而是验证集标签和训练集标签不一致最典型的是 names 顺序错位比如训练集里类别 0 是左转验证集标注时类别 0 却对应了右转模型输出和标签对不上号mAP 自然算不出来。另一类是 val 路径写错data.yaml 的 val 指向了一个空目录或不存在路径。解决先用第 3 章的配对脚本检查 val 目录文件是否齐全再随机打印两个 val 标签 txt 对照类别 ID 和实际目标语义最后确认 data.yaml 的 val 路径真实存在。这类问题排查起来不复杂但很磨人因为训练流程全程无报错。5.4 翻车场景四部署到小车上推理延迟高检测框乱跳现象把 best.pt 加载到树莓派或 Jetson 上做实时推理一帧处理时间超过 200 毫秒小车转弯的时候检测框还上下左右乱跳没法稳定跟踪指示牌。原因模型输入尺寸和推理尺寸都继承训练时的 640加上权重是 fp32 全精度在小算力设备上负担很大框跳动的直接原因是单帧检测缺少时间维度的平滑。解决推理时把输入压到与训练一致的 224用 half 精度加载权重推理耗时通常能降一半以上框跳动最常见的处理方式是对连续帧的检测框中心做 EMA 平滑ema_x 0.8 * ema_x 0.2 * detect_x ema_y 0.8 * ema_y 0.2 * detect_yEMA 系数 0.2 表示新检测结果只贡献 20% 权重能有效抑制单帧误检带来的抖动同时保留真实转向的跟随能力。如果还嫌慢可以导出 ONNX 再走 TensorRT 或 OpenVINO 加速这类工具在嵌入式小车场景里是成熟方案代价是部署链路多一环建议放在模型精度验证通过之后再碰。5.5 翻车场景五训练集 mAP 高验证集明显偏低过拟合现象训练到 80 轮左右训练集 mAP 接近 1.0验证集却只有训练集的一半左右两条曲线明显分叉。原因很明确1126 张图对 YOLOV5 来说属于小样本模型参数太多把训练数据里的噪声细节也背下来了。解决思路有三条按优先级排第一换 yolov5n 这种参数量更小的模型限制模型容量第二增强数据多样性在 hyp 超参数里把 hsv_h、hsv_s、fliplr 适当调大让模型见到的形态更多第三不要盲目加到 300 轮用 early stopping 停在验证集最优的轮次附近。过拟合在小数据集上无法完全消除但把训练和验证的 mAP 差距从一倍缩小到 20% 以内对这个体量的数据来说是完全可以做到的。6. 进阶验证三连类别AP分析、现场照片测试与半精度推理6.1 用验证集统计每个类别的 AP定位短板类训练结束后runs/exp 里的 val 结果会打出每个类别的 Precision、Recall、mAP0.5 列表。别只盯着整体 mAP 看逐类看一遍找到 mAP 最低的那个类。如果这个类在训练集中出现的次数本来就少那补该类的图片比调任何超参数都有效如果样本数不少但 recall 低说明目标尺寸太小或者特征不鲜明需要针对性做增强。6.2 收集 10 张真实赛道照片做验证模型训练时见过的都是数据集里的场景实际赛道的光线、角度和指示牌距离会有差异。我一般会在赛道现场拍 10 张照片不经过数据集的任何预处理直接丢给模型推理用漏检数和误检数作为是否部署的硬指标。import torch model torch.hub.load(ultralytics/yolov5, custom, pathbest.pt, force_reloadTrue) result model(track_spot_01.jpg) result.print()这一步用 torch.hub 加载自定义权重核心目的是验证数据流和推理链路本身没问题。如果现场照片上模型表现明显比 val 集差先看是不是拍摄距离比训练集更远导致目标变小是的话就考虑把训练输入从 320 再调低或回到第 3 章的体检脚本补小样本。6.3 半精度推理与嵌入式导出的最后一步在确认类别和现场表现都达标后我才会做推理优化。半精度是压测里效果最直接的一步把权重转成 half 精度推理在 GPU 或带 NPU 的板子上能拿到接近翻倍的推理速度内存占用也减少一半。权重转换不需要重新训练加载模型后加一行model.half()即可导出时选择对应的 half 版本就行。这些年我做小车部署每次都强制把「逐类看 AP → 现场拍照实测 → 转半精度再验一遍」完整走完少一步都会在比赛或答辩现场翻车这套流程帮我把很多隐患拦截在上车之前希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站