| <!doctype html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1"> |
| <meta name="theme-color" content="#0d7a62"> |
| <meta name="description" content="Static browser-side waste image classification with MS-SE-EfficientNet-B0 and ONNX Runtime Web."> |
| <title>MS-SE Waste Classifier</title> |
| <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin> |
| <link rel="stylesheet" href="styles.css"> |
| </head> |
| <body> |
| <header class="site-header"> |
| <div class="brand"> |
| <div class="brand-mark" aria-hidden="true">♻</div> |
| <div> |
| <p class="eyebrow">Browser-side waste recognition</p> |
| <h1>MS-SE Waste Classifier</h1> |
| </div> |
| </div> |
| <div class="runtime-pill" id="runtimePill" aria-live="polite"> |
| <span class="status-dot" id="statusDot"></span> |
| <span id="runtimeText">Preparing runtime</span> |
| </div> |
| </header> |
|
|
| <main class="page-shell"> |
| <section class="hero-card"> |
| <div class="hero-copy"> |
| <p class="kicker">MS-SE-EfficientNet-B0</p> |
| <h2>Classify a waste image entirely in your browser.</h2> |
| <p> |
| Upload one image to obtain a ten-class probability distribution. The model uses |
| average, maximum, and standard-deviation channel descriptors with bounded residual attention. |
| </p> |
| <div class="privacy-note"> |
| <span aria-hidden="true">🔒</span> |
| <span>The selected image remains on this device during inference.</span> |
| </div> |
| </div> |
| <dl class="model-facts" id="modelFacts"> |
| <div><dt>Input</dt><dd>224 × 224 RGB</dd></div> |
| <div><dt>Classes</dt><dd>10</dd></div> |
| <div><dt>Parameters</dt><dd>4.234M</dd></div> |
| <div><dt>Runtime</dt><dd>WebAssembly</dd></div> |
| </dl> |
| </section> |
|
|
| <section class="workspace" aria-label="Image classification workspace"> |
| <article class="panel upload-panel"> |
| <div class="panel-heading"> |
| <div> |
| <p class="step-label">Step 1</p> |
| <h2>Select an image</h2> |
| </div> |
| <button class="text-button" id="clearButton" type="button" disabled>Clear</button> |
| </div> |
|
|
| <input id="fileInput" class="visually-hidden" type="file" accept="image/jpeg,image/png,image/webp,image/bmp"> |
| <label class="drop-zone" id="dropZone" for="fileInput" tabindex="0"> |
| <div class="upload-icon" aria-hidden="true"> |
| <svg viewBox="0 0 24 24" role="img"> |
| <path d="M12 16V4m0 0L7.5 8.5M12 4l4.5 4.5M5 14.5v3A2.5 2.5 0 0 0 7.5 20h9a2.5 2.5 0 0 0 2.5-2.5v-3"/> |
| </svg> |
| </div> |
| <strong>Drop an image here</strong> |
| <span>or click to browse</span> |
| <small>JPEG, PNG, WebP, or BMP</small> |
| </label> |
|
|
| <div class="preview-wrap hidden" id="previewWrap"> |
| <img id="imagePreview" alt="Selected waste image preview"> |
| <div class="image-meta"> |
| <strong id="fileName"></strong> |
| <span id="fileDetails"></span> |
| </div> |
| </div> |
|
|
| <button class="primary-button" id="predictButton" type="button" disabled> |
| <span id="predictButtonText">Classify image</span> |
| <span class="button-spinner hidden" id="buttonSpinner" aria-hidden="true"></span> |
| </button> |
| <p class="inline-message" id="inputMessage" role="status"></p> |
| </article> |
|
|
| <article class="panel result-panel"> |
| <div class="panel-heading"> |
| <div> |
| <p class="step-label">Step 2</p> |
| <h2>Prediction</h2> |
| </div> |
| <span class="provider-badge" id="providerBadge">WASM</span> |
| </div> |
|
|
| <div class="empty-result" id="emptyResult"> |
| <div class="empty-result-icon" aria-hidden="true">◎</div> |
| <h3>Results will appear here</h3> |
| <p>Load the model, select an image, and press “Classify image.”</p> |
| </div> |
|
|
| <div class="results hidden" id="results"> |
| <div class="primary-result"> |
| <div> |
| <p class="result-label">Predicted class</p> |
| <h3 id="predictedClass">—</h3> |
| </div> |
| <div class="confidence-ring" id="confidenceRing" aria-label="Prediction confidence"> |
| <span id="confidenceValue">0%</span> |
| </div> |
| </div> |
|
|
| <div class="top-three-wrap"> |
| <h4>Top three</h4> |
| <ol class="top-three" id="topThree"></ol> |
| </div> |
|
|
| <details class="all-probabilities" open> |
| <summary>All class probabilities</summary> |
| <div class="probability-list" id="probabilityList"></div> |
| </details> |
|
|
| <div class="timing-grid"> |
| <div><span>Preprocess</span><strong id="preprocessTime">—</strong></div> |
| <div><span>Inference</span><strong id="inferenceTime">—</strong></div> |
| <div><span>Total</span><strong id="totalTime">—</strong></div> |
| </div> |
| </div> |
| </article> |
| </section> |
|
|
| <section class="status-card" aria-labelledby="modelStatusTitle"> |
| <div class="status-title-row"> |
| <div> |
| <p class="step-label">Model status</p> |
| <h2 id="modelStatusTitle">Runtime initialization</h2> |
| </div> |
| <strong id="loadPercent">0%</strong> |
| </div> |
| <div class="progress-track" aria-hidden="true"> |
| <div class="progress-bar" id="progressBar"></div> |
| </div> |
| <p id="statusDetail" aria-live="polite">Loading ONNX Runtime Web…</p> |
| </section> |
|
|
| <section class="information-grid"> |
| <article class="info-card"> |
| <h2>Supported classes</h2> |
| <div class="class-chips" id="classChips"></div> |
| </article> |
| <article class="info-card"> |
| <h2>Notebook-matched preprocessing</h2> |
| <p>Direct resize to 224 × 224, RGB conversion, scaling to [0,1], and ImageNet normalization.</p> |
| </article> |
| <article class="info-card caution-card"> |
| <h2>Research use</h2> |
| <p>Visual ambiguity remains possible, especially among related packaging materials and general trash.</p> |
| </article> |
| </section> |
| </main> |
|
|
| <footer> |
| <p>Static ONNX inference · MS-SE-EfficientNet-B0 · Ten waste classes</p> |
| </footer> |
|
|
| <canvas id="preprocessCanvas" width="224" height="224" class="visually-hidden" aria-hidden="true"></canvas> |
|
|
| <script src="https://cdn.jsdelivr.net/npm/onnxruntime-web@1.27.0/dist/ort.min.js" crossorigin="anonymous"></script> |
| <script src="app.js?v=20260802-2"></script> |
| </body> |
| </html> |
|
|