Smooth Mask
De-jag your mask without melting it
- mask
- MASK
Mask edges are ugly. Whether a mask comes from a segmentation model, a threshold, or you drawing with a mouse, the boundary is usually a staircase of hard steps - and hard steps are exactly what you don't want feeding an inpaint or a composite, because the model renders them as a hard seam. The stock solution, one big Gaussian blur, fixes the jaggedness and also destroys everything else: it shrinks the mask, melts the detail, and blurs the parts that were already smooth. Smooth Mask is the middle path. It runs a tiny 3×3 average filter over and over, so sharp steps get softened iteration by iteration while flat areas and gentle gradients barely move. You get the edge cleanup without the blowout.
That "doesn't touch what's already smooth" property is the whole trick, and it's why this node exists as its own thing. Averaging a smooth region changes almost nothing - the neighbors are already close to the center pixel - but averaging a sharp step drags it toward its neighbors. Repeat that a few times and a jagged boundary rounds off while the body of the mask stays put. It's the natural companion to the other mask-prep chores: it cleans up stair-stepping before you feed a mask to Set Mask → KSampler for inpainting, or before compositing, where the troubleshooting playbook's oldest advice - soften the mask edge to kill the seam - becomes something you can aim instead of just apply.
How it works
Each iteration applies a uniform 3×3 box filter (center pixel plus its eight neighbors, averaged with replicate padding at the image border). iterations (default 5, range 1–100) is how many passes you run - more iterations, smoother result, and proportionally more compute, since each pass is a full convolution. The only_increase boolean flips it from a plain smoother into a gap-filler: when on, each pass takes the element-wise maximum of the smoothed and current mask, so dips and pinholes fill in but peaks are never lowered. That's the flag you want when a mask has holes or thin cracks you need gone without shrinking coverage at all - useful for masks derived from segmentation that come back with speckles inside the subject.
The one thing to know about only_increase being off: iterative smoothing slowly grinds down sharp peaks, which over many iterations reads as slight edge erosion. That's expected, it's what smoothing does - but if you're watching a thin mask vanish, that's the mechanism, and the fix is either fewer iterations or the flag on.
Inputs are minimal: mask, iterations, only_increase. Single MASK output, wired anywhere a cleaner mask is needed - into Set Mask for inpainting, or into a compositing chain.
Install
Ships in the Advanced Mask Nodes pack by evanscho. Zero dependencies beyond ComfyUI's own torch - no pip requirements, no model files, nothing to download. ComfyUI Manager: search "Advanced Mask Nodes", or:
cd ComfyUI/custom_nodes
git clone https://github.com/evanscho/ComfyUI-advanced-mask-nodes
# restart ComfyUI
One real trap in the README: the clone command it prints uses underscores (evanscho/advanced_mask_nodes), and that repository returns a 404 - the actual repo is hyphenated as above. The Manager route sidesteps the whole thing. The pack is GPL-3.0 and fresh (a single commit as of early 2026), so there's no community lore to point at - but this is a twelve-line algorithm with tests; the main things it can do wrong are the things you can see immediately in the preview.
Verdict
If your masks keep coming out with pixel-stair edges and banding in the gradients, this is the quiet fix. It won't change your workflow's identity, it'll just stop the seams from showing - which, honestly, is most of mask work.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| mask | MASK | — | |
| iterations | INT | 51–100 | — |
| only_increase | BOOLEAN | false | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MASK | MASK | — |