feat(cutout_tool): Implement cutout region to shape functionality

- Added interaction helpers for cutout region validation and shape menu interaction.
- Created main operator for converting image regions into cutout shapes, including AI artifact generation.
- Introduced object creation logic for cutout shapes, handling depth and normal textures.
- Defined cutout shape identifiers and node groups for various shape types.
- Implemented depth texture writing and prediction artifact generation for MoGe-2.
- Developed server jobs for generating cutout artifacts, depth planes, and refining image regions.
- Added region refinement logic to enhance gesture masks using BEN2.
This commit is contained in:
2026-08-31 11:36:27 +08:00
parent 08309f719d
commit 87d7721128
80 changed files with 4823 additions and 4297 deletions

View File

@@ -1,48 +1,45 @@
# Image Tool
`operators/image_tool/` 对应工具栏中的 Box、Lasso、Line 与 Polyline。四个 WorkspaceTool 共用一个 `EditImageMask` Operator:手势先形成图片空间 Region,Region 栅格化为 Mask 后才修改图片 Alpha;只有 Box 与 Lasso 可以用 BEN2 执行 Refine Selection。
Image Tool 从 Box、Lasso、Line 或 Polyline 手势得到一个图片 Region,再用它修改当前 Image Empty 的 Alpha。
## 对应文件
```text
operators/image_tool/
├── __init__.py # 类型清单与对外导出
├── box.py # Box WorkspaceTool
├── lasso.py # Lasso WorkspaceTool
├── line.py # Line WorkspaceTool
├── polyline.py # Polyline WorkspaceTool
└── edit_mask.py # 本地编辑与 Refine Job 响应
```
手势、坐标和像素能力由 `operators/common/` 提供,四点矫正则属于独立的 [`operators/perspective_tool/`](perspective-tool.md)。
## 编辑流程
## 执行过程
```mermaid
flowchart TD
Tool["Box / Lasso / Line / Polyline"] --> Gesture["ImageRegionGesture"]
Gesture --> Region["RegionPath"]
Region --> Raster["栅格化 Region"]
Raster --> Data["RegionMask"]
Data --> Refine{"Refine Selection?"}
Refine -- "否" --> Mask["Region Mask"]
Refine -- "是" --> Input["带 Region Alpha 的裁切 RGBA"]
Input --> Job["refine-image-mask"]
Tool["Box / Lasso / Line / Polyline"] --> Gesture["采集图片空间手势"]
Gesture --> Region["RegionPath → RegionMask"]
Region --> Refine{"Fit to Foreground?"}
Refine -- "否" --> Mask["使用本地 RegionMask"]
Refine -- "是" --> Job["refine-image-region"]
Job --> Mask
Mask --> Alpha["源 Alpha × Mask"]
Mask --> Alpha["源 Alpha × RegionMask"]
Alpha --> Crop["紧裁切并写回 Empty"]
```
`EditImageMask` 只接受静态图片。`ImageRegionGesture` 把屏幕路径投射为 `RegionPath`;`rasterize_region_path()` 再生成 `RegionMask`。未启用 Refine 时直接把 Region Mask 乘入源 Alpha;启用后,Operator 将 `RegionMask` 写成局部 RGBA 并提交 Job,响应阶段读取细化后的 Alpha 与 `bounds`,再映射回完整画布。
四个工具共用 `EditImageMask`。Box 和 Lasso 可以执行 Fit to Foreground;Line 与 Polyline 始终保留几何边界,直接使用本地 `RegionMask`。
Box 和 Lasso 分别保存自己的 Refine Selection 状态。Line 与 Polyline 强制关闭 Refine,只使用本地 Region Mask;Line 将有向线扩展为半平面 Path,Polyline 显式闭合用户确认的 Path。
## 节点说明
## 手势与预览
### 选择工具并采集手势
四个工具使用相同的白色虚线轮廓和半透明填充。Lasso 按移动距离采点,并在线合并近似共线点;普通凹多边形使用三角剖分,自交路径使用 EVEN_ODD 扫描填充。预览缓存只在轨迹变化时更新。
`operators/image_tool/__init__.py` 汇总注册类型;`box.py`、`lasso.py`、`line.py` 和 `polyline.py` 分别定义四个 WorkspaceTool。它们都把操作交给 `edit_mask.py` 中的 `EditImageMask`。
首次点击通过公共选择逻辑决定是切换 Active Image Empty,还是开始编辑当前图片。这样工具不需要替代 Blender 的普通对象选择。
屏幕坐标投射、点击选择、轨迹预览和状态切换来自 `operators/common/image_interaction.py`。Lasso 按移动距离采点并合并近似共线点;Line 扩展为有向半平面;Polyline 在确认时闭合路径。
## 写回结果
### RegionPath → RegionMask
最终像素通过公共 `image_pixels()` / `image_rgba()` 读取,保留源 RGB,只修改 Alpha,再按非零 Alpha 紧裁切。公共像素写回函数创建结果后,通过统一的 Image Empty 替换入口处理共享引用,并更新 `empty_display_size` 与 `empty_image_offset`,因此剩余像素继续对齐原图片平面,对象 `matrix_world` 不变。
`EditImageMask` 通过 `operators/common/image_region.py` 把手势整理为 `RegionPath`,再栅格化为 `RegionMask`。凹多边形使用三角剖分,自交路径使用 `EVEN_ODD` 填充。预览缓存只在轨迹变化时更新。
Box 和 Lasso 分别读取自己的 **Fit to Foreground** 设置。Line 与 Polyline 强制关闭该选项,因此不会改变直线边界。
### Fit to Foreground
未开启 Fit to Foreground 时,`edit_mask.py` 直接使用本地 `RegionMask`。开启后,`RefineImageRegion` 把带 Region Alpha 的局部 RGBA 提交给 `server/jobs/refine_image_region.py`;Job 调用 `server/region/refine_region.py` 运行 BEN2,并返回收紧后的图片和 `bounds`。
响应阶段仍由 `edit_mask.py` 把局部结果映射回完整画布。
### 源 Alpha × RegionMask
`edit_mask.py` 保留源 RGB,只把最终 `RegionMask` 乘入源 Alpha,再按非零 Alpha 紧裁切。像素读取、结果 Image 创建和共享引用处理使用 `operators/common/image_data.py`。
公共 Image Empty 替换入口会同步更新 `empty_display_size` 和 `empty_image_offset`,因此裁切后的内容仍对齐原图片平面,对象 `matrix_world` 不变。Perspective 使用相同的像素写回能力,但属于独立工具和状态。