sports2d 0.8.3__py3-none-any.whl → 0.8.4__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.
@@ -17,7 +17,7 @@ video_input = 'demo.mp4' # 'webcam' or '<video_path.ext>', or ['video1_path.mp
17
17
  # Beware that images won't be saved if paths contain non ASCII characters.
18
18
 
19
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'
20
+ person_ordering_method = 'on_click' # 'on_click', 'highest_likelihood', 'largest_size', 'smallest_size', 'greatest_displacement', 'least_displacement', 'first_detected', or 'last_detected'
21
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
22
  visible_side = ['auto', 'front', 'none'] # Choose visible side among ['right', 'left', 'front', 'back', 'auto', 'none']. String or list of strings.
23
23
  # if 'auto', will be either 'left', 'right', or 'front' depending on the direction of the motion
Sports2D/Sports2D.py CHANGED
@@ -124,7 +124,7 @@ from Sports2D import Sports2D
124
124
  ## CONSTANTS
125
125
  DEFAULT_CONFIG = {'base': {'video_input': ['demo.mp4'],
126
126
  'nb_persons_to_detect': 'all',
127
- 'person_ordering_method': 'highest_likelihood',
127
+ 'person_ordering_method': 'on_click',
128
128
  'first_person_height': 1.65,
129
129
  'visible_side': ['auto', 'front', 'none'],
130
130
  'load_trc_px': '',
@@ -224,7 +224,7 @@ DEFAULT_CONFIG = {'base': {'video_input': ['demo.mp4'],
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
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"],
227
+ 'person_ordering_method': ["", "'on_click', 'highest_likelihood', 'largest_size', 'smallest_size', 'greatest_displacement', 'least_displacement', 'first_detected', or 'last_detected'. 'on_click' if not specified"],
228
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
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"],
230
230
  'load_trc_px': ["", "load trc file to avaid running pose estimation again. false if not specified"],
@@ -274,7 +274,7 @@ CONFIG_HELP = {'config': ["C", "path to a toml configuration file"],
274
274
  'large_hip_knee_angles': ["", "Hip and knee angles below this value are considered as imprecise. Defaults to 45"],
275
275
  'trimmed_extrema_percent': ["", "Proportion of the most extreme segment values to remove before calculating their mean. Defaults to 50"],
276
276
  'fontSize': ["", "font size for angle values. 0.3 if not specified"],
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"],
277
+ 'flip_left_right': ["", "true or false. Flips angles when the person faces the other side. The person looks to the right if their toe keypoint is to the right of their heel. Set it to false if the person is sprinting or if you want timeseries to be continuous even when the participent switches their stance. true if not specified"],
278
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"],
279
279
  'interpolate': ["", "interpolate missing data. true if not specified"],
280
280
  'interp_gap_smaller_than': ["", "interpolate sequences of missing data if they are less than N frames long. 10 if not specified"],
Sports2D/process.py CHANGED
@@ -785,7 +785,7 @@ def angle_plots(angle_data_unfiltered, angle_data, person_id):
785
785
 
786
786
  def get_personIDs_with_highest_scores(all_frames_scores, nb_persons_to_detect):
787
787
  '''
788
- Get the person ID with the highest scores
788
+ Get the person IDs with the highest scores
789
789
 
790
790
  INPUTS:
791
791
  - all_frames_scores: array of scores for all frames, all persons, all keypoints
@@ -821,15 +821,46 @@ def get_personIDs_in_detection_order(nb_persons_to_detect, reverse=False):
821
821
  return selected_persons
822
822
 
823
823
 
824
+ def get_personIDs_with_largest_size(all_frames_X_homog, all_frames_Y_homog, nb_persons_to_detect, reverse=False, vertical=False):
825
+ '''
826
+ Get the person IDs with the largest size
827
+
828
+ INPUTS:
829
+ - all_frames_X_homog: shape (Nframes, Npersons, Nkpts)
830
+ - all_frames_Y_homog: shape (Nframes, Npersons, Nkpts)
831
+ - nb_persons_to_detect: int. The number of persons to detect
832
+ - reverse: bool. Whether to reverse the order of detection from smallest to largest size
833
+ - vertical: bool. Whether to compute the size in the vertical direction only
834
+
835
+ OUTPUT:
836
+ - selected_persons: list of int. The person IDs with the largest size
837
+ '''
838
+
839
+ # average size over all keypoints (axis=2) and all frames (axis=0) for each person (axis=1)
840
+ y_sizes = np.array([np.nanmean(np.nanmax(all_frames_Y_homog, axis=2) - np.nanmin(all_frames_Y_homog, axis=2), axis=0)][0])
841
+ if vertical:
842
+ sizes = y_sizes
843
+ else:
844
+ x_sizes = np.array([np.nanmean(np.nanmax(all_frames_X_homog, axis=2) - np.nanmin(all_frames_X_homog, axis=2), axis=0)][0])
845
+ sizes = np.sqrt(x_sizes**2 + y_sizes**2)
846
+
847
+ if not reverse: # greatest to smallest size
848
+ sizes = -sizes
849
+
850
+ selected_persons = sizes.argsort()[:nb_persons_to_detect]
851
+
852
+ return selected_persons
853
+
854
+
824
855
  def get_personIDs_with_greatest_displacement(all_frames_X_homog, all_frames_Y_homog, nb_persons_to_detect, reverse=False, horizontal=True):
825
856
  '''
826
- Get the person ID with the greatest displacement
857
+ Get the person IDs with the greatest displacement
827
858
 
828
859
  INPUTS:
829
860
  - all_frames_X_homog: shape (Nframes, Npersons, Nkpts)
830
861
  - all_frames_Y_homog: shape (Nframes, Npersons, Nkpts)
831
862
  - nb_persons_to_detect: int. The number of persons to detect
832
- - reverse: bool. Whether to reverse the order of detection
863
+ - reverse: bool. Whether to reverse the order of detection from smallest to greatest displacement
833
864
  - horizontal: bool. Whether to compute the displacement in the horizontal direction
834
865
 
835
866
  OUTPUT:
@@ -848,9 +879,10 @@ def get_personIDs_with_greatest_displacement(all_frames_X_homog, all_frames_Y_ho
848
879
  max_dist_traveled = np.nansum([euclidean_distance(m,p) for (m,p) in zip(pos_XY[:,1:,:], pos_XY[:,:-1,:])], axis=1)
849
880
  max_dist_traveled = np.where(np.isinf(max_dist_traveled), 0, max_dist_traveled)
850
881
 
851
- selected_persons = (-max_dist_traveled).argsort()[:nb_persons_to_detect]
852
- if reverse:
853
- selected_persons = selected_persons[::-1]
882
+ if not reverse: # greatest to smallest displacement
883
+ max_dist_traveled = -max_dist_traveled
884
+
885
+ selected_persons = (max_dist_traveled).argsort()[:nb_persons_to_detect]
854
886
 
855
887
  return selected_persons
856
888
 
@@ -1647,14 +1679,18 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1647
1679
  # ====================================================
1648
1680
  all_frames_X_homog = make_homogeneous(all_frames_X)
1649
1681
  all_frames_X_homog = all_frames_X_homog[...,new_keypoints_ids]
1650
- all_frames_X_flipped_homog = make_homogeneous(all_frames_X_flipped)
1651
- all_frames_X_flipped_homog = all_frames_X_flipped_homog[...,new_keypoints_ids]
1682
+ if calculate_angles or save_angles:
1683
+ all_frames_X_flipped_homog = make_homogeneous(all_frames_X_flipped)
1684
+ all_frames_X_flipped_homog = all_frames_X_flipped_homog[...,new_keypoints_ids]
1685
+ all_frames_angles_homog = make_homogeneous(all_frames_angles)
1686
+ else:
1687
+ all_frames_X_flipped_homog = all_frames_X_flipped
1688
+ all_frames_angles_homog = all_frames_angles
1652
1689
  all_frames_Y_homog = make_homogeneous(all_frames_Y)
1653
1690
  all_frames_Y_homog = all_frames_Y_homog[...,new_keypoints_ids]
1654
1691
  all_frames_Z_homog = pd.DataFrame(np.zeros_like(all_frames_X_homog)[:,0,:], columns=new_keypoints_names)
1655
1692
  all_frames_scores_homog = make_homogeneous(all_frames_scores)
1656
1693
  all_frames_scores_homog = all_frames_scores_homog[...,new_keypoints_ids]
1657
- all_frames_angles_homog = make_homogeneous(all_frames_angles)
1658
1694
 
1659
1695
  frame_range = [0,frame_count] if video_file == 'webcam' else frame_range
1660
1696
  all_frames_time = pd.Series(np.linspace(frame_range[0]/fps, frame_range[1]/fps, frame_count-frame_range[0]), name='time')
@@ -1683,10 +1719,14 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1683
1719
  selected_persons = get_personIDs_in_detection_order(nb_persons_to_detect)
1684
1720
  elif person_ordering_method == 'last_detected':
1685
1721
  selected_persons = get_personIDs_in_detection_order(nb_persons_to_detect, reverse=True)
1722
+ elif person_ordering_method == 'largest_size':
1723
+ selected_persons = get_personIDs_with_largest_size(all_frames_X_homog, all_frames_Y_homog, nb_persons_to_detect=nb_persons_to_detect, vertical=False)
1724
+ elif person_ordering_method == 'smallest_size':
1725
+ selected_persons = get_personIDs_with_largest_size(all_frames_X_homog, all_frames_Y_homog, nb_persons_to_detect=nb_persons_to_detect, vertical=False, reverse=True)
1686
1726
  elif person_ordering_method == 'greatest_displacement':
1687
1727
  selected_persons = get_personIDs_with_greatest_displacement(all_frames_X_homog, all_frames_Y_homog, nb_persons_to_detect=nb_persons_to_detect, horizontal=True)
1688
1728
  elif person_ordering_method == 'least_displacement':
1689
- selected_persons = get_personIDs_with_greatest_displacement(all_frames_X_homog, all_frames_Y_homog, nb_persons_to_detect=nb_persons_to_detect, reverse=True, horizontal=True)
1729
+ selected_persons = get_personIDs_with_greatest_displacement(all_frames_X_homog, all_frames_Y_homog, nb_persons_to_detect=nb_persons_to_detect, horizontal=True, reverse=True)
1690
1730
  else:
1691
1731
  raise ValueError(f"Invalid person_ordering_method: {person_ordering_method}. Must be 'on_click', 'highest_likelihood', 'greatest_displacement', 'first_detected', or 'last_detected'.")
1692
1732
  logging.info(f'Reordered persons: IDs of persons {selected_persons} become {list(range(len(selected_persons)))}.')
@@ -1702,10 +1742,10 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1702
1742
  trc_data, trc_data_unfiltered = [], []
1703
1743
  for i, idx_person in enumerate(selected_persons):
1704
1744
  pose_path_person = pose_output_path.parent / (pose_output_path.stem + f'_person{i:02d}.trc')
1705
- all_frames_X_person = pd.DataFrame(all_frames_X_homog[:,idx_person,:], columns=new_keypoints_names)
1706
- all_frames_X_flipped_person = pd.DataFrame(all_frames_X_flipped_homog[:,idx_person,:], columns=new_keypoints_names)
1707
- all_frames_Y_person = pd.DataFrame(all_frames_Y_homog[:,idx_person,:], columns=new_keypoints_names)
1708
-
1745
+ all_frames_X_person = pd.DataFrame(all_frames_X_processed[:,idx_person,:], columns=new_keypoints_names)
1746
+ all_frames_Y_person = pd.DataFrame(all_frames_Y_processed[:,idx_person,:], columns=new_keypoints_names)
1747
+ if calculate_angles or save_angles:
1748
+ all_frames_X_flipped_person = pd.DataFrame(all_frames_X_flipped_processed[:,idx_person,:], columns=new_keypoints_names)
1709
1749
  # Delete person if less than 10 valid frames
1710
1750
  pose_nan_count = len(np.where(all_frames_X_person.sum(axis=1)==0)[0])
1711
1751
  if frame_count - frame_range[0] - pose_nan_count <= 10:
@@ -1779,7 +1819,9 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1779
1819
  if show_plots and not to_meters:
1780
1820
  pose_plots(trc_data_unfiltered_i, trc_data_i, i)
1781
1821
 
1782
- all_frames_X_processed[:,idx_person,:], all_frames_X_flipped_processed[:,idx_person,:], all_frames_Y_processed[:,idx_person,:] = all_frames_X_person_filt, all_frames_X_flipped_person, all_frames_Y_person_filt
1822
+ all_frames_X_processed[:,idx_person,:], all_frames_Y_processed[:,idx_person,:] = all_frames_X_person_filt, all_frames_Y_person_filt
1823
+ if calculate_angles or save_angles:
1824
+ all_frames_X_flipped_processed[:,idx_person,:] = all_frames_X_flipped_person
1783
1825
 
1784
1826
 
1785
1827
  #%% Convert px to meters
@@ -2004,9 +2046,11 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
2004
2046
  out_vid = cv2.VideoWriter(str(vid_output_path.absolute()), fourcc, fps, (cam_width, cam_height))
2005
2047
 
2006
2048
  # Reorder persons
2007
- all_frames_X_processed, all_frames_X_flipped_processed, all_frames_Y_processed = all_frames_X_processed[:,selected_persons,:], all_frames_X_flipped_processed[:,selected_persons,:], all_frames_Y_processed[:,selected_persons,:]
2049
+ all_frames_X_processed, all_frames_Y_processed = all_frames_X_processed[:,selected_persons,:], all_frames_Y_processed[:,selected_persons,:]
2008
2050
  all_frames_scores_processed = all_frames_scores_processed[:,selected_persons,:]
2009
- all_frames_angles_processed = all_frames_angles_processed[:,selected_persons,:]
2051
+ if save_angles or calculate_angles:
2052
+ all_frames_X_flipped_processed = all_frames_X_flipped_processed[:,selected_persons,:]
2053
+ all_frames_angles_processed = all_frames_angles_processed[:,selected_persons,:]
2010
2054
 
2011
2055
  # Reorder keypoints ids
2012
2056
  pose_model_with_new_ids = copy.deepcopy(pose_model)
@@ -1,38 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sports2d
3
- Version: 0.8.3
3
+ Version: 0.8.4
4
4
  Summary: Compute 2D human pose and angles from a video or a webcam.
5
5
  Author-email: David Pagnon <contact@david-pagnon.com>
6
- License: BSD 3-Clause License
7
-
8
- Copyright (c) 2022, perfanalytics
9
- All rights reserved.
10
-
11
- Redistribution and use in source and binary forms, with or without
12
- modification, are permitted provided that the following conditions are met:
13
-
14
- 1. Redistributions of source code must retain the above copyright notice, this
15
- list of conditions and the following disclaimer.
16
-
17
- 2. Redistributions in binary form must reproduce the above copyright notice,
18
- this list of conditions and the following disclaimer in the documentation
19
- and/or other materials provided with the distribution.
20
-
21
- 3. Neither the name of the copyright holder nor the names of its
22
- contributors may be used to endorse or promote products derived from
23
- this software without specific prior written permission.
24
-
25
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
-
6
+ License-Expression: BSD-3-Clause
36
7
  Project-URL: Homepage, https://github.com/davidpagnon/Sports2D
37
8
  Project-URL: Bug Tracker, https://github.com/davidpagnon/Sports2D/issues
38
9
  Keywords: markerless,kinematics,OpenPose,OpenSim,Mocap,biomechanics,sports coaching,pose estimation,joint angles,sports analytics,kinovea
@@ -41,7 +12,6 @@ Classifier: Development Status :: 3 - Alpha
41
12
  Classifier: Intended Audience :: Science/Research
42
13
  Classifier: Intended Audience :: Healthcare Industry
43
14
  Classifier: Intended Audience :: Education
44
- Classifier: License :: OSI Approved :: BSD License
45
15
  Classifier: Operating System :: OS Independent
46
16
  Classifier: Topic :: Scientific/Engineering
47
17
  Classifier: Topic :: Scientific/Engineering :: Image Processing
@@ -314,6 +284,8 @@ sports2d --nb_persons_to_detect 2 --person_ordering_method highest_likelihood
314
284
 
315
285
  We recommend to use the `on_click` method if you can afford a manual input. This lets the user handle both the person number and their order in the same stage. When prompted, select the persons you are interested in in the desired order. In our case, lets slide to a frame where both people are visible, and select the woman first, then the man.
316
286
 
287
+ Otherwise, if you want to run Sports2D automatically for example, you can choose other ordering methods such as 'highest_likelihood', 'largest_size', 'smallest_size', 'greatest_displacement', 'least_displacement', 'first_detected', or 'last_detected'.
288
+
317
289
  ``` cmd
318
290
  sports2d --person_ordering_method on_click
319
291
  ```
@@ -480,7 +452,7 @@ sports2d --help
480
452
 
481
453
  '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"],
482
454
  'nb_persons_to_detect': ["n", "number of persons to detect. int or 'all'. 'all' if not specified"],
483
- 'person_ordering_method': ["", "'on_click', 'highest_likelihood', 'greatest_displacement', 'least_displacement', 'first_detected', or 'last_detected'. 'on_click' if not specified"],
455
+ 'person_ordering_method': ["", "'on_click', 'highest_likelihood', 'largest_size', 'smallest_size', 'greatest_displacement', 'least_displacement', 'first_detected', or 'last_detected'. 'on_click' if not specified"],
484
456
  'first_person_height': ["H", "height of the reference person in meters. 1.65 if not specified. Not used if a calibration file is provided"],
485
457
  '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"],
486
458
  'load_trc_px': ["", "load trc file to avaid running pose estimation again. false if not specified"],
@@ -530,7 +502,7 @@ sports2d --help
530
502
  'large_hip_knee_angles': ["", "Hip and knee angles below this value are considered as imprecise. Defaults to 45"],
531
503
  'trimmed_extrema_percent': ["", "Proportion of the most extreme segment values to remove before calculating their mean. Defaults to 50"],
532
504
  'fontSize': ["", "font size for angle values. 0.3 if not specified"],
533
- '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"],
505
+ 'flip_left_right': ["", "true or false. Flips angles when the person faces the other side. The person looks to the right if their toe keypoint is to the right of their heel. Set it to false if the person is sprinting or if you want timeseries to be continuous even when the participent switches their stance. true if not specified"],
534
506
  '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"],
535
507
  'interpolate': ["", "interpolate missing data. true if not specified"],
536
508
  'interp_gap_smaller_than': ["", "interpolate sequences of missing data if they are less than N frames long. 10 if not specified"],
@@ -631,8 +603,9 @@ VIDEO THERE
631
603
  Sports2D:
632
604
  - Detects 2D joint centers from a video or a webcam with RTMLib.
633
605
  - Converts pixel coordinates to meters.
634
- - Optionally computes selected joint and segment angles.
635
- - Optionally saves processed image files and video file. Optionally saves processed poses as a TRC file, and angles as a MOT file (OpenSim compatible).
606
+ - Computes selected joint and segment angles.
607
+ - Optionally performs kinematic optimization via OpenSim.
608
+ - Optionally saves processed image and video files.
636
609
 
637
610
  <br>
638
611
 
@@ -0,0 +1,15 @@
1
+ Sports2D/Sports2D.py,sha256=EYsXZ3A3VpnsVQmpBSftbHC_iivVbyzst6--q2OOb74,30581
2
+ Sports2D/__init__.py,sha256=BuUkPEdItxlkeqz4dmoiPwZLkgAfABJK3KWQ1ujTGwE,153
3
+ Sports2D/process.py,sha256=Omg4xWoUircoqFzU2A6X88RmpV0Ez0RTOm3mv9wpVqY,109592
4
+ Sports2D/Demo/Config_demo.toml,sha256=IXrV7URqERHQ6cBJaPq05Yt3i86-u08RnCzC_dn53AM,13852
5
+ Sports2D/Demo/demo.mp4,sha256=2aZkFxhWR7ESMEtXCT8MGA83p2jmoU2sp1ylQfO3gDk,3968304
6
+ Sports2D/Utilities/__init__.py,sha256=BuUkPEdItxlkeqz4dmoiPwZLkgAfABJK3KWQ1ujTGwE,153
7
+ Sports2D/Utilities/common.py,sha256=idMRmesFv5BPX-5g3z5dOVa7SpS_8tNgijvGrOZlR-k,11185
8
+ Sports2D/Utilities/filter.py,sha256=rfZcqofjllKI_5ovZTKEAmyjOZpB_PzbAJ0P874T8Ak,4973
9
+ Sports2D/Utilities/tests.py,sha256=XnPNK63AZ_xlJBmFmPJtOMrzssBXIPXFzYd73CPzchI,4740
10
+ sports2d-0.8.4.dist-info/licenses/LICENSE,sha256=f4qe3nE0Y7ltJho5w-xAR0jI5PUox5Xl-MsYiY7ZRM8,1521
11
+ sports2d-0.8.4.dist-info/METADATA,sha256=Y0gu23144-yK5ADtvdvlEl4TZEiEkOUkYOZIgly0cPc,38058
12
+ sports2d-0.8.4.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
13
+ sports2d-0.8.4.dist-info/entry_points.txt,sha256=V8dFDIXatz9VvoGgoHzb2wE71C9-f85K6_OjnEQlxww,108
14
+ sports2d-0.8.4.dist-info/top_level.txt,sha256=DoURf9UDB8lQ_9lMUPQMQqhXCvWPFFjJco9NzPlHJ6I,9
15
+ sports2d-0.8.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (79.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,15 +0,0 @@
1
- Sports2D/Sports2D.py,sha256=KWrvWGq49UXta9VJisflyQA-4n7mdu-Uq4GsmDPkaRc,30470
2
- Sports2D/__init__.py,sha256=BuUkPEdItxlkeqz4dmoiPwZLkgAfABJK3KWQ1ujTGwE,153
3
- Sports2D/process.py,sha256=5j36J-G5f9cvoG_1eAPfRoFnPRS8Ipx2YidmY6NR0vQ,107417
4
- Sports2D/Demo/Config_demo.toml,sha256=GhV-VotYlpYMCu7rHY-AKdWVAT4f61z0oL9-MUBRsOc,13828
5
- Sports2D/Demo/demo.mp4,sha256=2aZkFxhWR7ESMEtXCT8MGA83p2jmoU2sp1ylQfO3gDk,3968304
6
- Sports2D/Utilities/__init__.py,sha256=BuUkPEdItxlkeqz4dmoiPwZLkgAfABJK3KWQ1ujTGwE,153
7
- Sports2D/Utilities/common.py,sha256=idMRmesFv5BPX-5g3z5dOVa7SpS_8tNgijvGrOZlR-k,11185
8
- Sports2D/Utilities/filter.py,sha256=rfZcqofjllKI_5ovZTKEAmyjOZpB_PzbAJ0P874T8Ak,4973
9
- Sports2D/Utilities/tests.py,sha256=XnPNK63AZ_xlJBmFmPJtOMrzssBXIPXFzYd73CPzchI,4740
10
- sports2d-0.8.3.dist-info/licenses/LICENSE,sha256=f4qe3nE0Y7ltJho5w-xAR0jI5PUox5Xl-MsYiY7ZRM8,1521
11
- sports2d-0.8.3.dist-info/METADATA,sha256=1e4xNUTcZr4_kDn8Ud8Rj83zQ5nIducWD9vXnW6wYGU,39516
12
- sports2d-0.8.3.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
13
- sports2d-0.8.3.dist-info/entry_points.txt,sha256=V8dFDIXatz9VvoGgoHzb2wE71C9-f85K6_OjnEQlxww,108
14
- sports2d-0.8.3.dist-info/top_level.txt,sha256=DoURf9UDB8lQ_9lMUPQMQqhXCvWPFFjJco9NzPlHJ6I,9
15
- sports2d-0.8.3.dist-info/RECORD,,