kapture: a pivot file format for Structure from Motion datasets
kapture is a file format as well as a set of tools for manipulating datasets, and in particular Visual Localization and Structure from Motion data.
At a glance
- What is it?
- Kapture is a pivot format and a Python toolkit for Structure from Motion and general sensor-acquired data, storing cameras, images, lidar, keypoints, descriptors, matches and a 3D reconstruction in tables that reference raw data rather than copy it. It ships with converters to and from other formats, a Docker image, and a dozen sample datasets.
- Who is it for?
- Kapture suits a team producing or consuming visual localization data who wants one layout for raw sensor records, poses and computed features, since the tables reference the heavy data instead of duplicating it and the archive variants keep a large dataset manageable. It does not suit you if you want a single self-describing file you can hand to someone without the tooling, because the format is a directory of related files with cross references between them.
- 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 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A pivot format for sensor data, and why pivot is the word
Kapture is described in two ways that pull in different directions, and both are true. It is a pivot file format, based on text and binary files, used to describe Structure from Motion and more generally sensor-acquired data. And it is a set of tools for manipulating datasets.
The pivot idea is the substance. Instead of one file per thing, the format arranges data into tables where each row is a record and each column is a field, so that sensor parameters, timestamps, poses and image paths live in separate files that can be joined on a key. That is what makes it possible to hold cameras, images, lidar and other sensor data alongside computed data such as 2D features and a 3D reconstruction, and to have the computed data reference the raw data rather than copy it.
The list of what it can store is explicit. Sensor parameters and raw sensor data cover cameras, images, and lidar and other sensor data. Computed data covers 2d features and 3d reconstruction. And many popular datasets can be downloaded directly through a downloader that is linked from the overview.
The format specification is a separate document, the kapture format specifications document, which the overview points at rather than inlining. That is the right structure for a format, because the specification has to be the contract and the documentation around it has to be able to move faster.
The topics give the domain the format serves: colmap, image-retrieval, localization, r2d2, sfm, structure-from-motion, visual-features and visual-localization. The project is BSD-3-Clause licensed, the last push was on 2026-10-20, and the recent releases are v1.1.10 in March 2024 followed by v1.1.11 and v1.1.12 in April 2026.
The sensors directory carries the geometry, the records carry the time
The example file structure is the clearest statement of how the format works, and the top of the tree is where the geometry lives.
my_dataset # Dataset root path
├─ sensors/ # Sensor data root path
│ ├─ sensors.txt # list of all sensors with their specifications (e.g. camera intrinsics)
│ ├─ rigs.txt # geometric relationship between sensors (optional)
│ ├─ trajectories.txt # extrinsics (timestamp, sensor, pose)
│ ├─ records_camera.txt # all records of type 'camera' (timestamp, sensor and path to image)
│ ├─ records_SENSOR_TYPE.txt # all records of type SENSOR_TYPE (other sensors, eg: 'magnetic', 'pressure'...)
│ └─ records_data/ # image and lidar data path
│ ├─ map/cam_01/00001.jpg # image path used in records_camera.txt (example)
│ ├─ map/cam_01/00002.jpg
│ ├─ map/lidar_01/0001.pcd # lidar data path used in records_lidar.txt
│ ├─ query/query001.jpg # image path used in records_camera.txt
│ ├─ ...
└─ reconstruction/The sensors directory holds five kinds of file and one data directory. sensors.txt is the list of all sensors with their specifications, for example camera intrinsics. rigs.txt describes the geometric relationship between sensors and is marked optional. trajectories.txt holds extrinsics as timestamp, sensor and pose. records_camera.txt holds all records of type camera as timestamp, sensor and a path to the image, and the pattern generalises to records_SENSOR_TYPE.txt for other sensor types such as magnetic or pressure. And records_data/ is where the image and lidar data itself lives, with subdirectories for the map and the query sets.
That separation is the design. A record says what was seen, when, by which sensor, and points at a file. The geometry says where the sensors were. The heavy binary data stays out of the tables. It is a layout that scales to lidar and to images without rewriting the metadata format, and it is why the same structure holds for a sensor type nobody anticipated, since records_SENSOR_TYPE.txt is a naming convention rather than a fixed set of files.
The reconstruction directory is where computed data sits, and it repeats the same pattern one level down. keypoints/ holds a directory per keypoint type, each with a keypoints.txt describing the type, shape and dtype, and one file per image. descriptors/ is the same with an additional field recording the keypoints type the descriptors belong to. matches/ holds matches, again grouped by keypoint type. global_features/ does the same for global features, with the type directory holding a description file and one file per image.
The one file that sits outside the type directories is points3d.txt, the 3D points of the reconstruction, and observations.txt, the 2D and 3D point correspondences.
There is a detail that tells you this format was designed for real datasets rather than for a paper demo. Several of the type directories offer an archive variant alongside the regular files, so keypoints.tar, descriptors.tar and matches.tar can hold the same content as a single file rather than one per image. On a dataset with a hundred thousand query images, one file per image is a filesystem problem and a tar is not.
Conversion both ways, and the two symbols that mark a gap
The repository holds a set of conversion tools to or from the kapture format. Import results into it, and export converts kapture data to other formats.
The interesting part is the honest accounting of what does not convert. Depending on the format, some data might not be converted, either because the other format does not support it, marked with an em dash, or because it was not implemented, marked with a circled cross. The summary table that follows has a row per format and a column per data type, with columns for camera, rig, image, trajectory, GPS, keypoints, descriptors, global features, 3D points, observations and matches.
That two-symbol convention is the part worth taking note of, because it distinguishes a limitation of the target format from an unfinished piece of the converter. Losing data because the format on the other side has no concept of it is a permanent property of the pair, while not implemented is a gap in this project that might close.
The export command names give a sense of the coverage. There are exports for COLMAP, for OpenMVG, for OpenSfM, for LTVL2020, for ETH MS LTVL, for depth images, for a PLY file, for an image list, and for the 4seasons pairs, along with importers and utilities of their own.
The tools are exposed as console scripts, and the list in the project configuration shows the shape. There are commands for kapture_data_date_ranges, kapture_download_dataset, kapture_extract_exif, and then a family of export commands, each pointing at a function in the tools package: kapture_export_colmap, kapture_export_image_list, kapture_export_ply, kapture_export_LTVL2020, kapture_export_openmvg, kapture_export_opensfm, kapture_export_ETH_MS_LTVL, kapture_export_depth_images and kapture_export_4seasons_pairs. The setuptools configuration declares the packages as kapture and tools, which is what makes those entry points resolvable.
So the library is one half and the converters are the other, and the converters are the half that has to keep pace with whatever format they target changes into.
Install, container, and a documentation file that is generated
The Python library installs with one command:
pip install kaptureAnd there is a more detailed installation document for the cases that need more than that.
The Docker route is the one with detail, and it starts from a Makefile target:
$> cd kapture
# build the docker image : if you have already cloned the repository
$> make docker
# OR build the docker image directly from github (no need to clone).
$> docker build git://github.com/naver/kapture -t kapture/kapture
# run unit tests
$> docker run -it --rm kapture/kapture python3 -m unittest discover -s /opt/src/kapture/testsTwo ways to build are given. You can clone and run make docker, which builds the image tagged kapture/kapture, or build directly from GitHub without cloning at all. The unit tests run inside the container with the unittest discovery command pointed at the tests directory inside the image, which means the test environment is the environment the tool ships in rather than whatever the host happens to have.
If you want to process your own data, you bind directories between the host and the container using the volume or mount option, and the example mounts a dataset path from the host to /dataset inside the container as read only.
The Makefile at the repository root shows the rest of the workflow, and there is one entry that explains a lot about how this project is organised:
build: README.md
python3 -m build
install: README.md
pip install .
unittests:
python3 -m unittest discover -s testsThe build target depends on README.md, and README.md is generated from README.adoc through asciidoctor and pandoc. The README.adoc is the source of truth and the README.md is a build artefact, and the clean target removes it along with the dist directory and the egg info.
That is why the project depends on asciidoctor and pandoc, which the Makefile checks for separately before running. The documentation is written in AsciiDoc because it needs tables and cross references, and the version people read on the repository page is converted from it.
The unit test target runs the unittest discovery over the tests directory, and the pyproject lists pytest among the dependencies, so both runners are present in the tree.
The top level of the repository also shows a dataset/ directory alongside samples/, and the samples directory holds a dozen ready made examples: 4seasons, 7scenes, Aachen-Day-Night, berlin, cour_carree_markers, m1x, maupertuis, maupertuis_openMVG, t265, utbm and virtual_gallery, alongside a keep file.
Running the tool against a known dataset rather than your own is how you find out whether the format is doing what you expected, and having a dozen of them in the repository makes that possible.
A dependency list that tells you what the format touches
The project configuration lists the runtime dependencies, and reading them tells you what the format has to deal with.
dependencies = [
'dataclasses>=0.3',
'numpy>=1.16',
'numpy-quaternion>=2019.3.18.14.33.20',
'numba>=0.42',
'matplotlib>=3.0',
'scipy>=1.10.1',
'tqdm>=4.30',numpy is the expected one, and numpy-quaternion is there for poses, since a trajectory file holds extrinsics and quaternions are how rotations are usually written. numba is a compiled accelerator, which for per-image keypoint and descriptor arrays is the difference between a loop over a million images and a few minutes.
matplotlib is a dependency rather than an optional extra, so the package can draw things. scipy at 1.10.1 or newer suggests numerical work on the reconstruction, and Pillow at 8.1.1 or newer is the image handling. piexif is pinned exactly at 1.1.3, which is unusual in a list of minimum-version dependencies and tells you the EXIF handling depends on a specific behaviour of that release.
Then the plumbing. requests for the dataset downloader, pyyaml for configuration, wcmatch for glob patterns when you select files by name, tabulate for printing the tables the tool produces, pytz for time zones since sensor timestamps are recorded in local time, tqdm for progress bars over large datasets, and dataclasses to give the format a structured record type.
The build backend is setuptools with setuptools-scm, which means the version comes from the git tags rather than being written by hand, and the version field in the project table is 1.1.12.
There is a single optional dependency group, zed, which pulls in pyzed for stereo cameras from that vendor. Everything else is either in the main list or absent.
The last thing worth noting is what is not in the list. There is no deep learning framework, despite the presence of the DELG and AP-GeM global feature types in the example structure. The format describes those features as data with a type, a shape and a dtype, and the tool stores and converts them without needing to know how they were computed. That is the payoff of separating the format from the algorithms that produce the data.
Editorial conclusion
Kapture suits a team producing or consuming visual localization data who wants one layout for raw sensor records, poses and computed features, since the tables reference the heavy data instead of duplicating it and the archive variants keep a large dataset manageable. It does not suit you if you want a single self-describing file you can hand to someone without the tooling, because the format is a directory of related files with cross references between them. Before you commit, read the conversion table for the specific pair of formats you care about, since the tool distinguishes a format that cannot express a field from a converter that was never written, and note that the README you read on the repository page is generated from README.adoc through asciidoctor and pandoc.
Frequently asked questions
What is the Kapture file format used for?
It is a pivot file format, based on text and binary files, used to describe Structure from Motion and more generally sensor-acquired data. It stores sensor parameters and raw sensor data such as cameras, images and lidar, alongside computed data such as 2d features and 3d reconstruction.
How do I install the Kapture Python library?
Run pip install kapture. There is a more detailed installation document for cases needing more than that, and a Docker route as well, where you can build the image with make docker or directly from GitHub with docker build.
How does the Kapture conversion table show what can be converted?
Each row is a format and each column a data type, with camera, rig, image, trajectory, GPS, keypoints, descriptors, global features, 3D points, observations and matches as columns. A cell marked with an em dash means the other format does not support that data, and a cell marked with a circled cross means the conversion was not implemented.
What are the Kapture conversion tools for?
There is one set to import results into the Kapture format and one to export Kapture data to other formats, including COLMAP, OpenMVG, OpenSfM, LTVL2020, ETH MS LTVL, depth images, PLY, an image list and the 4seasons pairs. They are exposed as console scripts such as kapture_export_colmap and kapture_export_ply.
Why does the Kapture repository store keypoints and descriptors as directories of files or as a tar?
The example structure shows both forms for keypoints, descriptors, matches and global features, with the archive variant described as an alternative to the regular files. On a dataset with a large number of images, one file per image becomes a filesystem problem and a single archive does not.
Official sources
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.
[](https://hysenlabs.com/projects/naver-kapture)Was this useful?