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.
@@ -11,15 +11,18 @@
11
11
  # Sports2D.process('Config_demo.toml')
12
12
 
13
13
 
14
- [project]
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
- px_to_m_from_person_id = 2 # Person to use for pixels to meters conversion (not used if a calibration file is provided)
19
- px_to_m_person_height = 1.65 # Height of the reference person in meters (for pixels -> meters conversion).
20
- visible_side = ['front', 'none', 'auto'] # Choose visible side among ['right', 'left', 'front', 'back', 'auto', 'none']. String or list of strings.
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 in difficult configurations
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 px_to_m_person_height
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 = true # Do scaling and inverse kinematics?
155
- use_augmentation = true # true or false (lowercase) # Set to true if you want to use the model with augmented markers
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 = [67.0, 55.0] # kg # defaults to 70 if not provided. No influence on kinematics (motion), only on kinetics (forces)
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 --multiperson false --mode lightweight --det_frequency 50
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 = {'project': {'video_input': ['demo.mp4'],
125
- 'px_to_m_from_person_id': 2,
126
- 'px_to_m_person_height': 1.65,
127
- 'visible_side': ['front', 'none', 'auto'],
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': [67.0, 55.0],
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
- 'px_to_m_person_height': ["H", "height of the person in meters. 1.70 if not specified"],
227
- 'visible_side': ["", "front, back, left, right, auto, or none. 'front none auto' 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"],
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
- 'multiperson': ["", "multiperson involves tracking: will be faster if set to false. true if not specified"],
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__ = "0.4.0"
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('project').get('video_dir')
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('process').get('result_dir')
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('project').get('video_input')
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('project').get('time_range'))
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 'process.multiperson'.
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 --multiperson false --mode lightweight --det_frequency 50
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('project').update({'video_dir': Path(__file__).resolve().parent / 'Demo'})
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)
@@ -2,6 +2,7 @@
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  import sys
5
+ from importlib.metadata import version
5
6
 
6
- __version__ = "0.4.0"
7
+ __version__ = version("sports2d")
7
8
  VERSION = __version__