// ---- Configuration ---- // This must point to the folder holding model.json, weights.bin, and metadata.json const MODEL_URL = "./model/model.json"; const METADATA_URL = "./model/metadata.json"; // ---- Elements ---- const imageUpload = document.getElementById("imageUpload"); const preview = document.getElementById("preview"); const uploadLabel = document.getElementById("uploadLabel"); const predictBtn = document.getElementById("predictBtn"); const statusEl = document.getElementById("status"); const resultsEl = document.getElementById("results"); const resultListEl = document.getElementById("resultList"); let model = null; let uploadedImage = null; // ---- Load the Teachable Machine model as soon as the page opens ---- async function loadModel() { statusEl.textContent = "Loading model..."; try { model = await tmImage.load(MODEL_URL, METADATA_URL); statusEl.textContent = "Model loaded. Upload an image to begin."; } catch (err) { console.error(err); statusEl.textContent = "Could not load the model. Make sure model.json, weights.bin, and metadata.json are inside a 'model' folder next to this page."; } } loadModel(); // ---- Handle image selection ---- imageUpload.addEventListener("change", (event) => { const file = event.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = (e) => { preview.src = e.target.result; preview.hidden = false; uploadLabel.hidden = true; predictBtn.disabled = false; resultsEl.hidden = true; statusEl.textContent = "Image ready. Click Predict."; }; reader.readAsDataURL(file); }); // ---- Run prediction ---- predictBtn.addEventListener("click", async () => { if (!model) { statusEl.textContent = "Model is not loaded yet. Please wait and try again."; return; } statusEl.textContent = "Predicting..."; predictBtn.disabled = true; try { const predictions = await model.predict(preview); // Sort by confidence, highest first predictions.sort((a, b) => b.probability - a.probability); renderResults(predictions); statusEl.textContent = "Done."; } catch (err) { console.error(err); statusEl.textContent = "Something went wrong while predicting."; } finally { predictBtn.disabled = false; } }); // ---- Render results as labeled progress bars ---- function renderResults(predictions) { resultListEl.innerHTML = ""; predictions.forEach((p, index) => { const percent = (p.probability * 100).toFixed(1); const row = document.createElement("div"); row.className = "result-row"; const labelRow = document.createElement("div"); labelRow.className = "result-label-row" + (index === 0 ? " top" : ""); labelRow.innerHTML = `${p.className}${percent}%`; const barBg = document.createElement("div"); barBg.className = "bar-bg"; const barFill = document.createElement("div"); barFill.className = "bar-fill"; barFill.style.width = `${percent}%`; barBg.appendChild(barFill); row.appendChild(labelRow); row.appendChild(barBg); resultListEl.appendChild(row); }); resultsEl.hidden = false; }