Using hand tracking we turn the user’s index finger into a pin on our program’s canvas. A bubble floats upward repeatedly and the user can pop the bubble with the pointy end of their pin-finger.
activities folder and name it bubble-popper (template-p5-project.zip)index.html to something appropriate like Bubble PopperThere are roughly four major things we need to do. We need to make hand tracking work, display a pin where the user’s index finger is, make a bubble move on the canvas, and finally make the pin pop the balloon.
So that’s the plan:
Technically the easiest way to get Handpose up and running with the webcam is probably just to take a pre-existing example and work from that, but let’s build it up from first principles instead.
First we clearly need to include the ml5.js library in our project
index.htmlLet’s start the webcam…
setup() of your preferred dimensions (640x480?)video variablesetup() use createCapture(VIDEO) to access the webcam and assign the return value to videovideo element so it doesn’t display on the pageIf we run this program we should be asked for permission to use the webcam (if needed) and then should see the webcam light turn on.
Let’s set up the Handpose model. We want to initialize the model and tell it we want to listen for “predict” events so we can track the user’s hand…
handpose variable to store the modelsetup() assign a new handpose model to handpose with three argumentsvideo variable containing the webcam (the source of detection)flipHorizontal property set to true (to make the video a mirror)predictions variable and assign an empty arraysetup() create a listener using .on() for the “predict” event with an anonymous callback function thatpredictions arrayconsole.log() to output the results to the JavaScript consoleAt this point if we run the program we should be able to go into the JavaScript console and, if we hold a hand in front of the webcam, we should see results coming in! Hand detection!
Now that we have hand data, we can display our pin on the canvas. We’ll need to find the coordinates of the tip and base of the user’s index finger and draw the pin between them. To do this we need to remember/check how Handpose formats the prediction data. We can figure this out by reading the data and experimenting, or just remember it.
We’ll do all this in draw() since we’re displaying this on the canvas:
predictions array has anything in it (is its length greater than 0?), if so:If we run this program we should be able to hold up our hand and see a pin drawn wherever our index finger is!
(Note: if we need to debug one useful trick is to display the webcam data on the canvas so we can see what it’s seeing. Flip the image with ml5.flipImage() and display the result with image() so that it’s displayed correctly.)
To make having a pin for a finger more interesting we need something to pop. We’ll add a simple bubble (AKA a circle) that moves upward on the canvas and wraps around.
bubble variablesetup() assign an object literal with properties for x, y, size, vx, vyvx of 0 and a negative vy so it moves upward (-2?)draw() after the predictions check, move and display the bubble using its propertiesif statement that check if it has gone off the top of the canvas and move it back to the bottom in a new random x positionAll going to the plan, when we run the program the bubble moves up the screen serenely and wraps when it hits the top. Right now our finger-pin does nothing because there’s no code for that yet…
Now we want to make the bubble and the pin interact. In particular we want to check if the tip of the pin (the tip of the index finger) is inside the bubble’s area. If so the bubble should “pop” and reset to the bottom of the canvas.
We’ll do this in draw() inside the predictions check, after we’ve calculated the positions of the index finger:
if statement that checks if this distance means the tip of the pin is inside the bubble (based on the bubble’s size)Now when we run the program we should be able to pop the bubble with the pin! We are literally moving our real hand around and in the program it’s represented as a pin that can pop a bubble. Ridiculous!
As always, there are improvements that can be made. Consider
draw() that can become individual functions with names like resetBubble() or displayPin() or displayBubble() etc.As with any simple program, we can imagine all kinds of improvements and changes?