Mask Expand Without Overlap
Grow every mask at once — without subjects bleeding into each other
- masks
- masks
This is the flagship of the pack - the node that makes installing it worth it. The problem: you segmented an image into several subjects, and now you want to grow each mask a few pixels to get a clean margin for inpainting or compositing. Grow them all with the stock GrowMask node and the expansions slam into each other; subject A's mask swallows subject B's shoulder. Mask Expand Without Overlap grows the whole list at once while making sure no mask ever leaks into another mask's original region.
How it works
Each mask is dilated, then the other masks' regions are subtracted from it. Two behaviors are deliberately matched to ComfyUI's natives so results don't surprise you:
- Dilation matches GrowMask - iterative 3×3 grey dilation via scipy, and
tapered_cornerszeroes the diagonal kernel entries for rounded growth, exactly like the built-in node. Negativeexpand_pixelseven erodes, same semantics. - Feathering matches KJNodes' GrowMaskWithBlur - a Gaussian blur where
feather_amountis used as sigma and the kernel is6σ+1. It's the same convention, so settings port over.
The cleverness is in what happens at the seams, and that's the overlap_policy:
allow- only each mask's original region is protected. Expansions may overlap freely in empty space. Fast, but you can get overlaps between subjects.retreat- contested empty pixels are cleared in both masks, leaving a clean empty seam.priority- earlier masks in the list win contested pixels, so you get a gap-free, deterministic partition. "Earlier wins" by list order - sort your list first if you want a specific subject to win.
feather_mode then decides how soft edges interact with neighbors: cut_feather feathers then subtracts (hard seam right at the neighbor's edge), while preserve_feather subtracts, feathers, and subtracts again so the soft edge never leaks into a neighbor.
Inputs that matter
masks- the list of masks (Mask Batch To List first if needed).expand_pixels- pixels to grow, default 10. 0 disables expansion.tapered_corners- rounded vs square growth; leave on.feather_amount- 0 means no feather, which is the right place to start.overlap_policyandfeather_mode- the seam behavior above.subtract_hard- recommended on; it flattens the protected region so a mask can never leave any value inside another mask's area.
Output is a single masks list, ready to feed Mask List To Batch and then MaskToImage or an inpaint node.
Where people get burned
feather_amountis a sigma, not a pixel radius. Setting it to 10 blurs the edge by a lot - a 6σ+1 kernel at σ=10 is 61 pixels wide. Start at 2–3. This trips up anyone who's used to a feather slider in pixels.- Test
overlap_policyon a single frame first.retreatandprioritychange seam behavior in ways that are hard to predict from reading the docs; theallowdefault is the safest first run. - Empty list - the node raises if you hand it zero masks.
Performance is fine despite being a Python loop over masks: the source precomputes the shared quantities once (the union of all originals, and a single batched dilation for the whole stack), which is the expensive part, so the per-mask pass stays cheap.
Installation
Same as the rest of the pack - clone, restart, no extra dependencies:
cd ComfyUI/custom_nodes
git clone https://github.com/INuBq8/ComfyUI-MultiMaskOps
Nodes appear under MultiMaskOps; Manager search "MultiMaskOps" should work once its listing is live. The pack ships no models and an empty requirements.txt. It's young - one commit as of mid-2026 - so treat the seam modes as "try and look at the result" rather than gospel, but the underlying dilation and feather are matched to natives you already trust.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| masks | MASK | A list of masks to expand/feather while preventing overlap. | |
| expand_pixels | INT | 100–4096 | Pixels to grow each mask (native GrowMask method). 0 = no expansion. |
| tapered_corners | BOOLEAN | true | Rounds the corners of the expansion (matches native GrowMask). True = rounded growth, False = square growth. |
| feather_amount | INT | 00–4096 | Gaussian blur radius for soft edges (used as sigma, matches KJNodes GrowMaskWithBlur). 0 = no feather. |
| feather_mode | COMBO | How feathering interacts with neighbors. cut_feather = feather then subtract neighbors (hard seam at neighbor edge). preserve_feather = subtract, feather, subtract again (soft seam that never leaks into neighbors). | |
| overlap_policy | COMBO | How expansions interact. allow = may overlap freely in empty space (only original regions protected). retreat = contested empty pixels cleared in both masks (clean seam). priority = earlier masks in the list win contested pixels (gap-free). | |
| subtract_hard | BOOLEAN | true | Flatten the protected/subtracted region so masks can never leave any nonzero value inside another mask's area. Recommended on. |
| threshold | FLOAT | 0.500–1 | Binarization cutoff used when building the hard protection regions. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| masks | MASK | — |