GeoCalib field net, ONNX export
The convolutional half of GeoCalib (Veicht et al., ECCV 2024, ETH CVG) as a single self-contained ONNX file: image in, four dense perspective fields out. Pair it with a small Levenberg-Marquardt solver on those fields to estimate roll, pitch, and gravity direction from a single image with no torch dependency.
Exported for Caliscope's board-free vertical estimation.
What it is
GeoCalib runs in two stages: a network predicts, per pixel, the projected world-up direction (up_field), the latitude of the viewing ray (latitude_field), and a confidence for each; a Levenberg-Marquardt optimizer then fits camera tilt (and optionally focal) to those fields. This export is the network stage only, from the official pinhole weights. The solver stage is ~300 lines of numpy, shipped with the consumer (Caliscope).
Contract
- Input
image:(1, 3, H, W)float32 RGB in[0, 1]. H and W are dynamic but must be multiples of 32. GeoCalib's preprocessing resizes the short side to 320 with bilinear+antialias and rounds edges to multiples of 32; match it for best results. - Outputs:
up_field(1, 2, H, W),up_confidence(1, H, W),latitude_field(1, 1, H, W)(radians),latitude_confidence(1, H, W). - One graph serves all resolutions and orientations (exported with torch.onnx dynamo, dynamic shapes).
- fp32, 118 MB, weights embedded — no external data file.
Differences from upstream
Upstream GeoCalib is stochastic at inference: its Hamburger/NMF decoder draws random bases on every forward, so identical inputs give slightly different fields run to run (~0.005–0.2° gravity wobble downstream). This export freezes one seeded basis (seed 0) as a graph constant, making it deterministic. Field parity against frozen-basis torch is ~1e-6; gravity parity through the same solver is ~1e-5 degrees — four orders of magnitude below upstream's own run-to-run noise.
Provenance
- Upstream weights:
geocalib-pinholev1.0 release, cvg/GeoCalib at commit747054d. - Export procedure: wrap the model's backbone, low-level encoder, and perspective decoder in a module returning the four fields; replace each NMF2D
_build_baseswith a constant seeded basis (torch.Generator().manual_seed(0), normalized); export withtorch.onnx.export(dynamo=True), dynamic height/width,external_data=False. Validated against torch on real frames before publishing. - SHA-256:
a724447e1bf7138352e5e70bbe0f011e6fb02909edd3148a5d0f46e8d153ae7b
License and attribution
Apache 2.0, as a derivative of GeoCalib (© ETH Zurich, Computer Vision and Geometry Group). If you use this model, cite the original work:
@inproceedings{veicht2024geocalib,
author = {Alexander Veicht and Paul-Edouard Sarlin and Philipp Lindenberger and Marc Pollefeys},
title = {{GeoCalib: Single-image Calibration with Geometric Optimization}},
booktitle = {ECCV},
year = {2024}
}