2023-07-19 17:37:20 +08:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
|
|
|
|
'''
|
2024-03-12 23:08:12 +08:00
|
|
|
###########################################################################
|
|
|
|
## POSE2SIM ##
|
|
|
|
###########################################################################
|
|
|
|
|
|
|
|
This repository offers a way to perform markerless kinematics, and gives an
|
|
|
|
example workflow from an Openpose input to an OpenSim result.
|
|
|
|
|
|
|
|
It offers tools for:
|
|
|
|
- Cameras calibration,
|
Pose estimation test (#116)
Edits from @hunminkim98's awesome work at integrating pose estimation into Pose2Sim with RTMLib. Most of the changes in syntax are not necessarily better, it is mostly for the code to be more consistent with the rest of the library. Thank you again for your fantastic work!
General:
- Automatically detects whether a valid CUDA install is available. If so, use the GPU with the ONNXRuntime backend. Otherwise, use the CPU with the OpenVINO backend
- The tensorflow version used for marker augmentation was incompatible with the cuda torch installation for pose estimation: edited code and models for it to work with the latest tf version.
- Added logging information to pose estimation
- Readme.md: provided an installation procedure for CUDA (took me a while to find something simple and robust)
- Readme.md: added information about PoseEstimation with RTMLib
- added poseEstimation to tests.py
- created videos for the multi-person case (used to only have json, no video), and reorganized Demo folders. Had to recreate calibration file as well
Json files:
- the json files only saved one person, I made it save all the detected ones
- tracking was not taken into account by rtmlib, which caused issues in synchronization: fixed, waiting for merge
- took the save_to_openpose function out from the main function
- minified the json files (they take less space when all spaces are removed)
Detection results:
- Compared the triangulated locations of RTMpose keypoints to the ones of OpenPose to potentially edit model marker locations on OpenSim. Did not seem to need it.
Others in Config.toml:
- removed the "to_openpose" option, which is not needed
- added the flag: save_video = 'to_images' # 'to_video' or 'to_images' or ['to_video', 'to_images']
- changed the way frame_range was handled (made me change synchronization in depth, as well as personAssociation and triangulation)
- added the flag: time_range_around_maxspeed in synchronization
- automatically detect framerate from video, or set to 60 fps if we work from images (or give a value)
- frame_range -> time_range
- moved height and weight to project (only read for markerAugmentation, and in the future for automatic scaling)
- removed reorder_trc from triangulation and Config -> call it for markerAugmentation instead
Others:
- Provided an installation procedure for OpenSim (for the future) and made continuous installation check its install (a bit harder since it cannot be installed via pip)
- scaling from motion instead of static pose (will have to study whether it's as good or not)
- added logging to synchronization
- Struggled quite a bit with continuous integration
* Starting point of integrating RTMPose into Pose2Sim. (#111)
* RTM_to_Open
Convert format from RTMPose to OpenPose
* rtm_intergrated
* rtm_integrated
* rtm_integrated
* rtm_integrated
* rtm
* Delete build/lib/Pose2Sim directory
* rtm
* Delete build/lib/Pose2Sim directory
* Delete onnxruntime-gpu
* device = cpu
* add pose folder
* Update tests.py
* added annotation
* fix typo
* Should work be still lots of tests to run. Detailed commit coming soon
* intermediary commit
* last checks before v0.9.0
* Update continuous-integration.yml
* Update tests.py
* replaced tabs with spaces
* unittest issue
* unittest typo
* deactivated display for CI test of pose detection
* Try to make continuous integration work
* a
* b
* c
* d
* e
* f
* g
* h
* i
* j
* k
* l
---------
Co-authored-by: HunMinKim <144449115+hunminkim98@users.noreply.github.com>
2024-07-09 22:39:33 +08:00
|
|
|
- 2D pose estimation,
|
|
|
|
- Camera synchronization,
|
2024-03-12 23:08:12 +08:00
|
|
|
- Tracking the person of interest,
|
|
|
|
- Robust triangulation,
|
|
|
|
- Filtration,
|
|
|
|
- Marker augmentation,
|
|
|
|
- OpenSim scaling and inverse kinematics
|
|
|
|
|
Pose estimation test (#116)
Edits from @hunminkim98's awesome work at integrating pose estimation into Pose2Sim with RTMLib. Most of the changes in syntax are not necessarily better, it is mostly for the code to be more consistent with the rest of the library. Thank you again for your fantastic work!
General:
- Automatically detects whether a valid CUDA install is available. If so, use the GPU with the ONNXRuntime backend. Otherwise, use the CPU with the OpenVINO backend
- The tensorflow version used for marker augmentation was incompatible with the cuda torch installation for pose estimation: edited code and models for it to work with the latest tf version.
- Added logging information to pose estimation
- Readme.md: provided an installation procedure for CUDA (took me a while to find something simple and robust)
- Readme.md: added information about PoseEstimation with RTMLib
- added poseEstimation to tests.py
- created videos for the multi-person case (used to only have json, no video), and reorganized Demo folders. Had to recreate calibration file as well
Json files:
- the json files only saved one person, I made it save all the detected ones
- tracking was not taken into account by rtmlib, which caused issues in synchronization: fixed, waiting for merge
- took the save_to_openpose function out from the main function
- minified the json files (they take less space when all spaces are removed)
Detection results:
- Compared the triangulated locations of RTMpose keypoints to the ones of OpenPose to potentially edit model marker locations on OpenSim. Did not seem to need it.
Others in Config.toml:
- removed the "to_openpose" option, which is not needed
- added the flag: save_video = 'to_images' # 'to_video' or 'to_images' or ['to_video', 'to_images']
- changed the way frame_range was handled (made me change synchronization in depth, as well as personAssociation and triangulation)
- added the flag: time_range_around_maxspeed in synchronization
- automatically detect framerate from video, or set to 60 fps if we work from images (or give a value)
- frame_range -> time_range
- moved height and weight to project (only read for markerAugmentation, and in the future for automatic scaling)
- removed reorder_trc from triangulation and Config -> call it for markerAugmentation instead
Others:
- Provided an installation procedure for OpenSim (for the future) and made continuous installation check its install (a bit harder since it cannot be installed via pip)
- scaling from motion instead of static pose (will have to study whether it's as good or not)
- added logging to synchronization
- Struggled quite a bit with continuous integration
* Starting point of integrating RTMPose into Pose2Sim. (#111)
* RTM_to_Open
Convert format from RTMPose to OpenPose
* rtm_intergrated
* rtm_integrated
* rtm_integrated
* rtm_integrated
* rtm
* Delete build/lib/Pose2Sim directory
* rtm
* Delete build/lib/Pose2Sim directory
* Delete onnxruntime-gpu
* device = cpu
* add pose folder
* Update tests.py
* added annotation
* fix typo
* Should work be still lots of tests to run. Detailed commit coming soon
* intermediary commit
* last checks before v0.9.0
* Update continuous-integration.yml
* Update tests.py
* replaced tabs with spaces
* unittest issue
* unittest typo
* deactivated display for CI test of pose detection
* Try to make continuous integration work
* a
* b
* c
* d
* e
* f
* g
* h
* i
* j
* k
* l
---------
Co-authored-by: HunMinKim <144449115+hunminkim98@users.noreply.github.com>
2024-07-09 22:39:33 +08:00
|
|
|
It has been tested on Windows, Linux and MacOS, and works for any Python version >= 3.9
|
2024-03-12 23:08:12 +08:00
|
|
|
|
|
|
|
Installation:
|
|
|
|
# Open Anaconda prompt. Type:
|
Pose estimation test (#116)
Edits from @hunminkim98's awesome work at integrating pose estimation into Pose2Sim with RTMLib. Most of the changes in syntax are not necessarily better, it is mostly for the code to be more consistent with the rest of the library. Thank you again for your fantastic work!
General:
- Automatically detects whether a valid CUDA install is available. If so, use the GPU with the ONNXRuntime backend. Otherwise, use the CPU with the OpenVINO backend
- The tensorflow version used for marker augmentation was incompatible with the cuda torch installation for pose estimation: edited code and models for it to work with the latest tf version.
- Added logging information to pose estimation
- Readme.md: provided an installation procedure for CUDA (took me a while to find something simple and robust)
- Readme.md: added information about PoseEstimation with RTMLib
- added poseEstimation to tests.py
- created videos for the multi-person case (used to only have json, no video), and reorganized Demo folders. Had to recreate calibration file as well
Json files:
- the json files only saved one person, I made it save all the detected ones
- tracking was not taken into account by rtmlib, which caused issues in synchronization: fixed, waiting for merge
- took the save_to_openpose function out from the main function
- minified the json files (they take less space when all spaces are removed)
Detection results:
- Compared the triangulated locations of RTMpose keypoints to the ones of OpenPose to potentially edit model marker locations on OpenSim. Did not seem to need it.
Others in Config.toml:
- removed the "to_openpose" option, which is not needed
- added the flag: save_video = 'to_images' # 'to_video' or 'to_images' or ['to_video', 'to_images']
- changed the way frame_range was handled (made me change synchronization in depth, as well as personAssociation and triangulation)
- added the flag: time_range_around_maxspeed in synchronization
- automatically detect framerate from video, or set to 60 fps if we work from images (or give a value)
- frame_range -> time_range
- moved height and weight to project (only read for markerAugmentation, and in the future for automatic scaling)
- removed reorder_trc from triangulation and Config -> call it for markerAugmentation instead
Others:
- Provided an installation procedure for OpenSim (for the future) and made continuous installation check its install (a bit harder since it cannot be installed via pip)
- scaling from motion instead of static pose (will have to study whether it's as good or not)
- added logging to synchronization
- Struggled quite a bit with continuous integration
* Starting point of integrating RTMPose into Pose2Sim. (#111)
* RTM_to_Open
Convert format from RTMPose to OpenPose
* rtm_intergrated
* rtm_integrated
* rtm_integrated
* rtm_integrated
* rtm
* Delete build/lib/Pose2Sim directory
* rtm
* Delete build/lib/Pose2Sim directory
* Delete onnxruntime-gpu
* device = cpu
* add pose folder
* Update tests.py
* added annotation
* fix typo
* Should work be still lots of tests to run. Detailed commit coming soon
* intermediary commit
* last checks before v0.9.0
* Update continuous-integration.yml
* Update tests.py
* replaced tabs with spaces
* unittest issue
* unittest typo
* deactivated display for CI test of pose detection
* Try to make continuous integration work
* a
* b
* c
* d
* e
* f
* g
* h
* i
* j
* k
* l
---------
Co-authored-by: HunMinKim <144449115+hunminkim98@users.noreply.github.com>
2024-07-09 22:39:33 +08:00
|
|
|
# - conda create -n Pose2Sim python=3.9
|
2024-03-12 23:08:12 +08:00
|
|
|
# - conda activate Pose2Sim
|
Pose estimation test (#116)
Edits from @hunminkim98's awesome work at integrating pose estimation into Pose2Sim with RTMLib. Most of the changes in syntax are not necessarily better, it is mostly for the code to be more consistent with the rest of the library. Thank you again for your fantastic work!
General:
- Automatically detects whether a valid CUDA install is available. If so, use the GPU with the ONNXRuntime backend. Otherwise, use the CPU with the OpenVINO backend
- The tensorflow version used for marker augmentation was incompatible with the cuda torch installation for pose estimation: edited code and models for it to work with the latest tf version.
- Added logging information to pose estimation
- Readme.md: provided an installation procedure for CUDA (took me a while to find something simple and robust)
- Readme.md: added information about PoseEstimation with RTMLib
- added poseEstimation to tests.py
- created videos for the multi-person case (used to only have json, no video), and reorganized Demo folders. Had to recreate calibration file as well
Json files:
- the json files only saved one person, I made it save all the detected ones
- tracking was not taken into account by rtmlib, which caused issues in synchronization: fixed, waiting for merge
- took the save_to_openpose function out from the main function
- minified the json files (they take less space when all spaces are removed)
Detection results:
- Compared the triangulated locations of RTMpose keypoints to the ones of OpenPose to potentially edit model marker locations on OpenSim. Did not seem to need it.
Others in Config.toml:
- removed the "to_openpose" option, which is not needed
- added the flag: save_video = 'to_images' # 'to_video' or 'to_images' or ['to_video', 'to_images']
- changed the way frame_range was handled (made me change synchronization in depth, as well as personAssociation and triangulation)
- added the flag: time_range_around_maxspeed in synchronization
- automatically detect framerate from video, or set to 60 fps if we work from images (or give a value)
- frame_range -> time_range
- moved height and weight to project (only read for markerAugmentation, and in the future for automatic scaling)
- removed reorder_trc from triangulation and Config -> call it for markerAugmentation instead
Others:
- Provided an installation procedure for OpenSim (for the future) and made continuous installation check its install (a bit harder since it cannot be installed via pip)
- scaling from motion instead of static pose (will have to study whether it's as good or not)
- added logging to synchronization
- Struggled quite a bit with continuous integration
* Starting point of integrating RTMPose into Pose2Sim. (#111)
* RTM_to_Open
Convert format from RTMPose to OpenPose
* rtm_intergrated
* rtm_integrated
* rtm_integrated
* rtm_integrated
* rtm
* Delete build/lib/Pose2Sim directory
* rtm
* Delete build/lib/Pose2Sim directory
* Delete onnxruntime-gpu
* device = cpu
* add pose folder
* Update tests.py
* added annotation
* fix typo
* Should work be still lots of tests to run. Detailed commit coming soon
* intermediary commit
* last checks before v0.9.0
* Update continuous-integration.yml
* Update tests.py
* replaced tabs with spaces
* unittest issue
* unittest typo
* deactivated display for CI test of pose detection
* Try to make continuous integration work
* a
* b
* c
* d
* e
* f
* g
* h
* i
* j
* k
* l
---------
Co-authored-by: HunMinKim <144449115+hunminkim98@users.noreply.github.com>
2024-07-09 22:39:33 +08:00
|
|
|
# - conda install -c opensim-org opensim -y
|
|
|
|
# - pip install Pose2Sim
|
2024-03-12 23:08:12 +08:00
|
|
|
|
|
|
|
Usage:
|
|
|
|
# First run Pose estimation and organize your directories (see Readme.md)
|
|
|
|
from Pose2Sim import Pose2Sim
|
|
|
|
Pose2Sim.calibration()
|
Pose estimation test (#116)
Edits from @hunminkim98's awesome work at integrating pose estimation into Pose2Sim with RTMLib. Most of the changes in syntax are not necessarily better, it is mostly for the code to be more consistent with the rest of the library. Thank you again for your fantastic work!
General:
- Automatically detects whether a valid CUDA install is available. If so, use the GPU with the ONNXRuntime backend. Otherwise, use the CPU with the OpenVINO backend
- The tensorflow version used for marker augmentation was incompatible with the cuda torch installation for pose estimation: edited code and models for it to work with the latest tf version.
- Added logging information to pose estimation
- Readme.md: provided an installation procedure for CUDA (took me a while to find something simple and robust)
- Readme.md: added information about PoseEstimation with RTMLib
- added poseEstimation to tests.py
- created videos for the multi-person case (used to only have json, no video), and reorganized Demo folders. Had to recreate calibration file as well
Json files:
- the json files only saved one person, I made it save all the detected ones
- tracking was not taken into account by rtmlib, which caused issues in synchronization: fixed, waiting for merge
- took the save_to_openpose function out from the main function
- minified the json files (they take less space when all spaces are removed)
Detection results:
- Compared the triangulated locations of RTMpose keypoints to the ones of OpenPose to potentially edit model marker locations on OpenSim. Did not seem to need it.
Others in Config.toml:
- removed the "to_openpose" option, which is not needed
- added the flag: save_video = 'to_images' # 'to_video' or 'to_images' or ['to_video', 'to_images']
- changed the way frame_range was handled (made me change synchronization in depth, as well as personAssociation and triangulation)
- added the flag: time_range_around_maxspeed in synchronization
- automatically detect framerate from video, or set to 60 fps if we work from images (or give a value)
- frame_range -> time_range
- moved height and weight to project (only read for markerAugmentation, and in the future for automatic scaling)
- removed reorder_trc from triangulation and Config -> call it for markerAugmentation instead
Others:
- Provided an installation procedure for OpenSim (for the future) and made continuous installation check its install (a bit harder since it cannot be installed via pip)
- scaling from motion instead of static pose (will have to study whether it's as good or not)
- added logging to synchronization
- Struggled quite a bit with continuous integration
* Starting point of integrating RTMPose into Pose2Sim. (#111)
* RTM_to_Open
Convert format from RTMPose to OpenPose
* rtm_intergrated
* rtm_integrated
* rtm_integrated
* rtm_integrated
* rtm
* Delete build/lib/Pose2Sim directory
* rtm
* Delete build/lib/Pose2Sim directory
* Delete onnxruntime-gpu
* device = cpu
* add pose folder
* Update tests.py
* added annotation
* fix typo
* Should work be still lots of tests to run. Detailed commit coming soon
* intermediary commit
* last checks before v0.9.0
* Update continuous-integration.yml
* Update tests.py
* replaced tabs with spaces
* unittest issue
* unittest typo
* deactivated display for CI test of pose detection
* Try to make continuous integration work
* a
* b
* c
* d
* e
* f
* g
* h
* i
* j
* k
* l
---------
Co-authored-by: HunMinKim <144449115+hunminkim98@users.noreply.github.com>
2024-07-09 22:39:33 +08:00
|
|
|
Pose2Sim.poseEstimation()
|
|
|
|
Pose2Sim.synchronization()
|
2024-03-12 23:08:12 +08:00
|
|
|
Pose2Sim.personAssociation()
|
|
|
|
Pose2Sim.triangulation()
|
|
|
|
Pose2Sim.filtering()
|
|
|
|
Pose2Sim.markerAugmentation()
|
|
|
|
# Then run OpenSim (see Readme.md)
|
2023-07-19 17:37:20 +08:00
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
## INIT
|
|
|
|
import toml
|
|
|
|
import os
|
|
|
|
import time
|
2023-12-08 00:08:34 +08:00
|
|
|
from copy import deepcopy
|
2023-07-19 17:37:20 +08:00
|
|
|
import logging, logging.handlers
|
2024-03-05 09:59:25 +08:00
|
|
|
from datetime import datetime
|
2023-07-19 17:37:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
## AUTHORSHIP INFORMATION
|
|
|
|
__author__ = "David Pagnon"
|
|
|
|
__copyright__ = "Copyright 2021, Pose2Sim"
|
|
|
|
__credits__ = ["David Pagnon"]
|
|
|
|
__license__ = "BSD 3-Clause License"
|
2024-07-10 16:12:57 +08:00
|
|
|
__version__ = "0.9.4"
|
2023-07-19 17:37:20 +08:00
|
|
|
__maintainer__ = "David Pagnon"
|
|
|
|
__email__ = "contact@david-pagnon.com"
|
|
|
|
__status__ = "Development"
|
|
|
|
|
|
|
|
|
|
|
|
## FUNCTIONS
|
2023-12-09 19:53:43 +08:00
|
|
|
def setup_logging(session_dir):
|
|
|
|
'''
|
|
|
|
Create logging file and stream handlers
|
|
|
|
'''
|
2024-07-10 02:54:18 +08:00
|
|
|
|
2023-12-09 19:53:43 +08:00
|
|
|
logging.basicConfig(format='%(message)s', level=logging.INFO,
|
|
|
|
handlers = [logging.handlers.TimedRotatingFileHandler(os.path.join(session_dir, 'logs.txt'), when='D', interval=7), logging.StreamHandler()])
|
|
|
|
|
|
|
|
|
2023-12-08 00:08:34 +08:00
|
|
|
def recursive_update(dict_to_update, dict_with_new_values):
|
|
|
|
'''
|
|
|
|
Update nested dictionaries without overwriting existing keys in any level of nesting
|
2023-12-06 16:48:11 +08:00
|
|
|
|
2023-12-08 00:08:34 +08:00
|
|
|
Example:
|
|
|
|
dict_to_update = {'key': {'key_1': 'val_1', 'key_2': 'val_2'}}
|
|
|
|
dict_with_new_values = {'key': {'key_1': 'val_1_new'}}
|
|
|
|
returns {'key': {'key_1': 'val_1_new', 'key_2': 'val_2'}}
|
|
|
|
while dict_to_update.update(dict_with_new_values) would return {'key': {'key_1': 'val_1_new'}}
|
|
|
|
'''
|
|
|
|
|
|
|
|
for key, value in dict_with_new_values.items():
|
|
|
|
if key in dict_to_update and isinstance(value, dict) and isinstance(dict_to_update[key], dict):
|
|
|
|
# Recursively update nested dictionaries
|
|
|
|
dict_to_update[key] = recursive_update(dict_to_update[key], value)
|
|
|
|
else:
|
|
|
|
# Update or add new key-value pairs
|
|
|
|
dict_to_update[key] = value
|
|
|
|
|
|
|
|
return dict_to_update
|
|
|
|
|
|
|
|
|
2023-12-10 05:06:57 +08:00
|
|
|
def determine_level(config_dir):
|
|
|
|
'''
|
|
|
|
Determine the level at which the function is called.
|
|
|
|
Level = 1: Trial folder
|
|
|
|
Level = 2: Participant folder
|
|
|
|
Level = 3: Session folder
|
|
|
|
'''
|
|
|
|
|
|
|
|
len_paths = [len(root.split(os.sep)) for root,dirs,files in os.walk(config_dir) if 'Config.toml' in files]
|
2024-02-05 07:04:36 +08:00
|
|
|
if len_paths == []:
|
|
|
|
raise FileNotFoundError('Please run Pose2Sim from a Session, Participant, or Trial directory.')
|
2023-12-10 05:06:57 +08:00
|
|
|
level = max(len_paths) - min(len_paths) + 1
|
|
|
|
return level
|
|
|
|
|
|
|
|
|
|
|
|
def read_config_files(config):
|
2023-12-08 00:08:34 +08:00
|
|
|
'''
|
|
|
|
Read Session, Participant, and Trial configuration files,
|
|
|
|
and output a dictionary with all the parameters.
|
|
|
|
'''
|
|
|
|
|
2023-12-10 05:06:57 +08:00
|
|
|
if type(config)==dict:
|
|
|
|
level = 3 # log_dir = os.getcwd()
|
|
|
|
config_dicts = [config]
|
|
|
|
if config_dicts[0].get('project').get('project_dir') == None:
|
|
|
|
raise ValueError('Please specify the project directory in config_dict:\n \
|
|
|
|
config_dict.get("project").update({"project_dir":"<YOUR_PROJECT_DIRECTORY>"})')
|
|
|
|
else:
|
|
|
|
# if launched without an argument, config == None, else it is the path to the config directory
|
|
|
|
config_dir = ['.' if config == None else config][0]
|
|
|
|
level = determine_level(config_dir)
|
|
|
|
|
|
|
|
# Trial level
|
|
|
|
if level == 1:
|
2024-04-14 00:42:30 +08:00
|
|
|
try:
|
|
|
|
# if batch
|
|
|
|
session_config_dict = toml.load(os.path.join(config_dir, '..','..','Config.toml'))
|
|
|
|
participant_config_dict = toml.load(os.path.join(config_dir, '..','Config.toml'))
|
|
|
|
session_config_dict = recursive_update(session_config_dict,participant_config_dict)
|
|
|
|
trial_config_dict = toml.load(os.path.join(config_dir, 'Config.toml'))
|
|
|
|
session_config_dict = recursive_update(session_config_dict,trial_config_dict)
|
|
|
|
except:
|
|
|
|
# if single trial
|
|
|
|
session_config_dict = toml.load(os.path.join(config_dir, 'Config.toml'))
|
2023-12-10 05:06:57 +08:00
|
|
|
session_config_dict.get("project").update({"project_dir":config_dir})
|
|
|
|
config_dicts = [session_config_dict]
|
|
|
|
|
|
|
|
# Participant level
|
|
|
|
if level == 2:
|
|
|
|
session_config_dict = toml.load(os.path.join(config_dir, '..','Config.toml'))
|
|
|
|
participant_config_dict = toml.load(os.path.join(config_dir, 'Config.toml'))
|
|
|
|
config_dicts = []
|
|
|
|
# Create config dictionaries for all trials of the participant
|
|
|
|
for (root,dirs,files) in os.walk(config_dir):
|
|
|
|
if 'Config.toml' in files and root != config_dir:
|
2023-12-08 00:08:34 +08:00
|
|
|
trial_config_dict = toml.load(os.path.join(root, files[0]))
|
|
|
|
# deep copy, otherwise session_config_dict is modified at each iteration within the config_dicts list
|
|
|
|
temp_dict = deepcopy(session_config_dict)
|
|
|
|
temp_dict = recursive_update(temp_dict,participant_config_dict)
|
|
|
|
temp_dict = recursive_update(temp_dict,trial_config_dict)
|
2023-12-10 05:06:57 +08:00
|
|
|
temp_dict.get("project").update({"project_dir":os.path.join(config_dir, os.path.relpath(root))})
|
|
|
|
if not os.path.basename(root) in temp_dict.get("project").get('exclude_from_batch'):
|
2023-12-08 00:08:34 +08:00
|
|
|
config_dicts.append(temp_dict)
|
|
|
|
|
2023-12-10 05:06:57 +08:00
|
|
|
# Session level
|
|
|
|
if level == 3:
|
|
|
|
session_config_dict = toml.load(os.path.join(config_dir, 'Config.toml'))
|
|
|
|
config_dicts = []
|
|
|
|
# Create config dictionaries for all trials of all participants of the session
|
|
|
|
for (root,dirs,files) in os.walk(config_dir):
|
|
|
|
if 'Config.toml' in files and root != config_dir:
|
|
|
|
# participant
|
|
|
|
if determine_level(root) == 2:
|
|
|
|
participant_config_dict = toml.load(os.path.join(root, files[0]))
|
|
|
|
# trial
|
|
|
|
elif determine_level(root) == 1:
|
|
|
|
trial_config_dict = toml.load(os.path.join(root, files[0]))
|
|
|
|
# deep copy, otherwise session_config_dict is modified at each iteration within the config_dicts list
|
|
|
|
temp_dict = deepcopy(session_config_dict)
|
|
|
|
temp_dict = recursive_update(temp_dict,participant_config_dict)
|
|
|
|
temp_dict = recursive_update(temp_dict,trial_config_dict)
|
|
|
|
temp_dict.get("project").update({"project_dir":os.path.join(config_dir, os.path.relpath(root))})
|
|
|
|
if not os.path.relpath(root) in [os.path.relpath(p) for p in temp_dict.get("project").get('exclude_from_batch')]:
|
|
|
|
config_dicts.append(temp_dict)
|
|
|
|
|
|
|
|
return level, config_dicts
|
2023-07-19 17:37:20 +08:00
|
|
|
|
|
|
|
|
2023-12-08 16:39:34 +08:00
|
|
|
def calibration(config=None):
|
2023-09-18 02:48:13 +08:00
|
|
|
'''
|
2023-12-06 16:48:11 +08:00
|
|
|
Cameras calibration from checkerboards or from qualisys files.
|
2023-09-20 20:39:40 +08:00
|
|
|
|
2023-12-10 05:06:57 +08:00
|
|
|
config can be a dictionary,
|
2023-12-17 05:15:12 +08:00
|
|
|
or a the directory path of a trial, participant, or session,
|
|
|
|
or the function can be called without an argument, in which case it the config directory is the current one.
|
2023-09-18 02:48:13 +08:00
|
|
|
'''
|
2023-12-06 16:48:11 +08:00
|
|
|
|
|
|
|
from Pose2Sim.calibration import calibrate_cams_all
|
2023-12-08 00:08:34 +08:00
|
|
|
|
2023-12-10 05:06:57 +08:00
|
|
|
level, config_dicts = read_config_files(config)
|
|
|
|
config_dict = config_dicts[0]
|
2024-04-16 05:40:01 +08:00
|
|
|
try:
|
|
|
|
session_dir = os.path.realpath([os.getcwd() if level==3 else os.path.join(os.getcwd(), '..') if level==2 else os.path.join(os.getcwd(), '..', '..')][0])
|
|
|
|
[os.path.join(session_dir, c) for c in os.listdir(session_dir) if 'calib' in c.lower() ][0]
|
|
|
|
except:
|
|
|
|
session_dir = os.path.realpath(os.getcwd())
|
2023-12-08 16:39:34 +08:00
|
|
|
config_dict.get("project").update({"project_dir":session_dir})
|
2023-12-06 16:48:11 +08:00
|
|
|
|
2023-12-08 16:39:34 +08:00
|
|
|
# Set up logging
|
2023-12-09 19:53:43 +08:00
|
|
|
setup_logging(session_dir)
|
2024-03-05 09:59:25 +08:00
|
|
|
currentDateAndTime = datetime.now()
|
2023-09-18 02:48:13 +08:00
|
|
|
|
2023-12-17 05:15:12 +08:00
|
|
|
# Run calibration
|
2024-04-27 05:15:34 +08:00
|
|
|
calib_dir = [os.path.join(session_dir, c) for c in os.listdir(session_dir) if os.path.isdir(os.path.join(session_dir, c)) and 'calib' in c.lower()][0]
|
2023-09-18 02:48:13 +08:00
|
|
|
logging.info("\n\n---------------------------------------------------------------------")
|
2023-12-06 16:48:11 +08:00
|
|
|
logging.info("Camera calibration")
|
2024-03-05 09:59:25 +08:00
|
|
|
logging.info(f"On {currentDateAndTime.strftime('%A %d. %B %Y, %H:%M:%S')}")
|
2023-09-18 02:48:13 +08:00
|
|
|
logging.info("---------------------------------------------------------------------")
|
2023-12-08 16:39:34 +08:00
|
|
|
logging.info(f"\nCalibration directory: {calib_dir}")
|
2023-09-18 02:48:13 +08:00
|
|
|
start = time.time()
|
|
|
|
|
2023-12-06 16:48:11 +08:00
|
|
|
calibrate_cams_all(config_dict)
|
2023-09-18 02:48:13 +08:00
|
|
|
|
|
|
|
end = time.time()
|
2024-04-15 21:36:47 +08:00
|
|
|
logging.info(f'\nCalibration took {end-start:.2f} s.')
|
2023-09-18 02:48:13 +08:00
|
|
|
|
|
|
|
|
2023-12-08 16:39:34 +08:00
|
|
|
def poseEstimation(config=None):
|
2023-07-19 17:37:20 +08:00
|
|
|
'''
|
Pose estimation test (#116)
Edits from @hunminkim98's awesome work at integrating pose estimation into Pose2Sim with RTMLib. Most of the changes in syntax are not necessarily better, it is mostly for the code to be more consistent with the rest of the library. Thank you again for your fantastic work!
General:
- Automatically detects whether a valid CUDA install is available. If so, use the GPU with the ONNXRuntime backend. Otherwise, use the CPU with the OpenVINO backend
- The tensorflow version used for marker augmentation was incompatible with the cuda torch installation for pose estimation: edited code and models for it to work with the latest tf version.
- Added logging information to pose estimation
- Readme.md: provided an installation procedure for CUDA (took me a while to find something simple and robust)
- Readme.md: added information about PoseEstimation with RTMLib
- added poseEstimation to tests.py
- created videos for the multi-person case (used to only have json, no video), and reorganized Demo folders. Had to recreate calibration file as well
Json files:
- the json files only saved one person, I made it save all the detected ones
- tracking was not taken into account by rtmlib, which caused issues in synchronization: fixed, waiting for merge
- took the save_to_openpose function out from the main function
- minified the json files (they take less space when all spaces are removed)
Detection results:
- Compared the triangulated locations of RTMpose keypoints to the ones of OpenPose to potentially edit model marker locations on OpenSim. Did not seem to need it.
Others in Config.toml:
- removed the "to_openpose" option, which is not needed
- added the flag: save_video = 'to_images' # 'to_video' or 'to_images' or ['to_video', 'to_images']
- changed the way frame_range was handled (made me change synchronization in depth, as well as personAssociation and triangulation)
- added the flag: time_range_around_maxspeed in synchronization
- automatically detect framerate from video, or set to 60 fps if we work from images (or give a value)
- frame_range -> time_range
- moved height and weight to project (only read for markerAugmentation, and in the future for automatic scaling)
- removed reorder_trc from triangulation and Config -> call it for markerAugmentation instead
Others:
- Provided an installation procedure for OpenSim (for the future) and made continuous installation check its install (a bit harder since it cannot be installed via pip)
- scaling from motion instead of static pose (will have to study whether it's as good or not)
- added logging to synchronization
- Struggled quite a bit with continuous integration
* Starting point of integrating RTMPose into Pose2Sim. (#111)
* RTM_to_Open
Convert format from RTMPose to OpenPose
* rtm_intergrated
* rtm_integrated
* rtm_integrated
* rtm_integrated
* rtm
* Delete build/lib/Pose2Sim directory
* rtm
* Delete build/lib/Pose2Sim directory
* Delete onnxruntime-gpu
* device = cpu
* add pose folder
* Update tests.py
* added annotation
* fix typo
* Should work be still lots of tests to run. Detailed commit coming soon
* intermediary commit
* last checks before v0.9.0
* Update continuous-integration.yml
* Update tests.py
* replaced tabs with spaces
* unittest issue
* unittest typo
* deactivated display for CI test of pose detection
* Try to make continuous integration work
* a
* b
* c
* d
* e
* f
* g
* h
* i
* j
* k
* l
---------
Co-authored-by: HunMinKim <144449115+hunminkim98@users.noreply.github.com>
2024-07-09 22:39:33 +08:00
|
|
|
Estimate pose using RTMLib
|
2023-09-20 20:39:40 +08:00
|
|
|
|
2023-12-17 05:15:12 +08:00
|
|
|
config can be a dictionary,
|
|
|
|
or a the directory path of a trial, participant, or session,
|
|
|
|
or the function can be called without an argument, in which case it the config directory is the current one.
|
2023-07-19 17:37:20 +08:00
|
|
|
'''
|
2023-12-06 16:48:11 +08:00
|
|
|
|
Pose estimation test (#116)
Edits from @hunminkim98's awesome work at integrating pose estimation into Pose2Sim with RTMLib. Most of the changes in syntax are not necessarily better, it is mostly for the code to be more consistent with the rest of the library. Thank you again for your fantastic work!
General:
- Automatically detects whether a valid CUDA install is available. If so, use the GPU with the ONNXRuntime backend. Otherwise, use the CPU with the OpenVINO backend
- The tensorflow version used for marker augmentation was incompatible with the cuda torch installation for pose estimation: edited code and models for it to work with the latest tf version.
- Added logging information to pose estimation
- Readme.md: provided an installation procedure for CUDA (took me a while to find something simple and robust)
- Readme.md: added information about PoseEstimation with RTMLib
- added poseEstimation to tests.py
- created videos for the multi-person case (used to only have json, no video), and reorganized Demo folders. Had to recreate calibration file as well
Json files:
- the json files only saved one person, I made it save all the detected ones
- tracking was not taken into account by rtmlib, which caused issues in synchronization: fixed, waiting for merge
- took the save_to_openpose function out from the main function
- minified the json files (they take less space when all spaces are removed)
Detection results:
- Compared the triangulated locations of RTMpose keypoints to the ones of OpenPose to potentially edit model marker locations on OpenSim. Did not seem to need it.
Others in Config.toml:
- removed the "to_openpose" option, which is not needed
- added the flag: save_video = 'to_images' # 'to_video' or 'to_images' or ['to_video', 'to_images']
- changed the way frame_range was handled (made me change synchronization in depth, as well as personAssociation and triangulation)
- added the flag: time_range_around_maxspeed in synchronization
- automatically detect framerate from video, or set to 60 fps if we work from images (or give a value)
- frame_range -> time_range
- moved height and weight to project (only read for markerAugmentation, and in the future for automatic scaling)
- removed reorder_trc from triangulation and Config -> call it for markerAugmentation instead
Others:
- Provided an installation procedure for OpenSim (for the future) and made continuous installation check its install (a bit harder since it cannot be installed via pip)
- scaling from motion instead of static pose (will have to study whether it's as good or not)
- added logging to synchronization
- Struggled quite a bit with continuous integration
* Starting point of integrating RTMPose into Pose2Sim. (#111)
* RTM_to_Open
Convert format from RTMPose to OpenPose
* rtm_intergrated
* rtm_integrated
* rtm_integrated
* rtm_integrated
* rtm
* Delete build/lib/Pose2Sim directory
* rtm
* Delete build/lib/Pose2Sim directory
* Delete onnxruntime-gpu
* device = cpu
* add pose folder
* Update tests.py
* added annotation
* fix typo
* Should work be still lots of tests to run. Detailed commit coming soon
* intermediary commit
* last checks before v0.9.0
* Update continuous-integration.yml
* Update tests.py
* replaced tabs with spaces
* unittest issue
* unittest typo
* deactivated display for CI test of pose detection
* Try to make continuous integration work
* a
* b
* c
* d
* e
* f
* g
* h
* i
* j
* k
* l
---------
Co-authored-by: HunMinKim <144449115+hunminkim98@users.noreply.github.com>
2024-07-09 22:39:33 +08:00
|
|
|
from Pose2Sim.poseEstimation import rtm_estimator # The name of the function might change
|
|
|
|
|
|
|
|
level, config_dicts = read_config_files(config)
|
|
|
|
|
|
|
|
if isinstance(config, dict):
|
|
|
|
config_dict = config_dicts[0]
|
|
|
|
if config_dict.get('project').get('project_dir') is None:
|
|
|
|
raise ValueError('Please specify the project directory in config_dict:\n \
|
|
|
|
config_dict.get("project").update({"project_dir":"<YOUR_TRIAL_DIRECTORY>"})')
|
|
|
|
|
|
|
|
# Set up logging
|
|
|
|
session_dir = os.path.realpath(os.path.join(config_dicts[0].get('project').get('project_dir'), '..', '..'))
|
|
|
|
setup_logging(session_dir)
|
|
|
|
|
|
|
|
# Batch process all trials
|
|
|
|
for config_dict in config_dicts:
|
|
|
|
start = time.time()
|
|
|
|
currentDateAndTime = datetime.now()
|
|
|
|
project_dir = os.path.realpath(config_dict.get('project').get('project_dir'))
|
|
|
|
seq_name = os.path.basename(project_dir)
|
|
|
|
frame_range = config_dict.get('project').get('frame_range')
|
|
|
|
frames = ["all frames" if not frame_range else f"frames {frame_range[0]} to {frame_range[1]}"][0]
|
|
|
|
|
|
|
|
logging.info("\n\n---------------------------------------------------------------------")
|
|
|
|
logging.info(f"Pose estimation for {seq_name}, for {frames}.")
|
|
|
|
logging.info(f"On {currentDateAndTime.strftime('%A %d. %B %Y, %H:%M:%S')}")
|
|
|
|
logging.info("---------------------------------------------------------------------")
|
|
|
|
logging.info(f"\nProject directory: {project_dir}")
|
2023-12-18 03:08:34 +08:00
|
|
|
|
Pose estimation test (#116)
Edits from @hunminkim98's awesome work at integrating pose estimation into Pose2Sim with RTMLib. Most of the changes in syntax are not necessarily better, it is mostly for the code to be more consistent with the rest of the library. Thank you again for your fantastic work!
General:
- Automatically detects whether a valid CUDA install is available. If so, use the GPU with the ONNXRuntime backend. Otherwise, use the CPU with the OpenVINO backend
- The tensorflow version used for marker augmentation was incompatible with the cuda torch installation for pose estimation: edited code and models for it to work with the latest tf version.
- Added logging information to pose estimation
- Readme.md: provided an installation procedure for CUDA (took me a while to find something simple and robust)
- Readme.md: added information about PoseEstimation with RTMLib
- added poseEstimation to tests.py
- created videos for the multi-person case (used to only have json, no video), and reorganized Demo folders. Had to recreate calibration file as well
Json files:
- the json files only saved one person, I made it save all the detected ones
- tracking was not taken into account by rtmlib, which caused issues in synchronization: fixed, waiting for merge
- took the save_to_openpose function out from the main function
- minified the json files (they take less space when all spaces are removed)
Detection results:
- Compared the triangulated locations of RTMpose keypoints to the ones of OpenPose to potentially edit model marker locations on OpenSim. Did not seem to need it.
Others in Config.toml:
- removed the "to_openpose" option, which is not needed
- added the flag: save_video = 'to_images' # 'to_video' or 'to_images' or ['to_video', 'to_images']
- changed the way frame_range was handled (made me change synchronization in depth, as well as personAssociation and triangulation)
- added the flag: time_range_around_maxspeed in synchronization
- automatically detect framerate from video, or set to 60 fps if we work from images (or give a value)
- frame_range -> time_range
- moved height and weight to project (only read for markerAugmentation, and in the future for automatic scaling)
- removed reorder_trc from triangulation and Config -> call it for markerAugmentation instead
Others:
- Provided an installation procedure for OpenSim (for the future) and made continuous installation check its install (a bit harder since it cannot be installed via pip)
- scaling from motion instead of static pose (will have to study whether it's as good or not)
- added logging to synchronization
- Struggled quite a bit with continuous integration
* Starting point of integrating RTMPose into Pose2Sim. (#111)
* RTM_to_Open
Convert format from RTMPose to OpenPose
* rtm_intergrated
* rtm_integrated
* rtm_integrated
* rtm_integrated
* rtm
* Delete build/lib/Pose2Sim directory
* rtm
* Delete build/lib/Pose2Sim directory
* Delete onnxruntime-gpu
* device = cpu
* add pose folder
* Update tests.py
* added annotation
* fix typo
* Should work be still lots of tests to run. Detailed commit coming soon
* intermediary commit
* last checks before v0.9.0
* Update continuous-integration.yml
* Update tests.py
* replaced tabs with spaces
* unittest issue
* unittest typo
* deactivated display for CI test of pose detection
* Try to make continuous integration work
* a
* b
* c
* d
* e
* f
* g
* h
* i
* j
* k
* l
---------
Co-authored-by: HunMinKim <144449115+hunminkim98@users.noreply.github.com>
2024-07-09 22:39:33 +08:00
|
|
|
rtm_estimator(config_dict)
|
2023-12-18 00:24:09 +08:00
|
|
|
|
Pose estimation test (#116)
Edits from @hunminkim98's awesome work at integrating pose estimation into Pose2Sim with RTMLib. Most of the changes in syntax are not necessarily better, it is mostly for the code to be more consistent with the rest of the library. Thank you again for your fantastic work!
General:
- Automatically detects whether a valid CUDA install is available. If so, use the GPU with the ONNXRuntime backend. Otherwise, use the CPU with the OpenVINO backend
- The tensorflow version used for marker augmentation was incompatible with the cuda torch installation for pose estimation: edited code and models for it to work with the latest tf version.
- Added logging information to pose estimation
- Readme.md: provided an installation procedure for CUDA (took me a while to find something simple and robust)
- Readme.md: added information about PoseEstimation with RTMLib
- added poseEstimation to tests.py
- created videos for the multi-person case (used to only have json, no video), and reorganized Demo folders. Had to recreate calibration file as well
Json files:
- the json files only saved one person, I made it save all the detected ones
- tracking was not taken into account by rtmlib, which caused issues in synchronization: fixed, waiting for merge
- took the save_to_openpose function out from the main function
- minified the json files (they take less space when all spaces are removed)
Detection results:
- Compared the triangulated locations of RTMpose keypoints to the ones of OpenPose to potentially edit model marker locations on OpenSim. Did not seem to need it.
Others in Config.toml:
- removed the "to_openpose" option, which is not needed
- added the flag: save_video = 'to_images' # 'to_video' or 'to_images' or ['to_video', 'to_images']
- changed the way frame_range was handled (made me change synchronization in depth, as well as personAssociation and triangulation)
- added the flag: time_range_around_maxspeed in synchronization
- automatically detect framerate from video, or set to 60 fps if we work from images (or give a value)
- frame_range -> time_range
- moved height and weight to project (only read for markerAugmentation, and in the future for automatic scaling)
- removed reorder_trc from triangulation and Config -> call it for markerAugmentation instead
Others:
- Provided an installation procedure for OpenSim (for the future) and made continuous installation check its install (a bit harder since it cannot be installed via pip)
- scaling from motion instead of static pose (will have to study whether it's as good or not)
- added logging to synchronization
- Struggled quite a bit with continuous integration
* Starting point of integrating RTMPose into Pose2Sim. (#111)
* RTM_to_Open
Convert format from RTMPose to OpenPose
* rtm_intergrated
* rtm_integrated
* rtm_integrated
* rtm_integrated
* rtm
* Delete build/lib/Pose2Sim directory
* rtm
* Delete build/lib/Pose2Sim directory
* Delete onnxruntime-gpu
* device = cpu
* add pose folder
* Update tests.py
* added annotation
* fix typo
* Should work be still lots of tests to run. Detailed commit coming soon
* intermediary commit
* last checks before v0.9.0
* Update continuous-integration.yml
* Update tests.py
* replaced tabs with spaces
* unittest issue
* unittest typo
* deactivated display for CI test of pose detection
* Try to make continuous integration work
* a
* b
* c
* d
* e
* f
* g
* h
* i
* j
* k
* l
---------
Co-authored-by: HunMinKim <144449115+hunminkim98@users.noreply.github.com>
2024-07-09 22:39:33 +08:00
|
|
|
end = time.time()
|
|
|
|
elapsed = end - start
|
|
|
|
logging.info(f'\nPose estimation took {time.strftime("%Hh%Mm%Ss", time.gmtime(elapsed))}.')
|
2023-07-19 17:37:20 +08:00
|
|
|
|
|
|
|
|
2023-12-08 16:39:34 +08:00
|
|
|
def synchronization(config=None):
|
2023-07-19 17:37:20 +08:00
|
|
|
'''
|
2023-09-20 20:39:40 +08:00
|
|
|
Synchronize cameras if needed.
|
|
|
|
|
2023-12-17 05:15:12 +08:00
|
|
|
config can be a dictionary,
|
|
|
|
or a the directory path of a trial, participant, or session,
|
|
|
|
or the function can be called without an argument, in which case it the config directory is the current one.
|
2023-07-19 17:37:20 +08:00
|
|
|
'''
|
2023-09-18 02:48:13 +08:00
|
|
|
|
2024-03-16 03:26:49 +08:00
|
|
|
# Import the function
|
2024-04-14 00:42:30 +08:00
|
|
|
from Pose2Sim.synchronization import synchronize_cams_all
|
2023-12-18 03:08:34 +08:00
|
|
|
|
2024-03-16 03:26:49 +08:00
|
|
|
# Determine the level at which the function is called (session:3, participant:2, trial:1)
|
|
|
|
level, config_dicts = read_config_files(config)
|
2023-12-18 03:08:34 +08:00
|
|
|
|
2024-03-16 03:26:49 +08:00
|
|
|
if type(config)==dict:
|
|
|
|
config_dict = config_dicts[0]
|
|
|
|
if config_dict.get('project').get('project_dir') == None:
|
|
|
|
raise ValueError('Please specify the project directory in config_dict:\n \
|
|
|
|
config_dict.get("project").update({"project_dir":"<YOUR_TRIAL_DIRECTORY>"})')
|
2023-12-18 03:08:34 +08:00
|
|
|
|
2024-03-16 03:26:49 +08:00
|
|
|
# Set up logging
|
|
|
|
session_dir = os.path.realpath(os.path.join(config_dicts[0].get('project').get('project_dir'), '..', '..'))
|
|
|
|
setup_logging(session_dir)
|
|
|
|
|
|
|
|
# Batch process all trials
|
|
|
|
for config_dict in config_dicts:
|
|
|
|
start = time.time()
|
|
|
|
currentDateAndTime = datetime.now()
|
|
|
|
project_dir = os.path.realpath(config_dict.get('project').get('project_dir'))
|
|
|
|
|
|
|
|
logging.info("\n\n---------------------------------------------------------------------")
|
|
|
|
logging.info("Camera synchronization")
|
|
|
|
logging.info(f"On {currentDateAndTime.strftime('%A %d. %B %Y, %H:%M:%S')}")
|
|
|
|
logging.info("---------------------------------------------------------------------")
|
|
|
|
logging.info(f"\nProject directory: {project_dir}")
|
2023-12-18 00:24:09 +08:00
|
|
|
|
2024-03-16 03:26:49 +08:00
|
|
|
synchronize_cams_all(config_dict)
|
2023-09-18 02:48:13 +08:00
|
|
|
|
2024-03-16 03:26:49 +08:00
|
|
|
end = time.time()
|
|
|
|
elapsed = end-start
|
2024-04-15 21:36:47 +08:00
|
|
|
logging.info(f'\nSynchronization took {time.strftime("%Hh%Mm%Ss", time.gmtime(elapsed))}.')
|
2023-09-18 02:48:13 +08:00
|
|
|
|
2023-07-19 17:37:20 +08:00
|
|
|
|
2023-12-08 16:39:34 +08:00
|
|
|
def personAssociation(config=None):
|
2023-07-19 17:37:20 +08:00
|
|
|
'''
|
2023-12-17 05:15:12 +08:00
|
|
|
Tracking one or several persons of interest.
|
2023-07-19 17:37:20 +08:00
|
|
|
Needs a calibration file.
|
2023-09-20 20:39:40 +08:00
|
|
|
|
2023-12-17 05:15:12 +08:00
|
|
|
config can be a dictionary,
|
|
|
|
or a the directory path of a trial, participant, or session,
|
|
|
|
or the function can be called without an argument, in which case it the config directory is the current one.
|
2023-07-19 17:37:20 +08:00
|
|
|
'''
|
|
|
|
|
|
|
|
from Pose2Sim.personAssociation import track_2d_all
|
2023-12-17 21:29:22 +08:00
|
|
|
|
|
|
|
# Determine the level at which the function is called (session:3, participant:2, trial:1)
|
|
|
|
level, config_dicts = read_config_files(config)
|
|
|
|
|
2023-09-20 20:39:40 +08:00
|
|
|
if type(config)==dict:
|
2023-12-17 21:29:22 +08:00
|
|
|
config_dict = config_dicts[0]
|
2023-12-09 19:53:43 +08:00
|
|
|
if config_dict.get('project').get('project_dir') == None:
|
|
|
|
raise ValueError('Please specify the project directory in config_dict:\n \
|
2023-12-17 21:29:22 +08:00
|
|
|
config_dict.get("project").update({"project_dir":"<YOUR_TRIAL_DIRECTORY>"})')
|
2023-12-09 19:53:43 +08:00
|
|
|
|
|
|
|
# Set up logging
|
|
|
|
session_dir = os.path.realpath(os.path.join(config_dicts[0].get('project').get('project_dir'), '..', '..'))
|
|
|
|
setup_logging(session_dir)
|
|
|
|
|
|
|
|
# Batch process all trials
|
2023-12-17 05:15:12 +08:00
|
|
|
for config_dict in config_dicts:
|
2023-12-18 00:24:09 +08:00
|
|
|
start = time.time()
|
2024-03-05 09:59:25 +08:00
|
|
|
currentDateAndTime = datetime.now()
|
2023-12-17 05:15:12 +08:00
|
|
|
project_dir = os.path.realpath(config_dict.get('project').get('project_dir'))
|
|
|
|
seq_name = os.path.basename(project_dir)
|
|
|
|
frame_range = config_dict.get('project').get('frame_range')
|
|
|
|
frames = ["all frames" if frame_range == [] else f"frames {frame_range[0]} to {frame_range[1]}"][0]
|
2023-12-17 05:19:58 +08:00
|
|
|
|
2023-12-17 05:15:12 +08:00
|
|
|
logging.info("\n\n---------------------------------------------------------------------")
|
|
|
|
logging.info(f"Associating persons for {seq_name}, for {frames}.")
|
2024-03-05 09:59:25 +08:00
|
|
|
logging.info(f"On {currentDateAndTime.strftime('%A %d. %B %Y, %H:%M:%S')}")
|
2023-12-17 05:15:12 +08:00
|
|
|
logging.info("---------------------------------------------------------------------")
|
|
|
|
logging.info(f"\nProject directory: {project_dir}")
|
2023-07-19 17:37:20 +08:00
|
|
|
|
2023-12-17 05:15:12 +08:00
|
|
|
track_2d_all(config_dict)
|
2023-07-19 17:37:20 +08:00
|
|
|
|
2023-12-18 00:24:09 +08:00
|
|
|
end = time.time()
|
2024-03-06 07:15:21 +08:00
|
|
|
elapsed = end-start
|
2024-04-15 21:36:47 +08:00
|
|
|
logging.info(f'\nAssociating persons took {time.strftime("%Hh%Mm%Ss", time.gmtime(elapsed))}.')
|
2023-07-19 17:37:20 +08:00
|
|
|
|
|
|
|
|
2023-12-08 16:39:34 +08:00
|
|
|
def triangulation(config=None):
|
2023-07-19 17:37:20 +08:00
|
|
|
'''
|
|
|
|
Robust triangulation of 2D points coordinates.
|
2023-09-20 20:39:40 +08:00
|
|
|
|
2023-12-17 05:15:12 +08:00
|
|
|
config can be a dictionary,
|
|
|
|
or a the directory path of a trial, participant, or session,
|
|
|
|
or the function can be called without an argument, in which case it the config directory is the current one.
|
2023-07-19 17:37:20 +08:00
|
|
|
'''
|
|
|
|
|
|
|
|
from Pose2Sim.triangulation import triangulate_all
|
|
|
|
|
2023-12-17 21:29:22 +08:00
|
|
|
# Determine the level at which the function is called (session:3, participant:2, trial:1)
|
|
|
|
level, config_dicts = read_config_files(config)
|
|
|
|
|
2023-09-20 20:39:40 +08:00
|
|
|
if type(config)==dict:
|
2023-12-17 21:29:22 +08:00
|
|
|
config_dict = config_dicts[0]
|
2023-12-17 05:15:12 +08:00
|
|
|
if config_dict.get('project').get('project_dir') == None:
|
|
|
|
raise ValueError('Please specify the project directory in config_dict:\n \
|
2023-12-17 21:29:22 +08:00
|
|
|
config_dict.get("project").update({"project_dir":"<YOUR_TRIAL_DIRECTORY>"})')
|
2023-07-19 17:37:20 +08:00
|
|
|
|
2023-12-17 05:15:12 +08:00
|
|
|
# Set up logging
|
|
|
|
session_dir = os.path.realpath(os.path.join(config_dicts[0].get('project').get('project_dir'), '..', '..'))
|
2023-12-17 21:29:22 +08:00
|
|
|
setup_logging(session_dir)
|
2023-12-17 05:15:12 +08:00
|
|
|
|
|
|
|
# Batch process all trials
|
|
|
|
for config_dict in config_dicts:
|
2023-12-18 00:24:09 +08:00
|
|
|
start = time.time()
|
2024-03-05 09:59:25 +08:00
|
|
|
currentDateAndTime = datetime.now()
|
2023-12-17 05:15:12 +08:00
|
|
|
project_dir = os.path.realpath(config_dict.get('project').get('project_dir'))
|
|
|
|
seq_name = os.path.basename(project_dir)
|
|
|
|
frame_range = config_dict.get('project').get('frame_range')
|
|
|
|
frames = ["all frames" if frame_range == [] else f"frames {frame_range[0]} to {frame_range[1]}"][0]
|
|
|
|
|
|
|
|
logging.info("\n\n---------------------------------------------------------------------")
|
|
|
|
logging.info(f"Triangulation of 2D points for {seq_name}, for {frames}.")
|
2024-03-05 09:59:25 +08:00
|
|
|
logging.info(f"On {currentDateAndTime.strftime('%A %d. %B %Y, %H:%M:%S')}")
|
2023-12-17 05:15:12 +08:00
|
|
|
logging.info("---------------------------------------------------------------------")
|
|
|
|
logging.info(f"\nProject directory: {project_dir}")
|
2024-01-15 08:39:33 +08:00
|
|
|
|
2024-01-12 10:15:27 +08:00
|
|
|
triangulate_all(config_dict)
|
|
|
|
|
2024-03-06 07:15:21 +08:00
|
|
|
end = time.time()
|
|
|
|
elapsed = end-start
|
2024-04-15 21:36:47 +08:00
|
|
|
logging.info(f'\nTriangulation took {time.strftime("%Hh%Mm%Ss", time.gmtime(elapsed))}.')
|
2024-01-15 08:39:33 +08:00
|
|
|
|
2023-07-19 17:37:20 +08:00
|
|
|
|
2023-12-08 16:39:34 +08:00
|
|
|
def filtering(config=None):
|
2023-07-19 17:37:20 +08:00
|
|
|
'''
|
|
|
|
Filter trc 3D coordinates.
|
2023-09-20 20:39:40 +08:00
|
|
|
|
2023-12-17 05:15:12 +08:00
|
|
|
config can be a dictionary,
|
|
|
|
or a the directory path of a trial, participant, or session,
|
|
|
|
or the function can be called without an argument, in which case it the config directory is the current one.
|
2023-07-19 17:37:20 +08:00
|
|
|
'''
|
|
|
|
|
|
|
|
from Pose2Sim.filtering import filter_all
|
|
|
|
|
2023-12-17 21:29:22 +08:00
|
|
|
# Determine the level at which the function is called (session:3, participant:2, trial:1)
|
|
|
|
level, config_dicts = read_config_files(config)
|
|
|
|
|
2023-09-20 20:39:40 +08:00
|
|
|
if type(config)==dict:
|
2023-12-17 21:29:22 +08:00
|
|
|
config_dict = config_dicts[0]
|
2023-12-17 05:15:12 +08:00
|
|
|
if config_dict.get('project').get('project_dir') == None:
|
|
|
|
raise ValueError('Please specify the project directory in config_dict:\n \
|
2023-12-17 21:29:22 +08:00
|
|
|
config_dict.get("project").update({"project_dir":"<YOUR_TRIAL_DIRECTORY>"})')
|
|
|
|
|
|
|
|
# Set up logging
|
|
|
|
session_dir = os.path.realpath(os.path.join(config_dicts[0].get('project').get('project_dir'), '..', '..'))
|
|
|
|
setup_logging(session_dir)
|
2023-12-17 05:15:12 +08:00
|
|
|
|
|
|
|
# Set up logging
|
|
|
|
session_dir = os.path.realpath(os.path.join(config_dicts[0].get('project').get('project_dir'), '..', '..'))
|
|
|
|
setup_logging(session_dir)
|
|
|
|
|
|
|
|
# Batch process all trials
|
|
|
|
for config_dict in config_dicts:
|
2024-03-05 09:59:25 +08:00
|
|
|
currentDateAndTime = datetime.now()
|
2023-12-17 05:15:12 +08:00
|
|
|
project_dir = os.path.realpath(config_dict.get('project').get('project_dir'))
|
|
|
|
seq_name = os.path.basename(project_dir)
|
|
|
|
frame_range = config_dict.get('project').get('frame_range')
|
|
|
|
frames = ["all frames" if frame_range == [] else f"frames {frame_range[0]} to {frame_range[1]}"][0]
|
2023-07-19 17:37:20 +08:00
|
|
|
|
2023-12-17 05:15:12 +08:00
|
|
|
logging.info("\n\n---------------------------------------------------------------------")
|
|
|
|
logging.info(f"Filtering 3D coordinates for {seq_name}, for {frames}.")
|
2024-03-05 09:59:25 +08:00
|
|
|
logging.info(f"On {currentDateAndTime.strftime('%A %d. %B %Y, %H:%M:%S')}")
|
2023-12-17 05:15:12 +08:00
|
|
|
logging.info("---------------------------------------------------------------------")
|
2024-02-27 01:13:39 +08:00
|
|
|
logging.info(f"\nProject directory: {project_dir}\n")
|
2023-07-19 17:37:20 +08:00
|
|
|
|
2023-12-17 05:19:58 +08:00
|
|
|
filter_all(config_dict)
|
2023-09-20 20:39:40 +08:00
|
|
|
|
2024-01-20 03:03:35 +08:00
|
|
|
|
|
|
|
def markerAugmentation(config=None):
|
|
|
|
'''
|
|
|
|
Augment trc 3D coordinates.
|
|
|
|
Estimate the position of 43 additional markers.
|
|
|
|
|
|
|
|
config can be a dictionary,
|
|
|
|
or a the directory path of a trial, participant, or session,
|
|
|
|
or the function can be called without an argument, in which case it the config directory is the current one.
|
|
|
|
'''
|
|
|
|
|
|
|
|
from Pose2Sim.markerAugmentation import augmentTRC
|
2024-01-12 10:15:27 +08:00
|
|
|
level, config_dicts = read_config_files(config)
|
|
|
|
|
|
|
|
if type(config) == dict:
|
|
|
|
config_dict = config_dicts[0]
|
|
|
|
if config_dict.get('project').get('project_dir') is None:
|
|
|
|
raise ValueError('Please specify the project directory in config_dict:\n \
|
|
|
|
config_dict.get("project").update({"project_dir":"<YOUR_TRIAL_DIRECTORY>"})')
|
|
|
|
|
|
|
|
session_dir = os.path.realpath(os.path.join(config_dicts[0].get('project').get('project_dir'), '..', '..'))
|
|
|
|
setup_logging(session_dir)
|
|
|
|
|
|
|
|
for config_dict in config_dicts:
|
|
|
|
start = time.time()
|
2024-03-05 09:59:25 +08:00
|
|
|
currentDateAndTime = datetime.now()
|
2024-01-12 10:15:27 +08:00
|
|
|
project_dir = os.path.realpath(config_dict.get('project').get('project_dir'))
|
|
|
|
seq_name = os.path.basename(project_dir)
|
|
|
|
frame_range = config_dict.get('project').get('frame_range')
|
|
|
|
frames = ["all frames" if frame_range == [] else f"frames {frame_range[0]} to {frame_range[1]}"][0]
|
|
|
|
|
|
|
|
logging.info("\n\n---------------------------------------------------------------------")
|
|
|
|
logging.info(f"Augmentation process for {seq_name}, for {frames}.")
|
2024-03-05 09:59:25 +08:00
|
|
|
logging.info(f"On {currentDateAndTime.strftime('%A %d. %B %Y, %H:%M:%S')}")
|
2024-01-12 10:15:27 +08:00
|
|
|
logging.info("---------------------------------------------------------------------")
|
2024-02-27 01:13:39 +08:00
|
|
|
logging.info(f"\nProject directory: {project_dir}\n")
|
2024-01-12 10:15:27 +08:00
|
|
|
|
|
|
|
augmentTRC(config_dict)
|
|
|
|
|
|
|
|
end = time.time()
|
2024-03-06 07:15:21 +08:00
|
|
|
elapsed = end-start
|
2024-04-15 21:36:47 +08:00
|
|
|
logging.info(f'\nMarker augmentation took {time.strftime("%Hh%Mm%Ss", time.gmtime(elapsed))}.')
|
2024-01-12 10:15:27 +08:00
|
|
|
|
|
|
|
|
2023-12-18 00:24:09 +08:00
|
|
|
def opensimProcessing(config=None):
|
2023-09-20 20:39:40 +08:00
|
|
|
'''
|
2023-12-18 00:24:09 +08:00
|
|
|
Uses OpenSim to run scaling based on a static trc pose
|
|
|
|
and inverse kinematics based on a trc motion file.
|
2023-09-20 20:39:40 +08:00
|
|
|
|
2023-12-17 05:15:12 +08:00
|
|
|
config can be a dictionary,
|
|
|
|
or a the directory path of a trial, participant, or session,
|
|
|
|
or the function can be called without an argument, in which case it the config directory is the current one.
|
2023-09-20 20:39:40 +08:00
|
|
|
'''
|
|
|
|
|
|
|
|
raise NotImplementedError('This has not been integrated yet. \nPlease read README.md for further explanation')
|
|
|
|
|
2023-12-18 03:08:34 +08:00
|
|
|
# # TODO
|
|
|
|
# from Pose2Sim.opensimProcessing import opensim_processing_all
|
|
|
|
|
|
|
|
# # Determine the level at which the function is called (session:3, participant:2, trial:1)
|
|
|
|
# level, config_dicts = read_config_files(config)
|
|
|
|
|
|
|
|
# if type(config)==dict:
|
|
|
|
# config_dict = config_dicts[0]
|
|
|
|
# if config_dict.get('project').get('project_dir') == None:
|
|
|
|
# raise ValueError('Please specify the project directory in config_dict:\n \
|
|
|
|
# config_dict.get("project").update({"project_dir":"<YOUR_TRIAL_DIRECTORY>"})')
|
|
|
|
|
|
|
|
# # Set up logging
|
|
|
|
# session_dir = os.path.realpath(os.path.join(config_dicts[0].get('project').get('project_dir'), '..', '..'))
|
|
|
|
# setup_logging(session_dir)
|
|
|
|
|
|
|
|
# # Batch process all trials
|
|
|
|
# for config_dict in config_dicts:
|
2024-03-05 09:59:25 +08:00
|
|
|
# currentDateAndTime = datetime.now()
|
2023-12-18 03:08:34 +08:00
|
|
|
# start = time.time()
|
|
|
|
# project_dir = os.path.realpath(config_dict.get('project').get('project_dir'))
|
|
|
|
# seq_name = os.path.basename(project_dir)
|
|
|
|
# frame_range = config_dict.get('project').get('frame_range')
|
|
|
|
# frames = ["all frames" if frame_range == [] else f"frames {frame_range[0]} to {frame_range[1]}"][0]
|
|
|
|
|
|
|
|
# logging.info("\n\n---------------------------------------------------------------------")
|
|
|
|
# # if static_file in project_dir:
|
|
|
|
# # logging.info(f"Scaling model with <STATIC TRC FILE>.")
|
|
|
|
# # else:
|
|
|
|
# # logging.info(f"Running inverse kinematics <MOTION TRC FILE>.")
|
2024-03-05 09:59:25 +08:00
|
|
|
# logging.info(f"On {currentDateAndTime.strftime('%A %d. %B %Y, %H:%M:%S')}")
|
2023-12-18 03:08:34 +08:00
|
|
|
# logging.info("---------------------------------------------------------------------")
|
|
|
|
# logging.info(f"\nOpenSim output directory: {project_dir}")
|
2023-12-18 00:24:09 +08:00
|
|
|
|
2023-12-18 03:08:34 +08:00
|
|
|
# opensim_processing_all(config_dict)
|
2023-09-20 20:39:40 +08:00
|
|
|
|
2023-12-18 03:08:34 +08:00
|
|
|
# end = time.time()
|
2024-03-06 07:15:21 +08:00
|
|
|
# elapsed = end-start
|
|
|
|
# # if static_file in project_dir:
|
|
|
|
# # logging.info(f'Model scaling took {time.strftime("%Hh%Mm%Ss", time.gmtime(elapsed))}.')
|
|
|
|
# # else:
|
|
|
|
# # logging.info(f'Inverse kinematics took {time.strftime("%Hh%Mm%Ss", time.gmtime(elapsed))}.')
|
2024-01-09 19:30:06 +08:00
|
|
|
|