#!/usr/bin/env python3 """ Step 1 — Feature detection for calibration. Detects chessboard corners (and ellipse centers for IR when needed) and writes one JSON per image next to the source file in the same camera folder. """ import sys from pathlib import Path sys.path.insert(0, str(Path.home() / "Speckle-Scanner")) sys.path.insert(0, str(Path(__file__).resolve().parent)) import argparse from calibrationclasses.cli_common import ( add_board_args, add_session_args, add_troubleshooting_arg, build_board_config, resolve_input_path, ) from calibrationclasses.feature_detection import DetectionConfig, run_detection def main(): parser = argparse.ArgumentParser( description="Calibration step 1: detect features and save per-image JSON" ) add_session_args(parser) add_board_args(parser) parser.add_argument( "--cameras", type=str, default=None, help="Comma-separated camera folders to process (default: all present)", ) parser.add_argument( "--ir_mode", choices=("auto", "chessboard", "ellipse"), default="auto", help="IR detection: try chessboard first (auto), or force one mode", ) add_troubleshooting_arg(parser) args = parser.parse_args() board_sizes, square_sizes = build_board_config(args) per_camera_board = { name: {"board_size": board_sizes[name], "square_size": square_sizes[name]} for name in board_sizes } cameras = None if args.cameras: cameras = [c.strip() for c in args.cameras.split(",") if c.strip()] config = DetectionConfig( chessboard_size=args.chessboard_size, square_size=args.square_size, preprocessing=args.preprocessing, ir_mode=args.ir_mode, troubleshooting=args.troubleshooting, ) input_path = resolve_input_path(args) print(f"[detect] session: {input_path}") run_detection(input_path, config, cameras=cameras, per_camera_board=per_camera_board) print("[detect] done") if __name__ == "__main__": main()