CV_v1 / index.html
Dp1412's picture
Upload 3 files
e659e9f verified
Raw History Blame Contribute Delete
8.96 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>YOLO Vision — macOS WebGPU</title>
<link rel="stylesheet" href="style.css" />
<!-- Load ONNX Runtime WebGPU Bundle directly -->
<script src="https://cdn.jsdelivr.net/npm/onnxruntime-web@1.20.1/dist/ort.webgpu.min.js"></script>
</head>
<body>
<div class="ambient-glow"></div>
<!-- macOS Window Container -->
<main class="window-container">
<!-- Window Titlebar -->
<header class="window-titlebar">
<div class="traffic-lights">
<span class="traffic-dot close"></span>
<span class="traffic-dot minimize"></span>
<span class="traffic-dot maximize"></span>
</div>
<div class="titlebar-center">
<span>YOLO Vision</span>
<span>•</span>
<strong>YOLO11 & YOLO26 WebGPU</strong>
</div>
<div>
<div id="engine-badge" class="badge-engine">
<span id="badge-dot" class="badge-dot loading"></span>
<span id="badge-text">WebGPU Init...</span>
</div>
</div>
</header>
<!-- Window Body -->
<div class="window-content">
<!-- Left Sidebar Controls -->
<aside class="sidebar">
<!-- Model Selection -->
<div class="control-card">
<div class="card-heading">Neural Engine</div>
<div class="select-wrapper">
<label class="select-label" for="model-preset">Model Architecture</label>
<select id="model-preset" class="macos-select">
<optgroup label="YOLO26 (Next-Gen NMS-Free)">
<option value="yolo26n" selected>YOLO26 Nano (9.5 MB) • Real-Time</option>
<option value="yolo26s">YOLO26 Small (36.5 MB) • Accurate</option>
<option value="yolo26m">YOLO26 Medium (78 MB) • High Precision</option>
</optgroup>
<optgroup label="YOLO11 (Ultra-Fast Anchor-Free)">
<option value="yolo11n">YOLO11 Nano (10.3 MB) • Lightweight</option>
<option value="yolo11s">YOLO11 Small (36.3 MB) • Balanced</option>
<option value="yolo11m">YOLO11 Medium (77 MB) • Enterprise</option>
</optgroup>
</select>
</div>
<div class="select-wrapper">
<label class="select-label" for="device-preset">Hardware Acceleration</label>
<select id="device-preset" class="macos-select">
<option value="webgpu" selected>WebGPU (Apple Silicon / Discrete GPU)</option>
<option value="wasm">WASM SIMD (CPU Fallback)</option>
</select>
</div>
<!-- Sleek Apple-style Loader -->
<div id="loader-box" class="loader-box">
<div class="loader-header">
<span id="loader-status">Preloading weights...</span>
<span id="loader-percent">0%</span>
</div>
<div class="progress-track">
<div id="loader-bar" class="progress-fill"></div>
</div>
</div>
</div>
<!-- Detection Parameters -->
<div class="control-card">
<div class="card-heading">Inference Tuning</div>
<div class="slider-container">
<div class="slider-top">
<span>Confidence Threshold</span>
<span id="conf-val" class="val">0.35</span>
</div>
<input type="range" id="conf-slider" class="macos-slider" min="0.10" max="0.95" step="0.05" value="0.35" />
</div>
<label class="checkbox-row" for="person-filter">
<input type="checkbox" id="person-filter" />
<span>Person only filter</span>
</label>
</div>
<!-- Metric HUD -->
<div class="control-card">
<div class="card-heading">Telemetry</div>
<div class="metrics-grid">
<div class="metric-tile">
<div class="metric-name">Latency</div>
<div class="metric-num"><span id="metric-latency">--</span><span style="font-size:12px;color:var(--text-secondary)"> ms</span></div>
</div>
<div class="metric-tile">
<div class="metric-name">Frame Rate</div>
<div class="metric-num"><span id="metric-fps">--</span><span style="font-size:12px;color:var(--text-secondary)"> fps</span></div>
</div>
<div class="metric-tile" style="grid-column: span 2;">
<div class="metric-name">Objects Detected</div>
<div class="metric-num"><span id="metric-count">0</span></div>
</div>
</div>
</div>
</aside>
<!-- Main Canvas Viewport -->
<section class="main-viewport">
<!-- macOS Segmented Control Tabs -->
<div class="segmented-control">
<button id="tab-webcam" class="segment-btn active" onclick="switchTabUI('webcam')">Live Camera</button>
<button id="tab-media" class="segment-btn" onclick="switchTabUI('media')">Image & Video</button>
</div>
<!-- Canvas Container -->
<div class="canvas-wrapper">
<!-- Hidden source elements for frame capture -->
<video id="live-video" autoplay playsinline muted style="display: none;"></video>
<video id="file-video" playsinline muted loop style="display: none;"></video>
<img id="file-image" style="display: none;" />
<canvas id="display-canvas"></canvas>
<!-- Idle State: Camera -->
<div id="cam-idle-overlay" class="viewport-empty-state">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<path d="M23 7l-7 5 7 5V7z"></path>
<rect x="1" y="5" width="15" height="14" rx="3" ry="3"></rect>
</svg>
<p>FaceTime HD Camera feed is inactive</p>
<button id="start-cam-btn" class="apple-btn primary">Enable Camera</button>
</div>
<!-- Idle State: File Upload Drop Zone -->
<div id="media-idle-overlay" class="viewport-empty-state" style="display: none;">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<rect x="3" y="3" width="18" height="18" rx="3" ry="3"></rect>
<circle cx="8.5" cy="8.5" r="1.5"></circle>
<polyline points="21 15 16 10 5 21"></polyline>
</svg>
<p>Drag & drop image or video here</p>
<label for="media-file-input" class="apple-btn primary" style="cursor: pointer;">
Choose File
</label>
<input type="file" id="media-file-input" accept="image/*,video/*" style="display: none;" />
</div>
</div>
<!-- Bottom Toolbar -->
<div class="bottom-toolbar">
<div id="webcam-controls" style="display: flex; gap: 8px;">
<button id="stop-cam-btn" class="apple-btn" disabled>Pause Camera</button>
</div>
<div id="media-controls" style="display: none; gap: 8px;">
<button id="video-play-btn" class="apple-btn">Play Video</button>
<label for="media-file-input-2" class="apple-btn" style="cursor: pointer;">Change Media</label>
<input type="file" id="media-file-input-2" accept="image/*,video/*" style="display: none;" />
</div>
<div style="font-size: 11px; color: var(--text-tertiary); font-family: var(--font-mono);">
Zero server dependencies • 100% Client-Side
</div>
</div>
</section>
</div>
</main>
<div id="toast" class="toast-notice">Notice</div>
<script>
// Immediate UI switcher for tabs ensuring zero delay or module blocking
window.switchTabUI = function(tab) {
const tabWebcam = document.getElementById('tab-webcam');
const tabMedia = document.getElementById('tab-media');
const camIdle = document.getElementById('cam-idle-overlay');
const mediaIdle = document.getElementById('media-idle-overlay');
const webcamControls = document.getElementById('webcam-controls');
const mediaControls = document.getElementById('media-controls');
if (tab === 'webcam') {
tabWebcam.classList.add('active');
tabMedia.classList.remove('active');
camIdle.style.display = 'flex';
mediaIdle.style.display = 'none';
webcamControls.style.display = 'flex';
mediaControls.style.display = 'none';
} else {
tabMedia.classList.add('active');
tabWebcam.classList.remove('active');
camIdle.style.display = 'none';
mediaIdle.style.display = 'flex';
webcamControls.style.display = 'none';
}
};
</script>
<script src="app.js"></script>
</body>
</html>