Make cross-check and reuse-as-seg the service default
Cross-check + reuse-as-seg are already the config/CLI default; align the HTTP service with them instead of forcing cross-check off. The earlier off-by-default was to avoid the extra inference, but reuse-as-seg now makes that forward double as the seg mask (birefnet backend) -- it replaces the primary seg model rather than adding to it, so the cost concern is gone. - app.py: honour the config default (on); BGFILTER_CROSS_CHECK still forces either way, unset = config. - service.py preload: warm the cross-check HR-matting model, and skip the now- redundant primary segmenter when reuse covers segmentation. - README / DEPLOY(_ZH): document cross-check as default-on, BiRefNet_HR-matting as required (not optional), BGFILTER_CROSS_CHECK=0 to disable. Verified: service defaults cross_check on, env forces both ways, preload picks cross-checker and skips the primary segmenter. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -158,20 +158,20 @@ Override the base directory with `BGFILTER_WEIGHTS_DIR`. `models/` is gitignored
|
||||
|
||||
### Cross-check veto (optional, off by default in the service)
|
||||
|
||||
The pipeline can run a second, high-resolution matting model
|
||||
(`ZhengPeng7/BiRefNet_HR-matting`, ~425 MB) as a "second opinion" that only clears
|
||||
background residue trapped between hair strands. In the **HTTP service it is OFF by
|
||||
default** and lazy-loaded, so you don't need this model unless you turn it on:
|
||||
The pipeline runs a second, high-resolution matting model
|
||||
(`ZhengPeng7/BiRefNet_HR-matting`, ~425 MB) as a "second opinion" that clears
|
||||
background residue trapped between hair strands. It is **ON by default** (both CLI
|
||||
and HTTP service) and, with reuse-as-seg, that same forward doubles as the
|
||||
segmentation mask on the birefnet backend — so it replaces the primary seg model
|
||||
rather than adding to it. **You must provision this model** (Option A or B above):
|
||||
|
||||
- Enable service-wide with `BGFILTER_CROSS_CHECK=1`, or per request with the
|
||||
`cross_check=true` form field.
|
||||
- ⚠️ **On an offline server (`HF_HUB_OFFLINE=1`) you must provision
|
||||
`BiRefNet_HR-matting` first** (Option A or B above) — otherwise the first
|
||||
cross-check request fails, because it cannot download the model at runtime.
|
||||
- It adds one extra 2048-px inference (~35 s/image on CPU), roughly doubling latency.
|
||||
- Note the config default (`configs/default.yaml`) has `cross_check.enabled: true`,
|
||||
which the **CLI** honours; only the HTTP service forces it off unless
|
||||
`BGFILTER_CROSS_CHECK=1`.
|
||||
- ⚠️ **On an offline server (`HF_HUB_OFFLINE=1`) it must be present before the
|
||||
first request** — otherwise every default request fails, since it cannot
|
||||
download the model at runtime.
|
||||
- Turn it off service-wide with `BGFILTER_CROSS_CHECK=0`, or override per request
|
||||
with the `cross_check` form field (`true`/`false`).
|
||||
- The service preloads it at startup with the rest of the warm set; on the
|
||||
birefnet backend the redundant primary segmenter is skipped.
|
||||
|
||||
### Downloading behind a firewall (CN networks)
|
||||
|
||||
@@ -196,7 +196,7 @@ redirect back to `huggingface.co`, which recent `huggingface_hub` rejects with
|
||||
| `BGFILTER_DEVICE` | `cpu` | Overrides **both** model and segmentation device (`cuda` for GPU) |
|
||||
| `BGFILTER_MAX_IMAGE_PIXELS` | `4194304` | Reject larger inputs with `413` (~4 MP) |
|
||||
| `BGFILTER_PRELOAD` | `1` | Load default models at startup (first request isn't cold) |
|
||||
| `BGFILTER_CROSS_CHECK` | `0` | Enable the cross-check veto (needs `BiRefNet_HR-matting`; ~2× latency) |
|
||||
| `BGFILTER_CROSS_CHECK` | config (`on`) | Force the cross-check veto on/off (`0` disables; needs `BiRefNet_HR-matting`) |
|
||||
| `BGFILTER_WEIGHTS_DIR` | `models` | Where local weight folders are looked up (Option B) |
|
||||
| `HF_HOME` | — | HF cache location (Option A) |
|
||||
| `HF_HUB_OFFLINE` / `TRANSFORMERS_OFFLINE` | — | Set to `1` in production once weights are cached |
|
||||
|
||||
+10
-11
@@ -147,18 +147,17 @@ hf download ZhengPeng7/BiRefNet_HR-matting --local-dir models/BiRefNet_HR-
|
||||
|
||||
用 `BGFILTER_WEIGHTS_DIR` 可改基目录。`models/` 已被 gitignore。
|
||||
|
||||
### cross-check 否决(可选,服务里默认关闭)
|
||||
### cross-check 否决(默认开启)
|
||||
|
||||
管线可以再跑一个高分辨率 matting 模型(`ZhengPeng7/BiRefNet_HR-matting`,约 425 MB)
|
||||
作为"第二意见",专门清理发丝间残留的背景色。在 **HTTP 服务里默认是关的**、且懒加载,
|
||||
所以不开启就不需要这个模型:
|
||||
管线会再跑一个高分辨率 matting 模型(`ZhengPeng7/BiRefNet_HR-matting`,约 425 MB)
|
||||
作为"第二意见",清理发丝间残留的背景色。**CLI 和 HTTP 服务都默认开启**,而且开了
|
||||
reuse-as-seg 之后,在 birefnet 后端这同一次前向还兼作分割掩码——它是**替换**了 primary
|
||||
分割模型,而不是额外叠加。因此**必须备好这个模型**(上面方案 A 或 B):
|
||||
|
||||
- 服务级开启:`BGFILTER_CROSS_CHECK=1`;或按请求:表单字段 `cross_check=true`。
|
||||
- ⚠️ **离线服务器(`HF_HUB_OFFLINE=1`)必须先备好 `BiRefNet_HR-matting`**(上面方案 A 或 B),
|
||||
否则第一个 cross-check 请求会失败——运行时它无法联网下载模型。
|
||||
- 每张图多一次 2048 分辨率推理(CPU 上约 35s/张),延迟大约翻倍。
|
||||
- 注意:配置默认(`configs/default.yaml`)里 `cross_check.enabled: true`,**CLI 会遵循它**;
|
||||
只有 HTTP 服务强制关闭,除非设了 `BGFILTER_CROSS_CHECK=1`。
|
||||
- ⚠️ **离线服务器(`HF_HUB_OFFLINE=1`)必须在第一个请求前就备好它**,否则每个默认请求都会
|
||||
失败——运行时它无法联网下载模型。
|
||||
- 服务级关闭:`BGFILTER_CROSS_CHECK=0`;或按请求覆盖:表单字段 `cross_check`(`true`/`false`)。
|
||||
- 服务启动时会随暖机集一起预载它;在 birefnet 后端,冗余的 primary 分割模型会被跳过。
|
||||
|
||||
### 墙内下载(国内网络)
|
||||
|
||||
@@ -182,7 +181,7 @@ export HF_HUB_DISABLE_XET=1 # 这些 repo 是 Xet 存储;强
|
||||
| `BGFILTER_DEVICE` | `cpu` | 同时覆盖 model 和 segmentation 的 device(GPU 用 `cuda`)|
|
||||
| `BGFILTER_MAX_IMAGE_PIXELS` | `4194304` | 超过则返回 `413`(约 4 MP)|
|
||||
| `BGFILTER_PRELOAD` | `1` | 启动时预加载默认模型(首个请求不用冷加载)|
|
||||
| `BGFILTER_CROSS_CHECK` | `0` | 启用 cross-check 否决(需 `BiRefNet_HR-matting`;延迟约 ×2)|
|
||||
| `BGFILTER_CROSS_CHECK` | 配置(`on`)| 强制开/关 cross-check 否决(`0` 关闭;需 `BiRefNet_HR-matting`)|
|
||||
| `BGFILTER_WEIGHTS_DIR` | `models` | 本地权重文件夹的查找目录(方案 B)|
|
||||
| `HF_HOME` | — | HF 缓存位置(方案 A)|
|
||||
| `HF_HUB_OFFLINE` / `TRANSFORMERS_OFFLINE` | — | 权重缓存好后,生产设为 `1` |
|
||||
|
||||
@@ -217,13 +217,13 @@ Config comes from `BGFILTER_CONFIG` (defaults to `configs/default.yaml` when pre
|
||||
caps input size (default ~4MP → `413`); `BGFILTER_PRELOAD=1` loads the default models at
|
||||
startup. Run a single worker (`--workers 1`) — each worker loads its own copy of the models.
|
||||
|
||||
Unlike the CLI, the service defaults the **cross-model veto to off** — it adds one
|
||||
extra large-model inference (~35 s/image on CPU, 14 s → 49 s total). Enable it
|
||||
per request with the `cross_check` form field, or flip the service default with
|
||||
`BGFILTER_CROSS_CHECK=1` (worth it on GPU or when hair-gap residue matters more
|
||||
than latency); `/healthz` reports the default as `crossCheck`. The cross-check
|
||||
model is lazy-loaded: it is never preloaded at startup, so the first request that
|
||||
enables it also pays the one-time model load (~1 GB) on top of the inference.
|
||||
Like the CLI, the service runs the **cross-model veto by default** (config
|
||||
default: on). With reuse-as-seg it replaces the primary seg forward rather than
|
||||
adding to it, so it is not the latency hit it once was; its HR-matting model is
|
||||
preloaded with the rest of the warm set (and, on the birefnet backend, the now-
|
||||
redundant primary segmenter is skipped at startup). Set `BGFILTER_CROSS_CHECK=0`
|
||||
to turn it off service-wide, or use the per-request `cross_check` form field to
|
||||
override either way; `/healthz` reports the default as `crossCheck`.
|
||||
|
||||
## Quality Check
|
||||
|
||||
|
||||
@@ -62,12 +62,14 @@ def _build_settings():
|
||||
if device:
|
||||
# Covers both settings.model.device and settings.segmentation.device.
|
||||
settings = override_settings(settings, device=device)
|
||||
# The cross-model veto adds one extra large-model inference (~35 s/image on
|
||||
# CPU), so the service defaults it OFF regardless of the config default;
|
||||
# opt back in with BGFILTER_CROSS_CHECK=1. Other cross_check params (model,
|
||||
# thresholds) still come from the config.
|
||||
cross_check = os.environ.get("BGFILTER_CROSS_CHECK", "0").strip().lower() in ("1", "true", "yes", "on")
|
||||
settings = override_settings(settings, cross_check=cross_check)
|
||||
# The cross-model veto is default behaviour (config default: on). With
|
||||
# reuse-as-seg it replaces the primary seg forward rather than adding to it,
|
||||
# so the earlier CPU-cost concern no longer applies. BGFILTER_CROSS_CHECK
|
||||
# can still force it either way; unset = honour the config.
|
||||
cc_env = os.environ.get("BGFILTER_CROSS_CHECK")
|
||||
if cc_env is not None and cc_env.strip() != "":
|
||||
cross_check = cc_env.strip().lower() in ("1", "true", "yes", "on")
|
||||
settings = override_settings(settings, cross_check=cross_check)
|
||||
return settings
|
||||
|
||||
|
||||
|
||||
+13
-3
@@ -38,10 +38,20 @@ class PipelineManager:
|
||||
if preload:
|
||||
if base_settings.model.matting_method == "vitmatte":
|
||||
self._get_runner()
|
||||
if base_settings.segmentation.enabled:
|
||||
# Cross-check is default behaviour, so its HR-matting model is part of
|
||||
# the warm set. With reuse-as-seg on the birefnet backend that same
|
||||
# forward also serves as the seg mask, so the primary segmenter is
|
||||
# never used on the default path -- only preload it when reuse won't
|
||||
# cover segmentation (reuse off, or a non-birefnet default backend).
|
||||
if base_settings.cross_check.enabled:
|
||||
self._get_cross_checker()
|
||||
reuse_covers_seg = (
|
||||
base_settings.cross_check.enabled
|
||||
and base_settings.cross_check.reuse_as_seg
|
||||
and base_settings.segmentation.backend == "birefnet"
|
||||
)
|
||||
if base_settings.segmentation.enabled and not reuse_covers_seg:
|
||||
self._get_segmenter(base_settings.segmentation.backend)
|
||||
# The cross-check model is deliberately NOT preloaded: it is opt-in
|
||||
# per request, so the first request that enables it pays the load.
|
||||
|
||||
@property
|
||||
def default_seg_model(self) -> str:
|
||||
|
||||
Reference in New Issue
Block a user