def resect(graph, graph_inliers, reconstruction, shot_id, camera, metadata, threshold, min_inliers): """Try resecting and adding a shot to the reconstruction. Return: True on success. """ bs, Xs, ids = [], [], [] for track in graph[shot_id]: if track in reconstruction.points: x = graph[track][shot_id]['feature'] b = camera.pixel_bearing(x) bs.append(b) Xs.append(reconstruction.points[track].coordinates) ids.append(track) bs = np.array(bs) Xs = np.array(Xs) if len(bs) < 5: return False, {'num_common_points': len(bs)} T = multiview.absolute_pose_ransac( bs, Xs, b"KNEIP", 1 - np.cos(threshold), 1000, 0.999) R = T[:, :3] t = T[:, 3] reprojected_bs = R.T.dot((Xs - t).T).T reprojected_bs /= np.linalg.norm(reprojected_bs, axis=1)[:, np.newaxis] inliers = np.linalg.norm(reprojected_bs - bs, axis=1) < threshold ninliers = int(sum(inliers)) logger.info("{} resection inliers: {} / {}".format( shot_id, ninliers, len(bs))) report = { 'num_common_points': len(bs), 'num_inliers': ninliers, } if ninliers >= min_inliers: R = T[:, :3].T t = -R.dot(T[:, 3]) shot = types.Shot() shot.id = shot_id shot.camera = camera shot.pose = types.Pose() shot.pose.set_rotation_matrix(R) shot.pose.translation = t shot.metadata = metadata reconstruction.add_shot(shot) for i, succeed in enumerate(inliers): if succeed: copy_graph_data(graph, graph_inliers, shot_id, ids[i]) return True, report else: return False, report
def resect(graph, reconstruction, shot_id, camera, metadata, threshold, min_inliers): """Try resecting and adding a shot to the reconstruction. Return: True on success. """ bs = [] Xs = [] for track in graph[shot_id]: if track in reconstruction.points: x = graph[track][shot_id]['feature'] b = camera.pixel_bearing(x) bs.append(b) Xs.append(reconstruction.points[track].coordinates) bs = np.array(bs) Xs = np.array(Xs) if len(bs) < 5: return False, {'num_common_points': len(bs)} T = multiview.absolute_pose_ransac( bs, Xs, b"KNEIP", 1 - np.cos(threshold), 1000, 0.999) R = T[:, :3] t = T[:, 3] reprojected_bs = R.T.dot((Xs - t).T).T reprojected_bs /= np.linalg.norm(reprojected_bs, axis=1)[:, np.newaxis] inliers = np.linalg.norm(reprojected_bs - bs, axis=1) < threshold ninliers = int(sum(inliers)) logger.info("{} resection inliers: {} / {}".format( shot_id, ninliers, len(bs))) report = { 'num_common_points': len(bs), 'num_inliers': ninliers, } if ninliers >= min_inliers: R = T[:, :3].T t = -R.dot(T[:, 3]) shot = types.Shot() shot.id = shot_id shot.camera = camera shot.pose = types.Pose() shot.pose.set_rotation_matrix(R) shot.pose.translation = t shot.metadata = metadata reconstruction.add_shot(shot) return True, report else: return False, report
def resect(tracks_manager, reconstruction, shot_id, camera, metadata, threshold, min_inliers): """Try resecting and adding a shot to the reconstruction. Return: True on success. """ bs, Xs, ids = [], [], [] for track, obs in tracks_manager.get_shot_observations(shot_id).items(): if track in reconstruction.points: b = camera.pixel_bearing(obs.point) bs.append(b) Xs.append(reconstruction.points[track].coordinates) ids.append(track) bs = np.array(bs) Xs = np.array(Xs) if len(bs) < 5: return False, {"num_common_points": len(bs)} T = multiview.absolute_pose_ransac(bs, Xs, threshold, 1000, 0.999) R = T[:, :3] t = T[:, 3] reprojected_bs = R.T.dot((Xs - t).T).T reprojected_bs /= np.linalg.norm(reprojected_bs, axis=1)[:, np.newaxis] inliers = np.linalg.norm(reprojected_bs - bs, axis=1) < threshold ninliers = int(sum(inliers)) logger.info("{} resection inliers: {} / {}".format(shot_id, ninliers, len(bs))) report = { "num_common_points": len(bs), "num_inliers": ninliers, } if ninliers >= min_inliers: R = T[:, :3].T t = -R.dot(T[:, 3]) assert shot_id not in reconstruction.shots shot = reconstruction.create_shot(shot_id, camera.id, pygeometry.Pose(R, t)) shot.metadata = metadata for i, succeed in enumerate(inliers): if succeed: add_observation_to_reconstruction(tracks_manager, reconstruction, shot_id, ids[i]) return True, report else: return False, report
def resect( data: DataSetBase, tracks_manager: pymap.TracksManager, reconstruction: types.Reconstruction, shot_id: str, threshold: float, min_inliers: int, ) -> Tuple[bool, Set[str], Dict[str, Any]]: """Try resecting and adding a shot to the reconstruction. Return: True on success. """ rig_assignments = data.load_rig_assignments_per_image() camera = reconstruction.cameras[data.load_exif(shot_id)["camera"]] bs, Xs, ids = [], [], [] for track, obs in tracks_manager.get_shot_observations(shot_id).items(): if track in reconstruction.points: b = camera.pixel_bearing(obs.point) bs.append(b) Xs.append(reconstruction.points[track].coordinates) ids.append(track) bs = np.array(bs) Xs = np.array(Xs) if len(bs) < 5: return False, set(), {"num_common_points": len(bs)} T = multiview.absolute_pose_ransac(bs, Xs, threshold, 1000, 0.999) R = T[:, :3] t = T[:, 3] reprojected_bs = R.T.dot((Xs - t).T).T reprojected_bs /= np.linalg.norm(reprojected_bs, axis=1)[:, np.newaxis] inliers = np.linalg.norm(reprojected_bs - bs, axis=1) < threshold ninliers = int(sum(inliers)) logger.info("{} resection inliers: {} / {}".format(shot_id, ninliers, len(bs))) report = { "num_common_points": len(bs), "num_inliers": ninliers, } if ninliers >= min_inliers: R = T[:, :3].T t = -R.dot(T[:, 3]) assert shot_id not in reconstruction.shots new_shots = add_shot(data, reconstruction, rig_assignments, shot_id, pygeometry.Pose(R, t)) if shot_id in rig_assignments: triangulate_shot_features(tracks_manager, reconstruction, new_shots, data.config) for i, succeed in enumerate(inliers): if succeed: add_observation_to_reconstruction(tracks_manager, reconstruction, shot_id, ids[i]) # pyre-fixme [6]: Expected `int` for 2nd positional report["shots"] = list(new_shots) return True, new_shots, report else: return False, set(), report
def resect_image(im, camera, gcps, reconstruction, data, dst_reconstruction=None): """ Resect an image into a reconstruction based only on GCPs annotations. Pass another reconstruction to dst_reconstruction if you want the resected points to be added there instead Returns: The resected shot. """ threshold = 0.01 min_inliers = 3 bs, Xs = [], [] for gcp in gcps: obs = _gcp_image_observation(gcp, im) if not obs: continue gcp_3d_coords = orec.triangulate_gcp(gcp, reconstruction.shots) if gcp_3d_coords is None: continue b = camera.pixel_bearing(obs.projection) bs.append(b) Xs.append(gcp_3d_coords) bs = np.array(bs) Xs = np.array(Xs) if len(bs) < min_inliers: print(f"Not enough annotations to resect image {im}") return None T = multiview.absolute_pose_ransac(bs, Xs, threshold, 1000, 0.999) R = T[:, :3] t = T[:, 3] reprojected_bs = R.T.dot((Xs - t).T).T reprojected_bs /= np.linalg.norm(reprojected_bs, axis=1)[:, np.newaxis] inliers = np.linalg.norm(reprojected_bs - bs, axis=1) < threshold ninliers = int(sum(inliers)) logger.info(f"{im} resection inliers: {ninliers} / {len(bs)}") if dst_reconstruction is None: dst_reconstruction = reconstruction if ninliers >= min_inliers: R = T[:, :3].T t = -R.dot(T[:, 3]) dst_reconstruction.add_camera(camera) shot = dst_reconstruction.create_shot(im, camera.id, pygeometry.Pose(R, t)) shot.metadata = orec.get_image_metadata(data, im) return shot else: print(f"Not enough inliers to resect image {im}") return None