COLMAP in practice
COLMAP is the open-source tool most 3DGS pipelines lean on to turn a photo folder into camera poses and a sparse point cloud, and running it well is mostly a matter of picking the right stage settings for your capture rather than accepting every default. This article walks the pipeline in the order you’ll actually run it, feature extraction, matching, sparse mapping, and flags where the choice materially changes the outcome.
Feature extraction: SIFT is still the safe default
COLMAP extracts SIFT descriptors by default, on GPU when available, and that default is the right choice for most captures: it’s robust to the rotation, scale and moderate lighting change that a normal walkthrough or drone orbit produces. COLMAP also supports ALIKED, a learned feature detector, as an alternative via the feature extraction options, which is worth knowing about if SIFT is consistently underperforming on a difficult, low-texture scene, though it requires an ONNX-enabled COLMAP build; it isn’t a default worth reaching for until SIFT has actually let you down. The setting that matters more day to day is camera model: use a single shared camera model per physical camera or lens rather than letting COLMAP estimate intrinsics separately for every image, since sharing intrinsics across a whole capture gives the optimisation far more constraint per parameter and converges more reliably.
Matching: exhaustive, sequential, or something smarter
COLMAP ships several matchers, and the choice depends on how the photos were taken, not on scene content:
Exhaustive matching compares every image against every other image, which gives the best chance of finding a correct match anywhere in the set. It scales quadratically with image count, so it’s the right choice for smaller sets, roughly up to a few hundred images, where thoroughness matters more than speed and there’s no meaningful sequence to the shots (handheld orbits around an object, scattered photos of a facade).
Sequential matching only compares each image against its near neighbours in capture order, which is the correct choice whenever the photos come from a video-like walkthrough or a drone flight path where consecutive frames overlap. It also has an optional loop-detection setting that periodically checks a frame against a vocabulary-tree index of everything seen so far, which is what lets a long walkthrough recognise that it’s returned to its starting point and close the loop rather than drifting.
Vocabulary tree matching and spatial matching exist for much larger collections, thousands of images, or ones with usable location priors respectively, where exhaustive comparison is no longer practical. Transitive matching is a cleanup pass rather than a first choice: it infers additional pairs from existing matches (if A matches B and B matches C, try A against C directly) to patch gaps in an already-run matching graph.
For a typical single-scene capture, walked once with real overlap, start with sequential matching plus loop detection if the path returns on itself, and fall back to exhaustive on anything small enough to afford it when sequential leaves gaps.
Sparse reconstruction: three mappers, one clear default
COLMAP offers incremental, global and hierarchical mapping strategies. Incremental mapping, register one image, triangulate, bundle-adjust, repeat, is the most robust and best-tested of the three and is the sensible default for nearly everything a splat pipeline will feed it. Global mapping solves all camera poses at once via rotation averaging and can be faster on large datasets with a clean matching graph, but it depends on reasonably good focal-length priors and is worth reaching for only once incremental mapping is demonstrably too slow for a dataset’s size. Hierarchical mapping partitions a very large scene into overlapping sub-models, reconstructs each independently, and merges them, useful mainly at a scale, thousands of images across a large site, well beyond what a single splat scene usually needs.
What actually lands in the sparse model
The output that matters downstream is the sparse/0 folder: cameras,
images and points3D, containing the estimated intrinsics, the
per-image pose and observed 2D-3D correspondences, and the triangulated
point cloud respectively. Splat trainers built around the INRIA reference
implementation and its derivatives read this folder directly: camera
poses seed the training views, and the sparse point cloud seeds the
initial Gaussian positions before densification takes over. A common
practical snag isn’t a wrong flag but a wrong assumption: if COLMAP
produces more than one sub-model because a chunk of images failed to
register into the main one, only the largest model gets used by default,
and any images stranded in a smaller sub-model contribute nothing to
training unless you explicitly merge the models first.
In practice
Pick the matcher from how the photos were taken, not from the scene:
sequential for a walked or flown path, exhaustive for a smaller,
unordered set. Leave the mapper on incremental unless a specific,
demonstrated speed problem justifies switching. And before handing a
sparse model to training, check images.txt (or its binary equivalent)
for how many images actually registered against how many you fed in; a
gap here is a matching or geometry problem to fix at the SfM stage, not
something splat training can compensate for later.
Related papers
Structure-from-Motion Revisited
Introduces the incremental Structure-from-Motion pipeline, robust initial-pair and next-image selection, and bundle-adjustment scheduling, later released as the open-source COLMAP toolkit that most 3DGS capture pipelines use to produce camera poses and a sparse point cloud for training.