def test_channels(self): with open('tests/test_mocapbank.bvh') as f: mocap = Bvh(f.read()) self.assertEqual(mocap.joint_channels('LeftElbow'), ['Zrotation', 'Xrotation', 'Yrotation']) self.assertEqual(mocap.joint_channels('Hips'), ['Xposition', 'Yposition', 'Zposition', 'Zrotation', 'Xrotation', 'Yrotation'] )
def load_from_bvh(self, fname, exclude_bones=None, spec_channels=None): if exclude_bones is None: exclude_bones = {} if spec_channels is None: spec_channels = dict() with open(fname) as f: mocap = Bvh(f.read()) joint_names = list( filter(lambda x: all([t not in x for t in exclude_bones]), mocap.get_joints_names())) dof_ind = {'x': 0, 'y': 1, 'z': 2} self.len_scale = 0.0254 self.root = Bone() self.root.id = 0 self.root.name = joint_names[0] self.root.channels = mocap.joint_channels(self.root.name) self.name2bone[self.root.name] = self.root self.bones.append(self.root) for i, joint in enumerate(joint_names[1:]): bone = Bone() bone.id = i + 1 bone.name = joint bone.channels = spec_channels[joint] if joint in spec_channels.keys( ) else mocap.joint_channels(joint) bone.dof_index = [dof_ind[x[0].lower()] for x in bone.channels] bone.offset = np.array(mocap.joint_offset(joint)) * self.len_scale bone.lb = [-180.0] * 3 bone.ub = [180.0] * 3 self.bones.append(bone) self.name2bone[joint] = bone for bone in self.bones[1:]: parent_name = mocap.joint_parent(bone.name).name if parent_name in self.name2bone.keys(): bone_p = self.name2bone[parent_name] bone_p.child.append(bone) bone.parent = bone_p self.forward_bvh(self.root) for bone in self.bones: if len(bone.child) == 0: bone.end = bone.pos + np.array([ float(x) for x in mocap.get_joint(bone.name).children[-1]['OFFSET'] ]) * self.len_scale else: bone.end = sum([bone_c.pos for bone_c in bone.child]) / len(bone.child)
class bvhModel(): def __init__( self ): self.Skeleton = [] self.mocapdata = None self.FileName = "" def Load( self, pathname, filename ): self.PathName = pathname self.FileName = filename tempFile = pathname + filename print(tempFile) with open( tempFile ) as f: self.mocapdata = Bvh( f.read() ) self.Skeleton = self.GetSkeleton() return tempFile def GetLength( self ): if self.mocapdata: return self.mocapdata.nframes return 0 def GetSkeleton( self ): self.Skeleton = [] def iterate_joints( joint ): self.Skeleton.append( str( joint )) for child in joint.filter( 'JOINT' ): iterate_joints( child ) iterate_joints( next( self.mocapdata.root.filter( 'ROOT' ))) return self.Skeleton def GetData( self ): return self.mocapdata def AsInputData( self, strType, globalGaugeRef, labelRef, gaugeRef ): ''' This seems to convert a bvh to the corresponding CSV in rogerio's paper, which can be used as input to his classifier. ''' data = [] nFrames = self.GetLength() pos = self.FileName.rfind( "\\" ) + 1 outputFile = "data_" + strType.lower() + "\\" + self.FileName[pos:-3] + "csv" #If an output file is not provided, process the bvh to get corresponding csv input data. #otherwise, load a previous version of the file that has been created and return if not os.path.isfile( outputFile ): gaugeRef.SetValue( 0 ) gaugeOffset = 0 if strType.lower() != "standardized": labelRef.SetLabel( "Analizing: " + self.FileName ) gaugeRef.SetRange( 2 * nFrames ) gaugeOffset = nFrames print( "File: " + self.FileName + " ... analyzing", end = ' ' ) # analyzing data to determine its minimum and maximum values minimumR = minimumP = [99999, 99999, 99999] maximumR = maximumP = [-99999, -99999, -99999] origin = [0,0,0] for frame in range( 1, nFrames ): globalGaugeRef.SetValue( globalGaugeRef.GetValue() + 1 ) for joint in self.Skeleton: jointName = joint.split(" ")[1] i = 0 for channel in self.mocapdata.joint_channels( jointName ): channelValue = self.mocapdata.frame_joint_channel( frame, jointName, channel ) if channel[1:] != "position": if minimumR[i] > channelValue: minimumR[i] = channelValue if maximumR[i] < channelValue: maximumR[i] = channelValue else: if frame == 1: origin[i] = channelValue if minimumP[i] > channelValue: minimumP[i] = channelValue if maximumP[i] < channelValue: maximumP[i] = channelValue i = (i+1) % 3 gaugeRef.SetValue( frame + 1 ) labelRef.SetLabel( "Normalizing: " + self.FileName ) print( "normalizing" ) else: gaugeRef.SetRange( nFrames ) labelRef.SetLabel( "Loading: " + self.FileName ) print( "File: " + self.FileName + " ... loading" ) header = "" structure = "" for frame in range( 1, nFrames ): globalGaugeRef.SetValue( globalGaugeRef.GetValue() + 1 ) frameData = [] for joint in self.Skeleton: jointName = joint.split(" ")[1] i = 0 for channel in self.mocapdata.joint_channels( jointName ): if frame == 1: if header == "": header = jointName + "_" + channel else: header += "," + jointName + "_" + channel structure += jointName + "_" + channel + "\n" channelValue = self.mocapdata.frame_joint_channel( frame, jointName, channel ) if channel[1:] != "position": if strType.lower() == "normalized": channelValue = ( channelValue - minimumR[i] ) / ( maximumR[i] - minimumR[i] ) elif strType.lower() == "rescaled": channelValue = 2 * (( channelValue - minimumR[i] ) / ( maximumR[i] - minimumR[i] )) - 1 else: if strType.lower() != "standardized": channelValue -= origin[i] if strType.lower() == "normalized": if i == 1: channelValue = ( channelValue - minimumP[i] ) / ( maximumP[i] - minimumP[i] ) else: channelValue = 0 elif strType.lower() == "rescaled": channelValue = 2 * (( channelValue - minimumP[i] ) / ( maximumP[i] - minimumP[i] )) - 1 frameData.append( channelValue ) i = (i+1) % 3 data.append( frameData ) gaugeRef.SetValue( frame + gaugeOffset + 1 ) self.SaveAsCSV( data, header, outputFile ) fileNode = open( "structure.txt","w" ) fileNode.write( structure ) fileNode.close() else: labelRef.SetLabel( "Loading previous version of file: " + self.FileName ) print( "Loading previous version of file: " + self.FileName ) gaugeRef.SetRange( 1 ) gaugeRef.SetValue( 1 ) globalGaugeRef.SetValue( globalGaugeRef.GetValue() + nFrames * 2 ) data = np.array( read_csv( outputFile ) ).tolist() #data = np.array( read_csv( outputFile, header = None ) ).tolist() return np.array( data ) def SaveAsCSV( self, data, header, outputFile ): fileNode = open( outputFile,"w" ) fileNode.write( header + "\n" ) for entry in data: entryStr = "" for value in entry: if entryStr != "": entryStr += "," entryStr += str( value ) fileNode.write( entryStr + "\n" ) fileNode.close()
with open('../Data/BVH/Vasso_Miserable_0.bvh') as data: mocap = Bvh(data.read()) #Get Mocap Tree tree = [str(item) for item in mocap.root] #['HIERARCHY', 'ROOT Hips', 'MOTION', 'Frames: 1068', 'Frame Time: 0.0333333'] #Get ROOT OFFSET root = next(mocap.root.filter('ROOT'))['OFFSET'] #['3.93885', '96.9818', '-23.2913'] #Get all JOINT names joints = mocap.get_joints_names() #54 mocap.get_joints_names()[17] #All Names mocap.joint_offset('Head') #Offset mocap.joint_channels('Neck') #Channels mocap.get_joint_channels_index('Spine') # mocap.joint_parent_index('Neck') #Parent Index mocap.joint_parent('Head').name # Parent Name #mocap.joint_direct_children('Hips') #Direct Children #Get Frames mocap.nframes mocap.frame_time mocap.frame_joint_channel(22, 'Spine', 'Xrotation') #SEARCH [str(node) for node in mocap.search('JOINT', 'LeftShoulder')] #Single Item [str(node) for node in mocap.search('JOINT')] #All Items
from bvh import Bvh with open('Male2_A1_Stand.bvh') as f: mocap = Bvh(f.read()) for name in mocap.get_joints_names(): print(name + " : ", mocap.frame_joint_channels(0, name, mocap.joint_channels(name)))