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); } }