Filament实现简易Animoji
Animoji是首先由苹果提出的增强现实表情包,利用摄像头捕捉到的面部特征点,及麦克风记录的声音,最终生成的3D动画表情。我们尝试在Android上实现类似的效果,于是有了这篇文章记录技术重点。
特征点捕捉
模型选用Face mesh(如果对眼球转动有捕捉要求可以使用Iris),谷歌给出了其捕捉的468个特征点坐标图,我们在找到需要的特征点后,通过减法得到表情值大小,从而计算出加权顶点坐标位置对应的模型效果。
在神经网络推理框架的选择上,ncnn相对于MediaPipe有更高的性能优势,但是其camera相关功能使用camera2NDK,部分机型底层并不支持以至于出现黑屏现象,所以考虑到demo的实现效率,我们选用mediapipe,若想把此功能运用在商业产品上,可以考虑使用ncnn并替换到camera部分实现。
iris在face mesh基础上增加了Iris地标模型,如下图3d表情眼珠的区别:
![](google_animoji.gif)
3D引擎渲染工具
我们选择Filament作为3D模型渲染库,一是其用于Android设备上的Sceneform库中实现ARCore,二是其优秀的3D渲染效果及低耗能。当然我们因为不可抗拒因素无法直接使用ARCore,对Filament的学习势在必行。
Filament不仅有自己的模型格式,且支持glb/gltf,并且提供api操作节点,在初步了解光照、天空盒等概念后,开始编写demo。
从摄像头获取面部模型
Mediapipe已经把camera数据转换成了textureFrame,进而触发filament渲染模型。filament demo提供的Choreographer触发方式在此是行不通的,垂直同步时间戳已经是最小刷新间隔,同时使用会出现严重的卡顿问题。
从特征点到3D模型
那么如何把模型捕捉到的特征点转化为3D表情呢?这里以张嘴为例,设计给出的GLB文件已经定义好嘴部动作的权重,如”weights”
|
可以看到”weights”权重默认为1,我们通过获取特征点坐标17、0处y轴坐标值,转换ndc坐标后,做减法得出嘴巴张开度,从何获取其权重
|
Filament调用setMorphWeights设置mouth节点权重,从而实现嘴部的开闭。
|
在镜头前需要移动头部模型,那么如何实现模型的移动呢,我们决定选用鼻子顶部坐标来映射模型移动,即94处坐标。
|
Filament使用setTransform即可实现模型移动,如上可实现简易的animoji效果。
Filament实现简易Animoji
http://hanniballol.github.io/2022/07/25/Filament实现简易Animoji/