- Implement sync_models.py for preparing and uploading ONNX artifacts. - Create build_node.py for building and validating Blender scripts. - Add docs.py for building and previewing documentation with Mike or MkDocs. - Introduce model_exports.py for exporting PyTorch models to ONNX format. - Develop pack.py for packaging the project with dependencies for different platforms. - Add test_sync_models.py to validate sync_models functionality. - Add test_tool_commands.py to ensure repository tools have correct command scripts. - Initialize tools package with __init__.py.
5.1 KiB
Cutout Tool
Cutout 从图片上的一个 Region 开始,可按需执行 Fit to Foreground、生成 Depth 或 Normal Map,最后在 Blender 中创建带材质与 Modifier 的 Mesh Object。
执行过程
flowchart TD
Select["圈定 Region,选择 Shape"]
Raster["栅格化 Region"]
Route{"需要后台生成数据?"}
Local["沿用本地 RegionMask"]
Job["执行 Fit to Foreground,生成 Depth / Normal 产物"]
Ready["汇总 Shape 输入"]
Build["构建 BaseShape"]
Create["创建 Blender 对象"]
Select --> Raster --> Route
Route -- "否" --> Local --> Ready
Route -- "是" --> Job --> Ready
Ready --> Build --> Create
Surface 与 Balloon 直接使用 RegionMask 构建 BaseShape;Fit to Foreground、Depth Shape 和 Normal Map 先通过 Server Job 生成所需产物。
节点说明
圈定 Region,选择 Shape
Cutout 工具由 __init__.py 注册,交互从 main.py 中的 SelectCutoutRegion 开始。它接收 Lasso 或双击整图手势,把图片空间路径保存为 RegionPath,然后调用 interaction.py 打开 Shape 饼菜单。
interaction.py 完成 Region 有效性检查、读取三个工具选项,并根据 Mesh Sampling Spacing 换算期望网格分辨率。菜单中的 Surface、Balloon、Depth Balloon 和 Depth Surface,以及它们对应的节点分支索引,统一来自 shape.py。
栅格化 Region
用户选定 Shape 后,main.py 中的 CutoutRegionToShape 接过主线。它使用 common/image_region.py 把 RegionPath 栅格化为 RegionMask:values 保存局部像素权重,bounds 保存它在源图中的位置。套索外和源图透明区域不会进入最终 Region。
此时也会应用 Maximum Cutout Mesh Resolution,统一限制四种 Shape 裁切区域的最长采样边。
需要后台生成数据?
只有以下情况需要提交 Job:
- 开启 Fit to Foreground;
- 选择 Depth Balloon 或 Depth Surface;
- 开启 Generate Normal Map。
Surface 和 Balloon 的本地路径直接沿用 RegionMask。
执行 Fit to Foreground,生成 Depth / Normal 产物
main.py 把请求提交给 server/jobs/cutout.py,生成本次 Shape 需要的产物:
- Fit to Foreground 调用
server/region/refine_region.py,写出收紧后的region.png和region_bounds.json; - 需要 Vector Depth 时写出相机空间 XYZ 组成的
vector-depth.exr,需要 Z Depth 时写出z-depth.exr,两者都配套depth.json; - Generate Normal Map 根据既定空间写出
tangent-normal.png或object-normal.png。
Depth 与 Normal Map 共享同一次 MoGe-2 Prediction。Depth Surface 的 Normal Map 编码为 Cutout 对象空间,其正面是对象局部 -X;其余 Shape 使用 Tangent Space。main.normal_mode_for_shape() 根据 Shape 确定 Normal Space。
Maximum AI Input Size 约束 BEN2 和 MoGe-2 的分析图长边;网格密度使用 Maximum Cutout Mesh Resolution,最终颜色图使用源图裁切分辨率。
构建 BaseShape
Job 完成后,main.py 在 Blender 主线程读取可选的 RegionMask,加载并 Pack Depth 与 Normal 图片。main.create_cutout_shape() 调用 geometry.py 中的 build_base_shape():
- 从最终
RegionMask提取外轮廓和孔洞; - 按 Mesh Sampling Spacing 生成轮廓与内部采样点;
- 进行约束三角化;
- 计算四种 Shape 共用的
o_balloon; - 汇总顶点、三角面、UV 和 Balloon 权重,得到内存中的
BaseShape。
geometry.py 还提供 Depth 标定、采样和网格尺度计算,供后面的对象创建阶段使用。
创建 Blender 对象
main.create_cutout_shape() 把 BaseShape 和可选产物交给 object.py 的 create_shape_object()。这里创建裁切后的 Color Image、Material、Mesh Object,并挂上统一的 O Image Cutout Modifier。材质通过 common/object.py 创建,Cutout 使用 1.2 的 IOR。Color Image 按最终 Region 包围矩形裁切源图并保留 RGBA。
| Shape | Modifier 如何形成结果 | 必需后台产物 |
|---|---|---|
| Surface | 保持基础平面轮廓,可增加真实厚度 | 无 |
| Balloon | 使用 o_balloon 从边缘向内部鼓起 |
无 |
| Depth Balloon | 在 Balloon 上叠加相对基准面的深度 | z-depth.exr、depth.json |
| Depth Surface | 使用相机点 XYZ 重建透视表面 | vector-depth.exr、depth.json |
Depth Shape 的 Base Plane Depth,以及 Depth Balloon 的 Direction,都由 object.py 调用 geometry.py 的标定函数,根据最终 Region Alpha 计算。透明像素达到 5% 时使用有效 Region 自适应标定,否则使用稳定的固定基准。
Normal Map 关闭时材质使用几何法线;开启时,object.py 把生成的图片和已经确定的 Normal Space 交给材质节点。最后 main.py 提交 Undo,整条 Cutout 流程结束。
Balloon 与 Depth Balloon 的材质会创建 Geometry Attribute 节点,把 o_balloon 的 Float 输出直接连接到 O Image Layer 已有的 Normal Scale;Surface 与 Depth Surface 不建立这条连接。