Exemplo n.º 1
0
def rigs_calibrate_average(trajectories: Trajectories,
                           rigs: Rigs,
                           master_sensors: Optional[List[str]] = None) -> Rigs:
    """
    Recomputes rig calibrations, ie. the poses of the senors inside a rig.
    It uses the poses of the senors in the given trajectories, to average a average rig.

    :param trajectories:
    :param rigs:
    :param master_sensors:
    :return:
    """
    # senor_id -> rig_id
    sensors_to_rigs = {
        sensor_id: rig_id
        for rig_id, sensor_id in rigs.key_pairs()
    }

    show_progress_bar = logger.getEffectiveLevel() <= logging.INFO
    for timestamp, poses in tqdm(trajectories.items(),
                                 disable=not show_progress_bar):
        # accumulate relative poses inside rig
        for sensor_id, pose_sensor_from_world in poses.items():
            pass

    rigs_calibrated = Rigs()
    return rigs_calibrated
Exemplo n.º 2
0
def get_rigs_mapping(rigs: kapture.Rigs, offset: int = 0) -> Dict[str, str]:
    """
    Creates list of rig names,identifiers

    :param rigs: list of rig definitions
    :param offset: optional offset for the identifier numbers
    :return: mapping of rig names to identifiers
    """
    return {
        k: f'rig{v}'
        for k, v in zip(rigs.keys(), range(offset, offset + len(rigs)))
    }
Exemplo n.º 3
0
    def setUp(self) -> None:
        self.rigs_expected = Rigs()
        # kind of make a rosace around a central point
        nb_cams = 6
        rig_id = 'rig'
        rig_radius = 10
        camera_yaw_angles = np.linspace(0, 2 * np.pi, nb_cams + 1)[:-1]
        t = [0, 0, -rig_radius]
        for idx, cam_yaw_angle in enumerate(camera_yaw_angles):
            r = quaternion.from_rotation_vector([0, cam_yaw_angle, 0])
            pose_cam_from_rig = PoseTransform(t=t, r=r)
            self.rigs_expected[rig_id, f'cam{idx:02d}'] = pose_cam_from_rig

        # and for the trajectory, do random
        self.rigs_trajectories = Trajectories()
        nb_timestamps = 100
        timestamps = np.arange(0, nb_timestamps)
        orientations = np.random.uniform(-1, 1., size=(nb_timestamps, 4))
        positions = np.random.uniform(-100., 100., size=(nb_timestamps, 3))
        for ts, r, t in zip(timestamps, orientations, positions):
            pose_rig_from_world = PoseTransform(t=t, r=r).inverse()
            self.rigs_trajectories[int(ts), rig_id] = pose_rig_from_world
Exemplo n.º 4
0
def rigs_to_file(filepath: str, rigs: kapture.Rigs) -> None:
    """
    Writes rigs to CSV file.

    :param filepath:
    :param rigs:
    """
    assert (isinstance(rigs, kapture.Rigs))
    header = '# rig_id, sensor_id, qw, qx, qy, qz, tx, ty, tz'
    padding = PADDINGS['device_id'] + PADDINGS['device_id'] + PADDINGS['pose']
    table = ([rig_id, sensor_id] + pose_to_list(pose)
             for rig_id, rig in rigs.items()
             for sensor_id, pose in rig.items())

    os.makedirs(path.dirname(filepath), exist_ok=True)
    with open(filepath, 'w') as file:
        table_to_file(file, table, header=header, padding=padding)
Exemplo n.º 5
0
    def test_perfect(self):
        # create the trajectory with perfect transforms
        cameras_trajectories = Trajectories()
        for timestamp, rig_id, pose_rig_from_world in flatten(
                self.rigs_trajectories):
            for rig_id, cam_id, pose_cam_from_rig in flatten(
                    self.rigs_expected):
                assert rig_id == 'rig'
                pose_cam_from_world = PoseTransform.compose(
                    [pose_cam_from_rig, pose_rig_from_world])
                cameras_trajectories[timestamp, cam_id] = pose_cam_from_world

        rigs_unknown_geometry = Rigs()
        for rig_id, cam_id in self.rigs_expected.key_pairs():
            rigs_unknown_geometry[rig_id, cam_id] = PoseTransform()

        # calibrate
        rigs_recovered = rigs_calibrate_average(cameras_trajectories,
                                                rigs_unknown_geometry)
Exemplo n.º 6
0
class TestCalibrate(unittest.TestCase):
    def setUp(self) -> None:
        self.rigs_expected = Rigs()
        # kind of make a rosace around a central point
        nb_cams = 6
        rig_id = 'rig'
        rig_radius = 10
        camera_yaw_angles = np.linspace(0, 2 * np.pi, nb_cams + 1)[:-1]
        t = [0, 0, -rig_radius]
        for idx, cam_yaw_angle in enumerate(camera_yaw_angles):
            r = quaternion.from_rotation_vector([0, cam_yaw_angle, 0])
            pose_cam_from_rig = PoseTransform(t=t, r=r)
            self.rigs_expected[rig_id, f'cam{idx:02d}'] = pose_cam_from_rig

        # and for the trajectory, do random
        self.rigs_trajectories = Trajectories()
        nb_timestamps = 100
        timestamps = np.arange(0, nb_timestamps)
        orientations = np.random.uniform(-1, 1., size=(nb_timestamps, 4))
        positions = np.random.uniform(-100., 100., size=(nb_timestamps, 3))
        for ts, r, t in zip(timestamps, orientations, positions):
            pose_rig_from_world = PoseTransform(t=t, r=r).inverse()
            self.rigs_trajectories[int(ts), rig_id] = pose_rig_from_world

    def test_perfect(self):
        # create the trajectory with perfect transforms
        cameras_trajectories = Trajectories()
        for timestamp, rig_id, pose_rig_from_world in flatten(
                self.rigs_trajectories):
            for rig_id, cam_id, pose_cam_from_rig in flatten(
                    self.rigs_expected):
                assert rig_id == 'rig'
                pose_cam_from_world = PoseTransform.compose(
                    [pose_cam_from_rig, pose_rig_from_world])
                cameras_trajectories[timestamp, cam_id] = pose_cam_from_world

        rigs_unknown_geometry = Rigs()
        for rig_id, cam_id in self.rigs_expected.key_pairs():
            rigs_unknown_geometry[rig_id, cam_id] = PoseTransform()

        # calibrate
        rigs_recovered = rigs_calibrate_average(cameras_trajectories,
                                                rigs_unknown_geometry)
Exemplo n.º 7
0
def get_top_level_rig_ids(rigs: kapture.Rigs) -> List[str]:
    """
    get all top level rig ids (top level == only in the left column of rigs.txt)
    """
    rig_low_level = set().union(*[list(k.keys()) for k in rigs.values()])
    return [rigid for rigid in rigs.keys() if rigid not in rig_low_level]
Exemplo n.º 8
0
def export_colmap_rig_json(
        kapture_rigs: kapture.Rigs, records_camera: kapture.RecordsCamera,
        colmap_camera_ids: Dict[str, int]) -> List[Dict[str, list]]:
    """
    From colmap source code comments (colmap.cc:1401) :

    // Read the configuration of the camera rigs from a JSON file. The input images
    // of a camera rig must be named consistently to assign them to the appropriate
    // camera rig and the respective kapture image.
    //
    // An example configuration of a single camera rig:
    // [
    //   {
    //     "ref_camera_id": 1,
    //     "cameras":
    //     [
    //       {
    //           "camera_id": 1,
    //           "image_prefix": "left1_image"
    //       }, ...
    //     ]
    //   }
    // ]


    // This file specifies the configuration for a single camera rig and that you
    // could potentially define multiple camera rigs.


    Images with the same prefix ("left1_image/") are assigned to the same camera in the rig.
    Images with the same suffix ("_frame000.png" and "/frame000.png") are
    assigned to the same camera record, i.e., they are assumed to be captured at the same time.

    This code, try to retrieve prefix of images.

    :param kapture_rigs: kapture rigs to export
    :param records_camera: used to guess camera prefix: assume a directory per camera
    :param colmap_camera_ids: dict mapping sensor_id -> colmap_camera_ID
    :return: The structure as expected in the colmap json file.
    """

    colmap_rigs = []
    for rig_kapture in kapture_rigs.values():
        # rig[sensor_device_id] = <Pose>
        rig_colmap = {'cameras': []}
        for camera_id in rig_kapture:
            if camera_id not in colmap_camera_ids:
                # e.g. lidar0 and other sensors without record on disk
                logger.warning(f'Camera {camera_id} not in COLMAP cameras')
                continue
            colmap_camera_id = colmap_camera_ids[camera_id]
            # recover the image prefix :
            images_dir_paths = set(
                path.dirname(record_filepath) for _, sensor_id, record_filepath
                in kapture.flatten(records_camera) if sensor_id == camera_id)
            # check there is one, and only one image prefix (required by colmap).
            if not len(images_dir_paths) == 1:
                raise ValueError(
                    f'unable to find an image for camera {camera_id}')

            the_images_dirpath = next(iter(images_dir_paths))
            if not the_images_dirpath:
                raise ValueError(
                    f'unable to find prefix for images {the_images_dirpath}.')
            rig_colmap['cameras'].append({
                'camera_id': colmap_camera_id,
                'image_prefix': the_images_dirpath
            })
        rig_colmap['ref_camera_id'] = rig_colmap['cameras'][0]['camera_id']
        colmap_rigs.append(rig_colmap)

    return colmap_rigs