新闻详情

新闻详情

首页 / 资讯中心 / 详情

基于YOLOv5的交通标志识别实战:从数据转换到模型训练避坑指南

发布时间:2026/10/2 10:04:41来源:尧图网络
基于YOLOv5的交通标志识别实战:从数据转换到模型训练避坑指南
简介基于YOLOv5的道路交通标志识别项目以完整源码与配套数据集打包专为毕业设计、期末大作业及课程设计打造。代码注释详实从数据准备到模型训练、推理部署均有清晰说明新手可快速上手项目曾获导师高度认可的98分部署门槛低下载解压即可运行。资源共266个文件包含YOLOv5模型配置yaml、训练权重pt、Python脚本py、标注图片jpg/png及数据集标签等整体压缩包423.32MB目录结构分明便于逐模块学习与二次开发。目前已吸引439人学习下载适合计算机视觉方向的学生参考其算法实现与工程组织方式作为高分开题或答辩展示亦具说服力。1. 交通标志识别为什么是 yolov5 的主场毕业设计选型先把生态摸清楚道路交通标志识别是目标检测方向里最常被拿来做毕业设计的真实场景之一原因很直白公开数据集好找、场景贴近实际生活、交付时能讲出完整的故事。yolov5 也是我接到这类选题时默认推荐的第一方案。它未必每一项指标都比新模型强但它把“数据准备—训练—验证—导出部署”整条链路收得很干净你搭出来的这套流程以后换到任何检测项目都能复用。这篇笔记从零走一遍先跑通 yolov5 的最小推理再把交通标志数据集转成训练格式接着把训练、调参、踩坑、验收讲透。不管手里是 40 系显卡还是老款 1060这套流程都走得动。2. 跑通 yolov5 最小系统环境配置、权重下载与第一次推理2.1 conda 新建环境这一步决定后面几天的心态第一次装 yolov5 最容易翻车的就是环境。torch 装错 CUDA 版本或者直接往 base 环境里堆依赖后面 protobuf、dill、matplotlib 各种打架能把人折腾到想换题。我一般会先按题目建一个干净的 conda 环境Python 版本按官方仓库要求来3.8 到 3.10 之间的常见版本都可以然后按有没有 NVIDIA 显卡决定装 GPU 版还是 CPU 版 torch。CPU 版训练慢但把流程跑通没问题后面再租云 GPU 也不迟。# 创建并激活独立环境避免污染 base conda create -n yolo5 python3.8 -y conda activate yolo5 # 按显卡情况安装 torch/torchvision有 CUDA 就选对应版本没有就装 CPU 版 pip install torch torchvision # 拉取 yolov5 源码并安装依赖 git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txt这里真正要关注的是最后一行 requirements.txt它会一次性装齐 numpy、opencv、pandas、tensorboard 这些训练和可视化依赖。常见错误是跳过这步直接用自己的环境跑 detect.py结果报No module named torchvision或者 opencv 版本对不上。另外一个经验是装完依赖后用一行命令检查 CUDA 是否真的可用省掉后面训练时才发现没用上 GPU 的时间。python -c import torch; print(torch.__version__, torch.cuda.is_available())如果输出末尾是 True说明 torch 正确识别到了显卡如果是 False要么装成了 CPU 版要么 CUDA 驱动不对。这一步排查成本很低但能避免你训练一整晚后才发现全程在用 CPU 硬扛的尴尬。显卡驱动和 torch 的 CUDA 版本对应关系不复杂但确实有点玄学我的建议是驱动别追最新去 torch 官方安装页看自己驱动支持到哪个 CUDA 版本再按那个索引装 torch。2.2 第一次推理用官方 yolov5s 验证链路通不通代码和依赖都就位以后先别急着碰自己的数据集用官方预训练权重做一次推理把整条链路验证通。这一步的意义是区分“代码环境问题”和“数据问题”如果官方权重跑不出框说明环境还有坑不值得带着坏环境去训练自己的模型。推理命令极其简单第一次跑会慢一点因为要下载 yolov5s.pt 权重。python detect.py --weights yolov5s.pt --source data/images/street.jpg --conf 0.4这条命令里yolov5s.pt 是官方提供的最小可训练权重文件会放到 weights 目录--source可以是一张图片、一个视频文件、一个目录实战最常用的三种输入都在这--conf 0.4是置信度阈值低于 0.4 的预测框被丢掉。跑完后结果默认写在runs/detect/exp/里面那张带框的图就是我们想要的输出。看到图里准确框出“人、车”这类 COCO 类别说明模型文件、图像解码、NMS 后处理全部正常可以进入数据阶段。如果这一步卡住绝大多数是 opencv 读取视频帧出错少部分是 matplotlib 在无显示环境下保存图片异常。我一般会顺手加两个参数再跑一次--save-txt保存每张图的坐标文本--save-conf把置信度一起写入文本。这两个参数后面做指标分析时非常有用现在就养成习惯后面不慌。python detect.py --weights yolov5s.pt --source data/images/street.jpg --conf 0.4 --save-txt --save-conf2.3 交通标志数据集长什么样VOC xml 与 yolov5 txt 的对应关系yolov5 训练时读取的不是 xml而是每个图片对应的同名 txt 标注文件。第 3 章会写完整转换脚本这里先把格式差异讲清楚因为后面所有翻车都从这里开始。项目VOC 格式xmlyolov5 格式txt坐标表达绝对像素坐标 xmin、ymin、xmax、ymax归一化中心点 x_center、y_center、宽、高数值范围0 到图片宽/高之间0 到 1 之间的小数类别表达字符串名称如 stop、pedestrian从 0 开始的整数编号存储方式每个对象一个object节点每行一个对象类别 x y w h举一个实际例子某个 VOC 标注片段长这样object namestop/name bndbox xmin120/xmin ymin80/ymin xmax190/xmax ymax150/ymax /bndbox /object如果这张图宽 640、高 480且 stop 在类别表里排第 2 位那么对应的 yolov5 标签行是2 0.242187 0.239583 0.109375 0.145833。四个小数分别对应中心 x、中心 y、宽、高全部是归一化结果。交通标志数据集的原始标注多半是 VOC 或 COCO 风格所以转换时最容易错的不是加减乘除而是忘了归一化或把 xmax 减 xmin 的宽度算成高度。转换完一定要抽几张图把框画出来肉眼检查这是所有后续训练的后悔药。3. 把交通标志数据集转成 yolov5 格式voc2yolo 脚本与标签校验3.1 坐标换算逻辑为什么中心点格式和 VOC 差着一层除法VOC 的 bndbox 给的是左上角和右下角的绝对像素坐标yolov5 要的是归一化中心点格式换算公式并不复杂。设图片宽为 W、高为 H有x_center (xmin xmax) / 2 / Wy_center (ymin ymax) / 2 / Hbox_w (xmax - xmin) / Wbox_h (ymax - ymin) / H分母必须是图片的实际宽高不是标注框的宽高也不是模型输入尺寸的 640。这个细节看着不起眼实际踩的人很多有人把坐标换算成 0 到 1 之后又拿模型输入尺寸 640 乘了一遍结果所有框都缩成了极小值也有人直接把 W 和 H 写反训练出的框全部偏斜。转换脚本本身很简单真正值钱的是转换后的自动校验因为这类错误不会报异常只会在训练曲线上慢慢折磨你。3.2 转换脚本一份能直接跑的 voc2yolo下面这份脚本面向最常见的数据集组织方式raw/annotations放 xmlraw/images放同名 jpg输出写到labels/目录。类名单用固定顺序的列表维护顺序一旦定下来就不要改。# voc2yolo.py import glob import os import xml.etree.ElementTree as ET def convert_one(xml_path, txt_path, class_names): tree ET.parse(xml_path) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) if img_w 0 or img_h 0: return False lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_names: # 遇到未知类别先跳过但外层要能统计到不能吞掉错误 continue cls_id class_names.index(name) bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) # 裁剪到图像边界防止坐标越界导致训练增强时报错 xmin max(0.0, min(img_w - 1, xmin)) ymin max(0.0, min(img_h - 1, ymin)) xmax max(0.0, min(img_w - 1, xmax)) ymax max(0.0, min(img_h - 1, ymax)) if xmax xmin or ymax ymin: continue x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h box_w (xmax - xmin) / img_w box_h (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) with open(txt_path, w, encodingutf-8) as f: f.write(\n.join(lines)) return True if __name__ __main__: # 顺序必须和后面的 data.yaml 完全一致这是最容易踩的坑 class_names [speedlimit-20, speedlimit-30, stop, pedestrian, warning, no_entry, yield] os.makedirs(labels, exist_okTrue) total 0 empty 0 for xml_path in sorted(glob.glob(raw/annotations/*.xml)): base os.path.basename(xml_path).replace(.xml, ) img_path os.path.join(raw/images, base .jpg) if not os.path.exists(img_path): print(missing image:, img_path) continue txt_path os.path.join(labels, base .txt) ok convert_one(xml_path, txt_path, class_names) if not ok: print(bad annotation:, xml_path) if os.path.exists(txt_path) and os.path.getsize(txt_path) 0: empty 1 total 1 print(fprocessed {total}, empty {empty})这段代码值得展开讲几个点。第一root.iter(object)用的是深层遍历有些 xml 里嵌套了segmented或part节点用findall(object)只会取到第一层容易漏掉目标。第二裁剪边界那四行不是多余的公开数据集的框经常比图像宽高多出几个像素不裁会让 yolov5 在 Mosaic 增强阶段直接报错。第三empty计数很关键如果某些类别不在class_names里被静默跳过就会生成大量空 txt而空标注文件在训练时等于告诉模型“这张图没有目标”轻则浪费样本重则把背景学成负样本。脚本跑完processed和empty两个数字必须心里有数empty占比超过 1% 就要回头排查类别命名。3.3 训练集/验证集划分随机种子、比例与文件搬运转换完之后要把数据按比例拆成训练集和验证集。我的习惯是 8:1 到 9:1 之间交通标志样本数量通常够用验证集至少留 100 张以上不然 mAP 曲线波动大得没法判断。划分脚本不难难在“怎么分得科学”。# split_data.py import glob import os import random import shutil random.seed(2024) # 固定种子保证每次划分结果可以复现 imgs sorted(glob.glob(raw/images/*.jpg)) random.shuffle(imgs) val_ratio 0.2 val_num int(len(imgs) * val_ratio) os.makedirs(dataset/images/train, exist_okTrue) os.makedirs(dataset/images/val, exist_okTrue) os.makedirs(dataset/labels/train, exist_okTrue) os.makedirs(dataset/labels/val, exist_okTrue) for idx, img_path in enumerate(imgs): base os.path.basename(img_path)[:-4] src_label os.path.join(labels, base .txt) if idx val_num: shutil.copy(img_path, dataset/images/val/) if os.path.exists(src_label): shutil.copy(src_label, dataset/labels/val/) else: shutil.copy(img_path, dataset/images/train/) if os.path.exists(src_label): shutil.copy(src_label, dataset/labels/train/)划分这里有个隐藏问题如果原始数据是视频抽帧同一段路的连续几帧高度相似随机洗牌后可能同一场景的帧同时出现在训练和验证集里这叫“泄漏”。验证集看起来指标很高但换一段新视频就崩。交通标志公开数据集大多是不同地点单独拍摄的图片这个问题不严重但如果你是自采视频抽帧必须先把连续帧按视频片段分组整组划分。举个例子video01_0001.jpg到video01_0100.jpg是一组划分时把组作为一个最小单位而不是把单帧打散。划分完再打印训练和验证各自的图片数、标签数、每个类别的样本数这一步能提前暴露漏拷 label 的问题。3.4 data.yaml类别名顺序决定训练结果能不能对齐yolov5 训练时的数据配置集中在 data.yaml 里格式如下# dataset/traffic_sign.yaml path: ./ train: images/train val: images/val nc: 7 names: 0: speedlimit-20 1: speedlimit-30 2: stop 3: pedestrian 4: warning 5: no_entry 6: yieldpath是配置文件所在目录的基准路径train 和 val 都相对它写不要写绝对路径否则换一台机器训练就要改一遍。nc是类别数必须和 names 的长度一致。这里的 names 顺序必须和第 3.2 节转换脚本里的class_names完全一致因为 txt 里只存整数 id顺序错一个整个模型的语义就错位了。比如 stop 排到第 0 位训练出来模型记住的 0 号类别是 stop而你推理时显示的第 0 位可能写成了 speedlimit-20。这类错误不报任何异常只能靠推理阶段手动对比一旦发现就要回炉重排标签。验证 data.yaml 最直接的方法是画图检查用 opencv 把训练集图片和 label 框画在一起随机抽 20 张看类别名和框是否对得上。4. 训练自己的交通标志识别模型预训练权重、超参数与曲线判读4.1 预训练权重选 s 还是 m精度、显存和训练时间的三角yolov5 官方权重从 n 到 x 一溜排开参数量和精度依次上涨。做交通标志识别这种不算太难的检测任务我一般不推荐一上来就选最大的实践中最常用的是 s 和 m 两档。yolov5s 显存占用小训练速度快6G 显存跑 batch 16 没有压力适合先通流程yolov5m 精度比 s 高一截但显存和时间成本上涨明显适合在 s 已经把流程跑通、准备冲最终指标时换上去。交通标志本身是小目标居多模型容量稍微大一点确实有帮助但前提是数据没有大问题否则就是拿显卡电费买教训。预训练权重还有个容易被忽略的用法当你自己标注的数据量不够时先从公开交通标志数据集训一版保留这个权重再用自己的数据继续微调。这比每次从 COCO 预训练权重开始效果更直接因为 COCO 的 80 类里没有专门的交通标志语义模型要花更多时间去理解什么是“限速牌”。迁移学习不是玄学它解决的是“数据量不够时模型先从大模型偷学特征”的问题交通标志识别这种任务很适合这个套路。4.2 训练命令与必调超参数batch、epoch、imgsz 和 hyp 文件一切就绪后训练命令长这样python train.py \ --data dataset/traffic_sign.yaml \ --weights yolov5s.pt \ --epochs 120 \ --batch-size 16 \ --imgsz 640 \ --workers 4 \ --device 0逐个拆开说。--data指向第 3 章写的 data.yaml--weights是预训练权重最好先下载到本地再填路径避免训练到一半联网拉权重失败--epochs交通标志这类数据集 100 到 150 轮足够再多就有过拟合倾向--batch-size越大 loss 曲线越平滑但受显存限制6G 显存配 batch 16 比较中庸--imgsz是训练输入分辨率交通标志小目标多条件允许就上 640 甚至 1280显存不够再往下退--workers是数据加载进程数Windows 上设成 0 反而更稳Linux 下 4 或 8 都没问题。yolov5 的超参数默认值在data/hyps/hyp.scratch-low.yaml里做交通标志识别我一般会单独建一个 hyp 文件调三处学习率、色域增强、mosaic 开关。一个常用的修改版长这样# data/hyps/hyp.traffic.yaml lr0: 0.005 # 初始学习率默认 0.01数据规模小时调低更可靠 lrf: 0.01 # 最终学习率 lr0 * lrf余弦退火的终点 momentum: 0.937 weight_decay: 0.0005 hsv_h: 0.015 # 色调扰动标志颜色本身是语义不能扰得太狠 hsv_s: 0.7 # 饱和度扰动提高对褪色标志的适应 hsv_v: 0.4 # 亮度扰动模拟逆光和阴影 degrees: 0.0 # 旋转设为 0交通标志不会倒着出现 translate: 0.1 # 平移扰动让目标出现在不同位置 scale: 0.5 # 缩放扰动模拟远近变化 mosaic: 1.0 # mosaic 增强默认开对小目标训练帮助明显 mixup: 0.1 # mixup 比例太大会让标志边缘变糊把文件传给训练命令python train.py ... --hyp data/hyps/hyp.traffic.yaml。这里要强调两个方向。一是交通标志的颜色是关键特征hsv_h不能设太大否则红色禁令牌被扰动成蓝色模型会学歪二是旋转扰动对标志这类刚性物体应该关掉现实中标志不会横着长。很多人拿默认 hyp 直接训效果也能看但这类任务相关的细节是自己调优时真正值钱的地方。还有一个参数值得单独说--multi-scale它让模型在训练中随机使用不同输入尺寸对交通标志这种尺度变化大的任务很友好代价是训练时间变长、曲线更抖适合数据量大的时候用。4.3 训练曲线怎么读loss、mAP 和过拟合信号训练过程中yolov5 会实时把指标写进runs/train/exp/results.csv和results.png。第一次训练的人最容易犯的错是只盯训练集 loss看到 train/box_loss 一路下降就以为万事大吉其实更要看的是 val 侧指标以及最终训练输出目录里weights/best.pt和last.pt的区别。正常曲线一般长这样前 10 轮 loss 下降又快又陡20 轮后逐渐平缓mAP0.5 上升后出现平台。如果 validation loss 先降后升而 train loss 还在降这是过拟合信号解决办法不是继续加数据增强而是提前停止、减小学习率或者减少 epoch。如果 mAP 从第一轮开始就在 0 附近抖动先别调参回头检查标签十有八九是第 3 章的归一化或类别顺序问题。训练结束时会自动选 mAP 最高的权重存为 best.pt后面所有推理、验证、导出都用它不要顺手用了 last.pt后者通常是最后一轮的权重过拟合程度更高。看曲线时我还习惯把results.csv用 pandas 读出来按轮次画精度的局部放大图这样比直接看 results.png 更细。import pandas as pd df pd.read_csv(runs/train/exp/results.csv) print(df.columns) # 列出所有指标列 print(df[[metrics/mAP_0.5, metrics/mAP_0.5:0.95, val/box_loss]].tail())这样做的好处是能精确看到 mAP 从第几轮开始不再上升方便你决定训练轮数而不是盲目填一个 300 轮跑三天。4.4 显存不够怎么办降分辨率、调 nbs、用梯度累积显存不够是这台课设最常遇到的事尤其老显卡上跑交通标志的高分辨率大图。最直接的办法是把--imgsz从 640 降到 512 或 416代价是小目标更难学所以这只适合数据里目标本身不太小的场景。第二个办法是把--batch-size调小到 8 甚至 4同时配合--nbs 64。yolov5 的 nbs 参数是“名义 batch size”它的机制是用梯度累积模拟大 batch实际 batch 小但每 N 步累加一次梯度再更新权重效果上等价于一个大 batch。我这个例子把 nbs 设成 64实际 batch 16 的话模型相当于每 4 步做一次更新既省显存又不牺牲太多训练稳定性。注意 loss 的放缩也因此变了不要只看表面数值对比 mAP 曲线才是判断依据。5. 避坑手册交通标志识别里 5 个典型的翻车现场与解法5.1 坐标全部错乱的坑xml 看起来没问题txt 却全乱现象转换脚本跑完抽查某一两张图框的位置明显对不上物体有的框跑到图外有的把所有物体堆在左上角。训练时 loss 一开始就很大验证集 mAP 始终在个位数徘徊。原因常见两类。一类是宽度写成(xmax - xmin)但忘了除以图像宽导致框宽是归一化后的几百倍另一类是图像本身存在 EXIF 旋转VOC xml 里的宽高是按旋转前算的而训练时读图和转换脚本读图用到了不同方向的尺寸信息。交通标志数据集很多从行车记录仪截取EXIF 里的 Orientation 字段经常暗藏问题转出来的框错位一点都看不出来直到训练阶段 loss 爆炸。解决先用一个 40 行的小脚本把“原图 预测框”画出来随机抽 20 张肉眼检查。一旦发现错位回到原始图片用 PIL 读 EXIF 方向统一按旋转后的宽高重算。我的习惯是转换前先把所有图片统一转成标准方向并覆盖写入再跑转换脚本从根上避免这个黑匣子。5.2 小目标漏检路牌明明在画面上模型就是不报现象训练完成后 mAP 看着不小但验证集中距离较远的限速牌、小型警告牌一个都检不出来画面上 30×30 像素的小标志直接穿过。原因交通标志数据集里源图往往是 2048×2048 甚至更大的行车记录仪截图直接 resize 到 640 之后一个 30 像素的标志只剩 9 个像素特征基本消失。模型不是不会检而是这个目标在输入图上已经不存在了。这类小目标漏检是交通标志识别的标配问题跟模型大小关系不大。解决最有效的手段是分块训练和分块推理。常见做法是维护一个滑窗裁切步骤把大图切成 640×640 且带重叠的若干块只保留中央区域的标注最后汇总各块检测结果做去重。如果嫌麻烦就把--imgsz提到 1280 直接训练显存不够就配合第 4.4 节降 batch。这两个方向是交通标志小目标问题的两条主线光靠调 conf 阈值解决不了问题。另外训练时保持默认的 Mosaic 增强对小目标有增益不要因为曲线波动就关掉先跑完再判断。5.3 逆光与夜间场景数据增强让灯牌从背景里显出来现象白天测试效果挺好换成逆光路段或傍晚场景召回率直线下滑标志牌上反光、背光模型要么漏检要么把路灯当目标框出来。原因数据集大多在白天晴天采集光照分布单一模型学到的其实是“白日光照下的标志长什么样”而不是“标志的语义形状”。逆光时标志牌的边缘对比度下降YOLO 的深层特征提取不出来夜间标志靠反光材质与背景区分白天训练数据里没有这种对比模式。解决在数据增强上对症下药。一是调大 hyp 文件里的hsv_v和translate并额外加对比度扰动让模型见过更暗、更偏色的输入二是如果数据集里完全没有夜间样本值得单独采一小批夜间图混进训练集人工标注几百张就够。增强不是越多越好特别是把颜色扰得太狠会影响标志类别判断这个度要在验证集上实测。实战中我会跑两组实验一组默认增强一组加了逆光扰动对比逆光测试集上的 recall数值说话。5.4 类别极度不均少样本类别 mAP 被拖到脚面现象val 输出的每个类别指标里stop、限速牌这类常见类别 mAP 很高少数类别如“禁止拖拉机”一类的 mAP 是 0整个项目的平均指标被拖低一大截。原因公开交通标志数据集天然存在长尾分布。常见标志出现几千次少数标志只有几十次yolov5 的 loss 是按 batch 平均计算的多数类别学得多、少数类别没机会学。这不是模型坏了是统计规律。解决最可靠的是在数据层面做类别平衡不要只在网络层面加损失权重。常见做法是把少数类别样本重复复制进训练集或者对包含少数类别的图片做额外增强后扩充如果自建数据就注意采集时主动补采少数类别。另一个技巧是先在完整公开数据上预训练再微调自己的少数类别。判断依据仍然是验证集上逐类打印的 P、R、mAP不要只看总平均。训练完第一件事就是打印 per-class 指标哪类最低就去查那类的训练样本数是 30 张还是 300 张心里要有数。5.5 导出 onnx 后指标掉一截预处理不一致的坑现象PyTorch 下推理 mAP 0.93导出 onnx 后用 onnxruntime 重新跑同一张图框的位置偏了几个像素低置信度目标消失指标掉了 5 个点以上。原因yolov5 推理用 letterbox 保持长宽比并把图填充到 640×640导出 onnx 后用 opencv 或 onnxruntime 加载时预处理做了两套但填充值和归一化方式不一致。常见三种错位PyTorch 侧用 BGR 而 onnx 侧用 RGB归一化一个用 0~255 另一个用 0~1letterbox 的填充位置左右算偏。每一步差一点点叠加起来精度就掉得明显。解决把预处理统一成同一套函数最实用的是在 onnx 推理侧复刻 letterbox 的完整逻辑包括填充值、位置、比例并把 imgsz 固定成训练时的值不要用动态输入。导出后第一件事是画一张“PyTorch 结果 vs onnx 结果”的对比图两个框完全重合再谈后续优化。我见过不少同学在量化上折腾半天最后发现只是 BGR 和 RGB 的顺序没对齐。6. 验证与交付把交通标志项目从能跑变成能答辩6.1 val.py 结果表怎么翻译P、R、mAP 三类指标的解读训练结束后的验证不是跑一遍 detect.py 看几张图就完事答辩时老师一定会问“你这个模型到底好在哪里”。标准做法是用验证脚本在测试集上出指标表。python val.py \ --data dataset/traffic_sign.yaml \ --weights runs/train/exp/weights/best.pt \ --task test \ --conf 0.4 \ --iou 0.5输出表里最重要的三列是 precision、recall 和 mAP0.5。precision 是检出的框里有多少是对的recall 是所有真实标志里被检出多少mAP0.5 是不同置信度下 P-R 曲线的面积。对交通标志识别我更看重 recall因为漏检一个路牌比多画一个框后果严重得多。关键指标不要只看平均数逐类打印后把最差的类别单独存图观察。6.2 视频 demo 与结果导出答辩现场演示的固定动作答辩可能不允许现场训练但可以现场跑推理。把测试视频放在项目根目录下用最佳权重跑一次同时导出坐标文本这是演示的固定动作。python detect.py \ --source test_road.mp4 \ --weights runs/train/exp/weights/best.pt \ --conf 0.35 \ --save-txt \ --save-conf跑完之后runs/detect/exp/里会有一份带框的视频和每帧的 txt 坐标文件。如果时间充裕我一般会把其中连续十几帧的检测结果落成一张大图标注出真值和预测框对比放进论文的实验分析章节里。6.3 答辩前必查的三个检查点第一个检查点把随机种子固定把测试集路径固定连续跑两遍 val.py 结果完全一致防止答辩现场复现时指标对不上。第二个检查点把最低置信度设为 0.25 重新跑一遍 detect确认视频 demo 不会因为阈值调太高经常漏检。第三个检查点把每种失败样例单独截图想清楚“为什么漏检”和改进方向哪怕答辩时回答不上来也能展示你做过验证。我带课设时吃过最大的亏就是一阵猛训对手里模型哪一类最差、为什么差完全没有印象答辩时被老师问住只能支支吾吾。所以后来我养成一个习惯训练结束先打印 per-class 指标表贴在代码旁边再开始写论文所有的改进方向都从表格里的最低项入手。这个习惯帮你把项目从“能跑”变成“能讲”希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

FPGA开发环境搭建避坑指南:Vivado/ISE安装、License与固化全解析 2026/10/2 11:01:45

FPGA开发环境搭建避坑指南:Vivado/ISE安装、License与固化全解析

1. xsetup.exe双击后毫无反应:按这个顺序排查能省一半时间 先说结论:多数人遇到Vivado安装程序点了没反应,问题根本不在Vivado本身,而是Windows环境在搞鬼。Xilinx(现在是AMD)的安装器本质上是一个封装了Ja…

阅读更多 →
深度学习模型跑得动却难解释?从工程实践到可解释性落地 2026/10/2 11:01:45

深度学习模型跑得动却难解释?从工程实践到可解释性落地

"深度学习跑得动,但我们说不清它为什么跑得动",这句话是我入行第三年,被一个验收方的提问逼到墙角后,自己默默写在项目笔记第一页的一句话。那年我负责一个图像分类项目,模型在测试集上跑到93%的准确率&…

阅读更多 →
STM32虚拟串口驱动详解:STSW-STM32102 V1.5.0安装与USB CDC故障排查 2026/10/2 11:01:44

STM32虚拟串口驱动详解:STSW-STM32102 V1.5.0安装与USB CDC故障排查

做嵌入式USB通信这行,最容易被忽略的不是固件里的端点配置,而是PC端那一条看不见的驱动链。上个月调一块STM32F407板子,CubeMX生成的CDC工程烧进去后,设备管理器里一直挂着一个“未知USB设备(设备描述符请求失败&#…

阅读更多 →
eFootball“慢半拍”真凶:游戏延迟四环节拆解与优化指南 2026/10/2 11:01:44

eFootball“慢半拍”真凶:游戏延迟四环节拆解与优化指南

你们有没有遇到过这种情况:和对手同时启动抢一个前插球,你明明先按了射门键,球却没第一时间传出去,对方已经把球断走了。或者在防守时,对方一个变向,你拉摇杆回追,画面里球员却愣了一拍才转身。…

阅读更多 →
Windows下安装make全攻略:告别“无法识别”报错,搭建C/C++编译环境 2026/10/2 11:01:38

Windows下安装make全攻略:告别“无法识别”报错,搭建C/C++编译环境

如果你最近在 Windows 上编译过任何开源项目,大概率撞上过这一幕:源码辛辛苦苦 clone 下来,README 里白纸黑字写着make && make install,结果你在 PowerShell 里敲下回车,终端毫不留情地甩回来一句——make : …

阅读更多 →
openrig 统一配置 Claude Code 与 Codex:YAML + Node.js 实战指南 2026/10/2 11:01:38

openrig 统一配置 Claude Code 与 Codex:YAML + Node.js 实战指南

1. 从“openrig”这个名字说起:它到底想解决什么问题第一次看到“openrig”这个词,我脑子里蹦出来的第一反应是“open”加“rig”——一个开放的、可拼装的装置或框架。结合热搜词里高频出现的 Claude Code、Codex、YAML、Node.js 这一串关键词&#xff…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉