ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于YOLO与ByteTrack的Python人流量检测系统实战:从检测到越线计数

基于YOLO与ByteTrack的Python人流量检测系统实战:从检测到越线计数 简介这份资源是面向高校计算机、人工智能及相关专业学生的毕业设计完整项目包主题为基于深度学习的人流量检测系统适合作为毕业设计、课程设计或期末大作业直接使用。项目已通过导师指导并取得高分下载后无需修改即可运行对缺乏完整项目经验、需要快速搭建可演示系统的同学尤为实用。压缩包共1235个文件约61.75MB涵盖76个Python源码文件、382个HTML页面、194个JavaScript脚本、208张PNG图片及186个GIF动图另含CSS样式、JSON配置、Markdown说明与模型相关文件前端展示与后端推理模块划分清晰。资源已有170人学习下载说明其方案具备一定参考价值。读者可获得从数据预处理、模型推理到可视化界面展示的完整实现思路并借助目录结构快速定位核心代码理解人流量统计的业务逻辑与工程组织方式为答辩演示和后续二次开发提供可靠基础。1. 从一段监控视频说起人流量检测系统到底在做什么商场门口那台摄像头每天拍下几万帧画面。物业想知道今天来了多少人、哪个时段最挤、哪个入口利用率最低——但没人愿意盯着屏幕一帧帧数。这就是人流量检测系统要解决的事让机器自动从视频里数出「人」和「人次」。它和普通目标检测的区别在于人流量检测不仅要框出画面里的人还要跨帧把同一个人认出来、避免重复计数最后输出一个随时间变化的客流曲线。基于深度学习的方案之所以成为主流是因为传统 HOGSVM 在人群遮挡、光照突变、逆光剪影这些场景下几乎必翻车而 CNN 类模型能学到更鲁棒的特征。这套系统适合谁做计算机相关毕业设计的学生、想入门深度学习落地的开发者、以及需要快速搭一个客流统计原型的工程师。Python 是这条链路里最省心的语言生态全、调参快、源码好找下面就从零把这条路走通。2. 技术选型为什么是 YOLO 跟踪而不是纯检测2.1 检测与跟踪的分工决定了计数准不准很多人第一反应是「用目标检测数框不就行了」。真跑起来会发现视频里同一个人连续 30 帧都被检出你数框就数出 30 个人。所以人流量检测的核心不是检测本身而是「检测 去重」。行业里成熟的拆法是两段式先用检测器逐帧找出人再用跟踪算法给每个人分配一个稳定 ID最后统计「新 ID 出现的次数」或「跨越某条线的 ID 次数」。检测负责「有没有人、在哪」跟踪负责「是不是同一个人」。这两件事分开做调试时能分别定位问题——检测漏了就看模型ID 频繁跳变就看跟踪参数。选型上检测器我一般推荐 YOLO 系列。原因很实际单阶段检测速度快能在普通显卡甚至 CPU 上跑到可用帧率权重文件小方便打包进毕业设计社区教程多出问题好搜。跟踪算法用 ByteTrack 或 DeepSORT 都行ByteTrack 更轻、不依赖外观特征适合人流密集但衣着差异不大的场景DeepSORT 加了 ReID 特征跨遮挡更稳但慢一些。毕业设计里如果机器一般ByteTrack 是更稳的选择。2.2 环境搭建Python 与依赖的版本对齐环境是第一个大坑。深度学习对版本极其敏感CUDA、cuDNN、PyTorch、Python 四者版本必须对齐否则 import 就报错。我一般用 conda 建独立环境避免污染系统 Python。# 创建独立环境Python 版本建议 3.8~3.10太新很多库还没适配 conda create -n crowd python3.9 -y conda activate crowd # 安装 PyTorch注意去官网查对应 CUDA 版本的命令这里以 CUDA 11.8 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装检测与跟踪相关依赖 pip install ultralytics opencv-python numpy scipy lap这段命令的逻辑先隔离环境再装和显卡匹配的 PyTorch最后装检测框架 ultralytics自带 YOLO 实现和 OpenCV。参数说明python3.9是兼容性最好的版本区间cu118要换成你机器实际的 CUDA 版本用nvidia-smi查看lap是跟踪算法做匈牙利匹配要用的库漏装会在跟踪初始化时报错。装完务必跑一句python -c import torch; print(torch.cuda.is_available())返回 True 才算 GPU 可用返回 False 说明版本没对齐别急着往下走。2.3 用预训练权重先跑通最小闭环不要一上来就训练。先用官方预训练权重跑通「读视频 → 检测 → 画框 → 输出」这条链路确认环境没问题再谈优化。import cv2 from ultralytics import YOLO # 加载预训练模型yolov8n 是最小的速度快适合先验证流程 model YOLO(yolov8n.pt) cap cv2.VideoCapture(test.mp4) # 换成你的视频路径 while cap.isOpened(): ret, frame cap.read() if not ret: break # 只检测 person 类COCO 数据集里 person 的类别 id 是 0 results model(frame, classes[0], conf0.4) annotated results[0].plot() # 把检测框画回画面 cv2.imshow(detect, annotated) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()逻辑说明classes[0]是关键只保留人类别过滤掉车、椅子等无关框能显著减少误检。conf0.4是置信度阈值低于它的框不输出。参数怎么调人流稀疏、要求不漏人把 conf 降到 0.3误检多、画面里有大量类人物体模特、海报把 conf 提到 0.5 以上。yolov8n.pt首次运行会自动下载如果网络受限提前手动下载权重放到当前目录。这一步跑通说明检测链路没问题接下来才加跟踪。3. 把检测变成计数跟踪、越线判定与去重逻辑3.1 接入 ByteTrack 实现稳定 ID 分配检测只给框跟踪才给 ID。ultralytics 内置了跟踪接口一行参数就能切换。import cv2 from ultralytics import YOLO model YOLO(yolov8n.pt) cap cv2.VideoCapture(test.mp4) while cap.isOpened(): ret, frame cap.read() if not ret: break # persistTrue 让跟踪器在帧之间保持状态这是 ID 稳定的前提 results model.track(frame, classes[0], conf0.4, trackerbytetrack.yaml, persistTrue) boxes results[0].boxes if boxes.id is not None: # 有跟踪结果时才处理 ids boxes.id.int().cpu().tolist() for box, tid in zip(boxes.xyxy.cpu().tolist(), ids): x1, y1, x2, y2 map(int, box) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(frame, fID {tid}, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.imshow(track, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()逻辑说明persistTrue是核心它让跟踪器记住上一帧的轨迹否则每帧都当新目标ID 会乱跳。trackerbytetrack.yaml指定跟踪配置文件ultralytics 自带这个文件不用自己写。参数说明ByteTrack 内部有两个阈值高置信度框直接匹配低置信度框用来补遮挡这些在 yaml 里可调一般默认够用。如果发现 ID 频繁切换先检查是不是检测框抖动太大再考虑调跟踪的匹配阈值。3.2 越线计数用一条虚拟线判断进出方向有了稳定 ID计数就有两种主流做法统计新出现的 ID 总数适合只关心总量或统计跨越某条线的 ID适合区分进出。商场场景通常用后者。import cv2 from ultralytics import YOLO from collections import defaultdict model YOLO(yolov8n.pt) cap cv2.VideoCapture(test.mp4) h, w int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)), int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) LINE_Y int(h * 0.5) # 虚拟线放在画面中间 track_history defaultdict(list) # 记录每个 ID 的历史中心点 counted set() # 已计数的 ID防止重复 total 0 while cap.isOpened(): ret, frame cap.read() if not ret: break results model.track(frame, classes[0], conf0.4, trackerbytetrack.yaml, persistTrue) boxes results[0].boxes if boxes.id is not None: for box, tid in zip(boxes.xyxy.cpu().tolist(), boxes.id.int().cpu().tolist()): x1, y1, x2, y2 box cy (y1 y2) / 2 # 用框的中心点代表人的位置 track_history[tid].append(cy) # 判断是否从上往下穿过线且该 ID 没计过数 if len(track_history[tid]) 2 and tid not in counted: prev_cy track_history[tid][-2] if prev_cy LINE_Y cy: total 1 counted.add(tid) cv2.line(frame, (0, LINE_Y), (w, LINE_Y), (0, 0, 255), 2) cv2.putText(frame, fCount: {total}, (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) cv2.imshow(count, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()逻辑说明用框中心点的 y 坐标代表人的位置记录每个 ID 的历史轨迹。当上一帧中心在线上方、当前帧在线下方判定为「从上往下穿过」计数加一。counted集合保证同一个 ID 只计一次这是防重复的关键。参数说明LINE_Y决定线的位置放在画面中部最稳太靠边会因为目标刚进画面就穿线导致漏计0.5这个比例可按实际场景调。方向判定只写了从上往下如果要区分进出加一个反向判断即可。3.3 密集场景下的漏检与 ID 跳变处理人流一密问题就来了人挤人时检测框互相重叠NMS 会把挨得近的框误删遮挡几帧后 ID 断了同一个人被当成两个新目标计数虚高。常见做法是调 NMS 的 IoU 阈值默认 0.7密集场景可以提到 0.8 甚至 0.9让重叠框多保留一些。跟踪侧可以调大track_buffer轨迹保留帧数让被遮挡的目标多等几帧再判定消失。如果还不行就得上带 ReID 的 DeepSORT用外观特征把断掉的轨迹接回来代价是速度下降。毕业设计里先保证稀疏场景准再逐步加难度别一上来就挑战地铁早高峰。4. 避坑与排查那些让计数对不上的细节4.1 现象计数比实际人数多出一大截原因最常见的是 ID 跳变。检测框在相邻帧之间位置抖动大跟踪器匹配不上同一个人被分配了新 ID每次跳变都触发一次计数。另一个原因是虚拟线附近目标来回移动反复穿越。解决先看可视化把 ID 画出来肉眼确认是不是同一个人换了 ID。如果是调大跟踪的匹配阈值、增大 track_buffer如果是线附近抖动给计数加一个「冷却时间」同一个 ID 在若干帧内不重复计或者把线加宽成一条带只有完全穿过带才计数。4.2 现象GPU 显存爆了程序中途崩原因视频分辨率太高或者 batch 设太大。1080P 视频逐帧推理显存占用会随分辨率平方增长。解决推理前把帧 resize 到 640 宽这是 YOLO 的默认输入尺寸精度损失可接受。如果还爆改用yolov8n这种小模型或者把imgsz参数显式设小。别硬扛 4K 原图人流量检测不需要那么高的分辨率。4.3 现象白天准晚上或逆光就漏一片原因模型在 COCO 上预训练夜间、逆光样本少特征分布不匹配。这是深度学习的老问题不是代码 bug。解决两条路。一是数据侧采集你实际场景的夜间视频标注一批做微调训练哪怕只标几百张也能明显改善。二是预处理侧对暗光帧做直方图均衡或 Gamma 校正把亮度拉回来再送进模型。前者治本后者救急。4.4 现象CPU 上跑帧率低到没法看原因默认用 CPU 推理YOLO 在 CPU 上单帧可能要几百毫秒。解决确认torch.cuda.is_available()为 True装对 CUDA 版本的 PyTorch。如果机器确实没显卡换更小的模型、降分辨率、跳帧处理每 2~3 帧检测一次中间帧靠跟踪预测都能把可用帧率拉上来。4.5 现象换了个视频参数全失效原因置信度阈值、线位置、跟踪参数都是针对特定场景调的换个机位、换个光照就水土不服。解决把这些参数抽成配置文件别写死在代码里。每换一个场景先跑一遍可视化重新标定线位置和阈值。这是工程化的基本习惯也是毕业设计答辩时能加分的点——说明你考虑到了可配置性。5. 从能跑到好用微调训练与效果验证的实操技巧预训练模型能跑通但要在你自己的场景里准微调是绕不开的。数据标注用 LabelImg 或 Roboflow格式选 YOLO 的 txt。标注时有个血泪经验宁可多标遮挡和边缘样本也别只标正脸清晰的人因为实际视频里这两种才是大头。数据量上每个场景 500 到 1000 张就能看到明显提升太少容易过拟合。训练命令很简洁但参数要理解# data.yaml 里写训练集、验证集路径和类别 yolo detect train modelyolov8n.pt datadata.yaml epochs100 imgsz640 batch16epochs100是迭代轮数小数据集 50 到 100 够用看验证损失不再下降就可以停。batch16受显存限制爆显存就减半。imgsz640要和推理时保持一致否则精度对不上。训练完会输出 best.pt用它替换之前的 yolov8n.pt 即可。验证效果别只看 loss要看业务指标。我一般会准备一段带人工标注「真实人数」的测试视频跑完对比系统计数和真实值算一个误差率。误差在 10% 以内毕业设计就够看了。如果误差大先排查是漏检还是重复计数再针对性调。最后提醒一句答辩时老师最爱问「你怎么证明它准」提前把这段对比数据准备好比讲一堆原理管用。这套方案从环境到计数到微调链路是完整的值不值得做取决于你的场景复杂度——稀疏场景一周能出结果密集场景要留足调参时间。希望帮到你。本文还有配套的精品资源点击获取
返回列表