Pose Align (2→1)
Drop a pose map onto a reference with a canvas, not guesswork
- ref_pose_img
- ref_pose_json
- poseA_img
- poseA_json
- poseB_img
- poseB_json
- aligned_poseA
- aligned_poseB
- combined_AB
- combine_all
If you've done pose-control work - OpenPose, DWPose, any of the skeleton maps that drive pose ControlNets - you know the pain this node targets. You've got a reference pose you like and a pose map that doesn't line up with it. Maybe the character is too tall, angled wrong, or sitting ten pixels to the left, and "fixing" it means rebuilding the skeleton in an external editor or stacking image-transform nodes with values you pick blind.
Pose Align (2→1) is the pack's actual reason to exist: an interactive canvas node that lets you drag, scale, and rotate pose maps directly onto a reference, visually, the way you'd nudge layers in Photoshop. The "2→1" in the name means it aligns up to two poses (A and B) onto one reference pose.
How it works
You feed it the reference pose plus the poses you want to move - each as an image and its matching POSE_KEYPOINT data. That keypoint type is a native ComfyUI type, produced by the DWPose/OpenPose preprocessors in ComfyUI ControlNet Aux (they output image + keypoints together) or by ComfyUI's built-in SDPose keypoint extractor. The reference stays fixed; each pose image gets warped with an affine transform - rotation, scale, translation - and composited onto a black canvas sized to the reference.
The clever bit is the node's canvas widget. Drag to move, scroll to scale, Shift+scroll to rotate, per pose. The node stores the resulting transform and rebuilds the image every time, so you're not blind-guessing numbers. There's also a debug toggle (off by default) if you want the console to explain what it did.
One honest gotcha: the current release is manual-only. The pack's utils contain a full automatic fitting pipeline - Procrustes rotation, robust scale from torso segments, translation refinement - but the latest commit ("Simplify PoseAlign node to manual-only mode") stopped calling it. The keypoint JSONs are still required inputs, but in this version they're not doing the aligning; your canvas gestures and sliders are. Don't queue it expecting auto-fit.
The inputs and outputs that matter
Required, in order of importance:
ref_pose_img+ref_pose_json- the reference pose, stays putposeA_img+poseA_json- first pose you moveangle_deg_A,scale_A,tx_A,ty_A- A's manual transform (angle ±720°, scale 0.2–3.0, translate ±2048 px)
Optional: poseB_img + poseB_json (second pose, for 2→1 compositing) plus angle_deg_B/scale_B/tx_B/ty_B, and debug. Leave pose B disconnected and it runs in single-pose mode.
Outputs are four IMAGE streams: aligned_poseA, aligned_poseB, combined_AB (A composited over B), and combine_all (everything overlaid on the reference). Wire the aligned pose map into a ControlNet Apply with a pose model - or into a keypoint-drawing node - and you've got a properly positioned condition for the sampler. The node is also an output node (it inherits PreviewImage), which is where that "saves the input images to your ComfyUI output directory" description on comfy.icu comes from - that's a side effect, not the point.
Installing
It's a one-commit pack with a stub README and no requirements.txt - nothing heavy. Install once, get both nodes:
cd ComfyUI/custom_nodes
git clone https://github.com/rubenvillarreal/ComfyUI_PoseAlign
Restart ComfyUI. (Or ComfyUI Manager → search "ComfyUI_PoseAlign" → install.) It depends on opencv, numpy, and torch, all already in a stock ComfyUI env - no model downloads. You do need a pose detector installed to supply the POSE_KEYPOINT inputs, so add comfyui_controlnet_aux (functionally required for any serious ControlNet work anyway) or rely on ComfyUI's native SDPose nodes.
Troubleshooting
- PoseAlignTwoToOne missing from the menu but SimpleTestNode present - the pose module failed to import; check the console for the
[PoseAlign] ERROR loading pose_align_node:line. - Won't queue on the JSON inputs - you must connect a real POSE_KEYPOINT source (DWPose/OpenPose/SDPose); a bare image alone doesn't satisfy
poseA_json. - Console spam - this pack logs its whole reasoning to the terminal on every run. Annoying, harmless.
- Output looks black around the figure - that's
BORDER_CONSTANTfill working as intended; the pose map is meant to be fed to a ControlNet, where black is "no condition."
Honest verdict: this is a niche helper from a small, early-stage pack - useful if you hand-align pose maps often, and a genuinely nicer way to do it than stacking transform nodes. Just know going in that the "smart" auto-alignment the utilities suggest isn't wired up yet.
Inputs (15)
| Name | Type | Default | Description |
|---|---|---|---|
| ref_pose_img | IMAGE | — | |
| ref_pose_json | POSE_KEYPOINT | — | |
| poseA_img | IMAGE | — | |
| poseA_json | POSE_KEYPOINT | — | |
| angle_deg_A | FLOAT | 0.0-720–720 | — |
| scale_A | FLOAT | 1.000.2–3 | — |
| tx_A | INT | 0-2048–2048 | — |
| ty_A | INT | 0-2048–2048 | — |
| angle_deg_B | FLOAT | 0.0-720–720 | — |
| scale_B | FLOAT | 1.000.2–3 | — |
| tx_B | INT | 0-2048–2048 | — |
| ty_B | INT | 0-2048–2048 | — |
| poseB_imgopt | IMAGE | — | |
| poseB_jsonopt | POSE_KEYPOINT | — | |
| debugopt | BOOLEAN | false | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| aligned_poseA | IMAGE | — |
| aligned_poseB | IMAGE | — |
| combined_AB | IMAGE | — |
| combine_all | IMAGE | — |