Add comprehensive tests for image processing and mask functionalities
- Introduced tests for color image handling, ensuring source preservation and premultiplied alpha usage. - Implemented tests for brush stroke operations, validating segment boundaries and brush anti-aliasing. - Added tests for frame anti-aliasing, confirming correct rendering behavior with various alpha values and depth settings. - Created tests for frame projection, ensuring accurate overlap calculations and half-plane clipping. - Developed tests for image premultiplied retention, verifying behavior during loading and packing processes. - Added undo functionality tests for mask operations, ensuring single transaction behavior during edits.
This commit is contained in:
@@ -343,7 +343,6 @@ class ServerRuntimeTest(unittest.TestCase):
|
||||
{
|
||||
"download-model",
|
||||
"download-required-models",
|
||||
"refine-image-selection",
|
||||
"remove-background",
|
||||
"upscale-image",
|
||||
"generate-depth-plane-geometry",
|
||||
@@ -547,10 +546,10 @@ class ServerRuntimeTest(unittest.TestCase):
|
||||
encoded,
|
||||
np.asarray(
|
||||
[[
|
||||
(0, 127, 127),
|
||||
(127, 127, 255),
|
||||
(255, 127, 127),
|
||||
(127, 0, 127),
|
||||
(127, 127, 0),
|
||||
(0, 128, 128),
|
||||
(128, 128, 255),
|
||||
]],
|
||||
dtype=np.uint8,
|
||||
),
|
||||
@@ -700,46 +699,6 @@ class ServerRuntimeTest(unittest.TestCase):
|
||||
self.assertTrue(all(path.is_file() for path in result.values()))
|
||||
self.assertTrue(infer.call_args.kwargs["include_points"])
|
||||
|
||||
def test_refine_selection_preserves_the_full_alpha_canvas(self):
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
refine = importlib.import_module("server.selection.refine_selection")
|
||||
input_path = self.storage_root / "input.png"
|
||||
output_path = self.storage_root / "output.png"
|
||||
source = np.zeros((3, 4, 4), dtype=np.uint8)
|
||||
source[..., :3] = (32, 64, 96)
|
||||
source[..., 3] = np.asarray(
|
||||
((0, 64, 128, 255), (255, 128, 64, 0), (0, 0, 255, 255)),
|
||||
dtype=np.uint8,
|
||||
)
|
||||
Image.fromarray(source, mode="RGBA").save(input_path)
|
||||
foreground = Image.fromarray(source, mode="RGBA")
|
||||
context = SimpleNamespace(
|
||||
resource=lambda _name: SimpleNamespace(directory=lambda _model: "model"),
|
||||
check_cancelled=lambda: None,
|
||||
)
|
||||
|
||||
with patch.object(
|
||||
refine,
|
||||
"infer_foreground",
|
||||
return_value=(foreground, 0.0, 0.0),
|
||||
) as infer:
|
||||
result = refine.refine_selection(
|
||||
context,
|
||||
input_path,
|
||||
"BEN2_BASE",
|
||||
"cpu",
|
||||
output_path,
|
||||
)
|
||||
|
||||
self.assertEqual(result, output_path)
|
||||
infer.assert_called_once()
|
||||
self.assertTrue(infer.call_args.kwargs["preserve_input_alpha"])
|
||||
with Image.open(output_path) as output:
|
||||
self.assertEqual(output.size, (4, 3))
|
||||
np.testing.assert_array_equal(np.asarray(output.convert("RGBA")), source)
|
||||
|
||||
def test_generate_cutout_artifacts_only_returns_requested_outputs(self):
|
||||
job = sys.modules["server.jobs.cutout"]
|
||||
input_path = self.storage_root / "input.png"
|
||||
@@ -789,91 +748,3 @@ class ServerRuntimeTest(unittest.TestCase):
|
||||
depth_mode="VECTOR",
|
||||
normal_mode="OBJECT",
|
||||
)
|
||||
|
||||
def test_generate_cutout_artifacts_refines_the_full_bounds_image(self):
|
||||
job = sys.modules["server.jobs.cutout"]
|
||||
input_path = self.storage_root / "input.png"
|
||||
input_path.write_bytes(b"selection")
|
||||
directory = self.storage_root / "job"
|
||||
context = SimpleNamespace(
|
||||
directory=directory,
|
||||
progress=lambda *_args: None,
|
||||
check_cancelled=lambda: None,
|
||||
)
|
||||
|
||||
def generate(_context, _input, _model, _device, output):
|
||||
output.write_bytes(b"refined")
|
||||
return output
|
||||
|
||||
with patch.object(job, "refine_selection", side_effect=generate):
|
||||
result = job.run(
|
||||
context,
|
||||
{
|
||||
"input": str(input_path),
|
||||
"refine_selection": True,
|
||||
"refine_model": "BEN2_BASE",
|
||||
"device": "cpu",
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
result,
|
||||
{"selection_image": "selection.png"},
|
||||
)
|
||||
self.assertFalse((directory / "selection_bounds.json").exists())
|
||||
|
||||
def test_refined_cutout_artifacts_share_the_full_refine_image(self):
|
||||
job = sys.modules["server.jobs.cutout"]
|
||||
input_path = self.storage_root / "input.png"
|
||||
input_path.write_bytes(b"selection")
|
||||
directory = self.storage_root / "job"
|
||||
context = SimpleNamespace(
|
||||
directory=directory,
|
||||
progress=lambda *_args: None,
|
||||
check_cancelled=lambda: None,
|
||||
)
|
||||
refined_path = directory / "selection.png"
|
||||
|
||||
def refine(_context, _input, _model, _device, output):
|
||||
output.write_bytes(b"refined")
|
||||
return output
|
||||
|
||||
with (
|
||||
patch.object(job, "refine_selection", side_effect=refine),
|
||||
patch.object(
|
||||
job,
|
||||
"generate_moge2_artifacts",
|
||||
return_value={
|
||||
"z_depth": directory / "z-depth.exr",
|
||||
"depth_metadata": directory / "depth.json",
|
||||
"tangent_normal": directory / "tangent-normal.png",
|
||||
},
|
||||
) as generate,
|
||||
):
|
||||
result = job.run(
|
||||
context,
|
||||
{
|
||||
"input": str(input_path),
|
||||
"refine_selection": True,
|
||||
"refine_model": "BEN2_BASE",
|
||||
"device": "cpu",
|
||||
"depth_mode": "Z",
|
||||
"normal_mode": "TANGENT",
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(result["selection_image"], "selection.png")
|
||||
generate.assert_called_once_with(
|
||||
context,
|
||||
{
|
||||
"input": str(input_path),
|
||||
"refine_selection": True,
|
||||
"refine_model": "BEN2_BASE",
|
||||
"device": "cpu",
|
||||
"depth_mode": "Z",
|
||||
"normal_mode": "TANGENT",
|
||||
},
|
||||
refined_path,
|
||||
depth_mode="Z",
|
||||
normal_mode="TANGENT",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user