ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

基于深度学习的交通标志与行人车辆识别系统实战指南

基于深度学习的交通标志与行人车辆识别系统实战指南 简介深度学习目标检测是计算机视觉领域的核心方向之一而YOLO作为单阶段检测器的代表凭借其端到端的回归设计和出色的实时性能成为交通场景感知任务中的主流方案。交通标志、行人与车辆的同步识别本质上是一个多类别、多尺度的小目标检测问题尤其交通标志的像素占比极小对模型的特征提取能力提出了更高要求。从公开数据集的选取与格式转换到YOLOv8的训练参数调优、小目标专项优化再到推理脚本与演示界面的搭建完整链路中每一步都影响最终效果。本文基于YOLO生态系统梳理了从环境配置到模型改进的工程实践并结合注意力机制、损失函数调整等常见优化思路为毕业设计、课设及入门实战提供可复用的方法参考帮助开发者快速搭建一套具备实时检测能力的交通标志与行人车辆识别系统。 每到毕业设计开题季“基于深度学习YOLO的交通标志与行人车辆识别系统”就成了出镜率极高的选题。我前前后后带过不少学弟学妹做这个方向也帮人调过不少跑不起来的代码最大的感受是这个课题的起点很低——网上教程多、YOLO生态成熟、可视化效果好但想从“能跑通官方demo”走到“答辩时能讲清楚、能拿得出手”中间的坑比想象中多。所以这篇文章我想把做这个系统的完整链路拆开讲一遍从环境搭建、数据集处理、模型训练到最后的界面展示和答辩准备把每一处关键选择的“为什么”也一起说清楚。适合正在准备毕设、课设或者想入门目标检测实战的同学参考。1. 动手写代码前先盘清楚这个课题真正的难点在哪1.1 这套系统到底要解决什么问题从功能上讲这套系统做的是三件事给定一张图片、一段视频或者一路摄像头画面模型要能实时标出“交通标志在哪里、是什么类型”“行人站在哪里”“车辆出现在哪里”并给出边界框和置信度。听起来很直观但如果把需求拆开你会发现它不是一个单纯的目标检测任务而是三个子任务的叠加。交通标志识别是其中最有区分度的一部分。和行人、车辆这种“大类目标”不同交通标志的类别非常多国内常见的就有禁令标志、警告标志、指示标志几大类每类下面还有几十种具体标志。更麻烦的是路口的标志在画面里往往很小可能只有几十个像素这种“小目标检测”问题恰好是深度学习模型最容易翻车的场景。行人车辆检测相对成熟但也有自己的难点行人姿态变化大遮挡严重车辆类别下还有轿车、公交车、卡车、摩托车之分不同车型外观差异很大光照和天气变化也会显著影响检测效果。所以这个课题虽然被归为“入门级毕设”但它真正考察的是你有没有能力把多个检测需求整合到一套系统里并针对不同目标的特性做取舍。答辩老师问得最多的往往不是“你用了什么模型”而是“你为交通标志这个小目标问题做了什么”这个问题如果答不上来代码写得再漂亮也容易扣分。我在后面第四章会专门讲小目标场景下的训练策略这是整套系统能不能拉开档次的关键。1.2 三类目标的技术指标怎么定在项目一开始建议先把技术指标想清楚不然训练的时候会反复摇摆。我习惯用下面这个表格来梳理需求也方便后面写进论文。目标类型检测难点可接受的最低精度mAP50关注指标交通标志目标尺寸小、类别多、部分类别样本少0.75以上小目标召回率行人遮挡、姿态变化、密集场景0.80以上漏检率车辆车型多样、夜间/逆光0.85以上误检率这几项指标不是拍脑袋定的是基于一般公开数据集上的可达到水平。比如TT100K交通标志数据集上YOLOv8s做到0.75的mAP50属于正常发挥BDD100K的行人车辆检测YOLOv8s做到0.8以上也不难。如果你的数据是自己采集的、标注不太规范可以把指标适当放宽一些否则训练时天天被Loss曲线折磨。1.3 为什么“几乎一定”要选YOLO这个问题几乎每个答辩老师都会问也是你写开题报告时就得回答的问题。YOLO是单阶段检测器它把目标检测当作一个回归问题一次前向推理同时输出目标的类别和位置。相比Faster R-CNN这种两阶段检测器YOLO最大的优势是速度快适合实时场景——我们要做的交通监控、驾驶辅助场景FPS至少得在20以上才谈得上“可用”。而且YOLO的生态在目标检测里是最成熟的。从YOLOv5开始Ultralytics把训练、验证、导出封装得非常好一个yolo train命令就能跑起来这对毕设课设来说意味着可以省下大量调框架的时间把精力放在数据优化和模型改进上。至于“用YOLOv5还是YOLOv8还是YOLO11”我的建议是优先用YOLOv8或更新的官方版本因为Ultralytics对v8的维护最稳定资料多遇到bug更容易搜到解决方案。v5和v8的核心逻辑差异不大你只要会了v8的接口v5也能快速上手。还有一点你答辩时可以提YOLO“单阶段检测Anchor-Free”的设计在工程上更简洁部署到边缘设备也更容易。这个理由加上实测FPS数据基本就能把“为什么选YOLO”这个问题答圆。2. 环境搭建不折腾选对版本组合能少走三天弯路2.1 硬件要求和没有GPU的备选方案先说硬件。训练YOLOv8s这种规模的模型最低要求是6GB显存8GB以上用起来比较从容。我的建议是优先用yolov8n和yolov8s这两个尺寸它们在显存占用和精度之间最平衡。如果电脑是4GB显存的GTX 1650这种也不是不能用但batch size会被压到4以下训练速度会比较感人。如果你完全没有GPU我这里说几个实际可行的路径一个是Google Colab免费版需要注意网络环境和文件持久化的问题一个是AutoDL这类云GPU平台按小时计费性价比很高学生认证还有折扣。我教过几个学妹用云平台训练两三百块就能完成一个毕设级别模型的全部训练和验证比自己在本地用CPU硬跑节省几十个小时。操作系统方面Windows和Ubuntu都行。Windows下用Ultralytics的pip包基本零门槛但如果你要编译自定义算子或者跑TensorRT部署还是Ubuntu更省心。我的习惯是纯训练调试用Windows涉及部署优化再开Ubuntu或连远程Linux服务器。2.2 使用Ultralytics包还是clone原版仓库这里有一个很实际的选型问题。YOLOv5有官方仓库YOLOv8被Ultralytics做成了pip包。毕设课设场景下我强烈推荐用Ultralytics的pip包也就是ultralytics这个库。原因是官方仓库的代码结构更底层适合改网络结构做研究但你要应付的是“快速迭代稳定出结果”pip包开箱即用而且同一个接口同时支持检测、分割、分类写起来非常顺手。如果你后面要改模型结构比如加注意力模块也是基于pip包在模型配置层面去做而不是改底层C代码。具体做法我在第六章会提到。2.3 一次到位的环境配置步骤下面这套流程我复现过很多次按顺序执行基本不会出问题。先装Anaconda然后创建虚拟环境conda create -n yolo python3.10 -y conda activate yolo pip install ultralyticsPyTorch的安装要特别注意版本匹配。如果你用的是NVIDIA显卡建议去PyTorch官网用生成的命令安装比如CUDA 11.8对应的命令是pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118装完之后打开Python环境验证一下import torch print(torch.__version__) print(torch.cuda.is_available())torch.cuda.is_available()输出True才说明PyTorch能用上GPU。我遇到过很多次的情况是torch.cuda.is_available()为False原因大多是环境里装了一个CPU版的torch或者CUDA驱动版本太低。这时候不要急着重装先看nvidia-smi里的CUDA版本再对照查一下torch的兼容矩阵一般就能定位。然后跑一个最简单的推理测试环境yolo predict modelyolov8n.pt sourcehttps://ultralytics.com/images/bus.jpg能看到一张带检测框的bus图片输出就说明环境已经通了。这个步骤强烈建议第一天就完成很多同学卡在环境上两三天其实都是版本不匹配的问题和代码本身没半点关系。后续训练时如果遇到CUDA out of memory优先降低batch size或换更小的模型而不是加内存。3. “喂”给模型的数据比模型本身更决定上限3.1 公开数据集怎么选TT100K、CCTSDB、BDD100K的取舍交通标志和行人车辆这类数据公开数据集非常丰富但选择时需要动点脑筋。我常用的搭配是交通标志用TT100K腾讯交通标志数据集或CCTSDB长沙理工的交通标志数据集行人车辆用BDD100K或KITTI。数据集内容标注格式适合场景TT100K30000张交通标志图片含45类常见标志COCO/自定义txt交通标志识别CCTSDB国产交通标志含禁令、警告、指示txt交通标志识别BDD100K10万张道路图片含行人、车、交通灯等JSON行人车辆检测KITTI德国道路场景行人车辆为主KITTI标签自动驾驶感知我建议的量是这样的交通标志部分取TT100K的train集里出现频次较高的20类左右每类样本量尽量保持接近然后结合CCTSDB做补充行人车辆部分从BDD100K里抽一部分图片就行不需要全部用否则训练时间会爆炸。总的训练图片量控制在15000到20000张之间比较合适再多的话单张GPU训练时间就得按天算了。3.2 类别体系设计三类任务要统一到同一套类别里这是新手最容易忽视的坑。你拿到TT100K和BDD100K的数据后会发现两个数据集的类别标签体系完全不同TT100K里的类别是i5、pl100、pne这种标志编码BDD100K里的类别是pedestrian、car、truck。直接混在一起训练模型会懵。我的做法是自定义一套类别表比如0: prohibitory 1: warning 2: indicative 3: pedestrian 4: car 5: bus 6: truck 7: motorcycle 8: bicycle交通标志不细分具体图案而是归成三大功能类——禁令、警告、指示。这样既保留了识别意义又避免了“某个具体标志样本太少”的类别不均衡问题。如果你实在想识别具体标志类型那至少保证每个细分类别有200张以上标注图不然模型的mAP会被这些样本少的类别严重拉低。3.3 BDD100K转YOLO格式一个可复用的转换脚本BDD100K默认的标签是JSON格式而YOLO需要的是每张图片对应一个txt文本里面每行是类别 x_center y_center width height数值都是相对图片宽高的比例。很多同学卡在这一步我直接给一个可用的转换脚本骨架import json # BDD100K的标签文件每行一个JSON对象 def bdd2yolo(json_path, out_dir, class_map): with open(json_path, r, encodingutf-8) as f: lines f.readlines() for line in lines: data json.loads(line.strip()) img_name data[name].replace(.jpg, .txt) img_w, img_h data[width], data[height] out_lines [] for label in data[labels]: cat label[category] if cat not in class_map: continue # BDD100K的box格式是[x1, y1, x2, y2] box label[box2d] x1, y1, x2, y2 box[x1], box[y1], box[x2], box[y2] cx (x1 x2) / 2.0 / img_w cy (y1 y2) / 2.0 / img_h bw (x2 - x1) / img_w bh (y2 - y1) / img_h out_lines.append(f{class_map[cat]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) with open(out_dir / img_name, w) as f: f.write(\n.join(out_lines))需要注意JSON里的category是car、pedestrian这样的大类如果你想细分车型得额外处理。转换完成之后还要把图片和标签按images/train、labels/train的目录结构组织好Ultralytics才会认。3.4 数据不够或标注不规范自己补数据时的标注原则公开数据集再全也覆盖不了你毕设可能遇到的特定场景——比如你住在学校附近毕业论文里想体现“校园场景检测能力”那就得自己补充一些数据。用手机或行车记录仪拍一段校园道路视频抽帧成图片再用LabelImg或Roboflow标注即可。标注的原则我总结三条第一遮挡超过50%的目标不要标标了反而教坏模型第二目标小于画面宽度1/50的小目标也要标注这正是你想让模型学会的东西可以专门加强第三同一目标在相邻帧不要重复标太多抽帧时隔几帧标一次就行不然会造成大量冗余训练样本。标注格式建议直接用YOLO格式工具里选择“Save as YOLO”省去后面转换。数据增强方面Ultralytics在训练时默认开启mosaic、HSV扰动、平移旋转等策略。实测下来mosaic对这种多类别混合场景非常有用它能在一张图上拼4张图相当于人为制造了多个目标密集同框的场景模型学到的小目标语义更丰富。这部分基本不需要自己额外写增强代码默认配置就很能打。4. 训练不是无脑跑命令参数背后的取舍逻辑都在这4.1 预训练权重是“站在巨人肩膀上”但不是选了就完事用Ultralytics训练时可以直接指定modelyolov8s.pt它会自动下载COCO预训练权重。COCO数据集有80类虽然里面没有交通标志但有行人、车辆这些和我们的目标高度相关的类别。用这个权重做初始化模型对图像特征的基础提取能力已经很强了我们只需要在新数据集上做微调。这一步对毕设来说几乎必选。从头训练一个YOLO至少需要几十万张数据才可能收敛到可用水平而微调只需要几千上万张就能出效果。模型骨架选哪个我建议根据显存来模型参数量显存占用大概mAP50适合情况YOLOv8n3.2M3GB左右中等显存小、追求速度YOLOv8s11.2M5-6GB较高毕设首选YOLOv8m25.9M8GB以上很高显存充裕、追求指标我自己帮人搭毕设时默认无脑选yolov8s。它比n精度高出一截比m训练时间节省很多对毕设这个体量来说性价比最高。4.2 训练参数怎么调一份可以直接抄的配置以YOLOv8s为例我会这样启动训练yolo train datatraffic.yaml modelyolov8s.pt epochs100 imgsz640 batch16 lr00.01 optimizerSGD解释一下这几个关键参数的选择理由这也是答辩时容易问到的。imgsz640YOLOv8的默认输入尺寸是640正好平衡了精度和速度。有些交通标志很小你可以试imgsz960甚至1280对小目标有肉眼可见的提升但显存占用和训练时间会涨不少。我的建议是先跑一版640作为baseline如果小目标指标不够再专门做一组960的对比实验这本身也可以写进论文。batch16这个值主要受显存限制。batch太小比如4以下训练过程不稳定Loss曲线会抖得很厉害批量翻倍训练时间几乎减半。我一般先看一眼想用的batch是否报OOM如果报就降到8不报就维持16。epochs100很多人问“到底训练多少轮”其实YOLO自带早停机制patience默认是50也就是说如果连续50轮验证集指标没有提升会自动停止。所以你可以直接设150让它在100到130轮左右自然停下。我实测交通标志这类小目标数据一般60-80轮就稳定了。lr00.01配optimizerSGD这两个要一起说。SGD是YOLO训练最稳的优化器配合0.01的初始学习率基本不会翻车。Adam收敛更快但最终精度往往略低而且学习率需要调小到0.001左右。首推SGD理由很简单稳定、好调。4.3 Loss曲线和指标怎么看不能只等训练结束训练启动后Ultralytics会实时打印box_loss、cls_loss、dfl_loss以及各类指标。我通常只看三个东西。第一是训练loss和验证loss的收敛曲线两者都持续下降说明模型在正常学如果验证loss先降后升说明过拟合了这时候把weight_decay从0.0005调到0.001或者加一点dropoutYOLO的配置里可以改dropout参数都会有帮助。第二是mAP50和mAP50-95。mAP50是IoU阈值0.5下的平均精度适合快速评估mAP50-95更严格是多个IoU阈值的平均论文里也比较认这个指标。交通标志小目标多mAP50-95偏低是正常的答辩时可以拿小目标理论来解释。第三是类别不均衡的体现。训练结束会生成results.png里面有混淆矩阵和PR曲线。如果发现某个类别准确率明显低多半是样本太少回去补数据比换模型更有效。这里分享一个我实际遇到过的坑有次帮学弟调参数他数据集里car占了70%warning标志只有200张训练完car的mAP50是0.92warning只有0.31。给他补了600张warning的标注数据后直接涨到0.63。所以说当某个类指标崩了先看样本量别急着换模型结构。4.4 小目标场景的专项调优技巧交通标志识别是这个系统的灵魂所以小目标优化值得单独拿出来讲。除了上面提到的调大imgsz之外还有三个非常实用的招数。一个是关闭或降低mosaic的mixup概率。mosaic对中等目标效果好但对小目标有时候反而有害因为4张图拼起来之后小目标会变得更小模型根本看不清。我一般把mosaic设成0.8保留大部分增强能力同时减轻小目标被缩小的问题。第二个是调整anchor。虽然YOLOv8是anchor-free不需要手动设anchor但对小目标密集的场景可以增加检测器在小特征图上的感受野这需要改模型结构对毕设来说工程量大。更简单的做法是用tune模式yolo tune modelyolov8s.pt datatraffic.yaml epochs30它会在一定迭代次数内自动搜索最优超参组合虽然跑起来慢但能帮你找到一组针对自己数据集的增强参数比自己手调靠谱。第三个是推理时启用TTATest-Time Augmentation也就是在预测时对图片做多尺度、翻转等变换再综合结果对小目标有明显提升。代价是速度变慢。如果要实时就别开如果做离线检测可以开。具体接口是yolo predict modelbest.pt sourcetest_imgs/ augmentTrue5. 把检测结果做成“能演示”的系统展示层是毕设答辩的加分项5.1 写一个自己的推理脚本别只调控制台命令训练完best.pt之后很多同学直接拿官方predict命令输出结果确实省事但答辩时导师让你现场演示或者换个数据看时你会发现控制台命令的可定制性太弱了。我建议花半天时间写一个自己的推理脚本既能加深理解后面演示也更灵活。下面是我常用的一套关键代码框架import cv2 from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) def detect_image(img_path, conf0.4): img cv2.imread(img_path) results model(img, confconf, verboseFalse) for r in results: boxes r.boxes for box in boxes: x1, y1, x2, y2 map(int, box.xyxy[0]) conf_val float(box.conf[0]) cls_id int(box.cls[0]) label f{model.names[cls_id]} {conf_val:.2f} cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) return imgconf这里默认设0.4演示时可以现场调低到0.25看召回率提升调高看精确率提升这是个很好的答辩互动点。视频处理也一样只需要用cv2.VideoCapture读帧逐帧调用上面的检测逻辑再把结果写入VideoWriter。实测时留意一下FPS把数字打到显示画面上。写一句话cv2.putText(img, fFPS: {fps:.1f}, ...)就够了。这个数字对答辩极其重要老师会直观地认可“系统是实时的”。5.2 用Gradio三分钟做个演示界面如果你不想写复杂的GUIGradio是最快的路子。它只需要十几行代码就能在浏览器里跑一个上传图片/视频进行检测的界面。代码大致是这样import gradio as gr from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) def inference(img): results model(img) return results[0].plot() gr.Interface( fninference, inputsgr.Image(typenumpy), outputsgr.Image(typenumpy), title交通标志与行人车辆识别系统 ).launch()运行后浏览器会打开一个本地页面拖入一张图片就能看到检测结果。这套界面虽然简单但在毕设现场演示时比在黑框框里敲命令要直观得多。你可以进一步接上摄像头实时画面用gr.Video或OpenCV的摄像头抽帧配合Gradio的队列更新做一个“摄像头实时检测”页面。这个效果在答辩现场非常加分。5.3 检测结果落盘论文里的图表从哪来除了界面演示最后还要把检测结果系统化地保存下来。我一般会让程序同时输出三类东西第一检测结果图片和视频挑若干张典型的放置到论文“实验结果”章节第二检测日志CSV记录每帧检测到哪些物体、置信度、耗时方便统计分析第三统计表比如检测到行人的总数、识别出的各类标志数量这些数据可以做成柱状图放进论文。这一步看起来简单但很多同学忽略导致论文写完才发现没有过程数据可用。我的建议是训练一结束就写一个批量检测脚本把测试集几百张图片全部跑一遍结果统一保存到文件夹顺便生成一个汇总表格。后面写论文时你会发现这步省了太多事。6. 想拿“优秀毕设”改进方向、对比实验和答辩准备6.1 最容易落地且不容易翻车的改进方向一套基础的YOLOv8s检测系统拿到“通过”几乎是必然的但如果想冲击优秀需要一些“你自己的工作”而不是纯套用。我看了很多同学的做法比较推荐并且比较容易出效果的有三个方向。第一个是给Backbone加注意力模块比如SE、CBAM或者CACoordinate Attention。原理很简单注意力模块能让模型在特征提取时更关注“哪里是要检测的目标”对交通标志这种小目标效果尤其明显。在Ultralytics的模型配置里加注意力模块需要改cfg/models/v8/yolov8.yaml在网络层的合适位置插入- [SE, [16]]这样的配置块或者直接改ultralytics.nn.modules里的基础模块。这个改动相对独立不太会影响原有逻辑比较可控。第二个是修改损失函数。YOLOv8默认用CIoU作为回归损失你可以把它换成EIoU或SIoU对小目标边界框回归有一定改善。EIoU在候选框宽高比不匹配时梯度更稳定代码改动只需在loss.py里替换IoU计算函数难度不大。第三个是知识蒸馏。用大模型yolov8m或x当teacher小模型yolov8n或s当student让小模型学大模型的输出通常能带来2-3个点的mAP提升。这个方向概念新、讲起来有深度代码上可以用Ultralytics自带的蒸馏辅助或自己写一个简单的logit蒸馏loss工作量适中。这三个方向任选其一加一组“baseline vs 改进后”的对比实验论文的“创新点”章节就不愁没内容写了。注意改进不能贪多改一个模块就做一轮对比实验不然最后无法定位是哪个改动起了作用。6.2 对比实验怎么设计才能说服答辩老师改进效果要靠数据说话。我的实验设计思路是固定训练数据和参数只改变要对比的变量。比如你加了CBAM那就跑两组第一组用标准yolov8s第二组在同样数据下用加CBAM的yolov8s其他参数完全一致。最后把两组模型的mAP50、mAP50-95、精确率、召回率、FPS放进一张表格。表格设计可以参考这样模型mAP50mAP50-95参数量推理耗时YOLOv8s baseline0.8120.58711.2M8.3msYOLOv8s CBAM0.8310.60211.8M9.1msYOLOv8s EIoU0.8260.59611.2M8.4ms答辩时这份表格往屏幕上一放不用多解释老师就知道你做的是实打实的对比实验。另外强烈建议把PR曲线和混淆矩阵的图放进PPT。PR曲线能展示模型在阈值变化下的整体表现混淆矩阵能直观看到哪些类容易混淆——比如“禁令标志”和“警告标志”如果互相分错老师会知道这个模型还有哪些改进空间这本身就是讨论话题。6.3 答辩常见问题怎么回应最后分享几个答辩高频问题和回应思路都是我陪同学模拟答辩时总结的。“你用的数据集有多大为什么不用更大的”——回答思路说明毕设时间精力有限15k张图片已经能覆盖主要场景同时展示了数据集类别分布统计说明关键类别样本均衡后续可以补充数据持续提升。“你的系统在夜间或者雨雾天效果怎么样”——这个问题几乎必问。如果你测试集里有夜间图片直接展示夜间检测效果图如果没有就坦言模型在夜间性能会下降并提出后续可用图像增强、域自适应等方向改进。诚实比硬撑得分更高。“YOLO和其他检测器的区别”——前面讲过突出单阶段、速度快、适合实时场景再补充一句如果追求极致精度可以尝试两阶段检测器但实时性不足。“你自己的贡献是什么”——这条最重要很多同学答不上来。你要明确说第一完成了多源数据集的整合和统一标注体系第二针对交通标志小目标问题做了数据增强和推理阶段的优化第三搭建了可交互的实时检测演示系统。三条足够撑起一篇毕设的核心工作量了。这个项目我前后带过不少同学做下来最大的感触是它的上限其实比很多人认为的“毕设标配”要高得多。你只要愿意花时间把数据集处理做扎实、把训练参数调明白、把展示界面做得像个产品它就完全可以成为简历上一个拿得出手的深度学习实战项目。最后再分享一个小技巧训练结束后把测试集里检测失败、漏检、误检的图片单独挑出来建一个文件夹反复看这些失败案例比单纯追求mAP数字更能理解模型的真实能力也更容易找到下一步的改进灵感。本文还有配套的精品资源点击获取
返回列表