def save_seq(i, pred_seq, src_seq, tgt_seq, skel): # seq_T contains pred, src, tgt data in the same order motions = [ motion_class.Motion.from_matrix(seq, skel) for seq in [pred_seq, src_seq, tgt_seq] ] ref_motion = motion_ops.append(motions[1], motions[2]) pred_motion = motion_ops.append(motions[1], motions[0]) bvh.save( ref_motion, os.path.join(args.save_output_path, "ref", f"{i}.bvh"), ) bvh.save( pred_motion, os.path.join(args.save_output_path, "pred", f"{i}.bvh"), )
def test_append_motion(self): motion1 = bvh.load(file="tests/data/sinusoidal.bvh") motion2 = bvh.load(file="tests/data/sinusoidal.bvh") num_frames = motion1.num_frames() # Append motion 1 and motion 2, and check total combined frames combined_motion1 = motion_ops.append(motion1, motion2) self.assertEqual( combined_motion1.num_frames(), motion1.num_frames() + motion2.num_frames(), ) # Append motion 1 and motion 3, and check total combined frames motion3 = bvh.load(file="tests/data/sinusoidal.bvh") combined_motion2 = motion_ops.append(motion1, motion3) self.assertEqual( combined_motion2.num_frames(), motion1.num_frames() + motion3.num_frames(), ) # Ensure operation has not been done in place self.assertEqual( motion1.num_frames(), num_frames, ) # Test blending blend_length = 0.1 combined_motion3 = motion_ops.append_and_blend( motion1, motion2, blend_length=blend_length, ) self.assertEqual( combined_motion3.num_frames(), (motion1.num_frames() + motion2.num_frames() - blend_length * motion1.fps), )
def create_random_motion(self, length, start_node=None, new=True, blend=True): """ 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 """ # random.seed(10) motion = velocity.MotionWithVelocity(skel=self.skel, fps=self.fps) 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 = nodes[start_node] visited_nodes = [] if blend: 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]}") # ipdb.set_trace() if blend: motion = motion_ops.append_and_blend( motion, m, blend_length=self.blend_length, ) else: motion = motion_ops.append(motion, m) 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 successors = list(self.graph.successors(cur_node)) cur_node = random.choice(successors) if new: for successor in successors: if (self.graph.nodes[successor]["motion_idx"] != motion_idx + 1 and self.graph.nodes[successor]["frame_start"] != frame_end): cur_node = successor break return motion, visited_nodes