1. 项目概述
去年在开发一个智能门禁系统时,客户突然提出要增加口罩检测功能。当时我第一反应就是使用YOLOv5,这个选择背后有几个实际考量:首先YOLOv5在目标检测领域的平衡性很好,既保证了精度又兼顾了速度;其次PyTorch生态的易用性让模型部署变得简单;最重要的是社区支持完善,遇到问题容易找到解决方案。这个项目从环境搭建到最终部署用了两周时间,期间踩了不少坑,也积累了一些实战经验,今天就把完整实现过程分享给大家。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心组件解析
2.1 YOLOv5架构特点
YOLOv5的代码结构非常清晰,主要包含以下几个关键部分:
- models/yolo.py:定义模型结构
- utils/datasets.py:数据处理工具
- utils/general.py:通用工具函数
- train.py:训练脚本
- detect.py:推理脚本
模型本身采用CSPDarknet作为backbone,PANet做特征融合,这种结构在保持轻量化的同时实现了多尺度特征提取。实测在NVIDIA 1660Ti显卡上,yolov5s模型能达到140FPS的推理速度,非常适合实时检测场景。
2.2 PyTorch环境配置
推荐使用conda创建虚拟环境,避免包冲突:
bash复制conda create -n mask_det python=3.8
conda activate mask_det
安装PyTorch时要特别注意CUDA版本匹配。以CUDA 11.3为例:
bash复制pip install torch==1.10.0+cu113 torchvision==0.11.1+cu113 -f https://download.pytorch.org/whl/torch_stable.html
注意:如果使用30系显卡,需要CUDA 11.x以上版本。安装前建议用nvidia-smi命令查看驱动支持的CUDA版本。
3. 数据集准备与标注
3.1 数据收集要点
优质的数据集应该包含:
- 不同光照条件下的样本(室内/室外/逆光等)
- 多种口罩类型(医用/N95/布质等)
- 各种遮挡情况(眼镜/围巾/手部遮挡等)
- 多角度人脸(正面/侧面/俯仰等)
建议收集至少5000张标注图像,正负样本比例保持在3:1左右。可以使用公开数据集如MAFA、FaceMask作为基础,再补充实际场景数据。
3.2 标注规范
使用LabelImg工具标注时要注意:
- 口罩区域应包含耳挂绳
- 被遮挡超过50%的口罩不做标注
- 每个边界框尽量贴近口罩边缘
- 标注文件保存为YOLO格式(class x_center y_center width_height)
标注完成后目录结构应该是:
code复制dataset/
├── images/
│ ├── train/
│ └── val/
└── labels/
├── train/
└── val/
4. 模型训练技巧
4.1 参数配置
修改data/mask.yaml指定数据集路径:
yaml复制train: ../dataset/images/train
val: ../dataset/images/val
nc: 2 # 类别数(戴口罩/不戴口罩)
names: ['mask', 'no_mask']
关键训练参数(train.py):
bash复制--img 640 # 输入尺寸
--batch 16 # 根据显存调整
--epochs 100
--data mask.yaml
--cfg models/yolov5s.yaml
--weights yolov5s.pt
--device 0 # 指定GPU
4.2 训练监控
使用TensorBoard监控训练过程:
bash复制tensorboard --logdir runs/train
重点关注三个指标:
- mAP@0.5:验证集精度
- box_loss:定位损失
- obj_loss:目标存在置信度
当验证指标连续10个epoch没有提升时,可以考虑提前终止训练。
5. 模型优化策略
5.1 数据增强
在data/hyp.scratch.yaml中调整:
yaml复制hsv_h: 0.015 # 色调增强
hsv_s: 0.7 # 饱和度增强
hsv_v: 0.4 # 明度增强
degrees: 10 # 旋转角度
translate: 0.1 # 平移比例
scale: 0.5 # 缩放比例
5.2 模型剪枝
使用TorchPruner进行通道剪枝:
python复制from torchpruner import SparsePruner
pruner = SparsePruner(model, sparsity=0.3)
pruner.step()
剪枝后需要微调2-3个epoch恢复精度。
6. 部署实践
6.1 ONNX导出
python复制import torch
model = torch.hub.load('ultralytics/yolov5', 'custom', path='best.pt')
model.eval()
dummy_input = torch.randn(1, 3, 640, 640)
torch.onnx.export(model, dummy_input, "mask_det.onnx",
input_names=['images'],
output_names=['output'],
dynamic_axes={'images': {0: 'batch'},
'output': {0: 'batch'}})
6.2 TensorRT加速
使用trtexec工具转换:
bash复制trtexec --onnx=mask_det.onnx \
--saveEngine=mask_det.engine \
--fp16 \
--workspace=2048
在Jetson设备上部署时,建议使用--fp16模式,速度可提升2-3倍。
7. 常见问题排查
7.1 训练不收敛
可能原因:
- 学习率过大:尝试从0.01逐步下调
- 标注错误:检查标注文件是否与图像匹配
- 数据不平衡:增加负样本数量
7.2 推理速度慢
优化方案:
- 使用更小的模型(如yolov5n)
- 降低输入分辨率(--img 320)
- 启用TensorRT加速
7.3 误检率高
解决方法:
- 增加困难负样本
- 调整置信度阈值(--conf 0.5)
- 添加后处理NMS(--iou 0.45)
8. 实际应用扩展
在门禁系统中,我们增加了以下业务逻辑:
- 连续5帧检测到未戴口罩触发语音提醒
- 与红外测温模块联动,体温异常+未戴口罩双重预警
- 使用OpenCV绘制检测框时,添加中文标签显示
对于嵌入式设备部署,建议:
- 使用libtorch C++接口
- 启用多线程流水线处理
- 量化模型到INT8精度
这个项目让我深刻体会到,一个好的AI系统不仅需要算法精度,更需要工程化思维。比如我们发现早上逆光环境下误检率会升高,最后通过增加侧向补光灯解决了问题。在实际部署时,建议先用真实场景视频测试至少24小时,统计不同时段的表现,这对模型迭代很有帮助。
