Mask Refine
Turning blocky segmentation masks into real alpha mattes
- image
- mask
- mask
You know the problem: BiRefNet or SAM 3 hands you a mask that's right in the middle and garbage at the edges - hard, jagged, stairstep boundaries that glow and fringe the moment you composite the cutout onto a new background. Mask Refine is the fix. It takes that rough mask plus the original image and solves for a soft alpha matte, so hair and fur and glass edges actually survive. No model download, no VRAM, no new checkpoint - it's closed-form matting, running on your CPU, and it works.
The one-line pitch: rough segmentation in, clean feathered alpha out. It slots right after any mask producer - BiRefNet, SAM 3.1, Depth Anything V3, a hand-painted mask, even the output of a threshold node - and before whatever consumes the mask, whether that's inpainting, a compositor, or a detailer loop. This is exactly the gap the KB's background-removal doc warns about: a segmentation model labels pixels foreground/background, which is structurally wrong for hair strands or a wine glass. Matting predicts fractional alpha. That's the difference between a cutout that holds up against a colored background and one that clearly didn't.
How it works
Mask Refine is a simplified reimplementation of spacepxl's Image Matting node from ComfyUI-Image-Filters - the README credits it outright - with every knob stripped down to one. The pipeline, straight from the source:
- If
prebluris above 0, the mask gets a Gaussian blur with kernel sizepreblur*2+1. This softens the hard edges into a gradient before matting even starts. - The blurred mask is turned into a trimap via pymatting's
fix_trimap, using fixed blackpoint/whitepoint of 0.01/0.99. That classifies pixels as definitely-foreground, definitely-background, or unknown. estimate_alpha_cfruns closed-form matting (Levin et al.'s algorithm, the classic one) - it estimates the alpha for the unknown band using the color statistics of the source image, up to 1000 conjugate-gradient iterations.
There's no neural network anywhere in this node. It's the old-school computer-vision matting that everyone forgot about until model masks started needing cleanup, and it's cheap to run. The code also silently aligns mask batch size to image batch size, so it plays fine in a batched workflow.
The inputs that matter
Only three, and only one you'll actually touch:
image- the source image the mask was drawn on. This is what guides the matting, so it needs to be the same resolution as your mask; there's no resizing happening between them.mask- your rough mask.preblur- Gaussian blur radius, default10. Higher values soften hard edges more before matting; set0to skip preblur entirely.
The single output is mask - a MASK tensor with real fractional alpha values, ready to feed an inpainting node, a compositor, or a second threshold pass.
Installing it
Same drill as every node in this pack. ComfyUI Manager → search "easygoing" → install. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/easygoing0114/ComfyUI-AutoMask.git
cd ComfyUI-AutoMask
pip install -r requirements.txt
That requirements.txt is just opencv-python and pymatting. No model files, no HF downloads, nothing to configure.
Where people get burned
Two real gotchas, both grounded in how the pack ships. First, it needs a recent ComfyUI. This pack is written against the new comfy_api.latest extension API (io.ComfyNode / define_schema), not the old NODE_CLASS_MAPPINGS style - if your install predates that API, the node fails at import with a ModuleNotFoundError. Update ComfyUI first if you see that.
Second, closed-form matting is iterative and CPU-bound. It's fine for a single image, but it will feel slow on 4K inputs, and if you're batch-processing a hundred frames it adds up. If you find yourself wanting more control - different trimap handling, more iterations - the full-size Image Matting node in spacepxl's ComfyUI-Image-Filters has the knobs this one hides. And if you feed it a mask that's a wildly different size from the image, the math breaks: matting needs the trimap and the image to line up pixel-for-pixel. Keep them the same resolution and it just works.
The name isn't a lie and it isn't hype: it's a small, honest node that does one job well. If you've been hand-feathering masks or accepting hard edges, this is the ten-second upgrade.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| mask | MASK | — | |
| preblur | INT | 100–256 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| mask | MASK | — |