Files
2026-10-08 09:46:47 +08:00

214 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# BiRefNet WebUI
**自包含**的网页版智能抠图工具:模型代码、权重、Python 运行时全部在项目目录内,
不依赖 ComfyUI,整个文件夹拷到别的机器(有 NVIDIA 显卡)也能直接跑。
浏览器里拖图 → 一键抠图 → 对比 → 下载;也可以直接填两个目录,整目录批量抠图。
- **零 Web 框架依赖**:标准库 `http.server` 实现,不装 Gradio / FastAPI / Flask
- **自带运行时**:`python/` 内置 Python 3.12 + torch(CUDA),无需配置环境
- **GPU 串行队列**:同一时刻只跑一个模型,8G 显存也能稳定使用
- **目录批量**:给一个图片目录 + 一个输出目录,结果按 `RMBG_原名_时间戳.后缀` 落盘
- 数值行为与 ComfyUI 节点 `comfyui_birefnet_ll` 对齐:同款预处理、`fast-foreground-estimation` 前景精修
## 快速开始
```
方式一:双击 run.bat
方式二:python\python.exe Webui.py
```
启动后自动打开 `http://127.0.0.1:7861/`。
> 把整个项目文件夹移动或拷贝到其它路径/机器后仍可直接运行;
> 若目标机器没有 NVIDIA 显卡,会自动退回 CPU(较慢)。
## 目录结构
```
BiRefNet_WebUI/
├─ Webui.py 启动入口
├─ run.bat 双击启动(优先用自带 python\ 运行时)
├─ selftest.py 端到端自检(python\python.exe selftest.py)
├─ selftest_batch.py 批量抠图自检(纯逻辑 + 假引擎流水线 + HTTP 契约,秒级)
├─ python/ ★ 自带 Python 3.12 运行时(torch 2.13 + CUDA)
├─ models/ ★ BiRefNet 权重(birefnet / Portrait)
├─ vendor/comfyui_birefnet_ll/ ★ 模型代码(来自 ComfyUI 节点,含 LICENSE)
├─ birefnet_web/ 服务端
│ ├─ compat.py 模型代码定位与 folder_paths 垫片
│ ├─ fsutil.py 图片后缀集合、文件名清洗(不依赖 torch)
│ ├─ imageops.py 预处理 / 后处理
│ ├─ batch.py 批量:路径校验、目录扫描、输出命名
│ ├─ engine.py 模型扫描、加载缓存与推理
│ └─ server.py HTTP 服务、REST API、任务队列
├─ web/ 前端(原生 HTML/CSS/JS,无构建步骤)
│ ├─ zip.js 纯 JS 的 ZIP 打包器(跨任务打包结果用)
│ └─ test_app.js 前端回归测试(node web/test_app.js,无需浏览器)
├─ outputs/ 结果输出(按任务分目录)
└─ config.json 首次启动自动生成
```
★ = 随项目分发的核心资源。
## 使用
1. **左侧「图片」**:拖入 / 点击选择 / `Ctrl+V` 粘贴。**一次只放一张**:新图会替换上一张,
重复拖入同一张会被去重提示;一次拖入多张时只保留最后一张
2. **「模型」**:选择权重(默认扫描项目 `models/`,也可加别的目录)
3. **「参数」**:按需调整(都有与节点一致的默认值)
4. 点击 **开始抠图**,右侧实时显示进度;**新任务的结果追加到列表末尾,
已有记录不会被清空**(换参数、传新图、重新处理都不影响)
5. 结果卡片上**左右拖动**分割线对比原图与结果,支持 抠图/遮罩/原图 三种视图、单图下载、ZIP 打包
6. **结果列表交互**:
- 每条记录的文件名下方有一行**参数摘要**(该次处理使用的模型/尺寸/背景等,
完整参数在悬停提示里),跨任务累积成历史
- **点击文件名或「重新处理」** → 把该记录的原图放回待处理槽,**并把它当时使用的
参数重新赋值到左侧面板**,可直接重跑(同一记录重复点击会去重)
- **参数记忆**:每张图最近一次使用的参数按文件名自动保存(localStorage),
之后再把同名图片拖进来时自动套用;同一张图多次处理时总是记录最新的参数
- **点击卡片本体** → 选中该记录(主题色描边),再点一次取消,`Esc` 也可取消
- **点卡片右上角 ×** → 从结果列表移除该条记录(仅移除列表项,`outputs/` 下的文件保留)
- **打包下载 ZIP** 覆盖列表里的全部记录(可能来自多个任务,同名自动加序号)
- 刷新页面后,服务端还在内存里的任务历史会自动恢复显示(含参数)
> 需要按目录整批处理时,用左侧面板 **4 · 批量处理**,详见下一节。
## 批量处理(整目录抠图)
不想一张张拖图时,用左侧面板 **4 · 批量处理**:
1. **图片目录(模板路径)**:待处理图片所在目录,例 `F:\photos\待抠图`
2. **输出目录**:结果写到哪;**留空=项目 `outputs/` 目录**(输入框默认已填好绝对路径)
3. 勾选 **包含子目录** 则递归扫描子目录
4. 点 **开始批量抠图** → 结果区顶部出现逐文件清单:`源文件名 → 输出文件名 → 状态 / 耗时`
抠图参数(模型、尺寸、背景、精修…)**沿用左侧「模型 / 参数」面板当前设置**,与单图模式完全一致。
### 目录与落盘规则
| 行为 | 说明 |
| --- | --- |
| 路径必须已存在 | 输入目录、输出目录都必须真实存在;**本工具不会创建任何目录**,路径不对直接在界面上报错 |
| 默认输出目录 | 项目内 `outputs/`(前端按服务端返回的绝对路径预填) |
| 命名规则 | `RMBG_<原文件名主干>_<Unix 时间戳>.<后缀>`;主干超过 **20 字符**按字符截断(中文同样按字符算) |
| 后缀 | 默认沿用原后缀;但透明输出需要 alpha 通道,遇到 `jpg/jpeg/bmp` 会退化成 `.png`(否则会被压成白底) |
| 遮罩文件 | 默认**不产出**;勾选「同时输出遮罩」后才额外写一份 `<主结果同名>_mask.png`(灰度,白=前景) |
| 重名不覆盖 | 同一秒内的同名结果自动加 `_1`、`_2` … 递增避让 |
| 扫描范围 | 只认图片后缀;**跳过 `RMBG_` 开头的文件**(避免把上次产物又抠一遍);输出目录在输入目录内时会被排除 |
| 输入 = 输出 | 允许:结果与源图同目录,靠 `RMBG_` 前缀区分 |
| 原图 | 批量模式**不拷贝、不修改**源图,就地读取 |
| 结果展示 | 批量结果不铺成单图卡片(几百张会拖慢页面),只在结果区顶部列清单;文件本体已在输出目录,无需再下载 |
> 批量任务与单图任务共用同一个串行队列(同一时刻只跑一张),不会抢显存;关掉页面不影响服务端继续跑完。
## 参数说明
「模型 / 设备」与「参数」两个面板中每一项的含义(均有与 ComfyUI 节点一致的默认值,改了会记入参数摘要):
### 设备与精度
| 参数 | 说明 | 默认 |
| -- | ------------------------------------------------------------------------ | ---- |
| 设备 | 自动(GPU)/ CPU | auto |
| 精度 | auto = fp32 权重 + fp16 autocast(官方推荐做法);float16 最省显存;出现 NaN 会自动回退 fp32 重算 | auto |
| 架构 | v1(新版 safetensors)/ old(旧版 .pth)/ 自动识别 | auto |
### 预处理尺寸(送入模型前的缩放方式)
BiRefNet 推理前会把原图缩放到固定输入尺寸,这一项决定怎么缩:
| 模式 | 说明 |
| -------------------- | ------------------------------------ |
| 固定 1024×1024(square) | 官方推荐做法:不论原图比例,直接拉伸到 1024×1024,精度最稳定 |
| 长边自适应(longest) | 保持宽高比,把长边缩放到指定值(边长对齐 32 的倍数),另一边按比例算 |
| 自定义宽高(custom) | 手动指定「宽 / 高」两个输入框(默认各 1024),不保持原图比例 |
> 输入尺寸越小推理越快、越省显存(如 512);越大细节越丰富但更慢。
### 其余参数
| 参数 | 说明 | 默认 |
| ------- | ------------------------------------------------------------------------------------- | -------- |
| 插值方式 | 预处理缩图与遮罩还原回原尺寸时使用的插值算法(bilinear / nearest / bicubic 等) | bilinear |
| 遮罩阈值 | 大于 0 时,把低于该阈值的 alpha 概率直接置零(不做二值化,只清零弱值),可清理弱边缘杂讯;0 = 不处理 | 0 |
| 背景 | 抠图结果的合成方式:**透明(PNG Alpha)** 输出带 alpha 通道的 PNG;**纯色** 则把前景合成到指定颜色上(含绿幕、色板快选) | 透明 |
| 前景精修 | fast-foreground-estimation:按遮罩估计前景色,去除半透明边缘残留的原背景色(白底抠图边缘发白就是它治的)。超大图(超过像素上限)会自动跳过并提示 | 开 |
| — 大核 r1 | 精修第一轮 box blur 的核尺寸,用于估计整体前景色 | 90 |
| — 小核 r2 | 精修第二轮 box blur 的核尺寸,用于收细边缘 | 6 |
| 同时输出遮罩 | 额外输出一张 8bit 灰度 PNG(黑白遮罩,白色 = 前景),可用于后期合成。**默认关闭**,需要时才勾 | 关 |
| 最终尺寸 · 最长边 | 按原图比例等比缩放结果,使**最长边等于**该值;0 = 保持原图尺寸。例:2000×3000 填 1440 → 960×1440;3000×2000 填 1440 → 1440×960 | 0 |
> 「最终尺寸 · 最长边」精确定义:设原图(抠图结果原尺寸)为 `W×H`,填充值为 `L`
>
> - `L = 0`:不缩放,原样输出(默认)
> - `L > 0`:`k = L / max(W, H)`,输出 `round(W·k) × round(H·k)`,最长边恰好等于 `L`;短边按比例取整,可能与理论值差 1 像素
> - 原图最长边**小于** `L` 时会**放大**(这点与旧的「输出长边上限」不同,旧参数只缩不放,已被本参数取代)
> - 缩放同时作用于抠图结果与(勾选时的)遮罩文件,两者始终保持同尺寸
## 命令行参数
```
python\python.exe Webui.py [--host 0.0.0.0] [--port 7861] [--device auto|cpu|cuda]
[--dtype auto|float32|float16|bfloat16]
[--model-dir 路径]... 追加模型目录
[--node-dir 路径] 指定模型代码目录(默认用项目内 vendor/)
[--output-dir 路径] 结果输出目录(默认 ./outputs)
[--max-cached-models N] 显存中驻留的模型数(默认 1)
[--no-browser] [--save-config] [--check]
```
`--check` 只做环境自检(依赖、GPU、模型扫描)后退出,适合排障。
## 模型代码与权重
模型代码内联在 `vendor/comfyui_birefnet_ll/`(来源:ComfyUI 节点 comfyui_birefnet_ll,
遵循其 LICENSE)。`birefnet_web/compat.py` 会在 import 阶段注入一个最小 `folder_paths`
垫片(模型包只在「加载骨干预训练权重」时用到它,本工具始终以 `bb_pretrained=False`
构建,因此垫片返回 None 即可),从而脱离 ComfyUI 独立运行。
权重文件(放入 `models/` 即可,扫描时自动识别):
- 新版 `*.safetensors`:[ZhengPeng7 的 HuggingFace 仓库](https://huggingface.co/ZhengPeng7),如 `General.safetensors`、`Portrait.safetensors`
- 旧版 `BiRefNet-DIS_ep580.pth` / `BiRefNet-ep480.pth`
- 骨干权重(`swin_*` / `pvt_*`)会被自动忽略,不会被当成抠图模型
也可用 `--model-dir` 或 `config.json` 的 `model_dirs` 追加其它目录
(例如继续共用 ComfyUI 的 `models/BiRefNet`,两处权重会合并去重显示)。
## HTTP API
| 方法 | 路径 | 说明 |
| ---- | ----------------------------------------- | ----------------------------------------------- |
| GET | `/api/state` | 环境、模型列表、默认参数 |
| GET | `/api/models` · POST `/api/models/reload` | 模型列表 / 重新扫描 |
| POST | `/api/tasks` | multipart 提交:`files`(可多份)+ `options`(JSON,字段同上) |
| POST | `/api/batch` | JSON 提交目录批量:`input_dir` / `output_dir`(可空=项目 outputs)/ `recursive` / `options`;两个目录都必须已存在 |
| GET | `/api/tasks` | 任务历史列表(含各自参数与 `mode`,前端据此恢复结果历史) |
| GET | `/api/tasks/<id>` | 任务状态与进度(前端 400ms 轮询);`?tail=N` 只回传最后 N 张,批量任务靠它压载荷 |
| POST | `/api/tasks/<id>/cancel` | 取消(阶段粒度) |
| GET | `/api/tasks/<id>/file/<index>/<kind>` | 取结果,kind = cutout / mask / original |
| GET | `/api/tasks/<id>/zip?kind=cutout` | 打包下载 |
| POST | `/api/engine/unload` | 释放显存 |
| POST | `/api/shutdown` | 关闭服务 |
## 常见问题
- **双击 run.bat 一闪而过**:确认 `run.bat` 是 CRLF 换行(纯 LF 的批处理会被 cmd 静默终止)
- **显存不足(OOM)**:精度选 `float16`,或预处理尺寸改小(如 512);默认同时只驻留 1 个模型
- **没有可用模型**:确认 `*.safetensors` 在 `models/` 下,或用 `--model-dir` 指定
- **结果边缘有原背景色残留**:确认「前景精修」开启
- **批量时报「输出目录不存在」**:本工具不会自动建目录,请先在资源管理器里把输出目录建好再填
- **批量产物多出 `_mask.png`**:说明勾了「同时输出遮罩」(默认不勾);取消勾选即可只留抠图结果
- **输出尺寸不对**:检查「最终尺寸 · 最长边」——填了非 0 值就会把结果等比缩放到该最长边(小图会被放大),想原样输出请填 0
- **旧版本里设过「输出长边上限」**:该参数已改名为「最终尺寸 · 最长边」,旧值会自动带到新输入框;浏览器里存的老参数还会自动修正一次「同时输出遮罩」的默认值
- **批量结果名被截断**:设计如此——原文件名主干超过 20 字符会截断,避免超长文件名;时间戳用来区分多次处理
- **CPU 很慢**:正常现象,建议 512 分辨率 + float32
- **想换 Python**:设环境变量 `BIREFNET_PYTHON=<解释器路径>`(需已装 `requirements.txt` 依赖);
缺依赖时入口会自动切换到自带的 `python\` 运行时
## 环境要求
自带运行时已就绪,无需安装。若用自己的解释器:Python 3.9+,
`pip install -r requirements.txt`(torch / torchvision / numpy / pillow / safetensors /
timm / einops / kornia / huggingface_hub / tqdm,可选 opencv-python)。