Spaces:
Sleeping
Sleeping
<html lang="fr"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Système de Reconnaissance Faciale Pro</title> | |
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet"> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"> | |
<style> | |
@keyframes pulse-border { | |
0% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.7); } | |
70% { box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); } | |
100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); } | |
} | |
.preview-container { | |
position: relative; | |
aspect-ratio: 1; | |
background: #f8fafc; | |
border-radius: 1rem; | |
overflow: hidden; | |
transition: all 0.3s ease; | |
} | |
.preview-image { | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background-size: cover; | |
background-position: center; | |
transition: transform 0.3s ease; | |
} | |
.preview-container:hover .preview-image { | |
transform: scale(1.05); | |
} | |
.loading-overlay { | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background: rgba(0, 0, 0, 0.7); | |
display: none; | |
justify-content: center; | |
align-items: center; | |
z-index: 1000; | |
} | |
.progress-ring { | |
animation: spin 2s linear infinite; | |
width: 50px; | |
height: 50px; | |
} | |
@keyframes spin { | |
100% { transform: rotate(360deg); } | |
} | |
.btn-primary { | |
background: linear-gradient(135deg, #4f46e5, #3b82f6); | |
transition: all 0.3s ease; | |
animation: pulse-border 2s infinite; | |
} | |
.btn-primary:hover { | |
transform: translateY(-2px); | |
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4); | |
} | |
.result-card { | |
transition: all 0.3s ease; | |
transform-origin: center; | |
} | |
.result-card.show { | |
animation: bounceIn 0.6s; | |
} | |
.camera-feed { | |
border-radius: 1rem; | |
transform: scaleX(-1); | |
transition: all 0.3s ease; | |
} | |
.github-corner { | |
position: fixed; | |
top: 0; | |
right: 0; | |
width: 80px; | |
height: 80px; | |
transition: transform 0.3s ease; | |
} | |
.github-corner:hover { | |
transform: scale(1.1); | |
} | |
</style> | |
</head> | |
<body class="bg-gradient-to-br from-gray-100 to-gray-200 min-h-screen font-sans"> | |
<div class="loading-overlay"> | |
<svg class="progress-ring text-blue-500" viewBox="0 0 50 50"> | |
<circle cx="25" cy="25" r="20" fill="none" stroke="currentColor" stroke-width="5" stroke-dasharray="80, 200"/> | |
</svg> | |
</div> | |
<nav class="bg-white shadow-lg"> | |
<div class="container mx-auto px-6 py-4"> | |
<div class="flex items-center justify-between"> | |
<div class="flex items-center"> | |
<i class="fas fa-brain text-4xl text-blue-600 mr-3"></i> | |
<h1 class="text-2xl font-bold text-gray-800">FaceAI Pro</h1> | |
</div> | |
<div class="flex items-center space-x-4"> | |
<button class="text-gray-600 hover:text-blue-600 transition-colors"> | |
<i class="fas fa-question-circle text-xl"></i> | |
</button> | |
<button class="text-gray-600 hover:text-blue-600 transition-colors"> | |
<i class="fas fa-cog text-xl"></i> | |
</button> | |
</div> | |
</div> | |
</div> | |
</nav> | |
<main class="container mx-auto p-6"> | |
<div class="grid md:grid-cols-2 gap-8"> | |
<!-- Section de capture --> | |
<div class="bg-white rounded-xl shadow-xl p-6 animate__animated animate__fadeInLeft"> | |
<h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center"> | |
<i class="fas fa-camera text-blue-600 mr-3"></i> | |
Capture d'Images | |
</h2> | |
<div class="space-y-4"> | |
<div class="flex space-x-4"> | |
<button id="uploadBtn" class="btn-primary text-white px-6 py-3 rounded-lg flex items-center"> | |
<i class="fas fa-upload mr-2"></i> | |
Importer | |
</button> | |
<button id="cameraBtn" class="bg-green-500 hover:bg-green-600 text-white px-6 py-3 rounded-lg flex items-center transition-all"> | |
<i class="fas fa-video mr-2"></i> | |
Caméra | |
</button> | |
</div> | |
<input type="file" id="fileInput" class="hidden" accept="image/*"> | |
<video id="video" class="camera-feed w-full hidden" autoplay></video> | |
<div class="grid grid-cols-2 gap-4"> | |
<div class="preview-container shadow-lg"> | |
<div id="preview1" class="preview-image"></div> | |
<div class="absolute bottom-2 right-2"> | |
<button class="bg-red-500 text-white p-2 rounded-full opacity-0 transition-opacity hover:opacity-100"> | |
<i class="fas fa-times"></i> | |
</button> | |
</div> | |
</div> | |
<div class="preview-container shadow-lg"> | |
<div id="preview2" class="preview-image"></div> | |
<div class="absolute bottom-2 right-2"> | |
<button class="bg-red-500 text-white p-2 rounded-full opacity-0 transition-opacity hover:opacity-100"> | |
<i class="fas fa-times"></i> | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Section des résultats --> | |
<div class="bg-white rounded-xl shadow-xl p-6 animate__animated animate__fadeInRight"> | |
<h2 class="text-2xl font-bold text-gray-800 mb-6 flex items-center"> | |
<i class="fas fa-chart-bar text-blue-600 mr-3"></i> | |
Résultats | |
</h2> | |
<div id="results" class="result-card p-4 rounded-lg bg-gray-50"> | |
<div class="text-center text-gray-500"> | |
<i class="fas fa-upload text-4xl mb-3"></i> | |
<p>Importez ou capturez deux images pour démarrer l'analyse</p> | |
</div> | |
</div> | |
<button id="compareBtn" class="btn-primary w-full mt-6 py-3 rounded-lg text-white font-semibold hidden"> | |
<i class="fas fa-sync-alt mr-2"></i> | |
Lancer la comparaison | |
</button> | |
</div> | |
</div> | |
</main> | |
<!-- GitHub Corner --> | |
<a href="https://github.com/Yusufibin" class="github-corner" target="_blank"> | |
<svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;"> | |
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path> | |
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path> | |
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path> | |
</svg> | |
</a> | |
<script> | |
// Le code JavaScript reste similaire mais avec des améliorations pour les animations | |
// et la gestion des états de l'interface... | |
// Exemple d'amélioration pour l'affichage des résultats | |
function showResults(data) { | |
const resultsDiv = document.getElementById('results'); | |
resultsDiv.classList.remove('show'); | |
setTimeout(() => { | |
resultsDiv.innerHTML = ` | |
<div class="text-center"> | |
<div class="text-4xl mb-4 ${data.verified ? 'text-green-500' : 'text-red-500'}"> | |
<i class="fas ${data.verified ? 'fa-check-circle' : 'fa-times-circle'}"></i> | |
</div> | |
<h3 class="text-xl font-bold mb-2"> | |
${data.verified ? 'Visages identiques' : 'Visages différents'} | |
</h3> | |
<div class="space-y-2"> | |
<p>Similarité: ${(data.similarity * 100).toFixed(1)}%</p> | |
<div class="w-full bg-gray-200 rounded-full h-2.5"> | |
<div class="bg-blue-600 h-2.5 rounded-full" | |
style="width: ${data.similarity * 100}%"></div> | |
</div> | |
</div> | |
</div> | |
`; | |
resultsDiv.classList.add('show'); | |
}, 300); | |
} | |
// Ajout des animations pour le chargement | |
function showLoading() { | |
document.querySelector('.loading-overlay').style.display = 'flex'; | |
} | |
function hideLoading() { | |
document.querySelector('.loading-overlay').style.display = 'none'; | |
} | |
// Le reste du code JavaScript original avec les gestionnaires d'événements... | |
</script> | |
</body> | |
</html> |