Surflo: Consistent 3D Surface Flow Model with Global State

Surflo turns a handful of unposed RGB views into a detailed 3D surface. It encodes a variable number of input views (2 to ~80) into a fixed-size latent and decodes that latent by flow matching into an arbitrary number of oriented surface points, which are then turned into a clean mesh.

Model description

Surflo v0 Release
Task Feed-forward surface reconstruction from unposed multi-view images
Input 2–80 RGB images of one static scene, no poses, no intrinsics
Output Oriented 3D point cloud (position + normal) at arbitrary resolution, plus an optional mesh
Total parameters 1.39 B
Trainable parameters 128.8 M
Frozen backbone 1.257 B (VGGT-1B)
Precision fp32 weights; inference runs under bf16 autocast for the backbone

Architecture

  1. Encode — a frozen VGGT-1B backbone maps the N unposed views to per-layer aggregated tokens (layers 4/11/17/23) plus camera tokens.
  2. Compress — a Perceiver-style cross-attention compressor reduces the variable-length token set to a fixed 128 latent tokens × 512 dims. Camera tokens are compressed separately and injected as AdaLN conditioning.
  3. Decode — a 12-layer, 512-dim field decoder defines a velocity field over a 6-D space (3-D position + 3-D normal). Points sampled from a source distribution are integrated along this field with a conditional-OT flow-matching scheduler, yielding oriented surface points. Because the latent is fixed-size, you can decode any number of points from one encode.
  4. Meshify (optional) — a wrapping-based extractor turns the points into a mesh; an optional rendering-guidance stage refines geometry with Gaussian-splatting gradients before extraction.

The size of the latent does not depend on the number of input views, which is what lets one encode serve arbitrarily many decoded points.

Usage

Surflo needs the code repository — it is a source install with compiled CUDA extensions, not a pip install package. See the repository README for installation.

from surflo import Surflo, load_preset, save_ply, save_mesh

surflo = Surflo.from_checkpoint("checkpoint_200.pt", device="cuda")

# Encode any number of unposed images into the fixed-size global state.
scene = surflo.encode("/path/to/images", n_images=16)
print(scene.global_state.shape)          # (128, 512) latent tokens

# Decode oriented surface points.
result = scene.reconstruct(
    mode="guided",                                   # or "plain"
    config_block=load_preset("guided", "default"),
    expert_cfg=load_preset("expert"),
    num_query_points=100_000,
)
save_ply(result, "point_cloud.ply")

# Optional mesh.
mesh = scene.extract_mesh(result, mesh_cfg=load_preset("mesh"))
scene.color_mesh(mesh, result)
save_mesh(mesh, "mesh.ply")

Or from the command line:

python scripts/infer.py mode=guided guided=default \
    ckpt=/path/to/checkpoint_200.pt \
    source.image_folder=/path/to/images \
    num_query_points=100000 \
    output_dir=outputs/surflo

Inference modes

Mode What it does Cost (H100, 16 views, 100 k points)
plain Pure flow-matching ODE. Deterministic, no rendering. ~8 s, ~8.5 GiB
guided=minimal Adds rendering guidance, shortest schedule ~16 s, ~14 GiB
guided=default Recommended quality/time trade-off ~47 s, ~14 GiB
guided=long Longest schedule; does not improve on default ~95 s, ~14 GiB

Training

  • Data: Our modified DL3DV,
  • preprocessed into cached VGGT tokens plus ground-truth surface points and normals. Preprocessing script is shipped with the code.
  • Regime: variable view count N ∈ [2, 16] drawn per iteration (curriculum), 4×H100, bf16 AMP, AdamW with fvcore schedulers, EMA (β = 0.9999). The reported checkpoint is epoch 200.
  • Objective: L2 flow-matching loss on the predicted velocity.
  • Frozen: the VGGT-1B backbone is frozen (requires_grad = False) throughout; only surface_net (compressor + decoder + learned tokens) is trained.

Training the variable-view schedule is what makes the model robust across a wide range of input view counts at inference.

License

⚠️ This checkpoint cannot be released under MIT. Part of its parameters are the VGGT-1B backbone, distributed by Meta under CC BY-NC 4.0, and those weights are stored verbatim in the checkpoint. Redistributing them under a permissive license is not available to us. The checkpoint is therefore released under CC BY-NC 4.0 — non-commercial use only.

The Surflo code is released under the Gaussian-Splatting License (Inria/MPII), which likewise restricts use to non-commercial research and evaluation, because Surflo contains modified 3D Gaussian Splatting code.

If you want a permissively licensed artifact, publish the trained head alone: surface_net is 128.8 M parameters (~9 % of the checkpoint) and is entirely our own work, so it can be MIT. Users would then obtain VGGT-1B themselves from the Hub. Note two caveats: the system still depends on CC BY-NC weights at run time, so an MIT tag on the head alone does not make commercial use possible; and the current loader calls load_state_dict(..., strict=True), so it would need to accept a partial state dict before a head-only checkpoint could be loaded.

Citation

@article{guedon2026surflo,
  title   = {Surflo: Consistent 3D Surface Flow Model with Global State},
  author  = {Gu{\'e}don, Antoine and Nakamura, Shu and Dufour, Nicolas
             and Lei, Jiahui and Nishino, Ko and Kanazawa, Angjoo},
  journal = {arXiv preprint arXiv:2606.13644},
  year    = {2026}
}

Acknowledgements

Surflo builds on VGGT (Meta), 3D Gaussian Splatting (Inria/MPII), and Depth-Anything-3 (ByteDance) for the optional monodepth expert. See THIRD_PARTY_NOTICES.md in the code repository for the full inventory.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Paper for AntoineGuedon/Surflo-v0