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

3D眼镜虚拟试戴:模型定位与面部追踪问题求助

修复实时3D眼镜虚拟试戴的位置与跟踪问题

以下是针对代码问题的具体修复建议:

1. 正确赋值glassesModel全局变量

当前代码中glassesModel未被赋值,导致后续无法修改模型位置。修改loadGlassesModel函数:

function loadGlassesModel() {
    const loader = new GLTFLoader();
    loader.load('/static/models/sport_glasses_b307/scene.gltf', (gltf) => {
        glassesModel = gltf.scene; // 将加载的模型赋值给全局变量
        glassesModel.position.set(0, 2, 2);

        const scaleFactor = 0.04;
        glassesModel.scale.set(scaleFactor, 0.05, scaleFactor);

        scene.add(glassesModel);
    });
}

2. 移除干扰视角的OrbitControls

OrbitControls允许用户拖拽相机,会破坏虚拟试戴的固定视角,删除相关代码:

// 删除以下OrbitControls初始化代码
// const controls = new OrbitControls(camera, renderer.domElement);
// controls.enableDamping = true;
// controls.dampingFactor = 0.25;
// controls.screenSpacePanning = false;
// controls.maxPolarAngle = Math.PI / 2;

// 修改animate函数,去掉controls.update()调用
function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}

3. 修正2D坐标到3D空间的转换逻辑

Webcam的2D像素坐标需要转换为Three.js的3D世界坐标,同时适配视频与画布的比例:

  • 先定义全局比例变量:
let videoWidth, videoHeight;
let scaleFactorX, scaleFactorY;
  • 在startWebcam中初始化比例参数:
async function startWebcam() {
    const stream = await navigator.mediaDevices.getUserMedia({ video: true });
    webcamElement.srcObject = stream;

    await new Promise((resolve) => {
        webcamElement.onloadedmetadata = () => {
            videoWidth = webcamElement.videoWidth;
            videoHeight = webcamElement.videoHeight;
            // 根据相机FOV和距离调整比例,示例值需根据实际场景微调
            scaleFactorX = 8 / videoWidth;
            scaleFactorY = -6 / videoHeight; // 负号修正Y轴翻转问题
            resolve();
        };
    });

    isVideo = true;
    await new Promise(resolve => requestAnimationFrame(resolve));

    loadGlassesModel();
}
  • 更新drawLandmarks中的模型位置计算:
if (glassesModel) {
    // 将双眼中心的2D坐标转换为3D空间坐标,以屏幕中心为原点对齐
    const x = (averageEyePosition[0] - videoWidth/2) * scaleFactorX;
    const y = (averageEyePosition[1] - videoHeight/2) * scaleFactorY;
    glassesModel.position.set(x, y, -5);
    glassesModel.visible = eyesDetected;
}

4. 修复Mediapipe Landmark识别逻辑

当前通过landmark[5]判断眼睛的方式错误,Mediapipe Face Mesh的关键点是固定索引的,直接使用官方定义的眼睛关键点:

// 替换drawLandmarks中的landmark遍历逻辑
for (const landmarkList of landmarksArray) {
    // 左眼关键点索引:33, 133;右眼关键点索引:362, 263
    const leftEye = landmarkList[33];
    const rightEye = landmarkList[362];

    // 绘制关键点(可选,用于调试)
    context.beginPath();
    context.arc(leftEye.x * videoWidth, leftEye.y * videoHeight, 2, 0, 2 * Math.PI);
    context.fill();
    context.beginPath();
    context.arc(rightEye.x * videoWidth, rightEye.y * videoHeight, 2, 0, 2 * Math.PI);
    context.fill();

    // 计算双眼中心坐标
    const averageEyePosition = [
        (leftEye.x * videoWidth + rightEye.x * videoWidth) / 2,
        (leftEye.y * videoHeight + rightEye.y * videoHeight) / 2,
    ];

    // 更新眼镜位置
    if (glassesModel) {
        const x = (averageEyePosition[0] - videoWidth/2) * scaleFactorX;
        const y = (averageEyePosition[1] - videoHeight/2) * scaleFactorY;
        glassesModel.position.set(x, y, -5);
        glassesModel.visible = true;
        eyesDetected = true;
    }
}

5. 优化相机设置适配试戴视角

调整相机参数,让3D模型更贴合真实面部视角:

const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.set(0, 0, 5); // 相机贴近屏幕,模拟第一人称视角
camera.lookAt(0, 0, 0);

6. 修复模型可见性控制逻辑

当前代码错误地尝试设置loadGlassesModel.visible(函数对象无此属性),直接使用glassesModel.visible即可:

// 删除错误代码:if (loadGlassesModel) { loadGlassesModel.visible = eyesDetected; }
// 替换为:
if (glassesModel) {
    glassesModel.visible = eyesDetected;
}

内容的提问来源于stack exchange,提问作者Amal Jallouli

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 05:16:05