The Problem
Standard Structure-from-Motion pipelines assume pinhole or fisheye camera models. Spherical cameras (Insta360, Ricoh Theta) capture 360° imagery in equirectangular projection (ERP), which breaks those assumptions—lines curve, distortion is extreme, and naive feature extraction fails. SphereSfM extends COLMAP to run incremental SfM directly on ERP images, producing sparse reconstructions for urban scenes where spherical capture is common.
What This Does
SphereSfM is a fork of COLMAP (itself forked from json87/SphereSfM) that adds a SPHERE camera model, a spherical feature extractor, and a sphere_cubic_reprojector for converting reconstructions to cubic format for dense matching. The core changes live in src/ (411 files) alongside the COLMAP codebase, with the spherical logic integrated into the existing feature extraction and mapping stages.
The repo ships with three test datasets (campus parterre, campus building, urban street) and a Dockerfile for containerized builds. A README.md documents a six-step CLI workflow from database creation through cubic conversion.
How It Is Wired
The pipeline is the standard COLMAP sequence, modified at two points. Entry is colmap database_creator, then feature_extractor with --ImageReader.camera_model SPHERE and --ImageReader.camera_params "1,3520,1760" (focal length, width, height). The spherical camera model is registered in src/ alongside the existing models. Feature matching via spatial_matcher uses POS data when available, falling back to vocabulary-tree matching. The mapper runs incremental SfM with --Mapper.sphere_camera 1 and camera parameters held fixed (--Mapper.ba_refine_focal_length 0). Finally, sphere_cubic_reprojecer converts the sparse model for downstream dense matching.
The import graph shows 22 internal Python modules with zero import edges—the Python scripts in scripts/python/ are standalone utilities (build, bundler conversion, database handling). The C++ core is where the real control flow lives, but the static analysis did not map C++ call graphs. No hub modules or cycles were detected in the Python layer.
How To Use It
Setup: Build requires CUDA 11.7 and the COLMAP dependency stack. The docker/Dockerfile pins nvcr.io/nvidia/cuda:11.7.0-devel-ubuntu22.04; docker/build.sh and docker/quick-start.sh handle the container build. Native builds follow COLMAP's CMake flow (CMakeLists.txt at root, cmake/ for helper modules).
Configuration: No environment variables. Camera parameters, POS data, and masks are passed as CLI flags to feature_extractor.
Running it (verbatim from README.md):
colmap database_creator --database_path ./colmap/database.db
colmap feature_extractor \
--database_path ./colmap/database.db \
--image_path ./images \
--ImageReader.camera_model SPHERE \
--ImageReader.camera_params "1,3520,1760" \
--ImageReader.single_camera 1 \
--ImageReader.camera_mask_path ./camera_mask.png \
--ImageReader.pose_path ./POS.txt
colmap spatial_matcher \
--database_path ./colmap/database.db \
--SiftMatching.max_error 4 \
--SiftMatching.min_num_inliers 50 \
--SpatialMatching.is_gps 0 \
--SpatialMatching.max_distance 50
colmap mapper \
--database_path ./colmap/database.db \
--image_path ./images \
--output_path ./colmap/sparse \
--Mapper.ba_refine_focal_length 0 \
--Mapper.ba_refine_principal_point 0 \
--Mapper.ba_refine_extra_params 0 \
--Mapper.sphere_camera 1
colmap gui --database_path ./colmap/database.db --image_path ./images --import_path ./colmap/sparse/0
colmap sphere_cubic_reprojecer --image_path ./images --in...
Real-World Use
A street-level survey captures 2,000 ERP images from a vehicle-mounted Insta360. The team runs the five-step CLI workflow, using GPS-derived POS data for spatial matching. The resulting sparse reconstruction is converted to cubic format and fed into COLMAP's dense matching stage, producing a 3D mesh of building facades without manual camera calibration.
Code Health & Issues
Static analysis (350 findings: 246 high, 104 medium) reports one dominant issue:
- High - Deep nesting (x60) -
lib/LSD/lsd.c,lib/PoissonRecon/MultiGridOctreeData.h,lib/PoissonRecon/PlyFile.cppreach max indentation depth 11; control flow is hard to follow. Fix: early returns and extracted inner blocks.
Additional SDLC observations from the audit:
- High - No CI pipeline - 79 source files, no workflow in
.github/or.azure-pipelines/(the latter has build configs but they are not wired as gates). Every change merges unbuilt. - High - No build gate for Docker image -
docker/Dockerfileexists but no workflow validates it. - Medium - Unpinned base image -
docker/Dockerfileusesnvcr.io/nvidia/cuda:11.7.0-devel-ubuntu22.04without a digest; builds are non-reproducible. - Medium - No timeout on outbound calls -
scripts/python/build.pymakes requests withouttimeout=. - Medium - Test coverage is minimal - 3 test files against 277 source files (ratio 0.011).
The Bottom Line
SphereSfM is a functional research-grade extension of COLMAP for spherical imagery, with working datasets and documented commands. It inherits COLMAP's build complexity, adds no CI, and ships with negligible test coverage—treat it as a reference implementation rather than production software. Teams needing spherical SfM should evaluate it against COLMAP's native support before committing.