1. 项目概述
口罩识别系统是当前计算机视觉领域极具实用价值的应用场景。作为一名长期从事目标检测算法开发的工程师,我在过去两年中为多个公共场所部署过类似的检测系统。今天要分享的这套方案,整合了YOLO系列最新三个版本的模型(v5/v8/v10),通过PySide6实现了完整的可视化界面,实测在普通消费级显卡上能达到30FPS以上的实时检测性能。
这个项目的独特之处在于:我们不仅比较了三种YOLO变体的实际表现,更重要的是构建了一套端到端的工业级解决方案。从数据采集标注到模型训练调优,再到最终的可视化部署,每个环节都包含了大量工程实践中积累的经验技巧。比如在数据增强阶段,我们发现适当增加遮挡样本能显著提升模型在真实场景中的鲁棒性;在界面设计中,通过多线程处理避免了视频流的卡顿问题。
2. 核心设计思路
2.1 技术选型考量
为什么选择YOLO系列而不是Faster R-CNN等其他检测框架?主要基于三个现实因素:
-
实时性要求:公共场所的监控系统通常需要处理1080p@25fps的视频流,YOLO的单阶段检测架构在速度上具有先天优势。实测表明,YOLOv10在RTX 3060上处理1080p图像仅需28ms。
-
部署便捷性:Ultralytics维护的YOLOv5/v8代码库提供了完善的导出工具,可轻松转换为ONNX/TensorRT等工业标准格式。相比之下,两阶段检测器的部署复杂度要高得多。
-
精度平衡:现代YOLO版本在COCO等基准测试上的mAP已超过两阶段检测器。对于口罩检测这种相对简单的任务,YOLO系列完全能满足精度需求。
2.2 系统架构设计
整套系统采用经典的三层架构:
code复制数据层(视频流/图像) → 算法层(YOLO模型) → 应用层(PySide6界面)
关键创新点在于:
- 动态模型切换:运行时可以自由选择v5/v8/v10模型
- 结果可视化:实时绘制检测框的同时显示置信度和模型耗时
- 数据记录:自动保存违规检测截图和统计报表
3. 数据集构建与增强
3.1 数据采集方案
优质的数据集是模型效果的基石。我们采用多源采集策略:
- 公开数据集:整合了MAFA、FaceMask等知名口罩数据集
- 网络爬取:使用Bing Image Search API获取多样化场景图片
- 实地拍摄:在商场、地铁站等场景采集2000+真实监控视角图像
最终构建的数据集包含35,728张标注图像,类别分布如下:
| 类别 | 数量 | 占比 |
|---|---|---|
| 正确佩戴口罩 | 18,642 | 52.1% |
| 未佩戴口罩 | 12,305 | 34.4% |
| 错误佩戴 | 4,781 | 13.5% |
3.2 数据标注技巧
使用LabelImg进行标注时,有几个关键注意事项:
- 对于遮挡情况(如被手部遮挡的口罩),应保持标注完整性
- 小目标(远距离人脸)需要适当放大标注框
- 模糊图像也应标注,但需单独标记为"difficult"属性
经验:标注时按住Ctrl键可以微调框体位置,这对精确标注很有帮助
3.3 数据增强策略
通过albumentations库实现了一套针对性增强方案:
python复制transform = A.Compose([
A.HorizontalFlip(p=0.5),
A.RandomBrightnessContrast(p=0.2),
A.RandomFog(p=0.1), # 模拟雾天场景
A.MotionBlur(blur_limit=7, p=0.1), # 运动模糊
A.RandomSunFlare(p=0.05), # 强光干扰
A.CoarseDropout(max_holes=8, max_height=20,
max_width=20, p=0.3) # 模拟遮挡
])
特别增加了口罩局部遮挡的模拟,这对提升模型鲁棒性效果显著。
4. 模型训练与优化
4.1 YOLO模型配置
三个版本的核心配置对比如下:
| 参数 | YOLOv5s | YOLOv8n | YOLOv10n |
|---|---|---|---|
| 骨干网络 | CSPDarknet | CSPDarknet | CSPDarknet |
| 检测头 | Anchor-Based | Anchor-Free | Anchor-Free |
| 输入尺寸 | 640x640 | 640x640 | 640x640 |
| 预训练权重 | coco | coco | coco |
训练命令示例(YOLOv8):
bash复制yolo detect train data=mask.yaml model=yolov8n.pt epochs=100 \
imgsz=640 batch=32 device=0 optimizer=AdamW
4.2 关键训练技巧
- 学习率调整:采用余弦退火策略,初始lr=0.01,最终lr=0.001
- 早停机制:设置patience=15,当验证集mAP连续不提升时终止训练
- 混合精度:使用AMP加速训练,batch_size可提升约30%
- 类别权重:对"错误佩戴"类别设置2.0的权重系数
4.3 性能对比
在测试集上的表现:
| 模型 | mAP@0.5 | 参数量(M) | 推理耗时(ms) |
|---|---|---|---|
| YOLOv5s | 0.892 | 7.2 | 15.2 |
| YOLOv8n | 0.907 | 3.2 | 12.8 |
| YOLOv10n | 0.915 | 3.8 | 11.5 |
YOLOv10在精度和速度上实现了最佳平衡,特别适合实时检测场景。
5. PySide6界面开发
5.1 界面架构设计
采用Model-View-Controller模式:
python复制class MaskDetectionApp(QMainWindow):
def __init__(self):
super().__init__()
self.model = YOLOModel() # 模型加载
self.video_thread = VideoThread() # 视频处理线程
self.init_ui() # 界面初始化
def init_ui(self):
self.setWindowTitle("口罩识别系统")
self.setGeometry(100, 100, 1200, 800)
# 中央部件为视频显示区域
self.video_label = QLabel(self)
# 底部为控制面板
self.control_panel = QWidget()
# 模型选择下拉框
self.model_combo = QComboBox()
self.model_combo.addItems(["YOLOv5", "YOLOv8", "YOLOv10"])
5.2 多线程处理
视频处理单独放在工作线程中,避免界面卡顿:
python复制class VideoThread(QThread):
frame_ready = pyqtSignal(np.ndarray)
def run(self):
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if ret:
# 发送处理后的帧
self.frame_ready.emit(process_frame(frame))
5.3 关键功能实现
- 实时绘制:使用OpenCV的polylines函数绘制口罩区域
- 报警功能:检测到未戴口罩时触发声音提示
- 日志记录:使用SQLite存储检测结果和时间戳
- 截图保存:按S键保存当前帧到./output目录
6. 部署优化技巧
6.1 模型量化
使用TensorRT进行FP16量化可提升约40%的推理速度:
python复制# 转换ONNX
yolo export model=yolov10n.pt format=onnx
# 转换为TensorRT
trtexec --onnx=yolov10n.onnx --saveEngine=yolov10n.trt --fp16
6.2 内存优化
通过以下方法控制内存占用:
- 使用torch.no_grad()禁用梯度计算
- 及时调用torch.cuda.empty_cache()
- 限制视频解码的缓冲区大小
6.3 跨平台适配
针对不同平台的解决方案:
- Windows:打包为exe使用PyInstaller
- Linux:制作deb/rpm包
- 树莓派:使用--device cpu参数运行
7. 常见问题排查
7.1 检测效果不佳
可能原因及解决方案:
- 数据不平衡:增加少数类别的样本数量
- 标注不准确:检查边缘case的标注质量
- 过拟合:添加更多数据增强,减小模型规模
7.2 界面卡顿
优化方向:
- 检查是否启用了GPU加速
- 降低视频显示分辨率(如从1080p降到720p)
- 限制检测帧率(如15FPS)
7.3 模型加载失败
检查清单:
- 模型文件路径是否正确
- 是否安装了正确版本的torch和ultralytics
- GPU驱动是否支持CUDA版本
在实际部署中,我们发现室内光线变化对检测效果影响较大。解决方法是在预处理阶段加入自适应直方图均衡化(CLAHE),这能显著提升暗光环境下的识别率。另一个实用技巧是对连续视频帧做检测结果投票,可以有效减少瞬时误报。