Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

SfmData

Created by Codex.

Collect Cal3Bundler cameras and three-dimensional tracks, and turn them into structure-from-motion (SfM) bundle-adjustment graphs.

Open In Colab

Mathematical idea

Bundle adjustment estimates cameras CiC_i and landmarks PjP_j by minimizing reprojection error,

min{Ci},{Pj}(i,j)Ozijπ(Ci,Pj)Σij2,\min_{\{C_i\},\{P_j\}}\sum_{(i,j)\in\mathcal O} \left\lVert z_{ij}-\pi(C_i,P_j)\right\rVert_{\Sigma_{ij}}^2,

where O\mathcal O is the observation set. SfmData stores exactly the cameras, points, and observations needed to construct this graph. BAL means Bundle Adjustment in the Large, a standard dataset and file format used by these examples.

import gtsam
import numpy as np

from gtsam import symbol_shorthand

C = symbol_shorthand.C
K = symbol_shorthand.K
P = symbol_shorthand.P
S = symbol_shorthand.S
X = symbol_shorthand.X

Dataset model

SfmData is the central BAL/Bundler-style container. Camera indices in each track address cameraList(). Use FromBalFile or FromBundlerFile for existing datasets, or populate the container directly.

generalSfmFactors() returns only measurement factors. sfmFactorGraph() can additionally fix a camera and point to remove the similarity gauge. Passing None for either fixed index disables that constraint.

data = gtsam.SfmData()
calibration = gtsam.Cal3Bundler(500.0, 0.0, 0.0, 0.0, 0.0)
camera = gtsam.PinholeCameraCal3Bundler(gtsam.Pose3(), calibration)
data.addCamera(camera)

track = gtsam.SfmTrack(np.array([0.0, 0.0, 5.0]))
track.addMeasurement(0, np.array([0.0, 0.0]))
data.addTrack(track)

graph = data.sfmFactorGraph()
print("cameras:", data.numberCameras())
print("tracks:", data.numberTracks())
print("graph factors:", graph.size())
cameras: 1
tracks: 1
graph factors: 3

Loading and initialization

For a BAL file, a typical start is:

data = gtsam.SfmData.FromBalFile(filename)
graph = data.sfmFactorGraph()
initial = gtsam.initialCamerasAndPointsEstimate(data)

For the fastest current CPU bundle-adjustment path, use the point-batched C++ construction described in ../sfm.md; SfmData.sfmFactorGraph() creates one projection factor per observation.