Skip to content

Commit 30873d4

Browse files
committed
added feet_on_floor parameter and fixed whole_body pose estimation with inverse kinematics
1 parent 2b052fa commit 30873d4

File tree

4 files changed

+36
-11
lines changed

4 files changed

+36
-11
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ sports2d --help
430430
'calculate_angles': ["c", "calculate joint and segment angles. true if not specified"],
431431
'save_angles': ["A", "save angles as mot files. true if not specified"],
432432
'slowmo_factor': ["", "slow-motion factor. For a video recorded at 240 fps and exported to 30 fps, it would be 240/30 = 8. 1 if not specified"],
433-
'pose_model': ["p", "only body_with_feet is available for now. body_with_feet if not specified"],
433+
'pose_model': ["p", "body_with_feet, whole_body_wrist, whole_body, or body. body_with_feet if not specified"],
434434
'mode': ["m", 'light, balanced, performance, or a """{dictionary within triple quote}""". balanced if not specified. Use a dictionary to specify your own detection and/or pose estimation models (more about in the documentation).'],
435435
'det_frequency': ["f", "run person detection only every N frames, and inbetween track previously detected bounding boxes. keypoint detection is still run on all frames.\n\
436436
Equal to or greater than 1, can be as high as you want in simple uncrowded cases. Much faster, but might be less accurate. 1 if not specified: detection runs on all frames"],
@@ -444,6 +444,7 @@ sports2d --help
444444
'save_calib': ["", "save calibration file. true if not specified"],
445445
'do_ik': ["", "do inverse kinematics. false if not specified"],
446446
'use_augmentation': ["", "Use LSTM marker augmentation. false if not specified"],
447+
'feet_on_floor': ["", "offset marker augmentation results so that feet are at floor level. true if not specified"],
447448
'use_contacts_muscles': ["", "Use model with contact spheres and muscles. false if not specified"],
448449
'participant_mass': ["", "mass of the participant in kg or none. Defaults to 70 if not provided. No influence on kinematics (motion), only on kinetics (forces)"],
449450
'close_to_zero_speed_m': ["","Sum for all keypoints: about 50 px/frame or 0.2 m/frame"],

Sports2D/Demo/Config_demo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ filter_type = 'butterworth' # butterworth, gaussian, LOESS, median
151151
[kinematics]
152152
do_ik = false # Do scaling and inverse kinematics?
153153
use_augmentation = false # true or false (lowercase) # Set to true if you want to use the model with augmented markers
154+
feet_on_floor = false # true or false (lowercase) # Set to false if you want to use the model with feet not on the floor (e.g. running, jumping, etc.)
154155
use_contacts_muscles = true # true or false (lowercase) # If true, contact spheres and muscles are added to the model
155156
participant_mass = [55.0, 67.0] # kg # defaults to 70 if not provided. No influence on kinematics (motion), only on kinetics (forces)
156157
right_left_symmetry = true # true or false (lowercase) # Set to false only if you have good reasons to think the participant is not symmetrical (e.g. prosthetic limb)

Sports2D/Sports2D.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@
205205
},
206206
'kinematics':{'do_ik': False,
207207
'use_augmentation': False,
208+
'feet_on_floor': False,
208209
'use_contacts_muscles': True,
209210
'participant_mass': [55.0, 67.0],
210211
'right_left_symmetry': True,
@@ -244,7 +245,7 @@
244245
'calculate_angles': ["c", "calculate joint and segment angles. true if not specified"],
245246
'save_angles': ["A", "save angles as mot files. true if not specified"],
246247
'slowmo_factor': ["", "slow-motion factor. For a video recorded at 240 fps and exported to 30 fps, it would be 240/30 = 8. 1 if not specified"],
247-
'pose_model': ["p", "only body_with_feet is available for now. body_with_feet if not specified"],
248+
'pose_model': ["p", "body_with_feet, whole_body_wrist, whole_body, or body. body_with_feet if not specified"],
248249
'mode': ["m", 'light, balanced, performance, or a """{dictionary within triple quote}""". balanced if not specified. Use a dictionary to specify your own detection and/or pose estimation models (more about in the documentation).'],
249250
'det_frequency': ["f", "run person detection only every N frames, and inbetween track previously detected bounding boxes. keypoint detection is still run on all frames.\n\
250251
Equal to or greater than 1, can be as high as you want in simple uncrowded cases. Much faster, but might be less accurate. 1 if not specified: detection runs on all frames"],
@@ -258,6 +259,7 @@
258259
'save_calib': ["", "save calibration file. true if not specified"],
259260
'do_ik': ["", "do inverse kinematics. false if not specified"],
260261
'use_augmentation': ["", "Use LSTM marker augmentation. false if not specified"],
262+
'feet_on_floor': ["", "offset marker augmentation results so that feet are at floor level. true if not specified"],
261263
'use_contacts_muscles': ["", "Use model with contact spheres and muscles. false if not specified"],
262264
'participant_mass': ["", "mass of the participant in kg or none. Defaults to 70 if not provided. No influence on kinematics (motion), only on kinetics (forces)"],
263265
'close_to_zero_speed_m': ["","Sum for all keypoints: about 50 px/frame or 0.2 m/frame"],

Sports2D/process.py

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
from tqdm import tqdm
6767
from collections import defaultdict
6868
from anytree import RenderTree
69+
from anytree.importer import DictImporter
6970

7071
import numpy as np
7172
import pandas as pd
@@ -1380,6 +1381,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
13801381
use_augmentation = config_dict.get('kinematics').get('use_augmentation')
13811382
participant_masses = config_dict.get('kinematics').get('participant_mass')
13821383
participant_masses = participant_masses if isinstance(participant_masses, list) else [participant_masses]
1384+
feet_on_floor = config_dict.get('kinematics').get('feet_on_floor')
13831385
fastest_frames_to_remove_percent = config_dict.get('kinematics').get('fastest_frames_to_remove_percent')
13841386
large_hip_knee_angles = config_dict.get('kinematics').get('large_hip_knee_angles')
13851387
trimmed_extrema_percent = config_dict.get('kinematics').get('trimmed_extrema_percent')
@@ -1426,26 +1428,45 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
14261428
cv2.setWindowProperty(f'{video_file} Sports2D', cv2.WND_PROP_ASPECT_RATIO, cv2.WINDOW_FULLSCREEN)
14271429

14281430
# Select the appropriate model based on the model_type
1431+
logging.info('\nEstimating pose...')
14291432
if pose_model.upper() in ('HALPE_26', 'BODY_WITH_FEET'):
14301433
model_name = 'HALPE_26'
14311434
ModelClass = BodyWithFeet # 26 keypoints(halpe26)
14321435
logging.info(f"Using HALPE_26 model (body and feet) for pose estimation.")
1433-
elif pose_model.upper() == 'WHOLE_BODY_WRIST':
1434-
model_name = 'COCO_133_WRIST'
1435-
ModelClass = Wholebody
1436-
logging.info(f"Using COCO_133 model (body, feet, 2 hand points) for pose estimation.")
1437-
elif pose_model.upper() in ('COCO_133', 'WHOLE_BODY'):
1436+
elif pose_model.upper() in ('COCO_133', 'WHOLE_BODY', 'WHOLE_BODY_WRIST'):
14381437
model_name = 'COCO_133'
14391438
ModelClass = Wholebody
14401439
logging.info(f"Using COCO_133 model (body, feet, hands, and face) for pose estimation.")
14411440
elif pose_model.upper() in ('COCO_17', 'BODY'):
14421441
model_name = 'COCO_17'
14431442
ModelClass = Body
14441443
logging.info(f"Using COCO_17 model (body) for pose estimation.")
1444+
elif pose_model.upper() =='HAND':
1445+
model_name = 'HAND_21'
1446+
ModelClass = Hand
1447+
logging.info(f"Using HAND_21 model for pose estimation.")
1448+
elif pose_model.upper() =='FACE':
1449+
model_name = 'FACE_106'
1450+
logging.info(f"Using FACE_106 model for pose estimation.")
1451+
elif pose_model.upper() =='ANIMAL':
1452+
model_name = 'ANIMAL2D_17'
1453+
logging.info(f"Using ANIMAL2D_17 model for pose estimation.")
14451454
else:
1446-
raise ValueError(f"Invalid model_type: {model_name}. Must be 'HALPE_26', 'COCO_133', or 'COCO_17'. Use another network (MMPose, DeepLabCut, OpenPose, AlphaPose, BlazePose...) and convert the output files if you need another model. See documentation.")
1455+
model_name = pose_model.upper()
1456+
logging.info(f"Using model {model_name} for pose estimation.")
14471457
pose_model_name = pose_model
1448-
pose_model = eval(model_name)
1458+
try:
1459+
pose_model = eval(model_name)
1460+
except:
1461+
try: # from Config.toml
1462+
pose_model = DictImporter().import_(config_dict.get('pose').get(pose_model))
1463+
if pose_model.id == 'None':
1464+
pose_model.id = None
1465+
except:
1466+
raise NameError(f'{pose_model} not found in skeletons.py nor in Config.toml')
1467+
1468+
# Select device and backend
1469+
backend, device = setup_backend_device(backend=backend, device=device)
14491470

14501471
# Manually select the models if mode is a dictionary rather than 'lightweight', 'balanced', or 'performance'
14511472
if not mode in ['lightweight', 'balanced', 'performance']:
@@ -2127,7 +2148,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
21272148

21282149
# Delete person if less than 4 valid frames
21292150
pose_path_person = pose_output_path.parent / (pose_output_path.stem + f'_person{i:02d}.trc')
2130-
all_frames_X_person = pd.DataFrame(all_frames_X_homog[:,i,:], columns=keypoints_names)
2151+
all_frames_X_person = pd.DataFrame(all_frames_X_homog[:,i,:], columns=new_keypoints_names)
21312152
pose_nan_count = len(np.where(all_frames_X_person.sum(axis=1)==0)[0])
21322153
if frame_count - frame_range[0] - pose_nan_count <= 4:
21332154
# heights_m.append(DEFAULT_HEIGHT)
@@ -2151,7 +2172,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
21512172
Pose2Sim_config_dict['project']['participant_height'] = heights_m
21522173
Pose2Sim_config_dict['project']['participant_mass'] = masses
21532174
Pose2Sim_config_dict['project']['frame_range'] = 'all'
2154-
Pose2Sim_config_dict['markerAugmentation']['feet_on_floor'] = False
2175+
Pose2Sim_config_dict['markerAugmentation']['feet_on_floor'] = feet_on_floor
21552176
Pose2Sim_config_dict['pose']['pose_model'] = pose_model_name.upper()
21562177
Pose2Sim_config_dict = to_dict(Pose2Sim_config_dict)
21572178

0 commit comments

Comments
 (0)