| 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]); |
| const vecB = new Array(b[0], b[1]); |
| const vecC = new Array(c[0], c[1]); |
| |
| 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); |
| } |
| } |
|
|