Field Morphology
Grow, Shrink, Feather and Outline Without the Jagged Edges
- field
- mask
The cleanup pass every mask chain needs
If you've built masks in ComfyUI for more than a week you've hit the same wall: the detection or the edge map gives you a region that's nearly right, and you need it a few pixels bigger so the seam doesn't land inside the subject. That's a dilate. Or you need it smaller (erode), or softer (feather), or you want the outline only (morphological gradient). Field Morphology is all four, and it's the node you'll drop in right before a sampler in almost every mask workflow.
It's also the pack's clearest demonstration of why all this fuss about length units matters.
Radius is a fraction, and that's the point
radius is expressed as a fraction of the longer frame edge - never in pixels. That's not pedantry; a pixel radius is the exact bug that makes a 512 preview and a 2048 render different pictures, and it's half the reason this pack exists. Radius 0.001 is about one pixel at 1024 wide, so the pixel case is still reachable, you just have to say it in the units everyone else is using. The default is 0.02, and the range runs to 0.5.
The four operations:
grow- dilate, expand the bright region.shrink- erode.feather- a Gaussian with sigma = radius/2, so the visible ramp is about one radius wide. Same word, same meaning, in all four modes.outline- the symmetric morphological gradient: a band of width 2R centred on the contour.
Feather uses replicate padding, so a mask touching the frame edge doesn't darken against it - a small detail you only notice when it's missing and your vignette has a dark bar down one side.
The structuring element is an octagon
Here's the bit that separates this from every max_pool2d dilate you've used. A plain square kernel is anisotropic - it grows corners faster than it grows edges - and a plain diamond is just as bad in the other direction. Both deviate from a true disc by 41.4%. Field Morphology instead builds an octagon by iterating 3×3 square and cross passes in the ratio sqrt(2) − 1 : 1. That ratio is solved rather than guessed, and the result deviates from a true disc by 8.24% - about five times better.
The deviation is asymptotic in radius: measured max/min ratio is 1.25 at R = 4 px, 1.14 at R = 8, and 1.06 at R = 16 and above. If you're growing by two pixels you'll still see slight octagon-ness; if you're growing by twenty you won't.
Cost, and why it sometimes feels stuck
Cost is linear in radius, and it's CPU-bound unless you're on CUDA. The author's own numbers at 1024×576: 160 ms at R=5, 463 ms at R=20, and 2.0 seconds at R=102 on CPU - then 8 ms at that same R=102 on GPU. So a big feather on a CPU-only install is genuinely slow, and it's not hanging. Above 64 pixels of radius the node prints the pass count to the console so a long wait is never a mystery. If you're on CPU and doing heavy morphology, do it once at low resolution and upscale the mask, or just accept the seconds.
Inputs and outputs
Three things: field (MASK), operation (grow, shrink, feather, outline), radius. One output: mask.
Where it goes next is the usual suspects. Grow before an inpainting pass so the seam sits outside the subject. Feather before a composite so the transition isn't a line. Outline into Field Composite with a different image to get a stroke. Shrink after a noisy detection to drop the speckle.
Install
ComfyUI Manager → ComfyUI Field, or:
cd ComfyUI/custom_nodes
git clone https://github.com/jeremieLouvaert/ComfyUI-Field
Restart. Nothing to download, no extra packages. It's under AKURATE/Fields/Refine.
Getting burned
Radius is the long edge, not the width. On a 1920×1080 frame, radius 0.02 is 0.02 × 1920 ≈ 38 pixels - not 0.02 × 1080. If your grow is coming out bigger than you budgeted, that's why.
And the one to internalise if you ever mix this node with Field Distance: they disagree by exactly half a pixel, by construction. Field Morphology counts pixels; Field Distance measures to the contour. Chaining one after the other and expecting the measurements to agree will have you chasing a phantom bug. Both are right for what they measure.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| field | MASK | — | |
| operation | COMBO | grow | 4 options: grow, shrink, feather, outline |
| radius | FLOAT | 0.0200–0.5 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| mask | MASK | — |