<body>
<div id="liveView" class="videoView">
<!-- <button id="webcamButton">Enable Webcam</button> -->
<video id="webcam" autoplay></video>
</div>
<!-- Require the peer dependencies of handpose. -->
<script src="https://unpkg.com/@tensorflow/tfjs-core@2.1.0/dist/tf-core.js"></script>
<script src="https://unpkg.com/@tensorflow/tfjs-converter@2.1.0/dist/tf-converter.js"></script>
<!-- You must explicitly require a TF.js backend if you're not using the tfs union bundle. -->
<script src="https://unpkg.com/@tensorflow/tfjs-backend-webgl@2.1.0/dist/tf-backend-webgl.js"></script>
<!-- Alternatively you can use the WASM backend: <script src="https://unpkg.com/@tensorflow/tfjs-backend-wasm@2.1.0/dist/tf-backend-wasm.js"></script> -->
<script src="https://unpkg.com/@tensorflow-models/handpose@0.0.6/dist/handpose.js"></script>
<!-- <script src="/script.js" defer></script> -->
</body>
body {
font-family: helvetica, arial, sans-serif;
margin: 2em;
color: #3D3D3D;
}
h1 {
font-style: italic;
color: #FF6F00;
}
h2 {
clear: both;
}
em {
font-weight: bold;
}
video {
clear: both;
display: block;
}
section {
opacity: 1;
transition: opacity 500ms ease-in-out;
}
header, footer {
clear: both;
}
button {
z-index: 1000;
position: relative;
}
.removed {
display: none;
}
.invisible {
opacity: 0.2;
}
.note {
font-style: italic;
font-size: 130%;
}
.webcam {
position: relative;
}
.webcam, .classifyOnClick {
position: relative;
float: left;
width: 48%;
margin: 2% 1%;
cursor: pointer;
}
.webcam p, .classifyOnClick p {
position: absolute;
padding: 5px;
background-color: rgba(255, 111, 0, 0.85);
color: #FFF;
border: 1px dashed rgba(255, 255, 255, 0.7);
z-index: 2;
font-size: 12px;
}
.highlighter {
background: rgba(0, 255, 0, 0.25);
border: 1px dashed #fff;
z-index: 1;
position: absolute;
}
.classifyOnClick {
z-index: 0;
position: relative;
}
.classifyOnClick canvas, .webcam canvas.overlay {
opacity: 0.66;
position: absolute;
top: 0;
left: 0;
z-index: 2;
}
let video;
let model;
const init = async () => {
video = await loadVideo();
await tf.setBackend("webgl");
model = await handpose.load();
main();
};
const loadVideo = async () => {
const video = await setupCamera();
video.play();
return video;
};
const setupCamera = async () => {
if (!navigator.mediaDevices || !navigator.mediaDevices.
getUserMedia) {
throw new Error(
"Browser API navigator.mediaDevices.getUserMedia not available"
);
}
video = document.querySelector("video");
video.width = window.innerWidth;
video.height = window.innerHeight;
const stream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {
facingMode: "user",
width: window.innerWidth,
height: window.innerHeight,
},
});
video.srcObject = stream;
return new Promise(
(resolve) => (video.onloadedmetadata = () =>
resolve(video))
);
};
init();
async function main() {
const predictions = await model.estimateHands(
document.querySelector("video")
);
if (predictions.length > 0) {
const thumbTip = predictions[0].annotations.thumb[3][1];
const indexTip = predictions[0].annotations.indexFinger[3][1];
const middleFTip = predictions[0].annotations.middleFinger[3][1];
const ringFTip = predictions[0].annotations.ringFinger[3][1];
const pinkyTip = predictions[0].annotations.pinky[3][1];
const indexBase1 = predictions[0].annotations.indexFinger[1][1];
const middleFBase1 = predictions[0].annotations.middleFinger[1][1];
const ringFBase1 = predictions[0].annotations.ringFinger[1][1];
const pinkyBase1 = predictions[0].annotations.pinky[1][1];
const diffThumbIndex = thumbTip - indexTip;
const diffIndexMiddle = indexTip - middleFTip;
const otherFourFingersFolded =
indexTip > indexBase1 &&
middleFTip > middleFBase1 &&
ringFTip > ringFBase1 &&
pinkyTip > pinkyBase1;
if (diffThumbIndex >= 20 && diffIndexMiddle <= 0) {
console.log("o");
} else if (pinkyTip < (middleFTip && ringFTip && indexTip)) {
console.log("i");
} else if (
thumbTip < (indexTip && middleFTip && ringFTip && pinkyTip) &&
otherFourFingersFolde
) {
console.log("a");
} else if (
thumbTip > (indexTip && middleFTip && ringFTip && pinkyTip) &&
!(diffThumbIndex >= 20 && diffIndexMiddle <= 0)
) {
console.log("e");
} else if (diffThumbIndex > 100 && diffIndexMiddle <= 20) {
console.log("u");
}
}
requestAnimationFrame(main);
}
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.