ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

多人脸关键点标定与美颜美妆活体检测系统:从原理到工程实践

多人脸关键点标定与美颜美妆活体检测系统:从原理到工程实践 简介深度学习在人脸分析领域的应用已从单目标走向多目标、从静态走向动态。多人脸场景下的关键点标定不仅要求检测与跟踪的联动还需兼顾算力分配与精度稳定性。美颜美妆依赖精准的面部特征定位而活体检测则通过纹理与时序分析抵御照片、视频及面具攻击。本文从基础概念出发讲解RetinaFace、PFLD、MiniFASNet等模型的组合原理剖析磨皮美白、面部液化、妆容贴合等像素级算法并深入工程落地中的推理加速、批量处理与模型量化策略最终收敛到一套可复现的多人脸标定与美颜美妆活体检测系统方案为图像处理开发者提供从算法到部署的完整技术路径。 做这个项目前我其实被一个问题折磨了很久单张人脸的检测、关键点标定网上开源方案一大把但一旦进入多人场景再叠加美颜美妆和活体检测整个系统的复杂度是指数级上升的。你不仅要处理多张人脸同时出现时算力分配的问题还要确保每一张脸的关键点标定足够精准不然美妆效果稍微偏一点整张脸就毁了。更棘手的是如果这段视频是攻击者拿着一张照片或者一段录制视频来骗系统的活体检测要能瞬间识别出来。这套基于深度学习的多人脸标定与美颜美妆活体检测系统就是围绕这三个核心问题展开的是一套可以直接落地的源码级方案。这篇文章我会把整个项目的架构设计、三大核心模块的算法选型与实现思路、以及我在工程实践里踩过的坑全部梳理出来。不管你是刚入行的算法工程师还是已经在做图像处理项目但想往人脸细分方向深耕的开发者这篇文章都能给你一条足够清晰的技术路线。我会按模块拆解每一个环节都会给出实测的可行方案和参数配置尽量让你拿到思路之后就能自己复现。1. 系统整体方案先画清楚技术选型的边界在动笔写代码之前我花了大量时间做的事情是搭技术选型的框架。深度学习人脸项目最忌讳的就是一上来就堆模型最后发现模块之间根本没法串联。这套系统的整体逻辑其实非常清晰输入一段视频流或一张静态图先做人脸检测与跟踪锁定画面里的每一张人脸接着对每一张人脸做关键点标定拿到眉毛、眼睛、鼻子、嘴巴、脸部轮廓这些关键位置然后同时走两条分支一条是美颜美妆的渲染分支一条是活体检测的判定分支最终输出的是美颜后的画面和活体判定结果。1.1 核心模块划分与数据流设计我把系统拆成了六个子模块人脸检测模块、多目标跟踪模块、关键点标定模块、美颜处理模块、美妆渲染模块和活体检测模块。前三个是底层基础美颜美妆是效果层活体检测是安全层这样的划分让代码结构非常清晰。数据流我这里专门画了一个逻辑链条视频帧进来先送进人脸检测器检测器返回所有人脸的边界框。这里要注意多张人脸的情况下边界框会有一个先后顺序为了保持后续处理的稳定性我接了一个简单的IoU匹配跟踪器给每张人脸分配一个固定的ID。然后关键点标定模块根据每个边界框做区域裁剪分别输出68点或者106点的人脸关键点坐标。有了关键点之后美颜模块会对整张脸做皮肤区域识别和磨皮美白美妆模块依据关键点把口红、眼影、腮红这些妆容元素贴合上去活体检测模块则直接复用关键点和纹理信息做防攻击判定。最后所有模块的输出合并成一帧完整的渲染结果。1.2 模型选型为什么组合使用这几套网络模型选型上我踩过不少坑最后定下来的组合方式是检测用轻量化的RetinaFace-MobileNet关键点用PFLD活体检测用MiniFASNet而美颜美妆部分主要依赖图像处理算法辅以人脸解析网络。选RetinaFace的原因是它天然带自适应的锚点设计在多人密集场景下小脸召回率明显优于MTCNN而且它本身就输出五个关键点左眼、右眼、鼻子、左嘴角、右嘴角可以做检测和粗对齐的联动。PFLD则是我实测过在移动端和CPU上推理速度最快、同时精度也够用的轻量级关键点网络输出106点比68点更加精细尤其是嘴唇和眼睛周围对后续美妆贴合的精度帮助很大。MiniFASNet是常用的静默活体检测网络模型体积小输入是RGB深度红外三通道不过我实际使用中做了简化只用RGB通道配合一些后处理逻辑效果已经完全够用。2. 多人脸场景下的关键点标定从检测框到精准面部特征的完整链路多人脸场景和单张人脸最大的区别在于你不能简单地检测一张脸然后做标定因为画面里可能有多个目标而且前一帧和当前帧的人脸需要一一对应。这个模块表面上叫关键点标定实际上要解决的是检测跟踪标定三个问题的联动。2.1 多目标跟踪与ID分配的工程实现我在工程里采用了一个非常轻量的跟踪方案不引入DeepSORT这种重模型而是直接用检测框的IoU匹配。每一帧检测出来的边界框会和上一帧已经有ID的目标框做IoU计算如果IoU大于0.5就认为它们是同一个人脸继续沿用原ID否则判定为新出现的人脸分配一个新的ID。这样做的原因是人脸检测的应用场景中相邻帧之间目标的位移通常很小IoU匹配在绝大多数情况下已经足够稳定。只有目标发生大幅度快速运动或者出画又入画的情况下ID才会丢失重分配但这不影响美颜美妆的渲染效果因为无论是美颜还是美妆都是逐帧独立执行的。活体检测在短时间窗口内做状态积累ID抖动的影响也有限。多人脸的推理顺序我做了个优化检测框按面积从大到小排列面积大的优先做关键点标定和渲染。因为面积大的人脸在画面中通常更靠近镜头是用户关注的焦点优先处理能显著提升主观体验。当画面中人脸特别多时比如超过10张我会把超过算力阈值的人脸标记为低优先级只做美颜不做美妆保证帧率不会掉得太快。2.2 关键点回归的精度优化与旋转人脸处理PFLD网络的核心结构是自带一个辅助的边界框回归分支这保证了它在人脸大角度旋转时依然有不错的收敛能力。但在实际使用中我还是做了几层数据增强来强化这个优势水平翻转、随机旋转10度以内、随机亮度扰动和随机遮挡。旋转人脸的标定有个常见问题PFLD输出的106个点是在归一化坐标空间中的位置如果直接把原始图像输入网络大角度旋转下人脸的归一化坐标会非常不稳定。我这边的做法是先用RetinaFace输出的五个粗关键点做一次仿射变换把脸对齐到一个标准姿态双眼水平、人脸居中再送入PFLD做精细标定最后把标定结果通过逆变换映射回原图坐标。这样处理之后即使人脸倾斜超过30度标定出来的关键点位置误差也能控制在2到3个像素以内。2.3 关键点后处理平滑滤波与异常点剔除深度学习模型输出的关键点序列在视频流中会有抖动尤其是在低光环境或者运动模糊的情况下。我增加了一个基于指数滑动平均的轻量级平滑器对眼睛、嘴角、鼻尖这些高频关键点单独做平滑处理。指数滑动平均的权重alpha我最终调到了0.35这是综合了延迟和稳定性之后的结果alpha太高平滑效果不明显alpha太低关键点会显得粘滞美妆效果会有明显的滞后感。另外我还写了一个简单的异常点剔除逻辑如果某一帧某个关键点距离前一帧同一个关键点的欧氏距离超过脸宽的20%就判定为异常点直接丢弃用前一帧的值替代。这个阈值看起来简单却非常有效能过滤掉模型在极端表情下产生的漂移。3. 美颜美妆的算法实现关键点如何驱动像素级的渲染美颜美妆这部分看起来是纯效果层面的东西但越做越发现它对底层关键点的依赖程度高得惊人。没有精准的关键点后面所有工作都是空中楼阁。3.1 磨皮美白双边滤波与肤色检测的配合磨皮我选择了双边滤波作为基础算法而不是直接用GAN或者深度学习超分网络。原因很简单双边滤波在保留边缘信息的同时能对平坦区域做平滑计算开销小而且对皮肤纹理的保留效果比均值滤波和高斯滤波都好。但双边滤波有个问题它会对整张图做平滑会把眼睛、眉毛、头发这些本应保持清晰的区域也磨掉细节。所以我在滤波前先做了一次肤色检测用YCrCb色彩空间中的Cr和Cb分量范围来锁定皮肤区域。YCrCb空间比RGB更适合做肤色检测因为肤色在Cr和Cb上有非常集中且稳定的分布范围受光照变化影响小。我只对皮肤区域应用双边滤波非皮肤区域保持原样。这里有一个参数需要注意肤色检测的范围不能设得太宽否则会把背景中类似肤色的区域也磨掉也不能太窄否则会和美妆区域冲突。我最后将Cr的范围限定在133到173Cb的范围限定在77到127。美白是磨皮的配套操作。我在皮肤区域上叠加一层半透明的白色蒙版蒙版透明度根据原始亮度动态调整亮度越高叠加的白色越弱以此来保证高光区域的质感不会被破坏。盲目提亮肤色会导致整张脸变成一张纸片脸几乎没有任何立体感。3.2 面部几何微调瘦脸、大眼与脸型调整的实现逻辑瘦脸和大眼这类几何操作在传统方案里叫液化Liquify核心思路是对图像做局部区域的位移映射。我这里实现了两种位移映射方式一种是基于关键点的局部平移另一种是基于网格的全局变形。先讲局部平移。以瘦脸为例我会取下颌轮廓上的关键点作为控制点然后以每个控制点为中心设定一个半径为r的圆形作用区域。区域内的像素点会根据它到控制点的距离向面部中心方向做一个权重衰减的偏移。距离控制点越近偏移量越大边缘处偏移为零这样过渡会非常自然。网格变形的思路则更系统化一些。我基于关键点构造一个覆盖整个面部的三角网格在标准姿势下预先记录网格顶点的原始位置然后在瘦脸模式下把网格顶点的期望位置计算出来目标顶点相对于原始顶点有一个朝内收缩的偏移量。图像上每个像素点根据它所在的三角形利用重心坐标插值计算出对应的采样源位置。这种方式的好处是变形的连续性和自然度更好不会出现局部平移方式下可能产生的断层感。大眼的实现相对简单以眼睛关键点的中心点为圆心对视网膜范围做径向放大。径向放大的实现本质上是建立一个从目标坐标到源坐标的映射关系目标点离圆心越近它采样自源图像的位置离圆心就越远从而产生放大效果。放大强度我用一个标量系数控制1.0表示无缩放1.2表示放大20%实测下来1.15到1.25之间是比较自然的效果区间超过1.3就很容易出现恐怖片即视感了。3.3 妆容贴合口红、眉毛、眼影和腮红的像素级操作美妆部分对关键点的精度要求是最苛刻的。我先拿口红来举例。上下嘴唇的关键点一共有20个左右我会基于这些点生成两个多边形区域一个代表嘴唇外轮廓一个代表嘴唇内轮廓。外轮廓多边形用于确定口红的涂抹范围内轮廓用于做咬唇妆等效果时减少中心区域的色彩浓度。实际操作中我不会直接用多边形填充而是对外轮廓做一次高斯模糊处理让口红区域和周围皮肤的边界不是一条生硬的线而是有一圈自然的过渡。口红颜色的透明度我设置在0.6到0.8之间且越靠近嘴唇边缘透明度越低。这样能模拟出光线在嘴唇边缘的散射效果妆容会显得更真实。眉毛的绘制逻辑是用类似的方式在两个眉毛的关键点序列之间拟合一条自然曲线然后沿着曲线方向以一定的宽度做颜色填充。眉笔色号的选择很关键纯黑色看起来极其生硬我一般会选择深棕色或者灰棕色透明度0.5左右。眼影和腮红则是做区域着色眼影区域由眉毛下方和眼睛上方之间的关键点围成腮红区域以颧骨最高点为中心做一个半径可调的模糊圆斑颜色透明度都控制在0.3到0.4之间高了会显得像猴屁股。3.4 妆容的时序稳定性避免妆容在视频流中闪烁这是美妆模块最容易翻车的地方。很多人做完静态图的效果觉得惊艳一接到视频流就废了原因在于关键点帧间抖动会导致妆容区域每帧都在轻微变化反映到视觉上就是妆容在闪烁。我的解决方案是多管齐下。关键点的平滑处理在前文已经提过这是第一层保障。第二层保障是所有妆容区域的渲染参数均是全局统一的口红颜色、眉笔颜色、透明度这些不会因为人脸区域的微小位移而改变。第三层保障是我对妆容蒙版也做了一次时间维度的平滑当前帧的蒙版和上一帧的蒙版做加权融合权重各占0.5。这样即使关键点有轻微抖动蒙版的变化也会被缓冲掉视觉上就稳定了。4. 活体检测如何识别照片、视频和3D面具攻击活体检测的核心目标只有一个区分面前的人是活的真人还是攻击介质。常见的攻击手段包括打印照片、屏幕录制视频回放、甚至3D面具每种攻击的特征都不一样所以一个可靠的活体检测系统必须能应对多种攻击方式。4.1 静默活体检测与动作活体检测的取舍静默活体检测的典型代表是MiniFASNet它通过分析单帧图像中人脸的表面材质和反射特性来判断真伪。真人皮肤有一种自然的亚表面散射现象而打印照片和屏幕显示图像不具备这种物理特性在频域和纹理细节上会有明显差异。MiniFASNet通过深度可分离卷积和注意力机制来捕捉这些细微的材质特征。但静默活体检测有一个天然的弱点它对2D平面攻击照片、视频效果好但对3D面具攻击的鲁棒性不足。因为面具也是立体结构表面材质在某些情况下和真人皮肤有相似性。为了弥补这个缺陷我叠加了一个动作活体检测模块。动作活体检测的逻辑是随机生成一个动作指令眨眼、张嘴、点头、摇头要求用户在规定时间内完成。攻击者使用静态照片时无法完成连续动作指令使用录制视频时则会因为动作时序与指令不匹配而被识别出来。实际部署中我把静默活体检测作为第一道闸门动作活体检测作为第二道加强验证只在静默检测的可信度在0.5到0.8这个灰色区间时才触发。4.2 活体检测的时序特征建模只依赖单帧的活体检测结果在实际场景中会频繁误判。光照变化、运动模糊、摄像头成像质量都会导致单帧分类置信度剧烈波动。我的做法是引入一个时间窗口从视频流中连续采样最近15帧的检测结果做一个滑动窗口投票。只有当窗口内活体帧的比例超过70%时才最终判定为活体。这个策略的好处是偶尔的个别帧误判不会成为最终结果系统整体的稳定性会大幅提升。同时这个策略天然具备防攻击能力因为攻击者不可能控制连续帧的检测结果。我还额外做了一个小细节要求连续30帧内人脸区域不能出现完全相同的像素块。这个逻辑是专门对付屏幕录制视频回放攻击的因为录屏视频中的人脸区域静态部分会有大量完全一致的像素重复而真实视频中由于摄像头噪声和处理的原因几乎不可能出现完全相同的连续帧。4.3 活体检测与美颜模块的联动机制活体检测和美颜模块之间不是两条独立的流水线它们之间存在有序的联动。美颜模块会改变皮肤区域的纹理细节而这些纹理细节恰好是活体检测判断皮肤真实性的重要依据。所以系统设计里做了严格的时序约束先进行活体检测检测通过后才允许对这张人脸应用美颜美妆渲染。如果是活体检测不通过系统会返回告警画面中的人脸不做任何美化处理。这样做一是避免美化后的图像干扰后续活体判断二是对攻击者形成威慑攻击行为会被明确标注而不是被掩饰。5. 工程落地的性能优化与加速策略从算法原型到可用的系统中间还有一段漫长的路要走。这个项目在原型阶段单帧处理时间在GPU上能达到100ms级别但这样的性能根本无法满足实时视频流处理的需求。我花了大量精力做工程优化总结下来主要可以分成三个方面推理引擎的切换、多路推理的并发调度、以及模型量化的取舍。5.1 ONNX Runtime与TensorRT的加速对比最初所有模型都在PyTorch环境下运行PyTorch的动态图机制在训练阶段很灵活但在推理阶段会引入大量额外的调度开销。我把三个模型都固定输入尺寸后导出成ONNX格式用ONNX Runtime做推理。这一步做完整体推理耗时下降了20%到35%。ONNX Runtime的图优化引擎会自动做算子融合把一些连续的卷积、批归一化、激活函数融合成一个算子减少了内核启动次数。如果说ONNX Runtime是保守优化那TensorRT就是激进优化。TensorRT支持FP16推理并在支持的GPU上会自动选择最优的卷积算法甚至能做层间融合和显存复用。实测下来RetinaFace在TensorRT FP16模式下比PyTorch原始模式快了接近4倍PFLD的推理耗时更是降到了1ms以内。但TensorRT的缺点是部署复杂度高不同的GPU架构需要重新做一次引擎构建且不支持所有算子。项目里我做了个折中策略检测和关键点模型使用TensorRT加速活体检测模型使用ONNX Runtime在算力相对较弱的部署环境中全部回退到ONNX Runtime。5.2 多人脸场景下的批量推理与显存管理多人脸场景下如果逐张脸跑关键点模型会产生大量重复的显存分配和内核启动开销。我的做法是把同一帧中所有检测到的人脸做批量推理把所有裁剪下来的人脸图像按统一尺寸堆叠成一个batch一次前向计算出所有脸的关键点。PFLD的输入尺寸是112x96假设画面里有8张人脸用batch8的推理比逐张推理节省了大概60%的总耗时。TensorRT对于动态batch的支持不算特别友好所以我在工程里预先定义了三个batch档位1、4、8。每帧的人脸数量落在哪个档位就用哪个档位的引擎推理避免了动态shape带来的额外开销。这个细节对于实际部署很有价值。显存管理上我全程使用单例模式管理TensorRT引擎确保不管视频流有多少路同一个模型的引擎在显存中只有一份拷贝。多路视频流共享这一个引擎做推理只是输入的buffer不同。5.3 模型量化从FP32到INT8的精度损失控制FP16推理在大多数GPU上已经能获得不错的加速但为了满足边缘设备部署的需求我还尝试了INT8量化尝试。INT8量化的原理是用一个缩放因子把FP32权重和激活值映射到8位整数范围内计算的时候用INT8做矩阵乘最后再反量化回FP32。这种方案能把模型体积压缩到原来的四分之一推理速度还能有进一步提升。但INT8量化不是免费的午餐。模型在转换时需要准备一个校准数据集量化前后的精度会有损失。我在PFLD上实验发现直接PTQ量化后关键点的平均归一化误差从0.018上升到了0.035这对美妆贴合来说已经是一个不可接受的范围。最后我只对RetinaFace做了INT8量化因为检测任务对边界框位置的误差容忍度相对较高而PFLD和维护美妆效果的关键点标定仍然保留FP16。这个取舍在精度和性能之间找到了一个平衡点。6. 实测效果记录各种场景下的真实表现与局限6.1 正常光照与逆光环境下的多人脸表现在正常均匀光照条件下这个系统的表现是比较稳定的。我测试了一个4人并排出镜的画面四张人脸全部正确检出关键点标定平均误差控制在2像素左右美妆渲染效果流畅活体检测全部判定正确。帧率在NVIDIA RTX 3060显卡上稳定跑在30FPS以上CPU推理模式下只有12FPS左右实际部署时建议还是以GPU为主。逆光场景是很多算法翻车的地方。人脸在逆光条件下大部分处于暗部纹理信息大幅丢失。我的实测结果是PFLD在这种场景下的关键点标定误差会扩大到5到6像素尤其是嘴部区域暗部会导致嘴部轮廓提取不稳定口红妆容会出现轻微偏移。这个场景下活体检测的表现倒是挺好因为照片和真人在暗部区域的材质差异依然存在。逆光问题我最终用了一个预处理方案做缓解对输入图像做自适应直方图均衡化提升暗部区域的纹理可见度。这个操作在图像预处理阶段几乎不增加计算量但能明显改善暗光下人脸关键点的标定精度。如果项目允许增加一个红外补光灯逆光场景的效果会有质的提升。6.2 口罩佩戴、夸张表情和低分辨率人脸的特殊情况2020年之后口罩佩戴成了一个无法回避的测试场景。RetinaFace对佩戴口罩的人脸检测依然有效因为面部的上半部分特征还在。但关键点标定就严重受影响了因为PFLD依赖嘴唇和下巴轮廓来定位下半张脸的106个关键点口罩把这些信息全遮挡了。我实测下来口罩场景下嘴角和下巴关键点会随机漂移直接导致口红妆容错乱。针对这个情况我设计了一个简单的分支判断在关键点标定前先用一个分类网络判断是否佩戴口罩。如果佩戴口罩就切换到一个半脸模式只渲染眉毛和眼睛区域的妆容禁用口红和腮红渲染。这个判断逻辑在多人脸场景下尤其重要因为不能因为一个人戴口罩导致整个画面的算法产出非预期结果。夸张表情是另一个让算法崩溃的场景。张大嘴、做鬼脸、极度皱眉这些情况下关键点标定结果的形状会和标准脸型差异很大美妆贴合自然会出现问题。我这里在关键点后处理阶段加了一个人脸形状合理性检验计算嘴部关键点形成的多边形面积占比如果超过正常范围的1.8倍就判定为夸张表情自动降低美妆的渲染强度。低分辨率人脸比如50x50像素以下的人脸基本无法做有效的关键点标定这个场景下我会直接放弃美妆渲染只保留检测框跟踪。6.3 活体检测对抗测试照片、录屏和3D面具的攻防结果我针对活体检测模块做了一轮完整的对抗测试。第一轮是打印照片攻击把一张清晰的人脸照片打印在A4纸上举在摄像头前。静默活体检测在90%以上的测试序列中都能正确拒绝。偶发误判出现在照片有轻微反光、光线极其均匀的情况下。第二轮是屏幕录制视频回放攻击用手机拍摄一段录制好的人脸视频对着摄像头播放。这个攻击方式对单帧检测器的挑战很大因为视频帧的成像质量和真实摄像头几乎一样单纯从单帧纹理上很难区分。我的滑动窗口投票加连续帧像素对比策略在这一轮起到了关键作用连续像素完全一致的帧被识别为回放特征系统会在1秒内给出拒绝判定。第三轮是3D面具攻击我用的是一只高仿真的硅胶面具。静默活体检测在部分角度下会发生误判看面具表面的反射特性而定但动作活体检测会拦住这类攻击。面具在眨眼和嘴部动作上无法完美模拟真人动作指令和实际表现的细微时序差会被捕捉到。总体来看这套系统对照片攻击的拦截率最高对录屏攻击的拦截率也远超业界平均水平对3D面具攻击则需要依赖多层策略组合才能可靠拦截。7. 源码结构解读各模块函数与流程的代码级说明代码的组织方式对后续维护和二次开发影响很大。我按照模块化的思路设计了整个源码的目录结构每个模块内部保持高内聚、低耦合让代码可以独立替换和演进。7.1 项目目录组织与核心类设计项目根目录下主要包含五个核心Python包detection人脸检测、landmark关键点标定、beauty美颜、makeup美妆、liveness活体检测外加一个utils工具包和run.py入口文件。detection包中有FaceDetector类对外暴露detect方法接收一帧BGR图像返回所有人脸边界框和五个粗关键点landmark包中有一个FaceAlignment类对外暴露get_landmarks方法接收一帧图像和一个边界框返回106个关键点beauty包中有一个Beautifier类对外暴露beautify方法makeup包中有一个MakeupApplier类对外暴露apply_makeup方法liveness包中有一个LivenessDetector类对外暴露predict方法。这样的设计好处是接口边界极其稳定任何一个模块的内部实现换成更优的算法时只要接口签名不变其他模块完全不需要改动。实测中我把PFLD换成另一个关键点模型时只修改了FaceAlignment类内部整个项目其他部分一行代码都不用动。7.2 核心流程的伪代码级逻辑run.py中的主流程大概是这样一个逻辑链条# 视频流处理主循环 for frame in video_stream: faces face_detector.detect(frame) # 检测人脸 for face in faces: face_id tracker.update(face.box) # IoU跟踪分配ID landmarks face_alignment.get_landmarks(frame, face.box) # 关键点标定 landmarks landmark_smoother.process(face_id, landmarks) # 关键点平滑 if liveness_checker.is_attack(face.box, landmarks, frame): continue # 不是活体不做美颜 beauty_frame beautifier.beautify(frame, face.box, landmarks) final_frame makeup_applier.apply(beauty_frame, face.box, landmarks)这里有一个工程细节值的强调每一张人脸的跟踪状态、关键点缓存在内存中用一个字典结构管理key是face_idvalue是包含历史关键点列表、平滑权重、妆容蒙版缓存等状态的对象。这样实现了多张人脸的状态隔离不会出现不同人脸的平滑数据互相干扰。7.3 自定义数据集的标注与训练流程如果你想在自有场景上微调关键点模型比如针对特定人种或者特定摄像头角度做优化我建议不要从零训练。最佳性价比的做法是加载PFLD的预训练权重冻结前80%的层只对最后几层做微调。数据准备阶段需要把自己的数据标注成106点格式标注工具可以用LabelMe或者开源的关键点标注器。数据数量上微调场景5000张图像就足够了但要覆盖足够多的角度和光照变化。训练的一个容易忽略的细节是图像预处理必须和推理时完全一致PFLD训练时会做人脸对齐推理时如果没做同样的对齐精度会大打折扣。训练完成后把权重导出为ONNX格式并按照训练时的预处理逻辑写进推理代码的预处理函数中保持一致性。8. 项目优化与扩展方向从能用走向好用我把这个项目发布出去之后收到的反馈里有很多有价值的改进建议我自己也一直在做迭代。目前看下来有几个方向值得继续深入。8.1 妆容个性化从预设妆效到千人千面目前的美妆模块提供的是几套固定的预设妆效全屏统一无法适配不同人的面部特征和肤色。千人千面是一个更高级的目标。现在深度学习生成领域已经有不少成熟的妆容迁移模型如BeautyGAN、LADN它们能把参考图中的妆容风格迁移到目标人脸。但这类模型普遍存在计算量大、边缘不够精细的问题。我的思路是以现有的基于关键点的方案为基础叠加一个轻量级的妆容风格提取网络。这个网络不直接生成像素而是生成妆容的颜色分布和风格参数再交给基于关键点的渲染模块执行。这样做既保留了关键点方案的精准性和可控性又引入了风格迁移的灵活性是一个值得投入的方向。还有一个方向是结合大语言模型做自然语言交互。用户可以直接说给我一个蜜桃色的眼影系统通过文本解析出颜色和妆容类型然后驱动渲染模块生成对应的妆容效果。这个方向在技术上并无太多障碍核心工作量在文本指令到妆容参数映射库的建设上。8.2 端侧部署从服务器到手机端的移植在工程部署层面很多用户反馈想在手机端跑这套系统。手机端的算力和显存资源远不如服务器但又有比较苛刻的实时性要求。目前MobileNet系列和PFLD这类轻量级网络其实天然适合手机端部署真正需要解决的问题有两个一是将模型转换成NCNN或者MNN框架支持的格式二是针对手机端的多线程调度做优化。NCNN的转换流程相对成熟把ONNX转NCNN的工具有现成的遇到的不兼容算子数量也比较少。手机端实测中RetinaFace-MobileNet在骁龙8系列芯片上采用NCNN框架部署后单帧检测速度能达到30ms左右PFLD关键点检测单张脸大约8ms基本能满足实时对话场景的需求。但多人脸场景下手机端帧率会下降得比较快。我的优化方案是手机上限制最大处理人脸数量为3张超出的部分只检测不渲染这样能保持帧率在可接受范围内。8.3 隐私保护本地推理与模型精简人脸数据是高度敏感的隐私信息做这个项目时我一直很注意隐私设计上的自觉。我整体采用了端侧推理的架构思路图像和视频流只在本地处理不传到云端这在隐私层面是更稳妥的选择。模型精简也能辅助隐私保护因为模型体积越小在端侧运行的可行性越高就越不需要依赖云端算力。目前三个模型的总大小已经压到了40MB以内其中RetinaFace大约11MBPFLD大约5MB活体检测模型大约23MB。这个体积在移动端下载和加载都很快。最后再分享一个小技巧如果做端侧部署人脸标定模型和活体检测模型其实可以合并成一个多任务网络共享底层的特征提取层只在上层分出多个输出头。这样模型体积能进一步压缩30%左右整体推理速度也会更快代价是训练过程的复杂度会上升需要同时监督多个任务的损失收敛。我在实验环境里验证过这个方案的可行性效果还不错后续如果出第二版我大概率会采用这种结构重构底层模型。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进