| |
| |
| const MODEL_URL = "./model/model.json"; |
| const METADATA_URL = "./model/metadata.json"; |
|
|
| |
| 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; |
|
|
| |
| 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(); |
|
|
| |
| 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); |
| }); |
|
|
| |
| 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); |
|
|
| |
| 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; |
| } |
| }); |
|
|
| |
| 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 = `<span>${p.className}</span><span>${percent}%</span>`; |
|
|
| 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; |
| } |
|
|