-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathblinkPrediction.js
80 lines (70 loc) · 2.11 KB
/
blinkPrediction.js
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
import * as faceLandmarksDetection from '@tensorflow-models/face-landmarks-detection';
import '@tensorflow/tfjs-backend-webgl';
const EAR_THRESHOLD = 0.27;
let model;
let event;
let blinkCount = 0;
// Loading model from Tensorflow.js
const loadModel = async () => {
model = await faceLandmarksDetection.load(
faceLandmarksDetection.SupportedPackages.mediapipeFacemesh,
{ maxFaces: 1 },
);
};
// Calculate the position of eyelid to predict a blink
function getEAR(upper, lower) {
function getEucledianDistance(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
return (
(getEucledianDistance(upper[5][0], upper[5][1], lower[4][0], lower[4][1])
+ getEucledianDistance(
upper[3][0],
upper[3][1],
lower[2][0],
lower[2][1],
))
/ (2
* getEucledianDistance(upper[0][0], upper[0][1], upper[8][0], upper[8][1]))
);
}
async function startPrediciton(video) {
// Sending video to model for prediction
const predictions = await model.estimateFaces({
input: video,
});
if (predictions.length > 0) {
predictions.forEach((prediction) => {
// Right eye parameters
const lowerRight = prediction.annotations.rightEyeUpper0;
const upperRight = prediction.annotations.rightEyeLower0;
const rightEAR = getEAR(upperRight, lowerRight);
// Left eye parameters
const lowerLeft = prediction.annotations.leftEyeUpper0;
const upperLeft = prediction.annotations.leftEyeLower0;
const leftEAR = getEAR(upperLeft, lowerLeft);
// True if the eye is closed
const blinked = leftEAR <= EAR_THRESHOLD && rightEAR <= EAR_THRESHOLD;
// Determine how long you blinked
if (blinked) {
event = {
shortBlink: false,
longBlink: false,
};
blinkCount += 1;
} else {
event = {
shortBlink: blinkCount <= 5 && blinkCount !== 0,
longBlink: blinkCount > 5,
};
blinkCount = 0;
}
});
}
return event;
}
const blinkCapture = {
loadModel,
startPrediciton,
};
export default blinkCapture;