Files
AnyImage/docs/internals/operators/cutout-tool.md
nan 377eee43f5 Refactor and enhance geometry node groups for depth plane and material layers
- Updated the depth plane node group to load from an asset and simplified the interface.
- Created a new build script for depth plane geometry nodes.
- Introduced material layer groups for image and depth materials with appropriate sockets.
- Added functionality to connect balloon normal scale to the image material.
- Enhanced tests to validate the new node groups and their connections.
- Ensured that production code does not create node groups directly.
2026-08-31 12:25:23 +08:00

5.9 KiB
Raw Blame History

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 可以完全在 Blender 中完成;启用 Fit to Foreground、生成 Depth Shape 或 Normal Map 时,中间会经过一次 Server Job。

两条路径的区别只在中间是否需要 Server 产物。回到 Blender 后,它们都使用最终的 RegionMask 构建同一种 BaseShape,再由同一入口创建对象。Server 不创建 Blender Mesh,也不访问 bpy。

下文中的 Blender 侧文件相对 src/anyimage/operators/cutout_tool/,Server 侧文件相对 src/anyimage/server/。

节点说明

圈定 Region,选择 Shape

Cutout 工具由 __init__.py 注册,交互从 main.py 中的 SelectCutoutRegion 开始。它接收 Lasso 或双击整图手势,把图片空间路径保存为 RegionPath,然后调用 interaction.py 打开 Shape 饼菜单。

interaction.py 在这里完成 Region 有效性检查、读取三个工具选项,并根据 Mesh Sampling Spacing 换算期望网格分辨率;它不定义 Operator。菜单中的 Surface、Balloon、Depth Balloon 和 Depth Surface,以及它们对应的节点分支索引,统一来自 shape.py。

栅格化 Region

用户选定 Shape 后,main.py 中的 CutoutRegionToShape 接过主线。它使用 operators/common/image_region.py 把 RegionPath 栅格化为 RegionMask:values 保存局部像素权重,bounds 保存它在源图中的位置。套索外和源图透明区域不会进入最终 Region。

此时也会应用 Maximum Cutout Mesh Resolution。它限制裁切区域的最长采样边,对四种 Shape 一视同仁,与是否使用 AI 无关。

需要后台生成数据?

只有以下情况需要提交 Job:

  • 开启 Fit to Foreground;
  • 选择 Depth Balloon 或 Depth Surface;
  • 开启 Generate Normal Map。

没有开启两个 AI 选项的 Surface 和 Balloon 会直接沿用本地 RegionMask。

执行 Fit to Foreground,生成 Depth / Normal 产物

main.py 把请求提交给 server/jobs/cutout.py。这个 Job 只生成本次 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。Prediction 只存在于 Server 内存,Job 目录只保留 Blender 可直接加载的图片和 JSON。Depth Surface 的 Normal Map 编码为 Cutout 对象空间,其正面是对象局部 -X;其余 Shape 使用 Tangent Space。Normal Space 由 main.normal_mode_for_shape() 根据 Shape 决定,不是单独的用户选项。

Maximum AI Input Size 只限制 BEN2 和 MoGe-2 看到的分析图长边。它不改变网格密度,也不降低最终颜色图分辨率。DA3 不进入这条正式路径,只保留 Debug 功能。

构建 BaseShape

Job 完成后,main.py 在 Blender 主线程读取可选的 RegionMask,直接加载并 Pack Depth 与 Normal 图片;本地路径则直接使用已有数据。两者最终都进入 main.create_cutout_shape(),再调用 geometry.py 中的 build_base_shape():

  1. 从最终 RegionMask 提取外轮廓和孔洞;
  2. 按 Mesh Sampling Spacing 生成轮廓与内部采样点;
  3. 进行约束三角化;
  4. 计算四种 Shape 共用的 o_balloon;
  5. 汇总顶点、三角面、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。材质通过 operators/common/mesh_result.py 创建,Cutout 使用 1.2 的 IOR。Color Image 是按最终 Region 包围矩形裁切的源图 RGBA;RegionMask 不写入颜色图 Alpha,源图原有 Alpha 会原样保留。

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 是材质细节,不改变上述四种 Shape 的几何分类。关闭时材质使用几何法线;开启时,object.py 把生成的图片和已经确定的 Normal Space 交给材质节点。最后 main.py 提交 Undo,整条 Cutout 流程结束。

Balloon 与 Depth Balloon 的材质会创建 Geometry Attribute 节点,把 o_balloon 的 Float 输出直接连接到 O Image Layer 已有的 Normal Scale;Surface 与 Depth Surface 不建立这条连接。