From e3d023cac51da622f8aa47756983f7c8f77065f4 Mon Sep 17 00:00:00 2001 From: nan Date: Wed, 12 Aug 2026 18:27:40 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20mini=5Fnpz=20=E6=B7=B1?= =?UTF-8?q?=E5=BA=A6=E6=95=B0=E6=8D=AE=E8=81=8C=E8=B4=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/snapform/image_depth.py | 40 +++++++++++++------------------------ src/snapform/worker.py | 40 ------------------------------------- tests/test_image_depth.py | 32 +++++++++++++++-------------- tests/test_worker.py | 39 +----------------------------------- 4 files changed, 32 insertions(+), 119 deletions(-) diff --git a/src/snapform/image_depth.py b/src/snapform/image_depth.py index 7636f25..668aad2 100644 --- a/src/snapform/image_depth.py +++ b/src/snapform/image_depth.py @@ -9,7 +9,6 @@ DEPTH_KEY_CANDIDATES = ("depth", "depths") INTRINSICS_KEY_CANDIDATES = ("intrinsics", "ixts") DISPLACEMENT_STRENGTH = 1.0 DISPLACEMENT_MIDLEVEL = 0.0 -REFERENCE_DEPTH_KEY = "snapform_reference_depth" ORIGINAL_DISPLACEMENT_STRENGTH = 1.0 ORIGINAL_DISPLACEMENT_MIDLEVEL = 0.0 BUMP_BASE_DISTANCE = 0.001 @@ -695,25 +694,6 @@ def extract_intrinsics_array(npz_path): return intrinsics -def extract_reference_depth(npz_path): - try: - import numpy as np - except ImportError as error: - raise RuntimeError("Blender Python does not provide NumPy") from error - - try: - with np.load(npz_path, allow_pickle=False) as archive: - if REFERENCE_DEPTH_KEY not in archive.files: - return None - reference_depth = float(archive[REFERENCE_DEPTH_KEY]) - except OSError as error: - raise ValueError(f"Unable to read Mini NPZ: {npz_path}") from error - - if not np.isfinite(reference_depth) or reference_depth <= 0.0: - raise ValueError("Mini NPZ has an invalid reference depth") - return reference_depth - - def prepare_depth_values(depth): import numpy as np @@ -725,6 +705,13 @@ def prepare_depth_values(depth): return values +def depth_displacement_values(depth): + """Convert raw DA3 camera distance to positive outward displacement.""" + import numpy as np + + return 1.0 - np.asarray(depth, dtype=np.float32) + + def camera_plane_bounds( source_object, depth, @@ -1407,18 +1394,19 @@ def build_depth_plane( depth_frames_directory=None, ): source_name = source_object.name - depth_arrays = extract_depth_arrays(npz_path) - depth = depth_arrays[0] + raw_depth_arrays = extract_depth_arrays(npz_path) + raw_depth = raw_depth_arrays[0] intrinsics = extract_intrinsics_array(npz_path) - stored_reference_depth = extract_reference_depth(npz_path) - depth_values = prepare_depth_values(depth) + raw_depth_values = prepare_depth_values(raw_depth) bounds, reference_depth = camera_plane_bounds( source_object, - depth_values, + raw_depth_values, intrinsics, DISPLACEMENT_STRENGTH, - reference_depth=stored_reference_depth, ) + depth_arrays = [ + depth_displacement_values(frame) for frame in raw_depth_arrays + ] depth_name = depth_name or depth_data_name(source_object) frame_count = len(depth_arrays) foreground_image = ( diff --git a/src/snapform/worker.py b/src/snapform/worker.py index eb493a1..92acc6d 100644 --- a/src/snapform/worker.py +++ b/src/snapform/worker.py @@ -36,7 +36,6 @@ HF_ENDPOINT = "https://huggingface.co" MODELSCOPE_ENDPOINT = "https://modelscope.cn" MODELSCOPE_REVISION = "master" MODELSCOPE_TIMEOUT = 60.0 -REFERENCE_DEPTH_KEY = "snapform_reference_depth" class TaskCancelled(RuntimeError): @@ -48,37 +47,6 @@ def check_cancelled(cancel_check): raise TaskCancelled("Task cancelled") -def convert_ai_depth_for_displacement(prediction): - """Convert DA3 distance into Blender's positive displacement direction.""" - import numpy as np - - prediction.depth = 1.0 - np.asarray(prediction.depth) - - -def depth_reference_value(depth): - """Return the unmasked depth used to size the imported camera plane.""" - import numpy as np - - values = np.asarray(depth) - valid = np.isfinite(values) & (values > 0.0) - if not valid.any(): - raise ValueError("Depth array contains no positive finite values") - return float(np.median(values[valid])) - - -def write_npz_reference_depth(npz_path, reference_depth): - """Add SnapForm metadata without changing exported prediction arrays.""" - import numpy as np - - npz_path = Path(npz_path) - temporary_path = npz_path.with_name(f"{npz_path.stem}.tmp.npz") - with np.load(npz_path, allow_pickle=False) as archive: - values = {key: archive[key] for key in archive.files} - values[REFERENCE_DEPTH_KEY] = np.asarray(reference_depth, dtype=np.float32) - np.savez_compressed(temporary_path, **values) - temporary_path.replace(npz_path) - - def write_status( path, progress, @@ -1640,10 +1608,6 @@ def reconstruct(args, model_cache=None, cancel_check=None): ref_view_strategy=args.ref_view_strategy, ) check_cancelled(cancel_check) - reference_depth = None - if args.export_format == "mini_npz": - reference_depth = depth_reference_value(prediction.depth[0]) - convert_ai_depth_for_displacement(prediction) write_status(args.status, 0.88, f"Exporting {args.export_format}") if args.export_format == "mesh": export_textured_mesh_glb( @@ -1701,10 +1665,6 @@ def reconstruct(args, model_cache=None, cancel_check=None): result_paths, cancel_check=cancel_check, ) - if args.export_format == "mini_npz": - result_path = output_directory / "results.npz" - if reference_depth is not None: - write_npz_reference_depth(result_path, reference_depth) check_cancelled(cancel_check) copy_frames(images, output_directory) write_status( diff --git a/tests/test_image_depth.py b/tests/test_image_depth.py index 34a36ee..75f3932 100644 --- a/tests/test_image_depth.py +++ b/tests/test_image_depth.py @@ -87,21 +87,6 @@ class ImageDepthTest(unittest.TestCase): self.assertEqual(depth.shape, (2, 3)) - def test_extracts_optional_reference_depth(self): - with tempfile.TemporaryDirectory() as directory: - npz_path = Path(directory) / "results.npz" - np.savez_compressed( - npz_path, - depth=np.ones((1, 2, 2), dtype=np.float32), - snapform_reference_depth=np.float32(2.5), - ) - - reference_depth = self.image_depth.extract_reference_depth( - npz_path - ) - - self.assertEqual(reference_depth, 2.5) - def test_is_animated_image_accepts_movie_and_sequence(self): self.assertTrue( self.image_depth.is_animated_image( @@ -384,6 +369,23 @@ class ImageDepthTest(unittest.TestCase): self.assertEqual(depth.shape, (2, 3)) + def test_raw_da3_depth_is_converted_only_for_displacement(self): + raw_depth = np.array( + ((0.25, 1.0), (1.5, 2.0)), + dtype=np.float32, + ) + + displacement = self.image_depth.depth_displacement_values(raw_depth) + + np.testing.assert_array_equal( + displacement, + np.array(((0.75, 0.0), (-0.5, -1.0)), dtype=np.float32), + ) + np.testing.assert_array_equal( + raw_depth, + np.array(((0.25, 1.0), (1.5, 2.0)), dtype=np.float32), + ) + def test_extracts_camera_intrinsics(self): expected = np.array( ((100.0, 0.0, 50.0), (0.0, 120.0, 40.0), (0.0, 0.0, 1.0)), diff --git a/tests/test_worker.py b/tests/test_worker.py index 5fb434b..c08f723 100644 --- a/tests/test_worker.py +++ b/tests/test_worker.py @@ -157,40 +157,6 @@ class WorkerTest(unittest.TestCase): ) self.assertEqual(args.remove_background_model_dir, "ben2") - def test_ai_depth_is_converted_for_positive_displacement(self): - prediction = SimpleNamespace( - depth=np.array([[[0.25, 1.0], [1.5, 2.0]]]), - conf=np.array([[[0.1, 0.2], [0.3, 0.4]]]), - ) - - self.worker.convert_ai_depth_for_displacement(prediction) - - np.testing.assert_array_equal( - prediction.depth, - [[[0.75, 0.0], [-0.5, -1.0]]], - ) - np.testing.assert_array_equal( - prediction.conf, - [[[0.1, 0.2], [0.3, 0.4]]], - ) - - def test_npz_reference_depth_preserves_prediction_arrays(self): - with tempfile.TemporaryDirectory() as directory: - npz_path = Path(directory) / "results.npz" - depth = np.array([[[1.0, 2.0]]], dtype=np.float32) - confidence = np.array([[[0.2, 0.8]]], dtype=np.float32) - np.savez_compressed(npz_path, depth=depth, conf=confidence) - - self.worker.write_npz_reference_depth(npz_path, 1.5) - - with np.load(npz_path, allow_pickle=False) as archive: - np.testing.assert_array_equal(archive["depth"], depth) - np.testing.assert_array_equal(archive["conf"], confidence) - self.assertEqual( - float(archive[self.worker.REFERENCE_DEPTH_KEY]), - 1.5, - ) - def test_prepares_a_single_image_file(self): with tempfile.TemporaryDirectory() as directory: image_path = Path(directory) / "input.png" @@ -1013,12 +979,9 @@ class WorkerTest(unittest.TestCase): _export_dir, options, ) in export_calls: - expected_depth = ( - -1.0 if export_format == "mini_npz" else 2.0 - ) np.testing.assert_array_equal( _prediction.depth, - np.full((1, 2, 2), expected_depth, dtype=np.float32), + np.full((1, 2, 2), 2.0, dtype=np.float32), ) if export_format == "glb": self.assertEqual(