TensorFlow JS调用createDetector时出现未处理Promise拒绝错误求助
React Native中调用MoveNet姿态检测createDetector时触发TypeError错误
尝试在React Native项目中使用@tensorflow-models/pose-detection进行人体姿态检测,调用createDetector加载MoveNet模型时触发TypeError,错误指向decodeString方法未定义,已排查依赖但未解决问题。
代码实现
import React, { useEffect, useState } from 'react' import { StyleSheet, Text, View, Button, Image } from 'react-native' import sample from './assets/sample.jpg' import * as tf from '@tensorflow/tfjs' import * as poseDetection from '@tensorflow-models/pose-detection' import '@tensorflow/tfjs-react-native' const App = () => { const [isTfReady, setTFReady] = useState(false); useEffect(() => { const getTF = async () => { tf.ready().then(setTFReady(true)) } getTF() }) const detect = async () => { const model = poseDetection.SupportedModels.MoveNet; const modelType = poseDetection.movenet.modelType.SINGLEPOSE_LIGHTNING; const detector = await poseDetection.createDetector(poseDetection.SupportedModels.MoveNet, { modelType: poseDetection.movenet.modelType.SINGLEPOSE_THUNDER }); const poses = await detector.estimatePoses(sample); } return ( <View style={styles.container}> <Image source={sample} style={{ height: '30%', width: '80%' }}></Image> <Text>TFJS ready? {isTfReady ? <Text>Yes</Text> : ''}</Text> <Button title='Detect' onPress={detect}></Button> </View> ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center' } }) export default App
依赖配置
"dependencies": { "@mediapipe/pose": "^0.5.1675469404", "@react-native-async-storage/async-storage": "1.17.11", "@tensorflow-models/pose-detection": "^2.0.0", "@tensorflow/tfjs": "^4.2.0", "@tensorflow/tfjs-react-native": "^0.8.0", "expo": "~48.0.6", "expo-camera": "~13.2.1", "expo-file-system": "~15.2.2", "expo-gl": "^11.4.0", "expo-gl-cpp": "^11.4.0", "expo-status-bar": "~1.4.4", "react": "18.2.0", "react-native": "0.71.3" },
错误日志
[Unhandled promise rejection: TypeError: undefined is not a function] at node_modules\@tensorflow\tfjs-core\dist\tf-core.node.js:null in decodeString at node_modules\@tensorflow\tfjs-core\dist\tf-core.node.js:null in <global> at node_modules\@tensorflow\tfjs-core\dist\tf-core.node.js:null in <global> at node_modules\@tensorflow\tfjs-core\dist\tf-core.node.js:null in decodeWeights at node_modules\@tensorflow\tfjs-converter\dist\tf-converter.node.js:null in GraphModel.prototype.loadSync at node_modules\@tensorflow\tfjs-converter\dist\tf-converter.node.js:null in GraphModel.prototype.load at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:null in _allocateCallback$argument_0 at node_modules\react-native\Libraries\Core\Timers\JSTimers.js:null in _callTimer - ... 8 more stack frames from framework internals
解决方案
1. 修复TensorFlow环境初始化逻辑
tf.ready()返回Promise,当前写法未正确处理异步流程,且useEffect缺少依赖数组会导致重复执行。修改后:
useEffect(() => { const initTF = async () => { await tf.ready(); setTFReady(true); }; initTF(); }, []); // 空依赖数组确保初始化只执行一次
2. 调整TensorFlow相关包版本兼容
当前@tensorflow/tfjs@4.2.0与@tensorflow/tfjs-react-native@0.8.0存在版本兼容问题,建议降级tfjs到3.x系列,同时匹配pose-detection版本:
"@tensorflow-models/pose-detection": "^1.1.0", "@tensorflow/tfjs": "^3.21.0", "@tensorflow/tfjs-react-native": "^0.8.0"
修改后执行npm install或yarn install重新安装依赖。
3. 正确处理图片输入格式
detector.estimatePoses()无法直接接收React Native的Image source,需要将图片转换为TensorFlow可处理的张量格式,配合expo-file-system读取:
import * as FileSystem from 'expo-file-system'; import { Asset } from 'expo-asset'; const detect = async () => { if (!isTfReady) return; // 将本地资源转为可读取的uri const asset = Asset.fromModule(sample); await asset.downloadAsync(); // 读取图片并转为张量 const imgData = await FileSystem.readAsStringAsync(asset.localUri, { encoding: FileSystem.EncodingType.Base64 }); const imgBuffer = tf.util.encodeString(imgData, 'base64').buffer; const tensor = tf.node.decodeImage(new Uint8Array(imgBuffer), 3); const detector = await poseDetection.createDetector(poseDetection.SupportedModels.MoveNet, { modelType: poseDetection.movenet.modelType.SINGLEPOSE_THUNDER }); const poses = await detector.estimatePoses(tensor); console.log(poses); tensor.dispose(); // 释放张量内存,避免内存泄漏 }
4. 切换轻量化模型测试
优先尝试体积更小、兼容性更好的SINGLEPOSE_LIGHTNING模型,降低加载时的兼容性风险:
const detector = await poseDetection.createDetector(poseDetection.SupportedModels.MoveNet, { modelType: poseDetection.movenet.modelType.SINGLEPOSE_LIGHTNING });
内容的提问来源于stack exchange,提问作者Faaiz Aslam
相关产品推荐
相关产品推荐

