Feather Mask from Boundary
Feathered Edges That Follow the Mask's Own Bounding Box
- mask
- mask
Most mask softening tools give you one number: blur. That is fine for hiding a seam, and useless when what you actually want is a shaped plate - a rectangle of content that fades out predictably toward its own edges, with a wider ramp at the top than the bottom, sized to whatever the mask happens to cover. This node does that second job. It finds each mask's bounding box and applies a linear ramp inward from each edge, with a separate width for left, top, right and bottom.
How it works
For every item in the mask batch, the node computes the nonzero bounding box of that item, copies just that rectangle, and multiplies in four ramps - one per edge, each left, top, right or bottom pixels wide, scaling from 0 at the boundary to 1 where the ramp ends. Everything outside the box is zeroed. The ramp lengths are clamped to the crop, so asking for a 500-pixel feather on a 40-pixel mask just ramps the whole thing rather than erroring.
Then there is outward, and it is the part worth reading twice. With it off (the default), the feather ramps inward, which means the outer part of your existing mask gets dimmed - that is the ordinary feather behaviour and it is what you want when you are compositing content you already have. With it on, the node first grows the mask by max(left, top, right, bottom) - 1 pixels and pads the canvas, then feathers the grown mask, then crops back. The effect is that the entire original mask stays solid and the ramp lands outside it. That is the mode for inpainting: your subject is preserved at full strength, the falloff spills into the surrounding image.
tapered_corners only affects the growth step. Off, the growth footprint is a square - corners keep their shape. On, the diagonal corners are dropped, so the grown region is chamfered and the corners of the feather round off. If your ramps meet at 90-degree corners and the result looks pasted, that is the dial.
Inputs and outputs
mask in, mask out, same shape and 0-1 range. The settings are left, top, right, bottom (integers, up to 16384), outward and tapered_corners. Batch handling is per item, which is the quietly useful bit: a batch of ten masks gets ten different bounding boxes, each feathered to its own extent, in one pass.
Reach for it when you are pasting generated content into a frame - a feathered rectangular plate makes the join disappear - or when you have a crop-and-stitch inpaint and you need the mask to reach full opacity before the crop boundary so the composite has a solid core. It is also a clean way to precondition a mask for a detailer whose region you do not want to grow.
Install
The node ships inside ComfyUI-Utility-Suite. ComfyUI Manager → search ComfyUI-Utility-Suite → install → restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/tom-m-2020/ComfyUI-Utility-Suite
Restart ComfyUI. This node imports scipy.ndimage, which is already in ComfyUI's own requirements, so a normal install has it - but if you are running a stripped-down environment, that is the import that will fail. It also pulls opencv-python-headless in via the pack's requirements, which other nodes in the suite use. No model files. Written against the newer V3 node API, so a current backend is required.
Traps
It is a straight line, not a Gaussian. A 200-pixel feather gives you a clean linear gradient - readable as a gradient, occasionally too "digital" for photographic blending. If you want a smooth falloff, Blur Mask Outward does the Gaussian version and preserves the solid core the same way. The two nodes are complements, not duplicates: one gives you shaped, side-specific ramps, the other gives you a soft blur.
An empty mask is not an error. If a batch item has no nonzero pixels there is no bounding box, so it passes through empty. That is usually right, and occasionally the reason your shot looks unchanged.
The box comes from stray pixels. One speck of mask at the far corner of the canvas makes the bounding box the whole canvas, and your carefully tuned feather now runs across everything. Clean the mask before you feather it - a small-component pass or a fill first - rather than trying to fix it with the ramp widths.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| mask | MASK | — | |
| left | INT | 00–16384 | — |
| top | INT | 00–16384 | — |
| right | INT | 00–16384 | — |
| bottom | INT | 00–16384 | — |
| outward | BOOLEAN | false | — |
| tapered_corners | BOOLEAN | false | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| mask | MASK | — |