Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,146 @@
<body>
<video id="video" width="720" height="560" autoplay muted></video>
</body>
</html>

const video = document.getElementById('video')

Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri('/models'),
faceapi.nets.faceLandmark68Net.loadFromUri('/models'),
faceapi.nets.faceRecognitionNet.loadFromUri('/models'),
faceapi.nets.faceExpressionNet.loadFromUri('/models')
]).then(startVideo)

function startVideo() {
navigator.getUserMedia(
{ video: {} },
stream => video.srcObject = stream,
err => console.error(err)
)
}

video.addEventListener('play', () => {
const canvas = faceapi.createCanvasFromMedia(video)
document.body.append(canvas)
const displaySize = { width: video.width, height: video.height }
faceapi.matchDimensions(canvas, displaySize)
setInterval(async () => {
const detections = await faceapi.detectAllFaces(video, new faceapi.TinyFaceDetectorOptions()).withFaceLandmarks().withFaceExpressions()
const resizedDetections = faceapi.resizeResults(detections, displaySize)
canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height)
faceapi.draw.drawDetections(canvas, resizedDetections)
faceapi.draw.drawFaceLandmarks(canvas, resizedDetections)
faceapi.draw.drawFaceExpressions(canvas, resizedDetections)
}, 100)
}) make complete project in this code
Complete Face Detection Project
Here's a complete face detection project using face-api.js with HTML, CSS, and JavaScript all in one file:

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Face Detection with face-api.js</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/face-api.min.js"></script>
<style>
body {
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
background-color: #f0f2f5;
font-family: Arial, sans-serif;
}

.container {
position: relative;
margin: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 8px;
overflow: hidden;
}

video {
display: block;
background: #000;
}

canvas {
position: absolute;
top: 0;
left: 0;
}

.controls {
margin-top: 20px;
display: flex;
gap: 10px;
}

button {
padding: 10px 15px;
background-color: #4267B2;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
}

button:hover {
background-color: #365899;
}

.loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 18px;
}

h1 {
color: #4267B2;
margin-bottom: 10px;
}

.stats {
margin-top: 10px;
padding: 10px;
background-color: white;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
</style>
</head>
<body>
<h1>Face Detection Demo</h1>
<p>Real-time face detection with expressions and landmarks</p>

<div class="container">
<video id="video" width="720" height="560" autoplay muted></video>
<div id="loading" class="loading">Loading models...</div>
</div>

<div class="stats" id="stats">
No faces detected
</div>

<div class="controls">
<button id="startBtn">Start Camera</button>
<button id="stopBtn" disabled>Stop Camera</button>
</div>

<script src="script.js"></script>
</body>
</html>
159 changes: 131 additions & 28 deletions script.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,134 @@
const video = document.getElementById('video')
// DOM elements
const video = document.getElementById('video');
const startBtn = document.getElementById('startBtn');
const stopBtn = document.getElementById('stopBtn');
const loadingText = document.getElementById('loading');
const statsDiv = document.getElementById('stats');

let stream = null;
let detectionInterval = null;
let canvas = null;

Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri('/models'),
faceapi.nets.faceLandmark68Net.loadFromUri('/models'),
faceapi.nets.faceRecognitionNet.loadFromUri('/models'),
faceapi.nets.faceExpressionNet.loadFromUri('/models')
]).then(startVideo)
// Load models
async function loadModels() {
try {
await Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri('https://justadudewhohacks.github.io/face-api.js/models'),
faceapi.nets.faceLandmark68Net.loadFromUri('https://justadudewhohacks.github.io/face-api.js/models'),
faceapi.nets.faceRecognitionNet.loadFromUri('https://justadudewhohacks.github.io/face-api.js/models'),
faceapi.nets.faceExpressionNet.loadFromUri('https://justadudewhohacks.github.io/face-api.js/models')
]);

loadingText.textContent = "Models loaded. Click 'Start Camera' to begin.";
startBtn.disabled = false;
} catch (error) {
loadingText.textContent = "Error loading models. Please check console.";
console.error(error);
}
}

function startVideo() {
navigator.getUserMedia(
{ video: {} },
stream => video.srcObject = stream,
err => console.error(err)
)
}
// Start video stream
async function startVideo() {
try {
stream = await navigator.mediaDevices.getUserMedia({ video: {} });
video.srcObject = stream;
startBtn.disabled = true;
stopBtn.disabled = false;
loadingText.style.display = "none";
} catch (err) {
loadingText.textContent = "Could not access camera. Please ensure you've granted permissions.";
console.error(err);
}
}

video.addEventListener('play', () => {
const canvas = faceapi.createCanvasFromMedia(video)
document.body.append(canvas)
const displaySize = { width: video.width, height: video.height }
faceapi.matchDimensions(canvas, displaySize)
setInterval(async () => {
const detections = await faceapi.detectAllFaces(video, new faceapi.TinyFaceDetectorOptions()).withFaceLandmarks().withFaceExpressions()
const resizedDetections = faceapi.resizeResults(detections, displaySize)
canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height)
faceapi.draw.drawDetections(canvas, resizedDetections)
faceapi.draw.drawFaceLandmarks(canvas, resizedDetections)
faceapi.draw.drawFaceExpressions(canvas, resizedDetections)
}, 100)
})
// Stop video stream
function stopVideo() {
if (stream) {
stream.getTracks().forEach(track => track.stop());
video.srcObject = null;
stream = null;

if (canvas) {
canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
document.body.removeChild(canvas);
canvas = null;
}

if (detectionInterval) {
clearInterval(detectionInterval);
detectionInterval = null;
}

startBtn.disabled = false;
stopBtn.disabled = true;
statsDiv.textContent = "Camera stopped";
loadingText.style.display = "block";
loadingText.textContent = "Click 'Start Camera' to begin again.";
}
}

// Setup face detection when video plays
video.addEventListener('play', () => {
if (!canvas) {
canvas = faceapi.createCanvasFromMedia(video);
document.querySelector('.container').append(canvas);
}

const displaySize = { width: video.width, height: video.height };
faceapi.matchDimensions(canvas, displaySize);

if (detectionInterval) {
clearInterval(detectionInterval);
}

detectionInterval = setInterval(async () => {
const detections = await faceapi.detectAllFaces(
video,
new faceapi.TinyFaceDetectorOptions()
).withFaceLandmarks().withFaceExpressions();

const resizedDetections = faceapi.resizeResults(detections, displaySize);

// Clear canvas before drawing new detections
canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);

// Draw detections
faceapi.draw.drawDetections(canvas, resizedDetections);
faceapi.draw.drawFaceLandmarks(canvas, resizedDetections);
faceapi.draw.drawFaceExpressions(canvas, resizedDetections);

// Update stats
updateStats(detections);
}, 100);
});

// Update statistics display
function updateStats(detections) {
if (detections.length === 0) {
statsDiv.textContent = "No faces detected";
return;
}

let statsText = `Detected ${detections.length} face${detections.length > 1 ? 's' : ''}:<br>`;

detections.forEach((detection, index) => {
const expressions = detection.expressions;
const dominantExpression = Object.entries(expressions).reduce(
(max, [key, value]) => value > max.value ? {key, value} : max,
{key: '', value: 0}
);

statsText += `<br>Face ${index + 1}:<br>`;
statsText += `- Dominant expression: ${dominantExpression.key} (${Math.round(dominantExpression.value * 100)}%)<br>`;
statsText += `- Detection score: ${Math.round(detection.detection.score * 100)}%`;
});

statsDiv.innerHTML = statsText;
}

// Event listeners
startBtn.addEventListener('click', startVideo);
stopBtn.addEventListener('click', stopVideo);

// Initialize
loadModels();