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
相关产品推荐
相关产品推荐

