Troubleshooting registration failures
“COLMAP registered 140 of 200 images” is the single most common bad news a splat pipeline produces, and it’s rarely a COLMAP bug. Registration failure is COLMAP being honest that it couldn’t find enough reliable geometric evidence to place a camera with confidence, and every cause traces back to one of a handful of underlying problems in the capture or the matching graph. This article works through them the way you’d actually debug a failed run: symptom first, most likely cause, concrete fix, in the order worth checking them.
Symptom: a scattering of unregistered images, no obvious pattern
Cause: usually insufficient overlap or matching coverage at the level of individual images rather than a scene-wide problem. Each unregistered image simply didn’t share enough verified matches with any image already in the model to be added with confidence. Check the matching log or database for those specific images: if they show few raw matches to their neighbours, the fault is upstream in feature extraction or matching, not in the mapper.
Fix: increase feature count per image if extraction is capped low, switch from sequential to exhaustive matching if the capture path wasn’t strictly sequential (a doubled-back walkthrough breaks the sequential matcher’s near-neighbour assumption), or enable guided matching, which re-attempts matches using a geometric estimate from an initial pass rather than descriptors alone. If specific images are genuinely thin on overlap because a stretch of the walkthrough moved too fast, the durable fix is a supplementary capture pass through that stretch rather than software tuning.
Symptom: a whole section registers into its own sub-model
Cause: the matching graph has two (or more) well-connected clusters with too few cross-links between them, so incremental mapping successfully builds each cluster but never finds a confident bridge to merge them into one model. This is common with multi-room interiors (a corridor break between rooms, doors closed between shots), a capture done in two separate sessions, or a building walked floor by floor without enough photos taken looking back through connecting stairwells or doorways.
Fix: shoot deliberate bridge photos at the connection points, standing in
a doorway or stairwell landing so a handful of frames share strong
overlap with both sides. If the capture is already done and reshooting
isn’t an option, COLMAP’s model_merger will combine two sub-models that
do share some registered images in common, though it can only merge what
already has an anchor; the practical lesson is to plan bridge shots
during capture rather than relying on merging after the fact.
Symptom: images register, but the reconstructed geometry is warped or “bowl-shaped”
Cause: this is a degenerate-geometry problem, not a registration count problem, and it’s more dangerous precisely because it doesn’t show up as an obvious failure. It happens when the capture path is close to a straight line or a shallow arc with very little baseline variation, an orbit at a single fixed radius and height, say, which starves bundle adjustment of the geometric diversity it needs to separate camera pose error from scene shape error. The two become coupled, and bundle adjustment converges on a self-consistent but subtly wrong answer: a flat facade that bows, or a room that tapers when it shouldn’t.
Fix: vary the capture path deliberately, height changes on an orbit, occasional closer and farther passes, rather than one clean, repetitive sweep. If the capture is already fixed, adding photos from clearly different vantage points, even a handful from a different height or distance, gives the optimisation the leverage it was missing. This is also where loop closure earns its keep on a walkthrough: matching the end of a long path back to its beginning gives bundle adjustment a long-range constraint that catches drift a purely local sequence never would.
Symptom: a specific surface or region has few or no triangulated points
Cause: feature matchingComparing feature descriptors across images to propose which points likely correspond to the same physical location, prior to geometric verification. COLMAP supports exhaustive, sequential, vocabulary-tree, spatial and transitive matching strategies. found nothing distinctive to work with there. Textureless surfaces, plain plaster, painted drywall, clear sky, matte tarmac, simply don’t produce SIFT keypoints in usable numbers, and no amount of matcher tuning invents texture that isn’t in the pixels. Reflective and transparent surfaces are a related but distinct failure: glass, mirrors and polished floors do produce features, but the features describe a reflection that shifts with viewing angle rather than a fixed 3D surface, so matches across views are either rejected by the epipolar geometryThe geometric constraint that, given two calibrated views of a rigid scene, a point's match in one image must lie along a specific line in the other image. COLMAP uses it to verify proposed feature matches and reject geometrically inconsistent ones. check as inconsistent, or worse, pass the check and triangulationComputing a 3D point's position from two or more matched, pose-known camera views by finding where the rays cast through each observation intersect, or pass closest to each other once pose and pixel noise are accounted for. places a confident but wrong point behind or in front of the actual surface.
Fix: for genuinely textureless regions, there’s no matching-side fix; the point cloud gap there is expected, and it’s training’s job to fill that geometry from photometric evidence in nearby textured surfaces, not SfM’s. For reflective and transparent surfaces, treat them as photograph-differently zones: shoot them under changed lighting or from angles that minimise specular reflection, or accept that a mirror or glass frontage will simply be a hole in the sparse model and plan the capture so no camera pose critically depends on features there.
Symptom: repetitive structure produces confidently wrong poses
Cause: the epipolar check verifies that a match is geometrically consistent with two views of a rigid scene, but it can’t tell that a window bay matched to a different, near-identical window bay two bays along is the wrong window. Repeated facade bays, uniform column grids, identical stair treads, and patterned tiling all give feature matching plausible correspondences that are simply incorrect, and if enough of them agree with each other, they form a self-consistent but wrong solution that bundle adjustment happily optimises into a stable, false minimum.
Fix: break the symmetry with capture, not software: include enough photos containing a unique, non-repeating reference, an odd-shaped fixture, a sign, a corner, alongside the repetitive structure so correspondences have something asymmetric to lock onto. Sequential matching with a tight neighbour window is also inherently safer here than exhaustive matching, since it never proposes a long-range match between two distant, identical-looking bays in the first place.
In practice
Work this list in order, because the fixes get more expensive further down it: check raw match counts first, check for cluster splits second, check whether the geometry itself looks subtly wrong before assuming a clean registration count means a clean reconstruction, then check specific problem surfaces last. And keep a mental map, during the shoot itself, of which parts of a scene are hostile by nature, glass, repeated bays, blank walls, so a failed registration afterwards is a confirmation of a known risk rather than a surprise you have to diagnose from scratch.
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.