[Paper] [arXiv] [Project Page] [Weights] [Demo] [BibTeX]
![]() |
- 2026-09-25: Accepted to NeurIPS 2026.
- 2026-08-21: Evaluation code released.
- 2026-06-01: arXiv v1, inference code, weights, and demo released.
Clone the repository:
git clone https://github.com/karimknaebel/surge
cd surgeThen install SurGe with the Inference CLI, Gradio app, and evaluation dependencies:
uv sync --all-extrasThis creates a virtual environment in .venv/.
Run commands with uv run (e.g., uv run surge-infer ...), or just activate it as usual with source .venv/bin/activate.
Alternatively, with pip: pip install -e ".[cli,app,eval]"
Use SurGe in an existing project:
uv add git+https://github.com/karimknaebel/surgeAlternatively, with pip: pip install git+https://github.com/karimknaebel/surge
SurGe expects image tensors in BCHW format with unnormalized RGB values in [0, 1].
Do not apply ImageNet normalization or similar preprocessing.
import torch
from surge import SurGe
model = SurGe.from_pretrained("karimknaebel/surge-large").eval().cuda()
image = torch.rand(1, 3, 518, 518, device="cuda")
with torch.autocast("cuda", dtype=torch.float16):
result = model.infer(image)
points = result["points"] # (B, H, W, 3)
depth = result["depth"] # (B, H, W)
intrinsics = result["intrinsics"] # (B, 3, 3)Run inference on an image or a directory of images:
uv run surge-infer path/to/image.jpg --output-dir output
By default, the Inference CLI writes mesh.glb for each input image.
Add output flags as needed:
uv run surge-infer path/to/images --save-maps --save-glb --save-ply
Useful options include --max-size 1200, --tokens max, --fov-x 60, --fp16, and --filter-sky.
For interactive viewing, use --show-mesh to open the reconstructed mesh with trimesh, or --rerun to log the inference results to a Rerun viewer.
Launch the local demo app:
uv run surge-app
The app lets you upload an image, adjust the token budget and mesh cleanup settings, view the reconstructed mesh, and download the generated maps and geometry.
Download MoGe's processed evaluation datasets from Hugging Face and extract them under data/eval:
mkdir -p data/eval
uv run hf download Ruicheng/monocular-geometry-evaluation \
--repo-type dataset \
--local-dir data/eval
cd data/eval
unzip '*.zip'
cd ../..Run the full suite:
uv run surge-eval --output eval_output/surge.jsonWe include official surge-large results for reference.
Coordinate frames:
point_map.exrandpoint_normal_map.png: RDF (OpenCV);+Xright,+Ydown,+Zforward.mesh.glbandpoint_cloud.ply: RUB;+Xright,+Yup,+Zbackward.
File formats:
depth_colorized.png: colorized depth visualization.point_map.exr: float32 XYZ points. Masked pixels areNaN.point_normal_map.png: unit normals. RGB stores[X, -Y, -Z]mapped from[-1, 1]to[0, 255]; invalid pixels are[127, 127, 127]. Renormalize after decoding if needed.intrinsics.json: camera intrinsics as a 3×3 JSON array.fov.json: horizontal and vertical fields of view in degrees.
The NAD is implemented as a reusable PyTorch module. It is intentionally self-contained, so you can copy it into your project as a single file without pulling in the rest of SurGe.
The self-contained point gradient matching loss used to train SurGe is included for reference.
The normal mean angular error metric used to evaluate surface normals is included in the evaluation code.
The SurGe code is released under the MIT license. The SurGe weights are released under CC BY-NC 4.0, due to the training datasets used.
We thank the MoGe project for their open-source code.
If you use our work in your research, please use the following BibTeX entry.
@inproceedings{knaebel2026surge,
title = {{SurGe}: Improved Surface Geometry in Point Maps},
author = {Knaebel, Karim and Martin Garcia, Gonzalo and Schmidt, Christian and Fradlin, Ilya and Nunes, Lucas and de Geus, Daan and Leibe, Bastian},
year = 2026,
booktitle = {Advances in Neural Information Processing Systems},
}