Kepri Mask Analysis (Quality Gate + Fallback)
A quality gate that catches silently-broken masks
- primary_mask
- fallback_mask
- mask
- fallback_used
- area_percent
- reason
Promptable segmenters - SAM3 driven by a text prompt, say - fail in a particularly nasty way: silently. Either nothing matches the prompt and you get an empty mask, or the model grabs a spurious tiny fragment that's technically nonzero and totally wrong. The empty mask crashes your downstream bounding-box node with a cryptic error; the fragment doesn't crash anything, it just quietly produces a wrong cutout. KepriMaskAnalysis is the quality gate that catches both.
The idea is simple: judge the primary mask by its relative area, and if it fails, switch to a fallback mask from a content-based salient model (RMBG-2.0, BiRefNet) that "sees" the object no matter what the prompt said. It's built by Kepri, the fashion-reseller backend behind the whole pack, and it exists because their production pipelines needed a segmentation step that can't fail quietly at scale.
How it works
min_area_percent (default 0.2) is the gate: the primary mask fails if its area is 0 or below that percentage of the image. When the gate fails, the node reaches for fallback_mask - and here's the trick, the input is lazy. ComfyUI only evaluates that branch when the gate actually fails (check_lazy_status pulls it on demand), so the nominal path costs you nothing extra. The ~1–2 second GPU salient pass only runs on the photos that need it.
If the fallback is itself empty or not wired, on_fallback_empty decides: error raises a readable error instead of letting the pipeline crash cryptically downstream (the default, and the right call for a batch you want to know about), full_frame returns a white mask and lets review catch it, passthrough hands the empty primary through.
Inputs and outputs that matter
primary_mask- the mask to judge (e.g. your merged SAM3 output).min_area_percent- the threshold.0.0means "only fall back when truly empty."fallback_mask- the lazy salient mask (RMBG/BiRefNet). Optional.on_fallback_empty-error/full_frame/passthrough.
Outputs: mask (the winner), fallback_used (boolean - log it in production), area_percent (area of the primary mask, for calibration), and reason (ok / empty / below_min_area / fallback_also_empty).
Calibrating the threshold
Don't just trust 0.2. Wire area_percent to a preview or console and collect two populations: the spurious mini-fragments, and your legitimately thin subjects - a fine necklace chain is the worst case, genuinely tiny in area. Set min_area_percent between them. The pack's own notes put fragments well under 0.1–0.2% and a thin chain on a 2048² image at typically 0.5–1%. Note the fallback is trusted as soon as it's non-empty - it's deliberately not re-gated, or a legitimately thin necklace would get bounced too.
Placement and install
Chain it after KepriMaskMerge (the detector-union node) and before the mask→bounding-box node. If you see that ValueError in your logs, it's not a bug - the gate caught a bad mask and no fallback was available. Wire the fallback branch, or set on_fallback_empty to full_frame.
It ships in comfyui-kepri-nodes-pack: ComfyUI Manager → search the pack title, or:
cd ComfyUI/custom_nodes
git clone https://github.com/wearekhepri/comfyui-kepri-nodes-pack
Restart and refresh; it's under Kepri/Background. Zero dependencies beyond ComfyUI's own torch, no model files in the pack - the RMBG/BiRefNet fallback weights come from whatever background-removal node you're already running. And watch out: the README's clone command points at the wrong repo (comfyui-kepri.git); the real one is comfyui-kepri-nodes-pack.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| primary_mask | MASK | — | |
| min_area_percent | FLOAT | 0.200–100 | Global area threshold on the primary mask. Area < this % of the image -> switch to fallback. 0.0 = fallback only when the mask is fully empty. |
| on_fallback_empty | COMBO | error | If the fallback mask is ALSO empty: raise a clean error (default) / return a full-frame mask / pass the empty primary through. |
| fallback_maskopt | MASK | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| mask | MASK | — |
| fallback_used | BOOLEAN | — |
| area_percent | FLOAT | — |
| reason | STRING | — |