基于YOLO的交通流量统计与违章检测:从检测跟踪到规则引擎的工程实践
简介这份资源面向人工智能、深度学习方向的毕业设计与课程设计学习者提供一套基于YOLO的交通流量统计与违章行为检测完整项目源码。系统通过交通摄像头采集视频流利用YOLO模型对车辆、行人、自行车等目标进行实时检测统计车流量并记录位置、速度与移动方向同时可识别压线、逆行、非法停车等违章行为并保存证据适合作为智慧城市交通管理方向的实战参考。压缩包共119个文件约64.38MB以46个py源码与53个pyc编译文件为主体辅以3个pt权重、2个cfg与2个names配置、3个ui界面文件及sh、bat启动脚本另含sql建表脚本与README说明目录结构清晰便于快速部署与二次开发。目前已有112人学习下载可帮助读者掌握YOLO目标检测在交通场景中的落地流程、模型配置与界面集成思路。1. 从一段路口监控说起这套 YOLO 交通流量统计与违章检测资源到底能干什么如果你手头有一段路口监控、一段行车记录仪或者干脆是公开数据集里的车流视频想把它变成「过了多少辆车、每辆车什么类型、哪几辆压了实线、哪几辆闯了红灯」这种结构化结果那这套基于 YOLO 的交通流量统计与违章行为检测资源就是冲这个场景来的。它不是一篇讲 YOLO 原理的 PPT而是一个能跑起来的工程包检测模型负责把画面里的车、人、非机动车框出来跟踪模块负责给每个目标分配稳定 ID流量统计靠虚拟线圈或越线计数违章检测则是在跟踪轨迹上叠加规则判断——压线、逆行、违停、闯红灯这些都能落进去。适合谁正在做毕业设计、课程设计需要一份「有检测、有跟踪、有业务逻辑」的完整代码参考的人也适合刚转深度学习、想拿一个真实交通场景练手目标检测加多目标跟踪的工程师。它解决的核心问题是把 YOLO 从「单帧检测」推到「视频级业务指标」中间那层跟踪和规则引擎才是这类项目真正值钱的地方。2. 拆开这个包YOLO 检测、跟踪与违章规则是怎么串起来的2.1 为什么交通场景不能只靠单帧 YOLO单帧 YOLO 给你的是「这一帧里有 3 辆车、1 个人」但流量统计要的是「这一分钟内有多少个不同的目标越过了停止线」违章检测要的是「同一个目标在连续帧里的运动轨迹是否压线」。这两件事单帧检测都做不到因为帧与帧之间没有身份关联。常见做法是引入多目标跟踪MOT把检测框按位置、外观、运动预测做匹配给每个目标一个 track_id。交通流量统计里最稳的方案是「检测 跟踪 虚拟线圈」在画面里画一条或几条计数线当某个 track_id 的轨迹从线的一侧穿到另一侧计数加一同时记录它的类别。违章行为检测则更依赖轨迹质量比如压线判断需要目标框底边与车道线区域的重叠关系在连续多帧里保持逆行判断需要轨迹方向与车道允许方向做夹角比较。这套资源的价值就在于它把这几层都写出来了而不是只丢一个 YOLO 推理脚本。2.2 环境搭建与依赖安装拿到包之后第一件事不是急着跑 main而是把环境对齐。YOLO 系列对 PyTorch 和 CUDA 版本比较敏感版本错位最常见的表现是能 import 但推理报错或者 GPU 用不上。我一般会先建独立虚拟环境再按包里的 requirements 装不要直接往 base 环境里怼。# 创建并激活虚拟环境Python 版本建议 3.8 到 3.10 conda create -n traffic_yolo python3.9 -y conda activate traffic_yolo # 安装 PyTorch具体 CUDA 版本按你显卡驱动来这里以 CUDA 11.8 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装其余依赖ultralytics 是 YOLO 常用封装 pip install ultralytics opencv-python numpy scipy filterpy lap这段命令的逻辑是先隔离环境避免和系统里其他深度学习项目打架PyTorch 单独指定 CUDA 源是因为默认 pip 源经常给你装 CPU 版跑起来慢到怀疑人生ultralytics 负责 YOLO 模型加载和推理opencv 负责视频读写和画框filterpy 和 lap 是跟踪里常用的卡尔曼滤波和匈牙利匹配依赖。参数上唯一要盯的是 CUDA 版本用nvidia-smi看右上角那个 CUDA Version不要超过它。装完跑一句python -c import torch; print(torch.cuda.is_available())返回 True 才算过关。2.3 模型加载与推理参数怎么设包里的检测部分通常已经带了权重文件或者给了下载入口常见是 YOLOv5 或 YOLOv8 的 .pt。加载时不要无脑用默认尺寸交通监控画面里车目标往往偏小输入分辨率直接决定小目标召回。from ultralytics import YOLO # 加载模型权重文件放在包内 weights 目录下 model YOLO(weights/yolov8n.pt) # 推理参数imgsz 提到 960 提升小目标召回conf 放低一点避免漏检 results model.predict( sourcetest_video.mp4, imgsz960, conf0.25, iou0.45, classes[0, 1, 2, 3, 5, 7], # 只保留人、自行车、汽车、摩托、公交、卡车 streamTrue, device0 )这里 imgsz 从默认 640 提到 960是因为路口监控里远处车辆可能只有几十像素640 下容易丢代价是显存和耗时上升T4 上 1080p 视频大概能跑到十几到二十几帧具体看你模型大小。conf 设 0.25 是交通场景常用值宁可多检一点后面用跟踪和规则过滤也不要漏掉真实车辆。classes 过滤掉无关类别减少后续跟踪的干扰。streamTrue 让推理按生成器返回避免一次性把整段视频读进内存。如果你用的是自己训练的模型把权重路径换掉类别索引按你的 data.yaml 来。2.4 跟踪与流量统计的代码落点跟踪部分包内一般会封装成一个 tracker 类核心是「预测 匹配 更新」。流量统计则是在跟踪结果之上加计数线逻辑。# 伪代码结构按包内实际类名调整 tracker TrafficTracker(max_age30, min_hits3, iou_threshold0.3) # 定义计数线坐标按你的画面分辨率来 count_line [(0, 500), (1920, 500)] counter LineCounter(linecount_line, directiondown) for frame in video_stream: detections model(frame) # 上一节的检测结果 tracks tracker.update(detections) # 返回带 track_id 的轨迹 for t in tracks: counter.update(t.track_id, t.center) flow counter.get_count() # 当前累计流量max_age 表示一个目标丢失多少帧后删除轨迹交通场景目标偶尔被遮挡设太小会频繁断 ID设太大又会让已离开的目标残留30 帧左右是常见起点。min_hits 是连续命中多少帧才确认轨迹防止误检产生假目标。计数线的方向参数决定是统计上行还是下行双向统计就放两条线。这里最容易翻车的是画面抖动或相机移动导致计数线相对路面漂移解决方式要么固定相机要么加简单的透视变换把画面先稳到俯视视角。2.5 违章行为检测的规则引擎违章检测不是模型直接输出的而是规则引擎在轨迹上做判断。压线、逆行、违停各有各的判定条件包内一般会给出可配置的规则文件或字典。# 违章规则配置示例 violation_rules { lane_cross: { enabled: True, lane_polygons: [[(200,400),(600,400),(600,700),(200,700)]], overlap_threshold: 0.3, # 目标框与车道线区域重叠比例 min_frames: 5 # 连续满足帧数才判定 }, wrong_way: { enabled: True, allowed_angle: 180, # 允许方向角度 angle_tolerance: 45 # 容差 } }lane_cross 里的 lane_polygons 是车道线或禁行区多边形overlap_threshold 控制多严格min_frames 是防抖的关键——单帧重叠可能是检测框抖动连续 5 帧才可信。wrong_way 用轨迹方向与允许方向做夹角比较容差设太小会误报设太大又漏报45 度是常见折中。这些参数没有万能值必须拿你的实际视频调调的时候把中间结果画出来看比盲调快得多。3. 避坑与排查这套资源跑不起来时先看这几条3.1 现象推理能跑但 GPU 利用率极低帧率只有个位数原因通常是 PyTorch 装成了 CPU 版或者推理时没有把数据搬到 GPU。另一个常见原因是每帧都重新加载模型而不是复用同一个 model 对象。解决先确认torch.cuda.is_available()为 True再把模型和输入统一放到 device 上推理循环外只加载一次模型。如果确认是 GPU 但帧率仍低检查 imgsz 是不是设得过大960 已经比 640 慢不少T4 上想跑多路就得降分辨率或换更小的模型。3.2 现象流量统计数字明显偏多同一辆车被计了好几次原因是跟踪 ID 频繁切换一辆车断成多个 track_id每个都触发一次计数。常见诱因是 max_age 太小、检测置信度波动大、或者目标被遮挡后重新出现。解决适当增大 max_age提高检测稳定性conf 不要设太高计数逻辑里加一个「同一 ID 只计一次」的集合去重另外可以在计数线附近加一个缓冲区只有轨迹完整穿过缓冲区才计数避免在线上来回抖动重复触发。3.3 现象违章检测误报严重正常行驶也被判压线原因是车道线多边形画得太宽或者 overlap_threshold 设得太低检测框稍微碰到区域就算违章。解决把车道线区域画窄一点贴着实际标线overlap_threshold 从 0.3 往上调试到 0.5 甚至 0.6min_frames 从 5 提到 8 到 10用时间维度过滤掉瞬时抖动。调的时候把违章帧截图存下来一批一批看比盯着数字猜有效。3.4 现象视频读写报错或者输出视频没有画面原因是 OpenCV 的 VideoWriter 编码器与输入格式不匹配或者帧尺寸和 writer 初始化时不一致。解决读第一帧拿到实际宽高用这个宽高初始化 VideoWriter编码器优先试 mp4v不行再试 XVID 配合 .avi 后缀。如果输入是 RTSP 流注意超时和重连不要用 while True 裸读加一个失败重试和退出条件否则流一断程序就卡死。3.5 现象换了自己的数据集后类别全乱或者检测不到目标原因是模型权重和你的类别定义不匹配。包内权重是在 COCO 或某个交通数据集上训的类别索引固定。解决要么用你自己的数据重新训练或微调要么在推理后做类别映射把模型输出的索引映射到你的业务类别。重新训练时注意 data.yaml 里的 nc 和 names 要和标注一致标注格式YOLO txt的归一化坐标不要搞错这是新手最高频的翻车点。4. 进阶玩法把流量统计和违章检测做成可验证的闭环4.1 用离线视频做回归验证别只靠肉眼这套资源最容易糊弄的地方就是「看起来在跑」但数字对不对没人知道。我的习惯是拿一段已知答案的短视频做回归人工数一遍某条计数线在 60 秒内过了多少辆车然后跑程序对比。误差在 5% 以内算可用超过 10% 就得回去查跟踪和计数逻辑。验证时把每辆车的 track_id、越线时刻、类别打成日志出问题能直接定位到是哪一段轨迹错了。# 简单的回归验证脚本思路 import csv with open(count_log.csv, w, newline) as f: writer csv.writer(f) writer.writerow([frame, track_id, class, direction]) for frame_idx, tracks in enumerate(all_tracks): for t in tracks: if counter.just_crossed(t.track_id): writer.writerow([frame_idx, t.track_id, t.class_name, t.direction])日志里 frame 和 track_id 是关键出问题时可以跳到对应帧看画面确认是漏检、ID 切换还是计数线位置不对。这个习惯能帮你把「玄学调参」变成「有据可查」。4.2 违章判定的参数标定表违章规则里那几个阈值不要拍脑袋建议做一张标定表每换一个场景重新填一遍。下面是我常用的记录格式参数含义路口 A 取值路口 B 取值调整方向overlap_threshold目标框与禁行区重叠比例0.450.55误报多就调高min_frames连续满足帧数68抖动多就调高max_age轨迹丢失容忍帧数3025ID 切换多就调高conf检测置信度0.250.3漏检多就调低imgsz推理分辨率9601280小目标多就调高这张表的价值在于下次换场景你不是从零开始猜而是有一个已知可用的起点。路口 A 和 B 的差异通常来自相机高度、焦距和车流密度俯角越大、车越密min_frames 和 overlap_threshold 一般都要往上走。4.3 从单路到多路的性能边界很多人拿到这套代码第一反应是「能不能同时跑 8 路」。答案取决于你的硬件和分辨率。以 T4 为例YOLO 640 分辨率下单路大概能到 30 帧以上1080p25 帧的视频做实时处理单卡跑 4 到 6 路是常见区间再往上就得靠 TensorRT 加速或者降分辨率、跳帧。跳帧是个实用技巧检测不必每帧都做跟踪器可以用运动预测补中间帧流量统计和违章判定对时间精度要求没那么高隔帧检测完全够用。但要注意跳帧后轨迹的时间间隔变了速度类判断比如是否超速需要按实际时间戳换算不能直接用帧号差。4.4 一个我踩过的坑别在计数线上做文章要在轨迹上做早期我做流量统计时总想着把计数线画得刁钻一点斜着画、画多条结果越搞越乱。后来才明白计数线本身不重要重要的是轨迹是否完整、ID 是否稳定。从那以后我每次接新场景都强制先跑一遍纯跟踪可视化把轨迹画出来看确认 ID 不怎么断、轨迹平滑再去调计数和违章规则。这一步多花二十分钟能省掉后面几个小时的瞎调。希望帮到你。本文还有配套的精品资源点击获取