Open-source project
cvg/limap avatar
cvg/limap

LIMAP: 3D mapping and SfM that treat lines and planes as first-class features

A toolbox for 3D visual mapping, localization, and SfM with structured geometric features (points, lines, planes, vanishing points, wireframes, etc.).

903 stars102 forksC++BSD-3-Clause

At a glance

What is it?
LIMAP is a C++ and Python toolbox from the Computer Vision and Geometry Group at ETH Zurich that reconstructs scenes with points, lines, vanishing points, planes and parametric primitives optimised jointly with the camera poses. Version 2.0.0 rebuilt it on top of the COLMAP ecosystem, and the installation story is where most of the friction lives.
Who is it for?
Adopt LIMAP if you are doing research on structured 3D reconstruction, if point clouds are not enough for your scenes, and if you are prepared to deal with a C++ and Python build with git-sourced dependencies.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 23 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem: a point cloud is a poor description of a building

Structure from motion has a standard output, and the standard output is a sparse cloud of points with camera poses. It works well for photogrammetry of textured surfaces and badly for the scenes that dominate urban and indoor reconstruction, where the interesting geometry is made of straight edges, flat surfaces and repeating shapes.

LIMAP is a toolbox for 3D mapping, localization and structure from motion with structured features. Alongside keypoints, it treats lines, vanishing points, planes, parametric primitives such as spheres, cylinders, ellipsoids, cuboids and cones, and the wireframe connecting them as first class citizens of the reconstruction, optimised jointly with the camera poses. The stated outcome is a sparse 3D reconstruction with geometric primitives beyond point clouds.

That joint optimisation is the research contribution. Adding lines to a point based pipeline is straightforward; using them as constraints that pull the camera poses into a better position, and letting detected planes and primitives refine the same bundle adjustment, is not. The project documentation makes the point with a line about multi-view images where LIMAP jointly optimises the features, the camera poses and the structural constraints.

The provenance matters for judging maturity. The toolbox grew out of the highlight paper 3D Line Mapping Revisited at CVPR 2023, with the SfM pipeline introduced and further improved in papers at ECCV 2024 and ECCV 2026, and the contributors are from the Computer Vision and Geometry Group at ETH Zurich. So this is research code that has been refactored into a released library, not a research prototype with a readme.

The audience is therefore researchers and engineers in 3D vision, and the expectation is that you know what a bundle adjustment is.

Three pipelines, and what each one assumes

The toolbox provides three pipelines, and the difference between them is what input you already have.

The first is visual mapping and triangulation. It builds a complete 3D model from images whose camera poses are already known, for instance from an existing COLMAP reconstruction. If you have a sparse SfM solution and want to add lines, planes and primitives to it, this is the entry point, and it is the most common way the toolbox gets used.

The second is visual localization. It estimates the camera pose of a query image with respect to an existing 3D model, using point and line correspondences jointly. Both calibrated and uncalibrated queries are supported, which matters because a query phone camera often has no reliable intrinsics.

The third is the incremental SfM pipeline that recovers everything at once. It recovers the camera poses and the 3D model together from images alone, with nothing given as input, again for calibrated and uncalibrated input.

The distinction between the second and third pipelines is the one to hold on to. Localization assumes the model exists, so the problem is a pose search against known geometry, and the correspondence problem is a matching problem. Incremental SfM assumes nothing, so it has to establish correspondences, triangulate, then refine, and it inherits every failure mode of that pipeline plus the ones introduced by the structured features.

Underneath the pipelines sit registries. The line detectors, matchers, vanishing point estimators and plane detectors are abstracted behind registries, which the documentation presents as a way to ensure flexibility to support recent advances and future development. In practice it means the detectors are pluggable, and that the set of available 2D line detectors is a configuration decision rather than a rebuild.

The 2.0.0 rewrite: LIMAP now sits on top of COLMAP

The most important change in the project is not a feature. It is that, starting from LIMAP 2.0.0, the toolbox is fully compatible with the COLMAP ecosystem, at COLMAP version 4.2.0 as of Sep 1 2026.

A reconstruction is now written as a plain COLMAP model, with the line, group and wireframe structures alongside it under structures/, so any output can be opened in the COLMAP GUI and read with pycolmap.

The documentation is clear that the unification runs deeper than the file format. The point side of the pipeline comes directly from COLMAP, consolidating with its scene types, database, estimators, correspondence graph and various incremental mapper logic, with LIMAP adding the structures on top instead of maintaining a parallel implementation. The stated benefit is that advances on the COLMAP side carry over directly, with multi-camera rig support and improved two-view geometry estimation given as examples.

That is the right architectural call for a project that adds structure to an existing point based reconstruction. The cost is that LIMAP is now coupled to a specific COLMAP version, and the Python dependency list pins pycolmap to 4.2.1, with a comment in the project metadata explaining that the bindings inherit pycolmap's types so the versions have to match.

The releases are recent and the versions are telling. There is 1.0.0 on 2026-09-02 and 2.0.0 on 2026-09-04, two days apart, which reads as a first public release followed immediately by the COLMAP unification, and the working tree is already at 2.1.0.dev. The repository is not archived and the last push was on 2026-09-30.

Installing: the pylimap wheel, and the source build

Starting from 2.0.0, each official release is published to PyPI as pylimap, which installs the compiled core library without building it:

bash
python -m pip install pylimap

The distribution is named pylimap, and the import name is still limap, which is worth knowing before you write a requirements file. A wheel provides the Core only mode, so the extras and the git-sourced detectors remain opt-in on top.

To build the package from source, the documentation gives two commands:

bash
python -m pip install -r requirements.txt
python -m pip install -Ive ".[all]"

and a way to check the result:

bash
python -c "import limap; print(limap.__version__)"

For faster incremental rebuilds during development, there is a variant that reuses the CMake build directory instead of rebuilding from scratch:

bash
python -m pip install -Cbuild-dir=./pylimap_build --no-build-isolation -Ive .

There are four install modes in total. Core only gives the compiled library and its Python API and nothing else: the geometry types, reading and writing of reconstructions, and the estimators and bundle adjustment, all operating on data you already have. The developer mode adds pytest and the pinned formatters on top of the full install. The full install needs the requirements file, and the wheel covers only the core.

The system requirements are Python 3.10 through 3.13, CMake 3.17 or newer, and CUDA for the deep learning based detectors and matchers, with a per-platform guide for the system dependencies. The project has been tested on Linux, macOS and Windows.

The dependency reality: hloc, git-sourced detectors, and open3d on 3.13

The install is where a reader needs to slow down, because the package metadata deliberately does not describe everything you need.

Running a reconstruction needs hloc, and hloc comes from requirements.txt rather than from the package metadata, because it is not published on PyPI and so cannot be declared as a dependency. The documentation is explicit about the consequence: without it the package imports fine, but the point frontend will fail when it is first used. That is a nasty failure mode to discover later, and it is the first thing to check when a LIMAP installation seems to work and then does not.

The same applies to the detectors. The requirements file pulls pytlsd, deeplsd, gluestick, hloc and pxwplanar directly from git, at pinned commits, with a comment explaining that PyPI rejects direct references in project metadata. Several further methods, named in the documentation as HAWP, TP-LSD, LBD, RoMa, Progressive-X and UPAL, are not installed by any of the modes and must be cloned and pip-installed separately, with per-method guides under the install directory.

The extras are small and explicit: viz for matplotlib, seaborn and open3d, needed by limap.visualize; line2d for einops, scikit-image and pillow, the support code for the 2D line detectors; dev for pytest, ruff and clang-format; and all, which is the union of viz and line2d.

Then there is the Python 3.13 problem. open3d publishes no wheels for Python 3.13 and later, and all 3D visualisation depends on it, so the visualisation scripts and the 3D helpers in limap.visualize do not run there. The pxwplanar plane detector also depends on open3d, so it is skipped on 3.13 as well. Line and point reconstruction are unaffected, since no pipeline touches open3d. The documentation puts it more bluntly elsewhere: one cannot visualise reconstructions on Python 3.13, because there are no published wheels available for open3d and the 3D viewer depends on it.

The codebase, the registries and the packaging constraints

The repository is a C++ project with a Python binding layer and a build system that is more considered than most research code. The top-level entries include a CMakeLists.txt, a cmake/ directory, a pyproject.toml, a requirements.txt, a pytest.ini, a ruff.toml, a vcpkg.json with a vcpkg-configuration.json for the C++ dependencies, and directories for src/, tests/, scripts/, cfgs/, docker/, runners/, experiments/, docs/ and misc/. The visualisation entry points sit at the root as visualize_colmap_model.py, visualize_holistic_recon.py and visualize_image_features.py.

The build backend is scikit-build-core, with CMake and a pinned pybind11 as build requirements, and the reason for the pin is stated in the metadata: it must match the COLMAP pin, because the bindings inherit pycolmap's types.

The Python version constraint has a comment attached, which is a good sign about the project's habits. The package is capped below 3.14 until dacite supports it, because limap converts every YAML config into an Options dataclass through dacite.from_dict, which relies on runtime annotation introspection, and that is exactly what the deferred annotations of 3.14 change.

The configuration system is worth noting for users: every pipeline is driven by YAML configs, with omegaconf in the dependency list for config handling, and the config is turned into typed dataclasses. The registries mentioned earlier sit on top of that, so a different line detector or plane estimator is a configuration and installation question rather than a code change.

Licence, ecosystem and when this is the wrong tool

The licence is BSD-3-Clause, stated in the project metadata with the LICENSE file listed as a licence file, which is permissive and carries no copyleft obligation for a commercial or academic user.

The alternatives have to be described carefully, because they are alternatives in approach rather than substitutes you can swap in. The first is plain COLMAP with a line detector bolted on. COLMAP gives you points, poses and a mature incremental mapper, and it is what LIMAP 2.0.0 now builds its point side on. The difference is that LIMAP optimises the structured features and the poses jointly, so a scene with strong linear structure comes out better constrained, at the cost of a much heavier build, more dependencies and a research codebase.

The second alternative is to write the structured extension yourself on top of COLMAP, which is what the LIMAP authors decided not to do. The third is to use a point-only pipeline, which is simpler, faster to install and entirely adequate if your scenes are texture rich rather than structurally rich.

So LIMAP is the wrong tool when you need a production SfM pipeline, when you want visualisation on Python 3.13, when you cannot install git-sourced dependencies or CUDA, or when your problem is points and nothing more. It is the right tool when your scenes are walls, corridors and facades, when you need lines, planes and vanishing points to constrain the geometry, and when you are willing to work with a research codebase that a university lab maintains.

The documentation, with brief tutorials and the API reference, is published separately from the repository, which is the place to check what a given detector expects before you commit an afternoon to it.

Editorial conclusion

Adopt LIMAP if you are doing research on structured 3D reconstruction, if point clouds are not enough for your scenes, and if you are prepared to deal with a C++ and Python build with git-sourced dependencies. Do not adopt it if you need a working installation on Python 3.13 with 3D visualisation, since the visualisation path and the pxwplanar plane detector are both unavailable there, and do not adopt it if you need a stable point-only pipeline, because the 2.0.0 release moved the point side onto COLMAP internals. Before you install, read the extras table and the requirements.txt, because hloc is not on PyPI and several detectors need manual installation.

Frequently asked questions

How do I install LIMAP?

From 2.0.0 each official release is on PyPI as pylimap, so python -m pip install pylimap installs the compiled core without building, with the import name still limap. To build from source, run python -m pip install -r requirements.txt followed by python -m pip install -Ive ".[all]", and check the result with python -c "import limap; print(limap.__version__)".

What do the three LIMAP pipelines do?

Visual mapping and triangulation builds a holistic 3D model from images whose camera poses are already known, for example from a COLMAP reconstruction. Visual localization estimates the camera pose of a query image against an existing model using point and line correspondences. Holistic incremental SfM recovers the poses and the model together from images alone.

Is LIMAP compatible with COLMAP?

Yes, since version 2.0.0 it is fully compatible with the COLMAP ecosystem, with COLMAP version 4.2.0 as of Sep 1, 2026. A reconstruction is written as a plain COLMAP model with the line, group and wireframe structures under structures/, and the point side of the pipeline comes directly from COLMAP rather than a parallel implementation.

Why does my LIMAP installation fail when I use the point frontend?

Running a reconstruction needs hloc, which is not published on PyPI and therefore cannot be declared as a dependency, so it comes from requirements.txt. The documentation notes that without it the package imports fine but the point frontend fails when first used.

What licence is LIMAP released under?

BSD-3-Clause, declared in the project metadata with the LICENSE file listed as a licence file, so it can be used in academic and commercial work without a copyleft obligation.

Official sources

  1. cvg/limap on GitHub
  2. Issues
  3. License: BSD-3-Clause
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/cvg-limap.svg)](https://hysenlabs.com/projects/cvg-limap)

Was this useful?