AI 视觉的应用|ZegoAvatar ⾯部表情随动技术解析

发布时间 2023-10-13 15:44:28作者: ZEGO即构

 一、AI“卷”进实时互动

2021年,元宇宙概念席卷全球,国内各大厂加速赛道布局,通过元宇宙为不同的应用场景的相关内容生态进行赋能。针对“身份”、“沉浸感”、“低延迟”、“随时随地”这四个元宇宙核心基础,ZEGO 即构科技基于互动智能的业务逻辑,提出并落地了 ZegoAvatar 解决方案,将 AI 视觉技术应用至虚拟形象,完成了业务和技术的无缝衔接

 

 图1:Avatar 产品 AI 能力矩阵

 

ZegoAvatar 基础能力包括:面部表情随动、语音驱动表情、AI 人脸特征识别(AI 捏脸)、骨骼捏脸等,涉及的 AI 技术点包括人脸检测、人脸跟踪、人脸关键点检测、头部姿态检测、3D人脸重建、AI 特征识别等。

本文将重点针对 ZegoAvatar 中面部表情随动这一技术点进行解读。

 

二、ZegoAvatar 面部表情随动效果展示

 

在技术分享前首先让我们通过一组具体的数字和视频来看下 ZegoAvatar 的面部表情随动效果,我们分别在配置从低到高四种不同安卓设备上进行实际推理开销测试,取 1000 次推理结果求平均:

 

 图2:测试数据

 

从上述的数据中可以看到,ZegoAvatar 在不同机型上均以极低的延迟实现了实时推理的效果,在保证表情精准稳定的同时,为用户带来了流畅极致的使用体验。可点击下方⬇️视频查看效果:

resize,l_300

ZegoAvatar面部表情随动效果视频展示

 

三、面部表情随动技术方案解析

 

面部表情捕捉(Facial Expression Capture)广泛应用于电影、游戏、动漫制作等领域,而目前的面部动作捕捉依托于相机或激光扫描仪将人脸转换为一系列参数数据,然后用于生成计算机图形、电影、游戏或实时化身的计算机动画。

与捕捉由关节点构成、较为稳定的人体动作相比,面部表情更为细微复杂,因此对数据精度的要求也更高。现在主流的3D 面部表情捕捉主要有基于相机阵列和基于结构光两种方法,存在拍摄难度大,设备成本高的问题。

 

 图3:表情捕捉示意图

 

 

 

 

 图4:欧拉角示意图

ZegoAvatar 技术方案中的移动端面部表情随动是指通过移动端摄像头进行人脸检测以及跟踪,通过人脸位置、关键点信息定位出人脸在屏幕上的位置,并实时输出包含面部、舌头、眼球在内的 52 种基础面部表情维度的线性组合以及头部姿态的三个欧拉角,最后导入虚拟形象进行实时渲染驱动。点击更多即构Avatar表情随动

目前 ZegoAvatar 面部表情随动在不同性能的硬件设备上均实现了低延迟的落地效果,通过实时的虚实交互,为用户带来沉浸式的体验。本文将向大家详细解读 ZegoAvatar 的面部表情随动的算法整体架构以及如何在落地过程中做到面部表情随动效果的精确与自然。

ZegoAvatar 的移动端面部表情随动的技术方案分为模型训练部署推理两部分。

在训练过程,我们设计了一个轻量化的全卷积神经网络,包括网络骨干(BackBone)和三个不同的任务分支(如图3)。 Backbone 是由标准卷积 + MobileNetV2 Block + MobileViT Block 组成(如图4);多个输出分支分别为:3D面部特征点定位、面部表情识别、头部欧拉角姿态估计,其中不同的分支负责不同的任务。我们通过多任务学习的思想和迁移学习的技巧,给模型送入人脸特征和表情以及欧拉角标签,输出稳定的相关的映射关系。 

 

 

 图5:网络结构示意图

 

 

 

 

图6:网络骨干(Backbone)示意图

 

 

 

 

图7:训练和推理流程示意图

 

1、训练模块

根据数据采集模块得到表情数据,并通过数据矫正和增强后训练得到 AI 表情模型,具体分为以下几个部分:

  • 数据采集:针对业务需求,我们开发了一套可用于捕捉人脸和动作的数据采集软件,用于获取表情和欧拉角以及 3D 特征点位置数据。

 

  • 数据矫正:对采集的图片依次进行人脸检测,面部特征点对齐,通过仿射变换得到矫正后的图片;

 

  • 数据增强:针对落地场景,设计了定制化的数据增强流程,丰富了训练数据的模式;

 

  • 模型训练:基于多任务学习和迁移学习的思想,我们尝试了多种轻量级的网络结构和训练策略,设计不同的任务分支如特征点定位和头部姿态估计以及面部表情检测,利用任务之间的相关性辅助目标任务学习。

对模型进行训练,模型分为三个分支,损失函数组成如下:

L_{total} = \alpha * L_{exp} + \beta * L_{ldm} + L_{angle}</a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑

其中 L_{total}</a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑为总的损失函数,<span class="cke_widget_wrapper cke_widget_inline cke_widget_image cke_image_nocaption cke_widget_selected" data-cke-display-name="图像" data-cke-filter="off" data-cke-widget-id="16" data-cke-widget-wrapper="1"><a class="cke_widget_element" data-cke-widget-data="%7B%22hasCaption%22%3Afalse%2C%22src%22%3A%22https%3A%2F%2Flatex.csdn.net%2Feq%3FL_%257Bexp%257D%22%2C%22alt%22%3A%22L_%7Bexp%7D%22%2C%22width%22%3A%22%22%2C%22height%22%3A%22%22%2C%22lock%22%3Atrue%2C%22align%22%3A%22none%22%2C%22classes%22%3A%7B%22mathcode%22%3A1%7D%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="image"><img src="https://latex.csdn.net/eq?L_%7Bexp%7D" alt="L_{exp}" class="mathcode" data-cke-saved-src="https://latex.csdn.net/eq?L_%7Bexp%7D" /></a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑表示表情任务损失函数,<span class="cke_widget_wrapper cke_widget_inline cke_widget_image cke_image_nocaption cke_widget_selected" data-cke-display-name="图像" data-cke-filter="off" data-cke-widget-id="15" data-cke-widget-wrapper="1"><a class="cke_widget_element" data-cke-widget-data="%7B%22hasCaption%22%3Afalse%2C%22src%22%3A%22https%3A%2F%2Flatex.csdn.net%2Feq%3FL_%257Bldm%257D%22%2C%22alt%22%3A%22L_%7Bldm%7D%22%2C%22width%22%3A%22%22%2C%22height%22%3A%22%22%2C%22lock%22%3Atrue%2C%22align%22%3A%22none%22%2C%22classes%22%3A%7B%22mathcode%22%3A1%7D%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="image"><img src="https://latex.csdn.net/eq?L_%7Bldm%7D" alt="L_{ldm}" class="mathcode" data-cke-saved-src="https://latex.csdn.net/eq?L_%7Bldm%7D" /></a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑表示 3D 特征点定位损失函数,<img src="https://latex.csdn.net/eq?L_%7Bangle%7D" alt="L_{angle}" class="mathcode" />表示头部姿态估计损失函数,<span class="cke_widget_wrapper cke_widget_inline cke_widget_image cke_image_nocaption cke_widget_selected" data-cke-display-name="图像" data-cke-filter="off" data-cke-widget-id="14" data-cke-widget-wrapper="1"><a class="cke_widget_element" data-cke-widget-data="%7B%22hasCaption%22%3Afalse%2C%22src%22%3A%22https%3A%2F%2Flatex.csdn.net%2Feq%3F%255Calpha%22%2C%22alt%22%3A%22%5C%5Calpha%22%2C%22width%22%3A%22%22%2C%22height%22%3A%22%22%2C%22lock%22%3Atrue%2C%22align%22%3A%22none%22%2C%22classes%22%3A%7B%22mathcode%22%3A1%7D%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="image"><img src="https://latex.csdn.net/eq?%5Calpha" alt="\alpha" class="mathcode" data-cke-saved-src="https://latex.csdn.net/eq?%5Calpha" /></a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑和<span class="cke_widget_wrapper cke_widget_inline cke_widget_image cke_image_nocaption cke_widget_selected" data-cke-display-name="图像" data-cke-filter="off" data-cke-widget-id="13" data-cke-widget-wrapper="1"><a class="cke_widget_element" data-cke-widget-data="%7B%22hasCaption%22%3Afalse%2C%22src%22%3A%22https%3A%2F%2Flatex.csdn.net%2Feq%3F%255Cbeta%22%2C%22alt%22%3A%22%5C%5Cbeta%22%2C%22width%22%3A%22%22%2C%22height%22%3A%22%22%2C%22lock%22%3Atrue%2C%22align%22%3A%22none%22%2C%22classes%22%3A%7B%22mathcode%22%3A1%7D%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="image"><img src="https://latex.csdn.net/eq?%5Cbeta" alt="\beta" class="mathcode" data-cke-saved-src="https://latex.csdn.net/eq?%5Cbeta" /></a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑表示损失加权系数。其中损失函数采用我们根据训练过程设计的自适应加权回归损失,可以达到强调重点部位表情和弱化无关表情的效果,使整个模型更贴近业务的需求。

2、推理模块

推理模块根据输入数据进行推理,具体分为以下几个部分:

 

  • 数据输入和矫正:用户使用时解析输入视频流,对图片中的人脸进行检测、跟踪以及面部特征点定位,然后计算出人脸位置与标准人脸之间的仿射矩阵,从而通过仿射变换得到矫正后的图像;

 

  • 模型推理:对训练好的 AI 模型,进行剪枝和量化,在FP16半精度下,在移动端进行推理加速部署,最后将矫正后的图像送入模型,推理得到表情向量和欧拉角向量;

 

  • 表情驱动和渲染:将表情向量和欧拉角向量送入驱动渲染模块解析,实时驱动虚拟人物形象。

四、“精确而自然”的效果难点攻克

本技术旨在解决互动智能领域移动端虚拟人物表情实时驱动问题,在研发过程中需要解决以下问题:

  • 移动端推理的实时性
  • 面部表情和头部姿态的稳定性
  • 不同用户在不同使用场景的鲁棒性
  • 各个表情的协调性

这四个维度层层递进,而如何做到同时兼顾,是贯穿整个项目周期的重难点。

首先,受限于移动端的计算资源,不同设备的用户要正常体验,必须要做到各种机型上的低延迟,因此落地需要做到极致的轻量化,这对模型设计和部署有较高要求。

其次,实际体验过程中,用户的使用方式、用户场景光照、用户镜头脏污或遮挡都会影响模型的表现,如何在这些因素的综合作用下,让模型又快又稳的输出面部表情和头部姿态,是 ZegoAvatar 走向商业化不可回避的难题。

最后,考虑到不同的表情之间既有独立性又互相影响,如何让虚拟形象的表情更加拟人化,让用户的使用更有沉浸感,既是一个有挑战性的技术难题,也是一个有价值的业务问题。

针对以上难题,我们设计了以下技术方案:

1、推理的实时性

一方面设计模型时遵循轻量化的原则,比如使用深度可分离卷积(Depthwise separable convolution)以及更少的卷积层数和通道数,可以减少模型的参数量,从而降低推理的计算开销。

这里补充一下一般的卷积和深度可分离卷积的示意图,并对计算量优化进行简单分析:

 

 

 图8

 

深度可分离卷积将一般的卷积过程分为了depthwise convolution(逐深度卷积)和 pointwise convolution(逐点卷积),略牺牲精度的情况下,计算量大幅下降,速度更快,模型更小。

对于一般卷积,如果用D_k \times D_k</a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑表示卷积核的尺寸,<span class="cke_widget_wrapper cke_widget_inline cke_widget_image cke_image_nocaption cke_widget_selected" data-cke-display-name="图像" data-cke-filter="off" data-cke-widget-id="10" data-cke-widget-wrapper="1"><a class="cke_widget_element" data-cke-widget-data="%7B%22hasCaption%22%3Afalse%2C%22src%22%3A%22https%3A%2F%2Flatex.csdn.net%2Feq%3FD%22%2C%22alt%22%3A%22D%22%2C%22width%22%3A%22%22%2C%22height%22%3A%22%22%2C%22lock%22%3Atrue%2C%22align%22%3A%22none%22%2C%22classes%22%3A%7B%22mathcode%22%3A1%7D%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="image"><img src="https://latex.csdn.net/eq?D" alt="D" class="mathcode" data-cke-saved-src="https://latex.csdn.net/eq?D" /></a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑表示输入feature map的尺寸,<span class="cke_widget_wrapper cke_widget_inline cke_widget_image cke_image_nocaption cke_widget_selected" data-cke-display-name="图像" data-cke-filter="off" data-cke-widget-id="9" data-cke-widget-wrapper="1"><a class="cke_widget_element" data-cke-widget-data="%7B%22hasCaption%22%3Afalse%2C%22src%22%3A%22https%3A%2F%2Flatex.csdn.net%2Feq%3FM%22%2C%22alt%22%3A%22M%22%2C%22width%22%3A%22%22%2C%22height%22%3A%22%22%2C%22lock%22%3Atrue%2C%22align%22%3A%22none%22%2C%22classes%22%3A%7B%22mathcode%22%3A1%7D%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="image"><img src="https://latex.csdn.net/eq?M" alt="M" class="mathcode" data-cke-saved-src="https://latex.csdn.net/eq?M" /></a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑表示输入通道数,<span class="cke_widget_wrapper cke_widget_inline cke_widget_image cke_image_nocaption cke_widget_selected" data-cke-display-name="图像" data-cke-filter="off" data-cke-widget-id="8" data-cke-widget-wrapper="1"><a class="cke_widget_element" data-cke-widget-data="%7B%22hasCaption%22%3Afalse%2C%22src%22%3A%22https%3A%2F%2Flatex.csdn.net%2Feq%3FN%22%2C%22alt%22%3A%22N%22%2C%22width%22%3A%22%22%2C%22height%22%3A%22%22%2C%22lock%22%3Atrue%2C%22align%22%3A%22none%22%2C%22classes%22%3A%7B%22mathcode%22%3A1%7D%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="image"><img src="https://latex.csdn.net/eq?N" alt="N" class="mathcode" data-cke-saved-src="https://latex.csdn.net/eq?N" /></a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑表示输出通道数,那么在<span class="cke_widget_wrapper cke_widget_inline cke_widget_image cke_image_nocaption cke_widget_selected" data-cke-display-name="图像" data-cke-filter="off" data-cke-widget-id="7" data-cke-widget-wrapper="1"><a class="cke_widget_element" data-cke-widget-data="%7B%22hasCaption%22%3Afalse%2C%22src%22%3A%22https%3A%2F%2Flatex.csdn.net%2Feq%3Fstride%2520%253D%25201%22%2C%22alt%22%3A%22stride%20%3D%201%22%2C%22width%22%3A%22%22%2C%22height%22%3A%22%22%2C%22lock%22%3Atrue%2C%22align%22%3A%22none%22%2C%22classes%22%3A%7B%22mathcode%22%3A1%7D%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="image"><img src="https://latex.csdn.net/eq?stride%20%3D%201" alt="stride = 1" class="mathcode" data-cke-saved-src="https://latex.csdn.net/eq?stride%20%3D%201" /></a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑且有<span class="cke_widget_wrapper cke_widget_inline cke_widget_image cke_image_nocaption cke_widget_selected" data-cke-display-name="图像" data-cke-filter="off" data-cke-widget-id="6" data-cke-widget-wrapper="1"><a class="cke_widget_element" data-cke-widget-data="%7B%22hasCaption%22%3Afalse%2C%22src%22%3A%22https%3A%2F%2Flatex.csdn.net%2Feq%3Fpadding%22%2C%22alt%22%3A%22padding%22%2C%22width%22%3A%22%22%2C%22height%22%3A%22%22%2C%22lock%22%3Atrue%2C%22align%22%3A%22none%22%2C%22classes%22%3A%7B%22mathcode%22%3A1%7D%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="image"><img src="https://latex.csdn.net/eq?padding" alt="padding" class="mathcode" data-cke-saved-src="https://latex.csdn.net/eq?padding" /></a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑的情况下,总的计算量为:<span class="cke_widget_wrapper cke_widget_inline cke_widget_image cke_image_nocaption cke_widget_selected" data-cke-display-name="图像" data-cke-filter="off" data-cke-widget-id="5" data-cke-widget-wrapper="1"><a class="cke_widget_element" data-cke-widget-data="%7B%22hasCaption%22%3Afalse%2C%22src%22%3A%22https%3A%2F%2Flatex.csdn.net%2Feq%3FD_k%255Ccdot%2520D_k%255Ccdot%2520M%2520%255Ccdot%2520N%2520%255Ccdot%2520D_F%2520%255Ccdot%2520D_F%22%2C%22alt%22%3A%22D_k%5C%5Ccdot%20D_k%5C%5Ccdot%20M%20%5C%5Ccdot%20N%20%5C%5Ccdot%20D_F%20%5C%5Ccdot%20D_F%22%2C%22width%22%3A%22%22%2C%22height%22%3A%22%22%2C%22lock%22%3Atrue%2C%22align%22%3A%22none%22%2C%22classes%22%3A%7B%22mathcode%22%3A1%7D%7D" data-cke-widget-keep-attr="0" data-cke-widget-upcasted="1" data-widget="image"><img src="https://latex.csdn.net/eq?D_k%5Ccdot%20D_k%5Ccdot%20M%20%5Ccdot%20N%20%5Ccdot%20D_F%20%5Ccdot%20D_F" alt="D_k\cdot D_k\cdot M \cdot N \cdot D_F \cdot D_F" class="mathcode" data-cke-saved-src="https://latex.csdn.net/eq?D_k%5Ccdot%20D_k%5Ccdot%20M%20%5Ccdot%20N%20%5Ccdot%20D_F%20%5Ccdot%20D_F" /></a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑。

对于深度可分离卷积,逐深度卷积和逐点卷积的计算量分别为:

depthwise convolution的计算量为:D_F \cdot D_F \cdot D_k \cdot D_k \cdot M</a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑

pointwise convolution的计算量为:D_F \cdot D_F \cdot M \cdot N</a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑

因此深度可分离卷积和一般卷积的计算量比较关系为:

\frac{D_F \cdot D_F \cdot D_k \cdot D_k \cdot M + D_F \cdot D_F \cdot M \cdot N}{D_k\cdot D_k\cdot M \cdot N \cdot D_F \cdot D_F}=\frac{1}{N} + \frac{1}{D_k^{2}}</a><span class="cke_reset cke_widget_drag_handler_container"><img src="https://img2023.cnblogs.com/blog/2010000/202310/2010000-20231013153513790-539985141.gif" width="15" height="15" class="cke_reset cke_widget_drag_handler" title="点击并拖拽以移动" data-cke-widget-drag-handler="1" /><span class="cke_image_resizer" title="点击并拖拽以改变尺寸">​<span class="cke_widget_edit_container" title="编辑图片">编辑

由此可见,深度可分离卷积可以显著减少一般卷积的计算量。

另一方面落地时,我们基于移动端推理引擎进行模型转换和部署,主要分为算子转换和推理优化两个部分。

a.算子转换:主要通过算子融合、算子替代、模型压缩、布局调整等方式对模型中的图进行基本的优化操作;

b.优化推理:主要进行算子级的优化包括:卷积和反卷积中应用 Winograd 算法、在矩阵乘法中应用 Strassen 算法、低精度计算、手写汇编、多线程优化、内存复用等。

此外我们通过分析模型在不同网络层的的计算量分布,对模型存在计算瓶颈的卷积层进一步剪枝,在 FP16 半浮点数精度下,进行模型转换,在保证模型表现的同时,显著的降低了推理开销,并减少了模型的尺寸。

2、模型精确性和鲁棒性

首先是数据采集阶段,基于 ZEGO 自身业务,自主开发了一套数据采集软件,并通过脚本对每一批数据进行可视化检查,确保原始数据的正确性。

在模型训练阶段,尝试了多种模型结构和训练策略,包括不同的输入形式和分支组成。最后采用 3D 面部特征点分支和面部表情分支与头部欧拉角分支结合的方式,利用多任务学习思想和迁移学习的训练技巧,通过特征点信息辅助表情和欧拉角输出,得到精确的模型表现。

在最后落地时,由于用户和场景的不同,我们遇到了模型泛化性(Generalization)问题,这也是几乎所有计算机视觉任务落地时都会遇到的问题。

 

 

图9:泛化性、欠拟合(underfitting)、过拟合(overfitting)示意图

 

泛化性指模型经过训练后,应用到新数据并做出准确预测的能力。一个模型在训练数据上如果被训练得太好往往会导致过拟合,以致泛化性降低。

针对此问题,一方面从网络结构和训练策略出发,增加必要的组件,比如一定强度的 DropOut,损失函数正则项,设计EarlyStopping 机制,另一方面我们针对出现的场景问题,比如“眼镜反光”,“阴阳脸”,“镜头模糊脏污”等,进行多轮测试后去追溯和定位问题,然后设计了针对性的数据增强方案,通过完备性的消融实验(ablation experiment),确定了最优的流程和相应超参数,在训练过程中引入相应的数据模式,极大的提升了模型的精确性和鲁棒性,从而解决了这一难题。

3、表情的协调性

如何让虚拟形象不同的表情之间自然的联动,这是整个团队协作解决的问题。

一方面算法在网络BackBone的设计考量上,我们引入了 MobileViT 模块,因为尽管 CNN 网络在视觉任务上具有参数少效果好以及空间感知的优势,然而这种空间感知是局部的,全局感知可以通过注意力机制和 transformer 实现, 然而普通的 transformer 无法部署在移动端,MobileViT 可以将 ViT 与 MobileNetV2 的结合起来, 兼顾全局信息和轻量化的需求,让模型的推理效果又快又准。

另一方面,开发和设计同学持续的解决虚拟形象的各种材质渲染难题,最后才有了现在 ZegoAvatar 精致而自然的随动效果。

五、总结

ZegoAvatar 面部表情随动是 ZEGO 基于已有业务,通过 AI 结合元宇宙赛道的一次成功的尝试和突破。我们从数据采集方案到模型架构设计再到训练策略整个算法闭环,以及虚拟形象和相关组件的开发实现了完全的自研,在实际的落地效果上,我们做到了行业领先水平。

对于落地遇到的各种问题,我们从问题本质出发,设计针对性的方案进行解决,整个项目用较少的数据,取得了很好的效果。基于 ZegoAvatar,不同业务切入点的新的算法开发也在进行中,后续会有更多新的项目孵化,Zego科技也将进一步在互动智能领域不断实现技术革新与突破,在元宇宙浪潮中扬帆起航!