1. 项目概述:基于MobileNet v2的口罩检测系统
去年在指导本科生毕业设计时,我们团队开发了一套基于MobileNet v2的实时口罩检测系统。这个项目源于疫情期间公共场所的防控需求,通过深度学习技术实现无接触的口罩佩戴检测。系统能够在普通PC和嵌入式设备上实时运行(约25FPS),检测准确率达到94.7%,特别适合部署在学校、商场等公共场所的入口处。
MobileNet v2作为轻量级CNN网络,其深度可分离卷积和倒残差结构在保持精度的同时大幅降低了计算量。我们在PyTorch框架下对模型进行了三方面改进:首先使用数据增强扩充了自建的10,000+张口罩数据集;其次调整了网络颈部结构,增强了小目标检测能力;最后采用TensorRT加速,使推理速度提升3倍。系统还集成了SpringBoot+Vue的全栈管理后台,方便查看检测记录和统计报表。
技术选型思考:为什么选择MobileNet v2而不是YOLO系列?
虽然YOLOv5检测精度更高,但经过实测,在Jetson Nano等边缘设备上,MobileNet v2+SSD的架构能更好地平衡速度和精度。当需要检测的目标(口罩)类别单一时,轻量级网络往往更实用。
2. 核心算法实现细节
2.1 数据准备与增强
我们收集的数据集包含12,485张标注图片,涵盖不同人种、光照条件和口罩类型。为提高模型鲁棒性,采用了以下增强策略:
python复制transform = transforms.Compose([
transforms.RandomHorizontalFlip(p=0.5),
transforms.ColorJitter(brightness=0.3, contrast=0.3),
transforms.RandomAffine(degrees=15, translate=(0.1,0.1)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
关键细节处理:
- 对遮挡情况(如手部遮挡口罩)单独增加了500+样本
- 针对透明口罩等特殊类型,调整了HSV色彩空间的饱和度增强
- 使用Albumentations库实现几何变换,避免torchvision的边界问题
2.2 模型架构调整
原始MobileNet v2的直接迁移效果不佳(准确率仅89%),我们做了三处改进:
- 颈部结构优化:
python复制class CustomNeck(nn.Module):
def __init__(self, in_channels):
super().__init__()
self.conv1 = nn.Conv2d(in_channels, 256, 3, padding=1)
self.conv2 = nn.Conv2d(256, 128, 3, padding=1)
self.conv3 = nn.Conv2d(128, 64, 3, padding=1)
def forward(self, x):
return self.conv3(self.conv2(self.conv1(x)))
-
注意力机制引入:
在最后三个倒残差块后添加SE模块,提升特征选择能力 -
损失函数改进:
采用Focal Loss解决正负样本不平衡问题:
python复制criterion = FocalLoss(alpha=0.75, gamma=2)
实测效果:经过调整后,模型在验证集上的mAP从0.89提升到0.92,特别是对侧脸检测的准确率提升明显。
3. 系统实现与部署
3.1 实时检测流程
mermaid复制graph TD
A[摄像头捕获] --> B(图像预处理)
B --> C{模型推理}
C -->|戴口罩| D[绿色框标注]
C -->|未戴口罩| E[红色框标注+警报]
D --> F[记录存储]
E --> F
实际部署时需要注意:
- 使用OpenCV的DNN模块比直接PyTorch推理快40%
- 对连续5帧未戴口罩才触发警报,避免误报
- 采用多线程处理:1个线程负责图像采集,1个线程处理推理
3.2 性能优化技巧
- TensorRT加速:
bash复制trtexec --onnx=mask_det.onnx --saveEngine=mask_det.engine \
--fp16 --workspace=2048
- 内存池化:
python复制class MemoryPool:
def __init__(self):
self.pool = {}
def get(self, shape):
key = str(shape)
if key not in self.pool:
self.pool[key] = torch.empty(shape, device='cuda')
return self.pool[key]
- 视频流处理优化:
- 使用GStreamer管道替代OpenCV的VideoCapture
- 设置合理的跳帧策略(动态调整)
4. 常见问题与解决方案
4.1 模型部署问题排查
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 推理速度慢 | 未启用TensorRT | 转换模型时添加--fp16参数 |
| 内存泄漏 | Python循环引用 | 使用memory_profiler定位 |
| 检测框抖动 | 未做轨迹平滑 | 添加Kalman滤波 |
4.2 实际场景挑战
- 光照条件差:
- 解决方案:在预处理阶段添加CLAHE直方图均衡化
- 代码实现:
python复制def clahe_process(img):
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
l, a, b = cv2.split(lab)
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
cl = clahe.apply(l)
return cv2.cvtColor(cv2.merge((cl,a,b)), cv2.COLOR_LAB2BGR)
- 多人同框检测:
- 采用YOLOv5的人脸检测先定位,再对每个面部单独判断
- 使用NMS的iou_threshold调整为0.4
5. 项目扩展方向
在实际应用中,我们发现几个有价值的改进点:
- 口罩类型识别:
- 增加分类头区分医用口罩/N95/布口罩
- 需要收集更细分的数据集
- 姿态估计结合:
- 当检测到未戴口罩时,判断人员是否处于交谈状态
- 使用MediaPipe获取面部关键点
- 边缘设备部署:
- 量化训练使模型缩小到3MB以内
- 测试在不同ARM架构芯片上的性能
这个项目从技术选型到最终部署共耗时3个月,最大的收获是认识到:在工业级应用中,模型的推理效率往往比单纯追求准确率更重要。我们最终放弃了一个准确率高2%但速度慢3倍的模型版本,这个权衡在实际场景中被证明是正确的。