Nodes/Comfyui_PDuse/PD:Mask Fill Holes
ComfyUI Node

PD:Mask Fill Holes

Fill the holes in a mask so inpaint regions stay solid

By 7BEII·Created 2 years ago·Updated 15 days ago· 53
PD:Mask Fill Holes
  • mask
  • filled_mask
fill_methodscipy
min_hole_size0
iterations1

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 iterations controlling 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.

CategoryPDuse/Mask

Inputs (4)

NameTypeDefaultDescription
maskMASK
fill_methodoptCOMBOscipy2 options: scipy, opencv
min_hole_sizeoptINT00–10000
iterationsoptINT11–10

Outputs (1)

NameTypeDescription
filled_maskMASK