做口罩佩戴检测这件事,听起来好像就是“拿个模型跑一下”的事:输入图片,输出“戴了”或“没戴”,完事。但真正把它放进一个需要原地部署、实时推流、还要接受现场光照和人员姿态考验的环境里,你会发现,问题量级完全不一样。我这次的落地项目,最初就是从这样一个需求开始的:给一个园区做通行检测,要识别进出人员是否佩戴口罩。团队里没有专职算法工程师,数据量也不大,最后选择了国内某主流AI开发平台的专业版来完成整套流程。这篇博客就是把整个实现过程、参数取舍和踩坑记录都摊开讲一遍,适合那些准备用平台化方式做视觉识别、但又不确定这条路能不能走通的开发者。
1. 场景定调:从“识别口罩”到“真正可用的口罩检测”
1.1 需求拆解与使用场景
“识别口罩”这句话太模糊了,如果不拆解清楚就开干,后面一定会反复返工。我当时先和需求方聊了整整一下午,把目标拆成了几个具体场景:
- 场景一:园区出入口闸机。人员近景、单人为主,偶尔有两人并行,摄像头角度偏高,需要判断是否佩戴口罩,并作为门禁联动的一个条件。
- 场景二:办公楼大堂走廊。中远距离,人员走动,拍摄画面里人比较小,存在逆光和玻璃反光情况。
- 场景三:室内活动区。多人同框、姿态随意,有人把口罩拉到下巴、有人只遮住嘴没遮住鼻子,需要识别“佩戴不规范”。
这三个场景对模型的要求差别很大。闸机口要求的是高精度、低延迟,走廊和室内则要求对“小目标”和“遮挡”有足够的鲁棒性。如果一上来就只做二分类“戴/没戴”,第三个场景基本没法交付,因为需求方明确说了:“拉了口罩露出鼻子,算不算没戴?我们要能区分。”所以实际的分类体系被定为四个类别:正常佩戴、未佩戴口罩、佩戴口罩不规范、背景。
1.2 先把指标定义清楚
做AI项目最怕的,就是需求方用“效果还行”来验收。我建议在项目开始之前,就把客观指标定下来。我们当时定义的核心指标有三个:检出率、误检率、单帧处理耗时。
- 检出率:对于画面中真实出现且清晰度足够的人脸,模型正确判断的比例有多高。这直接决定门禁场景能不能用。
- 误检率:有物体或人员被误判成“未佩戴口罩”,比如行人手里拿着的口罩、墙上的挂饰、头盔下沿等。误检率高,后台就会被无效告警刷屏。
- 单帧耗时:从图像输入到结果输出需要多少毫秒。放在边缘设备上,单帧耗时直接决定能接几路摄像头。
另外还要提前约定一个容易被忽略的指标:“最小检测像素”。摄像头画面里一个人脸只占20像素宽,和人脸占200像素宽,模型表现完全不是一回事。这个指标建议直接写进验收标准里,避免后面扯皮。
当时我们定的目标是:闸机场景识别准确率不低于98%,走廊场景不低于95%,室内多人场景不低于90%。后来实际训练下来,这个标准定得不算高,但落地过程中确实需要反复打磨才能稳定达到。
2. 平台选型:不做底层模型,不等于不做活
2.1 平台化开发与自建模型的对比
市面上做一个目标检测模型,现在有几条路:自己搭环境、写训练脚本、管理数据标注,这是最重的一条路;用开源模型仓库拿个预训练模型再微调,有代码能力团队可以走这条路;还有一种就是直接用AI开发平台,在界面上完成数据管理和训练发布。
我这次选的是第三条路,原因很现实。团队配置是:两名后端开发,一名前端,一名实施,都是能看懂Python但没系统学过深度学习的类型。如果让我自己从零搭PyTorch训练环境,光是处理数据格式、Loss收敛、环境依赖这几个环节,保守估计要把项目周期拉长一倍以上。而平台化开发的价值正好体现在这里:数据标注、模型训练、资源调度、模型部署被做成了可视化流程,开发者的注意力可以集中在业务场景本身。
但这并不意味着上了平台就能当甩手掌柜。平台解决的是“算力供给”和“训练框架封装”的问题,不解决“数据质量”和“验收标准”的问题。换句话说,平台帮你把“模型训练”这件事情做得足够简单,但“这个模型在你的场景里能不能用”,仍然取决于你有没有把数据准备到位、有没有把指标定义清楚。这条认知如果不建立,很容易出现训练完了、部署上去了、一测发现效果离谱,然后开始怀疑平台能力的情况。
2.2 平台的边界和取舍
平台化开发有很明确的边界。我们这次用的平台专业版,优势集中在这几点:
- 数据标注链路完整,支持多人协作、标签质检,还能用半自动标注提升效率。
- 预置了多个与目标检测相关的预训练模型,不需要自己找权重文件。
- 训练资源按需付费,不用自己维护GPU服务器,训练任务排队和调度也是平台托管。
- 部署方式灵活,支持在线API,也能导出本地部署包,这正好匹配我们的端云协同架构。
短板也显而易见。平台的训练过程有一定黑盒属性,你能调整的超参数范围是有限的,什么Loss曲线细节、anchor参数、数据增强策略明细,很多都看不到。如果你是一个喜欢把每个参数都手动拧一遍的算法工程师,会觉得有点憋屈。另外,导出到本地部署之后,能否在特定硬件上跑起来,取决于平台适配方案,本地二次开发的空间比较受限。
所以我的建议是:如果你的团队有算法背景,或者项目对模型结构有非常定制化的要求,那自建方案更合适;如果你和我一样,目标是把业务跑通,用工程手段解决场景问题,平台是完全够用的。要精力花在数据、评测、部署这些真正决定“能不能用”的事情上。
3. 数据准备与标注:决定模型天花板的环节
3.1 数据采集与清洗
进入数据环节后,我的第一个体会是:模型效果的天花板,基本由训练数据决定。平台再强,也没办法在你完全没有见过的数据形态上做出正确的判断。
我们最终整理出的数据集大概有一万一千多张图片。来源有三个:一是客户现场监控的脱敏截图,贡献了约七成;二是购买的一部分公开图片数据集,用于补充角度和光照多样性;三是团队自己找人在不同光线和背景下拍摄的模拟场景图。数据来源混杂,第一步做的是清洗工作,我按这几个规则执行:
- 清晰度过滤。分辨率太低、严重失焦的图片直接删除。一张图里人脸部分小于预设像素标准的,不留作训练样本。
- 近似重复的去重。监控视频抽帧会产出大量相似图片,我用简单的感知哈希做了相似度比对,把近似重复的图片剔除,避免训练时某个场景被过度强化,导致模型对真实场景产生偏差。
- 保难样本。逆光、低头、侧脸、手挡、刘海遮眼、口罩拉到下巴,这些难样本刻意保留,而且会在后面对这些场景做针对性补充。
- 场景分层。按闸机、走廊、活动区三个场景做了分组,训练时保持每个场景的样本比例,不因为某个场景的图好采集就让它淹没掉其他场景。
这里有一个教训:如果数据集里室内空调环境占了80%,比例失衡会让模型默认“人脸都在光线良好的室内”,一旦遇到室外的强光和阴影,表现就会明显下降。
3.2 标注规范与质检
数据标注是整个过程中最容易被低估的一步。说实话,我一度以为标注就是画框和选类别,做起来才发现,标注规范不一致,会让模型学到完全错误的东西。
我们做的第一个版本,有人把口罩部分单独框出来,有人把整个头部框进去,有人严格遮住额头只框面部。后来模型上线测试时发现,对“未佩戴”的判断忽高忽低,复盘后才意识到是标注框的松紧度不一致导致的。后来我重新制定了标注规范,核心就三条:
- 所有人员人脸目标统一标注:脸部整体区域,即从额头到下巴的正面或侧面可见部分,不能只标口罩区域。
- 遮挡超过一半的目标不纳入标注,保持背景类别默认。画面边缘的目标照常标注,但只标画面内可见部分,让模型学习完整目标概念时不受边缘截断影响。
- 多人同框时,所有人脸都必须标注,不能只标中心人物或“看起来清晰”的人。
标注完成后要有一个质检环节。我们按批次抽检,每批抽10%到20%的标注结果,重点看框的贴合度和类别是否一致。抽检中出现争议的图片单独拉出来评审。这一步虽然耗时,但能省下后面训练的很多反复。
数据增强策略我也在这个环节考虑了。平台通常会自动做一些翻转、缩放、色域变换,但我额外确认了一点:不做过度的马赛克类增强,因为我们要识别的是与现场强相关的“局部遮挡”问题,无脑拼图会产生大量不符合真实场景的合成目标,反而干扰训练。
4. 训练过程与参数设置:从第一版模型到稳定版本
4.1 预训练模型选用逻辑
专业版平台通常提供了多个预训练模型选项,我们当时面对的选择是:是高精度模型还是轻量化模型。有人可能会想:精度优先,先跑通再压缩。我这次没有这么做,而是先确认了部署目标硬件——一台常见配置的边缘计算盒子,CPU为主,没有独立显卡。这个约束直接决定了模型选型:模型再准,在盒子上跑不动就没有意义。
所以我选了平台上轻量化模型作为主线。它牺牲了一部分精度上限,但保证了导出到本地后能在边缘盒子上以可用帧率跑起来。先以轻量化模型跑通全链路,再在有余量的前提下考虑升级到高精度模型,这个顺序比较稳妥。
如果你同样是部署在边缘设备上,建议选模型前先查清楚两个参数:模型导出后的FLOPs数据,以及平台是否有针对边缘硬件的加速转换工具链。不要在训练完之后才发现模型跑不动,再从头换模型,时间成本很高。
4.2 训练配置与调参
平台屏蔽了底层细节,但我们能调整的关键参数还是有几个,这部分我的操作经验和建议如下:
训练输入分辨率方面,我们最终用的是短边640像素。分辨率越高对小目标越友好,但推理耗时也同步增长。在走廊这类中远景场景,人脸只占画面很小一部分,第一版模型在640分辨率下漏检明显,后来我把分辨率提到短边768,小目标的检出率提高了不少。代价则是单帧耗时从约50毫秒涨到了约80毫秒,还在可接受范围内。
训练轮数方面,平台通常默认设置较多的最大轮数,并带有早停机制。我早期自己控制训练轮数时,也踩过“欠拟合”的坑,训练还没收敛到平台设置的验证指标就草草结束。后来我改用默认的最大轮数,配合早停策略,让模型充分拟合,再依据验证指标来做判断。平台显示验证集loss和mAP曲线的,记得开启自动保存最优模型,这样能在训练中途重启时直接取用最优结果。
学习率方面,微调阶段不建议用太大的学习率。平台如果开放学习率参数,一般会落在0.0001到0.001这个梯度区间。我们的数据量在一万张级别,属于中小规模微调,用偏小学习率更稳妥。
还有一个容易被忽略的参数是“置信度阈值”和“NMS阈值”。这两个参数更多是在部署和推理阶段生效,但训练时如果设置过高,会导致模型为了迎合阈值而变得过于保守,宁可漏检也不报。我们训练的早期版本把置信度阈值提到0.6,后来在走廊场景里漏检率偏高,放低到0.4之后有了明显改善。
4.3 评估与迭代策略
训练结束以后,平台会生成一套评估报告,包括各类别的精确率、召回率、mAP等指标。但我认为真正有价值的评估不是看这组数字,而是要回到真实的数据上做可视化验证。
我们把评估数据按照三个场景切分开,分别统计。这样做的原因很简单:整体mAP可能被数据量最大的闸机场景拉高,走廊和活动区表现不佳的情况会被掩盖掉。按场景看数据、按场景调参,比对着一个整体指标努力更有针对性。
首次迭代里,我发现模型对“佩戴口罩不规范”这一类别的召回率特别低,很多时候会被判成“正常佩戴”。问题出在数据上:团队拍摄模拟图时,“不规范佩戴”往往只是把口罩拉到下巴,鼻子的露出程度不高,这类样本的特征一致性不够强。后来我在补充数据时,有意识地加入“口罩遮住嘴、露出鼻孔”“口罩只挂一只耳朵”“口罩被拉到下巴但嘴巴闭合”等更细的变体,重新训练之后这一项的召回率提升了接近7个百分点。
所以我对平台训练迭代的整体认知是:每一轮训练结束后,一定要可视化错误样本,看分类错误的都是什么样的图,然后回到数据和标注层面找原因。图像数据里的变体不够,就去补变体;标注边界不一,就重标。算法层面的问题,平台帮你解决了大半;剩下的错误原因是数据层面占主导。
5. 部署与API集成:从一个Demo到可运维的服务
5.1 模型导出与端云协同形态
模型训练完成并达到目标指标后,进入部署阶段。平台支持导出不同格式的部署包,我最后确定的架构是端云协同:边缘计算盒子负责摄像头视频流的实时刻画和推理,中心服务器负责数据汇聚、告警规则和业务联动。
边缘部署包的意义在于:推理在本地完成,即使断网也不影响基础检测功能,这对门禁场景很重要。同时,本地推理也减少了对中心服务器的带宽压力。中心服务器只接收结构化的检测事件,比如“某号摄像头在什么时间检测到未佩戴口罩人员”,不再直接接收海量视频数据。
导出时有个值得注意的细节:平台导出的本地部署包不一定自带所需的全部依赖库,部署环境中缺了某些底层依赖,会导致推理服务起不来。我第一次导出后就在一台新盒子上遇到缺库问题,解法是提前在目标设备上安装和导出环境一致的运行环境,或者直接采用平台推荐的容器化部署。
5.2 API调用链路
在线API方式相对简单。我们在中心服务器上调用平台提供的在线接口,把边缘盒子推流中抽出的帧发送过去做检测。接口的调用基本遵循一个套路:图片编码成Base64,连同检测阈值参数一起POST给服务,返回检测框和类别。我简化后的请求结构大概是这样:
{ "image": "base64编码的图片数据", "confidence_threshold": 0.4, "nms_threshold": 0.5 }返回结果里包含每个目标的类别、置信度和检测框坐标。结合坐标信息,后端服务可以判断目标是否落在某个区域,比如闸机通道或门口区域。Python侧的调用代码核心逻辑如下:
import requests import base64 import json def detect_mask(image_path, api_url, threshold=0.4): with open(image_path, "rb") as f: img_b64 = base64.b64encode(f.read()).decode("utf-8") payload = { "image": img_b64, "confidence_threshold": threshold } resp = requests.post(api_url, json=payload, timeout=10) if resp.status_code != 200: # 记录日志并走告警通道,而不是静默失败 return [] data = resp.json() detections = [] for item in data.get("results", []): detections.append({ "class": item["name"], "score": item["score"], "bbox": item["bbox"] }) return detections这里想提醒一点:在线接口调用和本地推理不一样,延迟依赖网络质量,所以凡是涉及门禁联动这种低延迟场景,不能依赖在线API,一定要走本地部署。我们只在中心服务器的非实时审核任务里用在线API,实时检测全部放边缘。
另一个容易忽视的点是,检测结果不能只留坐标。纯坐标数据在后续追溯时非常痛苦,因为无法直观判断当时画面里发生了什么。我们在中心服务里保存了触发告警前后的原始截图,并限制访问权限,只允许特定角色查看,既满足追踪需求,也在一定程度上兼顾了隐私合规。
5.3 硬件选型与吞吐优化
部署涉及到一个老生常谈但永远有人踩的问题:接几路视频流,需要买多大算力的盒子。不要只看模型推理的理论速度,还要考虑多路视频的解码、缩放、预处理这些开销。
我们的边缘盒子,接四路1080p摄像头时,单纯模型推理的压力不大,但把四路视频流解码、缩放、resize、格式转换这些环节算进去,CPU占用就上来了。实际压测后我们做了一个抽帧策略:实时检测统一按每秒两帧进行,不追求逐帧全检。这个策略在人口通行速度下是够用的,因为一个人通过闸机的过程大约有2到3秒,两帧抽检能保证至少有一次有效检测。
推理服务的并发处理也值得优化。在线API或本地推理服务通常使用高性能推理框架来加速,但默认配置可能仍然只支持低并发连接。我们在服务前面加了一层简单的任务队列和超时重试逻辑,避免摄像头突发的多路并发请求把服务打满。
6. 实测效果与踩坑记录
6.1 测试场景与成绩
模型训练和部署完成后,我们到现场做了三轮实测。先放一组整体数据,我给这个项目做一个匿名化处理后的结果汇总:
| 场景 | 检出率 | 误检率 | 单帧耗时(边缘盒子) |
|---|---|---|---|
| 闸机近景 | 98.7% | 1.1% | 约65ms |
| 走廊中景 | 95.6% | 2.3% | 约65ms |
| 活动区多人 | 92.4% | 3.8% | 约75ms |
| 低光照/逆光 | 86.2% | 6.5% | 约75ms |
这个结果整体可以接受,但低光照场景离验收标准还有差距。复盘之后发现,低光照下的误检多集中在把深色背景中的衣领、背包带误判成口罩边缘,以及逆光下把阴影当成人脸轮廓。模型层面做了一些优化,但物理层面同样重要:我们协调现场物业给摄像头开启了宽动态模式,并在关键点位增加了补光,效果立刻好转,检出率从86.2%提升到92%以上。
6.2 一次典型误报问题的完整排查链路
部署到走廊场景的第二天,后台就开始报警。每过几秒就会冒出一条“未佩戴口罩”的告警,但现场查看根本没有人员经过,更别说没戴口罩的人了。第一天我怀疑是算法阈值太低,把置信度提升了0.05,结果告警频率降了一些,但还在持续。后来通过后台把触发的截图拉出来才发现,惹祸的是走廊拐角的一个“安全出口”指示牌,绿底白字,在特定光线角度下,指示牌下半部分的黑色边框形成了类似“口罩遮挡下半脸”的图案,模型信誓旦旦地给了0.82的置信度。
这个问题的完整定位路径是这样的:先怀疑部署环境,确认推理服务正常;再看告警截图,发现是固定物体;把截图拿去平台在线测试接口,平台同样判成了“未佩戴口罩”,排除本地模型损坏的可能;最后检查训练集,发现背景样本里类似“指示牌+深色下边框”的负样本几乎没有。
解决方式分两步:一是在走廊摄像头覆盖的固定区域,框定一个检测区域,把指示牌所在位置排除掉;二是收集这类指示牌、宣传栏、消防器材箱的图片加入训练集,明确标为背景。第二个步骤虽然见效慢,但长期有效。
排查过程中最让我印象深刻的不是技术问题,而是流程教训:模型上线前,一定要先用固定场景的空镜跑一段时间,采集误报数据,再进入正式联动。很多视觉项目的误报问题,不是模型算法不行,而是实际环境里存在大量训练阶段无法预料的人工制品。
6.3 其他高频问题与处理办法
这次项目里还遇到过几个问题,单独列出来,供大家参考。
第一个是戴帽子加口罩导致漏检。有些用户戴安全帽,帽檐会遮挡额头上方,人脸检测框的面积比正常小很多。后来在标注时,我要求对戴帽目标也正常标注,并把“头戴安全帽+口罩”的图片单独增加样本。训练后这个组合场景的表现明显改善。这个问题的本质是:模型依赖的“脸”的特征被帽子破坏了,而数据里没有足够的帽子相关负例,模型不知道该不该把人判断为目标。
第二个是手挡口罩的瞬时状态。有人抬手整理口罩的瞬间,手部会挡住口罩的大半部分,模型容易将其判断为“未佩戴”。这类问题很难完全消除,我们把处理策略放在告警逻辑上:单次告警不触发联动,只有连续多帧判定为“未佩戴”才报警。时序过滤器大大降低了瞬时遮挡带来的误报。
第三个是模型导出后的精度下降。平台在线API验证时准确率有97%,导出的本地部署包在边缘盒子上实测,精度掉了一到两个百分点。可能原因是为了边缘推理做的量化处理带来的损失。这个问题在可控范围内,但我建议验收时以“导出部署后的实际指标”为准,不要只看训练时的指标。
7. 项目完成后的一点复盘与扩展
整个项目从启动到第一次验收,前后用了大约五周。说句实话,如果靠团队自建模型去完成,这个周期至少要翻一倍,平台把我们完全没底的“训练环境准备”环节给省掉了,这是它最大的价值。
但平台也改变不了一个事实:决定这个项目成败的,不是模型算法,而是我们对场景的理解深度和数据准备的质量。没有现场数据,没有严格标注,没有针对性的负样本补充,再好的训练平台也只是空转。
如果后续要继续扩展,我建议先把“样本回流”这条链路做起来。把线上实际产生的告警截图和现场实拍定期加入训练集,重新训练并发布新版本模型。视觉模型的一大特点就是“现场感”,部署环境越复杂,这句话越重要。现在平台版本迭代也比较方便,一个月回流一次数据、重新训练和发布一次,是完全可以接受的运维节奏。
另外,如果项目要扩展到其他识别任务,比如安全帽识别、区域闯入检测、工装穿戴识别,这次搭建的数据标注、训练、评测、部署、告警链路是可以整体复用的。模型的训练和部署只占整个项目的一部分工作,真正沉淀下来的,是那套围绕数据流转和现场反馈迭代的工程方法。这也是我觉得做这类AI落地项目最值得投入的地方。