Nodes/ComfyUI-BodyRatioMapper/BodyRatioMapper Proportion Transfer
ComfyUI Node

BodyRatioMapper Proportion Transfer

Steal one character's body proportions, keep another character's motion

By wuwukaka·Created 4 months ago·Updated about a month ago· 142
BodyRatioMapper Proportion Transfer
  • pose_keypoint
  • ref_pose_keypoint
  • manual_anchor_pose
  • manual_first_frame
  • changed_pose_keypoint
  • anchor_pose_keypoint
  • first_frame_output
enable_rpcafalse
hand_scalingtrue
foot_scalingtrue
offset_stabilizer_ytrue
offset_stabilizer_xfalse
best_hand_searchtrue
use_shoulder_fk_for_handfalse
use_torso_fk_for_armfalse
use_torso_fk_for_footfalse
best_neck_searchfalse
final_offset_alignmenttrue
base_offset_modefalse
head_fixed_modefalse
match_original_ear_scalefalse
anchor_output_modesingle_frame_multi_person
print_detailed_logsfalse
confidence_threshold0.30
output_absolute_coordinatestrue
signaturetrue

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:

  1. 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.
  2. 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.
  3. 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.
  4. Stabilizes the offset. Frame-to-frame stabilizers keep the body from jittering vertically (and optionally horizontally), and final_offset_alignment snaps 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 preview node to confirm the JSON is complete, then lower confidence_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.

CategoryBodyRatioMapper

Inputs (23)

NameTypeDefaultDescription
pose_keypointPOSE_KEYPOINTTarget pose keypoints (SDPose or OpenPose format)
ref_pose_keypointoptPOSE_KEYPOINTReference pose keypoint (Source of proportions)
manual_anchor_poseoptPOSE_KEYPOINT(Optional) Override WSCS. Provide a perfect straight-facing pose to set the baseline proportions.
manual_first_frameoptPOSE_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_rpcaoptBOOLEANfalseEnable global RPCA multiplier (anchor vs frame-0 scale correction).
hand_scalingoptBOOLEANtrue
foot_scalingoptBOOLEANtrue
offset_stabilizer_yoptBOOLEANtrue
offset_stabilizer_xoptBOOLEANfalse
best_hand_searchoptBOOLEANtrue
use_shoulder_fk_for_handoptBOOLEANfalseUse shoulder FK to replace hand FK.
use_torso_fk_for_armoptBOOLEANfalseUse torso FK to replace upper/lower arm FK.
use_torso_fk_for_footoptBOOLEANfalseUse torso FK to replace foot edge1/edge2/edge3 FK.
best_neck_searchoptBOOLEANfalse
final_offset_alignmentoptBOOLEANtrue
base_offset_modeoptBOOLEANfalseON: align global offset by reference vs first frame. OFF: align by reference vs anchor frame.
head_fixed_modeoptBOOLEANfalseON: per-frame nose alignment to reference nose, keeping head visually stationary. Overrides base_offset_mode and stabilizer.
match_original_ear_scaleoptBOOLEANfalseON: compute ear-width ratio between anchor and first valid head frame, use as RPCA multiplier to match original ear size.
anchor_output_modeoptCOMBOsingle_frame_multi_personAnchor output layout mode.
print_detailed_logsoptBOOLEANfalseEnable verbose internal logs. OFF uses concise summary logs.
confidence_thresholdoptFLOAT0.300–1Unified confidence threshold for WSCS and reference gating.
output_absolute_coordinatesoptBOOLEANtrue
signatureoptBOOLEANtrue

Outputs (3)

NameTypeDescription
changed_pose_keypointPOSE_KEYPOINT
anchor_pose_keypointPOSE_KEYPOINT
first_frame_outputPOSE_KEYPOINT