Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add mirror_horizontal for holistic poses#222

Merged
AmitMY merged 2 commits into
masterfrom
mirror-horizontal
Jun 3, 2026
Merged

Add mirror_horizontal for holistic poses#222
AmitMY merged 2 commits into
masterfrom
mirror-horizontal

Conversation

@AmitMY
Copy link
Copy Markdown
Collaborator

@AmitMY AmitMY commented Jun 3, 2026

What

Adds mirror_horizontal(pose) to pose_format/utils/holistic.py — horizontally mirrors a holistic pose so it matches what MediaPipe would produce on a left-right flipped image.

Flipping the x coordinate alone is not enough, because mirroring swaps the subject's left and right. The function:

  • reflects image-space points as width - x
  • relabels body landmarks via FLIPPED_BODY_POINTS (LEFT↔RIGHT)
  • swaps LEFT_HAND_LANDMARKSRIGHT_HAND_LANDMARKS
  • reindexes the face mesh via a new FLIPPED_FACE_POINTS permutation
  • leaves POSE_WORLD_LANDMARKS unchanged

Face permutation

FLIPPED_FACE_POINTS (478 entries) is derived from MediaPipe's symmetric canonical face model — reflect each vertex's x and take the nearest vertex (exact, clean involution) — plus the 10 iris swaps. The provenance is documented in a comment. The first 468 entries are self-contained, so it works with refine_face_landmarks on (478) or off (468).

Why world landmarks are left unchanged

Single-image 2D→3D lifting has an inherent left/right ambiguity, and MediaPipe's world-landmark head resolves it to a fixed canonical frame. Re-running holistic on a flipped image returns essentially the same world landmarks (verified: identity matches at ~8px mean vs. ~18px for a geometric mirror), so a faithful mirror leaves them as-is.

FLIPPED_BODY_POINTS is now computed from BODY_POINTS via a LEFT↔RIGHT swap instead of being hardcoded.

Testing

tests/holistic_mirror_test.py runs holistic on a committed test image and on the actually-flipped image, then asserts that for every point of each flipping component, mirror_horizontal(original) lands within 10px of the flipped-image run — with and without refine_face_landmarks. Also covers: face-permutation involution, header unchanged, double-mirror is identity, confidence is a permutation, world landmarks unchanged, and rejection of non-holistic poses.

🤖 Generated with Claude Code

AmitMY and others added 2 commits June 3, 2026 16:37
Horizontally mirrors a holistic pose to match what mediapipe produces on a
left-right flipped image:
- image-space points reflected as width - x
- body landmarks relabelled via FLIPPED_BODY_POINTS (LEFT<->RIGHT)
- LEFT_HAND_LANDMARKS / RIGHT_HAND_LANDMARKS swapped
- face mesh reindexed via FLIPPED_FACE_POINTS, derived from mediapipe's
  symmetric canonical face model (reflect x, nearest vertex) plus iris swaps
- POSE_WORLD_LANDMARKS left unchanged: mediapipe reconstructs world landmarks
  in a canonical 3D frame and does not mirror them under image flip

FLIPPED_BODY_POINTS is now computed from BODY_POINTS instead of hardcoded.

Tested against holistic run on the actually-flipped image: every point of each
flipping component lands within 10px of the flipped-image run (with and without
refine_face_landmarks).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
- precompute name->index map per component (removes O(n^2) list.index scans)
- replace if/elif map selection with a {component: flip_map} table
- build result body via type(pose.body)(...) instead of copy-then-overwrite
- test: slice world block explicitly; add _component lookup helper

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@AmitMY AmitMY merged commit 9040894 into master Jun 3, 2026
8 checks passed
@AmitMY AmitMY deleted the mirror-horizontal branch June 3, 2026 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant