|
|
| Rad 1: |
Rad 1: |
| <!-- Margiela Fit Detector 🥼🫐 -->
| | == Margiela Fit Detector == |
| | | <div id="margiela-fit-detector"> |
| | | <!-- Tom – fylls av JS --> |
| <div style="text-align:center; color:#ddd; font-family:Arial, sans-serif; background:#111; padding:20px; border-radius:12px; margin:20px auto; max-width:780px;">
| |
| | |
| <h2>Margiela Fit Detector 🥼🫐</h2>
| |
| <p>Ladda upp en bild för att se om din fit liknar Maison Margiela.</p>
| |
| | |
| <input type="file" id="inputImage" accept="image/*" style="margin:10px;"><br>
| |
| <button onclick="classifyMargiela()" style="padding:10px 16px; background:#333; border:none; border-radius:8px; color:#eee; cursor:pointer;">
| |
| Kör analys
| |
| </button>
| |
| | |
| <div id="margielaResult" style="margin-top:14px; font-size:1.1em;">Ingen analys ännu…</div>
| |
| | |
| <div style="display:flex; justify-content:center; gap:24px; margin-top:20px;" id="margielaImages"> | |
| <div>
| |
| <p>Din bild</p>
| |
| <img id="userImg" style="max-width:240px; border-radius:8px; border:2px solid #555;">
| |
| </div>
| |
| <div>
| |
| <p>Referens (Margiela vibe)</p>
| |
| <img id="refImg" src="https://i.ibb.co/0KfYm1f/margiela-ref.jpg" style="max-width:240px; border-radius:8px; border:2px solid #555;">
| |
| </div>
| |
| </div>
| |
| | |
| </div> | | </div> |
|
| |
| <script>
| |
| let mgModel;
| |
| const MG_THRESHOLD = 0.62; // Margiela-tröskel, kan justeras
| |
|
| |
| async function mgLoadModel() {
| |
| mgModel = await tf.loadLayersModel(
| |
| "https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v2_1.0_224/model.json"
| |
| );
| |
| }
| |
| mgLoadModel();
| |
|
| |
| function mgImageToTensor(imgEl) {
| |
| return tf.tidy(() => {
| |
| return tf.browser.fromPixels(imgEl)
| |
| .resizeNearestNeighbor([224,224])
| |
| .toFloat()
| |
| .div(127.5).sub(1)
| |
| .expandDims();
| |
| });
| |
| }
| |
|
| |
| async function mgCosineSimilarity(a, b) {
| |
| const dot = a.mul(b).sum();
| |
| const magA = a.norm();
| |
| const magB = b.norm();
| |
| return (await dot.data())[0] / ((await magA.data())[0] * (await magB.data())[0]);
| |
| }
| |
|
| |
| async function classifyMargiela() {
| |
| const fileInput = document.getElementById("inputImage");
| |
| if (!fileInput.files.length) {
| |
| document.getElementById("margielaResult").innerText = "Du måste ladda upp en bild först.";
| |
| return;
| |
| }
| |
|
| |
| const userImg = document.getElementById("userImg");
| |
| userImg.src = URL.createObjectURL(fileInput.files[0]);
| |
| await new Promise(r => userImg.onload = r);
| |
|
| |
| const refImg = document.getElementById("refImg");
| |
|
| |
| const embUser = mgModel.predict(mgImageToTensor(userImg));
| |
| const embRef = mgModel.predict(mgImageToTensor(refImg));
| |
|
| |
| const sim = await mgCosineSimilarity(embUser, embRef);
| |
| const pct = (sim * 100).toFixed(1);
| |
|
| |
| document.getElementById("margielaResult").innerHTML =
| |
| (sim >= MG_THRESHOLD)
| |
| ? `🔥 Din fit är Margiela-liknande! Likhet: ${pct}%`
| |
| : `😐 Inte särskilt Margiela… Likhet: ${pct}%`;
| |
|
| |
| embUser.dispose();
| |
| embRef.dispose();
| |
| }
| |
| </script>
| |