EditUtils: Alpha Noise Filter lrzjason
Qwen-Image 2.1 Hands You a Cutout With Dirty Alpha — This Is the Brush
- image
- mask
- image
- mask
If you've ever generated a transparent PNG and then fought the cutout for an hour, you already know the ranking: alpha the model produced while generating beats anything you bolt on afterwards. The edges are clean by construction instead of reconstructed.
Qwen-Image 2.1 ships that capability properly - its 64-channel, 16x-downscale VAE is RGBA-aware, so a generation can carry a real alpha channel. The catch is that nobody tells you how dirty that raw alpha is. The transparent region arrives speckled with faint low-value alpha, almost invisible on its own and instantly obvious the moment you composite over a dark background or feed the image to anything that reads the mask.
AlphaNoiseFilter_EditUtils is the node that fixes exactly that, and only that.
What it actually does
Three stages, in order, on the alpha channel alone:
- Clip. Anything below
alpha_thresholdis multiplied to zero. That kills the background wash in one pass. - Drop islands. Connected alpha regions smaller than
min_areapixels get deleted - stray flecks that survived the clip. - Feather, inwards. A gradient band is built inside the matte's own edge: fully transparent at the boundary, ramping up to fully opaque
featherpixels inwards.
That third step is the interesting design decision, and the reason to prefer this over blurring the mask in a mask-processing pack. A symmetric blur spreads the gradient band outward, into pixels the generator left at alpha 0 - and those pixels still hold the VAE's raw background colour, a purple wash in the author's own measurements. Blur at feather=4 lit up ~13,700 previously transparent pixels at a mean RGB of about (92,47,102), which is the classic "why does my cutout have a glow" halo. Feathering inwards keeps it at zero.
The cost is honest: alpha inside the band goes down, so the silhouette contracts - roughly −2.8% at feather 2, −10% at 8 - and thin stuff like fur fades if the band is wider than it is.
The inputs you'll touch
image is required, and it's where the alpha comes from - a four-channel image straight out of VAEDecode on a Qwen-Image 2.1 graph. mask is the fallback for when your image is RGB: the node uses it as the alpha instead, resizing it to match if needed.
Then four optional knobs, with sane defaults:
alpha_threshold(0.10) - the clip. Raise it if noise survives, lower it if soft semi-transparent detail is disappearing.min_area(100) - island filter, in pixels. 0 disables it.feather(2.0) - band width in pixels, 0 gives you a hard edge.invert_mask(false) - flips the output mask to1 - alpha, white = transparent, which is what inpainting nodes expect.
Two outputs: image (the cleaned RGBA) and mask (the alpha as a mask, white = opaque unless you inverted). The RGB channels come out byte-identical to the input - nothing is touched but alpha.
Wiring
VAEDecode ──► AlphaNoiseFilter_EditUtils ──┬──► SaveImage (RGBA cutout)
└──► mask ──► inpaint / edit nodes
If you're driving inpainting with the mask, flip invert_mask on and read the docs for the consumer node before you trust it - the ComfyUI convention for inpaint masks is white = the area to redo, which is the opposite of the node's default.
Install
ComfyUI Manager → search ComfyUI-EditUtils → install → restart. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/lrzjason/ComfyUI-EditUtils
Nothing to pip install - the pack has no requirements.txt. The one dependency worth knowing about is scipy: with it present the node uses ndimage.label and distance_transform_edt; without it both stages fall back to pure torch (erosion rings, morphological opening). Since scipy is effectively a ComfyUI dependency anyway, you'll almost always be on the better path.
No model downloads of its own, but the image you feed it has to come from a Qwen-Image 2.1 VAE - so that whole stack, and a ComfyUI build that supports qwen_image21.
Where people get burned
The RGB-with-no-mask crash. VAEDecode on most models gives you three channels. Feed that in with nothing on the mask socket and the node raises, deliberately: no alpha channel, no mask. It's the node refusing to guess - wire a mask or use the 2.1 VAE.
Cranking the threshold to clean harder. Past about 0.2 you start eating legitimately soft alpha - smoke, glass, out-of-focus hair - and you'll blame the feather. The threshold is for a noise floor, not a strength dial.
min_area too high on small subjects. A 100px island filter is nothing on a 2048px frame and catastrophic on a 400px product shot. Drop it to 0 first, confirm the islands are actually the problem, then climb.
Feather as a quality setting. It's a contract-the-silhouette setting. Default of 2 is right for most cutouts; 6+ is for deliberate soft-vignette looks, and it will eat fur.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | RGBA image, e.g. the VAEDecode output of the Qwen-Image 2.1 VAE | |
| maskopt | MASK | Used as the alpha when the input image has no alpha channel (RGB input) | |
| alpha_thresholdopt | FLOAT | 0.100–1 | Alpha below this is treated as low-value noise and clipped to 0 (0 disables) |
| min_areaopt | INT | 1000–65536 | Drop isolated alpha islands smaller than this many pixels (0 disables) |
| featheropt | FLOAT | 2.00–32 | Width in pixels of the gradient band created inside the edge: fully transparent at the matte boundary, rising smoothly to fully opaque `feather` px inwards. The matte never grows outwards, so no pixel the generator left transparent can become visible (0 = hard edge) |
| invert_maskopt | BOOLEAN | false | Output 1 - alpha as the mask (white = transparent, the ComfyUI inpaint convention) |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |