
简介本资源是一套完整的YOLOv5打电话行为检测实战项目面向计算机视觉初学者与安防、交通监管等场景开发者解决日常监控中对手机使用行为的自动化识别需求。压缩包共165个文件含34个核心Python脚本含训练/推理/界面逻辑、27个配置yaml文件模型结构与超参、26张标注图像及8张界面截图另有4个预训练.pt权重、4个PyQt设计.ui文件、2个实测视频mp4及CSV结果统计文件整体大小为433.91MB。已有600人学习下载项目已通过CSDN博文公开验证效果。用户可直接运行PyQt图形界面一键完成图片、视频及摄像头实时检测配套提供txt与xml双格式标注数据集支持快速迁移训练内容预览显示包含TensorBoard日志、Docker部署文件及完整实验记录results.csv兼顾算法复现、工程部署与结果分析全流程。1. 项目概述与核心价值最近在做一个挺有意思的监控场景项目核心需求是自动检测画面中是否有人正在打电话。这听起来简单但在实际安防、考场管理或者特定工作区域合规检查里是个挺刚需的功能。传统靠人眼盯监控效率低还容易漏用AI来做自动化识别就成了必然选择。我这次选用的技术栈是YOLOv5来完成目标检测然后自己整理数据集、训练模型最后用PyQt做了个带界面的演示程序把整个流程给跑通了。这个项目“YOLOv5打电话行为检测”完整地覆盖了从数据准备、模型训练到应用部署的闭环。对于想入门计算机视觉特别是目标检测应用的朋友来说是个非常不错的练手项目。它不像单纯跑通一个demo那么简单你需要处理实际场景中光照、角度、遮挡等各种问题还得考虑怎么把算法“包装”成一个普通人能用的工具。整个过程下来你对数据标注、模型调参、以及图形界面开发都会有更深的体会。接下来我就把这套方案的思路、踩过的坑和具体实现细节毫无保留地分享出来。2. 项目整体设计与技术选型考量2.1 为什么选择YOLOv5目标检测框架很多比如Faster R-CNN、SSD、YOLO系列等。我最终选择YOLOv5主要是基于以下几点实际考量在精度和速度间取得了很好的平衡YOLOv5虽然不是最新的已有v8、v9等但其代码成熟、社区资源丰富对于“打电话”这种常见行为其精度完全足够。更重要的是它的推理速度非常快在普通的消费级GPU如GTX 1660 Ti上处理一张图片只需几十毫秒这对于后续可能的实时视频流处理至关重要。工程化友好易于上手YOLOv5的PyTorch实现代码结构清晰提供了从训练到部署的完整脚本。它的数据加载、模型定义、训练循环都封装得很好修改起来很方便。特别是对于自定义数据集只需要按照其要求的格式YOLO格式的txt标注文件准备几乎不用改动核心代码。丰富的预训练模型和调参指南YOLOv5提供了从轻量级YOLOv5s到高精度YOLOv5x多个版本的预训练模型。我们可以用在大数据集如COCO上预训练好的权重进行迁移学习这能极大加快我们在小数据集打电话行为上的收敛速度并提升最终效果。官方和社区也有大量的超参数调优经验可供参考。注意虽然YOLOv8等更新版本在指标上可能更优但YOLOv5的稳定性、文档和社区支持对于项目快速落地更为关键。新版本有时会引入较大的变动可能增加学习成本和调试时间。2.2 行为检测的定义与难点“打电话行为检测”严格来说是一个细粒度的目标检测任务但它比单纯的“检测手机”或“检测人”要复杂。核心定义我们需要检测的是“人”与“手机”在特定空间位置上发生的交互行为。最典型的正样本是手机贴近人的耳部区域。主要难点姿态多样性人可能用左手或右手打电话可能站着、坐着、走着手机可能横屏或竖屏。遮挡问题长发可能遮挡耳朵和手机手部也可能部分遮挡手机。类间差异类似的举手动作如挠头、扶眼镜可能被误检。尺度变化监控摄像头距离远近会导致人和手机在图像中的尺寸变化很大。光照与环境室内外光照不均、逆光、夜间低光照等都会影响检测效果。因此我们的方案不能只检测“手机”而是需要同时检测“人”和“手机”并通过它们之间的位置关系如交并比IoU、中心点距离来判定是否为“打电话”行为。一种更鲁棒的做法是直接标注“打电话的人”作为一个整体类别让模型去学习这个复合特征。2.3 PyQt作为图形界面的优势模型训练好后我们需要一个方式来展示效果、进行测试或者给非技术人员使用。PyQt是一个理想的选择跨平台基于Qt可以轻松打包成Windows、macOS、Linux下的可执行文件。功能强大提供丰富的UI组件可以方便地集成图片/视频加载、模型推理、结果展示画框、标签、参数调整等功能。与Python生态无缝集成我们的模型是PyTorch的用PyQt可以都在Python环境下开发避免跨语言调用的麻烦。打包方便可以使用PyInstaller或cx_Freeze等工具将整个Python项目包括模型、界面、依赖封装成一个独立的.exe文件方便分发。3. 数据集构建与处理核心细节3.1 数据收集与标注策略高质量的数据集是模型成功的基石。对于“打电话行为”数据来源可以是公开数据集搜索是否有现成的“cellphone”或“hand calling”相关数据集但通常需要自己整理。网络爬取从合规的图片视频网站爬取相关场景图片需注意版权和隐私。自行拍摄针对特定场景如办公室、考场自行拍摄模拟打电话行为的图片和视频这样数据最贴合实际应用但工作量最大。我采用的是混合策略以部分公开数据为基础补充了大量自行拍摄和从电影、电视剧中截取的片段已脱敏仅用于技术研究。标注工具推荐使用LabelImg或CVAT。这里使用LabelImg因为它简单直接输出就是YOLO格式。标注类别定义 经过权衡我定义了两个类别person标注整个人体。cellphone标注手机。当手机被手持且贴近耳部时才进行标注。更优的方案直接定义一个类别calling标注框覆盖正在打电话的人通常是从头到胸的区域包含手和手机。这样模型直接学习“打电话”这个整体模式避免了后处理逻辑往往效果更好。我最初尝试了双类别方案后期部分数据转向了单类别calling方案进行对比实验。3.2 数据格式与目录结构YOLOv5要求特定的数据格式。假设我们的项目根目录为PhoneCall_Detection。PhoneCall_Detection/ ├── data/ │ ├── images/ # 存放所有图片 │ │ ├── train/ # 训练集图片 │ │ └── val/ # 验证集图片 │ └── labels/ # 存放所有标注文件与图片同名.txt后缀 │ ├── train/ # 训练集标签 │ └── val/ # 验证集标签标签文件.txt格式 每一行代表一个标注框格式为class_id x_center y_center width heightclass_id: 类别索引从0开始。例如0代表person1代表cellphone。x_center, y_center: 边界框中心点的归一化坐标除以图片宽度和高度。width, height: 边界框的归一化宽度和高度。例如一张500x400的图片上有一个person框其左上角为(100,50)右下角为(300,350)则计算如下x_center (100 300)/2 / 500 0.4y_center (50 350)/2 / 400 0.5width (300 - 100) / 500 0.4height (350 - 50) / 400 0.75 标签行即为0 0.4 0.5 0.4 0.753.3 数据增强与预处理为了提升模型泛化能力防止过拟合必须进行数据增强。YOLOv5内置了强大的增强功能在data/hyps/hyp.scratch-low.yaml等配置文件中定义。我们主要关注并可以调整的几项Mosaic将四张图片拼成一张进行训练极大地丰富了背景和小目标上下文。MixUp将两张图片线性混合增加类别和背景的复杂度。色彩空间变换包括色调(H)、饱和度(S)、明度(V)的随机调整模拟不同光照。随机旋转、平移、缩放、剪切模拟视角变化。实操心得对于“打电话”行为要谨慎使用过度的旋转和剪切因为这会破坏“手机贴近耳部”的关键空间关系。我通常会把旋转和剪切的比例调低。相反色彩抖动和模糊增强对提升鲁棒性非常有效。我们需要创建一个自己的数据集配置文件例如data/phonecall.yaml# 数据集路径 path: ../PhoneCall_Detection/data train: images/train val: images/val # 类别数 nc: 2 # 如果使用‘person’和‘cellphone’两类就是2。如果只用‘calling’一类就是1。 # 类别名称列表 names: [person, cellphone] # 或 [calling]4. YOLOv5模型训练全流程解析4.1 环境搭建与代码准备首先从官方仓库克隆代码并安装依赖。# 克隆YOLOv5仓库建议使用较稳定的版本如v6.0 git clone -b v6.0 https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txt # 安装所有依赖踩坑记录PyTorch版本需与CUDA版本匹配。如果使用GPU务必去PyTorch官网核对安装命令。我曾因版本不匹配导致训练时卡死。4.2 模型选择与迁移学习YOLOv5提供了多种规模的模型。对于“打电话检测”这是一个相对简单的任务但为了保证在复杂场景下的精度我选择了中等规模的YOLOv5m。它比YOLOv5s精度更高比YOLOv5l速度更快。启动训练的命令python train.py \ --img 640 \ # 训练图片尺寸 --batch 16 \ # 批次大小根据GPU内存调整 --epochs 100 \ # 训练轮数 --data ../PhoneCall_Detection/data/phonecall.yaml \ # 数据集配置文件 --cfg models/yolov5m.yaml \ # 模型结构配置文件 --weights yolov5m.pt \ # 加载预训练权重这是关键 --name phonecall_exp \ # 本次实验名称 --cache \ # 缓存图片到内存加速训练 --device 0 # 使用GPU 0关键参数解析--weights yolov5m.pt这是迁移学习的精髓。yolov5m.pt是在COCO数据集上预训练好的权重。加载它意味着我们的模型已经从海量数据中学到了如何提取通用特征边缘、纹理、形状等。我们只需要在其基础上针对“打电话”这个特定任务进行微调Fine-tuning这比从零训练快得多效果好得多。--img 640YOLOv5的默认输入尺寸。更大的尺寸如1280可能提升对小目标的检测精度但会显著增加计算量和内存消耗需要同步调整batch-size。--batch 16一次输入16张图片。在GPU内存允许的情况下较大的batch size有助于训练稳定。如果出现CUDA out of memory错误需要降低batch或img大小。--epochs 100通常足够收敛。可以通过观察验证集损失曲线提前停止。4.3 训练过程监控与超参数调优训练开始后YOLOv5会在runs/train/phonecall_exp目录下生成大量有用的文件和可视化结果。results.png最重要的图表包含了训练集和验证集的边界框损失、分类损失、目标性损失以及精度Precision、召回率Recall、mAP0.5等指标。我们的目标是让验证集损失平稳下降且mAP稳步上升。confusion_matrix.png混淆矩阵查看类别间误检情况。例如cellphone是否容易被误检为person或其他背景。val_batch0_pred.jpg验证集样本的预测结果可以直观看到模型当前的表现。超参数调优经验 YOLOv5的超参数定义在data/hyps/目录下。对于自定义数据集微调超参数能带来提升。我主要调整了以下几个学习率lr0这是最重要的参数。预训练权重微调时学习率不宜太大否则会破坏已有的好特征。我通常从默认值如0.01开始如果训练初期损失震荡剧烈就调小如0.001。数据增强参数如前所述降低degrees旋转角度和shear剪切强度以保持打电话姿态的完整性。适当提高hsv_h色调抖动来增强色彩鲁棒性。损失函数权重box_loss,obj_loss,cls_loss的权重。除非有特殊需求一般不建议新手改动。一个实用的方法是使用网格搜索或贝叶斯优化工具如wandb进行自动化调参但手动根据结果分析调整2-3轮也能取得不错效果。4.4 模型评估与导出训练完成后在runs/train/phonecall_exp/weights目录下会得到两个最重要的模型文件best.pt在验证集上表现最好的权重。last.pt最后一轮的权重。我们使用best.pt进行后续的评估和推理。评估模型python val.py \ --data ../PhoneCall_Detection/data/phonecall.yaml \ --weights runs/train/phonecall_exp/weights/best.pt \ --img 640 \ --batch 16 \ --task val \ --name phonecall_eval评估报告会详细列出各个类别的精确率、召回率、mAP等这是我们判断模型好坏的客观标准。一个不错的“打电话”检测模型mAP0.5应该能达到0.85以上。模型导出 为了在PyQt界面中使用我们需要将PyTorch模型.pt导出为更通用的格式。最常用的是TorchScript或ONNX。# 导出为ONNX格式推荐兼容性更广 python export.py \ --weights runs/train/phonecall_exp/weights/best.pt \ --img 640 640 \ # 输入尺寸 (高宽) --batch 1 \ # 批处理大小 --device cpu \ # 导出时指定设备如果部署环境是CPU就选cpu --include onnx \ # 导出为ONNX --simplify # 简化模型导出的best.onnx文件就可以被OpenCV DNN、TensorRT等多种推理引擎加载为后续部署到不同平台包括嵌入式设备提供了便利。5. PyQt图形界面开发与集成5.1 界面设计与功能规划我们的PyQt界面需要实现以下核心功能媒体加载支持选择单张图片、图片文件夹或视频文件。模型加载选择我们训练好的.pt或.onnx模型文件。推理执行点击按钮对当前媒体进行检测。结果可视化在图片/视频帧上绘制检测框、类别标签和置信度。结果输出显示统计信息如检测到的目标数量并可将带标注的结果保存到本地。界面布局可以设计如下左侧为媒体显示区域QLabel右侧为控制面板QGroupBox包含文件选择按钮、模型加载按钮、推理按钮、参数调节滑块如置信度阈值、NMS阈值和结果信息显示区QTextEdit。5.2 推理引擎的集成在PyQt中我们需要一个后台线程来执行模型推理避免阻塞UI主线程导致界面卡死。这里以使用原始PyTorch模型.pt为例展示核心推理代码的集成。首先创建一个专门的工作线程类from PyQt5.QtCore import QThread, pyqtSignal import torch import cv2 import numpy as np class DetectionThread(QThread): # 定义信号用于与主线程通信 finished pyqtSignal(np.ndarray) # 发送处理后的图像 info_updated pyqtSignal(str) # 发送检测信息 def __init__(self, model_path, image, conf_thres0.5, iou_thres0.45): super().__init__() self.model_path model_path self.image image self.conf_thres conf_thres self.iou_thres iou_thres self.model None def run(self): 线程运行的核心函数 # 1. 加载模型懒加载第一次运行时加载 if self.model is None: self.model torch.load(self.model_path, map_locationcpu)[model].float().eval() # 如果使用GPU可以改为 .to(cuda) # 2. 预处理图像 img_rgb cv2.cvtColor(self.image, cv2.COLOR_BGR2RGB) img_resized self.preprocess(img_rgb) # 3. 推理 with torch.no_grad(): pred self.model(img_resized)[0] # 4. 后处理非极大值抑制(NMS) detections self.non_max_suppression(pred, self.conf_thres, self.iou_thres) # 5. 在原图上绘制结果 result_img self.draw_boxes(self.image, detections) # 6. 发送信号 self.finished.emit(result_img) self.info_updated.emit(f检测到 {len(detections)} 个目标) def preprocess(self, img): 将图像预处理为模型输入格式 # 这里需要实现resize, padding, 归一化维度转换等 # 具体代码需参考YOLOv5的utils.datasets.py中的letterbox函数 pass def non_max_suppression(self, prediction, conf_thres, iou_thres): 非极大值抑制过滤重叠框 # 具体实现参考YOLOv5的utils.general.py中的non_max_suppression函数 pass def draw_boxes(self, img, detections): 在图像上绘制检测框 for *xyxy, conf, cls in detections: label f{self.model.names[int(cls)]} {conf:.2f} # 使用cv2.rectangle和cv2.putText画框和文字 pass return img在主界面中我们连接按钮信号启动这个工作线程class MainWindow(QMainWindow): def __init__(self): super().__init__() # ... 界面初始化代码 ... self.detection_thread None self.btn_detect.clicked.connect(self.start_detection) def start_detection(self): if self.current_image is None: return # 禁用检测按钮防止重复点击 self.btn_detect.setEnabled(False) # 创建并启动线程 self.detection_thread DetectionThread( model_pathruns/train/phonecall_exp/weights/best.pt, imageself.current_image, conf_thresself.slider_confidence.value()/100.0 ) self.detection_thread.finished.connect(self.on_detection_finished) self.detection_thread.info_updated.connect(self.text_info.append) self.detection_thread.start() def on_detection_finished(self, result_img): # 在主线程中更新UI self.display_image(result_img) self.btn_detect.setEnabled(True)5.3 性能优化与体验提升视频流处理对于视频检测需要在一个循环中读取帧并送入检测线程。可以使用QTimer定时触发检测或者使用另一个专门的视频处理线程。注意控制检测频率如果每帧都检测且模型较慢会导致严重延迟。可以采用跳帧检测或降低视频显示分辨率。实时性优化模型简化使用更小的模型YOLOv5s或对模型进行剪枝、量化。推理引擎使用TensorRT或OpenVINO对ONNX模型进行加速在相同硬件上可获得数倍的性能提升。硬件加速确保PyTorch使用了GPUCUDA进行推理。参数实时调节将置信度阈值和NMS阈值的滑块信号连接到检测函数实现参数实时调整并立即看到效果变化这对于模型调试非常有用。6. 项目封装、部署与常见问题排查6.1 使用PyInstaller打包为EXE为了让没有Python环境的人也能使用我们将整个应用打包成Windows可执行文件。首先创建一个主程序入口脚本main.py它只负责启动你的PyQt主窗口。然后使用PyInstaller打包。pip install pyinstaller # 基本打包命令 pyinstaller -F -w -i icon.ico main.py-F: 打包成单个exe文件。-w: 运行时不显示控制台窗口对于GUI程序。-i: 设置exe的图标。打包巨坑与解决方案问题1打包后运行提示“No module named ‘torch’, ‘cv2’”等。原因PyInstaller有时无法自动打包所有的二进制依赖。解决在打包命令中通过--hidden-import手动指定或创建一个hook文件。更简单的方法是在虚拟环境中确保所有依赖都已安装然后使用--collect-all参数谨慎使用可能会使包很大。推荐方案使用spec文件进行高级配置。先生成一个基础的spec文件pyi-makespec main.py。然后编辑main.spec在Analysis部分添加隐藏导入a Analysis([main.py], pathex[], binaries[], datas[], # 这里很重要需要把模型文件、配置文件等资源加进来 hiddenimports[torch, torchvision, cv2, PIL, numpy, pyqt5], # 添加所有可能缺失的库 hookspath[], ...)还需要把模型文件等资源复制到exe所在目录需要在datas里指定datas[(runs/train/phonecall_exp/weights/best.pt, .), (data/phonecall.yaml, data)],最后用pyinstaller main.spec命令打包。问题2打包文件体积巨大1GB。原因PyInstaller打包了整个PyTorch和CUDA库。解决使用CPU版本的PyTorch进行打包pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu。在推理代码中确保模型加载到CPUtorch.load(..., map_locationcpu)。使用--exclude-module尝试排除不必要的模块效果有限。终极方案考虑使用ONNX RuntimeCPU版作为推理后端它比完整的PyTorchCUDA小得多。将模型导出为ONNX然后在PyQt中改用onnxruntime库加载和推理。6.2 部署到其他平台Linux/MacPyInstaller同样支持在对应系统下执行打包命令即可。Web服务可以使用FastAPI或Flask将模型封装成RESTful API前端通过网页上传图片并获取检测结果。嵌入式设备如RK3568, RV1106这是另一个深水区。通常步骤是将模型转换为该芯片厂商支持的格式如RKNN for Rockchip, NNIE for HiSilicon。使用C/C编写针对该平台的推理代码并优化内存和速度。编写简单的本地UI如基于Qt for Embedded或直接将结果通过网络发送。 这个过程需要参考芯片厂商的官方SDK和文档挑战较大。6.3 常见问题排查速查表问题现象可能原因排查步骤与解决方案训练时loss为NaN学习率过高数据标注有误如坐标超出0-1数据中存在损坏图片。1. 大幅降低学习率lr0。2. 检查标注文件格式是否正确特别是归一化坐标。3. 使用--cache参数时尝试不使用它或检查图片文件。模型推理速度慢模型过大如用了YOLOv5x未使用GPU推理输入图片尺寸过大。1. 换用更小的模型YOLOv5s/n。2. 确认torch.cuda.is_available()为True模型和数据已.to(‘cuda’)。3. 减小推理时的imgsz参数如从640降到320。检测框闪烁或不稳定视频中视频帧间抖动置信度阈值过低。1. 对检测结果进行轨迹平滑如使用卡尔曼滤波或简单的移动平均。2. 适当提高置信度阈值conf-thres。误检率高将水杯、手等检为手机训练数据中负样本类似物体但不是手机不足手机特征学习不充分。1. 在数据集中增加“困难负样本”如手拿水杯、对讲机等的图片并进行正确标注或作为背景。2. 增加数据增强特别是色彩和模糊让模型更关注形状而非颜色。3. 检查混淆矩阵针对性补充数据。漏检率高尤其是小目标或遮挡目标数据集中小目标和遮挡样本少模型输入分辨率过低。1. 专门收集并标注小尺寸、遮挡严重的打电话图片。2. 提高训练和推理时的imgsz如从640升到1280但要注意计算成本。3. 在数据增强中增加Mosaic和MixUp的比例。PyQt界面点击检测按钮无反应UI被推理线程阻塞信号/槽连接错误。1. 确保推理任务在独立的QThread中运行并通过信号更新UI。2. 使用print或日志检查线程的run函数是否被正确调用。3. 检查按钮的clicked信号是否正确连接到启动线程的槽函数。这个项目从数据准备到最终可用的桌面软件涉及了AI项目落地的多个关键环节。每个环节都有不少细节需要打磨尤其是数据质量和推理性能的优化往往需要反复迭代。希望这份详细的梳理能帮你避开我踩过的那些坑更顺畅地完成自己的目标检测应用。本文还有配套的精品资源点击获取