简介面向毕业设计、课设与计算机视觉入门的道路车流量检测系统完整资源包基于YOLOv8算法和Python实现可完成车辆实时检测与流量统计适用交通监控、城市车流分析等场景。包内共307个文件含126个Python源码、125个pyc编译文件、37个YAML配置以及训练好的pt/onnx模型权重、测试视频、标注图片和说明文档压缩包约155.1MB目录结构清晰便于按模块查看与复用。资源附带了可直接运行的数据集和模型免去自行采集与训练的繁琐流程部署门槛低。当前已有87人学习下载内容对毕设答辩和YOLOv8实战学习均有参考价值。代码注释详尽可帮助读者理解目标检测的数据组织、模型调用与结果可视化过程也能为后续二次开发提供基础。1. 车流量统计还在数帧数YOLOv8 这套代码把检测与计数一起解决了交通口车辆统计这件事最原始的做法是一帧一帧数车、拿线圈感应、或者用背景差分做运动检测——前者累死人后两者在拥堵、并线、货车遮挡的场景下几乎不可用。这套基于 YOLOv8 的道路车流量检测系统把目标检测当作回归问题来处理输入图像直接输出边界框坐标和类别概率不需要人工设计特征真正做到了从像素到结论的端到端。我拆完这套代码后确认训练好的模型和数据集都已打包跑通一条视频链路只需改一个文件路径。适合正在做毕业设计的学生、需要快速验证车流统计方案的工程师以及想把自己的数据集套进 YOLOv8 训练流程的开发者。这套资源的价值不在于算法多新而在于「检测 计数 视频处理」这条链路是完整的。2. 环境搭建与模型选型为什么是 YOLOv8n 和 YOLOv8m 这两个权重2.1 模型文件的取舍逻辑拿到压缩包后第一件事先看权重文件。这套系统里同时给了yolov8n.pt、yolov8m.pt以及转好的yolov8n.onnx和yolov8m.onnx。n 是 nano 版m 是 medium 版两者的取舍本质上是延迟与精度的交换模型参数量适合场景推理延迟GPU推理延迟纯 CPUyolov8n约 3.2M实时视频流、嵌入式部署约 3-5ms约 80-150msyolov8m约 25.9M离线分析、密集场景约 8-12ms约 300-500ms我一般会先用 n 模型跑通流程确认代码链路没问题后再切到 m 模型看精度。如果机器是 GTX 1660Ti 这个级别直接用 m 模型做批量视频分析压力不大但如果要做实时摄像头流建议还是留在 n 模型上。2.2 环境配置的常见做法这类基于 YOLOv8 的项目环境配置是第一个坑。我的标准流程是用 conda 建独立环境避免和本机的其他深度学习环境打架# 创建 Python 3.9 环境YOLOv8 官方要求 Python 3.7 conda create -n carflow python3.9 -y conda activate carflow # 安装 PyTorch这里用 CUDA 11.8 版本如果你的驱动较老可以换成 CUDA 11.7 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装 ultralytics 包YOLOv8 的训练、推理、导出都走这个库 pip install ultralytics # 依赖OpenCV 用于视频帧读取与画框NumPy 用于数组运算 pip install opencv-python numpy参数说明torch和torchvision的版本必须配套否则 import torch 时会直接报错ultralytics包内置了 YOLOv8 的模型定义和权重加载逻辑不需要手动去 GitHub 拉 repoopencv-python负责读视频、写视频和画检测框注意它和opencv-contrib-python不要同时装否则会有符号冲突。装完后验证一次环境是否通python -c import torch, cv2; print(torch.__version__, cv2.__version__); print(torch.cuda.is_available())这里torch.cuda.is_available()输出 True 才说明 GPU 能用。如果输出 False要么 CUDA 版本装错了要么没有装 GPU 版的 PyTorch。CPU 也能跑但yolov8m在 CPU 上处理一段 1080p 视频会慢到让你怀疑人生——我实测过一张图 300 毫秒以上一秒钟的视频要处理几十分钟。3. 代码结构与检测流程从视频帧到车流计数3.1 包内文件的功能定位压缩包里的文件我一个个过了一遍功能定位如下文件 / 目录作用edit-Count-car-YOLOv8.imlIntelliJ IDEA 的模块文件说明作者用 PyCharm 开发对运行无影响bus.jpg/zidane.jpg测试图片来源于 YOLOv8 官方的示例图片用于快速验证检测效果car.mp4/car2.mp4/traffic.MP4测试视频不同场景下的道路车流视频注意两个是 mp4 后缀、一个是 MP4 后缀yolov8n.pt/yolov8m.pt预训练权重COCO 80 类数据集上训练得出包含 car、bus、truck 等车辆类别yolov8n.onnx/yolov8m.onnx从 PyTorch 导出的 onnx 格式模型用于 ONNXRuntime 推理或部署到边缘设备3.2 检测推理链路拆解这套系统的核心检测逻辑用的是 ultralytics 库的标准推理接口。代码主流程通常是这样的import cv2 from ultralytics import YOLO # 加载模型auto 模式下会自动选择 GPU 还是 CPU model YOLO(yolov8m.pt) # 打开视频 cap cv2.VideoCapture(car.mp4) if not cap.isOpened(): raise IOError(无法打开视频文件检查路径和后缀名) fps cap.get(cv2.CAP_PROP_FPS) width int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 初始化视频写入器输出格式为 mp4v writer cv2.VideoWriter(output.mp4, cv2.VideoWriter_fourcc(*mp4v), fps, (width, height)) while True: ret, frame cap.read() if not ret: break # 推理只保留置信度大于 0.4 的检测结果 results model(frame, conf0.4, verboseFalse) # 从 results 对象里取第一个 frame 的结果 boxes results[0].boxes for box in boxes: x1, y1, x2, y2 box.xyxy[0].tolist() conf box.conf[0].item() cls_id int(box.cls[0].item()) label model.names[cls_id] # 只统计车相关类别 if label in [car, bus, truck, motorcycle]: # 画框并标注 cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2) cv2.putText(frame, f{label} {conf:.2f}, (int(x1), int(y1) - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) writer.write(frame) cap.release() writer.release()这段代码逻辑很直白逐帧读取视频 → YOLOv8 推理出目标的边界框坐标、置信度和类别 ID → 过滤掉置信度低于 0.4 的框 → 只在类别为车辆时才画框标注 → 写入输出视频。conf0.4这个阈值很关键太低比如 0.1会出现大量误检把路牌、灯杆也当成车辆太高比如 0.8会导致远处的小车被漏掉。实际调参时我一般从 0.4 开始看检测效果再微调增减 0.05。3.3 车流量统计的核心问题重复计数很多人以为车流检测的难点在「检出车辆」实测下来真正崩溃的是「同一辆车在视频里出现了 50 帧怎么只算 1 次」。最粗暴的做法是每帧都数一次车然后把数值累加——这样统计出来的车流量会虚高到离谱因为一辆车被算了 50 次。常见做法是引入一个简单的跟踪机制维护一个「当前画面中车辆边界框」的列表每帧检测完新框后与上一帧的框计算 IoU交并比如果 IoU 大于某个阈值比如 0.3就认为同一个目标不重复计数如果这个目标在画面中间位置消失了则计数 1。更专业的做法是接入ByteTrack或DeepSORT做多目标跟踪但在这个项目的代码框架下iou 跟踪是最快能跑通的方式。TOTAL_COUNT 0 # 累计通过车辆数 TRACKED {} # 记录当前已跟踪的车辆边界框 def is_same_car(box1, box2, iou_thresh0.3): # 计算两个框的 IoU大于阈值视为同一目标 x1, y1, x2, y2 box1 x3, y3, x4, y4 box2 # 先算交集区域 inter_x1, inter_y1 max(x1, x3), max(y1, y3) inter_x2, inter_y2 min(x2, x4), min(y2, y4) inter_area max(0, inter_x2 - inter_x1) * max(0, inter_y2 - inter_y1) if inter_area 0: return False area1 (x2 - x1) * (y2 - y1) area2 (x4 - x3) * (y4 - y3) iou inter_area / (area1 area2 - inter_area) # 上一帧的车在下一帧中位置偏移一般不大IoU 0.3 已足够稳住 return iou iou_thresh逻辑说明TRACKED字典存放上帧所有车辆框每次新帧检测到结果后先和TRACKED里的所有框比对 IoU匹配上的就更新坐标相当于跟踪目标的位置匹配不上且置信度高于阈值的视为新进入画面的车加入TRACKED。当一辆车的框从画面底部消失也就是连续 N 帧都没匹配上、且中心点 y 坐标接近画面底部时TOTAL_COUNT 1。这套逻辑不依赖额外安装的跟踪库在car.mp4这种单方向车流的视频上准确率相当可观。4. 用自己的数据集重新训练labelme 标注与训练参数设定4.1 数据准备的目录规范与标注如果只跑别人的模型你用的还是 COCO 预训练权重车、卡车、公交这些类别够用但要是想统计「渣土车」「出租车」或者「行人是否闯红灯」就必须训自己的类别了。YOLOv8 的数据集目录结构要求如下datasets/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yaml标注工具用 labelme 或 labelImg 都行。labelme 默认输出 JSON 格式YOLOv8 不直接吃需要先转成 txt 格式。每条 txt 内容是一行class_id x_center y_center width height坐标全部归一化到 0-1 之间。这个转换脚本网上有很多但核心逻辑就一段import json import os from glob import glob # 遍历 labelme 生成的 json 文件 for json_path in glob(labels_json/*.json): with open(json_path, r) as f: data json.load(f) img_w data[imageWidth] img_h data[imageHeight] # 输出 txt 文件名与图片名一致后缀改为 .txt txt_name os.path.splitext(os.path.basename(json_path))[0] .txt with open(flabels_txt/{txt_name}, w) as f: for shape in data[shapes]: cls_id 0 if shape[label] car else 1 points shape[points] # labelme 的 points 是多边形顶点取外接矩形的左上和右下 xs [p[0] for p in points] ys [p[1] for p in points] x_min, x_max min(xs), max(xs) y_min, y_max min(ys), max(ys) # 转成 YOLO 格式的归一化坐标 x_center (x_min x_max) / 2 / img_w y_center (y_min y_max) / 2 / img_h w (x_max - x_min) / img_w h (y_max - y_min) / img_h f.write(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}\n)参数说明cls_id的映射要和data.yaml里的 classes 列表顺序严格一致否则训练完预测的类别标签全是错的。归一化的好处是不管原图分辨率是 1920×1080 还是 640×480模型输入都是 0-1 的相对坐标换分辨率后不用重新标注。标注时边界框不需要包得很紧只要框住目标主体的 90% 区域即可框架太贴边反而会影响模型学习。4.2 data.yaml 与训练参数详解data.yaml 是整个训练的配置中心# 训练和验证数据的路径建议写绝对路径相对路径在多机训练时容易出错 path: /home/user/datasets/ train: images/train val: images/val # 类别名索引从 0 开始和 txt 标注文件中的 class_id 对应 nc: 2 names: [car, bus]训练命令看起来简单但其中几个参数的坑值得注意yolo detect train \ modelyolov8n.pt \ datadata.yaml \ epochs100 \ imgsz640 \ batch8 \ lr00.01 \ patience15 \ device0 \ projectruns \ namecar_train参数解析modelyolov8n.pt表示在 COCO 预训练权重的基础上做迁移学习相比从零训练收敛快得多一般 100 个 epoch 就能达到不错的效果imgsz640是 YOLOv8 的默认输入尺寸如果你的视频里车辆较小可以调成 1280 来提升小目标检测率但显存占用和训练时间都会明显上升batch8在 12GB 显存的 GPU 上跑 n 模型是安全的m 模型则需要降到 4patience15表示训练连续 15 个 epoch 验证集指标没提升就提前终止这是省时间的后悔药。lr00.01是初始学习率用预训练权重时这个值不需要调大反而要小心过拟合。4.3 训练结果评估的两个核心指标训练结束后在runs/car_train/目录下会生成results.png上面画了 loss 曲线、mAP 曲线和精度召回曲线。看模型能不能用不用看那么多图重点盯两个指标指标含义合格线mAP50在 IoU 阈值 0.5 下的平均精度0.8 以上可以接受mAP50-95在 IoU 阈值 0.5-0.95 区间的平均精度0.5 以上算正常mAP50 高但 mAP50-95 低说明模型虽然能把车框出来但框的位置不够精准这对车流计数影响不大因为统计只需要框的存在就行。如果你的场景只是数车、不要求像素级的定位精度mAP50 达标即可。如果你发现训练完 mAP50 一直上不去第一件事不是调模型结构而是去看标注数据——大概率是某些类别漏标了或者一张图里目标太多、标注框大面积重叠。5. 避坑与常见问题路径、显存、计数翻车这些坑我全踩过5.1 视频文件打不开现象cv2.VideoCapture(traffic.MP4)返回的是 None或者read()一直读到 False。原因三个视频文件放在同一个目录下但两个是.mp4后缀、一个是.MP4大写后缀Windows 下文件系统不区分大小写没影响但在 Linux 服务器上跑代码时Python 的字符串匹配是区分大小写的路径写错就打开失败。解决不要依赖硬编码文件名称用路径拼接或 glob 匹配来定位视频文件然后打印出实际路径做检查。video_path traffic.MP4 assert os.path.exists(video_path), f文件不存在{video_path} cap cv2.VideoCapture(video_path) if not cap.isOpened(): print(视频打开失败检查编码格式或路径)5.2 推理速度奇慢GPU 利用率却上不去现象用yolov8m.pt跑car2.mp4程序能跑但速度感人看任务管理器 GPU 利用率只有 20%。原因代码里对每一帧都调用了model(frame)但 model 对象在循环里被反复调用的同时results[0].boxes提取和循环画框的操作都在 Python 主线程中串行执行。GPU 算完一张图后要等 Python 把上一张图的画框、文件写入这些操作做完等于 GPU 在空转。解决把检测和画框分开先批量检测再集中画框或者用更大的 batch 推理。另外画框用writer.write(frame)写入视频是同步操作非常耗时可以先把所有处理完的帧暂存在列表里最后一次用VideoWriter写出。但要注意存帧列表时内存占用1080p 的视频一帧约 3MB存 1000 帧就是 3GB。5.3 计数数值虚高一路乱跳现象跑完car.mp4计数结果有两三千而视频里肉眼数出来不过五六十辆车。原因没有做目标跟踪每帧检测到的车都累加进计数器等于把同一辆车在每一帧的检出都算成了新车。此外置信度阈值调得太低比如 0.1路边的树干、建筑的窗户都被当成了汽车。解决置信度阈值默认调到 0.4 以上同一目标的判定要加 IoU 逻辑这个我在 3.3 节里已经写了代码。还有一个容易被忽略的点检测模型如果用的是 COCO 类别索引model.names里的类别顺序和 COCO 原始类别顺序是一致的car的索引是 2 不是 0写过滤条件时别把索引写死。5.4 训练时显存不足 OOM现象训练命令敲下去还没跑完一个 epoch 就报CUDA out of memory。原因batch8imgsz640的设置在 6GB 显存的卡上跑 m 模型必炸。还有一个隐藏问题验证集没有做 shuffle如果验证图片里全是密集车辆大图前向推理时的中间张量会突然占满显存。解决batch 从 8 降到 4 或 2imgsz 从 640 降到 480modelyolov8n.pt替换yolov8m.pt。如果不想牺牲精度开启梯度累积也能救急。我自己的习惯是先跑一个 10 个 epoch 的小测试确认显存占用稳定后再跑正式训练避免训到一半炸了白等。6. 车流统计的进阶玩法把结果写到 CSV 并按需部署跑通检测与计数只是第一步真正有用的车流数据需要落到表格和可视化这里分享两个我常用的进阶技巧。第一个是输出结构化数据。车流统计最终的交付物通常是一份各时段的车流量报表而不是一个画了框的视频。做法很简单在代码里按固定时间间隔比如每 5 分钟把计数值写入 CSVimport csv from datetime import datetime # 每 5 分钟统计一次车流量的关键变量 INTERVAL_FRAMES int(fps * 300) # 假设 fps30300 秒 5 分钟 frame_count 0 interval_count 0 records [] while cap.isOpened(): ret, frame cap.read() frame_count 1 results model(frame, conf0.4, verboseFalse) # ... 检测与跟踪逻辑interval_count 统计本区间内的新增车辆 if frame_count % INTERVAL_FRAMES 0: records.append({ timestamp: datetime.now().strftime(%H:%M:%S), vehicle_count: interval_count, }) interval_count 0 with open(traffic_stats.csv, w, newline) as f: writer csv.DictWriter(f, fieldnames[timestamp, vehicle_count]) writer.writeheader() writer.writerows(records)这段代码的意义是把检测结果转成数据分析可用的格式方便后续在 Excel 里画时段流量曲线或者接入大屏系统。INTERVAL_FRAMES的计算逻辑是用视频的 FPS 乘以希望统计的秒数比如 fps30、想每 5 分钟统计一次就填 300 秒。注意如果视频本身不是恒定帧率这个统计会有几秒的偏差但作为车流趋势参考完全够用。第二个技巧是部署层面的如果要把模型部署到边缘设备或嵌入式终端不要直接用.pt权重转成 ONNX 后用 ONNXRuntime 推理你会发现两件事——推理速度可能比 PyTorch 原生推理还快而且环境依赖大幅简化不再需要装 PyTorch 全家桶。导出命令极简单yolo export modelyolov8n.pt formatonnx imgsz640导出后用yolov8n.onnx推理的代码和 PyTorch 版有区别import onnxruntime as ort import numpy as np sess ort.InferenceSession(yolov8n.onnx, providers[CUDAExecutionProvider, CPUExecutionProvider]) input_name sess.get_inputs()[0].name def detect_onnx(frame): # 预处理BGR 转 RGBresize 到 640x640归一化到 0-1 img cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) img cv2.resize(img, (640, 640)) img img.astype(np.float32) / 255.0 img np.transpose(img, (2, 0, 1)) img np.expand_dims(img, axis0) # 推理输出格式为 [1, 84, 8400]84 4 个框坐标 80 个类别得分 outputs sess.run(None, {input_name: img})[0] return outputsONNX 的输出格式和 PyTorch 不一样是一个[1, 84, 8400]的矩阵。其中 8400 是不同尺度下锚点的总数84 的含义是每个锚点有 4 个边框坐标加 80 个类别得分。从 ONNX 输出里解析边界框时要先做维度变换然后用置信度过滤最后还要把 640×640 的坐标映射回原始帧尺寸——这些都是最常见的坑建议用之前先在官方测试图上验证一轮。我个人的经验是跑车流统计环境造好、路径确认好、阈值调好这三件事做完这套系统 30 分钟内就能出第一个检测视频。从那以后我每次拿到新视频都会强制自己先跑一轮 n 模型小样本、检查置信度分布和漏检情况再决定是否要上 m 模型或重新训练。这套流程一路走下来基本没翻过车希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
汉赢酱酒运营中心创新能力怎么样,研发能力强吗 顺应酱酒产业发展趋势,锚定行业使命与社会责任近年来,酱酒产业在消费升级浪潮中快速发展,大众对正宗酱酒的认知不断提升,市场对高品质、高性价比酱酒的需求持续增长,同时行业长期存在的乱象也逐渐凸显:大量… · 2026/9/24 18:05:27
MATLAB随机森林回归预测实战:从原理到源码包解析 简介:随机森林(RF)回归预测的MATLAB源代码实现,面向需要快速上手机器学习回归预测的工程师、科研人员和学生,适合技能层级从入门到进阶的读者。应用场景覆盖价格预测、销售额预测、出行流量预测、能耗预测、案发数量预… · 2026/9/24 18:05:14
Spring Boot图片上传下载与ckeditor4对接实战 简介:面向Java Web开发者的图片上传下载示例项目,基于Spring Boot框架整合ckeditor4富文本编辑器,演示从后端接收图片、保存至服务器目录、再由前端访问的完整实现链路。资源适合初步接触文件上传的开发者,可从中掌握MultipartFil… · 2026/9/24 18:05:14
SpaceX-API v4 Crew 接口详解:数据模型、查询分页与缓存实现 后端API设计 【免费下载链接】SpaceX-API :rocket: Open Source REST API for SpaceX launch, rocket, core, capsule, starlink, launchpad, and landing pad data. 项目地址: https://gitcode.com/gh_mirrors/spa/SpaceX-API 点击查看 免费下载 导读
本文以 Spa… · 2026/9/24 18:43:38
本地餐饮同城外卖系统开发,多门店订单管理技术方案 本地餐饮同城外卖系统开发,多门店订单管理技术方案连锁餐饮、多商户入驻的同城外卖平台,会面临多门店订单统一归集、分单、库存、出餐管控等问题。很多简易外卖系统采用单店独立模式,门店数据相互隔离,无法实现跨店统筹࿱… · 2026/9/24 18:43:38
Kubernetes kubectl 实战手册:从排障到日常运维的完整命令指南 凌晨两点,手机告警把整个群都炸醒了——生产环境的某个节点直接 NotReady,业务 Pod 像多米诺骨牌一样接二连三进入 Pending。经历过这种场面的人应该都懂,微信群里所有人都在等你一句话:"我先看下集群状态。"这时候你敲… · 2026/9/24 18:43:31
ROS机器人开发中Terraform选型:托管服务与原生方案深度对比 1. 从一个真实的选择困境说起去年底我接手了一个机器人项目,团队里有人用ROS做仿真,有人搞机械臂标定,还有人负责SLAM建图和自主导航。项目推进到部署阶段时,一个绕不开的问题摆在面前:基础设施怎么管?我们… · 2026/9/24 18:43:25
6款AI编程工具实战指南:嵌入开发工作流的关键断点 1. 这6款工具不是“排行榜”,而是我过去18个月在3个真实项目里反复验证过的效率杠杆你点开这篇,大概率正被三件事压着喘不过气:需求文档还没读完,测试环境又崩了,而产品经理刚发来第7版UI改稿——这时候告诉你“用AI工… · 2026/9/24 18:43:19
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程 简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13
1D-CNN时间序列建模实战:从Conv1d原理到工业落地 简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26
柔软的L:汉语语流中被忽视的舌肌张力控制 1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44