feat(selection): separate selection geometry from image content processing
- Introduced a new design for selection rasterization that decouples the selection geometry from the image content, ensuring that the SelectionMask is independent of the source image's alpha and color. - Updated the `rasterize_selection_path` function to only accept selection paths and image dimensions, removing parameters related to source alpha and alpha thresholds. - Implemented a new approach for handling selection paths using non-zero winding fill, ensuring overlapping areas are preserved. - Enhanced performance by utilizing a scanline algorithm for rasterization, significantly reducing processing time for high-resolution images. - Updated internal documentation and added comprehensive tests to validate the new behavior and performance improvements. - Ensured backward compatibility by maintaining existing interfaces where necessary while introducing breaking changes in the selection processing logic.
This commit is contained in:
@@ -7,13 +7,15 @@ Image Tool 从 Box、Lasso、Line 或 Polyline 手势得到一个图片 Selectio
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Tool["Box / Lasso / Line / Polyline"] --> Gesture["采集图片空间手势"]
|
||||
Gesture --> Selection["SelectionPath → SelectionMask"]
|
||||
Gesture --> Path["构建 SelectionPath"]
|
||||
Path --> Selection["SelectionPath → 几何 SelectionMask"]
|
||||
Selection --> Refine{"Refine Selection?"}
|
||||
Refine -- "否" --> Mask["使用本地 SelectionMask"]
|
||||
Refine -- "是" --> Job["refine-image-selection"]
|
||||
Job --> Mask
|
||||
Mask --> Alpha["源 Alpha × SelectionMask"]
|
||||
Alpha --> Crop["紧裁切并写回 Empty"]
|
||||
Refine -- "否" --> Alpha["读取局部 RGBA<br/>源 Alpha × Selection 值"]
|
||||
Alpha --> Crop["计算内容 bounds<br/>创建并写回 Image"]
|
||||
Refine -- "是" --> Bounds["读取 RGBA<br/>写出几何 bounds 矩形"]
|
||||
Bounds --> Job["refine-image-selection"]
|
||||
Job --> Result["加载并 Pack BEN2 RGBA"]
|
||||
Result --> Replace["按响应内容 bounds 替换 Empty"]
|
||||
```
|
||||
|
||||
四个工具共用 `EditImageMask`。Box 和 Lasso 可以执行 Refine Selection;Line 与 Polyline 始终保留几何边界,直接使用本地 `SelectionMask`。
|
||||
@@ -28,18 +30,18 @@ flowchart TD
|
||||
|
||||
### SelectionPath → SelectionMask
|
||||
|
||||
`EditImageMask` 通过 `common/selection.py` 把手势整理为 `SelectionPath`,再栅格化为 `SelectionMask`。凹多边形使用三角剖分,自交路径使用 `EVEN_ODD` 填充。预览缓存只在轨迹变化时更新。
|
||||
`ImageSelectionGesture` 把手势整理为内存中的 `SelectionPath`,其中 Points 与 Invert 共同定义 Selection,并直接交给同一个 `EditImageMask` Operator,不经过 JSON。预览和最终 Mask 统一使用 non-zero winding,同方向重复绕行的重叠区域保持选中。实际图片编辑开始后,`EditImageMask` 通过 `common/selection.py` 在必要画布内把路径栅格化为一次纯几何 `SelectionMask`;这一阶段不读取或接收源图 Alpha。预览缓存只在轨迹变化时更新。
|
||||
|
||||
Box 和 Lasso 分别读取自己的 **Refine Selection** 设置。Line 与 Polyline 直接使用几何边界。
|
||||
|
||||
### Refine Selection
|
||||
|
||||
未开启 Refine Selection 时,`edit_mask.py` 直接使用本地 `SelectionMask`。开启后,`RefineImageSelection` 把带 Selection Alpha 的局部 RGBA 提交给 `server/jobs/refine_image_selection.py`;Job 调用 `server/selection/refine_selection.py` 运行 BEN2,并返回收紧后的图片和 `bounds`。
|
||||
未开启 Refine Selection 时,`edit_mask.py` 在实际编辑阶段读取 RGBA 并使用本地几何 `SelectionMask`。开启后,它按 Selection 几何 bounds 写出完整矩形 RGBA 并提交给 `server/jobs/refine_image_selection.py`;矩形内、Lasso 外的源像素与 Alpha 保持原样。Job 调用 `server/selection/refine_selection.py` 运行 BEN2,并返回按结果 Alpha 收紧后的图片和局部内容 `bounds`。
|
||||
|
||||
响应阶段仍由 `edit_mask.py` 把局部结果映射回完整画布。
|
||||
Lasso 在 Refine 中只提供矩形上下文,不再作为 BEN2 输出的硬 Mask。响应阶段把局部内容 bounds 映射回源图,并直接加载、配置和 Pack BEN2 已编码的 RGBA 后替换 Empty;不再提取输出 Alpha、重读源图或重新创建同一颜色图片。
|
||||
|
||||
### 源 Alpha × SelectionMask
|
||||
|
||||
`edit_mask.py` 保留源 RGB,只把最终 `SelectionMask` 乘入源 Alpha,再按非零 Alpha 紧裁切。像素读取、结果 Image 创建和共享引用处理使用 `common/image.py`。
|
||||
`edit_mask.py` 在 `SelectionMask.bounds` 内复用源 RGBA,只把几何 Selection 值乘入源 Alpha,再按行列可见范围计算内容 bounds 并紧裁切。几何 SelectionMask 在合并前后保持不变。像素读取、结果 Image 创建和共享引用处理使用 `common/image.py`。
|
||||
|
||||
公共 Image Empty 替换入口同步更新 `empty_display_size` 和 `empty_image_offset`,使裁切后的内容对齐原图片平面并保持对象 `matrix_world`。
|
||||
|
||||
Reference in New Issue
Block a user