基于YOLOv8与DeepSORT的实时人流量检测系统实战
简介这份资源面向计算机相关专业的毕业设计、课程设计与期末综合作业场景提供一套基于深度学习的实时人流量检测系统完整方案与Python源码。项目已通过导师审核并获优秀评价涵盖数据收集与预处理、模型训练与评估、实时视频流检测计数等环节后端可依托TensorFlow或PyTorch构建神经网络核心run.py负责整合模型加载、视频流处理与结果输出并配有部署说明与使用指南初学者也能快速上手。压缩包共1482个文件约61.53MB以382个html、194个js、208个png等前端与界面资源为主另有76个py源码、32个pyc、8个md文档及若干json、yaml配置兼顾代码、文档与展示素材。目前已有57人学习下载适合需要完整可运行项目、排错思路与目录结构参考的学生与开发者。1. 实时人流量检测系统从 YOLO 到 DeepSORT 的工程化落地商场入口的摄像头画面里人一多就糊成一片靠人工盯屏统计进出人数十分钟就眼花。基于深度学习的实时人流量检测系统要解决的就是这件事用目标检测模型把人框出来再用多目标跟踪算法给每个人分配稳定 ID最后按越线规则计数。整套流程用 Python 就能跑通从模型推理到业务逻辑不超过 500 行核心代码。适合有 Python 基础、想做一个能落地的深度学习实战项目的开发者也适合需要快速验证客流统计方案的工程团队。源码解析的重点不在模型结构本身而在检测与跟踪的衔接、ID 跳变处理和计数逻辑的鲁棒性。2. 检测与跟踪的选型为什么是 YOLOv8 DeepSORT2.1 检测模型选型精度、速度与部署成本的三角权衡实时人流量检测的第一环是行人检测。常见做法有三类两阶段检测器Faster R-CNN 系列、单阶段检测器YOLO 系列、SSD、以及基于 Transformer 的 DETR 系列。两阶段精度高但推理慢DETR 对小目标友好但训练成本高YOLO 系列在速度和精度之间取得了最好的平衡。YOLOv8 是目前工程落地中最常见的选择原因有三一是 Ultralytics 封装的 Python API 极其简洁三行代码就能完成推理二是 n/s/m/l/x 五个尺寸覆盖了从边缘设备到服务器的全部场景三是社区生态成熟导出 ONNX、TensorRT 的路径清晰。对于人流量检测这种只需要检测“人”一个类别的任务YOLOv8n 或 YOLOv8s 就足够了在 1080p 画面上用 GPU 推理可以轻松跑到 60 FPS 以上。如果部署在边缘设备如 Jetson Nano、树莓派可以考虑 YOLOv8n 导出 NCNN 或 ONNX Runtime牺牲少量精度换取实时性。我一般会先用 YOLOv8s 在目标硬件上测一轮 FPS如果低于 15 FPS 再降级到 n。2.2 跟踪算法选型DeepSORT 的工程优势与边界检测只给出每一帧的人框帧与帧之间没有关联。跟踪算法要解决的是第 1 帧里的张三和第 10 帧里的张三怎么判定是同一个人。常见方案有 SORT、DeepSORT、ByteTrack、OC-SORT。DeepSORT 在 SORT 的基础上增加了外观特征提取网络ReID通过卡尔曼滤波预测轨迹、匈牙利算法做匹配、级联匹配处理遮挡。它的优势是 ID 切换率低适合人流量检测这种需要稳定计数的场景。ByteTrack 速度更快但依赖检测质量遮挡严重时 ID 跳变明显。OC-SORT 在非线性运动场景下表现更好但工程资料相对少。我选 DeepSORT 的核心理由是它的 ReID 特征在人群密集、短暂遮挡的场景下能显著降低 ID 跳变而人流量计数最怕的就是同一个人被重复计数。代价是每帧要多跑一次 ReID 网络FPS 会下降 20% 到 30%。如果硬件吃紧可以换 ByteTrack但计数逻辑要加去重策略。2.3 最小可跑通环境搭建先确认 Python 版本。YOLOv8 要求 Python 3.8 以上DeepSORT 的依赖对 3.11 兼容性一般建议用 3.9 或 3.10。安装命令如下# 创建虚拟环境避免污染全局包 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 安装核心依赖 pip install ultralytics8.1.0 pip install deep-sort-realtime1.3.2 pip install opencv-python4.9.0.80 pip install numpy1.24.3这里选deep-sort-realtime而不是原版deep_sort因为前者封装更干净、依赖更少且支持直接传入检测框和置信度。ultralytics的版本锁定在 8.1.0 是因为后续版本 API 有变动源码解析以这个版本为准。验证安装是否成功import ultralytics from deep_sort_realtime.deepsort_tracker import DeepSort import cv2 print(ultralytics.__version__) print(cv2.__version__)如果ultralytics导入报错大概率是 torch 版本不匹配。先pip install torch torchvision再重试。CPU 环境下 torch 安装包约 200MBGPU 版本需要根据 CUDA 版本去 PyTorch 官网找对应命令。3. 从视频流到计数检测、跟踪、越线判定的完整链路3.1 用 YOLOv8 做行人检测的最小代码先跑通单帧检测确认模型能正确框出人。YOLOv8 预训练权重在 COCO 数据集上训练过其中 class 0 就是 person不需要自己训练就能用。from ultralytics import YOLO import cv2 # 加载预训练模型首次运行会自动下载权重 model YOLO(yolov8s.pt) # 读取一帧测试 frame cv2.imread(test.jpg) results model(frame, classes[0], conf0.5, iou0.45) # 解析检测结果 for r in results: boxes r.boxes for box in boxes: x1, y1, x2, y2 box.xyxy[0].tolist() conf box.conf[0].item() print(fperson: ({x1:.0f},{y1:.0f})-({x2:.0f},{y2:.0f}) conf{conf:.2f})classes[0]只保留 person 类减少后处理开销。conf0.5是置信度阈值低于这个值的框直接丢弃人流量场景建议设 0.4 到 0.6太低会引入误检太高会漏掉远处的小目标。iou0.45控制 NMS 的合并阈值人群密集时可以调到 0.5 到 0.6避免相邻的人被合并成一个框。3.2 DeepSORT 跟踪器初始化与参数调优DeepSORT 的核心参数有三个max_age、n_init、max_iou_distance。它们直接决定 ID 稳定性和计数准确性。from deep_sort_realtime.deepsort_tracker import DeepSort tracker DeepSort( max_age30, # 轨迹丢失后保留的帧数 n_init3, # 连续命中多少帧才确认新轨迹 max_iou_distance0.7, # IOU 匹配阈值 embeddermobilenet, # ReID 特征提取网络 embedder_gpuTrue, # 有 GPU 就开 halfTrue # 半精度推理省显存 )max_age30意味着一个人被遮挡后轨迹保留 30 帧约 1 秒等待重新匹配。设太小会导致遮挡后 ID 跳变设太大会让离开画面的人被错误匹配到新出现的人。n_init3要求连续 3 帧检测到才确认轨迹能过滤掉单帧误检。max_iou_distance0.7是 IOU 匹配阈值人群密集时可以降到 0.5 到 0.6减少错误匹配。3.3 检测结果转 DeepSORT 输入格式YOLO 输出的框格式是[x1, y1, x2, y2]DeepSORT 需要的是[left, top, width, height]加置信度。这个转换看起来简单但坐标格式写错是新手最常见的翻车点。def yolo_to_deepsort(results, conf_threshold0.5): 将 YOLO 检测结果转为 DeepSORT 输入格式 detections [] for r in results: for box in r.boxes: conf box.conf[0].item() if conf conf_threshold: continue x1, y1, x2, y2 box.xyxy[0].tolist() # DeepSORT 需要 [left, top, w, h] w x2 - x1 h y2 - y1 detections.append(([x1, y1, w, h], conf, person)) return detections注意box.xyxy[0]返回的是 tensor必须.tolist()转成 Python 列表否则 DeepSORT 内部做数值计算时会报类型错误。person这个类别标签在 DeepSORT 里只是透传不影响跟踪逻辑但方便后续按类别过滤。3.4 越线计数用线段交叉判断进出方向计数逻辑是整个系统最容易出玄学问题的地方。常见做法是画一条虚拟线判断人的中心点是否从线的一侧移动到另一侧。但直接用中心点位置判断会有抖动问题人在线上来回走会导致反复计数。更稳的做法是用轨迹的历史点做线段交叉判断def check_crossing(track_history, line_start, line_end): 判断轨迹是否跨越计数线 if len(track_history) 2: return 0 prev track_history[-2] curr track_history[-1] # 用叉积判断两点是否在线的两侧 def cross_product(p, a, b): return (b[0]-a[0])*(p[1]-a[1]) - (b[1]-a[1])*(p[0]-a[0]) d1 cross_product(prev, line_start, line_end) d2 cross_product(curr, line_start, line_end) if d1 * d2 0: # 异号说明跨越了 # 再用方向判断是进还是出 return 1 if d1 0 else -1 return 0track_history保存每个 ID 最近若干帧的中心点。叉积异号说明两点在线的两侧即发生了跨越。方向由d1的符号决定正负分别对应进和出。这个逻辑比单纯判断中心点位置稳定得多因为要求连续两帧都在线的不同侧才触发。4. 避坑与排查ID 跳变、漏检、计数翻倍的实战记录4.1 同一个人被分配多个 ID现象画面里一个人走过去计数结果加了 3 次。原因n_init设得太小比如 1单帧误检也会创建新轨迹或者max_age太小遮挡几帧后轨迹被删除重新出现时分配了新 ID。解决n_init至少设 3max_age设 25 到 30。如果 ReID 特征质量差换embeddermobilenet为torchreid但速度会慢一些。另外检查检测框是否抖动严重可以加一个简单的中心点平滑滤波。4.2 远处的人检测不到现象画面远端的人漏检计数偏少。原因YOLOv8 默认输入尺寸是 640远处的人在这个分辨率下只有十几个像素特征不足以触发检测。解决把推理尺寸调到 1280 或 1536model(frame, imgsz1280)。代价是 FPS 下降约 40%。另一个办法是用切片推理SAHI把大图切成小块分别检测再合并但工程复杂度高。我一般先试imgsz1280不够再考虑切片。4.3 计数线附近来回走导致反复计数现象有人在计数线附近徘徊计数结果反复加减。原因中心点抖动导致叉积符号反复变化。解决加一个冷却时间同一个 ID 在 2 秒内只允许计数一次。或者要求轨迹连续 3 帧都在线的同一侧才确认跨越。代码里加一个last_count_time字典按 ID 记录上次计数时间。4.4 GPU 显存溢出现象跑一段时间后报CUDA out of memory。原因DeepSORT 的 ReID 特征缓存没有及时释放或者 YOLO 推理的中间张量累积。解决在 DeepSORT 初始化时设halfTrue用半精度每处理 1000 帧手动torch.cuda.empty_cache()如果还不行把max_age降到 20 减少轨迹缓存。CPU 环境下不会溢出但速度会慢很多建议至少用 GTX 1660 以上的卡。4.5 视频流读取延迟累积现象处理速度跟不上视频帧率延迟越来越大。原因用cv2.VideoCapture逐帧读取时如果处理时间超过帧间隔缓冲区会累积。解决开一个独立线程专门读帧只保留最新一帧丢弃旧帧。或者用cap.grab()跳帧每处理一帧就 grab 掉几帧。实时场景下宁可丢帧也不要累积延迟。5. 进阶技巧用轨迹平滑和区域过滤提升计数准确率5.1 卡尔曼滤波平滑轨迹中心点DeepSORT 内部已经用了卡尔曼滤波做轨迹预测但输出的to_tlbr()仍然是原始检测框。如果检测框抖动严重可以在外层再加一层简单的移动平均from collections import deque class TrackSmoother: def __init__(self, window5): self.history {} # track_id - deque of centers self.window window def update(self, track_id, center): if track_id not in self.history: self.history[track_id] deque(maxlenself.window) self.history[track_id].append(center) # 返回平滑后的中心点 xs [c[0] for c in self.history[track_id]] ys [c[1] for c in self.history[track_id]] return (sum(xs)/len(xs), sum(ys)/len(ys))window5表示用最近 5 帧的平均值。窗口太大会导致响应滞后太小起不到平滑效果。5 到 7 是比较平衡的值。这个平滑只用于计数判断不影响 DeepSORT 内部的匹配逻辑。5.2 用多边形区域过滤无效检测实际场景中画面边缘可能有玻璃反光、广告牌上的人像等干扰。用多边形区域限定检测范围只统计区域内的目标import cv2 import numpy as np def filter_by_region(detections, polygon): 只保留中心点在多边形内的检测框 valid [] for det in detections: bbox, conf, cls det cx bbox[0] bbox[2] / 2 cy bbox[1] bbox[3] / 2 if cv2.pointPolygonTest(polygon, (cx, cy), False) 0: valid.append(det) return valid # 定义有效区域顺时针顶点 region np.array([[100, 200], [1800, 200], [1800, 1000], [100, 1000]], np.int32)pointPolygonTest返回正值表示点在多边形内。区域顶点按顺时针或逆时针排列都可以但不能自交叉。这个过滤放在检测之后、跟踪之前能显著减少误检带来的虚假轨迹。5.3 用计数结果做异常告警人流量数据本身就有业务价值。比如商场入口每分钟超过 50 人时触发拥堵告警或者夜间检测到人时触发安防告警。实现方式很简单维护一个滑动窗口计数器每 10 秒统计一次import time from collections import deque class FlowMonitor: def __init__(self, window_sec10, threshold50): self.events deque() # (timestamp, direction) self.window window_sec self.threshold threshold def add_event(self, direction): self.events.append((time.time(), direction)) def get_flow_rate(self): now time.time() # 清理窗口外的数据 while self.events and now - self.events[0][0] self.window: self.events.popleft() return len(self.events) / self.window * 60 # 每分钟人数 def check_alert(self): rate self.get_flow_rate() return rate self.threshold, ratewindow_sec10表示用最近 10 秒的数据估算每分钟流量。窗口太短波动大太长响应慢。10 到 30 秒是比较实用的范围。告警阈值根据场景调整商场入口和地铁闸机的合理值完全不同。5.4 验证计数准确率的土办法没有标注数据的情况下怎么知道计数准不准我的习惯是录一段 5 分钟的视频人工数一遍进出人数然后跑系统对比。误差在 5% 以内算合格超过 10% 就要查 ID 跳变和漏检。重点看计数线附近有没有反复加减以及遮挡区域有没有 ID 切换。这个土办法比任何指标都直接因为最终要的是业务数字对得上。踩过的坑里最深的永远是参数硬编码。max_age、conf、imgsz这些值在不同场景下最优解完全不同我现在的习惯是把它们全部提到配置文件里换一个摄像头就重新调一轮。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

YOLOv5果蔬识别实战:从数据清洗到产线PLC控制

YOLOv5果蔬识别实战:从数据清洗到产线PLC控制

简介:本资源是一套完整的YOLOv5果蔬识别系统实战项目,面向计算机专业本科生毕业设计、课程设计及深度学习初学者,解决目标检测领域中水果蔬菜类别识别与定位的典型任务。压缩包共56个文件,含14个Python训练与推理脚本(…

2026/10/11 12:20:20 阅读更多 →
【单片机课设毕设项目】基于 STM32 的孵化器温湿度监测与自动调温通风装置设计 基于物联网的老旧住宅室内空气安全监测预警系统设计(030121)

【单片机课设毕设项目】基于 STM32 的孵化器温湿度监测与自动调温通风装置设计 基于物联网的老旧住宅室内空气安全监测预警系统设计(030121)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机,Java、小程序技术领域和毕业项目实战 ✌️…

2026/10/11 12:20:19 阅读更多 →
PHP支付系统源码实战:易支付对接、回调验签与快手免CK部署

PHP支付系统源码实战:易支付对接、回调验签与快手免CK部署

简介:一套多通道支付系统源码,兼容易支付接口,面向网站站长、商城与发卡网运营者,整合快手小店保证金、快手免CK、快币支付等特色通道,并支持支付宝与微信的跳转、扫码支付。资源包共两千个文件,以后端业务…

2026/10/11 12:20:19 阅读更多 →

最新新闻

面对模糊需求如何落地项目?从rea代号拆解到技术选型与实现

面对模糊需求如何落地项目?从rea代号拆解到技术选型与实现

1. 当标题只剩三个字母:一次“信息真空”下的项目复盘拿到“rea”这个标题的时候,我第一反应是愣了一下。没有项目正文,没有关键词,没有摘要描述,连热搜词和网络热词都是空的。换句话说,这是一个几乎零信息…

2026/10/11 13:11:50 阅读更多 →
HBuilderX.zip解压即用原理与跨端开发实战指南

HBuilderX.zip解压即用原理与跨端开发实战指南

简介:本资源为HBuilderX官方集成开发环境安装包,面向前端开发者、uniapp初学者及跨平台应用实践者,解决Vue.js与多端项目开发环境快速搭建问题。压缩包为标准ZIP格式,大小306.77MB,内含完整可执行安装程序及配套运行时…

2026/10/11 13:11:50 阅读更多 →
PHP风控实战:活体识别集成方案与接口对接详解

PHP风控实战:活体识别集成方案与接口对接详解

1. 风控场景下的活体识别需求拆解1.1 为什么传统身份核验方式已经不够用了做过风控系统的人都有一个共识:身份核验这件事,从来不是"验一次就完事"的。早些年大家做实名认证,无非就是姓名加身份证号二要素比对,后来升级到…

2026/10/11 13:11:50 阅读更多 →
WIN7老主板USB3.0驱动安装与DISM镜像注入实战指南

WIN7老主板USB3.0驱动安装与DISM镜像注入实战指南

简介:这份资源是专为Windows 7系统准备的USB3.0驱动程序包,主要面向使用SKYLAKE平台及以上CPU、需要通过USB设备安装或恢复系统的用户。在原生支持USB3.1但向下兼容USB3.0的硬件环境下,若未预先加载该驱动,Win7安装程序往往无法识…

2026/10/11 13:11:50 阅读更多 →
Java 实现 HEIC 转 PNG/JPEG 全攻略:选型、性能与避坑

Java 实现 HEIC 转 PNG/JPEG 全攻略:选型、性能与避坑

简介:这份资源面向需要在Java环境中处理HEIC图片的开发者,尤其是遇到苹果设备素材、旧系统或第三方库不支持该格式的兼容性场景。HEIC基于HEVC编码,压缩效率优于JPEG,但Java标准库并不原生支持解码,因此项目围绕借助Im…

2026/10/11 13:11:50 阅读更多 →
代码随想录67天刷题总结:算法模板、避坑与面试转化

代码随想录67天刷题总结:算法模板、避坑与面试转化

代码随想录刷到第67天,说实话,这一天比我想象中来得平静。没有“终于结束了”的解脱感,也没有“我全都学会了”的兴奋,更多的是一种踏实的收束感。从第一天的数组二分查找开始,到后来二叉树、回溯、动规、单调栈&#…

2026/10/11 13:10:49 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →