BodyRatioMapper Proportion Transfer
Steal one character's body proportions, keep another character's motion
- pose_keypoint
- ref_pose_keypoint
- manual_anchor_pose
- manual_first_frame
- changed_pose_keypoint
- anchor_pose_keypoint
- first_frame_output
This is the node the whole pack exists for, so let's start with the problem it solves. You've got a motion-capture style pose sequence - someone dancing, say - and you want to drive your character with it. The catch: your character has a different body. Different shoulder width, shorter legs, bigger head, whatever. Feed the raw pose straight into a motion-transfer pipeline and the character's proportions drift and wobble every frame, because the keypoints don't match its skeleton. BodyRatioMapperProportionTransfer fixes that: it takes the "target motion" and the "reference body shape," figures out how the reference's proportions differ from the motion's, and rescales the target pose to fit - one skeleton, consistently, across every frame. It's the preprocessing step that makes chibi characters and stylized OC bodies stop looking like they're wearing someone else's bones.
How it works
The pipeline is genuinely clever and mostly automatic. It also handles multi-person clips - people are matched across frames by nearest-neighbor plus sliding-window voting, so two characters walking past each other don't swap proportions mid-clip. Specifically, it:
- Picks an anchor frame. An anchor-selection routine scans your input and finds the frame with the most complete, confident skeleton - a "perfect straight-facing" frame, basically. That's your baseline body.
- Solves per-bone scale factors. Using forward-kinematics chain scaling, it compares each bone in the reference body against the same bone in the anchor frame and works out the ratio. Shoulder width, torso, arms, legs - each gets its own multiplier.
- Applies a global RPCA correction. One robust scale multiplier derived from bone-length ratios between the anchor and frame zero, so the body doesn't drift as the sequence progresses.
- Stabilizes the offset. Frame-to-frame stabilizers keep the body from jittering vertically (and optionally horizontally), and
final_offset_alignmentsnaps things together at the end.
For a beginner, the whole point is that you mostly don't have to touch any of this. The defaults are sane.
The inputs and outputs that matter
Two inputs do the actual work:
pose_keypoint(required) - the target pose: the motion sequence you want to keep. SDPose or OpenPose format.ref_pose_keypoint- the reference body: the source of proportions. This is the skeleton whose shape you want to impose on the target.
There are two optional override inputs, manual_anchor_pose and manual_first_frame, for when the auto anchor isn't good enough - hand the node a clean straight-facing pose and it'll use that as the baseline instead. Handy when the auto-detected anchor picks a weird frame.
From the long settings list, a beginner actually touches maybe three:
confidence_threshold(default 0.3) - how confident a keypoint must be to count. If your detection is noisy, lower it; that's the first thing to try when output looks empty or broken.enable_rpca(default off) - the global scale correction. Turn it on if the whole body scales wrong across the clip.output_absolute_coordinates(default on) - off gives normalized 0–1 coordinates, which some downstream pipelines want. If something downstream renders a tiny stick figure, check this.
head_fixed_mode and base_offset_mode are power-user stabilization knobs; leave them alone until you've seen a real failure.
Three outputs come out:
changed_pose_keypoint- the rescaled target sequence. This is the one you wire onward.anchor_pose_keypoint- the anchor frame it picked, for debugging.first_frame_output- frame zero after processing, useful when you need the reference-aligned start.
Typical flow: render changed_pose_keypoint with the pack's SDPose Render node to see what you're feeding a ControlNet or motion-transfer model.
Installation
cd ComfyUI/custom_nodes
git clone https://github.com/wuwukaka/ComfyUI-BodyRatioMapper.git
cd ComfyUI-BodyRatioMapper
pip install -r requirements.txt
Then restart ComfyUI. ComfyUI Manager users can just search "ComfyUI-BodyRatioMapper." The dependencies are torch, numpy, opencv-python, and matplotlib - you almost certainly already have all four in your ComfyUI environment, so this is one of the rare packs that installs without drama. There are no model files to download; this node consumes keypoints, it doesn't detect them. You need an external SDPose keypoint extractor feeding it (the example workflows use SDPoseKeypointExtractor plus a YOLO person detector, and want ComfyUI 0.16.1+).
Common issues
- Nodes don't appear after install. Confirm the folder is
ComfyUI/custom_nodes/ComfyUI-BodyRatioMapper(wrong name breaks the import), check the startup log for errors, and restart. - Empty or abnormal keypoints out. Feed it through the pack's
pose_keypoint previewnode to confirm the JSON is complete, then lowerconfidence_threshold. - Proportions swap between people. Check the input detection, not the node - multi-person tracking only works if the detector returns stable per-frame people lists. If the reference and target overlap on screen, crop or separate them.
One caveat before you get excited: this is a young, GPL v3 pack from a solo author (partly derived from ProportionChanger). The math is well-tested by the author's own videos, but you're the early adopter - keep the pack updated and don't throw away working workflows.
Inputs (23)
| Name | Type | Default | Description |
|---|---|---|---|
| pose_keypoint | POSE_KEYPOINT | Target pose keypoints (SDPose or OpenPose format) | |
| ref_pose_keypointopt | POSE_KEYPOINT | Reference pose keypoint (Source of proportions) | |
| manual_anchor_poseopt | POSE_KEYPOINT | (Optional) Override WSCS. Provide a perfect straight-facing pose to set the baseline proportions. | |
| manual_first_frameopt | POSE_KEYPOINT | (Optional) Override the first-frame reference for base_offset_mode. Used as the global offset alignment baseline when base_offset_mode is ON. | |
| enable_rpcaopt | BOOLEAN | false | Enable global RPCA multiplier (anchor vs frame-0 scale correction). |
| hand_scalingopt | BOOLEAN | true | — |
| foot_scalingopt | BOOLEAN | true | — |
| offset_stabilizer_yopt | BOOLEAN | true | — |
| offset_stabilizer_xopt | BOOLEAN | false | — |
| best_hand_searchopt | BOOLEAN | true | — |
| use_shoulder_fk_for_handopt | BOOLEAN | false | Use shoulder FK to replace hand FK. |
| use_torso_fk_for_armopt | BOOLEAN | false | Use torso FK to replace upper/lower arm FK. |
| use_torso_fk_for_footopt | BOOLEAN | false | Use torso FK to replace foot edge1/edge2/edge3 FK. |
| best_neck_searchopt | BOOLEAN | false | — |
| final_offset_alignmentopt | BOOLEAN | true | — |
| base_offset_modeopt | BOOLEAN | false | ON: align global offset by reference vs first frame. OFF: align by reference vs anchor frame. |
| head_fixed_modeopt | BOOLEAN | false | ON: per-frame nose alignment to reference nose, keeping head visually stationary. Overrides base_offset_mode and stabilizer. |
| match_original_ear_scaleopt | BOOLEAN | false | ON: compute ear-width ratio between anchor and first valid head frame, use as RPCA multiplier to match original ear size. |
| anchor_output_modeopt | COMBO | single_frame_multi_person | Anchor output layout mode. |
| print_detailed_logsopt | BOOLEAN | false | Enable verbose internal logs. OFF uses concise summary logs. |
| confidence_thresholdopt | FLOAT | 0.300–1 | Unified confidence threshold for WSCS and reference gating. |
| output_absolute_coordinatesopt | BOOLEAN | true | — |
| signatureopt | BOOLEAN | true | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| changed_pose_keypoint | POSE_KEYPOINT | — |
| anchor_pose_keypoint | POSE_KEYPOINT | — |
| first_frame_output | POSE_KEYPOINT | — |