handposeutils.calculations package
Submodules
handposeutils.calculations.geometry module
- handposeutils.calculations.geometry.get_cross_finger_angles(pose) dict[str, float][source]
Measure the angle between direction vectors of adjacent fingers.
- Parameters:
pose (Pose) – Hand pose object or sequence supporting index-based access to Coordinate objects.
- Returns:
Mapping from adjacent finger name pairs (e.g., “THUMB-INDEX”) to angle in radians.
- Return type:
dict of str to float
- handposeutils.calculations.geometry.get_finger_curvature(finger_name: str, pose) float[source]
Estimate the average angular curvature of a finger.
Curvature is measured as the mean angle (in radians) between consecutive segment vectors. Lower values indicate a straighter finger.
- Parameters:
finger_name (str) – Name of the finger (case-insensitive).
pose (Pose) – Hand pose object or sequence supporting index-based access to Coordinate objects.
- Returns:
Average curvature angle in radians.
- Return type:
float
- handposeutils.calculations.geometry.get_finger_length(finger_name: str, pose) float[source]
Calculate the total 3D length of a finger.
Highkey, this information is pretty arbitrary, since unless you normalize scaling, absolute distances aren’t particularly useful, compared to relative distances. TODO: write a relative bone length function. That would be more useful.
The length is computed by summing the Euclidean distances between each pair of adjacent joints for the given finger.
- Parameters:
finger_name (str) – Name of the finger (case-insensitive). Must be a key in handposeutils.data.constants.FINGER_MAPPING (e.g., “thumb”, “index”, “middle”, “ring”, “pinky”).
pose (Pose) – Hand pose object or sequence supporting index-based access to Coordinate objects.
- Returns:
Total finger length in the same units as the pose coordinates.
- Return type:
float
- handposeutils.calculations.geometry.get_finger_segment_lengths(finger_name: str, pose) list[float][source]
Get the individual segment lengths of a finger.
Returns the lengths of the proximal, intermediate, and distal segments by computing Euclidean distances between successive joints.
- Parameters:
finger_name (str) – Name of the finger (case-insensitive). Must be a key in handposeutils.data.constants.FINGER_MAPPING.
pose (Pose) – Hand pose object or sequence supporting index-based access to Coordinate objects.
- Returns:
Three lengths (same units as coordinates), ordered from base to tip.
- Return type:
list of float
See also
get_finger_lengthgets the summed length of the full finger
- handposeutils.calculations.geometry.get_finger_spread(pose) dict[str, float][source]
Measure the angular spread between adjacent fingers at their MCP joints.
- Parameters:
pose (Pose) – Hand pose object or sequence supporting index-based access to Coordinate objects.
- Returns:
Mapping from finger pair names (e.g., “INDEX-MIDDLE”) to spread angle in radians.
- Return type:
dict of str to float
- handposeutils.calculations.geometry.get_hand_aspect_ratio(pose) float[source]
Calculate the aspect ratio (width / height) of the hand in the XY plane.
- Parameters:
pose (Pose) – Hand pose object
- Returns:
Ratio of hand width to height in the XY plane.
- Return type:
float
- handposeutils.calculations.geometry.get_joint_angle(triplet: tuple[int, int, int], pose) float[source]
Compute the internal angle at the middle joint of a 3-point chain.
- Parameters:
triplet (tuple of int) – Landmark indices (a, b, c) where b is the vertex joint.
pose (Pose) – Hand pose object or sequence supporting index-based access to Coordinate objects.
- Returns:
Angle at point b in radians.
- Return type:
float
- handposeutils.calculations.geometry.get_palm_normal_vector(pose) ndarray[source]
Compute the palm normal vector using three base landmarks.
Uses the cross product of the wrist-to-index_mcp and wrist-to-pinky_mcp vectors to obtain the palm’s outward normal.
- Parameters:
pose (Pose) – Hand pose object or sequence supporting index-based access to Coordinate objects.
- Returns:
Normalized 3D vector representing the palm normal.
- Return type:
numpy.ndarray
- handposeutils.calculations.geometry.get_pose_flatness(pose, axis='z') float[source]
Measure the flatness of the hand pose along a given axis.
Flatness is defined as the standard deviation of all coordinates along the specified axis.
- Parameters:
pose (Pose) – Hand pose object with get_all_coordinates() method.
axis ({'x', 'y', 'z'}, optional) – Axis along which to compute flatness. Default is ‘z’.
- Returns:
Standard deviation along the specified axis. Lower values mean flatter pose.
- Return type:
float
- handposeutils.calculations.geometry.get_total_hand_span(pose) float[source]
Compute the Euclidean distance between thumb tip and pinky tip.
- Parameters:
pose (Pose) – Hand pose object or sequence supporting index-based access to Coordinate objects.
- Returns:
Distance between landmarks 4 (thumb tip) and 20 (pinky tip).
- Return type:
float
- handposeutils.calculations.geometry.vector_between(c1, c2)[source]
Returns a NumPy vector from Coordinate c1 to c2.
- Parameters:
c1 (Coordinate) – First point (x,y,z)
c2 (Coordinate) – Second point (x,y,z)
- Returns:
A NumPy array representing the vector from c1 to c2.
- Return type:
np.array
handposeutils.calculations.similarity module
- handposeutils.calculations.similarity.compute_joint_angle_errors(pose1: HandPose, pose2: HandPose) List[float][source]
Computes per-joint absolute angle differences between two hand poses.
This method assumes the standard 21-landmark MediaPipe format. Angles are measured in radians for each consecutive finger joint triplet.
- handposeutils.calculations.similarity.cosine_similarity(pose1: HandPose, pose2: HandPose) float[source]
Compute cosine similarity between two 3D hand poses.
Each pose is represented as a flattened 63-dimensional vector (21 landmarks × 3 coordinates). The cosine similarity measures the angular difference between the vectors, making it invariant to scale but not to translation, so position is first normalized.
- Parameters:
- Returns:
similarity – Cosine similarity in the range [-1, 1]. - 1.0 indicates identical orientation. - 0.0 indicates orthogonal poses. - -1.0 indicates opposite orientation.
- Return type:
float
Notes
This method normalizes translation by centering poses before comparison.
Similarity is undefined for zero-length pose vectors (returns 0.0).
- handposeutils.calculations.similarity.embedding_similarity(vec1: ndarray, vec2: ndarray, method: str = 'cosine', **kwargs) float[source]
Computes similarity or distance between two embedding vectors or sequences.
Supports: - Single embeddings (1D arrays) - Temporal embeddings (2D arrays of shape [sequence_length, embedding_dim]),
where similarity is computed per frame and averaged.
- Parameters:
vec1 (numpy.ndarray) – First embedding vector or sequence.
vec2 (numpy.ndarray) – Second embedding vector or sequence.
method (str, default="cosine") – Method to compute similarity. Options: - ‘cosine’ - ‘euclidean’ - ‘manhattan’ - ‘mahalanobis’
**kwargs –
Additional parameters for specific methods. For example: - cov : numpy.ndarray
Covariance matrix for Mahalanobis distance.
- Returns:
The method name and the computed similarity or distance score. For cosine similarity, higher is more similar. For distances, lower is more similar.
- Return type:
tuple of (str, float)
- Raises:
ValueError – If vectors have different shapes, or covariance matrix shape is invalid.
NotImplementedError – If the given method is not supported.
- handposeutils.calculations.similarity.euclidean_distance(pose1: HandPose, pose2: HandPose) float[source]
Compute the mean Euclidean distance between two hand poses.
This function calculates the average distance between corresponding landmarks of two HandPose objects. Distances are computed directly in 3D space and are sensitive to both scale and translation.
It is STRONGLY recommended to normalize HandPoses before computing Euclidean distance.
- Parameters:
- Returns:
mean_distance – Mean Euclidean distance between corresponding landmarks. Lower values indicate greater similarity.
- Return type:
float
- Raises:
ValueError – If the number of landmarks (or their dimensionality) differs between poses.
- handposeutils.calculations.similarity.joint_angle_similarity(pose1: HandPose, pose2: HandPose) float[source]
Computes biomechanical similarity between two hand poses using joint angles.
The joint angles of each pose are extracted and compared using mean squared difference. Lower values indicate more similar poses.
- Parameters:
- Returns:
Mean squared difference between joint angles. A value of 0.0 indicates identical angles.
- Return type:
float
- Raises:
ValueError – If the angle descriptors have different lengths.
Notes
Useful in determining similarity in joint curvature across regions of the hand,
when used consecutively. - Can represent the same information as geometry.get_finger_curvature() when multiple function calls are fused.
See also
geometry.get_finger_curvature
- handposeutils.calculations.similarity.pose_similarity(pose1: HandPose, pose2: HandPose, method: str = 'procrustes') float[source]
Computes similarity between two hand poses using the specified method.
Supported methods
‘procrustes’: Procrustes distance (lower = more similar)
‘euclidean’ : Euclidean distance
‘cosine’ : Cosine similarity
‘joint_angle’: Mean squared joint angle difference
- param pose1:
First hand pose.
- type pose1:
HandPose
- param pose2:
Second hand pose.
- type pose2:
HandPose
- param method:
Similarity computation method.
- type method:
str, default=’procrustes’
- returns:
Similarity score according to the chosen method. Scale and interpretation vary depending on the method.
- rtype:
float
- raises NotImplementedError:
If the given method is not supported.
- handposeutils.calculations.similarity.procrustes_alignment(pose1: HandPose, pose2: HandPose) Tuple[ndarray, ndarray, float][source]
Perform Procrustes alignment between two 3D hand poses.
The alignment process removes translation, scale, and rotation differences between two HandPose objects, returning their aligned coordinates and the Procrustes distance (sum of squared differences).
It is STRONGLY recommended to normalize HandPoses before computing Euclidean distance.
- Parameters:
- Returns:
aligned_pose1 (ndarray of shape (n_landmarks, 3)) – Aligned version of pose1 after Procrustes transformation.
aligned_pose2 (ndarray of shape (n_landmarks, 3)) – Normalized version of pose2 for comparison.
distance (float) – Procrustes distance between aligned poses. Lower values indicate greater similarity.
- Raises:
ValueError – If the number of landmarks (or their dimensionality) differs between poses.
Notes
This method uses the Kabsch algorithm to compute the optimal rotation.
The Procrustes distance is not invariant to landmark correspondence errors.
handposeutils.calculations.transforms module
- handposeutils.calculations.transforms.mirror_pose(pose: HandPose, axis: Literal['x', 'y', 'z'] = 'x') HandPose[source]
Mirrors a hand pose across the specified axis.
- handposeutils.calculations.transforms.normalize_handpose(pose: HandPose) HandPose[source]
Normalizes a hand pose’s position and scale.
This function applies: 1. Translation so the centroid is at the origin. 2. Uniform scaling to fit in [-1, 1] on all axes.
- handposeutils.calculations.transforms.normalize_handpose_positioning(pose: HandPose) HandPose[source]
Translates a hand pose so that its centroid is at the origin.
Each coordinate is shifted such that the average x, y, and z positions across all landmarks are zero.
- handposeutils.calculations.transforms.normalize_handpose_scaling(pose: HandPose) HandPose[source]
Scales a hand pose to fit within a [-1, 1] cube across all axes.
The scaling is uniform and based on the largest axis range (max range of x, y, or z coordinates).
- Parameters:
pose (HandPose) – The hand pose to scale.
- Returns:
The uniformly scaled hand pose, preserving proportions.
- Return type:
Notes
If the maximum range is zero (all points are identical), the pose is returned unchanged.
- handposeutils.calculations.transforms.rotate_pose_by_axis(pose: HandPose, degrees: float, axis: Literal['x', 'y', 'z']) HandPose[source]
Rotates a hand pose by a given angle around a specified axis.
- handposeutils.calculations.transforms.straighten_finger(pose, finger: str) HandPose[source]
Straightens a specified finger so that its joints align in a straight line.
The finger’s base and first joint define the direction, and each joint is repositioned proportionally along this direction, preserving original segment lengths.
- Parameters:
pose (HandPose) – The hand pose containing the finger to straighten.
finger (str) – Finger name to straighten. Must match a key in handposeutils.data.constants.FINGER_MAPPING.
- Returns:
The modified hand pose with the finger straightened.
- Return type:
- Raises:
ValueError – If the finger name is invalid or has fewer than two joints.