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:
2026-09-01 22:36:20 +08:00
parent 2ff7b04f56
commit 7f6e47432e
54 changed files with 2831 additions and 634 deletions

View File

@@ -126,6 +126,7 @@ class ServerJobsTest(unittest.TestCase):
cls.debug_da3_outputs = load_server_module("outputs.debug_da3")
cls.debug_moge2_outputs = load_server_module("outputs.debug_moge2")
cls.debug_jobs = load_server_module("jobs.debug_predictions")
cls.depth_plane_job = load_server_module("jobs.depth_plane")
cls.upscale_job = load_server_module("jobs.upscale")
cls.download = load_server_module("model_download")
@@ -139,6 +140,51 @@ class ServerJobsTest(unittest.TestCase):
"Upscaling image (2/3)",
)
def test_depth_plane_job_requests_z_depth_and_tangent_normal_together(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
input_path = root / "input.png"
input_path.touch()
context = FakeJobContext(root / "result", "generate-depth-plane-geometry")
z_depth = context.directory / "z-depth.exr"
metadata = context.directory / "depth.json"
tangent_normal = context.directory / "tangent-normal.png"
parameters = {"input": str(input_path)}
with (
patch.object(
self.depth_plane_job,
"input_frames",
return_value=nullcontext([input_path]),
),
patch.object(self.depth_plane_job, "copy_color_images"),
patch.object(
self.depth_plane_job,
"generate_moge2_artifacts",
return_value={
"z_depth": z_depth,
"depth_metadata": metadata,
"tangent_normal": tangent_normal,
},
) as generate,
):
result = self.depth_plane_job.run(context, parameters)
self.assertEqual(
result,
{
"z_depth": "z-depth.exr",
"depth_metadata": "depth.json",
"tangent_normal": "tangent-normal.png",
},
)
generate.assert_called_once_with(
context,
parameters,
input_path,
depth_mode="Z",
normal_mode="TANGENT",
)
def test_collect_images_is_sorted_and_filters_suffixes(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)