forked from WebDevSimplified/Face-Detection-JavaScript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
134 lines (111 loc) · 4.66 KB
/
Copy pathscript.js
File metadata and controls
134 lines (111 loc) · 4.66 KB
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
// 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;
// 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);
}
}
// 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);
}
}
// 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();