xxxxxxxxxx
157
let port;
let winLen = 10;
let win = [];
function setup() {
createCanvas(400, 400);
setTimeout(init, 4000);
connect_button = createButton("connect arduino");
connect_button.position(width / 2, height / 1.5);
connect_button.id("connect");
}
function draw() {
// background(220);
}
// More API functionssinit
// https://github.com/googlecreativelab/teachablemachine-community/tree/master/libraries/pose
// the link to your model provided by Teachable Machine export panel
const URL = "https://teachablemachine.withgoogle.com/models/WW3TWA2XJ/";
let model, webcam, ctx, labelContainer, maxPredictions;
async function init() {
const modelURL = URL + "model.json";
const metadataURL = URL + "metadata.json";
// load the model and metadata
// Refer to tmImage.loadFromFiles() in the API to support files from a file picker
// Note: the pose library adds a tmPose object to your window (window.tmPose)
model = await tmPose.load(modelURL, metadataURL);
maxPredictions = model.getTotalClasses();
// Convenience function to setup a webcam
const size = 600;
const flip = true; // whether to flip the webcam
webcam = new tmPose.Webcam(size, size, flip); // width, height, flip
await webcam.setup(); // request access to the webcam
await webcam.play();
window.requestAnimationFrame(camera_loop);
// append/get elements to the DOM
const canvas = document.getElementById("defaultCanvas0");
canvas.width = size;
canvas.height = size;
ctx = canvas.getContext("2d");
labelContainer = document.getElementById("label-container");
for (let i = 0; i < maxPredictions; i++) {
// and class labels
labelContainer.appendChild(document.createElement("div"));
}
}
async function camera_loop(timestamp) {
webcam.update(); // update the webcam frame
await predict();
window.requestAnimationFrame(camera_loop);
}
function sendToArduino(prediction) {
console.log('actually sent something');
//create array for sending data to arduino
let data_to_send = new Uint8Array(1);
//get the value to send to arduino
//getSmoothedPrediction will return a number between 0 - 1
let value_to_send = getSmoothedPrediction(prediction[0].probability);
//send data if the arduino is connected
if (port != undefined) {
if (value_to_send > 0.5) {
data_to_send[0] = 0;
port.send(data_to_send);
console.log('sending 0')
} else {
data_to_send[0] = 1;
port.send(data_to_send);
console.log('sending 1')
}
}
}
function debounce(func, timeout = 300){
let timer;
return (args) => {
console.log('tried to send something')
clearTimeout(timer);
timer = setTimeout(() => { func.apply(this, args); }, timeout);
};
}
const sendToArduinoDebounced = debounce(sendToArduino, 1000);
async function predict() {
// Prediction #1: run input through posenet
// estimatePose can take in an image, video or canvas html element
const { pose, posenetOutput } = await model.estimatePose(webcam.canvas);
// Prediction 2: run input through teachable machine classification model
const prediction = await model.predict(posenetOutput);
for (let i = 0; i < maxPredictions; i++) {
const classPrediction =
prediction[i].className + ": " + prediction[i].probability.toFixed(2);
labelContainer.childNodes[i].innerHTML = classPrediction;
}
// finally draw the poses
drawPose(pose);
sendToArduinoDebounced(prediction);
// console.log(prediction[0]);
//console log the predictions
// prediction.forEach((cls) => console.log(cls.className, cls.probability))
}
function getSmoothedPrediction(pred) {
win.push(pred);
if (win.length > winLen) {
win.shift();
}
let avg = 0;
win.forEach((p) => (avg += p));
return avg / win.length;
}
function drawPose(pose) {
if (webcam.canvas) {
ctx.drawImage(
webcam.canvas,
0,
0,
webcam.canvas.width,
webcam.canvas.height,
0,
0,
width,
height
);
// draw the keypoints and skeleton
if (pose) {
const minPartConfidence = 0.5;
tmPose.drawKeypoints(pose.keypoints, minPartConfidence, ctx);
tmPose.drawSkeleton(pose.keypoints, minPartConfidence, ctx);
}
}
}