# Model: Hands
- Powered by MediaPipe's Hands
- Full technical documentation
- 🖐 22 2D hand landmarks
- 🖐🖐 Track up to 4 hands total
This model includes dozens of Pinch Events and helper styles to get you going quickly, along with a plugin for scrolling pages handsfree.
# Usage
# With defaults
const handsfree = new Handsfree({hands: true})
handsfree.start()
# With config
const handsfree = new Handsfree({
hands: {
enabled: true,
// The maximum number of hands to detect [0 - 4]
maxNumHands: 2,
// Minimum confidence [0 - 1] for a hand to be considered detected
minDetectionConfidence: 0.5,
// Minimum confidence [0 - 1] for the landmark tracker to be considered detected
// Higher values are more robust at the expense of higher latency
minTrackingConfidence: 0.5
}
})
handsfree.start()
# Data
Image source, MediaPipe: https://google.github.io/mediapipe/solutions/hands#hand-landmark-model (opens new window)
# Hand Landmarks
# .landmarks
and .landmarksVisible
You can access the landmarks for each hand through:
// handIndex [0 - 3] An array of landmark points for each detected hands
handsfree.data.hands.landmarks
// Left hand, person #1
handsfree.data.hands.landmarks[0]
// Right hand, person #1
handsfree.data.hands.landmarks[1]
// Left hand, person #2
handsfree.data.hands.landmarks[2]
// Right hand, person #2
handsfree.data.hands.landmarks[3]
Each of these has 22 {x, y}
landmarks. To check if the hand is detected, you can use handsfree.data.hands.landmarksVisible
:
// Left hand, person #1
handsfree.data.hands.landmarksVisible[0]
// Right hand, person #1
handsfree.data.hands.landmarksVisible[1]
// Left hand, person #2
handsfree.data.hands.landmarksVisible[2]
// Right hand, person #2
handsfree.data.hands.landmarksVisible[3]
# Original data
It's not recommended to use these as the hands are not always in the correct index, however it's exposed here to provide backward compatibility for those switching to Handsfree.js from using MediaPipe Hands directly.
// handIndex [0 - 3] An array of landmark points for each detected hands
handsfree.data.hands.multiHandLandmarks[handIndex] == [
// Landmark 0
{x, y},
// Landmark 1
{x, y},
// ...
// Landmark 20
{x, y}
]
// hand 0, landmark 0
handsfree.data.hands.multiHandLandmarks[0][0].x
handsfree.data.hands.multiHandLandmarks[0][0].y
# Is it the right or left hand?
// handIndex [0 - 3] An array of landmark points for each detected hands
handsfree.data.hands.multiHandedness[handIndex] == {
// "Right" or "Left"
label,
// The probability that it is "Right" or "Left"
score
}
// hand 0
handsfree.data.hands.multiHandedness[0].label
handsfree.data.hands.multiHandedness[0].score
# Examples of accessing the data
handsfree = new Handsfree({hands: true})
handsfree.start()
// From anywhere
handsfree.data.hands.landmarks
// From inside a plugin
handsfree.use('logger', data => {
if (!data.hands) return
// Show a log whenever the left hand is visible
if (data.hands.landmarksVisible[0]) {
console.log(data.hands.landmarks[0])
}
})
// From an event
document.addEventListener('handsfree-data', event => {
const data = event.detail
if (!data.hands) return
// Show a log whenever the right hand for person #2 is visible
if (data.hands.landmarksVisible[3]) {
console.log(data.hands.landmarks[3])
}
})
# Examples
I remixed @notwaldorf's Piano Genie so that you can jam out with your fingers through a webcam 🖐🎹🖐
— Oz Ramos (@MIDIBlocks) February 10, 2021
Try it on @Glitch: https://t.co/CvrOboC5tV
Or see the source: https://t.co/ffWG92OEm2
Remixed by simply using the "Pincher Plugin" of Handsfree.js! #MediaPipe #MadeWithTFJS pic.twitter.com/lblUgzNl7N
Day 2 of #100DaysHandsfree
— Oz Ramos (@MIDIBlocks) January 22, 2021
On recommendation I've started handsfree-ifying @daviddotli Blob Opera 🎶 Only works with 1 pinch at a time but it works really well!
If you'd like to see how I did it, it was just 39 smooth lines of JavaScript: https://t.co/ho39dwQiqB pic.twitter.com/qdoWZD1gJg
Been trying to figure out a way to safely sandbox webcam but also render it w/ green wireframes on top of pages
— Oz Ramos (@MIDIBlocks) December 31, 2020
My solution was to run webcam in a headless Browser Background Script, render it + wireframes onto canvas, then use Picture in Picture API to "pop it outside" browser! pic.twitter.com/dZDStQ6BFq
My browser based, handsfree UX toolkits are finally coming together after 2.5 looong years 😭
— Oz Ramos (@MIDIBlocks) November 29, 2020
Here I'm playing a Steam game with hand gestures detected in the browser and sent to the desktop
It's 100% JavaScript! #MadeWithTFJS cc @jason_mayes pic.twitter.com/Y1h7ajgnTD
In 2021 I'm going to make a small piece of handsfree art/music every few days using a different online tool, and I'll be curating everything on my new Instagram: https://t.co/gQZ3uk9muG
— Oz Ramos (@MIDIBlocks) December 30, 2020
Here's my first exploration from a few days ago, where I try to direct diffusions to music pic.twitter.com/OJywuYK7z9
Handsfree.js 8.2.4 is ready:
— Oz Ramos (@MIDIBlocks) January 27, 2021
- Pinch scrolling is now continuous which is so smooth now!
- Pointers now emulate mousedown, mousemove, and mouseup so hover styles/listeners now work & also works within Pointer Lock API
Here's the pinchScroll demo: https://t.co/DYWag59y1d pic.twitter.com/T5tln7A3a8
Handsfree.js now emits 24+ "Pinch Events" ✨👌
— Oz Ramos (@MIDIBlocks) January 1, 2021
Like mouse events, you can now listen for a "start", "held", and "release" event for each finger (index, middle, ring, pinky). You also get the original pixel you pinched at + tons of new styles!
Docs: https://t.co/ngOKInXzeV pic.twitter.com/J39qvDnWcV
# See Also
- palmPointers plugin - Creates pointers for each hand that can be moved around my moving the hands with the palm pointed towards the webcam
- pinchers plugin - This plugin adds dozens of new events and helper styles for pinching any finger (index, middle, ring, pinky) to your thumb. It is enabled by default
- pinchScroll plugin - Adds the ability to scroll pages with a pinch gesture