vulus98 commited on
Commit
148a7f9
Β·
verified Β·
1 Parent(s): 38de25f

Add arXiv link and BibTeX citation

Browse files
Files changed (1) hide show
  1. README.md +61 -23
README.md CHANGED
@@ -21,7 +21,7 @@ pipeline_tag: depth-estimation
21
  <a title="Website" href="https://prs-eth.github.io/PaGeR/" target="_blank" rel="noopener noreferrer" style="display: inline-block;">
22
  <img src="https://img.shields.io/badge/%E2%99%A5%20Project%20-Website-blue" alt="Website">
23
  </a>
24
- <a title="arXiv" href="https://arxiv.org/abs/TBD" target="_blank" rel="noopener noreferrer" style="display: inline-block;">
25
  <img src="https://img.shields.io/badge/%F0%9F%93%84%20Read%20-Paper-AF3436" alt="arXiv">
26
  </a>
27
  <a title="Hugging Face" href="https://huggingface.co/spaces/prs-eth/PaGeR" target="_blank" rel="noopener noreferrer" style="display: inline-block;">
@@ -41,40 +41,52 @@ pipeline_tag: depth-estimation
41
  </a>
42
  </p>
43
 
44
- `PaGeR` is the **unified** geometry-estimation checkpoint released with our paper *Unified Panoramic Geometry Estimation via Multi-View Foundation Models* β€” [arXiv (TBD)](https://arxiv.org/abs/TBD).
 
 
45
 
46
  From a single equirectangular (ERP) panorama, one forward pass returns:
47
 
48
- - **Scale-invariant (SI) depth** at full panoramic resolution, from the dense depth head.
49
- - **Metric depth** in metres, computed as `SI_depth Γ— exp(log_scale)` with a single global `log_scale` from a parallel coarse-scale head. Two scale heads ship (indoor / outdoor); exactly one runs per panorama, picked manually (`--scene_mode indoor|outdoor`) or auto-routed by a zero-shot [CLIP ViT-B/32](https://github.com/openai/CLIP) classifier (via [`open_clip`](https://github.com/mlfoundations/open_clip)) that scores the 4 equatorial cubemap faces against "indoor scene" / "outdoor scene" prompts.
50
- - **Surface normals** as unit vectors in the panorama's world frame.
51
- - **Sky mask** for filling unbounded regions in the depth and normal outputs.
 
 
 
 
52
 
53
- If you only need metric depth in a single direct head (no scale routing), use [`prs-eth/PaGeR-metric-depth`](https://huggingface.co/prs-eth/PaGeR-metric-depth). Browse the full [PaGeR HF collection](https://huggingface.co/collections/prs-eth/pager) or try the [interactive demo](https://huggingface.co/spaces/prs-eth/PaGeR).
54
 
55
  ## Model Details
56
 
57
  - **Developed by:** [Vukasin Bozic](https://vulus98.github.io/), [Isidora Slavkovic](https://linkedin.com/in/isidora-slavkovic), [Dominik Narnhofer](https://scholar.google.com/citations?user=tFx8AhkAAAAJ&hl=en), [Nando Metzger](https://nandometzger.github.io/), [Denis Rozumny](https://rozumden.github.io/), [Konrad Schindler](https://scholar.google.com/citations?user=FZuNgqIAAAAJ), [Nikolai Kalischek](https://scholar.google.com/citations?user=XwzlnZoAAAAJ&hl=de).
58
- - **Model type:** Feed-forward, multi-view foundation-model adaptation for single-image panoramic geometry (depth + normals + sky + metric scale).
59
- - **Backbone:** [Depth Anything 3](https://github.com/ByteDance-Seed/Depth-Anything-3) (`da3-giant`, ViT-Giant), repurposed for cubemap-based multi-view processing.
60
- - **I/O:** ERP panorama in (up to 3K) β†’ 6-face cubemap at 504 px/face β†’ ERP outputs (SI depth, metric depth, normals, sky mask).
61
- - **Routing note:** The paper's per-domain numbers were produced with the scale head selected manually per dataset; the CLIP router is an inference-time convenience (demo / CLI), lives outside the checkpoint, and can be overridden via `--scene_mode {auto,indoor,outdoor}`.
62
- - **License:** [CC BY-NC 4.0](LICENSE) β€” academic / non-commercial only, inherited from the `da3-giant` backbone (CC BY-NC 4.0). The runtime CLIP ViT-B/32 weights are MIT-licensed and travel separately. Commercial use is not permitted.
 
 
 
 
 
 
 
 
63
  ### Other released checkpoints
64
 
65
- | Checkpoint | SI depth | Metric depth | Normals | Sky |
66
  |---|---|---|---|---|
67
- | **PaGeR** *(this card, recommended)* β€” [`prs-eth/PaGeR`](https://huggingface.co/prs-eth/PaGeR) | βœ… | βœ… (SI Γ— CLIP-routed indoor / outdoor scale head) | βœ… | βœ… |
68
- | PaGeR-Metric-Depth β€” [`prs-eth/PaGeR-metric-depth`](https://huggingface.co/prs-eth/PaGeR-metric-depth) | β€” | βœ… (single direct head) | β€” | β€” |
69
- | PaGeR-Normals β€” [`prs-eth/PaGeR-normals`](https://huggingface.co/prs-eth/PaGeR-normals) | β€” | β€” | βœ… | β€” |
70
 
71
  ## Usage
72
 
73
- A minimal Python snippet that runs the unified model on a single panorama:
74
 
75
  ```python
76
- from pathlib import Path
77
-
78
  import matplotlib.pyplot as plt
79
  import numpy as np
80
  import torch
@@ -89,6 +101,7 @@ from src.utils.utils import prepare_depth_for_logging, prepare_normals_for_loggi
89
  checkpoint = "prs-eth/PaGeR" # or a local directory
90
  device = torch.device("cuda")
91
 
 
92
  config_path = hf_hub_download(repo_id=checkpoint, filename="config.yaml")
93
  cfg = OmegaConf.load(config_path)
94
 
@@ -96,23 +109,48 @@ pager = Pager(checkpoint, cfg=cfg, device=device)
96
  pager.get_intrinsics_extrinsics(image_size=cfg.face_size, fov=getattr(cfg, "cube_fov", 90.0))
97
  pager.model.to(device).eval()
98
 
99
- panorama = np.array(Image.open("examples/example_1.jpg").convert("RGB")) / 255.0
 
100
  panorama = torch.from_numpy(panorama).permute(2, 0, 1).float() * 2 - 1
101
  rgb_cubemap = erp_to_cubemap(panorama, face_w=cfg.face_size,
102
  fov=getattr(cfg, "cube_fov", 90.0)).unsqueeze(0).to(device)
103
 
 
 
 
 
 
104
  with torch.inference_mode():
105
  pred = pager(rgb_cubemap, dtype=torch.float16, skip_heads={"scale_indoor"})
106
 
 
 
 
 
107
  cmap = plt.get_cmap("Spectral")
108
  H, W = panorama.shape[-2:]
109
- depth_metric, _ = prepare_depth_for_logging(
110
  pager, pred["depth"][0], pred["sky"][0], (H, W), cmap,
111
  log_scale=pred["scale"],
112
  )
113
- normals, _ = prepare_normals_for_logging(
114
  pager, pred["normals"][0], pred["sky"][0], (H, W),
115
  )
116
  ```
117
 
118
- `depth_metric` is a `(1, H, W)` float32 array of metric depth (metres); `normals` is a `(3, H, W)` unit-normal field. Both already have the predicted sky region filled in. See the [GitHub repository](https://github.com/prs-eth/PaGeR) for the full CLI (`inference.py`), evaluation scripts, the Gradio demo (`app.py`), and the point-cloud exporter.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  <a title="Website" href="https://prs-eth.github.io/PaGeR/" target="_blank" rel="noopener noreferrer" style="display: inline-block;">
22
  <img src="https://img.shields.io/badge/%E2%99%A5%20Project%20-Website-blue" alt="Website">
23
  </a>
24
+ <a title="arXiv" href="https://arxiv.org/abs/2605.26368" target="_blank" rel="noopener noreferrer" style="display: inline-block;">
25
  <img src="https://img.shields.io/badge/%F0%9F%93%84%20Read%20-Paper-AF3436" alt="arXiv">
26
  </a>
27
  <a title="Hugging Face" href="https://huggingface.co/spaces/prs-eth/PaGeR" target="_blank" rel="noopener noreferrer" style="display: inline-block;">
 
41
  </a>
42
  </p>
43
 
44
+ `PaGeR` is the **unified** geometry-estimation checkpoint released with our paper:
45
+
46
+ - **Paper:** *Unified Panoramic Geometry Estimation via Multi-View Foundation Models* β€” [arXiv:2605.26368](https://arxiv.org/abs/2605.26368)
47
 
48
  From a single equirectangular (ERP) panorama, one forward pass returns:
49
 
50
+ - **Scale-invariant (SI) depth** at full panoramic resolution, predicted by the dense depth head.
51
+ - **Metric depth** in metres, obtained by multiplying the SI depth with a single global log-scale predicted by a parallel coarse metric-scale head. Two such scale heads are trained β€” one for indoor, one for outdoor scenes β€” and exactly one runs per panorama (see routing below).
52
+ - **Surface normals** as unit vectors in the panorama's world frame,
53
+ - **Sky segmentation** for masking unbounded depth regions.
54
+
55
+ So the unified PaGeR checkpoint emits *both* the SI depth map and the metric depth map in one shot: the dense head fixes geometry, the scale head fixes absolute scale. If you only need metric depth and don't want to manage the indoor/outdoor scale routing, the depth-only [`prs-eth/PaGeR-metric-depth`](https://huggingface.co/prs-eth/PaGeR-metric-depth) checkpoint predicts metric depth directly in a single head.
56
+
57
+ Indoor and outdoor scenes are served by twin scale heads, so a single checkpoint covers both regimes. The active head can be selected manually or routed automatically β€” see [Model Details](#model-details) below for how that routing is done at inference time.
58
 
59
+ You can also browse the rest of our [PaGeR HF collection](https://huggingface.co/collections/prs-eth/pager) or try the [interactive demo](https://huggingface.co/spaces/prs-eth/PaGeR).
60
 
61
  ## Model Details
62
 
63
  - **Developed by:** [Vukasin Bozic](https://vulus98.github.io/), [Isidora Slavkovic](https://linkedin.com/in/isidora-slavkovic), [Dominik Narnhofer](https://scholar.google.com/citations?user=tFx8AhkAAAAJ&hl=en), [Nando Metzger](https://nandometzger.github.io/), [Denis Rozumny](https://rozumden.github.io/), [Konrad Schindler](https://scholar.google.com/citations?user=FZuNgqIAAAAJ), [Nikolai Kalischek](https://scholar.google.com/citations?user=XwzlnZoAAAAJ&hl=de).
64
+ - **Model type:** Feed-forward, multi-view foundation-model adaptation for single-image panoramic geometry estimation (depth + normals + sky + metric scale).
65
+ - **Backbone:** [Depth Anything 3](https://github.com/ByteDance-Seed/Depth-Anything-3) (`da3-giant`, ViT-Giant), repurposed for cubemap-based multi-view processing of the panorama.
66
+ - **Inputs:** A single ERP panorama, internally projected onto a 6-face cubemap at 504 px per face.
67
+ - **Outputs (in one forward pass):**
68
+ - **Scale-invariant (SI) depth map** at panoramic resolution, from the dense depth head.
69
+ - **Metric depth** (metres), computed as `SI_depth * exp(log_scale)` where `log_scale` is the single global log-scale predicted by the active (indoor or outdoor) coarse metric-scale head. Both the SI and metric maps share the same dense geometry; the scale head only injects absolute scale.
70
+ - **Surface normals** as unit vectors in the panorama's world frame.
71
+ - **Sky mask** for filling/masking unbounded regions in the depth and normal outputs.
72
+ - **Indoor / outdoor routing (inference-time add-on, not part of the paper):** The paper's per-domain numbers were produced with the indoor or outdoor scale head selected manually per dataset. For convenience in the released demo and CLI, a small zero-shot [CLIP ViT-B/32](https://github.com/openai/CLIP) classifier (loaded via [`open_clip`](https://github.com/mlfoundations/open_clip)) can auto-pick between the twin scale heads at inference time, by scoring the 4 equatorial cubemap faces against two text-prompt centroids ("indoor scene" vs. "outdoor scene"). The router lives outside the checkpoint and can be overridden by the user (`--scene_mode {auto,indoor,outdoor}`).
73
+ - **Resolution:** Designed for high-resolution ERP inputs, up to 3K.
74
+ - **License:** [CC BY-NC 4.0](LICENSE) β€” academic / non-commercial use only. The released weights are derivative works of the [Depth Anything 3](https://github.com/ByteDance-Seed/Depth-Anything-3) `da3-giant` backbone, released by ByteDance under CC BY-NC 4.0, and inherit that restriction. The CLIP ViT-B/32 weights used for the indoor/outdoor router are loaded from [`open_clip`](https://github.com/mlfoundations/open_clip) at runtime; they are MIT-licensed and travel separately, so they do not propagate any additional restriction. Commercial use is not permitted.
75
+ - **Resources for more information:** [Project Website](https://prs-eth.github.io/PaGeR/), [Paper](https://arxiv.org/abs/2605.26368), [Code](https://github.com/prs-eth/PaGeR).
76
+
77
  ### Other released checkpoints
78
 
79
+ | Checkpoint | Hugging Face id | Depth | Normals | Sky |
80
  |---|---|---|---|---|
81
+ | **PaGeR** *(this card, recommended)* | [`prs-eth/PaGeR`](https://huggingface.co/prs-eth/PaGeR) | βœ… | βœ… | βœ… |
82
+ | PaGeR-Metric-Depth | [`prs-eth/PaGeR-metric-depth`](https://huggingface.co/prs-eth/PaGeR-metric-depth) | βœ… (metric) | | |
83
+ | PaGeR-Normals | [`prs-eth/PaGeR-normals`](https://huggingface.co/prs-eth/PaGeR-normals) | | βœ… | |
84
 
85
  ## Usage
86
 
87
+ A minimal Python snippet that runs the unified model on a single panorama and produces metric depth, surface normals, and a sky mask in one forward pass. The snippet assumes you have [cloned the repository](https://github.com/prs-eth/PaGeR) and `pip install -e .` ed it, so that `src.pager` is importable; checkpoint weights and config are streamed from the Hub on first use.
88
 
89
  ```python
 
 
90
  import matplotlib.pyplot as plt
91
  import numpy as np
92
  import torch
 
101
  checkpoint = "prs-eth/PaGeR" # or a local directory
102
  device = torch.device("cuda")
103
 
104
+ # 1. Load the model config from the Hub and instantiate Pager.
105
  config_path = hf_hub_download(repo_id=checkpoint, filename="config.yaml")
106
  cfg = OmegaConf.load(config_path)
107
 
 
109
  pager.get_intrinsics_extrinsics(image_size=cfg.face_size, fov=getattr(cfg, "cube_fov", 90.0))
110
  pager.model.to(device).eval()
111
 
112
+ # 2. Load a panorama and project it to the 6-face cubemap PaGeR consumes.
113
+ panorama = np.array(Image.open("assets/examples/apartment_synth.jpg").convert("RGB")) / 255.0
114
  panorama = torch.from_numpy(panorama).permute(2, 0, 1).float() * 2 - 1
115
  rgb_cubemap = erp_to_cubemap(panorama, face_w=cfg.face_size,
116
  fov=getattr(cfg, "cube_fov", 90.0)).unsqueeze(0).to(device)
117
 
118
+ # 3. Run one forward pass. The unified checkpoint carries both indoor and
119
+ # outdoor scale heads; pass ``skip_heads`` to keep exactly one of them
120
+ # (here: force the outdoor head by skipping ``scale_indoor``). The full
121
+ # CLI in ``inference.py`` instead routes each panorama automatically via
122
+ # a small CLIP ViT-B/32 classifier on the cubemap faces.
123
  with torch.inference_mode():
124
  pred = pager(rgb_cubemap, dtype=torch.float16, skip_heads={"scale_indoor"})
125
 
126
+ # 4. Convert raw head outputs into ERP-resolution arrays:
127
+ # - depth: SI depth Γ— exp(log_scale) β†’ metric depth (metres), with the
128
+ # predicted sky region filled to ``MAX_DEPTH`` via a soft alpha blend.
129
+ # - normals: unit vectors in the panorama's world frame, sky-filled.
130
  cmap = plt.get_cmap("Spectral")
131
  H, W = panorama.shape[-2:]
132
+ depth_metric, depth_viz = prepare_depth_for_logging(
133
  pager, pred["depth"][0], pred["sky"][0], (H, W), cmap,
134
  log_scale=pred["scale"],
135
  )
136
+ normals, normals_viz = prepare_normals_for_logging(
137
  pager, pred["normals"][0], pred["sky"][0], (H, W),
138
  )
139
  ```
140
 
141
+ `depth_metric` is a `(1, H, W)` float32 array of metric depth (metres); `normals` is a `(3, H, W)` unit-normal field. Both already have the predicted sky region filled in. The `*_viz` companions are uint8 RGB previews (Spectral-coloured for depth, per-sample rescaled for normals). See the [GitHub repository](https://github.com/prs-eth/PaGeR) for the full CLI (`inference.py`), evaluation scripts, the Gradio demo (`app.py`), and the point-cloud exporter.
142
+
143
+ ## Citation
144
+
145
+ If you use this checkpoint in your work, please cite:
146
+
147
+ ```bibtex
148
+ @article{bozic2026pager,
149
+ title = {Unified Panoramic Geometry Estimation via Multi-View Foundation Models},
150
+ author = {Bozic, Vukasin and Slavkovic, Isidora and Narnhofer, Dominik and
151
+ Metzger, Nando and Rozumny, Denis and Schindler, Konrad and
152
+ Kalischek, Nikolai},
153
+ journal = {arXiv preprint arXiv:2605.26368},
154
+ year = {2026}
155
+ }
156
+ ```