def add_shots_to_reconstruction( shots: List[List[str]], positions: List[np.ndarray], rotations: List[np.ndarray], rig_cameras: List[pymap.RigCamera], cameras: List[pygeometry.Camera], reconstruction: types.Reconstruction, sequence_key: str, ): for camera in cameras: reconstruction.add_camera(camera) rec_rig_cameras = [] for rig_camera in rig_cameras: rec_rig_cameras.append(reconstruction.add_rig_camera(rig_camera)) for i_shots, position, rotation in zip(shots, positions, rotations): instance_id = "_".join([s[0] for s in i_shots]) rig_instance = reconstruction.add_rig_instance(pymap.RigInstance(instance_id)) rig_instance.pose = pygeometry.Pose(rotation, -rotation.dot(position)) for shot, camera in zip(i_shots, cameras): shot_id = shot[0] rig_camera_id = shot[1] shot = reconstruction.create_shot( shot_id, camera.id, pose=None, rig_camera_id=rig_camera_id, rig_instance_id=instance_id, ) shot.metadata.sequence_key.value = sequence_key
def add_shot(data, reconstruction, rig_assignments, shot_id, pose): """Add a shot to the recontruction. In case of a shot belonging to a rig instance, the pose of shot will drive the initial pose setup of the rig instance. All necessary shots and rig models will be created. """ added_shots = [] if shot_id not in rig_assignments: camera_id = data.load_exif(shot_id)["camera"] shot = reconstruction.create_shot(shot_id, camera_id, pose) shot.metadata = get_image_metadata(data, shot_id) added_shots = [shot_id] else: rig_model_id, instance_id, _, instance_shots = rig_assignments[shot_id] created_shots = {} for shot in instance_shots: camera_id = data.load_exif(shot)["camera"] created_shots[shot] = reconstruction.create_shot( shot, camera_id, pygeometry.Pose()) created_shots[shot].metadata = get_image_metadata(data, shot) rig_instance = reconstruction.add_rig_instance( pymap.RigInstance(reconstruction.rig_models[rig_model_id], instance_id)) for shot in instance_shots: _, _, rig_camera_id, _ = rig_assignments[shot] rig_instance.add_shot(rig_camera_id, created_shots[shot]) rig_instance.update_instance_pose_with_shot(shot_id, pose) added_shots = instance_shots return added_shots
def create_shot( self, shot_id: str, camera_id: str, pose: Optional[pygeometry.Pose] = None, rig_camera_id: Optional[str] = None, rig_instance_id: Optional[str] = None, ) -> pymap.Shot: passed_rig_camera_id = rig_camera_id if rig_camera_id else camera_id passed_rig_instance_id = rig_instance_id if rig_instance_id else shot_id if (not rig_camera_id) and (camera_id not in self.rig_cameras): self.add_rig_camera(pymap.RigCamera(pygeometry.Pose(), camera_id)) if passed_rig_camera_id not in self.rig_cameras: raise RuntimeError( f"Rig Camera {passed_rig_camera_id} doesn't exist in reconstruction" ) if (not rig_instance_id) and (shot_id not in self.rig_instances): self.add_rig_instance(pymap.RigInstance(shot_id)) if passed_rig_instance_id not in self.rig_instances: raise RuntimeError( f"Rig Instance {passed_rig_instance_id} doesn't exist in reconstruction" ) if pose is None: created_shot = self.map.create_shot(shot_id, camera_id, passed_rig_camera_id, passed_rig_instance_id) else: created_shot = self.map.create_shot(shot_id, camera_id, passed_rig_camera_id, passed_rig_instance_id, pose) return created_shot
def _create_rig_instance(): rec = _create_reconstruction(1, {"0": 2}) rig_model = rec.add_rig_model(_create_rig_model()) rig_instance = pymap.RigInstance(rig_model, 1) shot = pymap.Shot("0", pygeometry.Camera.create_spherical(), pygeometry.Pose()) rig_instance.add_shot("rig_camera", shot) return rec, rig_instance, shot
def _reconstruction_from_rigs_and_assignments(data: DataSetBase): assignments = data.load_rig_assignments() rig_cameras = data.load_rig_cameras() data.init_reference() reconstruction = types.Reconstruction() reconstruction.cameras = data.load_camera_models() for rig_instance_id, instance in assignments.items(): for image, rig_camera_id in instance: rig_camera = rig_cameras[rig_camera_id] reconstruction.add_rig_camera( pymap.RigCamera(rig_camera.pose, rig_camera_id)) instance_obj = reconstruction.add_rig_instance( pymap.RigInstance(rig_instance_id)) instance_obj.pose.set_origin( helpers.get_image_metadata(data, image).gps_position.value) d = data.load_exif(image) shot = reconstruction.create_shot( image, camera_id=d["camera"], rig_camera_id=rig_camera_id, rig_instance_id=rig_instance_id, ) shot.metadata = helpers.get_image_metadata(data, image) return [reconstruction]
def test_rig_instance(): rig_model = _create_rig_model() rig_instance = pymap.RigInstance(rig_model) shot = pymap.Shot("0", pygeometry.Camera.create_spherical(), pygeometry.Pose()) rig_instance.add_shot("rig_camera", shot) assert list(rig_instance.keys()) == ["0"]
def add_rigs_to_reconstruction(shots, positions, rotations, model, reconstruction): rig_model = reconstruction.add_rig_model(model) for i, (i_shots, position, rotation) in enumerate(zip(shots, positions, rotations)): rig_instance = reconstruction.add_rig_instance( pymap.RigInstance(rig_model, i)) for s in i_shots: rig_instance.add_shot(s[1], reconstruction.get_shot(s[0])) rig_instance.pose = pygeometry.Pose(rotation, -rotation.dot(position))
def rig_instance_from_json( reconstruction: types.Reconstruction, instance_id: str, obj: Dict[str, Any] ) -> None: """ Read any rig instance from a json shot object """ reconstruction.add_rig_instance(pymap.RigInstance(instance_id)) pose = pygeometry.Pose() pose.rotation = obj["rotation"] pose.translation = obj["translation"] reconstruction.rig_instances[instance_id].pose = pose
def test_rig_instance_create(): rec = _create_reconstruction(1, {"0": 2}) rig_model = _create_rig_model() rig_instance = pymap.RigInstance(rig_model) shot = pymap.Shot("0", pygeometry.Camera.create_spherical(), pygeometry.Pose()) rig_instance.add_shot("rig_camera", shot) rec.add_rig_instance(rig_instance) assert len(rec.rig_instances) == 1 assert list(rec.rig_models.keys()) == ["rig_model"] assert list(rec.rig_instances[0].shots.keys()) == ["0"]
def perspective_views_of_a_panorama( spherical_shot: pymap.Shot, width: int, reconstruction: types.Reconstruction, image_format: str, rig_instance_count: Iterator[int], ) -> List[pymap.Shot]: """Create 6 perspective views of a panorama.""" camera = pygeometry.Camera.create_perspective(0.5, 0.0, 0.0) camera.id = "perspective_panorama_camera" camera.width = width camera.height = width reconstruction.add_camera(camera) names = ["front", "left", "back", "right", "top", "bottom"] rotations = [ tf.rotation_matrix(-0 * np.pi / 2, np.array([0, 1, 0])), tf.rotation_matrix(-1 * np.pi / 2, np.array([0, 1, 0])), tf.rotation_matrix(-2 * np.pi / 2, np.array([0, 1, 0])), tf.rotation_matrix(-3 * np.pi / 2, np.array([0, 1, 0])), tf.rotation_matrix(-np.pi / 2, np.array([1, 0, 0])), tf.rotation_matrix(+np.pi / 2, np.array([1, 0, 0])), ] rig_instance = reconstruction.add_rig_instance( pymap.RigInstance(str(next(rig_instance_count))) ) shots = [] for name, rotation in zip(names, rotations): if name not in reconstruction.rig_cameras: rig_camera_pose = pygeometry.Pose() rig_camera_pose.set_rotation_matrix(rotation[:3, :3]) rig_camera = pymap.RigCamera(rig_camera_pose, name) reconstruction.add_rig_camera(rig_camera) rig_camera = reconstruction.rig_cameras[name] shot_id = add_image_format_extension( f"{spherical_shot.id}_perspective_view_{name}", image_format ) shot = reconstruction.create_shot( shot_id, camera.id, pygeometry.Pose(), rig_camera.id, rig_instance.id ) shot.metadata = spherical_shot.metadata shots.append(shot) rig_instance.pose = spherical_shot.pose return shots
def rig_instance_from_json(reconstruction, key, obj): """ Read any rig instance from a json shot object """ instance_id = int(key) reconstruction.add_rig_instance(pymap.RigInstance(instance_id)) pose = pygeometry.Pose() pose.rotation = obj["rotation"] pose.translation = obj["translation"] reconstruction.rig_instances[instance_id].pose = pose for shot_id, rig_camera_id in obj["rig_camera_ids"].items(): reconstruction.rig_instances[instance_id].add_shot( reconstruction.rig_cameras[rig_camera_id], reconstruction.shots[shot_id])
def add_rigs_to_reconstruction(shots, positions, rotations, rig_cameras, reconstruction): rec_rig_cameras = [] for rig_camera in rig_cameras: if rig_camera.id not in reconstruction.rig_cameras: rec_rig_cameras.append(reconstruction.add_rig_camera(rig_camera)) else: rec_rig_cameras.append(reconstruction.rig_cameras[rig_camera.id]) for i, (i_shots, position, rotation) in enumerate(zip(shots, positions, rotations)): rig_instance = reconstruction.add_rig_instance(pymap.RigInstance(i)) for j, s in enumerate(i_shots): rig_instance.add_shot(rec_rig_cameras[j], reconstruction.get_shot(s[0])) rig_instance.pose = pygeometry.Pose(rotation, -rotation.dot(position))
def create_pano_shot(self, shot_id: str, camera_id: str, pose: Optional[pygeometry.Pose] = None) -> pymap.Shot: if pose is None: pose = pygeometry.Pose() rig_camera_id = f"{PANOSHOT_RIG_PREFIX}{camera_id}" if rig_camera_id not in self.rig_cameras: self.add_rig_camera( pymap.RigCamera(pygeometry.Pose(), rig_camera_id)) rig_instance_id = f"{PANOSHOT_RIG_PREFIX}{shot_id}" if rig_instance_id not in self.rig_instances: self.add_rig_instance(pymap.RigInstance(rig_instance_id)) created_shot = self.map.create_pano_shot(shot_id, camera_id, rig_camera_id, rig_instance_id, pose) return created_shot
def add_shot( data: DataSetBase, reconstruction: types.Reconstruction, rig_assignments: Dict[str, Tuple[int, str, List[str]]], shot_id: str, pose: pygeometry.Pose, ) -> Set[str]: """Add a shot to the recontruction. In case of a shot belonging to a rig instance, the pose of shot will drive the initial pose setup of the rig instance. All necessary shots and rig models will be created. """ added_shots = set() if shot_id not in rig_assignments: camera_id = data.load_exif(shot_id)["camera"] shot = reconstruction.create_shot(shot_id, camera_id, pose) shot.metadata = get_image_metadata(data, shot_id) added_shots = {shot_id} else: instance_id, _, instance_shots = rig_assignments[shot_id] created_shots = {} for shot in instance_shots: camera_id = data.load_exif(shot)["camera"] created_shots[shot] = reconstruction.create_shot( shot, camera_id, pygeometry.Pose() ) created_shots[shot].metadata = get_image_metadata(data, shot) rig_instance = reconstruction.add_rig_instance(pymap.RigInstance(instance_id)) for shot in instance_shots: _, rig_camera_id, _ = rig_assignments[shot] rig_instance.add_shot( reconstruction.rig_cameras[rig_camera_id], created_shots[shot] ) rig_instance.update_instance_pose_with_shot(shot_id, pose) added_shots = set(instance_shots) return added_shots
def perspective_views_of_a_panorama(spherical_shot, width, reconstruction, image_format, rig_instance_count): """Create 6 perspective views of a panorama.""" camera = pygeometry.Camera.create_perspective(0.5, 0.0, 0.0) camera.id = "perspective_panorama_camera" camera.width = width camera.height = width reconstruction.add_camera(camera) names = ["front", "left", "back", "right", "top", "bottom"] rotations = [ tf.rotation_matrix(-0 * np.pi / 2, (0, 1, 0)), tf.rotation_matrix(-1 * np.pi / 2, (0, 1, 0)), tf.rotation_matrix(-2 * np.pi / 2, (0, 1, 0)), tf.rotation_matrix(-3 * np.pi / 2, (0, 1, 0)), tf.rotation_matrix(-np.pi / 2, (1, 0, 0)), tf.rotation_matrix(+np.pi / 2, (1, 0, 0)), ] rig_instance = pymap.RigInstance(next(rig_instance_count)) rig_instance.pose = spherical_shot.pose shots = [] for name, rotation in zip(names, rotations): if name not in reconstruction.rig_cameras: rig_camera_pose = pygeometry.Pose() rig_camera_pose.set_rotation_matrix(rotation[:3, :3]) rig_camera = pymap.RigCamera(rig_camera_pose, name) reconstruction.add_rig_camera(rig_camera) rig_camera = reconstruction.rig_cameras[name] shot_id = add_image_format_extension( f"{spherical_shot.id}_perspective_view_{name}", image_format) shot = reconstruction.create_shot(shot_id, camera.id) rig_instance.add_shot(rig_camera, shot) shots.append(shot) reconstruction.add_rig_instance(rig_instance) return shots
def reconstruction_from_metadata(data: DataSetBase, images: Iterable[str]) -> types.Reconstruction: """Initialize a reconstruction by using EXIF data for constructing shot poses and cameras.""" data.init_reference() rig_assignments = rig.rig_assignments_per_image(data.load_rig_assignments()) reconstruction = types.Reconstruction() reconstruction.reference = data.load_reference() reconstruction.cameras = data.load_camera_models() for image in images: camera_id = data.load_exif(image)["camera"] if image in rig_assignments: rig_instance_id, rig_camera_id, _ = rig_assignments[image] else: rig_instance_id = image rig_camera_id = camera_id reconstruction.add_rig_camera(pymap.RigCamera(pygeometry.Pose(), rig_camera_id)) reconstruction.add_rig_instance(pymap.RigInstance(rig_instance_id)) shot = reconstruction.create_shot( shot_id=image, camera_id=camera_id, rig_camera_id=rig_camera_id, rig_instance_id=rig_instance_id, ) shot.metadata = get_image_metadata(data, image) if not shot.metadata.gps_position.has_value: reconstruction.remove_shot(image) continue gps_pos = shot.metadata.gps_position.value shot.pose.set_rotation_matrix(rotation_from_shot_metadata(shot)) shot.pose.set_origin(gps_pos) shot.scale = 1.0 return reconstruction