xxxxxxxxxx
170
/**
* Created by Clara, Ed & Henrique
*/
let handposeLeft
let handposeRight
let videoLeft
let videoRight
let tennisImg
let predictions = []
//Define ball objects
var balls = []
//gravity variable
var gravity = 0.3
function setup() {
tennisImg = loadImage('https://api.iconify.design/emojione-v1:tennis.svg')
createCanvas(640, 480)
videoLeft = createCapture(VIDEO)
videoLeft.size(width / 2, height)
handposeLeft = ml5.handpose(videoLeft, modelReady)
// videoRight = createCapture(VIDEO);
// videoRight.size(width / 2, height);
// handposeRight = ml5.handpose(videoRight, modelReady);
// This sets up an event that fills the global variable "predictions"
// with an array every time new hand poses are detected
handposeLeft.on('predict', (results) => {
predictions = results
})
// Hide the video element, and just show the canvas
videoLeft.hide()
// videoRight.hide()
// Create ball objects(startX,startY,Size)
for (var i = 0; i < 10; i++) {
balls.push(new Ball(random(0, width), 20, random(20, 40)))
}
}
function modelReady() {
console.log('Model ready!')
}
function draw() {
image(videoLeft, 0, 0, width, height)
// We can call both functions to draw all keypoints and the skeletons
// drawKeypoints()
const landmarks = getLandmarks()
drawLandmarks(landmarks)
if (frameCount % 50 === 0) {
// console.table(predictions)
// console.table(balls.map(b => b.y))
console.log(predictions?.[0])
}
for (var i = 0; i < balls.length; i++) {
// Whatever the length of that array, update and display all of the objects.
balls[i].update(landmarks)
balls[i].display()
}
}
function getLandmarks() {
const middleFinger = predictions?.[0]?.annotations?.middleFinger?.slice(-1)[0]
const indexFinger = predictions?.[0]?.annotations?.indexFinger?.slice(-1)[0]
const thumb = predictions?.[0]?.annotations?.thumb?.slice(-1)[0]
const pinky = predictions?.[0]?.annotations?.pinky?.slice(-1)[0]
const palmBase = predictions?.[0]?.annotations?.palmBase?.[0]
const targetBox =
thumb && pinky
? {
topLeft: [Math.min(pinky[0], thumb[0]), Math.min(pinky[1], thumb[1])],
bottomRight: [
Math.max(pinky[0], thumb[0]),
Math.max(pinky[1], thumb[1]),
],
}
: undefined
return { middleFinger, palmBase, targetBox, pinky, thumb, indexFinger }
}
function drawLandmarks({ middleFinger, palmBase, targetBox, thumb, pinky }) {
const landmarkWidth = 50
const landmarkHeight = 50
if (middleFinger) {
fill(0, 0, 255, 30)
rect(middleFinger[0], middleFinger[1], landmarkWidth, landmarkHeight)
}
if (palmBase) {
fill(0, 255, 0, 30)
rect(palmBase[0], palmBase[1], landmarkWidth, landmarkHeight)
}
if (pinky) {
fill(255, 0, 255, 30)
rect(pinky[0], pinky[1], landmarkWidth, landmarkHeight)
}
if (thumb) {
fill(255, 255, 255, 30)
rect(thumb[0], thumb[1], landmarkWidth, landmarkHeight)
}
if (targetBox) {
fill(255, 0, 0, 160)
const width = targetBox.bottomRight[0] - targetBox.topLeft[0]
const height = targetBox.bottomRight[1] - targetBox.topLeft[1]
rect(targetBox.topLeft[0], targetBox.topLeft[1], width, height)
}
// return
// const bbox = predictions?.[0]?.boundingBox
// if (!bbox) return
// fill(0, 255, 0)
// rect(bbox.topLeft[0], bbox.topLeft[1], 50, 50)
}
// Adaptation of Daniel Shiffman's https://editor.p5js.org/shiffman/sketches/B1E5uGa0
function Ball(tempX, tempY, tempSize) {
this.x = tempX // x location of square
this.y = tempY // y location of square
this.size = tempSize // speed of square
this.speed = 0 // size
this.display = function () {
image(tennisImg, this.x, this.y, this.size, this.size)
}
this.update = function ({ targetBox }) {
// Add speed to location
this.y = this.y + this.speed
// Add gravity to speed
this.speed = this.speed + gravity
if (frameCount % 100 === 0) {
// console.log(bbox, bbox?.topLeft[1], this.y)
}
if (
targetBox &&
this.y > targetBox.topLeft[1] &&
this.x > targetBox.topLeft[0] &&
this.x < targetBox.bottomRight[0]
) {
this.speed = this.speed * -0.95
return
}
// If square reaches the bottom
// Reverse speed
if (this.y > height) {
this.speed = this.speed * -0.95
}
}
}