diff --git a/.ipynb_checkpoints/README-checkpoint.md b/.ipynb_checkpoints/README-checkpoint.md
new file mode 100644
index 0000000000000000000000000000000000000000..290eb050c2de0c8a7305fe604ca61d5cda6a61a9
--- /dev/null
+++ b/.ipynb_checkpoints/README-checkpoint.md
@@ -0,0 +1,13 @@
+---
+title: EMAGE
+emoji: ⚡
+colorFrom: yellow
+colorTo: green
+sdk: gradio
+sdk_version: 4.24.0
+app_file: app.py
+pinned: false
+license: apache-2.0
+---
+
+Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
diff --git a/.ipynb_checkpoints/app-checkpoint.py b/.ipynb_checkpoints/app-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..11a141959a6f3b4638139e16772a0fa4431e69e4
--- /dev/null
+++ b/.ipynb_checkpoints/app-checkpoint.py
@@ -0,0 +1,664 @@
+import spaces
+import os
+# os.system("Xvfb :99 -ac &")
+# os.environ["DISPLAY"] = ":99"
+import OpenGL.GL as gl
+os.environ["PYOPENGL_PLATFORM"] = "egl"
+os.environ["MESA_GL_VERSION_OVERRIDE"] = "4.1"
+import signal
+import time
+import csv
+import sys
+import warnings
+import random
+import gradio as gr
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+import torch.distributed as dist
+from torch.nn.parallel import DistributedDataParallel as DDP
+import torch.multiprocessing as mp
+import numpy as np
+import time
+import pprint
+from loguru import logger
+import smplx
+from torch.utils.tensorboard import SummaryWriter
+import wandb
+import matplotlib.pyplot as plt
+from utils import config, logger_tools, other_tools_hf, metric, data_transfer
+from dataloaders import data_tools
+from dataloaders.build_vocab import Vocab
+from optimizers.optim_factory import create_optimizer
+from optimizers.scheduler_factory import create_scheduler
+from optimizers.loss_factory import get_loss_func
+from dataloaders.data_tools import joints_list
+from utils import rotation_conversions as rc
+import soundfile as sf
+import librosa
+
+def inverse_selection_tensor(filtered_t, selection_array, n):
+ selection_array = torch.from_numpy(selection_array).cuda()
+ original_shape_t = torch.zeros((n, 165)).cuda()
+ selected_indices = torch.where(selection_array == 1)[0]
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+ return original_shape_t
+
+@spaces.GPU(duration=120)
+def test_demo_gpu(
+ model, vq_model_face, vq_model_upper, vq_model_hands, vq_model_lower, global_motion, smplx_model,
+ dict_data,
+ args,
+ joints, joint_mask_upper, joint_mask_lower, joint_mask_hands,
+ log_softmax,
+):
+ rank = 0
+ other_tools_hf.load_checkpoints(vq_model_face, args.data_path_1 + "pretrained_vq/last_790_face_v2.bin", args.e_name)
+ other_tools_hf.load_checkpoints(vq_model_upper, args.data_path_1 + "pretrained_vq/upper_vertex_1layer_710.bin", args.e_name)
+ other_tools_hf.load_checkpoints(vq_model_hands, args.data_path_1 + "pretrained_vq/hands_vertex_1layer_710.bin", args.e_name)
+ other_tools_hf.load_checkpoints(vq_model_lower, args.data_path_1 + "pretrained_vq/lower_foot_600.bin", args.e_name)
+ other_tools_hf.load_checkpoints(global_motion, args.data_path_1 + "pretrained_vq/last_1700_foot.bin", args.e_name)
+ other_tools_hf.load_checkpoints(model, args.test_ckpt, args.g_name)
+ model.to(rank).eval()
+ smplx_model.to(rank).eval()
+ vq_model_face.to(rank).eval()
+ vq_model_upper.to(rank).eval()
+ vq_model_hands.to(rank).eval()
+ vq_model_lower.to(rank).eval()
+ global_motion.to(rank).eval()
+
+ with torch.no_grad():
+ tar_pose_raw = dict_data["pose"]
+ tar_pose = tar_pose_raw[:, :, :165].to(rank)
+ tar_contact = tar_pose_raw[:, :, 165:169].to(rank)
+ tar_trans = dict_data["trans"].to(rank)
+ tar_exps = dict_data["facial"].to(rank)
+ in_audio = dict_data["audio"].to(rank)
+ in_word = None# dict_data["word"].to(rank)
+ tar_beta = dict_data["beta"].to(rank)
+ tar_id = dict_data["id"].to(rank).long()
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], joints
+
+ tar_pose_jaw = tar_pose[:, :, 66:69]
+ tar_pose_jaw = rc.axis_angle_to_matrix(tar_pose_jaw.reshape(bs, n, 1, 3))
+ tar_pose_jaw = rc.matrix_to_rotation_6d(tar_pose_jaw).reshape(bs, n, 1*6)
+ tar_pose_face = torch.cat([tar_pose_jaw, tar_exps], dim=2)
+
+ tar_pose_hands = tar_pose[:, :, 25*3:55*3]
+ tar_pose_hands = rc.axis_angle_to_matrix(tar_pose_hands.reshape(bs, n, 30, 3))
+ tar_pose_hands = rc.matrix_to_rotation_6d(tar_pose_hands).reshape(bs, n, 30*6)
+
+ tar_pose_upper = tar_pose[:, :, joint_mask_upper.astype(bool)]
+ tar_pose_upper = rc.axis_angle_to_matrix(tar_pose_upper.reshape(bs, n, 13, 3))
+ tar_pose_upper = rc.matrix_to_rotation_6d(tar_pose_upper).reshape(bs, n, 13*6)
+
+ tar_pose_leg = tar_pose[:, :, joint_mask_lower.astype(bool)]
+ tar_pose_leg = rc.axis_angle_to_matrix(tar_pose_leg.reshape(bs, n, 9, 3))
+ tar_pose_leg = rc.matrix_to_rotation_6d(tar_pose_leg).reshape(bs, n, 9*6)
+ tar_pose_lower = torch.cat([tar_pose_leg, tar_trans, tar_contact], dim=2)
+
+ # tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ # tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ tar4dis = torch.cat([tar_pose_jaw, tar_pose_upper, tar_pose_hands, tar_pose_leg], dim=2)
+
+ tar_index_value_face_top = vq_model_face.map2index(tar_pose_face) # bs*n/4
+ tar_index_value_upper_top = vq_model_upper.map2index(tar_pose_upper) # bs*n/4
+ tar_index_value_hands_top = vq_model_hands.map2index(tar_pose_hands) # bs*n/4
+ tar_index_value_lower_top = vq_model_lower.map2index(tar_pose_lower) # bs*n/4
+
+ latent_face_top = vq_model_face.map2latent(tar_pose_face) # bs*n/4
+ latent_upper_top = vq_model_upper.map2latent(tar_pose_upper) # bs*n/4
+ latent_hands_top = vq_model_hands.map2latent(tar_pose_hands) # bs*n/4
+ latent_lower_top = vq_model_lower.map2latent(tar_pose_lower) # bs*n/4
+
+ latent_in = torch.cat([latent_upper_top, latent_hands_top, latent_lower_top], dim=2)
+
+ index_in = torch.stack([tar_index_value_upper_top, tar_index_value_hands_top, tar_index_value_lower_top], dim=-1).long()
+
+ tar_pose_6d = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, 55, 3))
+ tar_pose_6d = rc.matrix_to_rotation_6d(tar_pose_6d).reshape(bs, n, 55*6)
+ latent_all = torch.cat([tar_pose_6d, tar_trans, tar_contact], dim=-1)
+
+ loaded_data = {
+ "tar_pose_jaw": tar_pose_jaw,
+ "tar_pose_face": tar_pose_face,
+ "tar_pose_upper": tar_pose_upper,
+ "tar_pose_lower": tar_pose_lower,
+ "tar_pose_hands": tar_pose_hands,
+ 'tar_pose_leg': tar_pose_leg,
+ "in_audio": in_audio,
+ "in_word": in_word,
+ "tar_trans": tar_trans,
+ "tar_exps": tar_exps,
+ "tar_beta": tar_beta,
+ "tar_pose": tar_pose,
+ "tar4dis": tar4dis,
+ "tar_index_value_face_top": tar_index_value_face_top,
+ "tar_index_value_upper_top": tar_index_value_upper_top,
+ "tar_index_value_hands_top": tar_index_value_hands_top,
+ "tar_index_value_lower_top": tar_index_value_lower_top,
+ "latent_face_top": latent_face_top,
+ "latent_upper_top": latent_upper_top,
+ "latent_hands_top": latent_hands_top,
+ "latent_lower_top": latent_lower_top,
+ "latent_in": latent_in,
+ "index_in": index_in,
+ "tar_id": tar_id,
+ "latent_all": latent_all,
+ "tar_pose_6d": tar_pose_6d,
+ "tar_contact": tar_contact,
+ }
+
+ mode = 'test'
+ bs, n, j = loaded_data["tar_pose"].shape[0], loaded_data["tar_pose"].shape[1], joints
+ tar_pose = loaded_data["tar_pose"]
+ tar_beta = loaded_data["tar_beta"]
+ in_word =None# loaded_data["in_word"]
+ tar_exps = loaded_data["tar_exps"]
+ tar_contact = loaded_data["tar_contact"]
+ in_audio = loaded_data["in_audio"]
+ tar_trans = loaded_data["tar_trans"]
+
+ remain = n%8
+ if remain != 0:
+ tar_pose = tar_pose[:, :-remain, :]
+ tar_beta = tar_beta[:, :-remain, :]
+ tar_trans = tar_trans[:, :-remain, :]
+ # in_word = in_word[:, :-remain]
+ tar_exps = tar_exps[:, :-remain, :]
+ tar_contact = tar_contact[:, :-remain, :]
+ n = n - remain
+
+ tar_pose_jaw = tar_pose[:, :, 66:69]
+ tar_pose_jaw = rc.axis_angle_to_matrix(tar_pose_jaw.reshape(bs, n, 1, 3))
+ tar_pose_jaw = rc.matrix_to_rotation_6d(tar_pose_jaw).reshape(bs, n, 1*6)
+ tar_pose_face = torch.cat([tar_pose_jaw, tar_exps], dim=2)
+
+ tar_pose_hands = tar_pose[:, :, 25*3:55*3]
+ tar_pose_hands = rc.axis_angle_to_matrix(tar_pose_hands.reshape(bs, n, 30, 3))
+ tar_pose_hands = rc.matrix_to_rotation_6d(tar_pose_hands).reshape(bs, n, 30*6)
+
+ tar_pose_upper = tar_pose[:, :, joint_mask_upper.astype(bool)]
+ tar_pose_upper = rc.axis_angle_to_matrix(tar_pose_upper.reshape(bs, n, 13, 3))
+ tar_pose_upper = rc.matrix_to_rotation_6d(tar_pose_upper).reshape(bs, n, 13*6)
+
+ tar_pose_leg = tar_pose[:, :, joint_mask_lower.astype(bool)]
+ tar_pose_leg = rc.axis_angle_to_matrix(tar_pose_leg.reshape(bs, n, 9, 3))
+ tar_pose_leg = rc.matrix_to_rotation_6d(tar_pose_leg).reshape(bs, n, 9*6)
+ tar_pose_lower = torch.cat([tar_pose_leg, tar_trans, tar_contact], dim=2)
+
+ tar_pose_6d = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, 55, 3))
+ tar_pose_6d = rc.matrix_to_rotation_6d(tar_pose_6d).reshape(bs, n, 55*6)
+ latent_all = torch.cat([tar_pose_6d, tar_trans, tar_contact], dim=-1)
+
+ rec_index_all_face = []
+ rec_index_all_upper = []
+ rec_index_all_lower = []
+ rec_index_all_hands = []
+
+ roundt = (n - args.pre_frames) // (args.pose_length - args.pre_frames)
+ remain = (n - args.pre_frames) % (args.pose_length - args.pre_frames)
+ round_l = args.pose_length - args.pre_frames
+
+ for i in range(0, roundt):
+ # in_word_tmp = in_word[:, i*(round_l):(i+1)*(round_l)+args.pre_frames]
+ # audio fps is 16000 and pose fps is 30
+ in_audio_tmp = in_audio[:, i*(16000//30*round_l):(i+1)*(16000//30*round_l)+16000//30*args.pre_frames]
+ in_id_tmp = loaded_data['tar_id'][:, i*(round_l):(i+1)*(round_l)+args.pre_frames]
+ mask_val = torch.ones(bs, args.pose_length, args.pose_dims+3+4).float().cuda()
+ mask_val[:, :args.pre_frames, :] = 0.0
+ if i == 0:
+ latent_all_tmp = latent_all[:, i*(round_l):(i+1)*(round_l)+args.pre_frames, :]
+ else:
+ latent_all_tmp = latent_all[:, i*(round_l):(i+1)*(round_l)+args.pre_frames, :]
+ # print(latent_all_tmp.shape, latent_last.shape)
+ latent_all_tmp[:, :args.pre_frames, :] = latent_last[:, -args.pre_frames:, :]
+
+ net_out_val = model(
+ in_audio = in_audio_tmp,
+ in_word=None, #in_word_tmp,
+ mask=mask_val,
+ in_motion = latent_all_tmp,
+ in_id = in_id_tmp,
+ use_attentions=True,)
+
+ if args.cu != 0:
+ rec_index_upper = log_softmax(net_out_val["cls_upper"]).reshape(-1, args.vae_codebook_size)
+ _, rec_index_upper = torch.max(rec_index_upper.reshape(-1, args.pose_length, args.vae_codebook_size), dim=2)
+ #rec_upper = vq_model_upper.decode(rec_index_upper)
+ else:
+ _, rec_index_upper, _, _ = vq_model_upper.quantizer(net_out_val["rec_upper"])
+ #rec_upper = vq_model_upper.decoder(rec_index_upper)
+ if args.cl != 0:
+ rec_index_lower = log_softmax(net_out_val["cls_lower"]).reshape(-1, args.vae_codebook_size)
+ _, rec_index_lower = torch.max(rec_index_lower.reshape(-1, args.pose_length, args.vae_codebook_size), dim=2)
+ #rec_lower = vq_model_lower.decode(rec_index_lower)
+ else:
+ _, rec_index_lower, _, _ = vq_model_lower.quantizer(net_out_val["rec_lower"])
+ #rec_lower = vq_model_lower.decoder(rec_index_lower)
+ if args.ch != 0:
+ rec_index_hands = log_softmax(net_out_val["cls_hands"]).reshape(-1, args.vae_codebook_size)
+ _, rec_index_hands = torch.max(rec_index_hands.reshape(-1, args.pose_length, args.vae_codebook_size), dim=2)
+ #rec_hands = vq_model_hands.decode(rec_index_hands)
+ else:
+ _, rec_index_hands, _, _ = vq_model_hands.quantizer(net_out_val["rec_hands"])
+ #rec_hands = vq_model_hands.decoder(rec_index_hands)
+ if args.cf != 0:
+ rec_index_face = log_softmax(net_out_val["cls_face"]).reshape(-1, args.vae_codebook_size)
+ _, rec_index_face = torch.max(rec_index_face.reshape(-1, args.pose_length, args.vae_codebook_size), dim=2)
+ #rec_face = vq_model_face.decoder(rec_index_face)
+ else:
+ _, rec_index_face, _, _ = vq_model_face.quantizer(net_out_val["rec_face"])
+ #rec_face = vq_model_face.decoder(rec_index_face)
+
+ if i == 0:
+ rec_index_all_face.append(rec_index_face)
+ rec_index_all_upper.append(rec_index_upper)
+ rec_index_all_lower.append(rec_index_lower)
+ rec_index_all_hands.append(rec_index_hands)
+ else:
+ rec_index_all_face.append(rec_index_face[:, args.pre_frames:])
+ rec_index_all_upper.append(rec_index_upper[:, args.pre_frames:])
+ rec_index_all_lower.append(rec_index_lower[:, args.pre_frames:])
+ rec_index_all_hands.append(rec_index_hands[:, args.pre_frames:])
+
+ if args.cu != 0:
+ rec_upper_last = vq_model_upper.decode(rec_index_upper)
+ else:
+ rec_upper_last = vq_model_upper.decoder(rec_index_upper)
+ if args.cl != 0:
+ rec_lower_last = vq_model_lower.decode(rec_index_lower)
+ else:
+ rec_lower_last = vq_model_lower.decoder(rec_index_lower)
+ if args.ch != 0:
+ rec_hands_last = vq_model_hands.decode(rec_index_hands)
+ else:
+ rec_hands_last = vq_model_hands.decoder(rec_index_hands)
+ # if args.cf != 0:
+ # rec_face_last = vq_model_face.decode(rec_index_face)
+ # else:
+ # rec_face_last = vq_model_face.decoder(rec_index_face)
+
+ rec_pose_legs = rec_lower_last[:, :, :54]
+ bs, n = rec_pose_legs.shape[0], rec_pose_legs.shape[1]
+ rec_pose_upper = rec_upper_last.reshape(bs, n, 13, 6)
+ rec_pose_upper = rc.rotation_6d_to_matrix(rec_pose_upper)#
+ rec_pose_upper = rc.matrix_to_axis_angle(rec_pose_upper).reshape(bs*n, 13*3)
+ rec_pose_upper_recover = inverse_selection_tensor(rec_pose_upper, joint_mask_upper, bs*n)
+ rec_pose_lower = rec_pose_legs.reshape(bs, n, 9, 6)
+ rec_pose_lower = rc.rotation_6d_to_matrix(rec_pose_lower)
+ rec_pose_lower = rc.matrix_to_axis_angle(rec_pose_lower).reshape(bs*n, 9*3)
+ rec_pose_lower_recover = inverse_selection_tensor(rec_pose_lower, joint_mask_lower, bs*n)
+ rec_pose_hands = rec_hands_last.reshape(bs, n, 30, 6)
+ rec_pose_hands = rc.rotation_6d_to_matrix(rec_pose_hands)
+ rec_pose_hands = rc.matrix_to_axis_angle(rec_pose_hands).reshape(bs*n, 30*3)
+ rec_pose_hands_recover = inverse_selection_tensor(rec_pose_hands, joint_mask_hands, bs*n)
+ rec_pose = rec_pose_upper_recover + rec_pose_lower_recover + rec_pose_hands_recover
+ rec_pose = rc.axis_angle_to_matrix(rec_pose.reshape(bs, n, j, 3))
+ rec_pose = rc.matrix_to_rotation_6d(rec_pose).reshape(bs, n, j*6)
+ rec_trans_v_s = rec_lower_last[:, :, 54:57]
+ rec_x_trans = other_tools_hf.velocity2position(rec_trans_v_s[:, :, 0:1], 1/args.pose_fps, tar_trans[:, 0, 0:1])
+ rec_z_trans = other_tools_hf.velocity2position(rec_trans_v_s[:, :, 2:3], 1/args.pose_fps, tar_trans[:, 0, 2:3])
+ rec_y_trans = rec_trans_v_s[:,:,1:2]
+ rec_trans = torch.cat([rec_x_trans, rec_y_trans, rec_z_trans], dim=-1)
+ latent_last = torch.cat([rec_pose, rec_trans, rec_lower_last[:, :, 57:61]], dim=-1)
+
+ rec_index_face = torch.cat(rec_index_all_face, dim=1)
+ rec_index_upper = torch.cat(rec_index_all_upper, dim=1)
+ rec_index_lower = torch.cat(rec_index_all_lower, dim=1)
+ rec_index_hands = torch.cat(rec_index_all_hands, dim=1)
+ if args.cu != 0:
+ rec_upper = vq_model_upper.decode(rec_index_upper)
+ else:
+ rec_upper = vq_model_upper.decoder(rec_index_upper)
+ if args.cl != 0:
+ rec_lower = vq_model_lower.decode(rec_index_lower)
+ else:
+ rec_lower = vq_model_lower.decoder(rec_index_lower)
+ if args.ch != 0:
+ rec_hands = vq_model_hands.decode(rec_index_hands)
+ else:
+ rec_hands = vq_model_hands.decoder(rec_index_hands)
+ if args.cf != 0:
+ rec_face = vq_model_face.decode(rec_index_face)
+ else:
+ rec_face = vq_model_face.decoder(rec_index_face)
+
+ rec_exps = rec_face[:, :, 6:]
+ rec_pose_jaw = rec_face[:, :, :6]
+ rec_pose_legs = rec_lower[:, :, :54]
+ bs, n = rec_pose_jaw.shape[0], rec_pose_jaw.shape[1]
+ rec_pose_upper = rec_upper.reshape(bs, n, 13, 6)
+ rec_pose_upper = rc.rotation_6d_to_matrix(rec_pose_upper)#
+ rec_pose_upper = rc.matrix_to_axis_angle(rec_pose_upper).reshape(bs*n, 13*3)
+ rec_pose_upper_recover = inverse_selection_tensor(rec_pose_upper, joint_mask_upper, bs*n)
+ rec_pose_lower = rec_pose_legs.reshape(bs, n, 9, 6)
+ rec_pose_lower = rc.rotation_6d_to_matrix(rec_pose_lower)
+ rec_lower2global = rc.matrix_to_rotation_6d(rec_pose_lower.clone()).reshape(bs, n, 9*6)
+ rec_pose_lower = rc.matrix_to_axis_angle(rec_pose_lower).reshape(bs*n, 9*3)
+ rec_pose_lower_recover = inverse_selection_tensor(rec_pose_lower, joint_mask_lower, bs*n)
+ rec_pose_hands = rec_hands.reshape(bs, n, 30, 6)
+ rec_pose_hands = rc.rotation_6d_to_matrix(rec_pose_hands)
+ rec_pose_hands = rc.matrix_to_axis_angle(rec_pose_hands).reshape(bs*n, 30*3)
+ rec_pose_hands_recover = inverse_selection_tensor(rec_pose_hands, joint_mask_hands, bs*n)
+ rec_pose_jaw = rec_pose_jaw.reshape(bs*n, 6)
+ rec_pose_jaw = rc.rotation_6d_to_matrix(rec_pose_jaw)
+ rec_pose_jaw = rc.matrix_to_axis_angle(rec_pose_jaw).reshape(bs*n, 1*3)
+ rec_pose = rec_pose_upper_recover + rec_pose_lower_recover + rec_pose_hands_recover
+ rec_pose[:, 66:69] = rec_pose_jaw
+
+ to_global = rec_lower
+ to_global[:, :, 54:57] = 0.0
+ to_global[:, :, :54] = rec_lower2global
+ rec_global = global_motion(to_global)
+
+ rec_trans_v_s = rec_global["rec_pose"][:, :, 54:57]
+ rec_x_trans = other_tools_hf.velocity2position(rec_trans_v_s[:, :, 0:1], 1/args.pose_fps, tar_trans[:, 0, 0:1])
+ rec_z_trans = other_tools_hf.velocity2position(rec_trans_v_s[:, :, 2:3], 1/args.pose_fps, tar_trans[:, 0, 2:3])
+ rec_y_trans = rec_trans_v_s[:,:,1:2]
+ rec_trans = torch.cat([rec_x_trans, rec_y_trans, rec_z_trans], dim=-1)
+ tar_pose = tar_pose[:, :n, :]
+ tar_exps = tar_exps[:, :n, :]
+ tar_trans = tar_trans[:, :n, :]
+ tar_beta = tar_beta[:, :n, :]
+
+ rec_pose = rc.axis_angle_to_matrix(rec_pose.reshape(bs*n, j, 3))
+ rec_pose = rc.matrix_to_rotation_6d(rec_pose).reshape(bs, n, j*6)
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs*n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+
+ net_out = {
+ 'rec_pose': rec_pose,
+ 'rec_trans': rec_trans,
+ 'tar_pose': tar_pose,
+ 'tar_exps': tar_exps,
+ 'tar_beta': tar_beta,
+ 'tar_trans': tar_trans,
+ 'rec_exps': rec_exps,
+ }
+
+
+ tar_pose = net_out['tar_pose']
+ rec_pose = net_out['rec_pose']
+ tar_exps = net_out['tar_exps']
+ tar_beta = net_out['tar_beta']
+ rec_trans = net_out['rec_trans']
+ tar_trans = net_out['tar_trans']
+ rec_exps = net_out['rec_exps']
+ # print(rec_pose.shape, tar_pose.shape)
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], joints
+ # interpolate to 30fps
+ if (30/args.pose_fps) != 1:
+ assert 30%args.pose_fps == 0
+ n *= int(30/args.pose_fps)
+ tar_pose = torch.nn.functional.interpolate(tar_pose.permute(0, 2, 1), scale_factor=30/args.pose_fps, mode='linear').permute(0,2,1)
+ rec_pose = torch.nn.functional.interpolate(rec_pose.permute(0, 2, 1), scale_factor=30/args.pose_fps, mode='linear').permute(0,2,1)
+
+ # print(rec_pose.shape, tar_pose.shape)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose.reshape(bs*n, j, 6))
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs*n, j, 6))
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+
+ return tar_pose, rec_pose, tar_exps, tar_beta, rec_trans, tar_trans, rec_exps, bs, n, j
+
+
+class BaseTrainer(object):
+ def __init__(self, args, sp, ap, tp):
+ hf_dir = "hf"
+ if not os.path.exists(args.out_path + "custom/" + hf_dir + "/"):
+ os.makedirs(args.out_path + "custom/" + hf_dir + "/")
+ sf.write(args.out_path + "custom/" + hf_dir + "/tmp.wav", ap[1][:ap[0]*8], ap[0])
+ self.audio_path = args.out_path + "custom/" + hf_dir + "/tmp.wav"
+ audio, ssr = librosa.load(self.audio_path)
+ ap = (ssr, audio)
+ self.args = args
+ self.rank = 0 # dist.get_rank()
+
+ #self.checkpoint_path = args.out_path + "custom/" + args.name + args.notes + "/" #wandb.run.dir #args.cache_path+args.out_path+"/"+args.name
+ self.checkpoint_path = args.out_path + "custom/" + hf_dir + "/"
+ if self.rank == 0:
+ self.test_data = __import__(f"dataloaders.{args.dataset}", fromlist=["something"]).CustomDataset(args, "test", smplx_path=sp, audio_path=ap, text_path=tp)
+ self.test_loader = torch.utils.data.DataLoader(
+ self.test_data,
+ batch_size=1,
+ shuffle=False,
+ num_workers=args.loader_workers,
+ drop_last=False,
+ )
+ logger.info(f"Init test dataloader success")
+ model_module = __import__(f"models.{args.model}", fromlist=["something"])
+
+ if args.ddp:
+ self.model = getattr(model_module, args.g_name)(args).to(self.rank)
+ process_group = torch.distributed.new_group()
+ self.model = torch.nn.SyncBatchNorm.convert_sync_batchnorm(self.model, process_group)
+ self.model = DDP(self.model, device_ids=[self.rank], output_device=self.rank,
+ broadcast_buffers=False, find_unused_parameters=False)
+ else:
+ self.model = torch.nn.DataParallel(getattr(model_module, args.g_name)(args), args.gpus).cpu()
+
+ if self.rank == 0:
+ logger.info(self.model)
+ logger.info(f"init {args.g_name} success")
+
+ self.smplx = smplx.create(
+ self.args.data_path_1+"smplx_models/",
+ model_type='smplx',
+ gender='NEUTRAL_2020',
+ use_face_contour=False,
+ num_betas=300,
+ num_expression_coeffs=100,
+ ext='npz',
+ use_pca=False,
+ )
+
+ self.args = args
+ self.joints = self.test_data.joints
+ self.ori_joint_list = joints_list[self.args.ori_joints]
+ self.tar_joint_list_face = joints_list["beat_smplx_face"]
+ self.tar_joint_list_upper = joints_list["beat_smplx_upper"]
+ self.tar_joint_list_hands = joints_list["beat_smplx_hands"]
+ self.tar_joint_list_lower = joints_list["beat_smplx_lower"]
+
+ self.joint_mask_face = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ self.joints = 55
+ for joint_name in self.tar_joint_list_face:
+ self.joint_mask_face[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ self.joint_mask_upper = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ for joint_name in self.tar_joint_list_upper:
+ self.joint_mask_upper[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ self.joint_mask_hands = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ for joint_name in self.tar_joint_list_hands:
+ self.joint_mask_hands[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ self.joint_mask_lower = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ for joint_name in self.tar_joint_list_lower:
+ self.joint_mask_lower[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+
+ self.tracker = other_tools_hf.EpochTracker(["fid", "l1div", "bc", "rec", "trans", "vel", "transv", 'dis', 'gen', 'acc', 'transa', 'exp', 'lvd', 'mse', "cls", "rec_face", "latent", "cls_full", "cls_self", "cls_word", "latent_word","latent_self"], [False,True,True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,False,False,False])
+
+ vq_model_module = __import__(f"models.motion_representation", fromlist=["something"])
+ self.args.vae_layer = 2
+ self.args.vae_length = 256
+ self.args.vae_test_dim = 106
+ self.vq_model_face = getattr(vq_model_module, "VQVAEConvZero")(self.args).cpu()
+ # print(self.vq_model_face)
+ # other_tools_hf.load_checkpoints(self.vq_model_face, self.args.data_path_1 + "pretrained_vq/last_790_face_v2.bin", args.e_name)
+ self.args.vae_test_dim = 78
+ self.vq_model_upper = getattr(vq_model_module, "VQVAEConvZero")(self.args).cpu()
+ # other_tools_hf.load_checkpoints(self.vq_model_upper, self.args.data_path_1 + "pretrained_vq/upper_vertex_1layer_710.bin", args.e_name)
+ self.args.vae_test_dim = 180
+ self.vq_model_hands = getattr(vq_model_module, "VQVAEConvZero")(self.args).cpu()
+ # other_tools_hf.load_checkpoints(self.vq_model_hands, self.args.data_path_1 + "pretrained_vq/hands_vertex_1layer_710.bin", args.e_name)
+ self.args.vae_test_dim = 61
+ self.args.vae_layer = 4
+ self.vq_model_lower = getattr(vq_model_module, "VQVAEConvZero")(self.args).cpu()
+ # other_tools_hf.load_checkpoints(self.vq_model_lower, self.args.data_path_1 + "pretrained_vq/lower_foot_600.bin", args.e_name)
+ self.args.vae_test_dim = 61
+ self.args.vae_layer = 4
+ self.global_motion = getattr(vq_model_module, "VAEConvZero")(self.args).cpu()
+ # other_tools_hf.load_checkpoints(self.global_motion, self.args.data_path_1 + "pretrained_vq/last_1700_foot.bin", args.e_name)
+ self.args.vae_test_dim = 330
+ self.args.vae_layer = 4
+ self.args.vae_length = 240
+
+ # self.cls_loss = nn.NLLLoss().to(self.rank)
+ # self.reclatent_loss = nn.MSELoss().to(self.rank)
+ # self.vel_loss = torch.nn.L1Loss(reduction='mean').to(self.rank)
+ # self.rec_loss = get_loss_func("GeodesicLoss").to(self.rank)
+ self.log_softmax = nn.LogSoftmax(dim=2)
+
+
+ def inverse_selection(self, filtered_t, selection_array, n):
+ original_shape_t = np.zeros((n, selection_array.size))
+ selected_indices = np.where(selection_array == 1)[0]
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+ return original_shape_t
+
+ def inverse_selection_tensor(self, filtered_t, selection_array, n):
+ selection_array = torch.from_numpy(selection_array).cuda()
+ original_shape_t = torch.zeros((n, 165)).cuda()
+ selected_indices = torch.where(selection_array == 1)[0]
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+ return original_shape_t
+
+
+ def test_demo(self, epoch):
+ '''
+ input audio and text, output motion
+ do not calculate loss and metric
+ save video
+ '''
+ results_save_path = self.checkpoint_path + f"/{epoch}/"
+ if os.path.exists(results_save_path):
+ import shutil
+ shutil.rmtree(results_save_path)
+ os.makedirs(results_save_path)
+ start_time = time.time()
+ total_length = 0
+ test_seq_list = self.test_data.selected_file
+ align = 0
+ latent_out = []
+ latent_ori = []
+ l2_all = 0
+ lvel = 0
+ for its, batch_data in enumerate(self.test_loader):
+ tar_pose, rec_pose, tar_exps, tar_beta, rec_trans, tar_trans, rec_exps, bs, n, j = test_demo_gpu(
+ self.model, self.vq_model_face, self.vq_model_upper, self.vq_model_hands, self.vq_model_lower, self.global_motion, self.smplx,
+ batch_data,
+ self.args,
+ self.joints, self.joint_mask_upper, self.joint_mask_lower, self.joint_mask_hands,
+ self.log_softmax,
+ )
+
+ tar_pose_np = tar_pose.detach().cpu().numpy()
+ rec_pose_np = rec_pose.detach().cpu().numpy()
+ rec_trans_np = rec_trans.detach().cpu().numpy().reshape(bs*n, 3)
+ rec_exp_np = rec_exps.detach().cpu().numpy().reshape(bs*n, 100)
+ tar_exp_np = tar_exps.detach().cpu().numpy().reshape(bs*n, 100)
+ tar_trans_np = tar_trans.detach().cpu().numpy().reshape(bs*n, 3)
+ #'''
+ # its = 0
+ gt_npz = np.load(self.args.data_path+self.args.pose_rep +"/"+test_seq_list.iloc[its]['id']+".npz", allow_pickle=True)
+ np.savez(results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=tar_pose_np,
+ expressions=tar_exp_np,
+ trans=tar_trans_np,
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30,
+ )
+ np.savez(results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=rec_pose_np,
+ expressions=rec_exp_np,
+ trans=rec_trans_np,
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30,
+ )
+
+ total_length += n
+ render_vid_path = other_tools_hf.render_one_sequence_no_gt(
+ results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.npz',
+ # results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.npz',
+ results_save_path,
+ self.audio_path,
+ self.args.data_path_1+"smplx_models/",
+ use_matplotlib = False,
+ args = self.args,
+ )
+ result = gr.Video(value=render_vid_path, visible=True)
+ end_time = time.time() - start_time
+ logger.info(f"total inference time: {int(end_time)} s for {int(total_length/self.args.pose_fps)} s motion")
+ return result
+
+
+@logger.catch
+def emage(audio_path):
+ smplx_path = None
+ text_path = None
+ rank = 0
+ world_size = 1
+ args = config.parse_args()
+ #os.environ['TRANSFORMERS_CACHE'] = args.data_path_1 + "hub/"
+ if not sys.warnoptions:
+ warnings.simplefilter("ignore")
+ # dist.init_process_group(backend="gloo", rank=rank, world_size=world_size)
+
+ #logger_tools.set_args_and_logger(args, rank)
+ other_tools_hf.set_random_seed(args)
+ other_tools_hf.print_exp_info(args)
+
+ # return one intance of trainer
+ trainer = BaseTrainer(args, sp = smplx_path, ap = audio_path, tp = text_path)
+ result = trainer.test_demo(999)
+ return result
+
+examples = [
+ ["./EMAGE/test_sequences/wave16k/2_scott_0_1_1.wav"],
+ ["./EMAGE/test_sequences/wave16k/2_scott_0_2_2.wav"],
+ ["./EMAGE/test_sequences/wave16k/2_scott_0_3_3.wav"],
+]
+
+demo = gr.Interface(
+ emage, # function
+ inputs=[
+ # gr.File(label="Please upload SMPL-X file with npz format here.", file_types=["npz", "NPZ"]),
+ gr.Audio(),
+ # gr.File(label="Please upload textgrid format file here.", file_types=["TextGrid", "Textgrid", "textgrid"])
+ ], # input type
+ outputs=gr.Video(format="mp4", visible=True),
+ title='\
+
\
+ EMAGE: Towards Unified Holistic Co-Speech Gesture Generation via Expressive Masked Audio Gesture Modeling \
+ CVPR 2024 \
+
',
+ description='\
+ \
+ Haiyang Liu1*, Zihao Zhu2*, Giorgio Becherini3, Yichen Peng4, Mingyang Su5, \
+ You Zhou, Xuefei Zhe, Naoya Iwamoto, Bo Zheng, Michael J. Black3 \
+ (*Equal Contribution) \
+ 1The University of Tokyo, 2Keio University, 4Japan Advanced Institute of Science and Technology, \
+ 3Max Planck Institute for Intelligent Systems, 5Tsinghua University \
+
\
+ ',
+ article="\
+ Due to the limited resources in this space, we process the first 8s of your uploaded audio. \
+ Try to develop this space locally for longer motion generation, e.g., 60s. \
+ Relevant links: [Project Page (https://pantomatrix.github.io/EMAGE/)\
+ ",
+ examples=examples,
+)
+
+
+if __name__ == "__main__":
+ os.environ["MASTER_ADDR"]='127.0.0.1'
+ os.environ["MASTER_PORT"]='8675'
+ #os.environ["TORCH_DISTRIBUTED_DEBUG"] = "DETAIL"
+ demo.launch(share=True)
\ No newline at end of file
diff --git a/.ipynb_checkpoints/packages-checkpoint.txt b/.ipynb_checkpoints/packages-checkpoint.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9695433780ba56a2bbc4a9ba13e2725d6f9bbb7a
--- /dev/null
+++ b/.ipynb_checkpoints/packages-checkpoint.txt
@@ -0,0 +1,4 @@
+libgl1-mesa-dev
+libglu1-mesa-dev
+freeglut3-dev
+mesa-common-dev
\ No newline at end of file
diff --git a/.ipynb_checkpoints/requirements-checkpoint.txt b/.ipynb_checkpoints/requirements-checkpoint.txt
new file mode 100644
index 0000000000000000000000000000000000000000..924c282b799630240602eb639d8fb25d0505d74c
--- /dev/null
+++ b/.ipynb_checkpoints/requirements-checkpoint.txt
@@ -0,0 +1,39 @@
+ffmpeg
+ConfigArgParse==1.7
+fasttext==0.9.2
+h5py==3.10.0
+imageio==2.31.4
+ipython==8.12.3
+joblib==1.3.2
+librosa==0.10.1
+lmdb==1.4.1
+loguru==0.7.2
+matplotlib==3.7.3
+moviepy==1.0.3
+gradio
+fasttext-wheel
+opencv_contrib_python==4.8.1.78
+opencv_python==4.8.1.78
+pandas==1.5.3
+peakutils==1.3.4
+ptflops==0.7.1.2
+python_igraph==0.11.3
+pyvirtualdisplay==3.0
+PyYAML==6.0.1
+replicate==0.15.4
+scikit_learn==1.3.2
+scipy
+soundfile==0.12.1
+termcolor==2.4.0
+textgrid==1.5
+torch==2.1.0
+torchvision
+tqdm==4.66.1
+transformers==4.35.2
+trimesh==3.23.5
+wandb==0.16.0
+pyglet<2
+smplx
+tensorboard
+pyrender
+pyarrow
\ No newline at end of file
diff --git a/.ipynb_checkpoints/test_demo-checkpoint.py b/.ipynb_checkpoints/test_demo-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..6ad0b83c01947ccba896e8dd4d20a5b36860a060
--- /dev/null
+++ b/.ipynb_checkpoints/test_demo-checkpoint.py
@@ -0,0 +1,581 @@
+import os
+import signal
+import time
+import csv
+import sys
+import warnings
+import random
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+import torch.distributed as dist
+from torch.nn.parallel import DistributedDataParallel as DDP
+import torch.multiprocessing as mp
+import numpy as np
+import time
+import pprint
+from loguru import logger
+import smplx
+from torch.utils.tensorboard import SummaryWriter
+import wandb
+import matplotlib.pyplot as plt
+from utils import config, logger_tools, other_tools, metric, data_transfer
+from dataloaders import data_tools
+from dataloaders.build_vocab import Vocab
+from optimizers.optim_factory import create_optimizer
+from optimizers.scheduler_factory import create_scheduler
+from optimizers.loss_factory import get_loss_func
+from dataloaders.data_tools import joints_list
+from utils import rotation_conversions as rc
+
+class BaseTrainer(object):
+ def __init__(self, args):
+ self.args = args
+ self.rank = dist.get_rank()
+ self.checkpoint_path = args.out_path + "custom/" + args.name + args.notes + "/" #wandb.run.dir #args.cache_path+args.out_path+"/"+args.name
+ if self.rank == 0:
+ self.test_data = __import__(f"dataloaders.{args.dataset}", fromlist=["something"]).CustomDataset(args, "test")
+ self.test_loader = torch.utils.data.DataLoader(
+ self.test_data,
+ batch_size=1,
+ shuffle=False,
+ num_workers=args.loader_workers,
+ drop_last=False,
+ )
+ logger.info(f"Init test dataloader success")
+ model_module = __import__(f"models.{args.model}", fromlist=["something"])
+
+ if args.ddp:
+ self.model = getattr(model_module, args.g_name)(args).to(self.rank)
+ process_group = torch.distributed.new_group()
+ self.model = torch.nn.SyncBatchNorm.convert_sync_batchnorm(self.model, process_group)
+ self.model = DDP(self.model, device_ids=[self.rank], output_device=self.rank,
+ broadcast_buffers=False, find_unused_parameters=False)
+ else:
+ self.model = torch.nn.DataParallel(getattr(model_module, args.g_name)(args), args.gpus).cuda()
+
+ if self.rank == 0:
+ logger.info(self.model)
+ logger.info(f"init {args.g_name} success")
+
+ self.smplx = smplx.create(
+ self.args.data_path_1+"smplx_models/",
+ model_type='smplx',
+ gender='NEUTRAL_2020',
+ use_face_contour=False,
+ num_betas=300,
+ num_expression_coeffs=100,
+ ext='npz',
+ use_pca=False,
+ ).to(self.rank).eval()
+
+ self.args = args
+ self.joints = self.test_data.joints
+ self.ori_joint_list = joints_list[self.args.ori_joints]
+ self.tar_joint_list_face = joints_list["beat_smplx_face"]
+ self.tar_joint_list_upper = joints_list["beat_smplx_upper"]
+ self.tar_joint_list_hands = joints_list["beat_smplx_hands"]
+ self.tar_joint_list_lower = joints_list["beat_smplx_lower"]
+
+ self.joint_mask_face = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ self.joints = 55
+ for joint_name in self.tar_joint_list_face:
+ self.joint_mask_face[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ self.joint_mask_upper = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ for joint_name in self.tar_joint_list_upper:
+ self.joint_mask_upper[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ self.joint_mask_hands = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ for joint_name in self.tar_joint_list_hands:
+ self.joint_mask_hands[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ self.joint_mask_lower = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ for joint_name in self.tar_joint_list_lower:
+ self.joint_mask_lower[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+
+ self.tracker = other_tools.EpochTracker(["fid", "l1div", "bc", "rec", "trans", "vel", "transv", 'dis', 'gen', 'acc', 'transa', 'exp', 'lvd', 'mse', "cls", "rec_face", "latent", "cls_full", "cls_self", "cls_word", "latent_word","latent_self"], [False,True,True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,False,False,False])
+
+ vq_model_module = __import__(f"models.motion_representation", fromlist=["something"])
+ self.args.vae_layer = 2
+ self.args.vae_length = 256
+ self.args.vae_test_dim = 106
+ self.vq_model_face = getattr(vq_model_module, "VQVAEConvZero")(self.args).to(self.rank)
+ # print(self.vq_model_face)
+ other_tools.load_checkpoints(self.vq_model_face, self.args.data_path_1 + "pretrained_vq/last_790_face_v2.bin", args.e_name)
+ self.args.vae_test_dim = 78
+ self.vq_model_upper = getattr(vq_model_module, "VQVAEConvZero")(self.args).to(self.rank)
+ other_tools.load_checkpoints(self.vq_model_upper, self.args.data_path_1 + "pretrained_vq/upper_vertex_1layer_710.bin", args.e_name)
+ self.args.vae_test_dim = 180
+ self.vq_model_hands = getattr(vq_model_module, "VQVAEConvZero")(self.args).to(self.rank)
+ other_tools.load_checkpoints(self.vq_model_hands, self.args.data_path_1 + "pretrained_vq/hands_vertex_1layer_710.bin", args.e_name)
+ self.args.vae_test_dim = 61
+ self.args.vae_layer = 4
+ self.vq_model_lower = getattr(vq_model_module, "VQVAEConvZero")(self.args).to(self.rank)
+ other_tools.load_checkpoints(self.vq_model_lower, self.args.data_path_1 + "pretrained_vq/lower_foot_600.bin", args.e_name)
+ self.args.vae_test_dim = 61
+ self.args.vae_layer = 4
+ self.global_motion = getattr(vq_model_module, "VAEConvZero")(self.args).to(self.rank)
+ other_tools.load_checkpoints(self.global_motion, self.args.data_path_1 + "pretrained_vq/last_1700_foot.bin", args.e_name)
+ self.args.vae_test_dim = 330
+ self.args.vae_layer = 4
+ self.args.vae_length = 240
+
+ self.vq_model_face.eval()
+ self.vq_model_upper.eval()
+ self.vq_model_hands.eval()
+ self.vq_model_lower.eval()
+ self.global_motion.eval()
+
+ self.cls_loss = nn.NLLLoss().to(self.rank)
+ self.reclatent_loss = nn.MSELoss().to(self.rank)
+ self.vel_loss = torch.nn.L1Loss(reduction='mean').to(self.rank)
+ self.rec_loss = get_loss_func("GeodesicLoss").to(self.rank)
+ self.log_softmax = nn.LogSoftmax(dim=2).to(self.rank)
+
+
+ def inverse_selection(self, filtered_t, selection_array, n):
+ original_shape_t = np.zeros((n, selection_array.size))
+ selected_indices = np.where(selection_array == 1)[0]
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+ return original_shape_t
+
+ def inverse_selection_tensor(self, filtered_t, selection_array, n):
+ selection_array = torch.from_numpy(selection_array).cuda()
+ original_shape_t = torch.zeros((n, 165)).cuda()
+ selected_indices = torch.where(selection_array == 1)[0]
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+ return original_shape_t
+
+ def _load_data(self, dict_data):
+ tar_pose_raw = dict_data["pose"]
+ tar_pose = tar_pose_raw[:, :, :165].to(self.rank)
+ tar_contact = tar_pose_raw[:, :, 165:169].to(self.rank)
+ tar_trans = dict_data["trans"].to(self.rank)
+ tar_exps = dict_data["facial"].to(self.rank)
+ in_audio = dict_data["audio"].to(self.rank)
+ in_word = dict_data["word"].to(self.rank)
+ tar_beta = dict_data["beta"].to(self.rank)
+ tar_id = dict_data["id"].to(self.rank).long()
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+
+ tar_pose_jaw = tar_pose[:, :, 66:69]
+ tar_pose_jaw = rc.axis_angle_to_matrix(tar_pose_jaw.reshape(bs, n, 1, 3))
+ tar_pose_jaw = rc.matrix_to_rotation_6d(tar_pose_jaw).reshape(bs, n, 1*6)
+ tar_pose_face = torch.cat([tar_pose_jaw, tar_exps], dim=2)
+
+ tar_pose_hands = tar_pose[:, :, 25*3:55*3]
+ tar_pose_hands = rc.axis_angle_to_matrix(tar_pose_hands.reshape(bs, n, 30, 3))
+ tar_pose_hands = rc.matrix_to_rotation_6d(tar_pose_hands).reshape(bs, n, 30*6)
+
+ tar_pose_upper = tar_pose[:, :, self.joint_mask_upper.astype(bool)]
+ tar_pose_upper = rc.axis_angle_to_matrix(tar_pose_upper.reshape(bs, n, 13, 3))
+ tar_pose_upper = rc.matrix_to_rotation_6d(tar_pose_upper).reshape(bs, n, 13*6)
+
+ tar_pose_leg = tar_pose[:, :, self.joint_mask_lower.astype(bool)]
+ tar_pose_leg = rc.axis_angle_to_matrix(tar_pose_leg.reshape(bs, n, 9, 3))
+ tar_pose_leg = rc.matrix_to_rotation_6d(tar_pose_leg).reshape(bs, n, 9*6)
+ tar_pose_lower = torch.cat([tar_pose_leg, tar_trans, tar_contact], dim=2)
+
+ # tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ # tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ tar4dis = torch.cat([tar_pose_jaw, tar_pose_upper, tar_pose_hands, tar_pose_leg], dim=2)
+
+ tar_index_value_face_top = self.vq_model_face.map2index(tar_pose_face) # bs*n/4
+ tar_index_value_upper_top = self.vq_model_upper.map2index(tar_pose_upper) # bs*n/4
+ tar_index_value_hands_top = self.vq_model_hands.map2index(tar_pose_hands) # bs*n/4
+ tar_index_value_lower_top = self.vq_model_lower.map2index(tar_pose_lower) # bs*n/4
+
+ latent_face_top = self.vq_model_face.map2latent(tar_pose_face) # bs*n/4
+ latent_upper_top = self.vq_model_upper.map2latent(tar_pose_upper) # bs*n/4
+ latent_hands_top = self.vq_model_hands.map2latent(tar_pose_hands) # bs*n/4
+ latent_lower_top = self.vq_model_lower.map2latent(tar_pose_lower) # bs*n/4
+
+ latent_in = torch.cat([latent_upper_top, latent_hands_top, latent_lower_top], dim=2)
+
+ index_in = torch.stack([tar_index_value_upper_top, tar_index_value_hands_top, tar_index_value_lower_top], dim=-1).long()
+
+ tar_pose_6d = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, 55, 3))
+ tar_pose_6d = rc.matrix_to_rotation_6d(tar_pose_6d).reshape(bs, n, 55*6)
+ latent_all = torch.cat([tar_pose_6d, tar_trans, tar_contact], dim=-1)
+ # print(tar_index_value_upper_top.shape, index_in.shape)
+ return {
+ "tar_pose_jaw": tar_pose_jaw,
+ "tar_pose_face": tar_pose_face,
+ "tar_pose_upper": tar_pose_upper,
+ "tar_pose_lower": tar_pose_lower,
+ "tar_pose_hands": tar_pose_hands,
+ 'tar_pose_leg': tar_pose_leg,
+ "in_audio": in_audio,
+ "in_word": in_word,
+ "tar_trans": tar_trans,
+ "tar_exps": tar_exps,
+ "tar_beta": tar_beta,
+ "tar_pose": tar_pose,
+ "tar4dis": tar4dis,
+ "tar_index_value_face_top": tar_index_value_face_top,
+ "tar_index_value_upper_top": tar_index_value_upper_top,
+ "tar_index_value_hands_top": tar_index_value_hands_top,
+ "tar_index_value_lower_top": tar_index_value_lower_top,
+ "latent_face_top": latent_face_top,
+ "latent_upper_top": latent_upper_top,
+ "latent_hands_top": latent_hands_top,
+ "latent_lower_top": latent_lower_top,
+ "latent_in": latent_in,
+ "index_in": index_in,
+ "tar_id": tar_id,
+ "latent_all": latent_all,
+ "tar_pose_6d": tar_pose_6d,
+ "tar_contact": tar_contact,
+ }
+
+ def _g_test(self, loaded_data):
+ mode = 'test'
+ bs, n, j = loaded_data["tar_pose"].shape[0], loaded_data["tar_pose"].shape[1], self.joints
+ tar_pose = loaded_data["tar_pose"]
+ tar_beta = loaded_data["tar_beta"]
+ in_word = loaded_data["in_word"]
+ tar_exps = loaded_data["tar_exps"]
+ tar_contact = loaded_data["tar_contact"]
+ in_audio = loaded_data["in_audio"]
+ tar_trans = loaded_data["tar_trans"]
+
+ remain = n%8
+ if remain != 0:
+ tar_pose = tar_pose[:, :-remain, :]
+ tar_beta = tar_beta[:, :-remain, :]
+ tar_trans = tar_trans[:, :-remain, :]
+ in_word = in_word[:, :-remain]
+ tar_exps = tar_exps[:, :-remain, :]
+ tar_contact = tar_contact[:, :-remain, :]
+ n = n - remain
+
+ tar_pose_jaw = tar_pose[:, :, 66:69]
+ tar_pose_jaw = rc.axis_angle_to_matrix(tar_pose_jaw.reshape(bs, n, 1, 3))
+ tar_pose_jaw = rc.matrix_to_rotation_6d(tar_pose_jaw).reshape(bs, n, 1*6)
+ tar_pose_face = torch.cat([tar_pose_jaw, tar_exps], dim=2)
+
+ tar_pose_hands = tar_pose[:, :, 25*3:55*3]
+ tar_pose_hands = rc.axis_angle_to_matrix(tar_pose_hands.reshape(bs, n, 30, 3))
+ tar_pose_hands = rc.matrix_to_rotation_6d(tar_pose_hands).reshape(bs, n, 30*6)
+
+ tar_pose_upper = tar_pose[:, :, self.joint_mask_upper.astype(bool)]
+ tar_pose_upper = rc.axis_angle_to_matrix(tar_pose_upper.reshape(bs, n, 13, 3))
+ tar_pose_upper = rc.matrix_to_rotation_6d(tar_pose_upper).reshape(bs, n, 13*6)
+
+ tar_pose_leg = tar_pose[:, :, self.joint_mask_lower.astype(bool)]
+ tar_pose_leg = rc.axis_angle_to_matrix(tar_pose_leg.reshape(bs, n, 9, 3))
+ tar_pose_leg = rc.matrix_to_rotation_6d(tar_pose_leg).reshape(bs, n, 9*6)
+ tar_pose_lower = torch.cat([tar_pose_leg, tar_trans, tar_contact], dim=2)
+
+ tar_pose_6d = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, 55, 3))
+ tar_pose_6d = rc.matrix_to_rotation_6d(tar_pose_6d).reshape(bs, n, 55*6)
+ latent_all = torch.cat([tar_pose_6d, tar_trans, tar_contact], dim=-1)
+
+ rec_index_all_face = []
+ rec_index_all_upper = []
+ rec_index_all_lower = []
+ rec_index_all_hands = []
+
+ roundt = (n - self.args.pre_frames) // (self.args.pose_length - self.args.pre_frames)
+ remain = (n - self.args.pre_frames) % (self.args.pose_length - self.args.pre_frames)
+ round_l = self.args.pose_length - self.args.pre_frames
+
+ for i in range(0, roundt):
+ in_word_tmp = in_word[:, i*(round_l):(i+1)*(round_l)+self.args.pre_frames]
+ # audio fps is 16000 and pose fps is 30
+ in_audio_tmp = in_audio[:, i*(16000//30*round_l):(i+1)*(16000//30*round_l)+16000//30*self.args.pre_frames]
+ in_id_tmp = loaded_data['tar_id'][:, i*(round_l):(i+1)*(round_l)+self.args.pre_frames]
+ mask_val = torch.ones(bs, self.args.pose_length, self.args.pose_dims+3+4).float().cuda()
+ mask_val[:, :self.args.pre_frames, :] = 0.0
+ if i == 0:
+ latent_all_tmp = latent_all[:, i*(round_l):(i+1)*(round_l)+self.args.pre_frames, :]
+ else:
+ latent_all_tmp = latent_all[:, i*(round_l):(i+1)*(round_l)+self.args.pre_frames, :]
+ # print(latent_all_tmp.shape, latent_last.shape)
+ latent_all_tmp[:, :self.args.pre_frames, :] = latent_last[:, -self.args.pre_frames:, :]
+
+ net_out_val = self.model(
+ in_audio = in_audio_tmp,
+ in_word=in_word_tmp,
+ mask=mask_val,
+ in_motion = latent_all_tmp,
+ in_id = in_id_tmp,
+ use_attentions=True,)
+
+ if self.args.cu != 0:
+ rec_index_upper = self.log_softmax(net_out_val["cls_upper"]).reshape(-1, self.args.vae_codebook_size)
+ _, rec_index_upper = torch.max(rec_index_upper.reshape(-1, self.args.pose_length, self.args.vae_codebook_size), dim=2)
+ #rec_upper = self.vq_model_upper.decode(rec_index_upper)
+ else:
+ _, rec_index_upper, _, _ = self.vq_model_upper.quantizer(net_out_val["rec_upper"])
+ #rec_upper = self.vq_model_upper.decoder(rec_index_upper)
+ if self.args.cl != 0:
+ rec_index_lower = self.log_softmax(net_out_val["cls_lower"]).reshape(-1, self.args.vae_codebook_size)
+ _, rec_index_lower = torch.max(rec_index_lower.reshape(-1, self.args.pose_length, self.args.vae_codebook_size), dim=2)
+ #rec_lower = self.vq_model_lower.decode(rec_index_lower)
+ else:
+ _, rec_index_lower, _, _ = self.vq_model_lower.quantizer(net_out_val["rec_lower"])
+ #rec_lower = self.vq_model_lower.decoder(rec_index_lower)
+ if self.args.ch != 0:
+ rec_index_hands = self.log_softmax(net_out_val["cls_hands"]).reshape(-1, self.args.vae_codebook_size)
+ _, rec_index_hands = torch.max(rec_index_hands.reshape(-1, self.args.pose_length, self.args.vae_codebook_size), dim=2)
+ #rec_hands = self.vq_model_hands.decode(rec_index_hands)
+ else:
+ _, rec_index_hands, _, _ = self.vq_model_hands.quantizer(net_out_val["rec_hands"])
+ #rec_hands = self.vq_model_hands.decoder(rec_index_hands)
+ if self.args.cf != 0:
+ rec_index_face = self.log_softmax(net_out_val["cls_face"]).reshape(-1, self.args.vae_codebook_size)
+ _, rec_index_face = torch.max(rec_index_face.reshape(-1, self.args.pose_length, self.args.vae_codebook_size), dim=2)
+ #rec_face = self.vq_model_face.decoder(rec_index_face)
+ else:
+ _, rec_index_face, _, _ = self.vq_model_face.quantizer(net_out_val["rec_face"])
+ #rec_face = self.vq_model_face.decoder(rec_index_face)
+
+ if i == 0:
+ rec_index_all_face.append(rec_index_face)
+ rec_index_all_upper.append(rec_index_upper)
+ rec_index_all_lower.append(rec_index_lower)
+ rec_index_all_hands.append(rec_index_hands)
+ else:
+ rec_index_all_face.append(rec_index_face[:, self.args.pre_frames:])
+ rec_index_all_upper.append(rec_index_upper[:, self.args.pre_frames:])
+ rec_index_all_lower.append(rec_index_lower[:, self.args.pre_frames:])
+ rec_index_all_hands.append(rec_index_hands[:, self.args.pre_frames:])
+
+ if self.args.cu != 0:
+ rec_upper_last = self.vq_model_upper.decode(rec_index_upper)
+ else:
+ rec_upper_last = self.vq_model_upper.decoder(rec_index_upper)
+ if self.args.cl != 0:
+ rec_lower_last = self.vq_model_lower.decode(rec_index_lower)
+ else:
+ rec_lower_last = self.vq_model_lower.decoder(rec_index_lower)
+ if self.args.ch != 0:
+ rec_hands_last = self.vq_model_hands.decode(rec_index_hands)
+ else:
+ rec_hands_last = self.vq_model_hands.decoder(rec_index_hands)
+ # if self.args.cf != 0:
+ # rec_face_last = self.vq_model_face.decode(rec_index_face)
+ # else:
+ # rec_face_last = self.vq_model_face.decoder(rec_index_face)
+
+ rec_pose_legs = rec_lower_last[:, :, :54]
+ bs, n = rec_pose_legs.shape[0], rec_pose_legs.shape[1]
+ rec_pose_upper = rec_upper_last.reshape(bs, n, 13, 6)
+ rec_pose_upper = rc.rotation_6d_to_matrix(rec_pose_upper)#
+ rec_pose_upper = rc.matrix_to_axis_angle(rec_pose_upper).reshape(bs*n, 13*3)
+ rec_pose_upper_recover = self.inverse_selection_tensor(rec_pose_upper, self.joint_mask_upper, bs*n)
+ rec_pose_lower = rec_pose_legs.reshape(bs, n, 9, 6)
+ rec_pose_lower = rc.rotation_6d_to_matrix(rec_pose_lower)
+ rec_pose_lower = rc.matrix_to_axis_angle(rec_pose_lower).reshape(bs*n, 9*3)
+ rec_pose_lower_recover = self.inverse_selection_tensor(rec_pose_lower, self.joint_mask_lower, bs*n)
+ rec_pose_hands = rec_hands_last.reshape(bs, n, 30, 6)
+ rec_pose_hands = rc.rotation_6d_to_matrix(rec_pose_hands)
+ rec_pose_hands = rc.matrix_to_axis_angle(rec_pose_hands).reshape(bs*n, 30*3)
+ rec_pose_hands_recover = self.inverse_selection_tensor(rec_pose_hands, self.joint_mask_hands, bs*n)
+ rec_pose = rec_pose_upper_recover + rec_pose_lower_recover + rec_pose_hands_recover
+ rec_pose = rc.axis_angle_to_matrix(rec_pose.reshape(bs, n, j, 3))
+ rec_pose = rc.matrix_to_rotation_6d(rec_pose).reshape(bs, n, j*6)
+ rec_trans_v_s = rec_lower_last[:, :, 54:57]
+ rec_x_trans = other_tools.velocity2position(rec_trans_v_s[:, :, 0:1], 1/self.args.pose_fps, tar_trans[:, 0, 0:1])
+ rec_z_trans = other_tools.velocity2position(rec_trans_v_s[:, :, 2:3], 1/self.args.pose_fps, tar_trans[:, 0, 2:3])
+ rec_y_trans = rec_trans_v_s[:,:,1:2]
+ rec_trans = torch.cat([rec_x_trans, rec_y_trans, rec_z_trans], dim=-1)
+ latent_last = torch.cat([rec_pose, rec_trans, rec_lower_last[:, :, 57:61]], dim=-1)
+
+ rec_index_face = torch.cat(rec_index_all_face, dim=1)
+ rec_index_upper = torch.cat(rec_index_all_upper, dim=1)
+ rec_index_lower = torch.cat(rec_index_all_lower, dim=1)
+ rec_index_hands = torch.cat(rec_index_all_hands, dim=1)
+ if self.args.cu != 0:
+ rec_upper = self.vq_model_upper.decode(rec_index_upper)
+ else:
+ rec_upper = self.vq_model_upper.decoder(rec_index_upper)
+ if self.args.cl != 0:
+ rec_lower = self.vq_model_lower.decode(rec_index_lower)
+ else:
+ rec_lower = self.vq_model_lower.decoder(rec_index_lower)
+ if self.args.ch != 0:
+ rec_hands = self.vq_model_hands.decode(rec_index_hands)
+ else:
+ rec_hands = self.vq_model_hands.decoder(rec_index_hands)
+ if self.args.cf != 0:
+ rec_face = self.vq_model_face.decode(rec_index_face)
+ else:
+ rec_face = self.vq_model_face.decoder(rec_index_face)
+
+ rec_exps = rec_face[:, :, 6:]
+ rec_pose_jaw = rec_face[:, :, :6]
+ rec_pose_legs = rec_lower[:, :, :54]
+ bs, n = rec_pose_jaw.shape[0], rec_pose_jaw.shape[1]
+ rec_pose_upper = rec_upper.reshape(bs, n, 13, 6)
+ rec_pose_upper = rc.rotation_6d_to_matrix(rec_pose_upper)#
+ rec_pose_upper = rc.matrix_to_axis_angle(rec_pose_upper).reshape(bs*n, 13*3)
+ rec_pose_upper_recover = self.inverse_selection_tensor(rec_pose_upper, self.joint_mask_upper, bs*n)
+ rec_pose_lower = rec_pose_legs.reshape(bs, n, 9, 6)
+ rec_pose_lower = rc.rotation_6d_to_matrix(rec_pose_lower)
+ rec_lower2global = rc.matrix_to_rotation_6d(rec_pose_lower.clone()).reshape(bs, n, 9*6)
+ rec_pose_lower = rc.matrix_to_axis_angle(rec_pose_lower).reshape(bs*n, 9*3)
+ rec_pose_lower_recover = self.inverse_selection_tensor(rec_pose_lower, self.joint_mask_lower, bs*n)
+ rec_pose_hands = rec_hands.reshape(bs, n, 30, 6)
+ rec_pose_hands = rc.rotation_6d_to_matrix(rec_pose_hands)
+ rec_pose_hands = rc.matrix_to_axis_angle(rec_pose_hands).reshape(bs*n, 30*3)
+ rec_pose_hands_recover = self.inverse_selection_tensor(rec_pose_hands, self.joint_mask_hands, bs*n)
+ rec_pose_jaw = rec_pose_jaw.reshape(bs*n, 6)
+ rec_pose_jaw = rc.rotation_6d_to_matrix(rec_pose_jaw)
+ rec_pose_jaw = rc.matrix_to_axis_angle(rec_pose_jaw).reshape(bs*n, 1*3)
+ rec_pose = rec_pose_upper_recover + rec_pose_lower_recover + rec_pose_hands_recover
+ rec_pose[:, 66:69] = rec_pose_jaw
+
+ to_global = rec_lower
+ to_global[:, :, 54:57] = 0.0
+ to_global[:, :, :54] = rec_lower2global
+ rec_global = self.global_motion(to_global)
+
+ rec_trans_v_s = rec_global["rec_pose"][:, :, 54:57]
+ rec_x_trans = other_tools.velocity2position(rec_trans_v_s[:, :, 0:1], 1/self.args.pose_fps, tar_trans[:, 0, 0:1])
+ rec_z_trans = other_tools.velocity2position(rec_trans_v_s[:, :, 2:3], 1/self.args.pose_fps, tar_trans[:, 0, 2:3])
+ rec_y_trans = rec_trans_v_s[:,:,1:2]
+ rec_trans = torch.cat([rec_x_trans, rec_y_trans, rec_z_trans], dim=-1)
+ tar_pose = tar_pose[:, :n, :]
+ tar_exps = tar_exps[:, :n, :]
+ tar_trans = tar_trans[:, :n, :]
+ tar_beta = tar_beta[:, :n, :]
+
+ rec_pose = rc.axis_angle_to_matrix(rec_pose.reshape(bs*n, j, 3))
+ rec_pose = rc.matrix_to_rotation_6d(rec_pose).reshape(bs, n, j*6)
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs*n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+
+ return {
+ 'rec_pose': rec_pose,
+ 'rec_trans': rec_trans,
+ 'tar_pose': tar_pose,
+ 'tar_exps': tar_exps,
+ 'tar_beta': tar_beta,
+ 'tar_trans': tar_trans,
+ 'rec_exps': rec_exps,
+ }
+
+
+ def test_demo(self, epoch):
+ '''
+ input audio and text, output motion
+ do not calculate loss and metric
+ save video
+ '''
+ results_save_path = self.checkpoint_path + f"/{epoch}/"
+ if os.path.exists(results_save_path):
+ return 0
+ os.makedirs(results_save_path)
+ start_time = time.time()
+ total_length = 0
+ test_seq_list = self.test_data.selected_file
+ align = 0
+ latent_out = []
+ latent_ori = []
+ l2_all = 0
+ lvel = 0
+ self.model.eval()
+ self.smplx.eval()
+ # self.eval_copy.eval()
+ with torch.no_grad():
+ for its, batch_data in enumerate(self.test_loader):
+ loaded_data = self._load_data(batch_data)
+ net_out = self._g_test(loaded_data)
+ tar_pose = net_out['tar_pose']
+ rec_pose = net_out['rec_pose']
+ tar_exps = net_out['tar_exps']
+ tar_beta = net_out['tar_beta']
+ rec_trans = net_out['rec_trans']
+ tar_trans = net_out['tar_trans']
+ rec_exps = net_out['rec_exps']
+ # print(rec_pose.shape, tar_pose.shape)
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+
+ # interpolate to 30fps
+ if (30/self.args.pose_fps) != 1:
+ assert 30%self.args.pose_fps == 0
+ n *= int(30/self.args.pose_fps)
+ tar_pose = torch.nn.functional.interpolate(tar_pose.permute(0, 2, 1), scale_factor=30/self.args.pose_fps, mode='linear').permute(0,2,1)
+ rec_pose = torch.nn.functional.interpolate(rec_pose.permute(0, 2, 1), scale_factor=30/self.args.pose_fps, mode='linear').permute(0,2,1)
+
+ # print(rec_pose.shape, tar_pose.shape)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose.reshape(bs*n, j, 6))
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs*n, j, 6))
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+
+ tar_pose_np = tar_pose.detach().cpu().numpy()
+ rec_pose_np = rec_pose.detach().cpu().numpy()
+ rec_trans_np = rec_trans.detach().cpu().numpy().reshape(bs*n, 3)
+ rec_exp_np = rec_exps.detach().cpu().numpy().reshape(bs*n, 100)
+ tar_exp_np = tar_exps.detach().cpu().numpy().reshape(bs*n, 100)
+ tar_trans_np = tar_trans.detach().cpu().numpy().reshape(bs*n, 3)
+
+ gt_npz = np.load(self.args.data_path+self.args.pose_rep +"/"+test_seq_list.iloc[its]['id']+".npz", allow_pickle=True)
+ np.savez(results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=tar_pose_np,
+ expressions=tar_exp_np,
+ trans=tar_trans_np,
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30 ,
+ )
+ np.savez(results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=rec_pose_np,
+ expressions=rec_exp_np,
+ trans=rec_trans_np,
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30,
+ )
+ total_length += n
+ # other_tools.render_one_sequence(
+ # results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.npz',
+ # results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.npz',
+ # results_save_path,
+ # self.args.data_path+"wave16k/"+test_seq_list.iloc[its]['id']+".wav",
+ # self.args.data_path_1+"smplx_models/",
+ # use_matplotlib = False,
+ # args = self.args,
+ # )
+ end_time = time.time() - start_time
+ logger.info(f"total inference time: {int(end_time)} s for {int(total_length/self.args.pose_fps)} s motion")
+
+@logger.catch
+def main_worker(rank, world_size, args):
+ #os.environ['TRANSFORMERS_CACHE'] = args.data_path_1 + "hub/"
+ if not sys.warnoptions:
+ warnings.simplefilter("ignore")
+ dist.init_process_group(backend="nccl", rank=rank, world_size=world_size)
+
+ logger_tools.set_args_and_logger(args, rank)
+ other_tools.set_random_seed(args)
+ other_tools.print_exp_info(args)
+
+ # return one intance of trainer
+ other_tools.write_wav_names_to_csv(args.data_path, args.data_path+"test.csv")
+ trainer = BaseTrainer(args)
+ other_tools.load_checkpoints(trainer.model, args.test_ckpt, args.g_name)
+ trainer.test_demo(999)
+
+
+
+if __name__ == "__main__":
+ os.environ["MASTER_ADDR"]='127.0.0.1'
+ os.environ["MASTER_PORT"]='8675'
+ #os.environ["TORCH_DISTRIBUTED_DEBUG"] = "DETAIL"
+ args = config.parse_args()
+ if args.ddp:
+ mp.set_start_method("spawn", force=True)
+ mp.spawn(
+ main_worker,
+ args=(len(args.gpus), args,),
+ nprocs=len(args.gpus),
+ )
+ else:
+ main_worker(0, 1, args)
\ No newline at end of file
diff --git a/EMAGE/emage_audio_175.bin b/EMAGE/emage_audio_175.bin
new file mode 100644
index 0000000000000000000000000000000000000000..a65200bc53a2212e78567c7bbda12ec2e6e8dc46
--- /dev/null
+++ b/EMAGE/emage_audio_175.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b19f845300e7f52c77eddfb6307f48c8fd2766edada3efa8ad1973a87990c1ea
+size 556333206
diff --git a/EMAGE/pretrained_vq/.DS_Store b/EMAGE/pretrained_vq/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6
Binary files /dev/null and b/EMAGE/pretrained_vq/.DS_Store differ
diff --git a/EMAGE/pretrained_vq/hands_vertex_1layer_710.bin b/EMAGE/pretrained_vq/hands_vertex_1layer_710.bin
new file mode 100644
index 0000000000000000000000000000000000000000..da28ca39541d2811d9753c84bee2d8ead465826e
--- /dev/null
+++ b/EMAGE/pretrained_vq/hands_vertex_1layer_710.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1595a13fbdf38b95da2baf6a4ba9f0c62cd6af8b8f537da12c1c90321affa3b3
+size 9644516
diff --git a/EMAGE/pretrained_vq/last_1700_foot.bin b/EMAGE/pretrained_vq/last_1700_foot.bin
new file mode 100644
index 0000000000000000000000000000000000000000..06d2da3a17f60955e3e78333d0c3a2e3e99acb86
--- /dev/null
+++ b/EMAGE/pretrained_vq/last_1700_foot.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f293265b828c6b45e12068c9b7956283c92b40cfdc9dd56ae960bbeb7bba1ad6
+size 14611444
diff --git a/EMAGE/pretrained_vq/last_790_face_v2.bin b/EMAGE/pretrained_vq/last_790_face_v2.bin
new file mode 100644
index 0000000000000000000000000000000000000000..427de62ce83e964d2628d8b56105f80719c8ae21
--- /dev/null
+++ b/EMAGE/pretrained_vq/last_790_face_v2.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:13ff79afef2c3209804c0cae2b9a7c467c1a39268efa87a637e860b8e6b1b4c0
+size 8935204
diff --git a/EMAGE/pretrained_vq/lower_foot_600.bin b/EMAGE/pretrained_vq/lower_foot_600.bin
new file mode 100644
index 0000000000000000000000000000000000000000..0270a5e73202732adde4e6b88cb7d24cf8adc3b2
--- /dev/null
+++ b/EMAGE/pretrained_vq/lower_foot_600.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0e323ed5f7014957433b59249497188656811b76952d666eae5f4affdc341786
+size 14873924
diff --git a/EMAGE/pretrained_vq/upper_vertex_1layer_710.bin b/EMAGE/pretrained_vq/upper_vertex_1layer_710.bin
new file mode 100644
index 0000000000000000000000000000000000000000..33ccfbdf3aaf92df0e06bf3779ba7730bfb75503
--- /dev/null
+++ b/EMAGE/pretrained_vq/upper_vertex_1layer_710.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:58ffcb34ff18f3aeaf53898980ef623ea9ce36f0302a005b5f95ceef1a206a8f
+size 8701092
diff --git a/EMAGE/smplx_models/.DS_Store b/EMAGE/smplx_models/.DS_Store
new file mode 100644
index 0000000000000000000000000000000000000000..64c4cc33f2dfef96d20152797da59df9627ab464
Binary files /dev/null and b/EMAGE/smplx_models/.DS_Store differ
diff --git a/EMAGE/smplx_models/smplx/SMPLX_NEUTRAL_2020.npz b/EMAGE/smplx_models/smplx/SMPLX_NEUTRAL_2020.npz
new file mode 100644
index 0000000000000000000000000000000000000000..998c299e1ea055a6091e87edb92774c888940cd7
--- /dev/null
+++ b/EMAGE/smplx_models/smplx/SMPLX_NEUTRAL_2020.npz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bdf06146e27d92022fe5dadad3b9203373f6879eca8e4d8235359ee3ec6a5a74
+size 167264530
diff --git a/EMAGE/test_sequences/smplxflame_30/2_scott_0_1_1.npz b/EMAGE/test_sequences/smplxflame_30/2_scott_0_1_1.npz
new file mode 100644
index 0000000000000000000000000000000000000000..4d96616f0a09bd6df0971b9547d2e8376b078fcf
--- /dev/null
+++ b/EMAGE/test_sequences/smplxflame_30/2_scott_0_1_1.npz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:37b112fd59fcabb09270d6ca3c74e7459cc5b9729564bcacf1f75609f3999592
+size 2831524
diff --git a/EMAGE/test_sequences/smplxflame_30/2_scott_0_2_2.npz b/EMAGE/test_sequences/smplxflame_30/2_scott_0_2_2.npz
new file mode 100644
index 0000000000000000000000000000000000000000..f52cab82761973524dbd96ba8d442591779073bd
--- /dev/null
+++ b/EMAGE/test_sequences/smplxflame_30/2_scott_0_2_2.npz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5875f768aa4600af7d767625e0d87941b1cca9555855d8c6b509004116790f7d
+size 2754356
diff --git a/EMAGE/test_sequences/smplxflame_30/2_scott_0_3_3.npz b/EMAGE/test_sequences/smplxflame_30/2_scott_0_3_3.npz
new file mode 100644
index 0000000000000000000000000000000000000000..67846e0f8dd34b32f72946fff008c3ba3598ef0b
--- /dev/null
+++ b/EMAGE/test_sequences/smplxflame_30/2_scott_0_3_3.npz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:23ace88c7ff0288af83cc30d2428e0cb70c3d92bce981a67a5811cd53ab96db4
+size 3021476
diff --git a/EMAGE/test_sequences/smplxflame_30/2_scott_0_4_4.npz b/EMAGE/test_sequences/smplxflame_30/2_scott_0_4_4.npz
new file mode 100644
index 0000000000000000000000000000000000000000..a7f4b518c86337929556e42a2f79cae7bdfd66f2
--- /dev/null
+++ b/EMAGE/test_sequences/smplxflame_30/2_scott_0_4_4.npz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ede3993db9565b7b3a945532def69d617d6b2338f488a746a7be998f3b0685d8
+size 2976956
diff --git a/EMAGE/test_sequences/test.csv b/EMAGE/test_sequences/test.csv
new file mode 100644
index 0000000000000000000000000000000000000000..1f33f8b45bcd303b94c113e4865ab89ae14cbd24
--- /dev/null
+++ b/EMAGE/test_sequences/test.csv
@@ -0,0 +1,5 @@
+id,type
+2_scott_0_3_3,test
+2_scott_0_2_2,test
+2_scott_0_1_1,test
+2_scott_0_4_4,test
diff --git a/EMAGE/test_sequences/textgrid/2_scott_0_1_1.TextGrid b/EMAGE/test_sequences/textgrid/2_scott_0_1_1.TextGrid
new file mode 100644
index 0000000000000000000000000000000000000000..abd0228f0e219b86cc370b11c03712d85afa21cc
--- /dev/null
+++ b/EMAGE/test_sequences/textgrid/2_scott_0_1_1.TextGrid
@@ -0,0 +1,3636 @@
+File type = "ooTextFile"
+Object class = "TextGrid"
+
+xmin = 0
+xmax = 64.097375
+tiers?
+size = 2
+item []:
+ item [1]:
+ class = "IntervalTier"
+ name = "words"
+ xmin = 0
+ xmax = 64.097375
+ intervals: size = 220
+ intervals [1]:
+ xmin = 0
+ xmax = 1.42
+ text = ""
+ intervals [2]:
+ xmin = 1.42
+ xmax = 1.52
+ text = "the"
+ intervals [3]:
+ xmin = 1.52
+ xmax = 1.78
+ text = "first"
+ intervals [4]:
+ xmin = 1.78
+ xmax = 1.97
+ text = "thing"
+ intervals [5]:
+ xmin = 1.97
+ xmax = 2.04
+ text = "i"
+ intervals [6]:
+ xmin = 2.04
+ xmax = 2.21
+ text = "like"
+ intervals [7]:
+ xmin = 2.21
+ xmax = 2.28
+ text = "to"
+ intervals [8]:
+ xmin = 2.28
+ xmax = 2.47
+ text = "do"
+ intervals [9]:
+ xmin = 2.47
+ xmax = 2.63
+ text = "on"
+ intervals [10]:
+ xmin = 2.63
+ xmax = 3.32
+ text = "weekends"
+ intervals [11]:
+ xmin = 3.32
+ xmax = 3.58
+ text = "is"
+ intervals [12]:
+ xmin = 3.58
+ xmax = 4.41
+ text = "relaxing"
+ intervals [13]:
+ xmin = 4.41
+ xmax = 4.52
+ text = ""
+ intervals [14]:
+ xmin = 4.52
+ xmax = 5.05
+ text = "and"
+ intervals [15]:
+ xmin = 5.05
+ xmax = 5.14
+ text = "i"
+ intervals [16]:
+ xmin = 5.14
+ xmax = 5.33
+ text = "think"
+ intervals [17]:
+ xmin = 5.33
+ xmax = 5.41
+ text = "i'll"
+ intervals [18]:
+ xmin = 5.41
+ xmax = 5.5
+ text = "go"
+ intervals [19]:
+ xmin = 5.5
+ xmax = 6
+ text = "shopping"
+ intervals [20]:
+ xmin = 6
+ xmax = 6.11
+ text = "if"
+ intervals [21]:
+ xmin = 6.11
+ xmax = 6.29
+ text = "i'm"
+ intervals [22]:
+ xmin = 6.29
+ xmax = 6.54
+ text = "not"
+ intervals [23]:
+ xmin = 6.54
+ xmax = 6.7
+ text = "that"
+ intervals [24]:
+ xmin = 6.7
+ xmax = 7.19
+ text = "tired"
+ intervals [25]:
+ xmin = 7.19
+ xmax = 7.45
+ text = ""
+ intervals [26]:
+ xmin = 7.45
+ xmax = 7.62
+ text = "so"
+ intervals [27]:
+ xmin = 7.62
+ xmax = 7.74
+ text = "that"
+ intervals [28]:
+ xmin = 7.74
+ xmax = 7.85
+ text = "you"
+ intervals [29]:
+ xmin = 7.85
+ xmax = 8.14
+ text = "started"
+ intervals [30]:
+ xmin = 8.14
+ xmax = 8.24
+ text = "by"
+ intervals [31]:
+ xmin = 8.24
+ xmax = 8.52
+ text = "job"
+ intervals [32]:
+ xmin = 8.52
+ xmax = 8.59
+ text = "i"
+ intervals [33]:
+ xmin = 8.59
+ xmax = 8.75
+ text = "think"
+ intervals [34]:
+ xmin = 8.75
+ xmax = 8.88
+ text = "it's"
+ intervals [35]:
+ xmin = 8.88
+ xmax = 9.35
+ text = "very"
+ intervals [36]:
+ xmin = 9.35
+ xmax = 9.8
+ text = "important"
+ intervals [37]:
+ xmin = 9.8
+ xmax = 9.87
+ text = "to"
+ intervals [38]:
+ xmin = 9.87
+ xmax = 9.99
+ text = "get"
+ intervals [39]:
+ xmin = 9.99
+ xmax = 10.03
+ text = "a"
+ intervals [40]:
+ xmin = 10.03
+ xmax = 10.17
+ text = "good"
+ intervals [41]:
+ xmin = 10.17
+ xmax = 10.56
+ text = "sleep"
+ intervals [42]:
+ xmin = 10.56
+ xmax = 11.14
+ text = "during"
+ intervals [43]:
+ xmin = 11.14
+ xmax = 11.32
+ text = "your"
+ intervals [44]:
+ xmin = 11.32
+ xmax = 11.77
+ text = "weekend"
+ intervals [45]:
+ xmin = 11.77
+ xmax = 12.4
+ text = "because"
+ intervals [46]:
+ xmin = 12.4
+ xmax = 12.95
+ text = "when"
+ intervals [47]:
+ xmin = 12.95
+ xmax = 13.04
+ text = "you"
+ intervals [48]:
+ xmin = 13.04
+ xmax = 13.19
+ text = "have"
+ intervals [49]:
+ xmin = 13.19
+ xmax = 13.27
+ text = "to"
+ intervals [50]:
+ xmin = 13.27
+ xmax = 13.44
+ text = "work"
+ intervals [51]:
+ xmin = 13.44
+ xmax = 13.58
+ text = "on"
+ intervals [52]:
+ xmin = 13.58
+ xmax = 13.96
+ text = "monday"
+ intervals [53]:
+ xmin = 13.96
+ xmax = 14.1
+ text = "through"
+ intervals [54]:
+ xmin = 14.1
+ xmax = 14.75
+ text = "friday"
+ intervals [55]:
+ xmin = 14.75
+ xmax = 15.41
+ text = ""
+ intervals [56]:
+ xmin = 15.41
+ xmax = 15.53
+ text = "the"
+ intervals [57]:
+ xmin = 15.53
+ xmax = 15.75
+ text = "whole"
+ intervals [58]:
+ xmin = 15.75
+ xmax = 16.09
+ text = "week"
+ intervals [59]:
+ xmin = 16.09
+ xmax = 16.28
+ text = ""
+ intervals [60]:
+ xmin = 16.28
+ xmax = 16.42
+ text = "you"
+ intervals [61]:
+ xmin = 16.42
+ xmax = 16.49
+ text = "are"
+ intervals [62]:
+ xmin = 16.49
+ xmax = 16.73
+ text = "very"
+ intervals [63]:
+ xmin = 16.73
+ xmax = 17.59
+ text = "tired"
+ intervals [64]:
+ xmin = 17.59
+ xmax = 17.83
+ text = ""
+ intervals [65]:
+ xmin = 17.83
+ xmax = 18.29
+ text = "so"
+ intervals [66]:
+ xmin = 18.29
+ xmax = 18.55
+ text = "getting"
+ intervals [67]:
+ xmin = 18.55
+ xmax = 18.61
+ text = "a"
+ intervals [68]:
+ xmin = 18.61
+ xmax = 18.78
+ text = "good"
+ intervals [69]:
+ xmin = 18.78
+ xmax = 19.08
+ text = "rest"
+ intervals [70]:
+ xmin = 19.08
+ xmax = 19.21
+ text = "is"
+ intervals [71]:
+ xmin = 19.21
+ xmax = 19.3
+ text = "as"
+ intervals [72]:
+ xmin = 19.3
+ xmax = 19.77
+ text = "important"
+ intervals [73]:
+ xmin = 19.77
+ xmax = 20.16
+ text = "as"
+ intervals [74]:
+ xmin = 20.16
+ xmax = 20.3
+ text = ""
+ intervals [75]:
+ xmin = 20.3
+ xmax = 20.66
+ text = "complain"
+ intervals [76]:
+ xmin = 20.66
+ xmax = 20.75
+ text = "to"
+ intervals [77]:
+ xmin = 20.75
+ xmax = 21.09
+ text = "jaw"
+ intervals [78]:
+ xmin = 21.09
+ xmax = 21.3
+ text = "or"
+ intervals [79]:
+ xmin = 21.3
+ xmax = 21.79
+ text = "completing"
+ intervals [80]:
+ xmin = 21.79
+ xmax = 21.9
+ text = "an"
+ intervals [81]:
+ xmin = 21.9
+ xmax = 22.23
+ text = "excellent"
+ intervals [82]:
+ xmin = 22.23
+ xmax = 22.64
+ text = "job"
+ intervals [83]:
+ xmin = 22.64
+ xmax = 23.04
+ text = ""
+ intervals [84]:
+ xmin = 23.04
+ xmax = 23.17
+ text = "in"
+ intervals [85]:
+ xmin = 23.17
+ xmax = 23.29
+ text = "my"
+ intervals [86]:
+ xmin = 23.29
+ xmax = 23.56
+ text = "spare"
+ intervals [87]:
+ xmin = 23.56
+ xmax = 23.8
+ text = "time"
+ intervals [88]:
+ xmin = 23.8
+ xmax = 23.88
+ text = "if"
+ intervals [89]:
+ xmin = 23.88
+ xmax = 23.98
+ text = "i"
+ intervals [90]:
+ xmin = 23.98
+ xmax = 24.18
+ text = "feel"
+ intervals [91]:
+ xmin = 24.18
+ xmax = 24.84
+ text = "okay"
+ intervals [92]:
+ xmin = 24.84
+ xmax = 25.07
+ text = "i"
+ intervals [93]:
+ xmin = 25.07
+ xmax = 25.1
+ text = ""
+ intervals [94]:
+ xmin = 25.1
+ xmax = 25.38
+ text = "like"
+ intervals [95]:
+ xmin = 25.38
+ xmax = 25.44
+ text = "to"
+ intervals [96]:
+ xmin = 25.44
+ xmax = 25.55
+ text = "go"
+ intervals [97]:
+ xmin = 25.55
+ xmax = 25.79
+ text = "for"
+ intervals [98]:
+ xmin = 25.79
+ xmax = 25.83
+ text = "a"
+ intervals [99]:
+ xmin = 25.83
+ xmax = 26.12
+ text = "hike"
+ intervals [100]:
+ xmin = 26.12
+ xmax = 26.21
+ text = "in"
+ intervals [101]:
+ xmin = 26.21
+ xmax = 26.81
+ text = "nature"
+ intervals [102]:
+ xmin = 26.81
+ xmax = 27.11
+ text = ""
+ intervals [103]:
+ xmin = 27.11
+ xmax = 27.45
+ text = "sometimes"
+ intervals [104]:
+ xmin = 27.45
+ xmax = 27.51
+ text = "i"
+ intervals [105]:
+ xmin = 27.51
+ xmax = 27.74
+ text = "try"
+ intervals [106]:
+ xmin = 27.74
+ xmax = 27.88
+ text = "to"
+ intervals [107]:
+ xmin = 27.88
+ xmax = 28.37
+ text = "organize"
+ intervals [108]:
+ xmin = 28.37
+ xmax = 28.94
+ text = "something"
+ intervals [109]:
+ xmin = 28.94
+ xmax = 28.98
+ text = ""
+ intervals [110]:
+ xmin = 28.98
+ xmax = 29.19
+ text = "for"
+ intervals [111]:
+ xmin = 29.19
+ xmax = 29.32
+ text = "my"
+ intervals [112]:
+ xmin = 29.32
+ xmax = 29.89
+ text = "friends"
+ intervals [113]:
+ xmin = 29.89
+ xmax = 29.92
+ text = ""
+ intervals [114]:
+ xmin = 29.92
+ xmax = 29.95
+ text = "i"
+ intervals [115]:
+ xmin = 29.95
+ xmax = 30.2
+ text = ""
+ intervals [116]:
+ xmin = 30.2
+ xmax = 30.73
+ text = "volunteer"
+ intervals [117]:
+ xmin = 30.73
+ xmax = 30.86
+ text = "at"
+ intervals [118]:
+ xmin = 30.86
+ xmax = 30.97
+ text = "the"
+ intervals [119]:
+ xmin = 30.97
+ xmax = 31.38
+ text = "buddhist"
+ intervals [120]:
+ xmin = 31.38
+ xmax = 31.83
+ text = "temple"
+ intervals [121]:
+ xmin = 31.83
+ xmax = 31.94
+ text = "on"
+ intervals [122]:
+ xmin = 31.94
+ xmax = 32.01
+ text = "the"
+ intervals [123]:
+ xmin = 32.01
+ xmax = 32.6
+ text = "weekend"
+ intervals [124]:
+ xmin = 32.6
+ xmax = 33.01
+ text = "or"
+ intervals [125]:
+ xmin = 33.01
+ xmax = 33.24
+ text = "i"
+ intervals [126]:
+ xmin = 33.24
+ xmax = 33.62
+ text = "can"
+ intervals [127]:
+ xmin = 33.62
+ xmax = 33.91
+ text = "just"
+ intervals [128]:
+ xmin = 33.91
+ xmax = 34.3
+ text = "walk"
+ intervals [129]:
+ xmin = 34.3
+ xmax = 34.69
+ text = "around"
+ intervals [130]:
+ xmin = 34.69
+ xmax = 35.08
+ text = "enjoying"
+ intervals [131]:
+ xmin = 35.08
+ xmax = 35.17
+ text = "the"
+ intervals [132]:
+ xmin = 35.17
+ xmax = 35.87
+ text = "sunshine"
+ intervals [133]:
+ xmin = 35.87
+ xmax = 36.15
+ text = ""
+ intervals [134]:
+ xmin = 36.15
+ xmax = 36.34
+ text = "i'd"
+ intervals [135]:
+ xmin = 36.34
+ xmax = 36.52
+ text = "like"
+ intervals [136]:
+ xmin = 36.52
+ xmax = 36.59
+ text = "to"
+ intervals [137]:
+ xmin = 36.59
+ xmax = 36.74
+ text = "have"
+ intervals [138]:
+ xmin = 36.74
+ xmax = 36.79
+ text = "a"
+ intervals [139]:
+ xmin = 36.79
+ xmax = 37.06
+ text = "healthy"
+ intervals [140]:
+ xmin = 37.06
+ xmax = 37.66
+ text = "lifestyle"
+ intervals [141]:
+ xmin = 37.66
+ xmax = 38.06
+ text = "considering"
+ intervals [142]:
+ xmin = 38.06
+ xmax = 38.17
+ text = "how"
+ intervals [143]:
+ xmin = 38.17
+ xmax = 38.38
+ text = "much"
+ intervals [144]:
+ xmin = 38.38
+ xmax = 38.74
+ text = "time"
+ intervals [145]:
+ xmin = 38.74
+ xmax = 38.81
+ text = "i"
+ intervals [146]:
+ xmin = 38.81
+ xmax = 39.18
+ text = "spend"
+ intervals [147]:
+ xmin = 39.18
+ xmax = 39.29
+ text = "at"
+ intervals [148]:
+ xmin = 39.29
+ xmax = 39.84
+ text = "work"
+ intervals [149]:
+ xmin = 39.84
+ xmax = 40.29
+ text = ""
+ intervals [150]:
+ xmin = 40.29
+ xmax = 40.52
+ text = "i"
+ intervals [151]:
+ xmin = 40.52
+ xmax = 40.79
+ text = "always"
+ intervals [152]:
+ xmin = 40.79
+ xmax = 41.28
+ text = "try"
+ intervals [153]:
+ xmin = 41.28
+ xmax = 41.47
+ text = "to"
+ intervals [154]:
+ xmin = 41.47
+ xmax = 41.85
+ text = "move"
+ intervals [155]:
+ xmin = 41.85
+ xmax = 42
+ text = "as"
+ intervals [156]:
+ xmin = 42
+ xmax = 42.22
+ text = "much"
+ intervals [157]:
+ xmin = 42.22
+ xmax = 42.31
+ text = "as"
+ intervals [158]:
+ xmin = 42.31
+ xmax = 42.4
+ text = "i"
+ intervals [159]:
+ xmin = 42.4
+ xmax = 42.76
+ text = "can"
+ intervals [160]:
+ xmin = 42.76
+ xmax = 42.89
+ text = "when"
+ intervals [161]:
+ xmin = 42.89
+ xmax = 42.98
+ text = "i'm"
+ intervals [162]:
+ xmin = 42.98
+ xmax = 43.18
+ text = "not"
+ intervals [163]:
+ xmin = 43.18
+ xmax = 43.76
+ text = "working"
+ intervals [164]:
+ xmin = 43.76
+ xmax = 44.5
+ text = ""
+ intervals [165]:
+ xmin = 44.5
+ xmax = 45.19
+ text = "and"
+ intervals [166]:
+ xmin = 45.19
+ xmax = 45.32
+ text = "on"
+ intervals [167]:
+ xmin = 45.32
+ xmax = 45.49
+ text = "other"
+ intervals [168]:
+ xmin = 45.49
+ xmax = 45.82
+ text = "days"
+ intervals [169]:
+ xmin = 45.82
+ xmax = 45.96
+ text = "when"
+ intervals [170]:
+ xmin = 45.96
+ xmax = 46.16
+ text = "i'm"
+ intervals [171]:
+ xmin = 46.16
+ xmax = 46.65
+ text = "free"
+ intervals [172]:
+ xmin = 46.65
+ xmax = 46.86
+ text = "i"
+ intervals [173]:
+ xmin = 46.86
+ xmax = 47.16
+ text = "like"
+ intervals [174]:
+ xmin = 47.16
+ xmax = 47.39
+ text = "to"
+ intervals [175]:
+ xmin = 47.39
+ xmax = 47.86
+ text = "listen"
+ intervals [176]:
+ xmin = 47.86
+ xmax = 48.03
+ text = "to"
+ intervals [177]:
+ xmin = 48.03
+ xmax = 48.41
+ text = "music"
+ intervals [178]:
+ xmin = 48.41
+ xmax = 48.73
+ text = "and"
+ intervals [179]:
+ xmin = 48.73
+ xmax = 48.76
+ text = ""
+ intervals [180]:
+ xmin = 48.76
+ xmax = 49.01
+ text = "we're"
+ intervals [181]:
+ xmin = 49.01
+ xmax = 49.3
+ text = "watch"
+ intervals [182]:
+ xmin = 49.3
+ xmax = 49.38
+ text = "a"
+ intervals [183]:
+ xmin = 49.38
+ xmax = 50.05
+ text = "documentary"
+ intervals [184]:
+ xmin = 50.05
+ xmax = 50.51
+ text = "movies"
+ intervals [185]:
+ xmin = 50.51
+ xmax = 50.82
+ text = "on"
+ intervals [186]:
+ xmin = 50.82
+ xmax = 51.11
+ text = "my"
+ intervals [187]:
+ xmin = 51.11
+ xmax = 51.81
+ text = "laptop"
+ intervals [188]:
+ xmin = 51.81
+ xmax = 52.14
+ text = ""
+ intervals [189]:
+ xmin = 52.14
+ xmax = 52.44
+ text = "but"
+ intervals [190]:
+ xmin = 52.44
+ xmax = 52.86
+ text = "sometimes"
+ intervals [191]:
+ xmin = 52.86
+ xmax = 52.93
+ text = "it"
+ intervals [192]:
+ xmin = 52.93
+ xmax = 53.13
+ text = "just"
+ intervals [193]:
+ xmin = 53.13
+ xmax = 53.61
+ text = "sleep"
+ intervals [194]:
+ xmin = 53.61
+ xmax = 53.65
+ text = ""
+ intervals [195]:
+ xmin = 53.65
+ xmax = 53.83
+ text = "i"
+ intervals [196]:
+ xmin = 53.83
+ xmax = 54.27
+ text = "especially"
+ intervals [197]:
+ xmin = 54.27
+ xmax = 54.61
+ text = "liked"
+ intervals [198]:
+ xmin = 54.61
+ xmax = 55.01
+ text = "watching"
+ intervals [199]:
+ xmin = 55.01
+ xmax = 55.62
+ text = "japanese"
+ intervals [200]:
+ xmin = 55.62
+ xmax = 55.91
+ text = "anime"
+ intervals [201]:
+ xmin = 55.91
+ xmax = 56.33
+ text = "i"
+ intervals [202]:
+ xmin = 56.33
+ xmax = 56.85
+ text = ""
+ intervals [203]:
+ xmin = 56.85
+ xmax = 57.12
+ text = "think"
+ intervals [204]:
+ xmin = 57.12
+ xmax = 57.43
+ text = "watching"
+ intervals [205]:
+ xmin = 57.43
+ xmax = 57.62
+ text = "a"
+ intervals [206]:
+ xmin = 57.62
+ xmax = 57.79
+ text = "me"
+ intervals [207]:
+ xmin = 57.79
+ xmax = 58.09
+ text = "is"
+ intervals [208]:
+ xmin = 58.09
+ xmax = 58.39
+ text = "anime"
+ intervals [209]:
+ xmin = 58.39
+ xmax = 59.06
+ text = "is"
+ intervals [210]:
+ xmin = 59.06
+ xmax = 59.31
+ text = "very"
+ intervals [211]:
+ xmin = 59.31
+ xmax = 59.67
+ text = "helpful"
+ intervals [212]:
+ xmin = 59.67
+ xmax = 59.81
+ text = "for"
+ intervals [213]:
+ xmin = 59.81
+ xmax = 59.98
+ text = "me"
+ intervals [214]:
+ xmin = 59.98
+ xmax = 60.28
+ text = "to"
+ intervals [215]:
+ xmin = 60.28
+ xmax = 60.69
+ text = "learn"
+ intervals [216]:
+ xmin = 60.69
+ xmax = 60.78
+ text = "and"
+ intervals [217]:
+ xmin = 60.78
+ xmax = 61.21
+ text = "express"
+ intervals [218]:
+ xmin = 61.21
+ xmax = 61.89
+ text = "japanese"
+ intervals [219]:
+ xmin = 61.89
+ xmax = 62.42
+ text = "better"
+ intervals [220]:
+ xmin = 62.42
+ xmax = 64.097375
+ text = ""
+ item [2]:
+ class = "IntervalTier"
+ name = "phones"
+ xmin = 0
+ xmax = 64.097375
+ intervals: size = 684
+ intervals [1]:
+ xmin = 0
+ xmax = 1.42
+ text = ""
+ intervals [2]:
+ xmin = 1.42
+ xmax = 1.48
+ text = "DH"
+ intervals [3]:
+ xmin = 1.48
+ xmax = 1.52
+ text = "AH0"
+ intervals [4]:
+ xmin = 1.52
+ xmax = 1.62
+ text = "F"
+ intervals [5]:
+ xmin = 1.62
+ xmax = 1.72
+ text = "ER1"
+ intervals [6]:
+ xmin = 1.72
+ xmax = 1.75
+ text = "S"
+ intervals [7]:
+ xmin = 1.75
+ xmax = 1.78
+ text = "T"
+ intervals [8]:
+ xmin = 1.78
+ xmax = 1.81
+ text = "TH"
+ intervals [9]:
+ xmin = 1.81
+ xmax = 1.88
+ text = "IH1"
+ intervals [10]:
+ xmin = 1.88
+ xmax = 1.97
+ text = "NG"
+ intervals [11]:
+ xmin = 1.97
+ xmax = 2.04
+ text = "AY1"
+ intervals [12]:
+ xmin = 2.04
+ xmax = 2.08
+ text = "L"
+ intervals [13]:
+ xmin = 2.08
+ xmax = 2.17
+ text = "AY1"
+ intervals [14]:
+ xmin = 2.17
+ xmax = 2.21
+ text = "K"
+ intervals [15]:
+ xmin = 2.21
+ xmax = 2.24
+ text = "T"
+ intervals [16]:
+ xmin = 2.24
+ xmax = 2.28
+ text = "IH0"
+ intervals [17]:
+ xmin = 2.28
+ xmax = 2.34
+ text = "D"
+ intervals [18]:
+ xmin = 2.34
+ xmax = 2.47
+ text = "UW1"
+ intervals [19]:
+ xmin = 2.47
+ xmax = 2.58
+ text = "AA1"
+ intervals [20]:
+ xmin = 2.58
+ xmax = 2.63
+ text = "N"
+ intervals [21]:
+ xmin = 2.63
+ xmax = 2.68
+ text = "W"
+ intervals [22]:
+ xmin = 2.68
+ xmax = 2.78
+ text = "IY1"
+ intervals [23]:
+ xmin = 2.78
+ xmax = 2.88
+ text = "K"
+ intervals [24]:
+ xmin = 2.88
+ xmax = 3.01
+ text = "EH2"
+ intervals [25]:
+ xmin = 3.01
+ xmax = 3.14
+ text = "N"
+ intervals [26]:
+ xmin = 3.14
+ xmax = 3.2
+ text = "D"
+ intervals [27]:
+ xmin = 3.2
+ xmax = 3.32
+ text = "Z"
+ intervals [28]:
+ xmin = 3.32
+ xmax = 3.47
+ text = "IH1"
+ intervals [29]:
+ xmin = 3.47
+ xmax = 3.58
+ text = "Z"
+ intervals [30]:
+ xmin = 3.58
+ xmax = 3.64
+ text = "R"
+ intervals [31]:
+ xmin = 3.64
+ xmax = 3.7
+ text = "IY0"
+ intervals [32]:
+ xmin = 3.7
+ xmax = 3.8
+ text = "L"
+ intervals [33]:
+ xmin = 3.8
+ xmax = 3.96
+ text = "AE1"
+ intervals [34]:
+ xmin = 3.96
+ xmax = 4.02
+ text = "K"
+ intervals [35]:
+ xmin = 4.02
+ xmax = 4.11
+ text = "S"
+ intervals [36]:
+ xmin = 4.11
+ xmax = 4.2
+ text = "IH0"
+ intervals [37]:
+ xmin = 4.2
+ xmax = 4.41
+ text = "NG"
+ intervals [38]:
+ xmin = 4.41
+ xmax = 4.52
+ text = ""
+ intervals [39]:
+ xmin = 4.52
+ xmax = 4.97
+ text = "AH0"
+ intervals [40]:
+ xmin = 4.97
+ xmax = 5.01
+ text = "N"
+ intervals [41]:
+ xmin = 5.01
+ xmax = 5.05
+ text = "D"
+ intervals [42]:
+ xmin = 5.05
+ xmax = 5.14
+ text = "AY1"
+ intervals [43]:
+ xmin = 5.14
+ xmax = 5.19
+ text = "TH"
+ intervals [44]:
+ xmin = 5.19
+ xmax = 5.25
+ text = "IH1"
+ intervals [45]:
+ xmin = 5.25
+ xmax = 5.29
+ text = "NG"
+ intervals [46]:
+ xmin = 5.29
+ xmax = 5.33
+ text = "K"
+ intervals [47]:
+ xmin = 5.33
+ xmax = 5.36
+ text = "AY1"
+ intervals [48]:
+ xmin = 5.36
+ xmax = 5.41
+ text = "L"
+ intervals [49]:
+ xmin = 5.41
+ xmax = 5.44
+ text = "G"
+ intervals [50]:
+ xmin = 5.44
+ xmax = 5.5
+ text = "OW1"
+ intervals [51]:
+ xmin = 5.5
+ xmax = 5.68
+ text = "SH"
+ intervals [52]:
+ xmin = 5.68
+ xmax = 5.87
+ text = "AA1"
+ intervals [53]:
+ xmin = 5.87
+ xmax = 5.92
+ text = "P"
+ intervals [54]:
+ xmin = 5.92
+ xmax = 5.96
+ text = "IH0"
+ intervals [55]:
+ xmin = 5.96
+ xmax = 6
+ text = "NG"
+ intervals [56]:
+ xmin = 6
+ xmax = 6.06
+ text = "IH0"
+ intervals [57]:
+ xmin = 6.06
+ xmax = 6.11
+ text = "F"
+ intervals [58]:
+ xmin = 6.11
+ xmax = 6.16
+ text = "AY1"
+ intervals [59]:
+ xmin = 6.16
+ xmax = 6.29
+ text = "M"
+ intervals [60]:
+ xmin = 6.29
+ xmax = 6.35
+ text = "N"
+ intervals [61]:
+ xmin = 6.35
+ xmax = 6.48
+ text = "AA1"
+ intervals [62]:
+ xmin = 6.48
+ xmax = 6.54
+ text = "T"
+ intervals [63]:
+ xmin = 6.54
+ xmax = 6.58
+ text = "DH"
+ intervals [64]:
+ xmin = 6.58
+ xmax = 6.64
+ text = "AE1"
+ intervals [65]:
+ xmin = 6.64
+ xmax = 6.7
+ text = "T"
+ intervals [66]:
+ xmin = 6.7
+ xmax = 6.78
+ text = "T"
+ intervals [67]:
+ xmin = 6.78
+ xmax = 6.93
+ text = "AY1"
+ intervals [68]:
+ xmin = 6.93
+ xmax = 7.08
+ text = "ER0"
+ intervals [69]:
+ xmin = 7.08
+ xmax = 7.19
+ text = "D"
+ intervals [70]:
+ xmin = 7.19
+ xmax = 7.45
+ text = ""
+ intervals [71]:
+ xmin = 7.45
+ xmax = 7.59
+ text = "S"
+ intervals [72]:
+ xmin = 7.59
+ xmax = 7.62
+ text = "OW1"
+ intervals [73]:
+ xmin = 7.62
+ xmax = 7.66
+ text = "DH"
+ intervals [74]:
+ xmin = 7.66
+ xmax = 7.71
+ text = "AE1"
+ intervals [75]:
+ xmin = 7.71
+ xmax = 7.74
+ text = "T"
+ intervals [76]:
+ xmin = 7.74
+ xmax = 7.77
+ text = "Y"
+ intervals [77]:
+ xmin = 7.77
+ xmax = 7.85
+ text = "UW1"
+ intervals [78]:
+ xmin = 7.85
+ xmax = 7.92
+ text = "S"
+ intervals [79]:
+ xmin = 7.92
+ xmax = 7.97
+ text = "T"
+ intervals [80]:
+ xmin = 7.97
+ xmax = 8.02
+ text = "AA1"
+ intervals [81]:
+ xmin = 8.02
+ xmax = 8.05
+ text = "R"
+ intervals [82]:
+ xmin = 8.05
+ xmax = 8.08
+ text = "T"
+ intervals [83]:
+ xmin = 8.08
+ xmax = 8.11
+ text = "AH0"
+ intervals [84]:
+ xmin = 8.11
+ xmax = 8.14
+ text = "D"
+ intervals [85]:
+ xmin = 8.14
+ xmax = 8.17
+ text = "B"
+ intervals [86]:
+ xmin = 8.17
+ xmax = 8.24
+ text = "AY1"
+ intervals [87]:
+ xmin = 8.24
+ xmax = 8.35
+ text = "JH"
+ intervals [88]:
+ xmin = 8.35
+ xmax = 8.48
+ text = "AA1"
+ intervals [89]:
+ xmin = 8.48
+ xmax = 8.52
+ text = "B"
+ intervals [90]:
+ xmin = 8.52
+ xmax = 8.59
+ text = "AY1"
+ intervals [91]:
+ xmin = 8.59
+ xmax = 8.64
+ text = "TH"
+ intervals [92]:
+ xmin = 8.64
+ xmax = 8.69
+ text = "IH1"
+ intervals [93]:
+ xmin = 8.69
+ xmax = 8.72
+ text = "NG"
+ intervals [94]:
+ xmin = 8.72
+ xmax = 8.75
+ text = "K"
+ intervals [95]:
+ xmin = 8.75
+ xmax = 8.79
+ text = "IH1"
+ intervals [96]:
+ xmin = 8.79
+ xmax = 8.84
+ text = "T"
+ intervals [97]:
+ xmin = 8.84
+ xmax = 8.88
+ text = "S"
+ intervals [98]:
+ xmin = 8.88
+ xmax = 9.08
+ text = "V"
+ intervals [99]:
+ xmin = 9.08
+ xmax = 9.2
+ text = "EH1"
+ intervals [100]:
+ xmin = 9.2
+ xmax = 9.28
+ text = "R"
+ intervals [101]:
+ xmin = 9.28
+ xmax = 9.35
+ text = "IY0"
+ intervals [102]:
+ xmin = 9.35
+ xmax = 9.4
+ text = "IH0"
+ intervals [103]:
+ xmin = 9.4
+ xmax = 9.46
+ text = "M"
+ intervals [104]:
+ xmin = 9.46
+ xmax = 9.55
+ text = "P"
+ intervals [105]:
+ xmin = 9.55
+ xmax = 9.63
+ text = "AO1"
+ intervals [106]:
+ xmin = 9.63
+ xmax = 9.68
+ text = "R"
+ intervals [107]:
+ xmin = 9.68
+ xmax = 9.71
+ text = "T"
+ intervals [108]:
+ xmin = 9.71
+ xmax = 9.74
+ text = "AH0"
+ intervals [109]:
+ xmin = 9.74
+ xmax = 9.77
+ text = "N"
+ intervals [110]:
+ xmin = 9.77
+ xmax = 9.8
+ text = "T"
+ intervals [111]:
+ xmin = 9.8
+ xmax = 9.83
+ text = "T"
+ intervals [112]:
+ xmin = 9.83
+ xmax = 9.87
+ text = "IH0"
+ intervals [113]:
+ xmin = 9.87
+ xmax = 9.93
+ text = "G"
+ intervals [114]:
+ xmin = 9.93
+ xmax = 9.96
+ text = "EH1"
+ intervals [115]:
+ xmin = 9.96
+ xmax = 9.99
+ text = "T"
+ intervals [116]:
+ xmin = 9.99
+ xmax = 10.03
+ text = "AH0"
+ intervals [117]:
+ xmin = 10.03
+ xmax = 10.07
+ text = "G"
+ intervals [118]:
+ xmin = 10.07
+ xmax = 10.1
+ text = "IH0"
+ intervals [119]:
+ xmin = 10.1
+ xmax = 10.17
+ text = "D"
+ intervals [120]:
+ xmin = 10.17
+ xmax = 10.35
+ text = "S"
+ intervals [121]:
+ xmin = 10.35
+ xmax = 10.43
+ text = "L"
+ intervals [122]:
+ xmin = 10.43
+ xmax = 10.53
+ text = "IY1"
+ intervals [123]:
+ xmin = 10.53
+ xmax = 10.56
+ text = "P"
+ intervals [124]:
+ xmin = 10.56
+ xmax = 10.8
+ text = "D"
+ intervals [125]:
+ xmin = 10.8
+ xmax = 10.92
+ text = "ER1"
+ intervals [126]:
+ xmin = 10.92
+ xmax = 10.99
+ text = "IH0"
+ intervals [127]:
+ xmin = 10.99
+ xmax = 11.14
+ text = "NG"
+ intervals [128]:
+ xmin = 11.14
+ xmax = 11.2
+ text = "Y"
+ intervals [129]:
+ xmin = 11.2
+ xmax = 11.23
+ text = "UH1"
+ intervals [130]:
+ xmin = 11.23
+ xmax = 11.32
+ text = "R"
+ intervals [131]:
+ xmin = 11.32
+ xmax = 11.4
+ text = "W"
+ intervals [132]:
+ xmin = 11.4
+ xmax = 11.51
+ text = "IY1"
+ intervals [133]:
+ xmin = 11.51
+ xmax = 11.6
+ text = "K"
+ intervals [134]:
+ xmin = 11.6
+ xmax = 11.68
+ text = "EH2"
+ intervals [135]:
+ xmin = 11.68
+ xmax = 11.74
+ text = "N"
+ intervals [136]:
+ xmin = 11.74
+ xmax = 11.77
+ text = "D"
+ intervals [137]:
+ xmin = 11.77
+ xmax = 11.8
+ text = "B"
+ intervals [138]:
+ xmin = 11.8
+ xmax = 11.88
+ text = "IH0"
+ intervals [139]:
+ xmin = 11.88
+ xmax = 12
+ text = "K"
+ intervals [140]:
+ xmin = 12
+ xmax = 12.26
+ text = "AH1"
+ intervals [141]:
+ xmin = 12.26
+ xmax = 12.4
+ text = "Z"
+ intervals [142]:
+ xmin = 12.4
+ xmax = 12.6
+ text = "W"
+ intervals [143]:
+ xmin = 12.6
+ xmax = 12.88
+ text = "EH1"
+ intervals [144]:
+ xmin = 12.88
+ xmax = 12.95
+ text = "N"
+ intervals [145]:
+ xmin = 12.95
+ xmax = 12.99
+ text = "Y"
+ intervals [146]:
+ xmin = 12.99
+ xmax = 13.04
+ text = "UW1"
+ intervals [147]:
+ xmin = 13.04
+ xmax = 13.07
+ text = "HH"
+ intervals [148]:
+ xmin = 13.07
+ xmax = 13.16
+ text = "AE1"
+ intervals [149]:
+ xmin = 13.16
+ xmax = 13.19
+ text = "V"
+ intervals [150]:
+ xmin = 13.19
+ xmax = 13.22
+ text = "T"
+ intervals [151]:
+ xmin = 13.22
+ xmax = 13.27
+ text = "UW1"
+ intervals [152]:
+ xmin = 13.27
+ xmax = 13.32
+ text = "W"
+ intervals [153]:
+ xmin = 13.32
+ xmax = 13.4
+ text = "ER1"
+ intervals [154]:
+ xmin = 13.4
+ xmax = 13.44
+ text = "K"
+ intervals [155]:
+ xmin = 13.44
+ xmax = 13.51
+ text = "AA1"
+ intervals [156]:
+ xmin = 13.51
+ xmax = 13.58
+ text = "N"
+ intervals [157]:
+ xmin = 13.58
+ xmax = 13.66
+ text = "M"
+ intervals [158]:
+ xmin = 13.66
+ xmax = 13.76
+ text = "AH1"
+ intervals [159]:
+ xmin = 13.76
+ xmax = 13.81
+ text = "N"
+ intervals [160]:
+ xmin = 13.81
+ xmax = 13.85
+ text = "D"
+ intervals [161]:
+ xmin = 13.85
+ xmax = 13.96
+ text = "EY2"
+ intervals [162]:
+ xmin = 13.96
+ xmax = 14.01
+ text = "TH"
+ intervals [163]:
+ xmin = 14.01
+ xmax = 14.04
+ text = "R"
+ intervals [164]:
+ xmin = 14.04
+ xmax = 14.1
+ text = "UW1"
+ intervals [165]:
+ xmin = 14.1
+ xmax = 14.17
+ text = "F"
+ intervals [166]:
+ xmin = 14.17
+ xmax = 14.26
+ text = "R"
+ intervals [167]:
+ xmin = 14.26
+ xmax = 14.4
+ text = "AY1"
+ intervals [168]:
+ xmin = 14.4
+ xmax = 14.45
+ text = "D"
+ intervals [169]:
+ xmin = 14.45
+ xmax = 14.75
+ text = "EY2"
+ intervals [170]:
+ xmin = 14.75
+ xmax = 15.41
+ text = ""
+ intervals [171]:
+ xmin = 15.41
+ xmax = 15.49
+ text = "DH"
+ intervals [172]:
+ xmin = 15.49
+ xmax = 15.53
+ text = "AH1"
+ intervals [173]:
+ xmin = 15.53
+ xmax = 15.62
+ text = "HH"
+ intervals [174]:
+ xmin = 15.62
+ xmax = 15.67
+ text = "OW1"
+ intervals [175]:
+ xmin = 15.67
+ xmax = 15.75
+ text = "L"
+ intervals [176]:
+ xmin = 15.75
+ xmax = 15.8
+ text = "W"
+ intervals [177]:
+ xmin = 15.8
+ xmax = 15.94
+ text = "IY1"
+ intervals [178]:
+ xmin = 15.94
+ xmax = 16.09
+ text = "K"
+ intervals [179]:
+ xmin = 16.09
+ xmax = 16.28
+ text = ""
+ intervals [180]:
+ xmin = 16.28
+ xmax = 16.38
+ text = "Y"
+ intervals [181]:
+ xmin = 16.38
+ xmax = 16.42
+ text = "UW1"
+ intervals [182]:
+ xmin = 16.42
+ xmax = 16.49
+ text = "ER0"
+ intervals [183]:
+ xmin = 16.49
+ xmax = 16.55
+ text = "V"
+ intervals [184]:
+ xmin = 16.55
+ xmax = 16.58
+ text = "EH1"
+ intervals [185]:
+ xmin = 16.58
+ xmax = 16.65
+ text = "R"
+ intervals [186]:
+ xmin = 16.65
+ xmax = 16.73
+ text = "IY0"
+ intervals [187]:
+ xmin = 16.73
+ xmax = 16.92
+ text = "T"
+ intervals [188]:
+ xmin = 16.92
+ xmax = 17.08
+ text = "AY1"
+ intervals [189]:
+ xmin = 17.08
+ xmax = 17.22
+ text = "ER0"
+ intervals [190]:
+ xmin = 17.22
+ xmax = 17.59
+ text = "D"
+ intervals [191]:
+ xmin = 17.59
+ xmax = 17.83
+ text = ""
+ intervals [192]:
+ xmin = 17.83
+ xmax = 18.02
+ text = "S"
+ intervals [193]:
+ xmin = 18.02
+ xmax = 18.29
+ text = "OW1"
+ intervals [194]:
+ xmin = 18.29
+ xmax = 18.37
+ text = "G"
+ intervals [195]:
+ xmin = 18.37
+ xmax = 18.42
+ text = "IH1"
+ intervals [196]:
+ xmin = 18.42
+ xmax = 18.46
+ text = "T"
+ intervals [197]:
+ xmin = 18.46
+ xmax = 18.5
+ text = "IH0"
+ intervals [198]:
+ xmin = 18.5
+ xmax = 18.55
+ text = "NG"
+ intervals [199]:
+ xmin = 18.55
+ xmax = 18.61
+ text = "EY1"
+ intervals [200]:
+ xmin = 18.61
+ xmax = 18.67
+ text = "G"
+ intervals [201]:
+ xmin = 18.67
+ xmax = 18.73
+ text = "UH1"
+ intervals [202]:
+ xmin = 18.73
+ xmax = 18.78
+ text = "D"
+ intervals [203]:
+ xmin = 18.78
+ xmax = 18.86
+ text = "R"
+ intervals [204]:
+ xmin = 18.86
+ xmax = 18.97
+ text = "EH1"
+ intervals [205]:
+ xmin = 18.97
+ xmax = 19.05
+ text = "S"
+ intervals [206]:
+ xmin = 19.05
+ xmax = 19.08
+ text = "T"
+ intervals [207]:
+ xmin = 19.08
+ xmax = 19.13
+ text = "IH0"
+ intervals [208]:
+ xmin = 19.13
+ xmax = 19.21
+ text = "Z"
+ intervals [209]:
+ xmin = 19.21
+ xmax = 19.24
+ text = "EH1"
+ intervals [210]:
+ xmin = 19.24
+ xmax = 19.3
+ text = "Z"
+ intervals [211]:
+ xmin = 19.3
+ xmax = 19.34
+ text = "IH0"
+ intervals [212]:
+ xmin = 19.34
+ xmax = 19.38
+ text = "M"
+ intervals [213]:
+ xmin = 19.38
+ xmax = 19.48
+ text = "P"
+ intervals [214]:
+ xmin = 19.48
+ xmax = 19.55
+ text = "AO1"
+ intervals [215]:
+ xmin = 19.55
+ xmax = 19.59
+ text = "R"
+ intervals [216]:
+ xmin = 19.59
+ xmax = 19.62
+ text = "T"
+ intervals [217]:
+ xmin = 19.62
+ xmax = 19.65
+ text = "AH0"
+ intervals [218]:
+ xmin = 19.65
+ xmax = 19.68
+ text = "N"
+ intervals [219]:
+ xmin = 19.68
+ xmax = 19.77
+ text = "T"
+ intervals [220]:
+ xmin = 19.77
+ xmax = 19.94
+ text = "AE1"
+ intervals [221]:
+ xmin = 19.94
+ xmax = 20.16
+ text = "Z"
+ intervals [222]:
+ xmin = 20.16
+ xmax = 20.3
+ text = ""
+ intervals [223]:
+ xmin = 20.3
+ xmax = 20.39
+ text = "K"
+ intervals [224]:
+ xmin = 20.39
+ xmax = 20.43
+ text = "AH0"
+ intervals [225]:
+ xmin = 20.43
+ xmax = 20.46
+ text = "M"
+ intervals [226]:
+ xmin = 20.46
+ xmax = 20.53
+ text = "P"
+ intervals [227]:
+ xmin = 20.53
+ xmax = 20.59
+ text = "L"
+ intervals [228]:
+ xmin = 20.59
+ xmax = 20.63
+ text = "EY1"
+ intervals [229]:
+ xmin = 20.63
+ xmax = 20.66
+ text = "N"
+ intervals [230]:
+ xmin = 20.66
+ xmax = 20.69
+ text = "T"
+ intervals [231]:
+ xmin = 20.69
+ xmax = 20.75
+ text = "AH0"
+ intervals [232]:
+ xmin = 20.75
+ xmax = 20.87
+ text = "JH"
+ intervals [233]:
+ xmin = 20.87
+ xmax = 21.09
+ text = "AO1"
+ intervals [234]:
+ xmin = 21.09
+ xmax = 21.3
+ text = "ER0"
+ intervals [235]:
+ xmin = 21.3
+ xmax = 21.44
+ text = "K"
+ intervals [236]:
+ xmin = 21.44
+ xmax = 21.47
+ text = "AH0"
+ intervals [237]:
+ xmin = 21.47
+ xmax = 21.5
+ text = "M"
+ intervals [238]:
+ xmin = 21.5
+ xmax = 21.53
+ text = "P"
+ intervals [239]:
+ xmin = 21.53
+ xmax = 21.6
+ text = "L"
+ intervals [240]:
+ xmin = 21.6
+ xmax = 21.63
+ text = "IY1"
+ intervals [241]:
+ xmin = 21.63
+ xmax = 21.66
+ text = "T"
+ intervals [242]:
+ xmin = 21.66
+ xmax = 21.72
+ text = "IH0"
+ intervals [243]:
+ xmin = 21.72
+ xmax = 21.79
+ text = "NG"
+ intervals [244]:
+ xmin = 21.79
+ xmax = 21.83
+ text = "AH0"
+ intervals [245]:
+ xmin = 21.83
+ xmax = 21.9
+ text = "N"
+ intervals [246]:
+ xmin = 21.9
+ xmax = 21.98
+ text = "EH1"
+ intervals [247]:
+ xmin = 21.98
+ xmax = 22.03
+ text = "K"
+ intervals [248]:
+ xmin = 22.03
+ xmax = 22.07
+ text = "S"
+ intervals [249]:
+ xmin = 22.07
+ xmax = 22.11
+ text = "AH0"
+ intervals [250]:
+ xmin = 22.11
+ xmax = 22.14
+ text = "L"
+ intervals [251]:
+ xmin = 22.14
+ xmax = 22.17
+ text = "AH0"
+ intervals [252]:
+ xmin = 22.17
+ xmax = 22.2
+ text = "N"
+ intervals [253]:
+ xmin = 22.2
+ xmax = 22.23
+ text = "T"
+ intervals [254]:
+ xmin = 22.23
+ xmax = 22.34
+ text = "JH"
+ intervals [255]:
+ xmin = 22.34
+ xmax = 22.5
+ text = "AA1"
+ intervals [256]:
+ xmin = 22.5
+ xmax = 22.64
+ text = "B"
+ intervals [257]:
+ xmin = 22.64
+ xmax = 23.04
+ text = ""
+ intervals [258]:
+ xmin = 23.04
+ xmax = 23.14
+ text = "IH0"
+ intervals [259]:
+ xmin = 23.14
+ xmax = 23.17
+ text = "N"
+ intervals [260]:
+ xmin = 23.17
+ xmax = 23.2
+ text = "M"
+ intervals [261]:
+ xmin = 23.2
+ xmax = 23.29
+ text = "AY1"
+ intervals [262]:
+ xmin = 23.29
+ xmax = 23.36
+ text = "S"
+ intervals [263]:
+ xmin = 23.36
+ xmax = 23.41
+ text = "P"
+ intervals [264]:
+ xmin = 23.41
+ xmax = 23.52
+ text = "EH1"
+ intervals [265]:
+ xmin = 23.52
+ xmax = 23.56
+ text = "R"
+ intervals [266]:
+ xmin = 23.56
+ xmax = 23.65
+ text = "T"
+ intervals [267]:
+ xmin = 23.65
+ xmax = 23.76
+ text = "AY1"
+ intervals [268]:
+ xmin = 23.76
+ xmax = 23.8
+ text = "M"
+ intervals [269]:
+ xmin = 23.8
+ xmax = 23.85
+ text = "IH0"
+ intervals [270]:
+ xmin = 23.85
+ xmax = 23.88
+ text = "F"
+ intervals [271]:
+ xmin = 23.88
+ xmax = 23.98
+ text = "AY1"
+ intervals [272]:
+ xmin = 23.98
+ xmax = 24.04
+ text = "F"
+ intervals [273]:
+ xmin = 24.04
+ xmax = 24.13
+ text = "IY1"
+ intervals [274]:
+ xmin = 24.13
+ xmax = 24.18
+ text = "L"
+ intervals [275]:
+ xmin = 24.18
+ xmax = 24.26
+ text = "OW2"
+ intervals [276]:
+ xmin = 24.26
+ xmax = 24.39
+ text = "K"
+ intervals [277]:
+ xmin = 24.39
+ xmax = 24.84
+ text = "EY1"
+ intervals [278]:
+ xmin = 24.84
+ xmax = 25.07
+ text = "AY1"
+ intervals [279]:
+ xmin = 25.07
+ xmax = 25.1
+ text = ""
+ intervals [280]:
+ xmin = 25.1
+ xmax = 25.29
+ text = "L"
+ intervals [281]:
+ xmin = 25.29
+ xmax = 25.35
+ text = "AY1"
+ intervals [282]:
+ xmin = 25.35
+ xmax = 25.38
+ text = "K"
+ intervals [283]:
+ xmin = 25.38
+ xmax = 25.41
+ text = "T"
+ intervals [284]:
+ xmin = 25.41
+ xmax = 25.44
+ text = "IH0"
+ intervals [285]:
+ xmin = 25.44
+ xmax = 25.5
+ text = "G"
+ intervals [286]:
+ xmin = 25.5
+ xmax = 25.55
+ text = "OW1"
+ intervals [287]:
+ xmin = 25.55
+ xmax = 25.59
+ text = "F"
+ intervals [288]:
+ xmin = 25.59
+ xmax = 25.79
+ text = "ER0"
+ intervals [289]:
+ xmin = 25.79
+ xmax = 25.83
+ text = "AH0"
+ intervals [290]:
+ xmin = 25.83
+ xmax = 25.94
+ text = "HH"
+ intervals [291]:
+ xmin = 25.94
+ xmax = 26.06
+ text = "AY1"
+ intervals [292]:
+ xmin = 26.06
+ xmax = 26.12
+ text = "K"
+ intervals [293]:
+ xmin = 26.12
+ xmax = 26.17
+ text = "IH1"
+ intervals [294]:
+ xmin = 26.17
+ xmax = 26.21
+ text = "N"
+ intervals [295]:
+ xmin = 26.21
+ xmax = 26.27
+ text = "N"
+ intervals [296]:
+ xmin = 26.27
+ xmax = 26.4
+ text = "EY1"
+ intervals [297]:
+ xmin = 26.4
+ xmax = 26.53
+ text = "CH"
+ intervals [298]:
+ xmin = 26.53
+ xmax = 26.81
+ text = "ER0"
+ intervals [299]:
+ xmin = 26.81
+ xmax = 27.11
+ text = ""
+ intervals [300]:
+ xmin = 27.11
+ xmax = 27.21
+ text = "S"
+ intervals [301]:
+ xmin = 27.21
+ xmax = 27.25
+ text = "AH1"
+ intervals [302]:
+ xmin = 27.25
+ xmax = 27.28
+ text = "M"
+ intervals [303]:
+ xmin = 27.28
+ xmax = 27.31
+ text = "T"
+ intervals [304]:
+ xmin = 27.31
+ xmax = 27.38
+ text = "AY2"
+ intervals [305]:
+ xmin = 27.38
+ xmax = 27.41
+ text = "M"
+ intervals [306]:
+ xmin = 27.41
+ xmax = 27.45
+ text = "Z"
+ intervals [307]:
+ xmin = 27.45
+ xmax = 27.51
+ text = "AY1"
+ intervals [308]:
+ xmin = 27.51
+ xmax = 27.6
+ text = "T"
+ intervals [309]:
+ xmin = 27.6
+ xmax = 27.67
+ text = "R"
+ intervals [310]:
+ xmin = 27.67
+ xmax = 27.74
+ text = "AY1"
+ intervals [311]:
+ xmin = 27.74
+ xmax = 27.77
+ text = "T"
+ intervals [312]:
+ xmin = 27.77
+ xmax = 27.88
+ text = "AH0"
+ intervals [313]:
+ xmin = 27.88
+ xmax = 28.02
+ text = "AO1"
+ intervals [314]:
+ xmin = 28.02
+ xmax = 28.07
+ text = "R"
+ intervals [315]:
+ xmin = 28.07
+ xmax = 28.12
+ text = "G"
+ intervals [316]:
+ xmin = 28.12
+ xmax = 28.15
+ text = "AH0"
+ intervals [317]:
+ xmin = 28.15
+ xmax = 28.18
+ text = "N"
+ intervals [318]:
+ xmin = 28.18
+ xmax = 28.3
+ text = "AY2"
+ intervals [319]:
+ xmin = 28.3
+ xmax = 28.37
+ text = "Z"
+ intervals [320]:
+ xmin = 28.37
+ xmax = 28.42
+ text = "S"
+ intervals [321]:
+ xmin = 28.42
+ xmax = 28.47
+ text = "AH1"
+ intervals [322]:
+ xmin = 28.47
+ xmax = 28.5
+ text = "M"
+ intervals [323]:
+ xmin = 28.5
+ xmax = 28.53
+ text = "TH"
+ intervals [324]:
+ xmin = 28.53
+ xmax = 28.61
+ text = "IH0"
+ intervals [325]:
+ xmin = 28.61
+ xmax = 28.94
+ text = "NG"
+ intervals [326]:
+ xmin = 28.94
+ xmax = 28.98
+ text = ""
+ intervals [327]:
+ xmin = 28.98
+ xmax = 29.08
+ text = "F"
+ intervals [328]:
+ xmin = 29.08
+ xmax = 29.13
+ text = "AO1"
+ intervals [329]:
+ xmin = 29.13
+ xmax = 29.19
+ text = "R"
+ intervals [330]:
+ xmin = 29.19
+ xmax = 29.23
+ text = "M"
+ intervals [331]:
+ xmin = 29.23
+ xmax = 29.32
+ text = "AY1"
+ intervals [332]:
+ xmin = 29.32
+ xmax = 29.41
+ text = "F"
+ intervals [333]:
+ xmin = 29.41
+ xmax = 29.49
+ text = "R"
+ intervals [334]:
+ xmin = 29.49
+ xmax = 29.6
+ text = "EH1"
+ intervals [335]:
+ xmin = 29.6
+ xmax = 29.65
+ text = "N"
+ intervals [336]:
+ xmin = 29.65
+ xmax = 29.7
+ text = "D"
+ intervals [337]:
+ xmin = 29.7
+ xmax = 29.89
+ text = "Z"
+ intervals [338]:
+ xmin = 29.89
+ xmax = 29.92
+ text = ""
+ intervals [339]:
+ xmin = 29.92
+ xmax = 29.95
+ text = "AY1"
+ intervals [340]:
+ xmin = 29.95
+ xmax = 30.2
+ text = ""
+ intervals [341]:
+ xmin = 30.2
+ xmax = 30.26
+ text = "V"
+ intervals [342]:
+ xmin = 30.26
+ xmax = 30.39
+ text = "AA2"
+ intervals [343]:
+ xmin = 30.39
+ xmax = 30.45
+ text = "L"
+ intervals [344]:
+ xmin = 30.45
+ xmax = 30.48
+ text = "AH0"
+ intervals [345]:
+ xmin = 30.48
+ xmax = 30.51
+ text = "N"
+ intervals [346]:
+ xmin = 30.51
+ xmax = 30.6
+ text = "T"
+ intervals [347]:
+ xmin = 30.6
+ xmax = 30.67
+ text = "IH1"
+ intervals [348]:
+ xmin = 30.67
+ xmax = 30.73
+ text = "R"
+ intervals [349]:
+ xmin = 30.73
+ xmax = 30.77
+ text = "AE1"
+ intervals [350]:
+ xmin = 30.77
+ xmax = 30.86
+ text = "T"
+ intervals [351]:
+ xmin = 30.86
+ xmax = 30.91
+ text = "DH"
+ intervals [352]:
+ xmin = 30.91
+ xmax = 30.97
+ text = "AH1"
+ intervals [353]:
+ xmin = 30.97
+ xmax = 31.13
+ text = "B"
+ intervals [354]:
+ xmin = 31.13
+ xmax = 31.19
+ text = "UW1"
+ intervals [355]:
+ xmin = 31.19
+ xmax = 31.24
+ text = "D"
+ intervals [356]:
+ xmin = 31.24
+ xmax = 31.3
+ text = "AH0"
+ intervals [357]:
+ xmin = 31.3
+ xmax = 31.35
+ text = "S"
+ intervals [358]:
+ xmin = 31.35
+ xmax = 31.38
+ text = "T"
+ intervals [359]:
+ xmin = 31.38
+ xmax = 31.41
+ text = "T"
+ intervals [360]:
+ xmin = 31.41
+ xmax = 31.47
+ text = "EH1"
+ intervals [361]:
+ xmin = 31.47
+ xmax = 31.52
+ text = "M"
+ intervals [362]:
+ xmin = 31.52
+ xmax = 31.56
+ text = "P"
+ intervals [363]:
+ xmin = 31.56
+ xmax = 31.61
+ text = "AH0"
+ intervals [364]:
+ xmin = 31.61
+ xmax = 31.83
+ text = "L"
+ intervals [365]:
+ xmin = 31.83
+ xmax = 31.9
+ text = "AO1"
+ intervals [366]:
+ xmin = 31.9
+ xmax = 31.94
+ text = "N"
+ intervals [367]:
+ xmin = 31.94
+ xmax = 31.97
+ text = "DH"
+ intervals [368]:
+ xmin = 31.97
+ xmax = 32.01
+ text = "AH1"
+ intervals [369]:
+ xmin = 32.01
+ xmax = 32.08
+ text = "W"
+ intervals [370]:
+ xmin = 32.08
+ xmax = 32.17
+ text = "IY1"
+ intervals [371]:
+ xmin = 32.17
+ xmax = 32.26
+ text = "K"
+ intervals [372]:
+ xmin = 32.26
+ xmax = 32.45
+ text = "EH2"
+ intervals [373]:
+ xmin = 32.45
+ xmax = 32.51
+ text = "N"
+ intervals [374]:
+ xmin = 32.51
+ xmax = 32.6
+ text = "D"
+ intervals [375]:
+ xmin = 32.6
+ xmax = 32.88
+ text = "AO1"
+ intervals [376]:
+ xmin = 32.88
+ xmax = 33.01
+ text = "R"
+ intervals [377]:
+ xmin = 33.01
+ xmax = 33.24
+ text = "AY1"
+ intervals [378]:
+ xmin = 33.24
+ xmax = 33.36
+ text = "K"
+ intervals [379]:
+ xmin = 33.36
+ xmax = 33.51
+ text = "AE1"
+ intervals [380]:
+ xmin = 33.51
+ xmax = 33.62
+ text = "N"
+ intervals [381]:
+ xmin = 33.62
+ xmax = 33.7
+ text = "JH"
+ intervals [382]:
+ xmin = 33.7
+ xmax = 33.77
+ text = "IH0"
+ intervals [383]:
+ xmin = 33.77
+ xmax = 33.8
+ text = "S"
+ intervals [384]:
+ xmin = 33.8
+ xmax = 33.91
+ text = "T"
+ intervals [385]:
+ xmin = 33.91
+ xmax = 33.96
+ text = "W"
+ intervals [386]:
+ xmin = 33.96
+ xmax = 34.2
+ text = "AO1"
+ intervals [387]:
+ xmin = 34.2
+ xmax = 34.3
+ text = "K"
+ intervals [388]:
+ xmin = 34.3
+ xmax = 34.42
+ text = "ER0"
+ intervals [389]:
+ xmin = 34.42
+ xmax = 34.63
+ text = "AW1"
+ intervals [390]:
+ xmin = 34.63
+ xmax = 34.69
+ text = "N"
+ intervals [391]:
+ xmin = 34.69
+ xmax = 34.76
+ text = "IH0"
+ intervals [392]:
+ xmin = 34.76
+ xmax = 34.8
+ text = "N"
+ intervals [393]:
+ xmin = 34.8
+ xmax = 34.9
+ text = "JH"
+ intervals [394]:
+ xmin = 34.9
+ xmax = 34.99
+ text = "OY1"
+ intervals [395]:
+ xmin = 34.99
+ xmax = 35.03
+ text = "IH0"
+ intervals [396]:
+ xmin = 35.03
+ xmax = 35.08
+ text = "NG"
+ intervals [397]:
+ xmin = 35.08
+ xmax = 35.12
+ text = "DH"
+ intervals [398]:
+ xmin = 35.12
+ xmax = 35.17
+ text = "AH0"
+ intervals [399]:
+ xmin = 35.17
+ xmax = 35.26
+ text = "S"
+ intervals [400]:
+ xmin = 35.26
+ xmax = 35.33
+ text = "AH1"
+ intervals [401]:
+ xmin = 35.33
+ xmax = 35.4
+ text = "N"
+ intervals [402]:
+ xmin = 35.4
+ xmax = 35.53
+ text = "SH"
+ intervals [403]:
+ xmin = 35.53
+ xmax = 35.69
+ text = "AY2"
+ intervals [404]:
+ xmin = 35.69
+ xmax = 35.87
+ text = "N"
+ intervals [405]:
+ xmin = 35.87
+ xmax = 36.15
+ text = ""
+ intervals [406]:
+ xmin = 36.15
+ xmax = 36.3
+ text = "AY1"
+ intervals [407]:
+ xmin = 36.3
+ xmax = 36.34
+ text = "D"
+ intervals [408]:
+ xmin = 36.34
+ xmax = 36.38
+ text = "L"
+ intervals [409]:
+ xmin = 36.38
+ xmax = 36.49
+ text = "AY1"
+ intervals [410]:
+ xmin = 36.49
+ xmax = 36.52
+ text = "K"
+ intervals [411]:
+ xmin = 36.52
+ xmax = 36.56
+ text = "T"
+ intervals [412]:
+ xmin = 36.56
+ xmax = 36.59
+ text = "AH0"
+ intervals [413]:
+ xmin = 36.59
+ xmax = 36.62
+ text = "HH"
+ intervals [414]:
+ xmin = 36.62
+ xmax = 36.7
+ text = "AE1"
+ intervals [415]:
+ xmin = 36.7
+ xmax = 36.74
+ text = "V"
+ intervals [416]:
+ xmin = 36.74
+ xmax = 36.79
+ text = "AH0"
+ intervals [417]:
+ xmin = 36.79
+ xmax = 36.83
+ text = "HH"
+ intervals [418]:
+ xmin = 36.83
+ xmax = 36.88
+ text = "EH1"
+ intervals [419]:
+ xmin = 36.88
+ xmax = 36.93
+ text = "L"
+ intervals [420]:
+ xmin = 36.93
+ xmax = 37.01
+ text = "TH"
+ intervals [421]:
+ xmin = 37.01
+ xmax = 37.06
+ text = "IY0"
+ intervals [422]:
+ xmin = 37.06
+ xmax = 37.12
+ text = "L"
+ intervals [423]:
+ xmin = 37.12
+ xmax = 37.23
+ text = "AY1"
+ intervals [424]:
+ xmin = 37.23
+ xmax = 37.27
+ text = "F"
+ intervals [425]:
+ xmin = 37.27
+ xmax = 37.34
+ text = "S"
+ intervals [426]:
+ xmin = 37.34
+ xmax = 37.39
+ text = "T"
+ intervals [427]:
+ xmin = 37.39
+ xmax = 37.56
+ text = "AY2"
+ intervals [428]:
+ xmin = 37.56
+ xmax = 37.66
+ text = "L"
+ intervals [429]:
+ xmin = 37.66
+ xmax = 37.73
+ text = "K"
+ intervals [430]:
+ xmin = 37.73
+ xmax = 37.77
+ text = "AH0"
+ intervals [431]:
+ xmin = 37.77
+ xmax = 37.82
+ text = "N"
+ intervals [432]:
+ xmin = 37.82
+ xmax = 37.87
+ text = "S"
+ intervals [433]:
+ xmin = 37.87
+ xmax = 37.91
+ text = "IH1"
+ intervals [434]:
+ xmin = 37.91
+ xmax = 37.94
+ text = "D"
+ intervals [435]:
+ xmin = 37.94
+ xmax = 37.98
+ text = "ER0"
+ intervals [436]:
+ xmin = 37.98
+ xmax = 38.02
+ text = "IH0"
+ intervals [437]:
+ xmin = 38.02
+ xmax = 38.06
+ text = "NG"
+ intervals [438]:
+ xmin = 38.06
+ xmax = 38.13
+ text = "HH"
+ intervals [439]:
+ xmin = 38.13
+ xmax = 38.17
+ text = "AW1"
+ intervals [440]:
+ xmin = 38.17
+ xmax = 38.23
+ text = "M"
+ intervals [441]:
+ xmin = 38.23
+ xmax = 38.27
+ text = "AH1"
+ intervals [442]:
+ xmin = 38.27
+ xmax = 38.38
+ text = "CH"
+ intervals [443]:
+ xmin = 38.38
+ xmax = 38.5
+ text = "T"
+ intervals [444]:
+ xmin = 38.5
+ xmax = 38.67
+ text = "AY1"
+ intervals [445]:
+ xmin = 38.67
+ xmax = 38.74
+ text = "M"
+ intervals [446]:
+ xmin = 38.74
+ xmax = 38.81
+ text = "AY1"
+ intervals [447]:
+ xmin = 38.81
+ xmax = 38.95
+ text = "S"
+ intervals [448]:
+ xmin = 38.95
+ xmax = 39.02
+ text = "P"
+ intervals [449]:
+ xmin = 39.02
+ xmax = 39.09
+ text = "EH1"
+ intervals [450]:
+ xmin = 39.09
+ xmax = 39.12
+ text = "N"
+ intervals [451]:
+ xmin = 39.12
+ xmax = 39.18
+ text = "D"
+ intervals [452]:
+ xmin = 39.18
+ xmax = 39.21
+ text = "AE1"
+ intervals [453]:
+ xmin = 39.21
+ xmax = 39.29
+ text = "T"
+ intervals [454]:
+ xmin = 39.29
+ xmax = 39.47
+ text = "W"
+ intervals [455]:
+ xmin = 39.47
+ xmax = 39.69
+ text = "ER1"
+ intervals [456]:
+ xmin = 39.69
+ xmax = 39.84
+ text = "K"
+ intervals [457]:
+ xmin = 39.84
+ xmax = 40.29
+ text = ""
+ intervals [458]:
+ xmin = 40.29
+ xmax = 40.52
+ text = "AY1"
+ intervals [459]:
+ xmin = 40.52
+ xmax = 40.56
+ text = "AO1"
+ intervals [460]:
+ xmin = 40.56
+ xmax = 40.59
+ text = "L"
+ intervals [461]:
+ xmin = 40.59
+ xmax = 40.66
+ text = "W"
+ intervals [462]:
+ xmin = 40.66
+ xmax = 40.7
+ text = "IY0"
+ intervals [463]:
+ xmin = 40.7
+ xmax = 40.79
+ text = "Z"
+ intervals [464]:
+ xmin = 40.79
+ xmax = 40.94
+ text = "T"
+ intervals [465]:
+ xmin = 40.94
+ xmax = 41.05
+ text = "R"
+ intervals [466]:
+ xmin = 41.05
+ xmax = 41.28
+ text = "AY1"
+ intervals [467]:
+ xmin = 41.28
+ xmax = 41.38
+ text = "T"
+ intervals [468]:
+ xmin = 41.38
+ xmax = 41.47
+ text = "IH0"
+ intervals [469]:
+ xmin = 41.47
+ xmax = 41.7
+ text = "M"
+ intervals [470]:
+ xmin = 41.7
+ xmax = 41.77
+ text = "UW1"
+ intervals [471]:
+ xmin = 41.77
+ xmax = 41.85
+ text = "V"
+ intervals [472]:
+ xmin = 41.85
+ xmax = 41.9
+ text = "EH1"
+ intervals [473]:
+ xmin = 41.9
+ xmax = 42
+ text = "Z"
+ intervals [474]:
+ xmin = 42
+ xmax = 42.08
+ text = "M"
+ intervals [475]:
+ xmin = 42.08
+ xmax = 42.13
+ text = "AH1"
+ intervals [476]:
+ xmin = 42.13
+ xmax = 42.22
+ text = "CH"
+ intervals [477]:
+ xmin = 42.22
+ xmax = 42.26
+ text = "EH1"
+ intervals [478]:
+ xmin = 42.26
+ xmax = 42.31
+ text = "Z"
+ intervals [479]:
+ xmin = 42.31
+ xmax = 42.4
+ text = "AY1"
+ intervals [480]:
+ xmin = 42.4
+ xmax = 42.51
+ text = "K"
+ intervals [481]:
+ xmin = 42.51
+ xmax = 42.64
+ text = "AE1"
+ intervals [482]:
+ xmin = 42.64
+ xmax = 42.76
+ text = "N"
+ intervals [483]:
+ xmin = 42.76
+ xmax = 42.81
+ text = "W"
+ intervals [484]:
+ xmin = 42.81
+ xmax = 42.84
+ text = "EH1"
+ intervals [485]:
+ xmin = 42.84
+ xmax = 42.89
+ text = "N"
+ intervals [486]:
+ xmin = 42.89
+ xmax = 42.95
+ text = "AH0"
+ intervals [487]:
+ xmin = 42.95
+ xmax = 42.98
+ text = "M"
+ intervals [488]:
+ xmin = 42.98
+ xmax = 43.03
+ text = "N"
+ intervals [489]:
+ xmin = 43.03
+ xmax = 43.12
+ text = "AA1"
+ intervals [490]:
+ xmin = 43.12
+ xmax = 43.18
+ text = "T"
+ intervals [491]:
+ xmin = 43.18
+ xmax = 43.28
+ text = "W"
+ intervals [492]:
+ xmin = 43.28
+ xmax = 43.42
+ text = "ER1"
+ intervals [493]:
+ xmin = 43.42
+ xmax = 43.49
+ text = "K"
+ intervals [494]:
+ xmin = 43.49
+ xmax = 43.53
+ text = "IH0"
+ intervals [495]:
+ xmin = 43.53
+ xmax = 43.76
+ text = "NG"
+ intervals [496]:
+ xmin = 43.76
+ xmax = 44.5
+ text = ""
+ intervals [497]:
+ xmin = 44.5
+ xmax = 44.86
+ text = "AH0"
+ intervals [498]:
+ xmin = 44.86
+ xmax = 45.15
+ text = "N"
+ intervals [499]:
+ xmin = 45.15
+ xmax = 45.19
+ text = "D"
+ intervals [500]:
+ xmin = 45.19
+ xmax = 45.27
+ text = "AA1"
+ intervals [501]:
+ xmin = 45.27
+ xmax = 45.32
+ text = "N"
+ intervals [502]:
+ xmin = 45.32
+ xmax = 45.4
+ text = "AH1"
+ intervals [503]:
+ xmin = 45.4
+ xmax = 45.46
+ text = "DH"
+ intervals [504]:
+ xmin = 45.46
+ xmax = 45.49
+ text = "ER0"
+ intervals [505]:
+ xmin = 45.49
+ xmax = 45.55
+ text = "D"
+ intervals [506]:
+ xmin = 45.55
+ xmax = 45.74
+ text = "EY1"
+ intervals [507]:
+ xmin = 45.74
+ xmax = 45.82
+ text = "Z"
+ intervals [508]:
+ xmin = 45.82
+ xmax = 45.89
+ text = "W"
+ intervals [509]:
+ xmin = 45.89
+ xmax = 45.92
+ text = "EH1"
+ intervals [510]:
+ xmin = 45.92
+ xmax = 45.96
+ text = "N"
+ intervals [511]:
+ xmin = 45.96
+ xmax = 46.09
+ text = "AY1"
+ intervals [512]:
+ xmin = 46.09
+ xmax = 46.16
+ text = "M"
+ intervals [513]:
+ xmin = 46.16
+ xmax = 46.29
+ text = "F"
+ intervals [514]:
+ xmin = 46.29
+ xmax = 46.39
+ text = "R"
+ intervals [515]:
+ xmin = 46.39
+ xmax = 46.65
+ text = "IY1"
+ intervals [516]:
+ xmin = 46.65
+ xmax = 46.86
+ text = "AY1"
+ intervals [517]:
+ xmin = 46.86
+ xmax = 46.94
+ text = "L"
+ intervals [518]:
+ xmin = 46.94
+ xmax = 47.08
+ text = "AY1"
+ intervals [519]:
+ xmin = 47.08
+ xmax = 47.16
+ text = "K"
+ intervals [520]:
+ xmin = 47.16
+ xmax = 47.25
+ text = "T"
+ intervals [521]:
+ xmin = 47.25
+ xmax = 47.39
+ text = "UW1"
+ intervals [522]:
+ xmin = 47.39
+ xmax = 47.48
+ text = "L"
+ intervals [523]:
+ xmin = 47.48
+ xmax = 47.53
+ text = "IH1"
+ intervals [524]:
+ xmin = 47.53
+ xmax = 47.6
+ text = "S"
+ intervals [525]:
+ xmin = 47.6
+ xmax = 47.64
+ text = "AH0"
+ intervals [526]:
+ xmin = 47.64
+ xmax = 47.86
+ text = "N"
+ intervals [527]:
+ xmin = 47.86
+ xmax = 47.93
+ text = "T"
+ intervals [528]:
+ xmin = 47.93
+ xmax = 48.03
+ text = "IH0"
+ intervals [529]:
+ xmin = 48.03
+ xmax = 48.07
+ text = "M"
+ intervals [530]:
+ xmin = 48.07
+ xmax = 48.15
+ text = "Y"
+ intervals [531]:
+ xmin = 48.15
+ xmax = 48.2
+ text = "UW1"
+ intervals [532]:
+ xmin = 48.2
+ xmax = 48.27
+ text = "Z"
+ intervals [533]:
+ xmin = 48.27
+ xmax = 48.35
+ text = "IH0"
+ intervals [534]:
+ xmin = 48.35
+ xmax = 48.41
+ text = "K"
+ intervals [535]:
+ xmin = 48.41
+ xmax = 48.48
+ text = "AH0"
+ intervals [536]:
+ xmin = 48.48
+ xmax = 48.56
+ text = "N"
+ intervals [537]:
+ xmin = 48.56
+ xmax = 48.73
+ text = "D"
+ intervals [538]:
+ xmin = 48.73
+ xmax = 48.76
+ text = ""
+ intervals [539]:
+ xmin = 48.76
+ xmax = 48.91
+ text = "W"
+ intervals [540]:
+ xmin = 48.91
+ xmax = 49.01
+ text = "ER1"
+ intervals [541]:
+ xmin = 49.01
+ xmax = 49.13
+ text = "W"
+ intervals [542]:
+ xmin = 49.13
+ xmax = 49.23
+ text = "AA1"
+ intervals [543]:
+ xmin = 49.23
+ xmax = 49.3
+ text = "CH"
+ intervals [544]:
+ xmin = 49.3
+ xmax = 49.38
+ text = "AH0"
+ intervals [545]:
+ xmin = 49.38
+ xmax = 49.46
+ text = "D"
+ intervals [546]:
+ xmin = 49.46
+ xmax = 49.56
+ text = "AA2"
+ intervals [547]:
+ xmin = 49.56
+ xmax = 49.62
+ text = "K"
+ intervals [548]:
+ xmin = 49.62
+ xmax = 49.66
+ text = "Y"
+ intervals [549]:
+ xmin = 49.66
+ xmax = 49.7
+ text = "AH0"
+ intervals [550]:
+ xmin = 49.7
+ xmax = 49.76
+ text = "M"
+ intervals [551]:
+ xmin = 49.76
+ xmax = 49.81
+ text = "EH1"
+ intervals [552]:
+ xmin = 49.81
+ xmax = 49.85
+ text = "N"
+ intervals [553]:
+ xmin = 49.85
+ xmax = 49.98
+ text = "ER0"
+ intervals [554]:
+ xmin = 49.98
+ xmax = 50.05
+ text = "IY0"
+ intervals [555]:
+ xmin = 50.05
+ xmax = 50.17
+ text = "M"
+ intervals [556]:
+ xmin = 50.17
+ xmax = 50.2
+ text = "UW1"
+ intervals [557]:
+ xmin = 50.2
+ xmax = 50.28
+ text = "V"
+ intervals [558]:
+ xmin = 50.28
+ xmax = 50.38
+ text = "IY0"
+ intervals [559]:
+ xmin = 50.38
+ xmax = 50.51
+ text = "Z"
+ intervals [560]:
+ xmin = 50.51
+ xmax = 50.75
+ text = "AA1"
+ intervals [561]:
+ xmin = 50.75
+ xmax = 50.82
+ text = "N"
+ intervals [562]:
+ xmin = 50.82
+ xmax = 50.9
+ text = "M"
+ intervals [563]:
+ xmin = 50.9
+ xmax = 51.11
+ text = "AY1"
+ intervals [564]:
+ xmin = 51.11
+ xmax = 51.22
+ text = "L"
+ intervals [565]:
+ xmin = 51.22
+ xmax = 51.39
+ text = "AE1"
+ intervals [566]:
+ xmin = 51.39
+ xmax = 51.44
+ text = "P"
+ intervals [567]:
+ xmin = 51.44
+ xmax = 51.49
+ text = "T"
+ intervals [568]:
+ xmin = 51.49
+ xmax = 51.66
+ text = "AA2"
+ intervals [569]:
+ xmin = 51.66
+ xmax = 51.81
+ text = "P"
+ intervals [570]:
+ xmin = 51.81
+ xmax = 52.14
+ text = ""
+ intervals [571]:
+ xmin = 52.14
+ xmax = 52.2
+ text = "B"
+ intervals [572]:
+ xmin = 52.2
+ xmax = 52.33
+ text = "AH1"
+ intervals [573]:
+ xmin = 52.33
+ xmax = 52.44
+ text = "T"
+ intervals [574]:
+ xmin = 52.44
+ xmax = 52.51
+ text = "S"
+ intervals [575]:
+ xmin = 52.51
+ xmax = 52.59
+ text = "AH1"
+ intervals [576]:
+ xmin = 52.59
+ xmax = 52.64
+ text = "M"
+ intervals [577]:
+ xmin = 52.64
+ xmax = 52.67
+ text = "T"
+ intervals [578]:
+ xmin = 52.67
+ xmax = 52.77
+ text = "AY2"
+ intervals [579]:
+ xmin = 52.77
+ xmax = 52.82
+ text = "M"
+ intervals [580]:
+ xmin = 52.82
+ xmax = 52.86
+ text = "Z"
+ intervals [581]:
+ xmin = 52.86
+ xmax = 52.9
+ text = "IH1"
+ intervals [582]:
+ xmin = 52.9
+ xmax = 52.93
+ text = "T"
+ intervals [583]:
+ xmin = 52.93
+ xmax = 52.98
+ text = "JH"
+ intervals [584]:
+ xmin = 52.98
+ xmax = 53.07
+ text = "IH0"
+ intervals [585]:
+ xmin = 53.07
+ xmax = 53.1
+ text = "S"
+ intervals [586]:
+ xmin = 53.1
+ xmax = 53.13
+ text = "T"
+ intervals [587]:
+ xmin = 53.13
+ xmax = 53.18
+ text = "S"
+ intervals [588]:
+ xmin = 53.18
+ xmax = 53.26
+ text = "L"
+ intervals [589]:
+ xmin = 53.26
+ xmax = 53.35
+ text = "IY1"
+ intervals [590]:
+ xmin = 53.35
+ xmax = 53.61
+ text = "P"
+ intervals [591]:
+ xmin = 53.61
+ xmax = 53.65
+ text = ""
+ intervals [592]:
+ xmin = 53.65
+ xmax = 53.83
+ text = "AY1"
+ intervals [593]:
+ xmin = 53.83
+ xmax = 53.88
+ text = "AH0"
+ intervals [594]:
+ xmin = 53.88
+ xmax = 53.95
+ text = "S"
+ intervals [595]:
+ xmin = 53.95
+ xmax = 54
+ text = "P"
+ intervals [596]:
+ xmin = 54
+ xmax = 54.09
+ text = "EH1"
+ intervals [597]:
+ xmin = 54.09
+ xmax = 54.19
+ text = "SH"
+ intervals [598]:
+ xmin = 54.19
+ xmax = 54.22
+ text = "L"
+ intervals [599]:
+ xmin = 54.22
+ xmax = 54.27
+ text = "IY0"
+ intervals [600]:
+ xmin = 54.27
+ xmax = 54.33
+ text = "L"
+ intervals [601]:
+ xmin = 54.33
+ xmax = 54.43
+ text = "AY1"
+ intervals [602]:
+ xmin = 54.43
+ xmax = 54.57
+ text = "K"
+ intervals [603]:
+ xmin = 54.57
+ xmax = 54.61
+ text = "T"
+ intervals [604]:
+ xmin = 54.61
+ xmax = 54.69
+ text = "W"
+ intervals [605]:
+ xmin = 54.69
+ xmax = 54.79
+ text = "AA1"
+ intervals [606]:
+ xmin = 54.79
+ xmax = 54.85
+ text = "CH"
+ intervals [607]:
+ xmin = 54.85
+ xmax = 54.89
+ text = "IH0"
+ intervals [608]:
+ xmin = 54.89
+ xmax = 55.01
+ text = "NG"
+ intervals [609]:
+ xmin = 55.01
+ xmax = 55.12
+ text = "JH"
+ intervals [610]:
+ xmin = 55.12
+ xmax = 55.25
+ text = "AE2"
+ intervals [611]:
+ xmin = 55.25
+ xmax = 55.3
+ text = "P"
+ intervals [612]:
+ xmin = 55.3
+ xmax = 55.35
+ text = "AH0"
+ intervals [613]:
+ xmin = 55.35
+ xmax = 55.4
+ text = "N"
+ intervals [614]:
+ xmin = 55.4
+ xmax = 55.59
+ text = "IY1"
+ intervals [615]:
+ xmin = 55.59
+ xmax = 55.62
+ text = "Z"
+ intervals [616]:
+ xmin = 55.62
+ xmax = 55.77
+ text = "AE1"
+ intervals [617]:
+ xmin = 55.77
+ xmax = 55.83
+ text = "N"
+ intervals [618]:
+ xmin = 55.83
+ xmax = 55.87
+ text = "AH0"
+ intervals [619]:
+ xmin = 55.87
+ xmax = 55.91
+ text = "M"
+ intervals [620]:
+ xmin = 55.91
+ xmax = 56.33
+ text = "AY1"
+ intervals [621]:
+ xmin = 56.33
+ xmax = 56.85
+ text = ""
+ intervals [622]:
+ xmin = 56.85
+ xmax = 56.99
+ text = "TH"
+ intervals [623]:
+ xmin = 56.99
+ xmax = 57.05
+ text = "IH1"
+ intervals [624]:
+ xmin = 57.05
+ xmax = 57.09
+ text = "NG"
+ intervals [625]:
+ xmin = 57.09
+ xmax = 57.12
+ text = "K"
+ intervals [626]:
+ xmin = 57.12
+ xmax = 57.2
+ text = "W"
+ intervals [627]:
+ xmin = 57.2
+ xmax = 57.27
+ text = "AA1"
+ intervals [628]:
+ xmin = 57.27
+ xmax = 57.35
+ text = "CH"
+ intervals [629]:
+ xmin = 57.35
+ xmax = 57.4
+ text = "IH0"
+ intervals [630]:
+ xmin = 57.4
+ xmax = 57.43
+ text = "NG"
+ intervals [631]:
+ xmin = 57.43
+ xmax = 57.62
+ text = "EY1"
+ intervals [632]:
+ xmin = 57.62
+ xmax = 57.69
+ text = "M"
+ intervals [633]:
+ xmin = 57.69
+ xmax = 57.79
+ text = "IY1"
+ intervals [634]:
+ xmin = 57.79
+ xmax = 57.92
+ text = "IH0"
+ intervals [635]:
+ xmin = 57.92
+ xmax = 58.09
+ text = "Z"
+ intervals [636]:
+ xmin = 58.09
+ xmax = 58.12
+ text = "AE1"
+ intervals [637]:
+ xmin = 58.12
+ xmax = 58.19
+ text = "N"
+ intervals [638]:
+ xmin = 58.19
+ xmax = 58.23
+ text = "AH0"
+ intervals [639]:
+ xmin = 58.23
+ xmax = 58.39
+ text = "M"
+ intervals [640]:
+ xmin = 58.39
+ xmax = 58.97
+ text = "IH1"
+ intervals [641]:
+ xmin = 58.97
+ xmax = 59.06
+ text = "Z"
+ intervals [642]:
+ xmin = 59.06
+ xmax = 59.11
+ text = "V"
+ intervals [643]:
+ xmin = 59.11
+ xmax = 59.15
+ text = "EH1"
+ intervals [644]:
+ xmin = 59.15
+ xmax = 59.24
+ text = "R"
+ intervals [645]:
+ xmin = 59.24
+ xmax = 59.31
+ text = "IY0"
+ intervals [646]:
+ xmin = 59.31
+ xmax = 59.38
+ text = "HH"
+ intervals [647]:
+ xmin = 59.38
+ xmax = 59.43
+ text = "EH1"
+ intervals [648]:
+ xmin = 59.43
+ xmax = 59.52
+ text = "L"
+ intervals [649]:
+ xmin = 59.52
+ xmax = 59.55
+ text = "P"
+ intervals [650]:
+ xmin = 59.55
+ xmax = 59.58
+ text = "F"
+ intervals [651]:
+ xmin = 59.58
+ xmax = 59.61
+ text = "AH0"
+ intervals [652]:
+ xmin = 59.61
+ xmax = 59.67
+ text = "L"
+ intervals [653]:
+ xmin = 59.67
+ xmax = 59.72
+ text = "F"
+ intervals [654]:
+ xmin = 59.72
+ xmax = 59.75
+ text = "R"
+ intervals [655]:
+ xmin = 59.75
+ xmax = 59.81
+ text = "ER0"
+ intervals [656]:
+ xmin = 59.81
+ xmax = 59.88
+ text = "M"
+ intervals [657]:
+ xmin = 59.88
+ xmax = 59.98
+ text = "IY1"
+ intervals [658]:
+ xmin = 59.98
+ xmax = 60.08
+ text = "T"
+ intervals [659]:
+ xmin = 60.08
+ xmax = 60.28
+ text = "UW1"
+ intervals [660]:
+ xmin = 60.28
+ xmax = 60.42
+ text = "L"
+ intervals [661]:
+ xmin = 60.42
+ xmax = 60.63
+ text = "ER1"
+ intervals [662]:
+ xmin = 60.63
+ xmax = 60.69
+ text = "N"
+ intervals [663]:
+ xmin = 60.69
+ xmax = 60.72
+ text = "AE1"
+ intervals [664]:
+ xmin = 60.72
+ xmax = 60.75
+ text = "N"
+ intervals [665]:
+ xmin = 60.75
+ xmax = 60.78
+ text = "D"
+ intervals [666]:
+ xmin = 60.78
+ xmax = 60.84
+ text = "IH0"
+ intervals [667]:
+ xmin = 60.84
+ xmax = 60.88
+ text = "K"
+ intervals [668]:
+ xmin = 60.88
+ xmax = 60.95
+ text = "S"
+ intervals [669]:
+ xmin = 60.95
+ xmax = 61.01
+ text = "P"
+ intervals [670]:
+ xmin = 61.01
+ xmax = 61.09
+ text = "R"
+ intervals [671]:
+ xmin = 61.09
+ xmax = 61.14
+ text = "EH1"
+ intervals [672]:
+ xmin = 61.14
+ xmax = 61.21
+ text = "S"
+ intervals [673]:
+ xmin = 61.21
+ xmax = 61.33
+ text = "JH"
+ intervals [674]:
+ xmin = 61.33
+ xmax = 61.45
+ text = "AE2"
+ intervals [675]:
+ xmin = 61.45
+ xmax = 61.51
+ text = "P"
+ intervals [676]:
+ xmin = 61.51
+ xmax = 61.55
+ text = "AH0"
+ intervals [677]:
+ xmin = 61.55
+ xmax = 61.59
+ text = "N"
+ intervals [678]:
+ xmin = 61.59
+ xmax = 61.75
+ text = "IY1"
+ intervals [679]:
+ xmin = 61.75
+ xmax = 61.89
+ text = "Z"
+ intervals [680]:
+ xmin = 61.89
+ xmax = 62.02
+ text = "B"
+ intervals [681]:
+ xmin = 62.02
+ xmax = 62.11
+ text = "EH1"
+ intervals [682]:
+ xmin = 62.11
+ xmax = 62.19
+ text = "T"
+ intervals [683]:
+ xmin = 62.19
+ xmax = 62.42
+ text = "ER0"
+ intervals [684]:
+ xmin = 62.42
+ xmax = 64.097375
+ text = ""
diff --git a/EMAGE/test_sequences/textgrid/2_scott_0_2_2.TextGrid b/EMAGE/test_sequences/textgrid/2_scott_0_2_2.TextGrid
new file mode 100644
index 0000000000000000000000000000000000000000..faef4cc5a37423c8f9ad3a32097bb27a75cd9d0e
--- /dev/null
+++ b/EMAGE/test_sequences/textgrid/2_scott_0_2_2.TextGrid
@@ -0,0 +1,3716 @@
+File type = "ooTextFile"
+Object class = "TextGrid"
+
+xmin = 0.0
+xmax = 62
+tiers?
+size = 2
+item []:
+ item [1]:
+ class = "IntervalTier"
+ name = "words"
+ xmin = 0.0
+ xmax = 62
+ intervals: size = 223
+ intervals [1]:
+ xmin = 0.0
+ xmax = 1.45
+ text = ""
+ intervals [2]:
+ xmin = 1.45
+ xmax = 1.87
+ text = "so"
+ intervals [3]:
+ xmin = 1.87
+ xmax = 2.02
+ text = "when"
+ intervals [4]:
+ xmin = 2.02
+ xmax = 2.13
+ text = "i"
+ intervals [5]:
+ xmin = 2.13
+ xmax = 2.35
+ text = "have"
+ intervals [6]:
+ xmin = 2.35
+ xmax = 2.57
+ text = "time"
+ intervals [7]:
+ xmin = 2.57
+ xmax = 2.65
+ text = "to"
+ intervals [8]:
+ xmin = 2.65
+ xmax = 3.18
+ text = "kill"
+ intervals [9]:
+ xmin = 3.18
+ xmax = 3.22
+ text = ""
+ intervals [10]:
+ xmin = 3.22
+ xmax = 3.41
+ text = "i"
+ intervals [11]:
+ xmin = 3.41
+ xmax = 3.6
+ text = "like"
+ intervals [12]:
+ xmin = 3.6
+ xmax = 3.68
+ text = "to"
+ intervals [13]:
+ xmin = 3.68
+ xmax = 3.88
+ text = "play"
+ intervals [14]:
+ xmin = 3.88
+ xmax = 3.96
+ text = "on"
+ intervals [15]:
+ xmin = 3.96
+ xmax = 4.08
+ text = "the"
+ intervals [16]:
+ xmin = 4.08
+ xmax = 4.5
+ text = "internet"
+ intervals [17]:
+ xmin = 4.5
+ xmax = 4.66
+ text = "and"
+ intervals [18]:
+ xmin = 4.66
+ xmax = 4.87
+ text = "play"
+ intervals [19]:
+ xmin = 4.87
+ xmax = 5.19
+ text = "close"
+ intervals [20]:
+ xmin = 5.19
+ xmax = 5.67
+ text = "attention"
+ intervals [21]:
+ xmin = 5.67
+ xmax = 6.0
+ text = "to"
+ intervals [22]:
+ xmin = 6.0
+ xmax = 6.26
+ text = "new"
+ intervals [23]:
+ xmin = 6.26
+ xmax = 6.71
+ text = "fashion"
+ intervals [24]:
+ xmin = 6.71
+ xmax = 7.17
+ text = "events"
+ intervals [25]:
+ xmin = 7.17
+ xmax = 7.43
+ text = ""
+ intervals [26]:
+ xmin = 7.43
+ xmax = 7.76
+ text = "such"
+ intervals [27]:
+ xmin = 7.76
+ xmax = 8.14
+ text = "as"
+ intervals [28]:
+ xmin = 8.14
+ xmax = 8.19
+ text = ""
+ intervals [29]:
+ xmin = 8.19
+ xmax = 8.34
+ text = "the"
+ intervals [30]:
+ xmin = 8.34
+ xmax = 8.47
+ text = "new"
+ intervals [31]:
+ xmin = 8.47
+ xmax = 8.68
+ text = "york"
+ intervals [32]:
+ xmin = 8.68
+ xmax = 9.12
+ text = "fashion"
+ intervals [33]:
+ xmin = 9.12
+ xmax = 9.42
+ text = "week"
+ intervals [34]:
+ xmin = 9.42
+ xmax = 9.49
+ text = "the"
+ intervals [35]:
+ xmin = 9.49
+ xmax = 9.87
+ text = "paris"
+ intervals [36]:
+ xmin = 9.87
+ xmax = 10.25
+ text = "fashion"
+ intervals [37]:
+ xmin = 10.25
+ xmax = 10.56
+ text = "week"
+ intervals [38]:
+ xmin = 10.56
+ xmax = 10.66
+ text = "the"
+ intervals [39]:
+ xmin = 10.66
+ xmax = 11.07
+ text = "london"
+ intervals [40]:
+ xmin = 11.07
+ xmax = 11.51
+ text = "fashion"
+ intervals [41]:
+ xmin = 11.51
+ xmax = 11.78
+ text = "week"
+ intervals [42]:
+ xmin = 11.78
+ xmax = 12.17
+ text = "and"
+ intervals [43]:
+ xmin = 12.17
+ xmax = 12.21
+ text = ""
+ intervals [44]:
+ xmin = 12.21
+ xmax = 12.83
+ text = "milan"
+ intervals [45]:
+ xmin = 12.83
+ xmax = 13.24
+ text = "fashion"
+ intervals [46]:
+ xmin = 13.24
+ xmax = 13.62
+ text = "week"
+ intervals [47]:
+ xmin = 13.62
+ xmax = 14.03
+ text = ""
+ intervals [48]:
+ xmin = 14.03
+ xmax = 14.15
+ text = "the"
+ intervals [49]:
+ xmin = 14.15
+ xmax = 14.35
+ text = "rest"
+ intervals [50]:
+ xmin = 14.35
+ xmax = 14.43
+ text = "of"
+ intervals [51]:
+ xmin = 14.43
+ xmax = 14.49
+ text = "the"
+ intervals [52]:
+ xmin = 14.49
+ xmax = 14.8
+ text = "time"
+ intervals [53]:
+ xmin = 14.8
+ xmax = 14.87
+ text = "i"
+ intervals [54]:
+ xmin = 14.87
+ xmax = 15.2
+ text = "usually"
+ intervals [55]:
+ xmin = 15.2
+ xmax = 15.3
+ text = "go"
+ intervals [56]:
+ xmin = 15.3
+ xmax = 15.36
+ text = "to"
+ intervals [57]:
+ xmin = 15.36
+ xmax = 15.44
+ text = "the"
+ intervals [58]:
+ xmin = 15.44
+ xmax = 15.93
+ text = "library"
+ intervals [59]:
+ xmin = 15.93
+ xmax = 16.04
+ text = "and"
+ intervals [60]:
+ xmin = 16.04
+ xmax = 16.25
+ text = "find"
+ intervals [61]:
+ xmin = 16.25
+ xmax = 16.35
+ text = "some"
+ intervals [62]:
+ xmin = 16.35
+ xmax = 16.71
+ text = "interesting"
+ intervals [63]:
+ xmin = 16.71
+ xmax = 17.19
+ text = "books"
+ intervals [64]:
+ xmin = 17.19
+ xmax = 17.31
+ text = "and"
+ intervals [65]:
+ xmin = 17.31
+ xmax = 17.51
+ text = "then"
+ intervals [66]:
+ xmin = 17.51
+ xmax = 17.63
+ text = "go"
+ intervals [67]:
+ xmin = 17.63
+ xmax = 17.7
+ text = "to"
+ intervals [68]:
+ xmin = 17.7
+ xmax = 17.78
+ text = "a"
+ intervals [69]:
+ xmin = 17.78
+ xmax = 18.08
+ text = "park"
+ intervals [70]:
+ xmin = 18.08
+ xmax = 18.17
+ text = "and"
+ intervals [71]:
+ xmin = 18.17
+ xmax = 18.75
+ text = "relax"
+ intervals [72]:
+ xmin = 18.75
+ xmax = 19.04
+ text = ""
+ intervals [73]:
+ xmin = 19.04
+ xmax = 19.22
+ text = "there"
+ intervals [74]:
+ xmin = 19.22
+ xmax = 19.27
+ text = "are"
+ intervals [75]:
+ xmin = 19.27
+ xmax = 19.5
+ text = "many"
+ intervals [76]:
+ xmin = 19.5
+ xmax = 19.78
+ text = "books"
+ intervals [77]:
+ xmin = 19.78
+ xmax = 19.93
+ text = "that"
+ intervals [78]:
+ xmin = 19.93
+ xmax = 20.11
+ text = "i"
+ intervals [79]:
+ xmin = 20.11
+ xmax = 20.4
+ text = "find"
+ intervals [80]:
+ xmin = 20.4
+ xmax = 20.92
+ text = "interesting"
+ intervals [81]:
+ xmin = 20.92
+ xmax = 21.15
+ text = "such"
+ intervals [82]:
+ xmin = 21.15
+ xmax = 21.3
+ text = "as"
+ intervals [83]:
+ xmin = 21.3
+ xmax = 21.62
+ text = "fashion"
+ intervals [84]:
+ xmin = 21.62
+ xmax = 22.19
+ text = "magazines"
+ intervals [85]:
+ xmin = 22.19
+ xmax = 22.8
+ text = "inspirational"
+ intervals [86]:
+ xmin = 22.8
+ xmax = 23.15
+ text = "books"
+ intervals [87]:
+ xmin = 23.15
+ xmax = 23.44
+ text = "and"
+ intervals [88]:
+ xmin = 23.44
+ xmax = 24.04
+ text = "professional"
+ intervals [89]:
+ xmin = 24.04
+ xmax = 24.46
+ text = "books"
+ intervals [90]:
+ xmin = 24.46
+ xmax = 24.83
+ text = ""
+ intervals [91]:
+ xmin = 24.83
+ xmax = 25.06
+ text = "these"
+ intervals [92]:
+ xmin = 25.06
+ xmax = 25.37
+ text = "books"
+ intervals [93]:
+ xmin = 25.37
+ xmax = 25.54
+ text = "can"
+ intervals [94]:
+ xmin = 25.54
+ xmax = 25.66
+ text = "give"
+ intervals [95]:
+ xmin = 25.66
+ xmax = 25.76
+ text = "me"
+ intervals [96]:
+ xmin = 25.76
+ xmax = 25.86
+ text = "the"
+ intervals [97]:
+ xmin = 25.86
+ xmax = 26.85
+ text = "motivation"
+ intervals [98]:
+ xmin = 26.85
+ xmax = 26.88
+ text = ""
+ intervals [99]:
+ xmin = 26.88
+ xmax = 27.07
+ text = "to"
+ intervals [100]:
+ xmin = 27.07
+ xmax = 27.37
+ text = "be"
+ intervals [101]:
+ xmin = 27.37
+ xmax = 28.01
+ text = "healthier"
+ intervals [102]:
+ xmin = 28.01
+ xmax = 28.18
+ text = "and"
+ intervals [103]:
+ xmin = 28.18
+ xmax = 28.9
+ text = "energetic"
+ intervals [104]:
+ xmin = 28.9
+ xmax = 29.1
+ text = ""
+ intervals [105]:
+ xmin = 29.1
+ xmax = 29.3
+ text = "and"
+ intervals [106]:
+ xmin = 29.3
+ xmax = 29.37
+ text = "the"
+ intervals [107]:
+ xmin = 29.37
+ xmax = 29.74
+ text = "last"
+ intervals [108]:
+ xmin = 29.74
+ xmax = 29.94
+ text = "thing"
+ intervals [109]:
+ xmin = 29.94
+ xmax = 30.14
+ text = "i"
+ intervals [110]:
+ xmin = 30.14
+ xmax = 30.42
+ text = "like"
+ intervals [111]:
+ xmin = 30.42
+ xmax = 30.53
+ text = "to"
+ intervals [112]:
+ xmin = 30.53
+ xmax = 30.84
+ text = "do"
+ intervals [113]:
+ xmin = 30.84
+ xmax = 31.22
+ text = "when"
+ intervals [114]:
+ xmin = 31.22
+ xmax = 31.43
+ text = "i'm"
+ intervals [115]:
+ xmin = 31.43
+ xmax = 31.87
+ text = "free"
+ intervals [116]:
+ xmin = 31.87
+ xmax = 31.99
+ text = "is"
+ intervals [117]:
+ xmin = 31.99
+ xmax = 32.11
+ text = "it"
+ intervals [118]:
+ xmin = 32.11
+ xmax = 32.23
+ text = "out"
+ intervals [119]:
+ xmin = 32.23
+ xmax = 32.35
+ text = "with"
+ intervals [120]:
+ xmin = 32.35
+ xmax = 32.48
+ text = "my"
+ intervals [121]:
+ xmin = 32.48
+ xmax = 32.86
+ text = "family"
+ intervals [122]:
+ xmin = 32.86
+ xmax = 33.33
+ text = "members"
+ intervals [123]:
+ xmin = 33.33
+ xmax = 33.51
+ text = ""
+ intervals [124]:
+ xmin = 33.51
+ xmax = 33.89
+ text = "you"
+ intervals [125]:
+ xmin = 33.89
+ xmax = 34.11
+ text = "would"
+ intervals [126]:
+ xmin = 34.11
+ xmax = 34.29
+ text = "be"
+ intervals [127]:
+ xmin = 34.29
+ xmax = 35.07
+ text = "surprised"
+ intervals [128]:
+ xmin = 35.07
+ xmax = 35.16
+ text = "to"
+ intervals [129]:
+ xmin = 35.16
+ xmax = 35.36
+ text = "know"
+ intervals [130]:
+ xmin = 35.36
+ xmax = 35.5
+ text = "that"
+ intervals [131]:
+ xmin = 35.5
+ xmax = 35.64
+ text = "i"
+ intervals [132]:
+ xmin = 35.64
+ xmax = 35.84
+ text = "have"
+ intervals [133]:
+ xmin = 35.84
+ xmax = 36.3
+ text = "tried"
+ intervals [134]:
+ xmin = 36.3
+ xmax = 36.57
+ text = ""
+ intervals [135]:
+ xmin = 36.57
+ xmax = 36.99
+ text = "all"
+ intervals [136]:
+ xmin = 36.99
+ xmax = 37.08
+ text = "the"
+ intervals [137]:
+ xmin = 37.08
+ xmax = 37.68
+ text = "restaurants"
+ intervals [138]:
+ xmin = 37.68
+ xmax = 37.71
+ text = ""
+ intervals [139]:
+ xmin = 37.71
+ xmax = 37.83
+ text = "in"
+ intervals [140]:
+ xmin = 37.83
+ xmax = 37.95
+ text = "our"
+ intervals [141]:
+ xmin = 37.95
+ xmax = 38.5
+ text = "huge"
+ intervals [142]:
+ xmin = 38.5
+ xmax = 39.07
+ text = "community"
+ intervals [143]:
+ xmin = 39.07
+ xmax = 39.23
+ text = ""
+ intervals [144]:
+ xmin = 39.23
+ xmax = 39.6
+ text = "i"
+ intervals [145]:
+ xmin = 39.6
+ xmax = 40.09
+ text = "actually"
+ intervals [146]:
+ xmin = 40.09
+ xmax = 40.32
+ text = "give"
+ intervals [147]:
+ xmin = 40.32
+ xmax = 40.61
+ text = "each"
+ intervals [148]:
+ xmin = 40.61
+ xmax = 41.08
+ text = "restaurant"
+ intervals [149]:
+ xmin = 41.08
+ xmax = 41.15
+ text = "a"
+ intervals [150]:
+ xmin = 41.15
+ xmax = 41.55
+ text = "score"
+ intervals [151]:
+ xmin = 41.55
+ xmax = 41.82
+ text = "based"
+ intervals [152]:
+ xmin = 41.82
+ xmax = 41.89
+ text = "on"
+ intervals [153]:
+ xmin = 41.89
+ xmax = 42.05
+ text = "how"
+ intervals [154]:
+ xmin = 42.05
+ xmax = 42.17
+ text = "good"
+ intervals [155]:
+ xmin = 42.17
+ xmax = 42.23
+ text = "the"
+ intervals [156]:
+ xmin = 42.23
+ xmax = 42.51
+ text = "food"
+ intervals [157]:
+ xmin = 42.51
+ xmax = 42.85
+ text = "is"
+ intervals [158]:
+ xmin = 42.85
+ xmax = 43.13
+ text = ""
+ intervals [159]:
+ xmin = 43.13
+ xmax = 43.36
+ text = "how"
+ intervals [160]:
+ xmin = 43.36
+ xmax = 43.51
+ text = "good"
+ intervals [161]:
+ xmin = 43.51
+ xmax = 43.62
+ text = "the"
+ intervals [162]:
+ xmin = 43.62
+ xmax = 44.1
+ text = "environment"
+ intervals [163]:
+ xmin = 44.1
+ xmax = 44.4
+ text = "is"
+ intervals [164]:
+ xmin = 44.4
+ xmax = 44.49
+ text = ""
+ intervals [165]:
+ xmin = 44.49
+ xmax = 44.98
+ text = "and"
+ intervals [166]:
+ xmin = 44.98
+ xmax = 45.34
+ text = "at"
+ intervals [167]:
+ xmin = 45.34
+ xmax = 45.62
+ text = "the"
+ intervals [168]:
+ xmin = 45.62
+ xmax = 45.91
+ text = "same"
+ intervals [169]:
+ xmin = 45.91
+ xmax = 46.29
+ text = "time"
+ intervals [170]:
+ xmin = 46.29
+ xmax = 46.42
+ text = "i"
+ intervals [171]:
+ xmin = 46.42
+ xmax = 46.54
+ text = "will"
+ intervals [172]:
+ xmin = 46.54
+ xmax = 46.74
+ text = "write"
+ intervals [173]:
+ xmin = 46.74
+ xmax = 46.94
+ text = "down"
+ intervals [174]:
+ xmin = 46.94
+ xmax = 47.02
+ text = "the"
+ intervals [175]:
+ xmin = 47.02
+ xmax = 47.24
+ text = "type"
+ intervals [176]:
+ xmin = 47.24
+ xmax = 47.39
+ text = "of"
+ intervals [177]:
+ xmin = 47.39
+ xmax = 47.8
+ text = "food"
+ intervals [178]:
+ xmin = 47.8
+ xmax = 48.03
+ text = ""
+ intervals [179]:
+ xmin = 48.03
+ xmax = 48.24
+ text = "they"
+ intervals [180]:
+ xmin = 48.24
+ xmax = 48.76
+ text = "serve"
+ intervals [181]:
+ xmin = 48.76
+ xmax = 49.42
+ text = ""
+ intervals [182]:
+ xmin = 49.42
+ xmax = 49.9
+ text = "so"
+ intervals [183]:
+ xmin = 49.9
+ xmax = 50.46
+ text = "when"
+ intervals [184]:
+ xmin = 50.46
+ xmax = 50.49
+ text = ""
+ intervals [185]:
+ xmin = 50.49
+ xmax = 50.85
+ text = "you're"
+ intervals [186]:
+ xmin = 50.85
+ xmax = 50.98
+ text = "so"
+ intervals [187]:
+ xmin = 50.98
+ xmax = 51.13
+ text = "when"
+ intervals [188]:
+ xmin = 51.13
+ xmax = 51.35
+ text = "each"
+ intervals [189]:
+ xmin = 51.35
+ xmax = 51.55
+ text = "time"
+ intervals [190]:
+ xmin = 51.55
+ xmax = 51.62
+ text = "a"
+ intervals [191]:
+ xmin = 51.62
+ xmax = 51.91
+ text = "friend"
+ intervals [192]:
+ xmin = 51.91
+ xmax = 52.32
+ text = "comes"
+ intervals [193]:
+ xmin = 52.32
+ xmax = 52.46
+ text = "to"
+ intervals [194]:
+ xmin = 52.46
+ xmax = 52.59
+ text = "the"
+ intervals [195]:
+ xmin = 52.59
+ xmax = 52.9
+ text = "city"
+ intervals [196]:
+ xmin = 52.9
+ xmax = 53.07
+ text = "to"
+ intervals [197]:
+ xmin = 53.07
+ xmax = 53.35
+ text = "enjoy"
+ intervals [198]:
+ xmin = 53.35
+ xmax = 53.62
+ text = "time"
+ intervals [199]:
+ xmin = 53.62
+ xmax = 53.74
+ text = "with"
+ intervals [200]:
+ xmin = 53.74
+ xmax = 54.02
+ text = "me"
+ intervals [201]:
+ xmin = 54.02
+ xmax = 54.31
+ text = ""
+ intervals [202]:
+ xmin = 54.31
+ xmax = 54.54
+ text = "i"
+ intervals [203]:
+ xmin = 54.54
+ xmax = 54.69
+ text = "will"
+ intervals [204]:
+ xmin = 54.69
+ xmax = 54.84
+ text = "give"
+ intervals [205]:
+ xmin = 54.84
+ xmax = 54.97
+ text = "them"
+ intervals [206]:
+ xmin = 54.97
+ xmax = 55.07
+ text = "the"
+ intervals [207]:
+ xmin = 55.07
+ xmax = 55.38
+ text = "top"
+ intervals [208]:
+ xmin = 55.38
+ xmax = 55.53
+ text = "5"
+ intervals [209]:
+ xmin = 55.53
+ xmax = 56.1
+ text = "restaurants"
+ intervals [210]:
+ xmin = 56.1
+ xmax = 56.44
+ text = "based"
+ intervals [211]:
+ xmin = 56.44
+ xmax = 56.68
+ text = "on"
+ intervals [212]:
+ xmin = 56.68
+ xmax = 56.99
+ text = "this"
+ intervals [213]:
+ xmin = 56.99
+ xmax = 57.35
+ text = "ranking"
+ intervals [214]:
+ xmin = 57.35
+ xmax = 57.53
+ text = "and"
+ intervals [215]:
+ xmin = 57.53
+ xmax = 57.86
+ text = "every"
+ intervals [216]:
+ xmin = 57.86
+ xmax = 58.44
+ text = "time"
+ intervals [217]:
+ xmin = 58.44
+ xmax = 59.02
+ text = ""
+ intervals [218]:
+ xmin = 59.02
+ xmax = 59.2
+ text = "you're"
+ intervals [219]:
+ xmin = 59.2
+ xmax = 59.72
+ text = "satisfied"
+ intervals [220]:
+ xmin = 59.72
+ xmax = 59.85
+ text = "with"
+ intervals [221]:
+ xmin = 59.85
+ xmax = 60.1
+ text = "these"
+ intervals [222]:
+ xmin = 60.1
+ xmax = 60.81
+ text = "restaurants"
+ intervals [223]:
+ xmin = 60.81
+ xmax = 62
+ text = ""
+ item [2]:
+ class = "IntervalTier"
+ name = "phones"
+ xmin = 0.0
+ xmax = 62
+ intervals: size = 701
+ intervals [1]:
+ xmin = 0.0
+ xmax = 1.45
+ text = ""
+ intervals [2]:
+ xmin = 1.45
+ xmax = 1.64
+ text = "S"
+ intervals [3]:
+ xmin = 1.64
+ xmax = 1.87
+ text = "OW1"
+ intervals [4]:
+ xmin = 1.87
+ xmax = 1.94
+ text = "W"
+ intervals [5]:
+ xmin = 1.94
+ xmax = 1.97
+ text = "EH1"
+ intervals [6]:
+ xmin = 1.97
+ xmax = 2.02
+ text = "N"
+ intervals [7]:
+ xmin = 2.02
+ xmax = 2.13
+ text = "AY1"
+ intervals [8]:
+ xmin = 2.13
+ xmax = 2.21
+ text = "HH"
+ intervals [9]:
+ xmin = 2.21
+ xmax = 2.29
+ text = "AE1"
+ intervals [10]:
+ xmin = 2.29
+ xmax = 2.35
+ text = "V"
+ intervals [11]:
+ xmin = 2.35
+ xmax = 2.43
+ text = "T"
+ intervals [12]:
+ xmin = 2.43
+ xmax = 2.52
+ text = "AY1"
+ intervals [13]:
+ xmin = 2.52
+ xmax = 2.57
+ text = "M"
+ intervals [14]:
+ xmin = 2.57
+ xmax = 2.6
+ text = "T"
+ intervals [15]:
+ xmin = 2.6
+ xmax = 2.65
+ text = "AH0"
+ intervals [16]:
+ xmin = 2.65
+ xmax = 2.75
+ text = "K"
+ intervals [17]:
+ xmin = 2.75
+ xmax = 2.81
+ text = "IH1"
+ intervals [18]:
+ xmin = 2.81
+ xmax = 3.18
+ text = "L"
+ intervals [19]:
+ xmin = 3.18
+ xmax = 3.22
+ text = ""
+ intervals [20]:
+ xmin = 3.22
+ xmax = 3.41
+ text = "AY1"
+ intervals [21]:
+ xmin = 3.41
+ xmax = 3.46
+ text = "L"
+ intervals [22]:
+ xmin = 3.46
+ xmax = 3.57
+ text = "AY1"
+ intervals [23]:
+ xmin = 3.57
+ xmax = 3.6
+ text = "K"
+ intervals [24]:
+ xmin = 3.6
+ xmax = 3.63
+ text = "T"
+ intervals [25]:
+ xmin = 3.63
+ xmax = 3.68
+ text = "IH0"
+ intervals [26]:
+ xmin = 3.68
+ xmax = 3.75
+ text = "P"
+ intervals [27]:
+ xmin = 3.75
+ xmax = 3.83
+ text = "L"
+ intervals [28]:
+ xmin = 3.83
+ xmax = 3.88
+ text = "EY1"
+ intervals [29]:
+ xmin = 3.88
+ xmax = 3.93
+ text = "AA1"
+ intervals [30]:
+ xmin = 3.93
+ xmax = 3.96
+ text = "N"
+ intervals [31]:
+ xmin = 3.96
+ xmax = 4.01
+ text = "DH"
+ intervals [32]:
+ xmin = 4.01
+ xmax = 4.08
+ text = "IY0"
+ intervals [33]:
+ xmin = 4.08
+ xmax = 4.13
+ text = "IH1"
+ intervals [34]:
+ xmin = 4.13
+ xmax = 4.16
+ text = "N"
+ intervals [35]:
+ xmin = 4.16
+ xmax = 4.19
+ text = "T"
+ intervals [36]:
+ xmin = 4.19
+ xmax = 4.25
+ text = "ER0"
+ intervals [37]:
+ xmin = 4.25
+ xmax = 4.29
+ text = "N"
+ intervals [38]:
+ xmin = 4.29
+ xmax = 4.42
+ text = "EH2"
+ intervals [39]:
+ xmin = 4.42
+ xmax = 4.5
+ text = "T"
+ intervals [40]:
+ xmin = 4.5
+ xmax = 4.58
+ text = "AE1"
+ intervals [41]:
+ xmin = 4.58
+ xmax = 4.62
+ text = "N"
+ intervals [42]:
+ xmin = 4.62
+ xmax = 4.66
+ text = "D"
+ intervals [43]:
+ xmin = 4.66
+ xmax = 4.71
+ text = "P"
+ intervals [44]:
+ xmin = 4.71
+ xmax = 4.8
+ text = "L"
+ intervals [45]:
+ xmin = 4.8
+ xmax = 4.87
+ text = "EY1"
+ intervals [46]:
+ xmin = 4.87
+ xmax = 4.97
+ text = "K"
+ intervals [47]:
+ xmin = 4.97
+ xmax = 5.02
+ text = "L"
+ intervals [48]:
+ xmin = 5.02
+ xmax = 5.09
+ text = "OW1"
+ intervals [49]:
+ xmin = 5.09
+ xmax = 5.19
+ text = "S"
+ intervals [50]:
+ xmin = 5.19
+ xmax = 5.23
+ text = "AH0"
+ intervals [51]:
+ xmin = 5.23
+ xmax = 5.32
+ text = "T"
+ intervals [52]:
+ xmin = 5.32
+ xmax = 5.36
+ text = "EH1"
+ intervals [53]:
+ xmin = 5.36
+ xmax = 5.42
+ text = "N"
+ intervals [54]:
+ xmin = 5.42
+ xmax = 5.49
+ text = "SH"
+ intervals [55]:
+ xmin = 5.49
+ xmax = 5.55
+ text = "AH0"
+ intervals [56]:
+ xmin = 5.55
+ xmax = 5.67
+ text = "N"
+ intervals [57]:
+ xmin = 5.67
+ xmax = 5.8
+ text = "T"
+ intervals [58]:
+ xmin = 5.8
+ xmax = 6.0
+ text = "UW1"
+ intervals [59]:
+ xmin = 6.0
+ xmax = 6.03
+ text = "N"
+ intervals [60]:
+ xmin = 6.03
+ xmax = 6.15
+ text = "Y"
+ intervals [61]:
+ xmin = 6.15
+ xmax = 6.26
+ text = "UW1"
+ intervals [62]:
+ xmin = 6.26
+ xmax = 6.41
+ text = "F"
+ intervals [63]:
+ xmin = 6.41
+ xmax = 6.54
+ text = "AE1"
+ intervals [64]:
+ xmin = 6.54
+ xmax = 6.63
+ text = "SH"
+ intervals [65]:
+ xmin = 6.63
+ xmax = 6.66
+ text = "AH0"
+ intervals [66]:
+ xmin = 6.66
+ xmax = 6.71
+ text = "N"
+ intervals [67]:
+ xmin = 6.71
+ xmax = 6.75
+ text = "IH0"
+ intervals [68]:
+ xmin = 6.75
+ xmax = 6.81
+ text = "V"
+ intervals [69]:
+ xmin = 6.81
+ xmax = 6.93
+ text = "EH1"
+ intervals [70]:
+ xmin = 6.93
+ xmax = 6.97
+ text = "N"
+ intervals [71]:
+ xmin = 6.97
+ xmax = 7.02
+ text = "T"
+ intervals [72]:
+ xmin = 7.02
+ xmax = 7.17
+ text = "S"
+ intervals [73]:
+ xmin = 7.17
+ xmax = 7.43
+ text = ""
+ intervals [74]:
+ xmin = 7.43
+ xmax = 7.55
+ text = "S"
+ intervals [75]:
+ xmin = 7.55
+ xmax = 7.63
+ text = "AH1"
+ intervals [76]:
+ xmin = 7.63
+ xmax = 7.76
+ text = "CH"
+ intervals [77]:
+ xmin = 7.76
+ xmax = 7.94
+ text = "EH1"
+ intervals [78]:
+ xmin = 7.94
+ xmax = 8.14
+ text = "Z"
+ intervals [79]:
+ xmin = 8.14
+ xmax = 8.19
+ text = ""
+ intervals [80]:
+ xmin = 8.19
+ xmax = 8.28
+ text = "DH"
+ intervals [81]:
+ xmin = 8.28
+ xmax = 8.34
+ text = "AH0"
+ intervals [82]:
+ xmin = 8.34
+ xmax = 8.44
+ text = "N"
+ intervals [83]:
+ xmin = 8.44
+ xmax = 8.47
+ text = "UW1"
+ intervals [84]:
+ xmin = 8.47
+ xmax = 8.52
+ text = "Y"
+ intervals [85]:
+ xmin = 8.52
+ xmax = 8.56
+ text = "AO1"
+ intervals [86]:
+ xmin = 8.56
+ xmax = 8.62
+ text = "R"
+ intervals [87]:
+ xmin = 8.62
+ xmax = 8.68
+ text = "K"
+ intervals [88]:
+ xmin = 8.68
+ xmax = 8.79
+ text = "F"
+ intervals [89]:
+ xmin = 8.79
+ xmax = 8.93
+ text = "AE1"
+ intervals [90]:
+ xmin = 8.93
+ xmax = 9.03
+ text = "SH"
+ intervals [91]:
+ xmin = 9.03
+ xmax = 9.07
+ text = "AH0"
+ intervals [92]:
+ xmin = 9.07
+ xmax = 9.12
+ text = "N"
+ intervals [93]:
+ xmin = 9.12
+ xmax = 9.19
+ text = "W"
+ intervals [94]:
+ xmin = 9.19
+ xmax = 9.33
+ text = "IY1"
+ intervals [95]:
+ xmin = 9.33
+ xmax = 9.42
+ text = "K"
+ intervals [96]:
+ xmin = 9.42
+ xmax = 9.46
+ text = "DH"
+ intervals [97]:
+ xmin = 9.46
+ xmax = 9.49
+ text = "AH0"
+ intervals [98]:
+ xmin = 9.49
+ xmax = 9.57
+ text = "P"
+ intervals [99]:
+ xmin = 9.57
+ xmax = 9.64
+ text = "EH1"
+ intervals [100]:
+ xmin = 9.64
+ xmax = 9.75
+ text = "R"
+ intervals [101]:
+ xmin = 9.75
+ xmax = 9.8
+ text = "IH0"
+ intervals [102]:
+ xmin = 9.8
+ xmax = 9.87
+ text = "S"
+ intervals [103]:
+ xmin = 9.87
+ xmax = 9.93
+ text = "F"
+ intervals [104]:
+ xmin = 9.93
+ xmax = 10.09
+ text = "AE1"
+ intervals [105]:
+ xmin = 10.09
+ xmax = 10.19
+ text = "SH"
+ intervals [106]:
+ xmin = 10.19
+ xmax = 10.22
+ text = "AH0"
+ intervals [107]:
+ xmin = 10.22
+ xmax = 10.25
+ text = "N"
+ intervals [108]:
+ xmin = 10.25
+ xmax = 10.32
+ text = "W"
+ intervals [109]:
+ xmin = 10.32
+ xmax = 10.49
+ text = "IY1"
+ intervals [110]:
+ xmin = 10.49
+ xmax = 10.56
+ text = "K"
+ intervals [111]:
+ xmin = 10.56
+ xmax = 10.6
+ text = "DH"
+ intervals [112]:
+ xmin = 10.6
+ xmax = 10.66
+ text = "AH0"
+ intervals [113]:
+ xmin = 10.66
+ xmax = 10.76
+ text = "L"
+ intervals [114]:
+ xmin = 10.76
+ xmax = 10.81
+ text = "AH1"
+ intervals [115]:
+ xmin = 10.81
+ xmax = 10.87
+ text = "N"
+ intervals [116]:
+ xmin = 10.87
+ xmax = 10.92
+ text = "D"
+ intervals [117]:
+ xmin = 10.92
+ xmax = 10.97
+ text = "AH0"
+ intervals [118]:
+ xmin = 10.97
+ xmax = 11.07
+ text = "N"
+ intervals [119]:
+ xmin = 11.07
+ xmax = 11.18
+ text = "F"
+ intervals [120]:
+ xmin = 11.18
+ xmax = 11.31
+ text = "AE1"
+ intervals [121]:
+ xmin = 11.31
+ xmax = 11.42
+ text = "SH"
+ intervals [122]:
+ xmin = 11.42
+ xmax = 11.46
+ text = "AH0"
+ intervals [123]:
+ xmin = 11.46
+ xmax = 11.51
+ text = "N"
+ intervals [124]:
+ xmin = 11.51
+ xmax = 11.56
+ text = "W"
+ intervals [125]:
+ xmin = 11.56
+ xmax = 11.69
+ text = "IY1"
+ intervals [126]:
+ xmin = 11.69
+ xmax = 11.78
+ text = "K"
+ intervals [127]:
+ xmin = 11.78
+ xmax = 11.84
+ text = "AE1"
+ intervals [128]:
+ xmin = 11.84
+ xmax = 11.99
+ text = "N"
+ intervals [129]:
+ xmin = 11.99
+ xmax = 12.17
+ text = "D"
+ intervals [130]:
+ xmin = 12.17
+ xmax = 12.21
+ text = ""
+ intervals [131]:
+ xmin = 12.21
+ xmax = 12.36
+ text = "M"
+ intervals [132]:
+ xmin = 12.36
+ xmax = 12.48
+ text = "IH0"
+ intervals [133]:
+ xmin = 12.48
+ xmax = 12.55
+ text = "L"
+ intervals [134]:
+ xmin = 12.55
+ xmax = 12.73
+ text = "AA1"
+ intervals [135]:
+ xmin = 12.73
+ xmax = 12.83
+ text = "N"
+ intervals [136]:
+ xmin = 12.83
+ xmax = 12.92
+ text = "F"
+ intervals [137]:
+ xmin = 12.92
+ xmax = 13.06
+ text = "AE1"
+ intervals [138]:
+ xmin = 13.06
+ xmax = 13.16
+ text = "SH"
+ intervals [139]:
+ xmin = 13.16
+ xmax = 13.21
+ text = "AH0"
+ intervals [140]:
+ xmin = 13.21
+ xmax = 13.24
+ text = "N"
+ intervals [141]:
+ xmin = 13.24
+ xmax = 13.29
+ text = "W"
+ intervals [142]:
+ xmin = 13.29
+ xmax = 13.41
+ text = "IY1"
+ intervals [143]:
+ xmin = 13.41
+ xmax = 13.62
+ text = "K"
+ intervals [144]:
+ xmin = 13.62
+ xmax = 14.03
+ text = ""
+ intervals [145]:
+ xmin = 14.03
+ xmax = 14.11
+ text = "DH"
+ intervals [146]:
+ xmin = 14.11
+ xmax = 14.15
+ text = "AH1"
+ intervals [147]:
+ xmin = 14.15
+ xmax = 14.22
+ text = "R"
+ intervals [148]:
+ xmin = 14.22
+ xmax = 14.26
+ text = "EH1"
+ intervals [149]:
+ xmin = 14.26
+ xmax = 14.31
+ text = "S"
+ intervals [150]:
+ xmin = 14.31
+ xmax = 14.35
+ text = "T"
+ intervals [151]:
+ xmin = 14.35
+ xmax = 14.4
+ text = "AH0"
+ intervals [152]:
+ xmin = 14.4
+ xmax = 14.43
+ text = "V"
+ intervals [153]:
+ xmin = 14.43
+ xmax = 14.46
+ text = "DH"
+ intervals [154]:
+ xmin = 14.46
+ xmax = 14.49
+ text = "AH0"
+ intervals [155]:
+ xmin = 14.49
+ xmax = 14.55
+ text = "T"
+ intervals [156]:
+ xmin = 14.55
+ xmax = 14.73
+ text = "AY1"
+ intervals [157]:
+ xmin = 14.73
+ xmax = 14.8
+ text = "M"
+ intervals [158]:
+ xmin = 14.8
+ xmax = 14.87
+ text = "AY1"
+ intervals [159]:
+ xmin = 14.87
+ xmax = 14.96
+ text = "Y"
+ intervals [160]:
+ xmin = 14.96
+ xmax = 14.99
+ text = "UW1"
+ intervals [161]:
+ xmin = 14.99
+ xmax = 15.08
+ text = "ZH"
+ intervals [162]:
+ xmin = 15.08
+ xmax = 15.11
+ text = "AH0"
+ intervals [163]:
+ xmin = 15.11
+ xmax = 15.14
+ text = "L"
+ intervals [164]:
+ xmin = 15.14
+ xmax = 15.2
+ text = "IY0"
+ intervals [165]:
+ xmin = 15.2
+ xmax = 15.23
+ text = "G"
+ intervals [166]:
+ xmin = 15.23
+ xmax = 15.3
+ text = "OW1"
+ intervals [167]:
+ xmin = 15.3
+ xmax = 15.33
+ text = "T"
+ intervals [168]:
+ xmin = 15.33
+ xmax = 15.36
+ text = "AH0"
+ intervals [169]:
+ xmin = 15.36
+ xmax = 15.39
+ text = "DH"
+ intervals [170]:
+ xmin = 15.39
+ xmax = 15.44
+ text = "AH1"
+ intervals [171]:
+ xmin = 15.44
+ xmax = 15.51
+ text = "L"
+ intervals [172]:
+ xmin = 15.51
+ xmax = 15.67
+ text = "AY1"
+ intervals [173]:
+ xmin = 15.67
+ xmax = 15.71
+ text = "B"
+ intervals [174]:
+ xmin = 15.71
+ xmax = 15.74
+ text = "R"
+ intervals [175]:
+ xmin = 15.74
+ xmax = 15.83
+ text = "EH2"
+ intervals [176]:
+ xmin = 15.83
+ xmax = 15.9
+ text = "R"
+ intervals [177]:
+ xmin = 15.9
+ xmax = 15.93
+ text = "IY0"
+ intervals [178]:
+ xmin = 15.93
+ xmax = 15.96
+ text = "AH0"
+ intervals [179]:
+ xmin = 15.96
+ xmax = 15.99
+ text = "N"
+ intervals [180]:
+ xmin = 15.99
+ xmax = 16.04
+ text = "D"
+ intervals [181]:
+ xmin = 16.04
+ xmax = 16.11
+ text = "F"
+ intervals [182]:
+ xmin = 16.11
+ xmax = 16.18
+ text = "AY1"
+ intervals [183]:
+ xmin = 16.18
+ xmax = 16.21
+ text = "N"
+ intervals [184]:
+ xmin = 16.21
+ xmax = 16.25
+ text = "D"
+ intervals [185]:
+ xmin = 16.25
+ xmax = 16.29
+ text = "S"
+ intervals [186]:
+ xmin = 16.29
+ xmax = 16.32
+ text = "AH1"
+ intervals [187]:
+ xmin = 16.32
+ xmax = 16.35
+ text = "M"
+ intervals [188]:
+ xmin = 16.35
+ xmax = 16.38
+ text = "IH1"
+ intervals [189]:
+ xmin = 16.38
+ xmax = 16.41
+ text = "N"
+ intervals [190]:
+ xmin = 16.41
+ xmax = 16.46
+ text = "T"
+ intervals [191]:
+ xmin = 16.46
+ xmax = 16.49
+ text = "R"
+ intervals [192]:
+ xmin = 16.49
+ xmax = 16.53
+ text = "IH0"
+ intervals [193]:
+ xmin = 16.53
+ xmax = 16.57
+ text = "S"
+ intervals [194]:
+ xmin = 16.57
+ xmax = 16.6
+ text = "T"
+ intervals [195]:
+ xmin = 16.6
+ xmax = 16.64
+ text = "IH0"
+ intervals [196]:
+ xmin = 16.64
+ xmax = 16.71
+ text = "NG"
+ intervals [197]:
+ xmin = 16.71
+ xmax = 16.78
+ text = "B"
+ intervals [198]:
+ xmin = 16.78
+ xmax = 17.0
+ text = "UH1"
+ intervals [199]:
+ xmin = 17.0
+ xmax = 17.09
+ text = "K"
+ intervals [200]:
+ xmin = 17.09
+ xmax = 17.19
+ text = "S"
+ intervals [201]:
+ xmin = 17.19
+ xmax = 17.25
+ text = "AH0"
+ intervals [202]:
+ xmin = 17.25
+ xmax = 17.28
+ text = "N"
+ intervals [203]:
+ xmin = 17.28
+ xmax = 17.31
+ text = "D"
+ intervals [204]:
+ xmin = 17.31
+ xmax = 17.34
+ text = "DH"
+ intervals [205]:
+ xmin = 17.34
+ xmax = 17.42
+ text = "EH1"
+ intervals [206]:
+ xmin = 17.42
+ xmax = 17.51
+ text = "N"
+ intervals [207]:
+ xmin = 17.51
+ xmax = 17.58
+ text = "G"
+ intervals [208]:
+ xmin = 17.58
+ xmax = 17.63
+ text = "OW1"
+ intervals [209]:
+ xmin = 17.63
+ xmax = 17.67
+ text = "T"
+ intervals [210]:
+ xmin = 17.67
+ xmax = 17.7
+ text = "AH0"
+ intervals [211]:
+ xmin = 17.7
+ xmax = 17.78
+ text = "AH0"
+ intervals [212]:
+ xmin = 17.78
+ xmax = 17.89
+ text = "P"
+ intervals [213]:
+ xmin = 17.89
+ xmax = 17.95
+ text = "AA1"
+ intervals [214]:
+ xmin = 17.95
+ xmax = 18.04
+ text = "R"
+ intervals [215]:
+ xmin = 18.04
+ xmax = 18.08
+ text = "K"
+ intervals [216]:
+ xmin = 18.08
+ xmax = 18.11
+ text = "AH0"
+ intervals [217]:
+ xmin = 18.11
+ xmax = 18.14
+ text = "N"
+ intervals [218]:
+ xmin = 18.14
+ xmax = 18.17
+ text = "D"
+ intervals [219]:
+ xmin = 18.17
+ xmax = 18.2
+ text = "R"
+ intervals [220]:
+ xmin = 18.2
+ xmax = 18.25
+ text = "IH0"
+ intervals [221]:
+ xmin = 18.25
+ xmax = 18.33
+ text = "L"
+ intervals [222]:
+ xmin = 18.33
+ xmax = 18.53
+ text = "AE1"
+ intervals [223]:
+ xmin = 18.53
+ xmax = 18.58
+ text = "K"
+ intervals [224]:
+ xmin = 18.58
+ xmax = 18.75
+ text = "S"
+ intervals [225]:
+ xmin = 18.75
+ xmax = 19.04
+ text = ""
+ intervals [226]:
+ xmin = 19.04
+ xmax = 19.14
+ text = "DH"
+ intervals [227]:
+ xmin = 19.14
+ xmax = 19.18
+ text = "EH1"
+ intervals [228]:
+ xmin = 19.18
+ xmax = 19.22
+ text = "R"
+ intervals [229]:
+ xmin = 19.22
+ xmax = 19.27
+ text = "ER0"
+ intervals [230]:
+ xmin = 19.27
+ xmax = 19.34
+ text = "M"
+ intervals [231]:
+ xmin = 19.34
+ xmax = 19.39
+ text = "EH1"
+ intervals [232]:
+ xmin = 19.39
+ xmax = 19.43
+ text = "N"
+ intervals [233]:
+ xmin = 19.43
+ xmax = 19.5
+ text = "IY0"
+ intervals [234]:
+ xmin = 19.5
+ xmax = 19.56
+ text = "B"
+ intervals [235]:
+ xmin = 19.56
+ xmax = 19.66
+ text = "UH1"
+ intervals [236]:
+ xmin = 19.66
+ xmax = 19.72
+ text = "K"
+ intervals [237]:
+ xmin = 19.72
+ xmax = 19.78
+ text = "S"
+ intervals [238]:
+ xmin = 19.78
+ xmax = 19.81
+ text = "DH"
+ intervals [239]:
+ xmin = 19.81
+ xmax = 19.84
+ text = "AH0"
+ intervals [240]:
+ xmin = 19.84
+ xmax = 19.93
+ text = "T"
+ intervals [241]:
+ xmin = 19.93
+ xmax = 20.11
+ text = "AY1"
+ intervals [242]:
+ xmin = 20.11
+ xmax = 20.22
+ text = "F"
+ intervals [243]:
+ xmin = 20.22
+ xmax = 20.3
+ text = "AY1"
+ intervals [244]:
+ xmin = 20.3
+ xmax = 20.37
+ text = "N"
+ intervals [245]:
+ xmin = 20.37
+ xmax = 20.4
+ text = "D"
+ intervals [246]:
+ xmin = 20.4
+ xmax = 20.52
+ text = "IH1"
+ intervals [247]:
+ xmin = 20.52
+ xmax = 20.55
+ text = "N"
+ intervals [248]:
+ xmin = 20.55
+ xmax = 20.59
+ text = "T"
+ intervals [249]:
+ xmin = 20.59
+ xmax = 20.62
+ text = "R"
+ intervals [250]:
+ xmin = 20.62
+ xmax = 20.67
+ text = "AH0"
+ intervals [251]:
+ xmin = 20.67
+ xmax = 20.74
+ text = "S"
+ intervals [252]:
+ xmin = 20.74
+ xmax = 20.78
+ text = "T"
+ intervals [253]:
+ xmin = 20.78
+ xmax = 20.85
+ text = "IH0"
+ intervals [254]:
+ xmin = 20.85
+ xmax = 20.92
+ text = "NG"
+ intervals [255]:
+ xmin = 20.92
+ xmax = 21.02
+ text = "S"
+ intervals [256]:
+ xmin = 21.02
+ xmax = 21.06
+ text = "AH1"
+ intervals [257]:
+ xmin = 21.06
+ xmax = 21.15
+ text = "CH"
+ intervals [258]:
+ xmin = 21.15
+ xmax = 21.2
+ text = "EH1"
+ intervals [259]:
+ xmin = 21.2
+ xmax = 21.3
+ text = "Z"
+ intervals [260]:
+ xmin = 21.3
+ xmax = 21.36
+ text = "F"
+ intervals [261]:
+ xmin = 21.36
+ xmax = 21.47
+ text = "AE1"
+ intervals [262]:
+ xmin = 21.47
+ xmax = 21.56
+ text = "SH"
+ intervals [263]:
+ xmin = 21.56
+ xmax = 21.59
+ text = "AH0"
+ intervals [264]:
+ xmin = 21.59
+ xmax = 21.62
+ text = "N"
+ intervals [265]:
+ xmin = 21.62
+ xmax = 21.68
+ text = "M"
+ intervals [266]:
+ xmin = 21.68
+ xmax = 21.76
+ text = "AE1"
+ intervals [267]:
+ xmin = 21.76
+ xmax = 21.81
+ text = "G"
+ intervals [268]:
+ xmin = 21.81
+ xmax = 21.85
+ text = "AH0"
+ intervals [269]:
+ xmin = 21.85
+ xmax = 21.9
+ text = "Z"
+ intervals [270]:
+ xmin = 21.9
+ xmax = 22.0
+ text = "IY2"
+ intervals [271]:
+ xmin = 22.0
+ xmax = 22.1
+ text = "N"
+ intervals [272]:
+ xmin = 22.1
+ xmax = 22.19
+ text = "Z"
+ intervals [273]:
+ xmin = 22.19
+ xmax = 22.22
+ text = "IH2"
+ intervals [274]:
+ xmin = 22.22
+ xmax = 22.29
+ text = "N"
+ intervals [275]:
+ xmin = 22.29
+ xmax = 22.34
+ text = "S"
+ intervals [276]:
+ xmin = 22.34
+ xmax = 22.38
+ text = "P"
+ intervals [277]:
+ xmin = 22.38
+ xmax = 22.48
+ text = "ER0"
+ intervals [278]:
+ xmin = 22.48
+ xmax = 22.55
+ text = "EY1"
+ intervals [279]:
+ xmin = 22.55
+ xmax = 22.64
+ text = "SH"
+ intervals [280]:
+ xmin = 22.64
+ xmax = 22.67
+ text = "AH0"
+ intervals [281]:
+ xmin = 22.67
+ xmax = 22.7
+ text = "N"
+ intervals [282]:
+ xmin = 22.7
+ xmax = 22.73
+ text = "AH0"
+ intervals [283]:
+ xmin = 22.73
+ xmax = 22.8
+ text = "L"
+ intervals [284]:
+ xmin = 22.8
+ xmax = 22.88
+ text = "B"
+ intervals [285]:
+ xmin = 22.88
+ xmax = 23.03
+ text = "UH1"
+ intervals [286]:
+ xmin = 23.03
+ xmax = 23.09
+ text = "K"
+ intervals [287]:
+ xmin = 23.09
+ xmax = 23.15
+ text = "S"
+ intervals [288]:
+ xmin = 23.15
+ xmax = 23.24
+ text = "AH0"
+ intervals [289]:
+ xmin = 23.24
+ xmax = 23.35
+ text = "N"
+ intervals [290]:
+ xmin = 23.35
+ xmax = 23.44
+ text = "D"
+ intervals [291]:
+ xmin = 23.44
+ xmax = 23.5
+ text = "P"
+ intervals [292]:
+ xmin = 23.5
+ xmax = 23.55
+ text = "R"
+ intervals [293]:
+ xmin = 23.55
+ xmax = 23.59
+ text = "AH0"
+ intervals [294]:
+ xmin = 23.59
+ xmax = 23.69
+ text = "F"
+ intervals [295]:
+ xmin = 23.69
+ xmax = 23.76
+ text = "EH1"
+ intervals [296]:
+ xmin = 23.76
+ xmax = 23.87
+ text = "SH"
+ intervals [297]:
+ xmin = 23.87
+ xmax = 23.9
+ text = "AH0"
+ intervals [298]:
+ xmin = 23.9
+ xmax = 23.94
+ text = "N"
+ intervals [299]:
+ xmin = 23.94
+ xmax = 23.98
+ text = "AH0"
+ intervals [300]:
+ xmin = 23.98
+ xmax = 24.04
+ text = "L"
+ intervals [301]:
+ xmin = 24.04
+ xmax = 24.12
+ text = "B"
+ intervals [302]:
+ xmin = 24.12
+ xmax = 24.24
+ text = "UH1"
+ intervals [303]:
+ xmin = 24.24
+ xmax = 24.32
+ text = "K"
+ intervals [304]:
+ xmin = 24.32
+ xmax = 24.46
+ text = "S"
+ intervals [305]:
+ xmin = 24.46
+ xmax = 24.83
+ text = ""
+ intervals [306]:
+ xmin = 24.83
+ xmax = 24.91
+ text = "DH"
+ intervals [307]:
+ xmin = 24.91
+ xmax = 24.98
+ text = "IY1"
+ intervals [308]:
+ xmin = 24.98
+ xmax = 25.06
+ text = "Z"
+ intervals [309]:
+ xmin = 25.06
+ xmax = 25.13
+ text = "B"
+ intervals [310]:
+ xmin = 25.13
+ xmax = 25.23
+ text = "UH1"
+ intervals [311]:
+ xmin = 25.23
+ xmax = 25.3
+ text = "K"
+ intervals [312]:
+ xmin = 25.3
+ xmax = 25.37
+ text = "S"
+ intervals [313]:
+ xmin = 25.37
+ xmax = 25.44
+ text = "K"
+ intervals [314]:
+ xmin = 25.44
+ xmax = 25.51
+ text = "AH0"
+ intervals [315]:
+ xmin = 25.51
+ xmax = 25.54
+ text = "N"
+ intervals [316]:
+ xmin = 25.54
+ xmax = 25.59
+ text = "G"
+ intervals [317]:
+ xmin = 25.59
+ xmax = 25.63
+ text = "IH1"
+ intervals [318]:
+ xmin = 25.63
+ xmax = 25.66
+ text = "V"
+ intervals [319]:
+ xmin = 25.66
+ xmax = 25.71
+ text = "M"
+ intervals [320]:
+ xmin = 25.71
+ xmax = 25.76
+ text = "IY1"
+ intervals [321]:
+ xmin = 25.76
+ xmax = 25.82
+ text = "DH"
+ intervals [322]:
+ xmin = 25.82
+ xmax = 25.86
+ text = "AH0"
+ intervals [323]:
+ xmin = 25.86
+ xmax = 25.95
+ text = "M"
+ intervals [324]:
+ xmin = 25.95
+ xmax = 26.01
+ text = "OW2"
+ intervals [325]:
+ xmin = 26.01
+ xmax = 26.06
+ text = "T"
+ intervals [326]:
+ xmin = 26.06
+ xmax = 26.1
+ text = "AH0"
+ intervals [327]:
+ xmin = 26.1
+ xmax = 26.19
+ text = "V"
+ intervals [328]:
+ xmin = 26.19
+ xmax = 26.32
+ text = "EY1"
+ intervals [329]:
+ xmin = 26.32
+ xmax = 26.42
+ text = "SH"
+ intervals [330]:
+ xmin = 26.42
+ xmax = 26.51
+ text = "AH0"
+ intervals [331]:
+ xmin = 26.51
+ xmax = 26.85
+ text = "N"
+ intervals [332]:
+ xmin = 26.85
+ xmax = 26.88
+ text = ""
+ intervals [333]:
+ xmin = 26.88
+ xmax = 27.0
+ text = "T"
+ intervals [334]:
+ xmin = 27.0
+ xmax = 27.07
+ text = "IH0"
+ intervals [335]:
+ xmin = 27.07
+ xmax = 27.13
+ text = "B"
+ intervals [336]:
+ xmin = 27.13
+ xmax = 27.37
+ text = "IY1"
+ intervals [337]:
+ xmin = 27.37
+ xmax = 27.5
+ text = "HH"
+ intervals [338]:
+ xmin = 27.5
+ xmax = 27.55
+ text = "EH1"
+ intervals [339]:
+ xmin = 27.55
+ xmax = 27.68
+ text = "L"
+ intervals [340]:
+ xmin = 27.68
+ xmax = 27.72
+ text = "TH"
+ intervals [341]:
+ xmin = 27.72
+ xmax = 27.86
+ text = "IY0"
+ intervals [342]:
+ xmin = 27.86
+ xmax = 28.01
+ text = "ER0"
+ intervals [343]:
+ xmin = 28.01
+ xmax = 28.09
+ text = "AE1"
+ intervals [344]:
+ xmin = 28.09
+ xmax = 28.12
+ text = "N"
+ intervals [345]:
+ xmin = 28.12
+ xmax = 28.18
+ text = "D"
+ intervals [346]:
+ xmin = 28.18
+ xmax = 28.25
+ text = "EH2"
+ intervals [347]:
+ xmin = 28.25
+ xmax = 28.32
+ text = "N"
+ intervals [348]:
+ xmin = 28.32
+ xmax = 28.41
+ text = "ER0"
+ intervals [349]:
+ xmin = 28.41
+ xmax = 28.51
+ text = "JH"
+ intervals [350]:
+ xmin = 28.51
+ xmax = 28.59
+ text = "EH1"
+ intervals [351]:
+ xmin = 28.59
+ xmax = 28.62
+ text = "T"
+ intervals [352]:
+ xmin = 28.62
+ xmax = 28.71
+ text = "IH0"
+ intervals [353]:
+ xmin = 28.71
+ xmax = 28.9
+ text = "K"
+ intervals [354]:
+ xmin = 28.9
+ xmax = 29.1
+ text = ""
+ intervals [355]:
+ xmin = 29.1
+ xmax = 29.24
+ text = "AE1"
+ intervals [356]:
+ xmin = 29.24
+ xmax = 29.27
+ text = "N"
+ intervals [357]:
+ xmin = 29.27
+ xmax = 29.3
+ text = "D"
+ intervals [358]:
+ xmin = 29.3
+ xmax = 29.33
+ text = "DH"
+ intervals [359]:
+ xmin = 29.33
+ xmax = 29.37
+ text = "AH0"
+ intervals [360]:
+ xmin = 29.37
+ xmax = 29.47
+ text = "L"
+ intervals [361]:
+ xmin = 29.47
+ xmax = 29.62
+ text = "AE1"
+ intervals [362]:
+ xmin = 29.62
+ xmax = 29.74
+ text = "S"
+ intervals [363]:
+ xmin = 29.74
+ xmax = 29.8
+ text = "TH"
+ intervals [364]:
+ xmin = 29.8
+ xmax = 29.86
+ text = "IH1"
+ intervals [365]:
+ xmin = 29.86
+ xmax = 29.94
+ text = "NG"
+ intervals [366]:
+ xmin = 29.94
+ xmax = 30.14
+ text = "AY1"
+ intervals [367]:
+ xmin = 30.14
+ xmax = 30.23
+ text = "L"
+ intervals [368]:
+ xmin = 30.23
+ xmax = 30.38
+ text = "AY1"
+ intervals [369]:
+ xmin = 30.38
+ xmax = 30.42
+ text = "K"
+ intervals [370]:
+ xmin = 30.42
+ xmax = 30.48
+ text = "T"
+ intervals [371]:
+ xmin = 30.48
+ xmax = 30.53
+ text = "IH0"
+ intervals [372]:
+ xmin = 30.53
+ xmax = 30.59
+ text = "D"
+ intervals [373]:
+ xmin = 30.59
+ xmax = 30.84
+ text = "UW1"
+ intervals [374]:
+ xmin = 30.84
+ xmax = 30.97
+ text = "W"
+ intervals [375]:
+ xmin = 30.97
+ xmax = 31.03
+ text = "EH1"
+ intervals [376]:
+ xmin = 31.03
+ xmax = 31.22
+ text = "N"
+ intervals [377]:
+ xmin = 31.22
+ xmax = 31.35
+ text = "AY1"
+ intervals [378]:
+ xmin = 31.35
+ xmax = 31.43
+ text = "M"
+ intervals [379]:
+ xmin = 31.43
+ xmax = 31.55
+ text = "F"
+ intervals [380]:
+ xmin = 31.55
+ xmax = 31.65
+ text = "R"
+ intervals [381]:
+ xmin = 31.65
+ xmax = 31.87
+ text = "IY1"
+ intervals [382]:
+ xmin = 31.87
+ xmax = 31.91
+ text = "IH1"
+ intervals [383]:
+ xmin = 31.91
+ xmax = 31.99
+ text = "Z"
+ intervals [384]:
+ xmin = 31.99
+ xmax = 32.06
+ text = "IH1"
+ intervals [385]:
+ xmin = 32.06
+ xmax = 32.11
+ text = "T"
+ intervals [386]:
+ xmin = 32.11
+ xmax = 32.2
+ text = "AW1"
+ intervals [387]:
+ xmin = 32.2
+ xmax = 32.23
+ text = "T"
+ intervals [388]:
+ xmin = 32.23
+ xmax = 32.27
+ text = "W"
+ intervals [389]:
+ xmin = 32.27
+ xmax = 32.32
+ text = "IH0"
+ intervals [390]:
+ xmin = 32.32
+ xmax = 32.35
+ text = "TH"
+ intervals [391]:
+ xmin = 32.35
+ xmax = 32.39
+ text = "M"
+ intervals [392]:
+ xmin = 32.39
+ xmax = 32.48
+ text = "AY1"
+ intervals [393]:
+ xmin = 32.48
+ xmax = 32.61
+ text = "F"
+ intervals [394]:
+ xmin = 32.61
+ xmax = 32.72
+ text = "AE1"
+ intervals [395]:
+ xmin = 32.72
+ xmax = 32.76
+ text = "M"
+ intervals [396]:
+ xmin = 32.76
+ xmax = 32.81
+ text = "L"
+ intervals [397]:
+ xmin = 32.81
+ xmax = 32.86
+ text = "IY0"
+ intervals [398]:
+ xmin = 32.86
+ xmax = 32.92
+ text = "M"
+ intervals [399]:
+ xmin = 32.92
+ xmax = 32.97
+ text = "EH1"
+ intervals [400]:
+ xmin = 32.97
+ xmax = 33.0
+ text = "M"
+ intervals [401]:
+ xmin = 33.0
+ xmax = 33.05
+ text = "B"
+ intervals [402]:
+ xmin = 33.05
+ xmax = 33.16
+ text = "ER0"
+ intervals [403]:
+ xmin = 33.16
+ xmax = 33.33
+ text = "Z"
+ intervals [404]:
+ xmin = 33.33
+ xmax = 33.51
+ text = ""
+ intervals [405]:
+ xmin = 33.51
+ xmax = 33.75
+ text = "Y"
+ intervals [406]:
+ xmin = 33.75
+ xmax = 33.89
+ text = "UW1"
+ intervals [407]:
+ xmin = 33.89
+ xmax = 33.97
+ text = "W"
+ intervals [408]:
+ xmin = 33.97
+ xmax = 34.02
+ text = "UH1"
+ intervals [409]:
+ xmin = 34.02
+ xmax = 34.11
+ text = "D"
+ intervals [410]:
+ xmin = 34.11
+ xmax = 34.16
+ text = "B"
+ intervals [411]:
+ xmin = 34.16
+ xmax = 34.29
+ text = "IY1"
+ intervals [412]:
+ xmin = 34.29
+ xmax = 34.36
+ text = "S"
+ intervals [413]:
+ xmin = 34.36
+ xmax = 34.42
+ text = "AH0"
+ intervals [414]:
+ xmin = 34.42
+ xmax = 34.53
+ text = "P"
+ intervals [415]:
+ xmin = 34.53
+ xmax = 34.63
+ text = "R"
+ intervals [416]:
+ xmin = 34.63
+ xmax = 34.91
+ text = "AY1"
+ intervals [417]:
+ xmin = 34.91
+ xmax = 35.02
+ text = "Z"
+ intervals [418]:
+ xmin = 35.02
+ xmax = 35.07
+ text = "D"
+ intervals [419]:
+ xmin = 35.07
+ xmax = 35.1
+ text = "T"
+ intervals [420]:
+ xmin = 35.1
+ xmax = 35.16
+ text = "IH0"
+ intervals [421]:
+ xmin = 35.16
+ xmax = 35.26
+ text = "N"
+ intervals [422]:
+ xmin = 35.26
+ xmax = 35.36
+ text = "OW1"
+ intervals [423]:
+ xmin = 35.36
+ xmax = 35.44
+ text = "DH"
+ intervals [424]:
+ xmin = 35.44
+ xmax = 35.47
+ text = "AE1"
+ intervals [425]:
+ xmin = 35.47
+ xmax = 35.5
+ text = "T"
+ intervals [426]:
+ xmin = 35.5
+ xmax = 35.64
+ text = "AY1"
+ intervals [427]:
+ xmin = 35.64
+ xmax = 35.7
+ text = "HH"
+ intervals [428]:
+ xmin = 35.7
+ xmax = 35.75
+ text = "AE1"
+ intervals [429]:
+ xmin = 35.75
+ xmax = 35.84
+ text = "V"
+ intervals [430]:
+ xmin = 35.84
+ xmax = 35.9
+ text = "T"
+ intervals [431]:
+ xmin = 35.9
+ xmax = 35.98
+ text = "R"
+ intervals [432]:
+ xmin = 35.98
+ xmax = 36.15
+ text = "AY1"
+ intervals [433]:
+ xmin = 36.15
+ xmax = 36.3
+ text = "D"
+ intervals [434]:
+ xmin = 36.3
+ xmax = 36.57
+ text = ""
+ intervals [435]:
+ xmin = 36.57
+ xmax = 36.92
+ text = "AO1"
+ intervals [436]:
+ xmin = 36.92
+ xmax = 36.99
+ text = "L"
+ intervals [437]:
+ xmin = 36.99
+ xmax = 37.03
+ text = "DH"
+ intervals [438]:
+ xmin = 37.03
+ xmax = 37.08
+ text = "AH1"
+ intervals [439]:
+ xmin = 37.08
+ xmax = 37.17
+ text = "R"
+ intervals [440]:
+ xmin = 37.17
+ xmax = 37.28
+ text = "EH1"
+ intervals [441]:
+ xmin = 37.28
+ xmax = 37.34
+ text = "S"
+ intervals [442]:
+ xmin = 37.34
+ xmax = 37.39
+ text = "T"
+ intervals [443]:
+ xmin = 37.39
+ xmax = 37.44
+ text = "R"
+ intervals [444]:
+ xmin = 37.44
+ xmax = 37.55
+ text = "AA2"
+ intervals [445]:
+ xmin = 37.55
+ xmax = 37.6
+ text = "N"
+ intervals [446]:
+ xmin = 37.6
+ xmax = 37.64
+ text = "T"
+ intervals [447]:
+ xmin = 37.64
+ xmax = 37.68
+ text = "S"
+ intervals [448]:
+ xmin = 37.68
+ xmax = 37.71
+ text = ""
+ intervals [449]:
+ xmin = 37.71
+ xmax = 37.77
+ text = "IH0"
+ intervals [450]:
+ xmin = 37.77
+ xmax = 37.83
+ text = "N"
+ intervals [451]:
+ xmin = 37.83
+ xmax = 37.87
+ text = "AA1"
+ intervals [452]:
+ xmin = 37.87
+ xmax = 37.95
+ text = "R"
+ intervals [453]:
+ xmin = 37.95
+ xmax = 38.12
+ text = "HH"
+ intervals [454]:
+ xmin = 38.12
+ xmax = 38.2
+ text = "Y"
+ intervals [455]:
+ xmin = 38.2
+ xmax = 38.33
+ text = "UW1"
+ intervals [456]:
+ xmin = 38.33
+ xmax = 38.5
+ text = "JH"
+ intervals [457]:
+ xmin = 38.5
+ xmax = 38.53
+ text = "K"
+ intervals [458]:
+ xmin = 38.53
+ xmax = 38.59
+ text = "AH0"
+ intervals [459]:
+ xmin = 38.59
+ xmax = 38.64
+ text = "M"
+ intervals [460]:
+ xmin = 38.64
+ xmax = 38.67
+ text = "Y"
+ intervals [461]:
+ xmin = 38.67
+ xmax = 38.7
+ text = "UW1"
+ intervals [462]:
+ xmin = 38.7
+ xmax = 38.76
+ text = "N"
+ intervals [463]:
+ xmin = 38.76
+ xmax = 38.79
+ text = "AH0"
+ intervals [464]:
+ xmin = 38.79
+ xmax = 38.82
+ text = "T"
+ intervals [465]:
+ xmin = 38.82
+ xmax = 39.07
+ text = "IY0"
+ intervals [466]:
+ xmin = 39.07
+ xmax = 39.23
+ text = ""
+ intervals [467]:
+ xmin = 39.23
+ xmax = 39.6
+ text = "AY1"
+ intervals [468]:
+ xmin = 39.6
+ xmax = 39.81
+ text = "AE1"
+ intervals [469]:
+ xmin = 39.81
+ xmax = 39.86
+ text = "K"
+ intervals [470]:
+ xmin = 39.86
+ xmax = 39.93
+ text = "SH"
+ intervals [471]:
+ xmin = 39.93
+ xmax = 39.97
+ text = "AH0"
+ intervals [472]:
+ xmin = 39.97
+ xmax = 40.0
+ text = "L"
+ intervals [473]:
+ xmin = 40.0
+ xmax = 40.09
+ text = "IY0"
+ intervals [474]:
+ xmin = 40.09
+ xmax = 40.17
+ text = "G"
+ intervals [475]:
+ xmin = 40.17
+ xmax = 40.26
+ text = "IH1"
+ intervals [476]:
+ xmin = 40.26
+ xmax = 40.32
+ text = "V"
+ intervals [477]:
+ xmin = 40.32
+ xmax = 40.5
+ text = "IY1"
+ intervals [478]:
+ xmin = 40.5
+ xmax = 40.61
+ text = "CH"
+ intervals [479]:
+ xmin = 40.61
+ xmax = 40.7
+ text = "R"
+ intervals [480]:
+ xmin = 40.7
+ xmax = 40.78
+ text = "EH1"
+ intervals [481]:
+ xmin = 40.78
+ xmax = 40.83
+ text = "S"
+ intervals [482]:
+ xmin = 40.83
+ xmax = 40.9
+ text = "T"
+ intervals [483]:
+ xmin = 40.9
+ xmax = 40.94
+ text = "R"
+ intervals [484]:
+ xmin = 40.94
+ xmax = 41.02
+ text = "AA2"
+ intervals [485]:
+ xmin = 41.02
+ xmax = 41.05
+ text = "N"
+ intervals [486]:
+ xmin = 41.05
+ xmax = 41.08
+ text = "T"
+ intervals [487]:
+ xmin = 41.08
+ xmax = 41.15
+ text = "AH0"
+ intervals [488]:
+ xmin = 41.15
+ xmax = 41.29
+ text = "S"
+ intervals [489]:
+ xmin = 41.29
+ xmax = 41.33
+ text = "K"
+ intervals [490]:
+ xmin = 41.33
+ xmax = 41.44
+ text = "AO1"
+ intervals [491]:
+ xmin = 41.44
+ xmax = 41.55
+ text = "R"
+ intervals [492]:
+ xmin = 41.55
+ xmax = 41.61
+ text = "B"
+ intervals [493]:
+ xmin = 41.61
+ xmax = 41.73
+ text = "EY1"
+ intervals [494]:
+ xmin = 41.73
+ xmax = 41.77
+ text = "S"
+ intervals [495]:
+ xmin = 41.77
+ xmax = 41.82
+ text = "T"
+ intervals [496]:
+ xmin = 41.82
+ xmax = 41.85
+ text = "AA1"
+ intervals [497]:
+ xmin = 41.85
+ xmax = 41.89
+ text = "N"
+ intervals [498]:
+ xmin = 41.89
+ xmax = 41.98
+ text = "HH"
+ intervals [499]:
+ xmin = 41.98
+ xmax = 42.05
+ text = "AW1"
+ intervals [500]:
+ xmin = 42.05
+ xmax = 42.11
+ text = "G"
+ intervals [501]:
+ xmin = 42.11
+ xmax = 42.14
+ text = "IH0"
+ intervals [502]:
+ xmin = 42.14
+ xmax = 42.17
+ text = "D"
+ intervals [503]:
+ xmin = 42.17
+ xmax = 42.2
+ text = "DH"
+ intervals [504]:
+ xmin = 42.2
+ xmax = 42.23
+ text = "IY0"
+ intervals [505]:
+ xmin = 42.23
+ xmax = 42.35
+ text = "F"
+ intervals [506]:
+ xmin = 42.35
+ xmax = 42.48
+ text = "UW1"
+ intervals [507]:
+ xmin = 42.48
+ xmax = 42.51
+ text = "D"
+ intervals [508]:
+ xmin = 42.51
+ xmax = 42.71
+ text = "IH1"
+ intervals [509]:
+ xmin = 42.71
+ xmax = 42.85
+ text = "Z"
+ intervals [510]:
+ xmin = 42.85
+ xmax = 43.13
+ text = ""
+ intervals [511]:
+ xmin = 43.13
+ xmax = 43.28
+ text = "HH"
+ intervals [512]:
+ xmin = 43.28
+ xmax = 43.36
+ text = "AW1"
+ intervals [513]:
+ xmin = 43.36
+ xmax = 43.43
+ text = "G"
+ intervals [514]:
+ xmin = 43.43
+ xmax = 43.46
+ text = "IH0"
+ intervals [515]:
+ xmin = 43.46
+ xmax = 43.51
+ text = "D"
+ intervals [516]:
+ xmin = 43.51
+ xmax = 43.56
+ text = "DH"
+ intervals [517]:
+ xmin = 43.56
+ xmax = 43.62
+ text = "IY0"
+ intervals [518]:
+ xmin = 43.62
+ xmax = 43.65
+ text = "IH0"
+ intervals [519]:
+ xmin = 43.65
+ xmax = 43.69
+ text = "N"
+ intervals [520]:
+ xmin = 43.69
+ xmax = 43.78
+ text = "V"
+ intervals [521]:
+ xmin = 43.78
+ xmax = 43.89
+ text = "AY1"
+ intervals [522]:
+ xmin = 43.89
+ xmax = 43.92
+ text = "R"
+ intervals [523]:
+ xmin = 43.92
+ xmax = 43.95
+ text = "AH0"
+ intervals [524]:
+ xmin = 43.95
+ xmax = 43.98
+ text = "N"
+ intervals [525]:
+ xmin = 43.98
+ xmax = 44.01
+ text = "M"
+ intervals [526]:
+ xmin = 44.01
+ xmax = 44.04
+ text = "AH0"
+ intervals [527]:
+ xmin = 44.04
+ xmax = 44.07
+ text = "N"
+ intervals [528]:
+ xmin = 44.07
+ xmax = 44.1
+ text = "T"
+ intervals [529]:
+ xmin = 44.1
+ xmax = 44.25
+ text = "IH1"
+ intervals [530]:
+ xmin = 44.25
+ xmax = 44.4
+ text = "Z"
+ intervals [531]:
+ xmin = 44.4
+ xmax = 44.49
+ text = ""
+ intervals [532]:
+ xmin = 44.49
+ xmax = 44.79
+ text = "AE1"
+ intervals [533]:
+ xmin = 44.79
+ xmax = 44.9
+ text = "N"
+ intervals [534]:
+ xmin = 44.9
+ xmax = 44.98
+ text = "D"
+ intervals [535]:
+ xmin = 44.98
+ xmax = 45.26
+ text = "AE1"
+ intervals [536]:
+ xmin = 45.26
+ xmax = 45.34
+ text = "T"
+ intervals [537]:
+ xmin = 45.34
+ xmax = 45.39
+ text = "DH"
+ intervals [538]:
+ xmin = 45.39
+ xmax = 45.62
+ text = "AH1"
+ intervals [539]:
+ xmin = 45.62
+ xmax = 45.75
+ text = "S"
+ intervals [540]:
+ xmin = 45.75
+ xmax = 45.87
+ text = "EY1"
+ intervals [541]:
+ xmin = 45.87
+ xmax = 45.91
+ text = "M"
+ intervals [542]:
+ xmin = 45.91
+ xmax = 46.01
+ text = "T"
+ intervals [543]:
+ xmin = 46.01
+ xmax = 46.19
+ text = "AY1"
+ intervals [544]:
+ xmin = 46.19
+ xmax = 46.29
+ text = "M"
+ intervals [545]:
+ xmin = 46.29
+ xmax = 46.42
+ text = "AY1"
+ intervals [546]:
+ xmin = 46.42
+ xmax = 46.45
+ text = "W"
+ intervals [547]:
+ xmin = 46.45
+ xmax = 46.48
+ text = "AH0"
+ intervals [548]:
+ xmin = 46.48
+ xmax = 46.54
+ text = "L"
+ intervals [549]:
+ xmin = 46.54
+ xmax = 46.62
+ text = "R"
+ intervals [550]:
+ xmin = 46.62
+ xmax = 46.69
+ text = "AY1"
+ intervals [551]:
+ xmin = 46.69
+ xmax = 46.74
+ text = "T"
+ intervals [552]:
+ xmin = 46.74
+ xmax = 46.82
+ text = "D"
+ intervals [553]:
+ xmin = 46.82
+ xmax = 46.91
+ text = "AW1"
+ intervals [554]:
+ xmin = 46.91
+ xmax = 46.94
+ text = "N"
+ intervals [555]:
+ xmin = 46.94
+ xmax = 46.97
+ text = "DH"
+ intervals [556]:
+ xmin = 46.97
+ xmax = 47.02
+ text = "AH1"
+ intervals [557]:
+ xmin = 47.02
+ xmax = 47.1
+ text = "T"
+ intervals [558]:
+ xmin = 47.1
+ xmax = 47.19
+ text = "AY1"
+ intervals [559]:
+ xmin = 47.19
+ xmax = 47.24
+ text = "P"
+ intervals [560]:
+ xmin = 47.24
+ xmax = 47.29
+ text = "AH0"
+ intervals [561]:
+ xmin = 47.29
+ xmax = 47.39
+ text = "V"
+ intervals [562]:
+ xmin = 47.39
+ xmax = 47.45
+ text = "F"
+ intervals [563]:
+ xmin = 47.45
+ xmax = 47.64
+ text = "UW1"
+ intervals [564]:
+ xmin = 47.64
+ xmax = 47.8
+ text = "D"
+ intervals [565]:
+ xmin = 47.8
+ xmax = 48.03
+ text = ""
+ intervals [566]:
+ xmin = 48.03
+ xmax = 48.1
+ text = "DH"
+ intervals [567]:
+ xmin = 48.1
+ xmax = 48.24
+ text = "EY1"
+ intervals [568]:
+ xmin = 48.24
+ xmax = 48.37
+ text = "S"
+ intervals [569]:
+ xmin = 48.37
+ xmax = 48.58
+ text = "ER1"
+ intervals [570]:
+ xmin = 48.58
+ xmax = 48.76
+ text = "V"
+ intervals [571]:
+ xmin = 48.76
+ xmax = 49.42
+ text = ""
+ intervals [572]:
+ xmin = 49.42
+ xmax = 49.61
+ text = "S"
+ intervals [573]:
+ xmin = 49.61
+ xmax = 49.9
+ text = "OW1"
+ intervals [574]:
+ xmin = 49.9
+ xmax = 50.09
+ text = "W"
+ intervals [575]:
+ xmin = 50.09
+ xmax = 50.22
+ text = "EH1"
+ intervals [576]:
+ xmin = 50.22
+ xmax = 50.46
+ text = "N"
+ intervals [577]:
+ xmin = 50.46
+ xmax = 50.49
+ text = ""
+ intervals [578]:
+ xmin = 50.49
+ xmax = 50.58
+ text = "Y"
+ intervals [579]:
+ xmin = 50.58
+ xmax = 50.67
+ text = "UW1"
+ intervals [580]:
+ xmin = 50.67
+ xmax = 50.85
+ text = "R"
+ intervals [581]:
+ xmin = 50.85
+ xmax = 50.94
+ text = "S"
+ intervals [582]:
+ xmin = 50.94
+ xmax = 50.98
+ text = "OW1"
+ intervals [583]:
+ xmin = 50.98
+ xmax = 51.03
+ text = "W"
+ intervals [584]:
+ xmin = 51.03
+ xmax = 51.06
+ text = "EH1"
+ intervals [585]:
+ xmin = 51.06
+ xmax = 51.13
+ text = "N"
+ intervals [586]:
+ xmin = 51.13
+ xmax = 51.24
+ text = "IY1"
+ intervals [587]:
+ xmin = 51.24
+ xmax = 51.35
+ text = "CH"
+ intervals [588]:
+ xmin = 51.35
+ xmax = 51.41
+ text = "T"
+ intervals [589]:
+ xmin = 51.41
+ xmax = 51.49
+ text = "AY1"
+ intervals [590]:
+ xmin = 51.49
+ xmax = 51.55
+ text = "M"
+ intervals [591]:
+ xmin = 51.55
+ xmax = 51.62
+ text = "AH0"
+ intervals [592]:
+ xmin = 51.62
+ xmax = 51.69
+ text = "F"
+ intervals [593]:
+ xmin = 51.69
+ xmax = 51.74
+ text = "R"
+ intervals [594]:
+ xmin = 51.74
+ xmax = 51.8
+ text = "EH1"
+ intervals [595]:
+ xmin = 51.8
+ xmax = 51.85
+ text = "N"
+ intervals [596]:
+ xmin = 51.85
+ xmax = 51.91
+ text = "D"
+ intervals [597]:
+ xmin = 51.91
+ xmax = 51.98
+ text = "K"
+ intervals [598]:
+ xmin = 51.98
+ xmax = 52.03
+ text = "AH1"
+ intervals [599]:
+ xmin = 52.03
+ xmax = 52.14
+ text = "M"
+ intervals [600]:
+ xmin = 52.14
+ xmax = 52.32
+ text = "Z"
+ intervals [601]:
+ xmin = 52.32
+ xmax = 52.37
+ text = "T"
+ intervals [602]:
+ xmin = 52.37
+ xmax = 52.46
+ text = "UW1"
+ intervals [603]:
+ xmin = 52.46
+ xmax = 52.53
+ text = "DH"
+ intervals [604]:
+ xmin = 52.53
+ xmax = 52.59
+ text = "AH0"
+ intervals [605]:
+ xmin = 52.59
+ xmax = 52.68
+ text = "S"
+ intervals [606]:
+ xmin = 52.68
+ xmax = 52.74
+ text = "IH1"
+ intervals [607]:
+ xmin = 52.74
+ xmax = 52.77
+ text = "T"
+ intervals [608]:
+ xmin = 52.77
+ xmax = 52.9
+ text = "IY0"
+ intervals [609]:
+ xmin = 52.9
+ xmax = 52.97
+ text = "T"
+ intervals [610]:
+ xmin = 52.97
+ xmax = 53.07
+ text = "UW1"
+ intervals [611]:
+ xmin = 53.07
+ xmax = 53.12
+ text = "IH0"
+ intervals [612]:
+ xmin = 53.12
+ xmax = 53.17
+ text = "N"
+ intervals [613]:
+ xmin = 53.17
+ xmax = 53.26
+ text = "JH"
+ intervals [614]:
+ xmin = 53.26
+ xmax = 53.35
+ text = "OY1"
+ intervals [615]:
+ xmin = 53.35
+ xmax = 53.46
+ text = "T"
+ intervals [616]:
+ xmin = 53.46
+ xmax = 53.59
+ text = "AY1"
+ intervals [617]:
+ xmin = 53.59
+ xmax = 53.62
+ text = "M"
+ intervals [618]:
+ xmin = 53.62
+ xmax = 53.65
+ text = "W"
+ intervals [619]:
+ xmin = 53.65
+ xmax = 53.7
+ text = "IH1"
+ intervals [620]:
+ xmin = 53.7
+ xmax = 53.74
+ text = "DH"
+ intervals [621]:
+ xmin = 53.74
+ xmax = 53.81
+ text = "M"
+ intervals [622]:
+ xmin = 53.81
+ xmax = 54.02
+ text = "IY1"
+ intervals [623]:
+ xmin = 54.02
+ xmax = 54.31
+ text = ""
+ intervals [624]:
+ xmin = 54.31
+ xmax = 54.54
+ text = "AY1"
+ intervals [625]:
+ xmin = 54.54
+ xmax = 54.6
+ text = "W"
+ intervals [626]:
+ xmin = 54.6
+ xmax = 54.66
+ text = "AH0"
+ intervals [627]:
+ xmin = 54.66
+ xmax = 54.69
+ text = "L"
+ intervals [628]:
+ xmin = 54.69
+ xmax = 54.77
+ text = "G"
+ intervals [629]:
+ xmin = 54.77
+ xmax = 54.81
+ text = "IH1"
+ intervals [630]:
+ xmin = 54.81
+ xmax = 54.84
+ text = "V"
+ intervals [631]:
+ xmin = 54.84
+ xmax = 54.87
+ text = "DH"
+ intervals [632]:
+ xmin = 54.87
+ xmax = 54.94
+ text = "AH0"
+ intervals [633]:
+ xmin = 54.94
+ xmax = 54.97
+ text = "M"
+ intervals [634]:
+ xmin = 54.97
+ xmax = 55.0
+ text = "DH"
+ intervals [635]:
+ xmin = 55.0
+ xmax = 55.07
+ text = "AH0"
+ intervals [636]:
+ xmin = 55.07
+ xmax = 55.17
+ text = "T"
+ intervals [637]:
+ xmin = 55.17
+ xmax = 55.27
+ text = "AA1"
+ intervals [638]:
+ xmin = 55.27
+ xmax = 55.38
+ text = "P"
+ intervals [639]:
+ xmin = 55.38
+ xmax = 55.53
+ text = "spn"
+ intervals [640]:
+ xmin = 55.53
+ xmax = 55.62
+ text = "R"
+ intervals [641]:
+ xmin = 55.62
+ xmax = 55.7
+ text = "EH1"
+ intervals [642]:
+ xmin = 55.7
+ xmax = 55.76
+ text = "S"
+ intervals [643]:
+ xmin = 55.76
+ xmax = 55.83
+ text = "T"
+ intervals [644]:
+ xmin = 55.83
+ xmax = 55.86
+ text = "R"
+ intervals [645]:
+ xmin = 55.86
+ xmax = 55.97
+ text = "AA2"
+ intervals [646]:
+ xmin = 55.97
+ xmax = 56.01
+ text = "N"
+ intervals [647]:
+ xmin = 56.01
+ xmax = 56.04
+ text = "T"
+ intervals [648]:
+ xmin = 56.04
+ xmax = 56.1
+ text = "S"
+ intervals [649]:
+ xmin = 56.1
+ xmax = 56.17
+ text = "B"
+ intervals [650]:
+ xmin = 56.17
+ xmax = 56.32
+ text = "EY1"
+ intervals [651]:
+ xmin = 56.32
+ xmax = 56.37
+ text = "S"
+ intervals [652]:
+ xmin = 56.37
+ xmax = 56.44
+ text = "T"
+ intervals [653]:
+ xmin = 56.44
+ xmax = 56.64
+ text = "AA1"
+ intervals [654]:
+ xmin = 56.64
+ xmax = 56.68
+ text = "N"
+ intervals [655]:
+ xmin = 56.68
+ xmax = 56.72
+ text = "DH"
+ intervals [656]:
+ xmin = 56.72
+ xmax = 56.9
+ text = "IH0"
+ intervals [657]:
+ xmin = 56.9
+ xmax = 56.99
+ text = "S"
+ intervals [658]:
+ xmin = 56.99
+ xmax = 57.05
+ text = "R"
+ intervals [659]:
+ xmin = 57.05
+ xmax = 57.11
+ text = "AE1"
+ intervals [660]:
+ xmin = 57.11
+ xmax = 57.16
+ text = "NG"
+ intervals [661]:
+ xmin = 57.16
+ xmax = 57.22
+ text = "K"
+ intervals [662]:
+ xmin = 57.22
+ xmax = 57.29
+ text = "IH0"
+ intervals [663]:
+ xmin = 57.29
+ xmax = 57.35
+ text = "NG"
+ intervals [664]:
+ xmin = 57.35
+ xmax = 57.4
+ text = "AH0"
+ intervals [665]:
+ xmin = 57.4
+ xmax = 57.43
+ text = "N"
+ intervals [666]:
+ xmin = 57.43
+ xmax = 57.53
+ text = "D"
+ intervals [667]:
+ xmin = 57.53
+ xmax = 57.7
+ text = "EH1"
+ intervals [668]:
+ xmin = 57.7
+ xmax = 57.76
+ text = "V"
+ intervals [669]:
+ xmin = 57.76
+ xmax = 57.82
+ text = "R"
+ intervals [670]:
+ xmin = 57.82
+ xmax = 57.86
+ text = "IY0"
+ intervals [671]:
+ xmin = 57.86
+ xmax = 57.95
+ text = "T"
+ intervals [672]:
+ xmin = 57.95
+ xmax = 58.19
+ text = "AY1"
+ intervals [673]:
+ xmin = 58.19
+ xmax = 58.44
+ text = "M"
+ intervals [674]:
+ xmin = 58.44
+ xmax = 59.02
+ text = ""
+ intervals [675]:
+ xmin = 59.02
+ xmax = 59.12
+ text = "Y"
+ intervals [676]:
+ xmin = 59.12
+ xmax = 59.15
+ text = "UH1"
+ intervals [677]:
+ xmin = 59.15
+ xmax = 59.2
+ text = "R"
+ intervals [678]:
+ xmin = 59.2
+ xmax = 59.32
+ text = "S"
+ intervals [679]:
+ xmin = 59.32
+ xmax = 59.41
+ text = "AE1"
+ intervals [680]:
+ xmin = 59.41
+ xmax = 59.44
+ text = "T"
+ intervals [681]:
+ xmin = 59.44
+ xmax = 59.49
+ text = "AH0"
+ intervals [682]:
+ xmin = 59.49
+ xmax = 59.55
+ text = "S"
+ intervals [683]:
+ xmin = 59.55
+ xmax = 59.62
+ text = "F"
+ intervals [684]:
+ xmin = 59.62
+ xmax = 59.69
+ text = "AY2"
+ intervals [685]:
+ xmin = 59.69
+ xmax = 59.72
+ text = "D"
+ intervals [686]:
+ xmin = 59.72
+ xmax = 59.77
+ text = "W"
+ intervals [687]:
+ xmin = 59.77
+ xmax = 59.82
+ text = "IH0"
+ intervals [688]:
+ xmin = 59.82
+ xmax = 59.85
+ text = "DH"
+ intervals [689]:
+ xmin = 59.85
+ xmax = 59.88
+ text = "DH"
+ intervals [690]:
+ xmin = 59.88
+ xmax = 60.0
+ text = "IY1"
+ intervals [691]:
+ xmin = 60.0
+ xmax = 60.1
+ text = "Z"
+ intervals [692]:
+ xmin = 60.1
+ xmax = 60.15
+ text = "R"
+ intervals [693]:
+ xmin = 60.15
+ xmax = 60.23
+ text = "EH1"
+ intervals [694]:
+ xmin = 60.23
+ xmax = 60.28
+ text = "S"
+ intervals [695]:
+ xmin = 60.28
+ xmax = 60.34
+ text = "T"
+ intervals [696]:
+ xmin = 60.34
+ xmax = 60.4
+ text = "R"
+ intervals [697]:
+ xmin = 60.4
+ xmax = 60.52
+ text = "AA2"
+ intervals [698]:
+ xmin = 60.52
+ xmax = 60.57
+ text = "N"
+ intervals [699]:
+ xmin = 60.57
+ xmax = 60.62
+ text = "T"
+ intervals [700]:
+ xmin = 60.62
+ xmax = 60.81
+ text = "S"
+ intervals [701]:
+ xmin = 60.81
+ xmax = 62
+ text = ""
diff --git a/EMAGE/test_sequences/textgrid/2_scott_0_3_3.TextGrid b/EMAGE/test_sequences/textgrid/2_scott_0_3_3.TextGrid
new file mode 100644
index 0000000000000000000000000000000000000000..42b1321f18dcafe25ab172fe1607812a4c5c8eb9
--- /dev/null
+++ b/EMAGE/test_sequences/textgrid/2_scott_0_3_3.TextGrid
@@ -0,0 +1,3676 @@
+File type = "ooTextFile"
+Object class = "TextGrid"
+
+xmin = 0.0
+xmax = 68
+tiers?
+size = 2
+item []:
+ item [1]:
+ class = "IntervalTier"
+ name = "words"
+ xmin = 0.0
+ xmax = 68
+ intervals: size = 213
+ intervals [1]:
+ xmin = 0.0
+ xmax = 1.47
+ text = ""
+ intervals [2]:
+ xmin = 1.47
+ xmax = 2.36
+ text = "well"
+ intervals [3]:
+ xmin = 2.36
+ xmax = 2.56
+ text = ""
+ intervals [4]:
+ xmin = 2.56
+ xmax = 3.05
+ text = "in"
+ intervals [5]:
+ xmin = 3.05
+ xmax = 3.43
+ text = "my"
+ intervals [6]:
+ xmin = 3.43
+ xmax = 4.29
+ text = "opinion"
+ intervals [7]:
+ xmin = 4.29
+ xmax = 4.43
+ text = "i"
+ intervals [8]:
+ xmin = 4.43
+ xmax = 4.7
+ text = "think"
+ intervals [9]:
+ xmin = 4.7
+ xmax = 4.77
+ text = "the"
+ intervals [10]:
+ xmin = 4.77
+ xmax = 5.06
+ text = "best"
+ intervals [11]:
+ xmin = 5.06
+ xmax = 5.31
+ text = "job"
+ intervals [12]:
+ xmin = 5.31
+ xmax = 5.41
+ text = "for"
+ intervals [13]:
+ xmin = 5.41
+ xmax = 5.62
+ text = "me"
+ intervals [14]:
+ xmin = 5.62
+ xmax = 5.76
+ text = "is"
+ intervals [15]:
+ xmin = 5.76
+ xmax = 5.84
+ text = "to"
+ intervals [16]:
+ xmin = 5.84
+ xmax = 6.11
+ text = "become"
+ intervals [17]:
+ xmin = 6.11
+ xmax = 6.2
+ text = "a"
+ intervals [18]:
+ xmin = 6.2
+ xmax = 6.93
+ text = "journalist"
+ intervals [19]:
+ xmin = 6.93
+ xmax = 7.3
+ text = "cuz"
+ intervals [20]:
+ xmin = 7.3
+ xmax = 7.53
+ text = "this"
+ intervals [21]:
+ xmin = 7.53
+ xmax = 7.63
+ text = "is"
+ intervals [22]:
+ xmin = 7.63
+ xmax = 7.79
+ text = "my"
+ intervals [23]:
+ xmin = 7.79
+ xmax = 8.14
+ text = "dream"
+ intervals [24]:
+ xmin = 8.14
+ xmax = 8.53
+ text = "job"
+ intervals [25]:
+ xmin = 8.53
+ xmax = 8.71
+ text = "i've"
+ intervals [26]:
+ xmin = 8.71
+ xmax = 9.13
+ text = "always"
+ intervals [27]:
+ xmin = 9.13
+ xmax = 9.53
+ text = "wanted"
+ intervals [28]:
+ xmin = 9.53
+ xmax = 9.6
+ text = "to"
+ intervals [29]:
+ xmin = 9.6
+ xmax = 9.77
+ text = "be"
+ intervals [30]:
+ xmin = 9.77
+ xmax = 9.84
+ text = "a"
+ intervals [31]:
+ xmin = 9.84
+ xmax = 10.29
+ text = "journalist"
+ intervals [32]:
+ xmin = 10.29
+ xmax = 10.48
+ text = "since"
+ intervals [33]:
+ xmin = 10.48
+ xmax = 10.54
+ text = "i"
+ intervals [34]:
+ xmin = 10.54
+ xmax = 10.71
+ text = "was"
+ intervals [35]:
+ xmin = 10.71
+ xmax = 10.78
+ text = "in"
+ intervals [36]:
+ xmin = 10.78
+ xmax = 11.01
+ text = "middle"
+ intervals [37]:
+ xmin = 11.01
+ xmax = 11.4
+ text = "school"
+ intervals [38]:
+ xmin = 11.4
+ xmax = 11.96
+ text = ""
+ intervals [39]:
+ xmin = 11.96
+ xmax = 12.92
+ text = "journalists"
+ intervals [40]:
+ xmin = 12.92
+ xmax = 13.73
+ text = "never"
+ intervals [41]:
+ xmin = 13.73
+ xmax = 13.81
+ text = ""
+ intervals [42]:
+ xmin = 13.81
+ xmax = 14.38
+ text = "tell"
+ intervals [43]:
+ xmin = 14.38
+ xmax = 15.08
+ text = "lies"
+ intervals [44]:
+ xmin = 15.08
+ xmax = 15.19
+ text = "and"
+ intervals [45]:
+ xmin = 15.19
+ xmax = 15.38
+ text = "are"
+ intervals [46]:
+ xmin = 15.38
+ xmax = 15.75
+ text = "always"
+ intervals [47]:
+ xmin = 15.75
+ xmax = 16.07
+ text = "seeking"
+ intervals [48]:
+ xmin = 16.07
+ xmax = 16.17
+ text = "the"
+ intervals [49]:
+ xmin = 16.17
+ xmax = 16.69
+ text = "truth"
+ intervals [50]:
+ xmin = 16.69
+ xmax = 16.85
+ text = ""
+ intervals [51]:
+ xmin = 16.85
+ xmax = 17.09
+ text = "i"
+ intervals [52]:
+ xmin = 17.09
+ xmax = 17.27
+ text = "want"
+ intervals [53]:
+ xmin = 17.27
+ xmax = 17.33
+ text = "to"
+ intervals [54]:
+ xmin = 17.33
+ xmax = 17.45
+ text = "be"
+ intervals [55]:
+ xmin = 17.45
+ xmax = 17.73
+ text = "just"
+ intervals [56]:
+ xmin = 17.73
+ xmax = 18.0
+ text = "like"
+ intervals [57]:
+ xmin = 18.0
+ xmax = 18.36
+ text = "that"
+ intervals [58]:
+ xmin = 18.36
+ xmax = 18.73
+ text = ""
+ intervals [59]:
+ xmin = 18.73
+ xmax = 19.54
+ text = "i"
+ intervals [60]:
+ xmin = 19.54
+ xmax = 19.71
+ text = ""
+ intervals [61]:
+ xmin = 19.71
+ xmax = 20.27
+ text = "usually"
+ intervals [62]:
+ xmin = 20.27
+ xmax = 20.52
+ text = "feel"
+ intervals [63]:
+ xmin = 20.52
+ xmax = 20.96
+ text = "shy"
+ intervals [64]:
+ xmin = 20.96
+ xmax = 21.14
+ text = "when"
+ intervals [65]:
+ xmin = 21.14
+ xmax = 21.26
+ text = "i"
+ intervals [66]:
+ xmin = 21.26
+ xmax = 21.38
+ text = "am"
+ intervals [67]:
+ xmin = 21.38
+ xmax = 21.75
+ text = "talking"
+ intervals [68]:
+ xmin = 21.75
+ xmax = 21.86
+ text = "to"
+ intervals [69]:
+ xmin = 21.86
+ xmax = 22.22
+ text = "others"
+ intervals [70]:
+ xmin = 22.22
+ xmax = 22.37
+ text = "and"
+ intervals [71]:
+ xmin = 22.37
+ xmax = 22.46
+ text = "i"
+ intervals [72]:
+ xmin = 22.46
+ xmax = 22.8
+ text = "know"
+ intervals [73]:
+ xmin = 22.8
+ xmax = 23.1
+ text = "that"
+ intervals [74]:
+ xmin = 23.1
+ xmax = 23.79
+ text = "journalists"
+ intervals [75]:
+ xmin = 23.79
+ xmax = 23.99
+ text = "are"
+ intervals [76]:
+ xmin = 23.99
+ xmax = 24.73
+ text = "very"
+ intervals [77]:
+ xmin = 24.73
+ xmax = 25.29
+ text = "good"
+ intervals [78]:
+ xmin = 25.29
+ xmax = 25.44
+ text = ""
+ intervals [79]:
+ xmin = 25.44
+ xmax = 25.7
+ text = "at"
+ intervals [80]:
+ xmin = 25.7
+ xmax = 26.41
+ text = "communicating"
+ intervals [81]:
+ xmin = 26.41
+ xmax = 26.94
+ text = "because"
+ intervals [82]:
+ xmin = 26.94
+ xmax = 26.98
+ text = ""
+ intervals [83]:
+ xmin = 26.98
+ xmax = 27.2
+ text = "good"
+ intervals [84]:
+ xmin = 27.2
+ xmax = 27.95
+ text = "communication"
+ intervals [85]:
+ xmin = 27.95
+ xmax = 28.36
+ text = "skills"
+ intervals [86]:
+ xmin = 28.36
+ xmax = 28.51
+ text = "are"
+ intervals [87]:
+ xmin = 28.51
+ xmax = 28.75
+ text = "very"
+ intervals [88]:
+ xmin = 28.75
+ xmax = 29.22
+ text = "important"
+ intervals [89]:
+ xmin = 29.22
+ xmax = 29.39
+ text = "when"
+ intervals [90]:
+ xmin = 29.39
+ xmax = 29.51
+ text = "you're"
+ intervals [91]:
+ xmin = 29.51
+ xmax = 29.85
+ text = "doing"
+ intervals [92]:
+ xmin = 29.85
+ xmax = 30.43
+ text = "interviews"
+ intervals [93]:
+ xmin = 30.43
+ xmax = 30.71
+ text = ""
+ intervals [94]:
+ xmin = 30.71
+ xmax = 30.99
+ text = "i"
+ intervals [95]:
+ xmin = 30.99
+ xmax = 31.21
+ text = "want"
+ intervals [96]:
+ xmin = 31.21
+ xmax = 31.3
+ text = "to"
+ intervals [97]:
+ xmin = 31.3
+ xmax = 31.71
+ text = "possess"
+ intervals [98]:
+ xmin = 31.71
+ xmax = 31.82
+ text = "the"
+ intervals [99]:
+ xmin = 31.82
+ xmax = 32.16
+ text = "skill"
+ intervals [100]:
+ xmin = 32.16
+ xmax = 32.93
+ text = "myself"
+ intervals [101]:
+ xmin = 32.93
+ xmax = 33.0
+ text = ""
+ intervals [102]:
+ xmin = 33.0
+ xmax = 33.53
+ text = "so"
+ intervals [103]:
+ xmin = 33.53
+ xmax = 33.56
+ text = ""
+ intervals [104]:
+ xmin = 33.56
+ xmax = 33.95
+ text = "that's"
+ intervals [105]:
+ xmin = 33.95
+ xmax = 34.31
+ text = "why"
+ intervals [106]:
+ xmin = 34.31
+ xmax = 34.53
+ text = "i"
+ intervals [107]:
+ xmin = 34.53
+ xmax = 34.83
+ text = "want"
+ intervals [108]:
+ xmin = 34.83
+ xmax = 34.89
+ text = "to"
+ intervals [109]:
+ xmin = 34.89
+ xmax = 35.42
+ text = "become"
+ intervals [110]:
+ xmin = 35.42
+ xmax = 35.46
+ text = ""
+ intervals [111]:
+ xmin = 35.46
+ xmax = 35.59
+ text = "a"
+ intervals [112]:
+ xmin = 35.59
+ xmax = 36.37
+ text = "journalist"
+ intervals [113]:
+ xmin = 36.37
+ xmax = 36.74
+ text = ""
+ intervals [114]:
+ xmin = 36.74
+ xmax = 37.02
+ text = "other"
+ intervals [115]:
+ xmin = 37.02
+ xmax = 37.18
+ text = "than"
+ intervals [116]:
+ xmin = 37.18
+ xmax = 37.73
+ text = "that"
+ intervals [117]:
+ xmin = 37.73
+ xmax = 37.76
+ text = ""
+ intervals [118]:
+ xmin = 37.76
+ xmax = 38.72
+ text = "photography"
+ intervals [119]:
+ xmin = 38.72
+ xmax = 38.96
+ text = ""
+ intervals [120]:
+ xmin = 38.96
+ xmax = 39.4
+ text = "often"
+ intervals [121]:
+ xmin = 39.4
+ xmax = 39.66
+ text = "makes"
+ intervals [122]:
+ xmin = 39.66
+ xmax = 39.8
+ text = "me"
+ intervals [123]:
+ xmin = 39.8
+ xmax = 40.39
+ text = "feel"
+ intervals [124]:
+ xmin = 40.39
+ xmax = 40.72
+ text = "like"
+ intervals [125]:
+ xmin = 40.72
+ xmax = 41.42
+ text = "i'm"
+ intervals [126]:
+ xmin = 41.42
+ xmax = 41.77
+ text = ""
+ intervals [127]:
+ xmin = 41.77
+ xmax = 42.06
+ text = "doing"
+ intervals [128]:
+ xmin = 42.06
+ xmax = 42.13
+ text = "a"
+ intervals [129]:
+ xmin = 42.13
+ xmax = 42.41
+ text = "job"
+ intervals [130]:
+ xmin = 42.41
+ xmax = 42.58
+ text = "full"
+ intervals [131]:
+ xmin = 42.58
+ xmax = 42.64
+ text = "of"
+ intervals [132]:
+ xmin = 42.64
+ xmax = 42.99
+ text = "design"
+ intervals [133]:
+ xmin = 42.99
+ xmax = 43.12
+ text = "and"
+ intervals [134]:
+ xmin = 43.12
+ xmax = 43.25
+ text = "in"
+ intervals [135]:
+ xmin = 43.25
+ xmax = 43.52
+ text = "for"
+ intervals [136]:
+ xmin = 43.52
+ xmax = 44.31
+ text = "innovation"
+ intervals [137]:
+ xmin = 44.31
+ xmax = 45.18
+ text = ""
+ intervals [138]:
+ xmin = 45.18
+ xmax = 45.73
+ text = "because"
+ intervals [139]:
+ xmin = 45.73
+ xmax = 45.89
+ text = "for"
+ intervals [140]:
+ xmin = 45.89
+ xmax = 45.99
+ text = "the"
+ intervals [141]:
+ xmin = 45.99
+ xmax = 46.35
+ text = "same"
+ intervals [142]:
+ xmin = 46.35
+ xmax = 46.88
+ text = "scenery"
+ intervals [143]:
+ xmin = 46.88
+ xmax = 47.01
+ text = "we"
+ intervals [144]:
+ xmin = 47.01
+ xmax = 47.12
+ text = "can"
+ intervals [145]:
+ xmin = 47.12
+ xmax = 47.34
+ text = "use"
+ intervals [146]:
+ xmin = 47.34
+ xmax = 47.61
+ text = "different"
+ intervals [147]:
+ xmin = 47.61
+ xmax = 48.12
+ text = "angles"
+ intervals [148]:
+ xmin = 48.12
+ xmax = 48.21
+ text = "and"
+ intervals [149]:
+ xmin = 48.21
+ xmax = 48.48
+ text = "different"
+ intervals [150]:
+ xmin = 48.48
+ xmax = 49.32
+ text = "compositions"
+ intervals [151]:
+ xmin = 49.32
+ xmax = 49.68
+ text = ""
+ intervals [152]:
+ xmin = 49.68
+ xmax = 49.98
+ text = "for"
+ intervals [153]:
+ xmin = 49.98
+ xmax = 50.4
+ text = "example"
+ intervals [154]:
+ xmin = 50.4
+ xmax = 50.91
+ text = "people"
+ intervals [155]:
+ xmin = 50.91
+ xmax = 51.42
+ text = "being"
+ intervals [156]:
+ xmin = 51.42
+ xmax = 51.91
+ text = "shifted"
+ intervals [157]:
+ xmin = 51.91
+ xmax = 52.06
+ text = "from"
+ intervals [158]:
+ xmin = 52.06
+ xmax = 52.15
+ text = "the"
+ intervals [159]:
+ xmin = 52.15
+ xmax = 52.47
+ text = "center"
+ intervals [160]:
+ xmin = 52.47
+ xmax = 52.54
+ text = "of"
+ intervals [161]:
+ xmin = 52.54
+ xmax = 52.63
+ text = "the"
+ intervals [162]:
+ xmin = 52.63
+ xmax = 52.95
+ text = "frame"
+ intervals [163]:
+ xmin = 52.95
+ xmax = 53.1
+ text = "to"
+ intervals [164]:
+ xmin = 53.1
+ xmax = 53.32
+ text = "left"
+ intervals [165]:
+ xmin = 53.32
+ xmax = 53.54
+ text = "side"
+ intervals [166]:
+ xmin = 53.54
+ xmax = 53.6
+ text = "of"
+ intervals [167]:
+ xmin = 53.6
+ xmax = 53.69
+ text = "the"
+ intervals [168]:
+ xmin = 53.69
+ xmax = 54.17
+ text = "frame"
+ intervals [169]:
+ xmin = 54.17
+ xmax = 54.62
+ text = ""
+ intervals [170]:
+ xmin = 54.62
+ xmax = 54.75
+ text = "it"
+ intervals [171]:
+ xmin = 54.75
+ xmax = 54.91
+ text = "can"
+ intervals [172]:
+ xmin = 54.91
+ xmax = 55.13
+ text = "make"
+ intervals [173]:
+ xmin = 55.13
+ xmax = 55.22
+ text = "a"
+ intervals [174]:
+ xmin = 55.22
+ xmax = 55.56
+ text = "different"
+ intervals [175]:
+ xmin = 55.56
+ xmax = 56.05
+ text = "feeling"
+ intervals [176]:
+ xmin = 56.05
+ xmax = 56.41
+ text = ""
+ intervals [177]:
+ xmin = 56.41
+ xmax = 56.69
+ text = "when"
+ intervals [178]:
+ xmin = 56.69
+ xmax = 57.25
+ text = "we"
+ intervals [179]:
+ xmin = 57.25
+ xmax = 57.5
+ text = ""
+ intervals [180]:
+ xmin = 57.5
+ xmax = 57.82
+ text = "when"
+ intervals [181]:
+ xmin = 57.82
+ xmax = 58.07
+ text = "seen"
+ intervals [182]:
+ xmin = 58.07
+ xmax = 58.17
+ text = "in"
+ intervals [183]:
+ xmin = 58.17
+ xmax = 58.77
+ text = "context"
+ intervals [184]:
+ xmin = 58.77
+ xmax = 58.86
+ text = "with"
+ intervals [185]:
+ xmin = 58.86
+ xmax = 58.93
+ text = "the"
+ intervals [186]:
+ xmin = 58.93
+ xmax = 59.61
+ text = "background"
+ intervals [187]:
+ xmin = 59.61
+ xmax = 59.96
+ text = ""
+ intervals [188]:
+ xmin = 59.96
+ xmax = 60.31
+ text = "when"
+ intervals [189]:
+ xmin = 60.31
+ xmax = 60.79
+ text = "everyone's"
+ intervals [190]:
+ xmin = 60.79
+ xmax = 61.08
+ text = "taking"
+ intervals [191]:
+ xmin = 61.08
+ xmax = 61.14
+ text = "a"
+ intervals [192]:
+ xmin = 61.14
+ xmax = 61.46
+ text = "picture"
+ intervals [193]:
+ xmin = 61.46
+ xmax = 61.53
+ text = "of"
+ intervals [194]:
+ xmin = 61.53
+ xmax = 61.6
+ text = "the"
+ intervals [195]:
+ xmin = 61.6
+ xmax = 61.98
+ text = "exact"
+ intervals [196]:
+ xmin = 61.98
+ xmax = 62.19
+ text = "same"
+ intervals [197]:
+ xmin = 62.19
+ xmax = 62.64
+ text = "scenery"
+ intervals [198]:
+ xmin = 62.64
+ xmax = 62.67
+ text = ""
+ intervals [199]:
+ xmin = 62.67
+ xmax = 62.89
+ text = "i'm"
+ intervals [200]:
+ xmin = 62.89
+ xmax = 63.28
+ text = "very"
+ intervals [201]:
+ xmin = 63.28
+ xmax = 63.75
+ text = "happy"
+ intervals [202]:
+ xmin = 63.75
+ xmax = 63.9
+ text = "when"
+ intervals [203]:
+ xmin = 63.9
+ xmax = 64.35
+ text = "people"
+ intervals [204]:
+ xmin = 64.35
+ xmax = 64.6
+ text = "say"
+ intervals [205]:
+ xmin = 64.6
+ xmax = 64.84
+ text = "my"
+ intervals [206]:
+ xmin = 64.84
+ xmax = 65.29
+ text = "photos"
+ intervals [207]:
+ xmin = 65.29
+ xmax = 65.47
+ text = "look"
+ intervals [208]:
+ xmin = 65.47
+ xmax = 66.11
+ text = "better"
+ intervals [209]:
+ xmin = 66.11
+ xmax = 66.43
+ text = ""
+ intervals [210]:
+ xmin = 66.43
+ xmax = 66.56
+ text = "than"
+ intervals [211]:
+ xmin = 66.56
+ xmax = 66.7
+ text = "the"
+ intervals [212]:
+ xmin = 66.7
+ xmax = 67.19
+ text = "others"
+ intervals [213]:
+ xmin = 67.19
+ xmax = 68
+ text = ""
+ item [2]:
+ class = "IntervalTier"
+ name = "phones"
+ xmin = 0.0
+ xmax = 68
+ intervals: size = 701
+ intervals [1]:
+ xmin = 0.0
+ xmax = 1.47
+ text = ""
+ intervals [2]:
+ xmin = 1.47
+ xmax = 1.59
+ text = "W"
+ intervals [3]:
+ xmin = 1.59
+ xmax = 1.99
+ text = "EH1"
+ intervals [4]:
+ xmin = 1.99
+ xmax = 2.36
+ text = "L"
+ intervals [5]:
+ xmin = 2.36
+ xmax = 2.56
+ text = ""
+ intervals [6]:
+ xmin = 2.56
+ xmax = 2.88
+ text = "IH0"
+ intervals [7]:
+ xmin = 2.88
+ xmax = 3.05
+ text = "N"
+ intervals [8]:
+ xmin = 3.05
+ xmax = 3.18
+ text = "M"
+ intervals [9]:
+ xmin = 3.18
+ xmax = 3.43
+ text = "AY1"
+ intervals [10]:
+ xmin = 3.43
+ xmax = 3.53
+ text = "AH0"
+ intervals [11]:
+ xmin = 3.53
+ xmax = 3.6
+ text = "P"
+ intervals [12]:
+ xmin = 3.6
+ xmax = 3.7
+ text = "IH1"
+ intervals [13]:
+ xmin = 3.7
+ xmax = 3.77
+ text = "N"
+ intervals [14]:
+ xmin = 3.77
+ xmax = 3.85
+ text = "Y"
+ intervals [15]:
+ xmin = 3.85
+ xmax = 3.92
+ text = "AH0"
+ intervals [16]:
+ xmin = 3.92
+ xmax = 4.29
+ text = "N"
+ intervals [17]:
+ xmin = 4.29
+ xmax = 4.43
+ text = "AY1"
+ intervals [18]:
+ xmin = 4.43
+ xmax = 4.5
+ text = "TH"
+ intervals [19]:
+ xmin = 4.5
+ xmax = 4.57
+ text = "IH1"
+ intervals [20]:
+ xmin = 4.57
+ xmax = 4.67
+ text = "NG"
+ intervals [21]:
+ xmin = 4.67
+ xmax = 4.7
+ text = "K"
+ intervals [22]:
+ xmin = 4.7
+ xmax = 4.73
+ text = "DH"
+ intervals [23]:
+ xmin = 4.73
+ xmax = 4.77
+ text = "AH0"
+ intervals [24]:
+ xmin = 4.77
+ xmax = 4.84
+ text = "B"
+ intervals [25]:
+ xmin = 4.84
+ xmax = 4.96
+ text = "EH1"
+ intervals [26]:
+ xmin = 4.96
+ xmax = 5.02
+ text = "S"
+ intervals [27]:
+ xmin = 5.02
+ xmax = 5.06
+ text = "T"
+ intervals [28]:
+ xmin = 5.06
+ xmax = 5.17
+ text = "JH"
+ intervals [29]:
+ xmin = 5.17
+ xmax = 5.25
+ text = "AA1"
+ intervals [30]:
+ xmin = 5.25
+ xmax = 5.31
+ text = "B"
+ intervals [31]:
+ xmin = 5.31
+ xmax = 5.35
+ text = "F"
+ intervals [32]:
+ xmin = 5.35
+ xmax = 5.41
+ text = "ER0"
+ intervals [33]:
+ xmin = 5.41
+ xmax = 5.49
+ text = "M"
+ intervals [34]:
+ xmin = 5.49
+ xmax = 5.62
+ text = "IY1"
+ intervals [35]:
+ xmin = 5.62
+ xmax = 5.69
+ text = "IH1"
+ intervals [36]:
+ xmin = 5.69
+ xmax = 5.76
+ text = "Z"
+ intervals [37]:
+ xmin = 5.76
+ xmax = 5.8
+ text = "T"
+ intervals [38]:
+ xmin = 5.8
+ xmax = 5.84
+ text = "IH0"
+ intervals [39]:
+ xmin = 5.84
+ xmax = 5.88
+ text = "B"
+ intervals [40]:
+ xmin = 5.88
+ xmax = 5.94
+ text = "IH0"
+ intervals [41]:
+ xmin = 5.94
+ xmax = 6.01
+ text = "K"
+ intervals [42]:
+ xmin = 6.01
+ xmax = 6.06
+ text = "AH1"
+ intervals [43]:
+ xmin = 6.06
+ xmax = 6.11
+ text = "M"
+ intervals [44]:
+ xmin = 6.11
+ xmax = 6.2
+ text = "AH0"
+ intervals [45]:
+ xmin = 6.2
+ xmax = 6.42
+ text = "JH"
+ intervals [46]:
+ xmin = 6.42
+ xmax = 6.52
+ text = "ER1"
+ intervals [47]:
+ xmin = 6.52
+ xmax = 6.57
+ text = "N"
+ intervals [48]:
+ xmin = 6.57
+ xmax = 6.63
+ text = "AH0"
+ intervals [49]:
+ xmin = 6.63
+ xmax = 6.71
+ text = "L"
+ intervals [50]:
+ xmin = 6.71
+ xmax = 6.77
+ text = "AH0"
+ intervals [51]:
+ xmin = 6.77
+ xmax = 6.87
+ text = "S"
+ intervals [52]:
+ xmin = 6.87
+ xmax = 6.93
+ text = "T"
+ intervals [53]:
+ xmin = 6.93
+ xmax = 7.04
+ text = "K"
+ intervals [54]:
+ xmin = 7.04
+ xmax = 7.18
+ text = "UW0"
+ intervals [55]:
+ xmin = 7.18
+ xmax = 7.3
+ text = "Z"
+ intervals [56]:
+ xmin = 7.3
+ xmax = 7.37
+ text = "DH"
+ intervals [57]:
+ xmin = 7.37
+ xmax = 7.44
+ text = "IH1"
+ intervals [58]:
+ xmin = 7.44
+ xmax = 7.53
+ text = "S"
+ intervals [59]:
+ xmin = 7.53
+ xmax = 7.58
+ text = "IH0"
+ intervals [60]:
+ xmin = 7.58
+ xmax = 7.63
+ text = "Z"
+ intervals [61]:
+ xmin = 7.63
+ xmax = 7.71
+ text = "M"
+ intervals [62]:
+ xmin = 7.71
+ xmax = 7.79
+ text = "AY1"
+ intervals [63]:
+ xmin = 7.79
+ xmax = 7.9
+ text = "D"
+ intervals [64]:
+ xmin = 7.9
+ xmax = 7.97
+ text = "R"
+ intervals [65]:
+ xmin = 7.97
+ xmax = 8.07
+ text = "IY1"
+ intervals [66]:
+ xmin = 8.07
+ xmax = 8.14
+ text = "M"
+ intervals [67]:
+ xmin = 8.14
+ xmax = 8.26
+ text = "JH"
+ intervals [68]:
+ xmin = 8.26
+ xmax = 8.44
+ text = "AA1"
+ intervals [69]:
+ xmin = 8.44
+ xmax = 8.53
+ text = "B"
+ intervals [70]:
+ xmin = 8.53
+ xmax = 8.65
+ text = "AY1"
+ intervals [71]:
+ xmin = 8.65
+ xmax = 8.71
+ text = "V"
+ intervals [72]:
+ xmin = 8.71
+ xmax = 8.82
+ text = "AO1"
+ intervals [73]:
+ xmin = 8.82
+ xmax = 8.88
+ text = "L"
+ intervals [74]:
+ xmin = 8.88
+ xmax = 8.98
+ text = "W"
+ intervals [75]:
+ xmin = 8.98
+ xmax = 9.03
+ text = "IY0"
+ intervals [76]:
+ xmin = 9.03
+ xmax = 9.13
+ text = "Z"
+ intervals [77]:
+ xmin = 9.13
+ xmax = 9.3
+ text = "W"
+ intervals [78]:
+ xmin = 9.3
+ xmax = 9.42
+ text = "AO1"
+ intervals [79]:
+ xmin = 9.42
+ xmax = 9.46
+ text = "N"
+ intervals [80]:
+ xmin = 9.46
+ xmax = 9.5
+ text = "IH0"
+ intervals [81]:
+ xmin = 9.5
+ xmax = 9.53
+ text = "D"
+ intervals [82]:
+ xmin = 9.53
+ xmax = 9.56
+ text = "T"
+ intervals [83]:
+ xmin = 9.56
+ xmax = 9.6
+ text = "AH0"
+ intervals [84]:
+ xmin = 9.6
+ xmax = 9.66
+ text = "B"
+ intervals [85]:
+ xmin = 9.66
+ xmax = 9.77
+ text = "IY1"
+ intervals [86]:
+ xmin = 9.77
+ xmax = 9.84
+ text = "AH0"
+ intervals [87]:
+ xmin = 9.84
+ xmax = 9.95
+ text = "JH"
+ intervals [88]:
+ xmin = 9.95
+ xmax = 10.0
+ text = "ER1"
+ intervals [89]:
+ xmin = 10.0
+ xmax = 10.03
+ text = "N"
+ intervals [90]:
+ xmin = 10.03
+ xmax = 10.1
+ text = "AH0"
+ intervals [91]:
+ xmin = 10.1
+ xmax = 10.18
+ text = "L"
+ intervals [92]:
+ xmin = 10.18
+ xmax = 10.23
+ text = "AH0"
+ intervals [93]:
+ xmin = 10.23
+ xmax = 10.26
+ text = "S"
+ intervals [94]:
+ xmin = 10.26
+ xmax = 10.29
+ text = "T"
+ intervals [95]:
+ xmin = 10.29
+ xmax = 10.33
+ text = "S"
+ intervals [96]:
+ xmin = 10.33
+ xmax = 10.37
+ text = "IH1"
+ intervals [97]:
+ xmin = 10.37
+ xmax = 10.42
+ text = "N"
+ intervals [98]:
+ xmin = 10.42
+ xmax = 10.48
+ text = "S"
+ intervals [99]:
+ xmin = 10.48
+ xmax = 10.54
+ text = "AY1"
+ intervals [100]:
+ xmin = 10.54
+ xmax = 10.6
+ text = "W"
+ intervals [101]:
+ xmin = 10.6
+ xmax = 10.64
+ text = "AH0"
+ intervals [102]:
+ xmin = 10.64
+ xmax = 10.71
+ text = "Z"
+ intervals [103]:
+ xmin = 10.71
+ xmax = 10.75
+ text = "IH0"
+ intervals [104]:
+ xmin = 10.75
+ xmax = 10.78
+ text = "N"
+ intervals [105]:
+ xmin = 10.78
+ xmax = 10.84
+ text = "M"
+ intervals [106]:
+ xmin = 10.84
+ xmax = 10.87
+ text = "IH1"
+ intervals [107]:
+ xmin = 10.87
+ xmax = 10.9
+ text = "D"
+ intervals [108]:
+ xmin = 10.9
+ xmax = 10.95
+ text = "AH0"
+ intervals [109]:
+ xmin = 10.95
+ xmax = 11.01
+ text = "L"
+ intervals [110]:
+ xmin = 11.01
+ xmax = 11.11
+ text = "S"
+ intervals [111]:
+ xmin = 11.11
+ xmax = 11.16
+ text = "K"
+ intervals [112]:
+ xmin = 11.16
+ xmax = 11.21
+ text = "UW1"
+ intervals [113]:
+ xmin = 11.21
+ xmax = 11.4
+ text = "L"
+ intervals [114]:
+ xmin = 11.4
+ xmax = 11.96
+ text = ""
+ intervals [115]:
+ xmin = 11.96
+ xmax = 12.2
+ text = "JH"
+ intervals [116]:
+ xmin = 12.2
+ xmax = 12.28
+ text = "ER1"
+ intervals [117]:
+ xmin = 12.28
+ xmax = 12.34
+ text = "N"
+ intervals [118]:
+ xmin = 12.34
+ xmax = 12.38
+ text = "AH0"
+ intervals [119]:
+ xmin = 12.38
+ xmax = 12.5
+ text = "L"
+ intervals [120]:
+ xmin = 12.5
+ xmax = 12.64
+ text = "AH0"
+ intervals [121]:
+ xmin = 12.64
+ xmax = 12.83
+ text = "S"
+ intervals [122]:
+ xmin = 12.83
+ xmax = 12.86
+ text = "T"
+ intervals [123]:
+ xmin = 12.86
+ xmax = 12.92
+ text = "S"
+ intervals [124]:
+ xmin = 12.92
+ xmax = 13.14
+ text = "N"
+ intervals [125]:
+ xmin = 13.14
+ xmax = 13.34
+ text = "EH1"
+ intervals [126]:
+ xmin = 13.34
+ xmax = 13.46
+ text = "V"
+ intervals [127]:
+ xmin = 13.46
+ xmax = 13.73
+ text = "ER0"
+ intervals [128]:
+ xmin = 13.73
+ xmax = 13.81
+ text = ""
+ intervals [129]:
+ xmin = 13.81
+ xmax = 14.0
+ text = "T"
+ intervals [130]:
+ xmin = 14.0
+ xmax = 14.17
+ text = "EH1"
+ intervals [131]:
+ xmin = 14.17
+ xmax = 14.38
+ text = "L"
+ intervals [132]:
+ xmin = 14.38
+ xmax = 14.43
+ text = "L"
+ intervals [133]:
+ xmin = 14.43
+ xmax = 14.95
+ text = "AY1"
+ intervals [134]:
+ xmin = 14.95
+ xmax = 15.08
+ text = "Z"
+ intervals [135]:
+ xmin = 15.08
+ xmax = 15.13
+ text = "AE1"
+ intervals [136]:
+ xmin = 15.13
+ xmax = 15.16
+ text = "N"
+ intervals [137]:
+ xmin = 15.16
+ xmax = 15.19
+ text = "D"
+ intervals [138]:
+ xmin = 15.19
+ xmax = 15.38
+ text = "ER0"
+ intervals [139]:
+ xmin = 15.38
+ xmax = 15.43
+ text = "AO1"
+ intervals [140]:
+ xmin = 15.43
+ xmax = 15.48
+ text = "L"
+ intervals [141]:
+ xmin = 15.48
+ xmax = 15.57
+ text = "W"
+ intervals [142]:
+ xmin = 15.57
+ xmax = 15.61
+ text = "IY0"
+ intervals [143]:
+ xmin = 15.61
+ xmax = 15.75
+ text = "Z"
+ intervals [144]:
+ xmin = 15.75
+ xmax = 15.8
+ text = "S"
+ intervals [145]:
+ xmin = 15.8
+ xmax = 15.89
+ text = "IY1"
+ intervals [146]:
+ xmin = 15.89
+ xmax = 15.96
+ text = "K"
+ intervals [147]:
+ xmin = 15.96
+ xmax = 16.03
+ text = "IH0"
+ intervals [148]:
+ xmin = 16.03
+ xmax = 16.07
+ text = "NG"
+ intervals [149]:
+ xmin = 16.07
+ xmax = 16.12
+ text = "DH"
+ intervals [150]:
+ xmin = 16.12
+ xmax = 16.17
+ text = "AH0"
+ intervals [151]:
+ xmin = 16.17
+ xmax = 16.3
+ text = "T"
+ intervals [152]:
+ xmin = 16.3
+ xmax = 16.36
+ text = "R"
+ intervals [153]:
+ xmin = 16.36
+ xmax = 16.48
+ text = "UW1"
+ intervals [154]:
+ xmin = 16.48
+ xmax = 16.69
+ text = "TH"
+ intervals [155]:
+ xmin = 16.69
+ xmax = 16.85
+ text = ""
+ intervals [156]:
+ xmin = 16.85
+ xmax = 17.09
+ text = "AY1"
+ intervals [157]:
+ xmin = 17.09
+ xmax = 17.18
+ text = "W"
+ intervals [158]:
+ xmin = 17.18
+ xmax = 17.21
+ text = "AA1"
+ intervals [159]:
+ xmin = 17.21
+ xmax = 17.24
+ text = "N"
+ intervals [160]:
+ xmin = 17.24
+ xmax = 17.27
+ text = "T"
+ intervals [161]:
+ xmin = 17.27
+ xmax = 17.3
+ text = "T"
+ intervals [162]:
+ xmin = 17.3
+ xmax = 17.33
+ text = "AH0"
+ intervals [163]:
+ xmin = 17.33
+ xmax = 17.37
+ text = "B"
+ intervals [164]:
+ xmin = 17.37
+ xmax = 17.45
+ text = "IY0"
+ intervals [165]:
+ xmin = 17.45
+ xmax = 17.57
+ text = "JH"
+ intervals [166]:
+ xmin = 17.57
+ xmax = 17.64
+ text = "IH0"
+ intervals [167]:
+ xmin = 17.64
+ xmax = 17.7
+ text = "S"
+ intervals [168]:
+ xmin = 17.7
+ xmax = 17.73
+ text = "T"
+ intervals [169]:
+ xmin = 17.73
+ xmax = 17.81
+ text = "L"
+ intervals [170]:
+ xmin = 17.81
+ xmax = 17.91
+ text = "AY1"
+ intervals [171]:
+ xmin = 17.91
+ xmax = 18.0
+ text = "K"
+ intervals [172]:
+ xmin = 18.0
+ xmax = 18.06
+ text = "DH"
+ intervals [173]:
+ xmin = 18.06
+ xmax = 18.23
+ text = "AE1"
+ intervals [174]:
+ xmin = 18.23
+ xmax = 18.36
+ text = "T"
+ intervals [175]:
+ xmin = 18.36
+ xmax = 18.73
+ text = ""
+ intervals [176]:
+ xmin = 18.73
+ xmax = 19.54
+ text = "AY1"
+ intervals [177]:
+ xmin = 19.54
+ xmax = 19.71
+ text = ""
+ intervals [178]:
+ xmin = 19.71
+ xmax = 19.92
+ text = "Y"
+ intervals [179]:
+ xmin = 19.92
+ xmax = 20.03
+ text = "UW1"
+ intervals [180]:
+ xmin = 20.03
+ xmax = 20.11
+ text = "ZH"
+ intervals [181]:
+ xmin = 20.11
+ xmax = 20.14
+ text = "AH0"
+ intervals [182]:
+ xmin = 20.14
+ xmax = 20.17
+ text = "L"
+ intervals [183]:
+ xmin = 20.17
+ xmax = 20.27
+ text = "IY0"
+ intervals [184]:
+ xmin = 20.27
+ xmax = 20.37
+ text = "F"
+ intervals [185]:
+ xmin = 20.37
+ xmax = 20.45
+ text = "IY1"
+ intervals [186]:
+ xmin = 20.45
+ xmax = 20.52
+ text = "L"
+ intervals [187]:
+ xmin = 20.52
+ xmax = 20.73
+ text = "SH"
+ intervals [188]:
+ xmin = 20.73
+ xmax = 20.96
+ text = "AY1"
+ intervals [189]:
+ xmin = 20.96
+ xmax = 21.06
+ text = "W"
+ intervals [190]:
+ xmin = 21.06
+ xmax = 21.09
+ text = "EH1"
+ intervals [191]:
+ xmin = 21.09
+ xmax = 21.14
+ text = "N"
+ intervals [192]:
+ xmin = 21.14
+ xmax = 21.26
+ text = "AY1"
+ intervals [193]:
+ xmin = 21.26
+ xmax = 21.31
+ text = "AE1"
+ intervals [194]:
+ xmin = 21.31
+ xmax = 21.38
+ text = "M"
+ intervals [195]:
+ xmin = 21.38
+ xmax = 21.5
+ text = "T"
+ intervals [196]:
+ xmin = 21.5
+ xmax = 21.57
+ text = "AO1"
+ intervals [197]:
+ xmin = 21.57
+ xmax = 21.64
+ text = "K"
+ intervals [198]:
+ xmin = 21.64
+ xmax = 21.69
+ text = "IH0"
+ intervals [199]:
+ xmin = 21.69
+ xmax = 21.75
+ text = "NG"
+ intervals [200]:
+ xmin = 21.75
+ xmax = 21.8
+ text = "T"
+ intervals [201]:
+ xmin = 21.8
+ xmax = 21.86
+ text = "AH0"
+ intervals [202]:
+ xmin = 21.86
+ xmax = 21.96
+ text = "AH1"
+ intervals [203]:
+ xmin = 21.96
+ xmax = 22.02
+ text = "DH"
+ intervals [204]:
+ xmin = 22.02
+ xmax = 22.13
+ text = "ER0"
+ intervals [205]:
+ xmin = 22.13
+ xmax = 22.22
+ text = "Z"
+ intervals [206]:
+ xmin = 22.22
+ xmax = 22.29
+ text = "AE1"
+ intervals [207]:
+ xmin = 22.29
+ xmax = 22.32
+ text = "N"
+ intervals [208]:
+ xmin = 22.32
+ xmax = 22.37
+ text = "D"
+ intervals [209]:
+ xmin = 22.37
+ xmax = 22.46
+ text = "AY1"
+ intervals [210]:
+ xmin = 22.46
+ xmax = 22.6
+ text = "N"
+ intervals [211]:
+ xmin = 22.6
+ xmax = 22.8
+ text = "OW1"
+ intervals [212]:
+ xmin = 22.8
+ xmax = 22.85
+ text = "DH"
+ intervals [213]:
+ xmin = 22.85
+ xmax = 22.98
+ text = "AH0"
+ intervals [214]:
+ xmin = 22.98
+ xmax = 23.1
+ text = "T"
+ intervals [215]:
+ xmin = 23.1
+ xmax = 23.27
+ text = "JH"
+ intervals [216]:
+ xmin = 23.27
+ xmax = 23.35
+ text = "ER1"
+ intervals [217]:
+ xmin = 23.35
+ xmax = 23.39
+ text = "N"
+ intervals [218]:
+ xmin = 23.39
+ xmax = 23.46
+ text = "AH0"
+ intervals [219]:
+ xmin = 23.46
+ xmax = 23.54
+ text = "L"
+ intervals [220]:
+ xmin = 23.54
+ xmax = 23.61
+ text = "AH0"
+ intervals [221]:
+ xmin = 23.61
+ xmax = 23.69
+ text = "S"
+ intervals [222]:
+ xmin = 23.69
+ xmax = 23.72
+ text = "T"
+ intervals [223]:
+ xmin = 23.72
+ xmax = 23.79
+ text = "S"
+ intervals [224]:
+ xmin = 23.79
+ xmax = 23.89
+ text = "AA1"
+ intervals [225]:
+ xmin = 23.89
+ xmax = 23.99
+ text = "R"
+ intervals [226]:
+ xmin = 23.99
+ xmax = 24.22
+ text = "V"
+ intervals [227]:
+ xmin = 24.22
+ xmax = 24.49
+ text = "EH1"
+ intervals [228]:
+ xmin = 24.49
+ xmax = 24.64
+ text = "R"
+ intervals [229]:
+ xmin = 24.64
+ xmax = 24.73
+ text = "IY0"
+ intervals [230]:
+ xmin = 24.73
+ xmax = 24.9
+ text = "G"
+ intervals [231]:
+ xmin = 24.9
+ xmax = 25.12
+ text = "UH1"
+ intervals [232]:
+ xmin = 25.12
+ xmax = 25.29
+ text = "D"
+ intervals [233]:
+ xmin = 25.29
+ xmax = 25.44
+ text = ""
+ intervals [234]:
+ xmin = 25.44
+ xmax = 25.61
+ text = "AE1"
+ intervals [235]:
+ xmin = 25.61
+ xmax = 25.7
+ text = "T"
+ intervals [236]:
+ xmin = 25.7
+ xmax = 25.73
+ text = "K"
+ intervals [237]:
+ xmin = 25.73
+ xmax = 25.77
+ text = "AH0"
+ intervals [238]:
+ xmin = 25.77
+ xmax = 25.83
+ text = "M"
+ intervals [239]:
+ xmin = 25.83
+ xmax = 25.89
+ text = "Y"
+ intervals [240]:
+ xmin = 25.89
+ xmax = 25.93
+ text = "UW1"
+ intervals [241]:
+ xmin = 25.93
+ xmax = 25.98
+ text = "N"
+ intervals [242]:
+ xmin = 25.98
+ xmax = 26.05
+ text = "AH0"
+ intervals [243]:
+ xmin = 26.05
+ xmax = 26.19
+ text = "K"
+ intervals [244]:
+ xmin = 26.19
+ xmax = 26.25
+ text = "EY2"
+ intervals [245]:
+ xmin = 26.25
+ xmax = 26.28
+ text = "T"
+ intervals [246]:
+ xmin = 26.28
+ xmax = 26.35
+ text = "IH0"
+ intervals [247]:
+ xmin = 26.35
+ xmax = 26.41
+ text = "NG"
+ intervals [248]:
+ xmin = 26.41
+ xmax = 26.46
+ text = "B"
+ intervals [249]:
+ xmin = 26.46
+ xmax = 26.54
+ text = "IH0"
+ intervals [250]:
+ xmin = 26.54
+ xmax = 26.64
+ text = "K"
+ intervals [251]:
+ xmin = 26.64
+ xmax = 26.84
+ text = "AH0"
+ intervals [252]:
+ xmin = 26.84
+ xmax = 26.94
+ text = "Z"
+ intervals [253]:
+ xmin = 26.94
+ xmax = 26.98
+ text = ""
+ intervals [254]:
+ xmin = 26.98
+ xmax = 27.07
+ text = "G"
+ intervals [255]:
+ xmin = 27.07
+ xmax = 27.15
+ text = "UH1"
+ intervals [256]:
+ xmin = 27.15
+ xmax = 27.2
+ text = "D"
+ intervals [257]:
+ xmin = 27.2
+ xmax = 27.27
+ text = "K"
+ intervals [258]:
+ xmin = 27.27
+ xmax = 27.32
+ text = "AH0"
+ intervals [259]:
+ xmin = 27.32
+ xmax = 27.38
+ text = "M"
+ intervals [260]:
+ xmin = 27.38
+ xmax = 27.43
+ text = "Y"
+ intervals [261]:
+ xmin = 27.43
+ xmax = 27.46
+ text = "UW2"
+ intervals [262]:
+ xmin = 27.46
+ xmax = 27.49
+ text = "N"
+ intervals [263]:
+ xmin = 27.49
+ xmax = 27.54
+ text = "AH0"
+ intervals [264]:
+ xmin = 27.54
+ xmax = 27.65
+ text = "K"
+ intervals [265]:
+ xmin = 27.65
+ xmax = 27.75
+ text = "EY1"
+ intervals [266]:
+ xmin = 27.75
+ xmax = 27.84
+ text = "SH"
+ intervals [267]:
+ xmin = 27.84
+ xmax = 27.89
+ text = "AH0"
+ intervals [268]:
+ xmin = 27.89
+ xmax = 27.95
+ text = "N"
+ intervals [269]:
+ xmin = 27.95
+ xmax = 28.03
+ text = "S"
+ intervals [270]:
+ xmin = 28.03
+ xmax = 28.08
+ text = "K"
+ intervals [271]:
+ xmin = 28.08
+ xmax = 28.15
+ text = "IH1"
+ intervals [272]:
+ xmin = 28.15
+ xmax = 28.27
+ text = "L"
+ intervals [273]:
+ xmin = 28.27
+ xmax = 28.36
+ text = "Z"
+ intervals [274]:
+ xmin = 28.36
+ xmax = 28.42
+ text = "AA1"
+ intervals [275]:
+ xmin = 28.42
+ xmax = 28.51
+ text = "R"
+ intervals [276]:
+ xmin = 28.51
+ xmax = 28.56
+ text = "V"
+ intervals [277]:
+ xmin = 28.56
+ xmax = 28.61
+ text = "EH1"
+ intervals [278]:
+ xmin = 28.61
+ xmax = 28.72
+ text = "R"
+ intervals [279]:
+ xmin = 28.72
+ xmax = 28.75
+ text = "IY0"
+ intervals [280]:
+ xmin = 28.75
+ xmax = 28.8
+ text = "IH0"
+ intervals [281]:
+ xmin = 28.8
+ xmax = 28.86
+ text = "M"
+ intervals [282]:
+ xmin = 28.86
+ xmax = 28.97
+ text = "P"
+ intervals [283]:
+ xmin = 28.97
+ xmax = 29.01
+ text = "AO1"
+ intervals [284]:
+ xmin = 29.01
+ xmax = 29.07
+ text = "R"
+ intervals [285]:
+ xmin = 29.07
+ xmax = 29.11
+ text = "T"
+ intervals [286]:
+ xmin = 29.11
+ xmax = 29.14
+ text = "AH0"
+ intervals [287]:
+ xmin = 29.14
+ xmax = 29.18
+ text = "N"
+ intervals [288]:
+ xmin = 29.18
+ xmax = 29.22
+ text = "T"
+ intervals [289]:
+ xmin = 29.22
+ xmax = 29.29
+ text = "W"
+ intervals [290]:
+ xmin = 29.29
+ xmax = 29.32
+ text = "EH1"
+ intervals [291]:
+ xmin = 29.32
+ xmax = 29.39
+ text = "N"
+ intervals [292]:
+ xmin = 29.39
+ xmax = 29.43
+ text = "Y"
+ intervals [293]:
+ xmin = 29.43
+ xmax = 29.46
+ text = "UH1"
+ intervals [294]:
+ xmin = 29.46
+ xmax = 29.51
+ text = "R"
+ intervals [295]:
+ xmin = 29.51
+ xmax = 29.6
+ text = "D"
+ intervals [296]:
+ xmin = 29.6
+ xmax = 29.7
+ text = "UW1"
+ intervals [297]:
+ xmin = 29.7
+ xmax = 29.76
+ text = "IH0"
+ intervals [298]:
+ xmin = 29.76
+ xmax = 29.85
+ text = "NG"
+ intervals [299]:
+ xmin = 29.85
+ xmax = 29.88
+ text = "IH1"
+ intervals [300]:
+ xmin = 29.88
+ xmax = 29.99
+ text = "N"
+ intervals [301]:
+ xmin = 29.99
+ xmax = 30.06
+ text = "ER0"
+ intervals [302]:
+ xmin = 30.06
+ xmax = 30.1
+ text = "V"
+ intervals [303]:
+ xmin = 30.1
+ xmax = 30.21
+ text = "Y"
+ intervals [304]:
+ xmin = 30.21
+ xmax = 30.28
+ text = "UW2"
+ intervals [305]:
+ xmin = 30.28
+ xmax = 30.43
+ text = "Z"
+ intervals [306]:
+ xmin = 30.43
+ xmax = 30.71
+ text = ""
+ intervals [307]:
+ xmin = 30.71
+ xmax = 30.99
+ text = "AY1"
+ intervals [308]:
+ xmin = 30.99
+ xmax = 31.11
+ text = "W"
+ intervals [309]:
+ xmin = 31.11
+ xmax = 31.15
+ text = "AA1"
+ intervals [310]:
+ xmin = 31.15
+ xmax = 31.18
+ text = "N"
+ intervals [311]:
+ xmin = 31.18
+ xmax = 31.21
+ text = "T"
+ intervals [312]:
+ xmin = 31.21
+ xmax = 31.24
+ text = "T"
+ intervals [313]:
+ xmin = 31.24
+ xmax = 31.3
+ text = "AH0"
+ intervals [314]:
+ xmin = 31.3
+ xmax = 31.35
+ text = "P"
+ intervals [315]:
+ xmin = 31.35
+ xmax = 31.42
+ text = "AH0"
+ intervals [316]:
+ xmin = 31.42
+ xmax = 31.51
+ text = "Z"
+ intervals [317]:
+ xmin = 31.51
+ xmax = 31.62
+ text = "EH1"
+ intervals [318]:
+ xmin = 31.62
+ xmax = 31.71
+ text = "S"
+ intervals [319]:
+ xmin = 31.71
+ xmax = 31.75
+ text = "DH"
+ intervals [320]:
+ xmin = 31.75
+ xmax = 31.82
+ text = "AH0"
+ intervals [321]:
+ xmin = 31.82
+ xmax = 31.97
+ text = "S"
+ intervals [322]:
+ xmin = 31.97
+ xmax = 32.02
+ text = "K"
+ intervals [323]:
+ xmin = 32.02
+ xmax = 32.09
+ text = "IH1"
+ intervals [324]:
+ xmin = 32.09
+ xmax = 32.16
+ text = "L"
+ intervals [325]:
+ xmin = 32.16
+ xmax = 32.23
+ text = "M"
+ intervals [326]:
+ xmin = 32.23
+ xmax = 32.31
+ text = "AY2"
+ intervals [327]:
+ xmin = 32.31
+ xmax = 32.46
+ text = "S"
+ intervals [328]:
+ xmin = 32.46
+ xmax = 32.53
+ text = "EH1"
+ intervals [329]:
+ xmin = 32.53
+ xmax = 32.76
+ text = "L"
+ intervals [330]:
+ xmin = 32.76
+ xmax = 32.93
+ text = "F"
+ intervals [331]:
+ xmin = 32.93
+ xmax = 33.0
+ text = ""
+ intervals [332]:
+ xmin = 33.0
+ xmax = 33.22
+ text = "S"
+ intervals [333]:
+ xmin = 33.22
+ xmax = 33.53
+ text = "OW1"
+ intervals [334]:
+ xmin = 33.53
+ xmax = 33.56
+ text = ""
+ intervals [335]:
+ xmin = 33.56
+ xmax = 33.67
+ text = "DH"
+ intervals [336]:
+ xmin = 33.67
+ xmax = 33.82
+ text = "AE1"
+ intervals [337]:
+ xmin = 33.82
+ xmax = 33.89
+ text = "T"
+ intervals [338]:
+ xmin = 33.89
+ xmax = 33.95
+ text = "S"
+ intervals [339]:
+ xmin = 33.95
+ xmax = 34.09
+ text = "W"
+ intervals [340]:
+ xmin = 34.09
+ xmax = 34.31
+ text = "AY1"
+ intervals [341]:
+ xmin = 34.31
+ xmax = 34.53
+ text = "AY1"
+ intervals [342]:
+ xmin = 34.53
+ xmax = 34.67
+ text = "W"
+ intervals [343]:
+ xmin = 34.67
+ xmax = 34.77
+ text = "AO1"
+ intervals [344]:
+ xmin = 34.77
+ xmax = 34.8
+ text = "N"
+ intervals [345]:
+ xmin = 34.8
+ xmax = 34.83
+ text = "T"
+ intervals [346]:
+ xmin = 34.83
+ xmax = 34.86
+ text = "T"
+ intervals [347]:
+ xmin = 34.86
+ xmax = 34.89
+ text = "IH0"
+ intervals [348]:
+ xmin = 34.89
+ xmax = 34.93
+ text = "B"
+ intervals [349]:
+ xmin = 34.93
+ xmax = 35.0
+ text = "IH0"
+ intervals [350]:
+ xmin = 35.0
+ xmax = 35.08
+ text = "K"
+ intervals [351]:
+ xmin = 35.08
+ xmax = 35.19
+ text = "AH1"
+ intervals [352]:
+ xmin = 35.19
+ xmax = 35.42
+ text = "M"
+ intervals [353]:
+ xmin = 35.42
+ xmax = 35.46
+ text = ""
+ intervals [354]:
+ xmin = 35.46
+ xmax = 35.59
+ text = "AH0"
+ intervals [355]:
+ xmin = 35.59
+ xmax = 35.68
+ text = "JH"
+ intervals [356]:
+ xmin = 35.68
+ xmax = 35.79
+ text = "ER1"
+ intervals [357]:
+ xmin = 35.79
+ xmax = 35.84
+ text = "N"
+ intervals [358]:
+ xmin = 35.84
+ xmax = 35.89
+ text = "AH0"
+ intervals [359]:
+ xmin = 35.89
+ xmax = 35.97
+ text = "L"
+ intervals [360]:
+ xmin = 35.97
+ xmax = 36.07
+ text = "AH0"
+ intervals [361]:
+ xmin = 36.07
+ xmax = 36.27
+ text = "S"
+ intervals [362]:
+ xmin = 36.27
+ xmax = 36.37
+ text = "T"
+ intervals [363]:
+ xmin = 36.37
+ xmax = 36.74
+ text = ""
+ intervals [364]:
+ xmin = 36.74
+ xmax = 36.92
+ text = "AH1"
+ intervals [365]:
+ xmin = 36.92
+ xmax = 36.96
+ text = "DH"
+ intervals [366]:
+ xmin = 36.96
+ xmax = 37.02
+ text = "ER0"
+ intervals [367]:
+ xmin = 37.02
+ xmax = 37.05
+ text = "DH"
+ intervals [368]:
+ xmin = 37.05
+ xmax = 37.13
+ text = "AE1"
+ intervals [369]:
+ xmin = 37.13
+ xmax = 37.18
+ text = "N"
+ intervals [370]:
+ xmin = 37.18
+ xmax = 37.23
+ text = "DH"
+ intervals [371]:
+ xmin = 37.23
+ xmax = 37.47
+ text = "AE1"
+ intervals [372]:
+ xmin = 37.47
+ xmax = 37.73
+ text = "T"
+ intervals [373]:
+ xmin = 37.73
+ xmax = 37.76
+ text = ""
+ intervals [374]:
+ xmin = 37.76
+ xmax = 37.8
+ text = "F"
+ intervals [375]:
+ xmin = 37.8
+ xmax = 37.85
+ text = "AH0"
+ intervals [376]:
+ xmin = 37.85
+ xmax = 37.96
+ text = "T"
+ intervals [377]:
+ xmin = 37.96
+ xmax = 38.08
+ text = "AA1"
+ intervals [378]:
+ xmin = 38.08
+ xmax = 38.13
+ text = "G"
+ intervals [379]:
+ xmin = 38.13
+ xmax = 38.2
+ text = "R"
+ intervals [380]:
+ xmin = 38.2
+ xmax = 38.26
+ text = "AH0"
+ intervals [381]:
+ xmin = 38.26
+ xmax = 38.35
+ text = "F"
+ intervals [382]:
+ xmin = 38.35
+ xmax = 38.72
+ text = "IY0"
+ intervals [383]:
+ xmin = 38.72
+ xmax = 38.96
+ text = ""
+ intervals [384]:
+ xmin = 38.96
+ xmax = 39.25
+ text = "AO1"
+ intervals [385]:
+ xmin = 39.25
+ xmax = 39.3
+ text = "F"
+ intervals [386]:
+ xmin = 39.3
+ xmax = 39.36
+ text = "AH0"
+ intervals [387]:
+ xmin = 39.36
+ xmax = 39.4
+ text = "N"
+ intervals [388]:
+ xmin = 39.4
+ xmax = 39.47
+ text = "M"
+ intervals [389]:
+ xmin = 39.47
+ xmax = 39.54
+ text = "EY1"
+ intervals [390]:
+ xmin = 39.54
+ xmax = 39.59
+ text = "K"
+ intervals [391]:
+ xmin = 39.59
+ xmax = 39.66
+ text = "S"
+ intervals [392]:
+ xmin = 39.66
+ xmax = 39.7
+ text = "M"
+ intervals [393]:
+ xmin = 39.7
+ xmax = 39.8
+ text = "IY1"
+ intervals [394]:
+ xmin = 39.8
+ xmax = 39.94
+ text = "F"
+ intervals [395]:
+ xmin = 39.94
+ xmax = 40.09
+ text = "IY1"
+ intervals [396]:
+ xmin = 40.09
+ xmax = 40.39
+ text = "L"
+ intervals [397]:
+ xmin = 40.39
+ xmax = 40.48
+ text = "L"
+ intervals [398]:
+ xmin = 40.48
+ xmax = 40.62
+ text = "AY1"
+ intervals [399]:
+ xmin = 40.62
+ xmax = 40.72
+ text = "K"
+ intervals [400]:
+ xmin = 40.72
+ xmax = 40.97
+ text = "AY1"
+ intervals [401]:
+ xmin = 40.97
+ xmax = 41.42
+ text = "M"
+ intervals [402]:
+ xmin = 41.42
+ xmax = 41.77
+ text = ""
+ intervals [403]:
+ xmin = 41.77
+ xmax = 41.85
+ text = "D"
+ intervals [404]:
+ xmin = 41.85
+ xmax = 41.95
+ text = "UW1"
+ intervals [405]:
+ xmin = 41.95
+ xmax = 42.02
+ text = "IH0"
+ intervals [406]:
+ xmin = 42.02
+ xmax = 42.06
+ text = "NG"
+ intervals [407]:
+ xmin = 42.06
+ xmax = 42.13
+ text = "EY1"
+ intervals [408]:
+ xmin = 42.13
+ xmax = 42.25
+ text = "JH"
+ intervals [409]:
+ xmin = 42.25
+ xmax = 42.36
+ text = "AA1"
+ intervals [410]:
+ xmin = 42.36
+ xmax = 42.41
+ text = "B"
+ intervals [411]:
+ xmin = 42.41
+ xmax = 42.47
+ text = "F"
+ intervals [412]:
+ xmin = 42.47
+ xmax = 42.51
+ text = "UH1"
+ intervals [413]:
+ xmin = 42.51
+ xmax = 42.58
+ text = "L"
+ intervals [414]:
+ xmin = 42.58
+ xmax = 42.61
+ text = "AH0"
+ intervals [415]:
+ xmin = 42.61
+ xmax = 42.64
+ text = "V"
+ intervals [416]:
+ xmin = 42.64
+ xmax = 42.68
+ text = "D"
+ intervals [417]:
+ xmin = 42.68
+ xmax = 42.74
+ text = "IH0"
+ intervals [418]:
+ xmin = 42.74
+ xmax = 42.83
+ text = "Z"
+ intervals [419]:
+ xmin = 42.83
+ xmax = 42.96
+ text = "AY1"
+ intervals [420]:
+ xmin = 42.96
+ xmax = 42.99
+ text = "N"
+ intervals [421]:
+ xmin = 42.99
+ xmax = 43.03
+ text = "AE1"
+ intervals [422]:
+ xmin = 43.03
+ xmax = 43.07
+ text = "N"
+ intervals [423]:
+ xmin = 43.07
+ xmax = 43.12
+ text = "D"
+ intervals [424]:
+ xmin = 43.12
+ xmax = 43.19
+ text = "IH0"
+ intervals [425]:
+ xmin = 43.19
+ xmax = 43.25
+ text = "N"
+ intervals [426]:
+ xmin = 43.25
+ xmax = 43.3
+ text = "F"
+ intervals [427]:
+ xmin = 43.3
+ xmax = 43.52
+ text = "ER0"
+ intervals [428]:
+ xmin = 43.52
+ xmax = 43.68
+ text = "IH2"
+ intervals [429]:
+ xmin = 43.68
+ xmax = 43.74
+ text = "N"
+ intervals [430]:
+ xmin = 43.74
+ xmax = 43.8
+ text = "AH0"
+ intervals [431]:
+ xmin = 43.8
+ xmax = 43.87
+ text = "V"
+ intervals [432]:
+ xmin = 43.87
+ xmax = 44.01
+ text = "EY1"
+ intervals [433]:
+ xmin = 44.01
+ xmax = 44.09
+ text = "SH"
+ intervals [434]:
+ xmin = 44.09
+ xmax = 44.16
+ text = "AH0"
+ intervals [435]:
+ xmin = 44.16
+ xmax = 44.31
+ text = "N"
+ intervals [436]:
+ xmin = 44.31
+ xmax = 45.18
+ text = ""
+ intervals [437]:
+ xmin = 45.18
+ xmax = 45.24
+ text = "B"
+ intervals [438]:
+ xmin = 45.24
+ xmax = 45.3
+ text = "IH0"
+ intervals [439]:
+ xmin = 45.3
+ xmax = 45.39
+ text = "K"
+ intervals [440]:
+ xmin = 45.39
+ xmax = 45.54
+ text = "AH1"
+ intervals [441]:
+ xmin = 45.54
+ xmax = 45.73
+ text = "Z"
+ intervals [442]:
+ xmin = 45.73
+ xmax = 45.81
+ text = "F"
+ intervals [443]:
+ xmin = 45.81
+ xmax = 45.84
+ text = "R"
+ intervals [444]:
+ xmin = 45.84
+ xmax = 45.89
+ text = "ER0"
+ intervals [445]:
+ xmin = 45.89
+ xmax = 45.93
+ text = "DH"
+ intervals [446]:
+ xmin = 45.93
+ xmax = 45.99
+ text = "AH0"
+ intervals [447]:
+ xmin = 45.99
+ xmax = 46.12
+ text = "S"
+ intervals [448]:
+ xmin = 46.12
+ xmax = 46.25
+ text = "EY1"
+ intervals [449]:
+ xmin = 46.25
+ xmax = 46.35
+ text = "M"
+ intervals [450]:
+ xmin = 46.35
+ xmax = 46.48
+ text = "S"
+ intervals [451]:
+ xmin = 46.48
+ xmax = 46.59
+ text = "IY1"
+ intervals [452]:
+ xmin = 46.59
+ xmax = 46.65
+ text = "N"
+ intervals [453]:
+ xmin = 46.65
+ xmax = 46.74
+ text = "ER0"
+ intervals [454]:
+ xmin = 46.74
+ xmax = 46.88
+ text = "IY0"
+ intervals [455]:
+ xmin = 46.88
+ xmax = 46.94
+ text = "W"
+ intervals [456]:
+ xmin = 46.94
+ xmax = 47.01
+ text = "IY1"
+ intervals [457]:
+ xmin = 47.01
+ xmax = 47.06
+ text = "K"
+ intervals [458]:
+ xmin = 47.06
+ xmax = 47.09
+ text = "AH0"
+ intervals [459]:
+ xmin = 47.09
+ xmax = 47.12
+ text = "N"
+ intervals [460]:
+ xmin = 47.12
+ xmax = 47.22
+ text = "Y"
+ intervals [461]:
+ xmin = 47.22
+ xmax = 47.27
+ text = "UW1"
+ intervals [462]:
+ xmin = 47.27
+ xmax = 47.34
+ text = "Z"
+ intervals [463]:
+ xmin = 47.34
+ xmax = 47.4
+ text = "D"
+ intervals [464]:
+ xmin = 47.4
+ xmax = 47.45
+ text = "IH1"
+ intervals [465]:
+ xmin = 47.45
+ xmax = 47.49
+ text = "F"
+ intervals [466]:
+ xmin = 47.49
+ xmax = 47.52
+ text = "R"
+ intervals [467]:
+ xmin = 47.52
+ xmax = 47.55
+ text = "AH0"
+ intervals [468]:
+ xmin = 47.55
+ xmax = 47.58
+ text = "N"
+ intervals [469]:
+ xmin = 47.58
+ xmax = 47.61
+ text = "T"
+ intervals [470]:
+ xmin = 47.61
+ xmax = 47.74
+ text = "AE1"
+ intervals [471]:
+ xmin = 47.74
+ xmax = 47.82
+ text = "NG"
+ intervals [472]:
+ xmin = 47.82
+ xmax = 47.85
+ text = "G"
+ intervals [473]:
+ xmin = 47.85
+ xmax = 47.89
+ text = "AH0"
+ intervals [474]:
+ xmin = 47.89
+ xmax = 48.04
+ text = "L"
+ intervals [475]:
+ xmin = 48.04
+ xmax = 48.12
+ text = "Z"
+ intervals [476]:
+ xmin = 48.12
+ xmax = 48.15
+ text = "AH0"
+ intervals [477]:
+ xmin = 48.15
+ xmax = 48.18
+ text = "N"
+ intervals [478]:
+ xmin = 48.18
+ xmax = 48.21
+ text = "D"
+ intervals [479]:
+ xmin = 48.21
+ xmax = 48.26
+ text = "D"
+ intervals [480]:
+ xmin = 48.26
+ xmax = 48.31
+ text = "IH1"
+ intervals [481]:
+ xmin = 48.31
+ xmax = 48.36
+ text = "F"
+ intervals [482]:
+ xmin = 48.36
+ xmax = 48.39
+ text = "R"
+ intervals [483]:
+ xmin = 48.39
+ xmax = 48.42
+ text = "AH0"
+ intervals [484]:
+ xmin = 48.42
+ xmax = 48.45
+ text = "N"
+ intervals [485]:
+ xmin = 48.45
+ xmax = 48.48
+ text = "T"
+ intervals [486]:
+ xmin = 48.48
+ xmax = 48.53
+ text = "K"
+ intervals [487]:
+ xmin = 48.53
+ xmax = 48.6
+ text = "AA2"
+ intervals [488]:
+ xmin = 48.6
+ xmax = 48.64
+ text = "M"
+ intervals [489]:
+ xmin = 48.64
+ xmax = 48.67
+ text = "P"
+ intervals [490]:
+ xmin = 48.67
+ xmax = 48.72
+ text = "AH0"
+ intervals [491]:
+ xmin = 48.72
+ xmax = 48.8
+ text = "Z"
+ intervals [492]:
+ xmin = 48.8
+ xmax = 48.88
+ text = "IH1"
+ intervals [493]:
+ xmin = 48.88
+ xmax = 48.95
+ text = "SH"
+ intervals [494]:
+ xmin = 48.95
+ xmax = 49.02
+ text = "AH0"
+ intervals [495]:
+ xmin = 49.02
+ xmax = 49.12
+ text = "N"
+ intervals [496]:
+ xmin = 49.12
+ xmax = 49.32
+ text = "Z"
+ intervals [497]:
+ xmin = 49.32
+ xmax = 49.68
+ text = ""
+ intervals [498]:
+ xmin = 49.68
+ xmax = 49.91
+ text = "F"
+ intervals [499]:
+ xmin = 49.91
+ xmax = 49.98
+ text = "ER0"
+ intervals [500]:
+ xmin = 49.98
+ xmax = 50.02
+ text = "IH0"
+ intervals [501]:
+ xmin = 50.02
+ xmax = 50.06
+ text = "G"
+ intervals [502]:
+ xmin = 50.06
+ xmax = 50.13
+ text = "Z"
+ intervals [503]:
+ xmin = 50.13
+ xmax = 50.22
+ text = "AE1"
+ intervals [504]:
+ xmin = 50.22
+ xmax = 50.27
+ text = "M"
+ intervals [505]:
+ xmin = 50.27
+ xmax = 50.31
+ text = "P"
+ intervals [506]:
+ xmin = 50.31
+ xmax = 50.34
+ text = "AH0"
+ intervals [507]:
+ xmin = 50.34
+ xmax = 50.4
+ text = "L"
+ intervals [508]:
+ xmin = 50.4
+ xmax = 50.48
+ text = "P"
+ intervals [509]:
+ xmin = 50.48
+ xmax = 50.58
+ text = "IY1"
+ intervals [510]:
+ xmin = 50.58
+ xmax = 50.63
+ text = "P"
+ intervals [511]:
+ xmin = 50.63
+ xmax = 50.69
+ text = "AH0"
+ intervals [512]:
+ xmin = 50.69
+ xmax = 50.91
+ text = "L"
+ intervals [513]:
+ xmin = 50.91
+ xmax = 51.21
+ text = "B"
+ intervals [514]:
+ xmin = 51.21
+ xmax = 51.29
+ text = "IY1"
+ intervals [515]:
+ xmin = 51.29
+ xmax = 51.34
+ text = "IH0"
+ intervals [516]:
+ xmin = 51.34
+ xmax = 51.42
+ text = "NG"
+ intervals [517]:
+ xmin = 51.42
+ xmax = 51.57
+ text = "SH"
+ intervals [518]:
+ xmin = 51.57
+ xmax = 51.62
+ text = "IH1"
+ intervals [519]:
+ xmin = 51.62
+ xmax = 51.68
+ text = "F"
+ intervals [520]:
+ xmin = 51.68
+ xmax = 51.74
+ text = "T"
+ intervals [521]:
+ xmin = 51.74
+ xmax = 51.79
+ text = "IH0"
+ intervals [522]:
+ xmin = 51.79
+ xmax = 51.91
+ text = "D"
+ intervals [523]:
+ xmin = 51.91
+ xmax = 51.94
+ text = "F"
+ intervals [524]:
+ xmin = 51.94
+ xmax = 52.02
+ text = "ER0"
+ intervals [525]:
+ xmin = 52.02
+ xmax = 52.06
+ text = "M"
+ intervals [526]:
+ xmin = 52.06
+ xmax = 52.1
+ text = "DH"
+ intervals [527]:
+ xmin = 52.1
+ xmax = 52.15
+ text = "AH0"
+ intervals [528]:
+ xmin = 52.15
+ xmax = 52.27
+ text = "S"
+ intervals [529]:
+ xmin = 52.27
+ xmax = 52.32
+ text = "EH1"
+ intervals [530]:
+ xmin = 52.32
+ xmax = 52.38
+ text = "N"
+ intervals [531]:
+ xmin = 52.38
+ xmax = 52.47
+ text = "ER0"
+ intervals [532]:
+ xmin = 52.47
+ xmax = 52.51
+ text = "AH0"
+ intervals [533]:
+ xmin = 52.51
+ xmax = 52.54
+ text = "V"
+ intervals [534]:
+ xmin = 52.54
+ xmax = 52.57
+ text = "DH"
+ intervals [535]:
+ xmin = 52.57
+ xmax = 52.63
+ text = "AH0"
+ intervals [536]:
+ xmin = 52.63
+ xmax = 52.72
+ text = "F"
+ intervals [537]:
+ xmin = 52.72
+ xmax = 52.8
+ text = "R"
+ intervals [538]:
+ xmin = 52.8
+ xmax = 52.89
+ text = "EY1"
+ intervals [539]:
+ xmin = 52.89
+ xmax = 52.95
+ text = "M"
+ intervals [540]:
+ xmin = 52.95
+ xmax = 53.01
+ text = "T"
+ intervals [541]:
+ xmin = 53.01
+ xmax = 53.1
+ text = "AH0"
+ intervals [542]:
+ xmin = 53.1
+ xmax = 53.19
+ text = "L"
+ intervals [543]:
+ xmin = 53.19
+ xmax = 53.26
+ text = "EH1"
+ intervals [544]:
+ xmin = 53.26
+ xmax = 53.29
+ text = "F"
+ intervals [545]:
+ xmin = 53.29
+ xmax = 53.32
+ text = "T"
+ intervals [546]:
+ xmin = 53.32
+ xmax = 53.4
+ text = "S"
+ intervals [547]:
+ xmin = 53.4
+ xmax = 53.5
+ text = "AY1"
+ intervals [548]:
+ xmin = 53.5
+ xmax = 53.54
+ text = "D"
+ intervals [549]:
+ xmin = 53.54
+ xmax = 53.57
+ text = "AH0"
+ intervals [550]:
+ xmin = 53.57
+ xmax = 53.6
+ text = "V"
+ intervals [551]:
+ xmin = 53.6
+ xmax = 53.63
+ text = "DH"
+ intervals [552]:
+ xmin = 53.63
+ xmax = 53.69
+ text = "AH0"
+ intervals [553]:
+ xmin = 53.69
+ xmax = 53.78
+ text = "F"
+ intervals [554]:
+ xmin = 53.78
+ xmax = 53.92
+ text = "R"
+ intervals [555]:
+ xmin = 53.92
+ xmax = 54.03
+ text = "EY1"
+ intervals [556]:
+ xmin = 54.03
+ xmax = 54.17
+ text = "M"
+ intervals [557]:
+ xmin = 54.17
+ xmax = 54.62
+ text = ""
+ intervals [558]:
+ xmin = 54.62
+ xmax = 54.72
+ text = "IH0"
+ intervals [559]:
+ xmin = 54.72
+ xmax = 54.75
+ text = "T"
+ intervals [560]:
+ xmin = 54.75
+ xmax = 54.82
+ text = "K"
+ intervals [561]:
+ xmin = 54.82
+ xmax = 54.88
+ text = "AH0"
+ intervals [562]:
+ xmin = 54.88
+ xmax = 54.91
+ text = "N"
+ intervals [563]:
+ xmin = 54.91
+ xmax = 54.97
+ text = "M"
+ intervals [564]:
+ xmin = 54.97
+ xmax = 55.1
+ text = "EY1"
+ intervals [565]:
+ xmin = 55.1
+ xmax = 55.13
+ text = "K"
+ intervals [566]:
+ xmin = 55.13
+ xmax = 55.22
+ text = "EY1"
+ intervals [567]:
+ xmin = 55.22
+ xmax = 55.29
+ text = "D"
+ intervals [568]:
+ xmin = 55.29
+ xmax = 55.35
+ text = "IH1"
+ intervals [569]:
+ xmin = 55.35
+ xmax = 55.43
+ text = "F"
+ intervals [570]:
+ xmin = 55.43
+ xmax = 55.46
+ text = "R"
+ intervals [571]:
+ xmin = 55.46
+ xmax = 55.49
+ text = "AH0"
+ intervals [572]:
+ xmin = 55.49
+ xmax = 55.52
+ text = "N"
+ intervals [573]:
+ xmin = 55.52
+ xmax = 55.56
+ text = "T"
+ intervals [574]:
+ xmin = 55.56
+ xmax = 55.64
+ text = "F"
+ intervals [575]:
+ xmin = 55.64
+ xmax = 55.77
+ text = "IY1"
+ intervals [576]:
+ xmin = 55.77
+ xmax = 55.82
+ text = "L"
+ intervals [577]:
+ xmin = 55.82
+ xmax = 55.88
+ text = "IH0"
+ intervals [578]:
+ xmin = 55.88
+ xmax = 56.05
+ text = "NG"
+ intervals [579]:
+ xmin = 56.05
+ xmax = 56.41
+ text = ""
+ intervals [580]:
+ xmin = 56.41
+ xmax = 56.48
+ text = "W"
+ intervals [581]:
+ xmin = 56.48
+ xmax = 56.66
+ text = "EH1"
+ intervals [582]:
+ xmin = 56.66
+ xmax = 56.69
+ text = "N"
+ intervals [583]:
+ xmin = 56.69
+ xmax = 57.1
+ text = "W"
+ intervals [584]:
+ xmin = 57.1
+ xmax = 57.25
+ text = "IY1"
+ intervals [585]:
+ xmin = 57.25
+ xmax = 57.5
+ text = ""
+ intervals [586]:
+ xmin = 57.5
+ xmax = 57.68
+ text = "W"
+ intervals [587]:
+ xmin = 57.68
+ xmax = 57.72
+ text = "EH1"
+ intervals [588]:
+ xmin = 57.72
+ xmax = 57.82
+ text = "N"
+ intervals [589]:
+ xmin = 57.82
+ xmax = 57.96
+ text = "S"
+ intervals [590]:
+ xmin = 57.96
+ xmax = 58.02
+ text = "IY1"
+ intervals [591]:
+ xmin = 58.02
+ xmax = 58.07
+ text = "N"
+ intervals [592]:
+ xmin = 58.07
+ xmax = 58.11
+ text = "IH1"
+ intervals [593]:
+ xmin = 58.11
+ xmax = 58.17
+ text = "N"
+ intervals [594]:
+ xmin = 58.17
+ xmax = 58.25
+ text = "K"
+ intervals [595]:
+ xmin = 58.25
+ xmax = 58.41
+ text = "AA1"
+ intervals [596]:
+ xmin = 58.41
+ xmax = 58.47
+ text = "N"
+ intervals [597]:
+ xmin = 58.47
+ xmax = 58.53
+ text = "T"
+ intervals [598]:
+ xmin = 58.53
+ xmax = 58.65
+ text = "EH0"
+ intervals [599]:
+ xmin = 58.65
+ xmax = 58.69
+ text = "K"
+ intervals [600]:
+ xmin = 58.69
+ xmax = 58.74
+ text = "S"
+ intervals [601]:
+ xmin = 58.74
+ xmax = 58.77
+ text = "T"
+ intervals [602]:
+ xmin = 58.77
+ xmax = 58.8
+ text = "W"
+ intervals [603]:
+ xmin = 58.8
+ xmax = 58.83
+ text = "IH0"
+ intervals [604]:
+ xmin = 58.83
+ xmax = 58.86
+ text = "DH"
+ intervals [605]:
+ xmin = 58.86
+ xmax = 58.9
+ text = "DH"
+ intervals [606]:
+ xmin = 58.9
+ xmax = 58.93
+ text = "AH1"
+ intervals [607]:
+ xmin = 58.93
+ xmax = 59.03
+ text = "B"
+ intervals [608]:
+ xmin = 59.03
+ xmax = 59.2
+ text = "AE1"
+ intervals [609]:
+ xmin = 59.2
+ xmax = 59.25
+ text = "K"
+ intervals [610]:
+ xmin = 59.25
+ xmax = 59.29
+ text = "G"
+ intervals [611]:
+ xmin = 59.29
+ xmax = 59.33
+ text = "R"
+ intervals [612]:
+ xmin = 59.33
+ xmax = 59.45
+ text = "AW2"
+ intervals [613]:
+ xmin = 59.45
+ xmax = 59.52
+ text = "N"
+ intervals [614]:
+ xmin = 59.52
+ xmax = 59.61
+ text = "D"
+ intervals [615]:
+ xmin = 59.61
+ xmax = 59.96
+ text = ""
+ intervals [616]:
+ xmin = 59.96
+ xmax = 60.13
+ text = "W"
+ intervals [617]:
+ xmin = 60.13
+ xmax = 60.17
+ text = "EH1"
+ intervals [618]:
+ xmin = 60.17
+ xmax = 60.31
+ text = "N"
+ intervals [619]:
+ xmin = 60.31
+ xmax = 60.41
+ text = "EH1"
+ intervals [620]:
+ xmin = 60.41
+ xmax = 60.45
+ text = "V"
+ intervals [621]:
+ xmin = 60.45
+ xmax = 60.48
+ text = "R"
+ intervals [622]:
+ xmin = 60.48
+ xmax = 60.51
+ text = "IY0"
+ intervals [623]:
+ xmin = 60.51
+ xmax = 60.58
+ text = "W"
+ intervals [624]:
+ xmin = 60.58
+ xmax = 60.65
+ text = "AH2"
+ intervals [625]:
+ xmin = 60.65
+ xmax = 60.69
+ text = "N"
+ intervals [626]:
+ xmin = 60.69
+ xmax = 60.79
+ text = "Z"
+ intervals [627]:
+ xmin = 60.79
+ xmax = 60.86
+ text = "T"
+ intervals [628]:
+ xmin = 60.86
+ xmax = 60.92
+ text = "EY1"
+ intervals [629]:
+ xmin = 60.92
+ xmax = 60.95
+ text = "K"
+ intervals [630]:
+ xmin = 60.95
+ xmax = 61.0
+ text = "IH0"
+ intervals [631]:
+ xmin = 61.0
+ xmax = 61.08
+ text = "NG"
+ intervals [632]:
+ xmin = 61.08
+ xmax = 61.14
+ text = "AH0"
+ intervals [633]:
+ xmin = 61.14
+ xmax = 61.2
+ text = "P"
+ intervals [634]:
+ xmin = 61.2
+ xmax = 61.28
+ text = "IH1"
+ intervals [635]:
+ xmin = 61.28
+ xmax = 61.32
+ text = "K"
+ intervals [636]:
+ xmin = 61.32
+ xmax = 61.43
+ text = "CH"
+ intervals [637]:
+ xmin = 61.43
+ xmax = 61.46
+ text = "ER0"
+ intervals [638]:
+ xmin = 61.46
+ xmax = 61.49
+ text = "AH0"
+ intervals [639]:
+ xmin = 61.49
+ xmax = 61.53
+ text = "V"
+ intervals [640]:
+ xmin = 61.53
+ xmax = 61.56
+ text = "DH"
+ intervals [641]:
+ xmin = 61.56
+ xmax = 61.6
+ text = "AH0"
+ intervals [642]:
+ xmin = 61.6
+ xmax = 61.64
+ text = "IH0"
+ intervals [643]:
+ xmin = 61.64
+ xmax = 61.69
+ text = "G"
+ intervals [644]:
+ xmin = 61.69
+ xmax = 61.76
+ text = "Z"
+ intervals [645]:
+ xmin = 61.76
+ xmax = 61.9
+ text = "AE1"
+ intervals [646]:
+ xmin = 61.9
+ xmax = 61.94
+ text = "K"
+ intervals [647]:
+ xmin = 61.94
+ xmax = 61.98
+ text = "T"
+ intervals [648]:
+ xmin = 61.98
+ xmax = 62.05
+ text = "S"
+ intervals [649]:
+ xmin = 62.05
+ xmax = 62.13
+ text = "EY1"
+ intervals [650]:
+ xmin = 62.13
+ xmax = 62.19
+ text = "M"
+ intervals [651]:
+ xmin = 62.19
+ xmax = 62.3
+ text = "S"
+ intervals [652]:
+ xmin = 62.3
+ xmax = 62.34
+ text = "IY1"
+ intervals [653]:
+ xmin = 62.34
+ xmax = 62.39
+ text = "N"
+ intervals [654]:
+ xmin = 62.39
+ xmax = 62.47
+ text = "ER0"
+ intervals [655]:
+ xmin = 62.47
+ xmax = 62.64
+ text = "IY0"
+ intervals [656]:
+ xmin = 62.64
+ xmax = 62.67
+ text = ""
+ intervals [657]:
+ xmin = 62.67
+ xmax = 62.8
+ text = "AY1"
+ intervals [658]:
+ xmin = 62.8
+ xmax = 62.89
+ text = "M"
+ intervals [659]:
+ xmin = 62.89
+ xmax = 63.03
+ text = "V"
+ intervals [660]:
+ xmin = 63.03
+ xmax = 63.12
+ text = "EH1"
+ intervals [661]:
+ xmin = 63.12
+ xmax = 63.22
+ text = "R"
+ intervals [662]:
+ xmin = 63.22
+ xmax = 63.28
+ text = "IY0"
+ intervals [663]:
+ xmin = 63.28
+ xmax = 63.39
+ text = "HH"
+ intervals [664]:
+ xmin = 63.39
+ xmax = 63.56
+ text = "AE1"
+ intervals [665]:
+ xmin = 63.56
+ xmax = 63.62
+ text = "P"
+ intervals [666]:
+ xmin = 63.62
+ xmax = 63.75
+ text = "IY0"
+ intervals [667]:
+ xmin = 63.75
+ xmax = 63.81
+ text = "W"
+ intervals [668]:
+ xmin = 63.81
+ xmax = 63.85
+ text = "IH1"
+ intervals [669]:
+ xmin = 63.85
+ xmax = 63.9
+ text = "N"
+ intervals [670]:
+ xmin = 63.9
+ xmax = 64.03
+ text = "P"
+ intervals [671]:
+ xmin = 64.03
+ xmax = 64.14
+ text = "IY1"
+ intervals [672]:
+ xmin = 64.14
+ xmax = 64.19
+ text = "P"
+ intervals [673]:
+ xmin = 64.19
+ xmax = 64.23
+ text = "AH0"
+ intervals [674]:
+ xmin = 64.23
+ xmax = 64.35
+ text = "L"
+ intervals [675]:
+ xmin = 64.35
+ xmax = 64.48
+ text = "S"
+ intervals [676]:
+ xmin = 64.48
+ xmax = 64.6
+ text = "EY1"
+ intervals [677]:
+ xmin = 64.6
+ xmax = 64.69
+ text = "M"
+ intervals [678]:
+ xmin = 64.69
+ xmax = 64.84
+ text = "AY1"
+ intervals [679]:
+ xmin = 64.84
+ xmax = 64.99
+ text = "F"
+ intervals [680]:
+ xmin = 64.99
+ xmax = 65.07
+ text = "OW1"
+ intervals [681]:
+ xmin = 65.07
+ xmax = 65.1
+ text = "T"
+ intervals [682]:
+ xmin = 65.1
+ xmax = 65.18
+ text = "OW2"
+ intervals [683]:
+ xmin = 65.18
+ xmax = 65.29
+ text = "Z"
+ intervals [684]:
+ xmin = 65.29
+ xmax = 65.37
+ text = "L"
+ intervals [685]:
+ xmin = 65.37
+ xmax = 65.42
+ text = "UH1"
+ intervals [686]:
+ xmin = 65.42
+ xmax = 65.47
+ text = "K"
+ intervals [687]:
+ xmin = 65.47
+ xmax = 65.67
+ text = "B"
+ intervals [688]:
+ xmin = 65.67
+ xmax = 65.79
+ text = "EH1"
+ intervals [689]:
+ xmin = 65.79
+ xmax = 65.88
+ text = "T"
+ intervals [690]:
+ xmin = 65.88
+ xmax = 66.11
+ text = "ER0"
+ intervals [691]:
+ xmin = 66.11
+ xmax = 66.43
+ text = ""
+ intervals [692]:
+ xmin = 66.43
+ xmax = 66.5
+ text = "DH"
+ intervals [693]:
+ xmin = 66.5
+ xmax = 66.53
+ text = "AH0"
+ intervals [694]:
+ xmin = 66.53
+ xmax = 66.56
+ text = "N"
+ intervals [695]:
+ xmin = 66.56
+ xmax = 66.6
+ text = "DH"
+ intervals [696]:
+ xmin = 66.6
+ xmax = 66.7
+ text = "IY0"
+ intervals [697]:
+ xmin = 66.7
+ xmax = 66.76
+ text = "AH1"
+ intervals [698]:
+ xmin = 66.76
+ xmax = 66.82
+ text = "DH"
+ intervals [699]:
+ xmin = 66.82
+ xmax = 66.95
+ text = "ER0"
+ intervals [700]:
+ xmin = 66.95
+ xmax = 67.19
+ text = "Z"
+ intervals [701]:
+ xmin = 67.19
+ xmax = 68
+ text = ""
diff --git a/EMAGE/test_sequences/textgrid/2_scott_0_4_4.TextGrid b/EMAGE/test_sequences/textgrid/2_scott_0_4_4.TextGrid
new file mode 100644
index 0000000000000000000000000000000000000000..017574fad30ad90188cab3099371d11ff28c71a2
--- /dev/null
+++ b/EMAGE/test_sequences/textgrid/2_scott_0_4_4.TextGrid
@@ -0,0 +1,3844 @@
+File type = "ooTextFile"
+Object class = "TextGrid"
+
+xmin = 0.0
+xmax = 67
+tiers?
+size = 2
+item []:
+ item [1]:
+ class = "IntervalTier"
+ name = "words"
+ xmin = 0.0
+ xmax = 67
+ intervals: size = 235
+ intervals [1]:
+ xmin = 0.0
+ xmax = 0.53
+ text = ""
+ intervals [2]:
+ xmin = 0.53
+ xmax = 0.93
+ text = "my"
+ intervals [3]:
+ xmin = 0.93
+ xmax = 1.34
+ text = "favorite"
+ intervals [4]:
+ xmin = 1.34
+ xmax = 1.57
+ text = "kind"
+ intervals [5]:
+ xmin = 1.57
+ xmax = 1.65
+ text = "of"
+ intervals [6]:
+ xmin = 1.65
+ xmax = 2.2
+ text = "movies"
+ intervals [7]:
+ xmin = 2.2
+ xmax = 2.45
+ text = "are"
+ intervals [8]:
+ xmin = 2.45
+ xmax = 3.2
+ text = "romantic"
+ intervals [9]:
+ xmin = 3.2
+ xmax = 3.72
+ text = "movies"
+ intervals [10]:
+ xmin = 3.72
+ xmax = 3.75
+ text = ""
+ intervals [11]:
+ xmin = 3.75
+ xmax = 4.1
+ text = "such"
+ intervals [12]:
+ xmin = 4.1
+ xmax = 4.33
+ text = "as"
+ intervals [13]:
+ xmin = 4.33
+ xmax = 5.23
+ text = "titanic"
+ intervals [14]:
+ xmin = 5.23
+ xmax = 5.78
+ text = ""
+ intervals [15]:
+ xmin = 5.78
+ xmax = 6.19
+ text = "it's"
+ intervals [16]:
+ xmin = 6.19
+ xmax = 6.46
+ text = "a"
+ intervals [17]:
+ xmin = 6.46
+ xmax = 6.49
+ text = ""
+ intervals [18]:
+ xmin = 6.49
+ xmax = 7.13
+ text = "fantastic"
+ intervals [19]:
+ xmin = 7.13
+ xmax = 7.56
+ text = "film"
+ intervals [20]:
+ xmin = 7.56
+ xmax = 7.77
+ text = "it"
+ intervals [21]:
+ xmin = 7.77
+ xmax = 8.28
+ text = "captured"
+ intervals [22]:
+ xmin = 8.28
+ xmax = 8.73
+ text = "many"
+ intervals [23]:
+ xmin = 8.73
+ xmax = 9.1
+ text = "young"
+ intervals [24]:
+ xmin = 9.1
+ xmax = 9.44
+ text = "people's"
+ intervals [25]:
+ xmin = 9.44
+ xmax = 9.79
+ text = "hearts"
+ intervals [26]:
+ xmin = 9.79
+ xmax = 10.02
+ text = "with"
+ intervals [27]:
+ xmin = 10.02
+ xmax = 10.17
+ text = "it's"
+ intervals [28]:
+ xmin = 10.17
+ xmax = 10.65
+ text = "amazing"
+ intervals [29]:
+ xmin = 10.65
+ xmax = 11.12
+ text = "music"
+ intervals [30]:
+ xmin = 11.12
+ xmax = 11.36
+ text = "and"
+ intervals [31]:
+ xmin = 11.36
+ xmax = 11.92
+ text = "sentimental"
+ intervals [32]:
+ xmin = 11.92
+ xmax = 12.47
+ text = "plots"
+ intervals [33]:
+ xmin = 12.47
+ xmax = 12.84
+ text = ""
+ intervals [34]:
+ xmin = 12.84
+ xmax = 12.98
+ text = "when"
+ intervals [35]:
+ xmin = 12.98
+ xmax = 13.12
+ text = "i"
+ intervals [36]:
+ xmin = 13.12
+ xmax = 13.28
+ text = "think"
+ intervals [37]:
+ xmin = 13.28
+ xmax = 13.35
+ text = "of"
+ intervals [38]:
+ xmin = 13.35
+ xmax = 13.42
+ text = "the"
+ intervals [39]:
+ xmin = 13.42
+ xmax = 13.62
+ text = "movie"
+ intervals [40]:
+ xmin = 13.62
+ xmax = 14.2
+ text = "titanic"
+ intervals [41]:
+ xmin = 14.2
+ xmax = 14.23
+ text = ""
+ intervals [42]:
+ xmin = 14.23
+ xmax = 14.42
+ text = "the"
+ intervals [43]:
+ xmin = 14.42
+ xmax = 14.92
+ text = "word"
+ intervals [44]:
+ xmin = 14.92
+ xmax = 15.06
+ text = "that"
+ intervals [45]:
+ xmin = 15.06
+ xmax = 15.3
+ text = "comes"
+ intervals [46]:
+ xmin = 15.3
+ xmax = 15.39
+ text = "to"
+ intervals [47]:
+ xmin = 15.39
+ xmax = 15.5
+ text = "my"
+ intervals [48]:
+ xmin = 15.5
+ xmax = 15.91
+ text = "mind"
+ intervals [49]:
+ xmin = 15.91
+ xmax = 16.06
+ text = "mind"
+ intervals [50]:
+ xmin = 16.06
+ xmax = 16.41
+ text = ""
+ intervals [51]:
+ xmin = 16.41
+ xmax = 16.6
+ text = "to"
+ intervals [52]:
+ xmin = 16.6
+ xmax = 17.07
+ text = "mises"
+ intervals [53]:
+ xmin = 17.07
+ xmax = 17.15
+ text = "the"
+ intervals [54]:
+ xmin = 17.15
+ xmax = 17.39
+ text = "whole"
+ intervals [55]:
+ xmin = 17.39
+ xmax = 17.94
+ text = "film"
+ intervals [56]:
+ xmin = 17.94
+ xmax = 17.97
+ text = ""
+ intervals [57]:
+ xmin = 17.97
+ xmax = 18.18
+ text = "would"
+ intervals [58]:
+ xmin = 18.18
+ xmax = 18.62
+ text = "be"
+ intervals [59]:
+ xmin = 18.62
+ xmax = 19.09
+ text = ""
+ intervals [60]:
+ xmin = 19.09
+ xmax = 19.94
+ text = "love"
+ intervals [61]:
+ xmin = 19.94
+ xmax = 20.07
+ text = ""
+ intervals [62]:
+ xmin = 20.07
+ xmax = 20.27
+ text = "it's"
+ intervals [63]:
+ xmin = 20.27
+ xmax = 20.36
+ text = "a"
+ intervals [64]:
+ xmin = 20.36
+ xmax = 20.83
+ text = "kind"
+ intervals [65]:
+ xmin = 20.83
+ xmax = 20.98
+ text = "of"
+ intervals [66]:
+ xmin = 20.98
+ xmax = 21.25
+ text = "thing"
+ intervals [67]:
+ xmin = 21.25
+ xmax = 21.43
+ text = "that"
+ intervals [68]:
+ xmin = 21.43
+ xmax = 21.8
+ text = "makes"
+ intervals [69]:
+ xmin = 21.8
+ xmax = 22.28
+ text = "you"
+ intervals [70]:
+ xmin = 22.28
+ xmax = 22.31
+ text = ""
+ intervals [71]:
+ xmin = 22.31
+ xmax = 22.8
+ text = "makes"
+ intervals [72]:
+ xmin = 22.8
+ xmax = 22.91
+ text = "the"
+ intervals [73]:
+ xmin = 22.91
+ xmax = 23.21
+ text = "world"
+ intervals [74]:
+ xmin = 23.21
+ xmax = 23.38
+ text = "go"
+ intervals [75]:
+ xmin = 23.38
+ xmax = 23.87
+ text = "round"
+ intervals [76]:
+ xmin = 23.87
+ xmax = 24.08
+ text = ""
+ intervals [77]:
+ xmin = 24.08
+ xmax = 24.6
+ text = "watching"
+ intervals [78]:
+ xmin = 24.6
+ xmax = 24.8
+ text = "these"
+ intervals [79]:
+ xmin = 24.8
+ xmax = 25.18
+ text = "kinds"
+ intervals [80]:
+ xmin = 25.18
+ xmax = 25.29
+ text = "of"
+ intervals [81]:
+ xmin = 25.29
+ xmax = 25.83
+ text = "romantic"
+ intervals [82]:
+ xmin = 25.83
+ xmax = 26.23
+ text = "movies"
+ intervals [83]:
+ xmin = 26.23
+ xmax = 26.43
+ text = "is"
+ intervals [84]:
+ xmin = 26.43
+ xmax = 26.86
+ text = "just"
+ intervals [85]:
+ xmin = 26.86
+ xmax = 27.07
+ text = "like"
+ intervals [86]:
+ xmin = 27.07
+ xmax = 27.49
+ text = "reading"
+ intervals [87]:
+ xmin = 27.49
+ xmax = 27.56
+ text = "a"
+ intervals [88]:
+ xmin = 27.56
+ xmax = 27.98
+ text = "book"
+ intervals [89]:
+ xmin = 27.98
+ xmax = 28.11
+ text = ""
+ intervals [90]:
+ xmin = 28.11
+ xmax = 28.29
+ text = "that"
+ intervals [91]:
+ xmin = 28.29
+ xmax = 28.65
+ text = "teaches"
+ intervals [92]:
+ xmin = 28.65
+ xmax = 28.78
+ text = "me"
+ intervals [93]:
+ xmin = 28.78
+ xmax = 28.99
+ text = "how"
+ intervals [94]:
+ xmin = 28.99
+ xmax = 29.19
+ text = "to"
+ intervals [95]:
+ xmin = 29.19
+ xmax = 29.61
+ text = "love"
+ intervals [96]:
+ xmin = 29.61
+ xmax = 29.93
+ text = "and"
+ intervals [97]:
+ xmin = 29.93
+ xmax = 30.09
+ text = "be"
+ intervals [98]:
+ xmin = 30.09
+ xmax = 30.53
+ text = "loved"
+ intervals [99]:
+ xmin = 30.53
+ xmax = 30.96
+ text = ""
+ intervals [100]:
+ xmin = 30.96
+ xmax = 31.68
+ text = "moreover"
+ intervals [101]:
+ xmin = 31.68
+ xmax = 31.81
+ text = "we"
+ intervals [102]:
+ xmin = 31.81
+ xmax = 32.01
+ text = ""
+ intervals [103]:
+ xmin = 32.01
+ xmax = 32.51
+ text = "can"
+ intervals [104]:
+ xmin = 32.51
+ xmax = 32.56
+ text = ""
+ intervals [105]:
+ xmin = 32.56
+ xmax = 32.72
+ text = "learn"
+ intervals [106]:
+ xmin = 32.72
+ xmax = 33.09
+ text = "we"
+ intervals [107]:
+ xmin = 33.09
+ xmax = 33.25
+ text = "can"
+ intervals [108]:
+ xmin = 33.25
+ xmax = 34.05
+ text = "learn"
+ intervals [109]:
+ xmin = 34.05
+ xmax = 34.2
+ text = ""
+ intervals [110]:
+ xmin = 34.2
+ xmax = 35.12
+ text = "more"
+ intervals [111]:
+ xmin = 35.12
+ xmax = 35.44
+ text = "from"
+ intervals [112]:
+ xmin = 35.44
+ xmax = 35.66
+ text = "it"
+ intervals [113]:
+ xmin = 35.66
+ xmax = 35.98
+ text = "such"
+ intervals [114]:
+ xmin = 35.98
+ xmax = 36.35
+ text = "things"
+ intervals [115]:
+ xmin = 36.35
+ xmax = 36.69
+ text = "as"
+ intervals [116]:
+ xmin = 36.69
+ xmax = 36.89
+ text = ""
+ intervals [117]:
+ xmin = 36.89
+ xmax = 37.59
+ text = "loyalty"
+ intervals [118]:
+ xmin = 37.59
+ xmax = 37.76
+ text = "and"
+ intervals [119]:
+ xmin = 37.76
+ xmax = 37.88
+ text = "what"
+ intervals [120]:
+ xmin = 37.88
+ xmax = 37.99
+ text = "we"
+ intervals [121]:
+ xmin = 37.99
+ xmax = 38.47
+ text = "treasure"
+ intervals [122]:
+ xmin = 38.47
+ xmax = 38.58
+ text = "in"
+ intervals [123]:
+ xmin = 38.58
+ xmax = 38.71
+ text = "our"
+ intervals [124]:
+ xmin = 38.71
+ xmax = 39.11
+ text = "lives"
+ intervals [125]:
+ xmin = 39.11
+ xmax = 39.4
+ text = ""
+ intervals [126]:
+ xmin = 39.4
+ xmax = 39.8
+ text = "another"
+ intervals [127]:
+ xmin = 39.8
+ xmax = 40.13
+ text = "movie"
+ intervals [128]:
+ xmin = 40.13
+ xmax = 40.51
+ text = "about"
+ intervals [129]:
+ xmin = 40.51
+ xmax = 40.83
+ text = "love"
+ intervals [130]:
+ xmin = 40.83
+ xmax = 41.08
+ text = "is"
+ intervals [131]:
+ xmin = 41.08
+ xmax = 41.24
+ text = "the"
+ intervals [132]:
+ xmin = 41.24
+ xmax = 41.3
+ text = ""
+ intervals [133]:
+ xmin = 41.3
+ xmax = 41.9
+ text = "secret"
+ intervals [134]:
+ xmin = 41.9
+ xmax = 42.13
+ text = ""
+ intervals [135]:
+ xmin = 42.13
+ xmax = 42.47
+ text = "the"
+ intervals [136]:
+ xmin = 42.47
+ xmax = 43.01
+ text = "movie"
+ intervals [137]:
+ xmin = 43.01
+ xmax = 43.58
+ text = "secret"
+ intervals [138]:
+ xmin = 43.58
+ xmax = 43.71
+ text = "is"
+ intervals [139]:
+ xmin = 43.71
+ xmax = 44.1
+ text = "about"
+ intervals [140]:
+ xmin = 44.1
+ xmax = 44.15
+ text = "a"
+ intervals [141]:
+ xmin = 44.15
+ xmax = 44.88
+ text = "story"
+ intervals [142]:
+ xmin = 44.88
+ xmax = 44.95
+ text = ""
+ intervals [143]:
+ xmin = 44.95
+ xmax = 45.14
+ text = "of"
+ intervals [144]:
+ xmin = 45.14
+ xmax = 45.21
+ text = "a"
+ intervals [145]:
+ xmin = 45.21
+ xmax = 45.56
+ text = "musical"
+ intervals [146]:
+ xmin = 45.56
+ xmax = 45.96
+ text = "prodigy"
+ intervals [147]:
+ xmin = 45.96
+ xmax = 46.04
+ text = "do"
+ intervals [148]:
+ xmin = 46.04
+ xmax = 46.17
+ text = "that"
+ intervals [149]:
+ xmin = 46.17
+ xmax = 46.42
+ text = "falls"
+ intervals [150]:
+ xmin = 46.42
+ xmax = 46.49
+ text = "in"
+ intervals [151]:
+ xmin = 46.49
+ xmax = 46.62
+ text = "love"
+ intervals [152]:
+ xmin = 46.62
+ xmax = 46.72
+ text = "with"
+ intervals [153]:
+ xmin = 46.72
+ xmax = 46.85
+ text = "a"
+ intervals [154]:
+ xmin = 46.85
+ xmax = 46.91
+ text = ""
+ intervals [155]:
+ xmin = 46.91
+ xmax = 47.21
+ text = "girl"
+ intervals [156]:
+ xmin = 47.21
+ xmax = 47.46
+ text = "who's"
+ intervals [157]:
+ xmin = 47.46
+ xmax = 48.01
+ text = "dying"
+ intervals [158]:
+ xmin = 48.01
+ xmax = 49.08
+ text = ""
+ intervals [159]:
+ xmin = 49.08
+ xmax = 49.33
+ text = "there"
+ intervals [160]:
+ xmin = 49.33
+ xmax = 49.39
+ text = "are"
+ intervals [161]:
+ xmin = 49.39
+ xmax = 49.46
+ text = "a"
+ intervals [162]:
+ xmin = 49.46
+ xmax = 49.82
+ text = "lot"
+ intervals [163]:
+ xmin = 49.82
+ xmax = 50.2
+ text = "of"
+ intervals [164]:
+ xmin = 50.2
+ xmax = 50.29
+ text = ""
+ intervals [165]:
+ xmin = 50.29
+ xmax = 50.88
+ text = "enviable"
+ intervals [166]:
+ xmin = 50.88
+ xmax = 51.3
+ text = "moments"
+ intervals [167]:
+ xmin = 51.3
+ xmax = 51.37
+ text = "in"
+ intervals [168]:
+ xmin = 51.37
+ xmax = 51.53
+ text = "this"
+ intervals [169]:
+ xmin = 51.53
+ xmax = 51.77
+ text = "film"
+ intervals [170]:
+ xmin = 51.77
+ xmax = 52.01
+ text = "such"
+ intervals [171]:
+ xmin = 52.01
+ xmax = 52.2
+ text = "as"
+ intervals [172]:
+ xmin = 52.2
+ xmax = 52.3
+ text = "the"
+ intervals [173]:
+ xmin = 52.3
+ xmax = 52.57
+ text = "simple"
+ intervals [174]:
+ xmin = 52.57
+ xmax = 52.74
+ text = "love"
+ intervals [175]:
+ xmin = 52.74
+ xmax = 53.06
+ text = "between"
+ intervals [176]:
+ xmin = 53.06
+ xmax = 53.26
+ text = "high"
+ intervals [177]:
+ xmin = 53.26
+ xmax = 53.52
+ text = "school"
+ intervals [178]:
+ xmin = 53.52
+ xmax = 54.09
+ text = "students"
+ intervals [179]:
+ xmin = 54.09
+ xmax = 54.32
+ text = ""
+ intervals [180]:
+ xmin = 54.32
+ xmax = 54.56
+ text = "every"
+ intervals [181]:
+ xmin = 54.56
+ xmax = 54.93
+ text = "time"
+ intervals [182]:
+ xmin = 54.93
+ xmax = 54.96
+ text = ""
+ intervals [183]:
+ xmin = 54.96
+ xmax = 55.08
+ text = "i"
+ intervals [184]:
+ xmin = 55.08
+ xmax = 55.45
+ text = "watch"
+ intervals [185]:
+ xmin = 55.45
+ xmax = 55.68
+ text = "this"
+ intervals [186]:
+ xmin = 55.68
+ xmax = 55.89
+ text = "movie"
+ intervals [187]:
+ xmin = 55.89
+ xmax = 55.98
+ text = "it"
+ intervals [188]:
+ xmin = 55.98
+ xmax = 56.44
+ text = "reminds"
+ intervals [189]:
+ xmin = 56.44
+ xmax = 56.55
+ text = "me"
+ intervals [190]:
+ xmin = 56.55
+ xmax = 56.63
+ text = "of"
+ intervals [191]:
+ xmin = 56.63
+ xmax = 56.7
+ text = "a"
+ intervals [192]:
+ xmin = 56.7
+ xmax = 56.99
+ text = "time"
+ intervals [193]:
+ xmin = 56.99
+ xmax = 57.08
+ text = "that"
+ intervals [194]:
+ xmin = 57.08
+ xmax = 57.13
+ text = "i"
+ intervals [195]:
+ xmin = 57.13
+ xmax = 57.23
+ text = "was"
+ intervals [196]:
+ xmin = 57.23
+ xmax = 57.29
+ text = "in"
+ intervals [197]:
+ xmin = 57.29
+ xmax = 57.53
+ text = "high"
+ intervals [198]:
+ xmin = 57.53
+ xmax = 57.88
+ text = "school"
+ intervals [199]:
+ xmin = 57.88
+ xmax = 58.03
+ text = "and"
+ intervals [200]:
+ xmin = 58.03
+ xmax = 58.25
+ text = ""
+ intervals [201]:
+ xmin = 58.25
+ xmax = 58.4
+ text = "you"
+ intervals [202]:
+ xmin = 58.4
+ xmax = 58.55
+ text = "might"
+ intervals [203]:
+ xmin = 58.55
+ xmax = 59.1
+ text = "remember"
+ intervals [204]:
+ xmin = 59.1
+ xmax = 59.29
+ text = ""
+ intervals [205]:
+ xmin = 59.29
+ xmax = 59.44
+ text = "the"
+ intervals [206]:
+ xmin = 59.44
+ xmax = 59.83
+ text = "crush"
+ intervals [207]:
+ xmin = 59.83
+ xmax = 59.94
+ text = "you"
+ intervals [208]:
+ xmin = 59.94
+ xmax = 60.16
+ text = "had"
+ intervals [209]:
+ xmin = 60.16
+ xmax = 60.27
+ text = "in"
+ intervals [210]:
+ xmin = 60.27
+ xmax = 60.74
+ text = "school"
+ intervals [211]:
+ xmin = 60.74
+ xmax = 60.9
+ text = ""
+ intervals [212]:
+ xmin = 60.9
+ xmax = 61.12
+ text = "and"
+ intervals [213]:
+ xmin = 61.12
+ xmax = 61.24
+ text = "how"
+ intervals [214]:
+ xmin = 61.24
+ xmax = 61.36
+ text = "you"
+ intervals [215]:
+ xmin = 61.36
+ xmax = 61.48
+ text = "would"
+ intervals [216]:
+ xmin = 61.48
+ xmax = 61.7
+ text = "look"
+ intervals [217]:
+ xmin = 61.7
+ xmax = 61.77
+ text = "at"
+ intervals [218]:
+ xmin = 61.77
+ xmax = 62.16
+ text = "him"
+ intervals [219]:
+ xmin = 62.16
+ xmax = 62.37
+ text = ""
+ intervals [220]:
+ xmin = 62.37
+ xmax = 62.54
+ text = "while"
+ intervals [221]:
+ xmin = 62.54
+ xmax = 62.74
+ text = "he's"
+ intervals [222]:
+ xmin = 62.74
+ xmax = 63.02
+ text = "at"
+ intervals [223]:
+ xmin = 63.02
+ xmax = 63.61
+ text = "in"
+ intervals [224]:
+ xmin = 63.61
+ xmax = 64.04
+ text = "class"
+ intervals [225]:
+ xmin = 64.04
+ xmax = 64.38
+ text = "without"
+ intervals [226]:
+ xmin = 64.38
+ xmax = 64.83
+ text = "thinking"
+ intervals [227]:
+ xmin = 64.83
+ xmax = 64.95
+ text = "or"
+ intervals [228]:
+ xmin = 64.95
+ xmax = 64.98
+ text = ""
+ intervals [229]:
+ xmin = 64.98
+ xmax = 65.27
+ text = "wanting"
+ intervals [230]:
+ xmin = 65.27
+ xmax = 65.36
+ text = "to"
+ intervals [231]:
+ xmin = 65.36
+ xmax = 65.54
+ text = "go"
+ intervals [232]:
+ xmin = 65.54
+ xmax = 65.95
+ text = "places"
+ intervals [233]:
+ xmin = 65.95
+ xmax = 66.12
+ text = "with"
+ intervals [234]:
+ xmin = 66.12
+ xmax = 66.38
+ text = "him"
+ intervals [235]:
+ xmin = 66.38
+ xmax = 67
+ text = ""
+ item [2]:
+ class = "IntervalTier"
+ name = "phones"
+ xmin = 0.0
+ xmax = 67
+ intervals: size = 721
+ intervals [1]:
+ xmin = 0.0
+ xmax = 0.53
+ text = ""
+ intervals [2]:
+ xmin = 0.53
+ xmax = 0.75
+ text = "M"
+ intervals [3]:
+ xmin = 0.75
+ xmax = 0.93
+ text = "AY1"
+ intervals [4]:
+ xmin = 0.93
+ xmax = 1.06
+ text = "F"
+ intervals [5]:
+ xmin = 1.06
+ xmax = 1.16
+ text = "EY1"
+ intervals [6]:
+ xmin = 1.16
+ xmax = 1.23
+ text = "V"
+ intervals [7]:
+ xmin = 1.23
+ xmax = 1.26
+ text = "ER0"
+ intervals [8]:
+ xmin = 1.26
+ xmax = 1.31
+ text = "IH0"
+ intervals [9]:
+ xmin = 1.31
+ xmax = 1.34
+ text = "T"
+ intervals [10]:
+ xmin = 1.34
+ xmax = 1.42
+ text = "K"
+ intervals [11]:
+ xmin = 1.42
+ xmax = 1.51
+ text = "AY1"
+ intervals [12]:
+ xmin = 1.51
+ xmax = 1.54
+ text = "N"
+ intervals [13]:
+ xmin = 1.54
+ xmax = 1.57
+ text = "D"
+ intervals [14]:
+ xmin = 1.57
+ xmax = 1.61
+ text = "AH0"
+ intervals [15]:
+ xmin = 1.61
+ xmax = 1.65
+ text = "V"
+ intervals [16]:
+ xmin = 1.65
+ xmax = 1.74
+ text = "M"
+ intervals [17]:
+ xmin = 1.74
+ xmax = 1.8
+ text = "UW1"
+ intervals [18]:
+ xmin = 1.8
+ xmax = 1.9
+ text = "V"
+ intervals [19]:
+ xmin = 1.9
+ xmax = 2.01
+ text = "IY0"
+ intervals [20]:
+ xmin = 2.01
+ xmax = 2.2
+ text = "Z"
+ intervals [21]:
+ xmin = 2.2
+ xmax = 2.35
+ text = "AA1"
+ intervals [22]:
+ xmin = 2.35
+ xmax = 2.45
+ text = "R"
+ intervals [23]:
+ xmin = 2.45
+ xmax = 2.55
+ text = "R"
+ intervals [24]:
+ xmin = 2.55
+ xmax = 2.6
+ text = "OW0"
+ intervals [25]:
+ xmin = 2.6
+ xmax = 2.81
+ text = "M"
+ intervals [26]:
+ xmin = 2.81
+ xmax = 2.93
+ text = "AE1"
+ intervals [27]:
+ xmin = 2.93
+ xmax = 2.99
+ text = "N"
+ intervals [28]:
+ xmin = 2.99
+ xmax = 3.06
+ text = "T"
+ intervals [29]:
+ xmin = 3.06
+ xmax = 3.13
+ text = "IH0"
+ intervals [30]:
+ xmin = 3.13
+ xmax = 3.2
+ text = "K"
+ intervals [31]:
+ xmin = 3.2
+ xmax = 3.28
+ text = "M"
+ intervals [32]:
+ xmin = 3.28
+ xmax = 3.38
+ text = "UW1"
+ intervals [33]:
+ xmin = 3.38
+ xmax = 3.42
+ text = "V"
+ intervals [34]:
+ xmin = 3.42
+ xmax = 3.55
+ text = "IY0"
+ intervals [35]:
+ xmin = 3.55
+ xmax = 3.72
+ text = "Z"
+ intervals [36]:
+ xmin = 3.72
+ xmax = 3.75
+ text = ""
+ intervals [37]:
+ xmin = 3.75
+ xmax = 3.92
+ text = "S"
+ intervals [38]:
+ xmin = 3.92
+ xmax = 3.99
+ text = "AH1"
+ intervals [39]:
+ xmin = 3.99
+ xmax = 4.1
+ text = "CH"
+ intervals [40]:
+ xmin = 4.1
+ xmax = 4.22
+ text = "EH1"
+ intervals [41]:
+ xmin = 4.22
+ xmax = 4.33
+ text = "Z"
+ intervals [42]:
+ xmin = 4.33
+ xmax = 4.47
+ text = "T"
+ intervals [43]:
+ xmin = 4.47
+ xmax = 4.58
+ text = "AY0"
+ intervals [44]:
+ xmin = 4.58
+ xmax = 4.77
+ text = "T"
+ intervals [45]:
+ xmin = 4.77
+ xmax = 4.88
+ text = "AE1"
+ intervals [46]:
+ xmin = 4.88
+ xmax = 4.94
+ text = "N"
+ intervals [47]:
+ xmin = 4.94
+ xmax = 5.04
+ text = "IH0"
+ intervals [48]:
+ xmin = 5.04
+ xmax = 5.23
+ text = "K"
+ intervals [49]:
+ xmin = 5.23
+ xmax = 5.78
+ text = ""
+ intervals [50]:
+ xmin = 5.78
+ xmax = 5.95
+ text = "IH1"
+ intervals [51]:
+ xmin = 5.95
+ xmax = 6.05
+ text = "T"
+ intervals [52]:
+ xmin = 6.05
+ xmax = 6.19
+ text = "S"
+ intervals [53]:
+ xmin = 6.19
+ xmax = 6.46
+ text = "AH0"
+ intervals [54]:
+ xmin = 6.46
+ xmax = 6.49
+ text = ""
+ intervals [55]:
+ xmin = 6.49
+ xmax = 6.55
+ text = "F"
+ intervals [56]:
+ xmin = 6.55
+ xmax = 6.6
+ text = "AE0"
+ intervals [57]:
+ xmin = 6.6
+ xmax = 6.66
+ text = "N"
+ intervals [58]:
+ xmin = 6.66
+ xmax = 6.79
+ text = "T"
+ intervals [59]:
+ xmin = 6.79
+ xmax = 6.92
+ text = "AE1"
+ intervals [60]:
+ xmin = 6.92
+ xmax = 6.99
+ text = "S"
+ intervals [61]:
+ xmin = 6.99
+ xmax = 7.03
+ text = "T"
+ intervals [62]:
+ xmin = 7.03
+ xmax = 7.08
+ text = "IH0"
+ intervals [63]:
+ xmin = 7.08
+ xmax = 7.13
+ text = "K"
+ intervals [64]:
+ xmin = 7.13
+ xmax = 7.21
+ text = "F"
+ intervals [65]:
+ xmin = 7.21
+ xmax = 7.31
+ text = "IH1"
+ intervals [66]:
+ xmin = 7.31
+ xmax = 7.51
+ text = "L"
+ intervals [67]:
+ xmin = 7.51
+ xmax = 7.56
+ text = "M"
+ intervals [68]:
+ xmin = 7.56
+ xmax = 7.71
+ text = "IH1"
+ intervals [69]:
+ xmin = 7.71
+ xmax = 7.77
+ text = "T"
+ intervals [70]:
+ xmin = 7.77
+ xmax = 7.86
+ text = "K"
+ intervals [71]:
+ xmin = 7.86
+ xmax = 7.96
+ text = "AE1"
+ intervals [72]:
+ xmin = 7.96
+ xmax = 8.02
+ text = "P"
+ intervals [73]:
+ xmin = 8.02
+ xmax = 8.1
+ text = "CH"
+ intervals [74]:
+ xmin = 8.1
+ xmax = 8.16
+ text = "ER0"
+ intervals [75]:
+ xmin = 8.16
+ xmax = 8.28
+ text = "D"
+ intervals [76]:
+ xmin = 8.28
+ xmax = 8.4
+ text = "M"
+ intervals [77]:
+ xmin = 8.4
+ xmax = 8.46
+ text = "EH1"
+ intervals [78]:
+ xmin = 8.46
+ xmax = 8.53
+ text = "N"
+ intervals [79]:
+ xmin = 8.53
+ xmax = 8.73
+ text = "IY0"
+ intervals [80]:
+ xmin = 8.73
+ xmax = 8.81
+ text = "Y"
+ intervals [81]:
+ xmin = 8.81
+ xmax = 8.99
+ text = "AH1"
+ intervals [82]:
+ xmin = 8.99
+ xmax = 9.1
+ text = "NG"
+ intervals [83]:
+ xmin = 9.1
+ xmax = 9.18
+ text = "P"
+ intervals [84]:
+ xmin = 9.18
+ xmax = 9.26
+ text = "IY1"
+ intervals [85]:
+ xmin = 9.26
+ xmax = 9.31
+ text = "P"
+ intervals [86]:
+ xmin = 9.31
+ xmax = 9.34
+ text = "AH0"
+ intervals [87]:
+ xmin = 9.34
+ xmax = 9.39
+ text = "L"
+ intervals [88]:
+ xmin = 9.39
+ xmax = 9.44
+ text = "Z"
+ intervals [89]:
+ xmin = 9.44
+ xmax = 9.5
+ text = "HH"
+ intervals [90]:
+ xmin = 9.5
+ xmax = 9.57
+ text = "AA1"
+ intervals [91]:
+ xmin = 9.57
+ xmax = 9.68
+ text = "R"
+ intervals [92]:
+ xmin = 9.68
+ xmax = 9.73
+ text = "T"
+ intervals [93]:
+ xmin = 9.73
+ xmax = 9.79
+ text = "S"
+ intervals [94]:
+ xmin = 9.79
+ xmax = 9.88
+ text = "W"
+ intervals [95]:
+ xmin = 9.88
+ xmax = 9.94
+ text = "IH1"
+ intervals [96]:
+ xmin = 9.94
+ xmax = 10.02
+ text = "DH"
+ intervals [97]:
+ xmin = 10.02
+ xmax = 10.1
+ text = "IH0"
+ intervals [98]:
+ xmin = 10.1
+ xmax = 10.13
+ text = "T"
+ intervals [99]:
+ xmin = 10.13
+ xmax = 10.17
+ text = "S"
+ intervals [100]:
+ xmin = 10.17
+ xmax = 10.28
+ text = "AH0"
+ intervals [101]:
+ xmin = 10.28
+ xmax = 10.36
+ text = "M"
+ intervals [102]:
+ xmin = 10.36
+ xmax = 10.47
+ text = "EY1"
+ intervals [103]:
+ xmin = 10.47
+ xmax = 10.53
+ text = "Z"
+ intervals [104]:
+ xmin = 10.53
+ xmax = 10.59
+ text = "IH0"
+ intervals [105]:
+ xmin = 10.59
+ xmax = 10.65
+ text = "NG"
+ intervals [106]:
+ xmin = 10.65
+ xmax = 10.7
+ text = "M"
+ intervals [107]:
+ xmin = 10.7
+ xmax = 10.78
+ text = "Y"
+ intervals [108]:
+ xmin = 10.78
+ xmax = 10.81
+ text = "UW1"
+ intervals [109]:
+ xmin = 10.81
+ xmax = 10.9
+ text = "Z"
+ intervals [110]:
+ xmin = 10.9
+ xmax = 10.98
+ text = "IH0"
+ intervals [111]:
+ xmin = 10.98
+ xmax = 11.12
+ text = "K"
+ intervals [112]:
+ xmin = 11.12
+ xmax = 11.21
+ text = "AE1"
+ intervals [113]:
+ xmin = 11.21
+ xmax = 11.27
+ text = "N"
+ intervals [114]:
+ xmin = 11.27
+ xmax = 11.36
+ text = "D"
+ intervals [115]:
+ xmin = 11.36
+ xmax = 11.47
+ text = "S"
+ intervals [116]:
+ xmin = 11.47
+ xmax = 11.52
+ text = "EH2"
+ intervals [117]:
+ xmin = 11.52
+ xmax = 11.59
+ text = "N"
+ intervals [118]:
+ xmin = 11.59
+ xmax = 11.64
+ text = "T"
+ intervals [119]:
+ xmin = 11.64
+ xmax = 11.69
+ text = "AH0"
+ intervals [120]:
+ xmin = 11.69
+ xmax = 11.74
+ text = "M"
+ intervals [121]:
+ xmin = 11.74
+ xmax = 11.78
+ text = "EH1"
+ intervals [122]:
+ xmin = 11.78
+ xmax = 11.81
+ text = "N"
+ intervals [123]:
+ xmin = 11.81
+ xmax = 11.85
+ text = "T"
+ intervals [124]:
+ xmin = 11.85
+ xmax = 11.88
+ text = "AH0"
+ intervals [125]:
+ xmin = 11.88
+ xmax = 11.92
+ text = "L"
+ intervals [126]:
+ xmin = 11.92
+ xmax = 11.99
+ text = "P"
+ intervals [127]:
+ xmin = 11.99
+ xmax = 12.04
+ text = "L"
+ intervals [128]:
+ xmin = 12.04
+ xmax = 12.23
+ text = "AA1"
+ intervals [129]:
+ xmin = 12.23
+ xmax = 12.31
+ text = "T"
+ intervals [130]:
+ xmin = 12.31
+ xmax = 12.47
+ text = "S"
+ intervals [131]:
+ xmin = 12.47
+ xmax = 12.84
+ text = ""
+ intervals [132]:
+ xmin = 12.84
+ xmax = 12.92
+ text = "W"
+ intervals [133]:
+ xmin = 12.92
+ xmax = 12.95
+ text = "EH1"
+ intervals [134]:
+ xmin = 12.95
+ xmax = 12.98
+ text = "N"
+ intervals [135]:
+ xmin = 12.98
+ xmax = 13.12
+ text = "AY1"
+ intervals [136]:
+ xmin = 13.12
+ xmax = 13.16
+ text = "TH"
+ intervals [137]:
+ xmin = 13.16
+ xmax = 13.22
+ text = "IH1"
+ intervals [138]:
+ xmin = 13.22
+ xmax = 13.25
+ text = "NG"
+ intervals [139]:
+ xmin = 13.25
+ xmax = 13.28
+ text = "K"
+ intervals [140]:
+ xmin = 13.28
+ xmax = 13.32
+ text = "AH0"
+ intervals [141]:
+ xmin = 13.32
+ xmax = 13.35
+ text = "V"
+ intervals [142]:
+ xmin = 13.35
+ xmax = 13.38
+ text = "DH"
+ intervals [143]:
+ xmin = 13.38
+ xmax = 13.42
+ text = "AH0"
+ intervals [144]:
+ xmin = 13.42
+ xmax = 13.46
+ text = "M"
+ intervals [145]:
+ xmin = 13.46
+ xmax = 13.52
+ text = "UW1"
+ intervals [146]:
+ xmin = 13.52
+ xmax = 13.58
+ text = "V"
+ intervals [147]:
+ xmin = 13.58
+ xmax = 13.62
+ text = "IY0"
+ intervals [148]:
+ xmin = 13.62
+ xmax = 13.69
+ text = "T"
+ intervals [149]:
+ xmin = 13.69
+ xmax = 13.79
+ text = "AY0"
+ intervals [150]:
+ xmin = 13.79
+ xmax = 13.89
+ text = "T"
+ intervals [151]:
+ xmin = 13.89
+ xmax = 13.96
+ text = "AE1"
+ intervals [152]:
+ xmin = 13.96
+ xmax = 14.02
+ text = "N"
+ intervals [153]:
+ xmin = 14.02
+ xmax = 14.17
+ text = "IH0"
+ intervals [154]:
+ xmin = 14.17
+ xmax = 14.2
+ text = "K"
+ intervals [155]:
+ xmin = 14.2
+ xmax = 14.23
+ text = ""
+ intervals [156]:
+ xmin = 14.23
+ xmax = 14.34
+ text = "DH"
+ intervals [157]:
+ xmin = 14.34
+ xmax = 14.42
+ text = "AH1"
+ intervals [158]:
+ xmin = 14.42
+ xmax = 14.61
+ text = "W"
+ intervals [159]:
+ xmin = 14.61
+ xmax = 14.85
+ text = "ER1"
+ intervals [160]:
+ xmin = 14.85
+ xmax = 14.92
+ text = "D"
+ intervals [161]:
+ xmin = 14.92
+ xmax = 14.95
+ text = "DH"
+ intervals [162]:
+ xmin = 14.95
+ xmax = 15.02
+ text = "AH0"
+ intervals [163]:
+ xmin = 15.02
+ xmax = 15.06
+ text = "T"
+ intervals [164]:
+ xmin = 15.06
+ xmax = 15.13
+ text = "K"
+ intervals [165]:
+ xmin = 15.13
+ xmax = 15.19
+ text = "AH1"
+ intervals [166]:
+ xmin = 15.19
+ xmax = 15.24
+ text = "M"
+ intervals [167]:
+ xmin = 15.24
+ xmax = 15.3
+ text = "Z"
+ intervals [168]:
+ xmin = 15.3
+ xmax = 15.35
+ text = "T"
+ intervals [169]:
+ xmin = 15.35
+ xmax = 15.39
+ text = "AH0"
+ intervals [170]:
+ xmin = 15.39
+ xmax = 15.44
+ text = "M"
+ intervals [171]:
+ xmin = 15.44
+ xmax = 15.5
+ text = "AY1"
+ intervals [172]:
+ xmin = 15.5
+ xmax = 15.61
+ text = "M"
+ intervals [173]:
+ xmin = 15.61
+ xmax = 15.85
+ text = "AY1"
+ intervals [174]:
+ xmin = 15.85
+ xmax = 15.88
+ text = "N"
+ intervals [175]:
+ xmin = 15.88
+ xmax = 15.91
+ text = "D"
+ intervals [176]:
+ xmin = 15.91
+ xmax = 15.94
+ text = "M"
+ intervals [177]:
+ xmin = 15.94
+ xmax = 15.97
+ text = "AY1"
+ intervals [178]:
+ xmin = 15.97
+ xmax = 16.0
+ text = "N"
+ intervals [179]:
+ xmin = 16.0
+ xmax = 16.06
+ text = "D"
+ intervals [180]:
+ xmin = 16.06
+ xmax = 16.41
+ text = ""
+ intervals [181]:
+ xmin = 16.41
+ xmax = 16.54
+ text = "T"
+ intervals [182]:
+ xmin = 16.54
+ xmax = 16.6
+ text = "IH0"
+ intervals [183]:
+ xmin = 16.6
+ xmax = 16.69
+ text = "M"
+ intervals [184]:
+ xmin = 16.69
+ xmax = 16.85
+ text = "AY1"
+ intervals [185]:
+ xmin = 16.85
+ xmax = 16.95
+ text = "Z"
+ intervals [186]:
+ xmin = 16.95
+ xmax = 16.99
+ text = "IH0"
+ intervals [187]:
+ xmin = 16.99
+ xmax = 17.07
+ text = "Z"
+ intervals [188]:
+ xmin = 17.07
+ xmax = 17.11
+ text = "DH"
+ intervals [189]:
+ xmin = 17.11
+ xmax = 17.15
+ text = "AH1"
+ intervals [190]:
+ xmin = 17.15
+ xmax = 17.24
+ text = "HH"
+ intervals [191]:
+ xmin = 17.24
+ xmax = 17.32
+ text = "OW1"
+ intervals [192]:
+ xmin = 17.32
+ xmax = 17.39
+ text = "L"
+ intervals [193]:
+ xmin = 17.39
+ xmax = 17.48
+ text = "F"
+ intervals [194]:
+ xmin = 17.48
+ xmax = 17.57
+ text = "IH1"
+ intervals [195]:
+ xmin = 17.57
+ xmax = 17.68
+ text = "L"
+ intervals [196]:
+ xmin = 17.68
+ xmax = 17.94
+ text = "M"
+ intervals [197]:
+ xmin = 17.94
+ xmax = 17.97
+ text = ""
+ intervals [198]:
+ xmin = 17.97
+ xmax = 18.06
+ text = "W"
+ intervals [199]:
+ xmin = 18.06
+ xmax = 18.12
+ text = "UH1"
+ intervals [200]:
+ xmin = 18.12
+ xmax = 18.18
+ text = "D"
+ intervals [201]:
+ xmin = 18.18
+ xmax = 18.24
+ text = "B"
+ intervals [202]:
+ xmin = 18.24
+ xmax = 18.62
+ text = "IY1"
+ intervals [203]:
+ xmin = 18.62
+ xmax = 19.09
+ text = ""
+ intervals [204]:
+ xmin = 19.09
+ xmax = 19.34
+ text = "L"
+ intervals [205]:
+ xmin = 19.34
+ xmax = 19.51
+ text = "AH1"
+ intervals [206]:
+ xmin = 19.51
+ xmax = 19.94
+ text = "V"
+ intervals [207]:
+ xmin = 19.94
+ xmax = 20.07
+ text = ""
+ intervals [208]:
+ xmin = 20.07
+ xmax = 20.18
+ text = "IH1"
+ intervals [209]:
+ xmin = 20.18
+ xmax = 20.24
+ text = "T"
+ intervals [210]:
+ xmin = 20.24
+ xmax = 20.27
+ text = "S"
+ intervals [211]:
+ xmin = 20.27
+ xmax = 20.36
+ text = "AH0"
+ intervals [212]:
+ xmin = 20.36
+ xmax = 20.59
+ text = "K"
+ intervals [213]:
+ xmin = 20.59
+ xmax = 20.74
+ text = "AY1"
+ intervals [214]:
+ xmin = 20.74
+ xmax = 20.79
+ text = "N"
+ intervals [215]:
+ xmin = 20.79
+ xmax = 20.83
+ text = "D"
+ intervals [216]:
+ xmin = 20.83
+ xmax = 20.87
+ text = "AH0"
+ intervals [217]:
+ xmin = 20.87
+ xmax = 20.98
+ text = "V"
+ intervals [218]:
+ xmin = 20.98
+ xmax = 21.04
+ text = "TH"
+ intervals [219]:
+ xmin = 21.04
+ xmax = 21.13
+ text = "IH1"
+ intervals [220]:
+ xmin = 21.13
+ xmax = 21.25
+ text = "NG"
+ intervals [221]:
+ xmin = 21.25
+ xmax = 21.31
+ text = "DH"
+ intervals [222]:
+ xmin = 21.31
+ xmax = 21.37
+ text = "AE1"
+ intervals [223]:
+ xmin = 21.37
+ xmax = 21.43
+ text = "T"
+ intervals [224]:
+ xmin = 21.43
+ xmax = 21.54
+ text = "M"
+ intervals [225]:
+ xmin = 21.54
+ xmax = 21.64
+ text = "EY1"
+ intervals [226]:
+ xmin = 21.64
+ xmax = 21.68
+ text = "K"
+ intervals [227]:
+ xmin = 21.68
+ xmax = 21.8
+ text = "S"
+ intervals [228]:
+ xmin = 21.8
+ xmax = 21.87
+ text = "Y"
+ intervals [229]:
+ xmin = 21.87
+ xmax = 22.28
+ text = "UW1"
+ intervals [230]:
+ xmin = 22.28
+ xmax = 22.31
+ text = ""
+ intervals [231]:
+ xmin = 22.31
+ xmax = 22.63
+ text = "M"
+ intervals [232]:
+ xmin = 22.63
+ xmax = 22.7
+ text = "EY1"
+ intervals [233]:
+ xmin = 22.7
+ xmax = 22.75
+ text = "K"
+ intervals [234]:
+ xmin = 22.75
+ xmax = 22.8
+ text = "S"
+ intervals [235]:
+ xmin = 22.8
+ xmax = 22.84
+ text = "DH"
+ intervals [236]:
+ xmin = 22.84
+ xmax = 22.91
+ text = "AH0"
+ intervals [237]:
+ xmin = 22.91
+ xmax = 23.0
+ text = "W"
+ intervals [238]:
+ xmin = 23.0
+ xmax = 23.08
+ text = "ER1"
+ intervals [239]:
+ xmin = 23.08
+ xmax = 23.18
+ text = "L"
+ intervals [240]:
+ xmin = 23.18
+ xmax = 23.21
+ text = "D"
+ intervals [241]:
+ xmin = 23.21
+ xmax = 23.27
+ text = "G"
+ intervals [242]:
+ xmin = 23.27
+ xmax = 23.38
+ text = "OW1"
+ intervals [243]:
+ xmin = 23.38
+ xmax = 23.48
+ text = "R"
+ intervals [244]:
+ xmin = 23.48
+ xmax = 23.68
+ text = "AW1"
+ intervals [245]:
+ xmin = 23.68
+ xmax = 23.75
+ text = "N"
+ intervals [246]:
+ xmin = 23.75
+ xmax = 23.87
+ text = "D"
+ intervals [247]:
+ xmin = 23.87
+ xmax = 24.08
+ text = ""
+ intervals [248]:
+ xmin = 24.08
+ xmax = 24.27
+ text = "W"
+ intervals [249]:
+ xmin = 24.27
+ xmax = 24.36
+ text = "AA1"
+ intervals [250]:
+ xmin = 24.36
+ xmax = 24.46
+ text = "CH"
+ intervals [251]:
+ xmin = 24.46
+ xmax = 24.54
+ text = "IH0"
+ intervals [252]:
+ xmin = 24.54
+ xmax = 24.6
+ text = "NG"
+ intervals [253]:
+ xmin = 24.6
+ xmax = 24.65
+ text = "DH"
+ intervals [254]:
+ xmin = 24.65
+ xmax = 24.72
+ text = "IY1"
+ intervals [255]:
+ xmin = 24.72
+ xmax = 24.8
+ text = "Z"
+ intervals [256]:
+ xmin = 24.8
+ xmax = 24.9
+ text = "K"
+ intervals [257]:
+ xmin = 24.9
+ xmax = 25.05
+ text = "AY1"
+ intervals [258]:
+ xmin = 25.05
+ xmax = 25.12
+ text = "N"
+ intervals [259]:
+ xmin = 25.12
+ xmax = 25.18
+ text = "Z"
+ intervals [260]:
+ xmin = 25.18
+ xmax = 25.21
+ text = "AH0"
+ intervals [261]:
+ xmin = 25.21
+ xmax = 25.29
+ text = "V"
+ intervals [262]:
+ xmin = 25.29
+ xmax = 25.36
+ text = "R"
+ intervals [263]:
+ xmin = 25.36
+ xmax = 25.39
+ text = "OW0"
+ intervals [264]:
+ xmin = 25.39
+ xmax = 25.5
+ text = "M"
+ intervals [265]:
+ xmin = 25.5
+ xmax = 25.56
+ text = "AE1"
+ intervals [266]:
+ xmin = 25.56
+ xmax = 25.6
+ text = "N"
+ intervals [267]:
+ xmin = 25.6
+ xmax = 25.65
+ text = "T"
+ intervals [268]:
+ xmin = 25.65
+ xmax = 25.75
+ text = "IH0"
+ intervals [269]:
+ xmin = 25.75
+ xmax = 25.83
+ text = "K"
+ intervals [270]:
+ xmin = 25.83
+ xmax = 25.9
+ text = "M"
+ intervals [271]:
+ xmin = 25.9
+ xmax = 25.99
+ text = "UW1"
+ intervals [272]:
+ xmin = 25.99
+ xmax = 26.06
+ text = "V"
+ intervals [273]:
+ xmin = 26.06
+ xmax = 26.14
+ text = "IY0"
+ intervals [274]:
+ xmin = 26.14
+ xmax = 26.23
+ text = "Z"
+ intervals [275]:
+ xmin = 26.23
+ xmax = 26.34
+ text = "IH1"
+ intervals [276]:
+ xmin = 26.34
+ xmax = 26.43
+ text = "Z"
+ intervals [277]:
+ xmin = 26.43
+ xmax = 26.64
+ text = "JH"
+ intervals [278]:
+ xmin = 26.64
+ xmax = 26.73
+ text = "IH0"
+ intervals [279]:
+ xmin = 26.73
+ xmax = 26.82
+ text = "S"
+ intervals [280]:
+ xmin = 26.82
+ xmax = 26.86
+ text = "T"
+ intervals [281]:
+ xmin = 26.86
+ xmax = 26.92
+ text = "L"
+ intervals [282]:
+ xmin = 26.92
+ xmax = 27.04
+ text = "AY1"
+ intervals [283]:
+ xmin = 27.04
+ xmax = 27.07
+ text = "K"
+ intervals [284]:
+ xmin = 27.07
+ xmax = 27.26
+ text = "R"
+ intervals [285]:
+ xmin = 27.26
+ xmax = 27.33
+ text = "IY1"
+ intervals [286]:
+ xmin = 27.33
+ xmax = 27.36
+ text = "D"
+ intervals [287]:
+ xmin = 27.36
+ xmax = 27.43
+ text = "IH0"
+ intervals [288]:
+ xmin = 27.43
+ xmax = 27.49
+ text = "NG"
+ intervals [289]:
+ xmin = 27.49
+ xmax = 27.56
+ text = "AH0"
+ intervals [290]:
+ xmin = 27.56
+ xmax = 27.63
+ text = "B"
+ intervals [291]:
+ xmin = 27.63
+ xmax = 27.77
+ text = "UH1"
+ intervals [292]:
+ xmin = 27.77
+ xmax = 27.98
+ text = "K"
+ intervals [293]:
+ xmin = 27.98
+ xmax = 28.11
+ text = ""
+ intervals [294]:
+ xmin = 28.11
+ xmax = 28.21
+ text = "DH"
+ intervals [295]:
+ xmin = 28.21
+ xmax = 28.25
+ text = "AH0"
+ intervals [296]:
+ xmin = 28.25
+ xmax = 28.29
+ text = "T"
+ intervals [297]:
+ xmin = 28.29
+ xmax = 28.38
+ text = "T"
+ intervals [298]:
+ xmin = 28.38
+ xmax = 28.44
+ text = "IY1"
+ intervals [299]:
+ xmin = 28.44
+ xmax = 28.52
+ text = "CH"
+ intervals [300]:
+ xmin = 28.52
+ xmax = 28.57
+ text = "IH0"
+ intervals [301]:
+ xmin = 28.57
+ xmax = 28.65
+ text = "Z"
+ intervals [302]:
+ xmin = 28.65
+ xmax = 28.69
+ text = "M"
+ intervals [303]:
+ xmin = 28.69
+ xmax = 28.78
+ text = "IY1"
+ intervals [304]:
+ xmin = 28.78
+ xmax = 28.91
+ text = "HH"
+ intervals [305]:
+ xmin = 28.91
+ xmax = 28.99
+ text = "AW1"
+ intervals [306]:
+ xmin = 28.99
+ xmax = 29.08
+ text = "T"
+ intervals [307]:
+ xmin = 29.08
+ xmax = 29.19
+ text = "AH0"
+ intervals [308]:
+ xmin = 29.19
+ xmax = 29.27
+ text = "L"
+ intervals [309]:
+ xmin = 29.27
+ xmax = 29.52
+ text = "AH1"
+ intervals [310]:
+ xmin = 29.52
+ xmax = 29.61
+ text = "V"
+ intervals [311]:
+ xmin = 29.61
+ xmax = 29.78
+ text = "AE1"
+ intervals [312]:
+ xmin = 29.78
+ xmax = 29.86
+ text = "N"
+ intervals [313]:
+ xmin = 29.86
+ xmax = 29.93
+ text = "D"
+ intervals [314]:
+ xmin = 29.93
+ xmax = 29.97
+ text = "B"
+ intervals [315]:
+ xmin = 29.97
+ xmax = 30.09
+ text = "IY1"
+ intervals [316]:
+ xmin = 30.09
+ xmax = 30.21
+ text = "L"
+ intervals [317]:
+ xmin = 30.21
+ xmax = 30.33
+ text = "AH1"
+ intervals [318]:
+ xmin = 30.33
+ xmax = 30.43
+ text = "V"
+ intervals [319]:
+ xmin = 30.43
+ xmax = 30.53
+ text = "D"
+ intervals [320]:
+ xmin = 30.53
+ xmax = 30.96
+ text = ""
+ intervals [321]:
+ xmin = 30.96
+ xmax = 31.09
+ text = "M"
+ intervals [322]:
+ xmin = 31.09
+ xmax = 31.14
+ text = "AO0"
+ intervals [323]:
+ xmin = 31.14
+ xmax = 31.22
+ text = "R"
+ intervals [324]:
+ xmin = 31.22
+ xmax = 31.5
+ text = "OW1"
+ intervals [325]:
+ xmin = 31.5
+ xmax = 31.53
+ text = "V"
+ intervals [326]:
+ xmin = 31.53
+ xmax = 31.68
+ text = "ER0"
+ intervals [327]:
+ xmin = 31.68
+ xmax = 31.74
+ text = "W"
+ intervals [328]:
+ xmin = 31.74
+ xmax = 31.81
+ text = "IY1"
+ intervals [329]:
+ xmin = 31.81
+ xmax = 32.01
+ text = ""
+ intervals [330]:
+ xmin = 32.01
+ xmax = 32.13
+ text = "K"
+ intervals [331]:
+ xmin = 32.13
+ xmax = 32.39
+ text = "AE1"
+ intervals [332]:
+ xmin = 32.39
+ xmax = 32.51
+ text = "N"
+ intervals [333]:
+ xmin = 32.51
+ xmax = 32.56
+ text = ""
+ intervals [334]:
+ xmin = 32.56
+ xmax = 32.65
+ text = "L"
+ intervals [335]:
+ xmin = 32.65
+ xmax = 32.68
+ text = "ER1"
+ intervals [336]:
+ xmin = 32.68
+ xmax = 32.72
+ text = "N"
+ intervals [337]:
+ xmin = 32.72
+ xmax = 33.02
+ text = "W"
+ intervals [338]:
+ xmin = 33.02
+ xmax = 33.09
+ text = "IY1"
+ intervals [339]:
+ xmin = 33.09
+ xmax = 33.16
+ text = "K"
+ intervals [340]:
+ xmin = 33.16
+ xmax = 33.21
+ text = "AH0"
+ intervals [341]:
+ xmin = 33.21
+ xmax = 33.25
+ text = "N"
+ intervals [342]:
+ xmin = 33.25
+ xmax = 33.4
+ text = "L"
+ intervals [343]:
+ xmin = 33.4
+ xmax = 33.58
+ text = "ER1"
+ intervals [344]:
+ xmin = 33.58
+ xmax = 34.05
+ text = "N"
+ intervals [345]:
+ xmin = 34.05
+ xmax = 34.2
+ text = ""
+ intervals [346]:
+ xmin = 34.2
+ xmax = 34.91
+ text = "M"
+ intervals [347]:
+ xmin = 34.91
+ xmax = 35.05
+ text = "AO1"
+ intervals [348]:
+ xmin = 35.05
+ xmax = 35.12
+ text = "R"
+ intervals [349]:
+ xmin = 35.12
+ xmax = 35.23
+ text = "F"
+ intervals [350]:
+ xmin = 35.23
+ xmax = 35.32
+ text = "R"
+ intervals [351]:
+ xmin = 35.32
+ xmax = 35.36
+ text = "AH1"
+ intervals [352]:
+ xmin = 35.36
+ xmax = 35.44
+ text = "M"
+ intervals [353]:
+ xmin = 35.44
+ xmax = 35.56
+ text = "IH0"
+ intervals [354]:
+ xmin = 35.56
+ xmax = 35.66
+ text = "T"
+ intervals [355]:
+ xmin = 35.66
+ xmax = 35.76
+ text = "S"
+ intervals [356]:
+ xmin = 35.76
+ xmax = 35.84
+ text = "AH1"
+ intervals [357]:
+ xmin = 35.84
+ xmax = 35.98
+ text = "CH"
+ intervals [358]:
+ xmin = 35.98
+ xmax = 36.06
+ text = "TH"
+ intervals [359]:
+ xmin = 36.06
+ xmax = 36.16
+ text = "IH1"
+ intervals [360]:
+ xmin = 36.16
+ xmax = 36.24
+ text = "NG"
+ intervals [361]:
+ xmin = 36.24
+ xmax = 36.35
+ text = "Z"
+ intervals [362]:
+ xmin = 36.35
+ xmax = 36.56
+ text = "AE1"
+ intervals [363]:
+ xmin = 36.56
+ xmax = 36.69
+ text = "Z"
+ intervals [364]:
+ xmin = 36.69
+ xmax = 36.89
+ text = ""
+ intervals [365]:
+ xmin = 36.89
+ xmax = 37.03
+ text = "L"
+ intervals [366]:
+ xmin = 37.03
+ xmax = 37.16
+ text = "OY1"
+ intervals [367]:
+ xmin = 37.16
+ xmax = 37.23
+ text = "AH0"
+ intervals [368]:
+ xmin = 37.23
+ xmax = 37.32
+ text = "L"
+ intervals [369]:
+ xmin = 37.32
+ xmax = 37.4
+ text = "T"
+ intervals [370]:
+ xmin = 37.4
+ xmax = 37.59
+ text = "IY0"
+ intervals [371]:
+ xmin = 37.59
+ xmax = 37.68
+ text = "AE1"
+ intervals [372]:
+ xmin = 37.68
+ xmax = 37.73
+ text = "N"
+ intervals [373]:
+ xmin = 37.73
+ xmax = 37.76
+ text = "D"
+ intervals [374]:
+ xmin = 37.76
+ xmax = 37.8
+ text = "W"
+ intervals [375]:
+ xmin = 37.8
+ xmax = 37.83
+ text = "AH1"
+ intervals [376]:
+ xmin = 37.83
+ xmax = 37.88
+ text = "T"
+ intervals [377]:
+ xmin = 37.88
+ xmax = 37.94
+ text = "W"
+ intervals [378]:
+ xmin = 37.94
+ xmax = 37.99
+ text = "IY1"
+ intervals [379]:
+ xmin = 37.99
+ xmax = 38.15
+ text = "T"
+ intervals [380]:
+ xmin = 38.15
+ xmax = 38.21
+ text = "R"
+ intervals [381]:
+ xmin = 38.21
+ xmax = 38.26
+ text = "EH1"
+ intervals [382]:
+ xmin = 38.26
+ xmax = 38.38
+ text = "ZH"
+ intervals [383]:
+ xmin = 38.38
+ xmax = 38.47
+ text = "ER0"
+ intervals [384]:
+ xmin = 38.47
+ xmax = 38.53
+ text = "IH0"
+ intervals [385]:
+ xmin = 38.53
+ xmax = 38.58
+ text = "N"
+ intervals [386]:
+ xmin = 38.58
+ xmax = 38.64
+ text = "AA1"
+ intervals [387]:
+ xmin = 38.64
+ xmax = 38.71
+ text = "R"
+ intervals [388]:
+ xmin = 38.71
+ xmax = 38.77
+ text = "L"
+ intervals [389]:
+ xmin = 38.77
+ xmax = 38.96
+ text = "AY1"
+ intervals [390]:
+ xmin = 38.96
+ xmax = 39.02
+ text = "V"
+ intervals [391]:
+ xmin = 39.02
+ xmax = 39.11
+ text = "Z"
+ intervals [392]:
+ xmin = 39.11
+ xmax = 39.4
+ text = ""
+ intervals [393]:
+ xmin = 39.4
+ xmax = 39.57
+ text = "AH0"
+ intervals [394]:
+ xmin = 39.57
+ xmax = 39.63
+ text = "N"
+ intervals [395]:
+ xmin = 39.63
+ xmax = 39.69
+ text = "AH1"
+ intervals [396]:
+ xmin = 39.69
+ xmax = 39.73
+ text = "DH"
+ intervals [397]:
+ xmin = 39.73
+ xmax = 39.8
+ text = "ER0"
+ intervals [398]:
+ xmin = 39.8
+ xmax = 39.85
+ text = "M"
+ intervals [399]:
+ xmin = 39.85
+ xmax = 39.98
+ text = "UW1"
+ intervals [400]:
+ xmin = 39.98
+ xmax = 40.06
+ text = "V"
+ intervals [401]:
+ xmin = 40.06
+ xmax = 40.13
+ text = "IY0"
+ intervals [402]:
+ xmin = 40.13
+ xmax = 40.25
+ text = "AH0"
+ intervals [403]:
+ xmin = 40.25
+ xmax = 40.31
+ text = "B"
+ intervals [404]:
+ xmin = 40.31
+ xmax = 40.46
+ text = "AW1"
+ intervals [405]:
+ xmin = 40.46
+ xmax = 40.51
+ text = "T"
+ intervals [406]:
+ xmin = 40.51
+ xmax = 40.62
+ text = "L"
+ intervals [407]:
+ xmin = 40.62
+ xmax = 40.76
+ text = "AH1"
+ intervals [408]:
+ xmin = 40.76
+ xmax = 40.83
+ text = "V"
+ intervals [409]:
+ xmin = 40.83
+ xmax = 41.01
+ text = "IH1"
+ intervals [410]:
+ xmin = 41.01
+ xmax = 41.08
+ text = "Z"
+ intervals [411]:
+ xmin = 41.08
+ xmax = 41.11
+ text = "DH"
+ intervals [412]:
+ xmin = 41.11
+ xmax = 41.24
+ text = "AH0"
+ intervals [413]:
+ xmin = 41.24
+ xmax = 41.3
+ text = ""
+ intervals [414]:
+ xmin = 41.3
+ xmax = 41.47
+ text = "S"
+ intervals [415]:
+ xmin = 41.47
+ xmax = 41.53
+ text = "IY1"
+ intervals [416]:
+ xmin = 41.53
+ xmax = 41.61
+ text = "K"
+ intervals [417]:
+ xmin = 41.61
+ xmax = 41.64
+ text = "R"
+ intervals [418]:
+ xmin = 41.64
+ xmax = 41.75
+ text = "IH0"
+ intervals [419]:
+ xmin = 41.75
+ xmax = 41.9
+ text = "T"
+ intervals [420]:
+ xmin = 41.9
+ xmax = 42.13
+ text = ""
+ intervals [421]:
+ xmin = 42.13
+ xmax = 42.35
+ text = "DH"
+ intervals [422]:
+ xmin = 42.35
+ xmax = 42.47
+ text = "AH1"
+ intervals [423]:
+ xmin = 42.47
+ xmax = 42.56
+ text = "M"
+ intervals [424]:
+ xmin = 42.56
+ xmax = 42.62
+ text = "UW1"
+ intervals [425]:
+ xmin = 42.62
+ xmax = 42.71
+ text = "V"
+ intervals [426]:
+ xmin = 42.71
+ xmax = 43.01
+ text = "IY0"
+ intervals [427]:
+ xmin = 43.01
+ xmax = 43.19
+ text = "S"
+ intervals [428]:
+ xmin = 43.19
+ xmax = 43.26
+ text = "IY1"
+ intervals [429]:
+ xmin = 43.26
+ xmax = 43.31
+ text = "K"
+ intervals [430]:
+ xmin = 43.31
+ xmax = 43.37
+ text = "R"
+ intervals [431]:
+ xmin = 43.37
+ xmax = 43.53
+ text = "IH0"
+ intervals [432]:
+ xmin = 43.53
+ xmax = 43.58
+ text = "T"
+ intervals [433]:
+ xmin = 43.58
+ xmax = 43.65
+ text = "IH1"
+ intervals [434]:
+ xmin = 43.65
+ xmax = 43.71
+ text = "Z"
+ intervals [435]:
+ xmin = 43.71
+ xmax = 43.77
+ text = "AH0"
+ intervals [436]:
+ xmin = 43.77
+ xmax = 43.84
+ text = "B"
+ intervals [437]:
+ xmin = 43.84
+ xmax = 44.03
+ text = "AW1"
+ intervals [438]:
+ xmin = 44.03
+ xmax = 44.1
+ text = "T"
+ intervals [439]:
+ xmin = 44.1
+ xmax = 44.15
+ text = "AH0"
+ intervals [440]:
+ xmin = 44.15
+ xmax = 44.33
+ text = "S"
+ intervals [441]:
+ xmin = 44.33
+ xmax = 44.4
+ text = "T"
+ intervals [442]:
+ xmin = 44.4
+ xmax = 44.51
+ text = "AO1"
+ intervals [443]:
+ xmin = 44.51
+ xmax = 44.65
+ text = "R"
+ intervals [444]:
+ xmin = 44.65
+ xmax = 44.88
+ text = "IY0"
+ intervals [445]:
+ xmin = 44.88
+ xmax = 44.95
+ text = ""
+ intervals [446]:
+ xmin = 44.95
+ xmax = 45.09
+ text = "AH0"
+ intervals [447]:
+ xmin = 45.09
+ xmax = 45.14
+ text = "V"
+ intervals [448]:
+ xmin = 45.14
+ xmax = 45.21
+ text = "AH0"
+ intervals [449]:
+ xmin = 45.21
+ xmax = 45.27
+ text = "M"
+ intervals [450]:
+ xmin = 45.27
+ xmax = 45.31
+ text = "Y"
+ intervals [451]:
+ xmin = 45.31
+ xmax = 45.34
+ text = "UW1"
+ intervals [452]:
+ xmin = 45.34
+ xmax = 45.41
+ text = "Z"
+ intervals [453]:
+ xmin = 45.41
+ xmax = 45.45
+ text = "IH0"
+ intervals [454]:
+ xmin = 45.45
+ xmax = 45.48
+ text = "K"
+ intervals [455]:
+ xmin = 45.48
+ xmax = 45.51
+ text = "AH0"
+ intervals [456]:
+ xmin = 45.51
+ xmax = 45.56
+ text = "L"
+ intervals [457]:
+ xmin = 45.56
+ xmax = 45.62
+ text = "P"
+ intervals [458]:
+ xmin = 45.62
+ xmax = 45.69
+ text = "R"
+ intervals [459]:
+ xmin = 45.69
+ xmax = 45.81
+ text = "AA1"
+ intervals [460]:
+ xmin = 45.81
+ xmax = 45.84
+ text = "D"
+ intervals [461]:
+ xmin = 45.84
+ xmax = 45.87
+ text = "AH0"
+ intervals [462]:
+ xmin = 45.87
+ xmax = 45.91
+ text = "JH"
+ intervals [463]:
+ xmin = 45.91
+ xmax = 45.96
+ text = "IY0"
+ intervals [464]:
+ xmin = 45.96
+ xmax = 45.99
+ text = "D"
+ intervals [465]:
+ xmin = 45.99
+ xmax = 46.04
+ text = "UW1"
+ intervals [466]:
+ xmin = 46.04
+ xmax = 46.09
+ text = "DH"
+ intervals [467]:
+ xmin = 46.09
+ xmax = 46.12
+ text = "AH0"
+ intervals [468]:
+ xmin = 46.12
+ xmax = 46.17
+ text = "T"
+ intervals [469]:
+ xmin = 46.17
+ xmax = 46.24
+ text = "F"
+ intervals [470]:
+ xmin = 46.24
+ xmax = 46.29
+ text = "AO1"
+ intervals [471]:
+ xmin = 46.29
+ xmax = 46.36
+ text = "L"
+ intervals [472]:
+ xmin = 46.36
+ xmax = 46.42
+ text = "Z"
+ intervals [473]:
+ xmin = 46.42
+ xmax = 46.46
+ text = "IH0"
+ intervals [474]:
+ xmin = 46.46
+ xmax = 46.49
+ text = "N"
+ intervals [475]:
+ xmin = 46.49
+ xmax = 46.53
+ text = "L"
+ intervals [476]:
+ xmin = 46.53
+ xmax = 46.59
+ text = "AH1"
+ intervals [477]:
+ xmin = 46.59
+ xmax = 46.62
+ text = "V"
+ intervals [478]:
+ xmin = 46.62
+ xmax = 46.65
+ text = "W"
+ intervals [479]:
+ xmin = 46.65
+ xmax = 46.68
+ text = "IH0"
+ intervals [480]:
+ xmin = 46.68
+ xmax = 46.72
+ text = "DH"
+ intervals [481]:
+ xmin = 46.72
+ xmax = 46.85
+ text = "AH0"
+ intervals [482]:
+ xmin = 46.85
+ xmax = 46.91
+ text = ""
+ intervals [483]:
+ xmin = 46.91
+ xmax = 47.04
+ text = "G"
+ intervals [484]:
+ xmin = 47.04
+ xmax = 47.13
+ text = "ER1"
+ intervals [485]:
+ xmin = 47.13
+ xmax = 47.21
+ text = "L"
+ intervals [486]:
+ xmin = 47.21
+ xmax = 47.27
+ text = "HH"
+ intervals [487]:
+ xmin = 47.27
+ xmax = 47.38
+ text = "UW1"
+ intervals [488]:
+ xmin = 47.38
+ xmax = 47.46
+ text = "Z"
+ intervals [489]:
+ xmin = 47.46
+ xmax = 47.55
+ text = "D"
+ intervals [490]:
+ xmin = 47.55
+ xmax = 47.73
+ text = "AY1"
+ intervals [491]:
+ xmin = 47.73
+ xmax = 47.84
+ text = "IH0"
+ intervals [492]:
+ xmin = 47.84
+ xmax = 48.01
+ text = "NG"
+ intervals [493]:
+ xmin = 48.01
+ xmax = 49.08
+ text = ""
+ intervals [494]:
+ xmin = 49.08
+ xmax = 49.15
+ text = "DH"
+ intervals [495]:
+ xmin = 49.15
+ xmax = 49.18
+ text = "EH1"
+ intervals [496]:
+ xmin = 49.18
+ xmax = 49.33
+ text = "R"
+ intervals [497]:
+ xmin = 49.33
+ xmax = 49.36
+ text = "AA1"
+ intervals [498]:
+ xmin = 49.36
+ xmax = 49.39
+ text = "R"
+ intervals [499]:
+ xmin = 49.39
+ xmax = 49.46
+ text = "AH0"
+ intervals [500]:
+ xmin = 49.46
+ xmax = 49.52
+ text = "L"
+ intervals [501]:
+ xmin = 49.52
+ xmax = 49.69
+ text = "AA1"
+ intervals [502]:
+ xmin = 49.69
+ xmax = 49.82
+ text = "T"
+ intervals [503]:
+ xmin = 49.82
+ xmax = 49.98
+ text = "AH1"
+ intervals [504]:
+ xmin = 49.98
+ xmax = 50.2
+ text = "V"
+ intervals [505]:
+ xmin = 50.2
+ xmax = 50.29
+ text = ""
+ intervals [506]:
+ xmin = 50.29
+ xmax = 50.43
+ text = "EH1"
+ intervals [507]:
+ xmin = 50.43
+ xmax = 50.52
+ text = "N"
+ intervals [508]:
+ xmin = 50.52
+ xmax = 50.56
+ text = "V"
+ intervals [509]:
+ xmin = 50.56
+ xmax = 50.65
+ text = "IY0"
+ intervals [510]:
+ xmin = 50.65
+ xmax = 50.7
+ text = "AH0"
+ intervals [511]:
+ xmin = 50.7
+ xmax = 50.75
+ text = "B"
+ intervals [512]:
+ xmin = 50.75
+ xmax = 50.78
+ text = "AH0"
+ intervals [513]:
+ xmin = 50.78
+ xmax = 50.88
+ text = "L"
+ intervals [514]:
+ xmin = 50.88
+ xmax = 50.94
+ text = "M"
+ intervals [515]:
+ xmin = 50.94
+ xmax = 51.05
+ text = "OW1"
+ intervals [516]:
+ xmin = 51.05
+ xmax = 51.12
+ text = "M"
+ intervals [517]:
+ xmin = 51.12
+ xmax = 51.16
+ text = "AH0"
+ intervals [518]:
+ xmin = 51.16
+ xmax = 51.19
+ text = "N"
+ intervals [519]:
+ xmin = 51.19
+ xmax = 51.23
+ text = "T"
+ intervals [520]:
+ xmin = 51.23
+ xmax = 51.3
+ text = "S"
+ intervals [521]:
+ xmin = 51.3
+ xmax = 51.34
+ text = "IH0"
+ intervals [522]:
+ xmin = 51.34
+ xmax = 51.37
+ text = "N"
+ intervals [523]:
+ xmin = 51.37
+ xmax = 51.4
+ text = "DH"
+ intervals [524]:
+ xmin = 51.4
+ xmax = 51.46
+ text = "IH0"
+ intervals [525]:
+ xmin = 51.46
+ xmax = 51.53
+ text = "S"
+ intervals [526]:
+ xmin = 51.53
+ xmax = 51.58
+ text = "F"
+ intervals [527]:
+ xmin = 51.58
+ xmax = 51.62
+ text = "IH1"
+ intervals [528]:
+ xmin = 51.62
+ xmax = 51.72
+ text = "L"
+ intervals [529]:
+ xmin = 51.72
+ xmax = 51.77
+ text = "M"
+ intervals [530]:
+ xmin = 51.77
+ xmax = 51.86
+ text = "S"
+ intervals [531]:
+ xmin = 51.86
+ xmax = 51.91
+ text = "AH1"
+ intervals [532]:
+ xmin = 51.91
+ xmax = 52.01
+ text = "CH"
+ intervals [533]:
+ xmin = 52.01
+ xmax = 52.09
+ text = "EH1"
+ intervals [534]:
+ xmin = 52.09
+ xmax = 52.2
+ text = "Z"
+ intervals [535]:
+ xmin = 52.2
+ xmax = 52.23
+ text = "DH"
+ intervals [536]:
+ xmin = 52.23
+ xmax = 52.3
+ text = "AH0"
+ intervals [537]:
+ xmin = 52.3
+ xmax = 52.39
+ text = "S"
+ intervals [538]:
+ xmin = 52.39
+ xmax = 52.43
+ text = "IH1"
+ intervals [539]:
+ xmin = 52.43
+ xmax = 52.46
+ text = "M"
+ intervals [540]:
+ xmin = 52.46
+ xmax = 52.5
+ text = "P"
+ intervals [541]:
+ xmin = 52.5
+ xmax = 52.53
+ text = "AH0"
+ intervals [542]:
+ xmin = 52.53
+ xmax = 52.57
+ text = "L"
+ intervals [543]:
+ xmin = 52.57
+ xmax = 52.66
+ text = "L"
+ intervals [544]:
+ xmin = 52.66
+ xmax = 52.71
+ text = "AH1"
+ intervals [545]:
+ xmin = 52.71
+ xmax = 52.74
+ text = "V"
+ intervals [546]:
+ xmin = 52.74
+ xmax = 52.79
+ text = "B"
+ intervals [547]:
+ xmin = 52.79
+ xmax = 52.83
+ text = "IH0"
+ intervals [548]:
+ xmin = 52.83
+ xmax = 52.91
+ text = "T"
+ intervals [549]:
+ xmin = 52.91
+ xmax = 52.99
+ text = "W"
+ intervals [550]:
+ xmin = 52.99
+ xmax = 53.03
+ text = "IY1"
+ intervals [551]:
+ xmin = 53.03
+ xmax = 53.06
+ text = "N"
+ intervals [552]:
+ xmin = 53.06
+ xmax = 53.18
+ text = "HH"
+ intervals [553]:
+ xmin = 53.18
+ xmax = 53.26
+ text = "AY1"
+ intervals [554]:
+ xmin = 53.26
+ xmax = 53.34
+ text = "S"
+ intervals [555]:
+ xmin = 53.34
+ xmax = 53.42
+ text = "K"
+ intervals [556]:
+ xmin = 53.42
+ xmax = 53.45
+ text = "UW1"
+ intervals [557]:
+ xmin = 53.45
+ xmax = 53.52
+ text = "L"
+ intervals [558]:
+ xmin = 53.52
+ xmax = 53.63
+ text = "S"
+ intervals [559]:
+ xmin = 53.63
+ xmax = 53.68
+ text = "T"
+ intervals [560]:
+ xmin = 53.68
+ xmax = 53.77
+ text = "UW1"
+ intervals [561]:
+ xmin = 53.77
+ xmax = 53.8
+ text = "D"
+ intervals [562]:
+ xmin = 53.8
+ xmax = 53.84
+ text = "AH0"
+ intervals [563]:
+ xmin = 53.84
+ xmax = 53.89
+ text = "N"
+ intervals [564]:
+ xmin = 53.89
+ xmax = 53.95
+ text = "T"
+ intervals [565]:
+ xmin = 53.95
+ xmax = 54.09
+ text = "S"
+ intervals [566]:
+ xmin = 54.09
+ xmax = 54.32
+ text = ""
+ intervals [567]:
+ xmin = 54.32
+ xmax = 54.42
+ text = "EH1"
+ intervals [568]:
+ xmin = 54.42
+ xmax = 54.45
+ text = "V"
+ intervals [569]:
+ xmin = 54.45
+ xmax = 54.51
+ text = "R"
+ intervals [570]:
+ xmin = 54.51
+ xmax = 54.56
+ text = "IY0"
+ intervals [571]:
+ xmin = 54.56
+ xmax = 54.65
+ text = "T"
+ intervals [572]:
+ xmin = 54.65
+ xmax = 54.83
+ text = "AY1"
+ intervals [573]:
+ xmin = 54.83
+ xmax = 54.93
+ text = "M"
+ intervals [574]:
+ xmin = 54.93
+ xmax = 54.96
+ text = ""
+ intervals [575]:
+ xmin = 54.96
+ xmax = 55.08
+ text = "AY1"
+ intervals [576]:
+ xmin = 55.08
+ xmax = 55.28
+ text = "W"
+ intervals [577]:
+ xmin = 55.28
+ xmax = 55.36
+ text = "AA1"
+ intervals [578]:
+ xmin = 55.36
+ xmax = 55.45
+ text = "CH"
+ intervals [579]:
+ xmin = 55.45
+ xmax = 55.53
+ text = "DH"
+ intervals [580]:
+ xmin = 55.53
+ xmax = 55.59
+ text = "IH0"
+ intervals [581]:
+ xmin = 55.59
+ xmax = 55.68
+ text = "S"
+ intervals [582]:
+ xmin = 55.68
+ xmax = 55.73
+ text = "M"
+ intervals [583]:
+ xmin = 55.73
+ xmax = 55.76
+ text = "UW1"
+ intervals [584]:
+ xmin = 55.76
+ xmax = 55.84
+ text = "V"
+ intervals [585]:
+ xmin = 55.84
+ xmax = 55.89
+ text = "IY0"
+ intervals [586]:
+ xmin = 55.89
+ xmax = 55.92
+ text = "IH1"
+ intervals [587]:
+ xmin = 55.92
+ xmax = 55.98
+ text = "T"
+ intervals [588]:
+ xmin = 55.98
+ xmax = 56.05
+ text = "R"
+ intervals [589]:
+ xmin = 56.05
+ xmax = 56.12
+ text = "IY0"
+ intervals [590]:
+ xmin = 56.12
+ xmax = 56.2
+ text = "M"
+ intervals [591]:
+ xmin = 56.2
+ xmax = 56.34
+ text = "AY1"
+ intervals [592]:
+ xmin = 56.34
+ xmax = 56.38
+ text = "N"
+ intervals [593]:
+ xmin = 56.38
+ xmax = 56.41
+ text = "D"
+ intervals [594]:
+ xmin = 56.41
+ xmax = 56.44
+ text = "Z"
+ intervals [595]:
+ xmin = 56.44
+ xmax = 56.49
+ text = "M"
+ intervals [596]:
+ xmin = 56.49
+ xmax = 56.55
+ text = "IY1"
+ intervals [597]:
+ xmin = 56.55
+ xmax = 56.6
+ text = "AH0"
+ intervals [598]:
+ xmin = 56.6
+ xmax = 56.63
+ text = "V"
+ intervals [599]:
+ xmin = 56.63
+ xmax = 56.7
+ text = "AH0"
+ intervals [600]:
+ xmin = 56.7
+ xmax = 56.82
+ text = "T"
+ intervals [601]:
+ xmin = 56.82
+ xmax = 56.94
+ text = "AY1"
+ intervals [602]:
+ xmin = 56.94
+ xmax = 56.99
+ text = "M"
+ intervals [603]:
+ xmin = 56.99
+ xmax = 57.02
+ text = "DH"
+ intervals [604]:
+ xmin = 57.02
+ xmax = 57.05
+ text = "AH0"
+ intervals [605]:
+ xmin = 57.05
+ xmax = 57.08
+ text = "T"
+ intervals [606]:
+ xmin = 57.08
+ xmax = 57.13
+ text = "AY1"
+ intervals [607]:
+ xmin = 57.13
+ xmax = 57.17
+ text = "W"
+ intervals [608]:
+ xmin = 57.17
+ xmax = 57.2
+ text = "AH0"
+ intervals [609]:
+ xmin = 57.2
+ xmax = 57.23
+ text = "Z"
+ intervals [610]:
+ xmin = 57.23
+ xmax = 57.26
+ text = "IH0"
+ intervals [611]:
+ xmin = 57.26
+ xmax = 57.29
+ text = "N"
+ intervals [612]:
+ xmin = 57.29
+ xmax = 57.41
+ text = "HH"
+ intervals [613]:
+ xmin = 57.41
+ xmax = 57.53
+ text = "AY1"
+ intervals [614]:
+ xmin = 57.53
+ xmax = 57.66
+ text = "S"
+ intervals [615]:
+ xmin = 57.66
+ xmax = 57.69
+ text = "K"
+ intervals [616]:
+ xmin = 57.69
+ xmax = 57.84
+ text = "UW1"
+ intervals [617]:
+ xmin = 57.84
+ xmax = 57.88
+ text = "L"
+ intervals [618]:
+ xmin = 57.88
+ xmax = 57.91
+ text = "AH0"
+ intervals [619]:
+ xmin = 57.91
+ xmax = 57.94
+ text = "N"
+ intervals [620]:
+ xmin = 57.94
+ xmax = 58.03
+ text = "D"
+ intervals [621]:
+ xmin = 58.03
+ xmax = 58.25
+ text = ""
+ intervals [622]:
+ xmin = 58.25
+ xmax = 58.36
+ text = "Y"
+ intervals [623]:
+ xmin = 58.36
+ xmax = 58.4
+ text = "UW1"
+ intervals [624]:
+ xmin = 58.4
+ xmax = 58.45
+ text = "M"
+ intervals [625]:
+ xmin = 58.45
+ xmax = 58.51
+ text = "AY1"
+ intervals [626]:
+ xmin = 58.51
+ xmax = 58.55
+ text = "T"
+ intervals [627]:
+ xmin = 58.55
+ xmax = 58.59
+ text = "R"
+ intervals [628]:
+ xmin = 58.59
+ xmax = 58.66
+ text = "IH0"
+ intervals [629]:
+ xmin = 58.66
+ xmax = 58.7
+ text = "M"
+ intervals [630]:
+ xmin = 58.7
+ xmax = 58.76
+ text = "EH1"
+ intervals [631]:
+ xmin = 58.76
+ xmax = 58.79
+ text = "M"
+ intervals [632]:
+ xmin = 58.79
+ xmax = 58.84
+ text = "B"
+ intervals [633]:
+ xmin = 58.84
+ xmax = 59.1
+ text = "ER0"
+ intervals [634]:
+ xmin = 59.1
+ xmax = 59.29
+ text = ""
+ intervals [635]:
+ xmin = 59.29
+ xmax = 59.38
+ text = "DH"
+ intervals [636]:
+ xmin = 59.38
+ xmax = 59.44
+ text = "AH0"
+ intervals [637]:
+ xmin = 59.44
+ xmax = 59.56
+ text = "K"
+ intervals [638]:
+ xmin = 59.56
+ xmax = 59.63
+ text = "R"
+ intervals [639]:
+ xmin = 59.63
+ xmax = 59.69
+ text = "AH1"
+ intervals [640]:
+ xmin = 59.69
+ xmax = 59.83
+ text = "SH"
+ intervals [641]:
+ xmin = 59.83
+ xmax = 59.89
+ text = "Y"
+ intervals [642]:
+ xmin = 59.89
+ xmax = 59.94
+ text = "UW1"
+ intervals [643]:
+ xmin = 59.94
+ xmax = 60.03
+ text = "HH"
+ intervals [644]:
+ xmin = 60.03
+ xmax = 60.12
+ text = "AE1"
+ intervals [645]:
+ xmin = 60.12
+ xmax = 60.16
+ text = "D"
+ intervals [646]:
+ xmin = 60.16
+ xmax = 60.2
+ text = "IH0"
+ intervals [647]:
+ xmin = 60.2
+ xmax = 60.27
+ text = "N"
+ intervals [648]:
+ xmin = 60.27
+ xmax = 60.37
+ text = "S"
+ intervals [649]:
+ xmin = 60.37
+ xmax = 60.43
+ text = "K"
+ intervals [650]:
+ xmin = 60.43
+ xmax = 60.54
+ text = "UW1"
+ intervals [651]:
+ xmin = 60.54
+ xmax = 60.74
+ text = "L"
+ intervals [652]:
+ xmin = 60.74
+ xmax = 60.9
+ text = ""
+ intervals [653]:
+ xmin = 60.9
+ xmax = 61.06
+ text = "AE1"
+ intervals [654]:
+ xmin = 61.06
+ xmax = 61.09
+ text = "N"
+ intervals [655]:
+ xmin = 61.09
+ xmax = 61.12
+ text = "D"
+ intervals [656]:
+ xmin = 61.12
+ xmax = 61.2
+ text = "HH"
+ intervals [657]:
+ xmin = 61.2
+ xmax = 61.24
+ text = "AW1"
+ intervals [658]:
+ xmin = 61.24
+ xmax = 61.29
+ text = "Y"
+ intervals [659]:
+ xmin = 61.29
+ xmax = 61.36
+ text = "UW1"
+ intervals [660]:
+ xmin = 61.36
+ xmax = 61.4
+ text = "W"
+ intervals [661]:
+ xmin = 61.4
+ xmax = 61.43
+ text = "UH1"
+ intervals [662]:
+ xmin = 61.43
+ xmax = 61.48
+ text = "D"
+ intervals [663]:
+ xmin = 61.48
+ xmax = 61.57
+ text = "L"
+ intervals [664]:
+ xmin = 61.57
+ xmax = 61.63
+ text = "UH1"
+ intervals [665]:
+ xmin = 61.63
+ xmax = 61.7
+ text = "K"
+ intervals [666]:
+ xmin = 61.7
+ xmax = 61.73
+ text = "AE1"
+ intervals [667]:
+ xmin = 61.73
+ xmax = 61.77
+ text = "T"
+ intervals [668]:
+ xmin = 61.77
+ xmax = 61.84
+ text = "HH"
+ intervals [669]:
+ xmin = 61.84
+ xmax = 61.98
+ text = "IH1"
+ intervals [670]:
+ xmin = 61.98
+ xmax = 62.16
+ text = "M"
+ intervals [671]:
+ xmin = 62.16
+ xmax = 62.37
+ text = ""
+ intervals [672]:
+ xmin = 62.37
+ xmax = 62.42
+ text = "HH"
+ intervals [673]:
+ xmin = 62.42
+ xmax = 62.46
+ text = "W"
+ intervals [674]:
+ xmin = 62.46
+ xmax = 62.49
+ text = "AY1"
+ intervals [675]:
+ xmin = 62.49
+ xmax = 62.54
+ text = "L"
+ intervals [676]:
+ xmin = 62.54
+ xmax = 62.59
+ text = "HH"
+ intervals [677]:
+ xmin = 62.59
+ xmax = 62.64
+ text = "IY1"
+ intervals [678]:
+ xmin = 62.64
+ xmax = 62.74
+ text = "Z"
+ intervals [679]:
+ xmin = 62.74
+ xmax = 62.93
+ text = "AE1"
+ intervals [680]:
+ xmin = 62.93
+ xmax = 63.02
+ text = "T"
+ intervals [681]:
+ xmin = 63.02
+ xmax = 63.5
+ text = "IH1"
+ intervals [682]:
+ xmin = 63.5
+ xmax = 63.61
+ text = "N"
+ intervals [683]:
+ xmin = 63.61
+ xmax = 63.7
+ text = "K"
+ intervals [684]:
+ xmin = 63.7
+ xmax = 63.77
+ text = "L"
+ intervals [685]:
+ xmin = 63.77
+ xmax = 63.93
+ text = "AE1"
+ intervals [686]:
+ xmin = 63.93
+ xmax = 64.04
+ text = "S"
+ intervals [687]:
+ xmin = 64.04
+ xmax = 64.13
+ text = "W"
+ intervals [688]:
+ xmin = 64.13
+ xmax = 64.16
+ text = "IH0"
+ intervals [689]:
+ xmin = 64.16
+ xmax = 64.2
+ text = "DH"
+ intervals [690]:
+ xmin = 64.2
+ xmax = 64.3
+ text = "AW1"
+ intervals [691]:
+ xmin = 64.3
+ xmax = 64.38
+ text = "T"
+ intervals [692]:
+ xmin = 64.38
+ xmax = 64.45
+ text = "TH"
+ intervals [693]:
+ xmin = 64.45
+ xmax = 64.52
+ text = "IH1"
+ intervals [694]:
+ xmin = 64.52
+ xmax = 64.58
+ text = "NG"
+ intervals [695]:
+ xmin = 64.58
+ xmax = 64.64
+ text = "K"
+ intervals [696]:
+ xmin = 64.64
+ xmax = 64.76
+ text = "IH0"
+ intervals [697]:
+ xmin = 64.76
+ xmax = 64.83
+ text = "NG"
+ intervals [698]:
+ xmin = 64.83
+ xmax = 64.88
+ text = "AO1"
+ intervals [699]:
+ xmin = 64.88
+ xmax = 64.95
+ text = "R"
+ intervals [700]:
+ xmin = 64.95
+ xmax = 64.98
+ text = ""
+ intervals [701]:
+ xmin = 64.98
+ xmax = 65.13
+ text = "W"
+ intervals [702]:
+ xmin = 65.13
+ xmax = 65.17
+ text = "AA1"
+ intervals [703]:
+ xmin = 65.17
+ xmax = 65.21
+ text = "N"
+ intervals [704]:
+ xmin = 65.21
+ xmax = 65.24
+ text = "IH0"
+ intervals [705]:
+ xmin = 65.24
+ xmax = 65.27
+ text = "NG"
+ intervals [706]:
+ xmin = 65.27
+ xmax = 65.31
+ text = "T"
+ intervals [707]:
+ xmin = 65.31
+ xmax = 65.36
+ text = "AH0"
+ intervals [708]:
+ xmin = 65.36
+ xmax = 65.42
+ text = "G"
+ intervals [709]:
+ xmin = 65.42
+ xmax = 65.54
+ text = "OW1"
+ intervals [710]:
+ xmin = 65.54
+ xmax = 65.63
+ text = "P"
+ intervals [711]:
+ xmin = 65.63
+ xmax = 65.7
+ text = "L"
+ intervals [712]:
+ xmin = 65.7
+ xmax = 65.76
+ text = "EY1"
+ intervals [713]:
+ xmin = 65.76
+ xmax = 65.83
+ text = "S"
+ intervals [714]:
+ xmin = 65.83
+ xmax = 65.88
+ text = "IH0"
+ intervals [715]:
+ xmin = 65.88
+ xmax = 65.95
+ text = "Z"
+ intervals [716]:
+ xmin = 65.95
+ xmax = 66.0
+ text = "W"
+ intervals [717]:
+ xmin = 66.0
+ xmax = 66.03
+ text = "IH1"
+ intervals [718]:
+ xmin = 66.03
+ xmax = 66.12
+ text = "DH"
+ intervals [719]:
+ xmin = 66.12
+ xmax = 66.2
+ text = "IH0"
+ intervals [720]:
+ xmin = 66.2
+ xmax = 66.38
+ text = "M"
+ intervals [721]:
+ xmin = 66.38
+ xmax = 67
+ text = ""
diff --git a/EMAGE/test_sequences/wave16k/2_scott_0_1_1.wav b/EMAGE/test_sequences/wave16k/2_scott_0_1_1.wav
new file mode 100644
index 0000000000000000000000000000000000000000..ce126b220378ad565fb546a29aa3551325e16b8e
Binary files /dev/null and b/EMAGE/test_sequences/wave16k/2_scott_0_1_1.wav differ
diff --git a/EMAGE/test_sequences/wave16k/2_scott_0_2_2.wav b/EMAGE/test_sequences/wave16k/2_scott_0_2_2.wav
new file mode 100644
index 0000000000000000000000000000000000000000..237bef4d0fc331b2aad7aedefe8df8ccacaa3692
Binary files /dev/null and b/EMAGE/test_sequences/wave16k/2_scott_0_2_2.wav differ
diff --git a/EMAGE/test_sequences/wave16k/2_scott_0_3_3.wav b/EMAGE/test_sequences/wave16k/2_scott_0_3_3.wav
new file mode 100644
index 0000000000000000000000000000000000000000..136de1d7f9d24b0e35758c701379b578d5dd960f
Binary files /dev/null and b/EMAGE/test_sequences/wave16k/2_scott_0_3_3.wav differ
diff --git a/EMAGE/test_sequences/wave16k/2_scott_0_4_4.wav b/EMAGE/test_sequences/wave16k/2_scott_0_4_4.wav
new file mode 100644
index 0000000000000000000000000000000000000000..4d76914f5a9c269442eccc129e351de8ad14d7aa
Binary files /dev/null and b/EMAGE/test_sequences/wave16k/2_scott_0_4_4.wav differ
diff --git a/EMAGE/test_sequences/weights/AESKConv_240_100.bin b/EMAGE/test_sequences/weights/AESKConv_240_100.bin
new file mode 100644
index 0000000000000000000000000000000000000000..1d1ea36ecd9582802176c499eba43969144ad9fe
--- /dev/null
+++ b/EMAGE/test_sequences/weights/AESKConv_240_100.bin
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5cd9566b24264f34d44003b3de62cdfd50aa85b7cdde2d369214599023c40f55
+size 17558653
diff --git a/EMAGE/test_sequences/weights/mean_vel_smplxflame_30.npy b/EMAGE/test_sequences/weights/mean_vel_smplxflame_30.npy
new file mode 100644
index 0000000000000000000000000000000000000000..0789238537103f051a6c51a3c4725e8afe85e140
--- /dev/null
+++ b/EMAGE/test_sequences/weights/mean_vel_smplxflame_30.npy
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:53b5e48f2a7bf78c41a6de6395d6bb4f29018465ca5d0ee2820a2be3eebb7137
+size 348
diff --git a/EMAGE/test_sequences/weights/vocab.pkl b/EMAGE/test_sequences/weights/vocab.pkl
new file mode 100644
index 0000000000000000000000000000000000000000..3daf14aa7f32d7823b19fd765ff5739bb9a1bd32
--- /dev/null
+++ b/EMAGE/test_sequences/weights/vocab.pkl
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:54fbcea7b19e0ee9b5c5836c85087a682d3a9513041091ce3e95d83eed0b2acd
+size 13821361
diff --git a/README.md b/README.md
index bc4835a5ecc6342624354a1bd051209326282e81..290eb050c2de0c8a7305fe604ca61d5cda6a61a9 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,13 @@
---
title: EMAGE
-emoji: 💻
-colorFrom: green
+emoji: ⚡
+colorFrom: yellow
colorTo: green
sdk: gradio
sdk_version: 4.24.0
app_file: app.py
pinned: false
+license: apache-2.0
---
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
diff --git a/ae_trainer.py b/ae_trainer.py
new file mode 100644
index 0000000000000000000000000000000000000000..fcc27c34aa8c3544671cc3db0a529d73dab3134f
--- /dev/null
+++ b/ae_trainer.py
@@ -0,0 +1,375 @@
+import train
+import os
+import time
+import csv
+import sys
+import warnings
+import random
+import numpy as np
+import time
+import pprint
+import pickle
+
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+from torch.utils.tensorboard import SummaryWriter
+from torch.nn.parallel import DistributedDataParallel as DDP
+from loguru import logger
+import smplx
+
+from utils import config, logger_tools, other_tools, metric
+from utils import rotation_conversions as rc
+from dataloaders import data_tools
+from optimizers.optim_factory import create_optimizer
+from optimizers.scheduler_factory import create_scheduler
+from optimizers.loss_factory import get_loss_func
+from scipy.spatial.transform import Rotation
+
+
+class CustomTrainer(train.BaseTrainer):
+ """
+ motion representation learning
+ """
+ def __init__(self, args):
+ super().__init__(args)
+ self.joints = self.train_data.joints
+ self.smplx = smplx.create(
+ self.args.data_path_1+"smplx_models/",
+ model_type='smplx',
+ gender='NEUTRAL_2020',
+ use_face_contour=False,
+ num_betas=300,
+ num_expression_coeffs=100,
+ ext='npz',
+ use_pca=False,
+ ).cuda().eval()
+ self.tracker = other_tools.EpochTracker(["rec", "vel", "ver", "com", "kl", "acc"], [False, False, False, False, False, False])
+ if not self.args.rot6d: #"rot6d" not in args.pose_rep:
+ logger.error(f"this script is for rot6d, your pose rep. is {args.pose_rep}")
+ self.rec_loss = get_loss_func("GeodesicLoss")
+ self.vel_loss = torch.nn.L1Loss(reduction='mean')
+ self.vectices_loss = torch.nn.MSELoss(reduction='mean')
+
+ def inverse_selection(self, filtered_t, selection_array, n):
+ # 创建一个全为零的数组,形状为 n*165
+ original_shape_t = np.zeros((n, selection_array.size))
+
+ # 找到选择数组中为1的索引位置
+ selected_indices = np.where(selection_array == 1)[0]
+
+ # 将 filtered_t 的值填充到 original_shape_t 中相应的位置
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+
+ return original_shape_t
+
+ def inverse_selection_tensor(self, filtered_t, selection_array, n):
+ # 创建一个全为零的数组,形状为 n*165
+ selection_array = torch.from_numpy(selection_array).cuda()
+ original_shape_t = torch.zeros((n, 165)).cuda()
+
+ # 找到选择数组中为1的索引位置
+ selected_indices = torch.where(selection_array == 1)[0]
+
+ # 将 filtered_t 的值填充到 original_shape_t 中相应的位置
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+
+ return original_shape_t
+
+ def train(self, epoch):
+ self.model.train()
+ t_start = time.time()
+ self.tracker.reset()
+ for its, dict_data in enumerate(self.train_loader):
+ tar_pose = dict_data["pose"]
+ tar_beta = dict_data["beta"].cuda()
+ tar_trans = dict_data["trans"].cuda()
+ tar_pose = tar_pose.cuda()
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+ tar_exps = torch.zeros((bs, n, 100)).cuda()
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ t_data = time.time() - t_start
+
+ self.opt.zero_grad()
+ g_loss_final = 0
+ net_out = self.model(tar_pose)
+ rec_pose = net_out["rec_pose"]
+ rec_pose = rec_pose.reshape(bs, n, j, 6)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose)#
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs, n, j, 6))
+ loss_rec = self.rec_loss(rec_pose, tar_pose) * self.args.rec_weight * self.args.rec_pos_weight
+ self.tracker.update_meter("rec", "train", loss_rec.item())
+ g_loss_final += loss_rec
+
+ velocity_loss = self.vel_loss(rec_pose[:, 1:] - rec_pose[:, :-1], tar_pose[:, 1:] - tar_pose[:, :-1]) * self.args.rec_weight
+ acceleration_loss = self.vel_loss(rec_pose[:, 2:] + rec_pose[:, :-2] - 2 * rec_pose[:, 1:-1], tar_pose[:, 2:] + tar_pose[:, :-2] - 2 * tar_pose[:, 1:-1]) * self.args.rec_weight
+ self.tracker.update_meter("vel", "train", velocity_loss.item())
+ self.tracker.update_meter("acc", "train", acceleration_loss.item())
+ g_loss_final += velocity_loss
+ g_loss_final += acceleration_loss
+ # vertices loss
+ if self.args.rec_ver_weight > 0:
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+ rec_pose = self.inverse_selection_tensor(rec_pose, self.train_data.joint_mask, rec_pose.shape[0])
+ tar_pose = self.inverse_selection_tensor(tar_pose, self.train_data.joint_mask, tar_pose.shape[0])
+ vertices_rec = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=tar_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100),
+ jaw_pose=rec_pose[:, 66:69],
+ global_orient=rec_pose[:,:3],
+ body_pose=rec_pose[:,3:21*3+3],
+ left_hand_pose=rec_pose[:,25*3:40*3],
+ right_hand_pose=rec_pose[:,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=tar_pose[:, 69:72],
+ reye_pose=tar_pose[:, 72:75],
+ )
+ vertices_tar = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=tar_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100),
+ jaw_pose=tar_pose[:, 66:69],
+ global_orient=tar_pose[:,:3],
+ body_pose=tar_pose[:,3:21*3+3],
+ left_hand_pose=tar_pose[:,25*3:40*3],
+ right_hand_pose=tar_pose[:,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=tar_pose[:, 69:72],
+ reye_pose=tar_pose[:, 72:75],
+ )
+ vectices_loss = self.vectices_loss(vertices_rec['vertices'], vertices_tar['vertices'])
+ self.tracker.update_meter("ver", "train", vectices_loss.item()*self.args.rec_weight * self.args.rec_ver_weight)
+ g_loss_final += vectices_loss*self.args.rec_weight*self.args.rec_ver_weight
+
+ vertices_vel_loss = self.vel_loss(vertices_rec['vertices'][:, 1:] - vertices_rec['vertices'][:, :-1], vertices_tar['vertices'][:, 1:] - vertices_tar['vertices'][:, :-1]) * self.args.rec_weight
+ vertices_acc_loss = self.vel_loss(vertices_rec['vertices'][:, 2:] + vertices_rec['vertices'][:, :-2] - 2 * vertices_rec['vertices'][:, 1:-1], vertices_tar['vertices'][:, 2:] + vertices_tar['vertices'][:, :-2] - 2 * vertices_tar['vertices'][:, 1:-1]) * self.args.rec_weight
+ g_loss_final += vertices_vel_loss * self.args.rec_weight * self.args.rec_ver_weight
+ g_loss_final += vertices_acc_loss * self.args.rec_weight * self.args.rec_ver_weight
+
+ # if self.args.vel_weight > 0:
+ # pos_rec_vel = other_tools.estimate_linear_velocity(vertices_rec['joints'], 1/self.pose_fps)
+ # pos_tar_vel = other_tools.estimate_linear_velocity(vertices_tar['joints'], 1/self.pose_fps)
+ # vel_rec_loss = self.vel_loss(pos_rec_vel, pos_tar_vel)
+ # tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ # rec_pose = rc.axis_angle_to_matrix(rec_pose.reshape(bs, n, j, 3))
+ # rot_rec_vel = other_tools.estimate_angular_velocity(rec_pose, 1/self.pose_fps)
+ # rot_tar_vel = other_tools.estimate_angular_velocity(tar_pose, 1/self.pose_fps)
+ # vel_rec_loss += self.vel_loss(pos_rec_vel, pos_tar_vel)
+ # self.tracker.update_meter("vel", "train", vel_rec_loss.item()*self.args.vel_weight)
+ # loss += (vel_rec_loss*self.args.vel_weight)
+
+ # ---------------------- vae -------------------------- #
+ if "VQVAE" in self.args.g_name:
+ loss_embedding = net_out["embedding_loss"]
+ g_loss_final += loss_embedding
+ self.tracker.update_meter("com", "train", loss_embedding.item())
+ # elif "VAE" in self.args.g_name:
+ # pose_mu, pose_logvar = net_out["pose_mu"], net_out["pose_logvar"]
+ # KLD = -0.5 * torch.sum(1 + pose_logvar - pose_mu.pow(2) - pose_logvar.exp())
+ # if epoch < 0:
+ # KLD_weight = 0
+ # else:
+ # KLD_weight = min(1.0, (epoch - 0) * 0.05) * 0.01
+ # loss += KLD_weight * KLD
+ # self.tracker.update_meter("kl", "train", KLD_weight * KLD.item())
+ g_loss_final.backward()
+ if self.args.grad_norm != 0:
+ torch.nn.utils.clip_grad_norm_(self.model.parameters(), self.args.grad_norm)
+ self.opt.step()
+ t_train = time.time() - t_start - t_data
+ t_start = time.time()
+ mem_cost = torch.cuda.memory_cached() / 1E9
+ lr_g = self.opt.param_groups[0]['lr']
+ if its % self.args.log_period == 0:
+ self.train_recording(epoch, its, t_data, t_train, mem_cost, lr_g)
+ if self.args.debug:
+ if its == 1: break
+ self.opt_s.step(epoch)
+
+ def val(self, epoch):
+ self.model.eval()
+ t_start = time.time()
+ with torch.no_grad():
+ for its, dict_data in enumerate(self.val_loader):
+ tar_pose = dict_data["pose"]
+ tar_beta = dict_data["beta"].cuda()
+ tar_trans = dict_data["trans"].cuda()
+ tar_pose = tar_pose.cuda()
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+ tar_exps = torch.zeros((bs, n, 100)).cuda()
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ t_data = time.time() - t_start
+
+ #self.opt.zero_grad()
+ #g_loss_final = 0
+ net_out = self.model(tar_pose)
+ rec_pose = net_out["rec_pose"]
+ rec_pose = rec_pose.reshape(bs, n, j, 6)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose)#
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs, n, j, 6))
+ loss_rec = self.rec_loss(rec_pose, tar_pose) * self.args.rec_weight * self.args.rec_pos_weight
+ self.tracker.update_meter("rec", "val", loss_rec.item())
+ #g_loss_final += loss_rec
+
+ # vertices loss
+ if self.args.rec_ver_weight > 0:
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+ rec_pose = self.inverse_selection_tensor(rec_pose, self.train_data.joint_mask, rec_pose.shape[0])
+ tar_pose = self.inverse_selection_tensor(tar_pose, self.train_data.joint_mask, tar_pose.shape[0])
+ vertices_rec = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=tar_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100),
+ jaw_pose=rec_pose[:, 66:69],
+ global_orient=rec_pose[:,:3],
+ body_pose=rec_pose[:,3:21*3+3],
+ left_hand_pose=rec_pose[:,25*3:40*3],
+ right_hand_pose=rec_pose[:,40*3:55*3],
+ return_verts=True,
+ leye_pose=tar_pose[:, 69:72],
+ reye_pose=tar_pose[:, 72:75],
+ )
+ vertices_tar = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=tar_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100),
+ jaw_pose=tar_pose[:, 66:69],
+ global_orient=tar_pose[:,:3],
+ body_pose=tar_pose[:,3:21*3+3],
+ left_hand_pose=tar_pose[:,25*3:40*3],
+ right_hand_pose=tar_pose[:,40*3:55*3],
+ return_verts=True,
+ leye_pose=tar_pose[:, 69:72],
+ reye_pose=tar_pose[:, 72:75],
+ )
+ vectices_loss = self.vectices_loss(vertices_rec['vertices'], vertices_tar['vertices'])
+ self.tracker.update_meter("ver", "val", vectices_loss.item()*self.args.rec_weight * self.args.rec_ver_weight)
+ if "VQVAE" in self.args.g_name:
+ loss_embedding = net_out["embedding_loss"]
+ self.tracker.update_meter("com", "val", loss_embedding.item())
+ #g_loss_final += vectices_loss*self.args.rec_weight*self.args.rec_ver_weight
+ self.val_recording(epoch)
+
+ def test(self, epoch):
+ results_save_path = self.checkpoint_path + f"/{epoch}/"
+ if os.path.exists(results_save_path):
+ return 0
+ os.makedirs(results_save_path)
+ start_time = time.time()
+ total_length = 0
+ test_seq_list = self.test_data.selected_file
+ self.model.eval()
+ with torch.no_grad():
+ for its, dict_data in enumerate(self.test_loader):
+ tar_pose = dict_data["pose"]
+ tar_pose = tar_pose.cuda()
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ remain = n%self.args.pose_length
+ tar_pose = tar_pose[:, :n-remain, :]
+ #print(tar_pose.shape)
+ if True:
+ net_out = self.model(tar_pose)
+ rec_pose = net_out["rec_pose"]
+ n = rec_pose.shape[1]
+ tar_pose = tar_pose[:, :n, :]
+ rec_pose = rec_pose.reshape(bs, n, j, 6)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose)#
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+ rec_pose = rec_pose.cpu().numpy()
+ else:
+ pass
+# for i in range(tar_pose.shape[1]//(self.args.vae_test_len)):
+# tar_pose_new = tar_pose[:,i*(self.args.vae_test_len):i*(self.args.vae_test_len)+self.args.vae_test_len,:]
+# net_out = self.model(**dict(inputs=tar_pose_new))
+# rec_pose = net_out["rec_pose"]
+# rec_pose = (rec_pose.reshape(rec_pose.shape[0], rec_pose.shape[1], -1, 6) * self.joint_level_mask_cuda).reshape(rec_pose.shape[0], rec_pose.shape[1], -1)
+# if "rot6d" in self.args.pose_rep:
+# rec_pose = data_transfer.rotation_6d_to_matrix(rec_pose.reshape(tar_pose.shape[0], self.args.vae_test_len, -1, 6))
+# rec_pose = data_transfer.matrix_to_euler_angles(rec_pose, "XYZ").reshape(rec_pose.shape[0], rec_pose.shape[1], -1)
+# if "smplx" not in self.args.pose_rep:
+# rec_pose = torch.rad2deg(rec_pose)
+# rec_pose = rec_pose * self.joint_mask_cuda
+
+# out_sub = rec_pose.cpu().numpy().reshape(-1, rec_pose.shape[2])
+# if i != 0:
+# out_final = np.concatenate((out_final,out_sub), 0)
+# else:
+# out_final = out_sub
+
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs, n, j, 6))
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+ tar_pose = tar_pose.cpu().numpy()
+
+ total_length += n
+ # --- save --- #
+ if 'smplx' in self.args.pose_rep:
+ gt_npz = np.load(self.args.data_path+self.args.pose_rep+"/"+test_seq_list.iloc[its]['id']+'.npz', allow_pickle=True)
+ stride = int(30 / self.args.pose_fps)
+ tar_pose = self.inverse_selection(tar_pose, self.test_data.joint_mask, tar_pose.shape[0])
+ np.savez(results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=tar_pose[:n],
+ expressions=gt_npz["expressions"]-gt_npz["expressions"],
+ trans=gt_npz["trans"][::stride][:n] - gt_npz["trans"][::stride][:n],
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30 ,
+ )
+ rec_pose = self.inverse_selection(rec_pose, self.test_data.joint_mask, rec_pose.shape[0])
+ np.savez(results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=rec_pose,
+ expressions=gt_npz["expressions"]-gt_npz["expressions"],
+ trans=gt_npz["trans"][::stride][:n] - gt_npz["trans"][::stride][:n],
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30 ,
+ )
+ else:
+ rec_pose = rc.axis_angle_to_matrix(torch.from_numpy(rec_pose.reshape(bs*n, j, 3)))
+ rec_pose = np.rad2deg(rc.matrix_to_euler_angles(rec_pose, "XYZ")).reshape(bs*n, j*3).numpy()
+ tar_pose = rc.axis_angle_to_matrix(torch.from_numpy(tar_pose.reshape(bs*n, j, 3)))
+ tar_pose = np.rad2deg(rc.matrix_to_euler_angles(tar_pose, "XYZ")).reshape(bs*n, j*3).numpy()
+ #trans="0.000000 0.000000 0.000000"
+
+ with open(f"{self.args.data_path}{self.args.pose_rep}/{test_seq_list.iloc[its]['id']}.bvh", "r") as f_demo:
+ with open(results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.bvh', 'w+') as f_gt:
+ with open(results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.bvh', 'w+') as f_real:
+ for i, line_data in enumerate(f_demo.readlines()):
+ if i < 431:
+ f_real.write(line_data)
+ f_gt.write(line_data)
+ else: break
+ for line_id in range(n): #,args.pre_frames, args.pose_length
+ line_data = np.array2string(rec_pose[line_id], max_line_width=np.inf, precision=6, suppress_small=False, separator=' ')
+ f_real.write(line_data[1:-2]+'\n')
+ for line_id in range(n): #,args.pre_frames, args.pose_length
+ line_data = np.array2string(tar_pose[line_id], max_line_width=np.inf, precision=6, suppress_small=False, separator=' ')
+ f_gt.write(line_data[1:-2]+'\n')
+ # with open(results_save_path+"gt_"+test_seq_list[its]+'.pkl', 'wb') as fw:
+ # pickle.dump(new_dict, fw)
+ # #new_dict2["fullpose"] = out_final
+ # with open(results_save_path+"res_"+test_seq_list[its]+'.pkl', 'wb') as fw1:
+ # pickle.dump(new_dict2, fw1)
+
+ # other_tools.render_one_sequence(
+ # results_save_path+"res_"+test_seq_list[its]+'.pkl',
+ # results_save_path+"gt_"+test_seq_list[its]+'.pkl',
+ # results_save_path,
+ # self.args.data_path + self.args.test_data_path + 'wave16k/' + test_seq_list[its]+'.npy',
+ # )
+
+ #if its == 1:break
+ end_time = time.time() - start_time
+ logger.info(f"total inference time: {int(end_time)} s for {int(total_length/self.args.pose_fps)} s motion")
\ No newline at end of file
diff --git a/aeface_trainer.py b/aeface_trainer.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c174bc5c94d1240b4b1494ee57922a3c903ae73
--- /dev/null
+++ b/aeface_trainer.py
@@ -0,0 +1,388 @@
+import train
+import os
+import time
+import csv
+import sys
+import warnings
+import random
+import numpy as np
+import time
+import pprint
+import pickle
+
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+from torch.utils.tensorboard import SummaryWriter
+from torch.nn.parallel import DistributedDataParallel as DDP
+from loguru import logger
+import smplx
+
+from utils import config, logger_tools, other_tools, metric
+from utils import rotation_conversions as rc
+from dataloaders import data_tools
+from optimizers.optim_factory import create_optimizer
+from optimizers.scheduler_factory import create_scheduler
+from optimizers.loss_factory import get_loss_func
+from scipy.spatial.transform import Rotation
+
+
+class CustomTrainer(train.BaseTrainer):
+ """
+ motion representation learning
+ """
+ def __init__(self, args):
+ super().__init__(args)
+ self.joints = self.train_data.joints
+ self.tracker = other_tools.EpochTracker(["rec", "vel", "acc", "com", "face", "face_vel", "face_acc", "ver", "ver_vel", "ver_acc"], [False, False, False, False, False, False, False, False, False, False])
+ self.rec_loss = get_loss_func("GeodesicLoss")
+ self.mse_loss = torch.nn.MSELoss(reduction='mean')
+ self.vel_loss = torch.nn.MSELoss(reduction='mean') #torch.nn.L1Loss(reduction='mean')
+ self.vectices_loss = torch.nn.MSELoss(reduction='mean')
+
+ def inverse_selection(self, filtered_t, selection_array, n):
+ # 创建一个全为零的数组,形状为 n*165
+ original_shape_t = np.zeros((n, selection_array.size))
+
+ # 找到选择数组中为1的索引位置
+ selected_indices = np.where(selection_array == 1)[0]
+
+ # 将 filtered_t 的值填充到 original_shape_t 中相应的位置
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+
+ return original_shape_t
+
+ def train(self, epoch):
+ self.model.train()
+ t_start = time.time()
+ self.tracker.reset()
+ for its, dict_data in enumerate(self.train_loader):
+ tar_pose = dict_data["pose"]
+ tar_beta = dict_data["beta"].cuda()
+ tar_trans = dict_data["trans"].cuda()
+ tar_pose = tar_pose.cuda()
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+ tar_exps = dict_data["facial"].to(self.rank)
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ in_tar_pose = torch.cat([tar_pose, tar_exps], -1) # 103
+ t_data = time.time() - t_start
+
+ self.opt.zero_grad()
+ g_loss_final = 0
+ net_out = self.model(in_tar_pose)
+ # jaw open 6d loss
+ rec_pose = net_out["rec_pose"][:, :, :j*6]
+ rec_pose = rec_pose.reshape(bs, n, j, 6)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose)#
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs, n, j, 6))
+ loss_rec = self.rec_loss(rec_pose, tar_pose) * self.args.rec_weight * self.args.rec_pos_weight
+ self.tracker.update_meter("rec", "train", loss_rec.item())
+ g_loss_final += loss_rec
+ # jaw open 6d vel and acc loss
+ velocity_loss = self.vel_loss(rec_pose[:, 1:] - rec_pose[:, :-1], tar_pose[:, 1:] - tar_pose[:, :-1]) * self.args.rec_weight
+ acceleration_loss = self.vel_loss(rec_pose[:, 2:] + rec_pose[:, :-2] - 2 * rec_pose[:, 1:-1], tar_pose[:, 2:] + tar_pose[:, :-2] - 2 * tar_pose[:, 1:-1]) * self.args.rec_weight
+ self.tracker.update_meter("vel", "train", velocity_loss.item())
+ self.tracker.update_meter("acc", "train", acceleration_loss.item())
+ g_loss_final += velocity_loss
+ g_loss_final += acceleration_loss
+ # face parameter l1 loss
+ rec_exps = net_out["rec_pose"][:, :, j*6:]
+ loss_face = self.mse_loss(rec_exps, tar_exps) * self.args.rec_weight
+ self.tracker.update_meter("face", "train", loss_face.item())
+ g_loss_final += loss_face
+ # face parameter l1 vel and acc loss
+ face_velocity_loss = self.vel_loss(rec_exps[:, 1:] - rec_exps[:, :-1], tar_exps[:, 1:] - tar_exps[:, :-1]) * self.args.rec_weight
+ face_acceleration_loss = self.vel_loss(rec_exps[:, 2:] + rec_exps[:, :-2] - 2 * rec_exps[:, 1:-1], tar_exps[:, 2:] + tar_exps[:, :-2] - 2 * tar_exps[:, 1:-1]) * self.args.rec_weight
+ self.tracker.update_meter("face_vel", "train", face_velocity_loss.item())
+ self.tracker.update_meter("face_acc", "train", face_acceleration_loss.item())
+ g_loss_final += face_velocity_loss
+ g_loss_final += face_acceleration_loss
+
+ # vertices loss
+ if self.args.rec_ver_weight > 0:
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+ vertices_rec = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=tar_trans.reshape(bs*n, 3)-tar_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100),
+ jaw_pose=rec_pose,
+ global_orient=torch.zeros(bs*n, 3).cuda(),
+ body_pose=torch.zeros(bs*n, 21*3).cuda(),
+ left_hand_pose=torch.zeros(bs*n, 15*3).cuda(),
+ right_hand_pose=torch.zeros(bs*n, 15*3).cuda(),
+ return_verts=True,
+ # return_joints=True,
+ leye_pose=torch.zeros(bs*n, 3).cuda(),
+ reye_pose=torch.zeros(bs*n, 3).cuda(),
+ )
+ vertices_tar = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=tar_trans.reshape(bs*n, 3)-tar_trans.reshape(bs*n, 3),
+ expression=rec_exps.reshape(bs*n, 100),
+ jaw_pose=tar_pose,
+ global_orient=torch.zeros(bs*n, 3).cuda(),
+ body_pose=torch.zeros(bs*n, 21*3).cuda(),
+ left_hand_pose=torch.zeros(bs*n, 15*3).cuda(),
+ right_hand_pose=torch.zeros(bs*n, 15*3).cuda(),
+ return_verts=True,
+ # return_joints=True,
+ leye_pose=torch.zeros(bs*n, 3).cuda(),
+ reye_pose=torch.zeros(bs*n, 3).cuda(),
+ )
+ vectices_loss = self.mse_loss(vertices_rec['vertices'], vertices_tar['vertices'])
+ self.tracker.update_meter("ver", "train", vectices_loss.item()*self.args.rec_weight * self.args.rec_ver_weight)
+ g_loss_final += vectices_loss*self.args.rec_weight*self.args.rec_ver_weight
+ # vertices vel and acc loss
+ vert_velocity_loss = self.vel_loss(vertices_rec['vertices'][:, 1:] - vertices_rec['vertices'][:, :-1], vertices_tar['vertices'][:, 1:] - vertices_tar['vertices'][:, :-1]) * self.args.rec_weight * self.args.rec_ver_weight
+ vert_acceleration_loss = self.vel_loss(vertices_rec['vertices'][:, 2:] + vertices_rec['vertices'][:, :-2] - 2 * vertices_rec['vertices'][:, 1:-1], vertices_tar['vertices'][:, 2:] + vertices_tar['vertices'][:, :-2] - 2 * vertices_tar['vertices'][:, 1:-1]) * self.args.rec_weight * self.args.rec_ver_weight
+ self.tracker.update_meter("ver_vel", "train", vert_velocity_loss.item())
+ self.tracker.update_meter("ver_acc", "train", vert_acceleration_loss.item())
+ g_loss_final += vert_velocity_loss
+ g_loss_final += vert_acceleration_loss
+
+ # ---------------------- vae -------------------------- #
+ if "VQVAE" in self.args.g_name:
+ loss_embedding = net_out["embedding_loss"]
+ g_loss_final += loss_embedding
+ self.tracker.update_meter("com", "train", loss_embedding.item())
+ # elif "VAE" in self.args.g_name:
+ # pose_mu, pose_logvar = net_out["pose_mu"], net_out["pose_logvar"]
+ # KLD = -0.5 * torch.sum(1 + pose_logvar - pose_mu.pow(2) - pose_logvar.exp())
+ # if epoch < 0:
+ # KLD_weight = 0
+ # else:
+ # KLD_weight = min(1.0, (epoch - 0) * 0.05) * 0.01
+ # loss += KLD_weight * KLD
+ # self.tracker.update_meter("kl", "train", KLD_weight * KLD.item())
+ g_loss_final.backward()
+ if self.args.grad_norm != 0:
+ torch.nn.utils.clip_grad_norm_(self.model.parameters(), self.args.grad_norm)
+ self.opt.step()
+ t_train = time.time() - t_start - t_data
+ t_start = time.time()
+ mem_cost = torch.cuda.memory_cached() / 1E9
+ lr_g = self.opt.param_groups[0]['lr']
+ if its % self.args.log_period == 0:
+ self.train_recording(epoch, its, t_data, t_train, mem_cost, lr_g)
+ if self.args.debug:
+ if its == 1: break
+ self.opt_s.step(epoch)
+
+ def val(self, epoch):
+ self.model.eval()
+ t_start = time.time()
+ with torch.no_grad():
+ for its, dict_data in enumerate(self.val_loader):
+ tar_pose = dict_data["pose"]
+ tar_beta = dict_data["beta"].cuda()
+ tar_trans = dict_data["trans"].cuda()
+ tar_pose = tar_pose.cuda()
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+ tar_exps = dict_data["facial"].to(self.rank)
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ in_tar_pose = torch.cat([tar_pose, tar_exps], -1) # 103
+ # print(tar_pose.shape, in_tar_pose.shape, tar_exps.shape)
+ t_data = time.time() - t_start
+
+ #self.opt.zero_grad()
+ #g_loss_final = 0
+ net_out = self.model(in_tar_pose)
+ # jaw open 6d loss
+ rec_pose = net_out["rec_pose"][:, :, :j*6]
+ rec_pose = rec_pose.reshape(bs, n, j, 6)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose)#
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs, n, j, 6))
+ loss_rec = self.rec_loss(rec_pose, tar_pose) * self.args.rec_weight * self.args.rec_pos_weight
+ self.tracker.update_meter("rec", "val", loss_rec.item())
+ # g_loss_final += loss_rec
+ # jaw open 6d vel and acc loss
+ velocity_loss = self.vel_loss(rec_pose[:, 1:] - rec_pose[:, :-1], tar_pose[:, 1:] - tar_pose[:, :-1]) * self.args.rec_weight
+ acceleration_loss = self.vel_loss(rec_pose[:, 2:] + rec_pose[:, :-2] - 2 * rec_pose[:, 1:-1], tar_pose[:, 2:] + tar_pose[:, :-2] - 2 * tar_pose[:, 1:-1]) * self.args.rec_weight
+ self.tracker.update_meter("vel", "val", velocity_loss.item())
+ self.tracker.update_meter("acc", "val", acceleration_loss.item())
+ # g_loss_final += velocity_loss
+ # g_loss_final += acceleration_loss
+ # face parameter l1 loss
+ rec_exps = net_out["rec_pose"][:, :, j*6:]
+ loss_face = self.vel_loss(rec_exps, tar_exps) * self.args.rec_weight
+ self.tracker.update_meter("face", "val", loss_face.item())
+ # g_loss_final += loss_face
+ # face parameter l1 vel and acc loss
+ face_velocity_loss = self.vel_loss(rec_exps[:, 1:] - rec_exps[:, :-1], tar_exps[:, 1:] - tar_exps[:, :-1]) * self.args.rec_weight
+ face_acceleration_loss = self.vel_loss(rec_exps[:, 2:] + rec_exps[:, :-2] - 2 * rec_exps[:, 1:-1], tar_exps[:, 2:] + tar_exps[:, :-2] - 2 * tar_exps[:, 1:-1]) * self.args.rec_weight
+ self.tracker.update_meter("face_vel", "val", face_velocity_loss.item())
+ self.tracker.update_meter("face_acc", "val", face_acceleration_loss.item())
+ # g_loss_final += face_velocity_loss
+ # g_loss_final += face_acceleration_loss
+
+ # vertices loss
+ if self.args.rec_ver_weight > 0:
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+ vertices_rec = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=tar_trans.reshape(bs*n, 3)-tar_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100),
+ jaw_pose=rec_pose,
+ global_orient=torch.zeros(bs*n, 3).cuda(),
+ body_pose=torch.zeros(bs*n, 21*3).cuda(),
+ left_hand_pose=torch.zeros(bs*n, 15*3).cuda(),
+ right_hand_pose=torch.zeros(bs*n, 15*3).cuda(),
+ return_verts=True,
+ # return_joints=True,
+ leye_pose=torch.zeros(bs*n, 3).cuda(),
+ reye_pose=torch.zeros(bs*n, 3).cuda(),
+ )
+ vertices_tar = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=tar_trans.reshape(bs*n, 3)-tar_trans.reshape(bs*n, 3),
+ expression=rec_exps.reshape(bs*n, 100),
+ jaw_pose=tar_pose,
+ global_orient=torch.zeros(bs*n, 3).cuda(),
+ body_pose=torch.zeros(bs*n, 21*3).cuda(),
+ left_hand_pose=torch.zeros(bs*n, 15*3).cuda(),
+ right_hand_pose=torch.zeros(bs*n, 15*3).cuda(),
+ return_verts=True,
+ # return_joints=True,
+ leye_pose=torch.zeros(bs*n, 3).cuda(),
+ reye_pose=torch.zeros(bs*n, 3).cuda(),
+ )
+ vectices_loss = self.mse_loss(vertices_rec['vertices'], vertices_tar['vertices'])
+ self.tracker.update_meter("ver", "val", vectices_loss.item()*self.args.rec_weight * self.args.rec_ver_weight)
+ # g_loss_final += vectices_loss*self.args.rec_weight*self.args.rec_ver_weight
+ # vertices vel and acc loss
+ vert_velocity_loss = self.vel_loss(vertices_rec['vertices'][:, 1:] - vertices_rec['vertices'][:, :-1], vertices_tar['vertices'][:, 1:] - vertices_tar['vertices'][:, :-1]) * self.args.rec_weight * self.args.rec_ver_weight
+ vert_acceleration_loss = self.vel_loss(vertices_rec['vertices'][:, 2:] + vertices_rec['vertices'][:, :-2] - 2 * vertices_rec['vertices'][:, 1:-1], vertices_tar['vertices'][:, 2:] + vertices_tar['vertices'][:, :-2] - 2 * vertices_tar['vertices'][:, 1:-1]) * self.args.rec_weight * self.args.rec_ver_weight
+ self.tracker.update_meter("ver_vel", "val", vert_velocity_loss.item())
+ self.tracker.update_meter("ver_acc", "val", vert_acceleration_loss.item())
+ # g_loss_final += vert_velocity_loss
+ # g_loss_final += vert_acceleration_loss
+ if "VQVAE" in self.args.g_name:
+ loss_embedding = net_out["embedding_loss"]
+ self.tracker.update_meter("com", "val", loss_embedding.item())
+ #g_loss_final += vectices_loss*self.args.rec_weight*self.args.rec_ver_weight
+ self.val_recording(epoch)
+
+ def test(self, epoch):
+ results_save_path = self.checkpoint_path + f"/{epoch}/"
+ if os.path.exists(results_save_path):
+ return 0
+ os.makedirs(results_save_path)
+ start_time = time.time()
+ total_length = 0
+ test_seq_list = self.test_data.selected_file
+ self.model.eval()
+ with torch.no_grad():
+ for its, dict_data in enumerate(self.test_loader):
+ tar_pose = dict_data["pose"]
+ tar_pose = tar_pose.cuda()
+ tar_exps = dict_data["facial"].to(self.rank)
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ remain = n%self.args.pose_length
+ tar_pose = tar_pose[:, :n-remain, :]
+ # print(tar_exps.shape)
+ in_tar_pose = torch.cat([tar_pose, tar_exps[:, :n-remain, :]], -1) # 103
+ #print(tar_pose.shape)
+ if True:
+ net_out = self.model(in_tar_pose)
+ rec_pose = net_out["rec_pose"][:, :, :j*6]
+ n = rec_pose.shape[1]
+ tar_pose = tar_pose[:, :n, :]
+ rec_pose = rec_pose.reshape(bs, n, j, 6)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose)#
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+ rec_pose = rec_pose.cpu().numpy()
+ rec_exps = net_out["rec_pose"][:, :, j*6:]
+ rec_exps = rec_exps.cpu().numpy().reshape(bs*n, 100)
+ else:
+ pass
+# for i in range(tar_pose.shape[1]//(self.args.vae_test_len)):
+# tar_pose_new = tar_pose[:,i*(self.args.vae_test_len):i*(self.args.vae_test_len)+self.args.vae_test_len,:]
+# net_out = self.model(**dict(inputs=tar_pose_new))
+# rec_pose = net_out["rec_pose"]
+# rec_pose = (rec_pose.reshape(rec_pose.shape[0], rec_pose.shape[1], -1, 6) * self.joint_level_mask_cuda).reshape(rec_pose.shape[0], rec_pose.shape[1], -1)
+# if "rot6d" in self.args.pose_rep:
+# rec_pose = data_transfer.rotation_6d_to_matrix(rec_pose.reshape(tar_pose.shape[0], self.args.vae_test_len, -1, 6))
+# rec_pose = data_transfer.matrix_to_euler_angles(rec_pose, "XYZ").reshape(rec_pose.shape[0], rec_pose.shape[1], -1)
+# if "smplx" not in self.args.pose_rep:
+# rec_pose = torch.rad2deg(rec_pose)
+# rec_pose = rec_pose * self.joint_mask_cuda
+
+# out_sub = rec_pose.cpu().numpy().reshape(-1, rec_pose.shape[2])
+# if i != 0:
+# out_final = np.concatenate((out_final,out_sub), 0)
+# else:
+# out_final = out_sub
+
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs, n, j, 6))
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+ tar_pose = tar_pose.cpu().numpy()
+
+ total_length += n
+ # --- save --- #
+ if 'smplx' in self.args.pose_rep:
+ gt_npz = np.load(self.args.data_path+self.args.pose_rep+"/"+test_seq_list.iloc[its]['id']+'.npz', allow_pickle=True)
+ stride = int(30 / self.args.pose_fps)
+ tar_pose = self.inverse_selection(tar_pose, self.test_data.joint_mask, tar_pose.shape[0])
+ np.savez(results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=tar_pose[:n],
+ expressions=gt_npz["expressions"],
+ trans=gt_npz["trans"][::stride][:n] - gt_npz["trans"][::stride][:n],
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30 ,
+ )
+ rec_pose = self.inverse_selection(rec_pose, self.test_data.joint_mask, rec_pose.shape[0])
+ np.savez(results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=rec_pose,
+ expressions=rec_exps,
+ trans=gt_npz["trans"][::stride][:n] - gt_npz["trans"][::stride][:n],
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30 ,
+ )
+ else:
+ rec_pose = rc.axis_angle_to_matrix(torch.from_numpy(rec_pose.reshape(bs*n, j, 3)))
+ rec_pose = np.rad2deg(rc.matrix_to_euler_angles(rec_pose, "XYZ")).reshape(bs*n, j*3).numpy()
+ tar_pose = rc.axis_angle_to_matrix(torch.from_numpy(tar_pose.reshape(bs*n, j, 3)))
+ tar_pose = np.rad2deg(rc.matrix_to_euler_angles(tar_pose, "XYZ")).reshape(bs*n, j*3).numpy()
+ #trans="0.000000 0.000000 0.000000"
+
+ with open(f"{self.args.data_path}{self.args.pose_rep}/{test_seq_list.iloc[its]['id']}.bvh", "r") as f_demo:
+ with open(results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.bvh', 'w+') as f_gt:
+ with open(results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.bvh', 'w+') as f_real:
+ for i, line_data in enumerate(f_demo.readlines()):
+ if i < 431:
+ f_real.write(line_data)
+ f_gt.write(line_data)
+ else: break
+ for line_id in range(n): #,args.pre_frames, args.pose_length
+ line_data = np.array2string(rec_pose[line_id], max_line_width=np.inf, precision=6, suppress_small=False, separator=' ')
+ f_real.write(line_data[1:-2]+'\n')
+ for line_id in range(n): #,args.pre_frames, args.pose_length
+ line_data = np.array2string(tar_pose[line_id], max_line_width=np.inf, precision=6, suppress_small=False, separator=' ')
+ f_gt.write(line_data[1:-2]+'\n')
+ # with open(results_save_path+"gt_"+test_seq_list[its]+'.pkl', 'wb') as fw:
+ # pickle.dump(new_dict, fw)
+ # #new_dict2["fullpose"] = out_final
+ # with open(results_save_path+"res_"+test_seq_list[its]+'.pkl', 'wb') as fw1:
+ # pickle.dump(new_dict2, fw1)
+
+ # other_tools.render_one_sequence(
+ # results_save_path+"res_"+test_seq_list[its]+'.pkl',
+ # results_save_path+"gt_"+test_seq_list[its]+'.pkl',
+ # results_save_path,
+ # self.args.data_path + self.args.test_data_path + 'wave16k/' + test_seq_list[its]+'.npy',
+ # )
+
+ #if its == 1:break
+ end_time = time.time() - start_time
+ logger.info(f"total inference time: {int(end_time)} s for {int(total_length/self.args.pose_fps)} s motion")
\ No newline at end of file
diff --git a/aelower_trainer.py b/aelower_trainer.py
new file mode 100644
index 0000000000000000000000000000000000000000..3af3d647bcf63cd15e859cff3e619ac441e087e5
--- /dev/null
+++ b/aelower_trainer.py
@@ -0,0 +1,494 @@
+import train
+import os
+import time
+import csv
+import sys
+import warnings
+import random
+import numpy as np
+import time
+import pprint
+import pickle
+
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+from torch.utils.tensorboard import SummaryWriter
+from torch.nn.parallel import DistributedDataParallel as DDP
+from loguru import logger
+import smplx
+
+from utils import config, logger_tools, other_tools, metric
+from utils import rotation_conversions as rc
+from dataloaders import data_tools
+from optimizers.optim_factory import create_optimizer
+from optimizers.scheduler_factory import create_scheduler
+from optimizers.loss_factory import get_loss_func
+from scipy.spatial.transform import Rotation
+
+
+class CustomTrainer(train.BaseTrainer):
+ """
+ motion representation learning
+ """
+ def __init__(self, args):
+ super().__init__(args)
+ self.joints = self.train_data.joints
+ self.smplx = smplx.create(
+ self.args.data_path_1+"smplx_models/",
+ model_type='smplx',
+ gender='NEUTRAL_2020',
+ use_face_contour=False,
+ num_betas=300,
+ num_expression_coeffs=100,
+ ext='npz',
+ use_pca=False,
+ ).cuda().eval()
+ self.tracker = other_tools.EpochTracker(["rec", "contact", "vel", "foot", "ver", "com", "kl", "acc", "trans", "transv"], [False,False, False, False, False, False, False, False, False, False])
+ if not self.args.rot6d: #"rot6d" not in args.pose_rep:
+ logger.error(f"this script is for rot6d, your pose rep. is {args.pose_rep}")
+ self.rec_loss = get_loss_func("GeodesicLoss")
+ self.vel_loss = torch.nn.L1Loss(reduction='mean')
+ self.vectices_loss = torch.nn.MSELoss(reduction='mean')
+
+ def inverse_selection(self, filtered_t, selection_array, n):
+ # 创建一个全为零的数组,形状为 n*165
+ original_shape_t = np.zeros((n, selection_array.size))
+
+ # 找到选择数组中为1的索引位置
+ selected_indices = np.where(selection_array == 1)[0]
+
+ # 将 filtered_t 的值填充到 original_shape_t 中相应的位置
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+
+ return original_shape_t
+
+ def inverse_selection_tensor(self, filtered_t, selection_array, n):
+ # 创建一个全为零的数组,形状为 n*165
+ selection_array = torch.from_numpy(selection_array).cuda()
+ original_shape_t = torch.zeros((n, 165)).cuda()
+
+ # 找到选择数组中为1的索引位置
+ selected_indices = torch.where(selection_array == 1)[0]
+
+ # 将 filtered_t 的值填充到 original_shape_t 中相应的位置
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+
+ return original_shape_t
+
+
+ def train(self, epoch):
+ self.model.train()
+ t_start = time.time()
+ self.tracker.reset()
+ for its, dict_data in enumerate(self.train_loader):
+ tar_pose_raw = dict_data["pose"]
+ tar_beta = dict_data["beta"].cuda()
+ tar_trans = dict_data["trans"].cuda()
+ tar_trans_vel_x = other_tools.estimate_linear_velocity(tar_trans[:, :, 0:1], dt=1/self.args.pose_fps)
+ tar_trans_vel_z = other_tools.estimate_linear_velocity(tar_trans[:, :, 2:3], dt=1/self.args.pose_fps)
+ tar_pose = tar_pose_raw[:, :, :27].cuda()
+ tar_contact = tar_pose_raw[:, :, 27:31].cuda()
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+ tar_exps = torch.zeros((bs, n, 100)).cuda()
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ tar_trans_copy = tar_trans-tar_trans
+ tar_contact_copy = tar_contact-tar_contact
+ in_tar_pose = torch.cat((tar_pose, tar_trans_copy, tar_contact_copy), dim=-1)
+
+ t_data = time.time() - t_start
+
+ self.opt.zero_grad()
+ g_loss_final = 0
+ net_out = self.model(in_tar_pose)
+ rec_pose = tar_pose#net_out["rec_pose"][:, :, :j*6]
+ rec_pose = rec_pose.reshape(bs, n, j, 6)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose)#
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs, n, j, 6))
+ # loss_rec = self.rec_loss(rec_pose, tar_pose) * self.args.rec_weight * self.args.rec_pos_weight
+ # self.tracker.update_meter("rec", "train", loss_rec.item())
+ # g_loss_final += loss_rec
+
+ rec_contact = net_out["rec_pose"][:, :, j*6+3:j*6+7]
+ loss_contact = self.vectices_loss(rec_contact, tar_contact) * self.args.rec_weight * self.args.rec_pos_weight
+ self.tracker.update_meter("contact", "train", loss_contact.item())
+ g_loss_final += loss_contact
+
+ # velocity_loss = self.vel_loss(rec_pose[:, 1:] - rec_pose[:, :-1], tar_pose[:, 1:] - tar_pose[:, :-1]) * self.args.rec_weight
+ # acceleration_loss = self.vel_loss(rec_pose[:, 2:] + rec_pose[:, :-2] - 2 * rec_pose[:, 1:-1], tar_pose[:, 2:] + tar_pose[:, :-2] - 2 * tar_pose[:, 1:-1]) * self.args.rec_weight
+ # self.tracker.update_meter("vel", "train", velocity_loss.item())
+ # self.tracker.update_meter("acc", "train", acceleration_loss.item())
+ # g_loss_final += velocity_loss
+ # g_loss_final += acceleration_loss
+
+ rec_trans = net_out["rec_pose"][:, :, j*6:j*6+3]
+ rec_x_trans = other_tools.velocity2position(rec_trans[:, :, 0:1], 1/self.args.pose_fps, tar_trans[:, 0, 0:1])
+ rec_z_trans = other_tools.velocity2position(rec_trans[:, :, 2:3], 1/self.args.pose_fps, tar_trans[:, 0, 2:3])
+ rec_y_trans = rec_trans[:,:,1:2]
+ rec_xyz_trans = torch.cat([rec_x_trans, rec_y_trans, rec_z_trans], dim=-1)
+ loss_trans_vel = self.vel_loss(rec_trans[:, :, 0:1], tar_trans_vel_x) * self.args.rec_weight \
+ + self.vel_loss(rec_trans[:, :, 2:3], tar_trans_vel_z) * self.args.rec_weight
+ v3 = self.vel_loss(rec_trans[:, :, 0:1][:, 1:] - rec_trans[:, :, 0:1][:, :-1], tar_trans_vel_x[:, 1:] - tar_trans_vel_x[:, :-1]) * self.args.rec_weight \
+ + self.vel_loss(rec_trans[:, :, 2:3][:, 1:] - rec_trans[:, :, 2:3][:, :-1], tar_trans_vel_z[:, 1:] - tar_trans_vel_z[:, :-1]) * self.args.rec_weight
+ a3 = self.vel_loss(rec_trans[:, :, 0:1][:, 2:] + rec_trans[:, :, 0:1][:, :-2] - 2 * rec_trans[:, :, 0:1][:, 1:-1], tar_trans_vel_x[:, 2:] + tar_trans_vel_x[:, :-2] - 2 * tar_trans_vel_x[:, 1:-1]) * self.args.rec_weight \
+ + self.vel_loss(rec_trans[:, :, 2:3][:, 2:] + rec_trans[:, :, 2:3][:, :-2] - 2 * rec_trans[:, :, 2:3][:, 1:-1], tar_trans_vel_z[:, 2:] + tar_trans_vel_z[:, :-2] - 2 * tar_trans_vel_z[:, 1:-1]) * self.args.rec_weight
+ g_loss_final += 5*v3
+ g_loss_final += 5*a3
+ v2 = self.vel_loss(rec_xyz_trans[:, 1:] - rec_xyz_trans[:, :-1], tar_trans[:, 1:] - tar_trans[:, :-1]) * self.args.rec_weight
+ a2 = self.vel_loss(rec_xyz_trans[:, 2:] + rec_xyz_trans[:, :-2] - 2 * rec_xyz_trans[:, 1:-1], tar_trans[:, 2:] + tar_trans[:, :-2] - 2 * tar_trans[:, 1:-1]) * self.args.rec_weight
+ g_loss_final += 5*v2
+ g_loss_final += 5*a2
+ self.tracker.update_meter("transv", "train", loss_trans_vel.item())
+ g_loss_final += loss_trans_vel
+ loss_trans = self.vel_loss(rec_xyz_trans, tar_trans) * self.args.rec_weight
+ self.tracker.update_meter("trans", "train", loss_trans.item())
+ g_loss_final += loss_trans
+
+ # vertices loss
+ if self.args.rec_ver_weight > 0:
+ # print(tar_pose.shape, j)
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+ rec_pose = self.inverse_selection_tensor(rec_pose, self.train_data.joint_mask, rec_pose.shape[0])
+ tar_pose = self.inverse_selection_tensor(tar_pose, self.train_data.joint_mask, tar_pose.shape[0])
+ vertices_rec = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=rec_xyz_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100),
+ jaw_pose=rec_pose[:, 66:69],
+ global_orient=rec_pose[:,:3],
+ body_pose=rec_pose[:,3:21*3+3],
+ left_hand_pose=rec_pose[:,25*3:40*3],
+ right_hand_pose=rec_pose[:,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=tar_pose[:, 69:72],
+ reye_pose=tar_pose[:, 72:75],
+ )
+ vertices_tar = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=tar_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100),
+ jaw_pose=tar_pose[:, 66:69],
+ global_orient=tar_pose[:,:3],
+ body_pose=tar_pose[:,3:21*3+3],
+ left_hand_pose=tar_pose[:,25*3:40*3],
+ right_hand_pose=tar_pose[:,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=tar_pose[:, 69:72],
+ reye_pose=tar_pose[:, 72:75],
+ )
+ joints_rec = vertices_rec['joints']
+ # print(joints_rec.shape)
+ joints_rec = joints_rec.reshape(bs, n, -1, 3)
+ vectices_loss = self.vectices_loss(vertices_rec['vertices'], vertices_tar['vertices'])
+ vertices_vel_loss = self.vectices_loss(
+ vertices_rec['vertices'][:, 1:] - vertices_rec['vertices'][:, :-1],
+ vertices_tar['vertices'][:, 1:] - vertices_tar['vertices'][:, :-1])
+ vertices_acc_loss = self.vectices_loss(
+ vertices_rec['vertices'][:, 2:] + vertices_rec['vertices'][:, :-2] - 2 * vertices_rec['vertices'][:, 1:-1],
+ vertices_tar['vertices'][:, 2:] + vertices_tar['vertices'][:, :-2] - 2 * vertices_tar['vertices'][:, 1:-1])
+ foot_idx = [7, 8, 10, 11]
+ model_contact = net_out["rec_pose"][:, :, j*6+3:j*6+7]
+ # find static indices consistent with model's own predictions
+ static_idx = model_contact > 0.95 # N x S x 4
+ # print(model_contact,static_idx)
+ model_feet = joints_rec[:, :, foot_idx] # foot positions (N, S, 4, 3)
+ model_foot_v = torch.zeros_like(model_feet)
+ model_foot_v[:, :-1] = (
+ model_feet[:, 1:, :, :] - model_feet[:, :-1, :, :]
+ ) # (N, S-1, 4, 3)
+ model_foot_v[~static_idx] = 0
+ foot_loss = self.vel_loss(
+ model_foot_v, torch.zeros_like(model_foot_v)
+ )
+ self.tracker.update_meter("foot", "train", foot_loss.item()*self.args.rec_weight * self.args.rec_ver_weight*1000)
+ self.tracker.update_meter("ver", "train", vectices_loss.item()*self.args.rec_weight * self.args.rec_ver_weight)
+ g_loss_final += (vectices_loss+5*vertices_vel_loss+5*vertices_acc_loss)*self.args.rec_weight*self.args.rec_ver_weight
+ g_loss_final += foot_loss*self.args.rec_weight*self.args.rec_ver_weight*20
+
+ # ---------------------- vae -------------------------- #
+ if "VQVAE" in self.args.g_name:
+ loss_embedding = net_out["embedding_loss"]
+ g_loss_final += loss_embedding
+ self.tracker.update_meter("com", "train", loss_embedding.item())
+ # elif "VAE" in self.args.g_name:
+ # pose_mu, pose_logvar = net_out["pose_mu"], net_out["pose_logvar"]
+ # KLD = -0.5 * torch.sum(1 + pose_logvar - pose_mu.pow(2) - pose_logvar.exp())
+ # if epoch < 0:
+ # KLD_weight = 0
+ # else:
+ # KLD_weight = min(1.0, (epoch - 0) * 0.05) * 0.01
+ # loss += KLD_weight * KLD
+ # self.tracker.update_meter("kl", "train", KLD_weight * KLD.item())
+ g_loss_final.backward()
+ if self.args.grad_norm != 0:
+ torch.nn.utils.clip_grad_norm_(self.model.parameters(), self.args.grad_norm)
+ self.opt.step()
+ t_train = time.time() - t_start - t_data
+ t_start = time.time()
+ mem_cost = torch.cuda.memory_cached() / 1E9
+ lr_g = self.opt.param_groups[0]['lr']
+ if its % self.args.log_period == 0:
+ self.train_recording(epoch, its, t_data, t_train, mem_cost, lr_g)
+ if self.args.debug:
+ if its == 1: break
+ self.opt_s.step(epoch)
+
+ def val(self, epoch):
+ self.model.eval()
+ t_start = time.time()
+ with torch.no_grad():
+ for its, dict_data in enumerate(self.val_loader):
+ tar_pose_raw = dict_data["pose"]
+ tar_beta = dict_data["beta"].cuda()
+ tar_trans = dict_data["trans"].cuda()
+ tar_trans_vel_x = other_tools.estimate_linear_velocity(tar_trans[:, :, 0:1], dt=1/self.args.pose_fps)
+ tar_trans_vel_z = other_tools.estimate_linear_velocity(tar_trans[:, :, 2:3], dt=1/self.args.pose_fps)
+ #print(tar_pose.shape)
+ tar_pose = tar_pose_raw[:, :, :27].cuda()
+
+ tar_contact = tar_pose_raw[:, :, 27:31].cuda()
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+ tar_exps = torch.zeros((bs, n, 100)).cuda()
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ tar_trans_copy = tar_trans-tar_trans
+ tar_contact_copy = tar_contact-tar_contact
+ in_tar_pose = torch.cat((tar_pose, tar_trans_copy, tar_contact_copy), dim=-1)
+ t_data = time.time() - t_start
+
+ #self.opt.zero_grad()
+ #g_loss_final = 0
+ net_out = self.model(in_tar_pose)
+ rec_pose = tar_pose
+ rec_pose = rec_pose.reshape(bs, n, j, 6)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose)#
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs, n, j, 6))
+ # loss_rec = self.rec_loss(rec_pose, tar_pose) * self.args.rec_weight * self.args.rec_pos_weight
+ # self.tracker.update_meter("rec", "val", loss_rec.item())
+ rec_contact = net_out["rec_pose"][:, :, j*6+3:j*6+7]
+ # print(rec_contact.shape, tar_contact.shape)
+ loss_contact = self.vel_loss(rec_contact, tar_contact) * self.args.rec_weight * self.args.rec_pos_weight
+ self.tracker.update_meter("contact", "val", loss_contact.item())
+ #g_loss_final += loss_rec
+ # rec_trans = net_out["rec_pose"][:, :, j*6:j*6+3]
+ # rec_x_trans = other_tools.velocity2position(rec_trans[:, :, 0:1], 1/self.args.pose_fps, tar_trans[:, 0, 0:1])
+ # rec_z_trans = other_tools.velocity2position(rec_trans[:, :, 2:3], 1/self.args.pose_fps, tar_trans[:, 0, 2:3])
+ # rec_y_trans = rec_trans[:,:,1:2]
+ # rec_xyz_trans = torch.cat([rec_x_trans, rec_y_trans, rec_z_trans], dim=-1)
+
+ rec_trans = net_out["rec_pose"][:, :, j*6:j*6+3]
+ rec_x_trans = other_tools.velocity2position(rec_trans[:, :, 0:1], 1/self.args.pose_fps, tar_trans[:, 0, 0:1])
+ rec_z_trans = other_tools.velocity2position(rec_trans[:, :, 2:3], 1/self.args.pose_fps, tar_trans[:, 0, 2:3])
+ rec_y_trans = rec_trans[:,:,1:2]
+ rec_xyz_trans = torch.cat([rec_x_trans, rec_y_trans, rec_z_trans], dim=-1)
+ loss_trans_vel = self.vel_loss(rec_trans[:, :, 0:1], tar_trans_vel_x) * self.args.rec_weight \
+ + self.vel_loss(rec_trans[:, :, 2:3], tar_trans_vel_z) * self.args.rec_weight
+ # v3 = self.vel_loss(rec_trans[:, :, 0:1][:, 1:] - rec_trans[:, :, 0:1][:, :-1], tar_trans_vel_x[:, 1:] - tar_trans_vel_x[:, :-1]) * self.args.rec_weight \
+ # + self.vel_loss(rec_trans[:, :, 2:3][:, 1:] - rec_trans[:, :, 2:3][:, :-1], tar_trans_vel_z[:, 1:] - tar_trans_vel_z[:, :-1]) * self.args.rec_weight
+ # a3 = self.vel_loss(rec_trans[:, :, 0:1][:, 2:] + rec_trans[:, :, 0:1][:, :-2] - 2 * rec_trans[:, :, 0:1][:, 1:-1], tar_trans_vel_x[:, 2:] + tar_trans_vel_x[:, :-2] - 2 * tar_trans_vel_x[:, 1:-1]) * self.args.rec_weight \
+ # + self.vel_loss(rec_trans[:, :, 2:3][:, 2:] + rec_trans[:, :, 2:3][:, :-2] - 2 * rec_trans[:, :, 2:3][:, 1:-1], tar_trans_vel_z[:, 2:] + tar_trans_vel_z[:, :-2] - 2 * tar_trans_vel_z[:, 1:-1]) * self.args.rec_weight
+ # #g_loss_final += 5*v3
+ # #g_loss_final += 5*a3
+ # v2 = self.vel_loss(rec_xyz_trans[:, 1:] - rec_xyz_trans[:, :-1], tar_trans[:, 1:] - tar_trans[:, :-1]) * self.args.rec_weight
+ # a2 = self.vel_loss(rec_xyz_trans[:, 2:] + rec_xyz_trans[:, :-2] - 2 * rec_xyz_trans[:, 1:-1], tar_trans[:, 2:] + tar_trans[:, :-2] - 2 * tar_trans[:, 1:-1]) * self.args.rec_weight
+ #g_loss_final += 5*v2
+ #g_loss_final += 5*a2
+ self.tracker.update_meter("transv", "val", loss_trans_vel.item())
+ #g_loss_final += loss_trans_vel
+ loss_trans = self.vel_loss(rec_xyz_trans, tar_trans) * self.args.rec_weight
+ self.tracker.update_meter("trans", "val", loss_trans.item())
+ #g_loss_final += loss_trans
+
+ # vertices loss
+ if self.args.rec_ver_weight > 0:
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+ rec_pose = self.inverse_selection_tensor(rec_pose, self.train_data.joint_mask, rec_pose.shape[0])
+ tar_pose = self.inverse_selection_tensor(tar_pose, self.train_data.joint_mask, tar_pose.shape[0])
+ vertices_rec = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=rec_xyz_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100),
+ jaw_pose=rec_pose[:, 66:69],
+ global_orient=rec_pose[:,:3],
+ body_pose=rec_pose[:,3:21*3+3],
+ left_hand_pose=rec_pose[:,25*3:40*3],
+ right_hand_pose=rec_pose[:,40*3:55*3],
+ return_verts=False,
+ return_joints=True,
+ leye_pose=tar_pose[:, 69:72],
+ reye_pose=tar_pose[:, 72:75],
+ )
+ vertices_tar = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=tar_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100),
+ jaw_pose=tar_pose[:, 66:69],
+ global_orient=tar_pose[:,:3],
+ body_pose=tar_pose[:,3:21*3+3],
+ left_hand_pose=tar_pose[:,25*3:40*3],
+ right_hand_pose=tar_pose[:,40*3:55*3],
+ return_verts=False,
+ return_joints=True,
+ leye_pose=tar_pose[:, 69:72],
+ reye_pose=tar_pose[:, 72:75],
+ )
+ joints_rec = vertices_rec['joints']
+ joints_rec = joints_rec.reshape(bs, n, -1, 3)
+ vectices_loss = self.vectices_loss(vertices_rec['joints'], vertices_tar['joints'])
+ foot_idx = [7, 8, 10, 11]
+ model_contact = net_out["rec_pose"][:, :, j*6+3:j*6+7]
+ # find static indices consistent with model's own predictions
+ static_idx = model_contact > 0.95 # N x S x 4
+ # print(model_contact)
+ model_feet = joints_rec[:, :, foot_idx] # foot positions (N, S, 4, 3)
+ model_foot_v = torch.zeros_like(model_feet)
+ model_foot_v[:, :-1] = (
+ model_feet[:, 1:, :, :] - model_feet[:, :-1, :, :]
+ ) # (N, S-1, 4, 3)
+ model_foot_v[~static_idx] = 0
+ foot_loss = self.vectices_loss(
+ model_foot_v, torch.zeros_like(model_foot_v)
+ )
+ self.tracker.update_meter("foot", "val", foot_loss.item()*self.args.rec_weight * self.args.rec_ver_weight)
+ self.tracker.update_meter("ver", "val", vectices_loss.item()*self.args.rec_weight * self.args.rec_ver_weight)
+ if "VQVAE" in self.args.g_name:
+ loss_embedding = net_out["embedding_loss"]
+ self.tracker.update_meter("com", "val", loss_embedding.item())
+ #g_loss_final += vectices_loss*self.args.rec_weight*self.args.rec_ver_weight
+ self.val_recording(epoch)
+
+ def test(self, epoch):
+ results_save_path = self.checkpoint_path + f"/{epoch}/"
+ if os.path.exists(results_save_path):
+ return 0
+ os.makedirs(results_save_path)
+ start_time = time.time()
+ total_length = 0
+ test_seq_list = self.test_data.selected_file
+ self.model.eval()
+ with torch.no_grad():
+ for its, dict_data in enumerate(self.test_loader):
+ tar_pose_raw = dict_data["pose"]
+ tar_trans = dict_data["trans"].to(self.rank)
+ tar_pose = tar_pose_raw[:, :, :27].cuda()
+ tar_contact = tar_pose_raw[:, :, 27:31].cuda()
+ # tar_pose = tar_pose.cuda()
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ remain = n%self.args.pose_length
+ tar_pose = tar_pose[:, :n-remain, :]
+ tar_contact = tar_contact[:, :n-remain, :]
+ tar_trans_copy = tar_trans[:, :n-remain, :]-tar_trans[:, :n-remain, :]
+ tar_contact_copy = tar_contact-tar_contact
+ in_tar_pose = torch.cat([tar_pose, tar_trans_copy, tar_contact_copy], dim=-1)
+ #print(tar_pose.shape)
+ if True:
+ net_out = self.model(in_tar_pose)
+ rec_pose = tar_pose #net_out["rec_pose"][:, :, :j*6]
+ rec_trans = net_out["rec_pose"][:, :, j*6:j*6+3]
+ # print(rec_trans.shape)
+ rec_x_trans = other_tools.velocity2position(rec_trans[:, :, 0:1], 1/self.args.pose_fps, tar_trans[:, 0, 0:1])
+ rec_z_trans = other_tools.velocity2position(rec_trans[:, :, 2:3], 1/self.args.pose_fps, tar_trans[:, 0, 2:3])
+ rec_y_trans = rec_trans[:,:,1:2]
+ rec_trans = torch.cat([rec_x_trans, rec_y_trans, rec_z_trans], dim=-1)
+ n = rec_pose.shape[1]
+ rec_trans = rec_trans.cpu().numpy().reshape(bs*n, 3)
+ tar_pose = tar_pose[:, :n, :]
+ rec_pose = rec_pose.reshape(bs, n, j, 6)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose)#
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+ rec_pose = rec_pose.cpu().numpy()
+ else:
+ pass
+# for i in range(tar_pose.shape[1]//(self.args.vae_test_len)):
+# tar_pose_new = tar_pose[:,i*(self.args.vae_test_len):i*(self.args.vae_test_len)+self.args.vae_test_len,:]
+# net_out = self.model(**dict(inputs=tar_pose_new))
+# rec_pose = net_out["rec_pose"]
+# rec_pose = (rec_pose.reshape(rec_pose.shape[0], rec_pose.shape[1], -1, 6) * self.joint_level_mask_cuda).reshape(rec_pose.shape[0], rec_pose.shape[1], -1)
+# if "rot6d" in self.args.pose_rep:
+# rec_pose = data_transfer.rotation_6d_to_matrix(rec_pose.reshape(tar_pose.shape[0], self.args.vae_test_len, -1, 6))
+# rec_pose = data_transfer.matrix_to_euler_angles(rec_pose, "XYZ").reshape(rec_pose.shape[0], rec_pose.shape[1], -1)
+# if "smplx" not in self.args.pose_rep:
+# rec_pose = torch.rad2deg(rec_pose)
+# rec_pose = rec_pose * self.joint_mask_cuda
+
+# out_sub = rec_pose.cpu().numpy().reshape(-1, rec_pose.shape[2])
+# if i != 0:
+# out_final = np.concatenate((out_final,out_sub), 0)
+# else:
+# out_final = out_sub
+
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs, n, j, 6))
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+ tar_pose = tar_pose.cpu().numpy()
+
+ total_length += n
+ # --- save --- #
+ if 'smplx' in self.args.pose_rep:
+ gt_npz = np.load(self.args.data_path+self.args.pose_rep+"/"+test_seq_list.iloc[its]['id']+'.npz', allow_pickle=True)
+ stride = int(30 / self.args.pose_fps)
+ tar_pose = self.inverse_selection(tar_pose, self.test_data.joint_mask, tar_pose.shape[0])
+ np.savez(results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=tar_pose[:n],
+ expressions=gt_npz["expressions"]-gt_npz["expressions"],
+ trans=gt_npz["trans"][::stride][:n],
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30 ,
+ )
+ rec_pose = self.inverse_selection(rec_pose, self.test_data.joint_mask, rec_pose.shape[0])
+ np.savez(results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=rec_pose,
+ expressions=gt_npz["expressions"]-gt_npz["expressions"],
+ trans=rec_trans,
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30 ,
+ )
+ else:
+ rec_pose = rc.axis_angle_to_matrix(torch.from_numpy(rec_pose.reshape(bs*n, j, 3)))
+ rec_pose = np.rad2deg(rc.matrix_to_euler_angles(rec_pose, "XYZ")).reshape(bs*n, j*3).numpy()
+ tar_pose = rc.axis_angle_to_matrix(torch.from_numpy(tar_pose.reshape(bs*n, j, 3)))
+ tar_pose = np.rad2deg(rc.matrix_to_euler_angles(tar_pose, "XYZ")).reshape(bs*n, j*3).numpy()
+ #trans="0.000000 0.000000 0.000000"
+
+ with open(f"{self.args.data_path}{self.args.pose_rep}/{test_seq_list.iloc[its]['id']}.bvh", "r") as f_demo:
+ with open(results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.bvh', 'w+') as f_gt:
+ with open(results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.bvh', 'w+') as f_real:
+ for i, line_data in enumerate(f_demo.readlines()):
+ if i < 431:
+ f_real.write(line_data)
+ f_gt.write(line_data)
+ else: break
+ for line_id in range(n): #,args.pre_frames, args.pose_length
+ line_data = np.array2string(rec_pose[line_id], max_line_width=np.inf, precision=6, suppress_small=False, separator=' ')
+ f_real.write(line_data[1:-2]+'\n')
+ for line_id in range(n): #,args.pre_frames, args.pose_length
+ line_data = np.array2string(tar_pose[line_id], max_line_width=np.inf, precision=6, suppress_small=False, separator=' ')
+ f_gt.write(line_data[1:-2]+'\n')
+ # with open(results_save_path+"gt_"+test_seq_list[its]+'.pkl', 'wb') as fw:
+ # pickle.dump(new_dict, fw)
+ # #new_dict2["fullpose"] = out_final
+ # with open(results_save_path+"res_"+test_seq_list[its]+'.pkl', 'wb') as fw1:
+ # pickle.dump(new_dict2, fw1)
+
+ # other_tools.render_one_sequence(
+ # results_save_path+"res_"+test_seq_list[its]+'.pkl',
+ # results_save_path+"gt_"+test_seq_list[its]+'.pkl',
+ # results_save_path,
+ # self.args.data_path + self.args.test_data_path + 'wave16k/' + test_seq_list[its]+'.npy',
+ # )
+
+ #if its == 1:break
+ end_time = time.time() - start_time
+ logger.info(f"total inference time: {int(end_time)} s for {int(total_length/self.args.pose_fps)} s motion")
\ No newline at end of file
diff --git a/aelowerfoot_trainer.py b/aelowerfoot_trainer.py
new file mode 100644
index 0000000000000000000000000000000000000000..38c5f11e2dcebea01aae5a049eaa96b5ad327bb8
--- /dev/null
+++ b/aelowerfoot_trainer.py
@@ -0,0 +1,491 @@
+import train
+import os
+import time
+import csv
+import sys
+import warnings
+import random
+import numpy as np
+import time
+import pprint
+import pickle
+
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+from torch.utils.tensorboard import SummaryWriter
+from torch.nn.parallel import DistributedDataParallel as DDP
+from loguru import logger
+import smplx
+
+from utils import config, logger_tools, other_tools, metric
+from utils import rotation_conversions as rc
+from dataloaders import data_tools
+from optimizers.optim_factory import create_optimizer
+from optimizers.scheduler_factory import create_scheduler
+from optimizers.loss_factory import get_loss_func
+from scipy.spatial.transform import Rotation
+
+
+class CustomTrainer(train.BaseTrainer):
+ """
+ motion representation learning
+ """
+ def __init__(self, args):
+ super().__init__(args)
+ self.joints = self.train_data.joints
+ self.smplx = smplx.create(
+ self.args.data_path_1+"smplx_models/",
+ model_type='smplx',
+ gender='NEUTRAL_2020',
+ use_face_contour=False,
+ num_betas=300,
+ num_expression_coeffs=100,
+ ext='npz',
+ use_pca=False,
+ ).cuda().eval()
+ self.tracker = other_tools.EpochTracker(["rec", "contact", "vel", "foot", "ver", "com", "kl", "acc", "trans", "transv"], [False,False, False, False, False, False, False, False, False, False])
+ if not self.args.rot6d: #"rot6d" not in args.pose_rep:
+ logger.error(f"this script is for rot6d, your pose rep. is {args.pose_rep}")
+ self.rec_loss = get_loss_func("GeodesicLoss")
+ self.vel_loss = torch.nn.L1Loss(reduction='mean')
+ self.vectices_loss = torch.nn.MSELoss(reduction='mean')
+
+ def inverse_selection(self, filtered_t, selection_array, n):
+ # 创建一个全为零的数组,形状为 n*165
+ original_shape_t = np.zeros((n, selection_array.size))
+
+ # 找到选择数组中为1的索引位置
+ selected_indices = np.where(selection_array == 1)[0]
+
+ # 将 filtered_t 的值填充到 original_shape_t 中相应的位置
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+
+ return original_shape_t
+
+ def inverse_selection_tensor(self, filtered_t, selection_array, n):
+ # 创建一个全为零的数组,形状为 n*165
+ selection_array = torch.from_numpy(selection_array).cuda()
+ original_shape_t = torch.zeros((n, 165)).cuda()
+
+ # 找到选择数组中为1的索引位置
+ selected_indices = torch.where(selection_array == 1)[0]
+
+ # 将 filtered_t 的值填充到 original_shape_t 中相应的位置
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+
+ return original_shape_t
+
+
+ def train(self, epoch):
+ self.model.train()
+ t_start = time.time()
+ self.tracker.reset()
+ for its, dict_data in enumerate(self.train_loader):
+ tar_pose_raw = dict_data["pose"]
+ tar_beta = dict_data["beta"].cuda()
+ tar_trans = dict_data["trans"].cuda()
+ # tar_trans_vel_x = other_tools.estimate_linear_velocity(tar_trans[:, :, 0:1], dt=1/self.args.pose_fps)
+ # tar_trans_vel_z = other_tools.estimate_linear_velocity(tar_trans[:, :, 2:3], dt=1/self.args.pose_fps)
+ tar_pose = tar_pose_raw[:, :, :27].cuda()
+ tar_contact = tar_pose_raw[:, :, 27:31].cuda()
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+ tar_exps = torch.zeros((bs, n, 100)).cuda()
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ tar_trans_copy = tar_trans
+ tar_contact_copy = tar_contact
+ in_tar_pose = torch.cat((tar_pose, tar_trans_copy, tar_contact_copy), dim=-1)
+
+ t_data = time.time() - t_start
+
+ self.opt.zero_grad()
+ g_loss_final = 0
+ net_out = self.model(in_tar_pose)
+ rec_pose = net_out["rec_pose"][:, :, :j*6]
+ rec_pose = rec_pose.reshape(bs, n, j, 6)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose)#
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs, n, j, 6))
+ loss_rec = self.rec_loss(rec_pose, tar_pose) * self.args.rec_weight * self.args.rec_pos_weight
+ self.tracker.update_meter("rec", "train", loss_rec.item())
+ g_loss_final += loss_rec
+
+ rec_contact = net_out["rec_pose"][:, :, j*6+3:j*6+7]
+ loss_contact = self.vectices_loss(rec_contact, tar_contact) * self.args.rec_weight * self.args.rec_pos_weight
+ self.tracker.update_meter("contact", "train", loss_contact.item())
+ g_loss_final += loss_contact
+
+ velocity_loss = self.vel_loss(rec_pose[:, 1:] - rec_pose[:, :-1], tar_pose[:, 1:] - tar_pose[:, :-1]) * self.args.rec_weight
+ acceleration_loss = self.vel_loss(rec_pose[:, 2:] + rec_pose[:, :-2] - 2 * rec_pose[:, 1:-1], tar_pose[:, 2:] + tar_pose[:, :-2] - 2 * tar_pose[:, 1:-1]) * self.args.rec_weight
+ self.tracker.update_meter("vel", "train", velocity_loss.item())
+ self.tracker.update_meter("acc", "train", acceleration_loss.item())
+ g_loss_final += velocity_loss
+ g_loss_final += acceleration_loss
+
+ # rec_trans = net_out["rec_pose"][:, :, j*6:j*6+3]
+ # rec_x_trans = other_tools.velocity2position(rec_trans[:, :, 0:1], 1/self.args.pose_fps, tar_trans[:, 0, 0:1])
+ # rec_z_trans = other_tools.velocity2position(rec_trans[:, :, 2:3], 1/self.args.pose_fps, tar_trans[:, 0, 2:3])
+ # rec_y_trans = rec_trans[:,:,1:2]
+ # rec_xyz_trans = torch.cat([rec_x_trans, rec_y_trans, rec_z_trans], dim=-1)
+ # loss_trans_vel = self.vel_loss(rec_trans[:, :, 0:1], tar_trans_vel_x) * self.args.rec_weight \
+ # + self.vel_loss(rec_trans[:, :, 2:3], tar_trans_vel_z) * self.args.rec_weight
+ # v3 = self.vel_loss(rec_trans[:, :, 0:1][:, 1:] - rec_trans[:, :, 0:1][:, :-1], tar_trans_vel_x[:, 1:] - tar_trans_vel_x[:, :-1]) * self.args.rec_weight \
+ # + self.vel_loss(rec_trans[:, :, 2:3][:, 1:] - rec_trans[:, :, 2:3][:, :-1], tar_trans_vel_z[:, 1:] - tar_trans_vel_z[:, :-1]) * self.args.rec_weight
+ # a3 = self.vel_loss(rec_trans[:, :, 0:1][:, 2:] + rec_trans[:, :, 0:1][:, :-2] - 2 * rec_trans[:, :, 0:1][:, 1:-1], tar_trans_vel_x[:, 2:] + tar_trans_vel_x[:, :-2] - 2 * tar_trans_vel_x[:, 1:-1]) * self.args.rec_weight \
+ # + self.vel_loss(rec_trans[:, :, 2:3][:, 2:] + rec_trans[:, :, 2:3][:, :-2] - 2 * rec_trans[:, :, 2:3][:, 1:-1], tar_trans_vel_z[:, 2:] + tar_trans_vel_z[:, :-2] - 2 * tar_trans_vel_z[:, 1:-1]) * self.args.rec_weight
+ # g_loss_final += 5*v3
+ # g_loss_final += 5*a3
+ # v2 = self.vel_loss(rec_xyz_trans[:, 1:] - rec_xyz_trans[:, :-1], tar_trans[:, 1:] - tar_trans[:, :-1]) * self.args.rec_weight
+ # a2 = self.vel_loss(rec_xyz_trans[:, 2:] + rec_xyz_trans[:, :-2] - 2 * rec_xyz_trans[:, 1:-1], tar_trans[:, 2:] + tar_trans[:, :-2] - 2 * tar_trans[:, 1:-1]) * self.args.rec_weight
+ # g_loss_final += 5*v2
+ # g_loss_final += 5*a2
+ # self.tracker.update_meter("transv", "train", loss_trans_vel.item())
+ # g_loss_final += loss_trans_vel
+ # loss_trans = self.vel_loss(rec_xyz_trans, tar_trans) * self.args.rec_weight
+ # self.tracker.update_meter("trans", "train", loss_trans.item())
+ # g_loss_final += loss_trans
+
+ # vertices loss
+ if self.args.rec_ver_weight > 0:
+ # print(tar_pose.shape, bs, n, j)
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+ rec_pose = self.inverse_selection_tensor(rec_pose, self.train_data.joint_mask, rec_pose.shape[0])
+ tar_pose = self.inverse_selection_tensor(tar_pose, self.train_data.joint_mask, tar_pose.shape[0])
+ vertices_rec = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=tar_trans.reshape(bs*n, 3)-tar_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100),
+ jaw_pose=rec_pose[:, 66:69],
+ global_orient=rec_pose[:,:3],
+ body_pose=rec_pose[:,3:21*3+3],
+ left_hand_pose=rec_pose[:,25*3:40*3],
+ right_hand_pose=rec_pose[:,40*3:55*3],
+ return_verts=False,
+ return_joints=True,
+ leye_pose=tar_pose[:, 69:72],
+ reye_pose=tar_pose[:, 72:75],
+ )
+ vertices_tar = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=tar_trans.reshape(bs*n, 3)-tar_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100),
+ jaw_pose=tar_pose[:, 66:69],
+ global_orient=tar_pose[:,:3],
+ body_pose=tar_pose[:,3:21*3+3],
+ left_hand_pose=tar_pose[:,25*3:40*3],
+ right_hand_pose=tar_pose[:,40*3:55*3],
+ return_verts=False,
+ return_joints=True,
+ leye_pose=tar_pose[:, 69:72],
+ reye_pose=tar_pose[:, 72:75],
+ )
+ joints_rec = vertices_rec['joints']
+ # print(joints_rec.shape)
+ joints_rec = joints_rec.reshape(bs, n, -1, 3)
+ vectices_loss = self.vectices_loss(vertices_rec['joints'], vertices_tar['joints'])
+ foot_idx = [7, 8, 10, 11]
+ model_contact = net_out["rec_pose"][:, :, j*6+3:j*6+7]
+ # find static indices consistent with model's own predictions
+ static_idx = model_contact > 0.95 # N x S x 4
+ # print(model_contact,static_idx)
+ model_feet = joints_rec[:, :, foot_idx] # foot positions (N, S, 4, 3)
+ model_foot_v = torch.zeros_like(model_feet)
+ model_foot_v[:, :-1] = (
+ model_feet[:, 1:, :, :] - model_feet[:, :-1, :, :]
+ ) # (N, S-1, 4, 3)
+ model_foot_v[~static_idx] = 0
+ foot_loss = self.vel_loss(
+ model_foot_v, torch.zeros_like(model_foot_v)
+ )
+ self.tracker.update_meter("foot", "train", foot_loss.item()*self.args.rec_weight * self.args.rec_ver_weight*20)
+ self.tracker.update_meter("ver", "train", vectices_loss.item()*self.args.rec_weight * self.args.rec_ver_weight)
+ g_loss_final += (vectices_loss)*self.args.rec_weight*self.args.rec_ver_weight
+ g_loss_final += foot_loss*self.args.rec_weight*self.args.rec_ver_weight*20
+
+ # ---------------------- vae -------------------------- #
+ if "VQVAE" in self.args.g_name:
+ loss_embedding = net_out["embedding_loss"]
+ g_loss_final += loss_embedding
+ self.tracker.update_meter("com", "train", loss_embedding.item())
+ # elif "VAE" in self.args.g_name:
+ # pose_mu, pose_logvar = net_out["pose_mu"], net_out["pose_logvar"]
+ # KLD = -0.5 * torch.sum(1 + pose_logvar - pose_mu.pow(2) - pose_logvar.exp())
+ # if epoch < 0:
+ # KLD_weight = 0
+ # else:
+ # KLD_weight = min(1.0, (epoch - 0) * 0.05) * 0.01
+ # loss += KLD_weight * KLD
+ # self.tracker.update_meter("kl", "train", KLD_weight * KLD.item())
+ g_loss_final.backward()
+ if self.args.grad_norm != 0:
+ torch.nn.utils.clip_grad_norm_(self.model.parameters(), self.args.grad_norm)
+ self.opt.step()
+ t_train = time.time() - t_start - t_data
+ t_start = time.time()
+ mem_cost = torch.cuda.memory_cached() / 1E9
+ lr_g = self.opt.param_groups[0]['lr']
+ if its % self.args.log_period == 0:
+ self.train_recording(epoch, its, t_data, t_train, mem_cost, lr_g)
+ if self.args.debug:
+ if its == 1: break
+ self.opt_s.step(epoch)
+
+ def val(self, epoch):
+ self.model.eval()
+ t_start = time.time()
+ with torch.no_grad():
+ for its, dict_data in enumerate(self.val_loader):
+ tar_pose_raw = dict_data["pose"]
+ tar_beta = dict_data["beta"].cuda()
+ tar_trans = dict_data["trans"].cuda()
+ tar_trans_vel_x = other_tools.estimate_linear_velocity(tar_trans[:, :, 0:1], dt=1/self.args.pose_fps)
+ tar_trans_vel_z = other_tools.estimate_linear_velocity(tar_trans[:, :, 2:3], dt=1/self.args.pose_fps)
+ #print(tar_pose.shape)
+ tar_pose = tar_pose_raw[:, :, :27].cuda()
+
+ tar_contact = tar_pose_raw[:, :, 27:31].cuda()
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+ tar_exps = torch.zeros((bs, n, 100)).cuda()
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ tar_trans_copy = tar_trans
+ tar_contact_copy = tar_contact
+ in_tar_pose = torch.cat((tar_pose, tar_trans_copy, tar_contact_copy), dim=-1)
+ t_data = time.time() - t_start
+
+ #self.opt.zero_grad()
+ #g_loss_final = 0
+ net_out = self.model(in_tar_pose)
+ rec_pose = net_out["rec_pose"][:, :, :j*6]
+ rec_pose = rec_pose.reshape(bs, n, j, 6)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose)#
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs, n, j, 6))
+ loss_rec = self.rec_loss(rec_pose, tar_pose) * self.args.rec_weight * self.args.rec_pos_weight
+ self.tracker.update_meter("rec", "val", loss_rec.item())
+ rec_contact = net_out["rec_pose"][:, :, j*6+3:j*6+7]
+ # print(rec_contact.shape, tar_contact.shape)
+ loss_contact = self.vel_loss(rec_contact, tar_contact) * self.args.rec_weight * self.args.rec_pos_weight
+ self.tracker.update_meter("contact", "val", loss_contact.item())
+ #g_loss_final += loss_rec
+ rec_trans = net_out["rec_pose"][:, :, j*6:j*6+3]
+ rec_x_trans = other_tools.velocity2position(rec_trans[:, :, 0:1], 1/self.args.pose_fps, tar_trans[:, 0, 0:1])
+ rec_z_trans = other_tools.velocity2position(rec_trans[:, :, 2:3], 1/self.args.pose_fps, tar_trans[:, 0, 2:3])
+ rec_y_trans = rec_trans[:,:,1:2]
+ rec_xyz_trans = torch.cat([rec_x_trans, rec_y_trans, rec_z_trans], dim=-1)
+
+ # rec_trans = net_out["rec_pose"][:, :, j*6:j*6+3]
+ # rec_x_trans = other_tools.velocity2position(rec_trans[:, :, 0:1], 1/self.args.pose_fps, tar_trans[:, 0, 0:1])
+ # rec_z_trans = other_tools.velocity2position(rec_trans[:, :, 2:3], 1/self.args.pose_fps, tar_trans[:, 0, 2:3])
+ # rec_y_trans = rec_trans[:,:,1:2]
+ # rec_xyz_trans = torch.cat([rec_x_trans, rec_y_trans, rec_z_trans], dim=-1)
+ # loss_trans_vel = self.vel_loss(rec_trans[:, :, 0:1], tar_trans_vel_x) * self.args.rec_weight \
+ # + self.vel_loss(rec_trans[:, :, 2:3], tar_trans_vel_z) * self.args.rec_weight
+ # v3 = self.vel_loss(rec_trans[:, :, 0:1][:, 1:] - rec_trans[:, :, 0:1][:, :-1], tar_trans_vel_x[:, 1:] - tar_trans_vel_x[:, :-1]) * self.args.rec_weight \
+ # + self.vel_loss(rec_trans[:, :, 2:3][:, 1:] - rec_trans[:, :, 2:3][:, :-1], tar_trans_vel_z[:, 1:] - tar_trans_vel_z[:, :-1]) * self.args.rec_weight
+ # a3 = self.vel_loss(rec_trans[:, :, 0:1][:, 2:] + rec_trans[:, :, 0:1][:, :-2] - 2 * rec_trans[:, :, 0:1][:, 1:-1], tar_trans_vel_x[:, 2:] + tar_trans_vel_x[:, :-2] - 2 * tar_trans_vel_x[:, 1:-1]) * self.args.rec_weight \
+ # + self.vel_loss(rec_trans[:, :, 2:3][:, 2:] + rec_trans[:, :, 2:3][:, :-2] - 2 * rec_trans[:, :, 2:3][:, 1:-1], tar_trans_vel_z[:, 2:] + tar_trans_vel_z[:, :-2] - 2 * tar_trans_vel_z[:, 1:-1]) * self.args.rec_weight
+ # #g_loss_final += 5*v3
+ # #g_loss_final += 5*a3
+ # v2 = self.vel_loss(rec_xyz_trans[:, 1:] - rec_xyz_trans[:, :-1], tar_trans[:, 1:] - tar_trans[:, :-1]) * self.args.rec_weight
+ # a2 = self.vel_loss(rec_xyz_trans[:, 2:] + rec_xyz_trans[:, :-2] - 2 * rec_xyz_trans[:, 1:-1], tar_trans[:, 2:] + tar_trans[:, :-2] - 2 * tar_trans[:, 1:-1]) * self.args.rec_weight
+ #g_loss_final += 5*v2
+ #g_loss_final += 5*a2
+ # self.tracker.update_meter("transv", "val", loss_trans_vel.item())
+ # #g_loss_final += loss_trans_vel
+ # loss_trans = self.vel_loss(rec_xyz_trans, tar_trans) * self.args.rec_weight
+ # self.tracker.update_meter("trans", "val", loss_trans.item())
+ #g_loss_final += loss_trans
+
+ # vertices loss
+ if self.args.rec_ver_weight > 0:
+ # print(tar_pose.shape, bs, n, j)
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+ rec_pose = self.inverse_selection_tensor(rec_pose, self.train_data.joint_mask, rec_pose.shape[0])
+ tar_pose = self.inverse_selection_tensor(tar_pose, self.train_data.joint_mask, tar_pose.shape[0])
+ vertices_rec = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=tar_trans.reshape(bs*n, 3)-tar_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100),
+ jaw_pose=rec_pose[:, 66:69],
+ global_orient=rec_pose[:,:3],
+ body_pose=rec_pose[:,3:21*3+3],
+ left_hand_pose=rec_pose[:,25*3:40*3],
+ right_hand_pose=rec_pose[:,40*3:55*3],
+ return_verts=False,
+ return_joints=True,
+ leye_pose=tar_pose[:, 69:72],
+ reye_pose=tar_pose[:, 72:75],
+ )
+ vertices_tar = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=tar_trans.reshape(bs*n, 3)-tar_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100),
+ jaw_pose=tar_pose[:, 66:69],
+ global_orient=tar_pose[:,:3],
+ body_pose=tar_pose[:,3:21*3+3],
+ left_hand_pose=tar_pose[:,25*3:40*3],
+ right_hand_pose=tar_pose[:,40*3:55*3],
+ return_verts=False,
+ return_joints=True,
+ leye_pose=tar_pose[:, 69:72],
+ reye_pose=tar_pose[:, 72:75],
+ )
+ joints_rec = vertices_rec['joints']
+ joints_rec = joints_rec.reshape(bs, n, -1, 3)
+ vectices_loss = self.vectices_loss(vertices_rec['joints'], vertices_tar['joints'])
+ foot_idx = [7, 8, 10, 11]
+ model_contact = net_out["rec_pose"][:, :, j*6+3:j*6+7]
+ # find static indices consistent with model's own predictions
+ static_idx = model_contact > 0.95 # N x S x 4
+ # print(model_contact)
+ model_feet = joints_rec[:, :, foot_idx] # foot positions (N, S, 4, 3)
+ model_foot_v = torch.zeros_like(model_feet)
+ model_foot_v[:, :-1] = (
+ model_feet[:, 1:, :, :] - model_feet[:, :-1, :, :]
+ ) # (N, S-1, 4, 3)
+ model_foot_v[~static_idx] = 0
+ foot_loss = self.vectices_loss(
+ model_foot_v, torch.zeros_like(model_foot_v)
+ )
+ self.tracker.update_meter("foot", "val", foot_loss.item()*self.args.rec_weight * self.args.rec_ver_weight)
+ self.tracker.update_meter("ver", "val", vectices_loss.item()*self.args.rec_weight * self.args.rec_ver_weight)
+ if "VQVAE" in self.args.g_name:
+ loss_embedding = net_out["embedding_loss"]
+ self.tracker.update_meter("com", "val", loss_embedding.item())
+ #g_loss_final += vectices_loss*self.args.rec_weight*self.args.rec_ver_weight
+ if self.args.debug:
+ if its == 1: break
+ self.val_recording(epoch)
+
+ def test(self, epoch):
+ results_save_path = self.checkpoint_path + f"/{epoch}/"
+ if os.path.exists(results_save_path):
+ return 0
+ os.makedirs(results_save_path)
+ start_time = time.time()
+ total_length = 0
+ test_seq_list = self.test_data.selected_file
+ self.model.eval()
+ with torch.no_grad():
+ for its, dict_data in enumerate(self.test_loader):
+ tar_pose_raw = dict_data["pose"]
+ tar_trans = dict_data["trans"].to(self.rank)
+ tar_pose = tar_pose_raw[:, :, :27].cuda()
+ tar_contact = tar_pose_raw[:, :, 27:31].cuda()
+ # tar_pose = tar_pose.cuda()
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ remain = n%self.args.pose_length
+ tar_pose = tar_pose[:, :n-remain, :]
+ tar_contact = tar_contact[:, :n-remain, :]
+ tar_trans_copy = tar_trans[:, :n-remain, :]
+ tar_contact_copy = tar_contact
+ in_tar_pose = torch.cat([tar_pose, tar_trans_copy, tar_contact_copy], dim=-1)
+ #print(tar_pose.shape)
+ if True:
+ net_out = self.model(in_tar_pose)
+ rec_pose = net_out["rec_pose"][:, :, :j*6]
+ rec_trans = net_out["rec_pose"][:, :, j*6:j*6+3] - net_out["rec_pose"][:, :, j*6:j*6+3]
+ # print(rec_trans.shape)
+ rec_x_trans = other_tools.velocity2position(rec_trans[:, :, 0:1], 1/self.args.pose_fps, tar_trans[:, 0, 0:1])
+ rec_z_trans = other_tools.velocity2position(rec_trans[:, :, 2:3], 1/self.args.pose_fps, tar_trans[:, 0, 2:3])
+ rec_y_trans = rec_trans[:,:,1:2]
+ rec_trans = torch.cat([rec_x_trans, rec_y_trans, rec_z_trans], dim=-1)
+ n = rec_pose.shape[1]
+ rec_trans = rec_trans.cpu().numpy().reshape(bs*n, 3)
+ tar_pose = tar_pose[:, :n, :]
+ rec_pose = rec_pose.reshape(bs, n, j, 6)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose)#
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+ rec_pose = rec_pose.cpu().numpy()
+ else:
+ pass
+# for i in range(tar_pose.shape[1]//(self.args.vae_test_len)):
+# tar_pose_new = tar_pose[:,i*(self.args.vae_test_len):i*(self.args.vae_test_len)+self.args.vae_test_len,:]
+# net_out = self.model(**dict(inputs=tar_pose_new))
+# rec_pose = net_out["rec_pose"]
+# rec_pose = (rec_pose.reshape(rec_pose.shape[0], rec_pose.shape[1], -1, 6) * self.joint_level_mask_cuda).reshape(rec_pose.shape[0], rec_pose.shape[1], -1)
+# if "rot6d" in self.args.pose_rep:
+# rec_pose = data_transfer.rotation_6d_to_matrix(rec_pose.reshape(tar_pose.shape[0], self.args.vae_test_len, -1, 6))
+# rec_pose = data_transfer.matrix_to_euler_angles(rec_pose, "XYZ").reshape(rec_pose.shape[0], rec_pose.shape[1], -1)
+# if "smplx" not in self.args.pose_rep:
+# rec_pose = torch.rad2deg(rec_pose)
+# rec_pose = rec_pose * self.joint_mask_cuda
+
+# out_sub = rec_pose.cpu().numpy().reshape(-1, rec_pose.shape[2])
+# if i != 0:
+# out_final = np.concatenate((out_final,out_sub), 0)
+# else:
+# out_final = out_sub
+
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs, n, j, 6))
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+ tar_pose = tar_pose.cpu().numpy()
+
+ total_length += n
+ # --- save --- #
+ if 'smplx' in self.args.pose_rep:
+ gt_npz = np.load(self.args.data_path+self.args.pose_rep+"/"+test_seq_list.iloc[its]['id']+'.npz', allow_pickle=True)
+ stride = int(30 / self.args.pose_fps)
+ tar_pose = self.inverse_selection(tar_pose, self.test_data.joint_mask, tar_pose.shape[0])
+ np.savez(results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=tar_pose[:n],
+ expressions=gt_npz["expressions"]-gt_npz["expressions"],
+ trans=rec_trans-rec_trans,
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30 ,
+ )
+ rec_pose = self.inverse_selection(rec_pose, self.test_data.joint_mask, rec_pose.shape[0])
+ np.savez(results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=rec_pose,
+ expressions=gt_npz["expressions"]-gt_npz["expressions"],
+ trans=rec_trans-rec_trans,
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30 ,
+ )
+ else:
+ rec_pose = rc.axis_angle_to_matrix(torch.from_numpy(rec_pose.reshape(bs*n, j, 3)))
+ rec_pose = np.rad2deg(rc.matrix_to_euler_angles(rec_pose, "XYZ")).reshape(bs*n, j*3).numpy()
+ tar_pose = rc.axis_angle_to_matrix(torch.from_numpy(tar_pose.reshape(bs*n, j, 3)))
+ tar_pose = np.rad2deg(rc.matrix_to_euler_angles(tar_pose, "XYZ")).reshape(bs*n, j*3).numpy()
+ #trans="0.000000 0.000000 0.000000"
+
+ with open(f"{self.args.data_path}{self.args.pose_rep}/{test_seq_list.iloc[its]['id']}.bvh", "r") as f_demo:
+ with open(results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.bvh', 'w+') as f_gt:
+ with open(results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.bvh', 'w+') as f_real:
+ for i, line_data in enumerate(f_demo.readlines()):
+ if i < 431:
+ f_real.write(line_data)
+ f_gt.write(line_data)
+ else: break
+ for line_id in range(n): #,args.pre_frames, args.pose_length
+ line_data = np.array2string(rec_pose[line_id], max_line_width=np.inf, precision=6, suppress_small=False, separator=' ')
+ f_real.write(line_data[1:-2]+'\n')
+ for line_id in range(n): #,args.pre_frames, args.pose_length
+ line_data = np.array2string(tar_pose[line_id], max_line_width=np.inf, precision=6, suppress_small=False, separator=' ')
+ f_gt.write(line_data[1:-2]+'\n')
+ # with open(results_save_path+"gt_"+test_seq_list[its]+'.pkl', 'wb') as fw:
+ # pickle.dump(new_dict, fw)
+ # #new_dict2["fullpose"] = out_final
+ # with open(results_save_path+"res_"+test_seq_list[its]+'.pkl', 'wb') as fw1:
+ # pickle.dump(new_dict2, fw1)
+
+ # other_tools.render_one_sequence(
+ # results_save_path+"res_"+test_seq_list[its]+'.pkl',
+ # results_save_path+"gt_"+test_seq_list[its]+'.pkl',
+ # results_save_path,
+ # self.args.data_path + self.args.test_data_path + 'wave16k/' + test_seq_list[its]+'.npy',
+ # )
+
+ #if its == 1:break
+ end_time = time.time() - start_time
+ logger.info(f"total inference time: {int(end_time)} s for {int(total_length/self.args.pose_fps)} s motion")
\ No newline at end of file
diff --git a/app.py b/app.py
new file mode 100644
index 0000000000000000000000000000000000000000..11a141959a6f3b4638139e16772a0fa4431e69e4
--- /dev/null
+++ b/app.py
@@ -0,0 +1,664 @@
+import spaces
+import os
+# os.system("Xvfb :99 -ac &")
+# os.environ["DISPLAY"] = ":99"
+import OpenGL.GL as gl
+os.environ["PYOPENGL_PLATFORM"] = "egl"
+os.environ["MESA_GL_VERSION_OVERRIDE"] = "4.1"
+import signal
+import time
+import csv
+import sys
+import warnings
+import random
+import gradio as gr
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+import torch.distributed as dist
+from torch.nn.parallel import DistributedDataParallel as DDP
+import torch.multiprocessing as mp
+import numpy as np
+import time
+import pprint
+from loguru import logger
+import smplx
+from torch.utils.tensorboard import SummaryWriter
+import wandb
+import matplotlib.pyplot as plt
+from utils import config, logger_tools, other_tools_hf, metric, data_transfer
+from dataloaders import data_tools
+from dataloaders.build_vocab import Vocab
+from optimizers.optim_factory import create_optimizer
+from optimizers.scheduler_factory import create_scheduler
+from optimizers.loss_factory import get_loss_func
+from dataloaders.data_tools import joints_list
+from utils import rotation_conversions as rc
+import soundfile as sf
+import librosa
+
+def inverse_selection_tensor(filtered_t, selection_array, n):
+ selection_array = torch.from_numpy(selection_array).cuda()
+ original_shape_t = torch.zeros((n, 165)).cuda()
+ selected_indices = torch.where(selection_array == 1)[0]
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+ return original_shape_t
+
+@spaces.GPU(duration=120)
+def test_demo_gpu(
+ model, vq_model_face, vq_model_upper, vq_model_hands, vq_model_lower, global_motion, smplx_model,
+ dict_data,
+ args,
+ joints, joint_mask_upper, joint_mask_lower, joint_mask_hands,
+ log_softmax,
+):
+ rank = 0
+ other_tools_hf.load_checkpoints(vq_model_face, args.data_path_1 + "pretrained_vq/last_790_face_v2.bin", args.e_name)
+ other_tools_hf.load_checkpoints(vq_model_upper, args.data_path_1 + "pretrained_vq/upper_vertex_1layer_710.bin", args.e_name)
+ other_tools_hf.load_checkpoints(vq_model_hands, args.data_path_1 + "pretrained_vq/hands_vertex_1layer_710.bin", args.e_name)
+ other_tools_hf.load_checkpoints(vq_model_lower, args.data_path_1 + "pretrained_vq/lower_foot_600.bin", args.e_name)
+ other_tools_hf.load_checkpoints(global_motion, args.data_path_1 + "pretrained_vq/last_1700_foot.bin", args.e_name)
+ other_tools_hf.load_checkpoints(model, args.test_ckpt, args.g_name)
+ model.to(rank).eval()
+ smplx_model.to(rank).eval()
+ vq_model_face.to(rank).eval()
+ vq_model_upper.to(rank).eval()
+ vq_model_hands.to(rank).eval()
+ vq_model_lower.to(rank).eval()
+ global_motion.to(rank).eval()
+
+ with torch.no_grad():
+ tar_pose_raw = dict_data["pose"]
+ tar_pose = tar_pose_raw[:, :, :165].to(rank)
+ tar_contact = tar_pose_raw[:, :, 165:169].to(rank)
+ tar_trans = dict_data["trans"].to(rank)
+ tar_exps = dict_data["facial"].to(rank)
+ in_audio = dict_data["audio"].to(rank)
+ in_word = None# dict_data["word"].to(rank)
+ tar_beta = dict_data["beta"].to(rank)
+ tar_id = dict_data["id"].to(rank).long()
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], joints
+
+ tar_pose_jaw = tar_pose[:, :, 66:69]
+ tar_pose_jaw = rc.axis_angle_to_matrix(tar_pose_jaw.reshape(bs, n, 1, 3))
+ tar_pose_jaw = rc.matrix_to_rotation_6d(tar_pose_jaw).reshape(bs, n, 1*6)
+ tar_pose_face = torch.cat([tar_pose_jaw, tar_exps], dim=2)
+
+ tar_pose_hands = tar_pose[:, :, 25*3:55*3]
+ tar_pose_hands = rc.axis_angle_to_matrix(tar_pose_hands.reshape(bs, n, 30, 3))
+ tar_pose_hands = rc.matrix_to_rotation_6d(tar_pose_hands).reshape(bs, n, 30*6)
+
+ tar_pose_upper = tar_pose[:, :, joint_mask_upper.astype(bool)]
+ tar_pose_upper = rc.axis_angle_to_matrix(tar_pose_upper.reshape(bs, n, 13, 3))
+ tar_pose_upper = rc.matrix_to_rotation_6d(tar_pose_upper).reshape(bs, n, 13*6)
+
+ tar_pose_leg = tar_pose[:, :, joint_mask_lower.astype(bool)]
+ tar_pose_leg = rc.axis_angle_to_matrix(tar_pose_leg.reshape(bs, n, 9, 3))
+ tar_pose_leg = rc.matrix_to_rotation_6d(tar_pose_leg).reshape(bs, n, 9*6)
+ tar_pose_lower = torch.cat([tar_pose_leg, tar_trans, tar_contact], dim=2)
+
+ # tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ # tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ tar4dis = torch.cat([tar_pose_jaw, tar_pose_upper, tar_pose_hands, tar_pose_leg], dim=2)
+
+ tar_index_value_face_top = vq_model_face.map2index(tar_pose_face) # bs*n/4
+ tar_index_value_upper_top = vq_model_upper.map2index(tar_pose_upper) # bs*n/4
+ tar_index_value_hands_top = vq_model_hands.map2index(tar_pose_hands) # bs*n/4
+ tar_index_value_lower_top = vq_model_lower.map2index(tar_pose_lower) # bs*n/4
+
+ latent_face_top = vq_model_face.map2latent(tar_pose_face) # bs*n/4
+ latent_upper_top = vq_model_upper.map2latent(tar_pose_upper) # bs*n/4
+ latent_hands_top = vq_model_hands.map2latent(tar_pose_hands) # bs*n/4
+ latent_lower_top = vq_model_lower.map2latent(tar_pose_lower) # bs*n/4
+
+ latent_in = torch.cat([latent_upper_top, latent_hands_top, latent_lower_top], dim=2)
+
+ index_in = torch.stack([tar_index_value_upper_top, tar_index_value_hands_top, tar_index_value_lower_top], dim=-1).long()
+
+ tar_pose_6d = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, 55, 3))
+ tar_pose_6d = rc.matrix_to_rotation_6d(tar_pose_6d).reshape(bs, n, 55*6)
+ latent_all = torch.cat([tar_pose_6d, tar_trans, tar_contact], dim=-1)
+
+ loaded_data = {
+ "tar_pose_jaw": tar_pose_jaw,
+ "tar_pose_face": tar_pose_face,
+ "tar_pose_upper": tar_pose_upper,
+ "tar_pose_lower": tar_pose_lower,
+ "tar_pose_hands": tar_pose_hands,
+ 'tar_pose_leg': tar_pose_leg,
+ "in_audio": in_audio,
+ "in_word": in_word,
+ "tar_trans": tar_trans,
+ "tar_exps": tar_exps,
+ "tar_beta": tar_beta,
+ "tar_pose": tar_pose,
+ "tar4dis": tar4dis,
+ "tar_index_value_face_top": tar_index_value_face_top,
+ "tar_index_value_upper_top": tar_index_value_upper_top,
+ "tar_index_value_hands_top": tar_index_value_hands_top,
+ "tar_index_value_lower_top": tar_index_value_lower_top,
+ "latent_face_top": latent_face_top,
+ "latent_upper_top": latent_upper_top,
+ "latent_hands_top": latent_hands_top,
+ "latent_lower_top": latent_lower_top,
+ "latent_in": latent_in,
+ "index_in": index_in,
+ "tar_id": tar_id,
+ "latent_all": latent_all,
+ "tar_pose_6d": tar_pose_6d,
+ "tar_contact": tar_contact,
+ }
+
+ mode = 'test'
+ bs, n, j = loaded_data["tar_pose"].shape[0], loaded_data["tar_pose"].shape[1], joints
+ tar_pose = loaded_data["tar_pose"]
+ tar_beta = loaded_data["tar_beta"]
+ in_word =None# loaded_data["in_word"]
+ tar_exps = loaded_data["tar_exps"]
+ tar_contact = loaded_data["tar_contact"]
+ in_audio = loaded_data["in_audio"]
+ tar_trans = loaded_data["tar_trans"]
+
+ remain = n%8
+ if remain != 0:
+ tar_pose = tar_pose[:, :-remain, :]
+ tar_beta = tar_beta[:, :-remain, :]
+ tar_trans = tar_trans[:, :-remain, :]
+ # in_word = in_word[:, :-remain]
+ tar_exps = tar_exps[:, :-remain, :]
+ tar_contact = tar_contact[:, :-remain, :]
+ n = n - remain
+
+ tar_pose_jaw = tar_pose[:, :, 66:69]
+ tar_pose_jaw = rc.axis_angle_to_matrix(tar_pose_jaw.reshape(bs, n, 1, 3))
+ tar_pose_jaw = rc.matrix_to_rotation_6d(tar_pose_jaw).reshape(bs, n, 1*6)
+ tar_pose_face = torch.cat([tar_pose_jaw, tar_exps], dim=2)
+
+ tar_pose_hands = tar_pose[:, :, 25*3:55*3]
+ tar_pose_hands = rc.axis_angle_to_matrix(tar_pose_hands.reshape(bs, n, 30, 3))
+ tar_pose_hands = rc.matrix_to_rotation_6d(tar_pose_hands).reshape(bs, n, 30*6)
+
+ tar_pose_upper = tar_pose[:, :, joint_mask_upper.astype(bool)]
+ tar_pose_upper = rc.axis_angle_to_matrix(tar_pose_upper.reshape(bs, n, 13, 3))
+ tar_pose_upper = rc.matrix_to_rotation_6d(tar_pose_upper).reshape(bs, n, 13*6)
+
+ tar_pose_leg = tar_pose[:, :, joint_mask_lower.astype(bool)]
+ tar_pose_leg = rc.axis_angle_to_matrix(tar_pose_leg.reshape(bs, n, 9, 3))
+ tar_pose_leg = rc.matrix_to_rotation_6d(tar_pose_leg).reshape(bs, n, 9*6)
+ tar_pose_lower = torch.cat([tar_pose_leg, tar_trans, tar_contact], dim=2)
+
+ tar_pose_6d = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, 55, 3))
+ tar_pose_6d = rc.matrix_to_rotation_6d(tar_pose_6d).reshape(bs, n, 55*6)
+ latent_all = torch.cat([tar_pose_6d, tar_trans, tar_contact], dim=-1)
+
+ rec_index_all_face = []
+ rec_index_all_upper = []
+ rec_index_all_lower = []
+ rec_index_all_hands = []
+
+ roundt = (n - args.pre_frames) // (args.pose_length - args.pre_frames)
+ remain = (n - args.pre_frames) % (args.pose_length - args.pre_frames)
+ round_l = args.pose_length - args.pre_frames
+
+ for i in range(0, roundt):
+ # in_word_tmp = in_word[:, i*(round_l):(i+1)*(round_l)+args.pre_frames]
+ # audio fps is 16000 and pose fps is 30
+ in_audio_tmp = in_audio[:, i*(16000//30*round_l):(i+1)*(16000//30*round_l)+16000//30*args.pre_frames]
+ in_id_tmp = loaded_data['tar_id'][:, i*(round_l):(i+1)*(round_l)+args.pre_frames]
+ mask_val = torch.ones(bs, args.pose_length, args.pose_dims+3+4).float().cuda()
+ mask_val[:, :args.pre_frames, :] = 0.0
+ if i == 0:
+ latent_all_tmp = latent_all[:, i*(round_l):(i+1)*(round_l)+args.pre_frames, :]
+ else:
+ latent_all_tmp = latent_all[:, i*(round_l):(i+1)*(round_l)+args.pre_frames, :]
+ # print(latent_all_tmp.shape, latent_last.shape)
+ latent_all_tmp[:, :args.pre_frames, :] = latent_last[:, -args.pre_frames:, :]
+
+ net_out_val = model(
+ in_audio = in_audio_tmp,
+ in_word=None, #in_word_tmp,
+ mask=mask_val,
+ in_motion = latent_all_tmp,
+ in_id = in_id_tmp,
+ use_attentions=True,)
+
+ if args.cu != 0:
+ rec_index_upper = log_softmax(net_out_val["cls_upper"]).reshape(-1, args.vae_codebook_size)
+ _, rec_index_upper = torch.max(rec_index_upper.reshape(-1, args.pose_length, args.vae_codebook_size), dim=2)
+ #rec_upper = vq_model_upper.decode(rec_index_upper)
+ else:
+ _, rec_index_upper, _, _ = vq_model_upper.quantizer(net_out_val["rec_upper"])
+ #rec_upper = vq_model_upper.decoder(rec_index_upper)
+ if args.cl != 0:
+ rec_index_lower = log_softmax(net_out_val["cls_lower"]).reshape(-1, args.vae_codebook_size)
+ _, rec_index_lower = torch.max(rec_index_lower.reshape(-1, args.pose_length, args.vae_codebook_size), dim=2)
+ #rec_lower = vq_model_lower.decode(rec_index_lower)
+ else:
+ _, rec_index_lower, _, _ = vq_model_lower.quantizer(net_out_val["rec_lower"])
+ #rec_lower = vq_model_lower.decoder(rec_index_lower)
+ if args.ch != 0:
+ rec_index_hands = log_softmax(net_out_val["cls_hands"]).reshape(-1, args.vae_codebook_size)
+ _, rec_index_hands = torch.max(rec_index_hands.reshape(-1, args.pose_length, args.vae_codebook_size), dim=2)
+ #rec_hands = vq_model_hands.decode(rec_index_hands)
+ else:
+ _, rec_index_hands, _, _ = vq_model_hands.quantizer(net_out_val["rec_hands"])
+ #rec_hands = vq_model_hands.decoder(rec_index_hands)
+ if args.cf != 0:
+ rec_index_face = log_softmax(net_out_val["cls_face"]).reshape(-1, args.vae_codebook_size)
+ _, rec_index_face = torch.max(rec_index_face.reshape(-1, args.pose_length, args.vae_codebook_size), dim=2)
+ #rec_face = vq_model_face.decoder(rec_index_face)
+ else:
+ _, rec_index_face, _, _ = vq_model_face.quantizer(net_out_val["rec_face"])
+ #rec_face = vq_model_face.decoder(rec_index_face)
+
+ if i == 0:
+ rec_index_all_face.append(rec_index_face)
+ rec_index_all_upper.append(rec_index_upper)
+ rec_index_all_lower.append(rec_index_lower)
+ rec_index_all_hands.append(rec_index_hands)
+ else:
+ rec_index_all_face.append(rec_index_face[:, args.pre_frames:])
+ rec_index_all_upper.append(rec_index_upper[:, args.pre_frames:])
+ rec_index_all_lower.append(rec_index_lower[:, args.pre_frames:])
+ rec_index_all_hands.append(rec_index_hands[:, args.pre_frames:])
+
+ if args.cu != 0:
+ rec_upper_last = vq_model_upper.decode(rec_index_upper)
+ else:
+ rec_upper_last = vq_model_upper.decoder(rec_index_upper)
+ if args.cl != 0:
+ rec_lower_last = vq_model_lower.decode(rec_index_lower)
+ else:
+ rec_lower_last = vq_model_lower.decoder(rec_index_lower)
+ if args.ch != 0:
+ rec_hands_last = vq_model_hands.decode(rec_index_hands)
+ else:
+ rec_hands_last = vq_model_hands.decoder(rec_index_hands)
+ # if args.cf != 0:
+ # rec_face_last = vq_model_face.decode(rec_index_face)
+ # else:
+ # rec_face_last = vq_model_face.decoder(rec_index_face)
+
+ rec_pose_legs = rec_lower_last[:, :, :54]
+ bs, n = rec_pose_legs.shape[0], rec_pose_legs.shape[1]
+ rec_pose_upper = rec_upper_last.reshape(bs, n, 13, 6)
+ rec_pose_upper = rc.rotation_6d_to_matrix(rec_pose_upper)#
+ rec_pose_upper = rc.matrix_to_axis_angle(rec_pose_upper).reshape(bs*n, 13*3)
+ rec_pose_upper_recover = inverse_selection_tensor(rec_pose_upper, joint_mask_upper, bs*n)
+ rec_pose_lower = rec_pose_legs.reshape(bs, n, 9, 6)
+ rec_pose_lower = rc.rotation_6d_to_matrix(rec_pose_lower)
+ rec_pose_lower = rc.matrix_to_axis_angle(rec_pose_lower).reshape(bs*n, 9*3)
+ rec_pose_lower_recover = inverse_selection_tensor(rec_pose_lower, joint_mask_lower, bs*n)
+ rec_pose_hands = rec_hands_last.reshape(bs, n, 30, 6)
+ rec_pose_hands = rc.rotation_6d_to_matrix(rec_pose_hands)
+ rec_pose_hands = rc.matrix_to_axis_angle(rec_pose_hands).reshape(bs*n, 30*3)
+ rec_pose_hands_recover = inverse_selection_tensor(rec_pose_hands, joint_mask_hands, bs*n)
+ rec_pose = rec_pose_upper_recover + rec_pose_lower_recover + rec_pose_hands_recover
+ rec_pose = rc.axis_angle_to_matrix(rec_pose.reshape(bs, n, j, 3))
+ rec_pose = rc.matrix_to_rotation_6d(rec_pose).reshape(bs, n, j*6)
+ rec_trans_v_s = rec_lower_last[:, :, 54:57]
+ rec_x_trans = other_tools_hf.velocity2position(rec_trans_v_s[:, :, 0:1], 1/args.pose_fps, tar_trans[:, 0, 0:1])
+ rec_z_trans = other_tools_hf.velocity2position(rec_trans_v_s[:, :, 2:3], 1/args.pose_fps, tar_trans[:, 0, 2:3])
+ rec_y_trans = rec_trans_v_s[:,:,1:2]
+ rec_trans = torch.cat([rec_x_trans, rec_y_trans, rec_z_trans], dim=-1)
+ latent_last = torch.cat([rec_pose, rec_trans, rec_lower_last[:, :, 57:61]], dim=-1)
+
+ rec_index_face = torch.cat(rec_index_all_face, dim=1)
+ rec_index_upper = torch.cat(rec_index_all_upper, dim=1)
+ rec_index_lower = torch.cat(rec_index_all_lower, dim=1)
+ rec_index_hands = torch.cat(rec_index_all_hands, dim=1)
+ if args.cu != 0:
+ rec_upper = vq_model_upper.decode(rec_index_upper)
+ else:
+ rec_upper = vq_model_upper.decoder(rec_index_upper)
+ if args.cl != 0:
+ rec_lower = vq_model_lower.decode(rec_index_lower)
+ else:
+ rec_lower = vq_model_lower.decoder(rec_index_lower)
+ if args.ch != 0:
+ rec_hands = vq_model_hands.decode(rec_index_hands)
+ else:
+ rec_hands = vq_model_hands.decoder(rec_index_hands)
+ if args.cf != 0:
+ rec_face = vq_model_face.decode(rec_index_face)
+ else:
+ rec_face = vq_model_face.decoder(rec_index_face)
+
+ rec_exps = rec_face[:, :, 6:]
+ rec_pose_jaw = rec_face[:, :, :6]
+ rec_pose_legs = rec_lower[:, :, :54]
+ bs, n = rec_pose_jaw.shape[0], rec_pose_jaw.shape[1]
+ rec_pose_upper = rec_upper.reshape(bs, n, 13, 6)
+ rec_pose_upper = rc.rotation_6d_to_matrix(rec_pose_upper)#
+ rec_pose_upper = rc.matrix_to_axis_angle(rec_pose_upper).reshape(bs*n, 13*3)
+ rec_pose_upper_recover = inverse_selection_tensor(rec_pose_upper, joint_mask_upper, bs*n)
+ rec_pose_lower = rec_pose_legs.reshape(bs, n, 9, 6)
+ rec_pose_lower = rc.rotation_6d_to_matrix(rec_pose_lower)
+ rec_lower2global = rc.matrix_to_rotation_6d(rec_pose_lower.clone()).reshape(bs, n, 9*6)
+ rec_pose_lower = rc.matrix_to_axis_angle(rec_pose_lower).reshape(bs*n, 9*3)
+ rec_pose_lower_recover = inverse_selection_tensor(rec_pose_lower, joint_mask_lower, bs*n)
+ rec_pose_hands = rec_hands.reshape(bs, n, 30, 6)
+ rec_pose_hands = rc.rotation_6d_to_matrix(rec_pose_hands)
+ rec_pose_hands = rc.matrix_to_axis_angle(rec_pose_hands).reshape(bs*n, 30*3)
+ rec_pose_hands_recover = inverse_selection_tensor(rec_pose_hands, joint_mask_hands, bs*n)
+ rec_pose_jaw = rec_pose_jaw.reshape(bs*n, 6)
+ rec_pose_jaw = rc.rotation_6d_to_matrix(rec_pose_jaw)
+ rec_pose_jaw = rc.matrix_to_axis_angle(rec_pose_jaw).reshape(bs*n, 1*3)
+ rec_pose = rec_pose_upper_recover + rec_pose_lower_recover + rec_pose_hands_recover
+ rec_pose[:, 66:69] = rec_pose_jaw
+
+ to_global = rec_lower
+ to_global[:, :, 54:57] = 0.0
+ to_global[:, :, :54] = rec_lower2global
+ rec_global = global_motion(to_global)
+
+ rec_trans_v_s = rec_global["rec_pose"][:, :, 54:57]
+ rec_x_trans = other_tools_hf.velocity2position(rec_trans_v_s[:, :, 0:1], 1/args.pose_fps, tar_trans[:, 0, 0:1])
+ rec_z_trans = other_tools_hf.velocity2position(rec_trans_v_s[:, :, 2:3], 1/args.pose_fps, tar_trans[:, 0, 2:3])
+ rec_y_trans = rec_trans_v_s[:,:,1:2]
+ rec_trans = torch.cat([rec_x_trans, rec_y_trans, rec_z_trans], dim=-1)
+ tar_pose = tar_pose[:, :n, :]
+ tar_exps = tar_exps[:, :n, :]
+ tar_trans = tar_trans[:, :n, :]
+ tar_beta = tar_beta[:, :n, :]
+
+ rec_pose = rc.axis_angle_to_matrix(rec_pose.reshape(bs*n, j, 3))
+ rec_pose = rc.matrix_to_rotation_6d(rec_pose).reshape(bs, n, j*6)
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs*n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+
+ net_out = {
+ 'rec_pose': rec_pose,
+ 'rec_trans': rec_trans,
+ 'tar_pose': tar_pose,
+ 'tar_exps': tar_exps,
+ 'tar_beta': tar_beta,
+ 'tar_trans': tar_trans,
+ 'rec_exps': rec_exps,
+ }
+
+
+ tar_pose = net_out['tar_pose']
+ rec_pose = net_out['rec_pose']
+ tar_exps = net_out['tar_exps']
+ tar_beta = net_out['tar_beta']
+ rec_trans = net_out['rec_trans']
+ tar_trans = net_out['tar_trans']
+ rec_exps = net_out['rec_exps']
+ # print(rec_pose.shape, tar_pose.shape)
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], joints
+ # interpolate to 30fps
+ if (30/args.pose_fps) != 1:
+ assert 30%args.pose_fps == 0
+ n *= int(30/args.pose_fps)
+ tar_pose = torch.nn.functional.interpolate(tar_pose.permute(0, 2, 1), scale_factor=30/args.pose_fps, mode='linear').permute(0,2,1)
+ rec_pose = torch.nn.functional.interpolate(rec_pose.permute(0, 2, 1), scale_factor=30/args.pose_fps, mode='linear').permute(0,2,1)
+
+ # print(rec_pose.shape, tar_pose.shape)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose.reshape(bs*n, j, 6))
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs*n, j, 6))
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+
+ return tar_pose, rec_pose, tar_exps, tar_beta, rec_trans, tar_trans, rec_exps, bs, n, j
+
+
+class BaseTrainer(object):
+ def __init__(self, args, sp, ap, tp):
+ hf_dir = "hf"
+ if not os.path.exists(args.out_path + "custom/" + hf_dir + "/"):
+ os.makedirs(args.out_path + "custom/" + hf_dir + "/")
+ sf.write(args.out_path + "custom/" + hf_dir + "/tmp.wav", ap[1][:ap[0]*8], ap[0])
+ self.audio_path = args.out_path + "custom/" + hf_dir + "/tmp.wav"
+ audio, ssr = librosa.load(self.audio_path)
+ ap = (ssr, audio)
+ self.args = args
+ self.rank = 0 # dist.get_rank()
+
+ #self.checkpoint_path = args.out_path + "custom/" + args.name + args.notes + "/" #wandb.run.dir #args.cache_path+args.out_path+"/"+args.name
+ self.checkpoint_path = args.out_path + "custom/" + hf_dir + "/"
+ if self.rank == 0:
+ self.test_data = __import__(f"dataloaders.{args.dataset}", fromlist=["something"]).CustomDataset(args, "test", smplx_path=sp, audio_path=ap, text_path=tp)
+ self.test_loader = torch.utils.data.DataLoader(
+ self.test_data,
+ batch_size=1,
+ shuffle=False,
+ num_workers=args.loader_workers,
+ drop_last=False,
+ )
+ logger.info(f"Init test dataloader success")
+ model_module = __import__(f"models.{args.model}", fromlist=["something"])
+
+ if args.ddp:
+ self.model = getattr(model_module, args.g_name)(args).to(self.rank)
+ process_group = torch.distributed.new_group()
+ self.model = torch.nn.SyncBatchNorm.convert_sync_batchnorm(self.model, process_group)
+ self.model = DDP(self.model, device_ids=[self.rank], output_device=self.rank,
+ broadcast_buffers=False, find_unused_parameters=False)
+ else:
+ self.model = torch.nn.DataParallel(getattr(model_module, args.g_name)(args), args.gpus).cpu()
+
+ if self.rank == 0:
+ logger.info(self.model)
+ logger.info(f"init {args.g_name} success")
+
+ self.smplx = smplx.create(
+ self.args.data_path_1+"smplx_models/",
+ model_type='smplx',
+ gender='NEUTRAL_2020',
+ use_face_contour=False,
+ num_betas=300,
+ num_expression_coeffs=100,
+ ext='npz',
+ use_pca=False,
+ )
+
+ self.args = args
+ self.joints = self.test_data.joints
+ self.ori_joint_list = joints_list[self.args.ori_joints]
+ self.tar_joint_list_face = joints_list["beat_smplx_face"]
+ self.tar_joint_list_upper = joints_list["beat_smplx_upper"]
+ self.tar_joint_list_hands = joints_list["beat_smplx_hands"]
+ self.tar_joint_list_lower = joints_list["beat_smplx_lower"]
+
+ self.joint_mask_face = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ self.joints = 55
+ for joint_name in self.tar_joint_list_face:
+ self.joint_mask_face[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ self.joint_mask_upper = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ for joint_name in self.tar_joint_list_upper:
+ self.joint_mask_upper[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ self.joint_mask_hands = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ for joint_name in self.tar_joint_list_hands:
+ self.joint_mask_hands[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ self.joint_mask_lower = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ for joint_name in self.tar_joint_list_lower:
+ self.joint_mask_lower[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+
+ self.tracker = other_tools_hf.EpochTracker(["fid", "l1div", "bc", "rec", "trans", "vel", "transv", 'dis', 'gen', 'acc', 'transa', 'exp', 'lvd', 'mse', "cls", "rec_face", "latent", "cls_full", "cls_self", "cls_word", "latent_word","latent_self"], [False,True,True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False,False,False,False])
+
+ vq_model_module = __import__(f"models.motion_representation", fromlist=["something"])
+ self.args.vae_layer = 2
+ self.args.vae_length = 256
+ self.args.vae_test_dim = 106
+ self.vq_model_face = getattr(vq_model_module, "VQVAEConvZero")(self.args).cpu()
+ # print(self.vq_model_face)
+ # other_tools_hf.load_checkpoints(self.vq_model_face, self.args.data_path_1 + "pretrained_vq/last_790_face_v2.bin", args.e_name)
+ self.args.vae_test_dim = 78
+ self.vq_model_upper = getattr(vq_model_module, "VQVAEConvZero")(self.args).cpu()
+ # other_tools_hf.load_checkpoints(self.vq_model_upper, self.args.data_path_1 + "pretrained_vq/upper_vertex_1layer_710.bin", args.e_name)
+ self.args.vae_test_dim = 180
+ self.vq_model_hands = getattr(vq_model_module, "VQVAEConvZero")(self.args).cpu()
+ # other_tools_hf.load_checkpoints(self.vq_model_hands, self.args.data_path_1 + "pretrained_vq/hands_vertex_1layer_710.bin", args.e_name)
+ self.args.vae_test_dim = 61
+ self.args.vae_layer = 4
+ self.vq_model_lower = getattr(vq_model_module, "VQVAEConvZero")(self.args).cpu()
+ # other_tools_hf.load_checkpoints(self.vq_model_lower, self.args.data_path_1 + "pretrained_vq/lower_foot_600.bin", args.e_name)
+ self.args.vae_test_dim = 61
+ self.args.vae_layer = 4
+ self.global_motion = getattr(vq_model_module, "VAEConvZero")(self.args).cpu()
+ # other_tools_hf.load_checkpoints(self.global_motion, self.args.data_path_1 + "pretrained_vq/last_1700_foot.bin", args.e_name)
+ self.args.vae_test_dim = 330
+ self.args.vae_layer = 4
+ self.args.vae_length = 240
+
+ # self.cls_loss = nn.NLLLoss().to(self.rank)
+ # self.reclatent_loss = nn.MSELoss().to(self.rank)
+ # self.vel_loss = torch.nn.L1Loss(reduction='mean').to(self.rank)
+ # self.rec_loss = get_loss_func("GeodesicLoss").to(self.rank)
+ self.log_softmax = nn.LogSoftmax(dim=2)
+
+
+ def inverse_selection(self, filtered_t, selection_array, n):
+ original_shape_t = np.zeros((n, selection_array.size))
+ selected_indices = np.where(selection_array == 1)[0]
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+ return original_shape_t
+
+ def inverse_selection_tensor(self, filtered_t, selection_array, n):
+ selection_array = torch.from_numpy(selection_array).cuda()
+ original_shape_t = torch.zeros((n, 165)).cuda()
+ selected_indices = torch.where(selection_array == 1)[0]
+ for i in range(n):
+ original_shape_t[i, selected_indices] = filtered_t[i]
+ return original_shape_t
+
+
+ def test_demo(self, epoch):
+ '''
+ input audio and text, output motion
+ do not calculate loss and metric
+ save video
+ '''
+ results_save_path = self.checkpoint_path + f"/{epoch}/"
+ if os.path.exists(results_save_path):
+ import shutil
+ shutil.rmtree(results_save_path)
+ os.makedirs(results_save_path)
+ start_time = time.time()
+ total_length = 0
+ test_seq_list = self.test_data.selected_file
+ align = 0
+ latent_out = []
+ latent_ori = []
+ l2_all = 0
+ lvel = 0
+ for its, batch_data in enumerate(self.test_loader):
+ tar_pose, rec_pose, tar_exps, tar_beta, rec_trans, tar_trans, rec_exps, bs, n, j = test_demo_gpu(
+ self.model, self.vq_model_face, self.vq_model_upper, self.vq_model_hands, self.vq_model_lower, self.global_motion, self.smplx,
+ batch_data,
+ self.args,
+ self.joints, self.joint_mask_upper, self.joint_mask_lower, self.joint_mask_hands,
+ self.log_softmax,
+ )
+
+ tar_pose_np = tar_pose.detach().cpu().numpy()
+ rec_pose_np = rec_pose.detach().cpu().numpy()
+ rec_trans_np = rec_trans.detach().cpu().numpy().reshape(bs*n, 3)
+ rec_exp_np = rec_exps.detach().cpu().numpy().reshape(bs*n, 100)
+ tar_exp_np = tar_exps.detach().cpu().numpy().reshape(bs*n, 100)
+ tar_trans_np = tar_trans.detach().cpu().numpy().reshape(bs*n, 3)
+ #'''
+ # its = 0
+ gt_npz = np.load(self.args.data_path+self.args.pose_rep +"/"+test_seq_list.iloc[its]['id']+".npz", allow_pickle=True)
+ np.savez(results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=tar_pose_np,
+ expressions=tar_exp_np,
+ trans=tar_trans_np,
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30,
+ )
+ np.savez(results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=rec_pose_np,
+ expressions=rec_exp_np,
+ trans=rec_trans_np,
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30,
+ )
+
+ total_length += n
+ render_vid_path = other_tools_hf.render_one_sequence_no_gt(
+ results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.npz',
+ # results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.npz',
+ results_save_path,
+ self.audio_path,
+ self.args.data_path_1+"smplx_models/",
+ use_matplotlib = False,
+ args = self.args,
+ )
+ result = gr.Video(value=render_vid_path, visible=True)
+ end_time = time.time() - start_time
+ logger.info(f"total inference time: {int(end_time)} s for {int(total_length/self.args.pose_fps)} s motion")
+ return result
+
+
+@logger.catch
+def emage(audio_path):
+ smplx_path = None
+ text_path = None
+ rank = 0
+ world_size = 1
+ args = config.parse_args()
+ #os.environ['TRANSFORMERS_CACHE'] = args.data_path_1 + "hub/"
+ if not sys.warnoptions:
+ warnings.simplefilter("ignore")
+ # dist.init_process_group(backend="gloo", rank=rank, world_size=world_size)
+
+ #logger_tools.set_args_and_logger(args, rank)
+ other_tools_hf.set_random_seed(args)
+ other_tools_hf.print_exp_info(args)
+
+ # return one intance of trainer
+ trainer = BaseTrainer(args, sp = smplx_path, ap = audio_path, tp = text_path)
+ result = trainer.test_demo(999)
+ return result
+
+examples = [
+ ["./EMAGE/test_sequences/wave16k/2_scott_0_1_1.wav"],
+ ["./EMAGE/test_sequences/wave16k/2_scott_0_2_2.wav"],
+ ["./EMAGE/test_sequences/wave16k/2_scott_0_3_3.wav"],
+]
+
+demo = gr.Interface(
+ emage, # function
+ inputs=[
+ # gr.File(label="Please upload SMPL-X file with npz format here.", file_types=["npz", "NPZ"]),
+ gr.Audio(),
+ # gr.File(label="Please upload textgrid format file here.", file_types=["TextGrid", "Textgrid", "textgrid"])
+ ], # input type
+ outputs=gr.Video(format="mp4", visible=True),
+ title='\
+ \
+ EMAGE: Towards Unified Holistic Co-Speech Gesture Generation via Expressive Masked Audio Gesture Modeling \
+ CVPR 2024 \
+
',
+ description='\
+ \
+ Haiyang Liu1*, Zihao Zhu2*, Giorgio Becherini3, Yichen Peng4, Mingyang Su5, \
+ You Zhou, Xuefei Zhe, Naoya Iwamoto, Bo Zheng, Michael J. Black3 \
+ (*Equal Contribution) \
+ 1The University of Tokyo, 2Keio University, 4Japan Advanced Institute of Science and Technology, \
+ 3Max Planck Institute for Intelligent Systems, 5Tsinghua University \
+
\
+ ',
+ article="\
+ Due to the limited resources in this space, we process the first 8s of your uploaded audio. \
+ Try to develop this space locally for longer motion generation, e.g., 60s. \
+ Relevant links: [Project Page (https://pantomatrix.github.io/EMAGE/)\
+ ",
+ examples=examples,
+)
+
+
+if __name__ == "__main__":
+ os.environ["MASTER_ADDR"]='127.0.0.1'
+ os.environ["MASTER_PORT"]='8675'
+ #os.environ["TORCH_DISTRIBUTED_DEBUG"] = "DETAIL"
+ demo.launch(share=True)
\ No newline at end of file
diff --git a/camn_trainer.py b/camn_trainer.py
new file mode 100644
index 0000000000000000000000000000000000000000..c62fc207d2e58d27669a476ec90cadc10958baad
--- /dev/null
+++ b/camn_trainer.py
@@ -0,0 +1,361 @@
+import train
+import os
+import time
+import csv
+import sys
+import warnings
+import random
+import numpy as np
+import time
+import pprint
+import pickle
+
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+from torch.utils.tensorboard import SummaryWriter
+from torch.nn.parallel import DistributedDataParallel as DDP
+from loguru import logger
+import smplx
+import librosa
+
+from utils import config, logger_tools, other_tools, metric
+from utils import rotation_conversions as rc
+from dataloaders import data_tools
+from optimizers.optim_factory import create_optimizer
+from optimizers.scheduler_factory import create_scheduler
+from optimizers.loss_factory import get_loss_func
+from scipy.spatial.transform import Rotation
+
+
+class CustomTrainer(train.BaseTrainer):
+ def __init__(self, args):
+ super().__init__(args)
+ self.joints = self.train_data.joints
+ self.tracker = other_tools.EpochTracker(["fid", "l1div", "bc", "rec", "trans", "vel", "transv", 'dis', 'gen', 'acc', 'transa', 'div_reg', "kl"], [False,True,True, False, False, False, False, False, False, False, False, False, False])
+ if not self.args.rot6d: #"rot6d" not in args.pose_rep:
+ logger.error(f"this script is for rot6d, your pose rep. is {args.pose_rep}")
+ self.rec_loss = get_loss_func("GeodesicLoss").to(self.rank)
+ self.vel_loss = torch.nn.L1Loss(reduction='mean').to(self.rank)
+
+ def _load_data(self, dict_data):
+ tar_pose = dict_data["pose"].to(self.rank)
+ tar_trans = dict_data["trans"].to(self.rank)
+ tar_exps = dict_data["facial"].to(self.rank)
+ tar_beta = dict_data["beta"].to(self.rank)
+ tar_id = dict_data["id"].to(self.rank).long()
+ tar_word = dict_data["word"].to(self.rank)
+ in_audio = dict_data["audio"].to(self.rank)
+ in_emo = dict_data["emo"].to(self.rank)
+ #in_sem = dict_data["sem"].to(self.rank)
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], self.joints
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, j, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ in_pre_pose_cat = torch.cat([tar_pose[:, 0:self.args.pre_frames], tar_trans[:, :self.args.pre_frames]], dim=2).to(self.rank)
+
+ in_pre_pose = tar_pose.new_zeros((bs, n, j*6+1+3)).to(self.rank)
+ in_pre_pose[:, 0:self.args.pre_frames, :-1] = in_pre_pose_cat[:, 0:self.args.pre_frames]
+ in_pre_pose[:, 0:self.args.pre_frames, -1] = 1
+ return {
+ "tar_pose": tar_pose,
+ "in_audio": in_audio,
+ "in_motion": in_pre_pose,
+ "tar_trans": tar_trans,
+ "tar_exps": tar_exps,
+ "tar_beta": tar_beta,
+ "tar_word": tar_word,
+ 'tar_id': tar_id,
+ 'in_emo': in_emo,
+ #'in_sem': in_sem,
+ }
+
+ def _d_training(self, loaded_data):
+ bs, n, j = loaded_data["tar_pose"].shape[0], loaded_data["tar_pose"].shape[1], self.joints
+ net_out = self.model(in_audio = loaded_data['in_audio'], pre_seq = loaded_data["in_motion"], in_text=loaded_data["tar_word"], in_id=loaded_data["tar_id"], in_emo=loaded_data["in_emo"], in_facial = loaded_data["tar_exps"])
+ rec_pose = net_out["rec_pose"][:, :, :j*6]
+ # rec_trans = net_out["rec_pose"][:, :, j*6:j*6+3]
+
+ rec_pose = rec_pose.reshape(bs, n, j, 6)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose)
+ rec_pose = rc.matrix_to_rotation_6d(rec_pose).reshape(bs, n, j*6)
+ tar_pose = rc.rotation_6d_to_matrix(loaded_data["tar_pose"].reshape(bs, n, j, 6))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ out_d_fake = self.d_model(rec_pose)
+ out_d_real = self.d_model(tar_pose)
+
+ d_loss_adv = torch.sum(-torch.mean(torch.log(out_d_real + 1e-8) + torch.log(1 - out_d_fake + 1e-8)))
+ self.tracker.update_meter("dis", "train", d_loss_adv.item())
+ return d_loss_adv
+
+ def _g_training(self, loaded_data, use_adv, mode="train"):
+ bs, n, j = loaded_data["tar_pose"].shape[0], loaded_data["tar_pose"].shape[1], self.joints
+ net_out = self.model(in_audio = loaded_data['in_audio'], pre_seq = loaded_data["in_motion"], in_text=loaded_data["tar_word"], in_id=loaded_data["tar_id"], in_emo=loaded_data["in_emo"], in_facial = loaded_data["tar_exps"])
+ rec_pose = net_out["rec_pose"][:, :, :j*6]
+ rec_trans = net_out["rec_pose"][:, :, j*6:j*6+3]
+ # print(rec_pose.shape, bs, n, j, loaded_data['in_audio'].shape, loaded_data["in_motion"].shape)
+ rec_pose = rec_pose.reshape(bs, n, j, 6)
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose)
+ tar_pose = rc.rotation_6d_to_matrix(loaded_data["tar_pose"].reshape(bs, n, j, 6))
+
+ rec_loss = self.rec_loss(tar_pose, rec_pose)
+ rec_loss *= self.args.rec_weight
+ self.tracker.update_meter("rec", mode, rec_loss.item())
+ # rec_loss_vel = self.vel_loss(rec_pose[:, 1:] - rec_pose[:, :-1], tar_pose[:, 1:] - tar_pose[:, :-1])
+ # self.tracker.update_meter("vel", mode, rec_loss_vel.item())
+ # rec_loss_acc = self.vel_loss(rec_pose[:, 2:] - 2*rec_pose[:, 1:-1] + rec_pose[:, :-2], tar_pose[:, 2:] - 2*tar_pose[:, 1:-1] + tar_pose[:, :-2])
+ # self.tracker.update_meter("acc", mode, rec_loss_acc.item())
+
+ rec_pose = rc.matrix_to_rotation_6d(rec_pose).reshape(bs, n, j*6)
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ if self.args.pose_dims < 330 and mode != "train":
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose.reshape(bs, n, j, 6))
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs, n, j*3)
+ rec_pose = self.inverse_selection_tensor(rec_pose, self.train_data.joint_mask, rec_pose.shape[0])
+ rec_pose = rc.axis_angle_to_matrix(rec_pose.reshape(bs, n, 55, 3))
+ rec_pose = rc.matrix_to_rotation_6d(rec_pose).reshape(bs, n, 55*6)
+
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs, n, j, 6))
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs, n, j*3)
+ tar_pose = self.inverse_selection_tensor(tar_pose, self.train_data.joint_mask, tar_pose.shape[0])
+ tar_pose = rc.axis_angle_to_matrix(tar_pose.reshape(bs, n, 55, 3))
+ tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, 55*6)
+ if use_adv and mode == 'train':
+ out_d_fake = self.d_model(rec_pose)
+ d_loss_adv = -torch.mean(torch.log(out_d_fake + 1e-8))
+ self.tracker.update_meter("gen", mode, d_loss_adv.item())
+ else:
+ d_loss_adv = 0
+
+ if self.args.train_trans:
+ trans_loss = self.vel_loss(rec_trans, loaded_data["tar_trans"])
+ trans_loss *= self.args.rec_weight
+ self.tracker.update_meter("trans", mode, trans_loss.item())
+ else:
+ trans_loss = 0
+ # trans_loss_vel = self.vel_loss(rec_trans[:, 1:] - rec_trans[:, :-1], loaded_data["tar_trans"][:, 1:] - loaded_data["tar_trans"][:, :-1])
+ # self.tracker.update_meter("transv", mode, trans_loss_vel.item())
+ # trans_loss_acc = self.vel_loss(rec_trans[:, 2:] - 2*rec_trans[:, 1:-1] + rec_trans[:, :-2], loaded_data["tar_trans"][:, 2:] - 2*loaded_data["tar_trans"][:, 1:-1] + loaded_data["tar_trans"][:, :-2])
+ # self.tracker.update_meter("transa", mode, trans_loss_acc.item())
+
+ if mode == 'train':
+ return d_loss_adv + rec_loss + trans_loss # + rec_loss_vel + rec_loss_acc + trans_loss_vel + trans_loss_acc
+ elif mode == 'val':
+ return {
+ 'rec_pose': rec_pose,
+ 'rec_trans': rec_trans,
+ 'tar_pose': tar_pose,
+ }
+ else:
+ return {
+ 'rec_pose': rec_pose,
+ 'rec_trans': rec_trans,
+ 'tar_pose': tar_pose,
+ 'tar_exps': loaded_data["tar_exps"],
+ 'tar_beta': loaded_data["tar_beta"],
+ 'tar_trans': loaded_data["tar_trans"],
+ }
+
+ def train(self, epoch):
+ use_adv = bool(epoch>=self.args.no_adv_epoch)
+ self.model.train()
+ self.d_model.train()
+ self.tracker.reset()
+ t_start = time.time()
+ for its, batch_data in enumerate(self.train_loader):
+ loaded_data = self._load_data(batch_data)
+ t_data = time.time() - t_start
+
+ if use_adv:
+ d_loss_final = 0
+ self.opt_d.zero_grad()
+ d_loss_adv = self._d_training(loaded_data)
+ d_loss_final += d_loss_adv
+ d_loss_final.backward()
+ self.opt_d.step()
+
+ self.opt.zero_grad()
+ g_loss_final = 0
+ g_loss_final += self._g_training(loaded_data, use_adv, 'train')
+ g_loss_final.backward()
+ self.opt.step()
+
+ mem_cost = torch.cuda.memory_cached() / 1E9
+ lr_g = self.opt.param_groups[0]['lr']
+ lr_d = self.opt_d.param_groups[0]['lr']
+ t_train = time.time() - t_start - t_data
+ t_start = time.time()
+ if its % self.args.log_period == 0:
+ self.train_recording(epoch, its, t_data, t_train, mem_cost, lr_g, lr_d=lr_d)
+ if self.args.debug:
+ if its == 1: break
+ self.opt_s.step(epoch)
+ self.opt_d_s.step(epoch)
+
+
+ def val(self, epoch):
+ self.model.eval()
+ self.d_model.eval()
+ with torch.no_grad():
+ for its, batch_data in enumerate(self.train_loader):
+ loaded_data = self._load_data(batch_data)
+ net_out = self._g_training(loaded_data, False, 'val')
+ tar_pose = net_out['tar_pose']
+ rec_pose = net_out['rec_pose']
+ n = tar_pose.shape[1]
+ if (30/self.args.pose_fps) != 1:
+ assert 30%self.args.pose_fps == 0
+ n *= int(30/self.args.pose_fps)
+ tar_pose = torch.nn.functional.interpolate(tar_pose.permute(0, 2, 1), scale_factor=30/self.args.pose_fps, mode='linear').permute(0,2,1)
+ rec_pose = torch.nn.functional.interpolate(rec_pose.permute(0, 2, 1), scale_factor=30/self.args.pose_fps, mode='linear').permute(0,2,1)
+ n = tar_pose.shape[1]
+ remain = n%self.args.vae_test_len
+ tar_pose = tar_pose[:, :n-remain, :]
+ rec_pose = rec_pose[:, :n-remain, :]
+ latent_out = self.eval_copy.map2latent(rec_pose).reshape(-1, self.args.vae_length).cpu().numpy()
+ latent_ori = self.eval_copy.map2latent(tar_pose).reshape(-1, self.args.vae_length).cpu().numpy()
+ if its == 0:
+ latent_out_motion_all = latent_out
+ latent_ori_all = latent_ori
+ else:
+ latent_out_motion_all = np.concatenate([latent_out_motion_all, latent_out], axis=0)
+ latent_ori_all = np.concatenate([latent_ori_all, latent_ori], axis=0)
+ if self.args.debug:
+ if its == 1: break
+ fid_motion = data_tools.FIDCalculator.frechet_distance(latent_out_motion_all, latent_ori_all)
+ self.tracker.update_meter("fid", "val", fid_motion)
+ self.val_recording(epoch)
+
+ def test(self, epoch):
+ results_save_path = self.checkpoint_path + f"/{epoch}/"
+ if os.path.exists(results_save_path):
+ return 0
+ os.makedirs(results_save_path)
+ start_time = time.time()
+ total_length = 0
+ test_seq_list = self.test_data.selected_file
+ align = 0
+ latent_out = []
+ latent_ori = []
+ self.model.eval()
+ self.smplx.eval()
+ self.eval_copy.eval()
+ with torch.no_grad():
+ for its, batch_data in enumerate(self.test_loader):
+ loaded_data = self._load_data(batch_data)
+ net_out = self._g_training(loaded_data, False, 'test')
+ tar_pose = net_out['tar_pose']
+ rec_pose = net_out['rec_pose']
+ tar_exps = net_out['tar_exps']
+ tar_beta = net_out['tar_beta']
+ rec_trans = net_out['rec_trans']
+ tar_trans = net_out['tar_trans']
+ bs, n, j = tar_pose.shape[0], tar_pose.shape[1], 55
+ if (30/self.args.pose_fps) != 1:
+ assert 30%self.args.pose_fps == 0
+ n *= int(30/self.args.pose_fps)
+ tar_pose = torch.nn.functional.interpolate(tar_pose.permute(0, 2, 1), scale_factor=30/self.args.pose_fps, mode='linear').permute(0,2,1)
+ rec_pose = torch.nn.functional.interpolate(rec_pose.permute(0, 2, 1), scale_factor=30/self.args.pose_fps, mode='linear').permute(0,2,1)
+ tar_beta = torch.nn.functional.interpolate(tar_beta.permute(0, 2, 1), scale_factor=30/self.args.pose_fps, mode='linear').permute(0,2,1)
+ tar_exps = torch.nn.functional.interpolate(tar_exps.permute(0, 2, 1), scale_factor=30/self.args.pose_fps, mode='linear').permute(0,2,1)
+ tar_trans = torch.nn.functional.interpolate(tar_trans.permute(0, 2, 1), scale_factor=30/self.args.pose_fps, mode='linear').permute(0,2,1)
+ rec_trans = torch.nn.functional.interpolate(rec_trans.permute(0, 2, 1), scale_factor=30/self.args.pose_fps, mode='linear').permute(0,2,1)
+
+ # print(rec_pose.shape, tar_pose.shape)
+ # rec_pose = rc.rotation_6d_to_matrix(rec_pose.reshape(bs*n, j, 6))
+ # rec_pose = rc.matrix_to_rotation_6d(rec_pose).reshape(bs, n, j*6)
+ # tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs*n, j, 6))
+ # tar_pose = rc.matrix_to_rotation_6d(tar_pose).reshape(bs, n, j*6)
+ remain = n%self.args.vae_test_len
+ latent_out.append(self.eval_copy.map2latent(rec_pose[:, :n-remain]).reshape(-1, self.args.vae_length).detach().cpu().numpy()) # bs * n/8 * 240
+ latent_ori.append(self.eval_copy.map2latent(tar_pose[:, :n-remain]).reshape(-1, self.args.vae_length).detach().cpu().numpy())
+
+ rec_pose = rc.rotation_6d_to_matrix(rec_pose.reshape(bs*n, j, 6))
+ rec_pose = rc.matrix_to_axis_angle(rec_pose).reshape(bs*n, j*3)
+ tar_pose = rc.rotation_6d_to_matrix(tar_pose.reshape(bs*n, j, 6))
+ tar_pose = rc.matrix_to_axis_angle(tar_pose).reshape(bs*n, j*3)
+
+ vertices_rec = self.smplx(
+ betas=tar_beta.reshape(bs*n, 300),
+ transl=rec_trans.reshape(bs*n, 3)-rec_trans.reshape(bs*n, 3),
+ expression=tar_exps.reshape(bs*n, 100)-tar_exps.reshape(bs*n, 100),
+ jaw_pose=rec_pose[:, 66:69],
+ global_orient=rec_pose[:,:3],
+ body_pose=rec_pose[:,3:21*3+3],
+ left_hand_pose=rec_pose[:,25*3:40*3],
+ right_hand_pose=rec_pose[:,40*3:55*3],
+ return_joints=True,
+ leye_pose=rec_pose[:, 69:72],
+ reye_pose=rec_pose[:, 72:75],
+ )
+ # vertices_tar = self.smplx(
+ # betas=tar_beta.reshape(bs*n, 300),
+ # transl=rec_trans.reshape(bs*n, 3)-rec_trans.reshape(bs*n, 3),
+ # expression=tar_exps.reshape(bs*n, 100)-tar_exps.reshape(bs*n, 100),
+ # jaw_pose=tar_pose[:, 66:69],
+ # global_orient=tar_pose[:,:3],
+ # body_pose=tar_pose[:,3:21*3+3],
+ # left_hand_pose=tar_pose[:,25*3:40*3],
+ # right_hand_pose=tar_pose[:,40*3:55*3],
+ # return_joints=True,
+ # leye_pose=tar_pose[:, 69:72],
+ # reye_pose=tar_pose[:, 72:75],
+ # )
+ joints_rec = vertices_rec["joints"].detach().cpu().numpy().reshape(1, n, 127*3)[0, :n, :55*3]
+ # joints_tar = vertices_tar["joints"].detach().cpu().numpy().reshape(1, n, 127*3)[0, :n, :55*3]
+ _ = self.l1_calculator.run(joints_rec)
+ if self.alignmenter is not None:
+ in_audio_eval, sr = librosa.load(self.args.data_path+"wave16k/"+test_seq_list.iloc[its]['id']+".wav")
+ in_audio_eval = librosa.resample(in_audio_eval, orig_sr=sr, target_sr=self.args.audio_sr)
+ a_offset = int(self.align_mask * (self.args.audio_sr / self.args.pose_fps))
+ onset_bt = self.alignmenter.load_audio(in_audio_eval[:int(self.args.audio_sr / self.args.pose_fps*n)], a_offset, len(in_audio_eval)-a_offset, True)
+ beat_vel = self.alignmenter.load_pose(joints_rec, self.align_mask, n-self.align_mask, 30, True)
+ # print(beat_vel)
+ align += (self.alignmenter.calculate_align(onset_bt, beat_vel, 30) * (n-2*self.align_mask))
+
+ tar_pose_axis_np = tar_pose.detach().cpu().numpy()
+ rec_pose_axis_np = rec_pose.detach().cpu().numpy()
+ rec_trans_np = rec_trans.detach().cpu().numpy().reshape(bs*n, 3)
+ rec_exp_np = tar_exps.detach().cpu().numpy().reshape(bs*n, 100) - tar_exps.detach().cpu().numpy().reshape(bs*n, 100)
+ tar_exp_np = tar_exps.detach().cpu().numpy().reshape(bs*n, 100) - tar_exps.detach().cpu().numpy().reshape(bs*n, 100)
+ tar_trans_np = tar_trans.detach().cpu().numpy().reshape(bs*n, 3)
+ gt_npz = np.load(self.args.data_path+self.args.pose_rep +"/"+test_seq_list.iloc[its]['id']+".npz", allow_pickle=True)
+ if not self.args.train_trans:
+ tar_trans_np = tar_trans_np - tar_trans_np
+ rec_trans_np = rec_trans_np - rec_trans_np
+ np.savez(results_save_path+"gt_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=tar_pose_axis_np,
+ expressions=tar_exp_np,
+ trans=tar_trans_np,
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30 ,
+ )
+ np.savez(results_save_path+"res_"+test_seq_list.iloc[its]['id']+'.npz',
+ betas=gt_npz["betas"],
+ poses=rec_pose_axis_np,
+ expressions=rec_exp_np,
+ trans=rec_trans_np,
+ model='smplx2020',
+ gender='neutral',
+ mocap_frame_rate = 30,
+ )
+ total_length += n
+
+ latent_out_all = np.concatenate(latent_out, axis=0)
+ latent_ori_all = np.concatenate(latent_ori, axis=0)
+ fid = data_tools.FIDCalculator.frechet_distance(latent_out_all, latent_ori_all)
+ logger.info(f"fid score: {fid}")
+ self.test_recording("fid", fid, epoch)
+
+ align_avg = align/(total_length-2*len(self.test_loader)*self.align_mask)
+ logger.info(f"align score: {align_avg}")
+ self.test_recording("bc", align_avg, epoch)
+
+ l1div = self.l1_calculator.avg()
+ logger.info(f"l1div score: {l1div}")
+ self.test_recording("l1div", l1div, epoch)
+
+ # data_tools.result2target_vis(self.args.pose_version, results_save_path, results_save_path, self.test_demo, False)
+ end_time = time.time() - start_time
+ logger.info(f"total inference time: {int(end_time)} s for {int(total_length/self.args.pose_fps)} s motion")
\ No newline at end of file
diff --git a/configs/.ipynb_checkpoints/emage_test_hf-checkpoint.yaml b/configs/.ipynb_checkpoints/emage_test_hf-checkpoint.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..564aaf431479e2d25825507d2819b8e247e857a1
--- /dev/null
+++ b/configs/.ipynb_checkpoints/emage_test_hf-checkpoint.yaml
@@ -0,0 +1,101 @@
+is_train: True
+ddp: False
+stat: ts
+root_path: ./
+out_path: ./outputs/audio2pose/
+project: s2g
+data_path: ./EMAGE/test_sequences/
+e_path: weights/AESKConv_240_100.bin
+eval_model: motion_representation
+e_name: VAESKConv
+test_ckpt: ./EMAGE/emage_audio_175.bin
+data_path_1: ./EMAGE/
+vae_test_len: 32
+vae_test_dim: 330
+vae_test_stride: 20
+vae_length: 240
+vae_codebook_size: 256
+vae_layer: 4
+vae_grow: [1,1,2,1]
+variational: False
+
+# data config
+training_speakers: [2] #[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
+additional_data: False
+cache_path: ./datasets/beat_cache/beat_smplx_en_emage_test/
+dataset: beat_testonly_hf
+new_cache: True
+
+# motion config
+ori_joints: beat_smplx_joints
+tar_joints: beat_smplx_full
+pose_rep: smplxflame_30
+pose_norm: False
+pose_fps: 30
+rot6d: True
+pre_frames: 4
+pose_dims: 330
+pose_length: 64
+stride: 20
+test_length: 64
+motion_f: 256
+m_pre_encoder: null
+m_encoder: null
+m_fix_pre: False
+
+# audio config
+audio_rep: wave16k
+audio_sr: 16000
+audio_fps: 16000
+audio_norm: False
+audio_f: 256
+# a_pre_encoder: tcn_camn
+# a_encoder: none
+# a_fix_pre: False
+
+# text config
+# word_rep: textgrid
+# word_index_num: 11195
+# word_dims: 300
+# freeze_wordembed: False
+# word_f: 256
+# t_pre_encoder: fasttext
+# t_encoder: null
+# t_fix_pre: False
+
+# facial config
+facial_rep: smplxflame_30
+facial_dims: 100
+facial_norm: False
+facial_f: 0
+f_pre_encoder: null
+f_encoder: null
+f_fix_pre: False
+
+# speaker config
+id_rep: onehot
+speaker_f: 0
+
+# model config
+batch_size: 64
+# warmup_epochs: 1
+# warmup_lr: 1e-6
+lr_base: 5e-4
+model: emage_audio
+g_name: MAGE_Transformer
+trainer: emage
+hidden_size: 768
+n_layer: 1
+
+rec_weight: 1
+grad_norm: 0.99
+epochs: 400
+test_period: 20
+ll: 3
+lf: 3
+lu: 3
+lh: 3
+cl: 1
+cf: 0
+cu: 1
+ch: 1
diff --git a/configs/camn.yaml b/configs/camn.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..177f4864bc8a5d8c1bb50f89675f463646133342
--- /dev/null
+++ b/configs/camn.yaml
@@ -0,0 +1,101 @@
+is_train: True
+ddp: False
+stat: ts
+root_path: ./
+out_path: ./outputs/audio2pose/
+project: s2g
+data_path: ./BEAT2/beat_english_v2.0.0/
+e_path: weights/AESKConv_240_100.bin
+eval_model: motion_representation
+e_name: VAESKConv
+test_ckpt: ./EMAGE/camn.bin
+data_path_1: ./EMAGE/
+vae_test_len: 64
+vae_test_dim: 330
+vae_test_stride: 20
+vae_length: 240
+vae_codebook_size: 256
+vae_layer: 4
+vae_grow: [1,1,2,1]
+variational: False
+
+# data config
+training_speakers: [2] #[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
+additional_data: False
+cache_path: datasets/beat_cache/beat_smplx_en_camn/
+dataset: beat_sep
+new_cache: False
+
+# motion config
+ori_joints: beat_smplx_joints
+tar_joints: beat_smplx_full
+pose_rep: smplxflame_30
+pose_norm: False
+pose_fps: 15
+rot6d: True
+pre_frames: 4
+pose_dims: 330
+pose_length: 32
+stride: 10
+test_length: 32
+motion_f: 256
+m_pre_encoder: null
+m_encoder: null
+m_fix_pre: False
+
+# audio config
+audio_rep: wave16k
+audio_sr: 16000
+audio_fps: 16000
+audio_norm: False
+audio_f: 128
+# a_pre_encoder: tcn_camn
+# a_encoder: none
+# a_fix_pre: False
+
+# text config
+word_rep: textgrid
+word_index_num: 11195
+word_dims: 300
+freeze_wordembed: False
+word_f: 128
+t_pre_encoder: fasttext
+t_encoder: null
+t_fix_pre: False
+
+# facial config
+facial_rep: smplxflame_30
+facial_dims: 100
+facial_norm: False
+facial_f: 64
+f_pre_encoder: null
+f_encoder: null
+f_fix_pre: False
+
+# speaker config
+id_rep: onehot
+speaker_f: 16
+emo_rep: emo
+emotion_f: 8
+# sem_rep: sem
+
+
+# model config
+batch_size: 128
+# warmup_epochs: 1
+# warmup_lr: 1e-6
+lr_base: 3e-4
+model: camn
+g_name: CaMN
+d_name: ConvDiscriminator
+trainer: camn
+hidden_size: 512
+n_layer: 4
+rec_weight: 500
+no_adv_epoch: 999
+# rec_pos_weight: 1
+# rec_ver_weight: 0
+# rec_fac_weight: 1
+# grad_norm: 1
+epochs: 100
+test_period: 20
\ No newline at end of file
diff --git a/configs/cnn_vqvae_face_30.yaml b/configs/cnn_vqvae_face_30.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0f05b872ac57106cb57184397a6da5ebb016dffd
--- /dev/null
+++ b/configs/cnn_vqvae_face_30.yaml
@@ -0,0 +1,82 @@
+is_train: True
+ddp: False
+stat: ts
+training_speakers: [2] #[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
+root_path: ./
+out_path: ./outputs/audio2pose/
+cache_path: datasets/beat_cache/beat_smplx_en_face/
+project: mage_smplx
+data_path: ./BEAT2/beat_english_v2.0.0/
+e_path: weights/AESKConv_240_100.bin
+test_ckpt: weights/multi.bin
+data_path_1: ./EMAGE/
+#torch_hub_path: datasets/hub/
+additional_data: False
+dataset: beat_sep
+new_cache: False
+ori_joints: beat_smplx_joints
+tar_joints: beat_smplx_face
+pose_rep: smplxflame_30
+facial_rep: smplxflame_30
+pose_norm: False
+pose_fps: 30
+
+
+vae_test_len: 64
+vae_test_dim: 106
+vae_test_stride: 20
+vae_length: 256
+vae_codebook_size: 256
+vae_layer: 2
+vae_grow: [1,1,2,1]
+variational: False
+
+pose_dims: 106
+pose_length: 64
+stride: 20
+facial_dims: 100
+word_index_num: 11195
+word_dims: 300
+batch_size: 64
+lr_base: 3e-4
+model: motion_representation
+g_name: VQVAEConvZero
+#eval_model: motion_autoencoder
+#e_name: HalfEmbeddingNet
+trainer: aeface
+decay_epochs: 780
+# audio_f: 256
+# a_pre_encoder: tcn_camn
+# a_encoder: lp
+# a_fix_pre: False
+
+# freeze_wordembed: False
+# word_f: 128
+# t_pre_encoder: fasttext
+# t_encoder: lp
+# t_fix_pre: False
+
+# motion_f: 256
+# m_pre_encoder: lp
+# m_encoder: lp
+# m_fix_pre: False
+
+# facial_f: 128
+# f_pre_encoder: lp
+# f_encoder: lp
+# f_fix_pre: False
+
+#m_decoder: lstm
+#decode_fusion: cat
+#n_layer: 2
+#hidden_size: 512
+rec_weight: 1
+rec_pos_weight: 1
+rec_ver_weight: 1
+# rec_fac_weight: 1
+#ita_weight: 0
+#iwa_weight: 0
+#fusion_mode: sum
+# grad_norm: 1
+epochs: 800
+test_period: 100
\ No newline at end of file
diff --git a/configs/cnn_vqvae_hands_30.yaml b/configs/cnn_vqvae_hands_30.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e909d39d618bb89cd19333bb5eb427cfa937fc26
--- /dev/null
+++ b/configs/cnn_vqvae_hands_30.yaml
@@ -0,0 +1,81 @@
+is_train: True
+ddp: False
+stat: ts
+training_speakers: [2] #[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
+root_path: ./
+out_path: ./outputs/audio2pose/
+cache_path: datasets/beat_cache/beat_smplx_en_hands/
+project: mage_smplx
+data_path: ./BEAT2/beat_english_v2.0.0/
+e_path: weights/AESKConv_240_100.bin
+test_ckpt: weights/multi.bin
+data_path_1: ./EMAGE/
+#torch_hub_path: datasets/hub/
+additional_data: False
+dataset: beat_sep
+new_cache: False
+ori_joints: beat_smplx_joints
+tar_joints: beat_smplx_hands
+pose_rep: smplxflame_30
+pose_norm: False
+pose_fps: 30
+
+
+vae_test_len: 64
+vae_test_dim: 180
+vae_test_stride: 20
+vae_length: 256
+vae_codebook_size: 256
+vae_layer: 2
+vae_grow: [1,1,2,1]
+variational: False
+
+pose_dims: 180
+pose_length: 64
+stride: 20
+facial_dims: 100
+word_index_num: 11195
+word_dims: 300
+batch_size: 64
+lr_base: 3e-4
+model: motion_representation
+g_name: VQVAEConvZero
+#eval_model: motion_autoencoder
+#e_name: HalfEmbeddingNet
+trainer: ae
+decay_epochs: 780
+# audio_f: 256
+# a_pre_encoder: tcn_camn
+# a_encoder: lp
+# a_fix_pre: False
+
+# freeze_wordembed: False
+# word_f: 128
+# t_pre_encoder: fasttext
+# t_encoder: lp
+# t_fix_pre: False
+
+# motion_f: 256
+# m_pre_encoder: lp
+# m_encoder: lp
+# m_fix_pre: False
+
+# facial_f: 128
+# f_pre_encoder: lp
+# f_encoder: lp
+# f_fix_pre: False
+
+#m_decoder: lstm
+#decode_fusion: cat
+#n_layer: 2
+#hidden_size: 512
+rec_weight: 1
+rec_pos_weight: 1
+rec_ver_weight: 1
+# rec_fac_weight: 1
+#ita_weight: 0
+#iwa_weight: 0
+#fusion_mode: sum
+# grad_norm: 1
+epochs: 800
+test_period: 100
\ No newline at end of file
diff --git a/configs/cnn_vqvae_lower_30.yaml b/configs/cnn_vqvae_lower_30.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..b7c61a8cdc9f0ca6e16d13259285b36c9bd83309
--- /dev/null
+++ b/configs/cnn_vqvae_lower_30.yaml
@@ -0,0 +1,81 @@
+is_train: True
+ddp: False
+stat: ts
+training_speakers: [2] #[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
+root_path: ./
+out_path: ./outputs/audio2pose/
+cache_path: datasets/beat_cache/beat_smplx_en_lower/
+project: mage_smplx
+data_path: ./BEAT2/beat_english_v2.0.0/
+e_path: weights/AESKConv_240_100.bin
+test_ckpt: weights/multi.bin
+data_path_1: ./EMAGE/
+#torch_hub_path: datasets/hub/
+additional_data: False
+dataset: beat_sep_lower
+new_cache: False
+ori_joints: beat_smplx_joints
+tar_joints: beat_smplx_lower
+pose_rep: smplxflame_30
+pose_norm: False
+pose_fps: 30
+
+
+vae_test_len: 64
+vae_test_dim: 61
+vae_test_stride: 20
+vae_length: 256
+vae_codebook_size: 256
+vae_layer: 4
+vae_grow: [1,1,2,1]
+variational: False
+
+pose_dims: 61
+pose_length: 64
+stride: 20
+facial_dims: 100
+word_index_num: 11195
+word_dims: 300
+batch_size: 64
+lr_base: 3e-4
+model: motion_representation
+g_name: VAEConvZero
+#eval_model: motion_autoencoder
+#e_name: HalfEmbeddingNet
+trainer: aelower
+decay_epochs: 780
+# audio_f: 256
+# a_pre_encoder: tcn_camn
+# a_encoder: lp
+# a_fix_pre: False
+
+# freeze_wordembed: False
+# word_f: 128
+# t_pre_encoder: fasttext
+# t_encoder: lp
+# t_fix_pre: False
+
+# motion_f: 256
+# m_pre_encoder: lp
+# m_encoder: lp
+# m_fix_pre: False
+
+# facial_f: 128
+# f_pre_encoder: lp
+# f_encoder: lp
+# f_fix_pre: False
+
+#m_decoder: lstm
+#decode_fusion: cat
+#n_layer: 2
+#hidden_size: 512
+rec_weight: 1
+rec_pos_weight: 1
+rec_ver_weight: 1
+# rec_fac_weight: 1
+#ita_weight: 0
+#iwa_weight: 0
+#fusion_mode: sum
+# grad_norm: 1
+epochs: 800
+test_period: 100
\ No newline at end of file
diff --git a/configs/cnn_vqvae_lower_foot_30.yaml b/configs/cnn_vqvae_lower_foot_30.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..161befcd0344ee38cff19e7e6a09fa26523b083f
--- /dev/null
+++ b/configs/cnn_vqvae_lower_foot_30.yaml
@@ -0,0 +1,81 @@
+is_train: True
+ddp: False
+stat: ts
+training_speakers: [2]
+root_path: ./
+out_path: ./outputs/audio2pose/
+cache_path: datasets/beat_cache/beat_smplx_en_lower/
+project: mage_smplx
+data_path: ./BEAT2/beat_english_v2.0.0/
+e_path: weights/AESKConv_240_100.bin
+test_ckpt: weights/multi.bin
+data_path_1: ./EMAGE/
+#torch_hub_path: datasets/hub/
+additional_data: False
+dataset: beat_sep_lower
+new_cache: False
+ori_joints: beat_smplx_joints
+tar_joints: beat_smplx_lower
+pose_rep: smplxflame_30
+pose_norm: False
+pose_fps: 30
+
+
+vae_test_len: 64
+vae_test_dim: 61
+vae_test_stride: 20
+vae_length: 256
+vae_codebook_size: 256
+vae_layer: 4
+vae_grow: [1,1,2,1]
+variational: False
+
+pose_dims: 61
+pose_length: 64
+stride: 20
+facial_dims: 100
+word_index_num: 11195
+word_dims: 300
+batch_size: 64
+lr_base: 3e-4
+model: motion_representation
+g_name: VQVAEConvZero
+#eval_model: motion_autoencoder
+#e_name: HalfEmbeddingNet
+trainer: aelowerfoot
+decay_epochs: 780
+# audio_f: 256
+# a_pre_encoder: tcn_camn
+# a_encoder: lp
+# a_fix_pre: False
+
+# freeze_wordembed: False
+# word_f: 128
+# t_pre_encoder: fasttext
+# t_encoder: lp
+# t_fix_pre: False
+
+# motion_f: 256
+# m_pre_encoder: lp
+# m_encoder: lp
+# m_fix_pre: False
+
+# facial_f: 128
+# f_pre_encoder: lp
+# f_encoder: lp
+# f_fix_pre: False
+
+#m_decoder: lstm
+#decode_fusion: cat
+#n_layer: 2
+#hidden_size: 512
+rec_weight: 1
+rec_pos_weight: 1
+rec_ver_weight: 1
+# rec_fac_weight: 1
+#ita_weight: 0
+#iwa_weight: 0
+#fusion_mode: sum
+# grad_norm: 1
+epochs: 800
+test_period: 100
\ No newline at end of file
diff --git a/configs/cnn_vqvae_upper_30.yaml b/configs/cnn_vqvae_upper_30.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..db52e20b72ec2f18c81be58bf5414b99f8315fe5
--- /dev/null
+++ b/configs/cnn_vqvae_upper_30.yaml
@@ -0,0 +1,82 @@
+is_train: True
+ddp: False
+stat: ts
+training_speakers: [2]
+root_path: ./
+out_path: ./outputs/audio2pose/
+cache_path: datasets/beat_cache/beat_smplx_en_upper/
+project: mage_smplx
+data_path: ./BEAT2/beat_english_v2.0.0/
+e_path: weights/AESKConv_240_100.bin
+test_ckpt: weights/multi.bin
+data_path_1: ./EMAGE/
+#torch_hub_path: datasets/hub/
+additional_data: False
+dataset: beat_sep
+new_cache: False
+ori_joints: beat_smplx_joints
+tar_joints: beat_smplx_upper
+pose_rep: smplxflame_30
+pose_norm: False
+pose_fps: 30
+
+
+vae_test_len: 64
+vae_test_dim: 78
+vae_test_stride: 20
+vae_length: 256
+vae_codebook_size: 256
+vae_layer: 2
+vae_grow: [1,1,2,1]
+variational: False
+
+pose_dims: 78
+pose_length: 64
+stride: 20
+facial_dims: 100
+word_index_num: 11195
+word_dims: 300
+batch_size: 64
+lr_base: 3e-4
+decay_epochs: 9999
+model: motion_representation
+g_name: VQVAEConvZero
+#eval_model: motion_autoencoder
+#e_name: HalfEmbeddingNet
+trainer: ae
+
+# audio_f: 256
+# a_pre_encoder: tcn_camn
+# a_encoder: lp
+# a_fix_pre: False
+
+# freeze_wordembed: False
+# word_f: 128
+# t_pre_encoder: fasttext
+# t_encoder: lp
+# t_fix_pre: False
+
+# motion_f: 256
+# m_pre_encoder: lp
+# m_encoder: lp
+# m_fix_pre: False
+
+# facial_f: 128
+# f_pre_encoder: lp
+# f_encoder: lp
+# f_fix_pre: False
+
+#m_decoder: lstm
+#decode_fusion: cat
+#n_layer: 2
+#hidden_size: 512
+rec_weight: 1
+rec_pos_weight: 1
+rec_ver_weight: 1
+# rec_fac_weight: 1
+#ita_weight: 0
+#iwa_weight: 0
+#fusion_mode: sum
+# grad_norm: 1
+epochs: 500
+test_period: 100
\ No newline at end of file
diff --git a/configs/emage.yaml b/configs/emage.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..1160bde10ed93a591ab2fc8903255d08391d9ff7
--- /dev/null
+++ b/configs/emage.yaml
@@ -0,0 +1,101 @@
+is_train: True
+ddp: False
+stat: ts
+root_path: ./
+out_path: ./outputs/audio2pose/
+project: s2g
+data_path: ./BEAT2/beat_english_v2.0.0/
+e_path: weights/AESKConv_240_100.bin
+eval_model: motion_representation
+e_name: VAESKConv
+test_ckpt: ./EMAGE/emage_240.bin
+data_path_1: ./EMAGE/
+vae_test_len: 32
+vae_test_dim: 330
+vae_test_stride: 20
+vae_length: 240
+vae_codebook_size: 256
+vae_layer: 4
+vae_grow: [1,1,2,1]
+variational: False
+
+# data config
+training_speakers: [2] #[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
+additional_data: False
+cache_path: datasets/beat_cache/beat_smplx_en_emage/
+dataset: beat_sep_lower
+new_cache: False
+
+# motion config
+ori_joints: beat_smplx_joints
+tar_joints: beat_smplx_full
+pose_rep: smplxflame_30
+pose_norm: False
+pose_fps: 30
+rot6d: True
+pre_frames: 4
+pose_dims: 330
+pose_length: 64
+stride: 20
+test_length: 64
+motion_f: 256
+m_pre_encoder: null
+m_encoder: null
+m_fix_pre: False
+
+# audio config
+audio_rep: onset+amplitude
+audio_sr: 16000
+audio_fps: 16000
+audio_norm: False
+audio_f: 256
+# a_pre_encoder: tcn_camn
+# a_encoder: none
+# a_fix_pre: False
+
+# text config
+word_rep: textgrid
+word_index_num: 11195
+word_dims: 300
+freeze_wordembed: False
+word_f: 256
+t_pre_encoder: fasttext
+t_encoder: null
+t_fix_pre: False
+
+# facial config
+facial_rep: smplxflame_30
+facial_dims: 100
+facial_norm: False
+facial_f: 0
+f_pre_encoder: null
+f_encoder: null
+f_fix_pre: False
+
+# speaker config
+id_rep: onehot
+speaker_f: 0
+
+# model config
+batch_size: 64
+# warmup_epochs: 1
+# warmup_lr: 1e-6
+lr_base: 5e-4
+model: emage
+g_name: MAGE_Transformer
+trainer: emage
+hidden_size: 768
+n_layer: 1
+
+rec_weight: 1
+grad_norm: 0.99
+epochs: 400
+test_period: 20
+ll: 3
+lf: 3
+lu: 3
+lh: 3
+cl: 1
+cf: 0
+cu: 1
+ch: 1
diff --git a/configs/emage_test.yaml b/configs/emage_test.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ca29c88ba4cfe028f73a9f7ae3636b1e82be2a39
--- /dev/null
+++ b/configs/emage_test.yaml
@@ -0,0 +1,101 @@
+is_train: True
+ddp: False
+stat: ts
+root_path: ./
+out_path: ./outputs/audio2pose/
+project: s2g
+data_path: ./EMAGE/test_sequences/
+e_path: weights/AESKConv_240_100.bin
+eval_model: motion_representation
+e_name: VAESKConv
+test_ckpt: ./EMAGE/emage_240.bin
+data_path_1: ./EMAGE/
+vae_test_len: 32
+vae_test_dim: 330
+vae_test_stride: 20
+vae_length: 240
+vae_codebook_size: 256
+vae_layer: 4
+vae_grow: [1,1,2,1]
+variational: False
+
+# data config
+training_speakers: [2] #[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
+additional_data: False
+cache_path: ./datasets/beat_cache/beat_smplx_en_emage_test/
+dataset: beat_testonly
+new_cache: True
+
+# motion config
+ori_joints: beat_smplx_joints
+tar_joints: beat_smplx_full
+pose_rep: smplxflame_30
+pose_norm: False
+pose_fps: 30
+rot6d: True
+pre_frames: 4
+pose_dims: 330
+pose_length: 64
+stride: 20
+test_length: 64
+motion_f: 256
+m_pre_encoder: null
+m_encoder: null
+m_fix_pre: False
+
+# audio config
+audio_rep: onset+amplitude
+audio_sr: 16000
+audio_fps: 16000
+audio_norm: False
+audio_f: 256
+# a_pre_encoder: tcn_camn
+# a_encoder: none
+# a_fix_pre: False
+
+# text config
+word_rep: textgrid
+word_index_num: 11195
+word_dims: 300
+freeze_wordembed: False
+word_f: 256
+t_pre_encoder: fasttext
+t_encoder: null
+t_fix_pre: False
+
+# facial config
+facial_rep: smplxflame_30
+facial_dims: 100
+facial_norm: False
+facial_f: 0
+f_pre_encoder: null
+f_encoder: null
+f_fix_pre: False
+
+# speaker config
+id_rep: onehot
+speaker_f: 0
+
+# model config
+batch_size: 64
+# warmup_epochs: 1
+# warmup_lr: 1e-6
+lr_base: 5e-4
+model: emage
+g_name: MAGE_Transformer
+trainer: emage
+hidden_size: 768
+n_layer: 1
+
+rec_weight: 1
+grad_norm: 0.99
+epochs: 400
+test_period: 20
+ll: 3
+lf: 3
+lu: 3
+lh: 3
+cl: 1
+cf: 0
+cu: 1
+ch: 1
diff --git a/configs/emage_test_colab.yaml b/configs/emage_test_colab.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..79d64b05931bcba2291bea6199c8fff2a1557d71
--- /dev/null
+++ b/configs/emage_test_colab.yaml
@@ -0,0 +1,101 @@
+is_train: True
+ddp: False
+stat: ts
+root_path: ./
+out_path: ./outputs/audio2pose/
+project: s2g
+data_path: ./EMAGE/test_sequences/
+e_path: weights/AESKConv_240_100.bin
+eval_model: motion_representation
+e_name: VAESKConv
+test_ckpt: ./EMAGE/emage_240.bin
+data_path_1: ./EMAGE/
+vae_test_len: 32
+vae_test_dim: 330
+vae_test_stride: 20
+vae_length: 240
+vae_codebook_size: 256
+vae_layer: 4
+vae_grow: [1,1,2,1]
+variational: False
+
+# data config
+training_speakers: [2] #[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
+additional_data: False
+cache_path: ./datasets/beat_cache/beat_smplx_en_emage_test/
+dataset: beat_testonly_colab
+new_cache: True
+
+# motion config
+ori_joints: beat_smplx_joints
+tar_joints: beat_smplx_full
+pose_rep: smplxflame_30
+pose_norm: False
+pose_fps: 30
+rot6d: True
+pre_frames: 4
+pose_dims: 330
+pose_length: 64
+stride: 20
+test_length: 64
+motion_f: 256
+m_pre_encoder: null
+m_encoder: null
+m_fix_pre: False
+
+# audio config
+audio_rep: onset+amplitude
+audio_sr: 16000
+audio_fps: 16000
+audio_norm: False
+audio_f: 256
+# a_pre_encoder: tcn_camn
+# a_encoder: none
+# a_fix_pre: False
+
+# text config
+word_rep: textgrid
+word_index_num: 11195
+word_dims: 300
+freeze_wordembed: False
+word_f: 256
+t_pre_encoder: fasttext
+t_encoder: null
+t_fix_pre: False
+
+# facial config
+facial_rep: smplxflame_30
+facial_dims: 100
+facial_norm: False
+facial_f: 0
+f_pre_encoder: null
+f_encoder: null
+f_fix_pre: False
+
+# speaker config
+id_rep: onehot
+speaker_f: 0
+
+# model config
+batch_size: 64
+# warmup_epochs: 1
+# warmup_lr: 1e-6
+lr_base: 5e-4
+model: emage
+g_name: MAGE_Transformer
+trainer: emage
+hidden_size: 768
+n_layer: 1
+
+rec_weight: 1
+grad_norm: 0.99
+epochs: 400
+test_period: 20
+ll: 3
+lf: 3
+lu: 3
+lh: 3
+cl: 1
+cf: 0
+cu: 1
+ch: 1
diff --git a/configs/emage_test_hf.yaml b/configs/emage_test_hf.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..564aaf431479e2d25825507d2819b8e247e857a1
--- /dev/null
+++ b/configs/emage_test_hf.yaml
@@ -0,0 +1,101 @@
+is_train: True
+ddp: False
+stat: ts
+root_path: ./
+out_path: ./outputs/audio2pose/
+project: s2g
+data_path: ./EMAGE/test_sequences/
+e_path: weights/AESKConv_240_100.bin
+eval_model: motion_representation
+e_name: VAESKConv
+test_ckpt: ./EMAGE/emage_audio_175.bin
+data_path_1: ./EMAGE/
+vae_test_len: 32
+vae_test_dim: 330
+vae_test_stride: 20
+vae_length: 240
+vae_codebook_size: 256
+vae_layer: 4
+vae_grow: [1,1,2,1]
+variational: False
+
+# data config
+training_speakers: [2] #[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
+additional_data: False
+cache_path: ./datasets/beat_cache/beat_smplx_en_emage_test/
+dataset: beat_testonly_hf
+new_cache: True
+
+# motion config
+ori_joints: beat_smplx_joints
+tar_joints: beat_smplx_full
+pose_rep: smplxflame_30
+pose_norm: False
+pose_fps: 30
+rot6d: True
+pre_frames: 4
+pose_dims: 330
+pose_length: 64
+stride: 20
+test_length: 64
+motion_f: 256
+m_pre_encoder: null
+m_encoder: null
+m_fix_pre: False
+
+# audio config
+audio_rep: wave16k
+audio_sr: 16000
+audio_fps: 16000
+audio_norm: False
+audio_f: 256
+# a_pre_encoder: tcn_camn
+# a_encoder: none
+# a_fix_pre: False
+
+# text config
+# word_rep: textgrid
+# word_index_num: 11195
+# word_dims: 300
+# freeze_wordembed: False
+# word_f: 256
+# t_pre_encoder: fasttext
+# t_encoder: null
+# t_fix_pre: False
+
+# facial config
+facial_rep: smplxflame_30
+facial_dims: 100
+facial_norm: False
+facial_f: 0
+f_pre_encoder: null
+f_encoder: null
+f_fix_pre: False
+
+# speaker config
+id_rep: onehot
+speaker_f: 0
+
+# model config
+batch_size: 64
+# warmup_epochs: 1
+# warmup_lr: 1e-6
+lr_base: 5e-4
+model: emage_audio
+g_name: MAGE_Transformer
+trainer: emage
+hidden_size: 768
+n_layer: 1
+
+rec_weight: 1
+grad_norm: 0.99
+epochs: 400
+test_period: 20
+ll: 3
+lf: 3
+lu: 3
+lh: 3
+cl: 1
+cf: 0
+cu: 1
+ch: 1
diff --git a/configs/skcnn_ae.yaml b/configs/skcnn_ae.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..19430f8e617d1b069c023684e46eaceabe6fd795
--- /dev/null
+++ b/configs/skcnn_ae.yaml
@@ -0,0 +1,80 @@
+is_train: True
+ddp: False
+stat: ts
+training_speakers: [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
+root_path: /home/s24273/
+out_path: /home/s24273/outputs/audio2pose/
+cache_path: datasets/beat_cache/beat_smplx_en/
+project: mage_smplx
+data_path: /home/s24273/datasets/beat_v2.0.0/beat_english_v2.0.0/
+e_path: weights/AESKConv_240_100.bin
+test_ckpt: weights/multi.bin
+data_path_1: /home/s24273/datasets/hub/
+#torch_hub_path: datasets/hub/
+additional_data: False
+dataset: beat_smplx2020
+new_cache: False
+ori_joints: beat_smplx_joints
+tar_joints: beat_smplx_full
+pose_rep: smplxflame_30
+pose_norm: False
+pose_fps: 30
+
+
+vae_test_len: 64
+vae_test_dim: 330
+vae_test_stride: 20
+vae_length: 240
+vae_layer: 2
+vae_grow: [1,2]
+variational: False
+
+pose_dims: 330
+pose_length: 64
+stride: 20
+facial_dims: 100
+word_index_num: 11195
+word_dims: 300
+batch_size: 32
+lr_base: 1e-4
+model: motion_representation
+g_name: VAESKConv
+#eval_model: motion_autoencoder
+#e_name: HalfEmbeddingNet
+trainer: ae
+decay_epochs: 950
+# audio_f: 256
+# a_pre_encoder: tcn_camn
+# a_encoder: lp
+# a_fix_pre: False
+
+# freeze_wordembed: False
+# word_f: 128
+# t_pre_encoder: fasttext
+# t_encoder: lp
+# t_fix_pre: False
+
+# motion_f: 256
+# m_pre_encoder: lp
+# m_encoder: lp
+# m_fix_pre: False
+
+# facial_f: 128
+# f_pre_encoder: lp
+# f_encoder: lp
+# f_fix_pre: False
+
+#m_decoder: lstm
+#decode_fusion: cat
+#n_layer: 2
+#hidden_size: 512
+rec_weight: 1
+rec_pos_weight: 10
+rec_ver_weight: 0
+# rec_fac_weight: 1
+#ita_weight: 0
+#iwa_weight: 0
+#fusion_mode: sum
+# grad_norm: 1
+epochs: 1000
+test_period: 100
\ No newline at end of file
diff --git a/dataloaders/.ipynb_checkpoints/beat_testonly_hf-checkpoint.py b/dataloaders/.ipynb_checkpoints/beat_testonly_hf-checkpoint.py
new file mode 100644
index 0000000000000000000000000000000000000000..17393517d0d6f662114c19b009fa3471d7c1e91b
--- /dev/null
+++ b/dataloaders/.ipynb_checkpoints/beat_testonly_hf-checkpoint.py
@@ -0,0 +1,740 @@
+import os
+import pickle
+import math
+import shutil
+import numpy as np
+import lmdb as lmdb
+import textgrid as tg
+import pandas as pd
+import torch
+import glob
+import json
+from termcolor import colored
+from loguru import logger
+from collections import defaultdict
+from torch.utils.data import Dataset
+import torch.distributed as dist
+import pyarrow
+import librosa
+import smplx
+
+from .build_vocab import Vocab
+from .utils.audio_features import Wav2Vec2Model
+from .data_tools import joints_list
+from .utils import rotation_conversions as rc
+from .utils import other_tools_hf
+
+class CustomDataset(Dataset):
+ def __init__(self, args, loader_type, smplx_path=None, audio_path=None, text_path=None, augmentation=None, kwargs=None, build_cache=True):
+ self.args = args
+ self.loader_type = loader_type
+ self.smplx_path = "./EMAGE/test_sequences/smplxflame_30/2_scott_0_1_1.npz"
+ self.audio_path = audio_path
+ self.text_path = "./EMAGE/test_sequences/textgrid/2_scott_0_1_1.TextGrid"
+ self.rank = 0 # dist.get_rank()
+ self.ori_stride = self.args.stride
+ self.ori_length = self.args.pose_length
+ self.alignment = [0,0] # for trinity
+
+ self.ori_joint_list = joints_list[self.args.ori_joints]
+ self.tar_joint_list = joints_list[self.args.tar_joints]
+ if 'smplx' in self.args.pose_rep:
+ self.joint_mask = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ self.joints = len(list(self.tar_joint_list.keys()))
+ for joint_name in self.tar_joint_list:
+ self.joint_mask[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ else:
+ self.joints = len(list(self.ori_joint_list.keys()))+1
+ self.joint_mask = np.zeros(self.joints*3)
+ for joint_name in self.tar_joint_list:
+ if joint_name == "Hips":
+ self.joint_mask[3:6] = 1
+ else:
+ self.joint_mask[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ # select trainable joints
+ self.smplx = smplx.create(
+ self.args.data_path_1+"smplx_models/",
+ model_type='smplx',
+ gender='NEUTRAL_2020',
+ use_face_contour=False,
+ num_betas=300,
+ num_expression_coeffs=100,
+ ext='npz',
+ use_pca=False,
+ ).eval()
+
+ split_rule = pd.read_csv(args.data_path+"test.csv")
+ self.selected_file = split_rule
+ self.data_dir = args.data_path
+
+ if loader_type == "test":
+ self.args.multi_length_training = [1.0]
+ self.max_length = int(args.pose_length * self.args.multi_length_training[-1])
+ self.max_audio_pre_len = math.floor(args.pose_length / args.pose_fps * self.args.audio_sr)
+ if self.max_audio_pre_len > self.args.test_length*self.args.audio_sr:
+ self.max_audio_pre_len = self.args.test_length*self.args.audio_sr
+
+ if args.word_rep is not None:
+ with open(f"{args.data_path}weights/vocab.pkl", 'rb') as f:
+ self.lang_model = pickle.load(f)
+
+ preloaded_dir = self.args.root_path + self.args.cache_path + loader_type + f"/{args.pose_rep}_cache"
+ if build_cache and self.rank == 0:
+ self.build_cache(preloaded_dir)
+ self.lmdb_env = lmdb.open(preloaded_dir, readonly=True, lock=False)
+ with self.lmdb_env.begin() as txn:
+ self.n_samples = txn.stat()["entries"]
+
+
+ def build_cache(self, preloaded_dir):
+ logger.info(f"Audio bit rate: {self.args.audio_fps}")
+ logger.info("Reading data '{}'...".format(self.data_dir))
+ logger.info("Creating the dataset cache...")
+ if self.args.new_cache:
+ if os.path.exists(preloaded_dir):
+ shutil.rmtree(preloaded_dir)
+ if os.path.exists(preloaded_dir):
+ logger.info("Found the cache {}".format(preloaded_dir))
+ elif self.loader_type == "test":
+ self.cache_generation(
+ preloaded_dir, True,
+ 0, 0,
+ is_test=True)
+ else:
+ self.cache_generation(
+ preloaded_dir, self.args.disable_filtering,
+ self.args.clean_first_seconds, self.args.clean_final_seconds,
+ is_test=False)
+
+
+ def __len__(self):
+ return self.n_samples
+
+
+ def cache_generation(self, out_lmdb_dir, disable_filtering, clean_first_seconds, clean_final_seconds, is_test=False):
+ self.n_out_samples = 0
+ # create db for samples
+ if not os.path.exists(out_lmdb_dir): os.makedirs(out_lmdb_dir)
+ if len(self.args.training_speakers) == 1:
+ #dst_lmdb_env = lmdb.open(out_lmdb_dir, map_size= int(1024 ** 3 * 50))# 50G
+ dst_lmdb_env = lmdb.open(out_lmdb_dir, map_size= int(1024 ** 3 * 0.5))# 500M
+ else:
+ dst_lmdb_env = lmdb.open(out_lmdb_dir, map_size= int(1024 ** 3 * 200))# 200G
+ n_filtered_out = defaultdict(int)
+
+ #for index, file_name in self.selected_file.iterrows():
+ #f_name = file_name["id"]
+ ext = ".npz" if "smplx" in self.args.pose_rep else ".bvh"
+ pose_file = self.smplx_path#self.data_dir + self.args.pose_rep + "/" + f_name + ext
+ pose_each_file = []
+ trans_each_file = []
+ shape_each_file = []
+ audio_each_file = []
+ facial_each_file = []
+ word_each_file = []
+ emo_each_file = []
+ sem_each_file = []
+ vid_each_file = []
+ id_pose = "dummy 2nd"#f_name
+
+ logger.info(colored(f"# ---- Building cache for Pose {id_pose} ---- #", "blue"))
+ if "smplx" in self.args.pose_rep:
+ pose_data = np.load(pose_file, allow_pickle=True)
+ assert 30%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 30'
+ stride = int(30/self.args.pose_fps)
+ pose_each_file = pose_data["poses"][::stride]
+ trans_each_file = pose_data["trans"][::stride]
+ shape_each_file = np.repeat(pose_data["betas"].reshape(1, 300), pose_each_file.shape[0], axis=0)
+
+ assert self.args.pose_fps == 30, "should 30"
+ m_data = np.load(pose_file, allow_pickle=True)
+ betas, poses, trans, exps = m_data["betas"], m_data["poses"], m_data["trans"], m_data["expressions"]
+ n, c = poses.shape[0], poses.shape[1]
+ betas = betas.reshape(1, 300)
+ betas = np.tile(betas, (n, 1))
+ betas = torch.from_numpy(betas).float()
+ poses = torch.from_numpy(poses.reshape(n, c)).float()
+ exps = torch.from_numpy(exps.reshape(n, 100)).float()
+ trans = torch.from_numpy(trans.reshape(n, 3)).float()
+ max_length = 128
+ s, r = n//max_length, n%max_length
+ #print(n, s, r)
+ all_tensor = []
+ for i in range(s):
+ with torch.no_grad():
+ joints = self.smplx(
+ betas=betas[i*max_length:(i+1)*max_length],
+ transl=trans[i*max_length:(i+1)*max_length],
+ expression=exps[i*max_length:(i+1)*max_length],
+ jaw_pose=poses[i*max_length:(i+1)*max_length, 66:69],
+ global_orient=poses[i*max_length:(i+1)*max_length,:3],
+ body_pose=poses[i*max_length:(i+1)*max_length,3:21*3+3],
+ left_hand_pose=poses[i*max_length:(i+1)*max_length,25*3:40*3],
+ right_hand_pose=poses[i*max_length:(i+1)*max_length,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=poses[i*max_length:(i+1)*max_length, 69:72],
+ reye_pose=poses[i*max_length:(i+1)*max_length, 72:75],
+ )['joints'][:, (7,8,10,11), :].reshape(max_length, 4, 3).cpu()
+ all_tensor.append(joints)
+ if r != 0:
+ with torch.no_grad():
+ joints = self.smplx(
+ betas=betas[s*max_length:s*max_length+r],
+ transl=trans[s*max_length:s*max_length+r],
+ expression=exps[s*max_length:s*max_length+r],
+ jaw_pose=poses[s*max_length:s*max_length+r, 66:69],
+ global_orient=poses[s*max_length:s*max_length+r,:3],
+ body_pose=poses[s*max_length:s*max_length+r,3:21*3+3],
+ left_hand_pose=poses[s*max_length:s*max_length+r,25*3:40*3],
+ right_hand_pose=poses[s*max_length:s*max_length+r,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=poses[s*max_length:s*max_length+r, 69:72],
+ reye_pose=poses[s*max_length:s*max_length+r, 72:75],
+ )['joints'][:, (7,8,10,11), :].reshape(r, 4, 3).cpu()
+ all_tensor.append(joints)
+ joints = torch.cat(all_tensor, axis=0) # all, 4, 3
+ # print(joints.shape)
+ feetv = torch.zeros(joints.shape[1], joints.shape[0])
+ joints = joints.permute(1, 0, 2)
+ #print(joints.shape, feetv.shape)
+ feetv[:, :-1] = (joints[:, 1:] - joints[:, :-1]).norm(dim=-1)
+ #print(feetv.shape)
+ contacts = (feetv < 0.01).numpy().astype(float)
+ # print(contacts.shape, contacts)
+ contacts = contacts.transpose(1, 0)
+ pose_each_file = pose_each_file * self.joint_mask
+ pose_each_file = pose_each_file[:, self.joint_mask.astype(bool)]
+ pose_each_file = np.concatenate([pose_each_file, contacts], axis=1)
+ # print(pose_each_file.shape)
+
+
+ if self.args.facial_rep is not None:
+ logger.info(f"# ---- Building cache for Facial {id_pose} and Pose {id_pose} ---- #")
+ facial_each_file = pose_data["expressions"][::stride]
+ if self.args.facial_norm:
+ facial_each_file = (facial_each_file - self.mean_facial) / self.std_facial
+
+ else:
+ assert 120%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 120'
+ stride = int(120/self.args.pose_fps)
+ with open(pose_file, "r") as pose_data:
+ for j, line in enumerate(pose_data.readlines()):
+ if j < 431: continue
+ if j%stride != 0:continue
+ data = np.fromstring(line, dtype=float, sep=" ")
+ rot_data = rc.euler_angles_to_matrix(torch.from_numpy(np.deg2rad(data)).reshape(-1, self.joints,3), "XYZ")
+ rot_data = rc.matrix_to_axis_angle(rot_data).reshape(-1, self.joints*3)
+ rot_data = rot_data.numpy() * self.joint_mask
+
+ pose_each_file.append(rot_data)
+ trans_each_file.append(data[:3])
+
+ pose_each_file = np.array(pose_each_file)
+ trans_each_file = np.array(trans_each_file)
+ shape_each_file = np.repeat(np.array(-1).reshape(1, 1), pose_each_file.shape[0], axis=0)
+ if self.args.facial_rep is not None:
+ logger.info(f"# ---- Building cache for Facial {id_pose} and Pose {id_pose} ---- #")
+ facial_file = pose_file.replace(self.args.pose_rep, self.args.facial_rep).replace("bvh", "json")
+ assert 60%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 120'
+ stride = int(60/self.args.pose_fps)
+ if not os.path.exists(facial_file):
+ logger.warning(f"# ---- file not found for Facial {id_pose}, skip all files with the same id ---- #")
+ #self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ #continue
+ with open(facial_file, 'r') as facial_data_file:
+ facial_data = json.load(facial_data_file)
+ for j, frame_data in enumerate(facial_data['frames']):
+ if j%stride != 0:continue
+ facial_each_file.append(frame_data['weights'])
+ facial_each_file = np.array(facial_each_file)
+ if self.args.facial_norm:
+ facial_each_file = (facial_each_file - self.mean_facial) / self.std_facial
+
+ if self.args.id_rep is not None:
+ int_value = 1
+ vid_each_file = np.repeat(np.array(int_value).reshape(1, 1), pose_each_file.shape[0], axis=0)
+
+ if self.args.audio_rep is not None:
+ logger.info(f"# ---- Building cache for Audio {id_pose} and Pose {id_pose} ---- #")
+ audio_file = self.audio_path[1]#pose_file.replace(self.args.pose_rep, 'wave16k').replace(ext, ".wav")
+ sr = self.audio_path[0]
+ print(sr)
+ #if not os.path.exists(audio_file):
+ # logger.warning(f"# ---- file not found for Audio {id_pose}, skip all files with the same id ---- #")
+ #self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ #continue
+ #audio_each_file, sr = librosa.load(audio_file)
+ audio_each_file = audio_file.astype(np.float32)
+ print(audio_each_file.shape)
+ audio_each_file = librosa.resample(audio_each_file, orig_sr=sr, target_sr=self.args.audio_sr)
+ print(audio_each_file.shape)
+ if self.args.audio_rep == "onset+amplitude":
+ from numpy.lib import stride_tricks
+ frame_length = 1024
+ # hop_length = 512
+ shape = (audio_each_file.shape[-1] - frame_length + 1, frame_length)
+ strides = (audio_each_file.strides[-1], audio_each_file.strides[-1])
+ rolling_view = stride_tricks.as_strided(audio_each_file, shape=shape, strides=strides)
+ amplitude_envelope = np.max(np.abs(rolling_view), axis=1)
+ # pad the last frame_length-1 samples
+ amplitude_envelope = np.pad(amplitude_envelope, (0, frame_length-1), mode='constant', constant_values=amplitude_envelope[-1])
+ audio_onset_f = librosa.onset.onset_detect(y=audio_each_file, sr=self.args.audio_sr, units='frames')
+ onset_array = np.zeros(len(audio_each_file), dtype=float)
+ onset_array[audio_onset_f] = 1.0
+ # print(amplitude_envelope.shape, audio_each_file.shape, onset_array.shape)
+ audio_each_file = np.concatenate([amplitude_envelope.reshape(-1, 1), onset_array.reshape(-1, 1)], axis=1)
+ elif self.args.audio_rep == "mfcc":
+ audio_each_file = librosa.feature.melspectrogram(y=audio_each_file, sr=self.args.audio_sr, n_mels=128, hop_length=int(self.args.audio_sr/self.args.audio_fps))
+ audio_each_file = audio_each_file.transpose(1, 0)
+ # print(audio_each_file.shape, pose_each_file.shape)
+ if self.args.audio_norm and self.args.audio_rep == "wave16k":
+ audio_each_file = (audio_each_file - self.mean_audio) / self.std_audio
+
+ time_offset = 0
+ if self.args.word_rep is not None:
+ logger.info(f"# ---- Building cache for Word {id_pose} and Pose {id_pose} ---- #")
+ word_file = self.text_path#f"{self.data_dir}{self.args.word_rep}/{id_pose}.TextGrid"
+ if not os.path.exists(word_file):
+ logger.warning(f"# ---- file not found for Word {id_pose}, skip all files with the same id ---- #")
+ #self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ #continue
+ tgrid = tg.TextGrid.fromFile(word_file)
+ if self.args.t_pre_encoder == "bert":
+ from transformers import AutoTokenizer, BertModel
+ tokenizer = AutoTokenizer.from_pretrained(self.args.data_path_1 + "hub/bert-base-uncased", local_files_only=True)
+ model = BertModel.from_pretrained(self.args.data_path_1 + "hub/bert-base-uncased", local_files_only=True).eval()
+ list_word = []
+ all_hidden = []
+ max_len = 400
+ last = 0
+ word_token_mapping = []
+ first = True
+ for i, word in enumerate(tgrid[0]):
+ last = i
+ if (i%max_len != 0) or (i==0):
+ if word.mark == "":
+ list_word.append(".")
+ else:
+ list_word.append(word.mark)
+ else:
+ max_counter = max_len
+ str_word = ' '.join(map(str, list_word))
+ if first:
+ global_len = 0
+ end = -1
+ offset_word = []
+ for k, wordvalue in enumerate(list_word):
+ start = end+1
+ end = start+len(wordvalue)
+ offset_word.append((start, end))
+ #print(offset_word)
+ token_scan = tokenizer.encode_plus(str_word, return_offsets_mapping=True)['offset_mapping']
+ #print(token_scan)
+ for start, end in offset_word:
+ sub_mapping = []
+ for i, (start_t, end_t) in enumerate(token_scan[1:-1]):
+ if int(start) <= int(start_t) and int(end_t) <= int(end):
+ #print(i+global_len)
+ sub_mapping.append(i+global_len)
+ word_token_mapping.append(sub_mapping)
+ #print(len(word_token_mapping))
+ global_len = word_token_mapping[-1][-1] + 1
+ list_word = []
+ if word.mark == "":
+ list_word.append(".")
+ else:
+ list_word.append(word.mark)
+
+ with torch.no_grad():
+ inputs = tokenizer(str_word, return_tensors="pt")
+ outputs = model(**inputs)
+ last_hidden_states = outputs.last_hidden_state.reshape(-1, 768).cpu().numpy()[1:-1, :]
+ all_hidden.append(last_hidden_states)
+
+ #list_word = list_word[:10]
+ if list_word == []:
+ pass
+ else:
+ if first:
+ global_len = 0
+ str_word = ' '.join(map(str, list_word))
+ end = -1
+ offset_word = []
+ for k, wordvalue in enumerate(list_word):
+ start = end+1
+ end = start+len(wordvalue)
+ offset_word.append((start, end))
+ #print(offset_word)
+ token_scan = tokenizer.encode_plus(str_word, return_offsets_mapping=True)['offset_mapping']
+ #print(token_scan)
+ for start, end in offset_word:
+ sub_mapping = []
+ for i, (start_t, end_t) in enumerate(token_scan[1:-1]):
+ if int(start) <= int(start_t) and int(end_t) <= int(end):
+ sub_mapping.append(i+global_len)
+ #print(sub_mapping)
+ word_token_mapping.append(sub_mapping)
+ #print(len(word_token_mapping))
+ with torch.no_grad():
+ inputs = tokenizer(str_word, return_tensors="pt")
+ outputs = model(**inputs)
+ last_hidden_states = outputs.last_hidden_state.reshape(-1, 768).cpu().numpy()[1:-1, :]
+ all_hidden.append(last_hidden_states)
+ last_hidden_states = np.concatenate(all_hidden, axis=0)
+
+ for i in range(pose_each_file.shape[0]):
+ found_flag = False
+ current_time = i/self.args.pose_fps + time_offset
+ j_last = 0
+ for j, word in enumerate(tgrid[0]):
+ word_n, word_s, word_e = word.mark, word.minTime, word.maxTime
+ if word_s<=current_time and current_time<=word_e:
+ if self.args.word_cache and self.args.t_pre_encoder == 'bert':
+ mapping_index = word_token_mapping[j]
+ #print(mapping_index, word_s, word_e)
+ s_t = np.linspace(word_s, word_e, len(mapping_index)+1)
+ #print(s_t)
+ for tt, t_sep in enumerate(s_t[1:]):
+ if current_time <= t_sep:
+ #if len(mapping_index) > 1: print(mapping_index[tt])
+ word_each_file.append(last_hidden_states[mapping_index[tt]])
+ break
+ else:
+ if word_n == " ":
+ word_each_file.append(self.lang_model.PAD_token)
+ else:
+ word_each_file.append(self.lang_model.get_word_index(word_n))
+ found_flag = True
+ j_last = j
+ break
+ else: continue
+ if not found_flag:
+ if self.args.word_cache and self.args.t_pre_encoder == 'bert':
+ word_each_file.append(last_hidden_states[j_last])
+ else:
+ word_each_file.append(self.lang_model.UNK_token)
+ word_each_file = np.array(word_each_file)
+ #print(word_each_file.shape)
+
+ if self.args.emo_rep is not None:
+ logger.info(f"# ---- Building cache for Emo {id_pose} and Pose {id_pose} ---- #")
+ rtype, start = int(id_pose.split('_')[3]), int(id_pose.split('_')[3])
+ if rtype == 0 or rtype == 2 or rtype == 4 or rtype == 6:
+ if start >= 1 and start <= 64:
+ score = 0
+ elif start >= 65 and start <= 72:
+ score = 1
+ elif start >= 73 and start <= 80:
+ score = 2
+ elif start >= 81 and start <= 86:
+ score = 3
+ elif start >= 87 and start <= 94:
+ score = 4
+ elif start >= 95 and start <= 102:
+ score = 5
+ elif start >= 103 and start <= 110:
+ score = 6
+ elif start >= 111 and start <= 118:
+ score = 7
+ else: pass
+ else:
+ # you may denote as unknown in the future
+ score = 0
+ emo_each_file = np.repeat(np.array(score).reshape(1, 1), pose_each_file.shape[0], axis=0)
+ #print(emo_each_file)
+
+ if self.args.sem_rep is not None:
+ logger.info(f"# ---- Building cache for Sem {id_pose} and Pose {id_pose} ---- #")
+ sem_file = f"{self.data_dir}{self.args.sem_rep}/{id_pose}.txt"
+ sem_all = pd.read_csv(sem_file,
+ sep='\t',
+ names=["name", "start_time", "end_time", "duration", "score", "keywords"])
+ # we adopt motion-level semantic score here.
+ for i in range(pose_each_file.shape[0]):
+ found_flag = False
+ for j, (start, end, score) in enumerate(zip(sem_all['start_time'],sem_all['end_time'], sem_all['score'])):
+ current_time = i/self.args.pose_fps + time_offset
+ if start<=current_time and current_time<=end:
+ sem_each_file.append(score)
+ found_flag=True
+ break
+ else: continue
+ if not found_flag: sem_each_file.append(0.)
+ sem_each_file = np.array(sem_each_file)
+ #print(sem_each_file)
+
+ filtered_result = self._sample_from_clip(
+ dst_lmdb_env,
+ audio_each_file, pose_each_file, trans_each_file, shape_each_file, facial_each_file, word_each_file,
+ vid_each_file, emo_each_file, sem_each_file,
+ disable_filtering, clean_first_seconds, clean_final_seconds, is_test,
+ )
+ for type in filtered_result.keys():
+ n_filtered_out[type] += filtered_result[type]
+
+ with dst_lmdb_env.begin() as txn:
+ logger.info(colored(f"no. of samples: {txn.stat()['entries']}", "cyan"))
+ n_total_filtered = 0
+ for type, n_filtered in n_filtered_out.items():
+ logger.info("{}: {}".format(type, n_filtered))
+ n_total_filtered += n_filtered
+ logger.info(colored("no. of excluded samples: {} ({:.1f}%)".format(
+ n_total_filtered, 100 * n_total_filtered / (txn.stat()["entries"] + n_total_filtered)), "cyan"))
+ dst_lmdb_env.sync()
+ dst_lmdb_env.close()
+
+ def _sample_from_clip(
+ self, dst_lmdb_env, audio_each_file, pose_each_file, trans_each_file, shape_each_file, facial_each_file, word_each_file,
+ vid_each_file, emo_each_file, sem_each_file,
+ disable_filtering, clean_first_seconds, clean_final_seconds, is_test,
+ ):
+ """
+ for data cleaning, we ignore the data for first and final n s
+ for test, we return all data
+ """
+ # audio_start = int(self.alignment[0] * self.args.audio_fps)
+ # pose_start = int(self.alignment[1] * self.args.pose_fps)
+ #logger.info(f"before: {audio_each_file.shape} {pose_each_file.shape}")
+ # audio_each_file = audio_each_file[audio_start:]
+ # pose_each_file = pose_each_file[pose_start:]
+ # trans_each_file =
+ #logger.info(f"after alignment: {audio_each_file.shape} {pose_each_file.shape}")
+ #print(pose_each_file.shape)
+ round_seconds_skeleton = pose_each_file.shape[0] // self.args.pose_fps # assume 1500 frames / 15 fps = 100 s
+ print(pose_each_file.shape[0])
+ #print(round_seconds_skeleton)
+ #if audio_each_file != []:
+ if self.args.audio_rep != "wave16k":
+ round_seconds_audio = len(audio_each_file) // self.args.audio_fps # assume 16,000,00 / 16,000 = 100 s
+ elif self.args.audio_rep == "mfcc":
+ round_seconds_audio = audio_each_file.shape[0] // self.args.audio_fps
+ else:
+ round_seconds_audio = audio_each_file.shape[0] // self.args.audio_sr
+ # if facial_each_file != []:
+ round_seconds_facial = facial_each_file.shape[0] // self.args.pose_fps
+ logger.info(f"audio: {round_seconds_audio}s, pose: {round_seconds_skeleton}s, facial: {round_seconds_facial}s")
+ round_seconds_skeleton = min(round_seconds_audio, round_seconds_skeleton, round_seconds_facial)
+ max_round = max(round_seconds_audio, round_seconds_skeleton, round_seconds_facial)
+ if round_seconds_skeleton != max_round:
+ logger.warning(f"reduce to {round_seconds_skeleton}s, ignore {max_round-round_seconds_skeleton}s")
+ # else:
+ # logger.info(f"pose: {round_seconds_skeleton}s, audio: {round_seconds_audio}s")
+ # round_seconds_skeleton = min(round_seconds_audio, round_seconds_skeleton)
+ # max_round = max(round_seconds_audio, round_seconds_skeleton)
+ # if round_seconds_skeleton != max_round:
+ # logger.warning(f"reduce to {round_seconds_skeleton}s, ignore {max_round-round_seconds_skeleton}s")
+
+ clip_s_t, clip_e_t = clean_first_seconds, round_seconds_skeleton - clean_final_seconds # assume [10, 90]s
+ clip_s_f_audio, clip_e_f_audio = self.args.audio_fps * clip_s_t, clip_e_t * self.args.audio_fps # [160,000,90*160,000]
+ clip_s_f_pose, clip_e_f_pose = clip_s_t * self.args.pose_fps, clip_e_t * self.args.pose_fps # [150,90*15]
+
+
+ for ratio in self.args.multi_length_training:
+ if is_test:# stride = length for test
+ cut_length = clip_e_f_pose - clip_s_f_pose
+ self.args.stride = cut_length
+ self.max_length = cut_length
+ else:
+ self.args.stride = int(ratio*self.ori_stride)
+ cut_length = int(self.ori_length*ratio)
+
+ num_subdivision = math.floor((clip_e_f_pose - clip_s_f_pose - cut_length) / self.args.stride) + 1
+ logger.info(f"pose from frame {clip_s_f_pose} to {clip_e_f_pose}, length {cut_length}")
+ logger.info(f"{num_subdivision} clips is expected with stride {self.args.stride}")
+
+ # if audio_each_file != []:
+ audio_short_length = math.floor(cut_length / self.args.pose_fps * self.args.audio_fps)
+ logger.info(f"audio from frame {clip_s_f_audio} to {clip_e_f_audio}, length {audio_short_length}")
+
+ n_filtered_out = defaultdict(int)
+ sample_pose_list = []
+ sample_audio_list = []
+ sample_facial_list = []
+ sample_shape_list = []
+ sample_word_list = []
+ sample_emo_list = []
+ sample_sem_list = []
+ sample_vid_list = []
+ sample_trans_list = []
+
+ for i in range(num_subdivision): # cut into around 2s chip, (self npose)
+ start_idx = clip_s_f_pose + i * self.args.stride
+ fin_idx = start_idx + cut_length
+ sample_pose = pose_each_file[start_idx:fin_idx]
+
+ sample_trans = trans_each_file[start_idx:fin_idx]
+ sample_shape = shape_each_file[start_idx:fin_idx]
+ # print(sample_pose.shape)
+ if self.args.audio_rep is not None:
+ audio_start = clip_s_f_audio + math.floor(i * self.args.stride * self.args.audio_fps / self.args.pose_fps)
+ audio_end = audio_start + audio_short_length
+ sample_audio = audio_each_file[audio_start:audio_end]
+ else:
+ sample_audio = np.array([-1])
+ sample_facial = facial_each_file[start_idx:fin_idx] if self.args.facial_rep is not None else np.array([-1])
+ sample_word = word_each_file[start_idx:fin_idx] if self.args.word_rep is not None else np.array([-1])
+ sample_emo = emo_each_file[start_idx:fin_idx] if self.args.emo_rep is not None else np.array([-1])
+ sample_sem = sem_each_file[start_idx:fin_idx] if self.args.sem_rep is not None else np.array([-1])
+ sample_vid = vid_each_file[start_idx:fin_idx] if self.args.id_rep is not None else np.array([-1])
+
+ if sample_pose.any() != None:
+ # filtering motion skeleton data
+ sample_pose, filtering_message = MotionPreprocessor(sample_pose).get()
+ is_correct_motion = True #(sample_pose != [])
+ if is_correct_motion or disable_filtering:
+ sample_pose_list.append(sample_pose)
+ sample_audio_list.append(sample_audio)
+ sample_facial_list.append(sample_facial)
+ sample_shape_list.append(sample_shape)
+ sample_word_list.append(sample_word)
+ sample_vid_list.append(sample_vid)
+ sample_emo_list.append(sample_emo)
+ sample_sem_list.append(sample_sem)
+ sample_trans_list.append(sample_trans)
+ else:
+ n_filtered_out[filtering_message] += 1
+
+ if len(sample_pose_list) > 0:
+ with dst_lmdb_env.begin(write=True) as txn:
+ for pose, audio, facial, shape, word, vid, emo, sem, trans in zip(
+ sample_pose_list,
+ sample_audio_list,
+ sample_facial_list,
+ sample_shape_list,
+ sample_word_list,
+ sample_vid_list,
+ sample_emo_list,
+ sample_sem_list,
+ sample_trans_list,):
+ k = "{:005}".format(self.n_out_samples).encode("ascii")
+ v = [pose, audio, facial, shape, word, emo, sem, vid, trans]
+ # v = pyarrow.serialize(v).to_buffer()
+ # txn.put(k, v)
+ # self.n_out_samples += 1
+ v = pickle.dumps(v)
+ txn.put(k, v)
+ self.n_out_samples += 1
+ return n_filtered_out
+
+ def __getitem__(self, idx):
+ with self.lmdb_env.begin(write=False) as txn:
+ key = "{:005}".format(idx).encode("ascii")
+ sample = txn.get(key)
+ # sample = pyarrow.deserialize(sample)
+ if sample is not None:
+ sample = pickle.loads(sample)
+ tar_pose, in_audio, in_facial, in_shape, in_word, emo, sem, vid, trans = sample
+ #print(in_shape)
+ #vid = torch.from_numpy(vid).int()
+ emo = torch.from_numpy(emo).int()
+ sem = torch.from_numpy(sem).float()
+ in_audio = torch.from_numpy(in_audio).float()
+ in_word = torch.from_numpy(in_word).float() if self.args.word_cache else torch.from_numpy(in_word).int()
+ if self.loader_type == "test":
+ tar_pose = torch.from_numpy(tar_pose).float()
+ trans = torch.from_numpy(trans).float()
+ in_facial = torch.from_numpy(in_facial).float()
+ vid = torch.from_numpy(vid).float()
+ in_shape = torch.from_numpy(in_shape).float()
+ else:
+ in_shape = torch.from_numpy(in_shape).reshape((in_shape.shape[0], -1)).float()
+ trans = torch.from_numpy(trans).reshape((trans.shape[0], -1)).float()
+ vid = torch.from_numpy(vid).reshape((vid.shape[0], -1)).float()
+ tar_pose = torch.from_numpy(tar_pose).reshape((tar_pose.shape[0], -1)).float()
+ in_facial = torch.from_numpy(in_facial).reshape((in_facial.shape[0], -1)).float()
+ return {"pose":tar_pose, "audio":in_audio, "facial":in_facial, "beta": in_shape, "word":in_word, "id":vid, "emo":emo, "sem":sem, "trans":trans}
+
+
+class MotionPreprocessor:
+ def __init__(self, skeletons):
+ self.skeletons = skeletons
+ #self.mean_pose = mean_pose
+ self.filtering_message = "PASS"
+
+ def get(self):
+ assert (self.skeletons is not None)
+
+ # filtering
+ # if self.skeletons != []:
+ # if self.check_pose_diff():
+ # self.skeletons = []
+ # self.filtering_message = "pose"
+ # elif self.check_spine_angle():
+ # self.skeletons = []
+ # self.filtering_message = "spine angle"
+ # elif self.check_static_motion():
+ # self.skeletons = []
+ # self.filtering_message = "motion"
+
+ # if self.skeletons != []:
+ # self.skeletons = self.skeletons.tolist()
+ # for i, frame in enumerate(self.skeletons):
+ # assert not np.isnan(self.skeletons[i]).any() # missing joints
+
+ return self.skeletons, self.filtering_message
+
+ def check_static_motion(self, verbose=True):
+ def get_variance(skeleton, joint_idx):
+ wrist_pos = skeleton[:, joint_idx]
+ variance = np.sum(np.var(wrist_pos, axis=0))
+ return variance
+
+ left_arm_var = get_variance(self.skeletons, 6)
+ right_arm_var = get_variance(self.skeletons, 9)
+
+ th = 0.0014 # exclude 13110
+ # th = 0.002 # exclude 16905
+ if left_arm_var < th and right_arm_var < th:
+ if verbose:
+ print("skip - check_static_motion left var {}, right var {}".format(left_arm_var, right_arm_var))
+ return True
+ else:
+ if verbose:
+ print("pass - check_static_motion left var {}, right var {}".format(left_arm_var, right_arm_var))
+ return False
+
+
+ def check_pose_diff(self, verbose=False):
+# diff = np.abs(self.skeletons - self.mean_pose) # 186*1
+# diff = np.mean(diff)
+
+# # th = 0.017
+# th = 0.02 #0.02 # exclude 3594
+# if diff < th:
+# if verbose:
+# print("skip - check_pose_diff {:.5f}".format(diff))
+# return True
+# # th = 3.5 #0.02 # exclude 3594
+# # if 3.5 < diff < 5:
+# # if verbose:
+# # print("skip - check_pose_diff {:.5f}".format(diff))
+# # return True
+# else:
+# if verbose:
+# print("pass - check_pose_diff {:.5f}".format(diff))
+ return False
+
+
+ def check_spine_angle(self, verbose=True):
+ def angle_between(v1, v2):
+ v1_u = v1 / np.linalg.norm(v1)
+ v2_u = v2 / np.linalg.norm(v2)
+ return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0))
+
+ angles = []
+ for i in range(self.skeletons.shape[0]):
+ spine_vec = self.skeletons[i, 1] - self.skeletons[i, 0]
+ angle = angle_between(spine_vec, [0, -1, 0])
+ angles.append(angle)
+
+ if np.rad2deg(max(angles)) > 30 or np.rad2deg(np.mean(angles)) > 20: # exclude 4495
+ # if np.rad2deg(max(angles)) > 20: # exclude 8270
+ if verbose:
+ print("skip - check_spine_angle {:.5f}, {:.5f}".format(max(angles), np.mean(angles)))
+ return True
+ else:
+ if verbose:
+ print("pass - check_spine_angle {:.5f}".format(max(angles)))
+ return False
\ No newline at end of file
diff --git a/dataloaders/__pycache__/beat_testonly_hf.cpython-310.pyc b/dataloaders/__pycache__/beat_testonly_hf.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a6606ef23e6ff89c968415cbd5938753b2e7b450
Binary files /dev/null and b/dataloaders/__pycache__/beat_testonly_hf.cpython-310.pyc differ
diff --git a/dataloaders/__pycache__/beat_testonly_hf.cpython-38.pyc b/dataloaders/__pycache__/beat_testonly_hf.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4b4442886fefd170a44a27598eab176fc9abaad5
Binary files /dev/null and b/dataloaders/__pycache__/beat_testonly_hf.cpython-38.pyc differ
diff --git a/dataloaders/__pycache__/build_vocab.cpython-310.pyc b/dataloaders/__pycache__/build_vocab.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ed333dec7d794bddf8216370abad83cdcd6bbbb6
Binary files /dev/null and b/dataloaders/__pycache__/build_vocab.cpython-310.pyc differ
diff --git a/dataloaders/__pycache__/build_vocab.cpython-38.pyc b/dataloaders/__pycache__/build_vocab.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f391643b5e18cafcb145e2d8049141c978a0e26a
Binary files /dev/null and b/dataloaders/__pycache__/build_vocab.cpython-38.pyc differ
diff --git a/dataloaders/__pycache__/data_tools.cpython-310.pyc b/dataloaders/__pycache__/data_tools.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..cdf63580251ed8ad599b546f3defd04e1491f38c
Binary files /dev/null and b/dataloaders/__pycache__/data_tools.cpython-310.pyc differ
diff --git a/dataloaders/__pycache__/data_tools.cpython-38.pyc b/dataloaders/__pycache__/data_tools.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6ebb215579d4b2073878f92efe3fef3604c2fe00
Binary files /dev/null and b/dataloaders/__pycache__/data_tools.cpython-38.pyc differ
diff --git a/dataloaders/beat_sep.py b/dataloaders/beat_sep.py
new file mode 100644
index 0000000000000000000000000000000000000000..e5dc7dff9f52f0d8c9762946006fb6dd32540f23
--- /dev/null
+++ b/dataloaders/beat_sep.py
@@ -0,0 +1,771 @@
+import os
+import pickle
+import math
+import shutil
+import numpy as np
+import lmdb as lmdb
+import textgrid as tg
+import pandas as pd
+import torch
+import glob
+import json
+from termcolor import colored
+from loguru import logger
+from collections import defaultdict
+from torch.utils.data import Dataset
+import torch.distributed as dist
+import pyarrow
+import librosa
+import smplx
+
+from .build_vocab import Vocab
+from .utils.audio_features import Wav2Vec2Model
+from .data_tools import joints_list
+from .utils import rotation_conversions as rc
+from .utils import other_tools
+
+class CustomDataset(Dataset):
+ def __init__(self, args, loader_type, augmentation=None, kwargs=None, build_cache=True):
+ self.args = args
+ self.loader_type = loader_type
+
+ self.rank = dist.get_rank()
+ self.ori_stride = self.args.stride
+ self.ori_length = self.args.pose_length
+ self.alignment = [0,0] # for trinity
+
+ self.ori_joint_list = joints_list[self.args.ori_joints]
+ self.tar_joint_list = joints_list[self.args.tar_joints]
+ if 'smplx' in self.args.pose_rep:
+ self.joint_mask = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ self.joints = len(list(self.tar_joint_list.keys()))
+ for joint_name in self.tar_joint_list:
+ self.joint_mask[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ else:
+ self.joints = len(list(self.ori_joint_list.keys()))+1
+ self.joint_mask = np.zeros(self.joints*3)
+ for joint_name in self.tar_joint_list:
+ if joint_name == "Hips":
+ self.joint_mask[3:6] = 1
+ else:
+ self.joint_mask[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ # select trainable joints
+
+ split_rule = pd.read_csv(args.data_path+"train_test_split.csv")
+ self.selected_file = split_rule.loc[(split_rule['type'] == loader_type) & (split_rule['id'].str.split("_").str[0].astype(int).isin(self.args.training_speakers))]
+ if args.additional_data and loader_type == 'train':
+ split_b = split_rule.loc[(split_rule['type'] == 'additional') & (split_rule['id'].str.split("_").str[0].astype(int).isin(self.args.training_speakers))]
+ #self.selected_file = split_rule.loc[(split_rule['type'] == 'additional') & (split_rule['id'].str.split("_").str[0].astype(int).isin(self.args.training_speakers))]
+ self.selected_file = pd.concat([self.selected_file, split_b])
+ if self.selected_file.empty:
+ logger.warning(f"{loader_type} is empty for speaker {self.args.training_speakers}, use train set 0-8 instead")
+ self.selected_file = split_rule.loc[(split_rule['type'] == 'train') & (split_rule['id'].str.split("_").str[0].astype(int).isin(self.args.training_speakers))]
+ self.selected_file = self.selected_file.iloc[0:8]
+ self.data_dir = args.data_path
+
+ if loader_type == "test":
+ self.args.multi_length_training = [1.0]
+ self.max_length = int(args.pose_length * self.args.multi_length_training[-1])
+ self.max_audio_pre_len = math.floor(args.pose_length / args.pose_fps * self.args.audio_sr)
+ if self.max_audio_pre_len > self.args.test_length*self.args.audio_sr:
+ self.max_audio_pre_len = self.args.test_length*self.args.audio_sr
+
+ if args.word_rep is not None:
+ with open(f"{args.data_path}weights/vocab.pkl", 'rb') as f:
+ self.lang_model = pickle.load(f)
+
+ preloaded_dir = self.args.root_path + self.args.cache_path + loader_type + f"/{args.pose_rep}_cache"
+ # if args.pose_norm:
+ # # careful for rotation vectors
+ # if not os.path.exists(args.data_path+args.mean_pose_path+f"{args.pose_rep.split('_')[0]}/bvh_mean.npy"):
+ # self.calculate_mean_pose()
+ # self.mean_pose = np.load(args.data_path+args.mean_pose_path+f"{args.pose_rep.split('_')[0]}/bvh_mean.npy")
+ # self.std_pose = np.load(args.data_path+args.mean_pose_path+f"{args.pose_rep.split('_')[0]}/bvh_std.npy")
+ # if args.audio_norm:
+ # if not os.path.exists(args.data_path+args.mean_pose_path+f"{args.audio_rep.split('_')[0]}/bvh_mean.npy"):
+ # self.calculate_mean_audio()
+ # self.mean_audio = np.load(args.data_path+args.mean_pose_path+f"{args.audio_rep.split('_')[0]}/npy_mean.npy")
+ # self.std_audio = np.load(args.data_path+args.mean_pose_path+f"{args.audio_rep.split('_')[0]}/npy_std.npy")
+ # if args.facial_norm:
+ # if not os.path.exists(args.data_path+args.mean_pose_path+f"{args.pose_rep.split('_')[0]}/bvh_mean.npy"):
+ # self.calculate_mean_face()
+ # self.mean_facial = np.load(args.data_path+args.mean_pose_path+f"{args.facial_rep}/json_mean.npy")
+ # self.std_facial = np.load(args.data_path+args.mean_pose_path+f"{args.facial_rep}/json_std.npy")
+ if self.args.beat_align:
+ if not os.path.exists(args.data_path+f"weights/mean_vel_{args.pose_rep}.npy"):
+ self.calculate_mean_velocity(args.data_path+f"weights/mean_vel_{args.pose_rep}.npy")
+ self.avg_vel = np.load(args.data_path+f"weights/mean_vel_{args.pose_rep}.npy")
+
+ if build_cache and self.rank == 0:
+ self.build_cache(preloaded_dir)
+ self.lmdb_env = lmdb.open(preloaded_dir, readonly=True, lock=False)
+ with self.lmdb_env.begin() as txn:
+ self.n_samples = txn.stat()["entries"]
+
+
+ def calculate_mean_velocity(self, save_path):
+ self.smplx = smplx.create(
+ self.args.data_path_1+"smplx_models/",
+ model_type='smplx',
+ gender='NEUTRAL_2020',
+ use_face_contour=False,
+ num_betas=300,
+ num_expression_coeffs=100,
+ ext='npz',
+ use_pca=False,
+ ).cuda().eval()
+ dir_p = self.data_dir + self.args.pose_rep + "/"
+ all_list = []
+ from tqdm import tqdm
+ for tar in tqdm(os.listdir(dir_p)):
+ if tar.endswith(".npz"):
+ m_data = np.load(dir_p+tar, allow_pickle=True)
+ betas, poses, trans, exps = m_data["betas"], m_data["poses"], m_data["trans"], m_data["expressions"]
+ n, c = poses.shape[0], poses.shape[1]
+ betas = betas.reshape(1, 300)
+ betas = np.tile(betas, (n, 1))
+ betas = torch.from_numpy(betas).cuda().float()
+ poses = torch.from_numpy(poses.reshape(n, c)).cuda().float()
+ exps = torch.from_numpy(exps.reshape(n, 100)).cuda().float()
+ trans = torch.from_numpy(trans.reshape(n, 3)).cuda().float()
+ max_length = 128
+ s, r = n//max_length, n%max_length
+ #print(n, s, r)
+ all_tensor = []
+ for i in range(s):
+ with torch.no_grad():
+ joints = self.smplx(
+ betas=betas[i*max_length:(i+1)*max_length],
+ transl=trans[i*max_length:(i+1)*max_length],
+ expression=exps[i*max_length:(i+1)*max_length],
+ jaw_pose=poses[i*max_length:(i+1)*max_length, 66:69],
+ global_orient=poses[i*max_length:(i+1)*max_length,:3],
+ body_pose=poses[i*max_length:(i+1)*max_length,3:21*3+3],
+ left_hand_pose=poses[i*max_length:(i+1)*max_length,25*3:40*3],
+ right_hand_pose=poses[i*max_length:(i+1)*max_length,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=poses[i*max_length:(i+1)*max_length, 69:72],
+ reye_pose=poses[i*max_length:(i+1)*max_length, 72:75],
+ )['joints'][:, :55, :].reshape(max_length, 55*3)
+ all_tensor.append(joints)
+ if r != 0:
+ with torch.no_grad():
+ joints = self.smplx(
+ betas=betas[s*max_length:s*max_length+r],
+ transl=trans[s*max_length:s*max_length+r],
+ expression=exps[s*max_length:s*max_length+r],
+ jaw_pose=poses[s*max_length:s*max_length+r, 66:69],
+ global_orient=poses[s*max_length:s*max_length+r,:3],
+ body_pose=poses[s*max_length:s*max_length+r,3:21*3+3],
+ left_hand_pose=poses[s*max_length:s*max_length+r,25*3:40*3],
+ right_hand_pose=poses[s*max_length:s*max_length+r,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=poses[s*max_length:s*max_length+r, 69:72],
+ reye_pose=poses[s*max_length:s*max_length+r, 72:75],
+ )['joints'][:, :55, :].reshape(r, 55*3)
+ all_tensor.append(joints)
+ joints = torch.cat(all_tensor, axis=0)
+ joints = joints.permute(1, 0)
+ dt = 1/30
+ # first steps is forward diff (t+1 - t) / dt
+ init_vel = (joints[:, 1:2] - joints[:, :1]) / dt
+ # middle steps are second order (t+1 - t-1) / 2dt
+ middle_vel = (joints[:, 2:] - joints[:, 0:-2]) / (2 * dt)
+ # last step is backward diff (t - t-1) / dt
+ final_vel = (joints[:, -1:] - joints[:, -2:-1]) / dt
+ #print(joints.shape, init_vel.shape, middle_vel.shape, final_vel.shape)
+ vel_seq = torch.cat([init_vel, middle_vel, final_vel], dim=1).permute(1, 0).reshape(n, 55, 3)
+ #print(vel_seq.shape)
+ #.permute(1, 0).reshape(n, 55, 3)
+ vel_seq_np = vel_seq.cpu().numpy()
+ vel_joints_np = np.linalg.norm(vel_seq_np, axis=2) # n * 55
+ all_list.append(vel_joints_np)
+ avg_vel = np.mean(np.concatenate(all_list, axis=0),axis=0) # 55
+ np.save(save_path, avg_vel)
+
+
+ def build_cache(self, preloaded_dir):
+ logger.info(f"Audio bit rate: {self.args.audio_fps}")
+ logger.info("Reading data '{}'...".format(self.data_dir))
+ logger.info("Creating the dataset cache...")
+ if self.args.new_cache:
+ if os.path.exists(preloaded_dir):
+ shutil.rmtree(preloaded_dir)
+ if os.path.exists(preloaded_dir):
+ logger.info("Found the cache {}".format(preloaded_dir))
+ elif self.loader_type == "test":
+ self.cache_generation(
+ preloaded_dir, True,
+ 0, 0,
+ is_test=True)
+ else:
+ self.cache_generation(
+ preloaded_dir, self.args.disable_filtering,
+ self.args.clean_first_seconds, self.args.clean_final_seconds,
+ is_test=False)
+
+ def __len__(self):
+ return self.n_samples
+
+
+ def cache_generation(self, out_lmdb_dir, disable_filtering, clean_first_seconds, clean_final_seconds, is_test=False):
+ # if "wav2vec2" in self.args.audio_rep:
+ # self.wav2vec_model = Wav2Vec2Model.from_pretrained(f"{self.args.data_path_1}/hub/transformer/wav2vec2-base-960h")
+ # self.wav2vec_model.feature_extractor._freeze_parameters()
+ # self.wav2vec_model = self.wav2vec_model.cuda()
+ # self.wav2vec_model.eval()
+
+ self.n_out_samples = 0
+ # create db for samples
+ if not os.path.exists(out_lmdb_dir): os.makedirs(out_lmdb_dir)
+ dst_lmdb_env = lmdb.open(out_lmdb_dir, map_size= int(1024 ** 3 * 50))# 50G
+ n_filtered_out = defaultdict(int)
+
+ for index, file_name in self.selected_file.iterrows():
+ f_name = file_name["id"]
+ ext = ".npz" if "smplx" in self.args.pose_rep else ".bvh"
+ pose_file = self.data_dir + self.args.pose_rep + "/" + f_name + ext
+ pose_each_file = []
+ trans_each_file = []
+ shape_each_file = []
+ audio_each_file = []
+ facial_each_file = []
+ word_each_file = []
+ emo_each_file = []
+ sem_each_file = []
+ vid_each_file = []
+ id_pose = f_name #1_wayne_0_1_1
+
+ logger.info(colored(f"# ---- Building cache for Pose {id_pose} ---- #", "blue"))
+ if "smplx" in self.args.pose_rep:
+ pose_data = np.load(pose_file, allow_pickle=True)
+ assert 30%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 30'
+ stride = int(30/self.args.pose_fps)
+ pose_each_file = pose_data["poses"][::stride] * self.joint_mask
+ pose_each_file = pose_each_file[:, self.joint_mask.astype(bool)]
+ # print(pose_each_file.shape)
+ trans_each_file = pose_data["trans"][::stride]
+ shape_each_file = np.repeat(pose_data["betas"].reshape(1, 300), pose_each_file.shape[0], axis=0)
+ if self.args.facial_rep is not None:
+ logger.info(f"# ---- Building cache for Facial {id_pose} and Pose {id_pose} ---- #")
+ facial_each_file = pose_data["expressions"][::stride]
+ if self.args.facial_norm:
+ facial_each_file = (facial_each_file - self.mean_facial) / self.std_facial
+
+ else:
+ assert 120%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 120'
+ stride = int(120/self.args.pose_fps)
+ with open(pose_file, "r") as pose_data:
+ for j, line in enumerate(pose_data.readlines()):
+ if j < 431: continue
+ if j%stride != 0:continue
+ data = np.fromstring(line, dtype=float, sep=" ")
+ rot_data = rc.euler_angles_to_matrix(torch.from_numpy(np.deg2rad(data)).reshape(-1, self.joints,3), "XYZ")
+ rot_data = rc.matrix_to_axis_angle(rot_data).reshape(-1, self.joints*3)
+ rot_data = rot_data.numpy() * self.joint_mask
+
+ pose_each_file.append(rot_data)
+ trans_each_file.append(data[:3])
+
+ pose_each_file = np.array(pose_each_file)
+ # print(pose_each_file.shape)
+ trans_each_file = np.array(trans_each_file)
+ shape_each_file = np.repeat(np.array(-1).reshape(1, 1), pose_each_file.shape[0], axis=0)
+ if self.args.facial_rep is not None:
+ logger.info(f"# ---- Building cache for Facial {id_pose} and Pose {id_pose} ---- #")
+ facial_file = pose_file.replace(self.args.pose_rep, self.args.facial_rep).replace("bvh", "json")
+ assert 60%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 120'
+ stride = int(60/self.args.pose_fps)
+ if not os.path.exists(facial_file):
+ logger.warning(f"# ---- file not found for Facial {id_pose}, skip all files with the same id ---- #")
+ self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ continue
+ with open(facial_file, 'r') as facial_data_file:
+ facial_data = json.load(facial_data_file)
+ for j, frame_data in enumerate(facial_data['frames']):
+ if j%stride != 0:continue
+ facial_each_file.append(frame_data['weights'])
+ facial_each_file = np.array(facial_each_file)
+ if self.args.facial_norm:
+ facial_each_file = (facial_each_file - self.mean_facial) / self.std_facial
+
+ if self.args.id_rep is not None:
+ vid_each_file = np.repeat(np.array(int(f_name.split("_")[0])-1).reshape(1, 1), pose_each_file.shape[0], axis=0)
+
+ if self.args.audio_rep is not None:
+ logger.info(f"# ---- Building cache for Audio {id_pose} and Pose {id_pose} ---- #")
+ audio_file = pose_file.replace(self.args.pose_rep, 'wave16k').replace(ext, ".wav")
+ if not os.path.exists(audio_file):
+ logger.warning(f"# ---- file not found for Audio {id_pose}, skip all files with the same id ---- #")
+ self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ continue
+ audio_each_file, sr = librosa.load(audio_file)
+ audio_each_file = librosa.resample(audio_each_file, orig_sr=sr, target_sr=self.args.audio_sr)
+ if self.args.audio_rep == "onset+amplitude":
+ from numpy.lib import stride_tricks
+ frame_length = 1024
+ # hop_length = 512
+ shape = (audio_each_file.shape[-1] - frame_length + 1, frame_length)
+ strides = (audio_each_file.strides[-1], audio_each_file.strides[-1])
+ rolling_view = stride_tricks.as_strided(audio_each_file, shape=shape, strides=strides)
+ amplitude_envelope = np.max(np.abs(rolling_view), axis=1)
+ # pad the last frame_length-1 samples
+ amplitude_envelope = np.pad(amplitude_envelope, (0, frame_length-1), mode='constant', constant_values=amplitude_envelope[-1])
+ audio_onset_f = librosa.onset.onset_detect(y=audio_each_file, sr=self.args.audio_sr, units='frames')
+ onset_array = np.zeros(len(audio_each_file), dtype=float)
+ onset_array[audio_onset_f] = 1.0
+ # print(amplitude_envelope.shape, audio_each_file.shape, onset_array.shape)
+ audio_each_file = np.concatenate([amplitude_envelope.reshape(-1, 1), onset_array.reshape(-1, 1)], axis=1)
+ elif self.args.audio_rep == "mfcc":
+ audio_each_file = librosa.feature.melspectrogram(y=audio_each_file, sr=self.args.audio_sr, n_mels=128, hop_length=int(self.args.audio_sr/self.args.audio_fps))
+ audio_each_file = audio_each_file.transpose(1, 0)
+ # print(audio_each_file.shape, pose_each_file.shape)
+ if self.args.audio_norm and self.args.audio_rep == "wave16k":
+ audio_each_file = (audio_each_file - self.mean_audio) / self.std_audio
+ # print(audio_each_file.shape)
+ time_offset = 0
+ if self.args.word_rep is not None:
+ logger.info(f"# ---- Building cache for Word {id_pose} and Pose {id_pose} ---- #")
+ word_file = f"{self.data_dir}{self.args.word_rep}/{id_pose}.TextGrid"
+ if not os.path.exists(word_file):
+ logger.warning(f"# ---- file not found for Word {id_pose}, skip all files with the same id ---- #")
+ self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ continue
+ tgrid = tg.TextGrid.fromFile(word_file)
+ if self.args.t_pre_encoder == "bert":
+ from transformers import AutoTokenizer, BertModel
+ tokenizer = AutoTokenizer.from_pretrained(self.args.data_path_1 + "hub/bert-base-uncased", local_files_only=True)
+ model = BertModel.from_pretrained(self.args.data_path_1 + "hub/bert-base-uncased", local_files_only=True).eval()
+ list_word = []
+ all_hidden = []
+ max_len = 400
+ last = 0
+ word_token_mapping = []
+ first = True
+ for i, word in enumerate(tgrid[0]):
+ last = i
+ if (i%max_len != 0) or (i==0):
+ if word.mark == "":
+ list_word.append(".")
+ else:
+ list_word.append(word.mark)
+ else:
+ max_counter = max_len
+ str_word = ' '.join(map(str, list_word))
+ if first:
+ global_len = 0
+ end = -1
+ offset_word = []
+ for k, wordvalue in enumerate(list_word):
+ start = end+1
+ end = start+len(wordvalue)
+ offset_word.append((start, end))
+ #print(offset_word)
+ token_scan = tokenizer.encode_plus(str_word, return_offsets_mapping=True)['offset_mapping']
+ #print(token_scan)
+ for start, end in offset_word:
+ sub_mapping = []
+ for i, (start_t, end_t) in enumerate(token_scan[1:-1]):
+ if int(start) <= int(start_t) and int(end_t) <= int(end):
+ #print(i+global_len)
+ sub_mapping.append(i+global_len)
+ word_token_mapping.append(sub_mapping)
+ #print(len(word_token_mapping))
+ global_len = word_token_mapping[-1][-1] + 1
+ list_word = []
+ if word.mark == "":
+ list_word.append(".")
+ else:
+ list_word.append(word.mark)
+
+ with torch.no_grad():
+ inputs = tokenizer(str_word, return_tensors="pt")
+ outputs = model(**inputs)
+ last_hidden_states = outputs.last_hidden_state.reshape(-1, 768).cpu().numpy()[1:-1, :]
+ all_hidden.append(last_hidden_states)
+
+ #list_word = list_word[:10]
+ if list_word == []:
+ pass
+ else:
+ if first:
+ global_len = 0
+ str_word = ' '.join(map(str, list_word))
+ end = -1
+ offset_word = []
+ for k, wordvalue in enumerate(list_word):
+ start = end+1
+ end = start+len(wordvalue)
+ offset_word.append((start, end))
+ #print(offset_word)
+ token_scan = tokenizer.encode_plus(str_word, return_offsets_mapping=True)['offset_mapping']
+ #print(token_scan)
+ for start, end in offset_word:
+ sub_mapping = []
+ for i, (start_t, end_t) in enumerate(token_scan[1:-1]):
+ if int(start) <= int(start_t) and int(end_t) <= int(end):
+ sub_mapping.append(i+global_len)
+ #print(sub_mapping)
+ word_token_mapping.append(sub_mapping)
+ #print(len(word_token_mapping))
+ with torch.no_grad():
+ inputs = tokenizer(str_word, return_tensors="pt")
+ outputs = model(**inputs)
+ last_hidden_states = outputs.last_hidden_state.reshape(-1, 768).cpu().numpy()[1:-1, :]
+ all_hidden.append(last_hidden_states)
+ last_hidden_states = np.concatenate(all_hidden, axis=0)
+
+ for i in range(pose_each_file.shape[0]):
+ found_flag = False
+ current_time = i/self.args.pose_fps + time_offset
+ j_last = 0
+ for j, word in enumerate(tgrid[0]):
+ word_n, word_s, word_e = word.mark, word.minTime, word.maxTime
+ if word_s<=current_time and current_time<=word_e:
+ if self.args.word_cache and self.args.t_pre_encoder == 'bert':
+ mapping_index = word_token_mapping[j]
+ #print(mapping_index, word_s, word_e)
+ s_t = np.linspace(word_s, word_e, len(mapping_index)+1)
+ #print(s_t)
+ for tt, t_sep in enumerate(s_t[1:]):
+ if current_time <= t_sep:
+ #if len(mapping_index) > 1: print(mapping_index[tt])
+ word_each_file.append(last_hidden_states[mapping_index[tt]])
+ break
+ else:
+ if word_n == " ":
+ word_each_file.append(self.lang_model.PAD_token)
+ else:
+ word_each_file.append(self.lang_model.get_word_index(word_n))
+ found_flag = True
+ j_last = j
+ break
+ else: continue
+ if not found_flag:
+ if self.args.word_cache and self.args.t_pre_encoder == 'bert':
+ word_each_file.append(last_hidden_states[j_last])
+ else:
+ word_each_file.append(self.lang_model.UNK_token)
+ word_each_file = np.array(word_each_file)
+ #print(word_each_file.shape)
+
+ if self.args.emo_rep is not None:
+ logger.info(f"# ---- Building cache for Emo {id_pose} and Pose {id_pose} ---- #")
+ rtype, start = int(id_pose.split('_')[3]), int(id_pose.split('_')[3])
+ if rtype == 0 or rtype == 2 or rtype == 4 or rtype == 6:
+ if start >= 1 and start <= 64:
+ score = 0
+ elif start >= 65 and start <= 72:
+ score = 1
+ elif start >= 73 and start <= 80:
+ score = 2
+ elif start >= 81 and start <= 86:
+ score = 3
+ elif start >= 87 and start <= 94:
+ score = 4
+ elif start >= 95 and start <= 102:
+ score = 5
+ elif start >= 103 and start <= 110:
+ score = 6
+ elif start >= 111 and start <= 118:
+ score = 7
+ else: pass
+ else:
+ # you may denote as unknown in the future
+ score = 0
+ emo_each_file = np.repeat(np.array(score).reshape(1, 1), pose_each_file.shape[0], axis=0)
+ #print(emo_each_file)
+
+ if self.args.sem_rep is not None:
+ logger.info(f"# ---- Building cache for Sem {id_pose} and Pose {id_pose} ---- #")
+ sem_file = f"{self.data_dir}{self.args.sem_rep}/{id_pose}.txt"
+ sem_all = pd.read_csv(sem_file,
+ sep='\t',
+ names=["name", "start_time", "end_time", "duration", "score", "keywords"])
+ # we adopt motion-level semantic score here.
+ for i in range(pose_each_file.shape[0]):
+ found_flag = False
+ for j, (start, end, score) in enumerate(zip(sem_all['start_time'],sem_all['end_time'], sem_all['score'])):
+ current_time = i/self.args.pose_fps + time_offset
+ if start<=current_time and current_time<=end:
+ sem_each_file.append(score)
+ found_flag=True
+ break
+ else: continue
+ if not found_flag: sem_each_file.append(0.)
+ sem_each_file = np.array(sem_each_file)
+ #print(sem_each_file)
+
+ filtered_result = self._sample_from_clip(
+ dst_lmdb_env,
+ audio_each_file, pose_each_file, trans_each_file, shape_each_file, facial_each_file, word_each_file,
+ vid_each_file, emo_each_file, sem_each_file,
+ disable_filtering, clean_first_seconds, clean_final_seconds, is_test,
+ )
+ for type in filtered_result.keys():
+ n_filtered_out[type] += filtered_result[type]
+
+ with dst_lmdb_env.begin() as txn:
+ logger.info(colored(f"no. of samples: {txn.stat()['entries']}", "cyan"))
+ n_total_filtered = 0
+ for type, n_filtered in n_filtered_out.items():
+ logger.info("{}: {}".format(type, n_filtered))
+ n_total_filtered += n_filtered
+ logger.info(colored("no. of excluded samples: {} ({:.1f}%)".format(
+ n_total_filtered, 100 * n_total_filtered / (txn.stat()["entries"] + n_total_filtered)), "cyan"))
+ dst_lmdb_env.sync()
+ dst_lmdb_env.close()
+
+ def _sample_from_clip(
+ self, dst_lmdb_env, audio_each_file, pose_each_file, trans_each_file, shape_each_file, facial_each_file, word_each_file,
+ vid_each_file, emo_each_file, sem_each_file,
+ disable_filtering, clean_first_seconds, clean_final_seconds, is_test,
+ ):
+ """
+ for data cleaning, we ignore the data for first and final n s
+ for test, we return all data
+ """
+ # audio_start = int(self.alignment[0] * self.args.audio_fps)
+ # pose_start = int(self.alignment[1] * self.args.pose_fps)
+ #logger.info(f"before: {audio_each_file.shape} {pose_each_file.shape}")
+ # audio_each_file = audio_each_file[audio_start:]
+ # pose_each_file = pose_each_file[pose_start:]
+ # trans_each_file =
+ #logger.info(f"after alignment: {audio_each_file.shape} {pose_each_file.shape}")
+ #print(pose_each_file.shape)
+ round_seconds_skeleton = pose_each_file.shape[0] // self.args.pose_fps # assume 1500 frames / 15 fps = 100 s
+ #print(round_seconds_skeleton)
+ if audio_each_file != []:
+ if self.args.audio_rep != "wave16k":
+ round_seconds_audio = len(audio_each_file) // self.args.audio_fps # assume 16,000,00 / 16,000 = 100 s
+ elif self.args.audio_rep == "mfcc":
+ round_seconds_audio = audio_each_file.shape[0] // self.args.audio_fps
+ else:
+ round_seconds_audio = audio_each_file.shape[0] // self.args.audio_sr
+ if facial_each_file != []:
+ round_seconds_facial = facial_each_file.shape[0] // self.args.pose_fps
+ logger.info(f"audio: {round_seconds_audio}s, pose: {round_seconds_skeleton}s, facial: {round_seconds_facial}s")
+ round_seconds_skeleton = min(round_seconds_audio, round_seconds_skeleton, round_seconds_facial)
+ max_round = max(round_seconds_audio, round_seconds_skeleton, round_seconds_facial)
+ if round_seconds_skeleton != max_round:
+ logger.warning(f"reduce to {round_seconds_skeleton}s, ignore {max_round-round_seconds_skeleton}s")
+ else:
+ logger.info(f"pose: {round_seconds_skeleton}s, audio: {round_seconds_audio}s")
+ round_seconds_skeleton = min(round_seconds_audio, round_seconds_skeleton)
+ max_round = max(round_seconds_audio, round_seconds_skeleton)
+ if round_seconds_skeleton != max_round:
+ logger.warning(f"reduce to {round_seconds_skeleton}s, ignore {max_round-round_seconds_skeleton}s")
+
+ clip_s_t, clip_e_t = clean_first_seconds, round_seconds_skeleton - clean_final_seconds # assume [10, 90]s
+ clip_s_f_audio, clip_e_f_audio = self.args.audio_fps * clip_s_t, clip_e_t * self.args.audio_fps # [160,000,90*160,000]
+ clip_s_f_pose, clip_e_f_pose = clip_s_t * self.args.pose_fps, clip_e_t * self.args.pose_fps # [150,90*15]
+
+
+ for ratio in self.args.multi_length_training:
+ if is_test:# stride = length for test
+ cut_length = clip_e_f_pose - clip_s_f_pose
+ self.args.stride = cut_length
+ self.max_length = cut_length
+ else:
+ self.args.stride = int(ratio*self.ori_stride)
+ cut_length = int(self.ori_length*ratio)
+
+ num_subdivision = math.floor((clip_e_f_pose - clip_s_f_pose - cut_length) / self.args.stride) + 1
+ logger.info(f"pose from frame {clip_s_f_pose} to {clip_e_f_pose}, length {cut_length}")
+ logger.info(f"{num_subdivision} clips is expected with stride {self.args.stride}")
+
+ if audio_each_file != []:
+ audio_short_length = math.floor(cut_length / self.args.pose_fps * self.args.audio_fps)
+ """
+ for audio sr = 16000, fps = 15, pose_length = 34,
+ audio short length = 36266.7 -> 36266
+ this error is fine.
+ """
+ logger.info(f"audio from frame {clip_s_f_audio} to {clip_e_f_audio}, length {audio_short_length}")
+
+ n_filtered_out = defaultdict(int)
+ sample_pose_list = []
+ sample_audio_list = []
+ sample_facial_list = []
+ sample_shape_list = []
+ sample_word_list = []
+ sample_emo_list = []
+ sample_sem_list = []
+ sample_vid_list = []
+ sample_trans_list = []
+
+ for i in range(num_subdivision): # cut into around 2s chip, (self npose)
+ start_idx = clip_s_f_pose + i * self.args.stride
+ fin_idx = start_idx + cut_length
+ sample_pose = pose_each_file[start_idx:fin_idx]
+ sample_trans = trans_each_file[start_idx:fin_idx]
+ sample_shape = shape_each_file[start_idx:fin_idx]
+ # print(sample_pose.shape)
+ if self.args.audio_rep is not None:
+ audio_start = clip_s_f_audio + math.floor(i * self.args.stride * self.args.audio_fps / self.args.pose_fps)
+ audio_end = audio_start + audio_short_length
+ sample_audio = audio_each_file[audio_start:audio_end]
+ else:
+ sample_audio = np.array([-1])
+ sample_facial = facial_each_file[start_idx:fin_idx] if self.args.facial_rep is not None else np.array([-1])
+ sample_word = word_each_file[start_idx:fin_idx] if self.args.word_rep is not None else np.array([-1])
+ sample_emo = emo_each_file[start_idx:fin_idx] if self.args.emo_rep is not None else np.array([-1])
+ sample_sem = sem_each_file[start_idx:fin_idx] if self.args.sem_rep is not None else np.array([-1])
+ sample_vid = vid_each_file[start_idx:fin_idx] if self.args.id_rep is not None else np.array([-1])
+
+ if sample_pose.any() != None:
+ # filtering motion skeleton data
+ sample_pose, filtering_message = MotionPreprocessor(sample_pose).get()
+ is_correct_motion = (sample_pose != [])
+ if is_correct_motion or disable_filtering:
+ sample_pose_list.append(sample_pose)
+ sample_audio_list.append(sample_audio)
+ sample_facial_list.append(sample_facial)
+ sample_shape_list.append(sample_shape)
+ sample_word_list.append(sample_word)
+ sample_vid_list.append(sample_vid)
+ sample_emo_list.append(sample_emo)
+ sample_sem_list.append(sample_sem)
+ sample_trans_list.append(sample_trans)
+ else:
+ n_filtered_out[filtering_message] += 1
+
+ if len(sample_pose_list) > 0:
+ with dst_lmdb_env.begin(write=True) as txn:
+ for pose, audio, facial, shape, word, vid, emo, sem, trans in zip(
+ sample_pose_list,
+ sample_audio_list,
+ sample_facial_list,
+ sample_shape_list,
+ sample_word_list,
+ sample_vid_list,
+ sample_emo_list,
+ sample_sem_list,
+ sample_trans_list,):
+ k = "{:005}".format(self.n_out_samples).encode("ascii")
+ v = [pose, audio, facial, shape, word, emo, sem, vid, trans]
+ v = pyarrow.serialize(v).to_buffer()
+ txn.put(k, v)
+ self.n_out_samples += 1
+ return n_filtered_out
+
+ def __getitem__(self, idx):
+ with self.lmdb_env.begin(write=False) as txn:
+ key = "{:005}".format(idx).encode("ascii")
+ sample = txn.get(key)
+ sample = pyarrow.deserialize(sample)
+ tar_pose, in_audio, in_facial, in_shape, in_word, emo, sem, vid, trans = sample
+ #print(in_shape)
+ #vid = torch.from_numpy(vid).int()
+ emo = torch.from_numpy(emo).int()
+ sem = torch.from_numpy(sem).float()
+ in_audio = torch.from_numpy(in_audio).float()
+ in_word = torch.from_numpy(in_word).float() if self.args.word_cache else torch.from_numpy(in_word).int()
+ if self.loader_type == "test":
+ tar_pose = torch.from_numpy(tar_pose).float()
+ trans = torch.from_numpy(trans).float()
+ in_facial = torch.from_numpy(in_facial).float()
+ vid = torch.from_numpy(vid).float()
+ in_shape = torch.from_numpy(in_shape).float()
+ else:
+ in_shape = torch.from_numpy(in_shape).reshape((in_shape.shape[0], -1)).float()
+ trans = torch.from_numpy(trans).reshape((trans.shape[0], -1)).float()
+ vid = torch.from_numpy(vid).reshape((vid.shape[0], -1)).float()
+ tar_pose = torch.from_numpy(tar_pose).reshape((tar_pose.shape[0], -1)).float()
+ in_facial = torch.from_numpy(in_facial).reshape((in_facial.shape[0], -1)).float()
+ return {"pose":tar_pose, "audio":in_audio, "facial":in_facial, "beta": in_shape, "word":in_word, "id":vid, "emo":emo, "sem":sem, "trans":trans}
+
+
+class MotionPreprocessor:
+ def __init__(self, skeletons):
+ self.skeletons = skeletons
+ #self.mean_pose = mean_pose
+ self.filtering_message = "PASS"
+
+ def get(self):
+ assert (self.skeletons is not None)
+
+ # filtering
+ if self.skeletons != []:
+ if self.check_pose_diff():
+ self.skeletons = []
+ self.filtering_message = "pose"
+ # elif self.check_spine_angle():
+ # self.skeletons = []
+ # self.filtering_message = "spine angle"
+ # elif self.check_static_motion():
+ # self.skeletons = []
+ # self.filtering_message = "motion"
+
+ # if self.skeletons != []:
+ # self.skeletons = self.skeletons.tolist()
+ # for i, frame in enumerate(self.skeletons):
+ # assert not np.isnan(self.skeletons[i]).any() # missing joints
+
+ return self.skeletons, self.filtering_message
+
+ def check_static_motion(self, verbose=True):
+ def get_variance(skeleton, joint_idx):
+ wrist_pos = skeleton[:, joint_idx]
+ variance = np.sum(np.var(wrist_pos, axis=0))
+ return variance
+
+ left_arm_var = get_variance(self.skeletons, 6)
+ right_arm_var = get_variance(self.skeletons, 9)
+
+ th = 0.0014 # exclude 13110
+ # th = 0.002 # exclude 16905
+ if left_arm_var < th and right_arm_var < th:
+ if verbose:
+ print("skip - check_static_motion left var {}, right var {}".format(left_arm_var, right_arm_var))
+ return True
+ else:
+ if verbose:
+ print("pass - check_static_motion left var {}, right var {}".format(left_arm_var, right_arm_var))
+ return False
+
+
+ def check_pose_diff(self, verbose=False):
+# diff = np.abs(self.skeletons - self.mean_pose) # 186*1
+# diff = np.mean(diff)
+
+# # th = 0.017
+# th = 0.02 #0.02 # exclude 3594
+# if diff < th:
+# if verbose:
+# print("skip - check_pose_diff {:.5f}".format(diff))
+# return True
+# # th = 3.5 #0.02 # exclude 3594
+# # if 3.5 < diff < 5:
+# # if verbose:
+# # print("skip - check_pose_diff {:.5f}".format(diff))
+# # return True
+# else:
+# if verbose:
+# print("pass - check_pose_diff {:.5f}".format(diff))
+ return False
+
+
+ def check_spine_angle(self, verbose=True):
+ def angle_between(v1, v2):
+ v1_u = v1 / np.linalg.norm(v1)
+ v2_u = v2 / np.linalg.norm(v2)
+ return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0))
+
+ angles = []
+ for i in range(self.skeletons.shape[0]):
+ spine_vec = self.skeletons[i, 1] - self.skeletons[i, 0]
+ angle = angle_between(spine_vec, [0, -1, 0])
+ angles.append(angle)
+
+ if np.rad2deg(max(angles)) > 30 or np.rad2deg(np.mean(angles)) > 20: # exclude 4495
+ # if np.rad2deg(max(angles)) > 20: # exclude 8270
+ if verbose:
+ print("skip - check_spine_angle {:.5f}, {:.5f}".format(max(angles), np.mean(angles)))
+ return True
+ else:
+ if verbose:
+ print("pass - check_spine_angle {:.5f}".format(max(angles)))
+ return False
\ No newline at end of file
diff --git a/dataloaders/beat_sep_lower.py b/dataloaders/beat_sep_lower.py
new file mode 100644
index 0000000000000000000000000000000000000000..01c8b228d0436cfbf3b988e8443460af702c02e8
--- /dev/null
+++ b/dataloaders/beat_sep_lower.py
@@ -0,0 +1,855 @@
+import os
+import pickle
+import math
+import shutil
+import numpy as np
+import lmdb as lmdb
+import textgrid as tg
+import pandas as pd
+import torch
+import glob
+import json
+from termcolor import colored
+from loguru import logger
+from collections import defaultdict
+from torch.utils.data import Dataset
+import torch.distributed as dist
+import pyarrow
+import librosa
+import smplx
+
+from .build_vocab import Vocab
+from .utils.audio_features import Wav2Vec2Model
+from .data_tools import joints_list
+from .utils import rotation_conversions as rc
+from .utils import other_tools
+
+class CustomDataset(Dataset):
+ def __init__(self, args, loader_type, augmentation=None, kwargs=None, build_cache=True):
+ self.args = args
+ self.loader_type = loader_type
+
+ self.rank = dist.get_rank()
+ self.ori_stride = self.args.stride
+ self.ori_length = self.args.pose_length
+ self.alignment = [0,0] # for trinity
+
+ self.ori_joint_list = joints_list[self.args.ori_joints]
+ self.tar_joint_list = joints_list[self.args.tar_joints]
+ if 'smplx' in self.args.pose_rep:
+ self.joint_mask = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ self.joints = len(list(self.tar_joint_list.keys()))
+ for joint_name in self.tar_joint_list:
+ self.joint_mask[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ else:
+ self.joints = len(list(self.ori_joint_list.keys()))+1
+ self.joint_mask = np.zeros(self.joints*3)
+ for joint_name in self.tar_joint_list:
+ if joint_name == "Hips":
+ self.joint_mask[3:6] = 1
+ else:
+ self.joint_mask[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ # select trainable joints
+ self.smplx = smplx.create(
+ self.args.data_path_1+"smplx_models/",
+ model_type='smplx',
+ gender='NEUTRAL_2020',
+ use_face_contour=False,
+ num_betas=300,
+ num_expression_coeffs=100,
+ ext='npz',
+ use_pca=False,
+ ).cuda().eval()
+
+ split_rule = pd.read_csv(args.data_path+"train_test_split.csv")
+ self.selected_file = split_rule.loc[(split_rule['type'] == loader_type) & (split_rule['id'].str.split("_").str[0].astype(int).isin(self.args.training_speakers))]
+ if args.additional_data and loader_type == 'train':
+ split_b = split_rule.loc[(split_rule['type'] == 'additional') & (split_rule['id'].str.split("_").str[0].astype(int).isin(self.args.training_speakers))]
+ #self.selected_file = split_rule.loc[(split_rule['type'] == 'additional') & (split_rule['id'].str.split("_").str[0].astype(int).isin(self.args.training_speakers))]
+ self.selected_file = pd.concat([self.selected_file, split_b])
+ if self.selected_file.empty:
+ logger.warning(f"{loader_type} is empty for speaker {self.args.training_speakers}, use train set 0-8 instead")
+ self.selected_file = split_rule.loc[(split_rule['type'] == 'train') & (split_rule['id'].str.split("_").str[0].astype(int).isin(self.args.training_speakers))]
+ self.selected_file = self.selected_file.iloc[0:8]
+ self.data_dir = args.data_path
+
+ if loader_type == "test":
+ self.args.multi_length_training = [1.0]
+ self.max_length = int(args.pose_length * self.args.multi_length_training[-1])
+ self.max_audio_pre_len = math.floor(args.pose_length / args.pose_fps * self.args.audio_sr)
+ if self.max_audio_pre_len > self.args.test_length*self.args.audio_sr:
+ self.max_audio_pre_len = self.args.test_length*self.args.audio_sr
+
+ if args.word_rep is not None:
+ with open(f"{args.data_path}weights/vocab.pkl", 'rb') as f:
+ self.lang_model = pickle.load(f)
+
+ preloaded_dir = self.args.root_path + self.args.cache_path + loader_type + f"/{args.pose_rep}_cache"
+ # if args.pose_norm:
+ # # careful for rotation vectors
+ # if not os.path.exists(args.data_path+args.mean_pose_path+f"{args.pose_rep.split('_')[0]}/bvh_mean.npy"):
+ # self.calculate_mean_pose()
+ # self.mean_pose = np.load(args.data_path+args.mean_pose_path+f"{args.pose_rep.split('_')[0]}/bvh_mean.npy")
+ # self.std_pose = np.load(args.data_path+args.mean_pose_path+f"{args.pose_rep.split('_')[0]}/bvh_std.npy")
+ # if args.audio_norm:
+ # if not os.path.exists(args.data_path+args.mean_pose_path+f"{args.audio_rep.split('_')[0]}/bvh_mean.npy"):
+ # self.calculate_mean_audio()
+ # self.mean_audio = np.load(args.data_path+args.mean_pose_path+f"{args.audio_rep.split('_')[0]}/npy_mean.npy")
+ # self.std_audio = np.load(args.data_path+args.mean_pose_path+f"{args.audio_rep.split('_')[0]}/npy_std.npy")
+ # if args.facial_norm:
+ # if not os.path.exists(args.data_path+args.mean_pose_path+f"{args.pose_rep.split('_')[0]}/bvh_mean.npy"):
+ # self.calculate_mean_face()
+ # self.mean_facial = np.load(args.data_path+args.mean_pose_path+f"{args.facial_rep}/json_mean.npy")
+ # self.std_facial = np.load(args.data_path+args.mean_pose_path+f"{args.facial_rep}/json_std.npy")
+ if self.args.beat_align:
+ if not os.path.exists(args.data_path+f"weights/mean_vel_{args.pose_rep}.npy"):
+ self.calculate_mean_velocity(args.data_path+f"weights/mean_vel_{args.pose_rep}.npy")
+ self.avg_vel = np.load(args.data_path+f"weights/mean_vel_{args.pose_rep}.npy")
+
+ if build_cache and self.rank == 0:
+ self.build_cache(preloaded_dir)
+ self.lmdb_env = lmdb.open(preloaded_dir, readonly=True, lock=False)
+ with self.lmdb_env.begin() as txn:
+ self.n_samples = txn.stat()["entries"]
+
+
+ def calculate_mean_velocity(self, save_path):
+ self.smplx = smplx.create(
+ self.args.data_path_1+"smplx_models/",
+ model_type='smplx',
+ gender='NEUTRAL_2020',
+ use_face_contour=False,
+ num_betas=300,
+ num_expression_coeffs=100,
+ ext='npz',
+ use_pca=False,
+ ).cuda().eval()
+ dir_p = self.data_dir + self.args.pose_rep + "/"
+ all_list = []
+ from tqdm import tqdm
+ for tar in tqdm(os.listdir(dir_p)):
+ if tar.endswith(".npz"):
+ m_data = np.load(dir_p+tar, allow_pickle=True)
+ betas, poses, trans, exps = m_data["betas"], m_data["poses"], m_data["trans"], m_data["expressions"]
+ n, c = poses.shape[0], poses.shape[1]
+ betas = betas.reshape(1, 300)
+ betas = np.tile(betas, (n, 1))
+ betas = torch.from_numpy(betas).cuda().float()
+ poses = torch.from_numpy(poses.reshape(n, c)).cuda().float()
+ exps = torch.from_numpy(exps.reshape(n, 100)).cuda().float()
+ trans = torch.from_numpy(trans.reshape(n, 3)).cuda().float()
+ max_length = 128
+ s, r = n//max_length, n%max_length
+ #print(n, s, r)
+ all_tensor = []
+ for i in range(s):
+ with torch.no_grad():
+ joints = self.smplx(
+ betas=betas[i*max_length:(i+1)*max_length],
+ transl=trans[i*max_length:(i+1)*max_length],
+ expression=exps[i*max_length:(i+1)*max_length],
+ jaw_pose=poses[i*max_length:(i+1)*max_length, 66:69],
+ global_orient=poses[i*max_length:(i+1)*max_length,:3],
+ body_pose=poses[i*max_length:(i+1)*max_length,3:21*3+3],
+ left_hand_pose=poses[i*max_length:(i+1)*max_length,25*3:40*3],
+ right_hand_pose=poses[i*max_length:(i+1)*max_length,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=poses[i*max_length:(i+1)*max_length, 69:72],
+ reye_pose=poses[i*max_length:(i+1)*max_length, 72:75],
+ )['joints'][:, :55, :].reshape(max_length, 55*3)
+ all_tensor.append(joints)
+ if r != 0:
+ with torch.no_grad():
+ joints = self.smplx(
+ betas=betas[s*max_length:s*max_length+r],
+ transl=trans[s*max_length:s*max_length+r],
+ expression=exps[s*max_length:s*max_length+r],
+ jaw_pose=poses[s*max_length:s*max_length+r, 66:69],
+ global_orient=poses[s*max_length:s*max_length+r,:3],
+ body_pose=poses[s*max_length:s*max_length+r,3:21*3+3],
+ left_hand_pose=poses[s*max_length:s*max_length+r,25*3:40*3],
+ right_hand_pose=poses[s*max_length:s*max_length+r,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=poses[s*max_length:s*max_length+r, 69:72],
+ reye_pose=poses[s*max_length:s*max_length+r, 72:75],
+ )['joints'][:, :55, :].reshape(r, 55*3)
+ all_tensor.append(joints)
+ joints = torch.cat(all_tensor, axis=0)
+ joints = joints.permute(1, 0)
+ dt = 1/30
+ # first steps is forward diff (t+1 - t) / dt
+ init_vel = (joints[:, 1:2] - joints[:, :1]) / dt
+ # middle steps are second order (t+1 - t-1) / 2dt
+ middle_vel = (joints[:, 2:] - joints[:, 0:-2]) / (2 * dt)
+ # last step is backward diff (t - t-1) / dt
+ final_vel = (joints[:, -1:] - joints[:, -2:-1]) / dt
+ #print(joints.shape, init_vel.shape, middle_vel.shape, final_vel.shape)
+ vel_seq = torch.cat([init_vel, middle_vel, final_vel], dim=1).permute(1, 0).reshape(n, 55, 3)
+ #print(vel_seq.shape)
+ #.permute(1, 0).reshape(n, 55, 3)
+ vel_seq_np = vel_seq.cpu().numpy()
+ vel_joints_np = np.linalg.norm(vel_seq_np, axis=2) # n * 55
+ all_list.append(vel_joints_np)
+ avg_vel = np.mean(np.concatenate(all_list, axis=0),axis=0) # 55
+ np.save(save_path, avg_vel)
+
+
+ def build_cache(self, preloaded_dir):
+ logger.info(f"Audio bit rate: {self.args.audio_fps}")
+ logger.info("Reading data '{}'...".format(self.data_dir))
+ logger.info("Creating the dataset cache...")
+ if self.args.new_cache:
+ if os.path.exists(preloaded_dir):
+ shutil.rmtree(preloaded_dir)
+ if os.path.exists(preloaded_dir):
+ logger.info("Found the cache {}".format(preloaded_dir))
+ elif self.loader_type == "test":
+ self.cache_generation(
+ preloaded_dir, True,
+ 0, 0,
+ is_test=True)
+ else:
+ self.cache_generation(
+ preloaded_dir, self.args.disable_filtering,
+ self.args.clean_first_seconds, self.args.clean_final_seconds,
+ is_test=False)
+
+ def __len__(self):
+ return self.n_samples
+
+ def idmapping(self, id):
+ # map 1,2,3,4,5, 6,7,9,10,11, 12,13,15,16,17, 18,20,21,22,23, 24,25,27,28,30 to 0-24
+ if id == 30: id = 8
+ if id == 28: id = 14
+ if id == 27: id = 19
+ return id - 1
+
+ def cache_generation(self, out_lmdb_dir, disable_filtering, clean_first_seconds, clean_final_seconds, is_test=False):
+ # if "wav2vec2" in self.args.audio_rep:
+ # self.wav2vec_model = Wav2Vec2Model.from_pretrained(f"{self.args.data_path_1}/hub/transformer/wav2vec2-base-960h")
+ # self.wav2vec_model.feature_extractor._freeze_parameters()
+ # self.wav2vec_model = self.wav2vec_model.cuda()
+ # self.wav2vec_model.eval()
+
+ self.n_out_samples = 0
+ # create db for samples
+ if not os.path.exists(out_lmdb_dir): os.makedirs(out_lmdb_dir)
+ if len(self.args.training_speakers) == 1:
+ dst_lmdb_env = lmdb.open(out_lmdb_dir, map_size= int(1024 ** 3 * 50))# 50G
+ else:
+ dst_lmdb_env = lmdb.open(out_lmdb_dir, map_size= int(1024 ** 3 * 200))# 200G
+ n_filtered_out = defaultdict(int)
+
+ for index, file_name in self.selected_file.iterrows():
+ f_name = file_name["id"]
+ ext = ".npz" if "smplx" in self.args.pose_rep else ".bvh"
+ pose_file = self.data_dir + self.args.pose_rep + "/" + f_name + ext
+ pose_each_file = []
+ trans_each_file = []
+ shape_each_file = []
+ audio_each_file = []
+ facial_each_file = []
+ word_each_file = []
+ emo_each_file = []
+ sem_each_file = []
+ vid_each_file = []
+ id_pose = f_name #1_wayne_0_1_1
+
+ logger.info(colored(f"# ---- Building cache for Pose {id_pose} ---- #", "blue"))
+ if "smplx" in self.args.pose_rep:
+ pose_data = np.load(pose_file, allow_pickle=True)
+ assert 30%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 30'
+ stride = int(30/self.args.pose_fps)
+ pose_each_file = pose_data["poses"][::stride]
+ trans_each_file = pose_data["trans"][::stride]
+ shape_each_file = np.repeat(pose_data["betas"].reshape(1, 300), pose_each_file.shape[0], axis=0)
+
+ assert self.args.pose_fps == 30, "should 30"
+ m_data = np.load(pose_file, allow_pickle=True)
+ betas, poses, trans, exps = m_data["betas"], m_data["poses"], m_data["trans"], m_data["expressions"]
+ n, c = poses.shape[0], poses.shape[1]
+ betas = betas.reshape(1, 300)
+ betas = np.tile(betas, (n, 1))
+ betas = torch.from_numpy(betas).cuda().float()
+ poses = torch.from_numpy(poses.reshape(n, c)).cuda().float()
+ exps = torch.from_numpy(exps.reshape(n, 100)).cuda().float()
+ trans = torch.from_numpy(trans.reshape(n, 3)).cuda().float()
+ max_length = 128
+ s, r = n//max_length, n%max_length
+ #print(n, s, r)
+ all_tensor = []
+ for i in range(s):
+ with torch.no_grad():
+ joints = self.smplx(
+ betas=betas[i*max_length:(i+1)*max_length],
+ transl=trans[i*max_length:(i+1)*max_length],
+ expression=exps[i*max_length:(i+1)*max_length],
+ jaw_pose=poses[i*max_length:(i+1)*max_length, 66:69],
+ global_orient=poses[i*max_length:(i+1)*max_length,:3],
+ body_pose=poses[i*max_length:(i+1)*max_length,3:21*3+3],
+ left_hand_pose=poses[i*max_length:(i+1)*max_length,25*3:40*3],
+ right_hand_pose=poses[i*max_length:(i+1)*max_length,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=poses[i*max_length:(i+1)*max_length, 69:72],
+ reye_pose=poses[i*max_length:(i+1)*max_length, 72:75],
+ )['joints'][:, (7,8,10,11), :].reshape(max_length, 4, 3).cpu()
+ all_tensor.append(joints)
+ if r != 0:
+ with torch.no_grad():
+ joints = self.smplx(
+ betas=betas[s*max_length:s*max_length+r],
+ transl=trans[s*max_length:s*max_length+r],
+ expression=exps[s*max_length:s*max_length+r],
+ jaw_pose=poses[s*max_length:s*max_length+r, 66:69],
+ global_orient=poses[s*max_length:s*max_length+r,:3],
+ body_pose=poses[s*max_length:s*max_length+r,3:21*3+3],
+ left_hand_pose=poses[s*max_length:s*max_length+r,25*3:40*3],
+ right_hand_pose=poses[s*max_length:s*max_length+r,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=poses[s*max_length:s*max_length+r, 69:72],
+ reye_pose=poses[s*max_length:s*max_length+r, 72:75],
+ )['joints'][:, (7,8,10,11), :].reshape(r, 4, 3).cpu()
+ all_tensor.append(joints)
+ joints = torch.cat(all_tensor, axis=0) # all, 4, 3
+ # print(joints.shape)
+ feetv = torch.zeros(joints.shape[1], joints.shape[0])
+ joints = joints.permute(1, 0, 2)
+ #print(joints.shape, feetv.shape)
+ feetv[:, :-1] = (joints[:, 1:] - joints[:, :-1]).norm(dim=-1)
+ #print(feetv.shape)
+ contacts = (feetv < 0.01).numpy().astype(float)
+ # print(contacts.shape, contacts)
+ contacts = contacts.transpose(1, 0)
+ pose_each_file = pose_each_file * self.joint_mask
+ pose_each_file = pose_each_file[:, self.joint_mask.astype(bool)]
+ pose_each_file = np.concatenate([pose_each_file, contacts], axis=1)
+ # print(pose_each_file.shape)
+
+
+ if self.args.facial_rep is not None:
+ logger.info(f"# ---- Building cache for Facial {id_pose} and Pose {id_pose} ---- #")
+ facial_each_file = pose_data["expressions"][::stride]
+ if self.args.facial_norm:
+ facial_each_file = (facial_each_file - self.mean_facial) / self.std_facial
+
+ else:
+ assert 120%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 120'
+ stride = int(120/self.args.pose_fps)
+ with open(pose_file, "r") as pose_data:
+ for j, line in enumerate(pose_data.readlines()):
+ if j < 431: continue
+ if j%stride != 0:continue
+ data = np.fromstring(line, dtype=float, sep=" ")
+ rot_data = rc.euler_angles_to_matrix(torch.from_numpy(np.deg2rad(data)).reshape(-1, self.joints,3), "XYZ")
+ rot_data = rc.matrix_to_axis_angle(rot_data).reshape(-1, self.joints*3)
+ rot_data = rot_data.numpy() * self.joint_mask
+
+ pose_each_file.append(rot_data)
+ trans_each_file.append(data[:3])
+
+ pose_each_file = np.array(pose_each_file)
+ # print(pose_each_file.shape)
+ trans_each_file = np.array(trans_each_file)
+ shape_each_file = np.repeat(np.array(-1).reshape(1, 1), pose_each_file.shape[0], axis=0)
+ if self.args.facial_rep is not None:
+ logger.info(f"# ---- Building cache for Facial {id_pose} and Pose {id_pose} ---- #")
+ facial_file = pose_file.replace(self.args.pose_rep, self.args.facial_rep).replace("bvh", "json")
+ assert 60%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 120'
+ stride = int(60/self.args.pose_fps)
+ if not os.path.exists(facial_file):
+ logger.warning(f"# ---- file not found for Facial {id_pose}, skip all files with the same id ---- #")
+ self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ continue
+ with open(facial_file, 'r') as facial_data_file:
+ facial_data = json.load(facial_data_file)
+ for j, frame_data in enumerate(facial_data['frames']):
+ if j%stride != 0:continue
+ facial_each_file.append(frame_data['weights'])
+ facial_each_file = np.array(facial_each_file)
+ if self.args.facial_norm:
+ facial_each_file = (facial_each_file - self.mean_facial) / self.std_facial
+
+ if self.args.id_rep is not None:
+ int_value = self.idmapping(int(f_name.split("_")[0]))
+ vid_each_file = np.repeat(np.array(int_value).reshape(1, 1), pose_each_file.shape[0], axis=0)
+
+ if self.args.audio_rep is not None:
+ logger.info(f"# ---- Building cache for Audio {id_pose} and Pose {id_pose} ---- #")
+ audio_file = pose_file.replace(self.args.pose_rep, 'wave16k').replace(ext, ".wav")
+ if not os.path.exists(audio_file):
+ logger.warning(f"# ---- file not found for Audio {id_pose}, skip all files with the same id ---- #")
+ self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ continue
+ audio_each_file, sr = librosa.load(audio_file)
+ audio_each_file = librosa.resample(audio_each_file, orig_sr=sr, target_sr=self.args.audio_sr)
+ if self.args.audio_rep == "onset+amplitude":
+ from numpy.lib import stride_tricks
+ frame_length = 1024
+ # hop_length = 512
+ shape = (audio_each_file.shape[-1] - frame_length + 1, frame_length)
+ strides = (audio_each_file.strides[-1], audio_each_file.strides[-1])
+ rolling_view = stride_tricks.as_strided(audio_each_file, shape=shape, strides=strides)
+ amplitude_envelope = np.max(np.abs(rolling_view), axis=1)
+ # pad the last frame_length-1 samples
+ amplitude_envelope = np.pad(amplitude_envelope, (0, frame_length-1), mode='constant', constant_values=amplitude_envelope[-1])
+ audio_onset_f = librosa.onset.onset_detect(y=audio_each_file, sr=self.args.audio_sr, units='frames')
+ onset_array = np.zeros(len(audio_each_file), dtype=float)
+ onset_array[audio_onset_f] = 1.0
+ # print(amplitude_envelope.shape, audio_each_file.shape, onset_array.shape)
+ audio_each_file = np.concatenate([amplitude_envelope.reshape(-1, 1), onset_array.reshape(-1, 1)], axis=1)
+ elif self.args.audio_rep == "mfcc":
+ audio_each_file = librosa.feature.melspectrogram(y=audio_each_file, sr=self.args.audio_sr, n_mels=128, hop_length=int(self.args.audio_sr/self.args.audio_fps))
+ audio_each_file = audio_each_file.transpose(1, 0)
+ # print(audio_each_file.shape, pose_each_file.shape)
+ if self.args.audio_norm and self.args.audio_rep == "wave16k":
+ audio_each_file = (audio_each_file - self.mean_audio) / self.std_audio
+
+ time_offset = 0
+ if self.args.word_rep is not None:
+ logger.info(f"# ---- Building cache for Word {id_pose} and Pose {id_pose} ---- #")
+ word_file = f"{self.data_dir}{self.args.word_rep}/{id_pose}.TextGrid"
+ if not os.path.exists(word_file):
+ logger.warning(f"# ---- file not found for Word {id_pose}, skip all files with the same id ---- #")
+ self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ continue
+ tgrid = tg.TextGrid.fromFile(word_file)
+ if self.args.t_pre_encoder == "bert":
+ from transformers import AutoTokenizer, BertModel
+ tokenizer = AutoTokenizer.from_pretrained(self.args.data_path_1 + "hub/bert-base-uncased", local_files_only=True)
+ model = BertModel.from_pretrained(self.args.data_path_1 + "hub/bert-base-uncased", local_files_only=True).eval()
+ list_word = []
+ all_hidden = []
+ max_len = 400
+ last = 0
+ word_token_mapping = []
+ first = True
+ for i, word in enumerate(tgrid[0]):
+ last = i
+ if (i%max_len != 0) or (i==0):
+ if word.mark == "":
+ list_word.append(".")
+ else:
+ list_word.append(word.mark)
+ else:
+ max_counter = max_len
+ str_word = ' '.join(map(str, list_word))
+ if first:
+ global_len = 0
+ end = -1
+ offset_word = []
+ for k, wordvalue in enumerate(list_word):
+ start = end+1
+ end = start+len(wordvalue)
+ offset_word.append((start, end))
+ #print(offset_word)
+ token_scan = tokenizer.encode_plus(str_word, return_offsets_mapping=True)['offset_mapping']
+ #print(token_scan)
+ for start, end in offset_word:
+ sub_mapping = []
+ for i, (start_t, end_t) in enumerate(token_scan[1:-1]):
+ if int(start) <= int(start_t) and int(end_t) <= int(end):
+ #print(i+global_len)
+ sub_mapping.append(i+global_len)
+ word_token_mapping.append(sub_mapping)
+ #print(len(word_token_mapping))
+ global_len = word_token_mapping[-1][-1] + 1
+ list_word = []
+ if word.mark == "":
+ list_word.append(".")
+ else:
+ list_word.append(word.mark)
+
+ with torch.no_grad():
+ inputs = tokenizer(str_word, return_tensors="pt")
+ outputs = model(**inputs)
+ last_hidden_states = outputs.last_hidden_state.reshape(-1, 768).cpu().numpy()[1:-1, :]
+ all_hidden.append(last_hidden_states)
+
+ #list_word = list_word[:10]
+ if list_word == []:
+ pass
+ else:
+ if first:
+ global_len = 0
+ str_word = ' '.join(map(str, list_word))
+ end = -1
+ offset_word = []
+ for k, wordvalue in enumerate(list_word):
+ start = end+1
+ end = start+len(wordvalue)
+ offset_word.append((start, end))
+ #print(offset_word)
+ token_scan = tokenizer.encode_plus(str_word, return_offsets_mapping=True)['offset_mapping']
+ #print(token_scan)
+ for start, end in offset_word:
+ sub_mapping = []
+ for i, (start_t, end_t) in enumerate(token_scan[1:-1]):
+ if int(start) <= int(start_t) and int(end_t) <= int(end):
+ sub_mapping.append(i+global_len)
+ #print(sub_mapping)
+ word_token_mapping.append(sub_mapping)
+ #print(len(word_token_mapping))
+ with torch.no_grad():
+ inputs = tokenizer(str_word, return_tensors="pt")
+ outputs = model(**inputs)
+ last_hidden_states = outputs.last_hidden_state.reshape(-1, 768).cpu().numpy()[1:-1, :]
+ all_hidden.append(last_hidden_states)
+ last_hidden_states = np.concatenate(all_hidden, axis=0)
+
+ for i in range(pose_each_file.shape[0]):
+ found_flag = False
+ current_time = i/self.args.pose_fps + time_offset
+ j_last = 0
+ for j, word in enumerate(tgrid[0]):
+ word_n, word_s, word_e = word.mark, word.minTime, word.maxTime
+ if word_s<=current_time and current_time<=word_e:
+ if self.args.word_cache and self.args.t_pre_encoder == 'bert':
+ mapping_index = word_token_mapping[j]
+ #print(mapping_index, word_s, word_e)
+ s_t = np.linspace(word_s, word_e, len(mapping_index)+1)
+ #print(s_t)
+ for tt, t_sep in enumerate(s_t[1:]):
+ if current_time <= t_sep:
+ #if len(mapping_index) > 1: print(mapping_index[tt])
+ word_each_file.append(last_hidden_states[mapping_index[tt]])
+ break
+ else:
+ if word_n == " ":
+ word_each_file.append(self.lang_model.PAD_token)
+ else:
+ word_each_file.append(self.lang_model.get_word_index(word_n))
+ found_flag = True
+ j_last = j
+ break
+ else: continue
+ if not found_flag:
+ if self.args.word_cache and self.args.t_pre_encoder == 'bert':
+ word_each_file.append(last_hidden_states[j_last])
+ else:
+ word_each_file.append(self.lang_model.UNK_token)
+ word_each_file = np.array(word_each_file)
+ #print(word_each_file.shape)
+
+ if self.args.emo_rep is not None:
+ logger.info(f"# ---- Building cache for Emo {id_pose} and Pose {id_pose} ---- #")
+ rtype, start = int(id_pose.split('_')[3]), int(id_pose.split('_')[3])
+ if rtype == 0 or rtype == 2 or rtype == 4 or rtype == 6:
+ if start >= 1 and start <= 64:
+ score = 0
+ elif start >= 65 and start <= 72:
+ score = 1
+ elif start >= 73 and start <= 80:
+ score = 2
+ elif start >= 81 and start <= 86:
+ score = 3
+ elif start >= 87 and start <= 94:
+ score = 4
+ elif start >= 95 and start <= 102:
+ score = 5
+ elif start >= 103 and start <= 110:
+ score = 6
+ elif start >= 111 and start <= 118:
+ score = 7
+ else: pass
+ else:
+ # you may denote as unknown in the future
+ score = 0
+ emo_each_file = np.repeat(np.array(score).reshape(1, 1), pose_each_file.shape[0], axis=0)
+ #print(emo_each_file)
+
+ if self.args.sem_rep is not None:
+ logger.info(f"# ---- Building cache for Sem {id_pose} and Pose {id_pose} ---- #")
+ sem_file = f"{self.data_dir}{self.args.sem_rep}/{id_pose}.txt"
+ sem_all = pd.read_csv(sem_file,
+ sep='\t',
+ names=["name", "start_time", "end_time", "duration", "score", "keywords"])
+ # we adopt motion-level semantic score here.
+ for i in range(pose_each_file.shape[0]):
+ found_flag = False
+ for j, (start, end, score) in enumerate(zip(sem_all['start_time'],sem_all['end_time'], sem_all['score'])):
+ current_time = i/self.args.pose_fps + time_offset
+ if start<=current_time and current_time<=end:
+ sem_each_file.append(score)
+ found_flag=True
+ break
+ else: continue
+ if not found_flag: sem_each_file.append(0.)
+ sem_each_file = np.array(sem_each_file)
+ #print(sem_each_file)
+
+ filtered_result = self._sample_from_clip(
+ dst_lmdb_env,
+ audio_each_file, pose_each_file, trans_each_file, shape_each_file, facial_each_file, word_each_file,
+ vid_each_file, emo_each_file, sem_each_file,
+ disable_filtering, clean_first_seconds, clean_final_seconds, is_test,
+ )
+ for type in filtered_result.keys():
+ n_filtered_out[type] += filtered_result[type]
+
+ with dst_lmdb_env.begin() as txn:
+ logger.info(colored(f"no. of samples: {txn.stat()['entries']}", "cyan"))
+ n_total_filtered = 0
+ for type, n_filtered in n_filtered_out.items():
+ logger.info("{}: {}".format(type, n_filtered))
+ n_total_filtered += n_filtered
+ logger.info(colored("no. of excluded samples: {} ({:.1f}%)".format(
+ n_total_filtered, 100 * n_total_filtered / (txn.stat()["entries"] + n_total_filtered)), "cyan"))
+ dst_lmdb_env.sync()
+ dst_lmdb_env.close()
+
+ def _sample_from_clip(
+ self, dst_lmdb_env, audio_each_file, pose_each_file, trans_each_file, shape_each_file, facial_each_file, word_each_file,
+ vid_each_file, emo_each_file, sem_each_file,
+ disable_filtering, clean_first_seconds, clean_final_seconds, is_test,
+ ):
+ """
+ for data cleaning, we ignore the data for first and final n s
+ for test, we return all data
+ """
+ # audio_start = int(self.alignment[0] * self.args.audio_fps)
+ # pose_start = int(self.alignment[1] * self.args.pose_fps)
+ #logger.info(f"before: {audio_each_file.shape} {pose_each_file.shape}")
+ # audio_each_file = audio_each_file[audio_start:]
+ # pose_each_file = pose_each_file[pose_start:]
+ # trans_each_file =
+ #logger.info(f"after alignment: {audio_each_file.shape} {pose_each_file.shape}")
+ #print(pose_each_file.shape)
+ round_seconds_skeleton = pose_each_file.shape[0] // self.args.pose_fps # assume 1500 frames / 15 fps = 100 s
+ #print(round_seconds_skeleton)
+ if audio_each_file != []:
+ if self.args.audio_rep != "wave16k":
+ round_seconds_audio = len(audio_each_file) // self.args.audio_fps # assume 16,000,00 / 16,000 = 100 s
+ elif self.args.audio_rep == "mfcc":
+ round_seconds_audio = audio_each_file.shape[0] // self.args.audio_fps
+ else:
+ round_seconds_audio = audio_each_file.shape[0] // self.args.audio_sr
+ if facial_each_file != []:
+ round_seconds_facial = facial_each_file.shape[0] // self.args.pose_fps
+ logger.info(f"audio: {round_seconds_audio}s, pose: {round_seconds_skeleton}s, facial: {round_seconds_facial}s")
+ round_seconds_skeleton = min(round_seconds_audio, round_seconds_skeleton, round_seconds_facial)
+ max_round = max(round_seconds_audio, round_seconds_skeleton, round_seconds_facial)
+ if round_seconds_skeleton != max_round:
+ logger.warning(f"reduce to {round_seconds_skeleton}s, ignore {max_round-round_seconds_skeleton}s")
+ else:
+ logger.info(f"pose: {round_seconds_skeleton}s, audio: {round_seconds_audio}s")
+ round_seconds_skeleton = min(round_seconds_audio, round_seconds_skeleton)
+ max_round = max(round_seconds_audio, round_seconds_skeleton)
+ if round_seconds_skeleton != max_round:
+ logger.warning(f"reduce to {round_seconds_skeleton}s, ignore {max_round-round_seconds_skeleton}s")
+
+ clip_s_t, clip_e_t = clean_first_seconds, round_seconds_skeleton - clean_final_seconds # assume [10, 90]s
+ clip_s_f_audio, clip_e_f_audio = self.args.audio_fps * clip_s_t, clip_e_t * self.args.audio_fps # [160,000,90*160,000]
+ clip_s_f_pose, clip_e_f_pose = clip_s_t * self.args.pose_fps, clip_e_t * self.args.pose_fps # [150,90*15]
+
+
+ for ratio in self.args.multi_length_training:
+ if is_test:# stride = length for test
+ cut_length = clip_e_f_pose - clip_s_f_pose
+ self.args.stride = cut_length
+ self.max_length = cut_length
+ else:
+ self.args.stride = int(ratio*self.ori_stride)
+ cut_length = int(self.ori_length*ratio)
+
+ num_subdivision = math.floor((clip_e_f_pose - clip_s_f_pose - cut_length) / self.args.stride) + 1
+ logger.info(f"pose from frame {clip_s_f_pose} to {clip_e_f_pose}, length {cut_length}")
+ logger.info(f"{num_subdivision} clips is expected with stride {self.args.stride}")
+
+ if audio_each_file != []:
+ audio_short_length = math.floor(cut_length / self.args.pose_fps * self.args.audio_fps)
+ """
+ for audio sr = 16000, fps = 15, pose_length = 34,
+ audio short length = 36266.7 -> 36266
+ this error is fine.
+ """
+ logger.info(f"audio from frame {clip_s_f_audio} to {clip_e_f_audio}, length {audio_short_length}")
+
+ n_filtered_out = defaultdict(int)
+ sample_pose_list = []
+ sample_audio_list = []
+ sample_facial_list = []
+ sample_shape_list = []
+ sample_word_list = []
+ sample_emo_list = []
+ sample_sem_list = []
+ sample_vid_list = []
+ sample_trans_list = []
+
+ for i in range(num_subdivision): # cut into around 2s chip, (self npose)
+ start_idx = clip_s_f_pose + i * self.args.stride
+ fin_idx = start_idx + cut_length
+ sample_pose = pose_each_file[start_idx:fin_idx]
+
+ sample_trans = trans_each_file[start_idx:fin_idx]
+ sample_shape = shape_each_file[start_idx:fin_idx]
+ # print(sample_pose.shape)
+ if self.args.audio_rep is not None:
+ audio_start = clip_s_f_audio + math.floor(i * self.args.stride * self.args.audio_fps / self.args.pose_fps)
+ audio_end = audio_start + audio_short_length
+ sample_audio = audio_each_file[audio_start:audio_end]
+ else:
+ sample_audio = np.array([-1])
+ sample_facial = facial_each_file[start_idx:fin_idx] if self.args.facial_rep is not None else np.array([-1])
+ sample_word = word_each_file[start_idx:fin_idx] if self.args.word_rep is not None else np.array([-1])
+ sample_emo = emo_each_file[start_idx:fin_idx] if self.args.emo_rep is not None else np.array([-1])
+ sample_sem = sem_each_file[start_idx:fin_idx] if self.args.sem_rep is not None else np.array([-1])
+ sample_vid = vid_each_file[start_idx:fin_idx] if self.args.id_rep is not None else np.array([-1])
+
+ if sample_pose.any() != None:
+ # filtering motion skeleton data
+ sample_pose, filtering_message = MotionPreprocessor(sample_pose).get()
+ is_correct_motion = (sample_pose != [])
+ if is_correct_motion or disable_filtering:
+ sample_pose_list.append(sample_pose)
+ sample_audio_list.append(sample_audio)
+ sample_facial_list.append(sample_facial)
+ sample_shape_list.append(sample_shape)
+ sample_word_list.append(sample_word)
+ sample_vid_list.append(sample_vid)
+ sample_emo_list.append(sample_emo)
+ sample_sem_list.append(sample_sem)
+ sample_trans_list.append(sample_trans)
+ else:
+ n_filtered_out[filtering_message] += 1
+
+ if len(sample_pose_list) > 0:
+ with dst_lmdb_env.begin(write=True) as txn:
+ for pose, audio, facial, shape, word, vid, emo, sem, trans in zip(
+ sample_pose_list,
+ sample_audio_list,
+ sample_facial_list,
+ sample_shape_list,
+ sample_word_list,
+ sample_vid_list,
+ sample_emo_list,
+ sample_sem_list,
+ sample_trans_list,):
+ k = "{:005}".format(self.n_out_samples).encode("ascii")
+ v = [pose, audio, facial, shape, word, emo, sem, vid, trans]
+ v = pyarrow.serialize(v).to_buffer()
+ txn.put(k, v)
+ self.n_out_samples += 1
+ return n_filtered_out
+
+ def __getitem__(self, idx):
+ with self.lmdb_env.begin(write=False) as txn:
+ key = "{:005}".format(idx).encode("ascii")
+ sample = txn.get(key)
+ sample = pyarrow.deserialize(sample)
+ tar_pose, in_audio, in_facial, in_shape, in_word, emo, sem, vid, trans = sample
+ #print(in_shape)
+ #vid = torch.from_numpy(vid).int()
+ emo = torch.from_numpy(emo).int()
+ sem = torch.from_numpy(sem).float()
+ in_audio = torch.from_numpy(in_audio).float()
+ in_word = torch.from_numpy(in_word).float() if self.args.word_cache else torch.from_numpy(in_word).int()
+ if self.loader_type == "test":
+ tar_pose = torch.from_numpy(tar_pose).float()
+ trans = torch.from_numpy(trans).float()
+ in_facial = torch.from_numpy(in_facial).float()
+ vid = torch.from_numpy(vid).float()
+ in_shape = torch.from_numpy(in_shape).float()
+ else:
+ in_shape = torch.from_numpy(in_shape).reshape((in_shape.shape[0], -1)).float()
+ trans = torch.from_numpy(trans).reshape((trans.shape[0], -1)).float()
+ vid = torch.from_numpy(vid).reshape((vid.shape[0], -1)).float()
+ tar_pose = torch.from_numpy(tar_pose).reshape((tar_pose.shape[0], -1)).float()
+ in_facial = torch.from_numpy(in_facial).reshape((in_facial.shape[0], -1)).float()
+ return {"pose":tar_pose, "audio":in_audio, "facial":in_facial, "beta": in_shape, "word":in_word, "id":vid, "emo":emo, "sem":sem, "trans":trans}
+
+
+class MotionPreprocessor:
+ def __init__(self, skeletons):
+ self.skeletons = skeletons
+ #self.mean_pose = mean_pose
+ self.filtering_message = "PASS"
+
+ def get(self):
+ assert (self.skeletons is not None)
+
+ # filtering
+ if self.skeletons != []:
+ if self.check_pose_diff():
+ self.skeletons = []
+ self.filtering_message = "pose"
+ # elif self.check_spine_angle():
+ # self.skeletons = []
+ # self.filtering_message = "spine angle"
+ # elif self.check_static_motion():
+ # self.skeletons = []
+ # self.filtering_message = "motion"
+
+ # if self.skeletons != []:
+ # self.skeletons = self.skeletons.tolist()
+ # for i, frame in enumerate(self.skeletons):
+ # assert not np.isnan(self.skeletons[i]).any() # missing joints
+
+ return self.skeletons, self.filtering_message
+
+ def check_static_motion(self, verbose=True):
+ def get_variance(skeleton, joint_idx):
+ wrist_pos = skeleton[:, joint_idx]
+ variance = np.sum(np.var(wrist_pos, axis=0))
+ return variance
+
+ left_arm_var = get_variance(self.skeletons, 6)
+ right_arm_var = get_variance(self.skeletons, 9)
+
+ th = 0.0014 # exclude 13110
+ # th = 0.002 # exclude 16905
+ if left_arm_var < th and right_arm_var < th:
+ if verbose:
+ print("skip - check_static_motion left var {}, right var {}".format(left_arm_var, right_arm_var))
+ return True
+ else:
+ if verbose:
+ print("pass - check_static_motion left var {}, right var {}".format(left_arm_var, right_arm_var))
+ return False
+
+
+ def check_pose_diff(self, verbose=False):
+# diff = np.abs(self.skeletons - self.mean_pose) # 186*1
+# diff = np.mean(diff)
+
+# # th = 0.017
+# th = 0.02 #0.02 # exclude 3594
+# if diff < th:
+# if verbose:
+# print("skip - check_pose_diff {:.5f}".format(diff))
+# return True
+# # th = 3.5 #0.02 # exclude 3594
+# # if 3.5 < diff < 5:
+# # if verbose:
+# # print("skip - check_pose_diff {:.5f}".format(diff))
+# # return True
+# else:
+# if verbose:
+# print("pass - check_pose_diff {:.5f}".format(diff))
+ return False
+
+
+ def check_spine_angle(self, verbose=True):
+ def angle_between(v1, v2):
+ v1_u = v1 / np.linalg.norm(v1)
+ v2_u = v2 / np.linalg.norm(v2)
+ return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0))
+
+ angles = []
+ for i in range(self.skeletons.shape[0]):
+ spine_vec = self.skeletons[i, 1] - self.skeletons[i, 0]
+ angle = angle_between(spine_vec, [0, -1, 0])
+ angles.append(angle)
+
+ if np.rad2deg(max(angles)) > 30 or np.rad2deg(np.mean(angles)) > 20: # exclude 4495
+ # if np.rad2deg(max(angles)) > 20: # exclude 8270
+ if verbose:
+ print("skip - check_spine_angle {:.5f}, {:.5f}".format(max(angles), np.mean(angles)))
+ return True
+ else:
+ if verbose:
+ print("pass - check_spine_angle {:.5f}".format(max(angles)))
+ return False
\ No newline at end of file
diff --git a/dataloaders/beat_smplx2020.py b/dataloaders/beat_smplx2020.py
new file mode 100644
index 0000000000000000000000000000000000000000..7647c73d5962dd8856584ebdd6cfe26902ef5070
--- /dev/null
+++ b/dataloaders/beat_smplx2020.py
@@ -0,0 +1,763 @@
+import os
+import pickle
+import math
+import shutil
+import numpy as np
+import lmdb as lmdb
+import textgrid as tg
+import pandas as pd
+import torch
+import glob
+import json
+from termcolor import colored
+from loguru import logger
+from collections import defaultdict
+from torch.utils.data import Dataset
+import torch.distributed as dist
+import pyarrow
+import librosa
+import smplx
+
+from .build_vocab import Vocab
+from .utils.audio_features import Wav2Vec2Model
+from .data_tools import joints_list
+from .utils import rotation_conversions as rc
+from .utils import other_tools
+
+class CustomDataset(Dataset):
+ def __init__(self, args, loader_type, augmentation=None, kwargs=None, build_cache=True):
+ self.args = args
+ self.loader_type = loader_type
+
+ self.rank = dist.get_rank()
+ self.ori_stride = self.args.stride
+ self.ori_length = self.args.pose_length
+ self.alignment = [0,0] # for trinity
+
+ self.ori_joint_list = joints_list[self.args.ori_joints]
+ self.tar_joint_list = joints_list[self.args.tar_joints]
+ if 'smplx' in self.args.pose_rep:
+ self.joint_mask = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ self.joints = len(list(self.ori_joint_list.keys()))
+ for joint_name in self.tar_joint_list:
+ self.joint_mask[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ else:
+ self.joints = len(list(self.ori_joint_list.keys()))+1
+ self.joint_mask = np.zeros(self.joints*3)
+ for joint_name in self.tar_joint_list:
+ if joint_name == "Hips":
+ self.joint_mask[3:6] = 1
+ else:
+ self.joint_mask[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ # select trainable joints
+
+ split_rule = pd.read_csv(args.data_path+"train_test_split.csv")
+ self.selected_file = split_rule.loc[(split_rule['type'] == loader_type) & (split_rule['id'].str.split("_").str[0].astype(int).isin(self.args.training_speakers))]
+ if args.additional_data and loader_type == 'train':
+ split_b = split_rule.loc[(split_rule['type'] == 'additional') & (split_rule['id'].str.split("_").str[0].astype(int).isin(self.args.training_speakers))]
+ #self.selected_file = split_rule.loc[(split_rule['type'] == 'additional') & (split_rule['id'].str.split("_").str[0].astype(int).isin(self.args.training_speakers))]
+ self.selected_file = pd.concat([self.selected_file, split_b])
+ if self.selected_file.empty:
+ logger.warning(f"{loader_type} is empty for speaker {self.args.training_speakers}, use train set 0-8 instead")
+ self.selected_file = split_rule.loc[(split_rule['type'] == 'train') & (split_rule['id'].str.split("_").str[0].astype(int).isin(self.args.training_speakers))]
+ self.selected_file = self.selected_file.iloc[0:8]
+ self.data_dir = args.data_path
+
+ if loader_type == "test":
+ self.args.multi_length_training = [1.0]
+ self.max_length = int(args.pose_length * self.args.multi_length_training[-1])
+ self.max_audio_pre_len = math.floor(args.pose_length / args.pose_fps * self.args.audio_sr)
+ if self.max_audio_pre_len > self.args.test_length*self.args.audio_sr:
+ self.max_audio_pre_len = self.args.test_length*self.args.audio_sr
+
+ if args.word_rep is not None:
+ with open(f"{args.data_path}weights/vocab.pkl", 'rb') as f:
+ self.lang_model = pickle.load(f)
+
+ preloaded_dir = self.args.root_path + self.args.cache_path + loader_type + f"/{args.pose_rep}_cache"
+ # if args.pose_norm:
+ # # careful for rotation vectors
+ # if not os.path.exists(args.data_path+args.mean_pose_path+f"{args.pose_rep.split('_')[0]}/bvh_mean.npy"):
+ # self.calculate_mean_pose()
+ # self.mean_pose = np.load(args.data_path+args.mean_pose_path+f"{args.pose_rep.split('_')[0]}/bvh_mean.npy")
+ # self.std_pose = np.load(args.data_path+args.mean_pose_path+f"{args.pose_rep.split('_')[0]}/bvh_std.npy")
+ # if args.audio_norm:
+ # if not os.path.exists(args.data_path+args.mean_pose_path+f"{args.audio_rep.split('_')[0]}/bvh_mean.npy"):
+ # self.calculate_mean_audio()
+ # self.mean_audio = np.load(args.data_path+args.mean_pose_path+f"{args.audio_rep.split('_')[0]}/npy_mean.npy")
+ # self.std_audio = np.load(args.data_path+args.mean_pose_path+f"{args.audio_rep.split('_')[0]}/npy_std.npy")
+ # if args.facial_norm:
+ # if not os.path.exists(args.data_path+args.mean_pose_path+f"{args.pose_rep.split('_')[0]}/bvh_mean.npy"):
+ # self.calculate_mean_face()
+ # self.mean_facial = np.load(args.data_path+args.mean_pose_path+f"{args.facial_rep}/json_mean.npy")
+ # self.std_facial = np.load(args.data_path+args.mean_pose_path+f"{args.facial_rep}/json_std.npy")
+ if self.args.beat_align:
+ if not os.path.exists(args.data_path+f"weights/mean_vel_{args.pose_rep}.npy"):
+ self.calculate_mean_velocity(args.data_path+f"weights/mean_vel_{args.pose_rep}.npy")
+ self.avg_vel = np.load(args.data_path+f"weights/mean_vel_{args.pose_rep}.npy")
+
+ if build_cache and self.rank == 0:
+ self.build_cache(preloaded_dir)
+ self.lmdb_env = lmdb.open(preloaded_dir, readonly=True, lock=False)
+ with self.lmdb_env.begin() as txn:
+ self.n_samples = txn.stat()["entries"]
+
+
+ def calculate_mean_velocity(self, save_path):
+ self.smplx = smplx.create(
+ self.args.data_path_1+"smplx_models/",
+ model_type='smplx',
+ gender='NEUTRAL_2020',
+ use_face_contour=False,
+ num_betas=300,
+ num_expression_coeffs=100,
+ ext='npz',
+ use_pca=False,
+ ).cuda().eval()
+ dir_p = self.data_dir + self.args.pose_rep + "/"
+ all_list = []
+ from tqdm import tqdm
+ for tar in tqdm(os.listdir(dir_p)):
+ if tar.endswith(".npz"):
+ m_data = np.load(dir_p+tar, allow_pickle=True)
+ betas, poses, trans, exps = m_data["betas"], m_data["poses"], m_data["trans"], m_data["expressions"]
+ n, c = poses.shape[0], poses.shape[1]
+ betas = betas.reshape(1, 300)
+ betas = np.tile(betas, (n, 1))
+ betas = torch.from_numpy(betas).cuda().float()
+ poses = torch.from_numpy(poses.reshape(n, c)).cuda().float()
+ exps = torch.from_numpy(exps.reshape(n, 100)).cuda().float()
+ trans = torch.from_numpy(trans.reshape(n, 3)).cuda().float()
+ max_length = 128
+ s, r = n//max_length, n%max_length
+ #print(n, s, r)
+ all_tensor = []
+ for i in range(s):
+ with torch.no_grad():
+ joints = self.smplx(
+ betas=betas[i*max_length:(i+1)*max_length],
+ transl=trans[i*max_length:(i+1)*max_length],
+ expression=exps[i*max_length:(i+1)*max_length],
+ jaw_pose=poses[i*max_length:(i+1)*max_length, 66:69],
+ global_orient=poses[i*max_length:(i+1)*max_length,:3],
+ body_pose=poses[i*max_length:(i+1)*max_length,3:21*3+3],
+ left_hand_pose=poses[i*max_length:(i+1)*max_length,25*3:40*3],
+ right_hand_pose=poses[i*max_length:(i+1)*max_length,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=poses[i*max_length:(i+1)*max_length, 69:72],
+ reye_pose=poses[i*max_length:(i+1)*max_length, 72:75],
+ )['joints'][:, :55, :].reshape(max_length, 55*3)
+ all_tensor.append(joints)
+ if r != 0:
+ with torch.no_grad():
+ joints = self.smplx(
+ betas=betas[s*max_length:s*max_length+r],
+ transl=trans[s*max_length:s*max_length+r],
+ expression=exps[s*max_length:s*max_length+r],
+ jaw_pose=poses[s*max_length:s*max_length+r, 66:69],
+ global_orient=poses[s*max_length:s*max_length+r,:3],
+ body_pose=poses[s*max_length:s*max_length+r,3:21*3+3],
+ left_hand_pose=poses[s*max_length:s*max_length+r,25*3:40*3],
+ right_hand_pose=poses[s*max_length:s*max_length+r,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=poses[s*max_length:s*max_length+r, 69:72],
+ reye_pose=poses[s*max_length:s*max_length+r, 72:75],
+ )['joints'][:, :55, :].reshape(r, 55*3)
+ all_tensor.append(joints)
+ joints = torch.cat(all_tensor, axis=0)
+ joints = joints.permute(1, 0)
+ dt = 1/30
+ # first steps is forward diff (t+1 - t) / dt
+ init_vel = (joints[:, 1:2] - joints[:, :1]) / dt
+ # middle steps are second order (t+1 - t-1) / 2dt
+ middle_vel = (joints[:, 2:] - joints[:, 0:-2]) / (2 * dt)
+ # last step is backward diff (t - t-1) / dt
+ final_vel = (joints[:, -1:] - joints[:, -2:-1]) / dt
+ #print(joints.shape, init_vel.shape, middle_vel.shape, final_vel.shape)
+ vel_seq = torch.cat([init_vel, middle_vel, final_vel], dim=1).permute(1, 0).reshape(n, 55, 3)
+ #print(vel_seq.shape)
+ #.permute(1, 0).reshape(n, 55, 3)
+ vel_seq_np = vel_seq.cpu().numpy()
+ vel_joints_np = np.linalg.norm(vel_seq_np, axis=2) # n * 55
+ all_list.append(vel_joints_np)
+ avg_vel = np.mean(np.concatenate(all_list, axis=0),axis=0) # 55
+ np.save(save_path, avg_vel)
+
+
+ def build_cache(self, preloaded_dir):
+ logger.info(f"Audio bit rate: {self.args.audio_fps}")
+ logger.info("Reading data '{}'...".format(self.data_dir))
+ logger.info("Creating the dataset cache...")
+ if self.args.new_cache:
+ if os.path.exists(preloaded_dir):
+ shutil.rmtree(preloaded_dir)
+ if os.path.exists(preloaded_dir):
+ logger.info("Found the cache {}".format(preloaded_dir))
+ elif self.loader_type == "test":
+ self.cache_generation(
+ preloaded_dir, True,
+ 0, 0,
+ is_test=True)
+ else:
+ self.cache_generation(
+ preloaded_dir, self.args.disable_filtering,
+ self.args.clean_first_seconds, self.args.clean_final_seconds,
+ is_test=False)
+
+ def __len__(self):
+ return self.n_samples
+
+
+ def cache_generation(self, out_lmdb_dir, disable_filtering, clean_first_seconds, clean_final_seconds, is_test=False):
+ # if "wav2vec2" in self.args.audio_rep:
+ # self.wav2vec_model = Wav2Vec2Model.from_pretrained(f"{self.args.data_path_1}/hub/transformer/wav2vec2-base-960h")
+ # self.wav2vec_model.feature_extractor._freeze_parameters()
+ # self.wav2vec_model = self.wav2vec_model.cuda()
+ # self.wav2vec_model.eval()
+
+ self.n_out_samples = 0
+ # create db for samples
+ if not os.path.exists(out_lmdb_dir): os.makedirs(out_lmdb_dir)
+ dst_lmdb_env = lmdb.open(out_lmdb_dir, map_size= int(1024 ** 3 * 50))# 50G
+ n_filtered_out = defaultdict(int)
+
+ for index, file_name in self.selected_file.iterrows():
+ f_name = file_name["id"]
+ ext = ".npz" if "smplx" in self.args.pose_rep else ".bvh"
+ pose_file = self.data_dir + self.args.pose_rep + "/" + f_name + ext
+ pose_each_file = []
+ trans_each_file = []
+ shape_each_file = []
+ audio_each_file = []
+ facial_each_file = []
+ word_each_file = []
+ emo_each_file = []
+ sem_each_file = []
+ vid_each_file = []
+ id_pose = f_name #1_wayne_0_1_1
+
+ logger.info(colored(f"# ---- Building cache for Pose {id_pose} ---- #", "blue"))
+ if "smplx" in self.args.pose_rep:
+ pose_data = np.load(pose_file, allow_pickle=True)
+ assert 30%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 30'
+ stride = int(30/self.args.pose_fps)
+ pose_each_file = pose_data["poses"][::stride] * self.joint_mask
+ trans_each_file = pose_data["trans"][::stride]
+ shape_each_file = np.repeat(pose_data["betas"].reshape(1, 300), pose_each_file.shape[0], axis=0)
+ if self.args.facial_rep is not None:
+ logger.info(f"# ---- Building cache for Facial {id_pose} and Pose {id_pose} ---- #")
+ facial_each_file = pose_data["expressions"][::stride]
+ if self.args.facial_norm:
+ facial_each_file = (facial_each_file - self.mean_facial) / self.std_facial
+
+ else:
+ assert 120%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 120'
+ stride = int(120/self.args.pose_fps)
+ with open(pose_file, "r") as pose_data:
+ for j, line in enumerate(pose_data.readlines()):
+ if j < 431: continue
+ if j%stride != 0:continue
+ data = np.fromstring(line, dtype=float, sep=" ")
+ rot_data = rc.euler_angles_to_matrix(torch.from_numpy(np.deg2rad(data)).reshape(-1, self.joints,3), "XYZ")
+ rot_data = rc.matrix_to_axis_angle(rot_data).reshape(-1, self.joints*3)
+ rot_data = rot_data.numpy() * self.joint_mask
+
+ pose_each_file.append(rot_data)
+ trans_each_file.append(data[:3])
+
+ pose_each_file = np.array(pose_each_file)
+ # print(pose_each_file.shape)
+ trans_each_file = np.array(trans_each_file)
+ shape_each_file = np.repeat(np.array(-1).reshape(1, 1), pose_each_file.shape[0], axis=0)
+ if self.args.facial_rep is not None:
+ logger.info(f"# ---- Building cache for Facial {id_pose} and Pose {id_pose} ---- #")
+ facial_file = pose_file.replace(self.args.pose_rep, self.args.facial_rep).replace("bvh", "json")
+ assert 60%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 120'
+ stride = int(60/self.args.pose_fps)
+ if not os.path.exists(facial_file):
+ logger.warning(f"# ---- file not found for Facial {id_pose}, skip all files with the same id ---- #")
+ self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ continue
+ with open(facial_file, 'r') as facial_data_file:
+ facial_data = json.load(facial_data_file)
+ for j, frame_data in enumerate(facial_data['frames']):
+ if j%stride != 0:continue
+ facial_each_file.append(frame_data['weights'])
+ facial_each_file = np.array(facial_each_file)
+ if self.args.facial_norm:
+ facial_each_file = (facial_each_file - self.mean_facial) / self.std_facial
+
+ if self.args.id_rep is not None:
+ vid_each_file = np.repeat(np.array(int(f_name.split("_")[0])-1).reshape(1, 1), pose_each_file.shape[0], axis=0)
+
+ if self.args.audio_rep is not None:
+ logger.info(f"# ---- Building cache for Audio {id_pose} and Pose {id_pose} ---- #")
+ audio_file = pose_file.replace(self.args.pose_rep, 'wave16k').replace(ext, ".wav")
+ if not os.path.exists(audio_file):
+ logger.warning(f"# ---- file not found for Audio {id_pose}, skip all files with the same id ---- #")
+ self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ continue
+ audio_each_file, sr = librosa.load(audio_file)
+ audio_each_file = librosa.resample(audio_each_file, orig_sr=sr, target_sr=self.args.audio_sr)
+ if self.args.audio_rep == "onset+amplitude":
+ from numpy.lib import stride_tricks
+ frame_length = 1024
+ # hop_length = 512
+ shape = (audio_each_file.shape[-1] - frame_length + 1, frame_length)
+ strides = (audio_each_file.strides[-1], audio_each_file.strides[-1])
+ rolling_view = stride_tricks.as_strided(audio_each_file, shape=shape, strides=strides)
+ amplitude_envelope = np.max(np.abs(rolling_view), axis=1)
+ # pad the last frame_length-1 samples
+ amplitude_envelope = np.pad(amplitude_envelope, (0, frame_length-1), mode='constant', constant_values=amplitude_envelope[-1])
+ audio_onset_f = librosa.onset.onset_detect(y=audio_each_file, sr=self.args.audio_sr, units='frames')
+ onset_array = np.zeros(len(audio_each_file), dtype=float)
+ onset_array[audio_onset_f] = 1.0
+ # print(amplitude_envelope.shape, audio_each_file.shape, onset_array.shape)
+ audio_each_file = np.concatenate([amplitude_envelope.reshape(-1, 1), onset_array.reshape(-1, 1)], axis=1)
+ elif self.args.audio_rep == "mfcc":
+ audio_each_file = librosa.feature.mfcc(audio_each_file, sr=self.args.audio_sr, n_mfcc=13, hop_length=int(self.args.audio_sr/self.args.audio_fps))
+
+ if self.args.audio_norm and self.args.audio_rep == "wave16k":
+ audio_each_file = (audio_each_file - self.mean_audio) / self.std_audio
+
+ time_offset = 0
+ if self.args.word_rep is not None:
+ logger.info(f"# ---- Building cache for Word {id_pose} and Pose {id_pose} ---- #")
+ word_file = f"{self.data_dir}{self.args.word_rep}/{id_pose}.TextGrid"
+ if not os.path.exists(word_file):
+ logger.warning(f"# ---- file not found for Word {id_pose}, skip all files with the same id ---- #")
+ self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ continue
+ tgrid = tg.TextGrid.fromFile(word_file)
+ if self.args.t_pre_encoder == "bert":
+ from transformers import AutoTokenizer, BertModel
+ tokenizer = AutoTokenizer.from_pretrained(self.args.data_path_1 + "hub/bert-base-uncased", local_files_only=True)
+ model = BertModel.from_pretrained(self.args.data_path_1 + "hub/bert-base-uncased", local_files_only=True).eval()
+ list_word = []
+ all_hidden = []
+ max_len = 400
+ last = 0
+ word_token_mapping = []
+ first = True
+ for i, word in enumerate(tgrid[0]):
+ last = i
+ if (i%max_len != 0) or (i==0):
+ if word.mark == "":
+ list_word.append(".")
+ else:
+ list_word.append(word.mark)
+ else:
+ max_counter = max_len
+ str_word = ' '.join(map(str, list_word))
+ if first:
+ global_len = 0
+ end = -1
+ offset_word = []
+ for k, wordvalue in enumerate(list_word):
+ start = end+1
+ end = start+len(wordvalue)
+ offset_word.append((start, end))
+ #print(offset_word)
+ token_scan = tokenizer.encode_plus(str_word, return_offsets_mapping=True)['offset_mapping']
+ #print(token_scan)
+ for start, end in offset_word:
+ sub_mapping = []
+ for i, (start_t, end_t) in enumerate(token_scan[1:-1]):
+ if int(start) <= int(start_t) and int(end_t) <= int(end):
+ #print(i+global_len)
+ sub_mapping.append(i+global_len)
+ word_token_mapping.append(sub_mapping)
+ #print(len(word_token_mapping))
+ global_len = word_token_mapping[-1][-1] + 1
+ list_word = []
+ if word.mark == "":
+ list_word.append(".")
+ else:
+ list_word.append(word.mark)
+
+ with torch.no_grad():
+ inputs = tokenizer(str_word, return_tensors="pt")
+ outputs = model(**inputs)
+ last_hidden_states = outputs.last_hidden_state.reshape(-1, 768).cpu().numpy()[1:-1, :]
+ all_hidden.append(last_hidden_states)
+
+ #list_word = list_word[:10]
+ if list_word == []:
+ pass
+ else:
+ if first:
+ global_len = 0
+ str_word = ' '.join(map(str, list_word))
+ end = -1
+ offset_word = []
+ for k, wordvalue in enumerate(list_word):
+ start = end+1
+ end = start+len(wordvalue)
+ offset_word.append((start, end))
+ #print(offset_word)
+ token_scan = tokenizer.encode_plus(str_word, return_offsets_mapping=True)['offset_mapping']
+ #print(token_scan)
+ for start, end in offset_word:
+ sub_mapping = []
+ for i, (start_t, end_t) in enumerate(token_scan[1:-1]):
+ if int(start) <= int(start_t) and int(end_t) <= int(end):
+ sub_mapping.append(i+global_len)
+ #print(sub_mapping)
+ word_token_mapping.append(sub_mapping)
+ #print(len(word_token_mapping))
+ with torch.no_grad():
+ inputs = tokenizer(str_word, return_tensors="pt")
+ outputs = model(**inputs)
+ last_hidden_states = outputs.last_hidden_state.reshape(-1, 768).cpu().numpy()[1:-1, :]
+ all_hidden.append(last_hidden_states)
+ last_hidden_states = np.concatenate(all_hidden, axis=0)
+
+ for i in range(pose_each_file.shape[0]):
+ found_flag = False
+ current_time = i/self.args.pose_fps + time_offset
+ j_last = 0
+ for j, word in enumerate(tgrid[0]):
+ word_n, word_s, word_e = word.mark, word.minTime, word.maxTime
+ if word_s<=current_time and current_time<=word_e:
+ if self.args.word_cache and self.args.t_pre_encoder == 'bert':
+ mapping_index = word_token_mapping[j]
+ #print(mapping_index, word_s, word_e)
+ s_t = np.linspace(word_s, word_e, len(mapping_index)+1)
+ #print(s_t)
+ for tt, t_sep in enumerate(s_t[1:]):
+ if current_time <= t_sep:
+ #if len(mapping_index) > 1: print(mapping_index[tt])
+ word_each_file.append(last_hidden_states[mapping_index[tt]])
+ break
+ else:
+ if word_n == " ":
+ word_each_file.append(self.lang_model.PAD_token)
+ else:
+ word_each_file.append(self.lang_model.get_word_index(word_n))
+ found_flag = True
+ j_last = j
+ break
+ else: continue
+ if not found_flag:
+ if self.args.word_cache and self.args.t_pre_encoder == 'bert':
+ word_each_file.append(last_hidden_states[j_last])
+ else:
+ word_each_file.append(self.lang_model.UNK_token)
+ word_each_file = np.array(word_each_file)
+ #print(word_each_file.shape)
+
+ if self.args.emo_rep is not None:
+ logger.info(f"# ---- Building cache for Emo {id_pose} and Pose {id_pose} ---- #")
+ rtype, start = int(id_pose.split('_')[3]), int(id_pose.split('_')[3])
+ if rtype == 0 or rtype == 2 or rtype == 4 or rtype == 6:
+ if start >= 1 and start <= 64:
+ score = 0
+ elif start >= 65 and start <= 72:
+ score = 1
+ elif start >= 73 and start <= 80:
+ score = 2
+ elif start >= 81 and start <= 86:
+ score = 3
+ elif start >= 87 and start <= 94:
+ score = 4
+ elif start >= 95 and start <= 102:
+ score = 5
+ elif start >= 103 and start <= 110:
+ score = 6
+ elif start >= 111 and start <= 118:
+ score = 7
+ else: pass
+ else:
+ # you may denote as unknown in the future
+ score = 0
+ emo_each_file = np.repeat(np.array(score).reshape(1, 1), pose_each_file.shape[0], axis=0)
+ #print(emo_each_file)
+
+ if self.args.sem_rep is not None:
+ logger.info(f"# ---- Building cache for Sem {id_pose} and Pose {id_pose} ---- #")
+ sem_file = f"{self.data_dir}{self.args.sem_rep}/{id_pose}.txt"
+ sem_all = pd.read_csv(sem_file,
+ sep='\t',
+ names=["name", "start_time", "end_time", "duration", "score", "keywords"])
+ # we adopt motion-level semantic score here.
+ for i in range(pose_each_file.shape[0]):
+ found_flag = False
+ for j, (start, end, score) in enumerate(zip(sem_all['start_time'],sem_all['end_time'], sem_all['score'])):
+ current_time = i/self.args.pose_fps + time_offset
+ if start<=current_time and current_time<=end:
+ sem_each_file.append(score)
+ found_flag=True
+ break
+ else: continue
+ if not found_flag: sem_each_file.append(0.)
+ sem_each_file = np.array(sem_each_file)
+ #print(sem_each_file)
+
+ filtered_result = self._sample_from_clip(
+ dst_lmdb_env,
+ audio_each_file, pose_each_file, trans_each_file, shape_each_file, facial_each_file, word_each_file,
+ vid_each_file, emo_each_file, sem_each_file,
+ disable_filtering, clean_first_seconds, clean_final_seconds, is_test,
+ )
+ for type in filtered_result.keys():
+ n_filtered_out[type] += filtered_result[type]
+
+ with dst_lmdb_env.begin() as txn:
+ logger.info(colored(f"no. of samples: {txn.stat()['entries']}", "cyan"))
+ n_total_filtered = 0
+ for type, n_filtered in n_filtered_out.items():
+ logger.info("{}: {}".format(type, n_filtered))
+ n_total_filtered += n_filtered
+ logger.info(colored("no. of excluded samples: {} ({:.1f}%)".format(
+ n_total_filtered, 100 * n_total_filtered / (txn.stat()["entries"] + n_total_filtered)), "cyan"))
+ dst_lmdb_env.sync()
+ dst_lmdb_env.close()
+
+ def _sample_from_clip(
+ self, dst_lmdb_env, audio_each_file, pose_each_file, trans_each_file, shape_each_file, facial_each_file, word_each_file,
+ vid_each_file, emo_each_file, sem_each_file,
+ disable_filtering, clean_first_seconds, clean_final_seconds, is_test,
+ ):
+ """
+ for data cleaning, we ignore the data for first and final n s
+ for test, we return all data
+ """
+ # audio_start = int(self.alignment[0] * self.args.audio_fps)
+ # pose_start = int(self.alignment[1] * self.args.pose_fps)
+ #logger.info(f"before: {audio_each_file.shape} {pose_each_file.shape}")
+ # audio_each_file = audio_each_file[audio_start:]
+ # pose_each_file = pose_each_file[pose_start:]
+ # trans_each_file =
+ #logger.info(f"after alignment: {audio_each_file.shape} {pose_each_file.shape}")
+ #print(pose_each_file.shape)
+ round_seconds_skeleton = pose_each_file.shape[0] // self.args.pose_fps # assume 1500 frames / 15 fps = 100 s
+ #print(round_seconds_skeleton)
+ if audio_each_file != []:
+ round_seconds_audio = len(audio_each_file) // self.args.audio_fps # assume 16,000,00 / 16,000 = 100 s
+ if facial_each_file != []:
+ round_seconds_facial = facial_each_file.shape[0] // self.args.pose_fps
+ logger.info(f"audio: {round_seconds_audio}s, pose: {round_seconds_skeleton}s, facial: {round_seconds_facial}s")
+ round_seconds_skeleton = min(round_seconds_audio, round_seconds_skeleton, round_seconds_facial)
+ max_round = max(round_seconds_audio, round_seconds_skeleton, round_seconds_facial)
+ if round_seconds_skeleton != max_round:
+ logger.warning(f"reduce to {round_seconds_skeleton}s, ignore {max_round-round_seconds_skeleton}s")
+ else:
+ logger.info(f"pose: {round_seconds_skeleton}s, audio: {round_seconds_audio}s")
+ round_seconds_skeleton = min(round_seconds_audio, round_seconds_skeleton)
+ max_round = max(round_seconds_audio, round_seconds_skeleton)
+ if round_seconds_skeleton != max_round:
+ logger.warning(f"reduce to {round_seconds_skeleton}s, ignore {max_round-round_seconds_skeleton}s")
+
+ clip_s_t, clip_e_t = clean_first_seconds, round_seconds_skeleton - clean_final_seconds # assume [10, 90]s
+ clip_s_f_audio, clip_e_f_audio = self.args.audio_fps * clip_s_t, clip_e_t * self.args.audio_fps # [160,000,90*160,000]
+ clip_s_f_pose, clip_e_f_pose = clip_s_t * self.args.pose_fps, clip_e_t * self.args.pose_fps # [150,90*15]
+
+
+ for ratio in self.args.multi_length_training:
+ if is_test:# stride = length for test
+ cut_length = clip_e_f_pose - clip_s_f_pose
+ self.args.stride = cut_length
+ self.max_length = cut_length
+ else:
+ self.args.stride = int(ratio*self.ori_stride)
+ cut_length = int(self.ori_length*ratio)
+
+ num_subdivision = math.floor((clip_e_f_pose - clip_s_f_pose - cut_length) / self.args.stride) + 1
+ logger.info(f"pose from frame {clip_s_f_pose} to {clip_e_f_pose}, length {cut_length}")
+ logger.info(f"{num_subdivision} clips is expected with stride {self.args.stride}")
+
+ if audio_each_file != []:
+ audio_short_length = math.floor(cut_length / self.args.pose_fps * self.args.audio_fps)
+ """
+ for audio sr = 16000, fps = 15, pose_length = 34,
+ audio short length = 36266.7 -> 36266
+ this error is fine.
+ """
+ logger.info(f"audio from frame {clip_s_f_audio} to {clip_e_f_audio}, length {audio_short_length}")
+
+ n_filtered_out = defaultdict(int)
+ sample_pose_list = []
+ sample_audio_list = []
+ sample_facial_list = []
+ sample_shape_list = []
+ sample_word_list = []
+ sample_emo_list = []
+ sample_sem_list = []
+ sample_vid_list = []
+ sample_trans_list = []
+
+ for i in range(num_subdivision): # cut into around 2s chip, (self npose)
+ start_idx = clip_s_f_pose + i * self.args.stride
+ fin_idx = start_idx + cut_length
+ sample_pose = pose_each_file[start_idx:fin_idx]
+ sample_trans = trans_each_file[start_idx:fin_idx]
+ sample_shape = shape_each_file[start_idx:fin_idx]
+ # print(sample_pose.shape)
+ if self.args.audio_rep is not None:
+ audio_start = clip_s_f_audio + math.floor(i * self.args.stride * self.args.audio_fps / self.args.pose_fps)
+ audio_end = audio_start + audio_short_length
+ sample_audio = audio_each_file[audio_start:audio_end]
+ else:
+ sample_audio = np.array([-1])
+ sample_facial = facial_each_file[start_idx:fin_idx] if self.args.facial_rep is not None else np.array([-1])
+ sample_word = word_each_file[start_idx:fin_idx] if self.args.word_rep is not None else np.array([-1])
+ sample_emo = emo_each_file[start_idx:fin_idx] if self.args.emo_rep is not None else np.array([-1])
+ sample_sem = sem_each_file[start_idx:fin_idx] if self.args.sem_rep is not None else np.array([-1])
+ sample_vid = vid_each_file[start_idx:fin_idx] if self.args.id_rep is not None else np.array([-1])
+
+ if sample_pose.any() != None:
+ # filtering motion skeleton data
+ sample_pose, filtering_message = MotionPreprocessor(sample_pose).get()
+ is_correct_motion = (sample_pose != [])
+ if is_correct_motion or disable_filtering:
+ sample_pose_list.append(sample_pose)
+ sample_audio_list.append(sample_audio)
+ sample_facial_list.append(sample_facial)
+ sample_shape_list.append(sample_shape)
+ sample_word_list.append(sample_word)
+ sample_vid_list.append(sample_vid)
+ sample_emo_list.append(sample_emo)
+ sample_sem_list.append(sample_sem)
+ sample_trans_list.append(sample_trans)
+ else:
+ n_filtered_out[filtering_message] += 1
+
+ if len(sample_pose_list) > 0:
+ with dst_lmdb_env.begin(write=True) as txn:
+ for pose, audio, facial, shape, word, vid, emo, sem, trans in zip(
+ sample_pose_list,
+ sample_audio_list,
+ sample_facial_list,
+ sample_shape_list,
+ sample_word_list,
+ sample_vid_list,
+ sample_emo_list,
+ sample_sem_list,
+ sample_trans_list,):
+ k = "{:005}".format(self.n_out_samples).encode("ascii")
+ v = [pose, audio, facial, shape, word, emo, sem, vid, trans]
+ v = pyarrow.serialize(v).to_buffer()
+ txn.put(k, v)
+ self.n_out_samples += 1
+ return n_filtered_out
+
+ def __getitem__(self, idx):
+ with self.lmdb_env.begin(write=False) as txn:
+ key = "{:005}".format(idx).encode("ascii")
+ sample = txn.get(key)
+ sample = pyarrow.deserialize(sample)
+ tar_pose, in_audio, in_facial, in_shape, in_word, emo, sem, vid, trans = sample
+ #print(in_shape)
+ #vid = torch.from_numpy(vid).int()
+ emo = torch.from_numpy(emo).int()
+ sem = torch.from_numpy(sem).float()
+ in_audio = torch.from_numpy(in_audio).float()
+ in_word = torch.from_numpy(in_word).float() if self.args.word_cache else torch.from_numpy(in_word).int()
+ if self.loader_type == "test":
+ tar_pose = torch.from_numpy(tar_pose).float()
+ trans = torch.from_numpy(trans).float()
+ in_facial = torch.from_numpy(in_facial).float()
+ vid = torch.from_numpy(vid).float()
+ in_shape = torch.from_numpy(in_shape).float()
+ else:
+ in_shape = torch.from_numpy(in_shape).reshape((in_shape.shape[0], -1)).float()
+ trans = torch.from_numpy(trans).reshape((trans.shape[0], -1)).float()
+ vid = torch.from_numpy(vid).reshape((vid.shape[0], -1)).float()
+ tar_pose = torch.from_numpy(tar_pose).reshape((tar_pose.shape[0], -1)).float()
+ in_facial = torch.from_numpy(in_facial).reshape((in_facial.shape[0], -1)).float()
+ return {"pose":tar_pose, "audio":in_audio, "facial":in_facial, "beta": in_shape, "word":in_word, "id":vid, "emo":emo, "sem":sem, "trans":trans}
+
+
+class MotionPreprocessor:
+ def __init__(self, skeletons):
+ self.skeletons = skeletons
+ #self.mean_pose = mean_pose
+ self.filtering_message = "PASS"
+
+ def get(self):
+ assert (self.skeletons is not None)
+
+ # filtering
+ if self.skeletons != []:
+ if self.check_pose_diff():
+ self.skeletons = []
+ self.filtering_message = "pose"
+ # elif self.check_spine_angle():
+ # self.skeletons = []
+ # self.filtering_message = "spine angle"
+ # elif self.check_static_motion():
+ # self.skeletons = []
+ # self.filtering_message = "motion"
+
+ # if self.skeletons != []:
+ # self.skeletons = self.skeletons.tolist()
+ # for i, frame in enumerate(self.skeletons):
+ # assert not np.isnan(self.skeletons[i]).any() # missing joints
+
+ return self.skeletons, self.filtering_message
+
+ def check_static_motion(self, verbose=True):
+ def get_variance(skeleton, joint_idx):
+ wrist_pos = skeleton[:, joint_idx]
+ variance = np.sum(np.var(wrist_pos, axis=0))
+ return variance
+
+ left_arm_var = get_variance(self.skeletons, 6)
+ right_arm_var = get_variance(self.skeletons, 9)
+
+ th = 0.0014 # exclude 13110
+ # th = 0.002 # exclude 16905
+ if left_arm_var < th and right_arm_var < th:
+ if verbose:
+ print("skip - check_static_motion left var {}, right var {}".format(left_arm_var, right_arm_var))
+ return True
+ else:
+ if verbose:
+ print("pass - check_static_motion left var {}, right var {}".format(left_arm_var, right_arm_var))
+ return False
+
+
+ def check_pose_diff(self, verbose=False):
+# diff = np.abs(self.skeletons - self.mean_pose) # 186*1
+# diff = np.mean(diff)
+
+# # th = 0.017
+# th = 0.02 #0.02 # exclude 3594
+# if diff < th:
+# if verbose:
+# print("skip - check_pose_diff {:.5f}".format(diff))
+# return True
+# # th = 3.5 #0.02 # exclude 3594
+# # if 3.5 < diff < 5:
+# # if verbose:
+# # print("skip - check_pose_diff {:.5f}".format(diff))
+# # return True
+# else:
+# if verbose:
+# print("pass - check_pose_diff {:.5f}".format(diff))
+ return False
+
+
+ def check_spine_angle(self, verbose=True):
+ def angle_between(v1, v2):
+ v1_u = v1 / np.linalg.norm(v1)
+ v2_u = v2 / np.linalg.norm(v2)
+ return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0))
+
+ angles = []
+ for i in range(self.skeletons.shape[0]):
+ spine_vec = self.skeletons[i, 1] - self.skeletons[i, 0]
+ angle = angle_between(spine_vec, [0, -1, 0])
+ angles.append(angle)
+
+ if np.rad2deg(max(angles)) > 30 or np.rad2deg(np.mean(angles)) > 20: # exclude 4495
+ # if np.rad2deg(max(angles)) > 20: # exclude 8270
+ if verbose:
+ print("skip - check_spine_angle {:.5f}, {:.5f}".format(max(angles), np.mean(angles)))
+ return True
+ else:
+ if verbose:
+ print("pass - check_spine_angle {:.5f}".format(max(angles)))
+ return False
\ No newline at end of file
diff --git a/dataloaders/beat_testonly.py b/dataloaders/beat_testonly.py
new file mode 100644
index 0000000000000000000000000000000000000000..d6d8d8fd524d63754ae68ba999f12085208f91bb
--- /dev/null
+++ b/dataloaders/beat_testonly.py
@@ -0,0 +1,731 @@
+import os
+import pickle
+import math
+import shutil
+import numpy as np
+import lmdb as lmdb
+import textgrid as tg
+import pandas as pd
+import torch
+import glob
+import json
+from termcolor import colored
+from loguru import logger
+from collections import defaultdict
+from torch.utils.data import Dataset
+import torch.distributed as dist
+import pyarrow
+import librosa
+import smplx
+
+from .build_vocab import Vocab
+from .utils.audio_features import Wav2Vec2Model
+from .data_tools import joints_list
+from .utils import rotation_conversions as rc
+from .utils import other_tools
+
+class CustomDataset(Dataset):
+ def __init__(self, args, loader_type, augmentation=None, kwargs=None, build_cache=True):
+ self.args = args
+ self.loader_type = loader_type
+
+ self.rank = dist.get_rank()
+ self.ori_stride = self.args.stride
+ self.ori_length = self.args.pose_length
+ self.alignment = [0,0] # for trinity
+
+ self.ori_joint_list = joints_list[self.args.ori_joints]
+ self.tar_joint_list = joints_list[self.args.tar_joints]
+ if 'smplx' in self.args.pose_rep:
+ self.joint_mask = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ self.joints = len(list(self.tar_joint_list.keys()))
+ for joint_name in self.tar_joint_list:
+ self.joint_mask[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ else:
+ self.joints = len(list(self.ori_joint_list.keys()))+1
+ self.joint_mask = np.zeros(self.joints*3)
+ for joint_name in self.tar_joint_list:
+ if joint_name == "Hips":
+ self.joint_mask[3:6] = 1
+ else:
+ self.joint_mask[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ # select trainable joints
+ self.smplx = smplx.create(
+ self.args.data_path_1+"smplx_models/",
+ model_type='smplx',
+ gender='NEUTRAL_2020',
+ use_face_contour=False,
+ num_betas=300,
+ num_expression_coeffs=100,
+ ext='npz',
+ use_pca=False,
+ ).cuda().eval()
+
+ split_rule = pd.read_csv(args.data_path+"test.csv")
+ self.selected_file = split_rule
+ self.data_dir = args.data_path
+
+ if loader_type == "test":
+ self.args.multi_length_training = [1.0]
+ self.max_length = int(args.pose_length * self.args.multi_length_training[-1])
+ self.max_audio_pre_len = math.floor(args.pose_length / args.pose_fps * self.args.audio_sr)
+ if self.max_audio_pre_len > self.args.test_length*self.args.audio_sr:
+ self.max_audio_pre_len = self.args.test_length*self.args.audio_sr
+
+ if args.word_rep is not None:
+ with open(f"{args.data_path}weights/vocab.pkl", 'rb') as f:
+ self.lang_model = pickle.load(f)
+
+ preloaded_dir = self.args.root_path + self.args.cache_path + loader_type + f"/{args.pose_rep}_cache"
+ if build_cache and self.rank == 0:
+ self.build_cache(preloaded_dir)
+ self.lmdb_env = lmdb.open(preloaded_dir, readonly=True, lock=False)
+ with self.lmdb_env.begin() as txn:
+ self.n_samples = txn.stat()["entries"]
+
+
+ def build_cache(self, preloaded_dir):
+ logger.info(f"Audio bit rate: {self.args.audio_fps}")
+ logger.info("Reading data '{}'...".format(self.data_dir))
+ logger.info("Creating the dataset cache...")
+ if self.args.new_cache:
+ if os.path.exists(preloaded_dir):
+ shutil.rmtree(preloaded_dir)
+ if os.path.exists(preloaded_dir):
+ logger.info("Found the cache {}".format(preloaded_dir))
+ elif self.loader_type == "test":
+ self.cache_generation(
+ preloaded_dir, True,
+ 0, 0,
+ is_test=True)
+ else:
+ self.cache_generation(
+ preloaded_dir, self.args.disable_filtering,
+ self.args.clean_first_seconds, self.args.clean_final_seconds,
+ is_test=False)
+
+
+ def __len__(self):
+ return self.n_samples
+
+
+ def cache_generation(self, out_lmdb_dir, disable_filtering, clean_first_seconds, clean_final_seconds, is_test=False):
+ self.n_out_samples = 0
+ # create db for samples
+ if not os.path.exists(out_lmdb_dir): os.makedirs(out_lmdb_dir)
+ if len(self.args.training_speakers) == 1:
+ dst_lmdb_env = lmdb.open(out_lmdb_dir, map_size= int(1024 ** 3 * 50))# 50G
+ else:
+ dst_lmdb_env = lmdb.open(out_lmdb_dir, map_size= int(1024 ** 3 * 200))# 200G
+ n_filtered_out = defaultdict(int)
+
+ for index, file_name in self.selected_file.iterrows():
+ f_name = file_name["id"]
+ ext = ".npz" if "smplx" in self.args.pose_rep else ".bvh"
+ pose_file = self.data_dir + self.args.pose_rep + "/" + f_name + ext
+ pose_each_file = []
+ trans_each_file = []
+ shape_each_file = []
+ audio_each_file = []
+ facial_each_file = []
+ word_each_file = []
+ emo_each_file = []
+ sem_each_file = []
+ vid_each_file = []
+ id_pose = f_name #1_wayne_0_1_1
+
+ logger.info(colored(f"# ---- Building cache for Pose {id_pose} ---- #", "blue"))
+ if "smplx" in self.args.pose_rep:
+ pose_data = np.load(pose_file, allow_pickle=True)
+ assert 30%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 30'
+ stride = int(30/self.args.pose_fps)
+ pose_each_file = pose_data["poses"][::stride]
+ trans_each_file = pose_data["trans"][::stride]
+ shape_each_file = np.repeat(pose_data["betas"].reshape(1, 300), pose_each_file.shape[0], axis=0)
+
+ assert self.args.pose_fps == 30, "should 30"
+ m_data = np.load(pose_file, allow_pickle=True)
+ betas, poses, trans, exps = m_data["betas"], m_data["poses"], m_data["trans"], m_data["expressions"]
+ n, c = poses.shape[0], poses.shape[1]
+ betas = betas.reshape(1, 300)
+ betas = np.tile(betas, (n, 1))
+ betas = torch.from_numpy(betas).cuda().float()
+ poses = torch.from_numpy(poses.reshape(n, c)).cuda().float()
+ exps = torch.from_numpy(exps.reshape(n, 100)).cuda().float()
+ trans = torch.from_numpy(trans.reshape(n, 3)).cuda().float()
+ max_length = 128
+ s, r = n//max_length, n%max_length
+ #print(n, s, r)
+ all_tensor = []
+ for i in range(s):
+ with torch.no_grad():
+ joints = self.smplx(
+ betas=betas[i*max_length:(i+1)*max_length],
+ transl=trans[i*max_length:(i+1)*max_length],
+ expression=exps[i*max_length:(i+1)*max_length],
+ jaw_pose=poses[i*max_length:(i+1)*max_length, 66:69],
+ global_orient=poses[i*max_length:(i+1)*max_length,:3],
+ body_pose=poses[i*max_length:(i+1)*max_length,3:21*3+3],
+ left_hand_pose=poses[i*max_length:(i+1)*max_length,25*3:40*3],
+ right_hand_pose=poses[i*max_length:(i+1)*max_length,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=poses[i*max_length:(i+1)*max_length, 69:72],
+ reye_pose=poses[i*max_length:(i+1)*max_length, 72:75],
+ )['joints'][:, (7,8,10,11), :].reshape(max_length, 4, 3).cpu()
+ all_tensor.append(joints)
+ if r != 0:
+ with torch.no_grad():
+ joints = self.smplx(
+ betas=betas[s*max_length:s*max_length+r],
+ transl=trans[s*max_length:s*max_length+r],
+ expression=exps[s*max_length:s*max_length+r],
+ jaw_pose=poses[s*max_length:s*max_length+r, 66:69],
+ global_orient=poses[s*max_length:s*max_length+r,:3],
+ body_pose=poses[s*max_length:s*max_length+r,3:21*3+3],
+ left_hand_pose=poses[s*max_length:s*max_length+r,25*3:40*3],
+ right_hand_pose=poses[s*max_length:s*max_length+r,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=poses[s*max_length:s*max_length+r, 69:72],
+ reye_pose=poses[s*max_length:s*max_length+r, 72:75],
+ )['joints'][:, (7,8,10,11), :].reshape(r, 4, 3).cpu()
+ all_tensor.append(joints)
+ joints = torch.cat(all_tensor, axis=0) # all, 4, 3
+ # print(joints.shape)
+ feetv = torch.zeros(joints.shape[1], joints.shape[0])
+ joints = joints.permute(1, 0, 2)
+ #print(joints.shape, feetv.shape)
+ feetv[:, :-1] = (joints[:, 1:] - joints[:, :-1]).norm(dim=-1)
+ #print(feetv.shape)
+ contacts = (feetv < 0.01).numpy().astype(float)
+ # print(contacts.shape, contacts)
+ contacts = contacts.transpose(1, 0)
+ pose_each_file = pose_each_file * self.joint_mask
+ pose_each_file = pose_each_file[:, self.joint_mask.astype(bool)]
+ pose_each_file = np.concatenate([pose_each_file, contacts], axis=1)
+ # print(pose_each_file.shape)
+
+
+ if self.args.facial_rep is not None:
+ logger.info(f"# ---- Building cache for Facial {id_pose} and Pose {id_pose} ---- #")
+ facial_each_file = pose_data["expressions"][::stride]
+ if self.args.facial_norm:
+ facial_each_file = (facial_each_file - self.mean_facial) / self.std_facial
+
+ else:
+ assert 120%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 120'
+ stride = int(120/self.args.pose_fps)
+ with open(pose_file, "r") as pose_data:
+ for j, line in enumerate(pose_data.readlines()):
+ if j < 431: continue
+ if j%stride != 0:continue
+ data = np.fromstring(line, dtype=float, sep=" ")
+ rot_data = rc.euler_angles_to_matrix(torch.from_numpy(np.deg2rad(data)).reshape(-1, self.joints,3), "XYZ")
+ rot_data = rc.matrix_to_axis_angle(rot_data).reshape(-1, self.joints*3)
+ rot_data = rot_data.numpy() * self.joint_mask
+
+ pose_each_file.append(rot_data)
+ trans_each_file.append(data[:3])
+
+ pose_each_file = np.array(pose_each_file)
+ trans_each_file = np.array(trans_each_file)
+ shape_each_file = np.repeat(np.array(-1).reshape(1, 1), pose_each_file.shape[0], axis=0)
+ if self.args.facial_rep is not None:
+ logger.info(f"# ---- Building cache for Facial {id_pose} and Pose {id_pose} ---- #")
+ facial_file = pose_file.replace(self.args.pose_rep, self.args.facial_rep).replace("bvh", "json")
+ assert 60%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 120'
+ stride = int(60/self.args.pose_fps)
+ if not os.path.exists(facial_file):
+ logger.warning(f"# ---- file not found for Facial {id_pose}, skip all files with the same id ---- #")
+ self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ continue
+ with open(facial_file, 'r') as facial_data_file:
+ facial_data = json.load(facial_data_file)
+ for j, frame_data in enumerate(facial_data['frames']):
+ if j%stride != 0:continue
+ facial_each_file.append(frame_data['weights'])
+ facial_each_file = np.array(facial_each_file)
+ if self.args.facial_norm:
+ facial_each_file = (facial_each_file - self.mean_facial) / self.std_facial
+
+ if self.args.id_rep is not None:
+ int_value = 1
+ vid_each_file = np.repeat(np.array(int_value).reshape(1, 1), pose_each_file.shape[0], axis=0)
+
+ if self.args.audio_rep is not None:
+ logger.info(f"# ---- Building cache for Audio {id_pose} and Pose {id_pose} ---- #")
+ audio_file = pose_file.replace(self.args.pose_rep, 'wave16k').replace(ext, ".wav")
+ if not os.path.exists(audio_file):
+ logger.warning(f"# ---- file not found for Audio {id_pose}, skip all files with the same id ---- #")
+ self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ continue
+ audio_each_file, sr = librosa.load(audio_file)
+ audio_each_file = librosa.resample(audio_each_file, orig_sr=sr, target_sr=self.args.audio_sr)
+ if self.args.audio_rep == "onset+amplitude":
+ from numpy.lib import stride_tricks
+ frame_length = 1024
+ # hop_length = 512
+ shape = (audio_each_file.shape[-1] - frame_length + 1, frame_length)
+ strides = (audio_each_file.strides[-1], audio_each_file.strides[-1])
+ rolling_view = stride_tricks.as_strided(audio_each_file, shape=shape, strides=strides)
+ amplitude_envelope = np.max(np.abs(rolling_view), axis=1)
+ # pad the last frame_length-1 samples
+ amplitude_envelope = np.pad(amplitude_envelope, (0, frame_length-1), mode='constant', constant_values=amplitude_envelope[-1])
+ audio_onset_f = librosa.onset.onset_detect(y=audio_each_file, sr=self.args.audio_sr, units='frames')
+ onset_array = np.zeros(len(audio_each_file), dtype=float)
+ onset_array[audio_onset_f] = 1.0
+ # print(amplitude_envelope.shape, audio_each_file.shape, onset_array.shape)
+ audio_each_file = np.concatenate([amplitude_envelope.reshape(-1, 1), onset_array.reshape(-1, 1)], axis=1)
+ elif self.args.audio_rep == "mfcc":
+ audio_each_file = librosa.feature.melspectrogram(y=audio_each_file, sr=self.args.audio_sr, n_mels=128, hop_length=int(self.args.audio_sr/self.args.audio_fps))
+ audio_each_file = audio_each_file.transpose(1, 0)
+ # print(audio_each_file.shape, pose_each_file.shape)
+ if self.args.audio_norm and self.args.audio_rep == "wave16k":
+ audio_each_file = (audio_each_file - self.mean_audio) / self.std_audio
+
+ time_offset = 0
+ if self.args.word_rep is not None:
+ logger.info(f"# ---- Building cache for Word {id_pose} and Pose {id_pose} ---- #")
+ word_file = f"{self.data_dir}{self.args.word_rep}/{id_pose}.TextGrid"
+ if not os.path.exists(word_file):
+ logger.warning(f"# ---- file not found for Word {id_pose}, skip all files with the same id ---- #")
+ self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ continue
+ tgrid = tg.TextGrid.fromFile(word_file)
+ if self.args.t_pre_encoder == "bert":
+ from transformers import AutoTokenizer, BertModel
+ tokenizer = AutoTokenizer.from_pretrained(self.args.data_path_1 + "hub/bert-base-uncased", local_files_only=True)
+ model = BertModel.from_pretrained(self.args.data_path_1 + "hub/bert-base-uncased", local_files_only=True).eval()
+ list_word = []
+ all_hidden = []
+ max_len = 400
+ last = 0
+ word_token_mapping = []
+ first = True
+ for i, word in enumerate(tgrid[0]):
+ last = i
+ if (i%max_len != 0) or (i==0):
+ if word.mark == "":
+ list_word.append(".")
+ else:
+ list_word.append(word.mark)
+ else:
+ max_counter = max_len
+ str_word = ' '.join(map(str, list_word))
+ if first:
+ global_len = 0
+ end = -1
+ offset_word = []
+ for k, wordvalue in enumerate(list_word):
+ start = end+1
+ end = start+len(wordvalue)
+ offset_word.append((start, end))
+ #print(offset_word)
+ token_scan = tokenizer.encode_plus(str_word, return_offsets_mapping=True)['offset_mapping']
+ #print(token_scan)
+ for start, end in offset_word:
+ sub_mapping = []
+ for i, (start_t, end_t) in enumerate(token_scan[1:-1]):
+ if int(start) <= int(start_t) and int(end_t) <= int(end):
+ #print(i+global_len)
+ sub_mapping.append(i+global_len)
+ word_token_mapping.append(sub_mapping)
+ #print(len(word_token_mapping))
+ global_len = word_token_mapping[-1][-1] + 1
+ list_word = []
+ if word.mark == "":
+ list_word.append(".")
+ else:
+ list_word.append(word.mark)
+
+ with torch.no_grad():
+ inputs = tokenizer(str_word, return_tensors="pt")
+ outputs = model(**inputs)
+ last_hidden_states = outputs.last_hidden_state.reshape(-1, 768).cpu().numpy()[1:-1, :]
+ all_hidden.append(last_hidden_states)
+
+ #list_word = list_word[:10]
+ if list_word == []:
+ pass
+ else:
+ if first:
+ global_len = 0
+ str_word = ' '.join(map(str, list_word))
+ end = -1
+ offset_word = []
+ for k, wordvalue in enumerate(list_word):
+ start = end+1
+ end = start+len(wordvalue)
+ offset_word.append((start, end))
+ #print(offset_word)
+ token_scan = tokenizer.encode_plus(str_word, return_offsets_mapping=True)['offset_mapping']
+ #print(token_scan)
+ for start, end in offset_word:
+ sub_mapping = []
+ for i, (start_t, end_t) in enumerate(token_scan[1:-1]):
+ if int(start) <= int(start_t) and int(end_t) <= int(end):
+ sub_mapping.append(i+global_len)
+ #print(sub_mapping)
+ word_token_mapping.append(sub_mapping)
+ #print(len(word_token_mapping))
+ with torch.no_grad():
+ inputs = tokenizer(str_word, return_tensors="pt")
+ outputs = model(**inputs)
+ last_hidden_states = outputs.last_hidden_state.reshape(-1, 768).cpu().numpy()[1:-1, :]
+ all_hidden.append(last_hidden_states)
+ last_hidden_states = np.concatenate(all_hidden, axis=0)
+
+ for i in range(pose_each_file.shape[0]):
+ found_flag = False
+ current_time = i/self.args.pose_fps + time_offset
+ j_last = 0
+ for j, word in enumerate(tgrid[0]):
+ word_n, word_s, word_e = word.mark, word.minTime, word.maxTime
+ if word_s<=current_time and current_time<=word_e:
+ if self.args.word_cache and self.args.t_pre_encoder == 'bert':
+ mapping_index = word_token_mapping[j]
+ #print(mapping_index, word_s, word_e)
+ s_t = np.linspace(word_s, word_e, len(mapping_index)+1)
+ #print(s_t)
+ for tt, t_sep in enumerate(s_t[1:]):
+ if current_time <= t_sep:
+ #if len(mapping_index) > 1: print(mapping_index[tt])
+ word_each_file.append(last_hidden_states[mapping_index[tt]])
+ break
+ else:
+ if word_n == " ":
+ word_each_file.append(self.lang_model.PAD_token)
+ else:
+ word_each_file.append(self.lang_model.get_word_index(word_n))
+ found_flag = True
+ j_last = j
+ break
+ else: continue
+ if not found_flag:
+ if self.args.word_cache and self.args.t_pre_encoder == 'bert':
+ word_each_file.append(last_hidden_states[j_last])
+ else:
+ word_each_file.append(self.lang_model.UNK_token)
+ word_each_file = np.array(word_each_file)
+ #print(word_each_file.shape)
+
+ if self.args.emo_rep is not None:
+ logger.info(f"# ---- Building cache for Emo {id_pose} and Pose {id_pose} ---- #")
+ rtype, start = int(id_pose.split('_')[3]), int(id_pose.split('_')[3])
+ if rtype == 0 or rtype == 2 or rtype == 4 or rtype == 6:
+ if start >= 1 and start <= 64:
+ score = 0
+ elif start >= 65 and start <= 72:
+ score = 1
+ elif start >= 73 and start <= 80:
+ score = 2
+ elif start >= 81 and start <= 86:
+ score = 3
+ elif start >= 87 and start <= 94:
+ score = 4
+ elif start >= 95 and start <= 102:
+ score = 5
+ elif start >= 103 and start <= 110:
+ score = 6
+ elif start >= 111 and start <= 118:
+ score = 7
+ else: pass
+ else:
+ # you may denote as unknown in the future
+ score = 0
+ emo_each_file = np.repeat(np.array(score).reshape(1, 1), pose_each_file.shape[0], axis=0)
+ #print(emo_each_file)
+
+ if self.args.sem_rep is not None:
+ logger.info(f"# ---- Building cache for Sem {id_pose} and Pose {id_pose} ---- #")
+ sem_file = f"{self.data_dir}{self.args.sem_rep}/{id_pose}.txt"
+ sem_all = pd.read_csv(sem_file,
+ sep='\t',
+ names=["name", "start_time", "end_time", "duration", "score", "keywords"])
+ # we adopt motion-level semantic score here.
+ for i in range(pose_each_file.shape[0]):
+ found_flag = False
+ for j, (start, end, score) in enumerate(zip(sem_all['start_time'],sem_all['end_time'], sem_all['score'])):
+ current_time = i/self.args.pose_fps + time_offset
+ if start<=current_time and current_time<=end:
+ sem_each_file.append(score)
+ found_flag=True
+ break
+ else: continue
+ if not found_flag: sem_each_file.append(0.)
+ sem_each_file = np.array(sem_each_file)
+ #print(sem_each_file)
+
+ filtered_result = self._sample_from_clip(
+ dst_lmdb_env,
+ audio_each_file, pose_each_file, trans_each_file, shape_each_file, facial_each_file, word_each_file,
+ vid_each_file, emo_each_file, sem_each_file,
+ disable_filtering, clean_first_seconds, clean_final_seconds, is_test,
+ )
+ for type in filtered_result.keys():
+ n_filtered_out[type] += filtered_result[type]
+
+ with dst_lmdb_env.begin() as txn:
+ logger.info(colored(f"no. of samples: {txn.stat()['entries']}", "cyan"))
+ n_total_filtered = 0
+ for type, n_filtered in n_filtered_out.items():
+ logger.info("{}: {}".format(type, n_filtered))
+ n_total_filtered += n_filtered
+ logger.info(colored("no. of excluded samples: {} ({:.1f}%)".format(
+ n_total_filtered, 100 * n_total_filtered / (txn.stat()["entries"] + n_total_filtered)), "cyan"))
+ dst_lmdb_env.sync()
+ dst_lmdb_env.close()
+
+ def _sample_from_clip(
+ self, dst_lmdb_env, audio_each_file, pose_each_file, trans_each_file, shape_each_file, facial_each_file, word_each_file,
+ vid_each_file, emo_each_file, sem_each_file,
+ disable_filtering, clean_first_seconds, clean_final_seconds, is_test,
+ ):
+ """
+ for data cleaning, we ignore the data for first and final n s
+ for test, we return all data
+ """
+ # audio_start = int(self.alignment[0] * self.args.audio_fps)
+ # pose_start = int(self.alignment[1] * self.args.pose_fps)
+ #logger.info(f"before: {audio_each_file.shape} {pose_each_file.shape}")
+ # audio_each_file = audio_each_file[audio_start:]
+ # pose_each_file = pose_each_file[pose_start:]
+ # trans_each_file =
+ #logger.info(f"after alignment: {audio_each_file.shape} {pose_each_file.shape}")
+ #print(pose_each_file.shape)
+ round_seconds_skeleton = pose_each_file.shape[0] // self.args.pose_fps # assume 1500 frames / 15 fps = 100 s
+ #print(round_seconds_skeleton)
+ if audio_each_file != []:
+ if self.args.audio_rep != "wave16k":
+ round_seconds_audio = len(audio_each_file) // self.args.audio_fps # assume 16,000,00 / 16,000 = 100 s
+ elif self.args.audio_rep == "mfcc":
+ round_seconds_audio = audio_each_file.shape[0] // self.args.audio_fps
+ else:
+ round_seconds_audio = audio_each_file.shape[0] // self.args.audio_sr
+ if facial_each_file != []:
+ round_seconds_facial = facial_each_file.shape[0] // self.args.pose_fps
+ logger.info(f"audio: {round_seconds_audio}s, pose: {round_seconds_skeleton}s, facial: {round_seconds_facial}s")
+ round_seconds_skeleton = min(round_seconds_audio, round_seconds_skeleton, round_seconds_facial)
+ max_round = max(round_seconds_audio, round_seconds_skeleton, round_seconds_facial)
+ if round_seconds_skeleton != max_round:
+ logger.warning(f"reduce to {round_seconds_skeleton}s, ignore {max_round-round_seconds_skeleton}s")
+ else:
+ logger.info(f"pose: {round_seconds_skeleton}s, audio: {round_seconds_audio}s")
+ round_seconds_skeleton = min(round_seconds_audio, round_seconds_skeleton)
+ max_round = max(round_seconds_audio, round_seconds_skeleton)
+ if round_seconds_skeleton != max_round:
+ logger.warning(f"reduce to {round_seconds_skeleton}s, ignore {max_round-round_seconds_skeleton}s")
+
+ clip_s_t, clip_e_t = clean_first_seconds, round_seconds_skeleton - clean_final_seconds # assume [10, 90]s
+ clip_s_f_audio, clip_e_f_audio = self.args.audio_fps * clip_s_t, clip_e_t * self.args.audio_fps # [160,000,90*160,000]
+ clip_s_f_pose, clip_e_f_pose = clip_s_t * self.args.pose_fps, clip_e_t * self.args.pose_fps # [150,90*15]
+
+
+ for ratio in self.args.multi_length_training:
+ if is_test:# stride = length for test
+ cut_length = clip_e_f_pose - clip_s_f_pose
+ self.args.stride = cut_length
+ self.max_length = cut_length
+ else:
+ self.args.stride = int(ratio*self.ori_stride)
+ cut_length = int(self.ori_length*ratio)
+
+ num_subdivision = math.floor((clip_e_f_pose - clip_s_f_pose - cut_length) / self.args.stride) + 1
+ logger.info(f"pose from frame {clip_s_f_pose} to {clip_e_f_pose}, length {cut_length}")
+ logger.info(f"{num_subdivision} clips is expected with stride {self.args.stride}")
+
+ if audio_each_file != []:
+ audio_short_length = math.floor(cut_length / self.args.pose_fps * self.args.audio_fps)
+ """
+ for audio sr = 16000, fps = 15, pose_length = 34,
+ audio short length = 36266.7 -> 36266
+ this error is fine.
+ """
+ logger.info(f"audio from frame {clip_s_f_audio} to {clip_e_f_audio}, length {audio_short_length}")
+
+ n_filtered_out = defaultdict(int)
+ sample_pose_list = []
+ sample_audio_list = []
+ sample_facial_list = []
+ sample_shape_list = []
+ sample_word_list = []
+ sample_emo_list = []
+ sample_sem_list = []
+ sample_vid_list = []
+ sample_trans_list = []
+
+ for i in range(num_subdivision): # cut into around 2s chip, (self npose)
+ start_idx = clip_s_f_pose + i * self.args.stride
+ fin_idx = start_idx + cut_length
+ sample_pose = pose_each_file[start_idx:fin_idx]
+
+ sample_trans = trans_each_file[start_idx:fin_idx]
+ sample_shape = shape_each_file[start_idx:fin_idx]
+ # print(sample_pose.shape)
+ if self.args.audio_rep is not None:
+ audio_start = clip_s_f_audio + math.floor(i * self.args.stride * self.args.audio_fps / self.args.pose_fps)
+ audio_end = audio_start + audio_short_length
+ sample_audio = audio_each_file[audio_start:audio_end]
+ else:
+ sample_audio = np.array([-1])
+ sample_facial = facial_each_file[start_idx:fin_idx] if self.args.facial_rep is not None else np.array([-1])
+ sample_word = word_each_file[start_idx:fin_idx] if self.args.word_rep is not None else np.array([-1])
+ sample_emo = emo_each_file[start_idx:fin_idx] if self.args.emo_rep is not None else np.array([-1])
+ sample_sem = sem_each_file[start_idx:fin_idx] if self.args.sem_rep is not None else np.array([-1])
+ sample_vid = vid_each_file[start_idx:fin_idx] if self.args.id_rep is not None else np.array([-1])
+
+ if sample_pose.any() != None:
+ # filtering motion skeleton data
+ sample_pose, filtering_message = MotionPreprocessor(sample_pose).get()
+ is_correct_motion = (sample_pose != [])
+ if is_correct_motion or disable_filtering:
+ sample_pose_list.append(sample_pose)
+ sample_audio_list.append(sample_audio)
+ sample_facial_list.append(sample_facial)
+ sample_shape_list.append(sample_shape)
+ sample_word_list.append(sample_word)
+ sample_vid_list.append(sample_vid)
+ sample_emo_list.append(sample_emo)
+ sample_sem_list.append(sample_sem)
+ sample_trans_list.append(sample_trans)
+ else:
+ n_filtered_out[filtering_message] += 1
+
+ if len(sample_pose_list) > 0:
+ with dst_lmdb_env.begin(write=True) as txn:
+ for pose, audio, facial, shape, word, vid, emo, sem, trans in zip(
+ sample_pose_list,
+ sample_audio_list,
+ sample_facial_list,
+ sample_shape_list,
+ sample_word_list,
+ sample_vid_list,
+ sample_emo_list,
+ sample_sem_list,
+ sample_trans_list,):
+ k = "{:005}".format(self.n_out_samples).encode("ascii")
+ v = [pose, audio, facial, shape, word, emo, sem, vid, trans]
+ v = pyarrow.serialize(v).to_buffer()
+ txn.put(k, v)
+ self.n_out_samples += 1
+ return n_filtered_out
+
+ def __getitem__(self, idx):
+ with self.lmdb_env.begin(write=False) as txn:
+ key = "{:005}".format(idx).encode("ascii")
+ sample = txn.get(key)
+ sample = pyarrow.deserialize(sample)
+ tar_pose, in_audio, in_facial, in_shape, in_word, emo, sem, vid, trans = sample
+ #print(in_shape)
+ #vid = torch.from_numpy(vid).int()
+ emo = torch.from_numpy(emo).int()
+ sem = torch.from_numpy(sem).float()
+ in_audio = torch.from_numpy(in_audio).float()
+ in_word = torch.from_numpy(in_word).float() if self.args.word_cache else torch.from_numpy(in_word).int()
+ if self.loader_type == "test":
+ tar_pose = torch.from_numpy(tar_pose).float()
+ trans = torch.from_numpy(trans).float()
+ in_facial = torch.from_numpy(in_facial).float()
+ vid = torch.from_numpy(vid).float()
+ in_shape = torch.from_numpy(in_shape).float()
+ else:
+ in_shape = torch.from_numpy(in_shape).reshape((in_shape.shape[0], -1)).float()
+ trans = torch.from_numpy(trans).reshape((trans.shape[0], -1)).float()
+ vid = torch.from_numpy(vid).reshape((vid.shape[0], -1)).float()
+ tar_pose = torch.from_numpy(tar_pose).reshape((tar_pose.shape[0], -1)).float()
+ in_facial = torch.from_numpy(in_facial).reshape((in_facial.shape[0], -1)).float()
+ return {"pose":tar_pose, "audio":in_audio, "facial":in_facial, "beta": in_shape, "word":in_word, "id":vid, "emo":emo, "sem":sem, "trans":trans}
+
+
+class MotionPreprocessor:
+ def __init__(self, skeletons):
+ self.skeletons = skeletons
+ #self.mean_pose = mean_pose
+ self.filtering_message = "PASS"
+
+ def get(self):
+ assert (self.skeletons is not None)
+
+ # filtering
+ if self.skeletons != []:
+ if self.check_pose_diff():
+ self.skeletons = []
+ self.filtering_message = "pose"
+ # elif self.check_spine_angle():
+ # self.skeletons = []
+ # self.filtering_message = "spine angle"
+ # elif self.check_static_motion():
+ # self.skeletons = []
+ # self.filtering_message = "motion"
+
+ # if self.skeletons != []:
+ # self.skeletons = self.skeletons.tolist()
+ # for i, frame in enumerate(self.skeletons):
+ # assert not np.isnan(self.skeletons[i]).any() # missing joints
+
+ return self.skeletons, self.filtering_message
+
+ def check_static_motion(self, verbose=True):
+ def get_variance(skeleton, joint_idx):
+ wrist_pos = skeleton[:, joint_idx]
+ variance = np.sum(np.var(wrist_pos, axis=0))
+ return variance
+
+ left_arm_var = get_variance(self.skeletons, 6)
+ right_arm_var = get_variance(self.skeletons, 9)
+
+ th = 0.0014 # exclude 13110
+ # th = 0.002 # exclude 16905
+ if left_arm_var < th and right_arm_var < th:
+ if verbose:
+ print("skip - check_static_motion left var {}, right var {}".format(left_arm_var, right_arm_var))
+ return True
+ else:
+ if verbose:
+ print("pass - check_static_motion left var {}, right var {}".format(left_arm_var, right_arm_var))
+ return False
+
+
+ def check_pose_diff(self, verbose=False):
+# diff = np.abs(self.skeletons - self.mean_pose) # 186*1
+# diff = np.mean(diff)
+
+# # th = 0.017
+# th = 0.02 #0.02 # exclude 3594
+# if diff < th:
+# if verbose:
+# print("skip - check_pose_diff {:.5f}".format(diff))
+# return True
+# # th = 3.5 #0.02 # exclude 3594
+# # if 3.5 < diff < 5:
+# # if verbose:
+# # print("skip - check_pose_diff {:.5f}".format(diff))
+# # return True
+# else:
+# if verbose:
+# print("pass - check_pose_diff {:.5f}".format(diff))
+ return False
+
+
+ def check_spine_angle(self, verbose=True):
+ def angle_between(v1, v2):
+ v1_u = v1 / np.linalg.norm(v1)
+ v2_u = v2 / np.linalg.norm(v2)
+ return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0))
+
+ angles = []
+ for i in range(self.skeletons.shape[0]):
+ spine_vec = self.skeletons[i, 1] - self.skeletons[i, 0]
+ angle = angle_between(spine_vec, [0, -1, 0])
+ angles.append(angle)
+
+ if np.rad2deg(max(angles)) > 30 or np.rad2deg(np.mean(angles)) > 20: # exclude 4495
+ # if np.rad2deg(max(angles)) > 20: # exclude 8270
+ if verbose:
+ print("skip - check_spine_angle {:.5f}, {:.5f}".format(max(angles), np.mean(angles)))
+ return True
+ else:
+ if verbose:
+ print("pass - check_spine_angle {:.5f}".format(max(angles)))
+ return False
\ No newline at end of file
diff --git a/dataloaders/beat_testonly_hf.py b/dataloaders/beat_testonly_hf.py
new file mode 100644
index 0000000000000000000000000000000000000000..17393517d0d6f662114c19b009fa3471d7c1e91b
--- /dev/null
+++ b/dataloaders/beat_testonly_hf.py
@@ -0,0 +1,740 @@
+import os
+import pickle
+import math
+import shutil
+import numpy as np
+import lmdb as lmdb
+import textgrid as tg
+import pandas as pd
+import torch
+import glob
+import json
+from termcolor import colored
+from loguru import logger
+from collections import defaultdict
+from torch.utils.data import Dataset
+import torch.distributed as dist
+import pyarrow
+import librosa
+import smplx
+
+from .build_vocab import Vocab
+from .utils.audio_features import Wav2Vec2Model
+from .data_tools import joints_list
+from .utils import rotation_conversions as rc
+from .utils import other_tools_hf
+
+class CustomDataset(Dataset):
+ def __init__(self, args, loader_type, smplx_path=None, audio_path=None, text_path=None, augmentation=None, kwargs=None, build_cache=True):
+ self.args = args
+ self.loader_type = loader_type
+ self.smplx_path = "./EMAGE/test_sequences/smplxflame_30/2_scott_0_1_1.npz"
+ self.audio_path = audio_path
+ self.text_path = "./EMAGE/test_sequences/textgrid/2_scott_0_1_1.TextGrid"
+ self.rank = 0 # dist.get_rank()
+ self.ori_stride = self.args.stride
+ self.ori_length = self.args.pose_length
+ self.alignment = [0,0] # for trinity
+
+ self.ori_joint_list = joints_list[self.args.ori_joints]
+ self.tar_joint_list = joints_list[self.args.tar_joints]
+ if 'smplx' in self.args.pose_rep:
+ self.joint_mask = np.zeros(len(list(self.ori_joint_list.keys()))*3)
+ self.joints = len(list(self.tar_joint_list.keys()))
+ for joint_name in self.tar_joint_list:
+ self.joint_mask[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ else:
+ self.joints = len(list(self.ori_joint_list.keys()))+1
+ self.joint_mask = np.zeros(self.joints*3)
+ for joint_name in self.tar_joint_list:
+ if joint_name == "Hips":
+ self.joint_mask[3:6] = 1
+ else:
+ self.joint_mask[self.ori_joint_list[joint_name][1] - self.ori_joint_list[joint_name][0]:self.ori_joint_list[joint_name][1]] = 1
+ # select trainable joints
+ self.smplx = smplx.create(
+ self.args.data_path_1+"smplx_models/",
+ model_type='smplx',
+ gender='NEUTRAL_2020',
+ use_face_contour=False,
+ num_betas=300,
+ num_expression_coeffs=100,
+ ext='npz',
+ use_pca=False,
+ ).eval()
+
+ split_rule = pd.read_csv(args.data_path+"test.csv")
+ self.selected_file = split_rule
+ self.data_dir = args.data_path
+
+ if loader_type == "test":
+ self.args.multi_length_training = [1.0]
+ self.max_length = int(args.pose_length * self.args.multi_length_training[-1])
+ self.max_audio_pre_len = math.floor(args.pose_length / args.pose_fps * self.args.audio_sr)
+ if self.max_audio_pre_len > self.args.test_length*self.args.audio_sr:
+ self.max_audio_pre_len = self.args.test_length*self.args.audio_sr
+
+ if args.word_rep is not None:
+ with open(f"{args.data_path}weights/vocab.pkl", 'rb') as f:
+ self.lang_model = pickle.load(f)
+
+ preloaded_dir = self.args.root_path + self.args.cache_path + loader_type + f"/{args.pose_rep}_cache"
+ if build_cache and self.rank == 0:
+ self.build_cache(preloaded_dir)
+ self.lmdb_env = lmdb.open(preloaded_dir, readonly=True, lock=False)
+ with self.lmdb_env.begin() as txn:
+ self.n_samples = txn.stat()["entries"]
+
+
+ def build_cache(self, preloaded_dir):
+ logger.info(f"Audio bit rate: {self.args.audio_fps}")
+ logger.info("Reading data '{}'...".format(self.data_dir))
+ logger.info("Creating the dataset cache...")
+ if self.args.new_cache:
+ if os.path.exists(preloaded_dir):
+ shutil.rmtree(preloaded_dir)
+ if os.path.exists(preloaded_dir):
+ logger.info("Found the cache {}".format(preloaded_dir))
+ elif self.loader_type == "test":
+ self.cache_generation(
+ preloaded_dir, True,
+ 0, 0,
+ is_test=True)
+ else:
+ self.cache_generation(
+ preloaded_dir, self.args.disable_filtering,
+ self.args.clean_first_seconds, self.args.clean_final_seconds,
+ is_test=False)
+
+
+ def __len__(self):
+ return self.n_samples
+
+
+ def cache_generation(self, out_lmdb_dir, disable_filtering, clean_first_seconds, clean_final_seconds, is_test=False):
+ self.n_out_samples = 0
+ # create db for samples
+ if not os.path.exists(out_lmdb_dir): os.makedirs(out_lmdb_dir)
+ if len(self.args.training_speakers) == 1:
+ #dst_lmdb_env = lmdb.open(out_lmdb_dir, map_size= int(1024 ** 3 * 50))# 50G
+ dst_lmdb_env = lmdb.open(out_lmdb_dir, map_size= int(1024 ** 3 * 0.5))# 500M
+ else:
+ dst_lmdb_env = lmdb.open(out_lmdb_dir, map_size= int(1024 ** 3 * 200))# 200G
+ n_filtered_out = defaultdict(int)
+
+ #for index, file_name in self.selected_file.iterrows():
+ #f_name = file_name["id"]
+ ext = ".npz" if "smplx" in self.args.pose_rep else ".bvh"
+ pose_file = self.smplx_path#self.data_dir + self.args.pose_rep + "/" + f_name + ext
+ pose_each_file = []
+ trans_each_file = []
+ shape_each_file = []
+ audio_each_file = []
+ facial_each_file = []
+ word_each_file = []
+ emo_each_file = []
+ sem_each_file = []
+ vid_each_file = []
+ id_pose = "dummy 2nd"#f_name
+
+ logger.info(colored(f"# ---- Building cache for Pose {id_pose} ---- #", "blue"))
+ if "smplx" in self.args.pose_rep:
+ pose_data = np.load(pose_file, allow_pickle=True)
+ assert 30%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 30'
+ stride = int(30/self.args.pose_fps)
+ pose_each_file = pose_data["poses"][::stride]
+ trans_each_file = pose_data["trans"][::stride]
+ shape_each_file = np.repeat(pose_data["betas"].reshape(1, 300), pose_each_file.shape[0], axis=0)
+
+ assert self.args.pose_fps == 30, "should 30"
+ m_data = np.load(pose_file, allow_pickle=True)
+ betas, poses, trans, exps = m_data["betas"], m_data["poses"], m_data["trans"], m_data["expressions"]
+ n, c = poses.shape[0], poses.shape[1]
+ betas = betas.reshape(1, 300)
+ betas = np.tile(betas, (n, 1))
+ betas = torch.from_numpy(betas).float()
+ poses = torch.from_numpy(poses.reshape(n, c)).float()
+ exps = torch.from_numpy(exps.reshape(n, 100)).float()
+ trans = torch.from_numpy(trans.reshape(n, 3)).float()
+ max_length = 128
+ s, r = n//max_length, n%max_length
+ #print(n, s, r)
+ all_tensor = []
+ for i in range(s):
+ with torch.no_grad():
+ joints = self.smplx(
+ betas=betas[i*max_length:(i+1)*max_length],
+ transl=trans[i*max_length:(i+1)*max_length],
+ expression=exps[i*max_length:(i+1)*max_length],
+ jaw_pose=poses[i*max_length:(i+1)*max_length, 66:69],
+ global_orient=poses[i*max_length:(i+1)*max_length,:3],
+ body_pose=poses[i*max_length:(i+1)*max_length,3:21*3+3],
+ left_hand_pose=poses[i*max_length:(i+1)*max_length,25*3:40*3],
+ right_hand_pose=poses[i*max_length:(i+1)*max_length,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=poses[i*max_length:(i+1)*max_length, 69:72],
+ reye_pose=poses[i*max_length:(i+1)*max_length, 72:75],
+ )['joints'][:, (7,8,10,11), :].reshape(max_length, 4, 3).cpu()
+ all_tensor.append(joints)
+ if r != 0:
+ with torch.no_grad():
+ joints = self.smplx(
+ betas=betas[s*max_length:s*max_length+r],
+ transl=trans[s*max_length:s*max_length+r],
+ expression=exps[s*max_length:s*max_length+r],
+ jaw_pose=poses[s*max_length:s*max_length+r, 66:69],
+ global_orient=poses[s*max_length:s*max_length+r,:3],
+ body_pose=poses[s*max_length:s*max_length+r,3:21*3+3],
+ left_hand_pose=poses[s*max_length:s*max_length+r,25*3:40*3],
+ right_hand_pose=poses[s*max_length:s*max_length+r,40*3:55*3],
+ return_verts=True,
+ return_joints=True,
+ leye_pose=poses[s*max_length:s*max_length+r, 69:72],
+ reye_pose=poses[s*max_length:s*max_length+r, 72:75],
+ )['joints'][:, (7,8,10,11), :].reshape(r, 4, 3).cpu()
+ all_tensor.append(joints)
+ joints = torch.cat(all_tensor, axis=0) # all, 4, 3
+ # print(joints.shape)
+ feetv = torch.zeros(joints.shape[1], joints.shape[0])
+ joints = joints.permute(1, 0, 2)
+ #print(joints.shape, feetv.shape)
+ feetv[:, :-1] = (joints[:, 1:] - joints[:, :-1]).norm(dim=-1)
+ #print(feetv.shape)
+ contacts = (feetv < 0.01).numpy().astype(float)
+ # print(contacts.shape, contacts)
+ contacts = contacts.transpose(1, 0)
+ pose_each_file = pose_each_file * self.joint_mask
+ pose_each_file = pose_each_file[:, self.joint_mask.astype(bool)]
+ pose_each_file = np.concatenate([pose_each_file, contacts], axis=1)
+ # print(pose_each_file.shape)
+
+
+ if self.args.facial_rep is not None:
+ logger.info(f"# ---- Building cache for Facial {id_pose} and Pose {id_pose} ---- #")
+ facial_each_file = pose_data["expressions"][::stride]
+ if self.args.facial_norm:
+ facial_each_file = (facial_each_file - self.mean_facial) / self.std_facial
+
+ else:
+ assert 120%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 120'
+ stride = int(120/self.args.pose_fps)
+ with open(pose_file, "r") as pose_data:
+ for j, line in enumerate(pose_data.readlines()):
+ if j < 431: continue
+ if j%stride != 0:continue
+ data = np.fromstring(line, dtype=float, sep=" ")
+ rot_data = rc.euler_angles_to_matrix(torch.from_numpy(np.deg2rad(data)).reshape(-1, self.joints,3), "XYZ")
+ rot_data = rc.matrix_to_axis_angle(rot_data).reshape(-1, self.joints*3)
+ rot_data = rot_data.numpy() * self.joint_mask
+
+ pose_each_file.append(rot_data)
+ trans_each_file.append(data[:3])
+
+ pose_each_file = np.array(pose_each_file)
+ trans_each_file = np.array(trans_each_file)
+ shape_each_file = np.repeat(np.array(-1).reshape(1, 1), pose_each_file.shape[0], axis=0)
+ if self.args.facial_rep is not None:
+ logger.info(f"# ---- Building cache for Facial {id_pose} and Pose {id_pose} ---- #")
+ facial_file = pose_file.replace(self.args.pose_rep, self.args.facial_rep).replace("bvh", "json")
+ assert 60%self.args.pose_fps == 0, 'pose_fps should be an aliquot part of 120'
+ stride = int(60/self.args.pose_fps)
+ if not os.path.exists(facial_file):
+ logger.warning(f"# ---- file not found for Facial {id_pose}, skip all files with the same id ---- #")
+ #self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ #continue
+ with open(facial_file, 'r') as facial_data_file:
+ facial_data = json.load(facial_data_file)
+ for j, frame_data in enumerate(facial_data['frames']):
+ if j%stride != 0:continue
+ facial_each_file.append(frame_data['weights'])
+ facial_each_file = np.array(facial_each_file)
+ if self.args.facial_norm:
+ facial_each_file = (facial_each_file - self.mean_facial) / self.std_facial
+
+ if self.args.id_rep is not None:
+ int_value = 1
+ vid_each_file = np.repeat(np.array(int_value).reshape(1, 1), pose_each_file.shape[0], axis=0)
+
+ if self.args.audio_rep is not None:
+ logger.info(f"# ---- Building cache for Audio {id_pose} and Pose {id_pose} ---- #")
+ audio_file = self.audio_path[1]#pose_file.replace(self.args.pose_rep, 'wave16k').replace(ext, ".wav")
+ sr = self.audio_path[0]
+ print(sr)
+ #if not os.path.exists(audio_file):
+ # logger.warning(f"# ---- file not found for Audio {id_pose}, skip all files with the same id ---- #")
+ #self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ #continue
+ #audio_each_file, sr = librosa.load(audio_file)
+ audio_each_file = audio_file.astype(np.float32)
+ print(audio_each_file.shape)
+ audio_each_file = librosa.resample(audio_each_file, orig_sr=sr, target_sr=self.args.audio_sr)
+ print(audio_each_file.shape)
+ if self.args.audio_rep == "onset+amplitude":
+ from numpy.lib import stride_tricks
+ frame_length = 1024
+ # hop_length = 512
+ shape = (audio_each_file.shape[-1] - frame_length + 1, frame_length)
+ strides = (audio_each_file.strides[-1], audio_each_file.strides[-1])
+ rolling_view = stride_tricks.as_strided(audio_each_file, shape=shape, strides=strides)
+ amplitude_envelope = np.max(np.abs(rolling_view), axis=1)
+ # pad the last frame_length-1 samples
+ amplitude_envelope = np.pad(amplitude_envelope, (0, frame_length-1), mode='constant', constant_values=amplitude_envelope[-1])
+ audio_onset_f = librosa.onset.onset_detect(y=audio_each_file, sr=self.args.audio_sr, units='frames')
+ onset_array = np.zeros(len(audio_each_file), dtype=float)
+ onset_array[audio_onset_f] = 1.0
+ # print(amplitude_envelope.shape, audio_each_file.shape, onset_array.shape)
+ audio_each_file = np.concatenate([amplitude_envelope.reshape(-1, 1), onset_array.reshape(-1, 1)], axis=1)
+ elif self.args.audio_rep == "mfcc":
+ audio_each_file = librosa.feature.melspectrogram(y=audio_each_file, sr=self.args.audio_sr, n_mels=128, hop_length=int(self.args.audio_sr/self.args.audio_fps))
+ audio_each_file = audio_each_file.transpose(1, 0)
+ # print(audio_each_file.shape, pose_each_file.shape)
+ if self.args.audio_norm and self.args.audio_rep == "wave16k":
+ audio_each_file = (audio_each_file - self.mean_audio) / self.std_audio
+
+ time_offset = 0
+ if self.args.word_rep is not None:
+ logger.info(f"# ---- Building cache for Word {id_pose} and Pose {id_pose} ---- #")
+ word_file = self.text_path#f"{self.data_dir}{self.args.word_rep}/{id_pose}.TextGrid"
+ if not os.path.exists(word_file):
+ logger.warning(f"# ---- file not found for Word {id_pose}, skip all files with the same id ---- #")
+ #self.selected_file = self.selected_file.drop(self.selected_file[self.selected_file['id'] == id_pose].index)
+ #continue
+ tgrid = tg.TextGrid.fromFile(word_file)
+ if self.args.t_pre_encoder == "bert":
+ from transformers import AutoTokenizer, BertModel
+ tokenizer = AutoTokenizer.from_pretrained(self.args.data_path_1 + "hub/bert-base-uncased", local_files_only=True)
+ model = BertModel.from_pretrained(self.args.data_path_1 + "hub/bert-base-uncased", local_files_only=True).eval()
+ list_word = []
+ all_hidden = []
+ max_len = 400
+ last = 0
+ word_token_mapping = []
+ first = True
+ for i, word in enumerate(tgrid[0]):
+ last = i
+ if (i%max_len != 0) or (i==0):
+ if word.mark == "":
+ list_word.append(".")
+ else:
+ list_word.append(word.mark)
+ else:
+ max_counter = max_len
+ str_word = ' '.join(map(str, list_word))
+ if first:
+ global_len = 0
+ end = -1
+ offset_word = []
+ for k, wordvalue in enumerate(list_word):
+ start = end+1
+ end = start+len(wordvalue)
+ offset_word.append((start, end))
+ #print(offset_word)
+ token_scan = tokenizer.encode_plus(str_word, return_offsets_mapping=True)['offset_mapping']
+ #print(token_scan)
+ for start, end in offset_word:
+ sub_mapping = []
+ for i, (start_t, end_t) in enumerate(token_scan[1:-1]):
+ if int(start) <= int(start_t) and int(end_t) <= int(end):
+ #print(i+global_len)
+ sub_mapping.append(i+global_len)
+ word_token_mapping.append(sub_mapping)
+ #print(len(word_token_mapping))
+ global_len = word_token_mapping[-1][-1] + 1
+ list_word = []
+ if word.mark == "":
+ list_word.append(".")
+ else:
+ list_word.append(word.mark)
+
+ with torch.no_grad():
+ inputs = tokenizer(str_word, return_tensors="pt")
+ outputs = model(**inputs)
+ last_hidden_states = outputs.last_hidden_state.reshape(-1, 768).cpu().numpy()[1:-1, :]
+ all_hidden.append(last_hidden_states)
+
+ #list_word = list_word[:10]
+ if list_word == []:
+ pass
+ else:
+ if first:
+ global_len = 0
+ str_word = ' '.join(map(str, list_word))
+ end = -1
+ offset_word = []
+ for k, wordvalue in enumerate(list_word):
+ start = end+1
+ end = start+len(wordvalue)
+ offset_word.append((start, end))
+ #print(offset_word)
+ token_scan = tokenizer.encode_plus(str_word, return_offsets_mapping=True)['offset_mapping']
+ #print(token_scan)
+ for start, end in offset_word:
+ sub_mapping = []
+ for i, (start_t, end_t) in enumerate(token_scan[1:-1]):
+ if int(start) <= int(start_t) and int(end_t) <= int(end):
+ sub_mapping.append(i+global_len)
+ #print(sub_mapping)
+ word_token_mapping.append(sub_mapping)
+ #print(len(word_token_mapping))
+ with torch.no_grad():
+ inputs = tokenizer(str_word, return_tensors="pt")
+ outputs = model(**inputs)
+ last_hidden_states = outputs.last_hidden_state.reshape(-1, 768).cpu().numpy()[1:-1, :]
+ all_hidden.append(last_hidden_states)
+ last_hidden_states = np.concatenate(all_hidden, axis=0)
+
+ for i in range(pose_each_file.shape[0]):
+ found_flag = False
+ current_time = i/self.args.pose_fps + time_offset
+ j_last = 0
+ for j, word in enumerate(tgrid[0]):
+ word_n, word_s, word_e = word.mark, word.minTime, word.maxTime
+ if word_s<=current_time and current_time<=word_e:
+ if self.args.word_cache and self.args.t_pre_encoder == 'bert':
+ mapping_index = word_token_mapping[j]
+ #print(mapping_index, word_s, word_e)
+ s_t = np.linspace(word_s, word_e, len(mapping_index)+1)
+ #print(s_t)
+ for tt, t_sep in enumerate(s_t[1:]):
+ if current_time <= t_sep:
+ #if len(mapping_index) > 1: print(mapping_index[tt])
+ word_each_file.append(last_hidden_states[mapping_index[tt]])
+ break
+ else:
+ if word_n == " ":
+ word_each_file.append(self.lang_model.PAD_token)
+ else:
+ word_each_file.append(self.lang_model.get_word_index(word_n))
+ found_flag = True
+ j_last = j
+ break
+ else: continue
+ if not found_flag:
+ if self.args.word_cache and self.args.t_pre_encoder == 'bert':
+ word_each_file.append(last_hidden_states[j_last])
+ else:
+ word_each_file.append(self.lang_model.UNK_token)
+ word_each_file = np.array(word_each_file)
+ #print(word_each_file.shape)
+
+ if self.args.emo_rep is not None:
+ logger.info(f"# ---- Building cache for Emo {id_pose} and Pose {id_pose} ---- #")
+ rtype, start = int(id_pose.split('_')[3]), int(id_pose.split('_')[3])
+ if rtype == 0 or rtype == 2 or rtype == 4 or rtype == 6:
+ if start >= 1 and start <= 64:
+ score = 0
+ elif start >= 65 and start <= 72:
+ score = 1
+ elif start >= 73 and start <= 80:
+ score = 2
+ elif start >= 81 and start <= 86:
+ score = 3
+ elif start >= 87 and start <= 94:
+ score = 4
+ elif start >= 95 and start <= 102:
+ score = 5
+ elif start >= 103 and start <= 110:
+ score = 6
+ elif start >= 111 and start <= 118:
+ score = 7
+ else: pass
+ else:
+ # you may denote as unknown in the future
+ score = 0
+ emo_each_file = np.repeat(np.array(score).reshape(1, 1), pose_each_file.shape[0], axis=0)
+ #print(emo_each_file)
+
+ if self.args.sem_rep is not None:
+ logger.info(f"# ---- Building cache for Sem {id_pose} and Pose {id_pose} ---- #")
+ sem_file = f"{self.data_dir}{self.args.sem_rep}/{id_pose}.txt"
+ sem_all = pd.read_csv(sem_file,
+ sep='\t',
+ names=["name", "start_time", "end_time", "duration", "score", "keywords"])
+ # we adopt motion-level semantic score here.
+ for i in range(pose_each_file.shape[0]):
+ found_flag = False
+ for j, (start, end, score) in enumerate(zip(sem_all['start_time'],sem_all['end_time'], sem_all['score'])):
+ current_time = i/self.args.pose_fps + time_offset
+ if start<=current_time and current_time<=end:
+ sem_each_file.append(score)
+ found_flag=True
+ break
+ else: continue
+ if not found_flag: sem_each_file.append(0.)
+ sem_each_file = np.array(sem_each_file)
+ #print(sem_each_file)
+
+ filtered_result = self._sample_from_clip(
+ dst_lmdb_env,
+ audio_each_file, pose_each_file, trans_each_file, shape_each_file, facial_each_file, word_each_file,
+ vid_each_file, emo_each_file, sem_each_file,
+ disable_filtering, clean_first_seconds, clean_final_seconds, is_test,
+ )
+ for type in filtered_result.keys():
+ n_filtered_out[type] += filtered_result[type]
+
+ with dst_lmdb_env.begin() as txn:
+ logger.info(colored(f"no. of samples: {txn.stat()['entries']}", "cyan"))
+ n_total_filtered = 0
+ for type, n_filtered in n_filtered_out.items():
+ logger.info("{}: {}".format(type, n_filtered))
+ n_total_filtered += n_filtered
+ logger.info(colored("no. of excluded samples: {} ({:.1f}%)".format(
+ n_total_filtered, 100 * n_total_filtered / (txn.stat()["entries"] + n_total_filtered)), "cyan"))
+ dst_lmdb_env.sync()
+ dst_lmdb_env.close()
+
+ def _sample_from_clip(
+ self, dst_lmdb_env, audio_each_file, pose_each_file, trans_each_file, shape_each_file, facial_each_file, word_each_file,
+ vid_each_file, emo_each_file, sem_each_file,
+ disable_filtering, clean_first_seconds, clean_final_seconds, is_test,
+ ):
+ """
+ for data cleaning, we ignore the data for first and final n s
+ for test, we return all data
+ """
+ # audio_start = int(self.alignment[0] * self.args.audio_fps)
+ # pose_start = int(self.alignment[1] * self.args.pose_fps)
+ #logger.info(f"before: {audio_each_file.shape} {pose_each_file.shape}")
+ # audio_each_file = audio_each_file[audio_start:]
+ # pose_each_file = pose_each_file[pose_start:]
+ # trans_each_file =
+ #logger.info(f"after alignment: {audio_each_file.shape} {pose_each_file.shape}")
+ #print(pose_each_file.shape)
+ round_seconds_skeleton = pose_each_file.shape[0] // self.args.pose_fps # assume 1500 frames / 15 fps = 100 s
+ print(pose_each_file.shape[0])
+ #print(round_seconds_skeleton)
+ #if audio_each_file != []:
+ if self.args.audio_rep != "wave16k":
+ round_seconds_audio = len(audio_each_file) // self.args.audio_fps # assume 16,000,00 / 16,000 = 100 s
+ elif self.args.audio_rep == "mfcc":
+ round_seconds_audio = audio_each_file.shape[0] // self.args.audio_fps
+ else:
+ round_seconds_audio = audio_each_file.shape[0] // self.args.audio_sr
+ # if facial_each_file != []:
+ round_seconds_facial = facial_each_file.shape[0] // self.args.pose_fps
+ logger.info(f"audio: {round_seconds_audio}s, pose: {round_seconds_skeleton}s, facial: {round_seconds_facial}s")
+ round_seconds_skeleton = min(round_seconds_audio, round_seconds_skeleton, round_seconds_facial)
+ max_round = max(round_seconds_audio, round_seconds_skeleton, round_seconds_facial)
+ if round_seconds_skeleton != max_round:
+ logger.warning(f"reduce to {round_seconds_skeleton}s, ignore {max_round-round_seconds_skeleton}s")
+ # else:
+ # logger.info(f"pose: {round_seconds_skeleton}s, audio: {round_seconds_audio}s")
+ # round_seconds_skeleton = min(round_seconds_audio, round_seconds_skeleton)
+ # max_round = max(round_seconds_audio, round_seconds_skeleton)
+ # if round_seconds_skeleton != max_round:
+ # logger.warning(f"reduce to {round_seconds_skeleton}s, ignore {max_round-round_seconds_skeleton}s")
+
+ clip_s_t, clip_e_t = clean_first_seconds, round_seconds_skeleton - clean_final_seconds # assume [10, 90]s
+ clip_s_f_audio, clip_e_f_audio = self.args.audio_fps * clip_s_t, clip_e_t * self.args.audio_fps # [160,000,90*160,000]
+ clip_s_f_pose, clip_e_f_pose = clip_s_t * self.args.pose_fps, clip_e_t * self.args.pose_fps # [150,90*15]
+
+
+ for ratio in self.args.multi_length_training:
+ if is_test:# stride = length for test
+ cut_length = clip_e_f_pose - clip_s_f_pose
+ self.args.stride = cut_length
+ self.max_length = cut_length
+ else:
+ self.args.stride = int(ratio*self.ori_stride)
+ cut_length = int(self.ori_length*ratio)
+
+ num_subdivision = math.floor((clip_e_f_pose - clip_s_f_pose - cut_length) / self.args.stride) + 1
+ logger.info(f"pose from frame {clip_s_f_pose} to {clip_e_f_pose}, length {cut_length}")
+ logger.info(f"{num_subdivision} clips is expected with stride {self.args.stride}")
+
+ # if audio_each_file != []:
+ audio_short_length = math.floor(cut_length / self.args.pose_fps * self.args.audio_fps)
+ logger.info(f"audio from frame {clip_s_f_audio} to {clip_e_f_audio}, length {audio_short_length}")
+
+ n_filtered_out = defaultdict(int)
+ sample_pose_list = []
+ sample_audio_list = []
+ sample_facial_list = []
+ sample_shape_list = []
+ sample_word_list = []
+ sample_emo_list = []
+ sample_sem_list = []
+ sample_vid_list = []
+ sample_trans_list = []
+
+ for i in range(num_subdivision): # cut into around 2s chip, (self npose)
+ start_idx = clip_s_f_pose + i * self.args.stride
+ fin_idx = start_idx + cut_length
+ sample_pose = pose_each_file[start_idx:fin_idx]
+
+ sample_trans = trans_each_file[start_idx:fin_idx]
+ sample_shape = shape_each_file[start_idx:fin_idx]
+ # print(sample_pose.shape)
+ if self.args.audio_rep is not None:
+ audio_start = clip_s_f_audio + math.floor(i * self.args.stride * self.args.audio_fps / self.args.pose_fps)
+ audio_end = audio_start + audio_short_length
+ sample_audio = audio_each_file[audio_start:audio_end]
+ else:
+ sample_audio = np.array([-1])
+ sample_facial = facial_each_file[start_idx:fin_idx] if self.args.facial_rep is not None else np.array([-1])
+ sample_word = word_each_file[start_idx:fin_idx] if self.args.word_rep is not None else np.array([-1])
+ sample_emo = emo_each_file[start_idx:fin_idx] if self.args.emo_rep is not None else np.array([-1])
+ sample_sem = sem_each_file[start_idx:fin_idx] if self.args.sem_rep is not None else np.array([-1])
+ sample_vid = vid_each_file[start_idx:fin_idx] if self.args.id_rep is not None else np.array([-1])
+
+ if sample_pose.any() != None:
+ # filtering motion skeleton data
+ sample_pose, filtering_message = MotionPreprocessor(sample_pose).get()
+ is_correct_motion = True #(sample_pose != [])
+ if is_correct_motion or disable_filtering:
+ sample_pose_list.append(sample_pose)
+ sample_audio_list.append(sample_audio)
+ sample_facial_list.append(sample_facial)
+ sample_shape_list.append(sample_shape)
+ sample_word_list.append(sample_word)
+ sample_vid_list.append(sample_vid)
+ sample_emo_list.append(sample_emo)
+ sample_sem_list.append(sample_sem)
+ sample_trans_list.append(sample_trans)
+ else:
+ n_filtered_out[filtering_message] += 1
+
+ if len(sample_pose_list) > 0:
+ with dst_lmdb_env.begin(write=True) as txn:
+ for pose, audio, facial, shape, word, vid, emo, sem, trans in zip(
+ sample_pose_list,
+ sample_audio_list,
+ sample_facial_list,
+ sample_shape_list,
+ sample_word_list,
+ sample_vid_list,
+ sample_emo_list,
+ sample_sem_list,
+ sample_trans_list,):
+ k = "{:005}".format(self.n_out_samples).encode("ascii")
+ v = [pose, audio, facial, shape, word, emo, sem, vid, trans]
+ # v = pyarrow.serialize(v).to_buffer()
+ # txn.put(k, v)
+ # self.n_out_samples += 1
+ v = pickle.dumps(v)
+ txn.put(k, v)
+ self.n_out_samples += 1
+ return n_filtered_out
+
+ def __getitem__(self, idx):
+ with self.lmdb_env.begin(write=False) as txn:
+ key = "{:005}".format(idx).encode("ascii")
+ sample = txn.get(key)
+ # sample = pyarrow.deserialize(sample)
+ if sample is not None:
+ sample = pickle.loads(sample)
+ tar_pose, in_audio, in_facial, in_shape, in_word, emo, sem, vid, trans = sample
+ #print(in_shape)
+ #vid = torch.from_numpy(vid).int()
+ emo = torch.from_numpy(emo).int()
+ sem = torch.from_numpy(sem).float()
+ in_audio = torch.from_numpy(in_audio).float()
+ in_word = torch.from_numpy(in_word).float() if self.args.word_cache else torch.from_numpy(in_word).int()
+ if self.loader_type == "test":
+ tar_pose = torch.from_numpy(tar_pose).float()
+ trans = torch.from_numpy(trans).float()
+ in_facial = torch.from_numpy(in_facial).float()
+ vid = torch.from_numpy(vid).float()
+ in_shape = torch.from_numpy(in_shape).float()
+ else:
+ in_shape = torch.from_numpy(in_shape).reshape((in_shape.shape[0], -1)).float()
+ trans = torch.from_numpy(trans).reshape((trans.shape[0], -1)).float()
+ vid = torch.from_numpy(vid).reshape((vid.shape[0], -1)).float()
+ tar_pose = torch.from_numpy(tar_pose).reshape((tar_pose.shape[0], -1)).float()
+ in_facial = torch.from_numpy(in_facial).reshape((in_facial.shape[0], -1)).float()
+ return {"pose":tar_pose, "audio":in_audio, "facial":in_facial, "beta": in_shape, "word":in_word, "id":vid, "emo":emo, "sem":sem, "trans":trans}
+
+
+class MotionPreprocessor:
+ def __init__(self, skeletons):
+ self.skeletons = skeletons
+ #self.mean_pose = mean_pose
+ self.filtering_message = "PASS"
+
+ def get(self):
+ assert (self.skeletons is not None)
+
+ # filtering
+ # if self.skeletons != []:
+ # if self.check_pose_diff():
+ # self.skeletons = []
+ # self.filtering_message = "pose"
+ # elif self.check_spine_angle():
+ # self.skeletons = []
+ # self.filtering_message = "spine angle"
+ # elif self.check_static_motion():
+ # self.skeletons = []
+ # self.filtering_message = "motion"
+
+ # if self.skeletons != []:
+ # self.skeletons = self.skeletons.tolist()
+ # for i, frame in enumerate(self.skeletons):
+ # assert not np.isnan(self.skeletons[i]).any() # missing joints
+
+ return self.skeletons, self.filtering_message
+
+ def check_static_motion(self, verbose=True):
+ def get_variance(skeleton, joint_idx):
+ wrist_pos = skeleton[:, joint_idx]
+ variance = np.sum(np.var(wrist_pos, axis=0))
+ return variance
+
+ left_arm_var = get_variance(self.skeletons, 6)
+ right_arm_var = get_variance(self.skeletons, 9)
+
+ th = 0.0014 # exclude 13110
+ # th = 0.002 # exclude 16905
+ if left_arm_var < th and right_arm_var < th:
+ if verbose:
+ print("skip - check_static_motion left var {}, right var {}".format(left_arm_var, right_arm_var))
+ return True
+ else:
+ if verbose:
+ print("pass - check_static_motion left var {}, right var {}".format(left_arm_var, right_arm_var))
+ return False
+
+
+ def check_pose_diff(self, verbose=False):
+# diff = np.abs(self.skeletons - self.mean_pose) # 186*1
+# diff = np.mean(diff)
+
+# # th = 0.017
+# th = 0.02 #0.02 # exclude 3594
+# if diff < th:
+# if verbose:
+# print("skip - check_pose_diff {:.5f}".format(diff))
+# return True
+# # th = 3.5 #0.02 # exclude 3594
+# # if 3.5 < diff < 5:
+# # if verbose:
+# # print("skip - check_pose_diff {:.5f}".format(diff))
+# # return True
+# else:
+# if verbose:
+# print("pass - check_pose_diff {:.5f}".format(diff))
+ return False
+
+
+ def check_spine_angle(self, verbose=True):
+ def angle_between(v1, v2):
+ v1_u = v1 / np.linalg.norm(v1)
+ v2_u = v2 / np.linalg.norm(v2)
+ return np.arccos(np.clip(np.dot(v1_u, v2_u), -1.0, 1.0))
+
+ angles = []
+ for i in range(self.skeletons.shape[0]):
+ spine_vec = self.skeletons[i, 1] - self.skeletons[i, 0]
+ angle = angle_between(spine_vec, [0, -1, 0])
+ angles.append(angle)
+
+ if np.rad2deg(max(angles)) > 30 or np.rad2deg(np.mean(angles)) > 20: # exclude 4495
+ # if np.rad2deg(max(angles)) > 20: # exclude 8270
+ if verbose:
+ print("skip - check_spine_angle {:.5f}, {:.5f}".format(max(angles), np.mean(angles)))
+ return True
+ else:
+ if verbose:
+ print("pass - check_spine_angle {:.5f}".format(max(angles)))
+ return False
\ No newline at end of file
diff --git a/dataloaders/build_vocab.py b/dataloaders/build_vocab.py
new file mode 100644
index 0000000000000000000000000000000000000000..649204d0d502eaf671e40d2bbb08ca324e5e02f3
--- /dev/null
+++ b/dataloaders/build_vocab.py
@@ -0,0 +1,199 @@
+import numpy as np
+import glob
+import os
+import pickle
+import lmdb
+import pyarrow
+import fasttext
+from loguru import logger
+from scipy import linalg
+
+
+class Vocab:
+ PAD_token = 0
+ SOS_token = 1
+ EOS_token = 2
+ UNK_token = 3
+
+ def __init__(self, name, insert_default_tokens=True):
+ self.name = name
+ self.trimmed = False
+ self.word_embedding_weights = None
+ self.reset_dictionary(insert_default_tokens)
+
+ def reset_dictionary(self, insert_default_tokens=True):
+ self.word2index = {}
+ self.word2count = {}
+ if insert_default_tokens:
+ self.index2word = {self.PAD_token: "", self.SOS_token: "",
+ self.EOS_token: "", self.UNK_token: ""}
+ else:
+ self.index2word = {self.UNK_token: ""}
+ self.n_words = len(self.index2word) # count default tokens
+
+ def index_word(self, word):
+ if word not in self.word2index:
+ self.word2index[word] = self.n_words
+ self.word2count[word] = 1
+ self.index2word[self.n_words] = word
+ self.n_words += 1
+ else:
+ self.word2count[word] += 1
+
+ def add_vocab(self, other_vocab):
+ for word, _ in other_vocab.word2count.items():
+ self.index_word(word)
+
+ # remove words below a certain count threshold
+ def trim(self, min_count):
+ if self.trimmed:
+ return
+ self.trimmed = True
+
+ keep_words = []
+
+ for k, v in self.word2count.items():
+ if v >= min_count:
+ keep_words.append(k)
+
+ print(' word trimming, kept %s / %s = %.4f' % (
+ len(keep_words), len(self.word2index), len(keep_words) / len(self.word2index)
+ ))
+
+ # reinitialize dictionary
+ self.reset_dictionary()
+ for word in keep_words:
+ self.index_word(word)
+
+ def get_word_index(self, word):
+ if word in self.word2index:
+ return self.word2index[word]
+ else:
+ return self.UNK_token
+
+ def load_word_vectors(self, pretrained_path, embedding_dim=300):
+ print(" loading word vectors from '{}'...".format(pretrained_path))
+
+ # initialize embeddings to random values for special words
+ init_sd = 1 / np.sqrt(embedding_dim)
+ weights = np.random.normal(0, scale=init_sd, size=[self.n_words, embedding_dim])
+ weights = weights.astype(np.float32)
+
+ # read word vectors
+ word_model = fasttext.load_model(pretrained_path)
+ for word, id in self.word2index.items():
+ vec = word_model.get_word_vector(word)
+ weights[id] = vec
+ self.word_embedding_weights = weights
+
+ def __get_embedding_weight(self, pretrained_path, embedding_dim=300):
+ """ function modified from http://ronny.rest/blog/post_2017_08_04_glove/ """
+ print("Loading word embedding '{}'...".format(pretrained_path))
+ cache_path = pretrained_path
+ weights = None
+
+ # use cached file if it exists
+ if os.path.exists(cache_path): #
+ with open(cache_path, 'rb') as f:
+ print(' using cached result from {}'.format(cache_path))
+ weights = pickle.load(f)
+ if weights.shape != (self.n_words, embedding_dim):
+ logging.warning(' failed to load word embedding weights. reinitializing...')
+ weights = None
+
+ if weights is None:
+ # initialize embeddings to random values for special and OOV words
+ init_sd = 1 / np.sqrt(embedding_dim)
+ weights = np.random.normal(0, scale=init_sd, size=[self.n_words, embedding_dim])
+ weights = weights.astype(np.float32)
+
+ with open(pretrained_path, encoding="utf-8", mode="r") as textFile:
+ num_embedded_words = 0
+ for line_raw in textFile:
+ # extract the word, and embeddings vector
+ line = line_raw.split()
+ try:
+ word, vector = (line[0], np.array(line[1:], dtype=np.float32))
+ # if word == 'love': # debugging
+ # print(word, vector)
+
+ # if it is in our vocab, then update the corresponding weights
+ id = self.word2index.get(word, None)
+ if id is not None:
+ weights[id] = vector
+ num_embedded_words += 1
+ except ValueError:
+ print(' parsing error at {}...'.format(line_raw[:50]))
+ continue
+ print(' {} / {} word vectors are found in the embedding'.format(num_embedded_words, len(self.word2index)))
+
+ with open(cache_path, 'wb') as f:
+ pickle.dump(weights, f)
+ return weights
+
+
+def build_vocab(name, data_path, cache_path, word_vec_path=None, feat_dim=None):
+ print(' building a language model...')
+ #if not os.path.exists(cache_path):
+ lang_model = Vocab(name)
+ print(' indexing words from {}'.format(data_path))
+ index_words_from_textgrid(lang_model, data_path)
+
+ if word_vec_path is not None:
+ lang_model.load_word_vectors(word_vec_path, feat_dim)
+ else:
+ print(' loaded from {}'.format(cache_path))
+ with open(cache_path, 'rb') as f:
+ lang_model = pickle.load(f)
+ if word_vec_path is None:
+ lang_model.word_embedding_weights = None
+ elif lang_model.word_embedding_weights.shape[0] != lang_model.n_words:
+ logging.warning(' failed to load word embedding weights. check this')
+ assert False
+
+ with open(cache_path, 'wb') as f:
+ pickle.dump(lang_model, f)
+
+
+ return lang_model
+
+
+def index_words(lang_model, data_path):
+ #index words form text
+ with open(data_path, "r") as f:
+ for line in f.readlines():
+ line = line.replace(",", " ")
+ line = line.replace(".", " ")
+ line = line.replace("?", " ")
+ line = line.replace("!", " ")
+ for word in line.split():
+ lang_model.index_word(word)
+ print(' indexed %d words' % lang_model.n_words)
+
+def index_words_from_textgrid(lang_model, data_path):
+ import textgrid as tg
+ from tqdm import tqdm
+ #trainvaltest=os.listdir(data_path)
+ # for loadtype in trainvaltest:
+ # if "." in loadtype: continue #ignore .ipynb_checkpoints
+ texts = os.listdir(data_path+"/textgrid/")
+ #print(texts)
+ for textfile in tqdm(texts):
+ tgrid = tg.TextGrid.fromFile(data_path+"/textgrid/"+textfile)
+ for word in tgrid[0]:
+ word_n, word_s, word_e = word.mark, word.minTime, word.maxTime
+ word_n = word_n.replace(",", " ")
+ word_n = word_n.replace(".", " ")
+ word_n = word_n.replace("?", " ")
+ word_n = word_n.replace("!", " ")
+ #print(word_n)
+ lang_model.index_word(word_n)
+ print(' indexed %d words' % lang_model.n_words)
+ print(lang_model.word2index, lang_model.word2count)
+
+if __name__ == "__main__":
+ # 11195 for all, 5793 for 4 speakers
+ # build_vocab("beat_english_15_141", "/home/ma-user/work/datasets/beat_cache/beat_english_15_141/", "/home/ma-user/work/datasets/beat_cache/beat_english_15_141/vocab.pkl", "/home/ma-user/work/datasets/cc.en.300.bin", 300)
+ build_vocab("beat_chinese_v1.0.0", "/data/datasets/beat_chinese_v1.0.0/", "/data/datasets/beat_chinese_v1.0.0/weights/vocab.pkl", "/home/ma-user/work/cc.zh.300.bin", 300)
+
+
\ No newline at end of file
diff --git a/dataloaders/data_tools.py b/dataloaders/data_tools.py
new file mode 100644
index 0000000000000000000000000000000000000000..f7388daf0f9ed7620ba98ccf964d30dc901a7737
--- /dev/null
+++ b/dataloaders/data_tools.py
@@ -0,0 +1,1756 @@
+import numpy as np
+import glob
+import os
+import pickle
+import lmdb
+import pyarrow
+import fasttext
+from loguru import logger
+from scipy import linalg
+from .pymo.parsers import BVHParser
+from .pymo.viz_tools import *
+from .pymo.preprocessing import *
+
+
+
+
+# pose version fpsxx_trinity/japanese_joints(_xxx)
+joints_list = {
+ "trinity_joints":{
+ 'Hips': [6,6],
+ 'Spine': [3,9],
+ 'Spine1': [3,12],
+ 'Spine2': [3,15],
+ 'Spine3': [3,18],
+ 'Neck': [3,21],
+ 'Neck1': [3,24],
+ 'Head': [3,27],
+ 'RShoulder': [3,30],
+ 'RArm': [3,33],
+ 'RArm1': [3,36],
+ 'RHand': [3,39],
+ 'RHandT1': [3,42],
+ 'RHandT2': [3,45],
+ 'RHandT3': [3,48],
+ 'RHandI1': [3,51],
+ 'RHandI2': [3,54],
+ 'RHandI3': [3,57],
+ 'RHandM1': [3,60],
+ 'RHandM2': [3,63],
+ 'RHandM3': [3,66],
+ 'RHandR1': [3,69],
+ 'RHandR2': [3,72],
+ 'RHandR3': [3,75],
+ 'RHandP1': [3,78],
+ 'RHandP2': [3,81],
+ 'RHandP3': [3,84],
+ 'LShoulder': [3,87],
+ 'LArm': [3,90],
+ 'LArm1': [3,93],
+ 'LHand': [3,96],
+ 'LHandT1': [3,99],
+ 'LHandT2': [3,102],
+ 'LHandT3': [3,105],
+ 'LHandI1': [3,108],
+ 'LHandI2': [3,111],
+ 'LHandI3': [3,114],
+ 'LHandM1': [3,117],
+ 'LHandM2': [3,120],
+ 'LHandM3': [3,123],
+ 'LHandR1': [3,126],
+ 'LHandR2': [3,129],
+ 'LHandR3': [3,132],
+ 'LHandP1': [3,135],
+ 'LHandP2': [3,138],
+ 'LHandP3': [3,141],
+ 'RUpLeg': [3,144],
+ 'RLeg': [3,147],
+ 'RFoot': [3,150],
+ 'RFootF': [3,153],
+ 'RToeBase': [3,156],
+ 'LUpLeg': [3,159],
+ 'LLeg': [3,162],
+ 'LFoot': [3,165],
+ 'LFootF': [3,168],
+ 'LToeBase': [3,171],},
+ "trinity_joints_123":{
+ 'Spine': 3 ,
+ 'Neck': 3 ,
+ 'Neck1': 3 ,
+ 'RShoulder': 3 ,
+ 'RArm': 3 ,
+ 'RArm1': 3 ,
+ 'RHand': 3 ,
+ 'RHandT1': 3 ,
+ 'RHandT2': 3 ,
+ 'RHandT3': 3 ,
+ 'RHandI1': 3 ,
+ 'RHandI2': 3 ,
+ 'RHandI3': 3 ,
+ 'RHandM1': 3 ,
+ 'RHandM2': 3 ,
+ 'RHandM3': 3 ,
+ 'RHandR1': 3 ,
+ 'RHandR2': 3 ,
+ 'RHandR3': 3 ,
+ 'RHandP1': 3 ,
+ 'RHandP2': 3 ,
+ 'RHandP3': 3 ,
+ 'LShoulder': 3 ,
+ 'LArm': 3 ,
+ 'LArm1': 3 ,
+ 'LHand': 3 ,
+ 'LHandT1': 3 ,
+ 'LHandT2': 3 ,
+ 'LHandT3': 3 ,
+ 'LHandI1': 3 ,
+ 'LHandI2': 3 ,
+ 'LHandI3': 3 ,
+ 'LHandM1': 3 ,
+ 'LHandM2': 3 ,
+ 'LHandM3': 3 ,
+ 'LHandR1': 3 ,
+ 'LHandR2': 3 ,
+ 'LHandR3': 3 ,
+ 'LHandP1': 3 ,
+ 'LHandP2': 3 ,
+ 'LHandP3': 3 ,},
+ "trinity_joints_168":{
+ 'Hips': 3 ,
+ 'Spine': 3 ,
+ 'Spine1': 3 ,
+ 'Spine2': 3 ,
+ 'Spine3': 3 ,
+ 'Neck': 3 ,
+ 'Neck1': 3 ,
+ 'Head': 3 ,
+ 'RShoulder': 3 ,
+ 'RArm': 3 ,
+ 'RArm1': 3 ,
+ 'RHand': 3 ,
+ 'RHandT1': 3 ,
+ 'RHandT2': 3 ,
+ 'RHandT3': 3 ,
+ 'RHandI1': 3 ,
+ 'RHandI2': 3 ,
+ 'RHandI3': 3 ,
+ 'RHandM1': 3 ,
+ 'RHandM2': 3 ,
+ 'RHandM3': 3 ,
+ 'RHandR1': 3 ,
+ 'RHandR2': 3 ,
+ 'RHandR3': 3 ,
+ 'RHandP1': 3 ,
+ 'RHandP2': 3 ,
+ 'RHandP3': 3 ,
+ 'LShoulder': 3 ,
+ 'LArm': 3 ,
+ 'LArm1': 3 ,
+ 'LHand': 3 ,
+ 'LHandT1': 3 ,
+ 'LHandT2': 3 ,
+ 'LHandT3': 3 ,
+ 'LHandI1': 3 ,
+ 'LHandI2': 3 ,
+ 'LHandI3': 3 ,
+ 'LHandM1': 3 ,
+ 'LHandM2': 3 ,
+ 'LHandM3': 3 ,
+ 'LHandR1': 3 ,
+ 'LHandR2': 3 ,
+ 'LHandR3': 3 ,
+ 'LHandP1': 3 ,
+ 'LHandP2': 3 ,
+ 'LHandP3': 3 ,
+ 'RUpLeg': 3 ,
+ 'RLeg': 3 ,
+ 'RFoot': 3 ,
+ 'RFootF': 3 ,
+ 'RToeBase': 3 ,
+ 'LUpLeg': 3 ,
+ 'LLeg': 3 ,
+ 'LFoot': 3 ,
+ 'LFootF': 3 ,
+ 'LToeBase': 3 ,},
+ "trinity_joints_138":{
+ "Hips": 3 ,
+ 'Spine': 3 ,
+ 'Spine1': 3 ,
+ 'Spine2': 3 ,
+ 'Spine3': 3 ,
+ 'Neck': 3 ,
+ 'Neck1': 3 ,
+ 'Head': 3 ,
+ 'RShoulder': 3 ,
+ 'RArm': 3 ,
+ 'RArm1': 3 ,
+ 'RHand': 3 ,
+ 'RHandT1': 3 ,
+ 'RHandT2': 3 ,
+ 'RHandT3': 3 ,
+ 'RHandI1': 3 ,
+ 'RHandI2': 3 ,
+ 'RHandI3': 3 ,
+ 'RHandM1': 3 ,
+ 'RHandM2': 3 ,
+ 'RHandM3': 3 ,
+ 'RHandR1': 3 ,
+ 'RHandR2': 3 ,
+ 'RHandR3': 3 ,
+ 'RHandP1': 3 ,
+ 'RHandP2': 3 ,
+ 'RHandP3': 3 ,
+ 'LShoulder': 3 ,
+ 'LArm': 3 ,
+ 'LArm1': 3 ,
+ 'LHand': 3 ,
+ 'LHandT1': 3 ,
+ 'LHandT2': 3 ,
+ 'LHandT3': 3 ,
+ 'LHandI1': 3 ,
+ 'LHandI2': 3 ,
+ 'LHandI3': 3 ,
+ 'LHandM1': 3 ,
+ 'LHandM2': 3 ,
+ 'LHandM3': 3 ,
+ 'LHandR1': 3 ,
+ 'LHandR2': 3 ,
+ 'LHandR3': 3 ,
+ 'LHandP1': 3 ,
+ 'LHandP2': 3 ,
+ 'LHandP3': 3 ,},
+ "beat_smplx_joints": {
+ 'pelvis': [3,3],
+ 'left_hip': [3,6],
+ 'right_hip': [3,9],
+ 'spine1': [3,12],
+ 'left_knee': [3,15],
+ 'right_knee': [3,18],
+ 'spine2': [3,21],
+ 'left_ankle': [3,24],
+ 'right_ankle': [3,27],
+
+ 'spine3': [3,30],
+ 'left_foot': [3,33],
+ 'right_foot': [3,36],
+ 'neck': [3,39],
+ 'left_collar': [3,42],
+ 'right_collar': [3,45],
+ 'head': [3,48],
+ 'left_shoulder': [3,51],
+
+ 'right_shoulder': [3,54],
+ 'left_elbow': [3,57],
+ 'right_elbow': [3,60],
+ 'left_wrist': [3,63],
+ 'right_wrist': [3,66],
+
+ 'jaw': [3,69],
+ 'left_eye_smplhf': [3,72],
+ 'right_eye_smplhf': [3,75],
+ 'left_index1': [3,78],
+ 'left_index2': [3,81],
+
+ 'left_index3': [3,84],
+ 'left_middle1': [3,87],
+ 'left_middle2': [3,90],
+ 'left_middle3': [3,93],
+ 'left_pinky1': [3,96],
+
+ 'left_pinky2': [3,99],
+ 'left_pinky3': [3,102],
+ 'left_ring1': [3,105],
+ 'left_ring2': [3,108],
+
+ 'left_ring3': [3,111],
+ 'left_thumb1': [3,114],
+ 'left_thumb2': [3,117],
+ 'left_thumb3': [3,120],
+ 'right_index1': [3,123],
+ 'right_index2': [3,126],
+ 'right_index3': [3,129],
+ 'right_middle1': [3,132],
+
+ 'right_middle2': [3,135],
+ 'right_middle3': [3,138],
+ 'right_pinky1': [3,141],
+ 'right_pinky2': [3,144],
+ 'right_pinky3': [3,147],
+
+ 'right_ring1': [3,150],
+ 'right_ring2': [3,153],
+ 'right_ring3': [3,156],
+ 'right_thumb1': [3,159],
+ 'right_thumb2': [3,162],
+ 'right_thumb3': [3,165],
+
+# 'nose': [3,168],
+# 'right_eye': [3,171],
+# 'left_eye': [3,174],
+# 'right_ear': [3,177],
+
+# 'left_ear': [3,180],
+# 'left_big_toe': [3,183],
+# 'left_small_toe': [3,186],
+# 'left_heel': [3,189],
+
+# 'right_big_toe': [3,192],
+# 'right_small_toe': [3,195],
+# 'right_heel': [3,198],
+# 'left_thumb': [3,201],
+# 'left_index': [3,204],
+# 'left_middle': [3,207],
+
+# 'left_ring': [3,210],
+# 'left_pinky': [3,213],
+# 'right_thumb': [3,216],
+# 'right_index': [3,219],
+# 'right_middle': [3,222],
+# 'right_ring': [3,225],
+
+# 'right_pinky': [3,228],
+# 'right_eye_brow1': [3,231],
+# 'right_eye_brow2': [3,234],
+# 'right_eye_brow3': [3,237],
+
+# 'right_eye_brow4': [3,240],
+# 'right_eye_brow5': [3,243],
+# 'left_eye_brow5': [3,246],
+# 'left_eye_brow4': [3,249],
+
+# 'left_eye_brow3': [3,252],
+# 'left_eye_brow2': [3,255],
+# 'left_eye_brow1': [3,258],
+# 'nose1': [3,261],
+# 'nose2': [3,264],
+# 'nose3': [3,267],
+
+# 'nose4': [3,270],
+# 'right_nose_2': [3,273],
+# 'right_nose_1': [3,276],
+# 'nose_middle': [3,279],
+# 'left_nose_1': [3,282],
+# 'left_nose_2': [3,285],
+
+# 'right_eye1': [3,288],
+# 'right_eye2': [3,291],
+# 'right_eye3': [3,294],
+# 'right_eye4': [3,297],
+
+# 'right_eye5': [3,300],
+# 'right_eye6': [3,303],
+# 'left_eye4': [3,306],
+# 'left_eye3': [3,309],
+
+# 'left_eye2': [3,312],
+# 'left_eye1': [3,315],
+# 'left_eye6': [3,318],
+# 'left_eye5': [3,321],
+# 'right_mouth_1': [3,324],
+# 'right_mouth_2': [3,327],
+# 'right_mouth_3': [3,330],
+# 'mouth_top': [3,333],
+# 'left_mouth_3': [3,336],
+# 'left_mouth_2': [3,339],
+# 'left_mouth_1': [3,342],
+# 'left_mouth_5': [3,345],
+# 'left_mouth_4': [3,348],
+# 'mouth_bottom': [3,351],
+# 'right_mouth_4': [3,354],
+# 'right_mouth_5': [3,357],
+# 'right_lip_1': [3,360],
+# 'right_lip_2': [3,363],
+# 'lip_top': [3,366],
+# 'left_lip_2': [3,369],
+
+# 'left_lip_1': [3,372],
+# 'left_lip_3': [3,375],
+# 'lip_bottom': [3,378],
+# 'right_lip_3': [3,381],
+# 'right_contour_1': [3,384],
+# 'right_contour_2': [3,387],
+# 'right_contour_3': [3,390],
+# 'right_contour_4': [3,393],
+# 'right_contour_5': [3,396],
+# 'right_contour_6': [3,399],
+# 'right_contour_7': [3,402],
+# 'right_contour_8': [3,405],
+# 'contour_middle': [3,408],
+# 'left_contour_8': [3,411],
+# 'left_contour_7': [3,414],
+# 'left_contour_6': [3,417],
+# 'left_contour_5': [3,420],
+# 'left_contour_4': [3,423],
+# 'left_contour_3': [3,426],
+# 'left_contour_2': [3,429],
+# 'left_contour_1': [3,432],
+ },
+
+ "beat_smplx_no_eyes": {
+ "pelvis":3,
+ "left_hip":3,
+ "right_hip":3,
+ "spine1":3,
+ "left_knee":3,
+ "right_knee":3,
+ "spine2":3,
+ "left_ankle":3,
+ "right_ankle":3,
+ "spine3":3,
+ "left_foot":3,
+ "right_foot":3,
+ "neck":3,
+ "left_collar":3,
+ "right_collar":3,
+ "head":3,
+ "left_shoulder":3,
+ "right_shoulder":3,
+ "left_elbow":3,
+ "right_elbow":3,
+ "left_wrist":3,
+ "right_wrist":3,
+ "jaw":3,
+ # "left_eye_smplhf":3,
+ # "right_eye_smplhf":3,
+ "left_index1":3,
+ "left_index2":3,
+ "left_index3":3,
+ "left_middle1":3,
+ "left_middle2":3,
+ "left_middle3":3,
+ "left_pinky1":3,
+ "left_pinky2":3,
+ "left_pinky3":3,
+ "left_ring1":3,
+ "left_ring2":3,
+ "left_ring3":3,
+ "left_thumb1":3,
+ "left_thumb2":3,
+ "left_thumb3":3,
+ "right_index1":3,
+ "right_index2":3,
+ "right_index3":3,
+ "right_middle1":3,
+ "right_middle2":3,
+ "right_middle3":3,
+ "right_pinky1":3,
+ "right_pinky2":3,
+ "right_pinky3":3,
+ "right_ring1":3,
+ "right_ring2":3,
+ "right_ring3":3,
+ "right_thumb1":3,
+ "right_thumb2":3,
+ "right_thumb3":3,
+ },
+
+ "beat_smplx_full": {
+ "pelvis":3,
+ "left_hip":3,
+ "right_hip":3,
+ "spine1":3,
+ "left_knee":3,
+ "right_knee":3,
+ "spine2":3,
+ "left_ankle":3,
+ "right_ankle":3,
+ "spine3":3,
+ "left_foot":3,
+ "right_foot":3,
+ "neck":3,
+ "left_collar":3,
+ "right_collar":3,
+ "head":3,
+ "left_shoulder":3,
+ "right_shoulder":3,
+ "left_elbow":3,
+ "right_elbow":3,
+ "left_wrist":3,
+ "right_wrist":3,
+ "jaw":3,
+ "left_eye_smplhf":3,
+ "right_eye_smplhf":3,
+ "left_index1":3,
+ "left_index2":3,
+ "left_index3":3,
+ "left_middle1":3,
+ "left_middle2":3,
+ "left_middle3":3,
+ "left_pinky1":3,
+ "left_pinky2":3,
+ "left_pinky3":3,
+ "left_ring1":3,
+ "left_ring2":3,
+ "left_ring3":3,
+ "left_thumb1":3,
+ "left_thumb2":3,
+ "left_thumb3":3,
+ "right_index1":3,
+ "right_index2":3,
+ "right_index3":3,
+ "right_middle1":3,
+ "right_middle2":3,
+ "right_middle3":3,
+ "right_pinky1":3,
+ "right_pinky2":3,
+ "right_pinky3":3,
+ "right_ring1":3,
+ "right_ring2":3,
+ "right_ring3":3,
+ "right_thumb1":3,
+ "right_thumb2":3,
+ "right_thumb3":3,
+ },
+
+ "beat_smplx_upall": {
+ # "pelvis":3,
+ # "left_hip":3,
+ # "right_hip":3,
+ "spine1":3,
+ # "left_knee":3,
+ # "right_knee":3,
+ "spine2":3,
+ # "left_ankle":3,
+ # "right_ankle":3,
+ "spine3":3,
+ # "left_foot":3,
+ # "right_foot":3,
+ "neck":3,
+ "left_collar":3,
+ "right_collar":3,
+ "head":3,
+ "left_shoulder":3,
+ "right_shoulder":3,
+ "left_elbow":3,
+ "right_elbow":3,
+ "left_wrist":3,
+ "right_wrist":3,
+ # "jaw":3,
+ # "left_eye_smplhf":3,
+ # "right_eye_smplhf":3,
+ "left_index1":3,
+ "left_index2":3,
+ "left_index3":3,
+ "left_middle1":3,
+ "left_middle2":3,
+ "left_middle3":3,
+ "left_pinky1":3,
+ "left_pinky2":3,
+ "left_pinky3":3,
+ "left_ring1":3,
+ "left_ring2":3,
+ "left_ring3":3,
+ "left_thumb1":3,
+ "left_thumb2":3,
+ "left_thumb3":3,
+ "right_index1":3,
+ "right_index2":3,
+ "right_index3":3,
+ "right_middle1":3,
+ "right_middle2":3,
+ "right_middle3":3,
+ "right_pinky1":3,
+ "right_pinky2":3,
+ "right_pinky3":3,
+ "right_ring1":3,
+ "right_ring2":3,
+ "right_ring3":3,
+ "right_thumb1":3,
+ "right_thumb2":3,
+ "right_thumb3":3,
+ },
+
+ "beat_smplx_upper": {
+ #"pelvis":3,
+ # "left_hip":3,
+ # "right_hip":3,
+ "spine1":3,
+ # "left_knee":3,
+ # "right_knee":3,
+ "spine2":3,
+ # "left_ankle":3,
+ # "right_ankle":3,
+ "spine3":3,
+ # "left_foot":3,
+ # "right_foot":3,
+ "neck":3,
+ "left_collar":3,
+ "right_collar":3,
+ "head":3,
+ "left_shoulder":3,
+ "right_shoulder":3,
+ "left_elbow":3,
+ "right_elbow":3,
+ "left_wrist":3,
+ "right_wrist":3,
+ # "jaw":3,
+ # "left_eye_smplhf":3,
+ # "right_eye_smplhf":3,
+ # "left_index1":3,
+ # "left_index2":3,
+ # "left_index3":3,
+ # "left_middle1":3,
+ # "left_middle2":3,
+ # "left_middle3":3,
+ # "left_pinky1":3,
+ # "left_pinky2":3,
+ # "left_pinky3":3,
+ # "left_ring1":3,
+ # "left_ring2":3,
+ # "left_ring3":3,
+ # "left_thumb1":3,
+ # "left_thumb2":3,
+ # "left_thumb3":3,
+ # "right_index1":3,
+ # "right_index2":3,
+ # "right_index3":3,
+ # "right_middle1":3,
+ # "right_middle2":3,
+ # "right_middle3":3,
+ # "right_pinky1":3,
+ # "right_pinky2":3,
+ # "right_pinky3":3,
+ # "right_ring1":3,
+ # "right_ring2":3,
+ # "right_ring3":3,
+ # "right_thumb1":3,
+ # "right_thumb2":3,
+ # "right_thumb3":3,
+ },
+
+ "beat_smplx_hands": {
+ #"pelvis":3,
+ # "left_hip":3,
+ # "right_hip":3,
+ # "spine1":3,
+ # "left_knee":3,
+ # "right_knee":3,
+ # "spine2":3,
+ # "left_ankle":3,
+ # "right_ankle":3,
+ # "spine3":3,
+ # "left_foot":3,
+ # "right_foot":3,
+ # "neck":3,
+ # "left_collar":3,
+ # "right_collar":3,
+ # "head":3,
+ # "left_shoulder":3,
+ # "right_shoulder":3,
+ # "left_elbow":3,
+ # "right_elbow":3,
+ # "left_wrist":3,
+ # "right_wrist":3,
+ # "jaw":3,
+ # "left_eye_smplhf":3,
+ # "right_eye_smplhf":3,
+ "left_index1":3,
+ "left_index2":3,
+ "left_index3":3,
+ "left_middle1":3,
+ "left_middle2":3,
+ "left_middle3":3,
+ "left_pinky1":3,
+ "left_pinky2":3,
+ "left_pinky3":3,
+ "left_ring1":3,
+ "left_ring2":3,
+ "left_ring3":3,
+ "left_thumb1":3,
+ "left_thumb2":3,
+ "left_thumb3":3,
+ "right_index1":3,
+ "right_index2":3,
+ "right_index3":3,
+ "right_middle1":3,
+ "right_middle2":3,
+ "right_middle3":3,
+ "right_pinky1":3,
+ "right_pinky2":3,
+ "right_pinky3":3,
+ "right_ring1":3,
+ "right_ring2":3,
+ "right_ring3":3,
+ "right_thumb1":3,
+ "right_thumb2":3,
+ "right_thumb3":3,
+ },
+
+ "beat_smplx_lower": {
+ "pelvis":3,
+ "left_hip":3,
+ "right_hip":3,
+ # "spine1":3,
+ "left_knee":3,
+ "right_knee":3,
+ # "spine2":3,
+ "left_ankle":3,
+ "right_ankle":3,
+ # "spine3":3,
+ "left_foot":3,
+ "right_foot":3,
+ # "neck":3,
+ # "left_collar":3,
+ # "right_collar":3,
+ # "head":3,
+ # "left_shoulder":3,
+ # "right_shoulder":3,
+ # "left_elbow":3,
+ # "right_elbow":3,
+ # "left_wrist":3,
+ # "right_wrist":3,
+ # "jaw":3,
+ # "left_eye_smplhf":3,
+ # "right_eye_smplhf":3,
+ # "left_index1":3,
+ # "left_index2":3,
+ # "left_index3":3,
+ # "left_middle1":3,
+ # "left_middle2":3,
+ # "left_middle3":3,
+ # "left_pinky1":3,
+ # "left_pinky2":3,
+ # "left_pinky3":3,
+ # "left_ring1":3,
+ # "left_ring2":3,
+ # "left_ring3":3,
+ # "left_thumb1":3,
+ # "left_thumb2":3,
+ # "left_thumb3":3,
+ # "right_index1":3,
+ # "right_index2":3,
+ # "right_index3":3,
+ # "right_middle1":3,
+ # "right_middle2":3,
+ # "right_middle3":3,
+ # "right_pinky1":3,
+ # "right_pinky2":3,
+ # "right_pinky3":3,
+ # "right_ring1":3,
+ # "right_ring2":3,
+ # "right_ring3":3,
+ # "right_thumb1":3,
+ # "right_thumb2":3,
+ # "right_thumb3":3,
+ },
+
+ "beat_smplx_face": {
+ # "pelvis":3,
+ # "left_hip":3,
+ # "right_hip":3,
+ # # "spine1":3,
+ # "left_knee":3,
+ # "right_knee":3,
+ # # "spine2":3,
+ # "left_ankle":3,
+ # "right_ankle":3,
+ # # "spine3":3,
+ # "left_foot":3,
+ # "right_foot":3,
+ # "neck":3,
+ # "left_collar":3,
+ # "right_collar":3,
+ # "head":3,
+ # "left_shoulder":3,
+ # "right_shoulder":3,
+ # "left_elbow":3,
+ # "right_elbow":3,
+ # "left_wrist":3,
+ # "right_wrist":3,
+ "jaw":3,
+ # "left_eye_smplhf":3,
+ # "right_eye_smplhf":3,
+ # "left_index1":3,
+ # "left_index2":3,
+ # "left_index3":3,
+ # "left_middle1":3,
+ # "left_middle2":3,
+ # "left_middle3":3,
+ # "left_pinky1":3,
+ # "left_pinky2":3,
+ # "left_pinky3":3,
+ # "left_ring1":3,
+ # "left_ring2":3,
+ # "left_ring3":3,
+ # "left_thumb1":3,
+ # "left_thumb2":3,
+ # "left_thumb3":3,
+ # "right_index1":3,
+ # "right_index2":3,
+ # "right_index3":3,
+ # "right_middle1":3,
+ # "right_middle2":3,
+ # "right_middle3":3,
+ # "right_pinky1":3,
+ # "right_pinky2":3,
+ # "right_pinky3":3,
+ # "right_ring1":3,
+ # "right_ring2":3,
+ # "right_ring3":3,
+ # "right_thumb1":3,
+ # "right_thumb2":3,
+ # "right_thumb3":3,
+ },
+
+ "beat_joints": {
+ 'Hips': [6,6],
+ 'Spine': [3,9],
+ 'Spine1': [3,12],
+ 'Spine2': [3,15],
+ 'Spine3': [3,18],
+ 'Neck': [3,21],
+ 'Neck1': [3,24],
+ 'Head': [3,27],
+ 'HeadEnd': [3,30],
+
+ 'RShoulder': [3,33],
+ 'RArm': [3,36],
+ 'RArm1': [3,39],
+ 'RHand': [3,42],
+ 'RHandM1': [3,45],
+ 'RHandM2': [3,48],
+ 'RHandM3': [3,51],
+ 'RHandM4': [3,54],
+
+ 'RHandR': [3,57],
+ 'RHandR1': [3,60],
+ 'RHandR2': [3,63],
+ 'RHandR3': [3,66],
+ 'RHandR4': [3,69],
+
+ 'RHandP': [3,72],
+ 'RHandP1': [3,75],
+ 'RHandP2': [3,78],
+ 'RHandP3': [3,81],
+ 'RHandP4': [3,84],
+
+ 'RHandI': [3,87],
+ 'RHandI1': [3,90],
+ 'RHandI2': [3,93],
+ 'RHandI3': [3,96],
+ 'RHandI4': [3,99],
+
+ 'RHandT1': [3,102],
+ 'RHandT2': [3,105],
+ 'RHandT3': [3,108],
+ 'RHandT4': [3,111],
+
+ 'LShoulder': [3,114],
+ 'LArm': [3,117],
+ 'LArm1': [3,120],
+ 'LHand': [3,123],
+ 'LHandM1': [3,126],
+ 'LHandM2': [3,129],
+ 'LHandM3': [3,132],
+ 'LHandM4': [3,135],
+
+ 'LHandR': [3,138],
+ 'LHandR1': [3,141],
+ 'LHandR2': [3,144],
+ 'LHandR3': [3,147],
+ 'LHandR4': [3,150],
+
+ 'LHandP': [3,153],
+ 'LHandP1': [3,156],
+ 'LHandP2': [3,159],
+ 'LHandP3': [3,162],
+ 'LHandP4': [3,165],
+
+ 'LHandI': [3,168],
+ 'LHandI1': [3,171],
+ 'LHandI2': [3,174],
+ 'LHandI3': [3,177],
+ 'LHandI4': [3,180],
+
+ 'LHandT1': [3,183],
+ 'LHandT2': [3,186],
+ 'LHandT3': [3,189],
+ 'LHandT4': [3,192],
+
+ 'RUpLeg': [3,195],
+ 'RLeg': [3,198],
+ 'RFoot': [3,201],
+ 'RFootF': [3,204],
+ 'RToeBase': [3,207],
+ 'RToeBaseEnd': [3,210],
+
+ 'LUpLeg': [3,213],
+ 'LLeg': [3,216],
+ 'LFoot': [3,219],
+ 'LFootF': [3,222],
+ 'LToeBase': [3,225],
+ 'LToeBaseEnd': [3,228],},
+
+ "beat_full":{
+ 'Hips': 3,
+ 'Spine': 3 ,
+ 'Spine1': 3 ,
+ 'Spine2': 3 ,
+ 'Spine3': 3 ,
+ 'Neck': 3 ,
+ 'Neck1': 3 ,
+ 'Head' : 3,
+ 'HeadEnd' : 3,
+ 'RShoulder': 3 ,
+ 'RArm': 3 ,
+ 'RArm1': 3 ,
+ 'RHand': 3 ,
+ 'RHandM1': 3 ,
+ 'RHandM2': 3 ,
+ 'RHandM3': 3 ,
+ 'RHandM4': 3 ,
+ 'RHandR': 3 ,
+ 'RHandR1': 3 ,
+ 'RHandR2': 3 ,
+ 'RHandR3': 3 ,
+ 'RHandR4': 3 ,
+ 'RHandP': 3 ,
+ 'RHandP1': 3 ,
+ 'RHandP2': 3 ,
+ 'RHandP3': 3 ,
+ 'RHandP4': 3 ,
+ 'RHandI': 3 ,
+ 'RHandI1': 3 ,
+ 'RHandI2': 3 ,
+ 'RHandI3': 3 ,
+ 'RHandI4': 3 ,
+ 'RHandT1': 3 ,
+ 'RHandT2': 3 ,
+ 'RHandT3': 3 ,
+ 'RHandT4': 3 ,
+ 'LShoulder': 3 ,
+ 'LArm': 3 ,
+ 'LArm1': 3 ,
+ 'LHand': 3 ,
+ 'LHandM1': 3 ,
+ 'LHandM2': 3 ,
+ 'LHandM3': 3 ,
+ 'LHandM4': 3 ,
+ 'LHandR': 3 ,
+ 'LHandR1': 3 ,
+ 'LHandR2': 3 ,
+ 'LHandR3': 3 ,
+ 'LHandR4': 3 ,
+ 'LHandP': 3 ,
+ 'LHandP1': 3 ,
+ 'LHandP2': 3 ,
+ 'LHandP3': 3 ,
+ 'LHandP4': 3 ,
+ 'LHandI': 3 ,
+ 'LHandI1': 3 ,
+ 'LHandI2': 3 ,
+ 'LHandI3': 3 ,
+ 'LHandI4': 3 ,
+ 'LHandT1': 3 ,
+ 'LHandT2': 3 ,
+ 'LHandT3': 3 ,
+ 'LHandT4': 3 ,
+ 'RUpLeg': 3,
+ 'RLeg': 3,
+ 'RFoot': 3,
+ 'RFootF': 3,
+ 'RToeBase': 3,
+ 'RToeBaseEnd': 3,
+ 'LUpLeg': 3,
+ 'LLeg': 3,
+ 'LFoot': 3,
+ 'LFootF': 3,
+ 'LToeBase': 3,
+ 'LToeBaseEnd': 3,
+ },
+
+ "japanese_joints":{
+ 'Hips': [6,6],
+ 'Spine': [6,12],
+ 'Spine1': [6,18],
+ 'Spine2': [6,24],
+ 'Spine3': [6,30],
+ 'Neck': [6,36],
+ 'Neck1': [6,42],
+ 'Head': [6,48],
+ 'RShoulder': [6,54],
+ 'RArm': [6,60],
+ 'RArm1': [6,66],
+ 'RHand': [6,72],
+ 'RHandM1': [6,78],
+ 'RHandM2': [6,84],
+ 'RHandM3': [6,90],
+ 'RHandR': [6,96],
+ 'RHandR1': [6,102],
+ 'RHandR2': [6,108],
+ 'RHandR3': [6,114],
+ 'RHandP': [6,120],
+ 'RHandP1': [6,126],
+ 'RHandP2': [6,132],
+ 'RHandP3': [6,138],
+ 'RHandI': [6,144],
+ 'RHandI1': [6,150],
+ 'RHandI2': [6,156],
+ 'RHandI3': [6,162],
+ 'RHandT1': [6,168],
+ 'RHandT2': [6,174],
+ 'RHandT3': [6,180],
+ 'LShoulder': [6,186],
+ 'LArm': [6,192],
+ 'LArm1': [6,198],
+ 'LHand': [6,204],
+ 'LHandM1': [6,210],
+ 'LHandM2': [6,216],
+ 'LHandM3': [6,222],
+ 'LHandR': [6,228],
+ 'LHandR1': [6,234],
+ 'LHandR2': [6,240],
+ 'LHandR3': [6,246],
+ 'LHandP': [6,252],
+ 'LHandP1': [6,258],
+ 'LHandP2': [6,264],
+ 'LHandP3': [6,270],
+ 'LHandI': [6,276],
+ 'LHandI1': [6,282],
+ 'LHandI2': [6,288],
+ 'LHandI3': [6,294],
+ 'LHandT1': [6,300],
+ 'LHandT2': [6,306],
+ 'LHandT3': [6,312],
+ 'RUpLeg': [6,318],
+ 'RLeg': [6,324],
+ 'RFoot': [6,330],
+ 'RFootF': [6,336],
+ 'RToeBase': [6,342],
+ 'LUpLeg': [6,348],
+ 'LLeg': [6,354],
+ 'LFoot': [6,360],
+ 'LFootF': [6,366],
+ 'LToeBase': [6,372],},
+
+ "yostar":{
+ 'Hips': [6,6],
+ 'Spine': [3,9],
+ 'Spine1': [3,12],
+ 'Bone040': [3,15],
+ 'Bone041': [3,18],
+
+ 'Bone034': [3,21],
+ 'Bone035': [3,24],
+ 'Bone036': [3,27],
+ 'Bone037': [3,30],
+ 'Bone038': [3,33],
+ 'Bone039': [3,36],
+
+ 'RibbonL1': [3,39],
+ 'RibbonL1_end': [3,42],
+
+ 'Chest': [3,45],
+ 'L_eri': [3,48],
+ 'R_eri': [3,51],
+ 'Neck': [3,54],
+ 'Head': [3,57],
+ 'Head_end': [3,60],
+
+ 'RBackHair_1': [3,63],
+ 'RBackHair_2': [3,66],
+ 'RBackHair_3': [3,69],
+ 'RBackHair_4': [3,72],
+ 'RBackHair_end': [3,75],
+
+ 'RFrontHair': [3,78],
+ 'CFrontHair_1': [3,81],
+ 'CFrontHair_2': [3,84],
+ 'CFrontHair_3': [3,87],
+ 'CFrontHair_emd': [3,90],
+
+ 'LFrontHair_1': [3,93],
+ 'LFrontHair_2': [3,96],
+ 'LFrontHair_3': [3,99],
+
+ 'LBackHair_1': [3,102],
+ 'LBackHair_2': [3,105],
+ 'LBackHair_3': [3,108],
+ 'LBackHair_4': [3,111],
+ 'LBackHair_end': [3,114],
+
+ 'LSideHair_1': [3,117],
+ 'LSideHair_2': [3,120],
+ 'LSideHair_3': [3,123],
+ 'LSideHair_4': [3,126],
+ 'LSideHair_5': [3,129],
+ 'LSideHair_6': [3,132],
+ 'LSideHair_7': [3,135],
+ 'LSideHair_end': [3,138],
+
+ 'CBackHair_1': [3,141],
+ 'CBackHair_2': [3,144],
+ 'CBackHair_3': [3,147],
+ 'CBackHair_4': [3,150],
+ 'CBackHair_end': [3,153],
+
+ 'RSideHair_1': [3,156],
+ 'RSideHair_2': [3,159],
+ 'RSideHair_3': [3,162],
+ 'RSideHair_4': [3,165],
+
+ 'RibbonR_1': [3,168],
+ 'RibbonR_2': [3,171],
+ 'RibbonR_3': [3,174],
+
+ 'RibbonL_1': [3,177],
+ 'RibbonL_2': [3,180],
+ 'RibbonL_3': [3,183],
+
+ 'LeftEye': [3,186],
+ 'LeftEye_end': [3,189],
+ 'RightEye': [3,192],
+ 'RightEye_end': [3,195],
+
+ 'LeftShoulder': [3,198],
+ 'LeftArm': [3,201],
+ 'LeftForearm': [3,204],
+ 'LeftHand': [3,207],
+ 'LeftHandThumb1': [3,210],
+ 'LeftHandThumb2': [3,213],
+ 'LeftHandThumb3': [3,216],
+ 'LeftHandThumb_end': [3,219],
+
+ 'LeftHandIndex1': [3,222],
+ 'LeftHandIndex2': [3,225],
+ 'LeftHandIndex3': [3,228],
+ 'LeftHandIndex_end': [3,231],
+
+ 'LeftHandMiddle1': [3,234],
+ 'LeftHandMiddle2': [3,237],
+ 'LeftHandMiddle3': [3,240],
+ 'LeftHandMiddle_end': [3,243],
+
+ 'LeftHandRing1': [3,246],
+ 'LeftHandRing2': [3,249],
+ 'LeftHandRing3': [3,252],
+ 'LeftHandRing_end': [3,255],
+
+ 'LeftHandPinky1': [3,258],
+ 'LeftHandPinky2': [3,261],
+ 'LeftHandPinky3': [3,264],
+ 'LeftHandPinky_end': [3,267],
+
+ 'RightShoulder': [3,270],
+ 'RightArm': [3,273],
+ 'RightForearm': [3,276],
+ 'RightHand': [3,279],
+ 'RightHandThumb1': [3,282],
+ 'RightHandThumb2': [3,285],
+ 'RightHandThumb3': [3,288],
+ 'RightHandThumb_end': [3,291],
+
+ 'RightHandIndex1': [3,294],
+ 'RightHandIndex2': [3,297],
+ 'RightHandIndex3': [3,300],
+ 'RightHandIndex_end': [3,303],
+
+ 'RightHandMiddle1': [3,306],
+ 'RightHandMiddle2': [3,309],
+ 'RightHandMiddle3': [3,312],
+ 'RightHandMiddle_end': [3,315],
+
+ 'RightHandRing1': [3,318],
+ 'RightHandRing2': [3,321],
+ 'RightHandRing3': [3,324],
+ 'RightHandRing_end': [3,327],
+
+ 'RightHandPinky1': [3,330],
+ 'RightHandPinky2': [3,333],
+ 'RightHandPinky3': [3,336],
+ 'RightHandPinky_end': [3,339],
+
+ 'RibbonR1': [3,342],
+ 'RibbonR1_end': [3,345],
+ 'RibbonR2': [3,348],
+ 'RibbonR2_end': [3,351],
+ 'RibbonL2': [3,354],
+ 'RibbonL2_end': [3,357],
+
+ 'LeftUpLeg': [3,360],
+ 'LeftLeg': [3,363],
+ 'LeftFoot': [3,366],
+ 'LeftToe': [3,369],
+ 'LeftToe_end': [3,372],
+
+ 'RightUpLeg': [3,375],
+ 'RightLEg': [3,378],
+ 'RightFoot': [3,381],
+ 'RightToe': [3,384],
+ 'RightToe_end': [3,387],
+
+ 'bone_skirtF00': [3, 390],
+ 'bone_skirtF01': [3, 393],
+ 'bone_skirtF02': [3, 396],
+ 'bone_skirtF03': [3, 399],
+ 'Bone020': [3, 402],
+ 'Bone026': [3, 405],
+
+ 'bone_skirtF_R_00': [3, 408],
+ 'bone_skirtF_R_01': [3, 411],
+ 'bone_skirtF_R_02': [3, 414],
+ 'bone_skirtF_R_03': [3, 417],
+ 'Bone019': [3, 420],
+ 'Bone028': [3, 423],
+
+ 'bone_skirtR00': [3, 426],
+ 'bone_skirtR01': [3, 429],
+ 'bone_skirtR02': [3, 432],
+ 'bone_skirtR03': [3, 435],
+ 'Bone018': [3, 438],
+ 'Bone029': [3, 441],
+
+ 'bone_skirtF_L_00': [3, 444],
+ 'bone_skirtF_L_01': [3, 447],
+ 'bone_skirtF_L_02': [3, 450],
+ 'bone_skirtF_L_03': [3, 453],
+ 'Bone021': [3, 456],
+ 'Bone027': [3, 459],
+
+ 'bone_skirtL00': [3, 462],
+ 'bone_skirtL01': [3, 465],
+ 'bone_skirtL02': [3, 468],
+ 'bone_skirtL03': [3, 471],
+ 'Bone022': [3, 474],
+ 'Bone033': [3, 477],
+
+ 'bone_skirtB_L_00': [3, 480],
+ 'bone_skirtB_L_01': [3, 483],
+ 'bone_skirtB_L_02': [3, 486],
+ 'bone_skirtB_L_03': [3, 489],
+ 'Bone023': [3, 492],
+ 'Bone032': [3, 495],
+
+ 'bone_skirtB00': [3, 498],
+ 'bone_skirtB01': [3, 501],
+ 'bone_skirtB02': [3, 504],
+ 'bone_skirtB03': [3, 507],
+ 'Bone024': [3, 510],
+ 'Bone031': [3, 513],
+
+ 'bone_skirtB_R_00': [3, 516],
+ 'bone_skirtB_R_01': [3, 519],
+ 'bone_skirtB_R_02': [3, 521],
+ 'bone_skirtB_R_03': [3, 524],
+ 'Bone025': [3, 527],
+ 'Bone030': [3, 530],
+ },
+
+ "yostar_fullbody_213":{
+ 'Hips': 3 ,
+ 'Spine': 3 ,
+ 'Spine1': 3 ,
+ 'Chest': 3 ,
+ 'L_eri': 3 ,
+ 'R_eri': 3 ,
+ 'Neck': 3 ,
+ 'Head': 3 ,
+ 'Head_end': 3 ,
+
+ 'LeftEye': 3,
+ 'LeftEye_end': 3,
+ 'RightEye': 3,
+ 'RightEye_end': 3,
+
+ 'LeftShoulder': 3,
+ 'LeftArm': 3,
+ 'LeftForearm': 3,
+ 'LeftHand': 3,
+ 'LeftHandThumb1': 3,
+ 'LeftHandThumb2': 3,
+ 'LeftHandThumb3': 3,
+ 'LeftHandThumb_end': 3,
+
+ 'LeftHandIndex1': 3,
+ 'LeftHandIndex2': 3,
+ 'LeftHandIndex3': 3,
+ 'LeftHandIndex_end': 3,
+
+ 'LeftHandMiddle1': 3,
+ 'LeftHandMiddle2': 3,
+ 'LeftHandMiddle3': 3,
+ 'LeftHandMiddle_end': 3,
+
+ 'LeftHandRing1': 3,
+ 'LeftHandRing2': 3,
+ 'LeftHandRing3': 3,
+ 'LeftHandRing_end': 3,
+
+ 'LeftHandPinky1': 3,
+ 'LeftHandPinky2': 3,
+ 'LeftHandPinky3': 3,
+ 'LeftHandPinky_end':3,
+
+ 'RightShoulder': 3,
+ 'RightArm': 3,
+ 'RightForearm': 3,
+ 'RightHand': 3,
+ 'RightHandThumb1': 3,
+ 'RightHandThumb2': 3,
+ 'RightHandThumb3': 3,
+ 'RightHandThumb_end': 3,
+
+ 'RightHandIndex1': 3,
+ 'RightHandIndex2': 3,
+ 'RightHandIndex3': 3,
+ 'RightHandIndex_end': 3,
+
+ 'RightHandMiddle1': 3,
+ 'RightHandMiddle2': 3,
+ 'RightHandMiddle3': 3,
+ 'RightHandMiddle_end': 3,
+
+ 'RightHandRing1': 3,
+ 'RightHandRing2': 3,
+ 'RightHandRing3': 3,
+ 'RightHandRing_end': 3,
+
+ 'RightHandPinky1': 3,
+ 'RightHandPinky2': 3,
+ 'RightHandPinky3': 3,
+ 'RightHandPinky_end': 3,
+
+ 'LeftUpLeg': 3,
+ 'LeftLeg': 3,
+ 'LeftFoot': 3,
+ 'LeftToe': 3,
+ 'LeftToe_end': 3,
+
+ 'RightUpLeg': 3,
+ 'RightLEg': 3,
+ 'RightFoot': 3,
+ 'RightToe': 3,
+ 'RightToe_end': 3,
+ },
+ "yostar_mainbody_48": {
+ #'Hips': 3 ,
+ 'Spine': 3 ,
+ 'Spine1': 3 ,
+ 'Chest': 3 ,
+ 'L_eri': 3 ,
+ 'R_eri': 3 ,
+ 'Neck': 3 ,
+ 'Head': 3 ,
+ 'Head_end': 3 ,
+
+ 'LeftShoulder': 3,
+ 'LeftArm': 3,
+ 'LeftForearm': 3,
+ 'LeftHand': 3,
+
+ 'RightShoulder': 3,
+ 'RightArm': 3,
+ 'RightForearm': 3,
+ 'RightHand': 3,
+ },
+ "yostar_mainbody_69": {
+ 'Hips': 3 ,
+ 'Spine': 3 ,
+ 'Spine1': 3 ,
+ 'Chest': 3 ,
+ 'L_eri': 3 ,
+ 'R_eri': 3 ,
+ 'Neck': 3 ,
+ 'Head': 3 ,
+ 'Head_end': 3 ,
+
+ 'LeftShoulder': 3,
+ 'LeftArm': 3,
+ 'LeftForearm': 3,
+ 'LeftHand': 3,
+
+ 'RightShoulder': 3,
+ 'RightArm': 3,
+ 'RightForearm': 3,
+ 'RightHand': 3,
+
+ 'LeftUpLeg': 3,
+ 'LeftLeg': 3,
+ 'LeftFoot': 3,
+
+ 'RightUpLeg': 3,
+ 'RightLEg': 3,
+ 'RightFoot': 3,
+ },
+
+ "yostar_upbody_168": {
+ #'Hips': 3 ,
+ 'Spine': 3 ,
+ 'Spine1': 3 ,
+ 'Chest': 3 ,
+ 'L_eri': 3 ,
+ 'R_eri': 3 ,
+ 'Neck': 3 ,
+ 'Head': 3 ,
+ 'Head_end': 3 ,
+
+ 'LeftShoulder': 3,
+ 'LeftArm': 3,
+ 'LeftForearm': 3,
+ 'LeftHand': 3,
+ 'LeftHandThumb1': 3,
+ 'LeftHandThumb2': 3,
+ 'LeftHandThumb3': 3,
+ 'LeftHandThumb_end': 3,
+
+ 'LeftHandIndex1': 3,
+ 'LeftHandIndex2': 3,
+ 'LeftHandIndex3': 3,
+ 'LeftHandIndex_end': 3,
+
+ 'LeftHandMiddle1': 3,
+ 'LeftHandMiddle2': 3,
+ 'LeftHandMiddle3': 3,
+ 'LeftHandMiddle_end': 3,
+
+ 'LeftHandRing1': 3,
+ 'LeftHandRing2': 3,
+ 'LeftHandRing3': 3,
+ 'LeftHandRing_end': 3,
+
+ 'LeftHandPinky1': 3,
+ 'LeftHandPinky2': 3,
+ 'LeftHandPinky3': 3,
+ 'LeftHandPinky_end':3,
+
+ 'RightShoulder': 3,
+ 'RightArm': 3,
+ 'RightForearm': 3,
+ 'RightHand': 3,
+ 'RightHandThumb1': 3,
+ 'RightHandThumb2': 3,
+ 'RightHandThumb3': 3,
+ 'RightHandThumb_end': 3,
+
+ 'RightHandIndex1': 3,
+ 'RightHandIndex2': 3,
+ 'RightHandIndex3': 3,
+ 'RightHandIndex_end': 3,
+
+ 'RightHandMiddle1': 3,
+ 'RightHandMiddle2': 3,
+ 'RightHandMiddle3': 3,
+ 'RightHandMiddle_end': 3,
+
+ 'RightHandRing1': 3,
+ 'RightHandRing2': 3,
+ 'RightHandRing3': 3,
+ 'RightHandRing_end': 3,
+
+ 'RightHandPinky1': 3,
+ 'RightHandPinky2': 3,
+ 'RightHandPinky3': 3,
+ 'RightHandPinky_end': 3,
+ },
+ "spine_neck_141":{
+ 'Spine': 3 ,
+ 'Neck': 3 ,
+ 'Neck1': 3 ,
+ 'RShoulder': 3 ,
+ 'RArm': 3 ,
+ 'RArm1': 3 ,
+ 'RHand': 3 ,
+ 'RHandM1': 3 ,
+ 'RHandM2': 3 ,
+ 'RHandM3': 3 ,
+ 'RHandR': 3 ,
+ 'RHandR1': 3 ,
+ 'RHandR2': 3 ,
+ 'RHandR3': 3 ,
+ 'RHandP': 3 ,
+ 'RHandP1': 3 ,
+ 'RHandP2': 3 ,
+ 'RHandP3': 3 ,
+ 'RHandI': 3 ,
+ 'RHandI1': 3 ,
+ 'RHandI2': 3 ,
+ 'RHandI3': 3 ,
+ 'RHandT1': 3 ,
+ 'RHandT2': 3 ,
+ 'RHandT3': 3 ,
+ 'LShoulder': 3 ,
+ 'LArm': 3 ,
+ 'LArm1': 3 ,
+ 'LHand': 3 ,
+ 'LHandM1': 3 ,
+ 'LHandM2': 3 ,
+ 'LHandM3': 3 ,
+ 'LHandR': 3 ,
+ 'LHandR1': 3 ,
+ 'LHandR2': 3 ,
+ 'LHandR3': 3 ,
+ 'LHandP': 3 ,
+ 'LHandP1': 3 ,
+ 'LHandP2': 3 ,
+ 'LHandP3': 3 ,
+ 'LHandI': 3 ,
+ 'LHandI1': 3 ,
+ 'LHandI2': 3 ,
+ 'LHandI3': 3 ,
+ 'LHandT1': 3 ,
+ 'LHandT2': 3 ,
+ 'LHandT3': 3 ,},
+}
+
+
+class FIDCalculator(object):
+ '''
+ todo
+ '''
+ def __init__(self):
+ self.gt_rot = None # pandas dataframe for n frames * joints * 6
+ self.gt_pos = None # n frames * (joints + 13) * 3
+ self.op_rot = None # pandas dataframe for n frames * joints * 6
+ self.op_pos = None # n frames * (joints + 13) * 3
+
+
+ def load(self, path, load_type, save_pos=False):
+ '''
+ select gt or op for load_type
+ '''
+ parser = BVHParser()
+ parsed_data = parser.parse(path)
+ if load_type == 'gt':
+ self.gt_rot = parsed_data.values
+ elif load_type == 'op':
+ self.op_rot = parsed_data.values
+ else: print('error, select gt or op for load_type')
+
+ if save_pos:
+ mp = MocapParameterizer('position')
+ positions = mp.fit_transform([parsed_data])
+ if load_type == 'gt':
+ self.gt_pos = positions[0].values
+ elif load_type == 'op':
+ self.op_pos = positions[0].values
+ else: print('error, select gt or op for load_type')
+
+
+ def _joint_selector(self, selected_joints, ori_data):
+ selected_data = pd.DataFrame(columns=[])
+
+ for joint_name in selected_joints:
+ selected_data[joint_name] = ori_data[joint_name]
+ return selected_data.to_numpy()
+
+
+ def cal_vol(self, dtype):
+ if dtype == 'pos':
+ gt = self.gt_pos
+ op = self.op_pos
+ else:
+ gt = self.gt_rot
+ op = self.op_rot
+
+ gt_v = gt.to_numpy()[1:, :] - gt.to_numpy()[0:-1, :]
+ op_v = op.to_numpy()[1:, :] - op.to_numpy()[0:-1, :]
+ if dtype == 'pos':
+ self.gt_vol_pos = pd.DataFrame(gt_v, columns = gt.columns.tolist())
+ self.op_vol_pos = pd.DataFrame(op_v, columns = gt.columns.tolist())
+ else:
+ self.gt_vol_rot = pd.DataFrame(gt_v, columns = gt.columns.tolist())
+ self.op_vol_rot = pd.DataFrame(op_v, columns = gt.columns.tolist())
+
+
+ @staticmethod
+ def frechet_distance(samples_A, samples_B):
+ A_mu = np.mean(samples_A, axis=0)
+ A_sigma = np.cov(samples_A, rowvar=False)
+ B_mu = np.mean(samples_B, axis=0)
+ B_sigma = np.cov(samples_B, rowvar=False)
+ try:
+ frechet_dist = FIDCalculator.calculate_frechet_distance(A_mu, A_sigma, B_mu, B_sigma)
+ except ValueError:
+ frechet_dist = 1e+10
+ return frechet_dist
+
+
+ @staticmethod
+ def calculate_frechet_distance(mu1, sigma1, mu2, sigma2, eps=1e-6):
+ """ from https://github.com/mseitzer/pytorch-fid/blob/master/fid_score.py """
+ """Numpy implementation of the Frechet Distance.
+ The Frechet distance between two multivariate Gaussians X_1 ~ N(mu_1, C_1)
+ and X_2 ~ N(mu_2, C_2) is
+ d^2 = ||mu_1 - mu_2||^2 + Tr(C_1 + C_2 - 2*sqrt(C_1*C_2)).
+ Stable version by Dougal J. Sutherland.
+ Params:
+ -- mu1 : Numpy array containing the activations of a layer of the
+ inception net (like returned by the function 'get_predictions')
+ for generated samples.
+ -- mu2 : The sample mean over activations, precalculated on an
+ representative data set.
+ -- sigma1: The covariance matrix over activations for generated samples.
+ -- sigma2: The covariance matrix over activations, precalculated on an
+ representative data set.
+ Returns:
+ -- : The Frechet Distance.
+ """
+
+ mu1 = np.atleast_1d(mu1)
+ mu2 = np.atleast_1d(mu2)
+ #print(mu1[0], mu2[0])
+ sigma1 = np.atleast_2d(sigma1)
+ sigma2 = np.atleast_2d(sigma2)
+ #print(sigma1[0], sigma2[0])
+ assert mu1.shape == mu2.shape, \
+ 'Training and test mean vectors have different lengths'
+ assert sigma1.shape == sigma2.shape, \
+ 'Training and test covariances have different dimensions'
+
+ diff = mu1 - mu2
+
+ # Product might be almost singular
+ covmean, _ = linalg.sqrtm(sigma1.dot(sigma2), disp=False)
+ #print(diff, covmean[0])
+ if not np.isfinite(covmean).all():
+ msg = ('fid calculation produces singular product; '
+ 'adding %s to diagonal of cov estimates') % eps
+ print(msg)
+ offset = np.eye(sigma1.shape[0]) * eps
+ covmean = linalg.sqrtm((sigma1 + offset).dot(sigma2 + offset))
+
+ # Numerical error might give slight imaginary component
+ if np.iscomplexobj(covmean):
+ if not np.allclose(np.diagonal(covmean).imag, 0, atol=1e-3):
+ m = np.max(np.abs(covmean.imag))
+ raise ValueError('Imaginary component {}'.format(m))
+ covmean = covmean.real
+
+ tr_covmean = np.trace(covmean)
+
+ return (diff.dot(diff) + np.trace(sigma1) +
+ np.trace(sigma2) - 2 * tr_covmean)
+
+
+ def calculate_fid(self, cal_type, joint_type, high_level_opt):
+
+ if cal_type == 'pos':
+ if self.gt_pos.shape != self.op_pos.shape:
+ min_val = min(self.gt_pos.shape[0],self.op_pos.shape[0])
+ gt = self.gt_pos[:min_val]
+ op = self.op_pos[:min_val]
+ else:
+ gt = self.gt_pos
+ op = self.op_pos
+ full_body = gt.columns.tolist()
+ elif cal_type == 'rot':
+ if self.gt_rot.shape != self.op_rot.shape:
+ min_val = min(self.gt_rot.shape[0],self.op_rot.shape[0])
+ gt = self.gt_rot[:min_val]
+ op = self.op_rot[:min_val]
+ else:
+ gt = self.gt_rot
+ op = self.op_rot
+ full_body_with_offset = gt.columns.tolist()
+ full_body = [o for o in full_body_with_offset if ('position' not in o)]
+ elif cal_type == 'pos_vol':
+ assert self.gt_vol_pos.shape == self.op_vol_pos.shape
+ gt = self.gt_vol_pos
+ op = self.op_vol_pos
+ full_body_with_offset = gt.columns.tolist()
+ full_body = gt.columns.tolist()
+ elif cal_type == 'rot_vol':
+ assert self.gt_vol_rot.shape == self.op_vol_rot.shape
+ gt = self.gt_vol_rot
+ op = self.op_vol_rot
+ full_body_with_offset = gt.columns.tolist()
+ full_body = [o for o in full_body_with_offset if ('position' not in o)]
+ #print(f'full_body contains {len(full_body)//3} joints')
+
+ if joint_type == 'full_upper_body':
+ selected_body = [o for o in full_body if ('Leg' not in o) and ('Foot' not in o) and ('Toe' not in o)]
+ elif joint_type == 'upper_body':
+ selected_body = [o for o in full_body if ('Hand' not in o) and ('Leg' not in o) and ('Foot' not in o) and ('Toe' not in o)]
+ elif joint_type == 'fingers':
+ selected_body = [o for o in full_body if ('Hand' in o)]
+ elif joint_type == 'indivdual':
+ pass
+ else: print('error, plz select correct joint type')
+ #print(f'calculate fid for {len(selected_body)//3} joints')
+
+ gt = self._joint_selector(selected_body, gt)
+ op = self._joint_selector(selected_body, op)
+
+ if high_level_opt == 'fid':
+ fid = FIDCalculator.frechet_distance(gt, op)
+ return fid
+ elif high_level_opt == 'var':
+ var_gt = gt.var()
+ var_op = op.var()
+ return var_gt, var_op
+ elif high_level_opt == 'mean':
+ mean_gt = gt.mean()
+ mean_op = op.mean()
+ return mean_gt, mean_op
+ else: return 0
+
+
+def result2target_vis(pose_version, res_bvhlist, save_path, demo_name, verbose=True):
+ if "trinity" in pose_version:
+ ori_list = joints_list[pose_version[6:-4]]
+ target_list = joints_list[pose_version[6:]]
+ file_content_length = 336
+ elif "beat" in pose_version or "spine_neck_141" in pose_version:
+ ori_list = joints_list["beat_joints"]
+ target_list = joints_list["spine_neck_141"]
+ file_content_length = 431
+ elif "yostar" in pose_version:
+ ori_list = joints_list["yostar"]
+ target_list = joints_list[pose_version]
+ file_content_length = 1056
+ else:
+ ori_list = joints_list["japanese_joints"]
+ target_list = joints_list[pose_version]
+ file_content_length = 366
+
+ bvh_files_dirs = sorted(glob.glob(f'{res_bvhlist}*.bvh'), key=str)
+ #test_seq_list = os.list_dir(demo_name).sort()
+
+ counter = 0
+ if not os.path.exists(save_path):
+ os.makedirs(save_path)
+ for i, bvh_file_dir in enumerate(bvh_files_dirs):
+ short_name = bvh_file_dir.split("/")[-1][11:]
+ #print(short_name)
+ wirte_file = open(os.path.join(save_path, f'res_{short_name}'),'w+')
+ with open(f"{demo_name}{short_name}",'r') as pose_data_pre:
+ pose_data_pre_file = pose_data_pre.readlines()
+ for j, line in enumerate(pose_data_pre_file[0:file_content_length]):
+ wirte_file.write(line)
+ offset_data = pose_data_pre_file[file_content_length]
+ offset_data = np.fromstring(offset_data, dtype=float, sep=' ')
+ wirte_file.close()
+
+ wirte_file = open(os.path.join(save_path, f'res_{short_name}'),'r')
+ ori_lines = wirte_file.readlines()
+ with open(bvh_file_dir, 'r') as pose_data:
+ pose_data_file = pose_data.readlines()
+ ori_lines[file_content_length-2] = 'Frames: ' + str(len(pose_data_file)-1) + '\n'
+ wirte_file.close()
+
+ wirte_file = open(os.path.join(save_path, f'res_{short_name}'),'w+')
+ wirte_file.writelines(i for i in ori_lines[:file_content_length])
+ wirte_file.close()
+
+ with open(os.path.join(save_path, f'res_{short_name}'),'a+') as wirte_file:
+ with open(bvh_file_dir, 'r') as pose_data:
+ data_each_file = []
+ pose_data_file = pose_data.readlines()
+ for j, line in enumerate(pose_data_file):
+ if not j:
+ pass
+ else:
+ data = np.fromstring(line, dtype=float, sep=' ')
+ data_rotation = offset_data.copy()
+ for iii, (k, v) in enumerate(target_list.items()): # here is 147 rotations by 3
+ #print(data_rotation[ori_list[k][1]-v:ori_list[k][1]], data[iii*3:iii*3+3])
+ data_rotation[ori_list[k][1]-v:ori_list[k][1]] = data[iii*3:iii*3+3]
+ data_each_file.append(data_rotation)
+
+ for line_data in data_each_file:
+ line_data = np.array2string(line_data, max_line_width=np.inf, precision=6, suppress_small=False, separator=' ')
+ wirte_file.write(line_data[1:-2]+'\n')
+
+ counter += 1
+ if verbose:
+ logger.info('data_shape:', data_rotation.shape, 'process:', counter, '/', len(bvh_files_dirs))
\ No newline at end of file
diff --git a/dataloaders/pymo/Quaternions.py b/dataloaders/pymo/Quaternions.py
new file mode 100644
index 0000000000000000000000000000000000000000..d4b754871310a264e2bd2675479db9a79d24358e
--- /dev/null
+++ b/dataloaders/pymo/Quaternions.py
@@ -0,0 +1,468 @@
+import numpy as np
+
+class Quaternions:
+ """
+ Quaternions is a wrapper around a numpy ndarray
+ that allows it to act as if it were an narray of
+ a quaternion data type.
+
+ Therefore addition, subtraction, multiplication,
+ division, negation, absolute, are all defined
+ in terms of quaternion operations such as quaternion
+ multiplication.
+
+ This allows for much neater code and many routines
+ which conceptually do the same thing to be written
+ in the same way for point data and for rotation data.
+
+ The Quaternions class has been desgined such that it
+ should support broadcasting and slicing in all of the
+ usual ways.
+ """
+
+ def __init__(self, qs):
+ if isinstance(qs, np.ndarray):
+
+ if len(qs.shape) == 1: qs = np.array([qs])
+ self.qs = qs
+ return
+
+ if isinstance(qs, Quaternions):
+ self.qs = qs.qs
+ return
+
+ raise TypeError('Quaternions must be constructed from iterable, numpy array, or Quaternions, not %s' % type(qs))
+
+ def __str__(self): return "Quaternions("+ str(self.qs) + ")"
+ def __repr__(self): return "Quaternions("+ repr(self.qs) + ")"
+
+ """ Helper Methods for Broadcasting and Data extraction """
+
+ @classmethod
+ def _broadcast(cls, sqs, oqs, scalar=False):
+
+ if isinstance(oqs, float): return sqs, oqs * np.ones(sqs.shape[:-1])
+
+ ss = np.array(sqs.shape) if not scalar else np.array(sqs.shape[:-1])
+ os = np.array(oqs.shape)
+
+ if len(ss) != len(os):
+ raise TypeError('Quaternions cannot broadcast together shapes %s and %s' % (sqs.shape, oqs.shape))
+
+ if np.all(ss == os): return sqs, oqs
+
+ if not np.all((ss == os) | (os == np.ones(len(os))) | (ss == np.ones(len(ss)))):
+ raise TypeError('Quaternions cannot broadcast together shapes %s and %s' % (sqs.shape, oqs.shape))
+
+ sqsn, oqsn = sqs.copy(), oqs.copy()
+
+ for a in np.where(ss == 1)[0]: sqsn = sqsn.repeat(os[a], axis=a)
+ for a in np.where(os == 1)[0]: oqsn = oqsn.repeat(ss[a], axis=a)
+
+ return sqsn, oqsn
+
+ """ Adding Quaterions is just Defined as Multiplication """
+
+ def __add__(self, other): return self * other
+ def __sub__(self, other): return self / other
+
+ """ Quaterion Multiplication """
+
+ def __mul__(self, other):
+ """
+ Quaternion multiplication has three main methods.
+
+ When multiplying a Quaternions array by Quaternions
+ normal quaternion multiplication is performed.
+
+ When multiplying a Quaternions array by a vector
+ array of the same shape, where the last axis is 3,
+ it is assumed to be a Quaternion by 3D-Vector
+ multiplication and the 3D-Vectors are rotated
+ in space by the Quaternions.
+
+ When multipplying a Quaternions array by a scalar
+ or vector of different shape it is assumed to be
+ a Quaternions by Scalars multiplication and the
+ Quaternions are scaled using Slerp and the identity
+ quaternions.
+ """
+
+ """ If Quaternions type do Quaternions * Quaternions """
+ if isinstance(other, Quaternions):
+
+ sqs, oqs = Quaternions._broadcast(self.qs, other.qs)
+
+ q0 = sqs[...,0]; q1 = sqs[...,1];
+ q2 = sqs[...,2]; q3 = sqs[...,3];
+ r0 = oqs[...,0]; r1 = oqs[...,1];
+ r2 = oqs[...,2]; r3 = oqs[...,3];
+
+ qs = np.empty(sqs.shape)
+ qs[...,0] = r0 * q0 - r1 * q1 - r2 * q2 - r3 * q3
+ qs[...,1] = r0 * q1 + r1 * q0 - r2 * q3 + r3 * q2
+ qs[...,2] = r0 * q2 + r1 * q3 + r2 * q0 - r3 * q1
+ qs[...,3] = r0 * q3 - r1 * q2 + r2 * q1 + r3 * q0
+
+ return Quaternions(qs)
+
+ """ If array type do Quaternions * Vectors """
+ if isinstance(other, np.ndarray) and other.shape[-1] == 3:
+ vs = Quaternions(np.concatenate([np.zeros(other.shape[:-1] + (1,)), other], axis=-1))
+ return (self * (vs * -self)).imaginaries
+
+ """ If float do Quaternions * Scalars """
+ if isinstance(other, np.ndarray) or isinstance(other, float):
+ return Quaternions.slerp(Quaternions.id_like(self), self, other)
+
+ raise TypeError('Cannot multiply/add Quaternions with type %s' % str(type(other)))
+
+ def __div__(self, other):
+ """
+ When a Quaternion type is supplied, division is defined
+ as multiplication by the inverse of that Quaternion.
+
+ When a scalar or vector is supplied it is defined
+ as multiplicaion of one over the supplied value.
+ Essentially a scaling.
+ """
+
+ if isinstance(other, Quaternions): return self * (-other)
+ if isinstance(other, np.ndarray): return self * (1.0 / other)
+ if isinstance(other, float): return self * (1.0 / other)
+ raise TypeError('Cannot divide/subtract Quaternions with type %s' + str(type(other)))
+
+ def __eq__(self, other): return self.qs == other.qs
+ def __ne__(self, other): return self.qs != other.qs
+
+ def __neg__(self):
+ """ Invert Quaternions """
+ return Quaternions(self.qs * np.array([[1, -1, -1, -1]]))
+
+ def __abs__(self):
+ """ Unify Quaternions To Single Pole """
+ qabs = self.normalized().copy()
+ top = np.sum(( qabs.qs) * np.array([1,0,0,0]), axis=-1)
+ bot = np.sum((-qabs.qs) * np.array([1,0,0,0]), axis=-1)
+ qabs.qs[top < bot] = -qabs.qs[top < bot]
+ return qabs
+
+ def __iter__(self): return iter(self.qs)
+ def __len__(self): return len(self.qs)
+
+ def __getitem__(self, k): return Quaternions(self.qs[k])
+ def __setitem__(self, k, v): self.qs[k] = v.qs
+
+ @property
+ def lengths(self):
+ return np.sum(self.qs**2.0, axis=-1)**0.5
+
+ @property
+ def reals(self):
+ return self.qs[...,0]
+
+ @property
+ def imaginaries(self):
+ return self.qs[...,1:4]
+
+ @property
+ def shape(self): return self.qs.shape[:-1]
+
+ def repeat(self, n, **kwargs):
+ return Quaternions(self.qs.repeat(n, **kwargs))
+
+ def normalized(self):
+ return Quaternions(self.qs / self.lengths[...,np.newaxis])
+
+ def log(self):
+ norm = abs(self.normalized())
+ imgs = norm.imaginaries
+ lens = np.sqrt(np.sum(imgs**2, axis=-1))
+ lens = np.arctan2(lens, norm.reals) / (lens + 1e-10)
+ return imgs * lens[...,np.newaxis]
+
+ def constrained(self, axis):
+
+ rl = self.reals
+ im = np.sum(axis * self.imaginaries, axis=-1)
+
+ t1 = -2 * np.arctan2(rl, im) + np.pi
+ t2 = -2 * np.arctan2(rl, im) - np.pi
+
+ top = Quaternions.exp(axis[np.newaxis] * (t1[:,np.newaxis] / 2.0))
+ bot = Quaternions.exp(axis[np.newaxis] * (t2[:,np.newaxis] / 2.0))
+ img = self.dot(top) > self.dot(bot)
+
+ ret = top.copy()
+ ret[ img] = top[ img]
+ ret[~img] = bot[~img]
+ return ret
+
+ def constrained_x(self): return self.constrained(np.array([1,0,0]))
+ def constrained_y(self): return self.constrained(np.array([0,1,0]))
+ def constrained_z(self): return self.constrained(np.array([0,0,1]))
+
+ def dot(self, q): return np.sum(self.qs * q.qs, axis=-1)
+
+ def copy(self): return Quaternions(np.copy(self.qs))
+
+ def reshape(self, s):
+ self.qs.reshape(s)
+ return self
+
+ def interpolate(self, ws):
+ return Quaternions.exp(np.average(abs(self).log, axis=0, weights=ws))
+
+ def euler(self, order='xyz'):
+
+ q = self.normalized().qs
+ q0 = q[...,0]
+ q1 = q[...,1]
+ q2 = q[...,2]
+ q3 = q[...,3]
+ es = np.zeros(self.shape + (3,))
+
+ if order == 'xyz':
+ es[...,0] = np.arctan2(2 * (q0 * q1 + q2 * q3), 1 - 2 * (q1 * q1 + q2 * q2))
+ es[...,1] = np.arcsin((2 * (q0 * q2 - q3 * q1)).clip(-1,1))
+ es[...,2] = np.arctan2(2 * (q0 * q3 + q1 * q2), 1 - 2 * (q2 * q2 + q3 * q3))
+ elif order == 'yzx':
+ es[...,0] = np.arctan2(2 * (q1 * q0 - q2 * q3), -q1 * q1 + q2 * q2 - q3 * q3 + q0 * q0)
+ es[...,1] = np.arctan2(2 * (q2 * q0 - q1 * q3), q1 * q1 - q2 * q2 - q3 * q3 + q0 * q0)
+ es[...,2] = np.arcsin((2 * (q1 * q2 + q3 * q0)).clip(-1,1))
+ else:
+ raise NotImplementedError('Cannot convert from ordering %s' % order)
+
+ """
+
+ # These conversion don't appear to work correctly for Maya.
+ # http://bediyap.com/programming/convert-quaternion-to-euler-rotations/
+
+ if order == 'xyz':
+ es[...,0] = np.arctan2(2 * (q0 * q3 - q1 * q2), q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3)
+ es[...,1] = np.arcsin((2 * (q1 * q3 + q0 * q2)).clip(-1,1))
+ es[...,2] = np.arctan2(2 * (q0 * q1 - q2 * q3), q0 * q0 - q1 * q1 - q2 * q2 + q3 * q3)
+ elif order == 'yzx':
+ es[...,0] = np.arctan2(2 * (q0 * q1 - q2 * q3), q0 * q0 - q1 * q1 + q2 * q2 - q3 * q3)
+ es[...,1] = np.arcsin((2 * (q1 * q2 + q0 * q3)).clip(-1,1))
+ es[...,2] = np.arctan2(2 * (q0 * q2 - q1 * q3), q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3)
+ elif order == 'zxy':
+ es[...,0] = np.arctan2(2 * (q0 * q2 - q1 * q3), q0 * q0 - q1 * q1 - q2 * q2 + q3 * q3)
+ es[...,1] = np.arcsin((2 * (q0 * q1 + q2 * q3)).clip(-1,1))
+ es[...,2] = np.arctan2(2 * (q0 * q3 - q1 * q2), q0 * q0 - q1 * q1 + q2 * q2 - q3 * q3)
+ elif order == 'xzy':
+ es[...,0] = np.arctan2(2 * (q0 * q2 + q1 * q3), q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3)
+ es[...,1] = np.arcsin((2 * (q0 * q3 - q1 * q2)).clip(-1,1))
+ es[...,2] = np.arctan2(2 * (q0 * q1 + q2 * q3), q0 * q0 - q1 * q1 + q2 * q2 - q3 * q3)
+ elif order == 'yxz':
+ es[...,0] = np.arctan2(2 * (q1 * q2 + q0 * q3), q0 * q0 - q1 * q1 + q2 * q2 - q3 * q3)
+ es[...,1] = np.arcsin((2 * (q0 * q1 - q2 * q3)).clip(-1,1))
+ es[...,2] = np.arctan2(2 * (q1 * q3 + q0 * q2), q0 * q0 - q1 * q1 - q2 * q2 + q3 * q3)
+ elif order == 'zyx':
+ es[...,0] = np.arctan2(2 * (q0 * q1 + q2 * q3), q0 * q0 - q1 * q1 - q2 * q2 + q3 * q3)
+ es[...,1] = np.arcsin((2 * (q0 * q2 - q1 * q3)).clip(-1,1))
+ es[...,2] = np.arctan2(2 * (q0 * q3 + q1 * q2), q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3)
+ else:
+ raise KeyError('Unknown ordering %s' % order)
+
+ """
+
+ # https://github.com/ehsan/ogre/blob/master/OgreMain/src/OgreMatrix3.cpp
+ # Use this class and convert from matrix
+
+ return es
+
+
+ def average(self):
+
+ if len(self.shape) == 1:
+
+ import numpy.core.umath_tests as ut
+ system = ut.matrix_multiply(self.qs[:,:,np.newaxis], self.qs[:,np.newaxis,:]).sum(axis=0)
+ w, v = np.linalg.eigh(system)
+ qiT_dot_qref = (self.qs[:,:,np.newaxis] * v[np.newaxis,:,:]).sum(axis=1)
+ return Quaternions(v[:,np.argmin((1.-qiT_dot_qref**2).sum(axis=0))])
+
+ else:
+
+ raise NotImplementedError('Cannot average multi-dimensionsal Quaternions')
+
+ def angle_axis(self):
+
+ norm = self.normalized()
+ s = np.sqrt(1 - (norm.reals**2.0))
+ s[s == 0] = 0.001
+
+ angles = 2.0 * np.arccos(norm.reals)
+ axis = norm.imaginaries / s[...,np.newaxis]
+
+ return angles, axis
+
+
+ def transforms(self):
+
+ qw = self.qs[...,0]
+ qx = self.qs[...,1]
+ qy = self.qs[...,2]
+ qz = self.qs[...,3]
+
+ x2 = qx + qx; y2 = qy + qy; z2 = qz + qz;
+ xx = qx * x2; yy = qy * y2; wx = qw * x2;
+ xy = qx * y2; yz = qy * z2; wy = qw * y2;
+ xz = qx * z2; zz = qz * z2; wz = qw * z2;
+
+ m = np.empty(self.shape + (3,3))
+ m[...,0,0] = 1.0 - (yy + zz)
+ m[...,0,1] = xy - wz
+ m[...,0,2] = xz + wy
+ m[...,1,0] = xy + wz
+ m[...,1,1] = 1.0 - (xx + zz)
+ m[...,1,2] = yz - wx
+ m[...,2,0] = xz - wy
+ m[...,2,1] = yz + wx
+ m[...,2,2] = 1.0 - (xx + yy)
+
+ return m
+
+ def ravel(self):
+ return self.qs.ravel()
+
+ @classmethod
+ def id(cls, n):
+
+ if isinstance(n, tuple):
+ qs = np.zeros(n + (4,))
+ qs[...,0] = 1.0
+ return Quaternions(qs)
+
+ if isinstance(n, int) or isinstance(n, long):
+ qs = np.zeros((n,4))
+ qs[:,0] = 1.0
+ return Quaternions(qs)
+
+ raise TypeError('Cannot Construct Quaternion from %s type' % str(type(n)))
+
+ @classmethod
+ def id_like(cls, a):
+ qs = np.zeros(a.shape + (4,))
+ qs[...,0] = 1.0
+ return Quaternions(qs)
+
+ @classmethod
+ def exp(cls, ws):
+
+ ts = np.sum(ws**2.0, axis=-1)**0.5
+ ts[ts == 0] = 0.001
+ ls = np.sin(ts) / ts
+
+ qs = np.empty(ws.shape[:-1] + (4,))
+ qs[...,0] = np.cos(ts)
+ qs[...,1] = ws[...,0] * ls
+ qs[...,2] = ws[...,1] * ls
+ qs[...,3] = ws[...,2] * ls
+
+ return Quaternions(qs).normalized()
+
+ @classmethod
+ def slerp(cls, q0s, q1s, a):
+
+ fst, snd = cls._broadcast(q0s.qs, q1s.qs)
+ fst, a = cls._broadcast(fst, a, scalar=True)
+ snd, a = cls._broadcast(snd, a, scalar=True)
+
+ len = np.sum(fst * snd, axis=-1)
+
+ neg = len < 0.0
+ len[neg] = -len[neg]
+ snd[neg] = -snd[neg]
+
+ amount0 = np.zeros(a.shape)
+ amount1 = np.zeros(a.shape)
+
+ linear = (1.0 - len) < 0.01
+ omegas = np.arccos(len[~linear])
+ sinoms = np.sin(omegas)
+
+ amount0[ linear] = 1.0 - a[linear]
+ amount1[ linear] = a[linear]
+ amount0[~linear] = np.sin((1.0 - a[~linear]) * omegas) / sinoms
+ amount1[~linear] = np.sin( a[~linear] * omegas) / sinoms
+
+ return Quaternions(
+ amount0[...,np.newaxis] * fst +
+ amount1[...,np.newaxis] * snd)
+
+ @classmethod
+ def between(cls, v0s, v1s):
+ a = np.cross(v0s, v1s)
+ w = np.sqrt((v0s**2).sum(axis=-1) * (v1s**2).sum(axis=-1)) + (v0s * v1s).sum(axis=-1)
+ return Quaternions(np.concatenate([w[...,np.newaxis], a], axis=-1)).normalized()
+
+ @classmethod
+ def from_angle_axis(cls, angles, axis):
+ axis = axis / (np.sqrt(np.sum(axis**2, axis=-1)) + 1e-10)[...,np.newaxis]
+ sines = np.sin(angles / 2.0)[...,np.newaxis]
+ cosines = np.cos(angles / 2.0)[...,np.newaxis]
+ return Quaternions(np.concatenate([cosines, axis * sines], axis=-1))
+
+ @classmethod
+ def from_euler(cls, es, order='xyz', world=False):
+
+ axis = {
+ 'x' : np.array([1,0,0]),
+ 'y' : np.array([0,1,0]),
+ 'z' : np.array([0,0,1]),
+ }
+
+ q0s = Quaternions.from_angle_axis(es[...,0], axis[order[0]])
+ q1s = Quaternions.from_angle_axis(es[...,1], axis[order[1]])
+ q2s = Quaternions.from_angle_axis(es[...,2], axis[order[2]])
+
+ return (q2s * (q1s * q0s)) if world else (q0s * (q1s * q2s))
+
+ @classmethod
+ def from_transforms(cls, ts):
+
+ d0, d1, d2 = ts[...,0,0], ts[...,1,1], ts[...,2,2]
+
+ q0 = ( d0 + d1 + d2 + 1.0) / 4.0
+ q1 = ( d0 - d1 - d2 + 1.0) / 4.0
+ q2 = (-d0 + d1 - d2 + 1.0) / 4.0
+ q3 = (-d0 - d1 + d2 + 1.0) / 4.0
+
+ q0 = np.sqrt(q0.clip(0,None))
+ q1 = np.sqrt(q1.clip(0,None))
+ q2 = np.sqrt(q2.clip(0,None))
+ q3 = np.sqrt(q3.clip(0,None))
+
+ c0 = (q0 >= q1) & (q0 >= q2) & (q0 >= q3)
+ c1 = (q1 >= q0) & (q1 >= q2) & (q1 >= q3)
+ c2 = (q2 >= q0) & (q2 >= q1) & (q2 >= q3)
+ c3 = (q3 >= q0) & (q3 >= q1) & (q3 >= q2)
+
+ q1[c0] *= np.sign(ts[c0,2,1] - ts[c0,1,2])
+ q2[c0] *= np.sign(ts[c0,0,2] - ts[c0,2,0])
+ q3[c0] *= np.sign(ts[c0,1,0] - ts[c0,0,1])
+
+ q0[c1] *= np.sign(ts[c1,2,1] - ts[c1,1,2])
+ q2[c1] *= np.sign(ts[c1,1,0] + ts[c1,0,1])
+ q3[c1] *= np.sign(ts[c1,0,2] + ts[c1,2,0])
+
+ q0[c2] *= np.sign(ts[c2,0,2] - ts[c2,2,0])
+ q1[c2] *= np.sign(ts[c2,1,0] + ts[c2,0,1])
+ q3[c2] *= np.sign(ts[c2,2,1] + ts[c2,1,2])
+
+ q0[c3] *= np.sign(ts[c3,1,0] - ts[c3,0,1])
+ q1[c3] *= np.sign(ts[c3,2,0] + ts[c3,0,2])
+ q2[c3] *= np.sign(ts[c3,2,1] + ts[c3,1,2])
+
+ qs = np.empty(ts.shape[:-2] + (4,))
+ qs[...,0] = q0
+ qs[...,1] = q1
+ qs[...,2] = q2
+ qs[...,3] = q3
+
+ return cls(qs)
+
+
+
\ No newline at end of file
diff --git a/dataloaders/pymo/__init__.py b/dataloaders/pymo/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/dataloaders/pymo/__pycache__/Quaternions.cpython-310.pyc b/dataloaders/pymo/__pycache__/Quaternions.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c442d4bb4e465e0b2ac01b857277011dc21b1a0a
Binary files /dev/null and b/dataloaders/pymo/__pycache__/Quaternions.cpython-310.pyc differ
diff --git a/dataloaders/pymo/__pycache__/Quaternions.cpython-38.pyc b/dataloaders/pymo/__pycache__/Quaternions.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6a633c51e23554d02d76e0c91871ea03071adb39
Binary files /dev/null and b/dataloaders/pymo/__pycache__/Quaternions.cpython-38.pyc differ
diff --git a/dataloaders/pymo/__pycache__/__init__.cpython-310.pyc b/dataloaders/pymo/__pycache__/__init__.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2ca872db26fcc35f1ca291eb73f69d1e00a65a28
Binary files /dev/null and b/dataloaders/pymo/__pycache__/__init__.cpython-310.pyc differ
diff --git a/dataloaders/pymo/__pycache__/__init__.cpython-38.pyc b/dataloaders/pymo/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ddaae9de304099439b221c6969b125291b42b2da
Binary files /dev/null and b/dataloaders/pymo/__pycache__/__init__.cpython-38.pyc differ
diff --git a/dataloaders/pymo/__pycache__/data.cpython-310.pyc b/dataloaders/pymo/__pycache__/data.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f8ee1fd950153646a547b06997ab7a4923b90fa1
Binary files /dev/null and b/dataloaders/pymo/__pycache__/data.cpython-310.pyc differ
diff --git a/dataloaders/pymo/__pycache__/data.cpython-38.pyc b/dataloaders/pymo/__pycache__/data.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0e21f34f2ac73ab547c8e3ee741a0716229768d3
Binary files /dev/null and b/dataloaders/pymo/__pycache__/data.cpython-38.pyc differ
diff --git a/dataloaders/pymo/__pycache__/parsers.cpython-310.pyc b/dataloaders/pymo/__pycache__/parsers.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e6fa4d089bc3fc42c0e5f813a88af38aab0b82e7
Binary files /dev/null and b/dataloaders/pymo/__pycache__/parsers.cpython-310.pyc differ
diff --git a/dataloaders/pymo/__pycache__/parsers.cpython-38.pyc b/dataloaders/pymo/__pycache__/parsers.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..5fd7b42e790095e0304bfe2d6d171abf2b2a7e4d
Binary files /dev/null and b/dataloaders/pymo/__pycache__/parsers.cpython-38.pyc differ
diff --git a/dataloaders/pymo/__pycache__/preprocessing.cpython-310.pyc b/dataloaders/pymo/__pycache__/preprocessing.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..437e256e692b503b119ceed149866f8c75a7f49b
Binary files /dev/null and b/dataloaders/pymo/__pycache__/preprocessing.cpython-310.pyc differ
diff --git a/dataloaders/pymo/__pycache__/preprocessing.cpython-38.pyc b/dataloaders/pymo/__pycache__/preprocessing.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..88a4768f8d007de4b32e62874354dc3ae16b7875
Binary files /dev/null and b/dataloaders/pymo/__pycache__/preprocessing.cpython-38.pyc differ
diff --git a/dataloaders/pymo/__pycache__/rotation_tools.cpython-310.pyc b/dataloaders/pymo/__pycache__/rotation_tools.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..361b98cfa75690ed68f5a39330a39b3fa717bc1b
Binary files /dev/null and b/dataloaders/pymo/__pycache__/rotation_tools.cpython-310.pyc differ
diff --git a/dataloaders/pymo/__pycache__/rotation_tools.cpython-38.pyc b/dataloaders/pymo/__pycache__/rotation_tools.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6f6607c79dae42826f81737c479d227abeb7f93b
Binary files /dev/null and b/dataloaders/pymo/__pycache__/rotation_tools.cpython-38.pyc differ
diff --git a/dataloaders/pymo/__pycache__/viz_tools.cpython-310.pyc b/dataloaders/pymo/__pycache__/viz_tools.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4a343c349362720914fc8f9ac8ed5a5d9e6bdf28
Binary files /dev/null and b/dataloaders/pymo/__pycache__/viz_tools.cpython-310.pyc differ
diff --git a/dataloaders/pymo/__pycache__/viz_tools.cpython-38.pyc b/dataloaders/pymo/__pycache__/viz_tools.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..317a125318df8ac36572f0fd96fabeb43e484b09
Binary files /dev/null and b/dataloaders/pymo/__pycache__/viz_tools.cpython-38.pyc differ
diff --git a/dataloaders/pymo/data.py b/dataloaders/pymo/data.py
new file mode 100644
index 0000000000000000000000000000000000000000..7be4f0a819aa041218b8a3d78e700017253d277c
--- /dev/null
+++ b/dataloaders/pymo/data.py
@@ -0,0 +1,53 @@
+import numpy as np
+
+class Joint():
+ def __init__(self, name, parent=None, children=None):
+ self.name = name
+ self.parent = parent
+ self.children = children
+
+class MocapData():
+ def __init__(self):
+ self.skeleton = {}
+ self.values = None
+ self.channel_names = []
+ self.framerate = 0.0
+ self.root_name = ''
+
+ def traverse(self, j=None):
+ stack = [self.root_name]
+ while stack:
+ joint = stack.pop()
+ yield joint
+ for c in self.skeleton[joint]['children']:
+ stack.append(c)
+
+ def clone(self):
+ import copy
+ new_data = MocapData()
+ new_data.skeleton = copy.copy(self.skeleton)
+ new_data.values = copy.copy(self.values)
+ new_data.channel_names = copy.copy(self.channel_names)
+ new_data.root_name = copy.copy(self.root_name)
+ new_data.framerate = copy.copy(self.framerate)
+ return new_data
+
+ def get_all_channels(self):
+ '''Returns all of the channels parsed from the file as a 2D numpy array'''
+
+ frames = [f[1] for f in self.values]
+ return np.asarray([[channel[2] for channel in frame] for frame in frames])
+
+ def get_skeleton_tree(self):
+ tree = []
+ root_key = [j for j in self.skeleton if self.skeleton[j]['parent']==None][0]
+
+ root_joint = Joint(root_key)
+
+ def get_empty_channels(self):
+ #TODO
+ pass
+
+ def get_constant_channels(self):
+ #TODO
+ pass
diff --git a/dataloaders/pymo/features.py b/dataloaders/pymo/features.py
new file mode 100644
index 0000000000000000000000000000000000000000..fec29ed5758f79b61f296e01e9b077cba573f495
--- /dev/null
+++ b/dataloaders/pymo/features.py
@@ -0,0 +1,43 @@
+'''
+A set of mocap feature extraction functions
+
+Created by Omid Alemi | Nov 17 2017
+
+'''
+import numpy as np
+import pandas as pd
+import peakutils
+import matplotlib.pyplot as plt
+
+def get_foot_contact_idxs(signal, t=0.02, min_dist=120):
+ up_idxs = peakutils.indexes(signal, thres=t/max(signal), min_dist=min_dist)
+ down_idxs = peakutils.indexes(-signal, thres=t/min(signal), min_dist=min_dist)
+
+ return [up_idxs, down_idxs]
+
+
+def create_foot_contact_signal(mocap_track, col_name, start=1, t=0.02, min_dist=120):
+ signal = mocap_track.values[col_name].values
+ idxs = get_foot_contact_idxs(signal, t, min_dist)
+
+ step_signal = []
+
+ c = start
+ for f in range(len(signal)):
+ if f in idxs[1]:
+ c = 0
+ elif f in idxs[0]:
+ c = 1
+
+ step_signal.append(c)
+
+ return step_signal
+
+def plot_foot_up_down(mocap_track, col_name, t=0.02, min_dist=120):
+
+ signal = mocap_track.values[col_name].values
+ idxs = get_foot_contact_idxs(signal, t, min_dist)
+
+ plt.plot(mocap_track.values.index, signal)
+ plt.plot(mocap_track.values.index[idxs[0]], signal[idxs[0]], 'ro')
+ plt.plot(mocap_track.values.index[idxs[1]], signal[idxs[1]], 'go')
diff --git a/dataloaders/pymo/mocapplayer/data-template.js b/dataloaders/pymo/mocapplayer/data-template.js
new file mode 100644
index 0000000000000000000000000000000000000000..68a51392fb7d2458487eae2a00a3ed03c1e7153a
--- /dev/null
+++ b/dataloaders/pymo/mocapplayer/data-template.js
@@ -0,0 +1,3 @@
+var dataBuffer = `$$DATA$$`;
+
+start(dataBuffer);
\ No newline at end of file
diff --git a/dataloaders/pymo/mocapplayer/js/skeletonFactory.js b/dataloaders/pymo/mocapplayer/js/skeletonFactory.js
new file mode 100644
index 0000000000000000000000000000000000000000..e1d072b7df2fb40772e93f2dee595e467744e36b
--- /dev/null
+++ b/dataloaders/pymo/mocapplayer/js/skeletonFactory.js
@@ -0,0 +1,233 @@
+bm_v = new THREE.MeshPhongMaterial({
+ color: 0x08519c,
+ emissive: 0x08306b,
+ specular: 0x08519c,
+ shininess: 10,
+ side: THREE.DoubleSide
+});
+
+jm_v = new THREE.MeshPhongMaterial({
+ color: 0x08306b,
+ emissive: 0x000000,
+ specular: 0x111111,
+ shininess: 90,
+ side: THREE.DoubleSide
+});
+
+bm_a = new THREE.MeshPhongMaterial({
+ color: 0x980043,
+ emissive: 0x67001f,
+ specular: 0x6a51a3,
+ shininess: 10,
+ side: THREE.DoubleSide
+});
+
+jm_a = new THREE.MeshPhongMaterial({
+ color: 0x67001f,
+ emissive: 0x000000,
+ specular: 0x111111,
+ shininess: 90,
+ side: THREE.DoubleSide
+});
+
+bm_b = new THREE.MeshPhongMaterial({
+ color: 0x3f007d,
+ emissive: 0x3f007d,
+ specular: 0x807dba,
+ shininess: 2,
+ side: THREE.DoubleSide
+});
+
+jm_b = new THREE.MeshPhongMaterial({
+ color: 0x3f007d,
+ emissive: 0x000000,
+ specular: 0x807dba,
+ shininess: 90,
+ side: THREE.DoubleSide
+});
+
+//------------------
+
+
+jointmaterial = new THREE.MeshLambertMaterial({
+ color: 0xc57206,
+ emissive: 0x271c18,
+ side: THREE.DoubleSide,
+ // shading: THREE.FlatShading,
+ wireframe: false,
+ shininess: 90,
+});
+
+bonematerial = new THREE.MeshPhongMaterial({
+ color: 0xbd9a6d,
+ emissive: 0x271c18,
+ side: THREE.DoubleSide,
+ // shading: THREE.FlatShading,
+ wireframe: false
+});
+
+jointmaterial2 = new THREE.MeshPhongMaterial({
+ color: 0x1562a2,
+ emissive: 0x000000,
+ specular: 0x111111,
+ shininess: 30,
+ side: THREE.DoubleSide
+});
+
+bonematerial2 = new THREE.MeshPhongMaterial({
+ color: 0x552211,
+ emissive: 0x882211,
+ // emissive: 0x000000,
+ specular: 0x111111,
+ shininess: 30,
+ side: THREE.DoubleSide
+});
+
+bonematerial3 = new THREE.MeshPhongMaterial({
+ color: 0x176793,
+ emissive: 0x000000,
+ specular: 0x111111,
+ shininess: 90,
+ side: THREE.DoubleSide
+});
+
+
+
+jointmaterial4 = new THREE.MeshPhongMaterial({
+ color: 0xFF8A00,
+ emissive: 0x000000,
+ specular: 0x111111,
+ shininess: 90,
+ side: THREE.DoubleSide
+});
+
+
+bonematerial4 = new THREE.MeshPhongMaterial({
+ color: 0x53633D,
+ emissive: 0x000000,
+ specular: 0xFFC450,
+ shininess: 90,
+ side: THREE.DoubleSide
+});
+
+
+
+bonematerial44 = new THREE.MeshPhongMaterial({
+ color: 0x582A72,
+ emissive: 0x000000,
+ specular: 0xFFC450,
+ shininess: 90,
+ side: THREE.DoubleSide
+});
+
+jointmaterial5 = new THREE.MeshPhongMaterial({
+ color: 0xAA5533,
+ emissive: 0x000000,
+ specular: 0x111111,
+ shininess: 30,
+ side: THREE.DoubleSide
+});
+
+bonematerial5 = new THREE.MeshPhongMaterial({
+ color: 0x552211,
+ emissive: 0x772211,
+ specular: 0x111111,
+ shininess: 30,
+ side: THREE.DoubleSide
+});
+
+
+markermaterial = new THREE.MeshPhongMaterial({
+ color: 0xc57206,
+ emissive: 0x271c18,
+ side: THREE.DoubleSide,
+ // shading: THREE.FlatShading,
+ wireframe: false,
+ shininess: 20,
+});
+
+markermaterial2 = new THREE.MeshPhongMaterial({
+ color: 0x1562a2,
+ emissive: 0x271c18,
+ side: THREE.DoubleSide,
+ // shading: THREE.FlatShading,
+ wireframe: false,
+ shininess: 20,
+});
+
+markermaterial3 = new THREE.MeshPhongMaterial({
+ color: 0x555555,
+ emissive: 0x999999,
+ side: THREE.DoubleSide,
+ // shading: THREE.FlatShading,
+ wireframe: false,
+ shininess: 20,
+});
+
+
+var makeMarkerGeometry_Sphere10 = function(markerName, scale) {
+ return new THREE.SphereGeometry(10, 60, 60);
+};
+
+var makeMarkerGeometry_Sphere3 = function(markerName, scale) {
+ return new THREE.SphereGeometry(3, 60, 60);
+};
+
+var makeMarkerGeometry_SphereX = function(markerName, scale) {
+ return new THREE.SphereGeometry(5, 60, 60);
+};
+
+var makeJointGeometry_SphereX = function(X) {
+ return function(jointName, scale) {
+ return new THREE.SphereGeometry(X, 60, 60);
+ };
+};
+
+
+var makeJointGeometry_Sphere1 = function(jointName, scale) {
+ return new THREE.SphereGeometry(2 / scale, 60, 60);
+};
+
+var makeJointGeometry_Sphere2 = function(jointName, scale) {
+ return new THREE.SphereGeometry(1 / scale, 60, 60);
+};
+
+var makeJointGeometry_Dode = function(jointName, scale) {
+ return new THREE.DodecahedronGeometry(1 / scale, 0);
+};
+
+var makeBoneGeometry_Cylinder1 = function(joint1Name, joint2Name, length, scale) {
+ return new THREE.CylinderGeometry(1.5 / scale, 0.7 / scale, length, 40);
+};
+
+var makeBoneGeometry_Cylinder2 = function(joint1Name, joint2Name, length, scale) {
+ // if (joint1Name.includes("LeftHip"))
+ // length = 400;
+ return new THREE.CylinderGeometry(1.5 / scale, 0.2 / scale, length, 40);
+};
+
+var makeBoneGeometry_Cylinder3 = function(joint1Name, joint2Name, length, scale) {
+ var c1 = new THREE.CylinderGeometry(1.5 / scale, 0.2 / scale, length / 1, 20);
+ var c2 = new THREE.CylinderGeometry(0.2 / scale, 1.5 / scale, length / 1, 40);
+
+ var material = new THREE.MeshPhongMaterial({
+ color: 0xF7FE2E
+ });
+ var mmesh = new THREE.Mesh(c1, material);
+ mmesh.updateMatrix();
+ c2.merge(mmesh.geometry, mmesh.matrix);
+ return c2;
+};
+
+var makeBoneGeometry_Box1 = function(joint1Name, joint2Name, length, scale) {
+ return new THREE.BoxGeometry(1 / scale, length, 1 / scale, 40);
+};
+
+
+var makeJointGeometry_Empty = function(jointName, scale) {
+ return new THREE.SphereGeometry(0.001, 60, 60);
+};
+
+var makeBoneGeometry_Empty = function(joint1Name, joint2Name, length, scale) {
+ return new THREE.CylinderGeometry(0.001, 0.001, 0.001, 40);
+};
diff --git a/dataloaders/pymo/mocapplayer/libs/jquery.min.js b/dataloaders/pymo/mocapplayer/libs/jquery.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..b8c4187de18dd413ad3029839ce0773549e92a14
--- /dev/null
+++ b/dataloaders/pymo/mocapplayer/libs/jquery.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v2.2.3 | (c) jQuery Foundation | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="2.2.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isPlainObject:function(a){var b;if("object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype||{},"isPrototypeOf"))return!1;for(b in a);return void 0===b||k.call(a,b)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=d.createElement("script"),b.text=a,d.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:h.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(d=e.call(arguments,2),f=function(){return a.apply(b||this,d.concat(e.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML=" ",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML=" ","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML=" ",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return h.call(b,a)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&f.parentNode&&(this.length=1,this[0]=f),this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?void 0!==c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?h.call(n(a),this[0]):h.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||n.uniqueSort(e),D.test(a)&&e.reverse()),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.removeEventListener("DOMContentLoaded",J),a.removeEventListener("load",J),n.ready()}n.ready.promise=function(b){return I||(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(n.ready):(d.addEventListener("DOMContentLoaded",J),a.addEventListener("load",J))),I.promise(b)},n.ready.promise();var K=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)K(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},L=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function M(){this.expando=n.expando+M.uid++}M.uid=1,M.prototype={register:function(a,b){var c=b||{};return a.nodeType?a[this.expando]=c:Object.defineProperty(a,this.expando,{value:c,writable:!0,configurable:!0}),a[this.expando]},cache:function(a){if(!L(a))return{};var b=a[this.expando];return b||(b={},L(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[b]=c;else for(d in b)e[d]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=a[this.expando];if(void 0!==f){if(void 0===b)this.register(a);else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in f?d=[b,e]:(d=e,d=d in f?[d]:d.match(G)||[])),c=d.length;while(c--)delete f[d[c]]}(void 0===b||n.isEmptyObject(f))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!n.isEmptyObject(b)}};var N=new M,O=new M,P=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Q=/[A-Z]/g;function R(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Q,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:P.test(c)?n.parseJSON(c):c;
+}catch(e){}O.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return O.hasData(a)||N.hasData(a)},data:function(a,b,c){return O.access(a,b,c)},removeData:function(a,b){O.remove(a,b)},_data:function(a,b,c){return N.access(a,b,c)},_removeData:function(a,b){N.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=O.get(f),1===f.nodeType&&!N.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),R(f,d,e[d])));N.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){O.set(this,a)}):K(this,function(b){var c,d;if(f&&void 0===b){if(c=O.get(f,a)||O.get(f,a.replace(Q,"-$&").toLowerCase()),void 0!==c)return c;if(d=n.camelCase(a),c=O.get(f,d),void 0!==c)return c;if(c=R(f,d,void 0),void 0!==c)return c}else d=n.camelCase(a),this.each(function(){var c=O.get(this,d);O.set(this,d,b),a.indexOf("-")>-1&&void 0!==c&&O.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){O.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=N.get(a,b),c&&(!d||n.isArray(c)?d=N.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return N.get(a,c)||N.access(a,c,{empty:n.Callbacks("once memory").add(function(){N.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length",""],thead:[1,""],col:[2,""],tr:[2,""],td:[3,""],_default:[0,"",""]};$.optgroup=$.option,$.tbody=$.tfoot=$.colgroup=$.caption=$.thead,$.th=$.td;function _(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function aa(a,b){for(var c=0,d=a.length;d>c;c++)N.set(a[c],"globalEval",!b||N.get(b[c],"globalEval"))}var ba=/<|?\w+;/;function ca(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],o=0,p=a.length;p>o;o++)if(f=a[o],f||0===f)if("object"===n.type(f))n.merge(m,f.nodeType?[f]:f);else if(ba.test(f)){g=g||l.appendChild(b.createElement("div")),h=(Y.exec(f)||["",""])[1].toLowerCase(),i=$[h]||$._default,g.innerHTML=i[1]+n.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;n.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",o=0;while(f=m[o++])if(d&&n.inArray(f,d)>-1)e&&e.push(f);else if(j=n.contains(f.ownerDocument,f),g=_(l.appendChild(f),"script"),j&&aa(g),c){k=0;while(f=g[k++])Z.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ja(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ha;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,la=/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+