1
+ import codecs as cs
2
+ import nimblephysics as nimble
3
+ import numpy as np
1
4
import os
5
+ import random
2
6
import torch
3
- from torch .utils import data
4
- import numpy as np
7
+ from glob import glob
5
8
from os .path import join as pjoin
6
- import random
7
- import codecs as cs
9
+ from torch .utils import data
8
10
from tqdm import tqdm
9
- from glob import glob
10
-
11
11
12
12
class VQMotionDataset (data .Dataset ):
13
13
def __init__ (self , dataset_name , window_size = 64 , unit_length = 4 , mode = 'train' , mode2 = 'embeddings' , data_dirs = ['/home/ubuntu/data/MCS_DATA' , '/media/shubh/Elements/RoseYu/UCSD-OpenCap-Fitness-Dataset/MCS_DATA' ]):
@@ -204,6 +204,108 @@ def __getitem__(self, item):
204
204
205
205
return subsequences , subsequence_lengths , names
206
206
207
+ class AddBiomechanicsDataset (data .Dataset ):
208
+ def __init__ (self , window_size = 64 , unit_length = 4 , mode = 'train' , data_dir = '/home/mnt/data/addb_dataset_publication' ):
209
+ self .window_size = window_size
210
+ self .unit_length = unit_length
211
+ self .data_dir = data_dir
212
+ self .mode = mode
213
+
214
+ # Define subdirectories for each paper
215
+ paper_dirs = [
216
+ "train/No_Arm/Falisse2016_Formatted_No_Arm" ,
217
+ "train/No_Arm/Uhlrich2023_Opencap_Formatted_No_Arm" ,
218
+ "train/No_Arm/Wang2023_Formatted_No_Arm" ,
219
+ "train/No_Arm/Han2023_Formatted_No_Arm" ,
220
+ ]
221
+
222
+ # Collect all .b3d files from the specified subdirectories
223
+ self .b3d_file_paths = []
224
+ for paper_dir in paper_dirs :
225
+ search_path = os .path .join (data_dir , paper_dir , '**' , '*.b3d' )
226
+ files = glob (search_path , recursive = True )
227
+ self .b3d_file_paths .extend (files )
228
+
229
+ self .motion_data = []
230
+ self .motion_lengths = []
231
+ self .motion_names = []
232
+ self .motion_fps = []
233
+
234
+ for b3d_file in tqdm (self .b3d_file_paths ):
235
+ try :
236
+ if os .path .getsize (b3d_file ) == 0 :
237
+ continue
238
+ subject = nimble .biomechanics .SubjectOnDisk (b3d_file )
239
+ num_trials = subject .getNumTrials ()
240
+ for trial in range (num_trials ):
241
+ trial_length = subject .getTrialLength (trial )
242
+ if trial_length < self .window_size :
243
+ continue
244
+ frames = subject .readFrames (
245
+ trial = trial ,
246
+ startFrame = 0 ,
247
+ numFramesToRead = trial_length ,
248
+ includeSensorData = False ,
249
+ includeProcessingPasses = True
250
+ )
251
+ if not frames :
252
+ continue
253
+ kin_passes = [frame .processingPasses [0 ] for frame in frames ]
254
+ positions = np .array ([kp .pos for kp in kin_passes ]) # shape: (frames, dofs)
255
+ # Get FPS for this trial
256
+ seconds_per_frame = subject .getTrialTimestep (trial )
257
+ fps = int (round (1.0 / seconds_per_frame )) if seconds_per_frame > 0 else 0
258
+
259
+ # Downsample here, at load time
260
+ if fps == 100 :
261
+ positions = positions [::2 ] # Take every 2nd frame
262
+ elif fps == 250 :
263
+ positions = positions [::5 ] # Take every 5th frame
264
+
265
+ # After downsampling, skip if too short
266
+ if len (positions ) < self .window_size :
267
+ continue
268
+
269
+ self .motion_data .append (positions )
270
+ self .motion_lengths .append (len (positions ))
271
+ self .motion_names .append (f"{ b3d_file } ::trial{ trial } " )
272
+ self .motion_fps .append (fps )
273
+ except Exception as e :
274
+ print (f"Skipping file { b3d_file } due to error: { e } " )
275
+
276
+ print ("Total number of motions:" , len (self .motion_data ))
277
+ print ("Example motion shape:" , self .motion_data [0 ].shape if self .motion_data else "None" )
278
+
279
+ def __len__ (self ):
280
+ return len (self .motion_data )
281
+
282
+ def __getitem__ (self , item ):
283
+ motion = self .motion_data [item ]
284
+ len_motion = len (motion ) if len (motion ) <= self .window_size else self .window_size
285
+ name = self .motion_names [item ]
286
+
287
+ # Crop or pad to window_size (no downsampling here)
288
+ if len (motion ) >= self .window_size :
289
+ idx = random .randint (0 , len (motion ) - self .window_size )
290
+ motion = motion [idx :idx + self .window_size ]
291
+ else :
292
+ repeat_count = (self .window_size + len (motion ) - 1 ) // len (motion )
293
+ motion = np .tile (motion , (repeat_count , 1 ))[:self .window_size ]
294
+
295
+ return motion , len_motion , name
296
+
297
+
298
+ def addb_data_loader (window_size = 64 , unit_length = 4 , batch_size = 1 , num_workers = 4 , mode = 'train' ):
299
+ dataset = AddBiomechanicsDataset (window_size = window_size , unit_length = unit_length , mode = mode )
300
+ loader = torch .utils .data .DataLoader (
301
+ dataset ,
302
+ batch_size = batch_size ,
303
+ shuffle = True ,
304
+ num_workers = num_workers ,
305
+ drop_last = True
306
+ )
307
+ return loader
308
+
207
309
def DATALoader (dataset_name ,
208
310
batch_size ,
209
311
num_workers = 4 ,
@@ -231,4 +333,4 @@ def cycle(iterable):
231
333
232
334
233
335
if __name__ == "__main__" :
234
- dataloader = DATALoader ( 'mcs' , 1 , window_size = 64 ,unit_length = 2 ** 2 , mode = 'limo ' )
336
+ dataloader = addb_data_loader ( window_size = 64 , unit_length = 4 , batch_size = 1 , mode = 'train ' )
0 commit comments