You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于MediaPipe与Three.js:获取头部旋转不变的面部特征点距离

问题:头部左右倾斜时,MediaPipe 3D面部特征点距离计算结果异常

我在浏览器应用中使用@mediapipe/tasks-vision库提取3D面部特征点,尝试计算左右眼角(特征点143和372)之间的距离。

当前使用Three.js计算距离的代码如下:

const distance = new THREE.Vector3(
  faces.faceLandmarks[0][143].x - faces.faceLandmarks[0][372].x,
  faces.faceLandmarks[0][143].y - faces.faceLandmarks[0][372].y,
  faces.faceLandmarks[0][143].z - faces.faceLandmarks[0][372].z
).length();

当用户正视摄像头时计算结果正常,但头部左右倾斜(Roll动作)时,计算出的距离会异常增大,尽管这两个点的实际物理距离并未改变。

如何在浏览器环境中,利用MediaPipe的3D特征点获取一致的、旋转不变的面部特征点距离?


解决方案

方法1:使用面部局部坐标系变换

MediaPipe返回的面部数据中包含面部姿态变换矩阵,可以将原始3D坐标转换到以面部自身为基准的局部坐标系,该坐标系不受头部旋转影响。

// 从MediaPipe结果中获取面部姿态变换矩阵
const transformMatrix = new THREE.Matrix4().fromArray(faces.faceTransformationMatrix);

// 将两个眼角点转换到面部局部坐标系
const point143 = new THREE.Vector3(
  faces.faceLandmarks[0][143].x,
  faces.faceLandmarks[0][143].y,
  faces.faceLandmarks[0][143].z
).applyMatrix4(transformMatrix);

const point372 = new THREE.Vector3(
  faces.faceLandmarks[0][372].x,
  faces.faceLandmarks[0][372].y,
  faces.faceLandmarks[0][372].z
).applyMatrix4(transformMatrix);

// 计算局部坐标系下的两点距离
const distance = point143.distanceTo(point372);

方法2:计算相对距离(归一化到面部基准)

如果无法获取姿态矩阵,可以用目标距离除以面部固定基准点的距离,抵消旋转和缩放的影响。比如选择左右耳屏点(特征点234和454)的距离作为基准:

// 计算基准距离(左右耳屏)
const baseDistance = new THREE.Vector3(
  faces.faceLandmarks[0][234].x - faces.faceLandmarks[0][454].x,
  faces.faceLandmarks[0][234].y - faces.faceLandmarks[0][454].y,
  faces.faceLandmarks[0][234].z - faces.faceLandmarks[0][454].z
).length();

// 计算目标距离(左右眼角)
const targetDistance = new THREE.Vector3(
  faces.faceLandmarks[0][143].x - faces.faceLandmarks[0][372].x,
  faces.faceLandmarks[0][143].y - faces.faceLandmarks[0][372].y,
  faces.faceLandmarks[0][143].z - faces.faceLandmarks[0][372].z
).length();

// 归一化后的相对距离(旋转不变)
const normalizedDistance = targetDistance / baseDistance;

方法3:反向旋转抵消Roll角

提取MediaPipe返回的面部Roll旋转角,创建反向旋转矩阵将点坐标还原到正视状态,再计算距离:

// 获取头部Roll角(弧度)
const rollAngle = faces.faceRotation.roll;

// 创建反向旋转矩阵(抵消Roll倾斜)
const rotationMatrix = new THREE.Matrix4().makeRotationZ(-rollAngle);

// 转换点坐标
const point143 = new THREE.Vector3(
  faces.faceLandmarks[0][143].x,
  faces.faceLandmarks[0][143].y,
  faces.faceLandmarks[0][143].z
).applyMatrix4(rotationMatrix);

const point372 = new THREE.Vector3(
  faces.faceLandmarks[0][372].x,
  faces.faceLandmarks[0][372].y,
  faces.faceLandmarks[0][372].z
).applyMatrix4(rotationMatrix);

// 计算校正后的距离
const distance = point143.distanceTo(point372);

内容的提问来源于stack exchange,提问作者Muhammad Afshal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 02:42:10