Add complex-background matting mode to the service via background_mode

Backports master's non-flat matting (chroma.enabled: false + the hue-free
cross-check gate) into server-edition, and exposes it over HTTP without
surfacing the internal "chroma" wording: /remove-background gains a
background_mode form field (flat, default | complex). complex maps to
chroma disabled -- no colour key, segmentation alone drives the trimap and
every colour-keyed stage (auto-detect, hue split, chroma suppression,
despill) is bypassed. The cross-check veto still works in complex mode via
its second-opinion-confidence gate (cross_check.second_lo/hi) but defaults
OFF there (it costs the HR-matting forward); an explicit cross_check=on
re-enables it.

No new model weights: complex mode reuses the already-provisioned BiRefNet
seg + ViTMatte (+ optional HR-matting cross-check). Flat mode is unchanged
(bit-identical), and server-edition's own extras (cross_check.lock,
foreground.use_gpu CuPy path) are preserved -- the port is surgical, not a
copy of master's files.

- settings: ChromaSettings.enabled, CrossCheckSettings.second_lo/hi
- config: override_settings chroma passthrough
- despill/foreground: model=None safe guards (foreground keeps GPU path)
- alpha_post: cross_check_alpha hue-free gate when proj is None
- pipeline: _process_rgb complex branch (seg-only trimap, skip colour stages)
- service/app: process(chroma=), background_mode field, complex-defaults-off
  cross-check, X-BGFilter-Background-Mode header
- cli: --chroma/--no-chroma
- configs/docs: gpu.yaml + default.yaml + README/README_ZH

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 14:04:58 +08:00
parent 28d3fe8842
commit c56e58affe
13 changed files with 166 additions and 33 deletions
+7 -3
View File
@@ -25,9 +25,10 @@ class PipelineManager:
ViTMatte is the matting model shared by both segmentation backends, so it is
loaded once and reused. Each segmentation backend is lazily loaded once on
first use and cached by name. Per-request parameters (``screen_color``,
``seg_model``, ``cross_check``) never trigger a model reload -- ``screen_color``
only affects this request's chroma/despill, and ``seg_model``/``cross_check``
select an already-cached (or first-time-loaded, then cached) model.
``seg_model``, ``cross_check``, ``chroma``) never trigger a model reload --
they only re-parametrise the pipeline over already-cached (or first-time-
loaded, then cached) models. ``chroma=False`` selects non-flat/complex
background mode (no colour key); ``screen_color`` is then unused.
"""
def __init__(self, base_settings: PipelineSettings, preload: bool = True):
@@ -142,6 +143,7 @@ class PipelineManager:
screen_color: str | None,
seg_model: str,
cross_check: bool | None = None,
chroma: bool | None = None,
) -> MattingResult:
if seg_model not in _SEG_MODELS:
raise ValueError(f"invalid seg_model '{seg_model}'")
@@ -149,6 +151,8 @@ class PipelineManager:
self._base,
screen_color=screen_color,
seg_backend=seg_model,
# None leaves the base default; False selects non-flat/complex mode.
chroma=chroma,
# Honor the lane lock: a locked lane ignores the per-request override
# (a cpu-fast box never runs cross-check, even on cross_check=on).
cross_check=self.effective_cross_check(cross_check),