def test_keypoints_read_from_images(self): # Create images_ids = set(f'cam{cam}/{timestamp:05d}.jpg' for cam in range(2) for timestamp in range(2)) keypoints_config_filepath = path.join(self._keypoints_dirpath, 'keypoints.txt') os.makedirs(path.dirname(keypoints_config_filepath), exist_ok=True) with open(keypoints_config_filepath, 'wt') as f: f.write('SIFT, float, 4') # lock and load keypoints = csv.keypoints_from_dir(self._kapture_dirpath, images_ids) # check its empty self.assertEqual('SIFT', keypoints.type_name) self.assertEqual(0, len(keypoints)) valid = kapture.io.features.keypoints_check_dir( keypoints, self._kapture_dirpath) self.assertTrue(valid) # create actual files for images_id in images_ids: keypoint_filepath = path.join(self._keypoints_dirpath, images_id + '.kpt') os.makedirs(path.dirname(keypoint_filepath), exist_ok=True) with open(keypoint_filepath, 'wt') as f: f.write('') # lock and load again keypoints = csv.keypoints_from_dir(self._kapture_dirpath, images_ids) self.assertEqual('SIFT', keypoints.type_name) self.assertEqual(4, len(keypoints)) keypoints_filepaths = kapture.io.features.keypoints_to_filepaths( keypoints, self._kapture_dirpath) image_filenames_expected = { f'cam{ci}/{ts:05d}.jpg' for ci in [0, 1] for ts in [0, 1] } feature_filepaths_expected = { path_secure( f'{self._kapture_dirpath}/reconstruction/keypoints/cam{ci}/{ts:05d}.jpg.kpt' ) for ci in [0, 1] for ts in [0, 1] } self.assertEqual(image_filenames_expected, set(keypoints_filepaths)) self.assertEqual(feature_filepaths_expected, set(keypoints_filepaths.values())) valid = kapture.io.features.keypoints_check_dir( keypoints, self._kapture_dirpath) self.assertTrue(valid) # destroy files and check os.remove(path.join(self._keypoints_dirpath, 'cam0/00000.jpg.kpt')) valid = kapture.io.features.keypoints_check_dir( keypoints, self._kapture_dirpath) self.assertFalse(valid)
def test_keypoints_read_from_files(self): images_ids = set(f'cam{cam}/{timestamp:05d}.jpg' for cam in range(2) for timestamp in range(2)) # make up keypoints files keypoints_config_filepath = path.join(self._keypoints_dirpath, 'keypoints.txt') os.makedirs(path.dirname(keypoints_config_filepath), exist_ok=True) with open(keypoints_config_filepath, 'wt') as f: f.write('SIFT, float, 4') keypoints_fullpaths = [ path_secure(path.join(self._keypoints_dirpath, image_id + '.kpt')) for image_id in images_ids ] for keypoints_fullpath in keypoints_fullpaths: os.makedirs(path.dirname(keypoints_fullpath), exist_ok=True) with open(keypoints_fullpath, 'wt') as f: f.write(' ') # lock and load keypoints = csv.keypoints_from_dir(self._kapture_dirpath, None) # check self.assertEqual('SIFT', keypoints.type_name) self.assertEqual(4, len(keypoints)) keypoints_filepaths = kapture.io.features.keypoints_to_filepaths(keypoints, self._kapture_dirpath) image_filenames_expected = {path_secure(os.path.join(f'cam{ci}', f'{ts:05d}.jpg')) for ci in [0, 1] for ts in [0, 1]} feature_filepaths_expected = { path_secure(os.path.join(f'{self._kapture_dirpath}', 'reconstruction', 'keypoints', f'cam{ci}', f'{ts:05d}.jpg.kpt')) for ci in [0, 1] for ts in [0, 1]} self.assertEqual(image_filenames_expected, set(keypoints_filepaths)) self.assertEqual(feature_filepaths_expected, set(keypoints_filepaths.values()))
def extract_kapture_keypoints(kapture_root, config, output_dir='', overwrite=False): """ Extract r2d2 keypoints and descritors to the kapture format directly """ print('extract_kapture_keypoints...') kdata = kapture_from_dir(kapture_root, matches_pairsfile_path=None, skip_list= [kapture.GlobalFeatures, kapture.Matches, kapture.Points3d, kapture.Observations]) export_dir = output_dir if output_dir else kapture_root # root of output directory for features os.makedirs(export_dir, exist_ok=True) assert kdata.records_camera is not None image_list = [filename for _, _, filename in kapture.flatten(kdata.records_camera)] # resume extraction if some features exist try: # load existing features, if any kdata.keypoints = keypoints_from_dir(export_dir, None) kdata.descriptors = descriptors_from_dir(export_dir, None) if kdata.keypoints is not None and kdata.descriptors is not None and not overwrite: image_list = [name for name in image_list if name not in kdata.keypoints or name not in kdata.descriptors] except FileNotFoundError: pass except: logging.exception("Error with importing existing local features.") # clear features first if overwriting if overwrite: delete_existing_kapture_files(export_dir, True, only=[kapture.Descriptors, kapture.Keypoints]) if len(image_list) == 0: print('All features were already extracted') return else: print(f'Extracting r2d2 features for {len(image_list)} images') iscuda = common.torch_set_gpu([torch.cuda.is_available()]) # load the network... net = load_network(config['checkpoint']) if iscuda: net = net.cuda() # create the non-maxima detector detector = NonMaxSuppression( rel_thr = config['reliability_thr'], rep_thr = config['repeatability_thr']) keypoints_dtype = None if kdata.keypoints is None else kdata.keypoints.dtype descriptors_dtype = None if kdata.descriptors is None else kdata.descriptors.dtype keypoints_dsize = None if kdata.keypoints is None else kdata.keypoints.dsize descriptors_dsize = None if kdata.descriptors is None else kdata.descriptors.dsize for image_name in image_list: img_path = get_image_fullpath(kapture_root, image_name) if img_path.endswith('.txt'): images = open(img_path).read().splitlines() + images continue print(f"\nExtracting features for {img_path}") img = Image.open(img_path).convert('RGB') W, H = img.size img = norm_RGB(img)[None] if iscuda: img = img.cuda() # extract keypoints/descriptors for a single image xys, desc, scores = extract_multiscale(net, img, detector, scale_f = config['scale_f'], min_scale = config['min_scale'], max_scale = config['max_scale'], min_size = config['min_size'], max_size = config['max_size'], verbose = True) xys = xys.cpu().numpy() desc = desc.cpu().numpy() scores = scores.cpu().numpy() idxs = scores.argsort()[-config['top_k'] or None:] xys = xys[idxs] desc = desc[idxs] if keypoints_dtype is None or descriptors_dtype is None: keypoints_dtype = xys.dtype descriptors_dtype = desc.dtype keypoints_dsize = xys.shape[1] descriptors_dsize = desc.shape[1] kdata.keypoints = kapture.Keypoints('r2d2', keypoints_dtype, keypoints_dsize) kdata.descriptors = kapture.Descriptors('r2d2', descriptors_dtype, descriptors_dsize) keypoints_config_absolute_path = get_csv_fullpath(kapture.Keypoints, export_dir) descriptors_config_absolute_path = get_csv_fullpath(kapture.Descriptors, export_dir) keypoints_to_file(keypoints_config_absolute_path, kdata.keypoints) descriptors_to_file(descriptors_config_absolute_path, kdata.descriptors) else: assert kdata.keypoints.type_name == 'r2d2' assert kdata.descriptors.type_name == 'r2d2' assert kdata.keypoints.dtype == xys.dtype assert kdata.descriptors.dtype == desc.dtype assert kdata.keypoints.dsize == xys.shape[1] assert kdata.descriptors.dsize == desc.shape[1] keypoints_fullpath = get_keypoints_fullpath(export_dir, image_name) print(f"Saving {xys.shape[0]} keypoints to {keypoints_fullpath}") image_keypoints_to_file(keypoints_fullpath, xys) kdata.keypoints.add(image_name) descriptors_fullpath = get_descriptors_fullpath(export_dir, image_name) print(f"Saving {desc.shape[0]} descriptors to {descriptors_fullpath}") image_descriptors_to_file(descriptors_fullpath, desc) kdata.descriptors.add(image_name) if not keypoints_check_dir(kdata.keypoints, export_dir) or \ not descriptors_check_dir(kdata.descriptors, export_dir): print('local feature extraction ended successfully but not all files were saved')