Mask Grow
Shrink or expand a mask by N pixels — Mask Grow
- mask
- mask
A bbox detector hands you a rectangle that hugs the subject a little too tight, or a segmentation mask that bleeds a couple of pixels past the edge. Either way you need the mask bigger or smaller by a few pixels, and wcx_MaskGrow is the dial: positive values expand the mask (dilate), negative values shrink it (erode).
Mechanically it's morphological morphology via pooling - the sort of thing OpenCV calls dilate/erode. A positive grow runs a max-pool over the mask with a kernel sized from the grow value, which expands white regions outward by roughly that many pixels. A negative grow does the same thing on the inverted mask and inverts back, which erodes. The kernel is 2*|grow|+1, so grow 4 means roughly a 4-pixel expansion per side. It handles single masks and batches (channel dimension added and removed internally), and prints a small status line to the console after processing.
Inputs are mask (MASK) and grow (INT, default 4, range −999 to 999); output is mask. Note the default is 4, not 0 - if you drop this node in expecting a pass-through, you'll get a 4-pixel expansion. Set it to 0 for a true no-op.
Where it earns its keep:
- Compensate for tight bbox masks. The KB's masking doc flags exactly this: a bbox detector's rectangle can miss part of the subject, and growing the mask before the detail pass is the standard fix. A little grow plus a little blur (this pack's
MaskBlur) and the patch covers what it should with a soft edge. - Shrink to avoid bleeding. If a mask spills onto neighboring pixels you don't want edited - hair into background, say - eroding by a few pixels pulls it back onto the subject.
- Batch-ready. Feed a whole frame sequence and every mask gets the same treatment, which is what you want for a consistent pass.
Gotchas:
- Extreme values saturate and stop being useful. Grow 500 on a small mask just makes the whole frame masked - there's nowhere to expand to. Erode 500 does the opposite and the mask vanishes. These are gentle-touch numbers, single digits to low tens in practice.
- It's square and crude. No smooth falloff - you get a blocky geometric expansion. That's why the standard recipe is grow for coverage, then blur for the edge.
- Rounding on odd kernels. The relationship between grow value and actual pixels is approximate (kernel is
2n+1, centered), so expect roughly n pixels per side, not an exact contract.
Standard light install:
# ComfyUI Manager: search "ComfyUI-Practical-Tools" → Install → restart
# or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/wenchengxiang/ComfyUI-Practical-Tools
# restart ComfyUI
It's the unglamorous cousin of the blur node - no one posts about it, but every automatic detailing loop I've built has one sitting between the detector and the sampler.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| mask | MASK | — | |
| grow | INT | 4-999–999 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| mask | MASK | — |