2026/10/18 4:10:40

PyQt5+YOLOv10人群计数桌面应用:从模型训练到毕设答辩完整指南

PyQt5+YOLOv10人群计数桌面应用:从模型训练到毕设答辩完整指南 把“人群计数”这种听起来偏学术的方向落成一个能答辩、能演示、还能放进作品集的桌面应用这个选题在本科毕设里属于性价比很高的一档。PyQt做界面YOLOv10做检测计数这两个词一组合基本就是一个思路非常清晰的工程型课题先训练模型再做软件包装最后对着摄像头或图片数人头。我用这个题目带过几个学弟学妹也帮人改过类似的框架这里把整个项目从选题到答辩的完整思路拆开讲一遍包括哪些坑必须要避、哪些细节能直接拉开你和其他人的差距。先给没接触过这个方向的同学说清楚人群计数解决的问题很简单就是给定一张图片或一段视频算法自动算出画面里有几个人。传统做法是 density map 回归出一张热力图再积分现在主流做法是目标检测直接把每个人框出来数框。YOLOv10 走的是后者它的优势在于实时性和易用性配上 PyQt 的界面做出来的东西既能实时跑摄像头也能批量分析图片毕设展示时效果非常直观。接下来说说我在实际做这个项目的过程中每一步是怎么考虑的以及那些别人不会在论文里告诉你的细节。1. 项目内核拆解你要做的其实是一套“检测-计数-展示”链路刚拿到这个题目的时候最容易犯的错是直接去搜“PyQt YOLO 人群计数代码”然后抄一份就跑。这种做法放到答辩现场会非常尴尬因为老师的问题会集中在“你为什么用这个方案”“你的模型是怎么训练的”“数据怎么处理的”只要有一个环节说不清楚整个项目就会被打上“非原创”的标签。这个项目真正要做的是把三条技术线串起来目标检测模型选 YOLOv10 作为检测框架负责从图像中找出每个人的边框。这一步解决的是“人在哪里”的问题。计数的实现逻辑检测出所有人形框之后统计框的数量就是当前画面的总人数。这里有个细节YOLO 输出的是框的坐标、类别索引和置信度你需要自己写 NMS 去重或直接用官方内置的 NMS然后筛选出 class 为人通常是 class 0的框再做 count。很多教程里没有把这一步单独讲清楚实际上它是整个计数逻辑的核心。桌面应用的封装用 PyQt5 或 PyQt6 搭建一个窗口程序包含打开图片、打开视频、摄像头实时检测、结果显示等功能。这个层面解决的是“怎么让用户方便地用”的问题。如果只是调用一个现成的检测模型然后把框画出来谈不上“方法研究”。要在毕业论文里把题目撑起来核心在于处理策略、模型选型对比、数据增强、推理优化的这几个环节每一步你都要有自己思考和实验的记录。1.1 为什么选 YOLOv10 而不是 YOLOv8 或传统算法这里我帮你理清选型逻辑方便你写进论文“方案选型”那一节。人群计数大致有三条路线传统图像处理方法用 HOG SVM 做行人检测或者用背景建模提取运动目标。优点是计算量小缺点是密集场景下精度极差一旦两个人挨得近HOG 特征直接失效。密度估计方法CSRNet 这类网络直接回归 density map输出一张和原图同尺寸的热力图每个像素值代表该位置的人的密集程度。这个方向的精度在极度拥挤的场景下很高但训练需要人头点标注数据标注成本极大而且密度图可视化后不够直观——你没法告诉老师“这个框就是张三”。目标检测方法YOLO 系列、Faster R-CNN 这类直接输出人形框。优点是直观、容易工程化、部署方便缺点是在极度密集的情况下例如演唱会现场容易漏检。但作为本科毕设选这个方向的平衡性非常好学生的可操作性最强展示效果也最好看。至于为什么在 YOLO 系里选 10 而不是 8 或 9我的看法是选 10 的最大意义是“实时性好 技术新颖”。YOLOv10 的论文核心是 NMS-free 的训练策略在推理阶段去掉了 NMS 这一步延迟更低。你可以在论文里明确对比 YOLOv8 和 YOLOv10 的推理速度、mAP 值这就形成了一组具有说服力的对比实验。不必担心版本太新没有资料YOLOv10 的官方仓库一直在更新部署资料很齐全。1.2 你需要准备哪些工具和环境直接列一份可以照抄的环境清单系统Windows 10/11 或 Ubuntu 20.04 都可以建议 Windows方便演示和打包 exe语言Python 3.8 或 3.10 均可网上大多数资料基于 3.8如果卡在依赖问题上可以切版本深度学习框架PyTorch 1.8 以上YOLOv10 依赖 PyTorch不能用 TensorFlow 直接跑GPU最好有一张显存 6G 以上的 NVIDIA 显卡。没有 GPU 可以用 CPU 凑合训练小模型但会非常慢建议用免费的云端 Notebook 训练YOLOv10 仓库直接 clone 官方仓库不要用别人魔改的版本PyQt5用于桌面应用界面这个小节看起来简单但实际被卡住最多的就是环境问题。常见的坑torch 版本和 CUDA 不匹配import 直接报错ultralytics 包版本太高导致 YOLOv10 的某些接口被废弃。遇到这种问题最直接的方案是新建一个干净的虚拟环境torch 版本锁定为 1.13 配合 CUDA 11.7ultralytics 用官方 requirements 里锁定的版本别一上来就装最新版。2. 数据处理与模型训练决定项目上限的硬功夫PyQt 界面是皮模型精度才是骨架。如果模型在测试集上漏检严重界面做得再漂亮也没用。这一节是你在毕设里真正要展示“工作量”的地方。2.1 训练数据的搜集与预处理方案人群计数模型的训练数据一般有两个获取途径公开数据集有几个经典的比如 ShanghaiTech分为 A 部分和 B 部分、UCF-QNRF、VisDrone。这些数据集里的人群密度差异很大用它们既能训练模型也能说明模型在不同场景下的泛化能力。自建数据集从网上下载带有行人的街景图片或者自己用手机在不同场地拍然后用标注工具比如 LabelImg手动标注。注意如果你用了公开数据集论文里必须标注清楚来源并且说明是你“基于公开数据集进行微调训练”不能写“作者采集”。训练数据准备的三个细节直接影响模型效果第一标注格式要统一。YOLO 格式的标签是一个 txt 文件每行对应一个目标class x_center y_center width height。这里的 x_center、y_center、width、height 都是相对图片尺寸归一化后的值。如果你混用了不同来源的数据集一定要统一转换成这种格式否则训练直接报错。第二筛选掉不清晰的图片。很多公开数据集中存在严重模糊、遮挡面积过大或人脸极小的样本。把这些样本留下来模型会被带偏训练过程反而更难收敛。我处理数据时通常会做一轮人工清洗把分辨率过低的图片删掉因为人群计数的本质需要看清人体轮廓太糊的图没有意义。第三数据划分不要乱。训练集、验证集、测试集的比例建议 7:2:1。其中测试集必须是从未参与训练的数据用来模拟真实场景下的性能否则答辩现场演示时翻车了会很尴尬。2.2 模型训练的配置与参数选择用 YOLOv10 训练时有以下几个参数需要你仔细调。输入尺寸imgsz默认是 640。人群密集场景中小目标多可以适当提升到 1280但推理速度会变慢。我的建议是先在 640 下训练一版作为 baseline再用 1280 微调一个版本对比两者的 mAP 和速度把对比结果写进论文。batch size取决于显存大小。6G 显存建议 8-1612G 显存可以到 32。如果在云平台训练选 V100 或 A100 的实例可以直接拉到最大。epochs一般 100-300 轮足够收敛。重点看验证集 loss不要死板地跑满 300 轮loss 很久不降就该停了。数据增强YOLO 自带的增强包括随机翻转、缩放、色彩抖动等这些默认参数通常够用。人群场景下可以额外开启 mosaic它会把四张图拼接成一张训练对提升小目标检测能力很有帮助。训练过程中要记得做一件事打开 save_period 参数每训练一定轮数就保存一次权重。这样即使后面训练崩了你也可以回溯到中间某一步继续调。很多新手没开这个参数跑了两天发现验证集 loss 发散连重新来过的机会都没有。以我用官方 YOLOv10s 模型在上海数据集上训练的经验来看最终的 mAP50 通常在 0.7-0.8 之间。这个数值不算高但放在人群计数场景中是合理的因为密集场景下遮挡太严重换更好的模型也未必能大幅提升。答辩时你可以坦诚说明这一点然后把重点放在分析漏检场景上——这种“知道自己模型的边界在哪里”的回答反而给老师留下好印象。2.3 模型评估不要只报一个准确率论文里写实验结果时尽量把这几个指标都列出来撑起对比分析的篇幅Precision查准率检测出的人形框中确实是人的比例。越高说明误检越少。Recall查全率真实的人中被检测出来的比例。越高说明漏检越少。mAP0.5IoU 阈值为 0.5 时的平均精度均值YOLO 系列训练日志里会直接给出。FPS每秒处理帧数体现实时性。这个指标也直接对应 PyQt 演示时的流畅度。这些指标的计算逻辑你至少要能当着老师的面用一句大白话说出来。我记得有次预答辩同学只说了 mAP 是 0.75老师反手就问“mAP 的全称是什么怎么算的”当场卡住。这种基础概念真的得提前背熟。3. PyQt 桌面应用开发把模型变成老师能上手操作的产品这一节是大多数同学第一次接触 GUI 开发的环节也是最终答辩时老师真正会去点击操作的部分。不要把它想得很难PyQt 的开发逻辑就像搭积木布局 控件 信号槽。3.1 界面功能设计与布局一个合格的人群计数软件至少需要以下几个功能区域左上角操作面板放三个按钮——打开图片、打开视频、打开摄像头。中间区域图像显示区用 QLabel 或 QGraphicsView 显示带检测框的实时画面。右侧或底部结果面板显示当前帧人数、检测耗时单位 ms、FPS。底部菜单栏帮助、退出、模型版本选择。功能上需要补充三个细节图片模式点击“选择图片”后弹出文件对话框选中图片后执行推理然后把画好框的图片显示在界面上。这个功能用于静态场景的演示。视频模式用 OpenCV 的 VideoCapture 读取视频帧逐帧送入模型推理再把结果转回 QImage 显示在界面上。注意这里需要用一个 QTimer 或线程来控制帧率否则界面会卡死。摄像头实时模式逻辑与视频模式相同只需把 VideoCapture 的入口参数从文件路径改为 0代表默认摄像头。答辩现场用这个模式效果最炸因为它的“实时性”是肉眼可见的。3.2 Python 中 PyQt 和 YOLO 模型的核心交互代码以下是界面初始化的核心逻辑我写的是 PyQt5 配合官方 YOLO 模型接口的框架import cv2 import torch from PyQt5.QtWidgets import QMainWindow, QLabel, QPushButton, QFileDialog, QVBoxLayout, QWidget from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtCore import QTimer from ultralytics import YOLO class CountApp(QMainWindow): def __init__(self): super().__init__() self.model YOLO(best.pt) # 加载训练好的权重 self.cap None self.timer QTimer(self) self.timer.timeout.connect(self.process_frame) self.init_ui() def init_ui(self): self.setWindowTitle(人群计数系统) self.setGeometry(100, 100, 900, 600) self.image_label QLabel(self) self.image_label.setFixedSize(640, 480) # ... 按钮布局省略这里有个和纯脚本跑模型不一样的地方PyQt 的主线程不能做推理这种耗时操作否则画面会卡顿。解决方式有两种。第一种是最简单的用 QTimer 每隔 50ms 触发一次帧读取和推理如果推理速度在一帧 30ms 以内这种方案完全够用。第二种是开 QThread 子线程专门做推理用信号把帧结果传回主线程。从毕设角度说用第一种就足够了但如果你论文里写了“多线程架构”那代码就要改成第二种否则答辩被深挖就露馅了。推理部分的代码可以这么写def process_frame(self): ret, frame self.cap.read() if not ret: self.timer.stop() self.cap.release() return results self.model(frame, verboseFalse)[0] person_count 0 for box in results.boxes: cls int(box.cls[0]) conf float(box.conf[0]) if cls 0 and conf 0.5: person_count 1 x1, y1, x2, y2 map(int, box.xyxy[0]) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) # 显示人数 cv2.putText(frame, fPerson Count: {person_count}, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) rgb_frame cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch rgb_frame.shape bytes_per_line ch * w qt_image QImage(rgb_frame.data, w, h, bytes_per_line, QImage.Format_RGB888) self.image_label.setPixmap(QPixmap.fromImage(qt_image))很多同学一上来直接查 PyQt 的 drawRect 去画框但绕了一圈最稳的还是在 OpenCV 层面把框画好再转成 QImage 显示。这个思路省掉了大量坐标换算的时间实测效果也不错。需要单独强调一个关键点在显示图像时必须将 OpenCV 的 BGR 格式转为 RGB否则画面颜色会是蓝红色的很掉档次。还有就是 QImage 的构造参数有很多重载请确保传入 bytes_per_line也就是每行字节数不然图片可能显示为斜着的花纹。3.3 打包成 exe 的注意事项毕设答辩经常要现场演示如果电脑上没有安装 Python 环境和依赖最稳妥的办法是提前打包成 exe 文件。用 PyInstaller 是最主流的方式pip install pyinstaller pyinstaller -w -F main.py -i icon.ico这里有几个值得说的坑。第一-w参数表示不显示命令行窗口但如果你用了 print 调试就看不到输出建议调试阶段先不加-w。第二-F是打包成单文件方便拷贝但启动时间会变慢因为要临时解包如果你要分发给老师演示单文件更省心。第三也是最重要的一个协议问题打包出来的 exe 体积会很大通常 300MB-1GB因为里面带上了 PyTorch 和 CUDA 库。这个体积是正常的不要想着压缩PyTorch 生态决定了它小不了。最好在答辩用的 U 盘里放一份 exe 和一份源码环境备份以防现场机器无法运行。如果你打包完成双击后没有任何反应排查优先级是先看文件路径有没有中文和空格再看 NVIDIA 显卡驱动是否正常最后看杀毒软件是否隔离了临时文件。这是一个在实验室测试没问题、换台机器就崩掉的经典问题。4. 答辩实战怎么把项目讲得让老师无可挑剔做项目的最终目的是通过答辩。我不建议把毕设答辩当作一堂“汇报课”准备应该当作“商业模式路演”准备——围绕一个目标让老师在短时间内相信这个工作有价值、有工作量、且是你亲手做的。4.1 演示流程设计演示时间通常只有 5-8 分钟。建议直接按这个节奏来。前 1 分钟项目背景。说明人群计数的现实应用场景例如公共场所安全隐患排查。简单两句话介绍 YOLOv10 是当前工业界使用广泛的目标检测算法。中间 2 分钟模型训练过程。展示你用的公开数据集中的样例图片简单说一下标注格式再展示训练过程中 loss 曲线下降图。重点放在“我当时做了什么实验调整”来体现工作量。重头戏约 3 分钟软件演示。先打开一张图片识别再切到摄像头实时演示。如果现场有其他人走入摄像头范围你可以顺势解说“检测到了 XX 人说明模型可以实时识别动态人群”。最后 1 分钟结果分析。展示精确率、召回率、mAP 数值表格。坦诚说明在密集场景下会有漏检并说明后续改进方向比如融合注意力机制或者使用密度图回归模型。预答辩的时候我见过不少同学一上来就点开摄像头结果镜头对着老师界面上一堆检测框乱跳。要优先演示图片因为图片是静态的你可以控制结果摄像头很容易引入不可控变量。还有一个容易被忽略的细节提前在答辩机器上把需要展示的视频和图片素材放在“桌面”路径这样比较简单的地址上。很多人把素材放在“项目文件/最新版本/最终版/图片”这种多级目录里现场演示时弹窗找文件局面会非常尴尬。4.2 高频问答预案老师们的提问非常集中我梳理了三个出现频率极高的问题附上了可复述的回答思路。问你用的模型和你直接调用 YOLO 有什么区别 答直接调用 YOLO 的官方预训练权重是在 COCO 数据集上训练的它认识 80 类物体。我的工作是在此基础上用人群数据集做了 fine-tune使模型在稀疏/密集人群场景下的召回率显著提升。同时用 PyQt 框架解决了模型推理结果的业务化展示例如实时计数、画面标注和帧率控制。问你的人群计数结果和阈值有什么关系 答关系主要体现在置信度阈值上。模型会输出每个候选框的置信度0~1只有大于阈值的框才被计为有效目标。阈值设低会把误检也算进去数量偏高阈值设高会漏掉大量被遮挡的人数量偏低。我实验中对比了 0.3/0.5/0.7 三档阈值最终选用 0.5因为它对应的是准确率和召回率的平衡点。问如果场景里面有狗、背包会不会被误判成人 答会存在类似风险主要体现在类别过滤逻辑上。因为我在计数时只取 class index 为 0 的类别COCO 数据集中 person 的类别索引是 0狗的类别是 16所以模型本身已经做过一次过滤。但背包和人贴合在一起时仍然有可能被框进来。这一点在论文里会被认定为正常的识别争议你只需要说明可以配合后续的跟踪或分割算法来优化。4.3 论文写作的对应映射我要特别提醒一点代码工程和论文逻辑是两套话语体系。代码里你写“if cls 0 and conf 0.5”论文里不是直接贴这行代码而是这样写概述本研究选择 YOLOv10 作为基础检测网络在其头部分支中只保留 person 类别对应的输出通道后续以固定置信度阈值 0.5 作为筛选条件低于该阈值的候选框一律视为背景噪声剔除。数据段落在数据预处理部分本研究将多个公开数据集统一为 YOLO 标签格式统一归一化方式并进行人工清洗剔除模糊样本最终获得 5000 张有效图像。实验部分本研究设置了消融实验对比了有/无数据增强、有/无 fine-tune 两种条件的性能差异结果表明 fine-tune 策略能有效提升 mAP 约 9.4%。所谓工作量不是写了多少行代码而是你做了多少个决策——做决策的证据在论文里就是实验数据和对比表格。这一点吃透了你的论文框架就不会是空壳。5. 实操中踩过的坑清单最后把这些经验做一个整理每一条都是自己或学生实际踩过的数据集标注格式混乱。不同来源的公开数据集可能有 VOC 格式、COCO 格式、YOLO 格式。写一个批量转换脚本统一一下是很重要的事不要手动改。训练到一半 loss 陡增。大多是学习率太大或数据增强太猛。把初始学习率从 0.01 降到 0.001或者把 mosaic 概率稍微降低通常能稳住。显卡显存不够。训练时爆显存不一定代表代码的问题可以把 batch size 减半同时打开ampTrue混合精度训练显存开销能减少一半以上。摄像头演示画面卡顿。如果 FPS 只有个位数优先检查是否在视频模式里做了全分辨率推理。可以先用代码把帧 resize 到 1280 再送进模型690 像素的画面在视觉上和原图差异不大但速度能快一大截。PyQt 界面中文乱码。这是 Windows 平台上常见的老问题。直接在代码开头加上import sys并设置编码为utf-8同时尽量避免窗口标题栏以外用复杂中文字体。模型识别不准但是训练数据没问题。大概率是预训练模型的问题可以先试试下载官方 yolo11 或 yolo12 发布的不同尺寸权重效果再做判断。打包 exe 之后无法加载权重。相对路径问题占大头一定要用os.path.dirname(__file__)或Path(__file__).parent定位当前目录不能让程序依赖“当前工作目录”。第一次跑通完整流程大约需要两周时间但绝大多数时间其实是消磨在不同版本兼容性的磨合和数据格式调整上。真正跟模型原理死磕的时间很少。如果时间紧张坚持“先跑通再优化最后写文档”的顺序别一开始就想把所有细节都研究透。你首先要做出来的是一套能按两个按钮、能弹出结果的软件。再透露一个毕业答辩评分的小规律只要系统能实时运行、指标说得清、代码是亲手一颗螺丝拧起来的那这个项目就已经达到毕设的中上水准了。剩下要做的无非是磨嘴皮子把细节深挖到老师忍不住点头的程度。后面如果你想继续扩展这个项目有两个方向可以做插入目标追踪算法给每个人分配一个 ID做越线聚众报警或者接入本地知识库用自然语言查询某个时刻的人流量。但那就不是毕设的范畴了而是它走向真实产品形态的方向。