Add tests for foreground preservation and refactor geometry node asset

- Implement test to ensure foreground preserves source RGB and Ben2 alpha in WorkerTest.
- Remove outdated tests related to background distance and original background depth.
- Update geometry node asset to reflect new naming conventions and structure.
- Introduce validation for depth plane asset, ensuring correct input/output configurations and attribute handling.
- Adjust confidence and edge parameters in geometry node asset to support a wider range of values.
This commit is contained in:
2026-08-11 23:25:51 +08:00
parent 07d836d9ad
commit 7cd5681a8b
15 changed files with 1296 additions and 660 deletions

View File

@@ -73,12 +73,9 @@ class ActiveJob:
source_object_name: str = ""
depth_data_name: str = ""
process_res: int = IMAGE_DEPTH_DEFAULT_PROCESS_RES
subdivision_level: int = 5
delete_source: bool = True
displacement_via: str = "MODIFIER"
unshaded: bool = False
remove_background: bool = False
background_depth_distance: float = 0.0
mesh_create_camera: bool = False
temporary_input_path: Path | None = None
cancelled: bool = False
@@ -141,7 +138,7 @@ class RunJob(bpy.types.Operator):
("DOWNLOAD_MODEL", "Download Model", ""),
(RECONSTRUCTION_JOB, "Export DA3 Result", ""),
(IMAGE_DEPTH_JOB, "Convert Image to Depth Plane", ""),
(IMAGE_MESH_JOB, "Convert Image to Mesh", ""),
(IMAGE_MESH_JOB, "Convert Image to Surface", ""),
(BACKGROUND_REMOVAL_JOB, "Test BEN2 Background Removal", ""),
(IMAGE_BACKGROUND_JOB, "Remove Image Empty Background", ""),
(ORIGINAL_BACKGROUND_JOB, "Build Original Background Plane", ""),
@@ -183,29 +180,10 @@ class RunJob(bpy.types.Operator):
default=False,
options={"HIDDEN", "SKIP_SAVE"},
)
snapform_subdivision_level: bpy.props.IntProperty(
default=5,
min=0,
max=10,
options={"HIDDEN", "SKIP_SAVE"},
)
snapform_displacement_via: bpy.props.EnumProperty(
items=(
("MODIFIER", "Modifier", ""),
("MATERIAL", "Material", ""),
),
default="MODIFIER",
options={"HIDDEN", "SKIP_SAVE"},
)
snapform_unshaded: bpy.props.BoolProperty(
default=False,
options={"HIDDEN", "SKIP_SAVE"},
)
snapform_background_depth_distance: bpy.props.FloatProperty(
default=0.0,
min=0.0,
options={"HIDDEN", "SKIP_SAVE"},
)
snapform_mesh_create_camera: bpy.props.BoolProperty(
default=False,
options={"HIDDEN", "SKIP_SAVE"},
@@ -214,6 +192,7 @@ class RunJob(bpy.types.Operator):
default=False,
options={"HIDDEN", "SKIP_SAVE"},
)
def execute(self, context):
global _active_job
@@ -251,15 +230,11 @@ class RunJob(bpy.types.Operator):
source_object_name=self.snapform_source_object_name,
depth_data_name=self.snapform_depth_data_name,
process_res=self.snapform_process_res,
subdivision_level=self.snapform_subdivision_level,
delete_source=self.snapform_delete_source,
displacement_via=self.snapform_displacement_via,
unshaded=self.snapform_unshaded,
remove_background=(
self.snapform_background_depth_distance > 0.0
or bool(getattr(self, "snapform_remove_background", False))
remove_background=bool(
getattr(self, "snapform_remove_background", False)
),
background_depth_distance=self.snapform_background_depth_distance,
mesh_create_camera=getattr(
self,
"snapform_mesh_create_camera",
@@ -350,10 +325,9 @@ class RunJob(bpy.types.Operator):
)
self.snapform_input_path = str(archived_input)
self.snapform_delete_input = False
background_depth_distance = float(
getattr(self, "snapform_background_depth_distance", 0.0)
remove_background = bool(
getattr(self, "snapform_remove_background", False)
)
remove_background = background_depth_distance > 0.0
if self.job_type == IMAGE_MESH_JOB:
remove_background = True
if self.job_type == "INSTALL_RUNTIME":
@@ -413,11 +387,6 @@ class RunJob(bpy.types.Operator):
BEN2_MODEL.key,
start_frame=start_frame,
device=self._task_device(settings),
background_depth_distance=(
background_depth_distance
if self.job_type == ORIGINAL_BACKGROUND_JOB
else 0.0
),
),
paths,
)
@@ -483,11 +452,6 @@ class RunJob(bpy.types.Operator):
self.job_type in {IMAGE_DEPTH_JOB, IMAGE_MESH_JOB}
and remove_background
),
background_depth_distance=(
background_depth_distance
if self.job_type == IMAGE_DEPTH_JOB
else 0.0
),
device=self._task_device(settings),
),
paths,
@@ -520,7 +484,7 @@ class RunJob(bpy.types.Operator):
if self.job_type == IMAGE_DEPTH_JOB:
return "Starting depth estimation"
if self.job_type == IMAGE_MESH_JOB:
return "Starting perspective mesh generation"
return "Starting perspective surface generation"
if self.job_type == BACKGROUND_REMOVAL_JOB:
return "Starting BEN2 background removal"
if self.job_type == IMAGE_BACKGROUND_JOB:
@@ -696,19 +660,19 @@ class RunJob(bpy.types.Operator):
status["message"] = "Depth plane is ready"
if job.kind == IMAGE_MESH_JOB:
try:
settings.status = "Building perspective mesh"
settings.status = "Building perspective surface"
settings.progress = 0.96
self._redraw_ui(context, force=True)
self._build_image_mesh(job)
except (OSError, RuntimeError, ValueError) as import_error:
settings.status = "Mesh import failed"
settings.status = "Surface import failed"
settings.progress = 0.0
self.report({"ERROR"}, str(import_error))
runtime.mark_host_job_complete(job.status_path.stem)
close_active_job()
self._redraw_ui(context, force=True)
return {"CANCELLED"}
status["message"] = "Perspective mesh is ready"
status["message"] = "Perspective surface is ready"
if job.kind in {ORIGINAL_BACKGROUND_JOB, ORIGINAL_FRAMES_JOB}:
try:
settings.status = "Building depth plane"
@@ -761,10 +725,10 @@ class RunJob(bpy.types.Operator):
snapform_unshaded=job.unshaded,
)
if "FINISHED" not in result:
raise RuntimeError("Unable to build the perspective mesh")
undo_result = bpy.ops.ed.undo_push(message="Convert to Mesh")
raise RuntimeError("Unable to build the perspective surface")
undo_result = bpy.ops.ed.undo_push(message="Convert to Surface")
if "FINISHED" not in undo_result:
raise RuntimeError("Unable to create the mesh Undo step")
raise RuntimeError("Unable to create the surface Undo step")
def _build_depth_plane(self, context, job):
result_directory = job.result_directory
@@ -784,18 +748,14 @@ class RunJob(bpy.types.Operator):
snapform_depth_data_name=job.depth_data_name,
snapform_background_path=background_path,
snapform_color_frames_dir=(
str(result_directory)
if is_sequence and not foreground_paths
else ""
str(result_directory) if is_sequence else ""
),
snapform_depth_frames_dir=(
str(result_directory)
if is_sequence
else ""
),
snapform_subdivision_level=job.subdivision_level,
snapform_delete_source=job.delete_source,
snapform_displacement_via=job.displacement_via,
snapform_unshaded=job.unshaded,
)
if "FINISHED" not in result:
@@ -815,7 +775,7 @@ class RunJob(bpy.types.Operator):
if is_sequence
else result_directory / "foreground.png"
)
elif is_sequence:
if is_sequence:
color_frames_dir = str(result_directory)
result = bpy.ops.snapform.build_original_depth_plane(
snapform_source_object_name=job.source_object_name,
@@ -824,14 +784,8 @@ class RunJob(bpy.types.Operator):
snapform_depth_frames_dir=(
str(result_directory) if is_sequence else ""
),
snapform_depth_npz_path=(
str(result_directory / "original-depth.npz")
if job.kind == ORIGINAL_BACKGROUND_JOB
else ""
),
snapform_subdivision_level=job.subdivision_level,
snapform_depth_npz_path="",
snapform_delete_source=job.delete_source,
snapform_displacement_via=job.displacement_via,
snapform_unshaded=job.unshaded,
)
if "FINISHED" not in result: