Prathamesh1420 commited on
Commit
de71102
·
verified ·
1 Parent(s): 688ca2d

create a live object detection application from my camera - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +409 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Live Camera Object Detection
3
- emoji: 👀
4
- colorFrom: purple
5
- colorTo: pink
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: live-camera-object-detection
3
+ emoji: 🐳
4
+ colorFrom: red
5
+ colorTo: gray
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,409 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Live Object Detection</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/coco-ssd"></script>
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
+ <style>
12
+ .detection-box {
13
+ position: absolute;
14
+ border: 3px solid;
15
+ border-radius: 4px;
16
+ font-weight: bold;
17
+ text-shadow: 1px 1px 1px rgba(0,0,0,0.8);
18
+ padding: 2px 4px;
19
+ white-space: nowrap;
20
+ }
21
+ .video-container {
22
+ position: relative;
23
+ overflow: hidden;
24
+ border-radius: 12px;
25
+ box-shadow: 0 10px 25px rgba(0,0,0,0.2);
26
+ }
27
+ .detection-canvas {
28
+ position: absolute;
29
+ top: 0;
30
+ left: 0;
31
+ pointer-events: none;
32
+ }
33
+ .stats-card {
34
+ backdrop-filter: blur(10px);
35
+ background: rgba(255, 255, 255, 0.1);
36
+ }
37
+ .detection-grid {
38
+ display: grid;
39
+ grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
40
+ gap: 8px;
41
+ }
42
+ .detection-item {
43
+ transition: all 0.3s ease;
44
+ }
45
+ .detection-item:hover {
46
+ transform: translateY(-3px);
47
+ }
48
+ .pulse {
49
+ animation: pulse 2s infinite;
50
+ }
51
+ @keyframes pulse {
52
+ 0% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7); }
53
+ 70% { box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); }
54
+ 100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
55
+ }
56
+ </style>
57
+ </head>
58
+ <body class="bg-gradient-to-br from-gray-900 to-gray-800 min-h-screen text-white">
59
+ <div class="container mx-auto px-4 py-8">
60
+ <header class="text-center mb-12">
61
+ <h1 class="text-4xl md:text-5xl font-bold mb-4 bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-purple-500">
62
+ Live Object Detection
63
+ </h1>
64
+ <p class="text-gray-300 max-w-2xl mx-auto">
65
+ Real-time object detection using your device's camera powered by TensorFlow.js and COCO-SSD model.
66
+ Grant camera access to start detecting objects in your environment.
67
+ </p>
68
+ </header>
69
+
70
+ <main>
71
+ <div class="flex flex-col lg:flex-row gap-8">
72
+ <!-- Camera Feed Section -->
73
+ <div class="lg:w-2/3">
74
+ <div class="video-container relative">
75
+ <video id="video" autoplay playsinline class="w-full h-auto rounded-lg bg-gray-800 aspect-video"></video>
76
+ <canvas id="canvas" class="detection-canvas w-full h-auto rounded-lg"></canvas>
77
+
78
+ <!-- Camera Access Prompt -->
79
+ <div id="cameraPrompt" class="absolute inset-0 flex flex-col items-center justify-center bg-gray-900 bg-opacity-80 rounded-lg">
80
+ <div class="text-center p-8">
81
+ <i class="fas fa-camera text-6xl text-blue-400 mb-4"></i>
82
+ <h2 class="text-2xl font-bold mb-2">Camera Access Required</h2>
83
+ <p class="text-gray-300 mb-6">Please allow camera access to enable live object detection</p>
84
+ <button id="startBtn" class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-3 px-8 rounded-full text-lg transition-all transform hover:scale-105 pulse">
85
+ Start Detection
86
+ </button>
87
+ </div>
88
+ </div>
89
+ </div>
90
+
91
+ <!-- Controls -->
92
+ <div class="mt-6 flex flex-wrap gap-4 justify-center">
93
+ <button id="toggleDetectionBtn" class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-6 rounded-lg flex items-center disabled:opacity-50">
94
+ <i class="fas fa-play mr-2"></i> Start Detection
95
+ </button>
96
+ <button id="toggleCameraBtn" class="bg-gray-700 hover:bg-gray-600 text-white font-medium py-2 px-6 rounded-lg flex items-center">
97
+ <i class="fas fa-sync mr-2"></i> Switch Camera
98
+ </button>
99
+ <button id="captureBtn" class="bg-purple-600 hover:bg-purple-700 text-white font-medium py-2 px-6 rounded-lg flex items-center">
100
+ <i class="fas fa-camera mr-2"></i> Capture Frame
101
+ </button>
102
+ </div>
103
+ </div>
104
+
105
+ <!-- Detection Results -->
106
+ <div class="lg:w-1/3">
107
+ <div class="bg-gray-800 bg-opacity-50 rounded-xl p-6 h-full">
108
+ <h2 class="text-2xl font-bold mb-4 flex items-center">
109
+ <i class="fas fa-list mr-3 text-blue-400"></i> Detection Results
110
+ </h2>
111
+
112
+ <div class="stats-card rounded-lg p-4 mb-6">
113
+ <div class="grid grid-cols-3 gap-4 text-center">
114
+ <div>
115
+ <div class="text-sm text-gray-300">Objects</div>
116
+ <div id="objectCount" class="text-2xl font-bold">0</div>
117
+ </div>
118
+ <div>
119
+ <div class="text-sm text-gray-300">FPS</div>
120
+ <div id="fpsCounter" class="text-2xl font-bold">0</div>
121
+ </div>
122
+ <div>
123
+ <div class="text-sm text-gray-300">Confidence</div>
124
+ <div id="avgConfidence" class="text-2xl font-bold">0%</div>
125
+ </div>
126
+ </div>
127
+ </div>
128
+
129
+ <h3 class="text-lg font-semibold mb-3 flex items-center">
130
+ <i class="fas fa-boxes mr-2 text-blue-400"></i> Detected Objects
131
+ </h3>
132
+
133
+ <div id="detectionList" class="detection-grid">
134
+ <!-- Detected items will appear here -->
135
+ <div class="text-center py-4 text-gray-400">
136
+ No objects detected yet
137
+ </div>
138
+ </div>
139
+ </div>
140
+ </div>
141
+ </div>
142
+ </main>
143
+
144
+ <footer class="mt-16 text-center text-gray-400">
145
+ <p>Powered by TensorFlow.js and COCO-SSD model | Built with Tailwind CSS</p>
146
+ <p class="mt-2">Note: Processing happens entirely in your browser - no data is sent to any server</p>
147
+ </footer>
148
+ </div>
149
+
150
+ <script>
151
+ // DOM Elements
152
+ const video = document.getElementById('video');
153
+ const canvas = document.getElementById('canvas');
154
+ const ctx = canvas.getContext('2d');
155
+ const cameraPrompt = document.getElementById('cameraPrompt');
156
+ const startBtn = document.getElementById('startBtn');
157
+ const toggleDetectionBtn = document.getElementById('toggleDetectionBtn');
158
+ const toggleCameraBtn = document.getElementById('toggleCameraBtn');
159
+ const captureBtn = document.getElementById('captureBtn');
160
+ const objectCount = document.getElementById('objectCount');
161
+ const fpsCounter = document.getElementById('fpsCounter');
162
+ const avgConfidence = document.getElementById('avgConfidence');
163
+ const detectionList = document.getElementById('detectionList');
164
+
165
+ // App State
166
+ let model = null;
167
+ let detectionActive = false;
168
+ let stream = null;
169
+ let currentFacingMode = 'environment'; // 'user' for front, 'environment' for back
170
+ let lastTimestamp = 0;
171
+ let frameCount = 0;
172
+ let fps = 0;
173
+ let detectedObjects = [];
174
+
175
+ // Color palette for detection boxes
176
+ const colors = [
177
+ '#FF5252', '#FF4081', '#E040FB', '#7C4DFF',
178
+ '#536DFE', '#448AFF', '#40C4FF', '#18FFFF',
179
+ '#64FFDA', '#69F0AE', '#B2FF59', '#EEFF41'
180
+ ];
181
+
182
+ // Initialize the app
183
+ async function init() {
184
+ try {
185
+ // Load the model
186
+ model = await cocoSsd.load();
187
+ console.log('Model loaded successfully');
188
+
189
+ // Set up event listeners
190
+ startBtn.addEventListener('click', startCamera);
191
+ toggleDetectionBtn.addEventListener('click', toggleDetection);
192
+ toggleCameraBtn.addEventListener('click', switchCamera);
193
+ captureBtn.addEventListener('click', captureFrame);
194
+
195
+ // Disable buttons until camera is started
196
+ toggleDetectionBtn.disabled = true;
197
+ toggleCameraBtn.disabled = true;
198
+ captureBtn.disabled = true;
199
+ } catch (error) {
200
+ console.error('Error loading model:', error);
201
+ alert('Failed to load the object detection model. Please try again later.');
202
+ }
203
+ }
204
+
205
+ // Start the camera
206
+ async function startCamera() {
207
+ try {
208
+ stream = await navigator.mediaDevices.getUserMedia({
209
+ video: { facingMode: currentFacingMode }
210
+ });
211
+
212
+ video.srcObject = stream;
213
+ cameraPrompt.classList.add('hidden');
214
+ toggleDetectionBtn.disabled = false;
215
+ toggleCameraBtn.disabled = false;
216
+ captureBtn.disabled = false;
217
+
218
+ // Wait for video to load metadata
219
+ video.addEventListener('loadedmetadata', () => {
220
+ // Set canvas dimensions to match video
221
+ canvas.width = video.videoWidth;
222
+ canvas.height = video.videoHeight;
223
+
224
+ // Start detection if button was clicked to start
225
+ if (detectionActive) {
226
+ detectFrame();
227
+ }
228
+ });
229
+ } catch (error) {
230
+ console.error('Error accessing camera:', error);
231
+ cameraPrompt.querySelector('p').textContent = 'Camera access denied. Please allow camera permissions and refresh the page.';
232
+ }
233
+ }
234
+
235
+ // Switch between front and back camera
236
+ async function switchCamera() {
237
+ if (!stream) return;
238
+
239
+ // Stop current stream
240
+ stream.getTracks().forEach(track => track.stop());
241
+
242
+ // Toggle facing mode
243
+ currentFacingMode = currentFacingMode === 'environment' ? 'user' : 'environment';
244
+
245
+ // Restart camera
246
+ await startCamera();
247
+ }
248
+
249
+ // Toggle detection on/off
250
+ function toggleDetection() {
251
+ detectionActive = !detectionActive;
252
+
253
+ if (detectionActive) {
254
+ toggleDetectionBtn.innerHTML = '<i class="fas fa-pause mr-2"></i> Pause Detection';
255
+ detectFrame();
256
+ } else {
257
+ toggleDetectionBtn.innerHTML = '<i class="fas fa-play mr-2"></i> Resume Detection';
258
+ }
259
+ }
260
+
261
+ // Capture current frame
262
+ function captureFrame() {
263
+ if (!detectionActive) return;
264
+
265
+ // Create a temporary canvas to draw the current frame
266
+ const tempCanvas = document.createElement('canvas');
267
+ tempCanvas.width = canvas.width;
268
+ tempCanvas.height = canvas.height;
269
+ const tempCtx = tempCanvas.getContext('2d');
270
+
271
+ // Draw video frame
272
+ tempCtx.drawImage(video, 0, 0, tempCanvas.width, tempCanvas.height);
273
+
274
+ // Draw detections
275
+ tempCtx.drawImage(canvas, 0, 0);
276
+
277
+ // Create download link
278
+ const link = document.createElement('a');
279
+ link.download = 'object-detection-' + new Date().toISOString().replace(/:/g, '-') + '.png';
280
+ link.href = tempCanvas.toDataURL('image/png');
281
+ link.click();
282
+
283
+ // Show notification
284
+ showNotification('Frame captured successfully!');
285
+ }
286
+
287
+ // Show notification
288
+ function showNotification(message) {
289
+ const notification = document.createElement('div');
290
+ notification.className = 'fixed bottom-4 right-4 bg-green-600 text-white px-4 py-2 rounded-lg shadow-lg z-50 animate-fadeIn';
291
+ notification.textContent = message;
292
+ document.body.appendChild(notification);
293
+
294
+ setTimeout(() => {
295
+ notification.classList.add('animate-fadeOut');
296
+ setTimeout(() => {
297
+ document.body.removeChild(notification);
298
+ }, 500);
299
+ }, 3000);
300
+ }
301
+
302
+ // Main detection function
303
+ async function detectFrame() {
304
+ if (!detectionActive || !model) return;
305
+
306
+ // Start timing for FPS calculation
307
+ const startTime = performance.now();
308
+
309
+ try {
310
+ // Detect objects in the frame
311
+ const predictions = await model.detect(video);
312
+
313
+ // Clear previous detections
314
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
315
+
316
+ // Process predictions
317
+ detectedObjects = [];
318
+ let totalConfidence = 0;
319
+
320
+ predictions.forEach((prediction, index) => {
321
+ // Extract prediction data
322
+ const [x, y, width, height] = prediction.bbox;
323
+ const label = prediction.class;
324
+ const score = Math.round(prediction.score * 100);
325
+
326
+ // Add to detected objects
327
+ detectedObjects.push({
328
+ label,
329
+ score,
330
+ color: colors[index % colors.length]
331
+ });
332
+
333
+ // Draw bounding box
334
+ ctx.strokeStyle = colors[index % colors.length];
335
+ ctx.lineWidth = 3;
336
+ ctx.strokeRect(x, y, width, height);
337
+
338
+ // Draw label background
339
+ ctx.fillStyle = colors[index % colors.length];
340
+ const textWidth = ctx.measureText(`${label} ${score}%`).width;
341
+ ctx.fillRect(x, y, textWidth + 10, 25);
342
+
343
+ // Draw label text
344
+ ctx.fillStyle = 'white';
345
+ ctx.font = 'bold 16px Arial';
346
+ ctx.fillText(`${label} ${score}%`, x + 5, y + 18);
347
+
348
+ // Add to total confidence for average
349
+ totalConfidence += score;
350
+ });
351
+
352
+ // Update stats
353
+ objectCount.textContent = predictions.length;
354
+ const avgConf = predictions.length > 0 ? Math.round(totalConfidence / predictions.length) : 0;
355
+ avgConfidence.textContent = `${avgConf}%`;
356
+
357
+ // Update detection list
358
+ updateDetectionList();
359
+
360
+ // Calculate FPS
361
+ frameCount++;
362
+ const elapsed = startTime - lastTimestamp;
363
+
364
+ if (elapsed >= 1000) {
365
+ fps = Math.round((frameCount * 1000) / elapsed);
366
+ fpsCounter.textContent = fps;
367
+ frameCount = 0;
368
+ lastTimestamp = startTime;
369
+ }
370
+ } catch (error) {
371
+ console.error('Detection error:', error);
372
+ }
373
+
374
+ // Continue detection loop
375
+ if (detectionActive) {
376
+ requestAnimationFrame(detectFrame);
377
+ }
378
+ }
379
+
380
+ // Update the detection list UI
381
+ function updateDetectionList() {
382
+ if (detectedObjects.length === 0) {
383
+ detectionList.innerHTML = '<div class="text-center py-4 text-gray-400 col-span-3">No objects detected</div>';
384
+ return;
385
+ }
386
+
387
+ // Clear previous list
388
+ detectionList.innerHTML = '';
389
+
390
+ // Create new items
391
+ detectedObjects.forEach(obj => {
392
+ const item = document.createElement('div');
393
+ item.className = 'detection-item bg-gray-700 rounded-lg p-3 flex flex-col items-center';
394
+ item.innerHTML = `
395
+ <div class="w-12 h-12 rounded-full mb-2 flex items-center justify-center" style="background-color: ${obj.color}">
396
+ <i class="fas fa-box text-white text-xl"></i>
397
+ </div>
398
+ <div class="font-semibold">${obj.label}</div>
399
+ <div class="text-sm text-gray-300">${obj.score}%</div>
400
+ `;
401
+ detectionList.appendChild(item);
402
+ });
403
+ }
404
+
405
+ // Initialize the app when the page loads
406
+ window.addEventListener('DOMContentLoaded', init);
407
+ </script>
408
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Prathamesh1420/live-camera-object-detection" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
409
+ </html>