sports2d 0.7.2__py3-none-any.whl → 0.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- Sports2D/Demo/Config_demo.toml +12 -13
- Sports2D/Sports2D.py +27 -23
- Sports2D/Utilities/__init__.py +2 -1
- Sports2D/Utilities/common.py +2 -940
- Sports2D/Utilities/filter.py +2 -1
- Sports2D/Utilities/tests.py +40 -21
- Sports2D/__init__.py +2 -1
- Sports2D/process.py +540 -144
- {sports2d-0.7.2.dist-info → sports2d-0.8.0.dist-info}/METADATA +105 -83
- sports2d-0.8.0.dist-info/RECORD +15 -0
- {sports2d-0.7.2.dist-info → sports2d-0.8.0.dist-info}/WHEEL +1 -1
- sports2d-0.8.0.dist-info/entry_points.txt +3 -0
- Sports2D/Utilities/skeletons.py +0 -1000
- sports2d-0.7.2.dist-info/RECORD +0 -16
- sports2d-0.7.2.dist-info/entry_points.txt +0 -2
- {sports2d-0.7.2.dist-info → sports2d-0.8.0.dist-info/licenses}/LICENSE +0 -0
- {sports2d-0.7.2.dist-info → sports2d-0.8.0.dist-info}/top_level.txt +0 -0
Sports2D/Demo/Config_demo.toml
CHANGED
|
@@ -11,15 +11,18 @@
|
|
|
11
11
|
# Sports2D.process('Config_demo.toml')
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
[
|
|
14
|
+
[base]
|
|
15
15
|
video_input = 'demo.mp4' # 'webcam' or '<video_path.ext>', or ['video1_path.mp4', 'video2_path.avi>', ...]
|
|
16
16
|
# On Windows, replace '\' with '/'
|
|
17
17
|
# Beware that images won't be saved if paths contain non ASCII characters.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
|
|
19
|
+
nb_persons_to_detect = 'all' # int or 'all' # Limiting or not the number of persons to be analyzed
|
|
20
|
+
person_ordering_method = 'highest_likelihood' # 'on_click', 'highest_likelihood', 'greatest_displacement', 'least_displacement', 'first_detected', or 'last_detected'
|
|
21
|
+
first_person_height = 1.65 # Height of the reference person in meters (for pixels -> meters conversion: not used if a calibration file is provided)
|
|
22
|
+
visible_side = ['auto', 'front', 'none'] # Choose visible side among ['right', 'left', 'front', 'back', 'auto', 'none']. String or list of strings.
|
|
21
23
|
# if 'auto', will be either 'left', 'right', or 'front' depending on the direction of the motion
|
|
22
24
|
# if 'none', coordinates will be left in 2D rather than 3D
|
|
25
|
+
|
|
23
26
|
load_trc_px = '' # If you do not want to recalculate pose, load it from a trc file (in px, not in m)
|
|
24
27
|
compare = false # Not implemented yet
|
|
25
28
|
|
|
@@ -32,10 +35,6 @@ video_dir = '' # If empty, video dir is current dir
|
|
|
32
35
|
webcam_id = 0 # your webcam id (0 is default)
|
|
33
36
|
input_size = [1280, 720] # [W, H]. Lower resolution will be faster but less precise.
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
[process]
|
|
37
|
-
multiperson = true # Saving the motions of all the persons detected and tracked in the video.
|
|
38
|
-
# If false, the person saved will be the one with the highest sum of keypoint scores over the video
|
|
39
38
|
show_realtime_results = true
|
|
40
39
|
save_vid = true
|
|
41
40
|
save_img = true
|
|
@@ -89,7 +88,7 @@ det_frequency = 4 # Run person detection only every N frames, and inbetwee
|
|
|
89
88
|
# Equal to or greater than 1, can be as high as you want in simple uncrowded cases. Much faster, but might be less accurate.
|
|
90
89
|
device = 'auto' # 'auto', 'CPU', 'CUDA', 'MPS', 'ROCM'
|
|
91
90
|
backend = 'auto' # 'auto', 'openvino', 'onnxruntime', 'opencv'
|
|
92
|
-
tracking_mode = 'sports2d' # 'sports2d' or 'deepsort'. 'deepsort' is slower but more robust
|
|
91
|
+
tracking_mode = 'sports2d' # 'sports2d' or 'deepsort'. 'deepsort' is slower, harder to parametrize but can be more robust if correctly tuned
|
|
93
92
|
# deepsort_params = """{'max_age':30, 'n_init':3, 'max_cosine_distance':0.3, 'max_iou_distance':0.8, 'embedder_gpu': True, embedder':'torchreid'}""" # """{dictionary between 3 double quotes}"""
|
|
94
93
|
# More robust in crowded scenes but tricky to parametrize. More information there: https://github.com/levan92/deep_sort_realtime/blob/master/deep_sort_realtime/deepsort_tracker.py#L51
|
|
95
94
|
# Requires `pip install torch torchvision torchreid gdown tensorboard`
|
|
@@ -107,7 +106,7 @@ to_meters = true
|
|
|
107
106
|
make_c3d = true
|
|
108
107
|
save_calib = true # Coming soon!
|
|
109
108
|
|
|
110
|
-
# If conversion from
|
|
109
|
+
# If conversion from first_person_height
|
|
111
110
|
floor_angle = 'auto' # 'auto' or a value in degrees, eg 2.3. If 'auto', estimated from the line formed by the toes when they are on the ground (where speed = 0)
|
|
112
111
|
xy_origin = ['auto'] # ['auto'] or [px_x,px_y]. N.B.: px_y points downwards. If ['auto'], direction estimated from the start to the end of the line formed by the toes when they are on the ground
|
|
113
112
|
|
|
@@ -151,10 +150,10 @@ filter_type = 'butterworth' # butterworth, gaussian, LOESS, median
|
|
|
151
150
|
|
|
152
151
|
|
|
153
152
|
[kinematics]
|
|
154
|
-
do_ik =
|
|
155
|
-
use_augmentation =
|
|
153
|
+
do_ik = false # Do scaling and inverse kinematics?
|
|
154
|
+
use_augmentation = false # true or false (lowercase) # Set to true if you want to use the model with augmented markers
|
|
156
155
|
use_contacts_muscles = true # true or false (lowercase) # If true, contact spheres and muscles are added to the model
|
|
157
|
-
participant_mass = [
|
|
156
|
+
participant_mass = [55.0, 67.0] # kg # defaults to 70 if not provided. No influence on kinematics (motion), only on kinetics (forces)
|
|
158
157
|
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)
|
|
159
158
|
|
|
160
159
|
# Choosing best frames to scale the model
|
Sports2D/Sports2D.py
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
sports2d --video_input webcam
|
|
30
30
|
- Run with custom parameters (all non specified are set to default):
|
|
31
31
|
sports2d --show_plots False --time_range 0 2.1 --result_dir path_to_result_dir
|
|
32
|
-
sports2d --
|
|
32
|
+
sports2d --person_detection_method highest_likelihood --mode lightweight --det_frequency 50
|
|
33
33
|
- Run with a toml configuration file:
|
|
34
34
|
sports2d --config path_to_config.toml
|
|
35
35
|
|
|
@@ -109,6 +109,7 @@
|
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
## INIT
|
|
112
|
+
from importlib.metadata import version
|
|
112
113
|
import argparse
|
|
113
114
|
import toml
|
|
114
115
|
from datetime import datetime
|
|
@@ -121,18 +122,17 @@ from Sports2D import Sports2D
|
|
|
121
122
|
|
|
122
123
|
|
|
123
124
|
## CONSTANTS
|
|
124
|
-
DEFAULT_CONFIG = {'
|
|
125
|
-
'
|
|
126
|
-
'
|
|
127
|
-
'
|
|
125
|
+
DEFAULT_CONFIG = {'base': {'video_input': ['demo.mp4'],
|
|
126
|
+
'nb_persons_to_detect': 'all',
|
|
127
|
+
'person_ordering_method': 'highest_likelihood',
|
|
128
|
+
'first_person_height': 1.65,
|
|
129
|
+
'visible_side': ['auto', 'front', 'none'],
|
|
128
130
|
'load_trc_px': '',
|
|
129
131
|
'compare': False,
|
|
130
132
|
'time_range': [],
|
|
131
133
|
'video_dir': '',
|
|
132
134
|
'webcam_id': 0,
|
|
133
|
-
'input_size': [1280, 720]
|
|
134
|
-
},
|
|
135
|
-
'process': {'multiperson': True,
|
|
135
|
+
'input_size': [1280, 720],
|
|
136
136
|
'show_realtime_results': True,
|
|
137
137
|
'save_vid': True,
|
|
138
138
|
'save_img': True,
|
|
@@ -148,7 +148,7 @@ DEFAULT_CONFIG = {'project': {'video_input': ['demo.mp4'],
|
|
|
148
148
|
'device': 'auto',
|
|
149
149
|
'backend': 'auto',
|
|
150
150
|
'tracking_mode': 'sports2d',
|
|
151
|
-
'deepsort_params': """{'max_age':30, 'n_init':3, 'nms_max_overlap':0.8, 'max_cosine_distance':0.3, 'nn_budget':200, 'max_iou_distance':0.8, 'embedder_gpu': True}""",
|
|
151
|
+
'deepsort_params': """{'max_age':30, 'n_init':3, 'nms_max_overlap':0.8, 'max_cosine_distance':0.3, 'nn_budget':200, 'max_iou_distance':0.8, 'embedder_gpu': True, 'embedder':'torchreid'}""",
|
|
152
152
|
'keypoint_likelihood_threshold': 0.3,
|
|
153
153
|
'average_likelihood_threshold': 0.5,
|
|
154
154
|
'keypoint_number_threshold': 0.3
|
|
@@ -206,7 +206,7 @@ DEFAULT_CONFIG = {'project': {'video_input': ['demo.mp4'],
|
|
|
206
206
|
'kinematics':{'do_ik': False,
|
|
207
207
|
'use_augmentation': False,
|
|
208
208
|
'use_contacts_muscles': True,
|
|
209
|
-
'participant_mass': [
|
|
209
|
+
'participant_mass': [55.0, 67.0],
|
|
210
210
|
'right_left_symmetry': True,
|
|
211
211
|
'default_height': 1.70,
|
|
212
212
|
'remove_individual_scaling_setup': True,
|
|
@@ -223,8 +223,10 @@ DEFAULT_CONFIG = {'project': {'video_input': ['demo.mp4'],
|
|
|
223
223
|
|
|
224
224
|
CONFIG_HELP = {'config': ["C", "path to a toml configuration file"],
|
|
225
225
|
'video_input': ["i", "webcam, or video_path.mp4, or video1_path.avi video2_path.mp4 ... Beware that images won't be saved if paths contain non ASCII characters"],
|
|
226
|
-
'
|
|
227
|
-
'
|
|
226
|
+
'nb_persons_to_detect': ["n", "number of persons to detect. int or 'all'. 'all' if not specified"],
|
|
227
|
+
'person_ordering_method': ["", "'on_click', 'highest_likelihood', 'greatest_displacement', 'least_displacement', 'first_detected', or 'last_detected'. 'on_click' if not specified"],
|
|
228
|
+
'first_person_height': ["H", "height of the reference person in meters. 1.65 if not specified. Not used if a calibration file is provided"],
|
|
229
|
+
'visible_side': ["", "front, back, left, right, auto, or none. 'auto front none' if not specified. If 'auto', will be either left or right depending on the direction of the motion. If 'none', no IK for this person"],
|
|
228
230
|
'load_trc_px': ["", "load trc file to avaid running pose estimation again. false if not specified"],
|
|
229
231
|
'compare': ["", "visually compare motion with trc file. false if not specified"],
|
|
230
232
|
'webcam_id': ["w", "webcam ID. 0 if not specified"],
|
|
@@ -250,7 +252,6 @@ CONFIG_HELP = {'config': ["C", "path to a toml configuration file"],
|
|
|
250
252
|
'device': ["", "Device for pose estimatino can be 'auto', 'openvino', 'onnxruntime', 'opencv'"],
|
|
251
253
|
'to_meters': ["M", "convert pixels to meters. true if not specified"],
|
|
252
254
|
'make_c3d': ["", "Convert trc to c3d file. true if not specified"],
|
|
253
|
-
'px_to_m_from_person_id': ["", "person ID to calibrate on. 0 if not specified"],
|
|
254
255
|
'floor_angle': ["", "angle of the floor. 'auto' if not specified"],
|
|
255
256
|
'xy_origin': ["", "origin of the xy plane. 'auto' if not specified"],
|
|
256
257
|
'calib_file': ["", "path to calibration file. '' if not specified, eg no calibration file"],
|
|
@@ -260,8 +261,7 @@ CONFIG_HELP = {'config': ["C", "path to a toml configuration file"],
|
|
|
260
261
|
'use_contacts_muscles': ["", "Use model with contact spheres and muscles. false if not specified"],
|
|
261
262
|
'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)"],
|
|
262
263
|
'close_to_zero_speed_m': ["","Sum for all keypoints: about 50 px/frame or 0.2 m/frame"],
|
|
263
|
-
'
|
|
264
|
-
'tracking_mode': ["", "sports2d or rtmlib. sports2d is generally much more accurate and comparable in speed. sports2d if not specified"],
|
|
264
|
+
'tracking_mode': ["", "'sports2d' or 'deepsort'. 'deepsort' is slower, harder to parametrize but can be more robust if correctly tuned"],
|
|
265
265
|
'deepsort_params': ["", 'Deepsort tracking parameters: """{dictionary between 3 double quotes}""". \n\
|
|
266
266
|
Default: max_age:30, n_init:3, nms_max_overlap:0.8, max_cosine_distance:0.3, nn_budget:200, max_iou_distance:0.8, embedder_gpu: True\n\
|
|
267
267
|
More information there: https://github.com/levan92/deep_sort_realtime/blob/master/deep_sort_realtime/deepsort_tracker.py#L51'],
|
|
@@ -269,6 +269,10 @@ CONFIG_HELP = {'config': ["C", "path to a toml configuration file"],
|
|
|
269
269
|
'keypoint_likelihood_threshold': ["", "detected keypoints are not retained if likelihood is below this threshold. 0.3 if not specified"],
|
|
270
270
|
'average_likelihood_threshold': ["", "detected persons are not retained if average keypoint likelihood is below this threshold. 0.5 if not specified"],
|
|
271
271
|
'keypoint_number_threshold': ["", "detected persons are not retained if number of detected keypoints is below this threshold. 0.3 if not specified, i.e., i.e., 30 percent"],
|
|
272
|
+
'fastest_frames_to_remove_percent': ["", "Frames with high speed are considered as outliers. Defaults to 0.1"],
|
|
273
|
+
'close_to_zero_speed_px': ["", "Sum for all keypoints: about 50 px/frame or 0.2 m/frame. Defaults to 50"],
|
|
274
|
+
'large_hip_knee_angles': ["", "Hip and knee angles below this value are considered as imprecise. Defaults to 45"],
|
|
275
|
+
'trimmed_extrema_percent': ["", "Proportion of the most extreme segment values to remove before calculating their mean. Defaults to 50"],
|
|
272
276
|
'fontSize': ["", "font size for angle values. 0.3 if not specified"],
|
|
273
277
|
'flip_left_right': ["", "true or false. true to get consistent angles with people facing both left and right sides. Set it to false if you want timeseries to be continuous even when the participent switches their stance. true if not specified"],
|
|
274
278
|
'correct_segment_angles_with_floor_angle': ["", "true or false. If the camera is tilted, corrects segment angles as regards to the floor angle. Set to false is the floor is tilted instead. True if not specified"],
|
|
@@ -301,7 +305,7 @@ __author__ = "David Pagnon"
|
|
|
301
305
|
__copyright__ = "Copyright 2023, Sports2D"
|
|
302
306
|
__credits__ = ["David Pagnon"]
|
|
303
307
|
__license__ = "BSD 3-Clause License"
|
|
304
|
-
__version__ = "
|
|
308
|
+
__version__ = version("sports2d")
|
|
305
309
|
__maintainer__ = "David Pagnon"
|
|
306
310
|
__email__ = "contact@david-pagnon.com"
|
|
307
311
|
__status__ = "Development"
|
|
@@ -323,16 +327,16 @@ def base_params(config_dict):
|
|
|
323
327
|
'''
|
|
324
328
|
|
|
325
329
|
# video_dir and result_dir
|
|
326
|
-
video_dir = config_dict.get('
|
|
330
|
+
video_dir = config_dict.get('base').get('video_dir')
|
|
327
331
|
if video_dir == '': video_dir = Path.cwd()
|
|
328
332
|
else: video_dir = Path(video_dir).resolve()
|
|
329
333
|
|
|
330
|
-
result_dir = config_dict.get('
|
|
334
|
+
result_dir = config_dict.get('base').get('result_dir')
|
|
331
335
|
if result_dir == '': result_dir = Path.cwd()
|
|
332
336
|
else: result_dir = Path(result_dir).resolve()
|
|
333
337
|
|
|
334
338
|
# video_files, frame_rates, time_ranges
|
|
335
|
-
video_input = config_dict.get('
|
|
339
|
+
video_input = config_dict.get('base').get('video_input')
|
|
336
340
|
if video_input == "webcam" or video_input == ["webcam"]:
|
|
337
341
|
video_files = ['webcam'] # No video files for webcam
|
|
338
342
|
frame_rates = [None] # No frame rate for webcam
|
|
@@ -358,7 +362,7 @@ def base_params(config_dict):
|
|
|
358
362
|
video.release()
|
|
359
363
|
|
|
360
364
|
# time_ranges
|
|
361
|
-
time_ranges = np.array(config_dict.get('
|
|
365
|
+
time_ranges = np.array(config_dict.get('base').get('time_range'))
|
|
362
366
|
# No time range provided
|
|
363
367
|
if time_ranges.shape == (0,):
|
|
364
368
|
time_ranges = [None] * len(video_files)
|
|
@@ -393,7 +397,7 @@ def get_leaf_keys(config, prefix=''):
|
|
|
393
397
|
|
|
394
398
|
def update_nested_dict(config, key_path, value):
|
|
395
399
|
'''
|
|
396
|
-
Update a nested dictionary based on a key path string like '
|
|
400
|
+
Update a nested dictionary based on a key path string like 'base.nb_persons_to_detect'.
|
|
397
401
|
'''
|
|
398
402
|
|
|
399
403
|
keys = key_path.split('.')
|
|
@@ -491,7 +495,7 @@ def main():
|
|
|
491
495
|
sports2d --video_input webcam
|
|
492
496
|
- Run with custom parameters (all non specified are set to default):
|
|
493
497
|
sports2d --show_plots False --time_range 0 2.1 --result_dir path_to_result_dir
|
|
494
|
-
sports2d --
|
|
498
|
+
sports2d --mode lightweight --det_frequency 50
|
|
495
499
|
- Run with a toml configuration file:
|
|
496
500
|
sports2d --config path_to_config.toml
|
|
497
501
|
'''
|
|
@@ -526,7 +530,7 @@ def main():
|
|
|
526
530
|
else:
|
|
527
531
|
new_config = DEFAULT_CONFIG.copy()
|
|
528
532
|
if not args.video_input:
|
|
529
|
-
new_config.get('
|
|
533
|
+
new_config.get('base').update({'video_dir': Path(__file__).resolve().parent / 'Demo'})
|
|
530
534
|
|
|
531
535
|
# Override dictionary with command-line arguments if provided
|
|
532
536
|
leaf_keys = get_leaf_keys(new_config)
|