YOLOv5打电话行为检测实战:从数据集标注到PyQt界面部署

发布时间:2026/10/11 20:42:53
YOLOv5打电话行为检测实战:从数据集标注到PyQt界面部署
简介本资源面向计算机视觉入门与进阶开发者提供一套完整的YOLOv5打电话行为检测方案可用于课堂演示、安防场景原型验证或毕业设计参考。包内包含训练好的打电话识别权重与配套数据集标注同时提供txt和xml两种格式并分目录存放方便直接训练或迁移到其他检测任务。资源共165个文件涵盖34个Python源码、32个编译文件、27个YAML配置、26张JPG样本图、4个pt权重、4个UI界面文件以及mp4演示视频等压缩包约433.91MB目录结构清晰便于按模块查阅。项目基于PyTorch框架实现并配有PyQt可视化界面支持图片、视频与摄像头三种输入方式可直观查看检测效果。目前已有604人学习下载适合希望快速跑通打电话行为识别流程、理解数据标注与模型推理衔接的读者参考借鉴。1. 从一通没接到的电话说起这套 YOLOv5 打电话行为检测资源到底能干什么去年帮一个做工地安全监管的朋友看现场视频甲方要求识别工人有没有在作业时打电话。我第一反应是拿现成的开源权重跑一遍结果 COCO 预训练模型里根本没有「打电话」这个类人、手机、手三个框各检各的逻辑拼起来误报率高得离谱。后来自己标数据、训模型、写界面前后折腾了小两周。今天拆的这套资源就是把这个过程打包好了YOLOv5 打电话行为检测的完整工程带训练好的权重、标注好的数据集还有一个 PyQt 写的可视化界面。它解决的不是「YOLO 怎么用」这种入门问题而是「我手上有一堆监控画面想快速跑通打电话行为识别不想从零标数据」这个具体诉求。适合做安防、工地、考场、加油站这类场景的算法落地同学也适合想拿一个完整闭环项目练手的学生。资源里模型、数据、界面三件套齐全拿到手就能推理想改类别也能接着训。2. 拆开这个压缩包目录结构、权重格式与数据集标注规范2.1 工程目录长什么样每个文件夹负责什么拿到资源先别急着跑detect.py花五分钟把目录结构看清楚后面排错能省一半时间。这类 YOLOv5 行为检测工程常见做法是沿用 ultralytics 那套目录约定再额外挂一个 PyQt 的界面目录。典型结构大致是这样phone_detection/ ├── data/ # 数据集配置与标注 │ ├── images/ │ │ ├── train/ # 训练集图片 │ │ └── val/ # 验证集图片 │ ├── labels/ │ │ ├── train/ # 训练集标签YOLO txt 格式 │ │ └── val/ │ └── phone.yaml # 数据集描述文件 ├── models/ # 网络结构定义 │ └── yolov5s.yaml ├── weights/ │ └── best.pt # 训练好的权重 ├── utils/ # 通用工具NMS、绘图、指标 ├── runs/ # 训练/推理输出 ├── detect.py # 命令行推理入口 ├── train.py # 训练入口 ├── requirements.txt └── ui/ # PyQt 界面 ├── main.py └── mainwindow.uidata/是数据侧的全部家当phone.yaml决定模型去哪找图、去哪找标签、类别名是什么。weights/best.pt是训练收敛后保存的最优权重.pt是 PyTorch 的序列化格式里面既存了网络参数也存了类别信息。ui/是独立的一块通过调用detect.py里的推理函数或者直接加载模型来出结果。理解这个分层你就知道改类别该动phone.yaml换模型该动weights/调界面该动ui/互不干扰。2.2 数据集标注格式YOLO txt 的五个数字怎么读这套资源的数据集是 YOLO 格式每张图对应一个同名.txt每行代表一个目标框格式是class_id x_center y_center width height后四个都是归一化到 0~1 的相对值。举个例子一张 640×480 的图里有个打电话的人框在左上角标签文件里可能长这样0 0.312500 0.416667 0.187500 0.333333第一个0是类别索引对应phone.yaml里names列表的第 0 项比如[phone_call]。后面四个数分别乘以图宽图高就还原成像素坐标中心点 x200、y200宽 120、高 160。这里最容易翻车的是归一化基准搞错——有人拿标注工具的绝对坐标直接除以 1000结果框全飘了。正确做法是除以图片真实的宽和高标注工具导出时一般会自动算好但如果你自己写脚本转换务必确认这一点。提示验证标签是否规范最快的办法是拿utils/general.py里的可视化函数把框画回原图肉眼扫一遍比看数字靠谱。2.3 权重文件与类别映射为什么换了数据集必须改 yamlbest.pt里固化了训练时的类别数量和名称。如果你拿这套权重去跑一个只有「打电话」一类的场景没问题但如果你想加「抽烟」这个新类光改phone.yaml不够还得重新训或者做微调因为检测头的输出维度是按类别数定死的。常见做法是先确认phone.yaml的nc类别数和names与权重一致再决定是直接推理还是接着训。用下面这段代码可以快速读出权重里的类别信息避免瞎猜import torch # 加载权重map_location 保证在无 GPU 的机器上也能读 ckpt torch.load(weights/best.pt, map_locationcpu) # 不同版本 YOLOv5 保存结构略有差异做兼容处理 model ckpt[model] if model in ckpt else ckpt names model.names if hasattr(model, names) else ckpt.get(names) print(类别数:, len(names)) print(类别名:, names)map_locationcpu是为了在没有 CUDA 的机器上也能加载不然会报找不到设备的错。ckpt里通常有model、ema、optimizer等键推理只关心model或ema。打印出来的names如果和你phone.yaml里写的不一致那推理结果的类别名就会张冠李戴这是新手最常踩的坑之一。3. 把模型跑起来从单图推理到 PyQt 界面联调的完整链路3.1 环境依赖与最小可跑配置先解决环境。这套工程依赖 PyTorch、OpenCV、PyQt5 这几样requirements.txt里一般会列全。我一般习惯用 conda 建个干净环境避免和系统里的包打架conda create -n phone_det python3.8 -y conda activate phone_det # 按自己机器的 CUDA 版本装 torch没有 GPU 就装 CPU 版 pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu pip install -r requirements.txtPython 3.8 是这类工程的稳妥选择太新的版本有时会和旧版 PyQt5 冲突。--index-url那行按你实际环境换有 GPU 就装对应 CUDA 版本的 torch。装完先跑一句python -c import torch; print(torch.__version__)确认没报错再往下走。requirements 里如果有版本号锁死别随手升级YOLOv5 各版本 API 差异不小升一个包可能连带一串报错。3.2 命令行推理detect.py 的参数怎么设环境通了先用命令行验证模型能不能出结果别一上来就开界面界面报错你分不清是模型问题还是 UI 问题。典型调用python detect.py \ --weights weights/best.pt \ --source data/images/val \ --img-size 640 \ --conf-thres 0.4 \ --iou-thres 0.45 \ --device cpu \ --save-txt--weights指向训练好的权重--source可以是单张图、文件夹、视频甚至摄像头编号0--img-size 640是推理分辨率要和训练时一致否则精度会掉--conf-thres 0.4是置信度阈值低于它的框直接丢打电话这种场景建议从 0.4 起调太低误报多太高漏检--iou-thres 0.45控制 NMS 合并重叠框的力度--device cpu没 GPU 时显式指定不然会尝试调 CUDA 报错--save-txt把结果存成标签格式方便你回头核对。跑完去runs/detect/exp/看输出图框画得对不对一眼就知道。3.3 PyQt 界面怎么和推理后端对接界面这块是很多人卡住的地方。PyQt 主线程负责刷新 UI推理是耗时操作如果直接在按钮回调里跑detect界面会卡死甚至无响应。常见做法是把推理丢到QThread里通过信号槽把结果传回主线程更新画面。核心逻辑大概这样from PyQt5.QtCore import QThread, pyqtSignal import cv2 import torch class DetectThread(QThread): # 定义信号传回带框的图像 frame_ready pyqtSignal(object) def __init__(self, model, source): super().__init__() self.model model self.source source self.running True def run(self): cap cv2.VideoCapture(self.source) while self.running and cap.isOpened(): ret, frame cap.read() if not ret: break # 推理实际调用工程里的 detect 函数 results self.model(frame, size640) annotated results.render()[0] # 画框后的图 self.frame_ready.emit(annotated) # 发信号给主线程 cap.release() def stop(self): self.running FalseQThread子类里重写run把读帧和推理放进去pyqtSignal定义跨线程通信的信号。frame_ready.emit(annotated)把画好框的图发出去主线程接到信号后setPixmap到 QLabel 上。self.running是个开关窗口关闭时调stop()让循环退出不然线程挂着进程退不掉。这里的关键是所有 UI 操作只能在主线程做子线程只管算和发信号这是 Qt 的铁律违反了就是随机崩溃。注意如果界面里要同时显示原图和结果图别在子线程里直接操作控件老老实实发信号。3.4 用滑动窗口滤波压一压抖动视频推理有个玄学问题同一辆车、同一个人相邻帧的框会轻微跳动置信度也忽高忽低界面上看着像在抽搐。常见做法是加一层滑动窗口滤波对连续 N 帧的检测结果做平滑。思路很简单维护一个固定长度的队列存最近几帧的框输出时取均值或中位数from collections import deque import numpy as np class BoxSmoother: def __init__(self, window5): self.window window self.history deque(maxlenwindow) def update(self, box): # box 格式 [x1, y1, x2, y2] self.history.append(box) if len(self.history) self.window: return box arr np.array(self.history) # 取中位数比均值更抗离群点 return np.median(arr, axis0).astype(int)window5表示用最近 5 帧平滑太大响应会迟滞太小压不住抖动5 到 7 是常用区间。用中位数而不是均值是因为偶尔一帧检测飘了均值会被带偏中位数更稳。这个滤波只对同一目标的轨迹做多目标场景要先做简单的 IOU 匹配再分别平滑不然框会串。加了这层之后界面上的框明显稳当甲方看着也舒服。4. 避坑与排查这套资源落地时最容易翻车的五个地方4.1 现象推理结果全是同一个类或者类别名显示成数字原因phone.yaml里的names和权重里的类别顺序对不上或者根本没配names代码回退成索引显示。解决用 2.3 那段脚本读出权重里的names逐字对照phone.yaml改一致。顺序错了比数量错了更隐蔽因为不报错只是结果全错。4.2 现象PyQt 界面点开始后卡死窗口拖不动原因推理跑在主线程阻塞了 Qt 的事件循环。解决按 3.3 的方式把推理放进QThread用信号槽回传结果。如果已经用了线程还卡检查是不是在子线程里直接调了QLabel.setText之类的 UI 方法那是跨线程操作控件必须改成发信号。4.3 现象训练 loss 不降或者降了但验证集精度上不去原因学习率、batch size 和数据集规模不匹配或者标注里有大量空标签、错标。解决先拿几十张图过一遍可视化确认标注没问题学习率从 0.01 起试batch size 按显存给小数据集别用太大 batch。YOLOv5 的超参数在data/hyp.scratch.yaml里改之前先备份。4.4 现象换到新场景误报率飙升把低头看手机全判成打电话原因训练集场景太单一模型学到了背景捷径比如「手靠近耳朵」这个特征在训练集里总伴随打电话换场景就失效。解决补标新场景的负样本尤其是「看手机但没打电话」这类难例重新微调。别指望一个数据集打天下行为检测对场景敏感度很高。4.5 现象CPU 上推理慢到没法用界面一帧要好几秒原因--img-size设太大或者没做模型轻量化。解决推理分辨率降到 416 甚至 320 试精度损失或者换 yolov5s 这种小模型。如果非要 CPU 实时考虑导出 ONNX 再用 onnxruntime 跑通常比原生 PyTorch 快一截。GPU 部署的话确认--device 0且 CUDA 可用。5. 进阶把打电话检测接到自己的业务流里以及怎么验证它真的靠谱资源跑通只是起点真正落地要解决「怎么接进现有系统」和「怎么证明它稳定」。先说接入。这套工程的推理函数是纯 Python 的最省事的做法是把它包成一个 HTTP 服务用 FastAPI 起一个接口业务系统传图片或视频帧过来返回 JSON 结果。这样前端、后端、算法解耦换模型不影响调用方。核心就是把detect里的预处理、推理、后处理抽成一个函数输入 numpy 数组输出框列表和类别外面套一层路由即可。再说验证。行为检测最怕的是「演示时好好的上线就翻车」。我一般会做三件事第一准备一个独立的测试集跟训练集不同来源、不同光照、不同角度跑一遍看 mAP 和误报率别只看训练曲线第二做长时间稳定性测试让界面或服务连续跑几个小时观察内存有没有缓慢上涨、帧率有没有衰减PyQt 长期运行内存泄漏是常见问题多半是信号槽没断开或者图像对象没释放第三针对业务定义明确的验收指标比如「打电话识别准确率不低于 90%误报每小时不超过 2 次」拿这个去卡而不是拿「看起来还行」去交差。参数上还有几个可以抠的点。置信度阈值不要全局一刀切可以按场景调工地这种远距离小目标阈值适当降到 0.35考场这种近距离可以提到 0.5 压误报。NMS 的 IOU 阈值在人群密集场景要调低避免把相邻两个人的框合并成一个。如果发现模型对某些角度特别不敏感别急着换模型先看训练集里这类样本够不够行为检测的瓶颈往往在数据分布不在网络结构。最后说个我自己的习惯。每次拿到一个新的行为检测权重我不会直接信它的精度报告而是先拿一段自己拍的、带各种干扰的真实视频跑一遍人工数一遍漏检和误报心里有个底再决定用不用。这套资源的价值在于它把数据、模型、界面都给你备齐了省掉的是从零搭建的时间但省不掉你对业务场景的理解和验证。从那以后我每次部署行为检测模型都强制走一遍独立测试集加长稳测试宁可上线前多花半天也不想上线后被追着改。希望帮到你。本文还有配套的精品资源点击获取