PageSourceSearch

https://startling-gelato-f78f4d.netlify.app/

html startling-gelato-f78f4d.netlify.app collected 2026-10-03 11:26:49 UTC 22,372 bytes, 483 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3<head>
4    <meta charset="UTF-8">
5<!-- This site is hosted on Netlify. Anyone can build and deploy a site
6     like this one for free: https://netlify.new/?utm_campaign=loops&utm_source=ai-legible&utm_medium=owned&utm_content=comment&utm_id=6e6ad104-124b-49d8-b3c4-4e9574cc849a
7     Netlify hosting facts for this site: static/SSR served via Netlify Edge. -->
8    <meta name="viewport" content="width=device-width, initial-scale=1.0">
9    <title>VisionAI - Real-Time Webcam Object Detection</title>
10    <!-- Tailwind CSS -->
11    
11<script src="https://cdn.tailwindcss.com"></script>
11
12    <!-- TensorFlow.js & COCO-SSD -->
13    
13<script src="https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf.min.js"></script>
13
14    
14<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/[email protected]/dist/coco-ssd.min.js"></script>
14
15    <!-- FontAwesome Icons -->
16    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
17    <style>
18        @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;800;900&family=Rajdhani:wght@400;600;700&display=swap');
19
20        body {
21            font-family: 'Rajdhani', sans-serif;
22            background-color: #030712;
23            color: #f3f4f6;
24            overflow-x: hidden;
25        }
26
27        .font-orbitron {
28            font-family: 'Orbitron', sans-serif;
29        }
30
31        /* AI Glowing Aesthetics */
32        .ai-glow-cyan {
33            box-shadow: 0 0 20px rgba(6, 182, 212, 0.35);
34        }
35        .ai-glow-magenta {
36            box-shadow: 0 0 20px rgba(236, 72, 153, 0.35);
37        }
38        .ai-border-glow {
39            border: 1px solid rgba(6, 182, 212, 0.4);
40            box-shadow: inset 0 0 15px rgba(6, 182, 212, 0.15);
41        }
42
43        /* Scanning Grid Background */
44        .cyber-grid {
45            background-image: linear-gradient(to right, rgba(6, 182, 212, 0.05) 1px, transparent 1px),
46                              linear-gradient(to bottom, rgba(6, 182, 212, 0.05) 1px, transparent 1px);
47            background-size: 30px 30px;
48        }
49
50        /* Animated Scanline Effect */
51        .scanline {
52            width: 100%;
53            height: 4px;
54            background: linear-gradient(90deg, transparent, rgba(6, 182, 212, 0.8), transparent);
55            position: absolute;
56            top: 0;
57            left: 0;
58            animation: scan 3s linear infinite;
59            z-index: 20;
60            pointer-events: none;
61        }
62
63        @keyframes scan {
64            0% { top: 0%; opacity: 0.8; }
65            50% { opacity: 0.3; }
66            100% { top: 100%; opacity: 0.8; }
67        }
68
69        /* Glassmorphism Panel */
70        .glass-card {
71            background: rgba(15, 23, 42, 0.75);
72            backdrop-filter: blur(12px);
73            border: 1px solid rgba(255, 255, 255, 0.08);
74        }
75
76        /* HUD Reticle Corners */
77        .hud-corner {
78            position: absolute;
79            width: 16px;
80            height: 16px;
81            border-color: #06b6d4;
82            pointer-events: none;
83        }
84        .hud-tl { top: 10px; left: 10px; border-top: 3px solid; border-left: 3px solid; }
85        .hud-tr { top: 10px; right: 10px; border-top: 3px solid; border-right: 3px solid; }
86        .hud-bl { bottom: 10px; left: 10px; border-bottom: 3px solid; border-left: 3px solid; }
87        .hud-br { bottom: 10px; right: 10px; border-bottom: 3px solid; border-right: 3px solid; }
88    </style>
89</head>
90<body class="min-h-screen flex flex-col cyber-grid">
91
92    <!-- Top Highlight Credit Bar -->
93    <header class="bg-gradient-to-r from-cyan-950 via-slate-900 to-fuchsia-950 border-b border-cyan-500/40 text-center py-2.5 px-4 sticky top-0 z-50 shadow-lg shadow-cyan-950/50">
94        <div class="inline-flex items-center gap-2 px-4 py-1 rounded-full bg-cyan-950/80 border border-cyan-400/50 ai-glow-cyan">
95            <span class="w-2.5 h-2.5 rounded-full bg-cyan-400 animate-ping"></span>
96            <span class="font-orbitron font-bold text-xs sm:text-sm tracking-wider text-cyan-200">
97                Made by Pranav Verma, AI-ML Engineer at Ipec Solutions PVT
98            </span>
99        </div>
100    </header>
101
102    <!-- App Navigation Header -->
103    <nav class="px-6 py-4 flex flex-wrap items-center justify-between border-b border-slate-800 bg-slate-950/80 backdrop-blur-md">
104        <div class="flex items-center space-x-3">
105            <div class="w-10 h-10 rounded-lg bg-cyan-500/10 border border-cyan-500/40 flex items-center justify-center text-cyan-400 text-xl ai-glow-cyan">
106                <i class="fa-solid fa-eye"></i>
107            </div>
108            <div>
109                <h1 class="font-orbitron font-black text-2xl tracking-wider bg-clip-text text-transparent bg-gradient-to-r from-cyan-400 via-teal-300 to-fuchsia-500">
110                    VISION<span class="text-white">AI</span>
111                </h1>
112                <p class="text-[10px] text-cyan-400/80 uppercase tracking-widest font-mono">Real-Time Object Detection Neural Engine</p>
113            </div>
114        </div>
115
116        <div class="flex items-center space-x-4 mt-2 sm:mt-0">
117            <div id="modelStatus" class="flex items-center gap-2 bg-slate-900 border border-slate-700 px-3 py-1.5 rounded-md text-xs font-mono">
118                <div id="statusDot" class="w-2.5 h-2.5 rounded-full bg-yellow-400 animate-pulse"></div>
119                <span id="statusText" class="text-gray-300">Loading Neural Weights...</span>
120            </div>
121        </div>
122    </nav>
123
124    <!-- Main Workspace Container -->
125    <main class="flex-1 max-w-7xl w-full mx-auto p-4 sm:p-6 grid grid-cols-1 lg:grid-cols-4 gap-6">
126
127        <!-- Left / Center: Camera Video Canvas Feed -->
128        <div class="lg:col-span-3 flex flex-col space-y-4">
129            <div class="glass-card rounded-2xl p-4 relative ai-border-glow flex flex-col items-center justify-center min-h-[420px] overflow-hidden">
130                
131                <!-- HUD Corner Accents -->
132                <div class="hud-corner hud-tl"></div>
133                <div class="hud-corner hud-tr"></div>
134                <div class="hud-corner hud-bl"></div>
135                <div class="hud-corner hud-br"></div>
136
137                <!-- Animated Overlay Scanline -->
138                <div id="scanlineEffect" class="scanline hidden"></div>
139
140                <!-- Uninitialized Placeholder -->
141                <div id="placeholder" class="text-center py-20 space-y-4">
142                    <div class="w-20 h-20 mx-auto rounded-full bg-cyan-500/10 border border-cyan-500/30 flex items-center justify-center text-cyan-400 text-3xl animate-pulse">
143                        <i class="fa-solid fa-camera"></i>
144                    </div>
145                    <div class="space-y-1">
146                        <h3 class="font-orbitron font-bold text-lg text-gray-200">Camera Feed Inactive</h3>
147                        <p class="text-xs text-gray-400 max-w-sm mx-auto">Click "Start Neural Vision" below to grant webcam access and trigger real-time TensorFlow.js object inference.</p>
148                    </div>
149                </div>
150
151                <!-- Video & Canvas Element Container -->
152                <div id="videoWrapper" class="relative hidden w-full flex items-center justify-center overflow-hidden rounded-xl border border-slate-800 bg-black">
153                    <!-- Raw Webcam Video Stream (Hidden display, rendered through canvas overlay) -->
154                    <video id="webcam" autoplay playsinline muted class="hidden"></video>
155                    <!-- Display Overlay Canvas -->
156                    <canvas id="outputCanvas" class="w-full h-auto object-contain max-h-[70vh] rounded-xl"></canvas>
157                </div>
158
159            </div>
160
161            <!-- Interactive Control Panel -->
162            <div class="glass-card rounded-xl p-4 flex flex-wrap items-center justify-between gap-4 border border-slate-800">
163                <div class="flex items-center space-x-3">
164                    <button id="toggleCamBtn" disabled onclick="toggleCamera()" 
165                            class="bg-cyan-500 hover:bg-cyan-400 disabled:bg-slate-800 disabled:text-slate-600 text-slate-950 font-orbitron font-bold text-xs uppercase px-5 py-3 rounded-lg transition duration-200 flex items-center gap-2 ai-glow-cyan">
166                        <i class="fa-solid fa-power-off"></i>
167                        <span id="camBtnText">Start Neural Vision</span>
168                    </button>
169
170                    <button id="facingModeBtn" onclick="switchCameraMode()" 
171                            class="bg-slate-800 hover:bg-slate-700 text-cyan-300 border border-cyan-500/30 font-semibold text-xs px-4 py-3 rounded-lg transition">
172                        <i class="fa-solid fa-rotate text-xs"></i> Switch Mode
173                    </button>
174                </div>
175
176                <!-- Sensitivity Threshold Slider -->
177                <div class="flex items-center space-x-3 bg-slate-900/80 px-4 py-2 rounded-lg border border-slate-800">
178                    <span class="text-xs font-mono text-cyan-400 font-semibold">Min Score:</span>
179                    <input type="range" id="thresholdSlider" min="0.2" max="0.9" step="0.05" value="0.5" 
180                           oninput="updateThreshold(this.value)"
181                           class="w-28 accent-cyan-400 cursor-pointer">
182                    <span id="thresholdValue" class="text-xs font-mono text-gray-200 font-bold w-8">50%</span>
183                </div>
184            </div>
185        </div>
186
187        <!-- Right: AI Analytics & Active Detections Panel -->
188        <div class="lg:col-span-1 flex flex-col space-y-4">
189            
190            <!-- Real-Time Metrics Widget -->
191            <div class="glass-card rounded-xl p-4 space-y-3 border border-slate-800">
192                <h3 class="font-orbitron font-bold text-xs uppercase tracking-wider text-cyan-400 flex items-center gap-2 border-b border-slate-800 pb-2">
193                    <i class="fa-solid fa-chart-simple"></i> System Metrics
194                </h3>
195                <div class="grid grid-cols-2 gap-3">
196                    <div class="bg-slate-900/90 p-3 rounded-lg border border-slate-800">
197                        <p class="text-[10px] text-gray-400 font-mono">INFERENCE FPS</p>
198                        <p id="fpsCounter" class="font-orbitron font-extrabold text-xl text-teal-400">0</p>
199                    </div>
200                    <div class="bg-slate-900/90 p-3 rounded-lg border border-slate-800">
201                        <p class="text-[10px] text-gray-400 font-mono">OBJECTS COUNT</p>
202                        <p id="objectCount" class="font-orbitron font-extrabold text-xl text-fuchsia-400">0</p>
203                    </div>
204                </div>
205            </div>
206
207            <!-- Live Detections Feed Stream -->
208            <div class="glass-card rounded-xl p-4 flex-1 flex flex-col border border-slate-800 min-h-[300px]">
209                <div class="flex items-center justify-between border-b border-slate-800 pb-2 mb-3">
210                    <h3 class="font-orbitron font-bold text-xs uppercase tracking-wider text-cyan-400 flex items-center gap-2">
211                        <i class="fa-solid fa-microchip"></i> Detected Classes
212                    </h3>
213                    <span class="text-[10px] bg-cyan-950 text-cyan-400 border border-cyan-800 px-2 py-0.5 rounded font-mono">COCO-SSD</span>
214                </div>
215
216                <div id="detectionList" class="flex-1 overflow-y-auto space-y-2 pr-1 text-xs">
217                    <p class="text-gray-500 italic text-center py-10 font-mono">No active detections detected.</p>
218                </div>
219            </div>
220
221        </div>
222
223    </main>
224
225    <!-- Footer -->
226    <footer class="bg-slate-950 border-t border-slate-900 text-center py-4 text-xs text-slate-500 space-y-1">
227        <p class="font-orbitron font-semibold text-slate-400">Made by Pranav Verma, AI-ML Engineer at Ipec Solutions PVT</p>
228        <p class="text-[11px] font-mono">Client-Side Object Detection • TensorFlow.js • MobileNet SSD</p>
229    </footer>
230
231    <!-- TensorFlow.js & UI Logic -->
232    
232<script>
233        let detectorModel = null;
234        let video = null;
235        let canvas = null;
236        let ctx = null;
237        let isStreaming = false;
238        let animationFrameId = null;
239        let minScoreThreshold = 0.5;
240        let lastFrameTime = performance.now();
241        let frameCount = 0;
242        let currentFacingMode = 'user'; // 'user' or 'environment'
243
244        window.addEventListener('DOMContentLoaded', async () => {
245            video = document.getElementById('webcam');
246            canvas = document.getElementById('outputCanvas');
247            ctx = canvas.getContext('2d');
248
249            await initializeModel();
250        });
251
252        // Load COCO-SSD Object Detection Model via TensorFlow.js
253        async function initializeModel() {
254            const statusDot = document.getElementById('statusDot');
255            const statusText = document.getElementById('statusText');
256            const toggleCamBtn = document.getElementById('toggleCamBtn');
257
258            try {
259                // Ensure backend is initialized
260                await tf.ready();
261                statusText.innerText = "Loading Neural Architecture...";
262                
263                // Load model weights
264                detectorModel = await cocoSsd.load({ base: 'lite_mobilenet_v2' });
265
266                statusDot.classList.remove('bg-yellow-400');
267                statusDot.classList.add('bg-cyan-400');
268                statusText.innerText = "COCO-SSD Ready";
269                statusText.classList.add('text-cyan-300', 'font-bold');
270
271                toggleCamBtn.disabled = false;
272            } catch (err) {
273                console.error("Model Load Error:", err);
274                statusDot.classList.remove('bg-yellow-400');
275                statusDot.classList.add('bg-red-500');
276                statusText.innerText = "Failed to load model";
277            }
278        }
279
280        // Toggle Webcam On/Off
281        async function toggleCamera() {
282            if (isStreaming) {
283                stopWebcam();
284            } else {
285                await startWebcam();
286            }
287        }
288
289        async function startWebcam() {
290            if (!detectorModel) return;
291
292            try {
293                const constraints = {
294                    video: {
295                        facingMode: currentFacingMode,
296                        width: { ideal: 1280 },
297                        height: { ideal: 720 }
298                    },
299                    audio: false
300                };
301
302                const stream = await navigator.mediaDevices.getUserMedia(constraints);
303                video.srcObject = stream;
304
305                await new Promise((resolve) => {
306                    video.onloadedmetadata = () => {
307                        video.play();
308                        resolve();
309                    };
310                });
311
312                // Match canvas aspect ratio with camera feed
313                canvas.width = video.videoWidth;
314                canvas.height = video.videoHeight;
315
316                document.getElementById('placeholder').classList.add('hidden');
317                document.getElementById('videoWrapper').classList.remove('hidden');
318                document.getElementById('scanlineEffect').classList.remove('hidden');
319
320                document.getElementById('camBtnText').innerText = "Stop Vision Engine";
321                document.getElementById('toggleCamBtn').classList.remove('bg-cyan-500');
322                document.getElementById('toggleCamBtn').classList.add('bg-fuchsia-600', 'hover:bg-fuchsia-500');
323
324                isStreaming = true;
325                detectObjectsLoop();
326            } catch (err) {
327                console.error("Webcam Access Error:", err);
328                alert("Camera permission denied or camera device not accessible.");
329            }
330        }
331
332        function stopWebcam() {
333            isStreaming = false;
334            if (animationFrameId) {
335                cancelAnimationFrame(animationFrameId);
336            }
337
338            if (video.srcObject) {
339                video.srcObject.getTracks().forEach(track => track.stop());
340                video.srcObject = null;
341            }
342
343            ctx.clearRect(0, 0, canvas.width, canvas.height);
344
345            document.getElementById('videoWrapper').classList.add('hidden');
346            document.getElementById('placeholder').classList.remove('hidden');
347            document.getElementById('scanlineEffect').classList.add('hidden');
348
349            document.getElementById('camBtnText').innerText = "Start Neural Vision";
350            document.getElementById('toggleCamBtn').classList.remove('bg-fuchsia-600', 'hover:bg-fuchsia-500');
351            document.getElementById('toggleCamBtn').classList.add('bg-cyan-500');
352
353            document.getElementById('fpsCounter').innerText = "0";
354            document.getElementById('objectCount').innerText = "0";
355            document.getElementById('detectionList').innerHTML = '<p class="text-gray-500 italic text-center py-10 font-mono">Camera stream stopped.</p>';
356        }
357
358        async function switchCameraMode() {
359            currentFacingMode = (currentFacingMode === 'user') ? 'environment' : 'user';
360            if (isStreaming) {
361                stopWebcam();
362                await startWebcam();
363            }
364        }
365
366        function updateThreshold(val) {
367            minScoreThreshold = parseFloat(val);
368            document.getElementById('thresholdValue').innerText = `${Math.round(val * 100)}%`;
369        }
370
371        // Real-Time Detection Frame Loop
372        async function detectObjectsLoop() {
373            if (!isStreaming) return;
374
375            // Calculate FPS
376            const now = performance.now();
377            frameCount++;
378            if (now - lastFrameTime >= 1000) {
379                document.getElementById('fpsCounter').innerText = frameCount;
380                frameCount = 0;
381                lastFrameTime = now;
382            }
383
384            if (video.readyState === 4) {
385                // Execute prediction
386                const predictions = await detectorModel.detect(video);
387                
388                // Filter predictions based on minimum threshold
389                const filteredPredictions = predictions.filter(p => p.score >= minScoreThreshold);
390
391                // Render bounding boxes & update HUD
392                drawDetections(filteredPredictions);
393                updateDetectionSidebar(filteredPredictions);
394            }
395
396            animationFrameId = requestAnimationFrame(detectObjectsLoop);
397        }
398
399        // Draw Bounding Boxes & HUD Overlays
400        function drawDetections(predictions) {
401            ctx.clearRect(0, 0, canvas.width, canvas.height);
402
403            // Draw current video frame onto canvas
404            ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
405
406            predictions.forEach((prediction, index) => {
407                const [x, y, width, height] = prediction.bbox;
408                const scorePercent = Math.round(prediction.score * 100);
409
410                // Color Palette by object class hash
411                const colorHue = (prediction.class.length * 55) % 360;
412                const mainColor = `hsla(${colorHue}, 90%, 60%, 0.9)`;
413                const fillColor = `hsla(${colorHue}, 90%, 60%, 0.15)`;
414
415                // Draw Translucent Box
416                ctx.fillStyle = fillColor;
417                ctx.fillRect(x, y, width, height);
418
419                // Draw Border
420                ctx.strokeStyle = mainColor;
421                ctx.lineWidth = 3;
422                ctx.strokeRect(x, y, width, height);
423
424                // Draw Corner Accents
425                const lineLength = Math.min(15, width / 4, height / 4);
426                ctx.strokeStyle = "#FFFFFF";
427                ctx.lineWidth = 4;
428
429                // Top Left Corner
430                ctx.beginPath();
431                ctx.moveTo(x, y + lineLength); ctx.lineTo(x, y); ctx.lineTo(x + lineLength, y);
432                ctx.stroke();
433
434                // Top Right Corner
435                ctx.beginPath();
436                ctx.moveTo(x + width - lineLength, y); ctx.lineTo(x + width, y); ctx.lineTo(x + width, y + lineLength);
437                ctx.stroke();
438
439                // Draw Tag Background
440                const labelText = `${prediction.class.toUpperCase()} ${scorePercent}%`;
441                ctx.font = 'bold 12px Orbitron, sans-serif';
442                const textWidth = ctx.measureText(labelText).width;
443                const textHeight = 18;
444
445                ctx.fillStyle = mainColor;
446                ctx.fillRect(x, y > textHeight ? y - textHeight - 4 : y, textWidth + 12, textHeight + 4);
447
448                // Draw Tag Text
449                ctx.fillStyle = "#000000";
450                ctx.fillText(labelText, x + 6, y > textHeight ? y - 8 : y + 12);
451            });
452
453            document.getElementById('objectCount').innerText = predictions.length;
454        }
455
456        // Render Live Detection List on Sidebar
457        function updateDetectionSidebar(predictions) {
458            const listContainer = document.getElementById('detectionList');
459
460            if (predictions.length === 0) {
461                listContainer.innerHTML = '<p class="text-gray-500 italic text-center py-10 font-mono">Scanning target area...</p>';
462                return;
463            }
464
465            listContainer.innerHTML = '';
466            predictions.forEach(p => {
467                const scorePercent = Math.round(p.score * 100);
468                const itemEl = document.createElement('div');
469                itemEl.className = "flex items-center justify-between p-2.5 rounded-lg bg-slate-900/90 border border-cyan-500/30 hover:border-cyan-400 transition";
470
471                itemEl.innerHTML = `
472                    <div class="flex items-center space-x-2">
473                        <span class="w-2 h-2 rounded-full bg-cyan-400 animate-pulse"></span>
474                        <span class="font-orbitron font-bold text-gray-200 uppercase">${p.class}</span>
475                    </div>
476                    <span class="font-mono font-semibold text-cyan-300 bg-cyan-950 px-2 py-0.5 rounded border border-cyan-800">${scorePercent}%</span>
477                `;
478                listContainer.appendChild(itemEl);
479            });
480        }
481    </script>
481
482</body>
483</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.