UNPKG

bowling-analysis-system

Version:

A comprehensive system for analyzing bowling techniques using video processing and metrics calculation

254 lines (196 loc) 7.74 kB
/** * @module metrics/calculations/angles/UpperBodyAngles * @description Functions for calculating upper body joint angles */ const { calculateAngleBetweenVectors, getSafeLandmark, createVector } = require('../MetricsUtilities'); /** * Calculate arm angles for both sides * @param {Array} landmarks - Array of pose landmarks * @returns {Object} Left and right arm angles */ function calculateArmAngles(landmarks) { return { left: calculateLeftArmAngle(landmarks), right: calculateRightArmAngle(landmarks) }; } /** * Calculate elbow flexions for both sides * @param {Array} landmarks - Array of pose landmarks * @returns {Object} Left and right elbow flexions */ function calculateElbowFlexions(landmarks) { return { left: calculateLeftElbowFlexion(landmarks), right: calculateRightElbowFlexion(landmarks) }; } /** * Calculate shoulder rotations for both sides * @param {Array} landmarks - Array of pose landmarks * @returns {Object} Left and right shoulder rotations */ function calculateShoulderRotations(landmarks) { return { left: calculateLeftShoulderRotation(landmarks), right: calculateRightShoulderRotation(landmarks) }; } /** * Calculate shoulder tilts for both sides * @param {Array} landmarks - Array of pose landmarks * @returns {Object} Left and right shoulder tilts */ function calculateShoulderTilts(landmarks) { return { left: calculateLeftShoulderTilt(landmarks), right: calculateRightShoulderTilt(landmarks) }; } /** * Calculate shoulder flexions for both sides * @param {Array} landmarks - Array of pose landmarks * @returns {Object} Left and right shoulder flexions */ function calculateShoulderFlexions(landmarks) { return { left: calculateLeftShoulderFlexion(landmarks), right: calculateRightShoulderFlexion(landmarks) }; } /** * Calculate wrist angles for both sides * @param {Array} landmarks - Array of pose landmarks * @returns {Object} Left and right wrist angles */ function calculateWristAngles(landmarks) { return { left: calculateLeftWristAngle(landmarks), right: calculateRightWristAngle(landmarks) }; } // Individual calculation functions function calculateRightArmAngle(landmarks) { const shoulder = getSafeLandmark(landmarks, 12); const elbow = getSafeLandmark(landmarks, 14); const wrist = getSafeLandmark(landmarks, 16); if (!shoulder || !elbow || !wrist) return null; const upperArm = createVector(shoulder, elbow); const forearm = createVector(elbow, wrist); return calculateAngleBetweenVectors(upperArm, forearm); } function calculateLeftArmAngle(landmarks) { const shoulder = getSafeLandmark(landmarks, 11); const elbow = getSafeLandmark(landmarks, 13); const wrist = getSafeLandmark(landmarks, 15); if (!shoulder || !elbow || !wrist) return null; const upperArm = createVector(shoulder, elbow); const forearm = createVector(elbow, wrist); return calculateAngleBetweenVectors(upperArm, forearm); } function calculateRightElbowFlexion(landmarks) { const shoulder = getSafeLandmark(landmarks, 12); const elbow = getSafeLandmark(landmarks, 14); const wrist = getSafeLandmark(landmarks, 16); if (!shoulder || !elbow || !wrist) return null; const upperArm = createVector(shoulder, elbow); const forearm = createVector(elbow, wrist); return 180 - calculateAngleBetweenVectors(upperArm, forearm); } function calculateLeftElbowFlexion(landmarks) { const shoulder = getSafeLandmark(landmarks, 11); const elbow = getSafeLandmark(landmarks, 13); const wrist = getSafeLandmark(landmarks, 15); if (!shoulder || !elbow || !wrist) return null; const upperArm = createVector(shoulder, elbow); const forearm = createVector(elbow, wrist); return 180 - calculateAngleBetweenVectors(upperArm, forearm); } function calculateLeftShoulderRotation(landmarks) { const leftShoulder = getSafeLandmark(landmarks, 11); const leftElbow = getSafeLandmark(landmarks, 13); const rightShoulder = getSafeLandmark(landmarks, 12); if (!leftShoulder || !leftElbow || !rightShoulder) return null; const shoulderLine = createVector(rightShoulder, leftShoulder); const upperArm = createVector(leftShoulder, leftElbow); const upperArmHorizontal = { x: upperArm.x, y: 0, z: upperArm.z }; return calculateAngleBetweenVectors(shoulderLine, upperArmHorizontal); } function calculateRightShoulderRotation(landmarks) { const leftShoulder = getSafeLandmark(landmarks, 11); const rightShoulder = getSafeLandmark(landmarks, 12); const rightElbow = getSafeLandmark(landmarks, 14); if (!leftShoulder || !rightShoulder || !rightElbow) return null; const shoulderLine = createVector(leftShoulder, rightShoulder); const upperArm = createVector(rightShoulder, rightElbow); const upperArmHorizontal = { x: upperArm.x, y: 0, z: upperArm.z }; return calculateAngleBetweenVectors(shoulderLine, upperArmHorizontal); } function calculateLeftShoulderTilt(landmarks) { const leftShoulder = getSafeLandmark(landmarks, 11); const leftElbow = getSafeLandmark(landmarks, 13); if (!leftShoulder || !leftElbow) return null; const upperArm = createVector(leftShoulder, leftElbow); const vertical = { x: 0, y: 1, z: 0 }; return calculateAngleBetweenVectors(upperArm, vertical); } function calculateRightShoulderTilt(landmarks) { const rightShoulder = getSafeLandmark(landmarks, 12); const rightElbow = getSafeLandmark(landmarks, 14); if (!rightShoulder || !rightElbow) return null; const upperArm = createVector(rightShoulder, rightElbow); const vertical = { x: 0, y: 1, z: 0 }; return calculateAngleBetweenVectors(upperArm, vertical); } function calculateLeftWristAngle(landmarks) { const elbow = getSafeLandmark(landmarks, 13); const wrist = getSafeLandmark(landmarks, 15); const hand = getSafeLandmark(landmarks, 17); if (!elbow || !wrist || !hand) return null; const forearm = createVector(elbow, wrist); const handVector = createVector(wrist, hand); return calculateAngleBetweenVectors(forearm, handVector); } function calculateRightWristAngle(landmarks) { const elbow = getSafeLandmark(landmarks, 14); const wrist = getSafeLandmark(landmarks, 16); const hand = getSafeLandmark(landmarks, 18); if (!elbow || !wrist || !hand) return null; const forearm = createVector(elbow, wrist); const handVector = createVector(wrist, hand); return calculateAngleBetweenVectors(forearm, handVector); } function calculateLeftShoulderFlexion(landmarks) { const shoulder = getSafeLandmark(landmarks, 11); const elbow = getSafeLandmark(landmarks, 13); if (!shoulder || !elbow) return null; const upperArm = createVector(shoulder, elbow); const vertical = { x: 0, y: 1, z: 0 }; return calculateAngleBetweenVectors(upperArm, vertical); } function calculateRightShoulderFlexion(landmarks) { const shoulder = getSafeLandmark(landmarks, 12); const elbow = getSafeLandmark(landmarks, 14); if (!shoulder || !elbow) return null; const upperArm = createVector(shoulder, elbow); const vertical = { x: 0, y: 1, z: 0 }; return calculateAngleBetweenVectors(upperArm, vertical); } module.exports = { calculateArmAngles, calculateElbowFlexions, calculateShoulderRotations, calculateShoulderTilts, calculateShoulderFlexions, calculateWristAngles, calculateLeftShoulderFlexion, calculateRightShoulderFlexion };