MCPcopy Create free account
hub / github.com/Improbable-AI/VisionProTeleop / calibrate_joint

Function calibrate_joint

scripts/stereo_calibration.py:780–1070  ·  view source on GitHub ↗

Perform joint intrinsic/extrinsic calibration using position-only constraints. This method uses multiple markers at different locations to simultaneously solve for camera intrinsics and the head-to-camera extrinsic transform. Uses differential evolution (global optimizer)

(
    session_dir: Path,
    intrinsic_calib: dict,
    optimize_intrinsics: bool = True,
    max_iterations: int = 100,
    use_global_optimizer: bool = True
)

Source from the content-addressed store, hash-verified

778
779
780def calibrate_joint(
781 session_dir: Path,
782 intrinsic_calib: dict,
783 optimize_intrinsics: bool = True,
784 max_iterations: int = 100,
785 use_global_optimizer: bool = True
786) -> dict:
787 """
788 Perform joint intrinsic/extrinsic calibration using position-only constraints.
789
790 This method uses multiple markers at different locations to simultaneously
791 solve for camera intrinsics and the head-to-camera extrinsic transform.
792
793 Uses differential evolution (global optimizer) to avoid local minima.
794
795 The cost function minimizes:
796 sum_t sum_i || T_b^v(t) @ T_v^c @ solvePnP(corners_i(t), K, D) - p_b^{m_i} ||²
797
798 Where p_b^{m_i} is the ground truth marker position in world frame.
799
800 Args:
801 session_dir: Path to session directory
802 intrinsic_calib: Initial intrinsic calibration dictionary (used for image size, not values)
803 optimize_intrinsics: Whether to also optimize intrinsics or just extrinsics
804 max_iterations: Maximum iterations for the optimizer
805 use_global_optimizer: If True, use differential evolution; else use LM
806
807 Returns:
808 Dictionary with optimized calibration results
809 """
810 from scipy.optimize import differential_evolution
811
812 extrinsic_dir = session_dir / "extrinsic"
813 if not extrinsic_dir.exists():
814 raise ValueError(f"Extrinsic directory not found: {extrinsic_dir}")
815
816 # Load session info for marker size
817 session_info = load_session_info(session_dir)
818 marker_size = session_info.get("marker_size_meters", 0.055)
819
820 # Get image size from intrinsic calib
821 img_width = intrinsic_calib.get("image_width", 640)
822 img_height = intrinsic_calib.get("image_height", 480)
823
824 # Marker 3D points in marker frame (centered at origin)
825 marker_3d_points = np.array([
826 [-marker_size / 2, marker_size / 2, 0],
827 [marker_size / 2, marker_size / 2, 0],
828 [marker_size / 2, -marker_size / 2, 0],
829 [-marker_size / 2, -marker_size / 2, 0]
830 ], dtype=np.float32)
831
832 # Collect observations for both cameras
833 results = {}
834
835 for side in ["left", "right"]:
836 print(f"\n{'='*60}")
837 print(f"JOINT CALIBRATION - {side.upper()} CAMERA")

Callers 1

Calls 14

load_session_infoFunction · 0.85
build_camera_matrixFunction · 0.85
build_distortion_coeffsFunction · 0.85
rvec_tvec_to_matrixFunction · 0.85
joint_calibration_costFunction · 0.85
keysMethod · 0.80
split_stereo_imageFunction · 0.70
printFunction · 0.50
floatFunction · 0.50
getMethod · 0.45
indexMethod · 0.45
reshapeMethod · 0.45

Tested by

no test coverage detected