Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Python Bindings for COLMAP

PyCOLMAP exposes to Python most capabilities of the COLMAP Structure-from-Motion (SfM) and Multi-View Stereo (MVS) pipeline.

Installation

Pre-built wheels for Linux, macOS, and Windows can be installed using pip:

pip install pycolmap

The wheels are automatically built and pushed to PyPI at each release. To benefit from GPU acceleration, wheels built for CUDA 12 (only for Linux - for now) are available under the package pycolmap-cuda12.

[Building PyCOLMAP from source - click to expand]
  1. Install COLMAP from source following the official guide.

  2. Build PyCOLMAP:

    • On Linux and macOS:
      python -m pip install .
      
    • On Windows, after installing COLMAP via VCPKG, run in powershell:
      python -m pip install . `
          --cmake.define.CMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" `
          --cmake.define.VCPKG_TARGET_TRIPLET="x64-windows"
      

Reconstruction Pipeline

PyCOLMAP provides bindings for multiple steps of the standard reconstruction pipeline:

  • Extracting and matching SIFT features
  • Importing an image folder into a COLMAP database
  • Inferring the camera parameters from the EXIF metadata of an image file
  • Running two-view geometric verification of matches on a COLMAP database
  • Triangulating points into an existing COLMAP model
  • Running incremental reconstruction from a COLMAP database
  • Dense reconstruction with multi-view stereo

Sparse & Dense Reconstruction

Sparse & Dense reconstruction from a folder of images can be performed with:

output_path: pathlib.Path
image_dir: pathlib.Path

output_path.mkdir()
mvs_path = output_path / "mvs"
database_path = output_path / "database.db"

pycolmap.extract_features(database_path, image_dir)
pycolmap.match_exhaustive(database_path)
maps = pycolmap.incremental_mapping(database_path, image_dir, output_path)
maps[0].write(output_path)

# Dense reconstruction
pycolmap.undistort_images(mvs_path, output_path, image_dir)
pycolmap.patch_match_stereo(mvs_path)  # requires compilation with CUDA
pycolmap.stereo_fusion(mvs_path / "dense.ply", mvs_path)

PyCOLMAP can leverage the GPU for feature extraction, matching, and multi-view stereo if COLMAP was compiled with CUDA support. Similarly, PyCOLMAP can run Delaunay Triangulation and Advancing Front Surface Reconstruction if COLMAP was compiled with CGAL support. This requires to build the package from source and is not available with the PyPI wheels.

Configuration Options

All of the above steps are easily configurable with python dicts which are recursively merged into their respective defaults, for example:

pycolmap.extract_features(
    database_path, image_dir,
    extraction_options={"sift": {"max_num_features": 512}}
)

# Equivalent to:
ops = pycolmap.FeatureExtractionOptions()
ops.sift.max_num_features = 512
pycolmap.extract_features(database_path, image_dir, extraction_options=ops)

To list available options and their default parameters:

help(pycolmap.SiftExtractionOptions)

For another example of usage, see example.py or hloc/reconstruction.py.

Reconstruction Object

We can load and manipulate an existing COLMAP 3D reconstruction:

import pycolmap

reconstruction = pycolmap.Reconstruction("path/to/reconstruction/dir")
print(reconstruction.summary())

for image_id, image in reconstruction.images.items():
    print(image_id, image)

for point3D_id, point3D in reconstruction.points3D.items():
    print(point3D_id, point3D)

for camera_id, camera in reconstruction.cameras.items():
    print(camera_id, camera)

reconstruction.write("path/to/reconstruction/dir/")

Common Operations

The object API mirrors the COLMAP C++ library. The bindings support many operations, for example:

Projecting a 3D point into an image with arbitrary camera model:

uv = camera.img_from_cam(image.cam_from_world * point3D.xyz)

Aligning two 3D reconstructions by their camera poses:

rec2_from_rec1 = pycolmap.align_reconstructions_via_reprojections(
    reconstruction1, reconstruction2
)
reconstruction1.transform(rec2_from_rec1)
print(rec2_from_rec1.scale, rec2_from_rec1.rotation, rec2_from_rec1.translation)

Exporting reconstructions to text, PLY, or other formats:

reconstruction.write_text("path/to/new/reconstruction/dir/")  # text format
reconstruction.export_PLY("rec.ply")  # PLY format

Estimators

We provide robust RANSAC-based estimators for:

  • Absolute camera pose (single-camera and multi-camera-rig)
  • Essential matrix
  • Fundamental matrix
  • Homography
  • Two-view relative pose for calibrated cameras

All RANSAC and estimation parameters are exposed as objects that behave similarly as Python dataclasses. The RANSAC options are described in colmap/optim/ransac.h and their default values are:

ransac_options = pycolmap.RANSACOptions(
    max_error=4.0,  # For example the reprojection error in pixels
    min_inlier_ratio=0.01,
    confidence=0.9999,
    min_num_trials=1000,
    max_num_trials=100000,
)

Absolute Pose Estimation

To estimate the absolute pose of a query camera given 2D-3D correspondences:

# Parameters:
# - points2D: Nx2 array; pixel coordinates
# - points3D: Nx3 array; world coordinates
# - camera: pycolmap.Camera
# Optional parameters:
# - estimation_options: dict or pycolmap.AbsolutePoseEstimationOptions
# - refinement_options: dict or pycolmap.AbsolutePoseRefinementOptions
answer = pycolmap.estimate_and_refine_absolute_pose(points2D, points3D, camera)
# Returns: dictionary of estimation outputs or None if failure

2D and 3D points are passed as Numpy arrays or lists. The options are defined in estimators/absolute_pose.cc and can be passed as regular (nested) Python dictionaries:

pycolmap.estimate_and_refine_absolute_pose(
    points2D, points3D, camera,
    estimation_options=dict(ransac=dict(max_error=12.0)),
    refinement_options=dict(refine_focal_length=True),
)

Absolute Pose Refinement

# Parameters:
# - cam_from_world: pycolmap.Rigid3d, initial pose
# - points2D: Nx2 array; pixel coordinates
# - points3D: Nx3 array; world coordinates
# - inlier_mask: array of N bool; inlier_mask[i] is true if correspondence i is an inlier
# - camera: pycolmap.Camera
# Optional parameters:
# - refinement_options: dict or pycolmap.AbsolutePoseRefinementOptions
answer = pycolmap.refine_absolute_pose(
    cam_from_world, points2D, points3D, inlier_mask, camera
)
# Returns: dictionary of refinement outputs or None if failure

Essential Matrix Estimation

# Parameters:
# - points1: Nx2 array; 2D pixel coordinates in image 1
# - points2: Nx2 array; 2D pixel coordinates in image 2
# - camera1: pycolmap.Camera of image 1
# - camera2: pycolmap.Camera of image 2
# Optional parameters:
# - options: dict or pycolmap.RANSACOptions (default inlier threshold is 4px)
answer = pycolmap.estimate_essential_matrix(points1, points2, camera1, camera2)
# Returns: dictionary of estimation outputs or None if failure

Fundamental Matrix Estimation

answer = pycolmap.estimate_fundamental_matrix(
    points1,
    points2,
    [options],  # optional dict or pycolmap.RANSACOptions
)

Homography Estimation

answer = pycolmap.estimate_homography_matrix(
    points1,
    points2,
    [options],  # optional dict or pycolmap.RANSACOptions
)

Two-View Geometry Estimation

COLMAP can also estimate a relative pose between two calibrated cameras by estimating both E and H and accounting for the degeneracies of each model.

# Parameters:
# - camera1: pycolmap.Camera of image 1
# - points1: Nx2 array; 2D pixel coordinates in image 1
# - camera2: pycolmap.Camera of image 2
# - points2: Nx2 array; 2D pixel coordinates in image 2
# Optional parameters:
# - matches: Nx2 integer array; correspondences across images
# - options: dict or pycolmap.TwoViewGeometryOptions
answer = pycolmap.estimate_calibrated_two_view_geometry(
    camera1, points1, camera2, points2
)
# Returns: pycolmap.TwoViewGeometry

The TwoViewGeometryOptions control how each model is selected. The output structure contains the geometric model, inlier matches, the relative pose (if options.compute_relative_pose=True), and the type of camera configuration, which is an instance of the enum pycolmap.TwoViewGeometryConfiguration.

Camera Argument

Some estimators expect a COLMAP camera object, which can be created as follows:

camera = pycolmap.Camera(
    model=camera_model_name_or_id,
    width=width,
    height=height,
    params=params,
)

The different camera models and their extra parameters are defined in colmap/src/colmap/sensor/models.h. For example for a pinhole camera:

camera = pycolmap.Camera(
    model='SIMPLE_PINHOLE',
    width=width,
    height=height,
    params=[focal_length, cx, cy],
)

Alternatively, we can also pass a camera dictionary:

camera_dict = {
    'model': COLMAP_CAMERA_MODEL_NAME_OR_ID,
    'width': IMAGE_WIDTH,
    'height': IMAGE_HEIGHT,
    'params': EXTRA_CAMERA_PARAMETERS_LIST
}

SIFT Feature Extraction

import numpy as np
import pycolmap
from PIL import Image, ImageOps

# Input should be grayscale image with range [0, 1].
img = Image.open('image.jpg').convert('RGB')
img = ImageOps.grayscale(img)
img = np.array(img).astype(np.float) / 255.

# Optional parameters:
# - options: dict or pycolmap.SiftExtractionOptions
# - device: default pycolmap.Device.auto uses the GPU if available
sift = pycolmap.Sift()

# Parameters:
# - image: HxW float array
keypoints, descriptors = sift.extract(img)
# Returns:
# - keypoints: Nx4 array; format: x (j), y (i), scale, orientation
# - descriptors: Nx128 array; L2-normalized descriptors

Bitmap

PyCOLMAP provides bindings for the Bitmap class to work with images and convert them to/from NumPy arrays:

import numpy as np
import pycolmap

# Read a bitmap from file
bitmap = pycolmap.Bitmap.read("image.jpg", as_rgb=True)
print(f"Size: {bitmap.width}x{bitmap.height}, Channels: {bitmap.channels}")

# Convert to NumPy array
array = bitmap.to_array()  # Shape: (H, W, 3) for RGB or (H, W) for grayscale

# Create bitmap from NumPy array
array = np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8)
bitmap = pycolmap.Bitmap.from_array(array)

# Write bitmap to file
bitmap.write("output.jpg")

# Rescale bitmap
bitmap.rescale(new_width=320, new_height=240)

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pycolmap_cuda12-4.2.0.dev0-cp314-cp314-manylinux_2_28_x86_64.whl (63.0 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ x86-64

pycolmap_cuda12-4.2.0.dev0-cp313-cp313-manylinux_2_28_x86_64.whl (63.0 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ x86-64

pycolmap_cuda12-4.2.0.dev0-cp312-cp312-manylinux_2_28_x86_64.whl (63.0 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

pycolmap_cuda12-4.2.0.dev0-cp311-cp311-manylinux_2_28_x86_64.whl (63.0 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

pycolmap_cuda12-4.2.0.dev0-cp310-cp310-manylinux_2_28_x86_64.whl (63.0 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.28+ x86-64

File details

Details for the file pycolmap_cuda12-4.2.0.dev0-cp314-cp314-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pycolmap_cuda12-4.2.0.dev0-cp314-cp314-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 08b2438d6ca49d30d4c7c9eb2ea9212e81238c1139f4822a1ed128d6b36fb543
MD5 291de71b1f3238f85dd5e89bf74598f1
BLAKE2b-256 1750db7df37a5da7a24d5fa6e9cfbe7cb82555fce661e9750eeb30aa12705185

See more details on using hashes here.

Provenance

The following attestation bundles were made for pycolmap_cuda12-4.2.0.dev0-cp314-cp314-manylinux_2_28_x86_64.whl:

Publisher: build-pycolmap.yml on colmap/colmap

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pycolmap_cuda12-4.2.0.dev0-cp313-cp313-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pycolmap_cuda12-4.2.0.dev0-cp313-cp313-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 fac4f0a2da0d76a8e909b3ba5e697eb14dd1cc94a8a5afeeb2f873a9e854e889
MD5 c5272b69ba126a185d7ff593475b81bf
BLAKE2b-256 dd0a72337f2bde90c91c621c75d34f7c9e66e3236a5462ee4026c2eed3db0281

See more details on using hashes here.

Provenance

The following attestation bundles were made for pycolmap_cuda12-4.2.0.dev0-cp313-cp313-manylinux_2_28_x86_64.whl:

Publisher: build-pycolmap.yml on colmap/colmap

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pycolmap_cuda12-4.2.0.dev0-cp312-cp312-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pycolmap_cuda12-4.2.0.dev0-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 042276ec0b79974845b534f691415ef5ba3b69b50f9d277c65e64e2cf25a7b6c
MD5 791a7c0d5d2f2c7d6e60292398a26c13
BLAKE2b-256 a9cc4eb31fc3c7ce371f026acc999e3a0c9210fabeab65cf929f38d9d7bac325

See more details on using hashes here.

Provenance

The following attestation bundles were made for pycolmap_cuda12-4.2.0.dev0-cp312-cp312-manylinux_2_28_x86_64.whl:

Publisher: build-pycolmap.yml on colmap/colmap

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pycolmap_cuda12-4.2.0.dev0-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pycolmap_cuda12-4.2.0.dev0-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b6b14e10a94423957cced404341cba038d13d1ba579bcee58e17cfe8336a7118
MD5 d0227e4b5b7d5e4394d560e4855cb3d1
BLAKE2b-256 cd0e8e4d982ec786156c484cc332f58e403566ea65265af927a5790acd982392

See more details on using hashes here.

Provenance

The following attestation bundles were made for pycolmap_cuda12-4.2.0.dev0-cp311-cp311-manylinux_2_28_x86_64.whl:

Publisher: build-pycolmap.yml on colmap/colmap

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pycolmap_cuda12-4.2.0.dev0-cp310-cp310-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pycolmap_cuda12-4.2.0.dev0-cp310-cp310-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 8a773a20121933e2e958667bc49c9fc919534598f17d46375ea0dbae0c328d0a
MD5 5cf1e3d1953ab32b0e03a2d22199d7ba
BLAKE2b-256 568f0ed97175c407cf54159fa6a7326f8645581d58a8f44de79d5c4e8d5fb26b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pycolmap_cuda12-4.2.0.dev0-cp310-cp310-manylinux_2_28_x86_64.whl:

Publisher: build-pycolmap.yml on colmap/colmap

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page