diff --git a/.gitattributes b/.gitattributes index a6344aac8c09253b3b630fb776ae94478aa0275b..994d56be2393ecc80b46d898e201881f416c33d4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -33,3 +33,14 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text *.zst filter=lfs diff=lfs merge=lfs -text *tfevents* filter=lfs diff=lfs merge=lfs -text +*.torchscript filter=lfs diff=lfs merge=lfs -text +*.pkl filter=lfs diff=lfs merge=lfs -text +./magick filter=lfs diff=lfs merge=lfs -text +models/* filter=lfs diff=lfs merge=lfs -text +models/nlf_l_multi.torchscript filter=lfs diff=lfs merge=lfs -text +models/checkpoint_150.pt filter=lfs diff=lfs merge=lfs -text +downloads/* filter=lfs diff=lfs merge=lfs -text +outputs/* filter=lfs diff=lfs merge=lfs -text +intermediate_results/* filter=lfs diff=lfs merge=lfs -text +predictions/* filter=lfs diff=lfs merge=lfs -text +predictions/joints3d.npy filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..fc92d618f2cdfc8052200188e112e3b5ff6ad478 --- /dev/null +++ b/.gitignore @@ -0,0 +1,213 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# Virtual Environment +venv/ +ENV/ +env/ +.env + +# IDE +.idea/ +.vscode/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db + +# Project specific +*.pth +*.ckpt +# *.pt +*.bin +*.npy +*.npz +*.mp4 +*.avi +*.mov +*.jpg +*.jpeg +*.png + +# Logs +*.log +logs/ + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +# downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# UV +# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +#uv.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# PyPI configuration file +.pypirc +9622_GRAB/ +magick +outputs/*_obj +outputs/ +intermediate_results/ \ No newline at end of file diff --git a/.gradio/certificate.pem b/.gradio/certificate.pem new file mode 100644 index 0000000000000000000000000000000000000000..b85c8037f6b60976b2546fdbae88312c5246d9a3 --- /dev/null +++ b/.gradio/certificate.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..c5798d02f451686ccdf167506f3a654aef2038c8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "python.analysis.extraPaths": [ + "./SkeletonDiffusion/src", + "./src_joints2smpl_demo/convert_" + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 5ea35138c60796798200220fc1a099c3cfcba0db..51790050e767702d01a843aabd1e7c0bc9b3d872 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,12 @@ emoji: 💻 colorFrom: purple colorTo: green sdk: gradio -sdk_version: 5.12.0 +sdk_version: 5.24.0 app_file: app.py pinned: false license: mit +run: | + bash setup.sh + python app.py --- -Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference diff --git a/Roboto-VariableFont_wdth,wght.ttf b/Roboto-VariableFont_wdth,wght.ttf new file mode 100644 index 0000000000000000000000000000000000000000..bba55f616c811c4ee31535667dd2ed30229e5e71 Binary files /dev/null and b/Roboto-VariableFont_wdth,wght.ttf differ diff --git a/SkeletonDiffusion/__init__.py b/SkeletonDiffusion/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/SkeletonDiffusion/configs/config_eval/config.yaml b/SkeletonDiffusion/configs/config_eval/config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a825a850b47b5ce0e3fbead3dce7a2a906e1d7ad --- /dev/null +++ b/SkeletonDiffusion/configs/config_eval/config.yaml @@ -0,0 +1,53 @@ +hydra: + output_subdir: null + run: + dir: . + job: + chdir: False + +dataset_main_path: ./datasets +dataset_annotation_path: ${dataset_main_path}/annotations&interm +dataset_precomputed_path: ${dataset_main_path}/processed +checkpoint_path: '' +defaults: + - _self_ + - task: hmp + - method_specs: skeleton_diffusion + - dataset: amass + - override hydra/hydra_logging: disabled + - override hydra/job_logging: disabled + +method_name: ${method_specs.method_name} +dtype: float32 +if_noisy_obs: False +noise_level: 0.25 +noise_std: 0.02 +# num_nodes: ${eval:"int(${dataset.num_joints})-int(not ${task.if_consider_hip})"} + +stats_mode: deterministic #probabilistic, deterministic +batch_size: 512 +metrics_at_cpu: False +n_gpu: 1 +num_samples: 50 +if_measure_time: False + +seed: 0 +dataset_split: test +silent: False + +obs_length: ${eval:'int(${task.history_sec} * ${dataset.fps})'} +pred_length: ${eval:'int(${task.prediction_horizon_sec} * ${dataset.fps})'} + +if_store_output: False +store_output_path: ${eval:"'models/final_predictions_storage/${task.task_name}/${method_specs.method_name}/${dataset.dataset_name}/' if not ${if_long_term_test} else 'models/final_predictions_storage/${task.task_name}_longterm/${method_specs.method_name}/${dataset.dataset_name}/'"} +if_store_gt: False +store_gt_path: ${eval:"'models/final_predictions_storage/${task.task_name}/GT/${dataset.dataset_name}/' if not ${if_long_term_test} else 'models/final_predictions_storage/${task.task_name}_longterm/GT/${dataset.dataset_name}/'"} + +if_compute_apde: ${eval:"False if ${eval:"'${dataset.dataset_name}' in ['freeman', '3dpw', 'nymeria']"} else True"} +if_long_term_test: False +long_term_factor: 2.5 + +if_compute_fid: False +if_compute_cmd: False + + diff --git a/SkeletonDiffusion/configs/config_eval/config_inferencetime.yaml b/SkeletonDiffusion/configs/config_eval/config_inferencetime.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c6794666d0957873eb5ac865a5072d2fcaa34876 --- /dev/null +++ b/SkeletonDiffusion/configs/config_eval/config_inferencetime.yaml @@ -0,0 +1,43 @@ +hydra: + output_subdir: null + run: + dir: . + job: + chdir: False + +dataset_main_path: ./datasets +dataset_annotation_path: ${dataset_main_path}/annotations&interm +dataset_precomputed_path: ${dataset_main_path}/processed +checkpoint_path: '' +defaults: + - _self_ + - task: hmp + - method_specs: skeldiff + - dataset: amass + - override hydra/hydra_logging: disabled + - override hydra/job_logging: disabled + +method_name: ${method_specs.method_name} +dtype: float32 +if_noisy_obs: False +noise_level: 0.25 +noise_std: 0.02 + +mode: stats # 'vis: visualize results\ngen: generate and store all visualizations for a single batch\nstats: launch numeric evaluation') +stats_mode: deterministic # +if_measure_time: True +batch_size: 1 +metrics_at_cpu: False +n_gpu: 1 +num_samples: 50 + +seed: 0 +dataset_split: test +silent: False + +obs_length: ${eval:'int(${task.history_sec} * ${dataset.fps})'} +pred_length: ${eval:'int(${task.prediction_horizon_sec} * ${dataset.fps})'} + +if_long_term_test: False + + diff --git a/SkeletonDiffusion/configs/config_eval/dataset/3dpw.yaml b/SkeletonDiffusion/configs/config_eval/dataset/3dpw.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6e324f037d8bd84ed20256067b35bbfaa4168f10 --- /dev/null +++ b/SkeletonDiffusion/configs/config_eval/dataset/3dpw.yaml @@ -0,0 +1,35 @@ +num_joints: 22 #including the hip root joint +fps: 60 + +multimodal_threshold: 0.4 +dataset_type: D3PWZeroShotDataset +dataset_name: 3dpw +precomputed_folder: "${dataset_precomputed_path}/3DPW/${task.task_name}/" +annotations_folder: "${dataset_annotation_path}/3DPW/${task.task_name}/" +dtype: float32 + +data_loader_train_eval: + stride: 30 + augmentation: 0 + shuffle: False + da_mirroring: 0. + da_rotations: 0. + drop_last: False + if_load_mmgt: False + +data_loader_valid: + stride: 30 + augmentation: 0 + shuffle: False + segments_path: "${dataset.annotations_folder}/segments_valid.csv" + actions: "all" + drop_last: False + if_load_mmgt: False + + +data_loader_test: + shuffle: False + segments_path: "${dataset.annotations_folder}/segments_test_zero_shot.csv" + actions: "all" + drop_last: False + if_load_mmgt: ${eval:'True if "probabilistic" in "${stats_mode}" else False'} diff --git a/SkeletonDiffusion/configs/config_eval/dataset/amass-mano.yaml b/SkeletonDiffusion/configs/config_eval/dataset/amass-mano.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4e376991e30e20db610d760f45804f6a08076e00 --- /dev/null +++ b/SkeletonDiffusion/configs/config_eval/dataset/amass-mano.yaml @@ -0,0 +1,76 @@ +num_joints: 52 #included hip even if if_consider_hip=False +fps: 60 + +multimodal_threshold: 0.4 +dataset_type: AMASSDataset +dataset_name: amass-mano +precomputed_folder: "${dataset_precomputed_path}/AMASS-MANO/${task.task_name}/" +annotations_folder: "${dataset_annotation_path}/AMASS-MANO/${task.task_name}/" +dtype: float32 + +# Accordingly, the training set +# contains the ACCAD, BMLhandball, BMLmovi, BMLrub, +# CMU, EKUT, EyesJapanDataset, KIT, PosePrior, TCD- +# Hands, and TotalCapture datasets, and the validation set +# contains the HumanEva, HDM05, SFU, and MoSh datasets. +# The remaining datasets are all part of the test set: DFaust, +# DanceDB, GRAB, HUMAN4D, SOMA, SSM, and Transi- +# tions. + + +data_loader_train: + stride: 60 + augmentation: 30 + shuffle: True + datasets: ['ACCAD', "BMLhandball", "BMLmovi", "BMLrub", 'EKUT', 'CMU', 'EyesJapanDataset', 'KIT', "PosePrior", 'TCDHands', 'TotalCapture'] # from paper + + + + # "EyesJapanDataset", + + # , + + # "HDM05", + # "MoSh" + da_mirroring: 0.5 + da_rotations: 1.0 + drop_last: True + if_load_mmgt: False + + +data_loader_train_eval: + stride: 30 + augmentation: 0 + shuffle: False + datasets: ['ACCAD', "BMLhandball", "BMLmovi", "BMLrub", 'EKUT', 'CMU', 'EyesJapanDataset', 'KIT', "PosePrior", 'TCDHands', 'TotalCapture'] # from paper + # datasets: ['ACCAD', "BMLhandball", "BMLmovi", 'CMU', 'KIT', 'TotalCapture'] # decrease evaluatio time + da_mirroring: 0. + da_rotations: 0. + drop_last: False + if_load_mmgt: False + +data_loader_valid: + stride: 30 + augmentation: 0 + shuffle: False + # segments_path: "./dataset_annotation_path/FreeMan/${task.task_name}/segments_valid.csv" + datasets: ['HumanEva', 'HDM05', 'SFU', 'MoSh'] # from paper + file_idces: "all" + drop_last: False + if_load_mmgt: False + + +data_loader_test: + shuffle: False + segments_path: "${dataset.annotations_folder}/segments_test.csv" + # datasets: ['Transitions_mocap', 'SSM_synced'], #DFaust, DanceDB, GRAB, HUMAN4D, SOMA, SSM, and Transitions. + datasets: + - Transitions + - SSM + - DFaust + - DanceDB + - GRAB + - HUMAN4D + - SOMA + drop_last: False + if_load_mmgt: False diff --git a/SkeletonDiffusion/configs/config_eval/dataset/amass.yaml b/SkeletonDiffusion/configs/config_eval/dataset/amass.yaml new file mode 100644 index 0000000000000000000000000000000000000000..01776177b96d80baac4c9bacf710d9a19cd3e37f --- /dev/null +++ b/SkeletonDiffusion/configs/config_eval/dataset/amass.yaml @@ -0,0 +1,52 @@ +num_joints: 22 #including the hip root joint +fps: 60 + +multimodal_threshold: 0.4 +dataset_type: AMASSDataset +dataset_name: "amass" +precomputed_folder: "${dataset_precomputed_path}/AMASS/${task.task_name}/" +annotations_folder: "${dataset_annotation_path}/AMASS/${task.task_name}/" +dtype: float32 + +# Accordingly, the training set +# contains the ACCAD, BMLhandball, BMLmovi, BMLrub, +# CMU, EKUT, EyesJapanDataset, KIT, PosePrior, TCD- +# Hands, and TotalCapture datasets, and the validation set +# contains the HumanEva, HDM05, SFU, and MoSh datasets. +# The remaining datasets are all part of the test set: DFaust, +# DanceDB, GRAB, HUMAN4D, SOMA, SSM, and Transi- +# tions. + +data_loader_train_eval: + stride: 30 + augmentation: 0 + shuffle: False + datasets: ['ACCAD', "BMLhandball", "BMLmovi", "BMLrub", 'EKUT', 'CMU', 'EyesJapanDataset', 'KIT', "PosePrior", 'TCDHands', 'TotalCapture'] + da_mirroring: 0. + da_rotations: 0. + drop_last: False + if_load_mmgt: False + +data_loader_valid: + stride: 30 + augmentation: 0 + shuffle: False + datasets: ['HumanEva', 'HDM05', 'SFU', MoSh'] + file_idces: "all" + drop_last: False + if_load_mmgt: False + + +data_loader_test: + shuffle: False + segments_path: ${eval:"'${dataset.annotations_folder}/segments_test.csv' if not ${if_long_term_test} else '${dataset.annotations_folder}/segments_5s_test_long_term_pred.csv'"} + datasets: + - Transitions + - SSM + - DFaust + - DanceDB + - GRAB + - HUMAN4D + - SOMA + drop_last: False + if_load_mmgt: ${eval:'True if "probabilistic" in "${stats_mode}" else False'} \ No newline at end of file diff --git a/SkeletonDiffusion/configs/config_eval/dataset/freeman.yaml b/SkeletonDiffusion/configs/config_eval/dataset/freeman.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c6a54eafb960e3402afdb37dbfe97a7a27dd7677 --- /dev/null +++ b/SkeletonDiffusion/configs/config_eval/dataset/freeman.yaml @@ -0,0 +1,23 @@ +num_joints: 18 #including the hip root joint +fps: 30 +dataset_type: FreeManDataset +dataset_name: "freeman" +precomputed_folder: "${dataset_precomputed_path}/FreeMan/${task.task_name}/" +annotations_folder: "${dataset_annotation_path}/FreeMan/${task.task_name}/" +dtype: float32 +multimodal_threshold: 0.5 + +data_loader_valid: + shuffle: False + segments_path: "${dataset.annotations_folder}/segments_valid.csv" + actions: "all" + drop_last: False + if_load_mmgt: ${eval:'True if "probabilistic in str(${stats_mode})" else False'} + + +data_loader_test: + shuffle: False + segments_path: "${dataset.annotations_folder}/segments_test.csv" + actions: "all" + drop_last: False + if_load_mmgt: ${eval:'True if "probabilistic" in "${stats_mode}" else False'} \ No newline at end of file diff --git a/SkeletonDiffusion/configs/config_eval/dataset/h36m.yaml b/SkeletonDiffusion/configs/config_eval/dataset/h36m.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0e2fcaace744abb8bae3e09172a8d7591cd561f8 --- /dev/null +++ b/SkeletonDiffusion/configs/config_eval/dataset/h36m.yaml @@ -0,0 +1,26 @@ +num_joints: 17 #including the hip root joint +fps: 50 +dataset_type: H36MDataset +dataset_name: "h36m" +precomputed_folder: "${dataset_precomputed_path}/Human36M/${task.task_name}/" +annotations_folder: "${dataset_annotation_path}/Human36M/${task.task_name}" +dtype: float32 +multimodal_threshold: 0.5 + +data_loader_valid: + augmentation: 0 + shuffle: False + subjects: ["S8"] + segments_path: "${dataset.annotations_folder}/segments_valid.csv" + actions: "all" + drop_last: False + if_load_mmgt: ${eval:'True if "probabilistic in str(${stats_mode})" else False'} + +data_loader_test: + shuffle: False + augmentation: 0 + segments_path: "${dataset.annotations_folder}/segments_test.csv" + subjects: ["S9", "S11"] + actions: "all" + drop_last: False + if_load_mmgt: ${eval:'True if "probabilistic" in "${stats_mode}" else False'} \ No newline at end of file diff --git a/SkeletonDiffusion/configs/config_eval/method_specs/skeleton_diffusion.yaml b/SkeletonDiffusion/configs/config_eval/method_specs/skeleton_diffusion.yaml new file mode 100644 index 0000000000000000000000000000000000000000..89ff21a642614011513ff4dbb2950bf0c6300cc9 --- /dev/null +++ b/SkeletonDiffusion/configs/config_eval/method_specs/skeleton_diffusion.yaml @@ -0,0 +1 @@ +method_name: SkeletonDiffusion \ No newline at end of file diff --git a/SkeletonDiffusion/configs/config_eval/method_specs/zerovelocity_alg_baseline.yaml b/SkeletonDiffusion/configs/config_eval/method_specs/zerovelocity_alg_baseline.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cc61b0f0b84dfb523a21dc6230c413d2cec92cd1 --- /dev/null +++ b/SkeletonDiffusion/configs/config_eval/method_specs/zerovelocity_alg_baseline.yaml @@ -0,0 +1,3 @@ +motion_repr_type: "SkeletonCenterPose" +method_name: ZeroVelocityBaseline +baseline_out_path: ./models/output/baselines \ No newline at end of file diff --git a/SkeletonDiffusion/configs/config_eval/task/hmp.yaml b/SkeletonDiffusion/configs/config_eval/task/hmp.yaml new file mode 100644 index 0000000000000000000000000000000000000000..182d607d006d070d772da47b4f92f860d4254725 --- /dev/null +++ b/SkeletonDiffusion/configs/config_eval/task/hmp.yaml @@ -0,0 +1,4 @@ +history_sec: 0.5 #${eval:'float(1) if ${task}=="motpred" else float(0.5)'} +prediction_horizon_sec: 2 # ${eval:"float(4) if ${task}=='motpred' else float(2)"} +task_name: "hmp" +if_consider_hip: False diff --git a/SkeletonDiffusion/configs/config_train/config_autoencoder.yaml b/SkeletonDiffusion/configs/config_train/config_autoencoder.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1cf88b4bdd5c4fdac606de7c73681250380ea136 --- /dev/null +++ b/SkeletonDiffusion/configs/config_train/config_autoencoder.yaml @@ -0,0 +1,27 @@ +defaults: + - _self_ + - task: hmp + - dataset: h36m + - model: autoencoder + - override hydra/job_logging: disabled + # - override hydra/hydra_logging: disabled + +dataset_main_path: ./datasets +dataset_annotation_path: ${dataset_main_path}/annotations&interm +dataset_precomputed_path: ${dataset_main_path}/processed +if_resume_training: false +debug: false +device: cuda +load: false +load_path: '' +output_log_path: ../../my_exps/output/${task.task_name}/${dataset.dataset_name}/autoencoder/${now:%B%d_%H-%M-%S}_ID${slurm_id}_${info} +slurm_id: 0 +slurm_first_run: None +info: '' +hydra: + run: + dir: ${output_log_path} + job: + chdir: False + + diff --git a/SkeletonDiffusion/configs/config_train/dataset/amass.yaml b/SkeletonDiffusion/configs/config_train/dataset/amass.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d7b12f96c8f2965c1600cf705484cb2a600f2114 --- /dev/null +++ b/SkeletonDiffusion/configs/config_train/dataset/amass.yaml @@ -0,0 +1,48 @@ +num_joints: 22 #including the hip root joint +fps: 60 + +multimodal_threshold: 0.4 +dataset_type: AMASSDataset +dataset_name: amass +precomputed_folder: "${dataset_precomputed_path}/AMASS/${task.task_name}/" +annotations_folder: "${dataset_annotation_path}/AMASS/${task.task_name}/" +dtype: float32 + +# Accordingly, the training set +# contains the ACCAD, BMLhandball, BMLmovi, BMLrub, +# CMU, EKUT, EyesJapanDataset, KIT, PosePrior, TCD- +# Hands, and TotalCapture datasets, and the validation set +# contains the HumanEva, HDM05, SFU, and MoSh datasets. +# The remaining datasets are all part of the test set: DFaust, +# DanceDB, GRAB, HUMAN4D, SOMA, SSM, and Transi- +# tions. + +data_loader_train: + stride: 60 + augmentation: 30 + shuffle: True + datasets: ['ACCAD', "BMLhandball", "BMLmovi", "BMLrub", 'EKUT', 'CMU', 'EyesJapanDataset', 'KIT', "PosePrior", 'TCDHands', 'TotalCapture'] + da_mirroring: 0.5 + da_rotations: 1.0 + drop_last: True + if_load_mmgt: False + + +data_loader_train_eval: + stride: 30 + augmentation: 0 + shuffle: False + datasets: ['ACCAD', "BMLhandball", "BMLmovi", "BMLrub", 'EKUT', 'CMU', 'EyesJapanDataset', 'KIT', "PosePrior", 'TCDHands', 'TotalCapture'] + da_mirroring: 0. + da_rotations: 0. + drop_last: False + if_load_mmgt: False + +data_loader_valid: + stride: 30 + augmentation: 0 + shuffle: False + datasets: ['HumanEva', 'HDM05', 'SFU', 'MoSh'] + file_idces: "all" + drop_last: False + if_load_mmgt: False \ No newline at end of file diff --git a/SkeletonDiffusion/configs/config_train/dataset/freeman.yaml b/SkeletonDiffusion/configs/config_train/dataset/freeman.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5480427a5c71e1577388bfd50d1db30fcebdd0b1 --- /dev/null +++ b/SkeletonDiffusion/configs/config_train/dataset/freeman.yaml @@ -0,0 +1,38 @@ +num_joints: 18 #including the hip root joint +fps: 30 + +multimodal_threshold: 0.5 +dataset_type: FreeManDataset +dataset_name: freeman +precomputed_folder: "${dataset_precomputed_path}/FreeMan/${task.task_name}/" +annotations_folder: "${dataset_annotation_path}/FreeMan/${task.task_name}/" +dtype: float32 + +data_loader_train: + stride: 10 + augmentation: 5 + shuffle: True + actions: "all" + da_mirroring: 0.5 + da_rotations: 1.0 + drop_last: True + if_load_mmgt: False + +data_loader_train_eval: + stride: 30 + augmentation: 0 + shuffle: False + actions: "all" + da_mirroring: 0. + da_rotations: 0. + drop_last: False + if_load_mmgt: False + +data_loader_valid: + stride: 30 + augmentation: 0 + shuffle: False + segments_path: "${dataset.annotations_folder}/segments_valid.csv" + actions: "all" + drop_last: False + if_load_mmgt: False diff --git a/SkeletonDiffusion/configs/config_train/dataset/h36m.yaml b/SkeletonDiffusion/configs/config_train/dataset/h36m.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a089024d1406aa04873f49fe174de632421301f0 --- /dev/null +++ b/SkeletonDiffusion/configs/config_train/dataset/h36m.yaml @@ -0,0 +1,40 @@ +num_joints: 17 #including the hip root joint +fps: 50 + +multimodal_threshold: 0.5 +dataset_type: H36MDataset +dataset_name: h36m +precomputed_folder: "${dataset_precomputed_path}/Human36M/${task.task_name}/" +annotations_folder: "${dataset_annotation_path}/Human36M/${task.task_name}" +dtype: float32 +data_loader_train: + stride: 10 + augmentation: 5 + shuffle: True + subjects: ["S1", "S5", "S6", "S7", "S8"] # training on the validation split as well as in BeLFusion, CoMusion + actions: "all" + da_mirroring: 0.5 + da_rotations: 1.0 + drop_last: True + if_load_mmgt: False + +data_loader_train_eval: + stride: 30 + augmentation: 0 + shuffle: False + subjects: ["S1", "S5", "S6", "S7", "S8"] + actions: "all" + da_mirroring: 0. + da_rotations: 0. + drop_last: False + if_load_mmgt: False + +data_loader_valid: + stride: 30 + augmentation: 0 + shuffle: False + subjects: ["S8"] + segments_path: "${dataset.annotations_folder}/segments_valid.csv" + actions: "all" + drop_last: False + if_load_mmgt: False diff --git a/SkeletonDiffusion/configs/config_train/model/autoencoder.yaml b/SkeletonDiffusion/configs/config_train/model/autoencoder.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bdb6e3df746e115bdef2d1c5713cfa6cfdb2a6e1 --- /dev/null +++ b/SkeletonDiffusion/configs/config_train/model/autoencoder.yaml @@ -0,0 +1,57 @@ +batch_size: 64 +batch_size_eval: 512 +eval_frequency: 5 +num_epochs: 200 +num_iteration_eval: 10 +num_workers: 4 +seed: 52345 + +use_lr_scheduler: True +lr_scheduler_kwargs: + lr_scheduler_type: ExponentialLRSchedulerWarmup + warmup_duration: 10 + update_every: 1 + min_lr: 1.e-4 + gamma_decay: 0.98 + + +loss_pose_type: l1 + + +lr: 0.5e-2 + +latent_size: 96 +output_size: 3 #128 + + +z_activation: tanh + +num_iter_perepoch: ${eval:"int(485) if ${eval:"'${dataset.dataset_name}' == 'h36m'"} else 580"} + +obs_length: ${eval:'int(${task.history_sec} * ${dataset.fps})'} +prediction_horizon_train: ${model.prediction_horizon} +prediction_horizon_eval: ${model.prediction_horizon} +prediction_horizon: ${eval:'int(${task.prediction_horizon_sec} * ${dataset.fps})'} +pred_length: ${model.prediction_horizon_eval} + + + +autoenc_arch: + enc_num_layers: 1 + encoder_hidden_size: 96 + decoder_hidden_size: 96 + arch: AutoEncoder + recurrent_arch_enc: StaticGraphGRU + recurrent_arch_decoder: StaticGraphGRU + + + +prediction_horizon_train_min: 10 +prediction_horizon_train_min_from_epoch: 200 +curriculum_it: 10 +random_prediction_horizon: True + + + + + diff --git a/SkeletonDiffusion/configs/config_train/task/hmp.yaml b/SkeletonDiffusion/configs/config_train/task/hmp.yaml new file mode 100644 index 0000000000000000000000000000000000000000..eaf3b33222e30eb8a5c25bd2885fd44b8b2dfacc --- /dev/null +++ b/SkeletonDiffusion/configs/config_train/task/hmp.yaml @@ -0,0 +1,11 @@ +if_consider_hip: False + +history_sec: 0.5 +prediction_horizon_sec: 2 + + +# Joint representation & Skeleton specs +motion_repr_type: "SkeletonRescalePose" +pose_box_size: 1.5 # in meters +seq_centering: 0 +task_name: hmp \ No newline at end of file diff --git a/SkeletonDiffusion/configs/config_train_diffusion/config_diffusion.yaml b/SkeletonDiffusion/configs/config_train_diffusion/config_diffusion.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e4631c3aeaa4b48e9d723eb8ed3d63d69ebfd506 --- /dev/null +++ b/SkeletonDiffusion/configs/config_train_diffusion/config_diffusion.yaml @@ -0,0 +1,25 @@ +if_resume_training: false +debug: false +device: cuda +load: false +load_path: '' +dataset_main_path: ./datasets +dataset_annotation_path: ${dataset_main_path}/annotations&interm +dataset_precomputed_path: ${dataset_main_path}/processed +_load_saved_aoutoenc: hmp-h36m + +output_log_path: ../../my_exps/output/${eval:"'${_load_saved_aoutoenc}'.split('-', 1)[0]"}/${eval:"'${_load_saved_aoutoenc}'.split('-', 1)[1]"}/diffusion/${now:%B%d_%H-%M-%S}_ID${slurm_id}_${info} +slurm_id: 0 +slurm_first_run: None +info: '' +hydra: + run: + dir: ${output_log_path} + job: + chdir: False + +defaults: + - _self_ + - model: skeleton_diffusion + - cov_matrix: adjacency + - override hydra/job_logging: disabled diff --git a/SkeletonDiffusion/configs/config_train_diffusion/cov_matrix/adjacency.yaml b/SkeletonDiffusion/configs/config_train_diffusion/cov_matrix/adjacency.yaml new file mode 100644 index 0000000000000000000000000000000000000000..793dea4d97dc59c26c410bbdf131f7a190c1793d --- /dev/null +++ b/SkeletonDiffusion/configs/config_train_diffusion/cov_matrix/adjacency.yaml @@ -0,0 +1 @@ +covariance_matrix_type: adjacency diff --git a/SkeletonDiffusion/configs/config_train_diffusion/cov_matrix/reachability.yaml b/SkeletonDiffusion/configs/config_train_diffusion/cov_matrix/reachability.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f7bd924d440f02f92c6fb97928a135e3aa15ba0f --- /dev/null +++ b/SkeletonDiffusion/configs/config_train_diffusion/cov_matrix/reachability.yaml @@ -0,0 +1,3 @@ +covariance_matrix_type: reachability +reachability_matrix_degree_factor: 0.5 +reachability_matrix_stop_at: hips # or None 'hips' or null \ No newline at end of file diff --git a/SkeletonDiffusion/configs/config_train_diffusion/model/isotropic_diffusion.yaml b/SkeletonDiffusion/configs/config_train_diffusion/model/isotropic_diffusion.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a665c42f07faba21b3f4f847217d60cedea0ec29 --- /dev/null +++ b/SkeletonDiffusion/configs/config_train_diffusion/model/isotropic_diffusion.yaml @@ -0,0 +1,57 @@ +pretrained_GM_folder: ${eval:"'./models/final_checkpoints/H36M/hmp/autoencoder/January19_19-24-04_ID1137310' if ${eval:"'${_load_saved_aoutoenc}'.split('-')[1] == 'h36m'"} else './models/final_checkpoints/AMASS/hmp/autoencoder/May11_10-35-09_ID1185354'"} +pretrained_autoencoder_path: '${model.pretrained_GM_folder}/checkpoints/checkpoint_final.pt' + +# These options have to still be checked (ablation) +lr: 1.e-3 +diffusion_objective: pred_x0 +weight_decay: 0. + + +if_use_ema: True +step_start_ema: 100 #100 is default +ema_power: ${eval:'2/3'} #${eval:'3/4'} # +ema_update_every: 10 +ema_min_value: 0.0 +use_lr_scheduler: True +lr_scheduler_kwargs: + lr_scheduler_type: ExponentialLRSchedulerWarmup # or SchedulerReduceLROnPlateau + warmup_duration: 200 + update_every: 10 + min_lr: 1.e-4 + gamma_decay: 0.98 + +# THese option are already ablated +diffusion_conditioning: True +num_epochs: 600 +num_workers: 4 +batch_size: 64 +batch_size_eval: 256 # or 256 TO CHECK +eval_frequency: 25 #1000 # in epochs +train_pick_best_sample_among_k: 50 +similarity_space: latent_space # input_space, latent_space or metric_space + +diffusion_activation: identity +num_prob_samples: 50 +diffusion_timesteps: 10 + +diffusion_type: IsotropicGaussianDiffusion +beta_schedule: cosine +diffusion_loss_type: l1 +num_iter_perepoch: null +seed: 63485 + +diffusion_arch: + arch: Denoiser + use_attention: True + self_condition: False + norm_type: none + depth: 1 + # resnet_block_groups = 8, + # learned_variance: False + # learned_sinusoidal_cond: False + # random_fourier_features: False + # learned_sinusoidal_dim: 16 + # sinusoidal_pos_emb_theta: 10000 + attn_dim_head: 32 + attn_heads: 4 + learn_influence: True \ No newline at end of file diff --git a/SkeletonDiffusion/configs/config_train_diffusion/model/isotropic_diffusion_in_noniso_class.yaml b/SkeletonDiffusion/configs/config_train_diffusion/model/isotropic_diffusion_in_noniso_class.yaml new file mode 100644 index 0000000000000000000000000000000000000000..33a9be880dd7d736d62f16697bff878e18b382c0 --- /dev/null +++ b/SkeletonDiffusion/configs/config_train_diffusion/model/isotropic_diffusion_in_noniso_class.yaml @@ -0,0 +1,70 @@ +# pretrained_GM_folder: ./models/final_checkpoints/H36M/hmp/autoencoder/January19_19-24-04_ID1137310 +# _pretrained_GM_checkpoint: checkpoint_final +# pretrained_autoencoder_path: '${model.pretrained_GM_folder}/checkpoints/${model._pretrained_GM_checkpoint}.pt' + +_pretrained_GM_checkpoint: checkpoint_final +pretrained_autoencoder_path: '${model.pretrained_GM_folder}/checkpoints/${model._pretrained_GM_checkpoint}.pt' +pretrained_GM_folder: ${eval:"'./models/final_checkpoints/H36M/hmp/autoencoder/January19_19-24-04_ID1137310' if ${eval:"'${_load_saved_aoutoenc}'.split('-')[1] == 'h36m'"} else './models/final_checkpoints/AMASS/hmp/autoencoder/May11_10-35-09_ID1185354'"} + + +# These options have to still be checked (ablation) +lr: 1.e-3 +diffusion_objective: pred_x0 +weight_decay: 0. + + +if_use_ema: True +step_start_ema: 100 #100 is default +ema_power: ${eval:'2/3'} #${eval:'3/4'} # +ema_update_every: 10 +ema_min_value: 0.0 +use_lr_scheduler: True +lr_scheduler_kwargs: + lr_scheduler_type: ExponentialLRSchedulerWarmup # or SchedulerReduceLROnPlateau + warmup_duration: 200 + update_every: 10 + min_lr: 1.e-4 + gamma_decay: 0.98 + +# THese option are already ablated +diffusion_conditioning: True +num_epochs: 800 +num_workers: 4 +batch_size: 64 +batch_size_eval: 256 +eval_frequency: 25 #1000 # in epochs +train_pick_best_sample_among_k: 50 +similarity_space: latent_space # input_space, latent_space or metric_space + + +diffusion_activation: identity +num_prob_samples: 50 +diffusion_timesteps: 10 + +diffusion_type: NonisotropicGaussianDiffusion +diffusion_loss_type: snr #snr_triangle_inequality,mahalanobis, snr +loss_reduction_type: l1 +if_run_as_isotropic: True +if_sigma_n_scale: True +diffusion_covariance_type: isotropic # anisotropic, isotropic, skeleton-diffusion +gamma_scheduler: cosine # mono_decrease, cosine +beta_schedule: cosine +sigma_n_scale: spectral +num_iter_perepoch: null +seed: 63485 + +diffusion_arch: + arch: Denoiser + use_attention: True + self_condition: False # True holds better results, but it takes longer to train. + norm_type: none + depth: 1 + # resnet_block_groups = 8, + # learned_variance: False + # learned_sinusoidal_cond: False + # random_fourier_features: False + # learned_sinusoidal_dim: 16 + # sinusoidal_pos_emb_theta: 10000 + attn_dim_head: 32 + attn_heads: 4 + learn_influence: True \ No newline at end of file diff --git a/SkeletonDiffusion/configs/config_train_diffusion/model/skeleton_diffusion.yaml b/SkeletonDiffusion/configs/config_train_diffusion/model/skeleton_diffusion.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e4f9d3bb4e6bba727bbc508718e203f1f9c2e9ac --- /dev/null +++ b/SkeletonDiffusion/configs/config_train_diffusion/model/skeleton_diffusion.yaml @@ -0,0 +1,69 @@ +# pretrained_GM_folder: ./models/final_checkpoints/H36M/hmp/autoencoder/January19_19-24-04_ID1137310 +# _pretrained_GM_checkpoint: checkpoint_final +# pretrained_autoencoder_path: '${model.pretrained_GM_folder}/checkpoints/${model._pretrained_GM_checkpoint}.pt' + +_pretrained_GM_checkpoint: checkpoint_final +pretrained_autoencoder_path: '${model.pretrained_GM_folder}/checkpoints/${model._pretrained_GM_checkpoint}.pt' +pretrained_GM_folder: ${eval:"'./models/final_checkpoints/H36M/hmp/autoencoder/January19_19-24-04_ID1137310' if ${eval:"'${_load_saved_aoutoenc}'.split('-')[1] == 'h36m'"} else './models/final_checkpoints/AMASS/hmp/autoencoder/May11_10-35-09_ID1185354'"} + + +# These options have to still be checked (ablation) +lr: 1.e-3 +diffusion_objective: pred_x0 +weight_decay: 0. + + +if_use_ema: True +step_start_ema: 100 #100 is default +ema_power: ${eval:'2/3'} #${eval:'3/4'} # +ema_update_every: 10 +ema_min_value: 0.0 +use_lr_scheduler: True +lr_scheduler_kwargs: + lr_scheduler_type: ExponentialLRSchedulerWarmup # or SchedulerReduceLROnPlateau + warmup_duration: 200 + update_every: 10 + min_lr: 1.e-4 + gamma_decay: 0.98 + +diffusion_conditioning: True +num_epochs: 800 +num_workers: 4 +batch_size: 64 +batch_size_eval: 256 +eval_frequency: 25 #1000 # in epochs +train_pick_best_sample_among_k: 50 +similarity_space: latent_space # input_space, latent_space or metric_space + + +diffusion_activation: identity +num_prob_samples: 50 +diffusion_timesteps: 10 + +diffusion_type: NonisotropicGaussianDiffusion +diffusion_loss_type: snr #snr_triangle_inequality,mahalanobis, snr +loss_reduction_type: l1 +if_run_as_isotropic: False +if_sigma_n_scale: True +diffusion_covariance_type: skeleton-diffusion # anisotropic, isotropic, skeleton-diffusion +gamma_scheduler: cosine # mono_decrease, cosine +beta_schedule: cosine +sigma_n_scale: spectral +num_iter_perepoch: null +seed: 63485 + +diffusion_arch: + arch: Denoiser + use_attention: True + self_condition: False # True holds better results, but it takes longer to train. + norm_type: none + depth: 1 + # resnet_block_groups = 8, + # learned_variance: False + # learned_sinusoidal_cond: False + # random_fourier_features: False + # learned_sinusoidal_dim: 16 + # sinusoidal_pos_emb_theta: 10000 + attn_dim_head: 32 + attn_heads: 4 + learn_influence: True \ No newline at end of file diff --git a/SkeletonDiffusion/datasets b/SkeletonDiffusion/datasets new file mode 100644 index 0000000000000000000000000000000000000000..ec87b0460c6e94cf3b80ae7f5d7aa883f5ba9959 --- /dev/null +++ b/SkeletonDiffusion/datasets @@ -0,0 +1 @@ +../../motion_must_go_on/datasets/ \ No newline at end of file diff --git a/SkeletonDiffusion/environment_inference.yml b/SkeletonDiffusion/environment_inference.yml new file mode 100644 index 0000000000000000000000000000000000000000..4eddc730d6fb157b9d0e1d004785f8155c125cf3 --- /dev/null +++ b/SkeletonDiffusion/environment_inference.yml @@ -0,0 +1,19 @@ +name: skeldiff_inf +channels: + - pytorch + - nvidia +dependencies: + - python=3.10.12 + - pytorch=2.0.1 + - pytorch-cuda=11.8 + - torchvision=0.15.2 + - pyyaml=6.0.1 + - einops=0.7.0 + - pip + - pip: + - denoising-diffusion-pytorch==1.9.4 + # - pyyaml=6.0.1 + # - imageio + # - ipympl=0.9.3 + # - ffmpeg + # - opencv diff --git a/SkeletonDiffusion/inference.ipynb b/SkeletonDiffusion/inference.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..38e7d75b00b11f8355d46914c04bb27764927356 --- /dev/null +++ b/SkeletonDiffusion/inference.ipynb @@ -0,0 +1,343 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "e927d3c2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/storage/user/yaji/yaji/NonisotropicSkeletonDiffusion/SkeletonDiffusion/src\n" + ] + } + ], + "source": [ + "import os\n", + "os.chdir(r\"/home/stud/yaji/storage/user/yaji/NonisotropicSkeletonDiffusion/SkeletonDiffusion/src\") \n", + "root_path = os.getcwd()\n", + "print(root_path)\n", + "\n", + "os.environ[\"CUBLAS_WORKSPACE_CONFIG\"] = \":4096:8\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "32b71ab8", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/stud/yaji/miniconda3/envs/live_demo/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n", + "/storage/user/yaji/yaji/NonisotropicSkeletonDiffusion/SkeletonDiffusion/src/core/diffusion/base.py:184: FutureWarning: `torch.cuda.amp.autocast(args...)` is deprecated. Please use `torch.amp.autocast('cuda', args...)` instead.\n", + " @autocast(enabled = False)\n", + "/storage/user/yaji/yaji/NonisotropicSkeletonDiffusion/SkeletonDiffusion/src/core/diffusion/isotropic.py:72: FutureWarning: `torch.cuda.amp.autocast(args...)` is deprecated. Please use `torch.amp.autocast('cuda', args...)` instead.\n", + " @autocast(enabled = False)\n", + "/storage/user/yaji/yaji/NonisotropicSkeletonDiffusion/SkeletonDiffusion/src/core/diffusion/nonisotropic.py:138: FutureWarning: `torch.cuda.amp.autocast(args...)` is deprecated. Please use `torch.amp.autocast('cuda', args...)` instead.\n", + " @autocast(enabled = False)\n" + ] + } + ], + "source": [ + "from eval_prepare_model import prepare_model, get_prediction, load_model_config_exp\n", + "from data import create_skeleton\n", + "import torch\n", + "import numpy as np\n", + "import random\n", + "\n", + "def set_seed(seed=0):\n", + " torch.use_deterministic_algorithms(True)\n", + " torch.backends.cudnn.deterministic = True\n", + " torch.backends.cudnn.benchmark = False\n", + " np.random.seed(seed)\n", + " random.seed(seed)\n", + " torch.cuda.manual_seed(seed)\n", + " torch.cuda.manual_seed_all(seed)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0963a8bd", + "metadata": {}, + "outputs": [], + "source": [ + "checkpoint_path = '/usr/wiss/curreli/work/my_exps/checkpoints_release/amass/diffusion/cvpr_release/checkpoints/checkpoint_150.pt'\n", + "# checkpoint_path = '/usr/wiss/curreli/work/my_exps/checkpoints_release/amass-mano/diffusion/cvpr_release/checkpoints/checkpoint_150.pt'\n", + "\n", + "\n", + "num_samples = 50" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "c6ce7b0a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "> GPU 0 ready: NVIDIA RTX A2000 12GB\n", + "Loading Autoencoder checkpoint: /usr/wiss/curreli/work/my_exps/checkpoints_release/amass/autoencoder/cvpr_release/checkpoints/checkpoint_300.pt ...\n", + "Diffusion is_ddim_sampling: False\n", + "Loading Diffusion checkpoint: /usr/wiss/curreli/work/my_exps/checkpoints_release/amass/diffusion/cvpr_release/checkpoints/checkpoint_150.pt ...\n" + ] + } + ], + "source": [ + "set_seed(seed=0)\n", + "\n", + "config, exp_folder = load_model_config_exp(checkpoint_path)\n", + "config['checkpoint_path'] = checkpoint_path\n", + "skeleton = create_skeleton(**config) \n", + "\n", + "\n", + "model, device, *_ = prepare_model(config, skeleton, **config)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "5c4aa1a7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "torch.Size([1, 30, 22, 3])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# prepare input\n", + "# load input. It should be in meters\n", + "import numpy as np\n", + "import torch\n", + "obs = np.load('/usr/wiss/curreli/work/my_exps/checkpoints_release/amass/exaple_obs.npy') # (t_past, J, 3)\n", + "# obs = np.load('/usr/wiss/curreli/work/my_exps/checkpoints_release/amass-mano/example_obs.npy') # (t_past, J, 3)\n", + "\n", + "\n", + "obs = torch.from_numpy(obs).to(device)\n", + "obs = obs.unsqueeze(0) # add bacth size\n", + "obs.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "e782b749", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "torch.Size([1, 50, 120, 21, 3])\n", + "torch.Size([1, 30, 21, 3])\n" + ] + }, + { + "data": { + "text/plain": [ + "torch.Size([1, 50, 120, 21, 3])" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "obs_in = skeleton.tranform_to_input_space(obs) # obs sequence contains hip joints, it has not been dropped yet. \n", + "pred = get_prediction(obs_in, model, num_samples=num_samples, **config) # [batch_size, n_samples, seq_length, num_joints, features]\n", + "print(pred.shape)\n", + "pred = skeleton.transform_to_metric_space(pred)\n", + "print(obs_in.shape)\n", + "pred.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d9394774", + "metadata": {}, + "outputs": [], + "source": [ + "kpts3d = pred.cpu()[0][0]\n", + "import matplotlib.pyplot as plt\n", + "for i in range(120):\n", + " plt.figure()\n", + " plt.scatter(kpts3d[0, :, 1], kpts3d[0, :, 2])\n", + " plt.gca().set_aspect('equal')\n", + " plt.savefig(f'../../vis/kpts3d_{i}.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "f91ee849", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "torch.Size([1, 30, 21, 3])\n", + "torch.Size([1, 50, 120, 21, 3])\n", + "torch.Size([1, 30, 20, 3])\n", + "tensor([[0.0123, 0.0127, 0.0128, 0.0128, 0.0131, 0.0131, 0.0137, 0.0144, 0.0148,\n", + " 0.0149, 0.0151, 0.0153, 0.0154, 0.0158, 0.0164, 0.0168, 0.0170, 0.0171,\n", + " 0.0171, 0.0173, 0.0189, 0.0193, 0.0224, 0.0229, 0.0235, 0.0237, 0.0244,\n", + " 0.0248, 0.0261, 0.0269, 0.0270, 0.0271, 0.0274, 0.0275, 0.0280, 0.0282,\n", + " 0.0292, 0.0293, 0.0307, 0.0339, 0.0346, 0.0350, 0.0351, 0.0367, 0.0379,\n", + " 0.0386, 0.0391, 0.0395, 0.0439, 0.0523]], device='cuda:0')\n" + ] + }, + { + "data": { + "text/plain": [ + "tensor([[ 4, 12, 31, 34, 27, 29, 2, 46, 20, 11, 15, 33, 21, 14, 9, 38, 41, 1,\n", + " 22, 35, 19, 43, 16, 48, 5, 47, 25, 40, 8, 28, 39, 45, 17, 23, 37, 18,\n", + " 6, 42, 49, 26, 24, 13, 36, 3, 44, 0, 7, 10, 32, 30]],\n", + " device='cuda:0')" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# rank predictions according to Limb Stretching. We will visualize first the prediction that have lower limb stretching --> more realistic\n", + "from metrics.body_realism import limb_stretching_normed_mean, limb_stretching_normed_rmse\n", + "print(obs_in.shape)\n", + "print(pred.shape)\n", + "print(obs_in[..., 1:, :].shape)\n", + "# limbstretching = limb_stretching_normed_mean(pred, target=obs[..., 1:, :].unsqueeze(1), limbseq=skeleton.get_limbseq(), reduction='persample', obs_as_target=True)\n", + "limbstretching = limb_stretching_normed_rmse(pred, target=obs[..., 1:, :].unsqueeze(1), limbseq=skeleton.get_limbseq(), reduction='persample', obs_as_target=True)\n", + "limbstretching_sorted, indices = torch.sort(limbstretching.squeeze(1), dim=-1, descending=False) \n", + "\n", + "print(limbstretching_sorted)\n", + "indices\n", + "\n", + "# TO DO: index predictions with these indices.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "1a9a941a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Observation shape: torch.Size([1, 30, 21, 3])\n", + "Prediction shape: torch.Size([1, 50, 120, 22, 3])\n", + "tensor([[0.0446, 0.0711, 0.0517, 0.1149, 0.0689, 0.0238, 0.0374, 0.0329, 0.0411,\n", + " 0.0573, 0.0565, 0.0855, 0.0375, 0.1141, 0.0402, 0.0385, 0.0564, 0.0727,\n", + " 0.0904, 0.0620, 0.0374, 0.0363, 0.0443, 0.0386, 0.0702, 0.0413, 0.0455,\n", + " 0.0468, 0.1038, 0.0691, 0.0630, 0.0320, 0.0489, 0.0422, 0.0520, 0.0756,\n", + " 0.0444, 0.0414, 0.0852, 0.0673, 0.0391, 0.0500, 0.0484, 0.0457, 0.0556,\n", + " 0.0393, 0.0674, 0.0349, 0.0392, 0.0459]], device='cuda:0')\n" + ] + } + ], + "source": [ + "# read pred and obs from predictions/joints3d.npy\n", + "frames_for_half_second = 30\n", + "# Load the joints3d data from the saved numpy file\n", + "joints3d = np.load('/home/stud/yaji/storage/user/yaji/NonisotropicSkeletonDiffusion/predictions/joints3d.npy')\n", + "\n", + "# Split the data into observation and prediction parts\n", + "# The first frames_for_half_second frames are observations\n", + "obs = joints3d[:, 0, :frames_for_half_second, :, :] # [1, num_samples, frames_for_half_second, 22, 3]\n", + "pred = joints3d[:, :, frames_for_half_second:, :, :] # [1, num_samples, pred_length, 22, 3]\n", + "\n", + "# Convert to torch tensors and move to device\n", + "obs = torch.from_numpy(obs).to(device)\n", + "pred = torch.from_numpy(pred).to(device)\n", + "\n", + "print(\"Observation shape:\", obs[0, ..., 1:, :].unsqueeze(0).shape)\n", + "print(\"Prediction shape:\", pred.shape)\n", + "\n", + "# calculate \n", + "limbstretching = limb_stretching_normed_rmse(pred[..., 1:, :], target=obs[0, ..., 1:, :].unsqueeze(0), limbseq=skeleton.get_limbseq(), reduction='persample', obs_as_target=True)\n", + "limbstretching_sorted, indices = torch.sort(limbstretching.squeeze(1), dim=-1, descending=False) \n", + "print(limbstretching)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "e51ccbee", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "torch.Size([1, 120, 21, 3])\n", + "torch.Size([50, 120, 21, 3])\n", + "torch.Size([120, 21, 3])\n", + "torch.Size([10, 120, 21, 3])\n", + "[8, 18, 36, 30, 37, 43, 26, 17, 41, 6]\n" + ] + } + ], + "source": [ + "from metrics.ranking import get_closest_and_nfurthest_maxapd\n", + "# If you see problems with the visualizations, you can remove predictions that have limb stretching > 0.04\n", + "# limbstretching = limb_stretching_normed_mean(pred, target=obs[..., 1:, :], limbseq=skeleton.get_limbseq(), reduction='persample', obs_as_target=True)\n", + "# remove batch dimension\n", + "y_pred = pred.squeeze(0) # [n_samples, seq_length, num_joints, features]\n", + "#if GT is not there, we use the first sample as GT reference i.e. the most likely closest to GT\n", + "y_gt = y_pred[0].unsqueeze(0) # [seq_length, num_joints, features]\n", + "print(y_gt.shape)\n", + "print(y_pred.shape)\n", + "pred_closest, sorted_preds, sorted_preds_idxs = get_closest_and_nfurthest_maxapd(y_pred, y_gt, nsamples=10)\n", + "\n", + "print(pred_closest.shape)\n", + "print(sorted_preds.shape)\n", + "print(sorted_preds_idxs)\n", + "\n", + "\n", + "\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "live_demo", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/SkeletonDiffusion/inference_filtered.ipynb b/SkeletonDiffusion/inference_filtered.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..0519ecba6ea913e21689ec692e81e9e4973fbf73 --- /dev/null +++ b/SkeletonDiffusion/inference_filtered.ipynb @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/SkeletonDiffusion/setup.py b/SkeletonDiffusion/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..9924fedd0f6dced185031d96642cde6377cfc3d6 --- /dev/null +++ b/SkeletonDiffusion/setup.py @@ -0,0 +1,13 @@ +from setuptools import setup, find_packages + +setup( + name="SkeletonDiffusion", + version="0.1.0", + package_dir={"": "src"}, + packages=find_packages(where="src"), + install_requires=[ + "torch", + "numpy", + ], + python_requires=">=3.8", +) \ No newline at end of file diff --git a/SkeletonDiffusion/src/__init__.py b/SkeletonDiffusion/src/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..5b3153955dedcdea5695506f660eb13d3f9b3a7d --- /dev/null +++ b/SkeletonDiffusion/src/__init__.py @@ -0,0 +1,7 @@ +import os +import sys + +# Add the src directory to the Python path +src_path = os.path.dirname(os.path.abspath(__file__)) +if src_path not in sys.path: + sys.path.insert(0, src_path) diff --git a/SkeletonDiffusion/src/config_utils.py b/SkeletonDiffusion/src/config_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..5b4f93b5c5dd5d817457cfe3d17fed943023b599 --- /dev/null +++ b/SkeletonDiffusion/src/config_utils.py @@ -0,0 +1,62 @@ +import torch +from torch.utils.data import DataLoader +from ignite.handlers import Checkpoint +import os + +from SkeletonDiffusion.src.utils.config import init_obj +from SkeletonDiffusion.src.utils.reproducibility import seed_worker, seed_eval_worker, RandomStateDict +import SkeletonDiffusion.src.data.loaders as dataset_type + +from SkeletonDiffusion.src.utils.load import get_latest_model_path +from SkeletonDiffusion.src.inference_utils import create_model + + + +def create_train_dataloaders(batch_size, batch_size_eval, num_workers, skeleton, if_run_validation=True, if_resume_training=False, **config): + + random_state_manager = RandomStateDict() + if if_resume_training: + checkpoint = torch.load(config['load_path']) + Checkpoint.load_objects(to_load={"random_states": random_state_manager}, checkpoint=checkpoint) + dataset_train = init_obj(config, 'dataset_type', dataset_type, split="train", skeleton=skeleton, **(config['data_loader_train'])) + data_loader_train = DataLoader(dataset_train, batch_size=batch_size, shuffle=True, worker_init_fn = seed_worker, pin_memory= True, + num_workers=num_workers, generator=random_state_manager.generator) + + if if_run_validation: + dataset_eval = init_obj(config, 'dataset_type', dataset_type, split="valid", skeleton=skeleton, **(config['data_loader_valid'])) + dataset_eval_train = init_obj(config, 'dataset_type', dataset_type, split="train", skeleton=skeleton, **(config['data_loader_train_eval'])) + data_loader_eval = DataLoader(dataset_eval, shuffle=False, worker_init_fn=seed_eval_worker, batch_size=batch_size_eval, num_workers=1, pin_memory= True) + data_loader_train_eval = DataLoader(dataset_eval_train, shuffle=False, worker_init_fn=seed_eval_worker, batch_size=batch_size_eval, num_workers=1, pin_memory= True) + else: + data_loader_eval = None + data_loader_train_eval = None + return data_loader_train, data_loader_eval, data_loader_train_eval, random_state_manager + + +def flat_hydra_config(cfg): + """ + Flatten the main dict categories of the Hydra config object into a single one. + """ + for subconf in ['model', 'task', 'dataset', 'autoenc_arch', 'cov_matrix']: + if subconf in cfg: + cfg = {**cfg, **cfg[subconf]} + cfg.pop(subconf) + return cfg + +def resume_training(cfg): + #output folder has been already created. + assert 'output_log_path' in cfg + + # decide whether to start from scratch (default if no checkpoints), from latest save (if checkpoints exists), or from given path (if load_path is given) + + assert len(os.listdir(os.path.join(cfg['output_log_path'], 'checkpoints'))) != 0, "Checkpoints folder is empty. Please provide a valid path to load from." + + if len(cfg['load_path']) == 0: + # load latest model + cfg['load_path'] = get_latest_model_path(os.path.join(cfg['output_log_path'], 'checkpoints')) + print("Loading latest epoch: ", cfg['load_path'].split('/')[-1]) + else: + output_path = os.path.dirname(os.path.dirname(cfg['load_path'])) + assert cfg['output_log_path'] == output_path + cfg['output_log_path'] = output_path + return cfg diff --git a/SkeletonDiffusion/src/core/__init__.py b/SkeletonDiffusion/src/core/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce8e8599991765e7a367d3ef3eceb707cac4af9 --- /dev/null +++ b/SkeletonDiffusion/src/core/__init__.py @@ -0,0 +1,8 @@ +# Import network first +from .network import AutoEncoder, Denoiser + +# Then import diffusion manager +from .diffusion_manager import DiffusionManager + +# Export all +__all__ = ['AutoEncoder', 'Denoiser', 'DiffusionManager'] \ No newline at end of file diff --git a/SkeletonDiffusion/src/core/diffusion/__init__.py b/SkeletonDiffusion/src/core/diffusion/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..73b88516693dd9492c2d2ec35f7c8ec5dad09c9d --- /dev/null +++ b/SkeletonDiffusion/src/core/diffusion/__init__.py @@ -0,0 +1,3 @@ +from SkeletonDiffusion.src.core.diffusion.isotropic import IsotropicGaussianDiffusion +from SkeletonDiffusion.src.core.diffusion.nonisotropic import NonisotropicGaussianDiffusion +from SkeletonDiffusion.src.core.diffusion.utils import get_cov_from_corr \ No newline at end of file diff --git a/SkeletonDiffusion/src/core/diffusion/base.py b/SkeletonDiffusion/src/core/diffusion/base.py new file mode 100644 index 0000000000000000000000000000000000000000..28904a09da2c6a7355b440779a7e87902c0ab0bc --- /dev/null +++ b/SkeletonDiffusion/src/core/diffusion/base.py @@ -0,0 +1,445 @@ +import math +from random import random +from functools import partial +from collections import namedtuple +from typing import Tuple, Optional, List, Union, Dict + +import torch +from torch import nn +import torch.nn.functional as F +from torch.cuda.amp import autocast + +from einops import reduce + + +from tqdm.auto import tqdm + + +# constants +ModelPrediction = namedtuple('ModelPrediction', ['pred_noise', 'pred_x_start']) + +# helper functions + +def identity(t, *args, **kwargs): + return t + +def exists(x): + return x is not None + +def default(val, d): + if exists(val): + return val + return d() if callable(d) else d + +def extract(a, t, x_shape): + b, *_ = t.shape + out = a.gather(-1, t) + return out.reshape(b, *((1,) * (len(x_shape) - 1))) + +def linear_beta_schedule(timesteps): + scale = 1000 / timesteps + beta_start = scale * 0.0001 + beta_end = scale * 0.02 + return torch.linspace(beta_start, beta_end, timesteps, dtype = torch.float64) + +def cosine_beta_schedule(timesteps, s = 0.008): + """ + cosine schedule + as proposed in https://openreview.net/forum?id=-NEXDKk8gZ + """ + steps = timesteps + 1 + x = torch.linspace(0, timesteps, steps, dtype = torch.float64) + alphas_cumprod = torch.cos(((x / timesteps) + s) / (1 + s) * math.pi * 0.5) ** 2 + alphas_cumprod = alphas_cumprod / alphas_cumprod[0] + betas = 1 - (alphas_cumprod[1:] / alphas_cumprod[:-1]) + return torch.clip(betas, 0, 0.999) + +def exp_beta_schedule(timesteps, factor=3.0): + steps = timesteps + 1 + x = torch.linspace(-factor, 0, steps, dtype = torch.float64)#/timesteps + betas = torch.exp(x) + return torch.clip(betas, 0, 0.999) + + +class LatentDiffusion(nn.Module): + def __init__(self, + model:torch.nn.Module, latent_size=96, diffusion_timesteps=10, diffusion_objective="pred_x0", sampling_timesteps=None, diffusion_activation='identity', + silent=True, diffusion_conditioning=False, diffusion_loss_type='mse', + objective = 'pred_noise', + beta_schedule = 'cosine', + beta_schedule_factor=3.0, + ddim_sampling_eta = 0., + **kwargs + ): + + super().__init__() + + + if diffusion_activation == "tanh": + self.activation = torch.nn.Tanh() + elif diffusion_activation == "identity": + self.activation = torch.nn.Identity() + self.silent = silent + self.condition = diffusion_conditioning + self.loss_type = diffusion_loss_type + + self.statistics_pred = None + self.statistics_obs = None + + + timesteps=diffusion_timesteps + objective=diffusion_objective + + + self.model = model + self.channels = self.model.channels + self.self_condition = self.model.self_condition + + self.seq_length = latent_size + self.objective = objective + + assert objective in {'pred_noise', 'pred_x0', 'pred_v'}, 'objective must be either pred_noise (predict noise) or pred_x0 (predict image start) or pred_v (predict v [v-parameterization as defined in appendix D of progressive distillation paper, used in imagen-video successfully])' + + if beta_schedule == 'linear': + betas = linear_beta_schedule(timesteps) + elif beta_schedule == 'cosine': + betas = cosine_beta_schedule(timesteps) + elif beta_schedule == 'exp': + betas = exp_beta_schedule(timesteps, beta_schedule_factor) + else: + raise ValueError(f'unknown beta schedule {beta_schedule}') + + alphas = 1. - betas + alphas_cumprod = torch.cumprod(alphas, dim=0) + alphas_cumprod_prev = F.pad(alphas_cumprod[:-1], (1, 0), value = 1.) + + timesteps, = betas.shape + self.num_timesteps = int(timesteps) + + # sampling related parameters + + self.sampling_timesteps = default(sampling_timesteps, timesteps) # default num sampling timesteps to number of timesteps at training + + assert self.sampling_timesteps <= timesteps + self.is_ddim_sampling = self.sampling_timesteps < timesteps + self.ddim_sampling_eta = ddim_sampling_eta + + # helper function to register buffer from float64 to float32 + + register_buffer = lambda name, val: self.register_buffer(name, val.to(torch.float32)) + + register_buffer('betas', betas) + register_buffer('alphas_cumprod', alphas_cumprod) + register_buffer('alphas_cumprod_prev', alphas_cumprod_prev) + register_buffer('sqrt_alphas_cumprod', torch.sqrt(alphas_cumprod)) + + print("Diffusion is_ddim_sampling: ", self.is_ddim_sampling) + + + + def set_normalization_statistics(self, statistics_pred, statistics_obs): + self.statistics_pred = statistics_pred + self.statistics_obs = statistics_obs + print("Setting normalization statistics for diffusion") + + def get_white_noise(self, x, *args, **kwargs): + return self.get_noise(x, *args, **kwargs) + + def get_start_noise(self, x, *args, **kwargs): + return self.get_white_noise(x, *args, **kwargs) + + def get_noise(self, x, *args, **kwargs): + """ + x is either tensor or shape + """ + if torch.is_tensor(x): + return torch.randn_like(x) + elif isinstance(x, tuple): + return torch.randn(*x, *args, **kwargs) + + ####################################################################### + # TO SUBCLASS + ####################################################################### + + def predict_start_from_noise(self, x_t, t, noise): + assert 0, "Not implemented" + ... + return x_t + + def predict_noise_from_start(self, x_t, t, x0): + assert 0, "Not implemented" + ... + return x_t + + def predict_v(self, x_start, t, noise): + assert 0, "Not implemented" + ... + return x_start + + def predict_start_from_v(self, x_t, t, v): + assert 0, "Not implemented" + ... + return x_t + + @autocast(enabled = False) + def q_sample(self, x_start, t, noise=None): + assert 0, "Not implemented" + ... + return x_start + + def q_posterior(self, x_start, x_t, t): + assert 0, "Not implemented" + ... + return posterior_mean, posterior_variance, posterior_log_variance_clipped + + def p_combine_mean_var_noise(self, model_mean, model_log_variance, noise): + assert 0, "Not implemented" + ... + return model_mean + + def p_interpolate_mean_var_noise(self, model_mean, model_log_variance, noise, node_idx:Optional[int] = None, interpolate_factor=0.0, noise2interpolate=None, **kwargs): + assert 0, "Not implemented" + ... + return model_mean + + def loss_funct(self, model_out, target, *args, **kwargs): + if self.loss_type == "mse": + loss = F.mse_loss(model_out, target, reduction = 'none') + elif self.loss_type == 'l1': + loss = F.l1_loss(model_out, target, reduction = 'none') + else: + assert 0, "Not implemented" + return loss + + ######################################################################## + # NETWORK INTERFACE + ######################################################################### + + + def model_predictions(self, x, t, x_self_cond = None, x_cond=None, clip_x_start = False, rederive_pred_noise = False): + model_output = self.feed_model(x, t, x_self_cond=x_self_cond, x_cond=x_cond) + maybe_clip = partial(torch.clamp, min = -1., max = 1.) if clip_x_start else identity + + if self.objective == 'pred_noise': + pred_noise = model_output + x_start = self.predict_start_from_noise(x, t, pred_noise) + x_start = maybe_clip(x_start) + + if clip_x_start and rederive_pred_noise: + pred_noise = self.predict_noise_from_start(x, t, x_start) + + elif self.objective == 'pred_x0': + x_start = model_output + x_start = maybe_clip(x_start) + pred_noise = self.predict_noise_from_start(x, t, x_start) + + elif self.objective == 'pred_v': + v = model_output + x_start = self.predict_start_from_v(x, t, v) + x_start = maybe_clip(x_start) + pred_noise = self.predict_noise_from_start(x, t, x_start) + return ModelPrediction(pred_noise, x_start) + + def feed_model(self, x, t, x_self_cond = None, x_cond=None): + if self.condition: + assert x_cond is not None + if x.shape[0] > x_cond.shape[0]: + # training with multiple samples + x_cond = x_cond.repeat_interleave( int(x.shape[0]/x_cond.shape[0]), 0) + model_in = x + else: + model_in = x + + model_output = self.model(model_in, t, x_self_cond, x_cond) + model_output = self.activation(model_output) + return model_output + + ######################################################################## + # FORWARD PROCESS + ######################################################################### + + + def p_losses(self, x_start, t, noise = None, x_cond=None, n_train_samples=1): + b, c, n = x_start.shape + if n_train_samples > 1: + x_start = x_start.repeat_interleave(n_train_samples, dim=0) + t = t.repeat_interleave(n_train_samples, dim=0) + if x_cond is not None: + x_cond = x_cond.repeat_interleave(n_train_samples, dim=0) + noise = default(noise, self.get_white_noise(x_start, t)) # noise for timesteps t + + # noise sample + + x = self.q_sample(x_start = x_start, t = t, noise = noise) + + # if doing self-conditioning, 50% of the time, predict x_start from current set of times + # and condition with unet with that + # this technique will slow down training by 25%, but seems to lower FID significantly + + x_self_cond = None + if self.self_condition and random.random() < 0.5: + with torch.no_grad(): + x_self_cond = self.model_predictions(x, t, x_cond=x_cond).pred_x_start + x_self_cond.detach_() + + # predict and take gradient step + model_out = self.feed_model(x, t, x_self_cond=x_self_cond, x_cond=x_cond) + + if self.objective == 'pred_noise': + target = noise + elif self.objective == 'pred_x0': + target = x_start + elif self.objective == 'pred_v': + v = self.predict_v(x_start, t, noise) + target = v + else: + raise ValueError(f'unknown objective {self.objective}') + loss = self.loss_funct(model_out, target, t) + loss = reduce(loss, 'b ... -> b', 'mean') # [batch*n_train_samples, Nodes, latent_dim] -> [batch*n_train_samples] + + return loss, extract(self.loss_weight, t.view(b, -1)[:, 0], loss.shape[0:1]), model_out + + def forward(self, x, *args, x_cond=None, **kwargs): + b, c, n, device, seq_length, = *x.shape, x.device, self.seq_length + assert n == seq_length, f'seq length must be {seq_length}' + t = torch.randint(0, self.num_timesteps, (b,), device=device).long() + + return self.p_losses(x, t, *args, x_cond=x_cond, **kwargs) + + + ######################################################################## + # REVERSE PROCESS + ######################################################################### + + def p_mean_variance(self, x, t, x_self_cond = None, x_cond=None, clip_denoised = True): + preds = self.model_predictions(x, t, x_self_cond, x_cond=x_cond) + x_start = preds.pred_x_start + + if clip_denoised: + x_start.clamp_(-1., 1.) + + model_mean, posterior_variance, posterior_log_variance = self.q_posterior(x_start = x_start, x_t = x, t = t) + return model_mean, posterior_variance, posterior_log_variance, x_start + + @torch.no_grad() + def p_sample(self, x, t: int, x_self_cond = None, clip_denoised = True, sampling_noise=None, *args, if_interpolate=False, noise2interpolate=None, interpolation_kwargs:Dict=None, **kwargs): + b, *_, device = *x.shape, x.device + batched_times = torch.full((b,), t, device = x.device, dtype = torch.long) + model_mean, _, model_log_variance, x_start = self.p_mean_variance(x = x, t = batched_times, x_self_cond = x_self_cond, clip_denoised = clip_denoised, *args, **kwargs) + + if sampling_noise is not None and t > 0: + noise = sampling_noise[:, sampling_noise.shape[1]-t] + else: + noise = self.get_white_noise(x) if t > 0 else 0. # no noise if t == 0 + + if if_interpolate and t > 0: + noise2 = noise2interpolate[:, sampling_noise.shape[1]-t] + assert noise2.shape == noise.shape + pred_img = self.p_interpolate_mean_var_noise(model_mean, model_log_variance, noise, noise2, **interpolation_kwargs) + else: + pred_img = self.p_combine_mean_var_noise(model_mean, model_log_variance, noise) + return pred_img, x_start, noise, model_mean + + @torch.no_grad() + def p_sample_loop(self, shape, x_cond=None, start_noise=None, sampling_noise=None, return_sampling_noise=False, return_timages=False, **kwargs): + batch, device = shape[0], self.betas.device + if start_noise is not None: + assert start_noise.shape == shape, f"Shape mismatch: {start_noise.shape} != {shape}" + img = start_noise + noise = start_noise.clone() + else: + img = self.get_start_noise(shape, device=device) + noise = img.clone() + + if sampling_noise is not None: + assert sampling_noise.shape[2:] == shape[1:], f"Shape mismatch: {start_noise.shape} != {shape}" + assert sampling_noise.shape[0] == shape[0], f"Shape mismatch: {start_noise.shape} != {shape}" + assert sampling_noise.shape[1] == self.num_timesteps - 1 + + x_start = None + imgs = [] + noise_t = [] + mean_t = [] + if not self.silent: + print(f"Evaluation with {len(range(0, self.num_timesteps))} diffusion steps") + for t in reversed(range(0, self.num_timesteps)): #, desc = 'sampling loop time step', total = self.num_timesteps): + self_cond = x_start if self.self_condition else None + img, x_start, nt, model_mean = self.p_sample(img, t, self_cond, x_cond=x_cond, sampling_noise=sampling_noise, **kwargs) + if return_sampling_noise and t!=0: + noise_t.append(nt) + mean_t.append(model_mean) + if return_timages and t!=0: + imgs.append(img) + + + if return_sampling_noise: + noise_t = torch.stack(noise_t, dim=1) + mean_t = torch.stack(mean_t, dim=1) + if return_timages: + print("Returning timages") + imgs = torch.stack(imgs, dim=1) + + if return_sampling_noise: + if return_timages: + noise = (noise, noise_t, imgs) + else: + noise = (noise, noise_t, mean_t) + else: + if return_timages: + noise = (noise, imgs) + return img, noise + + @torch.no_grad() + def ddim_sample(self, shape, clip_denoised = True, x_cond=None, start_noise=None): + batch, device, total_timesteps, sampling_timesteps, eta, objective = shape[0], self.betas.device, self.num_timesteps, self.sampling_timesteps, self.ddim_sampling_eta, self.objective + + times = list(reversed(times.int().tolist())) + time_pairs = list(zip(times[:-1], times[1:])) # [(T-1, T-2), (T-2, T-3), ..., (1, 0), (0, -1)] + + if start_noise is not None: + assert start_noise.shape == shape + img = start_noise + noise = start_noise.clone() + else: + img = torch.randn(shape, device=device) + noise = img.clone() + + imgs = [] + + x_start = None + if not self.silent: + print(f"Evaluation with {len(time_pairs)} diffusion steps") + for time, time_next in tqdm(time_pairs, desc = 'sampling loop time step'): + time_cond = torch.full((batch,), time, device=device, dtype=torch.long) + self_cond = x_start if self.self_condition else None + pred_noise, x_start, *_ = self.model_predictions(img, time_cond, self_cond, x_cond=x_cond, clip_x_start = clip_denoised) + + if time_next < 0: + img = x_start + # imgs.append(img) + + alpha = self.alphas_cumprod[time] + alpha_next = self.alphas_cumprod[time_next] + sqrt_alpha_next = self.sqrt_alphas_cumprod[time_next] + + sigma = eta * ((1 - alpha / alpha_next) * (1 - alpha_next) / (1 - alpha)).sqrt() #eta*beta_t_tilde + c = (1 - alpha_next - sigma ** 2).sqrt() + + noise = torch.randn_like(img) + + img = x_start * sqrt_alpha_next + \ + c * pred_noise + \ + sigma * noise + # imgs.append(img) + + # imgs = torch.stack(imgs, dim=1) + return img, noise + + + @torch.no_grad() + def sample(self, batch_size = 16, *args, **kwargs): + seq_length, channels = self.seq_length, self.channels + sample_fn = self.p_sample_loop if not self.is_ddim_sampling else self.ddim_sample + return sample_fn((batch_size, channels, seq_length),*args, **kwargs) + + diff --git a/SkeletonDiffusion/src/core/diffusion/isotropic.py b/SkeletonDiffusion/src/core/diffusion/isotropic.py new file mode 100644 index 0000000000000000000000000000000000000000..1e5f0af7b1756cae40ab187ed4a0e680deb460c1 --- /dev/null +++ b/SkeletonDiffusion/src/core/diffusion/isotropic.py @@ -0,0 +1,104 @@ +import torch +from torch.cuda.amp import autocast + +from SkeletonDiffusion.src.core.diffusion.base import LatentDiffusion, extract, default + +class IsotropicGaussianDiffusion(LatentDiffusion): + def __init__(self, **kwargs): + super().__init__( **kwargs) + register_buffer = lambda name, val: self.register_buffer(name, val.to(torch.float32)) + + # calculations for diffusion q(x_t | x_{t-1}) and others + + register_buffer('sqrt_one_minus_alphas_cumprod', torch.sqrt(1. - self.alphas_cumprod)) + register_buffer('log_one_minus_alphas_cumprod', torch.log(1. - self.alphas_cumprod)) + register_buffer('sqrt_recip_alphas_cumprod', torch.sqrt(1. / self.alphas_cumprod)) + register_buffer('sqrt_recipm1_alphas_cumprod', torch.sqrt(1. / self.alphas_cumprod - 1)) + # calculations for posterior q(x_{t-1} | x_t, x_0) + + posterior_variance = self.betas * (1. - self.alphas_cumprod_prev) / (1. - self.alphas_cumprod) + alphas = 1. - self.betas + + # above: equal to 1. / (1. / (1. - alpha_cumprod_tm1) + alpha_t / beta_t) + + register_buffer('posterior_variance', posterior_variance) + + # below: log calculation clipped because the posterior variance is 0 at the beginning of the diffusion chain + + register_buffer('posterior_log_variance_clipped', torch.log(posterior_variance.clamp(min =1e-20))) + register_buffer('posterior_mean_coef1', self.betas * torch.sqrt(self.alphas_cumprod_prev) / (1. - self.alphas_cumprod)) + register_buffer('posterior_mean_coef2', (1. - self.alphas_cumprod_prev) * torch.sqrt(alphas) / (1. - self.alphas_cumprod)) + + # calculate loss weight + snr = self.alphas_cumprod / (1 - self.alphas_cumprod) + + if self.objective == 'pred_noise': + loss_weight = torch.ones_like(snr) + elif self.objective == 'pred_x0': + loss_weight = snr + elif self.objective == 'pred_v': + loss_weight = snr / (snr + 1) + + register_buffer('loss_weight', loss_weight) + + ######################################################################## + # FORWARD PROCESS + ######################################################################### + + def predict_start_from_noise(self, x_t, t, noise): + return ( + extract(self.sqrt_recip_alphas_cumprod, t, x_t.shape) * x_t - + extract(self.sqrt_recipm1_alphas_cumprod, t, x_t.shape) * noise + ) + + def predict_noise_from_start(self, x_t, t, x0): + return ( + (extract(self.sqrt_recip_alphas_cumprod, t, x_t.shape) * x_t - x0) / \ + extract(self.sqrt_recipm1_alphas_cumprod, t, x_t.shape) + ) + + def predict_v(self, x_start, t, noise): + return ( + extract(self.sqrt_alphas_cumprod, t, x_start.shape) * noise - + extract(self.sqrt_one_minus_alphas_cumprod, t, x_start.shape) * x_start + ) + + def predict_start_from_v(self, x_t, t, v): + return ( + extract(self.sqrt_alphas_cumprod, t, x_t.shape) * x_t - + extract(self.sqrt_one_minus_alphas_cumprod, t, x_t.shape) * v + ) + + @autocast(enabled = False) + def q_sample(self, x_start, t, noise=None): + noise = default(noise, lambda: self.get_white_noise(x_start)) + + return ( + extract(self.sqrt_alphas_cumprod, t, x_start.shape) * x_start + + extract(self.sqrt_one_minus_alphas_cumprod, t, x_start.shape) * noise + ) + + ######################################################################## + # REVERSE PROCESS + ######################################################################### + + def q_posterior(self, x_start, x_t, t): + posterior_mean = ( + extract(self.posterior_mean_coef1, t, x_t.shape) * x_start + + extract(self.posterior_mean_coef2, t, x_t.shape) * x_t + ) + posterior_variance = extract(self.posterior_variance, t, x_t.shape) + posterior_log_variance_clipped = extract(self.posterior_log_variance_clipped, t, x_t.shape) + return posterior_mean, posterior_variance, posterior_log_variance_clipped + + def p_combine_mean_var_noise(self, model_mean, model_log_variance, noise): + return model_mean + (0.5 * model_log_variance).exp() * noise + + def interpolate_noise(self, noise1, noise2, interpolate_funct=None, **kwargs): + interpolated_noise = interpolate_funct(noise1, noise2) + return interpolated_noise + + def p_interpolate_mean_var_noise(self, model_mean, model_log_variance, noise, noise2interpolate=None, **kwargs): + interpolated_noise = self.interpolate_noise(noise, noise2interpolate,**kwargs) + return model_mean + (0.5 * model_log_variance).exp() * interpolated_noise + diff --git a/SkeletonDiffusion/src/core/diffusion/nonisotropic.py b/SkeletonDiffusion/src/core/diffusion/nonisotropic.py new file mode 100644 index 0000000000000000000000000000000000000000..977a56302cc35e02f03033700115a5a52289d6b5 --- /dev/null +++ b/SkeletonDiffusion/src/core/diffusion/nonisotropic.py @@ -0,0 +1,213 @@ +import torch +from torch.cuda.amp import autocast +from .base import LatentDiffusion, extract, default + +def extract_matrix(matrix, t, x_shape): + b, *_ = t.shape + T, N, *_ = matrix.shape + out = torch.index_select(matrix, 0, t) + out = out.reshape(b, *out.shape[1:]) + while len(x_shape) > len(out.shape): + out = out.unsqueeze(-1) + return out + +def verify_noise_scale(diffusion): + N, *_ = diffusion.Lambda_N.shape + alphas = 1 - diffusion.betas + noise = diffusion.get_noise((2000, diffusion.num_timesteps, N)) + zeta_noise = torch.sqrt(diffusion.Lambda_t.unsqueeze(0)) * noise + print("current: ", (zeta_noise**2).sum(-1).mean(0)) + print("original standard gaussian diffusion: ",(1-alphas) * zeta_noise.shape[-1]) + +def compute_covariance_matrices(diffusion: torch.nn.Module, Lambda_N: torch.Tensor, diffusion_covariance_type='ani-isotropic', gamma_scheduler = 'cosine'): + N, *_ = Lambda_N.shape + alphas = 1. - diffusion.betas + def _alpha_sumprod(alphas, t): + return torch.sum(torch.cumprod(torch.flip(alphas[:t+1], [0]), dim=0)) + alphas_sumprod = torch.stack([_alpha_sumprod(alphas, t) for t in range(len(alphas))], dim=0) + diffusion.alphas_sumprod = alphas_sumprod + if diffusion_covariance_type == 'isotropic': + assert (Lambda_N == 0).all() + Lambda_t = (1-alphas).unsqueeze(-1) # (Tdiff, N) + Lambda_bar_t = (1-diffusion.alphas_cumprod.unsqueeze(-1)) + Lambda_bar_t_prev = torch.cat([torch.zeros(1).unsqueeze(0), Lambda_bar_t[:-1]], dim=0) + elif diffusion_covariance_type == 'anisotropic': + Lambda_t = (1-alphas.unsqueeze(-1))*Lambda_N # (Tdiff, N) + Lambda_bar_t = (1-diffusion.alphas_cumprod.unsqueeze(-1))*Lambda_N + Lambda_bar_t_prev = (1-diffusion.alphas_cumprod_prev.unsqueeze(-1))*Lambda_N + elif diffusion_covariance_type == 'skeleton-diffusion': + if gamma_scheduler== 'cosine': + gammas = 1 - alphas + elif gamma_scheduler == 'mono_decrease': + gammas = 1 - torch.arange(0, diffusion.num_timesteps)/diffusion.num_timesteps + else: + assert 0, "Not implemented" + Lambda_I = Lambda_N - 1 + gammas_bar = (1-alphas)*gammas + gammas_tilde = diffusion.alphas_cumprod*torch.cumsum(gammas_bar/diffusion.alphas_cumprod, dim=-1) + Lambda_t = Lambda_I.unsqueeze(0)*gammas_bar.unsqueeze(-1) + (1-alphas).unsqueeze(-1) # (Tdiff, N) + Lambda_bar_t = Lambda_I.unsqueeze(0)*gammas_tilde.unsqueeze(-1) + (1-diffusion.alphas_cumprod.unsqueeze(-1)) + Lambda_bar_t_prev = torch.cat([torch.zeros(N).unsqueeze(0), Lambda_bar_t[:-1]], dim=0) # we start from det so it must be zero for t=-1 + else: + assert 0, "Not implemented" + + return Lambda_t, Lambda_bar_t, Lambda_bar_t_prev + + +class NonisotropicGaussianDiffusion(LatentDiffusion): + def __init__(self, Sigma_N: torch.Tensor, Lambda_N: torch.Tensor, U: torch.Tensor, diffusion_covariance_type='skeleton-diffusion', loss_reduction_type='l1', gamma_scheduler = 'cosine', **kwargs): + super().__init__( **kwargs) + alphas = 1. - self.betas + + + N, _ = Sigma_N.shape + register_buffer = lambda name, val: self.register_buffer(name, val.to(torch.float32)) + register_buffer('Lambda_N', Lambda_N) + register_buffer('Sigma_N', Sigma_N) + self.set_rotation_matrix(U) + + + Lambda_t, Lambda_bar_t, Lambda_bar_t_prev = compute_covariance_matrices(diffusion=self, Lambda_N=Lambda_N, + diffusion_covariance_type=diffusion_covariance_type, gamma_scheduler=gamma_scheduler) + + def create_diagonal_matrix(diagonal_vector): + return torch.stack([torch.diag(diag) for diag in diagonal_vector], dim=0) # [T, N, N] + ######### forward , for training and inference ##################### + #predict_noise_from_start + inv_sqrt_Lambda_bar = 1/torch.sqrt(Lambda_bar_t) + inv_sqrt_Lambda_bar_sqrt_alphas_cumprod = (1/torch.sqrt(Lambda_bar_t))*self.sqrt_alphas_cumprod.unsqueeze(-1) + register_buffer('inv_sqrt_Lambda_bar_mmUt', create_diagonal_matrix(inv_sqrt_Lambda_bar)@self.U_transposed.unsqueeze(0)) + register_buffer('inv_sqrt_Lambda_bar_sqrt_alphas_cumprod_mmUt', create_diagonal_matrix(inv_sqrt_Lambda_bar_sqrt_alphas_cumprod)@self.U_transposed.unsqueeze(0)) + #predict_start_from_noise + sqrt_Lambda_bar = torch.sqrt(Lambda_bar_t) + sqrt_Lambda_bar_sqrt_recip_alphas_cumprod = torch.sqrt(Lambda_bar_t/self.alphas_cumprod.unsqueeze(-1)) + register_buffer('Umm_sqrt_Lambda_bar_t', U.unsqueeze(0)@create_diagonal_matrix(sqrt_Lambda_bar)) + register_buffer('Umm_sqrt_Lambda_bar_t_sqrt_recip_alphas_cumprod', U.unsqueeze(0)@create_diagonal_matrix(sqrt_Lambda_bar_sqrt_recip_alphas_cumprod)) + + ######### q_posterior , for reverse process ##################### + #q_posterior + Lambda_posterior_t = Lambda_t*Lambda_bar_t_prev*(1/Lambda_bar_t) + sqrt_alphas_cumprod_prev = torch.sqrt(self.alphas_cumprod_prev) + register_buffer('Lambda_posterior', Lambda_posterior_t) + register_buffer('Lambda_posterior_log_variance_clipped', torch.log(Lambda_posterior_t.clamp(min =1e-20))) + + posterior_mean_coef1_x0 = sqrt_alphas_cumprod_prev.unsqueeze(-1).unsqueeze(-1)*(U.unsqueeze(0)@create_diagonal_matrix((1/Lambda_bar_t)*Lambda_t)@self.U_transposed.unsqueeze(0)) + posterior_mean_coef2_xt = torch.sqrt(alphas).unsqueeze(-1).unsqueeze(-1)*(U.unsqueeze(0)@create_diagonal_matrix((1/Lambda_bar_t)*Lambda_bar_t_prev)@self.U_transposed.unsqueeze(0)) + register_buffer('posterior_mean_coef1_x0', posterior_mean_coef1_x0) + register_buffer('posterior_mean_coef2_xt', posterior_mean_coef2_xt) + + ######### loss ##################### + self.loss_reduction_type = loss_reduction_type + sqrt_recip_Lambda_bar_t = torch.sqrt(1. / Lambda_bar_t) + register_buffer('mahalanobis_S_sqrt_recip', create_diagonal_matrix(sqrt_recip_Lambda_bar_t)@self.U_transposed.unsqueeze(0)) + + if self.objective == 'pred_noise': + loss_weight = torch.ones_like(alphas) + elif self.objective == 'pred_x0': + loss_weight = self.alphas_cumprod + elif self.objective == 'pred_v': + assert 0, "Not implemented" + # loss_weight = snr / (snr + 1) + register_buffer('loss_weight', loss_weight) + + assert not len(self.mahalanobis_S_sqrt_recip.shape) == 1 + + + ######################################################################## + # CLASS FUNCTIONS + ######################################################################### + + def set_rotation_matrix(self, U:torch.Tensor): + register_buffer = lambda name, val: self.register_buffer(name, val.to(torch.float32)) + register_buffer('U', U) + register_buffer('U_transposed', U.t()) + + def check_eigh(self): + return torch.isclose(self.U@torch.diag(self.Lambda_N)@self.U_transposed,self.Sigma_N)#.all(), "U@Lambda_N@U^T must be equal to Sigma_N" + + def get_anisotropic_noise(self, x, *args, **kwargs): + """ + x is either tensor or shape + """ + return self.get_noise(x, *args, **kwargs)*self.Lambda_N.unsqueeze(-1) + + ######################################################################## + # FORWARD PROCESS + ######################################################################### + + @autocast(enabled = False) + def q_sample(self, x_start, t, noise=None): + noise = default(noise, lambda: self.get_white_noise(x_start)) + + return ( + extract(self.sqrt_alphas_cumprod, t, x_start.shape) * x_start + + extract_matrix(self.Umm_sqrt_Lambda_bar_t, t, x_start.shape) @ noise + ) + # for inference + def predict_start_from_noise(self, x_t, t, noise): + return ( + extract(self.sqrt_recip_alphas_cumprod, t, x_t.shape) * x_t - + extract_matrix(self.Umm_sqrt_Lambda_bar_t_sqrt_recip_alphas_cumprod, t, x_t.shape) @ noise + ) + # for inference + def predict_noise_from_start(self, x_t, t, x0): + return ( + extract_matrix(self.inv_sqrt_Lambda_bar_mmUt, t, x_t.shape)@x_t -\ + extract_matrix(self.inv_sqrt_Lambda_bar_sqrt_alphas_cumprod_mmUt, t, x_t.shape)@x0 + ) + + ######################################################################## + # LOSS + ######################################################################### + + def mahalanobis_dist(self, matrix, vector): + return (matrix@vector).abs() # check shape + + def loss_funct(self, model_out, target, t): + difference = target - model_out if self.objective == 'pred_noise' else model_out - target + + loss = self.mahalanobis_dist(extract_matrix(self.mahalanobis_S_sqrt_recip, t, difference.shape), difference) + if self.loss_reduction_type == 'l1': + loss = loss + elif self.loss_reduction_type == 'mse': + loss = loss**2 + else: + assert 0, "Not implemented" + return loss + + ######################################################################## + # REVERSE PROCESS + ######################################################################### + + def q_posterior_mean(self, x_start, x_t, t): + return ( + extract_matrix(self.posterior_mean_coef1_x0, t, x_t.shape) @ x_start + + extract_matrix(self.posterior_mean_coef2_xt, t, x_t.shape) @ x_t + ) + + def q_posterior(self, x_start, x_t, t): + posterior_mean = self.q_posterior_mean(x_start, x_t, t) + posterior_variance = extract_matrix(self.Lambda_posterior, t, x_t.shape) + posterior_log_variance_clipped = extract_matrix(self.Lambda_posterior_log_variance_clipped, t, x_t.shape) + return posterior_mean, posterior_variance, posterior_log_variance_clipped + + def p_combine_mean_var_noise(self, model_mean, posterior_log_variance, noise): + """ mean is in not diagonal coordinate system, posterior_log_variance is in diagonal coordinate system""" + return model_mean + self.U@((0.5 * posterior_log_variance).exp() * noise) + + + ######################################################################## + # INTERPOLATION + ######################################################################### + + def interpolate_noise(self, noise1, noise2, posterior_log_variance=None, interpolate_funct=None): + noise1 = self.U@((0.5 * posterior_log_variance).exp() * noise1) + noise2 = self.U@((0.5 * posterior_log_variance).exp() * noise2) + interpolated_noise = interpolate_funct(noise1, noise2) + return interpolated_noise + + + def p_interpolate_mean_var_noise(self, model_mean, model_log_variance, noise, noise2interpolate=None, **kwargs): + interpolated_noise = self.interpolate_noise(noise, noise2interpolate, posterior_log_variance=model_log_variance, **kwargs) + return model_mean + interpolated_noise # (0.5 * model_log_variance).exp() + diff --git a/SkeletonDiffusion/src/core/diffusion/utils.py b/SkeletonDiffusion/src/core/diffusion/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..f3e3adb6c77ec833327e1d5eec9fbc724acc54f4 --- /dev/null +++ b/SkeletonDiffusion/src/core/diffusion/utils.py @@ -0,0 +1,125 @@ +import torch + +def dim_null_space(matrix): + assert matrix.shape[-1] == matrix.shape[-2], "Matrix must be square" + # rank = torch.linalg.matrix_rank(matrix) This is not set to accuracy of PYTORCH float32 + # 1.0 + eps != 1.0 + # torhc.tensor(1.0) + 0.7e-7!= torhc.tensor(1.0) + return torch.sum(torch.linalg.eigh(matrix)[0].abs() < 0.7e-7) + +def is_positive_def(matrix): + #M is symmetric or Hermitian, and all its eigenvalues are real and positive. + assert torch.allclose(matrix.transpose(-1, -2), matrix), "Matrix must be symmetric" + eigenvalues = torch.linalg.eigvals(matrix) + is_pos_def = (torch.real(eigenvalues)> 0).all() + if is_pos_def: + assert torch.isreal(eigenvalues).all(), "Eigenvalues must be real" + return (torch.real(eigenvalues)> 0).all() + +def make_positive_definite(matrix, epsilon=1e-6, if_submin=False): + + eigenvalues = torch.linalg.eigvals(matrix) + # assert torch.isreal(eigenvalues).all() + if is_positive_def(matrix): + print("Input Matrix was positive Definitive without adding spectral norm to the diagonal") + return matrix + + eigenvalues = torch.real(eigenvalues) + if not if_submin: + max_eig = eigenvalues.abs().max() # + pos_def_matrix = matrix + torch.eye(matrix.shape[0])*(max_eig + epsilon) + else: + min_eig = eigenvalues.min() + pos_def_matrix = matrix + torch.eye(matrix.shape[0])*(- min_eig + epsilon) + assert dim_null_space(pos_def_matrix) == 0 + return pos_def_matrix + +def normalize_cov(Sigma_N:torch.Tensor, Lambda_N:torch.Tensor, U:torch.Tensor, if_sigma_n_scale=True, sigma_n_scale='spectral', **kwargs): + N, _ = Sigma_N.shape + assert Lambda_N.shape == (N,) + assert U.shape == (N, N) + + if if_sigma_n_scale: + # decrease the scale of Sigma_N to make it more similar to the identity matrix + if sigma_n_scale == 'spectral': + relative_scale_factor = Lambda_N.max() + else: + if sigma_n_scale == 'frob': + relative_scale_factor = Lambda_N.sum()/N + else: + assert 0, "Not implemented" + + Lambda_N = Lambda_N/relative_scale_factor + + Sigma_N = Sigma_N/relative_scale_factor + cond = U @ torch.diag(Lambda_N) @ U.mT + assert torch.isclose(Sigma_N, cond, atol=1e-06).all(), "Sigma_N must be equal to U @ Lambda_N @ U.t()" + # Sigma_N[Sigma_N>0.] = (Sigma_N + Sigma_N.t())[Sigma_N>0.]/2 + cond = Lambda_N>0.7e-7 + assert (cond).all(), f"Lambda_N must be positive definite: {Lambda_N}" + assert is_positive_def(Sigma_N), "Sigma_N must be positive definite" + # print("Frobenius Norm of SigmaN: ", torch.linalg.matrix_norm(Sigma_N, ord='fro').mean().item(), "Spectral Norm of SigmaN: ", Lambda_N.max(dim=-1)[0].mean().item()) + return Sigma_N, Lambda_N + + +def get_cov_from_corr(correlation_matrix: torch.Tensor, if_sigma_n_scale=True, sigma_n_scale='spectral', if_run_as_isotropic=False, diffusion_covariance_type='skeleton-diffusion', **kwargs): + N, _ = correlation_matrix.shape + + if if_run_as_isotropic: + if diffusion_covariance_type == 'skeleton-diffusion': + Lambda_N = torch.ones(N, device=correlation_matrix.device) + Sigma_N = torch.zeros_like(correlation_matrix) + U = torch.eye(N, device=correlation_matrix.device) + elif diffusion_covariance_type == 'anisotropic': + Lambda_N = torch.ones(N, device=correlation_matrix.device) + Sigma_N = torch.eye(N, device=correlation_matrix.device) + U = torch.eye(N, device=correlation_matrix.device) + else: + Lambda_N = torch.zeros(N, device=correlation_matrix.device) + Sigma_N = torch.zeros_like(correlation_matrix) + U = torch.eye(N, device=correlation_matrix.device) + else: + Sigma_N = make_positive_definite(correlation_matrix) + Lambda_N, U = torch.linalg.eigh(Sigma_N, UPLO='L') + + Sigma_N, Lambda_N = normalize_cov(Sigma_N=Sigma_N, Lambda_N=Lambda_N, U=U, if_sigma_n_scale=if_sigma_n_scale, sigma_n_scale=sigma_n_scale, **kwargs) + return Sigma_N, Lambda_N, U + + +def verify_noise_scale(diffusion): + N, *_ = diffusion.Lambda_N.shape + alphas = 1 - diffusion.betas + noise = diffusion.get_noise((2000, diffusion.num_timesteps, N)) + zeta_noise = torch.sqrt(diffusion.Lambda_t.unsqueeze(0)) * noise + print("current: ", (zeta_noise**2).sum(-1).mean(0)) + print("original standard gaussian diffusion: ",(1-alphas) * zeta_noise.shape[-1]) + + +def plot_matrix(matrix): + import matplotlib + import matplotlib.pyplot as plt + from matplotlib.colors import ListedColormap + import numpy as np + + Sigma_N = matrix.cpu().clone().numpy() + color = 'Purples' + cmap = matplotlib.colormaps[color].set_bad("white") + # colormap_r = ListedColormap(cmap.colors[::-1]) + + fig, ax = plt.subplots(1,1, figsize=(6, 6),sharex=True, subplot_kw=dict(box_aspect=1),) + # cax = fig.add_axes([0.93, 0.15, 0.01, 0.7]) # Adjust the position and size of the colorbar + # for i, ax in enumerate(axes): + vmax = Sigma_N.max() + Sigma_N[Sigma_N <=0.0000] = np.nan + im = ax.imshow(Sigma_N, cmap=color, vmin=0., vmax=vmax) + # ax.set_xticks(np.arange(len(Sigma_N))) + # ax.set_xticklabels(labels=list(skeleton.node_dict.values()), rotation=45, ha="right", + # rotation_mode="anchor") + # ax.set_yticks(np.arange(len(Sigma_N))) + # ax.set_yticklabels(labels=list(skeleton.node_dict.values()), rotation=45, ha="right", + # rotation_mode="anchor") + # ax.set_title(list(method2sigman.keys())[i]) + fig.colorbar(im, cmap=cmap) +# plt.title('Adjancecy Matrix') + plt.show() + # fig.savefig("../paper_plots/sigmaN.pdf", format="pdf", bbox_inches="tight") \ No newline at end of file diff --git a/SkeletonDiffusion/src/core/diffusion_manager.py b/SkeletonDiffusion/src/core/diffusion_manager.py new file mode 100644 index 0000000000000000000000000000000000000000..d692b6821cdb42469fbc3869ff1d124c6bfc8097 --- /dev/null +++ b/SkeletonDiffusion/src/core/diffusion_manager.py @@ -0,0 +1,45 @@ +from typing import Tuple, Optional, List, Union, Dict, Any +import torch + +from SkeletonDiffusion.src.core.network.nn import Denoiser +from SkeletonDiffusion.src.core.diffusion import IsotropicGaussianDiffusion, NonisotropicGaussianDiffusion, get_cov_from_corr + + +class DiffusionManager(): + def __init__(self, diffusion_type: str='IsotropicGaussianDiffusion', skeleton=None, covariance_matrix_type: str = 'adjacency', + reachability_matrix_degree_factor=0.5, reachability_matrix_stop_at=0, if_sigma_n_scale=True, sigma_n_scale='spectral', if_run_as_isotropic=False, + **kwargs): + + model = self.get_network(**kwargs) + self.diffusion_type = diffusion_type + + if diffusion_type == 'NonisotropicGaussianDiffusion': + # define SigmaN + if covariance_matrix_type == 'adjacency': + correlation_matrix = skeleton.adj_matrix + elif covariance_matrix_type == 'reachability': + correlation_matrix = skeleton.reachability_matrix(factor=reachability_matrix_degree_factor, stop_at=reachability_matrix_stop_at) + else: + assert 0, "Not implemented" + N, *_ = correlation_matrix.shape + + Sigma_N, Lambda_N, U = get_cov_from_corr(correlation_matrix=correlation_matrix, if_sigma_n_scale=if_sigma_n_scale, sigma_n_scale=sigma_n_scale, if_run_as_isotropic=if_run_as_isotropic, **kwargs) + self.diffusion = NonisotropicGaussianDiffusion(Sigma_N=Sigma_N, Lambda_N=Lambda_N, U=U, model=model, **kwargs) + elif diffusion_type == 'IsotropicGaussianDiffusion': + self.diffusion = IsotropicGaussianDiffusion(model=model, **kwargs) + else: + assert 0, f"{diffusion_type} Not implemented" + + def get_diffusion(self): + return self.diffusion + + def get_network(self, num_nodes, diffusion_conditioning=False, latent_size=96, node_types: torch.Tensor = None, diffusion_arch=Dict[str, Any], **kwargs): + + if diffusion_conditioning: + cond_dim = latent_size + else: + cond_dim = 0 + + model = Denoiser(dim=latent_size, cond_dim=cond_dim, out_dim=latent_size, channels=num_nodes, num_nodes=num_nodes, node_types=node_types,**diffusion_arch) + + return model \ No newline at end of file diff --git a/SkeletonDiffusion/src/core/network/__init__.py b/SkeletonDiffusion/src/core/network/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8f5e25cdee0f0567f7a7e177c13f351aaf430e43 --- /dev/null +++ b/SkeletonDiffusion/src/core/network/__init__.py @@ -0,0 +1,3 @@ +from .nn import AutoEncoder, Denoiser + +__all__ = ['AutoEncoder', 'Denoiser'] diff --git a/SkeletonDiffusion/src/core/network/layers/__init__.py b/SkeletonDiffusion/src/core/network/layers/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..adc6845452c223d49488533747ff0b5c64690566 --- /dev/null +++ b/SkeletonDiffusion/src/core/network/layers/__init__.py @@ -0,0 +1,3 @@ +from .graph_structural import StaticGraphLinear +from .recurrent import StaticGraphGRU, GraphGRUState, StaticGraphLSTM, GraphLSTMState +from .attention import Attention, ResnetBlock, Residual, PreNorm, RMSNorm diff --git a/SkeletonDiffusion/src/core/network/layers/attention.py b/SkeletonDiffusion/src/core/network/layers/attention.py new file mode 100644 index 0000000000000000000000000000000000000000..3f03f48009dd8334c66ac98f943011be0115664f --- /dev/null +++ b/SkeletonDiffusion/src/core/network/layers/attention.py @@ -0,0 +1,138 @@ +import torch +from torch import nn, einsum, Tensor +import torch.nn.functional as F +from einops import rearrange +from torch import nn, einsum + +from .graph_structural import StaticGraphLinear + + + +class Residual(nn.Module): + def __init__(self, fn): + super().__init__() + self.fn = fn + + def forward(self, x, *args, **kwargs): + return self.fn(x, *args, **kwargs) + x + +class LayerNorm(nn.Module): + def __init__(self, dim): + super().__init__() + self.norm = torch.nn.LayerNorm((dim), elementwise_affine=True) + + def forward(self, x): + x = torch.swapaxes(x, -2, -1) + x = self.norm(x) + x = torch.swapaxes(x, -2, -1) + return x + +class RMSNorm(nn.Module): + def __init__(self, dim): + super().__init__() + self.g = nn.Parameter(torch.ones(1, 1, dim)) + + def forward(self, x): + return F.normalize(x, dim = -1) * self.g * (x.shape[-1] ** 0.5) #normalize divides by maximum norm element. Different from original in which we take the max norma nd not the sum of square elem. + +class PreNorm(nn.Module): + def __init__(self, dim, fn): + super().__init__() + self.fn = fn + self.norm = RMSNorm(dim) + + def forward(self, x): + x = self.norm(x) + return self.fn(x) + + +class Block(nn.Module): + def __init__(self, dim, dim_out, norm_type='none', act_type='tanh', *args, **kwargs): + super().__init__() + self.proj = StaticGraphLinear(dim, dim_out, *args, **kwargs) + # num_nodes=num_nodes, + # node_types=T) + if norm_type == 'none': + self.norm = nn.Identity() #nn.GroupNorm(groups, dim_out) + elif norm_type == 'layer': + self.norm = LayerNorm(kwargs['num_nodes']) + else: + assert 0, f"Norm type {norm_type} not implemented!" + if act_type == 'tanh': + self.act = nn.Tanh() + else: + assert 0, f"Activation type {act_type} not implemented!" + + def forward(self, x, scale_shift = None): + x = self.proj(x) + x = self.norm(x) + + if scale_shift is not None: + scale, shift = scale_shift + x = x * (scale + 1) + shift + + x = self.act(x) + return x + + +class ResnetBlock(nn.Module): + def __init__(self, dim, dim_out, *, time_emb_dim = None, groups = 8, **kwargs): + super().__init__() + self.mlp = nn.Sequential( + nn.Tanh(), + nn.Linear(time_emb_dim, dim_out * 2) + ) if time_emb_dim is not None else None + + self.block1 = Block(dim, dim_out, groups = groups, **kwargs) + self.block2 = Block(dim_out, dim_out, groups = groups, **kwargs) + self.res_linear = StaticGraphLinear(dim, dim_out, bias=False, **kwargs) if dim != dim_out else nn.Identity() + + def forward(self, x, time_emb = None): + + scale_shift = None + if self.mlp is not None and time_emb is not None: + time_emb = self.mlp(time_emb) + time_emb = rearrange(time_emb, 'b c -> b 1 c') + scale_shift = time_emb.chunk(2, dim = -1) + + h = self.block1(x, scale_shift = scale_shift) + + h = self.block2(h) + + return h + self.res_linear(x) + +# We need default num_heads: int = 8, +class Attention(nn.Module): + def __init__(self, dim, dim_out=None, heads = 4, dim_head = 32,qkv_bias: bool = False, attn_dropout: float = 0., proj_dropout: float = 0., qk_norm: bool = False, norm_layer: nn.Module = nn.Identity, **kwargs): + super().__init__() + self.scale = dim_head ** -0.5 + self.heads = heads + hidden_dim = dim_head * heads + dim_out = dim_out if dim_out is not None else dim + + self.to_qkv = StaticGraphLinear(dim,hidden_dim * 3,bias=qkv_bias, **kwargs) + self.to_out = StaticGraphLinear(hidden_dim,dim_out,bias=False,**kwargs) + self.attn_dropout = nn.Dropout(attn_dropout) + self.out_dropout = nn.Dropout(proj_dropout) + + + self.q_norm = norm_layer(dim_head) if qk_norm else nn.Identity() + self.k_norm = norm_layer(dim_head) if qk_norm else nn.Identity() + + def forward(self, x): + b, n, c = x.shape + qkv = self.to_qkv(x).chunk(3, dim = -1) + q, k, v = map(lambda t: rearrange(t, 'b n (h c) -> b h c n', h = self.heads), qkv) + q, k = self.q_norm(q), self.k_norm(k) + + q = q * self.scale + sim = einsum('b h c n, b h c j -> b h n j', q, k) + attn = sim.softmax(dim = -1) + attn = self.attn_dropout(attn) + + out = einsum('b h n j, b h d j -> b h n d', attn, v) + + out = rearrange(out, 'b h n d -> b n (h d)') + return self.out_dropout(self.to_out(out)) + + diff --git a/SkeletonDiffusion/src/core/network/layers/graph_structural.py b/SkeletonDiffusion/src/core/network/layers/graph_structural.py new file mode 100644 index 0000000000000000000000000000000000000000..6be1c9e8574c7ca8b7f69d4c49e51809bca8f859 --- /dev/null +++ b/SkeletonDiffusion/src/core/network/layers/graph_structural.py @@ -0,0 +1,133 @@ +from typing import Tuple, Optional, List, Union + +import torch +from torch.nn import * +import math + +def gmm(x: torch.Tensor, w: torch.Tensor) -> torch.Tensor: + return torch.einsum('ndo,bnd->bno', w, x) + + +class GraphLinear(Module): + def __init__(self, in_features: int, out_features: int): + super().__init__() + self.in_features = in_features + self.out_features = out_features + + def reset_parameters(self) -> None: + init.kaiming_uniform_(self.weight, a=math.sqrt(5)) + #stdv = 1. / math.sqrt(self.weight.size(1)) + #self.weight.data.uniform_(-stdv, stdv) + #if self.learn_influence: + # self.G.data.uniform_(-stdv, stdv) + if len(self.weight.shape) == 3: + self.weight.data[1:] = self.weight.data[0] + if self.bias is not None: + fan_in, _ = init._calculate_fan_in_and_fan_out(self.weight) + bound = 1 / math.sqrt(fan_in) + init.uniform_(self.bias, -bound, bound) + + def forward(self, input: torch.Tensor, g: Optional[torch.Tensor] = None) -> torch.Tensor: + if g is None and self.learn_influence: + g = torch.nn.functional.normalize(self.G, p=1., dim=1) + #g = torch.softmax(self.G, dim=1) + elif g is None: + g = self.G + w = self.weight[self.node_type_index] + output = self.mm(input, w.transpose(-2, -1)) + if self.bias is not None: + bias = self.bias[self.node_type_index] + output += bias + output = g.matmul(output) + + return output + + +class DynamicGraphLinear(GraphLinear): + def __init__(self, num_node_types: int = 1, *args): + super().__init__(*args) + + def forward(self, input: torch.Tensor, g: torch.Tensor = None, t: torch.Tensor = None) -> torch.Tensor: + assert g is not None or t is not None, "Either Graph Influence Matrix or Node Type Vector is needed" + if g is None: + g = self.G[t][:, t] + return super().forward(input, g) + + + +class StaticGraphLinear(GraphLinear): + def __init__(self, *args, bias: bool = True, num_nodes: int = None, graph_influence: Union[torch.Tensor, Parameter] = None, + learn_influence: bool = False, node_types: torch.Tensor = None, weights_per_type: bool = False, **kwargs): + """ + :param in_features: Size of each input sample + :param out_features: Size of each output sample + :param num_nodes: Number of nodes. + :param graph_influence: Graph Influence Matrix + :param learn_influence: If set to ``False``, the layer will not learn an the Graph Influence Matrix. + :param node_types: List of Type for each node. All nodes of same type will share weights. + Default: All nodes have unique types. + :param weights_per_type: If set to ``False``, the layer will not learn weights for each node type. + :param bias: If set to ``False``, the layer will not learn an additive bias. + """ + super().__init__(*args) + + self.learn_influence = learn_influence + + if graph_influence is not None: + assert num_nodes == graph_influence.shape[0] or num_nodes is None, 'Number of Nodes or Graph Influence Matrix has to be given.' + num_nodes = graph_influence.shape[0] + if type(graph_influence) is Parameter: + assert learn_influence, "Graph Influence Matrix is a Parameter, therefore it must be learnable." + self.G = graph_influence + elif learn_influence: + self.G = Parameter(graph_influence) + else: + self.register_buffer('G', graph_influence) + else: + assert num_nodes, 'Number of Nodes or Graph Influence Matrix has to be given.' + eye_influence = torch.eye(num_nodes, num_nodes) + if learn_influence: + self.G = Parameter(eye_influence) + else: + self.register_buffer('G', eye_influence) + + if weights_per_type and node_types is None: + node_types = torch.tensor([i for i in range(num_nodes)]) + if node_types is not None: + num_node_types = node_types.max() + 1 + self.weight = Parameter(torch.Tensor(num_node_types, self.out_features, self.in_features)) + self.mm = gmm + self.node_type_index = node_types + else: + self.weight = Parameter(torch.Tensor(self.out_features, self.in_features)) + self.mm = torch.matmul + self.node_type_index = None + + if bias: + if node_types is not None: + self.bias = Parameter(torch.Tensor(num_node_types, self.out_features)) + else: + self.bias = Parameter(torch.Tensor(self.out_features)) + else: + self.register_parameter('bias', None) + + self.reset_parameters() + + +# class BN(Module): +# def __init__(self, num_nodes, num_features): +# super().__init__() +# self.num_nodes = num_nodes +# self.num_features = num_features +# self.bn = BatchNorm1d(num_nodes * num_features) + +# def forward(self, x: torch.Tensor) -> torch.Tensor: +# return self.bn(x.view(-1, self.num_nodes * self.num_features)).view(-1, self.num_nodes, self.num_features) + +# class LinearX(Module): +# def __init__(self): +# super().__init__() + +# def forward(self, input: torch.Tensor) -> torch.Tensor: +# return input + diff --git a/SkeletonDiffusion/src/core/network/layers/recurrent.py b/SkeletonDiffusion/src/core/network/layers/recurrent.py new file mode 100644 index 0000000000000000000000000000000000000000..4fb8f630d62260ad8e84a349a6615df7a2713bf3 --- /dev/null +++ b/SkeletonDiffusion/src/core/network/layers/recurrent.py @@ -0,0 +1,402 @@ +from typing import Tuple, Optional, List, Union + +import torch +from torch.nn import * +import math + +from .graph_structural import gmm + +IFDEF_JITSCRIPT = False # generates nan for long sequences. + +GraphLSTMState = Tuple[Optional[torch.Tensor], Optional[torch.Tensor], Optional[torch.Tensor]] + +class StaticGraphLSTMCell_(Module): + def __init__(self, input_size: int, hidden_size: int, num_nodes: int = None, dropout: float = 0., + recurrent_dropout: float = 0., graph_influence: Union[torch.Tensor, Parameter] = None, + learn_influence: bool = False, additive_graph_influence: Union[torch.Tensor, Parameter] = None, + learn_additive_graph_influence: bool = False, node_types: torch.Tensor = None, + weights_per_type: bool = False, clockwork: bool = False, bias: bool = True): + """ + + :param input_size: The number of expected features in the input `x` + :param hidden_size: The number of features in the hidden state `h` + :param num_nodes: + :param dropout: + :param recurrent_dropout: + :param graph_influence: + :param learn_influence: + :param additive_graph_influence: + :param learn_additive_graph_influence: + :param node_types: + :param weights_per_type: + :param bias: + """ + super().__init__() + self.input_size = input_size + self.hidden_size = hidden_size + + self.learn_influence = learn_influence + self.learn_additive_graph_influence = learn_additive_graph_influence + if graph_influence is not None: + assert num_nodes == graph_influence.shape[0] or num_nodes is None, 'Number of Nodes or Graph Influence Matrix has to be given.' + num_nodes = graph_influence.shape[0] + if type(graph_influence) is Parameter: + assert learn_influence, "Graph Influence Matrix is a Parameter, therefore it must be learnable." + self.G = graph_influence + elif learn_influence: + self.G = Parameter(graph_influence) + else: + self.register_buffer('G', graph_influence) + else: + assert num_nodes, 'Number of Nodes or Graph Influence Matrix has to be given.' + eye_influence = torch.eye(num_nodes, num_nodes) + if learn_influence: + self.G = Parameter(eye_influence) + else: + self.register_buffer('G', eye_influence) + + if additive_graph_influence is not None: + if type(additive_graph_influence) is Parameter: + self.G_add = additive_graph_influence + elif learn_additive_graph_influence: + self.G_add = Parameter(additive_graph_influence) + else: + self.register_buffer('G_add', additive_graph_influence) + else: + if learn_additive_graph_influence: + self.G_add = Parameter(torch.zeros_like(self.G)) + else: + self.G_add = 0. + + if weights_per_type and node_types is None: + node_types = torch.tensor([i for i in range(num_nodes)]) + if node_types is not None: + num_node_types = node_types.max() + 1 + self.weight_ih = Parameter(torch.Tensor(num_node_types, 4 * hidden_size, input_size)) + self.weight_hh = Parameter(torch.Tensor(num_node_types, 4 * hidden_size, hidden_size)) + self.mm = gmm + self.register_buffer('node_type_index', node_types) + else: + self.weight_ih = Parameter(torch.Tensor(4 * hidden_size, input_size)) + self.weight_hh = Parameter(torch.Tensor(4 * hidden_size, hidden_size)) + self.mm = torch.matmul + self.register_buffer('node_type_index', None) + + if bias: + if node_types is not None: + self.bias_ih = Parameter(torch.Tensor(num_node_types, 4 * hidden_size)) + self.bias_hh = Parameter(torch.Tensor(num_node_types, 4 * hidden_size)) + else: + self.bias_ih = Parameter(torch.Tensor(4 * hidden_size)) + self.bias_hh = Parameter(torch.Tensor(4 * hidden_size)) + else: + self.bias_ih = None + self.bias_hh = None + + self.clockwork = clockwork + if clockwork: + phase = torch.arange(0., hidden_size) + phase = phase - phase.min() + phase = (phase / phase.max()) * 8. + phase += 1. + phase = torch.floor(phase) + self.register_buffer('phase', phase) + else: + phase = torch.ones(hidden_size) + self.register_buffer('phase', phase) + + self.dropout = Dropout(dropout) + self.r_dropout = Dropout(recurrent_dropout) + + self.num_nodes = num_nodes + + self.init_weights() + + def init_weights(self): + stdv = 1.0 / math.sqrt(self.hidden_size) + for weight in self.parameters(): + if weight is self.G: + continue + if weight is self.G_add: + continue + weight.data.uniform_(-stdv, stdv) + if weight is self.weight_hh or weight is self.weight_ih and len(self.weight_ih.shape) == 3: + weight.data[1:] = weight.data[0] + + def forward(self, input: torch.Tensor, state: GraphLSTMState, t: int = 0) -> Tuple[torch.Tensor, GraphLSTMState]: + hx, cx, gx = state + if hx is None: + hx = torch.zeros(input.shape[0], self.num_nodes, self.hidden_size, dtype=input.dtype, device=input.device) + if cx is None: + cx = torch.zeros(input.shape[0], self.num_nodes, self.hidden_size, dtype=input.dtype, device=input.device) + if gx is None and self.learn_influence: + gx = torch.nn.functional.normalize(self.G, p=1., dim=1) + #gx = torch.softmax(self.G, dim=1) + elif gx is None: + gx = self.G + + hx = self.r_dropout(hx) + + weight_ih = self.weight_ih[self.node_type_index] + weight_hh = self.weight_hh[self.node_type_index] + if self.bias_hh is not None: + bias_hh = self.bias_hh[self.node_type_index] + else: + bias_hh = 0. + + c_mask = (torch.remainder(torch.tensor(t + 1., device=input.device), self.phase) < 0.01).type_as(cx) + + gates = (self.dropout(self.mm(input, weight_ih.transpose(-2, -1))) + + self.mm(hx, weight_hh.transpose(-2, -1)) + bias_hh) + gates = torch.matmul(gx, gates) + ingate, forgetgate, cellgate, outgate = gates.chunk(4, 2) + + ingate = torch.sigmoid(ingate) + forgetgate = torch.sigmoid(forgetgate) + cellgate = torch.tanh(cellgate) + outgate = torch.sigmoid(outgate) + + cy = c_mask * ((forgetgate * cx) + (ingate * cellgate)) + (1 - c_mask) * cx + hy = outgate * torch.tanh(cy) + + gx = gx + self.G_add + if self.learn_influence or self.learn_additive_graph_influence: + gx = torch.nn.functional.normalize(gx, p=1., dim=1) + #gx = torch.softmax(gx, dim=1) + + return hy, (hy, cy, gx) + + +class StaticGraphLSTM_(Module): + def __init__(self, input_size: int, hidden_size: int, num_layers: int = 1, layer_dropout: float = 0.0, **kwargs): + super().__init__() + self.layers = ModuleList([StaticGraphLSTMCell_(input_size, hidden_size, **kwargs)] + + [StaticGraphLSTMCell_(hidden_size, hidden_size, **kwargs) for _ in range(num_layers - 1)]) + self.dropout = Dropout(layer_dropout) + + def forward(self, input: torch.Tensor, states: Optional[List[GraphLSTMState]] = None, t_i: int = 0) -> Tuple[torch.Tensor, List[GraphLSTMState]]: + if states is None: + n: Optional[torch.Tensor] = None + states = [(n, n, n)] * len(self.layers) + + output_states: List[GraphLSTMState] = [] + output = input + i = 0 + for rnn_layer in self.layers: + state = states[i] + inputs = output.unbind(1) + outputs: List[torch.Tensor] = [] + for t, input in enumerate(inputs): + out, state = rnn_layer(input, state, t_i+t) + outputs += [out] + output = torch.stack(outputs, dim=1) + output = self.dropout(output) + output_states += [state] + i += 1 + return output, output_states + + +def StaticGraphLSTM(*args, **kwargs): + if IFDEF_JITSCRIPT: + return torch.jit.script(StaticGraphLSTM_(*args, **kwargs)) + else: + return StaticGraphLSTM_(*args, **kwargs) + +GraphGRUState = Tuple[Optional[torch.Tensor], Optional[torch.Tensor]] + + +class StaticGraphGRUCell_(Module): + def __init__(self, input_size: int, hidden_size: int, num_nodes: int = None, dropout: float = 0., + recurrent_dropout: float = 0., graph_influence: Union[torch.Tensor, Parameter] = None, + learn_influence: bool = False, additive_graph_influence: Union[torch.Tensor, Parameter] = None, + learn_additive_graph_influence: bool = False, node_types: torch.Tensor = None, + weights_per_type: bool = False, clockwork: bool = False, bias: bool = True): + """ + + :param input_size: The number of expected features in the input `x` + :param hidden_size: The number of features in the hidden state `h` + :param num_nodes: + :param dropout: + :param recurrent_dropout: + :param graph_influence: + :param learn_influence: + :param additive_graph_influence: + :param learn_additive_graph_influence: + :param node_types: + :param weights_per_type: + :param bias: + """ + super().__init__() + self.input_size = input_size + self.hidden_size = hidden_size + + self.learn_influence = learn_influence + self.learn_additive_graph_influence = learn_additive_graph_influence + if graph_influence is not None: + assert num_nodes == graph_influence.shape[0] or num_nodes is None, 'Number of Nodes or Graph Influence Matrix has to be given.' + num_nodes = graph_influence.shape[0] + if type(graph_influence) is Parameter: + assert learn_influence, "Graph Influence Matrix is a Parameter, therefore it must be learnable." + self.G = graph_influence + elif learn_influence: + self.G = Parameter(graph_influence) + else: + self.register_buffer('G', graph_influence) + else: + assert num_nodes, 'Number of Nodes or Graph Influence Matrix has to be given.' + eye_influence = torch.eye(num_nodes, num_nodes) + if learn_influence: + self.G = Parameter(eye_influence) + else: + self.register_buffer('G', eye_influence) + + if additive_graph_influence is not None: + if type(additive_graph_influence) is Parameter: + self.G_add = additive_graph_influence + elif learn_additive_graph_influence: + self.G_add = Parameter(additive_graph_influence) + else: + self.register_buffer('G_add', additive_graph_influence) + else: + if learn_additive_graph_influence: + self.G_add = Parameter(torch.zeros_like(self.G)) + else: + self.G_add = 0. + + if weights_per_type and node_types is None: + node_types = torch.tensor([i for i in range(num_nodes)]) + if node_types is not None: + num_node_types = node_types.max() + 1 + self.weight_ih = Parameter(torch.Tensor(num_node_types, 3 * hidden_size, input_size)) + self.weight_hh = Parameter(torch.Tensor(num_node_types, 3 * hidden_size, hidden_size)) + self.mm = gmm + self.register_buffer('node_type_index', node_types) + else: + self.weight_ih = Parameter(torch.Tensor(3 * hidden_size, input_size)) + self.weight_hh = Parameter(torch.Tensor(3 * hidden_size, hidden_size)) + self.mm = torch.matmul + self.register_buffer('node_type_index', None) + + if bias: + if node_types is not None: + self.bias_ih = Parameter(torch.Tensor(num_node_types, 3 * hidden_size)) + self.bias_hh = Parameter(torch.Tensor(num_node_types, 3 * hidden_size)) + else: + self.bias_ih = Parameter(torch.Tensor(3 * hidden_size)) + self.bias_hh = Parameter(torch.Tensor(3 * hidden_size)) + else: + self.bias_ih = None + self.bias_hh = None + + self.clockwork = clockwork + if clockwork: + phase = torch.arange(0., hidden_size) + phase = phase - phase.min() + phase = (phase / phase.max()) * 8. + phase += 1. + phase = torch.floor(phase) + self.register_buffer('phase', phase) + else: + phase = torch.ones(hidden_size) + self.register_buffer('phase', phase) + + self.dropout = Dropout(dropout) + self.r_dropout = Dropout(recurrent_dropout) + + self.num_nodes = num_nodes + + self.init_weights() + + def init_weights(self): + stdv = 1.0 / math.sqrt(self.hidden_size) + for weight in self.parameters(): + if weight is self.G: + continue + if weight is self.G_add: + continue + weight.data.uniform_(-stdv, stdv) + #if weight is self.weight_hh or weight is self.weight_ih and len(self.weight_ih.shape) == 3: + # weight.data[1:] = weight.data[0] + + def forward(self, input: torch.Tensor, state: GraphGRUState, t: int = 0) -> Tuple[torch.Tensor, GraphGRUState]: + hx, gx = state + if hx is None: + hx = torch.zeros(input.shape[0], self.num_nodes, self.hidden_size, dtype=input.dtype, device=input.device) + if gx is None and self.learn_influence: + gx = torch.nn.functional.normalize(self.G, p=1., dim=1) + #gx = torch.softmax(self.G, dim=1) + elif gx is None: + gx = self.G + + hx = self.r_dropout(hx) + + weight_ih = self.weight_ih[self.node_type_index] + weight_hh = self.weight_hh[self.node_type_index] + if self.bias_hh is not None: + bias_hh = self.bias_hh[self.node_type_index] + else: + bias_hh = 0. + if self.bias_ih is not None: + bias_ih = self.bias_ih[self.node_type_index] + else: + bias_ih = 0. + + c_mask = (torch.remainder(torch.tensor(t + 1., device=input.device), self.phase) < 0.01).type_as(hx) + + x_results = self.dropout(self.mm(input, weight_ih.transpose(-2, -1))) + bias_ih + h_results = self.mm(hx, weight_hh.transpose(-2, -1)) + bias_hh + x_results = torch.matmul(gx, x_results) + h_results = torch.matmul(gx, h_results) + + i_r, i_z, i_n = x_results.chunk(3, 2) + h_r, h_z, h_n = h_results.chunk(3, 2) + + r = torch.sigmoid(i_r + h_r) + z = torch.sigmoid(i_z + h_z) + n = torch.tanh(i_n + r * h_n) + + hy = n - torch.mul(n, z) + torch.mul(z, hx) + hy = c_mask * hy + (1 - c_mask) * hx + + gx = gx + self.G_add + if self.learn_influence or self.learn_additive_graph_influence: + gx = torch.nn.functional.normalize(gx, p=1., dim=1) + #gx = torch.softmax(gx, dim=1) + + return hy, (hy, gx) + + +class StaticGraphGRU_(Module): + def __init__(self, input_size: int, hidden_size: int, num_layers: int = 1, layer_dropout: float = 0.0, **kwargs): + super().__init__() + self.layers = ModuleList([StaticGraphGRUCell_(input_size, hidden_size, **kwargs)] + + [StaticGraphGRUCell_(hidden_size, hidden_size, **kwargs) for _ in range(num_layers - 1)]) + self.dropout = Dropout(layer_dropout) + + def forward(self, input: torch.Tensor, states: Optional[List[GraphGRUState]] = None, t_i: int = 0) -> Tuple[torch.Tensor, List[GraphGRUState]]: + if states is None: + n: Optional[torch.Tensor] = None + states = [(n, n)] * len(self.layers) + + output_states: List[GraphGRUState] = [] + output = input + i = 0 + for rnn_layer in self.layers: + state = states[i] + inputs = output.unbind(1) + outputs: List[torch.Tensor] = [] + for t, input in enumerate(inputs): + out, state = rnn_layer(input, state, t_i+t) + outputs += [out] + output = torch.stack(outputs, dim=1) + output = self.dropout(output) + output_states += [state] + i += 1 + return output, output_states + + +def StaticGraphGRU(*args, **kwargs): + if IFDEF_JITSCRIPT: + return torch.jit.script(StaticGraphGRU_(*args, **kwargs)) + else: + return StaticGraphGRU_(*args, **kwargs) \ No newline at end of file diff --git a/SkeletonDiffusion/src/core/network/nn/__init__.py b/SkeletonDiffusion/src/core/network/nn/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..af3abac7971d714c7638ef1b9ba478bde20c4280 --- /dev/null +++ b/SkeletonDiffusion/src/core/network/nn/__init__.py @@ -0,0 +1,2 @@ +from .generator import Denoiser +from .autoencoder import AutoEncoder \ No newline at end of file diff --git a/SkeletonDiffusion/src/core/network/nn/autoencoder.py b/SkeletonDiffusion/src/core/network/nn/autoencoder.py new file mode 100644 index 0000000000000000000000000000000000000000..f30bec00fe3685a5d2dc825e460f5dd619671650 --- /dev/null +++ b/SkeletonDiffusion/src/core/network/nn/autoencoder.py @@ -0,0 +1,105 @@ +from typing import Tuple, Union + +import torch +import torch.nn as nn + +from ..layers import StaticGraphLinear +from .decoder import Decoder +from .encoder import Encoder + + +class AutoEncoder(nn.Module): + def __init__(self, + num_nodes: int, + encoder_hidden_size: int, + decoder_hidden_size: int, + latent_size: int, + node_types: torch.Tensor = None, + input_size: int = 3, + z_activation: str = 'tanh', + enc_num_layers: int = 1, + loss_pose_type: str = 'l1', + **kwargs): + super().__init__() + self.param_groups = [{}] + self.latent_size = latent_size + self.loss_pose_type = loss_pose_type + + self.encoder = Encoder(num_nodes=num_nodes, + input_size=input_size, + hidden_size=encoder_hidden_size, + output_size=latent_size, + node_types=node_types, + enc_num_layers = enc_num_layers, + recurrent_arch = kwargs['recurrent_arch_enc'],) + + + assert kwargs['output_size'] == input_size + self.decoder = Decoder( num_nodes=num_nodes, + input_size=latent_size , + feature_size=input_size, + hidden_size=decoder_hidden_size, + node_types=node_types, + param_groups=self.param_groups, + **kwargs + ) + assert z_activation in ['tanh', 'identity'], f"z_activation must be either 'tanh' or 'identity', but got {z_activation}" + self.z_activation = nn.Tanh() if z_activation == "tanh" else nn.Identity() + + + def forward(self, x): + h, _ = self.encoder(x) + return h + + def get_past_embedding(self, past, state=None): + with torch.no_grad(): + h_hat_embedding = self(past) + z_past = self.z_activation(h_hat_embedding) + return z_past + + def get_embedding(self, future, state=None): + z = self.forward(future) + return z + + def get_train_embeddings(self, y, past, state=None): + z_past = self.get_past_embedding(past, state=state) + z = self.get_embedding(y, state=state) + return z_past, z + + def decode(self, x: torch.Tensor, h: torch.Tensor, z: torch.Tensor, ph=1, state=None): + x_tiled = x[:, -2:] + out, _ = self.decoder(x=x_tiled, + h=h, + z=z, + ph=ph, + state=state) # [B * Z, T, N, D] + return out + + def autoencode(self, y, past, ph=1, state=None): + z_past, z = self.get_train_embeddings(y, past, state=state) + out = self.decode(past, z, z_past, ph) + return out, z_past, z + + def loss(self, y_pred, y, type=None, reduction="mean", **kwargs): + type = self.loss_pose_type if type is None else type + if type=="mse": + out = torch.nn.MSELoss(reduction="none")(y_pred,y) + elif type in ["l1", "L1"]: + out = torch.nn.L1Loss(reduction="none")(y_pred,y) + else: + assert 0, "Not implemnted" + loss = (out.sum(-1) #spatial size + .mean(-1) #keypoints + .mean(-1) # timesteps + ) + if reduction == "mean": + return loss.mean() + elif reduction == "none": + return loss + else: + assert 0, "Not implemnted" + return loss + + + + diff --git a/SkeletonDiffusion/src/core/network/nn/decoder.py b/SkeletonDiffusion/src/core/network/nn/decoder.py new file mode 100644 index 0000000000000000000000000000000000000000..756cb9fec90696ac11d58756c718349eb87a6ef3 --- /dev/null +++ b/SkeletonDiffusion/src/core/network/nn/decoder.py @@ -0,0 +1,104 @@ +import torch +import torch.nn as nn +import torch.nn.functional as F +from typing import List, Tuple, Optional + +from SkeletonDiffusion.src.core.network.layers import StaticGraphLinear, StaticGraphGRU, StaticGraphLSTM + + +class Decoder(nn.Module): + def __init__(self, + num_nodes: int, + feature_size: int, # 3 + input_size: int, # bottleneck dim of h + hidden_size: int, # hidden size of the decoder + output_size: int, + node_types: torch.Tensor = None, + dec_num_layers: int = 1, + dropout: float = 0., + param_groups=None, + recurrent_arch_decoder: str = 'StaticGraphGRU', + **kwargs): + super().__init__() + + self.param_groups = param_groups + self.num_layers = dec_num_layers + self.if_consider_hip = kwargs["if_consider_hip"] + self.activation_fn = torch.nn.Tanh() + + + self.recurrent_arch = recurrent_arch_decoder + recurrent_class = globals()[self.recurrent_arch] + self.rnn = recurrent_class( feature_size + input_size, + hidden_size, + num_nodes=num_nodes, + num_layers=dec_num_layers, + learn_influence=True, + node_types=node_types, + recurrent_dropout=dropout, + learn_additive_graph_influence=True, + clockwork=False) + + self.initial_hidden_h = StaticGraphLinear(feature_size + input_size, + hidden_size, + num_nodes=num_nodes, + learn_influence=True, + node_types=node_types) + if self.recurrent_arch == 'StaticGraphLSTM': + self.initial_hidden_c = StaticGraphLinear(feature_size + input_size, + hidden_size, + num_nodes=num_nodes, + learn_influence=True, + node_types=node_types) + self.fc = StaticGraphLinear(hidden_size, + output_size, + num_nodes=num_nodes, + learn_influence=True, + node_types=node_types) + + self.dropout = nn.Dropout(dropout) + + def init_recurrent_hidden(self, x: torch.Tensor, h: torch.Tensor, z: torch.Tensor, state=None): + x_t = x[:, -1] + x_t_s = x[:, -1].clone() + if state is None: + x_t_1 = x[:, -2] # we are taking this one + else: + x_t_1 = state + + h_z = h + + # Initialize hidden state of rnn + if self.recurrent_arch == 'StaticGraphGRU': + rnn_h = self.initial_hidden_h(torch.cat([x_t_1, h_z], dim=-1)) + hidden = [(rnn_h, None)] * self.num_layers + elif self.recurrent_arch == 'StaticGraphLSTM': + rnn_h = self.initial_hidden_h(torch.cat([x_t_1, h_z], dim=-1)) + rnn_c = self.initial_hidden_c(torch.cat([x_t_1, h_z], dim=-1)) + hidden = [(rnn_h, rnn_c, None)] * self.num_layers + else: + assert 0, f"architeture type {self.recurrent_arch} not supported" + rec_input = torch.cat([x_t, h_z], dim=-1).unsqueeze(1) + return rec_input, hidden + + + def forward(self, x: torch.Tensor, h: torch.Tensor, z: torch.Tensor, + ph: int = 1, state=None) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]: + out = list() + x_t_s = x[:, -1].clone() + rec_input, hidden = self.init_recurrent_hidden(x=x, h=h, z=z, state=state) + + for i in range(ph): + # Run RNN + rnn_out, hidden = self.rnn(input=rec_input, states=hidden, t_i=i) # [B * Z, 1, N, D] + y_t = rnn_out.squeeze(1) # [B * Z, N, D] + y_t = self.dropout(y_t) + + y_t_state = self.fc(y_t) + y_t_state= self.activation_fn(y_t_state) + + out.append(y_t_state) + + out = torch.stack(out, dim=1) + + return out, x_t_s diff --git a/SkeletonDiffusion/src/core/network/nn/encoder.py b/SkeletonDiffusion/src/core/network/nn/encoder.py new file mode 100644 index 0000000000000000000000000000000000000000..b947e7388cee41132c23cea4669e479114a0a454 --- /dev/null +++ b/SkeletonDiffusion/src/core/network/nn/encoder.py @@ -0,0 +1,82 @@ +from typing import Tuple, Union + +import torch +import torch.nn as nn +from typing import Union + +from core.network.layers import StaticGraphLinear, StaticGraphGRU, GraphGRUState, StaticGraphLSTM, GraphLSTMState + + +class Encoder(nn.Module): + def __init__(self, + num_nodes: int, + input_size: int, + hidden_size: int, + output_size: int, + node_types: torch.Tensor = None, + enc_num_layers: int = 1, + dropout: float = 0., + encoder_act: str ="tanh", + recurrent_arch: str = 'StaticGraphGRU', + **kwargs): + super().__init__() + if encoder_act == "tanh": + self.activation_fn = torch.nn.Tanh() #Tanh() #torch.nn.LeakyReLU() + elif encoder_act == "identity": + self.activation_fn = torch.nn.Identity() + else: + assert 0, "not implemented" + self.num_layers = enc_num_layers + self.recurrent_arch = recurrent_arch + recurrent_class = globals()[self.recurrent_arch] + self.rnn = recurrent_class(input_size, + hidden_size, + num_layers=enc_num_layers, + node_types=node_types, + num_nodes=num_nodes, + bias=True, + clockwork=False, + learn_influence=True) + + self.fc = StaticGraphLinear(hidden_size, + output_size, + num_nodes=num_nodes, + node_types=node_types, + bias=True, + learn_influence=True) + + + self.initial_hidden1 = StaticGraphLinear(input_size, + hidden_size, + num_nodes=num_nodes, + node_types=node_types, + bias=True, + learn_influence=True) + if self.recurrent_arch == 'StaticGraphLSTM': + self.initial_hidden_c = StaticGraphLinear(input_size, + hidden_size, + num_nodes=num_nodes, + node_types=node_types, + bias=True, + learn_influence=True) + + self.dropout = nn.Dropout(dropout) + def init_recurrent_hidden(self, x: torch.Tensor, state=None) -> Union[GraphGRUState, GraphLSTMState]: + if state is None: + rnn_h = self.initial_hidden1(x[:, 0]) + #rnn_h2 = self.initial_hidden2(x[:, 0]) + if 'GRU' in self.recurrent_arch: + state = [(rnn_h, None)] * self.num_layers #states: Optional[List[GraphGRUState]] = None, GraphGRUState=Tuple[Optional[torch.Tensor], Optional[torch.Tensor]] + elif 'LSTM' in self.recurrent_arch: + rnn_c = self.initial_hidden_c(x[:, 0]) + state = [(rnn_h, rnn_c, None)] * self.num_layers #states: Optional[List[GraphGRUState]] = None + #Tuple[Optional[torch.Tensor], Optional[torch.Tensor], Optional[torch.Tensor]] + #Optional[List[GraphLSTMState]] = None + return state + + def forward(self, x: torch.Tensor, state: torch.Tensor = None) -> Tuple[torch.Tensor, Union[GraphGRUState, GraphLSTMState]]: + # Initialize hidden state of rnn + states = self.init_recurrent_hidden(x, state) # [B, T, N, 3] --> [B, N, D] + y, state = self.rnn(input=x, states=states) # [B, T, N, 3] --> [B, T, N, D] + h = self.activation_fn(self.fc(self.dropout(y[:, -1]))) # [B, T, N, D] --> [B, N, D] + return h, state diff --git a/SkeletonDiffusion/src/core/network/nn/generator.py b/SkeletonDiffusion/src/core/network/nn/generator.py new file mode 100644 index 0000000000000000000000000000000000000000..cfbc638456a80a4e7109634cb4b1db7b759aaa30 --- /dev/null +++ b/SkeletonDiffusion/src/core/network/nn/generator.py @@ -0,0 +1,112 @@ +import torch +from torch import nn, einsum, Tensor +import torch.nn.functional as F +from einops import rearrange +from typing import Union +from torch import nn, einsum +import math +from denoising_diffusion_pytorch.denoising_diffusion_pytorch_1d import RandomOrLearnedSinusoidalPosEmb, SinusoidalPosEmb + +from ..layers import StaticGraphLinear, Attention, ResnetBlock, Residual, PreNorm + + +class Denoiser(nn.Module): + def __init__( + self, + dim, + out_dim, + channels: int, + cond_dim: int = 0, + depth=1, + self_condition = False, + resnet_block_groups = 8, + learned_variance = False, + learned_sinusoidal_cond = False, + random_fourier_features = False, + learned_sinusoidal_dim = 16, + sinusoidal_pos_emb_theta = 10000, + attn_dim_head = 32, + attn_heads = 4, + use_attention = True, + **kwargs + ): + super().__init__() + + # determine dimensions + self.channels = channels + self.self_condition = self_condition + diffusion_size = dim + cond_dim + input_dim = dim* (2 if self_condition else 1) + cond_dim + self.init_lin = StaticGraphLinear(input_dim, diffusion_size, bias=True, **kwargs) + + + # time embeddings + time_dim = (dim + cond_dim) * 4 + + self.random_or_learned_sinusoidal_cond = learned_sinusoidal_cond or random_fourier_features + + if self.random_or_learned_sinusoidal_cond: + sinu_pos_emb = RandomOrLearnedSinusoidalPosEmb(learned_sinusoidal_dim, random_fourier_features) + fourier_dim = learned_sinusoidal_dim + 1 + else: + sinu_pos_emb = SinusoidalPosEmb(diffusion_size, theta = sinusoidal_pos_emb_theta) + fourier_dim = diffusion_size + + self.time_mlp = nn.Sequential( + sinu_pos_emb, + nn.Linear(fourier_dim, time_dim), + nn.GELU(), + nn.Linear(time_dim, time_dim) + ) + + # layers + self.layers = nn.ModuleList([]) + for i in range(depth): + + self.layers.append(nn.ModuleList([ + ResnetBlock(diffusion_size, diffusion_size, + time_emb_dim = time_dim, groups = resnet_block_groups, # bias=True, + **kwargs), + Residual(PreNorm(diffusion_size, Attention(diffusion_size, heads = attn_heads, dim_head = attn_dim_head,**kwargs))) if use_attention else Residual(PreNorm(diffusion_size, StaticGraphLinear(diffusion_size, diffusion_size,bias=False, **kwargs))), + ])) + layerlist = [ResnetBlock(diffusion_size, diffusion_size, + time_emb_dim = time_dim, groups = resnet_block_groups, # bias=True, + **kwargs), + ] + if i!=depth-1: + layerlist.append( + Residual(PreNorm(diffusion_size, Attention(diffusion_size, heads = attn_heads, dim_head = attn_dim_head,**kwargs))) if use_attention else Residual(PreNorm(diffusion_size, StaticGraphLinear(diffusion_size, diffusion_size,bias=False, **kwargs))), + ) + else: + layerlist.append(nn.Identity()) + self.layers.append(nn.ModuleList(layerlist)) + + + out_dim = out_dim * (1 if not learned_variance else 2) + self.final_res_block = ResnetBlock(diffusion_size*2, diffusion_size, + time_emb_dim = time_dim, groups = resnet_block_groups, # bias=True, + **kwargs) + self.final_glin = StaticGraphLinear(diffusion_size, out_dim, bias=True, **kwargs) + + def forward(self, x, time, x_self_cond = None, x_cond=None): + + if self.self_condition: + x_self_cond = x_self_cond if x_self_cond is not None else torch.zeros_like(x) + x = torch.cat((x_self_cond, x), dim = -1) + if x_cond is not None: + x = torch.cat([x_cond, x], dim=-1) + + x = self.init_lin(x) + r = x.clone() + + t = self.time_mlp(time) + + + for block1, attn in self.layers: + x = block1(x, t) + x = attn(x) + + x = torch.cat((x, r), dim = -1) + + x = self.final_res_block(x, t) + return self.final_glin(x) \ No newline at end of file diff --git a/SkeletonDiffusion/src/core/trainer.py b/SkeletonDiffusion/src/core/trainer.py new file mode 100644 index 0000000000000000000000000000000000000000..c839d4338dd84d91464436fc41d136c05737723a --- /dev/null +++ b/SkeletonDiffusion/src/core/trainer.py @@ -0,0 +1,313 @@ +import torch +from ignite.engine import Engine, Events +from typing import Sequence +import numpy as np + +import math +from ignite.contrib.handlers import CosineAnnealingScheduler +from ema_pytorch import EMA +from torch.optim import Adam +from .utils.scheduler import LRScheduler + +If_NDEBUG = False + +def has_int_squareroot(num): + return (math.sqrt(num) ** 2) == num + +class AutoEncoderTrainer(object): + def __init__( + self, model: torch.nn.Module, + lr: float, + iter_per_epoch: int, + curriculum_it: int = 0, + clip_grad_norm: float = 1.0, + use_lr_scheduler: bool = False, + **config, + ): + self.model = model + self.config = config + self.clip_grad_norm = clip_grad_norm + self.iter_per_epoch = iter_per_epoch + + # Define optimizer + self.optimizer = torch.optim.AdamW(model.parameters(), lr=lr, amsgrad=True) + # assert _check_lr_scheduler_params(lr_scheduler_warmup, lr_scheduler_update_every) + self.lr_scheduler = LRScheduler(lr=lr, optimizer=self.optimizer, **config['lr_scheduler_kwargs']) if use_lr_scheduler else None + + class CurriculumLearning: + def __init__(self): + self.param_groups = [{'curriculum_factor': 0.}] + + self.curriculum = CurriculumLearning() + self.curriculum_it = curriculum_it + self.curriculum_scheduler = None + if curriculum_it is not None and curriculum_it > 0.0: + curriculum_scheduler = CosineAnnealingScheduler(self.curriculum, + 'curriculum_factor', + start_value=1.0, + end_value=0., + cycle_size=curriculum_it*iter_per_epoch, + start_value_mult=0.0, + save_history=True, + ) + self.curriculum_scheduler = curriculum_scheduler + + def objects_to_checkpoint(self): + # Define objecs to save in checkpoint + if self.curriculum_it is not None and self.curriculum_it > 0.0: + objects_to_checkpoint = {'optimizer': self.optimizer, 'curriculum_scheduler': self.curriculum_scheduler} #'lr_scheduler': lr_scheduler, + else: + objects_to_checkpoint = { 'optimizer': self.optimizer,} #'lr_scheduler': lr_scheduler, + print("no curriculum scheduler") + if self.lr_scheduler is not None: + objects_to_checkpoint = {**objects_to_checkpoint, **{'lr_scheduler': self.lr_scheduler.lr_scheduler}} + return objects_to_checkpoint + + def get_random_ph(self, engine): + if engine.state.epoch >= self.config["prediction_horizon_train_min_from_epoch"]: + ph_min = self.config["prediction_horizon_train_min"] + else: + ph_min_per_epoch = torch.linspace(start=1, end=self.config["prediction_horizon_train_min"],steps=self.config["prediction_horizon_train_min_from_epoch"]*self.iter_per_epoch, dtype=int) + ph_min = ph_min_per_epoch[engine.state.iteration] + # ph_range = prediction_horizon_train - ph_min + ph = max(int(np.rint((1. - self.curriculum.param_groups[0]['curriculum_factor']) * self.config['prediction_horizon_train'])), ph_min) + if ph > ph_min and self.config['random_prediction_horizon']: + ph = np.random.randint(ph_min, ph) + return ph + + # Define process function which is called during every training step + def train_step(self, engine: Engine, batch: Sequence[torch.Tensor]): + self.model.train() + self.optimizer.zero_grad() + x, y = batch + + ph = self.get_random_ph(engine) + y = y[:, :ph] + + pred, _, _ = self.model.autoencode(y,past=x, ph=ph) + + loss = self.model.loss(pred, y) + loss_pose_unscaled, loss_hip_unscaled = loss, 0. + + loss.backward() + if self.clip_grad_norm is not None: + torch.nn.utils.clip_grad_norm_(self.model.parameters(), self.clip_grad_norm) + self.optimizer.step() + return loss, loss_pose_unscaled, (loss_hip_unscaled, _), pred, y, ph + + def validation_step(self, engine: Engine, batch: Sequence[torch.Tensor]): + self.model.eval() + with torch.no_grad(): + x, y = batch + model_out, z_past, z = self.model.autoencode(y,past=x, ph=self.config['prediction_horizon_eval']) #model(x, y, prediction_horizon_eval, None) + return model_out, y, x, z + + +class TrainerDiffusion(object): + def __init__( + self, + diffusion_model: torch.nn.Module, + *, + device: "cpu", + lr = 1e-4, + weight_decay=0., + train_pick_best_sample_among_k = 1, + similarity_space = 'latent_space', # 'latent_space' or 'input_space' or 'metric_space + if_use_ema = True, + ema_update_every = 10, + ema_decay = 0.995, + ema_power = 2 / 3, + ema_min_value = 0.0, + step_start_ema: 100, + adam_betas = (0.9, 0.99), + use_lr_scheduler: bool = False, + num_samples = 25, + max_grad_norm = 1., + skeleton=None, + autoencoder=None, + **config, + + ): + # model + self.device = device + self.model = diffusion_model + assert self.model.condition + # self.channels = diffusion_model.channels + self.train_pick_best_sample_among_k = train_pick_best_sample_among_k + self.similarity_space = similarity_space + assert similarity_space in ['input_space', 'metric_space', 'latent_space'], f"Similarity space must be either 'input_space' or 'metric_space' or 'latent_space' but is {similarity_space}" + + self.skeleton = skeleton + self.autoencoder = autoencoder + self.config = config + + # sampling and training hyperparameters + + assert has_int_squareroot(num_samples), 'number of samples must have an integer square root' + self.num_samples = num_samples + + # self.batch_size = train_batch_size + self.max_grad_norm = max_grad_norm + + # optimizer + self.opt = Adam(diffusion_model.parameters(), lr = lr, betas = adam_betas, weight_decay=weight_decay) + + # for logging results in a folder periodically + + self.if_use_ema = if_use_ema + if if_use_ema: + self.ema = EMA(diffusion_model, beta = ema_decay, update_every = ema_update_every, update_after_step=step_start_ema, power=ema_power, min_value=ema_min_value) + self.ema.to(self.device) + self.lr_scheduler = LRScheduler(lr=lr, optimizer=self.opt, **config['lr_scheduler_kwargs']) if use_lr_scheduler else None + + # step counter state + self.step = 0 + self.statistics_pred = None + self.statistics_obs = None + + def get_checkpoint_object(self): + from denoising_diffusion_pytorch.version import __version__ + data = { + 'model': self.model, + 'opt': self.opt, + } + if self.if_use_ema: + data = {**data, **{'ema': self.ema}} + if self.lr_scheduler is not None: + data = {**data, **{'lr_scheduler': self.lr_scheduler.lr_scheduler}} + + return data + + + def to_comparison_space_train(self, samples:torch.Tensor, diff_input:torch.Tensor, past_seq:torch.Tensor, autoencoder:torch.nn.Module, fut_seq:torch.Tensor, + space='latent_space', x_cond:torch.Tensor=None): + # check dimensions of samples & other stuff + num_samples = samples.shape[0]//past_seq.shape[0] + x_cond = x_cond.repeat_interleave(num_samples, dim=0) + if space == 'input_space' or space == 'metric_space': + out, _ = self.decode_diffusion_sample(samples, obs=past_seq, autoencoder=autoencoder, x_cond=x_cond) + # where do we want to compute similarity? input space(dct, or normaliezed)? metric space (in m)? + if space == 'input_space': + out_comparespace = out + fut_seq_comparespace = fut_seq.unsqueeze(1).repeat_interleave(num_samples, dim=1) + elif space == 'metric_space': + # metric space we would need the skeleton + out_comparespace = self.skeleton.transform_to_metric_space(out) + fut_seq_comparespace = self.skeleton.transform_to_metric_space(fut_seq) + out_comparespace = out_comparespace.flatten(start_dim=3) + fut_seq_comparespace = fut_seq_comparespace.unsqueeze(1).flatten(start_dim=3).repeat_interleave(num_samples, dim=1) + elif space == 'latent_space': + out_comparespace = samples.view(diff_input.shape[0], -1, *samples.shape[1:]) + fut_seq_comparespace = diff_input.unsqueeze(1).repeat_interleave(num_samples, dim=1) + else: + assert 0, "Not implemented" + assert out_comparespace.shape == fut_seq_comparespace.shape + return out_comparespace, fut_seq_comparespace + + def get_ksimilarity_loss(self, diffusion_loss:torch.Tensor, out_comparespace:torch.Tensor, fut_seq_comparespace:torch.Tensor, autoencoder:torch.nn.Module=None, **kwargs): + b = out_comparespace.shape[0] + with torch.no_grad(): + # where do we want to compute similarity? input space(dct, or normaliezed)? metric space (in m)? + if self.similarity_space == 'input_space': + loss_similarity = autoencoder.loss(out_comparespace, fut_seq_comparespace, reduction="none") + elif self.similarity_space == 'metric_space': + loss_similarity = torch.linalg.norm(out_comparespace-fut_seq_comparespace, axis=-1).mean(axis=-1) + elif self.similarity_space == 'latent_space': + loss_similarity = diffusion_loss + else: + assert 0, "Not implemented" + closest2gt_idx = loss_similarity.view(b, -1).min(axis=-1).indices + loss = torch.gather(diffusion_loss.view(b, -1), dim=1, index=closest2gt_idx.unsqueeze(1)).squeeze(-1) + assert len(loss.shape) == 1 and loss.shape[0] == b + return loss, closest2gt_idx + + def loss(self, data:torch.Tensor, x_cond:torch.Tensor=None, current_epoch=None, **kwargs): + b = data.shape[0] + loss, diff_weights, samples = self.model(data, x_cond=x_cond, n_train_samples=self.train_pick_best_sample_among_k) + if self.train_pick_best_sample_among_k > 1: + out_similarityspace, fut_seq_similarityspace = self.to_comparison_space_train(samples, diff_input=data, x_cond=x_cond, space=self.similarity_space, **kwargs) + sim_loss, closest2gt_idx = self.get_ksimilarity_loss(loss, out_similarityspace, fut_seq_similarityspace, **kwargs) + else: + sim_loss = loss + sim_loss = sim_loss * diff_weights + + return sim_loss.mean(), None, None, None + + def train_step(self, engine: Engine, data: Sequence[torch.Tensor]): + autoencoder = self.autoencoder + if self.if_use_ema: + self.ema.ema_model.train() + self.model.train() + self.opt.zero_grad() + + with torch.no_grad(): + autoencoder.eval() + x, y = data + z_past, z = autoencoder.get_train_embeddings(y, past=x, state=None) + + # Define diffusion objective + diffusion_gt, x_cond = z, z_past + + loss, _, _, _ = self.loss(diffusion_gt, x_cond=x_cond, autoencoder=autoencoder, past_seq=x, fut_seq=y, current_epoch=engine.state.epoch) if self.model.condition else self.loss(diffusion_gt, current_epoch=engine.state.epoch) + total_loss = loss.item() + if If_NDEBUG: + if torch.isnan(loss).any(): + import numpy as np + import os + mode = 'wb' + myfile = f"debug/latest_run/diffusion/{engine.state.iteration}" + os.makedirs(myfile) + torch.save(self.model.state_dict(), os.path.join(myfile, f"checkpoint.pth.tar")) + myfile = [myfile+"loss.npy", myfile+"target.npy", myfile+"h.npy", myfile+"z.npy", myfile+"x.npy"] + myouts = [loss, y, z, z_past, x] + for fpath, outensor in zip(myfile, myouts): + with open(fpath, mode) as f: + np.save( f, outensor.detach().cpu().numpy()) + + loss.backward() + torch.nn.utils.clip_grad_norm_(self.model.parameters(), self.max_grad_norm) + + self.opt.step() + self.opt.zero_grad() + self.step += 1 + + if self.if_use_ema: + self.ema.update() + return total_loss, None, None, None + + def decode_diffusion_sample(self, samples:torch.Tensor, obs:torch.Tensor, autoencoder:torch.nn.Module, x_cond:torch.Tensor=None): + + x_t = obs.repeat_interleave(samples.shape[0]//obs.shape[0], dim=0) + + z_past, z = x_cond, samples + out = autoencoder.decode(x_t, z, z_past, self.config['prediction_horizon_eval']) + + out =out.view(obs.shape[0], -1, *out.shape[1:]) # (batch, num_samples, T, J, 3) + samples = samples.view(obs.shape[0], -1, *samples.shape[1:]) + return out, samples + + def validation_step(self, engine: Engine, batch: Sequence[torch.Tensor]): + autoencoder = self.autoencoder + if self.if_use_ema: + self.ema.ema_model.eval() + self.model.eval() + with torch.no_grad(): + x, y = batch + autoencoder.eval() + if self.model.condition: + past_embedding = autoencoder.get_past_embedding(x) + x_cond = past_embedding + x_cond = x_cond.repeat_interleave(self.config['num_prob_samples'], dim=0) + else: + x_cond = None + + if self.if_use_ema: + samples, _ = self.ema.ema_model.sample(batch_size=self.config['num_prob_samples']*x.shape[0], x_cond=x_cond) + else: + samples, _ = self.model.sample(batch_size=self.config['num_prob_samples']*x.shape[0], x_cond=x_cond) + + + out, samples = self.decode_diffusion_sample(samples, obs=x, autoencoder=autoencoder, x_cond=x_cond) + + return out, y, samples, x + diff --git a/SkeletonDiffusion/src/core/utils/scheduler.py b/SkeletonDiffusion/src/core/utils/scheduler.py new file mode 100644 index 0000000000000000000000000000000000000000..d0b14ebe01ae9be5e50aa7927a82dc4255baa19c --- /dev/null +++ b/SkeletonDiffusion/src/core/utils/scheduler.py @@ -0,0 +1,50 @@ +from ignite.engine import Engine, Events +from torch.optim.lr_scheduler import ExponentialLR +from ignite.handlers import create_lr_scheduler_with_warmup + +class ExponentialLRSchedulerWarmup(object): + def __init__( + self, + lr: float, + optimizer, + warmup_duration: int = 200, + update_every: int = 1, + min_lr: float = 0., + gamma_decay: float = 0.98, + **kwargs + ): + assert min_lr is None or min_lr <= lr + self.minimal_lr_reached = False + self.lr = lr + self.lr_scheduler_warmup = warmup_duration + self.lr_scheduler_min_lr = min_lr + self.lr_scheduler_update_every = update_every + self.optimizer = optimizer + self.torch_lr_scheduler = ExponentialLR(optimizer=optimizer, gamma=gamma_decay) + self.lr_scheduler = create_lr_scheduler_with_warmup(self.torch_lr_scheduler, + warmup_start_value=lr, + warmup_end_value=lr, + warmup_duration=warmup_duration) #warm-up phase duration, number of events. + + def step(self, engine: Engine): + if engine.state.epoch 1: + mean_vel += ((np.diff(output[dataset][file_idx], axis=0)** 2).sum(axis=-1)**0.5).mean() + + counter += 1 + n_frames += len(seq) + + print(f"Processed total {counter} sequences.") + print(f"Total number of frames: {n_frames}") + print("Mean velocity:", mean_vel/counter) + print(f'Saving into "{output_path}"...') + np.savez_compressed(output_path, positions_3d=output) + return output + +amass_official_splits = { + 'validation': ['HumanEva', 'MPI_HDM05', 'SFU', 'MPI_mosh'], + 'test': ['Transitions_mocap', 'SSM_synced'], + 'train': ['CMU', 'MPI_Limits', 'TotalCapture', 'Eyes_Japan_Dataset', 'KIT', 'BML', 'EKUT', 'TCD_handMocap', 'ACCAD']# + } + + +# python -m data_loader.parsers.amass --gpu +# it will pre-process the AMASS dataset +if __name__ == '__main__': + + parser = argparse.ArgumentParser(description='AMASS Process Raw Data') + + parser.add_argument('--fps', + type=int, + default=60, + help='FPS') + + parser.add_argument('--datasets', + type=str, + nargs="+", + help='The names of the datasets to process', + default=None) + + parser.add_argument('-gpu', '--gpu', action='store_true', help='Use GPU for processing') + + parser.add_argument('-extract_zip', '--extract_zip', action='store_true', help='Extract all tar.bz2 files in the datasets folder and create zarr files') + + args = parser.parse_args() + + fps = args.fps + FPS = fps + datasets = args.datasets + # IF_EXTRACT_ZIP = args.extract_zip + include_hands = False + + num_joints = 22 if not include_hands else 22+30 + dataset_name = "AMASS" if not include_hands else "AMASS-MANO" + batch_size = 128 + original_folder = f"../datasets/raw/AMASS/" + annotations_folder = f"../datasets/annotations&interm/{dataset_name}/dataset" + annotations_folder_csv = f"../datasets/annotations&interm/{dataset_name}" + precomputed_folder = f"../datasets/processed/{dataset_name}/" + models_dir = f'../datasets/annotations&interm/AMASS/bodymodels/' + stride = 10 + augmentation = 0 + + multimodal_threshold = 0.4 # as in BeLFusion + + + comp_device = 'cpu' if not args.gpu else 'cuda' + print("Using device:", comp_device) + + if IF_EXTRACT_ZIP: + # list all datasets + print("Datasets to process:") + print(f"Extracting all tar.bz2 files from the datasets folder {original_folder} and create zarr files {annotations_folder}") + print(datasets) + extract_dataset(original_folder, annotations_folder, models_dir, datasets) + + + dataset_training = ["ACCAD", "BMLhandball", "BMLmovi", "BMLrub", "CMU", "EKUT", "EyesJapanDataset", "KIT", "PosePrior", "TCDHands", "TotalCapture"] + dataset_validation = [ "HumanEva", "HDM05", "SFU", "MoSh" ] + dataset_test = ['DFaust', 'DanceDB', 'GRAB', 'HUMAN4D', 'SOMA', 'SSM', 'Transitions'] + + datasets = [*dataset_training, *dataset_validation, *dataset_test] + + + + np.random.seed(0) + + file_idces = "all" + + for task in ["hmp"]: + if_consider_hip = True if task == "motpred" else False + precomputed_folder_task = f"{precomputed_folder}/{task}/" + annotations_folder_task = os.path.join(annotations_folder_csv, task) + os.makedirs(precomputed_folder, exist_ok=True) + + try: + sequences = create_npz_dataset_file(datasets, annotations_folder, precomputed_folder_task, num_joints=num_joints) + except Exception as e: + print(e) + + if task == "hmp": + obs_length = 30 + pred_length = 120 + else: + obs_length = 30 + pred_length = 120 + # obs_length = 60 + # pred_length = 240 + + + """ + for datasets in ["training", "validation", "test"]: + # count number of samples + stride = 150 + data_loader = AMASSDataLoader(batch_size, annotations_folder, precomputed_folder, + obs_length, pred_length, drop_root=True, + datasets=eval(datasets), file_idces=file_idces, drop_last=False, + stride=stride, shuffle=False, augmentation=0, normalize_data=False, + dtype="float32") + print("Number of samples in {}: {}".format(datasets, len(data_loader.dataset))) + """ + + print("="*50) + print("Computing values for CMD.") + segments_path = os.path.join(annotations_folder_csv, task, "segments_test.csv") + # segments_path = os.path.join(annotations_folder_csv, task)+f"/segments_{(obs_length//FPS) if obs_length%FPS==0 else round(obs_length/FPS, 1)}s-{pred_length//FPS}s_test.csv" + # below to compute the average motion per class for the TEST set, for the CMD computation + # def return_skeletons_for_stats_funct(current_task): + # def partialize_skel_class(skel_class): + # return partial(skel_class, obs_length=obs_length, pred_length=pred_length, num_joints=num_joints,) + # if current_task == "hmp": + # skeletons = [partialize_skel_class(AMASSSkeletonCenterPoseAlignSeqStart), None] + # else: + # skeletons = [partialize_skel_class(AMASSSkeletonVanillaAlignSeqStart), partialize_skel_class(AMASSSkeletonCenterPoseAlignSeqStart)] + # return skeletons + # compute_stats(precomputed_folder=precomputed_folder_task, + # Dataset=partial(AMASSDataset,annotations_folder=annotations_folder_task, datasets=dataset_test, file_idces=file_idces, stride=stride, segments_path=segments_path, obs_length=obs_length, pred_length=pred_length), + # Skeleton=return_skeletons_for_stats_funct(task), + # if_consider_hip=if_consider_hip, batch_size=batch_size) + + if task == "hmp": + skeleton= AMASSSkeletonCenterPoseAlignSeqStart(if_consider_hip=if_consider_hip, obs_length=obs_length, pred_length=pred_length, file_idces=file_idces, num_joints=num_joints) #H36MSkeletonCenterPose + else: + skeleton= AMASSSkeletonCenterPoseAlignSeqStart(if_consider_hip=False, obs_length=obs_length, pred_length=pred_length, file_idces=file_idces, num_joints=num_joints) + multimodal_threshold = 0.79 + Dataset=partial(AMASSDataset, skeleton=skeleton, obs_length=obs_length, pred_length=pred_length, if_consider_hip=False, + file_idces=file_idces, stride=stride) + print("="*50) + print(f"Computing Multimodal Ground Truth for task {task}.") + def create_dataset(split, **kwargs): + if split=="train": + return Dataset(datasets=dataset_training, split=split, **kwargs) + elif split=="test": + return Dataset(datasets=dataset_test, split=split, **kwargs) + elif split=="valid": + return Dataset(datasets=dataset_validation, split=split, **kwargs) + compute_multimodal_gt(Dataset=create_dataset, + multimodal_threshold=multimodal_threshold, segment_path_affix= f"segments_{(obs_length//FPS) if obs_length%FPS==0 else round(obs_length/FPS, 1)}s-{pred_length//FPS}s", + annotations_folder=annotations_folder_task, precomputed_folder=precomputed_folder_task, + ) \ No newline at end of file diff --git a/SkeletonDiffusion/src/data/create_freeman_dataset.py b/SkeletonDiffusion/src/data/create_freeman_dataset.py new file mode 100644 index 0000000000000000000000000000000000000000..e2e89d98619ea7eac39eab7650d5266d8b40a75b --- /dev/null +++ b/SkeletonDiffusion/src/data/create_freeman_dataset.py @@ -0,0 +1,195 @@ +import os +import numpy as np +from tqdm import tqdm +import json +import ast +from torch.utils.data import DataLoader +from functools import partial + +import sys +from ...base.create_dataset_utils import compute_stats, compute_multimodal_gt +from .dataset import FreeManDataset +from .skeleton import FreeManSkeletonCenterPoseAlignSeqStart, FreeManSkeletonVanillaAlignSeqStart + +IF_NDEBUG = False + +OUTPUT_3D = 'data_3d_freeman' + +def remove_illposedframes(seq_name, kpts, illposed_at_seq_startend): + + if seq_name in illposed_at_seq_startend: + s = illposed_at_seq_startend[seq_name] + if len(s) > 1: + new_kpts = [] + for i in range(len(s)): + slice = kpts[s[i][0]:s[i][1]] + assert np.isnan(slice).sum() == 0 + new_kpts.append(slice) + else: + new_kpts = kpts[s[0][0]:s[0][1]] + assert np.isnan(new_kpts).sum() == 0 + return new_kpts, [s[i][0] for i in range(len(s))] + return kpts, 0 + +def preprocess_kpts(positions): + assert not np.isnan(positions).any(), "Sequence has nan!" + # invert joint order such thta hip is first + # JOINTS_DICT_FREEMAN_17 = {0: "Nose", + # 1: "LEye", 2: "REye", 3: "LEar", 4: "REar", + # 5: "LShoulder", 6: "RShoulder", 7: "LElbow", 8: "RElbow", + # 9: "LWrist", 10: "RWrist", + # 11: "LHip", 12: "RHip", 13: "LKnee", + # 14: "RKnee", 15: "LAnkle", 16: "RAnkle"} + positions = np.concatenate([positions[..., 11:, :], positions[..., :11, :]], axis=-2) + # add center hip + positions = np.concatenate([positions[..., 0:1, :] + (positions[..., 1:2, :] - positions[..., 0:1, :])/2, positions], axis=-2) + positions /= 100 # Meters instead of centimeters + positions[..., 2] *= -1 # Invert y axis + return positions + +def preprocess_dataset(dataset_folder, annotation_folder, output_path=OUTPUT_3D, task="hmp"): + dataset_folder = os.path.abspath(dataset_folder) + if os.path.exists(f"{output_path}.npz"): + # print('The dataset already exists at', output_path) + raise Exception(f'The dataset already exists at {output_path}') + + print('Converting original FreeMan dataset from', dataset_folder, 'for task ', task, 'into', output_path, '...') + + with open(os.path.join(annotation_folder, 'ignore_list.txt')) as f: + ignore_files = set([line.strip() for line in f]) #f.readlines() + with open(os.path.join(annotation_folder, f"bad_sequences.json"), 'r') as outfile: + sequences_with_no_good_frames = json.load(outfile) + ignore_files = ignore_files.union(sequences_with_no_good_frames) + + with open(os.path.join(annotation_folder, f"illlposed_slices_idxs.json"), 'r') as outfile: + illposed_at_seq_startend = ast.literal_eval(json.load(outfile)) + + sequences = [file.strip('.npy') for file in os.listdir(os.path.join(dataset_folder, 'keypoints3d')) if (file.endswith('.npy') and file.strip('.npy') not in ignore_files)] # file = 'keypoints3d/20220818_857ffafc02_subj22.npy' pattern + file2action = {} + with open(os.path.join(annotation_folder, 'seq_actions_labels.txt')) as f: + for line in f: + name, label = line.strip().split(',') + file2action[name] = label + canonical_name = name.split('_slice')[0] + if canonical_name not in file2action: + file2action[canonical_name] = label + + if task == "motpred": + with open(os.path.join(annotation_folder, 'allowed_actions_motpred.txt')) as f: + allowed_actions = [line.strip() for line in f] #f.readlines() + sequences = [file for file in sequences if file in file2action] + assert all([file2action[file] in allowed_actions for file in sequences]), "Some sequences are not in the allowed actions for motpred task." + + output = {} + count = 0 + subseq_count = 0 + n_frames = 0 + for seq in tqdm(sequences): + f = os.path.join(dataset_folder, 'keypoints3d', seq+ '.npy') + kpts3d = np.load(f, allow_pickle=True) + + if 'keypoints3d_smoothnet32' in kpts3d[0].keys(): + positions = kpts3d[0]['keypoints3d_smoothnet32'] + elif 'keypoints3d_smoothnet' in kpts3d[0].keys(): + positions = kpts3d[0]['keypoints3d_smoothnet'] # change here if you want to load keypoints3d_smoothnet, keypoints3d_smoothnet32 or keypoints3d_optim + else: + positions = kpts3d[0]['keypoints3d_optim'] + + clean_seq, s = remove_illposedframes(seq, positions, illposed_at_seq_startend) + if isinstance(clean_seq, list): + for i, kpts in enumerate(clean_seq): + slice_name = f"{seq}_slice{i+1}" + if slice_name in file2action: + # Too short discarded slices sequences will not be considered + kpts = preprocess_kpts(kpts) + output[slice_name] = kpts.astype('float32') + subseq_count += 1 + n_frames += kpts.shape[0] + else: + kpts = preprocess_kpts(clean_seq) + output[seq] = kpts.astype('float32') + count += 1 + n_frames += kpts.shape[0] + if seq not in file2action: + print(f"Warning: {seq} not in file2action") + + print(f"Processed total {count+subseq_count} sequences. {count} original sequences or sequences sclied at beginning or end and {subseq_count} sub-sequences obtained by slicing.") + print(f"Total number of frames: {n_frames}") + print(f'Saving into "{output_path}"...') + np.savez_compressed(output_path, positions_3d=output) + print('Done.') + return sequences + +import argparse + + +# python -m data_loader.h36m +if __name__ == '__main__': + + parser = argparse.ArgumentParser(description='FreeMan Process Raw Data') + + parser.add_argument('-gpu', '--gpu', action='store_true', help='Use GPU for processing') + + args = parser.parse_args() + + np.random.seed(0) + + actions = "all" + + comp_device = 'cpu' if not args.gpu else 'cuda' + print("Using device:", comp_device) + + batch_size = 128 + original_folder = "../datasets/raw/FreeMan" + annotations_folder = "../datasets/annotations&interm/FreeMan" + stride = 1 + augmentation = 0 + multimodal_threshold = 0.5 + FPS = 30 + + # precompute data and statistics + for task in ["hmp"]: + if_consider_hip = True if task == "motpred" else False + precomputed_folder = f"../datasets/processed/FreeMan/{task}/" + annotations_folder_task = os.path.join(annotations_folder, task) + os.makedirs(precomputed_folder, exist_ok=True) + + if task == "hmp": + obs_length = 15 + pred_length = 60 + else: + obs_length = 30 + pred_length = 120 + + try: + sequences = preprocess_dataset(original_folder, annotations_folder_task, output_path=os.path.abspath(os.path.join(precomputed_folder, OUTPUT_3D)), task=task) + except Exception as e: + print(e) + + print("="*50) + print("Computing stats and values for CMD.") + segments_path = os.path.join(annotations_folder_task, "segments_test.csv") + # below to compute the average motion per class for the TEST set, for the CMD computation + def return_skeletons_for_stats_funct(current_task): + def partialize_skel_class(skel_class): + return partial(skel_class, obs_length=obs_length, pred_length=pred_length) + skeletons = [partialize_skel_class(FreeManSkeletonCenterPoseAlignSeqStart), None] + return skeletons + + compute_stats(precomputed_folder=precomputed_folder, + Dataset=partial(FreeManDataset,annotations_folder=annotations_folder_task, actions=actions, stride=stride, segments_path=segments_path, obs_length=obs_length, pred_length=pred_length), + Skeleton=return_skeletons_for_stats_funct(task), + if_consider_hip=if_consider_hip, + batch_size=batch_size) + print("="*50) + print(f"Computing Multimodal Ground Truth for task {task}.") + + skeleton= FreeManSkeletonCenterPoseAlignSeqStart( if_consider_hip=False, obs_length=obs_length, pred_length=pred_length, actions=actions) + compute_multimodal_gt( Dataset=partial(FreeManDataset, skeleton=skeleton, obs_length=obs_length, pred_length=pred_length, if_consider_hip=False, + actions=actions, stride=stride), + multimodal_threshold=multimodal_threshold, segment_path_affix= f"segments_test", + annotations_folder=annotations_folder_task, precomputed_folder=precomputed_folder, + ) + + + diff --git a/SkeletonDiffusion/src/data/create_h36m_dataset.py b/SkeletonDiffusion/src/data/create_h36m_dataset.py new file mode 100644 index 0000000000000000000000000000000000000000..f5fae1166c52b3611acbbc0cbde0aec70eb669dd --- /dev/null +++ b/SkeletonDiffusion/src/data/create_h36m_dataset.py @@ -0,0 +1,201 @@ +import os +import numpy as np +from tqdm import tqdm +import cdflib +from glob import glob +from functools import partial + +from .joint_correspondence_utils import CONVERSION_IDX_H36M_32TO17, CONVERSION_IDX_H36M_32TO25 +from .dataset import H36MDataset +# from .skeleton import H36MSkeletonVanillaAlignSeqStart, H36MSkeletonCenterPoseAlignSeqStart +from ...base.create_dataset_utils import compute_stats, compute_multimodal_gt, compute_multimodal_gt_onsplit + +IF_NDEBUG = False + +OUTPUT_3D = 'data_3d_h36m' +SUBJECTS = ['S1', 'S5', 'S6', 'S7', 'S8', 'S9', 'S11'] + + + +def preprocess_dataset(dataset_folder, num_joints=17, output_path=OUTPUT_3D, subjects=SUBJECTS): + + if os.path.exists(f"{output_path}.npz"): + print('The dataset already exists at', f"{output_path}.npz") + raise Exception(f'The dataset already exists at {output_path}') + + print('Converting original H36M dataset from', dataset_folder) + output = {} + count = 0 + nframes = 0 + mean_vel = 0 + + for subject in tqdm(subjects): + output[subject] = {} + file_list = glob(os.path.join(os.path.abspath(dataset_folder), subject, 'MyPoseFeatures', 'D3_Positions', '*.cdf')) + assert len(file_list) == 30, "Expected 30 files for subject " + subject + ", got " + str(len(file_list)) + for f in file_list: + action = os.path.splitext(os.path.basename(f))[0] + + if subject == 'S11' and action == 'Directions': + continue # Discard corrupted video + + # Use consistent naming convention + canonical_name = action.replace('TakingPhoto', 'Photo') \ + .replace('WalkingDog', 'WalkDog').replace(' ', '_') + + hf = cdflib.CDF(f) + positions = hf['Pose'].reshape(-1, 32, 3) + if num_joints == 17: + positions = positions[:, CONVERSION_IDX_H36M_32TO17, :] + elif num_joints == 25: + positions = positions[:, CONVERSION_IDX_H36M_32TO25, :] + else: + assert 0, "Not implemented for this number of joints" + + positions /= 1000 # Meters instead of millimeters + output[subject][canonical_name] = positions.astype('float32') + if len(output[subject][canonical_name]) > 1: + mean_vel += ((np.diff(output[subject][canonical_name], axis=0)** 2).sum(axis=-1)**0.5).mean() + + count += 1 + nframes += positions.shape[0] + + print(f"Processed total {count} sequences.") + print("Mean velocity:", mean_vel/count) + print(f"Total number of frames: {nframes}") + print(f'Saving into "{output_path}"...') + np.savez_compressed(output_path, positions_3d=output) + print('Done.') + +# def compute_stats(annotations_folder, precomputed_folder, segments_path, if_consider_hip, num_joints, obs_length, pred_length, batch_size = 128): +# np.random.seed(0) + +# skeleton = H36MSkeletonVanilla(if_consider_hip=if_consider_hip, obs_length=obs_length, pred_length=pred_length, num_joints=num_joints) +# dataset = H36MDataset(annotations_folder, split='test', skeleton=skeleton, precomputed_folder=precomputed_folder, +# obs_length=obs_length, pred_length=pred_length, if_consider_hip=if_consider_hip, segments_path=segments_path, subjects=SUBJ_test, +# actions=actions, stride=stride, augmentation=0, da_mirroring=0.0, da_rotations=0.0, +# dtype="float32") + +# class_average_3d, list_of_motions_3d, frequencies = compute_mean_motions(dataset, batch_size=batch_size) +# with open(os.path.join(precomputed_folder, "mean_motion_test.txt"), 'w') as filehandle: +# filehandle.write('\n'.join([f"{c},{meanmot},{freq}" for c, meanmot, freq in zip(list(class_average_3d.keys()), list_of_motions_3d, frequencies)])) + +# if if_consider_hip == True: # dataset must deliver items with hip +# class_average_3d, list_of_motions_3d, frequencies = compute_mean_motions(dataset, batch_size=batch_size, if_traj_only=True) +# with open(os.path.join(precomputed_folder, "mean_motion_traj_test.txt"), 'w') as filehandle: +# filehandle.write('\n'.join([f"{c},{meanmot},{freq}" for c, meanmot, freq in zip(list(class_average_3d.keys()), list_of_motions_3d, frequencies)])) +# # compute stats for centered pose +# if_consider_hip = False +# skeleton = H36MSkeletonCenterPose(if_consider_hip=if_consider_hip, obs_length=obs_length, pred_length=pred_length, num_joints=num_joints) +# dataset = H36MDataset(annotations_folder, split='test', skeleton=skeleton, precomputed_folder=precomputed_folder, +# obs_length=obs_length, pred_length=pred_length, if_consider_hip=if_consider_hip, segments_path=segments_path, subjects=SUBJ_test, +# actions=actions, stride=stride, augmentation=0, da_mirroring=0.0, da_rotations=0.0, +# dtype="float32") + +# class_average_3d, list_of_motions_3d, frequencies = compute_mean_motions(dataset, batch_size=batch_size) +# with open(os.path.join(precomputed_folder, "mean_motion_pose_test.txt"), 'w') as filehandle: +# filehandle.write('\n'.join([f"{c},{meanmot},{freq}" for c, meanmot, freq in zip(list(class_average_3d.keys()), list_of_motions_3d, frequencies)])) +# # print(f"Mean motion values for {len(list_of_motions_3d)} classes (actions={data_loader.dataset.idx_to_class}):\n", [float(l) for l in list_of_motions_3d]) +# # print(frequencies) + +import argparse + + +# python -m data_loader.h36m +if __name__ == '__main__': + + parser = argparse.ArgumentParser(description='FreeMan Process Raw Data') + + parser.add_argument('-gpu', '--gpu', action='store_true', help='Use GPU for processing') + + args = parser.parse_args() + + np.random.seed(0) + comp_device = 'cpu' if not args.gpu else 'cuda' + print("Using device:", comp_device) + + SUBJ_training = ["S1", "S5", "S6", "S7", "S8"] + SUBJ_valid = ["S8"] + SUBJ_test = ["S9", "S11"] + actions = "all" + + batch_size = 128 + original_folder = "../datasets/raw/Human36M/" + annotations_folder = "../datasets/annotations&interm/Human36M/" + FPS = 50 + stride = 1 # or 10???? + augmentation = 0 + multimodal_threshold = 0.5 + + # precompute data and statistics + for task in ["hmp", "motpred"]: + if_consider_hip = True if task == "motpred" else False + precomputed_folder = f"../datasets/processed/Human36M/{task}/" + annotations_folder_task = os.path.join(annotations_folder, task) + os.makedirs(precomputed_folder, exist_ok=True) + + if task == "hmp": + obs_length = 25 + pred_length = 100 + num_joints = 17 + else: + obs_length = 25 + pred_length = 100 + num_joints = 17 + # obs_length = 50 + # pred_length = 200 + # num_joints = 25 + + # if IF_NDEBUG: + # sequences = preprocess_dataset(original_folder, output_path=os.path.abspath(os.path.join(precomputed_folder, OUTPUT_3D)), num_joints=num_joints, subjects=SUBJECTS) + # else: + try: + sequences = preprocess_dataset(original_folder, output_path=os.path.abspath(os.path.join(precomputed_folder, OUTPUT_3D)), num_joints=num_joints, subjects=SUBJECTS) + except Exception as e: + print(e) + + if not IF_NDEBUG: + print("="*50) + print("Computing values for CMD.") + segments_path = os.path.join(annotations_folder_task, "segments_test.csv") + + # segments_path = annotations_folder_task+f"/segments_{(obs_length//FPS) if obs_length%FPS==0 else round(obs_length/FPS, 1)}s-{pred_length//FPS}s_test.csv" + # below to compute the average motion per class for the TEST set, for the CMD computation + def return_skeletons_for_stats_funct(current_task): + def partialize_skel_class(skel_class): + return partial(skel_class, obs_length=obs_length, pred_length=pred_length, num_joints=num_joints,) + if current_task == "hmp": + skeletons = [partialize_skel_class(H36MSkeletonCenterPoseAlignSeqStart), None] + else: + skeletons = [partialize_skel_class(H36MSkeletonVanillaAlignSeqStart), partialize_skel_class(H36MSkeletonCenterPoseAlignSeqStart)] + return skeletons + compute_stats(precomputed_folder=precomputed_folder, + Dataset=partial(H36MDataset,annotations_folder=annotations_folder_task, num_joints=num_joints, subjects=SUBJ_test, actions=actions, stride=stride, segments_path=segments_path, obs_length=obs_length, pred_length=pred_length), + Skeleton=return_skeletons_for_stats_funct(task), + if_consider_hip=if_consider_hip, batch_size=batch_size) + if task == "hmp": + skeleton= H36MSkeletonCenterPoseAlignSeqStart(if_consider_hip=if_consider_hip, obs_length=obs_length, pred_length=pred_length, num_joints=num_joints, actions=actions) #H36MSkeletonCenterPose + else: + skeleton= H36MSkeletonCenterPoseAlignSeqStart(if_consider_hip=False, obs_length=obs_length, pred_length=pred_length, num_joints=num_joints, actions=actions) + multimodal_threshold = 0.79 + Dataset=partial(H36MDataset, skeleton=skeleton, obs_length=obs_length, pred_length=pred_length, if_consider_hip=False, + actions=actions, stride=stride) + print("="*50) + print(f"Computing Multimodal Ground Truth for task {task}.") + def create_dataset(split, **kwargs): + if split=="train": + return Dataset(subjects=SUBJ_training, split=split, **kwargs) + elif split=="test": + return Dataset(subjects=SUBJ_test, split=split, **kwargs) + elif split=="valid": + return Dataset(subjects=SUBJ_valid, split=split, **kwargs) + compute_multimodal_gt(Dataset=create_dataset, + multimodal_threshold=multimodal_threshold, segment_path_affix= f"segments_{(obs_length//FPS) if obs_length%FPS==0 else round(obs_length/FPS, 1)}s-{pred_length//FPS}s", + annotations_folder=annotations_folder_task, precomputed_folder=precomputed_folder, + ) + # compute_multimodal_gt_onsplit(Dataset=partial(Dataset, subjects=["S1", "S5", "S6", "S7"], split='train', + # annotations_folder=annotations_folder_task, precomputed_folder=precomputed_folder,segments_path = None), + # dest_path=os.path.join(precomputed_folder, f"mmgt_train_noS8.txt"), + # multimodal_threshold=multimodal_threshold) + # Average number of similar trajectories test: 2.7373737373737375. Standard deviation: 0.00044074964405339107 + # Average number of similar trajectories valid: 3.302795954788816. Standard deviation: 0.0021425754636556433 diff --git a/SkeletonDiffusion/src/data/loaders/__init__.py b/SkeletonDiffusion/src/data/loaders/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..03fdb291259e025583856669e6a7ae343387b299 --- /dev/null +++ b/SkeletonDiffusion/src/data/loaders/__init__.py @@ -0,0 +1,8 @@ +from .freeman import FreeManDataset +from .h36m import H36MDataset +from .amass import AMASSDataset +from .amass_zeroshot import ZeroShotAMASSDataset +from .base import custom_collate_for_mmgt + +class D3PWZeroShotDataset(ZeroShotAMASSDataset): + dataset_name = '3dpw' \ No newline at end of file diff --git a/SkeletonDiffusion/src/data/loaders/amass.py b/SkeletonDiffusion/src/data/loaders/amass.py new file mode 100644 index 0000000000000000000000000000000000000000..a45d92a240a0706f165b4f8936e8ea1ce80bbeaa --- /dev/null +++ b/SkeletonDiffusion/src/data/loaders/amass.py @@ -0,0 +1,104 @@ +import numpy as np +import os + +import pandas as pd +from .base import MotionDataset + +amass_official_splits = { + 'validation': ['HumanEva', 'MPI_HDM05', 'SFU', 'MPI_mosh'], + 'test': ['Transitions_mocap', 'SSM_synced'], + 'train': ['CMU', 'MPI_Limits', 'TotalCapture', 'Eyes_Japan_Dataset', 'KIT', 'BML', 'EKUT', 'TCD_handMocap', 'ACCAD']# + } + +class AMASSDataset(MotionDataset): + def __init__(self, datasets, *args, file_idces='all', if_long_term_test=False, long_term_factor=4, **kwargs): + + + self.datasets, self.file_idces = datasets, file_idces + assert self.file_idces == "all", "We only support 'all' files for now" + + self.FPS = 60 + + self.dict_indices = {} # dict_indices[dataset][file_idx] indicated idx where dataset-file_idx annotations start. + self.mm_indces = None + self.metadata_class_idx = 0 # 0: dataset, 1: filename --> dataset is the class used for metrics computation + self.idx_to_class = ['DFaust', 'DanceDB', 'GRAB', 'HUMAN4D', 'SOMA', 'SSM', 'Transitions'] + self.class_to_idx = {v: k for k, v in enumerate(self.idx_to_class)} + self.if_long_term_test = if_long_term_test + self.long_term_factor = long_term_factor + # self.mean_motion_per_class = [0.004860274970204714, 0.00815901767307159, 0.001774023530090276, 0.004391708416532331, 0.007596136106898701, 0.00575787090703614, 0.008530069935655568] + + pred_length = kwargs['pred_length'] + self.pred_length = pred_length if not self.if_long_term_test else int(pred_length * self.long_term_factor) + kwargs['pred_length'] = self.pred_length + super().__init__(datasets=datasets, **kwargs) + assert (datasets is not None and file_idces is not None) or self.segments_path is not None + + + def _prepare_data(self, num_workers=8): + if self.segments_path: + self.segments, self.segment_idx_to_metadata = self._load_annotations_and_segments(self.segments_path, num_workers=num_workers) + self.stride = 1 + self.augmentation = 0 + else: + self.annotations = self._read_all_annotations(self.datasets, self.file_idces) + self.segments, self.segment_idx_to_metadata = self._generate_segments() + + def _read_all_annotations(self, datasets, file_idces): + preprocessed_path = os.path.join(self.precomputed_folder, f'data_3d_amass.npz') + if not os.path.exists(self.precomputed_folder): + raise NotImplementedError("Preprocessing of AMASS dataset is not implemented yet. Please use the preprocessed data.") + + # we load from already preprocessed dataset + data_o = np.load(preprocessed_path, allow_pickle=True)['positions_3d'].item() + + anns_all = [] + self.dict_indices = {} + self.clip_idx_to_metadata = [] + counter = 0 + n_frames = 0 + + print("Loading datasets: ", datasets, file_idces) + for dataset in datasets: + self.dict_indices[dataset] = {} + + # we build the feature vectors for each dataset and file_idx + #print(z_poses.shape, z_trans.shape, z_index.shape, z_index[-1]) + for file_idx in list(data_o[dataset].keys()): + + seq =data_o[dataset][file_idx] + + self.dict_indices[dataset][file_idx] = counter + self.clip_idx_to_metadata.append((dataset, str(file_idx))) + counter += 1 + n_frames += len(seq) + + anns_all.append(seq.astype(self.dtype)) # datasets axis expanded + + # self._generate_statistics_full(anns_all) + centered_anns = [ann - ann[0:1, 0:1, :] for ann in anns_all] + centered_cat_anns = np.concatenate(centered_anns , axis=0) + centered_cat_anns_no_trans = centered_cat_anns - centered_cat_anns[:, 0:1, :] + # print("min and max values of centered sequences: ", centered_cat_anns_no_trans .max(), centered_cat_anns_no_trans .min()) + # test 1.095772 -1.0687416 + # train 1.1635599 -1.12504 + # valid 1.1759695 -1.1325874 + return anns_all + + def _load_annotations_and_segments(self, segments_path, num_workers=8): + assert os.path.exists(segments_path), "The path specified for segments does not exist: %s" % segments_path + df = pd.read_csv(segments_path) + # columns -> dataset,file,file_idx,pred_init,pred_end + datasets, file_idces = list(df["dataset"].unique()), list(df["file_idx"].unique()) + self.annotations = self._read_all_annotations(datasets, "all")#file_idces) + + segments = [(self.dict_indices[row["dataset"]][row["file_idx"]], + row["pred_init"] - self.obs_length, + row["pred_init"] + self.pred_length - 1) + for i, row in df.iterrows()] + + segment_idx_to_metadata = [(row["dataset"], str(row["file_idx"])) for i, row in df.iterrows()] + + #print(segments) + #print(self.dict_indices) + return segments, segment_idx_to_metadata \ No newline at end of file diff --git a/SkeletonDiffusion/src/data/loaders/amass_zeroshot.py b/SkeletonDiffusion/src/data/loaders/amass_zeroshot.py new file mode 100644 index 0000000000000000000000000000000000000000..d020fab564859c911be8e35c1038b93bed8fca8d --- /dev/null +++ b/SkeletonDiffusion/src/data/loaders/amass_zeroshot.py @@ -0,0 +1,95 @@ +import numpy as np +import os +import pandas as pd +import torch + +from .base import MotionDataset + + +class ZeroShotAMASSDataset(MotionDataset): + dataset_name = '3dpw' + + def __init__(self, *args, annotations_folder=None, if_zero_shot=True, **kwargs): + # annotations_folder, split, + # precomputed_folder, obs_length, pred_length, skeleton: FreeManSkeleton, + # stride=1, augmentation=0, segments_path=None, + # if_consider_hip=False, dtype='float32', + # da_mirroring=0.0, da_rotations=0.0, **kwargs + self.annotations_folder = annotations_folder + self.FPS = 60 + # self.as_amass = as_amass + self.if_zero_shot = if_zero_shot + self.dict_indices = {} # dict_indices[seq_name] indicated idx where subject-action annotations start. + self.mm_indces = None + self.metadata_class_idx = 0 # 0: se_name, 1: fake_labelfor allseqs -->the idx sets the value for metrics computation + + # following variables will be created in the next function calls + # self.idx_to_class = [] + # self.class_to_idx = {v: k for k, v in enumerate(self.idx_to_class)} + # self.mean_motion_per_class = [0.004533339312024582, 0.005071772030221925, 0.003968115058494981, 0.00592599384929542, 0.003590651675618232, 0.004194935839372698, 0.005625120976387903, 0.0024796492124910586, 0.0035406092427418797, 0.003602172245980421, 0.004347639393585013, 0.004222595821256223, 0.007537553520400006, 0.007066049169369122, 0.006754175094952483] + + super().__init__(*args, **kwargs) + assert self.split != 'test' or self.segments_path is not None + + # def extract_action_label(self, extra): + # return extra['metadata'][0] + + + def _prepare_data(self, num_workers=8): + if self.segments_path: + self.segments, self.segment_idx_to_metadata = self._load_annotations_and_segments(self.segments_path, num_workers=num_workers) + self.stride = 1 + self.augmentation = 0 + else: + self.annotations = self._read_all_annotations(self.split) + self.segments, self.segment_idx_to_metadata = self._generate_segments() + + def _read_all_annotations(self, split): + # Note that seqs names do not include 'the slice subfix' + preprocessed_path = os.path.join(self.precomputed_folder, f'data_3d_{self.dataset_name}.npz') + + data_o = np.load(preprocessed_path, allow_pickle=True)['positions_3d'].item() + if self.if_zero_shot and split=="test": + print("Zero shot test setting: we are using all splits") + data_f = {name: seq for s in list(data_o.keys()) for name, seq in data_o[s].items()} + else: + data_f = data_o[split] + + self.idx_to_class = [seq for seq in list(data_f.keys())] + self.class_to_idx = {v: k for k, v in enumerate(self.idx_to_class)} + + anns_all = [] + self.dict_indices = {} + self.clip_idx_to_metadata = [] + counter = 0 + for seq_name in data_f: + self.dict_indices[seq_name] = counter + self.clip_idx_to_metadata.append((seq_name)) + counter += 1 + # if self.as_amass: + data_f[seq_name] = data_f[seq_name][..., :self.skeleton.num_joints, :] # Some datasets may have more than 22 joints. 3DPW has 24 joints + anns_all.append(data_f[seq_name].astype(self.dtype)) # participants axis expanded + + self._generate_statistics_full(anns_all) + centered_anns = [ann - ann[0:1, 0:1, :] for ann in anns_all] + centered_cat_anns = np.concatenate(centered_anns , axis=0) + centered_cat_anns_no_trans = centered_cat_anns - centered_cat_anns[:, 0:1, :] + # print("min and max values of centered sequences: ", centered_cat_anns_no_trans .max(), centered_cat_anns_no_trans .min()) + + return anns_all + + def _load_annotations_and_segments(self, segments_path, num_workers=8): + assert os.path.exists(segments_path), "The path specified for segments does not exist: %s" % segments_path + df = pd.read_csv(segments_path) + self.annotations = self._read_all_annotations(self.split) + segments = [(self.dict_indices[row["name"]], + int(row["init"]), + int(row["pred_end"])) + for i, row in df.iterrows()] + + segment_idx_to_metadata = [(row["name"], row["name"]) for i, row in df.iterrows()] + + #print(segments) + #print(self.dict_indices) + return segments, segment_idx_to_metadata + diff --git a/SkeletonDiffusion/src/data/loaders/base/__init__.py b/SkeletonDiffusion/src/data/loaders/base/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..106a05bea64d49a0c883fade658fa95b77fabe0d --- /dev/null +++ b/SkeletonDiffusion/src/data/loaders/base/__init__.py @@ -0,0 +1 @@ +from .motion_dataset import MotionDataset, custom_collate_for_mmgt \ No newline at end of file diff --git a/SkeletonDiffusion/src/data/loaders/base/base_dataset.py b/SkeletonDiffusion/src/data/loaders/base/base_dataset.py new file mode 100644 index 0000000000000000000000000000000000000000..2199fda32c30588c8d2b6fed27c374496921f61a --- /dev/null +++ b/SkeletonDiffusion/src/data/loaders/base/base_dataset.py @@ -0,0 +1,273 @@ +from torch.utils.data import Dataset +import numpy as np +import os +import torch +import json +import ast + +MEAN_NAME = "mean_landmarks.npy" +VAR_NAME = "var_landmarks.npy" +MIN_NAME = "min_landmarks.npy" +MAX_NAME = "max_landmarks.npy" + +NORMALIZATION_TYPES = ["standardize", "normalize"] + +class BaseDataset(Dataset): + def __init__(self, precomputed_folder, obs_length: int, pred_length: int, augmentation=0, stride=1, num_workers=8, normalize_data=False, normalize_type="standardize", dtype='float64', if_consider_hip=False, use_vel=False): + super().__init__() + self.obs_length = obs_length + self.pred_length = pred_length + self.seg_length = obs_length + pred_length + + # 'annotations' and 'segments' need to be lists of numpy arrays of shape [frame, num_people, num_joints, num_features] + # each list are clips where segments can be extracted. + # if there is a clip which needs to be cut for a given reason, two lists need to be created. + self.annotations = None + + # segments are pre-processed and stored as: (idx, init, end), with idx being the idx of the clip stored in self.annotations + # and 'init' and 'end' the starting and ending points of the segments to be predicted + self.segments = [] + self.clip_idx_to_metadata = None # this needs to match each clip with its metadata. It is a list of tuples of length num_segments. The tuples have length2 and can contain only strings. + self.segment_idx_to_metadata = None # this needs to match each clip with its metadata + + # augmentation and stride can be used together to make the epoch more thorough or not. + # e.g., augmentation=5 and stride=20 => first segment will start at a random frame between 0 to 10 (augmentation of 5: 5 +/- 5), + # and next one at a random frame between 20 to 30 (stride of 20: 25 +/- 5) + self.augmentation = augmentation + self.stride = stride + assert self.augmentation >= 0, f"[ERROR_AUGMENTATION] Augmentation must be non-negative, {self.augmentation}" + + # folder where precomputed values will be stored (e.g., mean and variance) + self.precomputed_folder = precomputed_folder + if not os.path.exists(self.precomputed_folder): + os.makedirs(self.precomputed_folder) + + assert dtype.lower() in ["float64", "float32"], "Only dtypes=float64/32 supported in this project." + self.dtype = np.float64 if dtype.lower() == 'float64' else np.float32 + + # Define task: hmp without global translation or motion prediction with global translation + self.drop_root = not if_consider_hip + self.if_consider_hip = if_consider_hip + self.use_vel = use_vel + assert use_vel == False, "Not implemented" + + self._prepare_data(num_workers=num_workers) + assert not normalize_data, "Not implemented for the task" + self.normalize_data = normalize_data + self.normalize_type = normalize_type + assert self.normalize_type in NORMALIZATION_TYPES + if self.normalize_data: + statistics_folder = os.path.join(self.precomputed_folder, "statistics") + self.mean = np.load(os.path.join(statistics_folder, MEAN_NAME), allow_pickle=True) + self.var = np.load(os.path.join(statistics_folder, VAR_NAME), allow_pickle=True) + self.min = np.load(os.path.join(statistics_folder, MIN_NAME), allow_pickle=True) + self.max = np.load(os.path.join(statistics_folder, MAX_NAME), allow_pickle=True) + self.mean_tensor = torch.tensor(self.mean) + self.var_tensor = torch.tensor(self.var) + self.min_tensor = torch.tensor(self.min) + self.max_tensor = torch.tensor(self.max) + + def _prepare_data(self, num_workers=8): + # to be implemented in subclass, reading and processing of data + raise NotImplementedError() + + def get_classifier(self, device): + # to be implemented in subclass, in case classifier for fid has been trained + raise NotImplementedError() + + def __len__(self): + return len(self.segments) // self.stride + + def _load_mean_motion(self): + clas2meanfreq = {} + if not self.drop_root: + mm_file_per_task = {'motpred': "mean_motion_test.txt", "pose": "mean_motion_pose_test.txt", "traj": "mean_motion_traj_test.txt"} + else: + mm_file_per_task = {"hmp": "mean_motion_test.txt",} + for task, mm_file_name in mm_file_per_task.items(): + motion_avg_path = os.path.join(self.precomputed_folder, mm_file_name) + if not os.path.isfile(motion_avg_path): + from .math_utils import compute_mean_motions + print("Computing mean motions...") + class_average_3d, list_of_motions_3d, frequencies = compute_mean_motions(self) + with open(motion_avg_path, 'w') as filehandle: + filehandle.write('\n'.join([f"{c},{meanmot},{freq}" for c, meanmot, freq in zip(list(class_average_3d.keys()), list_of_motions_3d, frequencies)])) + print("Saved to ", motion_avg_path) + with open(motion_avg_path) as f: + # action name, mean motion, freq + for line in f: + c, meanmot, freq = line.strip().split(',') + clas2meanfreq[c] = [meanmot, freq] + meanmot, freq = zip(*[[float(clas2meanfreq[c][0]),float(clas2meanfreq[c][1])] for i,c in enumerate(self.idx_to_class)]) + if not self.drop_root: + setattr(self, f'mean_motion_per_class_{task}' if task!="motpred" else f'mean_motion_per_class', meanmot) + else: + setattr(self, f'mean_motion_per_class', meanmot) + # self.mean_motion_per_class = meanmot + + def __getitem__(self, sample_idx): + segment_idx = int(self.stride * sample_idx + self.augmentation) + if self.augmentation != 0: + offset = np.random.randint(-self.augmentation, self.augmentation + 1) + segment_idx = max(0, min(segment_idx + offset, len(self.segments) - 1)) + (i, init, end) = self.segments[segment_idx] + else: + (i, init, end) = self.segments[segment_idx] + + #print(len(self.segments), idx, i, init, end) + obs, pred = self._get_segment(i, init, end) + + # we include in the observation the zero, first (second) orders + if self.normalize_data: + obs = self.normalize(obs) + pred = self.normalize(pred) + # the identificative idx must be the sample_idx. This is helpful for generating samplers + return obs, pred, { + "sample_idx": sample_idx, + "clip_idx": i, # index of self.annotations, i.e. of whole sequence + "init": init, + "end": end, + "metadata": self.segment_idx_to_metadata[segment_idx], + "segment_idx": segment_idx + } + + def unique_sample_string(self, extra): + def _unique_sample_string(extra): + return f"{extra['metadata'][0]}-{extra['metadata'][1]}_clip{extra['clip_idx']}_{extra['init']}:{extra['end']}-segment{extra['segment_idx']}" + if torch.is_tensor(extra['clip_idx']): + return [_unique_sample_string({k: (extra[k][i] if k!= 'metadata' else [extra[k][0][i], extra[k][1][i]]) for k in extra if 'non_rotated' not in k }) for i in range(len(extra['clip_idx']))] + else: + return _unique_sample_string(extra) + + def load_mmgt(self, path): + # load json from file at 'path' + with open(path, 'r') as filehandle: + self.mm_indces = ast.literal_eval(json.load(filehandle)) + self.mm_indces = {k: sorted(self.mm_indces[k]) for k in sorted(self.mm_indces)} + print(f"Multimodal GT loaded from '{path}'") + + def find_segment(self, clip_idx, init, end=None): + # find the segment index given the clip_idx, init and end + for i, (i_, init_, end_) in enumerate(self.segments): + if i_ == clip_idx and init_ == init and (end is None or end_ == end): + return i + return None + + def find_sample(self, clip_idx, init, end=None): + # find the sample index given the clip_idx, init and end + assert self.augmentation == 0, "Cannot find sample if augmentation is not 0" + sample_idx = self.find_segment(clip_idx, init, end) / self.stride + return int(sample_idx) + + + def _get_segment(self, i, init, end): + # i corresponds to the segment idx inside self.annotations + # EX: is 2 segments, first seg for third session will be in the third position and second in the fourth position. + # Then, the fourth session will be in the fifth position + assert init >= 0, "init point for segment must be > 0" + + data = self.annotations[i][init:end + 1] + + obs, pred = data[:self.obs_length], data[self.obs_length:] + assert len(obs) == self.obs_length and len(pred) == self.pred_length + #assert obs.shape[0] == self.obs_length, f"[ERROR_OBS] Obs: {obs.shape}, Pred: {pred.shape} - Segment: {(i, init, end)}, {self.annotations[i].shape}" + #assert pred.shape[0] == self.pred_length, f"[ERROR_PRED] Obs: {obs.shape}, Pred: {pred.shape} - Segment: {(i, init, end)}, {self.annotations[i].shape}" + + return obs, pred + + def _get_mmgt_for_segment(self, segment_idx): + # we need to find the closest (may not be computed for all indices) + mm_gt_idces = self.mm_indces[segment_idx] + # we get all prediction multimodal GT segments + mm_gts = [self._get_segment(*self.segments[idx])[1] for idx in mm_gt_idces] + mm_gt = np.stack(mm_gts, axis=0) + # mm_gt = mm_gt[..., 1:, :] if self.drop_root else mm_gt + return mm_gt + + + def _generate_segments(self): + # this strategy is followed to ensure each epoch visits all samples from the dataset. + assert self.clip_idx_to_metadata is not None, "idx_to_metadata must be initialized before generating segments" + both = [((idx, init, init + self.seg_length - 1), self.clip_idx_to_metadata[idx]) for idx in range(len(self.annotations)) + for init in range(0, self.annotations[idx].shape[0] - self.seg_length)] + + # unzip to separate the segments from the metadata + segments, segment_idx_to_metadata = list(zip(*both)) + assert -1 not in [init for idx,init,ed in segments] + return segments, segment_idx_to_metadata + + def validate_segments_extended_predlength(self): + # check if all segments have self.pred_length + not_too_long_idx = [i for i, (idx, init, end) in enumerate(self.segments) if end < self.annotations[idx].shape[0]] + new_segments_idx_mapping = {idx: i for i, idx in enumerate(not_too_long_idx)} + new_mm_indices = {} + for i, idx in enumerate(not_too_long_idx): + new_mm_indices[i] = [new_segments_idx_mapping[old_idx] for old_idx in self.mm_indces[idx] if old_idx in new_segments_idx_mapping] + self.mm_indces = new_mm_indices + self.segments = [self.segments[i] for i in not_too_long_idx] + + def validate_segments_extended_obslength(self, extended_obslength): + + not_too_long_idx = [i for i, (idx, init, end) in enumerate(self.segments) if init-extended_obslength >= 0] + new_segments_idx_mapping = {idx: i for i, idx in enumerate(not_too_long_idx)} + new_mm_indices = {} + for i, idx in enumerate(not_too_long_idx): + new_mm_indices[i] = [new_segments_idx_mapping[old_idx] for old_idx in self.mm_indces[idx] if old_idx in new_segments_idx_mapping] + self.mm_indces = new_mm_indices + self.segments = [(idx, init-extended_obslength, end) for i, (idx, init, end) in enumerate(self.segments) if i in not_too_long_idx] + + + def _generate_statistics_full(self, anns_list): + # basic statistics computation for which all segments for all participants loaded are concatenated and computed one mean and one variance per landmark + # more complex statistics computations can be done by overriding this function (normalization per participant, for instance) + statistics_folder = os.path.join(self.precomputed_folder, "statistics") + if not os.path.exists(statistics_folder): + os.makedirs(statistics_folder) + mean_file = os.path.join(statistics_folder, MEAN_NAME) + var_file = os.path.join(statistics_folder, VAR_NAME) + min_file = os.path.join(statistics_folder, MIN_NAME) + max_file = os.path.join(statistics_folder, MAX_NAME) + if np.array([os.path.exists(p) for p in [mean_file, var_file, min_file, max_file]]).all(): + print("Skipping statistics generation...") + return + + all_concatenated = np.concatenate(anns_list, axis=0) + _, N_landmarks, N_dims = all_concatenated.shape + ps = all_concatenated.reshape((-1, N_landmarks, N_dims)) # (NumParts * SegmentsEach, NumLandmarks, NumDims) generalized to N people + + np.mean(ps, axis=0).dump(mean_file) + np.var(ps, axis=0).dump(var_file) + np.min(ps, axis=0).dump(min_file) + np.max(ps, axis=0).dump(max_file) + + + def normalize(self, x): + # x := [seq_length, num_people, num_landmarks, num_dims] + if self.normalize_type == "standardize": + return (x - self.mean) / np.sqrt(self.var) + elif self.normalize_type == "normalize": + return 2 * (x - self.min) / (self.max - self.min) - 1 + raise NotImplementedError(f"'{self.normalize_type}' normalization not implemented.") + + def denormalize(self, x, idces=None): + # idces can be used to fix mismatches between the indices passed as arguments, and the indices from mean and var + # e.g., for visualization, the root is passed, but root isn ot part of var/mean arrays + + if idces is None: + idces = list(range(x.shape[-2])) + if torch.is_tensor(x): + var, mean, m, M = [arr.to(x.device) for arr in [self.var_tensor, self.mean_tensor, self.min_tensor, self.max_tensor]] + sqrt = torch.sqrt + else: + var, mean, m, M = self.var, self.mean, self.min, self.max + sqrt = np.sqrt + + if self.normalize_type == "standardize": + return sqrt(var[idces]) * x + mean[idces] + elif self.normalize_type == "normalize": + return (x + 1) * (M[idces] - m[idces]) / 2 + m[idces] + raise NotImplementedError(f"'{self.normalize_type}' normalization not implemented.") + + def _get_hash_str(self): + # this function is used to generate a unique hash for the dataset, based on the parameters used to generate it + raise NotImplementedError() \ No newline at end of file diff --git a/SkeletonDiffusion/src/data/loaders/base/create_dataset_utils.py b/SkeletonDiffusion/src/data/loaders/base/create_dataset_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..97f318ec034e854349322f5ec60ea5f104ebf9f5 --- /dev/null +++ b/SkeletonDiffusion/src/data/loaders/base/create_dataset_utils.py @@ -0,0 +1,70 @@ +import os +import numpy as np +import json +import torch +from torch.utils.data import DataLoader +from typing import Tuple, List, Dict, Set, Any +from functools import partial + +import sys +from .math_utils import compute_mean_motions, get_multimodal_gt +from .motion_dataset import MotionDataset +from ..skeleton import SkeletonCenterPose, SkeletonVanilla + +IF_NDEBUG = False + +def compute_stats(precomputed_folder, Dataset: MotionDataset, Skeleton: Tuple[SkeletonVanilla,SkeletonCenterPose], if_consider_hip:bool, batch_size = 128, overwrite=False): + np.random.seed(0) + torch.manual_seed(0) + torch.cuda.manual_seed(0) + + skeleton = Skeleton[0](if_consider_hip=if_consider_hip) + dataset = Dataset( split='test', skeleton=skeleton, precomputed_folder=precomputed_folder, + if_consider_hip=if_consider_hip, augmentation=0, da_mirroring=0.0, da_rotations=0.0, + dtype="float32") + dest_file = os.path.join(precomputed_folder, "mean_motion_test.txt") + if not os.path.exists(dest_file) or overwrite: + class_average_3d, list_of_motions_3d, frequencies = compute_mean_motions(dataset, batch_size=batch_size) + + with open(dest_file, 'w') as filehandle: + filehandle.write('\n'.join([f"{c},{meanmot},{freq}" for c, meanmot, freq in zip(list(class_average_3d.keys()), list_of_motions_3d, frequencies)])) + else: + print("Files for Mean motion values already exist. Skipping.") + + # print(f"Mean motion values for {len(list_of_motions_3d)} classes (actions={data_loader.dataset.idx_to_class}):\n", [float(l) for l in list_of_motions_3d]) + # print(frequencies) + + +def compute_multimodal_gt(Dataset: MotionDataset, + annotations_folder: str, precomputed_folder: str, split='test', + multimodal_threshold=0.5, segment_path="/hmp/segments_0.5s-2s", batch_size=2048): + mmgt_path = os.path.join(precomputed_folder, f"mmgt_{split}.txt") + if os.path.exists(mmgt_path): + print("Multimodal GT already exists. Skipping.") + return + mmgt = compute_multimodal_gt_onsplit(Dataset=partial(Dataset, split=split, segments_path = segment_path, + annotations_folder=annotations_folder, precomputed_folder=precomputed_folder), + dest_path=mmgt_path, + multimodal_threshold=multimodal_threshold, batch_size=batch_size) + + import ast + with open(os.path.join(precomputed_folder, f"mmgt_{split}.txt"), 'r') as filehandle: + mmgt_loaded = ast.literal_eval(json.load(filehandle)) + assert mmgt_loaded==mmgt, "Loaded multimodal GT is different from the original one." + +def compute_multimodal_gt_onsplit(Dataset: MotionDataset, + dest_path: str, + multimodal_threshold=0.5, batch_size=2048): + np.random.seed(0) + torch.manual_seed(0) + torch.cuda.manual_seed(0) + dataset = Dataset(#annotations_folder=annotations_folder, precomputed_folder=precomputed_folder, + augmentation=0, da_mirroring=0.0, da_rotations=0.0, dtype="float32") + + data_loader = DataLoader(dataset, pin_memory= True, shuffle=False, batch_size=batch_size, + num_workers=0, drop_last=False) + mmgt = get_multimodal_gt(data_loader, multimodal_threshold=multimodal_threshold, recover_landmarks=True)#, store_tempfile=dest_path if 'train' in dest_path else None) # recover_landmarks makes no difference for CenterPoseSkeleton + # analyze and store + with open(dest_path, 'w') as filehandle: + json.dump(str(mmgt), filehandle) + return mmgt diff --git a/SkeletonDiffusion/src/data/loaders/base/motion_dataset.py b/SkeletonDiffusion/src/data/loaders/base/motion_dataset.py new file mode 100644 index 0000000000000000000000000000000000000000..76bdcbf1ef2e5c866064b23d0003bae265b9ab1a --- /dev/null +++ b/SkeletonDiffusion/src/data/loaders/base/motion_dataset.py @@ -0,0 +1,206 @@ +import numpy as np +import os +import torch +import hashlib +from scipy.spatial.transform import Rotation as R +from torch.utils.data._utils.collate import default_collate + +from .base_dataset import BaseDataset + + +def add_noise(tensor, noise_level=0.25, noise_std=0.02): + shape = tensor.shape + num_elements = shape[-2] + + noise = np.random.randn(*tensor.shape) * noise_std + mask = np.random.rand(*shape[:-1]) < noise_level + + tensor[mask] += noise[mask] + return tensor + +### Change Flo +def add_noise_pytorch(tensor, noise_level=0.25, noise_std=0.02): + shape = tensor.shape + num_elements = shape[-2] + + noise_np = np.random.randn(*tensor.shape) * noise_std + mask_np = np.random.rand(*shape[:-1]) < noise_level + + noise = torch.randn_like(tensor) * noise_std + mask = torch.rand(*shape[:-1]) < noise_level + + tensor[mask] += noise[mask] + return tensor +########################### + +def custom_collate_for_mmgt(data): + have_mmgt = 'mm_gt' in data[0][2] + if have_mmgt: + mm_gt = [d[2].pop('mm_gt') for d in data] + obs, pred, extra = default_collate(data) + if have_mmgt: + extra['mm_gt'] = mm_gt + + return obs, pred, extra + +class MotionDataset(BaseDataset): + def __init__(self, split, precomputed_folder, skeleton, + obs_length: int, pred_length: int, + segments_path=None, + stride=1, augmentation=0, da_mirroring=0.0, da_rotations=0.0, + dtype='float32', + if_consider_hip=False, if_load_mmgt=False, extended_pred_length: int =None, + if_noisy_obs:bool = False, noise_level: float=0.30, noise_std: float = 0.03, **kwargs): + + # self.annotations_folder = annotations_folder + self.precomputed_folder = precomputed_folder + self.segments_path = segments_path + self.split = split + self.skeleton = skeleton + self.if_load_mmgt = if_load_mmgt + self.if_noisy_obs = if_noisy_obs + self.noise_level = noise_level + self.noise_std = noise_std + print(f"Constructing {type(self).__name__} for split ", self.split) + assert self.split in ["valid",'train', 'test'], f"{self.split} not implemented" + if self.split in ['test']: + assert self.segments_path is not None and self.split in self.segments_path + else: + assert self.segments_path is None or (self.segments_path is not None and self.split in self.segments_path) + + + assert da_mirroring >= 0.0 and da_mirroring <= 1.0 and da_rotations >= 0.0 and da_rotations <= 1.0, \ + "Data augmentation strategies must be in [0, 1]" + self.da_mirroring = da_mirroring + self.da_rotations = da_rotations + # self.extended_pred_length = extended_pred_length + if extended_pred_length is not None: + assert extended_pred_length > pred_length, "Extended pred length must be greater than pred length" + assert split in ['test', 'valid'], "Extended pred length is only available for test and valid splits" + pred_length = extended_pred_length + + self.in_eval = self.in_eval = True if split in ['test','valid'] else False # Change Flo + + super().__init__(precomputed_folder, obs_length, pred_length, augmentation=augmentation, stride=stride, dtype=dtype, if_consider_hip=if_consider_hip) + + self.load_mmgt() + if self.split in ['test'] and ('if_compute_cmd' in kwargs and kwargs['if_compute_cmd']): + self._load_mean_motion() + # if self.split == 'valid': + # print("Note that we are computing the Cumulative Motion Distribution (CMD) metric with data extracted from test split even if we are performin validation") + if extended_pred_length is not None: + self.validate_segments_extended_predlength() + + print(f"Constructed {type(self).__name__} for split {self.split} with a total of {len(self.segments)} samples") + + def extract_action_label(self, extra): + return extra['metadata'][self.metadata_class_idx] + + def eval(self): + self.in_eval = True + def train(self): + self.in_eval = False + + def load_mmgt(self, path=None): + if self.if_load_mmgt: + if self.if_consider_hip: + suffix = "_hmp" + else: + suffix = "" + if path is None: + mmgt_path = os.path.join(self.precomputed_folder, f"mmgt_{self.split}{suffix}.txt") + else: + mmgt_path = path.replace('.txt', f"{suffix}.txt") + assert os.path.exists(mmgt_path), "Multimodal GT file does not exist. Please compute it first." + super().load_mmgt(mmgt_path) + assert len(self.mm_indces) == len(self.segments), "Multimodal GT file does not have the same number of samples as the dataset" + + def get_classifier(self, device): + raise NotImplementedError(f"We don't have a classifier for the {type(self).__name__} dataset") + + def _get_hash_str(self, use_all=False): + use_all = [str(self.obs_length), str(self.pred_length), str(self.stride), str(self.augmentation)] if use_all else [] + to_hash = "".join(tuple(self.subjects + list(self.actions) + + [str(self.drop_root), str(self.use_vel)] + use_all)) + return str(hashlib.sha256(str(to_hash).encode('utf-8')).hexdigest()) + + # def get_custom_segment(self, subject, action, frame_num): + # counter = self.dict_indices[subject][action] + # obs, pred = self._get_segment(counter, frame_num, frame_num + self.seg_length - 1) + # return obs, pred + + def _get_mmgt_idx_(self, extra): + if self.mm_indces is not None and self.if_load_mmgt: + mm_gt = self._get_mmgt_for_segment(extra['segment_idx']) + if self.normalize_data: + mm_gt = self.normalize(mm_gt) + extra["mm_gt"] = mm_gt + else: + ... #extra["mm_gt"] = -1 + return extra + + def data_augmentation(self, obs, pred, extra): + if self.if_load_mmgt: + mm_gt = extra["mm_gt"] + + if self.da_mirroring != 0: + # apply mirroring with probability 0.5 + mirroring_idces = [0, 1] # 2 is not used because the person would be upside down + for m in mirroring_idces: + if np.random.rand() < self.da_mirroring: + # make a copy of obs, pred + obs, pred = obs.copy(), pred.copy() + # invert sign of first coordinate at last axis for obs, pred + obs[..., m] *= -1 + pred[..., m] *= -1 + + if self.if_load_mmgt: + mm_gt = mm_gt.copy() + mm_gt[..., m] *= -1 + + # extra["non_rotated_obs"] = obs.copy() + # extra["non_rotated_pred"] = pred.copy() + if self.da_rotations != 0: + # apply random rotations with probability 1 + rotation_axes = ['z'] # 'x' and 'y' not used because the person could be upside down + for a in rotation_axes: + if np.random.rand() < self.da_rotations: + degrees = np.random.randint(0, 360) + r = R.from_euler(a, degrees, degrees=True).as_matrix().astype(np.float32) + obs = (r @ obs.reshape((-1, 3)).T).T.reshape(obs.shape) + pred = (r @ pred.reshape((-1, 3)).T).T.reshape(pred.shape) + + if self.if_load_mmgt: + mm_gt = (r @ mm_gt.reshape((-1, 3)).T).T.reshape(mm_gt.shape) + + if self.if_load_mmgt: + extra["mm_gt"] = mm_gt + return obs, pred, extra + + def iter_thourgh_seqs(self): + for seq in self.annotations: + yield seq + + def get_segment_from_dataset(self, idx): + obs, pred, extra = super().__getitem__(idx) + extra['adj'] = self.skeleton.adj_matrix + return obs, pred, extra + + def tranform2inputspace(self, obs, pred, extra): + data = self.skeleton.tranform_to_input_space(torch.cat([torch.from_numpy(obs), torch.from_numpy(pred)], dim=-3)) + obs, pred = data[..., :obs.shape[-3], :, :], data[..., obs.shape[-3]:, :, :] + if self.if_load_mmgt: + extra["mm_gt"] = self.skeleton.tranform_to_input_space(torch.from_numpy(extra["mm_gt"])) + + return obs, pred, extra + + def __getitem__(self, idx): + obs, pred, extra = self.get_segment_from_dataset(idx) + extra = self._get_mmgt_idx_(extra) + if self.if_noisy_obs: + obs[..., 1:, :] = add_noise(obs[..., 1:, :], noise_level=self.noise_level, noise_std=self.noise_std) + if not self.in_eval: + obs, pred, extra = self.data_augmentation(obs, pred, extra) + obs, pred, extra = self.tranform2inputspace(obs, pred, extra) + + return obs, pred, extra \ No newline at end of file diff --git a/SkeletonDiffusion/src/data/loaders/freeman.py b/SkeletonDiffusion/src/data/loaders/freeman.py new file mode 100644 index 0000000000000000000000000000000000000000..d30c5695298cf107b6300a8e51e6ed2cad9f0a7a --- /dev/null +++ b/SkeletonDiffusion/src/data/loaders/freeman.py @@ -0,0 +1,120 @@ +import numpy as np +import os +import pandas as pd +import torch + +from .base import MotionDataset + + +class FreeManDataset(MotionDataset): + def __init__(self, *args, actions='all', annotations_folder=None, **kwargs): + # annotations_folder, split, + # precomputed_folder, obs_length, pred_length, skeleton: FreeManSkeleton, + # stride=1, augmentation=0, segments_path=None, + # if_consider_hip=False, dtype='float32', + # da_mirroring=0.0, da_rotations=0.0, **kwargs + + self.annotations_folder = annotations_folder + self.FPS = 30 + self.actions = actions + + self.dict_indices = {} # dict_indices[seq_name] indicated idx where subject-action annotations start. + self.mm_indces = None + self.metadata_class_idx = 0 # 0: action, 1: seq_name --> action is the class used for metrics computation + # following variables will be created in the next function calls + # self.idx_to_class = [] + # self.class_to_idx = {v: k for k, v in enumerate(self.idx_to_class)} + # self.mean_motion_per_class = [0.004533339312024582, 0.005071772030221925, 0.003968115058494981, 0.00592599384929542, 0.003590651675618232, 0.004194935839372698, 0.005625120976387903, 0.0024796492124910586, 0.0035406092427418797, 0.003602172245980421, 0.004347639393585013, 0.004222595821256223, 0.007537553520400006, 0.007066049169369122, 0.006754175094952483] + + super().__init__(*args, actions=actions, **kwargs) + assert (self.actions is not None) or self.segments_path is not None + + def extract_action_label(self, extra): + return extra['metadata'][0] + + + def _prepare_data(self, num_workers=8): + if self.segments_path: + self.segments, self.segment_idx_to_metadata = self._load_annotations_and_segments(self.segments_path, num_workers=num_workers) + self.stride = 1 + self.augmentation = 0 + else: + print("During traiing we should not have access to the annotation folder. Everything we need during training sould be in the precomputed folder. OR given as an extra path like the segments files.") + with open(os.path.join(self.annotations_folder, f'{self.split}.txt')) as f: + split_seqs = [line.strip() for line in f] #f.readlines() + assert len(split_seqs) == len(set(split_seqs)), "Some sequences are repeated in the split file." + self.annotations = self._read_all_annotations(self.actions, split_seqs) + self.segments, self.segment_idx_to_metadata = self._generate_segments() + + def _read_all_annotations(self, actions, seqs): + # Note that seqs names do not include 'the slice subfix' + preprocessed_path = os.path.join(self.precomputed_folder, 'data_3d_freeman.npz') + + data_o = np.load(preprocessed_path, allow_pickle=True)['positions_3d'].item() + + # filter sequences by name: remove sequences not in seqs + data_f = {key: data_o[key] for key in seqs} + + file2action = {} + with open(os.path.join(self.annotations_folder, 'seq_actions_labels.txt')) as f: + for line in f: + name, label = line.strip().split(',') + # if name in seqs and (label in actions or actions == 'all'): + file2action[name] = label + + # filter actions dict to keep only the seqs in data_f + file2action = {key: file2action[key] for key in file2action if key in data_f} + + # if we do not want to keep all actions + if actions != 'all': + assert isinstance(actions, list), "actions must be a list" + # filter actions + file2action = {key: file2action[key] for key in file2action if file2action[key] in actions} + data_f = {key: data_f[key] for key in data_f if key in file2action} + + action_list = {action: None for action in list(file2action.values())} + + data = {} + self.seq2action = file2action + self.idx_to_class = list(dict.fromkeys(action_list)) + self.countclassoccurrences = {a: 0 for a in action_list} + counter = 0 + # we build the feature vectors for each participant and action + for seq_name in list(data_f.keys()): + action = self.seq2action[seq_name] + self.dict_indices[seq_name] = counter + counter += 1 + kpts = data_f[seq_name] + data[seq_name] = kpts + self.countclassoccurrences[action] += 1 + assert not np.isnan(kpts).any() + + self.data = data + self.class_to_idx = {v: k for k, v in enumerate(self.idx_to_class)} + + anns_all = [] + self.clip_idx_to_metadata = [] + for seq_name in self.data: + self.clip_idx_to_metadata.append((self.seq2action[seq_name], seq_name)) + anns_all.append(self.data[seq_name].astype(self.dtype)) # participants axis expanded + + self._generate_statistics_full(anns_all) + + return anns_all + + def _load_annotations_and_segments(self, segments_path, num_workers=8): + assert os.path.exists(segments_path), "The path specified for segments does not exist: %s" % segments_path + df = pd.read_csv(segments_path) + seqs = list(df["name"].unique()) + self.annotations = self._read_all_annotations(self.actions, seqs) + segments = [(self.dict_indices[row["name"]], + int(row["init"]), + int(row["pred_end"])) + for i, row in df.iterrows()] + + segment_idx_to_metadata = [(self.seq2action[row["name"]], row["name"]) for i, row in df.iterrows()] + + #print(segments) + #print(self.dict_indices) + return segments, segment_idx_to_metadata + diff --git a/SkeletonDiffusion/src/data/loaders/h36m.py b/SkeletonDiffusion/src/data/loaders/h36m.py new file mode 100644 index 0000000000000000000000000000000000000000..28c17ec3d4c9b9bdce2e7ccd14cd21637aed3bec --- /dev/null +++ b/SkeletonDiffusion/src/data/loaders/h36m.py @@ -0,0 +1,106 @@ +import numpy as np +import os +import pandas as pd +import os + +from .base import MotionDataset + +class H36MDataset(MotionDataset): + def __init__(self, subjects, *args, actions='all', **kwargs): # data augmentation strategies + + + self.subjects, self.actions = subjects, actions + self.FPS = 50 + + self.dict_indices = {} # dict_indices[subject][action] indicated idx where subject-action annotations start. + self.mm_indces = None + self.metadata_class_idx = 1 # 0: subject, 1: action --> action is the class used for metrics computation + self.idx_to_class = ['Directions', 'Discussion', 'Eating', 'Greeting', 'Phoning', 'Posing', 'Purchases', 'Sitting', 'SittingDown', 'Smoking', 'Photo', 'Waiting', 'Walking', 'WalkDog', 'WalkTogether'] + self.class_to_idx = {v: k for k, v in enumerate(self.idx_to_class)} + # self.mean_motion_per_class = [0.004533339312024582, 0.005071772030221925, 0.003968115058494981, 0.00592599384929542, 0.003590651675618232, 0.004194935839372698, 0.005625120976387903, 0.0024796492124910586, 0.0035406092427418797, 0.003602172245980421, 0.004347639393585013, 0.004222595821256223, 0.007537553520400006, 0.007066049169369122, 0.006754175094952483] + + super().__init__(*args, actions=actions, **kwargs) + assert (subjects is not None and actions is not None) or self.segments_path is not None + + def load_mmgt(self): + if self.split == 'train': + if 'S8' in self.subjects: + mmgt_path = os.path.join(self.precomputed_folder, f"mmgt_{self.split}.txt") + else: + mmgt_path = os.path.join(self.precomputed_folder, f"mmgt_{self.split}_noS8.txt") + super().load_mmgt(mmgt_path) + else: + super().load_mmgt() + + + def _prepare_data(self, num_workers=8): + if self.segments_path: + self.segments, self.segment_idx_to_metadata = self._load_annotations_and_segments(self.segments_path, num_workers=num_workers) + self.stride = 1 + self.augmentation = 0 + else: + self.annotations = self._read_all_annotations(self.subjects, self.actions) + self.segments, self.segment_idx_to_metadata = self._generate_segments() + + def _read_all_annotations(self, subjects, actions): + preprocessed_path = os.path.join(self.precomputed_folder, f'data_3d_h36m.npz') + + # we load from already preprocessed dataset + data_o = np.load(preprocessed_path, allow_pickle=True)['positions_3d'].item() + data_f = dict(filter(lambda x: x[0] in subjects, data_o.items())) + if actions != 'all': # if not all, we only keep the data from the selected actions, for each participant + for subject in list(data_f.keys()): + #data_f[key] = dict(filter(lambda x: all([a in x[0] for a in actions]), data_f[key].items())) # OLD and wrong + # data_f[subject] = {k: v for k, v in data_f[subject].items() if any([a in k for a in self.actions])} + data_f[subject] = dict(filter(lambda x: any([a in x[0] for a in actions]), data_f[subject].items())) + if len(data_f[subject]) == 0: # no actions for subject => delete + data_f.pop(subject) + print(f"Subject '{subject}' has no actions available from '{actions}'.") + for action in data_f[subject].keys(): + assert not np.isnan(data_f[subject][action]).any() + else: + print(f"All actions loaded from {subjects}.") + + self.data = data_f + + anns_all = [] + self.dict_indices = {} + self.clip_idx_to_metadata = [] + counter = 0 + for subject in self.data: + self.dict_indices[subject] = {} + + for action in self.data[subject]: + self.dict_indices[subject][action] = counter + self.clip_idx_to_metadata.append((subject, action.split(" ")[0].split("_")[0])) + counter += 1 + + anns_all.append(self.data[subject][action].astype(self.dtype)) # participants axis expanded + centered_anns = [ann - ann[0:1, 0:1, :] for ann in anns_all] + centered_cat_anns = np.concatenate(centered_anns , axis=0) + centered_cat_anns_no_trans = centered_cat_anns - centered_cat_anns[:, 0:1, :] + # print("min and max values of centered sequences: ", centered_cat_anns_no_trans .max(), centered_cat_anns_no_trans .min()) + # train 0.98306274 -0.9905092 + # valid 0.9272223 -0.91470855 + + self._generate_statistics_full(anns_all) + + return anns_all + + def _load_annotations_and_segments(self, segments_path, num_workers=8): + assert os.path.exists(segments_path), "The path specified for segments does not exist: %s" % segments_path + df = pd.read_csv(segments_path) + df["action"] = df["action"].apply(lambda x: x.replace('TakingPhoto', 'Photo').replace('WalkingDog', 'WalkDog').replace(' ', '_')) + subjects, actions = list(df["subject"].unique()), list(df["action"].unique()) + print(subjects, actions) + self.annotations = self._read_all_annotations(subjects, actions) + segments = [(self.dict_indices[row["subject"]][row["action"]], + int(row["init"]), + int(row["pred_end"])) + for i, row in df.iterrows()] + + segment_idx_to_metadata = [(row["subject"], row["action"].split(" ")[0].split("_")[0]) for i, row in df.iterrows()] + + #print(segments) + #print(self.dict_indices) + return segments, segment_idx_to_metadata diff --git a/SkeletonDiffusion/src/data/skeleton/__init__.py b/SkeletonDiffusion/src/data/skeleton/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..69e0a84b6b1ca4c619aad020dd051498bcd4f09a --- /dev/null +++ b/SkeletonDiffusion/src/data/skeleton/__init__.py @@ -0,0 +1,19 @@ +from SkeletonDiffusion.src.data.skeleton.motion import get_motion_representation_objclass +from SkeletonDiffusion.src.data.skeleton.kinematic import get_kinematic_objclass + +def create_skeleton(**kwargs): + motion_repr_class = get_motion_representation_objclass(kwargs["motion_repr_type"]) + kinematic_class, dataset_name = get_kinematic_objclass(kwargs["dataset_name"]) + new_class_name = dataset_name + kwargs["motion_repr_type"] + def init_both_classes(self, *args, **kwargs): + # Initialize the kinematic class + kinematic_class.__init__(self, *args, **kwargs) + # Initialize the motion representation class + motion_repr_class.__init__(self, *args, **kwargs) + + CompoundSkeletonClass = type(new_class_name, (kinematic_class, motion_repr_class), {"__init__": init_both_classes,}) + #### THe previous line is creating a class similar to the following and returning the constructor/Class name + # class AMASSSkeletonCenterPose(AMASSKinematic, SkeletonCenterPose): + # def __init__(self, **kwargs): + # init_both_classes(self, **kwargs) + return CompoundSkeletonClass(**kwargs) \ No newline at end of file diff --git a/SkeletonDiffusion/src/data/skeleton/kinematic/__init__.py b/SkeletonDiffusion/src/data/skeleton/kinematic/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8c051939bc50498afbf78915cbd1072bcab244d7 --- /dev/null +++ b/SkeletonDiffusion/src/data/skeleton/kinematic/__init__.py @@ -0,0 +1,9 @@ +from .utils import get_adj_matrix +from .freeman import FreeManKinematic +from .h36m import H36MKinematic +from .amass import AMASSKinematic + +def get_kinematic_objclass(dataset_name): + dataset_type = {'h36m': 'H36M', 'freeman': 'FreeMan', 'amass': 'AMASS', 'amass-mano': 'AMASS', + '3dpw': 'AMASS' }[dataset_name.lower()] + return globals()[dataset_type+"Kinematic"], dataset_type \ No newline at end of file diff --git a/SkeletonDiffusion/src/data/skeleton/kinematic/amass.py b/SkeletonDiffusion/src/data/skeleton/kinematic/amass.py new file mode 100644 index 0000000000000000000000000000000000000000..7d19609fad771a6d64fbac5621061e55a73d324a --- /dev/null +++ b/SkeletonDiffusion/src/data/skeleton/kinematic/amass.py @@ -0,0 +1,85 @@ +import torch +import numpy as np + +from .base import Kinematic + + +class AMASSKinematic(Kinematic): + def __init__(self, num_joints=22, **kwargs): + + super().__init__(**kwargs) + self.relative_restpose = {'left_arm': np.array([[-0.08951462, 0.01432468, 0.11159658], + [-0.116652 , -0.01674555, 0.01757753], + [-0.02959993, 0.0193723 , -0.2667216 ], + [ 0.03015181, -0.12220491, -0.25177056]]), + 'right_arm': np.array([[ 0.05214295, 0.01628557, 0.11822093], + [ 0.11756767, 0.01566032, 0.03865051], + [ 0.04485199, 0.02369931, -0.26253664], + [ 0.00150388, -0.10840166, -0.25212884]]), + 'left_leg': np.array([[-0.00102365, 0.03786719, -0.37976843], + [-0.05257663, 0.00471593, -0.3990224 ], + [ 0.04243585, -0.1181156 , -0.04386783]]), + 'right_leg': np.array([[-0.00650667, 0.01321159, 0.10511905], + [ 0.01109964, -0.02364293, 0.13600564], + [ 0.003884 , -0.04299295, 0.03277576]])} + + self.joint_dict_orig = {0: 'GlobalRoot', 1: 'RHip', 2: 'LHip', 3: 'Spine1', + 4: 'RKnee', 5: 'LKnee', 6: 'Spine3', + 7: 'RHeel', 8: 'LHeel', 9: 'Neck', 10: 'RFoot', + 11: 'LFoot', 12: 'BMN', 13: 'RSI', 14: 'LSI', 15: 'Head', + 16: 'RShoulder', 17: 'LShoulder', 18: 'RElbow',19: 'LElbow', 20: 'RWrist',21: 'LWrist'} + + self.limbseq = [ [0,3], [3,6], [6,9], [9,12], [12,15], # body + [9,14], [14,17], [17,19], [19,21], # right arm + [9,13], [13,16], [16,18], [18,20], # left arm + [0,2], [2,5], [5,8], [8,11], # right leg + [0,1], [1,4], [4,7], [7,10] # left leg + ] + + assert num_joints in [22, 52] + if num_joints == 52: + self.joint_dict_orig = {**self.joint_dict_orig, **{22: 'left_index1', 23: 'left_index2', 24: 'left_index3', + 25: 'left_middle1', 26: 'left_middle2', 27: 'left_middle3', + 28: 'left_pinky1', 29: 'left_pinky2', 30: 'left_pinky3', + 31: 'left_ring1', 32: 'left_ring2', 33: 'left_ring3', + 34: 'left_thumb1', 35: 'left_thumb2', 36: 'left_thumb3', + 37: 'right_index1', 38: 'right_index2', 39: 'right_index3', + 40: 'right_middle1', 41: 'right_middle2', 42: 'right_middle3', + 43: 'right_pinky1', 44: 'right_pinky2', 45: 'right_pinky3', + 46: 'right_ring1', 47: 'right_ring2', 48: 'right_ring3', + 49: 'right_thumb1', 50: 'right_thumb2', 51: 'right_thumb3' + }} + self.limbseq += [ [20, 22], [20, 25], [20, 28], [20, 31], [20,34], + [22,23], [23,24], [25,26], [26,27], [28,29], [29,30], [31,32], [32,33], [34,35], [35,36], # falanges left hand + [21,37], [21,40],[21,43], [21,46], [21,49], + [37,38], [38,39], [40,41], [41,42], [43,44], [44,45], [46,47], [47,48], [49,50], [50,51], # falanges right hand + ] + + + self.left_right_limb_list = [False if (joint[0] == "L" and joint[1].isupper()) or 'left' in joint else True for joint in list(self.joint_dict_orig.values())] + + if not self.if_consider_hip: + self.node_dict = self.joint_dict_orig.copy() + self.node_dict.pop(0) + self.node_dict = {i:v for i,v in enumerate(list(self.node_dict.values()))} + node_dict_reversed = {v:i for i,v in self.node_dict.items()} + self.node_limbseq = [[node_dict_reversed['RHip'], node_dict_reversed['LHip']], + [node_dict_reversed['RHip'], node_dict_reversed['Spine1']], + [node_dict_reversed['LHip'], node_dict_reversed['Spine1']], + *[[limb[0] -1, limb[1] -1] for limb in self.limbseq if limb[1] != 0 and limb[0] != 0]] + # # index of limbs in limb_angles_idx for mae + # index of joints in kinchain for limb dropping + self.limb_angles_idx = [[0,2,3,4,5,6], [0,3], [4,7,8,9,10], [4,11,12,13,14], [0,15,16,17], [18,19,20]] + self.kinchain = [[2,5,8,11,14], #hip to head + [8,13,16,18,20], # left arm + [8,12,15,17,19], # right arm + [1,4,7,10], # left leg + [0,3,6,9], # right leg + [0,1,2,0], # hip connection + ] + else: + self.node_dict = {k:v for k,v in enumerate(list(self.node_hip.values())+list(self.joint_dict_orig.values())[1:])} + self.node_limbseq = self.limbseq.copy() + # self.limb_angles_idx = [[0,1,2,3,4], [5,6,7,8], [9,10,11,12], [13, 14, 15, 16], [17, 18, 19, 20]] + self.limbseq = np.array(self.limbseq) + diff --git a/SkeletonDiffusion/src/data/skeleton/kinematic/base.py b/SkeletonDiffusion/src/data/skeleton/kinematic/base.py new file mode 100644 index 0000000000000000000000000000000000000000..908c8d392db719c08fe92685eafa17fa7768449d --- /dev/null +++ b/SkeletonDiffusion/src/data/skeleton/kinematic/base.py @@ -0,0 +1,139 @@ +import torch + +from .utils import plot_matrix, get_adj_matrix + + +class Kinematic(): + """ + It is a abstract class, needs to be subclassed. + """ + def __init__(self, if_consider_hip=False, **kwargs): + self.if_consider_hip = if_consider_hip + + + # TO DO define following variables + # self.joint_dict_orig = {} + # self.limbseq = [[0, 1], ... + # ] + + # if if_consider_hip: + # self.node_dict = {**Skeleton.node_hip, **{i +len(Skeleton.node_hip): v for i,v in self.joint_dict_orig.items()}} + # self.node_limbseq = [[limb[0] -1, limb[1] -1] for limb in self.limbseq if limb[1] != 0 and limb[0] != 0] + # # rememeber to add hip connections! + # else: + # self.node_dict = self.joint_dict_orig + # self.node_limbseq = self.limbseq + # self.left_right_limb_list = [False if joint[0] == "L" and joint[1].isupper() else True for joint in list(self.joint_dict_orig.values())] + + # @property + def parents(self, mode='original'): + num_joints = self.num_joints if mode == 'original' else self.num_nodes + parents = [None] * num_joints + parents[0] = -1 + limbseq = self.limbseq if mode == 'original' else self.node_limbseq + for tup in limbseq: + assert tup[0] < tup[1] + parents[tup[1]] = tup[0] + return parents + + def limb_names(self, mode='original'): + limbseq = self.limbseq if mode == 'original' else self.node_limbseq + nlimbs = self.num_joints if mode == 'original' else self.num_nodes + joint_dict = self.joint_dict_orig if mode == 'original' else self.node_dict + parents = self.parents(mode=mode) + return [f"Limb {i}: {joint_dict[i]}-{joint_dict[parents[i]]}" for i in range(1, nlimbs)] + + @property + def num_joints(self): + return len(self.joint_dict_orig) + + @property + def num_nodes(self): + return len(self.node_dict) + + @property + def left_right_limb(self): + return self.left_right_limb_list.copy() + + @property + def nodes_type_id(self): + joint_id_string_wo = [] + for joint_id_string in list(self.node_dict.values()): + if joint_id_string[0] == 'L' and joint_id_string[1].isupper(): + joint_id_string_wo.append(joint_id_string[1:]) + elif joint_id_string[0] == 'R' and joint_id_string[1].isupper(): + joint_id_string_wo.append(joint_id_string[1:]) + else: + joint_id_string_wo.append(joint_id_string) + unique_strings = list(dict.fromkeys(joint_id_string_wo)) + joint_ids = [unique_strings.index(s) for s in joint_id_string_wo] + return torch.tensor(joint_ids) + + @property + def adj_matrix(self): + return get_adj_matrix(limbseq=self.node_limbseq, num_nodes=self.num_nodes) + + + @property + def plot_adj(self): + plot_matrix(self.adj_matrix, list(self.node_dict.values())) + + def get_limbseq(self): + limbseq = self.limbseq if self.if_consider_hip else self.node_limbseq + return limbseq + + def reachability_matrix(self, factor=0.5, stop_at='hips'): + # stop_at=0 + adj = self.adj_matrix + reach = torch.zeros_like(adj) + if stop_at is not None: + if stop_at == 'hips': + stop_at = [k for k, v in self.node_dict.items() if 'hip' in v.lower()] + elif stop_at == 'bmn': + stop_at = [k for k, v in self.node_dict.items() if 'bmn' in v.lower()] + else: + assert 0, "Not implemented" + def is_reachable(i, j, list_visited_nodes=[]): + def last_node_reached(k): + if stop_at is None: + return False + elif isinstance(stop_at, list): + return k in stop_at + return k == stop_at + + if adj[i,j] == 1: + return 1 + else: + reachable_paths = [0] + reachable_nodes = ['hip'] + for k in range(self.num_nodes): + if adj[i,k] == 1: + if last_node_reached(k): + return 0 + if k not in list_visited_nodes: + reached = is_reachable(k, j, list_visited_nodes+[k]) + if reached > 0: + if 0 in reachable_paths: + reachable_paths.pop(0) + reachable_nodes = reachable_nodes[1:] + reachable_paths.append(reached + 1) + reachable_nodes.append(self.node_dict[k]) + return min(reachable_paths) + + for i in range(0, reach.shape[0]): + for j in range(i+1, reach.shape[1]): + reach[i, j] = factor**(is_reachable(i, j)-1) if is_reachable(i, j) > 0 else 0 + reach[j, i] = reach[i, j] + return reach + + + def extract_limb_length(self, kpts, mode="metric"): + limbdist = [] + limbseq = self.limbseq if mode == "metric" else self.node_limbseq + for l1,l2 in limbseq: + limbdist.append( (kpts[..., l1, :] - kpts[..., l2, :]).norm(dim=-1)) + return torch.stack(limbdist, dim=-1) + + def get_node_num(self, NODE_NAME): + NODE_NUM = { v: k for k, v in self.joint_dict_orig.items()}[NODE_NAME] + return NODE_NUM \ No newline at end of file diff --git a/SkeletonDiffusion/src/data/skeleton/kinematic/freeman.py b/SkeletonDiffusion/src/data/skeleton/kinematic/freeman.py new file mode 100644 index 0000000000000000000000000000000000000000..e21d7aba82351145bf3aba060ac7cb9f2d055d16 --- /dev/null +++ b/SkeletonDiffusion/src/data/skeleton/kinematic/freeman.py @@ -0,0 +1,43 @@ +import torch +import numpy as np +from .base import Kinematic + +class FreeManKinematic(Kinematic): + def __init__(self, **kwargs): + + super().__init__(**kwargs) + + self.joint_dict_orig = {0: 'GlobalRoot', 1: 'LHip', 2: 'RHip', + 3: 'LKnee', 4: 'RKnee', 5: 'LAnkle', 6: 'RAnkle', + 7: 'Nose', 8: 'LEye', 9: 'REye', 10: 'LEar', 11: 'REar', + 12: 'LShoulder', 13: 'RShoulder', 14: 'LElbow', 15: 'RElbow', 16: 'LWrist', 17: 'RWrist'} + self.limbseq = [[0, 1], [0, 2], [1, 3], [2, 4], [3, 5], [4, 6], + [0, 7], [7, 8], [7, 9], [8, 10], [9, 11], + [7, 12], [7, 13], [12, 14], [13, 15], [14, 16], [15, 17]] + assert self.num_joints ==18 + + self.left_right_limb_list = [False if joint[0] == "L" and joint[1].isupper() else True for joint in list(self.joint_dict_orig.values())] + + + if not self.if_consider_hip: + self.node_dict = self.joint_dict_orig.copy() + self.node_dict.pop(0) + self.node_dict = {i:v for i,v in enumerate(list(self.node_dict.values()))} + node_dict_reversed = {v:i for i,v in self.node_dict.items()} + self.node_limbseq = [[node_dict_reversed['RHip'], node_dict_reversed['LHip']], + [node_dict_reversed['RHip'], node_dict_reversed['Nose']], + [node_dict_reversed['LHip'], node_dict_reversed['Nose']], + *[[limb[0] -1, limb[1] -1] for limb in self.limbseq if limb[1] != 0 and limb[0] != 0]] + self.limb_angles_idx = [[0,1,7,9], [0,4,6], [1,8,10], [3,5], [2,11,13, 15], [1,12,14,16]] + self.kinchain = [[0,6,7,9,10,8], # hip to head + [6,11,13,15], # left arm + [6,12,14,16], # right arm + [0,2,4], # left leg + [1,3,5], # right leg + [0,1], [7,8], # hip triangle + ] + + else: + self.node_dict = {k:v for k,v in enumerate(list(self.node_hip.values())+list(self.joint_dict_orig.values())[1:])} + self.node_limbseq = self.limbseq.copy() + self.limbseq = np.array(self.limbseq) diff --git a/SkeletonDiffusion/src/data/skeleton/kinematic/h36m.py b/SkeletonDiffusion/src/data/skeleton/kinematic/h36m.py new file mode 100644 index 0000000000000000000000000000000000000000..af8b43ac09bf20dc244daf64853af31f3b2609cc --- /dev/null +++ b/SkeletonDiffusion/src/data/skeleton/kinematic/h36m.py @@ -0,0 +1,111 @@ +import torch +import numpy as np +from .base import Kinematic + +##################################################################################################################### +#### Human3.6M joint representation +##################################################################################################################### + +# for human36m. Dataset gives 32 jionts, with duplicates +JOINTS_DICT_H36M_32 = {0: "Hip", + 1: "RHip", 2: "RKnee", 3: "RAnkle", 4: "RFoot", 5: "RToes", + 6: "LHip", 7: "LKnee", 8: "LAnkle", 9: "LFoot", 10: "LToes", + 11: "Hip", + 12: "Torso", 13: "Neck", 14: "Nose", 15: "Head", + 16: "Nose", + 17: "LShoulder", 18: "LElbow", 19: "LWrist", + 20: "LHand", 21: "LSmallFinger", 22: "LCenterFinger", 23: "LThumb", + 24: "Nose", + 25: "RShoulder", 26: "RElbow", 27: "RWrist", + 28: "RHand", 29: "RSmallFinger", 30: "RCenterFinger", 31: "RThumb", } + +# representation without duplicates. 25 joints. +CONVERSION_IDX_H36M_32TO25 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 17, 18, 19, 21, 22, 25, 26, 27, 29, 30] +JOINTS_DICT_H36M_25 = {0: "Hip", + 1: "RHip", 2: "RKnee", 3: "RAnkle", 4: "RFoot", 5: "RToes", + 6: "LHip", 7: "LKnee", 8: "LAnkle", 9: "LFoot", 10: "LToes", + 11: "Torso", 12: "Neck", 13: "Nose", 14: "Head", + 15: "LShoulder", 16: "LElbow", 17: "LWrist", + 18: "LSmallFinger", 19: "LThumb", + 20: "RShoulder", 21: "RElbow", 22: "RWrist", + 23: "RSmallFinger", 24: "RThumb"} +CENTER_JOINT_H36M_25 = 0 +LIMBSEQ_H36M_25 = [[0, 1], [0,6], #hips + [1,2], [2,3], [3,4], [4,5], # right foot + [6,7], [7,8], [8,9], [9,10], # left foot + [0,11], [11,12], [12,13], [13,14], # torso and head + [12,15], [12,20], # shoulders + [15,16], [16,17], [17,18], [17,19], # left hand + [20,21], [21,22], [22,23], [22,24] # right hand + ] + + +# removing feet and hands results in a 17 representation, which DIFFERS from other 17-joints representations (COCO, OpenPose, FreeMan, CHeck again for COCO and OpenPose). It is the same as BelFusion. +CONVERSION_IDX_H36M_32TO17 = [0, 1, 2, 3, 6, 7, 8, 12, 13, 14, 15, 17, 18, 19, 25, 26, 27] + +JOINTS_DICT_H36M_17 = {0: 'Hip', 1: 'RHip', 2: 'RKnee', 3: 'RAnkle', 4: 'LHip', 5: 'LKnee', 6: 'LAnkle', + 7: 'Torso', 8: 'Neck', 9: 'Nose', 10: 'Head', + 11: 'LShoulder', 12: 'LElbow', 13: 'LWrist', 14: 'RShoulder', 15: 'RElbow',16: 'RWrist'} + +CENTER_JOINT_H36M_17 = 0 +LIMBSEQ_H36M_17 = [[0, 1], [0,4], #hips + [1,2], [2,3], # right foot + [4,5], [5,6], # left foot + [0,7], [7,8], [8,9], [9,10], # torso and head + [8,11], [8,14], # shoulders + [11,12], [12,13], # left hand + [14,15], [15,16] # right hand + ] + + +assert len(JOINTS_DICT_H36M_32) == 32 +assert len(JOINTS_DICT_H36M_25) == 25 +assert len(CONVERSION_IDX_H36M_32TO25) == 25 +assert len(JOINTS_DICT_H36M_17) == 17 +assert len(CONVERSION_IDX_H36M_32TO17) == 17 + + +class H36MKinematic(Kinematic): + def __init__(self, num_joints=17, **kwargs): + + super().__init__(**kwargs) + + assert num_joints in [17, 25] + if num_joints == 17: + self.joint_dict_orig = JOINTS_DICT_H36M_17.copy() + self.limbseq = LIMBSEQ_H36M_17.copy() + elif num_joints == 25: + self.joint_dict_orig = JOINTS_DICT_H36M_25.copy() + self.limbseq = LIMBSEQ_H36M_25.copy() + self.joint_dict_orig[0] = 'GlobalRoot' + self.left_right_limb_list = [False if joint[0] == "L" and joint[1].isupper() else True for joint in list(self.joint_dict_orig.values())] + + # self.node_limbseq = [[limb[0] -1, limb[1] -1] for limb in self.limbseq if limb[1] != 0 and limb[0] != 0] + # # rememeber to add hip connections! + # else: + # self.node_dict = self.joint_dict_orig + # self.node_limbseq = self.limbseq + + if not self.if_consider_hip: + self.node_dict = self.joint_dict_orig.copy() + self.node_dict.pop(0) + self.node_dict = {i:v for i,v in enumerate(list(self.node_dict.values()))} + node_dict_reversed = {v:i for i,v in self.node_dict.items()} + self.node_limbseq = [[node_dict_reversed['RHip'], node_dict_reversed['LHip']], + [node_dict_reversed['RHip'], node_dict_reversed['Torso']], + [node_dict_reversed['LHip'], node_dict_reversed['Torso']], + *[[limb[0] -1, limb[1] -1] for limb in self.limbseq if limb[1] != 0 and limb[0] != 0]] + assert num_joints == 17 + self.limb_angles_idx = [[3,4], [0,2,7,8,9], [1,7,10,12,13], [7,11,14,15]] + self.kinchain = [[0,6,7,8,9], # hip to head + [7,10,11,12], # left arm + [7,13,14,15], # right arm + [3,4,5], # left leg + [0,1,2], # right leg + [0,3,6], # hip triangle + ] + else: + self.node_dict = {k:v for k,v in enumerate(list(self.node_hip.values())+list(self.joint_dict_orig.values())[1:])} + self.node_limbseq = self.limbseq.copy() + # self.limb_angles_idx = [[3,4], [0,2,7,8,9], [1,7,10,12,13], [7,11,14,15]] + self.limbseq = np.array(self.limbseq) diff --git a/SkeletonDiffusion/src/data/skeleton/kinematic/utils.py b/SkeletonDiffusion/src/data/skeleton/kinematic/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..4126802318e5b9aa0950d0adc9b57370180b95af --- /dev/null +++ b/SkeletonDiffusion/src/data/skeleton/kinematic/utils.py @@ -0,0 +1,44 @@ +from typing import List, Tuple, Optional +import torch + +def get_adj_matrix(limbseq:List[Tuple[int]], num_nodes: Optional[int]=None): + if num_nodes is None: + assert 0, "Not tested, it is probably bugged" + num_nodes = max([max(l) for l in limbseq]) + + adj = torch.zeros((num_nodes, num_nodes)) + for i, j in limbseq: + adj[i, j] = 1 + adj[j, i] = 1 + return adj + + +def plot_matrix(matrix, node_names): + import matplotlib + import matplotlib.pyplot as plt + from matplotlib.colors import ListedColormap + import numpy as np + + Sigma_N = matrix.cpu().clone().numpy() + color = 'Purples' + cmap = matplotlib.colormaps[color].set_bad("white") + # cmap[0] = + # colormap_r = ListedColormap(cmap.colors[::-1]) + + fig, ax = plt.subplots(1,1, figsize=(6, 6),sharex=True, subplot_kw=dict(box_aspect=1),) + # cax = fig.add_axes([0.93, 0.15, 0.01, 0.7]) # Adjust the position and size of the colorbar + # for i, ax in enumerate(axes): + vmax = Sigma_N.max() + Sigma_N[Sigma_N <=0.0000] = np.nan + im = ax.imshow(Sigma_N, cmap=color, vmin=0., vmax=vmax) + ax.set_xticks(np.arange(len(Sigma_N))) + ax.set_xticklabels(labels=node_names, rotation=45, ha="right", + rotation_mode="anchor") + ax.set_yticks(np.arange(len(Sigma_N))) + ax.set_yticklabels(labels=node_names, rotation=45, ha="right", + rotation_mode="anchor") + # ax.set_title(list(method2sigman.keys())[i]) + fig.colorbar(im, cmap=cmap) +# plt.title('Adjancecy Matrix') + plt.show() + fig.savefig("./today.pdf", format="pdf", bbox_inches="tight") \ No newline at end of file diff --git a/SkeletonDiffusion/src/data/skeleton/motion/__init__.py b/SkeletonDiffusion/src/data/skeleton/motion/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..c6c4fb7178a188689a279e67e5f53ef032e28a1a --- /dev/null +++ b/SkeletonDiffusion/src/data/skeleton/motion/__init__.py @@ -0,0 +1,8 @@ +from .utils import center_kpts_around_hip_and_drop_root +from .centerpose import SkeletonCenterPose +from .rescalepose import SkeletonRescalePose +from .dct import SkeletonDiscreteCosineTransform + + +def get_motion_representation_objclass(motion_repr_type): + return globals()[motion_repr_type] \ No newline at end of file diff --git a/SkeletonDiffusion/src/data/skeleton/motion/base.py b/SkeletonDiffusion/src/data/skeleton/motion/base.py new file mode 100644 index 0000000000000000000000000000000000000000..2a3bead4395c99ec9a5df8ac78d2baa78f526df5 --- /dev/null +++ b/SkeletonDiffusion/src/data/skeleton/motion/base.py @@ -0,0 +1,96 @@ +import torch + + +class Skeleton(): + node_hip = {0: 'GlobalRoot'} + + def __init__(self, if_consider_hip=True, obs_length=50, pred_length=100, seq_centering: int = 0, **kwargs): + + self.if_consider_hip = if_consider_hip + self.obs_length = obs_length + self.pred_length = pred_length + assert all([len(val.replace('Hip', ''))>1 for val in self.node_hip.values()]) # in this way it will have a different joint_id mapping from the other centered hip joints. + + + self.seq_centering = seq_centering + assert self.seq_centering < 0 or self.seq_centering < self.obs_length+self.pred_length, "seq_centering should be less than total seq length" + + + ################# functions to obtain input poses ######################################################################################## + # THese funcitons take all kpts as input and return all kpts as output (not only pose or hip) + def transform_hip_to_input_space(self, data): + def _get_where_is_seq_centered(self): + if self.seq_centering < 0: + return self.obs_length+self.seq_centering + assert 0, "This was changed from - to +, so your old exps are not reproducible..." + else: + return self.seq_centering + centered, hips = data[..., 1:, :], data[..., 0:1, :] + #set beginning of seq to where_isZero + # hips = hips - hips[...,0,:,:].unsqueeze(-3) + where_isZero = self._get_where_is_seq_centered() + hips = hips - hips[...,where_isZero,:,:].unsqueeze(-3) + return torch.cat([hips, centered], dim=-2) + + def tranform_to_input_space(self, data): + data = self.tranform_to_input_space_pose_only(data) + # centered, hips = data[..., 1:, :], data[..., 0, :].unsqueeze(-2) + if not self.if_consider_hip: + kpts = data[..., 1:, :] + else: + kpts = self.transform_hip_to_input_space(data) + return kpts + + def tranform_to_input_space_pose_only(self, data): + ... + return data + + def add_zero_pad_center_hip(self, kpts): + shape = list(kpts.shape) + shape[-2] = 1 + kpts = torch.cat([torch.zeros(shape, device=kpts.device), kpts], dim=-2) + return kpts + + def if_add_zero_pad_center_hip(self, kpts): + if not self.if_consider_hip and kpts.shape[-2] == self.num_joints - 1: + kpts =self.add_zero_pad_center_hip(kpts) + return kpts + + ########################## function to tranform back to metric space ########################################################################## + + def transform_hip_to_metric_space(self, kpts): + ... + return kpts + + def _merge_hip_and_poseinmetricspace(self, hip_coords, kpts): + ... + return torch.cat([hip_coords, kpts], dim=-2) + + def transform_to_metric_space(self, kpts): + """_summary_ + + Returns: + kpts: kpts in 3D coordinates + """ + + if self.if_consider_hip: + kpts = self.transform_hip_to_metric_space(kpts) # hip is now represented in metric space, so it is first location. + hip_coords = kpts[...,:1,:] + kpts = self.transform_to_metric_space_pose_only(kpts[...,1:,:]) + # kpts += hip_coords + return self._merge_hip_and_poseinmetricspace(hip_coords, kpts) + + else: + # input is without hips. + kpts = self.transform_to_metric_space_pose_only(kpts) + return kpts + + def transform_to_metric_space_pose_only(self, kpts): + """This is the only funtion that tkaes as input the pose and returns the pose joints""" + ... + return kpts + + + + + diff --git a/SkeletonDiffusion/src/data/skeleton/motion/centerpose.py b/SkeletonDiffusion/src/data/skeleton/motion/centerpose.py new file mode 100644 index 0000000000000000000000000000000000000000..1ceebfd13721c0d0d64904dd55a2bde70fcb87ea --- /dev/null +++ b/SkeletonDiffusion/src/data/skeleton/motion/centerpose.py @@ -0,0 +1,23 @@ +import torch + +from .utils import center_kpts_around_hip +from .base import Skeleton + +class SkeletonCenterPose(Skeleton): + """ + Skeleton class for vanilla skekelton (no particulara data reresentation, no normalization, no direction) + Does NOT center the pose around the hip. Leaves everythign as it is. + Bsically instantiable version of basic abstract class Skeleton without centering. + if we consider the hip, nothing is done but just the sequence start is shifted. + """ + def tranform_to_input_space_pose_only(self, data): + #center kpts + centered, hips = center_kpts_around_hip(data, hip_idx=0) + + kpts = torch.cat([hips, centered[...,len(self.node_hip):,:]], dim=-2) + return kpts + + def _merge_hip_and_poseinmetricspace(self, hip_coords, kpts): + kpts += hip_coords + return super()._merge_hip_and_poseinmetricspace(hip_coords, kpts) + \ No newline at end of file diff --git a/SkeletonDiffusion/src/data/skeleton/motion/dct.py b/SkeletonDiffusion/src/data/skeleton/motion/dct.py new file mode 100644 index 0000000000000000000000000000000000000000..bef8a203cdc0a4f32205fd34a784f90bc1360925 --- /dev/null +++ b/SkeletonDiffusion/src/data/skeleton/motion/dct.py @@ -0,0 +1,81 @@ +import numpy as np +import torch + +from .centerpose import SkeletonCenterPose + +def get_dct_matrix(N, is_torch=True): + dct_m = np.eye(N) + for k in np.arange(N): + for i in np.arange(N): + w = np.sqrt(2 / N) + if k == 0: + w = np.sqrt(1 / N) + dct_m[k, i] = w * np.cos(np.pi * (i + 1 / 2) * k / N) # DCT-II + idct_m = np.linalg.inv(dct_m) + if is_torch: + dct_m = torch.from_numpy(dct_m).float() + idct_m = torch.from_numpy(idct_m).float() + return dct_m, idct_m + +def dct_transform_torch(data, dct_m, dct_n): + *B, seq_len, features, d = data.shape + if len(B)==1: + data = torch.einsum('dn,bncf->bdcf', dct_m.to(data.device), data) + else: + data = torch.einsum('dn,ncf->dcf', dct_m.to(data.device), data) + return data + +def reverse_dct_torch(dct_data, idct_m): + *B, seq_len, j, d = dct_data.shape + if len(B)==1: + dct_data = torch.einsum('dn,bncf->bdcf', idct_m.to(dct_data.device), dct_data) + elif len(B)==2: + dct_data = torch.einsum('dn,bsncf->bsdcf', idct_m.to(dct_data.device), dct_data) + else: + dct_data = torch.einsum('dn,ncf->dcf', idct_m.to(dct_data.device), dct_data) + return dct_data + + +class SkeletonDiscreteCosineTransform(SkeletonCenterPose): + + def __init__(self, **kwargs): + super().__init__(**kwargs) + + self.n_pre = self.pred_length + self.dct_m_fut, self.idct_m_fut = get_dct_matrix(self.n_pre, is_torch=True) + self.dct_m_past, self.idct_m_past = get_dct_matrix(self.obs_length, is_torch=True) + + + def tranform_to_input_space_pose_only(self, data): + data = super().tranform_to_input_space_pose_only(data) + if data.shape[-3] == self.pred_length: + data_dct = dct_transform_torch(data, self.dct_m_fut, self.n_pre) + else: + obs, fut = data[..., :self.obs_length, :, :], data[..., self.obs_length:, :, :] + obs_dct = dct_transform_torch(obs, self.dct_m_past, self.obs_length) + fut_dct = dct_transform_torch(fut, self.dct_m_fut, self.n_pre) + data_dct = torch.cat([obs_dct, fut_dct], dim=-3) + return data_dct + + def transform_hip_to_input_space(self, data): + data = super().transform_hip_to_input_space(data) + hip, pose = data[..., 0:1, :], data[..., 1:, :] + assert 0, "This function is not implemented" + hip_dct = torch.matmul(self.dct_m[:self.n_pre], hip) + kpts = torch.cat([hip_dct, pose], dim=-2) + return kpts + + ############################## function to tranform back to metric space ########################################################################## + + def transform_hip_to_metric_space(self, kpts): + hip, pose = kpts[..., 0:1, :], kpts[..., 1:, :] + hip = torch.matmul(self.idct_m[:self.n_pre], hip) + kpts = torch.cat([hip, pose], dim=-2) + return kpts + + def transform_to_metric_space_pose_only(self, kpts): + """This is the only funtion that tkaes as input the pose and returns the pose joints""" + assert kpts.shape[-3] in[self.pred_length, self.obs_length], "The input shape is not correct" + idct_m = self.idct_m_fut if kpts.shape[-3] == self.pred_length else self.idct_m_past + pose = reverse_dct_torch(kpts, idct_m) + return pose \ No newline at end of file diff --git a/SkeletonDiffusion/src/data/skeleton/motion/rescalepose.py b/SkeletonDiffusion/src/data/skeleton/motion/rescalepose.py new file mode 100644 index 0000000000000000000000000000000000000000..0a9dcde312a585ea34a48f6a438377d295e30771 --- /dev/null +++ b/SkeletonDiffusion/src/data/skeleton/motion/rescalepose.py @@ -0,0 +1,40 @@ +import torch + +from .utils import center_kpts_around_hip +from .centerpose import SkeletonCenterPose + +class SkeletonRescalePose(SkeletonCenterPose): + """ + Poses are not only centered like in Skeleton, but also scaled in a unit cube. + Abstract class + """ + def __init__(self, pose_box_size=1.1, **kwargs): + super().__init__(**kwargs) + self.pose_box_size = pose_box_size # in m. not in mm + + ################# functions to obtain input poses ######################################################################################## + + def tranform_to_input_space_pose_only(self, data): + #center kpts + centered, hips = center_kpts_around_hip(data, hip_idx=0) + + lower_box_shift = self.pose_box_size # in mm + centered /= lower_box_shift + # assert (centered >= -1.).all() and (centered <= 1.).all(), f"{centered.max()} {centered.min()}" + kpts = torch.cat([hips, centered[...,1:,:]], dim=-2) + return kpts + + ########################## function to tranform back to metric space ########################################################################## + + def transform_to_metric_space_pose_only(self, kpts): + kpts = self._rescale_to_hip_box(kpts) + return kpts + + def _rescale_to_hip_box(self, kpts): + kpts = kpts.clone() + + lower_box_shift = self.pose_box_size # in mm + # range [-1,1] around hips + kpts *= lower_box_shift # scaled back to box around kpts + return kpts + diff --git a/SkeletonDiffusion/src/data/skeleton/motion/utils.py b/SkeletonDiffusion/src/data/skeleton/motion/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..6b6826a6b3bac84e39316c7d151500ce4f8a695d --- /dev/null +++ b/SkeletonDiffusion/src/data/skeleton/motion/utils.py @@ -0,0 +1,13 @@ + + +def center_kpts_around_hip(kpts, hip_idx=0): + #hip is always joint n0 in h36m regardless of number of joints considered + center = kpts[..., hip_idx, :].unsqueeze(-2) #(n_frames, n_joints, 3) + centered_kpts = kpts - center + # centered_kpts = centered_kpts[..., 1:, :] # keep hip joint for compatibility with rest of code + return centered_kpts, center + +def center_kpts_around_hip_and_drop_root(kpts, hip_idx=0): + centered_kpts, center = center_kpts_around_hip(kpts.clone(), hip_idx) + centered_kpts = centered_kpts[..., 1:, :] + return centered_kpts \ No newline at end of file diff --git a/SkeletonDiffusion/src/eval.py b/SkeletonDiffusion/src/eval.py new file mode 100644 index 0000000000000000000000000000000000000000..1c67d3444b2215b87aaa96df36d2f7b5ad82a237 --- /dev/null +++ b/SkeletonDiffusion/src/eval.py @@ -0,0 +1,231 @@ +import os +import json +import yaml +import time +import argparse +import pandas as pd +from functools import partial +import numpy as np +import math +import torch +from ignite.engine import Engine +from ignite.engine import Events, Engine +from ignite.contrib.handlers import ProgressBar + +from utils.reproducibility import set_seed +from metrics.utils import draw_table, get_best_sample_idx +from metrics import MetricStorer +from utils.config import merge_cfg +from utils.store import SequenceStorer +from utils.time import AverageTimer +from eval_utils import get_stats_funcs, get_cmd_storer, prepare_eval_dataset, get_apde_storer, get_fid_storer, long_term_prediction_best_every50 as long_term_prediction + +NDEBUG = False + +os.environ["CUBLAS_WORKSPACE_CONFIG"] = ":4096:8" + + + +def compute_metrics(dataset_split, store_folder, batch_size, num_samples=50, if_measure_time=False, + prepare_model=None, get_prediction=None, process_evaluation_pair=None, + silent=False, stats_mode="no_mm", metrics_at_cpu=False, if_store_output=False, if_store_gt=False, + store_output_path=None, store_gt_path=None, if_compute_apde=False, if_compute_fid=False, if_compute_cmd=False, **config): + + torch.set_default_dtype(torch.float64 if config["dtype"]== "float64" else torch.float32) + + data_loader, dataset, skeleton = prepare_eval_dataset(config, split=dataset_split, drop_last=False, num_workers=0, batch_size=batch_size, stats_mode=stats_mode) + if store_folder is not None: + store_folder = os.path.join(store_folder, f"obs{dataset.obs_length}pred{dataset.pred_length}") + os.makedirs(store_folder, exist_ok=True) + model, device, *_ = prepare_model(config, skeleton) + stats_func = get_stats_funcs(stats_mode, skeleton=skeleton, **config) + print('Computing metrics at ', 'cpu.' if metrics_at_cpu else 'gpu.') + pred_storer = SequenceStorer(store_output_path, num_samples, len(dataset), config) if if_store_output else None + gt_storer = SequenceStorer(store_gt_path, num_samples, len(dataset), config, if_gt=True) if if_store_gt else None + timer = AverageTimer() if if_measure_time else None + def preprocess(engine: Engine): + def mmgt_to_device(extradict): + if 'mm_gt' in extradict: + extradict['mm_gt'] = [mmgt.to(device) for mmgt in extradict['mm_gt']] + return extradict + engine.state.batch = [t.to(device) if i<2 else mmgt_to_device(t) for i, t in enumerate(engine.state.batch)] + + def set_epoch_seed(engine: Engine): + set_seed(config['seed']) + + def finalize_storing(engine: Engine): + if if_store_gt: + gt_storer.finalize_store() + if if_store_output: + pred_storer.finalize_store() + if if_measure_time: + timer.print_avg() + + def store_step(data, target, pred, extra, dataset): + if if_store_output: + pred_storer.store_batch(pred, extra, dataset) + if if_store_gt: + gt_storer.store_batch((target, data), extra, dataset) + + + + def process_function(engine, batch): + with torch.no_grad(): + data, target, extra = batch + if config['if_long_term_test'] and config['long_term_factor'] > 1: + target, pred, mm_gt, data = long_term_prediction(data, target, extra, get_prediction=partial(get_prediction,model=model), + process_evaluation_pair=partial(process_evaluation_pair, skeleton=skeleton), num_samples=num_samples, config=config) + else: + if if_measure_time: timer.start() + pred = get_prediction(data, model, num_samples=num_samples, pred_length=config['pred_length'], extra=extra) # [batch_size, n_samples, seq_length, num_joints, features] + if if_measure_time: timer.end() + target, pred, mm_gt, data = process_evaluation_pair(skeleton, target=target, pred_dict={'pred': pred, 'obs': data, 'mm_gt': extra['mm_gt'] if 'mm_gt' in extra else None}) + + store_step(data, target, pred, extra, dataset) + if metrics_at_cpu: + pred = pred.detach().cpu() + target = target.detach().cpu() + mm_gt = [mmgt.detach().cpu() for mmgt in mm_gt] + outdict = {'pred':pred, 'target':target, 'extra':extra, 'mm_gt': mm_gt, 'obs': data} + return outdict + + + + engine = Engine(process_function) + engine.add_event_handler(Events.ITERATION_STARTED, preprocess) + engine.add_event_handler(Events.EPOCH_STARTED, set_epoch_seed) + engine.add_event_handler(Events.EPOCH_COMPLETED, finalize_storing) + pbar = ProgressBar() + pbar.attach(engine) + + stats_metrics = {k: MetricStorer(output_transform=lambda *args, **kwargs: funct(*args, **kwargs.copy()), + return_op='max' if '_max' in k else 'avg') for k, funct in stats_func.items()} + for name, metric in stats_metrics.items(): + metric.attach(engine, name) + + if config['dataset_name'] == 'h36m' and dataset_split == 'test' and if_compute_fid: + fid_storer, funct = get_fid_storer(**config) + apde_metrics = {'FID': fid_storer(output_transform=funct)} + for name, metric in apde_metrics.items(): + metric.attach(engine, name) + + if dataset_split=='test' and if_compute_cmd: + cmd_storer = get_cmd_storer(dataset, **config) + cmd_metrics = {cmd_name: cmdclass(output_transform=lambda x_dict: funct(**x_dict.copy())) + for cmd_name, (cmdclass, funct) in cmd_storer.items()} + for name, metric in cmd_metrics.items(): + metric.attach(engine, name) + if if_compute_apde: + storer, funct = get_apde_storer(**config) + apde_metrics = {'APDE': storer(output_transform=lambda x_dict: funct(**x_dict.copy()))} + for name, metric in apde_metrics.items(): + metric.attach(engine, name) + + if NDEBUG: + engine.run(data_loader, max_epochs=1, epoch_length=1) + else: engine.run(data_loader) + results = engine.state.metrics + + # ----------------------------- Printing results ----------------------------- + print('=' * 80) + table = draw_table(results) + print(table) + for stats in results: + if stats.replace("traj", "").replace("pose", "") not in ['MPJPE', 'ADE', 'FDE', 'APD', 'MMADE', 'MMFDE']: + if isinstance(results[stats], list) or isinstance(results[stats], np.ndarray) or isinstance(results[stats], tuple): + print(f'Total {stats}: ', results[stats]) + else: + print(f'Total {stats}: {results[stats]:.4f}') + print('=' * 80) + # ----------------------------- Storing overall results ----------------------------- + for key, value in results.items(): + results[key] = float(value) + ov_path = os.path.join(store_folder, f"results_{num_samples}_{stats_mode}.yaml") + with open(ov_path, "w") as f: + yaml.dump(results, f, indent=4) + + + print(f"Overall results saved to {ov_path}") + print('=' * 80) + + + +# model specific options go to hydra +from omegaconf import DictConfig, OmegaConf +import hydra +OmegaConf.register_new_resolver("eval", eval) +@hydra.main(config_path="../configs/config_eval", config_name="config", version_base="1.3.2") +def main_hydra(cfg: DictConfig): + cfg = OmegaConf.to_container(cfg, resolve=True) + # for backwards compatibility with the code + for subconf in ['task', 'dataset']: + if subconf in cfg: + cfg = {**cfg, **cfg[subconf]} + cfg.pop(subconf) + if 'motion_repr_type' not in cfg: + cfg['motion_repr_type'] = "SkeletonRescalePose" + cfg['diffusion_type'] = 'NonisotropicGaussianDiffusion' + cfg['diffusion_covariance_type'] = 'skeleton-diffusion' + main(**cfg) + +def main(checkpoint_path, method_name='mmugoon', dataset_split='valid', seed=0, stats_mode='motpred', **cfg): + """setup""" + set_seed(seed) + + # build the config/checkpoint path + if 'baseline' in method_name.lower(): + checkpoint_path = f"{cfg['method_specs']['baseline_out_path']}/{cfg['task_name']}/{method_name.lower().replace('baseline', '')}/{cfg['dataset_name']}" + else: + assert ".pt" in checkpoint_path, "Path should point to model save" + if not os.path.exists(checkpoint_path): + raise Exception(f"Checkpoint not found in: %s" % checkpoint_path) + + + # decide from which file to load the functions depending on which model we are evaluating + if method_name == 'SkeletonDiffusion' : + from eval_prepare_model import prepare_model, get_prediction, process_evaluation_pair, load_model_config_exp, get_eval_out_folder + elif 'baseline' in method_name.lower(): + from eval_prepare_algorithmic_baseline import prepare_model, get_prediction, process_evaluation_pair, load_model_config_exp, get_eval_out_folder + else: + raise NotImplementedError() + + # load config + cfg_orig, exp_folder = load_model_config_exp(checkpoint_path) + # merge original experiment config with the current evaluation config + cfg = merge_cfg(cfg, cfg_orig) + cfg = merge_cfg(cfg, cfg['method_specs']) + cfg['seed'] = seed + + # set up evaluation functions + # can also be done method dependent wise + prepare_model = partial(prepare_model, **cfg) # check wheter we have later conflict because of method specs + get_prediction = partial(get_prediction, **cfg) + + + stats_folder = get_eval_out_folder(exp_folder, checkpoint_path, dataset_split, cfg) + with open(os.path.join(stats_folder, 'eval_config.yaml'), 'w') as config_file: + OmegaConf.save(cfg, config_file) + + print("Experiment data loaded from ", exp_folder) + + data_loader_name = f"data_loader_{dataset_split}" + assert 'segments_path' in cfg[data_loader_name], "We are not evaluating on segmetns" + + print(f"> Dataset: '{cfg['dataset_name']}'") + print(f"> Exp name: '{exp_folder.split('/')[-1]}'") + print(f"> Checkpoint: '{checkpoint_path.split('/')[-1]}'") + print(f"> Prediction Horizon: '{cfg['pred_length'] if 'extended_pred_length' not in cfg else cfg['extended_pred_length']}'") + + print(f"[WARNING] Remember: batch_size has an effect over the randomness of results. Keep batch_size fixed for comparisons, or implement several runs with different seeds to reduce stochasticity.") + + t0 = time.time() + compute_metrics(dataset_split=dataset_split, stats_mode=stats_mode, + prepare_model=prepare_model, get_prediction=get_prediction, process_evaluation_pair=process_evaluation_pair, + store_folder=stats_folder, checkpoint_path=checkpoint_path, **cfg + ) + tim = int(time.time() - t0) + print(f"[INFO] Evaluation took {tim // 60}min, {tim % 60}s.") + + +if __name__ == '__main__': + main_hydra() \ No newline at end of file diff --git a/SkeletonDiffusion/src/eval_prepare_algorithmic_baseline.py b/SkeletonDiffusion/src/eval_prepare_algorithmic_baseline.py new file mode 100644 index 0000000000000000000000000000000000000000..d5533367869c4e4de62b591152571b3c36be47c7 --- /dev/null +++ b/SkeletonDiffusion/src/eval_prepare_algorithmic_baseline.py @@ -0,0 +1,80 @@ +import torch +import os +import numpy as np + +class ZeroVelocityBaseline(torch.nn.Module): + def __init__(self, **kwargs): + super(ZeroVelocityBaseline, self).__init__(**kwargs) + + def forward(self, x: torch.Tensor, ph: int = 1) -> torch.Tensor: + last_frame = x[..., -1 ,:,:].unsqueeze(-3).clone() + B, T, J, D = last_frame.shape + last_frame = last_frame.broadcast_to((B, ph, J, D)) + return last_frame + +def load_model_config_exp(checkpoint_path): + """ + Load the config file and the experiment folder from the checkpoint_path + exp_folder: is a absolute or relative path + cfg: dict of configuration + """ + # checkpoint_path = f"../output/baselines/{cfg['task_name']}/{method_name.lower().replace('baseline', '')}/{cfg['dataset_name']}" + exp_folder = checkpoint_path + return {}, exp_folder + + +def get_eval_out_folder(exp_folder, checkpoint_path, data_split, cfg): + """ + Create folder where to store the evaluation results + """ + if_is_long_term = cfg['if_long_term_test'] and cfg['long_term_factor'] > 1 + noise_label = f"_noisyobs{cfg['noise_level']}-{cfg['noise_std']}" if cfg['if_noisy_obs'] else "" + stats_folder = os.path.join(exp_folder, f"eval_{'' if not if_is_long_term else '_longterm'+str(cfg['long_term_factor'])}{noise_label}seed{cfg['seed']}", data_split) + os.makedirs(stats_folder, exist_ok=True) + return stats_folder + + +def prepare_model(config, skeleton, silent=False, **kwargs): + """ + This function must take as input a config_file and at least a second arg (skeleton) and return a laoded model on a device (cpu or cuda) + model, device = prepare_model(config, skeleton, **kwargs) + """ + for i in range(torch.cuda.device_count()): + if not silent: + print(f"> GPU {i} ready: {torch.cuda.get_device_name(i)}") + device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + + torch.set_grad_enabled(False) + baseline_name = config['method_name'] + alg_baseline = globals()[baseline_name]() + alg_baseline = alg_baseline.to(device) + alg_baseline.eval() + + return alg_baseline, device + + +def get_prediction(obs, model, num_samples=50**, kwargs): + """ + Generate num_samples predictions from model and input obs. + return a dict or anything that will be used by process_evaluation_pair + """ + pred = model(obs, ph=kwargs['pred_length']) + pred = pred.unsqueeze(1) #[batch, 1, t, n_joints, 3] + return pred + + +def process_evaluation_pair(skeleton, target, pred_dict): + """ + Process the target and the prediction and return them in the right format for metrics computation + """ + pred, mm_gt = pred_dict['pred'], pred_dict['mm_gt'] + batch_size, n_samples, seq_length, num_joints, features = pred.shape + target = skeleton.transform_to_metric_space(target) + pred = skeleton.transform_to_metric_space(pred) + mm_gt = [skeleton.transform_to_metric_space(gt) for gt in mm_gt] if mm_gt is not None else None + # batch_size, n_samples, n_diffusion_steps, seq_length, num_joints, features = pred.shape + assert features == 3 and list(target.shape) == [batch_size, seq_length, num_joints, features] + # return dummy altent prediction + return target, pred, mm_gt, None + + \ No newline at end of file diff --git a/SkeletonDiffusion/src/eval_prepare_model.py b/SkeletonDiffusion/src/eval_prepare_model.py new file mode 100644 index 0000000000000000000000000000000000000000..ce7ea49a9cca55f76b1ff10da46014930d6cc5b8 --- /dev/null +++ b/SkeletonDiffusion/src/eval_prepare_model.py @@ -0,0 +1,139 @@ +import torch +import os +import yaml + +from SkeletonDiffusion.src.core import DiffusionManager +from SkeletonDiffusion.src.inference_utils import create_model +from SkeletonDiffusion.src.utils.load import load_model_checkpoint +from SkeletonDiffusion.src.utils.config import load_and_merge_autoenc_cfg + +def load_model_config_exp(checkpoint_path): + exp_folder = os.path.dirname(os.path.dirname(checkpoint_path)) + config_path = os.path.join(exp_folder, 'config.yaml') + with open(config_path, 'r') as stream: + cfg_diffusion = yaml.safe_load(stream) + cfg = load_and_merge_autoenc_cfg(cfg_diffusion) + return cfg, exp_folder + +def load_model_config_exp_autoenc(checkpoint_path): + exp_folder = os.path.dirname(os.path.dirname(checkpoint_path)) + config_path = os.path.join(exp_folder, 'config.yaml') + with open(config_path, 'r') as stream: + cfg = yaml.safe_load(stream) + return cfg, exp_folder + + +def get_eval_out_folder(exp_folder, checkpoint_path, data_split, cfg): + checkpoint = checkpoint_path.split("/")[-1].split('_val')[0].split("_")[-1].replace(".pt", "") + long_term_label = '' if not cfg['if_long_term_test'] and cfg['long_term_factor'] > 1 else '_longterm'+str(cfg['long_term_factor']) + noise_label = f"_noisyobs{cfg['noise_level']}-{cfg['noise_std']}" if cfg['if_noisy_obs'] else "" + stats_folder = os.path.join(exp_folder, f"eval_{cfg['dataset_name']}_{cfg['batch_size']}{long_term_label}{noise_label}", data_split, f"{torch.cuda.get_device_name(0).replace(' ', '_')}_seed{cfg['seed']}", f"checkpoint{checkpoint}") + os.makedirs(stats_folder, exist_ok=True) + return stats_folder + +def prepare_autoencoder(config, skeleton, silent=False): + for i in range(torch.cuda.device_count()): + if not silent: + print(f"> GPU {i} ready: {torch.cuda.get_device_name(i)}") + device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + torch.set_grad_enabled(False) + + # build model architecture + config['device'] = device + model = create_model(node_types=skeleton.nodes_type_id, num_nodes=skeleton.num_nodes, **config) + + # Load models + checkpoint_path = config['pretrained_autoencoder_path'] if 'pretrained_autoencoder_path' in config else config['checkpoint_path'] + if not silent: + print('Loading Autoencoder checkpoint: {} ...'.format(checkpoint_path)) + + checkpoint_model = load_model_checkpoint(checkpoint_path) + model.load_state_dict(checkpoint_model['model']) + + if 'n_gpu' in config and config['n_gpu'] > 1: + model = torch.nn.DataParallel(model) + + # prepare model for testing + model = model.to(device) + model.eval() + + return model, device + +def prepare_model(config, skeleton, silent=False, **kwargs): + """ + This function must take as input a config_file and at least a second arg (skeleton) and return a model and a device (cpu or cuda) + model, device = prepare_model(config, skeleton, **kwargs) + """ + + model, device = prepare_autoencoder(config, skeleton, silent=silent) + + # build model architecture + diffusionmanager = DiffusionManager(skeleton=skeleton, num_nodes=skeleton.num_nodes, node_types=skeleton.nodes_type_id, **kwargs) + diffusion = diffusionmanager.get_diffusion().to(device) + # Load models + if not silent: + print('Loading Diffusion checkpoint: {} ...'.format(config['checkpoint_path'])) + + checkpoint_diffusion = load_model_checkpoint(config['checkpoint_path']) + # if config['checkpoint_path'].endswith('.pth.tar'): + # diffusion.load_state_dict(checkpoint_diffusion) + diffusion.load_state_dict(checkpoint_diffusion['model']) + + if 'n_gpu' in config and config['n_gpu'] > 1: + diffusion = torch.nn.DataParallel(diffusion) + + diffusion = diffusion.to(device) + diffusion.eval() + + return (model, diffusion), device, diffusionmanager #, diffusion.num_timesteps toe eventually evaluate different diffusion timesteps + + + +def get_diffusion_latent_codes(obs, model, num_samples=50, **kwargs): + model, diffusion = model + bs, obs_length, j, f = obs.shape + sampler_kwargs = {} if 'sampler_kwargs' not in kwargs else kwargs['sampler_kwargs'] + + past_embedding = model.get_past_embedding(obs) + if kwargs['diffusion_conditioning']: + z_past = past_embedding.repeat_interleave(num_samples, 0) + latent_pred, _ = diffusion.sample(batch_size=bs*num_samples, x_cond=z_past, **sampler_kwargs) + z_past = past_embedding + + else: + latent_pred, _ = diffusion.sample(batch_size=bs*num_samples, **sampler_kwargs) # out_steps has shape -> [N, Joints, Feat] + z_past = model.z_activation(z_past) + + return latent_pred, z_past + +def decode_latent_pred(obs, latent_pred, z_past, model, num_samples=50, pred_length=100, **kwargs): + model, diffusion = model + bs, obs_length, j, f = obs.shape + obs = obs.repeat_interleave(num_samples, 0) + z_past = z_past.repeat_interleave(num_samples, 0) + z_past = z_past.view(bs*num_samples, *z_past.shape[1:]) + pred = model.decode(obs, latent_pred, z_past, ph=pred_length) # [N, t, Joints, 3] + + pred =pred.view(bs, num_samples, pred_length, j, f) + + return pred + +def get_prediction(obs, model, num_samples=50, pred_length=100, **kwargs): + lat_pred, z_past = get_diffusion_latent_codes(obs, model, num_samples=num_samples, **kwargs) + pred = decode_latent_pred(obs, lat_pred, z_past, model, num_samples=num_samples, pred_length=pred_length, **kwargs) + return pred + + +def process_evaluation_pair(skeleton, target, pred_dict): + pred, mm_gt, obs = pred_dict['pred'], pred_dict['mm_gt'], pred_dict['obs'] + target = skeleton.transform_to_metric_space(target) + pred = skeleton.transform_to_metric_space(pred) + obs = skeleton.transform_to_metric_space(obs) + mm_gt = [skeleton.transform_to_metric_space(gt) for gt in mm_gt] if mm_gt is not None else None + + batch_size, n_samples, seq_length, num_joints, features = pred.shape + # batch_size, n_samples, seq_length, num_joints, features = pred.shape + assert features == 3 and list(target.shape) == [batch_size, seq_length, num_joints, features] + return target, pred, mm_gt, obs + + \ No newline at end of file diff --git a/SkeletonDiffusion/src/eval_utils.py b/SkeletonDiffusion/src/eval_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..bc88e56f19075ad1f7584181dbf5ee187bf04885 --- /dev/null +++ b/SkeletonDiffusion/src/eval_utils.py @@ -0,0 +1,164 @@ +import torch +import os +from functools import partial +import numpy as np +from torch.utils.data import DataLoader + +from SkeletonDiffusion.src.utils.config import init_obj +# from metrics import MetricStorerFID, MetricStorerAPDE, apd, ade, mae, fde, mmade, mmfde +# from metrics import limb_stretching_normed_rmse, limb_stretching_normed_mean, limb_jitter_normed_rmse, limb_jitter_normed_mean +# from metrics import CMDMetricStorer, resolve_cmd, motion_for_cmd +from SkeletonDiffusion.src.data import create_skeleton +from SkeletonDiffusion.src.data.loaders import custom_collate_for_mmgt + +from SkeletonDiffusion.src.metrics.fid import get_classifier, MetricStorerFID +from SkeletonDiffusion.src.metrics.multimodal import apd, ade, mae, fde, mmade, mmfde, cmd, mpjpe, lat_apd +from SkeletonDiffusion.src.metrics.apde import MetricStorerAPDE +from SkeletonDiffusion.src.metrics.body_realism import limb_length_variance, limb_length_jitter, limb_length_variation_difference_wrtGT, limb_length_error, limb_stretching_normed_rmse, limb_stretching_normed_mean, limb_jitter_normed_rmse, limb_jitter_normed_mean +from SkeletonDiffusion.src.metrics.utils import draw_table, get_best_sample_idx +from SkeletonDiffusion.src.metrics.metric_storer import MetricStorer +from SkeletonDiffusion.src.metrics.cmd import CMDMetricStorer, resolve_cmd, motion_for_cmd +from SkeletonDiffusion.src.metrics.ignite_mpjpe import MeanPerJointPositionError +from SkeletonDiffusion.src.metrics.ignite_fde import FinalDisplacementError +from SkeletonDiffusion.src.metrics.utils import choose_best_sample + +os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID" + +def get_stats_funcs(stats_mode, skeleton, **kwargs): + limbseq = skeleton.get_limbseq() + limbseq_mae = limbseq.copy() + limb_angles_idx = skeleton.limb_angles_idx.copy() + + limb_stretching_normed_mean = lambda x: limb_stretching_normed_mean(x)*100 + limb_jitter_normed_mean = lambda x: limb_jitter_normed_mean(x)*100 + limb_stretching_normed_rmse = lambda x: limb_stretching_normed_rmse(x)*100 + limb_jitter_normed_rmse = lambda x: limb_jitter_normed_rmse(x)*100 + + assert not kwargs["if_consider_hip"] + if "deterministic" in stats_mode.lower(): + stats_func = { 'ADE': ade, 'FDE': fde , 'MAE': partial(mae, limbseq=limbseq_mae, limb_angles_idx=limb_angles_idx), + 'APD': apd, + 'StretchMean': partial(limb_stretching_normed_mean, limbseq=limbseq), + 'JitterMean': partial(limb_jitter_normed_mean, limbseq=limbseq), + 'StretchRMSE': partial(limb_stretching_normed_rmse, limbseq=limbseq), + 'JitterRMSE': partial(limb_jitter_normed_rmse, limbseq=limbseq), + } + elif "probabilistic_orig" == stats_mode.lower(): + stats_func = { 'APD': apd, 'ADE': ade, 'FDE': fde, + 'MMADE': mmade, 'MMFDE': mmfde, + } + elif "probabilistic" == stats_mode.lower(): + stats_func = { 'ADE': ade, 'FDE': fde , 'MAE': partial(mae, limbseq=limbseq_mae, limb_angles_idx=limb_angles_idx), + 'MMADE': mmade, 'MMFDE': mmfde, + 'APD': apd, + 'StretchMean': partial(limb_stretching_normed_mean, limbseq=limbseq), + 'JitterMean': partial(limb_jitter_normed_mean, limbseq=limbseq), + 'StretchRMSE': partial(limb_stretching_normed_rmse, limbseq=limbseq), + 'JitterRMSE': partial(limb_jitter_normed_rmse, limbseq=limbseq), + } + else : + raise NotImplementedError(f"stats_mode not implemented: {stats_mode}") + return stats_func + +def get_apde_storer(**kwargs): + return partial(MetricStorerAPDE, mmapd_gt_path= os.path.join(kwargs['annotations_folder'], "mmapd_GT.csv")), lambda pred, **kwargs: apd(pred) + +def get_fid_storer(**kwargs): + storer = partial(MetricStorerFID, classifier_path=kwargs['precomputed_folder'], **kwargs) + return storer ,lambda pred, target, **kwgs: (pred, target) + +def get_cmd_storer(dataset, if_consider_hip=False, **kwargs): + assert not if_consider_hip + cmdstorer = {"CMD": ( partial(CMDMetricStorer, final_funct=partial(resolve_cmd, idx_to_class=dataset.idx_to_class, mean_motion_per_class=dataset.mean_motion_per_class)), + lambda pred, extra, **kwgs: (motion_for_cmd(pred.clone()), + np.array([dataset.class_to_idx[c] for c in extra["metadata"][dataset.metadata_class_idx]])) + ), + } + return cmdstorer + +def prepare_eval_dataset(config, split, shuffle=False, augmentation=0, da_mirroring=0, da_rotations=0, drop_last=False, num_workers=None, batch_size=None ,dataset=None, stats_mode="probabilistic", **kwargs): + import data.loaders as dataset_type + data_loader_name = f"data_loader_{split}" + + + config[data_loader_name]["shuffle"] = shuffle + config[data_loader_name]["da_mirroring"] = da_mirroring + config[data_loader_name]["da_rotations"] = da_rotations + config[data_loader_name]["augmentation"] = augmentation + config[data_loader_name]["drop_last"] = drop_last + if "probabilistic" in stats_mode.lower(): + config[data_loader_name]["if_load_mmgt"] = True + else: + config[data_loader_name]["if_load_mmgt"] = False + if batch_size is not None: + config["batch_size"] = batch_size + if num_workers is not None: + config["num_workers"] = 0 + + skeleton = create_skeleton(**config) + if dataset == None: + dataset = init_obj(config, 'dataset_type', dataset_type, split=split, skeleton=skeleton, **(config[data_loader_name])) + + data_loader = DataLoader(dataset, pin_memory= True, shuffle=config[data_loader_name]["shuffle"], batch_size=config["batch_size"], + num_workers=config["num_workers"], drop_last=config[data_loader_name]["drop_last"],collate_fn=custom_collate_for_mmgt) + assert len(data_loader) >0, "Dataset is too small and last batch was dropped" + return data_loader, dataset, skeleton + + + +def long_term_prediction_best_every50(data, target, extra, get_prediction, process_evaluation_pair, num_samples, config): + """ + Generate 50 predictions, pick the one closest to GT, take the last frames as past and from it generate 50 predictions, pick the one closest to GT, and so on.""" + new_data = data + final_pred_data = [] + final_target_data = [] + n_past_frames = data.shape[-3] + for idx in range(math.ceil(config['long_term_factor'])): + pred = get_prediction(new_data, extra=extra) # [batch_size, n_samples, seq_length, num_joints, features] + if idx == math.ceil(config['long_term_factor']) -1 and int(config['long_term_factor']) != config['long_term_factor']: + pred = pred[..., :int(config['long_term_factor']*config['pred_length'])%config['pred_length'], :, :] + target_m, pred, mm_gt, data_metric_space = process_evaluation_pair(target=target[..., idx*config['pred_length']:(idx+1)*config['pred_length'], :, :], + pred_dict={'pred': pred, 'obs': new_data}) + if idx == 0: + data = data_metric_space + best_pred, indeces_bool = get_best_sample_idx(pred, target_m) + final_pred_data.append(best_pred) + final_target_data.append(target_m) + new_data = pred[indeces_bool][..., -n_past_frames:, :, :] # cut off the first frames + + final_pred_data = torch.cat(final_pred_data, dim=-3) + pred = final_pred_data.unsqueeze(1).repeat(1, num_samples, 1, 1, 1) + target = torch.cat(final_target_data, dim=-3) + return target, pred, mm_gt, data + +def long_term_prediction_best_first50(data, target, extra, get_prediction, process_evaluation_pair, num_samples, config): + """ + Generate 50 predictions wiht training future time horizont, + select the one closest to GT and then propagate that one (most likely countinuation)""" + new_data = data + final_pred_data = [] + final_target_data = [] + + for idx in range(math.ceil(config['long_term_factor'])): + if idx == 0: + pred = get_prediction(new_data, num_samples=num_samples, extra=extra) # [batch_size, n_samples, seq_length, num_joints, features] + else: + batch_size, num_samples, seq_length, num_joints, features = new_data.shape + pred = get_prediction(new_data.reshape(batch_size * num_samples, seq_length, num_joints, features), num_samples=1, extra=extra) + pred = pred.reshape(batch_size, num_samples, config['pred_length'], num_joints, features) + if idx == math.ceil(config['long_term_factor']) -1 and int(config['long_term_factor']) != config['long_term_factor']: + pred = pred[..., :int(config['long_term_factor']*config['pred_length'])%config['pred_length'], :, :] + target_m, pred, mm_gt, data_metric_space = process_evaluation_pair( + target=target[..., idx*config['pred_length']:(idx+1)*config['pred_length'], :, :], + pred_dict={'pred': pred, 'obs': new_data} + ) + if idx == 0: + data = data_metric_space + final_pred_data.append(pred) + final_target_data.append(target_m) + new_data = pred[..., -data.shape[-3]:, :, :] # cut off the first frames + + final_pred_data = torch.cat(final_pred_data, dim=-3) + pred = final_pred_data #.unsqueeze(1).repeat(1, num_samples, 1, 1, 1) + target = torch.cat(final_target_data, dim=-3) + return target, pred, mm_gt, data \ No newline at end of file diff --git a/SkeletonDiffusion/src/inference_example.py b/SkeletonDiffusion/src/inference_example.py new file mode 100644 index 0000000000000000000000000000000000000000..27f274f0b13ff253721afa6f3c47ade765d36e50 --- /dev/null +++ b/SkeletonDiffusion/src/inference_example.py @@ -0,0 +1,60 @@ +# %% +import os +os.chdir(r"/usr/wiss/curreli/work/my_modules/SkeletonDiffusion/src") +root_path = os.getcwd() +print(root_path) + +os.environ["CUBLAS_WORKSPACE_CONFIG"] = ":4096:8" + +# %% +from SkeletonDiffusion.src.eval_prepare_model import prepare_model, get_prediction, load_model_config_exp +from SkeletonDiffusion.src.data import create_skeleton +import torch +import numpy as np +import random + +from SkeletonDiffusion.src.metrics.body_realism import limb_stretching_normed_mean + +def set_seed(seed=0): + torch.use_deterministic_algorithms(True) + torch.backends.cudnn.deterministic = True + torch.backends.cudnn.benchmark = False + np.random.seed(seed) + random.seed(seed) + torch.cuda.manual_seed(seed) + torch.cuda.manual_seed_all(seed) +# %% +checkpoint_path = '/usr/wiss/curreli/work/my_exps/checkpoints_release/amass/diffusion/cvpr_release/checkpoints/checkpoint_150.pt' + +num_samples = 50 + +# %% +set_seed(seed=0) +config, exp_folder = load_model_config_exp(checkpoint_path) +config['checkpoint_path'] = checkpoint_path +skeleton = create_skeleton(**config) + + +model, device, *_ = prepare_model(config, skeleton, **config) + +# %% +# prepare input +# load input. It should be in meters +import numpy as np +import torch +obs = np.load('/usr/wiss/curreli/work/my_exps/checkpoints_release/amass/exaple_obs.npy') # (t_past, J, 3) +obs = torch.from_numpy(obs).to(device) +obs = obs.unsqueeze(0) # add bacth size + +# %% +obs_in = skeleton.tranform_to_input_space(obs) # obs sequence contains hip joints, it has not been dropped yet. +pred = get_prediction(obs_in, model, num_samples=num_samples, **config) # [batch_size, n_samples, seq_length, num_joints, features] +pred = skeleton.transform_to_metric_space(pred) + +# rank predictions according to Limb Stretching. We will visualize first the prediction that have lower limb stretching --> more realistic +limbstretching = limb_stretching_normed_mean(pred, target=obs[..., 1:, :].unsqueeze(1), limbseq=skeleton.get_limbseq(), reduction='persample', obs_as_target=True) + +limbstretching_sorted, indices = torch.sort(limbstretching.squeeze(1), dim=-1, descending=False) + + +print('finished') diff --git a/SkeletonDiffusion/src/inference_utils.py b/SkeletonDiffusion/src/inference_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..0d0fbc861f737cd83e48075c260bb78a3ec033ac --- /dev/null +++ b/SkeletonDiffusion/src/inference_utils.py @@ -0,0 +1,6 @@ +import core as model_arch +from utils.config import init_obj + +def create_model(device, **kwargs): + model = init_obj(kwargs, 'arch', model_arch).to(device) + return model \ No newline at end of file diff --git a/SkeletonDiffusion/src/metrics/__init__.py b/SkeletonDiffusion/src/metrics/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/SkeletonDiffusion/src/metrics/apde.py b/SkeletonDiffusion/src/metrics/apde.py new file mode 100644 index 0000000000000000000000000000000000000000..36bc26adccb068057ba97942299851ff1ef8ba75 --- /dev/null +++ b/SkeletonDiffusion/src/metrics/apde.py @@ -0,0 +1,48 @@ + +from ignite.metrics import Metric +from ignite.exceptions import NotComputableError +import pandas as pd +import numpy as np +import os +import torch + +class MetricStorerAPDE(Metric): + + def __init__(self, output_transform=lambda x: apd(x), return_op='mean', mmapd_gt_path=''): + self.cumulator = None + self.count = 0 + self.return_op = return_op + assert return_op in ['mean', 'avg'] + assert os.path.exists(mmapd_gt_path), f"Cannot find mmapd_GT.csv in {mmapd_gt_path}" + mmapd_gt = pd.read_csv(mmapd_gt_path, index_col=0)["gt_APD"] + mmapd_gt = mmapd_gt.replace(0, np.NaN) + self.mmapd_gt = mmapd_gt + self.index = 0 + super().__init__(output_transform=output_transform) + + def reset(self): + self.cumulator = 0. if self.return_op != 'min' else 1000000. + self.count = 0 + self.tot = 0 + super().reset() + + def update(self, output): + # pred, class_idxs, step = self._output_transform(output) # This will be called by engine if we use it + + output = output.cpu() + batch_size = output.shape[0] + mmapde = (output - self.mmapd_gt[self.index:self.index+batch_size].values).abs() + self.index += batch_size + + if self.return_op in ['mean', 'avg']: + self.cumulator += mmapde.nansum(0) + + self.count += (~torch.isnan(mmapde)).sum() + self.tot = self.cumulator/self.count if self.return_op in ['mean', 'avg'] else self.cumulator + + def compute(self): + if self.cumulator is None or self.count == None: + raise NotComputableError('MetricStorer must have at least one example before it can be computed.') + self.tot = self.cumulator/self.count if self.return_op in ['mean', 'avg'] else self.cumulator + tot = self.tot + return tot diff --git a/SkeletonDiffusion/src/metrics/body_realism.py b/SkeletonDiffusion/src/metrics/body_realism.py new file mode 100644 index 0000000000000000000000000000000000000000..5a969743243de25173449843feedb47091f8ae17 --- /dev/null +++ b/SkeletonDiffusion/src/metrics/body_realism.py @@ -0,0 +1,198 @@ +import numpy as np +import torch + +def _extract_limb_length(kpts, limbseq): + limbdist = [] + assert max(max(limbseq)) < kpts.shape[-2], f"Expected {max(max(limbseq))} < {kpts.shape[-2]}" + if np.array(limbseq).max() == kpts.shape[-2]: + shape = list(kpts.shape) + shape[-2] = 1 + kpts = torch.cat([torch.zeros(shape, device=kpts.device), kpts], dim=-2) + for l1,l2 in limbseq: + limbdist.append( torch.linalg.norm(kpts[..., l1, :] - kpts[..., l2, :], dim=-1)) + return torch.stack(limbdist, dim=-1) + +def limb_length_variation_difference_wrtGT(target, pred, limbseq, mode='mean', **kwargs): + pred_llerr = limb_length_jitter(pred=pred, limbseq=limbseq, mode=mode, **kwargs) # [batch_size] + target_llerr = limb_length_jitter(pred=target.unsqueeze(1), limbseq=limbseq, mode=mode, **kwargs) # [batch_size] + + # estimate is that target_llerr < pred_llerr, so it makes sense to output pred_llerr - target_llerr + # if negative, it means we have higher precision than gt! + if mode == 'mean': + pred_llerr, target_llerr = pred_llerr.mean(axis=-1), target_llerr.mean(axis=-1) + elif mode == 'max': + pred_llerr, target_llerr = pred_llerr.max(axis=-1).values , target_llerr.max(axis=-1).values + elif mode == 'min': + pred_llerr, target_llerr = pred_llerr.min(axis=-1).values , target_llerr.min(axis=-1).values + elif mode == 'none': + return (pred_llerr - target_llerr) + return (pred_llerr - target_llerr).unsqueeze(0) + + +def limb_length_error(target, pred, limbseq, mode='mean', **kwargs): + #(batch_size, num_samples, seq_length, num_joints, features) + batch_size, num_samples, seq_length, num_joints, features = pred.shape + + target_ll, pred_ll = _extract_limb_length(target, limbseq), _extract_limb_length(pred, limbseq) + assert [batch_size, num_samples, seq_length] == list(pred_ll.shape[:-1]) + llerr = torch.abs(target_ll.unsqueeze(1) - pred_ll).mean(dim=-1) # mean ll error over joints + assert [batch_size, num_samples, seq_length] == list(llerr.shape) + llerr = llerr.mean(axis=-1) # mean over time dim + assert [batch_size, num_samples] == list(llerr.shape) + assert mode in ['mean', 'max', 'min'], f"Mode {mode} not supported" + if mode == 'mean': + return llerr.mean(axis=-1) # mean over extracted samples + elif mode == 'max': + return llerr.max(axis=-1).values + elif mode == 'min': + return llerr.min(axis=-1).values + +def limb_length_variance(pred, limbseq, mode='mean', if_per_sample=False, **kwargs): + #(batch_size, num_samples, seq_length, num_joints, features) + batch_size, num_samples, seq_length, num_joints, features = pred.shape + pred_ll = _extract_limb_length(pred, limbseq) + assert [batch_size, num_samples, seq_length] == list(pred_ll.shape[:-1]) + # assert [batch_size, num_samples] == list(llerr.shape) + assert mode in ['mean', 'max', 'min', 'none'], f"Mode {mode} not supported" + llvar = pred_ll.var(dim=-2) # batch_size, num_samples, num_joints + if mode == 'mean': + llvar = llvar.mean(axis=-1) + if if_per_sample: + assert len(llvar.shape) == 2, f"Expected 2, got {len(llvar.shape)}" + return llvar + return llvar.mean(axis=-1) # mean over extracted samples + elif mode == 'max': + llvar = llvar.max(axis=-1).values + if if_per_sample: + assert len(llvar.shape) == 2, f"Expected 2, got {len(llvar.shape)}" + return llvar + return llvar.max(axis=-1).values + elif mode == 'min': + llvar = llvar.min(axis=-1).values + if if_per_sample: + assert len(llvar.shape) == 2, f"Expected 2, got {len(llvar.shape)}" + return llvar + return llvar.min(axis=-1).values + elif mode == 'none': + return llvar + +def limb_length_jitter(pred, limbseq, mode='mean', if_per_sample=False, **kwargs): + #(batch_size, num_samples, seq_length, num_joints, features) + batch_size, num_samples, seq_length, num_joints, features = pred.shape + pred_ll = _extract_limb_length(pred, limbseq) + assert [batch_size, num_samples, seq_length] == list(pred_ll.shape[:-1]) + llerr = torch.abs(pred_ll[..., 1:, :] - pred_ll[..., :-1, :]) + assert [batch_size, num_samples, seq_length-1, len(limbseq)] == list(llerr.shape) + # assert [batch_size, num_samples] == list(llerr.shape) + assert mode in ['mean', 'max', 'min', 'none'], f"Mode {mode} not supported" + if mode == 'mean': + llerr = llerr.mean(axis=-1).mean(dim=-1) + if if_per_sample: + assert len(llerr.shape) == 2, f"Expected 2, got {len(llerr.shape)}" + return llerr + return llerr.mean(axis=-1) # mean over extracted samples + elif mode == 'max': + llerr = llerr.max(axis=-1).values.max(axis=-1).values + if if_per_sample: + assert len(llerr.shape) == 2, f"Expected 2, got {len(llerr.shape)}" + return llerr + return llerr.max(axis=-1).values + elif mode == 'min': + llerr = llerr.min(axis=-1).values.min(axis=-1).values + if if_per_sample: + assert len(llerr.shape) == 2, f"Expected 2, got {len(llerr.shape)}" + return llerr + return llerr.min(axis=-1).values + elif mode == 'none': + return llerr + +def limb_stretching_normed_rmse(pred, target, limbseq, mode='std', obs_as_target=False, reduction='mean',**kwargs): + assert mode in ['std', 'var'], f"Mode {mode} not supported" + B, S, T, N, _ = pred.shape + limb_length = _extract_limb_length(pred, limbseq) + B, S, T, J = limb_length.shape + limb_length_gt = _extract_limb_length(target, limbseq) + assert limb_length_gt.shape == (B, T, J) or obs_as_target + mean =limb_length_gt.mean(-2).unsqueeze(-2) + mean = mean.unsqueeze(1) # B, 1, 1, J + + var = (limb_length - mean)**2 # B, S, T, J + var = var.mean(-2) + if mode == 'std': + var = torch.sqrt(var) + var = var/ mean.squeeze(-2) + if reduction == 'mean': + return var.view(B, -1).mean(-1) # B, S, J --> B + elif reduction == 'persample': + return var.mean(-1) + else: + return var + +def limb_stretching_normed_mean(pred, target, limbseq, reduction='mean', obs_as_target=False, **kwargs): + B, S, T, N, _ = pred.shape + limb_length = _extract_limb_length(pred, limbseq) + B, S, T, J = limb_length.shape + limb_length_gt = _extract_limb_length(target, limbseq) + assert limb_length_gt.shape == (B, T, J) or obs_as_target + mean_gt =limb_length_gt.mean(-2).unsqueeze(-2) # B, 1, J + mean = limb_length.mean(-2) # B, S, J + + normed_mean = (mean - mean_gt).abs()/ mean_gt + if reduction == 'mean': + return normed_mean.view(B, -1).mean(-1) # B, S, J --> B + elif reduction == 'persample': + return normed_mean.mean(-1) + else: + return normed_mean + + +def limb_jitter_normed_rmse(pred, target, limbseq, mode='std', reduction='mean',**kwargs): + """ + We assume the ground truth jitter to be zero. + We compute the variance accordingly, without subtracting any gt mean. + + Normalization is done by dividing the variance by the mean of the ground truth limb length. + In this way the output is the variance of the jitter in percentage of the GT limb length. + """ + assert mode in ['std', 'var'], f"Mode {mode} not supported" + B, S, T, N, _ = pred.shape + jitter = limb_length_jitter(pred, limbseq, mode='none', if_per_sample=True) + B, S, Tmin1, J = jitter.shape + limb_length_gt = _extract_limb_length(target, limbseq) + assert limb_length_gt.shape == (B, T, J) + mean =limb_length_gt.mean(-2).unsqueeze(-2) # B, 1, J + + var = (jitter)**2 # B, S, T, J + var = var.mean(-2) + if mode == 'std': + var = torch.sqrt(var) + var = var/ mean + if reduction == 'mean': + return var.view(B, -1).mean(-1) # B, S, J --> B + elif reduction == 'persample': + return var.mean(-1) + else: + return var + +def limb_jitter_normed_mean(pred, target, limbseq, reduction='mean', **kwargs): + """ + We assume the ground truth jitter to be zero. + So we compute the normed mean jitter of the prediction without subtracting any gt mean. + + Normalization is done by dividing the mean jitter of the predictions by the mean of the ground truth limb length. + In this way the output is the mean jitter in percentage of the GT limb length. + """ + B, S, T, N, _ = pred.shape + jitter = limb_length_jitter(pred, limbseq, mode='none', if_per_sample=True) + B, S, Tmin1, J = jitter.shape + limb_length_gt = _extract_limb_length(target, limbseq) + assert limb_length_gt.shape == (B, T, J) + mean_gt =limb_length_gt.mean(-2).unsqueeze(-2) # B, 1, J + + normed_mean = jitter.mean(-2)/ mean_gt # B, S, J + if reduction == 'mean': + return normed_mean.view(B, -1).mean(-1) # B, S, J --> B + elif reduction == 'persample': + return normed_mean.mean(-1) + else: + return normed_mean \ No newline at end of file diff --git a/SkeletonDiffusion/src/metrics/cmd.py b/SkeletonDiffusion/src/metrics/cmd.py new file mode 100644 index 0000000000000000000000000000000000000000..c6f150d112ae17f3274e6a8501813d39f47b6c1d --- /dev/null +++ b/SkeletonDiffusion/src/metrics/cmd.py @@ -0,0 +1,57 @@ +from typing import Tuple, List, Dict +import numpy as np + +import torch +from ignite.metrics import Metric +from ignite.exceptions import NotComputableError + +from .multimodal import cmd + +def motion_for_cmd(pred): + motion = (torch.linalg.norm(pred[..., 1:, :, :] - pred[..., :-1, :, :], axis=-1)).mean(axis=1).mean(axis=-1) + return motion + + +def resolve_cmd(histogram_data, all_obs_classes, idx_to_class: List[str], mean_motion_per_class: List[float]): + results = 0. + step_obs_classes = np.concatenate(all_obs_classes, axis=0) + motion_data = np.concatenate(histogram_data, axis=0) #shape (num_batches*batch_size, num_timesteps-1) = (num_segments, num_timesteps-1) + # motion_data_mean = motion_data.mean(axis=0) + # motion_datas = motion_data_mean + + motion_per_class = np.zeros((len(idx_to_class), motion_data.shape[1])) + # CMD weighted by class + for i, (name, class_val_ref) in enumerate(zip(idx_to_class, mean_motion_per_class)): + mask = step_obs_classes == i + if mask.sum() == 0: + continue + motion_data_mean = motion_data[mask].mean(axis=0) # mean over samples + motion_per_class[i] = motion_data_mean + results += cmd(motion_data_mean, class_val_ref) * (mask.sum() / step_obs_classes.shape[0]) # this impelmented weighted average of cmd over dataset classes + return results#, motion_datas + + +class CMDMetricStorer(Metric): + def __init__(self, final_funct, output_transform=lambda x: x): + + self.final_funct = final_funct + super().__init__(output_transform=output_transform) + + def reset(self): + self.vals = [] + self.idxs = [] + super().reset() + + def update(self, output): + # pred, class_idxs, step = self._output_transform(output) # This will be called by engine if we use it + # class_idxs = np.array([self.dataset_class_to_idx[c] for c in metadata]) + # pred = motion_for_cmd(pred).cpu().detach().numpy() + mot_cmd, class_idxs = output + self.vals.append(mot_cmd.cpu().numpy()) + self.idxs.append(class_idxs) + + def compute(self): + if self.vals is None or self.idxs is None: + raise NotComputableError('MetricStorer must have at least one example before it can be computed.') + ret = self.final_funct(self.vals, self.idxs) + return ret diff --git a/SkeletonDiffusion/src/metrics/fid.py b/SkeletonDiffusion/src/metrics/fid.py new file mode 100644 index 0000000000000000000000000000000000000000..78d1b7783b72725c9e610384bffd2f1c90568f7d --- /dev/null +++ b/SkeletonDiffusion/src/metrics/fid.py @@ -0,0 +1,129 @@ + +from scipy import linalg +import numpy as np +import os +import torch + +def _calculate_activation_statistics(activations): # [b, 48] + mu = np.mean(activations, axis=0) # [48,] + sigma = np.cov(activations, rowvar=False) # [48, 48] + + return mu, sigma + +def _calculate_fid_helper(statistics_1, statistics_2): + return _calculate_frechet_distance(statistics_1[0], statistics_1[1], + statistics_2[0], statistics_2[1]) + +def _calculate_frechet_distance(mu1, sigma1, mu2, sigma2, eps=1e-6): + """Numpy implementation of the Frechet Distance. + The Frechet distance between two multivariate Gaussians X_1 ~ N(mu_1, C_1) + and X_2 ~ N(mu_2, C_2) is + d^2 = ||mu_1 - mu_2||^2 + Tr(C_1 + C_2 - 2*sqrt(C_1*C_2)). + Stable version by Dougal J. Sutherland. + Params: + -- mu1 : Numpy array containing the activations of a layer of the + inception net (like returned by the function 'get_predictions') + for generated samples. + -- mu2 : The sample mean over activations, precalculated on an + representative data set. + -- sigma1: The covariance matrix over activations for generated samples. + -- sigma2: The covariance matrix over activations, precalculated on an + representative data set. + Returns: + -- : The Frechet Distance. + """ + + mu1 = np.atleast_1d(mu1) + mu2 = np.atleast_1d(mu2) + + sigma1 = np.atleast_2d(sigma1) + sigma2 = np.atleast_2d(sigma2) + + assert mu1.shape == mu2.shape, \ + 'Training and test mean vectors have different lengths' + assert sigma1.shape == sigma2.shape, \ + 'Training and test covariances have different dimensions' + + diff = mu1 - mu2 + + # Product might be almost singular + covmean, _ = linalg.sqrtm(sigma1.dot(sigma2), disp=False) + if not np.isfinite(covmean).all(): + msg = ('fid calculation produces singular product; ' + 'adding %s to diagonal of cov estimates') % eps + print(msg) + offset = np.eye(sigma1.shape[0]) * eps + covmean = linalg.sqrtm((sigma1 + offset).dot(sigma2 + offset)) + + # Numerical error might give slight imaginary component + if np.iscomplexobj(covmean): + if not np.allclose(np.diagonal(covmean).imag, 0, atol=1e-3): + m = np.max(np.abs(covmean.imag)) + raise ValueError('Imaginary component {}'.format(m)) + covmean = covmean.real + + tr_covmean = np.trace(covmean) + + return (diff.dot(diff) + np.trace(sigma1) + + np.trace(sigma2) - 2 * tr_covmean) + +def fid(act1, act2): + statistics_1 = _calculate_activation_statistics(act1) + statistics_2 = _calculate_activation_statistics(act2) + return _calculate_fid_helper(statistics_1, statistics_2) + + +from .fid_classifier import ClassifierForFID +from ignite.metrics import Metric +from ignite.exceptions import NotComputableError + +def get_classifier(classifier_path, device, **kwargs): + assert not kwargs['if_consider_hip'], "The skeleton should not consider hip to use the classifier." + classifier_for_fid = ClassifierForFID(input_size=48, hidden_size=128, hidden_layer=2, + output_size=15, device=device, use_noise=None).to(device) + + classifier_path = os.path.join(classifier_path, "h36m_classifier.pth") + classifier_state = torch.load(classifier_path, map_location=device) + classifier_for_fid.load_state_dict(classifier_state["model"]) + classifier_for_fid.eval() + return classifier_for_fid + +class MetricStorerFID(Metric): + + def __init__(self, output_transform=lambda x: x, classifier_path='', device='cuda', **kwargs): + self.all_gt_activations = [] + self.all_pred_activations = [] + + assert os.path.exists(classifier_path), f"Cannot find checkpoint of classifier in {classifier_path}" + self.classifier = get_classifier(classifier_path, device, **kwargs) + super().__init__(output_transform=output_transform) + + def reset(self): + self.all_gt_activations = [] + self.all_pred_activations = [] + super().reset() + + def update(self, output): + # pred, class_idxs, step = self._output_transform(output) # This will be called by engine if we use it + pred, target = output + # ----------------------------- Computing features for FID ----------------------------- + # pred -> [batch_size, samples, seq_length, n_joints, n_features]) + pred_ = pred.reshape(*pred.shape[:-2], -1) # [batch_size, samples, seq_length, n_features]) + pred_ = pred_.reshape(-1, *pred_.shape[2:]) # [batch_size * samples, seq_length, n_features]) + pred_ = pred_.permute(0, 2, 1) # [batch_size * samples, n_features, seq_length]) + + # same for target + target_ = target.reshape(*target.shape[:-2],-1) # [batch_size, seq_length, n_features]) + target_ = target_.permute(0, 2, 1) # [batch_size, n_features, seq_length]) + + pred_activations = self.classifier.get_fid_features(motion_sequence=pred_.float()).cpu().data.numpy() + gt_activations = self.classifier.get_fid_features(motion_sequence=target_.float()).cpu().data.numpy() + + self.all_gt_activations.append(gt_activations) + self.all_pred_activations.append(pred_activations) + + def compute(self): + if len(self.all_gt_activations) == 0 or len(self.all_pred_activations) == 0: + raise NotComputableError('MetricStorer must have at least one example before it can be computed.') + tot = fid(np.concatenate(self.all_gt_activations, axis=0), np.concatenate(self.all_pred_activations, axis=0)) + return tot diff --git a/SkeletonDiffusion/src/metrics/fid_classifier.py b/SkeletonDiffusion/src/metrics/fid_classifier.py new file mode 100644 index 0000000000000000000000000000000000000000..8711fabd5fc5f2f924b7f9f34e2292592a757f6b --- /dev/null +++ b/SkeletonDiffusion/src/metrics/fid_classifier.py @@ -0,0 +1,57 @@ +import torch +import torch.nn as nn + + +class ClassifierForFID(nn.Module): + def __init__(self, input_size=48, hidden_size=128, hidden_layer=2, output_size=15, device="", use_noise=None): + super(ClassifierForFID, self).__init__() + self.device = device + + self.input_size = input_size + self.hidden_size = hidden_size + self.hidden_layer = hidden_layer + self.use_noise = use_noise + + self.recurrent = nn.GRU(input_size, hidden_size, hidden_layer) + self.linear1 = nn.Linear(hidden_size, 30) + self.linear2 = nn.Linear(30, output_size) + + + def forward(self, motion_sequence, hidden_unit=None): + ''' + motion_sequence: b, 48, 100 + hidden_unit: + ''' + motion_sequence = motion_sequence.permute(2, 0, 1).contiguous() # [100, b, 48] + # dim (motion_length, num_samples, hidden_size) + if hidden_unit is None: + hidden_unit = self.initHidden(motion_sequence.size(1), self.hidden_layer) # [2, b, 128] + + gru_o, _ = self.recurrent(motion_sequence.float(), hidden_unit) # [100, b, 48] + # dim (num_samples, 30) + lin1 = self.linear1(gru_o[-1, :, :]) # [b, 48] + lin1 = torch.tanh(lin1) + # dim (num_samples, output_size) + lin2 = self.linear2(lin1) + return lin2 + + def get_fid_features(self, motion_sequence, hidden_unit=None): + ''' + motion_sequence: b, 48, 100 + hidden_unit: + ''' + motion_sequence = motion_sequence.permute(2, 0, 1).contiguous() # [100, b, 48] + + # dim (motion_length, num_samples, hidden_size) + if hidden_unit is None: + hidden_unit = self.initHidden(motion_sequence.size(1), self.hidden_layer) + + gru_o, _ = self.recurrent(motion_sequence.float(), hidden_unit) + # dim (num_samples, 30) + lin1 = self.linear1(gru_o[-1, :, :]) + lin1 = torch.tanh(lin1) + return lin1 + + + def initHidden(self, num_samples, layer): + return torch.randn(layer, num_samples, self.hidden_size, device=self.device, requires_grad=False) diff --git a/SkeletonDiffusion/src/metrics/ignite_fde.py b/SkeletonDiffusion/src/metrics/ignite_fde.py new file mode 100644 index 0000000000000000000000000000000000000000..d2ab4c78166ae842adb6e8ea100f7a29bbae5ec9 --- /dev/null +++ b/SkeletonDiffusion/src/metrics/ignite_fde.py @@ -0,0 +1,40 @@ +from typing import Tuple + +import torch +from ignite.metrics import Metric +from ignite.exceptions import NotComputableError + + +class FinalDisplacementError(Metric): + def __init__(self, output_transform=lambda x: x, if_cpu=True): + self.y = None + self.y_pred = None + self.if_cpu = if_cpu + super().__init__(output_transform=output_transform) + + def reset(self): + self.y = None + self.y_pred = None + super().reset() + + def update(self, output: Tuple[torch.Tensor, torch.Tensor]): + if len(output) == 2: + y_pred, y = output + else: + y_pred, y, _ = output + + if self.if_cpu: + y_pred, y = y_pred.cpu(), y.cpu() + + if self.y is None: + self.y = y[...,-1,:,:] + self.y_pred = y_pred[...,-1,:,:] + else: + self.y = torch.cat([self.y, y[...,-1,:,:]], dim=0) + self.y_pred = torch.cat([self.y_pred, y_pred[...,-1,:,:]], dim=0) + + def compute(self): + if self.y is None: + raise NotComputableError('FinalDisplacementError must have at least one example before it can be computed.') + fde = (self.y - self.y_pred).norm(dim=-1).mean() + return fde \ No newline at end of file diff --git a/SkeletonDiffusion/src/metrics/ignite_mpjpe.py b/SkeletonDiffusion/src/metrics/ignite_mpjpe.py new file mode 100644 index 0000000000000000000000000000000000000000..3cfb497b7d26331341166f706dde78d751b8b35f --- /dev/null +++ b/SkeletonDiffusion/src/metrics/ignite_mpjpe.py @@ -0,0 +1,49 @@ +from typing import Tuple + +import torch +from ignite.metrics import Metric +from ignite.exceptions import NotComputableError +from .utils import format_metric_time_table + + +class MeanPerJointPositionError(Metric): + def __init__(self, output_transform=lambda x: x, keep_time_dim: bool = True, keep_joint_dim: bool = False, if_cpu=True): + self.y = None + self.y_pred = None + self.keep_time_dim = keep_time_dim + self.keep_joint_dim = keep_joint_dim + self.if_cpu = if_cpu + super().__init__(output_transform=output_transform) + + def reset(self): + self.y = None + self.y_pred = None + super().reset() + + def update(self, output: Tuple[torch.Tensor, torch.Tensor]): + if len(output) == 2: + y_pred, y = output + else: + y_pred, y, _ = output + + if self.if_cpu: + y_pred, y = y_pred.cpu(), y.cpu() + + if self.y is None: + self.y = y + self.y_pred = y_pred + else: + self.y = torch.cat([self.y, y], dim=0) + self.y_pred = torch.cat([self.y_pred, y_pred], dim=0) + + def compute(self): + if self.y is None: + raise NotComputableError('MeanPerJointPositionError must have at least one example before it can be computed.') + ret = (self.y - self.y_pred).norm(dim=-1).mean(dim=[0]) + if not self.keep_joint_dim: + ret = ret.mean(dim=[-1]) + if not self.keep_time_dim: + ret = ret.mean(0) + else: + ret = format_metric_time_table(ret) + return ret diff --git a/SkeletonDiffusion/src/metrics/metric_storer.py b/SkeletonDiffusion/src/metrics/metric_storer.py new file mode 100644 index 0000000000000000000000000000000000000000..63887de2ce150b71bb6ef8904a0df64076753797 --- /dev/null +++ b/SkeletonDiffusion/src/metrics/metric_storer.py @@ -0,0 +1,44 @@ + +from ignite.metrics import Metric +from ignite.exceptions import NotComputableError +import os +import torch + +class MetricStorer(Metric): + def __init__(self, output_transform=lambda x: x, return_op='mean'): + self.cumulator = None + self.count = 0 + self.return_op = return_op + assert return_op in ['mean', 'avg', 'max', 'min'] + super().__init__(output_transform=output_transform) + + def reset(self): + self.cumulator = 0. if self.return_op != 'min' else 1000000. + self.count = 0 + self.tot = 0 + super().reset() + + def update(self, output): + # pred, class_idxs, step = self._output_transform(output) # This will be called by engine if we use it + + output = output.cpu().numpy() + + if self.return_op in ['mean', 'avg']: + self.cumulator += output.sum(0) + elif self.return_op == 'max': + current_max = output.max(0) + self.cumulator = self.cumulator if self.cumulator > current_max else current_max + elif self.return_op == 'min': + current_min = output.min(0) + self.cumulator = self.cumulator if self.cumulator < current_min else current_min + + self.count += output.shape[0] if self.return_op in ['mean', 'avg'] else 0 + self.tot = self.cumulator/self.count if self.return_op in ['mean', 'avg'] else self.cumulator + + def compute(self): + if self.cumulator is None or self.count == None: + raise NotComputableError('MetricStorer must have at least one example before it can be computed.') + self.tot = self.cumulator/self.count if self.return_op in ['mean', 'avg'] else self.cumulator + tot = self.tot + return tot + diff --git a/SkeletonDiffusion/src/metrics/multimodal.py b/SkeletonDiffusion/src/metrics/multimodal.py new file mode 100644 index 0000000000000000000000000000000000000000..420c66d6c41c72e8de9e3dd81b25828269632d60 --- /dev/null +++ b/SkeletonDiffusion/src/metrics/multimodal.py @@ -0,0 +1,154 @@ +import numpy as np +import torch + +def time_slice(array, t0, t, axis): + if t == -1: + return torch.index_select(array, axis, torch.arange(t0, array.shape[axis], device=array.device, dtype=torch.int32)) + else: + return torch.index_select(array, axis, torch.arange(t0, t, device=array.device, dtype=torch.int32)) + +def cmd(val_per_frame, val_ref): + # val_per_frame (array of floats) -> M_t, val_ref (float) -> M + T = len(val_per_frame) + 1 + return np.sum([(T - t) * np.abs(val_per_frame[t-1] - val_ref) for t in range(1, T)]) + +def apd(pred, t0=0, t=-1, **kwargs): + pred = time_slice(pred, t0, t, 2) + # (batch_size, num_samples, seq_length, num_joints, features) to (num_samples, all_others) + batch_size, n_samples = pred.shape[:2] + if n_samples == 1: # only one sample => no APD possible + return torch.tensor([0] * batch_size, device=pred.device) + + arr = pred.reshape(batch_size, n_samples, -1) # (batch_size, num_samples, others) + dist = torch.cdist(arr, arr) # (batch_size, num_samples, num_samples) + + # Get the upper triangular indices (excluding the diagonal) + iu = torch.triu_indices(n_samples, n_samples, offset=1) + + # Select upper triangular values for each batch + upper_triangular_values = dist[:, iu[0], iu[1]] # (batch_size, num_pairs) + + # Average the pairwise distances + results = upper_triangular_values.mean(dim=-1) # (batch_size,) + + assert list(results.shape) == [batch_size] + return results + +def mpjpe(target, pred, **kwargs): + batch_size, num_samples, seq_length, num_joints, features = pred.shape + dist = torch.linalg.norm(target.unsqueeze(1)-pred, axis=-1).mean(axis=-1) # mean over joints + assert [batch_size, num_samples, seq_length] == list(dist.shape) + dist = dist.mean(axis=-1) # mean over time dim + return dist.min(axis=-1).values + +def ade(target, pred, t0=0, t=-1, reduction='mean', **kwargs): + pred, target = time_slice(pred, t0, t, 2), time_slice(target, t0, t, 1) + batch_size, n_samples, seq_length = pred.shape[:3] + # from (batch_size, num_samples, seq_length, num_parts, num_joints, features) to (batch_size, num_samples, seq_length, num_parts * num_joints * features) + pred = pred.reshape((batch_size, n_samples, seq_length, -1)) + # from (batch_size, seq_length, num_parts, num_joints, features) to (batch_size, seq_length, num_parts * num_joints * features) + target = target.reshape((batch_size, 1, seq_length, -1)) + + diff = pred - target + dist = torch.linalg.norm(diff, axis=-1).mean(axis=-1) + if reduction=='mean': + return dist.min(axis=-1).values + else: + return dist + + +def fde(target, pred, t0=0, t=-1, reduction='mean', **kwargs): + pred, target = time_slice(pred, t0, t, 2), time_slice(target, t0, t, 1) + batch_size, n_samples, seq_length = pred.shape[:3] + # from (batch_size, num_samples, seq_length, num_parts, num_joints, features) to (batch_size, num_samples, seq_length, num_parts * num_joints * features) + pred = pred.reshape((batch_size, n_samples, seq_length, -1)) + # from (batch_size, seq_length, num_parts, num_joints, features) to (batch_size, seq_length, num_parts * num_joints * features) + target = target.reshape((batch_size, 1, seq_length, -1)) + + diff = pred - target + dist = torch.linalg.norm(diff, axis=-1)[..., -1] + if reduction=='mean': + return dist.min(axis=-1).values + else: + return dist + + +def mae(target, pred, limbseq, limb_angles_idx, t0=0, t=-1, if_return_cossim=False, **kwargs): + def cos_similarity(limb_vectors, limb_angles_idx_tup): + cos_sim = torch.einsum('bstjd,bstjd->bstj', limb_vectors[..., limb_angles_idx_tup[:,0], :], limb_vectors[..., limb_angles_idx_tup[:,1], :]) + den = (limb_vectors[..., limb_angles_idx_tup[:,0], :]**2).sum(-1).sqrt() * (limb_vectors[..., limb_angles_idx_tup[:,1], :]**2).sum(-1).sqrt() + den[den<1e-7] = 1e-7 + cos_sim = cos_sim/den + return cos_sim + pred, target = time_slice(pred, t0, t, 2), time_slice(target, t0, t, 1) + if isinstance(limbseq, list): + limbseq = torch.tensor(limbseq) + limbseq = torch.sort(limbseq, dim=-1, descending=False)[0] + limb_angles_idx_tup = torch.tensor([[kin[i], kin[i+1]] for kin in limb_angles_idx for i in range(len(kin)-1)]) + + limb_vectors_target = target[ ..., limbseq[:, 1], :] - target[..., limbseq[:, 0], :] + cossim_target = cos_similarity(limb_vectors_target.unsqueeze(1), limb_angles_idx_tup) + cossim_target = cossim_target + + limb_vectors_pred = pred[ ..., limbseq[:, 1], :] - pred[..., limbseq[:, 0], :] + cossim_pred = cos_similarity(limb_vectors_pred, limb_angles_idx_tup) + if if_return_cossim: + diff = cossim_pred - cossim_target + else: + diff = (torch.acos(cossim_pred.clamp(-1, 1)) - torch.acos(cossim_target.clamp(-1, 1))) # in radiant. To get degrees *(180/pi) + assert torch.isnan(diff).sum() == 0, f"Found NaN in cos_sim: {diff}" + dist = torch.abs(diff).mean(-1).mean(axis=-1) + dist_deg = dist*(180/np.pi) + return dist_deg.min(axis=-1).values + + +def mmade(target, pred, mm_gt, t0=0, t=-1, **kwargs): # memory efficient version + pred, target = time_slice(pred, t0, t, 2), time_slice(target, t0, t, 1) + batch_size, n_samples, seq_length = pred.shape[:3] + results = torch.zeros((batch_size, )) + for i in range(batch_size): + n_gts = mm_gt[i].shape[0] + + p = pred[i].reshape((n_samples, seq_length, -1)).unsqueeze(0) + gt = time_slice(mm_gt[i], t0, t, 1).reshape((n_gts, seq_length, -1)).unsqueeze(1) + + # diff = p - gt + dist = torch.linalg.norm(p - gt, axis=-1).mean(axis=-1) + results[i] = dist.min(axis=-1).values.mean() + + return results + +def mmfde(target, pred, mm_gt, t0=0, t=-1, **kwargs): + pred, target = time_slice(pred, t0, t, 2), time_slice(target, t0, t, 1) + batch_size, n_samples, seq_length = pred.shape[:3] + results = torch.zeros((batch_size, )) + for i in range(batch_size): + n_gts = mm_gt[i].shape[0] + + p = pred[i].reshape((n_samples, seq_length, -1)).unsqueeze(0) + gt = time_slice(mm_gt[i], t0, t, 1).reshape((n_gts, seq_length, -1)).unsqueeze(1) + + diff = p - gt + dist = torch.linalg.norm(diff, axis=-1)[..., -1] + results[i] = dist.min(axis=-1).values.mean() + + return results + +def lat_apd(lat_pred, **kwargs): + """Computes average pairwise distance of latent features = the average distance between each pair of samples in latent space. + + Args: + lat_pred (torch.Tensor): of shape (batch_size, num_samples, latent_dim) with possible multiple latent_dimensions + + Returns: + lat_apd (torch.Tensor): of shape (batch_size) + """ + sample_num = lat_pred.shape[1] + mask = torch.tril(torch.ones([sample_num, sample_num], device=lat_pred.device)) == 0 # we only keep values from a single triangle of the matrix + lat_pred = lat_pred.view(*lat_pred.shape[:2], -1) # collapse latent dimensions + pdist = torch.cdist(lat_pred, lat_pred, p=1)[:, mask] + lat_apd = pdist.mean(axis=-1) + return lat_apd + + + diff --git a/SkeletonDiffusion/src/metrics/ranking.py b/SkeletonDiffusion/src/metrics/ranking.py new file mode 100644 index 0000000000000000000000000000000000000000..89e6b87f78cab3b2e70106b29dda7173618f13de --- /dev/null +++ b/SkeletonDiffusion/src/metrics/ranking.py @@ -0,0 +1,64 @@ +import torch + +def greates_minimum_distance(cdist: torch.Tensor, other_indices: list) -> int: + # cdist (N, M) + # cdist[other_indices] (N - M, M) + min_dist = cdist[..., other_indices, :].min(dim=-1)[0] # (N - M) + greatest_min_distance = min_dist.max() + + indices = (cdist.min(dim=1)[0] == greatest_min_distance).nonzero().tolist() + + for index in indices: + if index[0] in other_indices: + return index[0] + raise ValueError("No index found") + + +def get_highest_diversity(cdist: torch.Tensor, num_chosen_samples: int, decision_fn): + # cdist (N, N) + indices = [0] # index of GT + other_indices = list(range(1, cdist.shape[0])) + + for i in range(0, num_chosen_samples): + chosen_idx = decision_fn(cdist[..., indices], other_indices) + indices.append(chosen_idx) + other_indices.remove(chosen_idx) + + return [ i-1 for i in indices[1:]] # remove GT from indices + + +def find_samples_maxapd_wrtGT(pred, target, num_chosen_samples=5): + batch_size, n_samples = pred.shape[:2] + arr = torch.cat([target.unsqueeze(1), pred], dim=1) + arr = arr.reshape(batch_size, n_samples+1, -1) + dist = torch.cdist(arr, arr) # (batch_size, num_samples, num_samples) + chosen_set = [get_highest_diversity(dist_, num_chosen_samples=num_chosen_samples, decision_fn=greates_minimum_distance) for dist_ in dist]# batch_size x 5 + chosen_set_apd = None #apd(torch.stack([pred[i, idxs] for i, idxs in enumerate(chosen_set)], dim=0)) + # print(chosen_set_apd.shape) + # val, idxs = chosen_set_apd.max(-1) + # return val, idxs.item(), chosen_set[idxs.item()] # highest apd, batchidx, sample_idxs + return chosen_set_apd, chosen_set + +def get_closest_and_nfurthest_maxapd(y_pred, y_gt, nsamples): + assert len(y_pred.shape) == 4 and y_pred.shape[-1] == 3, f"Expected SxTxJx3 tensors, got {len(y_pred.shape)}" + S, T, J, _ = y_pred.shape + assert len(y_gt.shape) == 4 and y_gt.shape[0] == 1 and y_gt.shape[-2:] == y_pred.shape[-2:], f"Expected 1xTxJx3 tensors, got and {len(y_gt.shape)}" + # arr = torch.cat([y_pred, y_gt.unsqueeze(0)], dim=0) + arr = torch.cat([y_pred, y_gt], dim=0) + arr = arr.reshape(arr.shape[0], -1)# (num_samples_orig+1, others) + dist = torch.cdist(arr, arr) # (num_samples_orig+1, num_samples_orig) + sorted, indices = torch.sort(dist[-1, :-1], dim=0, descending=True) # in descending order + # sorted, indices = sorted[:-1], indices[:-1] + assert len(indices) == y_pred.shape[0] + + _, closest_idx = sorted[-1], indices[-1] + pred_closest = y_pred[closest_idx] + pred_closest, y_pred = pred_closest.unsqueeze(0), y_pred.unsqueeze(0) + + _, sorted_preds_idxs = find_samples_maxapd_wrtGT(y_pred, pred_closest, num_chosen_samples=nsamples) + sorted_preds_idxs = sorted_preds_idxs[0] # remove batch dim + y_pred = y_pred.squeeze(0) + pred_closest = pred_closest.squeeze(0) + sorted_preds = torch.stack([y_pred[i] for i in sorted_preds_idxs], dim=0) + # sorted_preds = torch.cat([pred_closest.unsqueeze(0), sorted_preds], dim=0) + return pred_closest, sorted_preds, sorted_preds_idxs \ No newline at end of file diff --git a/SkeletonDiffusion/src/metrics/utils.py b/SkeletonDiffusion/src/metrics/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..15ca73350ff10cbad651a91e455631a39961e072 --- /dev/null +++ b/SkeletonDiffusion/src/metrics/utils.py @@ -0,0 +1,49 @@ +import torch +from tabulate import tabulate +import numpy as np + +def format_metric_time_table(metric): + # dim 0 is time + interval = 30 # FPS/2 + table_timesteps = [i*interval for i in range(16) if i*interval< len(metric)] + metric = torch.stack([metric[t] for t in table_timesteps], dim=0) # + [metric.mean(0)] + return metric + +def choose_best_sample(out, y): + kpts3d = out + indeces = torch.linalg.norm(out - y.unsqueeze(1), dim=-1).mean(-1).mean(-1).min(axis=-1).indices.cpu().numpy() + indeces_bool = torch.zeros(out.shape[0], out.shape[1], dtype=bool) + for b, idx in enumerate(indeces): + indeces_bool[b,idx] = True + kpts3d = kpts3d[indeces_bool] + assert kpts3d.shape == y.shape + return kpts3d, y + +def get_best_sample_idx(out, y): + kpts3d = out + indeces = torch.linalg.norm(out - y.unsqueeze(1), dim=-1).mean(-1).mean(-1).min(axis=-1).indices.cpu().numpy() + indeces_bool = torch.zeros(out.shape[0], out.shape[1], dtype=bool) + for b, idx in enumerate(indeces): + indeces_bool[b,idx] = True + kpts3d = kpts3d[indeces_bool] + assert kpts3d.shape == y.shape + return kpts3d, indeces_bool + + +def draw_table(results): + metric_names_ptype = { 'ADE': [None]*3, 'FDE': [None]*3, 'MAE': [None]*3, + 'MMADE': [None]*3, 'MMFDE': [None]*3, 'APD': [None]*3, 'CMD': [None]*3, 'BodyRmean': [None]*3, 'BodyRrmse': [None]*3, + } + table_header = list(metric_names_ptype.keys()) #['Metric'] + + + for stats in results: + for m in table_header: + if m==stats: + metric_names_ptype[m][0] = f"{results[stats][-1]:.4f}" if isinstance(results[stats], list) else f"{results[stats]:.4f}" + else: + continue + metric_names_ptype['BodyRmean'][0] = str(round(results['StretchMean']*100, 3)) + u"\u00B1" + str(round(results['JitterMean']*100, 3)) + metric_names_ptype['BodyRrmse'][0] = str(round(results['StretchRMSE']*100, 3)) + u"\u00B1" + str(round(results['JitterRMSE']*100, 3)) + table = [[["total"]] +[metric_names_ptype[m] for m in table_header]] + table_header = ['Metric'] + table_header + return tabulate(table, headers=table_header, tablefmt="grid") diff --git a/SkeletonDiffusion/src/train_autoencoder.py b/SkeletonDiffusion/src/train_autoencoder.py new file mode 100644 index 0000000000000000000000000000000000000000..faebe273b5a14d71de423081306a4b0b32bc1406 --- /dev/null +++ b/SkeletonDiffusion/src/train_autoencoder.py @@ -0,0 +1,159 @@ +import os +import socket +import torch +from ignite.contrib.handlers import ProgressBar +from ignite.engine import Events, Engine +from ignite.metrics import RunningAverage +from ignite.contrib.handlers.tensorboard_logger import TensorboardLogger +from ignite.handlers import Checkpoint, DiskSaver + +from config_utils import create_train_dataloaders, create_model, flat_hydra_config, resume_training +from data import create_skeleton +from utils.reproducibility import set_seed +from utils.tensorboard import setup_tb_logging_valid, setup_tb_logging_train +from train_utils import setup_validation_autoencoder +from core import AutoEncoderTrainer, setup_scheduler_step + + + +os.environ["CUBLAS_WORKSPACE_CONFIG"] = ":4096:8" + +def train(output_log_path: str, + num_epochs: int, + eval_frequency: int = None, + num_iteration_eval: int = 0, + device: str = 'cpu', + seed: int = 52345, + num_iter_perepoch: int = 580, + detect_anomaly: bool = False, + if_resume_training: bool = False, + **kwargs) -> None: + torch.autograd.set_detect_anomaly(detect_anomaly) + + # Init seed + set_seed(seed) + torch.set_default_dtype(torch.float64 if kwargs["dtype"]== "float64" else torch.float32) + print("Default datatype: ", torch.get_default_dtype(), " . Using device: ", device) + print("Training on device: ", f"{socket.gethostname().split('.')[0]}") + if_run_validation = eval_frequency is not None + + skeleton = create_skeleton(**kwargs) + + # # Create model + model = create_model(device, skeleton=skeleton, num_nodes=skeleton.num_nodes, + node_types=skeleton.nodes_type_id, **kwargs) + + print(f"Created Autoencoder with {sum(p.numel() for p in model.parameters() if p.requires_grad)} trainable parameters.") + + # Load dataset + data_loader_train, data_loader_eval, data_loader_train_eval, random_state_manager = create_train_dataloaders(skeleton=skeleton, if_run_validation=if_run_validation, if_resume_training=if_resume_training, **kwargs) + + model_trainer = AutoEncoderTrainer(model, iter_per_epoch=num_iter_perepoch, **kwargs) + + + def set_epoch_seed(engine: Engine): + set_seed(seed + engine.state.epoch) + random_state_manager.reseed_generator(seed + engine.state.epoch) + + def preprocess(engine: Engine): + engine.state.batch = [t.to(device) for t in engine.state.batch[:2]] + + # Define Training Engines + trainer = Engine(model_trainer.train_step) + RunningAverage(output_transform=lambda x: x[0]).attach(trainer, 'Loss') + trainer.add_event_handler(Events.ITERATION_STARTED, preprocess) + trainer.add_event_handler(Events.EPOCH_STARTED, set_epoch_seed) + # Set up schedulers + setup_scheduler_step(model_trainer, train_engine=trainer) + if model_trainer.curriculum_scheduler is not None: + trainer.add_event_handler(Events.ITERATION_STARTED, model_trainer.curriculum_scheduler) + + pbar = ProgressBar() + pbar.attach(trainer, ['Loss']) + + # Setup tensorboard logging and progressbar + tb_logger = TensorboardLogger(log_dir=os.path.join(output_log_path, 'tb')) + setup_tb_logging_train(tb_logger, trainer=trainer, optimizer=model_trainer.optimizer, + model=model, train_out_transform=lambda out: {"loss": out[0], "pred horiz": out[-1]}) + if if_run_validation: + evaluator, evaluator_train = setup_validation_autoencoder(model, preprocess, model_trainer, skeleton) + setup_tb_logging_valid(tb_logger, trainer=trainer, evaluator=evaluator, evaluator_train=evaluator_train, + loss_names=["Loss"], metric_names=['ADE', 'FDE', "MPJPE_AVG", "MPJPE"]) + + # Define handlers for saving checkpoints + objects_to_checkpoint = {'trainer': trainer, 'model': model,"random_states": random_state_manager, **model_trainer.objects_to_checkpoint()} + checkpoint_handler = Checkpoint(objects_to_checkpoint, DiskSaver(os.path.join(output_log_path, "checkpoints"), create_dir=True, require_empty=False), n_saved=6, + global_step_transform= lambda engine, event_name: trainer.state.epoch, score_function=lambda engine: -1* round(engine.state.metrics['MPJPE_AVG'].item(), 7), score_name="val_mpjpe") + static_checkpoint_handler = Checkpoint(objects_to_checkpoint, checkpoint_handler.save_handler, n_saved=None, global_step_transform= lambda engine, event_name: trainer.state.epoch, score_function=lambda engine: -1* round(engine.state.metrics['MPJPE_AVG'].item(), 7), score_name="val_mpjpe_static") + if if_resume_training: + checkpoint = torch.load(kwargs['load_path']) + Checkpoint.load_objects(to_load=objects_to_checkpoint, checkpoint=checkpoint) + print("Resuming training from: epoch = ", trainer.state.epoch, '. Iteration = ', trainer.state.iteration) + + #Setup evaluation process between epochs + if if_run_validation: + @trainer.on(Events.EPOCH_COMPLETED(every=eval_frequency)) + def train_epoch_completed(engine: Engine): + set_seed(0) + random_state_manager.reseed_generator(0) + evaluator.run(data_loader_eval) + evaluator_train.run(data_loader_train_eval, epoch_length=num_iteration_eval) + + checkpoint_handler(evaluator) + static_checkpoint_handler(evaluator) + set_seed(seed + trainer.state.epoch) + random_state_manager.reseed_generator(seed + trainer.state.epoch) + + + trainer.run(data_loader_train, epoch_length=num_iter_perepoch, max_epochs=num_epochs) + tb_logger.close() + + +import shutil +from utils.tensorboard import get_tensorb_style_filename +from omegaconf import DictConfig, OmegaConf +import hydra +OmegaConf.register_new_resolver("eval", eval) +@hydra.main(config_path="../", config_name="config", version_base="1.3") +def main(cfg: DictConfig): + cfg = OmegaConf.to_container(cfg, resolve=True) + # for backwards compatibility with the code + cfg = flat_hydra_config(cfg) + + assert cfg['num_workers'] >=1, "Necessary for reproducibility issues" + + if cfg['debug']: + cfg['eval_frequency'] = 1 + # cfg['info'] = 'debug' + + if cfg['if_resume_training']: + print("Configuration file will be ignored. Considering old configuration file.") + cfg = resume_training(cfg) + else: + # Start from scratch and eventually create necessary logdir + cfg['load_path'] = "" + if not 'output_log_path' in cfg: + dt_str = get_tensorb_style_filename() #datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + if not cfg['info'] == '': + info_str = f"_{cfg['info']}" + else: + info_str = '' + cfg['output_log_path'] = os.path.join('./output', f"{dt_str}{info_str}") + os.makedirs(os.path.join(cfg['output_log_path'], 'checkpoints'), exist_ok=True) + code_dest_folder = os.path.join(cfg['output_log_path'], 'code') + if not os.path.exists(code_dest_folder): + with open(os.path.join(cfg['output_log_path'], 'config.yaml'), 'w') as config_file: + OmegaConf.save(cfg, config_file) + shutil.copytree(os.path.dirname(__file__), code_dest_folder) + + print("Traing data saved at ", cfg['output_log_path']) + train(**cfg) + + + + +if __name__ == '__main__': + main() + + + diff --git a/SkeletonDiffusion/src/train_diffusion.py b/SkeletonDiffusion/src/train_diffusion.py new file mode 100644 index 0000000000000000000000000000000000000000..a2f4c9bccd76f17edd244bf9e71d3107165d6f11 --- /dev/null +++ b/SkeletonDiffusion/src/train_diffusion.py @@ -0,0 +1,181 @@ +import os +from functools import partial +import socket + +import torch +from ignite.contrib.handlers import ProgressBar +from ignite.engine import Events, Engine +from ignite.metrics import RunningAverage +from ignite.contrib.handlers.tensorboard_logger import TensorboardLogger +from ignite.handlers import Checkpoint, DiskSaver + +from utils.reproducibility import set_seed +from utils.tensorboard import setup_tb_logging_valid, setup_tb_logging_train +from train_utils import setup_validation_diffusion +from core import DiffusionManager, TrainerDiffusion, setup_scheduler_step +from config_utils import create_train_dataloaders, create_model, flat_hydra_config, resume_training +from utils.config import load_and_merge_autoenc_cfg +from data import create_skeleton +from utils.load import load_autoencoder + +os.environ["CUBLAS_WORKSPACE_CONFIG"] = ":4096:8" + +def train(output_log_path: str, + num_epochs: int, + eval_frequency: int = None, + num_iteration_eval: int = 0, + device: str = 'cpu', + seed: int = 63485, + num_iter_perepoch: int = None, + detect_anomaly: bool = False, + if_resume_training: bool = False, + **kwargs) -> None: + torch.autograd.set_detect_anomaly(detect_anomaly) + + # Init seed + set_seed(seed) + torch.set_default_dtype(torch.float64 if kwargs["dtype"]== "float64" else torch.float32) + print("Default datatype: ", torch.get_default_dtype(), " . Using device: ", device) + print("Training on device: ", f"{socket.gethostname().split('.')[0]}") + if_run_validation = eval_frequency is not None + + skeleton = create_skeleton(**kwargs) + + # # Create model + model = create_model(device, skeleton=skeleton, num_nodes=skeleton.num_nodes, + node_types=skeleton.nodes_type_id, **kwargs) + print(f"Loaded Autoencoder Model with {sum(p.numel() for p in model.parameters() if p.requires_grad)} parameters.") + # Load GraphModel + load_autoencoder(model, **kwargs) + + diffusionmanager = DiffusionManager(skeleton=skeleton, num_nodes=skeleton.num_nodes, + node_types=skeleton.nodes_type_id, **kwargs) + diffusion = diffusionmanager.get_diffusion().to(device) + + + print(f"Created Diffusion Model with {sum(p.numel() for p in diffusion.model.parameters() if p.requires_grad)} trainable parameters.") + + # Load dataset + data_loader_train, data_loader_eval, data_loader_train_eval, random_state_manager = create_train_dataloaders(skeleton=skeleton, if_run_validation=if_run_validation, if_resume_training=if_resume_training, **kwargs) + + diffusion_trainer = TrainerDiffusion( diffusion, device=device, + ema_decay = 0.995, # exponential moving average decay + skeleton=skeleton, + autoencoder=model, + **kwargs, + ) + + def set_epoch_seed(engine: Engine): + set_seed(seed + engine.state.epoch) + random_state_manager.reseed_generator(seed + engine.state.epoch) + def preprocess(engine: Engine): + engine.state.batch = [t.to(device) for t in engine.state.batch[:2]] + + + # Define Training Engines + trainer = Engine(diffusion_trainer.train_step) + RunningAverage(output_transform=lambda x: x[0]).attach(trainer, 'Loss') + trainer.add_event_handler(Events.ITERATION_STARTED, preprocess) + trainer.add_event_handler(Events.EPOCH_STARTED, set_epoch_seed) + # Set up scheduler + setup_scheduler_step(diffusion_trainer, train_engine=trainer) + + # Setup progressbar for training + pbar = ProgressBar() + pbar.attach(trainer, ['Loss']) + # Setup tensorboard logging + tb_logger = TensorboardLogger(log_dir=os.path.join(output_log_path, 'tb')) + setup_tb_logging_train(tb_logger, trainer=trainer, optimizer=diffusion_trainer.opt, + model=diffusion, train_out_transform=lambda out: {"loss": out[0]}) + if if_run_validation: + evaluator, evaluator_train = setup_validation_diffusion(model, preprocess, diffusion_trainer, skeleton) + setup_tb_logging_valid(tb_logger, trainer=trainer, evaluator=evaluator, evaluator_train=evaluator_train, + loss_names=["Loss"], metric_names=['ADE', 'APD', "MPJPE_AVG", "MPJPE", 'LLVar', 'LearningRate']) + + # Define objecs to save in checkpoint + objects_to_checkpoint = {**diffusion_trainer.get_checkpoint_object(), **{'trainer': trainer, "random_states": random_state_manager}} + checkpoint_handler = Checkpoint(objects_to_checkpoint, DiskSaver(os.path.join(output_log_path, "checkpoints"), create_dir=True, require_empty=False), n_saved=6, + global_step_transform= lambda engine, event_name: trainer.state.epoch, score_function=lambda engine: -1* round(engine.state.metrics['ADE'], 7), score_name="val_ade") + latest_checkpoint_handler = Checkpoint(objects_to_checkpoint, checkpoint_handler.save_handler, n_saved=1, global_step_transform= lambda engine, event_name: trainer.state.epoch) + if if_resume_training: + checkpoint = torch.load(kwargs['load_path']) + Checkpoint.load_objects(to_load=objects_to_checkpoint, checkpoint=checkpoint) + print("Resuming training from: epoch = ", trainer.state.epoch, '. Iteration = ', trainer.state.iteration) + + #Setup evaluation process between epochs + @trainer.on(Events.EPOCH_COMPLETED) + def save_latest_model(engine: Engine): + latest_checkpoint_handler(evaluator) + + if if_run_validation: + @trainer.on(Events.EPOCH_COMPLETED(every=eval_frequency)) + def train_epoch_completed(engine: Engine): + set_seed(0) + random_state_manager.reseed_generator(0) + evaluator.run(data_loader_eval) + evaluator_train.run(data_loader_train_eval, epoch_length=num_iteration_eval) + checkpoint_handler(evaluator) + set_seed(seed + trainer.state.epoch) + random_state_manager.reseed_generator(seed + trainer.state.epoch) + + + trainer.run(data_loader_train, epoch_length=num_iter_perepoch if num_iter_perepoch is not None else len(data_loader_train), max_epochs=num_epochs) + tb_logger.close() + + + +from omegaconf import DictConfig, OmegaConf +OmegaConf.register_new_resolver("eval", eval) +import hydra +import shutil +from utils.tensorboard import get_tensorb_style_filename + + +@hydra.main(config_path="../", config_name="config_diffusion", version_base="1.3") +def main(cfg: DictConfig): + + cfg = flat_hydra_config(cfg) + + suffix = "diffusion" + + assert cfg['num_workers'] >=1, "Necessary for reproducibility issues" + + # TO DO remove here + if cfg['debug']: + cfg['eval_frequency'] = 1 + cfg['info'] = 'debug' + + if cfg['if_resume_training']: + print("Configuration file will be ignored. Considering old configuration file.") + cfg = resume_training(cfg) + else: + # Start from scratch and eventually create necessary logdir + cfg['load_path'] = "" + if not 'output_log_path' in cfg: + dt_str = get_tensorb_style_filename() #datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + if not cfg['info'] == '': + info_str = f"_{cfg['info']}" + else: + info_str = '' + output_path = os.path.join(os.path.dirname(os.path.dirname(cfg['pretrained_autoencoder_path'])), suffix) + cfg['output_log_path'] = os.path.join(output_path, f"{dt_str}{info_str}") + os.makedirs(os.path.join(cfg['output_log_path'], 'checkpoints'), exist_ok=True) + # To DO remove code destination + code_dest_folder = os.path.join(cfg['output_log_path'], 'code') + if not os.path.exists(code_dest_folder): + os.makedirs(cfg['output_log_path'], exist_ok=True) + with open(os.path.join(cfg['output_log_path'], 'config.yaml'), 'w') as config_file: + OmegaConf.save(cfg, config_file) + shutil.copytree(os.path.dirname(__file__), code_dest_folder) + + cfg = load_and_merge_autoenc_cfg(cfg) + print("Traing data saved at ", cfg['output_log_path']) + train(**cfg) + + +if __name__ == '__main__': + main() + + + + diff --git a/SkeletonDiffusion/src/train_utils.py b/SkeletonDiffusion/src/train_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..9ed7bdb6a801cbc38292bc7407043db9bb9656c4 --- /dev/null +++ b/SkeletonDiffusion/src/train_utils.py @@ -0,0 +1,91 @@ +import torch +from ignite.engine import Events, Engine +from ignite.metrics import RunningAverage, Loss +from typing import Sequence + +from SkeletonDiffusion.src.metrics import MeanPerJointPositionError, FinalDisplacementError, ade, MetricStorer +from SkeletonDiffusion.src.metrics import apd, ade, limb_length_variance, MetricStorer, MeanPerJointPositionError, choose_best_sample + + +def setup_validation_autoencoder(model, preprocess, model_trainer, skeleton): + def validation_step_autoencoder(engine: Engine, batch: Sequence[torch.Tensor]): + with torch.no_grad(): + model_out, y, x, z = model_trainer.validation_step(engine, batch) + model_out_metric = skeleton.transform_to_metric_space(model_out) + y_metric = skeleton.transform_to_metric_space(y) + return (model_out_metric, y_metric), (model_out, y), z, + + # Define ignite metrics + ade_metric = MetricStorer(output_transform=lambda x: ade(pred=x[0][0].unsqueeze(1), target=x[0][1])) + mpjpe = MeanPerJointPositionError(output_transform=lambda x: (x[0])) + fde = FinalDisplacementError(output_transform=lambda x: (x[0])) + loss_metric = Loss(model.loss, output_transform=lambda x: (x[1])) + + def add_avg_metrics_to_existing_metrics(engine: Engine): + for metric in list(engine.state.metrics.keys()): + if metric in ["MPJPE"]: + engine.state.metrics[metric+"_AVG"] = engine.state.metrics[metric].mean(0) + + def attach_losses_to_engine(engine): + engine.add_event_handler(Events.ITERATION_STARTED, preprocess) + loss_metric.attach(engine, 'Loss') + + def attach_evalmetrics_to_engine(engine): + mpjpe.attach(engine, 'MPJPE') + ade_metric.attach(engine, 'ADE') + fde.attach(engine, 'FDE') + engine.add_event_handler(Events.COMPLETED, add_avg_metrics_to_existing_metrics) + + # Define Evaluation Engines and attach metrics + evaluator = Engine(validation_step_autoencoder) + attach_losses_to_engine(evaluator) + attach_evalmetrics_to_engine(evaluator) + + # Evaluate on Train dataset + evaluator_train = Engine(validation_step_autoencoder) + attach_losses_to_engine(evaluator_train) + attach_evalmetrics_to_engine(evaluator_train) + + return evaluator, evaluator_train + +def setup_validation_diffusion(model, preprocess, diffusion_trainer, skeleton): + def validation_step(engine: Engine, batch: Sequence[torch.Tensor]): + model_out, y, _, x = diffusion_trainer.validation_step(engine=engine, batch=batch) + model_out_metric = skeleton.transform_to_metric_space(model_out) + y_metric = skeleton.transform_to_metric_space(y) + return {'pred':model_out_metric, 'target':y_metric}, (model_out, y), x + + # Define ignite metrics + mpjpe = MeanPerJointPositionError(output_transform=lambda x: choose_best_sample( x[0]['pred'], x[0]['target'],)) + apd_metric = MetricStorer(output_transform=lambda x: apd(**x[0])) + ade_metric = MetricStorer(output_transform=lambda x: ade(**x[0])) + limbl_variance = MetricStorer(output_transform=lambda x: limb_length_variance(pred=x[0]['pred'], limbseq=skeleton.get_limbseq(), mode='mean')) + loss_metric = Loss(model.loss, output_transform=lambda x: choose_best_sample(*x[-2])) + + def add_avg_metrics_to_existing_metrics(engine: Engine): + for metric in list(engine.state.metrics.keys()): + if metric in ["MPJPE"]: + engine.state.metrics[metric+"_AVG"] = engine.state.metrics[metric].mean(0) + engine.state.metrics["LearningRate"] = diffusion_trainer.opt.param_groups[0]['lr'] + + def attach_evalmetrics_to_engine(engine): + engine.add_event_handler(Events.ITERATION_STARTED, preprocess) + mpjpe.attach(engine, 'MPJPE') + apd_metric.attach(engine, 'APD') + ade_metric.attach(engine, 'ADE') + limbl_variance.attach(engine, 'LLVar') + engine.add_event_handler(Events.COMPLETED, add_avg_metrics_to_existing_metrics) + + def attach_losses_to_engine(engine): + loss_metric.attach(engine, 'Loss') + + # Define Evaluation and Test Engines and attach metrics + evaluator = Engine(validation_step) + attach_evalmetrics_to_engine(evaluator) + attach_losses_to_engine(evaluator) + + evaluator_train = Engine(validation_step) + attach_evalmetrics_to_engine(evaluator_train) + attach_losses_to_engine(evaluator_train) + + return evaluator, evaluator_train diff --git a/SkeletonDiffusion/src/utils/__init__.py b/SkeletonDiffusion/src/utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/SkeletonDiffusion/src/utils/config.py b/SkeletonDiffusion/src/utils/config.py new file mode 100644 index 0000000000000000000000000000000000000000..03b75d7ee8cbec95246e86271645bbfa91848951 --- /dev/null +++ b/SkeletonDiffusion/src/utils/config.py @@ -0,0 +1,55 @@ + +import yaml +import os + +def load_and_merge_autoenc_cfg(cfg, eval=False): + config_gm = os.path.join(os.path.dirname(os.path.dirname(cfg['pretrained_autoencoder_path'])), 'config.yaml') + with open(config_gm, 'r') as stream: + cfg_gm = yaml.safe_load(stream) + if eval: + cfg_gm.pop('dataset', None) + cfg = merge_cfg(cfg, cfg_gm) + return cfg + +def merge_cfg(cfg, cfg_gm): + """ + If keys ar ein both cfg, we take the ones of cfg: cfg overrides cfg_gm + """ + for k in set(cfg.keys()).intersection(cfg_gm.keys()): + cfg_gm.pop(k, None) + assert len(set(cfg.keys()).intersection(cfg_gm.keys())) == 0 + cfg = {**cfg, **cfg_gm} + return cfg + +def make_paths_absolute(cfg): + cfg = cfg.copy() + # transform paths in cfg to absolute paths + for k in cfg: + if 'data_loader' in k: + if 'annotations_folder' in cfg[k]: + cfg[k]['annotations_folder'] = os.path.abspath(cfg[k]['annotations_folder']) + if 'segments_path' in cfg[k]: + cfg[k]['segments_path'] = os.path.abspath(cfg[k]['segments_path']) + + if 'precomputed_folder' in cfg: + cfg['precomputed_folder'] = os.path.abspath(cfg['precomputed_folder']) + if 'annotations_folder' in cfg: + cfg['annotations_folder'] = os.path.abspath(cfg['annotations_folder']) + if 'pretrained_autoencoder_path' in cfg: + cfg['pretrained_autoencoder_path'] = os.path.abspath(cfg['pretrained_autoencoder_path']) + return cfg + +def init_obj(config, name, module, *args, **kwargs): + """ + Finds a function handle with the name given as 'type' in config, and returns the + instance initialized with corresponding arguments given. + + `object = config.init_obj('name', module, a, b=1)` + is equivalent to + `object = module.name(a, b=1)` + """ + module_name = config[name] + module_args = config #dict(config[name]['args']) + assert all([k not in module_args for k in kwargs]), 'Overwriting kwargs given in config file is not allowed' + module_args = {**kwargs, **config} + return getattr(module, module_name)(*args, **module_args) \ No newline at end of file diff --git a/SkeletonDiffusion/src/utils/image.py b/SkeletonDiffusion/src/utils/image.py new file mode 100644 index 0000000000000000000000000000000000000000..122be69ba2e3197e132d3cf38aa46248ea03ffae --- /dev/null +++ b/SkeletonDiffusion/src/utils/image.py @@ -0,0 +1,35 @@ +import imageio +import torch +from PIL import Image +import numpy as np +from .numpy import tensor_img_to_numpy + +def save_img(img, path): + if torch.is_tensor(img): + img = convert_img_tensor_to_np_img(img) + if not (path.endswith('.jpg') or path.endswith('.png') or path.endswith('.jpeg')): + path += '.jpeg' + imageio.imwrite(path, img) + +def save_gif(frames, fps=30, name=None): + if torch.is_tensor(frames): + frames = tensor_img_to_numpy(frames) + if name is None: + name = './images/movie.gif' + if not name.endswith(".gif"): + name += ".gif" + imageio.mimsave(name, frames, fps=fps) + return name + + +def convert_img_tensor_to_np_img(tensor): + assert len(tensor.shape) == 3 + tensor = tensor.permute(1, 2, 0) + img = tensor.cpu().numpy() + return img + + +def load_image(img_path): + img = Image.open(img_path) + img = np.array(img) # in range(0, 255), + return img # shape (H,W, 3) \ No newline at end of file diff --git a/SkeletonDiffusion/src/utils/keypoints.py b/SkeletonDiffusion/src/utils/keypoints.py new file mode 100644 index 0000000000000000000000000000000000000000..eb44cab2c83f16e536bc8bb1154bd91c441069ca --- /dev/null +++ b/SkeletonDiffusion/src/utils/keypoints.py @@ -0,0 +1,37 @@ +import random +import torch +import math + +def center_kpts_around_hip(kpts, hip_idx=0): + #hip is always joint n0 in h36m regardless of number of joints considered + center = kpts[..., hip_idx, :].unsqueeze(-2) #(n_frames, n_joints, 3) + centered_kpts = kpts - center + # centered_kpts = centered_kpts[..., 1:, :] # keep hip joint for compatibility with rest of code + return centered_kpts, center + +def center_kpts_around_hip_and_drop_root(kpts, hip_idx=0): + centered_kpts, center = center_kpts_around_hip(kpts.clone(), hip_idx) + centered_kpts = centered_kpts[..., 1:, :] + return centered_kpts + +def rotate_y_axis(kpts, angle_degrees, axis=1): + phi = torch.tensor(angle_degrees * math.pi / 180) + s = torch.sin(phi) + c = torch.cos(phi) + if axis == 1: + rot = torch.tensor([[c, 0, -s], + [0, 1.0, 0], + [s, 0, c]]) # 3x3 + elif axis == 0: + rot = torch.tensor([[1.0, 0, 0], + [0, c, -s], + [0, s, c]]) # 3x3 + elif axis == 2: + rot = torch.tensor([[c, -s, 0], + [s, c, 0], + [0, 0, 1.0]]) # 3x3 + else: + assert 0, "Not implemented" + + x_rot = kpts @ rot.t() + return x_rot diff --git a/SkeletonDiffusion/src/utils/load.py b/SkeletonDiffusion/src/utils/load.py new file mode 100644 index 0000000000000000000000000000000000000000..2b2894d1cabedadb4ba8dc7f3b3897f944b2407e --- /dev/null +++ b/SkeletonDiffusion/src/utils/load.py @@ -0,0 +1,26 @@ +import torch +import os + +def get_latest_model_path(ckpnt_path): + files = [f for f in os.listdir(ckpnt_path) if f.startswith('checkpoint_')] + epoch = [int(f.split('_val')[0].replace('checkpoint_', '').replace('.pt', '')) for f in files] + corr = {m:f for m,f in zip(epoch, files)} + epoch.sort() + return os.path.join(ckpnt_path, corr[epoch[-1]]) + +def load_model_checkpoint(load_path): + if not load_path.endswith(".pt"): # support for models stored in ".p" format + print("Loading from a '.p' checkpoint. Only evaluation is supported. Only model weights will be loaded.") + checkpoint = torch.load(load_path, weights_only=False) + else: # ".pth" format + checkpoint = torch.load(load_path, weights_only=False) #, map_location=device) + return checkpoint + +def load_autoencoder(model, **kwargs): + checkpoint = torch.load(kwargs['pretrained_autoencoder_path']) + model.load_state_dict(checkpoint['model'])#, strict=False) + # freeze weights + for param in model.parameters(): + param.requires_grad = False + model.eval() + \ No newline at end of file diff --git a/SkeletonDiffusion/src/utils/numpy.py b/SkeletonDiffusion/src/utils/numpy.py new file mode 100644 index 0000000000000000000000000000000000000000..efd6a10a506aec22f4a9ecc65e5b8190de3ebf39 --- /dev/null +++ b/SkeletonDiffusion/src/utils/numpy.py @@ -0,0 +1,21 @@ +import torch +import numpy as np + +def numpy_img_to_tensor(np_array): + return torch.tensor(np_array).permute(2, 0, 1) + + +def get_fig_as_nparray(fig): + fig.canvas.draw() # draw the canvas, cache the renderer + image = np.frombuffer(fig.canvas.tostring_rgb(), dtype='uint8') + image = image.reshape(fig.canvas.get_width_height()[::-1] + (3,)) + return image + +def tensor_img_to_numpy(tensor): + # (n_frames, 3, widht, height) + if len(tensor.shape) == 4: + return tensor.permute(0, 2, 3, 1).numpy() + elif len(tensor.shape) == 3: + return tensor.permute(1, 2, 0).numpy() + else: + assert 0, f"Tensor has incorrect shape: {tensor.shape}" \ No newline at end of file diff --git a/SkeletonDiffusion/src/utils/plot.py b/SkeletonDiffusion/src/utils/plot.py new file mode 100644 index 0000000000000000000000000000000000000000..56c1af0f0a3bac1bada46b3a93f21d6f2926dbb4 --- /dev/null +++ b/SkeletonDiffusion/src/utils/plot.py @@ -0,0 +1,219 @@ +import matplotlib.animation as animation +import matplotlib.pyplot as plt +import numpy as np +from functools import partial + +from .numpy import get_fig_as_nparray, numpy_img_to_tensor + +RADIUS = np.array([1,1,1])*0.025 #in m +RESOPTIONS = { # high res + # "figsize": 200, "linewidth": 8, + # lower res + "figsize": 12, "linewidth": 2, + # "figsize": 6, "linewidth": 1, + + } + +def create_pose(ax, plots, vals, limbseq, left_right_limb, pred=True, num_multiple_preds=1, update=False, random_color=False, color=None, **kwargs): + + # Start and endpoints of our representation + I = np.array([touple[0] for touple in limbseq]) + J = np.array([touple[1] for touple in limbseq]) + # Left / right indicator + LR = np.array([left_right_limb[a] or left_right_limb[b] for a, b in limbseq]) + if pred: + lcolor = "#D22B2B" + if num_multiple_preds >1: + lcolor = "#0000FF" + if random_color: + import random + lcolor = "#"+''.join([random.choice('ABCDEF0123456789') for i in range(6)]) + if color is not None: + lcolor = color + rcolor = lcolor #"#2ecc71" + else: + rcolor = "#383838" # dark grey + lcolor = rcolor #"#8e8e8e" + if random_color: + import random + lcolor = "#"+''.join([random.choice('ABCDEF0123456789') for i in range(6)]) + rcolor = lcolor + elif color is not None: + lcolor = color + rcolor = lcolor + + rang = len(I)*num_multiple_preds if pred else 0 + for i in np.arange(len(I)): + x = np.array([vals[I[i], 0], vals[J[i], 0]]) + y = np.array([vals[I[i], 1], vals[J[i], 1]]) + z = np.array([vals[I[i], 2], vals[J[i], 2]]) + if not update: + + if i == 0: + plots.append(ax.plot(x, y, z, c=rcolor if LR[i] else lcolor, lw=RESOPTIONS["linewidth"], + label=['GT' if not pred else 'Pred'])) #lw=2, linestyle='--', + else: + plots.append(ax.plot(x, y, z, lw=RESOPTIONS["linewidth"], c=lcolor if LR[i] else rcolor)) #lw=2, linestyle='--', + + elif update: + plots[rang+i][0].set_xdata(x) + plots[rang+i][0].set_ydata(y) + plots[rang+i][0].set_3d_properties(z) + plots[rang+i][0].set_color(lcolor if LR[i] else rcolor) + return plots + + +def center_around_hip(vals, ax): + global RADIUS + rx, ry, rz = RADIUS[0], RADIUS[1], RADIUS[2] + # remember that y and z are switched in the plot + xroot, zroot, yroot = vals[0,0], vals[0,1], vals[0,2] + #uncomment folowing lines to set a limit to the plot (relevant if grid is) + ax.set_xlim3d([-rx+xroot*2, rx+xroot*2]) + ax.set_ylim3d([-ry+yroot*2, ry+yroot*2]) + ax.set_zlim3d([-rz+zroot*2, rz+zroot*2]) + +def update(num,data_gt,plots_gt,fig,ax, data_pred=None, center_pose=True, return_img=False, **kwargs): + + gt_vals=data_gt[num] + ax.set_title(ax.get_title(loc='center').split("\n")[0] + f"\nframe {num+1}/{len(data_gt)}") + +# pred_vals=data_pred[num] + plots_gt=create_pose(ax,plots_gt,gt_vals,pred=False,update=True, **kwargs) + if data_pred is not None: + if kwargs["multiple_data_pred"]: + for i,prediction in enumerate(data_pred): + gt_plots=create_pose(ax,plots_gt,prediction[num],num_multiple_preds=i+1, pred=True,update=True, **kwargs) + else: + vals=data_pred[num] + plots_gt=create_pose(ax,plots_gt,vals,pred=True,update=True, **kwargs) +# plots_pred=create_pose(ax,plots_pred,pred_vals,pred=True,update=True) + + if center_pose: + center_around_hip(gt_vals, ax) + # ax.set_title('pose at time frame: '+str(num)) + # ax.set_aspect('equal') + if return_img: + img = get_fig_as_nparray(fig) + return img + return plots_gt + + + +def get_np_frames_3d_projection(poses_reshaped3d, limbseq, left_right_limb, data_pred=None, multiple_data_pred=False, xyz_range=None, is_range_sym=False, center_pose=False, units="mm", + as_tensor=False, if_as_overlapping_image=False, orientation_like=None, title=None, center_like=None, if_hide_grid=False, color=None, fig=None): + assert len(poses_reshaped3d.shape) == 3, poses_reshaped3d.shape + assert units in ["mm", "bins"] + assert orientation_like is None or orientation_like in ["motron", "h36m", "somof", "3dpw", "freeman", "best"] + vals = poses_reshaped3d.copy() + if xyz_range is not None: + xyz_range = xyz_range.clone() + timesteps = vals.shape[0] + if fig is None: + fig = plt.figure(figsize=(RESOPTIONS["figsize"], RESOPTIONS["figsize"])) # change here for speed & lightweight, 20 + ax = plt.axes(projection='3d') + if title is not None: + ax.set_title(title) + # vals[:,:,0] = poses_reshaped3d[:,:,2].copy() + # vals[:,:,2] = poses_reshaped3d[:,:,0].copy() + if units == "mm": + vals /= 1000 # from mm to meters + + if data_pred is not None: + data_pred = data_pred.copy() + if units == "mm": + data_pred/= 1000 + + ax.set_xlabel("x") + ax.set_ylabel("z") + ax.set_zlabel("y") + + global RADIUS + if xyz_range is not None: + assert center_pose == False + if units=="mm": + xyz_range /= 1000 + if not is_range_sym: + ax.set_xlim3d([0, xyz_range[0]]) + ax.set_ylim3d([0, xyz_range[2]]) + ax.set_zlim3d([0, xyz_range[1]]) + else: + ax.set_xlim3d([-xyz_range[0]/2, xyz_range[0]/2]) + ax.set_ylim3d([-xyz_range[2]/2, xyz_range[2]/2]) + ax.set_zlim3d([-xyz_range[1]/2, xyz_range[1]/2]) + elif center_like is not None: + if units=="mm": + RADIUS = (center_like[0].max(axis=0)/1000)//2 # symmetric radius distance from body center + RADIUS[RADIUS==0] = 3 + center_around_hip(center_like[0]/1000, ax) + else: + RADIUS = center_like[0].max(axis=0)//2 # symmetric radius distance from body center + RADIUS[RADIUS==0] = 1 + center_around_hip(center_like[0], ax) + else: + RADIUS = vals[0].max(axis=0)//2 # symmetric radius distance from body center + RADIUS[RADIUS==0] = 3 + center_around_hip(vals[0], ax) + + # if (vals[...,1]<0.).all(): + # ax.invert_zaxis() + ax.set_box_aspect([1,1,1]) + if if_hide_grid: + ax.grid(False) + plt.axis('off') + # following to remove ticks + # ax.set_xticks([]) + # ax.set_yticks([]) + # ax.set_zticks([]) + # # following to remove axis labels + # ax.xaxis.label.set_visible(False) + # ax.yaxis.label.set_visible(False) + # ax.zaxis.label.set_visible(False) + + if orientation_like is not None: + if orientation_like =="h36m": + ax.view_init(0, -70) # View angle from cameras in h36m, in altitude(angle xzplane with y axis), azimuth + elif orientation_like =="motron": + ax.view_init(12, 48) # motron h36m view angle + elif orientation_like =="freeman" or orientation_like =="best": + ax.invert_zaxis() + ax.view_init(azim=-60, elev=30) + elif orientation_like =="3dpw": + ax.invert_zaxis() + ax.view_init(azim=-90, elev=0) # somof view angle + elif orientation_like =="somof": + ax.view_init(azim=-90, elev=0) # somof view angle + + gt_plots=[] + pred_plots=[] + + gt_plots=create_pose(ax,gt_plots,vals[0],pred=False,update=False, limbseq=limbseq, left_right_limb=left_right_limb, color=color) + if data_pred is not None: + if multiple_data_pred: + import random + colors = ["#"+''.join([random.choice('ABCDEF0123456789') for i in range(6)]) for i in range(len(data_pred))] + for i,prediction in enumerate(data_pred): + gt_plots=create_pose(ax,gt_plots,prediction[0],pred=True,num_multiple_preds=i+1, update=False, limbseq=limbseq, left_right_limb=left_right_limb, color=colors[i]) + else: + gt_plots=create_pose(ax,gt_plots,data_pred[0],pred=True,update=False, limbseq=limbseq, left_right_limb=left_right_limb, color=color) + + + if if_as_overlapping_image: + def add_timestep(t): + if data_pred is not None and t < data_pred.shape[-3]: + if multiple_data_pred: + for i,prediction in enumerate(data_pred): + __ = create_pose(ax,gt_plots,prediction[t],pred=True,num_multiple_preds=i+1, update=False, color=colors[i], limbseq=limbseq, left_right_limb=left_right_limb) + else: + __ =create_pose(ax,gt_plots,data_pred[t],pred=True,update=False, limbseq=limbseq, left_right_limb=left_right_limb, color=color) + __ = create_pose(ax,gt_plots,vals[t],pred=False,update=False, limbseq=limbseq, left_right_limb=left_right_limb, color=color) + for t in range(timesteps): + add_timestep(t) + frames = [get_fig_as_nparray(fig)] + else: + frames = [update(t,vals,gt_plots,fig,ax, data_pred=data_pred, center_pose=center_pose, return_img=True, limbseq=limbseq, left_right_limb=left_right_limb, color=color, multiple_data_pred=multiple_data_pred) for t in range(len(vals))] + if as_tensor: + frames = [numpy_img_to_tensor(f) for f in frames] + # frames = [numpy_img_to_tensor(update(t,vals,gt_plots,fig,ax, data_pred=data_pred, center_pose=center_pose, return_img=True, limbseq=limbseq, left_right_limb=left_right_limb, color=color, multiple_data_pred=multiple_data_pred)) for t in range(len(vals))] + plt.close() # necessary for memory if training) + return frames#, (fig,ax) diff --git a/SkeletonDiffusion/src/utils/reproducibility.py b/SkeletonDiffusion/src/utils/reproducibility.py new file mode 100644 index 0000000000000000000000000000000000000000..9d8888f625ac0330839400c93af8b864185a0cbe --- /dev/null +++ b/SkeletonDiffusion/src/utils/reproducibility.py @@ -0,0 +1,81 @@ +import torch +import ignite +import numpy as np +import random +import os + + + +def set_seed(seed): + torch.manual_seed(seed) + # if torch.cuda.is_available(): + # torch.backends.cudnn.enabled = False + torch.use_deterministic_algorithms(True) + torch.backends.cudnn.deterministic = True + torch.backends.cudnn.benchmark = False + np.random.seed(seed) + random.seed(seed) + torch.cuda.manual_seed(seed) + torch.cuda.manual_seed_all(seed) + # WARNING: if cudnn.enabled=False => greatly reduces training/inference speed. + torch.backends.cudnn.enabled = True + os.environ["PYTHONHASHSEED"] = str(seed) + ignite.utils.manual_seed(seed) + +def seed_worker(worker_id): + worker_seed = torch.initial_seed() % 2**32 + np.random.seed(worker_seed) + random.seed(worker_seed) + torch.cuda.manual_seed(worker_seed) + torch.manual_seed(worker_seed) + ignite.utils.manual_seed(worker_seed) + +def seed_eval_worker(worker_id): + + worker_seed = 0 # set to zero for evaluation + np.random.seed(worker_seed) + random.seed(worker_seed) + torch.cuda.manual_seed(worker_seed) + torch.manual_seed(worker_seed) + ignite.utils.manual_seed(worker_seed) + +def get_torch_generator(): + g = torch.Generator() + g.manual_seed(torch.initial_seed()) + return g + +class RandomStateDict(): + """ + According to https://pytorch.org/docs/stable/data.html#data-loading-randomness under Multi-process data loading, there is no need to set seeds inbetween an epoch. + <> + I suppose seeds are colelcted from environment, so setting up environment seeds aftr lading or resuming training should be sufficient to ensure reproducibility + """ + def __init__(self): + self.generator = get_torch_generator() + + def reseed_generator(self, seed): + # self.generator.manual_seed(torch.initial_seed()) + self.generator.manual_seed(seed) + + def state_dict(self): + state_dict = {} + state_dict['random'] = random.getstate() + state_dict['numpy'] = np.random.get_state() + state_dict['torch'] = torch.get_rng_state() + state_dict['torch_random'] = torch.random.get_rng_state() + state_dict['torch_cuda'] = torch.cuda.get_rng_state(device='cuda') + state_dict['generator'] = self.generator.get_state() + return state_dict + + def load_state_dict(self, chkpt_obj): + torch.random.set_rng_state(chkpt_obj['torch_random']) + torch.set_rng_state(chkpt_obj['torch']) + self.generator.set_state(chkpt_obj['generator']) + torch.use_deterministic_algorithms(True) + torch.backends.cudnn.deterministic = True + torch.backends.cudnn.benchmark = False + random.setstate(chkpt_obj['random']) + np.random.set_state(chkpt_obj['numpy']) + torch.cuda.set_rng_state(chkpt_obj['torch_cuda'], device='cuda') + + \ No newline at end of file diff --git a/SkeletonDiffusion/src/utils/store.py b/SkeletonDiffusion/src/utils/store.py new file mode 100644 index 0000000000000000000000000000000000000000..ed71b420899876b0a286b8e98d8280af3db40943 --- /dev/null +++ b/SkeletonDiffusion/src/utils/store.py @@ -0,0 +1,57 @@ +import os +import zarr +import numpy as np +import yaml + + +class SequenceStorer: + def __init__(self, store_output_path, num_samples, num_sequences, config,if_gt=False): + self.store_output_path = store_output_path + self.num_samples = num_samples + self.config = config + self.if_gt = if_gt + self.pred_length = self.config['pred_length']*config['long_term_factor'] if config['if_long_term_test'] and config['long_term_factor'] > 1 else self.config['pred_length'] + + os.makedirs(self.store_output_path, exist_ok=True) + self.setup_store_preds() + print(f"Storing output at {store_output_path}: ", num_sequences, 'segments') + + @property + def future_shape(self): + return (self.pred_length, self.config['num_joints'], 3) + @property + def past_shape(self): + return (self.config['obs_length'], self.config['num_joints'], 3) + + def _setup_store_preds(self): + store_output_path = os.path.join(self.store_output_path, 'output.zarr') + chunk_size = 10000/self.num_samples + self.output_poses = zarr.open(store_output_path, mode='w', shape=(0, self.num_samples, *self.future_shape), + chunks=(chunk_size, self.num_samples, *self.future_shape), dtype=np.float32) + + def _setup_store_gt(self): + self.gt_poses = zarr.open(os.path.join(self.store_output_path, 'gt.zarr'), mode='w', shape=(0, *self.future_shape), + chunks=(1000, *self.future_shape), dtype=np.float32) + self.obs_poses = zarr.open(os.path.join(self.store_output_path, 'obs.zarr'), mode='w', shape=(0, *self.past_shape), + chunks=(1000, *self.past_shape), dtype=np.float32) + + def setup_store_preds(self): + if self.if_gt: + self._setup_store_gt() + else: + self._setup_store_preds() + self.output_metadata = {'unique_id': [], 'metadata':[]} + + def store_batch(self, output, extra, dataset): + if self.if_gt: + gt, obs = output + self.gt_poses.append(dataset.skeleton.if_add_zero_pad_center_hip(gt).cpu().numpy(), axis=0) + self.obs_poses.append(dataset.skeleton.if_add_zero_pad_center_hip(obs).cpu().numpy(), axis=0) + else: + self.output_poses.append(dataset.skeleton.if_add_zero_pad_center_hip(output).cpu().numpy(), axis=0) + self.output_metadata['unique_id'].extend(dataset.unique_sample_string(extra)) + self.output_metadata['metadata'].extend(extra['metadata'][dataset.metadata_class_idx]) + + def finalize_store(self): + with open(os.path.join(self.store_output_path, 'metadata.yaml'), 'w') as outfile: + yaml.dump(self.output_metadata, outfile, default_flow_style=False) \ No newline at end of file diff --git a/SkeletonDiffusion/src/utils/tensorboard.py b/SkeletonDiffusion/src/utils/tensorboard.py new file mode 100644 index 0000000000000000000000000000000000000000..2a3f6c8209ac79d4771ff45819ea212cec4f5c71 --- /dev/null +++ b/SkeletonDiffusion/src/utils/tensorboard.py @@ -0,0 +1,138 @@ +from datetime import datetime +import socket + +import torch +from ignite.contrib.handlers.tensorboard_logger import TensorboardLogger, WeightsScalarHandler, WeightsHistHandler, GradsHistHandler, GradsScalarHandler +from ignite.engine import Engine, Events +from torch.optim import Optimizer + +def get_tensorb_style_filename(): + now = datetime.now() + month = now.strftime("%B") + dt_string = now.strftime("%d_%H-%M-%S") + name = month[:3] + dt_string + f"_{socket.gethostname().split('.')[0]}" + return name + +def setup_tb_logging_valid(tb_logger: TensorboardLogger, trainer: Engine, evaluator: Engine, evaluator_train: Engine, + loss_names=["Loss"], metric_names=[ "ADE", "FDE", "MPJPE_AVG", "MPJPE"]): + tb_custom_scalar_layout = {} + # We setup `global_step_transform=global_step_from_engine(trainer)` to take the epoch of the + # `trainer` instead of `evaluator`. + tb_logger.attach_output_handler( + evaluator_train, + event_name=Events.COMPLETED, + **{'tag': "losses/train", + 'metric_names': loss_names, + 'global_step_transform': lambda engine, event_name: trainer.state.epoch + } + ) + tb_logger.attach_output_handler( + evaluator, + event_name=Events.COMPLETED, + **{'tag': "losses/validation", + 'metric_names': loss_names, + 'global_step_transform': lambda engine, event_name: trainer.state.epoch + } + ) + + tb_logger.attach_output_handler( + evaluator, + event_name=Events.COMPLETED, + **{'tag': "validation", + 'metric_names': loss_names + metric_names, + 'global_step_transform': lambda engine, event_name: trainer.state.epoch + } + ) + + tb_logger.attach_output_handler( + evaluator_train, + event_name=Events.COMPLETED, + **{'tag': "validation_train", + 'metric_names': loss_names + metric_names, + 'global_step_transform': lambda engine, event_name: trainer.state.epoch + } + ) + + tb_custom_scalar_layout = { + **tb_custom_scalar_layout, + **{ + 'Validation Metrics': { + 'MPJPE_T': ['Multiline', [rf"validation_train/MPJPE_T/.*"]], + } + } + } + tb_logger.writer.add_custom_scalars(tb_custom_scalar_layout) + + +# def setup_logging(tb_logger: TensorboardLogger, trainer: Engine, evaluator: Engine, evaluator_train, optimizer: Optimizer, +# model: torch.nn.Module, if_run_validation=True, loss_names=["Loss"], metric_names=[ "ADE", "FDE", "MPJPE_AVG", "MPJPE"], +# train_out_transform=lambda out: {"loss": out[0], "pred horiz": out[-1]}, **kwargs): +# set_default_tb_train_logging(tb_logger, trainer, optimizer, model, funct=train_out_transform) + + + +def setup_tb_logging_train(tb_logger: TensorboardLogger, trainer: Engine, optimizer: Optimizer, + model: torch.nn.Module, train_out_transform: callable): + """ + Logs standard information to tensorboard during training. + """ + # Attach the logger to the trainer to log training loss at each iteration + + tb_logger.attach_output_handler( + trainer, + event_name=Events.ITERATION_COMPLETED, + **{ + 'tag': 'training', + 'output_transform': train_out_transform, + } + ) + + # Attach the logger to the trainer to log optimizer's parameters, e.g. learning rate at each iteration + tb_logger.attach_opt_params_handler( + trainer, + event_name=Events.ITERATION_COMPLETED, + **{ + 'optimizer': optimizer, + 'param_name': 'lr', + 'tag': 'training' + } + ) + + # Attach the logger to the trainer to log optimizer's parameters, e.g. learning rate at each iteration + tb_logger.attach_opt_params_handler( + trainer, + event_name=Events.EPOCH_STARTED, + **{ + 'optimizer': optimizer, + 'param_name': 'lr', + 'tag': 'losses' + } + ) + + # Attach the logger to the trainer to log model's weights norm after each iteration + tb_logger.attach( + trainer, + event_name=Events.ITERATION_COMPLETED(every=100), + log_handler=WeightsScalarHandler(model) + ) + + # Attach the logger to the trainer to log model's weights as a histogram after each epoch + tb_logger.attach( + trainer, + event_name=Events.EPOCH_COMPLETED, + log_handler=WeightsHistHandler(model) + ) + + # Attach the logger to the trainer to log model's gradients norm after each iteration + tb_logger.attach( + trainer, + event_name=Events.ITERATION_COMPLETED(every=100), + log_handler=GradsScalarHandler(model) + ) + + # Attach the logger to the trainer to log model's gradients as a histogram after each epoch + tb_logger.attach( + trainer, + event_name=Events.EPOCH_COMPLETED, + log_handler=GradsHistHandler(model) + ) diff --git a/SkeletonDiffusion/src/utils/time.py b/SkeletonDiffusion/src/utils/time.py new file mode 100644 index 0000000000000000000000000000000000000000..57959b42c0f80d958865d89a60ae47013a5c1c74 --- /dev/null +++ b/SkeletonDiffusion/src/utils/time.py @@ -0,0 +1,35 @@ +import numpy as np +from datetime import datetime +from datetime import timedelta + +class AverageTimer: + def __init__(self): + self.timings = [] + + def start(self): + self.t0 = datetime.now() + + def end(self, engine=None): + self.t = datetime.now() - self.t0 + self.timings.append(self.t) + if engine is not None and engine.state.iteration % 10 == 0: + print( + f"Iteration {engine.state.iteration}, time per batch: {self.t}, average time per batch in milliseconds: {np.mean(np.array(self.timings)/timedelta(milliseconds=1))}" + ) + def print_avg(self): + print(f"Average time per batch in milliseconds: {np.mean(np.array([t/timedelta(milliseconds=1) for t in self.timings]))}") + +class TrainingTimer: + def __init__(self): + self.timings = [] + + def start(self): + self.t0 = datetime.now() + + def end(self): + self.t = datetime.now() - self.t0 + self.timings.append(self.t) + + def print_avg(self): + print(f"Average time per epoch in seconds: {np.mean(np.array([t/timedelta(seconds=1) for t in self.timings]))}") + \ No newline at end of file diff --git a/SkeletonDiffusion_demo/.gitignore b/SkeletonDiffusion_demo/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c5e0304bfc401c67d094f4ecff7cb279cacc0e22 --- /dev/null +++ b/SkeletonDiffusion_demo/.gitignore @@ -0,0 +1,173 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# UV +# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +#uv.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# PyPI configuration file +.pypirc + +test/ \ No newline at end of file diff --git a/SkeletonDiffusion_demo/README.md b/SkeletonDiffusion_demo/README.md new file mode 100644 index 0000000000000000000000000000000000000000..729c11d045c51f266db81426ce29a091eb6277d8 --- /dev/null +++ b/SkeletonDiffusion_demo/README.md @@ -0,0 +1,52 @@ +# Generate gifs from sequences of obj files +## Environment +Sorry, there is no environment file (the env I am currently using contains packages that are not necessary here). Here the version of a few necessary modules. You will have to install other modules as warning appears once you try running the code. +``` +vedo 2024.5.1 +vpython 7.6.5 +python 3.10.13 +``` + +## Run the code +### Prepare the data +Copy the directory '/usr/wiss/curreli/work/my_modules/Skeleton2Mesh/final_output/hmp/visuals_50samples/amass/SkeletonDiffusion/test' to this folder (I already gave you the rights - afterwards I will delete it). There are meshes for two test segments from AMASS, 9622_GRAB and 11949_HUMAN4D. The predictions are named according to the following convention: + - obs: Past obervation (input sequence) + - gt: GT future + - pred_closest_GT: prediction that is most similar to the GT + - most_far_: the remaining predictions are sorted accordng to their similarity to the GT future, or better to the similarity to the prediction closest to the GT. So most_far_0 is the prediction most diverse from the GT + +In the demo we will not have a GT future. We will order the predictions according to a different criterion (maybe diversity). + +### Generate visuals +Now you can run +``` +python plot_several_meshes.py --mesh_parent_folder= +``` +The output should be in a parallel direction at lowest folder level. + ## If you are using a ssh connection + You probably have no screen, so the code terminates. You can avoid the problem by generating a screen first with our script setup_headless.bash: + ``` + setup_headless.bash python plot_several_meshes.py <...> + ``` + ### Debug via ssh connection + OPen the file of your VS Studio debug configurations, launch.json, and add this new configuration: + +``` + { "name": "Python: Attach to Edge", + "request": "attach", "type": "python", + "connect": { "host": "localhost", "port": 5678 }, + "justMyCode": true, + }, +``` +Now start the file in debugger mode with debugpy +``` +./setup_headless.bash python -m debugpy --listen 5678 --wait-for-client plot_several_meshes.py + ``` + +Now start your debug configuraiton ""Python: Attach to Edge" to attach your debugger and start debugging. + +## For the future +If you need to put more functions together consider using shell cripts +``` +bash create_mesh_gifs.sh +``` \ No newline at end of file diff --git a/SkeletonDiffusion_demo/combine_video.py b/SkeletonDiffusion_demo/combine_video.py new file mode 100644 index 0000000000000000000000000000000000000000..5792aedce1e7e1f2e02576abfc23060bd98d9c84 --- /dev/null +++ b/SkeletonDiffusion_demo/combine_video.py @@ -0,0 +1,168 @@ +import tempfile +import os +import cv2 +import numpy as np +import imageio +import torch +import torchvision.io as io +from torchvision.transforms import functional as F +from PIL import Image, ImageDraw, ImageFont +import torch.nn.functional as nnf + +def convert_to_rgb(frame): + """Convert frame to RGB format.""" + if frame.shape[2] == 4: # RGBA + # Convert RGBA to RGB using alpha compositing with white background + alpha = frame[:, :, 3:4] / 255.0 + rgb = frame[:, :, :3] + return (rgb * alpha + (1 - alpha) * 255).astype(np.uint8) + return frame + +def process_frames_batch(frames, target_size, device): + """Process a batch of frames efficiently.""" + # Stack frames and move to GPU + frames = torch.stack(frames).to(device) + # Batch resize + frames = nnf.interpolate(frames, size=target_size, + mode='bilinear', align_corners=False) + return frames + +def combine_video(obj_dir, output_path, input_frames=None, displayed_preds=3): + """Combine multiple GIFs into a grid layout using torchvision.""" + print("Starting video combination process...") + + # Set device for GPU acceleration + device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + print(f"Using device: {device}") + + # Get all GIF files from shadow_gif directory + shadow_gif_dir = os.path.join(obj_dir, 'shadow_gif') + gif_files = [f for f in os.listdir(shadow_gif_dir) if f.endswith('_tranp.gif') and not f.startswith('obs')] + gif_files = sorted(gif_files) + + # Limit number of GIFs based on displayed_preds + gif_files = gif_files[:displayed_preds] + print(f"Using {len(gif_files)} GIFs for {displayed_preds} predictions") + + # Calculate grid dimensions + grid_cols = min(displayed_preds, 3) # Maximum 3 columns + grid_rows = (displayed_preds + grid_cols - 1) // grid_cols + print(f"Grid layout: {grid_rows}x{grid_cols}") + + # Load and process all GIFs + gif_frames = [] + durations = [] + for gif_file in gif_files: + gif_path = os.path.join(shadow_gif_dir, gif_file) + print(f"Loading {gif_file}...") + # Read GIF frames efficiently + with imageio.get_reader(gif_path) as reader: + frames = [] + for frame in reader: + # Convert to RGB if needed + frame = convert_to_rgb(frame) + frame = cv2.resize(frame, (frame.shape[1] // 4, frame.shape[0] // 4), interpolation=cv2.INTER_AREA) + # Convert to tensor and normalize + frame = torch.from_numpy(frame).permute(2, 0, 1).float().to(device) / 255.0 + frames.append(frame) + + # Get duration from the first frame + with Image.open(gif_path) as img: + duration = img.info.get('duration', 100) / 1000.0 # Convert to seconds + + gif_frames.append(frames) + durations.append(duration) + + if not gif_frames: + raise ValueError("No GIF files found!") + + # Get common duration + common_duration = min(durations) + print(f"Common duration: {common_duration}") + + # Process input frames if provided + if input_frames is not None: + # Convert BGR to RGB and resize input frames + input_frames = [cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) for frame in input_frames] + input_frames = [cv2.resize(frame, (frame.shape[1]//8, frame.shape[0]//8), + interpolation=cv2.INTER_NEAREST) for frame in input_frames] + input_frames = [torch.from_numpy(frame).permute(2, 0, 1).float().to(device) / 255.0 + for frame in input_frames] + + # Calculate target size for each GIF in the grid + first_frame = gif_frames[0][0] + target_height = first_frame.shape[1] + target_width = first_frame.shape[2] + + # Create grid frames + num_frames = max(len(frames) for frames in gif_frames) + grid_frames = [] + + # Process frames in batches + batch_size = 4 # Adjust based on GPU memory + for frame_idx in range(0, num_frames, batch_size): + batch_end = min(frame_idx + batch_size, num_frames) + + # Create empty grid for the batch + grid = torch.ones((batch_end - frame_idx, 3, target_height * grid_rows, target_width * grid_cols), + device=device) + + # Process each GIF in the batch + for i, frames in enumerate(gif_frames): + row = i // grid_cols + col = i % grid_cols + + # Get frames for this batch + batch_frames = frames[frame_idx:batch_end] + if batch_frames: + # Process frames in batch + resized_frames = process_frames_batch(batch_frames, (target_height, target_width), device) + + # Add to grid + for j, frame in enumerate(resized_frames): + grid[j, :, row*target_height:(row+1)*target_height, + col*target_width:(col+1)*target_width] = frame + + # Add input frames if provided + if input_frames is not None: + for i in range(len(gif_frames)): + row = i // grid_cols + col = i % grid_cols + + # Get input frames for this batch + batch_input_frames = input_frames[frame_idx:batch_end] + if batch_input_frames: + orig_h, orig_w = batch_input_frames[0].shape[1:3] # (C, H, W) + pip_max_width = target_width // 2 + pip_max_height = target_height // 2 + aspect = orig_w / orig_h + if pip_max_width / aspect <= pip_max_height: + pip_w = pip_max_width + pip_h = int(pip_max_width / aspect) + else: + pip_h = pip_max_height + pip_w = int(pip_max_height * aspect) + # resize + resized_input_frames = process_frames_batch(batch_input_frames, (pip_h, pip_w), device) + # Add to grid + for j, frame in enumerate(resized_input_frames): + x_pos = col * target_width + target_width - frame.shape[2] - 10 + y_pos = row * target_height + 10 + grid[j, :, y_pos:y_pos+frame.shape[1], x_pos:x_pos+frame.shape[2]] = frame + + # Add batch to grid_frames + grid_frames.extend([frame for frame in grid]) + + # Convert frames to numpy and save as GIF + print(f"Saving to {output_path}") + frames_np = [(frame.cpu().permute(1, 2, 0).numpy() * 255).astype(np.uint8) + for frame in grid_frames] + + # Save as GIF with optimization + imageio.mimsave(output_path, frames_np, fps=30, optimize=True, quantizer=0, loop=0) + + print("Video combination completed!") + return output_path + +if __name__ == "__main__": + combine_video("./9622_GRAB/", tempfile.NamedTemporaryFile(suffix=".gif", delete=False).name) diff --git a/SkeletonDiffusion_demo/create_mesh_gifs.sh b/SkeletonDiffusion_demo/create_mesh_gifs.sh new file mode 100644 index 0000000000000000000000000000000000000000..643c2b4fc0887be1530a2e63dc3f0b2c9ce15168 --- /dev/null +++ b/SkeletonDiffusion_demo/create_mesh_gifs.sh @@ -0,0 +1,3 @@ +export IMAGEMAGICK_BINARY=/home/stud/yaji/storage/user/yaji/SkeletonDiffusion_Demo/magick + +python plot_several_meshes.py -f \ No newline at end of file diff --git a/SkeletonDiffusion_demo/plot_several_meshes.py b/SkeletonDiffusion_demo/plot_several_meshes.py new file mode 100644 index 0000000000000000000000000000000000000000..300ea4dc0bd103d2fea60c6ec9bd772ec1f2469c --- /dev/null +++ b/SkeletonDiffusion_demo/plot_several_meshes.py @@ -0,0 +1,325 @@ +import numpy as np +import cv2 +from vedo import Mesh, Plane, Plotter, screenshot +import imageio.v2 as imageio +# import imageio as imageio +import re +import os +from .visual import get_ptc # probaly vpython +from PIL import Image +from tqdm import tqdm + +screenshot_scale = 3 + +PLAY_OBS_BEFORE_PRED = True +obs_dir = "" +cam = dict( + position=(-3.85922, -4.78140, 2.689328), + focal_point=(0.192544, 4.77379e-3, 0.0127248), + viewup=(0.0724348, 0.109097, 0.991388), + distance=5.25119, + clipping_range=(4.38228, 6.36775), + ) + +_green= [0.4, 0.7, 0.5] +_blue =[0.7, 0.9, 1.0] +_dark_blue =[0.03, 0.4, 0.7] +_orange = [0.9, 0.7, 0.2] + +def get_mesh(mesh_name, color='darksalmon', mesh_opacity=1.0, mesh_lighting='default', rotation=[0, 0, 0], offset=[0, 0, 0], scale=0): + offset = np.array(offset) + #styles = ['default', 'metallic', 'plastic', 'shiny', 'glossy', 'ambient', 'off'] + mesh = Mesh(mesh_name, c=color, alpha=mesh_opacity).lighting(mesh_lighting) + if scale == 0: + bnd = np.array(mesh.bounds()) + scale = 1 / max(bnd[1]-bnd[0], bnd[3]-bnd[2], bnd[5]-bnd[4]) + mesh.scale(scale) + mesh.pos(offset) + mesh.rotate_x(rotation[0]) + mesh.rotate_y(rotation[1]) + mesh.rotate_z(rotation[2]) + # mesh.phong() + # mesh2.phong() + return mesh, scale + +def save_png_rm_bg(filename, im, bg_color_min=[0, 255, 100], bg_color_max=None, rgb=False): + # https://stackoverflow.com/questions/72062001/remove-everything-of-a-specific-color-with-a-color-variation-tolerance-from-an + # for transperancy: + # https://stackoverflow.com/questions/55582117/efficiently-converting-color-to-transparency-in-python + + if bg_color_max is None: + bg_color_max = bg_color_min + # bg_color_min = [bg_color_min[2], bg_color_min[1], bg_color_min[0]] + # bg_color_max = [bg_color_max[2], bg_color_max[1], bg_color_max[0]] + # Load image + # im = cv2.imread('test.png') + + # Define lower and upper limits of our blue + min = np.array(bg_color_min, np.uint8) + max = np.array(bg_color_max, np.uint8) + + # Go to HSV colourspace and get mask of blue pixels + # HSV = cv2.cvtColor(im, cv2.COLOR_BGR2HSV) + mask = cv2.inRange(im, min, max) + # Try dilating (enlarging) mask with 3x3 structuring element + # SE = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)) + # mask = cv2.dilate(mask, kernel, iterations=1) + + # create alpha channel + alpha = (im[:, :, 0] * 0 + 255) + + # Make all pixels in mask white + alpha[mask > 0] = 0 + + # add alpha channel + if rgb: + im = cv2.merge((im[:, :, 0], im[:, :, 1], im[:, :, 2], alpha)) + else: + im = cv2.merge((im[:, :, 2], im[:, :, 1], im[:, :, 0], alpha)) + + # crop to visible part + mask = im[:, :, 3] != 0. + coords = np.argwhere(mask) + y0, x0 = coords.min(axis=0) + y1, x1 = coords.max(axis=0) + 1 + # im = im[y0:y1, x0:x1, :] + + # write to file + cv2.imwrite(filename, im) + +def save_plot_as_transparent_png(plt, out_filename): + # if not out_filename is None: + bg_col = [255, 255, 255] + plt.background(c1=bg_col) + save_png_rm_bg(out_filename, plt.screenshot(asarray=True), bg_color_min=bg_col) + + +def get_mesh_shadow(mesh, offset=[0, 0, 0], plane_normal=(0, 0, 1), direction=[0.1, -1.8, 3]): + shadow = [] + shad_col = np.array([0.8, 0.8, 0.8]) + min_z = mesh.vertices.min(axis=0)[2] + # mesh.add_shadow(plane='z', point=min_z, alpha=1, c=shad_col, culling=0.9,) + plane = Plane(pos=np.array([0, 0, min_z]) + np.array(offset), normal=plane_normal, s=[7, 7]).alpha(0.2) + shad = mesh.clone().project_on_plane(plane, direction=-np.array(direction) + np.array(offset)) + shad.c(shad_col).alpha(1).lighting("off").use_bounds(False) + shadow = shad + return shadow + +def plot_meshes(mesh_files, cam, mesh_color=[1, 1, 1], rotation=[0, 0, 0]): + + mesh_opacity = 0.8 + plot_shadows = True + + pass + +def create_visual(mesh_files, color='coral', dest_name="", x=0,y=0,z=0, type='mesh', mesh_lighting='plastic', obs_dir=""): + meshes, scales =[], [] + bg_col = [255, 255, 255]# plotter = Plotter(offscreen=True) + plotter = Plotter(bg=[255, 255, 255], offscreen=True) + + frame_files = [] + # lights = get_lights() + for file in tqdm(mesh_files): + mesh, scale = get_mesh(file, color=color, rotation=[x,y,z], mesh_lighting=mesh_lighting, scale=0.6) + # scalars = 1- mesh.vertices[:, 2] + # mesh.cmap('Oranges', scalars) + + plotter.clear() + + shadow = get_mesh_shadow(mesh) + + # plotter.add([mesh, shadow]) + # plotter.show(mesh, __doc__, interactive=False, camera=cam, resetcam=True, zoom=2) + plotter.show(mesh, shadow, __doc__, interactive=False, camera=cam, resetcam=True, zoom=2) + frame_path =file[:-4] + ".png" + frame_files.append(frame_path) + screenshot(frame_path, scale=1) + save_png_rm_bg(file[:-4]+"new.png", plotter.screenshot(asarray=True), bg_color_min=bg_col) + + # Compile saved frames into a GIF + filename = os.path.join(dest_name + '.gif') + create_transparent_gif(frame_files, dest_name, obs_dir) + # with imageio.get_writer(filename, mode='I', duration=2) as writer: #duration=0.2) as writer: + # for filename in frame_files: + # image = imageio.imread(filename) + # writer.append_data(image) + + +def create_transparent_gif(frame_files, dest_name, obs_dir): + images = [] + if "obs" not in dest_name and PLAY_OBS_BEFORE_PRED: + # visit all file under obs_dir that end with new.png + obs_files = [os.path.join(obs_dir, f) for f in os.listdir(obs_dir) if f.endswith('new.png')] + # sort the files + obs_files = sort_list(obs_files) + for i, frame in enumerate(obs_files): + im = Image.open(frame) + images.append(im) + + # Optimize: Load all frames at once and process them in batch + frame_files = [f.replace('.png', 'new.png') for f in frame_files] + frame_files = sort_list(frame_files) + + # Use a more efficient way to load and process images + for frame in frame_files: + im = Image.open(frame) + images.append(im) + + # Save with optimized settings + images[0].save( + os.path.join(dest_name + '_tranp.gif'), + format="GIF", + save_all=True, + loop=1, + append_images=images[1:], # Skip first image as it's already saved + duration=0.033, # Reduced from 0.016 to 0.033 (30fps) + disposal=2, + optimize=True, # Enable optimization + quality=85, # Reduced quality for better performance + colors=64 # Reduce color palette + ) + + # Clean up + for im in images: + im.close() + +def sort_list(l): + try: + return list(sorted(l, key=lambda x: int(re.search(r'\d+(?=\.)', x).group()))) + except AttributeError: + return sorted(l) + + +def visual_gt(mesh_files, color, x,y,z, type='mesh'): + bg_col = [255, 255, 255]# plotter = Plotter(offscreen=True) + plotter = Plotter(bg=[255, 255, 255], offscreen=True) + + frame_files = [] + # lights = get_lights() + for file in mesh_files: + + if type == 'mesh': + mesh, scale = get_mesh(file, color=color, rotation=[x,y,z], mesh_lighting='plastic') + # scalars = 1- mesh.vertices[:, 2] + # mesh.cmap('Blues', scalars) + else: + mesh, scale = get_ptc(file, rotation=[x,y,z]) + mesh.c([0.5,0.5,0.5]) + + plotter.clear() + + shadow = get_mesh_shadow(mesh) + + # plotter.add([mesh, shadow]) + plotter.show(mesh, shadow, __doc__, interactive=False, camera=cam, resetcam=True, zoom=2) + frame_path =file[:-4] + ".png" + frame_files.append(frame_path) + screenshot(frame_path, scale=1) + save_png_rm_bg(file[:-4]+"new.png", plotter.screenshot(asarray=True), bg_color_min=bg_col) + + +def plot_two_mesh(meshfile1, meshfile2, color, x,y,z): + plotter = Plotter(bg=[255, 255, 255], offscreen=True) + mesh1, scale = get_ptc(meshfile1, rotation=[x,y,z]) + mesh1.alpha(1.0).c([0.5,0.5,0.5]) + # scalars = 1- mesh1.vertices[:, 2] + # mesh1.cmap('Oranges', scalars) + # mesh1.c(_dark_blue) + mesh2, scale = get_mesh(meshfile2, color=color, rotation=[x,y,z], mesh_lighting='plastic') + + shadow = get_mesh_shadow(mesh2) + plotter.show(mesh1, mesh2, shadow, __doc__, interactive=False, camera=cam, resetcam=True, zoom=2) + frame_path =meshfile2[:-4] + ".png" + + screenshot(frame_path, scale=1) + save_png_rm_bg(meshfile2[:-4]+"both.png", plotter.screenshot(asarray=True), bg_color_min=[255, 255, 255]) + +import argparse + + + + +def main(parent_folder, displayed_preds=3): + file_type = '.obj' #'mesh.ply' + x,y,z = 0, 0, -90 # Changed from 0,0,0 to rotate around x-axis + dest_dir = os.path.join(os.path.dirname(parent_folder), 'shadow_gif') + obs_dir = os.path.join(os.path.dirname(parent_folder), 'obs_obj') + os.makedirs(dest_dir, exist_ok=True) + + # Check if we already have enough GIFs + existing_gifs = [f for f in os.listdir(dest_dir) if f.endswith('_tranp.gif') and not f.startswith('obs')] + if len(existing_gifs) >= displayed_preds: + print(f"Found {len(existing_gifs)} existing GIFs, which is enough for {displayed_preds} predictions") + return + + print(f"Found {len(existing_gifs)} existing GIFs, need {displayed_preds}, proceeding with generation") + + # If no existing GIFs, proceed with generation + subfolders = sorted([f for f in os.listdir(parent_folder) if os.path.isdir(os.path.join(parent_folder, f)) and 'obj' in f]) + for f in subfolders: + folder = os.path.join(parent_folder, f) + dest_name = os.path.join(dest_dir, f) + + mesh_files = [os.path.join(folder, f) for f in os.listdir(folder) if f.endswith(file_type)] + mesh_files = sort_list(mesh_files) + os.makedirs(dest_dir, exist_ok=True) + + #color "lightblue" "navajowhite" + if 'obs' in f: + create_visual(mesh_files, _green, dest_name, x,y,z, type='mesh', mesh_lighting='plastic', obs_dir=obs_dir) + else: + create_visual(mesh_files, _dark_blue, dest_name, x,y,z, type='mesh', mesh_lighting='plastic', obs_dir=obs_dir) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + #conda activate hmp_visualize + parser.add_argument('-f', '--mesh_parent_folder', type=str, default="final_output/hmp/visuals/amass/SkeletonDiffusion/test/952_WalkTogether/obj") + + args = parser.parse_args() + main(args.mesh_parent_folder) + + #################################################################################################################################### + # Old code snippet, kept just for reference. Jialin here there may be somehting you will need, or maybe not :) If you do not need you can delete + #################################################################################################################################### + + # other functions not needed, from older code + # visual_gt(gt_mesh_files, 0,0,-90, type='mesh') # this line was commented out by Lu + # visual_gt(gt_obj_files, 'salmon', x,y,z)#--> .png and new.png (transparent) per frame + # gt_ptc_files = [os.path.join(folder, prefix +'gt_pointcloud_x.ply'),os.path.join(folder, prefix +'gt_pointcloud_y.ply')] + # gt_obj_files = sort_list([os.path.join(target_folder, f) for f in os.listdir(target_folder) if f.endswith(file_type)]) + # plot_two_mesh(gt_ptc_files[1], mesh_files[-1], "lightblue", x,y,z) + + # older code + # final_folder + # gif_folder + # filename = os.path.join(dest_name + '.gif') + # frame_files = [os.path.join(gif_folder, f"pred{i}.gif") for i in range(10)] + # obs_image = imageio.imread(os.path.join(gif_folder, f"obs_salmon.png")) + # for i,filename in enumerate(frame_files): + # image = imageio.imread(filename) + # frames = np.vstack([obs_image, image]) + # imageio.imwrite(os.path.join(final_folder, f"pred{i}.gif"), frames, fps=50) + + # image = imageio.imread(os.path.join(gif_folder, f"gt_salmon.gif")) + # frames = np.vstack([obs_image, image]) + # imageio.imwrite(os.path.join(final_folder, f"gt.gif"), frames, fps=50) + + + + # gifs= [imageio.imread(os.path.join(final_folder, f"pred{i}.gif")) for i in range(10)] + # #Create writer object + # new_gif = imageio.get_writer(os.path.join(final_folder, f"output.gif")) + + # for frame_number in range(len(gifs[0])): + # img1 = gif1.get_next_data() + # img2 = gif2.get_next_data() + # #here is the magic + # upper_row = np.hstack((gifs[:5, frame_number])) + # lower_row = np.hstack((gifs[5:, frame_number])) + # new_image = np.vstack((upper_row, lower_row)) + # new_gif.append_data(new_image) + + + print("done.") + diff --git a/SkeletonDiffusion_demo/setup_headless.bash b/SkeletonDiffusion_demo/setup_headless.bash new file mode 100644 index 0000000000000000000000000000000000000000..bee563caef4f61a1d8e32d6e593812fb31958c60 --- /dev/null +++ b/SkeletonDiffusion_demo/setup_headless.bash @@ -0,0 +1,8 @@ +#!/bin/bash +set -x +export DISPLAY=:99.0 +which Xvfb +Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & +# sleep 3 +set +x +exec "$@" \ No newline at end of file diff --git a/SkeletonDiffusion_demo/visual.py b/SkeletonDiffusion_demo/visual.py new file mode 100644 index 0000000000000000000000000000000000000000..8ab3b7d1331e1fc3dfe32f09cf10ad2f740cc5b1 --- /dev/null +++ b/SkeletonDiffusion_demo/visual.py @@ -0,0 +1,322 @@ +from vedo import Mesh, Points, Plotter, screenshot, Arrow, Light, Plane +import imageio +import os +import numpy as np +from scipy.interpolate import Rbf, NearestNDInterpolator as Near +import re + +screenshot_scale = 3 + +cam = dict( + position=(-3.85922, -4.78140, 0.689328), + focal_point=(0.192544, 4.77379e-3, 0.0127248), + viewup=(0.0724348, 0.109097, 0.991388), + distance=5.25119, + clipping_range=(4.38228, 6.36775), + ) + +_red = [0.9, 0.1, 0.1] +_green= [0.4, 1.0, 0.8] +_blue =[0.7, 0.9, 1.0] +_dark_blue =[0.03, 0.4, 0.7] + +def sort_list(l): + try: + return list(sorted(l, key=lambda x: int(re.search(r'\d+(?=\.)', x).group()))) + except AttributeError: + return sorted(l) + + +def get_lights(light_color=[255, 255, 245], offset=[0, 0, 0], intensity_mult=1): + # Add light sources at the given positions + # (grab the position and color of the arrow object) + orig = np.array([0, 0, 0]) + np.array(offset) + phl = Arrow(np.array([0.1, 0.1, 10]) + offset, orig, c=light_color).scale(0.2) + pfl = Arrow(np.array([1.5, 0.1, 0.3]) + offset, orig, c=light_color).scale(0.2) + pbl = Arrow(np.array([-1.5, 0.1, 0.3]) + offset, orig, c=light_color).scale(0.2) + prl = Arrow(np.array([0.1, -1.5, 0.3]) + offset, orig, c=light_color).scale(0.2) + pll = Arrow(np.array([0.1, 1.5, 0.3]) + offset, orig, c=light_color).scale(0.2) + hl = Light(phl, intensity=0.7 * intensity_mult, angle=180, ) + rl = Light(pfl, intensity=0.6 * intensity_mult, angle=180, ) + ll = Light(pbl, intensity=0.6 * intensity_mult, angle=180, ) + bl = Light(pll, intensity=0.6 * intensity_mult, angle=180, ) + fl = Light(prl, intensity=1 * intensity_mult, angle=180, ) + lights = [hl, fl, bl, ll, rl] + return lights + +def get_mesh(mesh_name, mesh_opacity=1.0, mesh_lighting='default', rotation=[0, 0, 0], offset=[0, 0, 0], scale=0): + offset = np.array(offset) + #styles = ['default', 'metallic', 'plastic', 'shiny', 'glossy', 'ambient', 'off'] + mesh = Mesh(mesh_name, c=_blue, alpha=mesh_opacity).lighting(mesh_lighting) + if scale == 0: + bnd = np.array(mesh.bounds()) + scale = 1 / max(bnd[1]-bnd[0], bnd[3]-bnd[2], bnd[5]-bnd[4]) + mesh.scale(scale) + mesh.pos(offset) + mesh.rotate_x(rotation[0]) + mesh.rotate_y(rotation[1]) + mesh.rotate_z(rotation[2]) + # mesh.phong() + # mesh2.phong() + return mesh, scale + +def get_ptc(ptc_name, rotation=[0, 0, 0], offset=[0, 0, 0], scale=0, color=_dark_blue): + offset = np.array(offset) + #styles = ['default', 'metallic', 'plastic', 'shiny', 'glossy', 'ambient', 'off'] + mesh = Points(Mesh(ptc_name), r=1).c([0.5,0.5,0.5]).alpha(0.8) + if scale == 0: + bnd = np.array(mesh.bounds()) + scale = 1 / max(bnd[1]-bnd[0], bnd[3]-bnd[2], bnd[5]-bnd[4]) + mesh.scale(scale) + mesh.pos(offset) + mesh.rotate_x(rotation[0]) + mesh.rotate_y(rotation[1]) + mesh.rotate_z(rotation[2]) + # mesh.phong() + # mesh2.phong() + return mesh, scale + +def get_mesh_shadow(mesh, offset=[0, 0, 0], plane_normal=(0, 0, 1), direction=[0.1, -1.8, 3]): + shadow = [] + shad_col = np.array([0.8, 0.8, 0.8]) + min_z = mesh.points().min(axis=0)[2] + # mesh.add_shadow(plane='z', point=min_z, alpha=1, c=shad_col, culling=0.9,) + plane = Plane(pos=np.array([0, 0, min_z]) + np.array(offset), normal=plane_normal, s=[7, 7]).alpha(0.2) + shad = mesh.clone().project_on_plane(plane, direction=-np.array(direction) + np.array(offset)) + shad.c(shad_col).alpha(1).lighting("off").use_bounds(False) + shadow = shad + return shadow + + + + +def create_visual(mesh_files, directory, x,y,z, type='mesh'): + meshes, scales =[], [] + # plotter = Plotter(offscreen=True) + plotter = Plotter(bg=[255, 255, 255], offscreen=True) + + frame_files = [] + # lights = get_lights() + for file in mesh_files: + if type == 'mesh': + mesh, scale = get_mesh(file, rotation=[x,y,z], mesh_lighting='metallic') + else: + mesh, scale = get_ptc(file) + plotter.clear() + + shadow = get_mesh_shadow(mesh) + # plotter.add([mesh, shadow]) + plotter.show(mesh, shadow, __doc__, interactive=False, camera=cam, resetcam=True, zoom=2) + frame_path =file[:-4] + ".png" + frame_files.append(frame_path) + screenshot(frame_path, scale=1) + + # Compile saved frames into a GIF + filename = os.path.join(directory, type+'_animation.gif') + with imageio.get_writer(filename, mode='I', duration=0.2) as writer: + for filename in frame_files: + image = imageio.imread(filename) + writer.append_data(image) + + + +def create_mesh_animation(mesh_files, directory, x,y,z): + + # Load all meshes + meshes = [Mesh(f) for f in mesh_files] + + # Create a plotter + plotter = Plotter(bg=[255, 255, 255], offscreen=True) + # plotter = vedo.Plotter()# Use offscreen rendering to save frames + + frame_files = [] # To store the path of each frame image + + # plotter.camera.SetViewUp(0,0,1) + + + # shadow = mesh.clone().projectOnPlane(direction=(0,0,-1)) + + # Color the shadow mesh dark and make it slightly transparent + + for frame_id, mesh in enumerate(meshes): + mesh.rotate_x(x).rotate_y(y).rotate_z(z).lighting('metallic') + shadow = get_mesh_shadow(mesh) + scalars = 1- mesh.vertices[:, 2] + mesh.cmap('Blues', scalars) + # mesh.add_shadow('x', 0.95) + plotter.clear() + # plotter.add(mesh) + plotter.show(mesh, shadow, __doc__, interactive=False, camera=cam, resetcam=True, zoom=2) + frame_path = mesh_files[frame_id][:-4] + ".png" + frame_files.append(frame_path) + screenshot(frame_path, scale=1) # Save frame as image + + + #crop the images + # os.system("""convert -trim {0} "{1}" """.format(frame_path, frame_path)) + + + # Compile saved frames into a GIF + filename = os.path.join(directory, 'mesh_animation.gif') + with imageio.get_writer(filename, mode='I', duration=0.2) as writer: + for f in frame_files: + image = imageio.imread(f) + writer.append_data(image) + os.system("""convert -trim {0} "{1}" """.format(f, f)) + + + + + +def create_point_cloud_animation(files, directory, x,y,z): + # Load all meshes + meshes = [Points(Mesh(f), r=1) for f in files] + + # Create a plotter + plotter = Plotter(bg=[255, 255, 255], offscreen=True) + # plotter = vedo.Plotter()# Use offscreen rendering to save frames + + frame_files = [] # To store the path of each frame image + + # plotter.camera.SetViewUp(0,0,1) + + + # shadow = mesh.clone().projectOnPlane(direction=(0,0,-1)) + + # Color the shadow mesh dark and make it slightly transparent + + for frame_id, mesh in enumerate(meshes): + mesh.rotate_x(x).rotate_y(y).rotate_z(z).c([0.5,0.5,0.5]) + shadow = get_mesh_shadow(mesh) + # scalars = 1- mesh.vertices[:, 2] + # mesh.cmap('binary', scalars) + plotter.clear() + plotter.show(mesh, shadow, __doc__, interactive=False, camera=cam, resetcam=True, zoom=2) + + frame_path = files[frame_id][:-4] + ".png" + frame_files.append(frame_path) + screenshot(frame_path, scale=1) # Save frame as image + + + #crop the images + # os.system("""convert -trim {0} "{1}" """.format(frame_path, frame_path)) + + + # Compile saved frames into a GIF + filename = os.path.join(directory, 'pct_animation.gif') + with imageio.get_writer(filename, mode='I', duration=0.2) as writer: + for f in frame_files: + image = imageio.imread(f) + writer.append_data(image) + os.system("""convert -trim {0} "{1}" """.format(f, f)) + + + +def point_cloud_colormap(gt_ptc, ptc, corr_num): + + s1, _ = get_ptc(gt_ptc, color=_red) + s2, _ = get_ptc(ptc, color=_blue) + + landmarks1 = s1.vertices[:corr_num,:] + landmarks2 = s2.vertices[:corr_num,:] + + x, y, z = np.split(landmarks1, 3, axis=1) + desc = x**2 + y**2 + z**2 + + # itr = Rbf(x, y, z, desc) # Radial Basis Function interpolator + itr = Near(landmarks1, desc) # Nearest-neighbour interpolator + + # interpolate descriptor on the full set of mesh vertices + xi, yi, zi = np.split(s2.vertices, 3, axis=1) + interpolated_desc = itr(xi, yi, zi) + + s2.cmap('coolwarm', interpolated_desc.squeeze()).add_scalarbar(title='error') + # s2.point_colors(interpolated_desc, cmap='coolwarm', vmin=min(interpolated_desc), vmax=max(interpolated_desc)).addScalarBar(title='$\error$') + + plotter = Plotter() + + plotter.show(s2, __doc__, axes=True) + + +def mesh_colormap(gt_mesh, mesh, corr_num): + + s1, _ = get_ptc(gt_ptc, color=_red) + s2, _ = get_ptc(ptc, color=_blue) + + landmarks1 = s1.vertices[:corr_num,:] + landmarks2 = s2.vertices[:corr_num,:] + + x, y, z = np.split(landmarks1, 3, axis=1) + desc = x**2 + y**2 + z**2 + + # itr = Rbf(x, y, z, desc) # Radial Basis Function interpolator + itr = Near(landmarks1, desc) # Nearest-neighbour interpolator + + # interpolate descriptor on the full set of mesh vertices + xi, yi, zi = np.split(s2.vertices, 3, axis=1) + interpolated_desc = itr(xi, yi, zi) + + s2.cmap('coolwarm', interpolated_desc.squeeze()).add_scalarbar(title='error') + # s2.point_colors(interpolated_desc, cmap='coolwarm', vmin=min(interpolated_desc), vmax=max(interpolated_desc)).addScalarBar(title='$\error$') + + plotter = Plotter() + + plotter.show(s2, __doc__, axes=True) + + +def plot_two_mesh(meshfile1, meshfile2, x,y,z): + plotter = Plotter(bg=[255, 255, 255], offscreen=True) + mesh1, scale = get_ptc(meshfile1, rotation=[x,y,z]) + mesh1.alpha(1.0).c([0.2,0.2,0.2]) + # scalars = 1- mesh1.vertices[:, 2] + # mesh1.cmap('Oranges', scalars) + # mesh1.c(_dark_blue) + mesh2, scale = get_mesh(meshfile2, rotation=[x,y,z], mesh_lighting='shiny') + scalars = 1- mesh2.vertices[:, 2] + mesh2.cmap('Blues', scalars) + plotter.show(mesh1, mesh2, __doc__, interactive=False, camera=cam, resetcam=True, zoom=2) + frame_path =meshfile2[:-4] + ".png" + + screenshot(frame_path, scale=1) + os.system("""convert -trim {0} "{1}" """.format(frame_path, frame_path)) + + +if __name__ == "__main__": + + folder = '/home/wiss/sang/git/implicit_neuro_morph/jax_implicit_neuro_morph/exp/smal/2024_04_18_15_11_59/reconstructions' + prefix = 'shape_0_to_4000_' + + # filenames = [os.path.join(folder, prefix + str(i) + '_mesh.ply') for i in range(0,11)] + # create_mesh_animation(filenames, folder, -45, -45, 90) + + + # filenames = [os.path.join(folder, prefix + str(i) + '_ptc.ply') for i in range(0,11)] + + # gt_ptc = os.path.join(folder, prefix + 'gt_pointcloud_y.ply') + # ptc = os.path.join(folder, prefix + 'epoch_10000_time_10_ptc.ply') + + # create_point_cloud_animation(filenames, folder, -45, -45, 90) + + folder = '/home/wiss/sang/git/implicit_neuro_morph/jax_implicit_neuro_morph/exp/smal/2024_04_18_15_11_59/eval' + # mesh_files = [os.path.join(folder, f) for f in os.listdir(folder) if f.endswith('mesh.ply')] + # mesh_files = sort_list(mesh_files) + + # create_visual(mesh_files, folder, 0,0,-90, type='mesh') + + # create_mesh_animation(mesh_files, folder, 0,0, -90) + + # folder = '/home/wiss/sang/git/implicit_neuro_morph/jax_implicit_neuro_morph/exp/fraust_r/2024_04_22_14_01_05/eval' + # mesh_files = [os.path.join(folder, f) for f in os.listdir(folder) if f.endswith('ptc.ply')] + # mesh_files = sort_list(mesh_files) + # create_point_cloud_animation(mesh_files, folder, 0,0,-90) + + prefix = 'shape_0_to_4000_' + mesh1 = 'gt_pointcloud_y.ply' + mesh2 = 'step_10_mesh.ply' + + meshfile1 = os.path.join(folder, prefix + mesh1) + meshfile2 = os.path.join(folder, prefix + mesh2) + + plot_two_mesh(meshfile1, meshfile2, 0, 0, -30) + + \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000000000000000000000000000000000000..d590657de21ab50f5fda5a18b879b940c9bca3a3 --- /dev/null +++ b/app.py @@ -0,0 +1,742 @@ +import os +import sys +import json +import socket +import tempfile +import pathlib +from dataclasses import dataclass +from typing import List, Dict, Any +import pickle + +import cv2 +import torch +import numpy as np +import imageio +import gradio as gr +import spaces +import smplx +import pyrender +import trimesh +import trimesh.transformations as tra +import requests +from download_precomputed import download_and_extract_precomputed + +# if intermediate_results/8_kid_crossing doesn't exist, download it +if not os.path.exists('intermediate_results/8_kid_crossing'): + download_and_extract_precomputed() + +# Constants and configuration +CHECKPOINT_PATH = './models/checkpoint_150.pt' +NUM_SAMPLES = 50 +DISPLAYED_PREDS = 3 +FRAME_LIMIT = 30 +FPS = 60 +DESCRIPTION = "# SkeletonDiffusion Demo" + +# Create necessary directories +for dir_name in ['downloads', 'predictions', 'vis', 'intermediate_results', 'outputs', 'assets']: + os.makedirs(dir_name, exist_ok=True) + +# Create a simple loading image if it doesn't exist +LOADING_IMAGE_PATH = os.path.join('assets', 'loading.png') +if not os.path.exists(LOADING_IMAGE_PATH): + # Create a simple loading image with text + img = np.zeros((200, 400, 3), dtype=np.uint8) + img.fill(255) # White background + cv2.putText(img, "Processing...", (50, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2) + cv2.putText(img, "Please wait", (50, 150), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2) + cv2.imwrite(LOADING_IMAGE_PATH, img) + +# Available options for displayed predictions +DISPLAYED_PREDS_OPTIONS = [2, 3, 4, 5, 6] + +# Fix display and setup issues +os.environ['PYOPENGL_PLATFORM'] = 'egl' +os.system('export IMAGEMAGICK_BINARY=./magick') +os.system('bash ./SkeletonDiffusion_demo/setup_headless.bash') + +# Download ImageMagick if not present +MAGICK_PATH = "./magick" +if not os.path.exists(MAGICK_PATH): + response = requests.get("https://imagemagick.org/archive/binaries/magick", stream=True) + if response.status_code == 200: + with open(MAGICK_PATH, "wb") as f: + for chunk in response.iter_content(chunk_size=8192): + if chunk: + f.write(chunk) + print(f"Download completed and saved as '{MAGICK_PATH}'") + else: + print(f"Download failed with status code: {response.status_code}") +os.system('chmod +x ./magick') + +# Setup device +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") +# Local imports +import SkeletonDiffusion_demo.plot_several_meshes as plot_several_meshes +import SkeletonDiffusion_demo.combine_video as combine +from SkeletonDiffusion.src.data.skeleton import create_skeleton +from SkeletonDiffusion.src.eval_prepare_model import get_prediction, load_model_config_exp, prepare_model +from src_joints2smpl_demo.joints2smpl.convert_joints2smpl import process_motion +from SkeletonDiffusion.src.metrics.ranking import get_closest_and_nfurthest_maxapd +@dataclass +class SMPLParams: + """Data structure to hold SMPL parameters.""" + global_orient: torch.Tensor + body_pose: torch.Tensor + betas: torch.Tensor + transl: torch.Tensor + joints3d: torch.Tensor + +def handle_video_input(video_file: str) -> str: + """Handle video input from either a local file or YouTube URL. + + Args: + video_file: Path to local video file + + Returns: + str: Path to the video file + """ + if video_file: + return video_file + return None + +def correct_vertices(vertices: np.ndarray) -> np.ndarray: + """Correct SMPL vertices to convert from SMPL to renderer coordinate system. + + Applies a rotation about the Y-axis by 180 degrees so that the original +X axis + (face direction) is transformed to the -Z axis. + + Args: + vertices: SMPL vertices in shape (1, N, 3) + + Returns: + np.ndarray: Corrected vertices in shape (1, N, 3) + """ + angle = np.radians(180) + R = tra.rotation_matrix(angle, [1, 0, 0]) + vertices_homo = np.hstack([vertices[0], np.ones((vertices[0].shape[0], 1))]) + vertices_corrected = (R @ vertices_homo.T).T + return vertices_corrected[:, :3].reshape(1, -1, 3) + +def render_smpl(vertices: np.ndarray, width: int, height: int) -> np.ndarray: + """Render SMPL 3D model using PyRender. + + Args: + vertices: SMPL vertices in shape (1, N, 3) + width: Output image width + height: Output image height + + Returns: + np.ndarray: Rendered image in BGR format + """ + device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + smpl_model = smplx.create("./models/SMPL_NEUTRAL.pkl", model_type="smpl", gender="neutral").to(device) + + vertices_corrected = correct_vertices(vertices) + mesh = trimesh.Trimesh(vertices_corrected[0], smpl_model.faces) + + scene = pyrender.Scene(bg_color=[1.0, 1.0, 1.0, 0.9]) + mesh_node = pyrender.Mesh.from_trimesh(mesh) + scene.add(mesh_node) + + camera = pyrender.OrthographicCamera(xmag=1.0, ymag=1.0) + camera_pose = np.eye(4) + camera_pose[:3, 3] = [0, 0, 5.0] # distance = 5.0 + scene.add(camera, pose=camera_pose) + + renderer = pyrender.OffscreenRenderer(width, height) + color, _ = renderer.render(scene) + return cv2.cvtColor(color, cv2.COLOR_RGB2BGR) + +def save_intermediate_results(video_name: str, results: Dict[str, Any], displayed_preds: int = DISPLAYED_PREDS): + """Save intermediate results for a video. + + Args: + video_name: Name of the video file + results: Dictionary containing intermediate results + displayed_preds: Number of displayed predictions + """ + base_name = os.path.splitext(os.path.basename(video_name))[0] + results_dir = os.path.join('intermediate_results', base_name) + os.makedirs(results_dir, exist_ok=True) + + # Save results with displayed_preds in filename + results_path = os.path.join(results_dir, f'results_{displayed_preds}.pkl') + with open(results_path, 'wb') as f: + pickle.dump(results, f) + +def load_intermediate_results(video_name: str, displayed_preds: int = DISPLAYED_PREDS) -> Dict[str, Any]: + """Load intermediate results for a video. + + Args: + video_name: Name of the video file + displayed_preds: Number of displayed predictions + + Returns: + Dictionary containing intermediate results or None if not found + """ + base_name = os.path.splitext(os.path.basename(video_name))[0] + results_path = os.path.join('intermediate_results', base_name, f'results_{displayed_preds}.pkl') + + if os.path.exists(results_path): + # Set default tensor type to CPU before loading + torch.set_default_tensor_type(torch.FloatTensor) + with open(results_path, 'rb') as f: + # Use map_location to ensure tensors are loaded on CPU + results = torch.load(f, map_location='cpu') + # Reset default tensor type + torch.set_default_tensor_type(torch.cuda.FloatTensor) + return results + return None + +@spaces.GPU(duration=60) +def process_video_gpu(video_file: str, displayed_preds: int = DISPLAYED_PREDS) -> tuple: + """GPU version of process_video that does the actual processing.""" + import time + start_time = time.time() + + # Load models + model_start_time = time.time() + smpl_model = smplx.create("./models/SMPL_NEUTRAL.pkl", model_type="smpl", gender="neutral").to(device) + nlf_model = torch.jit.load("./models/nlf_l_multi.torchscript").to(device).eval() + print(f"Time for model loading: {time.time() - model_start_time:.2f}s") + + # Handle video input + input_start_time = time.time() + input_path = handle_video_input(video_file) + if not input_path: + return None, None + print(f"Time for video input handling: {time.time() - input_start_time:.2f}s") + + # Create output path in outputs directory + base_name = os.path.splitext(os.path.basename(video_file))[0] + output_path = os.path.join('outputs', f'{base_name}_smpl_{displayed_preds}.gif') + + # Process frames + frame_start_time = time.time() + cap = cv2.VideoCapture(input_path) + frame_count = 0 + smpl_params_list = [] + nlf_frames = [] # Store NLF detection frames + + # Initialize time counters + total_nlf_time = 0 + total_smpl_time = 0 + total_frame_time = 0 + + while cap.isOpened() and frame_count < FRAME_LIMIT: + frame_process_start = time.time() + ret, frame = cap.read() + if not ret: + break + + frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + image_tensor = torch.from_numpy(frame_rgb).permute(2, 0, 1).int().to(device) + + # SMPL detection + nlf_start_time = time.time() + with torch.inference_mode(): + pred = nlf_model.detect_smpl_batched(image_tensor.unsqueeze(0)) + + pose_params = pred["pose"][0].cpu().numpy() + betas = pred["betas"][0].cpu().numpy() + transl = pred["trans"][0].cpu().numpy() + joints3d = pred['joints3d'][0].cpu().numpy() + + nlf_time = time.time() - nlf_start_time + total_nlf_time += nlf_time + print(f"Time for NLF model inference: {nlf_time:.2f}s") + + + if pose_params.shape[0] == 0: + print(f"No SMPL detected in frame {frame_count}") + nlf_frames.append(frame_rgb) + continue + + if pose_params.shape[0] > 0: + # SMPL model + render_start_time = time.time() + smpl_param = SMPLParams( + global_orient=torch.tensor(pose_params[:, :3]).to(device), + body_pose=torch.tensor(pose_params).to(device), + betas=torch.tensor(betas).to(device), + transl=torch.tensor(transl).to(device), + joints3d=torch.tensor(joints3d[:, 0:22, :3]).to(device), + ) + output_smpl = smpl_model( + global_orient=torch.tensor(pose_params[:, :3]).to(device), + body_pose=torch.tensor(pose_params[:, 3:]).to(device), + betas=torch.tensor(betas).to(device), + transl=torch.tensor(transl).to(device), + joints3d=torch.tensor(joints3d[:, 0:66]).to(device), + ) + + smpl_time = time.time() - render_start_time + total_smpl_time += smpl_time + print(f"Time for SMPL model: {smpl_time:.2f}s") + + smpl_params_list.append(smpl_param) + nlf_frames.append(frame_rgb) # Store original frame for NLF visualization + frame_count += 1 + + frame_time = time.time() - frame_process_start + total_frame_time += frame_time + print(f"Total time for frame {frame_count}: {frame_time:.2f}s") + + cap.release() + gr.Info("Video-to-motion processing completed!") + print(f"\nTime statistics for {frame_count} frames:") + print(f"Average NLF model time per frame: {total_nlf_time/frame_count:.2f}s") + print(f"Average SMPL model time per frame: {total_smpl_time/frame_count:.2f}s") + print(f"Average total time per frame: {total_frame_time/frame_count:.2f}s") + print(f"Total time for all frame processing: {time.time() - frame_start_time:.2f}s") + + # Serialize SMPL parameters + serial_start_time = time.time() + smpl_params_serialized = [ + { + "global_orient": p.global_orient.tolist(), + "body_pose": p.body_pose.tolist(), + "betas": p.betas.tolist(), + "transl": p.transl.tolist(), + "joints3d": p.joints3d.tolist(), + } + for p in smpl_params_list + ] + print(f"Time for parameter serialization: {time.time() - serial_start_time:.2f}s") + + print(f"Total time: {time.time() - start_time:.2f}s") + + # Save SMPL params as JSON + with open('smpl_params.json', 'w') as f: + json.dump(smpl_params_serialized, f) + + # Save intermediate results + results = { + 'output_path': output_path, + 'smpl_params_serialized': smpl_params_serialized, + 'nlf_frames': nlf_frames, + 'smpl_params_list': smpl_params_list + } + save_intermediate_results(video_file, results, displayed_preds) + + return output_path, smpl_params_serialized + +@spaces.GPU(duration=200) +def generate_motion_video_gpu(smpl_params_json: List[Dict[str, Any]], video_file: str, displayed_preds: int = DISPLAYED_PREDS) -> str: + """GPU version of generate_motion_video that does the actual processing.""" + import time + start_time = time.time() + + # Setup device + device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + + # Create output path in outputs directory with displayed_preds in filename + base_name = os.path.splitext(os.path.basename(video_file))[0] + output_path = os.path.join('outputs', f'{base_name}_motion_{displayed_preds}.gif') + + # Load input video frames + input_frames = [] + cap = cv2.VideoCapture(video_file) + frame_count = 0 + while cap.isOpened() and frame_count < FRAME_LIMIT: + ret, frame = cap.read() + if not ret: + break + input_frames.append(frame) + frame_count += 1 + cap.release() + + # Ensure we have exactly FRAME_LIMIT frames + if len(input_frames) < FRAME_LIMIT: + # Pad with the last frame if needed + last_frame = input_frames[-1] if input_frames else np.zeros((480, 640, 3), dtype=np.uint8) + input_frames.extend([last_frame] * (FRAME_LIMIT - len(input_frames))) + elif len(input_frames) > FRAME_LIMIT: + # Trim to FRAME_LIMIT frames + input_frames = input_frames[:FRAME_LIMIT] + + # Deserialize JSON back into SMPLParams objects + smpl_params_list = [ + SMPLParams( + global_orient=torch.tensor(p["global_orient"]).to(device), + body_pose=torch.tensor(p["body_pose"]).to(device), + betas=torch.tensor(p["betas"]).to(device), + transl=torch.tensor(p["transl"]).to(device), + joints3d=torch.tensor(p["joints3d"]).to(device), + ) + for p in smpl_params_json + ] + print(f"Time for deserialization: {time.time() - start_time:.2f}s") + + # Calculate number of frames for 0.5 seconds + # frames_for_half_second = int(FPS * 0.5) + frames_for_half_second = 30 + # Collect last 0.5 seconds of frames + obs = torch.stack([p.joints3d[0] for p in smpl_params_list[-frames_for_half_second:]]) + + # Pad with first frame if needed + if len(obs) < frames_for_half_second: + padding = torch.stack([obs[0]] * (frames_for_half_second - len(obs))) + obs = torch.cat([padding, obs], dim=0) + + # Load model and prepare data + model_start_time = time.time() + config, exp_folder = load_model_config_exp(CHECKPOINT_PATH) + config['checkpoint_path'] = CHECKPOINT_PATH + skeleton = create_skeleton(**config) + + model, device, *_ = prepare_model(config, skeleton, **config) + + # Convert from mm to m and prepare input + obs = obs / 1000.0 + obs = obs.reshape(1, frames_for_half_second, 22, 3).to(device) + obs = torch.stack([-obs[..., 2], obs[..., 0], -obs[..., 1]], dim=-1) + obs = obs - obs[..., 0:1, :] + obs_in = skeleton.tranform_to_input_space(obs).to(device) + + # Get predictions + pred = get_prediction(obs_in, model, num_samples=NUM_SAMPLES, **config) + pred = torch.cat((torch.zeros(1, NUM_SAMPLES, pred.shape[2], 1, 3).to(device), pred), dim=3) + obs_in = torch.cat((torch.zeros(1, frames_for_half_second, 1, 3).to(device), obs_in), dim=2) + + print(f"Time for model inference: {time.time() - model_start_time:.2f}s") + + # Convert predictions to SMPL parameters + smpl_start_time = time.time() + + print(f"Time for SMPL conversion: {time.time() - smpl_start_time:.2f}s") + + # Prepare data for visualization + obs_in_50 = obs_in.unsqueeze(1).repeat(1, NUM_SAMPLES, 1, 1, 1) + obs_and_pred = torch.cat((obs_in_50, pred), dim=2) + + # Save predictions + pred_np = obs_and_pred.cpu().numpy() + os.makedirs('predictions', exist_ok=True) + np.save('predictions/joints3d.npy', pred_np) + print(f"Joints3D data saved to predictions/joints3d.npy") + + # Calculate metrics and select best samples + metric_start_time = time.time() + from SkeletonDiffusion.src.metrics.body_realism import limb_stretching_normed_rmse + + limbstretching = limb_stretching_normed_rmse( + pred[..., 1:, :], + target=obs[0, ..., 1:, :].unsqueeze(0), + limbseq=skeleton.get_limbseq(), + reduction='persample', + obs_as_target=True + ) + + # Sort samples by limb stretching and take the half with smallest values + limbstretching_sorted, indices = torch.sort(limbstretching.squeeze(1), dim=-1, descending=False) + half_size = len(indices[0]) // 2 + best_half_indices = indices[0, :15] + + # Get predictions for best half + y_pred = pred.squeeze(0)[best_half_indices] + y_gt = y_pred[0].unsqueeze(0) + + # Use get_closest_and_nfurthest_maxapd to select diverse samples + _, _, top_indices = get_closest_and_nfurthest_maxapd(y_pred, y_gt, nsamples=displayed_preds) + + print(f"Selected {len(best_half_indices)} samples with smallest limb stretching") + print(f"Selected {len(top_indices)} diverse samples from best half") + + # Generate visualization + vis_start_time = time.time() + with torch.no_grad(): + # Create video-specific obj directory + obj_dir = os.path.join('outputs', f'{base_name}_obj/') + os.makedirs(obj_dir, exist_ok=True) + process_motion("smpl_params.json", "predictions/joints3d.npy", device=device, sorted_idx=top_indices, output_dir=obj_dir) + + print(f"Checking obj_dir contents: {obj_dir}") + if os.path.exists(obj_dir): + print("Contents of obj_dir:") + for root, dirs, files in os.walk(obj_dir): + print(f"Directory: {root}") + print(f"Files: {files}") + print(f"Subdirectories: {dirs}") + + plot_several_meshes.main(obj_dir, displayed_preds) + + # Show completion message before combining video + gr.Info("Step 3/3: Combine GIFs") + # Save the motion video to the output path with input frames as picture-in-picture + output_path = combine.combine_video(obj_dir, output_path, input_frames, displayed_preds) + + return output_path + +def process_video(video_file: str, displayed_preds: int = DISPLAYED_PREDS) -> tuple: + """Process input video to extract SMPL parameters and generate visualization.""" + # Check if we have pre-computed results + pre_computed = load_intermediate_results(video_file, displayed_preds) + if pre_computed is not None: + print("Using pre-computed results") + return pre_computed['output_path'], pre_computed['smpl_params_serialized'] + + # If no pre-computed results, use GPU processing + return process_video_gpu(video_file, displayed_preds) + +def generate_motion_video(smpl_params_json: List[Dict[str, Any]], video_file: str = None, displayed_preds: int = DISPLAYED_PREDS) -> str: + """Generate a motion video from SMPL parameters.""" + if smpl_params_json is None: + raise ValueError("No SMPL parameters provided. Please process a video first.") + + # Check if we have pre-computed results + if video_file: + pre_computed = load_intermediate_results(video_file, displayed_preds) + if pre_computed is not None and 'motion_video_path' in pre_computed: + print("Using pre-computed motion video") + return pre_computed['motion_video_path'] + + # If no pre-computed results, use GPU processing + return generate_motion_video_gpu(smpl_params_json, video_file, displayed_preds) + +def video_to_gif(video_path, gif_path, frame_limit=30): + """Convert video to GIF with specified frame limit and smooth looping.""" + frames = [] + # lower resolution + reader = imageio.get_reader(video_path) + for i, frame in enumerate(reader): + if i >= frame_limit: + break + frames.append(frame) + # Set FPS to 15 for smooth looping of 30 frames (2 seconds per loop) + imageio.mimsave(gif_path, frames, fps=15, loop=0) # loop=0 means infinite loop + return gif_path + +def concat_gifs_side_by_side(gif1_path, gif2_path, output_path): + """Pad both GIFs to the same (max) height, center them vertically, then concatenate side by side.""" + gif1 = imageio.mimread(gif1_path) + gif2 = imageio.mimread(gif2_path) + + # Ensure both GIFs have the same number of frames + if len(gif1) != len(gif2): + print(f"Warning: GIFs have different frame counts ({len(gif1)} vs {len(gif2)}). Adjusting to match.") + # Use the shorter length + min_frames = min(len(gif1), len(gif2)) + gif1 = gif1[:min_frames] + gif2 = gif2[:min_frames] + + frames = [] + for f1, f2 in zip(gif1, gif2): + # Convert both frames to RGB if needed (handle RGBA with alpha channel) + if f1.shape[2] == 4: + f1 = f1[..., :3] + if f2.shape[2] == 4: + f2 = f2[..., :3] + h1, w1, c1 = f1.shape + h2, w2, c2 = f2.shape + max_h = max(h1, h2) + # Pad f1 to max_h, vertically centered + pad_top1 = (max_h - h1) // 2 + pad_bot1 = max_h - h1 - pad_top1 + f1_pad = np.pad(f1, ((pad_top1, pad_bot1), (0, 0), (0, 0)), mode='constant', constant_values=255) + # Pad f2 to max_h, vertically centered + pad_top2 = (max_h - h2) // 2 + pad_bot2 = max_h - h2 - pad_top2 + f2_pad = np.pad(f2, ((pad_top2, pad_bot2), (0, 0), (0, 0)), mode='constant', constant_values=255) + # Concatenate horizontally + frame = np.concatenate([f1_pad, f2_pad], axis=1) + frames.append(frame) + imageio.mimsave(output_path, frames, fps=15, loop=0) + return output_path + +def create_gradio_interface(): + """Create and configure the Gradio interface.""" + with gr.Blocks(css="style.css") as demo: + gr.Markdown(DESCRIPTION) + + # Add user instructions + gr.Markdown(""" + Demo for the CVPR2025 paper "Nonisotropic Gaussian Diffusion for Realistic 3D Human Motion Prediction", available [here](https://ceveloper.github.io/publications/skeletondiffusion/). Codebase released on [GitHub](https://github.com/Ceveloper/SkeletonDiffusion/tree/main). + + SkeletonDiffusion takes as input a sequence of 3D body joints coordinates, which not everyone has at disposal. In this demo, we use a publicly available model, Neural Localizer Fields ([NLF](https://istvansarandi.com/nlf/)) to extract 3D poses from a given input video. We feed the extracted poses to SkeletonDiffusion to generate corresponding future motions. Note that the poses extracted from the video are noisy and imperfect, but SkeletonDiffusion has been trained only with precise sensor data obtained in laboratory settings. + Despite never having seen noisy data and various real-world actions (ballet, basketball, etc.), SkeletonDiffusion can handle most cases reasonably! + + ### Instructions + 1. Upload a video or select from examples + 2. Choose whether to use precomputed results (if available) + 3. Select the number of motion predictions to display (2-6) + 4. Click "Run Skeleton Diffusion" to start + + **Note:** + - SkeletonDiffusion requires less than half a second for a forward pass, but extracting the poses from RGB and rendering the output are time consuming + - Only the first 30 frames of the input video will be used + - The first 0.5 seconds of motion will be used to predict future motion + - Processing time depends on video length and selected number of predictions + - Precomputed results will be much faster if available + """) + + with gr.Tabs(): + with gr.Tab("Video Processing"): + with gr.Row(): + input_video = gr.Video(label="Input Video", height=600) + with gr.Row(): + gr.Examples( + examples=sorted(pathlib.Path("downloads").glob("*.mp4")), + inputs=input_video, + cache_examples=False, + ) + with gr.Row(): + use_precomputed = gr.Checkbox( + label="Use precomputed results if available", + value=True, + info="If checked, will use existing results instead of processing the video again" + ) + displayed_preds = gr.Dropdown( + choices=DISPLAYED_PREDS_OPTIONS, + value=DISPLAYED_PREDS, + label="Number of displayed predictions", + info="Select how many motion predictions to display (2-6)" + ) + with gr.Row(): + process_btn = gr.Button("Run Skeleton Diffusion") + + # Two-column output: left=input, right=output + with gr.Row(): + with gr.Column(): + input_video_display = gr.Image(label="Input Video (Preview GIF)", height=600) + with gr.Column(): + output_video = gr.Image(label="Generated Motion", height=600) + + # Download buttons + with gr.Row(): + with gr.Column(): + download_motion_btn = gr.Button("Download Motion Video") + download_motion_btn.click( + fn=lambda video_file, displayed_preds: os.path.join('outputs', f'{os.path.splitext(os.path.basename(video_file))[0]}_motion_{displayed_preds}.gif') if video_file else None, + inputs=[input_video, displayed_preds], + outputs=[gr.File(label="Download Motion Video")] + ) + with gr.Column(): + download_data_btn = gr.Button("Download Motion Data (SMPL + Joints)") + download_data_btn.click( + fn=lambda video_file, displayed_preds: os.path.join('intermediate_results', os.path.splitext(os.path.basename(video_file))[0], f'results_{displayed_preds}.pkl') if video_file else None, + inputs=[input_video, displayed_preds], + outputs=[gr.File(label="Download Motion Data")] + ) + + def process_video_with_notification(video_file, use_precomputed, displayed_preds): + # Step 1: Show input video as GIF immediately with exactly 30 frames + gr.Info("Converting input video to preview GIF...") + gif_path = os.path.join(tempfile.gettempdir(), f"input_preview_{os.path.splitext(os.path.basename(video_file))[0]}.gif") + video_to_gif(video_file, gif_path, frame_limit=30) # Explicitly set to 30 frames + yield gif_path, LOADING_IMAGE_PATH + + base_name = os.path.splitext(os.path.basename(video_file))[0] + output_path = os.path.join('outputs', f'{base_name}_motion_{displayed_preds}.gif') + obs_gif_path = os.path.join('outputs', f'{base_name}_obj', 'shadow_gif', 'obs_obj_tranp.gif') + concat_gif_path = os.path.join(tempfile.gettempdir(), f"concat_{base_name}.gif") + + # If using precomputed and obs_obj_tranp.gif exists, show concatenated GIF immediately + if use_precomputed and os.path.exists(obs_gif_path): + concat_gifs_side_by_side(gif_path, obs_gif_path, concat_gif_path) + # Replace the preview with the concatenated GIF + yield concat_gif_path, LOADING_IMAGE_PATH + # ... continue with rest of workflow + # (The rest of the workflow remains unchanged) + if os.path.exists(output_path): + gr.Info("Found precomputed video.\nUsing existing results...") + yield concat_gif_path, output_path + return + # ... existing code ... + + # If not precomputed, after obs_obj_tranp.gif is generated, show concatenated GIF + # Continue with the rest of the workflow as before + # Case 1: Not using precomputed results + if not use_precomputed: + gr.Info("Starting video processing with GPU...\nThis may take a few minutes.") + gr.Info("Step 1/3: Extracting SMPL parameters from video...") + _, smpl_params = process_video_gpu(video_file, displayed_preds) + # After SMPL extraction, check if obs_obj_tranp.gif exists and show concatenated GIF + if os.path.exists(obs_gif_path): + concat_gifs_side_by_side(gif_path, obs_gif_path, concat_gif_path) + yield concat_gif_path, LOADING_IMAGE_PATH + gr.Info("Step 2/3: Generating motion predictions...") + motion_gif = generate_motion_video_gpu(smpl_params, video_file, displayed_preds) + yield concat_gif_path, motion_gif + return + + # If no precomputed video, check if we have enough GIFs to generate one + shadow_gif_dir = os.path.join('outputs', f'{base_name}_obj', 'shadow_gif') + if os.path.exists(shadow_gif_dir): + existing_gifs = [f for f in os.listdir(shadow_gif_dir) if f.endswith('_tranp.gif') and not f.startswith('obs')] + if len(existing_gifs) >= displayed_preds: + gr.Info(f"Found {len(existing_gifs)} existing GIFs.\nGenerating video from existing predictions...") + # Load input video frames for picture-in-picture + input_frames = [] + cap = cv2.VideoCapture(video_file) + frame_count = 0 + while cap.isOpened() and frame_count < FRAME_LIMIT: + ret, frame = cap.read() + if not ret: + break + input_frames.append(frame) + frame_count += 1 + cap.release() + # Ensure we have exactly FRAME_LIMIT frames + if len(input_frames) < FRAME_LIMIT: + # Pad with the last frame if needed + last_frame = input_frames[-1] if input_frames else np.zeros((480, 640, 3), dtype=np.uint8) + input_frames.extend([last_frame] * (FRAME_LIMIT - len(input_frames))) + elif len(input_frames) > FRAME_LIMIT: + # Trim to FRAME_LIMIT frames + input_frames = input_frames[:FRAME_LIMIT] + # If obs_obj_tranp.gif exists, show concatenated GIF + if os.path.exists(obs_gif_path): + concat_gifs_side_by_side(gif_path, obs_gif_path, concat_gif_path) + gif_path = concat_gif_path + yield concat_gif_path, LOADING_IMAGE_PATH + + # Generate video from existing GIFs + gr.Info("Combining predictions into final video...") + motion_gif = combine.combine_video( + os.path.join('outputs', f'{base_name}_obj'), + output_path, + input_frames, + displayed_preds + ) + gr.Info("Processing complete!") + yield gif_path, motion_gif + return + + # If we don't have enough GIFs, proceed with full processing + gr.Info("No precomputed results found.\nStarting full video processing...") + gr.Info("Step 1/3: Extracting SMPL parameters from video...") + _, smpl_params = process_video_gpu(video_file, displayed_preds) + + gr.Info("Step 2/3: Generating motion predictions...") + motion_gif = generate_motion_video_gpu(smpl_params, video_file, displayed_preds) + # After SMPL extraction, check if obs_obj_tranp.gif exists and show concatenated GIF + if os.path.exists(obs_gif_path): + concat_gifs_side_by_side(gif_path, obs_gif_path, concat_gif_path) + yield concat_gif_path, LOADING_IMAGE_PATH + + yield concat_gif_path, motion_gif + return + + process_btn.click( + fn=process_video_with_notification, + inputs=[input_video, use_precomputed, displayed_preds], + outputs=[input_video_display, output_video] + ) + + return demo + +if __name__ == "__main__": + # Get local IP address + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.connect(("8.8.8.8", 80)) + print(s.getsockname()[0]) + s.close() + + # Create and launch interface + demo = create_gradio_interface() + print(demo.get_api_info()) + demo.launch(server_name="0.0.0.0", share=True) + + diff --git a/body_models/smpl/J_regressor_extra.npy b/body_models/smpl/J_regressor_extra.npy new file mode 100644 index 0000000000000000000000000000000000000000..d6cf8c0f6747d3c623a0d300c5176843ae99031d --- /dev/null +++ b/body_models/smpl/J_regressor_extra.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc968ea4f9855571e82f90203280836b01f13ee42a8e1b89d8d580b801242a89 +size 496160 diff --git a/body_models/smpl/SMPL_NEUTRAL.pkl b/body_models/smpl/SMPL_NEUTRAL.pkl new file mode 100644 index 0000000000000000000000000000000000000000..26574fd104c4b69467f3c7c3516a8508d8a1a36e --- /dev/null +++ b/body_models/smpl/SMPL_NEUTRAL.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:98e65c74ad9b998783132f00880d1025a8d64b158e040e6ef13a557e5098bc42 +size 39001280 diff --git a/body_models/smpl/kintree_table.pkl b/body_models/smpl/kintree_table.pkl new file mode 100644 index 0000000000000000000000000000000000000000..3f72aca47e9257f017ab09470ee977a33f41a49e --- /dev/null +++ b/body_models/smpl/kintree_table.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62116ec76c6192ae912557122ea935267ba7188144efb9306ea1366f0e50d4d2 +size 349 diff --git a/body_models/smpl/smplfaces.npy b/body_models/smpl/smplfaces.npy new file mode 100644 index 0000000000000000000000000000000000000000..6cadb74c9df2b6deebcdc90ee4f8cf9efbffb11d --- /dev/null +++ b/body_models/smpl/smplfaces.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ee8e99db736acf178a6078ab5710ca942edc3738d34c72f41a35c40b370e045 +size 165440 diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fbafb9306349cb976ecb6c6a2e29b58671edd0ec --- /dev/null +++ b/config.yaml @@ -0,0 +1,155 @@ +if_resume_training: false +debug: false +device: cuda +load: false +load_path: '' +dataset_main_path: ./datasets +dataset_annotation_path: ./datasets/annotations&interm +dataset_precomputed_path: ./datasets/processed +_load_saved_aoutoenc: hmp-amass +output_log_path: ./models/ +slurm_id: 0 +slurm_first_run: None +info: cvpr_release +pretrained_autoencoder_path: ./models/checkpoint_300.pt +lr: 0.001 +diffusion_objective: pred_x0 +weight_decay: 0.0 +if_use_ema: true +step_start_ema: 100 +ema_power: 0.6666666666666666 +ema_update_every: 10 +ema_min_value: 0.0 +use_lr_scheduler: true +lr_scheduler_kwargs: + lr_scheduler_type: ExponentialLRSchedulerWarmup + warmup_duration: 75 + update_every: 2 + min_lr: 0.0001 + gamma_decay: 0.98 + decay_factor: 0.1 + patience: 1 +diffusion_conditioning: true +num_epochs: 150 +num_workers: 4 +batch_size: 64 +batch_size_eval: 256 +eval_frequency: 1 +train_pick_best_sample_among_k: 50 +diffusion_k_train_after_epochs: 0 +diffusion_k_train_monot_increase: false +diffusion_k_train_monot_increase_howmanyperepoch: 1 +similarity_space: input_space +diffusion_activation: identity +num_prob_samples: 50 +diffusion_timesteps: 10 +diffusion_type: NonisotropicGaussianDiffusion +diffusion_loss_type: snr +loss_reduction_type: l1 +if_run_as_isotropic: false +if_sigma_n_scale: true +diffusion_covariance_type: skeleton-diffusion +gamma_scheduler: cosine +beta_schedule: cosine +sigma_n_scale: spectral +num_iter_perepoch: null +seed: 63485 +motion_repr_type: SkeletonRescalePose +dataset_type: AMASSDataset +dataset_name: amass +latent_size: 96 +output_size: 3 +z_activation: tanh +obs_length: 30 +prediction_horizon_train: 120 +prediction_horizon_eval: 120 +prediction_horizon: 120 +pred_length: 120 +prediction_horizon_train_min: 10 +prediction_horizon_train_min_from_epoch: 200 +curriculum_it: 10 +random_prediction_horizon: true +if_consider_hip: false +history_sec: 0.5 +prediction_horizon_sec: 2 +pose_box_size: 1.2 +seq_centering: 0 +task_name: hmp +num_joints: 22 +fps: 60 +multimodal_threshold: 0.4 +precomputed_folder: ./models/ +annotations_folder: ./models/ +data_loader_train: + stride: 60 + augmentation: 30 + shuffle: true + datasets: + - ACCAD + - BMLhandball + - BMLmovi + - BMLrub + - EKUT + - CMU + - EyesJapanDataset + - KIT + - PosePrior + - TCDHands + - TotalCapture + da_mirroring: 0.5 + da_rotations: 1.0 + drop_last: true + if_load_mmgt: false +data_loader_train_eval: + stride: 30 + augmentation: 0 + shuffle: false + datasets: + - ACCAD + - BMLhandball + - BMLmovi + - BMLrub + - EKUT + - CMU + - EyesJapanDataset + - KIT + - PosePrior + - TCDHands + - TotalCapture + da_mirroring: 0.0 + da_rotations: 0.0 + drop_last: false + if_load_mmgt: false +data_loader_valid: + stride: 30 + augmentation: 0 + shuffle: false + datasets: + - HumanEva + - HDM05 + - SFU + - MoSh + file_idces: all + drop_last: false + if_load_mmgt: false +enc_num_layers: 2 +encoder_hidden_size: 96 +decoder_hidden_size: 96 +arch: AutoEncoder +recurrent_arch_enc: StaticGraphGRU +recurrent_arch_decoder: StaticGraphGRU +diffusion_arch: + arch: Denoiser + use_attention: true + self_condition: false + norm_type: none + depth: 4 + attn_dim_head: 32 + attn_heads: 8 + learn_influence: true +covariance_matrix_type: adjacency +hydra: + run: + dir: ./models + job: + chdir: true diff --git a/download_precomputed.py b/download_precomputed.py new file mode 100644 index 0000000000000000000000000000000000000000..ee0967d91c1c4228ee4cd8848d63f87beaa1b151 --- /dev/null +++ b/download_precomputed.py @@ -0,0 +1,133 @@ +import os +from huggingface_hub import hf_hub_download, list_repo_files +import tarfile +import shutil +from tqdm import tqdm + +def download_and_extract_file(repo_id, filename, local_dir): + """ + Download and extract a file from Hugging Face. + + Args: + repo_id (str): The repository ID on Hugging Face + filename (str): The name of the file to download + local_dir (str): The directory to extract files to + """ + print(f"Starting download of {filename}...") + + # Create directory if it doesn't exist + os.makedirs(local_dir, exist_ok=True) + + try: + # Download the file using hf_hub_download + file_path = hf_hub_download( + repo_id=repo_id, + filename=filename, + repo_type="space", + local_dir=local_dir + ) + + print(f"Download completed. File saved to: {file_path}") + + # Extract the tar.xz file with progress bar + print(f"Extracting {filename}...") + with tarfile.open(file_path, 'r:xz') as tar: + # Get total number of files + total_files = len(tar.getmembers()) + + # Extract with progress bar + for member in tqdm(tar.getmembers(), total=total_files, desc=f"Extracting {filename}"): + tar.extract(member, path=local_dir) + + print(f"Extraction of {filename} completed successfully!") + + # Clean up the downloaded archive + os.remove(file_path) + print(f"Cleaned up downloaded archive {filename}.") + + except Exception as e: + print(f"An error occurred while processing {filename}: {str(e)}") + # Clean up in case of error + if os.path.exists(file_path): + os.remove(file_path) + raise + +def download_video_files(repo_id, local_dir): + """ + Download all video files from the downloads directory. + + Args: + repo_id (str): The repository ID on Hugging Face + local_dir (str): The directory to save videos to + """ + print("Starting download of video files...") + + # Create downloads directory if it doesn't exist + os.makedirs(local_dir, exist_ok=True) + + try: + # List all files in the downloads directory + files = list_repo_files( + repo_id=repo_id, + repo_type="space", + revision="main" + ) + + # Filter for video files in the downloads directory + video_files = [f for f in files if f.startswith('downloads/') and f.endswith('.mp4')] + + if not video_files: + print("No video files found in the downloads directory.") + return + + print(f"Found {len(video_files)} video files to download.") + + # Download each video file + for video_file in video_files: + print(f"\nDownloading {video_file}...") + hf_hub_download( + repo_id=repo_id, + filename=video_file, + repo_type="space", + local_dir=local_dir + ) + print(f"Downloaded {video_file} successfully!") + + print("\nAll video files downloaded successfully!") + + except Exception as e: + print(f"An error occurred while downloading video files: {str(e)}") + raise + +def download_and_extract_precomputed(): + """ + Download and extract precomputed results from Hugging Face. + Downloads both intermediate_results.tar.xz and outputs.tar.xz, + and downloads all video files from the downloads directory. + """ + repo_id = "abdullahyang/NonisotropicSkeletonDiffusion_PrecomputedResults" + + # Download and extract intermediate_results.tar.xz + download_and_extract_file( + repo_id=repo_id, + filename="intermediate_results.tar.xz", + local_dir="." + ) + + # Download and extract outputs.tar.xz + download_and_extract_file( + repo_id=repo_id, + filename="outputs.tar.xz", + local_dir="." + ) + + # Download video files + download_video_files( + repo_id=repo_id, + local_dir="." + ) + + print("All downloads and extractions completed successfully!") + +if __name__ == "__main__": + download_and_extract_precomputed() \ No newline at end of file diff --git a/downloads/stand-and-start-walking_vid.mp4 b/downloads/stand-and-start-walking_vid.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..cdf5b2c198b4a6249c3fb0532693d68ed2d32f6b --- /dev/null +++ b/downloads/stand-and-start-walking_vid.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6534f4f9ba88a55af40abcaed9f2a0f14a9d680726c7cf0a97ee7705e4bd1a6b +size 288855 diff --git a/joint2smpl_models/gmm_08.pkl b/joint2smpl_models/gmm_08.pkl new file mode 100644 index 0000000000000000000000000000000000000000..c97a1d7ef396581e56ce74a12cc39175680ce028 --- /dev/null +++ b/joint2smpl_models/gmm_08.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e1374908aae055a2afa01a2cd9a169bc6cfec1ceb7aa590e201a47b383060491 +size 839127 diff --git a/joint2smpl_models/neutral_smpl_mean_params.h5 b/joint2smpl_models/neutral_smpl_mean_params.h5 new file mode 100644 index 0000000000000000000000000000000000000000..b6ecce2a748128cfde09b219ccc74307de50bbae --- /dev/null +++ b/joint2smpl_models/neutral_smpl_mean_params.h5 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac9b474c74daec0253ed084720f662059336e976850f08a4a9a3f76d06613776 +size 4848 diff --git a/models/SMPL_NEUTRAL.pkl b/models/SMPL_NEUTRAL.pkl new file mode 100644 index 0000000000000000000000000000000000000000..26574fd104c4b69467f3c7c3516a8508d8a1a36e --- /dev/null +++ b/models/SMPL_NEUTRAL.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:98e65c74ad9b998783132f00880d1025a8d64b158e040e6ef13a557e5098bc42 +size 39001280 diff --git a/models/body_models/smpl/J_regressor_extra.npy b/models/body_models/smpl/J_regressor_extra.npy new file mode 100644 index 0000000000000000000000000000000000000000..d6cf8c0f6747d3c623a0d300c5176843ae99031d --- /dev/null +++ b/models/body_models/smpl/J_regressor_extra.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc968ea4f9855571e82f90203280836b01f13ee42a8e1b89d8d580b801242a89 +size 496160 diff --git a/models/body_models/smpl/SMPL_NEUTRAL.pkl b/models/body_models/smpl/SMPL_NEUTRAL.pkl new file mode 100644 index 0000000000000000000000000000000000000000..26574fd104c4b69467f3c7c3516a8508d8a1a36e --- /dev/null +++ b/models/body_models/smpl/SMPL_NEUTRAL.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:98e65c74ad9b998783132f00880d1025a8d64b158e040e6ef13a557e5098bc42 +size 39001280 diff --git a/models/body_models/smpl/kintree_table.pkl b/models/body_models/smpl/kintree_table.pkl new file mode 100644 index 0000000000000000000000000000000000000000..3f72aca47e9257f017ab09470ee977a33f41a49e --- /dev/null +++ b/models/body_models/smpl/kintree_table.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62116ec76c6192ae912557122ea935267ba7188144efb9306ea1366f0e50d4d2 +size 349 diff --git a/models/body_models/smpl/smplfaces.npy b/models/body_models/smpl/smplfaces.npy new file mode 100644 index 0000000000000000000000000000000000000000..6cadb74c9df2b6deebcdc90ee4f8cf9efbffb11d --- /dev/null +++ b/models/body_models/smpl/smplfaces.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ee8e99db736acf178a6078ab5710ca942edc3738d34c72f41a35c40b370e045 +size 165440 diff --git a/models/checkpoint_150.pt b/models/checkpoint_150.pt new file mode 100644 index 0000000000000000000000000000000000000000..ba06fd524b2c71ceedef0ae18aa5d14004466add --- /dev/null +++ b/models/checkpoint_150.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4dd58d3a6280a1534d82e500bbedb0bb68c3015195136460e22212ca86cfa044 +size 128728446 diff --git a/models/checkpoint_300.pt b/models/checkpoint_300.pt new file mode 100644 index 0000000000000000000000000000000000000000..461122b5535cd4224481dfd42b17bd4db2a1b937 --- /dev/null +++ b/models/checkpoint_300.pt @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f206a4108ce6ba1beec3f3e70f6b6092fb02a57c48f6c4b462a5d366d9518c5 +size 33673173 diff --git a/models/joint2smpl_models/gmm_08.pkl b/models/joint2smpl_models/gmm_08.pkl new file mode 100644 index 0000000000000000000000000000000000000000..c97a1d7ef396581e56ce74a12cc39175680ce028 --- /dev/null +++ b/models/joint2smpl_models/gmm_08.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e1374908aae055a2afa01a2cd9a169bc6cfec1ceb7aa590e201a47b383060491 +size 839127 diff --git a/models/joint2smpl_models/neutral_smpl_mean_params.h5 b/models/joint2smpl_models/neutral_smpl_mean_params.h5 new file mode 100644 index 0000000000000000000000000000000000000000..b6ecce2a748128cfde09b219ccc74307de50bbae --- /dev/null +++ b/models/joint2smpl_models/neutral_smpl_mean_params.h5 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac9b474c74daec0253ed084720f662059336e976850f08a4a9a3f76d06613776 +size 4848 diff --git a/models/nlf_l_multi.torchscript b/models/nlf_l_multi.torchscript new file mode 100644 index 0000000000000000000000000000000000000000..d287b15ab7bb8bad586faa85647767bf63677e35 --- /dev/null +++ b/models/nlf_l_multi.torchscript @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2090b041ccebbd395018033152628c4f24afe519aed3a299861621547582cdad +size 495696900 diff --git a/outputs/stand-and-start-walking_vid_smpl.gif b/outputs/stand-and-start-walking_vid_smpl.gif new file mode 100644 index 0000000000000000000000000000000000000000..fae01b9385edad0f3609eff33d54b8d57dc8c50a --- /dev/null +++ b/outputs/stand-and-start-walking_vid_smpl.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:12eb0431ca8500117e6e8082b808ae69f00c02467e7b9ad768eb9f346d1ba4c7 +size 8607023 diff --git a/packages.txt b/packages.txt new file mode 100644 index 0000000000000000000000000000000000000000..a27e44e4385c367151c3162dc703979680aa62a1 --- /dev/null +++ b/packages.txt @@ -0,0 +1,13 @@ +libglfw3-dev +libgles2-mesa-dev +libgl1-mesa-glx +libglib2.0-0 +git +imagemagick +ffmpeg +libsm6 +libxext6 +cmake +rsync +curl +nodejs \ No newline at end of file diff --git a/predictions/joints3d.npy b/predictions/joints3d.npy new file mode 100644 index 0000000000000000000000000000000000000000..138abc4bed2027b71b69987304d3f74640c9583d --- /dev/null +++ b/predictions/joints3d.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24343ef37bd2bb19a5e2686d9d361d67b2eaadece4e5b9d82b1f83d5ad673a2e +size 1980128 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..4ecba9520d6ccb976e959eb9505878d9ef231049 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,21 @@ +torch +torchvision +opencv-python +gradio==5.24.0 +imageio==2.33.1 +moviepy==1.0.3 +numpy==2.2.4 +Pillow==11.1.0 +pyrender==0.1.45 +Requests==2.32.3 +scipy==1.15.2 +smplx==0.1.28 +tqdm==4.67.1 +trimesh==4.6.4 +vedo==2024.5.2 +pydantic==2.10.6 +spaces +einops +denoising_diffusion_pytorch + +git+https://github.com/mattloper/chumpy@9b045ff5d6588a24a0bab52c83f032e2ba433e17 diff --git a/setup.sh b/setup.sh new file mode 100644 index 0000000000000000000000000000000000000000..2ec285dba01cee773eb133939af4a96f912c6c1f --- /dev/null +++ b/setup.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Create necessary directories +mkdir -p downloads predictions vis hanyu_obj cookies + +# Download ImageMagick if not exists +if [ ! -f "magick" ]; then + wget https://imagemagick.org/archive/binaries/magick + chmod +x magick +fi + +# Install Python packages +pip install -r requirements.txt + +# Install local packages +cd SkeletonDiffusion && pip install -e . && cd .. +cd src_joints2smpl_demo && pip install -e . && cd .. + +# Set up headless rendering +bash ./SkeletonDiffusion_demo/setup_headless.bash + +# Set environment variables +export PYOPENGL_PLATFORM=egl +export IMAGEMAGICK_BINARY=./magick \ No newline at end of file diff --git a/smpl_params.json b/smpl_params.json new file mode 100644 index 0000000000000000000000000000000000000000..32a82e4dfef6c6cad27823cb6de25d2e0d1c9507 --- /dev/null +++ b/smpl_params.json @@ -0,0 +1 @@ +[{"global_orient": [[2.7173380851745605, 0.2154044508934021, -0.1713731288909912]], "body_pose": [[2.7173380851745605, 0.2154044508934021, -0.1713731288909912, -0.12624379992485046, 0.13715466856956482, 0.4565974473953247, 0.1920183002948761, -0.06440308690071106, -0.047801654785871506, 0.21705403923988342, -0.027839036658406258, 0.08047401905059814, 0.5811466574668884, 0.008647316135466099, -0.19360493123531342, 0.2497010976076126, 0.1805887222290039, 0.1538708209991455, -0.14023946225643158, -0.21036165952682495, 0.003511310089379549, -0.004863820504397154, 0.5713046193122864, -0.20278269052505493, 0.11307571828365326, -0.16369237005710602, 0.13871046900749207, 0.25030532479286194, 0.012634490616619587, -0.018178967759013176, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.07938015460968018, -0.19244863092899323, -0.03489115089178085, -0.07289514690637589, -0.20929650962352753, -0.36017513275146484, -0.36682114005088806, -0.006592470686882734, 0.3664359748363495, -0.008062734268605709, 0.06722967326641083, 0.007912646979093552, 0.12060265243053436, -0.8556962609291077, -0.8462812900543213, 0.11162712424993515, 0.15130287408828735, 0.7831997275352478, -0.11093241721391678, 4.0776214599609375, -0.9443317651748657, -0.36074885725975037, 2.1612048149108887, -0.6343782544136047, -0.011571134440600872, -0.2672742009162903, 0.3164013624191284, -0.10627883672714233, 0.3606090545654297, -0.3952561616897583, -0.6526939868927002, -0.18812736868858337, -0.8669015765190125, -0.6713183522224426, -0.06378889828920364, 1.2577143907546997]], "betas": [[-1.0472468137741089, 1.9017797708511353, -0.003059511538594961, 0.00040476638241671026, -0.0004970746231265366, 0.0013927998952567577, 0.0005878470838069916, 0.002204597694799304, -0.00013433769345283508, 0.0014003458200022578]], "transl": [[0.008189271204173565, 0.21572738885879517, -0.003048265352845192]], "joints3d": [[[-44.91946792602539, 237.54698181152344, 4204.21826171875], [1.8984603881835938, 327.65142822265625, 4175.3701171875], [-116.47006225585938, 310.5624694824219, 4191.7138671875], [-29.73661231994629, 154.33306884765625, 4251.6201171875], [139.79151916503906, 627.1126098632812, 3996.0673828125], [-229.58322143554688, 667.892822265625, 4127.9736328125], [-16.880592346191406, 26.117355346679688, 4271.94921875], [132.62771606445312, 1010.4751586914062, 4042.107666015625], [-219.79434204101562, 1049.912841796875, 4173.9052734375], [-17.194149017333984, -25.763809204101562, 4268.6044921875], [215.33876037597656, 1073.7923583984375, 3969.71826171875], [-252.5067901611328, 1114.021240234375, 4070.673828125], [-1.3523330688476562, -216.50135803222656, 4321.70751953125], [59.50967788696289, -130.67137145996094, 4285.06689453125], [-66.3889389038086, -127.91014099121094, 4334.89111328125], [-20.398025512695312, -284.241455078125, 4276.181640625], [133.7199249267578, -133.8488006591797, 4245.20947265625], [-144.67652893066406, -124.02540588378906, 4376.1484375], [69.98316955566406, 46.95826721191406, 4081.39453125], [-260.61639404296875, 80.85179138183594, 4312.765625], [-31.349449157714844, -166.0983123779297, 4098.5830078125], [-311.6589660644531, -154.3068389892578, 4266.77783203125]]]}, {"global_orient": [[2.7532572746276855, 0.2179771512746811, -0.1941235363483429], [2.3190276622772217, 0.02047477662563324, 1.1169514656066895]], "body_pose": [[2.7532572746276855, 0.2179771512746811, -0.1941235363483429, -0.10019148886203766, 0.09769007563591003, 0.4228166937828064, 0.19103427231311798, -0.06150815263390541, -0.05457727238535881, 0.18203788995742798, -0.03148498013615608, 0.08049066364765167, 0.5098535418510437, -0.0573807992041111, -0.15529876947402954, 0.2175114005804062, 0.1940755546092987, 0.13640093803405762, -0.134415403008461, -0.23161141574382782, 0.0008490632171742618, 0.04556627571582794, 0.4675288498401642, -0.17627200484275818, 0.17049910128116608, -0.179635152220726, 0.19496844708919525, 0.2560544013977051, 0.033926963806152344, -0.00885956734418869, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.09383347630500793, -0.17282265424728394, -0.06608089059591293, -0.0902000367641449, -0.22579385340213776, -0.3741597831249237, -0.3566160202026367, -0.004875482060015202, 0.4090454578399658, -0.03060236945748329, 0.08462756127119064, 0.021335428580641747, 0.12580779194831848, -0.839908242225647, -0.842222273349762, 0.09006761759519577, 0.10908164829015732, 0.7226085662841797, -0.07722869515419006, 4.075491428375244, -0.8935940265655518, -0.3845251202583313, 2.2240006923675537, -0.577501118183136, 0.018432175740599632, -0.2938164174556732, 0.3235844373703003, -0.04961862042546272, 0.27230414748191833, -0.5281544923782349, -0.672906219959259, -0.19857798516750336, -0.841296374797821, -0.39337021112442017, -0.270010769367218, 1.0450668334960938], [2.3190276622772217, 0.02047477662563324, 1.1169514656066895, 0.21100807189941406, -0.06750394403934479, -0.04521867260336876, 0.5270692706108093, -0.14141182601451874, 0.5922353267669678, 0.9815428256988525, 0.35713163018226624, 0.3506377935409546, 0.3766789138317108, -0.16108685731887817, 0.360370010137558, 0.06423693895339966, 0.3915032744407654, -0.45350155234336853, -1.0140596628189087, -0.07248687744140625, 0.02212514914572239, 0.23451559245586395, 0.7216024398803711, -0.377108633518219, 0.1571492999792099, -1.0905842781066895, 0.2973938584327698, 0.4602300524711609, 0.006005540490150452, -0.288041353225708, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.3662608861923218, -0.5244122743606567, 0.26642149686813354, 0.11996804177761078, -0.04031291604042053, 0.07398489117622375, 0.3237040042877197, -0.11546136438846588, -0.5625133514404297, 0.5046292543411255, 0.19673049449920654, -0.1968299001455307, 0.21763835847377777, -0.42641767859458923, -0.9505122303962708, -0.6008425951004028, 0.8912438154220581, 2.123775005340576, 0.16190636157989502, -1.7885795831680298, 1.8912570476531982, 0.5281420350074768, 2.1663239002227783, -1.6126594543457031, -0.300342857837677, 0.6916441321372986, 0.2100602239370346, -0.09565339237451553, -0.6831782460212708, 2.161972761154175, 3.7263545989990234, 0.38829532265663147, 1.851472020149231, -1.2320526838302612, 1.8250396251678467, 1.1962474584579468]], "betas": [[-1.1287270784378052, 1.9422041177749634, -0.0037313438951969147, 5.957525718258694e-05, -0.0007246990571729839, 0.0014383165398612618, 0.000682257057633251, 0.002265570918098092, -0.00033520147553645074, 0.0016018591122701764], [-2.916598081588745, 5.126800537109375, 0.00923924334347248, 0.00028705678414553404, -0.005999854765832424, 0.0022098510526120663, 0.002520749345421791, -0.0016635777428746223, 0.0017192525556311011, -0.0028337757103145123]], "transl": [[0.010334285907447338, 0.21126151084899902, -0.006185364443808794], [-0.05142330750823021, 0.14410144090652466, 0.019538406282663345]], "joints3d": [[[-37.90998840332031, 227.0016632080078, 4191.99169921875], [8.823600769042969, 317.55596923828125, 4165.98828125], [-108.91846466064453, 300.5575256347656, 4183.63330078125], [-22.60407829284668, 142.479736328125, 4235.24462890625], [132.58273315429688, 628.1409912109375, 3998.24853515625], [-223.25877380371094, 658.3943481445312, 4134.8349609375], [-9.67538833618164, 14.833114624023438, 4255.1416015625], [151.35498046875, 1009.012939453125, 4045.85302734375], [-222.7701873779297, 1038.2171630859375, 4183.640625], [-10.396141052246094, -36.660980224609375, 4251.4462890625], [218.60987854003906, 1072.2850341796875, 3959.823974609375], [-254.54150390625, 1109.1134033203125, 4085.551025390625], [4.085227966308594, -226.95826721191406, 4302.6123046875], [64.78150939941406, -141.90492248535156, 4265.88916015625], [-59.155723571777344, -138.19175720214844, 4317.34375], [-14.13253402709961, -293.05059814453125, 4254.8056640625], [137.14041137695312, -144.90696716308594, 4223.9345703125], [-136.43582153320312, -130.61021423339844, 4358.482421875], [70.87916564941406, 35.84648132324219, 4062.770263671875], [-251.00619506835938, 77.42147827148438, 4308.646484375], [-28.088027954101562, -176.60008239746094, 4083.466796875], [-302.42584228515625, -156.8066864013672, 4264.62841796875]], [[-777.6783447265625, 298.03118896484375, 4502.4453125], [-750.4227905273438, 384.22503662109375, 4515.03662109375], [-809.2583618164062, 359.0862731933594, 4448.01953125], [-783.5860595703125, 226.51361083984375, 4528.2451171875], [-699.6002807617188, 728.76025390625, 4386.9208984375], [-753.7388305664062, 720.4361572265625, 4511.4111328125], [-723.0404052734375, 126.11529541015625, 4495.47021484375], [-700.1407470703125, 1083.709228515625, 4443.20654296875], [-797.6253662109375, 1072.879638671875, 4503.86181640625], [-729.8898315429688, 86.2359619140625, 4497.046875], [-620.3492431640625, 1164.3631591796875, 4440.00390625], [-784.25146484375, 1135.391845703125, 4413.45263671875], [-745.2230224609375, -73.83001708984375, 4532.7099609375], [-725.181396484375, 10.407012939453125, 4562.14404296875], [-774.451416015625, -3.193206787109375, 4486.2158203125], [-745.25048828125, -156.27288818359375, 4512.138671875], [-686.0447998046875, -16.07733154296875, 4606.7333984375], [-779.9945068359375, -65.57357788085938, 4464.10693359375], [-616.4420776367188, 198.89999389648438, 4672.154296875], [-680.2044677734375, 131.9326171875, 4431.13427734375], [-593.6547241210938, 7.555419921875, 4580.98779296875], [-669.8609008789062, -91.98947143554688, 4457.193359375]]]}, {"global_orient": [[2.7727291584014893, 0.1876048445701599, -0.20037619769573212], [2.352881669998169, 0.06930935382843018, 0.9990794062614441]], "body_pose": [[2.7727291584014893, 0.1876048445701599, -0.20037619769573212, -0.09236431121826172, 0.04829394817352295, 0.35456326603889465, 0.1771387755870819, -0.07266692072153091, -0.09133031964302063, 0.16929824650287628, -0.04206758365035057, 0.06510945409536362, 0.503840982913971, -0.16054581105709076, -0.10055877268314362, 0.19471994042396545, 0.20741061866283417, 0.13893289864063263, -0.13818426430225372, -0.21572302281856537, 0.0022482213098555803, 0.09217794984579086, 0.3848472237586975, -0.19170792400836945, 0.20691049098968506, -0.17460136115550995, 0.19830571115016937, 0.2402309775352478, 0.03663615137338638, -0.00758688198402524, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.08408605307340622, -0.15198566019535065, -0.10212283581495285, -0.11589767038822174, -0.211954265832901, -0.33041778206825256, -0.32879650592803955, -0.00847476627677679, 0.390625, -0.00998995453119278, 0.08229850977659225, 0.04038279876112938, 0.12387485802173615, -0.8599118590354919, -0.9245402216911316, 0.17572085559368134, 0.1868283599615097, 0.787993311882019, -0.09123142063617706, 4.075799465179443, -0.9347058534622192, -0.3961178660392761, 2.190563201904297, -0.5300257205963135, 0.004872865974903107, -0.3049311637878418, 0.34045398235321045, -0.023703543469309807, 0.5585401654243469, -0.5596114993095398, -0.6874515414237976, -0.17376330494880676, -0.8385070562362671, -0.569648027420044, -0.3139459788799286, 1.9728001356124878], [2.352881669998169, 0.06930935382843018, 0.9990794062614441, 0.14764520525932312, -0.018323654308915138, -0.027959592640399933, 0.5784505605697632, -0.14165416359901428, 0.5569113492965698, 1.0082632303237915, 0.35159868001937866, 0.3287321925163269, 0.4745829999446869, -0.12783588469028473, 0.4094575047492981, 0.030414722859859467, 0.4530269205570221, -0.4067034423351288, -0.9943323135375977, -0.04673942178487778, 0.031638070940971375, 0.2378641813993454, 0.7268866300582886, -0.45623937249183655, 0.17993374168872833, -1.0219157934188843, 0.3121197819709778, 0.4746354818344116, 0.06365816295146942, -0.24257886409759521, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.4382043182849884, -0.3656992018222809, 0.22020560503005981, 0.14323851466178894, -0.11182890087366104, 0.16217854619026184, 0.3258248567581177, 0.06821750104427338, -0.6912950873374939, 0.5438053011894226, 0.08797265589237213, -0.0838581770658493, -0.09269159287214279, -0.4821944534778595, -0.8172652721405029, -0.8930795192718506, 0.8056269884109497, 2.1542673110961914, -0.232698455452919, 2.801265001296997, -2.5691652297973633, 0.7273245453834534, 1.9668866395950317, -1.7941837310791016, -0.48273709416389465, 0.7640500068664551, 0.25523731112480164, -0.35641971230506897, -0.0010337663115933537, 1.479349136352539, -1.7374569177627563, -0.260368674993515, -1.0719155073165894, -1.6745562553405762, 1.6507631540298462, 2.139190673828125]], "betas": [[-1.0828191041946411, 1.8546268939971924, -0.0036986456252634525, -0.0007076803594827652, -0.000815629493445158, 0.0010937334736809134, 0.00040355304372496903, 0.002190827624872327, -0.0005915534566156566, 0.0017378457123413682], [-2.9553232192993164, 4.87940788269043, 0.009319189935922623, 0.00023925358254928142, -0.00701804319396615, 0.0019159252988174558, 0.001965989824384451, -0.000352507340721786, 0.0017780548660084605, -0.0025449669919908047]], "transl": [[0.011636328883469105, 0.2119981199502945, -0.006529999431222677], [-0.05849036946892738, 0.15139354765415192, 0.021379150450229645]], "joints3d": [[[-28.111024856567383, 222.6829071044922, 4201.50439453125], [21.037506103515625, 312.6959533691406, 4176.42041015625], [-97.81874084472656, 298.1662902832031, 4194.005859375], [-14.635322570800781, 136.87820434570312, 4244.25537109375], [126.94900512695312, 630.4742431640625, 4009.883056640625], [-216.77691650390625, 655.2767333984375, 4149.9619140625], [-2.6232621669769287, 8.861053466796875, 4263.61181640625], [175.85012817382812, 1008.0098876953125, 4066.660400390625], [-220.7940673828125, 1036.41015625, 4193.4501953125], [-3.7340283393859863, -42.911109924316406, 4259.71826171875], [223.42771911621094, 1077.171630859375, 3971.98974609375], [-252.9879913330078, 1109.387939453125, 4096.5419921875], [10.487759590148926, -233.3241729736328, 4313.828125], [71.85950469970703, -148.61082458496094, 4275.86767578125], [-53.3499641418457, -144.05828857421875, 4327.1533203125], [-4.235560417175293, -300.19390869140625, 4265.986328125], [145.79144287109375, -155.4442596435547, 4236.10693359375], [-131.24658203125, -137.4246368408203, 4368.5419921875], [72.8305435180664, 23.645002365112305, 4075.372314453125], [-236.49130249023438, 73.45094299316406, 4308.74560546875], [-21.831552505493164, -191.3632049560547, 4096.052734375], [-290.07269287109375, -155.91574096679688, 4244.07275390625]], [[-786.7532348632812, 307.4459228515625, 4538.689453125], [-757.3621215820312, 393.92041015625, 4546.84619140625], [-823.6454467773438, 366.9107360839844, 4485.10302734375], [-790.784912109375, 236.80767822265625, 4567.23583984375], [-702.8611450195312, 725.8434448242188, 4398.37939453125], [-784.3729248046875, 728.4646606445312, 4539.96728515625], [-731.5699462890625, 137.94390869140625, 4530.986328125], [-705.024658203125, 1075.0025634765625, 4470.6162109375], [-829.223388671875, 1078.14990234375, 4537.35302734375], [-735.8722534179688, 97.54694366455078, 4532.97509765625], [-629.219482421875, 1158.7906494140625, 4467.52978515625], [-814.4125366210938, 1143.4678955078125, 4449.74755859375], [-745.0510864257812, -64.33070373535156, 4565.560546875], [-727.0562133789062, 19.912567138671875, 4596.9375], [-777.5374145507812, 5.895432472229004, 4520.20654296875], [-738.862060546875, -147.0640869140625, 4551.68359375], [-683.8314208984375, -10.455045700073242, 4635.43505859375], [-769.2735595703125, -56.84507369995117, 4498.87451171875], [-557.7852783203125, 176.32249450683594, 4697.59765625], [-664.0532836914062, 136.2837371826172, 4465.0302734375], [-562.2516479492188, -12.101296424865723, 4600.79638671875], [-637.44140625, -83.374267578125, 4501.234375]]]}, {"global_orient": [[2.802102565765381, 0.1660439372062683, -0.24652515351772308], [2.349034070968628, 0.09977748245000839, 0.937207818031311]], "body_pose": [[2.802102565765381, 0.1660439372062683, -0.24652515351772308, -0.08014636486768723, 0.009794819168746471, 0.3133446276187897, 0.16711395978927612, -0.06966736912727356, -0.1282370388507843, 0.16373489797115326, -0.05302559956908226, 0.06121798977255821, 0.47762343287467957, -0.24988165497779846, -0.07734382897615433, 0.21910537779331207, 0.2352534383535385, 0.13739316165447235, -0.13631299138069153, -0.19660083949565887, 0.01180214248597622, 0.18593500554561615, 0.3835766613483429, -0.17576207220554352, 0.16258318722248077, -0.1487189084291458, 0.24105727672576904, 0.22167246043682098, 0.03373296558856964, -0.030826691538095474, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.12856614589691162, -0.09038498997688293, -0.1418595314025879, -0.13908082246780396, -0.1761513352394104, -0.3064599931240082, -0.32859721779823303, -0.08727520704269409, 0.397710919380188, -0.09252119064331055, 0.06381812691688538, 0.1058163195848465, 0.1488192230463028, -0.8212491869926453, -0.971575140953064, 0.25976213812828064, 0.10973378270864487, 0.8088377118110657, 0.009737683460116386, 4.108956336975098, -0.7793620228767395, -0.3571925163269043, 2.1366114616394043, -0.6634038090705872, 0.029650133103132248, -0.3396238386631012, 0.33239978551864624, -0.04201848432421684, 0.5665478110313416, -0.22541362047195435, -0.5707536339759827, -0.20329619944095612, -0.7164313197135925, -0.8737978339195251, -0.04457178711891174, 1.3975110054016113], [2.349034070968628, 0.09977748245000839, 0.937207818031311, 0.20912374556064606, -0.024088189005851746, 0.03248220309615135, 0.5510368347167969, -0.05764841288328171, 0.5712739825248718, 0.9840413331985474, 0.12839578092098236, 0.3187602460384369, 0.3925487697124481, -0.057880282402038574, 0.3738414943218231, 0.04954256862401962, 0.3305266797542572, -0.34069934487342834, -0.8513702154159546, 0.0460217148065567, 0.03906730189919472, 0.2648716866970062, 0.6722936630249023, -0.39155930280685425, 0.16963905096054077, -0.7350062131881714, 0.2656633257865906, 0.4662511348724365, 0.03304211050271988, -0.23201322555541992, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.31471824645996094, -0.3823840916156769, 0.30047762393951416, 0.0857200101017952, -0.09290066361427307, 0.12253919243812561, 0.29077276587486267, 0.09048826992511749, -0.8136065006256104, 0.32485485076904297, 0.21909955143928528, -0.15521499514579773, 0.3206048607826233, -0.37634390592575073, -1.3606863021850586, -0.7027212381362915, 0.5663633346557617, 2.38066029548645, -0.13018986582756042, 3.16497540473938, -1.7015656232833862, 0.15638749301433563, 2.7288849353790283, -0.5495736598968506, 0.2507422864437103, 0.6435161828994751, 0.2554576098918915, 0.5949195027351379, -1.2418763637542725, 2.0830440521240234, 2.848039150238037, 0.4071195125579834, 2.640765428543091, -0.9784827828407288, 2.2352817058563232, 1.2710868120193481]], "betas": [[-1.0318100452423096, 1.7364609241485596, -0.004081843886524439, -0.0014850719599053264, -0.0010998309589922428, 0.0011512753553688526, 0.00038591973134316504, 0.0018490036018192768, -0.0006568132084794343, 0.0015280346851795912], [-2.9345133304595947, 4.700604438781738, 0.009485509246587753, 0.0006776062655262649, -0.007713241036981344, 0.002378270495682955, 0.001813272712752223, -0.00025743318838067353, 0.0024977398570626974, -0.000986807863228023]], "transl": [[0.012699817307293415, 0.2109348475933075, -0.011577188968658447], [-0.04782697930932045, 0.14223439991474152, 0.027970677241683006]], "joints3d": [[[-19.914581298828125, 216.9109649658203, 4184.103515625], [31.007143020629883, 306.66259765625, 4159.42626953125], [-88.5919418334961, 294.35455322265625, 4180.310546875], [-7.041086673736572, 129.30712890625, 4225.11767578125], [124.34037780761719, 631.6746826171875, 3999.90283203125], [-213.52621459960938, 650.8184814453125, 4149.9677734375], [2.996670961380005, 0.5278713703155518, 4241.45703125], [197.40689086914062, 1005.5626220703125, 4058.381591796875], [-221.87840270996094, 1029.5633544921875, 4214.22265625], [0.3052138686180115, -51.438499450683594, 4236.265625], [234.17872619628906, 1083.9820556640625, 3965.66796875], [-251.90576171875, 1103.859619140625, 4117.0732421875], [16.376401901245117, -243.51470947265625, 4287.8251953125], [77.12251281738281, -157.98519897460938, 4248.833984375], [-47.92112350463867, -154.2310028076172, 4304.1826171875], [4.331010341644287, -306.7225341796875, 4234.7431640625], [152.251220703125, -165.41122436523438, 4210.0546875], [-121.64167785644531, -145.81655883789062, 4353.634765625], [83.77631378173828, 22.9268798828125, 4057.568603515625], [-212.2278594970703, 78.87996673583984, 4327.90966796875], [-13.828452110290527, -192.2355194091797, 4065.409423828125], [-295.8451232910156, -136.3974609375, 4247.0654296875]], [[-783.241943359375, 292.0923156738281, 4518.5068359375], [-752.5009155273438, 378.8772277832031, 4522.62939453125], [-822.60693359375, 349.7915954589844, 4463.92724609375], [-786.7582397460938, 222.4076690673828, 4550.2412109375], [-703.6788940429688, 717.3878173828125, 4391.7265625], [-779.7830810546875, 711.8687133789062, 4501.19970703125], [-741.9352416992188, 118.52864074707031, 4508.5625], [-701.8551635742188, 1067.93115234375, 4452.76123046875], [-815.6162109375, 1061.9171142578125, 4508.03662109375], [-742.9791259765625, 77.57327270507812, 4510.05859375], [-624.021240234375, 1149.876953125, 4448.6513671875], [-781.6528930664062, 1125.6336669921875, 4424.56591796875], [-739.0935668945312, -86.035888671875, 4540.08447265625], [-718.6817016601562, -1.284548282623291, 4570.0654296875], [-782.7039794921875, -16.66403579711914, 4502.35693359375], [-730.983154296875, -164.18264770507812, 4511.21142578125], [-668.8107299804688, -28.761425018310547, 4603.2763671875], [-770.7753295898438, -80.48114776611328, 4484.28466796875], [-682.8026123046875, 200.94786071777344, 4642.24365234375], [-721.0216064453125, 134.93350219726562, 4460.3671875], [-627.218994140625, 19.363365173339844, 4548.51318359375], [-693.6876220703125, -87.3216781616211, 4459.04052734375]]]}, {"global_orient": [[2.7800066471099854, 0.12399575114250183, -0.33978867530822754], [2.373413324356079, 0.07927420735359192, 0.9333925843238831]], "body_pose": [[2.7800066471099854, 0.12399575114250183, -0.33978867530822754, -0.0690651461482048, -0.026196492835879326, 0.2332303524017334, 0.0990692526102066, -0.07587486505508423, -0.20549888908863068, 0.12218762934207916, -0.07331030815839767, 0.07687072455883026, 0.5503822565078735, -0.30538201332092285, -0.05190693587064743, 0.3085174262523651, 0.2705385982990265, 0.16679440438747406, -0.11679195612668991, -0.18147844076156616, -0.011000087484717369, 0.14462082087993622, 0.33160877227783203, -0.16896460950374603, 0.14013701677322388, -0.13963215053081512, 0.2507113814353943, 0.23943568766117096, 0.03303670510649681, -0.03548796474933624, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.09510236978530884, -0.051891934126615524, -0.19568683207035065, -0.14852222800254822, -0.12919865548610687, -0.2980925440788269, -0.3255089223384857, -0.15223261713981628, 0.36385709047317505, -0.055181462317705154, 0.10864956676959991, 0.10375601798295975, 0.12460023164749146, -0.8418145179748535, -1.0169404745101929, 0.22005437314510345, 0.06508544832468033, 0.7947808504104614, -0.02844741754233837, -2.041980504989624, 0.431808739900589, -0.40146324038505554, 2.0788562297821045, -0.6657083034515381, 0.021988963708281517, -0.37287724018096924, 0.32829731702804565, -0.07278900593519211, 0.8023099899291992, 0.045008156448602676, -0.6015085577964783, -0.04215315729379654, -0.8635037541389465, -0.8093534708023071, -0.19080154597759247, 0.6734189987182617], [2.373413324356079, 0.07927420735359192, 0.9333925843238831, 0.19281508028507233, -0.05727057531476021, 0.000843414687551558, 0.5509992241859436, -0.055798180401325226, 0.5158207416534424, 0.8906455636024475, 0.1298888623714447, 0.3969906270503998, 0.4312986731529236, -0.04377610608935356, 0.3830357491970062, 0.03428664430975914, 0.42702198028564453, -0.30408796668052673, -0.8378750681877136, -0.10000552237033844, -0.04367351904511452, 0.23321188986301422, 0.7668768763542175, -0.4183845520019531, 0.07466641068458557, -0.7062673568725586, 0.281742125749588, 0.49960291385650635, 0.019264135509729385, -0.20726735889911652, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.4062078893184662, -0.19259381294250488, 0.3266492784023285, 0.13493120670318604, -0.04373975843191147, 0.16440130770206451, 0.20503421127796173, 0.0661611407995224, -0.668120265007019, 0.4882480800151825, -0.1531243920326233, -0.20005272328853607, 0.2456296682357788, -0.7934490442276001, -1.68468177318573, -0.5295124053955078, 0.5504870414733887, 2.225348949432373, -0.3208119571208954, 3.505333662033081, -1.3012250661849976, 0.29968005418777466, 2.720378875732422, -0.4956199824810028, -0.9024253487586975, -0.0727619081735611, -0.3114381432533264, 0.5334165096282959, -0.9070850014686584, 2.4271557331085205, 0.19240203499794006, 0.9306023716926575, 1.951217770576477, -0.6708903908729553, 2.302689552307129, -0.6329848170280457]], "betas": [[-1.0365064144134521, 1.9174041748046875, -0.0035679300781339407, -0.0030136769637465477, -0.001142476568929851, 0.0006230182480067015, 0.0002966466418001801, 0.0016469726106151938, -0.0006634899182245135, 0.0013630965258926153], [-3.026963710784912, 4.745744705200195, 0.005087352357804775, 0.0009910014923661947, -0.005534266587346792, 0.0022354687098413706, 0.00024332919565495104, 0.003709192853420973, 0.0021859172265976667, 0.00010881643538596109]], "transl": [[0.02281331829726696, 0.20888863503932953, -0.016716590151190758], [-0.030266201123595238, 0.1438700407743454, 0.0360008105635643]], "joints3d": [[[1.9930022954940796, 209.77053833007812, 4164.658203125], [54.10411834716797, 296.8999938964844, 4135.7646484375], [-63.005409240722656, 289.6441650390625, 4163.73193359375], [13.778489112854004, 122.69122314453125, 4205.73388671875], [121.43047332763672, 625.3983764648438, 3966.348876953125], [-210.21775817871094, 637.74072265625, 4118.927734375], [19.13735580444336, -5.531070232391357, 4229.72705078125], [217.20535278320312, 992.9009399414062, 4038.709716796875], [-217.41258239746094, 1016.4307250976562, 4189.716796875], [14.857358932495117, -57.295005798339844, 4227.25927734375], [235.52439880371094, 1074.650146484375, 3943.33154296875], [-251.68960571289062, 1090.099609375, 4093.487548828125], [27.496646881103516, -248.09310913085938, 4281.15673828125], [88.02658081054688, -165.5082550048828, 4237.14697265625], [-31.68143081665039, -156.38815307617188, 4299.8046875], [16.074810028076172, -313.4744567871094, 4229.8466796875], [161.5229034423828, -176.64138793945312, 4197.3681640625], [-97.60426330566406, -146.70001220703125, 4358.2080078125], [83.84294891357422, 9.533705711364746, 4045.6796875], [-184.11390686035156, 81.31427764892578, 4350.298828125], [-6.798759937286377, -209.14511108398438, 4051.019775390625], [-303.09478759765625, -124.18006134033203, 4289.0537109375]], [[-796.963134765625, 307.8564758300781, 4591.33056640625], [-765.8195190429688, 393.93218994140625, 4597.76513671875], [-836.0685424804688, 367.1304626464844, 4538.98486328125], [-800.363037109375, 237.7327880859375, 4620.40234375], [-717.8928833007812, 729.8378295898438, 4463.7919921875], [-803.1436157226562, 729.1694946289062, 4570.982421875], [-768.64794921875, 130.31686401367188, 4577.732421875], [-715.3076171875, 1076.2076416015625, 4535.24462890625], [-834.876708984375, 1077.4112548828125, 4576.32763671875], [-771.4979858398438, 89.93534088134766, 4580.58251953125], [-636.8080444335938, 1156.5880126953125, 4536.90380859375], [-787.2222290039062, 1132.73828125, 4494.6005859375], [-772.0860595703125, -72.96566009521484, 4608.0966796875], [-743.7276611328125, 9.622179985046387, 4635.3134765625], [-816.2638549804688, -1.2740256786346436, 4577.94970703125], [-771.1732177734375, -152.90359497070312, 4584.173828125], [-692.8121948242188, -22.802597045898438, 4660.26904296875], [-820.7659912109375, -64.11466979980469, 4556.2392578125], [-745.136962890625, 200.76760864257812, 4625.83056640625], [-771.1732788085938, 149.0361785888672, 4524.5810546875], [-695.4266967773438, 14.111542701721191, 4542.5927734375], [-728.3303833007812, -69.0057601928711, 4537.7783203125]]]}, {"global_orient": [[2.805304527282715, 0.10420092940330505, -0.4057263731956482], [2.4940686225891113, 0.16650904715061188, 0.4390529692173004]], "body_pose": [[2.805304527282715, 0.10420092940330505, -0.4057263731956482, -0.1359127163887024, -0.060727331787347794, 0.18091577291488647, -0.07352349907159805, -0.08815739303827286, -0.2410665601491928, 0.20391955971717834, -0.08211934566497803, 0.07950671017169952, 0.5949393510818481, -0.28385812044143677, 0.01082736998796463, 0.43607303500175476, 0.18749435245990753, 0.18223731219768524, -0.14182747900485992, -0.14526191353797913, -0.006489355117082596, 0.0627027228474617, 0.3286355137825012, -0.23622038960456848, 0.17666976153850555, -0.15625548362731934, 0.233201801776886, 0.1830642968416214, 0.03923080861568451, -0.040017545223236084, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.06456691771745682, -0.010108942165970802, -0.23978786170482635, -0.1613503098487854, -0.15835553407669067, -0.26234298944473267, -0.258514404296875, -0.13248522579669952, 0.3196427822113037, -0.06708770990371704, 0.09518555551767349, 0.14378172159194946, 0.09481598436832428, -0.8500020503997803, -1.0537340641021729, 0.19780103862285614, 0.06225590407848358, 0.9201053977012634, -0.004291476681828499, 4.066532135009766, -0.885532021522522, -0.40909022092819214, 2.0305585861206055, -0.7321093082427979, -0.0020382713992148638, -0.2998806834220886, 0.36970284581184387, -0.08921568095684052, 0.8490927815437317, 0.18950599431991577, -0.5292268395423889, -0.0515318363904953, -0.8589229583740234, -0.8396089673042297, -0.1052309200167656, 0.45200785994529724], [2.4940686225891113, 0.16650904715061188, 0.4390529692173004, 0.19690929353237152, 0.19298039376735687, 0.11840333044528961, 0.573140561580658, 0.11629566550254822, 0.4773736596107483, 0.6668389439582825, 0.04196028783917427, 0.28628411889076233, 0.446887344121933, 0.014074962586164474, 0.35841888189315796, 0.06067813187837601, 0.6761400103569031, -0.2780079245567322, -0.5128841400146484, -0.10520049184560776, -0.0531141571700573, 0.18369469046592712, 0.8641071319580078, -0.4469718337059021, 0.34094634652137756, -0.913054347038269, 0.3471378684043884, 0.5491788387298584, -0.13413909077644348, -0.13934336602687836, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.4629110097885132, 0.135844424366951, 0.4200868010520935, -0.02497239224612713, 0.33524608612060547, 0.04295557364821434, -0.330232173204422, -0.7059192061424255, -0.6580314636230469, 0.43564698100090027, -0.3296992778778076, -0.2845457196235657, 0.22161506116390228, -1.1638094186782837, -1.566794753074646, 0.7039769291877747, 0.9522503614425659, 2.3460779190063477, 0.15775847434997559, 3.990434169769287, -1.0842596292495728, 0.7995186448097229, 2.057727813720703, -1.6419025659561157, 0.6925469636917114, 0.7016911506652832, 4.06837272644043, 0.21984772384166718, 1.0251178741455078, 2.3783316612243652, 0.0594148188829422, 0.4193033277988434, 2.6214215755462646, 0.6265990734100342, 2.0166444778442383, 1.036186933517456]], "betas": [[-1.1983574628829956, 1.8120635747909546, -0.0025155609473586082, -0.002428343752399087, -0.0013960410142317414, 0.0006092242547310889, 0.00017369781562592834, 0.0014275027206167579, -0.0004359885351732373, 0.0012145403306931257], [-2.795419216156006, 5.161764144897461, 0.004364670719951391, 0.002134710783138871, -0.004284221678972244, 0.0033208332024514675, 0.00031215534545481205, 0.00581723265349865, 0.002132067922502756, -0.0001227007305715233]], "transl": [[0.03139885142445564, 0.21139603853225708, 0.0021157606970518827], [-0.021085621789097786, 0.14050646126270294, 0.03491997718811035]], "joints3d": [[[20.12757682800293, 209.71475219726562, 4107.13916015625], [73.5632553100586, 295.8224792480469, 4078.43310546875], [-43.02311325073242, 290.69049072265625, 4111.1474609375], [31.165956497192383, 122.07733154296875, 4144.69287109375], [114.67093658447266, 618.0223388671875, 3898.565185546875], [-211.36703491210938, 617.4230346679688, 4031.55419921875], [30.34678077697754, -6.398151397705078, 4155.4189453125], [229.30288696289062, 976.6851196289062, 3959.969970703125], [-211.06674194335938, 992.6328125, 4093.045654296875], [23.792556762695312, -57.05703353881836, 4148.2685546875], [237.76220703125, 1051.845947265625, 3859.751220703125], [-259.82379150390625, 1066.255615234375, 4005.324462890625], [36.11448287963867, -248.1038055419922, 4196.6171875], [95.90959930419922, -165.35330200195312, 4154.1083984375], [-22.000375747680664, -157.45867919921875, 4218.18310546875], [28.90192222595215, -311.5427551269531, 4143.6953125], [166.96910095214844, -179.1175079345703, 4112.15771484375], [-87.760009765625, -154.47891235351562, 4276.19873046875], [83.31964111328125, 6.7740278244018555, 3968.219482421875], [-151.46197509765625, 78.26302337646484, 4273.955078125], [-1.1677706241607666, -210.75953674316406, 3981.966552734375], [-292.61669921875, -107.8631362915039, 4209.78466796875]], [[-806.0465087890625, 302.7651672363281, 4670.99658203125], [-772.069580078125, 387.4103698730469, 4663.14208984375], [-857.8690795898438, 365.0326232910156, 4636.70703125], [-801.6468505859375, 231.9439697265625, 4700.828125], [-729.9073486328125, 735.5968627929688, 4533.51708984375], [-828.4921875, 737.781494140625, 4645.00244140625], [-795.9187622070312, 111.20162200927734, 4678.861328125], [-727.6815795898438, 1088.534912109375, 4617.8564453125], [-865.1723022460938, 1094.667724609375, 4642.6611328125], [-794.8189086914062, 70.55168151855469, 4683.29052734375], [-646.47314453125, 1169.0899658203125, 4623.15966796875], [-843.4033203125, 1173.8157958984375, 4566.791015625], [-781.5999755859375, -94.67536926269531, 4688.7451171875], [-742.3485717773438, -12.79629135131836, 4704.8955078125], [-834.1770629882812, -21.72071647644043, 4696.873046875], [-792.2603149414062, -175.75885009765625, 4663.52587890625], [-686.6092529296875, -43.05870056152344, 4721.4072265625], [-844.2548828125, -77.84945678710938, 4732.37158203125], [-746.431640625, 169.5784454345703, 4634.84521484375], [-813.38330078125, 142.939453125, 4697.53564453125], [-719.7572631835938, -12.485513687133789, 4523.02734375], [-727.2615356445312, -59.973785400390625, 4640.2587890625]]]}, {"global_orient": [[2.763634204864502, 0.08396100997924805, -0.5417796969413757], [2.519277572631836, 0.19807226955890656, 0.43686285614967346]], "body_pose": [[2.763634204864502, 0.08396100997924805, -0.5417796969413757, -0.07819411903619766, -0.0588374026119709, 0.14392055571079254, -0.10609166324138641, -0.10893578827381134, -0.29192644357681274, 0.2116003930568695, -0.08739987015724182, 0.09099993109703064, 0.6209052205085754, -0.27933773398399353, 0.010373283177614212, 0.45821452140808105, 0.10226481407880783, 0.1962956339120865, -0.14791187644004822, -0.12342631071805954, 0.0023952946066856384, -0.025156376883387566, 0.34940001368522644, -0.241996631026268, 0.18122227489948273, -0.36575812101364136, 0.278344064950943, 0.19803594052791595, 0.04854488745331764, -0.04704128950834274, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.0006291516474448144, 0.049693889915943146, -0.2991306781768799, -0.18238168954849243, -0.1270352154970169, -0.22758591175079346, -0.26360052824020386, -0.1445240080356598, 0.33078375458717346, -0.009633947163820267, 0.11077199131250381, 0.14154866337776184, 0.08392465859651566, -0.8017011880874634, -1.0734972953796387, 0.1846575289964676, 0.018019236624240875, 0.9457582235336304, 0.041178300976753235, 4.064852714538574, -0.8685998916625977, -0.371970534324646, 1.92302668094635, -0.6975474953651428, 0.05094084516167641, -0.366387277841568, 0.4244436025619507, -0.21195974946022034, 1.11573326587677, 0.237223818898201, -0.5749343633651733, -0.010473585687577724, -0.9375928640365601, -0.7690744400024414, -0.0010107402922585607, 0.18706673383712769], [2.519277572631836, 0.19807226955890656, 0.43686285614967346, 0.10887552052736282, 0.13936488330364227, 0.12625902891159058, 0.4956653118133545, 0.10433685034513474, 0.5144369602203369, 0.833781361579895, 0.00556032732129097, 0.2721017003059387, 0.49387866258621216, 0.13977384567260742, 0.35097822546958923, 0.11449965089559555, 0.4208867847919464, -0.3286145329475403, -0.6081087589263916, 0.12200819700956345, 0.03165711835026741, 0.2847573459148407, 0.7670180201530457, -0.36893966794013977, 0.4379641115665436, -0.7604070901870728, 0.39508137106895447, 0.45942699909210205, -0.04788324609398842, -0.1635202020406723, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2806353271007538, -0.17848031222820282, 0.42018651962280273, 0.015594997443258762, 0.05110660195350647, 0.03421028330922127, 0.058815136551856995, 0.20428459346294403, -0.6076915264129639, 0.1688803732395172, -0.09418471157550812, -0.29945108294487, 0.22414271533489227, -0.56236732006073, -1.6068304777145386, -0.46460890769958496, 0.7735306620597839, 2.1338915824890137, -0.20352086424827576, -1.6395615339279175, 0.5357084274291992, 0.5548898577690125, 1.6772434711456299, -0.7189559936523438, -0.032158151268959045, 0.44303789734840393, 3.762479543685913, 0.43961992859840393, 0.09658723324537277, 2.770845651626587, 0.1302933543920517, -1.417243242263794, 1.5364220142364502, 1.0907124280929565, 1.3659857511520386, 0.4416957497596741]], "betas": [[-1.2536190748214722, 2.1823501586914062, -0.0024503550957888365, -0.0021500710863620043, -0.0009777728701010346, 0.0009296234347857535, 0.00017727696103975177, 0.0017497674562036991, -0.00011809233546955511, 0.0011962023563683033], [-2.458601713180542, 3.660825490951538, 0.013007554225623608, 0.0022981951478868723, -0.008199169300496578, 0.0011205399641767144, 0.0012016319669783115, 0.004111669026315212, 0.002485209610313177, 0.001088982098735869]], "transl": [[0.03745172917842865, 0.20491190254688263, -2.1762803953606635e-05], [-0.02886994555592537, 0.14331325888633728, 0.040598317980766296]], "joints3d": [[[37.398651123046875, 204.33433532714844, 4083.32080078125], [89.0972671508789, 287.9723815917969, 4049.2451171875], [-21.1595516204834, 286.6695861816406, 4091.86572265625], [48.84261703491211, 117.91096496582031, 4119.6767578125], [116.42169189453125, 618.561279296875, 3876.4287109375], [-210.0767822265625, 606.6319580078125, 4020.073974609375], [43.771060943603516, -10.590126991271973, 4132.947265625], [244.91671752929688, 971.8262329101562, 3948.1611328125], [-197.6745147705078, 985.3162231445312, 4061.42138671875], [35.32783508300781, -60.522918701171875, 4128.77978515625], [244.04904174804688, 1045.1964111328125, 3846.560791015625], [-276.03955078125, 1057.3157958984375, 3997.60302734375], [42.28077697753906, -249.3054962158203, 4177.984375], [101.65494537353516, -169.8767547607422, 4131.97412109375], [-8.623275756835938, -156.5278778076172, 4201.64892578125], [38.06074142456055, -315.92303466796875, 4127.45556640625], [168.98056030273438, -190.0608673095703, 4089.248046875], [-68.78173065185547, -149.8219451904297, 4263.12548828125], [95.25035095214844, -1.7225059270858765, 3942.257080078125], [-111.39907836914062, 87.73799133300781, 4259.52001953125], [1.6217490434646606, -215.45494079589844, 3956.602783203125], [-288.95343017578125, -67.14213562011719, 4201.6796875]], [[-808.596435546875, 304.0316467285156, 4697.775390625], [-769.4451293945312, 391.1578063964844, 4686.73291015625], [-866.4573364257812, 364.5045471191406, 4657.34326171875], [-805.1524658203125, 232.75355529785156, 4737.37744140625], [-724.7218627929688, 723.3527221679688, 4542.38916015625], [-822.021728515625, 728.4693603515625, 4659.017578125], [-792.6940307617188, 117.71862030029297, 4697.82421875], [-733.8831176757812, 1075.8414306640625, 4620.00732421875], [-874.9635009765625, 1082.5284423828125, 4664.58447265625], [-791.3867797851562, 73.56904602050781, 4695.29736328125], [-655.5452270507812, 1161.3736572265625, 4629.23583984375], [-868.34375, 1170.7298583984375, 4592.64990234375], [-781.3982543945312, -101.64312744140625, 4709.0947265625], [-739.4301147460938, -16.83323097229004, 4733.28466796875], [-840.2488403320312, -26.607677459716797, 4698.142578125], [-791.1917724609375, -172.54258728027344, 4667.4482421875], [-676.8556518554688, -44.08530807495117, 4753.52197265625], [-860.1996459960938, -91.79137420654297, 4670.650390625], [-727.8720092773438, 187.19114685058594, 4748.248046875], [-796.0077514648438, 123.77310943603516, 4640.87109375], [-634.3377075195312, 150.86270141601562, 4555.689453125], [-650.4830932617188, 0.062212467193603516, 4516.205078125]]]}, {"global_orient": [[2.7116949558258057, 0.053245678544044495, -0.7016792297363281], [2.576704740524292, 0.2396824061870575, 0.41543546319007874]], "body_pose": [[2.7116949558258057, 0.053245678544044495, -0.7016792297363281, -0.022339122369885445, -0.033823076635599136, 0.1200309619307518, -0.1585865020751953, -0.1206165999174118, -0.33278095722198486, 0.22095425426959991, -0.09850326180458069, 0.07153697311878204, 0.5935268998146057, -0.2350482940673828, 0.013039856217801571, 0.5287785530090332, 0.025065042078495026, 0.17950882017612457, -0.126256063580513, -0.06258314102888107, 0.007458078674972057, -0.078774094581604, 0.30107489228248596, -0.2389775514602661, 0.17776824533939362, -0.3654785454273224, 0.2335972785949707, 0.1589794158935547, 0.019133824855089188, -0.07108068466186523, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.002386027481406927, 0.09750020503997803, -0.3140898048877716, -0.19827984273433685, -0.13351856172084808, -0.18271306157112122, -0.22167284786701202, -0.1398400366306305, 0.3351312577724457, -0.019072275608778, 0.13112501800060272, 0.1774798482656479, 0.10362929105758667, -0.74831223487854, -1.1044162511825562, 0.28359952569007874, 0.10862838476896286, 1.0019450187683105, 0.10948529839515686, 4.004561424255371, -0.9623181223869324, -0.17020997405052185, 1.7549700736999512, -0.6373965740203857, -0.0026424957904964685, -0.32676318287849426, 0.3016814887523651, -0.1342942863702774, 1.0754197835922241, 0.3376089930534363, -0.5505456328392029, -0.048324670642614365, -0.9878065586090088, -0.7119312882423401, 0.5189458727836609, -0.09689997136592865], [2.576704740524292, 0.2396824061870575, 0.41543546319007874, 0.053074296563863754, 0.11496155709028244, 0.1415846049785614, 0.4589218497276306, 0.058090999722480774, 0.4435479938983917, 0.7498047351837158, -0.0038706492632627487, 0.27288323640823364, 0.4982791543006897, 0.17435647547245026, 0.3345128893852234, 0.017552321776747704, 0.2243877798318863, -0.27179664373397827, -0.4995430111885071, 0.11180233955383301, 0.012327851727604866, 0.29547157883644104, 0.7461315393447876, -0.338101327419281, 0.5650407075881958, -0.5628613233566284, 0.33470332622528076, 0.4030919671058655, -0.01782006211578846, -0.10461477190256119, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.12249982357025146, -0.2779465913772583, 0.410370796918869, -0.004386619199067354, 0.007328676525503397, -0.01913801208138466, 0.08741085976362228, 0.2758057117462158, -0.4592649042606354, -0.09141108393669128, 0.06623423099517822, -0.3187175393104553, 0.30032211542129517, -0.43872371315956116, -1.5733444690704346, -0.42062854766845703, 0.826052188873291, 1.8738256692886353, -0.058238521218299866, -1.3883512020111084, 0.449751615524292, 0.502314567565918, 1.2417296171188354, -0.7035936713218689, -0.22365504503250122, 0.5771217942237854, 3.6837430000305176, 0.39349380135536194, 0.2698420286178589, 2.7428464889526367, 0.30692076683044434, -1.4137380123138428, 1.7209357023239136, 0.8094377517700195, 1.4315675497055054, 0.6039128303527832]], "betas": [[-1.2244236469268799, 2.1186864376068115, -0.0020590273197740316, -0.00225982372649014, -0.0012830061605200171, 0.001220563892275095, 0.00024499022401869297, 0.0016632936894893646, 3.330065737827681e-05, 0.0011262436164543033], [-2.097823143005371, 3.1585071086883545, 0.01723446324467659, 0.003552396781742573, -0.007399129681289196, 0.0028348045889288187, 0.0029771211557090282, 0.0017392955487594008, 0.002012375509366393, 0.0016671712510287762]], "transl": [[0.03734203428030014, 0.20328359305858612, -0.0009437711560167372], [-0.023820072412490845, 0.1411481648683548, 0.03812972828745842]], "joints3d": [[[47.06731414794922, 200.76609802246094, 4064.65283203125], [97.49344635009766, 281.6651916503906, 4022.22021484375], [-7.744587421417236, 285.517822265625, 4077.1181640625], [59.88677215576172, 114.73485565185547, 4102.54248046875], [119.46991729736328, 617.4434204101562, 3859.070556640625], [-212.3428497314453, 597.558837890625, 4013.847900390625], [53.43925857543945, -13.572492599487305, 4117.98388671875], [255.79408264160156, 969.1557006835938, 3925.524169921875], [-186.37704467773438, 976.683837890625, 4047.66259765625], [43.252464294433594, -63.41218185424805, 4114.13232421875], [242.5552520751953, 1039.072265625, 3822.115478515625], [-278.21270751953125, 1048.00146484375, 4003.64501953125], [56.84991455078125, -251.93869018554688, 4165.24462890625], [110.86416625976562, -172.6562957763672, 4112.0927734375], [7.3646721839904785, -159.00015258789062, 4192.720703125], [51.183597564697266, -318.54931640625, 4114.9384765625], [173.65525817871094, -196.3972930908203, 4063.94775390625], [-47.49397277832031, -152.03147888183594, 4259.453125], [96.14061737060547, -5.317785739898682, 3922.166015625], [-81.32122039794922, 87.09281921386719, 4250.7373046875], [8.30968189239502, -221.43548583984375, 3941.836669921875], [-265.3516845703125, -29.192842483520508, 4143.0654296875]], [[-807.43603515625, 289.8028869628906, 4709.1435546875], [-768.5926513671875, 379.8713684082031, 4698.83984375], [-870.0161743164062, 350.75653076171875, 4670.3173828125], [-801.8182373046875, 215.57839965820312, 4750.91796875], [-725.4019165039062, 714.4865112304688, 4554.3828125], [-849.4188232421875, 719.7686157226562, 4667.82568359375], [-790.067626953125, 97.2509536743164, 4714.77392578125], [-737.7156982421875, 1072.828125, 4633.01025390625], [-889.0794677734375, 1082.1131591796875, 4672.4326171875], [-786.2991333007812, 51.51701354980469, 4708.5302734375], [-657.1984252929688, 1159.95751953125, 4642.27099609375], [-892.7877807617188, 1176.5992431640625, 4603.6005859375], [-778.5999755859375, -130.21046447753906, 4716.67236328125], [-731.8617553710938, -44.799861907958984, 4744.53369140625], [-840.07861328125, -52.17552185058594, 4706.900390625], [-789.7911376953125, -192.05784606933594, 4662.5869140625], [-664.7294311523438, -69.62466430664062, 4765.4921875], [-870.6124267578125, -111.51712799072266, 4667.6005859375], [-717.4459228515625, 163.65011596679688, 4791.541015625], [-810.50439453125, 109.13540649414062, 4634.85107421875], [-657.7385864257812, 204.43685913085938, 4581.71875], [-652.3258666992188, 64.3829116821289, 4470.861328125]]]}, {"global_orient": [[2.660855293273926, 0.042816706001758575, -0.7691256403923035], [2.6409213542938232, 0.2717086970806122, -0.07721929997205734]], "body_pose": [[2.660855293273926, 0.042816706001758575, -0.7691256403923035, -0.00037240481469780207, -0.006655714474618435, 0.10680331289768219, -0.1910894513130188, -0.14947812259197235, -0.3543512225151062, 0.23172368109226227, -0.12413053959608078, 0.08111976832151413, 0.5978977680206299, -0.25592344999313354, 0.02089044637978077, 0.5777834057807922, 0.007879361510276794, 0.1567692756652832, -0.13895638287067413, -0.039666831493377686, 0.00241295387968421, -0.08738109469413757, 0.2369067370891571, -0.261491984128952, 0.1787830889225006, -0.3494083285331726, 0.20114952325820923, 0.17513614892959595, 0.010300799272954464, -0.088502436876297, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.002396135590970516, 0.12385278940200806, -0.3342461884021759, -0.19888249039649963, -0.09746067225933075, -0.11171146482229233, -0.1900838166475296, -0.1679999977350235, 0.2743796408176422, 0.0015337293734773993, 0.14068008959293365, 0.1574031263589859, 0.08436765521764755, -0.7361305356025696, -1.1655950546264648, 0.2905866801738739, 0.162334606051445, 1.1621350049972534, 0.05290977284312248, 3.9726805686950684, -1.0374841690063477, -0.2353862076997757, 1.660192847251892, -0.4890807569026947, -0.001061903894878924, -0.3468041718006134, 0.4142429530620575, -0.13281023502349854, 1.2103794813156128, 0.11832515150308609, -0.5775443315505981, -0.025235870853066444, -1.0342786312103271, -0.8030173778533936, 0.07515077292919159, 0.13572648167610168], [2.6409213542938232, 0.2717086970806122, -0.07721929997205734, 0.01858506351709366, 0.32548627257347107, 0.26679345965385437, 0.3947807848453522, 0.18465466797351837, 0.3111441433429718, 0.5524268746376038, 0.0802094042301178, 0.2045341283082962, 0.5878831148147583, 0.20518115162849426, 0.24393330514431, 0.028974199667572975, 0.14443059265613556, -0.11942070722579956, -0.46858859062194824, -0.024019692093133926, -0.07381688058376312, 0.20422495901584625, 0.7151338458061218, -0.38788822293281555, 0.49283427000045776, -0.38004186749458313, 0.1904258131980896, 0.6251369714736938, -0.09729861468076706, -0.0028427201323211193, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2668153643608093, 0.106206513941288, 0.12105965614318848, -0.19627243280410767, 0.016946570947766304, 0.09404681622982025, -0.3828028738498688, -0.04884996637701988, -0.4784226715564728, 0.08279698342084885, -0.029017621651291847, -0.028039779514074326, -0.02328730747103691, -1.0454851388931274, -1.5578997135162354, 0.2502133846282959, 1.1004711389541626, 2.05415415763855, -0.16779573261737823, -1.0430175065994263, 0.43465062975883484, 0.6107824444770813, 1.05619215965271, -0.4317367970943451, -0.13268771767616272, 0.739284098148346, 3.570986270904541, 0.07031091302633286, 0.7819105982780457, 2.620512008666992, 1.1360865831375122, 0.26256412267684937, 3.378302574157715, -0.20764879882335663, 1.217996597290039, 1.256237506866455]], "betas": [[-1.3120368719100952, 2.2768006324768066, -0.0015901251463219523, -0.0022571003064513206, -0.00127757980953902, 0.0013569226721301675, -1.3847791706211865e-05, 0.0017138615949079394, 0.00030786360730417073, 0.0008635756676085293], [-1.8120079040527344, 2.8656349182128906, 0.011720892041921616, 0.0052531105466187, -0.0059575531631708145, 0.002215092768892646, 0.0019032282289117575, 0.003394283587113023, 0.0010465148370712996, 0.0014783276710659266]], "transl": [[0.0389164574444294, 0.20060917735099792, -0.001196662662550807], [-0.01937934011220932, 0.16188190877437592, 0.03756599500775337]], "joints3d": [[[59.830467224121094, 196.58985900878906, 4030.94580078125], [108.3159408569336, 275.2491760253906, 3984.093994140625], [7.321896553039551, 281.8231506347656, 4043.569091796875], [73.23519897460938, 112.34929656982422, 4069.760986328125], [124.68497467041016, 609.4085083007812, 3817.302734375], [-208.9581298828125, 585.3796997070312, 3980.09521484375], [64.3526611328125, -14.787084579467773, 4089.68408203125], [266.97015380859375, 959.092529296875, 3874.339111328125], [-180.23789978027344, 963.6232299804688, 4005.271240234375], [53.76492691040039, -64.10932922363281, 4088.5263671875], [241.49411010742188, 1029.5703125, 3774.4150390625], [-276.3353271484375, 1033.146240234375, 3970.512939453125], [68.66693878173828, -250.39974975585938, 4141.26123046875], [119.25629425048828, -172.83627319335938, 4084.346435546875], [22.84819221496582, -157.13510131835938, 4169.8251953125], [61.870479583740234, -317.5215148925781, 4091.661376953125], [178.72035217285156, -203.06202697753906, 4037.2861328125], [-25.093719482421875, -154.43960571289062, 4240.666015625], [102.51521301269531, -12.039578437805176, 3896.0771484375], [-39.59071731567383, 84.30304718017578, 4213.4052734375], [12.884782791137695, -225.54837036132812, 3922.242431640625], [-243.1111602783203, 7.733249664306641, 4107.2353515625]], [[-820.2399291992188, 289.13885498046875, 4734.47998046875], [-780.3883666992188, 377.4398193359375, 4708.40771484375], [-889.7719116210938, 355.33685302734375, 4717.99169921875], [-804.8497314453125, 212.97994995117188, 4776.29248046875], [-724.1201171875, 713.0116577148438, 4563.66796875], [-901.84716796875, 726.4711303710938, 4683.48193359375], [-801.4056396484375, 87.76724243164062, 4761.9365234375], [-741.311279296875, 1071.50048828125, 4663.802734375], [-915.1934204101562, 1096.509033203125, 4692.2109375], [-795.9600830078125, 40.29484176635742, 4761.97900390625], [-657.9278564453125, 1159.3260498046875, 4660.09130859375], [-931.9022827148438, 1184.16650390625, 4612.93310546875], [-788.7626953125, -145.79747009277344, 4755.13671875], [-730.2666015625, -60.2176628112793, 4762.15771484375], [-848.7916870117188, -66.44676208496094, 4780.29638671875], [-788.9759521484375, -215.4692840576172, 4709.47509765625], [-661.5585327148438, -94.17698669433594, 4754.3291015625], [-893.7057495117188, -130.53326416015625, 4798.36669921875], [-739.9158935546875, 114.69143676757812, 4655.74365234375], [-846.1203002929688, 91.19290161132812, 4738.26904296875], [-802.7075805664062, 78.38594818115234, 4441.66650390625], [-689.5121459960938, 104.8797378540039, 4562.466796875]]]}, {"global_orient": [[2.6334335803985596, 0.0379725806415081, -0.8500755429267883], [2.6693813800811768, 0.2431289255619049, -0.3661825954914093]], "body_pose": [[2.6334335803985596, 0.0379725806415081, -0.8500755429267883, -0.01508279237896204, 0.02537214197218418, 0.12991368770599365, -0.24562247097492218, -0.17919524013996124, -0.3722100853919983, 0.24927695095539093, -0.12820129096508026, 0.07484667003154755, 0.615820586681366, -0.27526378631591797, -0.02413398027420044, 0.6318711638450623, -0.06234327331185341, 0.127139151096344, -0.13292178511619568, -0.025781549513339996, 0.0010834652930498123, -0.06691969931125641, 0.03829144313931465, -0.18566404283046722, 0.17164774239063263, -0.2531619369983673, 0.18296600878238678, 0.1590823382139206, 0.01624838449060917, -0.09086299687623978, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.006609959062188864, 0.1609518826007843, -0.34204256534576416, -0.22026555240154266, -0.10681641101837158, -0.11288326978683472, -0.17822265625, -0.14597110450267792, 0.2697661221027374, -0.009351332671940327, 0.1518336981534958, 0.1489919275045395, 0.08916745334863663, -0.700299084186554, -1.155387043952942, 0.32646113634109497, 0.18022125959396362, 1.1875590085983276, 0.010989688336849213, 3.955228090286255, -1.0063565969467163, -0.1594487726688385, 1.5601528882980347, -0.38671672344207764, 0.0053204442374408245, -0.3144584596157074, 0.45883265137672424, -0.099850594997406, 1.293541669845581, -0.07283348590135574, -0.5169241428375244, -0.16904468834400177, -0.8158503174781799, -0.7968792915344238, -0.039517637342214584, 0.2683674097061157], [2.6693813800811768, 0.2431289255619049, -0.3661825954914093, 0.021960115060210228, 0.3963736593723297, 0.28057435154914856, 0.3320212960243225, 0.2320437878370285, 0.26468780636787415, 0.40056174993515015, 0.12640485167503357, 0.13007934391498566, 0.545840322971344, 0.1555832177400589, 0.16959449648857117, 0.10053133964538574, -0.0014124969020485878, -0.1317441165447235, -0.410380095243454, -0.05791092291474342, -0.08453679084777832, 0.2958278954029083, 0.6590787172317505, -0.37488916516304016, 0.5461478233337402, -0.18890559673309326, 0.18893982470035553, 0.6523225903511047, -0.11295843124389648, 0.04359133541584015, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2820514738559723, 0.11578291654586792, 0.029805343598127365, -0.21459241211414337, -0.028824320062994957, 0.08804595470428467, -0.44155770540237427, 0.02138783223927021, -0.3226412832736969, 0.10065168887376785, -0.0033860341645777225, 0.01674407534301281, -0.06523951143026352, -1.0144604444503784, -1.4472362995147705, 0.4050304591655731, 0.8798976540565491, 1.9386273622512817, -0.10365559160709381, -1.2127717733383179, 0.3417153060436249, 1.0949785709381104, 1.3410403728485107, -0.48728910088539124, -0.24241967499256134, 0.07863160222768784, 3.53619647026062, 0.14022092521190643, 1.083739995956421, 2.4284112453460693, 1.969356894493103, 0.0995360016822815, 3.48445200920105, -0.12276507169008255, 0.979704737663269, 1.2308112382888794]], "betas": [[-1.2592171430587769, 2.2391228675842285, -0.0012159808538854122, -0.0020339146722108126, -0.001191345159895718, 0.0015160946641117334, -4.6318164095282555e-05, 0.0014923616545274854, 0.0005609116051346064, 0.0008505937876179814], [-1.4870225191116333, 2.234126091003418, 0.010250214487314224, 0.00541690643876791, -0.005030684173107147, 0.002101762453094125, 0.0027977058198302984, 0.0035162551794201136, -0.0003699455119203776, 0.0034097337629646063]], "transl": [[0.04011296480894089, 0.20207665860652924, 0.0015727488789707422], [-0.01995873637497425, 0.17495425045490265, 0.01724093034863472]], "joints3d": [[[71.18185424804688, 197.3632049560547, 4033.366455078125], [117.81734466552734, 275.198486328125, 3982.7802734375], [20.296911239624023, 283.5634765625, 4048.267822265625], [86.12307739257812, 112.94727325439453, 4072.533447265625], [133.9727020263672, 604.7403564453125, 3805.582275390625], [-209.69442749023438, 579.0715942382812, 3990.646728515625], [76.01435852050781, -14.579416275024414, 4091.80419921875], [275.5813903808594, 956.001220703125, 3862.26416015625], [-175.6117401123047, 958.5916748046875, 4005.969970703125], [64.37933349609375, -63.9177131652832, 4090.474365234375], [229.48388671875, 1030.8323974609375, 3772.939697265625], [-275.2544250488281, 1026.8798828125, 3977.725830078125], [80.554443359375, -251.26673889160156, 4141.73095703125], [129.32183837890625, -173.48828125, 4082.689697265625], [36.27640151977539, -157.56787109375, 4173.01220703125], [73.0224838256836, -317.41009521484375, 4090.7451171875], [186.7933349609375, -203.65496826171875, 4032.491455078125], [-10.417737007141113, -155.55490112304688, 4245.28515625], [108.86692810058594, -12.109638214111328, 3891.744384765625], [-18.97786521911621, 84.29329681396484, 4219.046875], [19.27837562561035, -224.88839721679688, 3928.824462890625], [-215.04940795898438, 39.86123275756836, 4083.0751953125]], [[-833.0238037109375, 286.7587890625, 4827.25439453125], [-791.1431274414062, 373.9433898925781, 4791.40087890625], [-902.988037109375, 358.7501220703125, 4823.82958984375], [-813.3463745117188, 207.15679931640625, 4869.97412109375], [-736.1636962890625, 712.1489868164062, 4652.3828125], [-915.7285766601562, 729.9305419921875, 4781.0029296875], [-807.1585083007812, 79.85099029541016, 4870.369140625], [-733.3399658203125, 1077.1011962890625, 4745.93994140625], [-922.3477172851562, 1103.8995361328125, 4809.08056640625], [-800.4517211914062, 30.39470863342285, 4871.23486328125], [-656.42822265625, 1171.3974609375, 4725.18994140625], [-947.1826782226562, 1200.6634521484375, 4739.00634765625], [-798.15283203125, -162.17239379882812, 4871.56103515625], [-734.3704833984375, -76.1769027709961, 4860.74169921875], [-854.3005981445312, -78.36165618896484, 4906.0458984375], [-802.51171875, -232.9906768798828, 4828.66455078125], [-665.5338745117188, -111.66407775878906, 4837.95263671875], [-909.8179931640625, -132.88035583496094, 4938.86572265625], [-746.0281982421875, 93.65518951416016, 4727.6328125], [-880.4793090820312, 95.19239044189453, 4877.74755859375], [-874.7738037109375, 9.215927124023438, 4556.88818359375], [-701.5689086914062, 74.2885971069336, 4720.7353515625]]]}, {"global_orient": [[2.630380392074585, 0.019897861406207085, -0.8741651773452759], [2.655644416809082, 0.2053348571062088, -0.6595681309700012]], "body_pose": [[2.630380392074585, 0.019897861406207085, -0.8741651773452759, 0.010558385401964188, 0.027307340875267982, 0.11785071343183517, -0.2799701392650604, -0.18990808725357056, -0.3846973180770874, 0.23646661639213562, -0.13304340839385986, 0.06379691511392593, 0.614004909992218, -0.2702585756778717, -0.0665506049990654, 0.6480117440223694, -0.06775181740522385, 0.11906138062477112, -0.1359599083662033, -0.015177799388766289, 0.003991642966866493, -0.0671759769320488, 0.013524213805794716, -0.15781229734420776, 0.19552500545978546, -0.26911455392837524, 0.17858180403709412, 0.1444626897573471, 0.017986956983804703, -0.10084951668977737, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01768641173839569, 0.1387709528207779, -0.3509681224822998, -0.20181412994861603, -0.098752960562706, -0.1139291375875473, -0.13616549968719482, -0.14343416690826416, 0.276422381401062, -0.009699967689812183, 0.12788383662700653, 0.15590974688529968, 0.07057127356529236, -0.7042900323867798, -1.153761863708496, 0.32441800832748413, 0.17036455869674683, 1.1698535680770874, 0.03844235837459564, 3.9534544944763184, -1.043292760848999, -0.042067915201187134, 1.5263137817382812, -0.3197592794895172, 0.0050154137425124645, -0.3325682580471039, 0.38483256101608276, -0.12811468541622162, 1.36542546749115, -0.12347906827926636, -0.5097640156745911, -0.1495288759469986, -0.8064932227134705, -0.5025495290756226, -0.16996608674526215, 0.23108358681201935], [2.655644416809082, 0.2053348571062088, -0.6595681309700012, 0.04221730679273605, 0.39841559529304504, 0.25471511483192444, 0.22983865439891815, 0.2241252362728119, 0.19545240700244904, 0.28341883420944214, 0.037237923592329025, 0.1051994189620018, 0.5481659770011902, 0.17501676082611084, 0.09957904368638992, 0.16734302043914795, 0.07017505168914795, -0.10623539984226227, -0.44127747416496277, -0.07104746252298355, -0.08874265104532242, 0.23284053802490234, 0.5778090953826904, -0.3319619297981262, 0.4797256290912628, -0.21871136128902435, 0.13683123886585236, 0.7446616291999817, -0.10917794704437256, 0.03810589760541916, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.3420887291431427, 0.19969995319843292, -0.11187423020601273, -0.3068987727165222, -0.1246228888630867, 0.12556865811347961, -0.5368480682373047, 0.14622464776039124, -0.3196779489517212, 0.20362281799316406, 0.05896010622382164, 0.05838779732584953, -0.1293521672487259, -0.9043753743171692, -1.232229471206665, 0.45872655510902405, 0.33056551218032837, 1.8423793315887451, -0.11000680178403854, -1.454144835472107, 0.3726908564567566, 0.9884128570556641, 2.120128870010376, -1.1572868824005127, -0.3562597930431366, -0.29710108041763306, 3.5115766525268555, 0.25954002141952515, 1.3250635862350464, 2.0861992835998535, 0.16793568432331085, -0.8566827178001404, -0.6448822617530823, 0.8245300650596619, 1.273389220237732, 0.8344273567199707]], "betas": [[-1.271323561668396, 2.2793116569519043, -0.0010097582126036286, -0.002218749839812517, -0.0011502108536660671, 0.0016868965467438102, 0.00010481417848495767, 0.0015413271030411124, 0.0005885284044779837, 0.0008730803383514285], [-1.3426928520202637, 1.5712172985076904, 0.008379083126783371, 0.004230061080306768, -0.004131902940571308, 0.002016468206420541, 0.0027615262661129236, 0.003326163627207279, -0.0008286410011351109, 0.004554396029561758]], "transl": [[0.03850941359996796, 0.20012392103672028, -0.0008348420960828662], [-0.00861445814371109, 0.19332362711429596, -0.0005308676627464592]], "joints3d": [[[75.69864654541016, 197.34255981445312, 4038.6328125], [122.83790588378906, 274.33868408203125, 3987.548583984375], [26.684120178222656, 284.3055419921875, 4054.22705078125], [89.62835693359375, 112.80099487304688, 4077.392333984375], [143.52542114257812, 608.293212890625, 3818.9189453125], [-208.77906799316406, 575.695556640625, 3996.8994140625], [79.71099853515625, -14.621452331542969, 4097.3447265625], [281.0261535644531, 958.06298828125, 3892.259033203125], [-175.5006103515625, 955.369384765625, 4007.991455078125], [68.1898193359375, -63.89215850830078, 4096.63671875], [231.63150024414062, 1036.39013671875, 3807.939697265625], [-275.1858215332031, 1025.4752197265625, 3985.318115234375], [88.44631958007812, -250.00616455078125, 4149.74658203125], [134.8107147216797, -172.12733459472656, 4089.2490234375], [43.16099548339844, -156.83380126953125, 4180.48876953125], [80.18222045898438, -316.38726806640625, 4099.08544921875], [191.96311950683594, -201.83053588867188, 4038.718017578125], [-3.3042197227478027, -155.04434204101562, 4252.67333984375], [109.31681823730469, -12.68185806274414, 3897.495361328125], [-10.424568176269531, 85.38905334472656, 4232.9423828125], [25.692960739135742, -228.31961059570312, 3931.18896484375], [-192.9161376953125, 56.68149948120117, 4075.620849609375]], [[-813.8274536132812, 289.7364807128906, 4801.2255859375], [-772.5067749023438, 374.6871337890625, 4754.09228515625], [-881.304931640625, 367.0716857910156, 4810.6318359375], [-789.5612182617188, 207.59327697753906, 4843.55517578125], [-730.1198120117188, 711.92626953125, 4618.9013671875], [-908.9309692382812, 731.1237182617188, 4747.0263671875], [-785.1653442382812, 81.22213745117188, 4857.4111328125], [-714.4666748046875, 1073.734619140625, 4719.5341796875], [-906.1514892578125, 1104.8970947265625, 4772.7939453125], [-779.211669921875, 30.31793975830078, 4862.12158203125], [-643.0304565429688, 1165.0682373046875, 4674.9580078125], [-950.1874389648438, 1195.75146484375, 4702.3544921875], [-784.7120361328125, -166.2991943359375, 4874.517578125], [-721.5599365234375, -83.9293212890625, 4837.45458984375], [-827.6978149414062, -76.51319122314453, 4919.94580078125], [-791.3533935546875, -238.25067138671875, 4836.41796875], [-664.4241943359375, -126.73922729492188, 4794.134765625], [-880.0042114257812, -125.68190002441406, 4969.81396484375], [-746.238525390625, 52.105926513671875, 4645.6572265625], [-889.7921142578125, 111.30257415771484, 4944.765625], [-909.505126953125, -93.74996185302734, 4573.02783203125], [-789.572509765625, -53.92947006225586, 4804.05322265625]]]}, {"global_orient": [[2.651844024658203, 0.02068587765097618, -0.8570880889892578], [2.551682233810425, 0.20683997869491577, -0.9827023148536682]], "body_pose": [[2.651844024658203, 0.02068587765097618, -0.8570880889892578, 0.015949366614222527, 0.020221278071403503, 0.11585403233766556, -0.31502828001976013, -0.18051432073116302, -0.3671088218688965, 0.24983449280261993, -0.1380327045917511, 0.03389247879385948, 0.5889596343040466, -0.28305476903915405, -0.0716935470700264, 0.6680473685264587, -0.10231165587902069, 0.08870142698287964, -0.16756443679332733, -0.025765256956219673, 0.006734577938914299, -0.09529044479131699, -0.020855965092778206, -0.16160616278648376, 0.20807969570159912, -0.3089674711227417, 0.19818145036697388, 0.18684980273246765, 0.02089889720082283, -0.09655328840017319, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.006825692486017942, 0.11424355953931808, -0.3566052317619324, -0.23284702003002167, -0.18522419035434723, -0.09014581888914108, -0.13538002967834473, -0.04159558191895485, 0.24122388660907745, -0.0674467533826828, 0.10347092896699905, 0.16098268330097198, 0.019555315375328064, -0.6789975762367249, -1.143654704093933, 0.2911040484905243, 0.2140684425830841, 1.185378909111023, 0.03226931765675545, 3.954561233520508, -1.0084593296051025, 0.011621508747339249, 1.4423311948776245, -0.2506924867630005, 0.02239358425140381, -0.31245237588882446, 0.3437047004699707, -0.1059320867061615, 1.4664419889450073, -0.15448570251464844, -0.48469313979148865, -0.22849828004837036, -0.7617464065551758, -0.46773838996887207, -0.29824167490005493, 0.41098421812057495], [2.551682233810425, 0.20683997869491577, -0.9827023148536682, 0.037220001220703125, 0.42373114824295044, 0.29254981875419617, 0.29514166712760925, 0.18039864301681519, 0.21364828944206238, 0.385438472032547, 0.0961894541978836, 0.05759318172931671, 0.5579514503479004, 0.136804461479187, 0.01692657545208931, 0.2472945749759674, 0.3088124096393585, -0.12509804964065552, -0.4615466296672821, -0.04662615805864334, -0.07852064073085785, 0.39330801367759705, 0.5235188603401184, -0.2970885634422302, 0.30854225158691406, -0.5492935180664062, 0.2670939266681671, 0.748678982257843, -0.07937011867761612, 0.05282443389296532, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5548083186149597, 0.12272747606039047, -0.06860212236642838, -0.34041881561279297, -0.15439483523368835, -0.001807806664146483, -0.5481136441230774, 0.24684874713420868, -0.21589015424251556, 0.15101900696754456, -0.05133015289902687, 0.09338928014039993, -0.14604313671588898, -0.6796998977661133, -1.1259989738464355, 0.46177783608436584, -0.09080813825130463, 1.5108650922775269, -0.3571456968784332, -1.5650043487548828, 0.42192134261131287, 0.7957099676132202, 2.313330888748169, -1.2252446413040161, -0.5441744923591614, -0.5562582612037659, 3.5206830501556396, 0.45054420828819275, -1.0226531028747559, 2.6287975311279297, 0.30698075890541077, -0.7957332730293274, 3.3198626041412354, -0.003247162327170372, 1.3317618370056152, 0.06643515080213547]], "betas": [[-1.2379088401794434, 2.104487419128418, -0.0007545104599557817, -0.0016599568771198392, -0.0013544292887672782, 0.001979650231078267, 0.0002025675494223833, 0.001306055230088532, 0.0005725197843275964, 0.0009968045633286238], [-1.6090028285980225, 1.564947485923767, 0.009919686242938042, 0.0020308292005211115, -0.004746985621750355, 0.0006958321901038289, 0.0023784406948834658, 0.0020538694225251675, -0.0008355526369996369, 0.002725518075749278]], "transl": [[0.038862887769937515, 0.2037927508354187, 0.005574867594987154], [-0.00735556660220027, 0.1867246925830841, 0.008029968477785587]], "joints3d": [[[79.5731201171875, 204.8645782470703, 4076.259765625], [127.78387451171875, 282.6551513671875, 4026.1376953125], [29.429183959960938, 291.8925476074219, 4092.216796875], [93.51480102539062, 119.45335388183594, 4114.984375], [151.77911376953125, 619.1376342773438, 3865.732421875], [-207.0206756591797, 578.4658203125, 4022.415771484375], [85.20622253417969, -8.71725082397461, 4129.47265625], [285.6204833984375, 969.5883178710938, 3940.656982421875], [-177.21510314941406, 958.1004638671875, 4036.119384765625], [74.71524810791016, -58.58341979980469, 4127.6162109375], [229.5350341796875, 1045.64892578125, 3858.21826171875], [-277.51361083984375, 1029.2841796875, 4018.811767578125], [94.95967864990234, -248.0296630859375, 4172.46728515625], [141.7794952392578, -167.3954315185547, 4114.83203125], [49.01593017578125, -156.0249481201172, 4207.857421875], [85.84029388427734, -312.0550537109375, 4119.5380859375], [195.07620239257812, -197.39039611816406, 4059.35595703125], [-4.266041278839111, -160.86155700683594, 4275.9677734375], [103.32223510742188, -10.985208511352539, 3920.34033203125], [-25.861717224121094, 79.05886840820312, 4259.97314453125], [26.198936462402344, -227.96697998046875, 3961.0], [-180.87799072265625, 65.87259674072266, 4073.83447265625]], [[-777.890380859375, 270.3051452636719, 4692.36474609375], [-745.5325317382812, 351.2714538574219, 4634.37158203125], [-837.9871215820312, 349.8586120605469, 4714.7431640625], [-748.5858154296875, 189.69842529296875, 4729.2578125], [-713.5120239257812, 674.5673217773438, 4478.55126953125], [-845.9116821289062, 710.5810546875, 4661.02392578125], [-748.0967407226562, 64.85527038574219, 4732.25390625], [-681.132568359375, 1032.5555419921875, 4560.63232421875], [-813.4066162109375, 1072.050537109375, 4718.13427734375], [-743.8370971679688, 14.497628211975098, 4731.9755859375], [-630.6625366210938, 1131.47802734375, 4510.02001953125], [-873.916259765625, 1160.821044921875, 4663.044921875], [-755.3666381835938, -179.5228271484375, 4734.19189453125], [-695.789794921875, -98.24729919433594, 4694.21728515625], [-787.4981079101562, -92.59463500976562, 4788.658203125], [-765.7393798828125, -255.13539123535156, 4708.40185546875], [-645.3723754882812, -130.57894897460938, 4638.29150390625], [-842.3027954101562, -134.9880828857422, 4838.76123046875], [-712.7177734375, 60.74058151245117, 4505.67578125], [-869.1444091796875, 92.25355529785156, 4890.0390625], [-835.2406005859375, -96.35198974609375, 4398.669921875], [-818.367431640625, -53.925106048583984, 4713.5361328125]]]}, {"global_orient": [[2.635573387145996, 0.020062092691659927, -0.8261643052101135], [2.4855122566223145, 0.23249191045761108, -1.2196754217147827]], "body_pose": [[2.635573387145996, 0.020062092691659927, -0.8261643052101135, 0.03561031073331833, 0.013630145229399204, 0.10042018443346024, -0.30470746755599976, -0.16665169596672058, -0.3707892596721649, 0.262259840965271, -0.17433512210845947, 0.0175919272005558, 0.5617332458496094, -0.2863287627696991, -0.06461609154939651, 0.674530565738678, -0.0902368500828743, 0.07733015716075897, -0.16977813839912415, -0.026194175705313683, 0.008429464884102345, -0.03382009640336037, -0.03258368745446205, -0.173265278339386, 0.23209726810455322, -0.2830768823623657, 0.17069055140018463, 0.20182238519191742, 0.0009396016830578446, -0.11574789881706238, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.0014780019409954548, 0.13256262242794037, -0.373900443315506, -0.2363354116678238, -0.18511492013931274, -0.05760059878230095, -0.15684862434864044, -0.07730275392532349, 0.17235730588436127, -0.06777062267065048, 0.10766705125570297, 0.18608157336711884, 0.018589762970805168, -0.6981542706489563, -1.1613110303878784, 0.314596027135849, 0.2572997510433197, 1.2534372806549072, 0.07829071581363678, 3.949496269226074, -1.0579322576522827, 0.002314496086910367, 1.3673385381698608, -0.20049571990966797, -0.006356141529977322, -0.3163694739341736, 0.37800416350364685, -0.10651469975709915, 1.5442707538604736, -0.2569112479686737, -0.4196639358997345, -0.2302733063697815, -0.7095693945884705, -0.4001976251602173, -0.4260937571525574, 0.3609682023525238], [2.4855122566223145, 0.23249191045761108, -1.2196754217147827, 0.08878837525844574, 0.4271728992462158, 0.2830805480480194, 0.35419800877571106, 0.07847046852111816, 0.1391141712665558, 0.38569751381874084, 0.09000631421804428, 0.07433469593524933, 0.4784822463989258, 0.05893298611044884, -0.022174609825015068, 0.18984276056289673, 0.5207662582397461, -0.14587238430976868, -0.432232528924942, -0.05498873442411423, -0.0956292450428009, 0.5183317065238953, 0.5460461378097534, -0.34395551681518555, 0.3333572745323181, -0.8410533666610718, 0.10689118504524231, 0.6390888690948486, -0.05499190092086792, 0.050748180598020554, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5013128519058228, 0.18801672756671906, -0.14485669136047363, -0.39349937438964844, -0.18029431998729706, -0.11314570903778076, -0.5173518657684326, 0.19154007732868195, -0.043960634618997574, 0.04176127910614014, -0.024234190583229065, 0.1525123566389084, 0.018848558887839317, -0.4889455735683441, -0.9132664799690247, 0.593704879283905, -0.3923776149749756, 1.3416962623596191, -0.5760279297828674, -1.6192517280578613, 0.6821973323822021, -0.2110758274793625, -0.0687170922756195, 0.40783360600471497, -0.9268045425415039, -0.9643361568450928, 3.2677195072174072, 1.2280387878417969, -0.1200978010892868, 0.5258887410163879, -0.7420268058776855, -0.9117433428764343, 2.7069835662841797, 1.0492569208145142, 0.6466659307479858, -1.3485029935836792]], "betas": [[-1.210652232170105, 2.1018245220184326, -0.0002747616090346128, -0.0019674180075526237, -0.0014931905316188931, 0.0018505043117329478, 6.703280814690515e-05, 0.0012162817874923348, 0.000569286581594497, 0.0008966388995759189], [-1.980178952217102, 3.150423049926758, 0.015250731259584427, 0.0009542282787151635, -0.002472661668434739, 0.0015880176797509193, 0.002827906049787998, 0.000569957890547812, -0.0006517295842058957, -0.0008781063952483237]], "transl": [[0.039649948477745056, 0.2040904462337494, 0.007001472171396017], [-0.017856573686003685, 0.1434141993522644, 0.008913256227970123]], "joints3d": [[[85.87699127197266, 207.6595001220703, 4101.99755859375], [134.1563262939453, 284.87945556640625, 4050.860595703125], [34.52812194824219, 294.589111328125, 4115.05712890625], [100.11188507080078, 123.15411376953125, 4143.09423828125], [156.5463104248047, 622.30078125, 3890.962646484375], [-203.12448120117188, 578.5962524414062, 4036.353271484375], [92.8117904663086, -5.232330322265625, 4158.2490234375], [283.3056335449219, 977.7120971679688, 3958.074462890625], [-178.6494598388672, 959.1847534179688, 4053.867431640625], [82.58965301513672, -55.27832794189453, 4156.99755859375], [227.95408630371094, 1057.129150390625, 3878.0009765625], [-278.13616943359375, 1030.98681640625, 4033.046630859375], [105.46936798095703, -245.65956115722656, 4197.74462890625], [149.68020629882812, -163.6995391845703, 4139.55078125], [60.51390075683594, -154.35328674316406, 4236.67529296875], [96.59578704833984, -308.66064453125, 4143.3955078125], [200.73077392578125, -194.9108428955078, 4082.409423828125], [13.707138061523438, -165.86532592773438, 4308.87646484375], [101.2491683959961, -8.245165824890137, 3948.41748046875], [-13.570293426513672, 73.94818115234375, 4293.912109375], [27.75391960144043, -227.26150512695312, 3987.46533203125], [-173.03741455078125, 78.08123016357422, 4110.5712890625]], [[-742.72265625, 250.8732452392578, 4589.400390625], [-717.4755859375, 330.8171081542969, 4536.6767578125], [-786.3150024414062, 330.0093994140625, 4621.9296875], [-719.4060668945312, 171.0126190185547, 4612.19580078125], [-695.4453735351562, 667.96435546875, 4387.46923828125], [-797.9818115234375, 701.4171142578125, 4603.0791015625], [-725.8707275390625, 45.91999435424805, 4612.82958984375], [-644.36376953125, 1028.2679443359375, 4455.2734375], [-767.7218017578125, 1061.975341796875, 4668.4853515625], [-721.9530029296875, -0.6587417125701904, 4612.11962890625], [-610.5885620117188, 1133.8594970703125, 4409.45703125], [-851.4021606445312, 1143.3494873046875, 4651.23974609375], [-729.7907104492188, -183.6610107421875, 4620.01171875], [-682.0651245117188, -104.89292907714844, 4575.95556640625], [-747.9129028320312, -99.00447082519531, 4671.45263671875], [-737.3790283203125, -261.4473876953125, 4590.95263671875], [-645.3854370117188, -131.13333129882812, 4515.68603515625], [-789.9834594726562, -129.28851318359375, 4730.1494140625], [-699.3652954101562, 54.538795471191406, 4369.5830078125], [-758.602783203125, 86.06631469726562, 4812.78125], [-784.121337890625, -123.16998291015625, 4262.95068359375], [-669.3319091796875, 298.9629821777344, 4851.5244140625]]]}, {"global_orient": [[2.6278176307678223, 0.02125830017030239, -0.8599988222122192], [2.4844090938568115, 0.09531500190496445, -1.54208505153656]], "body_pose": [[2.6278176307678223, 0.02125830017030239, -0.8599988222122192, 0.026266707107424736, 0.02370675653219223, 0.10874268412590027, -0.32262054085731506, -0.13550342619419098, -0.3497468829154968, 0.2757081687450409, -0.19069263339042664, 0.0015577934682369232, 0.5769995450973511, -0.26043039560317993, -0.06922465562820435, 0.6872472763061523, -0.0376853309571743, 0.06872811913490295, -0.19935448467731476, -0.024130024015903473, 0.012631732039153576, -0.02853875607252121, -0.04526710882782936, -0.1610543578863144, 0.23008215427398682, -0.26856866478919983, 0.17597946524620056, 0.21074284613132477, -0.016570962965488434, -0.12139872461557388, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.016620995476841927, 0.16172568500041962, -0.37702012062072754, -0.26281189918518066, -0.19653679430484772, -0.03319871425628662, -0.17693112790584564, -0.09006810933351517, 0.14277878403663635, -0.09061485528945923, 0.10681579262018204, 0.20887719094753265, 0.018102362751960754, -0.6485154628753662, -1.175233006477356, 0.3425586223602295, 0.2783059775829315, 1.2716087102890015, 0.1934075653553009, 3.955925941467285, -1.0135109424591064, 0.03632979467511177, 1.3267226219177246, -0.12897059321403503, 0.07706791162490845, -0.30445343255996704, 0.38613641262054443, -0.10756432265043259, 1.5491622686386108, -0.35876861214637756, -0.47211724519729614, -0.2668505609035492, -0.7140660285949707, -0.44959908723831177, -0.37585753202438354, 0.44245579838752747], [2.4844090938568115, 0.09531500190496445, -1.54208505153656, -0.055420663207769394, 0.3366239070892334, 0.23875851929187775, 0.12380947172641754, 0.002752864733338356, 0.019774897024035454, 0.2631053030490875, 0.11024874448776245, 0.0408070869743824, 0.4528473913669586, 0.1851906031370163, 0.015871912240982056, 0.25184211134910583, 0.4224793016910553, -0.11081279069185257, -0.47818678617477417, -0.05525277182459831, -0.05305778235197067, 0.46742069721221924, 0.24634359776973724, -0.3250107765197754, 0.16333317756652832, -0.8231883645057678, -0.010813092812895775, 0.5640723705291748, -0.013809102587401867, -0.012185534462332726, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.37250474095344543, 0.20972660183906555, -0.1505763679742813, -0.41198408603668213, -0.2510091960430145, -0.07816819101572037, -0.4996422827243805, 0.29372769594192505, -0.12200839817523956, -0.07574418187141418, 0.08762307465076447, 0.15593911707401276, 0.17057959735393524, -0.31692537665367126, -0.818623960018158, 0.4485524296760559, -0.2109377235174179, 0.9424795508384705, -0.6226128935813904, -1.848848819732666, 0.5855903029441833, -0.022492937743663788, 2.469496488571167, -1.2030298709869385, -0.024521557614207268, -0.4022625684738159, 3.955702543258667, 0.5330544114112854, -1.3964159488677979, 2.553863048553467, 0.18552809953689575, -0.24378477036952972, 2.827294111251831, -0.1925918012857437, 2.4980151653289795, -0.816713273525238]], "betas": [[-1.2687052488327026, 1.926579236984253, -0.0003310612228233367, -0.0015385407023131847, -0.001629935926757753, 0.002044475171715021, 7.63682255637832e-05, 0.0010497093899175525, 0.0005201813764870167, 0.0007862683269195259], [-1.8937840461730957, 2.949899196624756, 0.0058733136393129826, -0.004829497076570988, -0.0023912161123007536, -0.0005938828689977527, 0.0017593459924682975, 0.0018797190859913826, -0.0004791629035025835, 0.0007460600463673472]], "transl": [[0.03776346519589424, 0.20539313554763794, 0.00804006215184927], [0.006987411994487047, 0.18515726923942566, 0.01283757109194994]], "joints3d": [[[86.8851547241211, 215.37803649902344, 4100.59912109375], [134.48049926757812, 292.2447509765625, 4047.672119140625], [35.4001350402832, 302.4442138671875, 4114.9482421875], [102.12478637695312, 130.99676513671875, 4141.66845703125], [155.13323974609375, 625.64404296875, 3886.148681640625], [-200.08644104003906, 582.5396728515625, 4030.089111328125], [95.10071563720703, 3.2692370414733887, 4154.75537109375], [281.94439697265625, 977.6102905273438, 3955.242431640625], [-179.23150634765625, 960.127685546875, 4055.8994140625], [85.09245300292969, -46.88336181640625, 4153.62060546875], [227.78660583496094, 1057.3551025390625, 3875.588623046875], [-277.0585632324219, 1031.217529296875, 4029.045166015625], [112.80136108398438, -237.261962890625, 4192.19384765625], [152.3381805419922, -154.82034301757812, 4131.33984375], [68.80517578125, -146.86544799804688, 4234.302734375], [103.22286987304688, -299.67840576171875, 4138.4033203125], [200.0411834716797, -186.97067260742188, 4071.639404296875], [28.55930519104004, -161.0595703125, 4310.00634765625], [97.43766784667969, -1.3160886764526367, 3941.480224609375], [-5.432084560394287, 76.80638122558594, 4299.18798828125], [28.868175506591797, -221.2198486328125, 3975.635498046875], [-160.8452606201172, 92.27278900146484, 4114.99609375]], [[-714.7395629882812, 247.20701599121094, 4524.6396484375], [-685.715576171875, 325.6669616699219, 4470.14404296875], [-737.802001953125, 330.5441589355469, 4568.3583984375], [-701.0630493164062, 162.3279266357422, 4540.18310546875], [-685.4502563476562, 657.8395385742188, 4309.341796875], [-776.3538818359375, 700.542724609375, 4563.6201171875], [-714.2352294921875, 37.53981018066406, 4540.921875], [-598.61865234375, 1017.497802734375, 4337.84423828125], [-718.6188354492188, 1059.0150146484375, 4628.087890625], [-712.6720581054688, -9.765715599060059, 4541.7734375], [-592.7245483398438, 1117.7874755859375, 4271.22412109375], [-817.2221069335938, 1122.9715576171875, 4644.5517578125], [-708.2426147460938, -194.2676544189453, 4556.0947265625], [-671.686767578125, -114.25921630859375, 4502.25927734375], [-724.6202392578125, -108.32682037353516, 4608.1650390625], [-723.01708984375, -269.7030334472656, 4524.3251953125], [-646.0059814453125, -143.1947021484375, 4436.45947265625], [-761.1174926757812, -145.12124633789062, 4668.43408203125], [-687.0643920898438, 32.73448181152344, 4273.95556640625], [-838.3362426757812, 37.17464065551758, 4792.49169921875], [-799.3427124023438, -156.8405303955078, 4228.88330078125], [-835.1044921875, -148.4480743408203, 4648.671875]]]}, {"global_orient": [[2.6290647983551025, 0.03326757252216339, -0.9119793772697449], [2.4946353435516357, 0.10498414933681488, -1.4966109991073608]], "body_pose": [[2.6290647983551025, 0.03326757252216339, -0.9119793772697449, 0.01856064237654209, 0.02075193077325821, 0.11029667407274246, -0.3310488760471344, -0.11401993781328201, -0.3462062180042267, 0.2815753221511841, -0.19141680002212524, -0.002107814885675907, 0.603186845779419, -0.2561723589897156, -0.08513101935386658, 0.6825671195983887, -0.021706493571400642, 0.05854661762714386, -0.21661058068275452, -0.033279020339250565, 0.014142390340566635, -0.061600327491760254, -0.026950476691126823, -0.17023442685604095, 0.23562563955783844, -0.2802433371543884, 0.20014208555221558, 0.21775193512439728, -0.018442794680595398, -0.12483222782611847, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.012006158009171486, 0.16613000631332397, -0.3762059807777405, -0.2930653691291809, -0.1777385026216507, -0.0005456801154650748, -0.2026265561580658, -0.15389448404312134, 0.052923742681741714, -0.17069488763809204, 0.13445591926574707, 0.20064814388751984, 0.019837521016597748, -0.6217902302742004, -1.191063404083252, 0.4313008785247803, 0.26301050186157227, 1.329662799835205, 0.2379273772239685, 3.971737861633301, -0.9388135075569153, -0.13396774232387543, 1.276275634765625, -0.1514010727405548, 0.15770310163497925, -0.32207030057907104, 0.431345134973526, -0.04771844297647476, 1.616998314857483, -0.3881915211677551, -0.4932672083377838, -0.28285104036331177, -0.72309809923172, -0.6528235673904419, -0.5329037308692932, 0.49497687816619873], [2.4946353435516357, 0.10498414933681488, -1.4966109991073608, 0.001929243910126388, 0.29198914766311646, 0.21001707017421722, 0.15890082716941833, -0.01766606792807579, 0.04143128544092178, 0.35020527243614197, 0.07442358136177063, 0.039710819721221924, 0.46149733662605286, 0.10760217905044556, -0.006671414244920015, 0.14068982005119324, 0.38292235136032104, -0.12814529240131378, -0.4706994891166687, -0.03797217458486557, -0.058378856629133224, 0.3179052174091339, 0.20350809395313263, -0.31329062581062317, 0.11791734397411346, -0.7741219997406006, -0.07656513154506683, 0.4369686543941498, -0.0068667177110910416, -0.010262696072459221, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.30476078391075134, 0.19565659761428833, -0.21545523405075073, -0.42769938707351685, -0.2849733233451843, -0.12587715685367584, -0.4914557635784149, 0.3015621602535248, -0.10840915143489838, -0.16634023189544678, 0.17036157846450806, 0.1549576073884964, 0.1886175125837326, -0.4097808003425598, -0.8227648735046387, 0.4581858813762665, -0.12321335077285767, 0.9583486914634705, 0.8817324638366699, 3.8060224056243896, -1.1632322072982788, -0.09099715948104858, 2.354771375656128, -1.3653123378753662, 0.2918761968612671, -0.010663818567991257, -0.3907458186149597, -0.04366413503885269, -1.139204502105713, 1.4309265613555908, 0.5919057130813599, 0.8349759578704834, 2.4072179794311523, -0.7665624618530273, 2.653526782989502, 0.6427483558654785]], "betas": [[-1.0979986190795898, 2.0411269664764404, 0.0003424728929530829, -0.0016160232480615377, -0.0014959421241655946, 0.0021474920213222504, -2.5690567781566642e-05, 0.001000513439066708, 0.0007817313889972866, 0.0006856785039417446], [-1.7889002561569214, 2.8724071979522705, 0.004654754884541035, -0.002206474542617798, -0.001930629718117416, 0.001143702887929976, 0.0019601620733737946, 0.0009707958088256419, -8.432386675849557e-05, -0.0003289020387455821]], "transl": [[0.03958021476864815, 0.20733603835105896, 0.005133760627359152], [0.010291638784110546, 0.19148890674114227, 0.012900400906801224]], "joints3d": [[[92.99871826171875, 224.12689208984375, 4161.62255859375], [138.74398803710938, 302.2869873046875, 4108.4912109375], [42.7462043762207, 311.59002685546875, 4179.15771484375], [109.64244079589844, 138.1250457763672, 4201.24072265625], [154.06820678710938, 641.1132202148438, 3946.854736328125], [-199.28216552734375, 594.75439453125, 4101.84716796875], [102.03372192382812, 8.39461898803711, 4211.11279296875], [286.7104797363281, 994.53369140625, 4026.679931640625], [-185.37330627441406, 977.2724609375, 4137.65771484375], [92.5697250366211, -42.32246780395508, 4210.4267578125], [229.43704223632812, 1075.4820556640625, 3948.109130859375], [-285.1148986816406, 1049.29443359375, 4113.21533203125], [121.06218719482422, -234.93740844726562, 4243.42138671875], [158.62425231933594, -150.57644653320312, 4182.310546875], [79.57868194580078, -144.46620178222656, 4290.15185546875], [107.67731475830078, -295.8187561035156, 4187.146484375], [205.49923706054688, -183.6721649169922, 4121.54248046875], [49.624935150146484, -166.66302490234375, 4369.64111328125], [99.45340728759766, 4.09837532043457, 3991.369140625], [21.031801223754883, 74.79115295410156, 4380.08935546875], [30.277002334594727, -218.9373779296875, 4025.813232421875], [-167.58558654785156, 116.5769271850586, 4230.00732421875]], [[-712.6211547851562, 246.22283935546875, 4519.80419921875], [-683.500732421875, 325.2005920410156, 4465.10791015625], [-738.8699951171875, 329.8838806152344, 4562.37841796875], [-697.0447998046875, 160.93019104003906, 4536.904296875], [-677.115478515625, 665.5126953125, 4319.13623046875], [-766.8624267578125, 702.2473754882812, 4552.9677734375], [-717.9319458007812, 36.50043487548828, 4532.8896484375], [-577.5230102539062, 1022.2472534179688, 4365.90869140625], [-732.13330078125, 1069.6048583984375, 4592.37451171875], [-719.3599243164062, -11.299674987792969, 4531.57373046875], [-585.118408203125, 1118.930908203125, 4292.95751953125], [-839.4609985351562, 1121.0809326171875, 4603.72265625], [-706.7444458007812, -196.6016387939453, 4548.97216796875], [-672.4265747070312, -115.34017944335938, 4493.8330078125], [-728.4495239257812, -110.1473617553711, 4600.11767578125], [-719.5184326171875, -270.0411682128906, 4511.57666015625], [-645.4164428710938, -140.81817626953125, 4426.19970703125], [-766.0939331054688, -147.0647430419922, 4660.896484375], [-720.5375366210938, 30.281553268432617, 4268.818359375], [-864.9591064453125, 36.521949768066406, 4769.3017578125], [-797.63720703125, -182.23143005371094, 4282.34423828125], [-845.67578125, -164.73550415039062, 4647.03662109375]]]}, {"global_orient": [[2.617689609527588, 0.04177294299006462, -0.8953120112419128], [2.4826831817626953, 0.16302227973937988, -1.5262229442596436]], "body_pose": [[2.617689609527588, 0.04177294299006462, -0.8953120112419128, 0.02670433558523655, 0.011541422456502914, 0.10333540290594101, -0.3162643313407898, -0.09297869354486465, -0.344427227973938, 0.3070468008518219, -0.17936980724334717, -0.0007702191942371428, 0.6297594904899597, -0.25584641098976135, -0.0809670090675354, 0.7071236371994019, 0.009980141185224056, 0.056763529777526855, -0.2542509138584137, -0.046722427010536194, 0.00535151781514287, -0.05107793211936951, -0.020887384191155434, -0.18420422077178955, 0.21004945039749146, -0.33182278275489807, 0.2294224351644516, 0.24955542385578156, -0.01386511605232954, -0.1248285174369812, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.004291052930057049, 0.15809787809848785, -0.3918774425983429, -0.2943321466445923, -0.20362180471420288, -0.012694119475781918, -0.21990785002708435, -0.13437402248382568, 0.03874444589018822, -0.14872728288173676, 0.1535683423280716, 0.19810594618320465, -0.015198689885437489, -0.6585868000984192, -1.1892282962799072, 0.4351785480976105, 0.23941965401172638, 1.3367999792099, 0.15205496549606323, 3.9490621089935303, -1.053538203239441, -0.18993186950683594, 1.251417875289917, -0.22370319068431854, 0.08037758618593216, -0.2973434031009674, 0.38293811678886414, 0.004599405452609062, 1.6463569402694702, -0.6227235794067383, -0.45413628220558167, -0.30022090673446655, -0.6945050358772278, -0.903558075428009, -0.8647497892379761, 0.7683111429214478], [2.4826831817626953, 0.16302227973937988, -1.5262229442596436, 0.020091596990823746, 0.3283405900001526, 0.25065529346466064, 0.18060891330242157, -0.0019823145121335983, 0.07530339062213898, 0.43655717372894287, 0.08050862699747086, 0.02349167689681053, 0.47039514780044556, 0.07707865536212921, -0.007887815125286579, 0.10170522332191467, 0.39385780692100525, -0.13395191729068756, -0.5923977494239807, -0.02002442441880703, -0.06473040580749512, 0.3234269917011261, 0.20963944494724274, -0.29341137409210205, 0.11008398234844208, -0.7317705750465393, 0.06983040273189545, 0.5441981554031372, -0.030212609097361565, 0.026002736762166023, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.40310418605804443, 0.29080483317375183, -0.2059813290834427, -0.5151740312576294, -0.32354074716567993, -0.11488857120275497, -0.6120603680610657, 0.3257910907268524, -0.1333247572183609, -0.10168270021677017, 0.1744471788406372, 0.13878871500492096, 0.12446050345897675, -0.4443492293357849, -0.7165706157684326, 0.5249999761581421, -0.19844135642051697, 0.9517977237701416, 1.069855809211731, 3.7184219360351562, -1.2126879692077637, -0.115550197660923, 2.4174892902374268, -1.3169267177581787, 0.25251463055610657, 0.43020597100257874, -1.234871745109558, 0.02314581908285618, -1.4241079092025757, 1.573777675628662, 0.4187389314174652, 0.21378685534000397, 2.5272350311279297, -0.5801059007644653, 2.675774097442627, 0.1532023549079895]], "betas": [[-1.1213794946670532, 1.9075201749801636, 0.0008620382286608219, -0.0008306125528179109, -0.001242428901605308, 0.0019774921238422394, -6.134252089395886e-06, 0.0010154201881960034, 0.0009554822463542223, 0.000698388961609453], [-2.102773666381836, 2.5707833766937256, 0.005993990693241358, -0.0009967150399461389, -0.002317488892003894, 0.0009173871949315071, 0.001935736509039998, 0.0009417118853889406, -0.00010171780013479292, -0.0004088544228579849]], "transl": [[0.04045189544558525, 0.20931147038936615, 0.0022465388756245375], [0.010660563595592976, 0.19104965031147003, 0.019272180274128914]], "joints3d": [[[92.77040100097656, 231.67674255371094, 4160.54736328125], [138.087646484375, 309.6330261230469, 4106.14501953125], [40.61539077758789, 318.7295837402344, 4176.53125], [110.56874084472656, 146.47421264648438, 4201.84716796875], [149.6968994140625, 646.7003173828125, 3944.88330078125], [-200.0360565185547, 599.3444213867188, 4094.6025390625], [102.66397094726562, 17.21382713317871, 4211.06494140625], [285.6291809082031, 995.92333984375, 4029.795166015625], [-185.5987091064453, 978.8890380859375, 4143.25732421875], [94.32501220703125, -33.82609176635742, 4210.72998046875], [230.20379638671875, 1079.545166015625, 3953.16064453125], [-285.5674133300781, 1050.2994384765625, 4119.224609375], [124.0559310913086, -226.7374267578125, 4243.02783203125], [161.60708618164062, -141.84312438964844, 4182.35986328125], [81.05387878417969, -136.9069061279297, 4290.04248046875], [112.00165557861328, -286.77520751953125, 4186.2373046875], [207.97879028320312, -173.59767150878906, 4120.158203125], [49.728519439697266, -160.686767578125, 4368.78515625], [88.77738189697266, 7.832175254821777, 3994.0625], [18.470054626464844, 79.55569458007812, 4383.06005859375], [32.358306884765625, -217.2760772705078, 4032.932861328125], [-180.80760192871094, 121.23236083984375, 4248.92578125]], [[-699.4585571289062, 246.70223999023438, 4486.97314453125], [-673.8726806640625, 326.8459167480469, 4432.55078125], [-727.836181640625, 327.7021484375, 4532.85205078125], [-681.4500732421875, 163.11631774902344, 4501.21337890625], [-664.5796508789062, 660.2623291015625, 4295.03466796875], [-752.5441284179688, 690.6082763671875, 4525.7275390625], [-705.790283203125, 43.349281311035156, 4488.85498046875], [-563.2188110351562, 1004.6420288085938, 4346.9736328125], [-729.3104248046875, 1048.7283935546875, 4560.5439453125], [-705.10595703125, -3.6937732696533203, 4485.419921875], [-568.8490600585938, 1100.439453125, 4277.27001953125], [-832.4970703125, 1103.23095703125, 4559.62451171875], [-696.8372802734375, -187.87547302246094, 4495.59765625], [-662.5696411132812, -106.7161865234375, 4443.03271484375], [-715.5526733398438, -104.32067108154297, 4549.60595703125], [-704.8596801757812, -260.0688171386719, 4459.1748046875], [-638.5494995117188, -131.2195281982422, 4375.00732421875], [-749.7599487304688, -142.4571533203125, 4609.84326171875], [-731.9940185546875, 10.17038631439209, 4207.31884765625], [-843.4586791992188, 29.727027893066406, 4729.29443359375], [-772.7046508789062, -205.58395385742188, 4226.31640625], [-821.5827026367188, -160.66513061523438, 4601.802734375]]]}, {"global_orient": [[2.641500949859619, 0.028695138171315193, -0.8836416006088257], [2.5516340732574463, 0.20579707622528076, -1.4416826963424683]], "body_pose": [[2.641500949859619, 0.028695138171315193, -0.8836416006088257, -0.04498116672039032, -1.7931992260855623e-05, 0.10216314345598221, -0.3527901768684387, -0.05236905440688133, -0.3507719933986664, 0.321792334318161, -0.18449857831001282, 0.0003480446175672114, 0.7388997673988342, -0.2567429840564728, -0.11812422424554825, 0.775066614151001, 0.06645651161670685, 0.08206159621477127, -0.253333181142807, -0.04011831805109978, -0.005429127253592014, -0.09932146966457367, -0.09247437864542007, -0.09475855529308319, 0.12632952630519867, -0.44470229744911194, 0.2829745411872864, 0.21278086304664612, -0.014083998277783394, -0.12383020669221878, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.05098903924226761, 0.19122689962387085, -0.3934857249259949, -0.2861979305744171, -0.195871502161026, -0.06888199597597122, -0.2054046392440796, -0.20386919379234314, 0.047000378370285034, -0.09615522623062134, 0.18165312707424164, 0.22436174750328064, -0.009369567036628723, -0.636925995349884, -1.0934772491455078, 0.4448024332523346, 0.2433280199766159, 1.3706735372543335, 0.2405066043138504, 4.000069618225098, -0.8559632301330566, -0.3442450761795044, 1.2495713233947754, -0.2936193645000458, 0.21579355001449585, -0.300660640001297, 0.42218828201293945, 0.036417774856090546, 1.542087435722351, -0.33489471673965454, -0.6221241354942322, -0.2863278090953827, -0.7587668299674988, -1.0487418174743652, -0.3508644700050354, 0.5735081434249878], [2.5516340732574463, 0.20579707622528076, -1.4416826963424683, -0.017616884782910347, 0.34554797410964966, 0.2758827805519104, 0.18522195518016815, 0.04394631087779999, 0.07674840837717056, 0.4717067778110504, 0.06652702391147614, 0.0294566098600626, 0.4987940788269043, -0.01730063371360302, 0.020591288805007935, 0.09409113973379135, 0.28925248980522156, -0.07384201139211655, -0.6045395731925964, -0.03235652670264244, -0.08903941512107849, 0.33921292424201965, 0.077922023832798, -0.3864135146141052, 0.12156893312931061, -0.6607153415679932, -0.1286773830652237, 0.5339810252189636, -0.051054324954748154, 0.06668975949287415, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.43578818440437317, 0.22460375726222992, -0.17324207723140717, -0.4671274721622467, -0.30220043659210205, -0.07386578619480133, -0.6196935772895813, 0.3114634156227112, -0.19124490022659302, -0.07108613103628159, 0.1453445553779602, 0.07986164838075638, 0.0005869469605386257, -0.5018537640571594, -0.8092807531356812, 0.5675579309463501, -0.3026391565799713, 1.0616767406463623, 0.8000366687774658, 3.7629330158233643, -1.3791972398757935, -0.10244514793157578, 2.382291555404663, -1.4530553817749023, 0.1630474030971527, 0.2679484784603119, -1.0112210512161255, -0.1617383360862732, -1.1488149166107178, 2.034437417984009, 0.951941192150116, 0.13846102356910706, 2.393470048904419, -0.3556060492992401, 2.5603580474853516, -0.6620326042175293]], "betas": [[-1.1098514795303345, 2.0523715019226074, 0.00044357238220982254, -0.0007847191882319748, -0.0006077314028516412, 0.001464149565435946, -0.00035560797550715506, 0.0012468526838347316, 0.0012328983284533024, 0.0004306500777602196], [-1.891989827156067, 2.567146062850952, 0.006602200213819742, 0.0005878005758859217, -0.0017640487058088183, 0.0009413902880623937, 0.001719893072731793, 0.0005796555196866393, 0.00014868448488414288, -0.0008166917250491679]], "transl": [[0.043112315237522125, 0.2121998518705368, 0.006799171678721905], [0.010731639340519905, 0.19441437721252441, 0.02044925093650818]], "joints3d": [[[93.56000518798828, 242.92282104492188, 4161.06640625], [140.4805145263672, 321.186279296875, 4109.27197265625], [43.03843307495117, 330.30389404296875, 4177.771484375], [109.21835327148438, 156.8695526123047, 4200.66015625], [142.66148376464844, 652.462158203125, 3932.302978515625], [-203.18280029296875, 605.1578979492188, 4085.850341796875], [97.8065414428711, 27.23246955871582, 4206.162109375], [284.72344970703125, 994.3775024414062, 4039.988525390625], [-183.06019592285156, 982.24072265625, 4156.57470703125], [88.95756530761719, -23.5029296875, 4204.19970703125], [224.91644287109375, 1078.4332275390625, 3966.90625], [-284.8988342285156, 1051.264404296875, 4132.6591796875], [119.6081314086914, -216.06390380859375, 4234.43505859375], [157.2359619140625, -130.1154327392578, 4175.8203125], [75.72393798828125, -127.14372253417969, 4281.67822265625], [113.80227661132812, -278.0626220703125, 4178.10888671875], [204.95504760742188, -156.4826202392578, 4112.6064453125], [48.28416061401367, -151.12600708007812, 4361.42724609375], [92.19303131103516, 22.459209442138672, 3976.071044921875], [26.64674949645996, 90.88111114501953, 4372.27001953125], [30.997873306274414, -202.13536071777344, 4014.1162109375], [-193.0608367919922, 132.85147094726562, 4273.5869140625]], [[-704.2401123046875, 253.23272705078125, 4542.78271484375], [-677.00244140625, 336.62371826171875, 4492.94921875], [-737.75341796875, 332.5794677734375, 4589.61962890625], [-684.235595703125, 168.18304443359375, 4555.837890625], [-667.28515625, 673.8728637695312, 4353.61328125], [-769.7216796875, 699.466796875, 4595.89208984375], [-709.8346557617188, 47.91180419921875, 4535.30224609375], [-559.3121337890625, 1021.2901000976562, 4411.16162109375], [-740.439208984375, 1063.0601806640625, 4628.87646484375], [-708.1705322265625, 0.39247751235961914, 4529.2138671875], [-579.4006958007812, 1123.459716796875, 4350.8564453125], [-848.584228515625, 1111.61669921875, 4627.28564453125], [-702.0492553710938, -186.2703094482422, 4534.984375], [-664.817138671875, -103.27227783203125, 4484.5009765625], [-721.7005004882812, -102.8383560180664, 4591.7080078125], [-710.9274291992188, -260.2922058105469, 4500.52685546875], [-638.4674682617188, -128.94566345214844, 4416.38330078125], [-755.6972045898438, -146.23822021484375, 4650.49462890625], [-742.273681640625, 22.70482063293457, 4259.5185546875], [-825.13818359375, 33.7496223449707, 4780.62158203125], [-776.8389282226562, -197.94537353515625, 4275.82421875], [-820.53076171875, -159.56088256835938, 4649.61474609375]]]}, {"global_orient": [[2.637444257736206, 0.05700099095702171, -0.8434981107711792], [2.5362136363983154, 0.21352002024650574, -1.5189476013183594]], "body_pose": [[2.637444257736206, 0.05700099095702171, -0.8434981107711792, -0.02623901329934597, -0.0064063952304422855, 0.10872114449739456, -0.3000197112560272, -0.05220982804894447, -0.3530856966972351, 0.3076005280017853, -0.17834703624248505, 0.002309382427483797, 0.7439343929290771, -0.293887197971344, -0.10020601004362106, 0.7696404457092285, 0.06407906860113144, 0.07959505915641785, -0.24943296611309052, -0.05601878464221954, 0.004819095600396395, -0.04787617549300194, -0.039963047951459885, -0.11722815036773682, 0.1378684937953949, -0.4361463785171509, 0.3254193663597107, 0.24522243440151215, -0.00681264465674758, -0.13032107055187225, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.03015361912548542, 0.1288284808397293, -0.3777781128883362, -0.2878201901912689, -0.19693827629089355, -0.04932992532849312, -0.22606980800628662, -0.18535064160823822, 0.056227926164865494, -0.10411110520362854, 0.22129729390144348, 0.19852951169013977, 0.020811043679714203, -0.6857530474662781, -1.1580607891082764, 0.4240904450416565, 0.2419159859418869, 1.344909906387329, 0.24379152059555054, 4.004788875579834, -0.9719101190567017, -0.36518704891204834, 1.2589573860168457, -0.2988126575946808, 0.1782531589269638, -0.31276777386665344, 0.4914546310901642, 0.130509153008461, 1.495919942855835, -0.5822761654853821, -0.5851528644561768, -0.2927258014678955, -0.7716405391693115, -1.2642874717712402, -0.77055424451828, 0.9901225566864014], [2.5362136363983154, 0.21352002024650574, -1.5189476013183594, -0.01603754237294197, 0.35334914922714233, 0.2740848958492279, 0.1549224704504013, -0.0065528638660907745, 0.07844023406505585, 0.433788537979126, 0.12260749191045761, 0.05120678246021271, 0.4403819739818573, -0.042994629591703415, -0.008206069469451904, 0.05353999137878418, 0.41618677973747253, -0.09335717558860779, -0.6264551281929016, -0.014363252557814121, -0.08925669640302658, 0.3989046514034271, 0.08995724469423294, -0.3559430241584778, 0.31510910391807556, -0.7503939270973206, 0.08255771547555923, 0.5646519660949707, 0.004132370930165052, 0.05438576638698578, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.46576884388923645, 0.20578038692474365, -0.03579682111740112, -0.35995176434516907, -0.16241098940372467, -0.0026267601642757654, -0.5145145058631897, 0.2564237415790558, -0.20628537237644196, 0.019260549917817116, 0.0695323795080185, -0.008576604537665844, -0.12307118624448776, -0.4905250370502472, -0.8124862909317017, 0.46695706248283386, -0.3097801208496094, 0.845572292804718, 0.9812500476837158, 3.6577601432800293, -0.8588520288467407, -0.002874423749744892, 2.6075937747955322, -1.2933863401412964, 0.32435598969459534, 1.0136395692825317, -1.7418887615203857, 0.3565852642059326, -1.8239635229110718, -0.08537039905786514, 0.38147661089897156, 3.237603187561035, -2.4262216091156006, -0.9522053599357605, 1.492473840713501, 2.0848286151885986]], "betas": [[-1.1380164623260498, 1.9893850088119507, 0.0006851403159089386, -0.0009627030231058598, -0.0008421091479249299, 0.0015127165243029594, -0.00037912200787104666, 0.0012946717906743288, 0.0010250189807265997, 0.0006794438813813031], [-2.263648509979248, 3.1029739379882812, 0.008458007127046585, -0.000964352220762521, -0.002264264039695263, 0.0006193069857545197, 0.0021289479918777943, 0.0011297259479761124, -0.0001962389942491427, -0.0010010668775066733]], "transl": [[0.04099935665726662, 0.2112949639558792, 0.002497584791854024], [0.008074128068983555, 0.18345648050308228, 0.02546851523220539]], "joints3d": [[[88.6434326171875, 245.2492218017578, 4165.2705078125], [134.58226013183594, 324.3597412109375, 4113.69970703125], [35.025245666503906, 331.2212219238281, 4180.1787109375], [105.93451690673828, 160.07464599609375, 4205.95654296875], [136.97198486328125, 655.390380859375, 3938.8984375], [-207.3336944580078, 609.4874877929688, 4093.423828125], [99.30955505371094, 30.615209579467773, 4213.8212890625], [283.48980712890625, 994.7224731445312, 4044.44873046875], [-188.62820434570312, 983.0480346679688, 4175.86962890625], [91.58341979980469, -20.32430648803711, 4212.80908203125], [230.93380737304688, 1083.7635498046875, 3972.16455078125], [-287.526611328125, 1055.1844482421875, 4150.27392578125], [123.01055145263672, -212.6700439453125, 4243.53662109375], [161.224609375, -126.5010986328125, 4185.712890625], [77.3394775390625, -124.248046875, 4289.9140625], [113.8927230834961, -274.6374816894531, 4188.0546875], [210.40696716308594, -153.92591857910156, 4124.0673828125], [47.231178283691406, -147.49874877929688, 4368.890625], [91.426025390625, 27.751115798950195, 3998.035888671875], [14.454134941101074, 92.73982238769531, 4378.0791015625], [28.835155487060547, -197.22308349609375, 4026.378173828125], [-205.5343475341797, 121.54142761230469, 4276.984375]], [[-690.243896484375, 242.3331298828125, 4515.11865234375], [-663.24267578125, 324.6058044433594, 4468.7275390625], [-716.7380981445312, 319.5183410644531, 4564.1357421875], [-675.7847900390625, 159.750244140625, 4522.9541015625], [-656.6338500976562, 662.3978881835938, 4335.75439453125], [-753.134765625, 683.1018676757812, 4572.0986328125], [-700.8790893554688, 41.082706451416016, 4504.6748046875], [-561.6783447265625, 1008.9107666015625, 4381.97998046875], [-745.73388671875, 1041.642822265625, 4599.6640625], [-697.4688720703125, -4.350039482116699, 4500.2333984375], [-584.4221801757812, 1110.97119140625, 4328.1416015625], [-839.051025390625, 1109.6702880859375, 4600.8974609375], [-690.5200805664062, -184.70681762695312, 4505.53515625], [-652.2357788085938, -103.12783813476562, 4461.61279296875], [-712.4412841796875, -103.8031005859375, 4557.71533203125], [-700.9335327148438, -262.0009765625, 4480.01611328125], [-618.4944458007812, -133.3869171142578, 4403.3759765625], [-746.7398071289062, -148.3533935546875, 4609.4912109375], [-677.0953369140625, 18.044139862060547, 4229.54541015625], [-833.2994384765625, -5.245331287384033, 4765.1015625], [-691.435546875, -199.57923889160156, 4249.6044921875], [-782.3523559570312, -152.7657470703125, 4597.01611328125]]]}, {"global_orient": [[2.6681060791015625, 0.05135010927915573, -0.7759024500846863], [2.565901756286621, 0.14028674364089966, -1.4891130924224854]], "body_pose": [[2.6681060791015625, 0.05135010927915573, -0.7759024500846863, -0.029142964631319046, -0.015288380905985832, 0.08732377737760544, -0.2619858980178833, -0.05980799347162247, -0.3813534080982208, 0.2625044882297516, -0.162355437874794, 0.025590306147933006, 0.7665824294090271, -0.3120221197605133, -0.09007200598716736, 0.7289067506790161, 0.1473253071308136, 0.14203880727291107, -0.21795548498630524, -0.051496122032403946, 0.004767719190567732, -0.055985309183597565, -0.038221802562475204, -0.09141034632921219, 0.15028522908687592, -0.4008791744709015, 0.3054046630859375, 0.22278916835784912, -0.0022962915245443583, -0.14963269233703613, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.06006164848804474, 0.12067177146673203, -0.3719235956668854, -0.24268411099910736, -0.1695273220539093, -0.09058798104524612, -0.2505505084991455, -0.2009711116552353, 0.12314274162054062, -0.03842347115278244, 0.16158998012542725, 0.2517896592617035, 0.05734361335635185, -0.7646222114562988, -1.0871704816818237, 0.4273267388343811, 0.19981105625629425, 1.2643519639968872, 0.21627283096313477, 4.011058330535889, -1.0099800825119019, -0.5267630815505981, 1.2713886499404907, -0.34075742959976196, 0.12651857733726501, -0.3032504618167877, 0.4803939461708069, 0.11585385352373123, 1.5489528179168701, -0.7219786643981934, -0.5491474866867065, -0.28549209237098694, -0.7297400236129761, 2.7950618267059326, 1.6775745153427124, -2.457331418991089], [2.565901756286621, 0.14028674364089966, -1.4891130924224854, -0.07030805200338364, 0.3185913562774658, 0.21814653277397156, 0.09692151099443436, 0.032160475850105286, 0.023947423323988914, 0.38562217354774475, 0.07921845465898514, 0.03219536319375038, 0.4614141285419464, -0.027661988511681557, -0.002449353924021125, 0.11060895770788193, 0.3073440492153168, -0.0729026272892952, -0.6303172707557678, -0.00918307714164257, -0.06576142460107803, 0.43968677520751953, 0.043262310326099396, -0.3443056046962738, 0.2497512251138687, -0.7143609523773193, 0.0613987110555172, 0.690601110458374, -0.021151000633835793, 0.02089657075703144, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5080691576004028, 0.18888500332832336, -0.15363210439682007, -0.39995288848876953, -0.191566601395607, -0.01442099828273058, -0.5784263610839844, 0.2826204001903534, -0.21398459374904633, 0.0008751233108341694, 0.13070212304592133, 0.10155615955591202, -0.1355186551809311, -0.6289569735527039, -0.9576448202133179, 0.5057903528213501, -0.09409955143928528, 1.1681864261627197, -0.4036802649497986, -1.939090371131897, 0.505818784236908, 0.2419174462556839, 2.2832040786743164, -1.3326200246810913, -0.5853286385536194, -1.396486759185791, 3.435150384902954, 0.2918459475040436, -0.7571304440498352, 2.6485390663146973, -0.14628075063228607, 3.63840389251709, -1.8426042795181274, 0.004096038173884153, 2.07566237449646, -0.3702179193496704]], "betas": [[-1.0772716999053955, 2.1721351146698, 0.00024921001750044525, -0.0015640472993254662, -0.000664976891130209, 0.0015047191409394145, -0.0002617072605062276, 0.001351890154182911, 0.0008762525394558907, 0.0010023708455264568], [-2.230266571044922, 1.7450698614120483, 0.0070128049701452255, -1.3350806511880364e-05, -0.0030103493481874466, -0.000758390175178647, 0.00161977659445256, 0.0024663140065968037, -0.0004993978072889149, 0.0015312533359974623]], "transl": [[0.04084869846701622, 0.20982788503170013, -0.005161963868886232], [0.01983790285885334, 0.18822842836380005, 0.012765798717737198]], "joints3d": [[[82.8508529663086, 248.21051025390625, 4209.8544921875], [130.91485595703125, 328.2025451660156, 4162.41455078125], [29.208036422729492, 333.9978942871094, 4223.09521484375], [97.85179901123047, 162.33963012695312, 4249.89501953125], [133.9850616455078, 665.0820922851562, 3992.0654296875], [-212.06802368164062, 619.492431640625, 4143.59130859375], [92.24684143066406, 32.196109771728516, 4261.7548828125], [281.2406311035156, 1002.5726928710938, 4112.25732421875], [-198.12152099609375, 994.5782470703125, 4233.07421875], [84.72520446777344, -18.7257022857666, 4261.36328125], [231.09161376953125, 1093.578369140625, 4039.6474609375], [-290.5387878417969, 1069.9722900390625, 4193.52783203125], [117.33084106445312, -209.8904571533203, 4296.72119140625], [158.16415405273438, -123.36335754394531, 4241.3017578125], [66.99774169921875, -121.64173126220703, 4338.2880859375], [115.154541015625, -275.0039367675781, 4243.01953125], [213.0908660888672, -147.23721313476562, 4183.376953125], [31.218969345092773, -138.58590698242188, 4416.3974609375], [98.82257843017578, 29.685264587402344, 4043.77685546875], [-9.548452377319336, 101.92269897460938, 4421.66259765625], [31.80964469909668, -194.73216247558594, 4078.2294921875], [-239.9172821044922, 117.27574920654297, 4338.4609375]], [[-682.6826171875, 256.64801025390625, 4540.62744140625], [-652.2257690429688, 337.96685791015625, 4486.84619140625], [-714.4279174804688, 337.1744384765625, 4589.6513671875], [-665.0186157226562, 171.6985626220703, 4554.13623046875], [-655.7190551757812, 663.4741821289062, 4359.4912109375], [-757.5819702148438, 687.5448608398438, 4596.59619140625], [-686.2969970703125, 54.35260772705078, 4541.828125], [-563.8134765625, 1001.4632568359375, 4406.22119140625], [-738.68896484375, 1036.7529296875, 4633.60498046875], [-685.7164306640625, 6.4611406326293945, 4537.64892578125], [-588.711181640625, 1104.654296875, 4356.85546875], [-834.909423828125, 1100.07958984375, 4638.2470703125], [-689.4822387695312, -180.68150329589844, 4537.24462890625], [-646.8423461914062, -99.09668731689453, 4489.3701171875], [-708.7199096679688, -99.25613403320312, 4596.4580078125], [-701.6627197265625, -251.25941467285156, 4505.18701171875], [-614.4302368164062, -127.52190399169922, 4424.62744140625], [-746.7664184570312, -142.7849884033203, 4652.52099609375], [-708.1148681640625, 38.46260452270508, 4289.736328125], [-820.2323608398438, 43.032283782958984, 4757.3095703125], [-781.6149291992188, -164.0643768310547, 4272.9453125], [-817.9614868164062, -111.42829132080078, 4593.2724609375]]]}, {"global_orient": [[2.6477015018463135, 0.06946521997451782, -0.7240654826164246], [2.5886218547821045, 0.09362854063510895, -1.4617127180099487]], "body_pose": [[2.6477015018463135, 0.06946521997451782, -0.7240654826164246, -0.00047010634443722665, -0.03175580874085426, 0.09141805022954941, -0.19838157296180725, -0.051023151725530624, -0.37863588333129883, 0.24987047910690308, -0.154292032122612, 0.026494581252336502, 0.7992277145385742, -0.3219701051712036, -0.11079251021146774, 0.7124029397964478, 0.2496836632490158, 0.17220135033130646, -0.1895224153995514, -0.06805169582366943, 0.005028728861361742, -0.06166868656873703, 0.00658805575221777, -0.09973430633544922, 0.12635593116283417, -0.37769585847854614, 0.3427485227584839, 0.23719723522663116, -0.014027622528374195, -0.1530400961637497, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.046280983835458755, 0.09734480828046799, -0.34396132826805115, -0.1930219680070877, -0.18263225257396698, -0.14033916592597961, -0.24490998685359955, -0.19296152889728546, 0.19433841109275818, -0.01271083950996399, 0.15910613536834717, 0.25629615783691406, 0.07920069992542267, -0.7612471580505371, -1.036476969718933, 0.3649132251739502, 0.22472728788852692, 1.1805120706558228, 0.16216976940631866, 3.995553731918335, -0.9530928730964661, -0.5624618530273438, 1.3451483249664307, -0.4145142138004303, 0.15187592804431915, -0.2836843430995941, 0.5235491394996643, -0.07279983162879944, 1.4042253494262695, -0.18089494109153748, -0.4428825378417969, -0.3245035409927368, -0.6333074569702148, -1.2403063774108887, -0.3829692006111145, 0.843109667301178], [2.5886218547821045, 0.09362854063510895, -1.4617127180099487, -0.10729537159204483, 0.31593358516693115, 0.1946876347064972, 0.047138817608356476, 0.017402363941073418, -0.048121459782123566, 0.3503549098968506, 0.015232033096253872, 0.03346216306090355, 0.4519171416759491, -0.033362776041030884, 0.014699814841151237, 0.20025475323200226, 0.2632838785648346, -0.01896149478852749, -0.654625415802002, 0.009385007433593273, -0.06797566264867783, 0.4723200798034668, -0.05089956521987915, -0.32729870080947876, 0.23897890746593475, -0.6572683453559875, 0.08934030681848526, 0.7980307340621948, -0.07160025089979172, -0.0011355599854141474, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5826020240783691, 0.23879703879356384, -0.1778140813112259, -0.46296626329421997, -0.2584601938724518, -0.00930248573422432, -0.6227601766586304, 0.3269738554954529, -0.24770808219909668, 0.03649557754397392, 0.20642820000648499, 0.11800617724657059, -0.08995771408081055, -0.5752918124198914, -0.995915949344635, 0.43848738074302673, 0.01784580759704113, 1.375481128692627, -0.2773462235927582, -1.8007733821868896, 0.38672763109207153, 0.5050855278968811, 2.070413589477539, -0.9525494575500488, -0.47155216336250305, -0.6485975384712219, 3.389031171798706, 0.24836553633213043, 0.03297753259539604, 2.7055301666259766, 0.7139407992362976, -1.1578726768493652, -0.4440520107746124, 0.2766597270965576, 1.1942994594573975, 0.1865169107913971]], "betas": [[-1.120952844619751, 2.1927859783172607, -0.0008740887278690934, -0.002088903682306409, -0.0006554530700668693, 0.0014737967867404222, -6.12466101301834e-05, 0.001592279295437038, 0.0007427773671224713, 0.001116584287956357], [-2.2112178802490234, 0.8129706382751465, 0.005489577539265156, 8.117010293062776e-05, -0.003220184240490198, -0.0016831244574859738, 0.0014280980685725808, 0.004234555643051863, -0.0005996634135954082, 0.0044358898885548115]], "transl": [[0.039445020258426666, 0.209483802318573, -0.010329066775739193], [0.022310985252261162, 0.192196786403656, 0.0017694145208224654]], "joints3d": [[[77.6857681274414, 248.58465576171875, 4181.28125], [124.96056365966797, 328.487548828125, 4133.35791015625], [21.579723358154297, 333.0236511230469, 4190.77880859375], [93.57571411132812, 164.44834899902344, 4223.5947265625], [129.99307250976562, 663.8281860351562, 3961.508544921875], [-213.93072509765625, 622.286376953125, 4111.1708984375], [92.07830810546875, 35.0380744934082, 4240.076171875], [275.9685974121094, 995.8853759765625, 4094.44482421875], [-206.49417114257812, 993.4339599609375, 4212.5478515625], [85.24320220947266, -15.78707504272461, 4240.27587890625], [230.57154846191406, 1088.528076171875, 4021.38232421875], [-288.9945068359375, 1070.5626220703125, 4158.345703125], [118.10076904296875, -206.09779357910156, 4276.888671875], [159.06521606445312, -119.88157653808594, 4221.7861328125], [67.13604736328125, -118.08963012695312, 4317.181640625], [113.731689453125, -271.9768981933594, 4224.4697265625], [212.93345642089844, -140.371337890625, 4162.05517578125], [28.301742553710938, -129.2775421142578, 4394.44580078125], [105.24494934082031, 42.66994094848633, 4026.229248046875], [-25.092872619628906, 108.16293334960938, 4391.0087890625], [33.4937744140625, -178.71202087402344, 4065.72998046875], [-259.0750427246094, 85.83595275878906, 4322.6552734375]], [[-683.0519409179688, 263.0636291503906, 4564.4921875], [-649.8929443359375, 343.6970520019531, 4505.958984375], [-718.7298583984375, 346.0415954589844, 4613.22265625], [-663.36376953125, 176.3712615966797, 4582.05517578125], [-655.5130004882812, 659.87939453125, 4380.40087890625], [-774.3816528320312, 685.7467041015625, 4627.72998046875], [-682.7786254882812, 60.14363098144531, 4575.572265625], [-566.14306640625, 993.3027954101562, 4417.578125], [-734.1607055664062, 1025.863525390625, 4677.62841796875], [-683.0099487304688, 10.506580352783203, 4572.0166015625], [-595.7136840820312, 1095.96240234375, 4370.6904296875], [-826.5107421875, 1094.39501953125, 4683.36767578125], [-694.4367065429688, -180.91412353515625, 4567.71337890625], [-651.70849609375, -98.97872161865234, 4515.1357421875], [-708.7037353515625, -99.36978149414062, 4632.74609375], [-707.3412475585938, -248.83689880371094, 4536.12255859375], [-626.1470336914062, -126.31126403808594, 4443.76123046875], [-747.0858764648438, -144.280029296875, 4691.60546875], [-721.7459716796875, 49.118858337402344, 4328.8427734375], [-804.9742431640625, 60.0353889465332, 4761.8310546875], [-846.297119140625, -124.81340026855469, 4321.69921875], [-841.5560302734375, -49.69330596923828, 4571.765625]]]}, {"global_orient": [[2.699591636657715, 0.06289975345134735, -0.6233780980110168], [2.666602849960327, 0.09124389290809631, -1.3369977474212646]], "body_pose": [[2.699591636657715, 0.06289975345134735, -0.6233780980110168, -0.06133319437503815, -0.05496979132294655, 0.0982804223895073, -0.1772390455007553, -0.053749606013298035, -0.38393089175224304, 0.22397103905677795, -0.13129964470863342, 0.03522515669465065, 0.8429651260375977, -0.34165701270103455, -0.12271498888731003, 0.7000904083251953, 0.2663273811340332, 0.18267394602298737, -0.15918295085430145, -0.06934796273708344, -0.00301665929146111, -0.08947968482971191, 0.011037539690732956, -0.0738297626376152, 0.12357564270496368, -0.3523895740509033, 0.37745997309684753, 0.21852563321590424, -0.02324603497982025, -0.14410006999969482, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.025120969861745834, 0.12055431306362152, -0.32102087140083313, -0.18555058538913727, -0.18382209539413452, -0.16071832180023193, -0.2470991015434265, -0.17602254450321198, 0.2889977991580963, -0.015576114878058434, 0.098136305809021, 0.2645165026187897, 0.11020835489034653, -0.7971809506416321, -1.0490751266479492, 0.2923528552055359, 0.17656846344470978, 1.107181191444397, 0.09508927166461945, 3.9887516498565674, -0.9266769886016846, -0.4467453062534332, 1.5338765382766724, -0.5157294273376465, 0.15520814061164856, -0.2588379383087158, 0.5056409239768982, -0.25294119119644165, 1.2081575393676758, 0.20573754608631134, -0.5584692358970642, -0.3200669586658478, -0.7215560674667358, -0.44604969024658203, -0.08528792858123779, -0.06697338819503784], [2.666602849960327, 0.09124389290809631, -1.3369977474212646, -0.09461317956447601, 0.3224477171897888, 0.19620400667190552, 0.06611035019159317, 0.005438627675175667, -0.004262493923306465, 0.37814661860466003, 0.08012965321540833, 0.0012338001979514956, 0.4007198214530945, -0.05303970351815224, 0.019352255389094353, 0.18086397647857666, 0.32324710488319397, -0.04818824678659439, -0.6416037082672119, 0.0010457475436851382, -0.05984360724687576, 0.5264122486114502, 0.08158933371305466, -0.3488101065158844, 0.3111675977706909, -0.6396530270576477, 0.10944011807441711, 0.6885272860527039, -0.042336687445640564, 0.012797819450497627, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5279646515846252, 0.202456533908844, -0.17189332842826843, -0.400560200214386, -0.198492169380188, -0.007064548786729574, -0.5893113017082214, 0.2423192709684372, -0.20481805503368378, 0.020838798955082893, 0.10566532611846924, 0.14504878222942352, -0.0796433612704277, -0.631405234336853, -0.9739689826965332, 0.5839564204216003, -0.11408133804798126, 1.2564066648483276, -0.39803463220596313, -1.4828054904937744, 0.3453017473220825, 0.5250089764595032, 2.2871687412261963, -1.000694990158081, -0.4016074538230896, -0.40343958139419556, 3.510119676589966, 0.10627789050340652, 0.849663257598877, 2.542053699493408, 1.3313002586364746, 0.06871731579303741, 3.654827833175659, 0.08140107244253159, 1.6569762229919434, 0.8383745551109314]], "betas": [[-1.2951339483261108, 2.0535361766815186, -0.0012828920735046268, -0.002302268985658884, -0.0006014365935698152, 0.0013868145179003477, 9.643268276704475e-05, 0.0014809640124440193, 0.0005384388496167958, 0.0011772714788094163], [-2.26300311088562, 1.4457658529281616, 0.007613074034452438, 6.736988143529743e-05, -0.0040307180024683475, -0.001004233374260366, 0.0019198062364012003, 0.0028815751429647207, -0.0009457647684030235, 0.0024261893704533577]], "transl": [[0.0382259227335453, 0.20988892018795013, -0.009357384406030178], [0.01290215365588665, 0.18340358138084412, 0.01537473127245903]], "joints3d": [[[69.34773254394531, 246.82174682617188, 4120.84228515625], [120.21087646484375, 327.6221923828125, 4078.848388671875], [11.885133743286133, 330.34716796875, 4128.43359375], [82.093994140625, 162.39039611816406, 4161.29833984375], [128.5452117919922, 653.7903442382812, 3900.502685546875], [-212.84422302246094, 621.1296997070312, 4047.5361328125], [81.10660552978516, 34.78965759277344, 4177.5595703125], [268.09722900390625, 978.620849609375, 4041.58984375], [-212.56968688964844, 982.5914306640625, 4162.0263671875], [74.21449279785156, -15.523486137390137, 4174.7431640625], [225.46087646484375, 1068.4288330078125, 3965.96875], [-284.8367919921875, 1062.2498779296875, 4100.96630859375], [106.02911376953125, -204.44102478027344, 4213.02099609375], [150.18287658691406, -118.12776947021484, 4162.45751953125], [50.63368606567383, -118.21533203125, 4248.54833984375], [105.6492919921875, -268.420654296875, 4159.849609375], [208.88796997070312, -135.98519897460938, 4107.4892578125], [2.7972733974456787, -122.85948944091797, 4320.2822265625], [106.86930084228516, 47.99390411376953, 3974.413330078125], [-50.11747360229492, 111.41036224365234, 4308.87890625], [36.0015754699707, -170.53384399414062, 4011.747802734375], [-266.1011962890625, 35.81581115722656, 4231.68896484375]], [[-697.63623046875, 246.27752685546875, 4546.26416015625], [-658.5524291992188, 326.9976501464844, 4495.7744140625], [-734.3861694335938, 327.7241516113281, 4591.9140625], [-683.0018920898438, 160.56968688964844, 4562.060546875], [-648.1058959960938, 650.1614990234375, 4373.251953125], [-779.7623291015625, 674.2154541015625, 4597.763671875], [-702.3196411132812, 44.46409606933594, 4544.8486328125], [-566.44140625, 988.8998413085938, 4409.66552734375], [-745.2578735351562, 1017.0978393554688, 4651.80126953125], [-701.6935424804688, -3.708019495010376, 4539.447265625], [-581.3722534179688, 1093.02880859375, 4359.3134765625], [-830.9317016601562, 1093.1539306640625, 4643.11376953125], [-702.6022338867188, -191.9385986328125, 4535.9365234375], [-655.8399658203125, -108.94669342041016, 4493.4423828125], [-730.5446166992188, -111.65262603759766, 4594.26025390625], [-708.5761108398438, -261.18170166015625, 4501.60693359375], [-615.8287353515625, -136.1929931640625, 4431.7109375], [-772.651123046875, -155.47926330566406, 4648.05712890625], [-690.798583984375, 35.73213577270508, 4295.28125], [-834.5891723632812, 35.32530212402344, 4748.62841796875], [-832.4995727539062, -102.89396667480469, 4212.60302734375], [-821.845947265625, -64.92139434814453, 4548.95947265625]]]}, {"global_orient": [[2.7527644634246826, 0.058571964502334595, -0.5315210819244385], [2.5756022930145264, 0.12417144328355789, -1.2575032711029053]], "body_pose": [[2.7527644634246826, 0.058571964502334595, -0.5315210819244385, -0.12834858894348145, -0.07058889418840408, 0.1195121705532074, -0.15877170860767365, -0.041961513459682465, -0.37012162804603577, 0.20299257338047028, -0.09585542231798172, 0.031127840280532837, 0.8745540976524353, -0.34069955348968506, -0.11851415783166885, 0.6922124624252319, 0.28567296266555786, 0.2138868123292923, -0.1967177540063858, -0.10092116892337799, -0.009918184019625187, -0.0892113521695137, 0.02563946321606636, -0.06627868860960007, 0.07344241440296173, -0.4136182963848114, 0.39595991373062134, 0.24888595938682556, 0.011445239186286926, -0.11242802441120148, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.06516674906015396, 0.1152263805270195, -0.2847352921962738, -0.1757172793149948, -0.23991775512695312, -0.18748609721660614, -0.25319263339042664, -0.05969672277569771, 0.2863757610321045, 0.07241939753293991, 0.027407607063651085, 0.2700636684894562, 0.0670042634010315, -0.7741997241973877, -1.0280286073684692, 0.20893114805221558, 0.08856572210788727, 1.0566891431808472, 0.03665381297469139, 4.0187506675720215, -0.7763455510139465, -0.4428675174713135, 1.717848777770996, -0.5899834632873535, 0.11255714297294617, -0.18876774609088898, 0.4680563807487488, -0.3330586552619934, 1.213087797164917, -0.12191469967365265, -0.4482210874557495, -0.31265804171562195, -0.7058412432670593, -0.7312045693397522, -0.6584374308586121, 0.3153613209724426], [2.5756022930145264, 0.12417144328355789, -1.2575032711029053, 0.10707797110080719, 0.32236337661743164, 0.16652919352054596, 0.2977895140647888, -0.06722014397382736, 0.0008177751442417502, 0.4802086353302002, 0.13424177467823029, 0.045032769441604614, 0.24648305773735046, -0.05991863086819649, 0.024922853335738182, -0.06487177312374115, 0.3890797793865204, -0.09657293558120728, -0.520954966545105, 0.08005180954933167, -0.09117758274078369, 0.638136088848114, 0.22663938999176025, -0.346170574426651, 0.6507971882820129, -0.7043293714523315, 0.20590071380138397, 0.49314674735069275, -0.003537923563271761, 0.011017276905477047, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.12408548593521118, 0.04878900572657585, -0.1926223337650299, -0.3254406750202179, -0.050336070358753204, -0.2451302856206894, -0.4585099518299103, 0.13179360330104828, 0.07648395746946335, -0.3385043442249298, 0.15108348429203033, 0.13700507581233978, 0.23491144180297852, -0.25629281997680664, -1.0711270570755005, 0.7273740768432617, -0.13505934178829193, 1.240360140800476, -0.26077884435653687, -1.1001198291778564, 0.6212084889411926, 0.5710383653640747, 1.1205106973648071, 0.04096486419439316, -0.5457791686058044, 0.4518153965473175, 3.720613956451416, 0.11412131786346436, 0.0088172797113657, 2.691265344619751, 0.4038490951061249, -1.0491992235183716, -0.11591269075870514, -0.1409795582294464, 0.9616273641586304, 0.5860556960105896]], "betas": [[-1.1701751947402954, 2.01899790763855, -0.0011981759453192353, -0.001949838362634182, -0.0001555533817736432, 0.0014128504553809762, 0.0001324889890383929, 0.0011788427364081144, 0.00043239229125902057, 0.001358616747893393], [-2.253103256225586, 1.9867311716079712, 0.023066196590662003, 0.001736910897307098, -0.0038364261854439974, 0.003739879699423909, 0.005654961336404085, -0.0011906505096703768, -0.0011328852269798517, 0.001117766834795475]], "transl": [[0.03639493137598038, 0.21631504595279694, -0.008185946382582188], [-0.007772753015160561, 0.13600528240203857, 0.0030216770246624947]], "joints3d": [[[59.78397750854492, 250.92396545410156, 4162.0810546875], [113.26107788085938, 333.6021728515625, 4126.14111328125], [1.3162751197814941, 334.5218200683594, 4168.3125], [70.3258285522461, 164.41563415527344, 4201.40283203125], [130.73851013183594, 655.2024536132812, 3935.986328125], [-213.40557861328125, 634.6216430664062, 4083.3115234375], [70.89431762695312, 35.485538482666016, 4214.98046875], [267.3678283691406, 982.2539672851562, 4083.0615234375], [-212.33209228515625, 994.626953125, 4212.04638671875], [66.27071380615234, -15.608903884887695, 4212.43115234375], [232.49085998535156, 1072.0699462890625, 4002.0048828125], [-281.4554138183594, 1075.661865234375, 4147.04248046875], [94.5302734375, -205.97793579101562, 4253.67529296875], [144.24647521972656, -118.81197357177734, 4207.91455078125], [34.6796760559082, -119.36492919921875, 4283.7041015625], [99.74176788330078, -272.9859619140625, 4203.9296875], [206.5020294189453, -134.7707061767578, 4155.04541015625], [-28.207307815551758, -125.84478759765625, 4343.974609375], [110.49473571777344, 47.587158203125, 4012.269287109375], [-92.656494140625, 107.32386779785156, 4331.5029296875], [36.42090606689453, -171.48585510253906, 4052.72802734375], [-280.1393127441406, -20.87639045715332, 4243.99169921875]], [[-702.8373413085938, 211.98855590820312, 4547.9736328125], [-668.3452758789062, 290.4985656738281, 4493.8466796875], [-743.7691650390625, 293.81719970703125, 4584.90625], [-684.7676391601562, 129.73826599121094, 4569.93896484375], [-641.319091796875, 626.2767944335938, 4393.17138671875], [-748.647705078125, 648.1218872070312, 4605.0703125], [-707.3658447265625, 12.343427658081055, 4556.52685546875], [-573.5181884765625, 973.75048828125, 4410.7939453125], [-744.8334350585938, 1000.27978515625, 4622.54296875], [-708.9541015625, -34.73527145385742, 4549.52880859375], [-575.1680297851562, 1079.7955322265625, 4361.3369140625], [-811.1491088867188, 1094.421630859375, 4621.17578125], [-702.4569702148438, -220.1875, 4560.07861328125], [-652.124267578125, -138.2706298828125, 4523.07861328125], [-742.3173828125, -137.97259521484375, 4604.7392578125], [-719.306884765625, -279.2801208496094, 4510.36767578125], [-592.1871337890625, -150.51055908203125, 4476.40283203125], [-796.96484375, -161.4264373779297, 4657.73974609375], [-580.0513916015625, 75.90629577636719, 4418.73291015625], [-810.95947265625, 48.004825592041016, 4741.01025390625], [-643.5668334960938, 71.87899017333984, 4212.02880859375], [-808.6023559570312, 213.31185913085938, 4587.337890625]]]}, {"global_orient": [[2.769190549850464, 0.07304006069898605, -0.46668359637260437], [2.6132864952087402, 0.11474278569221497, -1.1875439882278442]], "body_pose": [[2.769190549850464, 0.07304006069898605, -0.46668359637260437, -0.11405123025178909, -0.04843736067414284, 0.1771964430809021, -0.0840962827205658, -0.03091103583574295, -0.33519864082336426, 0.17956437170505524, -0.04454910755157471, 0.02354627661406994, 0.844524085521698, -0.35734573006629944, -0.14705213904380798, 0.6732712984085083, 0.23722663521766663, 0.21012717485427856, -0.15660390257835388, -0.12122330069541931, -0.012440010905265808, -0.07862704992294312, 0.05059393495321274, -0.05714474618434906, 0.004875373560935259, -0.43389150500297546, 0.40211087465286255, 0.19990304112434387, 0.03002910129725933, -0.09796170145273209, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.012324951589107513, 0.07461167871952057, -0.23338769376277924, -0.09286235272884369, -0.21748636662960052, -0.263963520526886, -0.30504775047302246, -0.0506148524582386, 0.32261571288108826, 0.04814055934548378, -0.02552524209022522, 0.2845093309879303, 0.09597959369421005, -0.8433988690376282, -0.9214555025100708, 0.19043029844760895, -0.0013341768644750118, 0.9389455914497375, -0.01563170552253723, 4.057375907897949, -0.7765541672706604, -0.500084400177002, 1.8908483982086182, -0.8329285383224487, 0.0647936463356018, -0.2659827470779419, 0.4201219975948334, -0.21463772654533386, 0.4986664652824402, -0.008350467309355736, -0.5678408741950989, -0.22023393213748932, -0.8514680862426758, -0.7250451445579529, 0.07251355051994324, 0.5639902949333191], [2.6132864952087402, 0.11474278569221497, -1.1875439882278442, 0.08727278560400009, 0.350195974111557, 0.16281171143054962, 0.2696371078491211, -0.014045678079128265, 0.011967220343649387, 0.42949536442756653, 0.12844811379909515, 0.03729693591594696, 0.2962784171104431, -0.05427180230617523, 0.041890569031238556, 0.013666939921677113, 0.3935892879962921, -0.09788478910923004, -0.5761059522628784, 0.04162116348743439, -0.06887190788984299, 0.5794637799263, 0.18559475243091583, -0.3154396116733551, 0.6642491817474365, -0.6452473402023315, 0.2485099583864212, 0.6817004084587097, -0.035314615815877914, -0.009466511197388172, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.3232257068157196, 0.13422410190105438, -0.2022862732410431, -0.3770114481449127, -0.09454400092363358, -0.17272712290287018, -0.5820512771606445, 0.16122348606586456, -0.05130894109606743, -0.16440188884735107, 0.17028340697288513, 0.15512718260288239, 0.09125979989767075, -0.5785070061683655, -1.1066011190414429, 0.7337412238121033, -0.03251640498638153, 1.409575343132019, -0.3787166178226471, -1.2770344018936157, 0.4986002445220947, 0.9115892648696899, 1.7626559734344482, -0.6308693885803223, -0.4788849651813507, 0.11088376492261887, 3.6708710193634033, 0.07182922959327698, 0.6218556761741638, 2.558687925338745, 1.2808705568313599, -1.5308001041412354, 1.8274317979812622, 0.0769834965467453, 1.152157187461853, 0.5971553325653076]], "betas": [[-1.075334072113037, 2.1554906368255615, -0.0024729780852794647, -0.002027775626629591, 0.00021802663104608655, 0.0018742450047284365, 0.0006536879809573293, 0.0014724887441843748, 0.0002471370389685035, 0.0012962812324985862], [-2.4677021503448486, 1.7435376644134521, 0.012419896200299263, 0.0009412216604687274, -0.005448587704449892, 0.0012451957445591688, 0.004141497891396284, 0.001362102571874857, -0.0010997280478477478, 0.0023973393253982067]], "transl": [[0.028418976813554764, 0.21810367703437805, -0.013384993188083172], [-0.002483887830749154, 0.15207047760486603, 0.008026457391679287]], "joints3d": [[[41.426170349121094, 240.61802673339844, 4152.2978515625], [94.70537567138672, 324.7584228515625, 4119.87548828125], [-18.0919246673584, 323.4455261230469, 4156.81884765625], [51.590492248535156, 153.46893310546875, 4191.22265625], [138.79425048828125, 648.5712280273438, 3931.1435546875], [-217.6263885498047, 640.00244140625, 4079.802001953125], [56.54252243041992, 23.57903480529785, 4205.55712890625], [263.189208984375, 980.8530883789062, 4086.36474609375], [-207.27548217773438, 997.9205322265625, 4223.45751953125], [53.57373809814453, -27.69928741455078, 4201.771484375], [236.68836975097656, 1070.8701171875, 4001.12841796875], [-277.3883972167969, 1078.231689453125, 4156.9248046875], [84.48860931396484, -216.78524780273438, 4248.45458984375], [135.33303833007812, -128.01605224609375, 4206.37109375], [19.15258026123047, -131.59136962890625, 4271.55712890625], [89.47433471679688, -283.8108215332031, 4197.4267578125], [202.92111206054688, -135.9115753173828, 4158.18017578125], [-49.87980651855469, -136.05874633789062, 4325.3583984375], [113.3488540649414, 43.84446334838867, 4004.884033203125], [-135.9793243408203, 91.94648742675781, 4313.86865234375], [29.283302307128906, -174.23789978027344, 4042.47265625], [-286.0304260253906, -97.80496215820312, 4272.65576171875]], [[-701.628173828125, 211.92449951171875, 4471.12158203125], [-663.846435546875, 290.01397705078125, 4418.65380859375], [-745.3009643554688, 293.0545654296875, 4506.46923828125], [-684.9773559570312, 130.60348510742188, 4493.3818359375], [-636.4866943359375, 619.7566528320312, 4322.0302734375], [-757.8023071289062, 640.5216674804688, 4519.45068359375], [-701.6194458007812, 14.3761625289917, 4483.0205078125], [-565.3842163085938, 957.6741333007812, 4356.05419921875], [-746.217041015625, 983.8676147460938, 4553.203125], [-701.1876831054688, -32.72135543823242, 4478.91064453125], [-564.4168090820312, 1060.5576171875, 4304.3984375], [-803.285888671875, 1081.0604248046875, 4542.8134765625], [-702.513427734375, -217.50311279296875, 4477.53125], [-650.1932983398438, -136.3037109375, 4444.21337890625], [-737.8165283203125, -137.58920288085938, 4527.80908203125], [-712.02392578125, -279.6893310546875, 4432.3076171875], [-594.736083984375, -153.1875, 4394.4462890625], [-787.9766235351562, -169.64761352539062, 4579.4990234375], [-639.2223510742188, 52.892208099365234, 4302.89599609375], [-806.65087890625, 41.35525131225586, 4646.0341796875], [-745.5147094726562, -19.58878517150879, 4134.3134765625], [-777.100341796875, 52.636383056640625, 4426.8388671875]]]}, {"global_orient": [[2.7800867557525635, 0.0928935706615448, -0.42212527990341187], [2.624682903289795, 0.13436630368232727, -1.129225492477417]], "body_pose": [[2.7800867557525635, 0.0928935706615448, -0.42212527990341187, -0.1435963213443756, -0.028538675978779793, 0.23586972057819366, -0.08778007328510284, -0.03857128322124481, -0.29520130157470703, 0.21084575355052948, -0.004997330252081156, 0.016105622053146362, 0.8089141249656677, -0.33926624059677124, -0.16924665868282318, 0.6532904505729675, 0.18348638713359833, 0.2002812623977661, -0.1513262391090393, -0.13427723944187164, -0.03512555733323097, -0.06118610128760338, 0.19350901246070862, -0.11565344035625458, -0.06978049874305725, -0.4880960285663605, 0.3852022588253021, 0.20907793939113617, 0.05431836098432541, -0.07112317532300949, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.07579194754362106, 0.011511160060763359, -0.18577826023101807, -0.07827989012002945, -0.27610668540000916, -0.30898433923721313, -0.3008582890033722, 0.020092904567718506, 0.3220284581184387, -0.07037821412086487, -0.07956935465335846, 0.3114403486251831, 0.06893711537122726, -0.8569793701171875, -0.8223187923431396, 0.1211693063378334, 0.0022500893101096153, 0.7951492071151733, 0.11765103787183762, 4.106408596038818, -0.7647847533226013, -0.5872426629066467, 1.901679515838623, -0.8774597644805908, 0.18458722531795502, -0.3158160448074341, 0.477962851524353, -0.159360870718956, 0.5223599076271057, -0.06939426064491272, -0.6745516061782837, -0.17620661854743958, -0.820586085319519, -0.9948176145553589, 0.17418070137500763, 1.0775012969970703], [2.624682903289795, 0.13436630368232727, -1.129225492477417, 0.0891961008310318, 0.35148438811302185, 0.19940179586410522, 0.2895456552505493, 0.006590938661247492, 0.013259893283247948, 0.3884458839893341, 0.17003074288368225, 0.058398909866809845, 0.3353753089904785, -0.03715793043375015, 0.05901660397648811, 0.049241021275520325, 0.3866952061653137, -0.08674368262290955, -0.529905378818512, 0.012137364596128464, -0.07133758813142776, 0.43172788619995117, 0.13163265585899353, -0.32429027557373047, 0.5087069869041443, -0.6111498475074768, 0.24289849400520325, 0.6900442838668823, -0.023747306317090988, -0.011887849308550358, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.41051459312438965, 0.13080433011054993, -0.10584218800067902, -0.35079798102378845, -0.13994257152080536, -0.1315157264471054, -0.5698720812797546, 0.16136233508586884, -0.14504414796829224, -0.0070187728852033615, 0.13686040043830872, 0.10375169664621353, -0.010149694047868252, -0.7526469826698303, -0.9693468809127808, 0.6781463623046875, -0.02800108678638935, 1.4089988470077515, -0.5941727757453918, -1.3484728336334229, 0.4012053608894348, 0.7344275712966919, 2.178090810775757, -1.6152747869491577, -0.16167029738426208, 0.22594192624092102, 3.951784372329712, 0.1936027854681015, -1.306923747062683, 2.4891719818115234, 0.03391498327255249, -0.28478893637657166, 2.8816232681274414, -0.04525778815150261, 1.8406015634536743, -0.05684792622923851]], "betas": [[-1.0579863786697388, 2.295011043548584, -0.003091887105256319, -0.002489781007170677, 2.2927384634385817e-05, 0.002003665314987302, 0.0009345025755465031, 0.0016231777844950557, -5.5752068874426186e-05, 0.0016291841166093946], [-2.036236047744751, 2.3501367568969727, 0.005799497943371534, 0.0010045033413916826, -0.0032663557212799788, 0.0009367025922983885, 0.00197608582675457, 0.0024479415733367205, -0.0005404410767368972, 0.0016170976450666785]], "transl": [[0.02601330168545246, 0.22115913033485413, 0.001823664759285748], [-0.002195817418396473, 0.17227275669574738, 0.018420584499835968]], "joints3d": [[[32.6641731262207, 231.20216369628906, 4169.56396484375], [84.97966003417969, 316.550048828125, 4139.966796875], [-27.771854400634766, 312.9276123046875, 4173.3095703125], [43.02596664428711, 143.89659118652344, 4207.4267578125], [147.83656311035156, 633.427001953125, 3941.38818359375], [-219.7049102783203, 633.4039306640625, 4085.374755859375], [50.21697235107422, 13.155107498168945, 4216.2421875], [254.01588439941406, 978.6982421875, 4085.044189453125], [-207.08351135253906, 997.7776489257812, 4215.75146484375], [49.669715881347656, -37.807281494140625, 4209.90380859375], [247.2089080810547, 1064.0888671875, 3991.288330078125], [-285.6680908203125, 1068.1522216796875, 4147.09521484375], [79.7387924194336, -228.5339813232422, 4247.77197265625], [132.00975036621094, -136.87646484375, 4215.26708984375], [11.989818572998047, -145.47479248046875, 4270.595703125], [81.85031127929688, -291.82354736328125, 4191.30712890625], [199.97903442382812, -138.33462524414062, 4167.5126953125], [-63.6553840637207, -155.39501953125, 4313.150390625], [113.43342590332031, 37.589107513427734, 4006.935302734375], [-186.32183837890625, 56.17121505737305, 4308.904296875], [31.639217376708984, -184.32164001464844, 4027.299560546875], [-302.6521301269531, -156.57525634765625, 4266.521484375]], [[-728.4804077148438, 222.29490661621094, 4563.2978515625], [-691.034423828125, 302.35064697265625, 4514.36279296875], [-772.704833984375, 303.53533935546875, 4596.3203125], [-711.3372802734375, 139.33668518066406, 4586.224609375], [-653.909423828125, 642.9752197265625, 4404.513671875], [-792.3222045898438, 665.7111206054688, 4613.57861328125], [-724.0999145507812, 17.395015716552734, 4577.40576171875], [-570.6221313476562, 993.8038940429688, 4445.57763671875], [-775.2210693359375, 1023.2428588867188, 4659.80712890625], [-721.756591796875, -30.286897659301758, 4576.0205078125], [-571.5115356445312, 1092.7484130859375, 4379.43896484375], [-840.8742065429688, 1117.4622802734375, 4636.359375], [-726.2125244140625, -216.49026489257812, 4570.30859375], [-669.497314453125, -134.2052764892578, 4543.111328125], [-762.510009765625, -135.45481872558594, 4621.09228515625], [-733.8823852539062, -287.0045166015625, 4531.33544921875], [-613.8129272460938, -153.90829467773438, 4493.4072265625], [-814.2929077148438, -175.594970703125, 4667.3173828125], [-675.0570678710938, 32.24872970581055, 4357.2392578125], [-855.5541381835938, 38.9237060546875, 4739.2998046875], [-776.5835571289062, -87.20289611816406, 4201.55517578125], [-786.0223999023438, -99.25513458251953, 4568.4130859375]]]}, {"global_orient": [[2.7281622886657715, 0.15469510853290558, -0.2875867784023285], [2.6375842094421387, 0.1424749791622162, -1.1003481149673462]], "body_pose": [[2.7281622886657715, 0.15469510853290558, -0.2875867784023285, -0.08597537875175476, -0.0025622330140322447, 0.3248884677886963, 0.025726787745952606, -0.05343758314847946, -0.22121211886405945, 0.24920453131198883, -0.018308566883206367, 0.0032118193339556456, 0.7557427287101746, -0.3608718812465668, -0.16074220836162567, 0.6237513422966003, 0.17005525529384613, 0.21722686290740967, -0.15256226062774658, -0.12456062436103821, -0.007794667035341263, -0.04122629016637802, 0.25245875120162964, -0.16543665528297424, -0.04156691953539848, -0.46189799904823303, 0.34524720907211304, 0.24709093570709229, 0.033055249601602554, -0.0652589425444603, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.11018699407577515, -0.031830620020627975, -0.13097091019153595, -0.048594046384096146, -0.31071901321411133, -0.3440154194831848, -0.3377462327480316, 0.11178548634052277, 0.4064517021179199, -0.06384316086769104, -0.09867283701896667, 0.31329482793807983, 0.08964952081441879, -0.8860138058662415, -0.7295384407043457, 0.06844533979892731, 0.1502729207277298, 0.70317542552948, -0.05315971001982689, -2.0347211360931396, 0.4280865490436554, -0.5560175776481628, 1.9146065711975098, -0.7393155694007874, 0.1618710160255432, -0.32124200463294983, 0.5110176801681519, -0.15217357873916626, 0.6410645246505737, -0.073769211769104, -0.7212107181549072, -0.11072932928800583, -0.8609384894371033, -0.7750939726829529, 0.1222623735666275, 0.8149048686027527], [2.6375842094421387, 0.1424749791622162, -1.1003481149673462, 0.05970030650496483, 0.32439637184143066, 0.22016197443008423, 0.30470970273017883, -0.0056417942978441715, 0.05862291157245636, 0.3722468316555023, 0.18571926653385162, 0.049626220017671585, 0.32446056604385376, -0.04363258555531502, 0.08632264286279678, 0.03920812904834747, 0.3934814929962158, -0.14843957126140594, -0.479228138923645, 0.00381490308791399, -0.06935790926218033, 0.43314340710639954, 0.18611003458499908, -0.373569130897522, 0.45995670557022095, -0.7246583700180054, 0.27525776624679565, 0.6691182255744934, -0.009942151606082916, 0.006071930751204491, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.3741796612739563, 0.17902402579784393, -0.06676366925239563, -0.33647847175598145, -0.13229620456695557, -0.20462441444396973, -0.566507875919342, 0.1565515100955963, -0.06445932388305664, -0.08003446459770203, 0.0902370810508728, 0.12450136989355087, 0.025982463732361794, -0.6783885359764099, -0.9648171663284302, 0.6772404313087463, -0.07478480041027069, 1.348944067955017, -0.5490620732307434, -1.4167120456695557, 0.4099096655845642, 0.7628974318504333, 2.1769285202026367, -1.7346761226654053, 0.1662263125181198, -0.6454505920410156, -1.3645113706588745, 0.23030106723308563, -1.6264148950576782, 2.3626954555511475, -0.10730896890163422, 0.8690686225891113, 2.346142053604126, 0.00728175463154912, 1.789418339729309, 0.04121242091059685]], "betas": [[-1.1671972274780273, 2.0925981998443604, -0.004498050548136234, -0.0020822619553655386, -6.8832259785267524e-06, 0.0018385403091087937, 0.000970258261077106, 0.0019950249698013067, -0.00036268908297643065, 0.0017075019422918558], [-2.083724021911621, 2.454498529434204, 0.003970338497310877, 0.0005043477285653353, -0.0031725531443953514, 0.001354430103674531, 0.001973864156752825, 0.0021254492457956076, -0.0003766912850551307, 0.001416195766068995]], "transl": [[0.011491888202726841, 0.2207457721233368, 0.005390196107327938], [-0.00565681979060173, 0.16794656217098236, 0.023899871855974197]], "joints3d": [[[10.979928016662598, 217.67274475097656, 4149.09521484375], [60.449222564697266, 304.6047058105469, 4118.4716796875], [-55.6246223449707, 294.64044189453125, 4142.9326171875], [23.945131301879883, 133.89370727539062, 4192.87548828125], [154.21311950683594, 613.979736328125, 3928.701171875], [-225.2038116455078, 621.5176391601562, 4051.422607421875], [39.086692810058594, 5.521965980529785, 4204.96630859375], [244.4873809814453, 963.9044799804688, 4059.60498046875], [-205.5236053466797, 981.5360107421875, 4180.3037109375], [41.05758285522461, -45.372711181640625, 4199.18310546875], [254.21649169921875, 1044.7430419921875, 3963.47314453125], [-273.6288146972656, 1055.7879638671875, 4106.60888671875], [73.66519165039062, -234.9917755126953, 4239.1435546875], [125.4579086303711, -142.5071258544922, 4209.2734375], [2.3819668292999268, -154.20489501953125, 4257.56494140625], [73.5821762084961, -296.8968505859375, 4182.6201171875], [194.12564086914062, -139.4339141845703, 4162.701171875], [-79.11244201660156, -159.93563842773438, 4287.94140625], [113.30013275146484, 28.331829071044922, 3994.362060546875], [-218.70492553710938, 28.6618595123291, 4226.84375], [29.209701538085938, -190.00904846191406, 4016.48583984375], [-296.2684326171875, -195.9876251220703, 4172.91259765625]], [[-728.23291015625, 214.01255798339844, 4522.87255859375], [-690.3115844726562, 294.3885498046875, 4475.79541015625], [-773.0402221679688, 294.5395812988281, 4555.4091796875], [-711.6693115234375, 131.40711975097656, 4545.04248046875], [-653.632568359375, 631.2300415039062, 4354.328125], [-780.0582275390625, 657.413818359375, 4566.1083984375], [-721.1171875, 9.379508018493652, 4535.78466796875], [-563.1715087890625, 981.5029296875, 4375.6416015625], [-771.3181762695312, 1014.2070922851562, 4615.54443359375], [-718.9190063476562, -37.89259338378906, 4532.7236328125], [-561.1306762695312, 1077.2054443359375, 4305.46630859375], [-843.1795654296875, 1104.256591796875, 4596.17431640625], [-724.5753173828125, -222.9843292236328, 4524.3798828125], [-666.5426635742188, -141.1221160888672, 4501.17333984375], [-761.83203125, -142.6111602783203, 4574.26904296875], [-733.0836791992188, -292.18597412109375, 4483.1181640625], [-608.1680908203125, -155.42835998535156, 4453.63330078125], [-817.7977905273438, -177.3845672607422, 4618.841796875], [-653.3724975585938, 45.18541717529297, 4333.24560546875], [-852.8956909179688, 36.855281829833984, 4693.4345703125], [-744.28564453125, -67.55580139160156, 4167.0986328125], [-776.4606323242188, -104.98542785644531, 4529.173828125]]]}, {"global_orient": [[2.7183446884155273, 0.18935149908065796, -0.220804363489151], [2.586028814315796, 0.16741058230400085, -1.0954166650772095]], "body_pose": [[2.7183446884155273, 0.18935149908065796, -0.220804363489151, -0.10898370295763016, 0.03235732391476631, 0.3990928828716278, 0.04926889017224312, -0.06721646338701248, -0.1732563078403473, 0.22393500804901123, -0.018215088173747063, 0.017987435683608055, 0.7373210191726685, -0.3441944718360901, -0.22812755405902863, 0.5681150555610657, 0.13171349465847015, 0.22190770506858826, -0.14644211530685425, -0.14892059564590454, -0.013704533688724041, 0.016154613345861435, 0.2679157853126526, -0.08316554129123688, -0.029033493250608444, -0.4701484739780426, 0.3287602961063385, 0.27086684107780457, 0.038878560066223145, -0.04153601452708244, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.133122518658638, -0.064092256128788, -0.11763761937618256, -0.06177109479904175, -0.30453258752822876, -0.3410571813583374, -0.3558540642261505, 0.13528499007225037, 0.38436344265937805, -0.06364931911230087, -0.09123744070529938, 0.29314056038856506, 0.1244228184223175, -0.8827069401741028, -0.7774288058280945, -0.0452449657022953, 0.11415401846170425, 0.5892729759216309, -0.008638478815555573, -2.019753932952881, 0.5053110122680664, -0.6065353155136108, 1.9887783527374268, -0.6342543363571167, 0.06349214911460876, -0.26186275482177734, 0.48262542486190796, -0.054795097559690475, 0.517539918422699, -0.23608574271202087, -0.656339704990387, -0.16704431176185608, -0.7786681056022644, -0.7795358300209045, 0.13178570568561554, 0.9539393186569214], [2.586028814315796, 0.16741058230400085, -1.0954166650772095, 0.13293366134166718, 0.3269592821598053, 0.23013877868652344, 0.36524197459220886, 0.02410041354596615, 0.0798727422952652, 0.4117056131362915, 0.17992642521858215, 0.06106719747185707, 0.2757294774055481, -0.05623486638069153, 0.10235217958688736, 0.009401025250554085, 0.3259761333465576, -0.16350646317005157, -0.4813779592514038, 0.003125504357740283, -0.05622308701276779, 0.4622955024242401, 0.17413003742694855, -0.36856043338775635, 0.5015673637390137, -0.739520251750946, 0.2390856146812439, 0.6708034873008728, -0.006514828652143478, 0.006059678271412849, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.4094398617744446, 0.14019827544689178, -0.031249750405550003, -0.3505282700061798, -0.09904374927282333, -0.13231897354125977, -0.5229319334030151, 0.14334991574287415, -0.10083365440368652, -0.016359683126211166, 0.10128650814294815, 0.10170711576938629, 0.03500021994113922, -0.6193659901618958, -1.1155188083648682, 0.6344677209854126, -0.0840924084186554, 1.4281935691833496, -0.5997666120529175, -1.3885711431503296, 0.55793696641922, 1.052040934562683, 2.3209927082061768, -1.4245996475219727, -0.6913906335830688, -0.2764376103878021, 3.469374895095825, -0.18234315514564514, 2.552924871444702, -1.9368852376937866, -0.6282040476799011, -0.8226091861724854, 2.926109552383423, 0.30399489402770996, 1.8097784519195557, 0.26845356822013855]], "betas": [[-1.2742975950241089, 1.9399758577346802, -0.005036521703004837, -0.0018129089148715138, -0.00041393772698938847, 0.0014431580202654004, 0.0007925830432213843, 0.0016536670736968517, -0.0009019976714625955, 0.001697121188044548], [-1.9160001277923584, 2.5004231929779053, 0.008118188939988613, 0.001979998080059886, -0.003217073855921626, 0.0023853436578065157, 0.0021980716846883297, 0.0014964148867875338, -0.000389127031667158, 0.0009594323928467929]], "transl": [[0.00850775744765997, 0.22205178439617157, 0.0011737947352230549], [-0.013226514682173729, 0.16403022408485413, 0.02094000019133091]], "joints3d": [[[-0.6766892671585083, 202.5876922607422, 4129.9609375], [47.44826126098633, 290.71258544921875, 4100.32666015625], [-70.14938354492188, 276.73956298828125, 4120.11474609375], [13.360509872436523, 120.16109466552734, 4175.015625], [163.0750274658203, 588.2926025390625, 3911.186279296875], [-227.2854461669922, 603.9220581054688, 4023.278076171875], [30.960607528686523, -5.933313369750977, 4192.8017578125], [218.80401611328125, 944.3206787109375, 4032.9833984375], [-205.44847106933594, 966.73779296875, 4130.578125], [34.14522171020508, -56.71641159057617, 4188.03759765625], [241.23641967773438, 1022.9352416992188, 3938.409423828125], [-272.0405578613281, 1037.4334716796875, 4053.75634765625], [65.1392593383789, -245.00872802734375, 4233.087890625], [117.90715026855469, -153.71287536621094, 4202.646484375], [-6.58310079574585, -164.28317260742188, 4247.2890625], [63.140682220458984, -306.3828430175781, 4177.3046875], [188.3245391845703, -151.8322296142578, 4159.05029296875], [-88.86994934082031, -171.16542053222656, 4274.15185546875], [110.48514556884766, 17.958553314208984, 3994.625244140625], [-250.6705780029297, -5.1479926109313965, 4210.18994140625], [27.10552406311035, -198.6378631591797, 4013.00439453125], [-301.73846435546875, -239.52389526367188, 4182.5654296875]], [[-740.5853271484375, 209.5558624267578, 4560.92919921875], [-706.2285766601562, 289.8766174316406, 4510.24609375], [-787.9534912109375, 290.19769287109375, 4590.7548828125], [-720.2008056640625, 127.58981323242188, 4586.7705078125], [-664.3212280273438, 631.6077880859375, 4392.609375], [-788.794921875, 657.2723388671875, 4598.7626953125], [-729.8563842773438, 3.8860108852386475, 4579.02978515625], [-569.208984375, 986.1864624023438, 4400.73583984375], [-781.96240234375, 1020.0467529296875, 4639.896484375], [-727.8798828125, -44.008914947509766, 4577.6005859375], [-567.0067749023438, 1082.5452880859375, 4329.09912109375], [-856.4501342773438, 1111.096435546875, 4627.20068359375], [-736.3466186523438, -230.65704345703125, 4572.53759765625], [-676.5772094726562, -149.37669372558594, 4547.15869140625], [-772.4148559570312, -148.0862579345703, 4621.98681640625], [-748.041015625, -303.1523742675781, 4536.390625], [-617.604248046875, -170.75538635253906, 4501.7001953125], [-828.3225708007812, -184.53306579589844, 4667.2021484375], [-658.04248046875, 40.90341567993164, 4393.77490234375], [-846.2905883789062, 35.2850227355957, 4739.71923828125], [-719.4213256835938, -63.5637092590332, 4206.14697265625], [-743.2161865234375, -81.04145812988281, 4566.20947265625]]]}, {"global_orient": [[2.7336840629577637, 0.20507404208183289, -0.1760300248861313], [2.590719699859619, 0.1413719207048416, -1.0493097305297852]], "body_pose": [[2.7336840629577637, 0.20507404208183289, -0.1760300248861313, -0.14149604737758636, 0.04713425040245056, 0.43965771794319153, 0.07800643891096115, -0.05725973844528198, -0.13897815346717834, 0.21708282828330994, 0.0001745839836075902, 0.04434143006801605, 0.6591408848762512, -0.3681279420852661, -0.300619900226593, 0.5281466841697693, 0.11297668516635895, 0.23366126418113708, -0.09583047032356262, -0.16019606590270996, -0.013791732490062714, 0.1179049164056778, 0.3349103033542633, -0.12104111164808273, -0.11814557015895844, -0.45442429184913635, 0.25856876373291016, 0.20251061022281647, 0.054041072726249695, -0.033479638397693634, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2030201554298401, -0.08438947796821594, -0.10279588401317596, -0.04458216577768326, -0.28846296668052673, -0.3559271991252899, -0.3908730149269104, 0.17770271003246307, 0.4143633246421814, -0.1937403827905655, -0.07056202739477158, 0.26487821340560913, 0.09934715181589127, -0.892229437828064, -0.815217912197113, -0.10974591970443726, 0.10901955515146255, 0.4000057876110077, 0.007284245919436216, -2.0264291763305664, 0.4795645475387573, -0.6032515168190002, 1.9884814023971558, -0.5725188255310059, 0.10495754331350327, -0.2846102714538574, 0.4978138208389282, -0.023272717371582985, 0.3952195346355438, -0.2607458531856537, -0.6687870025634766, -0.16857674717903137, -0.7031943798065186, -0.3344613313674927, 0.2582606375217438, 0.679028332233429], [2.590719699859619, 0.1413719207048416, -1.0493097305297852, 0.13670367002487183, 0.29537251591682434, 0.20397567749023438, 0.3866928517818451, -0.005359345115721226, 0.09303800016641617, 0.39809224009513855, 0.25186026096343994, 0.09634546935558319, 0.28428414463996887, -0.0016501263016834855, 0.1324291080236435, -0.057244013994932175, 0.23191681504249573, -0.17045791447162628, -0.41575902700424194, -0.02988843247294426, -0.11753911525011063, 0.48144251108169556, 0.16076357662677765, -0.37655553221702576, 0.6227455735206604, -0.5418123602867126, 0.18099939823150635, 0.5485649108886719, -0.008272087201476097, 0.027468357235193253, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.3531346917152405, 0.06718744337558746, 0.02260969951748848, -0.25818607211112976, -0.13961198925971985, -0.27246925234794617, -0.5103579759597778, 0.12745380401611328, -0.04427177831530571, 0.00011715081927832216, 0.11352439224720001, 0.06043292209506035, 0.07750536501407623, -0.6748587489128113, -0.9402949213981628, 0.6787651777267456, -0.13029608130455017, 1.2972255945205688, -0.5374975800514221, -1.5210754871368408, 0.4792841970920563, 0.7669994831085205, 2.283993721008301, -1.6082247495651245, 0.26648616790771484, -0.2062055766582489, -1.9854525327682495, -0.5318726897239685, -1.3467984199523926, 2.0098440647125244, -0.4818047285079956, -0.058079641312360764, 2.7067384719848633, 0.12160910665988922, 1.9343523979187012, -0.8841603994369507]], "betas": [[-1.0269420146942139, 2.1433465480804443, -0.006477229297161102, -0.0026680228766053915, -0.0002282012574141845, 0.0016666464507579803, 0.0010598874650895596, 0.0018988869851455092, -0.001056154491379857, 0.0015625623054802418], [-1.8484549522399902, 2.9795477390289307, 0.00479246536269784, 0.00013884284999221563, -0.0029373776633292437, 0.002317598555237055, 0.0023530262988060713, 0.0019661299884319305, -0.0003029228828381747, 0.0009417056571692228]], "transl": [[0.00835178792476654, 0.2268683761358261, 0.004967524204403162], [-0.012465675361454487, 0.16584506630897522, 0.02445167303085327]], "joints3d": [[[-9.653550148010254, 192.8544158935547, 4149.3642578125], [37.19761276245117, 282.87115478515625, 4122.71826171875], [-79.46287536621094, 266.8750915527344, 4138.86376953125], [4.599297046661377, 108.7077865600586, 4194.2080078125], [170.56993103027344, 580.16650390625, 3930.615478515625], [-229.65184020996094, 606.9041137695312, 4046.699462890625], [21.433794021606445, -20.23579978942871, 4211.23779296875], [202.0646514892578, 955.4256591796875, 4026.072021484375], [-202.38877868652344, 977.3259887695312, 4155.58447265625], [24.188962936401367, -71.445068359375, 4204.76318359375], [228.1149444580078, 1039.125244140625, 3933.954345703125], [-270.94598388671875, 1039.607177734375, 4070.019775390625], [51.2911376953125, -261.7140197753906, 4251.2998046875], [107.04621887207031, -169.54205322265625, 4224.64013671875], [-21.219083786010742, -179.38807678222656, 4261.73876953125], [49.290077209472656, -321.441162109375, 4191.4892578125], [181.11029052734375, -166.43016052246094, 4185.75341796875], [-107.26741027832031, -184.26959228515625, 4279.6328125], [103.93559265136719, 8.450604438781738, 4019.46142578125], [-294.0514221191406, -45.5108528137207, 4203.90625], [24.058746337890625, -215.04888916015625, 4028.79638671875], [-314.0015869140625, -290.3263854980469, 4187.86962890625]], [[-750.1027221679688, 197.99940490722656, 4576.63671875], [-713.7068481445312, 277.42279052734375, 4528.205078125], [-795.3898315429688, 279.4156188964844, 4603.4443359375], [-732.8486328125, 116.165771484375, 4602.8828125], [-671.9390258789062, 624.3036499023438, 4405.671875], [-784.8902587890625, 652.5233764648438, 4606.85009765625], [-744.3892822265625, -9.191597938537598, 4598.1162109375], [-570.0509643554688, 982.5079345703125, 4412.8427734375], [-778.5220947265625, 1022.211181640625, 4624.51904296875], [-741.8406372070312, -56.543792724609375, 4596.0556640625], [-562.861572265625, 1080.0966796875, 4341.7841796875], [-844.3601684570312, 1119.5211181640625, 4605.0849609375], [-743.8507080078125, -241.87876892089844, 4601.8837890625], [-685.8427734375, -160.0279998779297, 4576.9560546875], [-784.4295043945312, -157.86572265625, 4643.27490234375], [-757.5093383789062, -317.40008544921875, 4569.1220703125], [-625.1958618164062, -171.85255432128906, 4531.822265625], [-842.5523681640625, -190.222412109375, 4687.2431640625], [-668.0796508789062, 34.23733139038086, 4408.875], [-881.9849853515625, 28.95758056640625, 4760.28076171875], [-746.4700927734375, -101.94882202148438, 4246.81396484375], [-794.27685546875, -115.71621704101562, 4596.22265625]]]}, {"global_orient": [[2.732316255569458, 0.23896542191505432, -0.19900889694690704], [2.5914506912231445, 0.14362236857414246, -1.0103542804718018]], "body_pose": [[2.732316255569458, 0.23896542191505432, -0.19900889694690704, -0.14294077455997467, 0.11805658787488937, 0.5194562077522278, 0.12340106070041656, -0.005570987239480019, -0.08976826071739197, 0.20942425727844238, 0.0010363240726292133, 0.06907155364751816, 0.6721561551094055, -0.24566060304641724, -0.32247236371040344, 0.4586440920829773, 0.05454300716519356, 0.2346397340297699, -0.0587049201130867, -0.14683903753757477, -0.031201908364892006, 0.21512842178344727, 0.24892736971378326, -0.07173506170511246, -0.10639496147632599, -0.37212228775024414, 0.2394581437110901, 0.18961524963378906, 0.05208690091967583, -0.018436312675476074, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.19686467945575714, -0.1117093563079834, -0.03314054012298584, -0.07789543271064758, -0.31756138801574707, -0.40189129114151, -0.3982633650302887, 0.246125727891922, 0.38854774832725525, -0.208931565284729, -0.011718731373548508, 0.19197990000247955, 0.14158503711223602, -0.8417401909828186, -0.7393367290496826, 0.0288451686501503, 0.23725469410419464, 0.28909823298454285, -0.049575600773096085, -2.0247836112976074, 0.47333529591560364, -0.6210392117500305, 1.8565492630004883, -0.684080183506012, 0.21698375046253204, -0.3355070650577545, 0.48118945956230164, -0.04784896969795227, 0.2406991571187973, -0.43252548575401306, -0.6476349234580994, -0.15901237726211548, -0.7314372658729553, -0.08560176193714142, 0.3361329138278961, 0.6151719689369202], [2.5914506912231445, 0.14362236857414246, -1.0103542804718018, 0.13235042989253998, 0.2747936248779297, 0.18269774317741394, 0.3972241282463074, -0.008521056734025478, 0.08892590552568436, 0.42871415615081787, 0.2520086467266083, 0.10322286933660507, 0.31353795528411865, -0.043261900544166565, 0.1295841634273529, -0.04379173740744591, 0.15492957830429077, -0.16001883149147034, -0.387672483921051, -0.021809328347444534, -0.11237089335918427, 0.4728979468345642, 0.16582711040973663, -0.36956295371055603, 0.5722535252571106, -0.5356728434562683, 0.1263033002614975, 0.5418033003807068, -0.01031067781150341, 0.02341560088098049, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.38110026717185974, 0.0866527259349823, 0.021626250818371773, -0.24254131317138672, -0.1119295209646225, -0.2507942020893097, -0.5054227113723755, 0.11268932372331619, -0.03200072422623634, 0.023163320496678352, 0.08319994807243347, 0.05124970152974129, 0.008444365113973618, -0.7637880444526672, -0.9668489694595337, 0.71943598985672, 0.10441739112138748, 1.4043070077896118, -0.5078555941581726, -1.4910670518875122, 0.4302065968513489, 0.8700276613235474, 2.0305349826812744, -1.6392418146133423, -0.3393872380256653, 0.043864816427230835, 3.9299652576446533, -0.5023928284645081, -1.2482171058654785, 1.9095977544784546, -0.35642319917678833, -0.31067875027656555, 2.8695571422576904, 0.041700247675180435, 1.914059042930603, -0.728775143623352]], "betas": [[-1.0064842700958252, 2.1288154125213623, -0.006096767261624336, -0.003456724574789405, -0.0007404458010569215, 0.0014750444097444415, 0.0010613375343382359, 0.0019299907144159079, -0.0010128539288416505, 0.0014826240949332714], [-1.7582206726074219, 2.9662563800811768, 0.006219932343810797, 0.00027633990976028144, -0.003232141025364399, 0.002067661378532648, 0.0024060148280113935, 0.002052270108833909, -0.0003225144755560905, 0.0010862341150641441]], "transl": [[0.004883095156401396, 0.23033368587493896, 0.008152986876666546], [-0.009443053044378757, 0.16602914035320282, 0.02963574044406414]], "joints3d": [[[-21.70891571044922, 180.26199340820312, 4148.64599609375], [22.78018569946289, 271.3497619628906, 4121.1611328125], [-93.31275939941406, 252.9280548095703, 4139.73388671875], [-4.757810592651367, 96.21334075927734, 4193.1845703125], [176.29368591308594, 564.9066772460938, 3938.025634765625], [-234.3112030029297, 600.3646850585938, 4060.276611328125], [12.10673713684082, -32.76015090942383, 4211.01953125], [179.9253387451172, 942.123046875, 4032.7294921875], [-202.18115234375, 973.3723754882812, 4160.31298828125], [15.297276496887207, -83.79251861572266, 4202.814453125], [215.23851013183594, 1032.8697509765625, 3950.702392578125], [-264.35406494140625, 1034.5201416015625, 4068.984619140625], [42.303794860839844, -275.1547546386719, 4246.00048828125], [98.24715423583984, -182.51458740234375, 4220.65771484375], [-30.1987361907959, -192.81021118164062, 4258.185546875], [34.5656623840332, -335.3551940917969, 4187.07470703125], [171.02374267578125, -175.54347229003906, 4179.556640625], [-116.98059844970703, -201.4553985595703, 4271.4287109375], [102.03934478759766, -0.7751965522766113, 4009.19775390625], [-319.1686706542969, -99.58258819580078, 4177.87255859375], [20.227853775024414, -224.02081298828125, 4015.088134765625], [-305.64312744140625, -343.37274169921875, 4144.52099609375]], [[-756.3857421875, 195.6904754638672, 4642.6044921875], [-719.70068359375, 275.3538818359375, 4594.09765625], [-803.4585571289062, 277.14630126953125, 4667.40087890625], [-738.44189453125, 113.80626678466797, 4670.6298828125], [-685.9503784179688, 624.2993774414062, 4469.81982421875], [-795.1484375, 652.1250610351562, 4671.640625], [-751.3907470703125, -12.082466125488281, 4663.85302734375], [-585.760009765625, 985.1751708984375, 4484.2529296875], [-782.8470458984375, 1023.9036254882812, 4691.92041015625], [-750.072021484375, -59.75654220581055, 4660.39892578125], [-580.9962768554688, 1084.6640625, 4414.38818359375], [-855.394287109375, 1117.9935302734375, 4675.97265625], [-756.6685791015625, -246.08840942382812, 4659.9853515625], [-695.372802734375, -164.5258331298828, 4639.68994140625], [-797.1674194335938, -162.01504516601562, 4703.02392578125], [-769.0831298828125, -321.6117858886719, 4625.88671875], [-632.1900634765625, -177.95225524902344, 4597.64453125], [-858.0496826171875, -193.55079650878906, 4745.04833984375], [-681.2056274414062, 26.07109260559082, 4470.958984375], [-885.836181640625, 36.02351760864258, 4790.56640625], [-760.8818359375, -108.52166748046875, 4306.138671875], [-795.6921997070312, -107.62371826171875, 4624.9052734375]]]}, {"global_orient": [[2.759960174560547, 0.23452310264110565, -0.1471189260482788], [2.5647127628326416, 0.2187637984752655, -0.9514619708061218]], "body_pose": [[2.759960174560547, 0.23452310264110565, -0.1471189260482788, -0.1736411452293396, 0.11189649999141693, 0.5218142867088318, 0.11513867229223251, -0.017971938475966454, -0.08708668500185013, 0.22092318534851074, -0.0066094971261918545, 0.07508586347103119, 0.7302934527397156, -0.17178131639957428, -0.36146360635757446, 0.4272063076496124, 0.036379553377628326, 0.2450801581144333, -0.04422038793563843, -0.1483498364686966, -0.029959911480545998, 0.07405117154121399, 0.3984449505805969, -0.17989788949489594, -0.06493738293647766, -0.3476068675518036, 0.1963357776403427, 0.15982845425605774, 0.037642184644937515, -0.02260330505669117, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.24156606197357178, -0.09742292016744614, -0.03495629131793976, -0.05388945713639259, -0.2734954059123993, -0.3369486927986145, -0.35615605115890503, 0.22831909358501434, 0.36546024680137634, -0.26344034075737, -0.022489843890070915, 0.19509467482566833, 0.11981454491615295, -0.8807589411735535, -0.8297937512397766, -0.03770952671766281, 0.34506478905677795, 0.18984848260879517, -0.03359270468354225, -1.986645221710205, 0.5029736757278442, -0.6887281537055969, 1.7816033363342285, -0.6737901568412781, 0.17045985162258148, -0.35767921805381775, 0.49503833055496216, 0.01685446873307228, 0.2188567966222763, -0.3582240641117096, -0.6325542330741882, -0.1801728904247284, -0.6936874985694885, -0.3406740128993988, 0.2933201789855957, 0.7669558525085449], [2.5647127628326416, 0.2187637984752655, -0.9514619708061218, 0.22906681895256042, 0.36519092321395874, 0.23837479948997498, 0.505659282207489, 0.07516401261091232, 0.2163718342781067, 0.48992136120796204, 0.32920509576797485, 0.14142964780330658, 0.16998536884784698, -0.09292043000459671, 0.15484391152858734, -0.09738289564847946, 0.1922682523727417, -0.2557581067085266, -0.34645378589630127, 0.0024327707942575216, -0.14251519739627838, 0.6654151678085327, 0.2045208215713501, -0.39085158705711365, 0.7723740339279175, -0.6397355794906616, 0.2740667462348938, 0.4269290566444397, -0.031123902648687363, 0.0835743397474289, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.16655421257019043, -0.014773267321288586, 0.07240801304578781, -0.09415819495916367, 0.06718791276216507, -0.3951297104358673, -0.42344364523887634, -0.10607634484767914, 0.01671818271279335, -0.15604135394096375, 0.07110123336315155, 0.015652257949113846, 0.16510111093521118, -0.46967071294784546, -1.0421425104141235, 0.9036723375320435, 0.12455449998378754, 1.596623420715332, -0.3654530644416809, -0.7031527161598206, 0.24854110181331635, 1.1525518894195557, 1.4052447080612183, -0.13875630497932434, -0.6165406703948975, 0.25981611013412476, 3.532999038696289, 0.040007539093494415, 1.128433108329773, 2.47731876373291, 0.8514372110366821, -1.4708764553070068, 0.4557364583015442, 0.23703719675540924, 1.4898511171340942, 0.959195077419281]], "betas": [[-0.9893420934677124, 2.3787741661071777, -0.005723897367715836, -0.003671434009447694, -0.000577134545892477, 0.0017213256796821952, 0.0012233564630150795, 0.002051353920251131, -0.0006105505744926631, 0.0014235369162634015], [-1.8877564668655396, 3.071171998977661, 0.02174350433051586, 0.005304338876157999, -0.0022755071986466646, 0.0060433014295995235, 0.005381475668400526, -0.0003555725561454892, -0.0013135102344676852, 0.0008386544650420547]], "transl": [[0.006588762626051903, 0.23196835815906525, 0.014802498742938042], [-0.033668968826532364, 0.12531626224517822, 0.008773582987487316]], "joints3d": [[[-25.46942138671875, 169.77261352539062, 4144.0419921875], [19.036745071411133, 261.4803771972656, 4121.630859375], [-95.72035217285156, 242.76486206054688, 4135.32861328125], [-10.229705810546875, 84.50871276855469, 4185.52734375], [181.00318908691406, 555.4830322265625, 3940.338623046875], [-234.87930297851562, 594.158203125, 4056.5458984375], [5.1568121910095215, -45.9583740234375, 4198.46533203125], [156.02357482910156, 930.0687255859375, 4050.33740234375], [-200.17532348632812, 970.8178100585938, 4150.017578125], [8.106586456298828, -96.37525939941406, 4188.47705078125], [204.65081787109375, 1017.8709106445312, 3971.529052734375], [-258.68890380859375, 1034.04541015625, 4057.3828125], [33.38575744628906, -288.1081237792969, 4226.53564453125], [89.49510192871094, -195.14450073242188, 4205.080078125], [-37.95625305175781, -205.64004516601562, 4240.0380859375], [26.415390014648438, -344.9024658203125, 4163.19921875], [164.18113708496094, -192.7278289794922, 4168.39892578125], [-123.94124603271484, -216.55787658691406, 4252.8154296875], [94.41661834716797, -6.755356788635254, 4008.82763671875], [-335.0527038574219, -144.15623474121094, 4149.7373046875], [10.904115676879883, -229.86712646484375, 3992.8271484375], [-312.2923583984375, -389.4160461425781, 4124.986328125]], [[-764.3726806640625, 177.6959228515625, 4642.57177734375], [-732.067626953125, 258.6830139160156, 4594.52001953125], [-816.7977905273438, 255.60939025878906, 4665.1240234375], [-742.4908447265625, 98.2738037109375, 4671.08935546875], [-684.5113525390625, 611.767822265625, 4493.32373046875], [-780.2332153320312, 627.0682983398438, 4669.17431640625], [-752.304443359375, -26.823116302490234, 4660.41845703125], [-593.2528076171875, 972.2841186523438, 4482.76806640625], [-783.5518188476562, 996.1712646484375, 4688.9921875], [-748.8327026367188, -73.4555892944336, 4653.84814453125], [-579.0186157226562, 1077.1092529296875, 4424.7333984375], [-836.2178344726562, 1101.95654296875, 4677.06884765625], [-750.8621215820312, -257.8436279296875, 4663.9697265625], [-690.5948486328125, -176.3277130126953, 4646.21337890625], [-797.0253295898438, -173.4048309326172, 4696.5], [-770.479248046875, -326.88134765625, 4621.19384765625], [-618.6627807617188, -180.46971130371094, 4621.95458984375], [-854.3510131835938, -200.5269012451172, 4743.93359375], [-618.8499145507812, 60.24937438964844, 4585.63818359375], [-816.4635620117188, 23.36351776123047, 4800.20068359375], [-638.2200317382812, 184.71218872070312, 4398.916015625], [-664.403076171875, 98.30896759033203, 4637.06103515625]]]}, {"global_orient": [[2.7230618000030518, 0.2382401078939438, -0.17953042685985565], [2.6558897495269775, 0.20222093164920807, -0.8448997735977173]], "body_pose": [[2.7230618000030518, 0.2382401078939438, -0.17953042685985565, -0.10266857594251633, 0.17757967114448547, 0.5597376227378845, 0.2061571627855301, -0.025184929370880127, -0.06087847426533699, 0.21025456488132477, 0.005949109327048063, 0.08450695872306824, 0.7209454774856567, -0.07033336907625198, -0.3815619945526123, 0.30540329217910767, 0.0217716246843338, 0.2170039862394333, -0.05177312716841698, -0.16630975902080536, -0.043236616998910904, 0.013791944831609726, 0.4742744565010071, -0.1973879039287567, -0.04683319106698036, -0.36175987124443054, 0.17445267736911774, 0.18465527892112732, 0.051646552979946136, -0.016347281634807587, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.23888607323169708, -0.13524027168750763, -0.022178057581186295, -0.04100662097334862, -0.26176589727401733, -0.36231571435928345, -0.3619515597820282, 0.23143307864665985, 0.3298599421977997, -0.23320287466049194, 0.014761258848011494, 0.13084013760089874, 0.10034338384866714, -0.8787499070167542, -0.7912558913230896, -0.034451961517333984, 0.3937627375125885, 0.09752766788005829, -0.054876938462257385, -1.9985147714614868, 0.51226806640625, -0.6647504568099976, 1.7005486488342285, -0.6618835926055908, 0.21493126451969147, -0.36020395159721375, 0.5197795033454895, 0.08060968667268753, 0.019856713712215424, -0.3444534242153168, -0.7259021997451782, -0.11876747012138367, -0.7881263494491577, -0.2738175690174103, 0.21031752228736877, 0.574836790561676], [2.6558897495269775, 0.20222093164920807, -0.8448997735977173, 0.12975507974624634, 0.31918060779571533, 0.250814825296402, 0.43608686327934265, 0.07398626953363419, 0.2064279019832611, 0.3643631935119629, 0.3190510869026184, 0.16632992029190063, 0.22359628975391388, -0.04786437749862671, 0.17625555396080017, -0.050764333456754684, 0.1450878381729126, -0.21447141468524933, -0.31327396631240845, -0.018353253602981567, -0.14038442075252533, 0.5513871312141418, 0.19740930199623108, -0.4193580746650696, 0.6174400448799133, -0.5702815651893616, 0.22368478775024414, 0.4488663673400879, -0.03349611163139343, 0.0646742507815361, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.27489474415779114, -0.0068880897015333176, 0.09587401151657104, -0.155362069606781, 0.046370428055524826, -0.3339357078075409, -0.4964374005794525, -0.036700259894132614, -0.11631637066602707, 0.00835783313959837, 0.05788780003786087, -0.05757409706711769, 0.1054886057972908, -0.6887273192405701, -1.1034733057022095, 0.8666141629219055, 0.35517069697380066, 1.7862520217895508, -0.2039547562599182, -1.7260172367095947, 0.3429173231124878, -1.6285083293914795, -2.0623011589050293, 2.5317883491516113, -0.903607964515686, -0.028793547302484512, 3.9400534629821777, 0.06915617734193802, 0.166392520070076, 2.3233723640441895, -0.5978729128837585, -0.8438354134559631, 2.7460243701934814, -0.5752660632133484, 1.937197208404541, -0.7689152956008911]], "betas": [[-0.9866032004356384, 2.5770390033721924, -0.006335688754916191, -0.0036294565070420504, -0.0005710083059966564, 0.0019624794367700815, 0.0013915447052568197, 0.002447704551741481, -0.0004765819467138499, 0.0012156307930126786], [-1.6145097017288208, 2.9841511249542236, 0.009112486615777016, 0.0024883695878088474, -0.003581792348995805, 0.002722158096730709, 0.0028745722956955433, 0.0010507775004953146, -1.851861634349916e-05, 0.0006398728583008051]], "transl": [[0.0042603411711752415, 0.23234233260154724, 0.007709766272455454], [-0.027883293107151985, 0.16022829711437225, 0.016973337158560753]], "joints3d": [[[-34.18031311035156, 155.02227783203125, 4133.9892578125], [8.95981502532959, 245.8316192626953, 4108.09814453125], [-103.89295959472656, 227.63070678710938, 4124.81103515625], [-18.029775619506836, 71.33273315429688, 4177.06103515625], [182.63780212402344, 545.6282348632812, 3943.3876953125], [-232.49755859375, 589.1509399414062, 4067.0], [-2.777285575866699, -58.978599548339844, 4195.44775390625], [128.98123168945312, 920.1405029296875, 4048.636962890625], [-197.07044982910156, 973.0095825195312, 4132.466796875], [0.5333611965179443, -109.61334228515625, 4188.58837890625], [193.461181640625, 1005.7740478515625, 3979.13818359375], [-261.3731689453125, 1030.903076171875, 4040.067138671875], [25.523725509643555, -299.6583251953125, 4230.71826171875], [81.09415435791016, -207.525146484375, 4206.69140625], [-44.547813415527344, -216.5828399658203, 4243.2265625], [14.928627967834473, -359.2976989746094, 4169.7890625], [154.80792236328125, -204.45419311523438, 4169.3603515625], [-129.28062438964844, -230.3021697998047, 4257.79150390625], [86.01656341552734, -24.405879974365234, 4001.570556640625], [-350.045654296875, -192.30528259277344, 4155.25830078125], [9.22771167755127, -250.87399291992188, 3992.0400390625], [-307.7027587890625, -435.58203125, 4129.525390625]], [[-782.1856079101562, 188.4602508544922, 4672.671875], [-744.8494873046875, 272.19256591796875, 4631.13818359375], [-836.4083862304688, 266.8216552734375, 4694.36376953125], [-762.4545288085938, 105.81455993652344, 4700.7001953125], [-693.07421875, 625.2183837890625, 4515.57080078125], [-811.4417724609375, 644.2674560546875, 4702.76318359375], [-768.9866333007812, -22.02788734436035, 4697.5458984375], [-591.7792358398438, 990.1770629882812, 4512.77099609375], [-805.2529907226562, 1019.4688720703125, 4733.958984375], [-764.8959350585938, -69.99754333496094, 4693.34423828125], [-573.7568359375, 1090.0413818359375, 4443.52978515625], [-866.9810791015625, 1120.508544921875, 4708.3076171875], [-765.4634399414062, -257.5613098144531, 4704.3525390625], [-703.44580078125, -174.20654296875, 4689.28955078125], [-816.0344848632812, -172.10023498535156, 4734.51708984375], [-780.3662109375, -332.6445617675781, 4668.70068359375], [-628.675048828125, -181.26535034179688, 4668.78955078125], [-875.1314697265625, -208.43922424316406, 4777.08740234375], [-663.8319091796875, 46.695343017578125, 4579.45068359375], [-848.0299072265625, 27.251087188720703, 4794.36328125], [-732.229248046875, -96.09918975830078, 4413.05419921875], [-754.1260375976562, -107.75970458984375, 4620.33056640625]]]}] \ No newline at end of file diff --git a/src_joints2smpl_demo/README.md b/src_joints2smpl_demo/README.md new file mode 100644 index 0000000000000000000000000000000000000000..0158cf8ba545f1b93d128236300db0979cae9d1c --- /dev/null +++ b/src_joints2smpl_demo/README.md @@ -0,0 +1,20 @@ +# ADD to your environment + +´´´ +pip install smplx +´´´ + +#### Fix broken chumpy + +Due to some deprecated python function the normal `chumpy` version you get from `pip install chumpy` is broken. To fix this, we replaced the original `chumpy` with updated github fork. It should be installed automatically, alternatively, you can install it manually with + +```shell +pip install git+https://github.com/mikigom/chumpy.git +``` + +# FOr mesh computation + +Add to your environemnt +´´´ +conda install conda-forge::trimesh +´´´ \ No newline at end of file diff --git a/src_joints2smpl_demo/convert_joints2smpl.py b/src_joints2smpl_demo/convert_joints2smpl.py new file mode 100644 index 0000000000000000000000000000000000000000..15baf94b0b1a3ecd54f3d8d2aa26490602766ffe --- /dev/null +++ b/src_joints2smpl_demo/convert_joints2smpl.py @@ -0,0 +1,85 @@ +import torch +import numpy as np +import os + +from .mesh.io import save_obj, to_mesh +from .mesh.smpl2mesh import SMPL2Mesh +from .skeleton import SkeletonAMASS, convert2humanml +from .skeleton2smpl.skeleton2smpl import Skeleton2Obj +import json + + +def save_mesh(vertices, faces, npy_file): + def npy_path_to_obj_path(npy_path: str) -> str: + return os.path.join(os.path.dirname(npy_path) , f"{npy_path}_obj") + results_dir = npy_path_to_obj_path(npy_file) + os.makedirs(results_dir, exist_ok=True) + for frame_i in range(vertices.shape[-1]): + file_path = os.path.join(results_dir, f"frame{frame_i:03d}.obj") + mesh = to_mesh(vertices[..., frame_i], faces) + save_obj(mesh, file_path) + print(f"Saved obj files to [{results_dir}]") + +def main(): + num_smplify_iters = 20 # This is what requires most time. It can be decreased or increasd depending on the output quality we want (or how quick we canr each it) + device = "cuda" + + # get observation smpl params + json_file_path = "./smpl_params.json" + with open(json_file_path, "r") as json_file: + loaded_data = json.load(json_file) + person_idx = 0 + smpl_dict_last_obs = loaded_data[-1] + smpl_dict_last_obs = {k: torch.from_numpy(np.array(v)).float().to(device) for k,v in smpl_dict_last_obs.items()} + + input_kpts = smpl_dict_last_obs['joints3d'] + input_kpts = torch.stack([input_kpts[..., 0], input_kpts[..., 2], -input_kpts[..., 1]], dim=-1) + input_kpts = input_kpts/1000 + input_kpts = input_kpts - input_kpts[..., 0:1, :] + + # get predictions + pred_motions = torch.from_numpy(np.load( "./joints3d.npy", allow_pickle=True)).to(device) + + + pred_motions = torch.stack([pred_motions[..., 0], pred_motions[..., 2], -pred_motions[..., 1]], dim=-1) + + + # remove bacth dimension, add a zero hip joint + pred_motions = pred_motions.squeeze(0) + pred_motions = torch.cat([torch.zeros(*pred_motions.shape[:2], 1, 3).to(device), pred_motions], dim=-2) + + # select just some of the motions + # TO DO use the previous code with the limb length variance error to choose the sample + # Or pick the most diverse + pred_motions = pred_motions[:1] + pred_motions = pred_motions.view(-1, 22, 3) + + skeleton = SkeletonAMASS + pred_motions = convert2humanml(pred_motions, skeleton.LANDMARKS, skeleton.TO_HUMANML_NAMES) + + init_params = {} + init_params["betas"] = smpl_dict_last_obs["betas"][person_idx].unsqueeze(0).expand(pred_motions.shape[0], -1) + init_params["pose"] = smpl_dict_last_obs["body_pose"][person_idx].view(-1, 3) + assert init_params["pose"].shape[0] == 24, "the body pose should have 24 joints, it is the output of NLF" + + init_params["pose"] = init_params["pose"].unsqueeze(0).expand(pred_motions.shape[0], -1, -1).view(pred_motions.shape[0], -1).to(device) + init_params["cam"] = smpl_dict_last_obs["transl"][person_idx].unsqueeze(0).unsqueeze(-2).expand(pred_motions.shape[0], -1, -1).to(device) + + skeleton2obj = Skeleton2Obj( + device=device, num_smplify_iters=num_smplify_iters, + smpl_model_dir="./body_models/", #path to smpl body models + gmm_model_dir="./joint2smpl_models/", #path to gmm model + ) + rot_motions, smpl_dict = skeleton2obj.convert_motion_2smpl(pred_motions, hmp=True, init_params=init_params, fix_betas=True) + + smpl2mesh = SMPL2Mesh(device) + vertices, faces = smpl2mesh.convert_smpl_to_mesh(rot_motions, pred_motions) + + pred_files = [('./hanyu')] + vertices = vertices.reshape(*vertices.shape[:2], len(pred_files), -1) + for v, npy_file in zip(np.moveaxis(vertices, 2, 0), pred_files): + save_mesh(v, faces, npy_file) + + +if __name__ == "__main__": + main() diff --git a/src_joints2smpl_demo/convert_joints2smpl_testCecilia.py b/src_joints2smpl_demo/convert_joints2smpl_testCecilia.py new file mode 100644 index 0000000000000000000000000000000000000000..fc8619b04c095e37d12a007b8beaeefa341357e0 --- /dev/null +++ b/src_joints2smpl_demo/convert_joints2smpl_testCecilia.py @@ -0,0 +1,90 @@ +import torch +import numpy as np +import os + +from mesh.smpl2mesh import SMPL2Mesh + +from skeleton import SkeletonAMASS, convert2humanml +from mesh.io import save_obj, to_mesh +from skeleton2smpl.skeleton2smpl import Skeleton2Obj +import json + + +def get_humanml_motion(npy_file, skeleton, remove_global_translation=False): + + motion = torch.from_numpy(np.load(npy_file, allow_pickle=True)) + + if remove_global_translation: + #remove hip motion + motion = motion - motion[..., 0:1, :] + + humanml_motion = convert2humanml( + motion, skeleton.LANDMARKS, skeleton.TO_HUMANML_NAMES + ) + return humanml_motion + +def save_mesh(vertices, faces, npy_file): + def npy_path_to_obj_path(npy_path: str) -> str: + return os.path.join(os.path.dirname(npy_path) , f"{npy_path}_obj") + results_dir = npy_path_to_obj_path(npy_file) + os.makedirs(results_dir, exist_ok=True) + # create obs_obj and pred_obj folders + obs_obj_dir = os.path.join(results_dir, "obs_obj") + pred_obj_dir = os.path.join(results_dir, "pred_obj") + os.makedirs(obs_obj_dir, exist_ok=True) + os.makedirs(pred_obj_dir, exist_ok=True) + for frame_i in range(vertices.shape[-1]): + # first 30 frames save to obs_obj/ + if frame_i < 30: + file_path = os.path.join(results_dir, f"obs_obj/frame{frame_i:03d}.obj") + else: + file_path = os.path.join(results_dir, f"pred_obj/frame{frame_i:03d}.obj") + mesh = to_mesh(vertices[..., frame_i], faces) + save_obj(mesh, file_path) + print(f"Saved obj files to [{results_dir}]") + + +def main(): + test_directory = '/usr/wiss/curreli/work/my_exps/final_predictions_storage/hmp/visuals_50samples/amass/SkeletonDiffusion/test_optimization' + num_smplify_iters = 20 + device = "cuda" + + # Load the dictionary of arrays from the npz file + output_file = "src_joints2smpl_demo/obs_data.npz" + loaded_data = np.load(output_file, allow_pickle=True) + rot_motions_obs = loaded_data["rot_motions_obs"] + smpl_dict_obs = loaded_data['smpl_dict_obs'].item() + smpl_dict_obs = {k: torch.from_numpy(v).to(device) for k,v in smpl_dict_obs.items()} + print("Loaded observation data from npz file.") + + skeleton = SkeletonAMASS + skeleton2obj = Skeleton2Obj( + device=device, num_smplify_iters=num_smplify_iters, + smpl_model_dir="./models/body_models/", #path to smpl body models + gmm_model_dir="./models/joint2smpl_models/", #path to gmm model + ) + + # get all the npy files in the directory + pred_files = ['pred_closest_GT.npy'] + pred_motions = torch.cat([get_humanml_motion(npy_file, skeleton=skeleton, remove_global_translation=True) for npy_file in pred_files], dim=0) + pred_motions = pred_motions.view(-1, 22, 3).to(device) + + init_params = {} + init_params["betas"] = smpl_dict_obs["betas"][-1].unsqueeze(0).expand(pred_motions.shape[0], -1).to(device) + init_params["pose"] = smpl_dict_obs["pose"][-1].unsqueeze(0).expand(pred_motions.shape[0], -1, -1).view(pred_motions.shape[0], -1).to(device) + init_params["cam"] = smpl_dict_obs["cam"][-1].unsqueeze(0).expand(pred_motions.shape[0], -1, -1).to(device) + + rot_motions, smpl_dict = skeleton2obj.convert_motion_2smpl(pred_motions, hmp=True, init_params=init_params, fix_betas=True) + + smpl2mesh = SMPL2Mesh(device) + vertices, faces = smpl2mesh.convert_smpl_to_mesh(rot_motions, pred_motions) + + pred_files = [('pred_closest_GT.npy')] + vertices = vertices.reshape(*vertices.shape[:2], len(pred_files), -1) + for v, npy_file in zip(np.moveaxis(vertices, 2, 0), pred_files): + save_mesh(v, faces, npy_file) + + + +if __name__ == "__main__": + main() diff --git a/src_joints2smpl_demo/joints2smpl/__init__.py b/src_joints2smpl_demo/joints2smpl/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src_joints2smpl_demo/joints2smpl/convert_joints2smpl.py b/src_joints2smpl_demo/joints2smpl/convert_joints2smpl.py new file mode 100644 index 0000000000000000000000000000000000000000..62074fe4da23f3acd09a1366fd13fdd235fbbdcd --- /dev/null +++ b/src_joints2smpl_demo/joints2smpl/convert_joints2smpl.py @@ -0,0 +1,762 @@ +import torch +import numpy as np +import os + +from ..mesh.io import save_obj, to_mesh +from ..mesh.smpl2mesh import SMPL2Mesh +from ..skeleton import SkeletonAMASS, convert2humanml +from ..skeleton2smpl.skeleton2smpl import Skeleton2Obj +import json +from scipy.ndimage import gaussian_filter1d + + +def save_mesh(vertices, faces, output_dir, output_idx=None): + """Save mesh vertices and faces to obj files. + + Args: + vertices: Mesh vertices with shape (num_vertices, 3, num_frames) + faces: Mesh faces + output_dir: Directory to save the obj files + output_idx: Index of the prediction to save + """ + # create obs_obj and pred_{i}_obj folders + obs_obj_dir = os.path.join(output_dir, "obs_obj") + os.makedirs(obs_obj_dir, exist_ok=True) + + if output_idx is not None: + pred_obj_dir = os.path.join(output_dir, f"pred_{output_idx}_obj") + os.makedirs(pred_obj_dir, exist_ok=True) + + # Ensure vertices has the correct shape (num_vertices, 3, num_frames) + if len(vertices.shape) == 4: # If we have an extra batch dimension + vertices = vertices.squeeze(0) # Remove the batch dimension + + # Convert vertices to numpy if it's a tensor + if torch.is_tensor(vertices): + vertices = vertices.cpu().numpy() + if torch.is_tensor(faces): + faces = faces.cpu().numpy() + + print(f"Processing mesh for output index {output_idx}") + + # Save first 30 frames to obs_obj directory + for frame_i in range(30): + file_path = os.path.join(output_dir, f"obs_obj/frame{frame_i:03d}.obj") + frame_vertices = vertices[:, :, frame_i] + mesh = to_mesh(frame_vertices, faces) + save_obj(mesh, file_path) + + # Save remaining frames to pred directory + if output_idx is not None: + for frame_i in range(30, vertices.shape[2]): + file_path = os.path.join(output_dir, f"pred_{output_idx}_obj/frame{frame_i:03d}.obj") + frame_vertices = vertices[:, :, frame_i] + mesh = to_mesh(frame_vertices, faces) + save_obj(mesh, file_path) + + print(f"Saved obj files to [{output_dir}]") + +def main(): + num_smplify_iters = 20 # This is what requires most time. It can be decreased or increasd depending on the output quality we want (or how quick we canr each it) + device = "cuda" + + # get observation smpl params + json_file_path = "./smpl_params.json" + with open(json_file_path, "r") as json_file: + loaded_data = json.load(json_file) + person_idx = 0 + smpl_dict_last_obs = loaded_data[-1] + smpl_dict_last_obs = {k: torch.from_numpy(np.array(v)).float().to(device) for k,v in smpl_dict_last_obs.items()} + + # select just some of the motions + # TO DO use the previous code with the limb length variance error to choose the sample + # Or pick the most diverse + + skeleton = SkeletonAMASS + + pred_files = ['pred_closest_GT.npy'] + pred_motions = torch.from_numpy(np.load(pred_files[0], allow_pickle=True)).to(device) + pred_motions = pred_motions.view(-1, 22, 3) + pred_motions = convert2humanml(pred_motions, skeleton.LANDMARKS, skeleton.TO_HUMANML_NAMES) + loaded_data = np.load("obs_data.npz", allow_pickle=True) + rot_motions_obs = loaded_data["rot_motions_obs"] + smpl_dict_obs = loaded_data['smpl_dict_obs'].item() + smpl_dict_obs = {k: torch.from_numpy(v).to(device) for k,v in smpl_dict_obs.items()} + + + # init_params = {} + init_params = {} + current_motions = pred_motions + init_params["betas"] = smpl_dict_last_obs["betas"][person_idx].unsqueeze(0).expand(current_motions.shape[0], -1) + init_params["pose"] = smpl_dict_last_obs["body_pose"][person_idx].view(-1, 3) + # init_params["pose"] = torch.stack([init_params["pose"][..., 0], init_params["pose"][..., 2], -init_params["pose"][..., 1]], dim=-1) + assert init_params["pose"].shape[0] == 24, "the body pose should have 24 joints, it is the output of NLF" + + init_params["pose"] = init_params["pose"].unsqueeze(0).expand(current_motions.shape[0], -1, -1).view(current_motions.shape[0], -1).to(device) + + # init_params["pose"] = (torch.tensor([ 0.4531, 0.3044, 0.2968, -0.2239, 0.0174, 0.0925, -0.2378, -0.0465, + # -0.0786, 0.2782, 0.0141, 0.0138, 0.4328, -0.0629, -0.0961, 0.5043, + # 0.0035, 0.0610, 0.0230, -0.0317, 0.0058, 0.0070, 0.1317, -0.0544, + # -0.0589, -0.1752, 0.1355, 0.0134, -0.0037, 0.0089, -0.2093, 0.1600, + # 0.1092, -0.0387, 0.0824, -0.2041, -0.0056, -0.0075, -0.0035, -0.0237, + # -0.1248, -0.2736, -0.0459, 0.1991, 0.2373, 0.0667, -0.0405, 0.0329, + # 0.0536, -0.2914, -0.6969, 0.0559, 0.2858, 0.6525, 0.1222, -0.9116, + # 0.2383, -0.0366, 0.9237, -0.2554, -0.0657, -0.1045, 0.0501, -0.0388, + # 0.0909, -0.0707, -0.1437, -0.0590, -0.1801, -0.0875, 0.1093, 0.2009]) + # .unsqueeze(0) + # .repeat(pred_motions.shape[0], 1) + # .float().to(device) + # ) + # init_params["pose"] = (torch.tensor([ 0.4531, 0.3044, -1, -0.2239, 0.0174, 0.0925, -0.2378, -0.0465, + # -0.0786, 0.2782, 0.0141, 0.0138, 0.4328, -0.0629, -0.0961, 0.5043, + # 0.0035, 0.0610, 0.0230, -0.0317, 0.0058, 0.0070, 0.1317, -0.0544, + # -0.0589, -0.1752, 0.1355, 0.0134, -0.0037, 0.0089, -0.2093, 0.1600, + # 0.1092, -0.0387, 0.0824, -0.2041, -0.0056, -0.0075, -0.0035, -0.0237, + # -0.1248, -0.2736, -0.0459, 0.1991, 0.2373, 0.0667, -0.0405, 0.0329, + # 0.0536, -0.2914, -0.6969, 0.0559, 0.2858, 0.6525, 0.1222, -0.9116, + # 0.2383, -0.0366, 0.9237, -0.2554, -0.0657, -0.1045, 0.0501, -0.0388, + # 0.0909, -0.0707, -0.1437, -0.0590, -0.1801, -0.0875, 0.1093, 0.2009]) + # .unsqueeze(0) + # .repeat(pred_motions.shape[0], 1) + # .float().to(device) + # ) + init_params = {} + init_params["betas"] = smpl_dict_obs["betas"][-1].unsqueeze(0).expand(pred_motions.shape[0], -1).to(device) + # init_params["betas"] = torch.tensor([10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]).repeat(pred_motions.shape[0], 1).to(device) + init_params["pose"] = smpl_dict_obs["pose"][-1].unsqueeze(0).expand(pred_motions.shape[0], -1, -1).view(pred_motions.shape[0], -1).to(device) + init_params["cam"] = smpl_dict_obs["cam"][-1].unsqueeze(0).expand(pred_motions.shape[0], -1, -1).to(device) + init_params["pose"] = torch.zeros(pred_motions.shape[0], 72).to(device) + # # smpl_dict_last_obs["transl"][person_idx] = torch.stack([-smpl_dict_last_obs["transl"][person_idx][..., 2], smpl_dict_last_obs["transl"][person_idx][..., 0], -smpl_dict_last_obs["transl"][person_idx][..., 1]], dim=-1) + # init_params["cam"] = smpl_dict_last_obs["transl"][person_idx].unsqueeze(0).unsqueeze(-2).expand(current_motions.shape[0], -1, -1).to(device) + + skeleton2obj = Skeleton2Obj( + device=device, num_smplify_iters=num_smplify_iters, + smpl_model_dir="./models/body_models/", #path to smpl body models + gmm_model_dir="./models/joint2smpl_models/", #path to gmm model + ) + rot_motions, smpl_dict = skeleton2obj.convert_motion_2smpl(pred_motions, hmp=True, init_params=init_params, fix_betas=True) + + smpl2mesh = SMPL2Mesh(device) + vertices, faces = smpl2mesh.convert_smpl_to_mesh(rot_motions, pred_motions) + + pred_files = [('./hanyu_t')] + vertices = vertices.reshape(*vertices.shape[:2], len(pred_files), -1) + for v, npy_file in zip(np.moveaxis(vertices, 2, 0), pred_files): + save_mesh(v, faces, npy_file) + + +def process_motion(smpl_params_path, pred_motions_path, device, sorted_idx, output_dir='./hanyu_obj'): + num_smplify_iters = 40 + device = "cuda" + + # Load and preprocess data once + with open(smpl_params_path, "r") as json_file: + loaded_data = json.load(json_file) + person_idx = 0 + smpl_dict_last_obs = {k: torch.from_numpy(np.array(v)).float().to(device) for k,v in loaded_data[1].items()} + + # Load predictions and preprocess + pred_motions = torch.from_numpy(np.load(pred_motions_path, allow_pickle=True)).to(device) + pred_motions = pred_motions.squeeze(0)[sorted_idx] # Shape: (num_samples, num_frames, 22, 3) + + # Initialize skeleton once + skeleton = SkeletonAMASS + + # Pre-allocate lists for results + all_vertices = [] + all_faces = None + first_rot_motions = None + first_smpl_dict = None + + # Pre-compute common parameters + init_betas = smpl_dict_last_obs["betas"][person_idx] + init_pose = smpl_dict_last_obs["body_pose"][person_idx].view(-1, 3) + assert init_pose.shape[0] == 24, "the body pose should have 24 joints, it is the output of NLF" + + # Initialize SMPL2Mesh once + smpl2mesh = SMPL2Mesh(device) + + # Initialize Skeleton2Obj once + skeleton2obj = Skeleton2Obj( + device=device, + num_smplify_iters=num_smplify_iters, + smpl_model_dir="./models/body_models/", + gmm_model_dir="./models/joint2smpl_models/", + ) + + # Process each sample + for sample_idx in range(len(sorted_idx)): + current_motions = pred_motions[sample_idx].reshape(-1, 22, 3) + current_motions = convert2humanml(current_motions, skeleton.LANDMARKS, skeleton.TO_HUMANML_NAMES) + + # Prepare init params efficiently + init_params = { + "betas": init_betas.unsqueeze(0).expand(current_motions.shape[0], -1), + "pose": init_pose.unsqueeze(0).expand(current_motions.shape[0], -1, -1).view(current_motions.shape[0], -1).to(device), + "cam": torch.Tensor([0.0, 0.0, 0.0]).unsqueeze(0).to(device) + } + + # Get first frame parameters if not already computed + if first_rot_motions is None: + with torch.set_grad_enabled(True): + first_rot_motions, first_smpl_dict = skeleton2obj.convert_motion_2smpl( + current_motions[0].unsqueeze(0).to(device), + hmp=False, + init_params=None, + fix_betas=False + ) + + # Update init params with first frame data + init_params["pose"] = first_rot_motions.repeat(current_motions.shape[0], 1) + init_params["betas"] = first_smpl_dict["betas"].repeat(current_motions.shape[0], 1) + init_params["cam"] = first_smpl_dict["cam"] + + # Convert motion to SMPL + with torch.set_grad_enabled(True): + rot_motions, smpl_dict = skeleton2obj.convert_motion_2smpl( + current_motions, + hmp=True, + init_params=init_params, + fix_betas=True + ) + + # Process rotations + rot_motions = rot_motions.reshape(-1, 24, 3).reshape(-1, 72) + + # Apply Gaussian smoothing to specific parameters + rot_motions_np = rot_motions.cpu().numpy() + sigma = 3.0 + for param_idx in range(36, 40): + rot_motions_np[:, param_idx] = gaussian_filter1d(rot_motions_np[:, param_idx], sigma=sigma) + for param_idx in range(45, 49): + rot_motions_np[:, param_idx] = gaussian_filter1d(rot_motions_np[:, param_idx], sigma=sigma) + rot_motions = torch.from_numpy(rot_motions_np).to(device) + + # Convert to mesh + vertices, faces = smpl2mesh.convert_smpl_to_mesh(rot_motions, current_motions) + if all_faces is None: + all_faces = faces + all_vertices.append(vertices) + + # Convert faces to numpy once at the end + if torch.is_tensor(all_faces): + all_faces = all_faces.cpu().numpy() + + # Save results + os.makedirs(output_dir, exist_ok=True) + for i, vertices in enumerate(all_vertices): + print(vertices.shape) + save_mesh(vertices, all_faces, output_dir, output_idx=i) + + +def smpl_to_mesh(smpl_params_path, pred_motions_path, device, sorted_idx): + num_smplify_iters = 20 # This is what requires most time. It can be decreased or increasd depending on the output quality we want (or how quick we canr each it) + device = "cuda" + # Process each sample separately to maintain frame order + all_vertices = [] + all_faces = None + # get observation smpl params + json_file_path = smpl_params_path + with open(json_file_path, "r") as json_file: + loaded_data = json.load(json_file) + person_idx = 0 + smpl_dict_last_obs = loaded_data[1] + smpl_dict_last_obs = {k: torch.from_numpy(np.array(v)).float().to(device) for k,v in smpl_dict_last_obs.items()} + + pred_motions = torch.from_numpy(np.load(pred_motions_path, allow_pickle=True)).to(device) + current_motions = pred_motions[sorted_idx][:30] + + smpl2mesh = SMPL2Mesh(device) + + init_params = {} + init_params["betas"] = smpl_dict_last_obs["betas"][person_idx].unsqueeze(0).expand(current_motions.shape[0], -1) + init_params["pose"] = smpl_dict_last_obs["body_pose"][person_idx].view(-1, 3) + # init_params["pose"] = torch.stack([init_params["pose"][..., 0], init_params["pose"][..., 2], -init_params["pose"][..., 1]], dim=-1) + assert init_params["pose"].shape[0] == 24, "the body pose should have 24 joints, it is the output of NLF" + + init_params["pose"] = init_params["pose"].unsqueeze(0).expand(current_motions.shape[0], -1, -1).view(current_motions.shape[0], -1).to(device) + # rot_motions is a tensor 30,72 + rot_motions = torch.zeros(30, 72).to(device) + current_motions = current_motions[0, 0, :30, :, :] + # rot_motions[frame_id] = loaded_data[frame_id]["pose"] + for frame_id in range(30): + # print(f"Processing frame {frame_id}") + # rot_motions.append(loaded_data[frame_id]["body_pose"]) + temp = torch.tensor(loaded_data[frame_id]["body_pose"]).to(device).reshape(-1, 24, 3) + # temp = torch.stack([temp[..., 0], temp[..., 2], -temp[..., 1]], dim=-1) + rot_motions[frame_id] = temp.view(-1, 72) + rot_motions[frame_id, 0] = 1.6005e+00 # X-axis rotation + rot_motions[frame_id, 1] = 8.2655e-01 # Y-axis rotation + rot_motions[frame_id, 2] = 9.4306e-01 # Z-axis rotation + + # rot_motions = torch.tensor([[ 1.6005e+00, 8.2655e-01, 9.4306e-01, -1.0372e-01, 2.7821e-02, + # -3.8120e-01, -6.2227e-01, -1.3174e-01, -3.9679e-01, -5.5898e-02, + # 4.0376e-02, 1.0782e-01, -2.1775e-02, 9.2568e-02, -8.4396e-02, + # 9.6487e-01, 4.5018e-02, 2.5192e-01, -1.0397e-01, 1.1797e-01, + # -1.3300e-01, -1.0074e+00, 5.0848e-01, 5.7921e-01, -6.9055e-01, + # -4.2592e-02, 2.1878e-01, 1.1854e-01, 1.6012e-01, -7.8607e-02, + # 3.0257e-01, 3.8598e-02, -5.1632e-01, 1.3716e-01, 1.6491e-01, + # 7.4003e-02, 2.7080e-01, 2.8428e-01, -1.6114e-01, -2.1017e-01, + # 3.2442e-01, 5.4414e-01, 1.6220e-01, -2.2343e-02, -5.5549e-01, + # -5.5686e-01, 1.4427e-01, 5.9082e-02, -8.0001e-02, 2.5315e-01, + # -4.6155e-01, -2.7584e-01, 2.5945e-03, 4.7265e-01, -5.5788e-02, + # -5.2776e-01, 8.8441e-02, 1.2666e-01, 1.8338e-01, 2.2411e-02, + # 2.5319e-02, -2.4700e-01, -4.3147e-01, -9.9603e-02, 2.8157e-01, + # 2.2922e-01, -4.2805e-01, 6.8633e-02, 1.2775e-01, -1.7168e-01, + # -6.4354e-02, -4.8196e-02], + # [ 1.6031e+00, 8.6938e-01, 9.5093e-01, -2.4728e-01, -2.5365e-02, + # -3.5090e-01, -6.2714e-01, -1.3281e-01, -3.8726e-01, -7.5513e-02, + # 5.1388e-02, 1.0953e-01, 2.4019e-01, 9.5262e-02, -1.1295e-01, + # 9.5034e-01, 3.7820e-02, 2.5818e-01, -1.1904e-01, 1.0212e-01, + # -1.2446e-01, -1.0170e+00, 5.0628e-01, 5.7588e-01, -6.8644e-01, + # -5.0001e-02, 1.9725e-01, 1.1670e-01, 1.5288e-01, -7.3347e-02, + # 2.7852e-01, 3.9223e-02, -5.1571e-01, 1.3149e-01, 1.5630e-01, + # 7.1519e-02, 2.7341e-01, 2.7110e-01, -1.6775e-01, -2.0063e-01, + # 3.1425e-01, 5.2800e-01, 1.5228e-01, -3.0518e-02, -5.5076e-01, + # -5.4393e-01, 1.5199e-01, 7.1569e-02, -8.7057e-02, 2.5214e-01, + # -4.4306e-01, -2.8668e-01, -2.0587e-02, 4.6127e-01, -4.5369e-02, + # -5.3020e-01, 8.1563e-02, 1.2601e-01, 2.0114e-01, 2.6854e-02, + # 2.3951e-02, -2.4098e-01, -4.2893e-01, -1.0319e-01, 2.7675e-01, + # 2.2407e-01, -4.0467e-01, 7.5838e-02, 1.2791e-01, -1.5939e-01, + # -6.1213e-02, -2.8723e-02], + # [ 1.6110e+00, 8.7997e-01, 9.4755e-01, -2.9480e-01, -5.0045e-02, + # -3.4665e-01, -6.4217e-01, -1.2302e-01, -3.8091e-01, -8.1906e-02, + # 5.4623e-02, 1.0953e-01, 3.0538e-01, 9.1858e-02, -1.1804e-01, + # 9.5882e-01, 4.4244e-02, 2.5869e-01, -1.2163e-01, 9.9909e-02, + # -1.2311e-01, -1.0218e+00, 4.9697e-01, 5.8416e-01, -6.8940e-01, + # -3.8903e-02, 1.9803e-01, 1.0894e-01, 1.5256e-01, -7.2756e-02, + # 2.7297e-01, 4.9584e-02, -5.2945e-01, 1.3066e-01, 1.4965e-01, + # 6.4956e-02, 2.8823e-01, 2.7311e-01, -1.7025e-01, -2.0369e-01, + # 3.1524e-01, 5.3636e-01, 1.5043e-01, -3.4381e-02, -5.6039e-01, + # -5.4034e-01, 1.5133e-01, 7.7262e-02, -8.2864e-02, 2.4608e-01, + # -4.5811e-01, -2.8397e-01, -1.5466e-02, 4.8184e-01, -3.5552e-02, + # -5.3320e-01, 9.3335e-02, 1.2752e-01, 2.0015e-01, 9.5036e-03, + # 2.3358e-02, -2.4074e-01, -4.3686e-01, -1.1153e-01, 2.7872e-01, + # 2.2347e-01, -4.0031e-01, 8.1883e-02, 1.3366e-01, -1.5507e-01, + # -6.3415e-02, -2.5810e-02], + # [ 1.6078e+00, 8.2731e-01, 9.4191e-01, -1.2817e-01, 1.0199e-02, + # -3.8164e-01, -6.3457e-01, -1.2142e-01, -3.9256e-01, -5.9317e-02, + # 4.1749e-02, 1.0364e-01, -6.4504e-03, 8.3162e-02, -8.5214e-02, + # 9.7525e-01, 5.4130e-02, 2.4759e-01, -1.0453e-01, 1.1918e-01, + # -1.3388e-01, -1.0173e+00, 4.9495e-01, 5.9313e-01, -7.0463e-01, + # -3.1721e-02, 2.2378e-01, 1.1515e-01, 1.6104e-01, -7.8829e-02, + # 3.0084e-01, 5.3103e-02, -5.3755e-01, 1.4287e-01, 1.6034e-01, + # 6.3805e-02, 2.8415e-01, 2.8788e-01, -1.6004e-01, -2.1489e-01, + # 3.3769e-01, 5.6067e-01, 1.6184e-01, -3.1818e-02, -5.6590e-01, + # -5.5922e-01, 1.3768e-01, 6.3404e-02, -8.5235e-02, 2.5253e-01, + # -4.8702e-01, -2.8300e-01, 1.6068e-02, 5.0862e-01, -6.2476e-02, + # -5.5081e-01, 1.3232e-01, 1.1314e-01, 1.7680e-01, -3.0066e-02, + # 2.8321e-02, -2.4106e-01, -4.3505e-01, -1.0106e-01, 2.7696e-01, + # 2.2127e-01, -4.3045e-01, 7.2721e-02, 1.3034e-01, -1.6938e-01, + # -6.5850e-02, -4.7649e-02], + # [ 1.6127e+00, 8.2087e-01, 9.3510e-01, -1.2865e-01, 7.0033e-03, + # -3.8277e-01, -6.4321e-01, -1.1820e-01, -3.9148e-01, -5.7967e-02, + # 4.2050e-02, 1.0235e-01, -1.8375e-02, 8.0566e-02, -8.2773e-02, + # 9.7714e-01, 5.6629e-02, 2.4823e-01, -1.0411e-01, 1.2287e-01, + # -1.3516e-01, -1.0191e+00, 4.8862e-01, 5.9904e-01, -7.0806e-01, + # -2.2407e-02, 2.2896e-01, 1.1342e-01, 1.6324e-01, -7.8949e-02, + # 3.0168e-01, 6.0124e-02, -5.4830e-01, 1.4416e-01, 1.5701e-01, + # 5.9664e-02, 2.8986e-01, 2.9288e-01, -1.5865e-01, -2.1956e-01, + # 3.4455e-01, 5.7280e-01, 1.6278e-01, -3.1477e-02, -5.7379e-01, + # -5.6414e-01, 1.3230e-01, 6.3549e-02, -8.4579e-02, 2.5156e-01, + # -5.0488e-01, -2.8463e-01, 2.8527e-02, 5.2620e-01, -6.6063e-02, + # -5.4647e-01, 1.4498e-01, 1.0835e-01, 1.5971e-01, -4.4815e-02, + # 2.8694e-02, -2.3884e-01, -4.4007e-01, -1.0147e-01, 2.7542e-01, + # 2.2058e-01, -4.3300e-01, 7.6706e-02, 1.3656e-01, -1.6946e-01, + # -6.9181e-02, -5.3041e-02], + # [ 1.6108e+00, 8.8141e-01, 9.4745e-01, -3.1157e-01, -5.7691e-02, + # -3.4433e-01, -6.4394e-01, -1.2029e-01, -3.7842e-01, -8.1581e-02, + # 5.4783e-02, 1.1136e-01, 3.2240e-01, 8.5124e-02, -1.1836e-01, + # 9.5431e-01, 4.9055e-02, 2.5693e-01, -1.2930e-01, 9.6078e-02, + # -1.2446e-01, -1.0248e+00, 4.9433e-01, 5.8570e-01, -7.0217e-01, + # -4.1788e-02, 1.9344e-01, 1.1305e-01, 1.5165e-01, -7.0912e-02, + # 2.7373e-01, 5.2925e-02, -5.3586e-01, 1.3504e-01, 1.4768e-01, + # 6.5673e-02, 2.8562e-01, 2.7257e-01, -1.7666e-01, -2.0663e-01, + # 2.9556e-01, 5.3934e-01, 1.4793e-01, -2.3227e-02, -5.6870e-01, + # -5.4620e-01, 1.5352e-01, 8.2237e-02, -8.0556e-02, 2.4192e-01, + # -4.6349e-01, -2.7927e-01, -2.2375e-02, 4.8494e-01, -3.1615e-02, + # -4.9880e-01, 7.3527e-02, 1.3946e-01, 1.8965e-01, 3.0069e-02, + # 1.9538e-02, -2.3811e-01, -4.4155e-01, -1.1854e-01, 2.7917e-01, + # 2.2786e-01, -3.9457e-01, 8.4604e-02, 1.3755e-01, -1.5437e-01, + # -6.4888e-02, -2.4748e-02], + # [ 1.6175e+00, 8.4030e-01, 9.4400e-01, -2.6284e-01, -4.4624e-02, + # -3.6173e-01, -6.6031e-01, -1.1552e-01, -3.8892e-01, -6.9325e-02, + # 5.2747e-02, 9.9177e-02, 2.3507e-01, 8.6017e-02, -1.1489e-01, + # 9.8375e-01, 5.2098e-02, 2.5241e-01, -1.1985e-01, 1.0992e-01, + # -1.3038e-01, -1.0503e+00, 4.9318e-01, 6.0568e-01, -7.0369e-01, + # -2.8890e-02, 2.1513e-01, 1.0779e-01, 1.5872e-01, -7.6392e-02, + # 2.8910e-01, 5.8300e-02, -5.4987e-01, 1.3028e-01, 1.5376e-01, + # 5.4624e-02, 2.9445e-01, 2.8195e-01, -1.6763e-01, -2.1595e-01, + # 3.2959e-01, 5.6479e-01, 1.5581e-01, -2.9649e-02, -5.7555e-01, + # -5.4656e-01, 1.4160e-01, 7.7658e-02, -8.1496e-02, 2.3873e-01, + # -4.8825e-01, -2.7527e-01, 1.7245e-02, 5.1932e-01, -4.8679e-02, + # -5.3691e-01, 1.1823e-01, 1.3559e-01, 1.8416e-01, -1.0622e-02, + # 2.1179e-02, -2.3586e-01, -4.4682e-01, -1.1912e-01, 2.7786e-01, + # 2.2629e-01, -4.1122e-01, 8.6780e-02, 1.4446e-01, -1.5303e-01, + # -6.8516e-02, -4.3646e-02], + # [ 1.6171e+00, 8.0908e-01, 9.3404e-01, -1.4870e-01, -3.6595e-03, + # -3.8383e-01, -6.5764e-01, -1.1242e-01, -3.9115e-01, -5.7404e-02, + # 4.3636e-02, 9.8583e-02, 1.3409e-02, 7.8856e-02, -8.7588e-02, + # 9.8670e-01, 6.0058e-02, 2.4756e-01, -1.0946e-01, 1.2403e-01, + # -1.3564e-01, -1.0405e+00, 4.9134e-01, 6.0754e-01, -7.1781e-01, + # -2.0699e-02, 2.2599e-01, 1.1115e-01, 1.6500e-01, -7.9038e-02, + # 3.0904e-01, 6.1142e-02, -5.5141e-01, 1.4399e-01, 1.5818e-01, + # 6.5279e-02, 2.9516e-01, 2.9465e-01, -1.5912e-01, -2.2604e-01, + # 3.4378e-01, 5.7770e-01, 1.6292e-01, -2.3460e-02, -5.7651e-01, + # -5.5556e-01, 1.3447e-01, 6.7109e-02, -7.7476e-02, 2.4402e-01, + # -5.0284e-01, -2.7063e-01, 4.2260e-02, 5.2265e-01, -6.5846e-02, + # -5.3722e-01, 1.2826e-01, 1.3189e-01, 1.6297e-01, -1.5593e-02, + # 2.0784e-02, -2.3802e-01, -4.4729e-01, -1.1048e-01, 2.7932e-01, + # 2.2813e-01, -4.2831e-01, 8.1248e-02, 1.4348e-01, -1.6234e-01, + # -7.2073e-02, -6.0110e-02], + # [ 1.6172e+00, 8.0780e-01, 9.2508e-01, -1.1043e-01, 1.5869e-02, + # -3.9091e-01, -6.5147e-01, -1.2169e-01, -3.8974e-01, -5.2630e-02, + # 3.9148e-02, 1.0425e-01, -5.0874e-02, 8.0342e-02, -7.4880e-02, + # 9.6878e-01, 4.6173e-02, 2.4613e-01, -1.1391e-01, 1.2274e-01, + # -1.3708e-01, -1.0093e+00, 4.9945e-01, 5.9141e-01, -7.1179e-01, + # -4.1468e-02, 2.2081e-01, 1.1880e-01, 1.6512e-01, -7.7646e-02, + # 3.0951e-01, 5.2777e-02, -5.3674e-01, 1.4769e-01, 1.6093e-01, + # 6.6290e-02, 2.7911e-01, 2.8816e-01, -1.6946e-01, -2.2208e-01, + # 3.2207e-01, 5.6807e-01, 1.5750e-01, -1.0790e-02, -5.7038e-01, + # -5.6035e-01, 1.3992e-01, 6.4614e-02, -7.6299e-02, 2.4234e-01, + # -4.9502e-01, -2.8281e-01, 3.6125e-02, 5.0050e-01, -5.3537e-02, + # -4.7532e-01, 9.4072e-02, 1.1179e-01, 1.3639e-01, 1.0555e-03, + # 3.0102e-02, -2.3356e-01, -4.4694e-01, -9.9521e-02, 2.7499e-01, + # 2.2463e-01, -4.2757e-01, 7.5108e-02, 1.4227e-01, -1.7291e-01, + # -7.0797e-02, -5.5015e-02], + # [ 1.6127e+00, 7.9969e-01, 9.2656e-01, -9.2324e-02, 2.1135e-02, + # -3.9503e-01, -6.4862e-01, -1.1920e-01, -3.8847e-01, -4.7938e-02, + # 3.7856e-02, 1.0542e-01, -7.5337e-02, 7.9361e-02, -7.1081e-02, + # 9.7582e-01, 4.9855e-02, 2.4424e-01, -1.1079e-01, 1.2464e-01, + # -1.3823e-01, -1.0107e+00, 5.0145e-01, 5.9228e-01, -7.1782e-01, + # -4.1891e-02, 2.2175e-01, 1.1935e-01, 1.6617e-01, -7.8416e-02, + # 3.1054e-01, 5.2554e-02, -5.3566e-01, 1.4889e-01, 1.6306e-01, + # 6.5496e-02, 2.8046e-01, 2.8974e-01, -1.6876e-01, -2.2292e-01, + # 3.2426e-01, 5.7149e-01, 1.5917e-01, -9.2451e-03, -5.7336e-01, + # -5.6363e-01, 1.3957e-01, 6.2405e-02, -7.7520e-02, 2.4188e-01, + # -5.0227e-01, -2.8387e-01, 4.2127e-02, 5.0270e-01, -5.5740e-02, + # -4.7964e-01, 9.9425e-02, 1.1146e-01, 1.3111e-01, -4.0174e-03, + # 3.0246e-02, -2.3279e-01, -4.4877e-01, -9.8105e-02, 2.7429e-01, + # 2.2596e-01, -4.3045e-01, 7.3784e-02, 1.4046e-01, -1.7344e-01, + # -7.0867e-02, -5.6526e-02], + # [ 1.6120e+00, 7.8502e-01, 9.1977e-01, -5.2430e-02, 3.4929e-02, + # -4.0406e-01, -6.5727e-01, -1.1731e-01, -3.8496e-01, -4.3661e-02, + # 3.5240e-02, 1.0774e-01, -1.6151e-01, 8.3658e-02, -5.7072e-02, + # 9.8469e-01, 4.6138e-02, 2.4297e-01, -1.0707e-01, 1.3566e-01, + # -1.3919e-01, -1.0010e+00, 5.0230e-01, 5.9108e-01, -7.1900e-01, + # -3.8501e-02, 2.2520e-01, 1.1559e-01, 1.7051e-01, -8.0410e-02, + # 3.1320e-01, 5.2449e-02, -5.3276e-01, 1.5435e-01, 1.7007e-01, + # 7.0888e-02, 2.8487e-01, 2.9777e-01, -1.5472e-01, -2.3231e-01, + # 3.5546e-01, 5.8281e-01, 1.6599e-01, -1.8913e-02, -5.7525e-01, + # -5.5674e-01, 1.3210e-01, 5.5984e-02, -8.3314e-02, 2.3888e-01, + # -5.1031e-01, -2.7750e-01, 6.4134e-02, 5.0933e-01, -8.5122e-02, + # -5.3972e-01, 1.3396e-01, 1.1648e-01, 1.2733e-01, -1.8583e-02, + # 2.3639e-02, -2.3216e-01, -4.4518e-01, -9.0224e-02, 2.6999e-01, + # 2.2834e-01, -4.3949e-01, 6.9299e-02, 1.3335e-01, -1.7576e-01, + # -6.5963e-02, -6.5975e-02], + # [ 1.6071e+00, 7.9310e-01, 9.2444e-01, -4.9396e-02, 4.3975e-02, + # -4.0127e-01, -6.4328e-01, -1.2693e-01, -3.9056e-01, -4.2565e-02, + # 3.4209e-02, 1.0909e-01, -1.4793e-01, 8.5667e-02, -6.2626e-02, + # 9.7650e-01, 3.6768e-02, 2.4164e-01, -1.0416e-01, 1.2861e-01, + # -1.3928e-01, -9.9763e-01, 5.1174e-01, 5.8280e-01, -7.2009e-01, + # -5.7355e-02, 2.1432e-01, 1.1871e-01, 1.6651e-01, -7.9274e-02, + # 3.1727e-01, 4.2364e-02, -5.2256e-01, 1.5518e-01, 1.7045e-01, + # 7.8902e-02, 2.7255e-01, 2.8947e-01, -1.6404e-01, -2.1773e-01, + # 3.2939e-01, 5.6419e-01, 1.6624e-01, -7.9742e-03, -5.6667e-01, + # -5.6618e-01, 1.3820e-01, 5.5287e-02, -7.6634e-02, 2.5377e-01, + # -4.8652e-01, -2.7879e-01, 3.2333e-02, 4.8341e-01, -6.1367e-02, + # -4.8904e-01, 8.6460e-02, 1.1950e-01, 1.3502e-01, 1.5787e-02, + # 2.9844e-02, -2.3639e-01, -4.4481e-01, -9.5168e-02, 2.7725e-01, + # 2.2710e-01, -4.3776e-01, 6.7010e-02, 1.3388e-01, -1.7756e-01, + # -6.7554e-02, -5.8787e-02], + # [ 1.6114e+00, 7.9535e-01, 9.2793e-01, -7.8612e-02, 3.5401e-02, + # -3.9924e-01, -6.4773e-01, -1.3112e-01, -3.9557e-01, -4.6138e-02, + # 3.7209e-02, 1.0605e-01, -9.1472e-02, 9.2488e-02, -7.1972e-02, + # 9.7635e-01, 2.6682e-02, 2.4072e-01, -1.0694e-01, 1.2549e-01, + # -1.3883e-01, -1.0046e+00, 5.1723e-01, 5.8259e-01, -7.1149e-01, + # -6.7292e-02, 2.1092e-01, 1.1739e-01, 1.6599e-01, -7.9772e-02, + # 3.1622e-01, 3.6763e-02, -5.1623e-01, 1.4984e-01, 1.7371e-01, + # 7.7168e-02, 2.7026e-01, 2.8119e-01, -1.6621e-01, -2.1452e-01, + # 3.2701e-01, 5.5576e-01, 1.6452e-01, -6.4499e-03, -5.6051e-01, + # -5.5295e-01, 1.4345e-01, 5.8258e-02, -7.2799e-02, 2.4994e-01, + # -4.7749e-01, -2.7572e-01, 3.4231e-02, 4.7468e-01, -5.5045e-02, + # -4.9712e-01, 7.6196e-02, 1.2551e-01, 1.5092e-01, 3.0985e-02, + # 2.5341e-02, -2.3434e-01, -4.4481e-01, -9.8031e-02, 2.7642e-01, + # 2.2843e-01, -4.3310e-01, 6.6681e-02, 1.3241e-01, -1.7513e-01, + # -6.4599e-02, -5.5685e-02], + # [ 1.6089e+00, 7.9613e-01, 9.2071e-01, -4.4012e-02, 4.6298e-02, + # -4.0188e-01, -6.3490e-01, -1.3039e-01, -3.9274e-01, -4.2072e-02, + # 3.4813e-02, 1.1080e-01, -1.4711e-01, 8.4902e-02, -6.2261e-02, + # 9.6799e-01, 3.5207e-02, 2.4217e-01, -1.0291e-01, 1.2735e-01, + # -1.3903e-01, -9.8320e-01, 5.1397e-01, 5.7345e-01, -6.9947e-01, + # -6.0845e-02, 2.1852e-01, 1.1894e-01, 1.6639e-01, -7.9859e-02, + # 3.1241e-01, 3.4346e-02, -5.0957e-01, 1.4511e-01, 1.7371e-01, + # 7.4733e-02, 2.6370e-01, 2.8498e-01, -1.6673e-01, -2.1329e-01, + # 3.2700e-01, 5.5354e-01, 1.6658e-01, -4.1914e-03, -5.5837e-01, + # -5.6159e-01, 1.4337e-01, 5.5111e-02, -7.1239e-02, 2.6087e-01, + # -4.7412e-01, -2.7577e-01, 3.0568e-02, 4.6762e-01, -5.3383e-02, + # -4.8441e-01, 6.8504e-02, 1.2392e-01, 1.4773e-01, 3.7464e-02, + # 2.6383e-02, -2.4123e-01, -4.4229e-01, -9.4151e-02, 2.8205e-01, + # 2.2989e-01, -4.3240e-01, 6.5174e-02, 1.3269e-01, -1.7646e-01, + # -6.7489e-02, -5.9306e-02], + # [ 1.6064e+00, 7.8379e-01, 9.1715e-01, -2.2837e-02, 5.6671e-02, + # -4.0800e-01, -6.3420e-01, -1.3400e-01, -3.9289e-01, -3.7460e-02, + # 3.2855e-02, 1.1298e-01, -1.8396e-01, 9.2378e-02, -5.6299e-02, + # 9.7151e-01, 2.7896e-02, 2.4129e-01, -1.0158e-01, 1.2944e-01, + # -1.4058e-01, -9.6946e-01, 5.1848e-01, 5.6872e-01, -6.9208e-01, + # -6.7717e-02, 2.2146e-01, 1.1953e-01, 1.6756e-01, -8.1250e-02, + # 3.0985e-01, 3.0301e-02, -5.0364e-01, 1.4353e-01, 1.7909e-01, + # 6.9708e-02, 2.5675e-01, 2.8108e-01, -1.6580e-01, -2.1183e-01, + # 3.3095e-01, 5.5397e-01, 1.6789e-01, -5.1917e-03, -5.5819e-01, + # -5.6124e-01, 1.4188e-01, 5.2478e-02, -7.1689e-02, 2.5887e-01, + # -4.8129e-01, -2.7914e-01, 3.6637e-02, 4.7029e-01, -5.3329e-02, + # -4.9868e-01, 7.5359e-02, 1.1654e-01, 1.4039e-01, 2.7606e-02, + # 2.6097e-02, -2.3892e-01, -4.4175e-01, -8.8701e-02, 2.7705e-01, + # 2.2809e-01, -4.3715e-01, 6.0672e-02, 1.2738e-01, -1.8168e-01, + # -6.3790e-02, -5.8458e-02], + # [ 1.6036e+00, 7.6848e-01, 9.1063e-01, 1.5594e-02, 7.0544e-02, + # -4.1805e-01, -6.4090e-01, -1.2969e-01, -3.8887e-01, -2.9953e-02, + # 2.8649e-02, 1.1545e-01, -2.5789e-01, 9.7814e-02, -4.4669e-02, + # 9.8152e-01, 2.8546e-02, 2.4027e-01, -9.8450e-02, 1.3538e-01, + # -1.4215e-01, -9.5859e-01, 5.2286e-01, 5.6802e-01, -6.9194e-01, + # -6.5219e-02, 2.2749e-01, 1.1723e-01, 1.7065e-01, -8.3186e-02, + # 3.1441e-01, 2.9292e-02, -4.9926e-01, 1.4394e-01, 1.8294e-01, + # 6.8533e-02, 2.5724e-01, 2.8267e-01, -1.6227e-01, -2.1602e-01, + # 3.3988e-01, 5.6238e-01, 1.7019e-01, -2.4435e-04, -5.6093e-01, + # -5.5890e-01, 1.3799e-01, 4.8388e-02, -6.6029e-02, 2.5733e-01, + # -4.9297e-01, -2.7230e-01, 5.9701e-02, 4.7325e-01, -5.3443e-02, + # -5.0340e-01, 7.7246e-02, 1.2219e-01, 1.3809e-01, 3.0451e-02, + # 2.2752e-02, -2.3838e-01, -4.4713e-01, -8.9093e-02, 2.7884e-01, + # 2.3090e-01, -4.4216e-01, 5.9356e-02, 1.2918e-01, -1.8294e-01, + # -6.6295e-02, -6.7253e-02], + # [ 1.5982e+00, 7.6427e-01, 9.0982e-01, 4.5329e-02, 8.3458e-02, + # -4.2476e-01, -6.3506e-01, -1.3275e-01, -3.8963e-01, -2.2915e-02, + # 2.5772e-02, 1.1876e-01, -2.9880e-01, 1.0129e-01, -3.9239e-02, + # 9.8655e-01, 2.3997e-02, 2.3891e-01, -9.0377e-02, 1.3715e-01, + # -1.4526e-01, -9.4479e-01, 5.2667e-01, 5.6371e-01, -6.8938e-01, + # -7.0775e-02, 2.2987e-01, 1.1846e-01, 1.7032e-01, -8.5228e-02, + # 3.1240e-01, 2.6075e-02, -4.9633e-01, 1.4413e-01, 1.8624e-01, + # 6.4543e-02, 2.5696e-01, 2.8016e-01, -1.6300e-01, -2.0918e-01, + # 3.4272e-01, 5.5946e-01, 1.7563e-01, -4.3650e-03, -5.6280e-01, + # -5.6853e-01, 1.3560e-01, 4.5305e-02, -6.5227e-02, 2.6975e-01, + # -4.9916e-01, -2.7250e-01, 4.4762e-02, 4.7997e-01, -5.1297e-02, + # -5.1131e-01, 8.1539e-02, 1.2004e-01, 1.4303e-01, 2.1781e-02, + # 2.4702e-02, -2.4191e-01, -4.4581e-01, -8.9587e-02, 2.8206e-01, + # 2.2981e-01, -4.4990e-01, 5.5708e-02, 1.2385e-01, -1.8772e-01, + # -6.5355e-02, -6.4543e-02], + # [ 1.5980e+00, 7.6793e-01, 9.1314e-01, 3.4286e-02, 7.8889e-02, + # -4.2239e-01, -6.3568e-01, -1.3518e-01, -3.9113e-01, -2.5918e-02, + # 2.7648e-02, 1.1746e-01, -2.7750e-01, 1.0026e-01, -4.1510e-02, + # 9.8393e-01, 2.1089e-02, 2.4000e-01, -9.1654e-02, 1.3650e-01, + # -1.4340e-01, -9.5062e-01, 5.2447e-01, 5.6600e-01, -6.9092e-01, + # -7.0625e-02, 2.2859e-01, 1.1953e-01, 1.7035e-01, -8.3394e-02, + # 3.1108e-01, 2.9202e-02, -5.0096e-01, 1.4573e-01, 1.8334e-01, + # 6.3919e-02, 2.5553e-01, 2.7929e-01, -1.6311e-01, -2.0922e-01, + # 3.3873e-01, 5.5995e-01, 1.7310e-01, -5.9155e-03, -5.6344e-01, + # -5.7090e-01, 1.3492e-01, 4.6463e-02, -6.8248e-02, 2.6328e-01, + # -5.0297e-01, -2.8269e-01, 4.1822e-02, 4.8055e-01, -4.8719e-02, + # -5.1152e-01, 8.8375e-02, 1.0532e-01, 1.3665e-01, 4.5898e-03, + # 2.9124e-02, -2.3928e-01, -4.4522e-01, -8.5394e-02, 2.7724e-01, + # 2.2524e-01, -4.5172e-01, 5.5692e-02, 1.2248e-01, -1.9115e-01, + # -6.3939e-02, -5.9218e-02], + # [ 1.6006e+00, 7.6986e-01, 9.1319e-01, 3.0826e-02, 7.8324e-02, + # -4.2216e-01, -6.3810e-01, -1.3510e-01, -3.9068e-01, -2.6516e-02, + # 2.7604e-02, 1.1624e-01, -2.7519e-01, 1.0167e-01, -4.3052e-02, + # 9.8528e-01, 1.9331e-02, 2.4012e-01, -9.2000e-02, 1.3593e-01, + # -1.4402e-01, -9.5365e-01, 5.2531e-01, 5.6749e-01, -6.9263e-01, + # -7.1398e-02, 2.2658e-01, 1.1795e-01, 1.7006e-01, -8.3400e-02, + # 3.1425e-01, 2.9896e-02, -5.0214e-01, 1.4688e-01, 1.8203e-01, + # 6.5908e-02, 2.5645e-01, 2.7999e-01, -1.6388e-01, -2.1038e-01, + # 3.3451e-01, 5.5951e-01, 1.7207e-01, -3.2292e-03, -5.6347e-01, + # -5.7077e-01, 1.3484e-01, 4.6472e-02, -6.8778e-02, 2.6014e-01, + # -5.0357e-01, -2.8219e-01, 4.2198e-02, 4.8172e-01, -5.1418e-02, + # -4.9674e-01, 8.6105e-02, 1.0458e-01, 1.2895e-01, 6.6461e-03, + # 3.2822e-02, -2.3739e-01, -4.4672e-01, -8.5156e-02, 2.7649e-01, + # 2.2583e-01, -4.5141e-01, 5.6561e-02, 1.2545e-01, -1.9071e-01, + # -6.4253e-02, -5.9937e-02], + # [ 1.6034e+00, 7.6981e-01, 9.1797e-01, 5.8256e-03, 7.3706e-02, + # -4.1936e-01, -6.4204e-01, -1.3613e-01, -3.9440e-01, -3.0745e-02, + # 2.9719e-02, 1.1275e-01, -2.3104e-01, 1.1198e-01, -5.2077e-02, + # 9.8376e-01, 2.0086e-02, 2.3991e-01, -9.8931e-02, 1.3170e-01, + # -1.4142e-01, -9.6163e-01, 5.3573e-01, 5.6420e-01, -6.7548e-01, + # -7.9034e-02, 2.2631e-01, 1.1712e-01, 1.7053e-01, -8.3982e-02, + # 3.1484e-01, 1.7779e-02, -4.8716e-01, 1.3686e-01, 1.9178e-01, + # 6.6041e-02, 2.4692e-01, 2.6554e-01, -1.6434e-01, -2.1034e-01, + # 3.2963e-01, 5.4917e-01, 1.6845e-01, 5.5389e-03, -5.5106e-01, + # -5.4591e-01, 1.4121e-01, 5.1210e-02, -6.5210e-02, 2.4511e-01, + # -4.8249e-01, -2.7984e-01, 6.5393e-02, 4.5499e-01, -4.5687e-02, + # -5.0374e-01, 6.0865e-02, 1.1309e-01, 1.1726e-01, 4.2383e-02, + # 2.5343e-02, -2.3224e-01, -4.4553e-01, -7.8187e-02, 2.6830e-01, + # 2.2931e-01, -4.4188e-01, 5.4166e-02, 1.2478e-01, -1.8616e-01, + # -5.9672e-02, -6.3519e-02], + # [ 1.5926e+00, 7.7004e-01, 9.1066e-01, 6.0095e-02, 9.3141e-02, + # -4.2458e-01, -6.2727e-01, -1.3663e-01, -3.8584e-01, -2.3479e-02, + # 2.4599e-02, 1.2425e-01, -3.1701e-01, 1.0760e-01, -3.4306e-02, + # 9.7771e-01, 2.1602e-02, 2.4281e-01, -9.3129e-02, 1.3761e-01, + # -1.4255e-01, -9.3193e-01, 5.2857e-01, 5.5570e-01, -6.8857e-01, + # -7.0443e-02, 2.2603e-01, 1.2181e-01, 1.7059e-01, -8.2862e-02, + # 3.0868e-01, 2.5153e-02, -4.9003e-01, 1.4731e-01, 1.8512e-01, + # 7.0469e-02, 2.5296e-01, 2.8148e-01, -1.6020e-01, -2.1291e-01, + # 3.3519e-01, 5.5883e-01, 1.7205e-01, -7.5351e-05, -5.6245e-01, + # -5.7011e-01, 1.3524e-01, 4.1297e-02, -6.9447e-02, 2.5631e-01, + # -5.0309e-01, -2.7900e-01, 4.7759e-02, 4.6969e-01, -5.6797e-02, + # -4.9566e-01, 7.5720e-02, 1.0821e-01, 1.1518e-01, 2.4912e-02, + # 2.8074e-02, -2.3861e-01, -4.4488e-01, -7.7877e-02, 2.7447e-01, + # 2.3065e-01, -4.5242e-01, 5.2467e-02, 1.1995e-01, -1.9576e-01, + # -6.2474e-02, -6.1936e-02], + # [ 1.5935e+00, 7.7744e-01, 9.1601e-01, 4.2118e-02, 8.5857e-02, + # -4.2007e-01, -6.2491e-01, -1.3534e-01, -3.8629e-01, -2.7382e-02, + # 2.6045e-02, 1.2257e-01, -2.8386e-01, 1.0374e-01, -3.9040e-02, + # 9.7333e-01, 2.6776e-02, 2.4316e-01, -9.5490e-02, 1.3390e-01, + # -1.4170e-01, -9.4103e-01, 5.2837e-01, 5.5689e-01, -6.8921e-01, + # -7.0424e-02, 2.2300e-01, 1.2247e-01, 1.6895e-01, -8.2356e-02, + # 3.0943e-01, 2.4012e-02, -4.9006e-01, 1.4612e-01, 1.8444e-01, + # 7.4065e-02, 2.5139e-01, 2.7956e-01, -1.6242e-01, -2.1162e-01, + # 3.2777e-01, 5.5320e-01, 1.7097e-01, 2.0646e-03, -5.5946e-01, + # -5.6685e-01, 1.3862e-01, 4.4633e-02, -6.7534e-02, 2.5763e-01, + # -4.9074e-01, -2.7487e-01, 4.0232e-02, 4.6158e-01, -5.2707e-02, + # -4.8889e-01, 6.1521e-02, 1.1770e-01, 1.2362e-01, 4.2399e-02, + # 2.5194e-02, -2.4064e-01, -4.4373e-01, -8.2418e-02, 2.7713e-01, + # 2.3262e-01, -4.4652e-01, 5.3957e-02, 1.2127e-01, -1.9140e-01, + # -6.3150e-02, -6.0892e-02], + # [ 1.5928e+00, 7.7859e-01, 9.1728e-01, 3.8561e-02, 8.3874e-02, + # -4.1888e-01, -6.2321e-01, -1.3401e-01, -3.8596e-01, -2.8135e-02, + # 2.6617e-02, 1.2287e-01, -2.7631e-01, 1.0193e-01, -3.9768e-02, + # 9.7028e-01, 3.0499e-02, 2.4327e-01, -9.7520e-02, 1.3332e-01, + # -1.4087e-01, -9.4116e-01, 5.2783e-01, 5.5581e-01, -6.8946e-01, + # -6.8912e-02, 2.2326e-01, 1.2420e-01, 1.6912e-01, -8.2000e-02, + # 3.0850e-01, 2.3511e-02, -4.8805e-01, 1.4524e-01, 1.8462e-01, + # 7.4131e-02, 2.5327e-01, 2.7908e-01, -1.6270e-01, -2.1301e-01, + # 3.2760e-01, 5.5323e-01, 1.6963e-01, 3.4241e-03, -5.5854e-01, + # -5.6342e-01, 1.3993e-01, 4.5648e-02, -6.7479e-02, 2.5608e-01, + # -4.8739e-01, -2.7315e-01, 4.3747e-02, 4.5720e-01, -5.2685e-02, + # -4.8583e-01, 5.6369e-02, 1.2152e-01, 1.2591e-01, 5.1173e-02, + # 2.2651e-02, -2.4076e-01, -4.4336e-01, -8.2901e-02, 2.7786e-01, + # 2.3445e-01, -4.4337e-01, 5.4611e-02, 1.2179e-01, -1.8976e-01, + # -6.3923e-02, -6.2194e-02], + # [ 1.5923e+00, 7.8907e-01, 9.3234e-01, 2.5958e-03, 7.4501e-02, + # -4.1142e-01, -6.2064e-01, -1.4013e-01, -3.9269e-01, -3.3605e-02, + # 2.9855e-02, 1.1648e-01, -1.9841e-01, 1.0612e-01, -5.6660e-02, + # 9.6785e-01, 2.4450e-02, 2.4122e-01, -1.0391e-01, 1.2529e-01, + # -1.3911e-01, -9.5762e-01, 5.3554e-01, 5.5490e-01, -6.8035e-01, + # -8.6011e-02, 2.1864e-01, 1.2768e-01, 1.6646e-01, -8.1843e-02, + # 3.0532e-01, 1.4512e-02, -4.8008e-01, 1.3870e-01, 1.9096e-01, + # 6.8221e-02, 2.4176e-01, 2.6344e-01, -1.6764e-01, -2.0647e-01, + # 3.1671e-01, 5.3998e-01, 1.6377e-01, 1.3754e-03, -5.4781e-01, + # -5.4963e-01, 1.4641e-01, 5.1760e-02, -7.3814e-02, 2.4241e-01, + # -4.6986e-01, -2.8396e-01, 3.9680e-02, 4.4490e-01, -4.5124e-02, + # -4.9316e-01, 4.9161e-02, 1.1173e-01, 1.2221e-01, 5.1617e-02, + # 2.6101e-02, -2.3272e-01, -4.3735e-01, -7.7574e-02, 2.6570e-01, + # 2.2987e-01, -4.3688e-01, 5.1705e-02, 1.1696e-01, -1.8714e-01, + # -5.6388e-02, -5.3614e-02], + # [ 1.6004e+00, 7.8749e-01, 9.3251e-01, -3.5837e-02, 5.9702e-02, + # -4.0712e-01, -6.3153e-01, -1.3912e-01, -3.9537e-01, -3.8402e-02, + # 3.3139e-02, 1.1036e-01, -1.3880e-01, 1.0822e-01, -6.6264e-02, + # 9.7113e-01, 2.2893e-02, 2.4089e-01, -1.0811e-01, 1.2273e-01, + # -1.3905e-01, -9.7440e-01, 5.3591e-01, 5.6279e-01, -6.7856e-01, + # -8.6346e-02, 2.1791e-01, 1.2513e-01, 1.6618e-01, -8.1820e-02, + # 3.0713e-01, 1.5781e-02, -4.8610e-01, 1.3578e-01, 1.9026e-01, + # 6.5493e-02, 2.4274e-01, 2.5998e-01, -1.7033e-01, -2.0635e-01, + # 3.1509e-01, 5.3885e-01, 1.6181e-01, 1.3671e-03, -5.4627e-01, + # -5.4277e-01, 1.4821e-01, 5.6998e-02, -7.3062e-02, 2.3915e-01, + # -4.6706e-01, -2.8552e-01, 4.3505e-02, 4.4814e-01, -4.3142e-02, + # -4.9203e-01, 5.0110e-02, 1.1126e-01, 1.2253e-01, 4.9766e-02, + # 2.6183e-02, -2.2894e-01, -4.3891e-01, -7.9625e-02, 2.6316e-01, + # 2.2770e-01, -4.3245e-01, 5.5008e-02, 1.2143e-01, -1.8278e-01, + # -5.6483e-02, -5.2643e-02], + # [ 1.6017e+00, 7.9113e-01, 9.3809e-01, -6.7551e-02, 4.6256e-02, + # -4.0219e-01, -6.3103e-01, -1.4095e-01, -4.0049e-01, -4.2492e-02, + # 3.7406e-02, 1.0725e-01, -7.3920e-02, 1.0542e-01, -7.7643e-02, + # 9.7202e-01, 2.2354e-02, 2.4111e-01, -1.0547e-01, 1.2038e-01, + # -1.3830e-01, -9.8883e-01, 5.3362e-01, 5.6671e-01, -6.7497e-01, + # -8.5774e-02, 2.1655e-01, 1.2290e-01, 1.6546e-01, -8.1752e-02, + # 3.0430e-01, 1.5775e-02, -4.8960e-01, 1.3168e-01, 1.8947e-01, + # 6.4231e-02, 2.4691e-01, 2.5640e-01, -1.7084e-01, -2.0219e-01, + # 3.1556e-01, 5.3456e-01, 1.6360e-01, -2.0048e-03, -5.4564e-01, + # -5.4182e-01, 1.4932e-01, 6.0489e-02, -7.2539e-02, 2.4137e-01, + # -4.6191e-01, -2.8725e-01, 3.4155e-02, 4.4766e-01, -3.8734e-02, + # -5.0761e-01, 5.0770e-02, 1.1271e-01, 1.2916e-01, 4.8807e-02, + # 2.5224e-02, -2.3130e-01, -4.3803e-01, -8.1995e-02, 2.6426e-01, + # 2.2759e-01, -4.3113e-01, 5.6952e-02, 1.2054e-01, -1.7994e-01, + # -5.5231e-02, -4.9082e-02], + # [ 1.5950e+00, 7.8904e-01, 9.3826e-01, -3.6576e-02, 5.9590e-02, + # -4.0528e-01, -6.2329e-01, -1.4581e-01, -3.9926e-01, -3.7969e-02, + # 3.5045e-02, 1.1077e-01, -1.2400e-01, 1.0273e-01, -7.0544e-02, + # 9.6620e-01, 1.6797e-02, 2.4125e-01, -1.0261e-01, 1.2276e-01, + # -1.3924e-01, -9.7538e-01, 5.3488e-01, 5.5833e-01, -6.7958e-01, + # -9.2604e-02, 2.1295e-01, 1.2727e-01, 1.6576e-01, -8.1800e-02, + # 3.0442e-01, 1.2527e-02, -4.8231e-01, 1.3687e-01, 1.9193e-01, + # 6.9017e-02, 2.4074e-01, 2.5518e-01, -1.6866e-01, -1.9987e-01, + # 3.1764e-01, 5.3039e-01, 1.6599e-01, -1.1522e-03, -5.4175e-01, + # -5.4745e-01, 1.4645e-01, 5.6824e-02, -7.4909e-02, 2.4823e-01, + # -4.5869e-01, -2.8971e-01, 2.7926e-02, 4.4000e-01, -4.5069e-02, + # -5.1098e-01, 4.9779e-02, 1.0933e-01, 1.3024e-01, 5.0407e-02, + # 2.7127e-02, -2.3223e-01, -4.3332e-01, -7.7113e-02, 2.6438e-01, + # 2.2604e-01, -4.3552e-01, 5.2848e-02, 1.1502e-01, -1.8366e-01, + # -5.3910e-02, -4.9222e-02], + # [ 1.5957e+00, 8.0788e-01, 9.4834e-01, -1.0032e-01, 3.4486e-02, + # -3.9099e-01, -6.1836e-01, -1.4673e-01, -4.0106e-01, -4.7277e-02, + # 4.1335e-02, 1.0779e-01, 3.9100e-03, 9.7966e-02, -8.8860e-02, + # 9.5900e-01, 1.9642e-02, 2.4337e-01, -1.0685e-01, 1.1403e-01, + # -1.3578e-01, -9.9286e-01, 5.3129e-01, 5.6030e-01, -6.7628e-01, + # -9.3024e-02, 2.0549e-01, 1.2625e-01, 1.6194e-01, -7.9586e-02, + # 2.9590e-01, 1.3397e-02, -4.8444e-01, 1.3130e-01, 1.8686e-01, + # 6.8038e-02, 2.4167e-01, 2.4957e-01, -1.7291e-01, -1.9544e-01, + # 3.0428e-01, 5.2003e-01, 1.6127e-01, -3.0937e-03, -5.3839e-01, + # -5.4331e-01, 1.5127e-01, 6.3756e-02, -7.6802e-02, 2.4234e-01, + # -4.4598e-01, -2.9270e-01, 9.4432e-03, 4.3445e-01, -3.5560e-02, + # -5.0477e-01, 3.9526e-02, 1.1015e-01, 1.3875e-01, 5.6716e-02, + # 2.8294e-02, -2.3300e-01, -4.3126e-01, -8.1621e-02, 2.6405e-01, + # 2.2596e-01, -4.2528e-01, 5.6517e-02, 1.1539e-01, -1.7770e-01, + # -5.2139e-02, -3.9383e-02], + # [ 1.5882e+00, 7.9877e-01, 9.4328e-01, -2.8720e-02, 6.2287e-02, + # -4.0260e-01, -6.0959e-01, -1.4748e-01, -3.9953e-01, -3.8967e-02, + # 3.5521e-02, 1.1342e-01, -1.2244e-01, 1.0107e-01, -7.0909e-02, + # 9.6160e-01, 2.1357e-02, 2.4391e-01, -1.0138e-01, 1.2151e-01, + # -1.3651e-01, -9.7141e-01, 5.3303e-01, 5.5471e-01, -6.6983e-01, + # -8.8017e-02, 2.1613e-01, 1.2814e-01, 1.6456e-01, -8.0381e-02, + # 2.9939e-01, 1.2009e-02, -4.7984e-01, 1.3194e-01, 1.8968e-01, + # 6.8013e-02, 2.3684e-01, 2.5566e-01, -1.6587e-01, -1.9949e-01, + # 3.1261e-01, 5.2987e-01, 1.6465e-01, -2.3355e-03, -5.4320e-01, + # -5.5236e-01, 1.4478e-01, 5.5450e-02, -7.6929e-02, 2.4452e-01, + # -4.5820e-01, -2.8957e-01, 1.8180e-02, 4.3747e-01, -4.2283e-02, + # -5.0567e-01, 4.5314e-02, 1.0879e-01, 1.2915e-01, 5.2620e-02, + # 2.7722e-02, -2.3599e-01, -4.3225e-01, -7.7019e-02, 2.6511e-01, + # 2.2908e-01, -4.3480e-01, 5.2430e-02, 1.1357e-01, -1.8510e-01, + # -5.3361e-02, -4.7402e-02], + # [ 1.5888e+00, 8.1703e-01, 9.5593e-01, -8.2536e-02, 4.7360e-02, + # -3.9056e-01, -6.0633e-01, -1.5541e-01, -4.0785e-01, -4.3322e-02, + # 4.0495e-02, 1.0820e-01, -4.6933e-03, 1.0861e-01, -9.3379e-02, + # 9.6168e-01, 9.5170e-03, 2.4247e-01, -9.9628e-02, 1.1271e-01, + # -1.3622e-01, -9.8448e-01, 5.3791e-01, 5.5485e-01, -6.5830e-01, + # -1.0166e-01, 2.1111e-01, 1.2765e-01, 1.6020e-01, -8.0440e-02, + # 2.9217e-01, 6.0119e-03, -4.7595e-01, 1.2242e-01, 1.9002e-01, + # 5.7588e-02, 2.3393e-01, 2.4151e-01, -1.7059e-01, -1.8763e-01, + # 3.0400e-01, 5.1543e-01, 1.6263e-01, -5.2092e-03, -5.3681e-01, + # -5.4848e-01, 1.4767e-01, 6.1067e-02, -8.5293e-02, 2.4911e-01, + # -4.4561e-01, -2.9968e-01, -1.0991e-03, 4.3592e-01, -4.0780e-02, + # -5.1197e-01, 5.0462e-02, 1.0212e-01, 1.5047e-01, 4.5822e-02, + # 3.3164e-02, -2.3132e-01, -4.2680e-01, -7.8209e-02, 2.6201e-01, + # 2.2518e-01, -4.2874e-01, 5.3289e-02, 1.1230e-01, -1.8014e-01, + # -4.9768e-02, -3.7934e-02]], device='cuda:0') + vertices, faces = smpl2mesh.convert_smpl_to_mesh(rot_motions, current_motions) + if all_faces is None: + all_faces = faces + + all_vertices.append(vertices) + + if torch.is_tensor(all_faces): + all_faces = all_faces.cpu().numpy() + + # Save each sample to its own directory + base_output_dir = './hanyu' + for i, vertices in enumerate(all_vertices): + save_mesh(vertices, all_faces, base_output_dir, output_idx=i) # Use sequential index i instead of sorted_idx[i] + + + +if __name__ == "__main__": + # process_motion("./smpl_params.json", "./predictions/joints3d.npy", "cuda", [25,17,33,7,24]) + # main() + # smpl_to_mesh("./smpl_params.json", "./predictions/joints3d.npy", "cuda", [0]) + process_motion("./smpl_params.json", "./predictions/joints3d.npy", "cuda", [17]) \ No newline at end of file diff --git a/src_joints2smpl_demo/joints2smpl/joint2smpl_models/gmm_08.pkl b/src_joints2smpl_demo/joints2smpl/joint2smpl_models/gmm_08.pkl new file mode 100644 index 0000000000000000000000000000000000000000..c97a1d7ef396581e56ce74a12cc39175680ce028 --- /dev/null +++ b/src_joints2smpl_demo/joints2smpl/joint2smpl_models/gmm_08.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e1374908aae055a2afa01a2cd9a169bc6cfec1ceb7aa590e201a47b383060491 +size 839127 diff --git a/src_joints2smpl_demo/joints2smpl/joint2smpl_models/neutral_smpl_mean_params.h5 b/src_joints2smpl_demo/joints2smpl/joint2smpl_models/neutral_smpl_mean_params.h5 new file mode 100644 index 0000000000000000000000000000000000000000..b6ecce2a748128cfde09b219ccc74307de50bbae --- /dev/null +++ b/src_joints2smpl_demo/joints2smpl/joint2smpl_models/neutral_smpl_mean_params.h5 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac9b474c74daec0253ed084720f662059336e976850f08a4a9a3f76d06613776 +size 4848 diff --git a/src_joints2smpl_demo/joints2smpl/or_convert_joints2smpl.py b/src_joints2smpl_demo/joints2smpl/or_convert_joints2smpl.py new file mode 100644 index 0000000000000000000000000000000000000000..f2c7e9283010b42675232e78ca2628fdb518d2ae --- /dev/null +++ b/src_joints2smpl_demo/joints2smpl/or_convert_joints2smpl.py @@ -0,0 +1,159 @@ +import torch +import numpy as np +import os + +from mesh.io import save_obj, to_mesh +from mesh.smpl2mesh import SMPL2Mesh +from skeleton import SkeletonAMASS, convert2humanml +from skeleton2smpl.skeleton2smpl import Skeleton2Obj +import json + + +def save_mesh(vertices, faces, npy_file): + def npy_path_to_obj_path(npy_path: str) -> str: + return os.path.join(os.path.dirname(npy_path) , f"{npy_path}_obj") + results_dir = npy_path_to_obj_path(npy_file) + os.makedirs(results_dir, exist_ok=True) + for frame_i in range(vertices.shape[-1]): + # first 30 frames save to ./hanyu_obj/obs_obj + if frame_i < 30: + os.makedirs(results_dir+"/obs_obj", exist_ok=True) + file_path = os.path.join(results_dir+"/obs_obj", f"frame{frame_i:03d}.obj") + mesh = to_mesh(vertices[..., frame_i], faces) + save_obj(mesh, file_path) + else: + os.makedirs(results_dir+"/pred_obj", exist_ok=True) + file_path = os.path.join(results_dir+"/pred_obj", f"frame{frame_i:03d}.obj") + mesh = to_mesh(vertices[..., frame_i], faces) + save_obj(mesh, file_path) + print(f"Saved obj files to [{results_dir}]") + +def main(): + num_smplify_iters = 20 # This is what requires most time. It can be decreased or increasd depending on the output quality we want (or how quick we canr each it) + device = "cuda" + + # get observation smpl params + json_file_path = "./smpl_params.json" + with open(json_file_path, "r") as json_file: + loaded_data = json.load(json_file) + person_idx = 0 + smpl_dict_last_obs = loaded_data[-1] + smpl_dict_last_obs = {k: torch.from_numpy(np.array(v)).float().to(device) for k,v in smpl_dict_last_obs.items()} + + # get predictions + #pred_motions = torch.from_numpy(np.load("./predictions/joints3d.npy", allow_pickle=True)).to(device) + pred_motions = torch.from_numpy(np.load("src_joints2smpl_demo/joints2smpl/joints3d.npy", allow_pickle=True)).to(device) + # remove bacth dimension, add a zero hip joint + pred_motions = pred_motions.squeeze(0) + # pred_motions = torch.cat([torch.zeros(*pred_motions.shape[:2], 1, 3).to(device), pred_motions], dim=-2) + + # select just some of the motions + # TO DO use the previous code with the limb length variance error to choose the sample + # Or pick the most diverse + # pred_motions = pred_motions[:1] + pred_motions = pred_motions.view(-1, 22, 3) + + skeleton = SkeletonAMASS + pred_motions = convert2humanml(pred_motions, skeleton.LANDMARKS, skeleton.TO_HUMANML_NAMES) + print(pred_motions) + print(pred_motions.shape) + + init_params = {} + init_params["betas"] = smpl_dict_last_obs["betas"][person_idx].unsqueeze(0).expand(pred_motions.shape[0], -1) + init_params["pose"] = smpl_dict_last_obs["body_pose"][person_idx].view(-1, 3) + init_params["pose"] = torch.stack([init_params["pose"][..., 0], init_params["pose"][..., 2], -init_params["pose"][..., 1]], dim=-1) + assert init_params["pose"].shape[0] == 24, "the body pose should have 24 joints, it is the output of NLF" + + init_params["pose"] = init_params["pose"].unsqueeze(0).expand(pred_motions.shape[0], -1, -1).view(pred_motions.shape[0], -1).to(device) + init_params["cam"] = smpl_dict_last_obs["transl"][person_idx].unsqueeze(0).unsqueeze(-2).expand(pred_motions.shape[0], -1, -1).to(device) + + skeleton2obj = Skeleton2Obj( + device=device, num_smplify_iters=num_smplify_iters, + smpl_model_dir="./models/body_models/", #path to smpl body models + gmm_model_dir="./models/joint2smpl_models/", #path to gmm model + ) + # rot_motions, smpl_dict = skeleton2obj.convert_motion_2smpl(pred_motions, hmp=True, init_params=init_params, fix_betas=True) + thetas, rot_motions = skeleton2obj.convert_motion_2smpl(pred_motions, hmp=True, init_params=init_params, fix_betas=True) + smpl2mesh = SMPL2Mesh(device) + vertices, faces = smpl2mesh.convert_smpl_to_mesh(rot_motions, pred_motions) + + pred_files = [('./hanyu')] + vertices = vertices.reshape(*vertices.shape[:2], len(pred_files), -1) + for v, npy_file in zip(np.moveaxis(vertices, 2, 0), pred_files): + save_mesh(v, faces, npy_file) + + +def process_motion(smpl_params_path, pred_motions_path, device): + num_smplify_iters = 100 # This is what requires most time. It can be decreased or increasd depending on the output quality we want (or how quick we canr each it) + device = "cuda" + + # get observation smpl params + json_file_path = smpl_params_path + with open(json_file_path, "r") as json_file: + loaded_data = json.load(json_file) + person_idx = 0 + smpl_dict_last_obs = loaded_data[-1] + smpl_dict_last_obs = {k: torch.from_numpy(np.array(v)).float().to(device) for k,v in smpl_dict_last_obs.items()} + + # get predictions + pred_motions = torch.from_numpy(np.load(pred_motions_path, allow_pickle=True)).to(device) + # remove bacth dimension, add a zero hip joint + pred_motions = pred_motions.squeeze(0) + # pred_motions = torch.cat([torch.zeros(*pred_motions.shape[:2], 1, 3).to(device), pred_motions], dim=-2) + + # select just some of the motions + # TO DO use the previous code with the limb length variance error to choose the sample + # Or pick the most diverse + pred_motions = pred_motions[:1] + pred_motions = pred_motions.view(-1, 22, 3) + + skeleton = SkeletonAMASS + pred_motions = convert2humanml(pred_motions, skeleton.LANDMARKS, skeleton.TO_HUMANML_NAMES) + # pred_motions = torch.cat([get_humanml_motion(npy_file, skeleton=skeleton, remove_global_translation=True) for npy_file in pred_files], dim=0) + print(pred_motions) + print(pred_motions.shape) + + pred_files = ['pred_closest_GT.npy'] + pred_motions = torch.from_numpy(np.load(pred_files[0], allow_pickle=True)).to(device) + + init_params = {} + init_params["betas"] = smpl_dict_last_obs["betas"][person_idx].unsqueeze(0).expand(pred_motions.shape[0], -1) + init_params["pose"] = smpl_dict_last_obs["body_pose"][person_idx].view(-1, 3) + init_params["pose"] = torch.stack([init_params["pose"][..., 0], init_params["pose"][..., 2], -init_params["pose"][..., 1]], dim=-1) + assert init_params["pose"].shape[0] == 24, "the body pose should have 24 joints, it is the output of NLF" + + init_params["pose"] = init_params["pose"].unsqueeze(0).expand(pred_motions.shape[0], -1, -1).view(pred_motions.shape[0], -1).to(device) + init_params["cam"] = smpl_dict_last_obs["transl"][person_idx].unsqueeze(0).unsqueeze(-2).expand(pred_motions.shape[0], -1, -1).to(device) + # Create a new context for optimization + + + loaded_data = np.load("obs_data.npz", allow_pickle=True) + rot_motions_obs = loaded_data["rot_motions_obs"] + smpl_dict_obs = loaded_data['smpl_dict_obs'].item() + smpl_dict_obs = {k: torch.from_numpy(v).to(device) for k,v in smpl_dict_obs.items()} + init_params = {} + init_params["betas"] = smpl_dict_obs["betas"][-1].unsqueeze(0).expand(pred_motions.shape[0], -1).to(device) + init_params["pose"] = smpl_dict_obs["pose"][-1].unsqueeze(0).expand(pred_motions.shape[0], -1, -1).view(pred_motions.shape[0], -1).to(device) + init_params["cam"] = smpl_dict_obs["cam"][-1].unsqueeze(0).expand(pred_motions.shape[0], -1, -1).to(device) + + + + with torch.set_grad_enabled(True): + skeleton2obj = Skeleton2Obj( + device=device, num_smplify_iters=num_smplify_iters, + smpl_model_dir="./models/body_models/", #path to smpl body models + gmm_model_dir="./models/joint2smpl_models/", #path to gmm model + ) + # rot_motions, smpl_dict = skeleton2obj.convert_motion_2smpl(pred_motions, hmp=True, init_params=init_params, fix_betas=True) + thetas, rot_motions = skeleton2obj.convert_motion_2smpl(pred_motions, hmp=True, init_params=init_params, fix_betas=True) + smpl2mesh = SMPL2Mesh(device) + vertices, faces = smpl2mesh.convert_smpl_to_mesh(rot_motions, pred_motions) + + pred_files = [('./hanyu')] + vertices = vertices.reshape(*vertices.shape[:2], len(pred_files), -1) + for v, npy_file in zip(np.moveaxis(vertices, 2, 0), pred_files): + save_mesh(v, faces, npy_file) + +if __name__ == "__main__": + process_motion("./smpl_params.json", "./predictions/joints3d.npy", "cuda") + # process_motion("./smpl_params.json", "./pred_closest_GT_joints3d.npy", "cuda") diff --git a/src_joints2smpl_demo/joints2smpl/smpl/J_regressor_extra.npy b/src_joints2smpl_demo/joints2smpl/smpl/J_regressor_extra.npy new file mode 100644 index 0000000000000000000000000000000000000000..d6cf8c0f6747d3c623a0d300c5176843ae99031d --- /dev/null +++ b/src_joints2smpl_demo/joints2smpl/smpl/J_regressor_extra.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc968ea4f9855571e82f90203280836b01f13ee42a8e1b89d8d580b801242a89 +size 496160 diff --git a/src_joints2smpl_demo/joints2smpl/smpl/SMPL_NEUTRAL.pkl b/src_joints2smpl_demo/joints2smpl/smpl/SMPL_NEUTRAL.pkl new file mode 100644 index 0000000000000000000000000000000000000000..26574fd104c4b69467f3c7c3516a8508d8a1a36e --- /dev/null +++ b/src_joints2smpl_demo/joints2smpl/smpl/SMPL_NEUTRAL.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:98e65c74ad9b998783132f00880d1025a8d64b158e040e6ef13a557e5098bc42 +size 39001280 diff --git a/src_joints2smpl_demo/joints2smpl/smpl/kintree_table.pkl b/src_joints2smpl_demo/joints2smpl/smpl/kintree_table.pkl new file mode 100644 index 0000000000000000000000000000000000000000..3f72aca47e9257f017ab09470ee977a33f41a49e --- /dev/null +++ b/src_joints2smpl_demo/joints2smpl/smpl/kintree_table.pkl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62116ec76c6192ae912557122ea935267ba7188144efb9306ea1366f0e50d4d2 +size 349 diff --git a/src_joints2smpl_demo/joints2smpl/smpl/smplfaces.npy b/src_joints2smpl_demo/joints2smpl/smpl/smplfaces.npy new file mode 100644 index 0000000000000000000000000000000000000000..6cadb74c9df2b6deebcdc90ee4f8cf9efbffb11d --- /dev/null +++ b/src_joints2smpl_demo/joints2smpl/smpl/smplfaces.npy @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ee8e99db736acf178a6078ab5710ca942edc3738d34c72f41a35c40b370e045 +size 165440 diff --git a/src_joints2smpl_demo/joints2smpl/smpl_params.json b/src_joints2smpl_demo/joints2smpl/smpl_params.json new file mode 100644 index 0000000000000000000000000000000000000000..42576357e390402fba968e06e2198742bb8a502b --- /dev/null +++ b/src_joints2smpl_demo/joints2smpl/smpl_params.json @@ -0,0 +1 @@ +[{"global_orient": [[2.235076665878296, 0.5912238359451294, -2.0333056449890137]], "body_pose": [[2.235076665878296, 0.5912238359451294, -2.0333056449890137, -0.26320821046829224, 0.08898892998695374, 0.09155242890119553, -0.05686645209789276, 0.04846980422735214, -0.01681695692241192, 0.4555761218070984, -0.17835219204425812, -0.0715295672416687, 0.2196042537689209, 0.2591986060142517, -0.3050512969493866, 0.1958654373884201, 0.003415633225813508, 0.014642138965427876, -0.4190638065338135, -0.13970603048801422, 0.061824455857276917, 0.35984086990356445, 0.07621655613183975, 0.46208688616752625, 0.10179727524518967, -0.299708753824234, 0.33556658029556274, 0.30391383171081543, -0.09006142616271973, -0.08523261547088623, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.06398747861385345, 0.2787499725818634, -0.16976237297058105, -0.06870773434638977, -0.20347172021865845, -0.2354484349489212, -0.0070228963159024715, 0.0007133737672120333, 0.2807971239089966, 0.29162076115608215, 0.5381389260292053, 0.10702140629291534, 0.06922454386949539, -0.41233503818511963, -0.5423561930656433, 0.36365941166877747, 0.02485593594610691, 0.6173074245452881, 0.16697777807712555, -0.8762050867080688, 0.12079168856143951, 0.4674608111381531, 1.0964016914367676, 0.13132011890411377, 0.30930304527282715, -0.09329826384782791, -0.30180662870407104, -0.02711314521729946, 0.3867233395576477, 0.10064511001110077, -0.8412137627601624, -0.7213162779808044, -1.7072700262069702, -0.018896423280239105, 1.2357428073883057, 2.9677586555480957]], "betas": [[-0.06483624130487442, 0.40275412797927856, 0.0064761401154100895, 0.0066214026883244514, -0.0005839485093019903, 0.00203340919688344, 0.0006864274037070572, 0.0004278834967408329, 0.0008746726671233773, 0.0018458463018760085]], "transl": [[0.08146461099386215, 0.20399260520935059, -0.03249068185687065]], "joints3d": [[[141.81312561035156, 41.47118377685547, 4334.27490234375], [124.35093688964844, 143.76434326171875, 4288.26220703125], [115.00958251953125, 110.40489196777344, 4417.650390625], [198.9158935546875, -51.31230163574219, 4317.49072265625], [-72.36227416992188, 468.3427734375, 4280.77685546875], [-25.81027603149414, 449.5975341796875, 4539.662109375], [178.35142517089844, -178.83273315429688, 4275.95849609375], [-205.87388610839844, 792.373046875, 4477.0673828125], [-58.224544525146484, 841.1532592773438, 4623.70361328125], [170.61224365234375, -234.93247985839844, 4264.02392578125], [-300.16119384765625, 865.5762329101562, 4416.16552734375], [-180.1011505126953, 882.23486328125, 4662.40087890625], [204.6754913330078, -435.6942138671875, 4192.99755859375], [171.57569885253906, -326.58636474609375, 4149.79931640625], [231.31594848632812, -366.04974365234375, 4289.59716796875], [153.00584411621094, -494.10845947265625, 4162.29345703125], [129.36146545410156, -310.4189453125, 4066.566650390625], [274.4052429199219, -397.46209716796875, 4374.330078125], [-26.496593475341797, -104.24761962890625, 4024.97607421875], [374.6375427246094, -244.58668518066406, 4552.00927734375], [-251.9062957763672, -80.86793518066406, 4128.87060546875], [217.2093963623047, -63.508811950683594, 4640.53173828125]]]}, {"global_orient": [[2.2543082237243652, 0.6171199083328247, -2.0399246215820312]], "body_pose": [[2.2543082237243652, 0.6171199083328247, -2.0399246215820312, -0.25774481892585754, 0.07594107836484909, 0.08769994974136353, -0.06010058522224426, 0.03669213876128197, -0.03831271827220917, 0.46410542726516724, -0.18798036873340607, -0.08461008220911026, 0.16584394872188568, 0.17101262509822845, -0.23154883086681366, 0.18530476093292236, -0.034168221056461334, 0.032099805772304535, -0.4051089286804199, -0.12863124907016754, 0.073444664478302, 0.31977495551109314, 0.18097065389156342, 0.39723241329193115, 0.14523246884346008, -0.2529960572719574, 0.36922556161880493, 0.2692379951477051, -0.09836448729038239, -0.09699954092502594, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.10063552856445312, 0.31853172183036804, -0.17644134163856506, -0.04174060747027397, -0.14169998466968536, -0.191114142537117, 0.05608537048101425, -0.0876624584197998, 0.2466963529586792, 0.2804758548736572, 0.47217750549316406, 0.12938424944877625, 0.03420298174023628, -0.5610716938972473, -0.5033178925514221, 0.45351794362068176, 0.021162105724215508, 0.6750926375389099, 0.09943123906850815, -0.7619940638542175, 0.09169357270002365, 0.5245627164840698, 1.2051246166229248, 0.07155852764844894, 0.24534109234809875, -0.2038554549217224, -0.03496594354510307, -0.04572098329663277, 0.1226971223950386, -0.1041010171175003, 0.8138472437858582, 1.0664364099502563, 3.2143826484680176, -0.6208218336105347, 1.0524497032165527, 2.2084059715270996]], "betas": [[0.23254860937595367, 0.8019757866859436, 0.007051130291074514, 0.006512812804430723, -0.0003769329923670739, 0.0021349319722503424, 0.0008098201942630112, 0.0003362905408721417, 0.0007462863577529788, 0.00165361852850765]], "transl": [[0.08427245914936066, 0.2046634703874588, -0.022500954568386078]], "joints3d": [[[124.99649047851562, 34.16127014160156, 4353.53369140625], [108.70700073242188, 138.2222442626953, 4311.86962890625], [99.5844497680664, 102.04702758789062, 4437.73974609375], [181.4635009765625, -59.86268997192383, 4333.93408203125], [-91.7372055053711, 472.56427001953125, 4313.60595703125], [-45.181434631347656, 443.0897521972656, 4581.1015625], [156.75863647460938, -188.30307006835938, 4286.4609375], [-235.2379913330078, 816.7262573242188, 4490.052734375], [-83.95306396484375, 842.999755859375, 4674.4609375], [149.1695098876953, -244.48106384277344, 4272.7041015625], [-331.6497497558594, 883.23388671875, 4419.5869140625], [-207.27037048339844, 888.80810546875, 4713.02392578125], [180.56492614746094, -443.9439392089844, 4193.21240234375], [148.779541015625, -331.6058349609375, 4154.51416015625], [209.52203369140625, -377.0416564941406, 4292.42236328125], [130.7503204345703, -502.99468994140625, 4155.099609375], [110.36031341552734, -315.10577392578125, 4068.8828125], [259.1894836425781, -415.6515197753906, 4371.5400390625], [-72.13164520263672, -121.76863861083984, 4037.1953125], [393.3454284667969, -265.34173583984375, 4536.42529296875], [-308.6474304199219, -102.02391815185547, 4131.39306640625], [240.4055938720703, -70.50879669189453, 4621.5302734375]]]}, {"global_orient": [[2.212221384048462, 0.6101405620574951, -2.039707660675049]], "body_pose": [[2.212221384048462, 0.6101405620574951, -2.039707660675049, -0.21139390766620636, 0.07957149296998978, 0.07715669274330139, -0.054758671671152115, 0.04517200589179993, -0.014852430671453476, 0.4878922998905182, -0.24414898455142975, -0.12042342126369476, 0.10256923735141754, 0.09229955077171326, -0.26168161630630493, 0.1895090788602829, -0.07213185727596283, -0.010695978067815304, -0.458047479391098, -0.12802107632160187, 0.09417801350355148, 0.4417083263397217, 0.1967267096042633, 0.39232760667800903, 0.13630686700344086, -0.2730455994606018, 0.44894471764564514, 0.27782735228538513, -0.11019176989793777, -0.10308943688869476, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.029161864891648293, 0.34717413783073425, -0.15727174282073975, -0.013441846705973148, -0.038262881338596344, -0.2061341255903244, 0.12182550132274628, -0.19507676362991333, 0.3038940131664276, 0.2783404290676117, 0.4955413341522217, 0.17731112241744995, 0.015002965927124023, -0.5056374073028564, -0.40240544080734253, 0.31221723556518555, 0.008033037185668945, 0.4038274884223938, 0.12657184898853302, -0.8936547636985779, 0.01627434231340885, 0.21337920427322388, 1.078681230545044, 0.011465794406831264, 0.2934558689594269, -0.15425565838813782, 0.14851339161396027, 0.1748007833957672, -0.271149218082428, 0.05556993559002876, -0.9067314863204956, -0.3073689341545105, -1.2046183347702026, -0.23224753141403198, 1.0129964351654053, 2.772582769393921]], "betas": [[-0.14402861893177032, 1.0521563291549683, 0.0077836778946220875, 0.006815033033490181, -0.00027357690851204097, 0.0025352067314088345, 0.0008003275142982602, 0.000667707237880677, 0.001577044720761478, 0.001392871723510325]], "transl": [[0.07492775470018387, 0.20332704484462738, -0.024709368124604225]], "joints3d": [[[102.39886474609375, 29.752689361572266, 4253.810546875], [85.07807159423828, 130.71432495117188, 4210.54345703125], [78.1800765991211, 98.29434967041016, 4334.95166015625], [156.42083740234375, -61.31106185913086, 4236.3701171875], [-106.35124206542969, 464.46563720703125, 4213.09814453125], [-69.83919525146484, 438.23272705078125, 4460.71435546875], [130.51242065429688, -187.6552734375, 4191.83935546875], [-255.20677185058594, 798.093994140625, 4386.10400390625], [-113.29044342041016, 830.0748291015625, 4548.3701171875], [125.7582015991211, -242.56275939941406, 4179.01220703125], [-353.074951171875, 868.6067504882812, 4328.33154296875], [-233.68362426757812, 873.7861328125, 4586.83544921875], [163.7755584716797, -435.2587890625, 4099.39794921875], [123.4250717163086, -327.9169006347656, 4064.87744140625], [193.96205139160156, -367.17657470703125, 4193.03857421875], [111.64566040039062, -494.85272216796875, 4067.76513671875], [86.46710205078125, -313.3641357421875, 3981.623779296875], [256.6843566894531, -396.20379638671875, 4261.95361328125], [-93.28985595703125, -131.91966247558594, 3919.395751953125], [415.1424560546875, -279.4210205078125, 4424.48974609375], [-320.4478454589844, -122.15679931640625, 4022.408203125], [302.672119140625, -154.66627502441406, 4618.55810546875]]]}, {"global_orient": [[2.3825037479400635, 0.6260526180267334, -1.911647081375122]], "body_pose": [[2.3825037479400635, 0.6260526180267334, -1.911647081375122, -0.28840577602386475, 0.07899037003517151, 0.07801518589258194, -0.041376613080501556, 0.05399354174733162, -0.0010278013069182634, 0.48135828971862793, -0.25685355067253113, -0.10379037261009216, 0.23127524554729462, 0.11888892203569412, -0.3095315992832184, 0.16410811245441437, -0.047616828233003616, 0.020566273480653763, -0.4607607126235962, -0.18772071599960327, 0.07995238900184631, 0.32400602102279663, 0.19091027975082397, 0.4308960735797882, 0.11188312619924545, -0.3489267826080322, 0.44534510374069214, 0.2744857668876648, -0.13331232964992523, -0.09988050907850266, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.0403435118496418, 0.3561192750930786, -0.1428021937608719, -0.017244085669517517, -0.05248198285698891, -0.1696353554725647, 0.10551725327968597, -0.2919872999191284, 0.22573544085025787, 0.2507457733154297, 0.48181983828544617, 0.18949924409389496, -0.02243208885192871, -0.584192156791687, -0.4730241894721985, 0.25681036710739136, -0.03058108128607273, 0.3597555458545685, 0.14870066940784454, -0.8310068249702454, 0.07401623576879501, 0.2071477621793747, 1.0458720922470093, 0.011282069608569145, 0.21511507034301758, -0.20170268416404724, 0.06359228491783142, 0.16638241708278656, -0.2928479015827179, 0.12296341359615326, 1.3083816766738892, 0.8407395482063293, 3.393223762512207, -0.4534059464931488, 0.6680096387863159, 1.3864232301712036]], "betas": [[-0.08194644004106522, 1.3152310848236084, 0.007354220375418663, 0.0054145874455571175, -0.0004448226827662438, 0.002404905157163739, 0.0006480487645603716, 0.0006523442571051419, 0.0014293798012658954, 0.0012825948651880026]], "transl": [[0.07137122005224228, 0.20767739415168762, -0.02052055299282074]], "joints3d": [[[74.3300552368164, 26.0869140625, 4222.87451171875], [66.98680877685547, 129.87326049804688, 4185.36328125], [44.03519058227539, 91.19314575195312, 4303.91015625], [125.44078063964844, -66.36713409423828, 4206.15966796875], [-136.89671325683594, 460.7422180175781, 4174.84814453125], [-102.10943603515625, 436.2289123535156, 4430.12646484375], [100.01060485839844, -190.63458251953125, 4152.91796875], [-280.484619140625, 784.8719482421875, 4376.37939453125], [-143.05126953125, 830.9347534179688, 4521.8818359375], [96.1631851196289, -244.56007385253906, 4136.7958984375], [-371.2506103515625, 857.7467041015625, 4309.1640625], [-266.2302551269531, 876.8377075195312, 4549.650390625], [135.47299194335938, -433.5325622558594, 4050.517333984375], [97.73590087890625, -324.3616638183594, 4019.698974609375], [162.8315887451172, -369.33807373046875, 4147.39453125], [85.28608703613281, -493.0155334472656, 4013.36083984375], [63.012020111083984, -309.63507080078125, 3935.987060546875], [228.9062957763672, -406.8209228515625, 4208.1435546875], [-128.50003051757812, -130.63067626953125, 3898.736328125], [405.9424133300781, -318.8743896484375, 4372.130859375], [-361.5446472167969, -138.23924255371094, 3992.571044921875], [324.24505615234375, -232.02581787109375, 4601.556640625]]]}, {"global_orient": [[2.380708932876587, 0.6163097023963928, -1.911881923675537]], "body_pose": [[2.380708932876587, 0.6163097023963928, -1.911881923675537, -0.2973889708518982, 0.0887250304222107, 0.09935217350721359, -0.05561130493879318, 0.053062181919813156, -0.014717062935233116, 0.45278626680374146, -0.2396496683359146, -0.09817306697368622, 0.27394556999206543, 0.1286919265985489, -0.3715493083000183, 0.16546763479709625, 0.01338794082403183, 0.007325942628085613, -0.41501930356025696, -0.1608271598815918, 0.07207491248846054, 0.2944152355194092, 0.18515942990779877, 0.4127456247806549, 0.1180858239531517, -0.3557567596435547, 0.4345252513885498, 0.2645758092403412, -0.13940607011318207, -0.1044124960899353, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.04694584757089615, 0.3267180025577545, -0.12734943628311157, -0.014023222960531712, -0.04729582369327545, -0.1611950844526291, 0.12702275812625885, -0.29958754777908325, 0.19190959632396698, 0.269170343875885, 0.48496150970458984, 0.13243193924427032, -0.047561164945364, -0.5395773649215698, -0.4363960027694702, 0.2590523064136505, -0.07345739006996155, 0.30913668870925903, 0.15229570865631104, -0.7869943380355835, 0.15417064726352692, 0.19703462719917297, 1.1005674600601196, -0.007627885323017836, 0.24785703420639038, -0.34684717655181885, 0.20403385162353516, 0.10680041462182999, -0.1910618096590042, 0.14051061868667603, 0.874902606010437, 0.6757925748825073, 3.070629596710205, -0.4977140426635742, 0.5527265071868896, 1.315273404121399]], "betas": [[0.12326984852552414, 1.1716829538345337, 0.006809080019593239, 0.004667975474148989, -0.0009237332851625979, 0.0023263907060027122, 0.0005868054577149451, 0.0006581837660633028, 0.0014446191489696503, 0.0011912997579202056]], "transl": [[0.06993304938077927, 0.21770556271076202, -0.01940072700381279]], "joints3d": [[[46.69514465332031, 25.45033836364746, 4233.7041015625], [38.705909729003906, 129.9502410888672, 4194.94091796875], [15.490792274475098, 91.66625213623047, 4315.1015625], [99.94190979003906, -68.51215362548828, 4217.603515625], [-165.27005004882812, 463.3668518066406, 4173.0888671875], [-136.279052734375, 436.9798889160156, 4443.54248046875], [78.05741119384766, -195.06031799316406, 4164.390625], [-301.84490966796875, 783.908935546875, 4393.45654296875], [-183.6354217529297, 832.8450927734375, 4547.220703125], [72.99304962158203, -249.93846130371094, 4148.41845703125], [-395.444580078125, 859.1387329101562, 4329.5869140625], [-309.3717346191406, 878.5414428710938, 4572.64013671875], [110.34602355957031, -442.7482604980469, 4062.860595703125], [75.7490005493164, -331.3295593261719, 4029.5517578125], [137.00123596191406, -378.4315185546875, 4162.18798828125], [59.95710372924805, -502.9306640625, 4026.03466796875], [44.249107360839844, -315.7702331542969, 3942.910888671875], [201.32310485839844, -420.795166015625, 4224.677734375], [-140.22628784179688, -132.1497344970703, 3881.6171875], [392.26751708984375, -357.91943359375, 4388.91162109375], [-389.1485595703125, -136.55780029296875, 3934.177734375], [310.1622314453125, -279.91046142578125, 4624.49609375]]]}, {"global_orient": [[2.404195785522461, 0.6195477843284607, -1.8596606254577637]], "body_pose": [[2.404195785522461, 0.6195477843284607, -1.8596606254577637, -0.29189783334732056, 0.06936804950237274, 0.09128884226083755, -0.032129015773534775, 0.03858928382396698, -0.03948532044887543, 0.48641541600227356, -0.24451591074466705, -0.1054789274930954, 0.22269631922245026, 0.11143483966588974, -0.2926728129386902, 0.15289025008678436, 0.0006733111804351211, 0.007558645214885473, -0.46688106656074524, -0.1781706064939499, 0.07438763976097107, 0.3460817337036133, 0.17864251136779785, 0.37842267751693726, 0.18810968101024628, -0.2998804450035095, 0.4882930815219879, 0.29063189029693604, -0.12590596079826355, -0.11634470522403717, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.08552396297454834, 0.29355600476264954, -0.155125230550766, -0.016262317076325417, -0.04054872691631317, -0.11357583850622177, 0.13871024549007416, -0.31905943155288696, 0.14516475796699524, 0.28876179456710815, 0.512678325176239, 0.17679539322853088, -0.05798203498125076, -0.5505009889602661, -0.5627993941307068, 0.24892735481262207, -0.007420890033245087, 0.2955150306224823, 0.04554777964949608, -0.7292127013206482, 0.2909534275531769, 0.1959964632987976, 1.1194041967391968, 0.13220296800136566, -0.03196952864527702, -0.21296270191669464, 0.164640873670578, 0.06296516954898834, -0.2419312447309494, 0.028783589601516724, -0.15290102362632751, 0.9272580742835999, 2.6727988719940186, -0.5231621861457825, 0.5604690909385681, 1.9690974950790405]], "betas": [[0.15485802292823792, 1.241098403930664, 0.008912445046007633, 0.005085628945380449, -0.0009325233986601233, 0.0025475553702563047, 0.0004584629205055535, 0.0004522039380390197, 0.001513455412350595, 0.0011844527907669544]], "transl": [[0.07182282954454422, 0.2162415236234665, -0.013711025938391685]], "joints3d": [[[18.296890258789062, 26.217548370361328, 4222.11669921875], [11.15942096710205, 130.60577392578125, 4183.1767578125], [-16.148439407348633, 92.476318359375, 4301.9990234375], [72.59161376953125, -67.5311279296875, 4208.1328125], [-195.55914306640625, 463.6243896484375, 4156.96923828125], [-168.437744140625, 436.79217529296875, 4436.54833984375], [48.70768737792969, -193.53298950195312, 4153.3564453125], [-351.06683349609375, 799.7687377929688, 4341.07275390625], [-220.44776916503906, 831.9321899414062, 4545.830078125], [46.00818634033203, -248.3839111328125, 4136.6669921875], [-443.0823669433594, 872.67578125, 4271.79443359375], [-344.2644958496094, 886.77197265625, 4562.7958984375], [85.12700653076172, -439.96539306640625, 4049.06298828125], [51.57307815551758, -327.87921142578125, 4016.730712890625], [109.57505798339844, -377.030517578125, 4149.8955078125], [37.575714111328125, -500.576416015625, 4008.58056640625], [23.192108154296875, -315.19622802734375, 3928.5810546875], [172.83425903320312, -424.2598571777344, 4209.96923828125], [-155.3636016845703, -120.32453155517578, 3883.464599609375], [354.7969665527344, -377.33343505859375, 4389.978515625], [-409.9009094238281, -133.00906372070312, 3895.846435546875], [257.9508972167969, -284.1645812988281, 4615.04150390625]]]}, {"global_orient": [[2.396054267883301, 0.5925970077514648, -1.8252424001693726]], "body_pose": [[2.396054267883301, 0.5925970077514648, -1.8252424001693726, -0.25729990005493164, 0.06358680874109268, 0.06188230589032173, -0.03168935328722, 0.04270322993397713, -0.03008376806974411, 0.5114863514900208, -0.21038806438446045, -0.12152291089296341, 0.18515823781490326, 0.11297072470188141, -0.27435725927352905, 0.15852957963943481, -0.011235533282160759, -0.01667979173362255, -0.48406273126602173, -0.16657647490501404, 0.06187892705202103, 0.3977048993110657, 0.18020176887512207, 0.3807508647441864, 0.17026160657405853, -0.3026164472103119, 0.4733774662017822, 0.2881123721599579, -0.1397760808467865, -0.11675059050321579, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.123573437333107, 0.2697981894016266, -0.15950925648212433, -0.026746761053800583, -0.05868586152791977, -0.14799495041370392, 0.09956395626068115, -0.27317383885383606, 0.16697119176387787, 0.3083474636077881, 0.5293124318122864, 0.21476127207279205, -0.053726546466350555, -0.48224082589149475, -0.5874256491661072, 0.3782420754432678, -0.0527438148856163, 0.37706509232521057, 0.14322055876255035, -0.8334208130836487, 0.2016715407371521, 0.29056814312934875, 1.4765177965164185, 0.015220138244330883, 0.18798242509365082, -0.11300001293420792, 0.035443518310785294, 0.014939728192985058, -0.03777145594358444, 0.16039709746837616, 0.7143453359603882, 0.8485549092292786, 2.8482768535614014, -0.29953962564468384, 0.7783933281898499, 2.5579535961151123]], "betas": [[0.06980101764202118, 1.1655066013336182, 0.008782452903687954, 0.005488620605319738, -0.0005574183887802064, 0.0027529853396117687, 0.0005172958481125534, 0.0001757637073751539, 0.0014377138577401638, 0.0012297575594857335]], "transl": [[0.07654742896556854, 0.20849831402301788, -0.008319029584527016]], "joints3d": [[[-13.299219131469727, 23.463592529296875, 4188.6923828125], [-20.300172805786133, 126.36774444580078, 4146.115234375], [-50.010475158691406, 91.59931945800781, 4265.8828125], [41.694820404052734, -69.84475708007812, 4178.78515625], [-220.73199462890625, 460.3845520019531, 4121.5888671875], [-205.4626922607422, 438.14349365234375, 4382.2509765625], [17.57858657836914, -195.03236389160156, 4124.5439453125], [-381.6385803222656, 796.9219360351562, 4293.607421875], [-260.9668273925781, 832.0089111328125, 4483.5087890625], [14.74765682220459, -249.5409698486328, 4107.44921875], [-470.5912780761719, 872.16162109375, 4224.28466796875], [-385.6569519042969, 883.1664428710938, 4499.234375], [57.460235595703125, -440.1687927246094, 4020.841552734375], [25.70229721069336, -328.2353820800781, 3987.72265625], [77.04146575927734, -378.2623291015625, 4122.85205078125], [14.107823371887207, -501.47161865234375, 3977.96435546875], [-0.03163480758666992, -312.1090393066406, 3899.622314453125], [134.7764892578125, -424.1262512207031, 4188.63037109375], [-162.35549926757812, -105.84074401855469, 3853.1845703125], [307.3749084472656, -358.3026428222656, 4369.83447265625], [-413.3360900878906, -109.09709930419922, 3888.838134765625], [127.30656433105469, -249.41920471191406, 4523.39404296875]]]}, {"global_orient": [[2.4445648193359375, 0.5463488101959229, -1.7800519466400146]], "body_pose": [[2.4445648193359375, 0.5463488101959229, -1.7800519466400146, -0.3060373067855835, 0.06533944606781006, 0.08020366728305817, -0.0673392191529274, 0.027315353974699974, -0.014921738766133785, 0.4711306691169739, -0.18690989911556244, -0.10009739547967911, 0.19789868593215942, 0.07199940085411072, -0.2642941474914551, 0.13679935038089752, 0.015929406508803368, -0.03347093239426613, -0.4416161775588989, -0.13290436565876007, 0.046681858599185944, 0.4237934648990631, 0.17194467782974243, 0.2925769090652466, 0.17399932444095612, -0.30510658025741577, 0.40622806549072266, 0.26738739013671875, -0.1265275627374649, -0.12378816306591034, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.08977160602807999, 0.24365116655826569, -0.15829940140247345, -0.004270297009497881, -0.06948314607143402, -0.18669170141220093, 0.05745923891663551, -0.2071714997291565, 0.2102183997631073, 0.26881614327430725, 0.47733867168426514, 0.17044073343276978, -0.05677280202507973, -0.3284102976322174, -0.46838903427124023, 0.37490642070770264, -0.04071705415844917, 0.48827001452445984, 0.1645919233560562, -0.9199379682540894, 0.15705949068069458, 0.3521408140659332, 1.4287797212600708, -0.15508103370666504, 0.21462202072143555, -0.13077133893966675, -0.027220627292990685, -0.18223074078559875, 0.44827699661254883, 0.6609207987785339, -1.094438076019287, -0.6892594695091248, -1.3453047275543213, -0.7881895899772644, 0.7433030009269714, 2.456218719482422]], "betas": [[0.2735362648963928, 1.0662719011306763, 0.008555292151868343, 0.005076784640550613, -0.0003711740719154477, 0.002418979536741972, 0.0006480439915321767, -1.9797338609350845e-05, 0.0012746521970257163, 0.0010513693559914827]], "transl": [[0.0805434137582779, 0.20811757445335388, 0.003223941894248128]], "joints3d": [[[-45.15541458129883, 24.404287338256836, 4232.01611328125], [-47.94039535522461, 127.92218017578125, 4187.82275390625], [-83.9178237915039, 94.91393280029297, 4307.5439453125], [9.41081428527832, -71.86653137207031, 4225.46533203125], [-250.27987670898438, 461.6295166015625, 4137.984375], [-244.98402404785156, 448.5290222167969, 4405.3857421875], [-11.047221183776855, -200.06753540039062, 4172.8251953125], [-417.2065734863281, 812.1777954101562, 4286.02001953125], [-315.8202819824219, 847.6571044921875, 4495.87939453125], [-15.002384185791016, -255.5595245361328, 4156.10546875], [-508.4673767089844, 887.9649658203125, 4217.1181640625], [-444.2955322265625, 895.3215942382812, 4507.36181640625], [29.374032974243164, -450.66363525390625, 4073.98876953125], [5.832345008850098, -336.3053894042969, 4036.4658203125], [40.47952651977539, -388.5434875488281, 4179.21728515625], [-14.516725540161133, -510.262939453125, 4028.188720703125], [-11.054619789123535, -315.46319580078125, 3945.617919921875], [85.20771789550781, -433.2146301269531, 4257.455078125], [-131.34584045410156, -95.61921691894531, 3846.9794921875], [218.18959045410156, -335.3568420410156, 4460.3564453125], [-387.3062744140625, -75.9612808227539, 3846.29736328125], [6.057694911956787, -236.68881225585938, 4581.498046875]]]}, {"global_orient": [[2.4422335624694824, 0.5623995661735535, -1.7674113512039185]], "body_pose": [[2.4422335624694824, 0.5623995661735535, -1.7674113512039185, -0.2870858311653137, 0.06937795132398605, 0.06273678690195084, -0.05999456346035004, 0.024241212755441666, -0.04113936051726341, 0.44176924228668213, -0.18795181810855865, -0.05539974942803383, 0.15911971032619476, 0.07422271370887756, -0.2420744150876999, 0.10831722617149353, 0.0017693918198347092, -0.03797932341694832, -0.4146682322025299, -0.12412650138139725, 0.029173441231250763, 0.5012294054031372, 0.15453436970710754, 0.2128254771232605, 0.2758071720600128, -0.273531436920166, 0.3880317509174347, 0.29171642661094666, -0.10243932157754898, -0.12098139524459839, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.11089939624071121, 0.2681077718734741, -0.2011173516511917, -0.008415859192609787, -0.1496702879667282, -0.1872405707836151, 0.013955209404230118, -0.07839033007621765, 0.23076781630516052, 0.24947601556777954, 0.5132343173027039, 0.21031317114830017, 0.027603933587670326, -0.36178138852119446, -0.6672059893608093, 0.3440578579902649, 0.012634336948394775, 0.6156251430511475, 0.11784215271472931, -0.8790580630302429, 0.20039817690849304, 0.3193919062614441, 1.1598128080368042, -0.11238472908735275, 0.17464028298854828, -0.09032782167196274, -0.06877787411212921, -0.1669895201921463, 0.5276763439178467, 1.6333173513412476, 0.08611496537923813, 0.944818913936615, 3.1132142543792725, -0.4132780432701111, -0.08520518988370895, 3.772068738937378]], "betas": [[0.3799269199371338, 0.77029949426651, 0.009776780381798744, 0.00448232889175415, -0.001175972050987184, 0.0023944543208926916, 0.0009574666619300842, -0.00024241699429694563, 0.001004742574878037, 0.0018615559674799442]], "transl": [[0.08360300958156586, 0.20767132937908173, -0.01536629255861044]], "joints3d": [[[-77.06851959228516, 31.3437557220459, 4237.9150390625], [-81.83026123046875, 135.7222442626953, 4192.6044921875], [-118.86189270019531, 101.36295318603516, 4314.31689453125], [-18.766443252563477, -65.04510498046875, 4231.93798828125], [-283.6612548828125, 469.94512939453125, 4152.302734375], [-283.4168701171875, 449.7843322753906, 4422.27734375], [-33.65678024291992, -196.4020233154297, 4184.8115234375], [-462.6204833984375, 817.3187866210938, 4295.74609375], [-370.673095703125, 844.6181030273438, 4521.3056640625], [-37.67428970336914, -253.13455200195312, 4169.41748046875], [-556.3703002929688, 899.0945434570312, 4236.29052734375], [-497.3909606933594, 898.3871459960938, 4535.80224609375], [5.279590606689453, -453.5719909667969, 4093.1689453125], [-15.038544654846191, -338.77362060546875, 4050.62109375], [14.410992622375488, -388.8288879394531, 4198.87646484375], [-37.07692337036133, -511.1963806152344, 4044.2060546875], [-35.515647888183594, -319.7362365722656, 3958.488525390625], [45.637718200683594, -431.4230041503906, 4286.4150390625], [-149.60189819335938, -80.86632537841797, 3905.9443359375], [130.20140075683594, -297.06292724609375, 4495.44482421875], [-402.7668151855469, -41.408973693847656, 3934.01611328125], [-72.71953582763672, -176.94528198242188, 4614.5341796875]]]}, {"global_orient": [[2.4887948036193848, 0.5310132503509521, -1.7432135343551636]], "body_pose": [[2.4887948036193848, 0.5310132503509521, -1.7432135343551636, -0.33600759506225586, 0.013037788681685925, 0.08037091046571732, -0.10137354582548141, -0.0033131425734609365, -0.06917686015367508, 0.4007682502269745, -0.13735099136829376, -0.06508900225162506, 0.13226181268692017, 0.08529317378997803, -0.1860276758670807, 0.08924545347690582, -0.038535382598638535, -0.01260216161608696, -0.40691041946411133, -0.09556951373815536, -0.018566468730568886, 0.48916882276535034, 0.147759348154068, 0.10092317312955856, 0.35468921065330505, -0.18927666544914246, 0.3995071351528168, 0.33480754494667053, -0.06726734340190887, -0.11146049946546555, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.1392185240983963, 0.1324564814567566, -0.2314857840538025, -0.10681517422199249, -0.2307267189025879, -0.27805060148239136, -0.1697346717119217, 0.1478683352470398, 0.2532943785190582, 0.23876844346523285, 0.526946485042572, 0.2278478741645813, 0.13666631281375885, -0.3158770203590393, -0.7605364322662354, 0.23294170200824738, 0.04433336853981018, 0.7739205956459045, 0.2750962972640991, -0.9265764951705933, 0.15252235531806946, 0.44283950328826904, 1.0397534370422363, 0.2349328249692917, 0.20031701028347015, 0.026237403973937035, -0.13114263117313385, -0.1373436003923416, 0.1457548886537552, 2.47894549369812, -0.6997312307357788, -0.5860100388526917, -1.879911184310913, -0.2101704627275467, -0.5144723057746887, 3.2989795207977295]], "betas": [[0.3377467691898346, 0.030110137537121773, 0.008670177310705185, 0.006044822279363871, -0.0014702518237754703, 0.0025042747147381306, 0.001541396602988243, -0.00023199088172987103, 0.0005765874520875514, 0.0034724494908005]], "transl": [[0.09119492769241333, 0.20701684057712555, -0.010076546110212803]], "joints3d": [[[-113.65170288085938, 39.58369445800781, 4206.39306640625], [-115.49175262451172, 145.28414916992188, 4158.3662109375], [-158.87452697753906, 110.08875274658203, 4283.99365234375], [-54.311126708984375, -58.960689544677734, 4202.42333984375], [-315.31988525390625, 469.0327453613281, 4106.775390625], [-325.4834899902344, 448.43463134765625, 4391.44140625], [-63.18033981323242, -188.0669708251953, 4153.51220703125], [-497.5694580078125, 821.56787109375, 4208.9736328125], [-422.57781982421875, 837.4548950195312, 4478.59130859375], [-68.0877685546875, -244.37501525878906, 4133.6640625], [-595.48193359375, 895.2483520507812, 4147.50830078125], [-546.7606201171875, 896.9119262695312, 4486.14892578125], [-23.5573787689209, -444.35272216796875, 4049.347900390625], [-34.124237060546875, -325.4247131347656, 4010.156982421875], [-26.5970516204834, -387.6517639160156, 4161.890625], [-63.46872329711914, -497.45538330078125, 3997.167236328125], [-46.949520111083984, -290.295166015625, 3919.2177734375], [-27.293621063232422, -434.9722595214844, 4254.67919921875], [-140.60890197753906, -40.78371810913086, 3912.4697265625], [-49.899322509765625, -278.5498046875, 4461.2451171875], [-382.78717041015625, 5.649313449859619, 3978.008056640625], [-250.3592529296875, -111.45879364013672, 4464.5673828125]]]}, {"global_orient": [[2.5115222930908203, 0.5271756649017334, -1.7199043035507202]], "body_pose": [[2.5115222930908203, 0.5271756649017334, -1.7199043035507202, -0.3213677406311035, -0.026688097044825554, 0.018968908116221428, -0.11574051529169083, -0.0311722569167614, -0.10428842902183533, 0.3772413730621338, -0.10415644943714142, -0.05526153743267059, 0.12248588353395462, 0.0661371499300003, -0.18808087706565857, 0.09885994344949722, -0.006967755034565926, -0.038309190422296524, -0.35700663924217224, -0.07512800395488739, -0.002793591935187578, 0.41898682713508606, 0.2593271732330322, 0.08235744386911392, 0.3254014253616333, -0.12382031232118607, 0.33739468455314636, 0.2776702046394348, -0.044476162642240524, -0.08381608873605728, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.17320677638053894, 0.13709157705307007, -0.20101425051689148, -0.026270581409335136, -0.18920382857322693, -0.3029659688472748, -0.1508762389421463, 0.16355983912944794, 0.29758787155151367, 0.28299906849861145, 0.38557499647140503, 0.21364544332027435, 0.10478812456130981, -0.2887594699859619, -0.691877007484436, 0.37453097105026245, 0.10844194144010544, 0.8672909736633301, 0.41014236211776733, -1.1066839694976807, -0.052460674196481705, 0.3659018576145172, 1.2772856950759888, 0.04836535081267357, 0.3300020098686218, -0.04216664656996727, -0.36073732376098633, -0.3492104709148407, 0.4845982789993286, 1.1480516195297241, -0.7326921224594116, -0.3554394841194153, -0.8451351523399353, 0.10709307342767715, 0.501556396484375, 3.5160489082336426]], "betas": [[0.386380672454834, 0.5406057238578796, 0.0047194259241223335, 0.005824988707900047, -0.0004584626294672489, 0.002232980914413929, 0.0010912654688581824, -3.380345879122615e-05, 0.00025037582963705063, 0.002479494782164693]], "transl": [[0.09206085652112961, 0.20382800698280334, -0.011031785048544407]], "joints3d": [[[-151.95140075683594, 51.793922424316406, 4234.08837890625], [-151.14437866210938, 157.12814331054688, 4188.89599609375], [-195.79302978515625, 122.47527313232422, 4309.90576171875], [-95.75467681884766, -46.92929458618164, 4230.001953125], [-358.8443908691406, 486.0182189941406, 4157.5595703125], [-373.4900207519531, 458.2410583496094, 4428.912109375], [-102.63388061523438, -177.55523681640625, 4180.43359375], [-544.1061401367188, 835.603515625, 4282.078125], [-480.4974670410156, 843.760009765625, 4539.03515625], [-107.7072982788086, -233.40252685546875, 4161.1982421875], [-642.0558471679688, 908.0230102539062, 4217.6630859375], [-608.48974609375, 896.2249145507812, 4544.3310546875], [-59.56736755371094, -435.6881103515625, 4090.061767578125], [-62.739990234375, -318.6652526855469, 4047.072265625], [-72.21255493164062, -373.93280029296875, 4197.96875], [-91.64337158203125, -494.1617431640625, 4035.661376953125], [-63.52478790283203, -285.5229797363281, 3955.8681640625], [-86.45377349853516, -414.0767822265625, 4291.73046875], [-132.10147094726562, -27.881528854370117, 3918.86474609375], [-121.69208526611328, -223.87210083007812, 4468.49609375], [-365.5235290527344, 24.646345138549805, 4013.487060546875], [-325.6503601074219, -84.86295318603516, 4376.21240234375]]]}, {"global_orient": [[2.5938425064086914, 0.5389984846115112, -1.6487871408462524]], "body_pose": [[2.5938425064086914, 0.5389984846115112, -1.6487871408462524, -0.35725918412208557, -0.03513073921203613, 0.019420744851231575, -0.10761252790689468, -0.04240311309695244, -0.15211884677410126, 0.34576818346977234, -0.05652826651930809, -0.04160712659358978, 0.12969867885112762, 0.1650947481393814, -0.16444960236549377, 0.06626134365797043, 0.09248259663581848, 0.013021310791373253, -0.34367066621780396, -0.076156847178936, -0.008675004355609417, 0.39511412382125854, 0.1913076788187027, 0.14031165838241577, 0.30719828605651855, -0.0949731394648552, 0.39209890365600586, 0.2781612277030945, -0.015052617527544498, -0.06558667123317719, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.15772239863872528, 0.14633460342884064, -0.16935090720653534, -0.010837376117706299, -0.20959687232971191, -0.3048372268676758, -0.14283140003681183, 0.18204210698604584, 0.3340221345424652, 0.24213886260986328, 0.3105284571647644, 0.19756223261356354, 0.13857300579547882, -0.37461841106414795, -0.7401213645935059, 0.35310667753219604, 0.18858659267425537, 0.9437819719314575, 0.5522937178611755, -1.214426040649414, -0.06075163930654526, 0.3595789074897766, 1.3203706741333008, -0.05627956986427307, 0.09669318050146103, 0.10240301489830017, -0.6084835529327393, 0.21483412384986877, -0.24545979499816895, 0.2593497931957245, -0.43369758129119873, -0.5492515563964844, -0.26610079407691956, 0.4904266893863678, 1.1317118406295776, 2.676398754119873]], "betas": [[0.32670703530311584, 0.5705804228782654, 0.004938386846333742, 0.005335201509296894, -0.0003975114377681166, 0.0018950700759887695, 0.0010569110745564103, -5.964055526419543e-05, 0.00016868551028892398, 0.0019935450982302427]], "transl": [[0.09269165247678757, 0.20442789793014526, -0.006159416865557432]], "joints3d": [[[-188.18568420410156, 62.48371887207031, 4226.419921875], [-182.58233642578125, 169.14163208007812, 4185.646484375], [-235.06326293945312, 130.9401092529297, 4302.0009765625], [-134.16558837890625, -36.70849609375, 4221.78955078125], [-392.385009765625, 495.00970458984375, 4148.4833984375], [-415.4549255371094, 456.547119140625, 4440.2763671875], [-135.91342163085938, -165.75550842285156, 4169.01904296875], [-590.7711181640625, 838.6242065429688, 4264.52197265625], [-531.0197143554688, 835.7149047851562, 4558.1669921875], [-139.71112060546875, -220.62759399414062, 4147.61376953125], [-680.1583251953125, 910.0189819335938, 4188.55615234375], [-655.8148803710938, 891.5819091796875, 4540.28466796875], [-87.89063262939453, -422.3490295410156, 4079.88330078125], [-81.82051086425781, -304.9889831542969, 4039.632568359375], [-113.67749786376953, -362.20526123046875, 4185.734375], [-115.10050964355469, -479.4499816894531, 4021.763916015625], [-71.23089599609375, -270.5109558105469, 3950.0361328125], [-144.30113220214844, -400.01678466796875, 4275.9013671875], [-142.49285888671875, -12.841485023498535, 3926.64599609375], [-205.47329711914062, -191.27099609375, 4420.529296875], [-369.92022705078125, 11.43596363067627, 4042.433837890625], [-389.8131103515625, -76.75745391845703, 4272.57421875]]]}, {"global_orient": [[2.608598232269287, 0.5052104592323303, -1.5622620582580566]], "body_pose": [[2.608598232269287, 0.5052104592323303, -1.5622620582580566, -0.3639957904815674, -0.056922797113657, -0.0200485922396183, -0.14293350279331207, -0.028862737119197845, -0.11496434360742569, 0.3620482087135315, -0.06774723529815674, -0.030406609177589417, 0.1571790724992752, 0.1144411489367485, -0.1686391830444336, 0.10695242881774902, 0.10594409704208374, -0.023896750062704086, -0.3294772207736969, -0.06119299307465553, -0.017315862700343132, 0.4860726594924927, 0.18589052557945251, 0.11423654109239578, 0.3128991425037384, -0.12172293663024902, 0.29059016704559326, 0.25385743379592896, -0.0051031834445893764, -0.047614943236112595, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.17167118191719055, 0.10075201094150543, -0.1874588429927826, -0.006103703752160072, -0.2534902095794678, -0.3242915868759155, -0.14554637670516968, 0.22651156783103943, 0.3184972405433655, 0.2976852357387543, 0.29809117317199707, 0.1647299975156784, 0.12308309227228165, -0.35130494832992554, -0.7582518458366394, 0.28974971175193787, 0.25090861320495605, 0.9565914869308472, 0.5536798238754272, -1.1983702182769775, -0.09038589149713516, 0.3541127145290375, 1.2904210090637207, -0.039528898894786835, 0.002886755857616663, -0.15175104141235352, -0.5874003171920776, 0.20343074202537537, 0.06548715382814407, 0.169697105884552, 0.7883182168006897, 0.7025656700134277, 2.95357084274292, 0.21631884574890137, 1.0938720703125, 2.872718095779419]], "betas": [[0.5070958733558655, 0.5958355069160461, 0.004892305471003056, 0.005297705065459013, -0.00017547070456203073, 0.0017558446852490306, 0.0009438741253688931, -2.0523712009890005e-05, -9.760475222719833e-06, 0.0020223092287778854]], "transl": [[0.09981376677751541, 0.20958589017391205, 0.0004762631724588573]], "joints3d": [[[-222.80935668945312, 68.82554626464844, 4346.6279296875], [-215.1441192626953, 174.686279296875, 4302.71044921875], [-274.28570556640625, 140.23928833007812, 4417.11865234375], [-167.52687072753906, -31.452665328979492, 4348.73388671875], [-434.4548645019531, 497.5547790527344, 4254.45263671875], [-471.6691589355469, 475.4554748535156, 4515.41015625], [-169.35031127929688, -163.84066772460938, 4300.10205078125], [-635.4768676757812, 846.836669921875, 4366.95556640625], [-594.5940551757812, 862.5333251953125, 4616.9306640625], [-173.24961853027344, -219.7964630126953, 4279.833984375], [-727.4940795898438, 925.515869140625, 4299.0283203125], [-722.211181640625, 915.5418701171875, 4597.58251953125], [-120.9849853515625, -427.0291442871094, 4224.37890625], [-109.1361083984375, -310.68585205078125, 4179.068359375], [-152.9894256591797, -361.1050720214844, 4326.5224609375], [-144.9513702392578, -487.53717041015625, 4167.0634765625], [-95.61224365234375, -278.27154541015625, 4088.0], [-195.18966674804688, -396.0981140136719, 4414.54052734375], [-164.01258850097656, -17.501989364624023, 4058.412109375], [-284.5520324707031, -176.6891632080078, 4531.00732421875], [-397.32220458984375, 15.703727722167969, 4166.99658203125], [-452.0550537109375, -75.51950073242188, 4351.34765625]]]}, {"global_orient": [[2.572523593902588, 0.529705286026001, -1.5332484245300293]], "body_pose": [[2.572523593902588, 0.529705286026001, -1.5332484245300293, -0.33780497312545776, -0.059136126190423965, -0.009675441309809685, -0.10598913580179214, -0.059214603155851364, -0.1581934243440628, 0.4014703035354614, -0.01521211676299572, -0.011681172996759415, 0.14879612624645233, 0.11321260035037994, -0.15310581028461456, 0.06530432403087616, 0.07533585280179977, 0.008344944566488266, -0.34135037660598755, -0.06752565503120422, -0.038251250982284546, 0.41276487708091736, 0.28736329078674316, 0.08209154009819031, 0.35686808824539185, -0.029504548758268356, 0.2742038667201996, 0.29115256667137146, -0.013218047097325325, -0.040065355598926544, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.17601214349269867, 0.15434996783733368, -0.17641094326972961, -0.04276486113667488, -0.3082917332649231, -0.3040400445461273, -0.21123407781124115, 0.3165649175643921, 0.2846004366874695, 0.25953325629234314, 0.3100703954696655, 0.160023495554924, 0.12902824580669403, -0.3561405837535858, -0.7733510732650757, 0.36694303154945374, 0.2569752037525177, 0.8062325119972229, 0.5707638263702393, -1.4753698110580444, -0.04810430109500885, 0.4782285988330841, 1.5225129127502441, 0.06669571250677109, -0.14519387483596802, -0.2010301649570465, -0.7894364595413208, 0.05040324851870537, -0.11003067344427109, 0.77583909034729, 0.34949615597724915, 0.8176491260528564, 3.1897335052490234, -0.1495925635099411, 1.0347175598144531, 2.426867723464966]], "betas": [[0.4515717327594757, 0.3484556972980499, 0.004698665346950293, 0.0050720339640975, -0.0003138330939691514, 0.0021295789629220963, 0.0013685113517567515, 0.0002689693064894527, -2.5714514777064323e-05, 0.0027726348489522934]], "transl": [[0.09734039008617401, 0.218958780169487, -0.000518746383022517]], "joints3d": [[[-254.1946563720703, 83.46382904052734, 4280.583984375], [-250.39256286621094, 188.6501007080078, 4233.111328125], [-310.28631591796875, 154.20472717285156, 4349.283203125], [-194.1845245361328, -14.401796340942383, 4286.0654296875], [-470.34344482421875, 505.44036865234375, 4178.03271484375], [-510.9637451171875, 479.3752746582031, 4459.42333984375], [-194.84124755859375, -146.66238403320312, 4240.119140625], [-674.3797607421875, 854.0111083984375, 4274.021484375], [-649.6943969726562, 860.3181762695312, 4550.390625], [-198.16433715820312, -202.69189453125, 4219.44873046875], [-761.0098876953125, 926.0968627929688, 4194.00341796875], [-776.7273559570312, 911.99560546875, 4527.83447265625], [-148.5616455078125, -411.4894714355469, 4165.4228515625], [-132.9109649658203, -295.42926025390625, 4119.91162109375], [-182.84695434570312, -345.24688720703125, 4266.958984375], [-170.93545532226562, -470.1807861328125, 4106.9560546875], [-119.83796691894531, -265.0660095214844, 4027.616943359375], [-234.80970764160156, -382.3628234863281, 4349.087890625], [-193.8949737548828, -8.146736145019531, 3994.033935546875], [-362.3752136230469, -193.95599365234375, 4480.13232421875], [-414.4206237792969, -44.94800567626953, 4122.59423828125], [-445.8968811035156, -85.9253921508789, 4254.28857421875]]]}, {"global_orient": [[2.6158204078674316, 0.49589356780052185, -1.406790018081665]], "body_pose": [[2.6158204078674316, 0.49589356780052185, -1.406790018081665, -0.35574600100517273, -0.06886269152164459, -0.038694269955158234, -0.10783522576093674, -0.0500195249915123, -0.16134290397167206, 0.4036445915699005, 0.0018729715375229716, 0.00982673279941082, 0.19164244830608368, 0.13653825223445892, -0.1871764063835144, 0.10277979075908661, 0.11686330288648605, -0.0009347255108878016, -0.3275431990623474, -0.06639546155929565, -0.06155810505151749, 0.5351313948631287, 0.24884167313575745, 0.08508946001529694, 0.35878631472587585, -0.04525702819228172, 0.22649024426937103, 0.29556581377983093, -0.012582208961248398, -0.01309955958276987, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.20668895542621613, 0.0779762864112854, -0.19340689480304718, -0.017414197325706482, -0.41960543394088745, -0.2652176022529602, -0.1743924617767334, 0.4138279855251312, 0.27484139800071716, 0.29858314990997314, 0.277253121137619, 0.1402302384376526, 0.057630568742752075, -0.4025726020336151, -0.7750173211097717, 0.29346293210983276, 0.5618114471435547, 0.8036180734634399, 0.49946364760398865, -1.6686809062957764, -0.09421642869710922, 0.5558987855911255, 1.5571023225784302, 0.14911583065986633, -0.5207230448722839, -0.5303195714950562, -0.9009547829627991, 0.00806149747222662, 0.1726347804069519, 0.4459773302078247, 0.8262430429458618, 0.4298681318759918, 3.010894536972046, -0.5360052585601807, 0.6929912567138672, 3.061091423034668]], "betas": [[0.39435890316963196, 0.2964358329772949, 0.0023562386631965637, 0.004868490155786276, 1.9782635718001984e-05, 0.002015981124714017, 0.0012247249251231551, 0.0012676228070631623, -0.00039972070953808725, 0.0036096011754125357]], "transl": [[0.09435833990573883, 0.22785112261772156, 0.011563838459551334]], "joints3d": [[[-284.7825622558594, 93.70843505859375, 4325.59521484375], [-275.9720153808594, 197.7703399658203, 4276.43017578125], [-346.6241455078125, 165.85101318359375, 4387.529296875], [-226.23614501953125, -3.979696273803711, 4338.43896484375], [-497.8185119628906, 507.1179504394531, 4202.044921875], [-554.9711303710938, 491.7027893066406, 4472.22802734375], [-224.7023468017578, -137.2049102783203, 4297.45703125], [-708.6201782226562, 848.8248291015625, 4299.86669921875], [-689.4752197265625, 873.4771728515625, 4557.23046875], [-227.29833984375, -193.1439208984375, 4276.8173828125], [-790.6163330078125, 933.989013671875, 4229.23193359375], [-812.7962646484375, 928.0896606445312, 4525.9384765625], [-179.9107666015625, -404.75347900390625, 4234.5791015625], [-155.41346740722656, -291.0892639160156, 4187.6865234375], [-222.41876220703125, -334.3628234863281, 4329.6640625], [-198.23834228515625, -466.04388427734375, 4177.9599609375], [-142.04905700683594, -268.11328125, 4093.513427734375], [-291.7463684082031, -367.2629089355469, 4399.52783203125], [-228.5106964111328, -19.12094497680664, 4042.70654296875], [-457.2992248535156, -167.75682067871094, 4434.45654296875], [-428.536865234375, -104.2485122680664, 4179.4287109375], [-407.6509704589844, -85.298828125, 4189.89306640625]]]}, {"global_orient": [[2.657885789871216, 0.5040292143821716, -1.3327527046203613]], "body_pose": [[2.657885789871216, 0.5040292143821716, -1.3327527046203613, -0.34758320450782776, -0.07616077363491058, -0.07113062590360641, -0.09956581145524979, -0.04084700345993042, -0.18299143016338348, 0.4161948263645172, 0.04306049272418022, 0.022627202793955803, 0.19504444301128387, 0.17210304737091064, -0.1723424792289734, 0.1132003515958786, 0.16570837795734406, 0.004297828767448664, -0.3407648801803589, -0.06088753044605255, -0.07503210008144379, 0.5039346814155579, 0.28679969906806946, 0.13716360926628113, 0.3717058300971985, -0.06931865960359573, 0.28119367361068726, 0.295903742313385, -0.001463638385757804, 0.007604936603456736, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.19174076616764069, 0.09480032324790955, -0.1477072834968567, -0.04708782583475113, -0.4814707934856415, -0.23311717808246613, -0.22473454475402832, 0.4895470142364502, 0.20637807250022888, 0.2692601680755615, 0.23279176652431488, 0.13973267376422882, -0.025789419189095497, -0.4369579553604126, -0.8037078380584717, 0.2701107859611511, 0.5713655948638916, 0.8474581241607666, 0.5258488655090332, -1.5989596843719482, -0.02623460441827774, 0.5846226215362549, 1.7683498859405518, -0.004425095394253731, -0.45364657044410706, -0.6387172937393188, -1.4487743377685547, -0.21777494251728058, -0.05580596253275871, -0.0818115621805191, 0.555927574634552, 0.38016998767852783, 2.910980224609375, -0.9163950085639954, 0.6340527534484863, 1.7263621091842651]], "betas": [[0.1987072229385376, 0.49205273389816284, 0.001941675553098321, 0.004255747422575951, -0.00026909849839285016, 0.0017920321552082896, 0.001251966692507267, 0.0013517611660063267, -0.00037773637450300157, 0.003319439711049199]], "transl": [[0.09329693764448166, 0.22994863986968994, 0.019095025956630707]], "joints3d": [[[-304.04840087890625, 97.41973876953125, 4294.4541015625], [-292.1835021972656, 201.30819702148438, 4248.7265625], [-367.7366638183594, 167.9674835205078, 4353.80419921875], [-248.42173767089844, 0.885404109954834, 4307.68603515625], [-514.5521240234375, 509.02459716796875, 4179.41357421875], [-581.92626953125, 486.80841064453125, 4439.62744140625], [-246.2813720703125, -130.35528564453125, 4264.6630859375], [-730.080078125, 842.3909301757812, 4279.56591796875], [-719.1082763671875, 860.6554565429688, 4535.3330078125], [-246.94322204589844, -184.77590942382812, 4242.7470703125], [-800.5374755859375, 929.3453979492188, 4201.89892578125], [-835.1998901367188, 921.634521484375, 4496.6572265625], [-199.3849334716797, -394.053466796875, 4204.47802734375], [-168.5356903076172, -281.8753967285156, 4162.9833984375], [-249.88575744628906, -324.20721435546875, 4293.22705078125], [-214.2622833251953, -455.2507019042969, 4147.17529296875], [-149.9912872314453, -263.0135498046875, 4070.647705078125], [-327.7989196777344, -362.8356628417969, 4346.08154296875], [-253.83763122558594, -24.948143005371094, 4012.588623046875], [-498.6937255859375, -168.06536865234375, 4346.47216796875], [-466.7236328125, -117.69225311279297, 4115.51708984375], [-378.2757263183594, -132.50379943847656, 4118.42724609375]]]}, {"global_orient": [[2.6935322284698486, 0.516211211681366, -1.2372361421585083]], "body_pose": [[2.6935322284698486, 0.516211211681366, -1.2372361421585083, -0.28593510389328003, -0.06705296039581299, -0.10259296000003815, -0.08366753906011581, -0.011334102600812912, -0.1433108001947403, 0.40365901589393616, 0.03525324538350105, 0.014038643799722195, 0.17660094797611237, 0.13163752853870392, -0.169755756855011, 0.058508481830358505, 0.1928783506155014, -0.0029202625155448914, -0.28169897198677063, -0.0561196506023407, -0.05296500027179718, 0.49206286668777466, 0.2644173502922058, 0.10596742480993271, 0.3962527811527252, -0.053417280316352844, 0.2904530167579651, 0.25135698914527893, 0.009787448681890965, 0.018062099814414978, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2514139711856842, 0.08164045959711075, -0.10947157442569733, -0.03138021007180214, -0.45291274785995483, -0.2394820898771286, -0.2292342185974121, 0.4637274742126465, 0.2134215384721756, 0.2826952636241913, 0.19277280569076538, 0.11424688994884491, 0.006253140978515148, -0.4396686851978302, -0.835538387298584, 0.38558030128479004, 0.46105778217315674, 0.7583271861076355, 0.42242950201034546, -1.6076511144638062, -0.004913431592285633, 0.6281929016113281, 1.9269269704818726, -0.09540308266878128, -0.022987142205238342, -0.4544720947742462, -0.1361057609319687, -0.43030592799186707, 0.232955664396286, 0.3892863094806671, 0.5407847762107849, 0.769432783126831, 2.953130006790161, -1.1693071126937866, 0.5924251675605774, 3.1648595333099365]], "betas": [[0.03633418679237366, 1.0032860040664673, 0.002128701424226165, 0.00447583943605423, -0.00022639056260231882, 0.002103254897519946, 0.0011171390069648623, 0.0011284096399322152, -0.00020303965720813721, 0.0028990008868277073]], "transl": [[0.09174903482198715, 0.2217942178249359, 0.02039853297173977]], "joints3d": [[[-325.27288818359375, 96.72030639648438, 4286.66015625], [-310.864501953125, 199.86117553710938, 4245.57373046875], [-390.2742004394531, 165.7515411376953, 4341.87646484375], [-273.1839294433594, 1.947399616241455, 4300.37060546875], [-525.6994018554688, 517.3146362304688, 4185.7861328125], [-605.161865234375, 490.70068359375, 4406.91845703125], [-265.8909606933594, -128.43832397460938, 4256.17333984375], [-741.8283081054688, 847.77294921875, 4291.3486328125], [-759.4522705078125, 862.4266357421875, 4476.7099609375], [-266.4075012207031, -181.1772003173828, 4233.7666015625], [-813.9044189453125, 935.1595458984375, 4217.54296875], [-865.5333862304688, 925.0463256835938, 4420.61865234375], [-219.91929626464844, -387.36236572265625, 4200.11962890625], [-185.5731201171875, -277.332763671875, 4162.90234375], [-273.5856628417969, -316.85321044921875, 4282.66845703125], [-228.6787872314453, -453.5749206542969, 4146.14794921875], [-159.39019775390625, -259.8805847167969, 4074.865966796875], [-352.067138671875, -354.2063903808594, 4330.18994140625], [-249.5653533935547, -16.306612014770508, 4019.901611328125], [-532.3890380859375, -171.7774200439453, 4356.830078125], [-472.99603271484375, -111.92250061035156, 4088.6259765625], [-390.4151306152344, -125.47435760498047, 4144.689453125]]]}, {"global_orient": [[2.7505288124084473, 0.5343273878097534, -1.1479772329330444]], "body_pose": [[2.7505288124084473, 0.5343273878097534, -1.1479772329330444, -0.2903667092323303, -0.05651991441845894, -0.11310049146413803, -0.11667199432849884, 0.008252034895122051, -0.10097569972276688, 0.39623069763183594, 0.03663397207856178, 0.022257858887314796, 0.21146433055400848, 0.11367294192314148, -0.15375331044197083, 0.07093274593353271, 0.18962112069129944, -0.0007662623538635671, -0.2497352957725525, -0.07811519503593445, -0.037843987345695496, 0.48041316866874695, 0.2467627227306366, 0.06751667708158493, 0.42397716641426086, -0.060935620218515396, 0.2518123686313629, 0.22029918432235718, -0.0015500024892389774, 0.03503638133406639, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2680910527706146, 0.08089476078748703, -0.10300593078136444, -0.05294322595000267, -0.4667307138442993, -0.21651741862297058, -0.2541501820087433, 0.44169339537620544, 0.17142637073993683, 0.24584561586380005, 0.20120546221733093, 0.11731881648302078, -0.023372933268547058, -0.4169006943702698, -0.82090824842453, 0.4060131013393402, 0.2798783481121063, 0.7710980176925659, 0.20326845347881317, -1.4487276077270508, 0.11414947360754013, 0.473270058631897, 1.8157793283462524, -0.25894299149513245, -0.11624439805746078, -0.7178552746772766, -0.6551896929740906, -0.07287706434726715, -0.13109420239925385, 0.24263715744018555, 0.16442352533340454, 0.7402419447898865, 2.614809036254883, -0.14003543555736542, 0.6566118001937866, 3.249182939529419]], "betas": [[-0.2999410927295685, 0.9462387561798096, 0.0040649655275046825, 0.0029967876616865396, -0.0012749904999509454, 0.0014042605180293322, 0.0010833778651431203, 0.000918146746698767, 4.725334292743355e-05, 0.002660347381606698]], "transl": [[0.09649202227592468, 0.21579237282276154, 0.029210999608039856]], "joints3d": [[[-335.2835388183594, 96.54940032958984, 4248.78173828125], [-317.80682373046875, 199.93312072753906, 4212.37255859375], [-403.27618408203125, 162.66351318359375, 4302.013671875], [-285.88812255859375, 3.276505470275879, 4261.55126953125], [-527.997802734375, 511.5725402832031, 4153.2900390625], [-617.4863891601562, 482.7413024902344, 4341.380859375], [-275.5328674316406, -123.42112731933594, 4216.6396484375], [-735.7337036132812, 835.5709228515625, 4259.71142578125], [-768.8286743164062, 847.9642944335938, 4395.0517578125], [-277.26971435546875, -174.11231994628906, 4192.50146484375], [-805.464599609375, 923.7304077148438, 4189.73828125], [-867.2467651367188, 911.9269409179688, 4334.00390625], [-231.14967346191406, -377.71600341796875, 4163.599609375], [-195.9592742919922, -270.1380920410156, 4127.08837890625], [-286.61529541015625, -307.17779541015625, 4241.41796875], [-238.36892700195312, -443.84765625, 4111.8017578125], [-167.79058837890625, -256.8453674316406, 4040.921630859375], [-362.4170227050781, -346.76605224609375, 4286.73779296875], [-251.48681640625, -20.798198699951172, 3970.572509765625], [-537.6405639648438, -176.03707885742188, 4350.0146484375], [-485.0135192871094, -99.9091796875, 3961.694580078125], [-477.8434143066406, -133.4552459716797, 4107.05908203125]]]}, {"global_orient": [[2.7472481727600098, 0.5057802200317383, -0.9728426933288574]], "body_pose": [[2.7472481727600098, 0.5057802200317383, -0.9728426933288574, -0.11425145715475082, -0.08105922490358353, -0.20171761512756348, -0.04153401777148247, 0.005775908939540386, -0.0848674401640892, 0.45528313517570496, 0.007680265698581934, 0.006441818084567785, 0.20477403700351715, 0.18530240654945374, -0.17253820598125458, 0.01870332472026348, 0.24837762117385864, -0.01905936375260353, -0.29249483346939087, -0.07841024547815323, -0.049425460398197174, 0.2867429256439209, 0.19472195208072662, 0.16740144789218903, 0.3800089657306671, -0.10566423833370209, 0.16778112947940826, 0.2165011763572693, 0.04248581826686859, 0.03215477615594864, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.16786514222621918, 0.05943955481052399, -0.12677976489067078, 0.06057443842291832, -0.4476434886455536, -0.23314382135868073, -0.1994078904390335, 0.3927057385444641, 0.15628159046173096, 0.2148905098438263, 0.23979194462299347, 0.1384163200855255, -0.028814932331442833, -0.49942803382873535, -0.8134450316429138, 0.3227894902229309, 0.5671384334564209, 0.7763096690177917, 0.2147023230791092, -1.3412514925003052, 0.14313137531280518, 0.5439261794090271, 1.954758882522583, -0.08089307695627213, 0.3318256437778473, -0.21092495322227478, 0.049316681921482086, -0.1607591211795807, -0.1754474639892578, -0.26141679286956787, -0.43765878677368164, 0.25961992144584656, -0.7260973453521729, -1.0328341722488403, 0.4417640268802643, 1.7134000062942505]], "betas": [[-0.08519036322832108, 1.709928035736084, 0.002574273617938161, 0.0053369575180113316, 0.00028207487775944173, 0.0019690350163728, 0.0008375980542041361, 0.001155963633209467, 0.0005756035097874701, 0.0011476378422230482]], "transl": [[0.08664580434560776, 0.20973558723926544, 0.03750045970082283]], "joints3d": [[[-354.7725830078125, 91.09598541259766, 4342.916015625], [-335.0121154785156, 192.62901306152344, 4307.35546875], [-425.7241516113281, 159.40882873535156, 4384.587890625], [-308.00262451171875, -1.293228268623352, 4363.72607421875], [-536.7711181640625, 528.19873046875, 4275.421875], [-636.0917358398438, 498.2090148925781, 4400.81005859375], [-296.39117431640625, -131.01510620117188, 4316.86474609375], [-749.0177001953125, 848.460205078125, 4420.09375], [-798.0079345703125, 873.9147338867188, 4424.43408203125], [-292.8948059082031, -182.54373168945312, 4295.689453125], [-810.90283203125, 933.3295288085938, 4335.8818359375], [-893.946044921875, 929.2926025390625, 4348.28759765625], [-242.70907592773438, -384.7992858886719, 4272.81103515625], [-204.2102813720703, -276.6977844238281, 4242.92529296875], [-305.9823913574219, -313.4776611328125, 4342.8779296875], [-245.86705017089844, -449.7173156738281, 4214.5107421875], [-167.56983947753906, -261.7184143066406, 4161.41796875], [-383.8944396972656, -356.0407409667969, 4379.6435546875], [-250.3879852294922, -18.232301712036133, 4092.899169921875], [-569.9295654296875, -178.4398193359375, 4362.76025390625], [-492.85137939453125, -75.23770904541016, 4052.61083984375], [-395.7573547363281, -153.08819580078125, 4171.5869140625]]]}, {"global_orient": [[2.8875997066497803, 0.5099083781242371, -0.8127023577690125]], "body_pose": [[2.8875997066497803, 0.5099083781242371, -0.8127023577690125, -0.09791882336139679, -0.08609697222709656, -0.2527993321418762, -0.1128043457865715, 0.011893951334059238, -0.0550025999546051, 0.40480369329452515, -0.009925466030836105, 0.029435565695166588, 0.2535329759120941, 0.1755043864250183, -0.1218399852514267, 0.006876985542476177, 0.1857205033302307, -0.016483109444379807, -0.2698368728160858, -0.06233147159218788, -0.04878407344222069, 0.10134860873222351, 0.13710720837116241, 0.15071044862270355, 0.4124726355075836, -0.10078109055757523, 0.038608137518167496, 0.1588706374168396, 0.007675854954868555, 0.03169576823711395, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2133379578590393, 0.015669407323002815, -0.08954361081123352, 0.05637650564312935, -0.4574577510356903, -0.21764130890369415, -0.17243929207324982, 0.4118211269378662, 0.14890366792678833, 0.2722129225730896, 0.18996989727020264, 0.11818547546863556, -0.06461871415376663, -0.5501833558082581, -0.8823786973953247, 0.24661846458911896, 0.6702943444252014, 0.8121451139450073, 0.20003026723861694, -1.14751136302948, 0.138568714261055, 0.46065789461135864, 1.7340770959854126, -0.13979780673980713, 0.3715384006500244, -0.08441876620054245, -0.07377516478300095, -0.14687950909137726, -0.09968376159667969, -0.14069367945194244, -0.3157493770122528, -0.05535474419593811, -0.15702064335346222, -0.5834012627601624, 0.5582321882247925, 1.3309590816497803]], "betas": [[0.2743426561355591, 1.6977509260177612, 0.0030746820848435163, 0.004925168585032225, 0.0005511929048225284, 0.0016878056339919567, 0.0007759633008390665, 0.00114191765896976, 0.0006853826926089823, 0.0008554372470825911]], "transl": [[0.0844557136297226, 0.21295934915542603, 0.045580778270959854]], "joints3d": [[[-375.78070068359375, 93.41423034667969, 4469.89306640625], [-350.1802673339844, 198.54440307617188, 4446.7666015625], [-450.3343200683594, 160.8257293701172, 4510.0576171875], [-332.0115966796875, -4.451488494873047, 4487.94873046875], [-553.880859375, 542.839599609375, 4443.04150390625], [-661.4601440429688, 508.53076171875, 4507.16650390625], [-316.6458435058594, -134.80224609375, 4435.056640625], [-760.5626220703125, 862.3325805664062, 4621.0498046875], [-823.9034423828125, 895.2595825195312, 4513.26025390625], [-311.6936340332031, -186.52212524414062, 4411.1845703125], [-816.6932373046875, 945.0227661132812, 4526.50830078125], [-920.9592895507812, 949.537841796875, 4432.11572265625], [-257.91778564453125, -391.93585205078125, 4388.6435546875], [-215.55233764648438, -281.03509521484375, 4364.5478515625], [-329.91357421875, -320.99462890625, 4455.22021484375], [-255.4085235595703, -460.92120361328125, 4332.814453125], [-169.96990966796875, -264.83465576171875, 4285.34033203125], [-414.06610107421875, -365.6280212402344, 4481.1875], [-269.3203430175781, -20.446096420288086, 4220.7255859375], [-588.160400390625, -177.95828247070312, 4420.2998046875], [-512.6572875976562, -49.573509216308594, 4138.935546875], [-419.2537536621094, -156.55914306640625, 4216.41259765625]]]}, {"global_orient": [[2.95688533782959, 0.4649149179458618, -0.6578723192214966]], "body_pose": [[2.95688533782959, 0.4649149179458618, -0.6578723192214966, -0.08564840257167816, -0.08487331122159958, -0.26480191946029663, -0.0928540825843811, -0.006029695738106966, -0.10600600391626358, 0.3624931573867798, -0.012843545526266098, -0.00177763553801924, 0.13630624115467072, 0.04925074428319931, -0.07712739706039429, 0.031646810472011566, 0.17201709747314453, -0.03210020065307617, -0.23730748891830444, -0.06454165279865265, -0.038611263036727905, 0.20484332740306854, 0.20510539412498474, 0.08750974386930466, 0.3365727663040161, -0.12286437302827835, 0.12062933295965195, 0.1375279724597931, -0.001815955387428403, 0.026740193367004395, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.25926074385643005, -0.023444749414920807, -0.06960076838731766, 0.0780334323644638, -0.3694126009941101, -0.26843973994255066, -0.1753164678812027, 0.3322804570198059, 0.17202261090278625, 0.3193880617618561, 0.17754212021827698, 0.10603609681129456, 0.022559570148587227, -0.49517425894737244, -0.8992018103599548, 0.3304367661476135, 0.5070575475692749, 0.8365604281425476, 0.23121370375156403, -1.1197359561920166, 0.11253906041383743, 0.45610594749450684, 1.5961341857910156, -0.19227509200572968, 0.37193992733955383, 0.09741007536649704, 0.14511235058307648, -0.27141156792640686, -0.30641984939575195, -0.22313590347766876, -0.45613977313041687, -0.21952436864376068, -0.43605732917785645, -0.31669387221336365, 0.24328936636447906, 2.3656458854675293]], "betas": [[0.32217147946357727, 1.7988028526306152, 0.003566752653568983, 0.005051298066973686, 0.0002481533447280526, 0.0016917893663048744, 0.0008291978156194091, 0.0007310493965633214, 0.0005285892402753234, 0.001231249887496233]], "transl": [[0.08219368755817413, 0.2022160142660141, 0.04349749907851219]], "joints3d": [[[-389.8565368652344, 92.84510803222656, 4519.9560546875], [-358.56829833984375, 197.55140686035156, 4503.5400390625], [-465.4581298828125, 161.95907592773438, 4554.42724609375], [-351.7285461425781, -7.254251956939697, 4538.98974609375], [-551.4756469726562, 550.2649536132812, 4495.88427734375], [-677.5341186523438, 511.4315490722656, 4557.98779296875], [-328.8020935058594, -137.2888946533203, 4486.314453125], [-771.7824096679688, 888.6019287109375, 4619.02880859375], [-842.6722412109375, 898.0347290039062, 4588.048828125], [-321.8138122558594, -188.47181701660156, 4461.71044921875], [-821.3014526367188, 972.9037475585938, 4521.5986328125], [-932.879150390625, 954.6593627929688, 4500.1162109375], [-265.4943542480469, -393.4748840332031, 4440.95947265625], [-221.2772674560547, -281.959716796875, 4423.3837890625], [-343.80023193359375, -323.5743713378906, 4501.40966796875], [-257.2386169433594, -465.0992431640625, 4388.33447265625], [-162.86819458007812, -259.56988525390625, 4354.84326171875], [-428.8353271484375, -367.5694580078125, 4525.7314453125], [-233.799072265625, 0.07357269525527954, 4311.02490234375], [-606.9935302734375, -173.74105834960938, 4504.9482421875], [-469.30230712890625, 13.071229934692383, 4202.98583984375], [-490.7340087890625, -114.4754867553711, 4272.30859375]]]}, {"global_orient": [[2.9876139163970947, 0.4342535436153412, -0.45006662607192993]], "body_pose": [[2.9876139163970947, 0.4342535436153412, -0.45006662607192993, 0.04942600056529045, -0.09930245578289032, -0.30500271916389465, -0.04325874522328377, -0.033240385353565216, -0.1397666335105896, 0.4026450514793396, -0.055385954678058624, 0.006426194217056036, 0.07706844061613083, -0.004754312336444855, -0.04407595098018646, 0.03951013833284378, 0.15091097354888916, -0.024854205548763275, -0.23725305497646332, -0.05593069642782211, -0.05053632706403732, 0.21512044966220856, 0.18105965852737427, 0.027677761390805244, 0.333103209733963, -0.13821229338645935, 0.130246102809906, 0.11176890879869461, -0.004398232325911522, 0.015752162784337997, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.258548766374588, -0.06606580317020416, -0.08838335424661636, 0.12418272346258163, -0.30947351455688477, -0.3118438720703125, -0.1444137543439865, 0.22377707064151764, 0.21454307436943054, 0.36701834201812744, 0.19228437542915344, 0.10564950853586197, 0.07703220099210739, -0.47900766134262085, -0.849250078201294, 0.3549456298351288, 0.365945428609848, 0.758251428604126, 0.37970760464668274, -0.9056850075721741, 0.07613171637058258, 0.5049760341644287, 1.403335690498352, -0.07716294378042221, 0.2011430263519287, -0.028426742181181908, -0.11689666658639908, 0.16630081832408905, -0.18578878045082092, -0.0007879132754169405, -0.16720987856388092, -0.04395761340856552, 0.11746345460414886, -0.4627411663532257, 0.6417720317840576, 1.9879392385482788]], "betas": [[0.6007941961288452, 2.0338363647460938, 0.005650955252349377, 0.005671618040651083, 0.0005136631662026048, 0.001891539548523724, 0.0011271638795733452, 0.0003011753433384001, 0.0004126839921809733, 0.0009929228108376265]], "transl": [[0.08393050730228424, 0.19000333547592163, 0.03287241607904434]], "joints3d": [[[-396.7364807128906, 87.48976135253906, 4621.7294921875], [-362.7763671875, 192.37779235839844, 4611.01513671875], [-474.7801208496094, 158.45281982421875, 4646.2421875], [-362.5510559082031, -14.757532119750977, 4645.484375], [-547.920166015625, 557.683837890625, 4634.81982421875], [-691.1207885742188, 515.052978515625, 4647.76123046875], [-338.62811279296875, -146.31719970703125, 4589.05615234375], [-770.6339111328125, 904.8385620117188, 4760.7802734375], [-857.0781860351562, 910.7314453125, 4683.912109375], [-329.8116760253906, -197.88540649414062, 4564.11181640625], [-819.6410522460938, 995.3693237304688, 4665.220703125], [-942.9588623046875, 973.1005859375, 4591.57177734375], [-272.5637512207031, -404.65423583984375, 4542.6630859375], [-225.5635223388672, -291.721435546875, 4533.24072265625], [-356.62298583984375, -334.69464111328125, 4598.12451171875], [-258.82037353515625, -476.6947326660156, 4488.65234375], [-157.50209045410156, -263.5877990722656, 4475.21142578125], [-444.3067932128906, -376.3146667480469, 4622.6728515625], [-206.22891235351562, 8.030389785766602, 4443.244140625], [-636.9603881835938, -189.57626342773438, 4639.54248046875], [-424.607666015625, 104.45181274414062, 4328.79248046875], [-584.46826171875, -56.05320739746094, 4408.4208984375]]]}, {"global_orient": [[2.9898452758789062, 0.4919099509716034, -0.45203638076782227]], "body_pose": [[2.9898452758789062, 0.4919099509716034, -0.45203638076782227, -0.012051334604620934, -0.0581999234855175, -0.22633884847164154, -0.03417058289051056, -0.04078887403011322, -0.1047515943646431, 0.4166633188724518, -0.027657289057970047, 0.024137888103723526, 0.17019596695899963, -0.06875135004520416, -0.08225183933973312, 0.08198307454586029, 0.17182253301143646, -0.015281757339835167, -0.2380262017250061, -0.05138259008526802, -0.04368618130683899, 0.12506140768527985, 0.26426178216934204, 0.0289523396641016, 0.2460917830467224, -0.11291306465864182, 0.16086669266223907, 0.13367609679698944, -0.004425554070621729, 0.022985128685832024, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.21738497912883759, -0.06634131073951721, -0.04724361002445221, 0.06993398070335388, -0.34285464882850647, -0.42352190613746643, -0.15060676634311676, 0.26560309529304504, 0.27453190088272095, 0.29571014642715454, 0.20370584726333618, 0.07145189493894577, 0.10909188538789749, -0.3773520886898041, -0.7538566589355469, 0.338432639837265, 0.2834511399269104, 0.6443642973899841, 0.3117578327655792, -0.6782563924789429, 0.1626996099948883, 0.5288803577423096, 1.0499513149261475, -0.08298376202583313, 0.22797879576683044, 0.10974205285310745, -0.06668634712696075, 0.16963475942611694, -0.11056135594844818, 0.009871679358184338, -0.39645916223526, -0.19041480123996735, -0.2979227900505066, -0.7764298319816589, 0.5073383450508118, 0.9638333320617676]], "betas": [[0.5245786309242249, 1.6400560140609741, 0.003747760783880949, 0.004337412770837545, 0.0005348086706362665, 0.0014376536710187793, 0.0008594655664637685, 0.0006368676549755037, 0.0004873364814557135, 0.0009281558450311422]], "transl": [[0.08220869302749634, 0.18242064118385315, 0.03447752073407173]], "joints3d": [[[-392.6338195800781, 85.56379699707031, 4606.9736328125], [-361.494873046875, 192.27760314941406, 4596.23779296875], [-474.83685302734375, 153.07984924316406, 4632.11083984375], [-354.1448059082031, -15.89034652709961, 4630.58447265625], [-538.3370971679688, 556.1304931640625, 4593.49951171875], [-686.7255249023438, 505.9219055175781, 4640.33935546875], [-327.9078063964844, -144.49765014648438, 4572.4541015625], [-749.08984375, 900.6712646484375, 4730.1884765625], [-841.9097900390625, 898.1004028320312, 4699.85546875], [-318.9018859863281, -195.14300537109375, 4545.232421875], [-789.5487670898438, 988.5655517578125, 4629.56640625], [-921.2861328125, 960.2789916992188, 4602.86181640625], [-262.3498840332031, -402.27984619140625, 4517.83935546875], [-213.84861755371094, -289.35369873046875, 4511.99560546875], [-347.983642578125, -334.155517578125, 4574.1181640625], [-254.0109100341797, -470.5383605957031, 4460.29150390625], [-147.61166381835938, -249.69442749023438, 4457.50048828125], [-440.1519470214844, -369.51995849609375, 4594.07763671875], [-187.0413360595703, 21.68207550048828, 4434.0634765625], [-641.356201171875, -196.24717712402344, 4619.55419921875], [-351.9273986816406, 171.1759490966797, 4294.986328125], [-682.65771484375, -20.607309341430664, 4419.4013671875]]]}, {"global_orient": [[2.983872413635254, 0.49188926815986633, -0.45121586322784424]], "body_pose": [[2.983872413635254, 0.49188926815986633, -0.45121586322784424, 0.03255767747759819, -0.026994260028004646, -0.2061242163181305, 0.03229904919862747, -0.043983545154333115, -0.10774142295122147, 0.4466613233089447, -0.0035019691567867994, 0.031683675944805145, 0.16151192784309387, -0.1346728801727295, -0.09776828438043594, 0.07030606269836426, 0.23214073479175568, -0.04771986976265907, -0.25203937292099, -0.05397806316614151, -0.056443288922309875, 0.3141666650772095, 0.2753794491291046, 0.003758730599656701, 0.3996680974960327, -0.08816654235124588, 0.18743528425693512, 0.08752727508544922, -0.0066700526513159275, 0.024904023855924606, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2327851504087448, -0.036927480250597, -0.060271006077528, 0.12743708491325378, -0.26138290762901306, -0.44759511947631836, -0.12288530170917511, 0.19485774636268616, 0.3110850751399994, 0.26668691635131836, 0.22457055747509003, 0.12855187058448792, 0.0683443546295166, -0.2906014621257782, -0.6290041208267212, 0.3359372615814209, 0.10759533941745758, 0.6360295414924622, 0.3969813585281372, -0.6107851266860962, 0.17808949947357178, 0.13989639282226562, 0.4025574028491974, 0.09777355939149857, 0.15318778157234192, 0.12956105172634125, -0.2998013496398926, 0.011568127200007439, 0.6895459890365601, 0.2852321267127991, -0.3116857409477234, -0.42502737045288086, 0.3081018924713135, -0.11402148008346558, 1.381977915763855, 3.0184528827667236]], "betas": [[0.4588857591152191, 2.0385794639587402, 0.007286209147423506, 0.005293494556099176, 0.00016343241441063583, 0.002143820282071829, 0.0015500654699280858, 0.0005173357203602791, 0.0006261101807467639, 0.0009983122581616044]], "transl": [[0.07826796919107437, 0.17196351289749146, 0.011826117523014545]], "joints3d": [[[-397.4902038574219, 73.14258575439453, 4672.51708984375], [-367.2608642578125, 178.76580810546875, 4663.03125], [-477.6297607421875, 140.5206298828125, 4698.13134765625], [-360.0849609375, -27.088912963867188, 4694.2978515625], [-533.1669921875, 550.7620849609375, 4670.9287109375], [-685.2261962890625, 497.4150085449219, 4729.5390625], [-335.7276916503906, -154.70004272460938, 4632.3857421875], [-737.5258178710938, 896.6875610351562, 4816.94921875], [-848.8657836914062, 882.7413940429688, 4812.44140625], [-326.0096740722656, -204.53167724609375, 4605.57568359375], [-785.2074584960938, 1001.6276245117188, 4738.7353515625], [-924.0380249023438, 968.087646484375, 4731.828125], [-267.4469299316406, -409.2958679199219, 4583.91845703125], [-221.09487915039062, -296.944091796875, 4578.30419921875], [-353.3477783203125, -340.8865966796875, 4636.02392578125], [-253.13787841796875, -479.405517578125, 4528.5087890625], [-151.7763214111328, -256.9538269042969, 4531.14599609375], [-443.54901123046875, -374.2353210449219, 4659.8193359375], [-148.44400024414062, 17.59290313720703, 4506.80712890625], [-637.0234985351562, -205.34417724609375, 4731.76806640625], [-257.5285339355469, 200.1862335205078, 4353.23681640625], [-814.7245483398438, -6.18148136138916, 4692.76611328125]]]}, {"global_orient": [[3.060441017150879, 0.5171935558319092, -0.5412401556968689]], "body_pose": [[3.060441017150879, 0.5171935558319092, -0.5412401556968689, -0.09446057677268982, -0.017012283205986023, -0.15755875408649445, -0.0363401435315609, -0.07261395454406738, -0.10959263890981674, 0.3637220561504364, 0.0018432574579492211, 0.03257814049720764, 0.17473584413528442, -0.11497699469327927, -0.1112600713968277, 0.07878376543521881, 0.20654211938381195, -0.03382641822099686, -0.26638564467430115, -0.02660219930112362, -0.043392620980739594, 0.4012047350406647, 0.27698051929473877, 0.009179086424410343, 0.5140138864517212, -0.09518483281135559, 0.17898662388324738, 0.12179508805274963, 0.017794398590922356, 0.022543497383594513, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2045721560716629, -0.004325761925429106, -0.04707788676023483, 0.06552384048700333, -0.2440468668937683, -0.4420834481716156, -0.12046916782855988, 0.24260108172893524, 0.294482946395874, 0.21420125663280487, 0.21179033815860748, 0.0943453460931778, 0.057201653718948364, -0.23130439221858978, -0.6115363240242004, 0.2577025592327118, 0.15303759276866913, 0.6363582015037537, 0.27580317854881287, -0.5492212176322937, 0.25533851981163025, 0.0796060562133789, 0.5756291747093201, -0.025593267753720284, 0.4049127995967865, 0.36185458302497864, -0.44913479685783386, -0.04077355936169624, 0.2830272316932678, 0.7524396777153015, -0.5787934064865112, -0.7886601090431213, -0.060203444212675095, -0.4520726203918457, 0.9795562028884888, 3.4259145259857178]], "betas": [[0.5627496242523193, 1.4654498100280762, 0.007755397353321314, 0.004559986758977175, -6.048505747457966e-05, 0.0017220316221937537, 0.0015150082763284445, 0.00012740661622956395, 0.00045881030382588506, 0.0010881967609748244]], "transl": [[0.07065844535827637, 0.18083791434764862, 0.015842106193304062]], "joints3d": [[[-396.2932434082031, 76.34918975830078, 4716.390625], [-364.678466796875, 184.03973388671875, 4711.22998046875], [-477.18548583984375, 142.1590118408203, 4751.48046875], [-356.6495056152344, -27.40324592590332, 4730.62548828125], [-524.7318725585938, 554.4298095703125, 4707.76025390625], [-685.29248046875, 492.6476745605469, 4802.55029296875], [-331.7864074707031, -154.07713317871094, 4667.95458984375], [-726.2681274414062, 902.3677368164062, 4848.93212890625], [-841.6488647460938, 875.505859375, 4904.08251953125], [-322.56536865234375, -204.52252197265625, 4639.615234375], [-772.5413818359375, 1013.5126342773438, 4777.86376953125], [-927.2842407226562, 969.2063598632812, 4844.5234375], [-264.2950744628906, -412.4626770019531, 4612.64697265625], [-215.24810791015625, -298.9350891113281, 4609.076171875], [-353.02325439453125, -344.9172668457031, 4666.40380859375], [-251.92495727539062, -478.2871398925781, 4553.50830078125], [-141.45294189453125, -257.40643310546875, 4565.44384765625], [-446.9064025878906, -378.6893615722656, 4685.07666015625], [-122.13858795166016, 16.39573860168457, 4546.01611328125], [-645.73388671875, -208.60740661621094, 4737.72412109375], [-178.48423767089844, 205.67568969726562, 4372.88720703125], [-821.3695678710938, -37.55018997192383, 4625.85693359375]]]}, {"global_orient": [[2.9769375324249268, 0.4682319462299347, -0.32754480838775635], [3.274489402770996, 0.16556048393249512, 0.8593395352363586]], "body_pose": [[2.9769375324249268, 0.4682319462299347, -0.32754480838775635, 0.03675023838877678, -0.005112271290272474, -0.1691255420446396, 0.04853228107094765, -0.07723493129014969, -0.09482274204492569, 0.45042645931243896, -0.012189887464046478, 0.039380814880132675, 0.0481976680457592, -0.14940115809440613, -0.05409407615661621, -0.016851358115673065, 0.21080702543258667, -0.03921191021800041, -0.2652420997619629, -0.05873120203614235, -0.0630156472325325, 0.41768279671669006, 0.28264036774635315, -0.01623949036002159, 0.5159899592399597, -0.19358401000499725, 0.2250247448682785, 0.10044802725315094, 0.016000131145119667, 0.04753511771559715, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.24663706123828888, -0.026987148448824883, -0.08171030133962631, 0.1489657312631607, -0.21545729041099548, -0.3782842457294464, -0.10236214846372604, 0.15441136062145233, 0.18833020329475403, 0.26147398352622986, 0.27603834867477417, 0.09569837152957916, 0.05190270394086838, -0.19999679923057556, -0.5987581014633179, 0.30201098322868347, 0.06938429921865463, 0.6861253976821899, 0.4142952859401703, -0.6115599870681763, 0.12630611658096313, 0.17465484142303467, 0.5789770483970642, 0.015752768144011497, 0.340753436088562, 0.3059609532356262, -0.4981967806816101, -0.08007065951824188, -0.03553525730967522, 1.6133012771606445, -0.42487913370132446, -0.6978374719619751, 0.2604108154773712, -0.21931715309619904, -0.6961773633956909, 3.791478157043457], [3.274489402770996, 0.16556048393249512, 0.8593395352363586, -0.3880954086780548, 0.15197007358074188, 0.25515636801719666, -0.3897390067577362, -0.05827430263161659, -0.16304631531238556, 0.5067726373672485, -0.07044663280248642, 0.08959199488162994, 0.6079704761505127, -0.11623825877904892, -0.1171765923500061, 0.6611600518226624, -0.11909524351358414, 0.3402329087257385, -0.5736173391342163, 0.03465447947382927, -0.0044188471511006355, -0.15066610276699066, 0.13764561712741852, -0.29141801595687866, 0.036657318472862244, -0.15842455625534058, -0.09128638356924057, 0.503032386302948, 0.014178147539496422, -0.05043741688132286, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.004982387647032738, -0.12808355689048767, -0.11369313299655914, -0.1934514343738556, -0.3621729612350464, -0.28797516226768494, -0.3710247874259949, 0.5376434326171875, 0.309714674949646, -0.18178513646125793, 0.01496722549200058, 0.1260165274143219, 0.2246844619512558, -0.37172213196754456, -0.8062009811401367, 0.25965821743011475, 0.30586448311805725, 0.6837471723556519, 0.584872305393219, -1.560555100440979, 0.033110834658145905, 0.44267308712005615, 1.4796429872512817, 0.19157260656356812, -0.06848116964101791, -0.42049071192741394, 0.4851393401622772, 0.4718903601169586, 0.5665730237960815, -0.2222082018852234, -1.0362763404846191, -0.30913999676704407, -1.3595845699310303, -1.0476073026657104, 0.2787812352180481, 0.9448012113571167]], "betas": [[0.41743940114974976, 1.9624171257019043, 0.010089158080518246, 0.0069275167770683765, 0.0008213541004806757, 0.002823531860485673, 0.0016476460732519627, 0.00021579861640930176, 0.0008463615668006241, 0.0010753873502835631], [-2.201188564300537, -0.15792329609394073, -0.005490835290402174, 0.007806380745023489, 0.0007984918192960322, 0.0007026800303719938, 0.0011140386341139674, 0.0033459288533777, -0.0009046286577358842, 0.002782961819320917]], "transl": [[0.06452270597219467, 0.17253907024860382, 0.01802031882107258], [-0.044489890336990356, 0.15515831112861633, 0.04361741617321968]], "joints3d": [[[-406.19708251953125, 70.21966552734375, 4785.09423828125], [-374.2276611328125, 175.49464416503906, 4776.43701171875], [-487.9493713378906, 138.36505126953125, 4802.8125], [-371.5158386230469, -29.77459716796875, 4811.50537109375], [-522.9917602539062, 552.7590942382812, 4763.7568359375], [-686.653076171875, 499.4163818359375, 4818.845703125], [-344.6295471191406, -158.3074493408203, 4753.8955078125], [-727.4169921875, 919.68603515625, 4833.71435546875], [-848.11083984375, 891.3651733398438, 4850.99951171875], [-333.25494384765625, -208.69639587402344, 4728.94482421875], [-760.07861328125, 1024.2144775390625, 4748.2607421875], [-925.4061889648438, 976.9545288085938, 4773.384765625], [-279.54541015625, -415.4224853515625, 4716.34033203125], [-229.2890167236328, -304.80255126953125, 4712.81201171875], [-367.63360595703125, -343.59307861328125, 4759.08935546875], [-260.453857421875, -486.3582763671875, 4664.1357421875], [-151.09793090820312, -274.05291748046875, 4673.25048828125], [-455.7466125488281, -385.09783935546875, 4776.771484375], [-93.06280517578125, -5.988197326660156, 4657.55126953125], [-656.7537841796875, -226.7187042236328, 4848.94921875], [-147.66357421875, 198.3262481689453, 4503.85595703125], [-836.53515625, -47.20361328125, 4761.1376953125]], [[-4042.43896484375, -2635.365966796875, 12118.9091796875], [-4000.02392578125, -2555.672119140625, 12178.3525390625], [-4115.49072265625, -2559.238525390625, 12108.4951171875], [-4037.447265625, -2728.662353515625, 12111.3193359375], [-3896.886474609375, -2243.221923828125, 12207.82421875], [-4183.71875, -2239.598876953125, 12033.17578125], [-4004.972900390625, -2814.026611328125, 12039.69140625], [-3982.933349609375, -1963.17822265625, 12381.2392578125], [-4202.83544921875, -1970.1995849609375, 12239.6845703125], [-3988.103271484375, -2851.312255859375, 12008.2939453125], [-3917.353271484375, -1880.873291015625, 12332.021484375], [-4209.69384765625, -1879.375244140625, 12169.56640625], [-3949.697998046875, -3030.51220703125, 11937.177734375], [-3907.284423828125, -2955.9794921875, 12004.5205078125], [-4031.697265625, -2960.300537109375, 11945.1787109375], [-3913.69091796875, -3044.123291015625, 11874.6396484375], [-3826.24072265625, -2948.2763671875, 12023.30859375], [-4092.107666015625, -2949.328857421875, 11884.3974609375], [-3786.427978515625, -2735.313232421875, 12091.771484375], [-4147.00390625, -2739.16796875, 11840.9296875], [-3903.3505859375, -2675.379638671875, 11925.689453125], [-3939.3564453125, -2670.91796875, 11860.056640625]]]}, {"global_orient": [[2.991042375564575, 0.4498838782310486, -0.29382678866386414], [3.3038103580474854, 0.23969914019107819, 0.6160356998443604]], "body_pose": [[2.991042375564575, 0.4498838782310486, -0.29382678866386414, 0.008690069429576397, 0.007805480621755123, -0.1535136103630066, 0.05000973865389824, -0.07059308141469955, -0.09566013514995575, 0.4291665256023407, -0.01505997497588396, 0.022804198786616325, 0.05764300376176834, -0.09294340014457703, -0.0648844838142395, -0.01711495779454708, 0.2230541706085205, -0.05593987554311752, -0.26280051469802856, -0.05456123501062393, -0.060549329966306686, 0.339843213558197, 0.30235448479652405, 0.022980675101280212, 0.4419652223587036, -0.19984003901481628, 0.24678650498390198, 0.10125073045492172, 0.004297156352549791, 0.037775542587041855, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2523192763328552, -0.022855358198285103, -0.04383152350783348, 0.1655677706003189, -0.1732219159603119, -0.3104568421840668, -0.10968144983053207, 0.1339310258626938, 0.12288971245288849, 0.31459999084472656, 0.23993489146232605, 0.06450439244508743, 0.030571535229682922, -0.24335701763629913, -0.5967059135437012, 0.33060112595558167, 0.150059774518013, 0.7688924074172974, 0.432363897562027, -0.6415802240371704, 0.177891343832016, 0.3658631145954132, 0.9687492251396179, -0.13680171966552734, 0.3436276316642761, 0.23571614921092987, -0.598875105381012, 0.08468985557556152, -0.04581189155578613, 0.6221702694892883, -0.3388034701347351, -0.5629852414131165, 0.3519933819770813, -1.313514232635498, 1.1727392673492432, 2.7117059230804443], [3.3038103580474854, 0.23969914019107819, 0.6160356998443604, -0.3794551193714142, 0.11583174765110016, 0.2543347477912903, -0.4052298069000244, -0.10590344667434692, -0.20477889478206635, 0.48695313930511475, -0.07063616067171097, 0.09580781310796738, 0.6129587888717651, -0.0810704231262207, -0.1365724503993988, 0.693822979927063, -0.18833261728286743, 0.32379138469696045, -0.5411099791526794, 0.005724587477743626, -0.036936841905117035, -0.1823335886001587, 0.2236696183681488, -0.29686540365219116, 0.08143116533756256, -0.027565129101276398, -0.0720367580652237, 0.5160870552062988, -0.00848450418561697, -0.0026068377774208784, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.10668941587209702, -0.10262757539749146, -0.18991275131702423, -0.25944632291793823, -0.43001487851142883, -0.34147909283638, -0.36843180656433105, 0.5366822481155396, 0.3314998149871826, -0.28947001695632935, 0.09338197857141495, 0.14837093651294708, 0.2551284432411194, -0.3403475880622864, -0.6937777400016785, 0.2741788327693939, 0.34046101570129395, 0.6945893168449402, 0.42360398173332214, -1.6027406454086304, 0.07759424299001694, 0.43910616636276245, 1.5150816440582275, 0.06372169405221939, 0.10938891768455505, -0.22693540155887604, 0.5570859313011169, 0.4316578507423401, 0.5468164086341858, -0.2607964873313904, -0.8367286324501038, -0.2908303141593933, -1.0469982624053955, -0.6794689297676086, 0.3211562931537628, 1.0184032917022705]], "betas": [[0.6095623970031738, 2.0410397052764893, 0.009100798517465591, 0.006748741492629051, 0.000913956027943641, 0.002692457055673003, 0.0013553767930716276, 3.211828152416274e-05, 0.0008288356475532055, 0.0005927199381403625], [-1.9752461910247803, -0.25156369805336, -0.004995314870029688, 0.0061988551169633865, -0.00015216550673358142, 0.00015726631681900471, 0.0016152217285707593, 0.00266519864089787, -0.001128485193476081, 0.0028463827911764383]], "transl": [[0.05562140792608261, 0.17687122523784637, 0.029718389734625816], [-0.03228355944156647, 0.15758445858955383, 0.05727440118789673]], "joints3d": [[[-419.907470703125, 75.8165283203125, 4841.84814453125], [-386.77862548828125, 181.30714416503906, 4834.94189453125], [-501.18560791015625, 145.4482421875, 4858.466796875], [-386.63458251953125, -26.02515983581543, 4868.71630859375], [-527.8517456054688, 565.952392578125, 4809.65869140625], [-698.5565795898438, 512.842041015625, 4874.11865234375], [-356.7249755859375, -156.14527893066406, 4811.52587890625], [-735.860107421875, 939.1467895507812, 4870.3203125], [-865.0616455078125, 908.7431640625, 4908.55322265625], [-344.14544677734375, -207.3774871826172, 4787.44580078125], [-751.7180786132812, 1041.789306640625, 4775.6455078125], [-939.2024536132812, 990.903076171875, 4821.56103515625], [-287.16278076171875, -415.04010009765625, 4775.03955078125], [-237.6952362060547, -302.7350769042969, 4772.8505859375], [-377.72991943359375, -343.7543640136719, 4817.0556640625], [-267.7549133300781, -488.0929870605469, 4724.11376953125], [-155.4376220703125, -276.7275085449219, 4736.056640625], [-463.3483581542969, -392.8221130371094, 4834.177734375], [-86.6838150024414, -8.577211380004883, 4711.08544921875], [-668.780517578125, -229.39913940429688, 4892.79443359375], [-130.01043701171875, 184.22512817382812, 4534.685546875], [-779.8846435546875, -67.63832092285156, 4704.18359375]], [[-3957.33056640625, -2667.6552734375, 12390.240234375], [-3911.3662109375, -2582.16796875, 12440.171875], [-4035.8017578125, -2594.80859375, 12386.5380859375], [-3948.431640625, -2763.14892578125, 12386.7099609375], [-3823.81884765625, -2259.876220703125, 12443.3212890625], [-4146.2001953125, -2285.388916015625, 12301.2646484375], [-3921.544677734375, -2852.5869140625, 12314.9169921875], [-3908.7939453125, -1974.7677001953125, 12619.6591796875], [-4148.951171875, -2000.333740234375, 12496.53125], [-3906.0, -2890.70263671875, 12282.3642578125], [-3847.354736328125, -1891.6142578125, 12562.8486328125], [-4170.728515625, -1908.9739990234375, 12426.8564453125], [-3869.244873046875, -3070.783935546875, 12205.3720703125], [-3818.73291015625, -2991.4267578125, 12263.8740234375], [-3954.580810546875, -3005.111328125, 12228.4892578125], [-3840.518798828125, -3074.535888671875, 12137.154296875], [-3735.82958984375, -2971.951904296875, 12265.677734375], [-4027.89990234375, -2997.1142578125, 12179.9443359375], [-3684.741455078125, -2750.53564453125, 12303.3203125], [-4096.42138671875, -2785.677978515625, 12146.96875], [-3825.247802734375, -2719.964111328125, 12143.0068359375], [-3886.12109375, -2720.604736328125, 12112.998046875]]]}, {"global_orient": [[2.950026035308838, 0.4348798394203186, -0.2784932255744934], [3.173024892807007, 0.0436704084277153, 0.9122112989425659]], "body_pose": [[2.950026035308838, 0.4348798394203186, -0.2784932255744934, 0.06459914147853851, 0.005444172769784927, -0.15189921855926514, 0.07821499556303024, -0.073972687125206, -0.09298702329397202, 0.4682815670967102, -0.007498929742723703, 0.016907954588532448, 0.052471429109573364, -0.07633055746555328, -0.07259408384561539, -0.022129764780402184, 0.276899129152298, -0.055831294506788254, -0.2800474464893341, -0.04976115748286247, -0.05893527343869209, 0.2848377227783203, 0.40537792444229126, 0.008995314128696918, 0.41999608278274536, -0.25463050603866577, 0.2651170492172241, 0.10236828774213791, 0.004852130077779293, 0.03458051756024361, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.22677774727344513, 0.018283341079950333, -0.06307128071784973, 0.18887512385845184, -0.15574324131011963, -0.2955024838447571, -0.09282845258712769, 0.11107900738716125, 0.1378743052482605, 0.3193870484828949, 0.2548312842845917, 0.11066089570522308, 0.0488082580268383, -0.2357224076986313, -0.5954880118370056, 0.35123902559280396, 0.1570916473865509, 0.7882919907569885, 0.4654618501663208, -0.7089591026306152, 0.10088375955820084, 0.33617451786994934, 1.025063395500183, -0.0942983403801918, 0.32570284605026245, 0.20592805743217468, -0.5776736736297607, 0.04876820370554924, 0.13494668900966644, 0.48914921283721924, -0.3761535882949829, -0.5514068007469177, 0.423099547624588, -1.2489591836929321, 1.1768401861190796, 2.4863805770874023], [3.173024892807007, 0.0436704084277153, 0.9122112989425659, -0.37405893206596375, 0.11958546191453934, 0.17684753239154816, -0.37096914649009705, -0.013646858744323254, -0.1505584567785263, 0.5389522910118103, -0.0371888242661953, 0.004073077347129583, 0.6332069039344788, -0.1110563650727272, -0.23482799530029297, 0.6334059834480286, -0.0408577099442482, 0.2624579966068268, -0.6184198260307312, 0.06397077441215515, 0.040884505957365036, -0.35108962655067444, 0.08647061139345169, -0.01562083326280117, -0.1007135808467865, -0.2106701135635376, -0.23756948113441467, 0.5808313488960266, -0.0540664903819561, -0.1109420657157898, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.033447183668613434, -0.10507507622241974, -0.09929165244102478, -0.22330226004123688, -0.377509742975235, -0.204405277967453, -0.48582181334495544, 0.7142041921615601, 0.40030530095100403, -0.1323530375957489, 0.0008160206489264965, 0.18922048807144165, 0.31015825271606445, -0.23371951282024384, -0.6814910173416138, 0.35536351799964905, 0.19901087880134583, 0.705761730670929, 0.1857718825340271, -1.3927407264709473, -0.1662168949842453, 0.30289870500564575, 1.4979580640792847, 0.021634675562381744, 0.04752054437994957, -0.6213659048080444, 0.9072535037994385, 0.3117678165435791, 0.33737578988075256, -0.3582639694213867, -1.3503504991531372, 0.1079091876745224, -1.470251441001892, -1.0020170211791992, 0.19516722857952118, 0.8062422871589661]], "betas": [[0.420788049697876, 2.178650379180908, 0.008346346206963062, 0.007299418561160564, 0.0010747751221060753, 0.0028283866122365, 0.0013423701748251915, 0.0003602842625696212, 0.0008431936148554087, 0.0005942912539467216], [-2.5372822284698486, -0.5488556623458862, -0.00544166611507535, 0.008950167335569859, 0.0016454190481454134, 0.0007461155182681978, 0.0011818255297839642, 0.002249217825010419, -0.0007393184350803494, 0.0025566068943589926]], "transl": [[0.051161929965019226, 0.1707652509212494, 0.028513409197330475], [-0.06385903805494308, 0.16065217554569244, 0.04138970375061035]], "joints3d": [[[-427.8150939941406, 78.12837982177734, 4799.91650390625], [-394.6537170410156, 182.24960327148438, 4789.91943359375], [-508.1552734375, 147.90028381347656, 4812.986328125], [-395.89300537109375, -21.114774703979492, 4829.64599609375], [-529.5814819335938, 566.753662109375, 4768.19482421875], [-700.5880737304688, 515.0382080078125, 4820.77392578125], [-366.4319763183594, -150.35427856445312, 4773.5869140625], [-733.902587890625, 937.0000610351562, 4830.5947265625], [-863.5250244140625, 908.5730590820312, 4845.12109375], [-353.6462707519531, -201.19381713867188, 4750.98486328125], [-737.4547119140625, 1039.7733154296875, 4736.9755859375], [-934.3713989257812, 987.4473876953125, 4755.08544921875], [-297.1534118652344, -406.51080322265625, 4743.564453125], [-248.7772674560547, -295.54559326171875, 4740.7314453125], [-386.8725891113281, -335.0633544921875, 4781.8544921875], [-274.575927734375, -477.864013671875, 4692.26611328125], [-166.51670837402344, -272.40570068359375, 4706.0107421875], [-471.3917236328125, -382.2638854980469, 4799.42041015625], [-88.77693939208984, -8.743680953979492, 4686.732421875], [-668.5007934570312, -212.83651733398438, 4858.12841796875], [-148.35687255859375, 187.84146118164062, 4524.02001953125], [-757.4584350585938, -45.1485595703125, 4666.68115234375]], [[-3835.779296875, -2615.423828125, 12282.9150390625], [-3786.61376953125, -2537.00244140625, 12339.078125], [-3901.13623046875, -2534.015380859375, 12262.958984375], [-3839.729736328125, -2707.49755859375, 12281.8291015625], [-3683.340576171875, -2234.67138671875, 12341.2646484375], [-3930.140625, -2222.775146484375, 12176.2275390625], [-3804.69384765625, -2796.374755859375, 12222.5947265625], [-3795.935791015625, -1953.1331787109375, 12468.00390625], [-3967.873046875, -1945.178466796875, 12347.365234375], [-3787.288818359375, -2836.17529296875, 12195.3291015625], [-3722.05322265625, -1897.4383544921875, 12402.775390625], [-3963.0537109375, -1878.52490234375, 12257.6953125], [-3743.24560546875, -3018.4287109375, 12140.8486328125], [-3706.201904296875, -2939.48486328125, 12204.533203125], [-3824.815185546875, -2949.1435546875, 12136.451171875], [-3704.07080078125, -3035.54736328125, 12084.1494140625], [-3626.23486328125, -2935.594970703125, 12225.302734375], [-3871.867431640625, -2931.710205078125, 12067.6328125], [-3547.818603515625, -2746.938232421875, 12308.8125], [-3902.347900390625, -2723.986083984375, 12018.8193359375], [-3615.335205078125, -2634.3671875, 12151.234375], [-3693.189697265625, -2688.14306640625, 12032.9619140625]]]}, {"global_orient": [[2.9675958156585693, 0.43155720829963684, -0.21066352725028992], [3.2308883666992188, 0.042159851640462875, 0.9532776474952698]], "body_pose": [[2.9675958156585693, 0.43155720829963684, -0.21066352725028992, 0.1102602556347847, -0.003942093811929226, -0.1515202820301056, 0.06756512075662613, -0.05590321868658066, -0.08593782037496567, 0.46144169569015503, -0.02265806682407856, 0.01622031256556511, 0.03734639659523964, -0.09412191808223724, -0.04782825708389282, -0.024647453799843788, 0.25033870339393616, -0.06448975205421448, -0.2999197542667389, -0.05698862299323082, -0.05416995286941528, 0.2552556097507477, 0.356319785118103, 0.014945019967854023, 0.44733282923698425, -0.20944948494434357, 0.26720014214515686, 0.10341764241456985, -0.0014985711313784122, 0.03536676988005638, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2157796174287796, 0.02804088220000267, -0.07473175972700119, 0.16561517119407654, -0.13195429742336273, -0.27225345373153687, -0.09517540037631989, 0.06656662374734879, 0.11993078142404556, 0.29457736015319824, 0.2662678062915802, 0.11330211162567139, 0.09422970563173294, -0.2451406717300415, -0.694182813167572, 0.3808167576789856, 0.10643091797828674, 0.8692842125892639, 0.49558717012405396, -0.6734598278999329, 0.06703832745552063, 0.47095224261283875, 1.0618257522583008, -0.16098134219646454, 0.3136657774448395, 0.173672616481781, -0.5766174793243408, 0.08020596951246262, 0.0985216274857521, 0.42495277523994446, -0.4748784303665161, -0.6662088632583618, 0.3278011083602905, -1.2398790121078491, 1.135573387145996, 1.5510540008544922], [3.2308883666992188, 0.042159851640462875, 0.9532776474952698, -0.31939688324928284, 0.11224737763404846, 0.1551925241947174, -0.37443429231643677, -0.014398247934877872, -0.13920368254184723, 0.46200400590896606, -0.06474429368972778, -0.0005794972530566156, 0.5463830828666687, -0.14990933239459991, -0.17238183319568634, 0.6012651324272156, -0.06537161767482758, 0.2365073412656784, -0.5561578273773193, 0.07159216701984406, 0.03472109138965607, -0.2994280755519867, 0.15080150961875916, -0.09177319705486298, -0.062349703162908554, -0.22012007236480713, -0.13332460820674896, 0.511733889579773, -0.08866997063159943, -0.1227344423532486, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.020003680139780045, -0.08844446390867233, -0.07178980857133865, -0.1951969563961029, -0.39456456899642944, -0.19339101016521454, -0.46261733770370483, 0.6869688630104065, 0.44203415513038635, -0.15050575137138367, -0.0754794105887413, 0.17178742587566376, 0.27166876196861267, -0.26740214228630066, -0.7978355884552002, 0.3633459508419037, 0.23959259688854218, 0.7451155781745911, 0.03031294047832489, -1.3275586366653442, -0.11760251969099045, 0.37172895669937134, 1.541334867477417, -0.05576026067137718, 0.4736816883087158, -0.7437950372695923, 1.4748939275741577, 0.183990016579628, 0.3411523103713989, -0.2755659222602844, 1.4028300046920776, -0.702400803565979, 2.4577882289886475, -1.1842304468154907, 0.22254213690757751, 1.0748831033706665]], "betas": [[0.40457743406295776, 2.051837921142578, 0.008454660885035992, 0.007808789145201445, 0.0010858399327844381, 0.0029835309833288193, 0.0014687585644423962, 0.00021266381372697651, 0.0008735538576729596, 0.0005560601130127907], [-2.008678436279297, -0.29851529002189636, -0.00299542467109859, 0.0058624399825930595, -0.00016650330508127809, 0.0005124906310811639, 0.0016882685013115406, 0.0018903763266280293, -0.0008335291058756411, 0.002476937137544155]], "transl": [[0.04804789274930954, 0.16886726021766663, 0.018332554027438164], [-0.06141531839966774, 0.16311080753803253, 0.03284657746553421]], "joints3d": [[[-444.0168762207031, 83.94020080566406, 4829.45703125], [-409.9595031738281, 188.34042358398438, 4822.30517578125], [-525.33251953125, 153.5661163330078, 4839.861328125], [-413.4029846191406, -15.949368476867676, 4859.3984375], [-540.1301879882812, 573.32763671875, 4820.2216796875], [-715.18408203125, 520.3519287109375, 4840.09912109375], [-381.95733642578125, -144.43409729003906, 4803.7861328125], [-732.9725952148438, 946.5680541992188, 4891.44287109375], [-879.7784423828125, 912.1419677734375, 4858.2998046875], [-368.43609619140625, -195.52040100097656, 4781.904296875], [-735.7669067382812, 1047.4730224609375, 4796.09375], [-943.1461791992188, 994.956787109375, 4766.51708984375], [-310.86492919921875, -401.0320739746094, 4779.5654296875], [-262.5798034667969, -289.8746643066406, 4775.63232421875], [-402.1610107421875, -329.4518127441406, 4814.33837890625], [-286.2771301269531, -471.7064208984375, 4728.99658203125], [-177.91802978515625, -269.26898193359375, 4744.51318359375], [-485.3687438964844, -378.3110046386719, 4834.81201171875], [-114.7056884765625, -1.892953872680664, 4736.921875], [-668.7574462890625, -200.81304931640625, 4909.4658203125], [-181.19126892089844, 205.1038360595703, 4591.703125], [-752.1710205078125, -28.651655197143555, 4720.484375]], [[-3782.923583984375, -2626.316162109375, 12456.7275390625], [-3736.47021484375, -2549.283447265625, 12518.638671875], [-3849.302734375, -2543.406494140625, 12442.19140625], [-3785.907470703125, -2721.8837890625, 12450.0419921875], [-3647.489013671875, -2230.427001953125, 12553.037109375], [-3880.835205078125, -2213.92578125, 12372.515625], [-3749.478759765625, -2814.492431640625, 12387.7216796875], [-3751.548583984375, -1940.49267578125, 12707.5107421875], [-3921.46826171875, -1927.513916015625, 12559.2568359375], [-3731.941162109375, -2854.927490234375, 12359.26171875], [-3674.6123046875, -1874.386474609375, 12647.8740234375], [-3918.7412109375, -1849.5545654296875, 12472.5546875], [-3684.89501953125, -3040.16015625, 12303.1591796875], [-3646.786376953125, -2958.726806640625, 12367.7275390625], [-3770.563720703125, -2971.114990234375, 12301.2978515625], [-3645.565185546875, -3056.041748046875, 12242.7041015625], [-3563.693115234375, -2952.523681640625, 12385.1025390625], [-3822.6904296875, -2952.10205078125, 12232.7451171875], [-3508.468017578125, -2743.107421875, 12461.4873046875], [-3849.990966796875, -2733.10009765625, 12193.962890625], [-3565.09619140625, -2633.2509765625, 12285.9736328125], [-3629.3603515625, -2710.50927734375, 12204.6513671875]]]}, {"global_orient": [[2.962327241897583, 0.42420825362205505, -0.17887726426124573], [3.223524570465088, 0.0035339933820068836, 1.0611284971237183]], "body_pose": [[2.962327241897583, 0.42420825362205505, -0.17887726426124573, 0.08083612471818924, -0.02065996266901493, -0.13319358229637146, 0.06818091869354248, -0.0472499243915081, -0.09584865719079971, 0.45509761571884155, -0.01123405247926712, 0.015691466629505157, 0.1081438884139061, -0.03866059333086014, -0.06949354708194733, -0.011717116460204124, 0.23767834901809692, -0.06727343797683716, -0.28781306743621826, -0.05252622812986374, -0.045955248177051544, 0.08376374840736389, 0.351893812417984, 0.061169493943452835, 0.3596127927303314, -0.2634582817554474, 0.2990625500679016, 0.12196315824985504, 0.007273558061569929, 0.022828638553619385, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.22783930599689484, 0.03283171355724335, -0.09367502480745316, 0.14343804121017456, -0.15215159952640533, -0.3073345124721527, -0.07906705141067505, 0.09985928982496262, 0.21591690182685852, 0.29198113083839417, 0.26205411553382874, 0.12320539355278015, 0.15271878242492676, -0.23939618468284607, -0.6615680456161499, 0.3684251606464386, 0.1210784912109375, 0.8353888392448425, 0.4639225900173187, -0.7815909385681152, 0.007795856799930334, 0.38259974122047424, 1.0141037702560425, -0.14009509980678558, 0.3503308892250061, 0.17721369862556458, -0.3998626172542572, 0.22242017090320587, 0.270346999168396, -0.058101583272218704, -0.5109325051307678, -0.5415725708007812, 0.09964552521705627, -0.8864059448242188, 0.329689085483551, 1.5534284114837646], [3.223524570465088, 0.0035339933820068836, 1.0611284971237183, -0.2942809462547302, 0.05003608390688896, 0.1100136861205101, -0.3503231406211853, -0.06551875919103622, -0.2282327562570572, 0.42502638697624207, -0.08070070296525955, -0.02087240479886532, 0.5262786746025085, -0.0834338366985321, -0.11360358446836472, 0.6439869403839111, -0.10677677392959595, 0.27150896191596985, -0.5164403319358826, 0.0805741399526596, 0.040898632258176804, -0.3378744423389435, 0.0974821075797081, -0.2712203860282898, -0.10020368546247482, -0.16827233135700226, -0.021451205015182495, 0.5298551917076111, -0.08940179646015167, -0.12649254500865936, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.12244727462530136, -0.14912022650241852, -0.02025349624454975, -0.2380972057580948, -0.41153544187545776, -0.18877100944519043, -0.5659566521644592, 0.6705980896949768, 0.41595467925071716, -0.08183591067790985, -0.03232824057340622, 0.15097038447856903, 0.29536816477775574, -0.14170131087303162, -0.7220588326454163, 0.4211898744106293, 0.2750885486602783, 0.7749241590499878, -0.06892363727092743, -1.3273086547851562, 0.009686272591352463, 0.15571007132530212, 1.4833821058273315, -0.06676437705755234, 0.07849699258804321, -0.7529239058494568, 1.0772621631622314, 0.19515052437782288, 0.3858683109283447, -0.3227424919605255, 1.5557348728179932, -0.7940150499343872, 2.7835307121276855, -1.0268712043762207, 0.12082333117723465, 1.148280143737793]], "betas": [[0.16604085266590118, 1.9712954759597778, 0.006030424498021603, 0.007747259922325611, 0.0013301224680617452, 0.0026612214278429747, 0.0011087594320997596, 0.0007552712922915816, 0.0010604759445413947, 0.0005731817218475044], [-1.6103700399398804, -0.29666784405708313, -0.0034440297167748213, 0.005720219574868679, 0.0013816773425787687, 0.0002567593182902783, 0.0017451882595196366, 0.001954031176865101, -0.00032809574622660875, 0.0028983857482671738]], "transl": [[0.04658763110637665, 0.16608351469039917, 0.022182000800967216], [-0.0647541880607605, 0.17087653279304504, 0.03126465156674385]], "joints3d": [[[-460.3253173828125, 91.40522766113281, 4840.294921875], [-425.4812316894531, 194.9515380859375, 4833.48095703125], [-541.5695190429688, 160.5082244873047, 4848.56298828125], [-431.1385803222656, -6.949207305908203, 4870.38916015625], [-547.7616577148438, 576.03955078125, 4814.091796875], [-731.1626586914062, 520.6890258789062, 4843.2109375], [-398.7433776855469, -134.1718292236328, 4818.34375], [-735.58251953125, 941.7704467773438, 4895.57666015625], [-896.9684448242188, 904.2943725585938, 4861.96484375], [-385.4117126464844, -184.4012908935547, 4796.42822265625], [-724.42822265625, 1029.8829345703125, 4791.466796875], [-959.911376953125, 977.3798828125, 4765.02978515625], [-328.96148681640625, -387.8975830078125, 4792.9990234375], [-280.978271484375, -278.1839599609375, 4792.630859375], [-420.16748046875, -317.4643249511719, 4824.73876953125], [-301.6614074707031, -456.3271484375, 4742.90625], [-197.2458038330078, -254.7156982421875, 4764.703125], [-507.6398010253906, -357.3270568847656, 4838.78564453125], [-133.36288452148438, 8.56325912475586, 4763.33349609375], [-680.5763549804688, -170.40272521972656, 4900.99951171875], [-226.9380645751953, 204.80657958984375, 4625.88232421875], [-749.8486328125, 6.507554531097412, 4716.564453125]], [[-3973.81640625, -2795.182861328125, 13323.7373046875], [-3929.145751953125, -2719.61279296875, 13390.8916015625], [-4037.751220703125, -2708.859375, 13308.048828125], [-3979.368408203125, -2893.864501953125, 13314.5986328125], [-3849.67138671875, -2391.223388671875, 13436.48828125], [-4092.18701171875, -2373.913818359375, 13236.150390625], [-3939.73291015625, -2990.162109375, 13253.318359375], [-3955.9208984375, -2096.30712890625, 13603.7021484375], [-4145.20849609375, -2091.669921875, 13445.123046875], [-3921.09912109375, -3031.678466796875, 13224.7119140625], [-3878.697021484375, -2027.808837890625, 13540.716796875], [-4141.6474609375, -2006.396484375, 13360.478515625], [-3867.051513671875, -3216.688232421875, 13160.6298828125], [-3832.90673828125, -3137.004638671875, 13233.59375], [-3956.0302734375, -3147.3349609375, 13157.046875], [-3828.072509765625, -3241.289306640625, 13100.8330078125], [-3748.77490234375, -3130.6728515625, 13256.8203125], [-4006.676513671875, -3128.640625, 13083.7216796875], [-3678.022705078125, -2931.761474609375, 13361.7021484375], [-4021.82861328125, -2903.514404296875, 13038.763671875], [-3677.55419921875, -2802.553466796875, 13181.91015625], [-3794.11669921875, -2885.19677734375, 13035.3125]]]}] \ No newline at end of file diff --git a/src_joints2smpl_demo/mesh/__init__.py b/src_joints2smpl_demo/mesh/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src_joints2smpl_demo/mesh/io.py b/src_joints2smpl_demo/mesh/io.py new file mode 100644 index 0000000000000000000000000000000000000000..7eaf4224d91f745d490558119928aced4ebe91da --- /dev/null +++ b/src_joints2smpl_demo/mesh/io.py @@ -0,0 +1,14 @@ +from pathlib import Path + +import numpy as np + +from trimesh import Trimesh + + +def to_mesh(vertices: np.ndarray, faces: np.ndarray) -> Trimesh: + return Trimesh(vertices=vertices, faces=faces) + + +def save_obj(mesh: Trimesh, save_path: Path): + with open(save_path, "w") as fw: + mesh.export(fw, "obj") diff --git a/src_joints2smpl_demo/mesh/rotation2xyz.py b/src_joints2smpl_demo/mesh/rotation2xyz.py new file mode 100644 index 0000000000000000000000000000000000000000..e64f20f9064c1780e7c07b481a00ff564a4049d2 --- /dev/null +++ b/src_joints2smpl_demo/mesh/rotation2xyz.py @@ -0,0 +1,106 @@ +# This code is based on https://github.com/Mathux/ACTOR.git +import torch +import numpy as np +import torch.nn.functional as F +from . import rotation_conversions as geometry +from .smpl import SMPL + +JOINTSTYPES = ["a2m", "a2mpl", "smpl", "vibe", "vertices"] + + +class Rotation2xyz: + def __init__(self, device, dataset="amass"): + self.device = device + self.dataset = dataset + self.smpl_model = SMPL().eval().to(device) + + def __call__( + self, + x, + mask, + pose_rep, + translation, + glob, + jointstype, + vertstrans, + betas=None, + beta=0, + glob_rot=None, + get_rotations_back=False, + **kwargs + ): + if pose_rep == "xyz": + return x + + if mask is None: + mask = torch.ones((x.shape[-1]), dtype=bool, device=x.device) + + if not glob and glob_rot is None: + raise TypeError("You must specify global rotation if glob is False") + + if jointstype not in JOINTSTYPES: + raise NotImplementedError("This jointstype is not implemented.") + + if translation: + x_translations = x[-1, :3] + x_rotations = x[:-1] + else: + x_rotations = x + + x_rotations = x_rotations.permute(2, 0, 1) + time, njoints, feats = x_rotations.shape + + # Compute rotations (convert only masked sequences output) + if pose_rep == "rotvec": + rotations = geometry.axis_angle_to_matrix(x_rotations[mask]) + elif pose_rep == "rotmat": + rotations = x_rotations[mask].view(-1, njoints, 3, 3) + elif pose_rep == "rotquat": + rotations = geometry.quaternion_to_matrix(x_rotations[mask]) + elif pose_rep == "rot6d": + rotations = geometry.rotation_6d_to_matrix(x_rotations[mask]) + else: + raise NotImplementedError("No geometry for this one.") + + if not glob: + global_orient = torch.tensor(glob_rot, device=x.device) + global_orient = geometry.axis_angle_to_matrix(global_orient).view( + 1, 1, 3, 3 + ) + global_orient = global_orient.repeat(len(rotations), 1, 1, 1) + else: + global_orient = rotations[:, 0] + rotations = rotations[:, 1:] + + if betas is None: + betas = torch.zeros( + [rotations.shape[0], self.smpl_model.num_betas], + dtype=rotations.dtype, + device=rotations.device, + ) + betas[:, 1] = beta + print(betas) + out = self.smpl_model( + body_pose=rotations, global_orient=global_orient, betas=betas + ) + + # get the desirable joints + joints = out[jointstype] + + x_xyz = torch.empty(time, joints.shape[1], 3, device=x.device, dtype=x.dtype) + x_xyz[~mask] = 0 + x_xyz[mask] = joints + + x_xyz = x_xyz.permute(1, 2, 0).contiguous() + + if translation and vertstrans: + # the first translation root at the origin + x_translations = x_translations - x_translations[:, [0]] + + # add the translation to all the joints + x_xyz = x_xyz + x_translations[None, :, :] + + if get_rotations_back: + return x_xyz, rotations, global_orient + else: + return x_xyz diff --git a/src_joints2smpl_demo/mesh/rotation_conversions.py b/src_joints2smpl_demo/mesh/rotation_conversions.py new file mode 100644 index 0000000000000000000000000000000000000000..210ae1f0878b3ab223ec3d51d4053751dceb47ff --- /dev/null +++ b/src_joints2smpl_demo/mesh/rotation_conversions.py @@ -0,0 +1,552 @@ +# This code is based on https://github.com/Mathux/ACTOR.git +# Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. +# Check PYTORCH3D_LICENCE before use + +import functools +from typing import Optional + +import torch +import torch.nn.functional as F + + +""" +The transformation matrices returned from the functions in this file assume +the points on which the transformation will be applied are column vectors. +i.e. the R matrix is structured as + + R = [ + [Rxx, Rxy, Rxz], + [Ryx, Ryy, Ryz], + [Rzx, Rzy, Rzz], + ] # (3, 3) + +This matrix can be applied to column vectors by post multiplication +by the points e.g. + + points = [[0], [1], [2]] # (3 x 1) xyz coordinates of a point + transformed_points = R * points + +To apply the same matrix to points which are row vectors, the R matrix +can be transposed and pre multiplied by the points: + +e.g. + points = [[0, 1, 2]] # (1 x 3) xyz coordinates of a point + transformed_points = points * R.transpose(1, 0) +""" + + +def quaternion_to_matrix(quaternions): + """ + Convert rotations given as quaternions to rotation matrices. + + Args: + quaternions: quaternions with real part first, + as tensor of shape (..., 4). + + Returns: + Rotation matrices as tensor of shape (..., 3, 3). + """ + r, i, j, k = torch.unbind(quaternions, -1) + two_s = 2.0 / (quaternions * quaternions).sum(-1) + + o = torch.stack( + ( + 1 - two_s * (j * j + k * k), + two_s * (i * j - k * r), + two_s * (i * k + j * r), + two_s * (i * j + k * r), + 1 - two_s * (i * i + k * k), + two_s * (j * k - i * r), + two_s * (i * k - j * r), + two_s * (j * k + i * r), + 1 - two_s * (i * i + j * j), + ), + -1, + ) + return o.reshape(quaternions.shape[:-1] + (3, 3)) + + +def _copysign(a, b): + """ + Return a tensor where each element has the absolute value taken from the, + corresponding element of a, with sign taken from the corresponding + element of b. This is like the standard copysign floating-point operation, + but is not careful about negative 0 and NaN. + + Args: + a: source tensor. + b: tensor whose signs will be used, of the same shape as a. + + Returns: + Tensor of the same shape as a with the signs of b. + """ + signs_differ = (a < 0) != (b < 0) + return torch.where(signs_differ, -a, a) + + +def _sqrt_positive_part(x): + """ + Returns torch.sqrt(torch.max(0, x)) + but with a zero subgradient where x is 0. + """ + ret = torch.zeros_like(x) + positive_mask = x > 0 + ret[positive_mask] = torch.sqrt(x[positive_mask]) + return ret + + +def matrix_to_quaternion(matrix): + """ + Convert rotations given as rotation matrices to quaternions. + + Args: + matrix: Rotation matrices as tensor of shape (..., 3, 3). + + Returns: + quaternions with real part first, as tensor of shape (..., 4). + """ + if matrix.size(-1) != 3 or matrix.size(-2) != 3: + raise ValueError(f"Invalid rotation matrix shape f{matrix.shape}.") + m00 = matrix[..., 0, 0] + m11 = matrix[..., 1, 1] + m22 = matrix[..., 2, 2] + o0 = 0.5 * _sqrt_positive_part(1 + m00 + m11 + m22) + x = 0.5 * _sqrt_positive_part(1 + m00 - m11 - m22) + y = 0.5 * _sqrt_positive_part(1 - m00 + m11 - m22) + z = 0.5 * _sqrt_positive_part(1 - m00 - m11 + m22) + o1 = _copysign(x, matrix[..., 2, 1] - matrix[..., 1, 2]) + o2 = _copysign(y, matrix[..., 0, 2] - matrix[..., 2, 0]) + o3 = _copysign(z, matrix[..., 1, 0] - matrix[..., 0, 1]) + return torch.stack((o0, o1, o2, o3), -1) + + +def _axis_angle_rotation(axis: str, angle): + """ + Return the rotation matrices for one of the rotations about an axis + of which Euler angles describe, for each value of the angle given. + + Args: + axis: Axis label "X" or "Y or "Z". + angle: any shape tensor of Euler angles in radians + + Returns: + Rotation matrices as tensor of shape (..., 3, 3). + """ + + cos = torch.cos(angle) + sin = torch.sin(angle) + one = torch.ones_like(angle) + zero = torch.zeros_like(angle) + + if axis == "X": + R_flat = (one, zero, zero, zero, cos, -sin, zero, sin, cos) + if axis == "Y": + R_flat = (cos, zero, sin, zero, one, zero, -sin, zero, cos) + if axis == "Z": + R_flat = (cos, -sin, zero, sin, cos, zero, zero, zero, one) + + return torch.stack(R_flat, -1).reshape(angle.shape + (3, 3)) + + +def euler_angles_to_matrix(euler_angles, convention: str): + """ + Convert rotations given as Euler angles in radians to rotation matrices. + + Args: + euler_angles: Euler angles in radians as tensor of shape (..., 3). + convention: Convention string of three uppercase letters from + {"X", "Y", and "Z"}. + + Returns: + Rotation matrices as tensor of shape (..., 3, 3). + """ + if euler_angles.dim() == 0 or euler_angles.shape[-1] != 3: + raise ValueError("Invalid input euler angles.") + if len(convention) != 3: + raise ValueError("Convention must have 3 letters.") + if convention[1] in (convention[0], convention[2]): + raise ValueError(f"Invalid convention {convention}.") + for letter in convention: + if letter not in ("X", "Y", "Z"): + raise ValueError(f"Invalid letter {letter} in convention string.") + matrices = map(_axis_angle_rotation, convention, torch.unbind(euler_angles, -1)) + return functools.reduce(torch.matmul, matrices) + + +def _angle_from_tan( + axis: str, other_axis: str, data, horizontal: bool, tait_bryan: bool +): + """ + Extract the first or third Euler angle from the two members of + the matrix which are positive constant times its sine and cosine. + + Args: + axis: Axis label "X" or "Y or "Z" for the angle we are finding. + other_axis: Axis label "X" or "Y or "Z" for the middle axis in the + convention. + data: Rotation matrices as tensor of shape (..., 3, 3). + horizontal: Whether we are looking for the angle for the third axis, + which means the relevant entries are in the same row of the + rotation matrix. If not, they are in the same column. + tait_bryan: Whether the first and third axes in the convention differ. + + Returns: + Euler Angles in radians for each matrix in dataset as a tensor + of shape (...). + """ + + i1, i2 = {"X": (2, 1), "Y": (0, 2), "Z": (1, 0)}[axis] + if horizontal: + i2, i1 = i1, i2 + even = (axis + other_axis) in ["XY", "YZ", "ZX"] + if horizontal == even: + return torch.atan2(data[..., i1], data[..., i2]) + if tait_bryan: + return torch.atan2(-data[..., i2], data[..., i1]) + return torch.atan2(data[..., i2], -data[..., i1]) + + +def _index_from_letter(letter: str): + if letter == "X": + return 0 + if letter == "Y": + return 1 + if letter == "Z": + return 2 + + +def matrix_to_euler_angles(matrix, convention: str): + """ + Convert rotations given as rotation matrices to Euler angles in radians. + + Args: + matrix: Rotation matrices as tensor of shape (..., 3, 3). + convention: Convention string of three uppercase letters. + + Returns: + Euler angles in radians as tensor of shape (..., 3). + """ + if len(convention) != 3: + raise ValueError("Convention must have 3 letters.") + if convention[1] in (convention[0], convention[2]): + raise ValueError(f"Invalid convention {convention}.") + for letter in convention: + if letter not in ("X", "Y", "Z"): + raise ValueError(f"Invalid letter {letter} in convention string.") + if matrix.size(-1) != 3 or matrix.size(-2) != 3: + raise ValueError(f"Invalid rotation matrix shape f{matrix.shape}.") + i0 = _index_from_letter(convention[0]) + i2 = _index_from_letter(convention[2]) + tait_bryan = i0 != i2 + if tait_bryan: + central_angle = torch.asin( + matrix[..., i0, i2] * (-1.0 if i0 - i2 in [-1, 2] else 1.0) + ) + else: + central_angle = torch.acos(matrix[..., i0, i0]) + + o = ( + _angle_from_tan( + convention[0], convention[1], matrix[..., i2], False, tait_bryan + ), + central_angle, + _angle_from_tan( + convention[2], convention[1], matrix[..., i0, :], True, tait_bryan + ), + ) + return torch.stack(o, -1) + + +def random_quaternions( + n: int, dtype: Optional[torch.dtype] = None, device=None, requires_grad=False +): + """ + Generate random quaternions representing rotations, + i.e. versors with nonnegative real part. + + Args: + n: Number of quaternions in a batch to return. + dtype: Type to return. + device: Desired device of returned tensor. Default: + uses the current device for the default tensor type. + requires_grad: Whether the resulting tensor should have the gradient + flag set. + + Returns: + Quaternions as tensor of shape (N, 4). + """ + o = torch.randn((n, 4), dtype=dtype, device=device, requires_grad=requires_grad) + s = (o * o).sum(1) + o = o / _copysign(torch.sqrt(s), o[:, 0])[:, None] + return o + + +def random_rotations( + n: int, dtype: Optional[torch.dtype] = None, device=None, requires_grad=False +): + """ + Generate random rotations as 3x3 rotation matrices. + + Args: + n: Number of rotation matrices in a batch to return. + dtype: Type to return. + device: Device of returned tensor. Default: if None, + uses the current device for the default tensor type. + requires_grad: Whether the resulting tensor should have the gradient + flag set. + + Returns: + Rotation matrices as tensor of shape (n, 3, 3). + """ + quaternions = random_quaternions( + n, dtype=dtype, device=device, requires_grad=requires_grad + ) + return quaternion_to_matrix(quaternions) + + +def random_rotation( + dtype: Optional[torch.dtype] = None, device=None, requires_grad=False +): + """ + Generate a single random 3x3 rotation matrix. + + Args: + dtype: Type to return + device: Device of returned tensor. Default: if None, + uses the current device for the default tensor type + requires_grad: Whether the resulting tensor should have the gradient + flag set + + Returns: + Rotation matrix as tensor of shape (3, 3). + """ + return random_rotations(1, dtype, device, requires_grad)[0] + + +def standardize_quaternion(quaternions): + """ + Convert a unit quaternion to a standard form: one in which the real + part is non negative. + + Args: + quaternions: Quaternions with real part first, + as tensor of shape (..., 4). + + Returns: + Standardized quaternions as tensor of shape (..., 4). + """ + return torch.where(quaternions[..., 0:1] < 0, -quaternions, quaternions) + + +def quaternion_raw_multiply(a, b): + """ + Multiply two quaternions. + Usual torch rules for broadcasting apply. + + Args: + a: Quaternions as tensor of shape (..., 4), real part first. + b: Quaternions as tensor of shape (..., 4), real part first. + + Returns: + The product of a and b, a tensor of quaternions shape (..., 4). + """ + aw, ax, ay, az = torch.unbind(a, -1) + bw, bx, by, bz = torch.unbind(b, -1) + ow = aw * bw - ax * bx - ay * by - az * bz + ox = aw * bx + ax * bw + ay * bz - az * by + oy = aw * by - ax * bz + ay * bw + az * bx + oz = aw * bz + ax * by - ay * bx + az * bw + return torch.stack((ow, ox, oy, oz), -1) + + +def quaternion_multiply(a, b): + """ + Multiply two quaternions representing rotations, returning the quaternion + representing their composition, i.e. the versor with nonnegative real part. + Usual torch rules for broadcasting apply. + + Args: + a: Quaternions as tensor of shape (..., 4), real part first. + b: Quaternions as tensor of shape (..., 4), real part first. + + Returns: + The product of a and b, a tensor of quaternions of shape (..., 4). + """ + ab = quaternion_raw_multiply(a, b) + return standardize_quaternion(ab) + + +def quaternion_invert(quaternion): + """ + Given a quaternion representing rotation, get the quaternion representing + its inverse. + + Args: + quaternion: Quaternions as tensor of shape (..., 4), with real part + first, which must be versors (unit quaternions). + + Returns: + The inverse, a tensor of quaternions of shape (..., 4). + """ + + return quaternion * quaternion.new_tensor([1, -1, -1, -1]) + + +def quaternion_apply(quaternion, point): + """ + Apply the rotation given by a quaternion to a 3D point. + Usual torch rules for broadcasting apply. + + Args: + quaternion: Tensor of quaternions, real part first, of shape (..., 4). + point: Tensor of 3D points of shape (..., 3). + + Returns: + Tensor of rotated points of shape (..., 3). + """ + if point.size(-1) != 3: + raise ValueError(f"Points are not in 3D, f{point.shape}.") + real_parts = point.new_zeros(point.shape[:-1] + (1,)) + point_as_quaternion = torch.cat((real_parts, point), -1) + out = quaternion_raw_multiply( + quaternion_raw_multiply(quaternion, point_as_quaternion), + quaternion_invert(quaternion), + ) + return out[..., 1:] + + +def axis_angle_to_matrix(axis_angle): + """ + Convert rotations given as axis/angle to rotation matrices. + + Args: + axis_angle: Rotations given as a vector in axis angle form, + as a tensor of shape (..., 3), where the magnitude is + the angle turned anticlockwise in radians around the + vector's direction. + + Returns: + Rotation matrices as tensor of shape (..., 3, 3). + """ + return quaternion_to_matrix(axis_angle_to_quaternion(axis_angle)) + + +def matrix_to_axis_angle(matrix): + """ + Convert rotations given as rotation matrices to axis/angle. + + Args: + matrix: Rotation matrices as tensor of shape (..., 3, 3). + + Returns: + Rotations given as a vector in axis angle form, as a tensor + of shape (..., 3), where the magnitude is the angle + turned anticlockwise in radians around the vector's + direction. + """ + return quaternion_to_axis_angle(matrix_to_quaternion(matrix)) + + +def axis_angle_to_quaternion(axis_angle): + """ + Convert rotations given as axis/angle to quaternions. + + Args: + axis_angle: Rotations given as a vector in axis angle form, + as a tensor of shape (..., 3), where the magnitude is + the angle turned anticlockwise in radians around the + vector's direction. + + Returns: + quaternions with real part first, as tensor of shape (..., 4). + """ + angles = torch.norm(axis_angle, p=2, dim=-1, keepdim=True) + half_angles = 0.5 * angles + eps = 1e-6 + small_angles = angles.abs() < eps + sin_half_angles_over_angles = torch.empty_like(angles) + sin_half_angles_over_angles[~small_angles] = ( + torch.sin(half_angles[~small_angles]) / angles[~small_angles] + ) + # for x small, sin(x/2) is about x/2 - (x/2)^3/6 + # so sin(x/2)/x is about 1/2 - (x*x)/48 + sin_half_angles_over_angles[small_angles] = ( + 0.5 - (angles[small_angles] * angles[small_angles]) / 48 + ) + quaternions = torch.cat( + [torch.cos(half_angles), axis_angle * sin_half_angles_over_angles], dim=-1 + ) + return quaternions + + +def quaternion_to_axis_angle(quaternions): + """ + Convert rotations given as quaternions to axis/angle. + + Args: + quaternions: quaternions with real part first, + as tensor of shape (..., 4). + + Returns: + Rotations given as a vector in axis angle form, as a tensor + of shape (..., 3), where the magnitude is the angle + turned anticlockwise in radians around the vector's + direction. + """ + norms = torch.norm(quaternions[..., 1:], p=2, dim=-1, keepdim=True) + half_angles = torch.atan2(norms, quaternions[..., :1]) + angles = 2 * half_angles + eps = 1e-6 + small_angles = angles.abs() < eps + sin_half_angles_over_angles = torch.empty_like(angles) + sin_half_angles_over_angles[~small_angles] = ( + torch.sin(half_angles[~small_angles]) / angles[~small_angles] + ) + # for x small, sin(x/2) is about x/2 - (x/2)^3/6 + # so sin(x/2)/x is about 1/2 - (x*x)/48 + sin_half_angles_over_angles[small_angles] = ( + 0.5 - (angles[small_angles] * angles[small_angles]) / 48 + ) + return quaternions[..., 1:] / sin_half_angles_over_angles + + +def rotation_6d_to_matrix(d6: torch.Tensor) -> torch.Tensor: + """ + Converts 6D rotation representation by Zhou et al. [1] to rotation matrix + using Gram--Schmidt orthogonalisation per Section B of [1]. + Args: + d6: 6D rotation representation, of size (*, 6) + + Returns: + batch of rotation matrices of size (*, 3, 3) + + [1] Zhou, Y., Barnes, C., Lu, J., Yang, J., & Li, H. + On the Continuity of Rotation Representations in Neural Networks. + IEEE Conference on Computer Vision and Pattern Recognition, 2019. + Retrieved from http://arxiv.org/abs/1812.07035 + """ + + a1, a2 = d6[..., :3], d6[..., 3:] + b1 = F.normalize(a1, dim=-1) + b2 = a2 - (b1 * a2).sum(-1, keepdim=True) * b1 + b2 = F.normalize(b2, dim=-1) + b3 = torch.cross(b1, b2, dim=-1) + return torch.stack((b1, b2, b3), dim=-2) + + +def matrix_to_rotation_6d(matrix: torch.Tensor) -> torch.Tensor: + """ + Converts rotation matrices to 6D rotation representation by Zhou et al. [1] + by dropping the last row. Note that 6D representation is not unique. + Args: + matrix: batch of rotation matrices of size (*, 3, 3) + + Returns: + 6D rotation representation, of size (*, 6) + + [1] Zhou, Y., Barnes, C., Lu, J., Yang, J., & Li, H. + On the Continuity of Rotation Representations in Neural Networks. + IEEE Conference on Computer Vision and Pattern Recognition, 2019. + Retrieved from http://arxiv.org/abs/1812.07035 + """ + return matrix[..., :2, :].clone().reshape(*matrix.size()[:-2], 6) diff --git a/src_joints2smpl_demo/mesh/smpl.py b/src_joints2smpl_demo/mesh/smpl.py new file mode 100644 index 0000000000000000000000000000000000000000..950fa0d39dcd985f7272768c69d1eb86c3b5649b --- /dev/null +++ b/src_joints2smpl_demo/mesh/smpl.py @@ -0,0 +1,182 @@ +# This code is based on https://github.com/Mathux/ACTOR.git +import contextlib + +import numpy as np +import torch +from smplx import SMPLLayer as _SMPLLayer +from smplx.lbs import vertices2joints + +# action2motion_joints = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 21, 24, 38] +# change 0 and 8 +action2motion_joints = [8, 1, 2, 3, 4, 5, 6, 7, 0, 9, 10, 11, 12, 13, 14, 21, 24, 38] + +# from utils.config import JOINT_REGRESSOR_TRAIN_EXTRA, SMPL_MODEL_PATH +import os + +SMPL_DATA_PATH = "./body_models/smpl" + +# SMPL_KINTREE_PATH = os.path.join(SMPL_DATA_PATH, "kintree_table.pkl") +SMPL_MODEL_PATH = os.path.join(SMPL_DATA_PATH, "SMPL_NEUTRAL.pkl") +JOINT_REGRESSOR_TRAIN_EXTRA = os.path.join(SMPL_DATA_PATH, "J_regressor_extra.npy") + +# ROT_CONVENTION_TO_ROT_NUMBER = { +# 'legacy': 23, +# 'no_hands': 21, +# 'full_hands': 51, +# 'mitten_hands': 33, +# } + +# GENDERS = ['neutral', 'male', 'female'] +# NUM_BETAS = 10 + +JOINTSTYPE_ROOT = { + "a2m": 0, # action2motion + "smpl": 0, + "a2mpl": 0, # set(smpl, a2m) + "vibe": 8, +} # 0 is the 8 position: OP MidHip below + +JOINT_MAP = { + "OP Nose": 24, + "OP Neck": 12, + "OP RShoulder": 17, + "OP RElbow": 19, + "OP RWrist": 21, + "OP LShoulder": 16, + "OP LElbow": 18, + "OP LWrist": 20, + "OP MidHip": 0, + "OP RHip": 2, + "OP RKnee": 5, + "OP RAnkle": 8, + "OP LHip": 1, + "OP LKnee": 4, + "OP LAnkle": 7, + "OP REye": 25, + "OP LEye": 26, + "OP REar": 27, + "OP LEar": 28, + "OP LBigToe": 29, + "OP LSmallToe": 30, + "OP LHeel": 31, + "OP RBigToe": 32, + "OP RSmallToe": 33, + "OP RHeel": 34, + "Right Ankle": 8, + "Right Knee": 5, + "Right Hip": 45, + "Left Hip": 46, + "Left Knee": 4, + "Left Ankle": 7, + "Right Wrist": 21, + "Right Elbow": 19, + "Right Shoulder": 17, + "Left Shoulder": 16, + "Left Elbow": 18, + "Left Wrist": 20, + "Neck (LSP)": 47, + "Top of Head (LSP)": 48, + "Pelvis (MPII)": 49, + "Thorax (MPII)": 50, + "Spine (H36M)": 51, + "Jaw (H36M)": 52, + "Head (H36M)": 53, + "Nose": 24, + "Left Eye": 26, + "Right Eye": 25, + "Left Ear": 28, + "Right Ear": 27, +} + +JOINT_NAMES = [ + "OP Nose", + "OP Neck", + "OP RShoulder", + "OP RElbow", + "OP RWrist", + "OP LShoulder", + "OP LElbow", + "OP LWrist", + "OP MidHip", + "OP RHip", + "OP RKnee", + "OP RAnkle", + "OP LHip", + "OP LKnee", + "OP LAnkle", + "OP REye", + "OP LEye", + "OP REar", + "OP LEar", + "OP LBigToe", + "OP LSmallToe", + "OP LHeel", + "OP RBigToe", + "OP RSmallToe", + "OP RHeel", + "Right Ankle", + "Right Knee", + "Right Hip", + "Left Hip", + "Left Knee", + "Left Ankle", + "Right Wrist", + "Right Elbow", + "Right Shoulder", + "Left Shoulder", + "Left Elbow", + "Left Wrist", + "Neck (LSP)", + "Top of Head (LSP)", + "Pelvis (MPII)", + "Thorax (MPII)", + "Spine (H36M)", + "Jaw (H36M)", + "Head (H36M)", + "Nose", + "Left Eye", + "Right Eye", + "Left Ear", + "Right Ear", +] + + +# adapted from VIBE/SPIN to output smpl_joints, vibe joints and action2motion joints +class SMPL(_SMPLLayer): + """Extension of the official SMPL implementation to support more joints""" + + def __init__(self, model_path=SMPL_MODEL_PATH, **kwargs): + kwargs["model_path"] = model_path + + # remove the verbosity for the 10-shapes beta parameters + with contextlib.redirect_stdout(None): + super(SMPL, self).__init__(**kwargs) + + J_regressor_extra = np.load(JOINT_REGRESSOR_TRAIN_EXTRA) + self.register_buffer( + "J_regressor_extra", torch.tensor(J_regressor_extra, dtype=torch.float32) + ) + vibe_indexes = np.array([JOINT_MAP[i] for i in JOINT_NAMES]) + a2m_indexes = vibe_indexes[action2motion_joints] + smpl_indexes = np.arange(24) + a2mpl_indexes = np.unique(np.r_[smpl_indexes, a2m_indexes]) + + self.maps = { + "vibe": vibe_indexes, + "a2m": a2m_indexes, + "smpl": smpl_indexes, + "a2mpl": a2mpl_indexes, + } + + def forward(self, *args, **kwargs): + smpl_output = super(SMPL, self).forward(*args, **kwargs) + + extra_joints = vertices2joints(self.J_regressor_extra, smpl_output.vertices) + all_joints = torch.cat([smpl_output.joints, extra_joints], dim=1) + + output = {"vertices": smpl_output.vertices} + + for joinstype, indexes in self.maps.items(): + output[joinstype] = all_joints[:, indexes] + + return output diff --git a/src_joints2smpl_demo/mesh/smpl2mesh.py b/src_joints2smpl_demo/mesh/smpl2mesh.py new file mode 100644 index 0000000000000000000000000000000000000000..f08ccccb26f2e00c9ddb5b6673efcda27148d7d7 --- /dev/null +++ b/src_joints2smpl_demo/mesh/smpl2mesh.py @@ -0,0 +1,40 @@ +import torch + +from .rotation2xyz import Rotation2xyz +from .rotation_conversions import matrix_to_rotation_6d, axis_angle_to_matrix + +class SMPL2Mesh: + def __init__( + self, + device: str = "cpu", + ): + self.rot2xyz = Rotation2xyz(device=device) + self.faces = self.rot2xyz.smpl_model.faces + + + def convert_smpl_to_mesh(self, new_opt_pose, keypoints_3d, betas=None): + batch_size = keypoints_3d.shape[0] + + thetas = new_opt_pose.reshape(batch_size, 24, 3) + thetas = matrix_to_rotation_6d( + axis_angle_to_matrix(thetas) + ) # [bs, 24, 6] + # root_loc = torch.tensor(keypoints_3d[:, 0]) # [bs, 3] + root_loc = keypoints_3d[:, 0].clone() # [bs, 3] + root_loc = torch.cat([root_loc, torch.zeros_like(root_loc)], dim=-1).unsqueeze( + 1 + ) # [bs, 1, 6] + thetas = torch.cat([thetas, root_loc], dim=1).permute(1, 2, 0) # [25, 6, 196] + rot_motions = thetas.detach() + vertices = self.rot2xyz( + rot_motions, + mask=None, + pose_rep="rot6d", + translation=True, + glob=True, + jointstype="vertices", + vertstrans=True, + betas=betas + ) + + return vertices.cpu().numpy(), self.faces \ No newline at end of file diff --git a/src_joints2smpl_demo/plots/joints_plot.png b/src_joints2smpl_demo/plots/joints_plot.png new file mode 100644 index 0000000000000000000000000000000000000000..e6e92ca38470e8aca47833931aee7d56c18060b9 Binary files /dev/null and b/src_joints2smpl_demo/plots/joints_plot.png differ diff --git a/src_joints2smpl_demo/plots/joints_plotNLF_XYswitched.png b/src_joints2smpl_demo/plots/joints_plotNLF_XYswitched.png new file mode 100644 index 0000000000000000000000000000000000000000..c2b359af9302319ee4db9710972a4b0906378b0b Binary files /dev/null and b/src_joints2smpl_demo/plots/joints_plotNLF_XYswitched.png differ diff --git a/src_joints2smpl_demo/plots/joints_plot_our_model.png b/src_joints2smpl_demo/plots/joints_plot_our_model.png new file mode 100644 index 0000000000000000000000000000000000000000..18d0dac1d76caaa70dc01f74dc23e6a0d160545a Binary files /dev/null and b/src_joints2smpl_demo/plots/joints_plot_our_model.png differ diff --git a/src_joints2smpl_demo/setup.py b/src_joints2smpl_demo/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..5a6e6897e2d66442683811a65468b67bd5b7822f --- /dev/null +++ b/src_joints2smpl_demo/setup.py @@ -0,0 +1,12 @@ +from setuptools import setup, find_packages + +setup( + name="joints2smpl", + version="0.1.0", + package_dir={"": "."}, + packages=find_packages(where="."), + install_requires=[ + "torch", + "numpy", + ], +) \ No newline at end of file diff --git a/src_joints2smpl_demo/skeleton/__init__.py b/src_joints2smpl_demo/skeleton/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..4fac8edb72905047543eb1d0a9510e26db8deaaf --- /dev/null +++ b/src_joints2smpl_demo/skeleton/__init__.py @@ -0,0 +1,2 @@ +from .amass import Amass as SkeletonAMASS +from .conversions import convert2humanml \ No newline at end of file diff --git a/src_joints2smpl_demo/skeleton/amass.py b/src_joints2smpl_demo/skeleton/amass.py new file mode 100644 index 0000000000000000000000000000000000000000..a83f8778010c1035077e52c81dfc02f9da6c92bc --- /dev/null +++ b/src_joints2smpl_demo/skeleton/amass.py @@ -0,0 +1,166 @@ +from dataclasses import dataclass + + +FPS=60 +from .base import SkeletonBaseClass + +LANDMARKS = [ + "pelvis", # check + "left_hip", # check + "right_hip", # check + "spine1", # check + "left_knee", # check + "right_knee", # check + "spine2", + "left_ankle", # check + "right_ankle", # check + "spine3", + "left_foot", # check, but wrong + "right_foot", # check, but wrong + "neck", # check + "left_collar", + "right_collar", + "head", # check + "left_shoulder", # check + "right_shoulder", # check + "left_elbow", # check + "right_elbow", # check + "left_wrist", # check + "right_wrist", # check +] +# ['GlobalHip', 'RHip', 'LHip', 'Spine1', 'RKnee', 'LKnee', 'Spine3', 'RHeel', 'LHeel', 'Neck', 'RFoot', 'LFoot', 'BMN', 'RSI', 'LSI', 'Head', 'RShoulder', 'LShoulder', 'RElbow', 'LElbow', 'RWrist', 'LWrist'] + +SKELETON_NAMES = [ + ["pelvis", "right_hip", "right_knee", "right_ankle", "right_foot"], + ["pelvis", "left_hip", "left_knee", "left_ankle", "left_foot"], + ["pelvis", "spine1", "spine2", "spine3", "neck", "head"], + ["spine3", "right_collar", "right_shoulder", "right_elbow", "right_wrist"], + ["spine3", "left_collar", "left_shoulder", "left_elbow", "left_wrist"], +] + +SKELETON = [[LANDMARKS.index(name) for name in names] for names in SKELETON_NAMES] + +ROOT_INDEX = LANDMARKS.index("pelvis") + +MIRRORED_LANDMARKS = { + "pelvis": "pelvis", + "left_hip": "right_hip", + "right_hip": "left_hip", + "spine1": "spine1", + "left_knee": "right_knee", + "right_knee": "left_knee", + "spine2": "spine2", + "left_ankle": "right_ankle", + "right_ankle": "left_ankle", + "spine3": "spine3", + "left_foot": "right_foot", + "right_foot": "left_foot", + "neck": "neck", + "left_collar": "right_collar", + "right_collar": "left_collar", + "head": "head", + "left_shoulder": "right_shoulder", + "right_shoulder": "left_shoulder", + "left_elbow": "right_elbow", + "right_elbow": "left_elbow", + "left_wrist": "right_wrist", + "right_wrist": "left_wrist", +} + +MIRRORED_INDICES = [ + LANDMARKS.index(MIRRORED_LANDMARKS[landmark]) for landmark in LANDMARKS +] + +TO_HUMANML_NAMES = [ + ("pelvis", "pelvis"), + ("right_hip", "right_hip"), + ("right_knee", "right_knee"), + ("right_ankle", "right_ankle"), + ("right_foot", "right_foot"), + ("left_hip", "left_hip"), + ("left_knee", "left_knee"), + ("left_ankle", "left_ankle"), + ("left_foot", "left_foot"), + ("spine1", "spine1"), + ("spine2", "spine2"), + ("spine3", "spine3"), + ("neck", "neck"), + ("head", "head"), + ("left_collar", "left_collar"), + ("right_collar", "right_collar"), + ("left_shoulder", "left_shoulder"), + ("right_shoulder", "right_shoulder"), + ("left_elbow", "left_elbow"), + ("right_elbow", "right_elbow"), + ("left_wrist", "left_wrist"), + ("right_wrist", "right_wrist"), +] + +LIMBSEQ = [ + [0, 3], + [3, 6], + [6, 9], + [9, 12], + [12, 15], # body + [9, 14], + [14, 17], + [17, 19], + [19, 21], # right arm + [9, 13], + [13, 16], + [16, 18], + [18, 20], # left arm + [0, 2], + [2, 5], + [5, 8], + [8, 11], # right leg + [0, 1], + [1, 4], + [4, 7], + [7, 10], # left leg +] + +PARENTS= [-1, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 12, 13, 14, 16, 17, 18, 19] +PARENTS_COLOR_LIST = ["m", 'r', 'l', "m", 'r', 'l', "m", 'r', 'l', "m", 'r', 'l', "m", 'r', 'l', "m", 'r', 'l', 'r', 'l', 'r', 'l'] + +LIMB_POSITIONS = [ + "m", + "m", + "m", + "m", + "m", + "r", + "r", + "r", + "r", + "l", + "l", + "l", + "l", + "r", + "r", + "r", + "r", + "l", + "l", + "l", + "l", +] + + +Amass = SkeletonBaseClass( + LANDMARKS, + SKELETON_NAMES, + SKELETON, + ROOT_INDEX, + MIRRORED_LANDMARKS, + MIRRORED_INDICES, + TO_HUMANML_NAMES, + LIMBSEQ, + LIMB_POSITIONS, + PARENTS, + PARENTS_COLOR_LIST, + FPS +) + + diff --git a/src_joints2smpl_demo/skeleton/base.py b/src_joints2smpl_demo/skeleton/base.py new file mode 100644 index 0000000000000000000000000000000000000000..0c04d34b254cf435c4dfac0baceaadae66fd6591 --- /dev/null +++ b/src_joints2smpl_demo/skeleton/base.py @@ -0,0 +1,58 @@ +from abc import ABC +from dataclasses import dataclass + + +LANDMARKS = [ + "pelvis", + "left_hip", + "right_hip", + "spine1", + "left_knee", + "right_knee", + "spine2", + "left_ankle", + "right_ankle", + "spine3", + "left_foot", + "right_foot", + "neck", + "left_collar", + "right_collar", + "head", + "left_shoulder", + "right_shoulder", + "left_elbow", + "right_elbow", + "left_wrist", + "right_wrist", +] + +SKELETON_NAMES = [ + ["pelvis", "right_hip", "right_knee", "right_ankle", "right_foot"], + ["pelvis", "left_hip", "left_knee", "left_ankle", "left_foot"], + ["pelvis", "spine1", "spine2", "spine3", "neck", "head"], + ["spine3", "right_collar", "right_shoulder", "right_elbow", "right_wrist"], + ["spine3", "left_collar", "left_shoulder", "left_elbow", "left_wrist"], +] + +SKELETON = [[LANDMARKS.index(name) for name in names] for names in SKELETON_NAMES] + +ROOT_INDEX = LANDMARKS.index("pelvis") + + +@dataclass +class SkeletonBaseClass(ABC): + LANDMARKS: list + SKELETON_NAMES: list + SKELETON: list + ROOT_INDEX: int + MIRRORED_LANDMARKS: dict + MIRRORED_INDICES: list + TO_HUMANML_NAMES: list + LIMBSEQ: list + LIMB_POSITIONS: list + PARENTS: list + PARENTS_COLOR_LIST: list + FPS: int + + diff --git a/src_joints2smpl_demo/skeleton/conversions.py b/src_joints2smpl_demo/skeleton/conversions.py new file mode 100644 index 0000000000000000000000000000000000000000..8b6fc8163773bb0b19ffbd01a252054d0dadcff9 --- /dev/null +++ b/src_joints2smpl_demo/skeleton/conversions.py @@ -0,0 +1,101 @@ +import numpy as np +import torch + +from .base import LANDMARKS + + +def convert2humanml( + motion: torch.tensor, + dataset_landmarks: list[str], + joint_to_humanml_names: list[tuple[str, str]], +) -> np.ndarray: + """ + Convert skeletons to human ml. + Args: + skeletons: Skeletons. + dataset_landmarks: Landmarks of the dataset. + joint_to_humanml_names: Conversion names. + Returns: + new_motion: Skeletons in human ml. + """ + new_motion = torch.zeros((*motion.shape[:-2], len(LANDMARKS), 3), device=motion.device) + indices = torch.tensor( + [ + (LANDMARKS.index(hml_name), dataset_landmarks.index(nba_name)) + for hml_name, nba_name in joint_to_humanml_names + ] + ) + new_motion[..., indices[:, 0], :] = motion[..., indices[:, 1], :] + + # Infer missing landmarks + covered_landmarks = [hml_landmark for hml_landmark, _ in joint_to_humanml_names] + root_index, left_hip_index, right_hip_index = ( + LANDMARKS.index("pelvis"), + LANDMARKS.index("left_hip"), + LANDMARKS.index("right_hip"), + ) + if "pelvis" not in covered_landmarks: + assert ( + "left_hip" in covered_landmarks and "right_hip" in covered_landmarks + ), "pelvis could not be inferred from left_hip and right_hip" + new_motion[..., root_index, :] = ( + new_motion[..., left_hip_index, :] + new_motion[..., right_hip_index, :] + ) / 2 + + neck_index, left_shoulder_index, right_shoulder_index = ( + LANDMARKS.index("neck"), + LANDMARKS.index("left_shoulder"), + LANDMARKS.index("right_shoulder"), + ) + if "neck" not in covered_landmarks: + assert ( + "left_shoulder" in covered_landmarks + and "right_shoulder" in covered_landmarks + ), "neck could not be inferred from left_shoulder and right_shoulder" + new_motion[..., neck_index, :] = ( + new_motion[..., left_shoulder_index, :] + + new_motion[..., right_shoulder_index, :] + ) / 2 + + spine_1_index, spine_2_index, spine_3_index = ( + LANDMARKS.index("spine1"), + LANDMARKS.index("spine2"), + LANDMARKS.index("spine3"), + ) + if "spine1" not in covered_landmarks: + new_motion[..., spine_1_index, :] = ( + 0.75 * new_motion[..., root_index, :] + + 0.25 * new_motion[..., neck_index, :] + ) + if "spine2" not in covered_landmarks: + new_motion[..., spine_2_index, :] = ( + 0.5 * new_motion[..., root_index, :] + 0.5 * new_motion[..., neck_index, :] + ) + if "spine3" not in covered_landmarks: + new_motion[..., spine_3_index, :] = ( + 0.25 * new_motion[..., root_index, :] + + 0.75 * new_motion[..., neck_index, :] + ) + + left_collar_index, right_collar_index = LANDMARKS.index( + "left_collar" + ), LANDMARKS.index("right_collar") + if "left_collar" not in covered_landmarks: + assert ( + "left_shoulder" in covered_landmarks + ), "left_collar could not be inferred from left_shoulder" + new_motion[..., left_collar_index, :] = ( + 0.25 * new_motion[..., left_shoulder_index, :] + + 0.75 * new_motion[..., neck_index, :] + ) + if "right_collar" not in covered_landmarks: + assert ( + "right_shoulder" in covered_landmarks + ), "right_collar could not be inferred from right_shoulder" + new_motion[..., right_collar_index, :] = ( + 0.25 * new_motion[..., right_shoulder_index, :] + + 0.75 * new_motion[..., neck_index, :] + ) + + return new_motion + diff --git a/src_joints2smpl_demo/skeleton2smpl/__init__.py b/src_joints2smpl_demo/skeleton2smpl/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src_joints2smpl_demo/skeleton2smpl/optimize/__init__.py b/src_joints2smpl_demo/skeleton2smpl/optimize/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src_joints2smpl_demo/skeleton2smpl/optimize/config/__init__.py b/src_joints2smpl_demo/skeleton2smpl/optimize/config/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e492061c415275869738035d21e430ccdd2906ed --- /dev/null +++ b/src_joints2smpl_demo/skeleton2smpl/optimize/config/__init__.py @@ -0,0 +1,33 @@ +import numpy as np + +# Map joints Name to SMPL joints idx +JOINT_MAP = { +'MidHip': 0, +'LHip': 1, 'LKnee': 4, 'LAnkle': 7, 'LFoot': 10, +'RHip': 2, 'RKnee': 5, 'RAnkle': 8, 'RFoot': 11, +'LShoulder': 16, 'LElbow': 18, 'LWrist': 20, 'LHand': 22, +'RShoulder': 17, 'RElbow': 19, 'RWrist': 21, 'RHand': 23, +'spine1': 3, 'spine2': 6, 'spine3': 9, 'Neck': 12, 'Head': 15, +'LCollar':13, 'Rcollar' :14, +'Nose':24, 'REye':26, 'LEye':26, 'REar':27, 'LEar':28, +'LHeel': 31, 'RHeel': 34, +'OP RShoulder': 17, 'OP LShoulder': 16, +'OP RHip': 2, 'OP LHip': 1, +'OP Neck': 12, +} + +full_smpl_idx = range(24) +key_smpl_idx = [0, 1, 4, 7, 2, 5, 8, 17, 19, 21, 16, 18, 20] + + +AMASS_JOINT_MAP = { +'MidHip': 0, +'LHip': 1, 'LKnee': 4, 'LAnkle': 7, 'LFoot': 10, +'RHip': 2, 'RKnee': 5, 'RAnkle': 8, 'RFoot': 11, +'LShoulder': 16, 'LElbow': 18, 'LWrist': 20, +'RShoulder': 17, 'RElbow': 19, 'RWrist': 21, +'spine1': 3, 'spine2': 6, 'spine3': 9, 'Neck': 12, 'Head': 15, +'LCollar':13, 'Rcollar' :14, +} +amass_idx = range(22) +amass_smpl_idx = range(22) \ No newline at end of file diff --git a/src_joints2smpl_demo/skeleton2smpl/optimize/customloss.py b/src_joints2smpl_demo/skeleton2smpl/optimize/customloss.py new file mode 100644 index 0000000000000000000000000000000000000000..b9035d09713e70cca70389774a519bde598d00f2 --- /dev/null +++ b/src_joints2smpl_demo/skeleton2smpl/optimize/customloss.py @@ -0,0 +1,287 @@ +import torch +import torch.nn as nn +from . import config + + +# Guassian +def gmof(x, sigma): + """ + Geman-McClure error function + """ + x_squared = x**2 + sigma_squared = sigma**2 + return (sigma_squared * x_squared) / (sigma_squared + x_squared) + + +# angle prior +def angle_prior(pose): + """ + Angle prior that penalizes unnatural bending of the knees and elbows + """ + # We subtract 3 because pose does not include the global rotation of the model + return ( + torch.exp( + pose[:, [55 - 3, 58 - 3, 12 - 3, 15 - 3]] + * torch.tensor([1.0, -1.0, -1, -1.0], device=pose.device) + ) + ** 2 + ) + + +def perspective_projection(points, rotation, translation, focal_length, camera_center): + """ + This function computes the perspective projection of a set of points. + Input: + points (bs, N, 3): 3D points + rotation (bs, 3, 3): Camera rotation + translation (bs, 3): Camera translation + focal_length (bs,) or scalar: Focal length + camera_center (bs, 2): Camera center + """ + batch_size = points.shape[0] + K = torch.zeros([batch_size, 3, 3], device=points.device) + K[:, 0, 0] = focal_length + K[:, 1, 1] = focal_length + K[:, 2, 2] = 1.0 + K[:, :-1, -1] = camera_center + + # Transform points + points = torch.einsum("bij,bkj->bki", rotation, points) + points = points + translation.unsqueeze(1) + + # Apply perspective distortion + projected_points = points / points[:, :, -1].unsqueeze(-1) + + # Apply camera intrinsics + projected_points = torch.einsum("bij,bkj->bki", K, projected_points) + + return projected_points[:, :, :-1] + + +def body_fitting_loss( + body_pose, + betas, + model_joints, + camera_t, + camera_center, + joints_2d, + joints_conf, + pose_prior, + focal_length=5000, + sigma=100, + pose_prior_weight=4.78, + shape_prior_weight=5, + angle_prior_weight=15.2, + output="sum", +): + """ + Loss function for body fitting + """ + batch_size = body_pose.shape[0] + rotation = ( + torch.eye(3, device=body_pose.device).unsqueeze(0).expand(batch_size, -1, -1) + ) + + projected_joints = perspective_projection( + model_joints, rotation, camera_t, focal_length, camera_center + ) + + # Weighted robust reprojection error + reprojection_error = gmof(projected_joints - joints_2d, sigma) + reprojection_loss = (joints_conf**2) * reprojection_error.sum(dim=-1) + + # Pose prior loss + pose_prior_loss = (pose_prior_weight**2) * pose_prior(body_pose, betas) + + # Angle prior for knees and elbows + angle_prior_loss = (angle_prior_weight**2) * angle_prior(body_pose).sum(dim=-1) + + # Regularizer to prevent betas from taking large values + shape_prior_loss = (shape_prior_weight**2) * (betas**2).sum(dim=-1) + + total_loss = ( + reprojection_loss.sum(dim=-1) + + pose_prior_loss + + angle_prior_loss + + shape_prior_loss + ) + + if output == "sum": + return total_loss.sum() + elif output == "reprojection": + return reprojection_loss + + +# --- get camera fitting loss ----- +def camera_fitting_loss( + model_joints, + camera_t, + camera_t_est, + camera_center, + joints_2d, + joints_conf, + focal_length=5000, + depth_loss_weight=100, +): + """ + Loss function for camera optimization. + """ + # Project model joints + batch_size = model_joints.shape[0] + rotation = ( + torch.eye(3, device=model_joints.device).unsqueeze(0).expand(batch_size, -1, -1) + ) + projected_joints = perspective_projection( + model_joints, rotation, camera_t, focal_length, camera_center + ) + + # get the indexed four + op_joints = ["OP RHip", "OP LHip", "OP RShoulder", "OP LShoulder"] + op_joints_ind = [config.JOINT_MAP[joint] for joint in op_joints] + gt_joints = ["RHip", "LHip", "RShoulder", "LShoulder"] + gt_joints_ind = [config.JOINT_MAP[joint] for joint in gt_joints] + + reprojection_error_op = ( + joints_2d[:, op_joints_ind] - projected_joints[:, op_joints_ind] + ) ** 2 + reprojection_error_gt = ( + joints_2d[:, gt_joints_ind] - projected_joints[:, gt_joints_ind] + ) ** 2 + + # Check if for each example in the batch all 4 OpenPose detections are valid, otherwise use the GT detections + # OpenPose joints are more reliable for this task, so we prefer to use them if possible + is_valid = (joints_conf[:, op_joints_ind].min(dim=-1)[0][:, None, None] > 0).float() + reprojection_loss = ( + is_valid * reprojection_error_op + (1 - is_valid) * reprojection_error_gt + ).sum(dim=(1, 2)) + + # Loss that penalizes deviation from depth estimate + depth_loss = (depth_loss_weight**2) * (camera_t[:, 2] - camera_t_est[:, 2]) ** 2 + + total_loss = reprojection_loss + depth_loss + return total_loss.sum() + + +# #####--- body fitiing loss ----- +def body_fitting_loss_3d( + body_pose, + preserve_pose, + betas, + model_joints, + camera_translation, + j3d, + pose_prior, + joints3d_conf, + sigma=100, + pose_prior_weight=4.78 * 1.5, + shape_prior_weight=5.0, + angle_prior_weight=15.2, + joint_loss_weight=500.0, + pose_preserve_weight=0.0, + use_collision=True, + model_vertices=None, + model_faces=None, + search_tree=None, + pen_distance=None, + filter_faces=None, + collision_loss_weight=1000, +): + """ + Loss function for body fitting + """ + batch_size = body_pose.shape[0] + + # joint3d_loss = (joint_loss_weight ** 2) * gmof((model_joints + camera_translation) - j3d, sigma).sum(dim=-1) + + joint3d_error = gmof((model_joints + camera_translation) - j3d, sigma) + + joint3d_loss_part = (joints3d_conf**2) * joint3d_error.sum(dim=-1) + joint3d_loss = ((joint_loss_weight**2) * joint3d_loss_part).sum(dim=-1) + + # Pose prior loss + pose_prior_loss = (pose_prior_weight**2) * pose_prior(body_pose, betas) + # Angle prior for knees and elbows + angle_prior_loss = (angle_prior_weight**2) * angle_prior(body_pose).sum(dim=-1) + # Regularizer to prevent betas from taking large values + shape_prior_loss = 0. #(shape_prior_weight**2) * (betas**2).sum(dim=-1) + + collision_loss = 0.0 + # Calculate the loss due to interpenetration + if use_collision: + triangles = torch.index_select(model_vertices, 1, model_faces).view( + batch_size, -1, 3, 3 + ) + + with torch.no_grad(): + collision_idxs = search_tree(triangles) + + # Remove unwanted collisions + if filter_faces is not None: + collision_idxs = filter_faces(collision_idxs) + + if collision_idxs.ge(0).sum().item() > 0: + collision_loss = torch.sum( + collision_loss_weight * pen_distance(triangles, collision_idxs) + ) + + pose_preserve_loss = 0. + # (pose_preserve_weight**2) * ( + # (body_pose - preserve_pose) ** 2 + # ).sum(dim=-1) + + # print('joint3d_loss', joint3d_loss.shape) + # print('pose_prior_loss', pose_prior_loss.shape) + # print('angle_prior_loss', angle_prior_loss.shape) + # print('shape_prior_loss', shape_prior_loss.shape) + # print('collision_loss', collision_loss) + # print('pose_preserve_loss', pose_preserve_loss.shape) + + total_loss = ( + joint3d_loss + + pose_prior_loss + + angle_prior_loss + + shape_prior_loss + + collision_loss + + pose_preserve_loss + ) + + return total_loss.sum() + + +# #####--- get camera fitting loss ----- +def camera_fitting_loss_3d( + model_joints, + camera_t, + camera_t_est, + j3d, + joints_category="orig", + depth_loss_weight=100.0, +): + """ + Loss function for camera optimization. + """ + model_joints = model_joints + camera_t + # # get the indexed four + # op_joints = ['OP RHip', 'OP LHip', 'OP RShoulder', 'OP LShoulder'] + # op_joints_ind = [config.JOINT_MAP[joint] for joint in op_joints] + # + # j3d_error_loss = (j3d[:, op_joints_ind] - + # model_joints[:, op_joints_ind]) ** 2 + + gt_joints = ["RHip", "LHip", "RShoulder", "LShoulder"] + gt_joints_ind = [config.JOINT_MAP[joint] for joint in gt_joints] + + if joints_category == "orig": + select_joints_ind = [config.JOINT_MAP[joint] for joint in gt_joints] + elif joints_category == "AMASS": + select_joints_ind = [config.AMASS_JOINT_MAP[joint] for joint in gt_joints] + else: + print("NO SUCH JOINTS CATEGORY!") + + j3d_error_loss = (j3d[:, select_joints_ind] - model_joints[:, gt_joints_ind]) ** 2 + + # Loss that penalizes deviation from depth estimate + depth_loss = (depth_loss_weight**2) * (camera_t - camera_t_est) ** 2 + + total_loss = j3d_error_loss + depth_loss + return total_loss.sum() diff --git a/src_joints2smpl_demo/skeleton2smpl/optimize/prior.py b/src_joints2smpl_demo/skeleton2smpl/optimize/prior.py new file mode 100644 index 0000000000000000000000000000000000000000..7f13806dd1f6607507b0c7e5ad463b3fb0026be8 --- /dev/null +++ b/src_joints2smpl_demo/skeleton2smpl/optimize/prior.py @@ -0,0 +1,230 @@ +# -*- coding: utf-8 -*- + +# Max-Planck-Gesellschaft zur Förderung der Wissenschaften e.V. (MPG) is +# holder of all proprietary rights on this computer program. +# You can only use this computer program if you have closed +# a license agreement with MPG or you get the right to use the computer +# program from someone who is authorized to grant you that right. +# Any use of the computer program without a valid license is prohibited and +# liable to prosecution. +# +# Copyright©2019 Max-Planck-Gesellschaft zur Förderung +# der Wissenschaften e.V. (MPG). acting on behalf of its Max Planck Institute +# for Intelligent Systems. All rights reserved. +# +# Contact: ps-license@tuebingen.mpg.de + +from __future__ import absolute_import +from __future__ import print_function +from __future__ import division + +import sys +import os + +import time +import pickle + +import numpy as np + +import torch +import torch.nn as nn + +DEFAULT_DTYPE = torch.float32 + + +def create_prior(prior_type, **kwargs): + if prior_type == 'gmm': + prior = MaxMixturePrior(**kwargs) + elif prior_type == 'l2': + return L2Prior(**kwargs) + elif prior_type == 'angle': + return SMPLifyAnglePrior(**kwargs) + elif prior_type == 'none' or prior_type is None: + # Don't use any pose prior + def no_prior(*args, **kwargs): + return 0.0 + prior = no_prior + else: + raise ValueError('Prior {}'.format(prior_type) + ' is not implemented') + return prior + + +class SMPLifyAnglePrior(nn.Module): + def __init__(self, dtype=torch.float32, **kwargs): + super(SMPLifyAnglePrior, self).__init__() + + # Indices for the roration angle of + # 55: left elbow, 90deg bend at -np.pi/2 + # 58: right elbow, 90deg bend at np.pi/2 + # 12: left knee, 90deg bend at np.pi/2 + # 15: right knee, 90deg bend at np.pi/2 + angle_prior_idxs = np.array([55, 58, 12, 15], dtype=np.int64) + angle_prior_idxs = torch.tensor(angle_prior_idxs, dtype=torch.long) + self.register_buffer('angle_prior_idxs', angle_prior_idxs) + + angle_prior_signs = np.array([1, -1, -1, -1], + dtype=np.float32 if dtype == torch.float32 + else np.float64) + angle_prior_signs = torch.tensor(angle_prior_signs, + dtype=dtype) + self.register_buffer('angle_prior_signs', angle_prior_signs) + + def forward(self, pose, with_global_pose=False): + ''' Returns the angle prior loss for the given pose + + Args: + pose: (Bx[23 + 1] * 3) torch tensor with the axis-angle + representation of the rotations of the joints of the SMPL model. + Kwargs: + with_global_pose: Whether the pose vector also contains the global + orientation of the SMPL model. If not then the indices must be + corrected. + Returns: + A sze (B) tensor containing the angle prior loss for each element + in the batch. + ''' + angle_prior_idxs = self.angle_prior_idxs - (not with_global_pose) * 3 + return torch.exp(pose[:, angle_prior_idxs] * + self.angle_prior_signs).pow(2) + + +class L2Prior(nn.Module): + def __init__(self, dtype=DEFAULT_DTYPE, reduction='sum', **kwargs): + super(L2Prior, self).__init__() + + def forward(self, module_input, *args): + return torch.sum(module_input.pow(2)) + + +class MaxMixturePrior(nn.Module): + + def __init__(self, prior_folder='prior', + num_gaussians=6, dtype=DEFAULT_DTYPE, epsilon=1e-16, + use_merged=True, + **kwargs): + super(MaxMixturePrior, self).__init__() + + if dtype == DEFAULT_DTYPE: + np_dtype = np.float32 + elif dtype == torch.float64: + np_dtype = np.float64 + else: + print('Unknown float type {}, exiting!'.format(dtype)) + sys.exit(-1) + + self.num_gaussians = num_gaussians + self.epsilon = epsilon + self.use_merged = use_merged + gmm_fn = 'gmm_{:02d}.pkl'.format(num_gaussians) + + full_gmm_fn = os.path.join(prior_folder, gmm_fn) + if not os.path.exists(full_gmm_fn): + print('The path to the mixture prior "{}"'.format(full_gmm_fn) + + ' does not exist, exiting!') + sys.exit(-1) + + with open(full_gmm_fn, 'rb') as f: + gmm = pickle.load(f, encoding='latin1') + + if type(gmm) == dict: + means = gmm['means'].astype(np_dtype) + covs = gmm['covars'].astype(np_dtype) + weights = gmm['weights'].astype(np_dtype) + elif 'sklearn.mixture.gmm.GMM' in str(type(gmm)): + means = gmm.means_.astype(np_dtype) + covs = gmm.covars_.astype(np_dtype) + weights = gmm.weights_.astype(np_dtype) + else: + print('Unknown type for the prior: {}, exiting!'.format(type(gmm))) + sys.exit(-1) + + self.register_buffer('means', torch.tensor(means, dtype=dtype)) + + self.register_buffer('covs', torch.tensor(covs, dtype=dtype)) + + precisions = [np.linalg.inv(cov) for cov in covs] + precisions = np.stack(precisions).astype(np_dtype) + + self.register_buffer('precisions', + torch.tensor(precisions, dtype=dtype)) + + # The constant term: + sqrdets = np.array([(np.sqrt(np.linalg.det(c))) + for c in gmm['covars']]) + const = (2 * np.pi)**(69 / 2.) + + nll_weights = np.asarray(gmm['weights'] / (const * + (sqrdets / sqrdets.min()))) + nll_weights = torch.tensor(nll_weights, dtype=dtype).unsqueeze(dim=0) + self.register_buffer('nll_weights', nll_weights) + + weights = torch.tensor(gmm['weights'], dtype=dtype).unsqueeze(dim=0) + self.register_buffer('weights', weights) + + self.register_buffer('pi_term', + torch.log(torch.tensor(2 * np.pi, dtype=dtype))) + + cov_dets = [np.log(np.linalg.det(cov.astype(np_dtype)) + epsilon) + for cov in covs] + self.register_buffer('cov_dets', + torch.tensor(cov_dets, dtype=dtype)) + + # The dimensionality of the random variable + self.random_var_dim = self.means.shape[1] + + def get_mean(self): + ''' Returns the mean of the mixture ''' + mean_pose = torch.matmul(self.weights, self.means) + return mean_pose + + def merged_log_likelihood(self, pose, betas): + diff_from_mean = pose.unsqueeze(dim=1) - self.means + + prec_diff_prod = torch.einsum('mij,bmj->bmi', + [self.precisions, diff_from_mean]) + diff_prec_quadratic = (prec_diff_prod * diff_from_mean).sum(dim=-1) + + curr_loglikelihood = 0.5 * diff_prec_quadratic - \ + torch.log(self.nll_weights) + # curr_loglikelihood = 0.5 * (self.cov_dets.unsqueeze(dim=0) + + # self.random_var_dim * self.pi_term + + # diff_prec_quadratic + # ) - torch.log(self.weights) + + min_likelihood, _ = torch.min(curr_loglikelihood, dim=1) + return min_likelihood + + def log_likelihood(self, pose, betas, *args, **kwargs): + ''' Create graph operation for negative log-likelihood calculation + ''' + likelihoods = [] + + for idx in range(self.num_gaussians): + mean = self.means[idx] + prec = self.precisions[idx] + cov = self.covs[idx] + diff_from_mean = pose - mean + + curr_loglikelihood = torch.einsum('bj,ji->bi', + [diff_from_mean, prec]) + curr_loglikelihood = torch.einsum('bi,bi->b', + [curr_loglikelihood, + diff_from_mean]) + cov_term = torch.log(torch.det(cov) + self.epsilon) + curr_loglikelihood += 0.5 * (cov_term + + self.random_var_dim * + self.pi_term) + likelihoods.append(curr_loglikelihood) + + log_likelihoods = torch.stack(likelihoods, dim=1) + min_idx = torch.argmin(log_likelihoods, dim=1) + weight_component = self.nll_weights[:, min_idx] + weight_component = -torch.log(weight_component) + + return weight_component + log_likelihoods[:, min_idx] + + def forward(self, pose, betas): + if self.use_merged: + return self.merged_log_likelihood(pose, betas) + else: + return self.log_likelihood(pose, betas) \ No newline at end of file diff --git a/src_joints2smpl_demo/skeleton2smpl/optimize/smplify.py b/src_joints2smpl_demo/skeleton2smpl/optimize/smplify.py new file mode 100644 index 0000000000000000000000000000000000000000..ab5e04b27b175880e15a0889621d3d935bb53c45 --- /dev/null +++ b/src_joints2smpl_demo/skeleton2smpl/optimize/smplify.py @@ -0,0 +1,283 @@ +import os +import sys + +import numpy as np +import torch +import torch.nn as nn +import smplx +import json +import time +import pickle + +from datetime import datetime +from datetime import timedelta + +from . import config +from .customloss import ( + body_fitting_loss_3d, + camera_fitting_loss_3d, +) +from .prior import MaxMixturePrior + + +@torch.no_grad() +def guess_init_3d(model_joints, j3d, joints_category="orig"): + """Initialize the camera translation via triangle similarity, by using the torso joints . + :param model_joints: SMPL model with pre joints + :param j3d: 25x3 array of Kinect Joints + :returns: 3D vector corresponding to the estimated camera translation + """ + # get the indexed four + gt_joints = ["RHip", "LHip", "RShoulder", "LShoulder"] + gt_joints_ind = [config.JOINT_MAP[joint] for joint in gt_joints] + + if joints_category == "orig": + joints_ind_category = [config.JOINT_MAP[joint] for joint in gt_joints] + elif joints_category == "AMASS": + joints_ind_category = [config.AMASS_JOINT_MAP[joint] for joint in gt_joints] + else: + print("NO SUCH JOINTS CATEGORY!") + + sum_init_t = (j3d[:, joints_ind_category] - model_joints[:, gt_joints_ind]).sum( + dim=1 + ) + init_t = sum_init_t / 4.0 + return init_t + + +# SMPLIfy 3D +class SMPLify3D: + """Implementation of SMPLify, use 3D joints.""" + + def __init__( + self, + smplxmodel, + step_size=1e-2, + num_iters=100, + joints_category="orig", + device=torch.device("cuda:0"), + GMM_MODEL_DIR="./joint2smpl_models/", + ): + + # Store options + self.device = device + self.step_size = step_size + + self.num_iters = num_iters + + # GMM pose prior + self.pose_prior = MaxMixturePrior( + prior_folder=GMM_MODEL_DIR, num_gaussians=8, dtype=torch.float32 + ).to(device) + + # reLoad SMPL-X model + self.smpl = smplxmodel + + self.model_faces = smplxmodel.faces_tensor.view(-1) + + # select joint joint_category + self.joints_category = joints_category + + if joints_category == "orig": + self.smpl_index = config.full_smpl_idx + self.corr_index = config.full_smpl_idx + elif joints_category == "AMASS": + self.smpl_index = config.amass_smpl_idx + self.corr_index = config.amass_idx + else: + self.smpl_index = None + self.corr_index = None + print("NO SUCH JOINTS CATEGORY!") + + # ---- get the man function here ------ + def __call__(self, init_pose, init_betas, init_cam_t, j3d, conf_3d=1.0, fix_betas=0, if_simple_hmp_optimizes=False, num_iters=None): + """Perform body fitting. + Input: + init_pose: SMPL pose estimate + init_betas: SMPL betas estimate + init_cam_t: Camera translation estimate + j3d: joints 3d aka keypoints + conf_3d: confidence for 3d joints + seq_ind: index of the sequence + Returns: + vertices: Vertices of optimized shape + joints: 3D joints of optimized shape + pose: SMPL pose parameters of optimized shape + betas: SMPL beta parameters of optimized shape + camera_translation: Camera translation + """ + + # # # add the mesh inter-section to avoid + search_tree = None + pen_distance = None + filter_faces = None + self.t0 = datetime.now() + + # Split SMPL pose to body pose and global orientation + body_pose = init_pose[:, 3:].detach().clone() + global_orient = init_pose[:, :3].detach().clone() + betas = init_betas.detach().clone() + camera_translation = init_cam_t.clone() + + preserve_pose = init_pose[:, 3:].detach().clone() + + # -------------Step 1: Optimize camera translation and body orientation-------- + # Optimize only camera translation and body orientation + body_pose.requires_grad = False + betas.requires_grad = False + global_orient.requires_grad = True + if not if_simple_hmp_optimizes: + camera_translation.requires_grad = True + + camera_opt_params = [global_orient, camera_translation] + + # camera_optimizer = torch.optim.LBFGS( + # camera_opt_params, + # max_iter=self.num_iters, + # lr=self.step_size, + # line_search_fn="strong_wolfe", + # ) + # for i in range(10): + + # def closure(): + # camera_optimizer.zero_grad() + # smpl_output = self.smpl( + # global_orient=global_orient, body_pose=body_pose, betas=betas + # ) + # model_joints = smpl_output.joints + # loss = camera_fitting_loss_3d( + # model_joints, + # camera_translation, + # init_cam_t, + # j3d, + # self.joints_category, + # ) + # loss.backward() + # return loss + + # camera_optimizer.step(closure) + + camera_optimizer = torch.optim.Adam( + camera_opt_params, lr=self.step_size, betas=(0.9, 0.999) + ) + + for i in range(10): + smpl_output = self.smpl( + global_orient=global_orient, body_pose=body_pose, betas=betas + ) + model_joints = smpl_output.joints + + loss = camera_fitting_loss_3d( + model_joints[:, self.smpl_index], + camera_translation, + init_cam_t, + j3d[:, self.corr_index], + self.joints_category, + ) + camera_optimizer.zero_grad() + loss.backward() + camera_optimizer.step() + + self.t = datetime.now() - self.t0 + self.t0 = datetime.now() + print(f"Step 0: Average time in seconds: {self.t/timedelta(seconds=1)}") + + # Fix camera translation after optimizing camera + # --------Step 2: Optimize body joints -------------------------- + # Optimize only the body pose and global orientation of the body + body_pose.requires_grad = True + global_orient.requires_grad = True + if not if_simple_hmp_optimizes: + camera_translation.requires_grad = True + # --- if we use the sequence, fix the shape + if not fix_betas: + betas.requires_grad = True + body_opt_params = [body_pose, betas, global_orient, camera_translation] + else: + betas.requires_grad = False + body_opt_params = [body_pose, global_orient, camera_translation] + + num_iters = self.num_iters if num_iters is None else num_iters + + + body_optimizer = torch.optim.LBFGS( + body_opt_params, + max_iter=num_iters, + lr=self.step_size, + line_search_fn="strong_wolfe", + ) + for i in range(num_iters): + + def closure(): + body_optimizer.zero_grad() + smpl_output = self.smpl( + global_orient=global_orient, body_pose=body_pose, betas=betas + ) + model_joints = smpl_output.joints + model_vertices = smpl_output.vertices + + loss = body_fitting_loss_3d( + body_pose, + preserve_pose, + betas, + model_joints[:, self.smpl_index], + camera_translation, + j3d[:, self.corr_index], + self.pose_prior, + joints3d_conf=conf_3d, + joint_loss_weight=600.0, + pose_preserve_weight=5.0, + use_collision=False, + model_vertices=model_vertices, + model_faces=self.model_faces, + search_tree=search_tree, + pen_distance=pen_distance, + filter_faces=filter_faces, + ) + loss.backward() + return loss + + body_optimizer.step(closure) + # body_optimizer = torch.optim.Adam( + # body_opt_params, lr=1.e-4, betas=(0.9, 0.999) + # ) + + # for i in range(num_iters): + # smpl_output = self.smpl( + # global_orient=global_orient, body_pose=body_pose, betas=betas + # ) + # model_joints = smpl_output.joints + # model_vertices = smpl_output.vertices + + # loss = body_fitting_loss_3d( + # body_pose, + # preserve_pose, + # betas, + # model_joints[:, self.smpl_index], + # camera_translation, + # j3d[:, self.corr_index], + # self.pose_prior, + # joints3d_conf=conf_3d, + # joint_loss_weight=600.0, + # use_collision=False, + # model_vertices=model_vertices, + # model_faces=self.model_faces, + # search_tree=search_tree, + # pen_distance=pen_distance, + # filter_faces=filter_faces, + # ) + # body_optimizer.zero_grad() + # loss.backward() + # body_optimizer.step() + self.t = datetime.now() - self.t0 + self.t0 = datetime.now() + print(f"Step2: Average time in seconds: {self.t/timedelta(seconds=1)}") + smpl_output = self.smpl( + global_orient=global_orient, body_pose=body_pose, betas=betas + ) + vertices = smpl_output.vertices.detach() + joints = smpl_output.joints.detach() + pose = torch.cat([global_orient, body_pose], dim=-1).detach() + betas = betas.detach() + + return vertices, joints, pose, betas, camera_translation diff --git a/src_joints2smpl_demo/skeleton2smpl/skeleton2smpl.py b/src_joints2smpl_demo/skeleton2smpl/skeleton2smpl.py new file mode 100644 index 0000000000000000000000000000000000000000..57829a9f8666ee1bd0f65af523bd8b5e31a88de4 --- /dev/null +++ b/src_joints2smpl_demo/skeleton2smpl/skeleton2smpl.py @@ -0,0 +1,143 @@ +import numpy as np +import smplx +import torch + +from .optimize.smplify import SMPLify3D + +class joints2smpl: + def __init__( + self, + device, + num_smplify_iters=150, + SMPL_MODEL_DIR= "./body_models/", + GMM_MODEL_DIR="./joint2smpl_models/", + ): + self.device = torch.device(device) + # self.batch_size = num_frames + self.num_joints = 22 # for HumanML3D + self.joint_category = "AMASS" + self.num_smplify_iters = num_smplify_iters + self.fix_foot = False + smplmodel = smplx.create( SMPL_MODEL_DIR, model_type="smpl", gender="neutral", ext="pkl").to(self.device) + # smplmodel = smplx.create( + # SMPL_MODEL_DIR, model_type="smpl", gender="female", ext="pkl" + # ).to(self.device) + + + # # #-------------initialize SMPLify + # self.smplify = SMPLify3D(smplxmodel=smplmodel, batch_size=self.batch_size, joints_category=self.joint_category, num_iters=self.num_smplify_iters, device=self.device) + self.smplify = SMPLify3D( + smplxmodel=smplmodel, + # batch_size=self.batch_size, + joints_category=self.joint_category, + num_iters=self.num_smplify_iters, + device=self.device, + GMM_MODEL_DIR=GMM_MODEL_DIR + ) + + def joint2smpl(self, input_joints, init_params=None, hmp=True, fix_betas=False): + batch_size = input_joints.shape[0] + + _smplify = self.smplify # if init_params is None else self.smplify_fast + pred_pose = torch.zeros(batch_size, 72).to(self.device) + pred_betas = torch.zeros(1, 10).expand(batch_size, 10).to(self.device) + pred_cam_t = torch.zeros(1, 3).expand(batch_size, 3).to(self.device) + keypoints_3d = torch.Tensor(input_joints).to(self.device).float() + + if init_params is None: + # assert 0, "Not implemented. Missing init pose." + pred_betas = ( + torch.tensor([ 1.47646511e+00, 4.79749501e-01, -6.36047006e-01, -1.52980864e+00, + -1.11884427e+00, -5.40487289e-01, 3.93005997e-01, -1.88832569e+00, + -2.78680950e-01, -5.49529344e-02]) + .unsqueeze(0) + .repeat(batch_size, 1) + .float() + .to(self.device) + ) + pred_pose = (torch.tensor([ 0.4531, 0.3044, 0.2968, -0.2239, 0.0174, 0.0925, -0.2378, -0.0465, + -0.0786, 0.2782, 0.0141, 0.0138, 0.4328, -0.0629, -0.0961, 0.5043, + 0.0035, 0.0610, 0.0230, -0.0317, 0.0058, 0.0070, 0.1317, -0.0544, + -0.0589, -0.1752, 0.1355, 0.0134, -0.0037, 0.0089, -0.2093, 0.1600, + 0.1092, -0.0387, 0.0824, -0.2041, -0.0056, -0.0075, -0.0035, -0.0237, + -0.1248, -0.2736, -0.0459, 0.1991, 0.2373, 0.0667, -0.0405, 0.0329, + 0.0536, -0.2914, -0.6969, 0.0559, 0.2858, 0.6525, 0.1222, -0.9116, + 0.2383, -0.0366, 0.9237, -0.2554, -0.0657, -0.1045, 0.0501, -0.0388, + 0.0909, -0.0707, -0.1437, -0.0590, -0.1801, -0.0875, 0.1093, 0.2009]) + .unsqueeze(0) + .repeat(batch_size, 1) + .float().to(self.device) + ) + pred_cam_t = torch.Tensor([0.0, 0.0, 0.0]).unsqueeze(0).to(self.device) + else: + pred_betas = init_params["betas"] + pred_pose = init_params["pose"] + pred_cam_t = init_params["cam"] + + if self.joint_category == "AMASS": + confidence_input = torch.ones(self.num_joints) + # make sure the foot and ankle + if self.fix_foot == True: + confidence_input[7] = 1.5 + confidence_input[8] = 1.5 + confidence_input[10] = 1.5 + confidence_input[11] = 1.5 + else: + print("Such category not settle down!") + + ( + new_opt_vertices, + new_opt_joints, + new_opt_pose, + new_opt_betas, + new_opt_cam_t, + ) = _smplify( + pred_pose.detach(), + pred_betas.detach(), + pred_cam_t.detach(), + keypoints_3d, + conf_3d=confidence_input.to(self.device), + if_simple_hmp_optimizes=hmp, + fix_betas=fix_betas, + ) + + # thetas = new_opt_pose.reshape(batch_size, 24, 3) + # thetas = matrix_to_rotation_6d( + # axis_angle_to_matrix(thetas) + # ) # [bs, 24, 6] + # # root_loc = torch.tensor(keypoints_3d[:, 0]) # [bs, 3] + # root_loc = keypoints_3d[:, 0].clone() # [bs, 3] + # root_loc = torch.cat([root_loc, torch.zeros_like(root_loc)], dim=-1).unsqueeze( + # 1 + # ) # [bs, 1, 6] + # thetas = torch.cat([thetas, root_loc], dim=1).permute(1, 2, 0) # [25, 6, 196] + # thetas = thetas.clone().detach() + + return new_opt_pose, { + "pose": new_opt_joints[..., :24, :].clone().detach(), + "betas": new_opt_betas.clone().detach(), + "cam": new_opt_cam_t.clone().detach(), + } + + +class Skeleton2Obj: + def __init__( + self, + device: str = "cpu", + num_smplify_iters=150, + smpl_model_dir="./body_models/", + gmm_model_dir="./joint2smpl_models/", + ): + self.simplify = joints2smpl( + device=device, + num_smplify_iters=num_smplify_iters, + SMPL_MODEL_DIR=smpl_model_dir, + GMM_MODEL_DIR=gmm_model_dir, + ) + + + def convert_motion_2smpl(self, motion, hmp=True, init_params=None, fix_betas=False) -> tuple[np.ndarray, np.ndarray]: + new_opt_rot, smpl_dict = self.simplify.joint2smpl(motion, hmp=hmp, init_params=init_params, fix_betas=fix_betas) + return new_opt_rot, smpl_dict + + diff --git a/src_joints2smpl_demo/smpl_params.json b/src_joints2smpl_demo/smpl_params.json new file mode 100644 index 0000000000000000000000000000000000000000..a0eae468893dc5f6628202a3ee689cf251c29d0f --- /dev/null +++ b/src_joints2smpl_demo/smpl_params.json @@ -0,0 +1 @@ +[{"global_orient": [[2.2353639602661133, 0.5916082262992859, -2.0327951908111572]], "body_pose": [[2.2353639602661133, 0.5916082262992859, -2.0327951908111572, -0.26305410265922546, 0.08902715146541595, 0.09117331355810165, -0.05655479058623314, 0.04682581126689911, -0.01659121923148632, 0.45540982484817505, -0.1787641942501068, -0.07187502831220627, 0.2193027287721634, 0.25553441047668457, -0.3057701289653778, 0.1958557516336441, 0.005155149847269058, 0.014121451415121555, -0.41809433698654175, -0.13902220129966736, 0.06221805512905121, 0.36002030968666077, 0.08064822852611542, 0.460913747549057, 0.10167539119720459, -0.30014097690582275, 0.3377859890460968, 0.3045009672641754, -0.09085783362388611, -0.08533435314893723, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.06574763357639313, 0.28167012333869934, -0.1680668443441391, -0.0705965906381607, -0.20237112045288086, -0.2343149185180664, -0.01083776168525219, -0.0001827423693612218, 0.2799582779407501, 0.2929314374923706, 0.5344237685203552, 0.1061825156211853, 0.07086415588855743, -0.4138922095298767, -0.5436715483665466, 0.37014240026474, 0.028073973953723907, 0.6175993084907532, 0.16316932439804077, -0.8743170499801636, 0.12068434059619904, 0.465713232755661, 1.0935436487197876, 0.12945294380187988, 0.31020206212997437, -0.09817531704902649, -0.3071029484272003, -0.03342866152524948, 0.3974432647228241, 0.10624181479215622, -0.8437318205833435, -0.7268637418746948, -1.7195913791656494, -0.016427934169769287, 1.2334325313568115, 2.978780746459961]], "betas": [[-0.0653349757194519, 0.40031492710113525, 0.0064461855217814445, 0.006632731296122074, -0.0005867599975317717, 0.0020345754455775023, 0.0006958516896702349, 0.0004315990663599223, 0.0008820535149425268, 0.0018546266946941614]], "transl": [[0.08144085109233856, 0.2040172815322876, -0.03253182768821716]], "joints3d": [[[141.80471801757812, 41.47804260253906, 4334.14892578125], [124.33297729492188, 143.77825927734375, 4288.140625], [114.94854736328125, 110.38762664794922, 4417.53662109375], [198.94204711914062, -51.289817810058594, 4317.3681640625], [-72.38935852050781, 468.312744140625, 4280.80712890625], [-25.781085968017578, 449.594970703125, 4539.5029296875], [178.44288635253906, -178.79055786132812, 4275.77490234375], [-205.78907775878906, 792.2427978515625, 4477.27783203125], [-58.17890548706055, 841.090087890625, 4623.69384765625], [170.66845703125, -234.88735961914062, 4263.8388671875], [-300.054443359375, 865.4716796875, 4416.384765625], [-180.06175231933594, 882.2303466796875, 4662.29150390625], [204.5257110595703, -435.69610595703125, 4192.82958984375], [171.4949951171875, -326.5673522949219, 4149.62353515625], [231.270751953125, -366.0614929199219, 4289.4111328125], [152.94703674316406, -494.14739990234375, 4162.06689453125], [129.38661193847656, -310.4590148925781, 4066.320556640625], [274.5198974609375, -397.52685546875, 4374.0478515625], [-26.52853012084961, -104.32209777832031, 4024.87744140625], [374.3701477050781, -244.80401611328125, 4552.05322265625], [-252.0554656982422, -80.77853393554688, 4128.4453125], [217.28558349609375, -63.53163146972656, 4640.7412109375]]]}, {"global_orient": [[2.257370710372925, 0.6186651587486267, -2.0379908084869385]], "body_pose": [[2.257370710372925, 0.6186651587486267, -2.0379908084869385, -0.2586197257041931, 0.07666215300559998, 0.0869029238820076, -0.058811403810977936, 0.03884667903184891, -0.035998519510030746, 0.46462708711624146, -0.18830759823322296, -0.08404269814491272, 0.17168289422988892, 0.1717434525489807, -0.23843622207641602, 0.18351352214813232, -0.03202147036790848, 0.030121810734272003, -0.40591421723365784, -0.1294901818037033, 0.07251285016536713, 0.31160420179367065, 0.19219352304935455, 0.40370187163352966, 0.14671535789966583, -0.25569289922714233, 0.36649027466773987, 0.27055051922798157, -0.09845957905054092, -0.09555293619632721, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.10085640102624893, 0.3193235993385315, -0.17837180197238922, -0.04256043955683708, -0.14295537769794464, -0.19247186183929443, 0.05435086041688919, -0.08769051730632782, 0.24733135104179382, 0.27851513028144836, 0.471311092376709, 0.13143716752529144, 0.03438277915120125, -0.5616598725318909, -0.502616286277771, 0.4564470946788788, 0.020264092832803726, 0.6773005723953247, 0.09616831690073013, -0.7586352229118347, 0.09192964434623718, 0.5190503001213074, 1.2030930519104004, 0.0707821175456047, 0.24333418905735016, -0.20705796778202057, -0.0382726676762104, -0.03993036597967148, 0.12864787876605988, -0.10077527910470963, 0.8130937814712524, 1.0592856407165527, 3.2031021118164062, -0.6200879216194153, 1.0541778802871704, 2.2149336338043213]], "betas": [[0.2257874608039856, 0.7976201176643372, 0.0070418561808764935, 0.0065337372943758965, -0.0003705936251208186, 0.002129638334736228, 0.0008112085051834583, 0.0003385836025699973, 0.0007344859768636525, 0.0016554809408262372]], "transl": [[0.0841391310095787, 0.20458386838436127, -0.022622568532824516]], "joints3d": [[[124.98410034179688, 33.84196472167969, 4352.52685546875], [108.82579040527344, 137.9703369140625, 4311.00634765625], [99.4366226196289, 101.56155395507812, 4436.81396484375], [181.42022705078125, -60.13700485229492, 4332.869140625], [-91.6550064086914, 472.0746765136719, 4313.20263671875], [-44.968868255615234, 442.7558288574219, 4579.6572265625], [156.7119598388672, -188.440185546875, 4285.2265625], [-233.75152587890625, 814.6910400390625, 4493.259765625], [-83.82560729980469, 842.2334594726562, 4673.8876953125], [149.1092529296875, -244.56687927246094, 4271.34521484375], [-329.1922912597656, 881.5775756835938, 4421.94873046875], [-207.0977020263672, 888.125732421875, 4712.2744140625], [180.45294189453125, -443.95025634765625, 4191.7763671875], [148.7561798095703, -331.6077880859375, 4153.1337890625], [209.35353088378906, -377.1490173339844, 4291.02392578125], [130.63088989257812, -502.81884765625, 4153.482421875], [110.3235092163086, -314.9340515136719, 4067.572998046875], [258.9703674316406, -415.7432556152344, 4370.134765625], [-72.21871185302734, -121.74047088623047, 4036.308349609375], [393.0921630859375, -265.1884765625, 4534.6474609375], [-308.8516845703125, -101.83120727539062, 4129.83447265625], [240.3374786376953, -70.50052642822266, 4620.03466796875]]]}, {"global_orient": [[2.2137064933776855, 0.6107713580131531, -2.0382792949676514]], "body_pose": [[2.2137064933776855, 0.6107713580131531, -2.0382792949676514, -0.21188361942768097, 0.08077166974544525, 0.0762668326497078, -0.05384232476353645, 0.04757464677095413, -0.013819646090269089, 0.48798513412475586, -0.2448304295539856, -0.12049611657857895, 0.10254490375518799, 0.08771661669015884, -0.2624400854110718, 0.18873989582061768, -0.07311903685331345, -0.009923001751303673, -0.45778584480285645, -0.12849707901477814, 0.09478405863046646, 0.44293516874313354, 0.2017519474029541, 0.3891269564628601, 0.13474780321121216, -0.2734219431877136, 0.4477704167366028, 0.2775344252586365, -0.11066154390573502, -0.10317016392946243, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.027308547869324684, 0.3472782373428345, -0.15595322847366333, -0.012558726593852043, -0.03762747347354889, -0.20623181760311127, 0.12257794290781021, -0.1961980015039444, 0.30460888147354126, 0.27687811851501465, 0.49492666125297546, 0.1757468283176422, 0.012768101878464222, -0.5071491599082947, -0.4035767614841461, 0.3118673861026764, 0.009973171167075634, 0.40152427554130554, 0.1268501877784729, -0.8923612236976624, 0.01512850634753704, 0.21670043468475342, 1.0780795812606812, 0.011508235707879066, 0.2948550283908844, -0.15426793694496155, 0.14656253159046173, 0.16882185637950897, -0.26937657594680786, 0.0527004599571228, -0.9083040952682495, -0.3110595643520355, -1.209275722503662, -0.23318670690059662, 1.005785346031189, 2.7750816345214844]], "betas": [[-0.145146444439888, 1.059788703918457, 0.00777006521821022, 0.006816289387643337, -0.0002771026047412306, 0.002536633051931858, 0.0008006906718946993, 0.0006750734755769372, 0.0015789634780958295, 0.0013999936636537313]], "transl": [[0.0749533399939537, 0.20319437980651855, -0.024718808010220528]], "joints3d": [[[102.35285186767578, 29.756778717041016, 4252.6123046875], [85.11763763427734, 130.7344970703125, 4209.419921875], [78.0677261352539, 98.24578094482422, 4333.73828125], [156.34033203125, -61.28706741333008, 4235.18017578125], [-106.50273895263672, 464.4393615722656, 4212.20166015625], [-69.90271759033203, 438.3677978515625, 4459.21484375], [130.4461212158203, -187.60797119140625, 4190.552734375], [-255.60073852539062, 797.7673950195312, 4385.6357421875], [-113.37235260009766, 830.294677734375, 4546.56982421875], [125.71678161621094, -242.50094604492188, 4177.7236328125], [-353.3816223144531, 868.5244140625, 4328.025390625], [-233.8936309814453, 873.8818969726562, 4584.74560546875], [163.777587890625, -435.1402893066406, 4098.1142578125], [123.40003967285156, -327.827392578125, 4063.626953125], [193.95587158203125, -367.04461669921875, 4191.71044921875], [111.5736083984375, -494.75811767578125, 4066.605224609375], [86.44908142089844, -313.29620361328125, 3980.399658203125], [256.7537536621094, -395.98553466796875, 4260.54931640625], [-93.48631286621094, -131.84576416015625, 3918.660888671875], [415.1119384765625, -279.4101867675781, 4423.33447265625], [-320.6202392578125, -122.078857421875, 4021.72802734375], [302.6921081542969, -154.49899291992188, 4617.341796875]]]}, {"global_orient": [[2.3817310333251953, 0.6260557174682617, -1.9126743078231812]], "body_pose": [[2.3817310333251953, 0.6260557174682617, -1.9126743078231812, -0.2882048189640045, 0.07864946126937866, 0.07792236655950546, -0.04153049364686012, 0.055879633873701096, -0.0015293114120140672, 0.48115524649620056, -0.2566428482532501, -0.10394474118947983, 0.23093819618225098, 0.12077966332435608, -0.30907464027404785, 0.16417552530765533, -0.05041143670678139, 0.021193811669945717, -0.4606209099292755, -0.18764784932136536, 0.07998109608888626, 0.323670357465744, 0.1908722221851349, 0.4291815161705017, 0.11262166500091553, -0.3483351767063141, 0.44528791308403015, 0.2745427191257477, -0.13304108381271362, -0.0996861532330513, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.04007406905293465, 0.3575316369533539, -0.1415591984987259, -0.01832648180425167, -0.052311766892671585, -0.16918717324733734, 0.10483746230602264, -0.29191476106643677, 0.22533397376537323, 0.25058597326278687, 0.4798450767993927, 0.18836964666843414, -0.02109443210065365, -0.5845598578453064, -0.47410935163497925, 0.25719892978668213, -0.030826231464743614, 0.3602112829685211, 0.1479281187057495, -0.830298125743866, 0.07436241954565048, 0.2083824723958969, 1.0461856126785278, 0.010187676176428795, 0.21645282208919525, -0.20237934589385986, 0.06409040093421936, 0.16431881487369537, -0.2937156558036804, 0.12431428581476212, 1.3183095455169678, 0.8420199155807495, 3.403687000274658, -0.4574921131134033, 0.6649783253669739, 1.3834930658340454]], "betas": [[-0.08256397396326065, 1.3140965700149536, 0.007359118666499853, 0.005409999284893274, -0.00045194762060418725, 0.002407170133665204, 0.0006494427798315883, 0.0006459940341301262, 0.0014333390863612294, 0.0012855796376243234]], "transl": [[0.07137517631053925, 0.2076934576034546, -0.020605653524398804]], "joints3d": [[[74.33299255371094, 26.125099182128906, 4222.38525390625], [66.95023345947266, 129.90658569335938, 4184.86474609375], [44.09589385986328, 91.2353515625, 4303.44140625], [125.43850708007812, -66.32452392578125, 4205.6396484375], [-136.91778564453125, 460.7630615234375, 4174.55712890625], [-102.11560821533203, 436.1404113769531, 4429.86279296875], [100.00907897949219, -190.58792114257812, 4152.408203125], [-280.49822998046875, 784.8609008789062, 4376.09423828125], [-143.0355682373047, 830.844970703125, 4521.52734375], [96.15155029296875, -244.51290893554688, 4136.28955078125], [-371.2658386230469, 857.7911987304688, 4308.95263671875], [-266.16009521484375, 876.8008422851562, 4549.42236328125], [135.43917846679688, -433.49462890625, 4050.0244140625], [97.69343566894531, -324.3297119140625, 4019.201171875], [162.82064819335938, -369.2917785644531, 4146.8876953125], [85.25625610351562, -492.99285888671875, 4012.900634765625], [62.9914436340332, -309.64141845703125, 3935.473876953125], [228.91432189941406, -406.7878723144531, 4207.60595703125], [-128.5369110107422, -130.63888549804688, 3898.392822265625], [405.9710388183594, -318.7908935546875, 4371.525390625], [-361.5643005371094, -138.18038940429688, 3992.23974609375], [324.2450866699219, -232.0519256591797, 4600.966796875]]]}, {"global_orient": [[2.3790035247802734, 0.6164579391479492, -1.9129290580749512]], "body_pose": [[2.3790035247802734, 0.6164579391479492, -1.9129290580749512, -0.2950431704521179, 0.08766961842775345, 0.09763146936893463, -0.056807588785886765, 0.053216177970170975, -0.01026968564838171, 0.4534338116645813, -0.23958534002304077, -0.09911402314901352, 0.2749287188053131, 0.13056805729866028, -0.3768998980522156, 0.1657845377922058, 0.018368003889918327, 0.0037216583732515574, -0.41611045598983765, -0.16000792384147644, 0.07110307365655899, 0.2949064373970032, 0.18790484964847565, 0.42014139890670776, 0.1169661208987236, -0.3590032458305359, 0.43089497089385986, 0.2648591697216034, -0.13967984914779663, -0.10372143238782883, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.04562170431017876, 0.3270804286003113, -0.12846605479717255, -0.013166367076337337, -0.04799198731780052, -0.16240540146827698, 0.13052035868167877, -0.2985006868839264, 0.1937038004398346, 0.2677251100540161, 0.48508191108703613, 0.1331017166376114, -0.04693484306335449, -0.5395301580429077, -0.43514731526374817, 0.25280240178108215, -0.07381061464548111, 0.30849969387054443, 0.15274986624717712, -0.7869316935539246, 0.15294918417930603, 0.2026916742324829, 1.1006088256835938, -0.008409949950873852, 0.24372629821300507, -0.34747233986854553, 0.20648683607578278, 0.10393789410591125, -0.18708419799804688, 0.14327092468738556, 0.8896384835243225, 0.667075514793396, 3.0614967346191406, -0.49553778767585754, 0.5616487264633179, 1.3347654342651367]], "betas": [[0.1138690933585167, 1.1714036464691162, 0.006788833998143673, 0.004691769368946552, -0.000905791821423918, 0.0023279543966054916, 0.0005891147302463651, 0.0006631477735936642, 0.001442774198949337, 0.0011963652214035392]], "transl": [[0.06991211324930191, 0.21750105917453766, -0.019368162378668785]], "joints3d": [[[46.792236328125, 25.027559280395508, 4233.2373046875], [38.71457290649414, 129.46783447265625, 4194.4228515625], [15.649561882019043, 91.24081420898438, 4314.6171875], [100.0153579711914, -68.8551025390625, 4217.13623046875], [-164.9416046142578, 462.9169921875, 4173.5947265625], [-136.30967712402344, 436.91485595703125, 4441.2119140625], [78.10223388671875, -195.3159637451172, 4163.94189453125], [-300.4995422363281, 781.8117065429688, 4396.49072265625], [-184.12258911132812, 832.519287109375, 4544.65185546875], [73.0517807006836, -250.1376190185547, 4147.89404296875], [-393.79638671875, 857.480224609375, 4332.861328125], [-309.8890686035156, 877.8838500976562, 4570.060546875], [110.54055786132812, -442.7431640625, 4062.18212890625], [75.83750915527344, -331.38458251953125, 4029.019775390625], [137.151123046875, -378.52191162109375, 4161.4990234375], [60.09410858154297, -502.8010559082031, 4025.325439453125], [44.20771026611328, -315.7135009765625, 3942.507080078125], [201.3644256591797, -420.8128356933594, 4224.04248046875], [-140.29730224609375, -132.21725463867188, 3881.563720703125], [392.1260986328125, -357.81097412109375, 4388.21630859375], [-388.93878173828125, -136.44949340820312, 3934.691650390625], [309.9939880371094, -280.0521240234375, 4623.70458984375]]]}, {"global_orient": [[2.403393268585205, 0.6190027594566345, -1.8582292795181274]], "body_pose": [[2.403393268585205, 0.6190027594566345, -1.8582292795181274, -0.2905692756175995, 0.06981834024190903, 0.0914372131228447, -0.03128525987267494, 0.0384339764714241, -0.040272194892168045, 0.488325297832489, -0.24525025486946106, -0.10657601803541183, 0.22196871042251587, 0.11050856113433838, -0.2929489314556122, 0.15346267819404602, 0.00021397415548563004, 0.006975309457629919, -0.4692673087120056, -0.17823505401611328, 0.07319428771734238, 0.34767964482307434, 0.17568376660346985, 0.378888338804245, 0.1832713931798935, -0.30736836791038513, 0.48836851119995117, 0.29272332787513733, -0.12608106434345245, -0.11482933163642883, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.0873793289065361, 0.2946929931640625, -0.15482451021671295, -0.01675410382449627, -0.0394337922334671, -0.11393047869205475, 0.13991102576255798, -0.32063961029052734, 0.14438414573669434, 0.2914316952228546, 0.513804018497467, 0.17630216479301453, -0.06128179281949997, -0.5490398406982422, -0.5628988742828369, 0.24667641520500183, -0.005629697348922491, 0.29477283358573914, 0.04406575486063957, -0.7246240377426147, 0.29480355978012085, 0.20156759023666382, 1.1214271783828735, 0.1324608474969864, -0.028417225927114487, -0.21397581696510315, 0.16995911300182343, 0.05841127410531044, -0.2409333884716034, 0.031382784247398376, -0.16516132652759552, 0.9345273971557617, 2.671260118484497, -0.5165746808052063, 0.5639410018920898, 1.9940273761749268]], "betas": [[0.15915976464748383, 1.2466437816619873, 0.008964400738477707, 0.005094605498015881, -0.0009094741544686258, 0.002549488330259919, 0.00045810232404619455, 0.0004511824809014797, 0.0015161026967689395, 0.001174175995402038]], "transl": [[0.07187455892562866, 0.21625109016895294, -0.013389858417212963]], "joints3d": [[[18.328805923461914, 26.10003662109375, 4224.6201171875], [11.141901969909668, 130.44021606445312, 4185.56689453125], [-16.2108154296875, 92.4475326538086, 4304.3837890625], [72.70763397216797, -67.6437759399414, 4210.7880859375], [-195.45700073242188, 463.6659240722656, 4158.8671875], [-168.68299865722656, 436.890869140625, 4438.833984375], [48.6722412109375, -193.67535400390625, 4156.0185546875], [-351.2145080566406, 800.1063232421875, 4342.56689453125], [-220.6793975830078, 832.1618041992188, 4548.22802734375], [46.074581146240234, -248.51498413085938, 4139.24951171875], [-443.43719482421875, 872.9378662109375, 4273.40869140625], [-344.6813049316406, 886.3988647460938, 4566.078125], [85.0926742553711, -440.19659423828125, 4051.7666015625], [51.55906677246094, -328.1060791015625, 4019.36474609375], [109.62378692626953, -377.1694030761719, 4152.5419921875], [37.650882720947266, -500.9028015136719, 4011.2265625], [23.23145866394043, -315.42901611328125, 3931.1875], [172.98167419433594, -424.4354553222656, 4212.50732421875], [-155.30384826660156, -120.49057006835938, 3885.77099609375], [355.08624267578125, -377.6755065917969, 4392.5283203125], [-410.0417785644531, -133.0377960205078, 3895.71630859375], [257.9721374511719, -284.1077880859375, 4617.41357421875]]]}, {"global_orient": [[2.3962209224700928, 0.5927565097808838, -1.8249449729919434]], "body_pose": [[2.3962209224700928, 0.5927565097808838, -1.8249449729919434, -0.25720536708831787, 0.0645982176065445, 0.06184481456875801, -0.0313095785677433, 0.042045701295137405, -0.0303865447640419, 0.5110312104225159, -0.2105301320552826, -0.12228385359048843, 0.18519465625286102, 0.11061417311429977, -0.2749151587486267, 0.15796196460723877, -0.009551961906254292, -0.016357656568288803, -0.48297932744026184, -0.16651949286460876, 0.06280353665351868, 0.3967891335487366, 0.1841113418340683, 0.378207266330719, 0.1704401820898056, -0.3040603697299957, 0.47442325949668884, 0.28801095485687256, -0.13982388377189636, -0.11705772578716278, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.12449970096349716, 0.2683669924736023, -0.15756329894065857, -0.02698948234319687, -0.05755547434091568, -0.14769349992275238, 0.09825858473777771, -0.2748200595378876, 0.16738668084144592, 0.3091398775577545, 0.5302367210388184, 0.2128640115261078, -0.052217036485672, -0.48482513427734375, -0.5874305963516235, 0.38159531354904175, -0.05030496418476105, 0.3748100996017456, 0.13895036280155182, -0.8325015306472778, 0.20039980113506317, 0.29351526498794556, 1.476853370666504, 0.01169038750231266, 0.19500334560871124, -0.11614782363176346, 0.03706108778715134, 0.0048329089768230915, -0.03362192213535309, 0.1607246994972229, 0.7017892599105835, 0.8559486269950867, 2.85507869720459, -0.301071435213089, 0.7734834551811218, 2.558934211730957]], "betas": [[0.06768818944692612, 1.168286681175232, 0.008750716224312782, 0.005513379815965891, -0.0005506359739229083, 0.0027564833872020245, 0.0005200064624659717, 0.00018181953055318445, 0.00143380684312433, 0.0012215556344017386]], "transl": [[0.07649296522140503, 0.20844385027885437, -0.00831868126988411]], "joints3d": [[[-13.373895645141602, 23.469804763793945, 4188.419921875], [-20.36097526550293, 126.36610412597656, 4145.86328125], [-50.0889778137207, 91.5909423828125, 4265.59765625], [41.597137451171875, -69.81993103027344, 4178.5126953125], [-220.7303009033203, 460.403076171875, 4121.318359375], [-205.45411682128906, 438.0986633300781, 4382.12548828125], [17.567785263061523, -194.97036743164062, 4124.177734375], [-381.615478515625, 796.8472900390625, 4293.45068359375], [-261.0758056640625, 831.8960571289062, 4483.42529296875], [14.719598770141602, -249.47006225585938, 4107.09716796875], [-470.4854431152344, 872.13916015625, 4224.10888671875], [-385.7349853515625, 883.0936889648438, 4499.1064453125], [57.35860061645508, -440.0724182128906, 4020.48291015625], [25.639192581176758, -328.1434326171875, 3987.390869140625], [76.96626281738281, -378.1830749511719, 4122.47119140625], [14.067748069763184, -501.512451171875, 3977.74267578125], [0.005209088325500488, -312.02484130859375, 3899.28271484375], [134.83787536621094, -423.9738464355469, 4188.1455078125], [-162.49623107910156, -105.89188385009766, 3852.992431640625], [307.3215026855469, -358.5694580078125, 4369.57421875], [-413.4362487792969, -109.03722381591797, 3888.738037109375], [127.2293701171875, -249.4510955810547, 4522.8974609375]]]}, {"global_orient": [[2.4450457096099854, 0.5464101433753967, -1.7803274393081665]], "body_pose": [[2.4450457096099854, 0.5464101433753967, -1.7803274393081665, -0.3066248893737793, 0.06392261385917664, 0.08082667738199234, -0.06799629330635071, 0.026352452114224434, -0.014786096289753914, 0.4704083502292633, -0.1871851086616516, -0.09939009696245193, 0.1987021267414093, 0.07508457452058792, -0.2646014988422394, 0.13727685809135437, 0.017589058727025986, -0.033307529985904694, -0.4408753514289856, -0.1326783001422882, 0.04654059559106827, 0.42347607016563416, 0.16857700049877167, 0.2923314571380615, 0.17292779684066772, -0.3054574131965637, 0.40613436698913574, 0.267301082611084, -0.12711264193058014, -0.12384220957756042, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.0914292261004448, 0.24325165152549744, -0.16103100776672363, -0.008574610576033592, -0.06856701523065567, -0.18701431155204773, 0.054954614490270615, -0.20645935833454132, 0.20867231488227844, 0.26848724484443665, 0.4782910645008087, 0.1729283630847931, -0.04705977067351341, -0.32926812767982483, -0.4676397740840912, 0.37808993458747864, -0.04099727421998978, 0.490736186504364, 0.1553797870874405, -0.9191376566886902, 0.15786893665790558, 0.34866631031036377, 1.4277355670928955, -0.1567002683877945, 0.21640466153621674, -0.132181316614151, -0.029249314218759537, -0.17951402068138123, 0.4500373303890228, 0.6651360988616943, -1.098103404045105, -0.6924648880958557, -1.3501112461090088, -0.7896775603294373, 0.7435082197189331, 2.4602901935577393]], "betas": [[0.2735428810119629, 1.0670156478881836, 0.008556242100894451, 0.005068575497716665, -0.00037200411316007376, 0.002424017759039998, 0.0006442863959819078, -2.8563461455632932e-05, 0.0012818692484870553, 0.0010503657395020127]], "transl": [[0.08053963631391525, 0.20816928148269653, 0.003229299560189247]], "joints3d": [[[-45.16545867919922, 24.444929122924805, 4231.99853515625], [-47.915740966796875, 127.98194122314453, 4187.853515625], [-83.89571380615234, 94.9356460571289, 4307.55712890625], [9.363151550292969, -71.84133911132812, 4225.40234375], [-250.32559204101562, 461.63983154296875, 4137.90283203125], [-245.02235412597656, 448.518798828125, 4405.44580078125], [-11.065603256225586, -200.0705108642578, 4172.81494140625], [-417.12213134765625, 812.16650390625, 4286.1513671875], [-315.7504577636719, 847.6531372070312, 4496.0205078125], [-15.047826766967773, -255.56356811523438, 4156.1083984375], [-508.53057861328125, 887.9558715820312, 4217.44677734375], [-444.2613220214844, 895.2339477539062, 4507.45458984375], [29.229469299316406, -450.69879150390625, 4074.020751953125], [5.692831516265869, -336.3464660644531, 4036.482177734375], [40.41659164428711, -388.55047607421875, 4179.2216796875], [-14.606879234313965, -510.2413330078125, 4028.091064453125], [-11.073723793029785, -315.46026611328125, 3945.624267578125], [85.16951751708984, -433.3092041015625, 4257.39208984375], [-131.373291015625, -95.71595001220703, 3846.76611328125], [218.1205596923828, -335.1921691894531, 4460.19091796875], [-387.3277282714844, -75.95403289794922, 3846.044921875], [5.958057403564453, -236.94737243652344, 4581.6279296875]]]}, {"global_orient": [[2.4422338008880615, 0.5623804330825806, -1.7672269344329834]], "body_pose": [[2.4422338008880615, 0.5623804330825806, -1.7672269344329834, -0.2865629494190216, 0.06728846579790115, 0.06310847401618958, -0.060178495943546295, 0.024158071726560593, -0.04136746749281883, 0.4423900842666626, -0.18771040439605713, -0.05550384894013405, 0.1586044877767563, 0.08141058683395386, -0.24115023016929626, 0.10880427062511444, 0.002468578750267625, -0.03756345435976982, -0.41488999128341675, -0.12432559579610825, 0.030383257195353508, 0.5009115934371948, 0.15002229809761047, 0.2117595672607422, 0.27590230107307434, -0.2743656635284424, 0.3863705098628998, 0.291545569896698, -0.10224977880716324, -0.1218557357788086, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.11186067014932632, 0.26609182357788086, -0.20295487344264984, -0.011131939478218555, -0.14975076913833618, -0.18747466802597046, 0.012316171079874039, -0.07868850976228714, 0.23055461049079895, 0.2496061772108078, 0.5157802700996399, 0.2118716537952423, 0.03223263844847679, -0.3616061806678772, -0.6670125722885132, 0.34579095244407654, 0.012442146427929401, 0.6155191659927368, 0.11252904683351517, -0.8789706230163574, 0.20060470700263977, 0.31811243295669556, 1.1575959920883179, -0.11356894671916962, 0.1793700009584427, -0.090451680123806, -0.07090403139591217, -0.1657966673374176, 0.528651237487793, 1.6350263357162476, 0.08470365405082703, 0.9489048719406128, 3.1120223999023438, -0.41602301597595215, -0.08765018731355667, 3.7714827060699463]], "betas": [[0.379775732755661, 0.7706508636474609, 0.009797689504921436, 0.0044625066220760345, -0.0011779036140069366, 0.002393339527770877, 0.0009567261440679431, -0.0002559579152148217, 0.0010060104541480541, 0.0018588700331747532]], "transl": [[0.08365294337272644, 0.20768876373767853, -0.015396841801702976]], "joints3d": [[[-77.00627136230469, 31.346288681030273, 4237.6240234375], [-81.76747131347656, 135.72030639648438, 4192.30712890625], [-118.8104248046875, 101.36823272705078, 4314.01513671875], [-18.70125961303711, -65.03858184814453, 4231.66015625], [-283.52813720703125, 469.9815368652344, 4151.9638671875], [-283.4803161621094, 449.7309875488281, 4421.98974609375], [-33.65846633911133, -196.37850952148438, 4184.5087890625], [-462.73236083984375, 817.328369140625, 4295.15966796875], [-370.63397216796875, 844.5933837890625, 4520.9873046875], [-37.6932373046875, -253.1247100830078, 4169.173828125], [-556.5009765625, 899.1154174804688, 4235.751953125], [-497.33892822265625, 898.3530883789062, 4535.6171875], [5.217637062072754, -453.58343505859375, 4092.9658203125], [-15.05566120147705, -338.7866516113281, 4050.39794921875], [14.344120979309082, -388.82745361328125, 4198.66357421875], [-37.11811065673828, -511.1935119628906, 4043.9677734375], [-35.456722259521484, -319.72705078125, 3958.25537109375], [45.59987258911133, -431.4129333496094, 4286.193359375], [-149.53077697753906, -80.88671112060547, 3905.55517578125], [130.1199188232422, -297.1050720214844, 4495.2724609375], [-402.7206726074219, -41.4542121887207, 3933.42138671875], [-72.56832885742188, -177.15548706054688, 4614.92333984375]]]}, {"global_orient": [[2.4888410568237305, 0.5312364101409912, -1.7432180643081665]], "body_pose": [[2.4888410568237305, 0.5312364101409912, -1.7432180643081665, -0.3357033431529999, 0.013471473008394241, 0.07999453693628311, -0.10107343643903732, -0.0027502640150487423, -0.06944775581359863, 0.4010993242263794, -0.13723790645599365, -0.06496204435825348, 0.13216295838356018, 0.08556952327489853, -0.18557769060134888, 0.08918026089668274, -0.03958997502923012, -0.01227466482669115, -0.4079445004463196, -0.09576824307441711, -0.01787162385880947, 0.48837730288505554, 0.1485176533460617, 0.0984734520316124, 0.354616641998291, -0.18888676166534424, 0.39977920055389404, 0.33516740798950195, -0.06686469912528992, -0.11194320023059845, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.13895292580127716, 0.13022112846374512, -0.232809379696846, -0.1064596101641655, -0.23079858720302582, -0.27816763520240784, -0.16935664415359497, 0.14793556928634644, 0.2532074749469757, 0.23854096233844757, 0.528749942779541, 0.2292843908071518, 0.1359134465456009, -0.31569162011146545, -0.7603520154953003, 0.23171614110469818, 0.04241035133600235, 0.77265465259552, 0.2769825756549835, -0.9261451363563538, 0.1527387797832489, 0.44339531660079956, 1.0397275686264038, 0.23556405305862427, 0.19842661917209625, 0.025530900806188583, -0.13010789453983307, -0.13496452569961548, 0.14506083726882935, 2.479975700378418, -0.6988457441329956, -0.5858420729637146, -1.8819907903671265, -0.21227599680423737, -0.5152068734169006, 3.298184394836426]], "betas": [[0.33812135457992554, 0.03237362578511238, 0.008686973713338375, 0.006029418669641018, -0.0014730767579749227, 0.0025016150902956724, 0.0015418941620737314, -0.0002286370872752741, 0.0005794575554318726, 0.0034729146864265203]], "transl": [[0.09115420281887054, 0.2070433348417282, -0.010205302387475967]], "joints3d": [[[-113.66932678222656, 39.589351654052734, 4206.53271484375], [-115.51238250732422, 145.29464721679688, 4158.53125], [-158.88653564453125, 110.08201599121094, 4284.138671875], [-54.332218170166016, -58.95072937011719, 4202.5458984375], [-315.32232666015625, 469.1221923828125, 4107.134765625], [-325.4864807128906, 448.4096374511719, 4391.7666015625], [-63.246002197265625, -188.0553436279297, 4153.61474609375], [-497.5811767578125, 821.6638793945312, 4209.40234375], [-422.5333251953125, 837.4603881835938, 4478.95263671875], [-68.10692596435547, -244.379150390625, 4133.80712890625], [-595.5255126953125, 895.3638305664062, 4148.0009765625], [-546.715576171875, 896.9292602539062, 4486.5], [-23.51938819885254, -444.3592834472656, 4049.54296875], [-34.084625244140625, -325.4403991699219, 4010.333984375], [-26.605493545532227, -387.636474609375, 4162.0693359375], [-63.45928192138672, -497.4634094238281, 3997.373046875], [-46.897117614746094, -290.32330322265625, 3919.393310546875], [-27.34505271911621, -434.95440673828125, 4254.8544921875], [-140.5911102294922, -40.812381744384766, 3912.5712890625], [-49.7166862487793, -278.74530029296875, 4461.62060546875], [-382.7899169921875, 5.71324348449707, 3978.013916015625], [-250.2040557861328, -111.67503356933594, 4465.3740234375]]]}, {"global_orient": [[2.5142886638641357, 0.5321655869483948, -1.7255388498306274]], "body_pose": [[2.5142886638641357, 0.5321655869483948, -1.7255388498306274, -0.32389163970947266, -0.02838778682053089, 0.01853042095899582, -0.11770614981651306, -0.033685293048620224, -0.11140553653240204, 0.37270471453666687, -0.10240112990140915, -0.05153453350067139, 0.11922188848257065, 0.07374877482652664, -0.17793940007686615, 0.10170622915029526, 0.006451799534261227, -0.0341046005487442, -0.3564493954181671, -0.07495304197072983, -0.0011687723454087973, 0.41184887290000916, 0.2535746991634369, 0.08429393917322159, 0.3284435272216797, -0.11081753671169281, 0.34219425916671753, 0.276629775762558, -0.04424159973859787, -0.0827636867761612, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.1702393889427185, 0.13821159303188324, -0.1975681036710739, -0.027611803263425827, -0.19094359874725342, -0.30064764618873596, -0.15198738873004913, 0.1656835377216339, 0.2995232343673706, 0.2824753224849701, 0.38144877552986145, 0.2113172858953476, 0.10704734176397324, -0.2894984483718872, -0.6917743682861328, 0.37303221225738525, 0.09611301124095917, 0.8565053939819336, 0.4120931625366211, -1.1070003509521484, -0.056395433843135834, 0.34947511553764343, 1.2538995742797852, 0.04243279993534088, 0.3225373327732086, -0.043823082000017166, -0.36151307821273804, -0.3735502064228058, 0.4624849557876587, 1.3305948972702026, -0.7247670292854309, -0.3450983762741089, -0.8151542544364929, 0.08069271594285965, 0.3017650246620178, 3.55257511138916]], "betas": [[0.38036322593688965, 0.5226633548736572, 0.004743653815239668, 0.005804938729852438, -0.0004760767915286124, 0.0021916653495281935, 0.0011010757880285382, -5.249198147794232e-05, 0.00028922551427967846, 0.0024756616912782192]], "transl": [[0.09206463396549225, 0.20452234148979187, -0.01300326082855463]], "joints3d": [[[-152.0196075439453, 52.927642822265625, 4230.8046875], [-151.25082397460938, 158.54649353027344, 4186.1865234375], [-195.6172637939453, 123.1654281616211, 4307.234375], [-95.8961181640625, -45.8160285949707, 4225.9541015625], [-359.3472900390625, 487.0572814941406, 4157.47509765625], [-373.5268859863281, 456.7259826660156, 4431.0185546875], [-102.51908874511719, -176.29190063476562, 4176.2158203125], [-545.1819458007812, 836.494873046875, 4280.58056640625], [-479.6208190917969, 840.8770141601562, 4545.65625], [-107.61557006835938, -232.1334686279297, 4156.95361328125], [-643.1459350585938, 907.8971557617188, 4215.1884765625], [-607.1211547851562, 894.51318359375, 4549.314453125], [-59.014549255371094, -434.40240478515625, 4086.033203125], [-62.385013580322266, -317.4335632324219, 4042.904296875], [-71.9171371459961, -372.6156005859375, 4193.89794921875], [-91.19137573242188, -492.9444274902344, 4031.883544921875], [-63.23897171020508, -284.5680236816406, 3951.580810546875], [-86.38082885742188, -412.5077819824219, 4287.74365234375], [-132.54428100585938, -27.414823532104492, 3913.685791015625], [-120.8156509399414, -224.1102752685547, 4466.3955078125], [-365.3500671386719, 25.041522979736328, 4009.458984375], [-327.95721435546875, -84.10909271240234, 4383.64599609375]]]}, {"global_orient": [[2.5938849449157715, 0.5391424894332886, -1.6484967470169067]], "body_pose": [[2.5938849449157715, 0.5391424894332886, -1.6484967470169067, -0.3567308783531189, -0.03600127622485161, 0.019654538482427597, -0.107634037733078, -0.044179659336805344, -0.15168175101280212, 0.34609171748161316, -0.05679847300052643, -0.040942855179309845, 0.12933090329170227, 0.16916777193546295, -0.1639377772808075, 0.0660509392619133, 0.09444664418697357, 0.01273462362587452, -0.3439462184906006, -0.07615701109170914, -0.009484599344432354, 0.3951842784881592, 0.18734194338321686, 0.13993367552757263, 0.3071805536746979, -0.09518049657344818, 0.39076292514801025, 0.2776995301246643, -0.01504533551633358, -0.06497177481651306, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.15678316354751587, 0.14755286276340485, -0.1686391532421112, -0.011017085053026676, -0.20964553952217102, -0.3047131896018982, -0.14326047897338867, 0.1810627430677414, 0.333933562040329, 0.24210487306118011, 0.3098628520965576, 0.19630151987075806, 0.13777704536914825, -0.37357068061828613, -0.7406164407730103, 0.35230398178100586, 0.18805432319641113, 0.942807137966156, 0.5558640956878662, -1.2144395112991333, -0.05956697463989258, 0.3664293885231018, 1.3212552070617676, -0.05635778605937958, 0.09170298278331757, 0.1015721783041954, -0.6081796884536743, 0.20726656913757324, -0.2481302171945572, 0.25396621227264404, -0.430988073348999, -0.5512126684188843, -0.2628111243247986, 0.48694393038749695, 1.1257816553115845, 2.669429063796997]], "betas": [[0.32564905285835266, 0.5683928728103638, 0.004931608214974403, 0.0053374576382339, -0.0003843029262498021, 0.001887527760118246, 0.00105401617474854, -5.52700694242958e-05, 0.00016702171706128865, 0.0019934007432311773]], "transl": [[0.09266659617424011, 0.20444825291633606, -0.006209063809365034]], "joints3d": [[[-188.21409606933594, 62.517574310302734, 4226.1416015625], [-182.61822509765625, 169.1763916015625, 4185.35986328125], [-235.12283325195312, 130.96414184570312, 4301.71826171875], [-134.1762237548828, -36.66395568847656, 4221.52392578125], [-392.2917785644531, 495.07696533203125, 4148.2236328125], [-415.41265869140625, 456.6258850097656, 4439.87158203125], [-135.96939086914062, -165.7270050048828, 4168.8310546875], [-590.7633666992188, 838.6333618164062, 4264.1298828125], [-531.0551147460938, 835.7474365234375, 4557.68359375], [-139.7680206298828, -220.5945587158203, 4147.416015625], [-680.2224731445312, 910.0009765625, 4188.24169921875], [-655.8800659179688, 891.5384521484375, 4539.85107421875], [-87.8404769897461, -422.3267517089844, 4079.80615234375], [-81.82283782958984, -304.9896240234375, 4039.487060546875], [-113.67610931396484, -362.1419982910156, 4185.61962890625], [-115.06861114501953, -479.4328918457031, 4021.715576171875], [-71.23367309570312, -270.5660705566406, 3949.869384765625], [-144.1916961669922, -399.91973876953125, 4275.83642578125], [-142.45928955078125, -12.921430587768555, 3926.373046875], [-205.56800842285156, -191.30471801757812, 4420.5283203125], [-369.8981628417969, 11.468282699584961, 4042.062744140625], [-389.6084289550781, -76.72957611083984, 4272.291015625]]]}, {"global_orient": [[2.6090641021728516, 0.5052034854888916, -1.5619349479675293]], "body_pose": [[2.6090641021728516, 0.5052034854888916, -1.5619349479675293, -0.36430275440216064, -0.056276097893714905, -0.020129213109612465, -0.14298824965953827, -0.028537720441818237, -0.11466751247644424, 0.36216792464256287, -0.0674305260181427, -0.0298283863812685, 0.15740206837654114, 0.11349167674779892, -0.16851788759231567, 0.10701338946819305, 0.10612641274929047, -0.024039963260293007, -0.33070486783981323, -0.0618404820561409, -0.018001798540353775, 0.4858658015727997, 0.1857590228319168, 0.11310851573944092, 0.3128364086151123, -0.12361638247966766, 0.29002344608306885, 0.25454068183898926, -0.00456360774114728, -0.04708901047706604, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.17153503000736237, 0.09882150590419769, -0.18981939554214478, -0.006404859479516745, -0.2543850839138031, -0.3240264356136322, -0.14576047658920288, 0.2262648046016693, 0.31824710965156555, 0.2976534962654114, 0.29972004890441895, 0.16709350049495697, 0.12263111025094986, -0.35010480880737305, -0.7579631805419922, 0.2905975580215454, 0.2510906755924225, 0.957528829574585, 0.5576749444007874, -1.1990957260131836, -0.09022046625614166, 0.35046666860580444, 1.2898038625717163, -0.039451420307159424, -0.004309547133743763, -0.15038524568080902, -0.5847898125648499, 0.20871026813983917, 0.06849605590105057, 0.17369280755519867, 0.7950544357299805, 0.6867409944534302, 2.9452080726623535, 0.22411593794822693, 1.1000109910964966, 2.876452922821045]], "betas": [[0.5058374404907227, 0.595978319644928, 0.004893986042588949, 0.005299006123095751, -0.00018673054000828415, 0.0017587481997907162, 0.0009452640661038458, -1.822726881073322e-05, -9.640044481784571e-06, 0.0020255299750715494]], "transl": [[0.09979516267776489, 0.2095702439546585, 0.00047687027836218476]], "joints3d": [[[-222.82208251953125, 68.82970428466797, 4346.76318359375], [-215.1240997314453, 174.69448852539062, 4302.87451171875], [-274.30419921875, 140.2314910888672, 4417.25390625], [-167.5657501220703, -31.44985008239746, 4348.85986328125], [-434.41815185546875, 497.5388488769531, 4254.57177734375], [-471.643798828125, 475.47650146484375, 4515.43115234375], [-169.43531799316406, -163.83702087402344, 4300.2578125], [-635.4166870117188, 846.8163452148438, 4367.0107421875], [-594.519775390625, 862.529541015625, 4616.96728515625], [-173.2784423828125, -219.7926788330078, 4279.99267578125], [-727.492431640625, 925.4666748046875, 4299.14990234375], [-722.1639404296875, 915.4984741210938, 4597.7734375], [-120.9749526977539, -427.0252685546875, 4224.62890625], [-109.10212707519531, -310.7012023925781, 4179.30078125], [-153.0452880859375, -361.07928466796875, 4326.72607421875], [-144.9220428466797, -487.4744567871094, 4167.25048828125], [-95.59972381591797, -278.3441162109375, 4088.2177734375], [-195.2665557861328, -396.0728759765625, 4414.72216796875], [-163.93045043945312, -17.60831069946289, 4058.34423828125], [-284.5572814941406, -176.5581512451172, 4531.001953125], [-397.103515625, 15.738788604736328, 4167.12890625], [-452.2198791503906, -75.54104614257812, 4351.4345703125]]]}, {"global_orient": [[2.573232412338257, 0.5302432775497437, -1.5322927236557007]], "body_pose": [[2.573232412338257, 0.5302432775497437, -1.5322927236557007, -0.3379521369934082, -0.05946778506040573, -0.010528993792831898, -0.10660403966903687, -0.06034759432077408, -0.1575600653886795, 0.40222787857055664, -0.015550083480775356, -0.011113439686596394, 0.1511579304933548, 0.11264770478010178, -0.15448735654354095, 0.0662197694182396, 0.07752692699432373, 0.008974400348961353, -0.34159180521965027, -0.06785836815834045, -0.03890600427985191, 0.4146321415901184, 0.2821404039859772, 0.0830756276845932, 0.35604652762413025, -0.03153524175286293, 0.2718493342399597, 0.290984183549881, -0.01271792408078909, -0.03903697058558464, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.17556142807006836, 0.15241459012031555, -0.17786189913749695, -0.042616404592990875, -0.3099539577960968, -0.30328452587127686, -0.2092025727033615, 0.316106379032135, 0.2831145226955414, 0.2588980197906494, 0.31116658449172974, 0.1608434021472931, 0.12619145214557648, -0.3546251058578491, -0.7749994993209839, 0.36318421363830566, 0.25791409611701965, 0.8073980212211609, 0.5701619982719421, -1.4724992513656616, -0.04491317272186279, 0.4805629849433899, 1.5215774774551392, 0.06635959446430206, -0.14876492321491241, -0.21185027062892914, -0.8087869882583618, 0.05099086835980415, -0.10850081592798233, 0.7779536843299866, 0.3199981153011322, 0.7758054733276367, 3.1507930755615234, -0.15720902383327484, 1.0361607074737549, 2.435560464859009]], "betas": [[0.4473535716533661, 0.3334096372127533, 0.004721098113805056, 0.00509998295456171, -0.00032115000067278743, 0.0021277957130223513, 0.0013733517844229937, 0.0002834831248037517, -3.123040369246155e-05, 0.0027950394432991743]], "transl": [[0.09735998511314392, 0.21905910968780518, -0.0006382165011018515]], "joints3d": [[[-254.11448669433594, 83.42861938476562, 4281.30322265625], [-250.3084716796875, 188.64535522460938, 4233.81591796875], [-310.334228515625, 154.1100311279297, 4350.0224609375], [-194.04209899902344, -14.418285369873047, 4286.806640625], [-470.3117980957031, 505.16510009765625, 4179.1083984375], [-511.02777099609375, 479.0965270996094, 4459.826171875], [-194.74105834960938, -146.61001586914062, 4240.875], [-673.7980346679688, 853.462646484375, 4276.2919921875], [-649.4497680664062, 859.9775390625, 4550.54833984375], [-198.117919921875, -202.6230010986328, 4220.14599609375], [-760.8646850585938, 925.6954345703125, 4196.958984375], [-776.515869140625, 911.5114135742188, 4528.10400390625], [-148.48765563964844, -411.46295166015625, 4166.216796875], [-132.80746459960938, -295.4229736328125, 4120.64111328125], [-182.86810302734375, -345.20941162109375, 4267.7275390625], [-170.92584228515625, -470.06689453125, 4107.7734375], [-119.79974365234375, -265.1424865722656, 4028.28759765625], [-234.85169982910156, -382.4011535644531, 4349.82763671875], [-193.7586669921875, -8.300882339477539, 3994.84326171875], [-362.3224182128906, -193.9265594482422, 4480.66748046875], [-414.9150695800781, -44.819522857666016, 4122.17333984375], [-445.90850830078125, -85.94547271728516, 4254.962890625]]]}, {"global_orient": [[2.6157307624816895, 0.4957706928253174, -1.4072688817977905]], "body_pose": [[2.6157307624816895, 0.4957706928253174, -1.4072688817977905, -0.35549822449684143, -0.07030901312828064, -0.038551632314920425, -0.10831456631422043, -0.051153890788555145, -0.16116215288639069, 0.4037722647190094, 0.001826710533350706, 0.009476149454712868, 0.1914997100830078, 0.1417255699634552, -0.18612156808376312, 0.10279043018817902, 0.11674672365188599, -0.0011197385611012578, -0.3274064064025879, -0.06630653142929077, -0.0609540119767189, 0.5350801348686218, 0.24290063977241516, 0.08635944873094559, 0.35814520716667175, -0.04358374699950218, 0.22558583319187164, 0.29441362619400024, -0.01285410113632679, -0.01354574877768755, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2058183252811432, 0.07823127508163452, -0.19334959983825684, -0.018019920215010643, -0.41950011253356934, -0.2650574743747711, -0.17266373336315155, 0.413343220949173, 0.27505818009376526, 0.2984426021575928, 0.2764280438423157, 0.1400349885225296, 0.05901270732283592, -0.40173330903053284, -0.7758088111877441, 0.291303426027298, 0.561870276927948, 0.8033002614974976, 0.5005823373794556, -1.668323040008545, -0.09265623241662979, 0.5592142343521118, 1.5577621459960938, 0.1488317996263504, -0.5182155966758728, -0.5304226279258728, -0.8967516422271729, 0.007419619709253311, 0.17020496726036072, 0.4425521194934845, 0.8250004649162292, 0.43320760130882263, 3.014055013656616, -0.536746084690094, 0.6962441802024841, 3.050813913345337]], "betas": [[0.39904025197029114, 0.2954466640949249, 0.002363075502216816, 0.0048659443855285645, 2.6615001843310893e-05, 0.0020197697449475527, 0.0012259065406396985, 0.0012624927330762148, -0.0004005441442131996, 0.0036114046815782785]], "transl": [[0.09436272084712982, 0.22790519893169403, 0.01154338102787733]], "joints3d": [[[-284.8189392089844, 93.70511627197266, 4326.0537109375], [-276.0206604003906, 197.783935546875, 4276.87646484375], [-346.647705078125, 165.86961364746094, 4388.0107421875], [-226.2445831298828, -4.019176006317139, 4338.89306640625], [-497.8807373046875, 507.25457763671875, 4202.60546875], [-555.02685546875, 491.8150634765625, 4472.69970703125], [-224.7350311279297, -137.2643585205078, 4297.8447265625], [-708.7056884765625, 849.109130859375, 4300.3623046875], [-689.598388671875, 873.7156372070312, 4557.61572265625], [-227.35906982421875, -193.2235565185547, 4277.2099609375], [-790.84765625, 934.2042846679688, 4229.7392578125], [-813.0086059570312, 928.2103271484375, 4526.28173828125], [-179.8334197998047, -404.8618469238281, 4234.98828125], [-155.4157257080078, -291.16204833984375, 4188.0458984375], [-222.37013244628906, -334.4652404785156, 4330.10595703125], [-198.18783569335938, -466.1532897949219, 4178.353515625], [-142.06591796875, -268.2011413574219, 4093.834228515625], [-291.67547607421875, -367.369140625, 4400.04443359375], [-228.50775146484375, -19.12102508544922, 4043.06787109375], [-457.2943420410156, -167.8477783203125, 4435.08251953125], [-428.6108703613281, -104.12757110595703, 4179.896484375], [-407.69720458984375, -85.35386657714844, 4190.44287109375]]]}, {"global_orient": [[2.6582694053649902, 0.504100501537323, -1.331891417503357]], "body_pose": [[2.6582694053649902, 0.504100501537323, -1.331891417503357, -0.3475719690322876, -0.07600262016057968, -0.0717725083231926, -0.09969331324100494, -0.043225862085819244, -0.18277998268604279, 0.41608697175979614, 0.0425943024456501, 0.02265111729502678, 0.19446676969528198, 0.1692901849746704, -0.1715727001428604, 0.11291231215000153, 0.17019930481910706, 0.004663769621402025, -0.34131741523742676, -0.06117420271039009, -0.07464329898357391, 0.5050041675567627, 0.28905755281448364, 0.1356942504644394, 0.37192580103874207, -0.07298939675092697, 0.2822243869304657, 0.29740187525749207, -0.0011729806428775191, 0.00736774317920208, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.1934206783771515, 0.09508828818798065, -0.14688584208488464, -0.04835285618901253, -0.48238620162010193, -0.23357921838760376, -0.22494839131832123, 0.48978692293167114, 0.20641417801380157, 0.27060872316360474, 0.23192527890205383, 0.13853099942207336, -0.02459908463060856, -0.4366109371185303, -0.8041858673095703, 0.27074500918388367, 0.5718395709991455, 0.8468202352523804, 0.5227636694908142, -1.5984201431274414, -0.027913369238376617, 0.5839671492576599, 1.7683297395706177, -0.004779548849910498, -0.4491444528102875, -0.6358134746551514, -1.4498796463012695, -0.21832840144634247, -0.05560294911265373, -0.0808461457490921, 0.5538157820701599, 0.3833003342151642, 2.911649465560913, -0.9171470403671265, 0.6336010694503784, 1.724023461341858]], "betas": [[0.19851796329021454, 0.4921376407146454, 0.0019476620946079493, 0.004234508611261845, -0.00027675399906001985, 0.001796049764379859, 0.001254855189472437, 0.0013438386376947165, -0.00037916647852398455, 0.0033159798476845026]], "transl": [[0.09334255754947662, 0.22991915047168732, 0.019090984016656876]], "joints3d": [[[-304.0183410644531, 97.4016342163086, 4294.75244140625], [-292.12982177734375, 201.2947235107422, 4249.0439453125], [-367.74566650390625, 167.93943786621094, 4354.07080078125], [-248.39695739746094, 0.8698292970657349, 4308.00732421875], [-514.58984375, 508.9609680175781, 4179.82080078125], [-581.8822021484375, 486.8302917480469, 4439.82861328125], [-246.2235870361328, -130.37142944335938, 4264.9931640625], [-730.1566772460938, 842.405517578125, 4279.6123046875], [-719.1321411132812, 860.6885375976562, 4535.375], [-246.85964965820312, -184.80747985839844, 4243.1171875], [-800.6119384765625, 929.3986206054688, 4201.9892578125], [-835.219970703125, 921.6967163085938, 4496.73876953125], [-199.4447784423828, -394.1023864746094, 4204.77734375], [-168.52548217773438, -281.9328308105469, 4163.31640625], [-249.88978576660156, -324.25128173828125, 4293.5517578125], [-214.27822875976562, -455.3695373535156, 4147.5390625], [-150.03941345214844, -263.0325622558594, 4070.97802734375], [-327.83331298828125, -362.8423156738281, 4346.3857421875], [-253.9365997314453, -24.933408737182617, 4013.1591796875], [-498.7085876464844, -168.05845642089844, 4346.763671875], [-466.8024597167969, -117.74061584472656, 4116.06494140625], [-378.1920471191406, -132.4736328125, 4118.77734375]]]}, {"global_orient": [[2.6940643787384033, 0.5160543918609619, -1.237664818763733]], "body_pose": [[2.6940643787384033, 0.5160543918609619, -1.237664818763733, -0.28722143173217773, -0.06666692346334457, -0.10188471525907516, -0.08419819921255112, -0.009648174047470093, -0.1431918889284134, 0.4035259187221527, 0.035366445779800415, 0.013972862623631954, 0.17852190136909485, 0.1325078010559082, -0.17086435854434967, 0.058622464537620544, 0.19119977951049805, -0.002912906464189291, -0.2821902930736542, -0.05631805583834648, -0.05328042432665825, 0.49222448468208313, 0.2630442976951599, 0.10667388886213303, 0.3947911560535431, -0.050519414246082306, 0.28900161385536194, 0.25116413831710815, 0.009929991327226162, 0.0186369176954031, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.251947820186615, 0.08079728484153748, -0.11120861023664474, -0.030722713097929955, -0.45348498225212097, -0.24015556275844574, -0.22769679129123688, 0.4643159508705139, 0.21259218454360962, 0.28396743535995483, 0.19354528188705444, 0.11586792021989822, 0.00682359142228961, -0.43959394097328186, -0.8333287239074707, 0.3853629231452942, 0.4611484110355377, 0.7593753933906555, 0.42284733057022095, -1.6084754467010498, -0.004347177222371101, 0.6250426173210144, 1.9271665811538696, -0.09377947449684143, -0.0262291356921196, -0.4513298273086548, -0.13619711995124817, -0.42423442006111145, 0.22875383496284485, 0.3893473744392395, 0.5431398153305054, 0.7653834223747253, 2.9546003341674805, -1.1652415990829468, 0.592566192150116, 3.1673200130462646]], "betas": [[0.04105652496218681, 0.9988479614257812, 0.0021338227670639753, 0.004459192045032978, -0.00023122405400499701, 0.002098730532452464, 0.0011202488094568253, 0.0011170814977958798, -0.00019942803191952407, 0.0029051792807877064]], "transl": [[0.09172064065933228, 0.22193996608257294, 0.02046819031238556]], "joints3d": [[[-325.3499450683594, 96.77848052978516, 4287.51513671875], [-310.918701171875, 199.95555114746094, 4246.4453125], [-390.3475646972656, 165.82362365722656, 4342.78125], [-273.2453918457031, 1.946479082107544, 4301.20166015625], [-525.7766723632812, 517.3916015625, 4186.32177734375], [-605.2945556640625, 490.8149719238281, 4407.7763671875], [-265.9849548339844, -128.44989013671875, 4256.93359375], [-741.76611328125, 847.8878784179688, 4292.41748046875], [-759.5780639648438, 862.6445922851562, 4477.61181640625], [-266.4894714355469, -181.20362854003906, 4234.50048828125], [-813.8619384765625, 935.4085693359375, 4218.72314453125], [-865.6173095703125, 925.1670532226562, 4421.232421875], [-219.97317504882812, -387.4580383300781, 4200.8759765625], [-185.6108856201172, -277.3990783691406, 4163.61767578125], [-273.6795654296875, -316.92626953125, 4283.4482421875], [-228.64761352539062, -453.6557922363281, 4146.8603515625], [-159.4683837890625, -259.86895751953125, 4075.540283203125], [-352.2349548339844, -354.3350830078125, 4330.90234375], [-249.55206298828125, -16.280353546142578, 4020.220458984375], [-532.3821411132812, -171.6730499267578, 4357.7099609375], [-472.96820068359375, -111.86933898925781, 4089.281005859375], [-390.3512878417969, -125.59742736816406, 4145.48291015625]]]}, {"global_orient": [[2.7504868507385254, 0.5347372889518738, -1.1488831043243408]], "body_pose": [[2.7504868507385254, 0.5347372889518738, -1.1488831043243408, -0.2906135022640228, -0.05617782473564148, -0.11317621171474457, -0.11567278206348419, 0.00981881096959114, -0.10153519362211227, 0.3961412310600281, 0.03713928163051605, 0.022432958707213402, 0.2110712230205536, 0.11237428337335587, -0.15293505787849426, 0.07089601457118988, 0.1828438639640808, -0.0010737704578787088, -0.24944210052490234, -0.07828138768672943, -0.037923213094472885, 0.48028942942619324, 0.24757523834705353, 0.06702445447444916, 0.4229099452495575, -0.05450553819537163, 0.25120848417282104, 0.2191760390996933, -0.001595711219124496, 0.035277120769023895, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2671060860157013, 0.0817200168967247, -0.10301756858825684, -0.051835037767887115, -0.46599921584129333, -0.2168274223804474, -0.2535310387611389, 0.44236329197883606, 0.1717061549425125, 0.24515828490257263, 0.1997445523738861, 0.11822029948234558, -0.023193078115582466, -0.41797417402267456, -0.8215929865837097, 0.40593472123146057, 0.27901673316955566, 0.7704620361328125, 0.20650683343410492, -1.4496901035308838, 0.11048844456672668, 0.47417205572128296, 1.8164833784103394, -0.25725257396698, -0.11726493388414383, -0.7196286916732788, -0.6440573334693909, -0.07573531568050385, -0.12278111279010773, 0.25530046224594116, 0.16371405124664307, 0.7460823655128479, 2.6151299476623535, -0.13692882657051086, 0.6585137844085693, 3.258119821548462]], "betas": [[-0.30137115716934204, 0.9455276131629944, 0.004077209625393152, 0.002994619542732835, -0.0012793975183740258, 0.0014010283630341291, 0.0010780502343550324, 0.0009129479294642806, 3.76988755306229e-05, 0.0026637359987944365]], "transl": [[0.09643547981977463, 0.21576757729053497, 0.029000231996178627]], "joints3d": [[[-335.2774963378906, 96.47369384765625, 4248.56982421875], [-317.82928466796875, 199.86683654785156, 4212.18115234375], [-403.2420959472656, 162.5606231689453, 4301.86572265625], [-285.8724365234375, 3.2082552909851074, 4261.27490234375], [-528.1171264648438, 511.4332275390625, 4153.29150390625], [-617.3560791015625, 482.58709716796875, 4341.80419921875], [-275.5298156738281, -123.46684265136719, 4216.3388671875], [-735.765869140625, 835.4957885742188, 4259.52490234375], [-768.4869995117188, 847.7836303710938, 4395.9287109375], [-277.2879943847656, -174.1408233642578, 4192.17529296875], [-805.5203857421875, 923.5933227539062, 4189.5205078125], [-866.8728637695312, 911.7115478515625, 4334.82080078125], [-231.06166076660156, -377.72113037109375, 4163.36376953125], [-195.93653869628906, -270.1477355957031, 4126.802734375], [-286.5572814941406, -307.18316650390625, 4241.1474609375], [-238.28607177734375, -443.822998046875, 4111.541015625], [-167.74786376953125, -256.8356628417969, 4040.65234375], [-362.37860107421875, -346.7548522949219, 4286.431640625], [-251.53883361816406, -20.77096176147461, 3970.566162109375], [-537.653564453125, -176.14926147460938, 4349.8076171875], [-485.1399841308594, -99.70881652832031, 3962.91162109375], [-477.6155090332031, -133.2450714111328, 4106.9951171875]]]}, {"global_orient": [[2.7470319271087646, 0.5061150193214417, -0.9741474986076355]], "body_pose": [[2.7470319271087646, 0.5061150193214417, -0.9741474986076355, -0.11549793928861618, -0.08211848884820938, -0.20031557977199554, -0.041641488671302795, 0.005971174221485853, -0.0851982831954956, 0.45512646436691284, 0.008590253069996834, 0.006959700956940651, 0.20500676333904266, 0.1902744323015213, -0.17230205237865448, 0.019394710659980774, 0.24797610938549042, -0.019069211557507515, -0.292273610830307, -0.07936815917491913, -0.04981919750571251, 0.28709840774536133, 0.18907828629016876, 0.17033639550209045, 0.37898993492126465, -0.10193705558776855, 0.16651815176010132, 0.21569795906543732, 0.043451566249132156, 0.03238227963447571, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.16704688966274261, 0.05970718711614609, -0.12733915448188782, 0.06077953428030014, -0.4486261010169983, -0.23327015340328217, -0.19928783178329468, 0.39247286319732666, 0.15639393031597137, 0.2150089591741562, 0.23959264159202576, 0.13886794447898865, -0.02914673462510109, -0.49774372577667236, -0.8137094974517822, 0.32359859347343445, 0.5672500133514404, 0.7762356400489807, 0.21556530892848969, -1.3416783809661865, 0.14420560002326965, 0.5424181222915649, 1.9551490545272827, -0.07906398922204971, 0.32911479473114014, -0.20996858179569244, 0.04844910278916359, -0.15737541019916534, -0.17874401807785034, -0.2637431025505066, -0.4370242655277252, 0.2542462646961212, -0.7147029042243958, -1.0316903591156006, 0.4420347809791565, 1.7095887660980225]], "betas": [[-0.08370883017778397, 1.7072575092315674, 0.0025877219159156084, 0.0053191278129816055, 0.00029122494743205607, 0.0019599611405283213, 0.0008355157333426178, 0.0011443608673289418, 0.0005717824678868055, 0.0011463877744972706]], "transl": [[0.0866537019610405, 0.20980340242385864, 0.03751665726304054]], "joints3d": [[[-354.74267578125, 91.12261962890625, 4342.65771484375], [-335.0233154296875, 192.6715087890625, 4307.0791015625], [-425.67889404296875, 159.42733764648438, 4384.4052734375], [-307.9275817871094, -1.2769951820373535, 4363.42822265625], [-536.7552490234375, 528.2167358398438, 4274.68359375], [-636.1624755859375, 498.1485290527344, 4400.92236328125], [-296.3534240722656, -131.01324462890625, 4316.5771484375], [-749.0886840820312, 848.61083984375, 4418.99365234375], [-798.0593872070312, 873.8557739257812, 4425.04541015625], [-292.8802795410156, -182.5467071533203, 4295.384765625], [-810.9921875, 933.3453369140625, 4334.642578125], [-893.8999633789062, 929.248291015625, 4348.76513671875], [-242.63897705078125, -384.82550048828125, 4272.5830078125], [-204.14845275878906, -276.71392822265625, 4242.65625], [-305.958251953125, -313.49029541015625, 4342.62451171875], [-245.78451538085938, -449.7015075683594, 4214.23681640625], [-167.56600952148438, -261.73284912109375, 4161.1044921875], [-383.88232421875, -356.049072265625, 4379.41845703125], [-250.22805786132812, -18.16412353515625, 4092.640869140625], [-569.9409790039062, -178.44760131835938, 4362.55712890625], [-492.68560791015625, -75.18079376220703, 4052.21875], [-395.6501770019531, -153.099853515625, 4171.47119140625]]]}, {"global_orient": [[2.887214183807373, 0.5096388459205627, -0.8134987354278564]], "body_pose": [[2.887214183807373, 0.5096388459205627, -0.8134987354278564, -0.09809114038944244, -0.08809401094913483, -0.2523636519908905, -0.11290913075208664, 0.012159720994532108, -0.05550291761755943, 0.4050348401069641, -0.009575748816132545, 0.0296948179602623, 0.2528001368045807, 0.18507173657417297, -0.12037702649831772, 0.007908440195024014, 0.18553383648395538, -0.016307072713971138, -0.2701304852962494, -0.06225460022687912, -0.04911315441131592, 0.10058073699474335, 0.1273728609085083, 0.15231792628765106, 0.4094187915325165, -0.09948953241109848, 0.03799133375287056, 0.1587546318769455, 0.007347931619733572, 0.031847067177295685, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.21366028487682343, 0.015159155242145061, -0.09102299064397812, 0.05223197117447853, -0.45666512846946716, -0.21822310984134674, -0.17233017086982727, 0.410643607378006, 0.14776171743869781, 0.2720584571361542, 0.19128145277500153, 0.11952357739210129, -0.05855323746800423, -0.5500790476799011, -0.8836601376533508, 0.2439531534910202, 0.671074628829956, 0.8141555786132812, 0.19525375962257385, -1.1466187238693237, 0.13993382453918457, 0.4655000567436218, 1.7330623865127563, -0.14001500606536865, 0.37541159987449646, -0.08278853446245193, -0.07502681761980057, -0.1522924154996872, -0.09788684546947479, -0.14119122922420502, -0.3175237774848938, -0.06662677228450775, -0.1650761216878891, -0.5814186930656433, 0.5575557351112366, 1.3273932933807373]], "betas": [[0.27742135524749756, 1.6972159147262573, 0.0030862584244459867, 0.0049289800226688385, 0.0005659500020556152, 0.0016915907617658377, 0.0007724710740149021, 0.0011345575330778956, 0.0006904774927534163, 0.0008549483609385788]], "transl": [[0.08448443561792374, 0.2130574882030487, 0.04558287188410759]], "joints3d": [[[-375.80389404296875, 93.48303985595703, 4470.07861328125], [-350.209228515625, 198.61517333984375, 4446.8974609375], [-450.3402404785156, 160.92449951171875, 4510.2587890625], [-332.0171813964844, -4.4009575843811035, 4488.1611328125], [-553.8348388671875, 543.0198974609375, 4443.048828125], [-661.6346435546875, 508.5995788574219, 4507.42041015625], [-316.7250061035156, -134.7919921875, 4435.2783203125], [-760.7081298828125, 862.7611083984375, 4620.57275390625], [-824.0143432617188, 895.4359741210938, 4513.896484375], [-311.77557373046875, -186.53091430664062, 4411.41748046875], [-816.923095703125, 945.2003784179688, 4525.826171875], [-921.052978515625, 949.4879760742188, 4432.5341796875], [-258.0246276855469, -391.9952087402344, 4388.9404296875], [-215.64212036132812, -281.0909423828125, 4364.77490234375], [-330.00372314453125, -321.0061950683594, 4455.52880859375], [-255.45965576171875, -460.9853515625, 4333.1015625], [-169.9337158203125, -264.9255676269531, 4285.609375], [-414.0945129394531, -365.73126220703125, 4481.62890625], [-269.3671875, -20.531076431274414, 4220.955078125], [-588.0958862304688, -177.9720916748047, 4420.556640625], [-512.6860961914062, -49.64925765991211, 4138.947265625], [-419.30279541015625, -156.488525390625, 4216.52197265625]]]}, {"global_orient": [[2.956857919692993, 0.4649953842163086, -0.6580240726470947]], "body_pose": [[2.956857919692993, 0.4649953842163086, -0.6580240726470947, -0.08555984497070312, -0.08534561842679977, -0.2648548185825348, -0.09291300177574158, -0.0058298357762396336, -0.1060284823179245, 0.36272382736206055, -0.013054060749709606, -0.0018056873232126236, 0.13699518144130707, 0.050487350672483444, -0.07722558081150055, 0.031313445419073105, 0.1698167622089386, -0.03207322582602501, -0.23716576397418976, -0.06423020362854004, -0.03861039876937866, 0.20329327881336212, 0.20508398115634918, 0.08774013072252274, 0.33775195479393005, -0.1198778823018074, 0.11876863986253738, 0.13725867867469788, -0.002346682595089078, 0.026797937229275703, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2587312161922455, -0.021998029202222824, -0.0692964419722557, 0.07632070779800415, -0.36832448840141296, -0.2691993713378906, -0.17669782042503357, 0.3323878347873688, 0.17208439111709595, 0.31828001141548157, 0.17673353850841522, 0.1056235060095787, 0.0261523500084877, -0.4955650269985199, -0.8993058204650879, 0.3313775658607483, 0.5056319832801819, 0.8375132083892822, 0.228658065199852, -1.1200917959213257, 0.11319956183433533, 0.45691564679145813, 1.5969123840332031, -0.19360484182834625, 0.3755194842815399, 0.09781532734632492, 0.14489540457725525, -0.27151551842689514, -0.30546045303344727, -0.22035568952560425, -0.4553731083869934, -0.22032128274440765, -0.43716058135032654, -0.32051464915275574, 0.24719911813735962, 2.3640706539154053]], "betas": [[0.3213828504085541, 1.8024640083312988, 0.0035677310079336166, 0.00503695011138916, 0.00024593109264969826, 0.0016920709749683738, 0.000823354406747967, 0.0007306470652110875, 0.00052861706353724, 0.001223640632815659]], "transl": [[0.08219534158706665, 0.2021670639514923, 0.043493762612342834]], "joints3d": [[[-389.78125, 92.8199691772461, 4519.32470703125], [-358.5040283203125, 197.51768493652344, 4502.92431640625], [-465.3609924316406, 161.92752075195312, 4553.810546875], [-351.6614990234375, -7.2671403884887695, 4538.3310546875], [-551.4459838867188, 550.2385864257812, 4495.3291015625], [-677.4909057617188, 511.388916015625, 4557.35888671875], [-328.7583923339844, -137.29183959960938, 4485.6171875], [-771.6571655273438, 888.515625, 4618.828125], [-842.6318359375, 898.0086059570312, 4587.2275390625], [-321.7759094238281, -188.4616241455078, 4461.0029296875], [-821.0935668945312, 972.7969360351562, 4521.34375], [-932.8370361328125, 954.6717529296875, 4499.32763671875], [-265.4734802246094, -393.44061279296875, 4440.216796875], [-221.27737426757812, -281.9339904785156, 4422.63037109375], [-343.7279357910156, -323.5422668457031, 4500.70556640625], [-257.2266845703125, -465.0411682128906, 4387.54638671875], [-162.82748413085938, -259.5063171386719, 4354.15869140625], [-428.72259521484375, -367.5452575683594, 4525.08740234375], [-233.78567504882812, 0.1503891944885254, 4310.45751953125], [-606.8497924804688, -173.66744995117188, 4504.53466796875], [-469.3097839355469, 13.037301063537598, 4202.45947265625], [-490.7314453125, -114.61510467529297, 4271.7705078125]]]}, {"global_orient": [[2.9878945350646973, 0.4344504773616791, -0.44918668270111084]], "body_pose": [[2.9878945350646973, 0.4344504773616791, -0.44918668270111084, 0.04960279539227486, -0.09837684780359268, -0.3050733506679535, -0.04257988557219505, -0.03337681293487549, -0.13982312381267548, 0.4023556709289551, -0.055886294692754745, 0.0068539809435606, 0.07658427953720093, -0.007786428090184927, -0.043604400008916855, 0.03904912248253822, 0.15015728771686554, -0.02507960982620716, -0.23761732876300812, -0.05568242445588112, -0.05044315382838249, 0.21526406705379486, 0.18265335261821747, 0.028267621994018555, 0.33334797620773315, -0.1373654156923294, 0.13132622838020325, 0.11140970885753632, -0.004108278546482325, 0.015407433733344078, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.25744152069091797, -0.06567706167697906, -0.08834811300039291, 0.12539274990558624, -0.30958375334739685, -0.3122714161872864, -0.1444934904575348, 0.22463372349739075, 0.21481850743293762, 0.36671942472457886, 0.19142946600914001, 0.10581932216882706, 0.07464148104190826, -0.47838422656059265, -0.8482774496078491, 0.3550971448421478, 0.36424240469932556, 0.7588204741477966, 0.3873046934604645, -0.9058106541633606, 0.07609403878450394, 0.5035639405250549, 1.4028829336166382, -0.0758892372250557, 0.19132012128829956, -0.025998571887612343, -0.11671996116638184, 0.16794592142105103, -0.18428091704845428, -0.0009723356342874467, -0.1605493128299713, -0.048371151089668274, 0.11925206333398819, -0.4609138071537018, 0.6408096551895142, 1.9993559122085571]], "betas": [[0.5997738838195801, 2.0327088832855225, 0.005637186113744974, 0.005679486785084009, 0.0005006117280572653, 0.0018916400149464607, 0.0011198375141248107, 0.000302368076518178, 0.0004105669795535505, 0.0009876324329525232]], "transl": [[0.08391429483890533, 0.1899956911802292, 0.032769642770290375]], "joints3d": [[[-396.75225830078125, 87.50761413574219, 4621.4443359375], [-362.79339599609375, 192.4005126953125, 4610.77490234375], [-474.8203430175781, 158.4530487060547, 4645.93115234375], [-362.57086181640625, -14.737852096557617, 4645.19091796875], [-547.9846801757812, 557.6421508789062, 4634.642578125], [-691.115966796875, 515.0399780273438, 4647.70849609375], [-338.6588134765625, -146.30606079101562, 4588.8076171875], [-770.6657104492188, 904.8720703125, 4760.33056640625], [-857.1500854492188, 910.6366577148438, 4683.97900390625], [-329.8401794433594, -197.88523864746094, 4563.892578125], [-819.5753784179688, 995.3653564453125, 4664.69873046875], [-942.9343872070312, 973.1158447265625, 4591.6376953125], [-272.5147399902344, -404.64593505859375, 4542.6376953125], [-225.54043579101562, -291.7108154296875, 4533.17626953125], [-356.6417236328125, -334.6768798828125, 4597.97412109375], [-258.7490539550781, -476.6633605957031, 4488.61474609375], [-157.46762084960938, -263.5470886230469, 4475.1796875], [-444.3662414550781, -376.27197265625, 4622.40283203125], [-206.1231231689453, 8.033096313476562, 4442.9521484375], [-636.939697265625, -189.4751434326172, 4639.24365234375], [-424.5565490722656, 104.45323181152344, 4328.650390625], [-584.4705200195312, -55.9093132019043, 4408.1650390625]]]}, {"global_orient": [[2.9898223876953125, 0.4918457567691803, -0.45282649993896484]], "body_pose": [[2.9898223876953125, 0.4918457567691803, -0.45282649993896484, -0.01212597917765379, -0.059697166085243225, -0.22582454979419708, -0.034973252564668655, -0.04093868285417557, -0.10466742515563965, 0.41695302724838257, -0.02724328078329563, 0.024237841367721558, 0.16868498921394348, -0.060094885528087616, -0.08158982545137405, 0.08198154717683792, 0.17283248901367188, -0.014597244560718536, -0.23788511753082275, -0.051731497049331665, -0.044004831463098526, 0.12623602151870728, 0.2552156150341034, 0.03119366243481636, 0.2466747760772705, -0.11511450260877609, 0.15949922800064087, 0.13229453563690186, -0.0044478471390903, 0.0234238151460886, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.21599778532981873, -0.0653010755777359, -0.04836226627230644, 0.0697919949889183, -0.34176257252693176, -0.4237517714500427, -0.1487094759941101, 0.265909343957901, 0.27400630712509155, 0.29518014192581177, 0.20250728726387024, 0.07249710708856583, 0.11151497066020966, -0.37838268280029297, -0.7542511820793152, 0.33750903606414795, 0.28359243273735046, 0.6449748873710632, 0.3082435131072998, -0.6781456470489502, 0.1634940654039383, 0.5248208045959473, 1.0501354932785034, -0.08225186914205551, 0.2298157662153244, 0.11127845197916031, -0.06594071537256241, 0.1760348528623581, -0.1104184091091156, 0.011100328527390957, -0.3960005044937134, -0.19159239530563354, -0.3004520535469055, -0.7780368328094482, 0.5059773921966553, 0.9642623662948608]], "betas": [[0.5254654884338379, 1.641026496887207, 0.0037876314017921686, 0.0043317098170518875, 0.0005600280710496008, 0.0014425230911001563, 0.0008583294111303985, 0.0006238714559003711, 0.0004928696434944868, 0.0009251346345990896]], "transl": [[0.08223406970500946, 0.18240514397621155, 0.03457459807395935]], "joints3d": [[[-392.6177978515625, 85.53047180175781, 4607.07421875], [-361.4797058105469, 192.24342346191406, 4596.32373046875], [-474.8002624511719, 153.05548095703125, 4632.2548828125], [-354.1226501464844, -15.930625915527344, 4630.66552734375], [-538.1445922851562, 556.2135009765625, 4593.5791015625], [-686.740478515625, 505.9052429199219, 4640.27880859375], [-327.9383239746094, -144.53512573242188, 4572.48095703125], [-749.2132568359375, 900.8229370117188, 4729.701171875], [-841.7488403320312, 898.2325439453125, 4699.4892578125], [-318.9449462890625, -195.1706085205078, 4545.232421875], [-789.7303466796875, 988.5817260742188, 4628.9736328125], [-921.3383178710938, 960.30810546875, 4602.59326171875], [-262.37548828125, -402.330810546875, 4518.0068359375], [-213.88534545898438, -289.4006652832031, 4512.0595703125], [-348.0076904296875, -334.1629943847656, 4574.24462890625], [-253.9842987060547, -470.5296325683594, 4460.3857421875], [-147.59872436523438, -249.76895141601562, 4457.60107421875], [-440.1756286621094, -369.5547180175781, 4594.173828125], [-187.0809326171875, 21.616247177124023, 4434.1494140625], [-641.2915649414062, -196.1717987060547, 4619.759765625], [-351.9200744628906, 171.03643798828125, 4294.90478515625], [-682.7150268554688, -20.707611083984375, 4419.45458984375]]]}, {"global_orient": [[2.9837865829467773, 0.4914543330669403, -0.44858211278915405]], "body_pose": [[2.9837865829467773, 0.4914543330669403, -0.44858211278915405, 0.03348734229803085, -0.027871688827872276, -0.20672114193439484, 0.031772125512361526, -0.04293624684214592, -0.10704359412193298, 0.4471147060394287, -0.004644814878702164, 0.03134647384285927, 0.1645294725894928, -0.1322975903749466, -0.09820986539125443, 0.07248564064502716, 0.23242169618606567, -0.04832061007618904, -0.2513808608055115, -0.05458395555615425, -0.05693558603525162, 0.3094949424266815, 0.2717290222644806, 0.006105626467615366, 0.39588698744773865, -0.09102121740579605, 0.18811282515525818, 0.08691749721765518, -0.006095066200941801, 0.02596566267311573, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2317221611738205, -0.039198778569698334, -0.061839260160923004, 0.12772683799266815, -0.26166048645973206, -0.44780585169792175, -0.12294721603393555, 0.1930427998304367, 0.31054505705833435, 0.26592808961868286, 0.22554564476013184, 0.12925460934638977, 0.06851009279489517, -0.2914329767227173, -0.6282418370246887, 0.34024837613105774, 0.10864095389842987, 0.6362298727035522, 0.39718663692474365, -0.6105057597160339, 0.17818641662597656, 0.13264037668704987, 0.3996700346469879, 0.09783292561769485, 0.15334610641002655, 0.1301129013299942, -0.3024822175502777, 0.020448705181479454, 0.6894196271896362, 0.2942705452442169, -0.31109872460365295, -0.42729422450065613, 0.30781862139701843, -0.11510787159204483, 1.386770248413086, 3.0229873657226562]], "betas": [[0.4536425471305847, 2.0456926822662354, 0.007304462604224682, 0.005322259850800037, 0.0001874770678114146, 0.002156701870262623, 0.0015582770574837923, 0.0005202942411415279, 0.0006354564102366567, 0.0009986337972804904]], "transl": [[0.078230120241642, 0.17189134657382965, 0.01180329266935587]], "joints3d": [[[-397.3675842285156, 73.2271957397461, 4670.65673828125], [-367.11822509765625, 178.80967712402344, 4661.234375], [-477.4960021972656, 140.606201171875, 4696.13037109375], [-360.0502624511719, -26.95722007751465, 4692.4658203125], [-533.0770263671875, 550.7469482421875, 4669.14404296875], [-684.9642333984375, 497.5968322753906, 4726.68798828125], [-335.63885498046875, -154.53579711914062, 4630.5751953125], [-737.2089233398438, 896.2106323242188, 4816.3095703125], [-848.5565795898438, 882.7926025390625, 4809.7919921875], [-325.8905334472656, -204.3206024169922, 4603.751953125], [-784.8590698242188, 1000.9520874023438, 4737.88037109375], [-923.6259765625, 967.8673095703125, 4728.875], [-267.3906555175781, -409.02008056640625, 4582.16943359375], [-221.04608154296875, -296.7217102050781, 4576.580078125], [-353.2444152832031, -340.59228515625, 4634.19482421875], [-253.10549926757812, -479.0798034667969, 4526.69384765625], [-151.7611083984375, -256.77386474609375, 4529.44140625], [-443.3417053222656, -373.98126220703125, 4658.08251953125], [-148.42605590820312, 17.694639205932617, 4504.837890625], [-636.7420654296875, -205.23049926757812, 4730.33056640625], [-257.4521179199219, 200.14332580566406, 4351.17431640625], [-814.6845092773438, -6.161397933959961, 4692.38623046875]]]}, {"global_orient": [[3.060161590576172, 0.5170426368713379, -0.5410254001617432]], "body_pose": [[3.060161590576172, 0.5170426368713379, -0.5410254001617432, -0.09406384825706482, -0.01665964350104332, -0.15762196481227875, -0.036084435880184174, -0.07159951329231262, -0.10953202843666077, 0.3635180592536926, 0.0018843606812879443, 0.032287999987602234, 0.17485274374485016, -0.11549030989408493, -0.11144104599952698, 0.07885277271270752, 0.20490676164627075, -0.03434182330965996, -0.26607850193977356, -0.026194807142019272, -0.043311163783073425, 0.40054523944854736, 0.2776351869106293, 0.009636089205741882, 0.5138988494873047, -0.09407636523246765, 0.18027587234973907, 0.12212109565734863, 0.017212627455592155, 0.02243192493915558, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.204515740275383, -0.0033729507122188807, -0.045265235006809235, 0.06531228870153427, -0.24301128089427948, -0.44220268726348877, -0.12082183361053467, 0.2426896095275879, 0.2942773103713989, 0.2139112800359726, 0.2107410579919815, 0.09256435930728912, 0.05751119181513786, -0.23263956606388092, -0.6110416054725647, 0.2571974992752075, 0.1529669463634491, 0.6360154151916504, 0.2742377817630768, -0.548659086227417, 0.25394564867019653, 0.08557356148958206, 0.5757749676704407, -0.02509748749434948, 0.4080365300178528, 0.36161085963249207, -0.44659802317619324, -0.04918687418103218, 0.28170737624168396, 0.7476007342338562, -0.5805631875991821, -0.7900961637496948, -0.05923886224627495, -0.45538750290870667, 0.9750814437866211, 3.426313638687134]], "betas": [[0.5627292990684509, 1.4665284156799316, 0.0077570173889398575, 0.004548286087810993, -7.563861436210573e-05, 0.0017207631608471274, 0.001506241736933589, 0.00013494871382135898, 0.0004611519689206034, 0.0010849109385162592]], "transl": [[0.07061987370252609, 0.18083934485912323, 0.015842542052268982]], "joints3d": [[[-396.3507080078125, 76.35491180419922, 4716.5283203125], [-364.7362976074219, 184.040771484375, 4711.34326171875], [-477.2422180175781, 142.1761932373047, 4751.58642578125], [-356.7129821777344, -27.39084815979004, 4730.796875], [-524.7557373046875, 554.457275390625, 4707.88623046875], [-685.3297729492188, 492.70513916015625, 4802.5361328125], [-331.7922058105469, -154.08163452148438, 4668.17822265625], [-726.2996826171875, 902.3703002929688, 4849.13037109375], [-841.8023071289062, 875.525146484375, 4904.0625], [-322.5529479980469, -204.52772521972656, 4639.84912109375], [-772.4906616210938, 1013.5057373046875, 4777.9931640625], [-927.32421875, 969.2899780273438, 4844.44091796875], [-264.2595520019531, -412.4520263671875, 4612.84521484375], [-215.2301788330078, -298.9190673828125, 4609.28955078125], [-352.9875183105469, -344.92529296875, 4666.61962890625], [-251.96078491210938, -478.3136291503906, 4553.728515625], [-141.3957061767578, -257.3793029785156, 4565.7421875], [-446.8550720214844, -378.7337951660156, 4685.2861328125], [-122.161376953125, 16.41969871520996, 4546.13671875], [-645.8180541992188, -208.7816619873047, 4737.85205078125], [-178.53550720214844, 205.79408264160156, 4373.1171875], [-821.2510986328125, -37.52458953857422, 4625.9638671875]]]}, {"global_orient": [[2.9770703315734863, 0.46827295422554016, -0.32776162028312683], [3.2742481231689453, 0.16503344476222992, 0.8582125306129456]], "body_pose": [[2.9770703315734863, 0.46827295422554016, -0.32776162028312683, 0.0365302674472332, -0.0030020263511687517, -0.16955457627773285, 0.04833350330591202, -0.07739036530256271, -0.09475181996822357, 0.44986486434936523, -0.01227358914911747, 0.039436813443899155, 0.04867975041270256, -0.15629878640174866, -0.05396902561187744, -0.01682109385728836, 0.21166206896305084, -0.03928875923156738, -0.264818012714386, -0.0589120052754879, -0.06291557848453522, 0.4166017770767212, 0.28861406445503235, -0.017821231856942177, 0.5154353976249695, -0.1942504346370697, 0.22614584863185883, 0.10057362914085388, 0.016706250607967377, 0.04727694019675255, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.24693003296852112, -0.02935776114463806, -0.08368765562772751, 0.1495620608329773, -0.21613140404224396, -0.3779882788658142, -0.10273827612400055, 0.15404091775417328, 0.18832722306251526, 0.2613377571105957, 0.2780284881591797, 0.09774891287088394, 0.05109462887048721, -0.20039455592632294, -0.5983133912086487, 0.3042638897895813, 0.07043609023094177, 0.6868618130683899, 0.41484835743904114, -0.6109432578086853, 0.12639226019382477, 0.16696664690971375, 0.5768617987632751, 0.015569711104035378, 0.33690786361694336, 0.3064810633659363, -0.49933740496635437, -0.08064740151166916, -0.03597341105341911, 1.6178014278411865, -0.41628313064575195, -0.6975516080856323, 0.26912447810173035, -0.22775410115718842, -0.6922503113746643, 3.7914223670959473], [3.2742481231689453, 0.16503344476222992, 0.8582125306129456, -0.38837534189224243, 0.15349751710891724, 0.25536441802978516, -0.3904213607311249, -0.05800484120845795, -0.1634063720703125, 0.5081664323806763, -0.06982695311307907, 0.08963210135698318, 0.6090446710586548, -0.1170935332775116, -0.11711007356643677, 0.6628795266151428, -0.11953861266374588, 0.3415420353412628, -0.574622631072998, 0.03447725251317024, -0.0049126106314361095, -0.1531323939561844, 0.13746213912963867, -0.2883991301059723, 0.03600076586008072, -0.1593935340642929, -0.09289482235908508, 0.5037434697151184, 0.01452874206006527, -0.050355214625597, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.006171347573399544, -0.12953150272369385, -0.1150192841887474, -0.19431941211223602, -0.3625645935535431, -0.28789815306663513, -0.3719056248664856, 0.5376259684562683, 0.30928894877433777, -0.18156535923480988, 0.016599830240011215, 0.12718187272548676, 0.2253342717885971, -0.370927095413208, -0.8052899837493896, 0.26022621989250183, 0.3057965338230133, 0.6840586066246033, 0.5841271281242371, -1.5593873262405396, 0.03213603422045708, 0.4414061903953552, 1.4782589673995972, 0.19231383502483368, -0.0683249905705452, -0.42222270369529724, 0.4873051643371582, 0.47339677810668945, 0.56651371717453, -0.22285382449626923, -1.0364620685577393, -0.3091617524623871, -1.361025333404541, -1.0478729009628296, 0.2786584794521332, 0.9430370330810547]], "betas": [[0.4171619117259979, 1.9647659063339233, 0.010074296966195107, 0.0069247279316186905, 0.0008162559824995697, 0.002823866903781891, 0.0016538212075829506, 0.0002240758331026882, 0.0008496771333739161, 0.0010731713846325874], [-2.2079262733459473, -0.15760189294815063, -0.005519750993698835, 0.007837624289095402, 0.0008155981777235866, 0.0006998127792030573, 0.0011098834220319986, 0.0033545908518135548, -0.0009093491826206446, 0.002784025389701128]], "transl": [[0.06451775133609772, 0.1725214272737503, 0.018038498237729073], [-0.044613610953092575, 0.15505747497081757, 0.0436965636909008]], "joints3d": [[[-406.19189453125, 70.22987365722656, 4784.92041015625], [-374.22802734375, 175.499755859375, 4776.283203125], [-487.9284973144531, 138.37303161621094, 4802.66796875], [-371.51324462890625, -29.763023376464844, 4811.29833984375], [-523.1748657226562, 552.7137451171875, 4763.642578125], [-686.6315307617188, 499.4449768066406, 4818.69970703125], [-344.6231384277344, -158.31857299804688, 4753.73388671875], [-727.47216796875, 919.6952514648438, 4833.7470703125], [-848.12646484375, 891.3856811523438, 4850.869140625], [-333.26123046875, -208.7091064453125, 4728.79052734375], [-760.0850219726562, 1024.2103271484375, 4748.259765625], [-925.3572998046875, 976.9796142578125, 4773.19873046875], [-279.55328369140625, -415.41864013671875, 4716.13330078125], [-229.30303955078125, -304.8025207519531, 4712.658203125], [-367.6402587890625, -343.60205078125, 4758.8828125], [-260.40179443359375, -486.32330322265625, 4663.8994140625], [-151.139404296875, -274.06060791015625, 4673.056640625], [-455.7376708984375, -385.1172790527344, 4776.56884765625], [-93.078125, -6.005683898925781, 4657.2109375], [-656.66943359375, -226.62841796875, 4848.72021484375], [-147.57855224609375, 198.32150268554688, 4503.49462890625], [-836.7431640625, -47.210472106933594, 4761.298828125]], [[-4045.102294921875, -2637.5390625, 12126.8173828125], [-4002.628173828125, -2557.859375, 12186.1943359375], [-4118.1259765625, -2561.4169921875, 12116.4130859375], [-4040.137939453125, -2730.780517578125, 12119.25], [-3899.304443359375, -2245.597900390625, 12215.5205078125], [-4186.21826171875, -2241.9794921875, 12040.75], [-4007.701416015625, -2816.0478515625, 12047.5830078125], [-3985.30615234375, -1965.7391357421875, 12388.904296875], [-4204.919921875, -1972.8787841796875, 12247.3857421875], [-3990.829345703125, -2853.31103515625, 12016.1953125], [-3919.513427734375, -1883.71435546875, 12339.6318359375], [-4211.9013671875, -1882.124755859375, 12177.2880859375], [-3952.414306640625, -3032.42822265625, 11945.0634765625], [-3910.0439453125, -2957.93408203125, 12012.4033203125], [-4034.374267578125, -2962.24560546875, 11953.064453125], [-3916.403076171875, -3046.075927734375, 11882.5673828125], [-3829.03662109375, -2950.245361328125, 12031.171875], [-4094.743408203125, -2951.31494140625, 11892.3037109375], [-3788.9931640625, -2737.452880859375, 12099.693359375], [-4149.611328125, -2741.25244140625, 11848.8388671875], [-3905.80029296875, -2677.12744140625, 11933.81640625], [-3942.146240234375, -2672.787353515625, 11867.9384765625]]]}, {"global_orient": [[2.9906058311462402, 0.44969281554222107, -0.2965534031391144], [3.3038296699523926, 0.24008633196353912, 0.6191896796226501]], "body_pose": [[2.9906058311462402, 0.44969281554222107, -0.2965534031391144, 0.009548270143568516, 0.008825843222439289, -0.15390779078006744, 0.04984593018889427, -0.07176265120506287, -0.09592708945274353, 0.4283996522426605, -0.014424960128962994, 0.022328021004796028, 0.0575416125357151, -0.09823601692914963, -0.06483517587184906, -0.015628989785909653, 0.22287823259830475, -0.056177109479904175, -0.2621757984161377, -0.05370912700891495, -0.0613156296312809, 0.3398701846599579, 0.3099413812160492, 0.022829074412584305, 0.44150975346565247, -0.19793471693992615, 0.24525229632854462, 0.10055586695671082, 0.003553138580173254, 0.03844558447599411, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2505696713924408, -0.020957086235284805, -0.04361497983336449, 0.16639116406440735, -0.1712416410446167, -0.31179279088974, -0.1080661490559578, 0.13435152173042297, 0.12340623140335083, 0.3122887909412384, 0.24039654433727264, 0.06511653959751129, 0.029705213382840157, -0.24427106976509094, -0.59453284740448, 0.32805657386779785, 0.15100418031215668, 0.7673406600952148, 0.4350408613681793, -0.6412435173988342, 0.175828754901886, 0.3721161484718323, 0.9689223766326904, -0.13685725629329681, 0.3435198664665222, 0.23328769207000732, -0.5992240309715271, 0.07715488225221634, -0.04419274255633354, 0.6136257648468018, -0.33965155482292175, -0.560789942741394, 0.3568102717399597, -1.3212591409683228, 1.179890751838684, 2.6709673404693604], [3.3038296699523926, 0.24008633196353912, 0.6191896796226501, -0.3801157772541046, 0.11609512567520142, 0.25486308336257935, -0.40532684326171875, -0.10553086549043655, -0.20609185099601746, 0.4875467121601105, -0.07145615667104721, 0.09465458244085312, 0.6122370362281799, -0.08268745988607407, -0.1364872306585312, 0.6934401988983154, -0.18763461709022522, 0.3248574137687683, -0.5418739318847656, 0.006926303263753653, -0.034849099814891815, -0.1816086322069168, 0.22544269263744354, -0.29823631048202515, 0.08300319314002991, -0.028929779306054115, -0.07094866782426834, 0.5164373517036438, -0.009000217542052269, -0.003955185879021883, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.10652793943881989, -0.10242631286382675, -0.18856778740882874, -0.2597513794898987, -0.4305741786956787, -0.33978161215782166, -0.36796998977661133, 0.5372007489204407, 0.332961767911911, -0.2894522249698639, 0.09271728992462158, 0.14792871475219727, 0.25496384501457214, -0.3405001163482666, -0.6941061615943909, 0.27268368005752563, 0.341705322265625, 0.6923397779464722, 0.4234209358692169, -1.60299551486969, 0.07636778801679611, 0.4402366876602173, 1.5152313709259033, 0.06400834023952484, 0.11110736429691315, -0.2285315841436386, 0.557915985584259, 0.43065375089645386, 0.5479943156242371, -0.2605859935283661, -0.8381598591804504, -0.29117071628570557, -1.0483753681182861, -0.6823369860649109, 0.3194751739501953, 1.0181126594543457]], "betas": [[0.6083906888961792, 2.038578987121582, 0.009061896242201328, 0.006744955200701952, 0.0009154535364359617, 0.0026843929663300514, 0.0013599562225863338, 4.596688813762739e-05, 0.0008226225036196411, 0.0005872970796190202], [-1.9759012460708618, -0.2557426691055298, -0.0049986569210886955, 0.006246550474315882, -0.0001459063496440649, 0.00017094583017751575, 0.001624005613848567, 0.002667936496436596, -0.001134315854869783, 0.002856922335922718]], "transl": [[0.055523984134197235, 0.1768525242805481, 0.02944883331656456], [-0.032511789351701736, 0.15757860243320465, 0.05725474655628204]], "joints3d": [[[-419.9686584472656, 75.8060073852539, 4841.7421875], [-386.82843017578125, 181.2887420654297, 4834.71923828125], [-501.2162170410156, 145.4545440673828, 4858.46484375], [-386.66363525390625, -26.024024963378906, 4868.60693359375], [-527.9600219726562, 565.8900146484375, 4809.90380859375], [-698.549072265625, 512.8041381835938, 4874.32373046875], [-356.7588195800781, -156.17434692382812, 4811.52392578125], [-735.627197265625, 939.1298217773438, 4871.1044921875], [-864.9429931640625, 908.63525390625, 4909.49462890625], [-344.1471862792969, -207.39076232910156, 4787.4296875], [-751.2754516601562, 1041.9288330078125, 4776.5810546875], [-939.310791015625, 990.7616577148438, 4822.68310546875], [-287.080078125, -415.03802490234375, 4775.201171875], [-237.66262817382812, -302.7173156738281, 4772.85595703125], [-377.6528015136719, -343.7552795410156, 4817.20166015625], [-267.67987060546875, -488.0305480957031, 4724.20654296875], [-155.39173889160156, -276.61102294921875, 4736.16064453125], [-463.28125, -392.7897033691406, 4834.3623046875], [-86.54724884033203, -8.53885269165039, 4710.8994140625], [-668.88916015625, -229.51708984375, 4892.6748046875], [-130.0540771484375, 184.39373779296875, 4534.72509765625], [-779.7459106445312, -67.74205780029297, 4703.9697265625]], [[-3957.239013671875, -2667.285888671875, 12388.1806640625], [-3911.357666015625, -2581.82177734375, 12438.251953125], [-4035.72412109375, -2594.440673828125, 12384.3740234375], [-3948.326171875, -2762.785400390625, 12384.611328125], [-3823.644775390625, -2259.636474609375, 12441.697265625], [-4146.32421875, -2285.18701171875, 12298.9755859375], [-3921.187744140625, -2852.11669921875, 12312.8037109375], [-3908.473876953125, -1974.4725341796875, 12617.9208984375], [-4149.67041015625, -2000.219482421875, 12494.2802734375], [-3905.614501953125, -2890.216796875, 12280.2373046875], [-3846.922119140625, -1891.3016357421875, 12561.2744140625], [-4171.38427734375, -1908.7493896484375, 12424.7421875], [-3868.607177734375, -3070.242431640625, 12203.19921875], [-3818.239501953125, -2990.88623046875, 12261.8408203125], [-3954.03564453125, -3004.63134765625, 12226.1884765625], [-3839.8173828125, -3073.95166015625, 12135.021484375], [-3735.31689453125, -2971.461181640625, 12263.7138671875], [-4027.2783203125, -2996.5009765625, 12177.53515625], [-3684.187255859375, -2750.09228515625, 12301.4287109375], [-4095.576904296875, -2785.07177734375, 12144.1904296875], [-3824.652099609375, -2719.483642578125, 12141.115234375], [-3885.161865234375, -2720.185791015625, 12110.73828125]]]}, {"global_orient": [[2.950227737426758, 0.4351535141468048, -0.2790478765964508], [3.1727521419525146, 0.043717339634895325, 0.9120535254478455]], "body_pose": [[2.950227737426758, 0.4351535141468048, -0.2790478765964508, 0.06417794525623322, 0.005217636004090309, -0.1514441967010498, 0.07798700034618378, -0.07351063936948776, -0.0926942527294159, 0.46796995401382446, -0.007418458815664053, 0.017229894176125526, 0.05269913375377655, -0.07619088143110275, -0.07310514897108078, -0.02224491722881794, 0.27607524394989014, -0.05603441968560219, -0.2804242968559265, -0.049786925315856934, -0.05891919136047363, 0.2845933139324188, 0.40480610728263855, 0.009366998448967934, 0.4198116064071655, -0.2544572949409485, 0.2647138237953186, 0.10244287550449371, 0.0053319502621889114, 0.034344080835580826, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.22593377530574799, 0.018984626978635788, -0.06320871412754059, 0.1884164661169052, -0.15606963634490967, -0.2955583333969116, -0.09336419403553009, 0.11194608360528946, 0.1383565366268158, 0.3189982771873474, 0.2540469765663147, 0.11041546612977982, 0.04950087144970894, -0.23516055941581726, -0.5951495170593262, 0.35307714343070984, 0.15769216418266296, 0.7889003753662109, 0.46862632036209106, -0.7092834115028381, 0.10203725844621658, 0.32882052659988403, 1.0242369174957275, -0.09306354820728302, 0.3188464343547821, 0.20676234364509583, -0.5777564644813538, 0.057174988090991974, 0.13566520810127258, 0.4905429482460022, -0.36740583181381226, -0.5507394075393677, 0.4262397289276123, -1.2430177927017212, 1.1780332326889038, 2.5093038082122803], [3.1727521419525146, 0.043717339634895325, 0.9120535254478455, -0.3734537363052368, 0.11932848393917084, 0.17648500204086304, -0.3705218732357025, -0.013995601795613766, -0.15070177614688873, 0.53952956199646, -0.037739258259534836, 0.004011545795947313, 0.6331731081008911, -0.11023624241352081, -0.2344581037759781, 0.633056104183197, -0.039942238479852676, 0.2624875605106354, -0.6186438202857971, 0.06474531441926956, 0.041387736797332764, -0.3527812957763672, 0.08548339456319809, -0.014019750989973545, -0.10092519223690033, -0.21134008467197418, -0.23840562999248505, 0.580906093120575, -0.054039645940065384, -0.11186179518699646, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.03350403904914856, -0.10299422591924667, -0.09688704460859299, -0.22457627952098846, -0.3778875172138214, -0.20251533389091492, -0.48767873644828796, 0.7143977880477905, 0.4013928771018982, -0.13281796872615814, -0.0007071294239722192, 0.1867983043193817, 0.3100912570953369, -0.23238667845726013, -0.6827031970024109, 0.3570510745048523, 0.19801659882068634, 0.7058336734771729, 0.18856298923492432, -1.3932347297668457, -0.16508468985557556, 0.30287665128707886, 1.4981591701507568, 0.02118653431534767, 0.04326648637652397, -0.6198554635047913, 0.9055838584899902, 0.3120713233947754, 0.337509423494339, -0.3576667010784149, -1.346846103668213, 0.107091024518013, -1.469695806503296, -1.001116394996643, 0.19630812108516693, 0.8055216073989868]], "betas": [[0.42172759771347046, 2.1782469749450684, 0.008364802226424217, 0.007310613989830017, 0.0010754296090453863, 0.002831129590049386, 0.001345012686215341, 0.000356027070665732, 0.0008442612015642226, 0.0005957323010079563], [-2.53831148147583, -0.5454114079475403, -0.005434414837509394, 0.008974216878414154, 0.0016658547101542354, 0.00075839291093871, 0.0011861040256917477, 0.0022492508869618177, -0.0007388136000372469, 0.002551634330302477]], "transl": [[0.05112888291478157, 0.1707678735256195, 0.028545284643769264], [-0.06385818123817444, 0.16059665381908417, 0.041432417929172516]], "joints3d": [[[-427.85211181640625, 78.12532043457031, 4799.9560546875], [-394.7055969238281, 182.25682067871094, 4789.96728515625], [-508.1983947753906, 147.88839721679688, 4813.07275390625], [-395.90380859375, -21.12834930419922, 4829.65625], [-529.5444946289062, 566.804931640625, 4768.18212890625], [-700.6065063476562, 515.05712890625, 4820.88232421875], [-366.4740905761719, -150.38406372070312, 4773.599609375], [-733.9136352539062, 937.0301513671875, 4830.7021484375], [-863.5795288085938, 908.6023559570312, 4845.21826171875], [-353.6953125, -201.2391357421875, 4751.017578125], [-737.5396118164062, 1039.766357421875, 4737.0341796875], [-934.5009155273438, 987.41552734375, 4755.17578125], [-297.1820983886719, -406.5648498535156, 4743.64892578125], [-248.80848693847656, -295.59039306640625, 4740.8076171875], [-386.92401123046875, -335.1140441894531, 4781.9052734375], [-274.5718994140625, -477.87823486328125, 4692.3046875], [-166.54322814941406, -272.4410705566406, 4706.08642578125], [-471.48968505859375, -382.2732238769531, 4799.40234375], [-88.69876098632812, -8.800291061401367, 4686.7587890625], [-668.5088500976562, -212.63282775878906, 4857.8525390625], [-148.33026123046875, 187.7249755859375, 4523.9697265625], [-757.4159545898438, -45.029273986816406, 4666.28857421875]], [[-3834.985595703125, -2614.76318359375, 12279.8447265625], [-3785.831787109375, -2536.337890625, 12335.984375], [-3900.3330078125, -2533.369140625, 12259.884765625], [-3838.9296875, -2706.8173828125, 12278.7685546875], [-3682.72314453125, -2233.935546875, 12338.14453125], [-3929.463134765625, -2222.132080078125, 12173.1455078125], [-3803.877685546875, -2795.668212890625, 12219.5078125], [-3795.43017578125, -1952.4404296875, 12464.8720703125], [-3967.274658203125, -1944.4923095703125, 12344.1845703125], [-3786.488037109375, -2835.46240234375, 12192.2412109375], [-3721.49462890625, -1896.915771484375, 12399.5693359375], [-3962.488525390625, -1877.914794921875, 12254.466796875], [-3742.3427734375, -3017.674560546875, 12137.8046875], [-3705.375244140625, -2938.71484375, 12201.4853515625], [-3823.927734375, -2948.437744140625, 12133.3798828125], [-3703.169189453125, -3034.80322265625, 12081.1015625], [-3625.403564453125, -2934.929931640625, 12222.1923828125], [-3870.967529296875, -2930.98828125, 12064.5791015625], [-3546.912353515625, -2746.337158203125, 12305.7666015625], [-3901.46044921875, -2723.275390625, 12015.7578125], [-3614.4072265625, -2633.734375, 12148.2119140625], [-3692.30615234375, -2687.447998046875, 12029.927734375]]]}, {"global_orient": [[2.9673545360565186, 0.4313851594924927, -0.20920389890670776], [3.2302374839782715, 0.04144923388957977, 0.9540479779243469]], "body_pose": [[2.9673545360565186, 0.4313851594924927, -0.20920389890670776, 0.11092555522918701, -0.0036465481389313936, -0.15149912238121033, 0.067373126745224, -0.055489059537649155, -0.08586745709180832, 0.4618714153766632, -0.023008063435554504, 0.016435416415333748, 0.03729507699608803, -0.09379500895738602, -0.04772072285413742, -0.023610590025782585, 0.24970531463623047, -0.06452947109937668, -0.3017560839653015, -0.05747580528259277, -0.053916290402412415, 0.2579709589481354, 0.35584086179733276, 0.014028947800397873, 0.44761747121810913, -0.20826444029808044, 0.26682013273239136, 0.10461071878671646, -0.0007885342347435653, 0.034953344613313675, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.2160365730524063, 0.025731362402439117, -0.07579247653484344, 0.16605256497859955, -0.13276897370815277, -0.2721181809902191, -0.09512880444526672, 0.06556746363639832, 0.12019527703523636, 0.29529088735580444, 0.26684245467185974, 0.11433138698339462, 0.09246719628572464, -0.24471744894981384, -0.6930821537971497, 0.38223710656166077, 0.10638412088155746, 0.868687093257904, 0.49994462728500366, -0.6742034554481506, 0.06754616647958755, 0.469601035118103, 1.061930537223816, -0.1604696363210678, 0.3115849494934082, 0.17319008708000183, -0.5744310021400452, 0.08147810399532318, 0.09774524718523026, 0.426357239484787, -0.47043219208717346, -0.6614685654640198, 0.32699859142303467, -1.2455110549926758, 1.137829065322876, 1.5641480684280396], [3.2302374839782715, 0.04144923388957977, 0.9540479779243469, -0.3190194070339203, 0.11199627816677094, 0.1551019251346588, -0.3736623227596283, -0.0160069577395916, -0.1391785740852356, 0.4614027738571167, -0.06549161672592163, -0.0005042687407694757, 0.5459940433502197, -0.1484866738319397, -0.1723661571741104, 0.6004579067230225, -0.06360196322202682, 0.2362673580646515, -0.5558065176010132, 0.071727454662323, 0.034747254103422165, -0.29866135120391846, 0.1492234617471695, -0.09244436025619507, -0.06291433423757553, -0.22078265249729156, -0.1341298520565033, 0.511479914188385, -0.08873407542705536, -0.12267500907182693, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.02166133001446724, -0.08741021901369095, -0.07098658382892609, -0.1945260912179947, -0.3945469260215759, -0.19383834302425385, -0.461304247379303, 0.6860195398330688, 0.4415889382362366, -0.15168330073356628, -0.07617435604333878, 0.17044398188591003, 0.27169978618621826, -0.26663312315940857, -0.7984515428543091, 0.362540602684021, 0.23969486355781555, 0.7453324198722839, 0.02967427484691143, -1.3269473314285278, -0.11757729202508926, 0.3737608790397644, 1.5414937734603882, -0.056878697127103806, 0.47715142369270325, -0.7423836588859558, 1.4807794094085693, 0.1813298910856247, 0.34169960021972656, -0.27553993463516235, 1.3961533308029175, -0.7077808380126953, 2.4615864753723145, -1.1838228702545166, 0.22291076183319092, 1.075305700302124]], "betas": [[0.3992041051387787, 2.0514168739318848, 0.008460727520287037, 0.007844141684472561, 0.0011112893698737025, 0.0029846352990716696, 0.0014731668634340167, 0.00020908081205561757, 0.0008787870756350458, 0.0005454535712487996], [-2.0074636936187744, -0.2986014485359192, -0.002999071264639497, 0.005861639976501465, -0.00016731453069951385, 0.0005168114439584315, 0.0016855716239660978, 0.0018935299012809992, -0.0008392083109356463, 0.0024811294861137867]], "transl": [[0.04802677780389786, 0.1688157021999359, 0.018288234248757362], [-0.06128314509987831, 0.1631900668144226, 0.03272765874862671]], "joints3d": [[[-444.0102233886719, 83.89220428466797, 4829.4296875], [-409.9408264160156, 188.2716522216797, 4822.296875], [-525.3271484375, 153.5033721923828, 4839.7421875], [-413.4406433105469, -15.956208229064941, 4859.39306640625], [-540.0369873046875, 573.1640625, 4820.2734375], [-715.11865234375, 520.184814453125, 4839.59765625], [-382.01031494140625, -144.4073486328125, 4803.81689453125], [-732.8199462890625, 946.2811279296875, 4891.419921875], [-879.6348266601562, 911.8416137695312, 4857.88330078125], [-368.48345947265625, -195.51153564453125, 4782.03271484375], [-735.683837890625, 1047.43115234375, 4796.39794921875], [-942.830810546875, 994.7261352539062, 4766.119140625], [-310.9078369140625, -400.9658508300781, 4779.86865234375], [-262.6488952636719, -289.8382568359375, 4775.916015625], [-402.2107238769531, -329.39178466796875, 4814.50048828125], [-286.3050231933594, -471.651611328125, 4729.365234375], [-178.01748657226562, -269.259521484375, 4744.78857421875], [-485.38665771484375, -378.21392822265625, 4835.009765625], [-114.61549377441406, -2.0247251987457275, 4736.8505859375], [-668.783203125, -200.86117553710938, 4909.6982421875], [-181.04185485839844, 204.66741943359375, 4591.33642578125], [-752.1629028320312, -28.68039894104004, 4720.84521484375]], [[-3783.076416015625, -2626.4970703125, 12458.056640625], [-3736.608154296875, -2549.469970703125, 12519.9716796875], [-3849.4013671875, -2543.548583984375, 12443.4658203125], [-3786.114501953125, -2722.07568359375, 12451.3984375], [-3647.54833984375, -2230.614501953125, 12554.404296875], [-3880.9658203125, -2214.015380859375, 12373.9296875], [-3749.753662109375, -2814.77001953125, 12389.146484375], [-3751.644287109375, -1940.5267333984375, 12708.6376953125], [-3921.546875, -1927.47998046875, 12560.552734375], [-3732.240966796875, -2855.2353515625, 12360.7080078125], [-3674.718017578125, -1874.39306640625, 12648.9990234375], [-3918.80322265625, -1849.625244140625, 12473.7421875], [-3685.326416015625, -3040.551025390625, 12304.7255859375], [-3647.147705078125, -2959.0927734375, 12369.2353515625], [-3770.956787109375, -2971.445556640625, 12302.8291015625], [-3646.011474609375, -3056.39111328125, 12244.244140625], [-3564.04541015625, -2952.88818359375, 12386.6025390625], [-3823.13671875, -2952.485107421875, 12234.291015625], [-3508.916259765625, -2743.46875, 12463.1025390625], [-3850.546142578125, -2733.48046875, 12195.4951171875], [-3565.385009765625, -2633.447021484375, 12287.6171875], [-3629.897705078125, -2710.82421875, 12206.072265625]]]}, {"global_orient": [[2.9625730514526367, 0.42397934198379517, -0.17851915955543518], [3.2237071990966797, 0.003063187701627612, 1.0607390403747559]], "body_pose": [[2.9625730514526367, 0.42397934198379517, -0.17851915955543518, 0.0810016468167305, -0.022151228040456772, -0.13336627185344696, 0.06762928515672684, -0.04678989574313164, -0.09610336273908615, 0.45497798919677734, -0.010983044281601906, 0.015723275020718575, 0.10809551179409027, -0.033274199813604355, -0.06897035986185074, -0.011831813491880894, 0.23529817163944244, -0.06691901385784149, -0.2870666980743408, -0.05321534350514412, -0.04641810804605484, 0.08192235231399536, 0.34518393874168396, 0.06208449602127075, 0.3600471019744873, -0.26247432827949524, 0.29751259088516235, 0.12130063772201538, 0.007364650722593069, 0.023210488259792328, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.22861193120479584, 0.03160399571061134, -0.09449157863855362, 0.1422284096479416, -0.15178655087947845, -0.3080039918422699, -0.07985098659992218, 0.0984022244811058, 0.21518045663833618, 0.29290950298309326, 0.26408472657203674, 0.12386365979909897, 0.15738733112812042, -0.2403537929058075, -0.6613324880599976, 0.3701755702495575, 0.12104032933712006, 0.8364239931106567, 0.4556799530982971, -0.7814871072769165, 0.008100593462586403, 0.38279950618743896, 1.013967514038086, -0.14081408083438873, 0.358950674533844, 0.17677107453346252, -0.39854052662849426, 0.22089926898479462, 0.27032536268234253, -0.05585339292883873, -0.512801468372345, -0.5404573082923889, 0.09553029388189316, -0.8893096446990967, 0.33441704511642456, 1.5522350072860718], [3.2237071990966797, 0.003063187701627612, 1.0607390403747559, -0.2938605844974518, 0.05040382593870163, 0.11011141538619995, -0.3498803377151489, -0.06506970524787903, -0.22773195803165436, 0.42419886589050293, -0.08002837002277374, -0.02096915990114212, 0.5253686308860779, -0.08501123636960983, -0.1142478883266449, 0.6426542401313782, -0.1054217591881752, 0.2718290686607361, -0.5160208940505981, 0.07998815923929214, 0.040884703397750854, -0.33732327818870544, 0.09989182651042938, -0.2720499038696289, -0.10074972361326218, -0.17020836472511292, -0.021909115836024284, 0.5295466184616089, -0.089340440928936, -0.12631580233573914, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.12176994979381561, -0.14962372183799744, -0.02075447328388691, -0.2368728667497635, -0.4113815128803253, -0.18923968076705933, -0.5650308728218079, 0.6700235605239868, 0.4161302149295807, -0.0817672535777092, -0.03172525390982628, 0.15100404620170593, 0.2949144244194031, -0.14214535057544708, -0.7223557233810425, 0.42086198925971985, 0.2753894627094269, 0.7739580869674683, -0.07029033452272415, -1.3263665437698364, 0.008911460638046265, 0.15661874413490295, 1.4833447933197021, -0.067221999168396, 0.07959996163845062, -0.7562708854675293, 1.0766245126724243, 0.19388453662395477, 0.38639581203460693, -0.32064661383628845, 1.5543596744537354, -0.7928921580314636, 2.7791574001312256, -1.025728464126587, 0.12126719951629639, 1.1451811790466309]], "betas": [[0.16626344621181488, 1.973799467086792, 0.006038443185389042, 0.007730154320597649, 0.0013460019836202264, 0.0026608260814100504, 0.0011096721282228827, 0.0007484631496481597, 0.0010613873600959778, 0.0005700745387002826], [-1.6104986667633057, -0.2972666621208191, -0.00345024187117815, 0.00570930540561676, 0.0013729545753449202, 0.00025406168424524367, 0.0017391435103490949, 0.0019575408659875393, -0.00033018746762536466, 0.0028982446528971195]], "transl": [[0.04658865928649902, 0.16607943177223206, 0.0221999604254961], [-0.06468313932418823, 0.17091944813728333, 0.03115759789943695]], "joints3d": [[[-460.3284606933594, 91.35868835449219, 4840.3369140625], [-425.4728698730469, 194.89686584472656, 4833.56201171875], [-541.552001953125, 160.47442626953125, 4848.60888671875], [-431.1678466796875, -7.005157470703125, 4870.40380859375], [-547.7308349609375, 576.0291137695312, 4814.26611328125], [-731.2373046875, 520.63671875, 4843.0556640625], [-398.7720031738281, -134.2307891845703, 4818.345703125], [-735.5613403320312, 941.7724609375, 4895.7939453125], [-896.9367065429688, 904.32470703125, 4861.56396484375], [-385.43365478515625, -184.43972778320312, 4796.3935546875], [-724.515625, 1029.62158203125, 4791.44580078125], [-959.9940185546875, 977.3128051757812, 4764.6259765625], [-328.9931945800781, -387.9292907714844, 4792.92626953125], [-281.0124816894531, -278.21917724609375, 4792.5791015625], [-420.1863708496094, -317.4958801269531, 4824.68408203125], [-301.6676025390625, -456.38153076171875, 4742.86376953125], [-197.27989196777344, -254.70567321777344, 4764.71044921875], [-507.5954895019531, -357.43475341796875, 4838.8671875], [-133.44265747070312, 8.597759246826172, 4763.41357421875], [-680.43603515625, -170.51220703125, 4901.3935546875], [-226.99801635742188, 204.7892608642578, 4625.85595703125], [-749.9457397460938, 6.486949920654297, 4717.1162109375]], [[-3974.465576171875, -2795.736572265625, 13326.7744140625], [-3929.7568359375, -2720.18359375, 13393.9248046875], [-4038.38720703125, -2709.396240234375, 13311.111328125], [-3980.042724609375, -2894.4169921875, 13317.626953125], [-3850.26123046875, -2391.832275390625, 13439.6943359375], [-4092.685791015625, -2374.3798828125, 13239.48046875], [-3940.473388671875, -2990.777099609375, 13256.40625], [-3956.35302734375, -2096.842529296875, 13606.86328125], [-4145.5673828125, -2092.052490234375, 13448.36328125], [-3921.86083984375, -3032.307373046875, 13227.8046875], [-3879.1083984375, -2028.3009033203125, 13543.9521484375], [-4141.97900390625, -2006.8631591796875, 13363.6376953125], [-3867.96435546875, -3217.384521484375, 13163.7861328125], [-3833.743408203125, -3137.69677734375, 13236.7109375], [-3956.892578125, -3147.9658203125, 13160.1923828125], [-3829.006103515625, -3241.987060546875, 13103.978515625], [-3749.608154296875, -3131.368408203125, 13259.9296875], [-4007.578369140625, -3129.249267578125, 13086.8984375], [-3678.93017578125, -2932.43408203125, 13364.80859375], [-4022.728515625, -2904.1572265625, 13041.7861328125], [-3678.3857421875, -2803.07373046875, 13185.1318359375], [-3795.02001953125, -2885.85791015625, 13038.240234375]]]}] \ No newline at end of file diff --git a/style.css b/style.css new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/style.css @@ -0,0 +1 @@ +