xxxxxxxxxx
140
let video;
let poseNet;
let poses = [];
let predictions = [];
function setup() {
createCanvas(640, 480);
video = createCapture(VIDEO);
video.size(width, height);
// Create a new poseNet method with a single detection
poseNet = ml5.poseNet(video, poseNetModelReady);
// This sets up an event that fills the global variable "poses"
// with an array every time new poses are detected
poseNet.on("pose", function (results) {
poses = results;
});
// Hide the video element, and just show the canvas
facemesh_layer = createGraphics(width, height);
body_keypoints_layer = createGraphics(width, height);
skeleton_layer = createGraphics(width, height);
video.hide();
}
function poseNetModelReady() {
console.log("poseNet Model ready!");
facemesh = ml5.facemesh(video, faceMeshModelReady);
facemesh.on("predict", (results) => {
predictions = results;
});
}
function faceMeshModelReady() {
console.log("faceMesh Model ready!");
}
function draw() {
if (frameCount % 300 == 0) {
clearScreen();
}
// We can call both functions to draw all keypoints and the skeletons
drawFacemeshKeypoints();
drawSkeleton();
drawBodyKeypoints();
image(video, 0, 0, width, height);
image(facemesh_layer, 0, 0, width, height);
image(skeleton_layer, 0, 0, width, height);
image(body_keypoints_layer, 0, 0, width, height);
}
// A function to draw ellipses over the detected keypoints
function drawBodyKeypoints() {
// Loop through all the poses detected
for (let i = 0; i < poses.length; i++) {
// For each pose detected, loop through all the keypoints
let pose = poses[i].pose;
for (let j = 0; j < pose.keypoints.length; j++) {
// A keypoint is an object describing a body part (like rightArm or leftShoulder)
let keypoint = pose.keypoints[j];
let x = keypoint.position.x;
let y = keypoint.position.y;
// Only draw an ellipse is the pose probability is bigger than 0.2
if (keypoint.score > 0.2) {
body_keypoints_layer.push();
body_keypoints_layer.fill("#6495ED");
body_keypoints_layer.noStroke();
body_keypoints_layer.circle(x, y, 20);
body_keypoints_layer.textAlign(CENTER, CENTER);
body_keypoints_layer.fill("Cornsilk");
body_keypoints_layer.text(j, x, y);
if (j == 1 || j == 2) {
body_keypoints_layer.textSize(42);
body_keypoints_layer.text("", x, y);
} else if (j == 9 || j == 10) {
body_keypoints_layer.textSize(84);
body_keypoints_layer.text("🐹", x, y);
}
body_keypoints_layer.pop();
}
}
}
}
function drawFacemeshKeypoints() {
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];
facemesh_layer.push();
facemesh_layer.noStroke();
facemesh_layer.fill("LightCyan");
facemesh_layer.circle(x, y, 6);
facemesh_layer.pop();
}
}
}
// A function to draw the skeletons
function drawSkeleton() {
// Loop through all the skeletons detected
for (let i = 0; i < poses.length; i++) {
let skeleton = poses[i].skeleton;
// For every skeleton, loop through all body connections
for (let j = 0; j < skeleton.length; j++) {
let partA = skeleton[j][0];
let partB = skeleton[j][1];
skeleton_layer.push();
skeleton_layer.strokeWeight(10);
skeleton_layer.stroke("Cornsilk");
skeleton_layer.line(
partA.position.x,
partA.position.y,
partB.position.x,
partB.position.y
);
skeleton_layer.pop();
}
}
}
function clearScreen() {
facemesh_layer.clear();
skeleton_layer.clear();
body_keypoints_layer.clear();
}
function keyPressed() {
if (key == "s") {
saveGif("animation.gif", 5);
} else if (key == "1") {
facemesh_layer.clear();
} else if (key == "2") {
skeleton_layer.clear();
} else if (key == "3") {
body_keypoints_layer.clear();
}
}