
简介这份资源是面向计算机相关专业学生与项目实战学习者的YOLOV5口罩检测完整方案适用于毕业设计、课程设计及期末大作业等场景。内容涵盖标注好的数据集、可运行的项目代码、训练好的模型权重以及配套配置文件帮助读者跳过繁琐的数据准备与调参环节直接完成检测系统的搭建与验证。压缩包共149个文件约922.84MB以yaml配置、py源码、pyc编译文件、jpg与jpeg图像样本为主另含pt模型权重、sh脚本、md说明文档及Dockerfile等覆盖训练、推理与部署各环节。目前已有193人学习关注。读者可获得一套结构清晰、经导师指导并获98分评审认可的完整工程既能用于快速复现口罩检测效果也便于在此基础上修改网络结构、替换数据集或撰写论文实验章节适合作为入门深度学习目标检测的实战参考。1. 口罩检测这套东西为什么成了毕业设计里最稳的选题口罩检测这个方向每年毕业季都会被翻出来做一遍。原因很直接需求场景清晰、数据好采、模型不复杂而且 YOLOV5 这套代码框架足够成熟从环境配置到训练到部署网上能查到的资料密度极高。但真正动手做过的人都知道坑不在模型本身而在数据集的质量和标注的一致性上。我见过太多人拿着网上随便找的两千张图就开始训结果 mAP 卡在 0.6 上不去回头一看标注框歪的歪、漏的漏口罩和脸部的边界定义每个人标得都不一样。这套「YOLOV5 口罩检测数据集代码训练好的模型标注好的数据」的组合本质上解决的是一个从零到一的问题你不需要自己去爬图、不需要从零写训练脚本、不需要调一版能跑的推理代码。拿到之后改改路径就能跑通训练换换数据就能迁移到自己的场景。适合的人群也很明确——做毕业设计的学生、需要快速出 demo 的期末大作业、以及想拿一个完整目标检测项目练手但不想在数据采集上耗太久的工程师。但我要先说清楚一件事这套东西的价值不在于「有模型」而在于「有标注好的数据」和「有能复现的训练流程」。模型结构是公开的YOLOV5 的源码谁都能下真正省时间的是那批已经标好的口罩/未戴口罩/错误佩戴的图片以及一套能让你在本地跑通训练、验证、推理的完整链路。接下来我会按「数据怎么用 → 环境怎么配 → 训练怎么跑 → 坑在哪 → 怎么验证和进阶」的顺序把这条链路拆开讲。2. 数据集和标注格式先搞清楚你拿到的是什么2.1 口罩检测数据集的典型构成和类别定义一套能用的口罩检测数据集通常包含三类标注戴口罩mask、未戴口罩no_mask、口罩佩戴不规范mask_incorrect。有些数据集会简化成两类只分戴和不戴。我建议如果你要做毕业设计至少保留三类因为「不规范佩戴」这个类别在答辩时是一个很好的加分点——它能体现你对实际场景的理解比如鼻子露在外面、口罩拉到下巴这些情况。数据量方面一个能训出可用模型的数据集训练集至少要在 3000 张以上验证集 500 到 800 张测试集 300 张左右。如果少于这个量YOLOV5s 这种小模型还能勉强跑但 mAP 会明显偏低。图片的分辨率不要求统一YOLOV5 在训练时会自动 resize 到 640×640但原始图片如果太小比如低于 320×320小目标口罩的检测效果会明显下降。标注格式上YOLOV5 用的是 YOLO 格式的 txt 文件每张图对应一个同名 txt每行是class_id x_center y_center width height坐标都是归一化到 0 到 1 之间的浮点数。如果你拿到的数据是 VOC 的 XML 格式或者 COCO 的 JSON 格式需要先转成 YOLO 格式。这个转换脚本我后面会给。2.2 标注文件的结构和目录组织一个标准的 YOLOV5 数据集目录长这样mask_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── mask_data.yamlimages/train/下面放训练图片labels/train/下面放对应的 txt 标注文件。注意图片和标注文件的文件名必须一致只是扩展名不同。比如images/train/001.jpg对应labels/train/001.txt。mask_data.yaml是数据集配置文件内容如下# mask_data.yaml train: ./mask_dataset/images/train val: ./mask_dataset/images/val test: ./mask_dataset/images/test nc: 3 names: [mask, no_mask, mask_incorrect]nc是类别数names是类别名称列表顺序必须和标注文件里的class_id对应。比如class_id0对应maskclass_id1对应no_maskclass_id2对应mask_incorrect。这个顺序搞错了模型训出来会把戴口罩识别成没戴这种翻车我见过不止一次。提示拿到数据集后第一件事是抽查标注。随机抽 20 张图用 labelImg 或者任何可视化工具打开看框有没有歪、类别有没有标错、有没有漏标。这一步花 10 分钟能省你后面 10 个小时的调参时间。2.3 从 VOC 或 COCO 格式转成 YOLO 格式的脚本如果你拿到的数据是 VOC 的 XML 格式用下面这个脚本转import xml.etree.ElementTree as ET import os from pathlib import Path # 类别映射根据你的数据集修改 class_map {mask: 0, no_mask: 1, mask_incorrect: 2} def convert_voc_to_yolo(xml_dir, img_dir, output_label_dir): xml_dir: VOC标注文件目录 img_dir: 对应图片目录用于获取图片宽高 output_label_dir: 输出的YOLO格式标注目录 os.makedirs(output_label_dir, exist_okTrue) for xml_file in Path(xml_dir).glob(*.xml): tree ET.parse(xml_file) root tree.getroot() # 获取图片尺寸 size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) lines [] for obj in root.findall(object): cls_name obj.find(name).text if cls_name not in class_map: continue cls_id class_map[cls_name] bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 转成YOLO格式中心点坐标和宽高全部归一化 x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) # 写入同名txt文件 txt_path os.path.join(output_label_dir, xml_file.stem .txt) with open(txt_path, w) as f: f.write(\n.join(lines)) # 使用示例 convert_voc_to_yolo( xml_dir./VOC/Annotations, img_dir./VOC/JPEGImages, output_label_dir./mask_dataset/labels/train )这段代码的逻辑很直接遍历 XML 文件读取图片宽高把 VOC 的xmin, ymin, xmax, ymax转成 YOLO 的中心点加宽高格式再做归一化。关键参数是class_map你必须根据自己数据集的类别名称修改这个字典否则所有框都会被跳过。另外注意img_w和img_h是从 XML 里读的如果 XML 里没有 size 字段就需要用 PIL 或 OpenCV 去读图片获取尺寸。转换完之后一定要抽查几个 txt 文件确认坐标都在 0 到 1 之间且类别 ID 没有越界。如果发现坐标大于 1说明归一化时除错了对象检查一下是不是把宽高当成了绝对坐标。3. 环境配置和训练流程从 conda 到跑通第一个 epoch3.1 YOLOV5 环境配置的版本选择和依赖安装YOLOV5 的环境配置有一个玄学不同版本的 PyTorch 和 torchvision 组合会导致完全不同的结果。我一般推荐用 PyTorch 1.8 到 1.12 之间的版本太新的版本有时候会和 YOLOV5 的某些算子不兼容。CUDA 版本根据你的显卡驱动来选30 系显卡用 CUDA 11.x20 系用 CUDA 10.2 或 11.x 都可以。用 conda 创建环境的命令# 创建conda环境指定python版本 conda create -n yolov5_mask python3.8 -y conda activate yolov5_mask # 安装PyTorch以CUDA 11.3为例 pip install torch1.12.1cu113 torchvision0.13.1cu113 --extra-index-url https://download.pytorch.org/whl/cu113 # 克隆YOLOV5源码如果你拿到的是代码包这步跳过 git clone https://github.com/ultralytics/yolov5 cd yolov5 # 安装依赖 pip install -r requirements.txt这里有一个低显存运行的技巧如果你的显卡只有 4GB 或 6GB 显存把requirements.txt里的torch和torchvision换成 CPU 版本先跑通流程或者用--batch-size 4这种小批量训练。YOLOV5 支持自动混合精度训练加--amp参数可以省显存但有时候会导致 loss 变成 NaN这个后面避坑章节会讲。3.2 用 YOLOV5 训练口罩检测模型的完整命令环境配好之后把前面准备好的mask_data.yaml放到yolov5/data/目录下然后运行训练命令python train.py \ --data data/mask_data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch-size 16 \ --epochs 100 \ --device 0 \ --workers 4 \ --project runs/train \ --name mask_exp1逐参数说明--data指定数据集配置文件路径--weights指定预训练权重yolov5s.pt是最小的模型适合快速验证如果追求精度可以换yolov5m.pt或yolov5l.pt--img 640是输入图片尺寸口罩检测这个尺寸够用--batch-size 16根据显存调整8GB 显存可以跑 164GB 跑 8 或 4--epochs 100是训练轮数一般 100 到 300 轮看 loss 收敛情况--device 0指定第一块 GPU没有 GPU 就写cpu--workers 4是数据加载线程数Windows 下建议设为 0 或 2否则容易报错。训练过程中终端会输出每个 epoch 的 loss、precision、recall、mAP0.5 等指标。重点关注mAP0.5如果 50 轮之后还在 0.5 以下大概率是数据有问题不是模型的问题。训练完成后权重文件会保存在runs/train/mask_exp1/weights/best.pt。3.3 推理验证和模型导出训练完之后用detect.py做推理验证python detect.py \ --weights runs/train/mask_exp1/weights/best.pt \ --source ./test_images \ --img 640 \ --conf-thres 0.4 \ --iou-thres 0.5 \ --save-txt \ --project runs/detect \ --name mask_test--source可以是单张图片、图片目录、视频文件或者0表示调用摄像头。--conf-thres 0.4是置信度阈值低于这个值的框会被过滤掉口罩检测场景建议设在 0.35 到 0.5 之间太低会误检太高会漏检。--save-txt会把检测结果保存成 txt 文件方便后续做统计分析。如果需要部署到树莓派或者边缘设备可以用export.py导出 ONNX 或 TensorRT 格式python export.py \ --weights runs/train/mask_exp1/weights/best.pt \ --include onnx \ --img 640 \ --batch-size 1导出的 ONNX 模型可以用 ONNX Runtime 在 CPU 上推理速度比 PyTorch 原生推理快 2 到 3 倍。如果树莓派 5 上部署建议导出成 NCNN 格式--include ncnn然后配合 NCNN 的推理框架使用。4. 避坑与排查那些让我熬夜的翻车现场4.1 训练 loss 不下降mAP 卡在 0.3 上不去现象训练跑了 50 个 epochbox_loss 和 obj_loss 几乎没变化mAP0.5 一直在 0.3 左右徘徊。原因最常见的原因是标注文件和图片没有对齐。比如图片是001.jpg标注文件写成了001.txt但内容对应的是另一张图或者标注文件里的类别 ID 超出了nc的范围。另一个原因是数据集中负样本没有口罩的图太多导致模型学不到有效特征。解决先检查labels/train/下的 txt 文件数量是否和images/train/下的图片数量一致。然后用下面这段代码抽查标注内容import os from pathlib import Path label_dir ./mask_dataset/labels/train img_dir ./mask_dataset/images/train # 检查文件数量 img_files set(p.stem for p in Path(img_dir).glob(*.jpg)) label_files set(p.stem for p in Path(label_dir).glob(*.txt)) print(f图片数量: {len(img_files)}, 标注数量: {len(label_files)}) print(f缺失标注的图片: {img_files - label_files}) print(f多余标注: {label_files - img_files}) # 检查类别ID是否越界 for txt_file in Path(label_dir).glob(*.txt): with open(txt_file) as f: for line in f: parts line.strip().split() if parts: cls_id int(parts[0]) if cls_id 2: # 假设nc3 print(f越界类别ID: {txt_file}, cls_id{cls_id})如果文件数量对不上手动补齐或删除多余文件。如果类别 ID 越界用脚本批量修正。4.2 训练过程中 loss 变成 NaN现象前几个 epoch 正常突然 loss 变成 NaN训练中断。原因学习率太大或者用了--amp混合精度训练但显卡不支持。另外如果数据集中有损坏的图片比如文件大小为 0也会导致 loss 异常。解决先把--amp去掉用默认的 FP32 训练。然后把学习率调小YOLOV5 默认学习率是 0.01改成 0.001 试试。如果还不行检查数据集里有没有损坏图片from PIL import Image from pathlib import Path for img_path in Path(./mask_dataset/images/train).glob(*.jpg): try: img Image.open(img_path) img.verify() except Exception as e: print(f损坏图片: {img_path}, 错误: {e})把损坏的图片删掉或者重新下载。4.3 推理时检测框重叠严重同一个口罩出现多个框现象推理结果里同一个口罩被检测出多个重叠的框NMS 没有正确抑制。原因--iou-thres设得太高导致 NMS 过滤不彻底。默认是 0.45如果设成 0.7 以上重叠框就会保留很多。解决把--iou-thres降到 0.4 到 0.5 之间。如果还是重叠说明模型对同一个目标产生了多个高置信度预测这时候需要检查训练数据里是不是有重复标注——同一张图里同一个口罩被标了两次。4.4 Windows 下训练报错 “DataLoader worker exited unexpectedly”现象在 Windows 上运行train.py报错说 DataLoader 的 worker 进程异常退出。原因Windows 下 PyTorch 的 DataLoader 多线程支持和 Linux 不一样--workers设成大于 0 的值就容易出这个问题。解决把--workers设为 0用主进程加载数据。训练速度会慢一点但能跑通。或者把--workers设为 2有时候也能正常工作但不稳定。4.5 模型在验证集上表现好但实际场景误检率高现象验证集 mAP 有 0.85但拿真实场景的图片测试误检率很高经常把白色墙壁或者浅色衣服识别成口罩。原因训练数据的场景太单一比如全是室内正面人脸模型没有见过复杂背景。另外如果数据集中有大量重复或相似的图片模型会过拟合到这些特定场景。解决在训练数据里加入负样本也就是没有口罩的复杂场景图片标注为空 txt 文件。负样本比例控制在 10% 到 20% 之间。另外用数据增强YOLOV5 默认开启了 mosaic、HSV 增强等可以在--hyp参数里调整增强强度。5. 进阶技巧怎么让这套方案真正能打5.1 用超参数进化找一组更适合口罩检测的参数YOLOV5 自带超参数进化功能可以自动搜索一组更适合你数据集的超参数。命令如下python train.py \ --data data/mask_data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch-size 16 \ --epochs 50 \ --device 0 \ --evolve 100--evolve 100表示进化 100 代每代会用不同的超参数组合训练几个 epoch然后根据 mAP 选择最优组合。这个过程比较耗时但如果你追求极致精度值得跑一次。进化结束后终端会输出一组推荐参数你可以把它们写进--hyp指定的 yaml 文件里再跑一次完整训练。5.2 用 TensorBoard 看训练过程定位问题YOLOV5 默认会把训练日志写到runs/train/mask_exp1/下用 TensorBoard 可以可视化tensorboard --logdir runs/train然后在浏览器打开http://localhost:6006。重点看三张图train/box_loss、train/obj_loss、metrics/mAP_0.5。如果 box_loss 下降但 obj_loss 不降说明模型学到了框的位置但没学到目标的存在性可能是正负样本不平衡。如果 mAP 曲线震荡严重说明学习率太大或者 batch size 太小。5.3 模型剪枝和量化让推理速度翻倍如果你需要把模型部署到边缘设备剪枝和量化是两个最直接的手段。YOLOV5 支持用torch.quantization做动态量化import torch from models.experimental import attempt_load # 加载训练好的模型 model attempt_load(runs/train/mask_exp1/weights/best.pt, map_locationcpu) model.eval() # 动态量化 quantized_model torch.quantization.quantize_dynamic( model, {torch.nn.Linear, torch.nn.Conv2d}, dtypetorch.qint8 ) # 保存量化后的模型 torch.save(quantized_model.state_dict(), mask_quantized.pt)量化后的模型体积会缩小到原来的 1/4 左右CPU 推理速度提升 2 到 3 倍但精度会掉 1 到 3 个百分点。如果精度掉得太多可以只对部分层做量化或者用量化感知训练QAT来恢复精度。5.4 一个我常用的验证习惯每次训练完一个模型我不会只看 mAP 数字而是会做一件事从验证集里随机抽 50 张图用模型跑一遍然后把检测结果和真实标注画在一起肉眼过一遍。这个习惯帮我发现过很多问题——比如模型把「口罩戴在下巴上」识别成了「戴口罩」因为训练数据里这类样本太少又比如模型对侧脸口罩的检测框明显偏小因为标注时侧脸的框就画小了。这个步骤花不了多少时间但能让你对模型的真实能力有一个直观的判断而不是被一个 0.87 的 mAP 数字蒙蔽。希望帮到你。本文还有配套的精品资源点击获取