ARFoundation之路-人脸检测增强之四

版权声明:Davidwang原创文章,严禁用于任何商业途径,授权后方可转载。

  苹果公司在iPhone X及后续机型上添加了一个深度摄像机(TrueDepth Camera),利用这个深度摄像机可以更加精准捕捉用户的面部表情,提供更详细的面部特征点信息。

(一) BlendShapes

  利用深度摄像机采集到用户面部表情特征,ARKit提供了一种更加抽象的表示面部表情的方式,这种表示方式就叫Blend Shapes。Blend Shapes在技术上是一组存储了用户面部表情特征运动因子的字典,共包含52组特征运动数据,ARKit会根据深度摄像机采集的用户表情特征值实时的设置相对应的运动因子。利用这些运动因子可以驱动2D或者3D模型,这些模型会实时的展现与用户一致的表情。

  ARKit实时提供全部52组运动因子,这52组运动因子中包括7组左眼运动因子数据、7组右眼运动因子数据、27组嘴与下巴运动因子数据、10组眉毛脸颊鼻子运动因子数据、1组舌头运动因子数据。但在使用时可以选择利用全部或者只利用一部分,如只关注眼睛运动,则只利用眼睛相关运动因子数据即可。
ARFoundation之路-人脸检测增强之四_第1张图片
  每一组运动因子表示一个ARKit识别的人脸表情特征,每一组运动因子都包括一个表示人脸特定表情的定位符与一个表示表情程度的浮点类型值,表情程度值的范围为[0,1],0表示没有表情,1表示完全表情,如在下图中,这个表情定位符为mouthSmileRight,代表右嘴角的表情定位,左图中表情程度值为0,即没有任何右嘴角表情,右图中表情值为1,即为最大的右嘴角表情运动,而0到1中间值则会对网格进行融合,形成一种过渡表情,这也是BlendShapes名字的来历。ARKit会实时捕捉到这些运动因子,利用这些运动因子我们即可以驱动2D、3D模型,这些模型会同步用户的面部表情,当然,我们可以只取其中的一部分所关注的运动因子,但如果想精确的模拟用户的表情,建议使用全部这52组运动因子数据。
ARFoundation之路-人脸检测增强之四_第2张图片

(二)技术原理

  在ARKit中,对表情特征位置定义了52组运动因子数据,使用了BlendShapeLocation来作为表情定位符,表情定位符定义了特定表情属性,如mouthSmileLeft、mouthSmileRight等,与其对应的运动因子则表示表情运动范围。这52组运动因子数据如下表所示。

表情定位符 描述
eyeBlinkLeft 左眼眨眼
eyeLookDownLeft 左眼目视下方
eyeLookInLeft 左眼注视鼻尖
eyeLookOutLeft 左眼向左看
eyeLookUpLeft 左眼目视上方
eyeSquintLeft 左眼眯眼
eyeWideLeft 左眼睁大
eyeBlinkRight 右眼眨眼
eyeLookDownRight 右眼目视下方
eyeLookInRight 右眼注视鼻尖
eyeLookOutRight 右眼向左看
eyeLookUpRight 右眼目视上方
eyeSquintRight 右眼眯眼
eyeWideRight 右眼睁大
jawForward 努嘴时下巴向前
jawLeft 撇嘴时下巴向左
jawRight 撇嘴时下巴向右
jawOpen 张嘴时下巴向下
mouthClose 闭嘴
mouthFunnel 稍张嘴并双唇张开
mouthPucker 抿嘴
mouthLeft 向左撇嘴
mouthRight 向右撇嘴
mouthSmileLeft 左撇嘴笑
mouthSmileRight 右撇嘴笑
mouthFrownLeft 左嘴唇下压
mouthFrownRight 右嘴唇下压
mouthDimpleLeft 左嘴唇向后
mouthDimpleRight 右嘴唇向后
mouthStretchLeft 左嘴角向左
mouthStretchRight 右嘴角向右
mouthRollLower 下嘴唇卷向里
mouthRollUpper 下嘴唇卷向上
mouthShrugLower 下嘴唇向下
mouthShrugUpper 上嘴唇向上
mouthPressLeft 下嘴唇压向左
mouthPressRight 下嘴唇压向右
mouthLowerDownLeft 下嘴唇压向左下
mouthLowerDownRight 下嘴唇压向右下
mouthUpperUpLeft 上嘴唇压向左上
mouthUpperUpRight 上嘴唇压向右上
browDownLeft 左眉向外
browDownRight 右眉向外
browInnerUp 蹙眉
browOuterUpLeft 左眉向左上
browOuterUpRight 右眉向右上
cheekPuff 脸颊向外
cheekSquintLeft 左脸颊向上并回旋
cheekSquintRight 右脸颊向上并回旋
noseSneerLeft 左蹙鼻子
noseSneerRight 右蹙鼻子
tongueOut 吐舌头

  需要注意的是,在上表中表情定位符的命名是基于人脸的,如eyeBlinkRight定义的是人脸右眼,在呈现3D模型时我们镜像了模型,看到的人脸模型右脸其实在左边。

  有了表情特征运动因子后,就需要使用到Unity的SkinnedMeshRenderer.SetBlendShapeWeight()方法,该方法原型为:

  public void SetBlendShapeWeight(int index, float value);

  该方法有两上参数,index参数为需要融合的网格索引,其值必须小于Mesh.blendShapeCount值;value为需要设置的BlendShape权重值,这个值与模型设定值相关,可以是[0,1],也可以是[0-100]等等。

  该方法主要就是用于设置指定网格索引的BlendShape权重值,这个值表示从源网格到目标网格的过滤(源网格与目标网格拥有同样的拓扑结构,但顶点位置两者有差异),最终值符合以下公式:

V f i n = ( 1 − v a l u e ) ∗ V s r c + v a l u e ∗ V d e s Vfin = (1-value)*Vsrc + value*Vdes Vfin=(1value)Vsrc+valueVdes

  因此,通过设置网格的BlendShape权重值可以将网格从源网格过渡到目标网格。如下图所示。
ARFoundation之路-人脸检测增强之四_第3张图片

(三)使用BlendShapes

  从上文可以看出,想要使用ARKit的BlendShapes功能需要满足两个条件:第一是有带有深度摄像机的移动设备,第二是有一个BlendShape已定义好的模型,这个模型BlendShape定义最好与上表中对应一致。

  为模型添加BlendShape可以在3dMax软件中定义变形器,并做好对应的网格变形,如下图所示。
ARFoundation之路-人脸检测增强之四_第4张图片
  在满足以上两个条件后,使用BlendShapes就变得相对简单了,实现的思路是:
  (1)获取到ARKit表情特征运动因子,这可以使用ARKitFaceSubsystem.GetBlendShapeCoefiicients()方法获取到,这会返回一个Unity NativeArray数组,里面即包括所有52组表情特征运动因子数据。
  (2)模型挂载Skinned Mesh Renderer组件,其BlendShape与模型中定义折BlendShape标记符一致,如下图所示,绑定ARKit的表情特征定位符与Skinned Mesh Renderer中的BlendShape,使其保持一致。
ARFoundation之路-人脸检测增强之四_第5张图片
  (3)在Face数据发生改变时更新所有的表情特征运动因子,示例代码如下所示:

    void UpdateFaceFeatures()
    {
     
        if (skinnedMeshRenderer == null || !skinnedMeshRenderer.enabled || skinnedMeshRenderer.sharedMesh == null)
        {
     
            return;
        }
        using (var blendShapes = m_ARKitFaceSubsystem.GetBlendShapeCoefficients(m_Face.trackableId, Allocator.Temp))
        {
     
            foreach (var featureCoefficient in blendShapes)
            {
     
                int mappedBlendShapeIndex;
                if (m_FaceArkitBlendShapeIndexMap.TryGetValue(featureCoefficient.blendShapeLocation, out mappedBlendShapeIndex))
                {
     
                    if (mappedBlendShapeIndex >= 0)
                    {
     
                        skinnedMeshRenderer.SetBlendShapeWeight(mappedBlendShapeIndex, featureCoefficient.coefficient * coefficientScale);
                    }
                }
            }
        }
    }

  BlendShapes实现效果如下图所示。
ARFoundation之路-人脸检测增强之四_第6张图片

参考文献

1、blendshapelocation blendshapelocation

你可能感兴趣的:(ARFoundation之路,BlendShape,ARKit)