def run_colmap_gv_from_loaded_data(kapture_none_matches: kapture.Kapture, kapture_colmap_matches: kapture.Kapture, kapture_none_matches_dirpath: str, kapture_colmap_matches_dirpath: str, tar_handlers_none_matches: Optional[TarCollection], tar_handlers_colmap_matches: Optional[TarCollection], colmap_binary: str, keypoints_type: Optional[str], skip_list: List[str], force: bool): logger.info('run_colmap_gv...') if not (kapture_none_matches.records_camera and kapture_none_matches.sensors and kapture_none_matches.keypoints and kapture_none_matches.matches): raise ValueError('records_camera, sensors, keypoints, matches are mandatory') # COLMAP does not fully support rigs. if kapture_none_matches.rigs is not None and kapture_none_matches.trajectories is not None: # make sure, rigs are not used in trajectories. logger.info('remove rigs notation.') rigs_remove_inplace(kapture_none_matches.trajectories, kapture_none_matches.rigs) # Set fixed name for COLMAP database colmap_db_path = os.path.join(kapture_colmap_matches_dirpath, 'colmap.db') if 'delete_existing' not in skip_list: safe_remove_file(colmap_db_path, force) if keypoints_type is None: keypoints_type = try_get_only_key_from_collection(kapture_none_matches.matches) assert keypoints_type is not None assert keypoints_type in kapture_none_matches.keypoints assert keypoints_type in kapture_none_matches.matches if 'matches_importer' not in skip_list: logger.debug('compute matches difference.') if kapture_colmap_matches.matches is not None and keypoints_type in kapture_colmap_matches.matches: colmap_matches = kapture_colmap_matches.matches[keypoints_type] else: colmap_matches = kapture.Matches() matches_to_verify = kapture.Matches(kapture_none_matches.matches[keypoints_type].difference(colmap_matches)) kapture_data_to_export = kapture.Kapture(sensors=kapture_none_matches.sensors, trajectories=kapture_none_matches.trajectories, records_camera=kapture_none_matches.records_camera, keypoints={ keypoints_type: kapture_none_matches.keypoints[keypoints_type] }, matches={ keypoints_type: matches_to_verify }) # creates a new database with matches logger.debug('export matches difference to db.') colmap_db = COLMAPDatabase.connect(colmap_db_path) database_extra.kapture_to_colmap(kapture_data_to_export, kapture_none_matches_dirpath, tar_handlers_none_matches, colmap_db, keypoints_type, None, export_two_view_geometry=False) # close db before running colmap processes in order to avoid locks colmap_db.close() logger.debug('run matches_importer command.') colmap_lib.run_matches_importer_from_kapture_matches( colmap_binary, colmap_use_cpu=True, colmap_gpu_index=None, colmap_db_path=colmap_db_path, kapture_matches=matches_to_verify, force=force ) if 'import' not in skip_list: logger.debug('import verified matches.') os.umask(0o002) colmap_db = COLMAPDatabase.connect(colmap_db_path) kapture_data = kapture.Kapture() kapture_data.records_camera, _ = get_images_and_trajectories_from_database(colmap_db) kapture_data.matches = { keypoints_type: get_matches_from_database(colmap_db, kapture_data.records_camera, kapture_colmap_matches_dirpath, tar_handlers_colmap_matches, keypoints_type, no_geometric_filtering=False) } colmap_db.close() if kapture_colmap_matches.matches is None: kapture_colmap_matches.matches = {} if keypoints_type not in kapture_colmap_matches.matches: kapture_colmap_matches.matches[keypoints_type] = kapture.Matches() kapture_colmap_matches.matches[keypoints_type].update(kapture_data.matches[keypoints_type]) if 'delete_db' not in skip_list: logger.debug('delete intermediate colmap db.') os.remove(colmap_db_path)
def colmap_build_map_from_loaded_data(kapture_data: kapture.Kapture, kapture_path: str, colmap_path: str, colmap_binary: str, pairsfile_path: Optional[str], use_colmap_matches_importer: bool, point_triangulator_options: List[str], skip_list: List[str], force: bool) -> None: """ Build a colmap model using custom features with the kapture data. :param kapture_data: kapture data to use :param kapture_path: path to the kapture to use :param colmap_path: path to the colmap build :param colmap_binary: path to the colmap executable :param pairsfile_path: Optional[str], :param use_colmap_matches_importer: bool, :param point_triangulator_options: options for the point triangulator :param skip_list: list of steps to skip :param force: Silently overwrite kapture files if already exists. """ os.makedirs(colmap_path, exist_ok=True) if not (kapture_data.records_camera and kapture_data.sensors and kapture_data.keypoints and kapture_data.matches): raise ValueError('records_camera, sensors, keypoints, matches are mandatory') if not kapture_data.trajectories: logger.info('there are no trajectories, running mapper instead of point_triangulator') # COLMAP does not fully support rigs. if kapture_data.rigs is not None and kapture_data.trajectories is not None: # make sure, rigs are not used in trajectories. logger.info('remove rigs notation.') rigs_remove_inplace(kapture_data.trajectories, kapture_data.rigs) kapture_data.rigs.clear() # Set fixed name for COLMAP database colmap_db_path = path.join(colmap_path, 'colmap.db') reconstruction_path = path.join(colmap_path, "reconstruction") priors_txt_path = path.join(colmap_path, "priors_for_reconstruction") if 'delete_existing' not in skip_list: safe_remove_file(colmap_db_path, force) safe_remove_any_path(reconstruction_path, force) safe_remove_any_path(priors_txt_path, force) os.makedirs(reconstruction_path, exist_ok=True) if 'colmap_db' not in skip_list: logger.info('Using precomputed keypoints and matches') logger.info('Step 1: Export kapture format to colmap') colmap_db = COLMAPDatabase.connect(colmap_db_path) if kapture_data.descriptors is not None: kapture_data.descriptors.clear() database_extra.kapture_to_colmap(kapture_data, kapture_path, colmap_db, export_two_view_geometry=not use_colmap_matches_importer) # close db before running colmap processes in order to avoid locks colmap_db.close() if use_colmap_matches_importer: logger.info('Step 2: Run geometric verification') logger.debug('running colmap matches_importer...') colmap_lib.run_matches_importer_from_kapture( colmap_binary, colmap_use_cpu=True, colmap_gpu_index=None, colmap_db_path=colmap_db_path, kapture_data=kapture_data, force=force ) else: logger.info('Step 2: Run geometric verification - skipped') if kapture_data.trajectories is not None: # Generate priors for reconstruction os.makedirs(priors_txt_path, exist_ok=True) if 'priors_for_reconstruction' not in skip_list: logger.info('Step 3: Exporting priors for reconstruction.') colmap_db = COLMAPDatabase.connect(colmap_db_path) database_extra.generate_priors_for_reconstruction(kapture_data, colmap_db, priors_txt_path) colmap_db.close() # Point triangulator reconstruction_path = path.join(colmap_path, "reconstruction") os.makedirs(reconstruction_path, exist_ok=True) if 'triangulation' not in skip_list: logger.info("Step 4: Triangulation") colmap_lib.run_point_triangulator( colmap_binary, colmap_db_path, get_image_fullpath(kapture_path), priors_txt_path, reconstruction_path, point_triangulator_options ) else: # mapper reconstruction_path = path.join(colmap_path, "reconstruction") os.makedirs(reconstruction_path, exist_ok=True) if 'triangulation' not in skip_list: logger.info("Step 4: Triangulation") colmap_lib.run_mapper( colmap_binary, colmap_db_path, get_image_fullpath(kapture_path), None, reconstruction_path, point_triangulator_options ) # use reconstruction 0 as main first_reconstruction = os.path.join(reconstruction_path, '0') files = os.listdir(first_reconstruction) for f in files: shutil.move(os.path.join(first_reconstruction, f), os.path.join(reconstruction_path, f)) shutil.rmtree(first_reconstruction) # run model_converter if 'model_converter' not in skip_list: logger.info("Step 5: Export reconstruction results to txt") colmap_lib.run_model_converter( colmap_binary, reconstruction_path, reconstruction_path )
def reconstruct(self, kapture_data): os.makedirs(self._colmap_path, exist_ok=True) if not (kapture_data.records_camera and kapture_data.sensors and kapture_data.keypoints and kapture_data.matches and kapture_data.trajectories): raise ValueError( 'records_camera, sensors, keypoints, matches, trajectories are mandatory' ) # Set fixed name for COLMAP database colmap_db_path = path.join(self._colmap_path, 'colmap.db') reconstruction_path = path.join(self._colmap_path, "reconstruction") priors_txt_path = path.join(self._colmap_path, "priors_for_reconstruction") safe_remove_file(colmap_db_path, True) safe_remove_any_path(reconstruction_path, True) safe_remove_any_path(priors_txt_path, True) os.makedirs(reconstruction_path, exist_ok=True) # COLMAP does not fully support rigs. print("Step 1. Remove rigs") if kapture_data.rigs is not None and kapture_data.trajectories is not None: # make sure, rigs are not used in trajectories. rigs_remove_inplace(kapture_data.trajectories, kapture_data.rigs) kapture_data.rigs.clear() print("Step 2. Kapture to colmap") colmap_db = COLMAPDatabase.connect(colmap_db_path) database_extra.kapture_to_colmap(kapture_data, kapture_data.kapture_path, colmap_db, export_two_view_geometry=True) colmap_db.close() os.makedirs(priors_txt_path, exist_ok=True) print("Step 3. Generate priors for reconstruction") colmap_db = COLMAPDatabase.connect(colmap_db_path) database_extra.generate_priors_for_reconstruction( kapture_data, colmap_db, priors_txt_path) colmap_db.close() # Point triangulator print("Step 4. Point triangulator") reconstruction_path = path.join(self._colmap_path, "reconstruction") os.makedirs(reconstruction_path, exist_ok=True) run_point_triangulator(self._colmap_binary, colmap_db_path, kapture_data.image_path, priors_txt_path, reconstruction_path, self._point_triangulator_options) print("Step 5. Model converter") run_model_converter(self._colmap_binary, reconstruction_path, reconstruction_path) print("Step 5. Reconstruction import") points3d, observations = import_from_colmap_points3d_txt( os.path.join(reconstruction_path, "points3D.txt"), kapture_data.image_names) kapture_data.observations = observations kapture_data.points3d = points3d