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

如何使用JavaScript结合MediaPipe实现眼镜虚拟试戴?

基于MediaPipe JavaScript的3D眼镜虚拟试戴实现方案

核心实现逻辑不复杂,全程不需要依赖重型AR引擎,跑通基础版只需要4步,最终效果和参考动效完全一致:

  • 核心原理:调用MediaPipe Face Mesh实时输出人脸468个高精度关键点,定位眼镜佩戴的锚点位置,计算头部的旋转、缩放、位移参数,把眼镜素材(2D贴图/3D模型)做透视变换后叠加到摄像头画面上。

1. 基础页面与依赖准备

不需要本地安装包,直接通过CDN引入MediaPipe相关依赖即可,页面只需要一个隐藏的video标签承接摄像头流,一个canvas做最终画面渲染:

<script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/face_mesh/face_mesh.js" crossorigin="anonymous"></script>

<video id="inputVideo" playsinline style="display: none;"></video>
<canvas id="outputCanvas" width="1280" height="720"></canvas>

2. 固定锚点选取

MediaPipe Face Mesh输出的关键点索引是固定的,直接取这5个点就能完成眼镜定位,不需要额外做图像识别:

  • 左太阳穴锚点:索引234
  • 右太阳穴锚点:索引454
  • 鼻梁支撑锚点:索引6
  • 左眼眶下沿锚点:索引253
  • 右眼眶下沿锚点:索引33
    这几个点不会受表情、眨眼动作影响,定位稳定性足够。

3. 核心检测逻辑初始化

初始化Face Mesh检测器和摄像头流,配置参数只需要开单人检测、中等置信度阈值即可,在普通手机上也能跑到30帧以上:

const video = document.getElementById('inputVideo');
const canvas = document.getElementById('outputCanvas');
const ctx = canvas.getContext('2d');
// 提前加载好你的眼镜素材,2D版用透明PNG即可,3D版可以替换为Three.js模型加载
const glassImg = new Image();
glassImg.src = './your-glass-asset.png';

// 初始化人脸网格检测器
const faceMesh = new FaceMesh({
  locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/face_mesh/${file}`
});
faceMesh.setOptions({
  maxNumFaces: 1,
  refineLandmarks: true,
  minDetectionConfidence: 0.5,
  minTrackingConfidence: 0.5
});
faceMesh.onResults(renderFrame);

// 启动摄像头
const camera = new Camera(video, {
  onFrame: async () => await faceMesh.send({image: video}),
  width: 1280,
  height: 720
});
camera.start();

4. 逐帧渲染逻辑

每一帧检测完成后,先把摄像头原始画面画到canvas,再根据关键点计算眼镜的位置、大小、旋转角度,叠加绘制即可:

function renderFrame(results) {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(results.image, 0, 0, canvas.width, canvas.height);

  if (!results.multiFaceLandmarks?.length) return;
  const points = results.multiFaceLandmarks[0];
  // 把归一化坐标转成canvas实际像素坐标
  const getCoord = (index) => ({
    x: points[index].x * canvas.width,
    y: points[index].y * canvas.height
  });
  const leftTemple = getCoord(234);
  const rightTemple = getCoord(454);
  const noseBridge = getCoord(6);

  // 计算眼镜参数
  const glassWidth = Math.hypot(rightTemple.x - leftTemple.x, rightTemple.y - leftTemple.y) * 1.1;
  const rotate = Math.atan2(rightTemple.y - leftTemple.y, rightTemple.x - leftTemple.x);
  const posX = noseBridge.x;
  const posY = noseBridge.y - glassWidth * 0.1; // 鼻梁位置往上微调,避免眼镜位置靠下

  // 绘制眼镜
  ctx.save();
  ctx.translate(posX, posY);
  ctx.rotate(rotate);
  ctx.drawImage(glassImg, -glassWidth/2, -glassWidth*0.3, glassWidth, glassWidth*0.6);
  ctx.restore();
}

效果优化方案

  • 要实现参考动效里的真实3D质感,不要用单张PNG贴图,引入轻量Three.js加载GLB格式的3D眼镜模型,把通过锚点计算出的头部俯仰、偏航、侧滚角直接同步给Three.js相机,模型会自动跟随头部做三维旋转,不会有2D贴图的扁平感
  • 增加平滑滤波:对每帧计算出的位置、角度、缩放值做0.15-0.2系数的线性插值,避免画面抖动
  • 增加遮挡判断:利用人脸轮廓关键点判断眼镜腿、镜框边缘是否被侧脸遮挡,对遮挡区域做裁剪或半透明处理,真实感会明显提升
  • iOS端一定要给video标签加playsinline属性,避免摄像头强制全屏导致渲染失效

内容的提问来源于stack exchange,提问作者Azamat Vahabov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 16:45:40