├── NSF_1.gif ├── NSF_2.gif ├── NSF_3.gif ├── README.md ├── config.py ├── evaluate.py ├── generating_queries ├── generate_test_PCL_baseline_sets.py ├── generate_test_PCL_ours_sets.py ├── generate_test_PCL_supervise_sets.py ├── generate_test_RGB_baseline_sets.py ├── generate_test_RGB_ours_sets.py ├── generate_test_RGB_real_baseline_sets.py ├── generate_test_RGB_real_ours_sets.py ├── generate_test_RGB_real_supervise_sets.py ├── generate_test_RGB_supervise_sets.py ├── generate_training_tuples_PCL_baseline.py ├── generate_training_tuples_PCL_ours.py ├── generate_training_tuples_PCL_supervise.py ├── generate_training_tuples_RGB_baseline.py ├── generate_training_tuples_RGB_ours.py ├── generate_training_tuples_RGB_real_baseline.py ├── generate_training_tuples_RGB_real_ours.py ├── generate_training_tuples_RGB_real_supervise.py ├── generate_training_tuples_RGB_supervise.py └── set_path.py ├── get_embeddings_ours.py ├── loading_pointclouds.py ├── loss └── pointnetvlad_loss.py ├── models ├── ImageNetVlad.py ├── PointNetVlad.py ├── Verification_PCL.py ├── Verification_RGB.py ├── Verification_RGB_real.py └── resnet_mod.py ├── requirements.txt ├── results └── .DS_Store ├── set_path.py ├── train_netvlad_RGB_baseline.py ├── train_netvlad_RGB_ours.py ├── train_netvlad_RGB_real_baseline.py ├── train_netvlad_RGB_real_ours.py ├── train_netvlad_RGB_real_supervise.py ├── train_netvlad_RGB_supervise.py ├── train_pointnetvlad_PCL_baseline.py ├── train_pointnetvlad_PCL_ours.py └── train_pointnetvlad_PCL_supervise.py /NSF_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ai4ce/TF-VPR/83a4fbf59c1e51c0024c97943788db82fca9da7d/NSF_1.gif -------------------------------------------------------------------------------- /NSF_2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ai4ce/TF-VPR/83a4fbf59c1e51c0024c97943788db82fca9da7d/NSF_2.gif -------------------------------------------------------------------------------- /NSF_3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ai4ce/TF-VPR/83a4fbf59c1e51c0024c97943788db82fca9da7d/NSF_3.gif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Self-Supervised Visual Place Recognition by Mining Temporal and Feature Neighborhoods 2 | [Chao Chen](https://scholar.google.com/citations?hl=en&user=WOBQbwQAAAAJ), [Xinhao Liu](https://gaaaavin.github.io), [Xuchu Xu](https://www.xuchuxu.com), [Yiming Li](https://scholar.google.com/citations?user=i_aajNoAAAAJ), [Li Ding](https://www.hajim.rochester.edu/ece/lding6/), [Ruoyu Wang](https://github.com/ruoyuwangeel4930), [Chen Feng](https://scholar.google.com/citations?user=YeG8ZM0AAAAJ) 3 | 4 | **"A Novel self-supervised VPR model capable of retrieving positives from various orientations."** 5 | 6 | ![PyTorch](https://img.shields.io/badge/PyTorch-%23EE4C2C.svg?logo=PyTorch&logoColor=white) 7 | [![Linux](https://svgshare.com/i/Zhy.svg)](https://svgshare.com/i/Zhy.svg) 8 | [![GitLab issues total](https://badgen.net/github/issues/ai4ce/V2X-Sim)](https://github.com/Joechencc/TF-VPR) 9 | [![GitHub stars](https://img.shields.io/github/stars/ai4ce/V2X-Sim.svg?style=social&label=Star&maxAge=2592000)](https://github.com/Joechencc/TF-VPR/stargazers/) 10 |
11 | 12 |
13 |
14 | 15 | ## Abstract 16 | 17 | Visual place recognition (VPR) using deep networks has achieved state-of-the-art performance. However, most of the related approaches require a training set with ground truth sensor poses to obtain the positive and negative samples of each observation's spatial neighborhoods. When such knowledge is unknown, the temporal neighborhoods from a sequentially collected data stream could be exploited for self-supervision, although with suboptimal performance. Inspired by noisy label learning, we propose a novel self-supervised VPR framework that uses both the temporal neighborhoods and the learnable feature neighborhoods to discover the unknown spatial neighborhoods. Our method follows an iterative training paradigm which alternates between: (1) representation learning with data augmentation, (2) positive set expansion to include the current feature space neighbors, and (3) positive set contraction via geometric verification. We conduct comprehensive experiments on both simulated and real datasets, with input of both images and point clouds. The results demonstrate that our method outperforms the baselines in both recall rate, robustness, and a novel metric we proposed for VPR, the orientation diversity. 18 | 19 | ## Dataset 20 | 21 | Download links: 22 | - For Pointcloud: Please refer to DeepMapping paper, https://github.com/ai4ce/PointCloudSimulator 23 | - For NYU-VPR-360 dataset: https://drive.google.com/drive/u/0/folders/1ErXzIx0je5aGSRFbo5jP7oR8gPrdersO 24 | 25 | You could find more detailed documents on our [website](https://ai4ce.github.io/TF-VPR/)! 26 | 27 | # Data Structure 28 | ``` 29 | Data_folder 30 | ├── 000001.pcd or 000001.RGB # Dataset 31 | ├── 000002.pcd or 000002.RGB # Dataset 32 | | ... 33 | ├── 00nnnn.pcd or 00nnnn.RGB # Dataset 34 | ├── gt_pose.mat # ground truth mat file contains the geographical information for evaluation 35 | ``` 36 | 37 | ## Folder Structure 38 | 39 | TF-VPR follows the same file structure as the [PointNetVLAD](https://github.com/mikacuy/pointnetvlad): 40 | ``` 41 | TF-VPR 42 | ├── loss # loss function 43 | ├── models # network model 44 | | ├── PointNetVlad.py # PointNetVLAD network model 45 | | ├── ImageNetVLAD.py # NetVLAD network model 46 | | ├── resnet_mod.py # ResNet network model 47 | | ├── Verification_PCL.py # Verification for PCL data 48 | | ├── Verification_RGB.py # Verification for RGB data 49 | | ├── Verification_RGB_real.py # Verification for RGB_real data 50 | | ... 51 | ├── generating_queries # Preprocess the data, initial the label, and generate Pickle file 52 | | ├── generate_test_PCL_baseline_sets.py # Generate the test pickle file for PCL baseline 53 | | ├── generate_test_PCL_ours_sets.py # Generate the test pickle file for PCL TF-VPR 54 | | ├── generate_test_PCL_supervise_sets.py # Generate the test pickle file for PCL supervise 55 | | ├── generate_test_RGB_baseline_sets.py # Generate the test pickle file for Habitat-sim baseline 56 | | ├── generate_test_RGB_ours_sets.py # Generate the test pickle file for Habitat-sim TF-VPR 57 | | ├── generate_test_RGB_supervise_sets.py # Generate the test pickle file for Habitat-sim supervise 58 | | ├── generate_test_RGB_real_baseline_sets.py # Generate the test pickle file for NYU-VPR-360 baseline 59 | | ├── generate_test_RGB_real_ours_sets.py # Generate the test pickle file for NYU-VPR-360 TF-VPR 60 | | ├── generate_test_RGB_real_supervise_sets.py # Generate the test pickle file for NYU-VPR-360 supervise 61 | | ├── generate_training_tuples_PCL_baseline.py # Generate the train pickle file for PCL baseline 62 | | ├── generate_training_tuples_PCL_ours.py # Generate the train pickle file for PCL TF-VPR 63 | | ├── generate_training_tuples_PCL_supervise.py # Generate the train pickle file for PCL supervise 64 | | ├── generate_training_tuples_RGB_baseline.py # Generate the train pickle file for Habitat-sim baseline 65 | | ├── generate_training_tuples_RGB_ours.py # Generate the train pickle file for Habitat-sim TF-VPR 66 | | ├── generate_training_tuples_RGB_supervise.py # Generate the train pickle file for Habitat-sim supervise 67 | | ├── generate_training_tuples_RGB_supervise.py # Generate the train pickle file for NYU-VPR-360 baseline 68 | | ├── generate_training_tuples_RGB_real_ours.py # Generate the train pickle file for NYU-VPR-360 TF-VPR 69 | | ├── generate_training_tuples_RGB_real_supervise.py # Generate the train pickle file for NYU-VPR-360 supervise 70 | | ... 71 | ├── results # Results are saved here 72 | ├── config.py # Config file 73 | ├── evaluate.py # evaluate file 74 | ├── loading_pointcloud.py # file loading script 75 | ├── train_pointnetvlad_PCL_baseline.py # Main file to train PCL baseline 76 | ├── train_pointnetvlad_PCL_ours.py # Main file to train PCL TF-VPR 77 | ├── train_pointnetvlad_PCL_supervise.py # Main file to train PCL supervise 78 | ├── train_netvlad_RGB_baseline.py # Main file to train Hatbitat-sim baseline 79 | ├── train_netvlad_RGB_ours.py # Main file to train Hatbitat-sim TF-VPR 80 | ├── train_netvlad_RGB_supervise.py # Main file to train Hatbitat-sim supervise 81 | ├── train_netvlad_RGB_real_baseline.py # Main file to train NYU-VPR-360 baseline 82 | ├── train_netvlad_RGB_real_ours.py # Main file to train NYU-VPR-360 TF-VPR 83 | ├── train_netvlad_RGB_real_supervise.py # Main file to train NYU-VPR-360 supervise 84 | | ... 85 | ``` 86 | Point cloud TF-VPR result: 87 | 88 | ![](NSF_1.gif) 89 | 90 | RGB TF-VPR result: 91 | 92 | ![](NSF_2.gif) 93 | 94 | NYU-VPR-360 TF-VPR result: 95 | 96 | ![](NSF_3.gif) 97 | 98 | # Note 99 | 100 | I kept almost everything not related to tensorflow as the original implementation. The main differences are: 101 | * Multi-GPU support 102 | * Configuration file (config.py) 103 | * Evaluation on the eval dataset after every epochs 104 | 105 | ### Pre-Requisites 106 | - Python 3.6 107 | - PyTorch >=1.10.0 108 | - tensorboardX 109 | - open3d-python 0.4 110 | - scipy 111 | - matplotlib 112 | - numpy 113 | - pandas 114 | - scikit-learn 115 | - pickle5 116 | - torchvision 117 | - opencv-contrib-python 118 | 119 | ### Generate pickle files 120 | ``` 121 | cd generating_queries/ 122 | ### For Pointcloud data 123 | 124 | # To create pickle file for PCL baseline method 125 | python generate_training_tuples_PCL_baseline.py 126 | 127 | # To create pickle file for PCL TF-VPR method 128 | python generate_training_tuples_PCL_ours.py 129 | 130 | # To create pickle file for PCL supervise method 131 | python generate_training_tuples_PCL_supervise.py 132 | 133 | # To create pickle file for PCL baseline evaluation pickle 134 | python generate_test_PCL_baseline_sets.py 135 | 136 | # To create pickle file for PCL TF-VPR evaluation pickle 137 | python generate_test_PCL_ours_sets.py 138 | 139 | # To create pickle file for PCL supervise evaluation pickle 140 | python generate_test_PCL_supervise_sets.py 141 | ``` 142 | 143 | ``` 144 | cd generating_queries/ 145 | ### For Habitat-sim data 146 | 147 | # For training tuples in our RGB baseline network 148 | python generate_training_tuples_RGB_baseline.py 149 | 150 | # For training tuples in our RGB baseline network 151 | python generate_training_tuples_RGB_ours.py 152 | 153 | # For training tuples in our RGB baseline network 154 | python generate_training_tuples_RGB_supervise.py 155 | 156 | # For RGB network evaluation 157 | python generate_test_RGB_baseline_sets.py 158 | 159 | # For RGB network evaluation 160 | python generate_test_RGB_ours_sets.py 161 | 162 | # For RGB network evaluation 163 | python generate_test_RGB_supervise_sets.py 164 | ``` 165 | 166 | ``` 167 | cd generating_queries/ 168 | ### For NYU-VPR-360 data 169 | 170 | # For training tuples in our RGB baseline network 171 | python generate_training_tuples_RGB_real_baseline.py 172 | 173 | # For training tuples in our RGB baseline network 174 | python generate_training_tuples_RGB_real_ours.py 175 | 176 | # For training tuples in our RGB baseline network 177 | python generate_training_tuples_RGB_real_supervise.py 178 | 179 | # For RGB network evaluation 180 | python generate_test_RGB_baseline_real_sets.py 181 | 182 | # For RGB network evaluation 183 | python generate_test_RGB_real_ours_sets.py 184 | 185 | # For RGB network evaluation 186 | python generate_test_RGB_real_supervise_sets.py 187 | ``` 188 | 189 | ### Verification threshold 190 | ``` 191 | ### For point cloud 192 | 193 | python Verification_PCL.py # you can create max and min threshold using this command. For RGB, we calculate the threshold on Verification stage, no need to precalculate 194 | ``` 195 | 196 | ### Train 197 | ``` 198 | ### For point cloud 199 | 200 | python train_pointnetvlad_PCL_baseline.py # Train baseline for PCL data 201 | python train_pointnetvlad_PCL_ours.py # Train ours for PCL data 202 | python train_pointnetvlad_PCL_supervise.py # Train supervise for PCL data 203 | 204 | ### For Habitat-sim 205 | 206 | python train_pointnetvlad_RGBL_baseline.py # Train baseline for Habitat-sim data 207 | python train_pointnetvlad_RGB_ours.py # Train ours for Habitat-sim data 208 | python train_pointnetvlad_RGB_supervise.py # Train supervise for Habitat-sim data 209 | 210 | ### For point cloud 211 | 212 | python train_pointnetvlad_RGB_real_baseline.py # Train baseline for NYU-VPR-360 data 213 | python train_pointnetvlad_RGB_real_ours.py # Train baseline for NYU-VPR-360 data 214 | python train_pointnetvlad_RGB_real_supervise.py # Train baseline for NYU-VPR-360 data 215 | ``` 216 | 217 | ### Evaluate (You don't need to run it separately. For every epoch, evaluation will be run automatically) 218 | ``` 219 | python evaluate.py 220 | ``` 221 | 222 | Take a look at train_pointnetvlad.py and evaluate.py for more parameters 223 | 224 | ## Benchmark 225 | 226 | We implement SPTM, TF-VPR, and supervise version, please check the other branches for reference 227 | 228 | ## Citation 229 | 230 | If you find TF-VPR useful in your research, please cite: 231 | 232 | ```bibtex 233 | @article{Chen2022arxiv, 234 | author = {Chen, Chao and Liu, Xinhao and Xu, Xuchu and Li, Yiming and Ding, Li and Wang, Ruoyu and Feng, Chen}, 235 | title = {Self-Supervised Visual Place Recognition by Mining Temporal and Feature Neighborhoods}, 236 | journal = {arxiv}, 237 | year = {2022} 238 | 239 | } 240 | ``` 241 | 242 | ## Acknowledgements 243 | 244 | Chen Feng is the corresponding author. The research is supported by NSF Future Manufacturing program under CMMI-1932187, CNS-2121391, and EEC-2036870. Chao Chen gratefully thanks the help from Bhargav Makwana. 245 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | # GLOBAL 2 | NUM_POINTS = 256 3 | FEATURE_OUTPUT_DIM = 512 4 | PICKLE_FOLDER = "train_pickle/" 5 | RESULTS_FOLDER = "results/" 6 | OUTPUT_FILE = "results/results.txt" 7 | SIZED_GRID_X = 64*4 8 | SIZED_GRID_Y = 64 9 | GRID_X = 1080 10 | GRID_Y = 1920 11 | file_name = "Goffs" 12 | 13 | LOG_DIR = 'log/' 14 | MODEL_FILENAME = "model.ckpt" 15 | 16 | DATASET_FOLDER = '/home/cc/dm_data' 17 | DATASET_FOLDER_RGB = '/mnt/NAS/home/cc/data/habitat_4/train' 18 | DATASET_FOLDER_RGB_REAL = '/mnt/NAS/data/cc_data/2D_RGB_real_full3' 19 | 20 | # TRAIN 21 | BATCH_NUM_QUERIES = 2 22 | TRAIN_POSITIVES_PER_QUERY = 2 23 | TRAIN_NEGATIVES_PER_QUERY = 18 24 | DECAY_STEP = 200000 25 | DECAY_RATE = 0.7 26 | BASE_LEARNING_RATE = 0.000005 27 | MOMENTUM = 0.9 28 | OPTIMIZER = 'ADAM' 29 | MAX_EPOCH = 20 30 | FOLD_NUM = 18 31 | 32 | MARGIN_1 = 0.5 33 | MARGIN_2 = 0.2 34 | 35 | BN_INIT_DECAY = 0.5 36 | BN_DECAY_DECAY_RATE = 0.5 37 | BN_DECAY_CLIP = 0.99 38 | 39 | RESUME = False 40 | ROT_NUM = 8 41 | 42 | EVAL_NEAREST = 16 43 | INIT_TRUST = 2 44 | INIT_TRUST_SCALAR = 1 45 | NEIGHBOR = 4 46 | 47 | TRAIN_FILE = 'generating_queries/training_queries_baseline.pickle' 48 | TEST_FILE = 'generating_queries/test_queries_baseline.pickle' 49 | scene_list = ['Goffs','Nimmons','Reyno','Spotswood','Springhill','Stilwell'] 50 | 51 | # LOSS 52 | LOSS_FUNCTION = 'quadruplet' 53 | LOSS_FUNCTION_RGB = 'triplet' 54 | 55 | LOSS_LAZY = True 56 | TRIPLET_USE_BEST_POSITIVES = False 57 | LOSS_IGNORE_ZERO_BATCH = False 58 | 59 | # EVAL6 60 | EVAL_BATCH_SIZE = 2 61 | EVAL_POSITIVES_PER_QUERY = 4 62 | EVAL_NEGATIVES_PER_QUERY = 12 63 | 64 | EVAL_DATABASE_FILE = 'generating_queries/evaluation_database.pickle' 65 | EVAL_QUERY_FILE = 'generating_queries/evaluation_query.pickle' 66 | 67 | 68 | def cfg_str(): 69 | out_string = "" 70 | for name in globals(): 71 | if not name.startswith("__") and not name.__contains__("cfg_str"): 72 | #print(name, "=", globals()[name]) 73 | out_string = out_string + "cfg." + name + \ 74 | "=" + str(globals()[name]) + "\n" 75 | return out_string 76 | -------------------------------------------------------------------------------- /generating_queries/generate_test_PCL_baseline_sets.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pickle 3 | import random 4 | import set_path 5 | 6 | import numpy as np 7 | import pandas as pd 8 | from sklearn.neighbors import KDTree 9 | 10 | import config as cfg 11 | 12 | import scipy.io as sio 13 | import torch 14 | 15 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 16 | base_path = cfg.DATASET_FOLDER 17 | 18 | runs_folder = "dm_data" 19 | filename = "gt_pose.mat" 20 | pointcloud_fols = "/pointcloud_20m_10overlap/" 21 | test_num = 10 22 | 23 | print("cfg.DATASET_FOLDER:"+str(cfg.DATASET_FOLDER)) 24 | 25 | cc_dir = "/home/cc/" 26 | all_folders = sorted(os.listdir(os.path.join(cc_dir,runs_folder))) 27 | file_size_ = 2048 28 | folders = [] 29 | 30 | # All runs are used for training (both full and partial) 31 | index_list = [11,14,15,17] 32 | print("Number of runs: "+str(len(index_list))) 33 | for index in index_list: 34 | folders.append(all_folders[index]) 35 | print(folders) 36 | 37 | 38 | #####For training and test data split##### 39 | def output_to_file(output, filename): 40 | with open(filename, 'wb') as handle: 41 | pickle.dump(output, handle, protocol=pickle.HIGHEST_PROTOCOL) 42 | print("Done ", filename) 43 | 44 | ######################################### 45 | def construct_query_dict(df_centroids, df_database, folder_num, filename_train, filename_test, test=False): 46 | database_trees = [] 47 | test_trees = [] 48 | tree = KDTree(df_centroids[['x','y']]) 49 | ind_nn = tree.query_radius(df_centroids[['x','y']],r=15) 50 | ind_r = tree.query_radius(df_centroids[['x','y']], r=50) 51 | queries_sets = [] 52 | database_sets = [] 53 | for folder in range(folder_num): 54 | queries = {} 55 | for i in range(len(df_centroids)//folder_num): 56 | temp_indx = folder*(len(df_centroids)//folder_num) + i 57 | query = df_centroids.iloc[temp_indx]["file"] 58 | #print("folder:"+str(folder)) 59 | #print("query:"+str(query)) 60 | queries[len(queries.keys())] = {"query":query, 61 | "x":float(df_centroids.iloc[temp_indx]['x']),"y":float(df_centroids.iloc[temp_indx]['y'])} 62 | queries_sets.append(queries) 63 | test_tree = KDTree(df_centroids[folder*test_num:(folder+1)*test_num][['x','y']]) 64 | test_trees.append(test_tree) 65 | 66 | for folder in range(folder_num): 67 | dataset = {} 68 | for i in range(len(df_database)//folder_num): 69 | temp_indx = folder*len(df_database)//folder_num + i 70 | data = df_database.iloc[temp_indx]["file"] 71 | dataset[len(dataset.keys())] = {"query":data, 72 | "x":float(df_database.iloc[temp_indx]['x']),"y":float(df_database.iloc[temp_indx]['y'])} 73 | 74 | database_sets.append(dataset) 75 | database_tree = KDTree(df_database[folder*file_size_:(folder+1)*file_size_][['x','y']]) 76 | database_trees.append(database_tree) 77 | 78 | if test: 79 | for i in range(len(database_sets)): 80 | tree = database_trees[i] 81 | for j in range(len(queries_sets)): 82 | if(i == j): 83 | continue 84 | for key in range(len(queries_sets[j].keys())): 85 | coor = np.array( 86 | [[queries_sets[j][key]["x"],queries_sets[j][key]["y"]]]) 87 | index = tree.query_radius(coor, r=25) 88 | # indices of the positive matches in database i of each query (key) in test set j 89 | queries_sets[j][key][i] = index[0].tolist() 90 | 91 | output_to_file(queries_sets, filename_test) 92 | output_to_file(database_sets, filename_train) 93 | 94 | # Initialize pandas DataFrame 95 | df_train = pd.DataFrame(columns=['file','x','y']) 96 | df_test = pd.DataFrame(columns=['file','x','y']) 97 | 98 | df_files_test = [] 99 | df_files_train =[] 100 | 101 | df_locations_tr_x = [] 102 | df_locations_tr_y = [] 103 | df_locations_ts_x = [] 104 | df_locations_ts_y = [] 105 | 106 | for folder in folders: 107 | df_locations = sio.loadmat(os.path.join( 108 | cc_dir,runs_folder,folder,filename)) 109 | 110 | df_locations = df_locations['pose'] 111 | df_locations = torch.tensor(df_locations, dtype = torch.float).cpu() 112 | 113 | #2038 Training 10 testing 114 | test_index = list(sorted(random.sample(range(len(df_locations)), k=test_num))) 115 | train_index = list(range(df_locations.shape[0])) 116 | #for i in test_index: 117 | # train_index.pop(i) 118 | 119 | df_locations_tr_x.extend(list(df_locations[train_index,0])) 120 | df_locations_tr_y.extend(list(df_locations[train_index,1])) 121 | df_locations_ts_x.extend(list(df_locations[test_index,0])) 122 | df_locations_ts_y.extend(list(df_locations[test_index,1])) 123 | 124 | all_files = list(sorted(os.listdir(os.path.join(cc_dir,runs_folder,folder)))) 125 | all_files.remove('gt_pose.mat') 126 | all_files.remove('gt_pose.png') 127 | 128 | for (indx, file_) in enumerate(all_files): 129 | if indx in test_index: 130 | df_files_test.append(os.path.join(cc_dir,runs_folder,folder,file_)) 131 | df_files_train.append(os.path.join(cc_dir,runs_folder,folder,file_)) 132 | 133 | 134 | df_train = pd.DataFrame(list(zip(df_files_train, df_locations_tr_x, df_locations_tr_y)), 135 | columns =['file','x', 'y']) 136 | df_test = pd.DataFrame(list(zip(df_files_test, df_locations_ts_x, df_locations_ts_y)), 137 | columns =['file','x', 'y']) 138 | 139 | print("Number of training submaps: "+str(len(df_train['file']))) 140 | print("Number of non-disjoint test submaps: "+str(len(df_test['file']))) 141 | 142 | print("df_train:"+str(len(df_train))) 143 | print("len(folders):"+str(len(folders))) 144 | 145 | #construct_query_dict(df_train,len(folders),"evaluation_database.pickle",False) 146 | construct_query_dict(df_test, df_train, len(folders),"evaluation_database.pickle", "evaluation_query.pickle", True) 147 | -------------------------------------------------------------------------------- /generating_queries/generate_test_PCL_ours_sets.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pickle 3 | import random 4 | import set_path 5 | 6 | import numpy as np 7 | import pandas as pd 8 | from sklearn.neighbors import KDTree 9 | 10 | import config as cfg 11 | 12 | import scipy.io as sio 13 | import torch 14 | 15 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 16 | base_path = cfg.DATASET_FOLDER 17 | 18 | runs_folder = "dm_data" 19 | filename = "gt_pose.mat" 20 | pointcloud_fols = "/pointcloud_20m_10overlap/" 21 | test_num = 10 22 | 23 | evaluate_all = True 24 | print("cfg.DATASET_FOLDER:"+str(cfg.DATASET_FOLDER)) 25 | 26 | for i in range(2): 27 | if i==1: 28 | evaluate_all = False 29 | cc_dir = "/home/cc/" 30 | all_folders = sorted(os.listdir(os.path.join(cc_dir,runs_folder))) 31 | file_size_ = 2048 32 | folders = [] 33 | 34 | # All runs are used for training (both full and partial) 35 | if evaluate_all: 36 | index_list = list(range(18)) 37 | else: 38 | index_list = [5,6,7,9]#,11,14,18,19,29,31,32,34,36,40,44,46,49,51,53,54,57,59,61,63,65,68,69,72,75,77,79,83,85,88,91,93,94] 39 | print("Number of runs: "+str(len(index_list))) 40 | for index in index_list: 41 | folders.append(all_folders[index]) 42 | print(folders) 43 | 44 | 45 | #####For training and test data split##### 46 | def output_to_file(output, filename): 47 | with open(filename, 'wb') as handle: 48 | pickle.dump(output, handle, protocol=pickle.HIGHEST_PROTOCOL) 49 | print("Done ", filename) 50 | 51 | ######################################### 52 | def construct_query_dict(df_centroids, df_database, folder_num, filename_train, filename_test, test=False): 53 | database_trees = [] 54 | test_trees = [] 55 | tree = KDTree(df_centroids[['x','y']]) 56 | ind_nn = tree.query_radius(df_centroids[['x','y']],r=15) 57 | ind_r = tree.query_radius(df_centroids[['x','y']], r=50) 58 | queries_sets = [] 59 | database_sets = [] 60 | for folder in range(folder_num): 61 | queries = {} 62 | for i in range(len(df_centroids)//folder_num): 63 | temp_indx = folder*(len(df_centroids)//folder_num) + i 64 | query = df_centroids.iloc[temp_indx]["file"] 65 | #print("folder:"+str(folder)) 66 | #print("query:"+str(query)) 67 | queries[len(queries.keys())] = {"query":query, 68 | "x":float(df_centroids.iloc[temp_indx]['x']),"y":float(df_centroids.iloc[temp_indx]['y'])} 69 | queries_sets.append(queries) 70 | test_tree = KDTree(df_centroids[folder*test_num:(folder+1)*test_num][['x','y']]) 71 | test_trees.append(test_tree) 72 | 73 | for folder in range(folder_num): 74 | dataset = {} 75 | for i in range(len(df_database)//folder_num): 76 | temp_indx = folder*len(df_database)//folder_num + i 77 | data = df_database.iloc[temp_indx]["file"] 78 | dataset[len(dataset.keys())] = {"query":data, 79 | "x":float(df_database.iloc[temp_indx]['x']),"y":float(df_database.iloc[temp_indx]['y'])} 80 | 81 | database_sets.append(dataset) 82 | database_tree = KDTree(df_database[folder*file_size_:(folder+1)*file_size_][['x','y']]) 83 | database_trees.append(database_tree) 84 | 85 | if test: 86 | for i in range(len(database_sets)): 87 | tree = database_trees[i] 88 | for j in range(len(queries_sets)): 89 | if(i == j): 90 | continue 91 | for key in range(len(queries_sets[j].keys())): 92 | coor = np.array( 93 | [[queries_sets[j][key]["x"],queries_sets[j][key]["y"]]]) 94 | index = tree.query_radius(coor, r=25) 95 | # indices of the positive matches in database i of each query (key) in test set j 96 | queries_sets[j][key][i] = index[0].tolist() 97 | 98 | output_to_file(queries_sets, filename_test) 99 | output_to_file(database_sets, filename_train) 100 | 101 | # Initialize pandas DataFrame 102 | df_train = pd.DataFrame(columns=['file','x','y']) 103 | df_test = pd.DataFrame(columns=['file','x','y']) 104 | 105 | df_files_test = [] 106 | df_files_train =[] 107 | 108 | df_locations_tr_x = [] 109 | df_locations_tr_y = [] 110 | df_locations_ts_x = [] 111 | df_locations_ts_y = [] 112 | 113 | for folder in folders: 114 | df_locations = sio.loadmat(os.path.join( 115 | cc_dir,runs_folder,folder,filename)) 116 | 117 | df_locations = df_locations['pose'] 118 | df_locations = torch.tensor(df_locations, dtype = torch.float).cpu() 119 | 120 | #2038 Training 10 testing 121 | test_index = list(sorted(random.sample(range(len(df_locations)), k=test_num))) 122 | train_index = list(range(df_locations.shape[0])) 123 | #for i in test_index: 124 | # train_index.pop(i) 125 | 126 | df_locations_tr_x.extend(list(df_locations[train_index,0])) 127 | df_locations_tr_y.extend(list(df_locations[train_index,1])) 128 | df_locations_ts_x.extend(list(df_locations[test_index,0])) 129 | df_locations_ts_y.extend(list(df_locations[test_index,1])) 130 | 131 | all_files = list(sorted(os.listdir(os.path.join(cc_dir,runs_folder,folder)))) 132 | all_files.remove('gt_pose.mat') 133 | all_files.remove('gt_pose.png') 134 | 135 | for (indx, file_) in enumerate(all_files): 136 | if indx in test_index: 137 | df_files_test.append(os.path.join(cc_dir,runs_folder,folder,file_)) 138 | df_files_train.append(os.path.join(cc_dir,runs_folder,folder,file_)) 139 | 140 | 141 | df_train = pd.DataFrame(list(zip(df_files_train, df_locations_tr_x, df_locations_tr_y)), 142 | columns =['file','x', 'y']) 143 | df_test = pd.DataFrame(list(zip(df_files_test, df_locations_ts_x, df_locations_ts_y)), 144 | columns =['file','x', 'y']) 145 | 146 | print("Number of training submaps: "+str(len(df_train['file']))) 147 | print("Number of non-disjoint test submaps: "+str(len(df_test['file']))) 148 | 149 | print("df_train:"+str(len(df_train))) 150 | print("len(folders):"+str(len(folders))) 151 | 152 | #construct_query_dict(df_train,len(folders),"evaluation_database.pickle",False) 153 | if not evaluate_all: 154 | construct_query_dict(df_test, df_train, len(folders),"evaluation_database.pickle", "evaluation_query.pickle", True) 155 | else: 156 | construct_query_dict(df_test, df_train, len(folders),"evaluation_database_full.pickle", "evaluation_query_full.pickle", True) -------------------------------------------------------------------------------- /generating_queries/generate_test_PCL_supervise_sets.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pickle 3 | import random 4 | import set_path 5 | 6 | import numpy as np 7 | import pandas as pd 8 | from sklearn.neighbors import KDTree 9 | 10 | import config as cfg 11 | 12 | import scipy.io as sio 13 | import torch 14 | 15 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 16 | base_path = cfg.DATASET_FOLDER 17 | 18 | runs_folder = "dm_data" 19 | filename = "gt_pose.mat" 20 | pointcloud_fols = "/pointcloud_20m_10overlap/" 21 | test_num = 4 22 | 23 | evaluate_all = False 24 | for k in range(2): 25 | if k == 1: 26 | evaluate_all = True 27 | print("cfg.DATASET_FOLDER:"+str(cfg.DATASET_FOLDER)) 28 | 29 | cc_dir = "/home/cc/" 30 | all_folders = sorted(os.listdir(os.path.join(cc_dir,runs_folder))) 31 | file_size_ = 2048 32 | folders = [] 33 | 34 | # All runs are used for training (both full and partial) 35 | if evaluate_all: 36 | index_list = list(range(18)) 37 | else: 38 | index_list = [5,6,7,9] 39 | print("Number of runs: "+str(len(index_list))) 40 | for index in index_list: 41 | folders.append(all_folders[index]) 42 | print(folders) 43 | 44 | 45 | #####For training and test data split##### 46 | def output_to_file(output, filename): 47 | with open(filename, 'wb') as handle: 48 | pickle.dump(output, handle, protocol=pickle.HIGHEST_PROTOCOL) 49 | print("Done ", filename) 50 | 51 | ######################################### 52 | def construct_query_dict(df_centroids, df_database, folder_num, filename_train, filename_test, test=False): 53 | database_trees = [] 54 | test_trees = [] 55 | tree = KDTree(df_centroids[['x','y']]) 56 | ind_nn = tree.query_radius(df_centroids[['x','y']],r=15) 57 | ind_r = tree.query_radius(df_centroids[['x','y']], r=50) 58 | queries_sets = [] 59 | database_sets = [] 60 | for folder in range(folder_num): 61 | queries = {} 62 | for i in range(len(df_centroids)//folder_num): 63 | temp_indx = folder*(len(df_centroids)//folder_num) + i 64 | query = df_centroids.iloc[temp_indx]["file"] 65 | #print("folder:"+str(folder)) 66 | #print("query:"+str(query)) 67 | queries[len(queries.keys())] = {"query":query, 68 | "x":float(df_centroids.iloc[temp_indx]['x']),"y":float(df_centroids.iloc[temp_indx]['y'])} 69 | queries_sets.append(queries) 70 | test_tree = KDTree(df_centroids[folder*test_num:(folder+1)*test_num][['x','y']]) 71 | test_trees.append(test_tree) 72 | 73 | for folder in range(folder_num): 74 | dataset = {} 75 | for i in range(len(df_database)//folder_num): 76 | temp_indx = folder*len(df_database)//folder_num + i 77 | data = df_database.iloc[temp_indx]["file"] 78 | dataset[len(dataset.keys())] = {"query":data, 79 | "x":float(df_database.iloc[temp_indx]['x']),"y":float(df_database.iloc[temp_indx]['y'])} 80 | 81 | database_sets.append(dataset) 82 | database_tree = KDTree(df_database[folder*file_size_:(folder+1)*file_size_][['x','y']]) 83 | database_trees.append(database_tree) 84 | 85 | if test: 86 | for i in range(len(database_sets)): 87 | tree = database_trees[i] 88 | for j in range(len(queries_sets)): 89 | if(i == j): 90 | continue 91 | for key in range(len(queries_sets[j].keys())): 92 | coor = np.array( 93 | [[queries_sets[j][key]["x"],queries_sets[j][key]["y"]]]) 94 | index = tree.query_radius(coor, r=25) 95 | # indices of the positive matches in database i of each query (key) in test set j 96 | queries_sets[j][key][i] = index[0].tolist() 97 | 98 | output_to_file(queries_sets, filename_test) 99 | output_to_file(database_sets, filename_train) 100 | 101 | # Initialize pandas DataFrame 102 | df_train = pd.DataFrame(columns=['file','x','y']) 103 | df_test = pd.DataFrame(columns=['file','x','y']) 104 | 105 | df_files_test = [] 106 | df_files_train =[] 107 | 108 | df_locations_tr_x = [] 109 | df_locations_tr_y = [] 110 | df_locations_ts_x = [] 111 | df_locations_ts_y = [] 112 | 113 | for folder in folders: 114 | df_locations = sio.loadmat(os.path.join( 115 | cc_dir,runs_folder,folder,filename)) 116 | 117 | df_locations = df_locations['pose'] 118 | df_locations = torch.tensor(df_locations, dtype = torch.float).cpu() 119 | 120 | #2038 Training 10 testing 121 | test_index = list(sorted(random.sample(range(len(df_locations)), k=test_num))) 122 | train_index = list(range(df_locations.shape[0])) 123 | #for i in test_index: 124 | # train_index.pop(i) 125 | 126 | df_locations_tr_x.extend(list(df_locations[train_index,0])) 127 | df_locations_tr_y.extend(list(df_locations[train_index,1])) 128 | df_locations_ts_x.extend(list(df_locations[test_index,0])) 129 | df_locations_ts_y.extend(list(df_locations[test_index,1])) 130 | 131 | all_files = list(sorted(os.listdir(os.path.join(cc_dir,runs_folder,folder)))) 132 | all_files.remove('gt_pose.mat') 133 | all_files.remove('gt_pose.png') 134 | 135 | for (indx, file_) in enumerate(all_files): 136 | if indx in test_index: 137 | df_files_test.append(os.path.join(cc_dir,runs_folder,folder,file_)) 138 | df_files_train.append(os.path.join(cc_dir,runs_folder,folder,file_)) 139 | 140 | 141 | df_train = pd.DataFrame(list(zip(df_files_train, df_locations_tr_x, df_locations_tr_y)), 142 | columns =['file','x', 'y']) 143 | df_test = pd.DataFrame(list(zip(df_files_test, df_locations_ts_x, df_locations_ts_y)), 144 | columns =['file','x', 'y']) 145 | 146 | print("Number of training submaps: "+str(len(df_train['file']))) 147 | print("Number of non-disjoint test submaps: "+str(len(df_test['file']))) 148 | 149 | print("df_train:"+str(len(df_train))) 150 | 151 | #construct_query_dict(df_train,len(folders),"evaluation_database.pickle",False) 152 | if not evaluate_all: 153 | construct_query_dict(df_test, df_train, len(folders),"evaluation_database.pickle", "evaluation_query.pickle", True) 154 | else: 155 | construct_query_dict(df_test, df_train, len(folders),"evaluation_database_full.pickle", "evaluation_query_full.pickle", True) -------------------------------------------------------------------------------- /generating_queries/generate_test_RGB_baseline_sets.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pickle 4 | import random 5 | import set_path 6 | 7 | import numpy as np 8 | import pandas as pd 9 | from sklearn.neighbors import KDTree 10 | 11 | import config as cfg 12 | 13 | import scipy.io as sio 14 | import torch 15 | import json 16 | 17 | ########################################## 18 | 19 | def output_to_file(output, filename): 20 | with open(filename, 'wb') as handle: 21 | pickle.dump(output, handle, protocol=pickle.HIGHEST_PROTOCOL) 22 | print("Done ", filename) 23 | 24 | ######################################### 25 | def construct_query_dict(df_centroids, df_database, folder_num, traj_len, filename_train, filename_test, nn_ind, r_mid, r_ind, test=False, evaluate_all=False): 26 | database_trees = [] 27 | test_trees = [] 28 | if not evaluate_all: 29 | tree = KDTree(df_centroids[['x','y']]) 30 | ind_nn = tree.query_radius(df_centroids[['x','y']],r=nn_ind) 31 | ind_r = tree.query_radius(df_centroids[['x','y']], r=r_ind) 32 | queries_sets = [] 33 | database_sets = [] 34 | 35 | #for folder in range(folder_num): 36 | queries = {} 37 | for i in range(len(df_centroids)): 38 | #temp_indx = folder*len(df_centroids)//folder_num + i 39 | temp_indx = i 40 | query = df_centroids.iloc[temp_indx]["file"] 41 | #print("folder:"+str(folder)) 42 | #print("query:"+str(query)) 43 | if not evaluate_all: 44 | queries[len(queries.keys())] = {"query":query, 45 | "x":float(df_centroids.iloc[temp_indx]['x']),"y":float(df_centroids.iloc[temp_indx]['y'])} 46 | else: 47 | queries[len(queries.keys())] = {"query":query} 48 | 49 | queries_sets.append(queries) 50 | if not evaluate_all: 51 | test_tree = KDTree(df_centroids[['x','y']]) 52 | test_trees.append(test_tree) 53 | 54 | ############################### 55 | #for folder in range(folder_num): 56 | dataset = {} 57 | for i in range(len(df_database)): 58 | #temp_indx = folder*len(df_database)//folder_num + i 59 | temp_indx = i 60 | data = df_database.iloc[temp_indx]["file"] 61 | if not evaluate_all: 62 | dataset[len(dataset.keys())] = {"query":data, 63 | "x":float(df_database.iloc[temp_indx]['x']),"y":float(df_database.iloc[temp_indx]['y']) } 64 | else: 65 | dataset[len(dataset.keys())] = {"query":data} 66 | database_sets.append(dataset) 67 | if not evaluate_all: 68 | database_tree = KDTree(df_database[['x','y']]) 69 | database_trees.append(database_tree) 70 | ################################## 71 | if test: 72 | if not evaluate_all: 73 | #for i in range(len(database_sets)): 74 | tree = database_trees[0] 75 | #for j in range(len(queries_sets)): 76 | #if(i == j): 77 | # continue 78 | #print("len(queries_sets[j].keys():"+str(len(queries_sets[j].keys()))) 79 | #assert(0) 80 | for key in range(len(queries_sets[0].keys())): 81 | coor = np.array( 82 | [[queries_sets[0][key]["x"],queries_sets[0][key]["y"]]]) 83 | index = tree.query_radius(coor, r=r_mid) 84 | # indices of the positive matches in database i of each query (key) in test set j 85 | queries_sets[0][key][0] = index[0].tolist() 86 | else: 87 | pass 88 | 89 | output_to_file(queries_sets, filename_test) 90 | output_to_file(database_sets, filename_train) 91 | 92 | def generate(scene_index, evaluate_all = False, inside=True): 93 | base_path = "/mnt/NAS/home/cc/data/habitat_4/train" 94 | runs_folder = cfg.scene_list[scene_index] 95 | #runs_folder = "Goffs" 96 | pre_dir = os.path.join(base_path, runs_folder) 97 | 98 | nn_ind = 0.2 99 | r_mid = 0.2 100 | r_ind = 0.6 101 | 102 | filename = "gt_pose.mat" 103 | 104 | folders = list(sorted(os.listdir(pre_dir))) 105 | 106 | if evaluate_all == False: 107 | index_list = list(range(len(folders))) 108 | else: 109 | index_list = list(range(len(folders))) 110 | 111 | fold_list = [] 112 | for index in index_list: 113 | fold_list.append(folders[index]) 114 | 115 | all_files = [] 116 | for fold in fold_list: 117 | files_ = [] 118 | files = list(sorted(os.listdir(os.path.join(pre_dir, fold)))) 119 | files.remove('gt_pose.mat') 120 | # print("len(files):"+str(len(files))) 121 | for ind in range(len(files)): 122 | file_ = "panoimg_"+str(ind)+".png" 123 | files_.append(os.path.join(pre_dir, fold, file_)) 124 | all_files.extend(files_) 125 | # all_files.remove('trajectory.mp4') 126 | # all_files = [i for i in all_files if not i.endswith(".npy")] 127 | 128 | traj_len = len(all_files) 129 | file_size = traj_len/len(fold_list) 130 | 131 | # Initialize pandas DataFrame 132 | if evaluate_all: 133 | df_train = pd.DataFrame(columns=['file']) 134 | df_test = pd.DataFrame(columns=['file']) 135 | else: 136 | df_train = pd.DataFrame(columns=['file','x','y']) 137 | df_test = pd.DataFrame(columns=['file','x','y']) 138 | 139 | if not evaluate_all: 140 | df_files_test = [] 141 | df_files_train =[] 142 | 143 | df_locations_tr_x = [] 144 | df_locations_tr_y = [] 145 | 146 | df_locations_ts_x = [] 147 | df_locations_ts_y = [] 148 | 149 | # print("os.path.join(pre_dir,filename):"+str(os.path.join(pre_dir,filename))) 150 | df_locations = torch.zeros((traj_len, 3), dtype = torch.float) 151 | for count, fold in enumerate(fold_list): 152 | data = sio.loadmat(os.path.join(pre_dir,fold,filename)) 153 | df_location = data['pose'] 154 | df_locations[int(count*file_size):int((count+1)*file_size)] = torch.tensor(df_location, dtype = torch.float) 155 | 156 | # df_locations = df_locations['pose'] 157 | # df_locations = torch.tensor(df_locations, dtype = torch.float).cpu() 158 | else: 159 | df_files_test = [] 160 | df_files_train =[] 161 | 162 | #n-40 Training 40 testing 163 | test_sample = len(fold_list)*10 164 | test_index = random.choices(range(traj_len), k=test_sample) 165 | train_index = list(range(traj_len)) 166 | #for i in test_index: 167 | # train_index.pop(i) 168 | if not evaluate_all: 169 | df_locations_tr_x.extend(list(df_locations[train_index,0])) 170 | df_locations_tr_y.extend(list(df_locations[train_index,2])) 171 | 172 | df_locations_ts_x.extend(list(df_locations[test_index,0])) 173 | df_locations_ts_y.extend(list(df_locations[test_index,2])) 174 | 175 | for indx in range(traj_len): 176 | # file_ = 'panoimg_'+str(indx)+'.png' 177 | if indx in test_index: 178 | df_files_test.append(all_files[indx]) 179 | df_files_train.append(all_files[indx]) 180 | 181 | if not evaluate_all: 182 | df_train = pd.DataFrame(list(zip(df_files_train, df_locations_tr_x, df_locations_tr_y)), 183 | columns =['file','x', 'y']) 184 | df_test = pd.DataFrame(list(zip(df_files_test, df_locations_ts_x, df_locations_ts_y)), 185 | columns =['file','x', 'y']) 186 | else: 187 | df_train = pd.DataFrame(list(zip(df_files_train)), 188 | columns =['file']) 189 | df_test = pd.DataFrame(list(zip(df_files_test)), 190 | columns =['file']) 191 | print("Number of training submaps: "+str(len(df_train['file']))) 192 | print("Number of non-disjoint test submaps: "+str(len(df_test['file']))) 193 | 194 | 195 | #construct_query_dict(df_train,len(folders),"evaluation_database.pickle",False) 196 | if inside == False: 197 | if not evaluate_all: 198 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"generating_queries/evaluation_database.pickle", "generating_queries/evaluation_query.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 199 | else: 200 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"generating_queries/evaluation_database_full.pickle", "generating_queries/evaluation_query_full.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 201 | else: 202 | if not evaluate_all: 203 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"evaluation_database.pickle", "evaluation_query.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 204 | else: 205 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"evaluation_database_full.pickle", "evaluation_query_full.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 206 | if __name__ == "__main__": 207 | generate(1, evaluate_all=False) 208 | -------------------------------------------------------------------------------- /generating_queries/generate_test_RGB_ours_sets.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pickle 4 | import random 5 | import set_path 6 | 7 | import numpy as np 8 | import pandas as pd 9 | from sklearn.neighbors import KDTree 10 | 11 | import config as cfg 12 | 13 | import scipy.io as sio 14 | import torch 15 | import json 16 | 17 | ########################################## 18 | 19 | def output_to_file(output, filename): 20 | with open(filename, 'wb') as handle: 21 | pickle.dump(output, handle, protocol=pickle.HIGHEST_PROTOCOL) 22 | print("Done ", filename) 23 | 24 | ######################################### 25 | def construct_query_dict(df_centroids, df_database, folder_num, traj_len, filename_train, filename_test, nn_ind, r_mid, r_ind, test=False, evaluate_all=False): 26 | database_trees = [] 27 | test_trees = [] 28 | if not evaluate_all: 29 | tree = KDTree(df_centroids[['x','y']]) 30 | ind_nn = tree.query_radius(df_centroids[['x','y']],r=nn_ind) 31 | ind_r = tree.query_radius(df_centroids[['x','y']], r=r_ind) 32 | queries_sets = [] 33 | database_sets = [] 34 | 35 | queries = {} 36 | for i in range(len(df_centroids)): 37 | temp_indx = i 38 | query = df_centroids.iloc[temp_indx]["file"] 39 | 40 | if not evaluate_all: 41 | queries[len(queries.keys())] = {"query":query, 42 | "x":float(df_centroids.iloc[temp_indx]['x']),"y":float(df_centroids.iloc[temp_indx]['y'])} 43 | else: 44 | queries[len(queries.keys())] = {"query":query} 45 | 46 | queries_sets.append(queries) 47 | if not evaluate_all: 48 | test_tree = KDTree(df_centroids[['x','y']]) 49 | test_trees.append(test_tree) 50 | 51 | ############################### 52 | dataset = {} 53 | for i in range(len(df_database)): 54 | temp_indx = i 55 | data = df_database.iloc[temp_indx]["file"] 56 | if not evaluate_all: 57 | dataset[len(dataset.keys())] = {"query":data, 58 | "x":float(df_database.iloc[temp_indx]['x']),"y":float(df_database.iloc[temp_indx]['y']) } 59 | else: 60 | dataset[len(dataset.keys())] = {"query":data} 61 | database_sets.append(dataset) 62 | if not evaluate_all: 63 | database_tree = KDTree(df_database[['x','y']]) 64 | database_trees.append(database_tree) 65 | ################################## 66 | if test: 67 | if not evaluate_all: 68 | tree = database_trees[0] 69 | 70 | for key in range(len(queries_sets[0].keys())): 71 | coor = np.array( 72 | [[queries_sets[0][key]["x"],queries_sets[0][key]["y"]]]) 73 | index = tree.query_radius(coor, r=r_mid) 74 | queries_sets[0][key][0] = index[0].tolist() 75 | else: 76 | pass 77 | 78 | output_to_file(queries_sets, filename_test) 79 | output_to_file(database_sets, filename_train) 80 | 81 | def generate(scene_index, evaluate_all = False, inside=True): 82 | base_path = "/mnt/NAS/home/cc/data/habitat_4/train" 83 | runs_folder = cfg.scene_list[scene_index] 84 | pre_dir = os.path.join(base_path, runs_folder) 85 | 86 | nn_ind = 0.2 87 | r_mid = 0.2 88 | r_ind = 0.6 89 | 90 | filename = "gt_pose.mat" 91 | 92 | folders = list(sorted(os.listdir(pre_dir))) 93 | if evaluate_all == False: 94 | index_list = list(range(len(folders))) 95 | else: 96 | index_list = list(range(len(folders))) 97 | 98 | fold_list = [] 99 | for index in index_list: 100 | fold_list.append(folders[index]) 101 | 102 | all_files = [] 103 | for fold in fold_list: 104 | files_ = [] 105 | files = list(sorted(os.listdir(os.path.join(pre_dir, fold)))) 106 | files.remove('gt_pose.mat') 107 | # print("len(files):"+str(len(files))) 108 | for ind in range(len(files)): 109 | file_ = "panoimg_"+str(ind)+".png" 110 | files_.append(os.path.join(pre_dir, fold, file_)) 111 | all_files.extend(files_) 112 | 113 | traj_len = len(all_files) 114 | file_size = traj_len/len(fold_list) 115 | 116 | # Initialize pandas DataFrame 117 | if evaluate_all: 118 | df_train = pd.DataFrame(columns=['file']) 119 | df_test = pd.DataFrame(columns=['file']) 120 | else: 121 | df_train = pd.DataFrame(columns=['file','x','y']) 122 | df_test = pd.DataFrame(columns=['file','x','y']) 123 | 124 | if not evaluate_all: 125 | df_files_test = [] 126 | df_files_train =[] 127 | 128 | df_locations_tr_x = [] 129 | df_locations_tr_y = [] 130 | 131 | df_locations_ts_x = [] 132 | df_locations_ts_y = [] 133 | 134 | df_locations = torch.zeros((traj_len, 3), dtype = torch.float) 135 | for count, fold in enumerate(fold_list): 136 | data = sio.loadmat(os.path.join(pre_dir,fold,filename)) 137 | df_location = data['pose'] 138 | df_locations[int(count*file_size):int((count+1)*file_size)] = torch.tensor(df_location, dtype = torch.float) 139 | 140 | else: 141 | df_files_test = [] 142 | df_files_train =[] 143 | 144 | #n-40 Training 40 testing 145 | test_sample = len(fold_list)*10 146 | test_index = random.choices(range(traj_len), k=test_sample) 147 | train_index = list(range(traj_len)) 148 | 149 | if not evaluate_all: 150 | df_locations_tr_x.extend(list(df_locations[train_index,0])) 151 | df_locations_tr_y.extend(list(df_locations[train_index,2])) 152 | 153 | df_locations_ts_x.extend(list(df_locations[test_index,0])) 154 | df_locations_ts_y.extend(list(df_locations[test_index,2])) 155 | 156 | for indx in range(traj_len): 157 | if indx in test_index: 158 | df_files_test.append(all_files[indx]) 159 | df_files_train.append(all_files[indx]) 160 | 161 | if not evaluate_all: 162 | df_train = pd.DataFrame(list(zip(df_files_train, df_locations_tr_x, df_locations_tr_y)), 163 | columns =['file','x', 'y']) 164 | df_test = pd.DataFrame(list(zip(df_files_test, df_locations_ts_x, df_locations_ts_y)), 165 | columns =['file','x', 'y']) 166 | else: 167 | df_train = pd.DataFrame(list(zip(df_files_train)), 168 | columns =['file']) 169 | df_test = pd.DataFrame(list(zip(df_files_test)), 170 | columns =['file']) 171 | print("Number of training submaps: "+str(len(df_train['file']))) 172 | print("Number of non-disjoint test submaps: "+str(len(df_test['file']))) 173 | 174 | #construct_query_dict(df_train,len(folders),"evaluation_database.pickle",False) 175 | if inside == False: 176 | if not evaluate_all: 177 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"generating_queries/evaluation_database.pickle", "generating_queries/evaluation_query.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 178 | else: 179 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"generating_queries/evaluation_database_full.pickle", "generating_queries/evaluation_query_full.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 180 | else: 181 | if not evaluate_all: 182 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"evaluation_database.pickle", "evaluation_query.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 183 | else: 184 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"evaluation_database_full.pickle", "evaluation_query_full.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 185 | if __name__ == "__main__": 186 | generate(0, evaluate_all=False) 187 | generate(0, evaluate_all=True) -------------------------------------------------------------------------------- /generating_queries/generate_test_RGB_real_baseline_sets.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pickle 4 | import random 5 | import set_path 6 | 7 | import numpy as np 8 | import pandas as pd 9 | from sklearn.neighbors import KDTree 10 | 11 | import config as cfg 12 | 13 | import scipy.io as sio 14 | import torch 15 | import json 16 | 17 | ########################################## 18 | 19 | def output_to_file(output, filename): 20 | with open(filename, 'wb') as handle: 21 | pickle.dump(output, handle, protocol=pickle.HIGHEST_PROTOCOL) 22 | print("Done ", filename) 23 | 24 | ######################################### 25 | def construct_query_dict(df_centroids, df_database, folder_num, traj_len, filename_train, filename_test, nn_ind, r_mid, r_ind, test=False, evaluate_all=False): 26 | database_trees = [] 27 | test_trees = [] 28 | if not evaluate_all: 29 | tree = KDTree(df_centroids[['x','y']]) 30 | ind_nn = tree.query_radius(df_centroids[['x','y']],r=nn_ind) 31 | ind_r = tree.query_radius(df_centroids[['x','y']], r=r_ind) 32 | queries_sets = [] 33 | database_sets = [] 34 | 35 | #for folder in range(folder_num): 36 | queries = {} 37 | for i in range(len(df_centroids)): 38 | #temp_indx = folder*len(df_centroids)//folder_num + i 39 | temp_indx = i 40 | query = df_centroids.iloc[temp_indx]["file"] 41 | #print("folder:"+str(folder)) 42 | #print("query:"+str(query)) 43 | if not evaluate_all: 44 | queries[len(queries.keys())] = {"query":query, 45 | "x":float(df_centroids.iloc[temp_indx]['x']),"y":float(df_centroids.iloc[temp_indx]['y'])} 46 | else: 47 | queries[len(queries.keys())] = {"query":query} 48 | 49 | queries_sets.append(queries) 50 | if not evaluate_all: 51 | test_tree = KDTree(df_centroids[['x','y']]) 52 | test_trees.append(test_tree) 53 | 54 | ############################### 55 | #for folder in range(folder_num): 56 | dataset = {} 57 | for i in range(len(df_database)): 58 | #temp_indx = folder*len(df_database)//folder_num + i 59 | temp_indx = i 60 | data = df_database.iloc[temp_indx]["file"] 61 | if not evaluate_all: 62 | dataset[len(dataset.keys())] = {"query":data, 63 | "x":float(df_database.iloc[temp_indx]['x']),"y":float(df_database.iloc[temp_indx]['y']) } 64 | else: 65 | dataset[len(dataset.keys())] = {"query":data} 66 | database_sets.append(dataset) 67 | if not evaluate_all: 68 | database_tree = KDTree(df_database[['x','y']]) 69 | database_trees.append(database_tree) 70 | ################################## 71 | if test: 72 | if not evaluate_all: 73 | #for i in range(len(database_sets)): 74 | tree = database_trees[0] 75 | #for j in range(len(queries_sets)): 76 | #if(i == j): 77 | # continue 78 | #print("len(queries_sets[j].keys():"+str(len(queries_sets[j].keys()))) 79 | #assert(0) 80 | for key in range(len(queries_sets[0].keys())): 81 | coor = np.array( 82 | [[queries_sets[0][key]["x"],queries_sets[0][key]["y"]]]) 83 | index = tree.query_radius(coor, r=r_mid) 84 | # indices of the positive matches in database i of each query (key) in test set j 85 | queries_sets[0][key][0] = index[0].tolist() 86 | #print("index[0].tolist():"+str(len(index[0].tolist()))) 87 | else: 88 | pass 89 | 90 | output_to_file(queries_sets, filename_test) 91 | output_to_file(database_sets, filename_train) 92 | 93 | def generate(scene_index, evaluate_all = False, inside=True): 94 | base_path = "/mnt/NAS/data/cc_data/2D_RGB_real_edited3" 95 | #runs_folder = cfg.scene_names[scene_index] 96 | #runs_folder = "Goffs" 97 | pre_dir = base_path #os.path.join(base_path, runs_folder) 98 | 99 | nn_ind = 0.003 100 | r_mid = 0.003 101 | r_ind = 0.006 102 | 103 | filename = "gt_pose.mat" 104 | 105 | folders = list(sorted(os.listdir(pre_dir))) 106 | if evaluate_all == False: 107 | index_list = [0] 108 | else: 109 | index_list = list(range(len(folders))) 110 | 111 | fold_list = [] 112 | for index in index_list: 113 | fold_list.append(folders[index]) 114 | 115 | all_files = [] 116 | for fold in fold_list: 117 | files_ = [] 118 | files = list(sorted(os.listdir(os.path.join(pre_dir, fold)))) 119 | files.remove('gt_pose.mat') 120 | # print("len(files):"+str(len(files))) 121 | for ind in range(len(files)): 122 | file_ = "panoimg_"+str(ind)+".jpg" 123 | files_.append(os.path.join(pre_dir, fold, file_)) 124 | all_files.extend(files_) 125 | # all_files.remove('trajectory.mp4') 126 | # all_files = [i for i in all_files if not i.endswith(".npy")] 127 | 128 | traj_len = len(all_files) 129 | file_size = traj_len/len(fold_list) 130 | 131 | # Initialize pandas DataFrame 132 | if evaluate_all: 133 | df_train = pd.DataFrame(columns=['file']) 134 | df_test = pd.DataFrame(columns=['file']) 135 | else: 136 | df_train = pd.DataFrame(columns=['file','x','y']) 137 | df_test = pd.DataFrame(columns=['file','x','y']) 138 | 139 | if not evaluate_all: 140 | df_files_test = [] 141 | df_files_train =[] 142 | 143 | df_locations_tr_x = [] 144 | df_locations_tr_y = [] 145 | 146 | df_locations_ts_x = [] 147 | df_locations_ts_y = [] 148 | 149 | # print("os.path.join(pre_dir,filename):"+str(os.path.join(pre_dir,filename))) 150 | df_locations = torch.zeros((traj_len, 2), dtype = torch.float) 151 | for count, fold in enumerate(fold_list): 152 | data = sio.loadmat(os.path.join(pre_dir,fold,filename)) 153 | df_location = data['pose'] 154 | df_locations[int(count*file_size):int((count+1)*file_size)] = torch.tensor(df_location, dtype = torch.float) 155 | 156 | # df_locations = df_locations['pose'] 157 | # df_locations = torch.tensor(df_locations, dtype = torch.float).cpu() 158 | else: 159 | df_files_test = [] 160 | df_files_train =[] 161 | 162 | #n-40 Training 40 testing 163 | test_sample = len(fold_list)*10 164 | test_index = random.choices(range(traj_len), k=test_sample) 165 | train_index = list(range(traj_len)) 166 | #for i in test_index: 167 | # train_index.pop(i) 168 | if not evaluate_all: 169 | df_locations_tr_x.extend(list(df_locations[train_index,0])) 170 | df_locations_tr_y.extend(list(df_locations[train_index,1])) 171 | 172 | df_locations_ts_x.extend(list(df_locations[test_index,0])) 173 | df_locations_ts_y.extend(list(df_locations[test_index,1])) 174 | 175 | for indx in range(traj_len): 176 | # file_ = 'panoimg_'+str(indx)+'.png' 177 | if indx in test_index: 178 | df_files_test.append(all_files[indx]) 179 | df_files_train.append(all_files[indx]) 180 | 181 | if not evaluate_all: 182 | #print("df_files_train:"+str((df_files_train))) 183 | df_train = pd.DataFrame(list(zip(df_files_train, df_locations_tr_x, df_locations_tr_y)), 184 | columns =['file','x', 'y']) 185 | df_test = pd.DataFrame(list(zip(df_files_test, df_locations_ts_x, df_locations_ts_y)), 186 | columns =['file','x', 'y']) 187 | else: 188 | df_train = pd.DataFrame(list(zip(df_files_train)), 189 | columns =['file']) 190 | df_test = pd.DataFrame(list(zip(df_files_test)), 191 | columns =['file']) 192 | print("Number of training submaps: "+str(len(df_train['file']))) 193 | print("Number of non-disjoint test submaps: "+str(len(df_test['file']))) 194 | 195 | 196 | #construct_query_dict(df_train,len(folders),"evaluation_database.pickle",False) 197 | if inside == False: 198 | if not evaluate_all: 199 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"generating_queries/evaluation_database.pickle", "generating_queries/evaluation_query.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 200 | else: 201 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"generating_queries/evaluation_database_full.pickle", "generating_queries/evaluation_query_full.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 202 | else: 203 | if not evaluate_all: 204 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"evaluation_database.pickle", "evaluation_query.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 205 | else: 206 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"evaluation_database_full.pickle", "evaluation_query_full.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 207 | if __name__ == "__main__": 208 | generate(1, evaluate_all=False) -------------------------------------------------------------------------------- /generating_queries/generate_test_RGB_real_ours_sets.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pickle 4 | import random 5 | import set_path 6 | 7 | import numpy as np 8 | import pandas as pd 9 | from sklearn.neighbors import KDTree 10 | 11 | import config as cfg 12 | 13 | import scipy.io as sio 14 | import torch 15 | import json 16 | 17 | ########################################## 18 | 19 | def output_to_file(output, filename): 20 | with open(filename, 'wb') as handle: 21 | pickle.dump(output, handle, protocol=pickle.HIGHEST_PROTOCOL) 22 | print("Done ", filename) 23 | 24 | ######################################### 25 | def construct_query_dict(df_centroids, df_database, folder_num, traj_len, filename_train, filename_test, nn_ind, r_mid, r_ind, test=False, evaluate_all=False): 26 | database_trees = [] 27 | test_trees = [] 28 | if not evaluate_all: 29 | tree = KDTree(df_centroids[['x','y']]) 30 | ind_nn = tree.query_radius(df_centroids[['x','y']],r=nn_ind) 31 | ind_r = tree.query_radius(df_centroids[['x','y']], r=r_ind) 32 | queries_sets = [] 33 | database_sets = [] 34 | 35 | #for folder in range(folder_num): 36 | queries = {} 37 | for i in range(len(df_centroids)): 38 | #temp_indx = folder*len(df_centroids)//folder_num + i 39 | temp_indx = i 40 | query = df_centroids.iloc[temp_indx]["file"] 41 | #print("folder:"+str(folder)) 42 | #print("query:"+str(query)) 43 | if not evaluate_all: 44 | queries[len(queries.keys())] = {"query":query, 45 | "x":float(df_centroids.iloc[temp_indx]['x']),"y":float(df_centroids.iloc[temp_indx]['y'])} 46 | else: 47 | queries[len(queries.keys())] = {"query":query} 48 | 49 | queries_sets.append(queries) 50 | if not evaluate_all: 51 | test_tree = KDTree(df_centroids[['x','y']]) 52 | test_trees.append(test_tree) 53 | 54 | ############################### 55 | #for folder in range(folder_num): 56 | dataset = {} 57 | for i in range(len(df_database)): 58 | #temp_indx = folder*len(df_database)//folder_num + i 59 | temp_indx = i 60 | data = df_database.iloc[temp_indx]["file"] 61 | if not evaluate_all: 62 | dataset[len(dataset.keys())] = {"query":data, 63 | "x":float(df_database.iloc[temp_indx]['x']),"y":float(df_database.iloc[temp_indx]['y']) } 64 | else: 65 | dataset[len(dataset.keys())] = {"query":data} 66 | database_sets.append(dataset) 67 | if not evaluate_all: 68 | database_tree = KDTree(df_database[['x','y']]) 69 | database_trees.append(database_tree) 70 | ################################## 71 | if test: 72 | if not evaluate_all: 73 | #for i in range(len(database_sets)): 74 | tree = database_trees[0] 75 | #for j in range(len(queries_sets)): 76 | #if(i == j): 77 | # continue 78 | #print("len(queries_sets[j].keys():"+str(len(queries_sets[j].keys()))) 79 | #assert(0) 80 | for key in range(len(queries_sets[0].keys())): 81 | coor = np.array( 82 | [[queries_sets[0][key]["x"],queries_sets[0][key]["y"]]]) 83 | index = tree.query_radius(coor, r=r_mid) 84 | # indices of the positive matches in database i of each query (key) in test set j 85 | queries_sets[0][key][0] = index[0].tolist() 86 | #print("index[0].tolist():"+str(len(index[0].tolist()))) 87 | else: 88 | pass 89 | 90 | output_to_file(queries_sets, filename_test) 91 | output_to_file(database_sets, filename_train) 92 | 93 | def generate(scene_index, evaluate_all = False, inside=True): 94 | if not evaluate_all: 95 | base_path = "/mnt/NAS/data/cc_data/2D_RGB_real_edited3" 96 | else: 97 | base_path = "/mnt/NAS/data/cc_data/2D_RGB_real_full3" 98 | #runs_folder = cfg.scene_names[scene_index] 99 | #runs_folder = "Goffs" 100 | pre_dir = base_path #os.path.join(base_path, runs_folder) 101 | 102 | nn_ind = 0.003 103 | r_mid = 0.003 104 | r_ind = 0.006 105 | 106 | filename = "gt_pose.mat" 107 | 108 | folders = list(sorted(os.listdir(pre_dir))) 109 | if evaluate_all == False: 110 | index_list = [0] 111 | else: 112 | index_list = list(range(len(folders))) 113 | 114 | fold_list = [] 115 | for index in index_list: 116 | fold_list.append(folders[index]) 117 | 118 | all_files = [] 119 | for fold in fold_list: 120 | files_ = [] 121 | files = list(sorted(os.listdir(os.path.join(pre_dir, fold)))) 122 | if not evaluate_all: 123 | files.remove('gt_pose.mat') 124 | else: 125 | pass 126 | # print("len(files):"+str(len(files))) 127 | for ind in range(len(files)): 128 | file_ = "panoimg_"+str(ind)+".jpg" 129 | files_.append(os.path.join(pre_dir, fold, file_)) 130 | all_files.extend(files_) 131 | # all_files.remove('trajectory.mp4') 132 | # all_files = [i for i in all_files if not i.endswith(".npy")] 133 | 134 | traj_len = len(all_files) 135 | file_size = traj_len/len(fold_list) 136 | 137 | # Initialize pandas DataFrame 138 | if evaluate_all: 139 | df_train = pd.DataFrame(columns=['file']) 140 | df_test = pd.DataFrame(columns=['file']) 141 | else: 142 | df_train = pd.DataFrame(columns=['file','x','y']) 143 | df_test = pd.DataFrame(columns=['file','x','y']) 144 | 145 | if not evaluate_all: 146 | df_files_test = [] 147 | df_files_train =[] 148 | 149 | df_locations_tr_x = [] 150 | df_locations_tr_y = [] 151 | 152 | df_locations_ts_x = [] 153 | df_locations_ts_y = [] 154 | 155 | # print("os.path.join(pre_dir,filename):"+str(os.path.join(pre_dir,filename))) 156 | df_locations = torch.zeros((traj_len, 2), dtype = torch.float) 157 | for count, fold in enumerate(fold_list): 158 | data = sio.loadmat(os.path.join(pre_dir,fold,filename)) 159 | df_location = data['pose'] 160 | df_locations[int(count*file_size):int((count+1)*file_size)] = torch.tensor(df_location, dtype = torch.float) 161 | 162 | # df_locations = df_locations['pose'] 163 | # df_locations = torch.tensor(df_locations, dtype = torch.float).cpu() 164 | else: 165 | df_files_test = [] 166 | df_files_train =[] 167 | 168 | #n-40 Training 40 testing 169 | test_sample = len(fold_list)*10 170 | test_index = random.choices(range(traj_len), k=test_sample) 171 | train_index = list(range(traj_len)) 172 | #for i in test_index: 173 | # train_index.pop(i) 174 | if not evaluate_all: 175 | df_locations_tr_x.extend(list(df_locations[train_index,0])) 176 | df_locations_tr_y.extend(list(df_locations[train_index,1])) 177 | 178 | df_locations_ts_x.extend(list(df_locations[test_index,0])) 179 | df_locations_ts_y.extend(list(df_locations[test_index,1])) 180 | 181 | for indx in range(traj_len): 182 | # file_ = 'panoimg_'+str(indx)+'.png' 183 | if indx in test_index: 184 | df_files_test.append(all_files[indx]) 185 | df_files_train.append(all_files[indx]) 186 | 187 | if not evaluate_all: 188 | #print("df_files_train:"+str((df_files_train))) 189 | df_train = pd.DataFrame(list(zip(df_files_train, df_locations_tr_x, df_locations_tr_y)), 190 | columns =['file','x', 'y']) 191 | df_test = pd.DataFrame(list(zip(df_files_test, df_locations_ts_x, df_locations_ts_y)), 192 | columns =['file','x', 'y']) 193 | else: 194 | df_train = pd.DataFrame(list(zip(df_files_train)), 195 | columns =['file']) 196 | df_test = pd.DataFrame(list(zip(df_files_test)), 197 | columns =['file']) 198 | print("Number of training submaps: "+str(len(df_train['file']))) 199 | print("Number of non-disjoint test submaps: "+str(len(df_test['file']))) 200 | 201 | 202 | #construct_query_dict(df_train,len(folders),"evaluation_database.pickle",False) 203 | if inside == False: 204 | if not evaluate_all: 205 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"generating_queries/evaluation_database.pickle", "generating_queries/evaluation_query.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 206 | else: 207 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"generating_queries/evaluation_database_full.pickle", "generating_queries/evaluation_query_full.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 208 | else: 209 | if not evaluate_all: 210 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"evaluation_database.pickle", "evaluation_query.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 211 | else: 212 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"evaluation_database_full.pickle", "evaluation_query_full.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 213 | if __name__ == "__main__": 214 | generate(1, evaluate_all=True) 215 | generate(1, evaluate_all=False) -------------------------------------------------------------------------------- /generating_queries/generate_test_RGB_real_supervise_sets.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pickle 4 | import random 5 | import set_path 6 | 7 | import numpy as np 8 | import pandas as pd 9 | from sklearn.neighbors import KDTree 10 | 11 | import config as cfg 12 | 13 | import scipy.io as sio 14 | import torch 15 | import json 16 | 17 | ########################################## 18 | 19 | def output_to_file(output, filename): 20 | with open(filename, 'wb') as handle: 21 | pickle.dump(output, handle, protocol=pickle.HIGHEST_PROTOCOL) 22 | print("Done ", filename) 23 | 24 | ######################################### 25 | def construct_query_dict(df_centroids, df_database, folder_num, traj_len, filename_train, filename_test, nn_ind, r_mid, r_ind, test=False, evaluate_all=False): 26 | database_trees = [] 27 | test_trees = [] 28 | if not evaluate_all: 29 | tree = KDTree(df_centroids[['x','y']]) 30 | ind_nn = tree.query_radius(df_centroids[['x','y']],r=nn_ind) 31 | ind_r = tree.query_radius(df_centroids[['x','y']], r=r_ind) 32 | queries_sets = [] 33 | database_sets = [] 34 | 35 | #for folder in range(folder_num): 36 | queries = {} 37 | for i in range(len(df_centroids)): 38 | #temp_indx = folder*len(df_centroids)//folder_num + i 39 | temp_indx = i 40 | query = df_centroids.iloc[temp_indx]["file"] 41 | #print("folder:"+str(folder)) 42 | #print("query:"+str(query)) 43 | if not evaluate_all: 44 | queries[len(queries.keys())] = {"query":query, 45 | "x":float(df_centroids.iloc[temp_indx]['x']),"y":float(df_centroids.iloc[temp_indx]['y'])} 46 | else: 47 | queries[len(queries.keys())] = {"query":query} 48 | 49 | queries_sets.append(queries) 50 | if not evaluate_all: 51 | test_tree = KDTree(df_centroids[['x','y']]) 52 | test_trees.append(test_tree) 53 | 54 | ############################### 55 | #for folder in range(folder_num): 56 | dataset = {} 57 | for i in range(len(df_database)): 58 | #temp_indx = folder*len(df_database)//folder_num + i 59 | temp_indx = i 60 | data = df_database.iloc[temp_indx]["file"] 61 | if not evaluate_all: 62 | dataset[len(dataset.keys())] = {"query":data, 63 | "x":float(df_database.iloc[temp_indx]['x']),"y":float(df_database.iloc[temp_indx]['y']) } 64 | else: 65 | dataset[len(dataset.keys())] = {"query":data} 66 | database_sets.append(dataset) 67 | if not evaluate_all: 68 | database_tree = KDTree(df_database[['x','y']]) 69 | database_trees.append(database_tree) 70 | ################################## 71 | if test: 72 | if not evaluate_all: 73 | #for i in range(len(database_sets)): 74 | tree = database_trees[0] 75 | #for j in range(len(queries_sets)): 76 | #if(i == j): 77 | # continue 78 | #print("len(queries_sets[j].keys():"+str(len(queries_sets[j].keys()))) 79 | #assert(0) 80 | for key in range(len(queries_sets[0].keys())): 81 | coor = np.array( 82 | [[queries_sets[0][key]["x"],queries_sets[0][key]["y"]]]) 83 | index = tree.query_radius(coor, r=r_mid) 84 | # indices of the positive matches in database i of each query (key) in test set j 85 | queries_sets[0][key][0] = index[0].tolist() 86 | else: 87 | pass 88 | 89 | output_to_file(queries_sets, filename_test) 90 | output_to_file(database_sets, filename_train) 91 | 92 | def generate(evaluate_all = False, inside=True): 93 | base_path = "/mnt/NAS/data/cc_data/2D_RGB_real_edited3" 94 | # runs_folder = cfg.scene_list[scene_index] 95 | #runs_folder = "Goffs" 96 | pre_dir = os.path.join(base_path) 97 | 98 | nn_ind = 0.2 99 | r_mid = 0.2 100 | r_ind = 0.6 101 | 102 | filename = "gt_pose.mat" 103 | 104 | folders = list(sorted(os.listdir(pre_dir))) 105 | if evaluate_all == False: 106 | index_list = list(range(len(folders))) 107 | else: 108 | index_list = list(range(len(folders))) 109 | 110 | fold_list = [] 111 | for index in index_list: 112 | fold_list.append(folders[index]) 113 | 114 | all_files = [] 115 | for fold in fold_list: 116 | files_ = [] 117 | files = list(sorted(os.listdir(os.path.join(pre_dir, fold)))) 118 | files.remove('gt_pose.mat') 119 | # print("len(files):"+str(len(files))) 120 | for ind in range(len(files)): 121 | file_ = "panoimg_"+str(ind)+".jpg" 122 | files_.append(os.path.join(pre_dir, fold, file_)) 123 | all_files.extend(files_) 124 | # all_files.remove('trajectory.mp4') 125 | # all_files = [i for i in all_files if not i.endswith(".npy")] 126 | 127 | traj_len = len(all_files) 128 | file_size = traj_len/len(fold_list) 129 | 130 | # Initialize pandas DataFrame 131 | if evaluate_all: 132 | df_train = pd.DataFrame(columns=['file']) 133 | df_test = pd.DataFrame(columns=['file']) 134 | else: 135 | df_train = pd.DataFrame(columns=['file','x','y']) 136 | df_test = pd.DataFrame(columns=['file','x','y']) 137 | 138 | if not evaluate_all: 139 | df_files_test = [] 140 | df_files_train =[] 141 | 142 | df_locations_tr_x = [] 143 | df_locations_tr_y = [] 144 | 145 | df_locations_ts_x = [] 146 | df_locations_ts_y = [] 147 | 148 | # print("os.path.join(pre_dir,filename):"+str(os.path.join(pre_dir,filename))) 149 | df_locations = torch.zeros((traj_len, 2), dtype = torch.float) 150 | for count, fold in enumerate(fold_list): 151 | data = sio.loadmat(os.path.join(pre_dir,fold,filename)) 152 | df_location = data['pose'] 153 | df_locations[int(count*file_size):int((count+1)*file_size)] = torch.tensor(df_location, dtype = torch.float) 154 | 155 | # df_locations = df_locations['pose'] 156 | # df_locations = torch.tensor(df_locations, dtype = torch.float).cpu() 157 | else: 158 | df_files_test = [] 159 | df_files_train =[] 160 | 161 | #n-40 Training 40 testing 162 | test_sample = len(fold_list)*10 163 | test_index = random.choices(range(traj_len), k=test_sample) 164 | train_index = list(range(traj_len)) 165 | #for i in test_index: 166 | # train_index.pop(i) 167 | if not evaluate_all: 168 | df_locations_tr_x.extend(list(df_locations[train_index,0])) 169 | df_locations_tr_y.extend(list(df_locations[train_index,1])) 170 | 171 | df_locations_ts_x.extend(list(df_locations[test_index,0])) 172 | df_locations_ts_y.extend(list(df_locations[test_index,1])) 173 | 174 | for indx in range(traj_len): 175 | # file_ = 'panoimg_'+str(indx)+'.png' 176 | if indx in test_index: 177 | df_files_test.append(all_files[indx]) 178 | df_files_train.append(all_files[indx]) 179 | 180 | if not evaluate_all: 181 | df_train = pd.DataFrame(list(zip(df_files_train, df_locations_tr_x, df_locations_tr_y)), 182 | columns =['file','x', 'y']) 183 | df_test = pd.DataFrame(list(zip(df_files_test, df_locations_ts_x, df_locations_ts_y)), 184 | columns =['file','x', 'y']) 185 | else: 186 | df_train = pd.DataFrame(list(zip(df_files_train)), 187 | columns =['file']) 188 | df_test = pd.DataFrame(list(zip(df_files_test)), 189 | columns =['file']) 190 | print("Number of training submaps: "+str(len(df_train['file']))) 191 | print("Number of non-disjoint test submaps: "+str(len(df_test['file']))) 192 | 193 | 194 | #construct_query_dict(df_train,len(folders),"evaluation_database.pickle",False) 195 | if inside == False: 196 | if not evaluate_all: 197 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"generating_queries/evaluation_database.pickle", "generating_queries/evaluation_query.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 198 | else: 199 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"generating_queries/evaluation_database_full.pickle", "generating_queries/evaluation_query_full.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 200 | else: 201 | if not evaluate_all: 202 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"evaluation_database.pickle", "evaluation_query.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 203 | else: 204 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"evaluation_database_full.pickle", "evaluation_query_full.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 205 | if __name__ == "__main__": 206 | generate(evaluate_all=False) -------------------------------------------------------------------------------- /generating_queries/generate_test_RGB_supervise_sets.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pickle 4 | import random 5 | import set_path 6 | 7 | import numpy as np 8 | import pandas as pd 9 | from sklearn.neighbors import KDTree 10 | 11 | import config as cfg 12 | 13 | import scipy.io as sio 14 | import torch 15 | import json 16 | 17 | ########################################## 18 | 19 | def output_to_file(output, filename): 20 | with open(filename, 'wb') as handle: 21 | pickle.dump(output, handle, protocol=pickle.HIGHEST_PROTOCOL) 22 | print("Done ", filename) 23 | 24 | ######################################### 25 | def construct_query_dict(df_centroids, df_database, folder_num, traj_len, filename_train, filename_test, nn_ind, r_mid, r_ind, test=False, evaluate_all=False): 26 | database_trees = [] 27 | test_trees = [] 28 | if not evaluate_all: 29 | tree = KDTree(df_centroids[['x','y']]) 30 | ind_nn = tree.query_radius(df_centroids[['x','y']],r=nn_ind) 31 | ind_r = tree.query_radius(df_centroids[['x','y']], r=r_ind) 32 | queries_sets = [] 33 | database_sets = [] 34 | 35 | queries = {} 36 | for i in range(len(df_centroids)): 37 | temp_indx = i 38 | query = df_centroids.iloc[temp_indx]["file"] 39 | 40 | if not evaluate_all: 41 | queries[len(queries.keys())] = {"query":query, 42 | "x":float(df_centroids.iloc[temp_indx]['x']),"y":float(df_centroids.iloc[temp_indx]['y'])} 43 | else: 44 | queries[len(queries.keys())] = {"query":query} 45 | 46 | queries_sets.append(queries) 47 | if not evaluate_all: 48 | test_tree = KDTree(df_centroids[['x','y']]) 49 | test_trees.append(test_tree) 50 | 51 | ############################### 52 | dataset = {} 53 | for i in range(len(df_database)): 54 | temp_indx = i 55 | data = df_database.iloc[temp_indx]["file"] 56 | if not evaluate_all: 57 | dataset[len(dataset.keys())] = {"query":data, 58 | "x":float(df_database.iloc[temp_indx]['x']),"y":float(df_database.iloc[temp_indx]['y']) } 59 | else: 60 | dataset[len(dataset.keys())] = {"query":data} 61 | database_sets.append(dataset) 62 | if not evaluate_all: 63 | database_tree = KDTree(df_database[['x','y']]) 64 | database_trees.append(database_tree) 65 | ################################## 66 | if test: 67 | if not evaluate_all: 68 | tree = database_trees[0] 69 | 70 | for key in range(len(queries_sets[0].keys())): 71 | coor = np.array( 72 | [[queries_sets[0][key]["x"],queries_sets[0][key]["y"]]]) 73 | index = tree.query_radius(coor, r=r_mid) 74 | # indices of the positive matches in database i of each query (key) in test set j 75 | queries_sets[0][key][0] = index[0].tolist() 76 | else: 77 | pass 78 | 79 | output_to_file(queries_sets, filename_test) 80 | output_to_file(database_sets, filename_train) 81 | 82 | def generate(scene_index, evaluate_all = False, inside=True): 83 | base_path = "/mnt/NAS/home/cc/data/habitat_4/train" 84 | runs_folder = cfg.scene_list[scene_index] 85 | pre_dir = os.path.join(base_path, runs_folder) 86 | 87 | nn_ind = 0.2 88 | r_mid = 0.2 89 | r_ind = 0.6 90 | 91 | filename = "gt_pose.mat" 92 | 93 | folders = list(sorted(os.listdir(pre_dir))) 94 | if evaluate_all == False: 95 | index_list = list(range(len(folders))) 96 | else: 97 | index_list = list(range(len(folders))) 98 | 99 | fold_list = [] 100 | for index in index_list: 101 | fold_list.append(folders[index]) 102 | 103 | all_files = [] 104 | for fold in fold_list: 105 | files_ = [] 106 | files = list(sorted(os.listdir(os.path.join(pre_dir, fold)))) 107 | files.remove('gt_pose.mat') 108 | # print("len(files):"+str(len(files))) 109 | for ind in range(len(files)): 110 | file_ = "panoimg_"+str(ind)+".png" 111 | files_.append(os.path.join(pre_dir, fold, file_)) 112 | all_files.extend(files_) 113 | 114 | traj_len = len(all_files) 115 | file_size = traj_len/len(fold_list) 116 | 117 | # Initialize pandas DataFrame 118 | if evaluate_all: 119 | df_train = pd.DataFrame(columns=['file']) 120 | df_test = pd.DataFrame(columns=['file']) 121 | else: 122 | df_train = pd.DataFrame(columns=['file','x','y']) 123 | df_test = pd.DataFrame(columns=['file','x','y']) 124 | 125 | if not evaluate_all: 126 | df_files_test = [] 127 | df_files_train =[] 128 | 129 | df_locations_tr_x = [] 130 | df_locations_tr_y = [] 131 | 132 | df_locations_ts_x = [] 133 | df_locations_ts_y = [] 134 | 135 | df_locations = torch.zeros((traj_len, 3), dtype = torch.float) 136 | for count, fold in enumerate(fold_list): 137 | data = sio.loadmat(os.path.join(pre_dir,fold,filename)) 138 | df_location = data['pose'] 139 | df_locations[int(count*file_size):int((count+1)*file_size)] = torch.tensor(df_location, dtype = torch.float) 140 | 141 | else: 142 | df_files_test = [] 143 | df_files_train =[] 144 | 145 | #n-40 Training 40 testing 146 | test_sample = len(fold_list)*10 147 | test_index = random.choices(range(traj_len), k=test_sample) 148 | train_index = list(range(traj_len)) 149 | if not evaluate_all: 150 | df_locations_tr_x.extend(list(df_locations[train_index,0])) 151 | df_locations_tr_y.extend(list(df_locations[train_index,2])) 152 | 153 | df_locations_ts_x.extend(list(df_locations[test_index,0])) 154 | df_locations_ts_y.extend(list(df_locations[test_index,2])) 155 | 156 | for indx in range(traj_len): 157 | if indx in test_index: 158 | df_files_test.append(all_files[indx]) 159 | df_files_train.append(all_files[indx]) 160 | 161 | if not evaluate_all: 162 | df_train = pd.DataFrame(list(zip(df_files_train, df_locations_tr_x, df_locations_tr_y)), 163 | columns =['file','x', 'y']) 164 | df_test = pd.DataFrame(list(zip(df_files_test, df_locations_ts_x, df_locations_ts_y)), 165 | columns =['file','x', 'y']) 166 | else: 167 | df_train = pd.DataFrame(list(zip(df_files_train)), 168 | columns =['file']) 169 | df_test = pd.DataFrame(list(zip(df_files_test)), 170 | columns =['file']) 171 | print("Number of training submaps: "+str(len(df_train['file']))) 172 | print("Number of non-disjoint test submaps: "+str(len(df_test['file']))) 173 | 174 | 175 | if inside == False: 176 | if not evaluate_all: 177 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"generating_queries/evaluation_database.pickle", "generating_queries/evaluation_query.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 178 | else: 179 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"generating_queries/evaluation_database_full.pickle", "generating_queries/evaluation_query_full.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 180 | else: 181 | if not evaluate_all: 182 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"evaluation_database.pickle", "evaluation_query.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 183 | else: 184 | construct_query_dict(df_train, df_train, len(fold_list), traj_len,"evaluation_database_full.pickle", "evaluation_query_full.pickle", nn_ind, r_mid, r_ind, True, evaluate_all) 185 | if __name__ == "__main__": 186 | generate(1, evaluate_all=False) -------------------------------------------------------------------------------- /generating_queries/generate_training_tuples_PCL_baseline.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pickle 3 | import random 4 | import set_path 5 | 6 | import numpy as np 7 | import pandas as pd 8 | from sklearn.neighbors import KDTree 9 | 10 | import config as cfg 11 | 12 | import scipy.io as sio 13 | import torch 14 | 15 | 16 | #####For training and test data split##### 17 | 18 | 19 | def construct_dict(df_files, df_indices, filename, folder_size, folder_num, all_folders, pre_dir, k_nearest, k_furthest): 20 | pos_index_range = list(range(-k_nearest//2, (k_nearest//2)+1)) 21 | mid_index_range = list(range(-k_nearest, (k_nearest)+1)) 22 | pos_index_range.remove(0) 23 | replace_counts = 0 24 | queries = {} 25 | for num in range(folder_num): 26 | for index in range(len(df_indices)//folder_num): 27 | df_indice = df_indices[num * (len(df_indices)//folder_num) + index] 28 | positive_l = [] 29 | negative_l = list(range(num*folder_size,(num+1)*folder_size,1)) 30 | for index_pos in pos_index_range: 31 | if (index_pos + df_indice >= 0) and (index_pos + df_indice <= folder_size -1): 32 | positive_l.append(index_pos + df_indice+folder_size*num) 33 | for index_pos in mid_index_range: 34 | if (index_pos + df_indice >= 0) and (index_pos + df_indice <= folder_size -1): 35 | negative_l.remove(index_pos + df_indice+folder_size*num) 36 | queries[num * (len(df_indices)//folder_num) + index] = {"query":df_files[num * (len(df_indices)//folder_num) + index], 37 | "positives":positive_l,"negatives":negative_l} 38 | 39 | #print("replace_counts:"+str(replace_counts)) 40 | #print("queries:"+str(queries[0][0])) 41 | 42 | with open(filename, 'wb') as handle: 43 | pickle.dump(queries, handle, protocol=pickle.HIGHEST_PROTOCOL) 44 | 45 | print("Done ", filename) 46 | 47 | def generate(data_index): 48 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 49 | base_path = cfg.DATASET_FOLDER 50 | runs_folder = "dm_data/" 51 | print("cfg.DATASET_FOLDER:"+str(cfg.DATASET_FOLDER)) 52 | 53 | cc_dir = "/home/cc/" 54 | all_folders = sorted(os.listdir(os.path.join(cc_dir,runs_folder))) 55 | 56 | folders = [] 57 | # All runs are used for training (both full and partial) 58 | index_list = range(len(all_folders)) 59 | print("Number of runs: "+str(len(index_list))) 60 | for index in index_list: 61 | folders.append(all_folders[index]) 62 | 63 | # Initialize pandas DataFrame 64 | k_nearest = 10 65 | k_furthest = 50 66 | 67 | df_train = pd.DataFrame(columns=['file','positives','negatives']) 68 | df_test = pd.DataFrame(columns=['file','positives','negatives']) 69 | 70 | df_files_test = [] 71 | df_files_train =[] 72 | df_files_all =[] 73 | 74 | df_indices_train = [] 75 | df_indices_test = [] 76 | df_indices_all = [] 77 | 78 | folder_num = len(folders) 79 | 80 | for folder in folders: 81 | all_files = list(sorted(os.listdir(os.path.join(cc_dir,runs_folder,folder)))) 82 | all_files.remove('gt_pose.mat') 83 | all_files.remove('gt_pose.png') 84 | 85 | folder_size = len(all_files) 86 | test_index = random.sample(range(folder_size), k=2) 87 | train_index = list(range(folder_size)) 88 | for ts_ind in test_index: 89 | train_index.remove(ts_ind) 90 | 91 | for (indx, file_) in enumerate(all_files): 92 | if indx in test_index: 93 | df_files_test.append(os.path.join(cc_dir,runs_folder,folder,file_)) 94 | df_indices_test.append(indx) 95 | else: 96 | df_files_train.append(os.path.join(cc_dir,runs_folder,folder,file_)) 97 | df_indices_train.append(indx) 98 | 99 | df_files_all.append(os.path.join(cc_dir,runs_folder,folder,file_)) 100 | df_indices_all.append(indx) 101 | pre_dir = os.path.join(cc_dir,runs_folder) 102 | 103 | if not os.path.exists(cfg.PICKLE_FOLDER): 104 | os.mkdir(cfg.PICKLE_FOLDER) 105 | 106 | construct_dict(df_files_train, df_indices_train, "train_pickle/training_queries_baseline_"+str(data_index)+".pickle", folder_size, folder_num, all_folders, pre_dir, k_nearest, k_furthest) 107 | construct_dict(df_files_test, df_indices_test, "train_pickle/test_queries_baseline_"+str(data_index)+".pickle", folder_size, folder_num, all_folders, pre_dir, k_nearest, k_furthest) 108 | construct_dict(df_files_all, df_indices_all, "train_pickle/all_queries_baseline_"+str(data_index)+".pickle", folder_size, folder_num, all_folders, pre_dir, k_nearest, k_furthest) 109 | if __name__ == "__main__": 110 | for i in range(1): 111 | generate(i) 112 | -------------------------------------------------------------------------------- /generating_queries/generate_training_tuples_PCL_ours.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import pickle 4 | import random 5 | import set_path 6 | 7 | import numpy as np 8 | import pandas as pd 9 | from sklearn.neighbors import KDTree 10 | 11 | import config as cfg 12 | 13 | import scipy.io as sio 14 | import torch 15 | 16 | 17 | #####For training and test data split##### 18 | 19 | 20 | def construct_dict(df_files, df_indices, filename, folder_size, folder_num, all_folders, pre_dir, k_nearest, k_furthest, definite_positives=None): 21 | pos_index_range = list(range(-k_nearest//2, (k_nearest//2)+1)) 22 | mid_index_range = list(range(-k_nearest, (k_nearest)+1)) 23 | pos_index_range.remove(0) 24 | 25 | replace_counts = 0 26 | queries = {} 27 | for num in range(folder_num): 28 | 29 | for index in range(len(df_indices)//folder_num): 30 | df_indice = df_indices[num * (len(df_indices)//folder_num) + index] 31 | positive_l = [] 32 | negative_l = list(range(num*folder_size,(num+1)*folder_size,1)) 33 | for index_pos in pos_index_range: 34 | if (index_pos + df_indice >= 0) and (index_pos + df_indice <= folder_size -1): 35 | positive_l.append(index_pos + df_indice+folder_size*num) 36 | for index_pos in mid_index_range: 37 | if (index_pos + df_indice >= 0) and (index_pos + df_indice <= folder_size -1): 38 | negative_l.remove(index_pos + df_indice+folder_size*num) 39 | if definite_positives is not None: 40 | 41 | if ((np.array(definite_positives[num][df_indice]).ndim) == 2) and (np.array(definite_positives[num][df_indice]).shape[0]!=0): 42 | extend_element = definite_positives[num][df_indice][0] 43 | else: 44 | # print("extend_element_pre:"+str(definite_positives[num][df_indice])) 45 | extend_element = definite_positives[num][df_indice] 46 | 47 | positive_l.extend(extend_element) 48 | # print("positive_l:"+str(positive_l)) 49 | positive_l = list(set(positive_l)) 50 | negative_l = [i for i in negative_l if i not in extend_element] 51 | 52 | queries[num * (len(df_indices)//folder_num) + index] = {"query":df_files[num * (len(df_indices)//folder_num) + index], 53 | "positives":positive_l,"negatives":negative_l} 54 | 55 | #print("replace_counts:"+str(replace_counts)) 56 | #print("queries:"+str(queries[0][0])) 57 | 58 | with open(filename, 'wb') as handle: 59 | pickle.dump(queries, handle, protocol=pickle.HIGHEST_PROTOCOL) 60 | 61 | print("Done ", filename) 62 | 63 | def generate(data_index, definite_positives=None, inside=True): 64 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 65 | base_path = cfg.DATASET_FOLDER 66 | runs_folder = "dm_data/" 67 | print("cfg.DATASET_FOLDER:"+str(cfg.DATASET_FOLDER)) 68 | 69 | cc_dir = "/home/cc/" 70 | all_folders = sorted(os.listdir(os.path.join(cc_dir,runs_folder))) 71 | 72 | folders = [] 73 | # All runs are used for training (both full and partial) 74 | index_list = range(len(all_folders)) 75 | print("Number of runs: "+str(len(index_list))) 76 | for index in index_list: 77 | folders.append(all_folders[index]) 78 | 79 | # Initialize pandas DataFrame 80 | k_nearest = 10 81 | k_furthest = 50 82 | 83 | df_train = pd.DataFrame(columns=['file','positives','negatives']) 84 | df_test = pd.DataFrame(columns=['file','positives','negatives']) 85 | 86 | df_files_test = [] 87 | df_files_train =[] 88 | df_files = [] 89 | 90 | df_indices_train = [] 91 | df_indices_test = [] 92 | df_indices = [] 93 | 94 | folder_num = len(folders) 95 | 96 | for folder in folders: 97 | all_files = list(sorted(os.listdir(os.path.join(cc_dir,runs_folder,folder)))) 98 | all_files.remove('gt_pose.mat') 99 | all_files.remove('gt_pose.png') 100 | 101 | folder_size = len(all_files) 102 | test_index = random.sample(range(folder_size), k=2) 103 | train_index = list(range(folder_size)) 104 | for ts_ind in test_index: 105 | train_index.remove(ts_ind) 106 | 107 | for (indx, file_) in enumerate(all_files): 108 | if indx in test_index: 109 | df_files_test.append(os.path.join(cc_dir,runs_folder,folder,file_)) 110 | df_indices_test.append(indx) 111 | else: 112 | df_files_train.append(os.path.join(cc_dir,runs_folder,folder,file_)) 113 | df_indices_train.append(indx) 114 | df_files.append(os.path.join(cc_dir,runs_folder,folder,file_)) 115 | df_indices.append(indx) 116 | 117 | pre_dir = os.path.join(cc_dir,runs_folder) 118 | 119 | if not os.path.exists(cfg.PICKLE_FOLDER): 120 | os.mkdir(cfg.PICKLE_FOLDER) 121 | 122 | if inside == True: 123 | construct_dict(df_files_train, df_indices_train, "train_pickle/training_queries_baseline_"+str(data_index)+".pickle", folder_size, folder_num, all_folders, pre_dir, k_nearest, k_furthest) 124 | construct_dict(df_files_test, df_indices_test, "train_pickle/test_queries_baseline_"+str(data_index)+".pickle", folder_size, folder_num, all_folders, pre_dir, k_nearest, k_furthest) 125 | construct_dict(df_files, df_indices, "train_pickle/db_queries_baseline_"+str(data_index)+".pickle", folder_size, folder_num, all_folders, pre_dir, k_nearest, k_furthest) 126 | 127 | else: 128 | construct_dict(df_files_train, df_indices_train, "generating_queries/train_pickle/training_queries_baseline_"+str(data_index)+".pickle", folder_size, folder_num, all_folders, pre_dir, k_nearest, k_furthest, definite_positives=definite_positives) 129 | construct_dict(df_files_test, df_indices_test, "generating_queries/train_pickle/test_queries_baseline_"+str(data_index)+".pickle", folder_size, folder_num, all_folders, pre_dir, k_nearest, k_furthest, definite_positives=definite_positives) 130 | construct_dict(df_files, df_indices, "generating_queries/train_pickle/db_queries_baseline_"+str(data_index)+".pickle", folder_size, folder_num, all_folders, pre_dir, k_nearest, k_furthest, definite_positives=definite_positives) 131 | 132 | if __name__ == "__main__": 133 | for i in range(1): 134 | generate(i) -------------------------------------------------------------------------------- /generating_queries/generate_training_tuples_PCL_supervise.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pickle 3 | import random 4 | import set_path 5 | 6 | import numpy as np 7 | import pandas as pd 8 | from sklearn.neighbors import KDTree 9 | 10 | import config as cfg 11 | 12 | import scipy.io as sio 13 | import torch 14 | 15 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 16 | base_path = cfg.DATASET_FOLDER 17 | 18 | runs_folder = "dm_data/" 19 | filename = "gt_pose.mat" 20 | pointcloud_fols = "/pointcloud_20m_10overlap/" 21 | 22 | print("cfg.DATASET_FOLDER:"+str(cfg.DATASET_FOLDER)) 23 | 24 | cc_dir = "/home/cc/" 25 | all_folders = sorted(os.listdir(os.path.join(cc_dir,runs_folder))) 26 | 27 | folders = [] 28 | 29 | # All runs are used for training (both full and partial) 30 | index_list = range(18) 31 | print("Number of runs: "+str(len(index_list))) 32 | for index in index_list: 33 | folders.append(all_folders[index]) 34 | print(folders) 35 | 36 | 37 | #####For training and test data split##### 38 | 39 | 40 | def construct_query_dict(df_centroids, train_index, test_index, filename_train, filename_test): 41 | tree = KDTree(df_centroids[['x','y']]) 42 | ind_nn = tree.query_radius(df_centroids[['x','y']],r=15) 43 | ind_r = tree.query_radius(df_centroids[['x','y']], r=50) 44 | queries = {} 45 | queries_test = {} 46 | 47 | #for i in range(len(ind_nn)): 48 | for i in train_index: 49 | query = df_centroids.iloc[i]["file"] 50 | positives = np.setdiff1d(ind_nn[i],[i]).tolist() 51 | negatives = np.setdiff1d( 52 | df_centroids.index.values.tolist(),ind_r[i]).tolist() 53 | random.shuffle(negatives) 54 | queries[i] = {"query":df_centroids.iloc[i]['file'], 55 | "positives":positives,"negatives":negatives} 56 | 57 | for i in test_index: 58 | query = df_centroids.iloc[i]["file"] 59 | positives = np.setdiff1d(ind_nn[i],[i]).tolist() 60 | negatives = np.setdiff1d( 61 | df_centroids.index.values.tolist(),ind_r[i]).tolist() 62 | random.shuffle(negatives) 63 | queries_test[i] = {"query":df_centroids.iloc[i]['file'], 64 | "positives":positives,"negatives":negatives} 65 | 66 | with open(filename_train, 'wb') as handle: 67 | pickle.dump(queries, handle, protocol=pickle.HIGHEST_PROTOCOL) 68 | with open(filename_test, 'wb') as handle: 69 | pickle.dump(queries_test, handle, protocol=pickle.HIGHEST_PROTOCOL) 70 | 71 | print("Done ", filename_train) 72 | print("Done ", filename_test) 73 | 74 | if not os.path.exists(cfg.PICKLE_FOLDER): 75 | os.mkdir(cfg.PICKLE_FOLDER) 76 | 77 | # Initialize pandas DataFrame 78 | df_train = pd.DataFrame(columns=['file','x','y']) 79 | df_test = pd.DataFrame(columns=['file','x','y']) 80 | df_file = pd.DataFrame(columns=['file','x','y']) 81 | 82 | df_files_test = [] 83 | df_files_train =[] 84 | df_files = [] 85 | 86 | df_indice_test = [] 87 | df_indice_train = [] 88 | df_indice = [] 89 | 90 | df_locations_tr_x = [] 91 | df_locations_tr_y = [] 92 | df_locations_ts_x = [] 93 | df_locations_ts_y = [] 94 | df_locations_db_x = [] 95 | df_locations_db_y = [] 96 | 97 | count = 0 98 | for folder in folders: 99 | df_locations = sio.loadmat(os.path.join( 100 | cc_dir,runs_folder,folder,filename)) 101 | 102 | df_locations = df_locations['pose'] 103 | df_locations = torch.tensor(df_locations, dtype = torch.float).cpu() 104 | 105 | #2038 Training 10 testing 106 | test_index = random.sample(range(len(df_locations)), k=10) 107 | df_indice_test.extend(np.array(test_index)+count*2048) 108 | train_index = list(range(df_locations.shape[0])) 109 | df_indice_train.extend(np.array(train_index)+count*2048) 110 | db_index = list(range(df_locations.shape[0])) 111 | count=count+1 112 | for i in test_index: 113 | train_index.remove(i) 114 | 115 | df_locations_tr_x.extend(list(df_locations[train_index,0])) 116 | df_locations_tr_y.extend(list(df_locations[train_index,1])) 117 | df_locations_ts_x.extend(list(df_locations[test_index,0])) 118 | df_locations_ts_y.extend(list(df_locations[test_index,1])) 119 | df_locations_db_x.extend(list(df_locations[db_index,0])) 120 | df_locations_db_y.extend(list(df_locations[db_index,1])) 121 | 122 | all_files = list(sorted(os.listdir(os.path.join(cc_dir,runs_folder,folder)))) 123 | all_files.remove('gt_pose.mat') 124 | all_files.remove('gt_pose.png') 125 | 126 | for (indx, file_) in enumerate(all_files): 127 | if indx in test_index: 128 | df_files_test.append(os.path.join(cc_dir,runs_folder,folder,file_)) 129 | else: 130 | df_files_train.append(os.path.join(cc_dir,runs_folder,folder,file_)) 131 | df_files.append(os.path.join(cc_dir,runs_folder,folder,file_)) 132 | 133 | 134 | print("df_locations_tr_x:"+str(len(df_locations_tr_x))) 135 | print("df_files_test:"+str(len(df_files_test))) 136 | 137 | df_train = pd.DataFrame(list(zip(df_files_train, df_locations_tr_x, df_locations_tr_y)), 138 | columns =['file','x', 'y']) 139 | df_test = pd.DataFrame(list(zip(df_files_test, df_locations_ts_x, df_locations_ts_y)), 140 | columns =['file','x', 'y']) 141 | df_file = pd.DataFrame(list(zip(df_files, df_locations_db_x, df_locations_db_y)), 142 | columns =['file','x', 'y']) 143 | 144 | 145 | print("Number of training submaps: "+str(len(df_train['file']))) 146 | print("Number of non-disjoint test submaps: "+str(len(df_test['file']))) 147 | 148 | construct_query_dict(df_file, df_indice_train, df_indice_test, "training_queries_baseline.pickle", "test_queries_baseline.pickle") 149 | #construct_query_dict(df_test,"test_queries_baseline.pickle") 150 | -------------------------------------------------------------------------------- /generating_queries/generate_training_tuples_RGB_baseline.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pickle 4 | import random 5 | import set_path 6 | 7 | import numpy as np 8 | import pandas as pd 9 | from sklearn.neighbors import KDTree 10 | 11 | import config as cfg 12 | 13 | import scipy.io as sio 14 | import torch 15 | 16 | #####For training and test data split##### 17 | 18 | def construct_dict(folder_num, df_files, df_files_all, df_indices, filename, pre_dir, k_nearest, k_furthest, traj_len, definite_positives=None): 19 | pos_index_range = list(range(-k_nearest//2, (k_nearest//2)+1)) 20 | mid_index_range = list(range(-k_nearest, (k_nearest)+1)) 21 | queries = {} 22 | count = 0 23 | traj_len = int(len(df_files_all)/folder_num) 24 | for df_indice in df_indices: 25 | cur_fold_num = int(df_indice//traj_len) 26 | file_index = int(df_indice%traj_len) 27 | positive_l = [] 28 | negative_l = list(range(cur_fold_num*traj_len, (cur_fold_num+1)*traj_len, 1)) 29 | 30 | cur_indice = df_indice % traj_len 31 | 32 | for index_pos in pos_index_range: 33 | if (index_pos + cur_indice >= 0) and (index_pos + cur_indice <= traj_len -1): 34 | positive_l.append(index_pos + df_indice) 35 | for index_pos in mid_index_range: 36 | if (index_pos + cur_indice >= 0) and (index_pos + cur_indice <= traj_len -1): 37 | negative_l.remove(index_pos + df_indice) 38 | #positive_l.append(df_indice) 39 | #positive_l.append(df_indice) 40 | #negative_l.remove(df_indice) 41 | 42 | if definite_positives is not None: 43 | if len(definite_positives)==1: 44 | if definite_positives[0][df_indice].ndim ==2: 45 | positive_l.extend(definite_positives[0][df_indice][0]) 46 | negative_l = [i for i in negative_l if i not in definite_positives[0][df_indice][0]] 47 | else: 48 | positive_l.extend(definite_positives[0][df_indice]) 49 | negative_l = [i for i in negative_l if i not in definite_positives[0][df_indice]] 50 | else: 51 | positive_l.extend(definite_positives[df_indice]) 52 | positive_l = list(set(positive_l)) 53 | negative_l = [i for i in negative_l if i not in definite_positives[df_indice]] 54 | 55 | queries[count] = {"query":df_files[count], 56 | "positives":positive_l,"negatives":negative_l} 57 | count = count + 1 58 | 59 | with open(filename, 'wb') as handle: 60 | pickle.dump(queries, handle, protocol=pickle.HIGHEST_PROTOCOL) 61 | 62 | print("Done ", filename) 63 | 64 | def generate(scene_index, data_index, definite_positives=None, inside=True): 65 | base_path = "/mnt/NAS/home/cc/data/habitat_4/train/" 66 | run_folder = cfg.scene_list[scene_index] 67 | base_path = os.path.join(base_path,run_folder) 68 | pre_dir = base_path 69 | ''' 70 | runs_folder = cfg.scene_names[scene_index] 71 | print("runs_folder2:"+str(runs_folder)) 72 | 73 | pre_dir = os.path.join(base_path, runs_folder) 74 | print("pre_dir:"+str(pre_dir)) 75 | ''' 76 | filename = "gt_pose.mat" 77 | 78 | # Initialize pandas DataFrame 79 | k_nearest = 10 80 | k_furthest = 50 81 | 82 | df_train = pd.DataFrame(columns=['file','positives','negatives']) 83 | df_test = pd.DataFrame(columns=['file','positives','negatives']) 84 | 85 | df_files_test = [] 86 | df_files_train =[] 87 | df_files = [] 88 | 89 | df_indices_train = [] 90 | df_indices_test = [] 91 | df_indices = [] 92 | 93 | fold_list = list(sorted(os.listdir(base_path))) 94 | all_files = [] 95 | for fold in fold_list: 96 | files_ = [] 97 | files = list(sorted(os.listdir(os.path.join(base_path, fold)))) 98 | files.remove('gt_pose.mat') 99 | # print("len(files):"+str(len(files))) 100 | for ind in range(len(files)): 101 | file_ = "panoimg_"+str(ind)+".png" 102 | files_.append(os.path.join(base_path, fold, file_)) 103 | all_files.extend(files_) 104 | 105 | traj_len = len(all_files) 106 | 107 | #n Training 10 testing 108 | test_sample = len(fold_list)*10 109 | file_index = list(range(traj_len)) 110 | test_index = random.sample(range(traj_len), k=test_sample) 111 | train_index = list(range(traj_len)) 112 | for ts_ind in test_index: 113 | train_index.remove(ts_ind) 114 | 115 | for indx in range(traj_len): 116 | # file_ = 'panoimg_'+str(indx)+'.png' 117 | if indx in test_index: 118 | df_files_test.append(all_files[indx]) 119 | df_indices_test.append(indx) 120 | else: 121 | df_files_train.append(all_files[indx]) 122 | df_indices_train.append(indx) 123 | df_files.append(all_files[indx]) 124 | df_indices.append(indx) 125 | 126 | if not os.path.exists(cfg.PICKLE_FOLDER): 127 | os.mkdir(cfg.PICKLE_FOLDER) 128 | 129 | if inside == True: 130 | construct_dict(len(fold_list),df_files_train, df_files,df_indices_train, "train_pickle/training_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list))) 131 | construct_dict(len(fold_list), df_files_test, df_files,df_indices_test, "train_pickle/test_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list))) 132 | construct_dict(len(fold_list), df_files,df_files, df_indices, "train_pickle/db_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list))) 133 | 134 | else: 135 | construct_dict(len(fold_list), df_files_train,df_files, df_indices_train, "generating_queries/train_pickle/training_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list)), definite_positives=definite_positives) 136 | construct_dict(len(fold_list), df_files_test,df_files, df_indices_test, "generating_queries/train_pickle/test_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list)), definite_positives=definite_positives) 137 | construct_dict(len(fold_list), df_files,df_files, df_indices, "generating_queries/train_pickle/db_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list)), definite_positives=definite_positives) 138 | 139 | if __name__ == "__main__": 140 | for i in range(1): 141 | generate(0,i) 142 | -------------------------------------------------------------------------------- /generating_queries/generate_training_tuples_RGB_ours.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pickle 4 | import random 5 | import set_path 6 | 7 | import numpy as np 8 | import pandas as pd 9 | from sklearn.neighbors import KDTree 10 | 11 | import config as cfg 12 | 13 | import scipy.io as sio 14 | import torch 15 | 16 | #####For training and test data split##### 17 | 18 | def construct_dict(folder_num, df_files, df_files_all, df_indices, filename, pre_dir, k_nearest, k_furthest, traj_len, definite_positives=None): 19 | pos_index_range = list(range(-k_nearest//2, (k_nearest//2)+1)) 20 | mid_index_range = list(range(-k_nearest, (k_nearest)+1)) 21 | queries = {} 22 | count = 0 23 | traj_len = int(len(df_files_all)/folder_num) 24 | for df_indice in df_indices: 25 | cur_fold_num = int(df_indice//traj_len) 26 | file_index = int(df_indice%traj_len) 27 | positive_l = [] 28 | negative_l = list(range(cur_fold_num*traj_len, (cur_fold_num+1)*traj_len, 1)) 29 | 30 | cur_indice = df_indice % traj_len 31 | 32 | for index_pos in pos_index_range: 33 | if (index_pos + cur_indice >= 0) and (index_pos + cur_indice <= traj_len -1): 34 | positive_l.append(index_pos + df_indice) 35 | for index_pos in mid_index_range: 36 | if (index_pos + cur_indice >= 0) and (index_pos + cur_indice <= traj_len -1): 37 | negative_l.remove(index_pos + df_indice) 38 | 39 | if definite_positives is not None: 40 | if len(definite_positives)==1: 41 | if definite_positives[0][df_indice].ndim ==2: 42 | positive_l.extend(definite_positives[0][df_indice][0]) 43 | negative_l = [i for i in negative_l if i not in definite_positives[0][df_indice][0]] 44 | else: 45 | positive_l.extend(definite_positives[0][df_indice]) 46 | negative_l = [i for i in negative_l if i not in definite_positives[0][df_indice]] 47 | else: 48 | positive_l.extend(definite_positives[df_indice]) 49 | positive_l = list(set(positive_l)) 50 | negative_l = [i for i in negative_l if i not in definite_positives[df_indice]] 51 | 52 | queries[count] = {"query":df_files[count], 53 | "positives":positive_l,"negatives":negative_l} 54 | count = count + 1 55 | 56 | with open(filename, 'wb') as handle: 57 | pickle.dump(queries, handle, protocol=pickle.HIGHEST_PROTOCOL) 58 | 59 | print("Done ", filename) 60 | 61 | def generate(scene_index, data_index, definite_positives=None, inside=True): 62 | base_path = "/mnt/NAS/home/cc/data/habitat_4/train/"#Goffs/" 63 | base_path = os.path.join(base_path,cfg.scene_list[scene_index]) 64 | pre_dir = base_path 65 | 66 | filename = "gt_pose.mat" 67 | 68 | # Initialize pandas DataFrame 69 | k_nearest = 10 70 | k_furthest = 50 71 | 72 | df_train = pd.DataFrame(columns=['file','positives','negatives']) 73 | df_test = pd.DataFrame(columns=['file','positives','negatives']) 74 | 75 | df_files_test = [] 76 | df_files_train =[] 77 | df_files = [] 78 | 79 | df_indices_train = [] 80 | df_indices_test = [] 81 | df_indices = [] 82 | 83 | fold_list = list(sorted(os.listdir(base_path))) 84 | all_files = [] 85 | for fold in fold_list: 86 | files_ = [] 87 | files = list(sorted(os.listdir(os.path.join(base_path, fold)))) 88 | files.remove('gt_pose.mat') 89 | # print("len(files):"+str(len(files))) 90 | for ind in range(len(files)): 91 | file_ = "panoimg_"+str(ind)+".png" 92 | files_.append(os.path.join(base_path, fold, file_)) 93 | all_files.extend(files_) 94 | 95 | traj_len = len(all_files) 96 | 97 | #n Training 10 testing 98 | test_sample = len(fold_list)*10 99 | file_index = list(range(traj_len)) 100 | test_index = random.sample(range(traj_len), k=test_sample) 101 | train_index = list(range(traj_len)) 102 | 103 | for indx in range(traj_len): 104 | if indx in test_index: 105 | df_files_test.append(all_files[indx]) 106 | df_indices_test.append(indx) 107 | else: 108 | df_files_train.append(all_files[indx]) 109 | df_indices_train.append(indx) 110 | df_files.append(all_files[indx]) 111 | df_indices.append(indx) 112 | 113 | if not os.path.exists(cfg.PICKLE_FOLDER): 114 | os.mkdir(cfg.PICKLE_FOLDER) 115 | 116 | if inside == True: 117 | construct_dict(len(fold_list),df_files_train, df_files,df_indices_train, "train_pickle/training_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list))) 118 | construct_dict(len(fold_list), df_files_test, df_files,df_indices_test, "train_pickle/test_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list))) 119 | construct_dict(len(fold_list), df_files,df_files, df_indices, "train_pickle/db_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list))) 120 | 121 | else: 122 | construct_dict(len(fold_list), df_files_train,df_files, df_indices_train, "generating_queries/train_pickle/training_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list)), definite_positives=definite_positives) 123 | construct_dict(len(fold_list), df_files_test,df_files, df_indices_test, "generating_queries/train_pickle/test_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list)), definite_positives=definite_positives) 124 | construct_dict(len(fold_list), df_files,df_files, df_indices, "generating_queries/train_pickle/db_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list)), definite_positives=definite_positives) 125 | 126 | if __name__ == "__main__": 127 | for i in range(1): 128 | generate(0,i) -------------------------------------------------------------------------------- /generating_queries/generate_training_tuples_RGB_real_baseline.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pickle 4 | import random 5 | import set_path 6 | 7 | import numpy as np 8 | import pandas as pd 9 | from sklearn.neighbors import KDTree 10 | 11 | import config as cfg 12 | 13 | import scipy.io as sio 14 | import torch 15 | 16 | #####For training and test data split##### 17 | 18 | def construct_dict(folder_num, df_files, df_files_all, df_indices, filename, pre_dir, k_nearest, k_furthest, traj_len, definite_positives=None): 19 | pos_index_range = list(range(-k_nearest//2, (k_nearest//2)+1)) 20 | pos_index_range.remove(0) 21 | mid_index_range = list(range(-k_furthest//2, (k_furthest)//2+1)) 22 | queries = {} 23 | count = 0 24 | traj_len = int(len(df_files_all)/folder_num) 25 | for df_indice in df_indices: 26 | cur_fold_num = int(df_indice//traj_len) 27 | file_index = int(df_indice%traj_len) 28 | positive_l = [] 29 | negative_l = list(range(cur_fold_num*traj_len, (cur_fold_num+1)*traj_len, 1)) 30 | 31 | cur_indice = df_indice % traj_len 32 | 33 | for index_pos in pos_index_range: 34 | if (index_pos + cur_indice >= 0) and (index_pos + cur_indice <= traj_len -1): 35 | positive_l.append(index_pos + df_indice) 36 | for index_pos in mid_index_range: 37 | if (index_pos + cur_indice >= 0) and (index_pos + cur_indice <= traj_len -1): 38 | negative_l.remove(index_pos + df_indice) 39 | #positive_l.append(df_indice) 40 | #positive_l.append(df_indice) 41 | #negative_l.remove(df_indice) 42 | 43 | if definite_positives is not None: 44 | if len(definite_positives)==1: 45 | if definite_positives[0][df_indice].ndim ==2: 46 | positive_l.extend(definite_positives[0][df_indice][0]) 47 | negative_l = [i for i in negative_l if i not in definite_positives[0][df_indice][0]] 48 | else: 49 | positive_l.extend(definite_positives[0][df_indice]) 50 | negative_l = [i for i in negative_l if i not in definite_positives[0][df_indice]] 51 | else: 52 | positive_l.extend(definite_positives[df_indice]) 53 | positive_l = list(set(positive_l)) 54 | negative_l = [i for i in negative_l if i not in definite_positives[df_indice]] 55 | 56 | queries[count] = {"query":df_files[count], 57 | "positives":positive_l,"negatives":negative_l} 58 | #print("query:"+str(df_files[count])) 59 | #print("positives:"+str(positive_l)) 60 | count = count + 1 61 | 62 | with open(filename, 'wb') as handle: 63 | pickle.dump(queries, handle, protocol=pickle.HIGHEST_PROTOCOL) 64 | 65 | print("Done ", filename) 66 | 67 | def generate(scene_index, data_index, definite_positives=None, inside=True): 68 | base_path = "/mnt/NAS/data/cc_data/2D_RGB_real_full3" 69 | pre_dir = base_path 70 | ''' 71 | runs_folder = cfg.scene_names[scene_index] 72 | print("runs_folder2:"+str(runs_folder)) 73 | 74 | pre_dir = os.path.join(base_path, runs_folder) 75 | print("pre_dir:"+str(pre_dir)) 76 | ''' 77 | filename = "gt_pose.mat" 78 | 79 | # Initialize pandas DataFrame 80 | k_nearest = 10 81 | k_furthest = 200 82 | 83 | df_train = pd.DataFrame(columns=['file','positives','negatives']) 84 | df_test = pd.DataFrame(columns=['file','positives','negatives']) 85 | 86 | df_files_test = [] 87 | df_files_train =[] 88 | df_files = [] 89 | 90 | df_indices_train = [] 91 | df_indices_test = [] 92 | df_indices = [] 93 | 94 | fold_list = list(sorted(os.listdir(base_path))) 95 | all_files = [] 96 | for fold in fold_list: 97 | files_ = [] 98 | files = list(sorted(os.listdir(os.path.join(base_path, fold)))) 99 | #files.remove('gt_pose.mat') 100 | # print("len(files):"+str(len(files))) 101 | for ind in range(len(files)): 102 | file_ = "panoimg_"+str(ind)+".jpg" 103 | files_.append(os.path.join(base_path, fold, file_)) 104 | all_files.extend(files_) 105 | 106 | traj_len = len(all_files) 107 | 108 | #n Training 10 testing 109 | test_sample = len(fold_list)*10 110 | file_index = list(range(traj_len)) 111 | test_index = random.sample(range(traj_len), k=test_sample) 112 | train_index = list(range(traj_len)) 113 | for ts_ind in test_index: 114 | train_index.remove(ts_ind) 115 | 116 | for indx in range(traj_len): 117 | # file_ = 'panoimg_'+str(indx)+'.png' 118 | if indx in test_index: 119 | df_files_test.append(all_files[indx]) 120 | df_indices_test.append(indx) 121 | else: 122 | df_files_train.append(all_files[indx]) 123 | df_indices_train.append(indx) 124 | df_files.append(all_files[indx]) 125 | df_indices.append(indx) 126 | 127 | if not os.path.exists(cfg.PICKLE_FOLDER): 128 | os.mkdir(cfg.PICKLE_FOLDER) 129 | 130 | if inside == True: 131 | construct_dict(len(fold_list),df_files_train, df_files,df_indices_train, "train_pickle/training_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list))) 132 | construct_dict(len(fold_list), df_files_test, df_files,df_indices_test, "train_pickle/test_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list))) 133 | construct_dict(len(fold_list), df_files,df_files, df_indices, "train_pickle/db_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list))) 134 | 135 | else: 136 | construct_dict(len(fold_list), df_files_train,df_files, df_indices_train, "generating_queries/train_pickle/training_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list)), definite_positives=definite_positives) 137 | construct_dict(len(fold_list), df_files_test,df_files, df_indices_test, "generating_queries/train_pickle/test_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list)), definite_positives=definite_positives) 138 | construct_dict(len(fold_list), df_files,df_files, df_indices, "generating_queries/train_pickle/db_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list)), definite_positives=definite_positives) 139 | 140 | if __name__ == "__main__": 141 | for i in range(1): 142 | generate(0,i) -------------------------------------------------------------------------------- /generating_queries/generate_training_tuples_RGB_real_ours.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pickle 4 | import random 5 | import set_path 6 | 7 | import numpy as np 8 | import pandas as pd 9 | from sklearn.neighbors import KDTree 10 | 11 | import config as cfg 12 | 13 | import scipy.io as sio 14 | import torch 15 | 16 | #####For training and test data split##### 17 | 18 | def construct_dict(folder_num, df_files, df_files_all, df_indices, filename, pre_dir, k_nearest, k_furthest, traj_len, definite_positives=None): 19 | pos_index_range = list(range(-k_nearest//2, (k_nearest//2)+1)) 20 | pos_index_range.remove(0) 21 | mid_index_range = list(range(-k_nearest, (k_nearest)+1)) 22 | queries = {} 23 | count = 0 24 | traj_len = int(len(df_files_all)/folder_num) 25 | for df_indice in df_indices: 26 | cur_fold_num = int(df_indice//traj_len) 27 | file_index = int(df_indice%traj_len) 28 | positive_l = [] 29 | negative_l = list(range(cur_fold_num*traj_len, (cur_fold_num+1)*traj_len, 1)) 30 | 31 | cur_indice = df_indice % traj_len 32 | 33 | for index_pos in pos_index_range: 34 | if (index_pos + cur_indice >= 0) and (index_pos + cur_indice <= traj_len -1): 35 | positive_l.append(index_pos + df_indice) 36 | for index_pos in mid_index_range: 37 | if (index_pos + cur_indice >= 0) and (index_pos + cur_indice <= traj_len -1): 38 | negative_l.remove(index_pos + df_indice) 39 | #positive_l.append(df_indice) 40 | #positive_l.append(df_indice) 41 | #negative_l.remove(df_indice) 42 | 43 | if definite_positives is not None: 44 | if len(definite_positives)==1: 45 | if (definite_positives[0][df_indice].ndim ==2) and (definite_positives[0][df_indice].shape[0]!=0) : 46 | positive_l.extend(definite_positives[0][df_indice][0]) 47 | negative_l = [i for i in negative_l if i not in definite_positives[0][df_indice][0]] 48 | else: 49 | positive_l.extend(definite_positives[0][df_indice]) 50 | negative_l = [i for i in negative_l if i not in definite_positives[0][df_indice]] 51 | else: 52 | positive_l.extend(definite_positives[df_indice]) 53 | positive_l = list(set(positive_l)) 54 | negative_l = [i for i in negative_l if i not in definite_positives[df_indice]] 55 | 56 | queries[count] = {"query":df_files[count], 57 | "positives":positive_l,"negatives":negative_l} 58 | count = count + 1 59 | 60 | with open(filename, 'wb') as handle: 61 | pickle.dump(queries, handle, protocol=pickle.HIGHEST_PROTOCOL) 62 | 63 | print("Done ", filename) 64 | 65 | def generate(scene_index, data_index, definite_positives=None, inside=True): 66 | base_path = "/mnt/NAS/data/cc_data/2D_RGB_real_full3" 67 | pre_dir = base_path 68 | ''' 69 | runs_folder = cfg.scene_names[scene_index] 70 | print("runs_folder2:"+str(runs_folder)) 71 | 72 | pre_dir = os.path.join(base_path, runs_folder) 73 | print("pre_dir:"+str(pre_dir)) 74 | ''' 75 | filename = "gt_pose.mat" 76 | 77 | # Initialize pandas DataFrame 78 | k_nearest = 10 79 | k_furthest = 100 80 | 81 | df_train = pd.DataFrame(columns=['file','positives','negatives']) 82 | df_test = pd.DataFrame(columns=['file','positives','negatives']) 83 | 84 | df_files_test = [] 85 | df_files_train =[] 86 | df_files = [] 87 | 88 | df_indices_train = [] 89 | df_indices_test = [] 90 | df_indices = [] 91 | 92 | fold_list = list(sorted(os.listdir(base_path))) 93 | all_files = [] 94 | for fold in fold_list: 95 | files_ = [] 96 | files = list(sorted(os.listdir(os.path.join(base_path, fold)))) 97 | #files.remove('gt_pose.mat') 98 | # print("len(files):"+str(len(files))) 99 | for ind in range(len(files)): 100 | file_ = "panoimg_"+str(ind)+".jpg" 101 | files_.append(os.path.join(base_path, fold, file_)) 102 | all_files.extend(files_) 103 | 104 | traj_len = len(all_files) 105 | 106 | #n Training 10 testing 107 | test_sample = len(fold_list)*10 108 | file_index = list(range(traj_len)) 109 | test_index = random.sample(range(traj_len), k=test_sample) 110 | train_index = list(range(traj_len)) 111 | #for ts_ind in test_index: 112 | # train_index.remove(ts_ind) 113 | 114 | for indx in range(traj_len): 115 | # file_ = 'panoimg_'+str(indx)+'.png' 116 | if indx in test_index: 117 | df_files_test.append(all_files[indx]) 118 | df_indices_test.append(indx) 119 | else: 120 | df_files_train.append(all_files[indx]) 121 | df_indices_train.append(indx) 122 | df_files.append(all_files[indx]) 123 | df_indices.append(indx) 124 | 125 | if not os.path.exists(cfg.PICKLE_FOLDER): 126 | os.mkdir(cfg.PICKLE_FOLDER) 127 | 128 | if inside == True: 129 | construct_dict(len(fold_list),df_files_train, df_files,df_indices_train, "train_pickle/training_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list))) 130 | construct_dict(len(fold_list), df_files_test, df_files,df_indices_test, "train_pickle/test_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list))) 131 | construct_dict(len(fold_list), df_files,df_files, df_indices, "train_pickle/db_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list))) 132 | 133 | else: 134 | construct_dict(len(fold_list), df_files_train,df_files, df_indices_train, "generating_queries/train_pickle/training_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list)), definite_positives=definite_positives) 135 | construct_dict(len(fold_list), df_files_test,df_files, df_indices_test, "generating_queries/train_pickle/test_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list)), definite_positives=definite_positives) 136 | construct_dict(len(fold_list), df_files,df_files, df_indices, "generating_queries/train_pickle/db_queries_baseline_"+str(data_index)+".pickle", pre_dir, k_nearest, k_furthest, int(traj_len/len(fold_list)), definite_positives=definite_positives) 137 | 138 | if __name__ == "__main__": 139 | for i in range(1): 140 | generate(0,i) 141 | -------------------------------------------------------------------------------- /generating_queries/generate_training_tuples_RGB_real_supervise.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pickle 4 | import random 5 | import set_path 6 | 7 | import numpy as np 8 | import pandas as pd 9 | from sklearn.neighbors import KDTree 10 | 11 | import config as cfg 12 | 13 | import scipy.io as sio 14 | import torch 15 | 16 | #####For training and test data split##### 17 | 18 | def construct_dict(folder_num, df_f, df_all, df_files, df_files_all, df_indices, df_indices_all, df_locations_x_all, df_locations_y_all, df_locations_x, df_locations_y, filename, pre_dir): 19 | nn_ind = 0.005 20 | r_mid = 0.005 21 | r_ind = 0.015 22 | 23 | queries = {} 24 | count = 0 25 | 26 | df_centroids = df_all 27 | df_folder_index = df_indices 28 | 29 | tree = KDTree(df_centroids[['x','y']]) 30 | ind_r = tree.query_radius(df_centroids[['x','y']], r=r_ind) 31 | ind_nn = tree.query_radius(df_centroids[['x','y']],r=nn_ind) 32 | 33 | for i in df_indices: 34 | query = df_centroids.iloc[i]["file"] 35 | positives = np.setdiff1d(ind_nn[i],[i]).tolist() 36 | negatives = np.setdiff1d( 37 | df_centroids.index.values.tolist(),ind_r[i]).tolist() 38 | random.shuffle(negatives) 39 | if len(positives)<2: 40 | positives = [] 41 | positives.append(i+1) 42 | positives.append(i-1) 43 | positives = np.array(positives) 44 | # print(len(positives)) 45 | # assert(len(positives)<=1000) 46 | 47 | queries[i] = {"query":df_centroids.iloc[i]['file'], 48 | "positives":positives,"negatives":negatives} 49 | 50 | 51 | with open(filename, 'wb') as handle: 52 | pickle.dump(queries, handle, protocol=pickle.HIGHEST_PROTOCOL) 53 | 54 | print("Done ", filename) 55 | 56 | def generate(data_index, definite_positives=None, inside=True): 57 | base_path = "/mnt/NAS/data/cc_data/2D_RGB_real_edited3" 58 | base_path = os.path.join(base_path) 59 | pre_dir = base_path 60 | ''' 61 | runs_folder = cfg.scene_names[scene_index] 62 | print("runs_folder2:"+str(runs_folder)) 63 | 64 | pre_dir = os.path.join(base_path, runs_folder) 65 | print("pre_dir:"+str(pre_dir)) 66 | ''' 67 | filename = "gt_pose.mat" 68 | 69 | # Initialize pandas DataFrame 70 | 71 | df_train = pd.DataFrame(columns=['file','x','y']) 72 | df_test = pd.DataFrame(columns=['file','x','y']) 73 | df_all = pd.DataFrame(columns=['file','x','y']) 74 | 75 | df_files_test = [] 76 | df_files_train =[] 77 | df_files = [] 78 | 79 | df_indices_train = [] 80 | df_indices_test = [] 81 | df_indices = [] 82 | 83 | df_locations_tr_x = [] 84 | df_locations_tr_y = [] 85 | # df_locations_tr_z = [] 86 | 87 | df_locations_ts_x = [] 88 | df_locations_ts_y = [] 89 | # df_locations_ts_z = [] 90 | 91 | df_locations_x = [] 92 | df_locations_y = [] 93 | # df_locations_z = [] 94 | 95 | fold_list = list(sorted(os.listdir(base_path))) 96 | all_files = [] 97 | for ind, fold in enumerate(fold_list): 98 | files_ = [] 99 | files = list(sorted(os.listdir(os.path.join(base_path, fold)))) 100 | files.remove('gt_pose.mat') 101 | # print("len(files):"+str(len(files))) 102 | for ind_f in range(len(files)): 103 | file_ = "panoimg_"+str(ind_f)+".jpg" 104 | files_.append(os.path.join(base_path, fold, file_)) 105 | df_files.extend(files_) 106 | df_locations = sio.loadmat(os.path.join(base_path,fold,filename)) 107 | df_locations = df_locations['pose'] 108 | #df_locations = torch.tensor(df_locations, dtype = torch.float).cpu() 109 | # print(df_locations.shape) 110 | # assert() 111 | file_index = list(range(df_locations.shape[0])) 112 | 113 | df_locations_x.extend(list(df_locations[file_index,0])) 114 | # df_locations_z.extend(list(df_locations[file_index,1])) 115 | df_locations_y.extend(list(df_locations[file_index,1])) 116 | test_sample = 10 117 | test_index_temp = random.sample(range(df_locations.shape[0]), k=test_sample) 118 | test_index = list(np.array(test_index_temp)+ind * df_locations.shape[0]) 119 | 120 | df_indices_test.extend(test_index) 121 | train_index_temp = list(range(df_locations.shape[0])) 122 | train_index = list(np.array(train_index_temp)+ind * len(files_)) 123 | df_indices.extend(train_index) 124 | files_ = [] 125 | for ts_ind in test_index: 126 | train_index.remove(ts_ind) 127 | file_ = "panoimg_"+str(ts_ind)+".jpg" 128 | files_.append(os.path.join(base_path, fold, file_)) 129 | df_indices_train.extend(train_index) 130 | df_files_test.extend(files_) 131 | files_ = [] 132 | for tr_ind in train_index: 133 | file_ = "panoimg_"+str(tr_ind)+".jpg" 134 | files_.append(os.path.join(base_path, fold, file_)) 135 | df_files_train.extend(files_) 136 | 137 | df_locations_tr_x.extend(list(df_locations[train_index_temp,0])) 138 | # df_locations_tr_z.extend(list(df_locations[train_index_temp,1])) 139 | df_locations_tr_y.extend(list(df_locations[train_index_temp,1])) 140 | 141 | df_locations_ts_x.extend(list(df_locations[test_index_temp,0])) 142 | # df_locations_ts_z.extend(list(df_locations[test_index_temp,1])) 143 | df_locations_ts_y.extend(list(df_locations[test_index_temp,1])) 144 | 145 | traj_len = len(all_files) 146 | 147 | df_train = pd.DataFrame(list(zip(df_files_train, df_locations_tr_x, df_locations_tr_y)), 148 | columns =['file','x', 'y']) 149 | df_test = pd.DataFrame(list(zip(df_files_test, df_locations_ts_x, df_locations_ts_y)), 150 | columns =['file','x', 'y']) 151 | df_all = pd.DataFrame(list(zip(df_files, df_locations_x, df_locations_y)), 152 | columns =['file','x', 'y']) 153 | #n Training 10 testing 154 | if not os.path.exists(cfg.PICKLE_FOLDER): 155 | os.mkdir(cfg.PICKLE_FOLDER) 156 | 157 | if inside == True: 158 | construct_dict(len(fold_list),df_train,df_all,df_files_train,df_files,df_indices_train, df_indices,df_locations_x,df_locations_y,df_locations_tr_x,df_locations_tr_y,"train_pickle/training_queries_baseline_"+str(data_index)+".pickle", pre_dir) 159 | construct_dict(len(fold_list),df_test,df_all,df_files_test,df_files,df_indices_test,df_indices,df_locations_x,df_locations_y,df_locations_ts_x,df_locations_ts_y, "train_pickle/test_queries_baseline_"+str(data_index)+".pickle", pre_dir) 160 | construct_dict(len(fold_list),df_all,df_all,df_files,df_files,df_indices,df_indices,df_locations_x,df_locations_y,df_locations_x,df_locations_y,"train_pickle/db_queries_baseline_"+str(data_index)+".pickle", pre_dir) 161 | 162 | else: 163 | construct_dict(len(fold_list),df_train,df_all,df_files_train,df_files,df_indices_train,df_indices,df_locations_x,df_locations_y,df_locations_tr_x,df_locations_tr_y, "generating_queries/train_pickle/training_queries_baseline_"+str(data_index)+".pickle", pre_dir) 164 | construct_dict(len(fold_list),df_test,df_all,df_files_test,df_files, df_indices_test,df_indices,df_locations_x,df_locations_y,df_locations_ts_x,df_locations_ts_y, "generating_queries/train_pickle/test_queries_baseline_"+str(data_index)+".pickle", pre_dir) 165 | construct_dict(len(fold_list),df_all,df_all,df_files,df_files, df_indices, df_indices, df_locations_x,df_locations_y,df_locations_x,df_locations_y, "generating_queries/train_pickle/db_queries_baseline_"+str(data_index)+".pickle", pre_dir) 166 | 167 | if __name__ == "__main__": 168 | for i in range(1): 169 | generate(i) -------------------------------------------------------------------------------- /generating_queries/generate_training_tuples_RGB_supervise.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pickle 4 | import random 5 | import set_path 6 | 7 | import numpy as np 8 | import pandas as pd 9 | from sklearn.neighbors import KDTree 10 | 11 | import config as cfg 12 | 13 | import scipy.io as sio 14 | import torch 15 | 16 | #####For training and test data split##### 17 | 18 | def construct_dict(folder_num, df_f, df_all, df_files, df_files_all, df_indices, df_indices_all, df_locations_x_all, df_locations_y_all, df_locations_z_all, df_locations_x, df_locations_y, df_locations_z, filename, pre_dir): 19 | nn_ind = 0.4 20 | r_mid = 0.4 21 | r_ind = 1.2 22 | 23 | queries = {} 24 | count = 0 25 | 26 | df_centroids = df_all 27 | df_folder_index = df_indices 28 | 29 | tree = KDTree(df_centroids[['x','y','z']]) 30 | ind_r = tree.query_radius(df_centroids[['x','y','z']], r=r_ind) 31 | ind_nn = tree.query_radius(df_centroids[['x','y','z']],r=nn_ind) 32 | 33 | for i in df_indices: 34 | query = df_centroids.iloc[i]["file"] 35 | positives = np.setdiff1d(ind_nn[i],[i]).tolist() 36 | negatives = np.setdiff1d( 37 | df_centroids.index.values.tolist(),ind_r[i]).tolist() 38 | random.shuffle(negatives) 39 | 40 | if len(positives)<2: 41 | print("i:"+str(i)) 42 | print("len(positives):"+str(len(positives))) 43 | assert(len(positives)>=2) 44 | 45 | queries[i] = {"query":df_centroids.iloc[i]['file'], 46 | "positives":positives,"negatives":negatives} 47 | 48 | 49 | with open(filename, 'wb') as handle: 50 | pickle.dump(queries, handle, protocol=pickle.HIGHEST_PROTOCOL) 51 | 52 | print("Done ", filename) 53 | 54 | def generate(scene_index, data_index, definite_positives=None, inside=True): 55 | base_path = "/mnt/NAS/home/cc/data/habitat_4/train/" 56 | base_path = os.path.join(base_path, cfg.scene_list[scene_index]) 57 | pre_dir = base_path 58 | 59 | filename = "gt_pose.mat" 60 | 61 | # Initialize pandas DataFrame 62 | 63 | df_train = pd.DataFrame(columns=['file','x','y','z']) 64 | df_test = pd.DataFrame(columns=['file','x','y','z']) 65 | df_all = pd.DataFrame(columns=['file','x','y','z']) 66 | 67 | df_files_test = [] 68 | df_files_train =[] 69 | df_files = [] 70 | 71 | df_indices_train = [] 72 | df_indices_test = [] 73 | df_indices = [] 74 | 75 | df_locations_tr_x = [] 76 | df_locations_tr_y = [] 77 | df_locations_tr_z = [] 78 | 79 | df_locations_ts_x = [] 80 | df_locations_ts_y = [] 81 | df_locations_ts_z = [] 82 | 83 | df_locations_x = [] 84 | df_locations_y = [] 85 | df_locations_z = [] 86 | 87 | fold_list = list(sorted(os.listdir(base_path))) 88 | all_files = [] 89 | for ind, fold in enumerate(fold_list): 90 | files_ = [] 91 | files = list(sorted(os.listdir(os.path.join(base_path, fold)))) 92 | files.remove('gt_pose.mat') 93 | for ind_f in range(len(files)): 94 | file_ = "panoimg_"+str(ind_f)+".png" 95 | files_.append(os.path.join(base_path, fold, file_)) 96 | df_files.extend(files_) 97 | df_locations = sio.loadmat(os.path.join(base_path,fold,filename)) 98 | df_locations = df_locations['pose'] 99 | file_index = list(range(df_locations.shape[0])) 100 | 101 | df_locations_x.extend(list(df_locations[file_index,0])) 102 | df_locations_z.extend(list(df_locations[file_index,1])) 103 | df_locations_y.extend(list(df_locations[file_index,2])) 104 | test_sample = 10 105 | test_index_temp = random.sample(range(df_locations.shape[0]), k=test_sample) 106 | test_index = list(np.array(test_index_temp)+ind * df_locations.shape[0]) 107 | 108 | df_indices_test.extend(test_index) 109 | train_index_temp = list(range(df_locations.shape[0])) 110 | train_index = list(np.array(train_index_temp)+ind * len(files_)) 111 | df_indices.extend(train_index) 112 | files_ = [] 113 | for ts_ind in test_index: 114 | train_index.remove(ts_ind) 115 | file_ = "panoimg_"+str(ts_ind)+".png" 116 | files_.append(os.path.join(base_path, fold, file_)) 117 | df_indices_train.extend(train_index) 118 | df_files_test.extend(files_) 119 | files_ = [] 120 | for tr_ind in train_index: 121 | file_ = "panoimg_"+str(tr_ind)+".png" 122 | files_.append(os.path.join(base_path, fold, file_)) 123 | df_files_train.extend(files_) 124 | 125 | df_locations_tr_x.extend(list(df_locations[train_index_temp,0])) 126 | df_locations_tr_z.extend(list(df_locations[train_index_temp,1])) 127 | df_locations_tr_y.extend(list(df_locations[train_index_temp,2])) 128 | 129 | df_locations_ts_x.extend(list(df_locations[test_index_temp,0])) 130 | df_locations_ts_z.extend(list(df_locations[test_index_temp,1])) 131 | df_locations_ts_y.extend(list(df_locations[test_index_temp,2])) 132 | 133 | traj_len = len(all_files) 134 | 135 | df_train = pd.DataFrame(list(zip(df_files_train, df_locations_tr_x, df_locations_tr_y, df_locations_tr_z)), 136 | columns =['file','x', 'y', 'z']) 137 | df_test = pd.DataFrame(list(zip(df_files_test, df_locations_ts_x, df_locations_ts_y, df_locations_ts_z)), 138 | columns =['file','x', 'y', 'z']) 139 | df_all = pd.DataFrame(list(zip(df_files, df_locations_x, df_locations_y, df_locations_z)), 140 | columns =['file','x', 'y', 'z']) 141 | #n Training 10 testing 142 | if not os.path.exists(cfg.PICKLE_FOLDER): 143 | os.mkdir(cfg.PICKLE_FOLDER) 144 | 145 | if inside == True: 146 | construct_dict(len(fold_list),df_train,df_all,df_files_train,df_files,df_indices_train, df_indices,df_locations_x,df_locations_y,df_locations_z,df_locations_tr_x,df_locations_tr_y,df_locations_tr_z,"train_pickle/training_queries_baseline_"+str(data_index)+".pickle", pre_dir) 147 | construct_dict(len(fold_list),df_test,df_all,df_files_test,df_files,df_indices_test,df_indices,df_locations_x,df_locations_y,df_locations_z,df_locations_ts_x,df_locations_ts_y,df_locations_ts_z, "train_pickle/test_queries_baseline_"+str(data_index)+".pickle", pre_dir) 148 | construct_dict(len(fold_list),df_all,df_all,df_files,df_files,df_indices,df_indices,df_locations_x,df_locations_y,df_locations_z,df_locations_x,df_locations_y,df_locations_z,"train_pickle/db_queries_baseline_"+str(data_index)+".pickle", pre_dir) 149 | 150 | else: 151 | construct_dict(len(fold_list),df_train,df_all,df_files_train,df_files,df_indices_train,df_indices,df_locations_x,df_locations_y,df_locations_z,df_locations_tr_x,df_locations_tr_y,df_locations_tr_z, "generating_queries/train_pickle/training_queries_baseline_"+str(data_index)+".pickle", pre_dir) 152 | construct_dict(len(fold_list),df_test,df_all,df_files_test,df_files, df_indices_test,df_indices,df_locations_x,df_locations_y,df_locations_z,df_locations_ts_x,df_locations_ts_y,df_locations_ts_z, "generating_queries/train_pickle/test_queries_baseline_"+str(data_index)+".pickle", pre_dir) 153 | construct_dict(len(fold_list),df_all,df_all,df_files,df_files, df_indices, df_indices, df_locations_x,df_locations_y,df_locations_z,df_locations_x,df_locations_y,df_locations_z, "generating_queries/train_pickle/db_queries_baseline_"+str(data_index)+".pickle", pre_dir) 154 | 155 | if __name__ == "__main__": 156 | for i in range(1): 157 | generate(0,i) -------------------------------------------------------------------------------- /generating_queries/set_path.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | sys.path.insert(0, '../') 4 | -------------------------------------------------------------------------------- /get_embeddings_ours.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import sys 4 | 5 | import numpy as np 6 | 7 | import config as cfg 8 | import models.PointNetVlad as PNV 9 | import torch 10 | from loading_pointclouds import * 11 | from torch.backends import cudnn 12 | from tqdm import tqdm 13 | 14 | #os.environ["CUDA_VISIBLE_DEVICES"] = "0" 15 | 16 | 17 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 18 | sys.path.append(BASE_DIR) 19 | 20 | cudnn.enabled = True 21 | 22 | parser = argparse.ArgumentParser() 23 | parser.add_argument('--log_dir', default='log/', help='Log dir [default: log]') 24 | parser.add_argument('--results_dir', default='results/', 25 | help='results dir [default: results/]') 26 | parser.add_argument('--positives_per_query', type=int, default=2, 27 | help='Number of potential positives in each training tuple [default: 2]') 28 | parser.add_argument('--negatives_per_query', type=int, default=18, 29 | help='Number of definite negatives in each training tuple [default: 18]') 30 | parser.add_argument('--max_epoch', type=int, default=100, 31 | help='Epoch to run [default: 100]') 32 | parser.add_argument('--batch_num_queries', type=int, default=2, 33 | help='Batch Size during training [default: 2]') 34 | parser.add_argument('--learning_rate', type=float, default=0.000005, 35 | help='Initial learning rate [default: 0.000005]') 36 | parser.add_argument('--momentum', type=float, default=0.9, 37 | help='Initial learning rate [default: 0.9]') 38 | parser.add_argument('--optimizer', default='adam', 39 | help='adam or momentum [default: adam]') 40 | parser.add_argument('--decay_step', type=int, default=200000, 41 | help='Decay step for lr decay [default: 200000]') 42 | parser.add_argument('--decay_rate', type=float, default=0.7, 43 | help='Decay rate for lr decay [default: 0.7]') 44 | parser.add_argument('--margin_1', type=float, default=0.5, 45 | help='Margin for hinge loss [default: 0.5]') 46 | parser.add_argument('--margin_2', type=float, default=0.2, 47 | help='Margin for hinge loss [default: 0.2]') 48 | parser.add_argument('--loss_function', default='quadruplet', choices=[ 49 | 'triplet', 'quadruplet'], help='triplet or quadruplet [default: quadruplet]') 50 | parser.add_argument('--loss_not_lazy', action='store_false', 51 | help='If present, do not use lazy variant of loss') 52 | parser.add_argument('--loss_ignore_zero_batch', action='store_true', 53 | help='If present, mean only batches with loss > 0.0') 54 | parser.add_argument('--triplet_use_best_positives', action='store_true', 55 | help='If present, use best positives, otherwise use hardest positives') 56 | parser.add_argument('--resume', action='store_true', 57 | help='If present, restore checkpoint and resume training') 58 | parser.add_argument('--dataset_folder', default='../../dataset/', 59 | help='PointNetVlad Dataset Folder') 60 | 61 | FLAGS = parser.parse_args() 62 | cfg.BATCH_NUM_QUERIES = FLAGS.batch_num_queries 63 | #cfg.EVAL_BATCH_SIZE = 12 64 | cfg.NUM_POINTS = 256 65 | cfg.TRAIN_POSITIVES_PER_QUERY = FLAGS.positives_per_query 66 | cfg.TRAIN_NEGATIVES_PER_QUERY = FLAGS.negatives_per_query 67 | cfg.MAX_EPOCH = FLAGS.max_epoch 68 | cfg.BASE_LEARNING_RATE = FLAGS.learning_rate 69 | cfg.MOMENTUM = FLAGS.momentum 70 | cfg.OPTIMIZER = FLAGS.optimizer 71 | cfg.DECAY_STEP = FLAGS.decay_step 72 | cfg.DECAY_RATE = FLAGS.decay_rate 73 | cfg.MARGIN1 = FLAGS.margin_1 74 | cfg.MARGIN2 = FLAGS.margin_2 75 | cfg.FEATURE_OUTPUT_DIM = 256 76 | 77 | cfg.LOSS_FUNCTION = FLAGS.loss_function 78 | cfg.TRIPLET_USE_BEST_POSITIVES = FLAGS.triplet_use_best_positives 79 | cfg.LOSS_LAZY = FLAGS.loss_not_lazy 80 | cfg.LOSS_IGNORE_ZERO_BATCH = FLAGS.loss_ignore_zero_batch 81 | 82 | 83 | cfg.LOG_DIR = FLAGS.log_dir 84 | if not os.path.exists(cfg.LOG_DIR): 85 | os.mkdir(cfg.LOG_DIR) 86 | LOG_FOUT = open(os.path.join(cfg.LOG_DIR, 'log_train.txt'), 'w') 87 | LOG_FOUT.write(str(FLAGS) + '\n') 88 | 89 | cfg.RESULTS_FOLDER = FLAGS.results_dir 90 | print("cfg.RESULTS_FOLDER:"+str(cfg.RESULTS_FOLDER)) 91 | 92 | cfg.DATASET_FOLDER = FLAGS.dataset_folder 93 | 94 | 95 | cfg.BN_INIT_DECAY = 0.5 96 | cfg.BN_DECAY_DECAY_RATE = 0.5 97 | BN_DECAY_DECAY_STEP = float(cfg.DECAY_STEP) 98 | cfg.BN_DECAY_CLIP = 0.99 99 | 100 | HARD_NEGATIVES = {} 101 | TRAINING_LATENT_VECTORS = [] 102 | 103 | TOTAL_ITERATIONS = 0 104 | 105 | device = torch.device("cuda" if torch.cuda.is_available() else "cpu") 106 | 107 | print(f'cfg.BATCH_NUM_QUERIES : {cfg.BATCH_NUM_QUERIES}') 108 | 109 | def get_bn_decay(batch): 110 | bn_momentum = cfg.BN_INIT_DECAY * \ 111 | (cfg.BN_DECAY_DECAY_RATE ** 112 | (batch * cfg.BATCH_NUM_QUERIES // BN_DECAY_DECAY_STEP)) 113 | return min(cfg.BN_DECAY_CLIP, 1 - bn_momentum) 114 | 115 | 116 | def log_string(out_str): 117 | LOG_FOUT.write(out_str + '\n') 118 | LOG_FOUT.flush() 119 | print(out_str) 120 | 121 | # learning rate halfed every 5 epoch 122 | def get_learning_rate(epoch): 123 | learning_rate = cfg.BASE_LEARNING_RATE * ((0.9) ** (epoch // 5)) 124 | learning_rate = max(learning_rate, 0.00001) # CLIP THE LEARNING RATE! 125 | return learning_rate 126 | 127 | 128 | def get_feature_representation(filename, model): 129 | model.eval() 130 | queries = load_pc_files([filename],True) 131 | queries = np.expand_dims(queries, axis=1) 132 | with torch.no_grad(): 133 | q = torch.from_numpy(queries).float() 134 | q = q.to(device) 135 | output = model(q) 136 | output = output.detach().cpu().numpy() 137 | output = np.squeeze(output) 138 | model.train() 139 | return output 140 | 141 | 142 | def train(): 143 | learning_rate = get_learning_rate(0) 144 | 145 | model = PNV.PointNetVlad(global_feat=True, feature_transform=True, 146 | max_pool=False, output_dim=cfg.FEATURE_OUTPUT_DIM, num_points=cfg.NUM_POINTS) 147 | model = model.to(device) 148 | 149 | parameters = filter(lambda p: p.requires_grad, model.parameters()) 150 | 151 | if cfg.OPTIMIZER == 'momentum': 152 | optimizer = torch.optim.SGD( 153 | parameters, learning_rate, momentum=cfg.MOMENTUM) 154 | elif cfg.OPTIMIZER == 'adam': 155 | optimizer = torch.optim.Adam(parameters, learning_rate) 156 | else: 157 | optimizer = None 158 | exit(0) 159 | 160 | model_path = cfg.RESULTS_FOLDER + "checkpoints.pth.tar" 161 | 162 | print("Loading model from ", model_path) 163 | 164 | checkpoint = torch.load(model_path) 165 | print(checkpoint.keys()) 166 | saved_state_dict = checkpoint['state_dict'] 167 | starting_epoch = checkpoint['epoch'] 168 | 169 | model.load_state_dict(saved_state_dict) 170 | optimizer.load_state_dict(checkpoint['optimizer']) 171 | 172 | data_path = "data/" 173 | 174 | files = sorted(os.listdir(data_path)) 175 | train_file_idxs = np.arange(0, len(files)) 176 | 177 | print(f'Length of train ids : {len(train_file_idxs)}') 178 | 179 | queries = [] 180 | 181 | for i in tqdm(train_file_idxs): 182 | path = os.path.join(data_path, files[i]) 183 | query = get_feature_representation(path, model) 184 | queries.append(query) 185 | 186 | queries = np.array(queries) 187 | 188 | save_file = cfg.RESULTS_FOLDER + "embeddings.npy" 189 | np.save(save_file, queries) 190 | 191 | print(queries.shape) 192 | 193 | train() 194 | -------------------------------------------------------------------------------- /loss/pointnetvlad_loss.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import math 3 | import torch 4 | 5 | 6 | def best_pos_distance(query, pos_vecs): 7 | num_pos = pos_vecs.shape[1] 8 | query_copies = query.repeat(1, int(num_pos), 1) 9 | diff = ((pos_vecs - query_copies) ** 2).sum(2) 10 | min_pos, _ = diff.min(1) 11 | max_pos, _ = diff.max(1) 12 | return min_pos, max_pos 13 | 14 | 15 | def triplet_loss(q_vec, pos_vecs, neg_vecs, margin, use_min=False, lazy=False, ignore_zero_loss=False): 16 | min_pos, max_pos = best_pos_distance(q_vec, pos_vecs) 17 | 18 | # PointNetVLAD official code use min_pos, but i think max_pos should be used 19 | if use_min: 20 | positive = min_pos 21 | else: 22 | positive = max_pos 23 | 24 | num_neg = neg_vecs.shape[1] 25 | batch = q_vec.shape[0] 26 | query_copies = q_vec.repeat(1, int(num_neg), 1) 27 | positive = positive.view(-1, 1) 28 | positive = positive.repeat(1, int(num_neg)) 29 | 30 | loss = margin + positive - ((neg_vecs - query_copies) ** 2).sum(2) 31 | loss = loss.clamp(min=0.0) 32 | if lazy: 33 | triplet_loss = loss.max(1)[0] 34 | else: 35 | triplet_loss = loss.sum(1) 36 | if ignore_zero_loss: 37 | hard_triplets = torch.gt(triplet_loss, 1e-16).float() 38 | num_hard_triplets = torch.sum(hard_triplets) 39 | triplet_loss = triplet_loss.sum() / (num_hard_triplets + 1e-16) 40 | else: 41 | triplet_loss = triplet_loss.mean() 42 | return triplet_loss 43 | 44 | 45 | def triplet_loss_wrapper(q_vec, pos_vecs, neg_vecs, other_neg, m1, m2, use_min=False, lazy=False, ignore_zero_loss=False): 46 | return triplet_loss(q_vec, pos_vecs, neg_vecs, m1, use_min, lazy, ignore_zero_loss) 47 | 48 | 49 | def quadruplet_loss(q_vec, pos_vecs, neg_vecs, other_neg, m1, m2, use_min=False, lazy=False, ignore_zero_loss=False): 50 | min_pos, max_pos = best_pos_distance(q_vec, pos_vecs) 51 | 52 | # PointNetVLAD official code use min_pos, but i think max_pos should be used 53 | if use_min: 54 | positive = min_pos 55 | else: 56 | positive = max_pos 57 | 58 | num_neg = neg_vecs.shape[1] 59 | batch = q_vec.shape[0] 60 | query_copies = q_vec.repeat(1, int(num_neg), 1) 61 | positive = positive.view(-1, 1) 62 | positive = positive.repeat(1, int(num_neg)) 63 | 64 | loss = m1 + positive - ((neg_vecs - query_copies) ** 2).sum(2) 65 | loss = loss.clamp(min=0.0) 66 | if lazy: 67 | triplet_loss = loss.max(1)[0] 68 | else: 69 | triplet_loss = loss.sum(1) 70 | if ignore_zero_loss: 71 | hard_triplets = torch.gt(triplet_loss, 1e-16).float() 72 | num_hard_triplets = torch.sum(hard_triplets) 73 | triplet_loss = triplet_loss.sum() / (num_hard_triplets + 1e-16) 74 | else: 75 | triplet_loss = triplet_loss.mean() 76 | 77 | other_neg_copies = other_neg.repeat(1, int(num_neg), 1) 78 | second_loss = m2 + positive - ((neg_vecs - other_neg_copies) ** 2).sum(2) 79 | second_loss = second_loss.clamp(min=0.0) 80 | if lazy: 81 | second_loss = second_loss.max(1)[0] 82 | else: 83 | second_loss = second_loss.sum(1) 84 | 85 | if ignore_zero_loss: 86 | hard_second = torch.gt(second_loss, 1e-16).float() 87 | num_hard_second = torch.sum(hard_second) 88 | second_loss = second_loss.sum() / (num_hard_second + 1e-16) 89 | else: 90 | second_loss = second_loss.mean() 91 | 92 | total_loss = triplet_loss + second_loss 93 | return total_loss 94 | -------------------------------------------------------------------------------- /models/ImageNetVlad.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.parallel 5 | import torch.utils.data 6 | from torch.autograd import Variable 7 | import numpy as np 8 | import torch.nn.functional as F 9 | import math 10 | import torchvision.models as models 11 | 12 | class NetVLAD_Image(nn.Module): 13 | """NetVLAD layer implementation""" 14 | def __init__(self, num_clusters=64, dim=128, 15 | normalize_input=True, vladv2=False): 16 | 17 | """ 18 | Args: 19 | num_clusters : int 20 | The number of clusters 21 | 22 | dim : int 23 | Dimension of descriptors 24 | 25 | alpha : float 26 | Parameter of initialization. Larger value is harder assignment. 27 | 28 | normalize_input : bool 29 | If true, descriptor-wise L2 normalization is applied to input. 30 | 31 | vladv2 : bool 32 | If true, use vladv2 otherwise use vladv1 33 | """ 34 | 35 | super(NetVLAD_Image, self).__init__() 36 | self.num_clusters = num_clusters 37 | self.dim = dim 38 | self.alpha = 0 39 | self.vladv2 = vladv2 40 | self.normalize_input = normalize_input 41 | self.conv = nn.Conv2d(dim, num_clusters, kernel_size=(1, 1), bias=vladv2) 42 | self.centroids = nn.Parameter(torch.rand(num_clusters, dim)) 43 | 44 | def init_params(self, clsts, traindescs): 45 | 46 | #TODO replace numpy ops with pytorch ops 47 | if self.vladv2 == False: 48 | clstsAssign = clsts / np.linalg.norm(clsts, axis=1, keepdims=True) 49 | dots = np.dot(clstsAssign, traindescs.T) 50 | dots.sort(0) 51 | dots = dots[::-1, :] # sort, descending 52 | 53 | self.alpha = (-np.log(0.01) / np.mean(dots[0,:] - dots[1,:])).item() 54 | self.centroids = nn.Parameter(torch.from_numpy(clsts)) 55 | self.conv.weight = nn.Parameter(torch.from_numpy(self.alpha*clstsAssign).unsqueeze(2).unsqueeze(3)) 56 | self.conv.bias = None 57 | else: 58 | knn = NearestNeighbors(n_jobs=-1) #TODO faiss? 59 | knn.fit(traindescs) 60 | del traindescs 61 | dsSq = np.square(knn.kneighbors(clsts, 2)[1]) 62 | del knn 63 | self.alpha = (-np.log(0.01) / np.mean(dsSq[:,1] - dsSq[:,0])).item() 64 | self.centroids = nn.Parameter(torch.from_numpy(clsts)) 65 | del clsts, dsSq 66 | 67 | self.conv.weight = nn.Parameter( 68 | (2.0 * self.alpha * self.centroids).unsqueeze(-1).unsqueeze(-1) 69 | ) 70 | 71 | self.conv.bias = nn.Parameter( 72 | - self.alpha * self.centroids.norm(dim=1) 73 | ) 74 | 75 | def forward(self, x): 76 | N, C = x.shape[:2] 77 | 78 | if self.normalize_input: 79 | x = F.normalize(x, p=2, dim=1) # across descriptor dim 80 | 81 | # soft-assignment 82 | soft_assign = self.conv(x).view(N, self.num_clusters, -1) 83 | soft_assign = F.softmax(soft_assign, dim=1) 84 | x_flatten = x.view(N, C, -1) 85 | 86 | # calculate residuals to each clusters 87 | vlad = torch.zeros([N, self.num_clusters, C], dtype=x.dtype, layout=x.layout, device=x.device) 88 | for C in range(self.num_clusters): # slower than non-looped, but lower memory usage 89 | residual = x_flatten.unsqueeze(0).permute(1, 0, 2, 3) - \ 90 | self.centroids[C:C+1, :].expand(x_flatten.size(-1), -1, -1).permute(1, 2, 0).unsqueeze(0) 91 | residual *= soft_assign[:,C:C+1,:].unsqueeze(2) 92 | vlad[:,C:C+1,:] = residual.sum(dim=-1) 93 | 94 | vlad = F.normalize(vlad, p=2, dim=2) # intra-normalization 95 | vlad = vlad.view(x.size(0), -1) # flatten 96 | vlad = F.normalize(vlad, p=2, dim=1) # L2 normalize 97 | 98 | return vlad 99 | 100 | class NetVLAD_Image2(nn.Module): 101 | """NetVLAD layer implementation""" 102 | def __init__(self, num_clusters=64, dim=128, alpha=100.0, 103 | normalize_input=True): 104 | """ 105 | Args: 106 | num_clusters : int 107 | The number of clusters 108 | dim : int 109 | Dimension of descriptors 110 | alpha : float 111 | Parameter of initialization. Larger value is harder assignment. 112 | normalize_input : bool 113 | If true, descriptor-wise L2 normalization is applied to input. 114 | """ 115 | super(NetVLAD_Image, self).__init__() 116 | self.num_clusters = num_clusters 117 | self.dim = dim 118 | self.alpha = alpha 119 | self.normalize_input = normalize_input 120 | self.conv = nn.Conv2d(dim, num_clusters, kernel_size=(1, 1), bias=True) 121 | self.centroids = nn.Parameter(torch.rand(num_clusters, dim)) 122 | self._init_params() 123 | 124 | def _init_params(self): 125 | self.conv.weight = nn.Parameter( 126 | (2.0 * self.alpha * self.centroids).unsqueeze(-1).unsqueeze(-1) 127 | ) 128 | 129 | self.conv.bias = nn.Parameter( 130 | - self.alpha * self.centroids.norm(dim=1) 131 | ) 132 | 133 | def forward(self, x): 134 | N, C = x.shape[:2] 135 | if self.normalize_input: 136 | x = F.normalize(x, p=2, dim=1) # across descriptor dim 137 | 138 | # soft-assignment 139 | soft_assign = self.conv(x).view(N, self.num_clusters, -1) 140 | soft_assign = F.softmax(soft_assign, dim=1) 141 | x_flatten = x.view(N, C, -1) 142 | 143 | # calculate residuals to each clusters 144 | residual = x_flatten.expand(self.num_clusters, -1, -1, -1).permute(1, 0, 2, 3) - \ 145 | self.centroids.expand(x_flatten.size(-1), -1, -1).permute(1, 2, 0).unsqueeze(0) 146 | residual *= soft_assign.unsqueeze(2) 147 | 148 | vlad = residual.sum(dim=-1) 149 | vlad = F.normalize(vlad, p=2, dim=2) # intra-normalization 150 | vlad = vlad.view(x.size(0), -1) # flatten 151 | vlad = F.normalize(vlad, p=2, dim=1) # L2 normalize 152 | return vlad 153 | 154 | class NetVLADLoupe(nn.Module): 155 | def __init__(self, feature_size, max_samples, cluster_size, output_dim, 156 | gating=True, add_batch_norm=True, is_training=True): 157 | super(NetVLADLoupe, self).__init__() 158 | self.feature_size = feature_size 159 | self.max_samples = max_samples 160 | self.output_dim = output_dim 161 | self.is_training = is_training 162 | self.gating = gating 163 | self.add_batch_norm = add_batch_norm 164 | self.cluster_size = cluster_size 165 | self.softmax = nn.Softmax(dim=-1) 166 | self.cluster_weights = nn.Parameter(torch.randn( 167 | feature_size, cluster_size) * 1 / math.sqrt(feature_size)) 168 | self.cluster_weights2 = nn.Parameter(torch.randn( 169 | 1, feature_size, cluster_size) * 1 / math.sqrt(feature_size)) 170 | self.hidden1_weights = nn.Parameter( 171 | torch.randn(cluster_size * feature_size, output_dim) * 1 / math.sqrt(feature_size)) 172 | 173 | if add_batch_norm: 174 | self.cluster_biases = None 175 | self.bn1 = nn.BatchNorm1d(cluster_size) 176 | else: 177 | self.cluster_biases = nn.Parameter(torch.randn( 178 | cluster_size) * 1 / math.sqrt(feature_size)) 179 | self.bn1 = None 180 | 181 | self.bn2 = nn.BatchNorm1d(output_dim) 182 | 183 | if gating: 184 | self.context_gating = GatingContext( 185 | output_dim, add_batch_norm=add_batch_norm) 186 | 187 | def forward(self, x): 188 | x = x.transpose(1, 3).contiguous() 189 | x = x.view((-1, self.max_samples, self.feature_size)) 190 | activation = torch.matmul(x, self.cluster_weights) 191 | if self.add_batch_norm: 192 | # activation = activation.transpose(1,2).contiguous() 193 | activation = activation.view(-1, self.cluster_size) 194 | activation = self.bn1(activation) 195 | activation = activation.view(-1, 196 | self.max_samples, self.cluster_size) 197 | # activation = activation.transpose(1,2).contiguous() 198 | else: 199 | activation = activation + self.cluster_biases 200 | activation = self.softmax(activation) 201 | activation = activation.view((-1, self.max_samples, self.cluster_size)) 202 | 203 | a_sum = activation.sum(-2, keepdim=True) 204 | a = a_sum * self.cluster_weights2 205 | 206 | activation = torch.transpose(activation, 2, 1) 207 | x = x.view((-1, self.max_samples, self.feature_size)) 208 | vlad = torch.matmul(activation, x) 209 | vlad = torch.transpose(vlad, 2, 1) 210 | vlad = vlad - a 211 | 212 | vlad = F.normalize(vlad, dim=1, p=2) 213 | vlad = vlad.view((-1, self.cluster_size * self.feature_size)) 214 | vlad = F.normalize(vlad, dim=1, p=2) 215 | 216 | vlad = torch.matmul(vlad, self.hidden1_weights) 217 | 218 | vlad = self.bn2(vlad) 219 | 220 | if self.gating: 221 | vlad = self.context_gating(vlad) 222 | 223 | return vlad 224 | 225 | 226 | class GatingContext(nn.Module): 227 | def __init__(self, dim, add_batch_norm=True): 228 | super(GatingContext, self).__init__() 229 | self.dim = dim 230 | self.add_batch_norm = add_batch_norm 231 | self.gating_weights = nn.Parameter( 232 | torch.randn(dim, dim) * 1 / math.sqrt(dim)) 233 | self.sigmoid = nn.Sigmoid() 234 | 235 | if add_batch_norm: 236 | self.gating_biases = None 237 | self.bn1 = nn.BatchNorm1d(dim) 238 | else: 239 | self.gating_biases = nn.Parameter( 240 | torch.randn(dim) * 1 / math.sqrt(dim)) 241 | self.bn1 = None 242 | 243 | def forward(self, x): 244 | gates = torch.matmul(x, self.gating_weights) 245 | 246 | if self.add_batch_norm: 247 | gates = self.bn1(gates) 248 | else: 249 | gates = gates + self.gating_biases 250 | 251 | gates = self.sigmoid(gates) 252 | 253 | activation = x * gates 254 | 255 | return activation 256 | 257 | 258 | class Flatten(nn.Module): 259 | def __init__(self): 260 | nn.Module.__init__(self) 261 | 262 | def forward(self, input): 263 | return input.view(input.size(0), -1) 264 | 265 | 266 | class STN2d(nn.Module): 267 | def __init__(self, num_points=256, k=2, use_bn=True): 268 | super(STN2d, self).__init__() 269 | self.k = k 270 | self.kernel_size = 2 if k == 2 else 1 271 | self.channels = 1 if k == 2 else k 272 | self.num_points = num_points 273 | self.use_bn = use_bn 274 | self.conv1 = torch.nn.Conv2d(self.channels, 64, (1, self.kernel_size)) 275 | self.conv2 = torch.nn.Conv2d(64, 128, (1,1)) 276 | self.conv3 = torch.nn.Conv2d(128, 1024, (1,1)) 277 | self.mp1 = torch.nn.MaxPool2d((num_points, 1), 1) 278 | self.fc1 = nn.Linear(1024, 512) 279 | self.fc2 = nn.Linear(512, 256) 280 | self.fc3 = nn.Linear(256, k*k) 281 | self.fc3.weight.data.zero_() 282 | self.fc3.bias.data.zero_() 283 | self.relu = nn.ReLU() 284 | 285 | if use_bn: 286 | self.bn1 = nn.BatchNorm2d(64) 287 | self.bn2 = nn.BatchNorm2d(128) 288 | self.bn3 = nn.BatchNorm2d(1024) 289 | self.bn4 = nn.BatchNorm1d(512) 290 | self.bn5 = nn.BatchNorm1d(256) 291 | 292 | def forward(self, x): 293 | batchsize = x.size()[0] 294 | if self.use_bn: 295 | x = F.relu(self.bn1(self.conv1(x))) 296 | x = F.relu(self.bn2(self.conv2(x))) 297 | x = F.relu(self.bn3(self.conv3(x))) 298 | else: 299 | x = F.relu(self.conv1(x)) 300 | x = F.relu(self.conv2(x)) 301 | x = F.relu(self.conv3(x)) 302 | x = self.mp1(x) 303 | x = x.view(-1, 1024) 304 | 305 | if self.use_bn: 306 | x = F.relu(self.bn4(self.fc1(x))) 307 | x = F.relu(self.bn5(self.fc2(x))) 308 | else: 309 | x = F.relu(self.fc1(x)) 310 | x = F.relu(self.fc2(x)) 311 | x = self.fc3(x) 312 | 313 | iden = Variable(torch.from_numpy(np.eye(self.k).astype(np.float32))).view( 314 | 1, self.k*self.k).repeat(batchsize, 1) 315 | if x.is_cuda: 316 | iden = iden.cuda() 317 | x = x + iden 318 | x = x.view(-1, self.k, self.k) 319 | return x 320 | 321 | 322 | class STN3d(nn.Module): 323 | def __init__(self, num_points=2500, k=3, use_bn=True): 324 | super(STN3d, self).__init__() 325 | self.k = k 326 | self.kernel_size = 3 if k == 3 else 1 327 | self.channels = 1 if k == 3 else k 328 | self.num_points = num_points 329 | self.use_bn = use_bn 330 | self.conv1 = torch.nn.Conv2d(self.channels, 64, (1, self.kernel_size)) 331 | self.conv2 = torch.nn.Conv2d(64, 128, (1,1)) 332 | self.conv3 = torch.nn.Conv2d(128, 1024, (1,1)) 333 | self.mp1 = torch.nn.MaxPool2d((num_points, 1), 1) 334 | self.fc1 = nn.Linear(1024, 512) 335 | self.fc2 = nn.Linear(512, 256) 336 | self.fc3 = nn.Linear(256, k*k) 337 | self.fc3.weight.data.zero_() 338 | self.fc3.bias.data.zero_() 339 | self.relu = nn.ReLU() 340 | 341 | if use_bn: 342 | self.bn1 = nn.BatchNorm2d(64) 343 | self.bn2 = nn.BatchNorm2d(128) 344 | self.bn3 = nn.BatchNorm2d(1024) 345 | self.bn4 = nn.BatchNorm1d(512) 346 | self.bn5 = nn.BatchNorm1d(256) 347 | 348 | def forward(self, x): 349 | batchsize = x.size()[0] 350 | if self.use_bn: 351 | x = F.relu(self.bn1(self.conv1(x))) 352 | x = F.relu(self.bn2(self.conv2(x))) 353 | x = F.relu(self.bn3(self.conv3(x))) 354 | else: 355 | x = F.relu(self.conv1(x)) 356 | x = F.relu(self.conv2(x)) 357 | x = F.relu(self.conv3(x)) 358 | x = self.mp1(x) 359 | x = x.view(-1, 1024) 360 | 361 | if self.use_bn: 362 | x = F.relu(self.bn4(self.fc1(x))) 363 | x = F.relu(self.bn5(self.fc2(x))) 364 | else: 365 | x = F.relu(self.fc1(x)) 366 | x = F.relu(self.fc2(x)) 367 | x = self.fc3(x) 368 | 369 | iden = Variable(torch.from_numpy(np.eye(self.k).astype(np.float32))).view( 370 | 1, self.k*self.k).repeat(batchsize, 1) 371 | if x.is_cuda: 372 | iden = iden.cuda() 373 | x = x + iden 374 | x = x.view(-1, self.k, self.k) 375 | return x 376 | 377 | 378 | class ObsFeatAVD(nn.Module): 379 | """Feature extractor for 2D organized point clouds""" 380 | def __init__(self, n_out=1024, num_points=2500, global_feat=True, feature_transform=False, max_pool=True): 381 | super(ObsFeatAVD, self).__init__() 382 | self.n_out = n_out 383 | self.global_feature = global_feat 384 | self.feature_transform = feature_transform 385 | self.max_pool = max_pool 386 | k = 3 387 | p = int(np.floor(k / 2)) + 2 388 | self.stn = STN3d(num_points=num_points, k=3, use_bn=False) 389 | self.feature_trans = STN3d(num_points=num_points, k=64, use_bn=False) 390 | self.conv1 = nn.Conv2d(3,64,kernel_size=k,padding=p,dilation=3) 391 | self.conv2 = nn.Conv2d(64,128,kernel_size=k,padding=p,dilation=3) 392 | self.conv3 = nn.Conv2d(128,256,kernel_size=k,padding=p,dilation=3) 393 | self.conv7 = nn.Conv2d(256,self.n_out,kernel_size=k,padding=p,dilation=3) 394 | self.amp = nn.AdaptiveMaxPool2d(1) 395 | 396 | def forward(self, x): 397 | batchsize = x.size()[0] 398 | trans = self.stn(x) 399 | x = torch.matmul(torch.squeeze(x), trans) 400 | x = x.view(batchsize, 1, -1, 3) 401 | x = x.permute(0,3,1,2) 402 | assert(x.shape[1]==3),"the input size must be " 403 | x = F.relu(self.conv1(x)) 404 | x = F.relu(self.conv2(x)) 405 | x = F.relu(self.conv3(x)) 406 | x = self.conv7(x) 407 | if self.max_pool: 408 | x = self.amp(x) 409 | #x = x.view(-1,self.n_out) # 410 | x = x.permute(0,2,3,1) 411 | return x 412 | 413 | class ImageNetfeat(nn.Module): 414 | def __init__(self, global_feat=True, feature_transform=False, max_pool=True): 415 | super(ImageNetfeat, self).__init__() 416 | encoder = models.vgg16(pretrained=True) 417 | layers = list(encoder.features.children())[:-2] 418 | 419 | self.base_model = nn.Sequential(*layers) 420 | 421 | def forward(self, x): 422 | B,_,g_x,g_y,_ = x.shape 423 | result = self.base_model(x.reshape(B,3,g_x,g_y)) 424 | return result 425 | 426 | class ImageNetVlad(nn.Module): 427 | def __init__(self, grid_x=256, grid_y=256, global_feat=True, feature_transform=False, max_pool=True, output_dim=1024): 428 | super(ImageNetVlad, self).__init__() 429 | 430 | self.obs_feat_extractor = ImageNetfeat(global_feat=global_feat, 431 | feature_transform=feature_transform, max_pool=max_pool) 432 | 433 | dim = list(self.obs_feat_extractor.parameters())[-1].shape[0] 434 | self.net_vlad = NetVLAD_Image(num_clusters=32, dim=512, vladv2=True) 435 | self.fc1 = nn.Linear(16384, 4096) 436 | self.bn1 = nn.BatchNorm1d(4096) 437 | self.fc2 = nn.Linear(4096, output_dim) 438 | self.bn2 = nn.BatchNorm1d(output_dim) 439 | self.relu = nn.ReLU() 440 | 441 | def forward(self, x): 442 | x = self.obs_feat_extractor(x) 443 | x = self.net_vlad(x) 444 | x = self.relu(self.bn1(self.fc1(x))) 445 | x = self.relu(self.bn2(self.fc2(x))) 446 | 447 | return x 448 | 449 | 450 | if __name__ == '__main__': 451 | num_points = 256 452 | sim_data = Variable(torch.rand(44, 1, num_points, 3)) 453 | sim_data = sim_data.cuda() 454 | 455 | pnv = PointNetVlad.PointNetVlad(global_feat=True, feature_transform=True, max_pool=False, 456 | output_dim=256, num_points=num_points).cuda() 457 | pnv.train() 458 | out3 = pnv(sim_data) 459 | print('pnv', out3.size()) -------------------------------------------------------------------------------- /models/PointNetVlad.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.parallel 5 | import torch.utils.data 6 | from torch.autograd import Variable 7 | import numpy as np 8 | import torch.nn.functional as F 9 | import math 10 | import random 11 | from .resnet_mod import * 12 | 13 | class NetVLADLoupe(nn.Module): 14 | def __init__(self, feature_size, max_samples, cluster_size, output_dim, 15 | gating=True, add_batch_norm=True, is_training=True): 16 | super(NetVLADLoupe, self).__init__() 17 | self.feature_size = feature_size 18 | self.max_samples = max_samples 19 | self.output_dim = output_dim 20 | self.is_training = is_training 21 | self.gating = gating 22 | self.add_batch_norm = add_batch_norm 23 | self.cluster_size = cluster_size 24 | self.softmax = nn.Softmax(dim=-1) 25 | self.cluster_weights = nn.Parameter(torch.randn( 26 | feature_size, cluster_size) * 1 / math.sqrt(feature_size)) 27 | self.cluster_weights2 = nn.Parameter(torch.randn( 28 | 1, feature_size, cluster_size) * 1 / math.sqrt(feature_size)) 29 | self.hidden1_weights = nn.Parameter( 30 | torch.randn(cluster_size * feature_size, output_dim) * 1 / math.sqrt(feature_size)) 31 | 32 | if add_batch_norm: 33 | self.cluster_biases = None 34 | self.bn1 = nn.BatchNorm1d(cluster_size) 35 | else: 36 | self.cluster_biases = nn.Parameter(torch.randn( 37 | cluster_size) * 1 / math.sqrt(feature_size)) 38 | self.bn1 = None 39 | 40 | self.bn2 = nn.BatchNorm1d(output_dim) 41 | 42 | if gating: 43 | self.context_gating = GatingContext( 44 | output_dim, add_batch_norm=add_batch_norm) 45 | 46 | def forward(self, x): 47 | x = x.transpose(1, 3).contiguous() 48 | x = x.view((-1, self.max_samples, self.feature_size)) 49 | activation = torch.matmul(x, self.cluster_weights) 50 | if self.add_batch_norm: 51 | # activation = activation.transpose(1,2).contiguous() 52 | activation = activation.view(-1, self.cluster_size) 53 | activation = self.bn1(activation) 54 | activation = activation.view(-1, 55 | self.max_samples, self.cluster_size) 56 | # activation = activation.transpose(1,2).contiguous() 57 | else: 58 | activation = activation + self.cluster_biases 59 | activation = self.softmax(activation) 60 | activation = activation.view((-1, self.max_samples, self.cluster_size)) 61 | 62 | a_sum = activation.sum(-2, keepdim=True) 63 | a = a_sum * self.cluster_weights2 64 | 65 | activation = torch.transpose(activation, 2, 1) 66 | x = x.view((-1, self.max_samples, self.feature_size)) 67 | vlad = torch.matmul(activation, x) 68 | vlad = torch.transpose(vlad, 2, 1) 69 | vlad = vlad - a 70 | 71 | vlad = F.normalize(vlad, dim=1, p=2) 72 | vlad = vlad.reshape((-1, self.cluster_size * self.feature_size)) 73 | vlad = F.normalize(vlad, dim=1, p=2) 74 | 75 | vlad = torch.matmul(vlad, self.hidden1_weights) 76 | 77 | vlad = self.bn2(vlad) 78 | 79 | if self.gating: 80 | vlad = self.context_gating(vlad) 81 | 82 | return vlad 83 | 84 | 85 | class GatingContext(nn.Module): 86 | def __init__(self, dim, add_batch_norm=True): 87 | super(GatingContext, self).__init__() 88 | self.dim = dim 89 | self.add_batch_norm = add_batch_norm 90 | self.gating_weights = nn.Parameter( 91 | torch.randn(dim, dim) * 1 / math.sqrt(dim)) 92 | self.sigmoid = nn.Sigmoid() 93 | 94 | if add_batch_norm: 95 | self.gating_biases = None 96 | self.bn1 = nn.BatchNorm1d(dim) 97 | else: 98 | self.gating_biases = nn.Parameter( 99 | torch.randn(dim) * 1 / math.sqrt(dim)) 100 | self.bn1 = None 101 | 102 | def forward(self, x): 103 | gates = torch.matmul(x, self.gating_weights) 104 | 105 | if self.add_batch_norm: 106 | gates = self.bn1(gates) 107 | else: 108 | gates = gates + self.gating_biases 109 | 110 | gates = self.sigmoid(gates) 111 | 112 | activation = x * gates 113 | 114 | return activation 115 | 116 | 117 | class Flatten(nn.Module): 118 | def __init__(self): 119 | nn.Module.__init__(self) 120 | 121 | def forward(self, input): 122 | return input.view(input.size(0), -1) 123 | 124 | 125 | class STN2d(nn.Module): 126 | def __init__(self, num_points=256, k=2, use_bn=True): 127 | super(STN2d, self).__init__() 128 | self.k = k 129 | self.kernel_size = 2 if k == 2 else 1 130 | self.channels = 1 if k == 2 else k 131 | self.num_points = num_points 132 | self.use_bn = use_bn 133 | self.conv1 = torch.nn.Conv2d(self.channels, 64, (1, self.kernel_size)) 134 | self.conv2 = torch.nn.Conv2d(64, 128, (1,1)) 135 | self.conv3 = torch.nn.Conv2d(128, 1024, (1,1)) 136 | self.mp1 = torch.nn.MaxPool2d((num_points, 1), 1) 137 | self.fc1 = nn.Linear(1024, 512) 138 | self.fc2 = nn.Linear(512, 256) 139 | self.fc3 = nn.Linear(256, k*k) 140 | self.fc3.weight.data.zero_() 141 | self.fc3.bias.data.zero_() 142 | self.relu = nn.ReLU() 143 | 144 | if use_bn: 145 | self.bn1 = nn.BatchNorm2d(64) 146 | self.bn2 = nn.BatchNorm2d(128) 147 | self.bn3 = nn.BatchNorm2d(1024) 148 | self.bn4 = nn.BatchNorm1d(512) 149 | self.bn5 = nn.BatchNorm1d(256) 150 | 151 | def forward(self, x): 152 | batchsize = x.size()[0] 153 | if self.use_bn: 154 | x = F.relu(self.bn1(self.conv1(x))) 155 | x = F.relu(self.bn2(self.conv2(x))) 156 | x = F.relu(self.bn3(self.conv3(x))) 157 | else: 158 | x = F.relu(self.conv1(x)) 159 | x = F.relu(self.conv2(x)) 160 | x = F.relu(self.conv3(x)) 161 | x = self.mp1(x) 162 | x = x.view(-1, 1024) 163 | 164 | if self.use_bn: 165 | x = F.relu(self.bn4(self.fc1(x))) 166 | x = F.relu(self.bn5(self.fc2(x))) 167 | else: 168 | x = F.relu(self.fc1(x)) 169 | x = F.relu(self.fc2(x)) 170 | x = self.fc3(x) 171 | 172 | iden = Variable(torch.from_numpy(np.eye(self.k).astype(np.float32))).view( 173 | 1, self.k*self.k).repeat(batchsize, 1) 174 | if x.is_cuda: 175 | iden = iden.cuda() 176 | x = x + iden 177 | x = x.view(-1, self.k, self.k) 178 | return x 179 | 180 | 181 | class STN3d(nn.Module): 182 | def __init__(self, num_points=2500, k=3, use_bn=True): 183 | super(STN3d, self).__init__() 184 | self.k = k 185 | self.kernel_size = 3 if k == 3 else 1 186 | self.channels = 1 if k == 3 else k 187 | self.num_points = num_points 188 | self.use_bn = use_bn 189 | self.conv1 = torch.nn.Conv2d(self.channels, 64, (1, self.kernel_size)) 190 | self.conv2 = torch.nn.Conv2d(64, 128, (1,1)) 191 | self.conv3 = torch.nn.Conv2d(128, 1024, (1,1)) 192 | self.mp1 = torch.nn.MaxPool2d((num_points, 1), 1) 193 | self.fc1 = nn.Linear(1024, 512) 194 | self.fc2 = nn.Linear(512, 256) 195 | self.fc3 = nn.Linear(256, k*k) 196 | self.fc3.weight.data.zero_() 197 | self.fc3.bias.data.zero_() 198 | self.relu = nn.ReLU() 199 | 200 | if use_bn: 201 | self.bn1 = nn.BatchNorm2d(64) 202 | self.bn2 = nn.BatchNorm2d(128) 203 | self.bn3 = nn.BatchNorm2d(1024) 204 | self.bn4 = nn.BatchNorm1d(512) 205 | self.bn5 = nn.BatchNorm1d(256) 206 | 207 | def forward(self, x): 208 | batchsize = x.size()[0] 209 | if self.use_bn: 210 | x = F.relu(self.bn1(self.conv1(x))) 211 | x = F.relu(self.bn2(self.conv2(x))) 212 | x = F.relu(self.bn3(self.conv3(x))) 213 | else: 214 | x = F.relu(self.conv1(x)) 215 | x = F.relu(self.conv2(x)) 216 | x = F.relu(self.conv3(x)) 217 | x = self.mp1(x) 218 | x = x.view(-1, 1024) 219 | 220 | if self.use_bn: 221 | x = F.relu(self.bn4(self.fc1(x))) 222 | x = F.relu(self.bn5(self.fc2(x))) 223 | else: 224 | x = F.relu(self.fc1(x)) 225 | x = F.relu(self.fc2(x)) 226 | x = self.fc3(x) 227 | 228 | iden = Variable(torch.from_numpy(np.eye(self.k).astype(np.float32))).view( 229 | 1, self.k*self.k).repeat(batchsize, 1) 230 | if x.is_cuda: 231 | iden = iden.cuda() 232 | x = x + iden 233 | x = x.view(-1, self.k, self.k) 234 | return x 235 | 236 | 237 | class ObsFeatAVD(nn.Module): 238 | """Feature extractor for 2D organized point clouds""" 239 | def __init__(self, n_out=1024, num_points=2500, global_feat=True, feature_transform=False, max_pool=True): 240 | super(ObsFeatAVD, self).__init__() 241 | self.n_out = n_out 242 | self.global_feature = global_feat 243 | self.feature_transform = feature_transform 244 | self.max_pool = max_pool 245 | k = 3 246 | p = int(np.floor(k / 2)) + 2 247 | self.stn = STN3d(num_points=num_points, k=3, use_bn=False) 248 | self.feature_trans = STN3d(num_points=num_points, k=64, use_bn=False) 249 | self.conv1 = nn.Conv2d(3,64,kernel_size=k,padding=p,dilation=3) 250 | self.conv2 = nn.Conv2d(64,128,kernel_size=k,padding=p,dilation=3) 251 | self.conv3 = nn.Conv2d(128,256,kernel_size=k,padding=p,dilation=3) 252 | self.conv7 = nn.Conv2d(256,self.n_out,kernel_size=k,padding=p,dilation=3) 253 | self.amp = nn.AdaptiveMaxPool2d(1) 254 | 255 | def forward(self, x): 256 | batchsize = x.size()[0] 257 | trans = self.stn(x) 258 | x = torch.matmul(torch.squeeze(x), trans) 259 | x = x.view(batchsize, 1, -1, 3) 260 | x = x.permute(0,3,1,2) 261 | assert(x.shape[1]==3),"the input size must be " 262 | x = F.relu(self.conv1(x)) 263 | x = F.relu(self.conv2(x)) 264 | x = F.relu(self.conv3(x)) 265 | x = self.conv7(x) 266 | if self.max_pool: 267 | x = self.amp(x) 268 | #x = x.view(-1,self.n_out) # 269 | x = x.permute(0,2,3,1) 270 | return x 271 | 272 | class PointNetfeat(nn.Module): 273 | def __init__(self, num_points=256, global_feat=True, feature_transform=False, max_pool=True): 274 | super(PointNetfeat, self).__init__() 275 | self.stn = STN2d(num_points=num_points, k=2, use_bn=False) 276 | self.feature_trans = STN2d(num_points=num_points, k=64, use_bn=False) 277 | self.apply_feature_trans = feature_transform 278 | self.conv1 = torch.nn.Conv1d(1, 64, (1, 2)) 279 | self.conv2 = torch.nn.Conv1d(64, 64, (1, 1)) 280 | self.conv3 = torch.nn.Conv1d(64, 64, (1, 1)) 281 | self.conv4 = torch.nn.Conv1d(64, 128, (1, 1)) 282 | self.conv5 = torch.nn.Conv2d(128, 1024, (1, 1)) 283 | self.bn1 = nn.BatchNorm2d(64) 284 | self.bn2 = nn.BatchNorm2d(64) 285 | self.bn3 = nn.BatchNorm2d(64) 286 | self.bn4 = nn.BatchNorm2d(128) 287 | self.bn5 = nn.BatchNorm2d(1024) 288 | self.mp1 = torch.nn.MaxPool2d((num_points, 1), 1) 289 | self.num_points = num_points 290 | self.global_feat = global_feat 291 | self.max_pool = max_pool 292 | 293 | def forward(self, x): 294 | x = x[:,:,:,:2] 295 | batchsize = x.size()[0] 296 | trans = self.stn(x) 297 | x = torch.matmul(torch.squeeze(x), trans) 298 | x = x.view(batchsize, 1, -1, 2) 299 | #x = x.transpose(2,1) 300 | #x = torch.bmm(x, trans) 301 | #x = x.transpose(2,1) 302 | x = F.relu(self.bn1(self.conv1(x))) 303 | x = F.relu(self.bn2(self.conv2(x))) 304 | pointfeat = x 305 | if self.apply_feature_trans: 306 | f_trans = self.feature_trans(x) 307 | x = torch.squeeze(x) 308 | if batchsize == 1: 309 | x = torch.unsqueeze(x, 0) 310 | x = torch.matmul(x.transpose(1, 2), f_trans) 311 | x = x.transpose(1, 2).contiguous() 312 | x = x.view(batchsize, 64, -1, 1) 313 | x = F.relu(self.bn3(self.conv3(x))) 314 | x = F.relu(self.bn4(self.conv4(x))) 315 | x = self.bn5(self.conv5(x)) 316 | if not self.max_pool: 317 | return x 318 | else: 319 | x = self.mp1(x) 320 | x = x.view(-1, 1024) 321 | if self.global_feat: 322 | return x, trans 323 | else: 324 | x = x.view(-1, 1024, 1).repeat(1, 1, self.num_points) 325 | return torch.cat([x, pointfeat], 1), trans 326 | 327 | 328 | class PointNetfeatCNN(nn.Module): 329 | def __init__(self, num_points=256, global_feat=True, feature_transform=False, max_pool=True): 330 | super(PointNetfeatCNN, self).__init__() 331 | self.stn = STN2d(num_points=num_points, k=2, use_bn=False) 332 | self.feature_trans = STN2d(num_points=num_points, k=64, use_bn=False) 333 | self.apply_feature_trans = feature_transform 334 | self.conv1 = torch.nn.Conv2d(1, 64, kernel_size=(3,4), stride=1, padding=(1,1), 335 | bias=False, padding_mode='circular') 336 | 337 | self.conv2 = torch.nn.Conv2d(64, 64, kernel_size=(3,3), stride=1, padding=(1,1), 338 | bias=False, padding_mode='circular') 339 | self.conv3 = torch.nn.Conv2d(64, 64, kernel_size=(3,3), stride=1, padding=(1,1), 340 | bias=False, padding_mode='circular') 341 | self.conv4 = torch.nn.Conv2d(64, 128, kernel_size=(3,3), stride=1, padding=(1,1), 342 | bias=False, padding_mode='circular') 343 | self.conv5 = torch.nn.Conv2d(128, 1024, kernel_size=(3,3), stride=1, padding=(1,1), 344 | bias=False, padding_mode='circular') 345 | self.bn1 = nn.BatchNorm2d(64) 346 | self.bn2 = nn.BatchNorm2d(64) 347 | self.bn3 = nn.BatchNorm2d(64) 348 | self.bn4 = nn.BatchNorm2d(128) 349 | self.bn5 = nn.BatchNorm2d(1024) 350 | self.mp1 = torch.nn.MaxPool2d((num_points, 1), 1) 351 | self.num_points = num_points 352 | self.global_feat = global_feat 353 | self.max_pool = max_pool 354 | 355 | def process_data(self,ob,low_th = -20,high_th = 20): 356 | for i in range(ob.size()[0]): 357 | seed = random.randint(low_th, high_th) 358 | ob[i] = torch.roll(ob[i], seed, dims=1) 359 | return ob 360 | 361 | def forward(self, x): 362 | x = x[:,:,:,:2] 363 | batchsize = x.size()[0] 364 | threshold = batchsize//2 365 | x = self.process_data(x, low_th=-threshold, high_th=threshold) 366 | #trans = self.stn(x) 367 | #x = torch.matmul(torch.squeeze(x), trans) 368 | x = x.view(batchsize, 1, -1, 2) 369 | x = F.relu(self.bn1(self.conv1(x))) 370 | x = F.relu(self.bn2(self.conv2(x))) 371 | 372 | pointfeat = x 373 | 374 | if self.apply_feature_trans: 375 | f_trans = self.feature_trans(x) 376 | x = torch.squeeze(x) 377 | if batchsize == 1: 378 | x = torch.unsqueeze(x, 0) 379 | x = torch.matmul(x.transpose(1, 2), f_trans) 380 | x = x.transpose(1, 2).contiguous() 381 | x = x.view(batchsize, 64, -1, 1) 382 | x = F.relu(self.bn3(self.conv3(x))) 383 | x = F.relu(self.bn4(self.conv4(x))) 384 | x = self.bn5(self.conv5(x)) 385 | if not self.max_pool: 386 | return x 387 | else: 388 | x = self.mp1(x) 389 | x = x.view(-1, 1024) 390 | 391 | if self.global_feat: 392 | return x, trans 393 | else: 394 | x = x.view(-1, 1024, 1).repeat(1, 1, self.num_points) 395 | return torch.cat([x, pointfeat], 1), trans 396 | 397 | class PointNetVlad(nn.Module): 398 | def __init__(self, num_points=256, global_feat=True, feature_transform=False, max_pool=True, output_dim=1024): 399 | super(PointNetVlad, self).__init__() 400 | #self.point_net = PointNetfeat(num_points=num_points, global_feat=global_feat, 401 | # feature_transform=feature_transform, max_pool=max_pool) 402 | #self.obs_feat_extractor = ObsFeatAVD(n_out=1024, num_points=num_points, global_feat=global_feat, 403 | # feature_transform=feature_transform, max_pool=max_pool) 404 | self.obs_feat_extractor = PointNetfeatCNN(num_points=num_points, global_feat=global_feat, 405 | feature_transform=feature_transform, max_pool=max_pool) 406 | self.net_vlad = NetVLADLoupe(feature_size=1024, max_samples=num_points, cluster_size=64, 407 | output_dim=output_dim, gating=True, add_batch_norm=True, 408 | is_training=True) 409 | 410 | def forward(self, x): 411 | #x = self.point_net(x) 412 | x = self.obs_feat_extractor(x) 413 | x = self.net_vlad(x) 414 | return x 415 | 416 | 417 | if __name__ == '__main__': 418 | num_points = 256 419 | sim_data = Variable(torch.rand(44, 1, num_points, 3)) 420 | sim_data = sim_data.cuda() 421 | 422 | pnv = PointNetVlad.PointNetVlad(global_feat=True, feature_transform=True, max_pool=False, 423 | output_dim=256, num_points=num_points).cuda() 424 | pnv.train() 425 | out3 = pnv(sim_data) 426 | print('pnv', out3.size()) 427 | -------------------------------------------------------------------------------- /models/resnet_mod.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | # from .utils import load_state_dict_from_url 4 | 5 | 6 | __all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101', 7 | 'resnet152', 'resnext50_32x4d', 'resnext101_32x8d', 8 | 'wide_resnet50_2', 'wide_resnet101_2'] 9 | 10 | 11 | model_urls = { 12 | 'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth', 13 | 'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth', 14 | 'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth', 15 | 'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth', 16 | 'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth', 17 | 'resnext50_32x4d': 'https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pth', 18 | 'resnext101_32x8d': 'https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pth', 19 | 'wide_resnet50_2': 'https://download.pytorch.org/models/wide_resnet50_2-95faca4d.pth', 20 | 'wide_resnet101_2': 'https://download.pytorch.org/models/wide_resnet101_2-32ee1156.pth', 21 | } 22 | 23 | 24 | def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1): 25 | """3x3 convolution with padding""" 26 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 27 | padding=dilation, groups=groups, bias=False, dilation=dilation, padding_mode='circular') 28 | 29 | 30 | def conv1x1(in_planes, out_planes, stride=1): 31 | """1x1 convolution""" 32 | return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False) 33 | 34 | 35 | class BasicBlock(nn.Module): 36 | expansion = 1 37 | __constants__ = ['downsample'] 38 | 39 | def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, 40 | base_width=64, dilation=1, norm_layer=None): 41 | super(BasicBlock, self).__init__() 42 | if norm_layer is None: 43 | norm_layer = nn.BatchNorm2d 44 | if groups != 1 or base_width != 64: 45 | raise ValueError('BasicBlock only supports groups=1 and base_width=64') 46 | if dilation > 1: 47 | raise NotImplementedError("Dilation > 1 not supported in BasicBlock") 48 | # Both self.conv1 and self.downsample layers downsample the input when stride != 1 49 | self.conv1 = conv3x3(inplanes, planes, stride) 50 | self.bn1 = norm_layer(planes) 51 | self.relu = nn.ReLU(inplace=True) 52 | self.conv2 = conv3x3(planes, planes) 53 | self.bn2 = norm_layer(planes) 54 | self.downsample = downsample 55 | self.stride = stride 56 | 57 | def forward(self, x): 58 | identity = x 59 | 60 | out = self.conv1(x) 61 | out = self.bn1(out) 62 | out = self.relu(out) 63 | 64 | out = self.conv2(out) 65 | out = self.bn2(out) 66 | 67 | if self.downsample is not None: 68 | identity = self.downsample(x) 69 | 70 | out += identity 71 | out = self.relu(out) 72 | 73 | return out 74 | 75 | 76 | class Bottleneck(nn.Module): 77 | expansion = 4 78 | __constants__ = ['downsample'] 79 | 80 | def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, 81 | base_width=64, dilation=1, norm_layer=None): 82 | super(Bottleneck, self).__init__() 83 | if norm_layer is None: 84 | norm_layer = nn.BatchNorm2d 85 | width = int(planes * (base_width / 64.)) * groups 86 | # Both self.conv2 and self.downsample layers downsample the input when stride != 1 87 | self.conv1 = conv1x1(inplanes, width) 88 | self.bn1 = norm_layer(width) 89 | self.conv2 = conv3x3(width, width, stride, groups, dilation) 90 | self.bn2 = norm_layer(width) 91 | self.conv3 = conv1x1(width, planes * self.expansion) 92 | self.bn3 = norm_layer(planes * self.expansion) 93 | self.relu = nn.ReLU(inplace=True) 94 | self.downsample = downsample 95 | self.stride = stride 96 | 97 | def forward(self, x): 98 | identity = x 99 | 100 | out = self.conv1(x) 101 | out = self.bn1(out) 102 | out = self.relu(out) 103 | 104 | out = self.conv2(out) 105 | out = self.bn2(out) 106 | out = self.relu(out) 107 | 108 | out = self.conv3(out) 109 | out = self.bn3(out) 110 | 111 | if self.downsample is not None: 112 | identity = self.downsample(x) 113 | 114 | out += identity 115 | out = self.relu(out) 116 | 117 | return out 118 | 119 | 120 | class ResNet(nn.Module): 121 | 122 | def __init__(self, block, layers, num_classes=1000, zero_init_residual=False, 123 | groups=1, width_per_group=64, replace_stride_with_dilation=None, 124 | norm_layer=None): 125 | super(ResNet, self).__init__() 126 | if norm_layer is None: 127 | norm_layer = nn.BatchNorm2d 128 | self._norm_layer = norm_layer 129 | 130 | self.inplanes = 64 131 | self.dilation = 1 132 | if replace_stride_with_dilation is None: 133 | # each element in the tuple indicates if we should replace 134 | # the 2x2 stride with a dilated convolution instead 135 | replace_stride_with_dilation = [False, False, False] 136 | if len(replace_stride_with_dilation) != 3: 137 | raise ValueError("replace_stride_with_dilation should be None " 138 | "or a 3-element tuple, got {}".format(replace_stride_with_dilation)) 139 | self.groups = groups 140 | self.base_width = width_per_group 141 | self.conv1 = nn.Conv2d(1, self.inplanes, kernel_size=7, stride=2, padding=3, 142 | bias=False, padding_mode='circular') 143 | self.bn1 = norm_layer(self.inplanes) 144 | self.relu = nn.ReLU(inplace=True) 145 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) 146 | self.layer1 = self._make_layer(block, 64, layers[0]) 147 | self.layer2 = self._make_layer(block, 128, layers[1], stride=2, 148 | dilate=replace_stride_with_dilation[0]) 149 | self.layer3 = self._make_layer(block, 256, layers[2], stride=2, 150 | dilate=replace_stride_with_dilation[1]) 151 | self.layer4 = self._make_layer(block, 512, layers[3], stride=2, 152 | dilate=replace_stride_with_dilation[2]) 153 | self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) 154 | self.fc = nn.Linear(512 * block.expansion, num_classes) 155 | 156 | for m in self.modules(): 157 | if isinstance(m, nn.Conv2d): 158 | nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') 159 | elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): 160 | nn.init.constant_(m.weight, 1) 161 | nn.init.constant_(m.bias, 0) 162 | 163 | # Zero-initialize the last BN in each residual branch, 164 | # so that the residual branch starts with zeros, and each residual block behaves like an identity. 165 | # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677 166 | if zero_init_residual: 167 | for m in self.modules(): 168 | if isinstance(m, Bottleneck): 169 | nn.init.constant_(m.bn3.weight, 0) 170 | elif isinstance(m, BasicBlock): 171 | nn.init.constant_(m.bn2.weight, 0) 172 | 173 | def _make_layer(self, block, planes, blocks, stride=1, dilate=False): 174 | norm_layer = self._norm_layer 175 | downsample = None 176 | previous_dilation = self.dilation 177 | if dilate: 178 | self.dilation *= stride 179 | stride = 1 180 | if stride != 1 or self.inplanes != planes * block.expansion: 181 | downsample = nn.Sequential( 182 | conv1x1(self.inplanes, planes * block.expansion, stride), 183 | norm_layer(planes * block.expansion), 184 | ) 185 | 186 | layers = [] 187 | layers.append(block(self.inplanes, planes, stride, downsample, self.groups, 188 | self.base_width, previous_dilation, norm_layer)) 189 | self.inplanes = planes * block.expansion 190 | for _ in range(1, blocks): 191 | layers.append(block(self.inplanes, planes, groups=self.groups, 192 | base_width=self.base_width, dilation=self.dilation, 193 | norm_layer=norm_layer)) 194 | 195 | return nn.Sequential(*layers) 196 | 197 | def _forward_impl(self, x): 198 | # See note [TorchScript super()] 199 | print("x:"+str(x.shape)) 200 | x = self.conv1(x) 201 | print("x2:"+str(x.shape)) 202 | x = self.bn1(x) 203 | print("x3:"+str(x.shape)) 204 | x = self.relu(x) 205 | print("x4:"+str(x.shape)) 206 | x = self.maxpool(x) 207 | print("x5:"+str(x.shape)) 208 | x = self.layer1(x) 209 | x = self.layer2(x) 210 | x = self.layer3(x) 211 | x = self.layer4(x) 212 | 213 | x = self.avgpool(x) 214 | x = torch.flatten(x, 1) 215 | x = self.fc(x) 216 | 217 | return x 218 | 219 | def forward(self, x): 220 | return self._forward_impl(x) 221 | 222 | 223 | def _resnet(arch, block, layers, pretrained, progress, **kwargs): 224 | model = ResNet(block, layers, **kwargs) 225 | # if pretrained: 226 | # state_dict = load_state_dict_from_url(model_urls[arch], 227 | # progress=progress) 228 | # model.load_state_dict(state_dict) 229 | return model 230 | 231 | 232 | def resnet18(pretrained=False, progress=True, **kwargs): 233 | r"""ResNet-18 model from 234 | `"Deep Residual Learning for Image Recognition" `_ 235 | Args: 236 | pretrained (bool): If True, returns a model pre-trained on ImageNet 237 | progress (bool): If True, displays a progress bar of the download to stderr 238 | """ 239 | return _resnet('resnet18', BasicBlock, [2, 2, 2, 2], pretrained, progress, 240 | **kwargs) 241 | 242 | 243 | def resnet34(pretrained=False, progress=True, **kwargs): 244 | r"""ResNet-34 model from 245 | `"Deep Residual Learning for Image Recognition" `_ 246 | Args: 247 | pretrained (bool): If True, returns a model pre-trained on ImageNet 248 | progress (bool): If True, displays a progress bar of the download to stderr 249 | """ 250 | return _resnet('resnet34', BasicBlock, [3, 4, 6, 3], pretrained, progress, 251 | **kwargs) 252 | 253 | 254 | def resnet50(pretrained=False, progress=True, **kwargs): 255 | r"""ResNet-50 model from 256 | `"Deep Residual Learning for Image Recognition" `_ 257 | Args: 258 | pretrained (bool): If True, returns a model pre-trained on ImageNet 259 | progress (bool): If True, displays a progress bar of the download to stderr 260 | """ 261 | return _resnet('resnet50', Bottleneck, [3, 4, 6, 3], pretrained, progress, 262 | **kwargs) 263 | 264 | 265 | def resnet101(pretrained=False, progress=True, **kwargs): 266 | r"""ResNet-101 model from 267 | `"Deep Residual Learning for Image Recognition" `_ 268 | Args: 269 | pretrained (bool): If True, returns a model pre-trained on ImageNet 270 | progress (bool): If True, displays a progress bar of the download to stderr 271 | """ 272 | return _resnet('resnet101', Bottleneck, [3, 4, 23, 3], pretrained, progress, 273 | **kwargs) 274 | 275 | 276 | def resnet152(pretrained=False, progress=True, **kwargs): 277 | r"""ResNet-152 model from 278 | `"Deep Residual Learning for Image Recognition" `_ 279 | Args: 280 | pretrained (bool): If True, returns a model pre-trained on ImageNet 281 | progress (bool): If True, displays a progress bar of the download to stderr 282 | """ 283 | return _resnet('resnet152', Bottleneck, [3, 8, 36, 3], pretrained, progress, 284 | **kwargs) 285 | 286 | 287 | def resnext50_32x4d(pretrained=False, progress=True, **kwargs): 288 | r"""ResNeXt-50 32x4d model from 289 | `"Aggregated Residual Transformation for Deep Neural Networks" `_ 290 | Args: 291 | pretrained (bool): If True, returns a model pre-trained on ImageNet 292 | progress (bool): If True, displays a progress bar of the download to stderr 293 | """ 294 | kwargs['groups'] = 32 295 | kwargs['width_per_group'] = 4 296 | return _resnet('resnext50_32x4d', Bottleneck, [3, 4, 6, 3], 297 | pretrained, progress, **kwargs) 298 | 299 | 300 | def resnext101_32x8d(pretrained=False, progress=True, **kwargs): 301 | r"""ResNeXt-101 32x8d model from 302 | `"Aggregated Residual Transformation for Deep Neural Networks" `_ 303 | Args: 304 | pretrained (bool): If True, returns a model pre-trained on ImageNet 305 | progress (bool): If True, displays a progress bar of the download to stderr 306 | """ 307 | kwargs['groups'] = 32 308 | kwargs['width_per_group'] = 8 309 | return _resnet('resnext101_32x8d', Bottleneck, [3, 4, 23, 3], 310 | pretrained, progress, **kwargs) 311 | 312 | 313 | def wide_resnet50_2(pretrained=False, progress=True, **kwargs): 314 | """Wide ResNet-50-2 model from 315 | `"Wide Residual Networks" `_ 316 | The model is the same as ResNet except for the bottleneck number of channels 317 | which is twice larger in every block. The number of channels in outer 1x1 318 | convolutions is the same, e.g. last block in ResNet-50 has 2048-512-2048 319 | channels, and in Wide ResNet-50-2 has 2048-1024-2048. 320 | Args: 321 | pretrained (bool): If True, returns a model pre-trained on ImageNet 322 | progress (bool): If True, displays a progress bar of the download to stderr 323 | """ 324 | kwargs['width_per_group'] = 64 * 2 325 | return _resnet('wide_resnet50_2', Bottleneck, [3, 4, 6, 3], 326 | pretrained, progress, **kwargs) 327 | 328 | 329 | def wide_resnet101_2(pretrained=False, progress=True, **kwargs): 330 | r"""Wide ResNet-101-2 model from 331 | `"Wide Residual Networks" `_ 332 | The model is the same as ResNet except for the bottleneck number of channels 333 | which is twice larger in every block. The number of channels in outer 1x1 334 | convolutions is the same, e.g. last block in ResNet-50 has 2048-512-2048 335 | channels, and in Wide ResNet-50-2 has 2048-1024-2048. 336 | Args: 337 | pretrained (bool): If True, returns a model pre-trained on ImageNet 338 | progress (bool): If True, displays a progress bar of the download to stderr 339 | """ 340 | kwargs['width_per_group'] = 64 * 2 341 | return _resnet('wide_resnet101_2', Bottleneck, [3, 4, 23, 3], 342 | pretrained, progress, **kwargs) 343 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | torch==1.10.1 2 | tensorboardX 3 | open3d-python==0.4 4 | scipy 5 | matplotlib 6 | numpy 7 | pandas 8 | scikit-learn 9 | pickle5 10 | opencv-python 11 | torchvision 12 | opencv-contrib-python 13 | -------------------------------------------------------------------------------- /results/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ai4ce/TF-VPR/83a4fbf59c1e51c0024c97943788db82fca9da7d/results/.DS_Store -------------------------------------------------------------------------------- /set_path.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | sys.path.insert(0, './') 4 | -------------------------------------------------------------------------------- /train_netvlad_RGB_real_supervise.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | #import torch 3 | #device = torch.device("cuda" if torch.cuda.is_available() else "cpu") 4 | import argparse 5 | import importlib 6 | import math 7 | import os 8 | import socket 9 | import sys 10 | 11 | import numpy as np 12 | from sklearn.neighbors import KDTree, NearestNeighbors 13 | import generating_queries.generate_training_tuples_RGB_real_supervise as generate_dataset_tt 14 | import generating_queries.generate_test_RGB_real_supervise_sets as generate_dataset_eval 15 | 16 | import config as cfg 17 | import evaluate 18 | import loss.pointnetvlad_loss as PNV_loss 19 | import models.Verification_RGB_real as VFC 20 | import models.ImageNetVlad as INV 21 | import torch 22 | import torch.nn as nn 23 | from loading_pointclouds import * 24 | from tensorboardX import SummaryWriter 25 | from torch.autograd import Variable 26 | from torch.backends import cudnn 27 | import scipy.io as sio 28 | 29 | BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 30 | sys.path.append(BASE_DIR) 31 | 32 | 33 | 34 | cudnn.enabled = True 35 | 36 | parser = argparse.ArgumentParser() 37 | parser.add_argument('--log_dir', default='log/', help='Log dir [default: log]') 38 | parser.add_argument('--results_dir', default='results/', 39 | help='results dir [default: results]') 40 | parser.add_argument('--positives_per_query', type=int, default=2, 41 | help='Number of potential positives in each training tuple [default: 2]') 42 | parser.add_argument('--negatives_per_query', type=int, default=18, 43 | help='Number of definite negatives in each training tuple [default: 18]') 44 | parser.add_argument('--max_epoch', type=int, default=30, 45 | help='Epoch to run [default: 100]') 46 | parser.add_argument('--batch_num_queries', type=int, default=2, 47 | help='Batch Size during training [default: 2]') 48 | parser.add_argument('--learning_rate', type=float, default=0.000005, 49 | help='Initial learning rate [default: 0.000005]') 50 | parser.add_argument('--momentum', type=float, default=0.9, 51 | help='Initial learning rate [default: 0.9]') 52 | parser.add_argument('--optimizer', default='adam', 53 | help='adam or momentum [default: adam]') 54 | parser.add_argument('--decay_step', type=int, default=200000, 55 | help='Decay step for lr decay [default: 200000]') 56 | parser.add_argument('--decay_rate', type=float, default=0.7, 57 | help='Decay rate for lr decay [default: 0.7]') 58 | parser.add_argument('--margin_1', type=float, default=0.5, 59 | help='Margin for hinge loss [default: 0.5]') 60 | parser.add_argument('--margin_2', type=float, default=0.2, 61 | help='Margin for hinge loss [default: 0.2]') 62 | parser.add_argument('--loss_function', default='triplet', choices=[ 63 | 'triplet', 'quadruplet'], help='triplet or quadruplet [default: quadruplet]') 64 | parser.add_argument('--loss_not_lazy', action='store_false', 65 | help='If present, do not use lazy variant of loss') 66 | parser.add_argument('--loss_ignore_zero_batch', action='store_true', 67 | help='If present, mean only batches with loss > 0.0') 68 | parser.add_argument('--triplet_use_best_positives', action='store_true', 69 | help='If present, use best positives, otherwise use hardest positives') 70 | parser.add_argument('--resume', action='store_true', 71 | help='If present, restore checkpoint and resume training') 72 | parser.add_argument('--dataset_folder', default='/mnt/NAS/data/cc_data/2D_RGB_real_full3', 73 | help='PointNetVlad Dataset Folder') 74 | 75 | FLAGS = parser.parse_args() 76 | #cfg.EVAL_BATCH_SIZE = 12 77 | cfg.GRID_X = 1080 78 | cfg.GRID_Y = 1920 79 | cfg.BASE_LEARNING_RATE = FLAGS.learning_rate 80 | cfg.MOMENTUM = FLAGS.momentum 81 | cfg.OPTIMIZER = FLAGS.optimizer 82 | cfg.DECAY_STEP = FLAGS.decay_step 83 | cfg.DECAY_RATE = FLAGS.decay_rate 84 | cfg.MARGIN1 = FLAGS.margin_1 85 | cfg.MARGIN2 = FLAGS.margin_2 86 | 87 | cfg.TRIPLET_USE_BEST_POSITIVES = FLAGS.triplet_use_best_positives 88 | cfg.LOSS_LAZY = FLAGS.loss_not_lazy 89 | cfg.LOSS_IGNORE_ZERO_BATCH = FLAGS.loss_ignore_zero_batch 90 | 91 | cfg.TRAIN_FILE = 'generating_queries/train_pickle/training_queries_baseline_0.pickle' 92 | cfg.TEST_FILE = 'generating_queries/train_pickle/test_queries_baseline_0.pickle' 93 | cfg.DB_FILE = 'generating_queries/train_pickle/db_queries_baseline_0.pickle' 94 | 95 | cfg.LOG_DIR = FLAGS.log_dir 96 | if not os.path.exists(cfg.LOG_DIR): 97 | os.mkdir(cfg.LOG_DIR) 98 | LOG_FOUT = open(os.path.join(cfg.LOG_DIR, 'log_train.txt'), 'w') 99 | LOG_FOUT.write(str(FLAGS) + '\n') 100 | 101 | cfg.RESULTS_FOLDER = FLAGS.results_dir 102 | print("cfg.RESULTS_FOLDER:"+str(cfg.RESULTS_FOLDER)) 103 | 104 | # Load dictionary of training queries 105 | TRAINING_QUERIES = get_queries_dict(cfg.TRAIN_FILE) 106 | TEST_QUERIES = get_queries_dict(cfg.TEST_FILE) 107 | DB_QUERIES = get_queries_dict(cfg.DB_FILE) 108 | 109 | cfg.BN_INIT_DECAY = 0.5 110 | cfg.BN_DECAY_DECAY_RATE = 0.5 111 | BN_DECAY_DECAY_STEP = float(cfg.DECAY_STEP) 112 | cfg.BN_DECAY_CLIP = 0.99 113 | 114 | HARD_NEGATIVES = {} 115 | TRAINING_LATENT_VECTORS = [] 116 | 117 | TOTAL_ITERATIONS = 0 118 | 119 | device = torch.device("cuda" if torch.cuda.is_available() else "cpu") 120 | cfg.margin = 0.1 121 | 122 | def get_bn_decay(batch): 123 | bn_momentum = cfg.BN_INIT_DECAY * \ 124 | (cfg.BN_DECAY_DECAY_RATE ** 125 | (batch * cfg.BATCH_NUM_QUERIES // BN_DECAY_DECAY_STEP)) 126 | return min(cfg.BN_DECAY_CLIP, 1 - bn_momentum) 127 | 128 | 129 | def log_string(out_str): 130 | LOG_FOUT.write(out_str + '\n') 131 | LOG_FOUT.flush() 132 | print(out_str) 133 | 134 | # learning rate halfed every 5 epoch 135 | 136 | def get_learning_rate(epoch): 137 | learning_rate = cfg.BASE_LEARNING_RATE * ((0.9) ** (epoch // 5)) 138 | learning_rate = max(learning_rate, 0.00001) # CLIP THE LEARNING RATE! 139 | return learning_rate 140 | 141 | 142 | def train(): 143 | global HARD_NEGATIVES, TOTAL_ITERATIONS, TRAINING_QUERIES 144 | bn_decay = get_bn_decay(0) 145 | 146 | TRAINING_QUERIES = get_queries_dict(cfg.TRAIN_FILE) 147 | TEST_QUERIES = get_queries_dict(cfg.TEST_FILE) 148 | DB_QUERIES = get_queries_dict(cfg.DB_FILE) 149 | 150 | cfg.RESULTS_FOLDER = os.path.join("results/", 'scene2') 151 | if not os.path.isdir(cfg.RESULTS_FOLDER): 152 | os.mkdir(cfg.RESULTS_FOLDER) 153 | if cfg.LOSS_FUNCTION_RGB == 'quadruplet': 154 | loss_function = PNV_loss.quadruplet_loss 155 | elif cfg.LOSS_FUNCTION_RGB == 'triplet_RI': 156 | loss_function = PNV_loss.triplet_loss_RI 157 | else: 158 | loss_function = PNV_loss.triplet_loss 159 | learning_rate = get_learning_rate(0) 160 | 161 | train_writer = SummaryWriter(os.path.join(cfg.LOG_DIR, 'train')) 162 | 163 | model = INV.ImageNetVlad(global_feat=True, feature_transform=True, 164 | max_pool=False, output_dim=cfg.FEATURE_OUTPUT_DIM, grid_x = cfg.GRID_X, grid_y = cfg.GRID_Y) 165 | model = model.to(device) 166 | 167 | parameters = filter(lambda p: p.requires_grad, model.parameters()) 168 | 169 | if cfg.OPTIMIZER == 'momentum': 170 | optimizer = torch.optim.SGD( 171 | parameters, learning_rate, momentum=cfg.MOMENTUM) 172 | elif cfg.OPTIMIZER == 'adam': 173 | optimizer = torch.optim.Adam(parameters, learning_rate) 174 | else: 175 | optimizer = None 176 | exit(0) 177 | 178 | if FLAGS.resume: 179 | resume_filename = cfg.LOG_DIR + "checkpoint.pth.tar" 180 | print("Resuming From ", resume_filename) 181 | checkpoint = torch.load(resume_filename) 182 | saved_state_dict = checkpoint['state_dict'] 183 | starting_epoch = checkpoint['epoch'] 184 | print("starting_epoch:"+str(starting_epoch)) 185 | #starting_epoch = starting_epoch +1 186 | TOTAL_ITERATIONS = starting_epoch * len(TRAINING_QUERIES) 187 | starting_epoch = starting_epoch +1 188 | model.load_state_dict(saved_state_dict) 189 | optimizer.load_state_dict(checkpoint['optimizer']) 190 | 191 | else: 192 | starting_epoch = 0 193 | 194 | 195 | LOG_FOUT.write(cfg.cfg_str()) 196 | LOG_FOUT.write("\n") 197 | LOG_FOUT.flush() 198 | 199 | try: 200 | potential_positives 201 | except NameError: 202 | potential_positives = None 203 | potential_distributions = None 204 | trusted_positives = None 205 | 206 | for epoch in range(starting_epoch, cfg.MAX_EPOCH): 207 | print(epoch) 208 | print() 209 | 210 | log_string('**** EPOCH %03d ****' % (epoch)) 211 | sys.stdout.flush() 212 | 213 | train_one_epoch(model, optimizer, train_writer, loss_function, epoch, TRAINING_QUERIES, TEST_QUERIES, DB_QUERIES) 214 | 215 | log_string('EVALUATING...') 216 | cfg.OUTPUT_FILE = os.path.join(cfg.RESULTS_FOLDER , 'results_' + str(epoch) + '.txt') 217 | eval_recall_1, eval_recall_5, eval_recall_10 = evaluate.evaluate_model_RGB_real(model,optimizer,epoch,True) 218 | 219 | log_string('EVAL RECALL_1: %s' % str(eval_recall_1)) 220 | log_string('EVAL RECALL_5: %s' % str(eval_recall_5)) 221 | log_string('EVAL RECALL_10: %s' % str(eval_recall_10)) 222 | 223 | 224 | def train_one_epoch(model, optimizer, train_writer, loss_function, epoch, TRAINING_QUERIES, TEST_QUERIES, DB_QUERIES): 225 | global HARD_NEGATIVES 226 | global TRAINING_LATENT_VECTORS, TOTAL_ITERATIONS 227 | 228 | is_training = True 229 | sampled_neg = 4000 230 | # number of hard negatives in the training tuple 231 | # which are taken from the sampled negatives 232 | num_to_take = 10 233 | 234 | # Shuffle train files 235 | train_file_idxs = np.arange(0, len(TRAINING_QUERIES.keys())) 236 | np.random.shuffle(train_file_idxs) 237 | 238 | for i in range(len(train_file_idxs)//cfg.BATCH_NUM_QUERIES): 239 | # for i in range(1): 240 | batch_keys = train_file_idxs[i * 241 | cfg.BATCH_NUM_QUERIES:(i+1)*cfg.BATCH_NUM_QUERIES] 242 | q_tuples = [] 243 | 244 | faulty_tuple = False 245 | no_other_neg = False 246 | for j in range(cfg.BATCH_NUM_QUERIES): 247 | if (len(DB_QUERIES[batch_keys[j]]["positives"]) < cfg.TRAIN_POSITIVES_PER_QUERY): 248 | faulty_tuple = True 249 | break 250 | # no cached feature vectors 251 | if (len(TRAINING_LATENT_VECTORS) == 0): 252 | q_tuples.append( 253 | get_query_tuple_RGB_real_supervise(DB_QUERIES[batch_keys[j]], cfg.TRAIN_POSITIVES_PER_QUERY, cfg.TRAIN_NEGATIVES_PER_QUERY, 254 | DB_QUERIES, hard_neg=[], other_neg=True)) 255 | #print("q_tuples:"+str(q_tuples)) 256 | 257 | elif (len(HARD_NEGATIVES.keys()) == 0): 258 | query = get_feature_representation( 259 | DB_QUERIES[batch_keys[j]]['query'], model) 260 | random.shuffle(DB_QUERIES[batch_keys[j]]['negatives']) 261 | negatives = DB_QUERIES[batch_keys[j] 262 | ]['negatives'][0:sampled_neg] 263 | hard_negs = get_random_hard_negatives( 264 | query, negatives, num_to_take) 265 | q_tuples.append( 266 | get_query_tuple_RGB_real_supervise(DB_QUERIES[batch_keys[j]], cfg.TRAIN_POSITIVES_PER_QUERY, cfg.TRAIN_NEGATIVES_PER_QUERY, 267 | DB_QUERIES, hard_negs, other_neg=True)) 268 | else: 269 | query = get_feature_representation( 270 | DB_QUERIES[batch_keys[j]]['query'], model) 271 | random.shuffle(DB_QUERIES[batch_keys[j]]['negatives']) 272 | negatives = DB_QUERIES[batch_keys[j] 273 | ]['negatives'][0:sampled_neg] 274 | hard_negs = get_random_hard_negatives( 275 | query, negatives, num_to_take) 276 | hard_negs = list(set().union( 277 | HARD_NEGATIVES[batch_keys[j]], hard_negs)) 278 | q_tuples.append( 279 | get_query_tuple_RGB_real_supervise(DB_QUERIES[batch_keys[j]], cfg.TRAIN_POSITIVES_PER_QUERY, cfg.TRAIN_NEGATIVES_PER_QUERY, 280 | DB_QUERIES, hard_negs, other_neg=True)) 281 | 282 | if (q_tuples[j][3].shape[2] != 3): 283 | no_other_neg = True 284 | break 285 | 286 | if(faulty_tuple): 287 | log_string('----' + str(i) + '-----') 288 | log_string('----' + 'FAULTY TUPLE' + '-----') 289 | continue 290 | 291 | if(no_other_neg): 292 | log_string('----' + str(i) + '-----') 293 | log_string('----' + 'NO OTHER NEG' + '-----') 294 | continue 295 | 296 | queries = [] 297 | positives = [] 298 | negatives = [] 299 | other_neg = [] 300 | for k in range(len(q_tuples)): 301 | queries.append(q_tuples[k][0]) 302 | positives.append(q_tuples[k][1]) 303 | negatives.append(q_tuples[k][2]) 304 | other_neg.append(q_tuples[k][3]) 305 | 306 | queries = np.array(queries, dtype=np.float32) 307 | queries = np.expand_dims(queries, axis=1) 308 | other_neg = np.array(other_neg, dtype=np.float32) 309 | other_neg = np.expand_dims(other_neg, axis=1) 310 | positives = np.array(positives, dtype=np.float32) 311 | negatives = np.array(negatives, dtype=np.float32) 312 | 313 | log_string('----' + str(i) + '-----') 314 | if (len(queries.shape) != 5): 315 | log_string('----' + 'FAULTY QUERY' + '-----') 316 | continue 317 | 318 | model.train() 319 | optimizer.zero_grad() 320 | 321 | output_queries, output_positives, output_negatives, output_other_neg = run_model( 322 | model, queries, positives, negatives, other_neg) 323 | 324 | loss = loss_function(output_queries, output_positives, output_negatives, 0.1, use_min=cfg.TRIPLET_USE_BEST_POSITIVES, lazy=cfg.LOSS_LAZY, ignore_zero_loss=cfg.LOSS_IGNORE_ZERO_BATCH) 325 | #loss = loss_function(output_queries, output_positives, output_negatives, rot_output_queries, rot_output_positives, rot_output_negatives, 0.1, use_min=cfg.TRIPLET_USE_BEST_POSITIVES, lazy=False, ignore_zero_loss=cfg.LOSS_IGNORE_ZERO_BATCH) 326 | loss.backward() 327 | optimizer.step() 328 | 329 | log_string('batch loss: %f' % loss) 330 | train_writer.add_scalar("Loss", loss.cpu().item(), TOTAL_ITERATIONS) 331 | TOTAL_ITERATIONS += cfg.BATCH_NUM_QUERIES 332 | 333 | def get_feature_representation(filename, model): 334 | model.eval() 335 | queries = load_image_files([filename],False) 336 | queries = np.expand_dims(queries, axis=1) 337 | 338 | with torch.no_grad(): 339 | q = torch.from_numpy(queries).float() 340 | q = q.to(device) 341 | output = model(q) 342 | output = output.detach().cpu().numpy() 343 | output = np.squeeze(output) 344 | model.train() 345 | return output 346 | 347 | 348 | def get_random_hard_negatives(query_vec, random_negs, num_to_take): 349 | global TRAINING_LATENT_VECTORS 350 | 351 | latent_vecs = [] 352 | for j in range(len(random_negs)): 353 | latent_vecs.append(TRAINING_LATENT_VECTORS[random_negs[j]]) 354 | 355 | latent_vecs = np.array(latent_vecs) 356 | nbrs = KDTree(latent_vecs) 357 | distances, indices = nbrs.query(np.array([query_vec]), k=num_to_take) 358 | hard_negs = np.squeeze(np.array(random_negs)[indices[0]]) 359 | hard_negs = hard_negs.tolist() 360 | return hard_negs 361 | 362 | 363 | def get_latent_vectors(model, dict_to_process): 364 | train_file_idxs = np.arange(0, len(dict_to_process.keys())) 365 | 366 | batch_num = cfg.BATCH_NUM_QUERIES * \ 367 | (1 + cfg.TRAIN_POSITIVES_PER_QUERY + cfg.TRAIN_NEGATIVES_PER_QUERY + 1) 368 | q_output = [] 369 | 370 | model.eval() 371 | 372 | for q_index in range(len(train_file_idxs)//batch_num): 373 | file_indices = train_file_idxs[q_index * 374 | batch_num:(q_index+1)*(batch_num)] 375 | file_names = [] 376 | for index in file_indices: 377 | file_names.append(dict_to_process[index]["query"]) 378 | queries = load_image_files(file_names,False) 379 | 380 | feed_tensor = torch.from_numpy(queries).float() 381 | feed_tensor = feed_tensor.unsqueeze(1) 382 | feed_tensor = feed_tensor.to(device) 383 | with torch.no_grad(): 384 | out = model(feed_tensor) 385 | 386 | out = out.detach().cpu().numpy() 387 | out = np.squeeze(out) 388 | 389 | q_output.append(out) 390 | 391 | q_output = np.array(q_output) 392 | if(len(q_output) != 0): 393 | q_output = q_output.reshape(-1, q_output.shape[-1]) 394 | 395 | # handle edge case 396 | for q_index in range((len(train_file_idxs) // batch_num * batch_num), len(dict_to_process.keys())): 397 | index = train_file_idxs[q_index] 398 | queries = load_image_files([dict_to_process[index]["query"]],False) 399 | queries = np.expand_dims(queries, axis=1) 400 | 401 | with torch.no_grad(): 402 | queries_tensor = torch.from_numpy(queries).float() 403 | o1 = model(queries_tensor.to(device)) 404 | 405 | output = o1.detach().cpu().numpy() 406 | output = np.squeeze(output) 407 | if (q_output.shape[0] != 0): 408 | q_output = np.vstack((q_output, output)) 409 | else: 410 | q_output = output 411 | 412 | model.train() 413 | return q_output 414 | 415 | 416 | def run_model(model, queries, positives, negatives, other_neg, require_grad=True): 417 | queries_tensor = torch.from_numpy(queries).float() 418 | positives_tensor = torch.from_numpy(positives).float() 419 | negatives_tensor = torch.from_numpy(negatives).float() 420 | other_neg_tensor = torch.from_numpy(other_neg).float() 421 | feed_tensor = torch.cat( 422 | (queries_tensor, positives_tensor, negatives_tensor, other_neg_tensor), 1) 423 | feed_tensor = feed_tensor.view((-1, 1, cfg.SIZED_GRID_X, cfg.SIZED_GRID_Y, 3)) 424 | 425 | feed_tensor.requires_grad_(require_grad) 426 | feed_tensor = feed_tensor.to(device) 427 | if require_grad: 428 | output = model(feed_tensor) 429 | else: 430 | with torch.no_grad(): 431 | output = model(feed_tensor) 432 | 433 | output = output.view(cfg.BATCH_NUM_QUERIES, -1, output.shape[-1]) 434 | o1, o2, o3, o4 = torch.split( 435 | output, [1, cfg.TRAIN_POSITIVES_PER_QUERY, cfg.TRAIN_NEGATIVES_PER_QUERY, 1], dim=1) 436 | return o1, o2, o3, o4#, ro1, ro2, ro3, ro4 437 | 438 | 439 | if __name__ == "__main__": 440 | for i in range(1): 441 | train() --------------------------------------------------------------------------------