简介一套基于YOLOv8的多端车流检测系统完整项目包面向计算机、人工智能、通信工程等专业的学生或开发者适用于智慧交通、车辆检测等毕设与课程设计场景解决从模型推理到多端界面展示、数据管理的全流程落地问题。资源共396个文件压缩包约16.94MB其中核心为150个Python源码另含模型权重、YAML配置、SQL数据库、UI界面、Shell启动脚本、说明文档及测试/演示视频等各类型分工明确便于按需检索。已有431人学习下载项目代码经完整测试答辩评审平均分达96分附带的安装说明与演示视频可辅助快速复现环境。除源码外还包含多张车流测试图片与测试视频可直观看到检测效果数据库SQL与管理端相关文件为系统多端展示提供支撑读者可在现有基础上修改实现车流计数、实时监测或Web端展示等扩展功能。1. 车流检测用 YOLOv8这套多端系统到底解决什么问题一个路口摄像头每天产生上万帧画面人工数车流不仅费眼高峰时段根本数不过来漏记、重复记都是常事。基于 YOLOv8 的多端车流检测系统就是把「目标检测模型 视频流处理 数据库存储 前端展示」串成一条完整链路YOLOv8 负责识别画面里的车辆后端按时间窗口统计流量SQL 库保存结构化数据Web 端随时查询。它不只是一个能画框的 Demo而是一套从「看到车」到「报出车流量」的可交付方案。适合做交通类毕设、实训项目或者想从纯模型训练转向完整系统搭建的开发者。标题里附带的源码、文档、测试视频、演示视频、数据库 SQL 和安装说明本质上就是这套系统的六个交付物我按这个顺序帮你拆透。2. 模型选型与训练从 COCO 预训练权重到车流专用检测器2.1 YOLOv8 在车流场景的三个核心特性车流检测不是随便拿个检测模型就能跑好的场景它对模型有三个具体要求。第一是大小目标同时存在路口画面里近处的大巴车可能占半个屏幕远处的轿车只有几十个像素YOLOv8 在 head 部分保留了三个不同尺度的检测层分别负责大、中、小目标这正好匹配俯视/侧视摄像头下的车流画面。第二是遮挡和密集排队早晚高峰车流密集车与车相互遮挡YOLOv8 的 anchor-free 设计让回归头直接预测目标框的中心与宽高比起依赖预设 anchor 的老版本对重叠目标的区分更稳。第三是实时性车流检测通常要接多路视频流模型推理速度直接决定系统能带几路摄像头YOLOv8 从 n 到 x 全系列可选CPU 上跑 n/s 版本GPU 上跑 m/l 版本给了明确的性能调节空间。这里有个很多人踩过的坑拿到 YOLOv8 直接拿 COCO 80 类权重去数车确实能框住 car 和 bus但一到夜间、雨天、或者特种车辆警车、救护车、工程车就频繁漏检。COCO 预训练权重只能当起点真正要落地必须用自己的车流数据微调。数据不需要一开始就搞几万张先准备 1000 到 2000 张典型场景图把 car、bus、truck、motorbike 四类标清楚训练一轮看效果再补数据这比一次性投入大量标注更实际。2.2 训练自己的车流数据集标注、YAML 配置与训练命令标注工具常见做法是使用 LabelImg 或 Label Studio 的矩形框标注导出为 YOLO TXT 格式每张图对应一个 txt 文件。标注完成后按照训练集 70%、验证集 20%、测试集 10% 划分目录结构数据集组织如下datasets/carflow/ ├── images/ │ ├── train/ # 训练图片 │ ├── val/ # 验证图片 │ └── test/ # 测试图片 └── labels/ ├── train/ # 对应的标注 txt ├── val/ └── test/然后写数据配置文件carflow.yamlpath: ./datasets/carflow train: images/train val: images/val test: images/test names: 0: car 1: bus 2: truck 3: motorbike训练命令使用 YOLOv8 官方 CLI 起步不必先写 Python 脚本能少踩很多参数传递的坑yolo detect train \ datacarflow.yaml \ modelyolov8m.pt \ epochs100 \ batch16 \ imgsz640 \ patience20 \ project./runs \ namecarflow_m这里几个参数是必须理解的modelyolov8m.pt表示加载 COCO 预训练的 m 规格权重做迁移学习m 是精度和速度的折中适合大多数本地显卡batch16在 8GB 显存以下建议降到 8不然容易 OOMimgsz640是 YOLOv8 默认分辨率车流场景不必急着用 1280先跑通再换大分辨率看收益patience20表示验证集指标连续 20 个 epoch 不提升就提前结束防止无效训练烧时间。训练结束后看runs/carflow_m/weights/best.pt和last.ptbest 是验证集最优的权重作为后续部署的主力。2.3 导出与封装把 pt 权重转成适合多端部署的格式训练完的 best.pt 是 PyTorch 格式它不能在所有端上直接运行。标题里提到的「多端」常见架构是一个 FastAPI 后端服务负责加载模型做推理Web 前端走 HTTP 接口访问移动端通过 H5 适配。在这种架构下模型推理只发生在后端但为了降低内存占用和提升推理速度通常会先把模型转成 ONNXyolo export modelruns/carflow_m/weights/best.pt formatonnx imgsz640 dynamicTruedynamicTrue让输入的 batch 维度和宽高可以动态变化这在后端同时处理图片和视频帧时很重要imgsz640要和训练时保持一致否则检测精度会衰减。如果后端机器的显卡支持 TensorRT还可以再转 engine 格式推理速度能提升 2 到 3 倍。我一般建议先保留 pt 和 onnx 双格式pt 用于日常调试onnx 用于对外服务接口这样既方便实验又保证交付形态稳定。3. 多端架构与 SQL 数据层检测结果如何落到 Web 和数据库3.1 多端架构怎么选FastAPI Web 前端 MySQL 的常见组合「多端」这个名字对没做过完整系统的人来说容易误解它不是指一个客户端应用跑在三个端上而是指检测引擎、后台服务、展示端分离的架构。常见做法是YOLOv8 推理封装在 FastAPI 服务里提供 HTTP 接口Web 前端Vue 或 React通过接口查数据、看视频流MySQL 存放车辆检测记录和车流量统计表。这个组合的好处是每一层都能独立替换模型可以换更大或更小规格的前端可以换模板数据库可以换 PostgreSQL都不影响其他层。安装配置环节标题里的安装说明一般包括Python 3.9、PyTorch、ultralytics 包、FastAPI、uvicorn、pymysql、MySQL 8.x。环境管理建议用 conda避免 ubuntu 系统和 macOS 之间因为依赖版本打架。启动服务的顺序是先启动 MySQL再初始化 SQL 脚本最后启动 FastAPI 服务。3.2 SQL 建表与初始化车辆记录、流量统计、设备信息三张核心表数据库是这套系统容易被忽略但最影响交付质量的部分。车流检测系统需要存三类数据设备表摄像头基本信息、车辆记录表每次检测到车辆的明细、流量统计表按分钟或小时聚合的通道流量。三张表的设计如下CREATE TABLE camera_device ( id INT PRIMARY KEY AUTO_INCREMENT, device_name VARCHAR(64) NOT NULL COMMENT 摄像头名称, location_desc VARCHAR(128) COMMENT 安装位置描述, stream_url VARCHAR(255) COMMENT 视频流地址, status TINYINT DEFAULT 1 COMMENT 1启用 0停用, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE vehicle_record ( id BIGINT PRIMARY KEY AUTO_INCREMENT, camera_id INT NOT NULL COMMENT 关联摄像头ID, vehicle_type VARCHAR(16) NOT NULL COMMENT car/bus/truck/motorbike, confidence DECIMAL(4,3) COMMENT 推理置信度, frame_time DATETIME NOT NULL COMMENT 检测时间, direction VARCHAR(8) DEFAULT COMMENT 通行方向in/out, track_id INT DEFAULT NULL COMMENT 跟踪ID用于去重计数, INDEX idx_camera_time (camera_id, frame_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE traffic_flow ( id BIGINT PRIMARY KEY AUTO_INCREMENT, camera_id INT NOT NULL, stat_time DATETIME NOT NULL COMMENT 统计时间按分钟, vehicle_type VARCHAR(16) NOT NULL, count_value INT NOT NULL COMMENT 该分钟内检测数量, UNIQUE KEY uk_camera_time_type (camera_id, stat_time, vehicle_type) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这段 SQL 里有几个设计点值得说明vehicle_record表的idx_camera_time联合索引是查询流量的关键没这个索引按摄像头和时间段检索会全表扫traffic_flow表的UNIQUE KEY防止同一分钟重复写入导致统计翻倍utf8mb4字符集必须有否则视频画面的地点名称带中文或 emoji 时直接报错。实际的 SQL 初始化脚本里还会加一些预置摄像头数据方便系统安装后立刻能看到演示效果。3.3 后端接口设计检测结果落库与前端联调FastAPI 的后端服务承担两个职责调用 YOLOv8 推理、把结果写入 MySQL。推理与落库的核心代码from fastapi import FastAPI, UploadFile import cv2 import numpy as np from ultralytics import YOLO import pymysql from datetime import datetime app FastAPI() model YOLO(runs/carflow_m/weights/best.pt) db_config { host: 127.0.0.1, user: carflow, password: carflow123, database: carflow_db, charset: utf8mb4, } def save_record(camera_id, vehicle_type, confidence, frame_time, track_id): conn pymysql.connect(**db_config) try: with conn.cursor() as cursor: sql INSERT INTO vehicle_record (camera_id, vehicle_type, confidence, frame_time, track_id) VALUES (%s, %s, %s, %s, %s) cursor.execute(sql, (camera_id, vehicle_type, confidence, frame_time, track_id)) conn.commit() finally: conn.close() app.post(/api/v1/detect) async def detect_frame(camera_id: int, file: UploadFile): img_bytes await file.read() img_array np.frombuffer(img_bytes, np.uint8) img cv2.imdecode(img_array, cv2.IMREAD_COLOR) results model.predict(img, conf0.4, iou0.5, verboseFalse) now datetime.now() for r in results: for box in r.boxes: cls_id int(box.cls[0]) conf float(box.conf[0]) vehicle_type model.names[cls_id] save_record(camera_id, vehicle_type, conf, now, None) return {status: ok, detected: len(results[0].boxes)}这里的conf0.4是置信度阈值白天可以设 0.5 减少误检夜间建议降到 0.3 避免漏检iou0.5是 NMS 去重阈值。每次检测都向数据库 insert 一条记录这是明细层的写法。但生产环境下不能每个请求都新建数据库连接性能扛不住实际部署时要用连接池如 dbutils 或 SQLAlchemy 池化并把写入动作丢进异步队列异步落库避免画面前端等太久。4. 测试视频跑通全流程单路视频、多路视频与实时流接入4.1 单视频推理与车流统计YOLOv8 的 predict 与 track 接口拿到测试视频后的第一步是用官方命令跑通推理确认模型在真实画面上表现如何yolo predict modelruns/carflow_m/weights/best.pt sourcetest_video.mp4 conf0.4 iou0.5 saveTruesource可以是视频文件路径、摄像头序号如 0或 RTSP 地址saveTrue输出标注后的视频。但 predict 只能画出检测框不能完成车流计数因为每次检测是独立的没有目标的跨帧关联。真正做车流统计要用 track 接口yolo track modelruns/carflow_m/weights/best.pt sourcetest_video.mp4 trackerbytetrack.yaml conf0.4 saveTruetrackerbytetrack.yaml表示使用 ByteTrack 跟踪器它会给每个目标分配一个track_id同一辆车在连续帧里保持相同 ID。有了 track_id 就能做去重计数只统计新出现的 ID而不是每帧都累加。这是车流检测系统里最容易翻车的地方——很多新手直接对检测框计数视频里一辆车停着不动每帧都被数一次一分钟能数出几千辆车。如果跑yolo命令只是为了验证效果那自己的 Python 脚本里调用方式如下from ultralytics import YOLO model YOLO(runs/carflow_m/weights/best.pt) results model.track( sourcetest_video.mp4, trackerbytetrack.yaml, conf0.4, iou0.5, vid_stride2, # 每2帧抽1帧做推理降低CPU负载 streamFalse, # False表示处理完整视频True表示实时流 )vid_stride2是视频推理独有的参数它让模型跳帧检测对慢速车流几乎没有影响但能显著提升处理速度。这个参数在实时视频流里要谨慎车辆速度较快时跳帧过大会导致跟踪丢失、轨迹断裂。4.2 测试视频与演示视频的差异化管理交付包里同时有测试视频和演示视频很多人把这两个搞混实际用途完全不同。测试视频的作用是回归验证每次修改模型参数或代码后用同一段视频跑一遍确认检测框数量、计数结果和上一次一致用来排查代码改动是否破坏了原有功能。演示视频的作用是效果展示挑选光照好、车型丰富、车流连续的路口片段跑通后录屏给评审人看最终效果不需要展示中间调试过程。我一般会把测试视频分成三段白天顺光理想条件、傍晚逆光中等难度、夜间高难度分别统计每段的计数误差。演示视频则单独选一段车流密度适中、画面清晰的素材并且提前确认模型在这段视频上不出现明显漏检。这个习惯能避免一个尴尬场景现场演示时视频一播目标框乱跳被问「你的模型到底行不行」。4.3 对接 RTSP 实时流参数与缓冲生产环境不会只处理视频文件更多是对接 RTSP 摄像头。常见做法是用 OpenCV 的VideoCapture拉流每帧送入模型推理import cv2 from ultralytics import YOLO model YOLO(runs/carflow_m/weights/best.pt) cap cv2.VideoCapture(rtsp://192.168.1.64:554/stream1) cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) # 只缓冲1帧降低延迟 while True: ret, frame cap.read() if not ret: break results model.predict(frame, conf0.4, iou0.5, verboseFalse) # 在这里做 track_id 去重计数和落库这里有一个容易被忽略的延迟陷阱VideoCapture默认缓冲区较大如果推理速度跟不上视频帧率缓冲区内堆满旧帧画面和检测结果会越来越滞后表现为延迟持续增大。CAP_PROP_BUFFERSIZE设为 1 只获取最新帧代价是丢帧但对检测统计来说丢帧远好于延迟累积。5. 部署避坑五个让车流检测系统翻车的低级错误5.1 CPU 推理卡成 PPT性能瓶颈到底在哪现象安装说明完全照做跑起来发现视频每秒只有三四帧检测框明显滞后。原因本机没有可用 GPU且用了 yolov8l 或 yolov8x 权重叠加vid_stride1对每一帧做推理计算量完全超出 CPU 能力。解决换 yolov8n 或 yolov8s 权重微调视频推理开启vid_stride2或vid_stride3imgsz降到 480 到 640 之间。一套组合下来CPU 推理速度可以从 3 fps 提升到 15 fps 左右。5.2 重复计数没有跟踪的检测只是数人头现象车辆在画面中停着等红灯统计结果一分钟内出现几十条同车记录。原因代码只做model.predict逐帧检测没有跟踪关联不同帧的同一目标ID 每次都不同。解决必须使用model.track或显式加载 ByteTrack 跟踪器计数逻辑以track_id第一次出现为准或设置单向计数线车辆从画面下方进入时计数 1同一 ID 重复经过计数线不重复计入。5.3 MySQL 连接失败与中文乱码现象后端启动正常一写入数据库就报OperationalError或者查询结果中地点的中文变成问号。原因MySQL 8.x 默认认证插件和 pymysql 早期版本的兼容问题建表时用了默认字符集而非utf8mb4。解决pymysql 升级到 1.0建库语句显式加CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci连接参数里带上charsetutf8mb4。这个小问题能卡住一整天所以安装说明里我建议直接把完整的建库建表语句跑一遍而不是复制粘贴片段。5.4 夜间和逆光场景漏检现象白天测试视频检得很好一到夜间视频就几乎框不出车或置信度普遍在 0.3 以下。原因训练集以白天顺光为主模型的曝光分布只覆盖了理想条件夜间车灯和阴影让特征分布偏移。解决训练时开启更强的数据增强尤其是hsv_h、hsv_s、hsv_v色相、饱和度、亮度扰动和fliplr0.5推理时把置信度阈值降到 0.25 到 0.3更彻底的做法是收集 200 到 500 张夜间画面补充训练集重新微调。5.5 显存溢出与分辨率适配现象训练或推理时报CUDA out of memory换小 batch 依然闪退。原因imgsz设置过大或训练batch超过了显卡显存容量。解决训练时先用batch4 imgsz640跑通确认显存占用后再逐步调大推理时给 detect 接口做输入尺寸限制超过 1920 宽的画面先等比缩放到imgsz避免 4K 视频直接喂给模型。车流摄像头现在很多是 1080p 甚至 4K直接按原分辨率推理不仅慢小目标反而可能因为缩放策略不当被漏掉正确的做法是统一缩放到 640 或 1280再做检测完事后把坐标映射回原图显示。6. 从检测到车流量统计后端聚合查询与可视化进阶模型能画出框只是第一步真正交付给使用方的是「某条路在这个小时走了多少辆车」。这需要从vehicle_record明细表做聚合统计。按小时、按车型维度聚合的 SQL 写法SELECT camera_id, DATE_FORMAT(frame_time, %Y-%m-%d %H:00:00) AS hour_slot, vehicle_type, COUNT(DISTINCT track_id) AS vehicle_count FROM vehicle_record WHERE frame_time BETWEEN 2024-06-01 08:00:00 AND 2024-06-01 12:00:00 AND track_id IS NOT NULL GROUP BY camera_id, hour_slot, vehicle_type ORDER BY hour_slot;用COUNT(DISTINCT track_id)而不是COUNT(*)是从明细表聚合时不重复计数的关键。前端拿到这些数据就能渲染折线图或柱状图但只查明细表在小数据量下没问题数据量一旦大了聚合查询会越来越慢。更进阶的做法是定时任务每分钟把聚合结果写入traffic_flow表前端直接查统计表明细表只留原始数据供追溯。可视化部分如果项目里没有专业前端可以后端几分钟内跑一个轻量替代方案FastAPI 直接返回 JSON前端页面用 Chart.js 或 ECharts 的 CDN 版本画折线图。ECharts 的折线配置对新手更友好核心设置就三个x 轴是时间y 轴是车流量series 按车型分类。我最早做这类系统时只顾着把 mAP 从 0.8 提到 0.9觉得检测精度才是项目核心。结果演示的时候被问了一句「你检测出这么多框我到底该看哪个数字」才意识到从检测结果到统计指标之间的链路才是这套系统真正值钱的部分。后来重构了数据库表结构加了 track_id 去重和分钟级聚合才把这套系统从「能画框」变成「能报数」。车流检测的方向是否值得做判断标准很简单你交付的不只是模型权重而是能不能回答「8 点到 9 点这个路段双向各过了多少辆车」。希望帮到你。本文还有配套的精品资源点击获取