├── .gitignore ├── LICENSE ├── README.md ├── dataset └── .gitkeep ├── human_3d_pose_baseline ├── __init__.py ├── configs │ ├── __init__.py │ ├── defaults.py │ └── load_config.py ├── datasets │ ├── __init__.py │ └── human36m.py ├── engines │ └── __init__.py ├── evaluators │ ├── __init__.py │ └── evaluator.py ├── models │ ├── __init__.py │ └── baseline_model.py ├── solvers │ └── __init__.py └── utils │ ├── __init__.py │ ├── camera_utils.py │ ├── cuda.py │ ├── data_utils.py │ ├── procrustes.py │ └── vis_utils.py ├── notebooks ├── visualize_2d_pose.ipynb └── visualize_3d_pose.ipynb ├── requirements.txt └── tools ├── _init_path.py ├── test.py └── train.py /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/macos,python,virtualenv,jupyternotebooks,visualstudiocode 3 | # Edit at https://www.gitignore.io/?templates=macos,python,virtualenv,jupyternotebooks,visualstudiocode 4 | 5 | ### JupyterNotebooks ### 6 | # gitignore template for Jupyter Notebooks 7 | # website: http://jupyter.org/ 8 | 9 | .ipynb_checkpoints 10 | */.ipynb_checkpoints/* 11 | 12 | # IPython 13 | profile_default/ 14 | ipython_config.py 15 | 16 | # Remove previous ipynb_checkpoints 17 | # git rm -r .ipynb_checkpoints/ 18 | 19 | ### macOS ### 20 | # General 21 | .DS_Store 22 | .AppleDouble 23 | .LSOverride 24 | 25 | # Icon must end with two \r 26 | Icon 27 | 28 | # Thumbnails 29 | ._* 30 | 31 | # Files that might appear in the root of a volume 32 | .DocumentRevisions-V100 33 | .fseventsd 34 | .Spotlight-V100 35 | .TemporaryItems 36 | .Trashes 37 | .VolumeIcon.icns 38 | .com.apple.timemachine.donotpresent 39 | 40 | # Directories potentially created on remote AFP share 41 | .AppleDB 42 | .AppleDesktop 43 | Network Trash Folder 44 | Temporary Items 45 | .apdisk 46 | 47 | ### Python ### 48 | # Byte-compiled / optimized / DLL files 49 | __pycache__/ 50 | *.py[cod] 51 | *$py.class 52 | 53 | # C extensions 54 | *.so 55 | 56 | # Distribution / packaging 57 | .Python 58 | build/ 59 | develop-eggs/ 60 | dist/ 61 | downloads/ 62 | eggs/ 63 | .eggs/ 64 | lib/ 65 | lib64/ 66 | parts/ 67 | sdist/ 68 | var/ 69 | wheels/ 70 | pip-wheel-metadata/ 71 | share/python-wheels/ 72 | *.egg-info/ 73 | .installed.cfg 74 | *.egg 75 | MANIFEST 76 | 77 | # PyInstaller 78 | # Usually these files are written by a python script from a template 79 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 80 | *.manifest 81 | *.spec 82 | 83 | # Installer logs 84 | pip-log.txt 85 | pip-delete-this-directory.txt 86 | 87 | # Unit test / coverage reports 88 | htmlcov/ 89 | .tox/ 90 | .nox/ 91 | .coverage 92 | .coverage.* 93 | .cache 94 | nosetests.xml 95 | coverage.xml 96 | *.cover 97 | .hypothesis/ 98 | .pytest_cache/ 99 | 100 | # Translations 101 | *.mo 102 | *.pot 103 | 104 | # Scrapy stuff: 105 | .scrapy 106 | 107 | # Sphinx documentation 108 | docs/_build/ 109 | 110 | # PyBuilder 111 | target/ 112 | 113 | # pyenv 114 | .python-version 115 | 116 | # pipenv 117 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 118 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 119 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 120 | # install all needed dependencies. 121 | #Pipfile.lock 122 | 123 | # celery beat schedule file 124 | celerybeat-schedule 125 | 126 | # SageMath parsed files 127 | *.sage.py 128 | 129 | # Spyder project settings 130 | .spyderproject 131 | .spyproject 132 | 133 | # Rope project settings 134 | .ropeproject 135 | 136 | # Mr Developer 137 | .mr.developer.cfg 138 | .project 139 | .pydevproject 140 | 141 | # mkdocs documentation 142 | /site 143 | 144 | # mypy 145 | .mypy_cache/ 146 | .dmypy.json 147 | dmypy.json 148 | 149 | # Pyre type checker 150 | .pyre/ 151 | 152 | ### VirtualEnv ### 153 | # Virtualenv 154 | # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ 155 | pyvenv.cfg 156 | .env 157 | .venv 158 | env/ 159 | venv/ 160 | ENV/ 161 | env.bak/ 162 | venv.bak/ 163 | pip-selfcheck.json 164 | 165 | ### VisualStudioCode ### 166 | .vscode/* 167 | #!.vscode/settings.json 168 | #!.vscode/tasks.json 169 | #!.vscode/launch.json 170 | #!.vscode/extensions.json 171 | 172 | ### VisualStudioCode Patch ### 173 | # Ignore all local history of files 174 | .history 175 | 176 | # End of https://www.gitignore.io/api/macos,python,virtualenv,jupyternotebooks,visualstudiocode 177 | 178 | /dataset/h36m 179 | /dataset/h36m.zip 180 | 181 | /results -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Motoki Kimura 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 3d-pose-baseline-pytorch 2 | 3 | PyTorch implementation of [*A simple yet effective baseline for 3d human pose estimation [Martinez+, ICCV'17]*](https://arxiv.org/abs/1705.03098). 4 | 5 | Todo: 6 | - [ ] Provide trained weight 7 | - [ ] Provide tutorials to predict 3D pose from 2D pose input 8 | - [ ] Train models on Stacked Hourglass output 9 | 10 | ## Performance 11 | 12 | ### Protocol #1 (no rigid alignment in post-processing) 13 | 14 | MPJPE [mm]: 15 | | | Avg | Direct | Discuss | Eating | Greet | Phone | Photo | Pose | Purch | Sitting | SittingD | Smoke | Wait | WalkD | Walk | WalkT | 16 | | :-------- | --------: | --------:| :------: |--------: | --------:| :------: |--------: | --------:| :------: |--------: | --------:| ------: |--------: | --------:| ------: |------: | 17 | | Paper | 45.5 | 37.7 | 44.4 | 40.3 | 42.1 | 48.2 | 54.9 | 44.4 | 42.1 | 54.6 | 58.0 | 45.1 | 46.4 | 47.6 | 36.4 | 40.4 | 18 | | This repo | 43.3 | 35.7 | 41.6 | 40.1 | 40.4 | 45.0 | 52.0 | 42.9 | 38.0 | 53.2 | 55.4 | 43.5 | 43.3 | 43.3 | 33.7 | 35.6 | 19 | 20 | Both were trained on GT 2D pose input from multiple actions. 21 | 22 | ## Preparation 23 | 24 | ### Human3.6M dataset 25 | 26 | Get `h36m.zip` by following [author's repo](https://github.com/una-dinosauria/3d-pose-baseline), place it under `dataset`, and unzip it. 27 | 28 | ``` 29 | $ cd dataset 30 | $ unzip h36m.zip 31 | ``` 32 | 33 | ### Install dependencies 34 | 35 | ``` 36 | $ pip install -r requirements.txt 37 | ``` 38 | 39 | ## Usage 40 | 41 | ### Train model 42 | 43 | ``` 44 | $ ./tools/train.py OUTPUT_DIR ./output 45 | ``` 46 | 47 | You'll find trained weight and tensorboard event file under `./output` directory. 48 | 49 | ### Evaluate model 50 | 51 | ``` 52 | $ ./tools/test.py OUTPUT_DIR ./output MODEL.WEIGHT ${PATH_TO_WEIGHT} 53 | ``` 54 | 55 | You'll find evaluation results in a JSON file under `./output` directory. 56 | 57 | ## Paper 58 | 59 | **A simple yet effective baseline for 3d human pose estimation** 60 | 61 | *Julieta Martinez, Rayat Hossain, Javier Romero, James J. Little* 62 | 63 | [[Paper]](https://arxiv.org/abs/1705.03098)[[Author's implementation]](https://github.com/una-dinosauria/3d-pose-baseline) 64 | 65 | ``` 66 | @inproceedings{martinez_2017_3dbaseline, 67 | title={A simple yet effective baseline for 3d human pose estimation}, 68 | author={Martinez, Julieta and Hossain, Rayat and Romero, Javier and Little, James J.}, 69 | booktitle={ICCV}, 70 | year={2017} 71 | } 72 | ``` -------------------------------------------------------------------------------- /dataset/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/motokimura/3d-pose-baseline-pytorch/7d5e599076a90b8d4fe0a53455231258b035837c/dataset/.gitkeep -------------------------------------------------------------------------------- /human_3d_pose_baseline/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/motokimura/3d-pose-baseline-pytorch/7d5e599076a90b8d4fe0a53455231258b035837c/human_3d_pose_baseline/__init__.py -------------------------------------------------------------------------------- /human_3d_pose_baseline/configs/__init__.py: -------------------------------------------------------------------------------- 1 | from .load_config import load_config 2 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/configs/defaults.py: -------------------------------------------------------------------------------- 1 | # references: 2 | # https://github.com/una-dinosauria/3d-pose-baseline/blob/master/src/predict_3dpose.py#L27-L60 3 | # https://github.com/weigq/3d_pose_baseline_pytorch/blob/master/opt.py 4 | 5 | from yacs.config import CfgNode as CN 6 | 7 | _C = CN() 8 | 9 | # Input data. 10 | _C.DATA = CN() 11 | _C.DATA.HM36M_DIR = "dataset/h36m" 12 | _C.DATA.POSE_IN_CAMERA_FRAME = True # Learn 3d poses in camera coordinates. 13 | _C.DATA.ACTIONS = [] # Actions to load. If empty, load all actions. 14 | 15 | # Dataloader. 16 | _C.LOADER = CN() 17 | _C.LOADER.TRAIN_BATCHSIZE = 64 18 | _C.LOADER.TRAIN_NUM_WORKERS = 8 19 | _C.LOADER.TEST_BATCHSIZE = 64 20 | _C.LOADER.TEST_NUM_WORKERS = 8 21 | 22 | # Model architecture. 23 | _C.MODEL = CN() 24 | _C.MODEL.LINEAR_SIZE = 1024 25 | _C.MODEL.NUM_STAGES = 2 26 | _C.MODEL.DROPOUT_PROB = 0.5 27 | _C.MODEL.PREDICT_14 = False 28 | _C.MODEL.WEIGHT = "" 29 | 30 | # Model optimization settings. 31 | _C.SOLVER = CN() 32 | _C.SOLVER.EPOCHS = 200 33 | _C.SOLVER.LR = 1e-3 34 | _C.SOLVER.LR_DECAY_STEP = 100000 35 | _C.SOLVER.LR_DECAY_GAMMA = 0.96 36 | 37 | # Model evaluation settings. 38 | _C.EVAL = CN() 39 | _C.EVAL.METRICS_TO_LOG = [ 40 | "MPJPE", 41 | "MPJPE/Directions", 42 | "MPJPE/Discussion", 43 | "MPJPE/Eating", 44 | "MPJPE/Greeting", 45 | "MPJPE/Phoning", 46 | "MPJPE/Photo", 47 | "MPJPE/Posing", 48 | "MPJPE/Purchases", 49 | "MPJPE/Sitting", 50 | "MPJPE/SittingDown", 51 | "MPJPE/Smoking", 52 | "MPJPE/Waiting", 53 | "MPJPE/WalkDog", 54 | "MPJPE/Walking", 55 | "MPJPE/WalkTogether", 56 | ] 57 | _C.EVAL.APPLY_PROCRUSTES_ALIGNMENT = False 58 | 59 | # Misc. 60 | _C.OUTPUT_DIR = "./results" 61 | _C.USE_CUDA = True 62 | 63 | 64 | def get_default_config(): 65 | """Get default configutation. 66 | 67 | Returns: 68 | (yacs.config.CfgNode): Default configuration. 69 | """ 70 | return _C.clone() 71 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/configs/load_config.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | from yacs.config import CfgNode as CN 4 | 5 | from .defaults import get_default_config 6 | 7 | 8 | def load_config(): 9 | """Load configuration. 10 | 11 | Returns: 12 | (yacs.config.CfgNode): Configuration. 13 | """ 14 | parser = argparse.ArgumentParser() 15 | parser.add_argument("--config", help="Path to YAML config file", type=str) 16 | parser.add_argument( 17 | "opts", 18 | default=None, 19 | help="parameter name and value pairs", 20 | nargs=argparse.REMAINDER, 21 | ) 22 | args = parser.parse_args() 23 | 24 | config = get_default_config() 25 | if args.config: 26 | # Overwrite hyper parameters with the ones given by the YAML file. 27 | config.merge_from_file(args.config) 28 | if args.opts: 29 | # Overwrite hyper parameters with the ones given by command line args. 30 | config.merge_from_list(args.opts) 31 | config.freeze() 32 | 33 | print("Successfully loaded config:") 34 | print(config) 35 | 36 | return config 37 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/datasets/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from torch.utils.data import DataLoader 4 | 5 | from ..utils import camera_utils, data_utils 6 | from .human36m import Human36M 7 | 8 | 9 | def get_dataset(config): 10 | """Get Human3.6M dataset. 11 | 12 | Args: 13 | config (yacs.config.CfgNode): Configuration. 14 | 15 | Returns: 16 | (Human36MDatasetHandler): Human3.6M dataset. 17 | """ 18 | return Human36M_DatasetHandler(config) 19 | 20 | 21 | class Human36M_DatasetHandler: 22 | def __init__(self, config): 23 | """ 24 | 25 | Args: 26 | config (yacs.config.CfgNode): Configuration. 27 | """ 28 | # Define actions. 29 | self.actions = self._get_actions(config) 30 | 31 | # Load Human3.6M camera parameters. 32 | self.cams = camera_utils.load_cameras( 33 | os.path.join(config.DATA.HM36M_DIR, "cameras.h5") 34 | ) 35 | 36 | # Load Human3.6M 3d poses. 37 | print("Loading 3d poses...") 38 | ( 39 | self.poses_3d_train, 40 | self.poses_3d_test, 41 | self.mean_3d, 42 | self.std_3d, 43 | self.dim_to_ignore_3d, 44 | self.dim_to_use_3d, 45 | self.train_root_positions, 46 | self.test_root_positions, 47 | ) = data_utils.read_3d_data( 48 | self.actions, 49 | config.DATA.HM36M_DIR, 50 | self.cams, 51 | camera_frame=config.DATA.POSE_IN_CAMERA_FRAME, 52 | predict_14=config.MODEL.PREDICT_14, 53 | ) 54 | print("Done!") 55 | 56 | # Load Human3.6M 2d poses. 57 | print("Loading 2d poses...") 58 | ( 59 | self.poses_2d_train, 60 | self.poses_2d_test, 61 | self.mean_2d, 62 | self.std_2d, 63 | self.dim_to_ignore_2d, 64 | self.dim_to_use_2d, 65 | ) = data_utils.create_2d_data(self.actions, config.DATA.HM36M_DIR, self.cams) 66 | print("Done!") 67 | 68 | # Create pytorch dataloaders for train and test set. 69 | self.train_dataloader = self._get_dataloaders( 70 | config, self.poses_2d_train, self.poses_3d_train, is_train=True 71 | ) 72 | 73 | self.test_dataloader = self._get_dataloaders( 74 | config, self.poses_2d_test, self.poses_3d_test, is_train=False 75 | ) 76 | 77 | # Private members. 78 | 79 | def _get_actions(self, config): 80 | actions = config.DATA.ACTIONS 81 | if len(actions) == 0: 82 | # If empty, load all actions. 83 | actions = data_utils.H36M_ACTIONS 84 | else: 85 | # Check if the specified actions are valid. 86 | for act in actions: 87 | assert act in data_utils.H36M_ACTIONS, f"Unrecognized action: {act}." 88 | return actions 89 | 90 | def _get_dataloaders(self, config, pose_set_2d, pose_set_3d, is_train): 91 | # Create pytorch dataset. 92 | dataset = Human36M( 93 | pose_set_2d, pose_set_3d, camera_frame=config.DATA.POSE_IN_CAMERA_FRAME 94 | ) 95 | 96 | # Create pytorch dataloader. 97 | if is_train: 98 | batch_size = config.LOADER.TRAIN_BATCHSIZE 99 | num_workers = config.LOADER.TRAIN_NUM_WORKERS 100 | shuffle = True 101 | else: 102 | batch_size = config.LOADER.TEST_BATCHSIZE 103 | num_workers = config.LOADER.TEST_NUM_WORKERS 104 | shuffle = False 105 | 106 | dataloader = DataLoader( 107 | dataset, 108 | batch_size=batch_size, 109 | shuffle=shuffle, 110 | num_workers=num_workers, 111 | pin_memory=True, 112 | ) 113 | 114 | return dataloader 115 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/datasets/human36m.py: -------------------------------------------------------------------------------- 1 | # references: 2 | # https://github.com/weigq/3d_pose_baseline_pytorch/blob/master/src/datasets/human36m.py 3 | # https://github.com/una-dinosauria/3d-pose-baseline/blob/master/src/linear_model.py#L247 4 | 5 | import numpy as np 6 | import torch 7 | from torch.utils.data import Dataset 8 | 9 | 10 | class Human36M(Dataset): 11 | def __init__(self, pose_set_2d, pose_set_3d, camera_frame=True): 12 | """ 13 | 14 | Args: 15 | pose_set_2d (dict[tuple, numpy.array]): 2d pose set. 16 | pose_set_3d (dict[tuple, numpy.array]): 3d pose set. 17 | camera_frame (bool, optional): Make this True if pose_set_3d is in camera coordinates. Defaults to True. 18 | """ 19 | self.poses_2d = [] 20 | self.poses_3d = [] 21 | self.actions = [] 22 | 23 | for key2d in pose_set_2d.keys(): 24 | subj, act, seqname = key2d 25 | # Keys should be the same if 3d poses are in camera frame. 26 | key3d = ( 27 | key2d 28 | if camera_frame 29 | else (subj, act, "{}.h5".format(seqname.split(".")[0])) 30 | ) 31 | 32 | poses_2d = pose_set_2d[key2d] # [n, 16 x 2] 33 | poses_3d = pose_set_3d[key3d] # [n, n_joints x 3] 34 | assert len(poses_2d) == len(poses_3d) 35 | actions = [act] * len(poses_2d) # [n,] 36 | 37 | self.poses_2d.append(poses_2d) 38 | self.poses_3d.append(poses_3d) 39 | self.actions.extend(actions) 40 | 41 | self.poses_2d = np.vstack(self.poses_2d) # [N, 16 x 2] 42 | self.poses_3d = np.vstack(self.poses_3d) # [N, n_joints x 3] 43 | self.actions = np.array(self.actions) # [N,] 44 | 45 | assert len(self.poses_2d) == len(self.poses_3d) == len(self.actions) 46 | 47 | def __getitem__(self, idx): 48 | """Get a set of 2d pose, 3d pose, and action. 49 | 50 | Args: 51 | idx (int): Index of the 2d/3d pose pair to get. 52 | 53 | Returns: 54 | (dict): a set of 2d pose, 3d pose, and action. 55 | pose_2d (torch.Tensor): 2d pose (model input). 56 | pose_3d (torch.Tensor): 3d pose (model output i.e., label). 57 | action (str): Action to which the pose pair belongs. 58 | """ 59 | pose_2d = torch.from_numpy(self.poses_2d[idx]).float() 60 | pose_3d = torch.from_numpy(self.poses_3d[idx]).float() 61 | action = self.actions[idx] 62 | 63 | return {"pose_2d": pose_2d, "pose_3d": pose_3d, "action": action} 64 | 65 | def __len__(self): 66 | """Return the number of the samples. 67 | 68 | Returns: 69 | (int): Number of the samples. 70 | """ 71 | return len(self.poses_2d) 72 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/engines/__init__.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from tqdm import tqdm 3 | 4 | from ..evaluators import get_evaluator 5 | 6 | 7 | def train_epoch(config, model, criterion, optimizer, lr_scheduler, human36m, device): 8 | """Train the model for an epoch. 9 | 10 | Args: 11 | config (yacs.config.CfgNode): Configuration. 12 | model (torch.nn.Module): Model to train. 13 | criterion (torch.nn.Module): Loss function. 14 | optimizer (torch.optimizer): Optimizer for training 15 | lr_scheduler (torch.lr_sceduler): Learning scheduler for training. 16 | human36m (Human36MDatasetHandler): Human3.6M dataset. 17 | device (torch.device): CUDA device to use for training. 18 | 19 | Returns: 20 | (dict): training results. 21 | """ 22 | model.train() 23 | 24 | sum_loss, num_samples = 0, 0 25 | 26 | for batch in tqdm(human36m.train_dataloader): 27 | data = batch["pose_2d"].to(device) 28 | target = batch["pose_3d"].to(device) 29 | optimizer.zero_grad() 30 | output = model(data) 31 | loss = criterion(output, target) 32 | loss.backward() 33 | optimizer.step() 34 | lr_scheduler.step() 35 | 36 | batch_size = len(data) 37 | sum_loss += loss.item() * batch_size 38 | num_samples += batch_size 39 | 40 | average_loss = sum_loss / num_samples 41 | metrics = {"loss": average_loss} 42 | 43 | return metrics 44 | 45 | 46 | def test_epoch(config, model, criterion, human36m, device): 47 | """Evaluate the model. 48 | 49 | Args: 50 | config (yacs.config.CfgNode): Configuration. 51 | model (torch.nn.Module): Model to test. 52 | criterion (torch.nn.Module): Loss function. 53 | human36m (Human36MDatasetHandler): Human3.6M dataset. 54 | device (torch.device): CUDA device to use for training. 55 | 56 | Returns: 57 | (dict): evaluation results. 58 | """ 59 | evaluator = get_evaluator(config, human36m) # Joint error evaluator. 60 | 61 | model.eval() 62 | 63 | sum_loss, num_samples = 0, 0 64 | 65 | with torch.no_grad(): 66 | for batch in tqdm(human36m.test_dataloader): 67 | data = batch["pose_2d"].to(device) 68 | target = batch["pose_3d"].to(device) 69 | output = model(data) 70 | loss = criterion(output, target) 71 | 72 | batch_size = len(data) 73 | sum_loss += loss.item() * batch_size 74 | num_samples += batch_size 75 | 76 | # Joint error evaluation. 77 | action = batch["action"] # Used for per action evaluation. 78 | evaluator.add_samples( 79 | pred_3d_poses=output.data.cpu().numpy(), 80 | truth_3d_poses=target.data.cpu().numpy(), 81 | actions=action, 82 | ) 83 | 84 | metrics = evaluator.get_metrics() 85 | 86 | # Add average test loss to the metric dictionary. 87 | average_loss = sum_loss / num_samples 88 | assert "loss" not in metrics 89 | metrics["loss"] = average_loss 90 | 91 | return metrics 92 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/evaluators/__init__.py: -------------------------------------------------------------------------------- 1 | from .evaluator import Human36M_JointErrorEvaluator 2 | 3 | 4 | def get_evaluator(config, human36m): 5 | """Get Human3.6M joint error evaluator. 6 | 7 | Args: 8 | config (yacs.config.CfgNode): Configuration. 9 | human36m (Human36MDatasetHandler): Human3.6M dataset. 10 | 11 | Returns: 12 | Human36M_JointErrorEvaluator: Human3.6M joint error evaluator. 13 | """ 14 | evaluator = Human36M_JointErrorEvaluator( 15 | human36m, 16 | predict_14=config.MODEL.PREDICT_14, 17 | apply_procrustes_alignment=config.EVAL.APPLY_PROCRUSTES_ALIGNMENT, 18 | ) 19 | return evaluator 20 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/evaluators/evaluator.py: -------------------------------------------------------------------------------- 1 | # references: 2 | # https://github.com/una-dinosauria/3d-pose-baseline/blob/master/src/predict_3dpose.py#L305 3 | 4 | import numpy as np 5 | 6 | from ..utils import data_utils, procrustes 7 | 8 | 9 | class Human36M_JointErrorEvaluator: 10 | def __init__(self, human36m, predict_14=False, apply_procrustes_alignment=False): 11 | """ 12 | 13 | Args: 14 | human36m (Human36MDatasetHandler): Human3.6M dataset. 15 | predict_14 (bool, optional): Whether to predict 14 3d-joints. Defaults to False. 16 | apply_procrustes_alignment (bool, optional): Whether to apply procrustes alignment to the predicted poses. 17 | """ 18 | self.human36m = human36m 19 | self.predict_14 = predict_14 20 | self.apply_procrustes_alignment = apply_procrustes_alignment 21 | 22 | self.n_joints = ( 23 | 14 if self.predict_14 else 17 24 | ) # 17 = predicted 16 joints + root (Hip joint) 25 | 26 | self.reset() 27 | 28 | def reset(self): 29 | """Remove all samples added so far. 30 | """ 31 | self.joint_distances = [] 32 | self.actions = [] 33 | 34 | def add_samples(self, pred_3d_poses, truth_3d_poses, actions): 35 | """Add pairs of predicted and ground-truth poses to evaluate. 36 | 37 | Args: 38 | pred_3d_poses (numpy.array): Predicted 3d poses (normalized). `[batch_size, n_joints, 3]`. 39 | truth_3d_poses (numpy.array): Ground-truth 3d poses (normalized). `[batch_size, n_joints, 3]`. 40 | actions (list[str]): Actions to which the poses belong. 41 | """ 42 | # Compute distances of corresponding joints of pred/truth poses. 43 | pred = self._preprocess_poses(pred_3d_poses) # [batch_size, n_joints x 3] 44 | truth = self._preprocess_poses(truth_3d_poses) # [batch_size, n_joints x 3] 45 | 46 | if self.apply_procrustes_alignment: 47 | pred = self._apply_procrustes_alignment( 48 | sources=pred, targets=truth 49 | ) # [batch_size, n_joints x 3] 50 | 51 | d = self._compute_joint_distances(pred, truth) # [batch_size, n_joints] 52 | self.joint_distances.append(d) 53 | 54 | # Cache action of each frame for per action evaluation. 55 | self.actions.extend(actions) 56 | 57 | def get_metrics(self): 58 | """Get evaluation results. 59 | 60 | Returns: 61 | (dict): evaluation results. 62 | """ 63 | joint_distances = np.vstack(self.joint_distances) # [N, n_joints] 64 | actions = np.array(self.actions) # [N,] 65 | assert len(joint_distances) == len(actions) 66 | 67 | # Evaluate joint position errors over all actions. 68 | mpjpe = np.mean(joint_distances) # mean per joint position error: float 69 | pjpe = np.mean(joint_distances, axis=0) # per joint position error: [n_joints,] 70 | metrics = { 71 | "MPJPE": mpjpe, 72 | "PJPE": pjpe.tolist(), 73 | } 74 | 75 | # Evaluate joint position error per action. 76 | for action in data_utils.H36M_ACTIONS: 77 | mask = actions == action 78 | if np.sum(mask) == 0: # In case no sample is found in the action, 79 | mpjpe = pjpe = -1 # set errors as -1. 80 | print("Warining: no test sample was found in the action: {action}. ") 81 | else: 82 | joint_distances_masked = joint_distances[mask] 83 | mpjpe = np.mean(joint_distances_masked) 84 | pjpe = np.mean(joint_distances_masked, axis=0) 85 | 86 | metrics["MPJPE/{}".format(action)] = mpjpe 87 | metrics["PJPE/{}".format(action)] = pjpe.tolist() 88 | 89 | return metrics 90 | 91 | def _preprocess_poses(self, poses_3d): 92 | mean_3d = self.human36m.mean_3d 93 | std_3d = self.human36m.std_3d 94 | dim_to_ignore_3d = self.human36m.dim_to_ignore_3d 95 | dim_to_use_3d = self.human36m.dim_to_use_3d 96 | 97 | # Unnormalize 3d poses. 98 | poses = data_utils.unnormalize_data( 99 | poses_3d, mean_3d, std_3d, dim_to_ignore_3d 100 | ) # [batch_size, 32 x 3] 101 | 102 | # Keep only the relevant joints. 103 | dim_to_keep = ( 104 | dim_to_use_3d 105 | if self.predict_14 106 | else np.hstack([np.arange(3), dim_to_use_3d]) 107 | # Add root (Hip joint) if the model predicts 16 joints. 108 | # XXX: Assuming the first 3 values represent root joint 3d position. 109 | ) 110 | poses = poses[:, dim_to_keep] # [batch_size, n_joints x 3] 111 | 112 | return poses 113 | 114 | def _apply_procrustes_alignment(self, sources, targets): 115 | sources_aligned = [] 116 | 117 | batch_size = len(sources) 118 | for i in range(batch_size): 119 | target = targets[i].reshape(-1, 3) # [n_joints, 3] 120 | source = sources[i].reshape(-1, 3) # [n_joints, 3] 121 | _, _, T, b, c = procrustes.compute_similarity_transform( 122 | target, source, compute_optimal_scale=True 123 | ) 124 | aligned = (b * source.dot(T)) + c 125 | aligned = aligned.reshape((-1, self.n_joints * 3)) # [1, n_joints x 3] 126 | 127 | sources_aligned.append(aligned) 128 | 129 | return np.vstack(sources_aligned) # [batch_size, n_joints x 3] 130 | 131 | def _compute_joint_distances(self, pred, truth): 132 | # Compute Euclidean distance error per joint. 133 | d_squared = (pred - truth) ** 2 # [batch_size, n_joints x 3] 134 | d_squared = d_squared.reshape( 135 | (-1, self.n_joints, 3) 136 | ) # [batch_size, n_joints, 3] 137 | d_squared = np.sum(d_squared, axis=2) # [batch_size, n_joints] 138 | d = np.sqrt(d_squared) # [batch_size, n_joints] 139 | 140 | return d 141 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/models/__init__.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from ..utils.cuda import get_device 4 | from .baseline_model import BaselineModel 5 | 6 | 7 | def get_model(config): 8 | """Get model. 9 | 10 | Args: 11 | config (yacs.config.CfgNode): Configuration. 12 | 13 | Returns: 14 | (torch.nn.Module): Model. 15 | """ 16 | print("Loading model...") 17 | 18 | model = BaselineModel( 19 | linear_size=config.MODEL.LINEAR_SIZE, 20 | num_stages=config.MODEL.NUM_STAGES, 21 | p_dropout=config.MODEL.DROPOUT_PROB, 22 | predict_14=config.MODEL.PREDICT_14, 23 | ) 24 | 25 | weight_path = config.MODEL.WEIGHT 26 | if weight_path: 27 | model.load_state_dict(torch.load(weight_path, map_location=torch.device("cpu"))) 28 | print(f"Loaded weight from {weight_path}.") 29 | 30 | device = get_device(config.USE_CUDA) 31 | model = model.to(device) 32 | 33 | print("Done!") 34 | 35 | return model 36 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/models/baseline_model.py: -------------------------------------------------------------------------------- 1 | # references: 2 | # https://github.com/weigq/3d_pose_baseline_pytorch/blob/master/src/model.py 3 | # https://github.com/una-dinosauria/3d-pose-baseline/blob/master/src/linear_model.py 4 | 5 | import torch.nn as nn 6 | 7 | 8 | def init_weights(module): 9 | """Initialize weights of the baseline linear model. 10 | 11 | Our initialization scheme is different from the official implementation in TensorFlow. 12 | Official one inits bias of linear layer with kaiming normal but we init with 0. 13 | Also we init weights of batchnorm layer with 1 and bias with 0. 14 | We have not investigated if this affects the accuracy. 15 | 16 | Args: 17 | module (torch.nn.Module): torch.nn.Module composing the baseline linear model. 18 | """ 19 | if isinstance(module, nn.Linear): 20 | nn.init.kaiming_normal_(module.weight.data, mode="fan_in", nonlinearity="relu") 21 | module.bias.data.zero_() 22 | if isinstance(module, nn.BatchNorm1d): 23 | module.weight.data.fill_(1) 24 | module.bias.data.zero_() 25 | 26 | 27 | class Linear(nn.Module): 28 | def __init__(self, linear_size, p_dropout): 29 | """ 30 | 31 | Args: 32 | linear_size (int): Number of nodes in the linear layers. 33 | p_dropout (float): Dropout probability. 34 | """ 35 | super(Linear, self).__init__() 36 | 37 | self.relu = nn.ReLU(inplace=True) 38 | self.dropout = nn.Dropout(p_dropout) 39 | 40 | self.w1 = nn.Linear(linear_size, linear_size) 41 | self.bn1 = nn.BatchNorm1d(linear_size) 42 | 43 | self.w2 = nn.Linear(linear_size, linear_size) 44 | self.bn2 = nn.BatchNorm1d(linear_size) 45 | 46 | def forward(self, x): 47 | """Forward operations of the linear block. 48 | 49 | Args: 50 | x (torch.Tensor): Input tensor. 51 | 52 | Returns: 53 | y (torch.Tensor): Output tensor. 54 | """ 55 | h = self.w1(x) 56 | h = self.bn1(h) 57 | h = self.relu(h) 58 | h = self.dropout(h) 59 | 60 | h = self.w2(h) 61 | h = self.bn2(h) 62 | h = self.relu(h) 63 | h = self.dropout(h) 64 | 65 | y = x + h 66 | return y 67 | 68 | 69 | class BaselineModel(nn.Module): 70 | def __init__(self, linear_size=1024, num_stages=2, p_dropout=0.5, predict_14=False): 71 | """ 72 | 73 | Args: 74 | linear_size (int, optional): Number of nodes in the linear layers. Defaults to 1024. 75 | num_stages (int, optional): Number to repeat the linear block. Defaults to 2. 76 | p_dropout (float, optional): Dropout probability. Defaults to 0.5. 77 | predict_14 (bool, optional): Whether to predict 14 3d-joints. Defaults to False. 78 | """ 79 | super(BaselineModel, self).__init__() 80 | 81 | input_size = 16 * 2 # Input 2d-joints. 82 | output_size = 14 * 3 if predict_14 else 16 * 3 # Output 3d-joints. 83 | 84 | self.w1 = nn.Linear(input_size, linear_size) 85 | self.bn1 = nn.BatchNorm1d(linear_size) 86 | 87 | self.linear_stages = [Linear(linear_size, p_dropout) for _ in range(num_stages)] 88 | self.linear_stages = nn.ModuleList(self.linear_stages) 89 | 90 | self.w2 = nn.Linear(linear_size, output_size) 91 | 92 | self.relu = nn.ReLU(inplace=True) 93 | self.dropout = nn.Dropout(p_dropout) 94 | 95 | # initialize model weights 96 | self.apply(init_weights) 97 | 98 | def forward(self, x): 99 | """Forward operations of the linear block. 100 | 101 | Args: 102 | x (torch.Tensor): Input tensor. 103 | 104 | Returns: 105 | y (torch.Tensor): Output tensor. 106 | """ 107 | y = self.w1(x) 108 | y = self.bn1(y) 109 | y = self.relu(y) 110 | y = self.dropout(y) 111 | 112 | # linear blocks 113 | for linear in self.linear_stages: 114 | y = linear(y) 115 | 116 | y = self.w2(y) 117 | 118 | return y 119 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/solvers/__init__.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | import torch.optim as optim 3 | 4 | from ..utils.cuda import get_device 5 | 6 | 7 | def get_criterion(config): 8 | """Get criterion (loss) to train models. 9 | 10 | Args: 11 | config (yacs.config.CfgNode): Configuration. 12 | 13 | Returns: 14 | (torch.nn.Module): Loss function. 15 | """ 16 | criterion = nn.MSELoss(reduction="mean") 17 | 18 | device = get_device(config.USE_CUDA) 19 | criterion.to(device) 20 | 21 | return criterion 22 | 23 | 24 | def get_lr_scheduler(config, optimizer): 25 | """Get learning rate scheduler to train models. 26 | 27 | Args: 28 | config (yacs.config.CfgNode): Configuration. 29 | optimizer (torch.optimizer): Optimizer. 30 | 31 | Returns: 32 | (torch.lr_scheduler): Learning rate scheduler. 33 | """ 34 | gamma = config.SOLVER.LR_DECAY_GAMMA 35 | decay_step = config.SOLVER.LR_DECAY_STEP 36 | lr_scheduler = optim.lr_scheduler.LambdaLR( 37 | optimizer, lr_lambda=lambda step: gamma ** (step / decay_step) 38 | ) 39 | return lr_scheduler 40 | 41 | 42 | def get_optimizer(config, model): 43 | """Get optimizer to train models. 44 | 45 | Args: 46 | config (yacs.config.CfgNode): Configuration. 47 | model (torch.nn.Module): Model to train. 48 | 49 | Returns: 50 | (torch.optimizer): Optimizer. 51 | """ 52 | optimizer = optim.Adam(model.parameters(), lr=config.SOLVER.LR) 53 | return optimizer 54 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/motokimura/3d-pose-baseline-pytorch/7d5e599076a90b8d4fe0a53455231258b035837c/human_3d_pose_baseline/utils/__init__.py -------------------------------------------------------------------------------- /human_3d_pose_baseline/utils/camera_utils.py: -------------------------------------------------------------------------------- 1 | # references: 2 | # https://github.com/una-dinosauria/3d-pose-baseline/blob/master/src/cameras.py 3 | 4 | import os 5 | 6 | import h5py 7 | import numpy as np 8 | 9 | 10 | def transform_camera_to_world(P, R, T): 11 | """Transform points from camera to world coordinates. 12 | 13 | Args: 14 | P (numpy.array): Nx3 3d points in camera coordinates. 15 | R (numpy.array): Camera rotation matrix. 16 | T (numpy.array): Camera translation vector. 17 | 18 | Returns: 19 | X (numpy.array): Nx3 3d points in world coordinates. 20 | """ 21 | assert len(P.shape) == 2 22 | assert P.shape[1] == 3 23 | 24 | X = R.T @ (P.T) + T # rotate and translate 25 | return X.T 26 | 27 | 28 | def transform_world_to_camera(P, R, T): 29 | """Transform points from world to camera coordinates. 30 | 31 | Args: 32 | P (numpy.array): Nx3 3d points in world coordinates. 33 | R (numpy.array): Camera rotation matrix. 34 | T (numpy.array): Camera translation vector. 35 | 36 | Returns: 37 | X (numpy.array): Nx3 3d points in camera coordinates. 38 | """ 39 | assert len(P.shape) == 2 40 | assert P.shape[1] == 3 41 | 42 | X = R @ (P.T - T) # rotate and translate 43 | return X.T 44 | 45 | 46 | def project_to_camrea(P, R, T, f, c, k, p): 47 | """Project points from 3d to 2d using camera parameters 48 | including radial and tangential distortions. 49 | 50 | Args: 51 | P (numpy.array): Nx3 3d points in world coordinates. 52 | R (numpy.array): 3x3 Camera rotation matrix. 53 | T (numpy.array): 3x1 Camera translation parameters. 54 | f (numpy.array): 2x1 Camera focal length. 55 | c (numpy.array): 2x1 Camera center. 56 | k (numpy.array): 3x1 Camera radial distortion coefficients. 57 | p (numpy.array): 2x1 Camera tangential distortion coefficients. 58 | Returns: 59 | p (numpy.array): Nx2 2d points in pixel space. 60 | d (numpy.array): 1xN depth of each point in camera space. 61 | radial (numpy.array): 1xN radial distortion per point. 62 | tan (numpy.array): 1xN tangential distortion per point. 63 | r2 (numpy.array): 1xN squared radius of the projected points before distortion. 64 | """ 65 | N = P.shape[0] 66 | 67 | X = transform_world_to_camera(P, R, T) # Nx3 68 | X = X.T # 3xN 69 | d = X[2, :] # Depth. 70 | XX = X[:2, :] / d # 2xN 71 | 72 | # Radial distorsion term 73 | r2 = XX[0, :] ** 2 + XX[1, :] ** 2 74 | radial = 1 + np.einsum( 75 | "ij,ij->j", np.tile(k, (1, N)), np.array([r2, r2 ** 2, r2 ** 3]) 76 | ) 77 | # Tangential distorsion term. 78 | tan = p[0] * XX[1, :] + p[1] * XX[0, :] 79 | # Apply the distorsions. 80 | XXX = XX * np.tile(radial + tan, (2, 1)) + np.outer( 81 | np.array([p[1], p[0]]).reshape(-1), r2 82 | ) 83 | 84 | # Project to camera. 85 | projected = f * XXX + c 86 | projected = projected.T # Nx2 87 | 88 | return projected, d, radial, tan, r2 89 | 90 | 91 | def load_camera_params(hf, base_path): 92 | """Load h36m camera parameters. 93 | 94 | Args: 95 | hf (file object): HDF5 open file with h36m cameras data 96 | path (str): Path or key inside hf to the camera we are interested in. 97 | 98 | Returns: 99 | R (numpy.array): 3x3 Camera rotation matrix. 100 | T (numpy.array): 3x1 Camera translation parameters. 101 | f (numpy.array): 2x1 Camera focal length. 102 | c (numpy.array): 2x1 Camera center. 103 | k (numpy.array): 3x1 Camera radial distortion coefficients. 104 | p (numpy.array): 2x1 Camera tangential distortion coefficients. 105 | name (str): String with camera id. 106 | """ 107 | R = hf[os.path.join(base_path, "R")][:] 108 | R = R.T 109 | 110 | T = hf[os.path.join(base_path, "T")][:] 111 | f = hf[os.path.join(base_path, "f")][:] 112 | c = hf[os.path.join(base_path, "c")][:] 113 | k = hf[os.path.join(base_path, "k")][:] 114 | p = hf[os.path.join(base_path, "p")][:] 115 | 116 | name = hf[os.path.join(base_path, "Name")][:] 117 | name = "".join(chr(item) for item in name) 118 | 119 | return R, T, f, c, k, p, name 120 | 121 | 122 | def load_cameras(camera_h5_path, subjects=[1, 5, 6, 7, 8, 9, 11]): 123 | """Load camera parameters from camera.h5 of Human3.6M 124 | 125 | Args: 126 | camera_h5_path (str): Path to hdf5 file of Human3.6M camera params 127 | subjects (list[int], optional): List of ints representing 128 | the subject IDs for which cameras are requested. 129 | Defaults to [1, 5, 6, 7, 8, 9, 11]. 130 | 131 | Returns: 132 | cams (dict[tuple, tuple]): Dictionary of 4 tuples per subject ID 133 | containing its camera parameters for the 4 Human3.6M cameras. 134 | """ 135 | cams = {} 136 | 137 | with h5py.File(camera_h5_path, "r") as hf: 138 | for subj in subjects: 139 | for cam_idx in range( 140 | 1, 5 141 | ): # Human3.6M has 4 cameras (#1~5) for each subject. 142 | base_path = f"subject{subj}/camera{cam_idx}" 143 | cams[(subj, cam_idx)] = load_camera_params(hf, base_path) 144 | 145 | return cams 146 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/utils/cuda.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | 4 | def get_device(use_cuda=True): 5 | """Get CUDA or CPU device used for model training/evaluation. 6 | 7 | Args: 8 | use_cuda (bool, optional): True if use CUDA. 9 | 10 | Returns: 11 | (torch.device): Device to use. 12 | """ 13 | if use_cuda: 14 | assert torch.cuda.is_available(), "CUDA is not available." 15 | 16 | device = torch.device("cuda" if use_cuda else "cpu") 17 | return device 18 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/utils/data_utils.py: -------------------------------------------------------------------------------- 1 | # references: 2 | # https://github.com/una-dinosauria/3d-pose-baseline/blob/master/src/data_utils.py 3 | 4 | import copy 5 | import os 6 | from glob import glob 7 | 8 | import h5py 9 | import numpy as np 10 | 11 | from .camera_utils import project_to_camrea 12 | from .camera_utils import transform_world_to_camera as transform_world_to_camera_base 13 | 14 | # Human3.6m IDs for training and testing. 15 | TRAIN_SUBJECTS = [1, 5, 6, 7, 8] 16 | TEST_SUBJECTS = [9, 11] 17 | 18 | # Actions defined in Human3.6M. 19 | H36M_ACTIONS = [ 20 | "Directions", 21 | "Discussion", 22 | "Eating", 23 | "Greeting", 24 | "Phoning", 25 | "Photo", 26 | "Posing", 27 | "Purchases", 28 | "Sitting", 29 | "SittingDown", 30 | "Smoking", 31 | "Waiting", 32 | "WalkDog", 33 | "Walking", 34 | "WalkTogether", 35 | ] 36 | 37 | # Joints in Human3.6M. 38 | # data has 32 joints, but only 17 that move. 39 | H36M_NAMES = [""] * 32 40 | H36M_NAMES[0] = "Hip" 41 | H36M_NAMES[1] = "RHip" 42 | H36M_NAMES[2] = "RKnee" 43 | H36M_NAMES[3] = "RFoot" 44 | H36M_NAMES[6] = "LHip" 45 | H36M_NAMES[7] = "LKnee" 46 | H36M_NAMES[8] = "LFoot" 47 | H36M_NAMES[12] = "Spine" 48 | H36M_NAMES[13] = "Thorax" 49 | H36M_NAMES[14] = "Neck/Nose" 50 | H36M_NAMES[15] = "Head" 51 | H36M_NAMES[17] = "LShoulder" 52 | H36M_NAMES[18] = "LElbow" 53 | H36M_NAMES[19] = "LWrist" 54 | H36M_NAMES[25] = "RShoulder" 55 | H36M_NAMES[26] = "RElbow" 56 | H36M_NAMES[27] = "RWrist" 57 | 58 | 59 | def load_data(data_dir, subjects, actions): 60 | """Load 3d ground truth from disk, and puts it in an easy-to-access dictionary. 61 | 62 | Args: 63 | data_dir (str): Path to where to load the data from. 64 | subjects (list[int]): Subjects whose data will be loaded. 65 | actions (list[str]): Actions to load. 66 | 67 | Returns: 68 | data (dict[tuple, numpy.array]): Directionary with 69 | keys k=(subjects, actions, seqname) and 70 | values v=(nx(32x3) matrix of 3d ground truth). 71 | """ 72 | 73 | data = {} 74 | for subj in subjects: 75 | for act in actions: 76 | # print(f"reading subject {subj}, action {act}...") 77 | 78 | path = os.path.join(data_dir, f"S{subj}/MyPoses/3D_positions/{act}*.h5") 79 | 80 | fnames = glob(path) 81 | 82 | loaded_seqs = 0 83 | for fname in fnames: 84 | seqname = os.path.basename(fname) 85 | 86 | # This makes sure SittingDown is not loaded when Sitting is required. 87 | if act == "Sitting" and seqname.startswith("SittingDown"): 88 | continue 89 | 90 | if seqname.startswith(act): 91 | # print(fname) 92 | loaded_seqs += 1 93 | 94 | with h5py.File(fname, "r") as f: 95 | poses = f["3D_positions"][:] 96 | 97 | poses = poses.T # [N, 96] 98 | data[(subj, act, seqname)] = poses 99 | 100 | assert ( 101 | loaded_seqs == 2 102 | ), f"Expecting 2 sequences, but found {loaded_seqs} instead." 103 | 104 | return data 105 | 106 | 107 | def transform_world_to_camera(pose_set, cams, ncams=4): 108 | """Transform 3d poses from world coordinate to camera coordinate. 109 | 110 | Args: 111 | pose_set (dict[tuple, numpy.array]): Dictionary with 3d poses. 112 | cams (dict[tuple, tuple]): Dictionary with cameras. 113 | ncams (int, optional): Number of cameras per subject. Defaults to 4. 114 | 115 | Returns: 116 | t3d_camera (dict[tuple, numpy.array]): Dictionary with 3d poses in camera coordinate. 117 | """ 118 | t3d_camera = {} 119 | for t3dk in sorted(pose_set.keys()): 120 | subj, act, seqname = t3dk 121 | t3d_world = pose_set[t3dk] # nx(32x3) 122 | t3d_world = t3d_world.reshape((-1, 3)) # (nx32)x3 123 | 124 | for cam_idx in range(1, ncams + 1): 125 | R, T, f, c, k, p, name = cams[(subj, cam_idx)] 126 | camera_coord = transform_world_to_camera_base(t3d_world, R, T) 127 | camera_coord = camera_coord.reshape((-1, len(H36M_NAMES) * 3)) # nx(32x3) 128 | 129 | base_seqname = seqname[:-3] # remove ".h5" 130 | sname = f"{base_seqname}.{name}.h5" # e.g., "Waiting 1.58860488.h5" 131 | t3d_camera[(subj, act, sname)] = camera_coord 132 | 133 | return t3d_camera 134 | 135 | 136 | def postprocess_3d(pose_set): 137 | """Centerize 3d joint points around root joint. 138 | 139 | Args: 140 | pose_set (dict[tuple, numpy.array]): Dictionary with 3d data. 141 | 142 | Returns: 143 | pose_set (dict[tuple, numpy.array]): Dictionary with 3d data centred around root (center hip) joint. 144 | root_positions (dict[tuple, numpy.array]): Dictionary with the original 3d position of each pose. 145 | """ 146 | root_positions = {} 147 | for k in sorted(pose_set.keys()): 148 | poses = pose_set[k] # nx(32x3) 149 | 150 | # Keep track of global position. 151 | root_begin = H36M_NAMES.index("Hip") * 3 152 | root_position = copy.deepcopy(poses[:, root_begin : root_begin + 3]) # nx3 153 | 154 | # Centerize around root. 155 | poses = poses - np.tile(root_position, [1, len(H36M_NAMES)]) 156 | 157 | pose_set[k] = poses 158 | root_positions[k] = root_position 159 | 160 | return pose_set, root_positions 161 | 162 | 163 | def compute_normalization_stats(data, dim, predict_14=False): 164 | """Compute normalization statistics: mean, std, dimensions to use and ignore. 165 | 166 | Args: 167 | data (numpy.array): nxd array of poses 168 | dim (int): Dimensionality of the pose. 2 or 3. 169 | predict_14 (bool, optional): Whether to use only 14 joints. Defaults to False. 170 | 171 | Returns: 172 | data_mean (numpy.array): Vector with the mean of the data. 173 | data_std (numpy.array): Vector with the standard deviation of the data. 174 | dim_to_ignore (numpy.array): List of dimensions not used in the model. 175 | dim_to_use (numpy.array): List of dimensions used in the model. 176 | """ 177 | assert dim in [2, 3], "dim must be 2 or 3." 178 | 179 | data_mean = np.mean(data, axis=0) 180 | data_std = np.std(data, axis=0) 181 | 182 | if dim == 2: 183 | # Get dimensions of 16 2d points to use. 184 | dim_to_ignore = np.where( 185 | np.array([x in ["", "Neck/Nose"] for x in H36M_NAMES]) 186 | )[0] 187 | dim_to_ignore = np.sort(np.hstack([dim_to_ignore * 2, dim_to_ignore * 2 + 1])) 188 | dim_to_use = np.delete(np.arange(len(H36M_NAMES) * 2), dim_to_ignore) 189 | else: # dim == 3 190 | # Get dimensions of 16 (or 14) 3d points to use. 191 | if predict_14: 192 | dim_to_ignore = np.where( 193 | np.array([x in ["", "Hip", "Spine", "Neck/Nose"] for x in H36M_NAMES]) 194 | )[0] 195 | else: # predict 16 points 196 | dim_to_ignore = np.where(np.array([x in ["", "Hip"] for x in H36M_NAMES]))[ 197 | 0 198 | ] 199 | 200 | dim_to_ignore = np.sort( 201 | np.hstack([dim_to_ignore * 3, dim_to_ignore * 3 + 1, dim_to_ignore * 3 + 2]) 202 | ) 203 | dim_to_use = np.delete(np.arange(len(H36M_NAMES) * 3), dim_to_ignore) 204 | 205 | return data_mean, data_std, dim_to_ignore, dim_to_use 206 | 207 | 208 | def normalize_data(data, data_mean, data_std, dim_to_use): 209 | """Normalize poses in the dictionary. 210 | 211 | Args: 212 | data (dict[tuple, numpy.array]): Dictionary with the poses. 213 | data_mean (numpy.array): Vector with the mean of the data. 214 | data_std (numpy.array): Vector with the std of the data. 215 | dim_to_use (numpy.array): Dimensions to keep in the data. 216 | 217 | Returns: 218 | data_normalized (dict[tuple, numpy.array]): Dictionary with same keys as data, but values have been normalized. 219 | """ 220 | data_normalized = {} 221 | 222 | for key in sorted(data.keys()): 223 | data[key] = data[key][:, dim_to_use] # remove joints to ignore 224 | mu = data_mean[dim_to_use] 225 | sigma = data_std[dim_to_use] 226 | data_normalized[key] = np.divide((data[key] - mu), sigma) 227 | 228 | return data_normalized 229 | 230 | 231 | def read_3d_data(actions, data_dir, cams, camera_frame=True, predict_14=False): 232 | """Load 3d poses, zero-centred and normalized. 233 | 234 | Args: 235 | actions (list[str]): Actions to load. 236 | data_dir (str): Directory where the data can be loaded from. 237 | cams (dict[tuple, tuple]): Dictionary with camera parameters. 238 | camera_frame (bool, optional): Whether to convert the data to camera coordinates. Defaults to True. 239 | predict_14 (bool, optional): Whether to predict only 14 joints. Defaults to False. 240 | 241 | Returns: 242 | train_set (dict[tuple, numpy.array]): Dictionary with loaded 3d poses for training. 243 | test_set (dict[tuple, numpy.array]): Dictionary with loaded 3d poses for testing. 244 | data_mean (numpy.array): Vector with the mean of the 3d training data. 245 | data_std (numpy.array): Vector with the standard deviation of the 3d training data. 246 | dim_to_ignore (list[int]): List with the dimensions not to predict. 247 | dim_to_use (list[int]): List with the dimensions to predict. 248 | train_root_positions (dict[tuple, numpy.array]): Dictionary with the 3d positions of the root in train set. 249 | test_root_positions (dict[tuple, numpy.array]: Dictionary with the 3d positions of the root in test set. 250 | """ 251 | # Load 3d data. 252 | train_set = load_data(data_dir, TRAIN_SUBJECTS, actions) 253 | test_set = load_data(data_dir, TEST_SUBJECTS, actions) 254 | 255 | if camera_frame: 256 | train_set = transform_world_to_camera(train_set, cams) 257 | test_set = transform_world_to_camera(test_set, cams) 258 | 259 | # Centering around root (center hip joint). 260 | train_set, train_root_positions = postprocess_3d(train_set) 261 | test_set, test_root_positions = postprocess_3d(test_set) 262 | 263 | # Compute normalization statistics. 264 | train_concat = copy.deepcopy(np.vstack(list(train_set.values()))) 265 | data_mean, data_std, dim_to_ignore, dim_to_use = compute_normalization_stats( 266 | train_concat, dim=3, predict_14=predict_14 267 | ) 268 | 269 | # Divide every dimension independently. 270 | train_set = normalize_data(train_set, data_mean, data_std, dim_to_use) 271 | test_set = normalize_data(test_set, data_mean, data_std, dim_to_use) 272 | 273 | return ( 274 | train_set, 275 | test_set, 276 | data_mean, 277 | data_std, 278 | dim_to_ignore, 279 | dim_to_use, 280 | train_root_positions, 281 | test_root_positions, 282 | ) 283 | 284 | 285 | def project_to_camreas(pose_set, cams, ncams=4): 286 | """Project 3d poses using camera parameters. 287 | 288 | Args: 289 | pose_set (dict[tuple, numpy.array]): Dictionary with 3d poses. 290 | cams (dict[tuple, tuple]): Dictionary with cameras. 291 | ncams (int, optional): Number of cameras per subject. Defaults to 4. 292 | 293 | Returns: 294 | t2d (dict[tuple, numpy.array]): Dictionary with projected 2d poses. 295 | """ 296 | t2d = {} 297 | 298 | for t3dk in sorted(pose_set.keys()): 299 | subj, act, seqname = t3dk 300 | t3d = pose_set[t3dk] # nx(32x3) 301 | t3d = t3d.reshape((-1, 3)) # (nx32)x3 302 | 303 | for cam_idx in range(1, ncams + 1): 304 | R, T, f, c, k, p, name = cams[(subj, cam_idx)] 305 | pts2d, _, _, _, _ = project_to_camrea(t3d, R, T, f, c, k, p) # (nx32)x2 306 | pts2d = pts2d.reshape((-1, len(H36M_NAMES) * 2)) # nx(32x2) 307 | 308 | base_seqname = seqname[:-3] # remove ".h5" 309 | sname = f"{base_seqname}.{name}.h5" # e.g., "Waiting 1.58860488.h5" 310 | t2d[(subj, act, sname)] = pts2d 311 | 312 | return t2d 313 | 314 | 315 | def create_2d_data(actions, data_dir, cams): 316 | """Create 2d poses by projecting 3d poses with the corresponding camera parameters, 317 | and also normalize the 2d poses. 318 | 319 | Args: 320 | actions (list[str]): Actions to load. 321 | data_dir (str): Directory where the data can be loaded from. 322 | cams (dict[tuple, tuple]): Dictionary with camera parameters. 323 | 324 | Returns: 325 | train_set (dict[tuple, numpy.array]): Dictionary with loaded 2d poses for training. 326 | test_set (dict[tuple, numpy.array]): Dictionary with loaded 2d poses for testing. 327 | data_mean (numpy.array): Vector with the mean of the 2d training data. 328 | data_std (numpy.array): Vector with the standard deviation of the 2d training data. 329 | dim_to_ignore (list[int]): List with the dimensions not to predict. 330 | dim_to_use (list[int]): List with the dimensions to predict. 331 | """ 332 | # Load 3d data. 333 | train_set = load_data(data_dir, TRAIN_SUBJECTS, actions) 334 | test_set = load_data(data_dir, TEST_SUBJECTS, actions) 335 | 336 | train_set = project_to_camreas(train_set, cams) 337 | test_set = project_to_camreas(test_set, cams) 338 | 339 | # Compute normalization statistics. 340 | train_concat = copy.deepcopy(np.vstack(list(train_set.values()))) 341 | data_mean, data_std, dim_to_ignore, dim_to_use = compute_normalization_stats( 342 | train_concat, dim=2, predict_14=False 343 | ) 344 | 345 | # Divide every dimension independently. 346 | train_set = normalize_data(train_set, data_mean, data_std, dim_to_use) 347 | test_set = normalize_data(test_set, data_mean, data_std, dim_to_use) 348 | 349 | return train_set, test_set, data_mean, data_std, dim_to_ignore, dim_to_use 350 | 351 | 352 | def unnormalize_data(data, data_mean, data_std, dim_to_ignore): 353 | """Un-normalize poses whose mean has been substracted and that has been divided by 354 | standard deviation. Returned array has mean values at ignored dimensions. 355 | 356 | Args: 357 | data (numpy.array): nxd array to unnormalize 358 | data_mean (numpy.array): Vector with the mean of the data. 359 | data_std (numpy.array): Vector with the std of the data. 360 | dim_to_ignore (numpy.array): Dimensions that were removed from the original data. 361 | 362 | Returns: 363 | data_unnormalized (numpy.array): unnormalized array 364 | """ 365 | N = data.shape[0] # Batch size. 366 | D = data_mean.shape[0] # Dimensionality. 367 | data_unnormalized = np.zeros((N, D), dtype=np.float32) # NxD 368 | 369 | dim_to_use = [d for d in range(D) if d not in dim_to_ignore] 370 | data_unnormalized[:, dim_to_use] = data 371 | 372 | # unnormalize with mean and std 373 | sigma = data_std.reshape((1, D)) # 1xD 374 | sigma = np.repeat(sigma, N, axis=0) # NxD 375 | mu = data_mean.reshape((1, D)) # 1xD 376 | mu = np.repeat(mu, N, axis=0) # NxD 377 | data_unnormalized = np.multiply(data_unnormalized, sigma) + mu 378 | 379 | return data_unnormalized 380 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/utils/procrustes.py: -------------------------------------------------------------------------------- 1 | # references: 2 | # https://github.com/una-dinosauria/3d-pose-baseline/blob/master/src/procrustes.py 3 | 4 | 5 | def compute_similarity_transform(X, Y, compute_optimal_scale=False): 6 | """A port of MATLAB's `procrustes` function to Numpy. 7 | Adapted from http://stackoverflow.com/a/18927641/1884420 8 | 9 | Args: 10 | X (numpy.array): array NxM of targets, with N number of points and M point dimensionality 11 | Y (numpy.array): array NxM of inputs 12 | compute_optimal_scale (bool): whether we compute optimal scale or force it to be 1 13 | 14 | Returns: 15 | d (float): squared error after transformation 16 | Z (numpy.array): transformed Y 17 | T (numpy.array): computed rotation 18 | b (float): scaling 19 | c (numpy.array): translation 20 | """ 21 | import numpy as np 22 | 23 | muX = X.mean(0) 24 | muY = Y.mean(0) 25 | 26 | X0 = X - muX 27 | Y0 = Y - muY 28 | 29 | ssX = (X0 ** 2.0).sum() 30 | ssY = (Y0 ** 2.0).sum() 31 | 32 | # Centred Frobenius norm. 33 | normX = np.sqrt(ssX) 34 | normY = np.sqrt(ssY) 35 | 36 | # Scale to equal (unit) norm. 37 | X0 = X0 / normX 38 | Y0 = Y0 / normY 39 | 40 | # Optimum rotation matrix of Y. 41 | A = np.dot(X0.T, Y0) 42 | U, s, Vt = np.linalg.svd(A, full_matrices=False) 43 | V = Vt.T 44 | T = np.dot(V, U.T) 45 | 46 | # Make sure we have a rotation. 47 | detT = np.linalg.det(T) 48 | V[:, -1] *= np.sign(detT) 49 | s[-1] *= np.sign(detT) 50 | T = np.dot(V, U.T) 51 | 52 | traceTA = s.sum() 53 | 54 | if compute_optimal_scale: # Compute optimum scaling of Y. 55 | b = traceTA * normX / normY 56 | d = 1 - traceTA ** 2 57 | Z = normX * traceTA * np.dot(Y0, T) + muX 58 | else: # If no scaling allowed 59 | b = 1 60 | d = 1 + ssY / ssX - 2 * traceTA * normY / normX 61 | Z = normY * np.dot(Y0, T) + muX 62 | 63 | c = muX - b * np.dot(muY, T) 64 | 65 | return d, Z, T, b, c 66 | -------------------------------------------------------------------------------- /human_3d_pose_baseline/utils/vis_utils.py: -------------------------------------------------------------------------------- 1 | # references: 2 | # https://github.com/una-dinosauria/3d-pose-baseline/blob/master/src/viz.py 3 | 4 | import numpy as np 5 | 6 | from .data_utils import H36M_NAMES 7 | 8 | 9 | def show_3d_pose(channels, ax, lcolor="#3498db", rcolor="#e74c3c", add_labels=False): 10 | """Visualize a 3d skeleton. 11 | 12 | Args: 13 | channels (numpy.array): 96x1 vector. The pose to plot. 14 | ax (mpl_toolkits.mplot3d.axes3d.Axes3D): matplotlib axis to draw on. 15 | lcolor (str, optional): Color for left part of the body. Defaults to "#3498db". 16 | rcolor (str, optional): Color for right part of the body. Defaults to "#e74c3c". 17 | add_labels (bool, optional): Whether to add coordinate labels. Defaults to False. 18 | """ 19 | 20 | assert ( 21 | channels.size == len(H36M_NAMES) * 3 22 | ), "channels should have 96 entries, it has {} instead.".format(channels.size) 23 | vals = np.reshape(channels, (len(H36M_NAMES), -1)) 24 | 25 | # XXX: Joint indices are hard coded. 26 | I = np.array( 27 | [0, 1, 2, 0, 6, 7, 0, 12, 13, 14, 13, 17, 18, 13, 25, 26] 28 | ) # Start points. 29 | J = np.array( 30 | [1, 2, 3, 6, 7, 8, 12, 13, 14, 15, 17, 18, 19, 25, 26, 27] 31 | ) # End points. 32 | LR = np.array([1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1], dtype=bool) 33 | 34 | # Make connection array. 35 | for i in range(len(I)): 36 | x, y, z = [np.array([vals[I[i], j], vals[J[i], j]]) for j in range(3)] 37 | ax.plot(x, y, z, lw=2, c=lcolor if LR[i] else rcolor) 38 | 39 | RADIUS = 750 # Space around the subject. 40 | # XXX: Assuming index-0 is for root joint. 41 | xroot, yroot, zroot = vals[0, 0], vals[0, 1], vals[0, 2] 42 | ax.set_xlim3d([-RADIUS + xroot, RADIUS + xroot]) 43 | ax.set_zlim3d([-RADIUS + zroot, RADIUS + zroot]) 44 | ax.set_ylim3d([-RADIUS + yroot, RADIUS + yroot]) 45 | 46 | if add_labels: 47 | ax.set_xlabel("x") 48 | ax.set_ylabel("y") 49 | ax.set_zlabel("z") 50 | 51 | # Get rid of the ticks and tick labels. 52 | ax.set_xticks([]) 53 | ax.set_yticks([]) 54 | ax.set_zticks([]) 55 | 56 | ax.get_xaxis().set_ticklabels([]) 57 | ax.get_yaxis().set_ticklabels([]) 58 | ax.set_zticklabels([]) 59 | 60 | ax.set_aspect("equal") 61 | 62 | # Get rid of the panes (actually make them white). 63 | white = (1.0, 1.0, 1.0, 0.0) 64 | ax.w_xaxis.set_pane_color(white) 65 | ax.w_yaxis.set_pane_color(white) 66 | # Keep z pane. 67 | 68 | # Get rid of the lines in 3d. 69 | ax.w_xaxis.line.set_color(white) 70 | ax.w_yaxis.line.set_color(white) 71 | ax.w_zaxis.line.set_color(white) 72 | 73 | 74 | def show_2d_pose(channels, ax, lcolor="#3498db", rcolor="#e74c3c", add_labels=False): 75 | """Visualize a 2d skeleton. 76 | 77 | Args: 78 | channels: 64x1 vector. The pose to plot. 79 | ax (matplotlib.axes._subplots.AxesSubplot): matplotlib axis to draw on. 80 | lcolor (str, optional): Color for left part of the body. Defaults to "#3498db". 81 | rcolor (str, optional): Color for right part of the body. Defaults to "#e74c3c". 82 | add_labels (bool, optional): Whether to add coordinate labels. Defaults to False. 83 | """ 84 | 85 | assert ( 86 | channels.size == len(H36M_NAMES) * 2 87 | ), "channels should have 64 entries, it has {} instead.".format(channels.size) 88 | vals = np.reshape(channels, (len(H36M_NAMES), -1)) 89 | 90 | # XXX: Joint indices are hard coded. 91 | I = np.array([0, 1, 2, 0, 6, 7, 0, 12, 13, 13, 17, 18, 13, 25, 26]) # Start points. 92 | J = np.array([1, 2, 3, 6, 7, 8, 12, 13, 15, 17, 18, 19, 25, 26, 27]) # End points. 93 | LR = np.array([1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1], dtype=bool) 94 | 95 | # Make connection array. 96 | for i in range(len(I)): 97 | x, y = [np.array([vals[I[i], j], vals[J[i], j]]) for j in range(2)] 98 | ax.plot(x, y, lw=2, c=lcolor if LR[i] else rcolor) 99 | 100 | RADIUS = 350 # Space around the subject. 101 | # XXX: Assuming index-0 is for root joint. 102 | xroot, yroot = vals[0, 0], vals[0, 1] 103 | ax.set_xlim([-RADIUS + xroot, RADIUS + xroot]) 104 | ax.set_ylim([-RADIUS + yroot, RADIUS + yroot]) 105 | 106 | if add_labels: 107 | ax.set_xlabel("x") 108 | ax.set_ylabel("y") 109 | 110 | # Get rid of the ticks and tick labels. 111 | ax.set_xticks([]) 112 | ax.set_yticks([]) 113 | 114 | ax.get_xaxis().set_ticklabels([]) 115 | ax.get_yaxis().set_ticklabels([]) 116 | 117 | ax.set_aspect("equal") 118 | ax.invert_yaxis() 119 | -------------------------------------------------------------------------------- /notebooks/visualize_2d_pose.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import matplotlib.pyplot as plt\n", 10 | "%matplotlib inline" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": 2, 16 | "metadata": {}, 17 | "outputs": [], 18 | "source": [ 19 | "import sys\n", 20 | "sys.path.append(\"../human_3d_pose_baseline/\")\n", 21 | "from utils import camera_utils, data_utils, vis_utils" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "## Load Human3.6M camera parameters" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": 3, 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [ 37 | "cams = camera_utils.load_cameras(\"../dataset/h36m/cameras.h5\")" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "## Generate 2d poses from Human3.6M 3d poses" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 4, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [ 53 | "actions = [\"Sitting\",] # actions to load.\n", 54 | "\n", 55 | "train_set, test_set, data_mean, data_std, dim_to_ignore, dim_to_use = \\\n", 56 | " data_utils.create_2d_data(actions, \"../dataset/h36m/\", cams)" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 5, 62 | "metadata": { 63 | "scrolled": false 64 | }, 65 | "outputs": [ 66 | { 67 | "data": { 68 | "text/plain": [ 69 | "{(1,\n", 70 | " 'Sitting',\n", 71 | " 'Sitting 1.54138969.h5'): array([[-1.78005441, -0.68216225, -1.34117159, ..., -0.28893505,\n", 72 | " -1.11101915, 0.28600438],\n", 73 | " [-1.78082797, -0.68150896, -1.34153378, ..., -0.27934079,\n", 74 | " -1.08352318, 0.32313631],\n", 75 | " [-1.7814926 , -0.68041954, -1.34188814, ..., -0.27008386,\n", 76 | " -1.05292886, 0.35927284],\n", 77 | " ...,\n", 78 | " [-1.1303134 , 1.18729798, -0.70708684, ..., 0.96955482,\n", 79 | " -0.81270456, 0.92874116],\n", 80 | " [-1.13116591, 1.18373652, -0.70811397, ..., 0.9700596 ,\n", 81 | " -0.82602019, 0.89714747],\n", 82 | " [-1.13152686, 1.17974519, -0.70867144, ..., 0.97204665,\n", 83 | " -0.83557853, 0.86894699]]),\n", 84 | " (1,\n", 85 | " 'Sitting',\n", 86 | " 'Sitting 1.55011271.h5'): array([[-0.07564788, -1.11050133, -0.52279428, ..., -0.73494101,\n", 87 | " -0.7518812 , 0.17674086],\n", 88 | " [-0.07470618, -1.10978267, -0.52163192, ..., -0.72823572,\n", 89 | " -0.7540454 , 0.20535658],\n", 90 | " [-0.07430545, -1.10835665, -0.52108582, ..., -0.72219974,\n", 91 | " -0.75708309, 0.23116509],\n", 92 | " ...,\n", 93 | " [ 0.43961502, -0.01930026, 0.01169138, ..., 0.06857251,\n", 94 | " -0.08940253, 0.37750652],\n", 95 | " [ 0.44039891, -0.02255575, 0.01249099, ..., 0.06911316,\n", 96 | " -0.07655194, 0.34692576],\n", 97 | " [ 0.44098528, -0.02643158, 0.01302746, ..., 0.07000832,\n", 98 | " -0.06732779, 0.31947932]]),\n", 99 | " (1,\n", 100 | " 'Sitting',\n", 101 | " 'Sitting 1.58860488.h5'): array([[ 1.73399225, -2.66519022, 2.10719395, ..., -1.91787709,\n", 102 | " 1.91344062, -0.95894267],\n", 103 | " [ 1.73316959, -2.6645867 , 2.10622643, ..., -1.90849163,\n", 104 | " 1.92096492, -0.92174636],\n", 105 | " [ 1.73280557, -2.66353815, 2.10576507, ..., -1.89945895,\n", 106 | " 1.92972713, -0.88544006],\n", 107 | " ...,\n", 108 | " [ 1.30457324, -0.87098377, 1.7230278 , ..., -0.66351882,\n", 109 | " 1.4243258 , -0.34655407],\n", 110 | " [ 1.30372395, -0.87454779, 1.72209616, ..., -0.66327707,\n", 111 | " 1.4108945 , -0.37868637],\n", 112 | " [ 1.30307406, -0.87850083, 1.72147112, ..., -0.66153818,\n", 113 | " 1.40118044, -0.40717742]]),\n", 114 | " (1,\n", 115 | " 'Sitting',\n", 116 | " 'Sitting 1.60457274.h5'): array([[ 0.76148428, -2.12691377, 0.22641461, ..., -1.78635683,\n", 117 | " 0.24036986, -0.25306198],\n", 118 | " [ 0.76248694, -2.12612262, 0.22683293, ..., -1.77898284,\n", 119 | " 0.18920119, -0.21655521],\n", 120 | " [ 0.76340745, -2.12427025, 0.22723139, ..., -1.77264512,\n", 121 | " 0.13341319, -0.18394688],\n", 122 | " ...,\n", 123 | " [-0.37115229, -0.94209769, -0.80942827, ..., -0.83010588,\n", 124 | " -0.33671693, -0.18123536],\n", 125 | " [-0.36992832, -0.94641663, -0.80781913, ..., -0.83002608,\n", 126 | " -0.31679034, -0.2233873 ],\n", 127 | " [-0.36928152, -0.95151261, -0.80686018, ..., -0.82970544,\n", 128 | " -0.30207706, -0.26081637]]),\n", 129 | " (1,\n", 130 | " 'Sitting',\n", 131 | " 'Sitting 2.54138969.h5'): array([[-1.99226199, -0.63286693, -1.53104102, ..., -0.22640553,\n", 132 | " -0.87610247, 0.46173938],\n", 133 | " [-1.99146732, -0.63314749, -1.5299443 , ..., -0.22127517,\n", 134 | " -0.89104581, 0.46743982],\n", 135 | " [-1.99051583, -0.63325858, -1.52888523, ..., -0.21564606,\n", 136 | " -0.90805098, 0.47376437],\n", 137 | " ...,\n", 138 | " [-1.36724228, 1.26395726, -0.87226214, ..., 1.07823601,\n", 139 | " -1.39730973, 0.95944207],\n", 140 | " [-1.36736729, 1.26413504, -0.87247907, ..., 1.07966884,\n", 141 | " -1.39662033, 0.95874632],\n", 142 | " [-1.3674983 , 1.26448741, -0.87268616, ..., 1.08058886,\n", 143 | " -1.39542298, 0.95676417]]),\n", 144 | " (1,\n", 145 | " 'Sitting',\n", 146 | " 'Sitting 2.55011271.h5'): array([[ 0.23498116, -1.087623 , -0.21422821, ..., -0.73701433,\n", 147 | " -0.67612616, 0.2108534 ],\n", 148 | " [ 0.23381288, -1.08780282, -0.21507242, ..., -0.73059169,\n", 149 | " -0.66283283, 0.21940282],\n", 150 | " [ 0.23239513, -1.08776182, -0.21631982, ..., -0.72421284,\n", 151 | " -0.64731448, 0.22878983],\n", 152 | " ...,\n", 153 | " [ 0.59393804, 0.11661192, 0.20648731, ..., 0.28992676,\n", 154 | " 0.56997843, 0.38833792],\n", 155 | " [ 0.59356683, 0.11716981, 0.20583659, ..., 0.29141153,\n", 156 | " 0.56975901, 0.3873544 ],\n", 157 | " [ 0.59336996, 0.11775898, 0.2053326 , ..., 0.29239511,\n", 158 | " 0.56862913, 0.38533682]]),\n", 159 | " (1,\n", 160 | " 'Sitting',\n", 161 | " 'Sitting 2.58860488.h5'): array([[ 1.46359454, -2.6285599 , 1.83708562, ..., -1.86025827,\n", 162 | " 1.90385851, -0.78484951],\n", 163 | " [ 1.46461057, -2.62878781, 1.83787996, ..., -1.85518337,\n", 164 | " 1.89098587, -0.77973622],\n", 165 | " [ 1.46584603, -2.62884329, 1.83900516, ..., -1.84964218,\n", 166 | " 1.87606656, -0.77410333],\n", 167 | " ...,\n", 168 | " [ 1.14862132, -0.81646865, 1.52048579, ..., -0.58565931,\n", 169 | " 0.78087545, -0.3609141 ],\n", 170 | " [ 1.14901089, -0.81626393, 1.52114697, ..., -0.58417553,\n", 171 | " 0.78105337, -0.36156163],\n", 172 | " [ 1.14922176, -0.81590728, 1.5216654 , ..., -0.58313785,\n", 173 | " 0.78210348, -0.36338097]]),\n", 174 | " (1,\n", 175 | " 'Sitting',\n", 176 | " 'Sitting 2.60457274.h5'): array([[ 1.0260695 , -2.15271509, 0.48001211, ..., -1.83711266,\n", 177 | " -0.17549174, -0.25118215],\n", 178 | " [ 1.02511667, -2.15273875, 0.47841703, ..., -1.82898768,\n", 179 | " -0.15323481, -0.24138933],\n", 180 | " [ 1.02396368, -2.15243102, 0.47693841, ..., -1.82108133,\n", 181 | " -0.12794737, -0.23082955],\n", 182 | " ...,\n", 183 | " [-0.08793134, -0.79509293, -0.60792539, ..., -0.5892274 ,\n", 184 | " 0.38605051, -0.27689845],\n", 185 | " [-0.08774396, -0.79425586, -0.60771263, ..., -0.58709011,\n", 186 | " 0.3851793 , -0.27814811],\n", 187 | " [-0.08757669, -0.7934344 , -0.60753794, ..., -0.58545675,\n", 188 | " 0.38388831, -0.28052545]]),\n", 189 | " (5,\n", 190 | " 'Sitting',\n", 191 | " 'Sitting 1.54138969.h5'): array([[-2.12916442, -0.61647881, -1.69889849, ..., -1.24669961,\n", 192 | " -0.03118341, -1.1566922 ],\n", 193 | " [-2.12924152, -0.61648612, -1.69901692, ..., -1.24667901,\n", 194 | " -0.03226165, -1.1559297 ],\n", 195 | " [-2.12900813, -0.61657269, -1.69880149, ..., -1.24676359,\n", 196 | " -0.03341926, -1.15460038],\n", 197 | " ...,\n", 198 | " [-1.71298949, 1.25683731, -1.29923314, ..., 1.36046774,\n", 199 | " -1.61219594, 0.81998105],\n", 200 | " [-1.71101999, 1.25776734, -1.29870914, ..., 1.35674326,\n", 201 | " -1.61106734, 0.81697893],\n", 202 | " [-1.70902735, 1.25974104, -1.29774669, ..., 1.3536488 ,\n", 203 | " -1.6102085 , 0.81478033]]),\n", 204 | " (5,\n", 205 | " 'Sitting',\n", 206 | " 'Sitting 1.55011271.h5'): array([[ 0.17364094, -1.06564502, -0.20991067, ..., -1.874322 ,\n", 207 | " -1.34346947, -1.67177046],\n", 208 | " [ 0.1743771 , -1.06600491, -0.20924196, ..., -1.87401358,\n", 209 | " -1.34438776, -1.67063382],\n", 210 | " [ 0.1751124 , -1.06664931, -0.20853968, ..., -1.87375179,\n", 211 | " -1.34556328, -1.66885114],\n", 212 | " ...,\n", 213 | " [ 0.75838696, 0.12414159, 0.37010231, ..., 0.6246253 ,\n", 214 | " 0.66472147, 0.24947369],\n", 215 | " [ 0.75844706, 0.12345876, 0.36978892, ..., 0.62052606,\n", 216 | " 0.66477502, 0.24591542],\n", 217 | " [ 0.75899364, 0.12335295, 0.37011968, ..., 0.61713039,\n", 218 | " 0.66498144, 0.24320071]]),\n", 219 | " (5,\n", 220 | " 'Sitting',\n", 221 | " 'Sitting 1.58860488.h5'): array([[ 1.09717572, -2.53819443, 1.43555819, ..., -2.85515329,\n", 222 | " 2.33332913, -2.42483934],\n", 223 | " [ 1.09655136, -2.53822178, 1.43499446, ..., -2.85509226,\n", 224 | " 2.33372263, -2.42398372],\n", 225 | " [ 1.0959489 , -2.53832736, 1.43444587, ..., -2.85513641,\n", 226 | " 2.33430957, -2.42252857],\n", 227 | " ...,\n", 228 | " [ 0.59674221, -0.75646604, 0.98034895, ..., -0.25136567,\n", 229 | " 0.37249321, -0.44631164],\n", 230 | " [ 0.59667238, -0.75552873, 0.98066862, ..., -0.25502516,\n", 231 | " 0.37234916, -0.44917072],\n", 232 | " [ 0.59611533, -0.75362452, 0.98038794, ..., -0.25807392,\n", 233 | " 0.37207516, -0.45127167]]),\n", 234 | " (5,\n", 235 | " 'Sitting',\n", 236 | " 'Sitting 1.60457274.h5'): array([[ 1.17980247, -1.67083902, 0.67869543, ..., -3.05749022,\n", 237 | " -1.31840268, -2.64575165],\n", 238 | " [ 1.17976965, -1.67148251, 0.67880769, ..., -3.05690364,\n", 239 | " -1.31728495, -2.64393726],\n", 240 | " [ 1.17926228, -1.6725443 , 0.6784126 , ..., -3.05634935,\n", 241 | " -1.31618272, -2.6411671 ],\n", 242 | " ...,\n", 243 | " [ 0.37703871, -0.39749991, -0.03157681, ..., 0.18602611,\n", 244 | " 0.68294765, -0.18420218],\n", 245 | " [ 0.37456 , -0.39862039, -0.03213613, ..., 0.18064478,\n", 246 | " 0.68171201, -0.18876928],\n", 247 | " [ 0.37194726, -0.39917422, -0.03330257, ..., 0.17617052,\n", 248 | " 0.68073654, -0.19229069]]),\n", 249 | " (5,\n", 250 | " 'Sitting',\n", 251 | " 'Sitting.54138969.h5'): array([[-2.00989765, -0.58997503, -1.58151116, ..., -1.34550739,\n", 252 | " 0.0936406 , -1.322103 ],\n", 253 | " [-2.0105878 , -0.58953286, -1.58231249, ..., -1.34317347,\n", 254 | " 0.09311779, -1.31920764],\n", 255 | " [-2.01096616, -0.58919678, -1.58275003, ..., -1.3409636 ,\n", 256 | " 0.09257246, -1.31562294],\n", 257 | " ...,\n", 258 | " [-1.93896006, 0.92524356, -1.51251016, ..., 1.00015319,\n", 259 | " -1.66705262, 1.46358937],\n", 260 | " [-1.93861506, 0.92565349, -1.51213462, ..., 1.00064939,\n", 261 | " -1.66644786, 1.46313445],\n", 262 | " [-1.93798254, 0.92578365, -1.51149002, ..., 1.00126088,\n", 263 | " -1.66591553, 1.46225848]]),\n", 264 | " (5,\n", 265 | " 'Sitting',\n", 266 | " 'Sitting.55011271.h5'): array([[ 0.18732811, -1.12059585, -0.19241504, ..., -2.01290366,\n", 267 | " -1.27505243, -1.8736572 ],\n", 268 | " [ 0.1887663 , -1.12047417, -0.19115796, ..., -2.01040509,\n", 269 | " -1.27572989, -1.87053935],\n", 270 | " [ 0.189899 , -1.1204946 , -0.19013062, ..., -2.00801866,\n", 271 | " -1.27646919, -1.86670607],\n", 272 | " ...,\n", 273 | " [ 0.69200204, 0.03410101, 0.30225442, ..., 0.63386592,\n", 274 | " 0.06995111, 1.30313522],\n", 275 | " [ 0.69209996, 0.03415698, 0.30238429, ..., 0.63367573,\n", 276 | " 0.06936173, 1.30257489],\n", 277 | " [ 0.6917756 , 0.03403455, 0.30210631, ..., 0.63349704,\n", 278 | " 0.06871512, 1.3016569 ]]),\n", 279 | " (5,\n", 280 | " 'Sitting',\n", 281 | " 'Sitting.58860488.h5'): array([[ 1.0946958 , -2.51353653, 1.43651415, ..., -2.96239451,\n", 282 | " 2.31365952, -2.60590959],\n", 283 | " [ 1.09341831, -2.51314667, 1.43536588, ..., -2.95999233,\n", 284 | " 2.31413626, -2.60282684],\n", 285 | " [ 1.09242367, -2.51285227, 1.43445476, ..., -2.95771137,\n", 286 | " 2.31467764, -2.59901537],\n", 287 | " ...,\n", 288 | " [ 0.65975652, -1.07519559, 1.02958539, ..., -0.60640058,\n", 289 | " 0.92631713, 0.20084568],\n", 290 | " [ 0.65966656, -1.07480214, 1.02949031, ..., -0.60584758,\n", 291 | " 0.92684796, 0.20045204],\n", 292 | " [ 0.65998659, -1.07464358, 1.02979246, ..., -0.60512882,\n", 293 | " 0.92741122, 0.1996513 ]]),\n", 294 | " (5,\n", 295 | " 'Sitting',\n", 296 | " 'Sitting.60457274.h5'): array([[ 0.9929018 , -1.76522044, 0.50066044, ..., -3.26993718,\n", 297 | " -1.44603093, -2.95365977],\n", 298 | " [ 0.99364584, -1.7653212 , 0.50170809, ..., -3.26642589,\n", 299 | " -1.44583028, -2.94909275],\n", 300 | " [ 0.99398499, -1.76557733, 0.50224732, ..., -3.26305912,\n", 301 | " -1.44568233, -2.94349122],\n", 302 | " ...,\n", 303 | " [ 0.69466612, -0.45909939, 0.25797898, ..., 0.29279405,\n", 304 | " 0.79987471, 1.30425187],\n", 305 | " [ 0.69416808, -0.45910781, 0.25746131, ..., 0.29259406,\n", 306 | " 0.79910285, 1.30365165],\n", 307 | " [ 0.69336651, -0.45924866, 0.25663828, ..., 0.29256216,\n", 308 | " 0.79849719, 1.30262523]]),\n", 309 | " (6,\n", 310 | " 'Sitting',\n", 311 | " 'Sitting 1.54138969.h5'): array([[-1.53248849, -1.29396288, -1.06293207, ..., -0.66217798,\n", 312 | " -0.72848746, 0.16330382],\n", 313 | " [-1.53218829, -1.29379996, -1.06271302, ..., -0.66193202,\n", 314 | " -0.72834022, 0.16357056],\n", 315 | " [-1.53195443, -1.29364856, -1.06252153, ..., -0.6616278 ,\n", 316 | " -0.72811289, 0.16395559],\n", 317 | " ...,\n", 318 | " [-0.61657485, 1.20754581, -0.12625561, ..., 1.29561518,\n", 319 | " -0.42864301, 1.35076878],\n", 320 | " [-0.61681108, 1.20799363, -0.12665917, ..., 1.29271601,\n", 321 | " -0.43277066, 1.34809649],\n", 322 | " [-0.61680149, 1.20827185, -0.12671201, ..., 1.29008991,\n", 323 | " -0.436532 , 1.34558422]]),\n", 324 | " (6,\n", 325 | " 'Sitting',\n", 326 | " 'Sitting 1.55011271.h5'): array([[-0.35325123, -1.77413056, -0.79661881, ..., -1.19781068,\n", 327 | " -0.88237936, -0.0938747 ],\n", 328 | " [-0.35328121, -1.77409452, -0.7967143 , ..., -1.19760191,\n", 329 | " -0.88230833, -0.09367387],\n", 330 | " [-0.35330813, -1.77403803, -0.79678238, ..., -1.19732742,\n", 331 | " -0.88224594, -0.09337551],\n", 332 | " ...,\n", 333 | " [ 0.18536708, -0.13418689, -0.20960309, ..., 0.43018627,\n", 334 | " -0.61741947, 0.881875 ],\n", 335 | " [ 0.1861882 , -0.13418624, -0.20892874, ..., 0.42913446,\n", 336 | " -0.61539176, 0.88050488],\n", 337 | " [ 0.18650486, -0.13415705, -0.20863554, ..., 0.42798888,\n", 338 | " -0.61349461, 0.87915135]]),\n", 339 | " (6,\n", 340 | " 'Sitting',\n", 341 | " 'Sitting 1.58860488.h5'): array([[ 1.78990099, -3.14535119, 2.18500381, ..., -2.21140679,\n", 342 | " 1.95289067, -1.00826858],\n", 343 | " [ 1.78997022, -3.14519367, 2.18512505, ..., -2.21116368,\n", 344 | " 1.95287968, -1.00799927],\n", 345 | " [ 1.79002748, -3.14504672, 2.18522169, ..., -2.21086208,\n", 346 | " 1.95289749, -1.00760954],\n", 347 | " ...,\n", 348 | " [ 1.44117519, -0.67952726, 1.86869217, ..., -0.21149106,\n", 349 | " 1.8363619 , 0.19517034],\n", 350 | " [ 1.44031399, -0.67915772, 1.86793998, ..., -0.21451784,\n", 351 | " 1.83372577, 0.19218236],\n", 352 | " [ 1.43999072, -0.67890662, 1.86762704, ..., -0.21733348,\n", 353 | " 1.83128141, 0.18937918]]),\n", 354 | " (6,\n", 355 | " 'Sitting',\n", 356 | " 'Sitting 1.60457274.h5'): array([[ 0.46437264, -2.59123809, -0.12490955, ..., -2.13349689,\n", 357 | " -0.36133088, -0.42449071],\n", 358 | " [ 0.46389533, -2.59123512, -0.12524992, ..., -2.13323454,\n", 359 | " -0.36157977, -0.42425094],\n", 360 | " [ 0.46352198, -2.59119479, -0.12555812, ..., -2.13288023,\n", 361 | " -0.36196186, -0.42388675],\n", 362 | " ...,\n", 363 | " [-0.92730696, -0.72905174, -1.44167779, ..., -0.04007673,\n", 364 | " -0.87072854, 0.78858536],\n", 365 | " [-0.9269943 , -0.72925724, -1.44107279, ..., -0.04105624,\n", 366 | " -0.86497185, 0.78660666],\n", 367 | " [-0.92699123, -0.72931026, -1.44093389, ..., -0.04239849,\n", 368 | " -0.85971199, 0.78465147]]),\n", 369 | " (6,\n", 370 | " 'Sitting',\n", 371 | " 'Sitting 2.54138969.h5'): array([[-1.24450227, -1.2871166 , -0.76983446, ..., -0.68186538,\n", 372 | " -0.32696201, 0.15182536],\n", 373 | " [-1.24443962, -1.28712864, -0.76980454, ..., -0.68337346,\n", 374 | " -0.32789305, 0.15261208],\n", 375 | " [-1.24450814, -1.28719092, -0.76983492, ..., -0.68414247,\n", 376 | " -0.32848212, 0.15359459],\n", 377 | " ...,\n", 378 | " [-0.63118047, 1.17344909, -0.15475129, ..., 1.21619633,\n", 379 | " 0.17064667, 1.55697583],\n", 380 | " [-0.63385549, 1.15822 , -0.1581342 , ..., 1.20461513,\n", 381 | " 0.16591167, 1.56047006],\n", 382 | " [-0.63803962, 1.14479298, -0.16277092, ..., 1.19302691,\n", 383 | " 0.16002629, 1.5636896 ]]),\n", 384 | " (6,\n", 385 | " 'Sitting',\n", 386 | " 'Sitting 2.55011271.h5'): array([[-0.49041398, -1.85427771, -0.90586455, ..., -1.3037019 ,\n", 387 | " -1.07488896, -0.21235501],\n", 388 | " [-0.49051543, -1.85427957, -0.90601032, ..., -1.30589282,\n", 389 | " -1.07075646, -0.21258806],\n", 390 | " [-0.49048223, -1.85432661, -0.90593436, ..., -1.30706403,\n", 391 | " -1.0677832 , -0.21234412],\n", 392 | " ...,\n", 393 | " [ 0.25271524, -0.20092586, -0.1581692 , ..., 0.21486691,\n", 394 | " -0.81036422, 0.85021655],\n", 395 | " [ 0.24945887, -0.21061909, -0.16209557, ..., 0.21560461,\n", 396 | " -0.81480107, 0.8584195 ],\n", 397 | " [ 0.24811779, -0.21902942, -0.16410533, ..., 0.21663628,\n", 398 | " -0.81808293, 0.86638882]]),\n", 399 | " (6,\n", 400 | " 'Sitting',\n", 401 | " 'Sitting 2.58860488.h5'): array([[ 1.94354829, -3.13984477, 2.33282301, ..., -2.2419912 ,\n", 402 | " 2.20304657, -1.01507293],\n", 403 | " [ 1.94364033, -3.1398557 , 2.3329459 , ..., -2.24359362,\n", 404 | " 2.1996105 , -1.01436332],\n", 405 | " [ 1.94360121, -3.13991745, 2.33287891, ..., -2.24441457,\n", 406 | " 2.19717029, -1.01342271],\n", 407 | " ...,\n", 408 | " [ 1.369311 , -0.71956892, 1.8115754 , ..., -0.2972683 ,\n", 409 | " 2.14562664, 0.44465224],\n", 410 | " [ 1.37231433, -0.73452708, 1.81491263, ..., -0.30876858,\n", 411 | " 2.14858256, 0.4483758 ],\n", 412 | " [ 1.37324122, -0.74790135, 1.81617613, ..., -0.32038852,\n", 413 | " 2.15019233, 0.45168011]]),\n", 414 | " (6,\n", 415 | " 'Sitting',\n", 416 | " 'Sitting 2.60457274.h5'): array([[ 0.04057977, -2.71463661, -0.55912325, ..., -2.31280463,\n", 417 | " -0.95876945, -0.59538521],\n", 418 | " [ 0.040495 , -2.71462787, -0.55917455, ..., -2.31609507,\n", 419 | " -0.95699071, -0.59641027],\n", 420 | " [ 0.04059929, -2.71468612, -0.55912765, ..., -2.31787186,\n", 421 | " -0.95586362, -0.59658785],\n", 422 | " ...,\n", 423 | " [-0.90288868, -0.83125364, -1.39823799, ..., -0.37444127,\n", 424 | " -1.64502029, 0.74511404],\n", 425 | " [-0.89935135, -0.84239216, -1.39453501, ..., -0.36949196,\n", 426 | " -1.64115648, 0.75775494],\n", 427 | " [-0.89408327, -0.8522714 , -1.38928036, ..., -0.36423307,\n", 428 | " -1.63564056, 0.76987076]]),\n", 429 | " (7,\n", 430 | " 'Sitting',\n", 431 | " 'Sitting 1.54138969.h5'): array([[-1.35459181, -0.9322084 , -0.94921353, ..., -0.29451232,\n", 432 | " -0.57060942, 0.36264918],\n", 433 | " [-1.35310828, -0.93191902, -0.94808633, ..., -0.29201663,\n", 434 | " -0.56704776, 0.36529009],\n", 435 | " [-1.35257311, -0.9303765 , -0.94713503, ..., -0.28878696,\n", 436 | " -0.56268932, 0.36817192],\n", 437 | " ...,\n", 438 | " [-2.75649329, -0.9342513 , -2.27544722, ..., -0.31826911,\n", 439 | " -1.51153196, 0.37810625],\n", 440 | " [-2.75623146, -0.93386157, -2.27494367, ..., -0.31916939,\n", 441 | " -1.51243577, 0.37620907],\n", 442 | " [-2.75594309, -0.93394351, -2.27464127, ..., -0.32065094,\n", 443 | " -1.51303365, 0.37324167]]),\n", 444 | " (7,\n", 445 | " 'Sitting',\n", 446 | " 'Sitting 1.55011271.h5'): array([[-2.10011115, -0.84382797, -2.48258226, ..., -0.48203099,\n", 447 | " -2.2251756 , 0.46689264],\n", 448 | " [-2.09941113, -0.84470872, -2.48224594, ..., -0.4795012 ,\n", 449 | " -2.2251531 , 0.46827907],\n", 450 | " [-2.09599376, -0.84464086, -2.47826608, ..., -0.47641657,\n", 451 | " -2.22494945, 0.46946752],\n", 452 | " ...,\n", 453 | " [-0.43352419, -0.70353284, -0.88029266, ..., -0.46774915,\n", 454 | " -0.93253083, 0.48091744],\n", 455 | " [-0.43282728, -0.70362434, -0.87910052, ..., -0.46777781,\n", 456 | " -0.93665054, 0.48103104],\n", 457 | " [-0.43300944, -0.70385077, -0.87921267, ..., -0.46860725,\n", 458 | " -0.94197202, 0.48018445]]),\n", 459 | " (7,\n", 460 | " 'Sitting',\n", 461 | " 'Sitting 1.58860488.h5'): array([[ 2.86229103, -2.79153951, 3.19629471, ..., -1.86162919,\n", 462 | " 2.77154611, -0.7992476 ],\n", 463 | " [ 2.86238262, -2.79126748, 3.19654724, ..., -1.85903091,\n", 464 | " 2.77313423, -0.79644443],\n", 465 | " [ 2.86053186, -2.78976815, 3.19463923, ..., -1.85567492,\n", 466 | " 2.77496306, -0.79338468],\n", 467 | " ...,\n", 468 | " [ 1.46597081, -2.81764897, 1.8114687 , ..., -1.87558074,\n", 469 | " 1.65664028, -0.82001847],\n", 470 | " [ 1.46555811, -2.81728878, 1.81082909, ..., -1.87644608,\n", 471 | " 1.65905782, -0.82181045],\n", 472 | " [ 1.46571911, -2.81736668, 1.81096466, ..., -1.87789173,\n", 473 | " 1.66229941, -0.82463726]]),\n", 474 | " (7,\n", 475 | " 'Sitting',\n", 476 | " 'Sitting 1.60457274.h5'): array([[ 0.17027402, -0.79916832, -0.48724204, ..., -0.79848503,\n", 477 | " -0.83566891, 0.75689889],\n", 478 | " [ 0.16748598, -0.80094762, -0.48929702, ..., -0.79525764,\n", 479 | " -0.84230839, 0.75842967],\n", 480 | " [ 0.16624045, -0.80204962, -0.49105544, ..., -0.79155361,\n", 481 | " -0.85035242, 0.75949304],\n", 482 | " ...,\n", 483 | " [ 2.51717514, -0.84172409, 1.83696063, ..., -0.90256709,\n", 484 | " 0.84295038, 0.53980659],\n", 485 | " [ 2.51630501, -0.84213268, 1.83550143, ..., -0.90186523,\n", 486 | " 0.84557127, 0.54128717],\n", 487 | " [ 2.51580126, -0.84243558, 1.83493126, ..., -0.90224092,\n", 488 | " 0.84798339, 0.54176204]]),\n", 489 | " (7,\n", 490 | " 'Sitting',\n", 491 | " 'Sitting.54138969.h5'): array([[-0.27209974, -0.5398484 , 0.14061248, ..., -0.05002655,\n", 492 | " 0.31840466, 0.63211754],\n", 493 | " [-0.27150649, -0.54013873, 0.14032765, ..., -0.05139638,\n", 494 | " 0.31899429, 0.63077333],\n", 495 | " [-0.27088034, -0.54103017, 0.14072023, ..., -0.05247588,\n", 496 | " 0.32002465, 0.6297822 ],\n", 497 | " ...,\n", 498 | " [-0.95571552, -0.38823733, -0.48117882, ..., 0.08218474,\n", 499 | " -0.03160512, 0.80184705],\n", 500 | " [-0.95202199, -0.37155215, -0.47726933, ..., 0.10352182,\n", 501 | " -0.04142031, 0.81781247],\n", 502 | " [-0.94780564, -0.36559009, -0.47323115, ..., 0.11017991,\n", 503 | " -0.04930847, 0.82292636]]),\n", 504 | " (7,\n", 505 | " 'Sitting',\n", 506 | " 'Sitting.55011271.h5'): array([[-1.27715345e+00, -1.36334178e+00, -1.62597276e+00, ...,\n", 507 | " -8.52981646e-01, -1.49879372e+00, 7.17847884e-02],\n", 508 | " [-1.27806679e+00, -1.36353335e+00, -1.62776368e+00, ...,\n", 509 | " -8.53739042e-01, -1.50173645e+00, 7.12799496e-02],\n", 510 | " [-1.27956227e+00, -1.36409954e+00, -1.62937701e+00, ...,\n", 511 | " -8.54145154e-01, -1.50504186e+00, 7.10803389e-02],\n", 512 | " ...,\n", 513 | " [-4.08373913e-03, -1.45575843e+00, -3.83472126e-01, ...,\n", 514 | " -9.07539987e-01, -5.25741898e-01, 4.83843097e-04],\n", 515 | " [-4.43365115e-03, -1.44178054e+00, -3.83572833e-01, ...,\n", 516 | " -8.87964906e-01, -5.19890628e-01, 1.68601136e-02],\n", 517 | " [-9.73906693e-04, -1.44001964e+00, -3.80264532e-01, ...,\n", 518 | " -8.81882029e-01, -5.14663087e-01, 2.27257924e-02]]),\n", 519 | " (7,\n", 520 | " 'Sitting',\n", 521 | " 'Sitting.58860488.h5'): array([[ 2.6199919 , -2.41456594, 3.00144859, ..., -1.64030015,\n", 522 | " 2.62371953, -0.52551709],\n", 523 | " [ 2.62090374, -2.41483606, 3.00279882, ..., -1.6417155 ,\n", 524 | " 2.62628945, -0.52683512],\n", 525 | " [ 2.6222934 , -2.41570956, 3.00422916, ..., -1.64281615,\n", 526 | " 2.62932197, -0.52775548],\n", 527 | " ...,\n", 528 | " [ 1.35513143, -2.30649458, 1.7610985 , ..., -1.51693489,\n", 529 | " 1.66862676, -0.39302173],\n", 530 | " [ 1.35616525, -2.28990291, 1.76205824, ..., -1.49511134,\n", 531 | " 1.66144024, -0.37694803],\n", 532 | " [ 1.35334508, -2.28412954, 1.75969246, ..., -1.48831846,\n", 533 | " 1.65497142, -0.37202384]]),\n", 534 | " (7,\n", 535 | " 'Sitting',\n", 536 | " 'Sitting.60457274.h5'): array([[-1.43754415, -1.9362377 , -1.9875055 , ..., -1.6362124 ,\n", 537 | " -1.96721943, -0.12010905],\n", 538 | " [-1.43848036, -1.93636733, -1.9876703 , ..., -1.63689797,\n", 539 | " -1.9689461 , -0.12023359],\n", 540 | " [-1.43954594, -1.93688374, -1.98863157, ..., -1.63703578,\n", 541 | " -1.97137439, -0.11988475],\n", 542 | " ...,\n", 543 | " [-0.42106045, -2.25969965, -0.9564295 , ..., -1.82622198,\n", 544 | " -1.26704101, -0.3902903 ],\n", 545 | " [-0.42664356, -2.24190098, -0.96174988, ..., -1.8001073 ,\n", 546 | " -1.25613206, -0.36854898],\n", 547 | " [-0.43181674, -2.24093065, -0.96630833, ..., -1.79211153,\n", 548 | " -1.24662889, -0.36099121]]),\n", 549 | " (8,\n", 550 | " 'Sitting',\n", 551 | " 'Sitting 1.54138969.h5'): array([[-1.09492193, -0.40109424, -0.58197328, ..., -1.49058468,\n", 552 | " 1.00776602, -1.23804695],\n", 553 | " [-1.09511988, -0.40107651, -0.58220778, ..., -1.49073238,\n", 554 | " 1.00761933, -1.23831914],\n", 555 | " [-1.0955076 , -0.40084594, -0.58220278, ..., -1.49050039,\n", 556 | " 1.00711641, -1.23884682],\n", 557 | " ...,\n", 558 | " [-0.60856171, 2.71280526, -0.06646745, ..., 1.85299387,\n", 559 | " -0.16838538, 1.91281852],\n", 560 | " [-0.60833994, 2.71547025, -0.06524655, ..., 1.86089667,\n", 561 | " -0.16825434, 1.90891414],\n", 562 | " [-0.60799215, 2.71824772, -0.06366969, ..., 1.86967751,\n", 563 | " -0.16784899, 1.90625593]]),\n", 564 | " (8,\n", 565 | " 'Sitting',\n", 566 | " 'Sitting 1.55011271.h5'): array([[ 0.00659346, -1.79009896, -0.42257191, ..., -2.49129052,\n", 567 | " -1.47338953, -2.02947747],\n", 568 | " [ 0.00653765, -1.78995985, -0.42265577, ..., -2.49141777,\n", 569 | " -1.4734646 , -2.02968742],\n", 570 | " [ 0.0069772 , -1.78979063, -0.42198841, ..., -2.49108167,\n", 571 | " -1.47382194, -2.0300429 ],\n", 572 | " ...,\n", 573 | " [ 0.71312234, -0.03615399, 0.30810691, ..., -0.02440355,\n", 574 | " 0.01138924, 0.45177059],\n", 575 | " [ 0.71433588, -0.0353561 , 0.3099339 , ..., -0.02367386,\n", 576 | " 0.01568334, 0.4460968 ],\n", 577 | " [ 0.71559218, -0.03459455, 0.3120034 , ..., -0.02230678,\n", 578 | " 0.01984549, 0.441349 ]]),\n", 579 | " (8,\n", 580 | " 'Sitting',\n", 581 | " 'Sitting 1.58860488.h5'): array([[ 0.61323705, -2.41650931, 1.09666416, ..., -3.22746868,\n", 582 | " 2.24034574, -2.61291006],\n", 583 | " [ 0.61330007, -2.4164881 , 1.09673797, ..., -3.22762088,\n", 584 | " 2.24037172, -2.6131949 ],\n", 585 | " [ 0.61282243, -2.4162774 , 1.096033 , ..., -3.22734371,\n", 586 | " 2.24057735, -2.61373493],\n", 587 | " ...,\n", 588 | " [-0.23832714, 0.54043675, 0.2789543 , ..., 0.18680357,\n", 589 | " 0.49498397, 0.60676818],\n", 590 | " [-0.24001617, 0.54281956, 0.27644652, ..., 0.19447078,\n", 591 | " 0.48948615, 0.60248219],\n", 592 | " [-0.24177996, 0.54530814, 0.27358433, ..., 0.20299249,\n", 593 | " 0.48417695, 0.59945368]]),\n", 594 | " (8,\n", 595 | " 'Sitting',\n", 596 | " 'Sitting 1.60457274.h5'): array([[-6.27870350e-02, -2.79342404e+00, -5.88656098e-01, ...,\n", 597 | " -4.01748506e+00, -2.19454054e+00, -3.23058948e+00],\n", 598 | " [-6.25696238e-02, -2.79321274e+00, -5.88412546e-01, ...,\n", 599 | " -4.01765663e+00, -2.19441545e+00, -3.23087326e+00],\n", 600 | " [-6.21462374e-02, -2.79303118e+00, -5.88354377e-01, ...,\n", 601 | " -4.01713503e+00, -2.19406228e+00, -3.23133309e+00],\n", 602 | " ...,\n", 603 | " [-6.54711069e-01, -8.20643063e-01, -1.10822323e+00, ...,\n", 604 | " -8.35387426e-01, -8.45673188e-01, 9.91192758e-04],\n", 605 | " [-6.54862663e-01, -8.19997689e-01, -1.10893298e+00, ...,\n", 606 | " -8.35848267e-01, -8.44639182e-01, -7.02769750e-03],\n", 607 | " [-6.55119068e-01, -8.19418776e-01, -1.10987147e+00, ...,\n", 608 | " -8.35519077e-01, -8.43956739e-01, -1.38727192e-02]]),\n", 609 | " (8,\n", 610 | " 'Sitting',\n", 611 | " 'Sitting.54138969.h5'): array([[-1.01844028, -0.42001032, -0.52246691, ..., -1.60883553,\n", 612 | " 1.03457198, -1.41970009],\n", 613 | " [-1.01864803, -0.42002437, -0.52277296, ..., -1.60798536,\n", 614 | " 1.03481065, -1.41900541],\n", 615 | " [-1.01883342, -0.41999394, -0.52306177, ..., -1.60734118,\n", 616 | " 1.03508913, -1.41830682],\n", 617 | " ...,\n", 618 | " [-0.67765888, 2.67277501, -0.13465417, ..., 1.96441525,\n", 619 | " -0.18544381, 1.92082496],\n", 620 | " [-0.67791692, 2.67194528, -0.1350059 , ..., 1.96555243,\n", 621 | " -0.18730757, 1.92912801],\n", 622 | " [-0.67798957, 2.67102927, -0.13523999, ..., 1.96646412,\n", 623 | " -0.1901317 , 1.93535744]]),\n", 624 | " (8,\n", 625 | " 'Sitting',\n", 626 | " 'Sitting.55011271.h5'): array([[-0.13774992, -1.77174881, -0.56921793, ..., -2.58608274,\n", 627 | " -1.60682822, -2.17986645],\n", 628 | " [-0.13772836, -1.77167199, -0.56925933, ..., -2.5853758 ,\n", 629 | " -1.60691169, -2.17927052],\n", 630 | " [-0.13770594, -1.77156677, -0.56930066, ..., -2.58482606,\n", 631 | " -1.60698208, -2.17867682],\n", 632 | " ...,\n", 633 | " [ 0.69821589, -0.00777921, 0.28747572, ..., 0.06834162,\n", 634 | " -0.00587822, 0.47679339],\n", 635 | " [ 0.69774738, -0.00783072, 0.2869935 , ..., 0.07172104,\n", 636 | " -0.00567711, 0.48416688],\n", 637 | " [ 0.69712671, -0.00794081, 0.28628481, ..., 0.07457792,\n", 638 | " -0.00437857, 0.48972913]]),\n", 639 | " (8,\n", 640 | " 'Sitting',\n", 641 | " 'Sitting.58860488.h5'): array([[ 0.770647 , -2.4300513 , 1.25503187, ..., -3.35816098,\n", 642 | " 2.37665448, -2.81350834],\n", 643 | " [ 0.77061988, -2.43006406, 1.25504818, ..., -3.35729898,\n", 644 | " 2.37683524, -2.81277433],\n", 645 | " [ 0.77059321, -2.43003352, 1.25506635, ..., -3.35664469,\n", 646 | " 2.37701526, -2.81203888],\n", 647 | " ...,\n", 648 | " [-0.20959854, 0.50178313, 0.31071496, ..., 0.30314102,\n", 649 | " 0.51687765, 0.61586537],\n", 650 | " [-0.20893034, 0.50104759, 0.31135894, ..., 0.30418081,\n", 651 | " 0.51684585, 0.62402557],\n", 652 | " [-0.2080749 , 0.50025874, 0.31230976, ..., 0.30494033,\n", 653 | " 0.51539739, 0.62999106]]),\n", 654 | " (8,\n", 655 | " 'Sitting',\n", 656 | " 'Sitting.60457274.h5'): array([[-0.15065052, -2.75295085, -0.67033545, ..., -4.1511286 ,\n", 657 | " -2.26902871, -3.44614522],\n", 658 | " [-0.15041634, -2.75283081, -0.67000686, ..., -4.15019302,\n", 659 | " -2.26935287, -3.44531837],\n", 660 | " [-0.15021008, -2.75267756, -0.66969825, ..., -4.14946051,\n", 661 | " -2.26970997, -3.44449774],\n", 662 | " ...,\n", 663 | " [-0.59636538, -0.77599999, -1.05752428, ..., -0.71229913,\n", 664 | " -0.83465875, 0.03731348],\n", 665 | " [-0.59616247, -0.77591906, -1.05727989, ..., -0.70750134,\n", 666 | " -0.83351288, 0.04669861],\n", 667 | " [-0.59613232, -0.77588737, -1.05720179, ..., -0.70348859,\n", 668 | " -0.83115015, 0.0536501 ]])}" 669 | ] 670 | }, 671 | "execution_count": 5, 672 | "metadata": {}, 673 | "output_type": "execute_result" 674 | } 675 | ], 676 | "source": [ 677 | "train_set" 678 | ] 679 | }, 680 | { 681 | "cell_type": "markdown", 682 | "metadata": {}, 683 | "source": [ 684 | "## Extract a seqence from the training sequences" 685 | ] 686 | }, 687 | { 688 | "cell_type": "code", 689 | "execution_count": 6, 690 | "metadata": {}, 691 | "outputs": [], 692 | "source": [ 693 | "def get_sequences(poses_set, seq_idx):\n", 694 | " n_cams = 4 # number of cameras per sequence.\n", 695 | " \n", 696 | " sequences = []\n", 697 | " for cam_idx in range(n_cams):\n", 698 | " pose_seq = list(poses_set.values())[seq_idx * n_cams + cam_idx]\n", 699 | " sequences.append(pose_seq)\n", 700 | " \n", 701 | " return sequences" 702 | ] 703 | }, 704 | { 705 | "cell_type": "code", 706 | "execution_count": 7, 707 | "metadata": {}, 708 | "outputs": [], 709 | "source": [ 710 | "seq_idx = 0\n", 711 | "pose_seqs_normalized = get_sequences(train_set, seq_idx) # 4 pose sets from 4 cameras of the same sequence" 712 | ] 713 | }, 714 | { 715 | "cell_type": "markdown", 716 | "metadata": {}, 717 | "source": [ 718 | "## Un-normalize poses" 719 | ] 720 | }, 721 | { 722 | "cell_type": "code", 723 | "execution_count": 8, 724 | "metadata": {}, 725 | "outputs": [], 726 | "source": [ 727 | "pose_seqs = []\n", 728 | "\n", 729 | "for pose_seq in pose_seqs_normalized:\n", 730 | " pose_seq = data_utils.unnormalize_data(pose_seq, data_mean, data_std, dim_to_ignore)\n", 731 | " pose_seqs.append(pose_seq)" 732 | ] 733 | }, 734 | { 735 | "cell_type": "markdown", 736 | "metadata": {}, 737 | "source": [ 738 | "## Plot a 2d pose in the sequence!" 739 | ] 740 | }, 741 | { 742 | "cell_type": "code", 743 | "execution_count": 9, 744 | "metadata": {}, 745 | "outputs": [ 746 | { 747 | "data": { 748 | "image/png": "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\n", 749 | "text/plain": [ 750 | "
" 751 | ] 752 | }, 753 | "metadata": {}, 754 | "output_type": "display_data" 755 | } 756 | ], 757 | "source": [ 758 | "frame_idx = 300\n", 759 | "\n", 760 | "cam_idx = 3\n", 761 | "assert cam_idx >= 0 and cam_idx <= 4\n", 762 | "\n", 763 | "fig = plt.figure(figsize=(6, 6))\n", 764 | "ax = fig.add_subplot(111)\n", 765 | "vis_utils.show_2d_pose(pose_seqs[cam_idx][frame_idx], ax)" 766 | ] 767 | }, 768 | { 769 | "cell_type": "markdown", 770 | "metadata": {}, 771 | "source": [ 772 | "## Plot 2d poses projected to the 4 cameras!" 773 | ] 774 | }, 775 | { 776 | "cell_type": "code", 777 | "execution_count": 10, 778 | "metadata": {}, 779 | "outputs": [ 780 | { 781 | "data": { 782 | "image/png": "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\n", 783 | "text/plain": [ 784 | "
" 785 | ] 786 | }, 787 | "metadata": {}, 788 | "output_type": "display_data" 789 | } 790 | ], 791 | "source": [ 792 | "frame_idx = 300\n", 793 | "\n", 794 | "fig = plt.figure(figsize=(16, 8))\n", 795 | "\n", 796 | "# 1st camera\n", 797 | "ax = fig.add_subplot(\"141\")\n", 798 | "vis_utils.show_2d_pose(pose_seqs[0][frame_idx], ax)\n", 799 | "ax.set_title(\"1st camera\")\n", 800 | "\n", 801 | "# 2nd camera\n", 802 | "ax = fig.add_subplot(\"142\")\n", 803 | "vis_utils.show_2d_pose(pose_seqs[1][frame_idx], ax)\n", 804 | "ax.set_title(\"2nd camera\")\n", 805 | "\n", 806 | "# 3rd camera\n", 807 | "ax = fig.add_subplot(\"143\")\n", 808 | "vis_utils.show_2d_pose(pose_seqs[2][frame_idx], ax)\n", 809 | "ax.set_title(\"3rd camera\")\n", 810 | "\n", 811 | "# 4th camera\n", 812 | "ax = fig.add_subplot(\"144\")\n", 813 | "vis_utils.show_2d_pose(pose_seqs[3][frame_idx], ax)\n", 814 | "ax.set_title(\"4th camera\");" 815 | ] 816 | }, 817 | { 818 | "cell_type": "code", 819 | "execution_count": null, 820 | "metadata": {}, 821 | "outputs": [], 822 | "source": [] 823 | } 824 | ], 825 | "metadata": { 826 | "kernelspec": { 827 | "display_name": "Python 3", 828 | "language": "python", 829 | "name": "python3" 830 | }, 831 | "language_info": { 832 | "codemirror_mode": { 833 | "name": "ipython", 834 | "version": 3 835 | }, 836 | "file_extension": ".py", 837 | "mimetype": "text/x-python", 838 | "name": "python", 839 | "nbconvert_exporter": "python", 840 | "pygments_lexer": "ipython3", 841 | "version": "3.7.7" 842 | } 843 | }, 844 | "nbformat": 4, 845 | "nbformat_minor": 4 846 | } 847 | -------------------------------------------------------------------------------- /notebooks/visualize_3d_pose.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import matplotlib.pyplot as plt\n", 10 | "from mpl_toolkits.mplot3d import Axes3D\n", 11 | "%matplotlib inline" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 2, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "import sys\n", 21 | "sys.path.append(\"../human_3d_pose_baseline/\")\n", 22 | "from utils import camera_utils, data_utils, vis_utils" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "## Load Human3.6M camera parameters" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 3, 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [ 38 | "cams = camera_utils.load_cameras(\"../dataset/h36m/cameras.h5\")" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "## Load Human3.6M 3d poses" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 4, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "actions = [\"Sitting\",] # actions to load.\n", 55 | "camera_frame = False # whether transform 3d poses into the camera frame from the original world frame or not.\n", 56 | "\n", 57 | "train_set, test_set, data_mean, data_std, dim_to_ignore, dim_to_use, train_root_positions, test_root_positions = \\\n", 58 | " data_utils.read_3d_data(actions, \"../dataset/h36m/\", cams, camera_frame=camera_frame, predict_14=False)" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 5, 64 | "metadata": { 65 | "scrolled": false 66 | }, 67 | "outputs": [ 68 | { 69 | "data": { 70 | "text/plain": [ 71 | "{(1,\n", 72 | " 'Sitting',\n", 73 | " 'Sitting 1.h5'): array([[-0.04467541, -0.85151713, 0.20741998, ..., -0.15090777,\n", 74 | " -0.14984435, -0.94343514],\n", 75 | " [-0.04697797, -0.83760562, 0.21784643, ..., -0.19492098,\n", 76 | " -0.08145451, -0.98522693],\n", 77 | " [-0.04920342, -0.82721392, 0.21596948, ..., -0.24358793,\n", 78 | " -0.00638867, -1.02458465],\n", 79 | " ...,\n", 80 | " [ 0.11116181, -1.37522818, 0.44217934, ..., 0.35248767,\n", 81 | " -0.21254123, -0.31766016],\n", 82 | " [ 0.11511766, -1.37958726, 0.47266568, ..., 0.3837098 ,\n", 83 | " -0.21527164, -0.28132391],\n", 84 | " [ 0.11779442, -1.38535078, 0.48185335, ..., 0.40635311,\n", 85 | " -0.21798923, -0.24971305]]),\n", 86 | " (1,\n", 87 | " 'Sitting',\n", 88 | " 'Sitting 2.h5'): array([[-0.09044989, -0.43156891, 0.52043872, ..., -0.88416183,\n", 89 | " 0.48567704, -1.07513702],\n", 90 | " [-0.09195869, -0.41712087, 0.52212797, ..., -0.84682861,\n", 91 | " 0.47896406, -1.08274477],\n", 92 | " [-0.09281077, -0.41056129, 0.52083288, ..., -0.80379937,\n", 93 | " 0.47226244, -1.09090866],\n", 94 | " ...,\n", 95 | " [ 0.02528841, 1.13492155, 0.81955866, ..., 1.50453304,\n", 96 | " 0.13471203, -0.21965517],\n", 97 | " [ 0.02206539, 1.12699157, 0.80770103, ..., 1.50372458,\n", 98 | " 0.13703218, -0.21838012],\n", 99 | " [ 0.01833381, 1.11880205, 0.79180328, ..., 1.50101561,\n", 100 | " 0.1377839 , -0.21570782]]),\n", 101 | " (5,\n", 102 | " 'Sitting',\n", 103 | " 'Sitting 1.h5'): array([[ 1.0356268 , -0.01381664, 0.45041446, ..., -2.9544334 ,\n", 104 | " 1.26155306, 1.0221923 ],\n", 105 | " [ 1.03582379, -0.01643948, 0.45177055, ..., -2.9548875 ,\n", 106 | " 1.25604395, 1.02084882],\n", 107 | " [ 1.03592876, -0.01789292, 0.45246033, ..., -2.95525825,\n", 108 | " 1.249197 , 1.01862763],\n", 109 | " ...,\n", 110 | " [ 1.14963438, -0.88292184, 0.42133113, ..., 1.39083845,\n", 111 | " 0.19922533, -0.05327336],\n", 112 | " [ 1.16121359, -0.92421722, 0.43741659, ..., 1.39121468,\n", 113 | " 0.19811686, -0.04923675],\n", 114 | " [ 1.16999681, -0.9530153 , 0.45342227, ..., 1.39162115,\n", 115 | " 0.19563401, -0.04557973]]),\n", 116 | " (5,\n", 117 | " 'Sitting',\n", 118 | " 'Sitting.h5'): array([[ 1.04258113, -0.02333128, 0.52139127, ..., -2.92261564,\n", 119 | " 1.39050681, 1.24358547],\n", 120 | " [ 1.0430305 , -0.02999884, 0.52380784, ..., -2.92486707,\n", 121 | " 1.38667421, 1.24001264],\n", 122 | " [ 1.04335967, -0.03387579, 0.52584903, ..., -2.92659568,\n", 123 | " 1.3826458 , 1.23549873],\n", 124 | " ...,\n", 125 | " [ 1.08705741, -0.53713672, 0.4864988 , ..., 0.6232366 ,\n", 126 | " -0.87143108, -1.2785658 ],\n", 127 | " [ 1.08691745, -0.53589818, 0.48704311, ..., 0.62196993,\n", 128 | " -0.87222297, -1.27784042],\n", 129 | " [ 1.08682284, -0.53465902, 0.48807543, ..., 0.62141007,\n", 130 | " -0.87307161, -1.2767746 ]]),\n", 131 | " (6,\n", 132 | " 'Sitting',\n", 133 | " 'Sitting 1.h5'): array([[-0.91870767, -0.22599749, 0.68775932, ..., -0.34472357,\n", 134 | " 0.53621975, -1.23257999],\n", 135 | " [-0.91850874, -0.22921333, 0.68759039, ..., -0.34450682,\n", 136 | " 0.53618838, -1.23278499],\n", 137 | " [-0.91854568, -0.23104217, 0.68597622, ..., -0.34448787,\n", 138 | " 0.53646512, -1.23312937],\n", 139 | " ...,\n", 140 | " [-0.91288826, 0.61249201, 0.59062253, ..., -0.07574155,\n", 141 | " -0.98513943, -0.96907092],\n", 142 | " [-0.91233295, 0.60532945, 0.60487795, ..., -0.06879377,\n", 143 | " -0.99149762, -0.96598045],\n", 144 | " [-0.91172321, 0.60319829, 0.61392015, ..., -0.06173825,\n", 145 | " -0.99672907, -0.96304261]]),\n", 146 | " (6,\n", 147 | " 'Sitting',\n", 148 | " 'Sitting 2.h5'): array([[-0.9265319 , 0.37129715, 0.6471703 , ..., -0.71413018,\n", 149 | " 0.74502098, -1.19887775],\n", 150 | " [-0.9267075 , 0.36974072, 0.64620367, ..., -0.70770596,\n", 151 | " 0.75200948, -1.19900081],\n", 152 | " [-0.92666344, 0.37142838, 0.64570628, ..., -0.70341149,\n", 153 | " 0.75726693, -1.19965522],\n", 154 | " ...,\n", 155 | " [-0.91827094, -0.03948691, 0.77826109, ..., -1.19864285,\n", 156 | " -0.15933545, -1.17986331],\n", 157 | " [-0.91907572, -0.06540633, 0.76311881, ..., -1.19737523,\n", 158 | " -0.16780372, -1.19706796],\n", 159 | " [-0.92088485, -0.08632094, 0.73874663, ..., -1.19645068,\n", 160 | " -0.17732306, -1.21275654]]),\n", 161 | " (7,\n", 162 | " 'Sitting',\n", 163 | " 'Sitting 1.h5'): array([[-0.36427808, -0.30258471, -0.96964743, ..., -0.43098184,\n", 164 | " 0.7461681 , -1.21048973],\n", 165 | " [-0.36289142, -0.31650785, -0.97193261, ..., -0.43562777,\n", 166 | " 0.75048045, -1.21357822],\n", 167 | " [-0.36281626, -0.29865128, -0.99420261, ..., -0.44475085,\n", 168 | " 0.75449575, -1.21601511],\n", 169 | " ...,\n", 170 | " [-0.38102391, 0.40330276, -0.83698938, ..., -0.56411821,\n", 171 | " 1.17324032, -1.17996102],\n", 172 | " [-0.3797123 , 0.41843184, -0.84270938, ..., -0.56708902,\n", 173 | " 1.15998895, -1.17857165],\n", 174 | " [-0.37950005, 0.42003976, -0.84451126, ..., -0.5710685 ,\n", 175 | " 1.14644417, -1.17622064]]),\n", 176 | " (7,\n", 177 | " 'Sitting',\n", 178 | " 'Sitting.h5'): array([[-0.38411112, 0.21597161, -0.91792341, ..., -0.40433953,\n", 179 | " 0.84792873, -1.18554835],\n", 180 | " [-0.38480574, 0.18292866, -0.91734625, ..., -0.40757732,\n", 181 | " 0.84353057, -1.18471005],\n", 182 | " [-0.384531 , 0.1764895 , -0.92304748, ..., -0.41129823,\n", 183 | " 0.8402727 , -1.18470217],\n", 184 | " ...,\n", 185 | " [-0.34823696, 0.70524358, -0.90302513, ..., -0.57736905,\n", 186 | " 1.15425035, -1.21823433],\n", 187 | " [-0.35087873, 0.71213414, -0.84614889, ..., -0.55369931,\n", 188 | " 1.1404078 , -1.225623 ],\n", 189 | " [-0.35097851, 0.70355344, -0.8628162 , ..., -0.53660017,\n", 190 | " 1.12084788, -1.22890438]]),\n", 191 | " (8,\n", 192 | " 'Sitting',\n", 193 | " 'Sitting 1.h5'): array([[-1.2754853 , -0.30469179, 0.33912547, ..., -3.23083478,\n", 194 | " 1.14605505, 1.11381868],\n", 195 | " [-1.2753745 , -0.30595254, 0.33928032, ..., -3.23088034,\n", 196 | " 1.14608165, 1.11417574],\n", 197 | " [-1.2762674 , -0.29307837, 0.34134027, ..., -3.23161522,\n", 198 | " 1.14410688, 1.11482396],\n", 199 | " ...,\n", 200 | " [-1.13984398, 0.09044577, 1.57267965, ..., -0.16157742,\n", 201 | " -0.09936226, -0.44665594],\n", 202 | " [-1.13858174, 0.12316232, 1.57940851, ..., -0.15642087,\n", 203 | " -0.09108705, -0.43891894],\n", 204 | " [-1.13616999, 0.16486861, 1.59059043, ..., -0.15170538,\n", 205 | " -0.08280577, -0.4325088 ]]),\n", 206 | " (8,\n", 207 | " 'Sitting',\n", 208 | " 'Sitting.h5'): array([[-1.24196197, -0.64007629, 0.26175764, ..., -3.24031037,\n", 209 | " 1.06065778, 1.32432498],\n", 210 | " [-1.24151876, -0.64336356, 0.26102563, ..., -3.24094612,\n", 211 | " 1.06131598, 1.32355229],\n", 212 | " [-1.24103796, -0.64678787, 0.26057986, ..., -3.2415916 ,\n", 213 | " 1.06203496, 1.32280748],\n", 214 | " ...,\n", 215 | " [-1.22573877, 0.02738136, 1.02375191, ..., -0.2025314 ,\n", 216 | " -0.02543551, -0.46872368],\n", 217 | " [-1.22519966, 0.02554421, 1.02767943, ..., -0.19994684,\n", 218 | " -0.02696136, -0.47858669],\n", 219 | " [-1.22545884, 0.0208932 , 1.02512209, ..., -0.19437323,\n", 220 | " -0.02777976, -0.48594636]])}" 221 | ] 222 | }, 223 | "execution_count": 5, 224 | "metadata": {}, 225 | "output_type": "execute_result" 226 | } 227 | ], 228 | "source": [ 229 | "train_set" 230 | ] 231 | }, 232 | { 233 | "cell_type": "markdown", 234 | "metadata": {}, 235 | "source": [ 236 | "## Extract a seqence from the training sequences" 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": 6, 242 | "metadata": {}, 243 | "outputs": [ 244 | { 245 | "data": { 246 | "text/plain": [ 247 | "(3304, 48)" 248 | ] 249 | }, 250 | "execution_count": 6, 251 | "metadata": {}, 252 | "output_type": "execute_result" 253 | } 254 | ], 255 | "source": [ 256 | "seq_idx = 0\n", 257 | "pose_seq = list(train_set.values())[seq_idx]\n", 258 | "\n", 259 | "pose_seq.shape" 260 | ] 261 | }, 262 | { 263 | "cell_type": "markdown", 264 | "metadata": {}, 265 | "source": [ 266 | "## Un-normalize poses" 267 | ] 268 | }, 269 | { 270 | "cell_type": "code", 271 | "execution_count": 7, 272 | "metadata": {}, 273 | "outputs": [ 274 | { 275 | "data": { 276 | "text/plain": [ 277 | "(3304, 96)" 278 | ] 279 | }, 280 | "execution_count": 7, 281 | "metadata": {}, 282 | "output_type": "execute_result" 283 | } 284 | ], 285 | "source": [ 286 | "pose_seq = data_utils.unnormalize_data(pose_seq, data_mean, data_std, dim_to_ignore)\n", 287 | "\n", 288 | "pose_seq.shape" 289 | ] 290 | }, 291 | { 292 | "cell_type": "markdown", 293 | "metadata": {}, 294 | "source": [ 295 | "## Plot a 3d pose in the sequence!" 296 | ] 297 | }, 298 | { 299 | "cell_type": "code", 300 | "execution_count": 8, 301 | "metadata": {}, 302 | "outputs": [ 303 | { 304 | "data": { 305 | "image/png": "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\n", 306 | "text/plain": [ 307 | "
" 308 | ] 309 | }, 310 | "metadata": {}, 311 | "output_type": "display_data" 312 | } 313 | ], 314 | "source": [ 315 | "frame_idx = 10\n", 316 | "\n", 317 | "fig = plt.figure(figsize=(6, 6))\n", 318 | "ax = fig.add_subplot(111, projection='3d')\n", 319 | "vis_utils.show_3d_pose(pose_seq[frame_idx], ax)" 320 | ] 321 | }, 322 | { 323 | "cell_type": "markdown", 324 | "metadata": {}, 325 | "source": [ 326 | "## Plot 3d pose sequence!" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "execution_count": 9, 332 | "metadata": {}, 333 | "outputs": [ 334 | { 335 | "data": { 336 | "image/png": "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Ghrg8XiwatUq/PnPf875c11xxRW47bbbsGHDBgBAT08PHnvssYw+dsmSJVAUBb/4xS8QDAZx7733AgBOPPHEnNtDVCxm6Ufvvvsu3nzzTYRCIfj9ftxxxx1oa2vDkUceCQC4+OKL8eCDD+KTTz5Bd3c3fvzjH+Nf/uVfcm4rUaGYpU9NmzYNxx13HG699VYEg0F8+umnePTRR3H66acDYJ8i6zBLnwKADz/8EJqmob29HZdffjnOPPNMzJo1CwD7VD4xTBXJfffdhxtuuAHV1dW4+eabcc455+T8uc4++2xce+21OPfcc1FTU4NDDjkEzz//fOz9y5Ytw09+8pOEH+tyufDkk0/ij3/8I+rq6rBixQo8+eSTcLlcObeHqFjM0o+CwSCuuuoqjBgxAuPHj8dzzz2HZ599Fo2NjQCAU089Fddccw2WLl2KiRMnYtKkSfjRj36Uc1uJCsUsfQoAHnnkEbS0tGDEiBE47bTTcMstt+ALX/gCAPYpsg4z9Slji+DMmTNRX1+P3/72t7H3sU/lj5Rm6TG3dUkie5PSvyQl9iuiwdiniPKLfYoo/xL2K65MERERERER5YBhioiIiIiIKAcMU0RERERERDlgmCIiIiIiIsoBwxQREREREVEOGKaIiIiIiIhywDBFRERERESUA4YpIiIiIiKiHDBMERERERER5YBhioiIiIiIKAcMU0RERERERDlgmCIiIiIiIsoBwxQREREREVEOGKaIiIiIiIhywDBFRERERESUA4YpIiIiIiKiHDBMERERERER5YBhioiIiIiIKAcMU0RERERERDlgmCIiIiIiIsoBwxQREREREVEOGKaIiIiIiIhywDBFRERERESUA4YpIiIiIiKiHDBMERERERER5YBhioiIiIiIKAcMU0RERERERDlgmCIiIiIiIsoBwxQREREREVEOGKaIiIiIiIhywDBFRERERESUA4YpIiIiIiKiHDBMERERERER5YBhioiIiIiIKAcMU0RERERERDlgmCIiIiIiIsoBwxQREREREVEOGKaIiIiIiIhywDBlQUKIUjeBiIiIiKjsMUxZjAgE0HH5uei576cQmlrq5hBZnh7wc4KCiIiIcsIwZTHBD9+FtmcX1M3NkBRHqZtDZHk9P7sV+757OcJbNpa6KURERGQxHI1bTOCNfwIAPMeeWOKWEFmf1t6G4HtvALIMub6h1M0hIiIii+HKlIXoAT8C778NAPAcs6S0jSGyAd8Lfwd0HZ6jl0CpH1Hq5hARESUlQsFSN4ESYJiykOD77wChIJwz50AZPbbUzSGyNBEOwf/i3wEAFaedXeLWEBERJafu2YW9F38ZfX/8Dc/5mgzDlIXEtvgdxy1+RAcq8OYr0Hu64Zg6A86D55a6OUSWJsLhUjeByNYGnngEYqAf2r52SJJU6uZQHIYpi9B9PgQ/fAcAt/gR5YPv2ScAABWnfYUPJqIDoO7eiY4rLkBg1VulbgqRLWld++Bf+RwAoOqr55e4NTQUw5RFBN57EwiF4Dx4LpSRo0vdHCJLC3/+KcLNn0Cqqob3+C+WujlElqX396Hr5muh7d0N/z+e4fYjogLw/f0xIByC+8hj4Zg4pdTNoSEYpixAhEPo+809AADXIYeWuDVE1tf38IMAAO9Jp0HyeErcGiJrEpqK7jtvhNbaAsekqaj97vVc5SXKM32gH77nngQAVC6/sMStoUQYpqzA4YTkjgz4gqs/gND1EjeIyLqCaz9E6KP3AACeo44rcWuIrKvvd79EaPX7kGvrUPfD2yFXVJa6SUS243v+KQjfAFxzF8A1a06pm0MJMExZgCRJGHnvHyDV1kHd9Bn8LzxV6iYRWZZj4hQoYxsBAAN/fZjbkohy4Hv2b/A98wTgcKLuB7fCMWZcqZtEZDsiFITvqb8AACqXX1Di1lAyDFMWIVdVo/bK7wEA+h56AFrH3hK3iMialPoGNNz+K0iVVQi+/zYCb7xc6iYRWUpw9fvo/c3PAQC1/+8auGbPK3GLiOyp74+/gd7dCcfUGXAtOKLUzaEkGKYsxHPMErgWH48tjgb86u6/INDRXuomEVmSMmIkqr/xbwCA3l/fA72nu8QtIrIG/2svoeum/wR0DZVfuxDeE08tdZOIbEnr64Pv6ccBAFJ1DcRAf4lbRMlIaba4cP+LCQghsLkzhJe29GPl593Y3h/5a7mj9VEsvfm/eeC3+A70B85+ZQJCCHRc/x9Yv6MH6yYdjqu+fwGUmtpSN6tcsU9ZxN5//Tr0Pbsg19Vj1B+ehCRzTtak2KcsTu/vQ9ePr0N4w8cABNTaEdh02DIceulFqK+pKHXzylXCfsUwZVJCCGzuCmHl5n68vKUf27r3X4hYE+7H4l0f4MytL2HmsYej5srv8oFWXHxIWVggrOO9nT68vm0Ar2/pRXc48td5/55HsOiH/82+VBrsUxah7tmNjivPB1QV9Tf/DO4Fh5e6SZQY+5TF6UJg474Q3l3finc+2oJ1nkaEFDf+c9OjOOdOTqSXCMOUFWzpDOIHK/egP6SjbUCLvb3WI2Pp5Cp8cVoVJt50KaS2nYDDCahheJachNrv/ACS4ihhy8sKH1IW0h/UENQE3mgZwOstA1jV6kdQ2/9XMNrfgaN2f4Qztq3EpAVzUPcf10Nyu0vY4rLEPmUh/X99GP1/eACOyVMx4p4VkBSl1E2i4dinLKYnoGEgrGNVqw+rdvrx/k4fugODqzdP7t2B5ZuexbIjJqP60qsYqIov4Q+co2+TeWxDDzZ3RVahaj0ylkyuwknTqrBonBcOJfJ3uDfogw6g9j9vQO89P0Hg1ZcgAgHUXXMTJKerhK0nMpdOn4qzHmlBQB08Lpgz2o3jJ1Xi+MmVqLnuh9B3tULyViD41qvo7OxA/X/fBrm2rkStJjK3yjOXw/f8k1C3bYF/5XOoOOWMUjeJyNJWbu7DD1a2DUuwoysdOLLJiyPGV2Dy7Veibm8LoCjwPfkeEA6j+vKruZvCBPg3YDLr9wYBABfMrcMLF07B9SeMxpFNFbEgBQC6zwcAcC86EvW33B2pSvbuG+i65b8gAoGStJvIjHb0hmNB6qgmL647bhSeu3AyHjp7Ai5d2IDpDW5I0dX52mtugjxyNMKfrse+a66Euqu1lE0nMi3J5Ub1Jd8CAPT/6XexZxIR5eat7T4IAIoELJlciWuOHYW/fn0inrlgEm5YMgYnj9ZQt7cFkteLuut+DDic8D37BHp/9T+8e9QEGKZMZMPeAD7rCKLGLeOKIxoGBSiD0FQgFAQkCZLbA9esOWi47ZeQa+sQWv0+Om/8HnRWfCECEFnpBYAL5tXhl6eNx1dm12JU5ZAFeS3yIHI0TcKIu34Nx9QZ0Ha1Yt/3r0Dos/XFbjKRJXiO+wKcM+dA7+7EphUrIDQt/QcR0TBdfg0rt0TGbQ9+uQn/c8o4fG1OLSbVuWLb+MLbtwKI3JPoOfJY1P/wdsDlgv8fz6Dn57ex/5UYw5SJ/DU68DtjZg08jsR/NcLvBwBIHm+skzmnTEfDbfdCHjEK4U8+Ruf134He21OcRhOZVIdPxctb+iFLwLmHJK/SJ0QkTEmyDGXESDTcdi9cC4+E6O1B539fjcDbrxWryUSW0BPQ8M+tA7jvuKtx2dI7cIHzVGx9/IlSN4vIkh7+uAsBVeDYiRWYM9qT8DVqyxYAgGPSVACAe+ERqL/pLkgeLwL/fAE9P7sFQlWL1mYajGHKJLoDGl7aHJmZWD47xcAvEA1T3sFlMR0TJqHh9nuhjG2EuqkZey88A+publOi8vW3T3qh6sDxkyoxttqZ/IXGFono5IRcUYH6G26H95QzgFAI3bddj+6f3wbdz61MVH7CmkBYE/hwlw/3rdqHS57YgZP/uBX/9dIe/H2PE22Vo1EV6sem51+Cb+WzpW4ukaV0B7TYDorLFjUkfZ26bXCYAgD33AWo/9FdkLwVCLz+MrrvvBEiHE72KaiAWIDCJJ5u7kVQE1g8oQJNtckHfiI6oJO83mHvc4xtRMPtv0L7N5cDmgZtzy44xjUVrM1EZhXWBB7/NPKA+nqKVSkAQHRlCnGHeCXFgZqrvg9lzDj0//E3CKx8DgiFUPf9GwvVZCLTEULgy49sQ/uANuhgvEMGFozz4sjxXhz05L2YvHolFAj0/vxTaK07UHXx5TwUT5SBRz7uhi8cGfslW5UCAHW7EaamDHq7a/Y81P/4bnTd8D0E33kd7Zd9DSPuegDKqLEFbTcNxt92JqALgcc/iQz8vjYn9cBPj4WpxBe2KSNGwjF5WuQ1nuGBi6gcvLK1H/t8GqbWu7CoMU0/0KPDxCGDP0mSUPW1i+A54aTIy3w8i0jlJawDHb5IkJpY68T5c2txz7Jx+Oe/TMUDZ4zHNxY2YLYnCAUC3lPPBGQFA48/jO7bb2AxJKI0eoMa/m99NwDgsoX1SV8nhIDaEj0zNWnasPe7DpqNhh/fAygK9M59GHjqL4VpMCXFMGUC7+zwYWevinFVDhw9IfWt1saZKTlJmAIAZeRoAIDe1Zm/RhJZyP+tj0xOnHNIbdp7OIQePbgrJf51WHXhZQCA8Ia1EMFg/hpJZHLv7/RBF8CUOiceP3cS/uPoUThmYiW8zrhV3OiknXPmnMiWo8oqBN95Dfuu+3/QOjtK1XQi03t0XTcGwgJHNnkxb2zyST+9fS+EbwBybR2UusShyzl9JtyLTwAAyCNGF6S9lBzDlAkYhSe+OqcWipxm4GesTKVYdZLrRwBgmKLy9Fl7AB+3BVDlkrFsRnX6D4iWRk+2LckxthGOaQdB+P0Irl6Vz6YSmdqrWwcAAF+cVpX0NcbEngj44Z5/GEb8z/1QxoyDuukz7PvetxDeuqkobSWykr6ghkfWRc9KLUx+VgqI3+I3NeXr3HPnR16/bXMeWkjZYJgqsZ29Yby13QenDJw5sybt60WabX4AINdHOqbWtS8/jSSykL/EqmJWo8KZwa84ffiZqaE8xywBAFb2o7Kh6QKvt0TC1JIpycOU8Swynk2OCZMx4qe/hvPgudA79qLzmn9DYNVbkWs9iAhAZPdEf0jHYY1ezB+Xeit6OEHxiUSMIx5G5T8qHoapEnvikx4IACdNq0a9V0n7+mTV/OIp0TClM0xRmekOaHhxUz8kpD9/GJNJmDo6sn0iuOotVkuisrCuLYBOv4bGagdmNLiSvs4ohiTiql3KtfVouPUeeJacBBHwo/uW/0LXLdcVvM1EVtAf0vHIuuhZqUXJz0oZ9pdFn5LydUbYUrdv4+RFkTFMlVBQ1fFUcy8AYHmGA79U1fwMcp0RprjNj8rLU5/1IqQJHD2xAhNqkw8ABxlSGj0Rx/iJcEyaCjHQj9DHH+WhpUTm9sq2/atSqc4d7l+Z8g9+u9OF2u/+EO6jjgMAaG27C9RSImt5bEM3eoM6Foz1YGGaVSkgPkwNLz4RT66sgjx6LBAOQdu1My9tpcwwTJXQyi396AnomDXSjUNGuzP6mNiBXkfyqvZyQ+TMlMYwRWVE1UXs/GHGq1KIv7Q39cqwO7o6FXj71ZzaR2QVQgi8ujVSvXLp5MqUrzXO74oE97BJkoSqcy6O/IGl0ongC+t4+OPIqtQ3FzWkL5CkqVB3tAAAHBNTr0wBgDO61S/Mc1NFxd9uJWRc1LZ8TvqKY4bQ+rUAAG1b8j2xilGAopthisrHmy0D2NOvYkKNE4vTVMUcJLptL1bVLwljq1/g3Te4hYJsbWNnCLv6VDR4Fcwdk/zuG2D/ypQe8Cd8vzJhEiBJ0HZu5xZZKnt/3dCDnoCOeWM8OGJ8+lWpwBv/BNQwpIoKyBXpn2uxrX4MU0XFMFUin7QHsGFvENUuGaekqJSUjJSkPCYAyNH36d2dEMYWJiKb+92HkcmD5XNqIWc4OQEgVs0v3cy5Y9JUKI1NEL09sUkNIjsyVqWOn1SZtsKsPKQAxbD3e7xQxjYCmgZ1V2t+G0pkIf6wjj+t3X9WKpNJdM3oM2l2ThgcU1iEohQYpkrkr3EVxzyZVByLcoxrAgC4Fxye9DWSyw2psgpQVYj+vgNrKJEFvLq1H837QpAAnH5Q9pMTAACHM+W7JUmKVfULsqof2ZhREn3JlNRb/ID4AhSJV6aA/duTjBLPROVGCIFfvteBroCG2aNcOKops90T7uNOjPxHiqMd8ZzGytRWrkwVE8NUCTR3BPBMcyTkfDWLsx0AoEdn/+SK1A85464plkencvD3aCGXKfVO1Hgye+gAkQecIdk9U/E8Ry8BAATefZ2rvmRLrb1hbOwModIl4/Dx6Qd8Q0ujJxILUy1b89NIIosJqDoe2xB5Tl04L7NVKQBwjB0PSBJEb09G28uV8RMAhxPa3t3QfQMH1GbKHMNUCfxlfaQcep1HxsRMK45FiWjnSFUaHQCUBl7cS+WhL6jh/Z2RWfEblozJ7oONMCVJGT3cHNMOgjJ6HPTOfQh/tj7bphKZnrHF79iJFXAp6fuECIcAAFp7W9LXxM5xcOsRlSlNSKhxR4bcU+ozH/dJTmfk7lBdh74v/eS4pDjgmDgZAPtbMTFMlYCxrW9piosQkxH+aJhKtzJVx7umqDw83dyHgCpw+Hgv5oxOfVh+GGGURc/sV6EkSXAffTwAXuBL9vSKscVvcobPp+iEhBjoTzoTbtyPo27nyhSVpyqXjJkjI1Wb233ZFTBSRkUmCVNNWMSLXd7LIhRFwzBVAhv2BgAAX5yaQ5jypb+0F0BkJgNcmSJ704WIVcX8+iHZbZmNfoLI/6c5ZB8vVtXv7dcGbRMksroOn4p1bQG4FAlHT8zsTIdz2kGQxzYCAAKvv5zwNY7xEwBZgbZ7J0QwmLf2ElnJ6MrIFvS9A6krxw6ljIyGqY69Gb3eGQtTXJkqFoapIguqOpo7gpAAzM52Fh2AHl2ZkjMMU7xriuzs7e0+tPaG0VjtwLET0x+WHybLlSkAcM6cA7lhJPT2NqgbP8v+axKZ1N8+iWxBXzjOg4oMCyNJTheqz78UAOB/6Zmkr1HGNwFCQN2xLU+tJbKWWJjqz25lSh41GkAWK1PRbbW8a6p4GKaK7LOOIFQdmNrgQpUrux+/EGL/mak09w3sv2uK2/zIvv5vffSuttm1aUs4J6TvPzOVKUmW4eFWP7Khhz+O9CdjO1KmPEcvgVRZhfDnnyYdwDknRs9Ncasflan9K1O5bfPTMw1TceXRuXuiOBimimx9dIvfITmsSiEcAjQNcLogOVMfYDSq+emdDFNkT9u6Q3i31Qe3Q8KZs2py+hwiujKVSSW/eO5oVT//W69C17LbskFkVmOqIoO9kRWZV8QEAMnthveEkwAA/peeTfganpuicnegYSrTbX5yXQPk2rrIOcb2zD6GDgzDVJGtb4vsF5+X5lb5RHRfpPSsca9HKjwzRXZn3NV26vRq1Hoyu9BwGJH9yhQAuGbPA1xu6Ht2IvjmP3P72kQmc2L0XqlOf/YTBN6TTgMA+F95MVbhLx4r+lG5MyYrsg5TI7Pb5idJUtxWv01ZfS3KDcNUka0zVqZyCFPGFr90d0wBgFxbBwBQd26Htq8j669FZGYDIR3PRO+WyqnwhMG4KyrLlSlJUaCMjswW+l9bmfvXJzKRCdGrOnb0hLP+WOf0mXBMnQHR14vAu28Me79x11SYd01Rmcp1ZUrOspofsL+iX3hTc1Zfi3LDMFVEewdUtPWrqHTJmFznzPrjjUsR05VFB+IuR9R1SFXVWX8tIjN79vNeDIQFFozzYMaI5Oc7AqoOXdeT7xvPcWUKACqWfTnyHyFWJyN7mFAbeS7t6M0+TAGA9+TTAQD+fwzf6qeMawScLujtbbxMlMpSnUeGUwZ6gzoC4cGXvq/a6UNfMPGKsFxbBzhdEP190FNcjh1P749MNvqefQKCW9ELjmGqiNa3Geel3JCHDN529IRw4u+34OxHtuHFTX3oSDBzkemFvUBkqwUAVC6/ELI7u8PERGamC4G/xMqh16V87YWP78BRv92C/3h+F17a3IfuwJCHip59NT+DcUYk9Mk6lnsmW5hQEwlTrT2hpBMQf/64C0tWbMZVz+zEe62+QYNC7wknAU4XQmveh9q2e9DHSYoDjgmTAADq9m2F+QaITEySJIwyVqeG3DX13ed348SHtuLKp1vxdHMvOv3qoI8ztvrpGZyb8r++EoFX/gEgskIlKTlug6eMZXfKlA7IumiYmpug+MSO3jD6Qjr6QjqufzmylDupzolF47xY1OjFwkYvqqIzEunKout+H4LRKmPGPnYiu1jV6kdLdxijKx04YXLqVdqegAYB4K0dfry1wx+9ksCNo5oqsHhCBQ52GQUosl+Zkmvr4Jg6A+qWjQh9tg7uQw/L4bshMo9aj4xql4y+kI5Ov4YRCQpRvNvqx0BYYNVOP1bt9MMhR55pixq9OGy8F1MWn4DQ6y/Bv/I5VF/wzUEf65g4BeqWjVBbtsA1a06xvi0i0xhT6cCuPhV7+1VMjG6rXbPbj6AWmbz4YFcAH+wKQELkOMhxEytw3KRKNIwaDW13K7T2NjgmTE76+YMfvIOen/0YEAJVF/0rqs65uAjfFXFlqojWpzgvdXijF15nZEB3WKMXXoeElu4wnvi0F//9chuW/e82PPTMGgBAd2cPtO6upF8n8NarEAE/nAfPhaOxqQDfCVHp/N/6bgDA8tk1cKQJQWdFq/wdPt6Lwxq9UGRgw94gHvyoC5c9tRPnPBrZDhs3y3zGAAAgAElEQVQKBOHftSvrtrgOXRT5+DUfZP2xRGYjSRKaolv9WpNs9TO2qB86xoODR7qh6cDqPQH87qMuXPH0LlynLgQAdP/tL9iz6kOI8P7Ps//cFItQUHkanaAIxQub+gAAZ8ysxvePGYmjmirgkCMT8Pe934nz/roDH7RHdlW0vv5WwgIvABDasBZdt/0Q0DRUnH0uKr92UYG/GzJwZapIwprAp+2RrUCJyqI7FRnT6l1YvzeIf13UgHljPPi0I4gPdvnw0S4/1uwJYOTuSFUW75ZP0H7RmXBMmAzXvIVwzZ0P1yHzIdfWAwAC/3wh8rovLCvSd0dUHK29Yby13QeXIuHLB6cvPNEU3bY0utKBm5aOgS+s48NdfrzX6sM7O3yo2rIHAOAI+tHzra+jf/wEuBccDteCI+CauyDtKrB7/mHw/e1RBNd8iOpLDvz7Iyq1ibVOfNoexI6eMA4dO7xybG8wspp7xqwanDWrBr1BDat3+/HBTj8+3OXHanEQVEmBM+gDbvkO9ro9cM6eC9fchRBqJFgF3/wnxMXfguTJ4YoQIgszilC0RcOUP6zjhU39AIDz59VheoMb5xxSh4GQjlU7fXijZSDyzPNHAlfly3/D3rdfgGv+EXAfcTQ8hy+GXFuP8ObP0XXztUAoCO9Jp6H6G/8GKYezwJQbhqki2dgZRFATmFTnTFrGeVJdJExt6w5hYaMXc8d4MHeMB99YEAljm8acivaXVNSEeuHeuxPqjm1Qd2yD79knAERKz8ojRyO0bjXgdMFz7NJifotEBfd0cy8EgJOmVaHem34f+PhomNoZnWWvcMo4blIljpsU2R64a4uMfT1HwdW5BzW97dB27oBv5w74nnkCcDjgmj0Pzllz4ZwxE87Z86DUDA5wztnzAIcT6uZm6H29kKtzu++KyCyMCYhkFf06omc9RlZE+l+NW8EJk6twwuQqAECXT8WunmVQt23GOL0P+q5WhFa/j9Dq92OfQ+/uQtdPb4b3+C/CfcwSyFlW0ySyqtiZqf7IStPKLf0YCOmYO9qN6Q37z7dXumQsnVKFpVOqoAuBTZVno/2fL6De3wVH+y4E33kNwXdeQ68kwTF5OrTdOyACAbgXH4+aq77PIFVkDFNFsr/4RPKZuEnR7RMt3cOXcJ2KhINPPwU4/RQAgAiHEP78M4TWfYTQutUIfbY+cn9HdPuEXN8AubIq398GUUldtrAB0+pdmNqQ+tJqQ2N1pE/t6ks8MGycOgGNd/wPAECoKsKff4LgR6sQWr0K4Y2fIfTxRwh9/BEAQJkwCaPu+9Ogj5c9XrgOPiTSB9ethufoE3L91ohMIV1Fvw5fZBCY7GLf+goH6q+9NvZnrWsfQutWw/f04wh/tj7yRiEQevcNhN59A6MffxlwZdafiaxuTDRMtUcnJZ76LFJ176wUOy1kScJBX/0y8NVIBVlt7x4E3n8bwVVvIbT2I6hbN8ZeG1z1FtSWrXBOnV6ob4ESYJgqkljxiRT3S02uizxQWjK440NyuuCaMw+uOfOAc/8FIhRE6LMN6Lrhe4CmwjWfh+HJfpyKhJOnZ17qf0yVA4oE7B3QEFR1uB3JZ8Cl6EqUa/Y84MLLoPf1IrjmAww8/jDUzZ9DGT0u4ce5Dl2E0LrVCK75gGGKLG9/Rb/UK1MjKjKrEKbUj4Bj/MTYfTc1/+8ahNZ+hMDrK6E0ToDMIEVlJHbXVL+KLV0hrN0TQIVTwknTMp/8VkaPReVpX4HnmKXovObfoO1uBVzuyDUdkgylaWKhmk9JcG29SGKX9aZcmYo8VLYlWJlKR3K5IckyoEUedO6FR+bQSiJ7ccgSxlZHHl67+7K8KLG6Bt7jToR74REAkLT6mCtaxS+0lkUoyPqMi3u394aHlUcPawI9AR2yBNQn2a4+lO73ofvOGwE1jIovnY2Kk8+Atq8dAFB14TfTfDSRvRgFKNoG1Niq1CnTq1HhzG44rg/0o+vG70Hb3QplbGMkSCkK6n94GycoSoBhqgg6/Sp29qrwOiRMS7E9qanGCUUCdvWqCKp60tcl448WngAAyZn9pcBEdmRs9duZZKtfOsYdUpJn+GF8AHDOmAmpohLarlZoe/fk1kgik6jzyKhyyRgI6egODH4O7YuuSjV4FSgZXifQ9+t7oO1qhWPyVFRfehX03h6EP10HKAon/ajsNHgVKFLkvvhnmiP3JRpVZzMlAgF03fJfULdshDK2ESJ6X2Ll1y5inyoRhqki8IcFvji1CsdPrkxZytmlSBhf44RA9jfQ6wE/Am/+M/ZnycEwRQQA46sHF6HIVixMuROvKkuKA665CwAAwbUf5vQ1iMxCkqTYVr/tPYN3SaQ7LzWU/9WX4H/5ecDlRt33b4LkdiP4wTuArkeqZfJcL5UZhyzh9W9Ow/ePHYneoMCMES7MHuVO/4FRIhxG9x0/RHjDWsgjRsF5yHzoe/fAMXkq75QqIYapIhhf48RtJ43Fj78wNu1r9xehyG7gF3z7NQi/H5JRypkrU0QA9lf025XlNj+DCEa26Eru5A+82H1TDFNkA8numhpayS8VdfdO9N53FwCg5vJvx+6YCqx6CwDgPvLYvLWXyEpcioQnP41s8fvyrJqMK+8JTUPPPbci+MG7kKprUX3x5Qi8/DwgK6i9+gfckVRCDFMmM6k2t3NTxhY/qaYu8v8O1hYhAoDG6JmpnFemQsbKVPIw5Z6//9zU0HMmRFYTq+jXMzRMRVamRqRZmRLhMLrvvAnC74PnmKXwnnxG9O0hhD56DwDgOeKYfDebyBJae8NYtdMPtyLh1BmZFVQSQqD3gbsReP1lSF4v6n9wK/of/QMgBCqXXwDn9JkFbjWlwjBVBLquIxQKQdO0tAOtyfXRMNWVeZjS9u6JlG92uiBVRFamuM2P7C4cDmfUp2J3TR3omakk2/wAQGmaBLlhJPTursgVBUQWpKoqVFVFU3QCYniYymxlqv9Pv4W66TPIo8ei5t/333kT+ng1hN8Px5TpUEan36lBZHXG+E/X9diz6ulo4YkTp1ahxp1ZIZf+//0N/C88BThdqPvhHQi8+zq03a1wTJyCqnN5Y3ypMUwVmBACwWAQwWAQfr8fPp8PgUAAqqomHARONrb5ZVAe3eB/5UVACHiOOhaSiB4Y5soU2ZQQAqFQCMFgED6fDwMDA/D7/QiHw9D14YVb4rf55bJqZGzzQ4owJUlS7DqC0BpW9SPrUVUVgUAAfr8fI12R0LS9Z/AkYCZnpoIfvYeBJx4BZAV1/3kD5Kr9M++B994EALi5KkVlQNd1BAIBhEIhDAwMRJ5X/gCebt6/xS8TQteh7W2L9Kn/uhmSwwHf3x+LbO/7zg8gOVm9r9QYpgrI6EhCCCiKErvl3XhoGYNAY9YC2L/Nr6U7lNHATwgB/8uRLX7eL3wJIhx5CHKbH9mREaRUVYUsy1AUBZIkQdM0BAIB+Hw++Hy+QSvBtW4ZlU4JAyEdPcHsq2TCWJlKU27WzXNTZFHhcBihUCjWpybXuXDu7EqcPcMTmwQMBoNoH4hM8o2qTDybrnXtQ8/dtwIAqs6/FK6D58beJ4RAMHpeysPzUmRzmqYhGH12GP0KAN7c1o92n4YJ1Qpm1Ymkk4DxJFlG7XevR8Mdv4L70MPQ8/PbItv7vnoenDNmFfx7ofQ44i4QTdMQCg0PRJIkxbY8CCGgaVqs08myDK/DgVq3jJ6gjnafFrvgLZnwp+ug7W6F3DAyMjOuRle0uM2PbCZ+u0S8oX3KWA023uZwONBY7cDGzjB29oZRl+H9OIb9Z6aSr0wBcUUo1q+BUFVOaJDpCREZzKnq4OIstR4FVy6qHfY6I0xVKZHnm8PhiE0SCl1Hz923Qu/ugmveQlQuv2DQ51Q3fw59XzvkhpFw8HwH2ZiqqgiFhh/VkCQJz23xAwBOm14Rm3CXJAmyLMPhcMQm3ocWpZBkGa5Zc9C74lfQdu6AY8JkVJ33jaJ8P5Qen/YFkKwjDTV0EAgAoVAIE2oU9LTr2Li3Hw0TqmKz74kI3wCUxiZ4Fh8PSVEgtMg2DA7kyE50XUcwGEy7Wmv0E2MWUAgBVVUxtlLGxk5ga8cAZtRFHlrx/S+V/dX8UocpZcQo1Pz7NXAedDAgc9GfzM1Y5dWiz4xUjL7S6Y9MZNS7gGAwiFAoBEmS4HA4EHr6rwitfh9SdS1qv3s9JGXwpMX+Kn7HZFy9jMhqwuEwwuHExzTafRre3RmEIgGnTqvYPxExZBJQkiQoihILV7Ezh5+th++pvwCyjJrvXMftfSbCEXceJZvly0T8IHBSrRPr28PY2hXCvJH+2NsdDsewQaD7sMUYuegowAhvXJkim4nfLpEto6+Mq3IACGJXXzh23sqYCTRm15NOWBhhypX+LpCKU87IqZ1ExZRslTcVTRfoil7iO6LCAUWRYpMb/k/WIfCn3wIAKq76T4jaegghBvWpYPS8lOcIbvEj+8lkcuKFzT7oAjhhogf13v2TDckmAY2z9YqiQNF19P78NkDXUfnV8+E6aHZhvyHKCsNUnmQzy5fOhJpoJaVeDYqiQAgRe/glHQRGyzaL6IwI7xsgO0g1y5cNozz6ngEdsiwPWgmOn103+pQct7IkohMVqUqjE1lFsi3o6XQHdegCqHXLcCqRwZ8kSRBqGMFf3QloGpzLvgzp0MPg9w+eBJS69kHdshGSxwvXvAV5/56ISslYVUo1OaELgWc3+QAAp8+oSPn5hu5a0nUd/kdWQGvdDrlxApxfvRCapqWcBKTiYpjKg0w6UjYmxsJUtJjEkO1IxgqYMQiMXw6GsSqmZHcuhMhMDmSVN5FxVZH+YFzcm2wm0Ahu8X0q021+RGaX6Rb0RPYZd0x5B29hlRxOeL7xbwg99yQ8F3wTUtzWJWMSMPTmKwAAx6GLoCsOyENWrYisKtMt6B/tCWF3v4axlQoOG5f5xJwkSdA3NyP89OOAJMNz5XcRBhD2+QZNAqY6DkKFxzB1gDLtSNmYVBv5a9nem3ggmaiIhaqqsVlCANAlGRIfWGRB+VzlNRhhand/4s+ZaCYwGAwCmhaZoJBlqAAc7FNkUQe6yrsvel5qhHf4RJ1zwRFwLjhi0Nvi+5T20arI2xYcCV90EKgoCpxO57CVYCKryGaV99mNAwCAZdMrIGfxDBGhEPz3/xQQOlxnLIcjbntfqklArloVF8PUAch1u0Q6Y6sUOGSgbUCDP6zD60z+oIl/YOm6Hhn8AfCHw5BUlbMWZCm5nOXIxNiqyK+6tgENqi7gkJP3hUHByrhjyuWO3RenKErsocVBIJldvlZ59/kTr0yl/fq+AWgb1gKSDNeiIyFHt67HTwKmq2RGZDbZrPJ2BzS8sSMAWQK+NC31Fr+hgo//CXrrdsjjmuA+5+JB70s6CQgM6lMc/xUew1SODmS7RDoOWcL4agdaelTs6NNwUENmDy9Jj866K47YWauhhxgTFbEgMoNCrPIa3IqEkV4ZHf7IlQPjqjL71Rd/Xso4a2UMAhOdtWKfIjPJ5xb0VCtTqahrPwA0FcqsQyDXRMqtp7rOIFklMyKzyHaV9x9b/AjrwFHj3Rid5I62RLRNzQg99RggSfBc+d2URZCyOQ7CScD8Y5jKUr7PciQzsSYapnpUHNSQYTEJo03RsuiJZi2yrWRGVAwHUrEvU+OqHejwR/atZxqmEL1jCtGHWLLrDIwHK1eCySzyvcprrEw1ZLkypX7wLgDAcdhRCd+fSSUzTgKSGeSyBV0IgWeMwhPTM1+VEuG47X2nfQWOmXOyamuq4yCSJMHpdHIlOI8YprJQiLMcyUysdQA7gO29YQDezD4oVhZ9+F9rskHg0Nl1DgKp2PJVsS+dxioF6/YCu/tUYGxmB4BTlUXPtIgFB4FUbIXYgh5bmarIfGZdqCrCqyPnpRyLFmf0MZwEJDPKdZV3fXsILT0qGjwyFjdlXsQo+MQj0FtbII9thPvrl2Tb3EESjf+GXmzP8d+BYZjKUL4r9qVjVPT7fF/mg0wRXZlKd2FvNpXM+MCiQinWKq8hVtEvSRGKhIytvBmURecgkMygUFvQO3M4M6U1bwAG+iE3ToDS2JT11+QkIJnBgWxBN1allk2rSHlWN562ZSNCTz4a2d53xXfzWkmWk4CFwTCVgUKe5Ugq+qU+2JPF1qch2/wyxUOMVGzFXOU1GBWU3moN4F8X1GT0MSLaDyRXdjfNpxsEspIZFUIhV3lzOTOlfph6i182OAlIpXAgq7zr9wbx0pbInWtfynCLn1DDke19ug7Xsi/DcfDcrL9uNjgJmB8MU2kU4yxHIvPHRgZvYQ1QNR0OJYMBVyxM5X5hb7JDjMkeWETZKlTFvnSq3ZF/13uyWpkyqvnlPjOYaBBo7F833s5BIB2IQq/yCiGyXpkSQiD8wTsAMt/ilw1OAlKhHegq73ObfdAEUO2S0FST2XA7+MQj0LdvhTRmHNznfiPnr52LTFeCOQk4HMNUCsU6y5HI2CpHrPrYXp+Oxur0/3Bj2/yU/P21pjvEyFkLykZJVnmjFo2JbNXLcKcFgLiVqQy2+WWKlcwon4qxBb03JBDWgUqnBI8js0GU3toC0bYbUnUtlINmFaxtACuZUf7lY/y3fFYlnt3kR1ATaa/kAABt2+bI9j4A3iu+B8lTuoviuRKcHYapBIp9liOZyXVOdPiD2NajorE6g7+qFAUo8oGVzOhAFPI6gUxMrHXAo0gYCAv0hXRUuzIYVBntzXKbX6ZSVTIDMGibBfev01DFmpzY5zNWpbLY4mdU8Vt4BCQ5u3LqB4qVzChX+dyCPrXehYk1DmzvVdG8L4w5o5I/R7RdrfDd8UNA0+A85Uw4Zhd2e1+2kq0EcxIwglM0QxgdqdRBCgAm10ZC0baezGZH9N07AQCir6dgbTLEdyDjgaSqKvx+P/r7++Hz+WJbuUqxCkHmYswSl5IkSWisjhah6Musf4uQUc2vODOExgWmRp8ytkQODAzA5/MhGAxC0zT2KYptQS/Gv4VcyqLHzksdfnRB2pQpo0/FD/KCwSD8fj8GBgYQCARiZdipvBmrvPk8yzt/TCRArWlLfVwk+MgKiM59gNsNz/mX5u3rF0J8nzJWelVVRSAQiD2rym38xzAVpxAd6UBMioaplu7MBn56fx8AQPh9BWtTMkM7FweBBOyfnCjVdtmhxkdXeHf2ZdbH1TUfAAC07VsL1qZk4oOV8cAKhULw+XwcBJY5VVWLul32nZ2RgWBIy+zr6d2d0DZ9BjidcMxdWMimZYWTgJSMrusIBAJ53y47P7q9fE1b6slE57IvAwAktweSJ8PrcEyCk4Dc5hdTyrMcyUyKrUxlFqbk8RMAAFJldcHalAlWMiOgNBX70hkfXZnamenKlBECRXGLZQzF/etkKMVZ3j39kf7iD2f2fFQ/fA8QAo65C0p67iMdVjIjoDD3shmMlal1e0Mpz005Zs0BvBUQvT3Qu/ZBrh+R97YUQ7leZ8CRLCIdKRAImCpIAZEzUwDQ0pPZ7LMycnTkP0z0DzR+JtDoPJqmxbZYGDOBdp+1KDfG5ISZghQQvzKVWZhyzD8MAKBMnFKwNuUi0UpwMBiEz+eLzQRy1cpeSrnKe9KUyEx5hgtT+7f4FaCKX6FkuhJc7CqkVFiFXuUdUaFgQo0CvyqwsTN535VkBcq0gwAA2qbmgrSl2BKN/+y6Elz2YSocDpek9Hkmat0y6j0y/KrAXl8Gg1Jv9B6DgL+wDTsAyQaBfr8fPp+PW5dswDjLYcZBR7bb/GLbLUz4vRji+5SxchUOh2MTFn6/H+Fw2JR/H5QZYwt6qc7yHtEYWV3a3a9C1VP/bla3bIS6ehUAwLHwyIK3rRBSDQI5CWgfxTrLe+jozLb6KdNnAgC0jZ8VvE2lYOfjIGUbpsx2liOZ2Fa/DM5NGdsphN+8YSoeDzHaT7HPcmSrMcttfpIzskVDhEtbPCMbQw/cGyvvxgw7B4HWUqizHNmodMkYX60grEd2SqSirV8dmXxwuyE3WHOr0lCcBLQXY3KiWOO/TItQKNMjVwhom+wZpuLFrwTHTwIazymrTQKWZZgyU8W+dCZnc27K4QQUBdBUCNXcITERHmK0NjNU7EtndIUChwzs8+vwhzP4JW2URLdQmIrHSmbWVsyKfelMr49sO0+1VQkAHEccG/mP6B1qdsNJQGsrRaGxQ6NFKIxzU8koM6JhavPnELq5tsgXWqpJQCusBJddmDLrWY5k4s9NpSNJEmBsSzLxVr9MsJKZdVhllRcAFFlCY1VkgmJXf/rfAbGVKZOHxEwkq2QWCARst3/dDsy2yjujIfIs2pQmTMljxgEVlUAoBNFb+Gs6So2TgNZRqlXe0ZUKxlcrGAgLbOpK3n/kugZIo8YAAT/01h1FbKG5DA1WRgA28yRgWYUpI0hZZdkQiCuPnuFdU8YZD6ts9ctEOR1itBorrfIasrpryliZskGYGmrohAUHgeZhxlVeI0xtTDEYBKL/rsY2AgD0PTsL3i4z4SSgeZV6ldcokb4203NTZbDVLxNWmQQsmzBl1op96cRv88uk7ZI3GqYsvjKVSrL968Yg0AorJHZgtVVeQzZFKCSXfVamUslkEGi1351WZOZVXmOb36aucNp/C/LY8QAAfc+ugrfLrDKZBLTSxK6VmWGV99DouanVe3hu6kCkmwQs1e/OsghTZq7Yl069R0a1S0J/SKDTn8EvXmNlKhAocMvMIVGw4qCv8MxcsS+drO6aclr7zFQuhs4ECpuefTGbUlfsS2eEV0adW0Z/SGDPQOqJiNjKVFv5hqmhhm5dsuLvTqsRQphmlTf+vikt1bkpI0zZtKJfPiUKVqVi6zBl5lm+TEmShMm1kRnBTIpQxEo5+32FbJbpGBcuulwuOJ3OUjfH1swwy3cgsrpryhXZmlFOYcpghChFUeDxeGx1waLZmKFiXzqSJGV+biq2zY9haijj79jr9fLS+gIy2/hvTKUD46oU9IcFNqeozqxMnQ4oCvQdLbbeYZRPxvjP7XaXbPxn255sxbMcycTKo2dwbip2ZipYHitTwOAg5XK5OOgrILPM8h2IrLb5RX8x232b31BGn5JlGV6vl32qgEp9liMb0xv2b/VLRR7DMJVIfJAyykFT/pWiYl8mjK1+a1Js9ZNcbsgTpwBCh7ZlY7GaZlnxQcplnHEuAVuGKaue5Uhmcl3m5dH3F6Aoj5UpBqniMNss34EYW6lAloC9Pg1hLc0A1uKl0XOl6zoURWGQKjCrrfJOr488izZ2pn4WcWVqOAap4jDzKu+CjItQcKtfJswSpAAbhikrVuxLxyhC0ZLBxb2IXtxr9dLomWCQKg47rfICgFORMLpCgS6Q9uyHFN3mJ0LWPHOZC03TGKSKwIqrvDMyXJmSausi53cH+iH6e4vRNFNjkCoOs6/yGitTa/cGoadoY+y+KRahSMoMW/vi2SpMWbViXzqTsjkz5a0AYP8CFAxSxWG3VV5DxkUojAIUofQVzOyAQarwrLzK21TtgFuR0DagoTeYfMIyvjy6tru8V6eM3xsMUoVlhVXecVUOjKlU0BcS2NKV4txUrDx6c7GaZilDz8ib4VllmzBl5Yp96YyqkFHhlNAT1NEdSDOT7jaq+dl3m5/RkZxOJ4NUAVm5Yl86xrmp1t7UYUpSFECWAaEDNguUQxlb+1hsonDMXrEvHUWWMC261S/95b2RMCXKeKufUcSFQapwzFSxLxNGVb81bcnHq/K4JqCiEqKzA3pnR7GaZglmnUi3fJiy8ixfpiIV/YzLe9M8hKP3TMGmK1PxQcrtdpumI9mNFWb5DoQRpnb1ZxCQjIp+Nt7qp+s6JEmCx+NhhbECMfNZjmxMz/DyXnlceZ+bYpAqPCuO/w6Nnptak+LclCTL+1eneG4qxqxBCrB4mLLbWY5UJtVmVoQiVoDChmemGKSKw0qzfLnK5q4pKbrVT1jogZ0NI0ixVHPhmP0sRzZm1GdY0c+4uLcM75oygpTb7WaQKhCzVuxLZ4FxbqotzbkpXt47iJmDFGDhMGXXsxzJxM5NpSlCIUULUAi/vcKU0ZEcDgeDVIFYcZYvV41Z3TVlnJuy38oUg1Th2W2Vd3o0TG3McJtfua1MxQcpMxyMtyMrr/KOq1IwqkJGb0hga6r7pnhuKsbsQQoAHKVuQC6MIGWXh1Mm9m/zSzPQjRagsFM1v/ggxfMchWEEqXKZnGisiswW7+7XoOkCipz835TkckEAEDYrj84gVXjhcNh2kxNT6x2QJWB7j4qgJuBWEvedciyPbjyrPB4Pg1SBaJqGUChk2fGfJEk4d3YVAKDek/z3bqyi3+bPIXQNklyeK5xWCFKABVem7FqxL53JmW7zc0dXpmwSphikCq/cVnkBwOuUMdIrQ9Uj902lFKvoZ58wxSBVWMYWJLsFKQDwOGRMqHFAE8C27uTfn1TfALjcEH09EAP9RWxhaTBIFZ5dVnmXH1yF5QdXocGbPCDJNXWQRo8FggHoO1qK2DrzsFKxMUs9Re1csS+dMVUK7jixAfedOjLl6+x0ZopBqvDsXLEvHWOr366+NGEqus1P2CRMMUgVllXPcmQjk61+8eXR9bbdRWlXqTBIFZbVKvblSzmfm7LaGXlLPEnL6SxHMrIk4ajxHoytSrMzM1bNz9phyth3ziBVOHaZ5cvVyVO9+Ma8aoyuTL19wihAARts84u/PJRBKv+sfJYjG5le3rv/3NTOgrepVBikCqucx3/7K/qV17kpqwUpwAJnpsrtLMeBiq1MWbgAhRGkeOdN4djxLEe2zphRmdkLbbIyxSBVWFY/y5GN6bG7plJvO4+tTNn04l5j0MdiE4VhrPLafXIiGefi46HMmAVl8vRSN6VorFpszNRhStd1hEKhsu1IubD6Nj8jSMmyzCBVAMZ2iXK4TiBf7LAyFR+kWKo5/1RVLastSDManM9WBaEAACAASURBVFAkQEfq4Lh/m5/9wlR8kHIZFT8pb8qx0NhQcsNIyA2pj3bYiZWPdpg2TLEj5cjjhfOLX4LkzXDW3USMjqQoCrxer6U6khVwlTdHFg9TDFKFVY6rvHUeBc+fNy5pJT+DXSv6MUgVVjmt8lKElYMUYNIwZRyKp+xJigLvv15d6mbkhEGqcLjKmzu5rh7SyNGAYspflykxSBVOuU9OpAtSgD3DFINUYZXbKi/Z44y8lCb5F31aoBxn+SgSoC0UpA60gUXtV5zlK08WC1KW6lPlfpYjU0LX0XfxmUA4jOqH/gbJuAfRooaekTL5s8pyfYpb0MuPBc/IJ2ygaaZa2ZHKl8WClKVwlq88GcHZIkHKUrgFPXOSLENumgSEQxB9vZYOU/GXh1ogSFlKua/ylis7nZE3xcoUtyCVL13XYx3JQhXGTD/jx8mJ8mU8oCwWpEzfp4DI5EQ4HGaQyoIQwtKDJGBwkDL75aFxLNGnODlRnuKDlMUm0s27MjV00CdJkpV+sJQj4/JQiwUpSzC29hnYp8qDRYOUJRhb++IHAexT6Vn9Z2TRIGUZwWAQqqrGfq58VpUHu52RN8XKFBD5waqqClVVY0u9Rqeyww+aBjOClEXvvLHEjJ8QApqmxfqVgX3KnoxBvsfjgcNhinmybFimT8U/qxis7M3iQcoSfQoYPP6L36HEZ5U9WfxoR8IGmyZMxWOwsjeLBynAQg+p2BccEqyMrTfsU/ZgDOotfHmoJftUsmAFWH9FptxZPEgBFuxTwPBgxWeVvVg8SAFWClPxdF2HpmkIh8MMVjZggyAFWPQhFfviDFa2Ygz6PB6PVYMUYIM+lWh2ncHKmmwQpACL9ymAE+t2Y4MgBVg1TMUzBoHxZ6zYsazDJkEKsMFDymAMGow+xWBlLTYJUoAN+5TxrGKwshbj78/pdMLtdlv578s2fQrgxLrVWbTYWCLWD1Px4oOVpmkcBJqcjYIUYLOHlCHV7Dr7lPnYKEgBNu5TQohYFUDj9yDA8yBmZKMgBdi0TwEMVlZTDuM/y4apeDxob27GoLyiosIOHQmw8UPKwIP25mazIAWUSZ8yghUP2puPzYIUUAZ9CuCOJbOzWZAC7Bym4jFYmYsNgxRQJg8pA4OVuRh/H263Gy6Xq9TNyZey6lMAK5iZidGnHA6H5S8PjVN2fWrojiUD+1Rp2DBIAeUSpuLxoH1pGQMEG955U3YPKQMP2peWTYMUUMZ9CuBB+1KyaZACyrxPcWK9tGwapIByDFPxeNC+uGwcpIAyf0gZeNC+uGwcpAD2qRgGq+KxcZAC2KdiOLFeXDYOUkC5h6l48bPr4XAYxs+A25byw+ZBCuBDaphkB+3jD9tT7mwepAD2qYR40L5wjN9ZiqLYMUgB7FMJMVgVls2DFMAwlRjPg+RXGQQpgA+plIYetNc0jRXMDkB8kHI6nXb9+bFPpcGD9vlTBkEKYJ9KizuW8sumZ+SHYphKh8HqwBg/L5sHKYAPqazwoH3ubHJ5aCbYp7LAq0FyVyZBCmCfygp3LB2YMplIBximspMqWAHctjRUGQUpgA+pnA0NVhwEJldGQQpgn8oZD9pnLv457vV67f7zYZ/KESfWs1NGQQpgmModK5ilVmZBCuBDKi940D65MgtSAPtUXjBYpaZpGhRFKYcgBbBP5QWDVWplFqQAhqn8SHTQHijfYGX8PDweDxwOR6mbUyx8SOUZD9rvV4ZBCmCfyjsetB+szIIUwD6Vd5xYH6wMgxTAMJV/5X7Q3vj+jYPxZYQPqQKK71PldtC+TIMUwD5VUOUerMowSAHsUwVV7leDlGmQAhimCmtosLL7QXvjF4nH4ym3IAXwIVU05XTQvoyDFMA+VTSJKpgB9j1oX6ZBCmCfKppy27FUhkc74jFMFZOdK5iVeZAC+JAqiaHBymCnPuV0OuF2uy3//eSAfaoE7H4eRNd1yLIMj8dj51LNybBPlYDddyyVeZACGKZKx04H7RmkAPAhVXJ2OmjPIAWAfark7BasyuDy0HTYp0zAThPrZXpGfiiGKTOwcrBikIrhQ8pErHwehEEqhn3KRKx+NQiDFAD2KdOx8tUgZXxGfiiGKbOxUgUz4+HqdrvhcrlK3ZxS40PKpKwUrIw+5XA47H55aCbYp0zKahXMGKRi2KdMzEoT65xIH4Rhysziz4OYrYIZg9QwfEhZQKKD9mbrUwxSMexTFmD2CmYMUoOwT1mEmSfWGaSGYZiyCjNVMGOQSogPKYtJNbteqj7FIDUI+5TFJKpgVsqD9gxSw7BPWZCZghWDVEIMU1ZUyoP2DFJJ8SFlYaU8aG98LUVRGKQGY5+ysFJfDcIglRD7lMWVcscSg1RSDFNWV8xgFR+knE4nB32D8SFlE8UMVgxSKbFP2UgxK5gZn7+iooJBajD2KRsp5tUgDFIpMUzZSSEP2jNIpcWHlA0V8qA9g1Ra7FM2VciD9kYfLeM7b1Jhn7KpQk6sc0dSWgxTdpXPg/bG53K5XHC5XBz0JcaHlM3l86B9/GqX1+tln0qMfaoM5DNYMUilxT5VBvI5sc4glRGGqXIQP7seDodh/P1msm2JQSpjfEiVkWQH7eMP26eiaRoURWGQSo19qswcyEF7BqmMsE+VmQMJVgxSGWOYKjfZnAdhkMoKH1JlauhBe03TUlYwY5DKGPtUGcvmoD2DVMbYp8pYNjuWGKSywjBVztLdaM8glRU+pAhA6oP2uq4zSGWOfYoApL4axBivMEhlhH2KAKTesQSAZ+SzwzBFEYkO2jNIZYUPKRpm6HkQBqmssE/RMIkO2jNIZYx9iobh+O+AMUzRcMYKlRlu2rYQPqQopaHnqigt9ilKaehuCkqLfYpS4vgvJwxTRHnChxRRfrFPEeUX+xRR/iXsV5ziISIiIiIiygHDFBERERERUQ4YpoiIiIiIiHLAMEVERERERJQDhikiIiIiIqIcMEwRERERERHlgGGKiIiIiIgoBwxTREREREREOWCYIiIiIiIiygHDFBERERERUQ4kIUSp20BERERERGQ5XJkiIiIiIiLKAcMUERERERFRDhimiIiIiIiIcsAwRURERERElAOGKSIiIiIiohwwTBEREREREeWAYYqIiIiIiCgHDFNEREREREQ5YJgiIiIiIiLKAcMUERERERFRDhimiIiIiIiIcuBI835RlFYQWYt0gB/PfkU0GPsUUX6xTxHlX8J+xZWpDDU3N2P+/Pmorq7GL37xi1I3h8jy2KeI8ot9iij/2K8oHYapDN15551YunQp+vr68O1vf7vUzUnr8ssvx8yZMyHLMh566KFB7/vDH/6ARYsWoaamBk1NTbjmmmugqmrs/Z2dnTj77LNRWVmJSZMm4c9//nORW0/lwE596qGHHoKiKKiqqor979VXX429f9u2bVi6dCkqKiowa9YsrFy5sriNp7Jgpz4lhMD111+P8ePHo7a2FkuWLMGGDRti7w8Gg7j00ktRU1ODsWPH4mc/+1mRW0/lwkr96vPPP8dZZ52FUaNGoaGhAaeccgqam5tj71+/fj1OOeUUjBw5EpI0fJGF47/cMExlqKWlBXPmzEn6fk3Titia9A499FDcd999WLhw4bD3+Xw+3HPPPejo6MB7772Hl19+GXfddVfs/VdddRVcLhfa2trw8MMP48orrxz0ECPKBzv1KQBYvHgx+vv7Y/9bsmRJ7H3nnXceFixYgH379uHWW2/F8uXL0d7eXqSWU7mwU5967LHHsGLFCrzxxhvo7OzE4sWLcdFFF8Xef9NNN2Hjxo1oaWnBK6+8gjvvvBMvvPBCMZtPZcJK/aq7uxtnnnkmmpub0dbWhiOOOAJnnXVW7P1OpxPnnHMOHnzwwYQfz/FfjoQQqf5HQoilS5cKWZaF2+0WlZWVorm5WVxyySXiiiuuEMuWLRMVFRXipZdeEs8884yYP3++qK6uFk1NTeLGG2+MfY6tW7cKAGLFihWiqalJ1NXVifvvv1+sWrVKzJ07V9TW1oqrrrpq0Nd98MEHxaxZs0RdXZ04+eSTxbZt27Ju+zHHHCN+//vfp3zNT3/6U3H66acLIYTo7+8XTqdTNDc3x95/4YUXimuvvTbrr21j6foN+1UadutTv//978UxxxyT8PXNzc3C5XKJ3t7e2NuOPfZYcf/992f9tW2MfeoA2a1P3X777eJrX/ta7M/r168Xbrc79udx48aJF1/8/+3dd5xcdb3/8dc5Z+r23RSSbHogIXSQIh2RiwK/C4IKYgP1oogNFUQUkaaoqMhVkSsqlnuvBRC4oAiKIAJKkR5ICCW9J9unn3N+f8yeyWyfmczstPfz8eBBsvU7Sb57vu9v+Xzvy/z+sssuc88666y8v3cNU58qgmruV67rutu3b3cBd9u2bUPevnLlSjcdAXbS+C8no/YXdaYcHXvsse7NN9+c+f0555zjtrS0uI888ohr27YbjUbdBx980H3++edd27bd5557zp0+fbp7xx13uK67szN97GMfc6PRqHvfffe5wWDQPe2009zNmze769atc6dNm+Y+9NBDruu67p133ukuWrTIfemll9xkMuleffXV7uGHH575/qeccop77bXXTtjuXMLUaaedluksTz/9tBsOh4e8/7rrrsuELXFdVw+poqilPnXLLbe4DQ0N7pQpU9w99tjDveqqq9xkMum6ruv+/ve/d/fcc88hH/+JT3zC/eQnP1nQn1uNUp8qglrqU6tWrXIPOuggd8WKFW4ikXAvvvhi97TTTnNd13V37NjhAu6mTZsyH3/rrbe6++yzT8F/djVIfapIqrVfua7r3nHHHe6MGTNGvH20MKXxX05G7S/a5rcLTjvtNI488khM0yQUCnHcccex7777Ypom++23H2effTZ/+9vfhnzOV77yFUKhECeeeCKNjY2cffbZTJ8+nc7OTo4++mieeeYZAG666SYuvfRSli5dis/n40tf+hLPPvssq1evBuCee+7hi1/84i6/hp/97Gc89dRTXHTRRQD09/fT0tIy5GNaW1vp6+vb5e8lMpFq7VPHHHMML774Ilu2bOH222/n17/+Nddddx2Q7lOtra1DPl59SiZLtfapmTNnctRRR7FkyRLC4TC33nor119/PZDuU8CQfqU+JZOpGvrVunXr+MQnPpHzeUKN/wqnMLUL5syZM+T3jz/+OG95y1uYNm0ara2t3HTTTWzbtm3Ix+y2226ZX4fD4RG/9x4Sq1ev5jOf+QxtbW20tbXR0dGB67qsX7++aO2/8847ufTSS7n33nuZOnUqAE1NTfT29g75uN7eXpqbm4v2fUXGUq19auHChSxYsADTNNl33325/PLLue222wD1KSmvau1TV111FU8++SRr164lFovx1a9+leOPP55IJEJTUxPAkH6lPiWTqdL71datWznxxBO54IILOPvss3P6HD2rCqcwtQuGV0J573vfy6mnnsratWvp6enh/PPPT++lLMCcOXP4r//6L7q7uzP/RaNRjjjiiGI0nT/96U+cd9553H333ey7776Zty9evJhUKsXKlSszb3vuuefGPXwpUizV3KeyGYaRaefee+/N66+/PmR2T31KJku19qlnn32Ws846i9mzZ+Pz+Tj33HPp6uripZdeor29nZkzZ/Lcc89lPl59SiZTJferrq4uTjzxRE499VS+/OUv5/x9Nf4rnMJUEfX19dHR0UEoFOKJJ57YpZKS559/Ptdee22mikpPTw+33nprzp+fSCSIxWK4rksymSQWi+E4DgB//etfed/73sftt9/OoYceOuTzGhsbOeOMM7j88ssZGBjg0Ucf5a677hpSRUlkslRLn7r33nvZvHkzAMuXL+fqq6/OVFBavHgxBxxwAFdeeSWxWIw77riD559/nne+850FvxaRQlVLnzrkkEO49dZb2bx5M47j8Ktf/YpkMsnuu+8OwAc/+EGuueYaurq6WL58OTfffDPnnntuwa9FZFdUSr/q7e3lbW97G0ceeSTf+MY3RrzfdV1isRiJRAKAWCxGPB4HNP7bFQpTRXTjjTdy+eWX09zczFVXXcWZZ55Z8Nc6/fTTueSSS3jPe95DS0sL++yzD/fee2/m/SeddBJf//rXx/z8E088kXA4zGOPPcZHP/pRwuEwDz/8MABXX301PT09nHzyyZk7cU466aQhryMajTJ9+nTOPvtsfvSjH2lmQsqiWvrUAw88wH777UdjYyMnn3wyZ5xxBl/60pcyn/ub3/yGp556ivb2dr74xS9y2223MW3atIJfi0ihqqVPXXLJJey///4ccMABtLW1cf3113P77bfT1tYGwJVXXsmiRYuYN28exx57LBdffDFvf/vbC34tIruiUvrVHXfcwZNPPsktt9wy5N7DNWvWAOkthOFwODOmC4fDLFmyZMjr0Pgvf8YEy5CFrVGK1LaRN93lR/1KZCj1KZHiUp8SKb5R+5VWpkRERERERAqgMCUiIiIiIlIAhSkREREREZECKEyJiIiIiIgUQGFKRERERESkAApTIiIiIiIiBVCYEhERERERKYDClIiIiIiISAEUpkRERERERAqgMCUiIiIiIlIAhSkREREREZECKEyJiIiIiIgUQGFKRERERESkAApTIiIiIiIiBVCYEhERERERKYDClIiIiIiISAEUpkRERERERAqgMCUiIiIiIlIAhSkREREREZECKEyJiIiIiIgUQGFKRERERESkAApTIiIiIiIiBVCY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\n", 337 | "text/plain": [ 338 | "
" 339 | ] 340 | }, 341 | "metadata": {}, 342 | "output_type": "display_data" 343 | } 344 | ], 345 | "source": [ 346 | "def plot(fig, subplot_xmax, subplot_ymax, subplot_idx, pose, frame_idx=None):\n", 347 | " ax = fig.add_subplot(\n", 348 | " f\"{subplot_ymax}{subplot_xmax}{subplot_idx}\",\n", 349 | " projection='3d'\n", 350 | " )\n", 351 | " vis_utils.show_3d_pose(pose, ax)\n", 352 | " if frame_idx is not None:\n", 353 | " ax.set_title(f\"frame: {frame_idx}\")\n", 354 | " \n", 355 | "\n", 356 | "fig = plt.figure(figsize=(12, 6))\n", 357 | "\n", 358 | "subplot_xmax, subplot_ymax = 4, 2\n", 359 | "frame_increment = 30\n", 360 | "\n", 361 | "subplot_idx = 0\n", 362 | "for x in range(subplot_xmax):\n", 363 | " for y in range(subplot_ymax):\n", 364 | " frame_idx = subplot_idx * frame_increment\n", 365 | " plot(\n", 366 | " fig,\n", 367 | " subplot_xmax,\n", 368 | " subplot_ymax,\n", 369 | " subplot_idx + 1,\n", 370 | " pose_seq[frame_idx],\n", 371 | " frame_idx\n", 372 | " )\n", 373 | " subplot_idx += 1\n", 374 | "\n", 375 | "fig.tight_layout()" 376 | ] 377 | }, 378 | { 379 | "cell_type": "code", 380 | "execution_count": null, 381 | "metadata": {}, 382 | "outputs": [], 383 | "source": [] 384 | } 385 | ], 386 | "metadata": { 387 | "kernelspec": { 388 | "display_name": "Python 3", 389 | "language": "python", 390 | "name": "python3" 391 | }, 392 | "language_info": { 393 | "codemirror_mode": { 394 | "name": "ipython", 395 | "version": 3 396 | }, 397 | "file_extension": ".py", 398 | "mimetype": "text/x-python", 399 | "name": "python", 400 | "nbconvert_exporter": "python", 401 | "pygments_lexer": "ipython3", 402 | "version": "3.7.7" 403 | } 404 | }, 405 | "nbformat": 4, 406 | "nbformat_minor": 4 407 | } 408 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # human_3d_pose_estimation 2 | h5py 3 | numpy 4 | tqdm 5 | torch==1.5.0 6 | yacs 7 | 8 | # misc 9 | flake8 10 | jupyterlab 11 | matplotlib==3.0.3 12 | tensorboard 13 | tensorboardX 14 | -------------------------------------------------------------------------------- /tools/_init_path.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | import sys 3 | 4 | 5 | def init_path(): 6 | """Add path to spacenet6_model dir 7 | """ 8 | this_dir = os.path.dirname(os.path.abspath(__file__)) 9 | proj_dir = os.path.abspath(os.path.join(this_dir, "..")) 10 | sys.path.append(proj_dir) 11 | 12 | 13 | init_path() 14 | -------------------------------------------------------------------------------- /tools/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import json 3 | import os 4 | 5 | from _init_path import init_path 6 | from human_3d_pose_baseline.configs import load_config 7 | from human_3d_pose_baseline.datasets import get_dataset 8 | from human_3d_pose_baseline.engines import test_epoch 9 | from human_3d_pose_baseline.models import get_model 10 | from human_3d_pose_baseline.solvers import get_criterion 11 | from human_3d_pose_baseline.utils.cuda import get_device 12 | 13 | 14 | def main(): 15 | """Evaluate model. 16 | """ 17 | 18 | config = load_config() 19 | human36m = get_dataset(config) 20 | model = get_model(config) # Load weight from config.MODEL.WEIGHT. 21 | criterion = get_criterion(config) 22 | device = get_device(config.USE_CUDA) 23 | 24 | # Prepare directory to output evaluation results. 25 | out_dir = config.OUTPUT_DIR 26 | os.makedirs(out_dir, exist_ok=False) 27 | 28 | # Testing. 29 | print("Evaluating...") 30 | test_logs = test_epoch(config, model, criterion, human36m, device) 31 | 32 | # Print. 33 | mpjpe = test_logs["MPJPE"] 34 | print(f"MPJPE: {mpjpe:.4f}") 35 | 36 | # Log. 37 | out_path = os.path.join(out_dir, "eval_results.json") 38 | with open(out_path, "w") as f: 39 | json.dump( 40 | test_logs, 41 | f, 42 | ensure_ascii=False, 43 | indent=4, 44 | sort_keys=True, 45 | separators=(",", ": "), 46 | ) 47 | print(f"Dumped detailed evaluation results to {out_path}.") 48 | 49 | 50 | if __name__ == "__main__": 51 | main() 52 | -------------------------------------------------------------------------------- /tools/train.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | 4 | import torch 5 | from tensorboardX import SummaryWriter 6 | 7 | from _init_path import init_path 8 | from human_3d_pose_baseline.configs import load_config 9 | from human_3d_pose_baseline.datasets import get_dataset 10 | from human_3d_pose_baseline.engines import test_epoch, train_epoch 11 | from human_3d_pose_baseline.models import get_model 12 | from human_3d_pose_baseline.solvers import ( 13 | get_criterion, 14 | get_lr_scheduler, 15 | get_optimizer, 16 | ) 17 | from human_3d_pose_baseline.utils.cuda import get_device 18 | 19 | 20 | def main(): 21 | """Train model. 22 | """ 23 | 24 | config = load_config() 25 | human36m = get_dataset(config) 26 | model = get_model(config) 27 | criterion = get_criterion(config) 28 | optimizer = get_optimizer(config, model) 29 | lr_scheduler = get_lr_scheduler(config, optimizer) 30 | device = get_device(config.USE_CUDA) 31 | 32 | # Prepare directory to output training logs and model weights. 33 | out_dir = config.OUTPUT_DIR 34 | os.makedirs(out_dir, exist_ok=False) 35 | # Prepare tensorboard logger. 36 | tblogger = SummaryWriter(out_dir) 37 | 38 | mpjpe_lowest = 1e10 39 | 40 | for epoch in range(config.SOLVER.EPOCHS): 41 | print() 42 | 43 | lr = lr_scheduler.get_last_lr()[0] 44 | print(f"epoch: {epoch}, lr: {lr:.10f}") 45 | 46 | # Training. 47 | print("Training...") 48 | train_logs = train_epoch( 49 | config, model, criterion, optimizer, lr_scheduler, human36m, device 50 | ) 51 | 52 | # Testing. 53 | print("Testing...") 54 | test_logs = test_epoch(config, model, criterion, human36m, device) 55 | 56 | # Save model weight if lowest error is updated. 57 | mpjpe = test_logs["MPJPE"] 58 | if mpjpe < mpjpe_lowest: 59 | torch.save(model.state_dict(), os.path.join(out_dir, "model_best.pth")) 60 | mpjpe_lowest = mpjpe 61 | 62 | # Print. 63 | train_loss = train_logs["loss"] 64 | test_loss = test_logs["loss"] 65 | print( 66 | f"train_loss: {train_loss:.8f}, test_loss: {test_loss:.8f}, MPJPE: {mpjpe:.4f}, MPJPE(best): {mpjpe_lowest:.4f}" 67 | ) 68 | 69 | # Log. 70 | tblogger.add_scalar("lr", lr, epoch) 71 | tblogger.add_scalar("train/loss", train_loss, epoch) 72 | tblogger.add_scalar("test/loss", test_loss, epoch) 73 | for metric in config.EVAL.METRICS_TO_LOG: 74 | tblogger.add_scalar(f"test/{metric}", test_logs[metric], epoch) 75 | 76 | 77 | if __name__ == "__main__": 78 | main() 79 | --------------------------------------------------------------------------------