Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Smart Home Security - Face Recognition</title> | |
<script src="https://cdn.jsdelivr.net/npm/face-api.js"></script> | |
<style> | |
:root { | |
--primary: #2962ff; | |
--dark: #1a237e; | |
--light: #f5f5f5; | |
--success: #00c853; | |
--danger: #d50000; | |
} | |
* { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
font-family: 'Segoe UI', sans-serif; | |
} | |
body { | |
background: var(--light); | |
min-height: 100vh; | |
} | |
.container { | |
max-width: 1200px; | |
margin: 0 auto; | |
padding: 20px; | |
} | |
.header { | |
background: var(--dark); | |
color: white; | |
padding: 1rem; | |
border-radius: 10px; | |
margin-bottom: 2rem; | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
} | |
.main-content { | |
display: grid; | |
grid-template-columns: 2fr 1fr; | |
gap: 2rem; | |
} | |
.video-container { | |
background: white; | |
padding: 20px; | |
border-radius: 10px; | |
box-shadow: 0 4px 6px rgba(0,0,0,0.1); | |
} | |
#video { | |
width: 100%; | |
border-radius: 5px; | |
} | |
.controls { | |
background: white; | |
padding: 20px; | |
border-radius: 10px; | |
box-shadow: 0 4px 6px rgba(0,0,0,0.1); | |
} | |
.status { | |
text-align: center; | |
padding: 1rem; | |
margin: 1rem 0; | |
border-radius: 5px; | |
font-weight: bold; | |
} | |
.status.authorized { | |
background: var(--success); | |
color: white; | |
} | |
.status.unauthorized { | |
background: var(--danger); | |
color: white; | |
} | |
.btn { | |
background: var(--primary); | |
color: white; | |
border: none; | |
padding: 10px 20px; | |
border-radius: 5px; | |
cursor: pointer; | |
transition: 0.3s; | |
width: 100%; | |
margin: 5px 0; | |
} | |
.btn:hover { | |
background: var(--dark); | |
} | |
.registered-faces { | |
margin-top: 2rem; | |
} | |
.face-item { | |
display: flex; | |
align-items: center; | |
padding: 10px; | |
background: #f8f9fa; | |
margin: 5px 0; | |
border-radius: 5px; | |
} | |
.face-item img { | |
width: 50px; | |
height: 50px; | |
border-radius: 50%; | |
margin-right: 10px; | |
} | |
.loading { | |
position: fixed; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
background: rgba(0,0,0,0.8); | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
color: white; | |
font-size: 1.2rem; | |
} | |
@keyframes spin { | |
to { transform: rotate(360deg); } | |
} | |
.spinner { | |
width: 40px; | |
height: 40px; | |
border: 4px solid #f3f3f3; | |
border-top: 4px solid var(--primary); | |
border-radius: 50%; | |
animation: spin 1s linear infinite; | |
margin-right: 10px; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="header"> | |
<h1>🏠 Smart Home Security</h1> | |
<div>System Status: <span id="system-status">Active</span></div> | |
</div> | |
<div class="main-content"> | |
<div class="video-container"> | |
<video id="video" autoplay muted></video> | |
<div class="status" id="access-status">Waiting for face detection...</div> | |
</div> | |
<div class="controls"> | |
<h2>Control Panel</h2> | |
<button class="btn" id="add-face">Add New Face</button> | |
<button class="btn" id="test-detection">Test Detection</button> | |
<div class="registered-faces"> | |
<h3>Registered Users</h3> | |
<div id="faces-list"> | |
<!-- Registered faces will be listed here --> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="loading" id="loading" style="display: none;"> | |
<div class="spinner"></div> | |
Loading face detection models... | |
</div> | |
<script> | |
// Mock database of registered faces | |
const registeredFaces = [ | |
{ id: 1, name: 'John Doe', image: 'data:image/jpeg;base64,/9j/4AAQSkZJRg==' }, | |
{ id: 2, name: 'Jane Smith', image: 'data:image/jpeg;base64,/9j/4AAQSkZJRg==' } | |
]; | |
// Initialize face detection | |
async function initFaceDetection() { | |
try { | |
document.getElementById('loading').style.display = 'flex'; | |
// Load face-api models (in real implementation) | |
// await faceapi.nets.tinyFaceDetector.loadFromUri('/models'); | |
// await faceapi.nets.faceLandmark68Net.loadFromUri('/models'); | |
// await faceapi.nets.faceRecognitionNet.loadFromUri('/models'); | |
// Access webcam | |
const video = document.getElementById('video'); | |
const stream = await navigator.mediaDevices.getUserMedia({ video: true }); | |
video.srcObject = stream; | |
document.getElementById('loading').style.display = 'none'; | |
} catch (error) { | |
console.error('Error initializing face detection:', error); | |
document.getElementById('loading').style.display = 'none'; | |
} | |
} | |
// Simulate face detection | |
function detectFace() { | |
const accessStatus = document.getElementById('access-status'); | |
const isAuthorized = Math.random() > 0.5; // Simulate detection | |
if (isAuthorized) { | |
accessStatus.textContent = 'Access Granted ✅'; | |
accessStatus.className = 'status authorized'; | |
} else { | |
accessStatus.textContent = 'Access Denied ❌'; | |
accessStatus.className = 'status unauthorized'; | |
} | |
} | |
// Display registered faces | |
function displayRegisteredFaces() { | |
const facesList = document.getElementById('faces-list'); | |
facesList.innerHTML = registeredFaces.map(face => ` | |
<div class="face-item"> | |
<img src="${face.image}" alt="${face.name}"> | |
<div> | |
<h4>${face.name}</h4> | |
<small>ID: ${face.id}</small> | |
</div> | |
</div> | |
`).join(''); | |
} | |
// Event listeners | |
document.getElementById('add-face').addEventListener('click', () => { | |
const name = prompt('Enter name for new face:'); | |
if (name) { | |
registeredFaces.push({ | |
id: registeredFaces.length + 1, | |
name, | |
image: 'data:image/jpeg;base64,/9j/4AAQSkZJRg==' | |
}); | |
displayRegisteredFaces(); | |
} | |
}); | |
document.getElementById('test-detection').addEventListener('click', detectFace); | |
// Initialize application | |
window.addEventListener('load', () => { | |
initFaceDetection(); | |
displayRegisteredFaces(); | |
}); | |
</script> | |
</body> | |
</html> |