# BgFilter > English: [README.md](README.md) 面向"纯色背景 AI 生成图"的离线人物抠图。背景色会**从图像边框自动探测**(绿色、 淡彩、任意纯色);也可用 `--screen-color` 显式指定。 ```text 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`。 要自己指定,给一个十六进制先验: ```bash ... --screen-color "#CFEFFF" ``` 或在配置里写 `screen_color: "#CFEFFF"`。无论哪种,chroma 键都按到该颜色的感知 (Lab/RGB)距离给像素打分,de-spill 沿该颜色方向压掉色度。(显式给的 hex 会用附近边框 像素做微调;自动探测的颜色直接使用。) ## 环境 任意 Python 3.11–3.13 环境(venv 或 conda)均可: ```bash pip install -r requirements.txt python -m bgfilter.cli --help ``` 服务器安装(CPU wheel 版 torch、离线权重、systemd)请直接按 [DEPLOY_ZH.md](DEPLOY_ZH.md) 走——同样的依赖,但把生产环境的取舍都写明了。 ## 单张图 ```bash python -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`。 ## 批量 ```bash python -m bgfilter.cli \ --input-dir Samples \ --output-dir Outputs \ --debug-dir Outputs/debug ``` ## 性能 量级参考:快速桌面 CPU(bf16、cross-check 开)约 **33–53 s/图**,现代 GPU 约 **1–2 s/图**。全部实测数据——CPU 各 lane、GPU 显存占用、内存上限及相关旋钮—— 见 [DEPLOY_ZH.md](DEPLOY_ZH.md) §11(容量与性能)。 ## Chroma-alpha 调试模式 `--matting-method chroma` 跳过 ViTMatte,直接用 chroma 置信度作为 alpha 种子。适合快速 检查 chroma 置信度、trimap 和 despill。(不同于上面的仅 Chroma *管线*,后者仍跑 ViTMatte。) ```bash python -m bgfilter.cli \ --input-dir Samples \ --output-dir Outputs/chroma \ --debug-dir Outputs/chroma_debug \ --matting-method chroma \ --device cpu ``` ## 输出 每处理一张图,CLI 写一张 RGBA PNG 和可选的调试文件: ```text 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](DEPLOY_ZH.md)。 ```bash 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: `**(常量时间比较);缺失或错误返回 `401`。不设时端点开放(预期由前置代理鉴权)。`/healthz` 始终开放。见 [DEPLOY_ZH.md](DEPLOY_ZH.md) §10。 ### 请求字段(`POST /remove-background`,`multipart/form-data`) | 字段 | 必填 | 取值 | 含义 | | --- | --- | --- | --- | | `file` | `file`/`image_url` 二选一 | 图片文件 | 以上传方式提供源图(字段名固定为 `file`)。 | | `image_url` | `file`/`image_url` 二选一 | `http(s)://…` | 以 URL 提供源图,服务端自行 fetch(受大小/超时限制,跟随 ≤3 跳重定向)。`file` 与 `image_url` 必须恰好提供一个。无 SSRF 过滤:端点信任已鉴权的调用方,请保持鉴权开启且调用方可信。 | | `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` | 本次实际的背景模式。 | | `X-Request-ID` | `42efe4e0d76f4b83` | 关联 id(你若传入 `X-Request-ID` 则回显,否则自动生成)。报障时报这个 id 即可对上服务端日志。每个响应都返回,含错误响应。 | ### 状态码 | 码 | 何时 | | --- | --- | | `200` | 成功——响应体是 RGBA PNG。 | | `400` | 输入有误:图片无法解码,`file`/`image_url` 不是恰好其一,`image_url` 非法/fetch 失败,`screen_color`/`seg_model`/`cross_check`/`background_mode` 非法,或自动探测失败(请传 `screen_color`)。 | | `401` | 鉴权已开且 token 缺失或错误。 | | `413` | 图片超过 `BGFILTER_MAX_IMAGE_PIXELS`(默认约 4 MP),或 `image_url` 响应体超过 `BGFILTER_FETCH_MAX_BYTES`(默认约 25 MB)。 | | `500` | 推理失败。 | | `503` | 服务仍在加载模型(未就绪)。 | ### 示例 ```bash # 默认(birefnet + 自动背景色);若服务要求鉴权则加上 auth header curl -sS -F "file=@input.png" \ -H "X-Genarrative-Image-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 # 用 URL 代替上传(服务端自行 fetch;image_url 与 file 二选一,不可同时给) curl -sS \ -F "image_url=https://example.com/input.png" \ -F "screen_color=#CFEFFF" \ -H "X-Genarrative-Image-Token: " \ http://127.0.0.1:18083/remove-background -o output.png ``` 运行时配置(配置文件、device、尺寸上限、预加载、鉴权 token、流水线 worker 数)全部 通过 `BGFILTER_*` 环境变量——完整表格见 [DEPLOY_ZH.md](DEPLOY_ZH.md) §6。 与 CLI 一样,服务**默认开启交叉模型否决**;`/healthz` 以 `crossCheck` 报告生效的默认值, 按请求的 `cross_check` 表单字段可任意覆盖(全服务关闭用 `BGFILTER_CROSS_CHECK=0`)。 `cross_check.reuse_as_seg`(仅配置文件可设,默认关——见上方"管线")没有请求级开关; 改它意味着改配置并重启服务。 ## 质量检查 质量检查器在半透明边缘像素上度量 alpha 有效性和边缘溢色。 ```bash python -m bgfilter.quality_cli \ Outputs/TestImage_rgba.png \ --max-edge-green-excess-p95 0.30 ``` 跑内置样本冒烟检查: ```bash python 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 缓存、`models/` 纯文件夹(`BGFILTER_WEIGHTS_DIR`)、一键下载 脚本 `scripts/fetch_weights.py`、以及国内网络的镜像 workaround——见 [DEPLOY_ZH.md](DEPLOY_ZH.md) §5。 - 前景颜色估计用 pymatting 的 `estimate_foreground_ml`,在 de-spill 前把干净前景色 传播进半透明边缘。设 `foreground.method: unmix` 回落到旧的启发式方法。 - `docs/green_screen_matting_workflow.md` 是最初的第一阶段绿幕规格;本 README 反映当前 的、泛化后的架构。