如何修改Google Teachable Machine模型以识别静态JPG图片而非摄像头流?
关于Google Teachable Machine TensorFlow.js模型识别静态图片的问题及解决建议
我有使用Google Teachable Machine生成的TensorFlow.js模型的需求,原生成代码能正常识别摄像头流,但修改为识别静态JPG图片时,无论用canvas还是img元素,预测结果都完全相同且错误。以下是原标准代码和我尝试的修改代码,求经验或建议:
原标准代码
<button type="button" onclick="init()">Start</button> <div id="webcam-container"></div> <div id="label-container"></div> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest/dist/tf.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/@teachablemachine/image@latest/dist/teachablemachine-image.min.js"></script> <script type="text/javascript"> // the link to your model provided by Teachable Machine export panel const URL = "myModel"; let model, webcam, labelContainer, maxPredictions; // Load the image model and setup the webcam async function init() { const modelURL = URL + "model.json"; const metadataURL = URL + "metadata.json"; model = await tmImage.load(modelURL, metadataURL); maxPredictions = model.getTotalClasses(); const flip = true; webcam = new tmImage.Webcam(200, 200, flip); await webcam.setup(); await webcam.play(); window.requestAnimationFrame(loop); document.getElementById("webcam-container").appendChild(webcam.canvas); labelContainer = document.getElementById("label-container"); for (let i = 0; i < maxPredictions; i++) { labelContainer.appendChild(document.createElement("div")); } } async function loop() { webcam.update(); await predict(); window.requestAnimationFrame(loop); } async function predict() { const prediction = await model.predict(webcam.canvas); for (let i = 0; i < maxPredictions; i++) { const classPrediction = prediction[i].className + ": " + prediction[i].probability.toFixed(2); labelContainer.childNodes[i].innerHTML = classPrediction; } } </script>
尝试的修改代码(未成功)
// predict can take in an image, video or canvas html element const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); const image = new Image(); image.onload = function() { ctx.drawImage(image, 0, 0); }; image.src = '1.jpg'; const prediction = await model.predict(canvas); //webcam.canvas for (let i = 0; i < maxPredictions; i++) { const classPrediction = prediction[i].className + ": " + prediction[i].probability.toFixed(2); labelContainer.childNodes[i].innerHTML = classPrediction; }
解决建议
核心问题:图片加载时机错误
你的修改代码中,model.predict(canvas)是在图片onload回调外部执行的,此时图片还未加载完成,画布上没有内容,模型预测的是空画布,结果必然错误。必须等待图片完全加载后再执行预测逻辑。
修正方案
方案1:直接使用img元素预测(更简洁)
Teachable Machine的model.predict()支持直接传入img元素,无需转成canvas,只需确保图片加载完成:
// 可在init函数完成后调用此方法 async function predictStaticImage() { const image = new Image(); // 处理跨域问题,本地测试或跨域图片必须设置 image.crossOrigin = 'anonymous'; image.onload = async function() { const prediction = await model.predict(image); for (let i = 0; i < maxPredictions; i++) { const classPrediction = prediction[i].className + ": " + prediction[i].probability.toFixed(2); labelContainer.childNodes[i].innerHTML = classPrediction; } }; image.src = '1.jpg'; }
方案2:正确使用canvas预测
如果必须用canvas,需确保图片加载后再执行预测,同时保证canvas尺寸与模型输入一致(原代码中为200x200):
async function predictWithCanvas() { const canvas = document.getElementById('myCanvas'); // 设置canvas尺寸匹配模型输入 canvas.width = 200; canvas.height = 200; const ctx = canvas.getContext('2d'); const image = new Image(); image.crossOrigin = 'anonymous'; image.onload = async function() { // 将图片绘制到canvas,按模型尺寸缩放 ctx.drawImage(image, 0, 0, canvas.width, canvas.height); const prediction = await model.predict(canvas); for (let i = 0; i < maxPredictions; i++) { const classPrediction = prediction[i].className + ": " + prediction[i].probability.toFixed(2); labelContainer.childNodes[i].innerHTML = classPrediction; } }; image.src = '1.jpg'; }
额外注意事项
- 跨域问题:本地测试时,直接打开HTML文件可能无法加载本地图片,建议用本地服务器(如
python -m http.server)运行项目。 - 路径正确性:确保图片路径与HTML文件相对位置正确,或使用绝对路径。
- 模型输入尺寸:必须保证传入的图片/canvas尺寸与训练时的输入尺寸一致(原代码中为200x200),否则会导致识别偏差。
内容的提问来源于stack exchange,提问作者user24857504
相关产品推荐
相关产品推荐

