def create_random_motion(self, length, start_node=None): """ This funtion generate a motion from the given motion graph by randomly traversing the graph. length - length of the generated motion start_node - we can specify a start node if necessary """ motion = velocity.MotionWithVelocity(skel=self.skel) t_processed = 0.0 nodes = list(self.graph.nodes) if start_node is None or start_node not in self.graph.nodes: cur_node = random.choice(nodes) else: cur_node = start_node visited_nodes = [] while t_processed < length: # Record currently visiting node visited_nodes.append(cur_node) # Append the selected motion to the current motion motion_idx = self.graph.nodes[cur_node]["motion_idx"] frame_start = self.graph.nodes[cur_node]["frame_start"] frame_end = self.graph.nodes[cur_node]["frame_end"] # Load the motion if it is not loaded in advance if self.motions[motion_idx] is None: self.load_motion_at_idx(motion_idx, self.motion_files[motion_idx]) """ We should detach with the extra (frames_blend) because motion.append affects the end of current motion """ m = motion_ops.cut( self.motions[motion_idx], frame_start, frame_end + self.frames_blend, ) if self.verbose: logging.info(f"[{cur_node}] {self.graph.nodes[cur_node]}") motion = motion_ops.append_and_blend( motion, m, blend_length=self.blend_length, ) t_processed = motion.length() # Jump to adjacent node (motion) randomly if self.graph.out_degree(cur_node) == 0: if self.verbose: logging.info("Dead-end exists in the graph!") break cur_node = random.choice(list(self.graph.successors(cur_node))) return motion, visited_nodes
def split_into_windows(motion, window_size, stride): """ Split motion object into list of motions with length window_size with the given stride. """ n_windows = (motion.num_frames() - window_size) // stride + 1 motion_ws = [ motion_ops.cut(motion, start, start + window_size) for start in stride * np.arange(n_windows) ] return motion_ws
def split_bvh(filepath, time_window, output_folder): motion = bvh.load(filepath) frames_per_time_window = time_window * motion.fps for num, i in enumerate( range(0, motion.num_frames(), int(frames_per_time_window / 2))): motion_slice = motion_ops.cut(motion, i, i + frames_per_time_window) filepath_slice = os.path.join( output_folder, filepath.split(".")[-2].split("/")[-1] + "_" + str(num) + ".bvh", ) bvh.save(motion_slice, filepath_slice)
def motionify(self, nodes): """ Turn a list of nodes into motion. """ motion = velocity.MotionWithVelocity(skel=self.skel, fps=self.fps) t_processed = 0.0 cur_node = nodes[0] for motion_idx in nodes[1:]: # Append the selected motion to the current motion motion_idx = self.graph.nodes[cur_node]["motion_idx"] frame_start = self.graph.nodes[cur_node]["frame_start"] frame_end = self.graph.nodes[cur_node]["frame_end"] # Load the motion if it is not loaded in advance if self.motions[motion_idx] is None: self.load_motion_at_idx(motion_idx, self.motion_files[motion_idx]) """ We should detach with the extra (frames_blend) because motion.append affects the end of current motion """ m = motion_ops.cut( self.motions[motion_idx], frame_start, frame_end + self.frames_blend, ) if self.verbose: logging.info(f"[{cur_node}] {self.graph.nodes[cur_node]}") # motion = motion_ops.append( # motion, m # ) motion = motion_ops.append_and_blend( motion, m, blend_length=self.blend_length, ) return motion
def test_cut_motion(self): motion = bvh.load(file="tests/data/sinusoidal.bvh") # Inspect 0th frame, root joint cut_motion = motion_ops.cut(motion, 3, 5) self.assertEqual(cut_motion.num_frames(), 2)