xxxxxxxxxx
127
let facemesh;
let video;
let predictions = [];
let faceLabel = "";
let expression;
let supriseImg, smileImg, neutralImg;
function preload() {
// preload() runs once
supriseImg = loadImage("suprise.png");
smileImg = loadImage("smile.png");
neutralImg = loadImage("neutral.png");
}
function setup() {
createCanvas(640, 480);
video = createCapture(VIDEO);
video.size(width, height);
facemesh = ml5.facemesh(video, modelReady);
// This sets up an event that fills the global variable "predictions"
// with an array every time new predictions are made
facemesh.on("predict", (results) => {
predictions = results;
});
// Hide the video element, and just show the canvas
video.hide();
}
function modelReady() {
console.log("Model ready!");
}
function draw() {
push();
translate(width, 0);
scale(-1, 1);
image(video, 0, 0, width, height);
// Display the face label on the canvas
fill(255, 0, 255);
// We can call both functions to draw all keypoints
drawKeypoints();
showExpression()
pop();
noStroke();
textSize(32);
textAlign(CENTER, CENTER);
text(faceLabel, width / 2, height / 2);
detectExpressions();
console.log(predictions);
}
function detectExpressions() {
if (predictions.length > 0) {
const keypoints = predictions[0].scaledMesh;
// Relevant landmarks for smile detection
const leftCornerMouth = keypoints[61];
const rightCornerMouth = keypoints[291];
const upperLipTopCenter = keypoints[13]; // Considered as a center top of the mouth
const lowerLipBottomCenter = keypoints[14]; // Considered as a center bottom of the mouth
// Calculate the center point of the mouth
const mouthCenter = [
(upperLipTopCenter[0] + lowerLipBottomCenter[0]) / 2,
(upperLipTopCenter[1] + lowerLipBottomCenter[1]) / 2,
];
// Calculate distances to determine mouth curvature
const distanceLeftCorner = dist(leftCornerMouth[0], leftCornerMouth[1], mouthCenter[0], mouthCenter[1]);
const distanceRightCorner = dist(rightCornerMouth[0], rightCornerMouth[1], mouthCenter[0], mouthCenter[1]);
const mouthWidth = dist(leftCornerMouth[0], leftCornerMouth[1], rightCornerMouth[0], rightCornerMouth[1]);
// Smile detection criteria based on the curvature and width of the mouth
const isSmiling = (distanceLeftCorner + distanceRightCorner) / 2 > mouthWidth * 0.3; // Adjust threshold as needed
// Existing code for other expressions
let mouthOpenness = dist(keypoints[13][0], keypoints[13][1], keypoints[14][0], keypoints[14][1]);
const surpriseThresholdMouth = 20;
const eyebrowRaiseLeft = dist(keypoints[105][0], keypoints[105][1], keypoints[107][0], keypoints[107][1]);
const eyebrowRaiseRight = dist(keypoints[334][0], keypoints[334][1], keypoints[336][0], keypoints[336][1]);
const eyebrowRaiseThreshold = 10;
if (mouthOpenness > surpriseThresholdMouth && (eyebrowRaiseLeft > eyebrowRaiseThreshold && eyebrowRaiseRight > eyebrowRaiseThreshold)) {
faceLabel = "Surprise detected";
expression = "surprise";
} else if (isSmiling && mouthOpenness < surpriseThresholdMouth / 2) {
faceLabel = "Smile detected";
expression = "smile";
} else {
faceLabel = "Neutral expression";
expression = "neutral";
}
}
}
function drawKeypoints() {
for (let i = 0; i < predictions.length; i += 1) {
const keypoints = predictions[i].scaledMesh;
// Draw facial keypoints.
for (let j = 0; j < keypoints.length; j += 1) {
const [x, y] = keypoints[j];
fill(0, 255, 0);
ellipse(x, y, 5, 5);
}
}
}
function showExpression() {
if (expression == "neutral") {
image(neutralImg, width/2,height/2, 150,150);
} else if (expression == "smile") {
image(smileImg, width/2,height/2, 150,150);
} else if (expression == "suprise") {
image(supriseImg, width/2,height/2,150,150);
}
}