ARTICLE DETAIL

资讯详情

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

本科毕设人流量检测实战:YOLOv5s+DeepSORT轻量部署指南

本科毕设人流量检测实战:YOLOv5s+DeepSORT轻量部署指南 简介本资源是一套完整的毕业设计级人流量检测系统实现方案面向计算机、人工智能、自动化等专业的在校学生及初学者解决实际场景中基于视频流的实时人流量统计与可视化分析问题。项目采用Python开发集成主流深度学习模型如YOLO或OpenPose类算法包含可直接运行的源码、详细项目说明文档、多组实测运行效果图及环境配置指南适合作为毕设、课程设计或入门级AI项目实践参考。压缩包共1235个文件涵盖76个Python核心脚本、382个HTML前端页面、208张PNG结果图、194个JS交互逻辑及186个GIF动态演示辅以CSS、MD文档和少量Java/C#后端接口文件整体大小61.21MB结构分层清晰便于理解前后端协同机制。目前已有373人学习下载代码经答辩实测验证平均评分96分附带远程答疑支持适合从运行到二次开发的全链路学习。1. 为什么人流量检测不能只靠OpenCV背景建模毕业设计选这个题真不是为了凑字数去年带三个本科生做毕设两个用传统帧差法形态学处理答辩时被问“商场早高峰人流密集重叠、遮挡严重你这连两个人并排走都分不清怎么算检测”——当场哑火。真正能落地的人流量检测系统核心不在“数人”而在“理解空间语义”谁在动、往哪走、是否聚集、是否滞留。深度学习不是炫技是解决传统方法在复杂光照、低帧率摄像头、多目标遮挡下的根本性失效。本项目用YOLOv5s DeepSORT轻量组合在单路1080P IPC海康DS-2CD3T47G0-I上实测达到23.6 FPS平均ID切换率8.2%支持导出每分钟进出人数CSV、热力图叠加视频、异常滞留告警90秒无位移。适合本科毕设的完整闭环数据采集→标注→训练→部署→可视化→报告生成。不依赖GPU服务器RTX3060笔记本即可跑通全流程所有代码、标注工具、预训练权重、测试视频全打包开箱即用。如果你正卡在“毕设选题没方向”“模型训完不会部署”“检测结果飘忽不定”这篇就是为你写的血泪复现笔记。2. 从零搭建人流量检测流水线数据、模型、推理三件套怎么配才不翻车2.1 数据采集与标注别用网上下载的“人头数据集”自己拍才有真实感毕业设计最常踩的坑是直接下载WIDER FACE或CrowdHuman塞进YOLO训练——这些数据集全是高清正面人脸、强光照、无遮挡而你实验室门口的IPC摄像头拍出来的是模糊拖影快门1/30s俯视视角摄像头装在3米高天花板人群重叠食堂打饭窗口前人堆人光照突变阴天→突然阳光直射玻璃门正确做法用手机支架固定iPhone 131080P30fps对准校门口/图书馆闸机/宿舍楼通道连续录3段各10分钟视频早/中/晚各一导出为MP4。用ffmpeg抽帧# 抽取每秒1帧避免冗余人流量检测不需要高帧率 ffmpeg -i campus_gate.mp4 -vf fps1 -q:v 2 frames/%06d.jpg提示-q:v 2控制JPEG质量1-32值越小质量越高毕设演示视频需清晰别用默认-q:v 25导致模糊。标注工具必须用CVAT开源Web版禁用LabelImgCVAT支持多边形框应对俯视下人体变形、轨迹标注为DeepSORT准备、自动插帧减少人工标注量。重点标两类目标person全身可见或至少腰部以上可见遮挡严重时标可见部分group明确聚集成簇≥3人且间距0.5m用于后续热力图密度计算标注后导出为YOLO格式.txt每行class_id center_x center_y width height归一化坐标。验证集严格按时间切分早间视频全作训练集晚间视频全作测试集——模拟真实场景泛化能力。2.2 模型选型YOLOv5s不是最优解但它是毕设最稳的“后悔药”搜“人流量检测 深度学习”会看到一堆论文吹DETR、ByteTrack、FairMOT但毕设要的是可复现、可解释、可答辩。YOLOv5s满足三点训练快RTX3060上2000张图训100 epoch仅需47分钟batch16部署简torchscript导出后一行命令转ONNX再用OpenCV DNN模块加载调参明hyp.scratch-low.yaml里lr0: 0.01、mosaic: 1.0、scale: 0.5三个参数改完立刻见效关键修改点直接抄models/yolov5s.yaml中nc: 1→ 改为nc: 2支持persongroup双类别data/campus.yaml中train: ../frames/train路径必须用相对路径避免绝对路径在答辩电脑上报错train.py启动命令加--cache缓存图像到RAM提速3倍毕设数据量小RAM够用# 训练命令务必加 --cache 和 --workers 4 python train.py --img 640 --batch 16 --epochs 100 --data data/campus.yaml \ --weights yolov5s.pt --cache --workers 4 --name campus_yolov5s--workers 4是玄学参数小于CPU核心数我的i7-10875H是8核大于会导致Dataloader卡死等于则常因IO瓶颈反而慢。实测4最稳。2.3 推理与跟踪DeepSORT不是万能胶得给它喂干净的检测框YOLO输出的是静态框人流量统计需要跨帧ID关联。DeepSORT比Sort强在用外观特征ReID模型抗遮挡但它的致命弱点是输入检测框质量差它就崩。必须做的预处理否则ID切换率爆表YOLO置信度过滤conf_thres0.5太低→误检多ID乱跳太高→漏检人数少报NMS阈值iou_thres0.45俯视场景人体框重叠率高0.45比默认0.6更合理框坐标矫正YOLO输出中心点DeepSORT要左上角坐标用xywh2xyxy()转换# detect_and_track.py 关键片段 def run_tracker(): model torch.hub.load(ultralytics/yolov5, custom, pathruns/train/campus_yolov5s/weights/best.pt) tracker DeepSort( model_pathdeep_sort_pytorch/deep_sort/deep/checkpoint/ckpt.t7, # ReID模型权重 max_age30, # ID丢失30帧后删除对应1秒因30fps n_init3, # 连续3帧确认ID防误跟 nn_budget70 # 特征库大小70够本科数据量 ) for frame in video_frames: results model(frame) # 自动做conf/iou过滤 detections [] for *box, conf, cls in results.xyxy[0].cpu().numpy(): if int(cls) 0 and conf 0.5: # 只跟踪person类 x1, y1, x2, y2 map(int, box) detections.append([x1, y1, x2, y2, conf]) tracks tracker.update(np.array(detections)) # DeepSORT核心 # tracks格式[x1,y1,x2,y2,track_id,class_id]注意max_age30对应30帧不是30秒你的视频如果是15fps这里就得设15。毕设务必用cv2.VideoCapture().get(cv2.CAP_PROP_FPS)实测帧率别硬写30。3. 避坑指南毕设答辩前夜还在修的5个血泪Bug3.1 现象训练loss曲线震荡剧烈val/mAP0.5掉到0.1以下原因标注文件.txt里存在空行或坐标超范围如center_x1.2。YOLO读取时静默跳过该图但train.txt仍计数导致实际训练图数≠列表数DataLoader索引错乱。解决用脚本清洗标注文件# clean_labels.py import os for label_file in os.listdir(labels/train): with open(flabels/train/{label_file}, r) as f: lines [l.strip() for l in f.readlines() if l.strip()] # 过滤坐标超限行 valid_lines [] for line in lines: parts line.split() if len(parts) ! 5: continue try: cx, cy, w, h map(float, parts[1:]) if 0cx1 and 0cy1 and 0w1 and 0h1: valid_lines.append(line) except: pass with open(flabels/train/{label_file}, w) as f: f.write(\n.join(valid_lines))3.2 现象推理时CPU占用100%GPU显存只用200MBFPS卡在3帧原因OpenCV DNN模块默认用CPU推理没启用CUDA。即使你装了opencv-python-headless它也不自动调GPU。解决强制指定后端和目标net cv2.dnn.readNet(yolov5s.onnx) net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA) # 关键 net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA_FP16) # FP16加速提示DNN_TARGET_CUDA_FP16要求显卡支持FP16GTX10系不行RTX20/30系可以若报错改用DNN_TARGET_CUDA。3.3 现象DeepSORT跟踪ID频繁切换同一人出现ID1→ID5→ID2原因ReID模型ckpt.t7是针对MOT17数据集训练的你的校园场景衣着颜色、尺度差异大特征提取失效。解决关掉外观匹配纯靠运动模型适合毕设tracker DeepSort( model_pathNone, # 不加载ReID模型 max_age30, n_init3, nn_budget0, # 关键设0禁用外观匹配 override_track_classTrue )3.4 现象热力图全黑或只在画面边缘有红点原因热力图坐标映射错误。YOLO输出是归一化坐标0~1而OpenCV绘图用像素坐标0~1920。解决统一用原始视频分辨率做映射# 假设视频宽1920高1080 frame_h, frame_w frame.shape[:2] for track in tracks: x1, y1, x2, y2, tid track # 将track坐标转为整数像素 x1, y1, x2, y2 int(x1), int(y1), int(x2), int(y2) # 热力图累加中心点 center_x, center_y (x1x2)//2, (y1y2)//2 heatmap[center_y, center_x] 1 # 注意numpy索引是[y,x]3.5 现象导出CSV人数统计为0或每分钟都是同一数字原因计数逻辑写在for track in tracks:循环内但tracks是单帧结果未做跨帧聚合。解决用字典维护ID生命周期id_history {} # {track_id: [frame_idx_list]} for frame_idx, tracks in enumerate(all_tracks): for track in tracks: tid int(track[4]) if tid not in id_history: id_history[tid] [] id_history[tid].append(frame_idx) # 统计每个ID存在帧数 30帧1秒才算有效通行 valid_ids [tid for tid, frames in id_history.items() if len(frames) 30] print(f第{frame_idx//30}分钟通行人数{len(valid_ids)}) # 30帧1秒4. 毕设加分项三招让答辩老师眼前一亮4.1 用Matplotlib动态热力图替代静态截图答辩PPT放一张热力图截图老师只会说“哦做了”。但如果你现场演示实时热力图叠加视频流并拖动进度条回看早高峰峰值效果立判。关键在matplotlib.animation.FuncAnimationimport matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation fig, ax plt.subplots() im ax.imshow(np.zeros((1080,1920)), cmaphot, vmin0, vmax100) def update(frame): # frame是当前帧索引从all_heatmaps取对应热力图 im.set_array(all_heatmaps[frame]) return [im] ani FuncAnimation(fig, update, frameslen(all_heatmaps), interval33, blitTrue) # 33ms≈30fps plt.show()注意interval33必须严格匹配视频帧率否则动画卡顿。用cv2.VideoCapture().get(cv2.CAP_PROP_FPS)实测后填。4.2 异常滞留检测不是简单“不动就报警”而是时空联合判断单纯用track.speed 1px/frame会误报电梯里等人、排队。真实场景要加时空约束空间在划定ROI如消防通道内时间连续静止≥90秒非累计上下文周围5米内无其他ID移动排除等人场景# 定义消防通道ROI四边形顶点 roi_points np.array([[100,800], [300,800], [250,200], [50,200]]) def is_in_roi(center_x, center_y): return cv2.pointPolygonTest(roi_points, (center_x, center_y), False) 0 # 滞留判定伪代码 if is_in_roi(cx, cy) and speed 1: idle_frames[tid] 1 # 检查邻近ID nearby_ids [t[4] for t in tracks if np.linalg.norm([cx-t[0], cy-t[1]]) 100] if len(nearby_ids) 0: # 周围无人 if idle_frames[tid] 90: # 90帧3秒30fps alert_log.append(fID{tid} at {time_str} in fire_exit)4.3 自动生成毕设报告PDF用Jinja2模板把结果嵌入LaTeX别手敲Word报告用Python自动生成带图表的PDF用pandas汇总CSV数据 → 生成折线图matplotlib用jinja2渲染LaTeX模板含\includegraphics{heatmap.pdf}用latexmk编译成PDF# report_generator.py from jinja2 import Template import pandas as pd template_str r \documentclass{article} \usepackage{graphicx} \begin{document} \section*{人流量统计报告} 日均通行量{{ daily_avg }}人次\\ 早高峰峰值{{ peak_hour }}人次{{ peak_time }}\\ \includegraphics[width0.8\textwidth]{{{ chart_path }}} \end{document} template Template(template_str) html_out template.render( daily_avgint(df[count].mean()), peak_hourint(df[count].max()), peak_timedf.loc[df[count].idxmax(), time], chart_pathcharts/daily_trend.pdf ) with open(report.tex, w) as f: f.write(html_out) # 终端执行latexmk -pdf report.tex5. 部署到树莓派4B不求实时但求答辩时能“跑起来”毕设答辩最怕“老师说演示一下你打开电脑等5分钟加载模型”。树莓派4B4GB RAM虽不能实时跑YOLOv5s但降帧率降分辨率INT8量化后能做到2.1 FPS勉强可演示5.1 三步压缩模型体积步骤命令效果ONNX导出python export.py --weights runs/train/campus_yolov5s/weights/best.pt --include onnx127MB → 118MBTensorRT优化trtexec --onnxyolov5s.onnx --saveEngineyolov5s.trt --fp16118MB → 62MB推理快2.3倍INT8校准trtexec --onnxyolov5s.onnx --int8 --calibcalib_cache.txt62MB → 28MB树莓派可加载注意树莓派不支持TensorRT得用onnxruntime。所以实际走ONNXOpenVINOIntel CPU或ONNXArmNN树莓派原生。我选后者sudo apt install openvino-dev python3 -m pip install onnxruntime-openvino5.2 树莓派实测配置清单项目配置备注OSRaspberry Pi OS (64-bit) 2023-10必须64位32位不支持ONNX Runtime OpenVINOPython3.9.2sudo apt install python3.9-dev依赖onnxruntime-openvino,numpy,opencv-python-headlessheadless版省内存视频源USB摄像头Logitech C920IPC网络流在树莓派上丢包严重本地USB最稳分辨率640×480YOLO输入尺寸树莓派GPU扛不住1280×7205.3 最小可行演示脚本pi_demo.pyimport cv2 import numpy as np import onnxruntime as ort # 加载ONNX模型INT8量化版 session ort.InferenceSession(yolov5s_int8.onnx, providers[CPUExecutionProvider]) # 树莓派无GPU provider cap cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) while cap.isOpened(): ret, frame cap.read() if not ret: break # 预处理BGR→RGB→归一化→NHWC→NCHW img cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) img img.astype(np.float32) / 255.0 img np.transpose(img, (2, 0, 1)) # HWC→CHW img np.expand_dims(img, 0) # CHW→NCHW # 推理 outputs session.run(None, {images: img}) # outputs[0] shape: (1, 25200, 6) → [x,y,w,h,conf,cls] # 解析结果简化版只画框 boxes outputs[0][0] for box in boxes: if box[4] 0.5: # conf x1 int(box[0] - box[2]/2) y1 int(box[1] - box[3]/2) x2 int(box[0] box[2]/2) y2 int(box[1] box[3]/2) cv2.rectangle(frame, (x1,y1), (x2,y2), (0,255,0), 2) cv2.imshow(Raspberry Pi Demo, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()运行命令# 关键限制内存使用否则OOM sudo systemctl set-property --runtime user.slice MemoryLimit2G python3 pi_demo.py6. 我的毕设答辩后记三个被问爆的问题和真实回答6.1 “为什么不用YOLOv8它不是更新吗”我答“YOLOv8官方没开源DeepSORT集成方案而毕设要求‘检测跟踪’闭环。YOLOv5的track.py已内置ByteTrack但ByteTrack在低帧率场景ID切换率比DeepSORT高12%我实测数据。YOLOv5s的PyTorch生态更成熟GitHub上ultralytics/yolov5的issue区有327个DeepSORT适配案例v8只有41个。选稳定不是保守是降低不可控风险。”6.2 “数据集只有3段视频会不会过拟合”我打开results.csv指着val/box_loss曲线“看第87epoch后loss开始回升我在85epoch手动stop。同时用--evolve超参进化跑了24小时找到最优lr00.008、mosaic0.7让模型在验证集mAP0.5稳定在0.73±0.02。过拟合不是数据少是没做正则——我加了--augment开启MosaicHSV增强等效把3段视频扩增为12段。”6.3 “系统如何保证7×24小时运行”我调出systemd服务配置# /etc/systemd/system/flow-detector.service [Unit] DescriptionPeople Flow Detector Afternetwork.target [Service] Typesimple Userpi WorkingDirectory/home/pi/flow-detector ExecStart/usr/bin/python3 /home/pi/flow-detector/run.py Restartalways RestartSec10 EnvironmentPYTHONUNBUFFERED1 [Install] WantedBymulti-user.target“Restartalways确保崩溃自启RestartSec10防高频重启。run.py里每30分钟写一次心跳日志用journalctl -u flow-detector -f实时监控。真正的可靠性不在算法多炫而在让老师看到‘这系统能自己活下来’。”最后想说毕设不是交差是你第一次把技术变成可触摸的东西。我调试DeepSORT ID切换率那周每天凌晨三点改max_age参数咖啡泼在键盘上但当热力图第一次在答辩电脑上流畅滚动那种“成了”的感觉比任何分数都真实。希望这篇笔记帮你少走些弯路把力气花在真正值得的地方。希望帮到你。本文还有配套的精品资源点击获取
返回列表