Views
No views yet
PaGeR-Normals is the normals-only variant of PaGeR released with the paper:prs-eth/PaGeR checkpoint instead.da3-giant, ViT-Giant), repurposed for cubemap-based multi-view processing of the panorama.da3-giant backbone, released by ByteDance under CC BY-NC 4.0, and inherit that restriction. Commercial use is not permitted.| Checkpoint | Hugging Face id | Depth | Normals | Sky |
|---|---|---|---|---|
| PaGeR (unified, recommended) | prs-eth/PaGeR | ✅ | ✅ | ✅ |
| PaGeR-Metric-Depth | prs-eth/PaGeR-metric-depth | ✅ (metric) | ||
| PaGeR-Normals (this card) | prs-eth/PaGeR-normals | ✅ |
pip install -e . ed it, so that src.pager is importable; checkpoint weights and config are streamed from the Hub on first use.1import numpy as np
2import torch
3from huggingface_hub import hf_hub_download
4from omegaconf import OmegaConf
5from PIL import Image
6
7from src.pager import Pager
8from src.utils.geometry_utils import erp_to_cubemap
9from src.utils.utils import prepare_normals_for_logging
10
11checkpoint = "prs-eth/PaGeR-normals"
12device = torch.device("cuda")
13
14# 1. Load the model config from the Hub and instantiate Pager.
15config_path = hf_hub_download(repo_id=checkpoint, filename="config.yaml")
16cfg = OmegaConf.load(config_path)
17
18pager = Pager(checkpoint, cfg=cfg, device=device)
19pager.get_intrinsics_extrinsics(image_size=cfg.face_size, fov=getattr(cfg, "cube_fov", 90.0))
20pager.model.to(device).eval()
21
22# 2. Load a panorama and project it to the 6-face cubemap PaGeR consumes.
23panorama = np.array(Image.open("assets/examples/apartment_synth.jpg").convert("RGB")) / 255.0
24panorama = torch.from_numpy(panorama).permute(2, 0, 1).float() * 2 - 1
25rgb_cubemap = erp_to_cubemap(panorama, face_w=cfg.face_size,
26 fov=getattr(cfg, "cube_fov", 90.0)).unsqueeze(0).to(device)
27
28# 3. Run one forward pass. The normals head is the only head in this
29# checkpoint — no depth, sky, or scale outputs.
30with torch.inference_mode():
31 pred = pager(rgb_cubemap, dtype=torch.float16)
32
33# 4. Convert the raw normals output into an ERP-resolution unit-normal map.
34# ``sky_mask=None`` because this checkpoint has no sky head, so unbounded
35# regions are left as predicted instead of being masked out.
36H, W = panorama.shape[-2:]
37normals, normals_viz = prepare_normals_for_logging(
38 pager, pred["normals"][0], None, (H, W),
39)normals is a (3, H, W) float32 unit-normal field in the panorama's world frame at the input panorama resolution; normals_viz is the uint8 RGB preview (per-sample rescaled). If you also need sky filling, depth, or metric scale from the same model, use the unified prs-eth/PaGeR checkpoint instead. See the GitHub repository for the full CLI (inference.py), evaluation scripts, the Gradio demo (app.py), and the point-cloud exporter.1@article{bozic2026pager,
2 title = {Unified Panoramic Geometry Estimation via Multi-View Foundation Models},
3 author = {Bozic, Vukasin and Slavkovic, Isidora and Narnhofer, Dominik and
4 Metzger, Nando and Rozumny, Denis and Schindler, Konrad and
5 Kalischek, Nikolai},
6 journal = {arXiv preprint arXiv:2605.26368},
7 year = {2026}
8}