manmohanai commited on
Commit
25653a8
·
verified ·
1 Parent(s): 3b9c83f

I am not seing my video - Follow Up Deployment

Browse files
Files changed (1) hide show
  1. index.html +164 -87
index.html CHANGED
@@ -11,22 +11,12 @@
11
  position: relative;
12
  width: 100%;
13
  max-width: 640px;
 
14
  margin: 0 auto;
15
  border-radius: 12px;
16
  overflow: hidden;
17
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
18
- }
19
-
20
- .emotion-badge {
21
- position: absolute;
22
- padding: 4px 8px;
23
- border-radius: 20px;
24
- font-size: 12px;
25
- font-weight: bold;
26
- color: white;
27
- background-color: rgba(0, 0, 0, 0.7);
28
- transform: translate(-50%, -50%);
29
- white-space: nowrap;
30
  }
31
 
32
  .loading-spinner {
@@ -54,6 +44,8 @@
54
  </head>
55
  <body class="bg-gray-100 min-h-screen">
56
  <div class="container mx-auto px-4 py-8">
 
 
57
  <div class="text-center mb-8">
58
  <h1 class="text-3xl md:text-4xl font-bold text-indigo-700 mb-2">Emotion Detection Camera</h1>
59
  <p class="text-gray-600 max-w-lg mx-auto">Take a photo and our AI will detect your facial expressions and emotions in real-time.</p>
@@ -66,7 +58,7 @@
66
  </div>
67
 
68
  <div class="camera-container bg-gray-200 aspect-video relative" id="cameraView">
69
- <video id="video" autoplay muted playsinline class="w-full h-full object-cover"></video>
70
  <canvas id="canvas" class="absolute top-0 left-0 w-full h-full hidden"></canvas>
71
  </div>
72
 
@@ -113,9 +105,34 @@
113
  </div>
114
  </div>
115
 
116
- <div class="mt-8 text-center text-gray-500 text-sm">
117
- <p>This app uses face-api.js for emotion detection. All processing happens in your browser.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  </div>
 
 
 
 
 
 
 
119
  </div>
120
 
121
  <script>
@@ -140,6 +157,10 @@
140
  statusElement.classList.remove('hidden');
141
 
142
  try {
 
 
 
 
143
  await Promise.all([
144
  faceapi.nets.tinyFaceDetector.loadFromUri('https://justadudewhohacks.github.io/face-api.js/models'),
145
  faceapi.nets.faceLandmark68Net.loadFromUri('https://justadudewhohacks.github.io/face-api.js/models'),
@@ -178,9 +199,6 @@
178
  video.srcObject = stream;
179
  video.onloadedmetadata = () => {
180
  video.play();
181
- if (!isCaptured) {
182
- detectEmotions();
183
- }
184
  };
185
  } catch (error) {
186
  console.error("Camera error:", error);
@@ -188,73 +206,6 @@
188
  }
189
  }
190
 
191
- // Detect emotions in real-time
192
- async function detectEmotions() {
193
- if (isCaptured) return;
194
-
195
- const detection = await faceapi.detectSingleFace(video, new faceapi.TinyFaceDetectorOptions())
196
- .withFaceLandmarks()
197
- .withFaceExpressions();
198
-
199
- // Clear previous drawings
200
- const canvas = faceapi.createCanvasFromMedia(video);
201
- const context = canvas.getContext('2d');
202
- context.clearRect(0, 0, canvas.width, canvas.height);
203
-
204
- // Resize canvas to match video dimensions
205
- faceapi.matchDimensions(canvas, {
206
- width: video.clientWidth,
207
- height: video.clientHeight
208
- });
209
-
210
- if (detection) {
211
- // Draw face detection box
212
- const resizedDetections = faceapi.resizeResults(detection, {
213
- width: video.clientWidth,
214
- height: video.clientHeight
215
- });
216
-
217
- // Draw face box
218
- const box = resizedDetections.detection.box;
219
- const drawBox = new faceapi.draw.DrawBox(box, {
220
- label: `Confidence: ${Math.round(detection.detection.score * 100)}%`
221
- });
222
- drawBox.draw(canvas);
223
-
224
- // Draw face landmarks
225
- faceapi.draw.drawFaceLandmarks(canvas, resizedDetections);
226
-
227
- // Get dominant emotion
228
- const expressions = detection.expressions;
229
- const primaryEmotion = Object.entries(expressions).reduce((a, b) => a[1] > b[1] ? a : b);
230
-
231
- // Display emotion badges
232
- Object.entries(expressions).forEach(([emotion, value]) => {
233
- if (value > 0.1) { // Only show emotions with > 10% confidence
234
- const landmarkPoint = resizedDetections.landmarks.getNose()[3];
235
- const position = {
236
- x: landmarkPoint.x + (Math.random() * 40 - 20),
237
- y: landmarkPoint.y - 50 - (Math.random() * 30)
238
- };
239
-
240
- const badge = document.createElement('div');
241
- badge.className = 'emotion-badge';
242
- badge.style.left = `${position.x}px`;
243
- badge.style.top = `${position.y}px`;
244
- badge.textContent = `${emotion}: ${Math.round(value * 100)}%`;
245
- document.getElementById('cameraView').appendChild(badge);
246
-
247
- // Remove badge after animation
248
- setTimeout(() => {
249
- badge.remove();
250
- }, 1000);
251
- }
252
- });
253
- }
254
-
255
- // Schedule next detection
256
- setTimeout(() => detectEmotions(), 300);
257
- }
258
 
259
  // Capture photo and analyze emotions
260
  captureBtn.addEventListener('click', async () => {
@@ -308,6 +259,14 @@
308
 
309
  resultsElement.classList.remove('hidden');
310
  resetBtn.classList.remove('hidden');
 
 
 
 
 
 
 
 
311
  } else {
312
  alert("No face detected in the captured image. Please try again.");
313
  resetApp();
@@ -336,10 +295,18 @@
336
  const context = canvas.getContext('2d');
337
  context.clearRect(0, 0, canvas.width, canvas.height);
338
 
339
- // Restart emotion detection
340
- detectEmotions();
341
  }
342
 
 
 
 
 
 
 
 
 
 
 
343
  // Helper functions
344
  function capitalizeFirstLetter(string) {
345
  return string.charAt(0).toUpperCase() + string.slice(1);
@@ -353,6 +320,116 @@
353
  return "Very Low";
354
  }
355
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
356
  // Initialize the app
357
  document.addEventListener('DOMContentLoaded', init);
358
  </script>
 
11
  position: relative;
12
  width: 100%;
13
  max-width: 640px;
14
+ height: 480px;
15
  margin: 0 auto;
16
  border-radius: 12px;
17
  overflow: hidden;
18
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
19
+ background-color: #000;
 
 
 
 
 
 
 
 
 
 
 
20
  }
21
 
22
  .loading-spinner {
 
44
  </head>
45
  <body class="bg-gray-100 min-h-screen">
46
  <div class="container mx-auto px-4 py-8">
47
+ <div class="flex flex-col lg:flex-row gap-8">
48
+ <div class="lg:w-2/3">
49
  <div class="text-center mb-8">
50
  <h1 class="text-3xl md:text-4xl font-bold text-indigo-700 mb-2">Emotion Detection Camera</h1>
51
  <p class="text-gray-600 max-w-lg mx-auto">Take a photo and our AI will detect your facial expressions and emotions in real-time.</p>
 
58
  </div>
59
 
60
  <div class="camera-container bg-gray-200 aspect-video relative" id="cameraView">
61
+ <video id="video" autoplay muted playsinline class="w-full h-full object-cover transform scaleX(-1)"></video>
62
  <canvas id="canvas" class="absolute top-0 left-0 w-full h-full hidden"></canvas>
63
  </div>
64
 
 
105
  </div>
106
  </div>
107
 
108
+ </div> <!-- End of video content -->
109
+
110
+ <!-- Emotion Suggestions Sidebar -->
111
+ <div class="lg:w-1/3 bg-white rounded-xl shadow-lg p-6 sticky top-8">
112
+ <div class="flex justify-between items-center mb-4">
113
+ <h3 class="text-xl font-semibold text-indigo-700">Emotion Tips</h3>
114
+ <button id="muteBtn" class="text-gray-500 hover:text-indigo-600">
115
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
116
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" />
117
+ </svg>
118
+ </button>
119
+ </div>
120
+ <div id="emotionSuggestions" class="space-y-4">
121
+ <div class="text-center py-8 text-gray-400">
122
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 mx-auto mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
123
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
124
+ </svg>
125
+ <p>Face the camera to get personalized suggestions!</p>
126
+ </div>
127
+ </div>
128
  </div>
129
+ </div> <!-- End of container -->
130
+
131
+ </div> <!-- End of flex container -->
132
+ </div> <!-- End of main container -->
133
+
134
+ <div class="mt-8 text-center text-gray-500 text-sm">
135
+ <p>This app uses face-api.js for emotion detection. All processing happens in your browser.</p>
136
  </div>
137
 
138
  <script>
 
157
  statusElement.classList.remove('hidden');
158
 
159
  try {
160
+ // Check camera permissions first
161
+ if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
162
+ throw new Error('Camera access not supported or blocked by browser');
163
+ }
164
  await Promise.all([
165
  faceapi.nets.tinyFaceDetector.loadFromUri('https://justadudewhohacks.github.io/face-api.js/models'),
166
  faceapi.nets.faceLandmark68Net.loadFromUri('https://justadudewhohacks.github.io/face-api.js/models'),
 
199
  video.srcObject = stream;
200
  video.onloadedmetadata = () => {
201
  video.play();
 
 
 
202
  };
203
  } catch (error) {
204
  console.error("Camera error:", error);
 
206
  }
207
  }
208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
 
210
  // Capture photo and analyze emotions
211
  captureBtn.addEventListener('click', async () => {
 
259
 
260
  resultsElement.classList.remove('hidden');
261
  resetBtn.classList.remove('hidden');
262
+
263
+ // Voice out the emotion tips
264
+ const primaryEmotion = Object.entries(expressions).reduce((a, b) => a[1] > b[1] ? a : b)[0];
265
+ const tips = emotionTips[primaryEmotion] || [
266
+ "Your emotions are valid. Take a moment to acknowledge how you feel."
267
+ ];
268
+ const randomTip = tips[Math.floor(Math.random() * tips.length)];
269
+ speak(`You seem ${primaryEmotion}. ${randomTip}. Here are some quick mood boosters: Take 3 deep breaths, drink some water, and stretch your body.`);
270
  } else {
271
  alert("No face detected in the captured image. Please try again.");
272
  resetApp();
 
295
  const context = canvas.getContext('2d');
296
  context.clearRect(0, 0, canvas.width, canvas.height);
297
 
 
 
298
  }
299
 
300
+ // Speech synthesis
301
+ function speak(text) {
302
+ if ('speechSynthesis' in window && !isMuted) {
303
+ speechSynthesis.cancel(); // Cancel any previous speech
304
+ const utterance = new SpeechSynthesisUtterance(text);
305
+ utterance.rate = 0.9;
306
+ speechSynthesis.speak(utterance);
307
+ }
308
+ }
309
+
310
  // Helper functions
311
  function capitalizeFirstLetter(string) {
312
  return string.charAt(0).toUpperCase() + string.slice(1);
 
320
  return "Very Low";
321
  }
322
 
323
+
324
+ // Emotion-based suggestions
325
+ const emotionTips = {
326
+ happy: [
327
+ "Your smile is contagious! Keep spreading joy!",
328
+ "Try doing something creative today - paint, write, or dance!",
329
+ "Share your happiness with someone who needs it today."
330
+ ],
331
+ sad: [
332
+ "Why did the sad computer apply for a job? It had too many bytes of emotional baggage!",
333
+ "Remember: This too shall pass. You've got this!",
334
+ "Try listening to uplifting music or calling a friend."
335
+ ],
336
+ angry: [
337
+ "Take 5 deep breaths - in through the nose, out through the mouth.",
338
+ "Try squeezing a stress ball or going for a quick walk.",
339
+ "Write down what's bothering you, then tear it up!"
340
+ ],
341
+ surprised: [
342
+ "Did you know? The average person is surprised 3 times a day!",
343
+ "Embrace the unexpected - it keeps life interesting!",
344
+ "Try something new today to keep that surprised look going!"
345
+ ],
346
+ fearful: [
347
+ "Face your fears one small step at a time - you're stronger than you think!",
348
+ "Try the 5-4-3-2-1 grounding technique: Name 5 things you can see, 4 you can touch, etc.",
349
+ "Remember: Courage isn't the absence of fear, but acting despite it."
350
+ ],
351
+ disgusted: [
352
+ "Eww, what's that face for? Try thinking of your favorite food instead!",
353
+ "When life gives you lemons... make sure they're not rotten first!",
354
+ "Change your environment - go somewhere pleasant to reset your mood."
355
+ ],
356
+ neutral: [
357
+ "Feeling balanced? Perfect time for mindfulness meditation!",
358
+ "Try a new facial expression - how about a smile?",
359
+ "Your calm demeanor is your superpower today."
360
+ ]
361
+ };
362
+
363
+ function updateEmotionSuggestions(expressions) {
364
+ const primaryEmotion = Object.entries(expressions).reduce((a, b) => a[1] > b[1] ? a : b)[0];
365
+ const suggestionsContainer = document.getElementById('emotionSuggestions');
366
+ const tips = emotionTips[primaryEmotion] || [
367
+ "Your emotions are valid. Take a moment to acknowledge how you feel."
368
+ ];
369
+
370
+ const randomTip = tips[Math.floor(Math.random() * tips.length)];
371
+
372
+ suggestionsContainer.innerHTML = `
373
+ <div class="bg-indigo-50 rounded-lg p-4">
374
+ <div class="flex items-center gap-3 mb-3">
375
+ <div class="bg-indigo-100 p-2 rounded-full">
376
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-indigo-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
377
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
378
+ </svg>
379
+ </div>
380
+ <h4 class="font-medium text-indigo-700">${capitalizeFirstLetter(primaryEmotion)} Detected</h4>
381
+ </div>
382
+ <p class="text-gray-700">${randomTip}</p>
383
+ </div>
384
+ <div class="bg-gray-50 rounded-lg p-4">
385
+ <h4 class="font-medium text-gray-700 mb-2">Quick Mood Boosters</h4>
386
+ <ul class="space-y-2 text-sm text-gray-600">
387
+ <li class="flex items-center gap-2">
388
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
389
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
390
+ </svg>
391
+ Take 3 deep breaths
392
+ </li>
393
+ <li class="flex items-center gap-2">
394
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
395
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
396
+ </svg>
397
+ Drink some water
398
+ </li>
399
+ <li class="flex items-center gap-2">
400
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
401
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
402
+ </svg>
403
+ Stretch your body
404
+ </li>
405
+ </ul>
406
+ </div>
407
+ `;
408
+ }
409
+
410
+ // Mute button functionality
411
+ const muteBtn = document.getElementById('muteBtn');
412
+ let isMuted = false;
413
+
414
+ muteBtn.addEventListener('click', () => {
415
+ isMuted = !isMuted;
416
+ if (isMuted) {
417
+ muteBtn.innerHTML = `
418
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
419
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" />
420
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2" />
421
+ </svg>
422
+ `;
423
+ speechSynthesis.cancel();
424
+ } else {
425
+ muteBtn.innerHTML = `
426
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
427
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" />
428
+ </svg>
429
+ `;
430
+ }
431
+ });
432
+
433
  // Initialize the app
434
  document.addEventListener('DOMContentLoaded', init);
435
  </script>