Add comprehensive tests for edge depth extension, empty image edits, and material view adaptation
- Introduced `test_edge_depth.py` to validate the functionality of edge depth extension, ensuring core alpha preservation, proper depth handling, and edge padding behavior. - Created `test_empty_image_edits.py` to verify the behavior of image edits in Blender, focusing on shared edits, preservation of image properties, and handling of failed operations. - Developed `test_material_view_adaptation.py` to test material adaptation preferences, ensuring color space and alpha settings are correctly applied and preserved across various scenarios.
This commit is contained in:
2
openspec/changes/extend-cutout-edge-depth/.openspec.yaml
Normal file
2
openspec/changes/extend-cutout-edge-depth/.openspec.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-09-05
|
||||
69
openspec/changes/extend-cutout-edge-depth/design.md
Normal file
69
openspec/changes/extend-cutout-edge-depth/design.md
Normal file
@@ -0,0 +1,69 @@
|
||||
## Context
|
||||
|
||||
Cutout 的矩形 RGBA 经黑底合成后进入 MoGe,Vector Depth 保存相机 XYZ,节点按 UV 线性采样。边缘 Alpha 可用于保留毛发,但其深度可能属于背景。
|
||||
|
||||
本次实验使用 BEN2、MoGe-2 ViT-S Level 5,固定猫(585×643)和人物(234×222)的同一份预测。Alpha ≥ 0.95、内缩 2 px、最近点外延、σ=0.8 px 局部平滑明显减少拖尾。替换深度的可见像素分别约 4.4% 与 9.6%;可靠内部保持原值。8 px 内缩替换人物约 27% 的可见区域,形状变化明显。
|
||||
|
||||
实验采用独立投影网格。完整 Blender 的线性采样、平滑、厚度、拉伸剔除及 Normal Map 组合需要在实施阶段验收。实验记录位于 `C:/Users/icrdr/.codex/visualizations/2026/09/05/01a071bc-9eae-7f91-8791-816aa621fd8a/`,其中 `depth_experiment.py` 保存推理入口,`analyze_depth.py` 保存对比算法,`metrics.json` 保存结果;该目录是本次本地证据,自动测试使用可重建的合成数据。
|
||||
|
||||
## Goals
|
||||
|
||||
保留 Alpha 0.1 的可见轮廓,以可靠内部深度补齐边缘,并保持相机投影与 Cutout 产物单位一致。
|
||||
|
||||
## Decisions
|
||||
|
||||
### 深度修复入口
|
||||
|
||||
在 `server/geometry/edge_depth.py` 集中处理普通数组和 GeometryFrame。`generate_moge2_artifacts()` 增加内部显式选项,由 Cutout Job 在生成深度时开启。Depth Surface 与 Depth Balloon 分别输出修复后的 Vector Depth、Z Depth,并使用对应 Metadata。Normal Writer 继续消费原始预测;普通 Depth Plane 和仅生成 Normal 的路径维持现有入口行为。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Cutout RGBA] --> B[现有黑底合成与 MoGe 推理]
|
||||
B --> C[原始 GeometryFrame]
|
||||
A --> D[对齐到深度图的连续 Alpha]
|
||||
C --> E[构建可靠内部]
|
||||
D --> E
|
||||
E --> F[分量内深度外延与局部平滑]
|
||||
F --> G[按当前像素射线重建 XYZ]
|
||||
G --> H[输出 Vector/Z Depth 与 Metadata]
|
||||
C --> I[现有 Normal Writer]
|
||||
H --> J[现有 Cutout 修改器]
|
||||
```
|
||||
|
||||
### 可见域与可靠域
|
||||
|
||||
- 连续 Alpha 使用与现有 `_alpha_mask()` 相同的最近邻尺寸对齐;可见域为 Alpha ≥ 0.1。
|
||||
- 可靠候选为 Alpha ≥ 0.95、模型 Validity > 0、深度有限且为正。
|
||||
- 在深度图输出像素单位下,保留到候选域外欧氏距离大于 2 px 的可靠核心;图片矩形边界按边缘延续处理,避免把贴边主体当作透明边缘内缩。
|
||||
- 全不透明源图直接使用原始 Frame。所有参数先固定在服务端实现中。
|
||||
|
||||
### 外延与回退
|
||||
|
||||
可见域按 8 连通分量处理,每个分量只使用自身的可靠核心作为供体。没有内缩核心时使用该分量内未内缩的可靠候选;连候选也没有时保留该分量的原始预测。这样细小或半透明分量具有确定的结果。
|
||||
|
||||
对有供体的分量,以最近可靠像素的标量深度补齐非核心区域。透明背景在可见域外扩 4 px 内接收最近可修复分量的延伸值,覆盖平滑核与线性采样所需的邻域;其他可见分量的值由自身规则决定。局部计算边界须保留滤波所需的 padding。
|
||||
|
||||
外延结果用 σ=0.8 px、半径 3 px 的 Gaussian 核平滑,仅写回补齐区域;可靠核心逐值保留。分量内平滑使用本分量的外延场,避免滤波读入其他分量深度。未处理区域保留原值。
|
||||
|
||||
### 投影与产物一致性
|
||||
|
||||
使用 Frame 的像素单位内参和当前像素中心,由修复后的 Z 重建相机 X、Y。复用服务端现有深度反投影函数时,须显式处理其归一化内参约定。核心位置保留原始 XYZ,防止不必要的浮点变化。
|
||||
|
||||
修复后的 Frame 保留原模型 Validity;修复不会把模型有效性改写为预测置信度。Metadata 使用修复后的 Depth、原模型 Validity 和现有参考 Alpha Mask 计算,确保参考深度与导出贴图一致。颜色 Alpha、UV 与 Selection Mask 继续由现有路径管理。
|
||||
|
||||
### 数值依赖
|
||||
|
||||
复用 SciPy 的距离变换、连通分量和 Gaussian 滤波。实施时选择同时支持开发 Python 3.11、服务端 Python 3.12 及其 NumPy 约束的版本,并同步运行环境声明、开发依赖与锁文件。处理按分量局部范围执行,验证 2048 长边输入的时间和峰值内存。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- 高 Alpha 不等同于正确深度 → 保留 2 px 内缩,并用真实深度场检查残余污染。
|
||||
- 最近供体在同一分量内可能跨越前后表面 → 保持小内缩、仅局部平滑,并验收耳朵、衣领和手部交界。
|
||||
- 半透明孤立分量没有可靠供体时仍可能后缩 → 保留原始预测,测试回退的有限值和确定性。
|
||||
- 固定像素宽度在不同输入尺寸下覆盖比例不同 → 以深度图像素明确单位,验证两张原图及缩放输入;进一步调整参数须有新增证据。
|
||||
- 原始 Normal Map 与修复几何在边缘可能不一致 → 分别验收 Normal 开关下的边缘着色,记录残余问题。
|
||||
- 边缘跳变减小只证明拉伸改善,并不等同于真实三维深度准确 → 同时核对可见域、正面投影和侧视外观。
|
||||
|
||||
## Migration Plan
|
||||
|
||||
新任务在模型产物导出阶段应用修复,已有 Blender 对象通过重新生成 Cutout 获得结果。实施完成后运行相关测试和完整 pytest,再对现有节点资产执行两张实图验收。
|
||||
25
openspec/changes/extend-cutout-edge-depth/proposal.md
Normal file
25
openspec/changes/extend-cutout-edge-depth/proposal.md
Normal file
@@ -0,0 +1,25 @@
|
||||
## Why
|
||||
|
||||
Cutout 用 Alpha 0.1 保留毛发时,边缘可能读取背景深度,形成严重后缩和长条拉伸。猫与人物的实图实验已验证:从可靠内部外延深度,可以保留原 Alpha 轮廓并明显减少拖尾。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 为 Cutout 的 Depth Surface 与 Depth Balloon 增加导出前的边缘深度修复。
|
||||
- 以 Alpha ≥ 0.95 且模型深度有效的内部区域为依据,内缩 2 个深度图像素后向边缘外延,并仅对补齐区域轻微平滑。
|
||||
- 保留颜色 Alpha、0.1 裁切阈值和可靠内部深度;按当前像素的相机射线重建 XYZ。
|
||||
- 为细小分量、无可靠深度和透明区采样增加确定的处理规则,并补充自动测试与 Blender 实图验收。
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `cutout-edge-depth`: Cutout 的可靠深度区域、边缘外延、投影保持和产物一致性。
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
## Impact
|
||||
|
||||
- `server/geometry/`:增加深度修复模块,接入推理产物编排。
|
||||
- `server/jobs/cutout.py`:为 Cutout 深度产物启用修复。
|
||||
- `runtime.py`、`pyproject.toml`、`uv.lock`:加入 SciPy,复用距离变换与局部滤波,并检查环境及打包测试。
|
||||
- 服务端几何与任务测试,以及现有 Blender Cutout 修改器的实图验证。
|
||||
@@ -0,0 +1,65 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Reliable interior supplies edge depth
|
||||
|
||||
系统 SHALL 为包含透明内容的 Cutout 深度产物,从 Alpha ≥ 0.95、Validity > 0 且深度有限为正的候选域中,选择欧氏内缩 2 个深度图像素后的可靠核心。可见域 SHALL 继续使用 Alpha ≥ 0.1,核心深度 SHALL 逐值保留。
|
||||
|
||||
#### Scenario: Hair samples contain background depth
|
||||
- **WHEN** 半透明毛发仍属于可见域,但其预测深度接近背景,所属分量存在可靠核心
|
||||
- **THEN** 系统以该分量最近可靠核心的深度补齐毛发区域,并保留原颜色 Alpha 和裁切轮廓
|
||||
|
||||
#### Scenario: Subject reaches the image rectangle boundary
|
||||
- **WHEN** 不透明主体延伸到图片矩形边界
|
||||
- **THEN** 系统按边缘延续计算内缩,不将图片外部自动视为透明背景
|
||||
|
||||
### Requirement: Extension has deterministic component fallbacks
|
||||
|
||||
系统 SHALL 按可见域的 8 连通分量选择供体。缺少内缩核心时 SHALL 使用本分量未内缩的可靠候选;缺少可靠候选时 SHALL 保留该分量原始预测。
|
||||
|
||||
#### Scenario: Narrow component has no eroded core
|
||||
- **WHEN** 细小分量的可靠候选在 2 px 内缩后消失
|
||||
- **THEN** 系统使用该分量未内缩候选完成外延
|
||||
|
||||
#### Scenario: Translucent component has no reliable candidates
|
||||
- **WHEN** 独立分量完全由低 Alpha 或模型无效像素组成
|
||||
- **THEN** 系统保留该分量预测,不从另一可见分量复制深度
|
||||
|
||||
### Requirement: Filtered sampling uses extended depth
|
||||
|
||||
系统 SHALL 向可修复分量相邻透明区外扩 4 px 的范围延伸深度,并以 σ=0.8 px、半径 3 px 的 Gaussian 核仅平滑补齐区域。核心及其他未处理区域 SHALL 保留原值。
|
||||
|
||||
#### Scenario: Texture sampling straddles the silhouette
|
||||
- **WHEN** 线性采样邻域跨越可见边缘和邻近透明背景
|
||||
- **THEN** 透明侧提供外延深度,采样不会重新混入该邻域原来的背景深度
|
||||
|
||||
#### Scenario: Adjacent components have different depths
|
||||
- **WHEN** 两个可见分量分别位于不同深度
|
||||
- **THEN** 各分量的供体与平滑输入保持分量隔离
|
||||
|
||||
### Requirement: Corrected geometry preserves camera projection
|
||||
|
||||
系统 SHALL 根据修复后的 Z 和当前像素中心的相机射线重建 XYZ,使修复前后的相机投影保持一致,并保留核心原始 XYZ。
|
||||
|
||||
#### Scenario: Edge pixel inherits an interior depth
|
||||
- **WHEN** 边缘像素采用另一像素的可靠 Z
|
||||
- **THEN** 重建 XYZ 仍投影到边缘像素自身位置,而不是供体位置;数值测试的归一化投影误差 SHALL 小于 1e-6
|
||||
|
||||
### Requirement: Cutout artifacts share corrected depth
|
||||
|
||||
系统 SHALL 为 Depth Surface 与 Depth Balloon 的 Vector/Z Depth 和 Metadata 使用同一修复后深度。模型 Validity SHALL 保留其原始语义,Normal Writer SHALL 继续使用原始预测。
|
||||
|
||||
#### Scenario: Cutout exports vector depth and metadata
|
||||
- **WHEN** Cutout 请求深度产物
|
||||
- **THEN** Vector Depth 的 Z 与 Metadata 参考深度来自同一修复后深度场,所有输出坐标有限
|
||||
|
||||
#### Scenario: Existing artifact paths do not require correction
|
||||
- **WHEN** 输入完全不透明,或请求来自普通 Depth Plane,或 Cutout 只生成 Normal
|
||||
- **THEN** 系统使用对应的原始产物路径与预测行为
|
||||
|
||||
### Requirement: Edge correction is verified in the full Cutout pipeline
|
||||
|
||||
验收 SHALL 使用猫与人物原图依次执行 Remove Background 和 Cutout,固定同一 Alpha 与模型预测比较修复前后结果,并检查 Depth Surface、Depth Balloon 及 Normal 开关组合。
|
||||
|
||||
#### Scenario: Side-view regression comparison
|
||||
- **WHEN** 两张实图完成完整 Blender 修改器求值
|
||||
- **THEN** 主要边缘长条后缩明显减少,原 Alpha 可见域保持一致,可靠核心深度逐值不变,并记录残余台阶、着色或剔除问题
|
||||
28
openspec/changes/extend-cutout-edge-depth/tasks.md
Normal file
28
openspec/changes/extend-cutout-edge-depth/tasks.md
Normal file
@@ -0,0 +1,28 @@
|
||||
## 1. 数值依赖与深度修复
|
||||
|
||||
- [x] 1.1 确定兼容开发和服务端 Python、NumPy 的 SciPy 版本,同步 `runtime.py`、`pyproject.toml` 和 `uv.lock`,检查 Manifest 与环境、打包测试约束。
|
||||
- [x] 1.2 在 `server/geometry/edge_depth.py` 实现连续 Alpha 对齐、可靠候选、2 px 欧氏内缩及图片边缘延续,补充阈值和贴边主体测试。
|
||||
- [x] 1.3 实现按可见域 8 连通分量选取最近供体,以及无内缩核心、无候选的回退规则,测试细小分量与不同深度的相邻分量。
|
||||
- [x] 1.4 实现透明区 4 px 外扩和 σ=0.8 px、半径 3 px 的局部平滑,测试核心逐值不变、邻域采样与跨分量隔离。
|
||||
|
||||
## 2. 产物接入
|
||||
|
||||
- [x] 2.1 按 Frame 内参和当前像素射线重建修复区域 XYZ;复用现有服务端反投影能力,测试非方形图片、像素中心、有限值及小于 1e-6 的归一化投影误差。
|
||||
- [x] 2.2 为 `generate_moge2_artifacts()` 增加内部修复选项,由 Cutout Job 在深度请求中启用;Vector/Z Depth 与 Metadata 共用修复后 Frame,保留模型 Validity 和原始 Normal Writer 输入。
|
||||
- [x] 2.3 补充任务回归测试,覆盖 Depth Surface、Depth Balloon、完全不透明图片、普通 Depth Plane 和仅 Normal 请求的产物行为。
|
||||
|
||||
## 3. 验证
|
||||
|
||||
- [x] 3.1 运行数值、服务端任务、运行环境和打包相关测试,再运行 `uv run pytest`。
|
||||
- [x] 3.2 用可重建的 2048 长边输入检查处理时间、峰值内存和分量数量对开销的影响,确认局部范围处理可用。
|
||||
- [x] 3.3 使用两张用户原图重新执行 BEN2 与 MoGe,固定同一 Alpha 和预测,对比修复前后边缘跳变、可见域及正面投影;补充缩放输入检查,记录结果。
|
||||
- [x] 3.4 使用现有 Blender 节点资产验收两张图的 Depth Surface、Depth Balloon 和 Normal 开关组合,检查线性采样、平滑、厚度与拉伸剔除后的侧视拖尾及残余台阶、着色问题。
|
||||
|
||||
## 验证记录
|
||||
|
||||
- `uv run pytest -q`:524 passed,56 subtests passed。
|
||||
- SciPy 1.15.3 支持 Python ≥ 3.10、NumPy ≥ 1.23.5 且 < 2.5;已在开发和服务端环境执行。
|
||||
- 2048×2048、1/64/1024 个分量:0.445/0.399/0.394 秒;独立进程峰值工作集约 453/343/367 MiB(处理前约 229 MiB)。
|
||||
- 猫与人物原图及半尺寸图完成重新推理,正面投影误差均小于 3×10⁻⁸,可靠核心逐值保持。猫原图边缘跳变 P95 从约 14.86% 降至 0.10%,人物从约 2.98% 降至 0.35%(以各自参考深度归一化)。
|
||||
- Blender 4.5.3 现有资产完成 16 组渲染,并对平滑 2 次、厚度 0.02、Stretch Limit 0.05 组合额外求值;所有网格坐标有限。Depth Surface 主要拖尾消除,猫最大网格边长从 2.266 降至 0.107,人物从 1.311 降至 0.662。Depth Balloon 轮廓整体稳定,人物手部原有拉伸仍可见;原始 Normal 的边缘着色仍有局部差异。
|
||||
- 本地验证脚本、预测、指标及渲染位于 `C:/Users/icrdr/.codex/visualizations/2026/09/05/01a071bc-9eae-7f91-8791-816aa621fd8a/verification/`;脚本 `verify_edge_depth.py`、`verify_blender_depth.py` 位于其父目录。
|
||||
Reference in New Issue
Block a user