def revert_coordinate_space(channels, R0, T0): """ Bring a series of poses to a canonical form so they are facing the camera when they start. Adapted from https://github.com/asheshjain399/RNNexp/blob/7fc5a53292dc0f232867beb66c3a9ef845d705cb/structural_rnn/CRFProblems/H3.6m/dataParser/Utils/revertCoordinateSpace.m Args channels: n-by-99 matrix of poses R0: 3x3 rotation for the first frame T0: 1x3 position for the first frame Returns channels_rec: The passed poses, but the first has T0 and R0, and the rest of the sequence is modified accordingly. """ n, d = channels.shape channels_rec = copy.copy(channels) R_prev = R0 T_prev = T0 rootRotInd = np.arange(3, 6) # Loop through the passed posses for ii in range(n): R_diff = data_utils.expmap2rotmat(channels[ii, rootRotInd]) R = R_diff.dot(R_prev) channels_rec[ii, rootRotInd] = data_utils.rotmat2expmap(R) T = T_prev + ( (R_prev.T).dot(np.reshape(channels[ii, :3], [3, 1]))).reshape(-1) channels_rec[ii, :3] = T T_prev = T R_prev = R return channels_rec
def get_srnn_gts(actions, model, test_set, data_mean, data_std, dim_to_ignore, one_hot, from_exp=True, to_euler=True): """ Get the ground truths for srnn's sequences, and convert to Euler angles. (the error is always computed in Euler angles). Args actions: a list of actions to get ground truths for. model: training model we are using (we only use the "get_batch" method). test_set: dictionary with normalized training data. data_mean: d-long vector with the mean of the training data. data_std: d-long vector with the standard deviation of the training data. dim_to_ignore: dimensions that we are not using to train/predict. one_hot: whether the data comes with one-hot encoding indicating action. to_euler: whether to convert the angles to Euler format or keep thm in exponential map Returns srnn_gts_euler: a dictionary where the keys are actions, and the values are the ground_truth, denormalized expected outputs of srnns's seeds. """ srnn_gts = {} for action in actions: srnn_gt = [] _, _, srnn = model.get_batch_srnn(test_set, action, False) for i in np.arange(srnn.shape[0]): denormed = data_utils.unNormalizeData(srnn[i, :, :], data_mean, data_std, dim_to_ignore, actions, one_hot) if from_exp and to_euler: for j in np.arange(denormed.shape[0]): for k in np.arange(3, 97, 3): denormed[j, k:k + 3] = data_utils.rotmat2euler( data_utils.expmap2rotmat(denormed[j, k:k + 3])) if not from_exp and not to_euler: # from euler to exp for j in np.arange(denormed.shape[0]): for k in np.arange(3, 97, 3): denormed[j, k:k + 3] = data_utils.rotmat2expmap( data_utils.euler2rotmat(denormed[j, k:k + 3])) srnn_gt.append(denormed) # Put back in the dictionary srnn_gts[action] = srnn_gt return srnn_gts
def sample(): """Sample predictions for srnn's seeds""" if FLAGS.load <= 0: raise (ValueError, "Must give an iteration to read parameters from") actions = define_actions(FLAGS.action) # Use the CPU if asked to device_count = {"GPU": 0} if FLAGS.use_cpu else {"GPU": 1} with tf.Session(config=tf.ConfigProto(device_count=device_count)) as sess: # === Create the model === print("Creating %d layers of %d units." % (FLAGS.num_layers, FLAGS.size)) sampling = True model = create_model(sess, actions, sampling) print("Model created") # Load all the data train_set, test_set, data_mean, data_std, dim_to_ignore, dim_to_use = read_all_data( actions, FLAGS.seq_length_in, FLAGS.seq_length_out, FLAGS.data_dir, not FLAGS.omit_one_hot, FLAGS.train_on_euler) # === Read and denormalize the gt with srnn's seeds, as we'll need them many times for evaluation in Euler Angles === srnn_gts_expmap = get_srnn_gts(actions, model, test_set, data_mean, data_std, dim_to_ignore, not FLAGS.omit_one_hot, from_exp=not FLAGS.train_on_euler, to_euler=False) srnn_gts_euler = get_srnn_gts(actions, model, test_set, data_mean, data_std, dim_to_ignore, not FLAGS.omit_one_hot, from_exp=not FLAGS.train_on_euler) # Clean and create a new h5 file of samples SAMPLES_FNAME = 'samples.h5' try: os.remove(SAMPLES_FNAME) except OSError: pass # Predict and save for each action for action in actions: # Make prediction with srnn' seeds action_prefix, action_postfix_input, action_postfix_output, action_poses = model.get_batch_srnn( test_set, action, FLAGS.velocity) forward_only = True srnn_seeds = True srnn_mse_loss_fw, _, srnn_poses = model.step( sess, action_prefix[:, :, 6:], action_postfix_input[:, :, 6:], action_postfix_output[:, :, 6:], action_poses[:, :, 6:], forward_only, srnn_seeds) srnn_poses = np.concatenate((np.transpose( action_postfix_output[:, :, :6], [1, 0, 2]), srnn_poses), axis=-1) # denorm srnn_pred = data_utils.revert_output_format( srnn_poses, action_poses[:, FLAGS.seq_length_in - 1, :], data_mean, data_std, dim_to_ignore, actions, not FLAGS.omit_one_hot, FLAGS.velocity) # change to expmap if FLAGS.train_on_euler: for i in np.arange(8): for j in np.arange(srnn_pred[i].shape[0]): for k in np.arange(3, 97, 3): srnn_pred[i][j, k:k + 3] = data_utils.rotmat2expmap( data_utils.euler2rotmat( srnn_pred[i][j, k:k + 3])) # Save the samples with h5py.File(SAMPLES_FNAME, 'a') as hf: for i in np.arange(8): # Save conditioning ground truth node_name = 'expmap/gt/{1}_{0}'.format(i, action) hf.create_dataset(node_name, data=srnn_gts_expmap[action][i]) # Save prediction node_name = 'expmap/preds/{1}_{0}'.format(i, action) hf.create_dataset(node_name, data=srnn_pred[i]) # Compute and save the errors here mean_errors = np.zeros((len(srnn_pred), srnn_pred[0].shape[0])) for i in np.arange(8): eulerchannels_pred = srnn_pred[i] # change back to euler for j in np.arange(eulerchannels_pred.shape[0]): for k in np.arange(3, 97, 3): eulerchannels_pred[j, k:k + 3] = data_utils.rotmat2euler( data_utils.expmap2rotmat( eulerchannels_pred[j, k:k + 3])) eulerchannels_pred[:, 0:6] = 0 # Pick only the dimensions with sufficient standard deviation. Others are ignored. idx_to_use = np.where(np.std(eulerchannels_pred, 0) > 1e-4)[0] euc_error = np.power( srnn_gts_euler[action][i][:, idx_to_use] - eulerchannels_pred[:, idx_to_use], 2) euc_error = np.sum(euc_error, 1) euc_error = np.sqrt(euc_error) mean_errors[i, :] = euc_error mean_mean_errors = np.mean(mean_errors, 0) print("{0: <16} |".format(action), end="") for ms in [1, 3, 7, 9, 13, 24]: if FLAGS.seq_length_out >= ms + 1: print(" {0:.3f} |".format(mean_mean_errors[ms]), end="") else: print(" n/a |", end="") print() with h5py.File(SAMPLES_FNAME, 'a') as hf: node_name = 'mean_{0}_error'.format(action) hf.create_dataset(node_name, data=mean_mean_errors) return