bowling-analysis-system
Version:
A comprehensive system for analyzing bowling techniques using video processing and metrics calculation
254 lines (196 loc) • 7.74 kB
JavaScript
/**
* @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
};