Files
AnyImage/experiments/panorama_surface/test_geometry.py
nan 27ca25224a feat: Implement depth surface strip cleanup and organize tool CLI
- Added a proposal for depth surface strip cleanup, detailing the rationale and changes to the depth plane and cutout nodes.
- Created specifications for the new cleanup requirements, including scenarios for strip removal and boundary edge detection.
- Developed tasks for implementing shared strip detection logic and integrating new interfaces for depth nodes.
- Established a new CLI structure for organizing node groups and model commands, replacing old entry points with a more intuitive command structure.
- Introduced a prototype for panorama surface generation, including requirements for distance reconstruction and geometry node surfaces.
- Added comprehensive tests for depth strip cleanup functionality, ensuring correct behavior for various mesh topologies and edge cases.
2026-09-10 00:53:43 +08:00

94 lines
3.7 KiB
Python

"""Behavior checks with independent spherical and room geometry references."""
import numpy as np
from geometry import (camera_bases, merge_distances, panorama_directions,
room_reference, sample_panorama, view_rays)
from prototype import fixed_fov_distance
def test_fixed_fov_recovers_shift_and_metric_distance():
rays = view_rays(64)
depth = 2 + 0.3 * rays[..., 0]
points = rays * depth[..., None]
points[..., 2] -= 0.7
distance, mask = fixed_fov_distance(points, np.ones((64, 64)), 1.5)
np.testing.assert_allclose(distance, depth * np.linalg.norm(rays, axis=-1) * 1.5, rtol=1e-5)
assert mask.all()
def test_longitude_sampling_wraps_without_a_seam():
directions = panorama_directions(256, 128)
image = 2 + directions[..., 0]
rays = np.array(((1, 1e-8, 0), (1, -1e-8, 0)))
sampled = sample_panorama(image, rays)
np.testing.assert_allclose(sampled[0], sampled[1], atol=1e-6)
np.testing.assert_allclose(sampled, 3, atol=0.001)
def test_fusion_removes_per_view_scale_offsets():
bases = camera_bases()
scales = np.exp(np.linspace(-0.4, 0.4, 12))
distances = []
for scale, basis in zip(scales, bases):
rays = view_rays(128) @ basis
rays /= np.linalg.norm(rays, axis=-1, keepdims=True)
distances.append((3 + 0.4 * rays[..., 0] + 0.2 * rays[..., 2]) * scale)
merged, mask = merge_distances(distances, np.ones((12, 128, 128), bool), bases, 64, 32)
rays = panorama_directions(64, 32)
expected = 3 + 0.4 * rays[..., 0] + 0.2 * rays[..., 2]
merged *= np.median(expected / merged)
assert mask.all()
assert np.mean(np.abs(merged / expected - 1)) < 0.002
assert np.max(np.abs(merged[:, [0, -1]] / expected[:, [0, -1]] - 1)) < 0.005
def test_room_distance_lands_on_floor():
rays = np.array(((0.0, 0.0, -1.0), (0.2, -0.3, -1.0)))
rays /= np.linalg.norm(rays, axis=-1, keepdims=True)
distance, _ = room_reference(rays)
np.testing.assert_allclose((rays * distance[:, None])[:, 2], -1.6)
def test_sky_view_returns_invalid_samples():
distance, mask = fixed_fov_distance(np.ones((32, 32, 3)), np.zeros((32, 32)), 1)
assert not mask.any()
assert np.isfinite(distance).all()
def test_room_projection_fusion_preserves_geometry():
bases = camera_bases()
distances = [room_reference(view_rays(256) @ basis)[0] for basis in bases]
merged, mask = merge_distances(distances, np.ones((12, 256, 256), bool), bases, 128, 64)
expected, _ = room_reference(panorama_directions(128, 64))
assert mask.all()
assert np.mean(np.abs(merged / expected - 1)) < 0.005
def test_input_alpha_survives_panorama_export(tmp_path, monkeypatch):
from PIL import Image
from prototype import main
rgba = np.full((16, 32, 4), 255, dtype=np.uint8)
rgba[:, :16, 3] = 0
source = tmp_path / "source.png"
destination = tmp_path / "result"
Image.fromarray(rgba).save(source)
monkeypatch.setattr("sys.argv", ["prototype", "--image", str(source), "--output", str(destination),
"--reference-only", "--size", "32", "--width", "32"])
main()
with Image.open(destination / "panorama.png") as exported:
np.testing.assert_array_equal(np.asarray(exported)[..., 3], rgba[..., 3])
with np.load(destination / "prediction.npz") as data:
assert np.all(data["alpha"][:, :16] == 0)
assert np.any(data["alpha"][:, 16:] > 0)
def test_depth_alpha_combines_mask_and_source_alpha_once():
from prototype import depth_alpha
image = np.ones((2, 4, 4), dtype=np.float32)
image[..., 3] = (0, 0.5, 0.75, 1)
mask = np.full((2, 4), 0.5, dtype=np.float32)
np.testing.assert_allclose(depth_alpha(image, mask), np.tile((0, 0.25, 0.375, 0.5), (2, 1)))