Files
BGfilter/README_ZH.md
T
lhk229 c56e58affe 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>
2026-07-14 14:04:58 +08:00

13 KiB

BgFilter

English: README.md

面向"纯色背景 AI 生成图"的离线人物抠图。背景色会从图像边框自动探测(绿色、 淡彩、任意纯色);也可用 --screen-color 显式指定。

RGB 输入
  -> chroma 背景置信度(按自动探测或指定的颜色打分)
  -> [可选] 语义分割 mask
  -> trimap -> ViTMatte -> alpha 清理
  -> 交叉模型否决(对背景色调残留做第二意见)
  -> pymatting 前景估计 -> despill 去溢色 -> RGBA PNG -> QA 预览

管线

两条管线,由配置里的 segmentation.enabled 选择:

  • 仅 Chroma(enabled: false)—— Chroma + ViTMatte,无分割模型。最轻/最快; 完全靠颜色键决定拓扑。
  • 单分割器(enabled: true,默认)—— 一个分割模型定 trimap 拓扑(镂空、发丝), ViTMatte 再细化软边。后端可切换:birefnet(默认,通用显著目标——文字、logo、 照片;需 trust_remote_code)或 anime-seg(ONNX,专为动漫角色调优)。运行时用 --seg-backend anime-seg 切换(会同时选好对应权重)。

两条管线都共用 pymatting 前景估计和一次颜色 de-spill。没有染绿修复 / recolour 层——源图干净时它没必要,已移除。

两条管线默认都跑交叉模型否决:第二个、无需 trimap 的抠图模型 (ZhengPeng7/BiRefNet_HR-matting)只能降低 alpha,且只作用于主结果自信、 但偏背景色调的亮像素——用来清掉卡在发丝间、被 chroma、分割器和 ViTMatte 都误判为 前景的偏色背景残留。代价是多下一个模型(~0.9 GB)+ 每图一次额外推理;用 --no-cross-check 关闭(见 cross_check 配置段,分析见 docs/hair_gap_artifacts.md)。

开启交叉否决时,那趟 HR-matting 前向可以选择性地兼作分割 mask (--cross-check-as-seg),从而完全跳过主分割模型(少加载一个模型,CPU 上每图约快 20 s,GPU 上省约 1 GB 显存)。已试点验证(TestImage3 / FixImage1):trimap 99.8% 一致, 手指、发丝、细线无结构性变化。默认关闭:专用分割器保留自己的前向,否决作为独立 的第二信号。该复用是同族替换,故仅对 birefnet 后端生效:用 --seg-backend anime-seg 时动漫分割器始终保留自己的前向。

分割 trimap 默认走 directional 模式(chroma + seg + 色调方向切分:保留白衬衫这类 背景色系的衣物,同时丢弃卡在发丝间的偏背景色残留如蓝色)。可切换 --trimap-mode seg(仅拓扑,无色调切分)或 directional-hard-bg(激进——硬删偏背景 色像素;可能吃掉冷色/阴影下的白布)。

背景色

默认(screen_color: null)背景色从图像边框自动探测:边框条带的主导纯色成为键色。 若边框不是单一干净纯色——渐变、纹理、或主体占满画面——探测会报错;此时请显式传 --screen-color。

要自己指定,给一个十六进制先验:

... --screen-color "#CFEFFF"

或在配置里写 screen_color: "#CFEFFF"。无论哪种,chroma 键都按到该颜色的感知 (Lab/RGB)距离给像素打分,de-spill 沿该颜色方向压掉色度。(显式给的 hex 会用附近边框 像素做微调;自动探测的颜色直接使用。)

环境

使用 conda 环境 lightML。

conda activate lightML
pip install -r requirements.txt

若未激活 shell,直接调用该环境的 Python:

D:\MiniConda\envs\lightML\python.exe -m bgfilter.cli --help

单张图

D:\MiniConda\envs\lightML\python.exe -m bgfilter.cli `
  --input Samples\TestImage.png `
  --output Outputs\TestImage_rgba.png `
  --debug-dir Outputs\TestImage_debug

无需 --config——内置默认值与 configs/default.yaml 完全一致。只有当你编辑了该文件 去调细节参数时,才需要 --config configs\default.yaml。运行时选择留在命令行: --device(默认 CPU;GPU 用 --device cuda)、--precision(默认 fp32;bf16 给三个模型加速、并把抠图模型的激活显存减半,alpha 视觉上一致——需 bf16 硬件,否则回落 fp32;大输入还会默认对 ViTMatte 全局注意力按 query 分块——精确、逐比特相同,把 2048x2048 的内存尖峰从 ~19 GB 压到 ~4 GB,见 model.attn_query_chunk)、--seg-backend (默认 birefnet;动漫角色用 anime-seg)、--screen-color(默认:自动探测纯背景)、 以及 --trimap-mode。

批量

D:\MiniConda\envs\lightML\python.exe -m bgfilter.cli `
  --input-dir Samples `
  --output-dir Outputs `
  --debug-dir Outputs\debug

性能(CPU 参考数据)

在 Ryzen 9700X(Zen 5,原生 bf16)、32 GB 内存上实测,cross-check 开启、 --cross-check-as-seg 开启、分块全局注意力开启。(本分支默认关闭复用;不开的话要 加上主 BiRefNet@1024 前向——在这些尺寸下每图约 +20 s。)

输入 精度 warm / 每图 峰值内存
1024x1536 fp32 ~45 s —
1024x1536 bf16 ~33 s —
2048x2048 bf16 ~53 s 11.4 GB(批处理)、8.1 GB(单图)

内存上限来自 cross-check 的 BiRefNet_HR 前向(无论图多大都固定 input_size 2048)—— 一个全分辨率密集预测网络的真实活跃激活。在分块注意力和 mimalloc 修复之前,同一个 2048x2048 bf16 run 峰值 25.2 GB;完全未优化的 fp32 run 估计要 55-60 GB(单是 ViTMatte 未分块的 N^2 注意力就 ~39 GB)。无原生 bf16 的 CPU(如 Zen 2)会自动回落 fp32——这类 机器上若内存或延迟紧张,优先 --no-cross-check。

Chroma-alpha 调试模式

--matting-method chroma 跳过 ViTMatte,直接用 chroma 置信度作为 alpha 种子。适合快速 检查 chroma 置信度、trimap 和 despill。(不同于上面的仅 Chroma 管线,后者仍跑 ViTMatte。)

D:\MiniConda\envs\lightML\python.exe -m bgfilter.cli `
  --input-dir Samples `
  --output-dir Outputs\chroma `
  --debug-dir Outputs\chroma_debug `
  --matting-method chroma `
  --device cpu

输出

每处理一张图,CLI 写一张 RGBA PNG 和可选的调试文件:

bg_confidence.png
trimap.png
seg_mask.png          # 仅分割管线
alpha.png
foreground_rgb.png    # 去溢色后的前景颜色
color_mask.png        # 逐像素 despill 权重
preview_black.png
preview_white.png
preview_gray.png
preview_red.png
preview_blue.png
qa_grid.png
metadata.json

HTTP 服务

一个 HTTP 封装(app.py + bgfilter/service.py)把管线暴露为常驻 FastAPI 服务。模型 只加载一次、跨请求复用。部署到 Linux 服务器(依赖、权重、systemd、离线模式、鉴权)见 DEPLOY_ZH.md。

python -m uvicorn app:app --host 127.0.0.1 --port 18083 --workers 1

单 worker 运行(--workers 1)—— 每个 worker 各自加载一份模型。

端点

  • GET /healthz —— 存活 + 配置 JSON,例如 {"ok":true,"service":"bgfilter","version":"0.1.0","defaultSegModel":"birefnet","device":"cpu","crossCheck":true}。 始终免鉴权。
  • POST /remove-background —— 入参 multipart/form-data,返回 image/png(RGBA)。

鉴权

可选、按需开启,由环境变量 BGFILTER_AUTH_TOKEN 控制。设置后,/remove-background 要求 header X-Genarrative-Image-Token: <token>(常量时间比较);缺失或错误返回 401。不设时端点开放(预期由前置代理鉴权)。/healthz 始终开放。见 DEPLOY_ZH.md §10。

请求字段(POST /remove-background,multipart/form-data)

字段 必填 取值 含义
file 是 图片文件 源图(字段名固定为 file)。
background_mode 否 flat(默认)/ complex flat = 纯色背景(走色键管线)。complex = 非纯色/实景背景:无色键,完全由分割器驱动抠图;此模式下 screen_color 被忽略,发丝细节通常弱于纯色模式。
screen_color 否 #RRGGBB,或留空/auto 背景色先验;留空则从边框自动探测。background_mode=complex 时忽略。
seg_model 否 birefnet(默认)/ anime-seg 分割后端。
cross_check 否 1/0(也接受 true/false/yes/no/on/off) 按请求覆盖交叉否决;留空在 flat 模式 = 服务端默认,但在 complex 模式默认关闭(传 on 启用其无色相门控)。

响应头(200 时)

头 示例 含义
X-BGFilter-Elapsed-Ms 2372 服务端处理耗时(ms)。
X-BGFilter-Seg-Model birefnet 实际使用的分割器。
X-BGFilter-Screen-Color #CFEFFF / auto 实际使用的背景色。
X-BGFilter-Cross-Check on / off 本次实际的 cross-check 状态。
X-BGFilter-Background-Mode flat / complex 本次实际的背景模式。

状态码

码 何时
200 成功——响应体是 RGBA PNG。
400 输入有误:图片无法解码,screen_color/seg_model/cross_check/background_mode 非法,或自动探测失败(请传 screen_color)。
401 鉴权已开且 token 缺失或错误。
413 图片超过 BGFILTER_MAX_IMAGE_PIXELS(默认约 4 MP)。
500 推理失败。
503 服务仍在加载模型(未就绪)。

示例

# 默认(birefnet + 自动背景色);若服务要求鉴权则加上 auth header
curl -sS -F "file=@input.png" \
  -H "X-Genarrative-Image-Token: <token>" \
  http://127.0.0.1:18083/remove-background -o output.png

# 显式背景色 + 动漫分割器,本次关闭 cross-check
curl -sS \
  -F "file=@input.png" \
  -F "screen_color=#CFEFFF" \
  -F "seg_model=anime-seg" \
  -F "cross_check=off" \
  http://127.0.0.1:18083/remove-background -o output.png

# 非纯色/实景背景(无色键);此模式 cross-check 默认关闭,
# 需要时加 cross_check=on 启用无色相残留否决
curl -sS \
  -F "file=@scene.jpg" \
  -F "background_mode=complex" \
  http://127.0.0.1:18083/remove-background -o output.png

配置来自 BGFILTER_CONFIG(存在时默认 configs/default.yaml);BGFILTER_DEVICE 同时 覆盖 model 和 segmentation 的 device;BGFILTER_MAX_IMAGE_PIXELS 限制输入尺寸 (默认约 4MP → 413);BGFILTER_PRELOAD=1 启动时预加载默认模型;BGFILTER_AUTH_TOKEN 控制端点鉴权(见上方"鉴权")。

与 CLI 一样,服务默认开启交叉模型否决(配置默认:on);其 HR-matting 模型随暖机集 一起预加载。用 BGFILTER_CROSS_CHECK=0 全服务关闭,或用按请求的 cross_check 表单 字段任意覆盖;/healthz 以 crossCheck 报告默认值。若配置里 cross_check.reuse_as_seg: true(默认关闭),HR-matting 前向会替代主分割前向而非叠加,那个冗余的主分割器会在启动 时跳过。

质量检查

质量检查器在半透明边缘像素上度量 alpha 有效性和边缘溢色。

D:\MiniConda\envs\lightML\python.exe -m bgfilter.quality_cli `
  Outputs\TestImage_rgba.png `
  --max-edge-green-excess-p95 0.30

跑内置样本冒烟检查:

D:\MiniConda\envs\lightML\python.exe scripts\smoke_samples.py `
  --samples-dir Samples `
  --output-dir Outputs\smoke_samples `
  --config configs\default.yaml `
  --device cpu `
  --fallback-to-chroma-alpha `
  --max-edge-green-excess-p95 0.30

备注

  • Samples/ 和 Outputs/ 被 Git 忽略。
  • ViTMatte 和分割权重在首次使用时从 Hugging Face 加载。anime-seg (skytnt/anime-seg)是普通 ONNX 下载;birefnet(ZhengPeng7/BiRefNet)自带 自定义建模代码,故需 trust_remote_code=True 外加 timm / einops / kornia。
  • 防火墙后下载权重——可靠组合是 hf-mirror.com 镜像 + 绕过本地代理 + 禁用 Xet:
    $env:HF_ENDPOINT      = "https://hf-mirror.com"  # 国内镜像
    $env:NO_PROXY         = "*"                       # 绕过代理;镜像是直连
    $env:HF_HUB_DISABLE_XET = "1"                     # 这些仓库是 Xet 后端;强制走经典 HTTP
    
    规避两个坑:(1) 镜像 + 海外代理会让镜像的 resolve 弹回 huggingface.co,新版 huggingface_hub 会以 FileMetadataError 拒绝;(2) 装了 hf-xet 时 Xet 下载路径会 立即失败。权重缓存好后,用 HF_HUB_OFFLINE=1 TRANSFORMERS_OFFLINE=1 离线运行 (生产环境即如此)。
  • 把权重打包进项目——不走 HF 缓存,而是把每个模型放进 models/ 下、以仓库 basename 命名的纯文件夹:models/vitmatte-base-composition-1k、models/BiRefNet、 models/anime-seg、models/BiRefNet_HR-matting(交叉否决第二意见,默认开启)。加载器 优先匹配本地文件夹,缺失时回落到 HF 仓库 id / 缓存,故为可选。用例如 hf download ZhengPeng7/BiRefNet --local-dir models/BiRefNet 填充。用 BGFILTER_WEIGHTS_DIR 改基目录。models/ 已被 gitignore。
  • 前景颜色估计用 pymatting 的 estimate_foreground_ml,在 de-spill 前把干净前景色 传播进半透明边缘。设 foreground.method: unmix 回落到旧的启发式方法。
  • docs/green_screen_matting_workflow.md 是最初的第一阶段绿幕规格;本 README 反映当前 的、泛化后的架构。