Download script.js from rootstrap-org/mediapipe-pose-demo: direct link, hf CLI and curl.
- Browser
- Download file 5.54 kB
-
https://huggingface.co/spaces/rootstrap-org/mediapipe-pose-demo/resolve/main/script.js
- Command line
-
hf download hf://spaces/rootstrap-org/mediapipe-pose-demo/script.js
-
curl -L -o script.js https://huggingface.co/spaces/rootstrap-org/mediapipe-pose-demo/resolve/main/script.js
5.54 kB
| import { PoseLandmarker, FilesetResolver, DrawingUtils } from "https://cdn.skypack.dev/@mediapipe/tasks-vision@0.10.0"; | |
| const demosSection = document.getElementById("demos"); | |
| let poseLandmarker = undefined; | |
| let runningMode = "IMAGE"; | |
| let enableWebcamButton; | |
| let enableCounter; | |
| let webcamRunning = false; | |
| const videoHeight = "360px"; | |
| const videoWidth = "480px"; | |
| let shoulder = []; | |
| let elbow = []; | |
| let wrist = []; | |
| let hip = []; | |
| let ankle = []; | |
| let knee = []; | |
| let stage; | |
| let angle; | |
| let counter = 0; | |
| let starter = 0; | |
| const createPoseLandmarker = async () => { | |
| const vision = await FilesetResolver.forVisionTasks("https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.0/wasm"); | |
| poseLandmarker = await PoseLandmarker.createFromOptions(vision, { | |
| baseOptions: { | |
| modelAssetPath: `https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_lite/float16/1/pose_landmarker_lite.task`, | |
| delegate: "GPU" | |
| }, | |
| runningMode: runningMode, | |
| numPoses: 2 | |
| }); | |
| demosSection.classList.remove("invisible"); | |
| }; | |
| createPoseLandmarker(); | |
| const video = document.getElementById("webcam"); | |
| const canvasElement = document.getElementById("output_canvas"); | |
| const canvasCtx = canvasElement.getContext("2d"); | |
| const drawingUtils = new DrawingUtils(canvasCtx); | |
| const hasGetUserMedia = () => { var _a; return !!((_a = navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.getUserMedia); }; | |
| if (hasGetUserMedia()) { | |
| enableWebcamButton = document.getElementById("webcamButton"); | |
| enableWebcamButton.addEventListener("click", enableCam); | |
| } | |
| else { | |
| console.warn("getUserMedia() is not supported by your browser"); | |
| } | |
| function enableCam(event) { | |
| if (!poseLandmarker) { | |
| console.log("Wait! poseLandmaker not loaded yet."); | |
| return; | |
| } | |
| if (webcamRunning === true) { | |
| webcamRunning = false; | |
| enableWebcamButton.innerText = "ENABLE PREDICTIONS"; | |
| } | |
| else { | |
| webcamRunning = true; | |
| enableWebcamButton.innerText = "DISABLE PREDICTIONS"; | |
| } | |
| const constraints = { | |
| video: true | |
| }; | |
| navigator.mediaDevices.getUserMedia(constraints).then((stream) => { | |
| video.srcObject = stream; | |
| video.addEventListener("loadeddata", predictWebcam); | |
| }); | |
| } | |
| let lastVideoTime = -1; | |
| async function predictWebcam() { | |
| canvasElement.style.height = videoHeight; | |
| video.style.height = videoHeight; | |
| canvasElement.style.width = videoWidth; | |
| video.style.width = videoWidth; | |
| if (runningMode === "IMAGE") { | |
| runningMode = "VIDEO"; | |
| await poseLandmarker.setOptions({ runningMode: "VIDEO" }); | |
| } | |
| let startTimeMs = performance.now(); | |
| if (lastVideoTime !== video.currentTime) { | |
| lastVideoTime = video.currentTime; | |
| poseLandmarker.detectForVideo(video, startTimeMs, (result) => { | |
| canvasCtx.save(); | |
| canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height); | |
| for (const landmark of result.landmarks) { | |
| shoulder = [landmark[11].x, landmark[11].y] | |
| elbow = [landmark[13].x, landmark[13].y] | |
| wrist = [landmark[15].x, landmark[15].y] | |
| hip = [landmark[23].x, landmark[23].y] | |
| knee = [landmark[25].x, landmark[25].y] | |
| ankle = [landmark[27].x, landmark[27].y] | |
| drawingUtils.drawLandmarks(landmark, { | |
| radius: (data) => DrawingUtils.lerp(data.from.z, -0.15, 0.1, 5, 1) | |
| }); | |
| drawingUtils.drawConnectors(landmark, PoseLandmarker.POSE_CONNECTIONS); | |
| } | |
| canvasCtx.restore(); | |
| }); | |
| } | |
| function calculateAngle(a, b, c) { | |
| const vecA = new Array(a[0], a[1]); // First | |
| const vecB = new Array(b[0], b[1]); // Mid | |
| const vecC = new Array(c[0], c[1]); // End | |
| const radians = Math.atan2(vecC[1] - vecB[1], vecC[0] - vecB[0]) - Math.atan2(vecA[1] - vecB[1], vecA[0] - vecB[0]); | |
| let angle = Math.abs(radians * (180.0 / Math.PI)); | |
| if (angle > 180.0) { | |
| angle = 360 - angle; | |
| } | |
| return angle; | |
| } | |
| const startButton = document.getElementById('startButton'); | |
| startButton.addEventListener('click', () => { | |
| starter = 1 | |
| }); | |
| const stopButton = document.getElementById('stopButton'); | |
| stopButton.addEventListener('click', () => { | |
| starter = 0 | |
| }); | |
| const restartButton = document.getElementById('restartButton'); | |
| restartButton.addEventListener('click', () => { | |
| counter = 0 | |
| }); | |
| if (starter == 1){ | |
| if(document.getElementById('curl').checked) { | |
| angle = calculateAngle(shoulder,elbow,wrist) | |
| if (angle > 160){ | |
| stage = "down" | |
| } | |
| if (angle < 30 & stage =='down'){ | |
| stage="up" | |
| counter +=1 | |
| } | |
| } | |
| if(document.getElementById('squat').checked) { | |
| angle = calculateAngle(hip,knee,ankle) | |
| if (angle > 169){ | |
| stage = "up" | |
| } | |
| if (angle < 90 & stage =='up'){ | |
| stage="down" | |
| counter +=1 | |
| } | |
| } | |
| } | |
| const landmarkValuesDiv = document.getElementById('counter'); | |
| landmarkValuesDiv.innerHTML = `stage: ${stage}, count: ${counter}`; | |
| if (webcamRunning === true) { | |
| window.requestAnimationFrame(predictWebcam); | |
| } | |
| } | |