ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLOv7口罩检测实战:从训练到端侧部署的完整路径

YOLOv7口罩检测实战:从训练到端侧部署的完整路径 简介本资源为基于Yolov7的口罩检测模型完整项目包面向计算机视觉学习者、目标检测开发者及公共场所防疫监控方案设计人员。模型可识别戴口罩、未戴口罩和未戴好口罩三类情况精度约93%支持实时检测适用于机场、车站、商场等人员密集场景的防疫监测也可嵌入无人机、机器人等智能硬件。压缩包共150个文件约669.41MB包含24个py脚本、26个yaml配置、4个pt权重文件、46张jpg示例图及17张png结果图另有xml标注、sh运行脚本、Dockerfile与说明文档覆盖数据准备、训练、推理与部署全流程。项目提供多个训练好的模型供不同场景选择并附详细使用教程与代码示例便于快速加载推理。目前已有3045人学习下载适合希望掌握Yolov7实战应用、快速搭建口罩检测系统的读者参考。1. 基于 YOLOv7 的口罩检测模型从零训练到部署一条能跑通的路公共场所的口罩佩戴检测是视觉落地里少有的「需求明确、数据好搞、算力要求不高」的题目。但真动手你会发现网上能搜到的多是「跑通 demo」级别的代码一旦换成自己的监控画面漏检、误检、模型加载慢全冒出来。YOLOv7 在精度和速度上的平衡让它成了这类边缘部署场景的常见选择——单卡 1080Ti 能训Jetson 上能跑ONNX 导出后推理延迟可控。这篇笔记不讲论文只讲一条从数据准备、训练调参、模型导出到端侧部署的完整路径顺带把几个我踩过的坑标出来。适合手里有几百张标注图、想在一周内做出可用原型的工程师也适合已经在跑 YOLOv5 想迁移到 v7 的人。2. 数据准备与 YOLOv7 环境搭建别急着改模型先把地基打牢2.1 口罩检测数据集怎么选、怎么标口罩检测的数据集来源无非三类公开数据集、自己爬取标注、监控截图人工标。公开数据集里RMFRD 和 SMFD 是常被引用的但类别定义和你的业务未必对齐——有的只分「戴口罩/未戴口罩」有的把「未正确佩戴」单独列一类。我一般会先明确业务需要几类再决定用哪个数据集打底。常见做法是三类mask规范佩戴、no_mask未佩戴、mask_incorrect口鼻露出。如果业务只关心「戴没戴」两类就够类别越少训练越稳。标注工具用 LabelImg 或 CVAT 都行导出 YOLO 格式的 txt。这里有个容易翻车的点标注框不要贴着脸部轮廓画要框住整个面部区域包括下巴和额头边缘否则模型学到的特征会偏向口罩本身而不是「佩戴状态」。数据量方面每类至少 800 张三类合计 2500 张起步。如果某一类样本太少先做离线增强补到均衡别指望模型自己学会。增强策略用 Mosaic、随机缩放、HSV 抖动就够翻转要慎用——水平翻转会让「左耳挂绳」变成「右耳挂绳」对判断佩戴规范性有干扰。2.2 用 conda 搭一套不打架的 YOLOv7 环境YOLOv7 官方仓库对 PyTorch 版本有要求装错了就是各种CUDA error或者torchvision不兼容。我习惯用 conda 隔离环境步骤如下conda create -n yolov7_mask python3.8 -y conda activate yolov7_mask # 安装 PyTorch注意 CUDA 版本要和驱动匹配 pip install torch1.12.1cu113 torchvision0.13.1cu113 \ --extra-index-url https://download.pytorch.org/whl/cu113 # 克隆 YOLOv7 仓库并装依赖 git clone https://github.com/WongKinYiu/yolov7.git cd yolov7 pip install -r requirements.txt逻辑说明Python 3.8 是 YOLOv7 官方测试过的版本3.9 以上有时会在torch.nn的某些算子上报错。PyTorch 1.12.1 配 cu113 是我在 30 系卡上验证最稳的组合40 系卡需要换 cu118 的包。requirements.txt里包含matplotlib、numpy、opencv-python等装完可以用python -c import torch; print(torch.cuda.is_available())验证 GPU 是否可用。参数说明--extra-index-url指定 PyTorch 官方 wheel 源国内网络慢的话可以换清华镜像但要注意镜像的包版本可能滞后。如果显存小于 8GB训练时把--batch-size降到 8 或 4同时开启--accumulate做梯度累积。2.3 数据集目录结构与 YAML 配置YOLOv7 要求的数据结构很固定我一般这样组织mask_dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── mask_data.yamlmask_data.yaml内容train: ./mask_dataset/images/train val: ./mask_dataset/images/val nc: 3 names: [mask, no_mask, mask_incorrect]逻辑说明train和val路径是相对于训练脚本执行目录的建议用绝对路径避免找不到文件。nc是类别数必须和标注文件里的 class id 从 0 开始对应。如果标注时用了 1、2、3 作为类别 id训练会直接报AssertionError。参数说明names的顺序要和标注时的类别顺序一致否则模型学出来的类别会错位。验证集比例建议 10%15%太少无法反映真实泛化能力。3. 训练 YOLOv7 口罩检测模型参数怎么设、曲线怎么看3.1 从预训练权重起步别从零训YOLOv7 官方提供了yolov7.pt、yolov7-tiny.pt等预训练权重。口罩检测属于通用目标检测的迁移任务用 COCO 预训练权重初始化能省掉至少一半训练时间。命令如下python train.py \ --weights yolov7.pt \ --cfg cfg/training/yolov7.yaml \ --data mask_dataset/mask_data.yaml \ --hyp data/hyp.scratch.p5.yaml \ --epochs 150 \ --batch-size 16 \ --img-size 640 640 \ --device 0 \ --workers 8 \ --name mask_yolov7逻辑说明--weights加载预训练权重--cfg指定模型结构--data指向数据集配置。--hyp是超参数文件hyp.scratch.p5.yaml适合从预训练微调如果数据量很大想从头训可以用hyp.scratch.p6.yaml。--name是输出目录名训练日志和权重会存在runs/train/mask_yolov7/下。参数说明--img-size设 640 是精度和速度的平衡点如果部署端算力紧张可以降到 416但小目标口罩的召回会下降。--batch-size在 16GB 显存上可以开到 328GB 显存建议 812。--workers是数据加载线程数设成 CPU 核心数的 70% 左右比较合适。3.2 三个必须盯住的训练参数训练过程中hyp.scratch.p5.yaml里有几个参数直接决定模型能不能收敛参数默认值作用调整建议lr00.01初始学习率微调任务降到 0.0010.005lrf0.1最终学习率系数保持默认太小会欠拟合box0.05框回归损失权重口罩框偏小可提到 0.08cls0.5分类损失权重类别不均衡时提到 0.8mosaic1.0Mosaic 增强概率小数据集保持 1.0大数据集可降到 0.5逻辑说明lr0是最容易翻车的参数。用预训练权重微调时如果还保持 0.01 的初始学习率前几个 epoch 损失会剧烈震荡甚至发散。我一般先设 0.001 跑 10 个 epoch 看曲线如果损失下降平滑再考虑调大。box权重影响定位精度口罩检测里「未正确佩戴」这类样本的框往往偏小适当提高能让模型更关注这些难例。参数说明这些值不是绝对的和数据集规模、标注质量强相关。如果训练 20 个 epoch 后mAP0.5还在 0.3 以下优先检查标注文件有没有类别 id 错位或框坐标越界。3.3 训练曲线怎么读loss 不降和 mAP 不涨是两回事训练日志里重点看三组曲线box_loss、obj_loss、cls_loss以及验证集的mAP0.5和mAP0.5:0.95。box_loss持续下降但mAP不涨通常是过拟合检查验证集和训练集分布是否一致。obj_loss震荡剧烈多半是学习率太大或 batch size 太小。cls_loss降不下去先看类别是否均衡——如果no_mask样本占 80%模型会倾向于全预测这一类此时需要在hyp里调cls权重或做重采样。我一般会在第 50、100、150 epoch 分别跑一次验证用test.py生成混淆矩阵python test.py \ --weights runs/train/mask_yolov7/weights/best.pt \ --data mask_dataset/mask_data.yaml \ --img-size 640 \ --task test \ --name mask_eval逻辑说明--task test会输出每类的 precision、recall、mAP以及混淆矩阵图。混淆矩阵能直接看出「未正确佩戴」被误判成「戴口罩」的比例这个指标比总体 mAP 更有业务参考价值。参数说明--img-size要和训练时一致否则锚框匹配会出问题。如果验证集 mAP 比训练集低超过 15 个百分点基本可以判定过拟合需要加数据或加正则。4. 模型导出与端侧部署ONNX、TensorRT 和踩过的坑4.1 导出 ONNX 并验证推理一致性训练完的.pt权重不能直接上端侧常见做法是导出 ONNX 再用 TensorRT 或 OpenVINO 加速。导出命令python export.py \ --weights runs/train/mask_yolov7/weights/best.pt \ --grid \ --img-size 640 640 \ --batch-size 1 \ --simplify \ --include onnx逻辑说明--grid把检测头里的网格生成逻辑固化到模型里--simplify调用 onnx-simplifier 去掉冗余算子。导出后会生成best.onnx可以用onnxruntime验证输出和 PyTorch 是否一致import onnxruntime as ort import numpy as np sess ort.InferenceSession(best.onnx) input_name sess.get_inputs()[0].name # 构造一个 1x3x640x640 的随机输入 dummy np.random.randn(1, 3, 640, 640).astype(np.float32) outputs sess.run(None, {input_name: dummy}) print(outputs[0].shape) # 应该是 (1, 25200, 35) 左右逻辑说明YOLOv7 的输出维度是(batch, num_anchors, 5 nc)其中 5 是x, y, w, h, obj。如果导出后维度不对检查--grid是否加上以及export.py里的--img-size是否和训练一致。参数说明--batch-size 1适合端侧单帧推理如果服务端要批量处理可以设成 8 或 16但 TensorRT 对动态 batch 的支持需要额外配置。4.2 TensorRT 加速与 FP16 量化在 Jetson 或带 NVIDIA GPU 的服务器上TensorRT 能带来 23 倍加速。转换命令trtexec \ --onnxbest.onnx \ --saveEnginebest_fp16.engine \ --fp16 \ --workspace2048 \ --minShapesinput:1x3x640x640 \ --optShapesinput:1x3x640x640 \ --maxShapesinput:1x3x640x640逻辑说明--fp16开启半精度量化精度损失通常在 1% mAP 以内速度提升明显。--workspace是显存工作空间单位 MB2048 够用。--minShapes、--optShapes、--maxShapes定义输入尺寸范围固定尺寸推理时三者设一样。参数说明如果端侧是 Jetson Nano 这类算力有限的设备建议用yolov7-tiny训练导出时--img-size降到 416FP16 后单帧能跑到 20 FPS 以上。INT8 量化需要校准集精度掉点风险更大新手先别碰。4.3 部署时的预处理和后处理对齐端侧部署最容易翻车的地方是预处理不一致。训练时 YOLOv7 用的是 letterbox 填充推理时如果直接 resize 会改变宽高比导致框偏移。Python 端的 letterbox 实现def letterbox(img, new_shape(640, 640), color(114, 114, 114)): shape img.shape[:2] r min(new_shape[0] / shape[0], new_shape[1] / shape[1]) new_unpad int(round(shape[1] * r)), int(round(shape[0] * r)) dw, dh new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] dw, dh dw // 2, dh // 2 img cv2.resize(img, new_unpad, interpolationcv2.INTER_LINEAR) top, bottom dh, dh left, right dw, dw img cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, valuecolor) return img, r, (dw, dh)逻辑说明letterbox 保持宽高比缩放再用灰色填充到目标尺寸。后处理时要把检测框坐标映射回原图映射公式是x_orig (x - dw) / ry_orig (y - dh) / r。如果忘了这一步框会整体偏移。参数说明color用 114 是 YOLO 系列的惯例和训练时的填充色一致。r是缩放比例dw、dh是填充像素数后处理时必须用同一组值。5. 避坑与排查口罩检测模型最常见的 5 个翻车现场5.1 现象训练 loss 正常下降但验证 mAP 始终为 0原因标注文件的类别 id 从 1 开始而 YAML 里nc: 3期望的是 0、1、2。YOLOv7 在加载标签时不会报错但所有类别都会被当成背景。解决用脚本批量检查labels/下所有 txt 的 class id确保最大值小于nc。命令awk {print $1} labels/train/*.txt | sort -u。5.2 现象推理时框位置整体偏移或者框比实际目标大一圈原因预处理用了直接 resize 而不是 letterbox或者后处理忘了除以缩放比例r。解决统一训练和推理的预处理逻辑把 letterbox 函数封装成公共模块训练和部署都调用同一份代码。后处理时打印几个框的坐标和原图对比确认映射正确。5.3 现象模型在测试集上表现好一到监控画面就大量漏检原因训练数据以正面清晰人脸为主监控画面存在俯视、侧脸、遮挡、低照度等情况域偏移严重。解决从目标场景截取 200300 帧人工标注后加入训练集做微调。如果无法标注至少做一轮无监督的域适应比如用目标场景图片做伪标签。另外检查输入尺寸监控画面里口罩目标可能只有 30×30 像素640 输入下特征太弱可以尝试切图推理或提高输入分辨率。5.4 现象TensorRT 推理结果和 ONNX 不一致框数量对不上原因ONNX 导出时没加--grid或者 TensorRT 转换时输入尺寸和 ONNX 不一致。解决重新导出 ONNX 并确认--grid已加用onnxruntime和 PyTorch 对比同一张图的输出确保误差在 1e-3 以内。TensorRT 转换时的--minShapes、--optShapes、--maxShapes要和 ONNX 的输入维度完全一致。5.5 现象训练到一半显存溢出报CUDA out of memory原因--batch-size太大或者--img-size设成了 1280 但显存不够。解决先降 batch size 到 4 或 8同时开启--accumulate 4做梯度累积等效 batch size 不变。如果还不行把--img-size降到 512 或 416。另外检查--workers是否设得过高数据加载线程也会占用显存。6. 把 mAP 再提 3 个点的几个技巧训练完第一版模型后如果 mAP0.5 卡在 0.85 左右上不去可以试这几个方向。第一个是锚框重聚类YOLOv7 默认锚框是基于 COCO 的口罩目标的宽高比和人脸接近但更扁用 k-means 在自己的数据集上重新聚类把yolov7.yaml里的anchors换掉通常能提 12 个点。第二个是测试时增强TTA推理时对图片做多尺度缩放和翻转把结果做 NMS 融合代价是推理时间翻倍适合服务端场景。# 简单的多尺度 TTA 示例 scales [640, 736, 832] all_boxes [] for s in scales: img_t letterbox(img, (s, s))[0] boxes model_infer(img_t) boxes rescale_boxes(boxes, s, orig_shape) all_boxes.append(boxes) final nms(torch.cat(all_boxes), iou_thres0.6)逻辑说明多尺度推理能覆盖不同大小的口罩目标尤其是远距离小目标。rescale_boxes把每个尺度下的框映射回原图再用 NMS 去重。iou_thres设 0.6 比默认的 0.45 稍高避免把相邻人脸框误删。参数说明尺度数量不是越多越好3 个尺度是精度和耗时的平衡点。如果端侧部署TTA 基本不用考虑延迟扛不住。第三个技巧是难例挖掘。训练完第一版后用test.py在验证集上跑一遍把置信度在 0.30.5 之间的样本挑出来人工复核后重新标注加入训练集做第二轮微调。这个流程我重复过三轮mAP 从 0.84 提到了 0.91代价是多了两天标注时间。值不值得做取决于业务对漏检的容忍度——如果是门禁闸机场景漏检一个未戴口罩的人可能带来实际风险那就值得。最后一个习惯每次训练完把hyp配置、数据集版本、mAP 曲线截图存到一个固定目录命名带上日期。我吃过亏三个月后想复现某个版本发现当时的超参数已经找不到了只能重训。这个习惯不花时间但能省掉很多后悔药。希望帮到你。本文还有配套的精品资源点击获取
返回列表