def bootstrap_reconstruction(data, graph, im1, im2, p1, p2): """Start a reconstruction using two shots.""" logger.info("Starting reconstruction with {} and {}".format(im1, im2)) report = { 'image_pair': (im1, im2), 'common_tracks': len(p1), } cameras = data.load_camera_models() camera1 = cameras[data.load_exif(im1)['camera']] camera2 = cameras[data.load_exif(im2)['camera']] threshold = data.config['five_point_algo_threshold'] min_inliers = data.config['five_point_algo_min_inliers'] R, t, inliers, report['two_view_reconstruction'] = \ two_view_reconstruction_general(p1, p2, camera1, camera2, threshold) logger.info("Two-view reconstruction inliers: {} / {}".format( len(inliers), len(p1))) if len(inliers) <= 5: report['decision'] = "Could not find initial motion" logger.info(report['decision']) return None, report reconstruction = types.Reconstruction() reconstruction.reference = data.load_reference() reconstruction.cameras = cameras shot1 = types.Shot() shot1.id = im1 shot1.camera = camera1 shot1.pose = types.Pose() shot1.metadata = get_image_metadata(data, im1) reconstruction.add_shot(shot1) shot2 = types.Shot() shot2.id = im2 shot2.camera = camera2 shot2.pose = types.Pose(R, t) shot2.metadata = get_image_metadata(data, im2) reconstruction.add_shot(shot2) triangulate_shot_features(graph, reconstruction, im1, data.config) logger.info("Triangulated: {}".format(len(reconstruction.points))) report['triangulated_points'] = len(reconstruction.points) if len(reconstruction.points) < min_inliers: report['decision'] = "Initial motion did not generate enough points" logger.info(report['decision']) return None, report bundle_single_view(graph, reconstruction, im2, data.config) retriangulate(graph, reconstruction, data.config) bundle_single_view(graph, reconstruction, im2, data.config) report['decision'] = 'Success' report['memory_usage'] = current_memory_usage() return reconstruction, report
def bootstrap_reconstruction(data, tracks_manager, camera_priors, im1, im2, p1, p2): """Start a reconstruction using two shots.""" logger.info("Starting reconstruction with {} and {}".format(im1, im2)) report = { 'image_pair': (im1, im2), 'common_tracks': len(p1), } camera_id1 = data.load_exif(im1)['camera'] camera_id2 = data.load_exif(im2)['camera'] camera1 = camera_priors[camera_id1] camera2 = camera_priors[camera_id2] threshold = data.config['five_point_algo_threshold'] min_inliers = data.config['five_point_algo_min_inliers'] iterations = data.config['five_point_refine_rec_iterations'] R, t, inliers, report['two_view_reconstruction'] = \ two_view_reconstruction_general( p1, p2, camera1, camera2, threshold, iterations) logger.info("Two-view reconstruction inliers: {} / {}".format( len(inliers), len(p1))) if len(inliers) <= 5: report['decision'] = "Could not find initial motion" logger.info(report['decision']) return None, report reconstruction = types.Reconstruction() reconstruction.reference = data.load_reference() reconstruction.cameras = camera_priors shot1 = reconstruction.create_shot(im1, camera_id1, pygeometry.Pose()) shot1.metadata = get_image_metadata(data, im1) shot2 = reconstruction.create_shot(im2, camera_id2, pygeometry.Pose(R, t)) shot2.metadata = get_image_metadata(data, im2) triangulate_shot_features(tracks_manager, reconstruction, im1, data.config) logger.info("Triangulated: {}".format(len(reconstruction.points))) report['triangulated_points'] = len(reconstruction.points) if len(reconstruction.points) < min_inliers: report['decision'] = "Initial motion did not generate enough points" logger.info(report['decision']) return None, report bundle_single_view(reconstruction, im2, camera_priors, data.config) retriangulate(tracks_manager, reconstruction, data.config) if len(reconstruction.points) < min_inliers: report['decision'] = "Re-triangulation after initial motion did not generate enough points" logger.info(report['decision']) return None, report bundle_single_view(reconstruction, im2, camera_priors, data.config) report['decision'] = 'Success' report['memory_usage'] = current_memory_usage() return reconstruction, report
def clean_depthmap(arguments): """Clean depthmap by checking consistency with neighbors.""" log.setup() data, udata, neighbors, shot = arguments # if udata.clean_depthmap_exists(shot.id): # logger.info("Using precomputed clean depthmap {}".format(shot.id)) # return logger.info("Cleaning depthmap for image {}".format(shot.id)) dc = pydense.DepthmapCleaner() dc.set_same_depth_threshold(udata.config['depthmap_same_depth_threshold']) dc.set_min_consistent_views(udata.config['depthmap_min_consistent_views']) add_views_to_depth_cleaner(data,udata, neighbors, dc) depth = dc.clean() # Save and display results raw_depth, raw_plane, raw_score, raw_nghbr, nghbrs = data.load_raw_depthmap(shot.id) udata.save_clean_depthmap(shot.id, depth, raw_plane, raw_score) depthmap={} depthmap.update({'depth':depth}) depthmap.update({'plane':raw_plane}) depthmap.update({'score':raw_score}) data.save_clean_depthmap(shot.id, depthmap) #cleaned_depthmap.update({shot.id:depthmap}) if udata.config['depthmap_save_debug_files']: image = data.udata_image[shot.id]#load_undistorted_image(shot.id) # opencv는 BGR로 받아서 계산 image = scale_down_image(image, depth.shape[1], depth.shape[0]) ply = depthmap_to_ply(shot, depth, image) data.save_clean_ply(shot.id,ply) #cleaned_ply.update({shot.id:ply}) with io.open_wt(udata._depthmap_file(shot.id, 'clean.npz.ply')) as fout: fout.write(ply) print('available memory== ', memory_available()) print("current memory usage==", current_memory_usage())
def merge_depthmaps(data, reconstruction): """Merge depthmaps into a single point cloud.""" logger.info("Merging depthmaps") shot_ids = [s for s in reconstruction.shots] if not shot_ids: logger.warning("Depthmaps contain no points. Try using more images.") return points = [] normals = [] colors = [] labels = [] detections = [] for shot_id in shot_ids: p, n, c, l, d = data.load_pruned_depthmap(shot_id) points.append(p) normals.append(n) colors.append(c) labels.append(l) detections.append(d) points = np.concatenate(points) normals = np.concatenate(normals) colors = np.concatenate(colors) labels = np.concatenate(labels) detections = np.concatenate(detections) with io.open_wt(data._depthmap_path() + '/merged.ply') as fp: point_cloud_to_ply(points, normals, colors, labels, detections, fp) print('available memory== ', memory_available()) print("current memory usage==", current_memory_usage()) ply= io.reconstruction_to_ply(data.reconstructions_as_json) with io.open_wt(data._depthmap_path() + '/SLAM.ply') as fout: fout.write(ply)
def grow_reconstruction(data, graph, reconstruction, images, gcp): """Incrementally add shots to an initial reconstruction.""" config = data.config report = {'steps': []} bundle(graph, reconstruction, None, config) remove_outliers(graph, reconstruction, config) align_reconstruction(reconstruction, gcp, config) should_bundle = ShouldBundle(data, reconstruction) should_retriangulate = ShouldRetriangulate(data, reconstruction) while True: if config['save_partial_reconstructions']: paint_reconstruction(data, graph, reconstruction) data.save_reconstruction( [reconstruction], 'reconstruction.{}.json'.format( datetime.datetime.now().isoformat().replace(':', '_'))) candidates = reconstructed_points_for_images( graph, reconstruction, images) if not candidates: break logger.info("-------------------------------------------------------") threshold = data.config['resection_threshold'] min_inliers = data.config['resection_min_inliers'] for image, num_tracks in candidates: camera = reconstruction.cameras[data.load_exif(image)['camera']] metadata = get_image_metadata(data, image) ok, resrep = resect(graph, reconstruction, image, camera, metadata, threshold, min_inliers) if not ok: continue bundle_single_view(graph, reconstruction, image, data.config) logger.info("Adding {0} to the reconstruction".format(image)) step = { 'image': image, 'resection': resrep, 'memory_usage': current_memory_usage() } report['steps'].append(step) images.remove(image) np_before = len(reconstruction.points) triangulate_shot_features(graph, reconstruction, image, config) np_after = len(reconstruction.points) step['triangulated_points'] = np_after - np_before if should_retriangulate.should(): logger.info("Re-triangulating") b1rep = bundle(graph, reconstruction, None, config) rrep = retriangulate(graph, reconstruction, config) b2rep = bundle(graph, reconstruction, None, config) remove_outliers(graph, reconstruction, config) align_reconstruction(reconstruction, gcp, config) step['bundle'] = b1rep step['retriangulation'] = rrep step['bundle_after_retriangulation'] = b2rep should_retriangulate.done() should_bundle.done() elif should_bundle.should(): brep = bundle(graph, reconstruction, None, config) remove_outliers(graph, reconstruction, config) align_reconstruction(reconstruction, gcp, config) step['bundle'] = brep should_bundle.done() elif config['local_bundle_radius'] > 0: brep = bundle_local(graph, reconstruction, None, image, config) remove_outliers(graph, reconstruction, config) step['local_bundle'] = brep break else: logger.info("Some images can not be added") break logger.info("-------------------------------------------------------") bundle(graph, reconstruction, gcp, config) remove_outliers(graph, reconstruction, config) align_reconstruction(reconstruction, gcp, config) paint_reconstruction(data, graph, reconstruction) return reconstruction, report
def bootstrap_reconstruction( data: DataSetBase, tracks_manager: pymap.TracksManager, im1: str, im2: str, p1: np.ndarray, p2: np.ndarray, ) -> Tuple[Optional[types.Reconstruction], Dict[str, Any]]: """Start a reconstruction using two shots.""" logger.info("Starting reconstruction with {} and {}".format(im1, im2)) report: Dict[str, Any] = { "image_pair": (im1, im2), "common_tracks": len(p1), } camera_priors = data.load_camera_models() camera1 = camera_priors[data.load_exif(im1)["camera"]] camera2 = camera_priors[data.load_exif(im2)["camera"]] threshold = data.config["five_point_algo_threshold"] min_inliers = data.config["five_point_algo_min_inliers"] iterations = data.config["five_point_refine_rec_iterations"] R, t, inliers, report[ "two_view_reconstruction"] = two_view_reconstruction_general( p1, p2, camera1, camera2, threshold, iterations) logger.info("Two-view reconstruction inliers: {} / {}".format( len(inliers), len(p1))) if len(inliers) <= 5: report["decision"] = "Could not find initial motion" logger.info(report["decision"]) return None, report rig_camera_priors = data.load_rig_cameras() rig_assignments = data.load_rig_assignments_per_image() reconstruction = types.Reconstruction() reconstruction.reference = data.load_reference() reconstruction.cameras = camera_priors reconstruction.rig_cameras = rig_camera_priors new_shots = add_shot(data, reconstruction, rig_assignments, im1, pygeometry.Pose()) if im2 not in new_shots: new_shots |= add_shot(data, reconstruction, rig_assignments, im2, pygeometry.Pose(R, t)) align_reconstruction(reconstruction, None, data.config) triangulate_shot_features(tracks_manager, reconstruction, new_shots, data.config) logger.info("Triangulated: {}".format(len(reconstruction.points))) report["triangulated_points"] = len(reconstruction.points) if len(reconstruction.points) < min_inliers: report["decision"] = "Initial motion did not generate enough points" logger.info(report["decision"]) return None, report to_adjust = {s for s in new_shots if s != im1} bundle_shot_poses(reconstruction, to_adjust, camera_priors, rig_camera_priors, data.config) retriangulate(tracks_manager, reconstruction, data.config) if len(reconstruction.points) < min_inliers: report[ "decision"] = "Re-triangulation after initial motion did not generate enough points" logger.info(report["decision"]) return None, report bundle_shot_poses(reconstruction, to_adjust, camera_priors, rig_camera_priors, data.config) report["decision"] = "Success" report["memory_usage"] = current_memory_usage() return reconstruction, report
def grow_reconstruction( data: DataSetBase, tracks_manager: pymap.TracksManager, reconstruction: types.Reconstruction, images: Set[str], gcp: List[pymap.GroundControlPoint], ) -> Tuple[types.Reconstruction, Dict[str, Any]]: """Incrementally add shots to an initial reconstruction.""" config = data.config report = {"steps": []} camera_priors = data.load_camera_models() rig_camera_priors = data.load_rig_cameras() paint_reconstruction(data, tracks_manager, reconstruction) align_reconstruction(reconstruction, gcp, config) bundle(reconstruction, camera_priors, rig_camera_priors, None, config) remove_outliers(reconstruction, config) paint_reconstruction(data, tracks_manager, reconstruction) should_bundle = ShouldBundle(data, reconstruction) should_retriangulate = ShouldRetriangulate(data, reconstruction) while True: if config["save_partial_reconstructions"]: paint_reconstruction(data, tracks_manager, reconstruction) data.save_reconstruction( [reconstruction], "reconstruction.{}.json".format( datetime.datetime.now().isoformat().replace(":", "_")), ) candidates = reconstructed_points_for_images(tracks_manager, reconstruction, images) if not candidates: break logger.info("-------------------------------------------------------") threshold = data.config["resection_threshold"] min_inliers = data.config["resection_min_inliers"] for image, _ in candidates: ok, new_shots, resrep = resect( data, tracks_manager, reconstruction, image, threshold, min_inliers, ) if not ok: continue images -= new_shots bundle_shot_poses( reconstruction, new_shots, camera_priors, rig_camera_priors, data.config, ) logger.info( f"Adding {' and '.join(new_shots)} to the reconstruction") step = { "images": list(new_shots), "resection": resrep, "memory_usage": current_memory_usage(), } report["steps"].append(step) np_before = len(reconstruction.points) triangulate_shot_features(tracks_manager, reconstruction, new_shots, config) np_after = len(reconstruction.points) step["triangulated_points"] = np_after - np_before if should_retriangulate.should(): logger.info("Re-triangulating") align_reconstruction(reconstruction, gcp, config) b1rep = bundle(reconstruction, camera_priors, rig_camera_priors, None, config) rrep = retriangulate(tracks_manager, reconstruction, config) b2rep = bundle(reconstruction, camera_priors, rig_camera_priors, None, config) remove_outliers(reconstruction, config) step["bundle"] = b1rep step["retriangulation"] = rrep step["bundle_after_retriangulation"] = b2rep should_retriangulate.done() should_bundle.done() elif should_bundle.should(): align_reconstruction(reconstruction, gcp, config) brep = bundle(reconstruction, camera_priors, rig_camera_priors, None, config) remove_outliers(reconstruction, config) step["bundle"] = brep should_bundle.done() elif config["local_bundle_radius"] > 0: bundled_points, brep = bundle_local( reconstruction, camera_priors, rig_camera_priors, None, image, config, ) remove_outliers(reconstruction, config, bundled_points) step["local_bundle"] = brep break else: logger.info("Some images can not be added") break logger.info("-------------------------------------------------------") align_reconstruction(reconstruction, gcp, config) bundle(reconstruction, camera_priors, rig_camera_priors, gcp, config) remove_outliers(reconstruction, config) paint_reconstruction(data, tracks_manager, reconstruction) return reconstruction, report
def compute_depthmaps(data, udata, graph, reconstruction): """Compute and refine depthmaps for all shots. Args: udata: an UndistortedDataset graph: the tracks graph reconstruction: the undistorted reconstruction """ logger.info('Computing neighbors') config = udata.config processes = config['processes'] num_neighbors = config['depthmap_num_neighbors'] print('available memory== ', memory_available()) print("current memory usage==", current_memory_usage()) neighbors = {} common_tracks = common_tracks_double_dict(graph) for shot in reconstruction.shots.values(): neighbors[shot.id] = find_neighboring_images( shot, common_tracks, reconstruction, num_neighbors) arguments = [] for shot in reconstruction.shots.values(): if len(neighbors[shot.id]) <= 1: continue mind, maxd = compute_depth_range(graph, reconstruction, shot, config) arguments.append((data, udata, neighbors[shot.id], mind, maxd, shot)) #parallel_map_thread(compute_depthmap_catched, arguments, processes) parallel_map(compute_depthmap_catched, arguments, processes) # data.save_raw_depthmap(raw_depthmap) # data.save_raw_ply(raw_ply) arguments = [] for shot in reconstruction.shots.values(): if len(neighbors[shot.id]) <= 1: continue arguments.append((data ,udata, neighbors[shot.id], shot)) #parallel_map_thread(clean_depthmap_catched, arguments, processes) parallel_map(clean_depthmap_catched, arguments, processes) # data.save_clean_depthmap(cleaned_depthmap) # data.save_clean_ply(cleaned_ply) arguments = [] for shot in reconstruction.shots.values(): if len(neighbors[shot.id]) <= 1: continue arguments.append((data, udata, neighbors[shot.id], shot)) #parallel_map_thread(prune_depthmap_catched, arguments, processes) parallel_map(prune_depthmap_catched, arguments, processes) # data.save_pruned_depthmap(pruned_depthmap) # data.save_ply_line(pruned_ply) merge_depthmaps(data, reconstruction)
def compute_depthmap(arguments): """Compute depthmap for a single shot.""" log.setup() data, udata, neighbors, min_depth, max_depth, shot = arguments method = udata.config['depthmap_method'] if udata.raw_depthmap_exists(shot.id): logger.info("Using precomputed raw depthmap {}".format(shot.id)) return logger.info("Computing depthmap for image {0} with {1}".format(shot.id, method)) hp=hpy() before=hp.heap() de = pydense.DepthmapEstimator() de.set_depth_range(min_depth, max_depth, 100) de.set_patchmatch_iterations(udata.config['depthmap_patchmatch_iterations']) de.set_patch_size(udata.config['depthmap_patch_size']) de.set_min_patch_sd(udata.config['depthmap_min_patch_sd']) add_views_to_depth_estimator(data,udata, neighbors, de) if (method == 'BRUTE_FORCE'): depth, plane, score, nghbr = de.compute_brute_force() elif (method == 'PATCH_MATCH'): depth, plane, score, nghbr = de.compute_patch_match() elif (method == 'PATCH_MATCH_SAMPLE'): depth, plane, score, nghbr = de.compute_patch_match_sample() else: raise ValueError( 'Unknown depthmap method type ' '(must be BRUTE_FORCE, PATCH_MATCH or PATCH_MATCH_SAMPLE)') good_score = score > udata.config['depthmap_min_correlation_score'] depth = depth * (depth < max_depth) * good_score # Save and display results neighbor_ids = [i.id for i in neighbors[1:]] udata.save_raw_depthmap(shot.id, depth, plane, score, nghbr, neighbor_ids) depthmap={} depthmap.update({'depth':depth}) depthmap.update({'plane':plane}) depthmap.update({'score':score}) depthmap.update({'nghbr':nghbr}) depthmap.update({'nghbrs':neighbor_ids}) #raw_depthmap.update({shot.id:depthmap}) data.save_raw_depthmap(shot.id, depthmap) # after=hp.heap() # leftover=after-before # objgraph.show_most_common_types() # pdb.set_trace() # after1=hp.heap() # leftover1=after1-before # exit() # print(data) # print("pid == ",os.getpid()) # print("depthmap== ", hex(id(depthmap))) # print("raw_depthmap== ", hex(id(raw_depthmap))) if udata.config['depthmap_save_debug_files']: image = data.udata_image[shot.id] #load_undistorted_image(shot.id) #image[:, :, :3] = image[:, :, [2, 1, 0]] image = scale_down_image(image, depth.shape[1], depth.shape[0]) ply = depthmap_to_ply(shot, depth, image) # raw_ply.update({shot.id:ply}) # print("ply== ", hex(id(ply))) # print("raw_ply== ", hex(id(raw_ply))) with io.open_wt(udata._depthmap_file(shot.id, 'raw.npz.ply')) as fout: fout.write(ply) data.save_raw_ply(shot.id,ply) print('available memory== ', memory_available()) print("current memory usage==", current_memory_usage())
def grow_reconstruction(data, graph, reconstruction, images, gcp): """Incrementally add shots to an initial reconstruction.""" bundle(graph, reconstruction, None, data.config) align.align_reconstruction(reconstruction, gcp, data.config) should_bundle = ShouldBundle(data, reconstruction) should_retriangulate = ShouldRetriangulate(data, reconstruction) report = { 'steps': [], } while True: if data.config['save_partial_reconstructions']: paint_reconstruction(data, graph, reconstruction) data.save_reconstruction( [reconstruction], 'reconstruction.{}.json'.format( datetime.datetime.now().isoformat().replace(':', '_'))) common_tracks = reconstructed_points_for_images( graph, reconstruction, images) if not common_tracks: break logger.info("-------------------------------------------------------") for image, num_tracks in common_tracks: ok, resrep = resect(data, graph, reconstruction, image) if ok: logger.info("Adding {0} to the reconstruction".format(image)) step = { 'image': image, 'resection': resrep, 'memory_usage': current_memory_usage() } report['steps'].append(step) images.remove(image) np_before = len(reconstruction.points) triangulate_shot_features( graph, reconstruction, image, data.config['triangulation_threshold'], data.config['triangulation_min_ray_angle']) np_after = len(reconstruction.points) step['triangulated_points'] = np_after - np_before if should_bundle.should(reconstruction): brep = bundle(graph, reconstruction, None, data.config) step['bundle'] = brep remove_outliers(graph, reconstruction, data.config) align.align_reconstruction(reconstruction, gcp, data.config) should_bundle.done(reconstruction) else: if data.config['local_bundle_radius'] > 0: brep = bundle_local(graph, reconstruction, None, image, data.config) step['local_bundle'] = brep if should_retriangulate.should(reconstruction): logger.info("Re-triangulating") rrep = retriangulate(graph, reconstruction, data.config) step['retriangulation'] = rrep bundle(graph, reconstruction, None, data.config) should_retriangulate.done(reconstruction) break else: logger.info("Some images can not be added") break logger.info("-------------------------------------------------------") bundle(graph, reconstruction, gcp, data.config) align.align_reconstruction(reconstruction, gcp, data.config) paint_reconstruction(data, graph, reconstruction) return reconstruction, report
def grow_reconstruction(data, tracks_manager, reconstruction, images, camera_priors, gcp): """Incrementally add shots to an initial reconstruction.""" config = data.config report = {"steps": []} align_reconstruction(reconstruction, gcp, config) bundle(reconstruction, camera_priors, None, config) remove_outliers(reconstruction, config) should_bundle = ShouldBundle(data, reconstruction) should_retriangulate = ShouldRetriangulate(data, reconstruction) while True: if config["save_partial_reconstructions"]: paint_reconstruction(data, tracks_manager, reconstruction) data.save_reconstruction( [reconstruction], "reconstruction.{}.json".format( datetime.datetime.now().isoformat().replace(":", "_")), ) candidates = reconstructed_points_for_images(tracks_manager, reconstruction, images) if not candidates: break logger.info("-------------------------------------------------------") threshold = data.config["resection_threshold"] min_inliers = data.config["resection_min_inliers"] for image, _ in candidates: camera = reconstruction.cameras[data.load_exif(image)["camera"]] metadata = get_image_metadata(data, image) ok, resrep = resect( tracks_manager, reconstruction, image, camera, metadata, threshold, min_inliers, ) if not ok: continue bundle_single_view(reconstruction, image, camera_priors, data.config) logger.info("Adding {0} to the reconstruction".format(image)) step = { "image": image, "resection": resrep, "memory_usage": current_memory_usage(), } report["steps"].append(step) images.remove(image) np_before = len(reconstruction.points) triangulate_shot_features(tracks_manager, reconstruction, image, config) np_after = len(reconstruction.points) step["triangulated_points"] = np_after - np_before if should_retriangulate.should(): logger.info("Re-triangulating") align_reconstruction(reconstruction, gcp, config) b1rep = bundle(reconstruction, camera_priors, None, config) rrep = retriangulate(tracks_manager, reconstruction, config) b2rep = bundle(reconstruction, camera_priors, None, config) remove_outliers(reconstruction, config) step["bundle"] = b1rep step["retriangulation"] = rrep step["bundle_after_retriangulation"] = b2rep should_retriangulate.done() should_bundle.done() elif should_bundle.should(): align_reconstruction(reconstruction, gcp, config) brep = bundle(reconstruction, camera_priors, None, config) remove_outliers(reconstruction, config) step["bundle"] = brep should_bundle.done() elif config["local_bundle_radius"] > 0: bundled_points, brep = bundle_local(reconstruction, camera_priors, None, image, config) remove_outliers(reconstruction, config, bundled_points) step["local_bundle"] = brep break else: logger.info("Some images can not be added") break logger.info("-------------------------------------------------------") align_reconstruction(reconstruction, gcp, config) bundle(reconstruction, camera_priors, gcp, config) remove_outliers(reconstruction, config) paint_reconstruction(data, tracks_manager, reconstruction) return reconstruction, report
def grow_reconstruction(data, graph, reconstruction, images, gcp): """Incrementally add shots to an initial reconstruction.""" bundle(graph, reconstruction, None, data.config) align.align_reconstruction(reconstruction, gcp, data.config) should_bundle = ShouldBundle(data, reconstruction) should_retriangulate = ShouldRetriangulate(data, reconstruction) report = { 'steps': [], } while True: if data.config['save_partial_reconstructions']: paint_reconstruction(data, graph, reconstruction) data.save_reconstruction( [reconstruction], 'reconstruction.{}.json'.format( datetime.datetime.now().isoformat().replace(':', '_'))) common_tracks = reconstructed_points_for_images(graph, reconstruction, images) if not common_tracks: break logger.info("-------------------------------------------------------") for image, num_tracks in common_tracks: ok, resrep = resect(data, graph, reconstruction, image) if ok: logger.info("Adding {0} to the reconstruction".format(image)) step = { 'image': image, 'resection': resrep, 'memory_usage': current_memory_usage() } report['steps'].append(step) images.remove(image) np_before = len(reconstruction.points) triangulate_shot_features( graph, reconstruction, image, data.config['triangulation_threshold'], data.config['triangulation_min_ray_angle']) np_after = len(reconstruction.points) step['triangulated_points'] = np_after - np_before if should_bundle.should(reconstruction): brep = bundle(graph, reconstruction, None, data.config) step['bundle'] = brep remove_outliers(graph, reconstruction, data.config) align.align_reconstruction(reconstruction, gcp, data.config) should_bundle.done(reconstruction) else: if data.config['local_bundle_radius'] > 0: brep = bundle_local(graph, reconstruction, None, image, data.config) step['local_bundle'] = brep if should_retriangulate.should(reconstruction): logger.info("Re-triangulating") rrep = retriangulate(graph, reconstruction, data.config) step['retriangulation'] = rrep bundle(graph, reconstruction, None, data.config) should_retriangulate.done(reconstruction) break else: logger.info("Some images can not be added") break logger.info("-------------------------------------------------------") bundle(graph, reconstruction, gcp, data.config) align.align_reconstruction(reconstruction, gcp, data.config) paint_reconstruction(data, graph, reconstruction) return reconstruction, report