NODEDC_MISSION_CORE/tests/test_e3_rectified_segmentat...

108 lines
3.5 KiB
Python

from __future__ import annotations
import importlib.util
import math
import sys
from pathlib import Path
from types import ModuleType
import numpy as np
import pytest
WORKER_ROOT = (
Path(__file__).parents[1] / "experiments" / "perception" / "worker"
)
PROFILE_PATH = WORKER_ROOT / "e3_k1_camera1_profile.json"
def _worker_module() -> ModuleType:
path = WORKER_ROOT / "run_e3_rectified_segmentation.py"
sys.path.insert(0, str(WORKER_ROOT))
spec = importlib.util.spec_from_file_location("e3_rectified_segmentation", path)
assert spec is not None and spec.loader is not None
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def test_e3_profile_is_pinned_to_camera1_kb4_and_exact_model() -> None:
worker = _worker_module()
profile, digest = worker._profile(PROFILE_PATH)
assert len(digest) == 64
assert profile["source"]["calibration_slot"] == "camera_1"
assert profile["source"]["distortion_kb4"] == pytest.approx(
[
-0.023164451386679667,
-0.0014974198594105452,
-0.001039213149441563,
-0.000035237331915978814,
]
)
assert profile["model"]["revision"] == "8d6b6d1a3f7b50d441afd7d247c2ed10db186e8f"
assert profile["model"]["files"]["model.safetensors"]["sha256"] == (
"c265da9a74f58f5c3f4826d23ca4ca78beac0b106cca5842beca61580de5b782"
)
def test_kb4_inverse_round_trips_valid_field_angles() -> None:
worker = _worker_module()
profile, _digest = worker._profile(PROFILE_PATH)
coefficients = np.asarray(profile["source"]["distortion_kb4"])
theta = np.linspace(0.0, math.radians(96.4), 512)
squared = theta * theta
distorted = theta * (
1.0
+ coefficients[0] * squared
+ coefficients[1] * squared**2
+ coefficients[2] * squared**3
+ coefficients[3] * squared**4
)
recovered = worker._invert_kb4(distorted, coefficients)
assert recovered == pytest.approx(theta, abs=1e-10)
def test_five_view_rectification_covers_the_k1_valid_circle() -> None:
worker = _worker_module()
profile, _digest = worker._profile(PROFILE_PATH)
width, height = profile["source"]["resolution"]
_fx, _fy, cx, cy = profile["source"]["intrinsic_fx_fy_cx_cy"]
y, x = np.mgrid[:height, :width]
valid_mask = np.hypot(x - cx, y - cy) <= 293.0
maps = worker._rectification_maps(profile, valid_mask)
assert maps["coverage"]["coverage_fraction"] == 1.0
assert maps["coverage"]["covered_pixel_count"] == int(valid_mask.sum())
assert maps["coverage"]["overlap_count"]["min"] >= 1
assert maps["coverage"]["overlap_count"]["max"] <= 3
def test_tile_fusion_uses_the_selected_view_and_masks_outside_fov() -> None:
worker = _worker_module()
valid_mask = np.asarray([[True, True], [False, True]])
maps = {
"selected_tile": np.asarray([[0, 1], [-1, 1]], dtype=np.int8),
"tiles": [
{
"tile_map_x": np.zeros((2, 2), dtype=np.float32),
"tile_map_y": np.zeros((2, 2), dtype=np.float32),
},
{
"tile_map_x": np.ones((2, 2), dtype=np.float32),
"tile_map_y": np.ones((2, 2), dtype=np.float32),
},
],
}
semantics = [
np.asarray([[4, 4], [4, 4]], dtype=np.uint8),
np.asarray([[7, 7], [7, 7]], dtype=np.uint8),
]
result = worker._fuse_tiles(semantics, maps, valid_mask)
assert result.tolist() == [[4, 7], [0, 7]]