feat: Introduce Balloon Lasso Tool for mesh extraction
- Added BalloonTool workspace tool to facilitate the extraction of balloon meshes in the 3D viewport. - Implemented ActivateBalloonTool operator to activate the Balloon Lasso Tool. - Refactored BalloonLasso operator into ExtractBalloon for better clarity and functionality. - Enhanced properties for balloon extraction, including mode, thickness, resolution, and material reuse options. - Updated SnapFormSettings to include new balloon-related properties. - Improved material and image handling for balloon extraction, ensuring compatibility and reusability. - Added tests to validate the registration and functionality of the new balloon tools and properties.
This commit is contained in:
151
docs/server.md
151
docs/server.md
@@ -1,129 +1,84 @@
|
||||
# Job Server
|
||||
|
||||
本页记录 Environment、模型缓存和 Job Runtime 的内部设计。安装或使用遇到问题时,请先查看
|
||||
[安装与首次配置](installation.md)和[常见问题](faq.md)。
|
||||
SnapForm 把 AI 与媒体处理放在独立 Job Server 中运行,使 Blender Python 保持轻量。安装和使用问题见[安装与首次配置](installation.md)与[常见问题](faq.md)。
|
||||
|
||||
## 运行架构
|
||||
## 架构
|
||||
|
||||
SnapForm 在独立的 Python 3.12 Environment 中运行 HTTP Job Server,Blender 只通过标准库 HTTP Client 提交和轮询任务,不把计算依赖载入 Blender Python。Server 只监听 `127.0.0.1`,由外置 BlendJob wheel 提供的 `ServerController` 保存随机端口与 Instance ID;专属本地进程协议不使用额外 Token 鉴权。
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Blender["Blender Operator"] --> Runtime["JobRuntime"]
|
||||
Runtime --> Queue["FIFO Queue"]
|
||||
Queue --> Job["SnapForm Job"]
|
||||
Job --> Media["Media"]
|
||||
Job --> Models["ModelManager"]
|
||||
Job --> Geometry["Geometry"]
|
||||
Job --> Outputs["Outputs"]
|
||||
Outputs --> Directory["Job Directory"]
|
||||
Directory --> Blender
|
||||
```
|
||||
|
||||
每个 Blender 实例启动并持有一个 SnapForm 专属 Server,不发现或复用其它 Blender、其它插件启动的本地 Server。多个 Blender 可以对应多个进程,但模型、Environment 与任务产物仍可共享同一个 Storage Root。
|
||||
每个 Blender 实例拥有自己的 Server 进程,连接绑定到本机随机端口和 Instance ID。多个实例可以共享 Storage Root,但各自维护进程、队列和内存中的模型 Session。
|
||||
|
||||
Environment、模型和任务结果默认保存在 `~/.snapform`:
|
||||
BlendJob 提供 Runtime、HTTP transport、队列、状态和取消协议。SnapForm 的 Operator 负责业务参数,Server Job 负责工作流编排,结果由 Operator 在 Blender 主线程中导入。
|
||||
|
||||
## Storage Root
|
||||
|
||||
默认位置为 `~/.snapform`:
|
||||
|
||||
```text
|
||||
~/.snapform/
|
||||
├── .venv/
|
||||
├── environment.json
|
||||
├── models/
|
||||
├── jobs/
|
||||
├── manifest.json
|
||||
├── install.log
|
||||
├── install-status.json # 仅在安装期间存在
|
||||
└── server.log
|
||||
├── .venv/ Python Environment
|
||||
├── models/ ONNX 模型
|
||||
├── jobs/ 任务产物
|
||||
├── environment.json 环境声明
|
||||
├── manifest.json 已安装环境指纹
|
||||
├── install.log 安装日志
|
||||
└── server.log Server 日志
|
||||
```
|
||||
|
||||
不同 Blender 版本可共享此目录。也可以在 Extension Preferences 的 `Storage Root` 中修改位置。连接端口与 Instance ID 只保存在启动它们的 Blender 进程内存中。
|
||||
更改 Storage Root 相当于切换整套 Environment、模型和任务数据。目录说明见[模型、设备与存储](models-and-storage.md)。
|
||||
|
||||
Blender Client 与独立 Server 的通用 HTTP Runtime 都复用 `src/snapform/wheels/` 中随扩展分发的同一份 BlendJob package;Server Environment 不再从 PyPI 安装第二份。`JobServer` 包装 FastAPI 并提供 Job、FIFO Queue 与 Resource API,`JobClient` 是无第三方依赖的 Blender 侧访问器。Blender 侧只把 `server/__init__.py:server` 入口字符串交给 Runtime,不导入 `server` package;独立进程启动后才取得其中的 `server` 实例、注册全部公开 Job,并创建 `model_manager` Resource。
|
||||
## 模块关系
|
||||
|
||||
SnapForm 根 package 不再有 `client.py`、`environment.py`、`storage.py` 或 `models.py`。这些文件会制造并不存在的业务边界:
|
||||
| 模块 | 职责 |
|
||||
| --- | --- |
|
||||
| `runtime.py` | Environment、Server 生命周期、任务状态与 Storage Root |
|
||||
| `server/jobs/` | 按功能编排完整任务 |
|
||||
| `server/media/` | 图片、视频和序列输入 |
|
||||
| `server/models/` | ONNX Session 与模型 Prediction |
|
||||
| `server/geometry/` | 投影、网格和 Surface 数据转换 |
|
||||
| `server/outputs/` | NPZ、EXR、PNG 与序列文件 |
|
||||
| `model_catalog.py` | Blender UI 的模型声明与本地就绪检查 |
|
||||
| `server/model_catalog.py` | Server 的模型下载与推理声明 |
|
||||
|
||||
- Storage Root、`.venv`、Manifest、安装状态与日志路径由 `JobRuntime` 唯一管理;
|
||||
- `InstallEnvironment` 由 `runtime.operator_classes()` 提供,Python 与 Job 自身的额外 packages 直接声明在传给 Runtime 的 `environment` 字典中;BlendJob 不需要重复声明;
|
||||
- Blender Client 使用根目录 `model_catalog.py` 构造 UI 并检查 Storage Root 下的模型必需文件;
|
||||
- 独立 Server 使用 `server/model_catalog.py` 下载和验证模型,不依赖 Extension 根 package。两份声明的共享存储字段由测试保持一致,已加载 Session 状态仍读取 Server Snapshot。
|
||||
调用方向从 Job 指向媒体、模型、几何和输出模块。模型层返回内存数据,输出层管理文件,Blender 数据始终由 Operator 的 Response 创建。
|
||||
|
||||
BlendJob 的 `JobClient` 只是无依赖 HTTP transport,不是 SnapForm 业务抽象,也不向 Operator 暴露 `JobRequest`。
|
||||
## Environment 与模型
|
||||
|
||||
SnapForm 的业务 Operator 直接提交参数字典,Job Type 一一对应:
|
||||
Environment 使用 Python 3.12、ONNX Runtime、NumPy、Pillow、PyAV、trimesh、FastAPI 和 Uvicorn。Windows 使用 DirectML 或 CPU;其他平台根据支持情况使用 CoreML、OpenVINO 或 CPU。
|
||||
|
||||
- `download_model` → `download-model`
|
||||
- `download_required_models` → `download-required-models`
|
||||
- `remove_background` → `remove-background`
|
||||
- `extract_frames` → `extract-frames`
|
||||
- `generate_depth` → `generate-depth`
|
||||
- `generate_surface` → `generate-surface`
|
||||
- `debug_da3` → `debug-da3`
|
||||
- `debug_moge2` → `debug-moge2`
|
||||
- `debug_ben2` → `debug-ben2`
|
||||
|
||||
DA3 与 MoGe-2 的生产任务不再合并成带 Backend 参数的通用请求。每个 Operator 的 `request(context)` 直接构造自己的有效参数,Debug 任务也与生产任务完全分开。
|
||||
|
||||
Server 端没有 `execute_*`、`*_result` 或 CLI worker 中转。全部 `@server.job(...)` 都集中在
|
||||
`server/__init__.py`,这里只负责注册 Job 与 Resource。完整工作流位于 `jobs/`;模型适配器和
|
||||
ONNX 实现位于 `models/`;纯投影、网格与唯一 Surface Builder 位于 `geometry/`;文件序列化位于
|
||||
`outputs/`;输入准备位于 `media/`。模型下载由 `ModelManager` 单向调用
|
||||
`model_download.py`,不存在循环 import。
|
||||
|
||||
## ONNX-only Environment
|
||||
|
||||
扩展不内置 `uv` 可执行文件或 AI 运行库。`Install Environment` 首先下载固定版本的 uv,校验 SHA-256 后解压到共享 Storage Root,再用它创建环境并安装:
|
||||
|
||||
- ONNX Runtime 1.24.4;Windows 使用 `onnxruntime-directml`
|
||||
- NumPy 2.4.2、Pillow 12.1.1、PyAV 17.0.0、trimesh 4.11.2
|
||||
- FastAPI 0.139.2、Uvicorn 0.51.0、huggingface-hub 1.4.1
|
||||
|
||||
运行环境不安装 PyTorch、TorchVision、xFormers,也不安装 DA3、MoGe、BEN2 或 utils3d 的 Python 源码包。模型推理和 SnapForm 所需的相机、点云、网格后处理均由 ONNX Runtime、NumPy 与内部实现完成。
|
||||
|
||||
Windows 当前发行环境提供 DirectML 与 CPU;`Auto` 优先使用 `DmlExecutionProvider`。显式指定不可用设备时会安全回退到 CPU。其他平台安装标准 ONNX Runtime,并按可用 provider 选择 CoreML、OpenVINO 或 CPU。Blender 侧通过 `sysctl` 识别 Apple Silicon 代际,只有 M4 或更新芯片才提供 MPS 选项;其他 Mac 只提供 CPU。M4 或更新芯片的 CoreML Session 使用 `MLProgram` 模型格式、全部可用计算单元并允许动态输入 Shape。
|
||||
|
||||
`environment.json` 保存规范化后的声明,`manifest.json` 保存该声明与基础 Server packages 的 Hash。Python、packages、平台 packages、基础 Server packages 或 Environment Schema 改变后需要重新执行 `Install Environment`,不再维护手工 Manifest Revision。BlendJob 直接随 Extension 更新,不参与 Environment Hash。
|
||||
|
||||
## 模型
|
||||
|
||||
所有正式功能都使用 ONNX:
|
||||
正式功能支持:
|
||||
|
||||
- MoGe-2 ViT-S、ViT-B、ViT-L Normal
|
||||
- DA3 Small、DA3 Base
|
||||
- BEN2 Base
|
||||
|
||||
首次安装在 `post_install(runtime)` 中自动下载 `MoGe-2 ViT-S Normal` 与 FP16 `BEN2 Base`。它们和 `Models` panel 的后续下载一样,都是 `download-model` Job,与推理共用队列、HTTP 进度和取消协议。模型按声明的目录名保存在 `~/.snapform/models/`,并保留仓库内部结构。声明了文件清单与校验值的模型先走 Hugging Face `resolve` 直链流式下载,失败后尝试 `https://models.omoolab.xyz/<repository-name>/<relative-path>`;两者都失败时当前 Job 直接失败,不记录或猜测后续下载源。模型直链的 TCP、代理 CONNECT 与 TLS 建连最长等待 10 秒;连接后连续 60 秒没有收到响应数据则视为当前来源失败并切换下一来源。该空闲超时不限制模型总下载时长。R2 文件会校验大小与 SHA-256。未声明清单的仓库仍使用 `huggingface_hub` 快照下载。可用 `HF_ENDPOINT` 指定 Hugging Face 镜像。
|
||||
首次安装会下载 MoGe-2 ViT-S Normal 与 BEN2 Base。模型保存在 `models/`,可由多个 Blender 版本共享。Server 缓存 BEN2 和最近使用的一个深度模型,以控制内存占用。
|
||||
|
||||
Image Empty 的右键菜单会读取 `model_manager` 状态;缺少 MoGe-2 ViT-S 或 BEN2 时显示
|
||||
`Download Required Models`。对应的 `download-required-models` Job 在 Server 端再次检查就绪状态,
|
||||
只下载缺失项,并把多个下载的进度合并为单次 0–100%。必需模型补齐前,右键菜单中的
|
||||
`Convert to Depth Plane` 保持禁用。
|
||||
模型下载优先使用 Hugging Face,并以 OmooLab 镜像作为回退。Environment 安装则提供官方源和镜像源两个明确入口;它们只影响 Environment Bootstrap,不改变模型下载策略。
|
||||
|
||||
`model_manager` Resource 在 Server 内持有磁盘就绪状态和内存 Session。Blender UI 使用 Client catalog 声明的目录名与 `ready_patterns` 直接检查 `<storage-root>/models/`,因此展开模型面板、打开转换对话框或 Image Empty 右键菜单都不会仅为状态检测启动 Server。真正下载或推理时,Server 仍按自身 catalog 通过 `ModelManager.ready()` 重新验证文件。`ModelSessionCache` 保留 BEN2,并在 DA3 与 MoGe-2 之间只保留最近使用的一种 Depth Session。`GET /resources/model_manager` 只返回当前加载状态;`POST /resources/model_manager/clear` 只允许在没有 Active 或 Queued Job 时执行。
|
||||
## 任务生命周期
|
||||
|
||||
DA3 ONNX 使用模型的 camera decoder 恢复外参与内参,不提供 ray-pose 参数。MoGe-2 的 metric depth、normal、mask、normalized intrinsics,以及 BEN2 的 Alpha,均在 NumPy 后处理中恢复。
|
||||
Server 在第一次提交 Job 或手动 Start 时启动。任务进入单 Worker FIFO Queue,同一时间执行一个推理、下载或媒体任务。
|
||||
|
||||
Job 被接受时,Runtime 创建 opaque ID 和对应目录。进度保存在 Server 内存中,Blender 定期轮询状态。取消会在下载分块或一次 ONNX 调用结束后的检查点生效。
|
||||
|
||||
## 安装网络与镜像
|
||||
Blender 正常退出或禁用扩展时会停止所属 Server;Server 也监视父进程,在异常退出后自行结束。
|
||||
|
||||
安装器不做带宽测速、来源竞速或失败后的自动切换。`Install Environment` 固定使用 Astral GitHub Release、uv 默认 Python 下载源和 PyPI;`Install Environment (Mirror)` 固定使用 CNB uv Release、CNB `python-build-standalone` 与清华 PyPI。两个 uv 来源使用同一固定版本和 SHA-256;下载压缩包只作临时文件,安装完成后删除。
|
||||
Environment 安装发生在 Server 启动前,使用 `install.log` 记录过程。安装完成后的模型下载是普通 Job,与推理共享队列、进度和取消机制。
|
||||
|
||||
镜像模式只在当前安装子进程中设置 `UV_PYTHON_INSTALL_MIRROR` 与 `UV_INDEX_URL`,不修改用户环境变量。Windows 系统代理会注入子进程;同时支持 `HTTP_PROXY`、`HTTPS_PROXY` 与 `ALL_PROXY`。post-install 模型下载保持 Hugging Face 与 OmooLab R2 的独立来源逻辑,不读取 Environment 安装模式。
|
||||
## DA3 多帧限制
|
||||
|
||||
Environment Bootstrap 的单次 0–100% 只包含 uv、Python 与 packages,不包含后续模型下载。开始显示 `Starting installation ...`;uv 使用 1–20%,显示 `1/3 Starting uv download ...`、`1/3 Downloading uv [速度]` 或镜像形式、`1/3 Installing uv ...`;Python 使用 20–50%,显示 Checking、Downloading、Installing,镜像下载带 `(mirror)`;packages 使用 50–98%,显示 Resolving、`Downloading packages [已开始数]/[解析总数]`、Installing,镜像模式带 `(mirror)`;98–100% 显示 `Verifying installation ...`。三个下载区间分别占对应阶段的 84–87%,缓存命中时直接跳过。单阶段状态不显示 `1/1`。
|
||||
DA3 ONNX 的联合注意力显存随帧数和分辨率快速增长。Depth Plane 动画采用逐帧推理并复用 Session,使峰值显存接近单帧任务;代价是各帧不共享相机位姿与深度尺度。
|
||||
|
||||
首次安装依次显示 Environment、MoGe-2 下载与 BEN2 下载,每项分别使用 0–100%。Environment 由 Job Runtime 依次完成 uv 下载、Python Environment 创建与 packages 安装,uv 不再占用独立一轮进度。两个模型下载由 SnapForm 的 `post_install(runtime)` 通过 `runtime.request()` 顺序发起;切换模型时进度归零,但不显示 `2/2` 等阶段编号。
|
||||
任一 post-install 模型失败时,Environment 文件仍然保留,但安装 Operator 返回失败并显示原始模型错误。
|
||||
|
||||
## 生命周期
|
||||
|
||||
扩展启用后不启动 Server;第一次执行 Job 或点击 `Start` 时才为当前 Blender 启动专属实例。正常关闭或禁用扩展时直接停止自己启动的进程;Server 也监视 Blender 父进程 PID,父进程异常退出后会自行停止。
|
||||
|
||||
AI、帧提取和 Models panel 下载的 Job 进度保存在 Server 内存中。Handler 只使用 `context.progress(value, message)` 发布进度,终态由 JobServer 内部管理;SnapForm 不再维护独立的 `server/progress.py` 或 Job 状态 JSON。Blender 每 0.25 秒轮询 `GET /jobs/{job_id}`,任务目录不写 `status.json`。Operator 直接提交参数字典;Job 被接受时由 `JobServer` 自动生成 ID 并创建 `jobs/<opaque-job-id>/`,提交响应同时返回 `job_id` 与 `directory`。路径通过 `JobContext.directory` 传给 Handler,SnapForm Server 强制将输出写入该目录。
|
||||
|
||||
`runtime.py` 创建唯一的 `runtime = JobRuntime(...)`,以 `src/snapform/` 为 `entrypoint_root`,传入 `server:server` 相对入口字符串与显式 `snapform` namespace,并导出 `runtime.JobOperatorBase`。Runtime 独占 Storage Root、Environment 路径、安装进程、Server 控制和 Status Bar。Operator 未覆盖 `request(context)` 时会提交全部 Property;覆盖后返回值纯替换默认参数。可选的 `response(context, result)` 在 Blender 主线程直接完成结果导入。SnapForm 不再提供 Client 请求层、Job Mixin、Status Bar 或 Build 中转 Operator。
|
||||
|
||||
Environment 安装是 Server 启动前唯一的 Bootstrap 流程:`environment.json` 记录期望安装的环境声明,`install-status.json` 在安装期间回传进度并在任务收尾后删除,`install.log` 持久记录安装输出。Bootstrap 不创建 Job 目录。Environment 成功后执行普通的 `post_install(runtime)`;默认模型下载此时已经是正式 Server Job,会创建自己的 Job 目录,并使用与其它任务相同的进度和取消协议。
|
||||
|
||||
Server 使用标准库单 Worker FIFO Queue,全局同时只执行一个 Job,包括模型下载。Server 忙碌时新 Job 进入 `queued`,不再返回 409;排队任务可以在执行前取消。取消运行中任务不会重启 Server;流式模型下载会在分块检查点结束,ONNX Runtime 当前调用则在返回后的最近检查点结束。JobServer 最多保留 100 个已完成 Job 的内存状态,后续提交时清理更早记录。
|
||||
|
||||
Server 由 Environment 通过 `python -m blendjob.runner` 启动,避免 BlendJob 内部模块名遮蔽 Python 标准库。启动与崩溃信息写入 `~/.snapform/server.log`。
|
||||
|
||||
## 已知限制
|
||||
|
||||
DA3 ONNX 的注意力是朴素实现(`MatMul → Softmax → MatMul`),峰值显存与 `(帧数 × 每帧 patch 数)²` 成正比。迁移到 ONNX 前的 PyTorch 版使用 `scaled_dot_product_attention`(`XFORMERS_DISABLED=1`),按块计算注意力分数、不落地完整注意力矩阵,显存近似线性,因此视频能处理几十上百帧;ONNX 导出把 SDPA 回退成朴素注意力,多帧在中高分辨率下会显存爆炸(约 12 帧 @ 1008 即需 ~90 GB)。
|
||||
|
||||
Depth Plane 的视频、序列帧转换会复用同一个 ONNX Session 逐帧独立推理,再把结果合并到现有序列输出,因此峰值显存只取决于单帧分辨率。逐帧结果不保留 DA3 的跨视图尺度与相机位姿一致性,适用于当前逐帧动画结构。Surface 只支持单张图片。DA3 Debug 多帧输入仍联合推理;MoGe-2 与 BEN2 Debug 按单图 API 逐帧保存直接返回。
|
||||
|
||||
联合推理时,`onnx_da3.infer` 会在执行前按 `views × patches` 预估注意力张量,超过 4 GiB 直接报错并提示减少帧数或 Resolution Scale,避免 onnxruntime 报出难以定位的分配失败或 `UnicodeDecodeError`(DirectML 在中文 Windows 下报错信息为 GBK 编码,被 UTF-8 解码掩盖)。
|
||||
|
||||
待解决方向:
|
||||
|
||||
- 重新导出 DA3 ONNX,使用 ORT 的 `Attention` / `MultiHeadAttention` 贡献算子,或注入内存高效的注意力算子;
|
||||
- 若未来需要统一坐标系的视频重建,可按小窗口分批推理,再对齐相机位姿与深度尺度。
|
||||
DA3 Debug 保留联合推理,用于检查模型原始多帧行为。Server 会在预计注意力张量过大时提前报错,此时应减少帧数或 Resolution Scale。
|
||||
|
||||
Reference in New Issue
Block a user