- Implemented viewport.py for handling 3D view projections, gestures, and overlay drawing. - Created refine_image_selection.py to manage the refinement of gesture masks and output image bounds. - Added selection module with refine_selection.py to process and crop images based on alpha channel visibility. - Introduced __init__.py for selection module to expose refine_selection function.
90 lines
5.3 KiB
Markdown
90 lines
5.3 KiB
Markdown
# Cutout Tool
|
||
|
||
Cutout 从图片上的一个 Selection 开始,可按需执行 Refine Selection、生成 Depth 或 Normal Map,最后在 Blender 中创建带材质与 Modifier 的 Mesh Object。
|
||
|
||
## 执行过程
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Select["圈定 Selection,选择 Shape"]
|
||
Raster["栅格化 Selection"]
|
||
Route{"需要后台生成数据?"}
|
||
Local["沿用本地 SelectionMask"]
|
||
Job["执行 Refine Selection,生成 Depth / Normal 产物"]
|
||
Ready["汇总 Shape 输入"]
|
||
Build["构建 BaseShape"]
|
||
Create["创建 Blender 对象"]
|
||
|
||
Select --> Raster --> Route
|
||
Route -- "否" --> Local --> Ready
|
||
Route -- "是" --> Job --> Ready
|
||
Ready --> Build --> Create
|
||
```
|
||
|
||
Surface 与 Balloon 直接使用 `SelectionMask` 构建 `BaseShape`;Refine Selection、Depth Shape 和 Normal Map 先通过 Server Job 生成所需产物。
|
||
|
||
## 节点说明
|
||
|
||
### 圈定 Selection,选择 Shape
|
||
|
||
Cutout 工具由 `__init__.py` 注册,交互从 `main.py` 中的 `SelectCutoutSelection` 开始。它接收 Lasso 或双击整图手势,把图片空间路径保存为 `SelectionPath`,然后调用 `interaction.py` 打开 Shape 饼菜单。
|
||
|
||
`interaction.py` 完成 Selection 有效性检查并读取三个工具选项。**Mesh Detail** 的 Low、Medium、High、Ultra 分别映射到 32、16、8、4 px 的采样间距,再换算期望网格分辨率;档位越高,采样越密。菜单中的 Surface、Balloon、Depth Balloon 和 Depth Surface,以及它们对应的节点分支索引,统一来自 `shape.py`。
|
||
|
||
### 栅格化 Selection
|
||
|
||
用户选定 Shape 后,`main.py` 中的 `CutoutSelectionToShape` 接过主线。它使用 `common/selection.py` 把 `SelectionPath` 栅格化为 `SelectionMask`:`values` 保存局部像素权重,`bounds` 保存它在源图中的位置。套索外和源图透明区域不会进入最终 Selection。
|
||
|
||
此时也会应用 **Maximum Cutout Mesh Resolution**,统一限制四种 Shape 裁切区域的最长采样边。
|
||
|
||
### 需要后台生成数据?
|
||
|
||
只有以下情况需要提交 Job:
|
||
|
||
- 开启 **Refine Selection**;
|
||
- 选择 Depth Balloon 或 Depth Surface;
|
||
- 开启 **Normal Map**。
|
||
|
||
Surface 和 Balloon 的本地路径直接沿用 `SelectionMask`。
|
||
|
||
### 执行 Refine Selection,生成 Depth / Normal 产物
|
||
|
||
`main.py` 把请求提交给 `server/jobs/cutout.py`,生成本次 Shape 需要的产物:
|
||
|
||
- **Refine Selection** 调用 `server/selection/refine_selection.py`,写出收紧后的 `selection.png` 和 `selection_bounds.json`;
|
||
- 需要 Vector Depth 时写出相机空间 XYZ 组成的 `vector-depth.exr`,需要 Z Depth 时写出 `z-depth.exr`,两者都配套 `depth.json`;
|
||
- **Normal Map** 根据既定空间写出 `tangent-normal.png` 或 `object-normal.png`。
|
||
|
||
Depth 与 Normal Map 共享同一个 MoGe-2 `GeometryFrame`。模型输入先按 Alpha 合成到黑底;Vector/Z Depth 的 RGB 保留完整连续 Field,Alpha 保存模型 Validity。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 主线程读取可选的 SelectionMask,加载并 Pack Depth 与 Normal 图片。`main.create_cutout_shape()` 调用 `geometry.py` 中的 `build_base_shape()`:
|
||
|
||
1. 从最终 `SelectionMask` 提取外轮廓和孔洞;
|
||
2. 按 Mesh Detail 对应的采样间距生成轮廓与内部采样点;
|
||
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。材质通过 `common/material.py` 创建,Cutout 使用 `1.2` 的 IOR。Color Image 按最终 Selection 包围矩形裁切源图并保留 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` 的标定函数,根据最终 Selection Alpha 计算。透明像素达到 `5%` 时使用有效 Selection 自适应标定,否则使用稳定的固定基准。
|
||
|
||
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 不建立这条连接。
|