YOLOv5交通标志检测:从数据预处理到ONNX部署完整指南

发布时间:2026/9/12 21:56:07

YOLOv5交通标志检测:从数据预处理到ONNX部署完整指南 简介YOLOv5交通标志物检测完整工程包面向计算机相关专业正在准备课程设计、期末大作业的学生以及需要完整项目进行实战练习的深度学习学习者。项目以YOLOv5为检测框架整合了源代码、训练好的权重模型、标注数据与训练配置覆盖从数据整理、模型训练、效果评估到单张/视频推理的完整链路能够直观展示目标检测在实际交通场景中的应用方式。压缩包共266个文件体积423MB文件类型以Python脚本、YOLO系列配置、模型权重、图像样本为主同时包含训练日志、指标统计和Docker部署文件兼顾二次开发与部署实践需求。目前已有362人学习浏览项目源码经过严格调试下载后按照说明即可直接运行免去复杂的环境搭建与数据集准备流程。对需要完成课程报告或答辩演示的同学来说包内训练记录、结果曲线和模型性能数据都是现成的支撑材料适合作为高分项目参考或在此基础上做算法优化。1. 拿到YOLOv5交通标志物检测项目包后先确认这三件事这种“源码训练好的模型全部数据”的压缩包看似一步到位但最常见的问题不是模型不收敛而是你拿到手就直接双击 train.py结果在数据加载阶段就抛异常。解压之后我会按三步走先确认目录是不是自包含的weights、data、models、runs 这些关键目录是否齐全再确认权重文件是完整 checkpoint 还是只用于推理的 stripped 模型前者能接着训练后者只能做推理最后检查数据集标注是不是 YOLO 的 txt 格式而不是 VOC 的 xml 或 COCO 的 json。交通标志检测和通用目标检测不太一样。标志在画面里往往只占几十个像素而且数据集之间的类别定义差异很大TT100K 有 45 类CCTSDB 只有 3 类直接拿别人训练好的模型跑你的测试图很可能类别名对不上、mAP 跌一半。所以先搞清楚这个包里的数据分布和标签结构比急着复现训练更重要。这个项目通常用于课程设计、毕业设计或小规模道路巡检验证正确打开方式是把模型、数据和代码三个部分分别校验一遍。2. YOLOv5交通标志物检测的网络结构和数据集格式2.1 从CSPDarknet到三尺度检测头YOLOv5网络结构如何服务小目标要真正用好 YOLOv5不能只会跑命令。YOLOv5 的网络结构分成三块Backbone 是 CSPDarknetNeck 是 PANetHead 是三个不同尺度的检测头。CSP 模块把特征图沿通道分成两路一路做卷积提取一路通过 short-cut 直连既减少计算量又保住梯度流。PANet 在 FPN 的基础上增加了一条自下而上的路径让高层语义信息和小目标的细节纹理双向融合这对交通标志这种小目标尤其关键。Head 部分在 80x80、40x40、20x20 三个特征层上输出预测框。80x80 的网格负责捕捉小目标感受野小20x20 的网格负责大目标。交通标志在 1080p 路面上可能只有 20x20 像素如果输入图像被缩得太小小目标特征直接丢光。所以做交通标志物检测时我一般会把输入尺寸从默认的 640 提到 1280或者至少开 multi-scale 训练。YOLOv5 的 anchor 是在训练时基于你的数据集重新计算的换数据集后如果还沿用 COCO 的 anchor前几个 epoch 会明显不稳定。2.2 数据集目录结构和 YOLO txt 标签格式拿到项目包后先看 data 目录是不是这样的结构project/ ├── data/ │ ├── images/ │ │ ├── train/ │ │ └── val/ │ ├── labels/ │ │ ├── train/ │ │ └── val/ │ ├── classes.txt │ └── traffic.yaml ├── weights/ │ ├── best.pt │ └── last.pt ├── models/ └── scripts/如果 labels 目录是空的那数据还需要预处理。YOLO 的标签每一行是五个浮点数类别索引、归一化后的中心点 x、中心点 y、宽度、高度。比如图像宽 1920 高 1080一个限速标志落在 (100, 200) 到 (160, 280)标签行就是0 0.06771 0.22222 0.03125 0.07407类别索引对应 classes.txt 里的顺序0 表示第一类不是中文名称。这里有个常见的脏数据标注框坐标越界x2 比图像宽度大几十像素。YOLOv5 在训练时会报坐标警告不致命但会影响框回归精度。我习惯先写一个脚本统计缺失标签的图片import os img_dir data/images/train label_dir data/labels/train missing 0 for name in os.listdir(img_dir): stem os.path.splitext(name)[0] if not os.path.exists(os.path.join(label_dir, stem .txt)): print(missing label:, name) missing 1 print(missing count:, missing)这个脚本的逻辑很简单图片文件名和标签名必须一致只是后缀不同。缺失标签要么是数据整理时漏拷了要么是这张图本身没有目标。如果没有目标的图片也放在 train 目录最好单独清掉否则 YOLOv5 会把它当成背景训练影响 recall。2.3 把 VOC XML 转成 YOLO 标签避免手动标注浪费时间项目如果给的标注是 Pascal VOC 的 xml转换代码可以这样写import xml.etree.ElementTree as ET def voc_label_to_yolo(xml_path, out_txt, classes): root ET.parse(xml_path).getroot() w int(root.find(size/width).text) h int(root.find(size/height).text) lines [] for obj in root.iter(object): name obj.find(name).text if name not in classes: continue box obj.find(bndbox) x1 float(box.find(xmin).text) y1 float(box.find(ymin).text) x2 float(box.find(xmax).text) y2 float(box.find(ymax).text) x_c (x1 x2) / 2.0 / w y_c (y1 y2) / 2.0 / h bw (x2 - x1) / w bh (y2 - y1) / h cls_id classes.index(name) lines.append(f{cls_id} {x_c:.6f} {y_c:.6f} {bw:.6f} {bh:.6f}) with open(out_txt, w) as f: f.write(\n.join(lines))使用前把 classes 列表按训练数据集的类别文件顺序填好。转换时如果 x2 比 w 大要先 clip 再归一化否则生成的 width 会大于 1YOLOv5 对这类标签的过滤策略不一定每次都报错。2.4 不同交通标志数据集的类别映射不要混着用常见的交通标志检测数据集差异很大训练前先看项目里的 classes.txt数据集类别数典型类别TT100K45i100, p26, pl100 等标志编号CCTSDB3prohibitory, warning, mandatoryGTSDB43各类限速、禁行、提示标志如果压缩包里的权重是用 CCTSDB 训练的模型输出层就是 3 个类别拿去做 TT100K 的 45 类评估结果一定很差。所以训练自己的数据前先确认 dataset.yaml 里的 nc 和 names 跟标签里的类别索引对齐。这一步比调学习率重要得多。3. 本地复现YOLOv5交通标志物检测环境、权重和推理3.1 安装依赖并跑一次最小推理命令解压项目后先建虚拟环境装依赖。不要用系统 Python 直接装YOLOv5 的依赖版本敏感torch 和 torchvision 版本不匹配会直接报错。cd YOLOv5交通标志物检测源码目录 python -m venv venv source venv/bin/activate pip install -r requirements.txtrequirements.txt 里通常包含 torch、torchvision、opencv-python、numpy、matplotlib、PyYAML、tqdm 等。如果机器是 NVIDIA GPU按你装的 CUDA 版本选择对应的 torch 版本如果是 CPU 机器直接装 CPU 版即可交通标志检测用 CPU 也能跑推理只是训练会很慢。环境装好后先用模型对单张图片做推理python detect.py \ --weights weights/best.pt \ --source data/images/val/00001.jpg \ --conf-thres 0.25 \ --img-size 640 \ --save-txt其中--source可以是单张图片、文件夹、视频文件或摄像头编号。--conf-thres是置信度阈值低于 0.25 的框会被过滤掉交通标志小目标置信度普遍偏低可以降到 0.2 试一下。--save-txt会把每个框的类别和归一化坐标写入 runs/detect 目录方便后面核对标注位置。3.2 detect.py 关键参数表与交通标志场景推荐值参数默认值交通标志场景建议--weightsyolov5s.pt换成项目自带的 best.pt--source单张图片先用一张图跑通再跑视频--conf-thres0.250.2 到 0.3 之间低了误报多高了漏检--iou-thres0.45标志密集时降到 0.3--img-size640小目标场景用 1280 或 1280 的倍数--devicecpu有 GPU 时指定 0--save-txt否建议开启方便检查坐标--projectruns/detect管理多次实验输出--img-size是推理时缩放到输入尺寸不是原图尺寸。交通标志检测建议不要低于 640否则远端小标志会被压缩成几个像素检测器再强也识别不出。代价是推理速度变慢可以用 TensorRT 或 ONNX Runtime 缓解。3.3 先检查权重文件再推理避免加载出空模型很多 zip 里的 best.pt 是训练中途保存的完整 checkpoint包含模型结构、优化器状态、epoch 和类别名但也有的被剥成 deploy 版本只能推理。用一个小脚本看权重结构import torch ckpt torch.load(weights/best.pt, map_locationcpu, weights_onlyFalse) print(ckpt.keys()) if model in ckpt: model ckpt[model].float().eval() print(names:, model.names) print(stride:, model.stride) else: print(no model key, only state_dict)如果输出里names是字典说明模型自带类别名如果为空需要你在调用 detect.py 时补一个 dataset.yaml。stride是三个检测头的下采样倍数正常是 [8, 16, 32]看到这个值说明模型结构加载完整。忽略这一步直接跑容易把类别数量不一致的模型当成可用权重推理结果全是 0 个目标。3.4 推理阶段最常见的三个错误第一个是报Label class N exceeds ncN_cfg in data/yaml这不是推理问题是训练标签写错了后面训练章节会细说。第二个是CUDA out of memory模型本身不大但输入图开到 1280 后显存占用会成倍增加先检查是不是真的用到了 GPU 和 batch size。第三个是图片路径含中文OpenCV 默认读取不了把测试集改成英文路径。提示如果 detect.py 输出了框但全标成无关类别先检查 weights 和 dataset.yaml 是否属于同一个数据配置。跨数据集的模型耦合在类别列表上路径、文件名对不上最典型的表现就是“检测到东西但全是错类”。4. 用YOLOv5训练自己的交通标志数据集和超参数调优4.1 写好 traffic.yaml类别数和标签强相关训练自己的数据集第一步是建 dataset.yamlpath: ./data train: images/train val: images/val nc: 3 names: 0: prohibitory 1: warning 2: mandatorypath是相对 dataset.yaml 所在目录的根路径YOLOv5 会把 path、train、val 拼接成最终目录。nc必须和标签文件里最大类别索引 1 相等。如果 names 里写了 3 个类别但某个标签第 6 个数据是3 0.5 0.5 0.2 0.2训练会直接报类标签越界。检查标签越界可以跑一条命令python - PY from pathlib import Path for p in Path(data/labels/train).glob(*.txt): for line in p.read_text().strip().splitlines(): if line and int(line.split()[0]) 3: print(p, line) PY这个脚本用 heredoc 方式执行 Python逻辑是遍历所有 txt把第一列类别索引不小于 3 的行打印出来。输出有内容就先修数据不要带着脏标签训练。4.2 train.py 训练命令和参数说明训练命令我一般写成这样python train.py \ --data data/traffic.yaml \ --weights yolov5s.pt \ --cfg models/yolov5s.yaml \ --img 640 \ --batch-size 16 \ --epochs 100 \ --hyp data/hyps/hyp.scratch-low.yaml \ --project runs/train \ --name traffic_exp--weights yolov5s.pt使用 COCO 预训练权重做迁移学习交通标志这种小数据集从零训练容易欠拟合用预训练权重能明显加快收敛。--cfg指定模型结构文件必须和--weights对应yolov5s.pt 配 yolov5s.yaml不能拿 yolov5m 的结构去加载 s 的权重。--hyp是超参数文件交通标志场景推荐 hyp.scratch-low.yaml因为数据量通常不大过强的数据增强反而让模型学不到特征。4.3 超参数怎么调从lr0到mosaic关键超参数我列在表里超参数默认值调整建议lr00.01数据集小于 5000 张时降到 0.005lrf0.01最后学习率是初始学习率的 1%一般不动warmup_epochs3.0前 3 个 epoch 用低学习率热身mosaic1.0小目标占比高时保持 1.0mixup0.0类别少且相似时不要开fl_gamma0.0背景多、正样本少时调到 1.5mosaic是拼接四张图训练对提升小目标召回有奇效但交通标志之间形态差异大拼接太猛会导致上下文失真。如果你的训练 loss 一直震荡先看lr0是不是太大而不是持续加训练轮数。4.4 训练过程异常排查和指标验证训练过程中实时看runs/train/traffic_exp/results.csv这个文件每轮都会写入 loss 和 mAP。用 pandas 快速看尾部数据import pandas as pd df pd.read_csv(runs/train/traffic_exp/results.csv) print(df[[epoch, train/box_loss, val/box_loss, metrics/mAP50, metrics/mAP50-95]].tail())正常情况是 box_loss 和 cls_loss 下降mAP50 上升。如果 mAP50 一直在零附近优先检查 labels 是否有内容、类别编号是否对、train 和 val 是否重叠。训练结束后用 best.pt 跑验证集python val.py \ --weights runs/train/traffic_exp/best.pt \ --data data/traffic.yaml \ --task val \ --conf-thres 0.001 \ --iou-thres 0.6验证时把置信度阈值设到 0.001是为了画 PR 曲线时覆盖所有置信度区间这样才能得到完整的 mAP。如果直接用推理时的 0.25 阈值做验证mAP 会被截断看起来偏低。5. 导出ONNX并在本地验证交通标志检测模型5.1 用 export.py 导出静态尺寸 ONNXPyTorch 模型直接部署到端侧不方便常见做法是先导出 ONNX。命令python export.py \ --weights runs/train/traffic_exp/best.pt \ --include onnx \ --opset 12 \ --img-size 640 640 \ --simplify--img-size 640 640固定成静态输入导出的 ONNX 在 CPU 设备上运行更稳定。--simplify会用 onnx-simplifier 做一些常量折叠和算子合并减少模型体积。对交通标志检测这种小目标场景不建议同时开--dynamic动态 shape 会导致端侧显存分配不确定流量大时延迟抖动很明显。5.2 用 onnxruntime 做一次推理导出后写一个最小推理脚本验证 ONNX 输出是否正常import cv2 import numpy as np import onnxruntime as ort session ort.InferenceSession(runs/train/traffic_exp/best.onnx, providers[CPUExecutionProvider]) input_name session.get_inputs()[0].name def preprocess(img): img cv2.resize(img, (640, 640)) img img[..., ::-1].transpose(2, 0, 1) img np.ascontiguousarray(img, dtypenp.float32) / 255.0 return img[None] image cv2.imread(data/images/val/00001.jpg) outputs session.run(None, {input_name: preprocess(image)})[0] print(outputs.shape) # (1, 25200, 8)输出形状里的25200是三个尺度的 anchor 总数8 是四个坐标、一个目标置信度、三个类别概率。YOLOv5 的 ONNX 输出默认是不带解码的裸 tensor后面还需要做 decode、conf 过滤和 NMS。如果你不想手写后处理可以直接用项目里自带的 detect.py 验证 PyTorch 模型把 ONNX 推理作为部署阶段的对齐参考。5.3 部署前检查指标差距一个容易被忽略的技巧是检查 ONNX 和 PyTorch 的输出差异。如果项目版本支持对 ONNX 直接跑 val.py就对比 mAP50如果不支持就抽三张图逐框对比坐标和置信度。允许的差距很小正常情况差在 0.1% 以内如果差得明显通常是预处理逻辑不一致比如 BGR/RGB 顺序、归一化系数、letterbox 补边方式。拿一张训练集和验证集里都没出现过的路段照片把 ONNX 输出的检测框画回原图确认限速标志、禁行标志的框位准确类别名和项目里 classes.txt 一致再进入端侧部署环节。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/9/12 21:56:07

Layui按钮级权限控制实战:从权限码设计到前端显隐方案

1. 需求来源与整体设计思路1.1 为什么后台管理系统必须做按钮级权限控制我最早接触layui的时候,其实也不太理解按钮权限这回事。菜单权限好理解,不同角色看到不同菜单,侧边栏渲染出来就不一样。但按钮权限是个更细的维度——同样是“编辑”按…

2026/9/12 21:51:07

Java智慧养老平台代码实战:工单闭环、Redis防抖与高并发优化

简介:一套基于SpringBoot的智慧养老平台完整Java源码,面向计算机、电子信息工程等专业学习者,适合作为毕业设计、课程设计及期末大作业。系统采用B/S架构与MVC模式,整合SpringBoot、Mybatis、Ajax、Vue等技术栈,覆盖前…

2026/9/12 23:01:13

AI绘画生态全解析:SD、Flux、ComfyUI与LoRA、ControlNet实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/12 23:01:13

Linux设备驱动开发实战:从芯片手册到可运行模块的完整链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/12 22:56:12

NVIDIA Warp深度解析:Python原生GPU编译器原理与工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/12 2:05:33

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/12 3:55:12

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/12 10:09:03

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/12 0:04:17

MATLAB仿生优化框架:长鼻浣熊算法多策略融合实现

简介:本资源是一份面向智能优化算法研究者与MATLAB初学者的仿生智能算法实践代码包,聚焦于长鼻浣熊优化算法(COA)的多策略改进与性能验证。针对传统COA易陷局部最优、收敛精度不足等问题,作者融合Circle映射初始化提升…

2026/9/12 0:04:17

【JAVA毕设源码分享】基于 JavaWeb 的校园一卡通管理系统的设计与实现 基于 JavaWeb 的校园卡业务管理系统(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/9/12 0:04:17

【JAVA毕设源码分享】基于 Java 的图书馆借阅管理平台的搭建与实现 基于 Java 的图书馆综合管理系统(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/12 6:37:43

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码