Nodes/ComfyUI-BCNodes/Mask Fill Holes
ComfyUI Node

Mask Fill Holes

Stop your matte looking like Swiss cheese

By 0xBeycan·Created 23 days ago·Updated 3 days ago· 2
Mask Fill Holes
  • masks
  • MASKS

Look closely at a background removal on a person in a patterned shirt and you'll find the pattern showing through the middle of the subject. The matte has holes. ComfyUI renders through them.

What it is

An optional MASK input, one MASKS output. It fills every fully enclosed hole in each mask of the batch - the classic fix for segmentation output where detail inside the subject got classified as background.

How it works

It calls scipy.ndimage.binary_fill_holes on each frame. The definition of "hole" is topological, and that's the part to internalise: a hole is a region of background that is fully enclosed by foreground. A gap that touches the border of the mask is not enclosed, and stays open - which is correct, because a gap touching the border usually is background.

A couple of implementation notes that explain the behaviour you get:

  • Each frame is quantised to 8-bit and anything above zero counts as foreground, so the operation is effectively binary. Interior dropouts disappear, and so does any subtlety: a mask with a soft gradient comes back as a hard 0/1 mask.
  • The output is hard 0/1 float32, shape (B, H, W), regardless of what went in.
  • Nothing wired in, an empty tensor, or None all return a blank (1, 64, 64) mask rather than raising.

When it's the right tool

  • Fixing a cutout. Subject masks with interior holes - the lanyard area on a jacket, hair between a strand and the face, a stripe on a shirt - where transparency punches through the subject. Fill, then grow, then blur, in that order.
  • Cleaning a detection mask before inpainting. A face mask with a hole where the glasses are produces an inpaint that re-renders everything except the glasses, which is the exact opposite of what you asked for.
  • Repairing masks that went through a lossy round trip. Any mask written to a PNG and read back can pick up speckle.

When it's the wrong tool

Two cases, both real:

Soft matting output. Models from the matting family - hair, veils, glass, smoke, motion blur - predict fractional alpha on purpose, and that fractional alpha is the entire value. Filling holes flattens it to 0/1, and your veil becomes a paper cutout. Leave matting output alone.

Later, not earlier. Fill before you feather. Run it after a blur and you've thrown away the blur; run it before a grow and the grown edge stays smooth.

And the one to actively avoid: background-removing your LoRA training set. The KB says it plainly, and hole-filling is a step in that direction rather than away from it.

Installing it

ComfyUI Manager → search ComfyUI-BCNodes → install → restart. Or:

cd ComfyUI/custom_nodes
git clone https://github.com/0xBeycan/ComfyUI-BCNodes
pip install -r ComfyUI-BCNodes/requirements.txt

Reload the browser tab. It lives under BCNodes/mask; search BCNodes in the node library to see the pack at once. requirements.txt installs postfx and caption-audit for other nodes in this pack - the mask ops rely on scipy and Pillow, which a normal ComfyUI install already has. If you're still carrying the pack's old ComfyUI-AutoBypass folder, remove it before restarting.

Where people get burned

Your "hole" touches the border. The most common disappointment: a mask where the subject wraps around the edge, or a gap that runs to the frame, gets left open because it isn't enclosed. That's the algorithm working as designed, and the fix is to fix the mask, not the node.

A soft mask goes hard. If your workflow depends on a graded, feathered matte, this node silently replaces it with a binary one. Check what's downstream before you drop it in the chain.

Filling is not closing. It fills enclosed voids; it does not connect separate blobs, close a notch in the silhouette, or round off a ragged edge. That's the grow pass.

CategoryBCNodes/mask

Inputs (1)

NameTypeDefaultDescription
masksoptMASK—

Outputs (1)

NameTypeDescription
MASKSMASK—