This package exposes a single function, easy_sba, for running sparse bundle
adjustment from Python.
import numpy as np
from easysba import easy_sba
num_points = 10
num_cams = 4
rng = np.random.default_rng(0)
image_uv = rng.normal(scale=0.5, size=(num_points, num_cams, 2)).astype(np.float64)
visibility_mask = np.ones((num_points, num_cams), dtype=np.uint8)
world_xyz = rng.normal(scale=2.0, size=(num_points, 3)).astype(np.float64)
# 12-parameter cameras: [fu, u0, v0, ar, skew, qw, qx, qy, qz, tx, ty, tz]
camera_params = np.zeros((num_cams, 12), dtype=np.float64)
camera_params[:, 0] = 1.0 # fu
camera_params[:, 3] = 1.0 # aspect ratio
camera_params[:, 5] = 1.0 # quaternion w
camera_params[:, 9:] = rng.normal(scale=0.1, size=(num_cams, 3))
world_out, cams_out, info = easy_sba(
image_uv,
visibility_mask,
world_xyz,
camera_params,
intrinsics_fixed=5,
distortion_fixed=-1,
max_iter=50,
verbose=False,
)
print(info)world_out, cams_out, info = easy_sba(
image_uv,
visibility_mask,
world_xyz,
camera_params,
intrinsics_fixed=-1,
distortion_fixed=-1,
max_iter=150,
verbose=False,
)-
image_uv- Either shape
(num_points, num_cams, 2)or(num_points, num_cams * 2). - Must be
float64. - For invisible measurements, set
visibility_maskto 0 and store NaNs at the correspondingimage_uvlocation.
- Either shape
-
visibility_mask- Shape
(num_points, num_cams). uint8, with nonzero values for visible projections.
- Shape
-
world_xyz- Shape
(num_points, 3). float64.
- Shape
-
camera_params- Shape
(num_cams, num_camera_params). float64.num_camera_paramsmust be 7, 12, or 17.
- Shape
-
7 parameters (default intrinsics):
[qw, qx, qy, qz, tx, ty, tz]- Intrinsics are assumed to be
[fu=1, u0=0, v0=0, ar=1, skew=0].
-
12 parameters (fixed intrinsics in array):
[fu, u0, v0, ar, skew, qw, qx, qy, qz, tx, ty, tz]
-
17 parameters (intrinsics + distortion):
[fu, u0, v0, ar, skew, k1, k2, p1, p2, k3, qw, qx, qy, qz, tx, ty, tz]
Notes:
- Quaternions are normalized internally. A zero-norm quaternion raises an error.
- Translation is in the camera coordinate system used by the projection model in the SBA implementation.
-
intrinsics_fixed- Controls which intrinsics are held fixed.
- Must be
-1for 7-parameter cameras (intrinsics not provided). - For 12- or 17-parameter cameras, use values 0..5 as defined by SBA.
- Common choice is
5to fix all intrinsics.
-
distortion_fixed- Controls which distortion parameters are held fixed for 17-parameter cameras.
- Use
-1to free all distortion params, or 0..5 to fix subsets. - For 7- or 12-parameter cameras, use
-1.
-
max_iter- Maximum LM iterations.
-
verbose- Print iteration details.
world_out: optimized 3D point array, shape(num_points, 3).cams_out: optimized camera parameters, same shape ascamera_params.info: dict with keys likereturn_code,initial_error,final_error,num_iterations.
- Provide reasonable initial guesses. BA is non-convex and sensitive to initialization.
- Use NaNs in
image_uvfor masked entries; the visibility mask must match. - Start with
max_iter=1to validate inputs and shapes.
To run the optional solver tests:
EASYSBA_RUN_SOLVER=1 pytest