Nodes/ComfyUI-MultiMaskOps/Mask Expand Without Overlap
ComfyUI Node

Mask Expand Without Overlap

Grow every mask at once — without subjects bleeding into each other

By INuBq8·Created 2 months ago·Updated 2 months ago· 0
Mask Expand Without Overlap
  • masks
  • masks
expand_pixels10
tapered_cornerstrue
feather_amount0
feather_mode
overlap_policy
subtract_hardtrue
threshold0.50

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_corners zeroes the diagonal kernel entries for rounded growth, exactly like the built-in node. Negative expand_pixels even erodes, same semantics.
  • Feathering matches KJNodes' GrowMaskWithBlur - a Gaussian blur where feather_amount is used as sigma and the kernel is 6σ+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_policy and feather_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_amount is 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_policy on a single frame first. retreat and priority change seam behavior in ways that are hard to predict from reading the docs; the allow default 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.

CategoryMultiMaskOps

Inputs (8)

NameTypeDefaultDescription
masksMASKA list of masks to expand/feather while preventing overlap.
expand_pixelsINT100–4096Pixels to grow each mask (native GrowMask method). 0 = no expansion.
tapered_cornersBOOLEANtrueRounds the corners of the expansion (matches native GrowMask). True = rounded growth, False = square growth.
feather_amountINT00–4096Gaussian blur radius for soft edges (used as sigma, matches KJNodes GrowMaskWithBlur). 0 = no feather.
feather_modeCOMBOHow 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_policyCOMBOHow 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_hardBOOLEANtrueFlatten the protected/subtracted region so masks can never leave any nonzero value inside another mask's area. Recommended on.
thresholdFLOAT0.500–1Binarization cutoff used when building the hard protection regions.

Outputs (1)

NameTypeDescription
masksMASK