Skip to content

Instantly share code, notes, and snippets.

@InputBlackBoxOutput
Created February 5, 2022 07:25
Show Gist options
  • Save InputBlackBoxOutput/a2a719b2772b5d591ce8c91d1ea49ea4 to your computer and use it in GitHub Desktop.
Save InputBlackBoxOutput/a2a719b2772b5d591ce8c91d1ea49ea4 to your computer and use it in GitHub Desktop.
Mediapipe: Holistic
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Holistic</title>
<script
src="https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]/camera_utils.js"
crossorigin="anonymous"
></script>
<script
src="https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]/control_utils.js"
crossorigin="anonymous"
></script>
<script
src="https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]/drawing_utils.js"
crossorigin="anonymous"
></script>
<script
src="https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]/holistic.js"
crossorigin="anonymous"
></script>
</head>
<body>
<style>
.container {
position: absolute;
top: 50%;
left: 50%;
-moz-transform: translateX(-50%) translateY(-50%);
-webkit-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
text-align: center;
}
</style>
<div class="container">
<h2>Mediapipe: Holistic</h2>
<canvas id="output" width="640px" height="480px"></canvas>
</div>
<script>
const video = document.createElement("video");
const output = document.getElementById("output");
const canvasContext = output.getContext("2d");
function removeElements(landmarks, elements) {
for (const element of elements) {
delete landmarks[element];
}
}
function removeLandmarks(results) {
if (results.poseLandmarks) {
removeElements(
results.poseLandmarks,
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 16, 17, 18, 19, 20, 21, 22]
);
}
}
function connect(ctx, connectors) {
const canvas = ctx.canvas;
for (const connector of connectors) {
const from = connector[0];
const to = connector[1];
if (from && to) {
if (
from.visibility &&
to.visibility &&
(from.visibility < 0.1 || to.visibility < 0.1)
) {
continue;
}
ctx.beginPath();
ctx.moveTo(from.x * canvas.width, from.y * canvas.height);
ctx.lineTo(to.x * canvas.width, to.y * canvas.height);
ctx.stroke();
}
}
}
function onResultsHolistic(results) {
removeLandmarks(results);
canvasContext.save();
canvasContext.clearRect(0, 0, output.width, output.height);
canvasContext.drawImage(
results.image,
0,
0,
output.width,
output.height
);
canvasContext.lineWidth = 5;
if (results.poseLandmarks) {
if (results.rightHandLandmarks) {
canvasContext.strokeStyle = "#00FF00";
connect(canvasContext, [
[
results.poseLandmarks[POSE_LANDMARKS.RIGHT_ELBOW],
results.rightHandLandmarks[0],
],
]);
}
if (results.leftHandLandmarks) {
canvasContext.strokeStyle = "#FF0000";
connect(canvasContext, [
[
results.poseLandmarks[POSE_LANDMARKS.LEFT_ELBOW],
results.leftHandLandmarks[0],
],
]);
}
}
drawConnectors(canvasContext, results.poseLandmarks, POSE_CONNECTIONS, {
color: "#00FF00",
});
drawLandmarks(canvasContext, results.poseLandmarks, {
color: "#00FF00",
fillColor: "#FF0000",
});
drawConnectors(
canvasContext,
results.rightHandLandmarks,
HAND_CONNECTIONS,
{ color: "#00CC00" }
);
drawLandmarks(canvasContext, results.rightHandLandmarks, {
color: "#00FF00",
fillColor: "#FF0000",
lineWidth: 2,
radius: (data) => {
return lerp(data.from.z, -0.15, 0.1, 10, 1);
},
});
drawConnectors(
canvasContext,
results.leftHandLandmarks,
HAND_CONNECTIONS,
{ color: "#CC0000" }
);
drawLandmarks(canvasContext, results.leftHandLandmarks, {
color: "#FF0000",
fillColor: "#00FF00",
lineWidth: 2,
radius: (data) => {
return lerp(data.from.z, -0.15, 0.1, 10, 1);
},
});
drawConnectors(
canvasContext,
results.faceLandmarks,
FACEMESH_TESSELATION,
{ color: "#C0C0C070", lineWidth: 1 }
);
drawConnectors(
canvasContext,
results.faceLandmarks,
FACEMESH_RIGHT_EYE,
{
color: "#FF3030",
}
);
drawConnectors(
canvasContext,
results.faceLandmarks,
FACEMESH_RIGHT_EYEBROW,
{ color: "#FF3030" }
);
drawConnectors(
canvasContext,
results.faceLandmarks,
FACEMESH_LEFT_EYE,
{
color: "#30FF30",
}
);
drawConnectors(
canvasContext,
results.faceLandmarks,
FACEMESH_LEFT_EYEBROW,
{ color: "#30FF30" }
);
drawConnectors(
canvasContext,
results.faceLandmarks,
FACEMESH_FACE_OVAL,
{
color: "#E0E0E0",
}
);
drawConnectors(canvasContext, results.faceLandmarks, FACEMESH_LIPS, {
color: "#E0E0E0",
});
canvasContext.restore();
}
const holistic = new Holistic({
locateFile: (file) => {
return `https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]/${file}`;
},
});
holistic.onResults(onResultsHolistic);
const camera = new Camera(video, {
onFrame: async () => {
await holistic.send({ image: video });
},
width: 640,
height: 480,
});
camera.start();
new ControlPanel(document.createElement("div"), {
selfieMode: true,
upperBodyOnly: true,
smoothLandmarks: true,
minDetectionConfidence: 0.5,
minTrackingConfidence: 0.5,
}).on((options) => {
video.classList.toggle("selfie", options.selfieMode);
holistic.setOptions(options);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment