ARTICLE DETAIL

资讯详情

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

交通标志检测与识别实战:基于YOLO的深度学习目标检测全流程解析

交通标志检测与识别实战:基于YOLO的深度学习目标检测全流程解析 简介计算机视觉中的目标检测与识别是自动驾驶感知系统的核心技术之一其核心任务是在复杂场景中精准定位并分类交通标志如限速牌、禁令标志等。这类技术常基于深度学习模型实现其中YOLO系列因兼具速度与精度成为实时检测的主流选择。目标检测的基本原理是通过卷积神经网络提取图像特征利用边界框回归和分类分支完成目标定位与语义识别其技术价值在于弥补传统图像处理在光照变化和恶劣天气下的不足为智能交通系统提供可靠的环境感知能力。实际应用中该技术被广泛用于自动驾驶、辅助驾驶和智能交通监控尤其需要处理小目标、类别不平衡和实时推理等挑战。本文围绕Python工程实践系统梳理了从公开数据集如TT100K标注格式转换、数据增强策略到YOLO模型训练、超参数调优及ONNX部署的完整链路并总结了常见训练与部署陷阱为开发者提供一套可落地的交通标志检测与识别解决方案。1. 交通标志检测与识别解压这个ZIP 后你要先想清楚三件事「基于 Python 实现的交通标志检测与识别源码文档说明数据模型.zip」这类资源包几乎是计算机视觉方向入门必碰的项目。检测交通标志、识别内容再输出限速、禁行、指示牌的分类结果这行技术做的是自动驾驶感知里最不起眼却最不能错的一环。你把这个压缩包解压后常见操作是急着跑 demo但我更建议先看三样东西训练脚本用的框架版本、数据集的目录结构和模型文件的输入尺寸——这三样直接决定你后续是十分钟跑通还是花一个周末改环境依赖。这套方案适合谁适合手里有 Python 基础、跑过至少一个 YOLO 检测项目、想真正把「检测 分类」链路走通的人。如果你是纯 python 入门阶段连虚拟环境都没建过那这个项目会同时涉及 OpenCV、PyTorch、标注文件格式转换建议先照着官方教程把 python 安装与环境配置走一遍再回头看这个包。一个能正常落地的交通标志识别系统通常由三块组成检测模型负责在整张图里找出标志牌的位置分类模型或检测头负责读出牌子上的语义调度脚本负责把两者串成一条可用的推理管线。这个包里的源码理应把这三件事的文件都分好了类但能不能跑通还得靠你自己按下面的思路逐层核验。2. 选型先行检测和识别的技术路线决定你后面所有工作量2.1 检测方案从传统CV到深度学习主流做法是选哪种交通标志检测这个任务不是「随便找一个检测模型就能上」。它有几个特点目标小一张 1920×1080 的图里标志牌常只有 30×30 像素类别不平衡限速牌出现频率远高于施工牌对实时性有要求落地到嵌入式设备时必须在几十毫秒内出结果。传统方法用 LBP 或 HOG 特征加 SVM 分类器对小目标能跑但光照一变换、雾天一来特征就崩。所以现在做交通标志检测主流方案集中在 YOLO 系v5/v8、SSD 和 Faster R-CNN 这三类里。我一般建议优先看包里的模型文件是什么格式如果是 .pt 权重八成是 YOLO 系如果是 .pth 且训练脚本里有 Faster R-CNN 字样那走的是双阶段路线。双阶段精度高但慢适合做离线识别单阶段速度快但小目标容易漏适合做实时视频流。如果你拿到的包两样都有那就更明确了——用 YOLO 在视频里跑实时检测把检测到的小图裁出来再用 ResNet 之类的分类网络确认语义这是工程里最常见的「检测 分类」级联方案。从训练成本看Faster R-CNN 对显存要求更高batch size 稍大就 OOM而 YOLO 系对新手友好得多。我在没有高端显卡的机器上做验证常用 YOLOv5s 这个体量参数量不大CPU 也能勉强推理一张标志牌小图的检测精度够用。选型时还有一个容易忽略的点看源码里数据处理部分读的是 VOC 格式还是 YOLO 格式。前者是 XML 文件后者是 txt 文件转换脚本写起来不复杂但如果包里的数据已经处理好就别轻易动格式少一件事少一个坑。# 用一个最小脚本检查模型文件类型判断该走哪条推理链路 import torch # 尝试用 PyTorch 加载权重文件看是完整模型还是纯权重字典 ckpt torch.load(best.pt, map_locationcpu) if model in ckpt: print(这是 YOLO 系列的权重里面包含完整模型结构) else: print(这是普通 state_dict需要配合模型定义文件一起加载)这段脚本解决的是「拿到一个 .pt 后缀文件不知道它到底是什么结构」的问题。YOLOv5 保存的权重里带model字段直接用torch.load能读出来而分类网络的权重往往只有state_dict没有结构信息必须找到对应的模型定义类才能加载。参数说明里最值得关注的是map_locationcpu很多新手在无 GPU 机器上加载 GPU 训练的权重直接报错加了这个参数就能软性迁移到 CPU 上先看结构不会卡在第一步。2.2 识别网络单独训练分类器还是复用检测头很多拿到这个项目的人会混淆「检测」和「识别」检测是把标志牌从背景里框出来识别是告诉你是「限速 40」还是「禁止左转」。如果包里的源码只有一个 yaml 文件、一个 train.py那说明作者把识别任务塞进了检测头里用 YOLO 的类别数直接对应标志类型——这种做法省事但在类别很多比如德国 GTSRB 数据集有 43 类中国 TT100K 有 45 类时不划算因为检测头要同时学位置和类别两类任务互相干扰。工程上更稳的做法是分开YOLO 只做二分类检测前景/标志牌或者按大类检测警告/禁令/指示然后裁出目标区域交给一个轻量分类网络判断细粒度类别。这样做的好处是检测模型可以换分类模型可以单独优化任何一边出问题都不会牵连另一边。缺点是多一次推理开销但对交通标志这种小目标场景开销可以接受。从源码结构上你可以在包里的 models 目录下找有没有classifier.py或resnet.py这类文件如果只有检测相关的定义那这个项目走的就是「一步到位」路线。我个人的经验是如果你后续要在真实道路视频上跑至少让检测负责大类和位置分类负责具体含义这样调参会轻松不少——检测漏了再强的分类器也没用检测框歪了分类器看到的特征会被背景污染错误率立刻上来。# 展示检测与分类解耦后的推理伪代码流程 import cv2 # 第一步检测模型输出所有目标的框、置信度、大类ID boxes, scores, class_ids detect_model.predict(frame) # 第二步按置信度过滤低质量框保留高置信度目标 valid [i for i in range(len(scores)) if scores[i] 0.5] for i in valid: x1, y1, x2, y2 boxes[i] crop frame[y1:y2, x1:x2] # 裁出标志牌小图 fine_label classifier.predict(crop) # 分类模型输出细粒度类别 print(f检测到大类 {class_ids[i]}具体为 {fine_label})这里的逻辑说明就一句话检测和分类各干各的检测负责找位置分类负责读内容。参数说明里scores[i] 0.5这个阈值不是死的检测框质量高可以放到 0.3框经常乱跳就提到 0.6具体看你的场景对漏检和误检哪个更不可接受。crop的区域建议往外扩 10% 像素把标志牌的边缘也包进去分类准确率会明显提升。2.3 数据从哪来公开数据集优先自采数据做补充交通标志数据集最常用的两个德国 GTSRB单张标志小图分类用和中国 TT100K整图检测用。TT100K 是腾讯提供的 10 万张全景图标注了限速、禁止、警告等类别是国内项目最爱用的。你拿到的这个包里有「数据」文件夹第一件事是看它的目录结构。通常有三种形态一是已经按 YOLO/train.txt 分好类的二是原始图像 JSON/XML 标注需要自己转换三是压根只有一个子集需要你另外下完整数据。对于新手我不建议一上来就用 TT100K 全集训练那个数据量太大且类别分布严重不均。先拿包里现成的数据处理流程跑通再往里面加自己的图片。如果你要自采数据用手机拍就行但要注意标志牌本身是标准化的颜色是核心特征拍的时候别开滤镜别用夜景模式保持真实道路的光照条件。采集时把同一块牌从不同距离、角度多拍几张然后裁剪成小图做成分类数据这部分工作能极大改善模型在实景中的表现。数据管理上有个反直觉的点宁可图片少但每张干净也不要堆一堆标注错的图。交通标志检测任务里标签错误的杀伤力比数据量不足大得多——标志牌本身视觉差异小类别之间长得像比如「禁止驶入」和「禁止通行」标注错一张就相当于给模型喂了反例。拿到包里现成的数据先抽样看一眼标注框跟图片内容对不对得上这一步花不了十分钟后面能省一天。3. 数据准备与标签清洗把标注文件处理好训练就成功了一半3.1 从 TT100K 到 YOLO 格式转换脚本与四个边界坑TT100K 的标注是 JSON 格式每个文件里用 bbox 字段存储目标的左上角坐标和宽高类别是英文缩写如pl100限速 100、pne禁止驶入。YOLO 训练需要的是每张图对应一个 txt 文件每行五个数字类别ID、归一化中心 x、归一化中心 y、归一化宽 w、归一化高 h。归一化的意思是除以图像的宽高让所有值落在 0 到 1 之间这样不同分辨率的图可以混在一起训练。转换脚本的核心就是读取 JSON、提取 bbox、换算坐标。看代码import json import os # 定义类别映射TT100K 的英文缩写转成从 0 开始的整数ID CLASS_MAPPING {pl100: 0, pl120: 1, pne: 2, w55: 3, i5: 4} def convert_tt100k_to_yolo(json_path, img_width, img_height, output_txt): with open(json_path, r, encodingutf-8) as f: data json.load(f) lines [] for obj in data[objects]: category obj[category] if category not in CLASS_MAPPING: continue # 跳过未定义的类别 bbox obj[bbox] # TT100K 的标注是 [x_min, y_min, x_max, y_max] 形式 x_min, y_min, x_max, y_max bbox x_center (x_min x_max) / 2 / img_width y_center (y_min y_max) / 2 / img_height width (x_max - x_min) / img_width height (y_max - y_min) / img_height lines.append(f{CLASS_MAPPING[category]} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) with open(output_txt, w, encodingutf-8) as f: f.write(\n.join(lines)) # 示例单张图片的转换实际使用时要遍历整个文件夹 convert_tt100k_to_yolo(annotations/1.json, 2048, 2048, labels/1.txt)这段代码的逻辑拿到 JSON 里的每个目标通过 CLASS_MAPPING 把英文类别名转成数字 ID然后按 YOLO 需要的格式计算归一化坐标。四个边界坑你迟早会遇到第一个坑是坐标格式。TT100K 的 bbox 是[x_min, y_min, x_max, y_max]但有些版本给你的是[x_min, y_min, width, height]不检查直接算边界框全偏。转换前打印一条标注看数值范围如果第二对数字比第一对小一定是第二种格式。第二个坑是类别映射表。TT100K 的类别缩写看着像英文单词实际上有规律可循pl开头是限速牌p是禁令w是警告i是指示。你拿到的包如果自带映射表文件别自己重新发明直接用它的没有的话按官方说明建注意别把pl100和pl120都塞进同一类限速值不同类别不同。第三个坑是除零。有些 JSON 标注里 bbox 是空数组或者宽高算出来是 0直接写进 txt 文件会让 YOLO 训练报错。转换时要做个判断宽或高小于 5 像素的直接丢弃。第四个坑是图片原始尺寸。TT100K 的图大部分是 2048×2048但有一些是 4096×4096转换时如果硬编码宽高那一批图会全部标注偏掉。正确做法是用 PIL 或 cv2 读图获取实际宽高或者从 JSON 的img_size字段里读。3.2 训练集与验证集的划分按场景划分而不是随机划分很多项目源码里用train_test_split随机划分数据这在交通标志任务里是个隐患。同一个路口的照片连着拍了几张随机划分会把内容几乎一样的图拆进训练集和验证集模型在验证集上表现很好一到真实道路就拉胯。正确做法是按「场景」划分同一个地点、同一批连续帧的图要绑在一起要么全进训练集要么全进验证集。具体操作上如果数据文件名里带地点编号比如road1_001.jpg、road1_002.jpg就按前缀分组如果没有任何编号就按拍摄时间段把连续 30 分钟内的图归为一组再按组划分。另一个被忽略的点是困难样本要优先放进训练集还是验证集——我建议把模糊、逆光、小尺寸的图更多放进训练集让模型见过更多「坏样本」验证集保留少量困难样本用来检测模型真实水平。划分比例上按组划分后常见做法是训练集 80%、验证集 20%。如果数据量很少低于 1000 张建议用 K 折交叉验证来确认模型稳定性但 K 折训练时间长中间阶段可以先跑一次单划分确认代码链路没问题最后再上 K 折。# 按文件名的场景前缀分组避免同一场景的数据横跨训练集和验证集 import os import random from collections import defaultdict image_dir images groups defaultdict(list) # 假设文件名格式为 scene001_0001.jpg按 scene001 分组 for fname in os.listdir(image_dir): if fname.endswith(.jpg): scene_id fname.split(_)[0] groups[scene_id].append(fname) scene_ids list(groups.keys()) random.shuffle(scene_ids) # 80% 的场景进训练集20% 进验证集 split_idx int(len(scene_ids) * 0.8) train_scenes set(scene_ids[:split_idx]) with open(train.txt, w) as f: for scene in train_scenes: for fname in groups[scene]: f.write(os.path.join(image_dir, fname) \n)这段脚本比直接random.shuffle(所有图片)多做的事就是保证同一个场景 ID 下的所有图片被整体分配到同一侧。参数说明里最关键的是split_idx它决定验证集大小如果验证集图片太少少于 50 张评估指标的方差会很大建议调低训练比例到 70% 来增加验证集样本。等后续数据积累多了再逐步调回 90/10。3.3 数据增强交通标志场景的增强策略与两个禁忌数据增强是对抗数据量不足的核心手段但交通标志有自己的特殊性。颜色是核心特征标志牌的红、蓝、黄是强语义信息所以颜色抖动增强亮度、对比度、饱和度可以有但幅度不能大——把红色调成橙色模型学到的颜色特征就歪了。几何增强方面水平翻转要慎用倒过来的限速牌没意义但「禁止左转」水平翻转后变成「禁止右转」类别语义完全变了。所以交通标志任务里mosaic 和 mixup 这类大尺度增强可以用在检测阶段但分类阶段的增强要克制。有效且安全的增强包括小角度旋转±15度以内、轻微缩放0.8 到 1.2 倍、高斯模糊模拟远距离、随机遮挡模拟被树枝挡住的场景。这些增强模拟的是真实拍摄中会出现的物理退化不会改变标志牌的语义。下面是一个适合分类小图的增强配置片段供参考import albumentations as A # albumentations 是比 torchvision.transforms 更适用于检测/分割的增强库 transform A.Compose([ A.Rotate(limit15, border_mode0), # 小角度旋转不超出标志牌语义范围 A.RandomScale(scale_limit0.2), # 缩放 0.8~1.2 倍模拟远近距离 A.RandomBrightnessContrast(p0.5), # 亮度对比度抖动幅度适中 A.GaussianBlur(blur_limit(3, 5), p0.3), # 偶尔加模糊模拟失焦 A.RandomSunFlare(p0.05), # 少量加入逆光光斑模拟太阳直射 ])这段配置的思路是「每个增强单独出现的概率不高组合起来模拟真实退化」。参数说明limit15是旋转的度数上限15 度之内人类仍能识别标志语义超过 20 度模型的感受野就开始错乱scale_limit0.2控制缩放的幅度缩太小会让小目标直接缩小到 20 像素以下检测器直接漏掉blur_limit(3, 5)是高斯核的大小核越大越模糊但交通标志本身是印刷体图案过度模糊会把数字细节抹掉核不超过 5 比较安全。上面没写水平翻转这属于「主动不去做」的增强就是前面提到的语义翻转问题。4. 跑通训练链路从最小命令到可用模型你需要盯住哪些环节4.1 用 YOLO 在本地跑通交通标志训练的最小命令假设你拿到的是 YOLOv5 或类似结构的项目源码训练入口是train.py。第一次跑通全流程不要一上来追求精度先确认代码链路没有断。最小命令长这样python train.py --data traffic_sign.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 50 --device 0这个命令的含义--data指定数据配置文件里面写清楚 train.txt、val.txt 的路径和类别数量--weights表示用 COCO 预训练权重做迁移学习初始化比从头训练收敛快得多--img 640是输入分辨率训练和验证阶段都会把图缩放到这个尺寸--batch 16是每轮迭代的样本数--device 0指定用第一块 GPU没有 GPU 就改成--device cpu。先跑 10 个 epoch重点看两个输出一是 loss 是否在下降二是每个 epoch 结束后的 mAP0.5 是否从 0 开始上涨。如果这两个指标动都不动不要调参先查数据链路——打开训练日志里的 sample 图看标注框是不是画在了正确的位置上。这个检查步骤比任何调参都重要。如果包里的训练脚本不是 YOLOv5 而是自定义模型那就读一下train.py里的argparse部分看它定义了哪些可配参数换汤不换药路径、batch、epochs 这三个基本跑不掉。跑通后把模型保存路径通常在runs/train/exp/weights/best.pt记下来后面推理要用。4.2 决定精度的四个超参数与验证阶段的必看指标新手最大的误区是把 epochs 调到最大就撒手不管。对交通标志这个小目标场景真正需要盯的是输入分辨率、anchor 尺寸、类别不平衡处理、置信度阈值。先说输入分辨率--img从 640 降到 416训练速度快一半但小目标检测能力显著下降升到 1280 对小目标友好但显存需求翻四倍。交通标志在画面中占比小我一般建议至少 640 起步有显卡条件就上 960。anchor 尺寸是 YOLO 系列里最容易被忽略的选项。YOLO 默认的 anchor 是针对 COCO 数据集设计的COCO 里目标普遍大而交通标志很碎。YOLOv5 提供了自动anchor 功能训练时会根据你的标注框尺寸重新聚类确保 anchor 和你的数据匹配。在 YOLOv5 里这是默认开启的但在其他框架里可能是关闭的需要手动算。类别不平衡方面TT100K 里限速牌数量远大于施工牌训练时模型会把所有目标都预测成限速牌。解法之一是调整每个类别的 loss 权重在数据配置文件里给少数类设更高的权重。验证阶段不要只看 mAP 这个综合指标把每一类的 Precision 和 Recall 单独打出来看——少数类如果 Recall 低于 0.5说明模型基本没学会这一类这时候加数据比加训练轮数更有效。# YOLOv5 自带的验证脚本输出每个类别的详细指标 python val.py --data traffic_sign.yaml --weights runs/train/exp/weights/best.pt --img 640 --conf-thres 0.4 --iou-thres 0.5这个命令解析--conf-thres 0.4是置信度阈值低于 0.4 的预测框会被丢弃调高它 Precision 升 Recall 降调低则相反--iou-thres 0.5是 NMS 的 IoU 阈值评估预测框和真实框是否匹配用0.5 是标准选择。跑完看每个类别的列重点找那些 AP 值明显低于平均值的类别那就是后续要补数据的方向。4.3 从训练权重到可部署模型导出中间表示与固定输入尺寸训练完的best.pt只能在 PyTorch 环境里用要落地到其他推理框架比如带硬件加速的推理引擎、或者嵌入式设备需要导出成 ONNX 格式。这一步在源码包里通常有export.py文件命令如下python export.py --weights runs/train/exp/weights/best.pt --img 640 --include onnx导出后得到一个best.onnx文件这个格式是通用中间表示可以用 ONNX Runtime 或 TensorRT 加载推理。导出时注意两点一是--img 640要和训练时一致ONNX 文件会固定住输入张量的尺寸后续推理图会先缩放到 640×640 再喂进去二是导出后务必用onnxruntime跑一次推理确认输出数值和 PyTorch 原模型在同一个量级排除导出过程精度损失。如果这个包里有模型的推理脚本通常长这样import onnxruntime as ort import cv2 import numpy as np # 创建 ONNX 推理会话 sess ort.InferenceSession(best.onnx, providers[CUDAExecutionProvider, CPUExecutionProvider]) def infer(image): # 输入预处理缩放、归一化、转通道顺序 img cv2.resize(image, (640, 640)) img img[:, :, ::-1].transpose(2, 0, 1) # BGR转RGBHWC转CHW img img.astype(np.float32) / 255.0 inputs {sess.get_inputs()[0].name: np.expand_dims(img, axis0)} outputs sess.run(None, inputs) return outputs这段代码展示了推理侧最常见的预处理三件套resize 到固定尺寸、BGR 转 RGB、归一化到 0~1。参数说明里最容易出错的是img[:, :, ::-1]——OpenCV 读图默认是 BGR 通道顺序而 PyTorch 和 ONNX 模型训练时用的是 RGB不转换的话模型看到的颜色通道全错了检测框会乱飘。providers参数决定优先用 GPU 还是 CPU如果机器没有 GPU运行时会把CUDAExecutionProvider这行忽略自动落到 CPU 上不影响流程。浮点精度这块导出 ONNX 默认是 FP32如果你的部署环境支持 FP16可以在导出命令加--half推理速度能提升但有些小目标检测场景精度损失明显需实测对比。5. 避坑指南训练与部署时最常见的五类翻车现场5.1 现象loss 一直在降但验证集 mAP 纹丝不动原因过拟合发生得过早模型把所有训练图的背景记住了标志牌本身反而没学到。交通标志数据常常来自固定路段的截图背景高度相似同一条路、同一个路牌、同一片绿化带模型直接通过背景判断类别一到新场景就失效。解决首先检查训练集和验证集是不是按场景划分的上一章那个分组脚本就是为此设计的其次加大数据增强的力度特别是随机缩放和模糊最后回到标注质量本身打开几张训练图看标注框有没有框偏。迁移学习在这种场景下特别有效用 COCO 权重初始化能帮模型更快学到通用特征而不是从零开始学背景。5.2 现象训练时报错 AssertionError: Label class x exceeds nc...原因数据转换时类别 ID 超出了模型配置文件里的类别总数。比如模型配置文件只定义了 10 类但 txt 标注文件里出现了类别 ID 为 11 的行。通常是转换脚本里 CLASS_MAPPING 配置错误或者某些标注框漏配了映射导致默认值溢出。解决写一个检查脚本遍历所有 label 文件打印出现过的类别 ID 集合与配置文件里的nc参数对比。同时检查是否有空的 txt 文件——YOLO 训练时遇到无目标的 label 文件会跳过但如果整个类别从训练集中消失了模型就永远学不会那个类别。注意类别 ID 必须从 0 开始连续编号中间断层比如只有 0、1、3没有 2也会让训练报错。5.3 现象用小图测试模型一切正常但一到视频就框乱跳原因视频帧里的标志牌是连续的但模型在相邻帧里对同一个目标的检测框位置不稳定看起来像是框在抖。这通常不是模型的问题而是置信度阈值设置太低把背景噪声也当成了目标或者 NMS 的 IoU 阈值偏高导致同一目标产生多个重叠框。解决把置信度阈值从 0.25 逐步提高到 0.5观察验证集 mAP 变化——阈值提高误检减少但 Recall 会降需要找到一个平衡点。另外检查 NMS 参数YOLO 系列默认iou-thres是 0.45如果发现同一目标同时出现两个框调低到 0.4 试试。还有一个进阶手法使用帧间平滑对连续帧的检测框做加权平均但这类逻辑要在推理脚本里自己实现源码包里不一定有。5.4 现象在 GPU 上训练好换到 CPU 推理时报 RuntimeError: Attempting to deserialize object on a CUDA device原因训练时的模型参数保存在 GPU 显存上torch.load默认会按保存时的设备加载CPU 机器上没有 CUDA于是报错。这个是 PyTorch 新手最容易撞的墙任何从别人那拷贝或用显卡训练过的模型都会遇到。解决加载权重时显式指定map_locationcpu这就是第 2 章那个检查脚本里写的参数。如果源码里的推理脚本没有加这个参数在torch.load那一行的括号里补上即可。另一个相关坑是训练脚本里用了model.cuda()但没有做if torch.cuda.is_available()判断换机器跑直接崩把.cuda()调用都换成model.to(device)并且device由参数控制一劳永逸。5.5 现象视频检测时输入大图会漏检小标志但 resize 后检测又会把标志牌拉变形原因视频流通常分辨率高1080P 甚至 4K直接缩放 640 会让标志牌缩到十几个像素模型特征根本提不出来如果按原始分辨率喂给模型又超出了模型设计时的输入限制性能下降。这是交通标志小目标检测的经典矛盾。解决在推理脚本里做「切片 缩放」。把 1080P 画面切成左右两半每半分别缩放到 640 再推理检测框坐标最后映射回原图坐标。这样做计算量翻倍但小目标的召回率能提升一个档次。如果你的场景允许牺牲实时性优先试这个方案不要盲目改模型结构——网络架构的改动牵一发而动全身新手容易改崩。6. 让模型在真实场景更稳验证脚本的写法与一个值得投入的进阶技巧训练完的模型能不能上车不能只看验证集指标要在真实视频上跑一遍才知道。我建议为这个项目单独写一个 walk-through 脚本读取一段连续拍摄的行车记录仪视频逐帧推理输出每帧的检测结果和置信度最后统计出「漏检率」和「平均单帧推理耗时」。漏检率的定义是人工数出视频里共有多少个标志牌模型检出了其中多少个。这个脚本不难写价值在于它能暴露出验证集上发现不了的问题比如某些角度的标志牌永远检不到或者某些非标志牌物体反复触发误检。进阶方向里最值得投入的是类别层面重新平衡。交通标志的长尾分布极其严重限速牌到处都是施工牌和辅助牌占比很小。有两个做法一是收集更多少数类图片哪怕只有几百张单独做分类训练也比整体重训效果好二是用重采样策略训练时对少数类样本以更高概率重复采样。第二个做法只需在数据加载器里改几行代码成本低收益明显。最后分享一个习惯每个模型训练完我会另外用一个固定视频片段做回归测试。这个视频从不参与训练里面包含了不同天气、不同时段的画面每次改动模型或数据后都跑一遍拿检测结果和上一次比较。这套流程相当于给模型做的「体检」能第一时间发现改动是否引入回归。交通标志检测从训练到上线没有一劳永逸但有了可复用的验证方法每一步改动都心里有底。这个方向值不值得投入答案是值得——它是自动驾驶感知里最成熟、最可独立验证的模块之一也是从纯调参走向工程部署的绝佳跳板。希望帮到你。提示如果拿到的包里没有现成的验证视频用小车的行车记录仪拍一段 3 分钟的城市道路即可注意包含十字路口、桥梁、隧道三个典型场景这段视频以后就是你的标准测试集。本文还有配套的精品资源点击获取
返回列表