Run the cross-check veto in complex-background mode with a hue-free gate

The veto's suspect zone was defined by background-hue projection, so
--no-chroma silently skipped it. Without a key colour there is no hue
test to lean on, so in complex mode the gate instead requires the second
opinion itself to be confidently near-empty (second_lo -> second_hi ramp,
default 0.15 -> 0.40): regions the HR-matting model decisively rejects
can be cleared, while thin strands it merely blurs to mid-alpha are
untouched -- protecting exactly the crisp-strand advantage the pipeline
has over a raw BiRefNet mask. Flat mode's gate is unchanged.

Validation (BG_IMAGE01-04, cuda fp32): flat default path bit-identical;
complex-mode veto touches 0.007-0.025% of pixels, visibly clearing
blurred residue near strands and milky specks in hair gaps with no
strand erosion. Costs the HR-matting forward in --no-chroma runs
(0.61 -> 1.6 s/image warm GPU); disable with --no-cross-check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 13:09:57 +08:00
parent e61fbe84f0
commit 2b3b62ed3f
5 changed files with 48 additions and 25 deletions
+4 -4
View File
@@ -199,16 +199,16 @@ def _process_rgb(rgb: np.ndarray, pipeline: MattingPipeline) -> MattingResult:
raw_alpha=raw_alpha if alpha_source == "vitmatte" else None,
)
alpha = clean_alpha(alpha, trimap, settings.alpha_post)
# The veto's suspect zone is defined by background hue, so it needs the key
# colour; without chroma the second opinion still serves as seg (reuse above).
if settings.cross_check.enabled and settings.chroma.enabled:
if settings.cross_check.enabled:
lab = convert_color_spaces(rgb)[1]
if second_alpha is None:
second_alpha = pipeline._second_opinion(rgb)
alpha = cross_check_alpha(
alpha,
second_alpha,
bg_hue_projection(lab, model.lab_center),
# No key colour in complex-background mode: proj=None switches the
# veto to its second-opinion-confidence gate (see cross_check_alpha).
bg_hue_projection(lab, model.lab_center) if model is not None else None,
lab[..., 0],
trimap,
settings.cross_check,