SapiensSampler
One image in, seg + pose + depth + normal + mask out
- model
- image
- cond
- seg_img
- pose_img
- depth_img
- normal_img
- pointmap_img
- albedo_img
- matting_img
- mask
If SapiensLoader is the toolbox, SapiensSampler is the hand that opens it. You feed it the loader's model handle plus an image, and it runs every model you loaded in one pass, handing back seven image outputs and a mask - segmentation, pose, depth, normal, pointmap, albedo, matting, and the alpha-style person mask. Everything the pack can tell you about a person, on one node, in one inference call.
This is the node that turns "Meta's Sapiens" from a research model into a working ControlNet pipeline. The seg map feeds region-based composition control, the depth map constrains spatial structure, the normal map drives relighting workflows, and the pose gives you the skeleton for pose-conditioned generation - the whole controlnet_aux job list, minus the extra packs. The mask output drops straight into inpainting or background-removal workflows (think BiRefNet-level cutouts, though this one is person-first).
How it works
The sampler is model-agnostic about which of the seven you loaded - it just calls whatever the predictor holds and returns a zero tensor for anything you didn't load. That's the key behavior to internalize: a black output isn't a crash, it's a "you didn't load this model" signal.
Under the hood there are two code paths. The v1 (Sapiens, V2 off) path moves the model to CUDA for inference, then CPU-offloads it afterwards to keep VRAM free. The v2 (Sapiens2, default) path keeps models on CPU and predicts from there. Batch inputs are chunked per-frame and reassembled, so you can throw multiple images at it and get aligned stacks back.
The inputs
- model - straight from SapiensLoader.
- image - the photo or render you're analyzing. The higher the resolution, the better the fine maps; it'll happily do a batch.
- cond (optional) - the output of the pack's SapiensSplit node. When provided, it filters the segmentation to only the body parts you selected and repaints everything else with the background color - more on that in the SapiensSplit article.
- BG_R / BG_G / BG_B (default 255,255,255) - the RGB color that "everything you didn't select" becomes, when a
condis active. White is the sensible default for mask-style outputs; set it to black or green-screen green if a downstream node wants it. - save_pose - when on and a pose was produced, it dumps the raw keypoints as
*.npyfiles into your ComfyUI output directory. Grab this if you want the actual skeleton data, not just the drawing.
The outputs and what to do with them
- seg_img - the color-coded body-part map. Feed it to a seg ControlNet, or into an inpaint workflow.
- pose_img - the skeleton render. Note this is Sapiens' own keypoint convention (308 Goliath keypoints in v2, detected via YOLOv8), which is not OpenPose-compatible - a pose ControlNet trained on OpenPose may not read it directly. Render it, then preprocess if needed.
- depth_img / normal_img - geometry and surface orientation. Classic ControlNet depth conditioning and relighting material.
- pointmap_img / albedo_img - the Sapiens2 extras: a point map and a lighting-independent albedo (base-color) version of the person.
- matting_img - the soft matte. Hand this to a compositing step when you need to re-background a person without hard cutout edges.
- mask - the person silhouette, ready for inpainting or masking-based editing.
Installing
It ships inside the same pack as the loader - ComfyUI Manager, search ComfyUI_Sapiens, or git clone https://github.com/smthemex/ComfyUI_Sapiens into ComfyUI/custom_nodes, then pip install -r requirements.txt (ultralytics is needed for the pose path). Models go in ComfyUI/models/sapiens/.
Common issues
- A black output for one of the slots - you didn't load that model in SapiensLoader. Add it, or ignore the output.
- No pose - pose needs both a Sapiens pose checkpoint and the YOLO person detector (
yolov8m.pt, auto-downloaded if absent). Checkmodels/sapiens/. - Save pose writes nothing -
save_poseonly fires when the pose path ran; no pose model, no.npyfiles. - VRAM pressure - this node loads big models; bfloat16 in the loader and the automatic CPU offload do the heavy lifting. If you're still OOMing, load fewer models.
One pass, seven maps, a mask, and a data export. That's the whole pitch - and for a person-in-the-frame pipeline, it's hard to beat.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| image | IMAGE | — | |
| save_pose | BOOLEAN | false | — |
| BG_R | INT | 2550–255 | — |
| BG_G | INT | 2550–255 | — |
| BG_B | INT | 2550–255 | — |
| condopt | CONDITIONING | — |
Outputs (8)
| Name | Type | Description |
|---|---|---|
| seg_img | IMAGE | — |
| pose_img | IMAGE | — |
| depth_img | IMAGE | — |
| normal_img | IMAGE | — |
| pointmap_img | IMAGE | — |
| albedo_img | IMAGE | — |
| matting_img | IMAGE | — |
| mask | MASK | — |