资讯动态

基于YOLOv5的口罩识别检测系统实战:从数据集构建到部署

发布时间:2026/9/8 8:58:27 来源:尧图企业网站定制
简介面向人工智能与深度学习初学者及开发者这份资源提供了一套完整的口罩识别检测系统实现方案。系统基于YOLOv5框架构建包含训练好的权重模型与配套数据集可直接对图片、视频、摄像头画面进行口罩佩戴检测适合课堂实验、算法学习或快速原型验证。压缩包共一百五十个文件整体约一百四十兆字节核心包括四十个源码文件、三个预训练模型文件以及四十四个配置文件和若干参数设置文件另含Dockerfile文档、教程笔记本、Shell脚本与测试图片等便于在不同环境中部署与二次开发。资源已吸引一千七百六十一人学习使用读者能够获得完整模型、数据样例与可运行代码从而快速复现检测效果并深入理解YOLOv5的工程实现细节。目录结构清晰训练与推理模块相对独立便于按需阅读和迁移到其他检测任务。 我在实际开发这套“基于深度学习的口罩识别检测系统”时最初并不是为了写论文或者交作业而是真有一个需要落地的场景某个工厂园区在特殊时期要求所有进入人员必须佩戴口罩靠保安盯着监控画面看显然不现实。于是我就想着用视觉检测的方式做一套能自动识别“有没有戴口罩”“口罩戴得规不规范”的系统。做完之后我把整套东西整理成了一个项目压缩包里面包含完整源码、标注好的数据集以及训练收敛后的权重模型。这篇博文就把这个项目的完整技术链路拆开讲一遍从方案选型到数据构建从训练调参到部署推理最后再补上我自己踩过的坑和排查思路希望能帮到正在做类似目标检测项目的朋友。这套内容比较适合两类人一是刚学完深度学习基础、想找一个完整项目练手的同学二是确实需要“戴口罩检测”这类特定场景识别能力的开发者可以参考整个落地方案。1. 项目整体设计与方案选型思路1.1 为什么选择YOLO系列作为检测模型口罩检测本质上是目标检测任务就是要在图像中找出人脸区域并判断该人脸是否佩戴了口罩。这个任务在检测思路上有一个明显的特殊性它必须依赖人脸作为上下文。如果只看一小块布料的纹理很容易把衣服领子、围巾等误判成口罩。所以模型需要在“找人脸”和“判口罩”之间做到某种程度的特征耦合。当前主流的目标检测方案里两阶段模型比如Faster R-CNN精度高但速度偏慢单阶段模型YOLO系列、SSD速度快但传统版本在小目标上容易翻车。考虑到这套系统后续要跑在普通CPU或者低端GPU上还要能处理摄像头实时视频流我最终选定了YOLOv5s作为基础模型。这个选择有几个理由首先YOLOv5的推理速度在同等精度下非常能打模型体积也小其次它对PyTorch生态友好训练和导出的资料多遇到问题好查再就是它的工程化程度足够高数据加载、数据增强、分布式训练、模型导出这些环节都已经封装得比较完善不需要我去重复造轮子。新版YOLOv8在结构上做了优化精度更高但v5的资料更丰富适合快速复现所以我保留了v5s版本作为主方案。1.2 系统架构与整体工作流整套系统在架构上分成三个模块数据层、模型层、应用层。数据层负责训练集的准备包括图像采集、标注、清洗和增强模型层负责YOLOv5s的训练、验证和导出应用层则是一个基于OpenCV和PyTorch的推理脚本支持图片、视频文件和本地摄像头三种输入源。应用层推理的流程是读取视频帧或图片送入模型前先将图像resize到640×640做归一化处理模型输出为检测框坐标、置信度和类别ID后处理阶段对检测框做NMS非极大值抑制去重最后在原始图像上绘制检测结果并把统计信息比如“未戴口罩人数”打印到画面上。整套流程看起来不复杂但后处理阶段的阈值选择和NMS参数设置对实际效果影响很大我在后面的常见问题部分会专门讲。2. 数据集构建与预处理实战2.1 数据来源与类别设计数据是这套系统的地基直接决定模型上线的表现。我这次构建数据集的思路是“公开数据打底 自采数据补盲区”。目前网上有若干公开的口罩人脸检测数据集常见的包括口罩遮挡人脸数据集MaskedFace-Net、东京大学的日系人工合成口罩数据集MAFA、Kaggle上的Face Mask Detection数据集等。我最终选用了Kaggle上的Face Mask Detection数据集作为主源同时从其他数据集中挑选了一部分形态差异较大的图片作为补充。在类别设计上我参考了Kaggle数据集的标注规范把类别设置成三个with_mask、without_mask、mask_weared_incorrect。之所以不采用简单的二分类是因为实际场景里“口罩戴在下巴上”“口罩只遮住嘴没遮住鼻子”这类情况非常常见。如果模型只学习“戴”和“没戴”两类这些不规范佩戴的情况就会被强行划分到其中一类导致误报率上升。三分类的方式让模型能更精细地表达状态也更贴近真实管理需求。如果你想快速验证流程也可以把后两类合并成二分类但生产环境我建议保留三分类。2.2 标注规范与数据清洗标注工作请务必使用统一工具。我这边用的是LabelImg一套基于Python的开源图像标注工具输出格式为Pascal VOC的XML文件。YOLO训练需要的是YOLO格式的TXT标注文件因此标注完成后还需要把XML转成TXT。转换的核心逻辑是从XML里读取出目标框的左上角坐标(x_min, y_min)和右下角坐标(x_max, y_max)然后计算中心点坐标和宽高最后除以图像的宽和高得到归一化后的相对坐标。格式是类别ID、中心点x、中心点y、目标框宽、目标框高所有数值均用空格分隔。数据清洗这一步很多人容易忽略但它对训练结果的影响特别大。我清洗时重点做三件事第一删掉大量重复或近似重复的图像避免模型在训练时对同一张图的特征过度拟合第二剔除标注框明显过小、目标面积低于图像总面积1%的样本这类微小目标会让模型学习到大量无意义的噪声第三检查并修正类别标签出错的数据尤其是“mask_weared_incorrect”这类容易混淆的标注需要人工逐张核对。整个清洗过程我花了大约两个半天虽然费时间但后面训练时收敛速度明显快了很多。2.3 数据增强策略与划分方式口罩检测的数据增强策略和通用目标检测任务基本一致但有一个细节需要注意像随机翻转、随机裁剪、颜色抖动这类常规增强都可以用但要谨慎使用强旋转。因为口罩的佩戴角度、人脸姿态在真实场景里不会出现大角度倒置如果训练集里出现过度旋转的样本模型反而会对不合理的姿态产生错误认知。最终划分时我按8:1:1的比例切分训练集、验证集和测试集。切换前先把每个类别的样本数量统计出来确保三个子集里各类别比例接近整体分布避免出现测试集里某一个类别数量极少导致评估指标失真。这一步可以用Python脚本实现也可以用YOLO自带的工具直接划分。如果数据量大建议分层采样即按类别比例抽样而不是简单随机打乱。3. 模型训练与核心源码解析3.1 训练环境配置与参数选择先说一下训练环境的配置。我用的是一张RTX 3060 12GB显卡CUDA版本为11.8PyTorch为1.13.1版本Python环境为3.8。深度学习环境配置这块如果从零开始最容易出问题的是CUDA、cuDNN和PyTorch版本之间的匹配关系。建议直接通过conda创建独立环境然后用pip安装对应版本的torch和torchvision不要手动去装全局的CUDA工具包容易把系统环境搞乱。这条经验在多个项目里验证过报错概率会降低很多。训练的核心参数我在这里给出一个可以直接参考的配置输入图像分辨率640×640batch size为16训练100个epoch使用COCO预训练权重作为初始权重。优化器选择SGD初始学习率0.01动量0.937权重衰减0.0005。选择预训练权重的逻辑是COCO数据集包含80类常见物体模型在它上面学到过丰富的通用视觉特征尤其是各类边缘、纹理、形状特征。迁移到口罩数据集上只需要在顶部检测头部分做调整训练速度更快收敛效果更好。3.2 核心源码模块解读这套项目的源码结构基本沿用YOLOv5的工程结构但我在推理部分做了一些定制让调用更简单。目录下比较关键的几个文件如下detect.py推理脚本负责加载模型、读取输入、执行前向推理、输出可视化结果。train.py训练脚本启动训练流程支持命令行参数。data.yaml数据配置文件定义了类别数量、类别名称、训练集路径和验证集路径。models/yolov5s.yaml模型结构配置文件定义了网络的深度和宽度。如果你要从零开始训练复杂度会更高但用预训练权重时结构配置会自动和预训练权重对齐。runs/train/exp*/weights/best.pt保存的最佳模型权重这是验证集上表现最好的模型。推理部分的源码核心逻辑我保留为相对简洁的结构读入图像转换为letterbox格式保持长宽比并resize到640×640空白部分用灰色填充归一化后传入模型。模型输出的向量形状为[batch, 25200, 85]其中25200是YOLOv5在640分辨率下三个尺度特征图拼接后的候选框数量85等于4个坐标信息加1个目标置信度再加80个类别置信度。针对本项目类别数量是3因此最后一位维度会相应变化。拿到原始输出后用置信度阈值0.25过滤低置信度框再用NMS方法去除重叠框最后把坐标映射回原图尺寸。如果你习惯用YOLOv8流程也类似只是输出结构会有差异但后处理思路完全一致。3.3 用训练好的模型跑通推理流程拿到训练好的best.pt权重之后验证项目是否能跑通最快的方式就是执行推理。命令如下python detect.py --weights best.pt --source ./test_images --conf-thres 0.4 --iou-thres 0.5当你第一次运行这条命令时需要注意几个细节。--source参数支持传入图片文件夹、单张图片、视频文件路径甚至可以直接填摄像头设备号比如0表示调用内置摄像头。--conf-thres是置信度阈值阈值调高可以减少误检但也会漏掉一些低置信度的目标阈值调低则反之。实际使用中口罩正面的置信度普遍偏高我习惯设置在0.4左右既能保持较高的检出率又能过滤掉大部分假阳性框。--iou-thres是NMS的IoU阈值这个参数决定了两个重叠检测框会被合并还是保留。默认0.45左右即可调得太高会导致同一目标出现多个框调得太低又会把目标靠得非常近的两个真目标合并成一个框需要根据实际场景微调。检测结束后推理结果会保存到runs/detect/exp目录下。如果输入是图片输出也是图片如果输入是视频输出则是带有检测框和标签的标注视频。我在实际测试时直接喂入一段园区门口采集的监控视频能较稳定地框出人脸并区分“正确佩戴口罩”和“未佩戴口罩”。在GPU环境下处理速度可以达到实时在CPU环境下处理速度会明显下降但也不会完全卡死这说明YOLOv5s在边缘设备上具备一定的可用性。4. 常见问题排查与性能优化经验4.1 训练踩坑实录与解决我在训练过程中遇到的最典型问题有两个一是loss不下降二是显存不足。loss不下降的排查思路是先看数据加载是否正常检查训练集图片路径是否正确、标注文件是否为空或是否损坏、类别索引是否从0开始且是否越界。排除数据问题后再看学习率是否设置过高导致震荡。实践中我发现把初始学习率从0.01降到0.005或者0.001多数情况下loss曲线就能稳定下降。这里要注意的是YOLOv5的训练脚本内置了warmup阶段前几个epoch会逐渐提升学习率所以即使看起来前面几个epoch的loss没什么变化也不用太担心。如果几十个epoch后曲线还是平的再去排查数据问题。显存不足的话优先调小batch size比如16降到8。如果只是想快速实验流程还可以调小输入分辨率从640降到512或者416但同时要注意目标框尺寸也会相应变小可能会影响小目标检测精度。还有一个常用方案是开启梯度累积通过增大累积步数来等效扩大batch size但显存本身不够时效果有限因为单次前向计算需要的内存并没有减少。4.2 模型效果不佳时的检查清单模型训练完以后先别急着换模型结构用下面这张检查清单逐步排查现象可能原因排查与解决办法漏检多置信度阈值设置太高调低conf-thres观察阈值变化对检出率的影响误检多数据集中负样本不足、背景单一增加包含干扰物的负样本在数据增强中增加随机裁剪背景块类别混淆“未规范佩戴口罩”样本太少补充该类别数据或将该类别合并到“未佩戴口罩”中戴口罩人脸被漏检训练集中该姿态/角度样本不足增加侧脸、低头、仰头等姿态的样本做轻微旋转增强边框位置不准标注框不够贴合目标返回标注阶段检查标注框是否把口罩四周的空白也框进去了这张表的核心思想是遇到问题先回到数据再调阈值最后才考虑换模型。很多新手一上手就换各种网络结构结果问题反而越换越多。4.3 项目扩展思路这个项目的价值并不局限在“口罩识别”这个窄场景里。只要把数据集换掉这套源码基本可以平移到安全帽检测、黄马甲检测、明火烟雾检测等大多数工业安全场景。核心要做的事只有三件一是整理目标场景的数据集并完成标注二是修改data.yaml里的类别信息三是重新训练模型。对于想深入学习深度学习的人来说这个项目是一个很好的模板因为它完整覆盖了从数据到模型到部署的全流程比只看理论结构和学习单个网络模型更容易建立全局认知。如果还想进一步优化精度可以尝试在训练好的best.pt基础上用更多真实场景数据做增量训练或者引入更轻量的骨干网络比如ShuffleNetV2来做移动端部署。5. 写在最后的实操心得这套口罩识别检测系统做到最后精度的提升已经不是最难的部分了最难的其实是数据分布的把握和阈值的选择。我实际测试时发现同一个模型在室内摄像头和室外强光环境下的表现差异很大根源就在于训练数据里室内场景占比过高。后来我在标注数据时专门补充了一批户外场景的样本模型在户外的表现才明显改善。因此我建议所有做类似检测项目的人在构建数据集的阶段就尽量“多想一步”把目标场景里可能出现的拍摄角度、光线变化、遮挡情况全都纳入考虑而不是等到模型上线后再疯狂打补丁。这算是整个项目里我个人最有体会也最想分享的一个经验。如果你手头正好也要做类似的目标检测项目这套源码和思路可以直接作为起点遇到具体问题也欢迎对照文中的排查思路进行定位。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价