AI 虚拟试妆:实时在脸上叠加妆容效果,怎么处理面部遮挡和光照变化

第一次用虚拟试妆 App 时,我干了件很蠢的事:打开前置摄像头,对着客厅的暖光灯,涂了一支“正红色”口红——屏幕上显示的是胡萝卜色。我以为是算法出了问题,后来才意识到,是我家的灯让颜色跑了。

AI technology illustration

这还不是最坑的。我理了理刘海,再往镜头前一凑,口红直接糊到了门牙上。没错,是贴图贴歪了。

这个经历让我意识到,虚拟试妆这个看起来“好玩”的功能,背后全是硬骨头。这篇文章想写的,就是其中最硌手的两个:面部遮挡光照变化

最朴素的实现:找关键点,然后贴图

最原始的虚拟试妆,本质上是“画上去”。流程很简单:先用目标检测模型找到人脸,再用关键点检测模型标出眼睛、鼻子、嘴唇等关键点,接着把口红的 PNG 素材按关键点做仿射变换,贴在嘴上。谷歌的 MediaPipe Face Landmarker 就能实时输出 468 个 3D 关键点,帮你把嘴框出来。这套管线跑在手机上毫无压力,于是很多早期 App 都这么做。

但它的弱点也很明显:关键点是“找点”,不是“理解区域”。你的手挡在嘴前,关键点检测器看到的就是一块模糊的像素,它根本不知道嘴在哪里。就算找到了,贴图的时候也会把手也涂上颜色。

遮挡:从“找点”升级到“理解区域”

怎么解决遮挡?一个自然的方向是把“点”换成“区域”——也就是语义分割。语义分割模型会给每个像素打一个标签:这是皮肤、这是嘴唇、这是头发。哪怕嘴唇被头发遮住了一半,模型也能根据周围像素的上下文,推测出整片嘴唇的轮廓。这样,妆容只作用于被标记为嘴唇的像素,头发再飘过来也不会蹭到口红。

但分割模型也有尴尬的时候。当遮挡面积过大,比如用口罩捂住半张脸,模型只能靠“脑补”猜测嘴唇的位置,这时候就很容易猜错。

更高级的解法直接放弃“贴图”这条路线,改用生成对抗网络(GAN)去“画”妆容。比如 BeautyGAN,它学习的是“素颜脸”到“带妆脸”的映射,网络自己决定在哪里画、画多浓。训练数据里如果包含大量遮挡样本,模型就能学会忽视遮挡,甚至把遮挡物上的误伤也抹掉。

这种方式的好处是,模型不再依赖关键点是否可见,而是学会了对整体人脸的完整理解。坏处是训练难,而且实时性是个问题——一个大规模生成网络跑在移动端,帧率很容易掉到 10 以下。

光照:你以为在涂口红,其实在做物理题

遮挡解决了,光照问题还在。虚拟试妆里最“反直觉”的部分是:同一个口红颜色,在不同光照下看起来完全不一样。因为你涂的不是颜色,而是“反射率”——它决定了光打到嘴上之后,哪些波长的光被反射回来。如果环境光本身是偏黄的,反射回来的光自然也就偏黄。

所以,处理光照的核心思路是:把反射率和环境光拆开。一个经典做法是先把图像从 RGB 转换到 Lab 或 YCbCr 颜色空间,这两个空间把“亮度”和“色度”分离了。亮度通道对应光照强度,色度通道对应颜色本身。上妆时只动色度,不动亮度,最后再把亮度和色度合并回去。这样,暗光环境下妆容不会变成一坨深色,亮光下也不会白得离谱。

另一种思路更激进:先做人脸光照归一化,把输入图的光照拉到一个标准状态,然后上妆,最后再把原来的光照信息恢复回去。这有点像是在拍照时先架好反光板,拍完再把反光板撤了。效果更好,但计算量更大。

我踩过的坑:光照才是 Demo 翻车的第一元凶

做第一个试妆原型时,我把所有精力都花在关键点对齐上。揉了揉眼睛,鼻梁上的眼镜反光,关键点全偏了;侧过脸,光照在脸上形成阴阳面,口红色号直接变暗。我这才明白,关键点检测只是门槛,遮挡和光照才是真正决定用户换不换 App 的因素

后来我试过各种花招:训练时随机加减亮度、用颜色迁移算法把参考妆容的颜色映射到目标脸上。最让我醍醐灌顶的是读到一篇关于循环一致性损失的论文——CycleGAN 不需要成对的训练数据,就能把素颜照片转换成带妆照片,而且它会自己学会适应不同光照。因为它被要求“转过去再转回来”时,图像还得长得一模一样,这就逼着模型去理解光照的本质,而不是盲目改变像素。

从此我意识到,要优雅地处理遮挡和光照,不能靠一堆 if-else,而是要教模型建立对“人脸应该长什么样”的先验知识。

三种技术路线的对比

方案 遮挡处理 光照处理 实时性 真实感
关键点贴图 几乎无效 依赖原图 中等
语义分割+贴图 可处理局部遮挡 可在颜色空间分离 较高
生成对抗网络 可学习遮挡补偿 通过对抗训练自适应

现实中的工程妥协

在真实产品里,你不会只用一个方案。通常的做法是:先用轻量级关键点模型做人脸对齐,再用一个小型分割模型标记嘴唇和眼周区域,最后用可微的颜色映射模块处理光照。这背后还有一个关键点:所有模型都要用大量遮挡和光照变化的样本来训练。为了让模型对光照鲁棒,训练时会故意叠加各种强光、阴影,甚至用 GAN 生成不同光照效果的假脸。

但即使这样,也有翻车的时候。戴着墨镜试眼影,墨镜反光,眼影直接“涂”到了镜片上;或者在地铁上逆光,阴影遮住了半边脸,妆容开始漂移。这些都是当前技术的边界。

总结:处理遮挡和光照,本质是让模型“懂物理”和“懂人脸”

回到最开始的问题。虚拟试妆其实是在做两件事:一是建立人脸结构的先验模型(哪怕看不到,也能推断出嘴唇在哪里),二是建立光照的物理模型(把反射率和环境光分离)。

现在的主流技术距离“完美”还有距离。极端遮挡(比如大面积口罩)和动态光源(比如 LED 彩灯)依然是难题。但在普通自拍场景下,你已经很难分清楚一个高质量的虚拟试妆和真妆的差别。

下一次你打开 App 试口红时,可以留意一下:你把刘海撩起来的时候,口红有没有抖一下?如果有,那说明它的语义分割还不够强。如果没有,那它多半用了不少心思在遮挡和光照上。

进阶:一种实用的光照归一化流程

用引导滤波估计低频光照图 L,那么反射率图 R = I / L(I 是原始图像)。在 R 上叠加妆容颜色(比如通过颜色查找表),得到新的反射率 R',最后输出 I' = R' × L。这样能保留原来的明暗分布,不会让妆容看起来像贴在画上。

常见误区:遮挡处理一定要用深度学习吗?

不是。早期系统可以用先检测遮挡区域、再用周边像素修补的传统图像处理方法,但鲁棒性差。深度学习的优势在于学了人脸先验,能把看不到的部分“猜”得合理。

为什么侧脸试妆容易翻车?

因为侧脸时部分关键点被遮挡,而且光照在侧面形成强烈梯度。解决侧脸问题通常需要 3D 人脸重建,把纹理映射到三维模型上,再投影回当前角度。这也是很多 App 提示“正对镜头”的原因。

原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/493.html

(0)
上一篇 3天前
下一篇 3天前

相关推荐