Nodes/Melite Kimodo Nodes/🧍 Multi-HMR 2 Β· Image β†’ Anny
ComfyUI Node

🧍 Multi-HMR 2 Β· Image β†’ Anny

One photo in, a crowd of parametric bodies out

By JayDataEngineerΒ·Created 2 months agoΒ·Updated 4 days agoΒ· 1
🧍 Multi-HMR 2 Β· Image β†’ Anny
  • image
  • out_dir
  • anny_params_path
  • mesh_paths
β—„conf_thresh0.40β–Ί
β—„dist_thresh_nms0.25β–Ί
β—„lowresfalseβ–Ί
β—„save_anny_paramstrueβ–Ί
β—„save_meshtrueβ–Ί
β—„renderfalseβ–Ί
β—„filename_prefixanny/multihmr2β–Ί
β—„image_pathβ–Ί
β—„checkpointβ–Ί

Photo of two people at a picnic table, and you want 3D bodies you can actually pose. That's this node. It runs Multi-HMR 2 - NAVER's multi-person body regression model - and hands you a per-person mesh plus the underlying body parameters. Both matter, and the parameters are the more useful half: they're the vocabulary the rest of the character pipeline speaks.

Hang the wider field's expectations here first. Image-to-3D's famous failure is that it returns triangle soup with machine-made UVs and no rig - great for a still, useless the moment something moves. A parametric body sidesteps most of that: it comes out in a fixed topology with a pose you can change, because it was never reconstructed vertex-by-vertex. That's the trade - less surface detail, more actual character.

What it computes

Multi-HMR 2 does regression, not optimization: one forward pass over the image, a DETR detector finds the people, and the model fits the Anny parametric body to each detection. There's no sampling loop and no iterations, so this is the fast engine in the pack's Anny family. The other engine, AnnyFitOptimize, is the slow, camera-space optimization path over the same photo, and it runs for minutes to hours out of process.

The session is loaded once and cached per checkpoint, with both halves of it registered against ComfyUI's VRAM accounting - the detector and the world body model. Eviction moves both to CPU together, so no half-evicted-model crash.

Everything the node writes lands in a numbered run directory in your output tree: anny_params/<name>.pkl for the parameters (the world parameterization - camera intrinsics, shape, pose parameters), meshes/<name>_NNN.glb for one GLB per detected person, and visu/<name>.png if you asked for a render.

Inputs that matter

The required block is mostly you deciding what counts as a person and what gets saved.

  • conf_thresh (0.4) - minimum confidence to keep a detection. Your recall dial. Too high and the person at the back vanishes; too low and you get bodies fitted to a lamp.
  • dist_thresh_nms (0.25) - the pelvis-distance threshold in metres for 3D non-max suppression, i.e. how the model decides two overlapping fits are one person. Seeing duplicated bodies? This is the knob, not conf_thresh.
  • lowres - swaps in the low-resolution Anny body (613 vertices). Cheap and ugly; fine for layout checks and camera-space work, not for a hero render.
  • save_anny_params, save_mesh - turn on what you want back on disk. Turning all three outputs off raises rather than silently doing nothing, which is a small mercy.
  • render - writes an overlay image. It needs Multi-HMR 2's render extras (pyrender), which are commented out in the pack's requirements and are not installed by default.
  • filename_prefix - defaults to anny/multihmr2; it determines both the subfolder and the run-directory name.

Optional: image takes an IMAGE tensor, but only batch index 0 - wire a batch and the rest is silently ignored. image_path reads a file instead and uses its filename as the stem, which keeps your outputs named sensibly. checkpoint overrides the model file path.

One gap worth knowing: wire neither image source and it raises rather than reaching for a default.

Outputs

out_dir is the run directory. anny_params_path is the .pkl. mesh_paths is the one you'll wire: a ;-joined string of GLB paths, one per detected person, in detection order. That joins straight to AnnySelectPerson's mesh_paths input, and from there to AnnyGroundBody to get a body that isn't floating in camera space.

Install

cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/JayDataEngineer/melite-kimodo-nodes.git
cd melite-kimodo-nodes
pip install -r requirements.txt

Restart. Manager does the same thing if you search "melite-kimodo-nodes". The requirements file pins multihmr2 to an exact upstream commit and adds trimesh, anny==0.6.0 and xatlas. Want render=True? Uncomment the pyrender / matplotlib / scipy lines, or you get no overlay render.

The checkpoint is its own thing: the node looks for multihmr2.pt in models/multihmr2/, honours a MULTIHMR2_CKPT env var, and otherwise lets upstream download it with wget on first run. The filename stem must be multihmr2 - the pack checks before upstream's assertion fires, so you get a readable error instead of a stack trace.

Licensing, before you ship

Multi-HMR 2's weights are NAVER non-commercial research licensed. Anny itself (the body model) is Apache 2.0; the estimator upstream is not. Shipping anything commercial? Use Sam3dBodyImageToAnny instead - that lane exists for exactly this reason and never imports the NAVER stack.

When it goes wrong

no person detected ... at conf_thresh=X means exactly that: lower the threshold, or check you pointed at a photo. no mesh GLBs were written - is trimesh installed in the serving venv? is the pack catching an upstream saver that failed quietly; install trimesh. And if save_anny_params is on but the expected .pkl never appeared, the node raises on purpose - it would rather fail than hand you an empty string that blows up three nodes later.

CategoryMelite/Anny

Inputs (10)

NameTypeDefaultDescription
conf_threshFLOAT0.400.05–0.95Minimum confidence to keep a person
dist_thresh_nmsFLOAT0.250.05–1Pelvis-distance threshold (m) for 3D NMS
lowresBOOLEANfalseLow-resolution Anny body (613 verts)
save_anny_paramsBOOLEANtrueβ€”
save_meshBOOLEANtrueβ€”
renderBOOLEANfalseOverlay render (needs the multihmr2 render extras: pyrender)
filename_prefixSTRINGanny/multihmr2β€”
imageoptIMAGEImage tensor (H,W,C in 0..1) β€” batch index 0
image_pathoptSTRINGPath to an image file (used when no tensor is wired)
checkpointoptSTRINGmultihmr2.pt path β€” defaults to MULTIHMR2_CKPT env > models dir

Outputs (3)

NameTypeDescription
out_dirSTRINGβ€”
anny_params_pathSTRINGβ€”
mesh_pathsSTRINGβ€”