Nodes/ComfyUI-Sapiens2/Sapiens2 Pose (308 KP)
ComfyUI Node

Sapiens2 Pose (308 KP)

308 human keypoints, down-mapped to OpenPose when you need it

By kijai·Created 4 months ago·Updated 4 months ago· 65
Sapiens2 Pose (308 KP)
  • image
  • sapiens2_model
  • bboxes
  • keypoints
output_formatopenpose
include_facefalse
frames_per_batch1

Pose estimation is the ControlNet preprocessor that made reposing people actually controllable, and Sapiens2 does it with a 308-keypoint layout that includes both hands' full finger chains and dense facial landmarks - far beyond the 17-joint skeleton most detectors give you. This node runs the Sapiens2 pose head on your image and hands you those keypoints. The clever part is the output format: it can hand them to you as OpenPose-compatible data, so every downstream openpose tool and ControlNet model you already use understands it.

How it works

Wire in the image and a SAPIENS2_MODEL from the Loader that loaded a -pose checkpoint. Two decisions matter:

  • output_format - openpose (default) remaps the 308 keypoints into the classic OpenPose shape: 17 body joints + 6 foot + 21+21 hand keypoints (plus 70 face landmarks if you tick include_face), stored as pose_keypoints_2d / foot_keypoints_2d / hand_* / face_keypoints_2d. This is what controlnet/openpose conditioning expects. raw_308 gives you the full native Sapiens2 layout with no remapping - mostly for the DrawPose node, which can render the complete 308-point skeleton with per-part coloring.

  • bboxes (optional, connection-only - you can't type it in) - person bounding boxes from a detector like RT-DETR, SDPoseFaceBBoxes, or SAM3. Give it boxes and the node does proper top-down inference: each person is cropped and warped individually to the model's 1024×768 input, matching how upstream Sapiens2 runs, then coordinates are remapped back to your image. Without boxes, the whole image gets resized and run as one person - fine for a tight single-person crop, wrong for a group shot.

  • frames_per_batch - frames per forward pass for video. The keypoint decode uses a DARK-style heatmap peak with blur, which is why the joints stay stable frame to frame instead of jittering like a naive argmax.

Output is keypoints (type POSE_KEYPOINT), a frame-per-image structure with per-person data. From here it goes one of two ways: into Sapiens2 Draw Pose to render an actual image (then into a ControlNet openpose conditioner or just saved as a visual), or straight into any node that consumes pose data.

The workflow you actually want

LoadImage → ImageResize → Sapiens2 Loader (pose-1b) → Sapiens2Pose → Sapiens2DrawPose → SaveImage
                                                              └→ ControlNet (openpose) → KSampler

include_face is off by default for a reason: it costs a little accuracy budget, and most reposing only needs the body. Turn it on when you're driving facial expression or lip shape. And the honest tip from running this pack: on a photo with one person, skip the detector and just pre-crop - the full-image path is simpler and nearly as good; on anything with multiple people, wire the bboxes or every person melts into one averaged skeleton.

Install: Manager search "ComfyUI-Sapiens2", or git clone https://github.com/kijai/ComfyUI-Sapiens2 into custom_nodes, restart. Pose checkpoints from facebook/sapiens2-pose-1b (0.4B is notably worse on hands and face) go into ComfyUI/models/sapiens2. No pip dependencies, but you need a recent ComfyUI - this pack targets the newer io.ComfyNode API.

CategorySapiens2

Inputs (6)

NameTypeDefaultDescription
imageIMAGE
sapiens2_modelSAPIENS2_MODEL
output_formatCOMBOopenpose2 options: openpose, raw_308
include_faceBOOLEANfalse
frames_per_batchINT11–256Frames per forward pass. Lower if you OOM.
bboxesoptBOUNDING_BOX[object Object]Person bboxes (RT-DETR / SDPoseFaceBBoxes / SAM3). When given, each person is cropped+warped individually (matches upstream Sapiens2 inference). Without bboxes, the whole image is resized — only correct when input is already a single-person crop.

Outputs (1)

NameTypeDescription
keypointsPOSE_KEYPOINT