Commit Graph

13 Commits

Author SHA1 Message Date
lhk229 da4164e95a Support loading model weights from local project folders
Add bgfilter/weights.py: resolve_model_source() maps a HuggingFace repo id
to a local folder under the weights dir (models/ by default, override with
BGFILTER_WEIGHTS_DIR) when one named after the repo basename exists; otherwise
the repo id is returned unchanged. Opt-in and backward compatible.

- vitmatte_infer.py / segmentation.py resolve model_name through it; anime-seg
  reads <dir>/isnetis.onnx directly instead of hf_hub_download when local.
- .gitignore: models/, model-cache/
- README: document bundling weights as plain project folders.

Verified: anime-seg loads from a local models/anime-seg/ folder offline.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 02:50:19 +00:00
lhk229 d24c6ed608 Add FastAPI HTTP service for background removal
Wrap the BGfilter matting pipeline in a long-running FastAPI service
(POST /remove-background, GET /healthz) exposing only screen_color and
seg_model, matching the birefnet-service request contract.

- bgfilter/pipeline.py: add in-memory run_rgb entry returning a
  MattingResult; allow injecting a shared runner/segmenter. CLI file
  path (run_image) behaviour is unchanged.
- bgfilter/service.py: PipelineManager caches one shared ViTMatte runner
  and per-backend segmenters, so screen_color/seg_model never reload a
  model.
- app.py: thin FastAPI layer -- param validation, image decode/encode,
  error codes (400/413/500), timing headers, global asyncio lock.
- requirements.txt: fastapi, uvicorn[standard], python-multipart.
- README + design doc: HTTP service usage and HF-mirror/proxy/Xet
  download notes.

Verified end-to-end (base ViTMatte + BiRefNet + anime-seg): 11/11
acceptance checks pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 12:08:25 +00:00
lhk229 cf0ceec496 Remove redundant configs/birefnet.yaml; drop a stray --config example
BiRefNet is the default backend and --seg-backend switches segmenters, so the
birefnet.yaml config (a copy of default.yaml with backend: birefnet) no longer had
a purpose. configs/ now holds just default.yaml, the editable parameter template.
Also dropped the now-redundant --config from the chroma-debug README example.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 18:11:47 +08:00
lhk229 3f66f66ec7 Align default ViTMatte model to base; make --config optional
The ModelSettings.model_name dataclass default was still vitmatte-small (the
phase-1 "start small" choice) while configs/default.yaml used vitmatte-base, so a
bare run (no --config) silently differed from every documented example. Set the
dataclass default to base too: the built-in defaults now match default.yaml
field-for-field, so --config is only needed after editing that file to tune
parameters. README examples drop the now-redundant --config.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 18:09:55 +08:00
lhk229 a6d84845c6 Default to BiRefNet + CPU; add --seg-backend to pick the segmenter
- 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>
2026-07-02 16:32:13 +08:00
lhk229 62f175948e Auto-detect the background colour (default); drop the green heuristic
Replace the hardcoded green-screen auto-detection with a general flat-colour
detector. When screen_color is null the background colour is now detected from the
image border (dominant colour of the border strip) and used directly as the chroma
model, with a failure gate that raises when the border is not one clean flat colour
(gradient / texture / subject filling the frame).

- chroma: add detect_background_color + _background_border_cluster; the null case of
  estimate_background_model samples the detected cluster directly (no seed search);
  compute_bg_confidence is now always perceptual (Lab/RGB distance). Removed the green
  heuristic (initial_green_candidates), the green multiplicative gating, the now-unused
  _smoothstep, and five green-only ChromaSettings fields.
- pipeline: reuse the detected colour for de-spill in the auto case.
- settings / default.yaml: add detect_* tuning fields; refresh screen_color docs.
- README: document auto-detection + the failure gate, trimap modes, birefnet config.

A supplied --screen-color hex still uses the seed-search refinement. Validated:
detects green / pastel / text samples correctly, raises on gradient / two-colour, CLI
exits 1 on failure, green and pastel mattes unchanged in quality.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 20:34:31 +08:00
lhk229 22ef1d6336 Sync docs to current architecture
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>
2026-07-01 15:46:21 +08:00
lhk229 9b7a192599 Use pymatting ML foreground estimation to remove edge spill
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>
2026-06-30 17:33:35 +08:00
Codex d6bb658244 Add foreground color estimation pass 2026-06-30 16:25:56 +08:00
Codex 10705d49df Support YAML pipeline configuration 2026-06-30 15:03:15 +08:00
Codex 923dbe9f09 Add sample smoke check and refine foreground despill 2026-06-30 14:42:08 +08:00
Codex 464a60c733 Improve despill and add quality checks 2026-06-30 14:29:19 +08:00
Codex 8fc53925e0 Implement green screen matting pipeline 2026-06-30 14:14:15 +08:00