pycolmap: Python Bindings for COLMAP
pycolmap provides robust Python bindings for COLMAP, an open-source Structure-from-Motion (SfM) and Multi-View Stereo (MVS) pipeline. It allows programmatic control over COLMAP's feature extraction, matching, and 3D reconstruction functionalities directly from Python. The current version is 4.0.3, with releases typically synchronized with major COLMAP C++ releases, focusing on performance, new features, and bug fixes.
Common errors
-
ImportError: DLL load failed while importing _pycolmap
cause On Windows, this often indicates missing Visual C++ Redistributable packages, or an issue with the installed `pycolmap` wheel.fixEnsure the latest Visual C++ Redistributable for Visual Studio is installed from Microsoft's website. If the problem persists, try reinstalling `pycolmap` in a clean virtual environment. -
RuntimeError: Could not find any images in directory
cause The specified image directory either does not exist, is empty, or contains files that are not recognized image formats (e.g., not `.jpg`, `.png`).fixVerify that the `image_dir` path passed to `pycolmap` functions is correct and points to a directory containing valid image files with supported extensions. -
AttributeError: module 'pycolmap' has no attribute 'reconstruct_dense'
cause The specific function `reconstruct_dense` might not be directly exposed at the top level of the `pycolmap` module, or its name has changed/is part of a lower-level API.fixFor high-level reconstruction, use the `pycolmap.Sfm` class. For more granular control, consult `pycolmap`'s documentation for functions like `extract_features`, `match_features`, and `reconstruct` (lowercase `r` for the specific step).
Warnings
- gotcha Installation of `pycolmap[cuda]` (for GPU support) requires a CUDA Toolkit version that is compatible with COLMAP's C++ build. Incompatibilities between CUDA Toolkit, NVIDIA drivers, and `pycolmap` can lead to runtime errors or prevent GPU acceleration from being utilized.
- gotcha Building `pycolmap` from source is highly complex due to its extensive C++ dependencies (e.g., Ceres, Boost, Eigen, SuiteSparse). Using the pre-built wheels (`pip install pycolmap`) is strongly recommended to avoid intricate build environment issues.
- gotcha Mismatched `numpy` versions can lead to ABI compatibility errors (e.g., `ValueError: numpy.ndarray size changed`, `ImportError` related to `_multiarray_umath`), especially with C++ extensions like `pycolmap`. This happens when `pycolmap` is compiled against a different NumPy ABI than the one currently installed.
Install
-
pip install pycolmap -
pip install pycolmap[cuda]
Imports
- Sfm
from pycolmap import Sfm
- Camera
from pycolmap import Camera
- Image
from pycolmap import Image
- Point3D
from pycolmap import Point3D
- extract_features
from pycolmap import extract_features
- match_features
from pycolmap import match_features
- reconstruct
from pycolmap import reconstruct
Quickstart
import os
import pycolmap
import numpy as np
from PIL import Image
# Create a dummy image directory
image_dir = "pycolmap_quickstart_images"
output_dir = "pycolmap_quickstart_output"
os.makedirs(image_dir, exist_ok=True)
os.makedirs(output_dir, exist_ok=True)
# Create two dummy images (COLMAP typically needs more and with overlap)
img_size = (100, 100)
for i in range(2):
dummy_image = Image.fromarray(np.random.randint(0, 255, img_size + (3,), dtype=np.uint8))
dummy_image.save(os.path.join(image_dir, f"image_{i+1:02d}.jpg"))
print(f"Dummy images created in {image_dir}")
# Run the high-level SfM reconstruction
# Note: With only two random images, this is expected to fail or produce an empty model.
# A real scenario requires actual images with sufficient overlap and features.
try:
sfm_pipeline = pycolmap.Sfm(image_dir, output_dir)
reconstruction = sfm_pipeline.run()
if reconstruction:
print(f"Reconstruction successful! Found {len(reconstruction.images)} images and {len(reconstruction.points3D)} 3D points.")
else:
print("Reconstruction did not produce a valid model (expected for random, non-overlapping images).")
except Exception as e:
print(f"Reconstruction failed (expected for random images without overlap/features): {e}")
# Optional: Clean up created directories
# import shutil
# shutil.rmtree(image_dir, ignore_errors=True)
# shutil.rmtree(output_dir, ignore_errors=True)