DensePose Estimator
Per-pixel body maps for pose and animation control
- image
- IMAGE
Where OpenPose gives you a stick figure, DensePose gives you a full body-surface map - every pixel of a person colored by where it sits on a 3D body model. The output looks like a person painted in smooth gradients of color, and it encodes far more than joint positions: it captures the orientation of the body surface itself, so it knows which way a torso is turned, how a limb is foreshortened, how the shape wraps. That extra information makes it the pose representation of choice for clothing detail, skin, and especially character animation pipelines, where a stick figure just isn't enough to keep a body coherent frame to frame.
How it works, and how it differs from OpenPose
OpenPose detects keypoints - joints, connected by lines. DensePose instead maps every visible body pixel to UV coordinates on the SMPL body model, effectively projecting a 3D body's surface onto your 2D image. The result is dense (hence the name) rather than sparse: instead of "here are 18 dots," it's "here is the entire body surface and how it's oriented." Feed that into a DensePose ControlNet and the model generates a person whose body shape and surface match, not just whose joints line up. This is why it became a backbone of tools like MagicAnimate - dense body maps drive much steadier character motion than skeletons do.
The inputs that matter
model(defaultdensepose_r50_fpn_dl.torchscript) - the detector backbone. The r50 default is faster; r101 is a heavier, potentially more accurate network. Start with r50; only step up to r101 if detection is missing bodies you need.cmap(defaultViridis (MagicAnimate)) - and this one is not cosmetic. It's the color scheme of the output map, and it must match the ControlNet you're feeding.Viridis (MagicAnimate)matches MagicAnimate-style models;Parula (CivitAI)matches the DensePose ControlNet distributed on CivitAI. Pick the wrong colormap and the ControlNet reads garbage - this is the single most common DensePose mistake.resolution(default 512) - working size; match your render.
The single output is an IMAGE (the dense body map) that wires into a ControlNet Apply node with a DensePose ControlNet. The node makes the map; the ControlNet model is separate.
Installing it
ComfyUI Manager: search ComfyUI's ControlNet Auxiliary Preprocessors, install, restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/Fannovel16/comfyui_controlnet_aux
pip install -r requirements.txt
Restart ComfyUI. The DensePose torchscript weight downloads from HuggingFace on first run.
Where people get burned
The big one, worth repeating: cmap must match your ControlNet. If your DensePose result looks completely wrong despite a clean-looking body map, you almost certainly picked the colormap the ControlNet wasn't trained on - flip between Viridis and Parula. Second, DensePose is heavier than OpenPose and, historically, pose estimators in this pack could fall back to slow CPU execution; if it's crawling, that's the likely cause, and it's most painful on long video batches. Third, pick the right tool for the job: if you only need a person to strike a pose, OpenPose is lighter and simpler. Reach for DensePose when you specifically need body-surface fidelity - clothing that drapes correctly, consistent body shape across animation frames, the things a stick figure can't express. And, as ever, it's a hint image: no DensePose ControlNet loaded means nothing happens.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| modelopt | COMBO | densepose_r50_fpn_dl.torchscript | 2 options: densepose_r50_fpn_dl.torchscript, densepose_r101_fpn_dl.torchscript |
| cmapopt | COMBO | Viridis (MagicAnimate) | 2 options: Viridis (MagicAnimate), Parula (CivitAI) |
| resolutionopt | INT | 51264–16384 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |