十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

YOLOv5交通标志检测实战:从数据准备到ONNX部署全流程解析

YOLOv5交通标志检测实战:从数据准备到ONNX部署全流程解析 简介YOLOv5交通标志物检测完整项目面向计算机专业正在完成课程设计、期末大作业或需要项目实战练习的学生。项目包含全部源码、训练好的.pt模型权重及配套图像数据与标注文件经严格调试下载后可直接运行或继续训练。资源共266个文件以Python源码53个py、YOLO配置59个yaml、图像与标注55个jpg、26个png为主另有预训练权重10个pt、Docker环境文件、训练结果csv与日志等整体约423MB目录结构清晰便于按模块查阅。目前已有362人学习/浏览适合入门深度学习和目标检测实战。读者可从中获得一个完整可复现的检测流程包括数据集组织与标注格式、YOLOv5训练参数配置、模型推理调用与结果记录方式也可参考其代码结构迁移到其他检测场景。1. 起步拿到一份 YOLOv5 交通标志检测源码之后先看一个反直觉的事实YOLOv5 交通标志物检测项目能不能跑通瓶颈往往不在模型而在数据。课程设计里见过太多人卡在标注格式不一致、训练路径配错、类别数对不上——这三件事随便哪一件出错train.py 都会在第五个 epoch 前后开始报错或 mAP 全零。这份 97 分的项目打包了源码、训练好的模型和全部数据等于把最容易出错的三关提前过掉了解压就能看到data/images和data/labels成对存在训练和推理入口都是现成的。图像处理、深度学习、目标检测三块知识都能从这里找到落点适合正在做课程设计的学生也适合想拿一套完整工程复现训练流程的从业者。2. YOLOv5 网络结构与交通标志的特征提取路线2.1 骨干网络与 C3 模块YOLOv5 的骨干网络把 Darknet53 改造成带跨阶段局部连接CSP的结构。跨阶段局部连接的核心是把输入特征图按通道拆成两条路径一条经过若干 Bottleneck 堆叠另一条直接向后传递最后在输出端合并。这样梯度回传时有短路通道训练更稳定计算量也不会随深度线性膨胀。这个思想最终被封装成 C3 模块源码在models/common.py里class C3(nn.Module): CSP Bottleneck with 3 convolutions def __init__(self, c1, c2, n1, shortcutTrue, g1, e0.5): super().__init__() c_ int(c2 * e) # hidden channels self.cv1 Conv(c1, c_, 1, 1) self.cv2 Conv(c1, c_, 1, 1) self.cv3 Conv(2 * c_, c2, 1) self.m nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, e1.0) for _ in range(n)))cv1 和 cv2 都是 1×1 卷积先把输入通道压缩到中间维度c_主路经过n个 Bottleneck 串接旁路保持原样最后用 cv3 把拼接后的 2×c_ 通道还原成输出通道。n是 Bottleneck 数量yolov5s 里为 3yolov5m 为 6这直接决定了模型容量和推理耗时的差异。提示C3 的shortcut默认 True只在特征图尺寸不变化时生效每次下采样后网络会自动绕过残差连接避免信息冗余。2.2 PANet 多尺度融合对小目标的意义交通标志在画面里普遍偏小一辆车 20 米外拍到的限速牌可能只有 24×24 像素。如果只用单一尺度的特征图小目标很容易在下采样过程中丢失。YOLOv5 用 FPN 把深层语义传到浅层再用 PANet 自底向上把细节信息接回来两条路径汇合后产生三个尺度的检测头。models/yolo.py中的 Detect 层初始化了这些检测头m nn.Conv2d(cv3_out, anchors * (5 num_classes), 1) self.anchors torch.tensor(anchors).float().view(self.nl, -1, 2) self.grid [torch.zeros(1) for _ in range(self.nl)] self.stride torch.tensor(stride).float()每个 anchor 输出5 num_classes个通道5 对应中心坐标偏移、宽高缩放和置信度后面的num_classes对应类别概率。stride 表示检测 head 相对原图的下采样倍数P3 是 8P4 是 16P5 是 32分别对应小、中、大目标。2.3 三个检测头的分工检测头下采样倍数特征图尺寸输入 640×640合适的目标P3880×80远处限速牌、警告牌P41640×40中距离禁令标志P53220×20近处大尺寸指示牌三个检测头共用一份 anchor 配置文件但各自侧重不同尺度的目标。交通标志这种小目标密集的场景里P3 头承载的压力最大训练时如果发现小目标漏检严重优先检查 P3 的输出。2.4 为什么选 YOLOv5 而不是两阶段模型Faster R-CNN 这类两阶段检测器在 COCO 上 mAP 略高但推理时间经常是 YOLOv5 的十倍以上。课程设计答辩现场只有普通笔记本用 Faster R-CNN 跑摄像头实时检测基本不可行。YOLOv5 把数据加载、Mosaic 增强、自动学习 anchor、EMA 权重平均全部内置本身就是一个完整训练闭环改配置就能换数据集对课程设计和工程验证都很友好。3. 交通标志数据集YOLO 标签格式与预处理3.1 目录组织与数据关联项目自带的交通标志数据已经按 YOLOv5 约定的目录结构放好解压后可直接被 train.py 读取。目录如下data/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── traffic_sign.yamlimages 和 labels 同级YOLOv5 在读取标签时通过把images路径替换为labels来定位标注文件。因此 images/train 里的每张img_0001.jpg必须对应 labels/train 里的一个img_0001.txt文件名前缀完全一致否则训练时会静默跳过那个样本。3.2 标注格式与坐标归一化YOLO 格式的标签文件每行表示一个目标格式为class_id x_center y_center width height五个数值中坐标和宽高都归一化到 0~1。假如一张 1280×960 图像中有一个边界框左上角为 (320, 240)宽和高都是 160 像素x_center (320 160/2) / 1280 0.3125y_center (240 160/2) / 960 ≈ 0.3333width 160/1280 0.125height 160/960 ≈ 0.1667。对应文本行是0 0.3125 0.3333 0.125 0.1667如果标注是 LabelImg 导出的 VOC XML做一次坐标换算再送入训练。项目里常见做法是写一个转换函数def convert_bbox(size, box): dw 1.0 / size[0] dh 1.0 / size[1] x (box[0] box[1]) / 2.0 * dw y (box[2] box[3]) / 2.0 * dh w box[1] * dw h box[3] * dh return x, y, w, hsize 是图像的 (width, height)box 按 (left, right, top, bottom) 传入。这里要注意 left/right 的取值顺序LabelImg 导出的 XML 里是 xmin/xmax/ymin/ymax对应关系写错会导致标注框反转。3.3 类别不平衡与增强策略交通标志的类别分布天然不均衡“限速”类样本可能是“注意儿童”的十倍。如果直接训练模型会偏向高频类别低频类的召回率掉得很快。缓解手段有两类一类是过采样少见类别样本另一类是在线增强。YOLOv5 内置的 Mosaic 会把四张图随机拼成一张等于每个 batch 都引入了更多位置、尺度、光照变化对交通标志这类小目标数据尤其有效。源码中通过 hyp 配置控制 mosaic 开关mosaic: 1.0 mixup: 0.0 copy_paste: 0.0mosaic1.0 表示每张训练图都是拼接产物mixup 和 copy_paste 默认关闭。如果换数据集后出现严重过拟合可以先把 copy_paste 调到 0.1 试它能让目标在图像间复制粘贴进一步丰富背景多样性。3.4 数据划分与路径配置训练/验证/测试集的划分建议在文件系统层面完成不要在训练时动态切分。按 8:1:1 比例分好后把路径写进 traffic_sign.yamltrain: data/images/train/ val: data/images/val/ nc: 5 names: [speed_limit, stop, warning, no_entry, crosswalk]一个容易踩的坑是 train 路径写成data/images/而不是data/images/train/。YOLOv5 的 dataloader 会递归读取子目录这看似能跑但会把 test 图也混进训练集导致验证指标虚高、答辩时被问到说不清。4. 训练配置、迁移学习与精度平衡4.1 模型体量选择交通标志检测对实时性要求高课程设计通常在一张入门级显卡上完成。项目里常见的模型选择如下模型参数量单卡 batch16 显存占用适用场景YOLOv5s7.2M约 8GB课程设计/边缘设备YOLOv5m21.2M约 12GB高精度实验YOLOv5l47.0M约 24GB线下评测不适合实时建议直接用 yolov5s 起步它精度足够推理速度也快。显存不够时优先调小 batch 而不是换更小的模型——batch 缩到 8 后仍可正常收敛只是训练时间变长。4.2 训练命令与参数解读python train.py \ --data traffic_sign.yaml \ --cfg models/yolov5s.yaml \ --weights yolov5s.pt \ --epochs 300 \ --batch-size 16 \ --img 640 \ --device 0 \ --patience 50--cfg指定模型结构不传时从--weights自动推断--weights yolov5s.pt是 COCO 预训练权重用迁移学习可以大幅缩短收敛时间--patience 50表示验证集 mAP 连续 50 轮不提升就早停300 轮上限通常 150 轮左右就能触发停止。提示如果类别数或数据分布与 COCO 差异较大训练脚本会在加载权重时自动跳过不匹配的检测头层不影响训练流程。4.3 学习率与优化器YOLOv5 默认优化器是 SGD配 cosine 学习率衰减。项目 hyp 配置里核心参数为lr0: 0.01 lrf: 0.2 momentum: 0.937 weight_decay: 0.0005lr0 是初始学习率lrf 是最终学习率相对初始值的比例0.2 表示最后一个 epoch 学习率衰减到 0.002。这个设置在多数目标检测任务里工作良好。数据量较少时可以手动把 lr0 调到 0.005 避免震荡。训练中不需要手动修改学习率scheduler 会按 cosine 曲线自动完成衰减。4.4 训练日志与 results.csv 分析训练过程每个 epoch 都会生成 box_loss、obj_loss、cls_loss、mAP0.5 等指标并写入 runs/train/exp 下的 results.csv。可以用 pandas 直接读取来观察趋势import pandas as pd df pd.read_csv(runs/train/exp/results.csv) print(df[[epoch, metrics/mAP_0.5, val/box_loss]].tail())判断标准很简单损失平稳下降、mAP 持续上升说明训练正常。如果验证损失在第 100 轮开始反弹而训练损失还在下降说明过拟合此时早期停止已经触发不需要额外干预。项目里自带的多个 results.csv 相当于几组对照实验对比不同实验的 mAP 曲线可以反推哪个超参数改动起了作用。4.5 继续微调与自己的数据迁移如果训练好的模型要适配新的交通标志类别直接在 best.pt 基础上进行微调即可。比如新增了一类“施工标志”把 traffic_sign.yaml 的类别表更新后执行python train.py \ --data traffic_sign_custom.yaml \ --weights runs/train/exp/weights/best.pt \ --epochs 50 \ --batch-size 8训练脚本会根据新类别数自动重置检测头输出维度预训练 backbone 的特征复用能力保留只需要少量数据即可达到够用的精度。这种微调方式是课程设计换题目的常用路径。5. 推理部署从 PyTorch 权重到 ONNX 工程化5.1 用训练好的权重跑推理python detect.py \ --source data/images/test.jpg \ --weights runs/train/exp/weights/best.pt \ --conf-thres 0.4 \ --iou-thres 0.45 \ --project runs/detect \ --name exp_test--conf-thres 0.4是置信度阈值只保留高于 0.4 的检测框。调低到 0.25 能减少漏检但误报会变多--iou-thres 0.45是 NMS 的 IoU 阈值交通标志重叠较少按默认即可。--source 0可以切换到摄像头输入这也是答辩演示最常用的方式。5.2 导出 ONNX 并用 onnxruntime 加载把权重导出为 ONNX 格式可以在没有 PyTorch GPU 环境的机器上部署python export.py --weights best.pt --include onnx --simplify--simplify会用 onnx-simplifier 移除冗余算子导出后的模型用 onnxruntime CPU 推理import onnxruntime as ort import numpy as np sess ort.InferenceSession(best.onnx) input_name sess.get_inputs()[0].name output sess.run(None, {input_name: image_np})注意导出过程中 YOLOv5 会绑定输入分辨率。如果训练时用的--img 640推理时输入也需要 letterbox 到 640×640否则会直接维度报错。ONNX 的输出是原始预测向量需要自己解码坐标和置信度项目里 detect.py 的解码逻辑可以直接搬过来。5.3 兼容摄像头与视频流的工程化处理视频流推理时要处理采样帧率和帧间对象闪烁问题直接逐帧跑检测没问题但输出框会在相邻帧间抖动。我一般保存检测结果时会保留原始帧的 BGR 通道顺序用 cv2.imwrite 落盘避免出现红蓝通道对调的人花掉的问题。如果要把检测框叠加回视频先复用 YOLOv5 的plot_one_box工具函数再作颜色映射比从零画要省很多事。从这份源码到线上服务唯一需要补的是前处理的标准化逻辑——模型导出 ONNX 后输入张量的 BGR/RGB 顺序和归一化方式必须和训练时完全一致核心的(x/255.0 - mean) / std参数不要拍脑袋改。本文还有配套的精品资源点击获取
返回列表