Skip to content

Commit ce7df1c

Browse files
Evaluate by dataset velocity (#89)
1 parent 6995f8d commit ce7df1c

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

evaluation/velocity_study.py

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import argparse
2+
import matplotlib.pyplot as plt
3+
import numpy as np
4+
import pandas as pd
5+
import seaborn as sns
6+
from tqdm import tqdm
7+
from pathlib import Path
8+
from scipy import interpolate
9+
from datasets.utils import constants as ds_constants, parsing as ds_parsing
10+
11+
12+
13+
def avg_vel(ds_name, timestamps, joints_gt):
14+
15+
assert 1 <= joints_gt.shape[2] <= 3, 'coordinates must be either 2D or 3D'
16+
# iterate on each joint
17+
data = np.zeros((len(timestamps), len(ds_constants.HPECoreSkeleton.KEYPOINTS_MAP) * 2))
18+
keys = []
19+
for joint_key, joint_ind in ds_constants.HPECoreSkeleton.KEYPOINTS_MAP.items():
20+
data[:,joint_ind*2] = joints_gt[:, joint_ind, 0]
21+
data[:,joint_ind*2+1] = joints_gt[:, joint_ind, 1]
22+
keys.append(joint_key + ' x')
23+
keys.append(joint_key + ' y')
24+
25+
df = pd.DataFrame(abs(data), columns=keys)
26+
# print(df.describe())
27+
avg75 = np.mean(df.describe().loc['75%'])
28+
# print("\n75% = " + str(avg75), flush=True)
29+
avgMax = np.mean(df.describe().loc['max'])
30+
# print("Max = " + str(avgMax), flush=True)
31+
avgMean = np.mean(df.describe().loc['mean'])
32+
# print("Mean = " + str(avgMean), flush=True)
33+
avgStd = np.mean(df.describe().loc['std'])
34+
# print("Std = " + str(avgStd), flush=True)
35+
36+
if(avgMax >= 250 and avgMean >=57):
37+
print("FAST")
38+
elif(avgMax < 100 and avgMean < 18):
39+
print("SLOW")
40+
41+
return avg75, avgMax, avgMean, avgStd
42+
43+
44+
def main(args):
45+
46+
plt.close('all')
47+
48+
# output_folder_path = Path(args.output_folder)
49+
# output_folder_path = output_folder_path.resolve()
50+
# output_folder_path.mkdir(parents=True, exist_ok=True)
51+
results = dict()
52+
results['datasets'] = dict()
53+
results['global'] = dict()
54+
list75 = []
55+
listMax = []
56+
listMean = []
57+
listStd = []
58+
59+
# import GT from yarp
60+
datasets_path = Path(args.datasets_path)
61+
yarp_file_paths = list(datasets_path.glob('**/data.log'))
62+
63+
for yarp_path in tqdm(yarp_file_paths, desc ="Progress: "):
64+
# for yarp_path in track(yarp_file_paths):
65+
66+
if 'skeleton' not in yarp_path.parent.name:
67+
continue
68+
dataset_name = yarp_path.parent.parent.name
69+
print('\x1b[1;33;20m' + "Procesing " + str(dataset_name) + '\x1b[0m')
70+
data = ds_parsing.import_yarp_skeleton_data(yarp_path)
71+
ts_gt = np.concatenate(([.0], data['ts'], [data['ts'][-1] + 1]))
72+
73+
# interpolate ground truth joints so that they can be compared with the high frequency predictions
74+
for k_map in ds_constants.HPECoreSkeleton.KEYPOINTS_MAP.items():
75+
x_interpolation = interpolate.interp1d(ts_gt, np.concatenate(([data[k_map[0]][0, 0]], data[k_map[0]][:, 0], [data[k_map[0]][-1, 0]])))
76+
y_interpolation = interpolate.interp1d(ts_gt, np.concatenate(([data[k_map[0]][0, 1]], data[k_map[0]][:, 1], [data[k_map[0]][-1, 1]])))
77+
data[k_map[0]] = dict()
78+
data[k_map[0]]['x'] = x_interpolation
79+
data[k_map[0]]['y'] = y_interpolation
80+
skeletons_gt = np.zeros((len(ts_gt), len(ds_constants.HPECoreSkeleton.KEYPOINTS_MAP), 2))
81+
for k_map in ds_constants.HPECoreSkeleton.KEYPOINTS_MAP.items():
82+
skeletons_gt[:, k_map[1], 0] = data[k_map[0]]['x'](ts_gt)
83+
skeletons_gt[:, k_map[1], 1] = data[k_map[0]]['y'](ts_gt)
84+
85+
# resample GT at 1 KHz
86+
fHz = 1000
87+
tGT1K = np.arange(ts_gt[0], ts_gt[-1], 1/fHz)
88+
skeletons_gt1K = np.zeros((len(tGT1K), len(ds_constants.HPECoreSkeleton.KEYPOINTS_MAP), 2))
89+
for k_map in ds_constants.HPECoreSkeleton.KEYPOINTS_MAP.items():
90+
skeletons_gt1K[:, k_map[1], 0] = data[k_map[0]]['x'](tGT1K)
91+
skeletons_gt1K[:, k_map[1], 1] = data[k_map[0]]['y'](tGT1K)
92+
# differenciate GT poses
93+
vel_gt1K_noF = np.gradient(skeletons_gt1K, axis=0)*fHz
94+
# filter velocity
95+
from scipy.signal import savgol_filter
96+
vel_gt1K = savgol_filter(vel_gt1K_noF, 901, 3, axis=0)
97+
98+
# calculate statistics for each dataset
99+
value75, valueMax, valueMean, valueStd = avg_vel(str(dataset_name), tGT1K, vel_gt1K)
100+
# add to global list
101+
list75.append(value75)
102+
listMax.append(valueMax)
103+
listMean.append(valueMean)
104+
listStd.append(valueStd)
105+
106+
dataList = list(zip(list75, listMax, listMean, listStd))
107+
df = pd.DataFrame(dataList, columns=['75%', 'Max', 'Mean', 'Std'])
108+
# print(df.describe())
109+
110+
# define clusters for mean velocity
111+
df['mean_group'] = pd.cut(df['Mean'], bins=range(5, 71, 13))
112+
# define clusters for max velocity
113+
df['max_group'] = pd.cut(df['Max'], bins=range(50, 301, 50))
114+
115+
# plots
116+
my_dpi = 96
117+
fig1 = plt.figure(figsize=(2048/my_dpi, 900/my_dpi), dpi=my_dpi)
118+
ax1 = sns.boxplot(x="mean_group", y="Mean", data=df)
119+
ax1.set_xlabel("Speed [px/s]", fontsize=24)
120+
ax1.set_ylabel("Speed [px/s]", fontsize=24)
121+
fig1.suptitle('Mean velocity distribution', fontsize=32, y=0.92)
122+
plt.xticks(fontsize=22, rotation=0)
123+
124+
fig2 = plt.figure(figsize=(2048/my_dpi, 900/my_dpi), dpi=my_dpi)
125+
ax2 = sns.boxplot(x="max_group", y="Max", data=df)
126+
ax2.set_xlabel("Speed [px/s]", fontsize=24)
127+
ax2.set_ylabel("Speed [px/s]", fontsize=24)
128+
fig2.suptitle('Max velocity distribution', fontsize=32, y=0.92)
129+
plt.xticks(fontsize=22, rotation=0)
130+
131+
# print statistics
132+
print(df)
133+
print("Mean values range:")
134+
print("[", np.min(df['Mean']), ", ", np.max(df['Mean']), "]")
135+
print("Max values range:")
136+
print("[", np.min(df['Max']), ", ", np.max(df['Max']), "]")
137+
138+
plt.show()
139+
140+
141+
142+
if __name__ == '__main__':
143+
parser = argparse.ArgumentParser(description='...')
144+
parser.add_argument('-d', '--datasets_path', help='Path to the folders containing data saved in Yarp format', required=True)
145+
parser.add_argument('-o', '--output_folder', help='Path to the folder where velocity study results will be saved', required=False)
146+
147+
args, unknown = parser.parse_known_args()
148+
if(unknown):
149+
print('\x1b[1;31;20m' + 'Unknown argument/s: ' + ' '.join(unknown) + '\x1b[0m')
150+
151+
main(args)

0 commit comments

Comments
 (0)