Average Overlapping Masks
Two masks, one mask, no seams
- mask_a
- mask_b
- MASK
Every ComfyUI workflow that touches a mask eventually hits the same question: you've got two masks and you want one. Maybe a SAM/GroundingDINO subject mask and a hand-painted inpaint region, or a face mask and a body mask that overlap. The naive answer - ImageCompositeMasked with a max/OR merge - gives you hard seams where the masks fight, and doubled values where both are confident. Average Overlapping Masks is the fix: where both masks agree, it takes the element-wise average; where only one is present, that mask wins outright; where neither exists, it's zero. Overlap gets a smooth blend, not a scar.
Think of it as the glue node for inpainting and regional work. Masked inpainting lives or dies on edge quality - the model sees the unmasked region as fixed context, and a seam at the mask boundary is exactly the artifact you're trying to avoid. When your target region is the union of two sources, this node is how you build one clean mask that feeds into Set Mask → KSampler without a visible boundary where the two masks used to meet.
How it works
The logic is per-pixel and spelled out in the code. A pixel only participates in averaging if it clears blend_threshold in both masks - then the output is their mean. If it's above presence_threshold in one but not the other, the present mask passes through untouched. Anything below both thresholds is zero. Two thresholds, not one, because soft edges are the whole problem: masks from segmentation almost never end in a clean 0/1 step, they trail off through soft values. presence_threshold (default 0.01, range 0–0.5) decides what counts as "there at all"; blend_threshold (default 0.01, range 0–1) decides what's confident enough to blend. Pixels caught between the two are present but passed through - so faint edges get carried along, just not averaged into mush.
Raise presence_threshold when one mask has broad, faint noise that shouldn't count as coverage. Lower blend_threshold toward 0 when you want even weak overlap to merge. The defaults are well chosen; most people never touch either.
Two practical constraints, both from the code. The masks must have matching spatial dimensions - it throws a ValueError if they don't, so resize to match before you wire them in. Batch dimensions don't have to match: it broadcasts to the larger batch, which is handy when you're processing a stack of frames (video inpainting, animation) and the two mask streams come from different sources.
Install
Part of the Advanced Mask Nodes pack by evanscho - a small, dependency-free collection (no pip requirements, no model downloads; it's pure PyTorch using ComfyUI's own torch). ComfyUI Manager: search "Advanced Mask Nodes", or:
cd ComfyUI/custom_nodes
git clone https://github.com/evanscho/ComfyUI-advanced-mask-nodes
# restart ComfyUI
Minor gotcha: the pack's README gives the clone URL with underscores (evanscho/advanced_mask_nodes) and that repo doesn't exist - use the hyphenated URL above, or let the Manager handle it. The pack is GPL-3.0 and young (one commit as of early 2026), so there's not much community history - which is fine for a node this simple and well-tested.
Verdict
It's not glamorous. It's the node you reach for on the way to somewhere more interesting, and it does exactly one job: turn two overlapping masks into one without a seam. In a world where masks come from every direction - SAM clicks, text prompts, hand painting, model output - that single job turns up constantly.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| mask_a | MASK | — | |
| mask_b | MASK | — | |
| presence_threshold | FLOAT | 0.010–0.5 | Minimum value for a pixel to be considered 'present' in a mask. Raise to ignore soft edges; set to 0 for strict non-zero behavior. |
| blend_threshold | FLOAT | 0.010–1 | Minimum value for a pixel to participate in averaging. Pixels between presence and blend thresholds are present but passed through without blending. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MASK | MASK | — |