def scene_synthetic_triangulation() -> synthetic_scene.SyntheticInputData: np.random.seed(42) reference = geo.TopocentricConverter(47.0, 6.0, 0) data = synthetic_examples.synthetic_circle_scene(reference) maximum_depth = 40 projection_noise = 1.0 gps_noise = 0.1 imu_noise = 1.0 gcp_noise = (0.0, 0.0) gcps_count = 10 gcps_shift = [10.0, 0.0, 100.0] return synthetic_scene.SyntheticInputData( data.get_reconstruction(), reference, maximum_depth, projection_noise, gps_noise, imu_noise, gcp_noise, False, gcps_count, gcps_shift, )
def load_reference(self) -> geo.TopocentricConverter: """Load reference as a topocentric converter.""" with self.io_handler.open_rt(self._reference_lla_path()) as fin: lla = io.json_load(fin) return geo.TopocentricConverter(lla["latitude"], lla["longitude"], lla["altitude"])
def generate_exifs(reconstruction, gps_noise, speed_ms=10): """Generate fake exif metadata from the reconstruction.""" previous_pose = None previous_time = 0 exifs = {} reference = geo.TopocentricConverter(0, 0, 0) for shot_name in sorted(reconstruction.shots.keys()): shot = reconstruction.shots[shot_name] exif = {} exif['width'] = shot.camera.width exif['height'] = shot.camera.height exif['focal_ratio'] = shot.camera.focal exif['camera'] = str(shot.camera.id) exif['make'] = str(shot.camera.id) pose = shot.pose.get_origin() if previous_pose is not None: previous_time += np.linalg.norm(pose-previous_pose)*speed_ms previous_pose = pose exif['capture_time'] = previous_time perturb_points([pose], [gps_noise, gps_noise, gps_noise]) _, _, _, comp = rc.shot_lla_and_compass(shot, reference) lat, lon, alt = reference.to_lla(*pose) exif['gps'] = {} exif['gps']['latitude'] = lat exif['gps']['longitude'] = lon exif['gps']['altitude'] = alt exif['gps']['dop'] = gps_noise exif['compass'] = {'angle': comp} exifs[shot_name] = exif return exifs
def add_cluster_neighbors(positions, labels, centers, max_distance): reflla = np.mean(positions, 0) reference = geo.TopocentricConverter(reflla[0], reflla[1], 0) topocentrics = [] for position in positions: x, y, z = reference.to_topocentric(position[0], position[1], 0) topocentrics.append([x, y]) topocentrics = np.array(topocentrics) topo_tree = spatial.cKDTree(topocentrics) clusters = [] for label in np.arange(centers.shape[0]): cluster_indices = np.where(labels == label)[0] neighbors = [] for i in cluster_indices: neighbors.extend( topo_tree.query_ball_point(topocentrics[i], max_distance)) cluster = list(np.union1d(cluster_indices, neighbors)) clusters.append(cluster) return clusters
def reconstruction_from_json(obj: Dict[str, Any]) -> types.Reconstruction: """ Read a reconstruction from a json object """ reconstruction = types.Reconstruction() # Extract cameras for key, value in obj["cameras"].items(): camera = camera_from_json(key, value) reconstruction.add_camera(camera) # Extract camera biases if "biases" in obj: for key, value in obj["biases"].items(): transform = bias_from_json(value) reconstruction.set_bias(key, transform) # Extract rig models if "rig_cameras" in obj: for key, value in obj["rig_cameras"].items(): reconstruction.add_rig_camera(rig_camera_from_json(key, value)) # Extract rig instances from shots if "rig_instances" in obj: for key, value in obj["rig_instances"].items(): rig_instance_from_json(reconstruction, key, value) # Extract shots rig_shots = rig_instance_camera_per_shot(obj) for key, value in obj["shots"].items(): shot_in_reconstruction_from_json( reconstruction, key, value, rig_camera_id=rig_shots[key][1] if key in rig_shots else None, rig_instance_id=rig_shots[key][0] if key in rig_shots else None, is_pano_shot=False, ) # Extract points if "points" in obj: for key, value in obj["points"].items(): point_from_json(reconstruction, key, value) # Extract pano_shots if "pano_shots" in obj: for key, value in obj["pano_shots"].items(): shot_in_reconstruction_from_json( reconstruction, key, value, is_pano_shot=True ) # Extract reference topocentric frame if "reference_lla" in obj: lla = obj["reference_lla"] reconstruction.reference = geo.TopocentricConverter( lla["latitude"], lla["longitude"], lla["altitude"] ) return reconstruction
def scene_synthetic_cube(): np.random.seed(42) data = synthetic_examples.synthetic_cube_scene() reference = geo.TopocentricConverter(47.0, 6.0, 0) reconstruction = data.get_reconstruction() input_data = synthetic_scene.SyntheticInputData(reconstruction, reference, 40, 0.0, 0.0, False) return reconstruction, input_data.tracks_manager
def test_get_gps_point() -> None: reference = geo.TopocentricConverter(0, 0, 0) exifs = {} exifs["gps"] = { "latitude": 0.0001, "longitude": 0.0001, "altitude": 100.0, } origin, direction = pairs_selection.get_gps_point(exifs, reference) assert np.allclose(origin, [[11.131, 11.057, 0.0]], atol=1e-3) assert np.allclose(direction, [[0, 0, 1]])
def reconstruction_from_json(obj: t.Dict[str, t.Any]): """ Read a reconstruction from a json object """ reconstruction = types.Reconstruction() # Extract cameras for key, value in obj["cameras"].items(): camera = camera_from_json(key, value) reconstruction.add_camera(camera) # Extract rig models if "rig_cameras" in obj: for key, value in obj["rig_cameras"].items(): reconstruction.add_rig_camera(rig_camera_from_json(key, value)) # Extract shots for key, value in obj["shots"].items(): shot_in_reconstruction_from_json(reconstruction, key, value) # Extract rig instances from shots if "rig_instances" in obj: for key, value in obj["rig_instances"].items(): rig_instance_from_json(reconstruction, key, value) # Extract points if "points" in obj: for key, value in obj["points"].items(): point_from_json(reconstruction, key, value) # Extract pano_shots if "pano_shots" in obj: for key, value in obj["pano_shots"].items(): is_pano_shot = True shot_in_reconstruction_from_json(reconstruction, key, value, is_pano_shot) # Extract main and unit shots if "main_shot" in obj: # pyre-fixme[16]: `types.Reconstruction` has no attribute `main_shot` reconstruction.main_shot = obj["main_shot"] if "unit_shot" in obj: # pyre-fixme[16]: `types.Reconstruction` has no attribute `unit_shot` reconstruction.unit_shot = obj["unit_shot"] # Extract reference topocentric frame if "reference_lla" in obj: lla = obj["reference_lla"] reconstruction.reference = geo.TopocentricConverter( lla["latitude"], lla["longitude"], lla["altitude"]) return reconstruction
def test_read_ground_control_points(): text = """ { "points": [ { "id": "1", "position": { "latitude": 52.519134104, "longitude": 13.400740745, "altitude": 12.0792090446 }, "observations": [ { "shot_id": "01.jpg", "projection": [0.7153, 0.5787] }, { "shot_id": "02.jpg", "projection": [0.8085, 0.3831] } ] }, { "id": "2", "position": { "latitude": 52.519251158, "longitude": 13.400502446, "altitude": 16.7021233002 }, "observations": [ { "shot_id": "01.jpg", "projection": [0.2346, 0.4628] } ] } ] } """ fp = StringIO(text) reference = geo.TopocentricConverter(52.51913, 13.4007, 0) points = io.read_ground_control_points(fp, reference) assert len(points) == 2 a, b = (len(point.observations) for point in points) assert min(a, b) == 1 assert max(a, b) == 2
def generate_exifs(reconstruction, gps_noise, speed_ms=10): """ Return extracted exif information, as dictionary, usually with fields: ================ ===== =================================== Field Type Description ================ ===== =================================== width int Width of image, in pixels height int Height of image, in pixels focal_prior float Focal length (real) / sensor width ================ ===== =================================== :param image: Image name, with extension (i.e. 123.jpg) """ previous_pose = None previous_time = 0 exifs = {} reference = geo.TopocentricConverter(0, 0, 0) for shot_name in sorted(reconstruction.shots.keys()): shot = reconstruction.shots[shot_name] exif = {} exif['width'] = shot.camera.width exif['height'] = shot.camera.height exif['focal_prior'] = shot.camera.focal_prior exif['camera'] = str(shot.camera.id) exif['make'] = str(shot.camera.id) pose = shot.pose.get_origin() if previous_pose is not None: previous_time += np.linalg.norm(pose - previous_pose) * speed_ms previous_pose = pose exif['capture_time'] = previous_time perturb_points([pose], [gps_noise, gps_noise, gps_noise]) shot_copy = copy.deepcopy(shot) shot_copy.pose.set_origin(pose) lat, lon, alt, comp = rc.shot_lla_and_compass(shot_copy, reference) exif['gps'] = {} exif['gps']['latitude'] = lat exif['gps']['longitude'] = lon exif['gps']['altitude'] = alt exif['gps']['dop'] = gps_noise exif['compass'] = {'angle': comp} exifs[shot_name] = exif return exifs
def reconstruction_from_json(obj): """ Read a reconstruction from a json object """ reconstruction = types.Reconstruction() # Extract alignment meta-data reconstruction.alignment = alignment_from_json(obj.get('alignment', None)) # Extract cameras for key, value in iteritems(obj['cameras']): camera = camera_from_json(key, value) reconstruction.add_camera(camera) # Extract shots for key, value in iteritems(obj['shots']): shot = shot_from_json(key, value, reconstruction.cameras) reconstruction.add_shot(shot) # Extract points if 'points' in obj: for key, value in iteritems(obj['points']): point = point_from_json(key, value) reconstruction.add_point(point) # Extract pano_shots if 'pano_shots' in obj: reconstruction.pano_shots = {} for key, value in iteritems(obj['pano_shots']): shot = shot_from_json(key, value, reconstruction.cameras) reconstruction.pano_shots[shot.id] = shot # Extract main and unit shots if 'main_shot' in obj: reconstruction.main_shot = obj['main_shot'] if 'main_shots' in obj: reconstruction.main_shots = obj['main_shots'] if 'unit_shot' in obj: reconstruction.unit_shot = obj['unit_shot'] # Extract reference topocentric frame if 'reference_lla' in obj: lla = obj['reference_lla'] reconstruction.reference = geo.TopocentricConverter( lla['latitude'], lla['longitude'], lla['altitude']) return reconstruction
def test_read_gcp_list(): text = """WGS84 13.400740745 52.519134104 12.0792090446 2335.0 1416.7 01.jpg 13.400740745 52.519134104 12.0792090446 2639.1 938.0 02.jpg 13.400502446 52.519251158 16.7021233002 766.0 1133.1 01.jpg """ fp = StringIO(text) reference = geo.TopocentricConverter(52.51913, 13.4007, 0) images = ["01.jpg", "02.jpg"] exif = {i: {"width": 3000, "height": 2000} for i in images} points = io.read_gcp_list(fp, reference, exif) assert len(points) == 2 a, b = (len(point.observations) for point in points) assert min(a, b) == 1 assert max(a, b) == 2
def scene_synthetic_rig() -> synthetic_scene.SyntheticInputData: np.random.seed(42) data = synthetic_examples.synthetic_rig_scene() maximum_depth = 40 projection_noise = 1.0 gps_noise = 0.1 reference = geo.TopocentricConverter(47.0, 6.0, 0) return synthetic_scene.SyntheticInputData( data.get_reconstruction(), reference, maximum_depth, projection_noise, gps_noise, False, )
def reconstruction_from_json(obj): """ Read a reconstruction from a json object """ reconstruction = types.Reconstruction() # Extract cameras for key, value in obj["cameras"].items(): camera = camera_from_json(key, value) reconstruction.add_camera(camera) # Extract shots for key, value in obj["shots"].items(): shot_from_json(reconstruction, key, value) # Extract points if "points" in obj: for key, value in obj["points"].items(): point_from_json(reconstruction, key, value) # Extract pano_shots if "pano_shots" in obj: for key, value in obj["pano_shots"].items(): is_pano_shot = True shot_from_json(reconstruction, key, value, is_pano_shot) # Extract main and unit shots if "main_shot" in obj: reconstruction.main_shot = obj["main_shot"] if "unit_shot" in obj: reconstruction.unit_shot = obj["unit_shot"] # Extract reference topocentric frame if "reference_lla" in obj: lla = obj["reference_lla"] reconstruction.reference = geo.TopocentricConverter( lla["latitude"], lla["longitude"], lla["altitude"] ) return reconstruction
def reconstruction_from_json(obj): """ Read a reconstruction from a json object """ reconstruction = types.Reconstruction() # Extract cameras for key, value in iteritems(obj['cameras']): camera = camera_from_json(key, value) reconstruction.add_camera(camera) # Extract shots for key, value in iteritems(obj['shots']): shot_from_json(reconstruction, key, value) # Extract points if 'points' in obj: for key, value in iteritems(obj['points']): point_from_json(reconstruction, key, value) # Extract pano_shots if 'pano_shots' in obj: for key, value in iteritems(obj['pano_shots']): is_pano_shot = True shot_from_json(reconstruction, key, value, is_pano_shot) # Extract main and unit shots if 'main_shot' in obj: reconstruction.main_shot = obj['main_shot'] if 'unit_shot' in obj: reconstruction.unit_shot = obj['unit_shot'] # Extract reference topocentric frame if 'reference_lla' in obj: lla = obj['reference_lla'] reconstruction.reference = geo.TopocentricConverter( lla['latitude'], lla['longitude'], lla['altitude']) return reconstruction
def invent_reference_from_gps_and_gcp( data: DataSetBase, images: Optional[List[str]] = None) -> geo.TopocentricConverter: lat, lon, alt = 0.0, 0.0, 0.0 wlat, wlon, walt = 0.0, 0.0, 0.0 if images is None: images = data.images() for image in images: d = data.load_exif(image) if "gps" in d and "latitude" in d["gps"] and "longitude" in d["gps"]: w = 1.0 / max(0.01, d["gps"].get("dop", 15)) lat += w * d["gps"]["latitude"] lon += w * d["gps"]["longitude"] wlat += w wlon += w if "altitude" in d["gps"]: alt += w * d["gps"]["altitude"] walt += w if not wlat and not wlon: for gcp in data.load_ground_control_points(): lat += gcp.lla["latitude"] lon += gcp.lla["longitude"] wlat += 1 wlon += 1 if gcp.has_altitude: alt += gcp.lla["altitude"] walt += 1 if wlat: lat /= wlat if wlon: lon /= wlon if walt: alt /= walt return geo.TopocentricConverter(lat, lon, 0) # Set altitude manually.
def pairs_and_poses(): np.random.seed(42) data = synthetic_examples.synthetic_cube_scene() reconstruction = data.get_reconstruction() reference = geo.TopocentricConverter(0, 0, 0) input_data = synthetic_scene.SyntheticInputData(reconstruction, reference, 40, 0.0, 0.0, False) features, tracks_manager = input_data.features, input_data.tracks_manager points_keys = list(reconstruction.points.keys()) pairs, poses = defaultdict(list), defaultdict(list) for im1, im2 in tracks_manager.get_all_pairs_connectivity(): tuples = tracks_manager.get_all_common_observations(im1, im2) f1 = [p.point for k, p, _ in tuples if k in points_keys] f2 = [p.point for k, _, p in tuples if k in points_keys] pairs[im1, im2].append((f1, f2)) pose1 = reconstruction.shots[im1].pose pose2 = reconstruction.shots[im2].pose poses[im1, im2] = pose2.relative_to(pose1) camera = list(reconstruction.cameras.values())[0] return pairs, poses, camera, features, tracks_manager, reconstruction
def test_eq_geo() -> None: assert geo.TopocentricConverter(40, 30, 0) == geo.TopocentricConverter(40, 30, 0) assert geo.TopocentricConverter(40, 32, 0) != geo.TopocentricConverter( 40, 30, 0)
def load_reference(self): """Load reference as a topocentric converter.""" lla = self.load_reference_lla() return geo.TopocentricConverter( lla['latitude'], lla['longitude'], lla['altitude'])
def load_reference(file_path): """Load reference as a topocentric converter.""" lla = load_reference_lla(file_path) return geo.TopocentricConverter( lla['latitude'], lla['longitude'], lla['altitude'])
def test_read_write_ground_control_points(): text = """ { "points": [ { "id": "1", "observations": [ { "shot_id": "01.jpg", "projection": [0.7153, 0.5787] }, { "shot_id": "02.jpg", "projection": [0.8085, 0.3831] } ] }, { "id": "2", "position": { "latitude": 52.519251158, "longitude": 13.400502446, "altitude": 16.7021233002 }, "observations": [ { "shot_id": "01.jpg", "projection": [0.2346, 0.4628] } ] } ] } """ def check_points(points): assert len(points) == 2 p1, p2 = points if p1.id != "1": p1, p2 = p2, p1 assert p1.coordinates.has_value is False assert len(p1.observations) == 2 assert np.allclose(p2.lla["latitude"], 52.519251158) assert np.allclose(p2.lla["longitude"], 13.400502446) assert np.allclose(p2.coordinates.value[2], 16.7021233002) assert len(p2.observations) == 1 reference = geo.TopocentricConverter(52.51913, 13.4007, 0) # Read json fp = StringIO(text) points = io.read_ground_control_points(fp, reference) check_points(points) # Write json and re-read fwrite = StringIO() io.write_ground_control_points(points, fwrite, reference) freread = StringIO(fwrite.getvalue()) points_reread = io.read_ground_control_points(freread, reference) check_points(points_reread)
def generate_exifs( reconstruction: types.Reconstruction, gps_noise: Union[Dict[str, float], float], causal_gps_noise: bool = False, ) -> Dict[str, Any]: """Generate fake exif metadata from the reconstruction.""" speed_ms = 10.0 previous_pose = None previous_time = 0 exifs = {} reference = geo.TopocentricConverter(0, 0, 0) def _gps_dop(shot): gps_dop = 15 if isinstance(gps_noise, float): gps_dop = gps_noise if isinstance(gps_noise, dict): gps_dop = gps_noise[shot.camera.id] return gps_dop per_sequence = defaultdict(list) for shot_name in sorted(reconstruction.shots.keys()): shot = reconstruction.shots[shot_name] exif = {} exif["width"] = shot.camera.width exif["height"] = shot.camera.height exif["camera"] = str(shot.camera.id) exif["make"] = str(shot.camera.id) exif["skey"] = str(shot.camera.id) per_sequence[exif["skey"]].append(shot_name) if shot.camera.projection_type in ["perspective", "fisheye"]: exif["focal_ratio"] = shot.camera.focal pose = shot.pose.get_origin() if previous_pose is not None: previous_time += np.linalg.norm(pose - previous_pose) * speed_ms previous_pose = pose exif["capture_time"] = previous_time exifs[shot_name] = exif for sequence_images in per_sequence.values(): if causal_gps_noise: sequence_gps_dop = _gps_dop( reconstruction.shots[sequence_images[0]]) perturbations_2d = generate_causal_noise(2, sequence_gps_dop, len(sequence_images), 2.0) for i, shot_name in enumerate(sequence_images): shot = reconstruction.shots[shot_name] exif = exifs[shot_name] pose = shot.pose.get_origin() if causal_gps_noise: gps_perturbation = [perturbations_2d[j][i] for j in range(2)] + [0] else: gps_noise = _gps_dop(shot) gps_perturbation = [gps_noise, gps_noise, 0] pose = np.array([pose]) perturb_points(pose, gps_perturbation) pose = pose[0] _, _, _, comp = rc.shot_lla_and_compass(shot, reference) lat, lon, alt = reference.to_lla(*pose) exif["gps"] = {} exif["gps"]["latitude"] = lat exif["gps"]["longitude"] = lon exif["gps"]["altitude"] = alt exif["gps"]["dop"] = _gps_dop(shot) exif["compass"] = {"angle": comp} return exifs
def load_reference(self) -> geo.TopocentricConverter: """Load reference as a topocentric converter.""" lla = self.load_reference_lla() return geo.TopocentricConverter(lla["latitude"], lla["longitude"], lla["altitude"])