我使用可教机器(Teachable Machine)创建了一个 TensorFlow 模型,并希望在 React Native 中实现它。我使用 cameraWithTensor 来获取输入,以下是摄像头视图
<TensorCamera // 标准摄像头属性 style={styles.camera} type={Camera.Constants.Type.front} // 与张量相关的属性 cameraTextureHeight={textureDims.height} cameraTextureWidth={textureDims.width} resizeHeight={320} resizeWidth={240} resizeDepth={3} onReady={makeHandleCameraStream()} autorender={true} />
以下是 makeHandleCameraStream
函数
const makeHandleCameraStream = ()=> { return (images, updatePreview, gl) => { const loop = async () => { const nextImageTensor = images.next().value; try { // const predictions = await model.estimateHands(nextImageTensor); const predictions = await model.predict(nextImageTensor); //这是出现错误的行 console.log(predictions) setPredictions(predictions) } catch (error) { // console.log(error.message) } requestAnimationFrame(loop); }; loop(); }; }
当我尝试使用 model.predict
时,出现以下错误
Error when checking : expected input_1 to have 4 dimension(s), but got array with shape [320,240,3]
我尝试更改这两行
let expandedImageTensor = tf.expandDims(nextImageTensor,0)// 未使用 reshape 时遇到错误:// Error when checking : expected input_1 to have shape [null,224,224,3] but got array with shape [1,320,240,3] const predictions = await model.predict(expandedImageTensor.reshape([null,240,240,3]));//添加 .reshape 后出现错误:Size(230400) must match the product of shape ,240,240,3
回答:
这里是我回答的另一个问题,同样是关于在 React Native 中对实时视频进行预测的。
需要注意的一些事项:
- 您不需要调整张量的大小,因为您可以使用
TensorCamera
的参数resizeHeight
、resizeWidth
和resizeDepth
进行动态调整,在这种情况下将它们设置为224,224,3
。 - 在
handleCameraStream()
函数中,您需要在模型状态被设置后才进行预测。 - 您需要主动取消动画帧,使用
cancelAnimationFrames
并使用requestAnimationFrame
获取帧的 ID,但我老实说忘了为什么要这样做。
export default function App() { const [isModelRead, setIsModelRead] = useState(false); const [useModel, setUseModel] = useState({}); const [model, setModel] = useState(null); const [cameraPermission, setCameraPermission] = useState(false); const [predictions, setPredictions] = useState([]); let requestAnimationFrameId = 0; useEffect(() => { return () => { cancelAnimationFrame(requestAnimationFrameId); }; }, [requestAnimationFrameId]); const setUp = async () => { try { await tf.ready(); const { status } = await Camera.requestCameraPermissionsAsync(); console.log(status); setCameraPermission(status == "granted"); const newmodel = await tf.loadLayersModel( bundleResourceIO(modelJson, modelWeights) ); setIsModelRead(true), setModel(newmodel); console.log("模型已加载"); console.log(cameraPermission); return model; } catch (error) { console.log("无法加载模型", error); } }; useEffect(() => { setUp(); }, []); let textureDims; if (Platform.OS === "ios") { textureDims = { height: 1920, width: 1080, }; } else { textureDims = { height: 1200, width: 1600, }; } const handleCameraStream = (tensors) => { if (!tensors) { console.log("未找到图像!"); } const loop = async () => { if (model) { const imageTensor = tensors.next().value; // 在位置 0 添加维度 const expandedImageTensor = tf.expandDims(imageResize, 0); const predictions = await model.predict(expandedImageTensor, { batchSize: 1, }); setPredictions(predictions.dataSync()); tf.dispose(tensors); } requestAnimationFrameId = requestAnimationFrame(loop); }; loop(); }; const predictionAvailable = () => { return <Text>{predictions}</Text>; }; return ( <View> {model && ( <TensorCamera // 标准摄像头属性 style={styles.camera} type={Camera.Constants.Type.front} cameraTextureHeight={textureDims.height} cameraTextureWidth={textureDims.width} resizeHeight={224} resizeWidth={224} resizeDepth={3} onReady={(tensors) => handleCameraStream(tensors)} autorender={true} /> )} {prediction && predictionAvailable()} </View> );}