PoseInversion#
PoseInversion is the inverse-fitting utility used by the conversion tools in this
repository.
It fits SOMA-compatible skeleton rotations from posed vertices and supports:
analytical inverse-LBS refinement
optional Lie algebra Gauss-Newton refinement
optional autograd-based refinement through FK + LBS
This makes it the key API for conversions such as SMPL-to-SOMA and MHR-to-SOMA.
- class soma.pose_inversion.PoseInversion(
- soma_layer,
- low_lod=True,
- skeleton_transfer_rotation_method='auto',
- refit_rotation_method='auto',
Bases:
objectInvert posed vertices to a layer’s skeleton rotations.
Accepts vertices in the wrapped layer topology. For
SOMALayer, it also accepts supported identity-model native topologies (MHR, SMPL, etc.) and transfers them through the identity model’s barycentric interpolator. All translational inputs and outputs are in the wrapped layer’soutput_unit.- Parameters:
low_lod (bool) – Use low-LOD SOMA topology (4505 verts) for the iterative refit. This is ~4x fewer vertices than mid-LOD (18056) with negligible accuracy loss (~0.006 cm). When True and the given soma_layer is mid-LOD, a second low-LOD SOMALayer is created internally for the refit. XLO layers keep their own topology because there is no direct xlo-to-low vertex transfer. Default
True.skeleton_transfer_rotation_method (str) – rotation extraction method used by the initial
SkeletonTransferpose estimate."auto"uses a Newton-Schulz-first reference-gauge policy.refit_rotation_method (str) – rotation extraction method used by the analytical inverse-LBS refit.
"auto"applies a weak reference-rotation gauge to the local Procrustes covariance, then uses SVD only as a final validity projection if Newton-Schulz does not produce a rotation."kabsch"and"newton-schulz"remain available for diagnostics.
Usage:
inv = PoseInversion(soma_layer) inv.prepare_identity(identity_coeffs, scale_params) result = inv.fit(posed_vertices) # any supported topology, in soma_layer.output_unit
- transfer_to_soma(vertices)#
Transfer vertices from identity-model topology to SOMA topology.
If vertices are already on SOMA topology, returns them unchanged.
- Parameters:
vertices (Tensor) – (B, V, 3) or (V, 3) in any supported topology.
- Returns:
(B, V_soma, 3) vertices on SOMA topology.
- Return type:
Tensor
- prepare_identity(
- identity_coeffs,
- scale_params=None,
- repose_to_bind_pose=True,
- kwargs=None,
Set up rig from identity parameters.
Supports both single identity
(1, C)and batched identities(B, C). Structural caches (sparse weights, groups, levels) are built once on the first call and reused on subsequent calls. Per-identity bind data (bind_local_t,W_bind_inv,bind_verts) is updated every call.- Parameters:
identity_coeffs (Tensor) – (1, C) or (B, C) identity coefficients.
scale_params (Tensor | None) – (1, S) or (B, S) optional scale parameters.
repose_to_bind_pose (bool) – if True (default), transform the rest shape into SOMA’s bind pose. Set to False when the target vertices are posed relative to the identity model’s native rest pose (e.g. MHR).
kwargs (Mapping[str, Any] | None) – optional dict passed to the identity model’s
get_rest_shape.
- fit(
- posed_vertices,
- body_iters=2,
- finger_iters=0,
- full_iters=1,
- lie_iters=3,
- lie_lambda=1e-1,
- autograd_iters=0,
- autograd_lr=5e-3,
- autograd_translation_lr_scale=1.0,
- autograd_pose_prior=0.0,
- autograd_leaf_weight=None,
- autograd_pose_prior_weights=None,
- constrain_1dof=False,
- leaf_weight=1.0,
- batch_size=None,
Fit SOMA skeleton rotations to posed vertices.
Supports several modes depending on the iteration arguments:
Analytical + Lie algebra Gauss-Newton (default):
body_iters=2, full_iters=1, lie_iters=3. The analytical solve gives a fast warm start, then Lie-GN solves all active joint rotations simultaneously via a dense FK-coupled normal equation.Analytical only:
lie_iters=0.Lie algebra Gauss-Newton only:
body_iters=0, full_iters=0, lie_iters=5.Autograd FK only:
body_iters=0, full_iters=0, lie_iters=0, autograd_iters=10. Slow but controllable (e.g. extra weights on extremities).Default + autograd FK:
autograd_iters=10. The default analytical + Lie-GN solve warm-starts autograd refinement.
- Parameters:
posed_vertices (Tensor) – (B, V, 3) vertices on any supported topology.
body_iters (int) – analytical iterations for body chain (default: 2).
finger_iters (int) – analytical iterations for finger chain (default: 0).
full_iters (int) – analytical iterations for all joints (default: 1).
lie_iters (int) – Lie algebra Gauss-Newton iterations (default: 3). When > 0, runs a dense batched Gauss-Newton solve in SO(3) after the analytical solver. Each iter solves a (3J x 3J) system for all joint twists simultaneously.
lie_lambda (float) – Tikhonov regularisation for the Lie-GN normal equations (default: 1e-1).
autograd_iters (int) – Adam optimization steps through FK + LBS (default: 0). When > 0, runs autograd refinement after the analytical solve.
autograd_lr (float) – learning rate for autograd Adam (default: 5e-3).
autograd_translation_lr_scale (float) – multiplier for the root-translation Adam learning rate. Useful because translations are optimized in layer output units while rotations use unitless 6D parameters.
autograd_pose_prior (float) – local-rotation prior weight for autograd FK. Penalizes deviation from the initial local rotation matrices. 0.0 disables it.
autograd_leaf_weight (float | Mapping[str, float] | None) – optional vertex weighting used only by the autograd FK stage. This lets the analytical/Lie warm start remain unweighted while the refinement emphasizes contact regions.
autograd_pose_prior_weights (Mapping[str, float] | None) – optional per-joint multipliers for the autograd pose prior. Values > 1 stiffen a joint relative to the warm start; values < 1 let it move more.
constrain_1dof (bool) – apply 1-DOF constraints on elbows/knees (analytical only).
leaf_weight (float | Mapping[str, float]) – importance multiplier for extremity vertices. Float for uniform (e.g. 3.0), or dict for per-group (e.g.
{"head": 2, "hands": 2, "feet": 5, "heels": 10}). 1.0 = uniform (default).batch_size (int | None) – process in chunks of this size.
- Returns:
dict with
rotations(B, J, 3, 3),root_translation(B, 3), andper_vertex_error(B, V) L2 error per vertex.- Return type:
PoseInversionResult