Spaces:
Running
Running
File size: 10,371 Bytes
deddb46 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Application de Reconnaissance Faciale</title>
<!-- Tailwind CSS -->
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<!-- Font Awesome (pour les icônes) -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">
<style>
/* Styles personnalisés (si nécessaire) */
.preview-image {
background-size: cover;
background-position: center;
min-height: 150px;
}
.github-link {
position: fixed;
bottom: 20px;
right: 20px;
padding: 10px;
background-color: #333;
color: white;
border-radius: 5px;
text-decoration: none;
display: flex;
align-items: center;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.github-link i {
margin-right: 8px;
font-size: 20px;
}
.github-link:hover {
background-color: #555;
}
</style>
</head>
<body class="bg-gray-100 font-sans">
<div class="container mx-auto p-4">
<h1 class="text-4xl font-bold text-center text-blue-700 mb-8">
<i class="fas fa-user-check text-5xl mr-3"></i>
Reconnaissance et Comparaison Faciale
</h1>
<div class="grid md:grid-cols-2 gap-8">
<!-- Section de sélection d'images -->
<div class="bg-white p-6 rounded-lg shadow-lg">
<h2 class="text-2xl font-semibold mb-4 text-gray-700">
<i class="fas fa-images text-blue-500 mr-2"></i>
Sélectionner des images
</h2>
<input type="file" id="imageUpload" accept="image/*" class="mb-4 hidden">
<label for="imageUpload" class="cursor-pointer bg-blue-500 hover:bg-blue-600 text-white font-bold py-3 px-6 rounded-lg inline-flex items-center transition duration-200 ease-in-out">
<i class="fas fa-upload mr-2"></i>
Choisir un fichier
</label>
<button id="cameraButton" class="bg-green-500 hover:bg-green-600 text-white font-bold py-3 px-6 rounded-lg ml-4 inline-flex items-center transition duration-200 ease-in-out">
<i class="fas fa-camera mr-2"></i>
Utiliser la caméra
</button>
<video id="videoFeed" width="320" height="240" autoplay class="hidden mt-4 rounded-lg"></video>
<canvas id="canvas" width="320" height="240" class="hidden"></canvas>
<!-- Prévisualisation des images -->
<div class="grid grid-cols-2 gap-4 mt-6">
<div id="imagePreview1" class="w-full aspect-w-1 aspect-h-1 rounded-lg overflow-hidden preview-image"></div>
<div id="imagePreview2" class="w-full aspect-w-1 aspect-h-1 rounded-lg overflow-hidden preview-image"></div>
</div>
</div>
<!-- Section des résultats -->
<div class="bg-white p-6 rounded-lg shadow-lg">
<h2 class="text-2xl font-semibold mb-4 text-gray-700">
<i class="fas fa-poll-h text-blue-500 mr-2"></i>
Résultats de la comparaison
</h2>
<div id="results" class="text-center">
<p class="text-gray-600">Veuillez sélectionner des images ou utiliser la caméra pour commencer.</p>
</div>
<button id="compareButton" class="hidden bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded mt-4">
Comparer les visages
</button>
</div>
</div>
</div>
<!-- Lien GitHub -->
<a href="https://github.com/Yusufibin" target="_blank" class="github-link">
<i class="fab fa-github"></i>
<span>Yusufibin</span>
</a>
<script>
const imageUpload = document.getElementById('imageUpload');
const cameraButton = document.getElementById('cameraButton');
const videoFeed = document.getElementById('videoFeed');
const canvas = document.getElementById('canvas');
const imagePreview1 = document.getElementById('imagePreview1');
const imagePreview2 = document.getElementById('imagePreview2');
const resultsDiv = document.getElementById('results');
const compareButton = document.getElementById('compareButton');
const API_BASE_URL = 'http://127.0.0.1:5000'; // URL de base de ton API Flask
let usingCamera = false;
let currentImage = 1; // 1 or 2 pour suivre quelle image prévisualiser
// Gestionnaire pour le téléchargement de fichiers
imageUpload.addEventListener('change', async (event) => {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
if (currentImage === 1) {
imagePreview1.style.backgroundImage = `url(${e.target.result})`;
currentImage = 2;
} else {
imagePreview2.style.backgroundImage = `url(${e.target.result})`;
currentImage = 1;
}
compareButton.classList.remove('hidden'); // Affiche le bouton de comparaison
};
reader.readAsDataURL(file);
}
});
// Gestionnaire pour le bouton de la caméra
cameraButton.addEventListener('click', async () => {
usingCamera = !usingCamera;
if (usingCamera) {
cameraButton.textContent = 'Arrêter la caméra';
try {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
videoFeed.srcObject = stream;
videoFeed.classList.remove('hidden');
} catch (err) {
console.error("Erreur lors de l'accès à la caméra :", err);
}
} else {
cameraButton.textContent = 'Utiliser la caméra';
const tracks = videoFeed.srcObject.getTracks();
tracks.forEach(track => track.stop());
videoFeed.classList.add('hidden');
}
});
// Capture d'image à partir de la caméra
function captureImageFromCamera() {
const context = canvas.getContext('2d');
context.drawImage(videoFeed, 0, 0, canvas.width, canvas.height);
const imageDataURL = canvas.toDataURL('image/png');
if (currentImage === 1) {
imagePreview1.style.backgroundImage = `url(${imageDataURL})`;
currentImage = 2;
} else {
imagePreview2.style.backgroundImage = `url(${imageDataURL})`;
currentImage = 1;
}
compareButton.classList.remove('hidden'); // Affiche le bouton de comparaison
}
// Gestionnaire pour le bouton de comparaison
compareButton.addEventListener('click', () => {
if (imagePreview1.style.backgroundImage && imagePreview2.style.backgroundImage) {
const formData = new FormData();
const imageData1 = dataURLtoBlob(imagePreview1.style.backgroundImage.slice(5, -2));
const imageData2 = dataURLtoBlob(imagePreview2.style.backgroundImage.slice(5, -2));
formData.append('image1', imageData1, 'image1.png');
formData.append('image2', imageData2, 'image2.png');
fetch(`${API_BASE_URL}/verify`, {
method: 'POST',
body: formData,
})
.then(response => response.json())
.then(data => {
displayResults(data);
})
.catch(error => {
console.error('Erreur lors de la comparaison des visages:', error);
resultsDiv.innerHTML = `<p>Erreur lors de la comparaison.</p>`;
});
} else {
alert('Veuillez télécharger deux images pour la comparaison.');
}
});
// Fonction pour convertir une URL de données en Blob
function dataURLtoBlob(dataURL) {
const parts = dataURL.split(';base64,');
const contentType = parts[0].split(':')[1];
const raw = window.atob(parts[1]);
const rawLength = raw.length;
const uInt8Array = new Uint8Array(rawLength);
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], { type: contentType });
}
// Fonction pour afficher les résultats de la comparaison
function displayResults(data) {
let resultHTML = '';
if (data.error) {
resultHTML = `<p class="text-red-600">${data.error}</p>`;
} else {
const similarity = data.verified ? 'Visages similaires' : 'Visages différents';
resultHTML += `<p class="text-lg ${data.verified ? 'text-green-600' : 'text-red-600'}">${similarity}</p>`;
if (data.distance !== undefined && data.threshold !== undefined) {
resultHTML += `<p class="mt-2">Distance : ${data.distance.toFixed(4)}</p>`;
resultHTML += `<p>Seuil de similarité : ${data.threshold.toFixed(4)}</p>`;
}
if (data.image1_url && data.image2_url) {
resultHTML += `<img src="${API_BASE_URL}/${data.image1_url}" alt="Image 1" class="w-32 h-32 mt-4 rounded-lg">`;
resultHTML += `<img src="${API_BASE_URL}/${data.image2_url}" alt="Image 2" class="w-32 h-32 mt-4 rounded-lg">`;
}
}
resultsDiv.innerHTML = resultHTML;
}
</script>
</body>
</html> |