🖐️ 修手重绘 (HandRefiner)
Actually re-draw the hands, not just re-render them
- 图片
- 模型
- 正向提示词
- 反向提示词
- VAE
- 修手图像
- 手部深度图
- 手部遮罩
The problem this solves
A detailer pass fixes a hand that's blurry. It does not fix a hand that's wrong. FaceDetailer, ADetailer, DetailerForEach - all of them mask the region and re-render it with a prompt that says "five fingers, please." You're asking the model that drew six fingers to count this time, with only text as guidance. Sometimes it works; often you get a differently-wrong hand.
HandRefineInpaint is the other approach. It's the HandRefiner pipeline, wired up as a single node: reconstruct a 3D hand mesh from your image, render that mesh as a depth map, and re-inpaint the hand region with a depth ControlNet trained on hand depth. The mesh has five fingers by construction, so the condition is anatomically correct instead of hopefully correct - that's the whole trick.
How it works
Three stages, all inside the node. First, MeshGraphormerDetector from comfyui_controlnet_aux runs on your image and returns a depth map plus a hand mask. The mask gets grown a few pixels (the source grey-dilates it five times with a 3×3 footprint) - a mask that hugs the knuckles leaves broken fingers outside the re-render.
Second, that depth map goes into a ControlNet applied over the full 0→1 range at the strength you set, with the mask restricting where it matters.
Third, the image is VAE-encoded, the mask becomes a latent noise mask, and a KSampler runs the whole frame at your denoise - 0.85 by default. That's deliberately high: a mangled hand can't be nudged into place, so you want the region regenerated with the depth map holding the structure.
One honest caveat: this is the older whole-frame route, not crop-and-stitch. Unmasked pixels still go through a VAE round trip - the same class of problem behind ADetailer's "grey box" complaints. If you need bit-identical untouched pixels, take the 手部遮罩 output and composite with ImageCompositeMasked.
Inputs that matter
图片 takes the finished image - or the 图片列表 output from 🧪 手工提示词单项测试, so a whole sweep can be hand-fixed in one run. Don't feed it the grid image; the detector will hunt for hands in a contact sheet.
HandControlNet wants the Hand Inpaint Depth ControlNet. The node auto-selects the first file whose name contains inpaint_depth_hand, and prints a warning if your selection looks like an OpenPose model - worth heeding, since OpenPose conditions on pose skeletons, not hand depth. Checkpoint模型 carries the rest of the stack, with 可选CLIP / CLIP类型 / 可选VAE for checkpoints with no bundled text encoder.
Then the normal sampling knobs: 种子, 步数, CFG, 采样器, 调度器, CLIP跳过层. Each image in a batch gets 种子 + its index, so a batch doesn't come back with the same hand style copy-pasted down the row.
The two you'll actually tune are 降噪 and ControlNet强度. Leave denoise up at 0.85 for a genuinely broken hand; drop to 0.5–0.6 if the patch comes back with a seam or a color shift. 检测分辨率 (512 default) is how large the mesh detector works internally - raising it helps with small or partially occluded hands.
Worth knowing: 模型, 正向提示词, 反向提示词 and VAE are optional inputs - wire all four and the checkpoint widget is ignored.
Outputs
修手图像 is the fixed image, straight to Save Image. 手部深度图 is the rendered mesh depth - the fastest way to see whether the reconstruction found a real hand shape. 手部遮罩 is the dilated mask, for compositing the fix back over your original pixels.
Install
There's no separate setup for the two test nodes; this one carries the optional dependencies, which is why they live in requirements.txt.
cd ComfyUI/custom_nodes
git clone https://github.com/kukuxz007/comfyui-t2i-tester.git
cd comfyui-t2i-tester
pip install -r requirements.txt # ultralytics>=8.0.0, scipy>=1.10.0
Then the model-side bits: install comfyui_controlnet_aux the normal way, drop control_sd15_inpaint_depth_hand_fp16.safetensors into ComfyUI/models/controlnet/, and on macOS also put hand_yolov8s.pt in ComfyUI/models/ultralytics/bbox/. Restart ComfyUI. Through ComfyUI Manager, search the Registry for ComfyUI T2I Tester; newer Manager builds only install Registry packages, so if that search is empty, use the clone above.
Common issues
It "works" and every image comes back unchanged. If the detector finds no hand, the node passes the original image through, prints a skipped line to the console, and returns a zero mask. On macOS the detector is fed hand boxes from YOLO precisely because MediaPipe crashes the process there - so a missing hand_yolov8s.pt in models/ultralytics/bbox/ means permanent no-detection with nothing visible in the UI. Check that path first.
You selected the wrong ControlNet. The auto-pick falls back to the first ControlNet in your folder when it can't match inpaint_depth_hand, which can silently be an unrelated model. Confirm the widget text.
CLIP or VAE errors. The node says so explicitly when the checkpoint ships neither; there is nothing to debug. CLIP跳过层 is ignored for non-SD text encoders (names containing qwen, llama, gemma, umt5, anima) because clipping layers there breaks the encoding.
One dependency deserves a pause. requirements.txt pulls ultralytics - AGPL-3.0, and in December 2024 a release carried a cryptominer that reached ComfyUI users through a detailing node pack. Pin a version you trust rather than grabbing latest.
Inputs (24)
| Name | Type | Default | Description |
|---|---|---|---|
| 图片 | IMAGE | — | |
| HandControlNet | COMBO | None | 1 options: None |
| Checkpoint模型 | COMBO | None | 1 options: None |
| 正向提示词文本 | STRING | masterpiece, best quality, 1girl, detailed hands, five fingers, well-formed fingers | — |
| 反向提示词文本 | STRING | (worst quality, low quality:1.4), bad hands, extra fingers, missing fingers, fused fingers, too many fingers, mutated hands | — |
| 种子 | INT | 00–18446744073709550000 | — |
| 步数 | INT | 201–100 | — |
| CFG | FLOAT | 7.01–30 | — |
| 采样器 | COMBO | euler | 44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38 |
| 调度器 | COMBO | normal | 9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3 |
| 降噪 | FLOAT | 0.850–1 | — |
| ControlNet强度 | FLOAT | 1.000–2 | — |
| CLIP跳过层 | INT | 21–12 | — |
| 检测分辨率 | INT | 512256–1024 | — |
| 模型opt | MODEL | — | |
| 正向提示词opt | CONDITIONING | — | |
| 反向提示词opt | CONDITIONING | — | |
| VAEopt | VAE | — | |
| LoRA模型opt | COMBO | None | 1 options: None |
| 模型强度opt | FLOAT | 1.00-20–20 | — |
| CLIP强度opt | FLOAT | 1.00-20–20 | — |
| 可选CLIPopt | COMBO | None | 1 options: None |
| CLIP类型opt | COMBO | stable_diffusion | 28 options: stable_diffusion, stable_cascade, sd3, stable_audio, mochi, ltxv, +22 |
| 可选VAEopt | COMBO | None | 1 options: None |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| 修手图像 | IMAGE | — |
| 手部深度图 | IMAGE | — |
| 手部遮罩 | MASK | — |