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

React+Facemesh+Three.js项目出现info.backend.decComplexRef错误求助

React + Facemesh + Three.js 报错:info.backend.decComplexRef is not a function

我正在开发一个基于React的应用,通过Facemesh追踪用户人脸并结合Three.js实现3D视差效果。起初程序能正常输出预期的Facemesh数据,但突然开始报错:

info.backend.decComplexRef is not a function TypeError: info.backend.decComplexRef is not a function
at Engine.disposeTensor (https://h5c2h5-3000.csb.app/static/js/bundle.js:30676:22) 
at Tensor.dispose (https://h5c2h5-3000.csb.app/static/js/bundle.js:75130:19)
at Engine.endScope (https://h5c2h5-3000.csb.app/static/js/bundle.js:30873:18) 
at https://h5c2h5-3000.csb.app/static/js/bundle.js:30240:23 
at t.<anonymous> (https://h5c2h5-3000.csb.app/static/js/bundle.js:16772:92) 
at https://h5c2h5-3000.csb.app/static/js/bundle.js:16024:17 
at Object.next (https://h5c2h5-3000.csb.app/static/js/bundle.js:16035:8)
at Engine.scopedRun (https://h5c2h5-3000.csb.app/static/js/bundle.js:30258:9) 
at Engine.tidy (https://h5c2h5-3000.csb.app/static/js/bundle.js:30237:19) 
at tidy (https://h5c2h5-3000.csb.app/static/js/bundle.js:31746:54)

项目代码

App.js

import React, { useRef, useEffect, useState } from "react";
import "./styles.css";
import { Canvas } from "@react-three/fiber";
import { OrbitControls } from "@react-three/drei";
import { Sky } from "@react-three/drei";
import { Physics, useBox, usePlane } from "@react-three/cannon";
import Webcam from "react-webcam";
import * as facemesh from "@tensorflow-models/facemesh";
import * as tf from "@tensorflow/tfjs";

export default function App() {
  const webcamref = useRef(null);
  const boxPosition = [0, 2, 0];
  const spotlightPosition = [
    boxPosition[0] + 3,
    boxPosition[1] + 5,
    boxPosition[2],
  ];

  const runFacemesh = async () => {
    const net = await facemesh.load({
      inputResolution: { width: 640, height: 480 },
      scale: 0.8,
    });
    setInterval(() => {
      detect(net);
    }, 100);
  };

  const detect = async (net) => {
    if (
      typeof webcamref.current !== "undefined" &&
      webcamref.current !== null &&
      webcamref.current.video.readyState === 4
    ) {
      const video = webcamref.current.video;
      const faces = await net.estimateFaces(video);

      if (faces && faces.length > 0) {
        const face = faces[0];
        const rotationY = face.annotations.midwayBetweenEyes[0][0];
        const rotationX = face.annotations.midwayBetweenEyes[0][1];
      }
      console.log(faces);
    } else {
      console.log(webcamref.current.video.readyState);
    }
  };

  const Box = () => {
    const [ref, api] = useBox(() => ({ mass: 1, position: boxPosition }));
    return (
      <mesh ref={ref}>
        <boxGeometry args={[1, 1, 1]} />
        <meshStandardMaterial color="hotpink" />
      </mesh>
    );
  };

  const Plane = () => {
    const [ref] = usePlane(() => ({
      position: [0, 0, 0],
      rotation: [-Math.PI / 2, 0, 0],
    }));
    return (
      <mesh position={[0, 0, 0]} rotation={[-Math.PI / 2, 0, 0]}>
        <planeGeometry attach="geometry" args={[100, 100]} />
        <meshLambertMaterial attach="material" color="brown" />
      </mesh>
    );
  };
  useEffect(() => {
    tf.setBackend("webgl");
    console.log(tf.getBackend());
    runFacemesh();
  }, []);
  return (
    <div style={{ width: "100vw", height: "100vh" }}>
      <Webcam
        ref={webcamref}
        style={{
          position: "absolute",
          marginLeft: "auto",
          marginRight: "auto",
          left: 0,
          right: 0,
          width: 640,
          height: 480,
          zIndex: -1,
        }}
      />
      <Canvas >
        <OrbitControls />
        <Sky />
        <ambientLight intensity={1.5} />
        <spotLight
          position={spotlightPosition}
          angle={0.3}
          penumbra={1}
          intensity={10}
          castShadow
        />
        <Physics>
          <Box />
          <Plane />
        </Physics>
      </Canvas>
    </div>
  );
}

package.json 依赖

"dependencies": {
    "@react-three/cannon": "^6.5.2",
    "@react-three/drei": "^9.80.2",
    "@react-three/fiber": "^8.13.6",
    "@tensorflow-models/facemesh": "^0.0.5",
    "@tensorflow/tfjs": "^4.10.0",
    "loader-utils": "3.2.1",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-scripts": "5.0.1",
    "react-webcam": "^7.1.1",
    "three": "^0.155.0",
  }

已尝试的解决方法

  • 切换TensorFlow.js后端为cpu:tf.setBackend("cpu")
  • 切换TensorFlow.js后端为wasm:tf.setBackend("wasm")
    但问题仍未解决。

解决方案

1. 降级TensorFlow.js版本到兼容版本

@tensorflow-models/facemesh@0.0.5属于旧版模型,和@tensorflow/tfjs@4.x存在API兼容性问题。将@tensorflow/tfjs降级到3.21.0(经过验证的兼容版本):

修改package.json中的依赖:

"@tensorflow/tfjs": "^3.21.0"

执行npm install或yarn install重新安装依赖。

2. 优化Tensor内存管理

在detect函数中用tf.tidy()包裹模型推理逻辑,确保临时张量及时释放,避免内存泄漏引发的异常:

const detect = async (net) => {
  if (
    typeof webcamref.current !== "undefined" &&
    webcamref.current !== null &&
    webcamref.current.video.readyState === 4
  ) {
    const video = webcamref.current.video;
    // 用tf.tidy包裹推理过程,自动清理临时张量
    const faces = await tf.tidy(() => net.estimateFaces(video));

    if (faces && faces.length > 0) {
      const face = faces[0];
      const rotationY = face.annotations.midwayBetweenEyes[0][0];
      const rotationX = face.annotations.midwayBetweenEyes[0][1];
    }
    console.log(faces);
  } else {
    console.log(webcamref.current.video.readyState);
  }
};

3. 避免重复加载模型

用useState保存模型实例,确保只加载一次,避免重复创建导致的资源冲突:

const [faceMeshModel, setFaceMeshModel] = useState(null);

const runFacemesh = async () => {
  if (!faceMeshModel) {
    const net = await facemesh.load({
      inputResolution: { width: 640, height: 480 },
      scale: 0.8,
    });
    setFaceMeshModel(net);
    // 模型加载完成后再启动检测循环
    setInterval(() => {
      detect(net);
    }, 100);
  }
};

4. 组件卸载时清理资源

在组件卸载时清除定时器并释放TensorFlow资源,避免内存泄漏:

useEffect(() => {
  tf.setBackend("webgl");
  console.log(tf.getBackend());
  let timerId;
  const init = async () => {
    const net = await facemesh.load({
      inputResolution: { width: 640, height: 480 },
      scale: 0.8,
    });
    timerId = setInterval(() => {
      detect(net);
    }, 100);
  };
  init();
  
  return () => {
    if (timerId) clearInterval(timerId);
    tf.disposeVariables();
    tf.dispose();
  };
}, []);

内容的提问来源于stack exchange,提问作者sarthak pawar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 00:22:03