ComfyUI Node

Edge Spread

The dark line around your cutout isn't your matte — it's the fringe

By Code2Collapse·Created 7 months ago·Updated 2 days ago· 56
Edge Spread
  • image
  • mask
  • image
  • report
spread4
invert_maskfalse

What it's for

Your cutout looks fine against the grey checkerboard and then you comp it over a bright background and there's a dark contour all the way round the subject. That's not a bad matte. It's a soft matte stored premultiplied - the RGB underneath the semi-transparent edge pixels has already been multiplied by alpha, so the partially-covered pixels carry a mix of subject colour and whatever dark backdrop the cutout was made against. Comp those pixels over white and the black leaks through the ramp.

The comp answer is edge spread (Nuke people call it edge extend, Photoshop people call it "decontaminate colours"). Push the known interior colour of the subject outward underneath the edge, so the ramp interpolates towards the subject's own colour instead of towards black.

Edge Spread (MEC) is 40 lines of that, and it's the missing half of the matting pipeline. The KB's background-removal doc makes the point that a cutout which "looks clean against a grey preview and falls apart against a coloured background" is a matting problem, not a segmentation problem - this is the deterministic fix for the other half of the same complaint, and it costs nothing (tier 1 node, no model, no VRAM).

How it works

It erodes the matte to find the pixels that are unambiguously interior, then repeatedly dilates those colours into the unknown band with a 3×3 max-pool, growing the colour outward spread pixels. The result is written back only inside spread of the edge, so the interior of the subject is untouched. It's a per-pixel colour push, not a blur - which is why it kills the fringe instead of smearing it.

Inputs that matter

  • image - the unpremultiplied plate. Subject + background, not a pre-cut RGBA.
  • spread - how many pixels of colour to push inward-to-outward. 4 is a sane default for a soft 1–2px edge; go higher for hair, fur, or a very soft matte. It's clamped internally to something frame-sized, no matter what you type, and the report says what actually ran.
  • mask (optional) - the matte that defines the subject edge. The tooltip says alpha is used if you omit it. Connect it anyway. A normal ComfyUI IMAGE is [B,H,W,3] with no alpha channel, so with nothing wired, every pixel counts as interior, the erode leaves nothing to spread, and the node quietly does very little. That's the number one "this node doesn't work" report.
  • invert_mask - flips polarity. Get it wrong and it spreads the background's colour under the edge, which usually reads as "nothing happened" or a subtle colour halo.

Outputs are image (the spread plate - note this is an IMAGE, not a MASK, and alpha is dropped, so keep your alpha from wherever it came) and report, a string of notes including any clamping.

Where it goes in a graph

Typical settling: Background Remover (MEC) or SAM + ViTMatte PipelineEdge Spread → your comp / ImageCompositeMasked / save-with-alpha. Run it at final resolution - if you upscale after, the band you just spread gets resampled along with everything else and you'll want a second pass.

Order matters: spread before grain, before any colour grade that might move the edge's exposure independently, and before you composite onto the plate. If you comp first and spread second you're pushing the composite's colours around, which is not the point.

Install

ComfyUI Manager → search "CustomNodePacks", or:

cd ComfyUI/custom_nodes
git clone https://github.com/Code2Collapse/ComfyUI-CustomNodePacks

Restart ComfyUI and look for the [MEC] Loaded … line in the console. The pack's required dependencies are opencv-python, scipy and safetensors; nothing here needs a model download. The README's own warning is worth repeating: don't blindly pip install -r requirements.txt - ComfyUI ships its own torch/numpy/Pillow and a blind install can overwrite them. Install only what pip list says you're missing.

Common issues

  • Nothing changes. Either the mask isn't wired (see above), the polarity is wrong, or the fringe isn't a premultiply problem at all. If the matte itself is ragged, no amount of spread will help - that's a matting job.
  • A visible ring of duplicated colour on high-contrast edges. spread is too large. It only ever pushes the nearest interior colour outward, so past the natural edge width you're inventing a band.
  • Nodes aren't in the menu. Check the console for an import error at startup; a failed import silently drops the whole pack's nodes.
CategoryMEC/Mask

Inputs (4)

NameTypeDefaultDescription
imageIMAGEUnpremultiplied plate — interior colour is pushed under the edge.
spreadINT40–9999How many pixels to push inward colour outward — kills the dark fringe on a lighter background.
invert_maskBOOLEANfalseFlip mask polarity when your matte is white-on-black.
maskoptMASKMatte defining the subject edge; alpha used if omitted.

Outputs (2)

NameTypeDescription
imageIMAGE
reportSTRING