Nodes/ComfyUI_Swwan/Mask Process (Swwan)
ComfyUI Node

Mask Process (Swwan)

Five mask algorithms under one roof, and which knob belongs to which

By aining2022·Created 10 months ago·Updated about 18 hours ago· 33
Mask Process (Swwan)
  • mask
  • mask
  • mask_inverted
◄operation▾►
◄threshold20►
◄erode_dilate0►
◄close_holes0►
◄remove_isolated_pixels0►
◄smooth0►
◄blur0►
◄invert_maskfalse►
◄grow4►
◄expand0►
◄incremental_expandrate0.00►
◄tapered_cornerstrue►
◄flip_inputfalse►
◄blur_radius0.00►
◄lerp_alpha1.00►
◄decay_factor1.00►
◄fill_holesfalse►

What it's for

Every mask workflow needs the same three things eventually: clean up the ragged edge the detector gave you, hard-threshold it into a real binary mask, and grow it a bit so the inpaint has somewhere to breathe. This node does all of that in one, plus hole filling and two different growth algorithms.

It's the pack's mask utility knife - WAS, Impact, LayerStyle, KJNodes and ComfyUI_essentials algorithms collected behind a single operation dropdown. Which is also its main trap: it has fourteen optional widgets, and most of them are ignored by the mode you're in. Here's the map.

Which knobs do anything

cleanup - the general-purpose "make this mask nicer" pass, and the one you'll use most. It reads erode_dilate (negative erodes, positive dilates, via grey erosion/dilation), close_holes (grey closing, which is the fill-small-gaps operation despite the name), remove_isolated_pixels (grey opening - kills specks), smooth and blur (both gaussian, both forced to odd kernels, the difference being that smooth blurs a hard-thresholded copy while blur blurs the actual values). This is the ComfyUI_essentials algorithm.

binary - hard threshold at threshold/255, so the default 20 means "anything above 7.8% opacity becomes solid white" and everything else becomes black. Gives you a real 0/1 mask. Good before a crop, bad before a feather.

fill_holes - scipy.ndimage.binary_fill_holes, and it follows WAS Node Suite's behaviour exactly, quantisation and all: the mask is clipped to 0–255 as a uint8, anything non-zero counts as content, and the result keeps a singleton channel dimension. That shape detail is straight from the author's own description: fill_holes returns [B,1,H,W] while every other mode returns [B,H,W]. Most nodes cope, some don't.

layer_grow - the LayerStyle-style growth pass, using grow (which can go negative to shrink), invert_mask, and blur. This one is about soft mask edges for layer compositing, not about a clean hard grow.

grow_blur - KJNodes' GrowMaskWithBlur algorithm: iterative kornia morphological dilation/erosion on the GPU with expand, tapered_corners (the 3×3 cross kernel - turn it off for a square kernel), flip_input, blur_radius, incremental_expandrate, lerp_alpha and decay_factor, plus an optional fill_holes. This is the heavy hitter: it can grow by a large amount and feather the result in the same pass, which is exactly the recipe for an inpaint mask that doesn't leave a visible box. It runs on CUDA via kornia, so it's the one mode here with a real dependency beyond the pack's baseline.

You get two outputs: mask and mask_inverted, the latter being 1 - the result. That saves you a separate invert node when you need both sides of a matte - background and subject in one pass.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/aining2022/ComfyUI_Swwan
cd ComfyUI_Swwan
python -m pip install -r requirements.txt

Restart, refresh, search Swwan. The pack's requirements bring scipy, scikit-image and OpenCV, so cleanup, binary and fill_holes work out of the box. grow_blur additionally needs kornia - normally present in a ComfyUI environment, and the node raises a specific message if it's missing rather than failing cryptically.

Common issues

Mask Cleanup requires scipy and torchvision (vision dependencies) or Grow Blur requires kornia and scipy. Install into the same Python that runs ComfyUI - the venv or the portable python_embeded. Half the "dependency missing" reports for pack-based nodes are a second interpreter.

Nothing appears to change. You're turning a knob that the current operation doesn't read. Check the map above before reaching for bigger numbers.

The fill-holes result breaks a downstream node. That extra [B,1,H,W] channel dimension. Squeeze it, or use binary instead.

Grow is slow. grow_blur loops one dilation per pixel of expand. Growing by 64 is 64 morphological passes per frame. Keep expand modest and lean on blur_radius for softness.

CategorySwwan/Advanced/Mask

Inputs (18)

NameTypeDefaultDescription
maskMASK—
operationCOMBO5 options: cleanup, fill_holes, binary, layer_grow, grow_blur
thresholdoptINT201–255—
erode_dilateoptINT0-256–256—
close_holesoptINT00–128—
remove_isolated_pixelsoptINT00–32—
smoothoptINT00–256—
bluroptINT00–999—
invert_maskoptBOOLEANfalse—
growoptINT4-999–999—
expandoptINT0-16384–16384—
incremental_expandrateoptFLOAT0.000–100—
tapered_cornersoptBOOLEANtrue—
flip_inputoptBOOLEANfalse—
blur_radiusoptFLOAT0.000–100—
lerp_alphaoptFLOAT1.000–1—
decay_factoroptFLOAT1.000–1—
fill_holesoptBOOLEANfalse—

Outputs (2)

NameTypeDescription
maskMASK—
mask_invertedMASK—