Openpose Keypoint Mask
Your pose skeleton has no shape — this node draws it a mask
- pose_keypoint
- MASK
Your pose preprocessor hands you a skeleton: a pile of keypoints with x, y and a confidence value. That's great for feeding a pose ControlNet, but it's useless the moment you want to do something with that body - mask a torso to re-dress it, isolate a face region, or composite the original body back over a regenerated frame. The skeleton has no shape, no area, nothing you can paste or inpaint against. Openpose Keypoint Mask is the postprocess step that fixes exactly that: it turns the POSE_KEYPOINT data into a real, drawable MASK.
How it works
The node reads the pose dict that comes out of a preprocessor (in the shipped workflows it's DWPreprocessor, the DWPose node from ControlNet Auxiliary Preprocessors - same thing that feeds pose ControlNet), then does three things per person:
- Pulls the keypoints you asked for out of
points_listand computes a bounding box around them (or, intorsomode, a box sized from the neck-to-hip distances). - Draws a solid shape - oval, square, or triangle - filling that box on a black canvas.
- Optionally rotates the shape to match the body part's actual angle, then pastes it at the right spot on a canvas of your chosen
image_width×image_height.
The output is a white shape on black, i.e. a MASK. Keypoints with zero confidence get skipped, so a limb the detector couldn't see just doesn't contribute. It loops over every person in the frame unless you pin it down with person_index.
The three inputs that actually matter are the first three, and they're the ones people get wrong. pose_keypoint comes straight from the preprocessor's POSE_KEYPOINT output. image_width and image_height must match the image you're compositing onto - the standard move is to wire Get Image Size from the same source image into both, which is exactly what the example workflow does. If those numbers disagree with your target canvas, your mask lands somewhere that isn't where the person is.
The optional list is long but most of it is fine-tuning. points_list is comma-separated COCO keypoint indices: the default 1,8,11 is neck plus both hips (the torso), 0,1,14,17 is the face, 8,9,10 is one leg. mode picks box (bounding box of whatever you listed) or torso (an automatic torso-sized region), shape picks oval/square/triangle, auto_rotate spins the shape to align with the limb - handy when someone's leaning. alpha (0–1) fades the mask, and person_index set to 0+ isolates a single person in a group shot. x_offset/y_offset and the zoom/min knobs are nudges you'll rarely touch on a first pass.
Installing it
It's a zero-dependency pack - the only libraries it touches are torch, numpy and PIL, which ComfyUI already ships. No model files download from this repo. The easiest path:
# via ComfyUI Manager: search "PoseKeypoint Mask" and install
cd ComfyUI/custom_nodes
git clone https://github.com/muzi12888/ComfyUI-PoseKeypoint-Mask
Restart ComfyUI after installing. The one heavy download you will hit is upstream: the DWPreprocessor you're feeding it pulls yolox_l.onnx and dw-ll_ucoco_384_bs5.torchscript.pt into models/annotator/ on first run. That's a real and common failure point - people hit missing/corrupt .incomplete download files, usually fixable by deleting the partial file and re-running.
Common gotchas
- Mismatched canvas size. The mask only lines up with your image if
image_width/image_heightmatch the canvas you composite onto. UseGet Image Size; don't hardcode. - Empty or degenerate masks. Wrong keypoint indices, or a body part the detector missed (zero confidence), and you get a tiny dot or nothing. Check the skeleton preview first.
- It's a geometric shape, not a silhouette. An oval over a torso is approximate by design. Run it through
GrowMask/MaskBlurbefore compositing, or the edges will show. - Group shots.
person_indexfilters to one person; leave it at -1 to mask everyone.
This isn't a flashy node - it's a utility that sits between "I have keypoints" and "I have a mask I can inpaint, composite, or redraw into." Once you need body-region masks in a pose-driven workflow, it's hard to find a simpler way to get them.
Inputs (16)
| Name | Type | Default | Description |
|---|---|---|---|
| pose_keypoint | POSE_KEYPOINT | — | |
| image_width | INT | 0–16384 | — |
| image_height | INT | 0–16384 | — |
| points_listopt | STRING | 1,8,11 | — |
| modeopt | COMBO | box | 2 options: box, torso |
| shapeopt | COMBO | oval | 3 options: oval, square, triangle |
| x_offsetopt | FLOAT | 0.00-10–10 | — |
| y_offsetopt | FLOAT | 0.00-10–10 | — |
| x_zoomopt | FLOAT | 1.00–100 | — |
| y_zoomopt | FLOAT | 1.00–100 | — |
| x_minopt | FLOAT | 0.0000–1 | — |
| y_minopt | FLOAT | 0.0000–1 | — |
| person_indexopt | INT | -1 | — |
| auto_rotateopt | BOOLEAN | true | — |
| back_hideopt | BOOLEAN | false | — |
| alphaopt | FLOAT | 1.00–1 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MASK | MASK | — |