ECHO Refine Mask / 回响·边缘精修(待复核)
ECHO Refine Mask fixes hair on CPU, no model download
- image
- foreground_proposal
- sure_foreground
- sure_background
- unknown
- foreground_alpha
- background_alpha
- risk_not_confidence
- review_report
ECHO is a color-consistency pack with a narrow job: take a stack of product or fashion photos and nudge each one toward a reference shot's exposure, warmth and color so a whole SKU set reads as one collection. If you found this page, you probably came for its headline node, ECHOReferenceMatch. This is the quiet one that makes that node's output look right - the mask-repair pass whose display name literally ends in (待复核), "pending review."
That name isn't admin noise. It's the node's whole design philosophy, and it's the reason to care about ECHORefineMask even if you never touch color matching.
Why a "mask repair" node exists at all
When ECHO shifts your background toward the reference color, any hair strand, arm-to-body slit or lace edge where your subject mask is wrong becomes a halo - a bleed of old background into the new one. The cheap fix is feathering the mask, which just makes a bigger, blurrier mistake. Segmentation models (BiRefNet, rembg, whatever made your crude mask) label pixels person-or-background, and that's structurally wrong for pixels that are partly both: a wisp of hair over a background is genuinely fractional.
Matting is the operation that solves fractional alpha instead of deciding. ECHORefineMask is a closed-form matting solver that runs at original resolution on your CPU, needs no GPU and downloads no weights.
How it works
Feed it the image plus a rough foreground mask (white = person/object). It erodes a band around the mask's transition into an unknown gray zone - that's your trimap, the classic matting input - then re-solves real fractional alpha for just those unknown pixels. Internally it uses PyMatting's closed-form solver (estimate_alpha_cf), patched over overlapping tiles in balanced mode.
The inputs that actually matter:
foreground_proposal- your crude mask. Geometry must match the image exactly; the node refuses to silently resize it, because resizing moves edges you may have carefully placed.band_pixels- width of the unknown band to re-solve (default 8, range 1–64). Too narrow and it can't reach the hair; too wide and it solves a lot of expensive pixels.sure_foreground/sure_background/unknown- optional correction masks for when you want to force a region. Hard black-and-white marks only; soft feathered strokes error out on purpose.quality-balanced(default) orhigh. High solves the complete unknown domain in one piece instead of tiles, and unlocks the color-space and solver choices.
Here's a take on the settings: quality=high, solver_space=linear and solver_backend=sparse_cf are real knobs with real effects - alpha computed in linear light is a different number than in sRGB, and sparse_cf is the path for big bounding boxes with a narrow edge band. But balanced mode errors out if you try high-only options rather than silently ignoring them, a deliberate fix after an audit found silent ignores. memory_mb and max_unknown_pixels are admission budgets that let it refuse work it can't finish. Leave them alone until a run tells you otherwise.
Outputs and where they wire in
foreground_alpha- fractional alpha, white = foreground.background_alpha- its complement, white = background. This is the one to feed intoECHOReferenceMatch'ssource_background_maskinput (white = background there), so the color run gets your cleaned-up separation.risk_not_confidence- a risk map flagging edge regions with weak or distant evidence. It is not a confidence map. Black doesn't prove the cutout is right; it proves nothing was flagged.review_report- a JSON string of per-patch diagnostics. Read it when something smells off.
Install and the one gotcha that will bite you
cd ComfyUI/custom_nodes
git clone https://github.com/x9c4gqtpv4-coder/ECHO.git
/path/to/comfyui/python -m pip install -r ECHO/requirements.txt
Restart, and ECHORefineMask appears under ECHO/Mask repair. Here's the trap: requirements.txt only installs numpy and Pillow. The matting solver lives in the pack's optional matting extra, and without it the node dies with a pointed error telling you to install it. Do that explicitly:
/path/to/comfyui/python -m pip install pymatting==1.1.15
Common issues
- "CPU matting is not installed" - the gotcha above. No runtime downloads, it just needs the extra.
- Blocked runs. If the solver can't finish - full-bleed uniform color, too little local evidence, budget exceeded - it raises instead of faking success with a feathered pass. The README is honest that a real 3584×4800 hard case was blocked on capacity and evidence. When it blocks, check
review_report, not the feather width. - Soft or conflicting correction strokes - use hard marks; feathered edits error deliberately.
- Remember the 待复核. Every output is a review candidate, not an approved cutout. For actual production, a human signs off - which, given how confidently background tools lie about hair, is the most defensible design choice in this whole pack.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| foreground_proposal | MASK | — | |
| band_pixels | INT | 81–64 | — |
| sure_foregroundopt | MASK | — | |
| sure_backgroundopt | MASK | — | |
| unknownopt | MASK | — | |
| qualityopt | COMBO | balanced | 2 options: balanced, high |
| solver_spaceopt | COMBO | srgb | 2 options: srgb, linear |
| solver_backendopt | COMBO | cf | 2 options: cf, sparse_cf |
| context_pixelsopt | INT | 00–256 | 0 = quality preset default |
| max_context_pixelsopt | INT | 00–256 | 0 = quality preset default |
| memory_mbopt | INT | 102464–4096 | — |
| max_unknown_pixelsopt | INT | 5000001–2000000 | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| foreground_alpha | MASK | — |
| background_alpha | MASK | — |
| risk_not_confidence | MASK | — |
| review_report | STRING | — |