DuXRFace

基础库 1.10.3 开始支持

每一帧检测获取到的人脸对象。调用 DuXRFrameFaceMode#getUpdatedTrackableFaces 返回。通过对象下你可以获取到所有可以用到的人脸部分的数据。

下面是所有 DuXRFace 的属性:

centerPoseMatrix

centerPoseMatrix属性是一个用来表示人脸姿态的 4x4 的变换矩阵,存储在一个 Float32Array 中。

THREE.js 代码示例

1
2
3
4
5
6
7
const face = frame.getUpdatedTrackableFaces()[0];
if (face) {
// 将姿态矩阵应用到模型变换中
model.matrixAutoUpdate = false;
model.matrix.fromArray(face.centerPoseMatrix);
model.matrixWorldNeedsUpdate = true;
}

landmarks

landmarks 属性存储了底层算法得到的人脸所有的特征点数据,目前算法能够检测到人脸的 95 个特征点,每个特征点都有 xyscore 三个数据,分别是相对于相机的归一坐标(范围为 0 - 1)以及置信度。这 95 个特征点的数据都存在一个 Float32Array 中。

下面例子使用 Context 2D 的接口来绘制这些特征点

1
2
3
4
5
6
7
8
9
10
11
12
13
const landmarks = face.landmarks;
const width = ctx.canvas.width;
const height = ctx.canvas.height;
// 绘制成绿色
ctx.fillStyle = '#00ff00';
for (let i = 0; i < landmarks.length; i += 3) {
// 给到的 x 和 y 是归一到 0 - 1 的,所以如果要绘制在 canvas 上
// 需要缩放到画布的尺寸。
const x = landmarks[i] * width;
const y = landmarks[i + 1] * height;
// 用小方点表示特征点
ctx.fillRect(x, y, 4, 4);
}

当然除了简单的绘制,特征点还可以用来做很多其它的事情,可以说是大部分人脸应用的基础了,比如说美颜中的瘦脸、大眼、2D 贴纸等效果,都需要使用到这些特征点。

下面这张图片标注了每个特征点对应脸上的位置。

特征点标注图

skeleton

相关接口 DuXRSessionFaceMode#getSkeletonDefinition

skeleton 对象包含了骨骼节点的变换矩阵数据。

  • jointPoseMatrices

存储有所有骨骼节点 4x4 矩阵的 Float32Array,如何遍历获取每个骨骼节点需要的矩阵数据参考下面的代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 保存每个节点在 jointPoseMatrices 数组中的偏移下表
// 这个只需要在初始化的时候存储一次
const bonesOffsetMap = {};
const skeletonDef = xrSession.getSkeletonDefinition();
skeletonDef.joints.forEach(joint => {
bonesOffsetMap[joint.name] = joint.offset;
});

function update() {
// 每帧更新的时候根据初始化存储的偏移下标读取矩阵
skeleton.bones.forEach(bone => { // 遍历 THREE.js 中的骨骼节点
const offset = this._bonesOffsetMap[bone.name];
if (offset != null) { // 以防模型中的骨骼节点返回数据中没有
bone.matrix.fromArray(jointPoseMatrices, offset);
bone.matrixWorldNeedsUpdate = true;
}
});
}

blendShapes

blendShapes 属性表示了一系列预定义的五官的表情系数。这些系数可以用于实现三维渲染中的 Morph Animation,或者用于对比两个表情的相似度。

blendShapes 数据格式

1
2
3
4
5
6
7
8
9
10
11
// blendShapes 属性是一个数组,数组中每一项都有 name 和 weight 两个属性分别表示系数名字和系数值
[
{
"name": "browDownLeft",
"weight": 0.2
},
{
"name": "browDownRight",
"weight": 0.2
}
]

这些系数的命名跟 ARKit 中的 blendShapes 是一样的。下面是所有的系数列表: