sports2d 0.8.0__py3-none-any.whl → 0.8.2__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.
@@ -93,7 +93,6 @@ tracking_mode = 'sports2d' # 'sports2d' or 'deepsort'. 'deepsort' is slower, har
93
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
94
94
  # Requires `pip install torch torchvision torchreid gdown tensorboard`
95
95
 
96
-
97
96
  # Processing parameters
98
97
  keypoint_likelihood_threshold = 0.3 # Keypoints whose likelihood is lower will not be taken into account
99
98
  average_likelihood_threshold = 0.5 # Person will be ignored if average likelihood of good keypoints is lower than this value
Sports2D/Sports2D.py CHANGED
@@ -252,7 +252,7 @@ CONFIG_HELP = {'config': ["C", "path to a toml configuration file"],
252
252
  'device': ["", "Device for pose estimatino can be 'auto', 'openvino', 'onnxruntime', 'opencv'"],
253
253
  'to_meters': ["M", "convert pixels to meters. true if not specified"],
254
254
  'make_c3d': ["", "Convert trc to c3d file. true if not specified"],
255
- 'floor_angle': ["", "angle of the floor. 'auto' if not specified"],
255
+ 'floor_angle': ["", "angle of the floor (degrees). 'auto' if not specified"],
256
256
  'xy_origin': ["", "origin of the xy plane. 'auto' if not specified"],
257
257
  'calib_file': ["", "path to calibration file. '' if not specified, eg no calibration file"],
258
258
  'save_calib': ["", "save calibration file. true if not specified"],
Sports2D/process.py CHANGED
@@ -56,6 +56,7 @@ import sys
56
56
  import logging
57
57
  import json
58
58
  import ast
59
+ import copy
59
60
  import shutil
60
61
  import os
61
62
  from importlib.metadata import version
@@ -642,7 +643,7 @@ def make_trc_with_trc_data(trc_data, trc_path, fps=30):
642
643
 
643
644
  INPUTS:
644
645
  - trc_data: pd.DataFrame. The time and coordinates of the keypoints.
645
- The column names must be 't', 'kpt1', 'kpt1', 'kpt1', 'kpt2', 'kpt2', 'kpt2', ...
646
+ The column names must be 'time', 'kpt1', 'kpt1', 'kpt1', 'kpt2', 'kpt2', 'kpt2', ...
646
647
  - trc_path: Path. The path to the TRC file to save
647
648
  - fps: float. The framerate of the video
648
649
 
@@ -1349,10 +1350,16 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1349
1350
  trimmed_extrema_percent = config_dict.get('kinematics').get('trimmed_extrema_percent')
1350
1351
  close_to_zero_speed_px = config_dict.get('kinematics').get('close_to_zero_speed_px')
1351
1352
  close_to_zero_speed_m = config_dict.get('kinematics').get('close_to_zero_speed_m')
1352
- if do_ik:
1353
- if use_augmentation:
1354
- from Pose2Sim.markerAugmentation import augment_markers_all
1355
- from Pose2Sim.kinematics import kinematics_all
1353
+ if do_ik or use_augmentation:
1354
+ try:
1355
+ if use_augmentation:
1356
+ from Pose2Sim.markerAugmentation import augment_markers_all
1357
+ if do_ik:
1358
+ from Pose2Sim.kinematics import kinematics_all
1359
+ except ImportError:
1360
+ logging.error("OpenSim package is not installed. Please install it to use inverse kinematics or marker augmentation features (see 'Full install' section of the documentation).")
1361
+ raise ImportError("OpenSim package is not installed. Please install it to use inverse kinematics or marker augmentation features (see 'Full install' section of the documentation).")
1362
+
1356
1363
  # Create a Pose2Sim dictionary and fill in missing keys
1357
1364
  recursivedict = lambda: defaultdict(recursivedict)
1358
1365
  Pose2Sim_config_dict = recursivedict()
@@ -1427,7 +1434,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1427
1434
  backend=backend, device=device)
1428
1435
 
1429
1436
  except (json.JSONDecodeError, TypeError):
1430
- logging.warning("\nInvalid mode. Must be 'lightweight', 'balanced', 'performance', or '''{dictionary}''' of parameters within triple quotes. Make sure input_sizes are within square brackets.")
1437
+ logging.warning("Invalid mode. Must be 'lightweight', 'balanced', 'performance', or '''{dictionary}''' of parameters within triple quotes. Make sure input_sizes are within square brackets.")
1431
1438
  logging.warning('Using the default "balanced" mode.')
1432
1439
  mode = 'balanced'
1433
1440
 
@@ -1457,6 +1464,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1457
1464
  keypoints_ids = [node.id for _, _, node in RenderTree(pose_model) if node.id!=None]
1458
1465
  keypoints_names = [node.name for _, _, node in RenderTree(pose_model) if node.id!=None]
1459
1466
  t0 = 0
1467
+ print(keypoints_names, keypoints_ids)
1460
1468
 
1461
1469
  # Set up pose tracker
1462
1470
  try:
@@ -1468,7 +1476,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1468
1476
  if tracking_mode not in ['deepsort', 'sports2d']:
1469
1477
  logging.warning(f"Tracking mode {tracking_mode} not recognized. Using sports2d method.")
1470
1478
  tracking_mode = 'sports2d'
1471
- logging.info(f'\nPose tracking set up for "{pose_model_name}" model.')
1479
+ logging.info(f'Pose tracking set up for "{pose_model_name}" model.')
1472
1480
  logging.info(f'Mode: {mode}.\n')
1473
1481
  logging.info(f'Persons are detected every {det_frequency} frames and tracked inbetween. Tracking is done with {tracking_mode}.')
1474
1482
  if tracking_mode == 'deepsort': logging.info(f'Deepsort parameters: {deepsort_params}.')
@@ -1494,7 +1502,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1494
1502
  logging.warning(f"Skipping {ang_name} angle computation because at least one of the following keypoints is not provided by the model: {ang_params[0]}.")
1495
1503
 
1496
1504
 
1497
- # ====================================================
1505
+ #%% ==================================================
1498
1506
  # Process video or webcam feed
1499
1507
  # ====================================================
1500
1508
  logging.info(f"\nProcessing video stream...")
@@ -1528,10 +1536,6 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1528
1536
  else:
1529
1537
  frames.append(frame.copy())
1530
1538
 
1531
- cv2.putText(frame, f"Press 'q' to quit", (cam_width-int(400*fontSize), cam_height-20), cv2.FONT_HERSHEY_SIMPLEX, fontSize+0.2, (255,255,255), thickness+1, cv2.LINE_AA)
1532
- cv2.putText(frame, f"Press 'q' to quit", (cam_width-int(400*fontSize), cam_height-20), cv2.FONT_HERSHEY_SIMPLEX, fontSize+0.2, (0,0,255), thickness, cv2.LINE_AA)
1533
-
1534
-
1535
1539
  # Retrieve pose or Estimate pose and track people
1536
1540
  if load_trc_px:
1537
1541
  if frame_nb >= len(keypoints_all):
@@ -1607,6 +1611,8 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1607
1611
  # Draw keypoints and skeleton
1608
1612
  if show_realtime_results:
1609
1613
  img = frame.copy()
1614
+ cv2.putText(img, f"Press 'q' to stop", (cam_width-int(600*fontSize), cam_height-20), cv2.FONT_HERSHEY_SIMPLEX, fontSize+0.2, (255,255,255), thickness+1, cv2.LINE_AA)
1615
+ cv2.putText(img, f"Press 'q' to stop", (cam_width-int(600*fontSize), cam_height-20), cv2.FONT_HERSHEY_SIMPLEX, fontSize+0.2, (0,0,255), thickness, cv2.LINE_AA)
1610
1616
  img = draw_bounding_box(img, valid_X, valid_Y, colors=colors, fontSize=fontSize, thickness=thickness)
1611
1617
  img = draw_keypts(img, valid_X, valid_Y, valid_scores, cmap_str='RdYlGn')
1612
1618
  img = draw_skel(img, valid_X, valid_Y, pose_model)
@@ -1636,7 +1642,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1636
1642
  cv2.destroyAllWindows()
1637
1643
 
1638
1644
 
1639
- # ====================================================
1645
+ #%% ==================================================
1640
1646
  # Post-processing: Select persons, Interpolate, filter, and save pose and angles
1641
1647
  # ====================================================
1642
1648
  all_frames_X_homog = make_homogeneous(all_frames_X)
@@ -1651,12 +1657,11 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1651
1657
  all_frames_angles_homog = make_homogeneous(all_frames_angles)
1652
1658
 
1653
1659
  frame_range = [0,frame_count] if video_file == 'webcam' else frame_range
1660
+ all_frames_time = pd.Series(np.linspace(frame_range[0]/fps, frame_range[1]/fps, frame_count-frame_range[0]), name='time')
1654
1661
  if load_trc_px:
1655
- all_frames_time = time_col
1656
1662
  selected_persons = [0]
1657
1663
  else:
1658
1664
  # Select persons
1659
- all_frames_time = pd.Series(np.linspace(frame_range[0]/fps, frame_range[1]/fps, frame_count-frame_range[0]), name='time')
1660
1665
  nb_detected_persons = all_frames_scores_homog.shape[1]
1661
1666
  if nb_persons_to_detect == 'all':
1662
1667
  nb_persons_to_detect = all_frames_scores_homog.shape[1]
@@ -1687,7 +1692,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1687
1692
  logging.info(f'Reordered persons: IDs of persons {selected_persons} become {list(range(len(selected_persons)))}.')
1688
1693
 
1689
1694
 
1690
- # ====================================================
1695
+ #%% ==================================================
1691
1696
  # Post-processing pose
1692
1697
  # ====================================================
1693
1698
  all_frames_X_processed, all_frames_X_flipped_processed, all_frames_Y_processed, all_frames_scores_processed, all_frames_angles_processed = all_frames_X_homog.copy(), all_frames_X_flipped_homog.copy(), all_frames_Y_homog.copy(), all_frames_scores_homog.copy(), all_frames_angles_homog.copy()
@@ -1706,8 +1711,8 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1706
1711
  if frame_count - frame_range[0] - pose_nan_count <= 10:
1707
1712
  all_frames_X_processed[:,idx_person,:], all_frames_X_flipped_processed[:,idx_person,:], all_frames_Y_processed[:,idx_person,:] = np.nan, np.nan, np.nan
1708
1713
  columns=np.array([[c]*3 for c in all_frames_X_person.columns]).flatten()
1709
- trc_data_i = pd.DataFrame(0, index=all_frames_X_person.index, columns=['t']+list(columns))
1710
- trc_data_i['t'] = all_frames_time
1714
+ trc_data_i = pd.DataFrame(0, index=all_frames_X_person.index, columns=['time']+list(columns))
1715
+ trc_data_i['time'] = all_frames_time
1711
1716
  trc_data.append(trc_data_i)
1712
1717
  trc_data_unfiltered_i = trc_data_i.copy()
1713
1718
  trc_data_unfiltered.append(trc_data_unfiltered_i)
@@ -1777,7 +1782,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1777
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
1778
1783
 
1779
1784
 
1780
- # Convert px to meters
1785
+ #%% Convert px to meters
1781
1786
  trc_data_m = []
1782
1787
  if to_meters and save_pose:
1783
1788
  logging.info('\nConverting pose to meters:')
@@ -1796,17 +1801,17 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1796
1801
  toe_speed_below_px_frame = toe_speed_below * px_per_m / fps
1797
1802
  if floor_angle == 'auto' or xy_origin == 'auto':
1798
1803
  # estimated from the line formed by the toes when they are on the ground (where speed = 0)
1799
- # try:
1804
+ try:
1800
1805
  if all(key in trc_data[0] for key in ['LBigToe', 'RBigToe']):
1801
1806
  floor_angle_estim, xy_origin_estim, _ = compute_floor_line(trc_data[0], keypoint_names=['LBigToe', 'RBigToe'], toe_speed_below=toe_speed_below_px_frame)
1802
1807
  else:
1803
1808
  floor_angle_estim, xy_origin_estim, _ = compute_floor_line(trc_data[0], keypoint_names=['LAnkle', 'RAnkle'], toe_speed_below=toe_speed_below_px_frame)
1804
1809
  xy_origin_estim[0] = xy_origin_estim[0]-0.13
1805
1810
  logging.warning(f'The RBigToe and LBigToe are missing from your model. Using ankles - 13 cm to compute the floor line.')
1806
- # except:
1807
- # floor_angle_estim = 0
1808
- # xy_origin_estim = cam_width/2, cam_height/2
1809
- # logging.warning(f'Could not estimate the floor angle and xy_origin from person {0}. Make sure that the full body is visible. Using floor angle = 0° and xy_origin = [{cam_width/2}, {cam_height/2}] px.')
1811
+ except:
1812
+ floor_angle_estim = 0
1813
+ xy_origin_estim = cam_width/2, cam_height/2
1814
+ logging.warning(f'Could not estimate the floor angle and xy_origin from person {0}. Make sure that the full body is visible. Using floor angle = 0° and xy_origin = [{cam_width/2}, {cam_height/2}] px.')
1810
1815
  if not floor_angle == 'auto':
1811
1816
  floor_angle_estim = floor_angle
1812
1817
  if xy_origin == 'auto':
@@ -1845,9 +1850,10 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1845
1850
 
1846
1851
  # Convert to meters
1847
1852
  px_to_m_i = [convert_px_to_meters(trc_data[i][kpt_name], first_person_height, height_px, cx, cy, -floor_angle_estim, visible_side=visible_side_i) for kpt_name in new_keypoints_names]
1848
- trc_data_m_i = pd.concat([all_frames_time.rename('t')]+px_to_m_i, axis=1)
1853
+ trc_data_m_i = pd.concat([all_frames_time.rename('time')]+px_to_m_i, axis=1)
1854
+ trc_data_m_i = trc_data_m_i.ffill(axis=0).bfill(axis=0)
1849
1855
  px_to_m_unfiltered_i = [convert_px_to_meters(trc_data_unfiltered[i][kpt_name], first_person_height, height_px, cx, cy, -floor_angle_estim) for kpt_name in new_keypoints_names]
1850
- trc_data_unfiltered_m_i = pd.concat([all_frames_time.rename('t')]+px_to_m_unfiltered_i, axis=1)
1856
+ trc_data_unfiltered_m_i = pd.concat([all_frames_time.rename('time')]+px_to_m_unfiltered_i, axis=1)
1851
1857
 
1852
1858
  if to_meters and show_plots:
1853
1859
  pose_plots(trc_data_unfiltered_m_i, trc_data_m_i, i)
@@ -1904,7 +1910,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1904
1910
 
1905
1911
 
1906
1912
 
1907
- # ====================================================
1913
+ #%% ==================================================
1908
1914
  # Post-processing angles
1909
1915
  # ====================================================
1910
1916
  if save_angles and calculate_angles:
@@ -1984,11 +1990,11 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
1984
1990
 
1985
1991
  # Plotting angles before and after interpolation and filtering
1986
1992
  if show_plots:
1987
- all_frames_angles_person.insert(0, 't', all_frames_time)
1993
+ all_frames_angles_person.insert(0, 'time', all_frames_time)
1988
1994
  angle_plots(all_frames_angles_person, angle_data, i) # i = current person
1989
1995
 
1990
1996
 
1991
- # ====================================================
1997
+ #%% ==================================================
1992
1998
  # Save images/video with processed pose and angles
1993
1999
  # ====================================================
1994
2000
  if save_vid or save_img:
@@ -2003,7 +2009,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
2003
2009
  all_frames_angles_processed = all_frames_angles_processed[:,selected_persons,:]
2004
2010
 
2005
2011
  # Reorder keypoints ids
2006
- pose_model_with_new_ids = pose_model
2012
+ pose_model_with_new_ids = copy.deepcopy(pose_model)
2007
2013
  new_id = 0
2008
2014
  for node in PreOrderIter(pose_model_with_new_ids):
2009
2015
  if node.id!=None:
@@ -2021,7 +2027,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
2021
2027
  img = frame.copy()
2022
2028
  img = draw_bounding_box(img, valid_X, valid_Y, colors=colors, fontSize=fontSize, thickness=thickness)
2023
2029
  img = draw_keypts(img, valid_X, valid_Y, valid_scores, cmap_str='RdYlGn')
2024
- img = draw_skel(img, valid_X, valid_Y, pose_model)
2030
+ img = draw_skel(img, valid_X, valid_Y, pose_model_with_new_ids)
2025
2031
  if calculate_angles:
2026
2032
  img = draw_angles(img, valid_X, valid_Y, valid_angles, valid_X_flipped, new_keypoints_ids, new_keypoints_names, angle_names, display_angle_values_on=display_angle_values_on, colors=colors, fontSize=fontSize, thickness=thickness)
2027
2033
 
@@ -2043,7 +2049,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
2043
2049
  logging.info(f"Processed images saved to {img_output_dir.resolve()}.")
2044
2050
 
2045
2051
 
2046
- # ====================================================
2052
+ #%% ==================================================
2047
2053
  # OpenSim inverse kinematics (and optional marker augmentation)
2048
2054
  # ====================================================
2049
2055
  if do_ik or use_augmentation:
@@ -2064,6 +2070,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
2064
2070
 
2065
2071
  heights_m, masses = [], []
2066
2072
  for i in range(len(trc_data_m)):
2073
+ trc_data_m_i = trc_data_m[i]
2067
2074
  if do_ik and not use_augmentation:
2068
2075
  logging.info(f'- Person {i}: Running scaling and inverse kinematics without marker augmentation. Set use_augmentation to True if you need it.')
2069
2076
  elif not do_ik and use_augmentation:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sports2d
3
- Version: 0.8.0
3
+ Version: 0.8.2
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
6
  License: BSD 3-Clause License
@@ -105,7 +105,7 @@ Dynamic: license-file
105
105
  > - Better visualization output
106
106
  > - More flexible, easier to run
107
107
  >
108
- > Run `pip install sports2d -U` to get the latest version.
108
+ > Run `pip install sports2d pose2sim -U` to get the latest version.
109
109
 
110
110
  ***N.B.:*** As always, I am more than happy to welcome contributions (see [How to contribute](#how-to-contribute-and-to-do-list))!
111
111
  <!--User-friendly Colab version released! (and latest issues fixed, too)\
@@ -122,7 +122,7 @@ https://github.com/user-attachments/assets/6a444474-4df1-4134-af0c-e9746fa433ad
122
122
 
123
123
  `Warning:` Angle estimation is only as good as the pose estimation algorithm, i.e., it is not perfect.\
124
124
  `Warning:` Results are acceptable only if the persons move in the 2D plane (sagittal or frontal plane). The persons need to be filmed as parallel as possible to the motion plane.\
125
- If you need 3D research-grade markerless joint kinematics, consider using several cameras, and constraining angles to a biomechanically accurate model. See **[Pose2Sim](https://github.com/perfanalytics/pose2sim)** for example.
125
+ If you need 3D research-grade markerless joint kinematics, consider using several cameras with **[Pose2Sim](https://github.com/perfanalytics/pose2sim)**.
126
126
 
127
127
  <!--`Warning:` Google Colab does not follow the European GDPR requirements regarding data privacy. [Install locally](#installation) if this matters.-->
128
128
 
@@ -208,7 +208,7 @@ pip install .
208
208
 
209
209
  - **Install Sports2D with Pose2Sim**:
210
210
  ``` cmd
211
- pip install sports2d pose2sim
211
+ pip install sports2d
212
212
  ```
213
213
 
214
214
 
@@ -238,7 +238,6 @@ The Demo video is voluntarily challenging to demonstrate the robustness of the p
238
238
  - One person walking in the sagittal plane
239
239
  - One person doing jumping jacks in the frontal plane. This person then performs a flip while being backlit, both of which are challenging for the pose detection algorithm
240
240
  - One tiny person flickering in the background who needs to be ignored
241
- - The first person is starting high and ending low on the image, which messes up the automatic floor angle calculation. You can set it up manually with the parameter `--floor_angle 0`
242
241
 
243
242
  <br>
244
243
 
@@ -509,7 +508,7 @@ sports2d --help
509
508
  'device': ["", "Device for pose estimatino can be 'auto', 'openvino', 'onnxruntime', 'opencv'"],
510
509
  'to_meters': ["M", "convert pixels to meters. true if not specified"],
511
510
  'make_c3d': ["", "Convert trc to c3d file. true if not specified"],
512
- 'floor_angle': ["", "angle of the floor. 'auto' if not specified"],
511
+ 'floor_angle': ["", "angle of the floor (degrees). 'auto' if not specified"],
513
512
  'xy_origin': ["", "origin of the xy plane. 'auto' if not specified"],
514
513
  'calib_file': ["", "path to calibration file. '' if not specified, eg no calibration file"],
515
514
  'save_calib': ["", "save calibration file. true if not specified"],
@@ -0,0 +1,15 @@
1
+ Sports2D/Sports2D.py,sha256=KWrvWGq49UXta9VJisflyQA-4n7mdu-Uq4GsmDPkaRc,30470
2
+ Sports2D/__init__.py,sha256=BuUkPEdItxlkeqz4dmoiPwZLkgAfABJK3KWQ1ujTGwE,153
3
+ Sports2D/process.py,sha256=AtD17Q68Qh688BQKqgnmBWhlNgcl_Iz1igN5q-zxoMs,107297
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.2.dist-info/licenses/LICENSE,sha256=f4qe3nE0Y7ltJho5w-xAR0jI5PUox5Xl-MsYiY7ZRM8,1521
11
+ sports2d-0.8.2.dist-info/METADATA,sha256=KqPyLRBEtEVB_CK7OrZQBMebuHFaT2gbGXqx745TgWU,39516
12
+ sports2d-0.8.2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
13
+ sports2d-0.8.2.dist-info/entry_points.txt,sha256=V8dFDIXatz9VvoGgoHzb2wE71C9-f85K6_OjnEQlxww,108
14
+ sports2d-0.8.2.dist-info/top_level.txt,sha256=DoURf9UDB8lQ_9lMUPQMQqhXCvWPFFjJco9NzPlHJ6I,9
15
+ sports2d-0.8.2.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- Sports2D/Sports2D.py,sha256=0BQ5ainW3EOxElwiXHGywDKVlnHktTIz3EfEH3JhJR0,30460
2
- Sports2D/__init__.py,sha256=BuUkPEdItxlkeqz4dmoiPwZLkgAfABJK3KWQ1ujTGwE,153
3
- Sports2D/process.py,sha256=ymiWlS_VakIUy99pEle2mbuZKcQV2KE5AaauAy95Xuo,106637
4
- Sports2D/Demo/Config_demo.toml,sha256=STcdCLpi4-94RpkP6JjvRUxce_QRQnTzjAny71b6ejI,13829
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.0.dist-info/licenses/LICENSE,sha256=f4qe3nE0Y7ltJho5w-xAR0jI5PUox5Xl-MsYiY7ZRM8,1521
11
- sports2d-0.8.0.dist-info/METADATA,sha256=QrX8rCAoE8-aHew7HeY5eGsvRBrez7AVVWQBfdCoYyc,39763
12
- sports2d-0.8.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
13
- sports2d-0.8.0.dist-info/entry_points.txt,sha256=V8dFDIXatz9VvoGgoHzb2wE71C9-f85K6_OjnEQlxww,108
14
- sports2d-0.8.0.dist-info/top_level.txt,sha256=DoURf9UDB8lQ_9lMUPQMQqhXCvWPFFjJco9NzPlHJ6I,9
15
- sports2d-0.8.0.dist-info/RECORD,,