news 2026/10/18 7:55:42

基于深度学习的目标检测口罩识别系统:从数据到边缘部署实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于深度学习的目标检测口罩识别系统:从数据到边缘部署实战

口罩识别这两年在各种出入口场景里几乎是标配需求。无论是园区闸机、学校门口,还是公共场馆,都会碰到同一个问题:能不能用摄像头自动判断谁没戴口罩,并且实时提醒?这类系统背后的核心,就是用深度学习做目标检测,先定位人脸,再判断人脸区域有没有口罩、口罩佩戴得规不规范。这篇文章记录了我基于深度学习的口罩识别系统从零到一的全过程:数据准备、模型训练、优化压缩、边缘部署,以及现场部署时踩过的坑。内容偏工程落地,很适合正在做计算机视觉实战项目或者毕业设计的同学参考。

很多人以为口罩识别就是图片二分类:输入一张图,输出“戴了/没戴”。但真正在现实场景里跑过就知道,摄像头拍到的画面往往是一堆人、侧脸、低头、逆光,目标有大有小,还有人用手捂嘴、口罩挂在下巴上。所以完整的方案必须是“目标检测 + 状态判断”的结合。我最终选用的技术路线是 YOLOv5s 做人脸定位,再结合类别输出和业务后处理判断口罩状态,在边缘设备上做到实时告警。这篇文章会把每一步的关键细节、参数设置和为什么这么选讲清楚,尽量减少你自己摸索的时间。

1. 项目整体设计与方案选型

1.1 需求拆解:先想清楚“检测什么、在哪跑、怎么联动”

动手写代码之前,最该做的事情是拆需求。对于一个出入口场景,算法要在视频流里实时检测所有人的人脸,并且判断口罩状态。状态绝对不是只有“有”和“没有”两种,还必须覆盖“口罩挂在下巴上”“露出鼻子聊天”这类不规范佩戴,否则提醒形同虚设。我把类别定义为三类:mask(规范佩戴)、no_mask(未佩戴)、bad_mask(佩戴不规范)。不要小看这个定义,它直接决定了后面的数据标注、训练和后处理逻辑。

接下来要明确运行环境。如果模型跑在服务器上,随便上一个大的检测网络都行;如果是嵌入式盒子,算力有限,就必须做取舍。我这次的目标设备是一块常见的边缘计算板卡,算力大概在几TOPS级别,要求视频流处理速度不低于10 FPS,最好能到25 FPS,异常情况下还要联动现场语音或者闸机。因为算力受限,一开始就排除了特别重的模型,把方案锁定在轻量级目标检测模型上。

最后是业务联动需求:检测到未佩戴时要告警,检测到佩戴不规范时也要告警,规范佩戴不响应。告警不能只看单帧,需要连续几帧都异常才触发,否则人员快速经过会导致误报风暴。这些需求都定了,再去选模型,才不会走弯路。

1.2 技术选型:为什么最终选了YOLOv5s

目前做口罩检测可以走的路不少,我简单梳理一下:

方案优点缺点
Haar/OpenCV人脸检测+图像分类实现简单,适合跑通Demo复杂场景鲁棒性差,分类不准
MediaPipe人脸检测速度快,能出人脸框和关键点口罩状态判断要额外接模型,流程复杂
YOLOv5/YOLOv8检测分类一步到位,部署工具链成熟需要一定数据量和训练经验
PP-YOLO等其它检测框架精度上限可能更高部署链路不一定通用,社区资料相对少

我的选型逻辑很直白:口罩区域在画面里通常是中小目标,模型需要足够强的特征提取能力;同时模型要能导出ONNX,再转换到TensorRT或者OpenVINO,方便在不同硬件上运行。YOLOv5s的模型体积小、平均精度够用、网上资料多,改起来方便,所以优先选了它。YOLOv8检测精度确实高一点,但我在折腾TensorRT部署时遇到更多算子和版本兼容问题,需要解决的问题更多。如果你的算力比我这还紧张,可以考虑YOLOv5n;如果精度优先,YOLOv8s也没问题,整体思路是一样的。

选定YOLOv5s之后,我设置输出三个类别:mask、no_mask、bad_mask。实际场景里有一种特殊情况很烦人:人手捂住嘴。模型在no_mask和bad_mask之间来回跳,单靠网络很难完美处理。这个我在方案选型时就做好了心理准备,留给业务后处理用视频时序和连续帧规则去兜底。

1.3 系统整体框架与模块划分

系统不是一个孤立的检测脚本,而是一套流水线。我把它拆成了六个模块:视频接入、目标检测、状态判断、事件聚合、告警联动、可视化。视频接入负责RTSP或者本地视频解码;目标检测模块负责输出人脸框和类别;状态判断模块根据置信度和业务规则输出最终状态;事件聚合模块负责多帧稳定判断;告警联动模块在发现异常时发送HTTP请求或者触发现场语音;可视化模块负责把检测框叠到画面里。

这样拆的好处是,训练阶段只需要关注模型文件,部署阶段可以独立调试每个模块。所有阈值参数,比如置信度、类别映射、感兴趣区域,我都放到同一个配置文件里。现场客户反馈“误报多”或者“漏检多”时,我直接改配置文件让现场远程验证,不用重新编译程序。这个习惯在后来的联调阶段省了很多时间。

2. 数据准备与标注细节

2.1 数据集怎么来:公开数据打底,自采数据补场景

开始训练前,我找了一些公开的口罩检测数据集作为基础。这类数据通常包含不同光照条件下的人脸和口罩标注,有蓝色口罩、布口罩、N95,也有不少未佩戴口罩的人。但直接拿来用有个问题:数据类别定义不完全统一,有的只有“戴口罩”和“不戴口罩”两类;很多图片是自拍或者社交媒体照片,摄像头视角和出入口实际画面差别很大。如果只用公开数据训练,部署到闸机场景时表现往往很差。

所以我额外补了大约2000张现场视角数据。把摄像头架在门口一侧,模拟白天、逆光、夜晚红外补光、阴天以及人员密集等情况。采集这件事别想着一口气做完,最好分几天采集,不同时间的光照差异会让模型学到更稳定的特征。采集时还要注意脱敏,我处理后的图只保留人脸区域,不在公网上存原图。

数据清洗也花了些功夫。对于人眼都看不清的模糊图、人脸占比过小的图、严重遮挡的图,我直接删掉。公开数据集也做了统一过滤,把类别映射成我需要的三类。这里有个要注意的:有些公开数据集会把“口罩挂在下巴上”标成“戴口罩”,这在业务里绝对不行,必须人工跑一遍筛出来改标签。

2.2 标注策略:三类目标怎么标,才有稳定的模型

我用的标注工具是labelImg,先标成Pascal VOC格式,再统一转换成YOLO需要的txt格式。标注规则很关键,我给自己定了几个硬性要求:

  • 标注框必须紧贴人脸外轮廓,不要把额头或者头发包太多进去。
  • 如果一个人出现在多张图里,模糊程度不同的样本都要保留,不能只留清晰的那张。
  • 人脸被遮挡面积超过50%不标,标了只会给模型增加噪声;但如果遮挡部分是口罩,仍然按口罩标注。
  • 遇到透明面罩、挡风面罩这类特殊情况,我会根据业务规则统一归为bad_mask,因为普通摄像头很难判断透明面罩下面到底有没有口罩。

类别不均衡在自采数据里非常明显:大部分人规范佩戴口罩,没戴和不规范样本很少。我没有硬调损失函数,而是通过复制少数类样本并配合随机增强,把三类比例控制在大概5:3:2。实测证明,比强改类别权重简单有效得多。难例图片,比如手捂嘴、低头只看到额头,我单独放在一个文件夹,后续做增量训练的时候再用。

2.3 数据增强和标签抖动

训练时我用了YOLOv5自带的数据增强策略,包括mosaic、mixup、HSV扰动、随机旋转、平移和缩放。mosaic增强对提升小目标检测能力很有用,口罩人脸在闸机视角下经常很小,这个增强基本是必开项。

但增强不是越多越好。我在实验里发现,旋转角度超过10度时,模型会把原本正常的侧脸旋成奇怪的角度,反而导致不稳定。最终我把角度限制在±5度。HSV饱和度扰动也不能调太大,否则会把口罩的蓝色、白色调偏,分类错误率上升。这种细节很多教程不会提,但实际调参时非常关键。

我通常分两版对比:开mosaic和关mosaic各跑一轮。开mosaic的mAP@0.5一般要高2-3个百分点,但在小目标多的场景训练时间更长。最后几十个epoch我会把mosaic关掉,用正常增强微调一下,精度还能回一点,模型也更稳。

3. YOLOv5模型训练与优化

3.1 训练环境与参数选择

我的实验环境是Python 3.8、PyTorch 1.12.1、CUDA 11.3,显卡显存12G。训练代码直接用的是YOLOv5 6.0版本,下载COCO预训练权重作为backbone初始化。之所以坚持用预训练权重,是因为口罩检测的人脸特征和COCO里的人物类别多多少少有点关系,迁移学习可以让模型收敛更快,尤其在我这种自采数据量只有2000张的情况下。

训练命令大致长这样:

python train.py --data mask.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 120 --device 0

参数怎么定要解释一下:

  • --img 640:输入分辨率640x640。口罩人脸在画面里尺寸小,用416容易漏检,用640综合效果最好。硬件更弱就用480。
  • --batch 16:12G显存下已经非常接近上限,再大就OOM。想跑更大batch,可以开梯度累积,效果类似。
  • --epochs 120:配合早停机制,验证集mAP长时间不涨会自动停。
  • 超参数文件用了微调配置,只调了初始学习率和权重衰减,其余保持默认。

训练时我重点看mAP@0.5和各类别AP。实际跑到大概60个epoch,mAP@0.5就到了0.93;120个epoch停下来是0.95左右。bad_mask类别的AP最低,大概0.87。原因也清楚,“露出鼻子”和“规范佩戴”在视觉上差异实在太小,模型只能靠口罩边缘位置推断,难度确实大。

3.2 过拟合和类别不平衡处理

自采数据只有2000张,很容易过拟合。我的对策除了迁移学习和数据增强,还有就是把公开数据里光照差异大的样本混进来,验证集也特意放了现场不同时间段拍的图,避免模型只学到某种光照的“捷径”。训练时我会同时看训练损失和验证损失:如果训练损失持续下降而验证损失开始反弹,就是过拟合,要调整增强力度、减少epoch或者加些dropout。

类别不平衡导致的误判,靠推理时调阈值效果有限,问题根源还是在数据分布上。我的做法是通过数据层面的过采样和增强均衡样本比例。如果你不想动数据,也可以在YOLOv5的自定义数据集配置里增加no_mask类别的损失权重,但要改训练代码,调起来不如数据直接。

3.3 模型压缩与导出:ONNX到TensorRT

训练完的pt权重不能直接用于边缘部署,我先把它导出成ONNX格式:

python export.py --weights best.pt --img 640 --batch 1 --include onnx

拿到ONNX之后,再转成TensorRT引擎。我用了fp16精度来跑GPU推理,速度和fp32相比几乎提升了一倍,精度损失在可接受范围内。转换时注意固定输入尺寸,尽量别用动态输入,动态尺寸会带来额外开销。如果是CPU设备,我会优先考虑OpenVINO,同样能导出一个IR模型。

我没有做严格的模型剪枝,因为YOLOv5s本身参数不多,只有大概7M,对这块边缘板卡已经比较友好。如果要求同时跑更多路视频,可以考虑结构化剪枝,把C3模块的通道数砍掉30%,精度损失通常在1-2个点以内,但需要重新微调。这个测试我做过,最终没有上线剪枝模型,原因是流水线的CPU抢占问题比模型大小影响更大。

4. 系统部署与工程集成

4.1 从视频流到推理结果的完整流程

部署阶段最容易被低估的是视频解码。一开始我用OpenCV的VideoCapture拉RTSP流,CPU占用高,网络一抖画面就卡,整个检测链路都被拖慢。后来换成GStreamer取流,并把视频帧直接转成推理需要的张量格式,情况好了很多。如果你的设备CPU吃紧,用FFmpeg加多线程取流也是不错的选择。

主流程是:取流线程不断拉帧,放进环形缓冲;推理线程取帧做letterbox缩放和归一化,送入TensorRT引擎得到检测结果;后处理线程解析输出,做NMS和类别过滤,再把结果交给事件模块。这种流水线设计比单线程循环有本质提升,推理速度从不到10 FPS提升到25 FPS以上。当然,要控制队列长度,处理不过来时宁可丢帧也不要追帧,否则延迟越来越大。

推理部分我一开始用Python写作。后来发现GIL对多线程性能有影响,就把预处理里的resize和归一化、后处理里的NMS用Cython/C++重写了接口,整个链路的CPU占用下降了一截。如果你不想碰C++,可以只用PyTorch的TensorRT接口,也能把大部分计算放到GPU上,效果尚可。

4.2 业务规则:置信度、NMS和事件联动

模型输出三个类别,我根据置信度取最高那个,但阈值设定很有讲究。最终我把conf_thres设为0.45,NMS IoU设为0.5。这个值不是随便定的。conf太低,闸机边框、宣传海报上的人脸都会被当成真人;conf太高,戴深色口罩或者人脸比较小的时候漏检率上升。我做过一次阈值扫描,发现0.45到0.5之间是当前场景的均衡点。

事件联动部分要特别注意“稳定判定”。单帧检测到未佩戴口罩时先不告警,而是等连续3帧都检测到no_mask或者bad_mask,才触发一次告警。这相当于一个时间滤波,把短时的误检和瞬时遮挡过滤掉。告警内容会附带截图和时间戳,通过群机器人Webhook推送给值班人员。如果要联动闸机,还要等目标框越过一条“警戒线”后再做判断,避免远处的人还没走到闸机就被误拦。

4.3 性能数据的评估与调优

部署完成后,我记录了几组典型数据:边缘GPU上fp16推理一帧约30ms,CPU上OpenVINO大概50-70ms一帧。按这个数据,单路视频流畅跑没问题,但多路视频就要小心。逆光时漏报率最高,我加了一个“亮度自适应”预处理:整帧平均亮度低于阈值时,先做自适应直方图均衡化再送模型。虽然多花几毫秒,但漏报率下降明显。

多摄像头共用一台机器时,我建议用抽帧检测加并发控制。比如5路视频每1帧检测1次,或者4路视频每2帧检测1次。我在项目里做了摄像头优先级调度,重要卡口检测频率更高,普通走廊降低频率,整体吞吐稳定了很多。

5. 实战中踩过的坑与排查技巧

5.1 误检集中在哪几种情况

我把现场跑出来的误检整理成三类。

第一类是人手捂住嘴。模型在no_mask和bad_mask之间反复横跳,因为人脸框里没有口罩纹理,而嘴部区域又被手遮住。想彻底解决很难,最有效的办法是采集大量手捂嘴的样本做难例挖掘。另外还可以依靠视频时序,手不可能一直捂嘴,连续几帧判断能缓解不少。

第二类是后脑勺或者背影被检测成人脸。训练数据里侧脸和背影混在一起时容易这样。想做得稳,可以加一个人脸关键点模型校验五个关键点;不想增加模块,也可以用检测框宽高比和位置关系做简单过滤,虽然不完美,但能过滤一部分。

第三类是反光玻璃、广告牌上的人像被识别成真人。这种静态误检设置ROI就能解决,让模型只关注门口实际通行区域,同时结合背景建模或者运动检测,只有运动区域里的检测结果才有效。实测误报率下降了一半以上。

5.2 漏检与分类错误排查思路

漏检大多数是小目标问题。我排查时先看原图分辨率,再看letterbox之后检测框面积。如果检测框面积小于1600像素,基本不可靠。针对这种情况,要么把输入尺寸提高到768,要么把ROI区域裁剪出来单独放大检测。闸机近距场景我直接只检测门口ROI区域,相当于在输入端变相放大目标,效果立竿见影。

分类错误最典型的是bad_mask。比如口罩挂在下巴上,检测框包含了下巴和嘴部,类别容易偏向no_mask。我后来重新调整标注策略:把下巴区域尽量框完整,增加口罩下移的样本,再补充一些“露出鼻子”的近景图,AP提升非常明显。如果bad_mask的AP偏低,先怀疑标注一致性,而不是急着换模型结构。

5.3 实战中最好用的三个调试技巧

第一,把模型输出的类别框和原图叠加保存。出现误报时,让现场人员直接把截图发回来,不用远程看视频,沟通效率高很多。

第二,做一个阈值扫描脚本。把每天的测试视频反复跑一遍,从0.2到0.7循环测试置信度阈值,统计误报和漏报曲线,选曲线最低点作为最终阈值。不要凭感觉改参数。

第三,先用小输入尺寸部署跑通全链路,再逐步提高分辨率。很多人一开始就在640分辨率下调来调去,最后发现速度不达标,又得回到416重来。先保证代码链路正确,再追求精度,是最省时间的做法。

我自己的体会是,基于深度学习的口罩识别系统,技术难点往往不在“深度学习”本身,而在数据采集、标注一致性和工程流水线。把这三个方面做扎实,模型精度自然就稳了,后面再谈性能优化和业务联动也才有基础。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/18 7:53:29

diagram-design:从草图到系统的图表设计方法论

1. 从一张草图到一套系统:diagram-design 到底在解决什么问题第一次看到“diagram-design”这个标题,我脑子里蹦出来的不是某个具体工具,而是一类非常典型的困境:手里有一堆零散的信息——业务流程、系统架构、数据流向、组织关系…

作者头像 李华
网站建设 2026/10/18 7:49:26

如何构建Agent 评测体系?

Agent 评测体系一、体系架构 Agent 评测 三层分类(评什么) 一条流程(怎么评)三层分类:① 端到端 → ② 轨迹 → ③ 表现 一条流程:① 定数据集 → ② 定标准 → ③ 跑测试 → ④ 看指标归因 → ⑤ 持续迭…

作者头像 李华
网站建设 2026/10/18 7:49:21

Sublime Text 3 插件与配置实战:打造高效代码编辑环境

简介:Sublime Text 3 插件完美配置版,专为 Web 前端与全栈开发者打造,解决原生编辑器功能单一、插件配置繁琐的问题。压缩包共 2000 个文件,大小约 113.88MB,以 js、sublime-snippet、py、md 等类型为主,涵…

作者头像 李华
网站建设 2026/10/18 7:46:04

Abaqus复合材料RVE周期性网格划分与弹性常数计算全攻略

做复合材料的多尺度分析,不少同行第一次碰钉子都是在RVE周期性网格这一步。模型看着简单,一个纤维包在基体里面,但真到划分网格、施加周期边界条件、提取E11、E22、E33、G12、G13这些工程常数的时候,才发现处处是坑。这篇我把自己…

作者头像 李华
网站建设 2026/10/18 7:46:02

前端教学4-Flex 布局详解与常用方法

Flex 布局详解与常用方法 一、Flex 是什么 Flex(Flexible Box,弹性盒子)是 CSS3 提供的一种一维布局模型,专门用于在容器中对项目进行排列、对齐和分配空间。 一句话概括:给父容器加上 display: flex,子元…

作者头像 李华
网站建设 2026/10/18 7:45:52

图神经网络助力工业设备关联建模与故障传播分析实战

做工业智能运维这些年,我越来越觉得,单点设备的故障预测虽然重要,但真正的复杂度都藏在设备与设备之间的关联关系里。图神经网络在工业设备关联建模与故障传播分析这个方向上,这几年沉淀了不少可靠玩法:把产线的物理连…

作者头像 李华