ashwmurt commited on
Commit
2b156ca
·
verified ·
1 Parent(s): 511dc1e

Upload depth_pro recipe (v1)

Browse files
Files changed (9) hide show
  1. LICENSE +1 -0
  2. README.md +76 -0
  3. __init__.py +10 -0
  4. app.py +127 -0
  5. demo.py +60 -0
  6. manifest.yaml +36 -0
  7. model.py +146 -0
  8. requirements.txt +1 -0
  9. test.py +44 -0
LICENSE ADDED
@@ -0,0 +1 @@
 
 
1
+ The license of the original trained model can be found at https://huggingface.co/apple/DepthPro/blob/main/LICENSE.
README.md ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ library_name: pytorch
3
+ license: other
4
+ tags:
5
+ - qai-hub-models
6
+ - qualcomm
7
+ - android
8
+ pipeline_tag: depth-estimation
9
+ ---
10
+
11
+ # DepthPro: Sharp monocular metric depth in less than a second, on-device
12
+
13
+ Apple DepthPro is a zero-shot monocular metric depth estimator that emits high-resolution, sharp depth maps from a single 1536x1536 RGB image. The architecture is a multi-scale Vision Transformer built on Dinov2 encoders with DPT-style fusion; alongside the depth map the model predicts a per-image horizontal field of view, which downstream calibration converts into a focal length in pixels. This recipe wraps Apple's HuggingFace checkpoint (`apple/DepthPro-hf`, ~952M parameters) at the model's native 1536x1536 input resolution.
14
+
15
+ This is based on the implementation of DepthPro found [here](https://github.com/apple/ml-depth-pro).
16
+ This is a standalone recipe compatible with the [Qualcomm® AI Hub Models](https://github.com/quic/ai-hub-models) CLI — it can be compiled and evaluated on real Snapdragon devices via [Qualcomm® AI Hub Workbench](https://workbench.aihub.qualcomm.com).
17
+
18
+ Qualcomm AI Hub Models uses [Qualcomm AI Hub Workbench](https://workbench.aihub.qualcomm.com) to compile, profile, and evaluate this model. [Sign up](https://myaccount.qualcomm.com/signup) to run these models on a hosted Qualcomm® device.
19
+
20
+
21
+ ## Setup
22
+ ### 1. Install the package
23
+ Install the base package, fetch this recipe from Hugging Face, then use the
24
+ `qai-hub-models` CLI to install the recipe's dependencies:
25
+ ```bash
26
+ # NOTE: 3.10 <= PYTHON_VERSION < 3.14 is supported.
27
+ pip install qai-hub-models
28
+ qai-hub-models register ashwmurt/depth_pro
29
+ qai-hub-models install depth_pro
30
+ ```
31
+ `register` downloads the recipe and names it `depth_pro`, which is how every
32
+ command below refers to it.
33
+
34
+ ### 2. Configure Qualcomm® AI Hub Workbench
35
+ Sign-in to [Qualcomm® AI Hub Workbench](https://workbench.aihub.qualcomm.com/) with your
36
+ Qualcomm® ID. Once signed in navigate to `Account -> Settings -> API Token`.
37
+
38
+ With this API token, you can configure your client to run models on the cloud
39
+ hosted devices.
40
+ ```bash
41
+ qai-hub configure --api_token API_TOKEN
42
+ ```
43
+ Navigate to [docs](https://workbench.aihub.qualcomm.com/docs/) for more information.
44
+
45
+ ## Run CLI Demo
46
+ Run the following simple CLI demo to verify the model is working end to end:
47
+
48
+ ```bash
49
+ qai-hub-models demo depth_pro
50
+ ```
51
+ More details on the CLI tool can be found with the `--help` option. See
52
+ [demo.py](demo.py) for sample usage of the model including pre/post processing
53
+ scripts.
54
+
55
+ By default, the demo will run locally in PyTorch. Pass `--eval-mode on-device` to run the model on a cloud-hosted target device.
56
+
57
+ ## Export for on-device deployment
58
+ To run the model on Qualcomm® devices, you must export the model for use with an edge runtime such as
59
+ TensorFlow Lite, ONNX Runtime, or Qualcomm AI Engine Direct.
60
+ Use the following command to export the model:
61
+ ```bash
62
+ qai-hub-models export depth_pro
63
+ ```
64
+ Additional options are documented with the `--help` option.
65
+
66
+ ## License
67
+ * The license for the original implementation of DepthPro can be found
68
+ [here](https://huggingface.co/apple/DepthPro/blob/main/LICENSE).
69
+
70
+ ## References
71
+ * [Depth Pro: Sharp Monocular Metric Depth in Less Than a Second](https://arxiv.org/abs/2410.02073)
72
+ * [Source Model Implementation](https://github.com/apple/ml-depth-pro)
73
+
74
+ ## Community
75
+ * Join [our AI Hub Slack community](https://aihub.qualcomm.com/community/slack) to collaborate, post questions and learn more about on-device AI.
76
+ * For questions or feedback please [reach out to us](mailto:ai-hub-support@qti.qualcomm.com).
__init__.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ # ---------------------------------------------------------------------
2
+ # Copyright (c) 2026 Qualcomm Technologies, Inc. and/or its subsidiaries.
3
+ # SPDX-License-Identifier: BSD-3-Clause
4
+ # ---------------------------------------------------------------------
5
+
6
+ from .app import DepthProApp as App
7
+ from .model import MODEL_ID
8
+ from .model import DepthPro as Model
9
+
10
+ __all__ = ["MODEL_ID", "App", "Model"]
app.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ---------------------------------------------------------------------
2
+ # Copyright (c) 2026 Qualcomm Technologies, Inc. and/or its subsidiaries.
3
+ # SPDX-License-Identifier: BSD-3-Clause
4
+ # ---------------------------------------------------------------------
5
+
6
+ from __future__ import annotations
7
+
8
+ from collections.abc import Callable
9
+ from dataclasses import dataclass
10
+ from typing import Any, cast
11
+
12
+ import matplotlib.pyplot as plt
13
+ import numpy as np
14
+ import numpy.typing as npt
15
+ import torch
16
+ from PIL import Image
17
+ from torchvision import transforms
18
+
19
+ from qai_hub_models.utils.image_processing import pil_resize_pad, undo_resize_pad
20
+
21
+
22
+ @dataclass
23
+ class DepthProPrediction:
24
+ """Structured output of :class:`DepthProApp`.
25
+
26
+ ``depth`` is metric depth in scene units (aligned via ``focal_length_px``);
27
+ ``heatmap`` is a plasma-colored visualization of inverse depth for display;
28
+ ``field_of_view`` is horizontal FoV in degrees; ``focal_length_px`` is
29
+ the pixel focal length derived from FoV and the original image width.
30
+ """
31
+
32
+ depth: npt.NDArray[np.float32]
33
+ heatmap: Image.Image
34
+ field_of_view: float
35
+ focal_length_px: float
36
+
37
+
38
+ class DepthProApp:
39
+ """End-to-end app for Apple DepthPro depth estimation.
40
+
41
+ Wraps a callable returning ``(predicted_depth, field_of_view)`` — either
42
+ the torch model or an on-device runner. Preprocessing resizes with
43
+ aspect-preserving padding to the network's 1536x1536 input; post-
44
+ processing mirrors HuggingFace's
45
+ ``DepthProImageProcessorFast.post_process_depth_estimation`` (metric
46
+ scaling by ``width / focal_length_px``, then inversion of the canonical
47
+ inverse depth).
48
+ """
49
+
50
+ def __init__(
51
+ self,
52
+ model: Callable[
53
+ [torch.Tensor], tuple[torch.Tensor, torch.Tensor]
54
+ ],
55
+ input_height: int | None = None,
56
+ input_width: int | None = None,
57
+ ) -> None:
58
+ self.model = model
59
+ if input_height is None or input_width is None:
60
+ get_input_spec = getattr(model, "get_input_spec", None)
61
+ if get_input_spec is None:
62
+ raise TypeError(
63
+ "DepthProApp needs input_height and input_width when the "
64
+ "provided model is not a BaseModel (has no get_input_spec)."
65
+ )
66
+ _, _, h, w = get_input_spec()["image"][0]
67
+ input_height = input_height if input_height is not None else h
68
+ input_width = input_width if input_width is not None else w
69
+ self.input_height = input_height
70
+ self.input_width = input_width
71
+
72
+ def predict(self, *args: Any, **kwargs: Any) -> DepthProPrediction:
73
+ return self.estimate_depth(*args, **kwargs)
74
+
75
+ def estimate_depth(self, image: Image.Image) -> DepthProPrediction:
76
+ """Estimate depth, FoV, and focal length for a single image.
77
+
78
+ Parameters
79
+ ----------
80
+ image
81
+ PIL image in any resolution / aspect ratio.
82
+ """
83
+ resized_image, scale, padding = pil_resize_pad(
84
+ image, (self.input_height, self.input_width)
85
+ )
86
+ image_tensor = transforms.ToTensor()(resized_image).unsqueeze(0)
87
+ predicted_depth, field_of_view = self.model(image_tensor)
88
+
89
+ # Horizontal FoV -> focal length in pixels of the *original* image.
90
+ # Matches HF's post_process_depth_estimation.
91
+ orig_width = float(image.size[0])
92
+ fov_deg = field_of_view.detach().float().view(-1)
93
+ focal_length_px = 0.5 * orig_width / torch.tan(
94
+ 0.5 * torch.deg2rad(fov_deg)
95
+ )
96
+
97
+ # Metric scaling of canonical inverse depth (again, from HF).
98
+ depth_scaled = predicted_depth * (
99
+ orig_width / focal_length_px
100
+ ).view(-1, 1, 1)
101
+
102
+ # (B, 1, H, W) shape is what undo_resize_pad expects.
103
+ depth_map = undo_resize_pad(
104
+ depth_scaled.unsqueeze(1), image.size, scale, padding
105
+ )
106
+
107
+ # Canonical inverse depth -> metric depth. Clamp mirrors HF.
108
+ depth_map = 1.0 / torch.clamp(depth_map, min=1e-4, max=1e4)
109
+
110
+ depth_np = cast(
111
+ npt.NDArray[np.float32],
112
+ depth_map.squeeze().detach().cpu().numpy().astype(np.float32),
113
+ )
114
+
115
+ # Visualize inverse depth so closer objects appear brighter, matching
116
+ # the shared depth-estimation demo convention.
117
+ inv = 1.0 / np.maximum(depth_np, 1e-6)
118
+ inv_norm = inv / max(inv.max(), 1e-6)
119
+ heatmap = plt.cm.get_cmap("plasma")(inv_norm)[..., :3]
120
+ heatmap_image = Image.fromarray((heatmap * 255).astype(np.uint8))
121
+
122
+ return DepthProPrediction(
123
+ depth=depth_np,
124
+ heatmap=heatmap_image,
125
+ field_of_view=float(fov_deg.squeeze().item()),
126
+ focal_length_px=float(focal_length_px.squeeze().item()),
127
+ )
demo.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ---------------------------------------------------------------------
2
+ # Copyright (c) 2026 Qualcomm Technologies, Inc. and/or its subsidiaries.
3
+ # SPDX-License-Identifier: BSD-3-Clause
4
+ # ---------------------------------------------------------------------
5
+
6
+ from __future__ import annotations
7
+
8
+ from qai_hub_models.utils.args import (
9
+ demo_model_from_cli_args,
10
+ get_model_cli_parser,
11
+ get_on_device_demo_parser,
12
+ validate_on_device_demo_args,
13
+ )
14
+ from qai_hub_models.utils.asset_loaders import CachedWebModelAsset, load_image
15
+ from qai_hub_models.utils.display import display_or_save_image
16
+
17
+ from .app import DepthProApp
18
+ from .model import MODEL_ID, DepthPro
19
+
20
+ # Reuse the midas depth-estimation fixture — any indoor/outdoor natural image
21
+ # works; keeping this out-of-tree avoids uploading a fresh asset just for
22
+ # the initial recipe.
23
+ INPUT_IMAGE_ADDRESS = CachedWebModelAsset.from_asset_store(
24
+ "midas", 3, "test_input_image.jpg"
25
+ )
26
+
27
+
28
+ def main(is_test: bool = False) -> None:
29
+ parser = get_model_cli_parser(DepthPro)
30
+ parser = get_on_device_demo_parser(parser, add_output_dir=True)
31
+ parser.add_argument(
32
+ "--image",
33
+ type=str,
34
+ default=INPUT_IMAGE_ADDRESS,
35
+ help="image file path or URL",
36
+ )
37
+ args = parser.parse_args([] if is_test else None)
38
+ model = demo_model_from_cli_args(DepthPro, MODEL_ID, args)
39
+ validate_on_device_demo_args(args, MODEL_ID)
40
+
41
+ (_, _, height, width) = model.get_input_spec()["image"][0]
42
+ image = load_image(args.image)
43
+ print("Model Loaded")
44
+
45
+ app = DepthProApp(model, height, width) # type: ignore[arg-type]
46
+ prediction = app.estimate_depth(image)
47
+
48
+ print(
49
+ f"Predicted field of view: {prediction.field_of_view:.2f} deg "
50
+ f"(focal length: {prediction.focal_length_px:.1f} px)"
51
+ )
52
+
53
+ if not is_test:
54
+ display_or_save_image(
55
+ prediction.heatmap, args.output_dir, "out_heatmap.png", "heatmap"
56
+ )
57
+
58
+
59
+ if __name__ == "__main__":
60
+ main()
manifest.yaml ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: DepthPro
2
+ id: depth_pro
3
+ headline: Sharp monocular metric depth in less than a second, on-device.
4
+ description: Apple DepthPro is a zero-shot monocular metric depth estimator that
5
+ emits high-resolution, sharp depth maps from a single 1536x1536 RGB image.
6
+ The architecture is a multi-scale Vision Transformer built on Dinov2 encoders
7
+ with DPT-style fusion; alongside the depth map the model predicts a per-image
8
+ horizontal field of view, which downstream calibration converts into a focal
9
+ length in pixels. This recipe wraps Apple's HuggingFace checkpoint
10
+ (`apple/DepthPro-hf`, ~952M parameters) at the model's native 1536x1536 input
11
+ resolution.
12
+ domain: Computer Vision
13
+ use_case: Depth Estimation
14
+ applicable_scenarios:
15
+ - Anomaly Detection
16
+ - Inventory Management
17
+ form_factors:
18
+ - Phone
19
+ - Tablet
20
+ - IoT
21
+ - XR
22
+ has_static_banner: false
23
+ has_animated_banner: false
24
+ has_on_target_demo: true
25
+ license_type: other-non-commercial
26
+ license: https://huggingface.co/apple/DepthPro/blob/main/LICENSE
27
+ source_repo: https://github.com/apple/ml-depth-pro
28
+ research_paper: https://arxiv.org/abs/2410.02073
29
+ research_paper_title: "Depth Pro: Sharp Monocular Metric Depth in Less Than a Second"
30
+ related_models:
31
+ - depth_anything_v2
32
+ - midas
33
+ templates:
34
+ - depth_estimation
35
+ supported_precisions:
36
+ - float
model.py ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ---------------------------------------------------------------------
2
+ # Copyright (c) 2026 Qualcomm Technologies, Inc. and/or its subsidiaries.
3
+ # SPDX-License-Identifier: BSD-3-Clause
4
+ # ---------------------------------------------------------------------
5
+
6
+ from __future__ import annotations
7
+
8
+ import torch
9
+ from transformers import DepthProForDepthEstimation
10
+ from typing_extensions import Self
11
+
12
+ from qai_hub_models.datasets.nyuv2 import NYUV2Dataset
13
+ from qai_hub_models.models._shared.depth_estimation.depth_evaluator import (
14
+ DepthEvaluator,
15
+ )
16
+ from qai_hub_models.utils.base_dataset import BaseDataset
17
+ from qai_hub_models.utils.base_evaluator import BaseEvaluator
18
+ from qai_hub_models.utils.base_model import BaseModel
19
+ from qai_hub_models.utils.input_spec import (
20
+ ColorFormat,
21
+ ImageMetadata,
22
+ InputSpec,
23
+ IoType,
24
+ OutputSpec,
25
+ TensorSpec,
26
+ )
27
+
28
+ MODEL_ID = "depth_pro"
29
+ MODEL_ASSET_VERSION = 1
30
+ DEFAULT_WEIGHTS = "apple/DepthPro-hf"
31
+ DEFAULT_INPUT_SIZE = 1536
32
+
33
+
34
+ class DepthProDepthEvaluator(DepthEvaluator):
35
+ """Adapts the shared depth δ1 evaluator to DepthPro's (depth, fov) tuple.
36
+
37
+ DepthPro's canonical inverse-depth head is what the shared evaluator
38
+ already scale/shift-aligns against NYUv2 ground truth, so the FoV output
39
+ is ignored here — focal-length calibration is only needed for absolute
40
+ metric alignment, which the δ1 metric is invariant to.
41
+ """
42
+
43
+ def add_batch(
44
+ self,
45
+ output: torch.Tensor | tuple[torch.Tensor, ...] | list[torch.Tensor],
46
+ gt: torch.Tensor,
47
+ ) -> None:
48
+ if isinstance(output, (tuple, list)):
49
+ output = output[0]
50
+ if output.dim() == 3:
51
+ # depth arrives as (B, H, W); base evaluator expects (B, 1, H, W)
52
+ output = output.unsqueeze(1)
53
+ super().add_batch(output, gt)
54
+
55
+
56
+ class DepthPro(BaseModel):
57
+ """Apple DepthPro monocular metric depth estimator, end-to-end.
58
+
59
+ Exposes two on-device outputs: canonical inverse depth at the network's
60
+ input resolution and a scalar horizontal field of view (degrees) per
61
+ image. Off-device post-processing (see ``DepthProApp``) converts these
62
+ into metric depth and a focal length in pixels, matching HuggingFace's
63
+ ``DepthProImageProcessorFast.post_process_depth_estimation``.
64
+ """
65
+
66
+ def __init__(self, model: torch.nn.Module) -> None:
67
+ super().__init__()
68
+ self.model = model.eval()
69
+
70
+ @classmethod
71
+ def from_pretrained(cls, ckpt: str = DEFAULT_WEIGHTS) -> Self:
72
+ net = DepthProForDepthEstimation.from_pretrained(ckpt)
73
+ return cls(net)
74
+
75
+ def forward(
76
+ self, image: torch.Tensor
77
+ ) -> tuple[torch.Tensor, torch.Tensor]:
78
+ """Run DepthPro on `image`.
79
+
80
+ Parameters
81
+ ----------
82
+ image
83
+ Shape ``[B, 3, 1536, 1536]`` RGB in ``[0, 1]``.
84
+
85
+ Returns
86
+ -------
87
+ predicted_depth
88
+ Shape ``[B, 1536, 1536]``. Canonical inverse depth (the raw head
89
+ output before FoV-based metric scaling and inversion).
90
+ field_of_view
91
+ Shape ``[B]``, horizontal field of view in degrees.
92
+ """
93
+ # HF's DepthProImageProcessorFast rescales to [0, 1] then normalizes
94
+ # with mean=std=0.5, i.e. (image - 0.5) / 0.5 = 2 * image - 1.
95
+ pixel_values = image * 2.0 - 1.0
96
+ predicted_depth, field_of_view = self.model(
97
+ pixel_values, return_dict=False
98
+ )
99
+ return predicted_depth, field_of_view
100
+
101
+ def get_input_spec(
102
+ self,
103
+ batch_size: int = 1,
104
+ height: int = DEFAULT_INPUT_SIZE,
105
+ width: int = DEFAULT_INPUT_SIZE,
106
+ ) -> InputSpec:
107
+ return {
108
+ "image": TensorSpec(
109
+ shape=(batch_size, 3, height, width),
110
+ dtype="float32",
111
+ io_type=IoType.IMAGE,
112
+ value_range=(0.0, 1.0),
113
+ image_metadata=ImageMetadata(color_format=ColorFormat.RGB),
114
+ apply_runtime_channel_reordering=True,
115
+ ),
116
+ }
117
+
118
+ def get_output_spec(self) -> OutputSpec:
119
+ return {
120
+ "predicted_depth": TensorSpec(
121
+ io_type=IoType.TENSOR,
122
+ description=(
123
+ "Canonical inverse depth at the network's input "
124
+ "resolution. Invert and rescale by "
125
+ "width / focal_length_px for metric depth."
126
+ ),
127
+ apply_runtime_channel_reordering=True,
128
+ ),
129
+ "field_of_view": TensorSpec(
130
+ io_type=IoType.TENSOR,
131
+ description=(
132
+ "Horizontal field of view in degrees, one scalar per "
133
+ "image; used off-device to derive focal length."
134
+ ),
135
+ ),
136
+ }
137
+
138
+ def get_evaluator(self) -> BaseEvaluator:
139
+ return DepthProDepthEvaluator()
140
+
141
+ @classmethod
142
+ def get_eval_dataset_classes(cls) -> list[type[BaseDataset]]:
143
+ return [NYUV2Dataset]
144
+
145
+ def get_calibration_dataset_cls(self) -> type[BaseDataset]:
146
+ return NYUV2Dataset
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ transformers==4.56.2
test.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ---------------------------------------------------------------------
2
+ # Copyright (c) 2026 Qualcomm Technologies, Inc. and/or its subsidiaries.
3
+ # SPDX-License-Identifier: BSD-3-Clause
4
+ # ---------------------------------------------------------------------
5
+
6
+ from __future__ import annotations
7
+
8
+ import numpy as np
9
+
10
+ from qai_hub_models.utils.asset_loaders import load_image
11
+
12
+ from .app import DepthProApp
13
+ from .demo import INPUT_IMAGE_ADDRESS
14
+ from .demo import main as demo_main
15
+ from .model import DepthPro
16
+
17
+
18
+ def test_task() -> None:
19
+ """Run torch DepthPro end-to-end on the sample fixture.
20
+
21
+ Sanity-checks that the pipeline resolves the HF weights, produces a
22
+ depth map at the network's native 1536x1536 unpadded to the original
23
+ input resolution, and yields a plausible field of view (roughly the
24
+ range Apple demos on natural imagery, 30-100 degrees).
25
+ """
26
+ model = DepthPro.from_pretrained()
27
+ (_, _, height, width) = model.get_input_spec()["image"][0]
28
+ app = DepthProApp(model, height, width)
29
+ image = load_image(INPUT_IMAGE_ADDRESS)
30
+ prediction = app.estimate_depth(image)
31
+
32
+ assert prediction.depth.ndim == 2
33
+ assert prediction.depth.shape == (image.size[1], image.size[0])
34
+ assert np.all(np.isfinite(prediction.depth))
35
+ assert prediction.depth.min() > 0
36
+
37
+ assert 10.0 < prediction.field_of_view < 170.0
38
+ assert prediction.focal_length_px > 0
39
+
40
+ assert prediction.heatmap.size == image.size
41
+
42
+
43
+ def test_demo() -> None:
44
+ demo_main(is_test=True)