def calibrate_intrinsic(args): paths = setup_paths(args.paths) setup_logging(args.runtime.log_level, [], log_file=paths.log_file) info(pformat_struct(args)) image_path = os.path.expanduser(args.paths.image_path) info(f"Finding images in {image_path}") camera_images = find_camera_images(image_path, args.paths.cameras, args.paths.camera_pattern, matching=False) image_counts = { k: len(files) for k, files in zip(camera_images.cameras, camera_images.filenames) } info("Found camera directories with images {}".format(image_counts)) board_names, boards = split_dict( find_board_config(image_path, args.paths.boards)) info("Loading images..") images = image.detect.load_images(camera_images.filenames, prefix=camera_images.image_path, j=args.runtime.num_threads) image_sizes = map_list(common_image_size, images) info({ k: image_size for k, image_size in zip(camera_images.cameras, image_sizes) }) cache_key = struct(boards=boards, image_sizes=image_sizes, filenames=camera_images.filenames) detected_points = detect_boards_cached(boards, images, paths.detections, cache_key, j=args.runtime.num_threads) cameras, errs = calibrate_cameras(boards, detected_points, image_sizes, model=args.camera.distortion_model, fix_aspect=args.camera.fix_aspect, has_skew=args.camera.allow_skew, max_images=args.camera.limit_intrinsic) for name, camera, err in zip(camera_images.cameras, cameras, errs): info(f"Calibrated {name}, with RMS={err:.2f}") info(camera) info("") info(f"Writing single calibrations to {paths.calibration_file}") export_single(paths.calibration_file, cameras, camera_images.cameras, camera_images.filenames)
def setup_paths(paths): output_path = paths.image_path or paths.output_path temp_folder = pathlib.Path(output_path).joinpath("." + paths.name) temp_folder.mkdir(exist_ok=True, parents=True) return struct(output=output_path, temp=str(temp_folder), calibration_file=path.join(output_path, f"{paths.name}.json"), log_file=str(temp_folder.joinpath("log.txt")), detections=str(temp_folder.joinpath("detections.pkl")))
def matching_points(points, board, cam1, cam2): points1, points2 = points._index[cam1], points._index[cam2] matching = [] for i, j in zip(points1._sequence(0), points2._sequence(0)): row1, row2, ids = common_entries(i, j) matching.append( struct(points1=row1.points, points2=row2.points, object_points=board.points[ids], ids=ids)) return transpose_structs(matching)
def initialise_poses(pose_table): # Find relative transforms between cameras and rig poses camera = estimate_relative_poses(pose_table, axis=0) board = estimate_relative_poses_inv(pose_table, axis=2) # solve for the rig transforms cam @ rig @ board = pose # first take inverse of both sides by board pose # cam @ rig = board_relative = pose @ board^-1 board_relative = multiply_tables(pose_table, expand(inverse(board), [0, 1]) ) # solve for unknown rig expanded = broadcast_to(expand(camera, [1, 2]), board_relative) times = relative_between_n(expanded, board_relative, axis=1, inv=True) return struct(times=times, camera=camera, board=board)
def initialise_poses(pose_table, camera_poses=None): # Find relative transforms between cameras and rig poses camera = estimate_relative_poses(pose_table, axis=0) if camera_poses is not None: info("Camera initialisation vs. supplied calibration") report_poses("camera", camera_poses, camera.poses) camera = Table.create(poses=camera_poses, valid=np.ones(camera_poses.shape[0], dtype=np.bool)) board = estimate_relative_poses_inv(pose_table, axis=2) # solve for the rig transforms cam @ rig @ board = pose # first take inverse of both sides by board pose # cam @ rig = board_relative = pose @ board^-1 board_relative = multiply_tables(pose_table, expand(inverse(board), [0, 1])) # solve for unknown rig expanded = broadcast_to(expand(camera, [1, 2]), board_relative) times = relative_between_n(expanded, board_relative, axis=1, inv=True) return struct(times=times, camera=camera, board=board)
def extract_points(frame_dets): points, mask = fill_sparse(num_points, frame_dets.corners, frame_dets.ids) return struct(points=points, valid=mask)
def pad_points(board): points = board.adjusted_points.astype(np.float64) return struct(points=np.pad(points, [(0, padded_points - points.shape[0]), (0, 0)]), valid=np.arange(padded_points) < board.num_points)
def valid_pose(t): return struct(poses=t, valid=True)
def sparse_points(points): ids = np.flatnonzero(points.valid) return struct(corners=points.points[ids], ids=ids)
def fill_sparse_tile(n, values, ids, tile): assert tile.shape == values.shape[1:] dense = np.broadcast_to(np.expand_dims(tile, 0), (n, *tile.shape)).copy() dense[ids] = values mask = np.full(n, False) mask[ids] = True return dense, mask def sparse_points(points): ids = np.flatnonzero(points.valid) return struct(corners=points.points[ids], ids=ids) invalid_pose = struct(poses=np.eye(4), num_points=0, valid=False) def valid_pose(t): return struct(poses=t, valid=True) def extract_pose(points, board, camera): detections = sparse_points(points) poses = board.estimate_pose_points(camera, detections) return valid_pose(rtvec.to_matrix(poses))._extend(num_points=len(detections.ids))\ if poses is not None else invalid_pose def map_table(f, point_table, boards, cameras):