资讯动态

基于YOLOv8的智慧交通闯红灯检测全流程:小目标与类别区分优化

发布时间:2026/10/20 4:35:40 来源:尧图企业网站定制
做智慧交通项目尤其是“车辆闯红灯检测”这类需求多数人的第一反应是这不就是个目标检测嘛。真把路口数据拉出来开始训练之后才发现难点根本不在“认出那是一辆车”而在认出“远处驶来的一辆小车”、区分“红灯和绿灯”、再把信号灯状态、车辆位置、停止线这几样信息放进同一个逻辑里做违章判定。我基于 YOLOv8 完整做过一套智慧交通场景下的车辆闯红灯目标检测训练流程涉及数据集组织、小目标优化和类别区分策略这篇文章把全链路拆开讲。适合已经能跑通 YOLO 基础训练、想往交通违规检测方向落地的开发者尤其是正在被小目标和红绿灯误检折磨的朋友。1. 智慧交通闯红灯检测为什么是 YOLOv81.1 任务拆解不是“检测车”那么简单闯红灯检测从来不是单模型识别任务。真正要上线视觉模型只是其中一环信号灯状态要从画面里识别出来车辆要被框出来并跟踪停止线和斑马线用于判断车辆是否越过路口边界。只有这些信息叠加在一起才能判定一次闯红灯事件。从视觉感知的角度看YOLOv8 要输出的目标类别至少有这些红灯、绿灯、黄灯、车辆可细分小车、公交车、货车、摩托车、停止线。这里的“类别区分”包含两层第一层是不同目标类型的区分比如信号灯和车辆第二层是同类目标不同状态之间的区分——红灯和绿灯在形状上几乎一样只是颜色通道不同远处灯光只有几个像素时端到端网络很容易学混。还有一个容易被忽视的潜在需求违章取证的可解释性。取证图片要求能看到红灯亮着、车辆越过停止线所以模型输出的不仅是 bbox还要支撑规则引擎去核对时间线。如果模型把绿灯下正常通行的车辆框出来业务方看到的直接就是“绿灯车被标成闯红灯”项目基本就黄了。也是因为这个原因我反复强调宁可召回低一点也要把红灯状态判准把类别混淆压下去。1.2 为什么选 YOLOv8 而不是其他方案我用 YOLOv8 的原因可以归纳成四点。第一anchor-free 检测头让小目标训练更直接少了一层 anchor 匹配的麻烦第二ultralytics 的训练、验证、导出链路完整后续转 ONNX、TensorRT 再落到边缘设备都很顺第三n/s/m/l/x 模型家族伸缩性很强demo 用 s边缘盒子可以用 m 甚至 n选型空间大第四社区资料多遇到问题好排查不会卡在一个框架私有坑里出不来。当然 YOLOv8 不是万能的。交通场景里的“小目标”和“类间相似”恰好是通用检测的通病模型结构本身并不能自动解决。最终效果好不好六分在数据三分在分辨率与训练策略一分在模型结构调整。下面我会把这几层分别拆开讲清楚。1.3 智慧交通场景的独有约束固定视角是交通场景最大的先验摄像头安装高度、角度基本不变车辆朝向相对规律这比随机开放场景的检测容易不少。但约束也很明显夜晚、逆光、过曝、雨雪、摄像头白平衡不一致每一个都能让模型翻车。另外真实路口视频涉及隐私数据必须脱敏车牌和人脸都要模糊处理只能在受控环境内训练。单帧检测同样不够用。路口信号灯变化有固定时序车辆闯红灯是连续几帧内发生的事最终判决最好用多帧结果投票。所以我在项目里会把 YOLOv8 的输出喂给跟踪器和规则判断模块而不是拿单帧置信度直接拍板。这一点和很多公开 demo 不一样却恰恰是能不能落地的关键。2. 数据集构建与标注规范决定模型天花板2.1 数据来源与合规处理数据来源通常有三种真实路口数据、公开数据集、合成数据。真实数据最接近部署场景但需要经过严格的脱敏处理公开数据可以补充类别平衡性但相机安装角度差异大最好只做预训练或少量微调合成数据针对小目标样本特别有用——用渲染工具模拟远距离信号灯和车辆能补充大量难例。对红灯状态识别来说合成数据可以人为控制光照和距离是提升小目标分类性价比最高的方式。样本覆盖也要分层。不能只拿下午两点的视频训练白天、夜晚、雨天、逆光、过曝最好都按比例覆盖。摄像头安装位置不统一时每条数据最好记一下相机ID方便后续发现“某个相机表现特别差”的问题时回溯。2.2 类别定义一定要克制类别定义要克制不是越细越好。我常用的是这套red_light / green_light / yellow_light信号灯状态按颜色分car / bus / truck / motorcycle车辆类别按业务需求合并stop_line停止线可选千万不要设“闯红灯车辆”这个类别。闯红灯是事件不是静态物体单帧图像里模型不可能可靠判断“这辆车正在闯红灯”。正确做法是输出要素让规则引擎判断。有些公开数据里有“闯红灯”标注那是视频片段级别的人工事件标注直接拿来做目标检测类别会非常乱。类别数量也要控制。智慧交通画面里信号灯和车辆的尺度差异巨大类别越多分类头在小目标上的压力越大。能合并的类别尽量合并比如小轿车和 SUV 在交管业务里往往不需要分开统一成 car 反而能减少类内差异提升小目标召回。2.3 标注细节与质检标注是“小目标类别区分”问题的第一道关卡。红绿灯小目标往往只有 8~12 像素多标几像素少标几像素对 IoU 影响非常大。我的经验是bbox 要紧贴灯体亮起区域而不是框整个灯盘如果模型需要分颜色灯盘暗色部分对识别反而是噪声。停止线是细长目标整段框会引入大量背景建议按可见断段标注。车辆遮挡超过一半就不标只标完整可见的车。标完之后必须做类别混淆抽检红灯被标成绿灯、车辆尾灯被标成红灯都是重点核查对象。建议最后统计每个类别的目标尺寸分布。一个小脚本就能看出哪些类别主要落在 32×32 以下哪些主要落在 300×300 以上。如果红灯、绿灯几乎全在小目标区间后续所有优化都要优先针对这个区间做而不是盯着整体 mAP。2.4 数据增强不要无脑套默认增强策略不能默认全开。Mosaic、随机透视、亮度扰动都可以用但有两个坑一是不要对 HSV 的 H 通道做大幅度扰动否则红灯和绿灯的色相会互相污染二是 mixup 在红绿灯分类任务上建议谨慎它会混合出“红绿之间”的奇怪像素让分类头学出问题。小目标样本少推荐复制粘贴增强把真实小目标抠出来贴到不同背景的路口图像上并做多尺度缩放。这不改变图像语义又能把远处小车的数量快速提上来。同时可以按场景分层抽样白天、夜晚、雨天、逆光各占一定比例避免模型被白天样本带偏到晚上就崩。负样本也要进训练集。没有信号灯的路口、绿灯放行的车辆、红灯但是远处无车的画面都要作为背景出现。目标检测模型的误检往往不是因为正样本不够而是因为背景负样本没见过。3. YOLOv8 训练实操与参数调优3.1 目录结构、标注格式与 dataset.yaml训练前准备经常被忽略但格式错了基本白费。YOLOv8 的 label 是归一化格式类别索引 中心点 x/y 宽高全部归一化到 0~1。目录结构建议这样traffic_dataset/ images/ train/ val/ labels/ train/ val/dataset.yaml 配置如下path: ./traffic_dataset train: images/train val: images/val nc: 6 names: [red_light, green_light, yellow_light, car, bus, truck]建议使用绝对路径或者在固定的项目目录下运行避免和 ultralytics 默认设置冲突导致数据集加载失败。3.2 模型选型、分辨率与关键参数模型优先选 YOLOv8s 或 m。YOLOv8n 在小目标上的特征表达能力有限l/x 在边缘设备上又跑不动。我最后用的是 yolov8s 加 1280 分辨率兼顾精度和推理速度。分辨率必须提。默认 640 输入下远处车辆只有十几像素降采样两次就基本没了。imgsz1280 后小目标召回会有肉眼可见的提升代价是显存和耗时翻倍后期可以配合切图、双路部署来解决。训练命令参考yolo train datatraffic.yaml modelyolov8s.pt \ epochs100 imgsz1280 batch16 device0 \ optimizerAdamW lr00.001 close_mosaic10 patience20batch 要根据显存灵活调整16 跑不动就降到 8同时把 lr0 调小。最后 10 个 epoch 关掉 mosaic是为了让模型适应真实数据分布避免 mosaic 的拼接痕迹影响最终精度。3.3 训练指标怎么读不要盯着训练 loss 自我感动直接看验证集指标。重点看 box_loss、cls_loss、dfl_loss 曲线还有 val 的 P、R、mAP50、mAP50-95。尤其要看 YOLOv8 按尺寸分组的验证结果small、medium、large 的 AP。典型问题是 small 的 AP 明显低于 medium。这说明小目标优化还没到位优先回数据层补样本和提分辨率而不是盲目加 epoch。如果训练 mAP 很高但验证 mAP 上不去多半是过拟合或数据分布偏差先减少 epochs、增强早停或者降低模型容量。如果 cls_loss 一直下不去检查类别标注是否一致比如有的红灯框了灯盘、有的只框了亮灯区域。3.4 模型导出与部署注意训练结束后导出yolo export modelruns/train/exp/weights/best.pt formatonnx imgsz1280在 NVIDIA 边缘设备上可以直接导出 TensorRT engineFP16 精度损失在小目标场景可以接受INT8 必须用真实路口数据做校准否则红灯颜色可能被量化到没法看。部署时另一个容易踩的坑是后处理参数要和训练保持一致。置信度阈值、NMS IoU 阈值、类别过滤是否开启都会影响最终输出。业务端要求低误报时conf 可以提到 0.5 以上离线取证分析可以降到 0.3再用时序投票过滤。4. 小目标检测专项优化从数据到结构4.1 小目标在路口场景到底有多小先量化一下COCO 里 small 目标指小于 32×32 像素的目标。在 1080p 固定路口相机的画面里距离停车线 50 米的小轿车经常只有 20×10 像素。这个尺寸经过 YOLOv8 的 stride 8 下采样后在特征图上只剩 4×2 个格子分类和回归信息都非常少。所以小目标问题本质是两件事特征分辨率不足加上正样本分配不足。4.2 不魔改模型的四条路优先级最高的是提高输入分辨率。imgsz1280 是性价比比较高的档位1536 还能再涨一点但显存和推理速度代价明显继续堆到 2048 收益已经很小部署时也跑不动。第二个方案是切图推理也就是 SAHI 思路。把大图按重叠率切成若干子图每个子图各自推理再把检测结果映射回原图合并。对 4K/8K 摄像头抓拍这个方案通常比单纯提分辨率更有效尤其适合离线取证。第三个方案是多尺度训练。YOLOv8 训练时本身会随机缩放但我更倾向于在数据集里固定放 960 和 1280 两种分辨率子集混合训练让模型同时适应不同下采样尺度。这对相机分辨率不统一的真实项目非常有用。第四个思路是视频多帧聚合。车辆在路口连续出现同一个目标在 10 帧里往往能被检出 7~8 帧偶尔漏检可以通过跟踪器补上不需要单帧模型强到完美。4.3 结构改动路线如果数据和分辨率优化都做到位小目标还是差再考虑改结构。YOLOv8-P2 是一个方向在 stride 4 的位置增加一层检测头小目标的特征分辨率直接翻倍代价是 FLOPs 上涨约 20%显存占用也会升高。另一个改动是 SPD-Conv用空间到深度卷积替换部分 stride2 卷积减少低分辨率下信息丢失对极小目标有实验性提升。还有一类思路是改正样本分配尺度YOLOv8 的 anchor-free 匹配对小目标比较苛刻可以放大匹配范围或者对小目标样本加权但这需要深入读框架内部代码建议作为最后手段。4.4 怎么验证优化效果不要只看整体 mAP要单独看 small 目标 AP 和每一类的召回率。我习惯把小目标漏检样本按原因归类遮挡、过曝、雾天、本身太小、夜间对比度低然后针对占比最高的两类补数据。这样迭代几轮比无脑调参快得多。可视化的漏检样本一定要保存下来很多问题一眼就能看出来不用猜。5. 类别区分的核心实践红灯绿灯分得清5.1 类别区分难在哪红灯和绿灯的相似度极高在画面里只差颜色通道的数值。而且不同摄像头、不同白平衡下同一个颜色在 RGB 空间里能差出很大的范围。如果直接端到端学“红灯”和“绿灯”两个小目标类别分类头很容易把颜色信息学成固定 RGB 阈值换个相机就失效。夜间更麻烦车辆尾灯、刹车灯都是红色形状和信号灯相近误检率一下就上来了。5.2 我的最终方案检测分类两级最终我在项目里用的是两级方案。第一级 YOLOv8 只检测 traffic_light 位置不做颜色分类第二级把每个灯框裁剪出来缩放到 64×64 或 96×96再交给一个小分类网络判断红/黄/绿。这样小目标分类的分辨率由分类网络决定不再绑死在原图尺度上颜色判定也能做得更稳甚至可以在分类网络里加入 HSV 颜色统计作为辅助特征。两级方案的收益非常明显红绿灯分类准确率能到 99% 以上端到端单模型经常卡在 90% 左右。代价是流程多一级推理增加一点开销但交通取证场景完全能接受。如果坚持单模型多类别至少要把 mixup 关掉并对红灯类样本做重复采样。5.3 端到端多类别训练的保底策略如果因为部署限制必须走端到端单模型有几个保底策略。不要在增强里开 mixup不要大幅扰动 H 通道。样本不均衡可以用 cls_loss 权重或者对红灯类做重复采样。类别定义上要把尾灯和信号灯场景尽量区分开必要时用负样本专门压一下。模型输出后还要对相邻帧做信号灯状态投票红灯必须在连续多帧内保持才能进入违章判断逻辑这能有效抵消单帧误检。5.4 类别信息如何变成业务逻辑视觉模型的输出最好是这样的结构化记录每帧里每个目标一个 json——frame_id、class、bbox、conf。跟踪器给车辆分配 ID 后规则引擎拿到车辆 ID 信号灯状态 停止线位置判断车辆越过停止线时信号灯是否为红灯。在这个流程里模型类别错误会被指数级放大。所以类别区分不是模型的炫技指标而是业务正确率的基础。项目评审阶段就要和业务方对齐口径他们更接受“红灯状态判断必须极准车辆类别偶尔分错没关系”还是必须所有类别都高精度。对齐之后数据投入方向完全不同。6. 常见问题与排查技巧实录6.1 高频问题速查表问题现象常见原因排查方法解决措施红灯被识别成绿灯H通道增强过猛、mixup污染、白平衡差异看训练增强配置查混淆矩阵 red/green 行关掉颜色扰动和mixup改用两级分类远处的车漏检imgsz640、目标本身太小看 small AP可视化漏检样本imgsz 提到1280或切图推理停止线断断续续标注不连续、跨尺度抽检停止线标注按断段标注或改成分割辅助夜间尾灯误检红灯负样本不足、conf阈值低统计误检帧来源加入无信号灯夜晚样本提高conf训练loss不下降标注噪声、类别定义混乱抽查label看cls_loss统一标注规范、合并相似类别mAP高但部署效果差训练/部署前处理不一致对比letterbox、缩放、NMS参数严格对齐预处理和后处理参数6.2 实战案例小目标漏检从哪来有一个项目初始用 imgsz640整体 mAP50 0.9 以上但真实视频里 40 米外的小车漏检很严重。后来先用 SAHI 切图推理漏检大幅改善再把训练统一改到 imgsz1280两者结合后小目标召回率提升了约 12 个百分点。这个案例说明小目标问题第一刀永远从分辨率和输入策略上切。6.3 实战案例红绿灯颜色错乱另一轮实验训练时开了 mixup0.2验证 mAP 看着挺高但夜间红灯老被识别成绿灯。关掉 mixup、降低 H 通道扰动强度后红灯/绿灯混淆矩阵里的交叉错误几乎消失。演练结论是在颜色强相关的小目标分类任务里语义混合类增强要非常非常谨慎。6.4 实战案例停止线标到怀疑人生还有一次停止线检测不稳定排查后发现是标注偷懒把整段线框成一个 bbox模型对线中间段召回一直不稳定。重新按可见断段标注后停止线 mAP 才真正可用来判断越线。细长目标的标注规范最好一开始就定死后面返工成本很高。6.5 被硬件坑过的一次过曝的摄像头下红灯灯盘中心一片白边缘才是红色模型怎么调都容易误判。这本质上属于硬件问题不是模型问题。后来一边把标注 bbox 框到中心白区一边协调设备方调整曝光参数问题才真正压下来。智慧交通项目里摄像头质量参差不齐是常态模型不可能补偿硬件所有缺陷尽早把问题反馈到设备侧。最后说点个人体会做这类项目最深的坑就在类别区分上。我一开始图省事把所有信号灯都归成 traffic_light 一个类训练出来总 mAP 很高以为万事大吉。结果业务方一看路口视频说“这红灯状态全是绿的怎么出取证报告”我才意识到端到端类别区分和业务可用之间还差着十万八千里。后来重新梳理类别定义把“信号灯位置检测”和“红灯状态分类”拆成两级配合多帧投票系统才真正到达可用状态。如果你也是第一次做类似智慧交通项目我的建议很直接先别急着堆模型参数量或魔改网络结构先把小目标样本、信号灯颜色、停止线标注这三件事做到位。地基扎实了YOLOv8 只是把成果放大了而已地基不牢换什么模型都是在沙子上盖楼。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑