Adopts master as the standard for all overlapping work. Master's landed
optimizations supersede server-edition's own fp16 experiment:
- Unified --precision fp32|bf16 knob (bgfilter/precision.py) driving all
three models: ViTMatte weight cast + both BiRefNets via autocast, with a
hardware gate (falls back to fp32 off native-bf16 CPUs) and an
AutocastCPU fp32 shim for torchvision deform_conv2d.
- Query-chunked ViTMatte global attention (bgfilter/attn_chunk.py), exact
and bitwise-identical, caps the N^2 spike (~19 -> ~4 GB at 2048).
- Cross-check HR-matting forward reused as the seg mask (birefnet backend
only), skipping the primary seg model; MIMALLOC_PURGE_DELAY=0.
- inference_mode and the detect_background_color removal converge with
server-edition's earlier equivalents.
Conflict resolution (favoring master, preserving server-only features):
- vitmatte_infer/segmentation: dropped server's device-derived fp16 for
master's precision path, kept resolve_model_source (local weights).
- service.py: cross-check SegmentationSettings now passes precision so the
HTTP service honors bf16 like the CLI's _second_opinion does.
Verified on CPU: default fp32 pipeline loads 2 models (seg-reuse active)
and bf16 path runs (autocast + deform_conv2d shim) — both exit 0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- chroma.py: remove detect_background_color — orphaned since auto-detection
goes through estimate_background_model -> _background_border_cluster;
nothing in the repo calls it.
- settings.py: fix stale "Segmentation always stays fp32" comment
(--precision now fans out to the BiRefNet models too).
- README: add a measured CPU performance section (9700X reference numbers,
memory ceiling explanation, Zen 2 fallback guidance).
- docs/hair_gap_artifacts.md: record that the cross-check cost note is
obsolete — reuse_as_seg returns the net model count to 2, bf16 and
chunked attention absorb the rest.
- docs/green_screen_matting_workflow.md: add the 2026-07 additions to the
architecture-evolution note.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Brings in the two algorithm optimisations from master:
- Gate chroma suppression by the matte's own confidence (639fdf0)
- Add cross-model veto of hair-gap background residue (adbbb9d)
Server-edition integration on top of the plain merge:
- PipelineManager caches the cross-check model (BiRefNet_HR-matting) and
injects it into MattingPipeline, so HTTP requests never reload it.
- MattingResult carries cross_check_alpha; debug output matches master.
- /healthz reports crossCheck; README lists models/BiRefNet_HR-matting
in the local-weights bundle.
Verified: CLI --no-cross-check baseline and full cross-check run both
pass on samples/TestImage3.png; cross_check_alpha.png written to debug.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Colour-drifted background trapped between hair strands defeats every
single-signal defence: the chroma key reads it as foreground (bgc ~0.07),
the segmenter backs it, ViTMatte rates it opaque, and post-hoc removal is
a proven dead end (it shreds the hair volume the same pixels belong to).
A second, trimap-free matting model (BiRefNet_HR-matting) is the only
tested model that separates this residue from the subject, so its opinion
is fused in as a veto: min-fusion that may only LOWER alpha, restricted to
the background-hued bright suspect zone (proj >= 3, L >= 45, feathered)
and gated by primary-alpha confidence (0.70 -> 0.95 ramp) so soft wisps
and dark hair are exempt by construction.
- settings/config/CLI: cross_check block, --cross-check/--no-cross-check
- alpha_post.cross_check_alpha after clean_alpha; second opinion reuses
BiRefNetSegmenter; saved to debug as cross_check_alpha.png
- chroma.bg_hue_projection extracted and shared with the trimap
- docs: methodology.md (new), hair_gap_artifacts.md (investigation log)
Verified: cross-check ON reproduces the visually-reviewed B1gate
prototype byte-for-byte on TestImage3; --no-cross-check reproduces the
previous baseline byte-for-byte; pink-bg FixImage1 face untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Segmentation backend now defaults to birefnet (ZhengPeng7/BiRefNet); anime-seg is
selected at runtime with --seg-backend anime-seg, which also swaps in the matching
weights (unknown backends raise). Config files stay for detailed tuning, not
backend selection.
- Default device is now cpu everywhere (dataclass defaults, default.yaml,
birefnet.yaml); pass --device cuda for GPU. Avoids a hard CUDA-required failure on
machines without a CUDA-enabled PyTorch build.
- Docs: README + workflow status note updated (backend via --seg-backend, CPU
default, examples no longer force --device cuda).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
README rewritten for the current design: two pipelines (chroma-only vs single
segmenter, default anime-seg), the screen_color prior (--screen-color / config,
green default), correct debug-file list, and HF/hf-mirror notes for the seg models.
No rescue/recolour layer is documented (it was removed).
green_screen_matting_workflow.md keeps the phase-1 green-screen spec but gains a
status note pointing to the README for the evolved architecture, and its debug-file
list is corrected (foreground_rgb / color_mask / seg_mask, not the old
foreground_background / foreground_correction / despill_mask).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
After the full-foreground despill (5ddf0cd) the residual green was confined to
semi-transparent hair (alpha < 0.5): 85% of the worst pixels had alpha < 0.3,
where a pixel-wise unmix (divide by small alpha) is too noisy to trust.
Replace the hand-rolled unmix/local-blur estimator with pymatting's
estimate_foreground_ml (Germer et al. multi-level closed form), which propagates
reliable foreground colour from high-alpha neighbours into the fringe and
estimates the background, so green spill is unmixed rather than clamped. The
despill pass stays as a light cleanup on top.
- foreground.method selects "ml" (default) or "unmix" (legacy heuristic kept as
a fallback when pymatting is unavailable, matching the chroma fallback idiom).
- ForegroundEstimate now exposes rgb (F), background (B) and a correction map;
debug outputs become foreground_rgb / foreground_background / foreground_correction.
Controlled comparison (same ViTMatte alpha, only foreground method changed),
edge_green_excess:
TestImage p95 0.176->0.031, mean 0.061->0.005
TestImage2 p95 0.165->0.004, mean 0.052->0.002
Adds pymatting (pulls in numba) to requirements.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>