Nodes/comfyui-fvmtools/Person Detailer ControlNet
ComfyUI Node

Person Detailer ControlNet

Person Detailer with depth and pose baked in — one model, auto-generated control maps

By ping1979ping·Created 7 months ago·Updated a day ago· 2
Person Detailer ControlNet
  • images
  • person_data
  • model
  • clip
  • vae
  • positive_base
  • negative
  • dd_options
  • inpaint_options
  • images
  • refined
  • refined_references
  • refined_generic
◄seed0►
◄steps4►
◄denoise0.52►
◄sampler_name▾►
◄scheduler▾►
◄detail_daemon_enabledtrue►
◄detail_amount0.20►
◄dd_smoothtrue►
◄mask_blend_pixels32►
◄mask_expand_pixels0►
◄target_width800►
◄target_height1200►
◄controlnet_enabledtrue►
◄model_patch▾►
◄control_typedepth►
◄control_strength0.30►
◄cn_resolution512►
◄depth_modeldepth_anything_v2_vitl.pth►
◄reference_1_enabledtrue►
◄reference_1_lora▾►
◄reference_1_lora_strength1.00►
◄reference_1_prompt►
◄reference_2_enabledfalse►
◄reference_2_lora▾►
◄reference_2_lora_strength1.00►
◄reference_2_prompt►
◄reference_3_enabledfalse►
◄reference_3_lora▾►
◄reference_3_lora_strength1.00►
◄reference_3_prompt►
◄reference_4_enabledfalse►
◄reference_4_lora▾►
◄reference_4_lora_strength1.00►
◄reference_4_prompt►
◄reference_5_enabledfalse►
◄reference_5_lora▾►
◄reference_5_lora_strength1.00►
◄reference_5_prompt►
◄generic_enabledfalse►
◄generic_catch_unprocessedtrue►
◄generic_lora▾►
◄generic_lora_strength1.00►
◄generic_prompt►

The plain Person Detailer is great until it isn't. The failure mode: an inpaint pass that's supposed to just refine a face decides to re-invent the pose or throw in a second nose, because the sampler has no structural information about what's actually in the masked region. PersonDetailerControlNet is the answer - it's Person Detailer with a Z-Image ControlNet Union model strapped on. For every person crop it automatically generates a depth map or a DWPose skeleton, encodes it, and applies it as ControlNet conditioning so the detail pass has to respect the geometry that's already there.

This is aimed squarely at Z-Image Turbo (Lumina2) workflows. The whole thing is built around a ControlNet Union model patch - one model that handles depth, pose, canny and inpainting - loaded from ComfyUI's models/model_patches/ directory. If you're not on Z-Image, or you leave model_patch at "None", the node degrades gracefully to behaving exactly like Person Detailer, so you lose nothing by trying it.

How it works

Beyond every Person Detailer feature (5 reference slots, generic catch-all, LoRA caching, Detail Daemon, multi-round latent cycling), it adds:

  • control_type - depth, pose, or depth+pose. Depth mode runs DepthAnythingV2 on each crop; pose mode runs DWPose to get a skeleton. Both get applied as separate patches in the third mode.
  • control_strength - base ControlNet strength (default 0.3). This is where the clever part lives: the node auto-scales it down as denoise rises, using effective = control_strength * (1.0 - denoise * 0.5). At denoise 0.52 and strength 0.5 you get an effective 0.37, logged to console as depth s=0.50->0.37. The reasoning is sound - at high denoise the inpaint is rewriting a lot, and full-strength ControlNet at high denoise is how you get pose artifacts bleeding in. Lower denoise means you can afford stronger control.
  • cn_resolution - the preprocessing resolution (default 512).
  • depth_model - which DepthAnythingV2 checkpoint to use: vitl is the balanced default, vitg is best quality, vits is fastest.
  • Pose maps get a Gaussian blur that scales with resolution, specifically to stop hard skeleton lines from bleeding into the output as visible edges.

The input that gates everything

controlnet_enabled (default on) - flipping it off turns this into plain Person Detailer, which is also your built-in A/B switch. Worth remembering when you're debugging: if the image looks worse with control on, the fix isn't necessarily to turn it off - try dropping control_strength first. A face with too much structural constraint comes out stiff, not wrong.

Outputs mirror Person Detailer: images (stitched result), refined, refined_references, refined_generic (crop grids).

Installing

Same pack as the rest of the face tools:

cd ComfyUI/custom_nodes
git clone https://github.com/ping1979ping/comfyui-FVMtools
pip install insightface>=0.7.3 onnxruntime-gpu>=1.17.0 opencv-python>=4.8.0 numpy>=1.24.0

But it needs more models than the base nodes, and this is where people stall. You need the Z-Image ControlNet Union patch in models/model_patches/, the DepthAnythingV2 .pth in your controlnet/diffusion models folder, and DWPose models for pose mode. None of these auto-download. The depth checkpoints (depth_anything_v2_vitl.pth etc.) are from the Depth Anything V2 repo; the ControlNet Union patch comes from wherever you get your Z-Image control models. If the model_patch dropdown shows only "None", that's the tell - you haven't put a patch in model_patches/ yet.

The honest caveat

This node is new enough and niche enough that the model-loading story is the real barrier. It's not a "wire it up in 30 seconds" experience the way the color nodes are. But if you're doing Z-Image character work and your refined faces keep drifting in pose or depth, this is the specific tool for that specific problem - and the auto-scaling strength logic is genuinely thoughtful, the kind of detail a beginner wouldn't know to set by hand.

CategoryFVM Tools/Face

Inputs (52)

NameTypeDefaultDescription
imagesIMAGEInput image batch [B, H, W, C]
person_dataPERSON_DATAPerson data from Person Selector Multi node
modelMODELBase model (Z-Image Turbo or other)
clipCLIPCLIP model for prompt encoding
vaeVAEVAE for encode/decode (also used to encode control images for the model patch)
seedINT00–18446744073709550000—
stepsINT41–100—
denoiseFLOAT0.520–1—
sampler_nameCOMBO44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38
schedulerCOMBO9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3
detail_daemon_enabledBOOLEANtrue—
detail_amountFLOAT0.20-5–5—
dd_smoothBOOLEANtrue—
mask_blend_pixelsINT320–128Feather radius at the mask edge, measured in SAMPLING pixels (relative to target_width/target_height, the one fixed frame in the pipeline). The same radius is converted back to image pixels for the blend, so both ramps cover the same strip of the picture. The console prints the conversion, e.g. '32px @ 800px sampling = 15px in the image (crop 380px)'. Which side of the edge the ramp lies on is set by feather_direction in Inpaint Options. On 'both' (the default) the ramp eats into the mask as much as out of it - raise this only as far as the thinnest part of your mask tolerates.
mask_expand_pixelsINT00–64Dilate the mask by this many IMAGE pixels before anything else happens - before the crop region is computed, before feathering. Grows the mask outward in every direction, so on a hair or accessory mask it also grows toward the face. Unaffected by feather_direction. Leave at 0 unless the segmentation is clipping the subject.
target_widthINT80064–4096—
target_heightINT120064–4096—
controlnet_enabledBOOLEANtrueEnable/disable ControlNet guidance. When off, behaves like Person Detailer.
model_patchCOMBOZ-Image ControlNet Union model patch from models/model_patches/.
control_typeCOMBOdepthWhich control signal to generate from each crop: depth — structural depth guidance (DepthAnythingV2) pose — skeletal pose guidance (DWPose) depth+pose — both applied as separate patches
control_strengthFLOAT0.300–2ControlNet Union strength. 0 = disabled.
cn_resolutionINT51264–2048Resolution for DWPose/DepthAnything preprocessors
depth_modelCOMBOdepth_anything_v2_vitl.pthDepthAnythingV2 checkpoint (vitl=balanced, vitg=best, vits=fastest)
reference_1_enabledBOOLEANtrueEnable reference slot 1 for detailing
reference_1_loraCOMBOLoRA to apply when detailing reference 1
reference_1_lora_strengthFLOAT1.000–2LoRA strength for reference 1
reference_1_promptSTRINGPositive prompt for reference 1. If empty, uses base conditioning.
reference_2_enabledBOOLEANfalseEnable reference slot 2 for detailing
reference_2_loraCOMBOLoRA to apply when detailing reference 2
reference_2_lora_strengthFLOAT1.000–2LoRA strength for reference 2
reference_2_promptSTRINGPositive prompt for reference 2. If empty, uses base conditioning.
reference_3_enabledBOOLEANfalseEnable reference slot 3 for detailing
reference_3_loraCOMBOLoRA to apply when detailing reference 3
reference_3_lora_strengthFLOAT1.000–2LoRA strength for reference 3
reference_3_promptSTRINGPositive prompt for reference 3. If empty, uses base conditioning.
reference_4_enabledBOOLEANfalseEnable reference slot 4 for detailing
reference_4_loraCOMBOLoRA to apply when detailing reference 4
reference_4_lora_strengthFLOAT1.000–2LoRA strength for reference 4
reference_4_promptSTRINGPositive prompt for reference 4. If empty, uses base conditioning.
reference_5_enabledBOOLEANfalseEnable reference slot 5 for detailing
reference_5_loraCOMBOLoRA to apply when detailing reference 5
reference_5_lora_strengthFLOAT1.000–2LoRA strength for reference 5
reference_5_promptSTRINGPositive prompt for reference 5. If empty, uses base conditioning.
generic_enabledBOOLEANfalseEnable detailing for unmatched faces
generic_catch_unprocessedBOOLEANtrueON: detail all faces not processed by active slots. OFF: only truly unmatched faces.
generic_loraCOMBOLoRA for unmatched faces
generic_lora_strengthFLOAT1.000–2LoRA strength for unmatched faces
generic_promptSTRINGPositive prompt for unmatched faces.
positive_baseoptCONDITIONINGBase positive conditioning
negativeoptCONDITIONINGNegative conditioning
dd_optionsoptDD_OPTIONSAdvanced Detail Daemon parameters
inpaint_optionsoptINPAINT_OPTIONSAdvanced inpaint settings

Outputs (4)

NameTypeDescription
imagesIMAGE—
refinedIMAGE—
refined_referencesIMAGE—
refined_genericIMAGE—