PD:Mask Fill Holes
Fill the holes in a mask so inpaint regions stay solid
- mask
- filled_mask
Masks get holes. A face mask from a detector will have a gap where the hair is, a sky mask will have a cloud-shaped void, and every one of those holes is a place where an inpainting pass can leak or a composite can ghost. PD_MaskFillHoles ("PD:Mask Fill Holes") closes them: it fills the interior gaps that are completely enclosed by foreground, leaving the rest of the mask alone. It's mask hygiene, plain and simple - the kind of one-input utility node you keep in a drawer and pull out when a mask needs to be solid before you feed it to an inpaint or detailer.
It's from the 7BEII/Comfyui_PDuse pack, the mask-cleanup sibling of PD_MaskRemoveSmallObjects in the same pack. Together they form a two-step "clean my mask" pipeline: remove the specks, fill the holes.
How it works
Two backends, selectable via fill_method:
- scipy (default) -
binary_fill_holes, the mathematical approach. It fills any hole fully surrounded by foreground and does not touch regions that connect to the boundary. That's the behavior you want: an open bay along the mask's edge stays open, a closed donut hole gets filled. This is why scipy is one of the few genuinely new dependencies this pack installs. - opencv - a morphological close instead. Same spirit, but it uses dilation+erosion with
iterationscontrolling how aggressively the close happens. Use this when you also want to smooth the edge, or if scipy's exact fill leaves you a hair short.
Two more knobs: min_hole_size (default 0 = fill every hole; set it higher to only fill holes above a pixel count, so you don't erase the tiny gaps that don't matter), and iterations (only used by the opencv path).
Output is a single filled_mask, same dimensions as the input. Wire it straight into the next stage - an inpainting mask, a detailer's mask, whatever consumes masks.
The inputs that matter
mask- required, the MASK to clean.fill_method- scipy vs opencv, above.min_hole_size- 0 fills all holes; raise to leave tiny ones alone.iterations- opencv-only strength knob, default 1.
Installing
ComfyUI Manager, search Comfyui_PDuse; or:
cd ComfyUI/custom_nodes
git clone https://github.com/7BEII/Comfyui_PDuse
cd Comfyui_PDuse
pip install -r requirements.txt
Restart. The scipy path requires scipy, which is in the pack's requirements - if you skipped pip install -r requirements.txt, this node's scipy method will fail at runtime (the module loads fine, the fill just errors).
Gotchas
The boundary rule is the thing to internalize: holes open to the edge are not filled, by design. If you expected a mask with a notched edge to come back fully solid, you need the remove-small-objects node or a morphological close with more iterations, not this one. Also, if you load a mask with soft (anti-aliased) edges, the binarization threshold the node applies is at 0.5, so feathering can make it decide an edge region is "open" when you meant it closed. For typical hard-edged masks from detectors, it behaves exactly as advertised: in hole, out solid.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| mask | MASK | — | |
| fill_methodopt | COMBO | scipy | 2 options: scipy, opencv |
| min_hole_sizeopt | INT | 00–10000 | — |
| iterationsopt | INT | 11–10 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| filled_mask | MASK | — |