MeshGraphormer Hand Refiner With External Detector
Bring your own hand detector
- image
- bbox_detector
- IMAGE
- INPAINTING_MASK
Same job as the regular MeshGraphormer Hand Refiner - fix mangled AI hands by fitting a correct 3D hand mesh and outputting a depth map plus an inpaint mask - but with one big difference: you supply your own detector. Instead of relying on the built-in hand finder, this variant takes a BBOX_DETECTOR input, so you can plug in a purpose-trained hand-detection model and catch hands the default pass misses.
Why the external detector matters
The stock hand refiner works great until it doesn't find the hand. Small hands, partially occluded hands, hands at the edge of frame, busy scenes - the built-in detector shrugs and the whole repair silently no-ops. That's the failure this node exists to solve. You wire in a dedicated detector (the usual source is a detector loader from Impact Pack, pointed at a hand-specific YOLO model like hand_yolov8s), and now the detection stage is as good as whatever model you feed it. Everything downstream - the mesh fitting, the depth render, the mask - is identical to the standard node. You've just upgraded the eyes.
If your hands are getting found fine by the regular MeshGraphormer node, you don't need this one. Reach for it specifically when detection is the bottleneck.
The inputs that matter
The two required inputs are image and bbox_detector (the detector object you loaded elsewhere). After that, the detection knobs come from the Impact-style detector world:
bbox_threshold(default 0.5) - detection confidence gate. Lower it if hands are being missed, raise it if it's boxing things that aren't hands.bbox_dilation(default 10) andbbox_crop_factor(default 3) - how much the detected box is grown and how much context around it gets cropped in for the mesh fit. If repairs feel starved of surrounding context, nudge the crop factor up.mask_type(defaultbased_on_depth) - how the inpaint mask is shaped.based_on_depthhugs the actual hand geometry and repaints the least;tight_bboxesandoriginalare the rectangular and raw alternatives.mask_bbox_padding(30) andmask_expand(5) - breathing room around the mask; grow them if the rebuilt hand blends badly at the wrist.rand_seed(88),drop_size(10), andresolution(512) round it out - leave them unless you're chasing a specific problem.
The two outputs - you need both
IMAGE- the depth map of the corrected hand mesh.INPAINTING_MASK(a MASK) - the region to regenerate.
Route the depth IMAGE into a ControlNet Apply node with the HandRefiner depth ControlNet (control_sd15_inpaint_depth_hand), and use the MASK to drive the inpaint pass. Miss either half and it breaks the same way the base node does: depth without a mask repaints the whole frame, mask without depth gives the model no template.
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. First run pulls the Graphormer hand weights and an HRNet backbone from HuggingFace. You'll also need Impact Pack (or another node that produces a BBOX_DETECTOR) installed separately to feed the detector input - that's the whole reason to use this variant.
Where people get burned
Number one: nothing plugged into bbox_detector. This input is required, and it doesn't come from this pack - you need a detector-provider node and a downloaded hand-detection model. No detector, no node. Number two, same as the base refiner: it only fixes hands it can detect, so if even your upgraded detector can't find a totally destroyed hand, you may have to fix the pose upstream first. Number three: this is an SD1.5-era hand-fix tool built around one specific ControlNet, so it belongs in an SD1.5 workflow, not a Flux one.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| bbox_detector | BBOX_DETECTOR | — | |
| bbox_thresholdopt | FLOAT | 0.500.1–1 | — |
| bbox_dilationopt | INT | 10-512–512 | — |
| bbox_crop_factoropt | FLOAT | 3.001–10 | — |
| drop_sizeopt | INT | 101–16384 | — |
| mask_bbox_paddingopt | INT | 300–100 | — |
| mask_typeopt | COMBO | based_on_depth | 3 options: based_on_depth, tight_bboxes, original |
| mask_expandopt | INT | 5-16384–16384 | — |
| rand_seedopt | INT | 880–18446744073709550000 | — |
| resolutionopt | INT | 51264–16384 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |
| INPAINTING_MASK | MASK | — |