sports2d 0.5.4__py3-none-any.whl → 0.5.5__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/process.py +41 -23
- {sports2d-0.5.4.dist-info → sports2d-0.5.5.dist-info}/METADATA +1 -1
- {sports2d-0.5.4.dist-info → sports2d-0.5.5.dist-info}/RECORD +7 -7
- {sports2d-0.5.4.dist-info → sports2d-0.5.5.dist-info}/LICENSE +0 -0
- {sports2d-0.5.4.dist-info → sports2d-0.5.5.dist-info}/WHEEL +0 -0
- {sports2d-0.5.4.dist-info → sports2d-0.5.5.dist-info}/entry_points.txt +0 -0
- {sports2d-0.5.4.dist-info → sports2d-0.5.5.dist-info}/top_level.txt +0 -0
Sports2D/process.py
CHANGED
|
@@ -1101,7 +1101,7 @@ def get_personID_with_highest_scores(all_frames_scores):
|
|
|
1101
1101
|
return person_id
|
|
1102
1102
|
|
|
1103
1103
|
|
|
1104
|
-
def compute_floor_line(trc_data, keypoint_names = ['LBigToe', 'RBigToe'],
|
|
1104
|
+
def compute_floor_line(trc_data, keypoint_names = ['LBigToe', 'RBigToe'], toe_speed_below = 1.0, tot_speed_above=2.0):
|
|
1105
1105
|
'''
|
|
1106
1106
|
Compute the floor line equation and angle
|
|
1107
1107
|
from the feet keypoints when they have zero speed.
|
|
@@ -1111,19 +1111,24 @@ def compute_floor_line(trc_data, keypoint_names = ['LBigToe', 'RBigToe'], speed_
|
|
|
1111
1111
|
INPUTS:
|
|
1112
1112
|
- trc_data: pd.DataFrame. The trc data
|
|
1113
1113
|
- keypoint_names: list of str. The names of the keypoints to use
|
|
1114
|
-
-
|
|
1114
|
+
- toe_speed_below: float. The speed threshold (px/frame) below which the keypoints are considered as not moving
|
|
1115
1115
|
|
|
1116
1116
|
OUTPUT:
|
|
1117
1117
|
- angle: float. The angle of the floor line in radians
|
|
1118
1118
|
- xy_origin: list. The origin of the floor line
|
|
1119
1119
|
'''
|
|
1120
1120
|
|
|
1121
|
+
|
|
1122
|
+
# Remove frames where the person is mostly not moving (outlier)
|
|
1123
|
+
av_speeds = np.nanmean([np.linalg.norm(trc_data[kpt].diff(), axis=1) for kpt in trc_data.columns.unique()[1:]], axis=0)
|
|
1124
|
+
trc_data = trc_data[av_speeds>tot_speed_above]
|
|
1125
|
+
|
|
1121
1126
|
# Retrieve zero-speed coordinates for the foot
|
|
1122
1127
|
low_speeds_X, low_speeds_Y = [], []
|
|
1123
1128
|
for kpt in keypoint_names:
|
|
1124
1129
|
speeds = np.linalg.norm(trc_data[kpt].diff(), axis=1)
|
|
1125
1130
|
|
|
1126
|
-
low_speed_frames = trc_data[speeds<
|
|
1131
|
+
low_speed_frames = trc_data[speeds<toe_speed_below].index
|
|
1127
1132
|
low_speeds_coords = trc_data[kpt].loc[low_speed_frames]
|
|
1128
1133
|
low_speeds_coords = low_speeds_coords[low_speeds_coords!=0]
|
|
1129
1134
|
|
|
@@ -1501,7 +1506,7 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
|
|
|
1501
1506
|
frame_count = 0
|
|
1502
1507
|
while cap.isOpened():
|
|
1503
1508
|
# Skip to the starting frame
|
|
1504
|
-
if frame_count < frame_range[0]:
|
|
1509
|
+
if frame_count < frame_range[0] and not load_trc:
|
|
1505
1510
|
cap.read()
|
|
1506
1511
|
frame_count += 1
|
|
1507
1512
|
continue
|
|
@@ -1528,6 +1533,8 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
|
|
|
1528
1533
|
|
|
1529
1534
|
# Retrieve pose or Estimate pose and track people
|
|
1530
1535
|
if load_trc:
|
|
1536
|
+
if frame_nb >= len(keypoints_all):
|
|
1537
|
+
break
|
|
1531
1538
|
keypoints = keypoints_all[frame_nb]
|
|
1532
1539
|
scores = scores_all[frame_nb]
|
|
1533
1540
|
else:
|
|
@@ -1545,18 +1552,23 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
|
|
|
1545
1552
|
valid_X, valid_Y, valid_scores = [], [], []
|
|
1546
1553
|
valid_X_flipped, valid_angles = [], []
|
|
1547
1554
|
for person_idx in range(len(keypoints)):
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1555
|
+
if load_trc:
|
|
1556
|
+
person_X = keypoints[person_idx][:,0]
|
|
1557
|
+
person_Y = keypoints[person_idx][:,1]
|
|
1558
|
+
person_scores = scores[person_idx]
|
|
1559
|
+
else:
|
|
1560
|
+
# Retrieve keypoints and scores for the person, remove low-confidence keypoints
|
|
1561
|
+
person_X, person_Y = np.where(scores[person_idx][:, np.newaxis] < keypoint_likelihood_threshold, np.nan, keypoints[person_idx]).T
|
|
1562
|
+
person_scores = np.where(scores[person_idx] < keypoint_likelihood_threshold, np.nan, scores[person_idx])
|
|
1563
|
+
|
|
1564
|
+
# Skip person if the fraction of valid detected keypoints is too low
|
|
1565
|
+
enough_good_keypoints = len(person_scores[~np.isnan(person_scores)]) >= len(person_scores) * keypoint_number_threshold
|
|
1566
|
+
scores_of_good_keypoints = person_scores[~np.isnan(person_scores)]
|
|
1567
|
+
average_score_of_remaining_keypoints_is_enough = (np.nanmean(scores_of_good_keypoints) if len(scores_of_good_keypoints)>0 else 0) >= average_likelihood_threshold
|
|
1568
|
+
if not enough_good_keypoints or not average_score_of_remaining_keypoints_is_enough:
|
|
1569
|
+
person_X = np.full_like(person_X, np.nan)
|
|
1570
|
+
person_Y = np.full_like(person_Y, np.nan)
|
|
1571
|
+
person_scores = np.full_like(person_scores, np.nan)
|
|
1560
1572
|
valid_X.append(person_X)
|
|
1561
1573
|
valid_Y.append(person_Y)
|
|
1562
1574
|
valid_scores.append(person_scores)
|
|
@@ -1634,7 +1646,8 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
|
|
|
1634
1646
|
frame_range = [0,frame_count] if video_file == 'webcam' else frame_range
|
|
1635
1647
|
all_frames_time = pd.Series(np.linspace(frame_range[0]/fps/slowmo_factor, frame_range[1]/fps/slowmo_factor, frame_count+1), name='time')
|
|
1636
1648
|
if not multiperson:
|
|
1637
|
-
|
|
1649
|
+
calib_on_person_id = get_personID_with_highest_scores(all_frames_scores)
|
|
1650
|
+
detected_persons = [calib_on_person_id]
|
|
1638
1651
|
else:
|
|
1639
1652
|
detected_persons = range(all_frames_X_homog.shape[1])
|
|
1640
1653
|
|
|
@@ -1735,24 +1748,26 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
|
|
|
1735
1748
|
|
|
1736
1749
|
if floor_angle == 'auto' or xy_origin == 'auto':
|
|
1737
1750
|
# estimated from the line formed by the toes when they are on the ground (where speed = 0)
|
|
1738
|
-
|
|
1751
|
+
toe_speed_below = 1 # m/s (below which the foot is considered to be stationary)
|
|
1752
|
+
px_per_m = height_px/person_height_m
|
|
1753
|
+
toe_speed_below_px_frame = toe_speed_below * px_per_m / (fps*slowmo_factor)
|
|
1754
|
+
floor_angle_estim, xy_origin_estim = compute_floor_line(trc_data[calib_on_person_id], keypoint_names=['LBigToe', 'RBigToe'], toe_speed_below=toe_speed_below_px_frame)
|
|
1739
1755
|
if not floor_angle == 'auto':
|
|
1740
1756
|
floor_angle_estim = floor_angle
|
|
1741
|
-
floor_angle_estim = -floor_angle_estim # Y points downwards
|
|
1742
1757
|
if xy_origin == 'auto':
|
|
1743
1758
|
cx, cy = xy_origin_estim
|
|
1744
1759
|
else:
|
|
1745
1760
|
cx, cy = xy_origin
|
|
1746
1761
|
logging.info(f'Using height of person #{calib_on_person_id} ({person_height_m}m) to convert coordinates in meters. '
|
|
1747
|
-
f'Floor angle: {np.degrees(
|
|
1748
|
-
f'xy_origin: {xy_origin if not xy_origin=="auto" else f"auto (estimation: {[round(c
|
|
1762
|
+
f'Floor angle: {np.degrees(floor_angle_estim) if not floor_angle=="auto" else f"auto (estimation: {round(np.degrees(floor_angle_estim),2)}°)"}, '
|
|
1763
|
+
f'xy_origin: {xy_origin if not xy_origin=="auto" else f"auto (estimation: {[round(c) for c in xy_origin_estim]})"}.')
|
|
1749
1764
|
|
|
1750
1765
|
# Coordinates in m
|
|
1751
1766
|
for i in range(len(trc_data)):
|
|
1752
1767
|
if not np.array(trc_data[i].iloc[:,1:] ==0).all():
|
|
1753
|
-
trc_data_m_i = pd.concat([convert_px_to_meters(trc_data[i][kpt_name], person_height_m, height_px, cx, cy, floor_angle_estim) for kpt_name in keypoints_names], axis=1)
|
|
1768
|
+
trc_data_m_i = pd.concat([convert_px_to_meters(trc_data[i][kpt_name], person_height_m, height_px, cx, cy, -floor_angle_estim) for kpt_name in keypoints_names], axis=1)
|
|
1754
1769
|
trc_data_m_i.insert(0, 't', all_frames_time)
|
|
1755
|
-
trc_data_unfiltered_m_i = pd.concat([convert_px_to_meters(trc_data_unfiltered[i][kpt_name], person_height_m, height_px, cx, cy, floor_angle_estim) for kpt_name in keypoints_names], axis=1)
|
|
1770
|
+
trc_data_unfiltered_m_i = pd.concat([convert_px_to_meters(trc_data_unfiltered[i][kpt_name], person_height_m, height_px, cx, cy, -floor_angle_estim) for kpt_name in keypoints_names], axis=1)
|
|
1756
1771
|
trc_data_unfiltered_m_i.insert(0, 't', all_frames_time)
|
|
1757
1772
|
|
|
1758
1773
|
if to_meters and show_plots:
|
|
@@ -1815,6 +1830,9 @@ def process_fun(config_dict, video_file, time_range, frame_rate, result_dir):
|
|
|
1815
1830
|
if save_angles and calculate_angles:
|
|
1816
1831
|
logging.info('\nPost-processing angles:')
|
|
1817
1832
|
all_frames_angles = make_homogeneous(all_frames_angles)
|
|
1833
|
+
|
|
1834
|
+
# unwrap angles
|
|
1835
|
+
all_frames_angles = np.unwrap(all_frames_angles, axis=0, period=180)
|
|
1818
1836
|
|
|
1819
1837
|
# Process angles for each person
|
|
1820
1838
|
for i in detected_persons:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Sports2D/Sports2D.py,sha256=dZv4xglguFJZDu9Zv0AZKAGu1TQIW9ynmY8pMsNHw14,26377
|
|
2
2
|
Sports2D/__init__.py,sha256=TyCP7Uuuy6CNklhPf8W84MbYoO1_-1dxowSYAJyk_OI,102
|
|
3
|
-
Sports2D/process.py,sha256=
|
|
3
|
+
Sports2D/process.py,sha256=g2kfmEaSs8LTir3IpuWSKDsNwYqnuWGLpsMj-vQ-xUE,88675
|
|
4
4
|
Sports2D/Demo/Config_demo.toml,sha256=kp2iqohOLlN3vzFBDgz69BB8kpaYqcGXDQpchlxeO9w,6769
|
|
5
5
|
Sports2D/Demo/demo.mp4,sha256=2aZkFxhWR7ESMEtXCT8MGA83p2jmoU2sp1ylQfO3gDk,3968304
|
|
6
6
|
Sports2D/Utilities/__init__.py,sha256=TyCP7Uuuy6CNklhPf8W84MbYoO1_-1dxowSYAJyk_OI,102
|
|
@@ -8,9 +8,9 @@ Sports2D/Utilities/common.py,sha256=FEWmlq9HNlHzA2ioV5MPPOeC-5Py4JaDbIIxQgq9hGE,
|
|
|
8
8
|
Sports2D/Utilities/filter.py,sha256=8mVefMjDzxmh9a30eNtIrUuK_mUKoOJ2Nr-OzcQKkKM,4922
|
|
9
9
|
Sports2D/Utilities/skeletons.py,sha256=44IWpz47zjh_6YDqkwaJnSysaGi7ovgYE25ji-hC-Kw,15660
|
|
10
10
|
Sports2D/Utilities/tests.py,sha256=g06HBExGkvZrhZpNXN19G9Shisfgp1cqjAp0kFxiKEc,2574
|
|
11
|
-
sports2d-0.5.
|
|
12
|
-
sports2d-0.5.
|
|
13
|
-
sports2d-0.5.
|
|
14
|
-
sports2d-0.5.
|
|
15
|
-
sports2d-0.5.
|
|
16
|
-
sports2d-0.5.
|
|
11
|
+
sports2d-0.5.5.dist-info/LICENSE,sha256=f4qe3nE0Y7ltJho5w-xAR0jI5PUox5Xl-MsYiY7ZRM8,1521
|
|
12
|
+
sports2d-0.5.5.dist-info/METADATA,sha256=vIFM97emgo_ZgljSbeI_lBRI2QObHeAwB3uf5TCJ5x8,23067
|
|
13
|
+
sports2d-0.5.5.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
14
|
+
sports2d-0.5.5.dist-info/entry_points.txt,sha256=h2CJTuydtNf8JyaLoWxWl5HTSIxx5Ra_FSiSGQsf7Sk,52
|
|
15
|
+
sports2d-0.5.5.dist-info/top_level.txt,sha256=DoURf9UDB8lQ_9lMUPQMQqhXCvWPFFjJco9NzPlHJ6I,9
|
|
16
|
+
sports2d-0.5.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|