OpenPose to Point List π§
Keypoints as JSON instead of a skeleton drawing
- image
- POINT_LIST
- IMAGE
Most people know OpenPose from ControlNet: you run a preprocessor, you get a skeleton drawing, and the drawing guides generation. This node does something weirder and more useful for a specific job - it detects the same body keypoints but outputs them as a JSON string of coordinates. If you want the data of where a person's face, hands, or joints are, rather than a picture of them, this is the node.
How it works
It's built on the controlnet_aux OpenPose detector, which is bundled inside the pack's own repo - no separate install needed. On first use it downloads the pose model from HuggingFace (lllyasviel/Annotators), so your first run will hang for a bit while it fetches weights. That's expected, not a bug.
Feed it an image and it runs pose detection. The method dropdown decides what comes out:
face- the average position of the nose/eyes/ears, one point per detected person.hand- the left and right wrist positions per person.all- every detected keypoint per person (17 joints: nose, neck, shoulders, elbows, wrists, hips, knees, ankles, eyes, ears), each with x, y, and a confidence score.
detect_resolution controls the internal resize (default 512, up to 2048) - higher gives more accurate detection on small subjects at the cost of speed. The coordinates are normalized (0.0 to 1.0, relative to image size), which is the key detail for everything downstream.
The node also outputs a second IMAGE - the classic OpenPose skeleton drawing - so you can preview what it detected or feed it into a ControlNet that wants a pose image. You get both the data and the picture in one go.
Inputs and outputs
image,detect_resolution,method.- Outputs:
POINT_LIST(JSON string) andIMAGE(skeleton visualization).
Why JSON keypoints beat a drawing
Because the coordinates are numbers, you can do math on them. That's the whole point of this node's existence: it feeds the pack's PointListToMask (turn keypoints into round mask blobs) and DetectFaceRotationForInpainting (estimate head rotation from the nose-to-neck vector). The all output is the one those two expect. If you're not using those companion nodes, you probably just want a normal OpenPose ControlNet preprocessor instead - this node's superpower is that its output is structured data, and structured data needs a consumer.
Installing it
It's part of ComfyUI-NegiTools - ComfyUI Manager (search "ComfyUI-NegiTools") or:
cd ComfyUI/custom_nodes
git clone https://github.com/natto-maki/ComfyUI-NegiTools
pip install -r ComfyUI-NegiTools/requirements.txt
then restart. No API key. Just remember that first-run weight download.
The gotcha
The detection quality ceiling is OpenPose-level, not DWPose-level - on busy scenes, low resolution, or heavily cropped subjects, you'll get misses or low-confidence points that land wrong. The all method includes a score per point, so you can filter out weak detections downstream if you're writing your own JSON consumers. And since the skeleton IMAGE output exists mainly for preview, don't expect it to rival a dedicated ControlNet preprocessor's drawing - for ControlNet itself you're usually better off with a standard OpenPose node; this one shines when you need the numbers.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | β | |
| detect_resolution | INT | 51264β2048 | β |
| method | COMBO | 3 options: face, hand, all |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| POINT_LIST | STRING | β |
| IMAGE | IMAGE | β |