{"id":1700,"date":"2022-08-15T13:54:10","date_gmt":"2022-08-15T12:54:10","guid":{"rendered":"https:\/\/wp.coventry.domains\/e2edu\/?page_id=1700"},"modified":"2022-08-24T14:34:56","modified_gmt":"2022-08-24T13:34:56","slug":"utility-classes-and-functions","status":"publish","type":"page","link":"https:\/\/wp.coventry.domains\/e2edu\/utility-classes-and-functions\/","title":{"rendered":"Utility Classes and Functions"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">The Python module &#8220;common&#8221; contains a variety of submodules that provide utility classes and functions. The module is part of a series of tutorials on using PyTorch to create and train generative deep learning models. The code for these tutorials is available <a rel=\"noreferrer noopener\" href=\"https:\/\/github.coventry.ac.uk\/ad5041\/PyTorch_ML_Tutorials\" target=\"_blank\">here<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">common.quaternion<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This module provides functions for performing calculations on quaternions that are either stored in tensors or as numpy arrays. This module has been adapted from an original implementation by the authors of the <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/facebookresearch\/QuaterNet\" target=\"_blank\">Quaternet model<\/a>.  <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The following functions operate on quaternions stored in tensors.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def qmul(q, r) # multiply quaternion(s) q with quaternion(s) r\n\ndef qrot(q, v) # rotate vector(s) v about the rotation described by quaternion(s) q\n\ndef qeuler(q, order, epsilon=0) # Convert quaternion(s) q to Euler angles\n\ndef slerp(q0, q1, amount=0.5) # perform quaternion slerp between quaternion q0 and quaternion q1. Multiple quaternions are not supported.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The following functions operate on quaternions stored in numpy arrays.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def qnormalize_np(q) # normalise a quaternion\n\ndef qmul_np(q, r) # multiply quaternion(s) q with quaternion(s) r\n\ndef qrot_np(q, v) # rotate vector(s) v about the rotation described by quaternion(s) q\n\ndef qeuler_np(q, order, epsilon=0, use_gpu=False) # Convert quaternion(s) q to Euler angles\n\ndef qfix(q): # Enforce quaternion continuity\n\ndef expmap_to_quaternion(e) # Convert axis-angle rotations (aka exponential maps) to quaternions.\n\ndef euler_to_quaternion(e, order) # Convert Euler angles to quaternions.<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">common.utils<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This module provides functions to save a history of training losses as CSV file or as graphical plot and to perform simple computations on motion capture data. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The most frequently used functions in the common.utils submodule are:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def save_loss_as_csv(loss_history, csv_file_name) # export a training loss history as CSV file\n\ndef save_loss_as_image(loss_history, image_file_name) # export a training loss history as graphical plot.\n\ndef get_skeleton_edge_list(skeleton) # compute a list of edges connecting skeleton joints.\n\ndef get_equal_mix_max_positions(poses): # compute minimum and maximum positions from a sequence of motion capture poses.<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">common.skeleton<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The Skeleton class holds information about a hierarchy of joints and  positional joint offsets. An instance of the class is created by passing the positional joint offsets and a list of parent joints as arguments. Instantiation usually happens automatically when loading motion capture data from a file using the MocapDataset class. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The main use of the Skeleton class is to compute forward kinematics based on the position of a root joint and the relative rotations of all the joints. The corresponding function is named &#8220;forward_kinematics&#8221; and takes two arguments: a sequence of poses in which poses are represented as relative joint rotations (quaternions), and a sequence of positions for the root joint. Both of these arguments are provided as tensors. The first tensor has the shape: batch_size x sequence_length x joint_count x 4. The second tensor has the shape: batch_size  x sequence_length x 3. The function returns a tensor of the shape: batch_size x sequence_length x joint_count x 3.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The full list of function declarations in the Skeleton class is as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def __init__(self, offsets, parents) # constructor\n\ndef num_joints(self) # returns numbers of skeleton joints\n\ndef offsets(self) # returns list of joint position offsets\n\ndef parents(self) # returns list of parent joint indices\n\ndef has_children(self) # returns list of flags specifying for each joint if it has children joints or not\n\ndef children(self) # returns list of child joint indices\n\ndef remove_joints(self, joints_to_remove, dataset) # remove joints from a motion capture dataset\n\ndef forward_kinematics(self, rotations, root_positions) # compute forward kinematics<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">common.mocap_dataset<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This submodule defines the MocapDataset class. This class operates on motion capture data that is imported from a file containing a pickled dictionary. More information about this dictionary is available <a rel=\"noreferrer noopener\" href=\"https:\/\/wp.coventry.domains\/e2edu\/motion-capture-data\/\" target=\"_blank\">here<\/a>. The class is instantiated by passing a file path and a framerate (motion capture frames per second) as arguments.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from common.mocap_dataset import MocapDataset\n\nmocap_data_path = \"..\/..\/data\/Mocap\/MUR_Nov_2021\/MUR_Fluidity_Body_Take1_mb_proc_rh.p\"\nmocap_fps = 50\n\nmocap_data = MocapDataset(mocap_data_path, fps=mocap_fps)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once motion capture data has been loaded, it is stored in the MocapDataset class instance alongside an instance of the Skeleton class. The storage format of the motion capture data follows the structure of the <a rel=\"noreferrer noopener\" href=\"http:\/\/humaneva.is.tue.mpg.de\/\" target=\"_blank\">HumanEva dataset<\/a>. Accordingly, motion capture data is hierarchically organised on two  levels. The top level represents the subjects from which motion capture was recorded. The second level represents the actions a subject was performing while being recorded. The MocapDataset  class provides functions to obtain a list of subject names and action names. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>subjects = mocap_data.subjects()\nactions = mocap_data.all_actions()\nactions_of_subject = mocap_data.subject_actions(subjects&#091;0])<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In the tutorial examples, the motion capture recordings contain only one subject named &#8220;S1&#8221; and one action for this subject named &#8220;A1&#8221;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If the motion capture data is used for machine learning and the machine learning model runs on the GPU, then the MotionCapture class has to be told to move its data to the GPU. This is done by calling the function &#8220;cuda&#8221; without any arguments.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The MocapDataset  provides a function named  &#8220;compute_positions&#8221; for calculating absolute positions of joints from relative positions. This function takes no arguments.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mocap_data.compute_positions()<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The MocapDataset  owns an instance of the Skeleton class. This instance is defined once the MocapDataset  class has been initiated by importing a motion capture file. The Skeleton instance can be obtained by using the &#8220;skeleton&#8221; function.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>skeleton = mocap_data.skeleton()<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The full list of function declarations in the MocapDataset class is as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def __init__(self, path, fps) # constructor\n\ndef cuda(self) # move internal tensors to the GPU\n\ndef downsample(self, factor, keep_strides=True) # downsample the motion capture data to a lower frame rate.\n\ndef compute_euler_angles(self, order) # calculate joint rotations in Euler angles from rotations represented by quaternions. \n\ndef compute_positions(self): # calculate absolute joint positions from relative joint positions\n\ndef compute_standardized_values(self, value_key) # compute standardised values for the specified motion capture data.\n\ndef subjects(self): return the list of subjects from which motion capture data was recorded\n\ndef subject_actions(self, subject): return the list of recorded actions of a motion capture subject.\n\ndef all_actions(self): return a concatenated list of recorded actions of all motion capture subjects.\n\ndef fps(self): return the motion capture frame rate\n\ndef skeleton(self): return an instance of the Skeleton class created from the motion capture data.<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">common.pose_renderer<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The pose_renderer module provides the PoseRenderer class which can be used to create simple skeleton animations from motion capture data. The PoseRenderer  is instantiated by passing joint connectivity information of a skeleton as argument. This information can be obtained using the &#8220;get_skeleton_edge_list&#8221; function of the common.utils module.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The PoseRenderer class provides two functions for creating either single images or multiple images from motion capture poses. These images show a simple graphical depiction of a skeleton. Both functions take as arguments either a single pose or a list of poses, the minimum and maximum range of joint positions, camera angles as elevation and azimuth, the line width with which edges of the skeleton are drawn, and the width and height of the created image in inches. The PoseRenderer also provides a simple convenience function to arrange multiple images into a grid layout.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def create_pose_image(self, pose, axis_min, axis_max, rot_elev, rot_azi, line_width, image_xinch, image_yinch) # create a single image containing graphical depiction of a single pose.\n\ndef create_pose_images(self, poses, axis_min, axis_max, rot_elev, rot_azi, line_width, image_xinch, image_yinch) # create a list of images, one for each pose. \n\ndef create_grid_image(self, images, grid) # arrange a list of images in a grid layout<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>The Python module &#8220;common&#8221; contains a variety of submodules that provide utility classes and functions. The module is part of a series of tutorials on using PyTorch to create and train generative deep learning models. The code for these tutorials is available here. common.quaternion This module provides functions for performing calculations on quaternions that are [&hellip;]<\/p>\n","protected":false},"author":2154,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","footnotes":""},"class_list":["post-1700","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/wp.coventry.domains\/e2edu\/wp-json\/wp\/v2\/pages\/1700","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wp.coventry.domains\/e2edu\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/wp.coventry.domains\/e2edu\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/wp.coventry.domains\/e2edu\/wp-json\/wp\/v2\/users\/2154"}],"replies":[{"embeddable":true,"href":"https:\/\/wp.coventry.domains\/e2edu\/wp-json\/wp\/v2\/comments?post=1700"}],"version-history":[{"count":41,"href":"https:\/\/wp.coventry.domains\/e2edu\/wp-json\/wp\/v2\/pages\/1700\/revisions"}],"predecessor-version":[{"id":3180,"href":"https:\/\/wp.coventry.domains\/e2edu\/wp-json\/wp\/v2\/pages\/1700\/revisions\/3180"}],"wp:attachment":[{"href":"https:\/\/wp.coventry.domains\/e2edu\/wp-json\/wp\/v2\/media?parent=1700"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}