Batched OpenPose Pose
OpenPose That Actually Enjoys Being Fed a Video
- image
- image
- pose_keypoint
- Pose Overlay Mask
If you've ever run a pose pass over a 200-frame clip with the classic OpenPose preprocessor, you know the shape of that afternoon. UC_BatchedOpenPose is a from-scratch, eager-PyTorch OpenPose implementation that takes an image batch - a video frame sequence - and works through it in chunks, with a video-specific filter tacked on.
It ships in ComfyUI-UtilsCollection, a kitchen-sink pack from silveroxides - obscure enough that you'll be reading tooltips, not forum threads.
What it actually does
Pose conditioning still matters in the edit-model era: an edit model has no strength dial, so partial strength - or two conditions at once - still means ControlNet. OpenPose is the pose half of that, with 17 body joints, 70 face landmarks and 21 points per hand.
Mechanically it's the classic 2017 pipeline: the body model predicts heatmaps plus part-affinity fields, joints fall out of the heatmaps, and the affinity field is what decides whether two joints are actually connected. Then it crops boxes around the detected hands and face and runs those models on the crops.
Unlike comfyui_controlnet_aux, none of Ultralytics, ONNX Runtime, MMPose or TorchScript is a runtime dependency here. But the author is upfront in the README that speed and prediction parity against the original preprocessors "need real-model validation" - the converted weights are verified for shape/dtype/value correctness, not for matching the reference implementation joint for joint. If your whole pipeline is tuned around exact legacy pose maps, test before you rebuild anything.
The inputs worth touching
image takes the batch; for the temporal options, feed consecutive frames in order, not a folder of unrelated pictures.
detect_hand, detect_face and detect_body all default on. Hand and face off genuinely skips those models - that's your speed lever. Body off does not skip body inference; it only stops drawing it, because body inference is what locates the hands and faces in the first place.
resolution (0 = leave the frames as supplied, otherwise the shortest edge in pixels) and batch_size (default 4) are the memory pair. Drop batch_size first if you're running out of VRAM, since hand and face crops are also processed batch_size at a time.
The body threshold cluster is where you tune quality: body_threshold (0.45), hand_threshold, face_threshold, limb_threshold (how much evidence a limb line needs), limb_support (0.8 - the fraction of sampled limb points that must pass limb_threshold, and strictly, so 1 rejects everything), min_body_parts (4) and min_body_score (0.4, not a probability). Raising them rejects junk skeletons and partly-visible people along with it.
Below-threshold face landmarks are kept as empty slots rather than dropped, so landmark indices can't shift between frames of a video.
Then there are the six temporal options, off by default: temporal_filter, temporal_radius (2), temporal_min_support (2), temporal_max_distance (0.1 = 10% of the body-box diagonal), temporal_match_iou (0.3). It prunes joints that nearby frames can't confirm, from both the drawing and the keypoints. It does not smooth, and it does not fill anything in. Matching spans your batch_size chunks, so raising the batch doesn't break the filter. Leave it off for unrelated stills.
Outputs
image is the pose map in frame order - the thing you feed a pose ControlNet. pose_keypoint is OpenPose-format keypoints after thresholding and temporal filtering. Pose Overlay Mask is white on drawn limbs and points, black elsewhere: handy for compositing the pose map over your footage. It's not a person silhouette.
Install
Manager → search "ComfyUI-UtilsCollection", or:
cd ComfyUI/custom_nodes
git clone https://github.com/silveroxides/ComfyUI-UtilsCollection
# restart ComfyUI
Models are not in the repo. They download on first execution from silveroxides/ComfyUI-UtilsCollection-Models via huggingface_hub, and land flat in ComfyUI/models/controlnet/preprocessors (registered off your normal controlnet roots, so extra model paths work). Files: openpose_body.safetensors, openpose_hand.safetensors, openpose_face.safetensors. To place them yourself:
mkdir -p ComfyUI/models/controlnet/preprocessors
huggingface-cli download silveroxides/ComfyUI-UtilsCollection-Models \
preprocessors/openpose/openpose_body.safetensors --local-dir /tmp/uc
cp /tmp/uc/preprocessors/openpose/openpose_body.safetensors \
ComfyUI/models/controlnet/preprocessors/
Where people get burned
The node imports kornia at module load, and kornia isn't in the pack's requirements.txt. If you don't already have it from another pack, the whole node pack fails to import until you pip install kornia in ComfyUI's environment. Same story for torchaudio, scipy and torchvision, which the pack also imports - those normally arrive with ComfyUI, kornia often doesn't.
The first queue with the pack installed hits the network. Offline or behind a proxy, you get a download error instead of a pose map; pre-place the three files above and it will reuse them.
One more install detail: this pack is written against ComfyUI's newer V3 node schema (comfy_api.latest) and uses autogrow/dynamic inputs, so it wants a current ComfyUI. On an old build you get import errors and missing nodes, not a subtly wrong pose map.
And the usual one: a pose map is only as good as the ControlNet reading it. Current union models want their published scale - 0.65–0.8 on most 2026 ones - so don't carry an SDXL-era 1.0 across and then blame the estimator.
Inputs (19)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Image or image batch to process. For temporal filtering, supply consecutive video frames in order, not unrelated images. | |
| detect_hand | BOOLEAN | true | Detect and draw hand joints. Turn off to skip the hand model and reduce processing time; hand keypoints will be omitted. |
| detect_body | BOOLEAN | true | Draw body skeletons. Body inference still locates hands/faces and produces keypoints. |
| detect_face | BOOLEAN | true | Detect and draw facial landmarks. Turn off to skip the face model and reduce processing time; face keypoints will be omitted. |
| resolution | INT | 00–4096 | 0 preserves the input dimensions. A positive value sets the output's shortest edge in pixels, preserving aspect ratio. Larger maps do not increase the body model's fixed processing scale. |
| batch_size | INT | 41–64 | Maximum frames or person crops per network call. Lower this if VRAM is insufficient. |
| scale_stick_for_xinsr_cn | BOOLEAN | false | Scale body-line thickness with image size for Xinsir-style pose maps. Changes drawing only, not detected coordinates. |
| body_threshold | FLOAT | 0.450–1 | Minimum strength of a body-joint candidate. Raise to reject weak joints; lower to recover faint joints at the risk of false detections. |
| hand_threshold | FLOAT | 0.450–1 | Minimum strength of a hand-joint candidate. Raise to remove uncertain fingers; lower to retain more joints. Only used when hand detection is on. |
| face_threshold | FLOAT | 0.450–1 | Minimum strength of a facial landmark. Raise to remove uncertain points; lower to retain more detail. Only used when face detection is on. |
| limb_threshold | FLOAT | 0.450–1 | Required evidence along the line connecting two body joints. Raise to reject unlikely limb connections; too high can break valid skeletons. |
| limb_support | FLOAT | 0.800–1 | Fraction of sampled positions along a limb that must pass limb_threshold; the accepted fraction must be strictly greater. Raise for stricter connections; 1 rejects every connection. |
| min_body_parts | INT | 41–18 | Minimum connected joints needed to keep a person. Raise to reject tiny false skeletons; lower for partly visible people. |
| min_body_score | FLOAT | 0.400–10 | Minimum average skeleton score, combining joint and connection evidence. Raise to reject weak people; lower for difficult poses. This is not a probability. |
| temporal_filter | BOOLEAN | false | Video frames only: remove joints unsupported by nearby frames from both pose maps and keypoints. Keeps person entries; does not smooth or fill missing joints. Leave off for unrelated images. |
| temporal_radius | INT | 21–30 | Temporal filter only: frames to inspect before and after each frame. 2 checks up to four neighbors, across batch_size chunks. Larger windows cost more and may reject fast motion. |
| temporal_min_support | INT | 21–60 | Temporal filter only: neighboring frames that must confirm a joint. Raise to remove more flicker; lower to retain brief poses. Limited to available neighbors, including at clip edges. |
| temporal_max_distance | FLOAT | 0.100.001–1 | Temporal filter only: allowed joint displacement relative to the person's body-box diagonal; 0.1 means 10%. Raise for faster motion; lower to reject sudden jumps. |
| temporal_match_iou | FLOAT | 0.300–1 | Temporal filter only: required overlap between body boxes to match a person across frames. Raise to avoid mixing people; lower for faster movement or changing boxes. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | Pose maps in input-frame order, showing the enabled body, hand and face drawings. |
| pose_keypoint | POSE_KEYPOINT | Per-frame OpenPose-format keypoints after thresholding and optional temporal filtering. Disabled hand/face detectors omit those landmarks. |
| Pose Overlay Mask | MASK | White on rendered pose lines and points; black elsewhere. Use to composite the pose map over an image or video. Matches pose-map size and frame order; not a person silhouette. |