# GTSfM turns structure from motion into a browser workspace with Dask inside

> GTSfM is Georgia Tech's end-to-end structure from motion pipeline built on GTSAM and designed from the ground up around Dask for parallel computation, now shipping a browser workspace, a reconstruction model and a choice of Gaussian splat backends. It suits research and engineering teams who want a single pipeline rather than a set of stitched scripts.

**borglab/gtsfm** — End-to-end SFM framework based on GTSAM

- Repository: https://github.com/borglab/gtsfm
- Stars: 526 · Forks: 64
- Language: Jupyter Notebook
- License: NOASSERTION
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/borglab-gtsfm

## What GTSfM is and who the pipeline is for

Georgia Tech Structure from Motion is an end-to-end SfM pipeline based on GTSAM, and the project says it was designed from the ground up to natively support parallel computation using Dask. The arXiv preprint is linked for more detail, and the repository carries the paper/ directory alongside the code, which tells you this is research software released with the publication rather than a packaged product.

Structure from motion is the problem of recovering camera poses and 3D geometry from a set of photographs. It is the first stage of most visual reconstruction work, and the reason end-to-end matters is that the stages feed each other. Feature matching produces tracks, tracks produce camera poses, poses and the tracks together produce a point cloud. Do it badly at one stage and the errors propagate. A pipeline that carries all of it end to end lets the stages share state, which is what lets Dask parallelise across them rather than parallelising one stage at a time.

The topic list names 3d-reconstruction, multiview-geometry and structure-from-motion, and the build badge shows Ubuntu 20.04.3 on the Linux CI, so the supported target is a Linux workstation. The audience is research and engineering teams working on reconstruction, and the two things that make this project distinct from a typical open source SfM release are the Dask-native parallelism and the browser workspace described below.

The repository is not archived and the last push was on 2026-10-20, so the work is current. There are no GitHub releases, which is worth noting because the version lives in the packaging metadata instead, and the version there is 0.2.0.

## The browser workspace and the terminal path

The most visible change in the project is GTSFM Studio, an application-style command that opens a browser workspace. From a recursive checkout or a published wheel, one install is enough:

```bash
uv tool install .
gtsfm run
```

The browser opens automatically and gives you controls for dataset, model, splat implementation, hardware and advanced configuration. Input comes from dragging in your own folder or selecting a curated GTSFM GitHub sample, and sample scenes automatically apply the matching loader and recommended settings, then are cached after their first download. The workspace manages runs, shows logs, visualises iterative Gaussian optimisation, and opens final reconstructions in the built-in 3D viewer. Completed splats download as .ply files from either Activity or Results.

The terminal workflow still exists for anyone who wants it:

```bash
gtsfm execute -- --dataset_dir /path/to/data --config_name vggt --loader olsson
```

And there are a few utility commands worth knowing:

```bash
gtsfm hardware          # list detected CPU/GPU devices
gtsfm viz               # open existing results
gtsfm run --no-browser  # start the workspace without opening a browser
```

The architecture of the interface is described precisely, which is unusual for a project of this kind. GTSFM Studio is a strict TypeScript React application built with Vite and lightweight Radix UI primitives, and its FastAPI and Uvicorn backend publishes typed OpenAPI documentation at /docs and streams job, log and live-splat state over WebSockets instead of polling the server. Release wheels contain the compiled frontend and the local 3D viewer vendor assets, so Node.js and external CDNs are not needed to run the installed application. For interface work, the Python API and the Vite development server run in separate terminals, and pnpm install, pnpm dev, pnpm check and pnpm build handle the frontend, with pnpm build refreshing the bundled assets.

The decision to stream over WebSockets rather than poll is the one that matters most for the experience. Long reconstruction runs with live splat previews produce a lot of state, and a polling client either lags behind or hammers the backend.

## Reconstruction model and the two splat backends

VGGT is the browser's default reconstruction model. Splat generation is a separate choice, and the project treats it as one, which is the right call because the two backends have very different cost profiles.

Optimized Gaussian splats uses the iterative gsplat implementation and publishes live training previews during the optimisation. AnySplat uses the feed-forward AnySplat pipeline, which does not iterate. A third option, No splats, runs reconstruction only, which is what you want when you care about the point cloud and the cameras rather than the appearance.

Additional Gaussian optimiser presets placed in gtsfm/configs/gaussian_splatting/ automatically appear in the interface, so a custom preset is a configuration file rather than a code change. The hard constraint is stated plainly: iterative gsplat and AnySplat currently require Linux with an NVIDIA CUDA GPU, and the UI detects this capability and prevents unsupported runs. That is a good design decision in one sense, since a silent failure or a confusing crash on an unsupported machine is worse than a disabled button, and a bad one in another, because it rules out a lot of laptops.

Model weights are handled in a way that avoids one common annoyance. The default VGGT checkpoint is downloaded from Hugging Face on first use when it is not already present, and an explicitly configured checkpoint path is never replaced automatically. The last part is the important detail: if you have pinned a specific checkpoint, a run will not quietly swap it out from under you.

For the older feature-based path, the usage guide says that if you intend to use modules with pre-trained weights such as SuperPoint, SuperGlue or PatchmatchNet, you download the model weights first with a script:

```bash
bash scripts/download_model_weights.sh
```

## Running on a remote GPU, and the Dask configuration

The remote path is where the Dask-native design becomes visible to a user. To submit work to a remote GPU machine, you start its workspace with an API key:

```bash
GTSFM_API_KEY=your-secret gtsfm run --host 0.0.0.0 --no-browser
```

Then you choose Remote VM in the workspace and select an API or SSH connection. Modal is the first hosted API option, and its credential handling is specified in detail: you enter a token ID and token secret separately, or paste the full modal token set command into either field and the workspace splits it automatically.

The data flow across that boundary is described with the care it deserves. GTSFM sample datasets are downloaded directly by the remote workspace, so you do not pay to ship them. User-selected folders are archived and streamed to the protected workspace before the job starts. Live preview splats and the final .ply result are mirrored back to the local viewer. Modal account credentials and the derived workspace API key are kept in memory and are not included in public job state.

That last sentence is the one to notice. A pipeline that shuttles your dataset to a remote machine and streams results back is handling data that may not be yours to send, so the credential handling and the job state boundaries are the security surface, and the project addresses both explicitly.

The hosting options beyond Modal are listed as coming soon, with Lambda Cloud, RunPod, Vast.ai and AWS EC2 named. The warning about exposure is also explicit: use HTTPS or a trusted private network when exposing a remote workspace, because the built-in server is intended for local or controlled-network use. The .env.example file shows the same three-part configuration, SSH settings, Dask workers as a JSON map of host and port pairs, and PostgreSQL connection values, which tells you the Dask cluster and the database are both intended to be reachable services rather than in-process defaults.

## Installation paths and the packaging detail that constrains you

GTSfM requires no compilation, because Python wheels are provided for GTSAM, and that single line removes the usual worst of an SfM dependency. The repository does include external repositories as Git submodules, so unless you cloned with git clone --recursive you need to initialise them:

```bash
git submodule update --init --recursive
```

Beyond that there are two supported installation methods, each with its own document. Option 1 is Conda setup, recommended for most users, with detailed instructions in docs/setup/conda-setup.md. Option 2 is UV setup, described as a fast alternative package manager, with instructions in docs/setup/uv-setup.md. The repository also ships environment_linux.yml, environment_linux_cpuonly.yml and environment_mac.yml for the conda route.

The packaging metadata is where the constraints hide, and there is a real discrepancy worth knowing about before you commit to a Python version. The pyproject.toml requires Python >=3.12,<3.13, which is an exact pin, while setup.py declares python_requires as >= 3.6. The pyproject file also names the version as 0.2.0 and the licence as BSD-3-Clause. The older setup.py looks like a leftover, since the project documents uv and pip installs of the current package rather than the legacy path, but the two files disagree about the Python floor, and the pyproject value is the one the current install commands go through.

The dependency list in pyproject is also where the architecture shows. Dask and distributed are both pinned at 2025.9.1, with lz4 and msgpack alongside, which is the standard Dask stack for distributed task scheduling and serialisation. hydra-core provides the configuration system, and the usage guide describes a unified runner that supports all dataset types through Hydra configuration. numpy is pinned at 2.2.6 and pandas at 2.3.3, both exact, along with toolz, tornado and bokeh. There is also a modal dependency at 1.0.0 or newer, which is the remote GPU path rather than the local one.

## The licence split, and where this is the wrong tool

The licence needs a paragraph of its own, because the two halves of this repository are under different terms. The documentation states that the majority of the code is governed by an MIT licence and is suitable for commercial use, but that certain implementations featured in the repository, naming SuperPoint and SuperGlue, are governed by a non-commercial licence and may not be used commercially. The packaging metadata says BSD-3-Clause, and GitHub's own classifier for the project is recorded as a custom licence it cannot classify. The upshot for an adopter is simple and important: you can use the pipeline commercially, but the feature matching implementations that many SfM pipelines are built on are not free for that purpose, and the boundaries are per implementation rather than per repository.

The limitation that is easiest to hit is the hardware one. If you are on macOS, the splat backends are not available to you, and the same applies to a Linux machine without an NVIDIA CUDA GPU. The point cloud and camera reconstruction still run, because No splats is a supported option, so the pipeline is not useless, but the visual output that most people want from a reconstruction is exactly what you lose.

The second limitation is that this is a research codebase with a specific provenance. The paper/ directory, the presence of a Colab notebook, the primary language recorded as Jupyter Notebook, and the fact that the reproduction scripts and example datasets in the repository are the ones the authors used all point the same way. That is a strength when you want to reproduce a paper or extend a published method, and a weakness when you want something with an API stability guarantee, since there are no GitHub releases and the version is 0.2.0.

The alternative is a collection of separate SfM tools, each doing one stage, stitched together by hand. The difference in approach is precisely what GTSfM is arguing about. Separate tools give you per-stage optimisation and a familiar stage-by-stage debugging model, at the cost of serialising the data between formats, and they cannot share state across stages, which is where the Dask-native design pays off. The other alternative is to use a photogrammetry suite with a commercial licence and a support contract, which removes the licence questions entirely at the cost of a different cost model and no source access. For a research group reproducing a published result, GTSfM is the sharper choice, because the configuration, the checkpoints and the evaluation scripts in the repository are the ones the paper describes.

## Conclusion

Adopt GTSfM if you need a complete structure from motion pipeline rather than a collection of scripts, and you are working on Linux with an NVIDIA CUDA GPU if you want Gaussian splats. Do not adopt it if you need macOS or CPU only splat generation, because the iterative gsplat and AnySplat backends currently require Linux with an NVIDIA GPU and the interface blocks unsupported runs. Before you start, read the licence section carefully, because the majority of the code is MIT while implementations such as SuperPoint and SuperGlue carry a non-commercial licence, and check the Python requirement, since the package metadata pins Python 3.12 exactly.

## FAQ

### What is GTSfM and what makes it different from other structure from motion code?

It is Georgia Tech's end-to-end structure from motion pipeline based on GTSAM, designed from the ground up to support parallel computation natively using Dask. Rather than separate tools per stage, the stages share state, and the whole pipeline ships with a browser workspace, a default VGGT reconstruction model and a choice of splat backends.

### How do I install GTSfM and start the workspace?

No compilation is needed because Python wheels are provided for GTSAM. From a recursive checkout run `uv tool install .` and then `gtsfm run`, or use `pip install .` inside a Python 3.12 environment. The browser opens automatically, and `gtsfm run --no-browser` starts the workspace without opening one.

### Which splat backends does GTSfM support and what do they need?

Optimized Gaussian splats uses the iterative gsplat implementation with live training previews, AnySplat uses the feed-forward pipeline, and there is a No splats option that runs reconstruction only. Both splat backends currently require Linux with an NVIDIA CUDA GPU, and the interface detects this and prevents unsupported runs.

### Can I run GTSfM on a remote GPU machine?

Yes, start the remote workspace with `GTSFM_API_KEY=your-secret gtsfm run --host 0.0.0.0 --no-browser` and then choose Remote VM in the workspace with an API or SSH connection. Modal is the first hosted API option, with Lambda Cloud, RunPod, Vast.ai and AWS EC2 listed as coming soon, and the documentation warns to use HTTPS or a trusted private network when exposing the workspace.

### What licence does GTSfM use and can it be used commercially?

The majority of the code is under MIT and is suitable for commercial use, but certain implementations such as SuperPoint and SuperGlue are under a non-commercial licence and may not be used commercially. The packaging metadata declares BSD-3-Clause, and the repository also carries a thirdparty/ directory and a NOTICE-style separation of the two.

## Sources

- [borglab/gtsfm on GitHub](https://github.com/borglab/gtsfm)
- [Issues](https://github.com/borglab/gtsfm/issues)
- [README](https://github.com/borglab/gtsfm/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/borglab-gtsfm
