timgreyy commited on
Commit
62820a2
·
verified ·
1 Parent(s): cc4037f

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +594 -594
index.html CHANGED
@@ -1,595 +1,595 @@
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>AI Beauty Analyzer</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
- <style>
10
- .result-gauge {
11
- height: 10px;
12
- background: linear-gradient(90deg, #ec4899 0%, #f97316 25%, #eab308 50%, #22c55e 75%, #3b82f6 100%);
13
- }
14
- .face-element {
15
- transition: all 0.3s ease;
16
- }
17
- .face-element:hover {
18
- transform: scale(1.05);
19
- box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
20
- }
21
- .custom-scrollbar::-webkit-scrollbar {
22
- width: 6px;
23
- }
24
- .custom-scrollbar::-webkit-scrollbar-track {
25
- background: #f1f1f1;
26
- }
27
- .custom-scrollbar::-webkit-scrollbar-thumb {
28
- background: #888;
29
- border-radius: 3px;
30
- }
31
- .custom-scrollbar::-webkit-scrollbar-thumb:hover {
32
- background: #555;
33
- }
34
- .skin-tone-wheel {
35
- background: conic-gradient(#f5d0b4, #e5b887, #d9a066, #c88c58, #b87d4a);
36
- width: 100px;
37
- height: 100px;
38
- border-radius: 50%;
39
- }
40
- .loading-dots:after {
41
- content: '.';
42
- animation: dots 1.5s steps(5, end) infinite;
43
- }
44
- @keyframes dots {
45
- 0%, 20% {
46
- color: rgba(0,0,0,0);
47
- text-shadow: .25em 0 0 rgba(0,0,0,0), .5em 0 0 rgba(0,0,0,0);
48
- }
49
- 40% {
50
- color: gray;
51
- text-shadow: .25em 0 0 rgba(0,0,0,0), .5em 0 0 rgba(0,0,0,0);
52
- }
53
- 60% {
54
- text-shadow: .25em 0 0 gray, .5em 0 0 rgba(0,0,0,0);
55
- }
56
- 80%, 100% {
57
- text-shadow: .25em 0 0 gray, .5em 0 0 gray;
58
- }
59
- }
60
- </style>
61
- </head>
62
- <body class="bg-gray-50 text-gray-800">
63
- <div class="container mx-auto px-4 py-8 max-w-6xl">
64
- <header class="text-center mb-12">
65
- <h1 class="text-4xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-pink-500 to-orange-500 mb-3">
66
- <i class="fas fa-camera-retro mr-2"></i>AI Beauty Analyzer
67
- </h1>
68
- <p class="text-lg text-gray-600 max-w-2xl mx-auto">
69
- Upload a photo to receive a detailed analysis of facial features and beauty score based on scientific standards.
70
- </p>
71
- </header>
72
-
73
- <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
74
- <div class="lg:col-span-2 bg-white rounded-xl shadow-lg p-6 border border-gray-100">
75
- <div class="mb-6">
76
- <div id="upload-container" class="border-2 border-dashed border-gray-300 rounded-xl p-8 text-center cursor-pointer hover:border-pink-300 transition-colors">
77
- <i class="fas fa-cloud-upload-alt text-4xl text-gray-400 mb-3"></i>
78
- <h3 class="text-xl font-semibold mb-1">Upload a photo</h3>
79
- <p class="text-gray-500 mb-4">Drag & drop or click to browse (JPG, PNG)</p>
80
- <button class="btn-upload bg-gradient-to-r from-pink-500 to-orange-500 text-white px-6 py-2 rounded-full font-medium hover:opacity-90 transition-opacity">
81
- Select File
82
- </button>
83
- <input type="file" id="file-input" accept="image/*" class="hidden">
84
- </div>
85
- <div id="loading-container" class="hidden items-center justify-center p-8">
86
- <div class="text-center">
87
- <div class="inline-block text-2xl mb-3 loading-dots">Analyzing</div>
88
- <div class="h-1 w-full bg-gray-200 rounded-full overflow-hidden">
89
- <div id="progress-bar" class="h-full bg-gradient-to-r from-pink-500 to-orange-500" style="width: 0%"></div>
90
- </div>
91
- </div>
92
- </div>
93
- <div id="preview-container" class="hidden relative">
94
- <canvas id="preview-canvas" class="w-full h-auto rounded-lg border border-gray-200"></canvas>
95
- <button id="analyze-another" class="absolute top-2 right-2 bg-white rounded-full p-2 text-gray-700 shadow-md hover:bg-gray-100">
96
- <i class="fas fa-redo"></i>
97
- </button>
98
- </div>
99
- </div>
100
-
101
- <div id="face-data-container" class="hidden">
102
- <div class="flex items-center justify-between mb-6">
103
- <h3 class="text-xl font-semibold">Analysis Results</h3>
104
- <div class="flex items-center">
105
- <span class="text-sm text-gray-500 mr-2">Culture Standard:</span>
106
- <select class="bg-gray-100 border border-gray-300 rounded-full px-3 py-1 text-sm">
107
- <option>Global</option>
108
- <option>Western</option>
109
- <option>Asian</option>
110
- <option>Middle Eastern</option>
111
- <option>Latin American</option>
112
- <option>African</option>
113
- </select>
114
- </div>
115
- </div>
116
-
117
- <div id="multiple-faces-alert" class="hidden bg-yellow-100 border-l-4 border-yellow-500 p-4 mb-6">
118
- <div class="flex items-center">
119
- <i class="fas fa-exclamation-circle text-yellow-500 mr-3 text-xl"></i>
120
- <p class="text-yellow-700">Multiple faces detected. Showing analysis for the primary face.</p>
121
- </div>
122
- </div>
123
-
124
- <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
125
- <div class="face-element bg-gradient-to-br from-white to-gray-50 p-5 rounded-xl border border-gray-200 shadow-sm">
126
- <div class="flex items-center mb-3">
127
- <div class="w-10 h-10 rounded-full bg-pink-100 flex items-center justify-center mr-3">
128
- <i class="fas fa-star text-pink-500"></i>
129
- </div>
130
- <h4 class="font-semibold">Overall Score</h4>
131
- </div>
132
- <div class="flex items-center justify-between mb-2">
133
- <span id="overall-score-text" class="text-3xl font-bold">87</span>
134
- <span id="overall-rating" class="text-sm py-1 px-3 rounded-full bg-green-100 text-green-700">Excellent</span>
135
- </div>
136
- <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden mb-3">
137
- <div id="overall-score-bar" class="h-full bg-gradient-to-r from-pink-500 to-orange-500" style="width: 87%"></div>
138
- </div>
139
- <p class="text-gray-600 text-sm" id="overall-feedback">Your facial features show excellent harmony and balance, well above average compared to our database of 50,000 faces.</p>
140
- </div>
141
-
142
- <div class="face-element bg-gradient-to-br from-white to-gray-50 p-5 rounded-xl border border-gray-200 shadow-sm">
143
- <div class="flex items-center mb-3">
144
- <div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center mr-3">
145
- <i class="fas fa-project-diagram text-blue-500"></i>
146
- </div>
147
- <h4 class="font-semibold">Symmetry</h4>
148
- </div>
149
- <div class="mb-3">
150
- <div class="flex items-center justify-between text-sm mb-1">
151
- <span>Horizontal</span>
152
- <span class="font-medium" id="horizontal-symmetry">94%</span>
153
- </div>
154
- <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
155
- <div class="h-full bg-gradient-to-r from-blue-400 to-blue-600" style="width: 94%"></div>
156
- </div>
157
- </div>
158
- <div>
159
- <div class="flex items-center justify-between text-sm mb-1">
160
- <span>Vertical</span>
161
- <span class="font-medium" id="vertical-symmetry">91%</span>
162
- </div>
163
- <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
164
- <div class="h-full bg-gradient-to-r from-blue-400 to-blue-600" style="width: 91%"></div>
165
- </div>
166
- </div>
167
- </div>
168
- </div>
169
- </div>
170
- </div>
171
-
172
- <div class="lg:col-span-1">
173
- <div id="detailed-metrics-container" class="bg-white rounded-xl shadow-lg p-6 border border-gray-100 custom-scrollbar" style="max-height: 800px; overflow-y: auto;">
174
- <h3 class="text-xl font-semibold mb-4 sticky top-0 bg-white py-2 border-b">Detailed Metrics</h3>
175
-
176
- <div id="metrics-placeholder" class="text-center py-8">
177
- <i class="fas fa-chart-bar text-gray-300 text-4xl mb-3"></i>
178
- <p class="text-gray-500">Upload a photo to see detailed facial analysis</p>
179
- </div>
180
-
181
- <div id="metrics-content" class="hidden">
182
- <div class="mb-6">
183
- <h4 class="font-medium text-gray-700 mb-3 flex items-center">
184
- <i class="fas fa-expand-alt text-purple-500 mr-2"></i>Golden Ratio Proportions
185
- </h4>
186
- <div class="space-y-3">
187
- <div>
188
- <div class="flex justify-between text-sm mb-1">
189
- <span>Forehead to Midface</span>
190
- <span id="forehead-midface-score" class="font-medium">1.62 (Ideal)</span>
191
- </div>
192
- <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
193
- <div class="h-full bg-purple-500" style="width: 98%"></div>
194
- </div>
195
- </div>
196
- <div>
197
- <div class="flex justify-between text-sm mb-1">
198
- <span>Midface to Chin</span>
199
- <span id="midface-chin-score" class="font-medium">1.58 (Near Ideal)</span>
200
- </div>
201
- <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
202
- <div class="h-full bg-purple-500" style="width: 94%"></div>
203
- </div>
204
- </div>
205
- <div>
206
- <div class="flex justify-between text-sm mb-1">
207
- <span>Nose Width/Length</span>
208
- <span id="nose-ratio-score" class="font-medium">0.74 (Ideal 0.7)</span>
209
- </div>
210
- <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
211
- <div class="h-full bg-purple-500" style="width: 88%"></div>
212
- </div>
213
- </div>
214
- </div>
215
- </div>
216
-
217
- <div class="mb-6">
218
- <h4 class="font-medium text-gray-700 mb-3 flex items-center">
219
- <i class="fas fa-eye text-green-500 mr-2"></i>Eye Analysis
220
- </h4>
221
- <div class="grid grid-cols-2 gap-3">
222
- <div class="bg-gray-50 p-3 rounded-lg">
223
- <div class="text-sm text-gray-500 mb-1">Shape</div>
224
- <div class="font-medium" id="eye-shape">Almond</div>
225
- </div>
226
- <div class="bg-gray-50 p-3 rounded-lg">
227
- <div class="text-sm text-gray-500 mb-1">Spacing</div>
228
- <div class="font-medium" id="eye-spacing">Ideal</div>
229
- </div>
230
- <div class="bg-gray-50 p-3 rounded-lg">
231
- <div class="text-sm text-gray-500 mb-1">Size Balance</div>
232
- <div class="font-medium" id="eye-balance">Perfect</div>
233
- </div>
234
- <div class="bg-gray-50 p-3 rounded-lg">
235
- <div class="text-sm text-gray-500 mb-1">Iris Ratio</div>
236
- <div class="font-medium" id="iris-ratio">87%</div>
237
- </div>
238
- </div>
239
- </div>
240
-
241
- <div class="mb-6">
242
- <h4 class="font-medium text-gray-700 mb-3 flex items-center">
243
- <i class="fas fa-smile text-yellow-500 mr-2"></i>Lip Analysis
244
- </h4>
245
- <div class="space-y-3">
246
- <div>
247
- <div class="flex justify-between text-sm mb-1">
248
- <span>Cupid's Bow Definition</span>
249
- <span id="cupids-bow-score" class="font-medium">Excellent</span>
250
- </div>
251
- <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
252
- <div class="h-full bg-yellow-500" style="width: 92%"></div>
253
- </div>
254
- </div>
255
- <div>
256
- <div class="flex justify-between text-sm mb-1">
257
- <span>Upper/Lower Ratio</span>
258
- <span id="lip-ratio-score" class="font-medium">1:1.6 (Ideal)</span>
259
- </div>
260
- <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
261
- <div class="h-full bg-yellow-500" style="width: 96%"></div>
262
- </div>
263
- </div>
264
- <div>
265
- <div class="flex justify-between text-sm mb-1">
266
- <span>Width to Nose Ratio</span>
267
- <span id="lip-width-score" class="font-medium">1.3x (Perfect)</span>
268
- </div>
269
- <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
270
- <div class="h-full bg-yellow-500" style="width: 100%"></div>
271
- </div>
272
- </div>
273
- </div>
274
- </div>
275
-
276
- <div class="mb-6">
277
- <h4 class="font-medium text-gray-700 mb-3 flex items-center">
278
- <i class="fas fa-vector-square text-red-500 mr-2"></i>Face Shape
279
- </h4>
280
- <div class="flex items-center">
281
- <div class="mr-4">
282
- <div class="w-16 h-16 rounded-full bg-red-100 flex items-center justify-center">
283
- <i class="fas fa-user text-red-500 text-xl"></i>
284
- </div>
285
- </div>
286
- <div>
287
- <div id="face-shape" class="font-medium">Oval</div>
288
- <div id="face-shape-desc" class="text-sm text-gray-600">Considered the most versatile and balanced shape</div>
289
- </div>
290
- </div>
291
- </div>
292
-
293
- <div class="mb-6">
294
- <h4 class="font-medium text-gray-700 mb-3 flex items-center">
295
- <i class="fas fa-palette text-orange-500 mr-2"></i>Skin Analysis
296
- </h4>
297
- <div class="flex items-center mb-3">
298
- <div class="skin-tone-wheel mr-4"></div>
299
- <div>
300
- <div id="skin-tone" class="font-medium">Light Beige (Type IV)</div>
301
- <div id="skin-quality" class="text-sm text-gray-600 min-w-max">Even tone, minor pigmentation (92%)</div>
302
- </div>
303
- </div>
304
- <div class="grid grid-cols-3 gap-2">
305
- <div class="bg-gray-50 p-2 rounded text-center">
306
- <div class="text-sm text-gray-500">Pores</div>
307
- <div class="font-medium text-green-600">Fine</div>
308
- </div>
309
- <div class="bg-gray-50 p-2 rounded text-center">
310
- <div class="text-sm text-gray-500">Wrinkles</div>
311
- <div class="font-medium text-green-600">Few</div>
312
- </div>
313
- <div class="bg-gray-50 p-2 rounded text-center">
314
- <div class="text-sm text-gray-500">Spots</div>
315
- <div class="font-medium text-yellow-600">Some</div>
316
- </div>
317
- </div>
318
- </div>
319
-
320
- <div>
321
- <h4 class="font-medium text-gray-700 mb-3 flex items-center">
322
- <i class="fas fa-gem text-pink-500 mr-2"></i>Special Features
323
- </h4>
324
- <div class="flex flex-wrap gap-2">
325
- <span class="bg-pink-100 text-pink-800 text-xs px-3 py-1 rounded-full">Dimples</span>
326
- <span class="bg-pink-100 text-pink-800 text-xs px-3 py-1 rounded-full">High Cheekbones</span>
327
- <span class="bg-pink-100 text-pink-800 text-xs px-3 py-1 rounded-full">Expressive Eyes</span>
328
- </div>
329
- </div>
330
- </div>
331
- </div>
332
- </div>
333
- </div>
334
-
335
- <footer class="mt-12 text-center text-gray-500 text-sm">
336
- <p>This beauty analysis is for entertainment purposes only. All photos are processed securely and not stored.</p>
337
- <p class="mt-2">&copy; 2023 AI Beauty Analyzer. Using advanced computer vision algorithms.</p>
338
- </footer>
339
- </div>
340
-
341
- <script>
342
- document.addEventListener('DOMContentLoaded', function() {
343
- const uploadContainer = document.getElementById('upload-container');
344
- const fileInput = document.getElementById('file-input');
345
- const loadingContainer = document.getElementById('loading-container');
346
- const progressBar = document.getElementById('progress-bar');
347
- const previewContainer = document.getElementById('preview-container');
348
- const previewCanvas = document.getElementById('preview-canvas');
349
- const faceDataContainer = document.getElementById('face-data-container');
350
- const metricsPlaceholder = document.getElementById('metrics-placeholder');
351
- const metricsContent = document.getElementById('metrics-content');
352
- const analyzeAnotherBtn = document.getElementById('analyze-another');
353
- const multipleFacesAlert = document.getElementById('multiple-faces-alert');
354
-
355
- // Upload click handler
356
- uploadContainer.addEventListener('click', function() {
357
- fileInput.click();
358
- });
359
-
360
- // File input change handler
361
- fileInput.addEventListener('change', function(e) {
362
- if (e.target.files.length > 0) {
363
- const file = e.target.files[0];
364
- processImage(file);
365
- }
366
- });
367
-
368
- // Drag and drop handlers
369
- uploadContainer.addEventListener('dragover', function(e) {
370
- e.preventDefault();
371
- uploadContainer.classList.add('border-pink-400', 'bg-pink-50');
372
- });
373
-
374
- uploadContainer.addEventListener('dragleave', function() {
375
- uploadContainer.classList.remove('border-pink-400', 'bg-pink-50');
376
- });
377
-
378
- uploadContainer.addEventListener('drop', function(e) {
379
- e.preventDefault();
380
- uploadContainer.classList.remove('border-pink-400', 'bg-pink-50');
381
-
382
- if (e.dataTransfer.files.length > 0) {
383
- const file = e.dataTransfer.files[0];
384
- processImage(file);
385
- }
386
- });
387
-
388
- // Analyze another button
389
- analyzeAnotherBtn.addEventListener('click', function() {
390
- resetUI();
391
- });
392
-
393
- function processImage(file) {
394
- if (!file.type.match('image.*')) {
395
- alert('Please select an image file (JPG, PNG)');
396
- return;
397
- }
398
-
399
- // Show loading state
400
- uploadContainer.classList.add('hidden');
401
- loadingContainer.classList.remove('hidden');
402
-
403
- // Simulate progress (in a real app, this would be the actual analysis progress)
404
- let progress = 0;
405
- const progressInterval = setInterval(() => {
406
- progress += Math.random() * 5;
407
- if (progress >= 100) {
408
- progress = 100;
409
- clearInterval(progressInterval);
410
- setTimeout(showAnalysisResults, 500, file);
411
- }
412
- progressBar.style.width = `${progress}%`;
413
- }, 100);
414
-
415
- // Create image preview
416
- const reader = new FileReader();
417
- reader.onload = function(e) {
418
- const img = new Image();
419
- img.onload = function() {
420
- const ctx = previewCanvas.getContext('2d');
421
- const maxWidth = 800;
422
- const maxHeight = 600;
423
- let width = img.width;
424
- let height = img.height;
425
-
426
- if (width > maxWidth) {
427
- const ratio = maxWidth / width;
428
- width = maxWidth;
429
- height = height * ratio;
430
- }
431
-
432
- if (height > maxHeight) {
433
- const ratio = maxHeight / height;
434
- height = maxHeight;
435
- width = width * ratio;
436
- }
437
-
438
- previewCanvas.width = width;
439
- previewCanvas.height = height;
440
- ctx.drawImage(img, 0, 0, width, height);
441
- };
442
- img.src = e.target.result;
443
- };
444
- reader.readAsDataURL(file);
445
- }
446
-
447
- function showAnalysisResults() {
448
- loadingContainer.classList.add('hidden');
449
- previewContainer.classList.remove('hidden');
450
- faceDataContainer.classList.remove('hidden');
451
- metricsPlaceholder.classList.add('hidden');
452
- metricsContent.classList.remove('hidden');
453
-
454
- // Randomly decide if multiple faces were detected (for demo)
455
- if (Math.random() > 0.7) {
456
- multipleFacesAlert.classList.remove('hidden');
457
- }
458
-
459
- // Draw face landmarks (simulated)
460
- const ctx = previewCanvas.getContext('2d');
461
- ctx.strokeStyle = '#3b82f6';
462
- ctx.lineWidth = 2;
463
-
464
- // Draw a rectangle around the "detected" face
465
- const faceX = previewCanvas.width * 0.25;
466
- const faceY = previewCanvas.height * 0.2;
467
- const faceWidth = previewCanvas.width * 0.5;
468
- const faceHeight = previewCanvas.height * 0.6;
469
-
470
- ctx.strokeRect(faceX, faceY, faceWidth, faceHeight);
471
-
472
- // Draw some "landmarks" (eyes, nose, mouth)
473
- // Left eye
474
- ctx.beginPath();
475
- ctx.arc(faceX + faceWidth * 0.35, faceY + faceHeight * 0.3, faceWidth * 0.05, 0, 2 * Math.PI);
476
- ctx.stroke();
477
-
478
- // Right eye
479
- ctx.beginPath();
480
- ctx.arc(faceX + faceWidth * 0.65, faceY + faceHeight * 0.3, faceWidth * 0.05, 0, 2 * Math.PI);
481
- ctx.stroke();
482
-
483
- // Nose
484
- ctx.beginPath();
485
- ctx.moveTo(faceX + faceWidth * 0.5, faceY + faceHeight * 0.35);
486
- ctx.lineTo(faceX + faceWidth * 0.5, faceY + faceHeight * 0.6);
487
- ctx.stroke();
488
-
489
- // Mouth
490
- ctx.beginPath();
491
- ctx.ellipse(faceX + faceWidth * 0.5, faceY + faceHeight * 0.75,
492
- faceWidth * 0.15, faceHeight * 0.08, 0, 0, Math.PI);
493
- ctx.stroke();
494
- }
495
-
496
- function resetUI() {
497
- fileInput.value = '';
498
- previewContainer.classList.add('hidden');
499
- faceDataContainer.classList.add('hidden');
500
- loadingContainer.classList.add('hidden');
501
- uploadContainer.classList.remove('hidden');
502
- metricsContent.classList.add('hidden');
503
- metricsPlaceholder.classList.remove('hidden');
504
- multipleFacesAlert.classList.add('hidden');
505
- progressBar.style.width = '0%';
506
- }
507
-
508
- // For demo purposes, let's simulate some random data generation
509
- const scoreElements = {
510
- 'overall-score-text': [75, 95],
511
- 'horizontal-symmetry': [85, 98],
512
- 'vertical-symmetry': [80, 96],
513
- 'forehead-midface-score': ['1.58 (Near Ideal)', '1.62 (Ideal)'],
514
- 'midface-chin-score': ['1.54 (Good)', '1.62 (Perfect)'],
515
- 'nose-ratio-score': ['0.68 (Near Ideal)', '0.72 (Ideal)'],
516
- 'eye-shape': ['Round', 'Almond', 'Deep-set', 'Downturned'],
517
- 'eye-spacing': ['Slightly Wide', 'Ideal', 'Slightly Narrow'],
518
- 'eye-balance': ['Good', 'Perfect', 'Slightly Asymmetric'],
519
- 'iris-ratio': ['75%', '82%', '89%', '93%'],
520
- 'cupids-bow-score': ['Subtle', 'Defined', 'Very Defined', 'Perfect'],
521
- 'lip-ratio-score': ['1:1.4', '1:1.6 (Ideal)', '1:1.8'],
522
- 'lip-width-score': ['1.1x', '1.3x (Perfect)', '1.5x'],
523
- 'face-shape': ['Oval', 'Round', 'Square', 'Heart', 'Diamond'],
524
- 'skin-tone': ['Pale (Type II)', 'Light Beige (Type IV)', 'Olive (Type V)', 'Deep Brown (Type VI)'],
525
- 'skin-quality': ['Even tone', 'Minor pigmentation', 'Some redness', 'Clear']
526
- };
527
-
528
- const faceShapeDescriptions = {
529
- 'Oval': 'Considered the most versatile and balanced shape',
530
- 'Round': 'Soft features with similar width and length',
531
- 'Square': 'Strong jawline with angular features',
532
- 'Heart': 'Wider forehead tapering to a pointed chin',
533
- 'Diamond': 'Narrow forehead and jaw with wide cheekbones'
534
- };
535
-
536
- // Generate random demo data
537
- if (metricsContent) {
538
- for (const [id, values] of Object.entries(scoreElements)) {
539
- const element = document.getElementById(id);
540
- if (element) {
541
- if (typeof values[0] === 'number') {
542
- // Handle numeric ranges
543
- const val = Math.floor(Math.random() * (values[1] - values[0] + 1)) + values[0];
544
- if (id === 'overall-score-text') {
545
- element.textContent = val;
546
- document.getElementById('overall-score-bar').style.width = `${val}%`;
547
-
548
- // Set rating text
549
- let rating, ratingClass;
550
- if (val >= 90) {
551
- rating = 'Excellent'; ratingClass = 'bg-green-100 text-green-700';
552
- } else if (val >= 75) {
553
- rating = 'Great'; ratingClass = 'bg-blue-100 text-blue-700';
554
- } else if (val >= 60) {
555
- rating = 'Good'; ratingClass = 'bg-yellow-100 text-yellow-700';
556
- } else {
557
- rating = 'Average'; ratingClass = 'bg-gray-100 text-gray-700';
558
- }
559
-
560
- const ratingElement = document.getElementById('overall-rating');
561
- ratingElement.textContent = rating;
562
- ratingElement.className = `text-sm py-1 px-3 rounded-full ${ratingClass}`;
563
-
564
- // Set feedback
565
- const feedbacks = [
566
- "Your facial features show excellent harmony and balance, well above average.",
567
- "Your face has very pleasing proportions that match beauty standards.",
568
- "Good overall symmetry and features, with some room for perfect alignment.",
569
- "Average features with some strong points and some areas that could be more balanced."
570
- ];
571
- document.getElementById('overall-feedback').textContent = feedbacks[Math.min(3, Math.floor((100-val)/15))];
572
- } else {
573
- element.textContent = typeof val === 'number' ? `${val}%` : val;
574
- if (id.includes('symmetry')) {
575
- const bar = element.closest('div').querySelector('.h-2 > div');
576
- if (bar) bar.style.width = `${val}%`;
577
- }
578
- }
579
- } else {
580
- // Handle string arrays
581
- const val = values[Math.floor(Math.random() * values.length)];
582
- element.textContent = val;
583
-
584
- // Special handling for face shape
585
- if (id === 'face-shape') {
586
- document.getElementById('face-shape-desc').textContent = faceShapeDescriptions[val] || '';
587
- }
588
- }
589
- }
590
- }
591
- }
592
- });
593
- </script>
594
- </body>
595
  </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>AI Beauty Analyzer</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .result-gauge {
11
+ height: 10px;
12
+ background: linear-gradient(90deg, #ec4899 0%, #f97316 25%, #eab308 50%, #22c55e 75%, #3b82f6 100%);
13
+ }
14
+ .face-element {
15
+ transition: all 0.3s ease;
16
+ }
17
+ .face-element:hover {
18
+ transform: scale(1.05);
19
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
20
+ }
21
+ .custom-scrollbar::-webkit-scrollbar {
22
+ width: 6px;
23
+ }
24
+ .custom-scrollbar::-webkit-scrollbar-track {
25
+ background: #f1f1f1;
26
+ }
27
+ .custom-scrollbar::-webkit-scrollbar-thumb {
28
+ background: #888;
29
+ border-radius: 3px;
30
+ }
31
+ .custom-scrollbar::-webkit-scrollbar-thumb:hover {
32
+ background: #555;
33
+ }
34
+ .skin-tone-wheel {
35
+ background: conic-gradient(#f5d0b4, #e5b887, #d9a066, #c88c58, #b87d4a);
36
+ width: 100px;
37
+ height: 100px;
38
+ border-radius: 50%;
39
+ }
40
+ .loading-dots:after {
41
+ content: '.';
42
+ animation: dots 1.5s steps(5, end) infinite;
43
+ }
44
+ @keyframes dots {
45
+ 0%, 20% {
46
+ color: rgba(0,0,0,0);
47
+ text-shadow: .25em 0 0 rgba(0,0,0,0), .5em 0 0 rgba(0,0,0,0);
48
+ }
49
+ 40% {
50
+ color: gray;
51
+ text-shadow: .25em 0 0 rgba(0,0,0,0), .5em 0 0 rgba(0,0,0,0);
52
+ }
53
+ 60% {
54
+ text-shadow: .25em 0 0 gray, .5em 0 0 rgba(0,0,0,0);
55
+ }
56
+ 80%, 100% {
57
+ text-shadow: .25em 0 0 gray, .5em 0 0 gray;
58
+ }
59
+ }
60
+ </style>
61
+ </head>
62
+ <body class="bg-gray-50 text-gray-800">
63
+ <div class="container mx-auto px-4 py-8 max-w-6xl">
64
+ <header class="text-center mb-12">
65
+ <h1 class="text-4xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-pink-500 to-orange-500 mb-3">
66
+ <i class="fas fa-camera-retro mr-2"></i>AI Beauty Analyzer
67
+ </h1>
68
+ <p class="text-lg text-gray-600 max-w-2xl mx-auto">
69
+ Upload a photo to receive a detailed analysis of facial features and beauty score based on scientific standards.
70
+ </p>
71
+ </header>
72
+
73
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
74
+ <div class="lg:col-span-2 bg-white rounded-xl shadow-lg p-6 border border-gray-100">
75
+ <div class="mb-6">
76
+ <div id="upload-container" class="border-2 border-dashed border-gray-300 rounded-xl p-8 text-center cursor-pointer hover:border-pink-300 transition-colors">
77
+ <i class="fas fa-cloud-upload-alt text-4xl text-gray-400 mb-3"></i>
78
+ <h3 class="text-xl font-semibold mb-1">Upload a photo</h3>
79
+ <p class="text-gray-500 mb-4">Drag & drop or click to browse (JPG, PNG)</p>
80
+ <button class="btn-upload bg-gradient-to-r from-pink-500 to-orange-500 text-white px-6 py-2 rounded-full font-medium hover:opacity-90 transition-opacity">
81
+ Select File
82
+ </button>
83
+ <input type="file" id="file-input" accept="image/*" class="hidden">
84
+ </div>
85
+ <div id="loading-container" class="hidden items-center justify-center p-8">
86
+ <div class="text-center">
87
+ <div class="inline-block text-2xl mb-3 loading-dots">Analyzing</div>
88
+ <div class="h-1 w-full bg-gray-200 rounded-full overflow-hidden">
89
+ <div id="progress-bar" class="h-full bg-gradient-to-r from-pink-500 to-orange-500" style="width: 0%"></div>
90
+ </div>
91
+ </div>
92
+ </div>
93
+ <div id="preview-container" class="hidden relative">
94
+ <canvas id="preview-canvas" class="w-full h-auto rounded-lg border border-gray-200"></canvas>
95
+ <button id="analyze-another" class="absolute top-2 right-2 bg-white rounded-full p-2 text-gray-700 shadow-md hover:bg-gray-100">
96
+ <i class="fas fa-redo"></i>
97
+ </button>
98
+ </div>
99
+ </div>
100
+
101
+ <div id="face-data-container" class="hidden">
102
+ <div class="flex items-center justify-between mb-6">
103
+ <h3 class="text-xl font-semibold">Analysis Results</h3>
104
+ <div class="flex items-center">
105
+ <span class="text-sm text-gray-500 mr-2">Culture Standard:</span>
106
+ <select class="bg-gray-100 border border-gray-300 rounded-full px-3 py-1 text-sm">
107
+ <option>Global</option>
108
+ <option>Western</option>
109
+ <option>Asian</option>
110
+ <option>Middle Eastern</option>
111
+ <option>Latin American</option>
112
+ <option>African</option>
113
+ </select>
114
+ </div>
115
+ </div>
116
+
117
+ <div id="multiple-faces-alert" class="hidden bg-yellow-100 border-l-4 border-yellow-500 p-4 mb-6">
118
+ <div class="flex items-center">
119
+ <i class="fas fa-exclamation-circle text-yellow-500 mr-3 text-xl"></i>
120
+ <p class="text-yellow-700">Multiple faces detected. Showing analysis for the primary face.</p>
121
+ </div>
122
+ </div>
123
+
124
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
125
+ <div class="face-element bg-gradient-to-br from-white to-gray-50 p-5 rounded-xl border border-gray-200 shadow-sm">
126
+ <div class="flex items-center mb-3">
127
+ <div class="w-10 h-10 rounded-full bg-pink-100 flex items-center justify-center mr-3">
128
+ <i class="fas fa-star text-pink-500"></i>
129
+ </div>
130
+ <h4 class="font-semibold">Overall Score</h4>
131
+ </div>
132
+ <div class="flex items-center justify-between mb-2">
133
+ <span id="overall-score-text" class="text-3xl font-bold">87</span>
134
+ <span id="overall-rating" class="text-sm py-1 px-3 rounded-full bg-green-100 text-green-700">Excellent</span>
135
+ </div>
136
+ <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden mb-3">
137
+ <div id="overall-score-bar" class="h-full bg-gradient-to-r from-pink-500 to-orange-500" style="width: 87%"></div>
138
+ </div>
139
+ <p class="text-gray-600 text-sm" id="overall-feedback">Your facial features show excellent harmony and balance, well above average compared to our database of 50,000 faces.</p>
140
+ </div>
141
+
142
+ <div class="face-element bg-gradient-to-br from-white to-gray-50 p-5 rounded-xl border border-gray-200 shadow-sm">
143
+ <div class="flex items-center mb-3">
144
+ <div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center mr-3">
145
+ <i class="fas fa-project-diagram text-blue-500"></i>
146
+ </div>
147
+ <h4 class="font-semibold">Symmetry</h4>
148
+ </div>
149
+ <div class="mb-3">
150
+ <div class="flex items-center justify-between text-sm mb-1">
151
+ <span>Horizontal</span>
152
+ <span class="font-medium" id="horizontal-symmetry">94%</span>
153
+ </div>
154
+ <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
155
+ <div class="h-full bg-gradient-to-r from-blue-400 to-blue-600" style="width: 94%"></div>
156
+ </div>
157
+ </div>
158
+ <div>
159
+ <div class="flex items-center justify-between text-sm mb-1">
160
+ <span>Vertical</span>
161
+ <span class="font-medium" id="vertical-symmetry">91%</span>
162
+ </div>
163
+ <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
164
+ <div class="h-full bg-gradient-to-r from-blue-400 to-blue-600" style="width: 91%"></div>
165
+ </div>
166
+ </div>
167
+ </div>
168
+ </div>
169
+ </div>
170
+ </div>
171
+
172
+ <div class="lg:col-span-1">
173
+ <div id="detailed-metrics-container" class="bg-white rounded-xl shadow-lg p-6 border border-gray-100 custom-scrollbar" style="max-height: 800px; overflow-y: auto;">
174
+ <h3 class="text-xl font-semibold mb-4 sticky top-0 bg-white py-2 border-b">Detailed Metrics</h3>
175
+
176
+ <div id="metrics-placeholder" class="text-center py-8">
177
+ <i class="fas fa-chart-bar text-gray-300 text-4xl mb-3"></i>
178
+ <p class="text-gray-500">Upload a photo to see detailed facial analysis</p>
179
+ </div>
180
+
181
+ <div id="metrics-content" class="hidden">
182
+ <div class="mb-6">
183
+ <h4 class="font-medium text-gray-700 mb-3 flex items-center">
184
+ <i class="fas fa-expand-alt text-purple-500 mr-2"></i>Golden Ratio Proportions
185
+ </h4>
186
+ <div class="space-y-3">
187
+ <div>
188
+ <div class="flex justify-between text-sm mb-1">
189
+ <span>Forehead to Midface</span>
190
+ <span id="forehead-midface-score" class="font-medium">1.62 (Ideal)</span>
191
+ </div>
192
+ <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
193
+ <div class="h-full bg-purple-500" style="width: 98%"></div>
194
+ </div>
195
+ </div>
196
+ <div>
197
+ <div class="flex justify-between text-sm mb-1">
198
+ <span>Midface to Chin</span>
199
+ <span id="midface-chin-score" class="font-medium">1.58 (Near Ideal)</span>
200
+ </div>
201
+ <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
202
+ <div class="h-full bg-purple-500" style="width: 94%"></div>
203
+ </div>
204
+ </div>
205
+ <div>
206
+ <div class="flex justify-between text-sm mb-1">
207
+ <span>Nose Width/Length</span>
208
+ <span id="nose-ratio-score" class="font-medium">0.74 (Ideal 0.7)</span>
209
+ </div>
210
+ <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
211
+ <div class="h-full bg-purple-500" style="width: 88%"></div>
212
+ </div>
213
+ </div>
214
+ </div>
215
+ </div>
216
+
217
+ <div class="mb-6">
218
+ <h4 class="font-medium text-gray-700 mb-3 flex items-center">
219
+ <i class="fas fa-eye text-green-500 mr-2"></i>Eye Analysis
220
+ </h4>
221
+ <div class="grid grid-cols-2 gap-3">
222
+ <div class="bg-gray-50 p-3 rounded-lg">
223
+ <div class="text-sm text-gray-500 mb-1">Shape</div>
224
+ <div class="font-medium" id="eye-shape">Almond</div>
225
+ </div>
226
+ <div class="bg-gray-50 p-3 rounded-lg">
227
+ <div class="text-sm text-gray-500 mb-1">Spacing</div>
228
+ <div class="font-medium" id="eye-spacing">Ideal</div>
229
+ </div>
230
+ <div class="bg-gray-50 p-3 rounded-lg">
231
+ <div class="text-sm text-gray-500 mb-1">Size Balance</div>
232
+ <div class="font-medium" id="eye-balance">Perfect</div>
233
+ </div>
234
+ <div class="bg-gray-50 p-3 rounded-lg">
235
+ <div class="text-sm text-gray-500 mb-1">Iris Ratio</div>
236
+ <div class="font-medium" id="iris-ratio">87%</div>
237
+ </div>
238
+ </div>
239
+ </div>
240
+
241
+ <div class="mb-6">
242
+ <h4 class="font-medium text-gray-700 mb-3 flex items-center">
243
+ <i class="fas fa-smile text-yellow-500 mr-2"></i>Lip Analysis
244
+ </h4>
245
+ <div class="space-y-3">
246
+ <div>
247
+ <div class="flex justify-between text-sm mb-1">
248
+ <span>Cupid's Bow Definition</span>
249
+ <span id="cupids-bow-score" class="font-medium">Excellent</span>
250
+ </div>
251
+ <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
252
+ <div class="h-full bg-yellow-500" style="width: 92%"></div>
253
+ </div>
254
+ </div>
255
+ <div>
256
+ <div class="flex justify-between text-sm mb-1">
257
+ <span>Upper/Lower Ratio</span>
258
+ <span id="lip-ratio-score" class="font-medium">1:1.6 (Ideal)</span>
259
+ </div>
260
+ <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
261
+ <div class="h-full bg-yellow-500" style="width: 96%"></div>
262
+ </div>
263
+ </div>
264
+ <div>
265
+ <div class="flex justify-between text-sm mb-1">
266
+ <span>Width to Nose Ratio</span>
267
+ <span id="lip-width-score" class="font-medium">1.3x (Perfect)</span>
268
+ </div>
269
+ <div class="h-2 w-full bg-gray-200 rounded-full overflow-hidden">
270
+ <div class="h-full bg-yellow-500" style="width: 100%"></div>
271
+ </div>
272
+ </div>
273
+ </div>
274
+ </div>
275
+
276
+ <div class="mb-6">
277
+ <h4 class="font-medium text-gray-700 mb-3 flex items-center">
278
+ <i class="fas fa-vector-square text-red-500 mr-2"></i>Face Shape
279
+ </h4>
280
+ <div class="flex items-center">
281
+ <div class="mr-4">
282
+ <div class="w-16 h-16 rounded-full bg-red-100 flex items-center justify-center">
283
+ <i class="fas fa-user text-red-500 text-xl"></i>
284
+ </div>
285
+ </div>
286
+ <div>
287
+ <div id="face-shape" class="font-medium">Oval</div>
288
+ <div id="face-shape-desc" class="text-sm text-gray-600">Considered the most versatile and balanced shape</div>
289
+ </div>
290
+ </div>
291
+ </div>
292
+
293
+ <div class="mb-6">
294
+ <h4 class="font-medium text-gray-700 mb-3 flex items-center">
295
+ <i class="fas fa-palette text-orange-500 mr-2"></i>Skin Analysis
296
+ </h4>
297
+ <div class="flex items-center mb-3">
298
+ <div class="skin-tone-wheel mr-4"></div>
299
+ <div>
300
+ <div id="skin-tone" class="font-medium">Light Beige (Type IV)</div>
301
+ <div id="skin-quality" class="text-sm text-gray-600 min-w-max">Even tone, minor pigmentation (92%)</div>
302
+ </div>
303
+ </div>
304
+ <div class="grid grid-cols-3 gap-2">
305
+ <div class="bg-gray-50 p-2 rounded text-center">
306
+ <div class="text-sm text-gray-500">Pores</div>
307
+ <div class="font-medium text-green-600">Fine</div>
308
+ </div>
309
+ <div class="bg-gray-50 p-2 rounded text-center">
310
+ <div class="text-sm text-gray-500">Wrinkles</div>
311
+ <div class="font-medium text-green-600">Few</div>
312
+ </div>
313
+ <div class="bg-gray-50 p-2 rounded text-center">
314
+ <div class="text-sm text-gray-500">Spots</div>
315
+ <div class="font-medium text-yellow-600">Some</div>
316
+ </div>
317
+ </div>
318
+ </div>
319
+
320
+ <div>
321
+ <h4 class="font-medium text-gray-700 mb-3 flex items-center">
322
+ <i class="fas fa-gem text-pink-500 mr-2"></i>Special Features
323
+ </h4>
324
+ <div class="flex flex-wrap gap-2">
325
+ <span class="bg-pink-100 text-pink-800 text-xs px-3 py-1 rounded-full">Dimples</span>
326
+ <span class="bg-pink-100 text-pink-800 text-xs px-3 py-1 rounded-full">High Cheekbones</span>
327
+ <span class="bg-pink-100 text-pink-800 text-xs px-3 py-1 rounded-full">Expressive Eyes</span>
328
+ </div>
329
+ </div>
330
+ </div>
331
+ </div>
332
+ </div>
333
+ </div>
334
+
335
+ <footer class="mt-12 text-center text-gray-500 text-sm">
336
+ <p>This beauty analysis is for entertainment purposes only. All photos are processed securely and not stored.</p>
337
+ <p class="mt-2">&copy; 2023 AI Beauty Analyzer. Using advanced computer vision algorithms.</p>
338
+ </footer>
339
+ </div>
340
+
341
+ <script>
342
+ document.addEventListener('DOMContentLoaded', function() {
343
+ const uploadContainer = document.getElementById('upload-container');
344
+ const fileInput = document.getElementById('file-input');
345
+ const loadingContainer = document.getElementById('loading-container');
346
+ const progressBar = document.getElementById('progress-bar');
347
+ const previewContainer = document.getElementById('preview-container');
348
+ const previewCanvas = document.getElementById('preview-canvas');
349
+ const faceDataContainer = document.getElementById('face-data-container');
350
+ const metricsPlaceholder = document.getElementById('metrics-placeholder');
351
+ const metricsContent = document.getElementById('metrics-content');
352
+ const analyzeAnotherBtn = document.getElementById('analyze-another');
353
+ const multipleFacesAlert = document.getElementById('multiple-faces-alert');
354
+
355
+ // Upload click handler
356
+ uploadContainer.addEventListener('click', function() {
357
+ fileInput.click();
358
+ });
359
+
360
+ // File input change handler
361
+ fileInput.addEventListener('change', function(e) {
362
+ if (e.target.files.length > 0) {
363
+ const file = e.target.files[0];
364
+ processImage(file);
365
+ }
366
+ });
367
+
368
+ // Drag and drop handlers
369
+ uploadContainer.addEventListener('dragover', function(e) {
370
+ e.preventDefault();
371
+ uploadContainer.classList.add('border-pink-400', 'bg-pink-50');
372
+ });
373
+
374
+ uploadContainer.addEventListener('dragleave', function() {
375
+ uploadContainer.classList.remove('border-pink-400', 'bg-pink-50');
376
+ });
377
+
378
+ uploadContainer.addEventListener('drop', function(e) {
379
+ e.preventDefault();
380
+ uploadContainer.classList.remove('border-pink-400', 'bg-pink-50');
381
+
382
+ if (e.dataTransfer.files.length > 0) {
383
+ const file = e.dataTransfer.files[0];
384
+ processImage(file);
385
+ }
386
+ });
387
+
388
+ // Analyze another button
389
+ analyzeAnotherBtn.addEventListener('click', function() {
390
+ resetUI();
391
+ });
392
+
393
+ function processImage(file) {
394
+ if (!file.type.match('image.*')) {
395
+ alert('Please select an image file (JPG, PNG)');
396
+ return;
397
+ }
398
+
399
+ // Show loading state
400
+ uploadContainer.classList.add('hidden');
401
+ loadingContainer.classList.remove('hidden');
402
+
403
+ // Simulate progress (in a real app, this would be the actual analysis progress)
404
+ let progress = 0;
405
+ const progressInterval = setInterval(() => {
406
+ progress += Math.random() * 5;
407
+ if (progress >= 100) {
408
+ progress = 100;
409
+ clearInterval(progressInterval);
410
+ setTimeout(showAnalysisResults, 500, file);
411
+ }
412
+ progressBar.style.width = `${progress}%`;
413
+ }, 100);
414
+
415
+ // Create image preview
416
+ const reader = new FileReader();
417
+ reader.onload = function(e) {
418
+ const img = new Image();
419
+ img.onload = function() {
420
+ const ctx = previewCanvas.getContext('2d');
421
+ const maxWidth = 800;
422
+ const maxHeight = 600;
423
+ let width = img.width;
424
+ let height = img.height;
425
+
426
+ if (width > maxWidth) {
427
+ const ratio = maxWidth / width;
428
+ width = maxWidth;
429
+ height = height * ratio;
430
+ }
431
+
432
+ if (height > maxHeight) {
433
+ const ratio = maxHeight / height;
434
+ height = maxHeight;
435
+ width = width * ratio;
436
+ }
437
+
438
+ previewCanvas.width = width;
439
+ previewCanvas.height = height;
440
+ ctx.drawImage(img, 0, 0, width, height);
441
+ };
442
+ img.src = e.target.result;
443
+ };
444
+ reader.readAsDataURL(file);
445
+ }
446
+
447
+ function showAnalysisResults() {
448
+ loadingContainer.classList.add('hidden');
449
+ previewContainer.classList.remove('hidden');
450
+ faceDataContainer.classList.remove('hidden');
451
+ metricsPlaceholder.classList.add('hidden');
452
+ metricsContent.classList.remove('hidden');
453
+
454
+ // Randomly decide if multiple faces were detected (for demo)
455
+ if (Math.random() > 0.7) {
456
+ multipleFacesAlert.classList.remove('hidden');
457
+ }
458
+
459
+ // Draw face landmarks (simulated)
460
+ const ctx = previewCanvas.getContext('2d');
461
+ ctx.strokeStyle = '#3b82f6';
462
+ ctx.lineWidth = 2;
463
+
464
+ // Draw a rectangle around the "detected" face
465
+ const faceX = previewCanvas.width * 0.25;
466
+ const faceY = previewCanvas.height * 0.2;
467
+ const faceWidth = previewCanvas.width * 0.5;
468
+ const faceHeight = previewCanvas.height * 0.6;
469
+
470
+ ctx.strokeRect(faceX, faceY, faceWidth, faceHeight);
471
+
472
+ // Draw some "landmarks" (eyes, nose, mouth)
473
+ // Left eye
474
+ ctx.beginPath();
475
+ ctx.arc(faceX + faceWidth * 0.35, faceY + faceHeight * 0.3, faceWidth * 0.05, 0, 2 * Math.PI);
476
+ ctx.stroke();
477
+
478
+ // Right eye
479
+ ctx.beginPath();
480
+ ctx.arc(faceX + faceWidth * 0.65, faceY + faceHeight * 0.3, faceWidth * 0.05, 0, 2 * Math.PI);
481
+ ctx.stroke();
482
+
483
+ // Nose
484
+ ctx.beginPath();
485
+ ctx.moveTo(faceX + faceWidth * 0.5, faceY + faceHeight * 0.35);
486
+ ctx.lineTo(faceX + faceWidth * 0.5, faceY + faceHeight * 0.6);
487
+ ctx.stroke();
488
+
489
+ // Mouth
490
+ ctx.beginPath();
491
+ ctx.ellipse(faceX + faceWidth * 0.5, faceY + faceHeight * 0.75,
492
+ faceWidth * 0.15, faceHeight * 0.08, 0, 0, Math.PI);
493
+ ctx.stroke();
494
+ }
495
+
496
+ function resetUI() {
497
+ fileInput.value = '';
498
+ previewContainer.classList.add('hidden');
499
+ faceDataContainer.classList.add('hidden');
500
+ loadingContainer.classList.add('hidden');
501
+ uploadContainer.classList.remove('hidden');
502
+ metricsContent.classList.add('hidden');
503
+ metricsPlaceholder.classList.remove('hidden');
504
+ multipleFacesAlert.classList.add('hidden');
505
+ progressBar.style.width = '0%';
506
+ }
507
+
508
+ // For demo purposes, let's simulate some random data generation
509
+ const scoreElements = {
510
+ 'overall-score-text': [75, 95],
511
+ 'horizontal-symmetry': [85, 98],
512
+ 'vertical-symmetry': [80, 96],
513
+ 'forehead-midface-score': ['1.58 (Near Ideal)', '1.62 (Ideal)'],
514
+ 'midface-chin-score': ['1.54 (Good)', '1.62 (Perfect)'],
515
+ 'nose-ratio-score': ['0.68 (Near Ideal)', '0.72 (Ideal)'],
516
+ 'eye-shape': ['Round', 'Almond', 'Deep-set', 'Downturned'],
517
+ 'eye-spacing': ['Slightly Wide', 'Ideal', 'Slightly Narrow'],
518
+ 'eye-balance': ['Good', 'Perfect', 'Slightly Asymmetric'],
519
+ 'iris-ratio': ['75%', '82%', '89%', '93%'],
520
+ 'cupids-bow-score': ['Subtle', 'Defined', 'Very Defined', 'Perfect'],
521
+ 'lip-ratio-score': ['1:1.4', '1:1.6 (Ideal)', '1:1.8'],
522
+ 'lip-width-score': ['1.1x', '1.3x (Perfect)', '1.5x'],
523
+ 'face-shape': ['Oval', 'Round', 'Square', 'Heart', 'Diamond'],
524
+ 'skin-tone': ['Pale (Type II)', 'Light Beige (Type IV)', 'Olive (Type V)', 'Deep Brown (Type VI)'],
525
+ 'skin-quality': ['Even tone', 'Minor pigmentation', 'Some redness', 'Clear']
526
+ };
527
+
528
+ const faceShapeDescriptions = {
529
+ 'Oval': 'Considered the most versatile and balanced shape',
530
+ 'Round': 'Soft features with similar width and length',
531
+ 'Square': 'Strong jawline with angular features',
532
+ 'Heart': 'Wider forehead tapering to a pointed chin',
533
+ 'Diamond': 'Narrow forehead and jaw with wide cheekbones'
534
+ };
535
+
536
+ // Generate random demo data
537
+ if (metricsContent) {
538
+ for (const [id, values] of Object.entries(scoreElements)) {
539
+ const element = document.getElementById(id);
540
+ if (element) {
541
+ if (typeof values[0] === 'number') {
542
+ // Handle numeric ranges
543
+ const val = Math.floor(Math.random() * (values[1] - values[0] + 1)) + values[0];
544
+ if (id === 'overall-score-text') {
545
+ element.textContent = val;
546
+ document.getElementById('overall-score-bar').style.width = `${val}%`;
547
+
548
+ // Set rating text
549
+ let rating, ratingClass;
550
+ if (val >= 90) {
551
+ rating = 'Excellent'; ratingClass = 'bg-green-100 text-green-700';
552
+ } else if (val >= 75) {
553
+ rating = 'Great'; ratingClass = 'bg-blue-100 text-blue-700';
554
+ } else if (val >= 60) {
555
+ rating = 'Good'; ratingClass = 'bg-yellow-100 text-yellow-700';
556
+ } else {
557
+ rating = 'Average'; ratingClass = 'bg-gray-100 text-gray-700';
558
+ }
559
+
560
+ const ratingElement = document.getElementById('overall-rating');
561
+ ratingElement.textContent = rating;
562
+ ratingElement.className = `text-sm py-1 px-3 rounded-full ${ratingClass}`;
563
+
564
+ // Set feedback
565
+ const feedbacks = [
566
+ "Your facial features show excellent harmony and balance, well above average.",
567
+ "Your face has very pleasing proportions that match beauty standards.",
568
+ "Good overall symmetry and features, with some room for perfect alignment.",
569
+ "Average features with some strong points and some areas that could be more balanced."
570
+ ];
571
+ document.getElementById('overall-feedback').textContent = feedbacks[Math.min(3, Math.floor((100-val)/15))];
572
+ } else {
573
+ element.textContent = typeof val === 'number' ? `${val}%` : val;
574
+ if (id.includes('symmetry')) {
575
+ const bar = element.closest('div').querySelector('.h-2 > div');
576
+ if (bar) bar.style.width = `${val}%`;
577
+ }
578
+ }
579
+ } else {
580
+ // Handle string arrays
581
+ const val = values[Math.floor(Math.random() * values.length)];
582
+ element.textContent = val;
583
+
584
+ // Special handling for face shape
585
+ if (id === 'face-shape') {
586
+ document.getElementById('face-shape-desc').textContent = faceShapeDescriptions[val] || '';
587
+ }
588
+ }
589
+ }
590
+ }
591
+ }
592
+ });
593
+ </script>
594
+ </body>
595
  </html>