3D-animation-arena commited on
Commit
815bbeb
·
verified ·
1 Parent(s): b92422b

Add column to data

Browse files
Files changed (2) hide show
  1. app.py +2 -5
  2. utils.py +178 -0
app.py CHANGED
@@ -196,20 +196,16 @@ with gr.Blocks(title='3D Animation Arena', head=head, css_paths='static/style.cs
196
  - GVHMR (https://github.com/zju3dv/GVHMR)
197
  - HybrIK (https://github.com/jeffffffli/HybrIK)
198
  - WHAM (https://github.com/yohanshin/WHAM)
199
- - CameraHMR (https://github.com/pixelite1201/CameraHMR)
200
- - STAF (https://github.com/yw0208/STAF)
201
- - TokenHMR (https://github.com/saidwivedi/TokenHMR)
202
 
203
  All inferences are precomputed following the code in the associated GitHub repository.
204
  Some post-inference modifications have been made to some models in order to make the comparison possible.
205
  These modifications include:
206
  * Adjusting height to a common ground
207
  * Fixing the root depth of certain models, when depth was extremely jittery
 
208
 
209
  All models use the SMPL body model to discard the influence of the body model on the comparison.
210
  These choices were made without any intention to favor or harm any model.
211
-
212
- The videos were selected to tests models on a large variety of motions, don't hesitate to send me your videos if you want to have it uploaded in the arena!
213
  All matchups are generated randomly, don't hesitate to rate the same videos multiple times as the matchups will probably be different!
214
 
215
  ---
@@ -307,6 +303,7 @@ with gr.Blocks(title='3D Animation Arena', head=head, css_paths='static/style.cs
307
  async def process_rating(state, i, criteria):
308
  return gr.update(value=await submit_rating(
309
  criteria=criteria,
 
310
  winner=state['modelLeft'] if i == 0 else state['modelRight'] if i == 2 else None,
311
  loser=state['modelRight'] if i == 0 else state['modelLeft'] if i == 2 else None,
312
  uuid=state['uuid']
 
196
  - GVHMR (https://github.com/zju3dv/GVHMR)
197
  - HybrIK (https://github.com/jeffffffli/HybrIK)
198
  - WHAM (https://github.com/yohanshin/WHAM)
 
 
 
199
 
200
  All inferences are precomputed following the code in the associated GitHub repository.
201
  Some post-inference modifications have been made to some models in order to make the comparison possible.
202
  These modifications include:
203
  * Adjusting height to a common ground
204
  * Fixing the root depth of certain models, when depth was extremely jittery
205
+ * Fixing the root position of certain models, when no root position was available
206
 
207
  All models use the SMPL body model to discard the influence of the body model on the comparison.
208
  These choices were made without any intention to favor or harm any model.
 
 
209
  All matchups are generated randomly, don't hesitate to rate the same videos multiple times as the matchups will probably be different!
210
 
211
  ---
 
303
  async def process_rating(state, i, criteria):
304
  return gr.update(value=await submit_rating(
305
  criteria=criteria,
306
+ video=state['video'],
307
  winner=state['modelLeft'] if i == 0 else state['modelRight'] if i == 2 else None,
308
  loser=state['modelRight'] if i == 0 else state['modelLeft'] if i == 2 else None,
309
  uuid=state['uuid']
utils.py ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Tuple
2
+ import pandas as pd
3
+ import numpy as np
4
+ import time
5
+ import asyncio
6
+ from utils.s3_utils import write_to_s3
7
+ from utils.data_utils import generate_leaderboard, generate_data
8
+
9
+ submit_lock = asyncio.Lock()
10
+
11
+ def update_ratings(R_win : int, R_lose : int, k : int = 32) -> Tuple[int, int]:
12
+ """
13
+ Update the ratings of two players after a match.
14
+
15
+ Args:
16
+ R_win (int): The rating of the winning player.
17
+ R_lose (int): The rating of the losing player.
18
+ k (int, optional): The k-factor. Defaults to 32.
19
+
20
+ Returns:
21
+ Tuple[int, int]: The updated ratings of the winning and losing players.
22
+ """
23
+ E_win = 1 / (1 + 10 ** ((R_lose - R_win) / 480))
24
+ E_lose = 1 / (1 + 10 ** ((R_win - R_lose) / 480))
25
+ return int(R_win + k * (1 - E_win)), int(R_lose + k * (0 - E_lose))
26
+
27
+ def generate_matchup(leaderboard : pd.DataFrame, beta : int) -> tuple[str, str]:
28
+ """
29
+ Generate a pseudo-random matchup between two models.
30
+
31
+ Args:
32
+ leaderboard (pd.DataFrame): The leaderboard of models
33
+ beta (int): The damping factor for the Elo update.
34
+
35
+ Returns:
36
+ model1 (str): The first model.
37
+ model2 (str): The second model.
38
+ """
39
+ if leaderboard['Matches'].sum() == 0:
40
+ return np.random.choice(leaderboard.index, 2, replace=False)
41
+ weights = [np.exp(-leaderboard.at[model, 'Matches'] / beta) for model in leaderboard.index]
42
+ weights = weights / np.sum(weights) # Normalize weights
43
+ selected = np.random.choice(leaderboard.index, 2, replace=False, p=weights)
44
+ np.random.shuffle(selected)
45
+ model1, model2 = selected
46
+ return model1, model2
47
+
48
+ async def simulate(iter : int, beta : int, criteria : str) -> pd.DataFrame:
49
+ """
50
+ Simulate matches between random models.
51
+
52
+ Args:
53
+ iter (int): The number of matches to simulate.
54
+ beta (int): The damping factor for the Elo update.
55
+ criteria (str): The criteria for the rating.
56
+
57
+ Returns:
58
+ leaderboard (pd.DataFrame): Updated leaderboard after simulation
59
+ """
60
+ data = await generate_data()
61
+
62
+ leaderboard = await generate_leaderboard(criteria)
63
+ leaderboard.set_index('Model', inplace=True)
64
+
65
+ for _ in range(iter):
66
+ # Generate random matchups
67
+ timestamp = time.time()
68
+ model1, model2 = generate_matchup(leaderboard, beta)
69
+ R1, R2 = leaderboard.at[model1, 'Elo'], leaderboard.at[model2, 'Elo']
70
+ R1_new, R2_new = update_ratings(R1, R2)
71
+
72
+ # Update leaderboard
73
+ leaderboard.at[model1, 'Elo'], leaderboard.at[model2, 'Elo'] = R1_new, R2_new
74
+ leaderboard.at[model1, 'Wins'] += 1
75
+ leaderboard.at[model1, 'Matches'] += 1
76
+ leaderboard.at[model2, 'Matches'] += 1
77
+ leaderboard.at[model1, 'Win Rate'] = np.round(leaderboard.at[model1, 'Wins'] / leaderboard.at[model1, 'Matches'], 2)
78
+ leaderboard.at[model2, 'Win Rate'] = np.round(leaderboard.at[model2, 'Wins'] / leaderboard.at[model2, 'Matches'], 2)
79
+
80
+ # Save match data
81
+ data.loc[len(data)] = {
82
+ 'Criteria': criteria,
83
+ 'Model': model1,
84
+ 'Opponent': model2,
85
+ 'Won': True,
86
+ 'Elo': leaderboard.at[model1, 'Elo'],
87
+ 'Win Rate': leaderboard.at[model1, 'Win Rate'],
88
+ 'Matches': leaderboard.at[model1, 'Matches'],
89
+ 'Timestamp': timestamp,
90
+ 'UUID': None
91
+ }
92
+
93
+ data.loc[len(data)] = {
94
+ 'Criteria': criteria,
95
+ 'Model': model2,
96
+ 'Opponent': model1,
97
+ 'Won': False,
98
+ 'Elo': leaderboard.at[model2, 'Elo'],
99
+ 'Win Rate': leaderboard.at[model2, 'Win Rate'],
100
+ 'Matches': leaderboard.at[model2, 'Matches'],
101
+ 'Timestamp': timestamp,
102
+ 'UUID': None
103
+ }
104
+
105
+ leaderboard = leaderboard.sort_values('Elo', ascending=False).reset_index(drop=False)
106
+
107
+ await asyncio.gather(
108
+ write_to_s3(f'leaderboard_{criteria}.csv', leaderboard),
109
+ write_to_s3('data.csv', data)
110
+ )
111
+
112
+ return leaderboard
113
+
114
+
115
+ async def submit_rating(criteria : str, video : str, winner : str, loser : str, uuid : str) -> None:
116
+ """
117
+ Submit a rating for a match.
118
+
119
+ Args:
120
+ criteria (str): The criteria for the rating.
121
+ winner (str): The winning model.
122
+ loser (str): The losing model.
123
+ uuid (str): The UUID of the session.
124
+ """
125
+ async with submit_lock:
126
+ data = await generate_data()
127
+
128
+ leaderboard = await generate_leaderboard(criteria)
129
+ leaderboard.set_index('Model', inplace=True)
130
+
131
+ if winner is None or loser is None or video is None:
132
+ return leaderboard
133
+
134
+ timestamp = time.time()
135
+ R_win, R_lose = leaderboard.at[winner, 'Elo'], leaderboard.at[loser, 'Elo']
136
+ R_win_new, R_lose_new = update_ratings(R_win, R_lose)
137
+
138
+ # Update leaderboard
139
+ leaderboard.loc[[winner, loser], 'Elo'] = [R_win_new, R_lose_new]
140
+ leaderboard.at[winner, 'Wins'] += 1
141
+ leaderboard.loc[[winner, loser], 'Matches'] += [1, 1]
142
+ leaderboard.loc[[winner, loser], 'Win Rate'] = (
143
+ leaderboard.loc[[winner, loser], 'Wins'] / leaderboard.loc[[winner, loser], 'Matches']
144
+ ).apply(lambda x: round(x, 2))
145
+
146
+ # Save match data
147
+ data.loc[len(data)] = {
148
+ 'Criteria': criteria,
149
+ 'Model': winner,
150
+ 'Opponent': loser,
151
+ 'Won': True,
152
+ 'Elo': leaderboard.at[winner, 'Elo'],
153
+ 'Win Rate': leaderboard.at[winner, 'Win Rate'],
154
+ 'Matches': leaderboard.at[winner, 'Matches'],
155
+ 'Video': video,
156
+ 'Timestamp': timestamp,
157
+ 'UUID': uuid
158
+ }
159
+
160
+ data.loc[len(data)] = {
161
+ 'Criteria': criteria,
162
+ 'Model': loser,
163
+ 'Opponent': winner,
164
+ 'Won': False,
165
+ 'Elo': leaderboard.at[loser, 'Elo'],
166
+ 'Win Rate': leaderboard.at[loser, 'Win Rate'],
167
+ 'Matches': leaderboard.at[loser, 'Matches'],
168
+ 'Video': video,
169
+ 'Timestamp': timestamp,
170
+ 'UUID': uuid
171
+ }
172
+
173
+ leaderboard = leaderboard.sort_values('Elo', ascending=False).reset_index(drop=False)
174
+ await asyncio.gather(
175
+ write_to_s3(f'leaderboard_{criteria}.csv', leaderboard),
176
+ write_to_s3('data.csv', data)
177
+ )
178
+ return leaderboard