ayzeksalimli's picture
Fix broken image links (blob URL -> self-hosted) + markdown image syntax
110ba8b verified
|
Raw
History Blame Contribute Delete
2.82 kB
# Pose Driven 3D Characters
Stand in front of the camera and a rigged 3D character copies your pose in real time.
![Fig.1: Example 1](examples/POSE_DRIVEN_3D_EXAMPLE_1.png)
![Fig.2: Example 2](examples/POSE_DRIVEN_3D_EXAMPLE_2.png)
## Model
Two models, no training:
- **YOLO pose** (`models/yolo26s-pose.pt`) returns 17 body keypoints per person
(shoulders, elbows, wrists, hips, knees, ankles, face), tracked across frames and
smoothed with a one euro filter.
- **Rigged glTF characters** (`models/characters/*.glb`) carry their own skeletons:
`Michelle` (Mixamo), `Rigged Figure` and `Cesium Man` (Khronos samples). Switch with
`M` / `N`. The `.glb` files are read directly - meshes, skinning weights, bones and
embedded textures - and drawn by a small software rasterizer, so there is no
game engine and no GPU requirement.
## Logic
Each bone is aimed at the direction its keypoints describe. A bone points along
`parent.rotation @ child_offset`, so making that equal the target gives its local
rotation:
```
R = animated_parent.rotation^-1 @ swing(rest -> target) @ bind_parent.rotation
```
Both accumulated rotations are needed, animated **and** bind. Using the animated one on
both sides only works when the bind rotation is identity, which is never true once a rig
has an axis-conversion root, and it misaims every limb by up to 20 degrees.
The rest of it:
- **Depth.** One camera sees no depth, so a limb shorter than its own reference length
must be angled toward or away from the lens; that missing length is recovered as a
damped Z component.
- **Turning.** Shoulders narrower than the body's proportions mean the torso is turned.
That yaw is folded into every bone's swing, because each driven bone's orientation is
absolute - spinning one alone is undone by the next one down.
- **Mirroring.** The camera image is flipped, so left and right chains swap and the
horizontal axis flips: raise your right arm and the character raises its right arm,
facing you.
- **Speed.** All per-triangle work - projection, culling, lighting, colour - is batched
in numpy, leaving one OpenCV polygon fill per triangle, and dense meshes are thinned
at load to a triangle budget. Roughly 30-70 FPS depending on the character.
Views cycle with `K`: character only, character with a camera inset, or camera with a
character inset. Keypoints and the skeleton are drawn on the camera image.
Keys: `K` view, `M` / `N` model, `F` detail, `L` keypoint names, `Y` / `P` rotate view,
`R` reset view, `D` debug, `H` help, `Q` quit.
## Run
```bash
pip install -r requirements.txt
python src/app.py
```
```bash
python src/app.py --model "Rigged Figure"
python src/app.py --camera 1 --pose-size 448 --no-mirror
```
by Salimli Ayzek (Салимли Айзек): https://mathematiclove.github.io