xxxxxxxxxx
130
// This demonstrates the use of ml5js to draw shapes over the face or body
//
// This sketch is loosely based this "Hour of Code" Coding Train video
// by Daniel Shiffman: https://youtu.be/EA3-k9mnLHs
//
// This Sketch uses ml5js, a Machine Learning JavaScript library that
// works well with p5js. ml5js provides lots of interesting methods
// including pitch detection, human pose detection, sound classification, etc.
// Read more here: https://ml5js.org/
//
// Specifically, we use ml5js's PoseNet implementation for human pose tracking.
//
// Reference for the ml5js PoseNet implementation:
// - https://ml5js.org/reference/api-PoseNet/
//
// Primary PoseNet library, which ml5js is using under the hood:
// - Read this article: "Real-time Human Pose Estimation in the Browser with TensorFlow.js"
// here: https://link.medium.com/7EBfMICUh2
// - https://github.com/tensorflow/tfjs-models/tree/master/posenet
//
// Other ML JavaScript APIs:
// - Face Rec: https://github.com/justadudewhohacks/face-api.js/
//
// By Jon E. Froehlich
// http://makeabilitylab.io/
let video;
let poseNet;
let human = null;
function setup() {
createCanvas(640, 480);
video = createCapture(VIDEO);
video.hide();
// setup PoseNet. This can take a while, so we load it
// asynchronously (when it's done, it will call modelReady)
poseNet = ml5.poseNet(video, onPoseNetModelReady); //call onModelReady when setup
poseNet.on('pose', onPoseDetected); // call onPoseDetected when pose detected
}
function onPoseNetModelReady() {
print("The PoseNet model is ready...");
}
function onPoseDetected(poses) {
// poses can contain an array of bodies (because PoseNet supports
// recognition for *multiple* human bodies at the same time
// however, for this demo, we are interested in only one human body
// which is at poses[0]
human = poses[0];
}
function draw() {
image(video, 0, 0); // draw the video to screen
noStroke(); // turn off drawing outlines of shapes
//if a human has been detected, draw overlay shapes!
if (human != null) {
// For this sample, we work with three body parts but
// PoseNet supports 17 body parts in total, see:
// https://github.com/tensorflow/tfjs-models/tree/master/posenet#keypoints
drawNose(human.pose.nose.x, human.pose.nose.y);
drawEye(human.pose.leftEye.x, human.pose.leftEye.y);
drawEye(human.pose.rightEye.x, human.pose.rightEye.y);
//drawEar(human.pose.leftEar.x, human.pose.leftEar.y);
//drawEar(human.pose.rightEar.x, human.pose.rightEar.y);
}
}
/**
* Draws a nose at the given x,y position
*
* @param {number} x the x pos of the nose
* @param {number} y the y pos of the nose
*/
function drawNose(x, y) {
// To set the paintbrush color, use fill(R, G, B) where R, G, and B
// are red, green, blue intensities between 0 - 255
// So, to set a paint brush color of red, you would do fill(255, 0, 0);
// For orange, you could try: orange: fill(255,165,0);
// For pure blue, blue: fill(0, 0, 255);
let noseWidth = 60; // a reasonable nose width
// TODO: set color using fill
fill(255, 0, 0);
// TODO: draw the nose using some shape like ellipse, rect, triangle
ellipse(x, y, noseWidth);
}
/**
* Draws an eye at the given x,y position
*
* @param {number} x the x pos of the eye
* @param {number} y the y pos of the eye
*/
function drawEye(x, y) {
let eyeWidth = 40; // a reasonable white eye width
let pupilWidth = 15; // a reasonable pupil width
// TODO: Draw the white part of the eye (the sclera)
fill(255); // all white
ellipse(x, y, eyeWidth);
// TODO: Draw the pupils
fill(0); // all black
ellipse(x, y, pupilWidth);
}
/**
* Draws an ear at the given x,y position
*
* @param {number} x the x pos of the ear
* @param {number} y the y pos of the ear
*/
function drawEar(x, y) {
fill(255, 0, 255);
let earWidth = 20;
let earHeight = 60;
ellipse(x, y, earWidth, earHeight);
}