From 0c614b63acce0fdc76a56eb1544d77a359e7ec88 Mon Sep 17 00:00:00 2001 From: OlafenwaMoses Date: Sun, 3 May 2026 01:20:42 +0100 Subject: [PATCH 1/7] DepthEstimation advanced config for imrpoved results --- docs/api/lifting.md | 8 + docs/features/depth_estimation.md | 34 +- .../depth_estimation_advanced_config.md | 339 +++++++++++++++++ tests/integration/test_direct.py | 56 ++- tests/integration/test_grpc.py | 39 ++ tests/integration/test_rest.py | 45 +++ tests/unit/test_advanced_config.py | 355 ++++++++++++++++++ vizion3d/lifting/__init__.py | 27 +- vizion3d/lifting/commands.py | 13 +- vizion3d/lifting/handlers.py | 47 ++- vizion3d/lifting/models.py | 31 ++ vizion3d/proto/__init__.py | 7 + vizion3d/proto/lifting.proto | 10 + vizion3d/proto/lifting_pb2.py | 26 +- vizion3d/proto/lifting_pb2_grpc.py | 16 +- vizion3d/server/grpc/server.py | 21 ++ vizion3d/server/rest/app.py | 17 + 17 files changed, 1045 insertions(+), 46 deletions(-) create mode 100644 docs/features/depth_estimation_advanced_config.md create mode 100644 tests/unit/test_advanced_config.py diff --git a/docs/api/lifting.md b/docs/api/lifting.md index e46aa58..521509d 100644 --- a/docs/api/lifting.md +++ b/docs/api/lifting.md @@ -20,6 +20,14 @@ Input contract for the depth estimation task. All inference parameters are decla --- +## DepthEstimationAdvanceConfig + +Camera intrinsics and depth range settings. Pass an instance of this model as `advanced_config` on `DepthEstimationCommand` to override the PrimeSense defaults used for point cloud unprojection. + +::: vizion3d.lifting.models.DepthEstimationAdvanceConfig + +--- + ## DepthEstimationResult Output contract returned by `DepthEstimation.run()`. All fields are always present; optional geometry fields are `None` when the corresponding `return_*` flag was not set. diff --git a/docs/features/depth_estimation.md b/docs/features/depth_estimation.md index 1e3da1c..dfa1d53 100644 --- a/docs/features/depth_estimation.md +++ b/docs/features/depth_estimation.md @@ -32,6 +32,7 @@ Set `VIZION3D_MODEL_CACHE` in your environment to change the default cache direc | `return_depth_image` | `bool` | No | `False` | If `True`, the result includes a 16-bit grayscale Open3D Image of the depth map. | | `return_point_cloud` | `bool` | No | `False` | If `True`, the result includes an Open3D PointCloud unprojected from the RGB-D image. | | `return_mesh` | `bool` | No | `False` | If `True`, the result includes an Open3D TriangleMesh reconstructed from the point cloud via ball-pivoting. | +| `advanced_config` | `DepthEstimationAdvanceConfig` | No | PrimeSense defaults | Camera intrinsics and depth range settings. See [Advanced config](#10-advanced-config-camera-intrinsics--depth-range) below. | --- @@ -46,7 +47,7 @@ Set `VIZION3D_MODEL_CACHE` in your environment to change the default cache direc | `max_depth` | `float` | Yes | Maximum value in `depth_map`. Guaranteed `max_depth >= min_depth`. | | `backend_used` | `str` | Yes | Resolved model identifier that processed the request (local file path). | | `depth_image` | `open3d.geometry.Image \| None` | When `return_depth_image=True` | 16-bit grayscale image, dtype `uint16`, shape `(H, W)`. The full 0–65535 range maps to `[min_depth, max_depth]`. | -| `point_cloud` | `open3d.geometry.PointCloud \| None` | When `return_point_cloud=True` | Coloured 3D point cloud unprojected from the RGB-D image using PrimeSense default intrinsics. Coordinates are in metres. | +| `point_cloud` | `open3d.geometry.PointCloud \| None` | When `return_point_cloud=True` | Coloured 3D point cloud unprojected from the RGB-D image using the intrinsics in `advanced_config`. Coordinates are in metres. | | `mesh` | `open3d.geometry.TriangleMesh \| None` | When `return_mesh=True` | Triangle mesh surface reconstructed from the point cloud via ball-pivoting. Includes vertex colours. | | `point_cloud_scale` | `float` | Yes | Scale factor: multiply any distance measured between two points in the point cloud by this value to get the equivalent distance in metres. Always `1.0` — Open3D produces point cloud coordinates directly in metres. | @@ -294,9 +295,38 @@ print(f"Backend : {response.backend_used}") --- +## 10. Advanced config: camera intrinsics & depth range + +`DepthEstimationAdvanceConfig` lets you supply the actual camera intrinsics and depth range for your sensor, replacing the built-in PrimeSense defaults. This is required for accurate metric 3D geometry when your camera is not a 640×480 PrimeSense sensor. + +```python +from vizion3d.lifting import ( + DepthEstimation, + DepthEstimationAdvanceConfig, + DepthEstimationCommand, +) + +result = DepthEstimation().run( + DepthEstimationCommand( + image_input="scene.png", + return_point_cloud=True, + advanced_config=DepthEstimationAdvanceConfig( + fx=909.15, + fy=908.48, + cx=640.0, + cy=360.0, + depth_trunc=6.0, + ), + ) +) +``` + +The same config is available in the REST and gRPC entry points. See [Advanced Config](depth_estimation_advanced_config.md) for the full field reference, formulas, entry-point examples, and camera presets. + +--- + ## Known limitations - **Relative depth only** — the default monocular backend produces relative (inverse) depth, not metric depth. Point cloud distances are internally consistent but not calibrated to real-world scale without a known reference distance. -- **Fixed camera intrinsics** — point cloud unprojection uses `PrimeSenseDefault` (640×480) intrinsics regardless of input image resolution. For accurate metric geometry, supply real camera intrinsics. - **Ball-pivoting mesh quality** — the mesh reconstructor works best on dense, evenly sampled point clouds. Sparse or noisy clouds may produce gaps or missing faces. - **Python 3.12 required for Open3D** — `return_depth_image`, `return_point_cloud`, and `return_mesh` require Open3D, which currently only supports Python 3.12 in this project. diff --git a/docs/features/depth_estimation_advanced_config.md b/docs/features/depth_estimation_advanced_config.md new file mode 100644 index 0000000..c332c43 --- /dev/null +++ b/docs/features/depth_estimation_advanced_config.md @@ -0,0 +1,339 @@ +# Advanced Config: Camera Intrinsics & Depth Range + +`DepthEstimationAdvanceConfig` lets you override the camera intrinsics and depth range parameters that control how a raw depth map is lifted into a 3D point cloud. Without it, vizion3d uses built-in PrimeSense defaults; with it, you can match your actual camera and scene requirements precisely. + +--- + +## Background: the pinhole camera model + +Every point in a point cloud is computed by inverting the pinhole camera projection. Given a pixel at image coordinates `(u, v)` with a depth value `d` (in metres), its 3D position `(X, Y, Z)` is: + +``` +Z = d +X = (u - cx) * d / fx +Y = (v - cy) * d / fy +``` + +All four intrinsic parameters — `fx`, `fy`, `cx`, `cy` — appear in this formula. Getting them wrong produces a point cloud that is geometrically distorted: correct topology but wrong angles, skewed shapes, or objects that appear compressed or stretched. + +--- + +## Config fields + +### `fx` — horizontal focal length (pixels) + +**Default:** `525.0` + +The horizontal focal length of the camera in pixels. It is the product of the physical focal length (mm) and the horizontal pixel density (pixels/mm). A larger `fx` means the camera has a narrower horizontal field of view; the same scene width maps to fewer pixels. + +**Effect on the point cloud:** `fx` controls the horizontal spread of 3D points. If `fx` is too small, the point cloud is horizontally compressed. If too large, it is horizontally stretched. + +**How to find it:** Use your camera's calibration matrix `K[0][0]`, or compute it from the horizontal field of view `FoV_h`: + +``` +fx = (image_width / 2) / tan(FoV_h / 2) +``` + +--- + +### `fy` — vertical focal length (pixels) + +**Default:** `525.0` + +The vertical focal length in pixels. For cameras with square pixels, `fy ≈ fx`. Cameras with non-square sensors may have `fy ≠ fx`. + +**Effect on the point cloud:** Controls vertical spread analogously to `fx`. Incorrect `fy` produces vertically compressed or stretched geometry. + +**How to find it:** `K[1][1]` from the calibration matrix, or: + +``` +fy = (image_height / 2) / tan(FoV_v / 2) +``` + +--- + +### `cx` — horizontal principal point (pixels) + +**Default:** `319.5` + +The horizontal image coordinate of the optical axis — ideally the exact centre of the sensor. For a 640-wide image the ideal value is `319.5`; for a 1920-wide image it is typically near `959.5`. + +**Effect on the point cloud:** Shifts the entire point cloud left or right. A wrong `cx` makes the scene appear to be viewed from an off-centre vantage point, introducing a lateral tilt. + +--- + +### `cy` — vertical principal point (pixels) + +**Default:** `239.5` + +The vertical image coordinate of the optical axis. For a 480-tall image the ideal value is `239.5`. + +**Effect on the point cloud:** Shifts the entire point cloud up or down. Like `cx`, an incorrect value introduces a tilt — vertical in this case. + +--- + +### `depth_scale` — depth value scale factor + +**Default:** `1000.0` + +The divisor applied to the raw uint16 depth buffer before passing depth values to Open3D's `RGBDImage.create_from_color_and_depth`. Open3D divides the stored integer depth by `depth_scale` to obtain a value in metres. The default of `1000.0` means the uint16 range `[0, 65535]` maps to `[0, 65.535]` metres. + +**Effect on the point cloud:** Changing `depth_scale` rescales all Z values (and therefore X/Y values, since `X = (u - cx) * Z / fx`). Doubling `depth_scale` halves all distances. This does **not** change the relative shape of the cloud — only the metric scale. + +**When to adjust:** Only change this if you are supplying a depth buffer in a different unit (e.g. centimetres instead of millimetres). In vizion3d the depth map is internally normalised before being encoded into uint16, so the default `1000.0` is correct for the standard workflow. + +--- + +### `depth_trunc` — maximum depth clip distance (metres) + +**Default:** `10.0` + +Points with a depth value greater than `depth_trunc` metres are discarded by Open3D before building the point cloud. This controls the far clipping plane. + +**Effect on the point cloud:** Lowering `depth_trunc` removes distant background points and produces a denser, cleaner cloud for near objects. Setting it to a very small value will discard almost all points. Setting it too large can include noisy, low-confidence depth estimates at the scene boundary. + +**Practical guidance:** +- Indoor close-up scenes: `2.0–5.0` m +- Room-scale scenes: `5.0–10.0` m (default) +- Outdoor or large-scale: `10.0–30.0` m + +--- + +## Default values and PrimeSense + +The built-in defaults match the **PrimeSense / Microsoft Kinect v1** sensor at 640×480 VGA resolution: + +| Parameter | Default | PrimeSense VGA | +|---|---|---| +| `fx` | `525.0` | 525.0 px | +| `fy` | `525.0` | 525.0 px | +| `cx` | `319.5` | 319.5 px | +| `cy` | `239.5` | 239.5 px | +| `depth_scale` | `1000.0` | — | +| `depth_trunc` | `10.0` | — | + +These are reasonable placeholders for any RGB camera with a ~60° horizontal FoV. For accurate metric reconstruction, always supply intrinsics from your actual camera calibration. + +--- + +## Usage: Direct Python + +```python +from vizion3d.lifting import ( + DepthEstimation, + DepthEstimationAdvanceConfig, + DepthEstimationCommand, +) + +# Full custom intrinsics (e.g. Intel RealSense D435 at 1280×720) +config = DepthEstimationAdvanceConfig( + fx=909.15, + fy=908.48, + cx=640.0, + cy=360.0, + depth_scale=1000.0, + depth_trunc=6.0, +) + +with open("scene.png", "rb") as f: + img_bytes = f.read() + +result = DepthEstimation().run( + DepthEstimationCommand( + image_input=img_bytes, + return_point_cloud=True, + advanced_config=config, + ) +) + +import numpy as np +points = np.asarray(result.point_cloud.points) +print(f"Points: {len(points)}") +``` + +Partial overrides work too — unspecified fields keep their defaults: + +```python +# Only change depth_trunc; everything else stays at PrimeSense defaults +result = DepthEstimation().run( + DepthEstimationCommand( + image_input=img_bytes, + return_point_cloud=True, + advanced_config=DepthEstimationAdvanceConfig(depth_trunc=3.0), + ) +) +``` + +--- + +## Usage: REST API + +All six config parameters are optional form fields on the `POST /lifting/depth-estimation` endpoint. + +```bash +# Full custom intrinsics +curl -X POST "http://localhost:8000/lifting/depth-estimation" \ + -F "image=@scene.png" \ + -F "return_point_cloud=true" \ + -F "fx=909.15" \ + -F "fy=908.48" \ + -F "cx=640.0" \ + -F "cy=360.0" \ + -F "depth_scale=1000.0" \ + -F "depth_trunc=6.0" +``` + +Partial overrides — omit any field to keep its default: + +```bash +# Only override depth_trunc +curl -X POST "http://localhost:8000/lifting/depth-estimation" \ + -F "image=@scene.png" \ + -F "return_point_cloud=true" \ + -F "depth_trunc=3.0" +``` + +Python `requests` equivalent: + +```python +import requests + +with open("scene.png", "rb") as f: + img_bytes = f.read() + +response = requests.post( + "http://localhost:8000/lifting/depth-estimation", + files={"image": ("scene.png", img_bytes, "image/png")}, + data={ + "return_point_cloud": "true", + "fx": "909.15", + "fy": "908.48", + "cx": "640.0", + "cy": "360.0", + "depth_trunc": "6.0", + }, +) +data = response.json() +print(f"Depth range: {data['min_depth']:.4f} → {data['max_depth']:.4f}") +``` + +--- + +## Usage: gRPC API + +The `DepthEstimationAdvanceConfig` proto message mirrors the Python model. All fields are `optional`, so any omitted field falls back to the server-side default. + +```python +import grpc +from vizion3d.proto import lifting_pb2, lifting_pb2_grpc + +channel = grpc.insecure_channel("localhost:50051") +stub = lifting_pb2_grpc.LiftingServiceStub(channel) + +with open("scene.png", "rb") as f: + img_bytes = f.read() + +# Full custom intrinsics +request = lifting_pb2.DepthEstimationRequest( + image_bytes=img_bytes, + return_point_cloud=True, + advanced_config=lifting_pb2.DepthEstimationAdvanceConfig( + fx=909.15, + fy=908.48, + cx=640.0, + cy=360.0, + depth_scale=1000.0, + depth_trunc=6.0, + ), +) +response = stub.RunDepthEstimation(request) +print(f"Depth range: {response.min_depth:.4f} → {response.max_depth:.4f}") +``` + +Partial override — only `depth_trunc`: + +```python +request = lifting_pb2.DepthEstimationRequest( + image_bytes=img_bytes, + return_point_cloud=True, + advanced_config=lifting_pb2.DepthEstimationAdvanceConfig(depth_trunc=3.0), +) +response = stub.RunDepthEstimation(request) +``` + +--- + +## How to get your camera intrinsics + +### Option 1: camera datasheet or SDK + +Most camera SDKs expose the intrinsic matrix directly: + +```python +# Intel RealSense +import pyrealsense2 as rs +pipeline = rs.pipeline() +profile = pipeline.start() +intr = profile.get_stream(rs.stream.color).as_video_stream_profile().intrinsics +config = DepthEstimationAdvanceConfig( + fx=intr.fx, fy=intr.fy, cx=intr.ppx, cy=intr.ppy +) +``` + +### Option 2: OpenCV calibration + +Run a standard checkerboard calibration with `cv2.calibrateCamera`. The returned `camera_matrix` is: + +``` +[[fx, 0, cx], + [ 0, fy, cy], + [ 0, 0, 1]] +``` + +```python +import cv2 +import numpy as np + +# After calibrating… +_, camera_matrix, _, _, _ = cv2.calibrateCamera(obj_points, img_points, image_size, None, None) + +config = DepthEstimationAdvanceConfig( + fx=float(camera_matrix[0, 0]), + fy=float(camera_matrix[1, 1]), + cx=float(camera_matrix[0, 2]), + cy=float(camera_matrix[1, 2]), +) +``` + +### Option 3: approximate from field of view + +If you know the camera's horizontal field of view `FoV_h` (in degrees) and image dimensions: + +```python +import math + +image_width = 1920 +image_height = 1080 +fov_h_deg = 69.0 # horizontal FoV in degrees + +fx = (image_width / 2) / math.tan(math.radians(fov_h_deg / 2)) +fy = fx # assumes square pixels +cx = image_width / 2 - 0.5 +cy = image_height / 2 - 0.5 + +config = DepthEstimationAdvanceConfig(fx=fx, fy=fy, cx=cx, cy=cy) +``` + +--- + +## Common camera presets + +These are approximate values for common cameras. Always prefer calibrated values over these presets. + +| Camera | Resolution | fx | fy | cx | cy | +|---|---|---|---|---|---| +| PrimeSense / Kinect v1 | 640×480 | 525.0 | 525.0 | 319.5 | 239.5 | +| Intel RealSense D415 | 1920×1080 | 1382.0 | 1382.0 | 960.5 | 540.5 | +| Intel RealSense D435 | 1280×720 | 909.0 | 908.0 | 640.0 | 360.0 | +| iPhone 14 wide (approx.) | 4032×3024 | 5500.0 | 5500.0 | 2016.0 | 1512.0 | +| Webcam 1080p (typical) | 1920×1080 | 1400.0 | 1400.0 | 960.0 | 540.0 | diff --git a/tests/integration/test_direct.py b/tests/integration/test_direct.py index ad7ad78..c37ca42 100644 --- a/tests/integration/test_direct.py +++ b/tests/integration/test_direct.py @@ -22,7 +22,11 @@ pytest.importorskip("open3d", reason="open3d required — run: uv python pin 3.12 && uv sync") -from vizion3d.lifting import DepthEstimation, DepthEstimationCommand # noqa: E402 +from vizion3d.lifting import ( # noqa: E402 + DepthEstimation, + DepthEstimationAdvanceConfig, + DepthEstimationCommand, +) from vizion3d.lifting.defaults import DEFAULT_DEPTH_MODEL_URL # noqa: E402 from vizion3d.lifting.handlers import DepthEstimationHandler # noqa: E402 from vizion3d.lifting.utils import create_ply_binary # noqa: E402 @@ -140,3 +144,53 @@ def test_direct_local_model( scenario="Local model", timing_collector=timing_collector, ) + + +def test_direct_advanced_config_custom_intrinsics(indoor_image_bytes, local_model_path): + """Custom fx/fy/cx/cy produce a valid point cloud without errors.""" + DepthEstimationHandler._depth_anything_models.clear() + result = DepthEstimation().run( + DepthEstimationCommand( + image_input=indoor_image_bytes, + model_backend=local_model_path, + return_point_cloud=True, + advanced_config=DepthEstimationAdvanceConfig( + fx=615.0, fy=615.0, cx=320.0, cy=240.0 + ), + ) + ) + assert isinstance(result.depth_map, list) and len(result.depth_map) > 0 + assert result.point_cloud is not None + assert result.point_cloud.has_points() + + +def test_direct_advanced_config_tight_depth_trunc_yields_fewer_points( + indoor_image_bytes, local_model_path +): + """A very tight depth_trunc maps depth values to near-zero → fewer/no points.""" + DepthEstimationHandler._depth_anything_models.clear() + + default_result = DepthEstimation().run( + DepthEstimationCommand( + image_input=indoor_image_bytes, + model_backend=local_model_path, + return_point_cloud=True, + ) + ) + + tight_result = DepthEstimation().run( + DepthEstimationCommand( + image_input=indoor_image_bytes, + model_backend=local_model_path, + return_point_cloud=True, + advanced_config=DepthEstimationAdvanceConfig(depth_trunc=0.0001), + ) + ) + + import numpy as np + default_pts = len(np.asarray(default_result.point_cloud.points)) + tight_pts = len(np.asarray(tight_result.point_cloud.points)) + assert tight_pts < default_pts, ( + f"Expected tight depth_trunc to yield fewer points " + f"({tight_pts} vs default {default_pts})" + ) diff --git a/tests/integration/test_grpc.py b/tests/integration/test_grpc.py index acb18b1..7880460 100644 --- a/tests/integration/test_grpc.py +++ b/tests/integration/test_grpc.py @@ -138,3 +138,42 @@ def test_grpc_local_model( grpc_client_stub=grpc_client_stub, timing_collector=timing_collector, ) + + +def test_grpc_advanced_config_custom_intrinsics_accepted( + indoor_image_bytes, local_model_path, grpc_client_stub +): + """Custom fx/fy/cx/cy in the proto config are accepted and produce a valid response.""" + DepthEstimationHandler._depth_anything_models.clear() + + request = lifting_pb2.DepthEstimationRequest( + image_bytes=indoor_image_bytes, + model_backend=local_model_path, + return_point_cloud=True, + advanced_config=lifting_pb2.DepthEstimationAdvanceConfig( + fx=615.0, fy=615.0, cx=320.0, cy=240.0, + ), + ) + response = grpc_client_stub.RunDepthEstimation(request) + + assert len(response.depth_map) > 0 + assert response.max_depth >= response.min_depth + assert len(response.point_cloud_ply) > 0 + assert response.point_cloud_ply.startswith(b"ply\n") + + +def test_grpc_advanced_config_partial_override_accepted( + indoor_image_bytes, local_model_path, grpc_client_stub +): + """A proto config with only depth_trunc set is accepted without errors.""" + DepthEstimationHandler._depth_anything_models.clear() + + request = lifting_pb2.DepthEstimationRequest( + image_bytes=indoor_image_bytes, + model_backend=local_model_path, + advanced_config=lifting_pb2.DepthEstimationAdvanceConfig(depth_trunc=5.0), + ) + response = grpc_client_stub.RunDepthEstimation(request) + + assert len(response.depth_map) > 0 + assert response.max_depth >= response.min_depth diff --git a/tests/integration/test_rest.py b/tests/integration/test_rest.py index 6f6f2e7..8ec3914 100644 --- a/tests/integration/test_rest.py +++ b/tests/integration/test_rest.py @@ -142,3 +142,48 @@ def test_rest_local_model( scenario="Local model", timing_collector=timing_collector, ) + + +def test_rest_advanced_config_custom_intrinsics_accepted( + indoor_image_bytes, local_model_path +): + """Custom fx/fy/cx/cy form fields are accepted and produce a valid response.""" + from vizion3d.lifting.handlers import DepthEstimationHandler + DepthEstimationHandler._depth_anything_models.clear() + + response = client.post( + "/lifting/depth-estimation", + files={"image": ("scene.jpg", indoor_image_bytes, "image/jpeg")}, + data={ + "model_backend": local_model_path, + "return_point_cloud": "true", + "fx": "615.0", + "fy": "615.0", + "cx": "320.0", + "cy": "240.0", + }, + ) + assert response.status_code == 200 + data = response.json() + assert isinstance(data["depth_map"], list) and len(data["depth_map"]) > 0 + assert data["point_cloud_ply"] is not None + assert base64.b64decode(data["point_cloud_ply"]).startswith(b"ply\n") + + +def test_rest_advanced_config_custom_depth_trunc_accepted( + indoor_image_bytes, local_model_path +): + """Custom depth_trunc form field is accepted without errors.""" + from vizion3d.lifting.handlers import DepthEstimationHandler + DepthEstimationHandler._depth_anything_models.clear() + + response = client.post( + "/lifting/depth-estimation", + files={"image": ("scene.jpg", indoor_image_bytes, "image/jpeg")}, + data={ + "model_backend": local_model_path, + "depth_trunc": "5.0", + }, + ) + assert response.status_code == 200 + assert response.json()["max_depth"] >= response.json()["min_depth"] diff --git a/tests/unit/test_advanced_config.py b/tests/unit/test_advanced_config.py new file mode 100644 index 0000000..02ad122 --- /dev/null +++ b/tests/unit/test_advanced_config.py @@ -0,0 +1,355 @@ +""" +Unit tests for DepthEstimationAdvanceConfig and its propagation through +the command, handler, REST API, and gRPC server. +""" + +import io +from unittest.mock import MagicMock, patch + +import numpy as np +import pytest +from PIL import Image + +from vizion3d.lifting.commands import DepthEstimationCommand +from vizion3d.lifting.handlers import DepthEstimationHandler +from vizion3d.lifting.models import DepthEstimationAdvanceConfig + +# ── Fixtures ────────────────────────────────────────────────────────────────── + +@pytest.fixture +def fake_depth(): + rng = np.random.default_rng(0) + return rng.uniform(0.5, 3.0, (100, 100)) + + +# ── DepthEstimationAdvanceConfig ────────────────────────────────────────────── + +class TestDepthEstimationAdvanceConfig: + def test_defaults_match_primesense(self): + cfg = DepthEstimationAdvanceConfig() + assert cfg.fx == 525.0 + assert cfg.fy == 525.0 + assert cfg.cx == 319.5 + assert cfg.cy == 239.5 + assert cfg.depth_scale == 1000.0 + assert cfg.depth_trunc == 10.0 + + def test_partial_override_keeps_other_defaults(self): + cfg = DepthEstimationAdvanceConfig(fx=615.0, fy=615.0) + assert cfg.fx == 615.0 + assert cfg.fy == 615.0 + assert cfg.cx == 319.5 + assert cfg.cy == 239.5 + assert cfg.depth_scale == 1000.0 + assert cfg.depth_trunc == 10.0 + + def test_all_fields_overridable(self): + cfg = DepthEstimationAdvanceConfig( + fx=700.0, fy=701.0, cx=320.0, cy=241.0, + depth_scale=500.0, depth_trunc=5.0, + ) + assert cfg.fx == 700.0 + assert cfg.fy == 701.0 + assert cfg.cx == 320.0 + assert cfg.cy == 241.0 + assert cfg.depth_scale == 500.0 + assert cfg.depth_trunc == 5.0 + + def test_invalid_type_rejected(self): + with pytest.raises(Exception): + DepthEstimationAdvanceConfig(fx="not_a_number") + + +# ── DepthEstimationCommand advanced_config field ────────────────────────────── + +class TestDepthEstimationCommandAdvancedConfig: + def test_default_advanced_config_is_correct_type(self): + cmd = DepthEstimationCommand(image_input=b"img") + assert isinstance(cmd.advanced_config, DepthEstimationAdvanceConfig) + + def test_default_advanced_config_has_primesense_values(self): + cmd = DepthEstimationCommand(image_input=b"img") + assert cmd.advanced_config.fx == 525.0 + assert cmd.advanced_config.depth_trunc == 10.0 + + def test_each_command_gets_separate_config_instance(self): + cmd1 = DepthEstimationCommand(image_input=b"img") + cmd2 = DepthEstimationCommand(image_input=b"img") + assert cmd1.advanced_config is not cmd2.advanced_config + + def test_mutation_of_one_command_does_not_affect_another(self): + cmd1 = DepthEstimationCommand(image_input=b"img") + cmd2 = DepthEstimationCommand(image_input=b"img") + cmd1.advanced_config.fx = 999.0 + assert cmd2.advanced_config.fx == 525.0 + + def test_custom_config_stored_on_command(self): + cfg = DepthEstimationAdvanceConfig(fx=615.0, depth_trunc=5.0) + cmd = DepthEstimationCommand(image_input=b"img", advanced_config=cfg) + assert cmd.advanced_config.fx == 615.0 + assert cmd.advanced_config.depth_trunc == 5.0 + + +# ── _depth_array_to_rgbd_depth ──────────────────────────────────────────────── + +class TestDepthArrayToRgbdDepth: + def test_output_dtype_is_uint16(self): + arr = np.array([[0.0, 1.0], [2.0, 3.0]], dtype=float) + result = DepthEstimationHandler._depth_array_to_rgbd_depth(arr, 1000.0, 10.0) + assert result.dtype == np.uint16 + + def test_zero_range_input_returns_zeros(self): + arr = np.ones((4, 4), dtype=float) * 3.0 + result = DepthEstimationHandler._depth_array_to_rgbd_depth(arr, 1000.0, 10.0) + assert np.all(result == 0) + + def test_max_value_equals_trunc_times_scale(self): + arr = np.array([[0.0, 1.0]], dtype=float) + result = DepthEstimationHandler._depth_array_to_rgbd_depth(arr, 1000.0, 10.0) + assert result[0, 1] == pytest.approx(10_000, abs=1) + + def test_custom_depth_scale_halves_output(self): + arr = np.array([[0.0, 1.0]], dtype=float) + full = DepthEstimationHandler._depth_array_to_rgbd_depth(arr, 1000.0, 10.0) + half = DepthEstimationHandler._depth_array_to_rgbd_depth(arr, 500.0, 10.0) + assert half[0, 1] == pytest.approx(full[0, 1] / 2, abs=1) + + def test_custom_depth_trunc_halves_output(self): + arr = np.array([[0.0, 1.0]], dtype=float) + full = DepthEstimationHandler._depth_array_to_rgbd_depth(arr, 1000.0, 10.0) + half = DepthEstimationHandler._depth_array_to_rgbd_depth(arr, 1000.0, 5.0) + assert half[0, 1] == pytest.approx(full[0, 1] / 2, abs=1) + + def test_output_clipped_to_uint16_max(self): + arr = np.array([[0.0, 1.0]], dtype=float) + result = DepthEstimationHandler._depth_array_to_rgbd_depth(arr, 1e6, 1e6) + assert result[0, 1] == np.iinfo(np.uint16).max + + def test_min_value_is_always_zero(self): + arr = np.array([[2.0, 5.0, 10.0]], dtype=float) + result = DepthEstimationHandler._depth_array_to_rgbd_depth(arr, 1000.0, 10.0) + assert result[0, 0] == 0 + + +# ── Handler propagates config to Open3D ────────────────────────────────────── + +class TestHandlerPropagatesAdvancedConfig: + def test_custom_intrinsics_forwarded_to_pinhole(self, dummy_image_bytes, fake_depth): + open3d = pytest.importorskip( + "open3d", reason="open3d required — run: uv python pin 3.12 && uv sync" + ) + cfg = DepthEstimationAdvanceConfig(fx=615.0, fy=616.0, cx=321.0, cy=241.0) + captured = [] + original_cls = open3d.camera.PinholeCameraIntrinsic + + def capturing(*args, **kwargs): + captured.append(args) + return original_cls(*args, **kwargs) + + with ( + patch.object( + DepthEstimationHandler, + "_run_depth_anything_checkpoint", + return_value=fake_depth, + ), + patch.object(open3d.camera, "PinholeCameraIntrinsic", side_effect=capturing), + ): + DepthEstimationHandler().handle( + DepthEstimationCommand( + image_input=dummy_image_bytes, + model_backend="/fake/model.pth", + return_point_cloud=True, + advanced_config=cfg, + ) + ) + + assert len(captured) == 1 + _w, _h, fx, fy, cx, cy = captured[0] + assert fx == 615.0 + assert fy == 616.0 + assert cx == 321.0 + assert cy == 241.0 + + def test_custom_depth_scale_trunc_forwarded_to_rgbd(self, dummy_image_bytes, fake_depth): + open3d = pytest.importorskip( + "open3d", reason="open3d required — run: uv python pin 3.12 && uv sync" + ) + cfg = DepthEstimationAdvanceConfig(depth_scale=500.0, depth_trunc=3.0) + captured_kwargs = {} + original_fn = open3d.geometry.RGBDImage.create_from_color_and_depth + + def capturing(*args, **kwargs): + captured_kwargs.update(kwargs) + return original_fn(*args, **kwargs) + + with ( + patch.object( + DepthEstimationHandler, + "_run_depth_anything_checkpoint", + return_value=fake_depth, + ), + patch.object( + open3d.geometry.RGBDImage, + "create_from_color_and_depth", + side_effect=capturing, + ), + ): + DepthEstimationHandler().handle( + DepthEstimationCommand( + image_input=dummy_image_bytes, + model_backend="/fake/model.pth", + return_point_cloud=True, + advanced_config=cfg, + ) + ) + + assert captured_kwargs["depth_scale"] == 500.0 + assert captured_kwargs["depth_trunc"] == 3.0 + + +# ── REST API propagates config form fields ──────────────────────────────────── + +class TestRestAdvancedConfig: + @pytest.fixture(autouse=True) + def _setup(self): + pytest.importorskip( + "open3d", reason="open3d required — run: uv python pin 3.12 && uv sync" + ) + from fastapi.testclient import TestClient + + from vizion3d.server.rest.app import app + self.client = TestClient(app) + + def _post(self, extra_data=None): + img = Image.new("RGB", (50, 50), color="blue") + buf = io.BytesIO() + img.save(buf, format="PNG") + buf.seek(0) + + result = MagicMock() + result.depth_map = [[1.0]] + result.min_depth = 1.0 + result.max_depth = 1.0 + result.backend_used = "/fake/model.pth" + result.depth_image = None + result.point_cloud = None + result.mesh = None + + with patch("vizion3d.server.rest.app.DepthEstimation") as mock_cls: + mock_cls.return_value.run.return_value = result + self.client.post( + "/lifting/depth-estimation", + files={"image": ("test.png", buf, "image/png")}, + data=extra_data or {}, + ) + return mock_cls.return_value.run.call_args[0][0] + + def test_default_config_used_when_no_form_fields_sent(self): + cmd = self._post() + assert cmd.advanced_config.fx == 525.0 + assert cmd.advanced_config.fy == 525.0 + assert cmd.advanced_config.cx == 319.5 + assert cmd.advanced_config.cy == 239.5 + assert cmd.advanced_config.depth_scale == 1000.0 + assert cmd.advanced_config.depth_trunc == 10.0 + + def test_custom_fx_fy_forwarded(self): + cmd = self._post({"fx": "615.0", "fy": "616.0"}) + assert cmd.advanced_config.fx == pytest.approx(615.0) + assert cmd.advanced_config.fy == pytest.approx(616.0) + assert cmd.advanced_config.cx == 319.5 # unchanged + + def test_custom_cx_cy_forwarded(self): + cmd = self._post({"cx": "321.0", "cy": "241.0"}) + assert cmd.advanced_config.cx == pytest.approx(321.0) + assert cmd.advanced_config.cy == pytest.approx(241.0) + + def test_custom_depth_scale_forwarded(self): + cmd = self._post({"depth_scale": "500.0"}) + assert cmd.advanced_config.depth_scale == pytest.approx(500.0) + assert cmd.advanced_config.depth_trunc == 10.0 # unchanged + + def test_custom_depth_trunc_forwarded(self): + cmd = self._post({"depth_trunc": "5.0"}) + assert cmd.advanced_config.depth_trunc == pytest.approx(5.0) + assert cmd.advanced_config.depth_scale == 1000.0 # unchanged + + def test_partial_override_does_not_affect_other_fields(self): + cmd = self._post({"fx": "700.0"}) + assert cmd.advanced_config.fx == pytest.approx(700.0) + assert cmd.advanced_config.fy == 525.0 + assert cmd.advanced_config.depth_trunc == 10.0 + + +# ── gRPC server propagates config proto fields ──────────────────────────────── + +class TestGrpcAdvancedConfig: + @pytest.fixture(autouse=True) + def _setup(self): + pytest.importorskip( + "open3d", reason="open3d required — run: uv python pin 3.12 && uv sync" + ) + from vizion3d.proto import lifting_pb2 + from vizion3d.server.grpc.server import LiftingServiceServicer + self.pb2 = lifting_pb2 + self.servicer = LiftingServiceServicer() + self.context = MagicMock() + + img = Image.new("RGB", (50, 50), color="red") + buf = io.BytesIO() + img.save(buf, format="PNG") + self.image_bytes = buf.getvalue() + + def _run(self, proto_cfg=None): + kwargs = {"image_bytes": self.image_bytes} + if proto_cfg is not None: + kwargs["advanced_config"] = proto_cfg + request = self.pb2.DepthEstimationRequest(**kwargs) + + result = MagicMock() + result.depth_map = [[1.0]] + result.min_depth = 1.0 + result.max_depth = 1.0 + result.backend_used = "/fake/model.pth" + result.depth_image = None + result.point_cloud = None + result.mesh = None + + with patch("vizion3d.server.grpc.server.DepthEstimation") as mock_cls: + mock_cls.return_value.run.return_value = result + self.servicer.RunDepthEstimation(request, self.context) + return mock_cls.return_value.run.call_args[0][0] + + def test_no_config_in_request_uses_defaults(self): + cmd = self._run() + assert cmd.advanced_config.fx == 525.0 + assert cmd.advanced_config.depth_trunc == 10.0 + + def test_full_config_forwarded(self): + proto_cfg = self.pb2.DepthEstimationAdvanceConfig( + fx=615.0, fy=616.0, cx=320.0, cy=241.0, + depth_scale=500.0, depth_trunc=3.0, + ) + cmd = self._run(proto_cfg) + assert cmd.advanced_config.fx == pytest.approx(615.0) + assert cmd.advanced_config.fy == pytest.approx(616.0) + assert cmd.advanced_config.cx == pytest.approx(320.0) + assert cmd.advanced_config.cy == pytest.approx(241.0) + assert cmd.advanced_config.depth_scale == pytest.approx(500.0) + assert cmd.advanced_config.depth_trunc == pytest.approx(3.0) + + def test_partial_config_overrides_only_set_fields(self): + proto_cfg = self.pb2.DepthEstimationAdvanceConfig(fx=700.0, depth_trunc=2.0) + cmd = self._run(proto_cfg) + assert cmd.advanced_config.fx == pytest.approx(700.0) + assert cmd.advanced_config.fy == 525.0 # default + assert cmd.advanced_config.cx == 319.5 # default + assert cmd.advanced_config.depth_scale == 1000.0 # default + assert cmd.advanced_config.depth_trunc == pytest.approx(2.0) + + def test_empty_config_message_uses_all_defaults(self): + proto_cfg = self.pb2.DepthEstimationAdvanceConfig() + cmd = self._run(proto_cfg) + assert cmd.advanced_config.fx == 525.0 + assert cmd.advanced_config.fy == 525.0 + assert cmd.advanced_config.depth_trunc == 10.0 diff --git a/vizion3d/lifting/__init__.py b/vizion3d/lifting/__init__.py index 3da1674..7f8f2da 100644 --- a/vizion3d/lifting/__init__.py +++ b/vizion3d/lifting/__init__.py @@ -2,7 +2,7 @@ from .commands import DepthEstimationCommand from .handlers import DepthEstimationHandler -from .models import DepthEstimationResult +from .models import DepthEstimationAdvanceConfig, DepthEstimationResult # Register handlers on import or application startup register_command_handler(DepthEstimationCommand, DepthEstimationHandler) @@ -17,9 +17,21 @@ class DepthEstimation: Example: ```python - cmd = DepthEstimationCommand(image_input=b"...", return_mesh=True) - task = DepthEstimation() - result = task.run(cmd) + from vizion3d.lifting import ( + DepthEstimation, + DepthEstimationAdvanceConfig, + DepthEstimationCommand, + ) + + cmd = DepthEstimationCommand( + image_input=b"...", + return_point_cloud=True, + return_mesh=True, + advanced_config=DepthEstimationAdvanceConfig( + fx=615.0, fy=615.0, cx=320.0, cy=240.0, depth_trunc=5.0 + ), + ) + result = DepthEstimation().run(cmd) ``` """ @@ -38,4 +50,9 @@ def run(self, command: DepthEstimationCommand) -> DepthEstimationResult: return command_bus.dispatch(command) -__all__ = ["DepthEstimation", "DepthEstimationCommand", "DepthEstimationResult"] +__all__ = [ + "DepthEstimation", + "DepthEstimationAdvanceConfig", + "DepthEstimationCommand", + "DepthEstimationResult", +] diff --git a/vizion3d/lifting/commands.py b/vizion3d/lifting/commands.py index 6528b67..6abe366 100644 --- a/vizion3d/lifting/commands.py +++ b/vizion3d/lifting/commands.py @@ -1,9 +1,9 @@ -from dataclasses import dataclass +from dataclasses import dataclass, field from vizion3d.core.cqrs import Command from .defaults import DEFAULT_DEPTH_MODEL_URL -from .models import DepthEstimationResult +from .models import DepthEstimationAdvanceConfig, DepthEstimationResult @dataclass @@ -30,11 +30,15 @@ class DepthEstimationCommand(Command[DepthEstimationResult]): to the full 0–65535 range. Requires Open3D (Python 3.12). return_point_cloud: When `True`, the result includes an `open3d.geometry.PointCloud` unprojected from the RGB-D image using - PrimeSense default camera intrinsics. Point coordinates are in metres. + the camera intrinsics in `advanced_config`. Point coordinates are in metres. Requires Open3D (Python 3.12). return_mesh: When `True`, the result includes an `open3d.geometry.TriangleMesh` reconstructed from the point cloud via ball-pivoting. Includes vertex colours. Requires Open3D (Python 3.12). + advanced_config: Camera intrinsics and depth range settings. Override any + field to customise — e.g. + ``advanced_config=DepthEstimationAdvanceConfig(fx=615.0, fy=615.0)``. + Unspecified fields keep their defaults (PrimeSense values). """ image_input: str | bytes @@ -42,3 +46,6 @@ class DepthEstimationCommand(Command[DepthEstimationResult]): return_depth_image: bool = False return_point_cloud: bool = False return_mesh: bool = False + advanced_config: DepthEstimationAdvanceConfig = field( + default_factory=DepthEstimationAdvanceConfig + ) diff --git a/vizion3d/lifting/handlers.py b/vizion3d/lifting/handlers.py index a4cc7d6..3c7a0e8 100644 --- a/vizion3d/lifting/handlers.py +++ b/vizion3d/lifting/handlers.py @@ -1,3 +1,4 @@ +import contextlib import io import threading @@ -11,8 +12,10 @@ from .depth_anything import convert_depth_anything_v2_state_dict, depth_anything_v2_config from .models import DepthEstimationResult -RGBD_DEPTH_SCALE = 1000.0 # default: uint16 millimetres (RealSense / Kinect / PrimeSense) -RGBD_DEPTH_TRUNC = 10.0 # default: discard points beyond 10 m +# Legacy module-level constants kept for reference — actual values come from +# DepthEstimationAdvanceConfig on each command. +_DEFAULT_DEPTH_SCALE = 1000.0 +_DEFAULT_DEPTH_TRUNC = 10.0 OPEN3D_CAMERA_TO_IMAGE_VIEW_TRANSFORM = np.array( [ [1.0, 0.0, 0.0, 0.0], @@ -40,7 +43,7 @@ def handle(self, command: DepthEstimationCommand) -> DepthEstimationResult: min_depth = float(np.min(depth_array)) max_depth = float(np.max(depth_array)) - depth_map = depth_array.tolist() + depth_map = depth_array.astype(np.float32).tolist() depth_image = None if command.return_depth_image: @@ -71,21 +74,22 @@ def handle(self, command: DepthEstimationCommand) -> DepthEstimationResult: "Pin to Python 3.12 and run: uv sync" ) + cfg = command.advanced_config color_o3d = o3d.geometry.Image(np.asarray(image).copy()) depth_o3d = o3d.geometry.Image( - self._depth_array_to_rgbd_depth(depth_array) + self._depth_array_to_rgbd_depth(depth_array, cfg.depth_scale, cfg.depth_trunc) ) rgbd_image = o3d.geometry.RGBDImage.create_from_color_and_depth( color_o3d, depth_o3d, - depth_scale=RGBD_DEPTH_SCALE, - depth_trunc=RGBD_DEPTH_TRUNC, + depth_scale=cfg.depth_scale, + depth_trunc=cfg.depth_trunc, convert_rgb_to_intensity=False, ) generated_point_cloud = o3d.geometry.PointCloud.create_from_rgbd_image( rgbd_image, o3d.camera.PinholeCameraIntrinsic( - o3d.camera.PinholeCameraIntrinsicParameters.PrimeSenseDefault + image.width, image.height, cfg.fx, cfg.fy, cfg.cx, cfg.cy ), ) self._orient_point_cloud_like_image(generated_point_cloud) @@ -113,7 +117,9 @@ def _orient_point_cloud_like_image(point_cloud): return point_cloud @staticmethod - def _depth_array_to_rgbd_depth(depth_array: np.ndarray) -> np.ndarray: + def _depth_array_to_rgbd_depth( + depth_array: np.ndarray, depth_scale: float, depth_trunc: float + ) -> np.ndarray: min_depth = float(np.nanmin(depth_array)) max_depth = float(np.nanmax(depth_array)) depth_range = max_depth - min_depth @@ -121,7 +127,7 @@ def _depth_array_to_rgbd_depth(depth_array: np.ndarray) -> np.ndarray: return np.zeros_like(depth_array, dtype=np.uint16) normalized = (depth_array - min_depth) / depth_range - scaled_depth = normalized * RGBD_DEPTH_TRUNC * RGBD_DEPTH_SCALE + scaled_depth = normalized * depth_trunc * depth_scale return np.clip(scaled_depth, 0, np.iinfo(np.uint16).max).astype(np.uint16) @staticmethod @@ -200,16 +206,23 @@ def _load_depth_anything_checkpoint(self, model_path: str): image_std=[0.229, 0.224, 0.225], ) - self._depth_anything_models[model_path] = (model, processor, torch) + self._depth_anything_models[model_path] = (model, processor, torch, device) return self._depth_anything_models[model_path] def _run_depth_anything_checkpoint(self, model_path: str, image: Image.Image) -> np.ndarray: - model, processor, torch = self._load_depth_anything_checkpoint(model_path) - device = next(model.parameters()).device + model, processor, torch, device = self._load_depth_anything_checkpoint(model_path) inputs = processor(images=image, return_tensors="pt") - inputs = {name: value.to(device) for name, value in inputs.items()} + inputs = {name: value.to(device, non_blocking=True) for name, value in inputs.items()} - with torch.inference_mode(): + device_type = device if isinstance(device, str) else device.type + if device_type == 'cuda': + autocast_ctx = torch.amp.autocast(device_type='cuda', dtype=torch.float16, enabled=True) + elif device_type == 'mps': + autocast_ctx = torch.amp.autocast(device_type='mps', dtype=torch.float16, enabled=True) + else: + autocast_ctx = contextlib.nullcontext() + + with torch.inference_mode(), autocast_ctx: outputs = model(**inputs) post_processed = processor.post_process_depth_estimation( @@ -217,5 +230,9 @@ def _run_depth_anything_checkpoint(self, model_path: str, image: Image.Image) -> target_sizes=[(image.height, image.width)], ) depth = post_processed[0]["predicted_depth"] + result = depth.detach().cpu().numpy().astype(np.float32) + + if device_type == 'mps': + torch.mps.empty_cache() - return depth.detach().cpu().numpy().astype(float) + return result diff --git a/vizion3d/lifting/models.py b/vizion3d/lifting/models.py index 2990379..e1bd73b 100644 --- a/vizion3d/lifting/models.py +++ b/vizion3d/lifting/models.py @@ -4,6 +4,37 @@ from pydantic import BaseModel, ConfigDict +class DepthEstimationAdvanceConfig(BaseModel): + """ + Camera intrinsics and depth range settings for depth estimation. + + All fields are optional overrides — unspecified fields retain their defaults, + which match the Open3D PrimeSense preset (640×480 RGB-D sensor). + + Attributes: + fx: Horizontal focal length in pixels. Controls the horizontal field of + view: a larger value means a narrower FOV and more perspective compression. + fy: Vertical focal length in pixels. Usually equal to ``fx`` for square + pixels; differs on sensors with non-square pixels. + cx: Principal point x — the pixel column of the optical axis, typically + near the horizontal image centre. + cy: Principal point y — the pixel row of the optical axis, typically near + the vertical image centre. + depth_scale: Divisor applied to raw uint16 depth values to convert them to + metres. ``1000`` means the raw values are in millimetres (the standard + for RealSense, Kinect, and PrimeSense sensors). + depth_trunc: Maximum depth in metres. Points beyond this distance are + discarded from the point cloud and mesh. + """ + + fx: float = 525.0 + fy: float = 525.0 + cx: float = 319.5 + cy: float = 239.5 + depth_scale: float = 1000.0 + depth_trunc: float = 10.0 + + class DepthEstimationResult(BaseModel): """ Result payload returned after a depth estimation inference task. diff --git a/vizion3d/proto/__init__.py b/vizion3d/proto/__init__.py index e69de29..6bffbb8 100644 --- a/vizion3d/proto/__init__.py +++ b/vizion3d/proto/__init__.py @@ -0,0 +1,7 @@ +import os +import sys + +# grpc_tools generates `import lifting_pb2` (bare) inside lifting_pb2_grpc.py. +# Adding this directory to sys.path makes that import resolvable when the +# package is used as `from vizion3d.proto import ...`. +sys.path.insert(0, os.path.dirname(__file__)) diff --git a/vizion3d/proto/lifting.proto b/vizion3d/proto/lifting.proto index 8314751..f859399 100644 --- a/vizion3d/proto/lifting.proto +++ b/vizion3d/proto/lifting.proto @@ -6,6 +6,15 @@ service LiftingService { rpc RunDepthEstimation (DepthEstimationRequest) returns (DepthEstimationResponse); } +message DepthEstimationAdvanceConfig { + optional float fx = 1; + optional float fy = 2; + optional float cx = 3; + optional float cy = 4; + optional float depth_scale = 5; + optional float depth_trunc = 6; +} + message DepthEstimationRequest { bytes image_bytes = 1; string model_backend = 2; @@ -13,6 +22,7 @@ message DepthEstimationRequest { bool return_point_cloud = 4; bool return_mesh = 5; optional string local_model_path = 6; + optional DepthEstimationAdvanceConfig advanced_config = 7; } message FloatRow { diff --git a/vizion3d/proto/lifting_pb2.py b/vizion3d/proto/lifting_pb2.py index ee69c74..f488181 100644 --- a/vizion3d/proto/lifting_pb2.py +++ b/vizion3d/proto/lifting_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE -# source: vizion3d/proto/lifting.proto +# source: lifting.proto # Protobuf Python Version: 6.31.1 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor @@ -15,7 +15,7 @@ 31, 1, '', - 'vizion3d/proto/lifting.proto' + 'lifting.proto' ) # @@protoc_insertion_point(imports) @@ -24,19 +24,21 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cvizion3d/proto/lifting.proto\x12\x10vizion3d.lifting\"\xc5\x01\n\x16\x44\x65pthEstimationRequest\x12\x13\n\x0bimage_bytes\x18\x01 \x01(\x0c\x12\x15\n\rmodel_backend\x18\x02 \x01(\t\x12\x1a\n\x12return_depth_image\x18\x03 \x01(\x08\x12\x1a\n\x12return_point_cloud\x18\x04 \x01(\x08\x12\x13\n\x0breturn_mesh\x18\x05 \x01(\x08\x12\x1d\n\x10local_model_path\x18\x06 \x01(\tH\x00\x88\x01\x01\x42\x13\n\x11_local_model_path\"\x1a\n\x08\x46loatRow\x12\x0e\n\x06values\x18\x01 \x03(\x02\"\xc4\x01\n\x17\x44\x65pthEstimationResponse\x12-\n\tdepth_map\x18\x01 \x03(\x0b\x32\x1a.vizion3d.lifting.FloatRow\x12\x11\n\tmin_depth\x18\x02 \x01(\x02\x12\x11\n\tmax_depth\x18\x03 \x01(\x02\x12\x14\n\x0c\x62\x61\x63kend_used\x18\x04 \x01(\t\x12\x13\n\x0b\x64\x65pth_image\x18\x05 \x01(\x0c\x12\x17\n\x0fpoint_cloud_ply\x18\x06 \x01(\x0c\x12\x10\n\x08mesh_ply\x18\x07 \x01(\x0c\x32{\n\x0eLiftingService\x12i\n\x12RunDepthEstimation\x12(.vizion3d.lifting.DepthEstimationRequest\x1a).vizion3d.lifting.DepthEstimationResponseb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rlifting.proto\x12\x10vizion3d.lifting\"\xd2\x01\n\x1c\x44\x65pthEstimationAdvanceConfig\x12\x0f\n\x02\x66x\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x0f\n\x02\x66y\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x0f\n\x02\x63x\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x0f\n\x02\x63y\x18\x04 \x01(\x02H\x03\x88\x01\x01\x12\x18\n\x0b\x64\x65pth_scale\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x18\n\x0b\x64\x65pth_trunc\x18\x06 \x01(\x02H\x05\x88\x01\x01\x42\x05\n\x03_fxB\x05\n\x03_fyB\x05\n\x03_cxB\x05\n\x03_cyB\x0e\n\x0c_depth_scaleB\x0e\n\x0c_depth_trunc\"\xa7\x02\n\x16\x44\x65pthEstimationRequest\x12\x13\n\x0bimage_bytes\x18\x01 \x01(\x0c\x12\x15\n\rmodel_backend\x18\x02 \x01(\t\x12\x1a\n\x12return_depth_image\x18\x03 \x01(\x08\x12\x1a\n\x12return_point_cloud\x18\x04 \x01(\x08\x12\x13\n\x0breturn_mesh\x18\x05 \x01(\x08\x12\x1d\n\x10local_model_path\x18\x06 \x01(\tH\x00\x88\x01\x01\x12L\n\x0f\x61\x64vanced_config\x18\x07 \x01(\x0b\x32..vizion3d.lifting.DepthEstimationAdvanceConfigH\x01\x88\x01\x01\x42\x13\n\x11_local_model_pathB\x12\n\x10_advanced_config\"\x1a\n\x08\x46loatRow\x12\x0e\n\x06values\x18\x01 \x03(\x02\"\xc4\x01\n\x17\x44\x65pthEstimationResponse\x12-\n\tdepth_map\x18\x01 \x03(\x0b\x32\x1a.vizion3d.lifting.FloatRow\x12\x11\n\tmin_depth\x18\x02 \x01(\x02\x12\x11\n\tmax_depth\x18\x03 \x01(\x02\x12\x14\n\x0c\x62\x61\x63kend_used\x18\x04 \x01(\t\x12\x13\n\x0b\x64\x65pth_image\x18\x05 \x01(\x0c\x12\x17\n\x0fpoint_cloud_ply\x18\x06 \x01(\x0c\x12\x10\n\x08mesh_ply\x18\x07 \x01(\x0c\x32{\n\x0eLiftingService\x12i\n\x12RunDepthEstimation\x12(.vizion3d.lifting.DepthEstimationRequest\x1a).vizion3d.lifting.DepthEstimationResponseb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vizion3d.proto.lifting_pb2', _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'lifting_pb2', _globals) if not _descriptor._USE_C_DESCRIPTORS: DESCRIPTOR._loaded_options = None - _globals['_DEPTHESTIMATIONREQUEST']._serialized_start=51 - _globals['_DEPTHESTIMATIONREQUEST']._serialized_end=248 - _globals['_FLOATROW']._serialized_start=250 - _globals['_FLOATROW']._serialized_end=276 - _globals['_DEPTHESTIMATIONRESPONSE']._serialized_start=279 - _globals['_DEPTHESTIMATIONRESPONSE']._serialized_end=475 - _globals['_LIFTINGSERVICE']._serialized_start=477 - _globals['_LIFTINGSERVICE']._serialized_end=600 + _globals['_DEPTHESTIMATIONADVANCECONFIG']._serialized_start=36 + _globals['_DEPTHESTIMATIONADVANCECONFIG']._serialized_end=246 + _globals['_DEPTHESTIMATIONREQUEST']._serialized_start=249 + _globals['_DEPTHESTIMATIONREQUEST']._serialized_end=544 + _globals['_FLOATROW']._serialized_start=546 + _globals['_FLOATROW']._serialized_end=572 + _globals['_DEPTHESTIMATIONRESPONSE']._serialized_start=575 + _globals['_DEPTHESTIMATIONRESPONSE']._serialized_end=771 + _globals['_LIFTINGSERVICE']._serialized_start=773 + _globals['_LIFTINGSERVICE']._serialized_end=896 # @@protoc_insertion_point(module_scope) diff --git a/vizion3d/proto/lifting_pb2_grpc.py b/vizion3d/proto/lifting_pb2_grpc.py index b6b6e1d..a93fd0c 100644 --- a/vizion3d/proto/lifting_pb2_grpc.py +++ b/vizion3d/proto/lifting_pb2_grpc.py @@ -3,7 +3,7 @@ import grpc import warnings -from vizion3d.proto import lifting_pb2 as vizion3d_dot_proto_dot_lifting__pb2 +import lifting_pb2 as lifting__pb2 GRPC_GENERATED_VERSION = '1.80.0' GRPC_VERSION = grpc.__version__ @@ -18,7 +18,7 @@ if _version_not_supported: raise RuntimeError( f'The grpc package installed is at version {GRPC_VERSION},' - + ' but the generated code in vizion3d/proto/lifting_pb2_grpc.py depends on' + + ' but the generated code in lifting_pb2_grpc.py depends on' + f' grpcio>={GRPC_GENERATED_VERSION}.' + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' @@ -36,8 +36,8 @@ def __init__(self, channel): """ self.RunDepthEstimation = channel.unary_unary( '/vizion3d.lifting.LiftingService/RunDepthEstimation', - request_serializer=vizion3d_dot_proto_dot_lifting__pb2.DepthEstimationRequest.SerializeToString, - response_deserializer=vizion3d_dot_proto_dot_lifting__pb2.DepthEstimationResponse.FromString, + request_serializer=lifting__pb2.DepthEstimationRequest.SerializeToString, + response_deserializer=lifting__pb2.DepthEstimationResponse.FromString, _registered_method=True) @@ -55,8 +55,8 @@ def add_LiftingServiceServicer_to_server(servicer, server): rpc_method_handlers = { 'RunDepthEstimation': grpc.unary_unary_rpc_method_handler( servicer.RunDepthEstimation, - request_deserializer=vizion3d_dot_proto_dot_lifting__pb2.DepthEstimationRequest.FromString, - response_serializer=vizion3d_dot_proto_dot_lifting__pb2.DepthEstimationResponse.SerializeToString, + request_deserializer=lifting__pb2.DepthEstimationRequest.FromString, + response_serializer=lifting__pb2.DepthEstimationResponse.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( @@ -84,8 +84,8 @@ def RunDepthEstimation(request, request, target, '/vizion3d.lifting.LiftingService/RunDepthEstimation', - vizion3d_dot_proto_dot_lifting__pb2.DepthEstimationRequest.SerializeToString, - vizion3d_dot_proto_dot_lifting__pb2.DepthEstimationResponse.FromString, + lifting__pb2.DepthEstimationRequest.SerializeToString, + lifting__pb2.DepthEstimationResponse.FromString, options, channel_credentials, insecure, diff --git a/vizion3d/server/grpc/server.py b/vizion3d/server/grpc/server.py index ebd091c..48f85d1 100644 --- a/vizion3d/server/grpc/server.py +++ b/vizion3d/server/grpc/server.py @@ -8,6 +8,7 @@ from vizion3d.lifting import DepthEstimation, DepthEstimationCommand from vizion3d.lifting.defaults import DEFAULT_DEPTH_MODEL_URL +from vizion3d.lifting.models import DepthEstimationAdvanceConfig from vizion3d.lifting.utils import create_mesh_ply_binary, create_ply_binary from vizion3d.proto import lifting_pb2, lifting_pb2_grpc @@ -34,12 +35,32 @@ def _o3d_mesh_to_ply_bytes(mesh) -> bytes: class LiftingServiceServicer(lifting_pb2_grpc.LiftingServiceServicer): def RunDepthEstimation(self, request, context): + base_cfg = DepthEstimationAdvanceConfig() + if request.HasField("advanced_config"): + proto_cfg = request.advanced_config + base_cfg = DepthEstimationAdvanceConfig( + fx=proto_cfg.fx if proto_cfg.HasField("fx") else base_cfg.fx, + fy=proto_cfg.fy if proto_cfg.HasField("fy") else base_cfg.fy, + cx=proto_cfg.cx if proto_cfg.HasField("cx") else base_cfg.cx, + cy=proto_cfg.cy if proto_cfg.HasField("cy") else base_cfg.cy, + depth_scale=( + proto_cfg.depth_scale + if proto_cfg.HasField("depth_scale") + else base_cfg.depth_scale + ), + depth_trunc=( + proto_cfg.depth_trunc + if proto_cfg.HasField("depth_trunc") + else base_cfg.depth_trunc + ), + ) cmd = DepthEstimationCommand( image_input=request.image_bytes, model_backend=request.model_backend or DEFAULT_DEPTH_MODEL_URL, return_depth_image=request.return_depth_image, return_point_cloud=request.return_point_cloud, return_mesh=request.return_mesh, + advanced_config=base_cfg, ) result = DepthEstimation().run(cmd) diff --git a/vizion3d/server/rest/app.py b/vizion3d/server/rest/app.py index 3291cc7..e52b808 100644 --- a/vizion3d/server/rest/app.py +++ b/vizion3d/server/rest/app.py @@ -9,6 +9,7 @@ from vizion3d.lifting import DepthEstimation, DepthEstimationCommand from vizion3d.lifting.defaults import DEFAULT_DEPTH_MODEL_URL +from vizion3d.lifting.models import DepthEstimationAdvanceConfig from vizion3d.lifting.utils import create_mesh_ply_binary, create_ply_binary _MAX_BODY = 500 * 1024 * 1024 # 500 MB @@ -56,14 +57,30 @@ async def depth_estimation( return_depth_image: bool = Form(False), return_point_cloud: bool = Form(False), return_mesh: bool = Form(False), + fx: float | None = Form(None), + fy: float | None = Form(None), + cx: float | None = Form(None), + cy: float | None = Form(None), + depth_scale: float | None = Form(None), + depth_trunc: float | None = Form(None), ): image_bytes = await image.read() + base_cfg = DepthEstimationAdvanceConfig() + advanced_config = DepthEstimationAdvanceConfig( + fx=fx if fx is not None else base_cfg.fx, + fy=fy if fy is not None else base_cfg.fy, + cx=cx if cx is not None else base_cfg.cx, + cy=cy if cy is not None else base_cfg.cy, + depth_scale=depth_scale if depth_scale is not None else base_cfg.depth_scale, + depth_trunc=depth_trunc if depth_trunc is not None else base_cfg.depth_trunc, + ) cmd = DepthEstimationCommand( image_input=image_bytes, model_backend=model_backend, return_depth_image=return_depth_image, return_point_cloud=return_point_cloud, return_mesh=return_mesh, + advanced_config=advanced_config, ) result = DepthEstimation().run(cmd) From 67dbe276aa18a1e9d8c88ea9e1b387555fe87836 Mon Sep 17 00:00:00 2001 From: OlafenwaMoses Date: Mon, 4 May 2026 00:48:24 +0100 Subject: [PATCH 2/7] add stereo vision and camera intrinsics options --- docs/features/depth_estimation.md | 29 +- .../depth_estimation_vs_stereo_depth.md | 165 +++++++ docs/features/stereo_depth.md | 417 ++++++++++++++++++ mkdocs.yml | 3 + pyproject.toml | 3 +- tests/assets/stereo/teddy/SOURCE.md | 13 + tests/assets/stereo/teddy/calib.txt | 12 + tests/assets/stereo/teddy/left.png | Bin 0 -> 309929 bytes tests/assets/stereo/teddy/right.png | Bin 0 -> 311265 bytes tests/integration/conftest.py | 170 +++++-- tests/integration/test_direct.py | 38 +- tests/integration/test_grpc.py | 36 +- tests/integration/test_rest.py | 35 +- tests/integration/test_stereo_direct.py | 256 +++++++++++ tests/integration/test_stereo_grpc.py | 156 +++++++ tests/integration/test_stereo_rest.py | 167 +++++++ tests/unit/test_advanced_config.py | 39 +- tests/unit/test_facade.py | 1 + tests/unit/test_lifting_defaults.py | 10 +- tests/unit/test_rest_api.py | 229 +++++++++- tests/unit/test_stereo_config.py | 317 +++++++++++++ tests/unit/test_stereo_handler.py | 300 +++++++++++++ vizion3d/lifting/depth_anything.py | 19 +- vizion3d/lifting/handlers.py | 32 +- vizion3d/proto/lifting.proto | 38 ++ vizion3d/proto/lifting_pb2.py | 34 +- vizion3d/proto/lifting_pb2_grpc.py | 59 ++- vizion3d/server/grpc/server.py | 113 ++++- vizion3d/server/rest/app.py | 243 +++++----- vizion3d/server/rest/depth_estimation.py | 108 +++++ vizion3d/server/rest/serialisation.py | 42 ++ vizion3d/server/rest/stereo_depth.py | 126 ++++++ vizion3d/stereo/__init__.py | 74 ++++ vizion3d/stereo/arch/__init__.py | 5 + vizion3d/stereo/arch/attention.py | 289 ++++++++++++ vizion3d/stereo/arch/components.py | 341 ++++++++++++++ vizion3d/stereo/arch/refiners.py | 281 ++++++++++++ vizion3d/stereo/arch/s2m2.py | 350 +++++++++++++++ vizion3d/stereo/arch/utils.py | 190 ++++++++ vizion3d/stereo/commands.py | 59 +++ vizion3d/stereo/defaults.py | 36 ++ vizion3d/stereo/handlers.py | 372 ++++++++++++++++ vizion3d/stereo/models.py | 96 ++++ 43 files changed, 5010 insertions(+), 293 deletions(-) create mode 100644 docs/features/depth_estimation_vs_stereo_depth.md create mode 100644 docs/features/stereo_depth.md create mode 100644 tests/assets/stereo/teddy/SOURCE.md create mode 100644 tests/assets/stereo/teddy/calib.txt create mode 100644 tests/assets/stereo/teddy/left.png create mode 100644 tests/assets/stereo/teddy/right.png create mode 100644 tests/integration/test_stereo_direct.py create mode 100644 tests/integration/test_stereo_grpc.py create mode 100644 tests/integration/test_stereo_rest.py create mode 100644 tests/unit/test_stereo_config.py create mode 100644 tests/unit/test_stereo_handler.py create mode 100644 vizion3d/server/rest/depth_estimation.py create mode 100644 vizion3d/server/rest/serialisation.py create mode 100644 vizion3d/server/rest/stereo_depth.py create mode 100644 vizion3d/stereo/__init__.py create mode 100644 vizion3d/stereo/arch/__init__.py create mode 100644 vizion3d/stereo/arch/attention.py create mode 100644 vizion3d/stereo/arch/components.py create mode 100644 vizion3d/stereo/arch/refiners.py create mode 100644 vizion3d/stereo/arch/s2m2.py create mode 100644 vizion3d/stereo/arch/utils.py create mode 100644 vizion3d/stereo/commands.py create mode 100644 vizion3d/stereo/defaults.py create mode 100644 vizion3d/stereo/handlers.py create mode 100644 vizion3d/stereo/models.py diff --git a/docs/features/depth_estimation.md b/docs/features/depth_estimation.md index dfa1d53..7c4f1f2 100644 --- a/docs/features/depth_estimation.md +++ b/docs/features/depth_estimation.md @@ -32,7 +32,7 @@ Set `VIZION3D_MODEL_CACHE` in your environment to change the default cache direc | `return_depth_image` | `bool` | No | `False` | If `True`, the result includes a 16-bit grayscale Open3D Image of the depth map. | | `return_point_cloud` | `bool` | No | `False` | If `True`, the result includes an Open3D PointCloud unprojected from the RGB-D image. | | `return_mesh` | `bool` | No | `False` | If `True`, the result includes an Open3D TriangleMesh reconstructed from the point cloud via ball-pivoting. | -| `advanced_config` | `DepthEstimationAdvanceConfig` | No | PrimeSense defaults | Camera intrinsics and depth range settings. See [Advanced config](#10-advanced-config-camera-intrinsics--depth-range) below. | +| `advanced_config` | `DepthEstimationAdvanceConfig` | No | PrimeSense defaults | Camera intrinsics and depth range settings. See [Advanced config](#10-advanced-config-camera-intrinsics-depth-range) below. | --- @@ -230,7 +230,7 @@ print(f"Backend: {result.backend_used}") ## 8. REST API -Start the server: +Start the server with all REST features enabled: **pip / Poetry** ```bash @@ -242,6 +242,31 @@ vizion3d-serve-rest uv run vizion3d-serve-rest ``` +To preload a depth-estimation checkpoint into memory at startup, pass +`--depth_model`. This also enables the depth-estimation endpoint. If this flag +is omitted, the default vizion3D release model is downloaded on first inference +and cached under `~/.cache/vizion3d/models/`. + +```bash +uv run vizion3d-serve-rest --depth_model /models/depth_anything_v2_vitb.pth +``` + +The REST server can also expose only selected features. If none of +`--depth_estimation`, `--stereo_depth`, `--depth_model`, or `--stereo_model` is +provided, all features are enabled. If any of those flags is provided, only the +selected features are enabled. A model path flag selects and preloads its +feature: + +```bash +# Only POST /lifting/depth-estimation +uv run vizion3d-serve-rest --depth_estimation + +# Only depth estimation, with the model loaded before the first request +uv run vizion3d-serve-rest \ + --depth_estimation \ + --depth_model /models/depth_anything_v2_vitb.pth +``` + Send a request with `multipart/form-data`: ```bash diff --git a/docs/features/depth_estimation_vs_stereo_depth.md b/docs/features/depth_estimation_vs_stereo_depth.md new file mode 100644 index 0000000..99b9e85 --- /dev/null +++ b/docs/features/depth_estimation_vs_stereo_depth.md @@ -0,0 +1,165 @@ +# Depth Estimation vs Stereo Depth + +vizion3d offers two different approaches to recovering depth from images. This page explains how they differ, when to choose each one, and what the practical trade-offs are. + +--- + +## What is Depth Estimation? + +[Depth Estimation](depth_estimation.md) uses a single RGB image and a monocular neural network (Depth Anything V2) to predict a per-pixel depth map. The network infers depth from visual cues — perspective, texture gradients, occlusion — without any geometric information about the camera. + +The output is **relative** (inverse) depth: closer objects have higher values, but the actual distances in metres are unknown. Point clouds built from monocular depth are geometrically consistent in shape but not anchored to a real-world scale. + +## What is Stereo Depth? + +[Stereo Depth](stereo_depth.md) takes a **rectified pair** of images (left and right, from two cameras with a known physical separation) and finds corresponding pixels across both views. The horizontal shift between matched pixels — called **disparity** — directly encodes depth through the stereo geometry formula: + +``` +depth_m = baseline_mm × focal_length_px / disparity_px / 1000 +``` + +Provided the camera calibration is accurate, the output is **real metric depth in metres** — every point in the point cloud has a physically meaningful distance from the camera. + +--- + +## Side-by-side comparison + +| | Stereo Depth (S2M2) | Depth Estimation (Depth Anything V2) | +|---|---|---| +| **Input** | Rectified left + right image pair | Single RGB image | +| **Depth type** | Metric (real metres) | Relative (inverse depth, arbitrary scale) | +| **Coordinate system** | Camera space | Camera space | +| **Units** | Metres (real) | Metres (fictitious — mapped to `[0, depth_trunc]`) | +| **Object at 2.4 m reads as 2.4 m** | Yes — if calibration is correct | No — depends on scene content | +| **Scale factor to world** | 1.0 (accurate) | Unknown, scene-dependent | +| **`point_cloud_scale` field** | 1.0 (accurate) | 1.0 (misleading — not real metres) | +| **Shape / topology correct** | Yes | Yes, if correct intrinsics supplied via `DepthEstimationAdvanceConfig` | +| **Camera calibration needed** | Yes — `focal_length`, `baseline`, `cx`, `cy` | Optional — only affects point cloud geometry | +| **Input requirements** | Stereo rig, rectified images | Any single photo | +| **Depth completeness** | Gaps in occluded / textureless regions | Dense — every pixel has a prediction | +| **Runtime** | Moderate (transformer-based matching) | Moderate (ViT-based encoder-decoder) | + +--- + +## When to use each + +### Use Depth Estimation when: +- You only have a single camera or single image. +- You need **dense** depth predictions (no holes from occlusion). +- You want to visualise relative 3D structure without exact scale. +- You are doing scene understanding, novel view synthesis, or artistic depth-of-field effects. + +### Use Stereo Depth when: +- You have a stereo camera rig with known calibration. +- You need **real metric distances** — for robotics, measurement, AR anchoring. +- Textureless or low-contrast regions can be handled by the rig geometry. +- You need consistent scale across different scenes and camera positions. + +--- + +## Working with point clouds from each + +### Monocular point cloud (Depth Estimation) + +```python +from vizion3d.lifting import DepthEstimation, DepthEstimationAdvanceConfig, DepthEstimationCommand +import numpy as np + +result = DepthEstimation().run( + DepthEstimationCommand( + image_input="scene.png", + return_point_cloud=True, + advanced_config=DepthEstimationAdvanceConfig( + fx=909.15, fy=908.48, cx=640.0, cy=360.0, + ), + ) +) + +points = np.asarray(result.point_cloud.points) # shape (N, 3) +# point_cloud_scale == 1.0, but distances are NOT real metres — +# the depth model output is relative and mapped to depth_trunc. +print(f"point_cloud_scale: {result.point_cloud_scale}") # 1.0 (misleading) +``` + +### Stereo point cloud (Stereo Depth) + +```python +from vizion3d.stereo import StereoDepth, StereoDepthAdvancedConfig, StereoDepthCommand +import numpy as np + +result = StereoDepth().run( + StereoDepthCommand( + left_image="left.png", + right_image="right.png", + return_point_cloud=True, + advanced_config=StereoDepthAdvancedConfig( + focal_length=1733.74, + cx=792.27, + cy=541.89, + baseline=536.62, + ), + ) +) + +points = np.asarray(result.point_cloud.points) # shape (N, 3), real metres +dist = np.linalg.norm(points[0] - points[1]) * result.point_cloud_scale +print(f"Real distance between p0 and p1: {dist:.4f} m") # actual metres +print(f"point_cloud_scale: {result.point_cloud_scale}") # 1.0 (accurate) +``` + +--- + +## Output differences at a glance + +| Output field | Depth Estimation | Stereo Depth | +|---|---|---| +| `depth_map` | Relative depth (fictitious metres) | Metric depth (real metres) | +| `disparity_map` | Not present | Pixel disparity (always returned) | +| `min_depth` / `max_depth` | Relative range | Real range in metres | +| `point_cloud_scale` | 1.0 (misleading) | 1.0 (accurate) | +| `backend_used` | Local path to Depth Anything V2 `.pth` | Local path to S2M2 `.pth` | + +--- + +## Advanced config comparison + +Both tasks expose a camera configuration object, but the fields are different because the underlying geometry differs: + +### DepthEstimationAdvanceConfig (monocular) + +Controls how the relative depth map is converted into a point cloud: + +```python +from vizion3d.lifting import DepthEstimationAdvanceConfig + +cfg = DepthEstimationAdvanceConfig( + fx=525.0, # horizontal focal length (pixels) + fy=525.0, # vertical focal length (pixels) + cx=319.5, # principal point x + cy=239.5, # principal point y + depth_scale=1000.0, # uint16 → metres divisor + depth_trunc=10.0, # max depth in metres +) +``` + +### StereoDepthAdvancedConfig (stereo) + +Controls the stereo geometry and point cloud quality filters: + +```python +from vizion3d.stereo import StereoDepthAdvancedConfig + +cfg = StereoDepthAdvancedConfig( + focal_length=1000.0, # focal length in pixels (fx = fy assumed) + cx=640.0, # principal point x + cy=360.0, # principal point y + baseline=100.0, # stereo baseline in millimetres + doffs=0.0, # disparity offset (Middlebury-style calibration) + z_far=10.0, # max depth in metres + conf_threshold=0.1, # min confidence score for point inclusion + occ_threshold=0.5, # min occlusion score for point inclusion + scale_factor=1.0, # input downscale for speed/quality tradeoff +) +``` + +The key stereo-only parameters are `baseline` (physical rig geometry) and `doffs` (calibration offset), which have no equivalent in monocular depth — they are meaningless without a second camera. diff --git a/docs/features/stereo_depth.md b/docs/features/stereo_depth.md new file mode 100644 index 0000000..e654d1b --- /dev/null +++ b/docs/features/stereo_depth.md @@ -0,0 +1,417 @@ +# Stereo Depth + +**Category:** Lifting (2D → 3D) +**Experimental:** No + +Stereo depth estimation recovers per-pixel **metric depth** (in metres) from a pair of rectified left/right RGB images by matching corresponding pixels across the two views and applying the stereo geometry formula: + +``` +depth_m = baseline_mm × focal_length_px / disparity_px / 1000 +``` + +vizion3d uses [S2M2](https://github.com/Dongyeop-Yoo/S2M2) (Stereo Matching Model with Multi-scale transformer) as its stereo backend. Unlike [Depth Estimation](depth_estimation.md), stereo depth produces **real-world metric distances** — provided the camera calibration parameters are correct. + +--- + +## Model backends + +| Value | What happens | +|---|---| +| *(default)* | Downloads the vizion3D release checkpoint (`stereo-depth-s2m2-L.pth`, the L variant) to `~/.cache/vizion3d/models/` on first use, then loads it | +| An HTTPS URL ending in `.pth` or `.pt` | Downloaded to the cache directory on first use, then loaded as an S2M2 checkpoint | +| A local `.pth` or `.pt` file path | Loaded directly — no download | + +Models are kept in memory after the first inference. Set `VIZION3D_MODEL_CACHE` to override the cache directory. + +### S2M2 variants + +The S2M2 architecture comes in four size variants. The correct one is detected automatically from the checkpoint filename: + +| Variant | Channels | Transformers | Speed | Quality | +|---|---|---|---|---| +| S (`-S.pth`) | 128 | 1 | Fastest | Good | +| M (`-M.pth`) | 192 | 2 | Fast | Better | +| L (`-L.pth`) | 256 | 3 | Balanced | Best (default) | +| XL (`-XL.pth`) | 384 | 3 | Slowest | Best | + +--- + +## Command parameters + +`StereoDepthCommand` is the input contract for this task. + +| Parameter | Type | Required | Default | Description | +|---|---|---|---|---| +| `left_image` | `str \| bytes` | **Yes** | — | Left-camera image. Pass a file path string or raw image bytes. | +| `right_image` | `str \| bytes` | **Yes** | — | Right-camera image (same resolution, horizontally offset from `left_image`). | +| `model_backend` | `str` | No | vizion3D release checkpoint URL | S2M2 checkpoint. See [Model backends](#model-backends) above. | +| `return_depth_image` | `bool` | No | `False` | If `True`, the result includes a 16-bit grayscale Open3D Image of the depth map. | +| `return_point_cloud` | `bool` | No | `False` | If `True`, the result includes an Open3D PointCloud in metres. | +| `return_mesh` | `bool` | No | `False` | If `True`, the result includes an Open3D TriangleMesh reconstructed via ball-pivoting. | +| `advanced_config` | `StereoDepthAdvancedConfig` | No | 1280×720 @ 100 mm baseline defaults | Camera intrinsics and inference settings. See [Advanced config](#advanced-config) below. | + +--- + +## Result fields + +`StereoDepthResult` is the output contract. + +| Field | Type | Always present | Description | +|---|---|---|---| +| `depth_map` | `list[list[float]]` | Yes | Metric depth in **metres**, shape `[H][W]`. Real-world distances (assuming correct calibration). | +| `disparity_map` | `list[list[float]]` | Yes | Raw disparity in **pixels**, shape `[H][W]`. Horizontal pixel offset between matched features. | +| `min_depth` | `float` | Yes | Minimum value in `depth_map` (metres). | +| `max_depth` | `float` | Yes | Maximum value in `depth_map`. Guaranteed `max_depth >= min_depth`. | +| `backend_used` | `str` | Yes | Resolved local file path of the checkpoint used. | +| `depth_image` | `open3d.geometry.Image \| None` | When `return_depth_image=True` | 16-bit grayscale image, dtype `uint16`. The full 0–65535 range maps to `[min_depth, max_depth]` in metres. | +| `point_cloud` | `open3d.geometry.PointCloud \| None` | When `return_point_cloud=True` | Coloured 3D point cloud, coordinates in **metres**. | +| `mesh` | `open3d.geometry.TriangleMesh \| None` | When `return_mesh=True` | Surface mesh from ball-pivoting. Includes vertex colours. | +| `point_cloud_scale` | `float` | Yes | Always `1.0` — stereo depth produces real metric coordinates. | + +--- + +## 1. Direct Python import — image bytes + +```python +from vizion3d.stereo import StereoDepth, StereoDepthCommand + +with open("left.png", "rb") as f: + left_bytes = f.read() +with open("right.png", "rb") as f: + right_bytes = f.read() + +cmd = StereoDepthCommand(left_image=left_bytes, right_image=right_bytes) +result = StereoDepth().run(cmd) + +print(f"Depth range : {result.min_depth:.2f} → {result.max_depth:.2f} m") +print(f"Backend : {result.backend_used}") +``` + +--- + +## 2. Direct Python import — file paths + +```python +from vizion3d.stereo import StereoDepth, StereoDepthCommand + +cmd = StereoDepthCommand( + left_image="left.png", + right_image="right.png", +) +result = StereoDepth().run(cmd) + +print(f"Depth range: {result.min_depth:.2f} → {result.max_depth:.2f} m") +``` + +--- + +## 3. Disparity map + +The raw disparity map (in pixels) is always returned alongside the depth map. + +```python +import numpy as np +from vizion3d.stereo import StereoDepth, StereoDepthCommand + +cmd = StereoDepthCommand(left_image="left.png", right_image="right.png") +result = StereoDepth().run(cmd) + +disp = np.array(result.disparity_map) +print(f"Disparity range: {disp.min():.1f} → {disp.max():.1f} px") +``` + +--- + +## 4. Depth image (16-bit PNG) + +```python +import numpy as np +from PIL import Image as PILImage +from vizion3d.stereo import StereoDepth, StereoDepthCommand + +cmd = StereoDepthCommand( + left_image="left.png", + right_image="right.png", + return_depth_image=True, +) +result = StereoDepth().run(cmd) + +depth_array = np.asarray(result.depth_image) # shape (H, W), dtype uint16 +PILImage.fromarray(depth_array).save("depth.png") +``` + +--- + +## 5. Point cloud + +Point coordinates are in **real metres** — `point_cloud_scale` is always `1.0`. + +```python +import numpy as np +import open3d as o3d +from vizion3d.stereo import StereoDepth, StereoDepthAdvancedConfig, StereoDepthCommand + +cmd = StereoDepthCommand( + left_image="left.png", + right_image="right.png", + return_point_cloud=True, + advanced_config=StereoDepthAdvancedConfig( + focal_length=1733.74, + cx=792.27, + cy=541.89, + baseline=536.62, # mm + ), +) +result = StereoDepth().run(cmd) + +pcd = result.point_cloud +points = np.asarray(pcd.points) # shape (N, 3), metres +print(f"Points: {len(points):,}") +print(f"Scale : {result.point_cloud_scale} m/unit") # always 1.0 + +# Real-world distance between two points +dist = np.linalg.norm(points[0] - points[1]) * result.point_cloud_scale +print(f"p0→p1: {dist:.4f} m") + +o3d.io.write_point_cloud("scene.ply", pcd) +``` + +--- + +## 6. Surface mesh + +```python +import open3d as o3d +from vizion3d.stereo import StereoDepth, StereoDepthCommand + +cmd = StereoDepthCommand( + left_image="left.png", + right_image="right.png", + return_mesh=True, +) +result = StereoDepth().run(cmd) + +mesh = result.mesh +print(f"Vertices : {len(mesh.vertices)}") +print(f"Triangles : {len(mesh.triangles)}") +o3d.io.write_triangle_mesh("scene_mesh.ply", mesh) +``` + +--- + +## 7. All outputs at once + +```python +import numpy as np +import open3d as o3d +from vizion3d.stereo import StereoDepth, StereoDepthCommand + +cmd = StereoDepthCommand( + left_image="left.png", + right_image="right.png", + return_depth_image=True, + return_point_cloud=True, + return_mesh=True, +) +result = StereoDepth().run(cmd) + +print(f"Depth range : {result.min_depth:.2f} → {result.max_depth:.2f} m") +depth_arr = np.asarray(result.depth_image) # uint16 (H, W) +o3d.io.write_point_cloud("scene.ply", result.point_cloud) +o3d.io.write_triangle_mesh("scene_mesh.ply", result.mesh) +``` + +--- + +## 8. Speed vs quality: scale factor + +Use `scale_factor < 1.0` to downsample input before inference for faster results: + +```python +from vizion3d.stereo import StereoDepth, StereoDepthAdvancedConfig, StereoDepthCommand + +cmd = StereoDepthCommand( + left_image="left.png", + right_image="right.png", + advanced_config=StereoDepthAdvancedConfig( + scale_factor=0.5, # half-resolution → ~3–4× faster + ), +) +result = StereoDepth().run(cmd) +``` + +--- + +## 9. REST API + +Start the server with all REST features enabled: + +```bash +uv run vizion3d-serve-rest +``` + +To preload the stereo checkpoint into memory at startup, pass `--stereo_model`. +This also enables the stereo-depth endpoint. If this flag is omitted, the +default vizion3D release model is downloaded on first inference and cached under +`~/.cache/vizion3d/models/`. + +```bash +uv run vizion3d-serve-rest \ + --stereo_model /models/stereo-depth-s2m2-L.pth +``` + +The REST server can expose only selected features. If none of +`--depth_estimation`, `--stereo_depth`, `--depth_model`, or `--stereo_model` is +provided, all features are enabled. If any of those flags is provided, only the +selected features are enabled. A model path flag selects and preloads its +feature: + +```bash +# Only POST /lifting/stereo-depth +uv run vizion3d-serve-rest --stereo_depth + +# Only stereo depth, with the model loaded before the first request +uv run vizion3d-serve-rest \ + --stereo_depth \ + --stereo_model /models/stereo-depth-s2m2-L.pth + +# Enable both depth estimation and stereo depth explicitly +uv run vizion3d-serve-rest \ + --depth_estimation \ + --stereo_depth \ + --depth_model /models/depth_anything_v2_vitb.pth \ + --stereo_model /models/stereo-depth-s2m2-L.pth +``` + +Send a request with two image files: + +```bash +curl -X POST "http://localhost:8000/lifting/stereo-depth" \ + -F "left_image=@left.png" \ + -F "right_image=@right.png" \ + -F "focal_length=1733.74" \ + -F "baseline=536.62" \ + -F "cx=792.27" \ + -F "cy=541.89" \ + -F "return_point_cloud=true" +``` + +The response is a JSON-serialised `StereoDepthResult`. Binary fields (`depth_image`, `point_cloud_ply`, `mesh_ply`) are base64-encoded. + +--- + +## 10. gRPC API + +Start the server: + +```bash +uv run vizion3d-serve-grpc +``` + +Call from a gRPC client: + +```python +import grpc +from vizion3d.proto import lifting_pb2, lifting_pb2_grpc + +channel = grpc.insecure_channel("localhost:50051") +stub = lifting_pb2_grpc.LiftingServiceStub(channel) + +with open("left.png", "rb") as f: + left_bytes = f.read() +with open("right.png", "rb") as f: + right_bytes = f.read() + +request = lifting_pb2.StereoDepthRequest( + left_image_bytes=left_bytes, + right_image_bytes=right_bytes, + return_point_cloud=True, + advanced_config=lifting_pb2.StereoDepthAdvancedConfig( + focal_length=1733.74, + baseline=536.62, + cx=792.27, + cy=541.89, + ), +) +response = stub.RunStereoDepth(request) +print(f"Min depth : {response.min_depth:.2f} m") +print(f"Max depth : {response.max_depth:.2f} m") +print(f"Backend : {response.backend_used}") +``` + +--- + +## Advanced config + +`StereoDepthAdvancedConfig` supplies the camera calibration needed for accurate metric depth. + +| Field | Type | Default | Description | +|---|---|---|---| +| `focal_length` | `float` | `1000.0` | Focal length in pixels (assumes fx = fy). Override with your calibration. | +| `cx` | `float` | `640.0` | Principal point x (pixel column of optical axis). | +| `cy` | `float` | `360.0` | Principal point y (pixel row of optical axis). | +| `baseline` | `float` | `100.0` | Stereo baseline in **millimetres**. | +| `doffs` | `float` | `0.0` | Disparity offset (non-zero for Middlebury-style calibration). | +| `z_far` | `float` | `10.0` | Max depth in metres for point cloud. | +| `conf_threshold` | `float` | `0.1` | Min per-pixel confidence score for point cloud inclusion. | +| `occ_threshold` | `float` | `0.5` | Min occlusion score for point cloud inclusion. | +| `scale_factor` | `float` | `1.0` | Input downscale factor (`0.5` = half-res, ~3–4× faster). | + +### How to obtain camera intrinsics + +**From a calibration file (e.g. Middlebury):** +```python +# calib.txt format: cam0=[fx 0 cx; 0 fy cy; 0 0 1] +# baseline=B (mm), doffs=d +from vizion3d.stereo import StereoDepthAdvancedConfig + +cfg = StereoDepthAdvancedConfig( + focal_length=1733.74, # from calib.txt + cx=792.27, + cy=541.89, + baseline=536.62, # B in mm + doffs=0.0, # d from calib.txt +) +``` + +**From Intel RealSense SDK:** +```python +import pyrealsense2 as rs + +pipeline = rs.pipeline() +profile = pipeline.start() +left_stream = profile.get_stream(rs.stream.infrared, 1) +intrinsics = left_stream.as_video_stream_profile().get_intrinsics() + +cfg = StereoDepthAdvancedConfig( + focal_length=intrinsics.fx, + cx=intrinsics.ppx, + cy=intrinsics.ppy, + baseline=50.0, # RealSense D435 baseline ≈ 50 mm +) +``` + +**Approximation from field of view:** +```python +import math + +hfov_deg = 90.0 # horizontal FOV from camera spec +image_width = 1280 +focal_length = image_width / (2 * math.tan(math.radians(hfov_deg / 2))) + +cfg = StereoDepthAdvancedConfig( + focal_length=focal_length, + cx=image_width / 2 - 0.5, + cy=720 / 2 - 0.5, + baseline=100.0, +) +``` + +--- + +## Known limitations + +- **Rectified pairs required** — images must be stereo-rectified so corresponding points lie on the same horizontal scanline. Un-rectified pairs will produce incorrect results. +- **Metric scale depends on calibration** — an incorrect `baseline` or `focal_length` scales all depth values uniformly. Always use calibrated values for real applications. +- **Ball-pivoting mesh quality** — works best on dense, evenly sampled point clouds. Sparse or noisy clouds from occluded regions may produce gaps or missing faces. +- **Python 3.12 required for Open3D** — `return_depth_image`, `return_point_cloud`, and `return_mesh` require Open3D, which currently only supports Python 3.12 in this project. diff --git a/mkdocs.yml b/mkdocs.yml index 57651a7..fdaabb0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -26,5 +26,8 @@ nav: - Home: index.md - Features: - Depth Estimation: features/depth_estimation.md + - Depth Estimation Advanced Config: features/depth_estimation_advanced_config.md + - Stereo Depth: features/stereo_depth.md + - Depth Estimation vs Stereo Depth: features/depth_estimation_vs_stereo_depth.md - API Reference: - Lifting (2D → 3D): api/lifting.md diff --git a/pyproject.toml b/pyproject.toml index 4377016..eb8ee69 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -96,9 +96,8 @@ addopts = "-v" [tool.ruff] line-length = 100 target-version = "py312" -extend-exclude = ["*_pb2*.py"] +extend-exclude = ["*_pb2*.py", "stereo_sample.py"] [tool.ruff.lint] select = ["E", "F", "I"] ignore = [] - diff --git a/tests/assets/stereo/teddy/SOURCE.md b/tests/assets/stereo/teddy/SOURCE.md new file mode 100644 index 0000000..5c09636 --- /dev/null +++ b/tests/assets/stereo/teddy/SOURCE.md @@ -0,0 +1,13 @@ +Middlebury Stereo Evaluation v3 quarter-resolution Teddy sample. + +Source: https://vision.middlebury.edu/stereo/submit3/ +Archive: https://vision.middlebury.edu/stereo/submit3/zip/MiddEval3-data-Q.zip +Scene path in archive: MiddEval3/trainingQ/Teddy/ + +Files: +- `left.png` is `im0.png` +- `right.png` is `im1.png` +- `calib.txt` is the original Middlebury calibration file + +The calibration file uses the Middlebury stereo format: +`Z = baseline * f / (disparity + doffs)`. diff --git a/tests/assets/stereo/teddy/calib.txt b/tests/assets/stereo/teddy/calib.txt new file mode 100644 index 0000000..afeb0ad --- /dev/null +++ b/tests/assets/stereo/teddy/calib.txt @@ -0,0 +1,12 @@ +cam0=[1500 0 199; 0 1500 187; 0 0 1] +cam1=[1500 0 251; 0 1500 187; 0 0 1] +doffs=52 +baseline=80 +width=450 +height=375 +ndisp=64 +isint=0 +vmin=12 +vmax=55 +dyavg=0 +dymax=0 diff --git a/tests/assets/stereo/teddy/left.png b/tests/assets/stereo/teddy/left.png new file mode 100644 index 0000000000000000000000000000000000000000..c8e7d271602ec9e09d2b0acbb9e8624d182dba1c GIT binary patch literal 309929 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

>h>9ICZI#7SRP&HOvy4 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 ?!F3Tyf$BZTO`4o`EsM&`nsrE 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

;6+M3;zkGLTXVtcFpz zFbk74BiS9Qj!@91&?bXjjC(?v-H||#jDKa|iJr4U5E+OxL;{FRXaZ3Y>Dk@OQ?jQ} zB9r0>$pA4V@=0=|*^-h{iB39H;FhUi5X`<@?su6QISFeN5C&XRkl7UsQJ2uC#+5`U{VDP_p=2;X$N-2ycfS)I30MBQ>gir|0%mgVSh=fO~OQtv@5flyGa_(pWDR9M-vW{TH;sGE9 zGgF;Cvjr4Pho^g*P-Bpq&5THnObN^k%}9|5qI1Y-?Yzu6EiBU^N6mGywqR6cDNqM8 zVoXWRrhT0cqeIHST7`u`!nz~V{Hg3@ zMAIn>*_$y`B!C23NjT1l8u#G>pS;JDkpsnY!Hwk>}~HRhy5HVr3j@RWvfC zXY_a^GuyNo_mOl`dZCC43D<<1X!dEjBeRs@;qb6q>0ql&(;Sx5J<LBD(s#Je(3;HoG$JDfg5a+<9wDI};`1mTHDgrk64#kGaY5W>+GT7fYYk zYfk5R;Z$v;rpjOoa#^VBL{;Rp94P7DJ(l%&MXHFHN9a>`3R)u(2%(VTa721H^0uh8KkPUNpIz=)|5QHdG)=`vTZ7QG((`OhZn4p$XS9G_H zC4D(|cC=Dx95NNTs4x}5$P@}oLeaDIR0EaXT84%^IjtIXj$~g37a%?QvP@}0<=hyn zG7y#&E)ZuXxeA{tXR*xaf%4?vSEdj~H7N{Zaz&rK9VUdvRytA=J=xUcICbWRP%B`d zvm12|kIu~6rB_`FYNIKH>R`->lw74thLeL0>Y%wpqqW9XZB?M&#GhFBT+*R3bZ`=KSX3?vkf+I;I~HnLPJ#LD?*_ z&&z)EXaBE1{qUnNAHK7jr#_ue?L4atO*!?$TDaMN_Rs&t-~844>G?nT5AWy0{CLvy zxkXF$I3OagzJIm&-7o+1Kf}NIX&dD6(NE`NLP1Z)SXWC--+OiS&;G0b?%|r3tLHwq z6vq7#&ih}ydGXnc?aLKYKYa80;g9cbzW83uQ%-ln(>${;>GN#T>a!cO`uZpTRr}t* z^&p36JU%Q;@uj`LJ$&c8oXTNbZT_48_K$z|Ra<@M8RsP)KP=0fnagrU*m{4p)vGsO z{^~8>#rJ=IKAolD;qDMF8OyZvXU{oS_)mDy(tiHc`#<@MKl-Qt>;v>=#I5aTInC<6kd<&zYfsfMX!`Fy+G-Gr+^)Vp~{V8NnEG)9EdAj8zA(|H=DL~YKd zC~0o~MA-I>OpXntMq(E2f)bgXPkHN4nVjO13`jR*_VjA#T#`~#gvtSEtpy~DFkx;X zXj;qwkK9(Xl`W(PX3J5fcy>BqeP$;xaGg)89TOykqM8&C(o-ZovxCxu$zCWnintdw z(<<4E6~)MuE{UWH!?7?2Q45~a3ycUyE=#Y_b=}Pxed_6qY|E0OHETkmd4~~8T0~lJ zPhJZK98h5@LkJ_iCo&!I1b&?rsgliAq!Zm!SX!_+G%-YlhKBZ@sTc@&km^OkDWI4p zi3|!GL8v*NY+HPqduBwm!m7FQX(6jtCAx@0tG8(9)~9}VcYk$#b3Q+AHfu!nrLV@- zPk;I+7gsMX z$FoP?-fr6Garu1r`K-rZ&A)v1?3xKQ_k^w1XyxDkH~tr`{qKkJ&qv!HA8oVFvOc9& zZ@OFg!?C@3w*H?z|DUhgRo%aO!2MAkt}kBpzQl_|)$Nj7W|n{ay{pUhU|TbN6K}4r z_a0-QFL8LeetAAEzxzA?_;;!nt-7_Z-+Ue8ek^0X{LRPqFnEcn+Vv~`fvxs?Wu6|V zhvRX7b=j8E+N3I0ht?MT6aIm+rIGJrm1vx-W?u3`s{ONozH`@zW(-?Ef1I5XW`@daX}o;OO#>#0jN|9Z1sR~ejkdR(?6I`liA z{6=4v34j-8zLU7Y7t1F?-ge3nW=n6xlpU{yIPEUk#nu)sYztJDuiIwiF0OOtLC6 zEKE~(o2ymXWIIKA(RpAygnPO)0#}hWqx+LyG1_Bk=kyUyhs5Ftc3D$L4%^MRDoh|5 zi=SPZhV{@?KBYC2471*wc^X9AX+va4c381=u)+0dJFthRpK>0W2ujn&2teV{n>Rrl zirj4W9g-SE7%4KgXbG*z0=lFqkQotH)(%Y#AZv?+r-pHE)WBMt?CFT~kTkatRX}KK zN_uOaxnzoJ<{UYw(Az^22ytf-dY2wnEX5S59*9Pf;_#LVtE-XB(iWpm*;R`Hkyr|t zbS2^`P$`gMj#N7rZ7pqbiWU)2q%P=TsSOQXO92%Tq6m`anbO@QpB(v;5ZB0r zbR=Ds!ejzs#cV+WTBJL?h$IG(ovksGq0tJXSXn$(k|_^|v(@F|a?jX~V`-UJ7ng~7 zUO1lysjJ)LH$VIN&p&zo!^@kU$Nqd?HU)JRhm-WFOy{7UzWwr@;n_zoKU)n;h^v%w zRocXMvWY&d?W?!9cMsoQZNGbUxenrTEzft&)b3v&?jG;Ua5bF|kJFdepM8FPeG##( z=Zha)T)(_7Z)@8|3@#MU*FUp{24Ho zaa#s#R`oo^<82IsTRp#hbHCe_41W@r5iB92D!%x!y z5&DDQ`t9|&7tc}(EtgXhR~5`T_w#vGhu*?ADlv6$kB@PA@sXA|^}ZW-DQ%wL3$={n zA`?%jT8MU>&r5>Hem-4aT+|V#Y0f|eh)6EP%ArMiK^RQ4Fq`D4Rx`PlbLy_6DNr3w6{Mt~>D54^&nyLZ{ zM5ILt1SH(qGn`KZa}gUNQl79jJd(mvttOME$Rg50jgm|k8&l96or(g8_c*7NVg=fd z=U#?k5Ir1@DbQlk+p?fofyv|%DJG_pMgwZH0_kW?BE1-_3PMXu1yrb#q<7LXGU-5Z z7oZ>m7V?k z@ZsUhZ)#azUk*1H*R>8IQ04vo+tV~%U3@Z>^6HaMs;xhM`SCZezw}t{9zK*>)YL=A z@k%vX93(dT-OVSTe!RIFt=4E$MpYR_qE?NFx9{FOfA;)hwg2eZ3)P`}e)HyM>+Nc3 zdU<($^XlcWmi<+}y!mJ~UY7wwDd)3~EBp5CFHfiA#l^D_zWU^&)A4Z}hu)Us^!D!l zwdkMP>UAVNSechytr+N#e-QD**KfW>DXaDP;@NYpzFzODtY3fl1sHGM zzTI!H(xud)4(smy!|nU)%kA@ zmoI%IUpO4LB}FLgARRPm(ge*$06_rNp03Vrziu^iX66{f7whl`tcZEB)|#1Pyzlc^ ztfujLw`=nu6&;7wM<0D!hU8)M91aK*yS#Y*yv{A6rnLR^lke%tIu z|MvLHpS@d^EBf%^$1g-AJeiv&!0GBkmLwv{MWYn$#F;%0AYcLm-RVvT8bZ$6i*Nr) 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

BSqJ*Mgsas^orwMNcpMf@ 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

o4b~9)(j!J?k~m(P+nyjY276pVDk8y! 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 z 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

dTOevPhuFPW)^lqw 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 literal 0 HcmV?d00001 diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 7bbe771..8399fd1 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -3,14 +3,17 @@ Provides -------- -indoor_image_bytes — real 640×480 indoor-scene JPEG for inference -local_model_path — explicit .pth path in a session-scoped tmp dir - (symlinked from the default cache if available, - otherwise freshly downloaded; cleaned up by pytest) -grpc_client_stub — live LiftingService stub backed by an in-process - gRPC server running in a background thread-pool -timing_collector — session-wide store that every test appends to -pytest_terminal_summary — pretty inference-timing report printed at the end +indoor_image_bytes — real 640×480 indoor-scene JPEG for inference +stereo_image_pair — real calibrated Middlebury Teddy stereo pair +stereo_advanced_config — Teddy calibration mapped to StereoDepthAdvancedConfig +local_model_path — explicit .pth path for the depth-estimation model + (symlinked from cache if available, else downloaded) +local_stereo_model_path — explicit .pth path for the stereo-depth model + (symlinked from cache if available, else downloaded) +grpc_client_stub — live LiftingService stub backed by an in-process + gRPC server running in a background thread-pool +timing_collector — session-wide store that every test appends to +pytest_terminal_summary — pretty inference-timing report printed at the end """ from __future__ import annotations @@ -36,6 +39,7 @@ # Timing collector # ────────────────────────────────────────────────────────────────────────────── + @dataclass class TimingRecord: entry_point: str @@ -57,9 +61,7 @@ def add( duration: float, output_dir: str = "", ) -> None: - self.records.append( - TimingRecord(entry_point, scenario, run, duration, output_dir) - ) + self.records.append(TimingRecord(entry_point, scenario, run, duration, output_dir)) # Module-level singleton — pytest_terminal_summary reads from it after the session @@ -72,9 +74,10 @@ def timing_collector() -> InferenceTimingCollector: # ────────────────────────────────────────────────────────────────────────────── -# Image fixture +# Image fixtures # ────────────────────────────────────────────────────────────────────────────── + @pytest.fixture(scope="session") def indoor_image_bytes() -> bytes: path = ASSETS_DIR / "indoor_scene.jpg" @@ -86,10 +89,66 @@ def indoor_image_bytes() -> bytes: return path.read_bytes() +def _parse_middlebury_calibration(path: Path) -> dict[str, float]: + values: dict[str, float] = {} + for line in path.read_text().splitlines(): + if not line or "=" not in line: + continue + key, raw_value = line.split("=", 1) + if key == "cam0": + rows = raw_value.strip()[1:-1].split(";") + matrix = [[float(v) for v in row.split()] for row in rows] + values["focal_length"] = matrix[0][0] + values["cx"] = matrix[0][2] + values["cy"] = matrix[1][2] + elif key in {"doffs", "baseline", "width", "height", "ndisp"}: + values[key] = float(raw_value) + return values + + +@pytest.fixture(scope="session") +def stereo_image_pair() -> tuple[bytes, bytes]: + """Return a real calibrated ``(left_bytes, right_bytes)`` stereo pair. + + The fixture uses Middlebury's quarter-resolution Teddy sample. Each image is + roughly 300 KB, and the paired ``calib.txt`` provides the camera intrinsics, + disparity offset, and baseline used by ``stereo_advanced_config``. + """ + left = ASSETS_DIR / "stereo" / "teddy" / "left.png" + right = ASSETS_DIR / "stereo" / "teddy" / "right.png" + assert left.exists(), f"Stereo left image not found: {left}" + assert right.exists(), f"Stereo right image not found: {right}" + return left.read_bytes(), right.read_bytes() + + +@pytest.fixture(scope="session") +def stereo_calibration_values() -> dict[str, float]: + calib = ASSETS_DIR / "stereo" / "teddy" / "calib.txt" + assert calib.exists(), f"Stereo calibration not found: {calib}" + return _parse_middlebury_calibration(calib) + + +@pytest.fixture(scope="session") +def stereo_advanced_config(stereo_calibration_values): + from vizion3d.stereo import StereoDepthAdvancedConfig + + return StereoDepthAdvancedConfig( + focal_length=stereo_calibration_values["focal_length"], + cx=stereo_calibration_values["cx"], + cy=stereo_calibration_values["cy"], + baseline=stereo_calibration_values["baseline"], + doffs=stereo_calibration_values["doffs"], + z_far=10.0, + conf_threshold=0.0, + occ_threshold=0.0, + ) + + # ────────────────────────────────────────────────────────────────────────────── -# Local-model-path fixture +# Local-model-path fixtures # ────────────────────────────────────────────────────────────────────────────── + @pytest.fixture(scope="session") def local_model_path(tmp_path_factory) -> str: """ @@ -117,14 +176,40 @@ def local_model_path(tmp_path_factory) -> str: return str(dest) +@pytest.fixture(scope="session") +def local_stereo_model_path(tmp_path_factory) -> str: + """ + Provide a local .pth path for the stereo-depth model, cleaned up after + the session. If the model is already in the default vizion3d cache we + symlink it (free); otherwise we download it fresh. + """ + from vizion3d.lifting.defaults import default_model_cache_dir, download_model + from vizion3d.stereo.defaults import ( + DEFAULT_STEREO_MODEL_FILENAME, + DEFAULT_STEREO_MODEL_URL, + ) + + default_cache = default_model_cache_dir() / DEFAULT_STEREO_MODEL_FILENAME + tmp_dir = tmp_path_factory.mktemp("local_stereo_model") + dest = tmp_dir / DEFAULT_STEREO_MODEL_FILENAME + + if default_cache.exists(): + dest.symlink_to(default_cache.resolve()) + else: + download_model(DEFAULT_STEREO_MODEL_URL, cache_dir=tmp_dir) + + assert dest.exists() or dest.is_symlink(), f"Stereo model not found at {dest}" + return str(dest) + + # ────────────────────────────────────────────────────────────────────────────── # gRPC server + client stub fixture # ────────────────────────────────────────────────────────────────────────────── -_MAX_MSG = 500 * 1024 * 1024 # match server cap +_MAX_MSG = 500 * 1024 * 1024 # match server cap _GRPC_OPTIONS = [ - ("grpc.max_send_message_length", _MAX_MSG), + ("grpc.max_send_message_length", _MAX_MSG), ("grpc.max_receive_message_length", _MAX_MSG), ] @@ -142,10 +227,8 @@ def grpc_client_stub(): futures.ThreadPoolExecutor(max_workers=4), options=_GRPC_OPTIONS, ) - lifting_pb2_grpc.add_LiftingServiceServicer_to_server( - LiftingServiceServicer(), server - ) - port = server.add_insecure_port("[::]:0") # 0 → OS picks a free port + lifting_pb2_grpc.add_LiftingServiceServicer_to_server(LiftingServiceServicer(), server) + port = server.add_insecure_port("[::]:0") # 0 → OS picks a free port server.start() channel = grpc.insecure_channel(f"localhost:{port}", options=_GRPC_OPTIONS) @@ -161,17 +244,18 @@ def grpc_client_stub(): # Terminal report (hook) # ────────────────────────────────────────────────────────────────────────────── -def pytest_terminal_summary(terminalreporter, exitstatus, config): # noqa: ARG001 + +def pytest_terminal_summary(terminalreporter, exitstatus, config): # noqa: ARG001 records = _COLLECTOR.records if not records: return - W = 82 - EP = 10 # entry-point col width - SC = 16 # scenario col width - RN = 4 # run col width - DU = 10 # duration col width - ST = 20 # status col width + W = 82 + EP = 10 # entry-point col width + SC = 16 # scenario col width + RN = 4 # run col width + DU = 10 # duration col width + ST = 20 # status col width def _write(line: str = "") -> None: terminalreporter.write_line(line) @@ -180,14 +264,10 @@ def _thick() -> None: _write("━" * W) def _thin() -> None: - _write( - f" {'─'*EP}─┼─{'─'*SC}─┼─{'─'*RN}─┼─{'─'*(DU)}─┼─{'─'*ST}" - ) + _write(f" {'─' * EP}─┼─{'─' * SC}─┼─{'─' * RN}─┼─{'─' * (DU)}─┼─{'─' * ST}") def _row(ep="", sc="", run="", dur="", status="") -> None: - _write( - f" {ep:<{EP}} │ {sc:<{SC}} │ {run:^{RN}} │ {dur:>{DU}} │ {status}" - ) + _write(f" {ep:<{EP}} │ {sc:<{SC}} │ {run:^{RN}} │ {dur:>{DU}} │ {status}") _write() _thick() @@ -197,17 +277,17 @@ def _row(ep="", sc="", run="", dur="", status="") -> None: _row("Entry Point", "Scenario", "Run", "Duration", "Status") _thin() - def sort_key(r): return (r.entry_point, r.scenario, r.run) - def group_key(r): return (r.entry_point, r.scenario) + def sort_key(r): + return (r.entry_point, r.scenario, r.run) + + def group_key(r): + return (r.entry_point, r.scenario) first_loads: list[float] = [] - warm_times: list[float] = [] + warm_times: list[float] = [] sorted_records = sorted(records, key=sort_key) - groups = [ - (k, list(v)) - for k, v in groupby(sorted_records, key=group_key) - ] + groups = [(k, list(v)) for k, v in groupby(sorted_records, key=group_key)] for g_idx, ((ep, sc), recs) in enumerate(groups): if g_idx > 0: @@ -217,15 +297,15 @@ def group_key(r): return (r.entry_point, r.scenario) first_dur = recs[0].duration for i, rec in enumerate(recs): - ep_label = ep if i == 0 else "" - sc_label = sc if i == 0 else "" - dur_str = f"{rec.duration:7.3f}s" + ep_label = ep if i == 0 else "" + sc_label = sc if i == 0 else "" + dur_str = f"{rec.duration:7.3f}s" if rec.run == 1: status = "◉ COLD LOAD" first_loads.append(rec.duration) else: - pct = (1.0 - rec.duration / first_dur) * 100.0 + pct = (1.0 - rec.duration / first_dur) * 100.0 status = f"⚡ {pct:4.1f}% faster" warm_times.append(rec.duration) @@ -238,8 +318,8 @@ def group_key(r): return (r.entry_point, r.scenario) if first_loads and warm_times: avg_load = sum(first_loads) / len(first_loads) avg_warm = sum(warm_times) / len(warm_times) - speedup = avg_load / avg_warm if avg_warm > 0 else float("inf") - total = len(records) + speedup = avg_load / avg_warm if avg_warm > 0 else float("inf") + total = len(records) pad = 42 _write(f" {'SUMMARY'}") diff --git a/tests/integration/test_direct.py b/tests/integration/test_direct.py index c37ca42..17f8fa7 100644 --- a/tests/integration/test_direct.py +++ b/tests/integration/test_direct.py @@ -40,22 +40,21 @@ # Helpers # ────────────────────────────────────────────────────────────────────────────── + def _save_outputs(result, run_dir: Path, run: int) -> None: run_dir.mkdir(parents=True, exist_ok=True) prefix = run_dir / f"run_{run:02d}" - (prefix.with_suffix(".depth_map.json")).write_text( - json.dumps(result.depth_map) - ) + (prefix.with_suffix(".depth_map.json")).write_text(json.dumps(result.depth_map)) if result.depth_image is not None: - arr = np.asarray(result.depth_image) # uint16 (H, W) + arr = np.asarray(result.depth_image) # uint16 (H, W) PILImage.fromarray(arr).save(str(prefix) + "_depth.png") if result.point_cloud is not None and result.point_cloud.has_points(): - pts = np.asarray(result.point_cloud.points).astype(np.float32) + pts = np.asarray(result.point_cloud.points).astype(np.float32) cols = (np.asarray(result.point_cloud.colors) * 255).astype(np.uint8) - ply = create_ply_binary(pts, cols) + ply = create_ply_binary(pts, cols) (str(prefix) + "_point_cloud.ply") Path(str(prefix) + "_point_cloud.ply").write_bytes(ply) @@ -74,7 +73,7 @@ def _run_group( timings: list[float] = [] for run in range(1, N_RUNS + 1): - t0 = time.perf_counter() + t0 = time.perf_counter() result = DepthEstimation().run( DepthEstimationCommand( image_input=indoor_image_bytes, @@ -92,20 +91,22 @@ def _run_group( # ── per-run assertions ──────────────────────────────────────────────── assert isinstance(result.depth_map, list) and len(result.depth_map) > 0 assert all(isinstance(row, list) for row in result.depth_map) - assert result.max_depth > result.min_depth, \ + assert result.max_depth > result.min_depth, ( "Depth variation expected for a real indoor scene" + ) assert result.depth_image is not None, "depth_image was requested but missing" - assert result.point_cloud is not None and result.point_cloud.has_points(), \ + assert result.point_cloud is not None and result.point_cloud.has_points(), ( "point_cloud was requested but missing or empty" + ) # ── caching assertion: model must be in memory after run 1 ─────────────── - assert len(DepthEstimationHandler._depth_anything_models) > 0, \ + assert len(DepthEstimationHandler._depth_anything_models) > 0, ( "Model should be in DepthEstimationHandler._depth_anything_models after first inference" + ) # ── timing assertions ───────────────────────────────────────────────────── assert timings[0] < COLD_LIMIT, ( - f"[{entry_point} / {scenario}] " - f"Cold load took {timings[0]:.3f}s — expected < {COLD_LIMIT}s" + f"[{entry_point} / {scenario}] Cold load took {timings[0]:.3f}s — expected < {COLD_LIMIT}s" ) for i, t in enumerate(timings[1:], start=2): assert t < WARM_LIMIT, ( @@ -120,6 +121,7 @@ def _run_group( # Tests # ────────────────────────────────────────────────────────────────────────────── + def test_direct_default_model(indoor_image_bytes, tmp_path, timing_collector): """5 inferences with the default model backend (downloads to vizion3d cache).""" _run_group( @@ -132,9 +134,7 @@ def test_direct_default_model(indoor_image_bytes, tmp_path, timing_collector): ) -def test_direct_local_model( - indoor_image_bytes, local_model_path, tmp_path, timing_collector -): +def test_direct_local_model(indoor_image_bytes, local_model_path, tmp_path, timing_collector): """5 inferences with an explicit local .pth path in a tmp directory.""" _run_group( model_backend=local_model_path, @@ -154,9 +154,7 @@ def test_direct_advanced_config_custom_intrinsics(indoor_image_bytes, local_mode image_input=indoor_image_bytes, model_backend=local_model_path, return_point_cloud=True, - advanced_config=DepthEstimationAdvanceConfig( - fx=615.0, fy=615.0, cx=320.0, cy=240.0 - ), + advanced_config=DepthEstimationAdvanceConfig(fx=615.0, fy=615.0, cx=320.0, cy=240.0), ) ) assert isinstance(result.depth_map, list) and len(result.depth_map) > 0 @@ -188,9 +186,9 @@ def test_direct_advanced_config_tight_depth_trunc_yields_fewer_points( ) import numpy as np + default_pts = len(np.asarray(default_result.point_cloud.points)) tight_pts = len(np.asarray(tight_result.point_cloud.points)) assert tight_pts < default_pts, ( - f"Expected tight depth_trunc to yield fewer points " - f"({tight_pts} vs default {default_pts})" + f"Expected tight depth_trunc to yield fewer points ({tight_pts} vs default {default_pts})" ) diff --git a/tests/integration/test_grpc.py b/tests/integration/test_grpc.py index 7880460..2e52880 100644 --- a/tests/integration/test_grpc.py +++ b/tests/integration/test_grpc.py @@ -33,6 +33,7 @@ # Helpers # ────────────────────────────────────────────────────────────────────────────── + def _save_outputs(response, run_dir: Path, run: int) -> None: run_dir.mkdir(parents=True, exist_ok=True) prefix = str(run_dir / f"run_{run:02d}") @@ -69,9 +70,9 @@ def _run_group( return_point_cloud=True, ) - t0 = time.perf_counter() + t0 = time.perf_counter() response = grpc_client_stub.RunDepthEstimation(request) - elapsed = time.perf_counter() - t0 + elapsed = time.perf_counter() - t0 timings.append(elapsed) _save_outputs(response, run_dir, run) @@ -79,25 +80,24 @@ def _run_group( # ── per-run assertions ──────────────────────────────────────────────── assert len(response.depth_map) > 0, "depth_map rows are missing" - assert response.max_depth > response.min_depth, \ + assert response.max_depth > response.min_depth, ( "Depth variation expected for a real indoor scene" - assert len(response.depth_image) > 0, \ - "depth_image was requested but empty in response" - assert len(response.point_cloud_ply) > 0, \ + ) + assert len(response.depth_image) > 0, "depth_image was requested but empty in response" + assert len(response.point_cloud_ply) > 0, ( "point_cloud_ply was requested but empty in response" + ) # Validate file-format magic bytes - assert response.depth_image[:4] == b"\x89PNG", \ - "depth_image is not a valid PNG" - assert response.point_cloud_ply.startswith(b"ply\n"), \ - "point_cloud_ply is not a valid PLY" + assert response.depth_image[:4] == b"\x89PNG", "depth_image is not a valid PNG" + assert response.point_cloud_ply.startswith(b"ply\n"), "point_cloud_ply is not a valid PLY" - assert len(DepthEstimationHandler._depth_anything_models) > 0, \ + assert len(DepthEstimationHandler._depth_anything_models) > 0, ( "Model should be cached in memory after first gRPC inference" + ) assert timings[0] < COLD_LIMIT, ( - f"[gRPC / {scenario}] " - f"Cold load took {timings[0]:.3f}s — expected < {COLD_LIMIT}s" + f"[gRPC / {scenario}] Cold load took {timings[0]:.3f}s — expected < {COLD_LIMIT}s" ) for i, t in enumerate(timings[1:], start=2): assert t < WARM_LIMIT, ( @@ -112,9 +112,8 @@ def _run_group( # Tests # ────────────────────────────────────────────────────────────────────────────── -def test_grpc_default_model( - indoor_image_bytes, grpc_client_stub, tmp_path, timing_collector -): + +def test_grpc_default_model(indoor_image_bytes, grpc_client_stub, tmp_path, timing_collector): """5 RPC calls with the default model backend.""" _run_group( model_backend=DEFAULT_DEPTH_MODEL_URL, @@ -151,7 +150,10 @@ def test_grpc_advanced_config_custom_intrinsics_accepted( model_backend=local_model_path, return_point_cloud=True, advanced_config=lifting_pb2.DepthEstimationAdvanceConfig( - fx=615.0, fy=615.0, cx=320.0, cy=240.0, + fx=615.0, + fy=615.0, + cx=320.0, + cy=240.0, ), ) response = grpc_client_stub.RunDepthEstimation(request) diff --git a/tests/integration/test_rest.py b/tests/integration/test_rest.py index 8ec3914..67541d8 100644 --- a/tests/integration/test_rest.py +++ b/tests/integration/test_rest.py @@ -36,6 +36,7 @@ # Helpers # ────────────────────────────────────────────────────────────────────────────── + def _save_outputs(data: dict, run_dir: Path, run: int) -> None: run_dir.mkdir(parents=True, exist_ok=True) prefix = str(run_dir / f"run_{run:02d}") @@ -46,9 +47,7 @@ def _save_outputs(data: dict, run_dir: Path, run: int) -> None: Path(prefix + "_depth.png").write_bytes(base64.b64decode(data["depth_image"])) if data.get("point_cloud_ply"): - Path(prefix + "_point_cloud.ply").write_bytes( - base64.b64decode(data["point_cloud_ply"]) - ) + Path(prefix + "_point_cloud.ply").write_bytes(base64.b64decode(data["point_cloud_ply"])) def _run_group( @@ -86,12 +85,15 @@ def _run_group( # ── per-run assertions ──────────────────────────────────────────────── assert isinstance(data["depth_map"], list) and len(data["depth_map"]) > 0 - assert data["max_depth"] > data["min_depth"], \ + assert data["max_depth"] > data["min_depth"], ( "Depth variation expected for a real indoor scene" - assert data["depth_image"] is not None, \ + ) + assert data["depth_image"] is not None, ( "depth_image was requested but missing from response" - assert data["point_cloud_ply"] is not None, \ + ) + assert data["point_cloud_ply"] is not None, ( "point_cloud_ply was requested but missing from response" + ) # Binary fields should decode to valid PLY / PNG png_bytes = base64.b64decode(data["depth_image"]) @@ -100,12 +102,12 @@ def _run_group( ply_bytes = base64.b64decode(data["point_cloud_ply"]) assert ply_bytes.startswith(b"ply\n"), "point_cloud_ply is not a valid PLY" - assert len(DepthEstimationHandler._depth_anything_models) > 0, \ + assert len(DepthEstimationHandler._depth_anything_models) > 0, ( "Model should be cached in memory after first REST inference" + ) assert timings[0] < COLD_LIMIT, ( - f"[REST / {scenario}] " - f"Cold load took {timings[0]:.3f}s — expected < {COLD_LIMIT}s" + f"[REST / {scenario}] Cold load took {timings[0]:.3f}s — expected < {COLD_LIMIT}s" ) for i, t in enumerate(timings[1:], start=2): assert t < WARM_LIMIT, ( @@ -120,6 +122,7 @@ def _run_group( # Tests # ────────────────────────────────────────────────────────────────────────────── + def test_rest_default_model(indoor_image_bytes, tmp_path, timing_collector): """5 POST requests with the default model backend.""" _run_group( @@ -131,9 +134,7 @@ def test_rest_default_model(indoor_image_bytes, tmp_path, timing_collector): ) -def test_rest_local_model( - indoor_image_bytes, local_model_path, tmp_path, timing_collector -): +def test_rest_local_model(indoor_image_bytes, local_model_path, tmp_path, timing_collector): """5 POST requests with an explicit local .pth path.""" _run_group( model_backend=local_model_path, @@ -144,11 +145,10 @@ def test_rest_local_model( ) -def test_rest_advanced_config_custom_intrinsics_accepted( - indoor_image_bytes, local_model_path -): +def test_rest_advanced_config_custom_intrinsics_accepted(indoor_image_bytes, local_model_path): """Custom fx/fy/cx/cy form fields are accepted and produce a valid response.""" from vizion3d.lifting.handlers import DepthEstimationHandler + DepthEstimationHandler._depth_anything_models.clear() response = client.post( @@ -170,11 +170,10 @@ def test_rest_advanced_config_custom_intrinsics_accepted( assert base64.b64decode(data["point_cloud_ply"]).startswith(b"ply\n") -def test_rest_advanced_config_custom_depth_trunc_accepted( - indoor_image_bytes, local_model_path -): +def test_rest_advanced_config_custom_depth_trunc_accepted(indoor_image_bytes, local_model_path): """Custom depth_trunc form field is accepted without errors.""" from vizion3d.lifting.handlers import DepthEstimationHandler + DepthEstimationHandler._depth_anything_models.clear() response = client.post( diff --git a/tests/integration/test_stereo_direct.py b/tests/integration/test_stereo_direct.py new file mode 100644 index 0000000..e5f048a --- /dev/null +++ b/tests/integration/test_stereo_direct.py @@ -0,0 +1,256 @@ +""" +Integration tests — direct Python entry point for Stereo Depth (StereoDepth.run). + +Each test group clears the in-memory model cache before the first inference to +simulate a cold start, then runs N_RUNS iterations. We assert: + - every run produces a valid depth map and disparity map + - depth image and point cloud are returned and non-trivial + - all artefacts are persisted to a session tmp directory + - the model is cached in memory after run 1 (subsequent runs faster) +""" + +from __future__ import annotations + +import json +import os +import time +from pathlib import Path + +import numpy as np +import pytest +from PIL import Image as PILImage + +pytest.importorskip("open3d", reason="open3d required — run: uv python pin 3.12 && uv sync") + +from vizion3d.lifting.utils import create_ply_binary # noqa: E402 +from vizion3d.stereo import ( # noqa: E402 + StereoDepth, + StereoDepthAdvancedConfig, + StereoDepthCommand, +) +from vizion3d.stereo.defaults import DEFAULT_STEREO_MODEL_URL # noqa: E402 +from vizion3d.stereo.handlers import StereoDepthHandler # noqa: E402 + +N_RUNS = 5 +COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_COLD_LIMIT", "60.0")) +WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_WARM_LIMIT", "5.0")) + + +# ────────────────────────────────────────────────────────────────────────────── +# Helpers +# ────────────────────────────────────────────────────────────────────────────── + + +def _save_outputs(result, run_dir: Path, run: int) -> None: + run_dir.mkdir(parents=True, exist_ok=True) + prefix = run_dir / f"run_{run:02d}" + + Path(str(prefix) + ".depth_map.json").write_text(json.dumps(result.depth_map)) + Path(str(prefix) + ".disparity_map.json").write_text(json.dumps(result.disparity_map)) + + if result.depth_image is not None: + arr = np.asarray(result.depth_image) + PILImage.fromarray(arr).save(str(prefix) + "_depth.png") + + if result.point_cloud is not None and result.point_cloud.has_points(): + pts = np.asarray(result.point_cloud.points).astype(np.float32) + cols = (np.asarray(result.point_cloud.colors) * 255).astype(np.uint8) + ply = create_ply_binary(pts, cols) + Path(str(prefix) + "_point_cloud.ply").write_bytes(ply) + + +def _run_group( + model_backend: str, + stereo_image_pair: tuple[bytes, bytes], + stereo_advanced_config: StereoDepthAdvancedConfig, + run_dir: Path, + entry_point: str, + scenario: str, + timing_collector, +) -> list[float]: + StereoDepthHandler._stereo_models.clear() + + left_bytes, right_bytes = stereo_image_pair + timings: list[float] = [] + + for run in range(1, N_RUNS + 1): + t0 = time.perf_counter() + result = StereoDepth().run( + StereoDepthCommand( + left_image=left_bytes, + right_image=right_bytes, + model_backend=model_backend, + return_depth_image=True, + return_point_cloud=True, + advanced_config=stereo_advanced_config, + ) + ) + elapsed = time.perf_counter() - t0 + timings.append(elapsed) + + _save_outputs(result, run_dir, run) + timing_collector.add(entry_point, scenario, run, elapsed, str(run_dir)) + + assert isinstance(result.depth_map, list) and len(result.depth_map) > 0 + assert all(isinstance(row, list) for row in result.depth_map) + assert isinstance(result.disparity_map, list) and len(result.disparity_map) > 0 + assert result.max_depth >= result.min_depth + assert result.depth_image is not None, "depth_image was requested but missing" + assert result.point_cloud is not None, "point_cloud was requested but missing" + + assert len(StereoDepthHandler._stereo_models) > 0, ( + "Model should be cached in StereoDepthHandler._stereo_models after first inference" + ) + + assert timings[0] < COLD_LIMIT, ( + f"[{entry_point} / {scenario}] Cold load took {timings[0]:.3f}s — expected < {COLD_LIMIT}s" + ) + for i, t in enumerate(timings[1:], start=2): + assert t < WARM_LIMIT, ( + f"[{entry_point} / {scenario}] " + f"Run {i} took {t:.3f}s — expected < {WARM_LIMIT}s (model should be cached)" + ) + + return timings + + +# ────────────────────────────────────────────────────────────────────────────── +# Tests +# ────────────────────────────────────────────────────────────────────────────── + + +def test_stereo_direct_default_model( + stereo_image_pair, stereo_advanced_config, tmp_path, timing_collector +): + """5 direct inferences with the default model backend (downloads to cache).""" + _run_group( + model_backend=DEFAULT_STEREO_MODEL_URL, + stereo_image_pair=stereo_image_pair, + stereo_advanced_config=stereo_advanced_config, + run_dir=tmp_path / "stereo_direct_default", + entry_point="Stereo Direct", + scenario="Default model", + timing_collector=timing_collector, + ) + + +def test_stereo_direct_local_model( + stereo_image_pair, + stereo_advanced_config, + local_stereo_model_path, + tmp_path, + timing_collector, +): + """5 direct inferences with an explicit local .pth path.""" + _run_group( + model_backend=local_stereo_model_path, + stereo_image_pair=stereo_image_pair, + stereo_advanced_config=stereo_advanced_config, + run_dir=tmp_path / "stereo_direct_local", + entry_point="Stereo Direct", + scenario="Local model", + timing_collector=timing_collector, + ) + + +def test_stereo_direct_advanced_config_custom_intrinsics( + stereo_image_pair, stereo_advanced_config, local_stereo_model_path +): + """The calibrated Middlebury intrinsics produce a valid point cloud.""" + StereoDepthHandler._stereo_models.clear() + left_bytes, right_bytes = stereo_image_pair + + result = StereoDepth().run( + StereoDepthCommand( + left_image=left_bytes, + right_image=right_bytes, + model_backend=local_stereo_model_path, + return_point_cloud=True, + advanced_config=stereo_advanced_config, + ) + ) + assert isinstance(result.depth_map, list) and len(result.depth_map) > 0 + assert result.max_depth >= result.min_depth + assert result.point_cloud is not None + + +def test_stereo_direct_advanced_config_tight_z_far_yields_fewer_points( + stereo_image_pair, stereo_advanced_config, local_stereo_model_path +): + """A tight z_far clips points to a smaller range → fewer points than the default.""" + StereoDepthHandler._stereo_models.clear() + left_bytes, right_bytes = stereo_image_pair + + default_result = StereoDepth().run( + StereoDepthCommand( + left_image=left_bytes, + right_image=right_bytes, + model_backend=local_stereo_model_path, + return_point_cloud=True, + advanced_config=stereo_advanced_config.model_copy(update={"z_far": 100.0}), + ) + ) + + tight_result = StereoDepth().run( + StereoDepthCommand( + left_image=left_bytes, + right_image=right_bytes, + model_backend=local_stereo_model_path, + return_point_cloud=True, + advanced_config=stereo_advanced_config.model_copy(update={"z_far": 0.001}), + ) + ) + + default_pts = len(np.asarray(default_result.point_cloud.points)) + tight_pts = len(np.asarray(tight_result.point_cloud.points)) + assert tight_pts < default_pts, ( + f"Expected tight z_far to yield fewer points ({tight_pts} vs default {default_pts})" + ) + + +def test_stereo_direct_advanced_config_scale_factor( + stereo_image_pair, stereo_advanced_config, local_stereo_model_path +): + """scale_factor=0.5 completes without error and returns a valid depth map.""" + StereoDepthHandler._stereo_models.clear() + left_bytes, right_bytes = stereo_image_pair + + result = StereoDepth().run( + StereoDepthCommand( + left_image=left_bytes, + right_image=right_bytes, + model_backend=local_stereo_model_path, + advanced_config=stereo_advanced_config.model_copy(update={"scale_factor": 0.5}), + ) + ) + assert isinstance(result.depth_map, list) and len(result.depth_map) > 0 + assert result.max_depth >= result.min_depth + + +def test_stereo_direct_all_outputs_returned( + stereo_image_pair, stereo_advanced_config, local_stereo_model_path +): + """depth_image, point_cloud, and mesh are all returned when requested.""" + StereoDepthHandler._stereo_models.clear() + left_bytes, right_bytes = stereo_image_pair + + result = StereoDepth().run( + StereoDepthCommand( + left_image=left_bytes, + right_image=right_bytes, + model_backend=local_stereo_model_path, + return_depth_image=True, + return_point_cloud=True, + return_mesh=True, + advanced_config=stereo_advanced_config, + ) + ) + assert result.depth_image is not None + arr = np.asarray(result.depth_image) + assert arr.dtype == np.uint16 + + assert result.point_cloud is not None + assert result.point_cloud.has_points() + assert result.point_cloud_scale == 1.0 + + assert result.mesh is not None diff --git a/tests/integration/test_stereo_grpc.py b/tests/integration/test_stereo_grpc.py new file mode 100644 index 0000000..5b21806 --- /dev/null +++ b/tests/integration/test_stereo_grpc.py @@ -0,0 +1,156 @@ +""" +Integration tests for the Stereo Depth gRPC entry point. + +A live in-process gRPC server is provided by the session fixture. These tests +exercise real S2M2 inference through RunStereoDepth. +""" + +from __future__ import annotations + +import json +import os +import time +from pathlib import Path + +import pytest + +pytest.importorskip("open3d", reason="open3d required - run: uv python pin 3.12 && uv sync") + +from vizion3d.proto import lifting_pb2 # noqa: E402 +from vizion3d.stereo.defaults import DEFAULT_STEREO_MODEL_URL # noqa: E402 +from vizion3d.stereo.handlers import StereoDepthHandler # noqa: E402 + +N_RUNS = 5 +COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_STEREO_COLD_LIMIT", "60.0")) +WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_STEREO_WARM_LIMIT", "5.0")) + + +def _proto_config(config, **overrides): + values = { + "focal_length": config.focal_length, + "baseline": config.baseline, + "cx": config.cx, + "cy": config.cy, + "doffs": config.doffs, + "z_far": config.z_far, + "conf_threshold": config.conf_threshold, + "occ_threshold": config.occ_threshold, + "scale_factor": config.scale_factor, + } + values.update(overrides) + return lifting_pb2.StereoDepthAdvancedConfig(**values) + + +def _save_outputs(response, run_dir: Path, run: int) -> None: + run_dir.mkdir(parents=True, exist_ok=True) + prefix = str(run_dir / f"run_{run:02d}") + + depth_map = [list(row.values) for row in response.depth_map] + disparity_map = [list(row.values) for row in response.disparity_map] + Path(prefix + ".depth_map.json").write_text(json.dumps(depth_map)) + Path(prefix + ".disparity_map.json").write_text(json.dumps(disparity_map)) + + if response.depth_image: + Path(prefix + "_depth.png").write_bytes(response.depth_image) + + if response.point_cloud_ply: + Path(prefix + "_point_cloud.ply").write_bytes(response.point_cloud_ply) + + +def _run_group( + model_backend: str, + stereo_image_pair: tuple[bytes, bytes], + stereo_advanced_config, + run_dir: Path, + scenario: str, + grpc_client_stub, + timing_collector, +) -> list[float]: + StereoDepthHandler._stereo_models.clear() + left_bytes, right_bytes = stereo_image_pair + timings: list[float] = [] + + for run in range(1, N_RUNS + 1): + request = lifting_pb2.StereoDepthRequest( + left_image_bytes=left_bytes, + right_image_bytes=right_bytes, + model_backend=model_backend, + return_depth_image=True, + return_point_cloud=True, + advanced_config=_proto_config(stereo_advanced_config), + ) + + t0 = time.perf_counter() + response = grpc_client_stub.RunStereoDepth(request) + elapsed = time.perf_counter() - t0 + timings.append(elapsed) + + _save_outputs(response, run_dir, run) + timing_collector.add("Stereo gRPC", scenario, run, elapsed, str(run_dir)) + + assert len(response.depth_map) > 0 + assert len(response.disparity_map) > 0 + assert response.max_depth >= response.min_depth + assert response.depth_image[:4] == b"\x89PNG" + assert response.point_cloud_ply.startswith(b"ply\n") + + assert len(StereoDepthHandler._stereo_models) > 0 + assert timings[0] < COLD_LIMIT + for elapsed in timings[1:]: + assert elapsed < WARM_LIMIT + + return timings + + +def test_stereo_grpc_default_model( + stereo_image_pair, stereo_advanced_config, grpc_client_stub, tmp_path, timing_collector +): + _run_group( + model_backend=DEFAULT_STEREO_MODEL_URL, + stereo_image_pair=stereo_image_pair, + stereo_advanced_config=stereo_advanced_config, + run_dir=tmp_path / "stereo_grpc_default", + scenario="Default model", + grpc_client_stub=grpc_client_stub, + timing_collector=timing_collector, + ) + + +def test_stereo_grpc_local_model( + stereo_image_pair, + stereo_advanced_config, + local_stereo_model_path, + grpc_client_stub, + tmp_path, + timing_collector, +): + _run_group( + model_backend=local_stereo_model_path, + stereo_image_pair=stereo_image_pair, + stereo_advanced_config=stereo_advanced_config, + run_dir=tmp_path / "stereo_grpc_local", + scenario="Local model", + grpc_client_stub=grpc_client_stub, + timing_collector=timing_collector, + ) + + +def test_stereo_grpc_advanced_config_accepted( + stereo_image_pair, stereo_advanced_config, local_stereo_model_path, grpc_client_stub +): + StereoDepthHandler._stereo_models.clear() + left_bytes, right_bytes = stereo_image_pair + + request = lifting_pb2.StereoDepthRequest( + left_image_bytes=left_bytes, + right_image_bytes=right_bytes, + model_backend=local_stereo_model_path, + return_point_cloud=True, + advanced_config=_proto_config(stereo_advanced_config, scale_factor=0.5), + ) + response = grpc_client_stub.RunStereoDepth(request) + + assert len(response.depth_map) > 0 + assert len(response.disparity_map) > 0 + assert response.max_depth >= response.min_depth + assert response.point_cloud_ply.startswith(b"ply\n") diff --git a/tests/integration/test_stereo_rest.py b/tests/integration/test_stereo_rest.py new file mode 100644 index 0000000..81b4f62 --- /dev/null +++ b/tests/integration/test_stereo_rest.py @@ -0,0 +1,167 @@ +""" +Integration tests for the Stereo Depth REST entry point. + +These tests exercise real S2M2 inference through POST /lifting/stereo-depth, +covering both default URL download/cache behavior and explicit local model paths. +""" + +from __future__ import annotations + +import base64 +import json +import os +import time +from pathlib import Path + +import pytest +from fastapi.testclient import TestClient + +pytest.importorskip("open3d", reason="open3d required - run: uv python pin 3.12 && uv sync") + +from vizion3d.server.rest.app import app # noqa: E402 +from vizion3d.stereo.defaults import DEFAULT_STEREO_MODEL_URL # noqa: E402 +from vizion3d.stereo.handlers import StereoDepthHandler # noqa: E402 + +N_RUNS = 5 +COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_STEREO_COLD_LIMIT", "60.0")) +WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_STEREO_WARM_LIMIT", "5.0")) + +client = TestClient(app, raise_server_exceptions=True) + + +def _save_outputs(data: dict, run_dir: Path, run: int) -> None: + run_dir.mkdir(parents=True, exist_ok=True) + prefix = str(run_dir / f"run_{run:02d}") + + Path(prefix + ".depth_map.json").write_text(json.dumps(data["depth_map"])) + Path(prefix + ".disparity_map.json").write_text(json.dumps(data["disparity_map"])) + + if data.get("depth_image"): + Path(prefix + "_depth.png").write_bytes(base64.b64decode(data["depth_image"])) + + if data.get("point_cloud_ply"): + Path(prefix + "_point_cloud.ply").write_bytes(base64.b64decode(data["point_cloud_ply"])) + + +def _run_group( + model_backend: str, + stereo_image_pair: tuple[bytes, bytes], + stereo_advanced_config, + run_dir: Path, + scenario: str, + timing_collector, +) -> list[float]: + StereoDepthHandler._stereo_models.clear() + left_bytes, right_bytes = stereo_image_pair + timings: list[float] = [] + + for run in range(1, N_RUNS + 1): + t0 = time.perf_counter() + response = client.post( + "/lifting/stereo-depth", + files={ + "left_image": ("left.jpg", left_bytes, "image/jpeg"), + "right_image": ("right.jpg", right_bytes, "image/jpeg"), + }, + data={ + "model_backend": model_backend, + "return_depth_image": "true", + "return_point_cloud": "true", + "focal_length": str(stereo_advanced_config.focal_length), + "baseline": str(stereo_advanced_config.baseline), + "cx": str(stereo_advanced_config.cx), + "cy": str(stereo_advanced_config.cy), + "doffs": str(stereo_advanced_config.doffs), + "z_far": str(stereo_advanced_config.z_far), + "conf_threshold": str(stereo_advanced_config.conf_threshold), + "occ_threshold": str(stereo_advanced_config.occ_threshold), + }, + ) + elapsed = time.perf_counter() - t0 + timings.append(elapsed) + + assert response.status_code == 200, ( + f"Run {run} failed: {response.status_code} - {response.text[:300]}" + ) + data = response.json() + _save_outputs(data, run_dir, run) + timing_collector.add("Stereo REST", scenario, run, elapsed, str(run_dir)) + + assert isinstance(data["depth_map"], list) and len(data["depth_map"]) > 0 + assert isinstance(data["disparity_map"], list) and len(data["disparity_map"]) > 0 + assert data["max_depth"] >= data["min_depth"] + assert data["depth_image"] is not None + assert data["point_cloud_ply"] is not None + assert base64.b64decode(data["depth_image"])[:4] == b"\x89PNG" + assert base64.b64decode(data["point_cloud_ply"]).startswith(b"ply\n") + + assert len(StereoDepthHandler._stereo_models) > 0 + assert timings[0] < COLD_LIMIT + for elapsed in timings[1:]: + assert elapsed < WARM_LIMIT + + return timings + + +def test_stereo_rest_default_model( + stereo_image_pair, stereo_advanced_config, tmp_path, timing_collector +): + _run_group( + model_backend=DEFAULT_STEREO_MODEL_URL, + stereo_image_pair=stereo_image_pair, + stereo_advanced_config=stereo_advanced_config, + run_dir=tmp_path / "stereo_rest_default", + scenario="Default model", + timing_collector=timing_collector, + ) + + +def test_stereo_rest_local_model( + stereo_image_pair, + stereo_advanced_config, + local_stereo_model_path, + tmp_path, + timing_collector, +): + _run_group( + model_backend=local_stereo_model_path, + stereo_image_pair=stereo_image_pair, + stereo_advanced_config=stereo_advanced_config, + run_dir=tmp_path / "stereo_rest_local", + scenario="Local model", + timing_collector=timing_collector, + ) + + +def test_stereo_rest_advanced_config_accepted( + stereo_image_pair, stereo_advanced_config, local_stereo_model_path +): + StereoDepthHandler._stereo_models.clear() + left_bytes, right_bytes = stereo_image_pair + + response = client.post( + "/lifting/stereo-depth", + files={ + "left_image": ("left.jpg", left_bytes, "image/jpeg"), + "right_image": ("right.jpg", right_bytes, "image/jpeg"), + }, + data={ + "model_backend": local_stereo_model_path, + "return_point_cloud": "true", + "focal_length": str(stereo_advanced_config.focal_length), + "baseline": str(stereo_advanced_config.baseline), + "cx": str(stereo_advanced_config.cx), + "cy": str(stereo_advanced_config.cy), + "doffs": str(stereo_advanced_config.doffs), + "z_far": str(stereo_advanced_config.z_far), + "conf_threshold": str(stereo_advanced_config.conf_threshold), + "occ_threshold": str(stereo_advanced_config.occ_threshold), + "scale_factor": "0.5", + }, + ) + + assert response.status_code == 200 + data = response.json() + assert isinstance(data["depth_map"], list) and len(data["depth_map"]) > 0 + assert data["point_cloud_ply"] is not None + assert base64.b64decode(data["point_cloud_ply"]).startswith(b"ply\n") diff --git a/tests/unit/test_advanced_config.py b/tests/unit/test_advanced_config.py index 02ad122..1b6e432 100644 --- a/tests/unit/test_advanced_config.py +++ b/tests/unit/test_advanced_config.py @@ -16,6 +16,7 @@ # ── Fixtures ────────────────────────────────────────────────────────────────── + @pytest.fixture def fake_depth(): rng = np.random.default_rng(0) @@ -24,6 +25,7 @@ def fake_depth(): # ── DepthEstimationAdvanceConfig ────────────────────────────────────────────── + class TestDepthEstimationAdvanceConfig: def test_defaults_match_primesense(self): cfg = DepthEstimationAdvanceConfig() @@ -45,8 +47,12 @@ def test_partial_override_keeps_other_defaults(self): def test_all_fields_overridable(self): cfg = DepthEstimationAdvanceConfig( - fx=700.0, fy=701.0, cx=320.0, cy=241.0, - depth_scale=500.0, depth_trunc=5.0, + fx=700.0, + fy=701.0, + cx=320.0, + cy=241.0, + depth_scale=500.0, + depth_trunc=5.0, ) assert cfg.fx == 700.0 assert cfg.fy == 701.0 @@ -62,6 +68,7 @@ def test_invalid_type_rejected(self): # ── DepthEstimationCommand advanced_config field ────────────────────────────── + class TestDepthEstimationCommandAdvancedConfig: def test_default_advanced_config_is_correct_type(self): cmd = DepthEstimationCommand(image_input=b"img") @@ -92,6 +99,7 @@ def test_custom_config_stored_on_command(self): # ── _depth_array_to_rgbd_depth ──────────────────────────────────────────────── + class TestDepthArrayToRgbdDepth: def test_output_dtype_is_uint16(self): arr = np.array([[0.0, 1.0], [2.0, 3.0]], dtype=float) @@ -133,6 +141,7 @@ def test_min_value_is_always_zero(self): # ── Handler propagates config to Open3D ────────────────────────────────────── + class TestHandlerPropagatesAdvancedConfig: def test_custom_intrinsics_forwarded_to_pinhole(self, dummy_image_bytes, fake_depth): open3d = pytest.importorskip( @@ -209,15 +218,15 @@ def capturing(*args, **kwargs): # ── REST API propagates config form fields ──────────────────────────────────── + class TestRestAdvancedConfig: @pytest.fixture(autouse=True) def _setup(self): - pytest.importorskip( - "open3d", reason="open3d required — run: uv python pin 3.12 && uv sync" - ) + pytest.importorskip("open3d", reason="open3d required — run: uv python pin 3.12 && uv sync") from fastapi.testclient import TestClient from vizion3d.server.rest.app import app + self.client = TestClient(app) def _post(self, extra_data=None): @@ -235,7 +244,7 @@ def _post(self, extra_data=None): result.point_cloud = None result.mesh = None - with patch("vizion3d.server.rest.app.DepthEstimation") as mock_cls: + with patch("vizion3d.server.rest.depth_estimation.DepthEstimation") as mock_cls: mock_cls.return_value.run.return_value = result self.client.post( "/lifting/depth-estimation", @@ -283,14 +292,14 @@ def test_partial_override_does_not_affect_other_fields(self): # ── gRPC server propagates config proto fields ──────────────────────────────── + class TestGrpcAdvancedConfig: @pytest.fixture(autouse=True) def _setup(self): - pytest.importorskip( - "open3d", reason="open3d required — run: uv python pin 3.12 && uv sync" - ) + pytest.importorskip("open3d", reason="open3d required — run: uv python pin 3.12 && uv sync") from vizion3d.proto import lifting_pb2 from vizion3d.server.grpc.server import LiftingServiceServicer + self.pb2 = lifting_pb2 self.servicer = LiftingServiceServicer() self.context = MagicMock() @@ -327,8 +336,12 @@ def test_no_config_in_request_uses_defaults(self): def test_full_config_forwarded(self): proto_cfg = self.pb2.DepthEstimationAdvanceConfig( - fx=615.0, fy=616.0, cx=320.0, cy=241.0, - depth_scale=500.0, depth_trunc=3.0, + fx=615.0, + fy=616.0, + cx=320.0, + cy=241.0, + depth_scale=500.0, + depth_trunc=3.0, ) cmd = self._run(proto_cfg) assert cmd.advanced_config.fx == pytest.approx(615.0) @@ -342,8 +355,8 @@ def test_partial_config_overrides_only_set_fields(self): proto_cfg = self.pb2.DepthEstimationAdvanceConfig(fx=700.0, depth_trunc=2.0) cmd = self._run(proto_cfg) assert cmd.advanced_config.fx == pytest.approx(700.0) - assert cmd.advanced_config.fy == 525.0 # default - assert cmd.advanced_config.cx == 319.5 # default + assert cmd.advanced_config.fy == 525.0 # default + assert cmd.advanced_config.cx == 319.5 # default assert cmd.advanced_config.depth_scale == 1000.0 # default assert cmd.advanced_config.depth_trunc == pytest.approx(2.0) diff --git a/tests/unit/test_facade.py b/tests/unit/test_facade.py index 3764f2f..9782d64 100644 --- a/tests/unit/test_facade.py +++ b/tests/unit/test_facade.py @@ -32,6 +32,7 @@ def test_depth_estimation_returns_depth_image(dummy_image_bytes): assert isinstance(res.depth_image, o3d.geometry.Image) import numpy as np + arr = np.asarray(res.depth_image) assert arr.dtype == np.uint16 assert arr.shape == (100, 100) diff --git a/tests/unit/test_lifting_defaults.py b/tests/unit/test_lifting_defaults.py index 65ca3af..4ad7101 100644 --- a/tests/unit/test_lifting_defaults.py +++ b/tests/unit/test_lifting_defaults.py @@ -38,14 +38,8 @@ def test_loaded_checkpoint_cache_is_shared_across_handler_instances(): try: DepthEstimationHandler._depth_anything_models = {cache_key: cached_model} - assert ( - DepthEstimationHandler()._load_depth_anything_checkpoint(cache_key) - is cached_model - ) - assert ( - DepthEstimationHandler()._load_depth_anything_checkpoint(cache_key) - is cached_model - ) + assert DepthEstimationHandler()._load_depth_anything_checkpoint(cache_key) is cached_model + assert DepthEstimationHandler()._load_depth_anything_checkpoint(cache_key) is cached_model finally: DepthEstimationHandler._depth_anything_models = original_cache diff --git a/tests/unit/test_rest_api.py b/tests/unit/test_rest_api.py index 7d480b4..b080f47 100644 --- a/tests/unit/test_rest_api.py +++ b/tests/unit/test_rest_api.py @@ -7,7 +7,9 @@ pytest.importorskip("open3d", reason="open3d required — run: uv python pin 3.12 && uv sync") -from vizion3d.server.rest.app import app # noqa: E402 +from vizion3d.lifting.defaults import DEFAULT_DEPTH_MODEL_URL # noqa: E402 +from vizion3d.server.rest.app import app, create_app, run # noqa: E402 +from vizion3d.stereo.defaults import DEFAULT_STEREO_MODEL_URL # noqa: E402 client = TestClient(app) @@ -21,6 +23,18 @@ def image_file(): return buf +@pytest.fixture +def stereo_files(): + img = Image.new("RGB", (50, 50), color="green") + left = io.BytesIO() + right = io.BytesIO() + img.save(left, format="PNG") + img.save(right, format="PNG") + left.seek(0) + right.seek(0) + return left, right + + def _fake_result(depth_map=None): result = MagicMock() result.depth_map = depth_map or [[1.0, 2.0], [3.0, 4.0]] @@ -33,8 +47,20 @@ def _fake_result(depth_map=None): return result +def _fake_stereo_result(): + result = _fake_result() + result.disparity_map = [[4.0, 5.0], [6.0, 7.0]] + result.backend_used = "/fake/stereo.pth" + return result + + +def _uvicorn_app_routes(uvicorn_run) -> set[str]: + app_arg = uvicorn_run.call_args.args[0] + return {route.path for route in app_arg.routes} + + def test_depth_estimation_returns_200(image_file): - with patch("vizion3d.server.rest.app.DepthEstimation") as mock_cls: + with patch("vizion3d.server.rest.depth_estimation.DepthEstimation") as mock_cls: mock_cls.return_value.run.return_value = _fake_result() response = client.post( "/lifting/depth-estimation", @@ -44,7 +70,7 @@ def test_depth_estimation_returns_200(image_file): def test_depth_estimation_response_has_expected_keys(image_file): - with patch("vizion3d.server.rest.app.DepthEstimation") as mock_cls: + with patch("vizion3d.server.rest.depth_estimation.DepthEstimation") as mock_cls: mock_cls.return_value.run.return_value = _fake_result() response = client.post( "/lifting/depth-estimation", @@ -58,7 +84,7 @@ def test_depth_estimation_response_has_expected_keys(image_file): def test_depth_estimation_depth_map_is_nested_list(image_file): - with patch("vizion3d.server.rest.app.DepthEstimation") as mock_cls: + with patch("vizion3d.server.rest.depth_estimation.DepthEstimation") as mock_cls: mock_cls.return_value.run.return_value = _fake_result() response = client.post( "/lifting/depth-estimation", @@ -70,7 +96,7 @@ def test_depth_estimation_depth_map_is_nested_list(image_file): def test_depth_estimation_max_depth_gte_min_depth(image_file): - with patch("vizion3d.server.rest.app.DepthEstimation") as mock_cls: + with patch("vizion3d.server.rest.depth_estimation.DepthEstimation") as mock_cls: mock_cls.return_value.run.return_value = _fake_result() response = client.post( "/lifting/depth-estimation", @@ -81,7 +107,7 @@ def test_depth_estimation_max_depth_gte_min_depth(image_file): def test_depth_estimation_optional_outputs_null_by_default(image_file): - with patch("vizion3d.server.rest.app.DepthEstimation") as mock_cls: + with patch("vizion3d.server.rest.depth_estimation.DepthEstimation") as mock_cls: mock_cls.return_value.run.return_value = _fake_result() response = client.post( "/lifting/depth-estimation", @@ -94,7 +120,7 @@ def test_depth_estimation_optional_outputs_null_by_default(image_file): def test_depth_estimation_backend_used_is_returned(image_file): - with patch("vizion3d.server.rest.app.DepthEstimation") as mock_cls: + with patch("vizion3d.server.rest.depth_estimation.DepthEstimation") as mock_cls: mock_cls.return_value.run.return_value = _fake_result() response = client.post( "/lifting/depth-estimation", @@ -105,7 +131,7 @@ def test_depth_estimation_backend_used_is_returned(image_file): def test_depth_estimation_passes_form_fields_to_command(image_file): - with patch("vizion3d.server.rest.app.DepthEstimation") as mock_cls: + with patch("vizion3d.server.rest.depth_estimation.DepthEstimation") as mock_cls: mock_cls.return_value.run.return_value = _fake_result() client.post( "/lifting/depth-estimation", @@ -117,6 +143,193 @@ def test_depth_estimation_passes_form_fields_to_command(image_file): assert called_cmd.return_depth_image is False +def test_depth_estimation_uses_default_backend_when_omitted(image_file): + with patch("vizion3d.server.rest.depth_estimation.DepthEstimation") as mock_cls: + mock_cls.return_value.run.return_value = _fake_result() + client.post( + "/lifting/depth-estimation", + files={"image": ("test.png", image_file, "image/png")}, + ) + called_cmd = mock_cls.return_value.run.call_args[0][0] + assert called_cmd.model_backend == DEFAULT_DEPTH_MODEL_URL + + def test_depth_estimation_missing_image_returns_422(): response = client.post("/lifting/depth-estimation") assert response.status_code == 422 + + +def test_stereo_depth_returns_200(stereo_files): + left, right = stereo_files + with patch("vizion3d.server.rest.stereo_depth.StereoDepth") as mock_cls: + mock_cls.return_value.run.return_value = _fake_stereo_result() + response = client.post( + "/lifting/stereo-depth", + files={ + "left_image": ("left.png", left, "image/png"), + "right_image": ("right.png", right, "image/png"), + }, + ) + assert response.status_code == 200 + + +def test_stereo_depth_response_has_expected_keys(stereo_files): + left, right = stereo_files + with patch("vizion3d.server.rest.stereo_depth.StereoDepth") as mock_cls: + mock_cls.return_value.run.return_value = _fake_stereo_result() + response = client.post( + "/lifting/stereo-depth", + files={ + "left_image": ("left.png", left, "image/png"), + "right_image": ("right.png", right, "image/png"), + }, + ) + data = response.json() + assert "depth_map" in data + assert "disparity_map" in data + assert "min_depth" in data + assert "max_depth" in data + assert "backend_used" in data + + +def test_stereo_depth_uses_default_backend_when_omitted(stereo_files): + left, right = stereo_files + with patch("vizion3d.server.rest.stereo_depth.StereoDepth") as mock_cls: + mock_cls.return_value.run.return_value = _fake_stereo_result() + client.post( + "/lifting/stereo-depth", + files={ + "left_image": ("left.png", left, "image/png"), + "right_image": ("right.png", right, "image/png"), + }, + ) + called_cmd = mock_cls.return_value.run.call_args[0][0] + assert called_cmd.model_backend == DEFAULT_STEREO_MODEL_URL + + +def test_stereo_depth_passes_form_fields_to_command(stereo_files): + left, right = stereo_files + with patch("vizion3d.server.rest.stereo_depth.StereoDepth") as mock_cls: + mock_cls.return_value.run.return_value = _fake_stereo_result() + client.post( + "/lifting/stereo-depth", + files={ + "left_image": ("left.png", left, "image/png"), + "right_image": ("right.png", right, "image/png"), + }, + data={ + "model_backend": "/my/stereo.pth", + "return_depth_image": "true", + "focal_length": "1733.74", + "baseline": "536.62", + "scale_factor": "0.5", + }, + ) + called_cmd = mock_cls.return_value.run.call_args[0][0] + assert called_cmd.model_backend == "/my/stereo.pth" + assert called_cmd.return_depth_image is True + assert called_cmd.advanced_config.focal_length == pytest.approx(1733.74) + assert called_cmd.advanced_config.baseline == pytest.approx(536.62) + assert called_cmd.advanced_config.scale_factor == pytest.approx(0.5) + + +def test_create_app_depth_only_disables_stereo_endpoint(stereo_files, image_file): + depth_only = TestClient(create_app(enable_depth_estimation=True, enable_stereo_depth=False)) + response = depth_only.post( + "/lifting/stereo-depth", + files={ + "left_image": ("left.png", stereo_files[0], "image/png"), + "right_image": ("right.png", stereo_files[1], "image/png"), + }, + ) + assert response.status_code == 404 + + with patch("vizion3d.server.rest.depth_estimation.DepthEstimation") as mock_cls: + mock_cls.return_value.run.return_value = _fake_result() + response = depth_only.post( + "/lifting/depth-estimation", + files={"image": ("test.png", image_file, "image/png")}, + ) + assert response.status_code == 200 + + +def test_create_app_stereo_only_disables_depth_endpoint(stereo_files, image_file): + stereo_only = TestClient(create_app(enable_depth_estimation=False, enable_stereo_depth=True)) + response = stereo_only.post( + "/lifting/depth-estimation", + files={"image": ("test.png", image_file, "image/png")}, + ) + assert response.status_code == 404 + + left, right = stereo_files + with patch("vizion3d.server.rest.stereo_depth.StereoDepth") as mock_cls: + mock_cls.return_value.run.return_value = _fake_stereo_result() + response = stereo_only.post( + "/lifting/stereo-depth", + files={ + "left_image": ("left.png", left, "image/png"), + "right_image": ("right.png", right, "image/png"), + }, + ) + assert response.status_code == 200 + + +def test_run_preloads_enabled_feature_model_paths(): + with ( + patch("vizion3d.server.rest.app.depth_estimation.configure_model") as depth_cfg, + patch("vizion3d.server.rest.app.stereo_depth.configure_model") as stereo_cfg, + patch("vizion3d.server.rest.app.uvicorn.run") as uvicorn_run, + ): + run( + [ + "--host", + "127.0.0.1", + "--port", + "9000", + "--depth_model", + "/models/depth.pth", + "--stereo_model", + "/models/stereo.pth", + ] + ) + + depth_cfg.assert_called_once_with("/models/depth.pth") + stereo_cfg.assert_called_once_with("/models/stereo.pth") + uvicorn_run.assert_called_once() + assert uvicorn_run.call_args.kwargs["host"] == "127.0.0.1" + assert uvicorn_run.call_args.kwargs["port"] == 9000 + assert "/lifting/depth-estimation" in _uvicorn_app_routes(uvicorn_run) + assert "/lifting/stereo-depth" in _uvicorn_app_routes(uvicorn_run) + + +def test_run_model_path_enables_and_preloads_feature(): + with ( + patch("vizion3d.server.rest.app.depth_estimation.configure_model") as depth_cfg, + patch("vizion3d.server.rest.app.stereo_depth.configure_model") as stereo_cfg, + patch("vizion3d.server.rest.app.uvicorn.run") as uvicorn_run, + ): + run( + [ + "--depth_model", + "/models/depth.pth", + ] + ) + + depth_cfg.assert_called_once_with("/models/depth.pth") + stereo_cfg.assert_not_called() + assert "/lifting/depth-estimation" in _uvicorn_app_routes(uvicorn_run) + assert "/lifting/stereo-depth" not in _uvicorn_app_routes(uvicorn_run) + + +def test_run_only_selected_feature_does_not_enable_other_endpoint(): + with ( + patch("vizion3d.server.rest.app.depth_estimation.configure_model") as depth_cfg, + patch("vizion3d.server.rest.app.stereo_depth.configure_model") as stereo_cfg, + patch("vizion3d.server.rest.app.uvicorn.run") as uvicorn_run, + ): + run(["--stereo_depth", "--stereo_model", "/models/stereo.pth"]) + + depth_cfg.assert_not_called() + stereo_cfg.assert_called_once_with("/models/stereo.pth") + assert "/lifting/depth-estimation" not in _uvicorn_app_routes(uvicorn_run) + assert "/lifting/stereo-depth" in _uvicorn_app_routes(uvicorn_run) diff --git a/tests/unit/test_stereo_config.py b/tests/unit/test_stereo_config.py new file mode 100644 index 0000000..191b311 --- /dev/null +++ b/tests/unit/test_stereo_config.py @@ -0,0 +1,317 @@ +""" +Unit tests for StereoDepthAdvancedConfig and its propagation through +the command, handler, REST API, and gRPC server. +""" + +import io +from unittest.mock import MagicMock, patch + +import numpy as np +import pytest +from PIL import Image + +from vizion3d.stereo.commands import StereoDepthCommand +from vizion3d.stereo.models import StereoDepthAdvancedConfig + +# ── Fixtures ────────────────────────────────────────────────────────────────── + + +@pytest.fixture +def dummy_stereo_bytes(): + """Return a pair of identical small PNG images as bytes.""" + img = Image.new("RGB", (64, 48), color=(100, 150, 200)) + buf = io.BytesIO() + img.save(buf, format="PNG") + data = buf.getvalue() + return data, data # (left_bytes, right_bytes) + + +@pytest.fixture +def fake_disp(): + """Small synthetic disparity map.""" + rng = np.random.default_rng(42) + return rng.uniform(0.5, 50.0, (48, 64)).astype(np.float32) + + +# ── StereoDepthAdvancedConfig ───────────────────────────────────────────────── + + +class TestStereoDepthAdvancedConfig: + def test_defaults(self): + cfg = StereoDepthAdvancedConfig() + assert cfg.focal_length == 1000.0 + assert cfg.cx == 640.0 + assert cfg.cy == 360.0 + assert cfg.baseline == 100.0 + assert cfg.doffs == 0.0 + assert cfg.z_far == 10.0 + assert cfg.conf_threshold == 0.1 + assert cfg.occ_threshold == 0.5 + assert cfg.scale_factor == 1.0 + + def test_partial_override_keeps_other_defaults(self): + cfg = StereoDepthAdvancedConfig(focal_length=1733.74, baseline=536.62) + assert cfg.focal_length == pytest.approx(1733.74) + assert cfg.baseline == pytest.approx(536.62) + assert cfg.cx == 640.0 # unchanged + assert cfg.cy == 360.0 # unchanged + + def test_all_fields_overridable(self): + cfg = StereoDepthAdvancedConfig( + focal_length=800.0, + cx=320.0, + cy=240.0, + baseline=200.0, + doffs=5.0, + z_far=15.0, + conf_threshold=0.3, + occ_threshold=0.7, + scale_factor=0.5, + ) + assert cfg.focal_length == 800.0 + assert cfg.cx == 320.0 + assert cfg.cy == 240.0 + assert cfg.baseline == 200.0 + assert cfg.doffs == 5.0 + assert cfg.z_far == 15.0 + assert cfg.conf_threshold == 0.3 + assert cfg.occ_threshold == 0.7 + assert cfg.scale_factor == 0.5 + + def test_invalid_type_rejected(self): + with pytest.raises(Exception): + StereoDepthAdvancedConfig(focal_length="not_a_float") + + +# ── StereoDepthCommand advanced_config field ────────────────────────────────── + + +class TestStereoDepthCommandAdvancedConfig: + def test_default_advanced_config_is_correct_type(self, dummy_stereo_bytes): + left, right = dummy_stereo_bytes + cmd = StereoDepthCommand(left_image=left, right_image=right) + assert isinstance(cmd.advanced_config, StereoDepthAdvancedConfig) + + def test_default_advanced_config_has_expected_values(self, dummy_stereo_bytes): + left, right = dummy_stereo_bytes + cmd = StereoDepthCommand(left_image=left, right_image=right) + assert cmd.advanced_config.focal_length == 1000.0 + assert cmd.advanced_config.baseline == 100.0 + + def test_each_command_gets_separate_config_instance(self, dummy_stereo_bytes): + left, right = dummy_stereo_bytes + cmd1 = StereoDepthCommand(left_image=left, right_image=right) + cmd2 = StereoDepthCommand(left_image=left, right_image=right) + assert cmd1.advanced_config is not cmd2.advanced_config + + def test_mutation_of_one_command_does_not_affect_another(self, dummy_stereo_bytes): + left, right = dummy_stereo_bytes + cmd1 = StereoDepthCommand(left_image=left, right_image=right) + cmd2 = StereoDepthCommand(left_image=left, right_image=right) + cmd1.advanced_config.focal_length = 999.0 + assert cmd2.advanced_config.focal_length == 1000.0 + + def test_custom_config_stored_on_command(self, dummy_stereo_bytes): + left, right = dummy_stereo_bytes + cfg = StereoDepthAdvancedConfig(focal_length=1733.74, baseline=536.62) + cmd = StereoDepthCommand(left_image=left, right_image=right, advanced_config=cfg) + assert cmd.advanced_config.focal_length == pytest.approx(1733.74) + assert cmd.advanced_config.baseline == pytest.approx(536.62) + + +# ── Depth formula correctness ───────────────────────────────────────────────── + + +class TestDepthFormula: + """Validate the disparity→depth formula: depth_m = baseline * focal / disp / 1000.""" + + def test_depth_from_known_disparity(self): + # baseline=100mm, focal=1000px, disp=10px → depth = 100*1000/10/1000 = 10m + baseline = 100.0 + focal = 1000.0 + disp = 10.0 + expected_depth = baseline * focal / disp / 1000.0 + assert expected_depth == pytest.approx(10.0) + + def test_zero_disparity_gives_zero_depth(self): + # Handler sets depth_mm[disp<=0]=0.0, so depth_m=0 + disp = np.array([0.0, 1.0, 2.0]) + baseline = 100.0 + focal = 1000.0 + with np.errstate(divide="ignore", invalid="ignore"): + depth_mm = baseline * focal / (disp + 0.0) + depth_mm[disp <= 0] = 0.0 + depth_m = depth_mm / 1000.0 + assert depth_m[0] == 0.0 + + def test_doffs_shifts_depth(self): + # doffs shifts the effective disparity: depth = baseline * focal / (disp + doffs) + baseline = 100.0 + focal = 1000.0 + disp = 10.0 + doffs = 5.0 + depth = baseline * focal / (disp + doffs) / 1000.0 + expected = 100.0 * 1000.0 / 15.0 / 1000.0 + assert depth == pytest.approx(expected) + + +# ── REST API propagates config form fields ──────────────────────────────────── + + +class TestStereoRestAdvancedConfig: + @pytest.fixture(autouse=True) + def _setup(self): + pytest.importorskip("open3d", reason="open3d required — run: uv python pin 3.12 && uv sync") + from fastapi.testclient import TestClient + + from vizion3d.server.rest.app import app + + self.client = TestClient(app) + + def _post(self, extra_data=None): + img = Image.new("RGB", (32, 32), color="green") + buf = io.BytesIO() + img.save(buf, format="PNG") + img_bytes = buf.getvalue() + + result = MagicMock() + result.depth_map = [[1.0]] + result.disparity_map = [[5.0]] + result.min_depth = 1.0 + result.max_depth = 1.0 + result.backend_used = "/fake/stereo.pth" + result.depth_image = None + result.point_cloud = None + result.mesh = None + + with patch("vizion3d.server.rest.stereo_depth.StereoDepth") as mock_cls: + mock_cls.return_value.run.return_value = result + self.client.post( + "/lifting/stereo-depth", + files={ + "left_image": ("left.png", io.BytesIO(img_bytes), "image/png"), + "right_image": ("right.png", io.BytesIO(img_bytes), "image/png"), + }, + data=extra_data or {}, + ) + return mock_cls.return_value.run.call_args[0][0] + + def test_default_config_used_when_no_form_fields_sent(self): + cmd = self._post() + assert cmd.advanced_config.focal_length == 1000.0 + assert cmd.advanced_config.baseline == 100.0 + assert cmd.advanced_config.cx == 640.0 + assert cmd.advanced_config.cy == 360.0 + assert cmd.advanced_config.z_far == 10.0 + + def test_custom_focal_length_forwarded(self): + cmd = self._post({"focal_length": "1733.74"}) + assert cmd.advanced_config.focal_length == pytest.approx(1733.74) + assert cmd.advanced_config.baseline == 100.0 # unchanged + + def test_custom_baseline_forwarded(self): + cmd = self._post({"baseline": "536.62"}) + assert cmd.advanced_config.baseline == pytest.approx(536.62) + + def test_custom_cx_cy_forwarded(self): + cmd = self._post({"cx": "792.27", "cy": "541.89"}) + assert cmd.advanced_config.cx == pytest.approx(792.27) + assert cmd.advanced_config.cy == pytest.approx(541.89) + + def test_custom_z_far_forwarded(self): + cmd = self._post({"z_far": "5.0"}) + assert cmd.advanced_config.z_far == pytest.approx(5.0) + + def test_custom_scale_factor_forwarded(self): + cmd = self._post({"scale_factor": "0.5"}) + assert cmd.advanced_config.scale_factor == pytest.approx(0.5) + + def test_partial_override_does_not_affect_other_fields(self): + cmd = self._post({"focal_length": "800.0"}) + assert cmd.advanced_config.focal_length == pytest.approx(800.0) + assert cmd.advanced_config.cy == 360.0 # unchanged + + +# ── gRPC server propagates config proto fields ──────────────────────────────── + + +class TestStereoGrpcAdvancedConfig: + @pytest.fixture(autouse=True) + def _setup(self): + pytest.importorskip("open3d", reason="open3d required — run: uv python pin 3.12 && uv sync") + from vizion3d.proto import lifting_pb2 + from vizion3d.server.grpc.server import LiftingServiceServicer + + self.pb2 = lifting_pb2 + self.servicer = LiftingServiceServicer() + self.context = MagicMock() + + img = Image.new("RGB", (32, 32), color=(50, 100, 150)) + buf = io.BytesIO() + img.save(buf, format="PNG") + self.image_bytes = buf.getvalue() + + def _run(self, proto_cfg=None): + kwargs = { + "left_image_bytes": self.image_bytes, + "right_image_bytes": self.image_bytes, + } + if proto_cfg is not None: + kwargs["advanced_config"] = proto_cfg + request = self.pb2.StereoDepthRequest(**kwargs) + + result = MagicMock() + result.depth_map = [[1.0]] + result.disparity_map = [[5.0]] + result.min_depth = 1.0 + result.max_depth = 1.0 + result.backend_used = "/fake/stereo.pth" + result.depth_image = None + result.point_cloud = None + result.mesh = None + + with patch("vizion3d.server.grpc.server.StereoDepth") as mock_cls: + mock_cls.return_value.run.return_value = result + self.servicer.RunStereoDepth(request, self.context) + return mock_cls.return_value.run.call_args[0][0] + + def test_no_config_in_request_uses_defaults(self): + cmd = self._run() + assert cmd.advanced_config.focal_length == 1000.0 + assert cmd.advanced_config.baseline == 100.0 + + def test_full_config_forwarded(self): + proto_cfg = self.pb2.StereoDepthAdvancedConfig( + focal_length=1733.74, + cx=792.27, + cy=541.89, + baseline=536.62, + doffs=0.0, + z_far=8.0, + conf_threshold=0.2, + occ_threshold=0.6, + scale_factor=0.5, + ) + cmd = self._run(proto_cfg) + assert cmd.advanced_config.focal_length == pytest.approx(1733.74) + assert cmd.advanced_config.cx == pytest.approx(792.27) + assert cmd.advanced_config.cy == pytest.approx(541.89) + assert cmd.advanced_config.baseline == pytest.approx(536.62) + assert cmd.advanced_config.z_far == pytest.approx(8.0) + assert cmd.advanced_config.conf_threshold == pytest.approx(0.2) + assert cmd.advanced_config.occ_threshold == pytest.approx(0.6) + assert cmd.advanced_config.scale_factor == pytest.approx(0.5) + + def test_partial_config_overrides_only_set_fields(self): + proto_cfg = self.pb2.StereoDepthAdvancedConfig(focal_length=800.0, z_far=5.0) + cmd = self._run(proto_cfg) + assert cmd.advanced_config.focal_length == pytest.approx(800.0) + assert cmd.advanced_config.baseline == 100.0 # default + assert cmd.advanced_config.cx == 640.0 # default + assert cmd.advanced_config.z_far == pytest.approx(5.0) + + def test_empty_config_message_uses_all_defaults(self): + proto_cfg = self.pb2.StereoDepthAdvancedConfig() + cmd = self._run(proto_cfg) + assert cmd.advanced_config.focal_length == 1000.0 + assert cmd.advanced_config.baseline == 100.0 diff --git a/tests/unit/test_stereo_handler.py b/tests/unit/test_stereo_handler.py new file mode 100644 index 0000000..f2029cb --- /dev/null +++ b/tests/unit/test_stereo_handler.py @@ -0,0 +1,300 @@ +""" +Unit tests for StereoDepthHandler internals and the StereoDepth facade. + +These tests mock the S2M2 model so no checkpoint file is needed on disk. +""" + +import io +from unittest.mock import MagicMock, patch + +import numpy as np +import pytest +from PIL import Image + +from vizion3d.stereo.commands import StereoDepthCommand +from vizion3d.stereo.handlers import StereoDepthHandler +from vizion3d.stereo.models import StereoDepthAdvancedConfig + +# ── Fixtures ────────────────────────────────────────────────────────────────── + + +@pytest.fixture +def dummy_image_bytes(): + img = Image.new("RGB", (64, 48), color=(80, 120, 160)) + buf = io.BytesIO() + img.save(buf, format="PNG") + return buf.getvalue() + + +@pytest.fixture +def fake_disp(): + """Realistic disparity field: positive, 48×64 float32 array.""" + rng = np.random.default_rng(7) + return rng.uniform(1.0, 50.0, (48, 64)).astype(np.float32) + + +# ── Handler device helper ───────────────────────────────────────────────────── + + +class TestHandlerDeviceHelper: + def test_returns_cuda_when_available(self): + torch_mock = MagicMock() + torch_mock.cuda.is_available.return_value = True + assert StereoDepthHandler._torch_device(torch_mock) == "cuda" + + def test_returns_mps_when_cuda_unavailable(self): + torch_mock = MagicMock() + torch_mock.cuda.is_available.return_value = False + torch_mock.backends.mps.is_available.return_value = True + assert StereoDepthHandler._torch_device(torch_mock) == "mps" + + def test_returns_cpu_as_fallback(self): + torch_mock = MagicMock() + torch_mock.cuda.is_available.return_value = False + torch_mock.backends.mps.is_available.return_value = False + assert StereoDepthHandler._torch_device(torch_mock) == "cpu" + + +# ── Handler output shapes ───────────────────────────────────────────────────── + + +class TestHandlerOutputShapes: + """Verify depth_map, disparity_map shapes and metric depth computation.""" + + def test_depth_map_is_2d_list_of_floats(self, dummy_image_bytes, fake_disp): + with patch.object(StereoDepthHandler, "_run_s2m2", return_value=fake_disp): + cmd = StereoDepthCommand( + left_image=dummy_image_bytes, + right_image=dummy_image_bytes, + model_backend="/fake/model.pth", + ) + result = StereoDepthHandler().handle(cmd) + + assert isinstance(result.depth_map, list) + assert isinstance(result.depth_map[0], list) + assert isinstance(result.depth_map[0][0], float) + + def test_disparity_map_matches_input_shape(self, dummy_image_bytes, fake_disp): + with patch.object(StereoDepthHandler, "_run_s2m2", return_value=fake_disp): + cmd = StereoDepthCommand( + left_image=dummy_image_bytes, + right_image=dummy_image_bytes, + model_backend="/fake/model.pth", + ) + result = StereoDepthHandler().handle(cmd) + + H, W = fake_disp.shape + assert len(result.disparity_map) == H + assert len(result.disparity_map[0]) == W + + def test_min_max_depth_ordering(self, dummy_image_bytes, fake_disp): + with patch.object(StereoDepthHandler, "_run_s2m2", return_value=fake_disp): + result = StereoDepthHandler().handle( + StereoDepthCommand( + left_image=dummy_image_bytes, + right_image=dummy_image_bytes, + model_backend="/fake/model.pth", + ) + ) + assert result.max_depth >= result.min_depth + + def test_point_cloud_scale_is_1(self, dummy_image_bytes, fake_disp): + with patch.object(StereoDepthHandler, "_run_s2m2", return_value=fake_disp): + result = StereoDepthHandler().handle( + StereoDepthCommand( + left_image=dummy_image_bytes, + right_image=dummy_image_bytes, + model_backend="/fake/model.pth", + ) + ) + assert result.point_cloud_scale == 1.0 + + def test_backend_used_propagated(self, dummy_image_bytes, fake_disp): + with patch.object(StereoDepthHandler, "_run_s2m2", return_value=fake_disp): + result = StereoDepthHandler().handle( + StereoDepthCommand( + left_image=dummy_image_bytes, + right_image=dummy_image_bytes, + model_backend="/fake/model.pth", + ) + ) + assert result.backend_used == "/fake/model.pth" + + +# ── Depth formula integration ───────────────────────────────────────────────── + + +class TestDepthMetricConversion: + """Verify the handler converts disparity to real metric depth correctly.""" + + def test_high_disparity_gives_low_depth(self, dummy_image_bytes): + # All pixels at disp=100px: depth = 100 * 1000 / 100 / 1000 = 1m + uniform_disp = np.full((48, 64), 100.0, dtype=np.float32) + with patch.object(StereoDepthHandler, "_run_s2m2", return_value=uniform_disp): + result = StereoDepthHandler().handle( + StereoDepthCommand( + left_image=dummy_image_bytes, + right_image=dummy_image_bytes, + model_backend="/fake/model.pth", + advanced_config=StereoDepthAdvancedConfig(focal_length=1000.0, baseline=100.0), + ) + ) + # depth = baseline * focal / disp / 1000 = 100*1000/100/1000 = 1.0 m + assert result.min_depth == pytest.approx(1.0, abs=1e-3) + assert result.max_depth == pytest.approx(1.0, abs=1e-3) + + def test_zero_disparity_pixels_excluded_from_depth(self, dummy_image_bytes): + disp = np.zeros((48, 64), dtype=np.float32) + disp[0, 0] = 10.0 # one valid pixel + with patch.object(StereoDepthHandler, "_run_s2m2", return_value=disp): + result = StereoDepthHandler().handle( + StereoDepthCommand( + left_image=dummy_image_bytes, + right_image=dummy_image_bytes, + model_backend="/fake/model.pth", + advanced_config=StereoDepthAdvancedConfig(focal_length=1000.0, baseline=100.0), + ) + ) + # Zero disparity → zero depth; non-zero depth present for (0,0) + assert result.min_depth == pytest.approx(0.0) + assert result.max_depth > 0.0 + + +# ── Optional outputs ────────────────────────────────────────────────────────── + + +class TestHandlerOptionalOutputs: + def test_no_optional_outputs_by_default(self, dummy_image_bytes, fake_disp): + with patch.object(StereoDepthHandler, "_run_s2m2", return_value=fake_disp): + result = StereoDepthHandler().handle( + StereoDepthCommand( + left_image=dummy_image_bytes, + right_image=dummy_image_bytes, + model_backend="/fake/model.pth", + ) + ) + assert result.depth_image is None + assert result.point_cloud is None + assert result.mesh is None + + def test_return_depth_image_requires_open3d(self, dummy_image_bytes, fake_disp): + pytest.importorskip("open3d", reason="open3d required") + with patch.object(StereoDepthHandler, "_run_s2m2", return_value=fake_disp): + result = StereoDepthHandler().handle( + StereoDepthCommand( + left_image=dummy_image_bytes, + right_image=dummy_image_bytes, + model_backend="/fake/model.pth", + return_depth_image=True, + ) + ) + assert result.depth_image is not None + arr = np.asarray(result.depth_image) + assert arr.dtype == np.uint16 + + def test_return_point_cloud_requires_open3d(self, dummy_image_bytes, fake_disp): + pytest.importorskip("open3d", reason="open3d required") + with patch.object(StereoDepthHandler, "_run_s2m2", return_value=fake_disp): + result = StereoDepthHandler().handle( + StereoDepthCommand( + left_image=dummy_image_bytes, + right_image=dummy_image_bytes, + model_backend="/fake/model.pth", + return_point_cloud=True, + advanced_config=StereoDepthAdvancedConfig( + focal_length=1000.0, baseline=100.0, z_far=10.0 + ), + ) + ) + assert result.point_cloud is not None + assert result.point_cloud.has_points() + assert result.point_cloud.has_colors() + + def test_conf_occ_thresholds_filter_point_cloud(self, dummy_image_bytes, fake_disp): + pytest.importorskip("open3d", reason="open3d required") + occ = np.ones_like(fake_disp, dtype=np.float32) + conf = np.ones_like(fake_disp, dtype=np.float32) + conf[:, :32] = 0.0 + + with patch.object(StereoDepthHandler, "_run_s2m2", return_value=(fake_disp, occ, conf)): + result = StereoDepthHandler().handle( + StereoDepthCommand( + left_image=dummy_image_bytes, + right_image=dummy_image_bytes, + model_backend="/fake/model.pth", + return_point_cloud=True, + advanced_config=StereoDepthAdvancedConfig( + focal_length=1000.0, + baseline=100.0, + z_far=100.0, + conf_threshold=0.5, + occ_threshold=0.5, + ), + ) + ) + + assert result.point_cloud is not None + assert len(np.asarray(result.point_cloud.points)) < fake_disp.size + + def test_return_mesh_requires_open3d(self, dummy_image_bytes, fake_disp): + open3d = pytest.importorskip("open3d", reason="open3d required") + with patch.object(StereoDepthHandler, "_run_s2m2", return_value=fake_disp): + result = StereoDepthHandler().handle( + StereoDepthCommand( + left_image=dummy_image_bytes, + right_image=dummy_image_bytes, + model_backend="/fake/model.pth", + return_mesh=True, + advanced_config=StereoDepthAdvancedConfig( + focal_length=1000.0, baseline=100.0, z_far=10.0 + ), + ) + ) + assert result.mesh is not None + assert isinstance(result.mesh, open3d.geometry.TriangleMesh) + + +# ── S2M2 variant detection ──────────────────────────────────────────────────── + + +class TestS2M2VariantDetection: + def test_l_variant_detected(self): + from vizion3d.stereo.arch.s2m2 import s2m2_config_from_checkpoint + + cfg = s2m2_config_from_checkpoint("/models/stereo-depth-s2m2-L.pth") + assert cfg["feature_channels"] == 256 + assert cfg["num_transformer"] == 3 + + def test_s_variant_detected(self): + from vizion3d.stereo.arch.s2m2 import s2m2_config_from_checkpoint + + cfg = s2m2_config_from_checkpoint("/models/stereo-depth-s2m2-S.pth") + assert cfg["feature_channels"] == 128 + assert cfg["num_transformer"] == 1 + + def test_m_variant_detected(self): + from vizion3d.stereo.arch.s2m2 import s2m2_config_from_checkpoint + + cfg = s2m2_config_from_checkpoint("/models/stereo-depth-s2m2-M.pth") + assert cfg["feature_channels"] == 192 + assert cfg["num_transformer"] == 2 + + def test_xl_variant_detected(self): + from vizion3d.stereo.arch.s2m2 import s2m2_config_from_checkpoint + + cfg = s2m2_config_from_checkpoint("/models/stereo-depth-s2m2-XL.pth") + assert cfg["feature_channels"] == 384 + assert cfg["num_transformer"] == 3 + + def test_unknown_variant_falls_back_to_l(self): + from vizion3d.stereo.arch.s2m2 import s2m2_config_from_checkpoint + + cfg = s2m2_config_from_checkpoint("/models/my-custom-stereo-model.pth") + assert cfg["feature_channels"] == 256 # L default + assert cfg["num_transformer"] == 3 + + def test_xl_not_confused_with_l(self): + from vizion3d.stereo.arch.s2m2 import s2m2_config_from_checkpoint + + cfg = s2m2_config_from_checkpoint("/models/model-XL.pth") + assert cfg["feature_channels"] == 384 # XL, not L diff --git a/vizion3d/lifting/depth_anything.py b/vizion3d/lifting/depth_anything.py index 16bbc3b..5462829 100644 --- a/vizion3d/lifting/depth_anything.py +++ b/vizion3d/lifting/depth_anything.py @@ -94,11 +94,14 @@ def add(target: str, source: str): "pretrained.patch_embed.proj.bias", ) - layer_count = max( - int(key.split(".")[2]) - for key in state_dict - if key.startswith("pretrained.blocks.") and key.endswith(".norm1.weight") - ) + 1 + layer_count = ( + max( + int(key.split(".")[2]) + for key in state_dict + if key.startswith("pretrained.blocks.") and key.endswith(".norm1.weight") + ) + + 1 + ) for idx in range(layer_count): original = f"pretrained.blocks.{idx}" @@ -107,12 +110,10 @@ def add(target: str, source: str): add(f"{target}.norm1.weight", f"{original}.norm1.weight") add(f"{target}.norm1.bias", f"{original}.norm1.bias") - query_weight, key_weight, value_weight = state_dict[ - f"{original}.attn.qkv.weight" - ].chunk(3, dim=0) - query_bias, key_bias, value_bias = state_dict[f"{original}.attn.qkv.bias"].chunk( + query_weight, key_weight, value_weight = state_dict[f"{original}.attn.qkv.weight"].chunk( 3, dim=0 ) + query_bias, key_bias, value_bias = state_dict[f"{original}.attn.qkv.bias"].chunk(3, dim=0) converted[f"{target}.attention.attention.query.weight"] = query_weight converted[f"{target}.attention.attention.key.weight"] = key_weight diff --git a/vizion3d/lifting/handlers.py b/vizion3d/lifting/handlers.py index 3c7a0e8..660fbc5 100644 --- a/vizion3d/lifting/handlers.py +++ b/vizion3d/lifting/handlers.py @@ -51,8 +51,7 @@ def handle(self, command: DepthEstimationCommand) -> DepthEstimationResult: import open3d as o3d except ImportError: raise ImportError( - "open3d is required for depth image output. " - "Pin to Python 3.12 and run: uv sync" + "open3d is required for depth image output. Pin to Python 3.12 and run: uv sync" ) range_depth = max_depth - min_depth normalized = ( @@ -154,14 +153,22 @@ def _mesh_from_point_cloud(point_cloud, o3d): o3d.utility.DoubleVector([radius, radius * 2.0]), ) + @classmethod + def preload(cls, model_path: str) -> None: + """Resolve *model_path* (downloading if a URL) and load it into the class-level cache. + + Call this at server startup to ensure the model is in memory before the first request. + """ + from .defaults import resolve_model_backend + + resolved = resolve_model_backend(model_path) + cls()._load_depth_anything_checkpoint(resolved) + @staticmethod def _torch_device(torch_module) -> str: if torch_module.cuda.is_available(): return "cuda" - if ( - hasattr(torch_module.backends, "mps") - and torch_module.backends.mps.is_available() - ): + if hasattr(torch_module.backends, "mps") and torch_module.backends.mps.is_available(): return "mps" return "cpu" @@ -178,8 +185,7 @@ def _load_depth_anything_checkpoint(self, model_path: str): from transformers import DepthAnythingForDepthEstimation, DPTImageProcessor except ImportError as exc: raise ImportError( - "Depth Anything V2 checkpoints require torch and transformers. " - "Run: uv sync" + "Depth Anything V2 checkpoints require torch and transformers. Run: uv sync" ) from exc model = DepthAnythingForDepthEstimation(depth_anything_v2_config(model_path)) @@ -215,10 +221,10 @@ def _run_depth_anything_checkpoint(self, model_path: str, image: Image.Image) -> inputs = {name: value.to(device, non_blocking=True) for name, value in inputs.items()} device_type = device if isinstance(device, str) else device.type - if device_type == 'cuda': - autocast_ctx = torch.amp.autocast(device_type='cuda', dtype=torch.float16, enabled=True) - elif device_type == 'mps': - autocast_ctx = torch.amp.autocast(device_type='mps', dtype=torch.float16, enabled=True) + if device_type == "cuda": + autocast_ctx = torch.amp.autocast(device_type="cuda", dtype=torch.float16, enabled=True) + elif device_type == "mps": + autocast_ctx = torch.amp.autocast(device_type="mps", dtype=torch.float16, enabled=True) else: autocast_ctx = contextlib.nullcontext() @@ -232,7 +238,7 @@ def _run_depth_anything_checkpoint(self, model_path: str, image: Image.Image) -> depth = post_processed[0]["predicted_depth"] result = depth.detach().cpu().numpy().astype(np.float32) - if device_type == 'mps': + if device_type == "mps": torch.mps.empty_cache() return result diff --git a/vizion3d/proto/lifting.proto b/vizion3d/proto/lifting.proto index f859399..9848b26 100644 --- a/vizion3d/proto/lifting.proto +++ b/vizion3d/proto/lifting.proto @@ -4,8 +4,11 @@ package vizion3d.lifting; service LiftingService { rpc RunDepthEstimation (DepthEstimationRequest) returns (DepthEstimationResponse); + rpc RunStereoDepth (StereoDepthRequest) returns (StereoDepthResponse); } +// ── Depth Estimation ────────────────────────────────────────────────────────── + message DepthEstimationAdvanceConfig { optional float fx = 1; optional float fy = 2; @@ -38,3 +41,38 @@ message DepthEstimationResponse { bytes point_cloud_ply = 6; bytes mesh_ply = 7; } + +// ── Stereo Depth ────────────────────────────────────────────────────────────── + +message StereoDepthAdvancedConfig { + optional float focal_length = 1; + optional float cx = 2; + optional float cy = 3; + optional float baseline = 4; + optional float doffs = 5; + optional float z_far = 6; + optional float conf_threshold = 7; + optional float occ_threshold = 8; + optional float scale_factor = 9; +} + +message StereoDepthRequest { + bytes left_image_bytes = 1; + bytes right_image_bytes = 2; + string model_backend = 3; + bool return_depth_image = 4; + bool return_point_cloud = 5; + bool return_mesh = 6; + optional StereoDepthAdvancedConfig advanced_config = 7; +} + +message StereoDepthResponse { + repeated FloatRow depth_map = 1; + repeated FloatRow disparity_map = 2; + float min_depth = 3; + float max_depth = 4; + string backend_used = 5; + bytes depth_image = 6; + bytes point_cloud_ply = 7; + bytes mesh_ply = 8; +} diff --git a/vizion3d/proto/lifting_pb2.py b/vizion3d/proto/lifting_pb2.py index f488181..d43ef44 100644 --- a/vizion3d/proto/lifting_pb2.py +++ b/vizion3d/proto/lifting_pb2.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE -# source: lifting.proto +# source: vizion3d/proto/lifting.proto # Protobuf Python Version: 6.31.1 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor @@ -15,7 +15,7 @@ 31, 1, '', - 'lifting.proto' + 'vizion3d/proto/lifting.proto' ) # @@protoc_insertion_point(imports) @@ -24,21 +24,27 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rlifting.proto\x12\x10vizion3d.lifting\"\xd2\x01\n\x1c\x44\x65pthEstimationAdvanceConfig\x12\x0f\n\x02\x66x\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x0f\n\x02\x66y\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x0f\n\x02\x63x\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x0f\n\x02\x63y\x18\x04 \x01(\x02H\x03\x88\x01\x01\x12\x18\n\x0b\x64\x65pth_scale\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x18\n\x0b\x64\x65pth_trunc\x18\x06 \x01(\x02H\x05\x88\x01\x01\x42\x05\n\x03_fxB\x05\n\x03_fyB\x05\n\x03_cxB\x05\n\x03_cyB\x0e\n\x0c_depth_scaleB\x0e\n\x0c_depth_trunc\"\xa7\x02\n\x16\x44\x65pthEstimationRequest\x12\x13\n\x0bimage_bytes\x18\x01 \x01(\x0c\x12\x15\n\rmodel_backend\x18\x02 \x01(\t\x12\x1a\n\x12return_depth_image\x18\x03 \x01(\x08\x12\x1a\n\x12return_point_cloud\x18\x04 \x01(\x08\x12\x13\n\x0breturn_mesh\x18\x05 \x01(\x08\x12\x1d\n\x10local_model_path\x18\x06 \x01(\tH\x00\x88\x01\x01\x12L\n\x0f\x61\x64vanced_config\x18\x07 \x01(\x0b\x32..vizion3d.lifting.DepthEstimationAdvanceConfigH\x01\x88\x01\x01\x42\x13\n\x11_local_model_pathB\x12\n\x10_advanced_config\"\x1a\n\x08\x46loatRow\x12\x0e\n\x06values\x18\x01 \x03(\x02\"\xc4\x01\n\x17\x44\x65pthEstimationResponse\x12-\n\tdepth_map\x18\x01 \x03(\x0b\x32\x1a.vizion3d.lifting.FloatRow\x12\x11\n\tmin_depth\x18\x02 \x01(\x02\x12\x11\n\tmax_depth\x18\x03 \x01(\x02\x12\x14\n\x0c\x62\x61\x63kend_used\x18\x04 \x01(\t\x12\x13\n\x0b\x64\x65pth_image\x18\x05 \x01(\x0c\x12\x17\n\x0fpoint_cloud_ply\x18\x06 \x01(\x0c\x12\x10\n\x08mesh_ply\x18\x07 \x01(\x0c\x32{\n\x0eLiftingService\x12i\n\x12RunDepthEstimation\x12(.vizion3d.lifting.DepthEstimationRequest\x1a).vizion3d.lifting.DepthEstimationResponseb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cvizion3d/proto/lifting.proto\x12\x10vizion3d.lifting\"\xd2\x01\n\x1c\x44\x65pthEstimationAdvanceConfig\x12\x0f\n\x02\x66x\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x0f\n\x02\x66y\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x0f\n\x02\x63x\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x0f\n\x02\x63y\x18\x04 \x01(\x02H\x03\x88\x01\x01\x12\x18\n\x0b\x64\x65pth_scale\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x18\n\x0b\x64\x65pth_trunc\x18\x06 \x01(\x02H\x05\x88\x01\x01\x42\x05\n\x03_fxB\x05\n\x03_fyB\x05\n\x03_cxB\x05\n\x03_cyB\x0e\n\x0c_depth_scaleB\x0e\n\x0c_depth_trunc\"\xa7\x02\n\x16\x44\x65pthEstimationRequest\x12\x13\n\x0bimage_bytes\x18\x01 \x01(\x0c\x12\x15\n\rmodel_backend\x18\x02 \x01(\t\x12\x1a\n\x12return_depth_image\x18\x03 \x01(\x08\x12\x1a\n\x12return_point_cloud\x18\x04 \x01(\x08\x12\x13\n\x0breturn_mesh\x18\x05 \x01(\x08\x12\x1d\n\x10local_model_path\x18\x06 \x01(\tH\x00\x88\x01\x01\x12L\n\x0f\x61\x64vanced_config\x18\x07 \x01(\x0b\x32..vizion3d.lifting.DepthEstimationAdvanceConfigH\x01\x88\x01\x01\x42\x13\n\x11_local_model_pathB\x12\n\x10_advanced_config\"\x1a\n\x08\x46loatRow\x12\x0e\n\x06values\x18\x01 \x03(\x02\"\xc4\x01\n\x17\x44\x65pthEstimationResponse\x12-\n\tdepth_map\x18\x01 \x03(\x0b\x32\x1a.vizion3d.lifting.FloatRow\x12\x11\n\tmin_depth\x18\x02 \x01(\x02\x12\x11\n\tmax_depth\x18\x03 \x01(\x02\x12\x14\n\x0c\x62\x61\x63kend_used\x18\x04 \x01(\t\x12\x13\n\x0b\x64\x65pth_image\x18\x05 \x01(\x0c\x12\x17\n\x0fpoint_cloud_ply\x18\x06 \x01(\x0c\x12\x10\n\x08mesh_ply\x18\x07 \x01(\x0c\"\xe1\x02\n\x19StereoDepthAdvancedConfig\x12\x19\n\x0c\x66ocal_length\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x0f\n\x02\x63x\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x0f\n\x02\x63y\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x15\n\x08\x62\x61seline\x18\x04 \x01(\x02H\x03\x88\x01\x01\x12\x12\n\x05\x64offs\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x12\n\x05z_far\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x1b\n\x0e\x63onf_threshold\x18\x07 \x01(\x02H\x06\x88\x01\x01\x12\x1a\n\rocc_threshold\x18\x08 \x01(\x02H\x07\x88\x01\x01\x12\x19\n\x0cscale_factor\x18\t \x01(\x02H\x08\x88\x01\x01\x42\x0f\n\r_focal_lengthB\x05\n\x03_cxB\x05\n\x03_cyB\x0b\n\t_baselineB\x08\n\x06_doffsB\x08\n\x06_z_farB\x11\n\x0f_conf_thresholdB\x10\n\x0e_occ_thresholdB\x0f\n\r_scale_factor\"\x8c\x02\n\x12StereoDepthRequest\x12\x18\n\x10left_image_bytes\x18\x01 \x01(\x0c\x12\x19\n\x11right_image_bytes\x18\x02 \x01(\x0c\x12\x15\n\rmodel_backend\x18\x03 \x01(\t\x12\x1a\n\x12return_depth_image\x18\x04 \x01(\x08\x12\x1a\n\x12return_point_cloud\x18\x05 \x01(\x08\x12\x13\n\x0breturn_mesh\x18\x06 \x01(\x08\x12I\n\x0f\x61\x64vanced_config\x18\x07 \x01(\x0b\x32+.vizion3d.lifting.StereoDepthAdvancedConfigH\x00\x88\x01\x01\x42\x12\n\x10_advanced_config\"\xf3\x01\n\x13StereoDepthResponse\x12-\n\tdepth_map\x18\x01 \x03(\x0b\x32\x1a.vizion3d.lifting.FloatRow\x12\x31\n\rdisparity_map\x18\x02 \x03(\x0b\x32\x1a.vizion3d.lifting.FloatRow\x12\x11\n\tmin_depth\x18\x03 \x01(\x02\x12\x11\n\tmax_depth\x18\x04 \x01(\x02\x12\x14\n\x0c\x62\x61\x63kend_used\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65pth_image\x18\x06 \x01(\x0c\x12\x17\n\x0fpoint_cloud_ply\x18\x07 \x01(\x0c\x12\x10\n\x08mesh_ply\x18\x08 \x01(\x0c\x32\xda\x01\n\x0eLiftingService\x12i\n\x12RunDepthEstimation\x12(.vizion3d.lifting.DepthEstimationRequest\x1a).vizion3d.lifting.DepthEstimationResponse\x12]\n\x0eRunStereoDepth\x12$.vizion3d.lifting.StereoDepthRequest\x1a%.vizion3d.lifting.StereoDepthResponseb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) -_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'lifting_pb2', _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vizion3d.proto.lifting_pb2', _globals) if not _descriptor._USE_C_DESCRIPTORS: DESCRIPTOR._loaded_options = None - _globals['_DEPTHESTIMATIONADVANCECONFIG']._serialized_start=36 - _globals['_DEPTHESTIMATIONADVANCECONFIG']._serialized_end=246 - _globals['_DEPTHESTIMATIONREQUEST']._serialized_start=249 - _globals['_DEPTHESTIMATIONREQUEST']._serialized_end=544 - _globals['_FLOATROW']._serialized_start=546 - _globals['_FLOATROW']._serialized_end=572 - _globals['_DEPTHESTIMATIONRESPONSE']._serialized_start=575 - _globals['_DEPTHESTIMATIONRESPONSE']._serialized_end=771 - _globals['_LIFTINGSERVICE']._serialized_start=773 - _globals['_LIFTINGSERVICE']._serialized_end=896 + _globals['_DEPTHESTIMATIONADVANCECONFIG']._serialized_start=51 + _globals['_DEPTHESTIMATIONADVANCECONFIG']._serialized_end=261 + _globals['_DEPTHESTIMATIONREQUEST']._serialized_start=264 + _globals['_DEPTHESTIMATIONREQUEST']._serialized_end=559 + _globals['_FLOATROW']._serialized_start=561 + _globals['_FLOATROW']._serialized_end=587 + _globals['_DEPTHESTIMATIONRESPONSE']._serialized_start=590 + _globals['_DEPTHESTIMATIONRESPONSE']._serialized_end=786 + _globals['_STEREODEPTHADVANCEDCONFIG']._serialized_start=789 + _globals['_STEREODEPTHADVANCEDCONFIG']._serialized_end=1142 + _globals['_STEREODEPTHREQUEST']._serialized_start=1145 + _globals['_STEREODEPTHREQUEST']._serialized_end=1413 + _globals['_STEREODEPTHRESPONSE']._serialized_start=1416 + _globals['_STEREODEPTHRESPONSE']._serialized_end=1659 + _globals['_LIFTINGSERVICE']._serialized_start=1662 + _globals['_LIFTINGSERVICE']._serialized_end=1880 # @@protoc_insertion_point(module_scope) diff --git a/vizion3d/proto/lifting_pb2_grpc.py b/vizion3d/proto/lifting_pb2_grpc.py index a93fd0c..bf0be99 100644 --- a/vizion3d/proto/lifting_pb2_grpc.py +++ b/vizion3d/proto/lifting_pb2_grpc.py @@ -3,7 +3,7 @@ import grpc import warnings -import lifting_pb2 as lifting__pb2 +from vizion3d.proto import lifting_pb2 as vizion3d_dot_proto_dot_lifting__pb2 GRPC_GENERATED_VERSION = '1.80.0' GRPC_VERSION = grpc.__version__ @@ -18,7 +18,7 @@ if _version_not_supported: raise RuntimeError( f'The grpc package installed is at version {GRPC_VERSION},' - + ' but the generated code in lifting_pb2_grpc.py depends on' + + ' but the generated code in vizion3d/proto/lifting_pb2_grpc.py depends on' + f' grpcio>={GRPC_GENERATED_VERSION}.' + f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}' + f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.' @@ -36,8 +36,13 @@ def __init__(self, channel): """ self.RunDepthEstimation = channel.unary_unary( '/vizion3d.lifting.LiftingService/RunDepthEstimation', - request_serializer=lifting__pb2.DepthEstimationRequest.SerializeToString, - response_deserializer=lifting__pb2.DepthEstimationResponse.FromString, + request_serializer=vizion3d_dot_proto_dot_lifting__pb2.DepthEstimationRequest.SerializeToString, + response_deserializer=vizion3d_dot_proto_dot_lifting__pb2.DepthEstimationResponse.FromString, + _registered_method=True) + self.RunStereoDepth = channel.unary_unary( + '/vizion3d.lifting.LiftingService/RunStereoDepth', + request_serializer=vizion3d_dot_proto_dot_lifting__pb2.StereoDepthRequest.SerializeToString, + response_deserializer=vizion3d_dot_proto_dot_lifting__pb2.StereoDepthResponse.FromString, _registered_method=True) @@ -50,13 +55,24 @@ def RunDepthEstimation(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def RunStereoDepth(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def add_LiftingServiceServicer_to_server(servicer, server): rpc_method_handlers = { 'RunDepthEstimation': grpc.unary_unary_rpc_method_handler( servicer.RunDepthEstimation, - request_deserializer=lifting__pb2.DepthEstimationRequest.FromString, - response_serializer=lifting__pb2.DepthEstimationResponse.SerializeToString, + request_deserializer=vizion3d_dot_proto_dot_lifting__pb2.DepthEstimationRequest.FromString, + response_serializer=vizion3d_dot_proto_dot_lifting__pb2.DepthEstimationResponse.SerializeToString, + ), + 'RunStereoDepth': grpc.unary_unary_rpc_method_handler( + servicer.RunStereoDepth, + request_deserializer=vizion3d_dot_proto_dot_lifting__pb2.StereoDepthRequest.FromString, + response_serializer=vizion3d_dot_proto_dot_lifting__pb2.StereoDepthResponse.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler( @@ -84,8 +100,35 @@ def RunDepthEstimation(request, request, target, '/vizion3d.lifting.LiftingService/RunDepthEstimation', - lifting__pb2.DepthEstimationRequest.SerializeToString, - lifting__pb2.DepthEstimationResponse.FromString, + vizion3d_dot_proto_dot_lifting__pb2.DepthEstimationRequest.SerializeToString, + vizion3d_dot_proto_dot_lifting__pb2.DepthEstimationResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def RunStereoDepth(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/vizion3d.lifting.LiftingService/RunStereoDepth', + vizion3d_dot_proto_dot_lifting__pb2.StereoDepthRequest.SerializeToString, + vizion3d_dot_proto_dot_lifting__pb2.StereoDepthResponse.FromString, options, channel_credentials, insecure, diff --git a/vizion3d/server/grpc/server.py b/vizion3d/server/grpc/server.py index 48f85d1..36d2d5a 100644 --- a/vizion3d/server/grpc/server.py +++ b/vizion3d/server/grpc/server.py @@ -1,3 +1,17 @@ +""" +gRPC server for the vizion3d Lifting service. + +Exposes two RPC methods: +- ``RunDepthEstimation`` — monocular depth from a single image. +- ``RunStereoDepth`` — metric depth from a rectified stereo image pair. + +Start with:: + + uv run vizion3d-serve-grpc + # or + python -m vizion3d.server.grpc.server +""" + import io import logging from concurrent import futures @@ -11,9 +25,15 @@ from vizion3d.lifting.models import DepthEstimationAdvanceConfig from vizion3d.lifting.utils import create_mesh_ply_binary, create_ply_binary from vizion3d.proto import lifting_pb2, lifting_pb2_grpc +from vizion3d.stereo import StereoDepth, StereoDepthCommand +from vizion3d.stereo.defaults import DEFAULT_STEREO_MODEL_URL +from vizion3d.stereo.models import StereoDepthAdvancedConfig + +# ── Shared serialisation helpers ────────────────────────────────────────────── def _o3d_depth_image_to_png_bytes(o3d_image) -> bytes: + """Encode an Open3D uint16 depth image as a PNG byte string.""" arr = np.asarray(o3d_image) buf = io.BytesIO() Image.fromarray(arr).save(buf, format="PNG") @@ -21,20 +41,41 @@ def _o3d_depth_image_to_png_bytes(o3d_image) -> bytes: def _o3d_point_cloud_to_ply_bytes(pcd) -> bytes: + """Serialise an Open3D PointCloud to binary PLY bytes.""" points = np.asarray(pcd.points).astype(np.float32) colors = (np.asarray(pcd.colors) * 255).astype(np.uint8) return create_ply_binary(points, colors) def _o3d_mesh_to_ply_bytes(mesh) -> bytes: + """Serialise an Open3D TriangleMesh to binary PLY bytes.""" points = np.asarray(mesh.vertices).astype(np.float32) colors = (np.asarray(mesh.vertex_colors) * 255).astype(np.uint8) faces = np.asarray(mesh.triangles).astype(np.int32) return create_mesh_ply_binary(points, colors, faces) +# ── gRPC Servicer ───────────────────────────────────────────────────────────── + + class LiftingServiceServicer(lifting_pb2_grpc.LiftingServiceServicer): + """Implements the LiftingService proto RPC methods.""" + + # ── RunDepthEstimation ──────────────────────────────────────────────────── + def RunDepthEstimation(self, request, context): + """Handle a monocular depth estimation request. + + Unmarshals the proto config, dispatches through the CQRS command bus, and + packs the result back into a proto response message. + + Args: + request: ``DepthEstimationRequest`` proto message. + context: gRPC server context. + + Returns: + ``DepthEstimationResponse`` proto message. + """ base_cfg = DepthEstimationAdvanceConfig() if request.HasField("advanced_config"): proto_cfg = request.advanced_config @@ -69,31 +110,91 @@ def RunDepthEstimation(self, request, context): max_depth=result.max_depth, backend_used=result.backend_used, ) - for row in result.depth_map: response.depth_map.append(lifting_pb2.FloatRow(values=row)) - if result.depth_image is not None: response.depth_image = _o3d_depth_image_to_png_bytes(result.depth_image) - if result.point_cloud is not None: response.point_cloud_ply = _o3d_point_cloud_to_ply_bytes(result.point_cloud) - if result.mesh is not None: response.mesh_ply = _o3d_mesh_to_ply_bytes(result.mesh) + return response + + # ── RunStereoDepth ──────────────────────────────────────────────────────── + def RunStereoDepth(self, request, context): + """Handle a stereo depth estimation request. + + Unmarshals the proto config, dispatches through the CQRS command bus, and + packs the result back into a proto response message. + + Args: + request: ``StereoDepthRequest`` proto message. + context: gRPC server context. + + Returns: + ``StereoDepthResponse`` proto message. + """ + base_cfg = StereoDepthAdvancedConfig() + if request.HasField("advanced_config"): + proto_cfg = request.advanced_config + + def _f(field: str, default): + return getattr(proto_cfg, field) if proto_cfg.HasField(field) else default + + base_cfg = StereoDepthAdvancedConfig( + focal_length=_f("focal_length", base_cfg.focal_length), + cx=_f("cx", base_cfg.cx), + cy=_f("cy", base_cfg.cy), + baseline=_f("baseline", base_cfg.baseline), + doffs=_f("doffs", base_cfg.doffs), + z_far=_f("z_far", base_cfg.z_far), + conf_threshold=_f("conf_threshold", base_cfg.conf_threshold), + occ_threshold=_f("occ_threshold", base_cfg.occ_threshold), + scale_factor=_f("scale_factor", base_cfg.scale_factor), + ) + + cmd = StereoDepthCommand( + left_image=request.left_image_bytes, + right_image=request.right_image_bytes, + model_backend=request.model_backend or DEFAULT_STEREO_MODEL_URL, + return_depth_image=request.return_depth_image, + return_point_cloud=request.return_point_cloud, + return_mesh=request.return_mesh, + advanced_config=base_cfg, + ) + result = StereoDepth().run(cmd) + + response = lifting_pb2.StereoDepthResponse( + min_depth=result.min_depth, + max_depth=result.max_depth, + backend_used=result.backend_used, + ) + for row in result.depth_map: + response.depth_map.append(lifting_pb2.FloatRow(values=row)) + for row in result.disparity_map: + response.disparity_map.append(lifting_pb2.FloatRow(values=row)) + if result.depth_image is not None: + response.depth_image = _o3d_depth_image_to_png_bytes(result.depth_image) + if result.point_cloud is not None: + response.point_cloud_ply = _o3d_point_cloud_to_ply_bytes(result.point_cloud) + if result.mesh is not None: + response.mesh_ply = _o3d_mesh_to_ply_bytes(result.mesh) return response -_MAX_MSG = 500 * 1024 * 1024 # 500 MB +# ── Server bootstrap ────────────────────────────────────────────────────────── + +_MAX_MSG = 500 * 1024 * 1024 # 500 MB _GRPC_OPTIONS = [ - ("grpc.max_send_message_length", _MAX_MSG), + ("grpc.max_send_message_length", _MAX_MSG), ("grpc.max_receive_message_length", _MAX_MSG), ] def serve(): + """Start the gRPC server on port 50051 and block until terminated.""" server = grpc.server( futures.ThreadPoolExecutor(max_workers=10), options=_GRPC_OPTIONS, diff --git a/vizion3d/server/rest/app.py b/vizion3d/server/rest/app.py index e52b808..b20c6b1 100644 --- a/vizion3d/server/rest/app.py +++ b/vizion3d/server/rest/app.py @@ -1,119 +1,142 @@ -import base64 -import io +""" +FastAPI REST server for the vizion3d Lifting service. + +Registers feature routers under the ``/lifting`` prefix: +- ``POST /lifting/depth-estimation`` — monocular depth from a single image. +- ``POST /lifting/stereo-depth`` — metric depth from a rectified stereo pair. + +Start with:: + + uv run vizion3d-serve-rest + + # Enable only depth estimation: + uv run vizion3d-serve-rest --depth_estimation + + # Enable only stereo depth with a pre-loaded local model: + uv run vizion3d-serve-rest --stereo_depth --stereo_model /path/to/stereo-depth-s2m2-L.pth + + # Both features, custom model paths (pre-loaded at startup): + uv run vizion3d-serve-rest \\ + --depth_model /path/to/depth_anything_v2_vitb.pth \\ + --stereo_model /path/to/stereo-depth-s2m2-L.pth +""" + +import argparse -import numpy as np import uvicorn -from fastapi import APIRouter, FastAPI, File, Form, Request, UploadFile +from fastapi import APIRouter, FastAPI, Request from fastapi.responses import JSONResponse -from PIL import Image - -from vizion3d.lifting import DepthEstimation, DepthEstimationCommand -from vizion3d.lifting.defaults import DEFAULT_DEPTH_MODEL_URL -from vizion3d.lifting.models import DepthEstimationAdvanceConfig -from vizion3d.lifting.utils import create_mesh_ply_binary, create_ply_binary - -_MAX_BODY = 500 * 1024 * 1024 # 500 MB - -app = FastAPI(title="vizion3d REST API", version="1.0.0") - - -@app.middleware("http") -async def limit_body_size(request: Request, call_next): - content_length = request.headers.get("content-length") - if content_length and int(content_length) > _MAX_BODY: - return JSONResponse( - {"detail": "Request body exceeds the 500 MB limit."}, - status_code=413, - ) - return await call_next(request) - -lifting_router = APIRouter(prefix="/lifting", tags=["Lifting (2D -> 3D)"]) - - -def _o3d_depth_image_to_png_bytes(o3d_image) -> bytes: - arr = np.asarray(o3d_image) - buf = io.BytesIO() - Image.fromarray(arr).save(buf, format="PNG") - return buf.getvalue() - - -def _o3d_point_cloud_to_ply_bytes(pcd) -> bytes: - points = np.asarray(pcd.points).astype(np.float32) - colors = (np.asarray(pcd.colors) * 255).astype(np.uint8) - return create_ply_binary(points, colors) - - -def _o3d_mesh_to_ply_bytes(mesh) -> bytes: - points = np.asarray(mesh.vertices).astype(np.float32) - colors = (np.asarray(mesh.vertex_colors) * 255).astype(np.uint8) - faces = np.asarray(mesh.triangles).astype(np.int32) - return create_mesh_ply_binary(points, colors, faces) - - -@lifting_router.post("/depth-estimation") -async def depth_estimation( - image: UploadFile = File(...), - model_backend: str = Form(DEFAULT_DEPTH_MODEL_URL), - return_depth_image: bool = Form(False), - return_point_cloud: bool = Form(False), - return_mesh: bool = Form(False), - fx: float | None = Form(None), - fy: float | None = Form(None), - cx: float | None = Form(None), - cy: float | None = Form(None), - depth_scale: float | None = Form(None), - depth_trunc: float | None = Form(None), -): - image_bytes = await image.read() - base_cfg = DepthEstimationAdvanceConfig() - advanced_config = DepthEstimationAdvanceConfig( - fx=fx if fx is not None else base_cfg.fx, - fy=fy if fy is not None else base_cfg.fy, - cx=cx if cx is not None else base_cfg.cx, - cy=cy if cy is not None else base_cfg.cy, - depth_scale=depth_scale if depth_scale is not None else base_cfg.depth_scale, - depth_trunc=depth_trunc if depth_trunc is not None else base_cfg.depth_trunc, + +from vizion3d.server.rest import depth_estimation, stereo_depth + +_MAX_BODY = 500 * 1024 * 1024 # 500 MB + + +def create_app( + *, + enable_depth_estimation: bool = True, + enable_stereo_depth: bool = True, +) -> FastAPI: + """Build and return a FastAPI application with the selected feature routers. + + Args: + enable_depth_estimation: When ``True``, register ``POST /lifting/depth-estimation``. + enable_stereo_depth: When ``True``, register ``POST /lifting/stereo-depth``. + + Returns: + A fully configured :class:`FastAPI` instance ready to pass to ``uvicorn.run``. + """ + _app = FastAPI(title="vizion3d REST API", version="1.0.0") + + @_app.middleware("http") + async def limit_body_size(request: Request, call_next): + """Reject requests whose Content-Length header exceeds 500 MB.""" + content_length = request.headers.get("content-length") + if content_length and int(content_length) > _MAX_BODY: + return JSONResponse( + {"detail": "Request body exceeds the 500 MB limit."}, + status_code=413, + ) + return await call_next(request) + + lifting_router = APIRouter(prefix="/lifting", tags=["Lifting (2D -> 3D)"]) + if enable_depth_estimation: + lifting_router.include_router(depth_estimation.router) + if enable_stereo_depth: + lifting_router.include_router(stereo_depth.router) + _app.include_router(lifting_router) + + return _app + + +# Module-level app with all features enabled — used by tests and direct imports. +app = create_app() + + +def _parse_args(argv=None) -> argparse.Namespace: + parser = argparse.ArgumentParser( + prog="vizion3d-serve-rest", + description="Start the vizion3d REST API server.", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +feature/model flags (omit all four to enable all features): + --depth_estimation enable POST /lifting/depth-estimation + --stereo_depth enable POST /lifting/stereo-depth + +model pre-loading (also enables that feature; downloads if a URL is given): + --depth_model PATH use PATH as the default depth-estimation model; + the model is loaded into memory at startup + --stereo_model PATH use PATH as the default stereo-depth model; + the model is loaded into memory at startup +""", + ) + parser.add_argument( + "--host", default="0.0.0.0", metavar="HOST", help="Bind host (default: 0.0.0.0)" + ) + parser.add_argument( + "--port", type=int, default=8000, metavar="PORT", help="Bind port (default: 8000)" ) - cmd = DepthEstimationCommand( - image_input=image_bytes, - model_backend=model_backend, - return_depth_image=return_depth_image, - return_point_cloud=return_point_cloud, - return_mesh=return_mesh, - advanced_config=advanced_config, + parser.add_argument( + "--depth_model", + default=None, + metavar="PATH", + help="Local path or URL for the depth-estimation checkpoint", ) + parser.add_argument( + "--stereo_model", + default=None, + metavar="PATH", + help="Local path or URL for the stereo-depth checkpoint", + ) + parser.add_argument( + "--depth_estimation", action="store_true", help="Enable only the depth-estimation endpoint" + ) + parser.add_argument( + "--stereo_depth", action="store_true", help="Enable only the stereo-depth endpoint" + ) + return parser.parse_args(argv) + + +def run(argv=None) -> None: + """Parse CLI arguments, configure models, and start the uvicorn server.""" + args = _parse_args(argv) - result = DepthEstimation().run(cmd) - - def _b64(data: bytes | None) -> str | None: - return base64.b64encode(data).decode() if data is not None else None - - return { - "depth_map": result.depth_map, - "min_depth": result.min_depth, - "max_depth": result.max_depth, - "backend_used": result.backend_used, - "depth_image": _b64( - _o3d_depth_image_to_png_bytes(result.depth_image) - if result.depth_image is not None - else None - ), - "point_cloud_ply": _b64( - _o3d_point_cloud_to_ply_bytes(result.point_cloud) - if result.point_cloud is not None - else None - ), - "mesh_ply": _b64( - _o3d_mesh_to_ply_bytes(result.mesh) if result.mesh is not None else None - ), - } - - -app.include_router(lifting_router) - - -def run(): - uvicorn.run(app, host="0.0.0.0", port=8000) + any_selector = ( + args.depth_estimation or args.stereo_depth or args.depth_model or args.stereo_model + ) + enable_depth = args.depth_estimation or bool(args.depth_model) or not any_selector + enable_stereo = args.stereo_depth or bool(args.stereo_model) or not any_selector + + if args.depth_model and enable_depth: + depth_estimation.configure_model(args.depth_model) + if args.stereo_model and enable_stereo: + stereo_depth.configure_model(args.stereo_model) + + _app = create_app( + enable_depth_estimation=enable_depth, + enable_stereo_depth=enable_stereo, + ) + uvicorn.run(_app, host=args.host, port=args.port) if __name__ == "__main__": diff --git a/vizion3d/server/rest/depth_estimation.py b/vizion3d/server/rest/depth_estimation.py new file mode 100644 index 0000000..d195e7f --- /dev/null +++ b/vizion3d/server/rest/depth_estimation.py @@ -0,0 +1,108 @@ +""" +REST endpoint for the Depth Estimation feature. + +Registers ``POST /lifting/depth-estimation`` on the ``lifting_router`` exported +from this module. Import the router in ``app.py`` and call +``app.include_router(lifting_router)``. +""" + +from fastapi import APIRouter, File, Form, UploadFile + +from vizion3d.lifting import DepthEstimation, DepthEstimationCommand +from vizion3d.lifting.defaults import DEFAULT_DEPTH_MODEL_URL +from vizion3d.lifting.models import DepthEstimationAdvanceConfig + +from .serialisation import ( + b64, + o3d_depth_image_to_png_bytes, + o3d_mesh_to_ply_bytes, + o3d_point_cloud_to_ply_bytes, +) + +router = APIRouter() + +# Set by configure_model() at server startup when --depth_model is passed on the CLI. +_model_override: str | None = None + + +def configure_model(path: str) -> None: + """Set a server-wide default model path and pre-load it into handler memory. + + Called from ``app.run()`` when ``--depth_model`` is supplied on the command line. + After this call the endpoint uses *path* whenever the caller omits + ``model_backend`` from the form data. + """ + global _model_override + _model_override = path + from vizion3d.lifting.handlers import DepthEstimationHandler + + DepthEstimationHandler.preload(path) + + +@router.post("/depth-estimation") +async def depth_estimation( + image: UploadFile = File(...), + model_backend: str | None = Form(None), + return_depth_image: bool = Form(False), + return_point_cloud: bool = Form(False), + return_mesh: bool = Form(False), + fx: float | None = Form(None), + fy: float | None = Form(None), + cx: float | None = Form(None), + cy: float | None = Form(None), + depth_scale: float | None = Form(None), + depth_trunc: float | None = Form(None), +): + """Run monocular depth estimation on a single uploaded image. + + Args: + image: The image file (any PIL-supported format). + model_backend: Checkpoint URL or local path (defaults to the vizion3D release). + return_depth_image: Include a base64-encoded 16-bit PNG depth image. + return_point_cloud: Include a base64-encoded binary PLY point cloud. + return_mesh: Include a base64-encoded binary PLY surface mesh. + fx, fy, cx, cy: Camera intrinsics (uses PrimeSense defaults if omitted). + depth_scale: Raw uint16 → metres divisor (default 1000). + depth_trunc: Maximum depth in metres (default 10). + + Returns: + JSON with ``depth_map``, ``min_depth``, ``max_depth``, ``backend_used``, + and optional ``depth_image``, ``point_cloud_ply``, ``mesh_ply`` (base64). + """ + image_bytes = await image.read() + effective_backend = model_backend or _model_override or DEFAULT_DEPTH_MODEL_URL + base_cfg = DepthEstimationAdvanceConfig() + advanced_config = DepthEstimationAdvanceConfig( + fx=fx if fx is not None else base_cfg.fx, + fy=fy if fy is not None else base_cfg.fy, + cx=cx if cx is not None else base_cfg.cx, + cy=cy if cy is not None else base_cfg.cy, + depth_scale=depth_scale if depth_scale is not None else base_cfg.depth_scale, + depth_trunc=depth_trunc if depth_trunc is not None else base_cfg.depth_trunc, + ) + cmd = DepthEstimationCommand( + image_input=image_bytes, + model_backend=effective_backend, + return_depth_image=return_depth_image, + return_point_cloud=return_point_cloud, + return_mesh=return_mesh, + advanced_config=advanced_config, + ) + result = DepthEstimation().run(cmd) + return { + "depth_map": result.depth_map, + "min_depth": result.min_depth, + "max_depth": result.max_depth, + "backend_used": result.backend_used, + "depth_image": b64( + o3d_depth_image_to_png_bytes(result.depth_image) + if result.depth_image is not None + else None + ), + "point_cloud_ply": b64( + o3d_point_cloud_to_ply_bytes(result.point_cloud) + if result.point_cloud is not None + else None + ), + "mesh_ply": b64(o3d_mesh_to_ply_bytes(result.mesh) if result.mesh is not None else None), + } diff --git a/vizion3d/server/rest/serialisation.py b/vizion3d/server/rest/serialisation.py new file mode 100644 index 0000000..ff375ec --- /dev/null +++ b/vizion3d/server/rest/serialisation.py @@ -0,0 +1,42 @@ +""" +Shared serialisation helpers for the vizion3d REST server. + +Converts Open3D geometry objects to wire-format bytes (PNG or binary PLY) +and base64-encodes arbitrary byte payloads for JSON transport. +""" + +import base64 +import io + +import numpy as np +from PIL import Image + +from vizion3d.lifting.utils import create_mesh_ply_binary, create_ply_binary + + +def o3d_depth_image_to_png_bytes(o3d_image) -> bytes: + """Encode an Open3D uint16 depth image as a PNG byte string.""" + arr = np.asarray(o3d_image) + buf = io.BytesIO() + Image.fromarray(arr).save(buf, format="PNG") + return buf.getvalue() + + +def o3d_point_cloud_to_ply_bytes(pcd) -> bytes: + """Serialise an Open3D PointCloud to binary PLY bytes.""" + points = np.asarray(pcd.points).astype(np.float32) + colors = (np.asarray(pcd.colors) * 255).astype(np.uint8) + return create_ply_binary(points, colors) + + +def o3d_mesh_to_ply_bytes(mesh) -> bytes: + """Serialise an Open3D TriangleMesh to binary PLY bytes.""" + points = np.asarray(mesh.vertices).astype(np.float32) + colors = (np.asarray(mesh.vertex_colors) * 255).astype(np.uint8) + faces = np.asarray(mesh.triangles).astype(np.int32) + return create_mesh_ply_binary(points, colors, faces) + + +def b64(data: bytes | None) -> str | None: + """Base64-encode *data*, or return ``None`` if *data* is ``None``.""" + return base64.b64encode(data).decode() if data is not None else None diff --git a/vizion3d/server/rest/stereo_depth.py b/vizion3d/server/rest/stereo_depth.py new file mode 100644 index 0000000..6794556 --- /dev/null +++ b/vizion3d/server/rest/stereo_depth.py @@ -0,0 +1,126 @@ +""" +REST endpoint for the Stereo Depth feature. + +Registers ``POST /lifting/stereo-depth`` on the ``router`` exported from this +module. Import the router in ``app.py`` and call +``app.include_router(router)``. +""" + +from fastapi import APIRouter, File, Form, UploadFile + +from vizion3d.stereo import StereoDepth, StereoDepthCommand +from vizion3d.stereo.defaults import DEFAULT_STEREO_MODEL_URL +from vizion3d.stereo.models import StereoDepthAdvancedConfig + +from .serialisation import ( + b64, + o3d_depth_image_to_png_bytes, + o3d_mesh_to_ply_bytes, + o3d_point_cloud_to_ply_bytes, +) + +router = APIRouter() + +# Set by configure_model() at server startup when --stereo_model is passed on the CLI. +_model_override: str | None = None + + +def configure_model(path: str) -> None: + """Set a server-wide default stereo model path and pre-load it into handler memory. + + Called from ``app.run()`` when ``--stereo_model`` is supplied on the command line. + After this call the endpoint uses *path* whenever the caller omits + ``model_backend`` from the form data. + """ + global _model_override + _model_override = path + from vizion3d.stereo.handlers import StereoDepthHandler + + StereoDepthHandler.preload(path) + + +@router.post("/stereo-depth") +async def stereo_depth( + left_image: UploadFile = File(...), + right_image: UploadFile = File(...), + model_backend: str | None = Form(None), + return_depth_image: bool = Form(False), + return_point_cloud: bool = Form(False), + return_mesh: bool = Form(False), + focal_length: float | None = Form(None), + cx: float | None = Form(None), + cy: float | None = Form(None), + baseline: float | None = Form(None), + doffs: float | None = Form(None), + z_far: float | None = Form(None), + conf_threshold: float | None = Form(None), + occ_threshold: float | None = Form(None), + scale_factor: float | None = Form(None), +): + """Run stereo depth estimation on a rectified left/right image pair. + + Args: + left_image: Left-camera image file (any PIL-supported format). + right_image: Right-camera image file (same resolution, horizontally offset). + model_backend: S2M2 checkpoint URL or local path (defaults to the vizion3D release). + return_depth_image: Include a base64-encoded 16-bit PNG depth image. + return_point_cloud: Include a base64-encoded binary PLY point cloud. + return_mesh: Include a base64-encoded binary PLY surface mesh. + focal_length: Focal length in pixels (default 1000.0 — override with your calibration). + cx, cy: Principal point in pixels. + baseline: Stereo baseline in millimetres (default 100.0). + doffs: Disparity offset (default 0.0). + z_far: Max depth in metres for point cloud (default 10.0). + conf_threshold: Minimum confidence for point inclusion (default 0.1). + occ_threshold: Minimum occlusion score for point inclusion (default 0.5). + scale_factor: Input downscale factor for speed/quality tradeoff (default 1.0). + + Returns: + JSON with ``depth_map``, ``disparity_map``, ``min_depth``, ``max_depth``, + ``backend_used``, and optional ``depth_image``, ``point_cloud_ply``, + ``mesh_ply`` (base64). + """ + left_bytes = await left_image.read() + right_bytes = await right_image.read() + effective_backend = model_backend or _model_override or DEFAULT_STEREO_MODEL_URL + + base_cfg = StereoDepthAdvancedConfig() + advanced_config = StereoDepthAdvancedConfig( + focal_length=focal_length if focal_length is not None else base_cfg.focal_length, + cx=cx if cx is not None else base_cfg.cx, + cy=cy if cy is not None else base_cfg.cy, + baseline=baseline if baseline is not None else base_cfg.baseline, + doffs=doffs if doffs is not None else base_cfg.doffs, + z_far=z_far if z_far is not None else base_cfg.z_far, + conf_threshold=conf_threshold if conf_threshold is not None else base_cfg.conf_threshold, + occ_threshold=occ_threshold if occ_threshold is not None else base_cfg.occ_threshold, + scale_factor=scale_factor if scale_factor is not None else base_cfg.scale_factor, + ) + cmd = StereoDepthCommand( + left_image=left_bytes, + right_image=right_bytes, + model_backend=effective_backend, + return_depth_image=return_depth_image, + return_point_cloud=return_point_cloud, + return_mesh=return_mesh, + advanced_config=advanced_config, + ) + result = StereoDepth().run(cmd) + return { + "depth_map": result.depth_map, + "disparity_map": result.disparity_map, + "min_depth": result.min_depth, + "max_depth": result.max_depth, + "backend_used": result.backend_used, + "depth_image": b64( + o3d_depth_image_to_png_bytes(result.depth_image) + if result.depth_image is not None + else None + ), + "point_cloud_ply": b64( + o3d_point_cloud_to_ply_bytes(result.point_cloud) + if result.point_cloud is not None + else None + ), + "mesh_ply": b64(o3d_mesh_to_ply_bytes(result.mesh) if result.mesh is not None else None), + } diff --git a/vizion3d/stereo/__init__.py b/vizion3d/stereo/__init__.py new file mode 100644 index 0000000..e32a043 --- /dev/null +++ b/vizion3d/stereo/__init__.py @@ -0,0 +1,74 @@ +""" +Stereo Depth task — direct Python entry point. + +Import :class:`StereoDepth` and run it with a :class:`StereoDepthCommand` to +obtain metric depth maps, disparity maps, point clouds, and meshes from +rectified left/right stereo image pairs. + +Example:: + + from vizion3d.stereo import ( + StereoDepth, + StereoDepthAdvancedConfig, + StereoDepthCommand, + ) + + cmd = StereoDepthCommand( + left_image="left.png", + right_image="right.png", + return_point_cloud=True, + return_mesh=True, + advanced_config=StereoDepthAdvancedConfig( + focal_length=1733.74, + cx=792.27, + cy=541.89, + baseline=536.62, + ), + ) + result = StereoDepth().run(cmd) + print(f"Depth range: {result.min_depth:.2f} – {result.max_depth:.2f} m") +""" + +from vizion3d.core.container import command_bus, register_command_handler + +from .commands import StereoDepthCommand +from .handlers import StereoDepthHandler +from .models import StereoDepthAdvancedConfig, StereoDepthResult + +register_command_handler(StereoDepthCommand, StereoDepthHandler) + + +class StereoDepth: + """Facade for the Stereo Depth task. + + Serves as the primary entry point for stereo depth inference via direct + Python import. Internally dispatches through the CQRS command bus to + :class:`~vizion3d.stereo.handlers.StereoDepthHandler`. + + Example:: + + from vizion3d.stereo import StereoDepth, StereoDepthCommand + + cmd = StereoDepthCommand(left_image=b"...", right_image=b"...") + result = StereoDepth().run(cmd) + """ + + def run(self, command: StereoDepthCommand) -> StereoDepthResult: + """Dispatch *command* through the CQRS bus to the registered handler. + + Args: + command: The stereo inference parameters and flags. + + Returns: + :class:`StereoDepthResult` with metric depth, disparity, and optional + depth image, point cloud, and mesh. + """ + return command_bus.dispatch(command) + + +__all__ = [ + "StereoDepth", + "StereoDepthAdvancedConfig", + "StereoDepthCommand", + "StereoDepthResult", +] diff --git a/vizion3d/stereo/arch/__init__.py b/vizion3d/stereo/arch/__init__.py new file mode 100644 index 0000000..ee88309 --- /dev/null +++ b/vizion3d/stereo/arch/__init__.py @@ -0,0 +1,5 @@ +"""S2M2 stereo model architecture package.""" + +from .s2m2 import S2M2, build_s2m2, s2m2_config_from_checkpoint + +__all__ = ["S2M2", "build_s2m2", "s2m2_config_from_checkpoint"] diff --git a/vizion3d/stereo/arch/attention.py b/vizion3d/stereo/arch/attention.py new file mode 100644 index 0000000..dfd88cb --- /dev/null +++ b/vizion3d/stereo/arch/attention.py @@ -0,0 +1,289 @@ +""" +Multi-head attention modules for the S2M2 stereo matching transformer. + +Provides self-attention and bidirectional cross-attention in both 1D (row-wise) +and 2D (global/flattened) variants, plus feed-forward network layers and the +combined ``GlobalAttnBlock`` / ``BasicAttnBlock`` building blocks used by the +feature pyramid and transformer stages. +""" + +import torch +import torch.nn as nn +import torch.nn.functional as F +from torch import Tensor + + +class SelfAttn(nn.Module): + """Multi-head self-attention with optional sinc-based relative positional encoding. + + Args: + dim: Input and output channel count. + num_heads: Number of attention heads. + dim_expansion: Channel expansion factor inside Q/K/V projections. + use_pe: If ``True``, adds a learned projection of the 2D relative PE to + each head's output. + """ + + def __init__(self, dim: int, num_heads: int, dim_expansion: int, use_pe: bool): + super().__init__() + self.num_heads = num_heads + self.head_dim = dim_expansion * dim // num_heads + self.scale = self.head_dim**-0.5 + self.use_pe = use_pe + self.q = nn.Linear(dim, dim_expansion * dim, bias=False) + self.k = nn.Linear(dim, dim_expansion * dim, bias=False) + self.v = nn.Linear(dim, dim_expansion * dim, bias=True) + self.proj = nn.Linear(dim_expansion * dim, dim, bias=False) + if use_pe: + self.pe_proj = nn.Linear(32, self.head_dim) + + def forward(self, x: Tensor, pe: Tensor = None) -> Tensor: + """ + Args: + x: Token sequence ``(B, N, C)``. + pe: Relative positional encoding ``(N, N, 32)`` (only used when + ``use_pe=True``). + + Returns: + Attended output ``(B, N, C)``. + """ + B, N, C = x.shape + q = self.q(x).reshape(B, N, self.num_heads, self.head_dim).transpose(1, 2) + k = self.k(x).reshape(B, N, self.num_heads, self.head_dim).transpose(1, 2) + v = self.v(x).reshape(B, N, self.num_heads, self.head_dim).transpose(1, 2) + if self.use_pe: + score = torch.einsum("...ic,...jc->...ij", self.scale * q, k) + attn = score.softmax(dim=-1) + out = torch.einsum("...ij,...jc->...ic", attn, v) + pe_sum = torch.einsum("...nij,ijc->...nic", attn, pe) + out = out + self.pe_proj(pe_sum) + else: + out = F.scaled_dot_product_attention(q, k, v) + return self.proj(out.transpose(1, 2).reshape(B, N, self.num_heads * self.head_dim)) + + +class CrossAttn(nn.Module): + """Bidirectional cross-attention that updates both left and right feature sequences. + + Each direction attends the other's keys/values, allowing both images to + exchange information in a single block. + + Args: + dim: Input and output channel count. + num_heads: Number of attention heads. + dim_expansion: Channel expansion factor inside Q/K/V projections. + """ + + def __init__(self, dim: int, num_heads: int, dim_expansion: int): + super().__init__() + self.num_heads = num_heads + self.head_dim = dim_expansion * dim // num_heads + self.q = nn.Linear(dim, dim_expansion * dim, bias=False) + self.k = nn.Linear(dim, dim_expansion * dim, bias=False) + self.v = nn.Linear(dim, dim_expansion * dim, bias=True) + self.proj = nn.Linear(dim_expansion * dim, dim, bias=False) + + def forward(self, x: Tensor, y: Tensor): + """ + Args: + x: Left feature sequence ``(B, N, C)``. + y: Right feature sequence ``(B, N, C)``. + + Returns: + ``(x_out, y_out)`` — updated left and right sequences ``(B, N, C)``. + """ + B, N, _ = x.shape + qx = self.q(x).reshape(B, N, self.num_heads, self.head_dim).transpose(1, 2) + ky = self.k(y).reshape(B, N, self.num_heads, self.head_dim).transpose(1, 2) + vy = self.v(y).reshape(B, N, self.num_heads, self.head_dim).transpose(1, 2) + x_out = F.scaled_dot_product_attention(qx, ky, vy) + kx = self.k(x).reshape(B, N, self.num_heads, self.head_dim).transpose(1, 2) + qy = self.q(y).reshape(B, N, self.num_heads, self.head_dim).transpose(1, 2) + vx = self.v(x).reshape(B, N, self.num_heads, self.head_dim).transpose(1, 2) + y_out = F.scaled_dot_product_attention(qy, kx, vx) + x_out = self.proj(x_out.transpose(1, 2).reshape(B, N, self.num_heads * self.head_dim)) + y_out = self.proj(y_out.transpose(1, 2).reshape(B, N, self.num_heads * self.head_dim)) + return x_out, y_out + + +class FFN(nn.Module): + """Position-wise two-layer feed-forward network with pre-LayerNorm and residual. + + Args: + dim: Input and output channel count. + dim_expansion: Hidden layer size multiplier. + """ + + def __init__(self, dim: int, dim_expansion: int): + super().__init__() + self.ffn = nn.Sequential( + nn.Linear(dim, dim_expansion * dim), + nn.GELU(), + nn.Linear(dim_expansion * dim, dim), + ) + self.norm_pre = nn.LayerNorm(dim, elementwise_affine=False) + + def forward(self, z: Tensor) -> Tensor: + return self.ffn(self.norm_pre(z)) + z + + +class SelfAttnBlock1D(nn.Module): + """Row-wise self-attention: treats each image row as an independent sequence. + + Reshapes ``(B, H, W, C)`` → ``(B·H, W, C)`` so attention operates along W. + + Args: + dim: Channel count. + num_heads: Attention heads. + dim_expansion: Q/K/V expansion factor. + use_pe: Whether to apply relative PE. + """ + + def __init__(self, dim: int, num_heads: int, dim_expansion: int, use_pe: bool): + super().__init__() + self.attn = SelfAttn(dim, num_heads, dim_expansion, use_pe) + self.norm_pre = nn.LayerNorm(dim, elementwise_affine=False) + + def forward(self, z: Tensor, pe: Tensor = None) -> Tensor: + B, H, W, C = z.shape + z = z.reshape(B * H, W, C) + z = self.attn(self.norm_pre(z), pe) + z + return z.reshape(B, H, W, C) + + +class CrossAttnBlock1D(nn.Module): + """Row-wise bidirectional cross-attention for paired left/right feature maps. + + Expects *z* to hold ``[left, right]`` concatenated along the batch dimension, + i.e. ``z.shape[0]`` is ``2·B``. + + Args: + dim: Channel count. + num_heads: Attention heads. + dim_expansion: Q/K/V expansion factor. + """ + + def __init__(self, dim: int, num_heads: int, dim_expansion: int): + super().__init__() + self.attn = CrossAttn(dim, num_heads, dim_expansion) + self.norm_pre = nn.LayerNorm(dim, elementwise_affine=False) + + def forward(self, z: Tensor) -> Tensor: + x, y = self.norm_pre(z).chunk(2, dim=0) + B, H, W, C = x.shape + x, y = x.reshape(B * H, W, C), y.reshape(B * H, W, C) + x, y = self.attn(x, y) + x, y = x.reshape(B, H, W, C), y.reshape(B, H, W, C) + return torch.cat([x, y], dim=0) + z + + +class SelfAttnBlock2D(nn.Module): + """Global self-attention: flattens H×W into one long sequence per image. + + Args: + dim: Channel count. + num_heads: Attention heads. + dim_expansion: Q/K/V expansion factor. + use_pe: Whether to apply relative PE. + """ + + def __init__(self, dim: int, num_heads: int, dim_expansion: int, use_pe: bool): + super().__init__() + self.attn = SelfAttn(dim, num_heads, dim_expansion, use_pe) + self.norm_pre = nn.LayerNorm(dim, elementwise_affine=False) + + def forward(self, z: Tensor, pe: Tensor = None) -> Tensor: + B, H, W, C = z.shape + z = z.reshape(B, H * W, C) + z = self.attn(self.norm_pre(z), pe) + z + return z.reshape(B, H, W, C).contiguous() + + +class CrossAttnBlock2D(nn.Module): + """Global bidirectional cross-attention for paired left/right feature maps. + + Expects *z* to hold ``[left, right]`` concatenated along batch. + + Args: + dim: Channel count. + num_heads: Attention heads. + dim_expansion: Q/K/V expansion factor. + """ + + def __init__(self, dim: int, num_heads: int, dim_expansion: int): + super().__init__() + self.attn = CrossAttn(dim, num_heads, dim_expansion) + self.norm_pre = nn.LayerNorm(dim, elementwise_affine=False) + + def forward(self, z: Tensor) -> Tensor: + x, y = self.norm_pre(z).chunk(2, dim=0) + B, H, W, C = x.shape + x, y = x.reshape(B, H * W, C), y.reshape(B, H * W, C) + x, y = self.attn(x, y) + x, y = x.reshape(B, H, W, C), y.reshape(B, H, W, C) + return torch.cat([x, y], dim=0) + z + + +class GlobalAttnBlock(nn.Module): + """Global self-attention (+ optional cross-attention) block used in U-Net stages. + + Operates on ``(B, C, H, W)`` conv-format tensors by permuting to + ``(B, H, W, C)`` internally. + + Args: + dim: Channel count. + num_heads: Attention heads. + dim_expansion: Expansion factor. + use_cross_attn: If ``True``, applies 2D cross-attention before self-attention. + use_pe: Whether to apply relative PE in self-attention. + """ + + def __init__( + self, + dim: int, + num_heads: int, + dim_expansion: int, + use_cross_attn: bool = False, + use_pe: bool = False, + ): + super().__init__() + self.self_attn = SelfAttnBlock2D(dim, num_heads, dim_expansion, use_pe) + if use_cross_attn: + self.cross_attn = CrossAttnBlock2D(dim, num_heads, dim_expansion) + self.ffn_c = FFN(dim, dim_expansion) + else: + self.cross_attn = None + self.ffn = FFN(dim, dim_expansion) + + def forward(self, z: Tensor, pe: Tensor = None) -> Tensor: + z = z.permute(0, 2, 3, 1) + if self.cross_attn is not None: + z = self.ffn_c(self.cross_attn(z)) + z = self.ffn(self.self_attn(z, pe)) + return z.permute(0, 3, 1, 2).contiguous() + + +class BasicAttnBlock(nn.Module): + """Row-wise cross-attention then row-wise self-attention, with FFN after each. + + The standard building block for the MRT transformer stages. + + Args: + dim: Channel count. + num_heads: Attention heads. + dim_expansion: Expansion factor. + use_pe: Whether to apply relative PE in self-attention. + """ + + def __init__(self, dim: int, num_heads: int, dim_expansion: int, use_pe: bool = False): + super().__init__() + self.cross_attn = CrossAttnBlock1D(dim, num_heads, dim_expansion) + self.self_attn = SelfAttnBlock1D(dim, num_heads, dim_expansion, use_pe) + self.ffn_c = FFN(dim, dim_expansion) + self.ffn = FFN(dim, dim_expansion) + + def forward(self, z: Tensor, pe: Tensor = None) -> Tensor: + z = z.permute(0, 2, 3, 1) + z = self.ffn_c(self.cross_attn(z)) + z = self.ffn(self.self_attn(z, pe)) + return z.permute(0, 3, 1, 2) diff --git a/vizion3d/stereo/arch/components.py b/vizion3d/stereo/arch/components.py new file mode 100644 index 0000000..427db77 --- /dev/null +++ b/vizion3d/stereo/arch/components.py @@ -0,0 +1,341 @@ +""" +Feature extraction, U-Net pyramid, cost volume, and disparity initialisation for S2M2. + +Contains: +- :class:`FeatureFusion` — gated blending of two same-dimension feature maps. +- :class:`ConvBlock2D` — residual conv block used throughout the U-Net. +- :class:`CNNEncoder` — 4× downsampling CNN backbone. +- :class:`Unet` — multi-scale feature pyramid with bottleneck attention. +- :class:`CostVolume` — efficient stereo cost-volume sampler. +- :class:`DispInit` — optimal-transport disparity initialisation from correlations. +""" + +import torch +import torch.nn as nn +import torch.nn.functional as F +from torch import Tensor + +from .attention import GlobalAttnBlock +from .utils import bilinear_sampler, get_pe, logsumexp_stable + + +class FeatureFusion(nn.Module): + """Gated fusion of two same-resolution feature maps. + + Learns a soft gate *w ∈ (0, 1)* per spatial position so the output is + ``fusion(z0, z1) + w·z0 + (1−w)·z1`` when ``use_gate=True``, or just + ``fusion(z0, z1)`` otherwise. + + Args: + dim: Input and output channel count for both *z0* and *z1*. + kernel_size: Convolution kernel size for the gate and fusion networks. + use_gate: Whether to include the learnable gate (default ``True``). + """ + + def __init__(self, dim: int, kernel_size: int, use_gate: bool = True): + super().__init__() + pad = kernel_size // 2 + self.use_gate = use_gate + if use_gate: + self.feature_gate = nn.Sequential( + nn.Conv2d(2 * dim, dim, kernel_size=kernel_size, padding=pad), + nn.GELU(), + nn.Conv2d(dim, dim, kernel_size=1), + nn.Sigmoid(), + ) + self.feature_fusion = nn.Sequential( + nn.Conv2d(2 * dim, 2 * dim, kernel_size=kernel_size, padding=pad), + nn.GELU(), + nn.Conv2d(2 * dim, dim, kernel_size=1), + ) + + def forward(self, z0: Tensor, z1: Tensor) -> Tensor: + z = torch.cat([z0, z1], dim=1) + if self.use_gate: + eps = 0.01 + w = self.feature_gate(z).clamp(min=eps, max=1 - eps) + return self.feature_fusion(z) + w * z0 + (1 - w) * z1 + return self.feature_fusion(z) + + +class ConvBlock2D(nn.Module): + """Residual 2D conv block: kxk conv path fused with a parallel 1×1 skip path. + + Args: + dim: Channel count (input = output). + kernel_size: Kernel size for the main conv path. + dim_expansion: Hidden-width multiplier for both paths. + """ + + def __init__(self, dim: int, kernel_size: int, dim_expansion: int): + super().__init__() + p = kernel_size // 2 + self.convs = nn.Sequential( + nn.Conv2d(dim, dim_expansion * dim, kernel_size, padding=p), + nn.GELU(), + nn.Conv2d(dim_expansion * dim, dim, kernel_size, padding=p), + ) + self.convs_1x = nn.Sequential( + nn.Conv2d(dim, dim_expansion * dim, 1), + nn.ReLU(), + nn.Conv2d(dim_expansion * dim, dim, 1), + ) + + def forward(self, z: Tensor) -> Tensor: + return self.convs(z) + self.convs_1x(z) + + +class CNNEncoder(nn.Module): + """4× downsampling CNN backbone producing features at 2× and 4× strides. + + Processes concatenated left+right images (along the batch dim) so both + images share weights. The two outputs are split externally. + + Args: + output_dim: Output channel count at both stride levels. + """ + + def __init__(self, output_dim: int): + super().__init__() + self.conv0 = nn.Sequential(nn.Conv2d(3, 16, 1), nn.GELU(), nn.Conv2d(16, 16, 1)) + self.conv1_down = nn.Sequential( + nn.Conv2d(16, 64, 5, stride=2, padding=2), + nn.GELU(), + nn.Conv2d(64, output_dim, 3, padding=1), + ) + self.norm1 = nn.GroupNorm(8, output_dim) + self.conv2 = nn.Sequential( + nn.Conv2d(output_dim, output_dim, 3, padding=1), + nn.GELU(), + nn.Conv2d(output_dim, output_dim, 3, padding=1), + ) + self.conv2_down = nn.Sequential(nn.Conv2d(output_dim, output_dim, 3, stride=2, padding=1)) + + def forward(self, x: Tensor): + """ + Args: + x: ``(2B, 3, H, W)`` — left and right images stacked along batch. + + Returns: + ``(feature_4x, feature_2x)`` — downsampled 4× and 2× feature maps, + both ``(2B, output_dim, H/4, W/4)`` and ``(2B, output_dim, H/2, W/2)``. + """ + x = self.conv0(x) + x_2x = self.norm1(self.conv1_down(x)) + x_2x = self.conv2(x_2x) + x_2x + return self.conv2_down(x_2x), x_2x + + +class Unet(nn.Module): + """Multi-scale U-Net feature pyramid with global attention at the bottleneck. + + Encoder downsamples three times via average pooling; decoder upsamples back + with gated skip connections. Global attention blocks sit at the lowest + resolution for long-range context. + + Args: + dims: Channel counts at the three pyramid levels ``[d0, d1, d2]``. + dim_expansion: Conv/attention expansion factor. + use_pe: Whether to use relative PE in bottleneck attention. + n_attn: Number of global-attention blocks at the bottleneck. + use_gate_fusion: Whether to use gated skip connections. + """ + + def __init__( + self, + dims: list, + dim_expansion: int, + use_pe: bool, + n_attn: int = 1, + use_gate_fusion: bool = True, + ): + super().__init__() + self.use_pe = use_pe + self.down_conv0 = nn.Sequential(nn.AvgPool2d(2), nn.Conv2d(dims[0], dims[1], 1)) + self.down_conv1 = nn.Sequential(nn.AvgPool2d(2), nn.Conv2d(dims[1], dims[2], 1)) + self.down_conv2 = nn.Sequential(nn.AvgPool2d(2), nn.Conv2d(dims[2], dims[2], 1)) + self.up_conv0 = nn.Sequential( + nn.Upsample(scale_factor=2, mode="bilinear", align_corners=False), + nn.Conv2d(dims[1], dims[0], 1), + ) + self.up_conv1 = nn.Sequential( + nn.Upsample(scale_factor=2, mode="bilinear", align_corners=False), + nn.Conv2d(dims[2], dims[1], 1), + ) + self.up_conv2 = nn.Sequential( + nn.Upsample(scale_factor=2, mode="bilinear", align_corners=False), + nn.Conv2d(dims[2], dims[2], 1), + ) + self.concat_conv0 = FeatureFusion(dims[0], 1, use_gate_fusion) + self.concat_conv1 = FeatureFusion(dims[1], 1, use_gate_fusion) + self.concat_conv2 = FeatureFusion(dims[2], 1, use_gate_fusion) + self.enc0 = ConvBlock2D(dims[0], 3, dim_expansion) + self.enc1 = ConvBlock2D(dims[1], 3, dim_expansion) + self.enc2 = ConvBlock2D(dims[2], 3, dim_expansion) + self.enc3s = nn.ModuleList( + [GlobalAttnBlock(dims[2], 8, dim_expansion, False, use_pe) for _ in range(n_attn)] + ) + self.dec0 = ConvBlock2D(dims[0], 3, dim_expansion) + self.dec1 = ConvBlock2D(dims[1], 3, dim_expansion) + self.dec2 = ConvBlock2D(dims[2], 3, dim_expansion) + self.dec3s = nn.ModuleList( + [GlobalAttnBlock(dims[2], 8, dim_expansion, False, False) for _ in range(n_attn)] + ) + + def forward(self, z: Tensor): + """ + Args: + z: Input feature map ``(B, dims[0], H, W)``. + + Returns: + ``(z0, z1, z2, z3)`` — multi-scale outputs at strides 1×, 2×, 4×, 8× + relative to the input spatial size. + """ + pe = None + if self.use_pe: + H, W = z.shape[-2:] + pe = get_pe(H // 8, W // 8, 32, z.dtype, z.device) + z0 = self.enc0(z) + z1 = self.enc1(self.down_conv0(z0)) + z2 = self.enc2(self.down_conv1(z1)) + z3 = self.down_conv2(z2) + for blk in self.enc3s: + z3 = blk(z3, pe) + for blk in self.dec3s: + z3 = blk(z3, pe) + z2_new = self.dec2(self.concat_conv2(z2, self.up_conv2(z3))) + z1_new = self.dec1(self.concat_conv1(z1, self.up_conv1(z2_new))) + z0_new = self.dec0(self.concat_conv0(z0, self.up_conv0(z1_new))) + return z0_new, z1_new, z2_new, z3 + + +class CostVolume: + """Efficient stereo cost-volume sampler for local refinement. + + Pre-computes the dense correlation matrix and supports fast local lookups + around a running disparity estimate during GRU-based refinement. + + Args: + cv: Dense correlation volume ``(B, H, W, W)`` — left × right feature dot-products. + coords: Left-image x-coordinates ``(B, H, W, 1)`` used to anchor lookups. + radius: Disparity search radius; lookups cover ``[disp−radius, disp+radius]``. + """ + + def __init__(self, cv: Tensor, coords: Tensor, radius: int): + self.radius = radius + dx = torch.linspace(-radius, radius, 2 * radius + 1, device=cv.device, dtype=cv.dtype) + self.dx = dx.reshape(1, 1, 2 * radius + 1, 1) + b, h, w, w2 = cv.shape + self.cv = cv.reshape(b * h * w, 1, 1, w2) + self.cv_2x = F.avg_pool2d(self.cv, kernel_size=[1, 2]) + self.cv = self.cv.reshape(b * h, 1, w, w2) + self.cv_2x = self.cv_2x.reshape(b * h, 1, w, w2 // 2) + self.coords = coords.reshape(b * h * w, 1, 1, 1) + + def __call__(self, disp: Tensor): + """Sample full-res and half-res cost values around the current disparity. + + Args: + disp: Current disparity estimate ``(B, 1, H, W)``. + + Returns: + ``(corrs, corrs_2x)`` — sampled cost volumes at full and half resolution, + each ``(B, 2·radius+1, H, W)``. + """ + b, _, h, w = disp.shape + dx = self.dx + x0 = (self.coords - disp.reshape(b * h * w, 1, 1, 1) + dx).reshape(b * h, w, -1, 1) + y0 = (self.coords + 0 * dx).reshape(b * h, w, -1, 1) + corrs = bilinear_sampler(self.cv, torch.cat([x0, y0], dim=-1)) + corrs = corrs.reshape(b, h, w, 2 * self.radius + 1).permute(0, 3, 1, 2) + x0_2 = (self.coords / 2 - disp.reshape(b * h * w, 1, 1, 1) / 2 + dx).reshape( + b * h, w, -1, 1 + ) + corrs_2x = bilinear_sampler(self.cv_2x, torch.cat([x0_2, y0], dim=-1)) + corrs_2x = corrs_2x.reshape(b, h, w, 2 * self.radius + 1).permute(0, 3, 1, 2) + return corrs, corrs_2x + + +class DispInit(nn.Module): + """Optimal-transport disparity initialisation from dense feature correlations. + + Computes the dense left-right correlation volume, applies a Sinkhorn OT solver + to produce a soft correspondence distribution, and extracts the expected disparity + via a soft-argmax over a local window around the peak. + + Args: + dim: Feature channel count. + ot_iter: Number of Sinkhorn iterations. + use_positivity: Mask the upper triangle so only positive (left→right) disparities + are considered — appropriate for well-rectified stereo pairs. + """ + + def __init__(self, dim: int, ot_iter: int, use_positivity: bool): + super().__init__() + self.layer_norm = nn.LayerNorm(dim, elementwise_affine=True) + self.ot_iter = ot_iter + self.use_positivity = use_positivity + + def _sinkhorn(self, attn: Tensor, log_mu: Tensor, log_nu: Tensor) -> Tensor: + """Run *ot_iter* steps of the Sinkhorn algorithm in log-space.""" + v = log_nu - logsumexp_stable(attn, dim=2) + u = log_mu - logsumexp_stable(attn + v.unsqueeze(2), dim=3) + for _ in range(self.ot_iter - 1): + v = log_nu - logsumexp_stable(attn + u.unsqueeze(3), dim=2) + u = log_mu - logsumexp_stable(attn + v.unsqueeze(2), dim=3) + return attn + u.unsqueeze(3) + v.unsqueeze(2) + + def _optimal_transport(self, attn: Tensor) -> Tensor: + """Convert a raw attention matrix to a normalised transport plan.""" + bs, h, w, _ = attn.shape + dtype = attn.dtype + marginal = torch.cat( + [torch.ones([w], device=attn.device), torch.tensor([w], device=attn.device)] + ) / (2 * w) + log_mu = marginal.log().reshape(1, 1, w + 1) + log_nu = marginal.log().reshape(1, 1, w + 1) + attn = F.pad(attn, (0, 1, 0, 1), "constant", 0) + attn = self._sinkhorn(attn, log_mu, log_nu) + log_const = torch.log(torch.tensor(w, dtype=dtype, device=attn.device) * 2) + return (attn[:, :, :-1, :-1] + log_const).exp().to(dtype) + + def forward(self, feature: Tensor): + """ + Args: + feature: Joint left+right feature tensor ``(2B, C, H, W)``. + + Returns: + ``(disparity, confidence, occlusion, cost_volume)`` — all at the same + spatial resolution as *feature*. + """ + dtype = feature.dtype + device = feature.device + w = feature.shape[-1] + x_grid = torch.linspace(0, w - 1, w, device=device, dtype=dtype) + mask = ( + torch.triu(torch.ones((w, w), dtype=torch.bool, device=device), diagonal=1) + if self.use_positivity + else torch.zeros((w, w), dtype=torch.bool, device=device) + ) + + feature0, feature1 = self.layer_norm(feature.permute(0, 2, 3, 1)).chunk(2, dim=0) + cv = torch.einsum("...hic,...hjc->...hij", feature0, feature1) + cv_mask = cv.masked_fill(mask, -1e4) + prob = self._optimal_transport(cv_mask) + masked_prob = prob.masked_fill(mask, 0) + + prob_max_ind = masked_prob.argmax(dim=3).unsqueeze(3) + prob_l = 2 + masked_prob_pad = F.pad(masked_prob, (prob_l, prob_l), "constant", 0) + conf = 0 + correspondence_left = 0 + for idx in range(2 * prob_l + 1): + weight = torch.gather(masked_prob_pad, index=prob_max_ind + idx, dim=3) + conf += weight + correspondence_left += weight * (prob_max_ind + idx - prob_l) + eps = 1e-4 + correspondence_left = (correspondence_left + eps) / (conf + eps) + disparity = (x_grid.reshape(1, 1, w) - correspondence_left.squeeze(3)).unsqueeze(1) + conf = conf.unsqueeze(1).squeeze(-1) + occ = masked_prob.sum(dim=3).unsqueeze(1) + return disparity, conf, occ, cv diff --git a/vizion3d/stereo/arch/refiners.py b/vizion3d/stereo/arch/refiners.py new file mode 100644 index 0000000..53fdd76 --- /dev/null +++ b/vizion3d/stereo/arch/refiners.py @@ -0,0 +1,281 @@ +""" +Disparity refinement modules for S2M2. + +Contains: +- :class:`ConvGRU` — separable convolutional GRU for iterative updates. +- :class:`UpsampleMask4x` — learned 4× disparity upsampler. +- :class:`UpsampleMask1x` — learned 1× (or 2×) guided upsampler. +- :class:`GlobalRefiner` — U-Net-based global gap-filling pass. +- :class:`LocalRefiner` — cost-volume-guided local GRU refinement. +""" + +from typing import Callable + +import torch +import torch.nn as nn +from torch import Tensor + +from .components import Unet + + +class ConvGRU(nn.Module): + """Separable convolutional GRU: horizontal then vertical 1D convolutions. + + Runs two sequential GRU steps — one with a vertical kernel then one with a + horizontal kernel — to propagate context efficiently across 2D feature maps. + + Args: + hidden_dim: Recurrent state channel count. + input_dim: Input feature channel count. + kernel_size: Kernel size along the non-unit spatial dimension. + """ + + def __init__(self, hidden_dim: int = 128, input_dim: int = 128, kernel_size: int = 3): + super().__init__() + self.convz1 = nn.Conv2d( + hidden_dim + input_dim, hidden_dim, [kernel_size, 1], padding=[kernel_size // 2, 0] + ) + self.convr1 = nn.Conv2d( + hidden_dim + input_dim, hidden_dim, [kernel_size, 1], padding=[kernel_size // 2, 0] + ) + self.convq1 = nn.Conv2d( + hidden_dim + input_dim, hidden_dim, [kernel_size, 1], padding=[kernel_size // 2, 0] + ) + self.convz2 = nn.Conv2d( + hidden_dim + input_dim, hidden_dim, [1, kernel_size], padding=[0, kernel_size // 2] + ) + self.convr2 = nn.Conv2d( + hidden_dim + input_dim, hidden_dim, [1, kernel_size], padding=[0, kernel_size // 2] + ) + self.convq2 = nn.Conv2d( + hidden_dim + input_dim, hidden_dim, [1, kernel_size], padding=[0, kernel_size // 2] + ) + + def forward(self, h: Tensor, x: Tensor) -> Tensor: + """ + Args: + h: Current hidden state ``(B, hidden_dim, H, W)``. + x: Input features ``(B, input_dim, H, W)``. + + Returns: + Updated hidden state ``(B, hidden_dim, H, W)``, dtype matches *x*. + """ + hx = torch.cat([h, x], dim=1) + z = torch.sigmoid(self.convz1(hx)) + r = torch.sigmoid(self.convr1(hx)) + h = (1 - z) * h + z * torch.tanh(self.convq1(torch.cat([r * h, x], dim=1))) + hx = torch.cat([h, x], dim=1) + z = torch.sigmoid(self.convz2(hx)) + r = torch.sigmoid(self.convr2(hx)) + h = (1 - z) * h + z * torch.tanh(self.convq2(torch.cat([r * h, x], dim=1))) + return h.to(x.dtype) + + +class UpsampleMask4x(nn.Module): + """Learned convex-combination 4× upsampler using multi-scale feature context. + + Produces a ``(B, 9, H·4, W·4)`` weight map (via a transposed-conv step) that is + used to combine 3×3 neighbourhood patches of the 4×-downsampled disparity map. + + Args: + dim: Context feature channel count. + """ + + def __init__(self, dim: int): + super().__init__() + self.conv_x = nn.ConvTranspose2d(dim, 64, 2, stride=2) + self.conv_y = nn.Conv2d(dim, 64, 3, padding=1) + self.conv_concat = nn.Sequential( + nn.Conv2d(128, 128, 3, padding=1), + nn.ReLU(inplace=False), + nn.ConvTranspose2d(128, 9, 2, stride=2), + ) + + def forward(self, feat_x: Tensor, feat_y: Tensor) -> Tensor: + """ + Args: + feat_x: GRU hidden state ``(B, dim, H, W)``. + feat_y: 2× feature map ``(B, dim, H·2, W·2)``. + + Returns: + 9-channel upsample weight map ``(B, 9, H·4, W·4)``. + """ + return self.conv_concat(torch.cat([self.conv_x(feat_x), self.conv_y(feat_y)], dim=1)) + + +class UpsampleMask1x(nn.Module): + """Guided 1× (or 2×) disparity upsampler using disparity, RGB, and context. + + Produces a ``(B, 9, H, W)`` (or ``(B, 9, H·2, W·2)`` when ``output_upsample`` + is enabled in S2M2) weight map for subpixel-accurate disparity refinement. + + Args: + dim: Context feature channel count. + """ + + def __init__(self, dim: int): + super().__init__() + self.conv_disp = nn.Sequential( + nn.ConvTranspose2d(1, 16, 3, padding=1), nn.ReLU(inplace=False) + ) + self.conv_rgb = nn.Sequential( + nn.ConvTranspose2d(3, 16, 3, padding=1), nn.ReLU(inplace=False) + ) + self.conv_ctx = nn.ConvTranspose2d(dim, 16, 2, stride=2) + self.conv_concat = nn.Sequential( + nn.Conv2d(48, 48, 3, padding=1), + nn.ReLU(inplace=False), + nn.ConvTranspose2d(48, 9, 1), + ) + + def forward(self, disp: Tensor, rgb: Tensor, ctx: Tensor) -> Tensor: + """ + Args: + disp: 4×-upsampled disparity ``(B, 1, H, W)``. + rgb: Normalised left image ``(B, 3, H, W)``. + ctx: 2× feature map ``(B, dim, H/2, W/2)``. + + Returns: + 9-channel upsample filter weights ``(B, 9, H, W)``. + """ + return self.conv_concat( + torch.cat([self.conv_disp(disp), self.conv_rgb(rgb), self.conv_ctx(ctx)], dim=1) + ) + + +class GlobalRefiner(nn.Module): + """U-Net-based global gap-filling pass that corrects low-confidence regions. + + Uses the confidence mask to suppress reliable disparities and predict + corrections only where the OT initialisation was uncertain. + + Args: + feature_channels: Context feature channel count. + """ + + def __init__(self, feature_channels: int): + super().__init__() + ch = feature_channels + self.init_feat = nn.Sequential( + nn.Conv2d(2 + ch, ch, 3, padding=1), nn.GELU(), nn.Conv2d(ch, ch, 1) + ) + self.refine_unet = Unet([ch, ch, ch], 1, False, n_attn=1, use_gate_fusion=True) + self.out_feat = nn.Sequential(nn.Conv2d(ch, 1, 3, padding=1)) + + def forward(self, ctx: Tensor, disp: Tensor, conf: Tensor) -> Tensor: + """ + Args: + ctx: Left context features ``(B, C, H, W)``. + disp: Initial disparity estimate ``(B, 1, H, W)``. + conf: Per-pixel confidence ``(B, 1, H, W)`` in ``[0, 1]``. + + Returns: + Refined disparity ``(B, 1, H, W)`` — confident regions are kept, + uncertain regions are replaced by the U-Net prediction. + """ + mask = 1.0 * (conf > 0.2) + conf_logit = (mask * conf).logit(eps=1e-1) + feat = self.init_feat(torch.cat([disp / 1e2 * mask, conf_logit, ctx], dim=1).to(disp.dtype)) + disp_update = self.out_feat(self.refine_unet(feat)[0]) * 1e2 + return (mask * disp + (1 - mask) * disp_update).to(disp.dtype) + + +class LocalRefiner(nn.Module): + """Cost-volume-guided iterative local refinement using a ConvGRU. + + Each call to :meth:`forward` performs one GRU update step, reading cost-volume + correlations around the current disparity estimate and jointly updating the + disparity, confidence, and occlusion maps. + + Args: + feature_channels: Context feature channel count. + dim_expansion: U-Net expansion factor. + radius: Cost-volume lookup radius. + use_gate_fusion: Whether to use gated U-Net skip connections. + """ + + def __init__( + self, + feature_channels: int, + dim_expansion: int, + radius: int, + use_gate_fusion: bool, + ): + super().__init__() + ch = feature_channels + r = radius + self.disp_feat = nn.Sequential( + nn.Conv2d(1, 96, 3, padding=1), nn.GELU(), nn.Conv2d(96, 96, 3, padding=1) + ) + self.corr_feat1 = nn.Sequential( + nn.Conv2d((2 * r + 1), 96, 1), nn.GELU(), nn.Conv2d(96, 64, 1) + ) + self.corr_feat2 = nn.Sequential( + nn.Conv2d((2 * r + 1), 96, 1), nn.GELU(), nn.Conv2d(96, 64, 1) + ) + self.conf_occ_feat = nn.Sequential( + nn.Conv2d(2, 64, 3, padding=1), nn.GELU(), nn.Conv2d(64, 32, 1) + ) + self.disp_corr_ctx_cat = nn.Sequential( + nn.Conv2d(256 + ch, 2 * ch, 1), nn.GELU(), nn.Conv2d(2 * ch, ch, 3, padding=1) + ) + self.refine_unet = Unet( + [ch, ch, 2 * ch], dim_expansion, False, n_attn=1, use_gate_fusion=use_gate_fusion + ) + self.disp_update = nn.Sequential( + nn.Conv2d(ch, ch, 3, padding=1), + nn.GELU(), + nn.Conv2d(ch, 1, 3, padding=1, bias=False), + ) + self.conf_occ_update = nn.Sequential( + nn.Conv2d(ch, ch, 3, padding=1), + nn.GELU(), + nn.Conv2d(ch, 2, 3, padding=1, bias=False), + ) + self.gru = ConvGRU(ch, ch, 3) + + def forward( + self, + hidden: Tensor, + ctx: Tensor, + disp: Tensor, + conf: Tensor, + occ: Tensor, + cv_fn: Callable, + ): + """Perform one refinement step. + + Args: + hidden: GRU hidden state ``(B, C, H, W)``. + ctx: Left context features ``(B, C, H, W)``. + disp: Current disparity ``(B, 1, H, W)``. + conf: Current confidence ``(B, 1, H, W)``. + occ: Current occlusion ``(B, 1, H, W)``. + cv_fn: Callable that accepts *disp* and returns ``(corrs, corrs_2x)``. + + Returns: + ``(hidden_new, disp_new, conf_new, occ_new)`` — all updated tensors. + """ + conf_logit = conf.logit(eps=1e-2) + occ_logit = occ.logit(eps=1e-2) + corr1, corr2 = cv_fn(disp) + cat_in = torch.cat( + [ + self.disp_feat(disp / 1e2), + self.corr_feat1(corr1 / 16), + self.corr_feat2(corr2 / 16), + ctx, + self.conf_occ_feat(torch.cat([conf_logit, occ_logit], dim=1).to(disp.dtype)), + ], + dim=1, + ).to(disp.dtype) + refine_feat = self.refine_unet(self.disp_corr_ctx_cat(cat_in))[0] + hidden_new = self.gru(hidden, refine_feat) + disp_update = self.disp_update(hidden_new) + conf_update, occ_update = self.conf_occ_update(hidden_new).chunk(2, dim=1) + return ( + hidden_new.to(disp.dtype), + (disp + disp_update).to(disp.dtype), + torch.sigmoid(conf_update + conf_logit).to(disp.dtype), + torch.sigmoid(occ_update + occ_logit).to(disp.dtype), + ) diff --git a/vizion3d/stereo/arch/s2m2.py b/vizion3d/stereo/arch/s2m2.py new file mode 100644 index 0000000..6af860e --- /dev/null +++ b/vizion3d/stereo/arch/s2m2.py @@ -0,0 +1,350 @@ +""" +S2M2 stereo matching transformer — model definition and checkpoint helpers. + +Model architecture constants are hardcoded here and must not be exposed as user +configuration. The only external knob is the checkpoint variant (S / M / L / XL), +which is detected automatically from the checkpoint filename. + +Architecture constants (fixed for all inference): + _DIM_EXPANSION = 1 — Q/K/V width multiplier (not a tunable hyperparameter). + _OT_ITER = 3 — Sinkhorn iterations for disparity initialisation. + _USE_POSITIVITY = True — clamp disparity ≥ 0 (correct for rectified pairs). + _OUTPUT_UPSAMPLE = False — training-only 2× flag; never needed at inference. + _REFINE_ITER = 3 — local GRU refinement steps per inference call. + +Variant configs (feature_channels, num_transformer): + S → (128, 1) + M → (192, 2) + L → (256, 3) ← default / recommended + XL → (384, 3) +""" + +from __future__ import annotations + +from pathlib import Path + +import torch +import torch.nn as nn +import torch.nn.functional as F +from torch import Tensor + +from .attention import BasicAttnBlock, GlobalAttnBlock +from .components import CNNEncoder, CostVolume, DispInit, FeatureFusion, Unet +from .refiners import GlobalRefiner, LocalRefiner, UpsampleMask1x, UpsampleMask4x +from .utils import custom_unfold + +# ── Model-level constants (must not be user-configurable) ───────────────────── + +_DIM_EXPANSION: int = 1 +_OT_ITER: int = 3 +_USE_POSITIVITY: bool = True +_OUTPUT_UPSAMPLE: bool = False +_REFINE_ITER: int = 3 + +# Per-variant channel / transformer counts — detected from checkpoint filename +_VARIANT_CONFIGS: dict[str, dict] = { + "S": {"feature_channels": 128, "num_transformer": 1}, + "M": {"feature_channels": 192, "num_transformer": 2}, + "L": {"feature_channels": 256, "num_transformer": 3}, + "XL": {"feature_channels": 384, "num_transformer": 3}, +} +_DEFAULT_VARIANT: str = "L" + + +def s2m2_config_from_checkpoint(model_path: str) -> dict: + """Return the architecture config for the S2M2 variant inferred from *model_path*. + + Detection checks the filename (case-insensitive) for ``-S``, ``-M``, ``-L``, + or ``-XL`` suffixes (with or without the ``.pth``/``.pt`` extension). + Falls back to the L variant when no match is found. + + Args: + model_path: Local file path to the checkpoint. + + Returns: + Dict with ``"feature_channels"`` and ``"num_transformer"`` keys. + """ + stem = Path(model_path).stem.upper() + for variant in ("XL", "L", "M", "S"): # XL before L to avoid partial match + if stem.endswith(f"-{variant}") or stem.endswith(f"_{variant}"): + return _VARIANT_CONFIGS[variant] + return _VARIANT_CONFIGS[_DEFAULT_VARIANT] + + +# ── MRT transformer block ───────────────────────────────────────────────────── + + +class MRT(nn.Module): + """Multi-scale recurrent transformer block — one stage of the StackedMRT. + + Implements a U-Net-shaped encoder-decoder path where each level applies + one :class:`BasicAttnBlock` (cross + self attention) and the bottleneck + applies two :class:`GlobalAttnBlock` steps with cross-attention. + + Args: + dims: Channel counts at three resolution levels ``[d0, d1, d2]``. + num_heads: Base head count (multiplied per level: 1×, 2×, 4×, 8×). + dim_expansion: Attention expansion factor. + use_gate_fusion: Whether to use gated skip connections. + """ + + def __init__(self, dims: list, num_heads: int, dim_expansion: int, use_gate_fusion: bool): + super().__init__() + self.down_conv0 = nn.Sequential(nn.AvgPool2d(2), nn.Conv2d(dims[0], dims[1], 1)) + self.down_conv1 = nn.Sequential(nn.AvgPool2d(2), nn.Conv2d(dims[1], dims[2], 1)) + self.down_conv2 = nn.Sequential(nn.AvgPool2d(2), nn.Conv2d(dims[2], dims[2], 1)) + self.up_conv0 = nn.Sequential( + nn.Upsample(scale_factor=2, mode="bilinear", align_corners=False), + nn.Conv2d(dims[1], dims[0], 1), + ) + self.up_conv1 = nn.Sequential( + nn.Upsample(scale_factor=2, mode="bilinear", align_corners=False), + nn.Conv2d(dims[2], dims[1], 1), + ) + self.up_conv2 = nn.Sequential( + nn.Upsample(scale_factor=2, mode="bilinear", align_corners=False), + nn.Conv2d(dims[2], dims[2], 1), + ) + self.down_concat1 = FeatureFusion(dims[1], 1, use_gate_fusion) + self.down_concat2 = FeatureFusion(dims[2], 1, use_gate_fusion) + self.down_concat3 = FeatureFusion(dims[2], 1, use_gate_fusion) + self.up_concat0 = FeatureFusion(dims[0], 1, use_gate_fusion) + self.up_concat1 = FeatureFusion(dims[1], 1, use_gate_fusion) + self.up_concat2 = FeatureFusion(dims[2], 1, use_gate_fusion) + self.enc_attn0 = BasicAttnBlock(dims[0], 1 * num_heads, dim_expansion) + self.enc_attn1 = BasicAttnBlock(dims[1], 2 * num_heads, dim_expansion) + self.enc_attn2 = BasicAttnBlock(dims[2], 4 * num_heads, dim_expansion) + self.enc_attn3s = nn.ModuleList( + [GlobalAttnBlock(dims[2], 8 * num_heads, dim_expansion, True) for _ in range(2)] + ) + self.dec_attn0 = BasicAttnBlock(dims[0], 1 * num_heads, dim_expansion) + self.dec_attn1 = BasicAttnBlock(dims[1], 2 * num_heads, dim_expansion) + self.dec_attn2 = BasicAttnBlock(dims[2], 4 * num_heads, dim_expansion) + self.dec_attn3s = nn.ModuleList( + [GlobalAttnBlock(dims[2], 8 * num_heads, dim_expansion, True) for _ in range(2)] + ) + + def forward(self, z0, z1, z2, z3): + """Apply one MRT encoder-decoder pass to four multi-scale feature maps. + + Args: + z0, z1, z2, z3: Feature maps at strides 1×, 2×, 4×, 8× (all ``(2B, C, H, W)``). + + Returns: + Updated ``(z0, z1, z2, z3)`` at the same shapes. + """ + z0 = self.enc_attn0(z0) + z1 = self.enc_attn1(self.down_concat1(z1, self.down_conv0(z0))) + z2 = self.enc_attn2(self.down_concat2(z2, self.down_conv1(z1))) + z3 = self.down_concat3(z3, self.down_conv2(z2)) + for blk in self.enc_attn3s: + z3 = blk(z3) + for blk in self.dec_attn3s: + z3 = blk(z3) + z2 = self.dec_attn2(self.up_concat2(z2, self.up_conv2(z3))) + z1 = self.dec_attn1(self.up_concat1(z1, self.up_conv1(z2))) + z0 = self.dec_attn0(self.up_concat0(z0, self.up_conv0(z1))) + return z0, z1, z2, z3 + + +class StackedMRT(nn.Module): + """Stack of *num_transformer* MRT blocks that refine multi-scale features iteratively. + + Args: + num_transformer: Number of MRT stages to stack. + dims: Channel counts per pyramid level ``[d0, d1, d2]``. + num_heads: Base attention head count. + dim_expansion: Attention expansion factor. + use_gate_fusion: Whether to use gated skip connections. + """ + + def __init__( + self, + num_transformer: int, + dims: list, + num_heads: int, + dim_expansion: int, + use_gate_fusion: bool, + ): + super().__init__() + self.uformer_list = nn.ModuleList( + [MRT(dims, num_heads, dim_expansion, use_gate_fusion) for _ in range(num_transformer)] + ) + + def forward(self, z0, z1, z2, z3) -> Tensor: + """Run all MRT stages in sequence and return the finest-resolution output. + + Returns: + ``z0`` after the final MRT stage, shape ``(2B, dims[0], H/4, W/4)``. + """ + for blk in self.uformer_list: + z0, z1, z2, z3 = blk(z0, z1, z2, z3) + return z0.contiguous() + + +# ── S2M2 top-level model ────────────────────────────────────────────────────── + + +class S2M2(nn.Module): + """Stereo Matching Model with Multi-scale transformer (S2M2). + + Full forward pass: CNN backbone → feature pyramid → stacked MRT transformer + → OT disparity init → global refinement → iterative local GRU refinement + → learned 4× and 1× upsampling. + + Instantiate via :func:`build_s2m2` rather than calling this constructor + directly, so architecture constants are applied consistently. + + Args: + feature_channels: Per-level channel count (variant-dependent). + dim_expansion: Q/K/V expansion factor (hardcoded to ``_DIM_EXPANSION``). + num_transformer: Number of StackedMRT stages (variant-dependent). + use_positivity: Clamp disparity ≥ 0 (hardcoded to ``_USE_POSITIVITY``). + output_upsample: Enable 2× output head (hardcoded to ``_OUTPUT_UPSAMPLE``). + refine_iter: Local GRU refinement steps (hardcoded to ``_REFINE_ITER``). + """ + + def __init__( + self, + feature_channels: int, + dim_expansion: int, + num_transformer: int, + use_positivity: bool = _USE_POSITIVITY, + output_upsample: bool = _OUTPUT_UPSAMPLE, + refine_iter: int = _REFINE_ITER, + ): + super().__init__() + ch = feature_channels + self.use_positivity = use_positivity + self.refine_iter = refine_iter + self.output_upsample = output_upsample + self.cnn_backbone = CNNEncoder(ch) + self.feat_pyramid = Unet( + [ch, ch, 2 * ch], + dim_expansion, + True, + n_attn=num_transformer * 2, + use_gate_fusion=True, + ) + self.transformer = StackedMRT(num_transformer, [ch, ch, 2 * ch], 1, dim_expansion, True) + self.disp_init = DispInit(ch, _OT_ITER, use_positivity) + self.upsample_mask_1x = UpsampleMask1x(ch) + self.upsample_mask_4x = UpsampleMask4x(ch) + self.global_refiner = GlobalRefiner(ch) + self.feat_fusion_layer = FeatureFusion(ch, 3, True) + self.refiner = LocalRefiner(ch, dim_expansion, 4, True) + self.ctx_feat = nn.Sequential(nn.Conv2d(ch, ch, 1), nn.GELU(), nn.Conv2d(ch, ch, 1)) + + def my_load_state_dict(self, state_dict: dict): + """Load *state_dict* with shape-mismatch tolerance. + + Silently skips keys whose tensor shapes differ from the current model + (e.g. when fine-tuning a pretrained model on a different image size). + + Args: + state_dict: Dict of parameter tensors, typically from + ``torch.load(...).get("state_dict", ckpt)``. + """ + own = self.state_dict() + for k in state_dict: + if k in own and state_dict[k].shape != own[k].shape: + state_dict[k] = own[k] + self.load_state_dict(state_dict, strict=False) + + @staticmethod + def _normalize(img0: Tensor, img1: Tensor): + """Normalise uint8 pixel values to ``[-1, 1]``.""" + return (img0 / 255.0 - 0.5) * 2, (img1 / 255.0 - 0.5) * 2 + + def _upsample4x(self, x: Tensor, up_weights: Tensor) -> Tensor: + """Apply the learned 4× convex-combination upsampler.""" + b, c, h, w = x.shape + x_unfold = custom_unfold(x.reshape(b, c, h, w), 3, 1) + x_unfold = F.interpolate(x_unfold, (h * 4, w * 4), mode="nearest").reshape( + b, 9, h * 4, w * 4 + ) + return (x_unfold * up_weights.softmax(dim=1)).sum(1, keepdim=True) + + def _upsample1x(self, disp: Tensor, filter_weights: Tensor) -> Tensor: + """Apply the guided 1× (or 2× when ``output_upsample``) disparity upsampler.""" + disp_unfold = custom_unfold(disp, 3, 1) + if self.output_upsample: + disp_unfold = F.interpolate(disp_unfold, scale_factor=2, mode="nearest") + filter_weights = F.interpolate( + filter_weights, scale_factor=2, mode="bilinear", align_corners=False + ) + return (disp_unfold * filter_weights.softmax(dim=1).to(disp.dtype)).sum(1, keepdim=True) + + def forward(self, img0: Tensor, img1: Tensor): + """Run full stereo forward pass. + + Args: + img0: Left image ``(B, 3, H, W)`` with pixel values in ``[0, 255]``. + img1: Right image ``(B, 3, H, W)`` with pixel values in ``[0, 255]``. + + Returns: + ``(disp_up, occ_up, conf_up)`` — disparity (in pixels at input resolution), + occlusion, and confidence maps, all ``(B, 1, H, W)``. + """ + img0_nor, img1_nor = self._normalize(img0, img1) + feature_4x, feature_2x = self.cnn_backbone(torch.cat([img0_nor, img1_nor], dim=0)) + feature0_2x, _ = feature_2x.chunk(2, dim=0) + feature_py_4x, feature_py_8x, feature_py_16x, feature_py_32x = self.feat_pyramid(feature_4x) + feature_tr_4x = self.transformer( + feature_py_4x, feature_py_8x, feature_py_16x, feature_py_32x + ) + disp, conf, occ, cv = self.disp_init(feature_tr_4x) + feature0_tr_4x, _ = feature_tr_4x.chunk(2, dim=0) + feature0_py_4x, _ = feature_py_4x.chunk(2, dim=0) + disp = self.global_refiner(feature0_tr_4x.contiguous(), disp.detach(), conf.detach()) + if self.use_positivity: + disp = disp.clamp(min=0) + feature0_fusion_4x = self.feat_fusion_layer(feature0_tr_4x, feature0_py_4x) + ctx0 = self.ctx_feat(feature0_fusion_4x) + hidden = torch.tanh(ctx0) + b, c, h, w = feature0_fusion_4x.shape + coords_4x = torch.arange( + w, device=feature0_fusion_4x.device, dtype=feature0_fusion_4x.dtype + ) + cv_fn = CostVolume(cv, coords_4x.reshape(1, 1, w, 1).repeat(b, h, 1, 1), radius=4) + for _ in range(self.refine_iter): + hidden, disp, conf, occ = self.refiner(hidden, ctx0, disp, conf, occ, cv_fn) + if self.use_positivity: + disp = disp.clamp(min=0) + occ = occ * torch.ge(coords_4x.reshape(1, 1, 1, -1) - disp, 0) + upsample_mask = self.upsample_mask_4x(hidden, feature0_2x) + disp_up = self._upsample4x(disp * 4, upsample_mask) + occ_up = self._upsample4x(occ, upsample_mask) + conf_up = self._upsample4x(conf, upsample_mask) + filter_weights = self.upsample_mask_1x(disp_up, img0_nor, feature0_2x) + disp_up = self._upsample1x(disp_up, filter_weights) + occ_up = self._upsample1x(occ_up, filter_weights) + conf_up = self._upsample1x(conf_up, filter_weights) + if self.output_upsample: + disp_up = 2 * disp_up + return disp_up, occ_up, conf_up + + +def build_s2m2(model_path: str) -> S2M2: + """Construct an :class:`S2M2` instance with the correct architecture for *model_path*. + + Architecture constants (_DIM_EXPANSION, _USE_POSITIVITY, _REFINE_ITER, + _OUTPUT_UPSAMPLE) are applied automatically. The variant (S/M/L/XL) is + detected from the checkpoint filename. + + Args: + model_path: Path to the ``.pth`` checkpoint. + + Returns: + Un-loaded :class:`S2M2` in eval-ready configuration (call + ``my_load_state_dict`` + ``.eval()`` to complete initialisation). + """ + cfg = s2m2_config_from_checkpoint(model_path) + return S2M2( + feature_channels=cfg["feature_channels"], + dim_expansion=_DIM_EXPANSION, + num_transformer=cfg["num_transformer"], + use_positivity=_USE_POSITIVITY, + output_upsample=_OUTPUT_UPSAMPLE, + refine_iter=_REFINE_ITER, + ) diff --git a/vizion3d/stereo/arch/utils.py b/vizion3d/stereo/arch/utils.py new file mode 100644 index 0000000..4ac9763 --- /dev/null +++ b/vizion3d/stereo/arch/utils.py @@ -0,0 +1,190 @@ +""" +Image manipulation, positional encoding, and numeric utilities for S2M2. + +This module contains pure tensor operations shared across the model architecture: +padding/cropping helpers, sinc-based positional encoding, cost-volume sampling, +and numerically stable log-sum-exp. +""" + +import math + +import torch +import torch.nn.functional as F +from torch import Tensor + + +def image_pad(img: Tensor, factor: int = 32) -> Tensor: + """Pad spatial dims to the next multiple of *factor* with content-aware fill. + + The border pixels are filled by downsampling then upsampling the padded region + so edge artefacts do not bleed into the network. The original image content is + then written back into the centre of the padded result. + + Args: + img: Float tensor of shape ``(B, C, H, W)``. + factor: Divisibility factor (default 32). + + Returns: + Padded tensor of shape ``(B, C, H', W')`` where ``H'`` and ``W'`` are the + nearest multiples of *factor* ≥ ``H`` and ``W``. + """ + H, W = img.shape[-2:] + H_new = math.ceil(H / factor) * factor + W_new = math.ceil(W / factor) * factor + pad_h = H_new - H + pad_w = W_new - W + img_pad = F.pad(img, (pad_w // 2, pad_w - pad_w // 2, 0, 0), "constant", 0) + img_pad = F.pad(img_pad, (0, 0, pad_h // 2, pad_h - pad_h // 2), "constant", 0) + img_pad_down = F.adaptive_avg_pool2d(img_pad.float(), output_size=[H // factor, W // factor]) + img_pad = F.interpolate(img_pad_down, size=[H_new, W_new], mode="bilinear") + h_s, h_e = pad_h // 2, pad_h - pad_h // 2 + w_s, w_e = pad_w // 2, pad_w - pad_w // 2 + if h_e == 0 and w_e == 0: + img_pad[:, :, h_s:, w_s:] = img + elif h_e == 0: + img_pad[:, :, h_s:, w_s:-w_e] = img + elif w_e == 0: + img_pad[:, :, h_s:-h_e, w_s:] = img + else: + img_pad[:, :, h_s:-h_e, w_s:-w_e] = img + return img_pad + + +def image_crop(img: Tensor, img_shape: tuple) -> Tensor: + """Remove symmetric padding added by :func:`image_pad`. + + Args: + img: Padded tensor of shape ``(B, C, H_pad, W_pad)``. + img_shape: ``(H_orig, W_orig)`` — the target crop size. + + Returns: + Cropped tensor of shape ``(B, C, H_orig, W_orig)``. + """ + H, W = img.shape[-2:] + H_new, W_new = img_shape + crop_h = H - H_new + if crop_h > 0: + s, e = crop_h // 2, crop_h - crop_h // 2 + img = img[:, :, s:-e] + crop_w = W - W_new + if crop_w > 0: + s, e = crop_w // 2, crop_w - crop_w // 2 + img = img[:, :, :, s:-e] + return img + + +def custom_sinc(x: Tensor) -> Tensor: + """Numerically stable sinc: ``sin(π·x)/(π·x)`` with the correct limit 1 at x=0. + + Args: + x: Input tensor (any shape, any dtype). + + Returns: + Sinc values, same shape and dtype as *x*. + """ + return torch.where( + torch.abs(x) < 1e-6, + torch.ones_like(x), + (torch.sin(3.1415 * x) / (3.1415 * x)).to(x.dtype), + ) + + +def custom_unfold(x: Tensor, kernel_size: int = 3, padding: int = 1) -> Tensor: + """Expand a feature map into per-pixel 3×3 neighbourhood patches. + + The output channels contain the ``kernel_size²`` shifted copies of the input, + concatenated along the channel dimension — equivalent to ``nn.Unfold`` but + implemented as a stack of slices to avoid large intermediate tensors. + + Args: + x: Input tensor ``(B, C, H, W)``. + kernel_size: Neighbourhood size (default 3). + padding: Replicate padding applied before extraction (default 1). + + Returns: + Tensor ``(B, C·kernel_size², H, W)``. + """ + B, C, H, W = x.shape + x_pad = F.pad(x, (padding, padding, padding, padding), "replicate") + parts = [] + for i in range(kernel_size): + for j in range(kernel_size): + parts.append(x_pad[:, :, i : i + H, j : j + W]) + return torch.cat(parts, dim=1) + + +def get_pe(h: int, w: int, pe_dim: int, dtype, device) -> Tensor: + """Compute 2D relative positional encoding via sinc interpolation. + + Produces a ``(h·w, h·w, pe_dim)`` tensor whose ``[i, j, :]`` entry encodes + the relative 2D offset between spatial positions *i* and *j*. + + Args: + h: Feature-map height (at the scale where PE is applied). + w: Feature-map width. + pe_dim: Encoding dimensionality (split equally between x and y). + dtype: Torch dtype for the output. + device: Torch device for the output. + + Returns: + Positional encoding tensor ``(h·w, h·w, pe_dim)``. + """ + with torch.no_grad(): + grid_y, grid_x = torch.meshgrid( + torch.linspace(0, h - 1, h, device=device, dtype=dtype), + torch.linspace(0, w - 1, w, device=device, dtype=dtype), + indexing="ij", + ) + rel_x = (grid_x.reshape(-1, 1) - grid_x.reshape(1, -1)).long() + rel_y = (grid_y.reshape(-1, 1) - grid_y.reshape(1, -1)).long() + + sig = 5 / pe_dim + x_pos = torch.linspace(-3, 3, 2 * w + 1, device=device, dtype=dtype).tanh() + dim_t = torch.linspace(-1, 1, pe_dim // 2, device=device, dtype=dtype) + pe_x = F.normalize(custom_sinc((dim_t[None] - x_pos[:, None]) / sig), p=2, dim=-1) + rel_pe_x = pe_x[rel_x + w - 1].reshape(h * w, h * w, pe_dim // 2) + + y_pos = torch.linspace(-3, 3, 2 * h + 1, device=device, dtype=dtype).tanh() + pe_y = F.normalize(custom_sinc((dim_t[None] - y_pos[:, None]) / sig), p=2, dim=-1) + rel_pe_y = pe_y[rel_y + h - 1].reshape(h * w, h * w, pe_dim // 2) + + pe = 0.5 * torch.cat([rel_pe_x, rel_pe_y], dim=2) + return pe.clone() + + +def bilinear_sampler(img: Tensor, coords: Tensor, mode: str = "bilinear") -> Tensor: + """Sample *img* at fractional pixel coordinates using bilinear interpolation. + + Args: + img: Feature map ``(B·H, 1, H_feat, W_feat)`` (squeezed batch format used + by :class:`CostVolume`). + coords: Sampling coordinates ``(B·H, W, K, 2)`` where the last dim is + ``(x, y)`` in pixel units (not normalised). + mode: Interpolation mode forwarded to ``F.grid_sample``. + + Returns: + Sampled values, same shape prefix as *coords* with the channel squeezed. + """ + W = torch.tensor(img.shape[-1], dtype=img.dtype, device=img.device) + H = torch.tensor(img.shape[-2], dtype=img.dtype, device=img.device) + xgrid, ygrid = coords.split([1, 1], dim=-1) + grid = torch.cat([2 * xgrid / (W - 1) - 1, 2 * ygrid / (H - 1) - 1], dim=-1) + return F.grid_sample(img, grid, mode=mode, align_corners=True) + + +def logsumexp_stable(x: Tensor, dim: int, keepdim: bool = False, eps: float = 1e-30) -> Tensor: + """Numerically stable log-sum-exp along *dim* using the max-subtraction trick. + + Args: + x: Input tensor. + dim: Reduction dimension. + keepdim: Whether to keep the reduced dimension. + eps: Floor clamped onto the inner sum to avoid ``log(0)``. + + Returns: + Log-sum-exp values, with *dim* reduced (or kept as size 1 if *keepdim*). + """ + m, _ = x.max(dim=dim, keepdim=True) + y = (x - m).exp().sum(dim=dim, keepdim=True) + y = m + torch.log(torch.clamp(y, min=eps)) + return y if keepdim else y.squeeze(dim) diff --git a/vizion3d/stereo/commands.py b/vizion3d/stereo/commands.py new file mode 100644 index 0000000..b78dd94 --- /dev/null +++ b/vizion3d/stereo/commands.py @@ -0,0 +1,59 @@ +""" +CQRS command payload for the Stereo Depth task. +""" + +from dataclasses import dataclass, field + +from vizion3d.core.cqrs import Command + +from .defaults import DEFAULT_STEREO_MODEL_URL +from .models import StereoDepthAdvancedConfig, StereoDepthResult + + +@dataclass +class StereoDepthCommand(Command[StereoDepthResult]): + """Command payload to trigger a stereo depth inference task. + + Stereo depth produces **real metric depth** (in metres) by matching + corresponding pixels across a rectified left/right image pair and applying + the stereo geometry formula: + + depth_m = baseline_mm × focal_length_px / disparity_px / 1000 + + Attributes: + left_image: The left-camera image. Pass a file-path string or raw + image bytes. The handler auto-detects which form is supplied. + right_image: The right-camera image (same resolution as *left_image*, + from a horizontally-offset camera). Same path/bytes convention. + model_backend: S2M2 checkpoint to use for inference. + + - Default value is the vizion3D release checkpoint URL + (``stereo-depth-s2m2-L.pth``), downloaded on first use and cached + under ``~/.cache/vizion3d/models/``. + Set ``VIZION3D_MODEL_CACHE`` to override the cache directory. + - A local ``.pth`` or ``.pt`` path is loaded directly. + - Any HTTPS URL is downloaded to the cache directory and loaded. + + return_depth_image: When ``True``, the result includes a 16-bit grayscale + ``open3d.geometry.Image`` (dtype ``uint16``) where the full 0–65535 + range maps linearly to ``[min_depth, max_depth]`` in metres. + return_point_cloud: When ``True``, the result includes an + ``open3d.geometry.PointCloud`` unprojected using the stereo camera + intrinsics in ``advanced_config``. Point coordinates are in metres. + return_mesh: When ``True``, the result includes an + ``open3d.geometry.TriangleMesh`` reconstructed from the point cloud + via ball-pivoting. Includes vertex colours. + advanced_config: Camera intrinsics and inference settings. Override any + field to match your stereo rig — e.g. + ``advanced_config=StereoDepthAdvancedConfig(focal_length=1733.74, + cx=792.27, cy=541.89, baseline=536.62)``. + Unspecified fields keep their defaults (1280×720 @ 100 mm baseline). + """ + + left_image: str | bytes + right_image: str | bytes + model_backend: str = DEFAULT_STEREO_MODEL_URL + return_depth_image: bool = False + return_point_cloud: bool = False + return_mesh: bool = False + advanced_config: StereoDepthAdvancedConfig = field(default_factory=StereoDepthAdvancedConfig) diff --git a/vizion3d/stereo/defaults.py b/vizion3d/stereo/defaults.py new file mode 100644 index 0000000..9ebbe46 --- /dev/null +++ b/vizion3d/stereo/defaults.py @@ -0,0 +1,36 @@ +""" +Default model configuration and download utilities for Stereo Depth. + +Model download logic is shared with the lifting module — URLs are resolved, +downloaded on first use, and cached under ``~/.cache/vizion3d/models/`` (or the +directory specified by the ``VIZION3D_MODEL_CACHE`` environment variable). +""" + +from __future__ import annotations + +from pathlib import Path + +from vizion3d.lifting.defaults import resolve_model_backend + +DEFAULT_STEREO_MODEL_URL = ( + "https://github.com/OlafenwaMoses/vizion3D/releases/download/" + "essentials-v1/stereo-depth-s2m2-L.pth" +) +DEFAULT_STEREO_MODEL_FILENAME = "stereo-depth-s2m2-L.pth" + + +def resolve_stereo_model_backend(model_backend: str, cache_dir: Path | None = None) -> str: + """Resolve *model_backend* to a local file path, downloading if needed. + + Delegates to :func:`vizion3d.lifting.defaults.resolve_model_backend` so the + stereo and depth-estimation modules share the same download/cache logic. + + Args: + model_backend: A URL or local file path to the S2M2 checkpoint. + cache_dir: Override for the model cache directory. ``None`` uses + ``default_model_cache_dir()`` from the lifting defaults. + + Returns: + Absolute local path to the resolved checkpoint file. + """ + return resolve_model_backend(model_backend, cache_dir=cache_dir) diff --git a/vizion3d/stereo/handlers.py b/vizion3d/stereo/handlers.py new file mode 100644 index 0000000..66cd2a5 --- /dev/null +++ b/vizion3d/stereo/handlers.py @@ -0,0 +1,372 @@ +""" +CQRS command handler for the Stereo Depth task. + +Orchestrates model loading, image pre-processing, stereo inference, depth +computation, and optional point-cloud / mesh generation. +""" + +from __future__ import annotations + +import contextlib +import io +import threading + +import numpy as np +from PIL import Image + +from vizion3d.core.cqrs import CommandHandler +from vizion3d.lifting.handlers import ( + OPEN3D_CAMERA_TO_IMAGE_VIEW_TRANSFORM, + DepthEstimationHandler, +) + +from .arch import build_s2m2 +from .arch.utils import image_crop, image_pad +from .commands import StereoDepthCommand +from .defaults import resolve_stereo_model_backend +from .models import StereoDepthResult + +# Flip-Y transform reused from the depth estimation handler so point-cloud +# orientation matches the image-plane convention (Y increases downward). +_CAMERA_TO_IMAGE_VIEW = OPEN3D_CAMERA_TO_IMAGE_VIEW_TRANSFORM + + +class StereoDepthHandler(CommandHandler[StereoDepthCommand, StereoDepthResult]): + """Handles :class:`~vizion3d.stereo.commands.StereoDepthCommand` inference requests. + + Models are loaded on first use and cached in a class-level dict so subsequent + calls within the same process reuse weights without re-reading disk. A lock + ensures thread-safe initialisation. + + The inference pipeline: + 1. Resolve / download the checkpoint. + 2. Load and cache the S2M2 model (thread-safe). + 3. Pre-process the image pair (resize, pad to 32-px multiple). + 4. Run stereo inference with mixed-precision autocast where available. + 5. Crop output back to original resolution; optionally upsample if scaled. + 6. Convert disparity → metric depth using the pinhole stereo formula. + 7. Unproject depth + colour into an Open3D PointCloud and optionally mesh. + """ + + _stereo_models: dict = {} + _model_lock = threading.Lock() + + def handle(self, command: StereoDepthCommand) -> StereoDepthResult: + """Execute the full stereo depth inference pipeline. + + Args: + command: Fully populated :class:`StereoDepthCommand`. + + Returns: + :class:`StereoDepthResult` with depth map, disparity map, and + optional depth image, point cloud, and mesh. + """ + model_id = resolve_stereo_model_backend(command.model_backend) + + def _load_image(src: str | bytes) -> Image.Image: + if isinstance(src, str): + return Image.open(src).convert("RGB") + return Image.open(io.BytesIO(src)).convert("RGB") + + left_pil = _load_image(command.left_image) + right_pil = _load_image(command.right_image) + + inference = self._run_s2m2(model_id, left_pil, right_pil, command.advanced_config) + if isinstance(inference, tuple): + disp_np, occ_np, conf_np = inference + else: + # Backwards-compatible path for tests or custom subclasses that patch + # _run_s2m2 to return only a disparity map. + disp_np, occ_np, conf_np = inference, None, None + + cfg = command.advanced_config + + # Disparity → metric depth (millimetre formula → metres) + with np.errstate(divide="ignore", invalid="ignore"): + depth_mm = cfg.baseline * cfg.focal_length / (disp_np + cfg.doffs) + depth_mm[disp_np <= 0] = 0.0 + depth_m = depth_mm / 1000.0 + + min_depth = float(np.min(depth_m)) + max_depth = float(np.max(depth_m)) + depth_map: list[list[float]] = depth_m.astype(np.float32).tolist() + disparity_map: list[list[float]] = disp_np.astype(np.float32).tolist() + + depth_image = None + if command.return_depth_image: + try: + import open3d as o3d + except ImportError: + raise ImportError( + "open3d is required for depth image output. Pin to Python 3.12 and run: uv sync" + ) + depth_range = max_depth - min_depth + if depth_range > 0: + normalized = (depth_m - min_depth) / depth_range + else: + normalized = np.zeros_like(depth_m) + depth_16bit = (normalized * 65535).astype(np.uint16) + depth_image = o3d.geometry.Image(depth_16bit) + + point_cloud = None + mesh = None + if command.return_point_cloud or command.return_mesh: + try: + import open3d as o3d + except ImportError: + raise ImportError( + "open3d is required for point cloud / mesh output. " + "Pin to Python 3.12 and run: uv sync" + ) + point_cloud, mesh = self._unproject( + left_pil, + depth_m, + disp_np, + cfg, + o3d, + occ_np=occ_np, + conf_np=conf_np, + want_cloud=command.return_point_cloud, + want_mesh=command.return_mesh, + ) + + return StereoDepthResult( + depth_map=depth_map, + disparity_map=disparity_map, + min_depth=min_depth, + max_depth=max_depth, + backend_used=model_id, + depth_image=depth_image, + point_cloud=point_cloud, + mesh=mesh, + point_cloud_scale=1.0, + ) + + # ── Model loading ───────────────────────────────────────────────────────── + + def _load_s2m2(self, model_path: str): + """Load and cache an S2M2 checkpoint (thread-safe double-checked locking). + + Args: + model_path: Resolved local path to the ``.pth`` checkpoint. + + Returns: + ``(model, torch, device)`` tuple ready for inference. + """ + if model_path in self._stereo_models: + return self._stereo_models[model_path] + + with self._model_lock: + if model_path in self._stereo_models: + return self._stereo_models[model_path] + + try: + import torch + except ImportError as exc: + raise ImportError("S2M2 stereo checkpoints require torch. Run: uv sync") from exc + + device = self._torch_device(torch) + model = build_s2m2(model_path) + + try: + ckpt = torch.load(model_path, map_location="cpu", weights_only=True) + except TypeError: + ckpt = torch.load(model_path, map_location="cpu") + + state_dict = ckpt.get("state_dict", ckpt) + model.my_load_state_dict(state_dict) + model = model.to(device).eval() + + self._stereo_models[model_path] = (model, torch, device) + return self._stereo_models[model_path] + + # ── Inference ───────────────────────────────────────────────────────────── + + def _run_s2m2( + self, + model_path: str, + left: Image.Image, + right: Image.Image, + cfg, + ) -> np.ndarray: + """Run one stereo forward pass and return the disparity map (in pixels). + + Handles input scaling, padding, autocast, output cropping, and upsampling. + + Args: + model_path: Resolved local path to the checkpoint. + left: Left PIL image (RGB). + right: Right PIL image (RGB). + cfg: :class:`~vizion3d.stereo.models.StereoDepthAdvancedConfig`. + + Returns: + Tuple of ``(disparity, occlusion, confidence)`` float32 numpy arrays, + each shape ``(H, W)`` at the original image resolution. + """ + model, torch, device = self._load_s2m2(model_path) + + import torch.nn.functional as F + + img_h, img_w = left.height, left.width + + left_t = torch.from_numpy(np.asarray(left).copy()).permute(2, 0, 1).unsqueeze(0).float() + right_t = torch.from_numpy(np.asarray(right).copy()).permute(2, 0, 1).unsqueeze(0).float() + + sf = cfg.scale_factor + if sf != 1.0: + scaled_h = round(img_h * sf / 32) * 32 + scaled_w = round(img_w * sf / 32) * 32 + left_t_inp = F.interpolate( + left_t, + (scaled_h, scaled_w), + mode="bilinear", + align_corners=False, + ) + right_t_inp = F.interpolate( + right_t, + (scaled_h, scaled_w), + mode="bilinear", + align_corners=False, + ) + else: + left_t_inp = left_t + right_t_inp = right_t + + left_pad = image_pad(left_t_inp, 32).to(device) + right_pad = image_pad(right_t_inp, 32).to(device) + + device_type = device if isinstance(device, str) else device.type + if device_type == "cuda": + autocast_ctx = torch.amp.autocast(device_type="cuda", dtype=torch.float16, enabled=True) + elif device_type == "mps": + autocast_ctx = torch.amp.autocast(device_type="mps", dtype=torch.float16, enabled=True) + else: + autocast_ctx = contextlib.nullcontext() + + with torch.inference_mode(), autocast_ctx: + pred_disp, pred_occ, pred_conf = model(left_pad, right_pad) + + if sf != 1.0: + scaled_h = round(img_h * sf / 32) * 32 + scaled_w = round(img_w * sf / 32) * 32 + pred_disp = image_crop(pred_disp, (scaled_h, scaled_w)) + pred_disp = ( + F.interpolate( + pred_disp, + (img_h, img_w), + mode="bilinear", + align_corners=False, + ) + / sf + ) + pred_occ = image_crop(pred_occ, (scaled_h, scaled_w)) + pred_occ = F.interpolate( + pred_occ, + (img_h, img_w), + mode="bilinear", + align_corners=False, + ) + pred_conf = image_crop(pred_conf, (scaled_h, scaled_w)) + pred_conf = F.interpolate( + pred_conf, + (img_h, img_w), + mode="bilinear", + align_corners=False, + ) + else: + pred_disp = image_crop(pred_disp, (img_h, img_w)) + pred_occ = image_crop(pred_occ, (img_h, img_w)) + pred_conf = image_crop(pred_conf, (img_h, img_w)) + + if device_type == "mps": + torch.mps.empty_cache() + + return ( + pred_disp.squeeze().float().cpu().numpy(), + pred_occ.squeeze().float().cpu().numpy(), + pred_conf.squeeze().float().cpu().numpy(), + ) + + # ── Point cloud / mesh ──────────────────────────────────────────────────── + + def _unproject( + self, + left_pil, + depth_m, + disp_np, + cfg, + o3d, + *, + occ_np=None, + conf_np=None, + want_cloud, + want_mesh, + ): + """Unproject the left image into a coloured 3D point cloud and optional mesh. + + Args: + left_pil: Left PIL image (RGB) — used for vertex colours. + depth_m: Metric depth map, shape ``(H, W)``. + disp_np: Raw disparity map, shape ``(H, W)``. + cfg: :class:`~vizion3d.stereo.models.StereoDepthAdvancedConfig`. + o3d: Imported open3d module. + occ_np: Optional per-pixel occlusion score, shape ``(H, W)``. + conf_np: Optional per-pixel confidence score, shape ``(H, W)``. + want_cloud: Whether to return the point cloud. + want_mesh: Whether to return the mesh. + + Returns: + ``(point_cloud, mesh)`` — each is the Open3D object or ``None`` if not requested. + """ + H, W = depth_m.shape + left_np = np.asarray(left_pil) + + uu, vv = np.meshgrid(np.arange(W, dtype=np.float32), np.arange(H, dtype=np.float32)) + x = (uu - cfg.cx) * depth_m / cfg.focal_length + y = (vv - cfg.cy) * depth_m / cfg.focal_length + z = depth_m + + valid = (z > 0) & (z < cfg.z_far) + if conf_np is not None: + valid &= conf_np >= cfg.conf_threshold + if occ_np is not None: + valid &= occ_np >= cfg.occ_threshold + pts = np.stack([x, y, z], axis=-1)[valid] + cols = left_np[valid].astype(np.float64) / 255.0 + + pcd = o3d.geometry.PointCloud() + pcd.points = o3d.utility.Vector3dVector(pts) + pcd.colors = o3d.utility.Vector3dVector(cols) + + # Flip Y so Y increases downward in the viewer, matching image-plane orientation. + pcd.transform(_CAMERA_TO_IMAGE_VIEW) + + mesh = None + if want_mesh: + mesh = DepthEstimationHandler._mesh_from_point_cloud(pcd, o3d) + + return (pcd if want_cloud else None), mesh + + # ── Pre-loading ─────────────────────────────────────────────────────────── + + @classmethod + def preload(cls, model_path: str) -> None: + """Resolve *model_path* (downloading if a URL) and load it into the class-level cache. + + Call this at server startup to ensure the model is in memory before the first request. + """ + from .defaults import resolve_stereo_model_backend + + resolved = resolve_stereo_model_backend(model_path) + cls()._load_s2m2(resolved) + + # ── Device selection ────────────────────────────────────────────────────── + + @staticmethod + def _torch_device(torch_module) -> str: + """Return the best available device string: ``'cuda'``, ``'mps'``, or ``'cpu'``.""" + if torch_module.cuda.is_available(): + return "cuda" + if hasattr(torch_module.backends, "mps") and torch_module.backends.mps.is_available(): + return "mps" + return "cpu" diff --git a/vizion3d/stereo/models.py b/vizion3d/stereo/models.py new file mode 100644 index 0000000..41c91e9 --- /dev/null +++ b/vizion3d/stereo/models.py @@ -0,0 +1,96 @@ +""" +Data models for the Stereo Depth task. + +Defines the camera-configuration Pydantic model and the result payload. +""" + +from open3d.geometry import Image as O3dImage # type: ignore[import-untyped] +from open3d.geometry import PointCloud as O3dPointCloud # type: ignore[import-untyped] +from open3d.geometry import TriangleMesh as O3dTriangleMesh # type: ignore[import-untyped] +from pydantic import BaseModel, ConfigDict + + +class StereoDepthAdvancedConfig(BaseModel): + """Camera intrinsics and inference settings for stereo depth estimation. + + All fields are optional overrides — unspecified fields retain sensible defaults + for a 1280×720 commodity stereo camera with a 100 mm baseline. + + Attributes: + focal_length: Focal length in pixels (assumes square pixels, i.e. fx = fy). + Larger values mean a narrower field of view and more perspective + compression. Override with your camera's actual calibrated value. + cx: Principal point x — the pixel column of the optical axis, typically + near the horizontal image centre (``image_width / 2 - 0.5``). + cy: Principal point y — the pixel row of the optical axis, typically near + the vertical image centre (``image_height / 2 - 0.5``). + baseline: Stereo baseline in **millimetres** — the physical distance between + the two camera optical centres. Real metric depth is proportional to + this value, so an incorrect baseline scales all depth values uniformly. + doffs: Disparity offset in pixels. Non-zero for Middlebury-style calibration + where the principal points are not aligned across the two views. + Set to ``0.0`` for standard rectified pairs. + z_far: Maximum depth in metres. Points beyond this distance are excluded + from the point cloud and mesh to reduce noise and file size. + conf_threshold: Minimum per-pixel confidence score (in ``[0, 1]``) for a + point to be included in the point cloud. Lower values include more + uncertain points; higher values give sparser but more reliable clouds. + occ_threshold: Minimum occlusion score (in ``[0, 1]``) for a point to be + included. Points with low occlusion scores are likely partially occluded + in one view and produce less reliable depth estimates. + scale_factor: Input image downscale factor before inference. ``1.0`` means + full resolution (highest quality, slowest). ``0.5`` halves both spatial + dimensions (~3–4× faster at some quality cost). + """ + + focal_length: float = 1000.0 + cx: float = 640.0 + cy: float = 360.0 + baseline: float = 100.0 + doffs: float = 0.0 + z_far: float = 10.0 + conf_threshold: float = 0.1 + occ_threshold: float = 0.5 + scale_factor: float = 1.0 + + +class StereoDepthResult(BaseModel): + """Result payload returned after a stereo depth inference task. + + Attributes: + depth_map: Metric depth in **metres**, shape ``[H][W]``. Unlike monocular + depth estimation, these are real-world distances (assuming correct camera + calibration) — not relative or fictitious values. + disparity_map: Raw disparity map in pixels, shape ``[H][W]``. Disparity + is the horizontal pixel offset between matched features across the + left and right images. Depth = baseline × focal_length / disparity. + min_depth: Minimum value in ``depth_map`` (metres). + max_depth: Maximum value in ``depth_map`` (metres). Guaranteed + ``max_depth >= min_depth``. + backend_used: Resolved local file path of the checkpoint used. + depth_image: 16-bit grayscale ``open3d.geometry.Image`` (dtype ``uint16``) + where the full 0–65535 range maps linearly to ``[min_depth, max_depth]``. + Present when ``return_depth_image=True`` was set on the command. + point_cloud: Coloured ``open3d.geometry.PointCloud`` unprojected from the + RGB-D image using the camera intrinsics in ``advanced_config``. + Coordinates are in metres. Present when ``return_point_cloud=True``. + mesh: ``open3d.geometry.TriangleMesh`` reconstructed via ball-pivoting + from the point cloud. Includes vertex colours. + Present when ``return_mesh=True``. + point_cloud_scale: Scale factor: multiply any distance measured between + two points in the returned point cloud by this value to get the + equivalent distance in metres. Always ``1.0`` for stereo depth — + coordinates are already in real metric units. + """ + + depth_map: list[list[float]] + disparity_map: list[list[float]] + min_depth: float + max_depth: float + backend_used: str + depth_image: O3dImage | None = None + point_cloud: O3dPointCloud | None = None + mesh: O3dTriangleMesh | None = None + point_cloud_scale: float = 1.0 + + model_config = ConfigDict(arbitrary_types_allowed=True) From 719d2a83e9e5d056b535e78170ab45918b1f9c2e Mon Sep 17 00:00:00 2001 From: OlafenwaMoses Date: Mon, 4 May 2026 00:55:26 +0100 Subject: [PATCH 3/7] doc update for model link --- docs/features/depth_estimation.md | 14 +++++++++++++- docs/features/stereo_depth.md | 9 +++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/features/depth_estimation.md b/docs/features/depth_estimation.md index 7c4f1f2..8c1c00c 100644 --- a/docs/features/depth_estimation.md +++ b/docs/features/depth_estimation.md @@ -9,6 +9,15 @@ Depth estimation predicts the per-pixel distance from the camera for every pixel ## Model backends +Default checkpoint download: +[depth_anything_v2_vitb.pth](https://github.com/OlafenwaMoses/vizion3D/releases/download/essentials-v1/depth_anything_v2_vitb.pth) + +```bash +curl -L \ + https://github.com/OlafenwaMoses/vizion3D/releases/download/essentials-v1/depth_anything_v2_vitb.pth \ + -o depth_anything_v2_vitb.pth +``` + | Value | What happens | |---|---| | *(default)* | Downloads the vizion3D release checkpoint (`depth_anything_v2_vitb.pth`) to `~/.cache/vizion3d/models/` on first use, then loads it directly | @@ -220,7 +229,10 @@ print(f"Backend: {result.backend_used}") # Remote checkpoint URL (downloaded and cached on first use) cmd = DepthEstimationCommand( image_input="scene.png", - model_backend="https://example.com/weights/depth_anything_v2_vits.pth", + model_backend=( + "https://github.com/OlafenwaMoses/vizion3D/releases/download/" + "essentials-v1/depth_anything_v2_vitb.pth" + ), ) result = DepthEstimation().run(cmd) print(f"Backend: {result.backend_used}") diff --git a/docs/features/stereo_depth.md b/docs/features/stereo_depth.md index e654d1b..488f9f1 100644 --- a/docs/features/stereo_depth.md +++ b/docs/features/stereo_depth.md @@ -15,6 +15,15 @@ vizion3d uses [S2M2](https://github.com/Dongyeop-Yoo/S2M2) (Stereo Matching Mode ## Model backends +Default checkpoint download: +[stereo-depth-s2m2-L.pth](https://github.com/OlafenwaMoses/vizion3D/releases/download/essentials-v1/stereo-depth-s2m2-L.pth) + +```bash +curl -L \ + https://github.com/OlafenwaMoses/vizion3D/releases/download/essentials-v1/stereo-depth-s2m2-L.pth \ + -o stereo-depth-s2m2-L.pth +``` + | Value | What happens | |---|---| | *(default)* | Downloads the vizion3D release checkpoint (`stereo-depth-s2m2-L.pth`, the L variant) to `~/.cache/vizion3d/models/` on first use, then loads it | From f04d6f53437b5231d21701a6879f9919cec53db9 Mon Sep 17 00:00:00 2001 From: OlafenwaMoses Date: Mon, 4 May 2026 01:22:36 +0100 Subject: [PATCH 4/7] rename warm and cold start limits varuable --- tests/integration/test_direct.py | 14 ++++++++------ tests/integration/test_grpc.py | 13 +++++++------ tests/integration/test_rest.py | 13 +++++++------ tests/integration/test_stereo_direct.py | 14 ++++++++------ tests/integration/test_stereo_grpc.py | 8 ++++---- tests/integration/test_stereo_rest.py | 8 ++++---- 6 files changed, 38 insertions(+), 32 deletions(-) diff --git a/tests/integration/test_direct.py b/tests/integration/test_direct.py index 17f8fa7..e37bb4e 100644 --- a/tests/integration/test_direct.py +++ b/tests/integration/test_direct.py @@ -32,8 +32,8 @@ from vizion3d.lifting.utils import create_ply_binary # noqa: E402 N_RUNS = 5 -COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_COLD_LIMIT", "10.0")) -WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_WARM_LIMIT", "1.0")) +DEPTH_COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_DEPTH_COLD_LIMIT", "10.0")) +DEPTH_WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_DEPTH_WARM_LIMIT", "1.0")) # ────────────────────────────────────────────────────────────────────────────── @@ -105,13 +105,15 @@ def _run_group( ) # ── timing assertions ───────────────────────────────────────────────────── - assert timings[0] < COLD_LIMIT, ( - f"[{entry_point} / {scenario}] Cold load took {timings[0]:.3f}s — expected < {COLD_LIMIT}s" + assert timings[0] < DEPTH_COLD_LIMIT, ( + f"[{entry_point} / {scenario}] Cold load took {timings[0]:.3f}s " + f"— expected < {DEPTH_COLD_LIMIT}s" ) for i, t in enumerate(timings[1:], start=2): - assert t < WARM_LIMIT, ( + assert t < DEPTH_WARM_LIMIT, ( f"[{entry_point} / {scenario}] " - f"Run {i} took {t:.3f}s — expected < {WARM_LIMIT}s (model should be cached)" + f"Run {i} took {t:.3f}s — expected < {DEPTH_WARM_LIMIT}s " + "(model should be cached)" ) return timings diff --git a/tests/integration/test_grpc.py b/tests/integration/test_grpc.py index 2e52880..91573e5 100644 --- a/tests/integration/test_grpc.py +++ b/tests/integration/test_grpc.py @@ -25,8 +25,8 @@ from vizion3d.proto import lifting_pb2 # noqa: E402 N_RUNS = 5 -COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_COLD_LIMIT", "10.0")) -WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_WARM_LIMIT", "1.0")) +DEPTH_COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_DEPTH_COLD_LIMIT", "10.0")) +DEPTH_WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_DEPTH_WARM_LIMIT", "1.0")) # ────────────────────────────────────────────────────────────────────────────── @@ -96,13 +96,14 @@ def _run_group( "Model should be cached in memory after first gRPC inference" ) - assert timings[0] < COLD_LIMIT, ( - f"[gRPC / {scenario}] Cold load took {timings[0]:.3f}s — expected < {COLD_LIMIT}s" + assert timings[0] < DEPTH_COLD_LIMIT, ( + f"[gRPC / {scenario}] Cold load took {timings[0]:.3f}s — expected < {DEPTH_COLD_LIMIT}s" ) for i, t in enumerate(timings[1:], start=2): - assert t < WARM_LIMIT, ( + assert t < DEPTH_WARM_LIMIT, ( f"[gRPC / {scenario}] " - f"Run {i} took {t:.3f}s — expected < {WARM_LIMIT}s (model should be cached)" + f"Run {i} took {t:.3f}s — expected < {DEPTH_WARM_LIMIT}s " + "(model should be cached)" ) return timings diff --git a/tests/integration/test_rest.py b/tests/integration/test_rest.py index 67541d8..051b2af 100644 --- a/tests/integration/test_rest.py +++ b/tests/integration/test_rest.py @@ -26,8 +26,8 @@ from vizion3d.server.rest.app import app # noqa: E402 N_RUNS = 5 -COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_COLD_LIMIT", "10.0")) -WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_WARM_LIMIT", "1.0")) +DEPTH_COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_DEPTH_COLD_LIMIT", "10.0")) +DEPTH_WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_DEPTH_WARM_LIMIT", "1.0")) client = TestClient(app, raise_server_exceptions=True) @@ -106,13 +106,14 @@ def _run_group( "Model should be cached in memory after first REST inference" ) - assert timings[0] < COLD_LIMIT, ( - f"[REST / {scenario}] Cold load took {timings[0]:.3f}s — expected < {COLD_LIMIT}s" + assert timings[0] < DEPTH_COLD_LIMIT, ( + f"[REST / {scenario}] Cold load took {timings[0]:.3f}s — expected < {DEPTH_COLD_LIMIT}s" ) for i, t in enumerate(timings[1:], start=2): - assert t < WARM_LIMIT, ( + assert t < DEPTH_WARM_LIMIT, ( f"[REST / {scenario}] " - f"Run {i} took {t:.3f}s — expected < {WARM_LIMIT}s (model should be cached)" + f"Run {i} took {t:.3f}s — expected < {DEPTH_WARM_LIMIT}s " + "(model should be cached)" ) return timings diff --git a/tests/integration/test_stereo_direct.py b/tests/integration/test_stereo_direct.py index e5f048a..0bc5cc3 100644 --- a/tests/integration/test_stereo_direct.py +++ b/tests/integration/test_stereo_direct.py @@ -32,8 +32,8 @@ from vizion3d.stereo.handlers import StereoDepthHandler # noqa: E402 N_RUNS = 5 -COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_COLD_LIMIT", "60.0")) -WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_WARM_LIMIT", "5.0")) +STEREO_COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_STEREO_COLD_LIMIT", "60.0")) +STEREO_WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_STEREO_WARM_LIMIT", "5.0")) # ────────────────────────────────────────────────────────────────────────────── @@ -102,13 +102,15 @@ def _run_group( "Model should be cached in StereoDepthHandler._stereo_models after first inference" ) - assert timings[0] < COLD_LIMIT, ( - f"[{entry_point} / {scenario}] Cold load took {timings[0]:.3f}s — expected < {COLD_LIMIT}s" + assert timings[0] < STEREO_COLD_LIMIT, ( + f"[{entry_point} / {scenario}] Cold load took {timings[0]:.3f}s " + f"— expected < {STEREO_COLD_LIMIT}s" ) for i, t in enumerate(timings[1:], start=2): - assert t < WARM_LIMIT, ( + assert t < STEREO_WARM_LIMIT, ( f"[{entry_point} / {scenario}] " - f"Run {i} took {t:.3f}s — expected < {WARM_LIMIT}s (model should be cached)" + f"Run {i} took {t:.3f}s — expected < {STEREO_WARM_LIMIT}s " + "(model should be cached)" ) return timings diff --git a/tests/integration/test_stereo_grpc.py b/tests/integration/test_stereo_grpc.py index 5b21806..47231ab 100644 --- a/tests/integration/test_stereo_grpc.py +++ b/tests/integration/test_stereo_grpc.py @@ -21,8 +21,8 @@ from vizion3d.stereo.handlers import StereoDepthHandler # noqa: E402 N_RUNS = 5 -COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_STEREO_COLD_LIMIT", "60.0")) -WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_STEREO_WARM_LIMIT", "5.0")) +STEREO_COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_STEREO_COLD_LIMIT", "60.0")) +STEREO_WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_STEREO_WARM_LIMIT", "5.0")) def _proto_config(config, **overrides): @@ -95,9 +95,9 @@ def _run_group( assert response.point_cloud_ply.startswith(b"ply\n") assert len(StereoDepthHandler._stereo_models) > 0 - assert timings[0] < COLD_LIMIT + assert timings[0] < STEREO_COLD_LIMIT for elapsed in timings[1:]: - assert elapsed < WARM_LIMIT + assert elapsed < STEREO_WARM_LIMIT return timings diff --git a/tests/integration/test_stereo_rest.py b/tests/integration/test_stereo_rest.py index 81b4f62..9ce3dff 100644 --- a/tests/integration/test_stereo_rest.py +++ b/tests/integration/test_stereo_rest.py @@ -23,8 +23,8 @@ from vizion3d.stereo.handlers import StereoDepthHandler # noqa: E402 N_RUNS = 5 -COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_STEREO_COLD_LIMIT", "60.0")) -WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_STEREO_WARM_LIMIT", "5.0")) +STEREO_COLD_LIMIT = float(os.environ.get("VIZION3D_TEST_STEREO_COLD_LIMIT", "60.0")) +STEREO_WARM_LIMIT = float(os.environ.get("VIZION3D_TEST_STEREO_WARM_LIMIT", "5.0")) client = TestClient(app, raise_server_exceptions=True) @@ -96,9 +96,9 @@ def _run_group( assert base64.b64decode(data["point_cloud_ply"]).startswith(b"ply\n") assert len(StereoDepthHandler._stereo_models) > 0 - assert timings[0] < COLD_LIMIT + assert timings[0] < STEREO_COLD_LIMIT for elapsed in timings[1:]: - assert elapsed < WARM_LIMIT + assert elapsed < STEREO_WARM_LIMIT return timings From 29ee90f22b3a0264702865fb1bdd8843df900924 Mon Sep 17 00:00:00 2001 From: OlafenwaMoses Date: Mon, 4 May 2026 01:46:10 +0100 Subject: [PATCH 5/7] test file renames and fixes --- .../{test_direct.py => test_depth_estimation_direct.py} | 0 tests/integration/{test_grpc.py => test_depth_estimation_grpc.py} | 0 tests/integration/{test_rest.py => test_depth_estimation_rest.py} | 0 .../{test_stereo_direct.py => test_stereo_depth_direct.py} | 0 .../{test_stereo_grpc.py => test_stereo_depth_grpc.py} | 0 .../{test_stereo_rest.py => test_stereo_depth_rest.py} | 0 ...dvanced_config.py => test_depth_estimation_advanced_config.py} | 0 ...test_lifting_defaults.py => test_depth_estimation_defaults.py} | 0 tests/unit/{test_facade.py => test_depth_estimation_facade.py} | 0 tests/unit/{test_grpc.py => test_depth_estimation_grpc.py} | 0 ...rest_api.py => test_depth_estimation_stereo_depth_rest_api.py} | 0 tests/unit/{test_stereo_config.py => test_stereo_depth_config.py} | 0 .../unit/{test_stereo_handler.py => test_stereo_depth_handler.py} | 0 13 files changed, 0 insertions(+), 0 deletions(-) rename tests/integration/{test_direct.py => test_depth_estimation_direct.py} (100%) rename tests/integration/{test_grpc.py => test_depth_estimation_grpc.py} (100%) rename tests/integration/{test_rest.py => test_depth_estimation_rest.py} (100%) rename tests/integration/{test_stereo_direct.py => test_stereo_depth_direct.py} (100%) rename tests/integration/{test_stereo_grpc.py => test_stereo_depth_grpc.py} (100%) rename tests/integration/{test_stereo_rest.py => test_stereo_depth_rest.py} (100%) rename tests/unit/{test_advanced_config.py => test_depth_estimation_advanced_config.py} (100%) rename tests/unit/{test_lifting_defaults.py => test_depth_estimation_defaults.py} (100%) rename tests/unit/{test_facade.py => test_depth_estimation_facade.py} (100%) rename tests/unit/{test_grpc.py => test_depth_estimation_grpc.py} (100%) rename tests/unit/{test_rest_api.py => test_depth_estimation_stereo_depth_rest_api.py} (100%) rename tests/unit/{test_stereo_config.py => test_stereo_depth_config.py} (100%) rename tests/unit/{test_stereo_handler.py => test_stereo_depth_handler.py} (100%) diff --git a/tests/integration/test_direct.py b/tests/integration/test_depth_estimation_direct.py similarity index 100% rename from tests/integration/test_direct.py rename to tests/integration/test_depth_estimation_direct.py diff --git a/tests/integration/test_grpc.py b/tests/integration/test_depth_estimation_grpc.py similarity index 100% rename from tests/integration/test_grpc.py rename to tests/integration/test_depth_estimation_grpc.py diff --git a/tests/integration/test_rest.py b/tests/integration/test_depth_estimation_rest.py similarity index 100% rename from tests/integration/test_rest.py rename to tests/integration/test_depth_estimation_rest.py diff --git a/tests/integration/test_stereo_direct.py b/tests/integration/test_stereo_depth_direct.py similarity index 100% rename from tests/integration/test_stereo_direct.py rename to tests/integration/test_stereo_depth_direct.py diff --git a/tests/integration/test_stereo_grpc.py b/tests/integration/test_stereo_depth_grpc.py similarity index 100% rename from tests/integration/test_stereo_grpc.py rename to tests/integration/test_stereo_depth_grpc.py diff --git a/tests/integration/test_stereo_rest.py b/tests/integration/test_stereo_depth_rest.py similarity index 100% rename from tests/integration/test_stereo_rest.py rename to tests/integration/test_stereo_depth_rest.py diff --git a/tests/unit/test_advanced_config.py b/tests/unit/test_depth_estimation_advanced_config.py similarity index 100% rename from tests/unit/test_advanced_config.py rename to tests/unit/test_depth_estimation_advanced_config.py diff --git a/tests/unit/test_lifting_defaults.py b/tests/unit/test_depth_estimation_defaults.py similarity index 100% rename from tests/unit/test_lifting_defaults.py rename to tests/unit/test_depth_estimation_defaults.py diff --git a/tests/unit/test_facade.py b/tests/unit/test_depth_estimation_facade.py similarity index 100% rename from tests/unit/test_facade.py rename to tests/unit/test_depth_estimation_facade.py diff --git a/tests/unit/test_grpc.py b/tests/unit/test_depth_estimation_grpc.py similarity index 100% rename from tests/unit/test_grpc.py rename to tests/unit/test_depth_estimation_grpc.py diff --git a/tests/unit/test_rest_api.py b/tests/unit/test_depth_estimation_stereo_depth_rest_api.py similarity index 100% rename from tests/unit/test_rest_api.py rename to tests/unit/test_depth_estimation_stereo_depth_rest_api.py diff --git a/tests/unit/test_stereo_config.py b/tests/unit/test_stereo_depth_config.py similarity index 100% rename from tests/unit/test_stereo_config.py rename to tests/unit/test_stereo_depth_config.py diff --git a/tests/unit/test_stereo_handler.py b/tests/unit/test_stereo_depth_handler.py similarity index 100% rename from tests/unit/test_stereo_handler.py rename to tests/unit/test_stereo_depth_handler.py From d9c3365fc1bf2b37831d05abfd173cb4da0bfd2a Mon Sep 17 00:00:00 2001 From: OlafenwaMoses Date: Mon, 4 May 2026 01:54:22 +0100 Subject: [PATCH 6/7] fix ci limit variable issues --- .github/workflows/ci.yml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 228ea4e..c09d23a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,11 +78,25 @@ jobs: uses: actions/cache@v4 with: path: ${{ env.VIZION3D_MODEL_CACHE }} - # Key is tied to the model filename — bump if the model changes - key: depth-anything-v2-vitb-pth + # Key is tied to the model filenames — bump if either model changes + key: depth-anything-v2-vitb-stereo-depth-s2m2-l-pth + + - name: Show integration timing limits + env: + VIZION3D_TEST_DEPTH_COLD_LIMIT: ${{ vars.VIZION3D_TEST_DEPTH_COLD_LIMIT || vars.VIZION3D_TEST_COLD_LIMIT || '10' }} + VIZION3D_TEST_DEPTH_WARM_LIMIT: ${{ vars.VIZION3D_TEST_DEPTH_WARM_LIMIT || vars.VIZION3D_TEST_WARM_LIMIT || '1' }} + VIZION3D_TEST_STEREO_COLD_LIMIT: ${{ vars.VIZION3D_TEST_STEREO_COLD_LIMIT || '60' }} + VIZION3D_TEST_STEREO_WARM_LIMIT: ${{ vars.VIZION3D_TEST_STEREO_WARM_LIMIT || '5' }} + run: | + echo "VIZION3D_TEST_DEPTH_COLD_LIMIT=$VIZION3D_TEST_DEPTH_COLD_LIMIT" + echo "VIZION3D_TEST_DEPTH_WARM_LIMIT=$VIZION3D_TEST_DEPTH_WARM_LIMIT" + echo "VIZION3D_TEST_STEREO_COLD_LIMIT=$VIZION3D_TEST_STEREO_COLD_LIMIT" + echo "VIZION3D_TEST_STEREO_WARM_LIMIT=$VIZION3D_TEST_STEREO_WARM_LIMIT" - name: Run integration tests env: - VIZION3D_TEST_COLD_LIMIT: ${{ vars.VIZION3D_TEST_COLD_LIMIT }} - VIZION3D_TEST_WARM_LIMIT: ${{ vars.VIZION3D_TEST_WARM_LIMIT }} + VIZION3D_TEST_DEPTH_COLD_LIMIT: ${{ vars.VIZION3D_TEST_DEPTH_COLD_LIMIT || vars.VIZION3D_TEST_COLD_LIMIT || '10' }} + VIZION3D_TEST_DEPTH_WARM_LIMIT: ${{ vars.VIZION3D_TEST_DEPTH_WARM_LIMIT || vars.VIZION3D_TEST_WARM_LIMIT || '1' }} + VIZION3D_TEST_STEREO_COLD_LIMIT: ${{ vars.VIZION3D_TEST_STEREO_COLD_LIMIT || '60' }} + VIZION3D_TEST_STEREO_WARM_LIMIT: ${{ vars.VIZION3D_TEST_STEREO_WARM_LIMIT || '5' }} run: uv run pytest tests/integration/ -v From 1f669e27fbdd9fa4e5bb68bd4e2e18a9a7d1216c Mon Sep 17 00:00:00 2001 From: OlafenwaMoses Date: Mon, 4 May 2026 20:24:11 +0100 Subject: [PATCH 7/7] action permissions --- .github/workflows/ci.yml | 3 +++ .github/workflows/enforce-release-branch.yml | 3 +++ .github/workflows/publish.yml | 3 +++ 3 files changed, 9 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c09d23a..ea31b29 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,9 @@ on: branches: [main] pull_request: +permissions: + contents: read + # Cancel in-progress runs for the same branch on new pushes. # Never cancel runs on main (every merge must be fully tested). concurrency: diff --git a/.github/workflows/enforce-release-branch.yml b/.github/workflows/enforce-release-branch.yml index b60d963..7f291e5 100644 --- a/.github/workflows/enforce-release-branch.yml +++ b/.github/workflows/enforce-release-branch.yml @@ -5,6 +5,9 @@ on: branches: - release +permissions: + contents: read + jobs: check-source: name: Source branch check diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0f3918c..9d40be9 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -6,6 +6,9 @@ on: workflow_dispatch: inputs: version: + +permissions: + contents: read description: "Release version (e.g. 1.2.0)" required: true type: string

J01ER00jEnQ_!%& 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 bZ=iq7|Fb|=F~^<0fZ?9`eY3_}kDmSyt+s-! literal 0 HcmV?d00001 diff --git a/tests/assets/stereo/teddy/right.png b/tests/assets/stereo/teddy/right.png new file mode 100644 index 0000000000000000000000000000000000000000..dde5d9a79a9a534e57a24da71a61c98176943ef6 GIT binary patch literal 311265 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