def rotate_path(path, theta): ct = math.cos(theta) st = math.sin(theta) return [ trajnetplusplustools.TrackRow(r.frame, r.pedestrian, ct * r.x + st * r.y, -st * r.x + ct * r.y) for r in path ]
def main(args=None): ## List of .json file inside the args.path (waiting to be predicted by the testing model) datasets = sorted([f.split('.')[-2] for f in os.listdir(args.path.replace('_pred', '')) if not f.startswith('.') and f.endswith('.ndjson')]) all_goals = {} seq_length = args.obs_length + args.pred_length ## Handcrafted Baselines (if included) if args.kf: args.output.append('/kf.pkl') if args.sf: args.output.append('/sf.pkl') args.output.append('/sf_opt.pkl') if args.orca: args.output.append('/orca.pkl') args.output.append('/orca_opt.pkl') ## Extract Model names from arguments and create its own folder in 'test_pred' for storing predictions ## WARNING: If Model predictions already exist from previous run, this process SKIPS WRITING for model in args.output: model_name = model.split('/')[-1].replace('.pkl', '') model_name = model_name + '_modes' + str(args.modes) ## Check if model predictions already exist if not os.path.exists(args.path): os.makedirs(args.path) if not os.path.exists(args.path + model_name): os.makedirs(args.path + model_name) else: print('Predictions corresponding to {} already exist.'.format(model_name)) print('Loading the saved predictions') continue ## Start writing predictions in dataset/test_pred for dataset in datasets: # Model's name name = dataset.replace(args.path.replace('_pred', '') + 'test/', '') + '.ndjson' print('NAME: ', name) # Read Scenes from 'test' folder reader = trajnetplusplustools.Reader(args.path.replace('_pred', '') + dataset + '.ndjson', scene_type='paths') ## Necessary modification of train scene to add filename (for goals) scenes = [(dataset, s_id, s) for s_id, s in reader.scenes()] ## Consider goals ## Goal file must be present in 'goal_files/test_private' folder ## Goal file must have the same name as corresponding test file if args.goals: goal_dict = pickle.load(open('goal_files/test_private/' + dataset +'.pkl', "rb")) all_goals[dataset] = {s_id: [goal_dict[path[0].pedestrian] for path in s] for _, s_id, s in scenes} # Loading the APPROPRIATE model ## Keep Adding Different Model Architectures to this List print("Model Name: ", model_name) if model_name == 'kf': print("Kalman") predictor = trajnetbaselines.classical.kalman.predict elif model_name in {'sf', 'sf_opt'}: print("Social Force") predictor = trajnetbaselines.classical.socialforce.predict elif model_name in {'orca', 'orca_opt'}: print("ORCA") predictor = trajnetbaselines.classical.orca.predict elif 'sgan' in model_name: print("SGAN") predictor = trajnetbaselines.sgan.SGANPredictor.load(model) device = torch.device('cpu') predictor.model.to(device) elif 'lstm' in model_name: print("LSTM") predictor = trajnetbaselines.lstm.LSTMPredictor.load(model) device = torch.device('cpu') predictor.model.to(device) else: print("Model Architecture not recognized") raise ValueError # Get the model prediction and write them in corresponding test_pred file # VERY IMPORTANT: Prediction Format # The predictor function should output a dictionary. The keys of the dictionary should correspond to the prediction modes. # ie. predictions[0] corresponds to the first mode. predictions[m] corresponds to the m^th mode.... Multimodal predictions! # Each modal prediction comprises of primary prediction and neighbour (surrrounding) predictions i.e. predictions[m] = [primary_prediction, neigh_predictions] # Note: Return [primary_prediction, []] if model does not provide neighbour predictions # Shape of primary_prediction: Tensor of Shape (Prediction length, 2) # Shape of Neighbour_prediction: Tensor of Shape (Prediction length, n_tracks - 1, 2). # (See LSTMPredictor.py for more details) with open(args.path + '{}/{}'.format(model_name, name), "a") as myfile: for filename, scene_id, paths in scenes: ## Extract 1) first_frame, 2) frame_diff 3) ped_ids for writing predictions observed_path = paths[0] frame_diff = observed_path[1].frame - observed_path[0].frame first_frame = observed_path[args.obs_length-1].frame + frame_diff ped_id = observed_path[0].pedestrian ped_id_ = [] for j, _ in enumerate(paths[1:]): ## Only need neighbour ids ped_id_.append(paths[j+1][0].pedestrian) ## For each scene, get predictions if model_name == 'sf_opt': predictions = predictor(paths, sf_params=[0.5, 5.0, 0.3], n_predict=args.pred_length, obs_length=args.obs_length) ## optimal sf_params (no collision constraint) [0.5, 1.0, 0.1], elif model_name == 'orca_opt': predictions = predictor(paths, orca_params=[0.4, 1.0, 0.3], n_predict=args.pred_length, obs_length=args.obs_length) ## optimal orca_params (no collision constraint) [0.25, 1.0, 0.3] elif model_name in {'sf', 'orca', 'kf'}: predictions = predictor(paths, n_predict=args.pred_length, obs_length=args.obs_length, args=args) else: goals = get_goals(paths, all_goals, filename, scene_id) ## Zeros if no goals utilized predictions = predictor(paths, goals, n_predict=args.pred_length, obs_length=args.obs_length, modes=args.modes, args=args) ## Write SceneRow scenerow = trajnetplusplustools.SceneRow(scene_id, ped_id, observed_path[0].frame, observed_path[0].frame + seq_length - 1, 2.5, 0) myfile.write(trajnetplusplustools.writers.trajnet(scenerow)) myfile.write('\n') for m in range(len(predictions)): prediction, neigh_predictions = predictions[m] ## Write Primary for i in range(len(prediction)): track = trajnetplusplustools.TrackRow(first_frame + i * frame_diff, ped_id, prediction[i, 0].item(), prediction[i, 1].item(), m, scene_id) myfile.write(trajnetplusplustools.writers.trajnet(track)) myfile.write('\n') ## Write Neighbours (if non-empty) if len(neigh_predictions): for n in range(neigh_predictions.shape[1]): neigh = neigh_predictions[:, n] for j in range(len(neigh)): track = trajnetplusplustools.TrackRow(first_frame + j * frame_diff, ped_id_[n], neigh[j, 0].item(), neigh[j, 1].item(), m, scene_id) myfile.write(trajnetplusplustools.writers.trajnet(track)) myfile.write('\n') print('')
def main(): parser = argparse.ArgumentParser() parser.add_argument('--path', default='trajdata', help='directory of data to test') parser.add_argument('--output', required=True, nargs='+', help='relative path to saved model') parser.add_argument('--obs_length', default=9, type=int, help='observation length') parser.add_argument('--pred_length', default=12, type=int, help='prediction length') parser.add_argument('--disable-write', action='store_true', help='disable writing new files') parser.add_argument('--disable-collision', action='store_true', help='disable collision metrics') parser.add_argument('--labels', required=False, nargs='+', help='labels of models') parser.add_argument('--normalize_scene', action='store_true', help='augment scenes') parser.add_argument('--unimodal', action='store_true', help='provide unimodal evaluation') parser.add_argument('--topk', action='store_true', help='provide topk evaluation') parser.add_argument('--multimodal', action='store_true', help='provide multimodal nll evaluation') parser.add_argument('--modes', default=1, type=int, help='number of modes to predict') parser.add_argument('--scene_type', default=0, type=int, choices=(0, 1, 2, 3, 4), help='type of scene to evaluate') parser.add_argument('--thresh', default=0.0, type=float, help='noise thresh') parser.add_argument('--ped_type', default='primary', help='type of ped to add noise to') args = parser.parse_args() scipy.seterr('ignore') ## Path to the data folder name to predict args.path = 'DATA_BLOCK/' + args.path + '/' ## Test_pred: Folders for saving model predictions args.path = args.path + 'test_pred/' if (not args.unimodal) and (not args.topk) and (not args.multimodal): args.unimodal = True # Compute unimodal metrics by default if args.topk: args.modes = 3 if args.multimodal: args.modes = 20 enable_col1 = True ## drop pedestrians that appear post observation def drop_post_obs(ground_truth, obs_length): obs_end_frame = ground_truth[0][obs_length].frame ground_truth = [ track for track in ground_truth if track[0].frame < obs_end_frame ] return ground_truth ## Writes to Test_pred ## Does this overwrite existing predictions? No. ### datasets = sorted([ f.split('.')[-2] for f in os.listdir(args.path.replace('_pred', '')) if not f.startswith('.') and f.endswith('.ndjson') ]) ## Model names are passed as arguments for model in args.output: model_name = model.split('/')[-1].replace('.pkl', '') # Loading the appropriate model (functionality only for SGAN and LSTM) print("Model Name: ", model_name) if 'sgan' in model_name: predictor = trajnetbaselines.sgan.SGANPredictor.load(model) goal_flag = predictor.model.generator.goal_flag elif 'vae' in model_name: predictor = trajnetbaselines.vae.VAEPredictor.load(model) goal_flag = predictor.model.goal_flag else: predictor = trajnetbaselines.lstm.LSTMPredictor.load(model) goal_flag = predictor.model.goal_flag # On CPU device = torch.device('cpu') predictor.model.to(device) total_scenes = 0 average = 0 final = 0 gt_col = 0. pred_col = 0. neigh_scenes = 0 topk_average = 0 topk_final = 0 all_goals = {} average_nll = 0 ## Start writing in dataset/test_pred for dataset in datasets: # Model's name name = dataset.replace( args.path.replace('_pred', '') + 'test/', '') # Copy file from test into test/train_pred folder print('processing ' + name) if 'collision_test' in name: continue ## Filter for Scene Type reader_tag = trajnetplusplustools.Reader( args.path.replace('_pred', '_private') + dataset + '.ndjson', scene_type='tags') if args.scene_type != 0: filtered_scene_ids = [ s_id for s_id, tag, s in reader_tag.scenes() if tag[0] == args.scene_type ] else: filtered_scene_ids = [ s_id for s_id, _, _ in reader_tag.scenes() ] # Read file from 'test' reader = trajnetplusplustools.Reader( args.path.replace('_pred', '') + dataset + '.ndjson', scene_type='paths') ## Necessary modification of train scene to add filename (for goals) scenes = [(dataset, s_id, s) for s_id, s in reader.scenes() if s_id in filtered_scene_ids] ## Consider goals ## Goal file must be present in 'goal_files/test_private' folder ## Goal file must have the same name as corresponding test file if goal_flag: goal_dict = pickle.load( open('goal_files/test_private/' + dataset + '.pkl', "rb")) all_goals[dataset] = { s_id: [goal_dict[path[0].pedestrian] for path in s] for _, s_id, s in scenes } ## Get Goals if goal_flag: scene_goals = [ np.array(all_goals[filename][scene_id]) for filename, scene_id, _ in scenes ] else: scene_goals = [ np.zeros((len(paths), 2)) for _, scene_id, paths in scenes ] print("Getting Predictions") scenes = tqdm(scenes) ## Get all predictions in parallel. Faster! pred_list = Parallel(n_jobs=12)( delayed(process_scene)(predictor, model_name, paths, scene_goal, args) for (_, _, paths), scene_goal in zip(scenes, scene_goals)) ## GT Scenes reader_gt = trajnetplusplustools.Reader( args.path.replace('_pred', '_private') + dataset + '.ndjson', scene_type='paths') scenes_gt = [ s for s_id, s in reader_gt.scenes() if s_id in filtered_scene_ids ] total_scenes += len(scenes_gt) print("Evaluating Predictions") scenes = tqdm(scenes) for (predictions, (_, scene_id, paths), ground_truth) in zip(pred_list, scenes, scenes_gt): ## Extract 1) first_frame, 2) frame_diff 3) ped_ids for writing predictions observed_path = paths[0] frame_diff = observed_path[1].frame - observed_path[0].frame first_frame = observed_path[args.obs_length - 1].frame + frame_diff ped_id = observed_path[0].pedestrian ped_id_ = [] for j, _ in enumerate(paths[1:]): ## Only need neighbour ids ped_id_.append(paths[j + 1][0].pedestrian) if args.unimodal: ## Unimodal ## ADE / FDE prediction, neigh_predictions = predictions[0] prediction = np.round(prediction, 2) ## make Track Rows # primary prediction = [ trajnetplusplustools.TrackRow( first_frame + i * frame_diff, ped_id, prediction[i, 0], prediction[i, 1], 0) for i in range(len(prediction)) ] primary_tracks = [ t for t in prediction if t.prediction_number == 0 ] frame_gt = [ t.frame for t in ground_truth[0] ][args.obs_length:args.obs_length + args.pred_length] frame_pred = [t.frame for t in primary_tracks] ## To verify if same scene if frame_gt != frame_pred: raise Exception('frame numbers are not consistent') average_l2 = trajnetplusplustools.metrics.average_l2( ground_truth[0][args.obs_length:args.obs_length + args.pred_length], primary_tracks, n_predictions=args.pred_length) final_l2 = trajnetplusplustools.metrics.final_l2( ground_truth[0][args.obs_length:args.obs_length + args.pred_length], primary_tracks) # aggregate FDE and ADE average += average_l2 final += final_l2 ground_truth = drop_post_obs(ground_truth, args.obs_length) ## Collision Metrics for j in range(1, len(ground_truth)): if trajnetplusplustools.metrics.collision( primary_tracks, ground_truth[j], n_predictions=args.pred_length): gt_col += 1 break num_gt_neigh = len(ground_truth) - 1 num_predicted_neigh = neigh_predictions.shape[1] if num_gt_neigh != num_predicted_neigh: enable_col1 = False # [Col-I] only if neighs in gt = neighs in prediction if enable_col1: neigh_scenes += 1 for n in range(neigh_predictions.shape[1]): neigh = neigh_predictions[:, n] neigh = np.round(neigh, 2) neigh_track = [ trajnetplusplustools.TrackRow( first_frame + j * frame_diff, n, neigh[j, 0], neigh[j, 1], 0) for j in range(len(neigh)) ] if trajnetplusplustools.metrics.collision( primary_tracks, neigh_track, n_predictions=args.pred_length): pred_col += 1 break primary_tracks_all = [ trajnetplusplustools.TrackRow(first_frame + i * frame_diff, ped_id, x, y, m) for m, (prim, neighs) in predictions.items() for i, (x, y) in enumerate(prim) ] if args.topk: topk_ade, topk_fde = trajnetplusplustools.metrics.topk( primary_tracks_all, ground_truth[0][args.obs_length:args.obs_length + args.pred_length], n_predictions=args.pred_length) topk_average += topk_ade topk_final += topk_fde if args.multimodal: nll_val = trajnetplusplustools.metrics.nll( primary_tracks_all, ground_truth[0], n_predictions=args.pred_length, n_samples=20) average_nll += nll_val if args.unimodal: ## Average ADE and FDE average /= total_scenes final /= total_scenes gt_col /= (total_scenes * 0.01) if not enable_col1: pred_col = -1 else: pred_col /= (neigh_scenes * 0.01) print('ADE: ', np.round(average, 3)) print('FDE: ', np.round(final, 3)) print("Col-I: ", np.round(pred_col, 2)) print("Col-II: ", np.round(gt_col, 2)) if args.topk: topk_average /= total_scenes topk_final /= total_scenes print('Topk_ADE: ', topk_average) print('Topk_FDE: ', topk_final) if args.multimodal: average_nll /= total_scenes print('Average NLL: ', average_nll)
def xy_to_paths(xy_paths): return [ trajnetplusplustools.TrackRow(i, 0, xy_paths[i, 0].item(), xy_paths[i, 1].item(), 0, 0) for i in range(len(xy_paths)) ]
def aggregate(self, name, predictor, dest_type='true'): print('evaluating', name) average = 0.0 final = 0.0 # pred_dict = {} # pred_neigh_dict = {} # n = 0 for _, paths in enumerate(self.scenes): ## select only those trajectories which interactions ## # rows = trajnetplusplustools.Reader.paths_to_xy(paths) # neigh_paths = paths[1:] # interaction_index = collision_avoidance(rows) # neigh = list(compress(neigh_paths, interaction_index)) # paths = [paths[0]] + neigh if 'kf' in name: prediction, neigh = predictor( paths, n_predict=self.args.pred_length, obs_length=self.args.obs_length)[0] if 'sf' in name: prediction, neigh = predictor(paths, self.dest, dest_type, self.params['sf'], args=self.args)[0] if 'orca' in name: prediction, neigh = predictor(paths, self.dest, dest_type, self.params['orca'], args=self.args)[0] ## visualize predictions ## # pred_dict['pred'] = prediction # pred_neigh_dict['pred'] = neigh # n += 1 # if n < 17: # with show.predicted_paths(paths, pred_dict, pred_neigh_paths=pred_neigh_dict): # pass # else: # break ## Convert numpy array to Track Rows ## ## Extract 1) first_frame, 2) frame_diff 3) ped_ids for writing predictions observed_path = paths[0] frame_diff = observed_path[1].frame - observed_path[0].frame first_frame = observed_path[self.args.obs_length - 1].frame + frame_diff ped_id = observed_path[0].pedestrian ## make Track Rows prediction = [ trajnetplusplustools.TrackRow(first_frame + i * frame_diff, ped_id, prediction[i, 0], prediction[i, 1], 0) for i in range(len(prediction)) ] average_l2 = trajnetplusplustools.metrics.average_l2( paths[0], prediction) final_l2 = trajnetplusplustools.metrics.final_l2( paths[0], prediction) # aggregate average += average_l2 final += final_l2 average /= len(self.scenes) final /= len(self.scenes) self.average_l2[name] = average self.final_l2[name] = final return self
def main(): parser = argparse.ArgumentParser() parser.add_argument('--path', default='trajdata', help='directory of data to test') parser.add_argument('--output', required=True, nargs='+', help='relative path to saved model') parser.add_argument('--obs_length', default=9, type=int, help='observation length') parser.add_argument('--pred_length', default=12, type=int, help='prediction length') parser.add_argument('--disable-write', action='store_true', help='disable writing new files') parser.add_argument('--disable-collision', action='store_true', help='disable collision metrics') parser.add_argument('--labels', required=False, nargs='+', help='labels of models') parser.add_argument('--normalize_scene', action='store_true', help='augment scenes') parser.add_argument('--goals', action='store_true', help='Considers goals during prediction') parser.add_argument('--unimodal', action='store_true', help='provide unimodal evaluation') parser.add_argument('--topk', action='store_true', help='provide topk evaluation') parser.add_argument('--multimodal', action='store_true', help='provide multimodal nll evaluation') parser.add_argument('--modes', default=1, type=int, help='number of modes to predict') args = parser.parse_args() scipy.seterr('ignore') ## Path to the data folder name to predict args.path = 'DATA_BLOCK/' + args.path + '/' ## Test_pred: Folders for saving model predictions args.path = args.path + 'test_pred/' if (not args.unimodal) and (not args.topk) and (not args.multimodal): args.unimodal = True # Compute unimodal metrics by default if args.multimodal: args.modes = 20 ## Writes to Test_pred ## Does this overwrite existing predictions? No. ### datasets = sorted([ f.split('.')[-2] for f in os.listdir(args.path.replace('_pred', '')) if not f.startswith('.') and f.endswith('.ndjson') ]) ## Model names are passed as arguments for model in args.output: model_name = model.split('/')[-1].replace('.pkl', '') # Loading the appropriate model (functionality only for SGAN and LSTM) print("Model Name: ", model_name) if 'sgan' in model_name: predictor = trajnetbaselines.sgan.SGANPredictor.load(model) else: predictor = trajnetbaselines.lstm.LSTMPredictor.load(model) # On CPU device = torch.device('cpu') predictor.model.to(device) total_scenes = 0 average = 0 final = 0 gt_col = 0. pred_col = 0. neigh_scenes = 0 topk_average = 0 topk_final = 0 all_goals = {} average_nll = 0 ## Start writing in dataset/test_pred for dataset in datasets: # Model's name name = dataset.replace( args.path.replace('_pred', '') + 'test/', '') # Copy file from test into test/train_pred folder print('processing ' + name) if 'collision_test' in name: continue # Read file from 'test' reader = trajnetplusplustools.Reader( args.path.replace('_pred', '') + dataset + '.ndjson', scene_type='paths') ## Necessary modification of train scene to add filename (for goals) scenes = [(dataset, s_id, s) for s_id, s in reader.scenes()] ## Consider goals ## Goal file must be present in 'goal_files/test_private' folder ## Goal file must have the same name as corresponding test file if args.goals: goal_dict = pickle.load( open('goal_files/test_private/' + dataset + '.pkl', "rb")) all_goals[dataset] = { s_id: [goal_dict[path[0].pedestrian] for path in s] for _, s_id, s in scenes } reader_gt = trajnetplusplustools.Reader( args.path.replace('_pred', '_private') + dataset + '.ndjson', scene_type='paths') scenes_gt = [s for _, s in reader_gt.scenes()] total_scenes += len(scenes_gt) for i, (filename, scene_id, paths) in enumerate(scenes): if i % 100 == 0: print("Scenes evaluated: ", '{}/{}'.format(i, len(scenes_gt))) ground_truth = scenes_gt[i] ## Convert numpy array to Track Rows ## ## Extract 1) first_frame, 2) frame_diff 3) ped_ids for writing predictions observed_path = paths[0] frame_diff = observed_path[1].frame - observed_path[0].frame first_frame = observed_path[args.obs_length - 1].frame + frame_diff ped_id = observed_path[0].pedestrian goals = get_goals(paths, all_goals, filename, scene_id) ## Zeros if no goals utilized predictions = predictor(paths, goals, n_predict=args.pred_length, obs_length=args.obs_length, modes=args.modes, args=args) if args.unimodal: ## Unimodal ## ADE / FDE prediction, neigh_predictions = predictions[0] prediction = np.round(prediction, 2) ## make Track Rows # primary prediction = [ trajnetplusplustools.TrackRow( first_frame + i * frame_diff, ped_id, prediction[i, 0], prediction[i, 1], 0) for i in range(len(prediction)) ] primary_tracks = [ t for t in prediction if t.prediction_number == 0 ] frame_gt = [ t.frame for t in ground_truth[0] ][args.obs_length:args.obs_length + args.pred_length] frame_pred = [t.frame for t in primary_tracks] ## To verify if same scene if frame_gt != frame_pred: raise Exception('frame numbers are not consistent') average_l2 = trajnetplusplustools.metrics.average_l2( ground_truth[0][args.obs_length:args.obs_length + args.pred_length], primary_tracks, n_predictions=args.pred_length) final_l2 = trajnetplusplustools.metrics.final_l2( ground_truth[0][args.obs_length:args.obs_length + args.pred_length], primary_tracks) # aggregate FDE and ADE average += average_l2 final += final_l2 ## Collision Metrics for j in range(1, len(ground_truth)): if trajnetplusplustools.metrics.collision( primary_tracks, ground_truth[j], n_predictions=args.pred_length): gt_col += 1 break # ## neighbours (if not empty) [Col-I] if neigh_predictions.shape[1]: neigh_scenes += 1 for n in range(neigh_predictions.shape[1]): neigh = neigh_predictions[:, n] neigh = np.round(neigh, 2) neigh_track = [ trajnetplusplustools.TrackRow( first_frame + j * frame_diff, n, neigh[j, 0], neigh[j, 1], 0) for j in range(len(neigh)) ] if trajnetplusplustools.metrics.collision( primary_tracks, neigh_track, n_predictions=args.pred_length): pred_col += 1 break primary_tracks_all = [ trajnetplusplustools.TrackRow(first_frame + i * frame_diff, ped_id, x, y, m) for m, (prim, neighs) in predictions.items() for i, (x, y) in enumerate(prim) ] if args.topk: topk_ade, topk_fde = trajnetplusplustools.metrics.topk( primary_tracks_all, ground_truth[0][args.obs_length:args.obs_length + args.pred_length], n_predictions=args.pred_length) topk_average += topk_ade topk_final += topk_fde if args.multimodal: nll_val = trajnetplusplustools.metrics.nll( primary_tracks_all, ground_truth[0], n_predictions=args.pred_length, n_samples=20) average_nll += nll_val if args.unimodal: ## Average ADE and FDE average /= total_scenes final /= total_scenes gt_col /= (total_scenes * 0.01) if neigh_scenes == 0: pred_col = -1 else: pred_col /= (neigh_scenes * 0.01) print('ADE: ', average) print('FDE: ', final) print("Col-I: ", pred_col) print("Col-II: ", gt_col) if args.topk: topk_average /= total_scenes topk_final /= total_scenes print('Topk_ADE: ', topk_average) print('Topk_FDE: ', topk_final) if args.multimodal: average_nll /= total_scenes print('Average NLL: ', average_nll)