<filename>npms/interpolate_shapes.py
import sys,os

from numpy.core.fromnumeric import shape
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

import os
import trimesh
import numpy as np
import json
import open3d as o3d
import torch
from tqdm import tqdm
from timeit import default_timer as timer
import utils.deepsdf_utils as deepsdf_utils 
import matplotlib.pyplot as plt

from models.pose_decoder import PoseDecoder, PoseDecoderSE3
from models.shape_decoder import ShapeDecoder

from utils.pcd_utils import (BBox,
                            trimesh_to_open3d,
                            transform_pointcloud_to_opengl_coords,
                            rotate_around_axis,
                            origin, normalize_transformation)

import utils.nnutils as nnutils
import config as cfg
import data_scripts.config_data as cfg_data


class ViewerInterpolateShape:
    def __init__(
        self, 
        labels,
        labels_tpose,
        shape_codes,
        out_root_dir,
        num_to_eval=-1,
        view="lateral_left",
        dataset_class=None,
        src_identity_name=None,
        tgt_identity_name=None,
        num_iterpolations=10,
        use_gt_tpose_mesh=False,
        render_video_options="/rhome/ppalafox/workspace/render_video_options",
        frame_rate=30,
        res_mult=1,
    ):
        self.frame_rate = frame_rate

        mult = res_mult
        self.reconstruction_res = 256 * mult
        self.max_batch = (mult * 32)**3

        self.labels = labels
        self.labels_tpose = labels_tpose
        self.num_to_eval = num_to_eval
        
        self.src_identity_name = src_identity_name
        self.tgt_identity_name = tgt_identity_name

        # Find the identity's id
        self.src_identity_id, self.tgt_identity_id = None, None
        for identity_id, label_tpose in enumerate(self.labels_tpose):
            if label_tpose['identity_name'] == self.src_identity_name:
                self.src_identity_id = identity_id
            if label_tpose['identity_name'] == self.tgt_identity_name:
                self.tgt_identity_id = identity_id

        assert self.src_identity_id is not None and self.tgt_identity_id is not None

        self.num_iterpolations = num_iterpolations

        self.shape_codes = shape_codes

        self.dataset_class = dataset_class

        self.START_COLOR = np.array([0.4, 0.6, 0.4])
        self.END_COLOR   = np.array([0.6, 0.4, 0.4])

        self.time = 0
        self.ref = None

        self.use_gt_tpose_mesh = use_gt_tpose_mesh

        # Recording options
        self.view = view
        self.render_json            = os.path.join(render_video_options, "render_options.json")
        self.viewpoint_json         = os.path.join(render_video_options, "viewpoint.json")
        self.viewpoint_lateral_json = os.path.join(render_video_options, "viewpoint_lateral.json")
        self.viewpoint_lateral_left_json = os.path.join(render_video_options, "viewpoint_lateral_left.json")
        os.makedirs(render_video_options, exist_ok=True)
        self.out_dir = os.path.join(out_root_dir, f"{self.src_identity_name}__TO__{self.tgt_identity_name}__@{self.reconstruction_res}__fps{self.frame_rate}")
        os.makedirs(self.out_dir, exist_ok=True)

        self.initialize()


    def initialize(self):

        self.ref_list = []

        self.loaded_frames = 0

        ################################################################################################################
        # Prepare the start and end pose codes
        ################################################################################################################
        shape_code_start = self.shape_codes[[self.src_identity_id], ...] # [bs, 1, C]
        shape_code_end   = self.shape_codes[[self.tgt_identity_id], ...] # [bs, 1, C]

        ################################################################################################################
        ################################################################################################################
        # Go over the different poses
        ################################################################################################################
        ################################################################################################################
        
        for i in tqdm(range(self.num_iterpolations + 1)):

            alpha = i / self.num_iterpolations

            with torch.no_grad():
                ### Prepare INTERPOLATED shape code ###
                shape_code_interp = (1 - alpha) * shape_code_start + alpha * shape_code_end
                assert shape_code_interp.shape == (1, 1, shape_codes_dim), f"{shape_code_interp} vs {(1, 1, shape_codes_dim)}"
                ref_mesh = deepsdf_utils.create_mesh_from_code(
                    shape_decoder, shape_code_interp, shape_codes_dim=shape_codes_dim,
                    N=self.reconstruction_res, max_batch=self.max_batch
                )

            COLOR_INTERP = (1 - alpha) * self.START_COLOR + alpha * self.END_COLOR
            ref_mesh = trimesh_to_open3d(ref_mesh, COLOR_INTERP)

            # o3d.visualization.draw_geometries([ref_mesh])
            
            self.ref_list.append(ref_mesh)

            # Increase counter of evaluated frames
            self.loaded_frames += 1

            print(f'Loaded {self.loaded_frames} frames')

            if self.loaded_frames == self.num_to_eval:
                print()
                print(f"Stopping early. Already loaded {self.loaded_frames}")
                print()
                break

            # break

        # ###############################################################################################
        # # Generate additional meshes.
        # ###############################################################################################
        # unit bbox
        p_min = -0.5
        p_max =  0.5
        self.unit_bbox = BBox.compute_bbox_from_min_point_and_max_point(
            np.array([p_min]*3), np.array([p_max]*3), color=[0.7, 0.7, 0.7]
        )

        # world frame
        self.world_frame = o3d.geometry.TriangleMesh.create_coordinate_frame(
            size=0.00001, origin=[0, 0, 0]
        )

    def update_ref(self, vis):
        param = vis.get_view_control().convert_to_pinhole_camera_parameters()

        if self.ref is not None:
            vis.remove_geometry(self.ref)
        
        self.ref = self.ref_list[self.time]
        vis.add_geometry(self.ref)

        ctr = vis.get_view_control()
        ctr.convert_from_pinhole_camera_parameters(param)

    def _load_render_and_viewpoint_option(self, vis, view):
        vis.get_render_option().load_from_json(self.render_json)
        
        # change viewpoint
        ctr = vis.get_view_control()
        if view == "frontal":
            param = o3d.io.read_pinhole_camera_parameters(self.viewpoint_json)
        elif view == "lateral":
            param = o3d.io.read_pinhole_camera_parameters(self.viewpoint_lateral_json)
        elif view == "lateral_left":
            param = o3d.io.read_pinhole_camera_parameters(self.viewpoint_lateral_left_json)
        else:
            exit()
        ctr.convert_from_pinhole_camera_parameters(param)

    def render_image(self, vis, out_filename):
        image_np = np.asarray(vis.capture_screen_float_buffer(False))
        h, w, _ = image_np.shape
        new_h, new_w = 1200, 1600
        image_np = image_np[(h-new_h)//2:(h+new_h)//2, (w-new_w)//2:(w+new_w)//2,:]
        plt.imsave(f"{self.out_dir}/{out_filename}.jpg", image_np)
        
    def run(self):

        def update_all(vis):
            self.update_ref(vis)
            return False

        # Define callbacks.
        def toggle_next(vis):
            self.time += 1
            if self.time >= self.loaded_frames:
                self.time = 0
            update_all(vis)
            return False
        
        def toggle_previous(vis):
            self.time -= 1
            if self.time < 0:
                self.time = self.loaded_frames - 1
            update_all(vis)
            return False

        def render(vis):
            print("::render")

            self._load_render_and_viewpoint_option(vis, self.view)

            ##################################################
            # Render the interpolated poses
            ##################################################
            self.time = 0
            self.show_ref = True 
            self.ref = self.ref_list[self.time]
            update_all(vis)
            vis.poll_events()
            vis.update_renderer()
            
            for i in range(len(self.ref_list)):
                # Render
                self.render_image(vis, f"interp_{str(i).zfill(2)}")
                toggle_next(vis)
                vis.poll_events()
                vis.update_renderer()
            self.show_src_refw = False 

            os.system(f"ffmpeg -r {self.frame_rate} -i {self.out_dir}/interp_%02d.jpg -c:v libx264 -vf fps=30 -pix_fmt yuv420p -y {self.out_dir}/{self.src_identity_name}__TO__{self.tgt_identity_name}__@{self.reconstruction_res}.mp4")
            exit() 

            return False

        def save_viewpoint_lateral_left(vis):
            print("::save_viewpoint")
            param = vis.get_view_control().convert_to_pinhole_camera_parameters()
            o3d.io.write_pinhole_camera_parameters(self.viewpoint_lateral_left_json, param)
            return False

        key_to_callback = {}
        key_to_callback[ord("D")] = toggle_next
        key_to_callback[ord("A")] = toggle_previous
        key_to_callback[ord("R")] = render
        key_to_callback[ord("'")] = save_viewpoint_lateral_left

        # Add mesh at initial time step.
        assert self.time < self.loaded_frames

        print("Showing time", self.time)

        # Start showing the tgt tpose
        self.ref = self.ref_list[self.time]

        o3d.visualization.draw_geometries_with_key_callbacks([self.world_frame, self.ref], key_to_callback)


################################################################################################################################
################################################################################################################################


if __name__ == "__main__":

    torch.backends.cudnn.benchmark = True

    ########################################################################################################################
    # Options
    ########################################################################################################################
    # import argparse
    # parser = argparse.ArgumentParser(
    #     description='Run Model'
    # )
    # parser.add_argument('-o', '--optimize_codes', action='store_true')
    # parser.add_argument('-e', '--extra_name', default="")
    # parser.add_argument('-v', '--viz', action='store_true')
    # parser.add_argument('-n', '--optim_name', default=None)

    # try:
    #     args = parser.parse_args()
    # except:
    #     args = parser.parse_known_args()[0]

    out_root_dir = "/cluster_HDD/lothlann/ppalafox/qualitative_results__interpolation_SHAPE"
    
    viz = False

    # ------------------------------------------- #
    DATASET_TYPE = "HUMAN"
    print("#"*30)
    print(f"DATASET_TYPE: {DATASET_TYPE}")
    print("#"*30)
    # input("Continue?")
    # ------------------------------------------- #

    if DATASET_TYPE == "HUMAN":
        from configs_eval.config_eval_HUMAN import *
    elif DATASET_TYPE == "MANO":
        from configs_eval.config_eval_MANO import *

    ########################################################################################################################
    ########################################################################################################################

    # Extract dataset name
    tmp = exp_name.split('__ON__')
    dataset_name = tmp[-1]

    from utils.parsing_utils import get_dataset_type_from_dataset_name
    dataset_type = get_dataset_type_from_dataset_name(dataset_name)
    splits_dir = f"{cfg.splits_dir}_{dataset_type}"

    labels_json       = os.path.join(data_dir, splits_dir, dataset_name, "labels.json")
    labels_tpose_json = os.path.join(data_dir, splits_dir, dataset_name, "labels_tpose.json")

    print("Reading from:")
    print(labels_json)
    print("Dataset name:")
    print(dataset_name)
    print()
    
    train_to_augmented_json = os.path.join(data_dir, splits_dir, dataset_name, "train_to_augmented.json")

    #######################################################################################################
    # Data
    #######################################################################################################
    with open(labels_json, "r") as f:
        labels = json.loads(f.read())

    with open(labels_tpose_json, "r") as f:
        labels_tpose = json.loads(f.read())

    train_to_augmented = None
    if os.path.isfile(train_to_augmented_json):
        with open(train_to_augmented_json, "r") as f:
            train_to_augmented = json.loads(f.read())

    batch_size = min(batch_size, len(labels))
    print("batch_size", batch_size)

    print("clamping distance", clamping_distance)

    num_identities = len(labels_tpose)
    num_frames = len(labels)

    print()
    print("#"*60)
    print("Num identities", num_identities)
    print("Num frames    ", num_frames)
    print()
    print('Interval', interval)
    print('Factor', factor)
    print("#"*60)
    print()

    ########################################################################################################################
    ########################################################################################################################

    # Pose MLP
    exp_dir = os.path.join(exps_dir, exp_name)
    checkpoint = nnutils.load_checkpoint(exp_dir, checkpoint_epoch)    

    ########################
    # Shape decoder
    ########################
    if checkpoint_tpose is None:
        checkpoint_tpose = checkpoint
    
    shape_decoder = ShapeDecoder(shape_codes_dim, **shape_network_specs).cuda()
    shape_decoder.load_state_dict(checkpoint_tpose['model_state_dict_shape_decoder'])
    for param in shape_decoder.parameters():
        param.requires_grad = False
    shape_decoder.eval()
    nnutils.print_num_parameters(shape_decoder)

    ########################
    # Pose decoder
    ########################
    if use_se3:
        print()
        print("Using SE(3) formulation for the PoseDecoder")
        pose_decoder = PoseDecoderSE3(
            pose_codes_dim + shape_codes_dim, **pose_network_specs
        ).cuda()
    else:
        print()
        print("Using normal (translation) formulation for the PoseDecoder")
        pose_decoder = PoseDecoder(
            pose_codes_dim + shape_codes_dim, **pose_network_specs
        ).cuda()
    pose_decoder.load_state_dict(checkpoint['model_state_dict_pose_decoder'])
    for param in pose_decoder.parameters():
        param.requires_grad = False
    pose_decoder.eval()
    nnutils.print_num_parameters(pose_decoder)
    
    ########################
    # SHAPE Codes
    ########################
    shape_codes = torch.ones(num_identities, 1, shape_codes_dim).normal_(0, 0.1).cuda()
    
    pretrained_shape_codes = checkpoint['shape_codes'].cuda().detach().clone()

    if shape_codes.shape[0] != pretrained_shape_codes.shape[0] and train_to_augmented is not None:
        print("Loading shape codes - Since shape_codes and pretrained_shapes_codes dont match in shape, have to compute mapping...")
        shape_codes = pretrained_shape_codes[list(train_to_augmented.values())].detach().clone()
        if len(shape_codes.shape) == 2:
            shape_codes = shape_codes.unsqueeze(0)
    else:
        print("Loading shape codes - Perfect: shapes match between pretrained and current shape_codes")
        shape_codes = checkpoint['shape_codes'].cuda().detach().clone()
    
    ##################################################################################################################
    ##################################################################################################################
    print()
    print()
    print("#######################################################################")
    print("Final visualization")
    print("#######################################################################")

    # -----------------------------------------------------------------

    # src_identity_name = "kate"
    # tgt_identity_name = "adam"

    src_identity_name = "suzie"
    tgt_identity_name = "racer"

    # src_identity_name = "shae"
    # tgt_identity_name = "regina"

    view = "frontal"

    # -----------------------------------------------------------------

    viewer = ViewerInterpolateShape(
        labels,
        labels_tpose,
        shape_codes,
        out_root_dir,
        num_to_eval=-1,
        view=view,
        dataset_class="mixamo_trans_all",
        src_identity_name=src_identity_name,
        tgt_identity_name=tgt_identity_name,
        num_iterpolations=60,
        frame_rate=15,
        res_mult=2
    )
    viewer.run()
<filename>npms/interpolate_shapes.py
import sys,os

from numpy.core.fromnumeric import shape
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

import os
import trimesh
import numpy as np
import json
import open3d as o3d
import torch
from tqdm import tqdm
from timeit import default_timer as timer
import utils.deepsdf_utils as deepsdf_utils 
import matplotlib.pyplot as plt

from models.pose_decoder import PoseDecoder, PoseDecoderSE3
from models.shape_decoder import ShapeDecoder

from utils.pcd_utils import (BBox,
                            trimesh_to_open3d,
                            transform_pointcloud_to_opengl_coords,
                            rotate_around_axis,
                            origin, normalize_transformation)

import utils.nnutils as nnutils
import config as cfg
import data_scripts.config_data as cfg_data


class ViewerInterpolateShape:
    def __init__(
        self, 
        labels,
        labels_tpose,
        shape_codes,
        out_root_dir,
        num_to_eval=-1,
        view="lateral_left",
        dataset_class=None,
        src_identity_name=None,
        tgt_identity_name=None,
        num_iterpolations=10,
        use_gt_tpose_mesh=False,
        render_video_options="/rhome/ppalafox/workspace/render_video_options",
        frame_rate=30,
        res_mult=1,
    ):
        self.frame_rate = frame_rate

        mult = res_mult
        self.reconstruction_res = 256 * mult
        self.max_batch = (mult * 32)**3

        self.labels = labels
        self.labels_tpose = labels_tpose
        self.num_to_eval = num_to_eval
        
        self.src_identity_name = src_identity_name
        self.tgt_identity_name = tgt_identity_name

        # Find the identity's id
        self.src_identity_id, self.tgt_identity_id = None, None
        for identity_id, label_tpose in enumerate(self.labels_tpose):
            if label_tpose['identity_name'] == self.src_identity_name:
                self.src_identity_id = identity_id
            if label_tpose['identity_name'] == self.tgt_identity_name:
                self.tgt_identity_id = identity_id

        assert self.src_identity_id is not None and self.tgt_identity_id is not None

        self.num_iterpolations = num_iterpolations

        self.shape_codes = shape_codes

        self.dataset_class = dataset_class

        self.START_COLOR = np.array([0.4, 0.6, 0.4])
        self.END_COLOR   = np.array([0.6, 0.4, 0.4])

        self.time = 0
        self.ref = None

        self.use_gt_tpose_mesh = use_gt_tpose_mesh

        # Recording options
        self.view = view
        self.render_json            = os.path.join(render_video_options, "render_options.json")
        self.viewpoint_json         = os.path.join(render_video_options, "viewpoint.json")
        self.viewpoint_lateral_json = os.path.join(render_video_options, "viewpoint_lateral.json")
        self.viewpoint_lateral_left_json = os.path.join(render_video_options, "viewpoint_lateral_left.json")
        os.makedirs(render_video_options, exist_ok=True)
        self.out_dir = os.path.join(out_root_dir, f"{self.src_identity_name}__TO__{self.tgt_identity_name}__@{self.reconstruction_res}__fps{self.frame_rate}")
        os.makedirs(self.out_dir, exist_ok=True)

        self.initialize()


    def initialize(self):

        self.ref_list = []

        self.loaded_frames = 0

        ################################################################################################################
        # Prepare the start and end pose codes
        ################################################################################################################
        shape_code_start = self.shape_codes[[self.src_identity_id], ...] # [bs, 1, C]
        shape_code_end   = self.shape_codes[[self.tgt_identity_id], ...] # [bs, 1, C]

        ################################################################################################################
        ################################################################################################################
        # Go over the different poses
        ################################################################################################################
        ################################################################################################################
        
        for i in tqdm(range(self.num_iterpolations + 1)):

            alpha = i / self.num_iterpolations

            with torch.no_grad():
                ### Prepare INTERPOLATED shape code ###
                shape_code_interp = (1 - alpha) * shape_code_start + alpha * shape_code_end
                assert shape_code_interp.shape == (1, 1, shape_codes_dim), f"{shape_code_interp} vs {(1, 1, shape_codes_dim)}"
                ref_mesh = deepsdf_utils.create_mesh_from_code(
                    shape_decoder, shape_code_interp, shape_codes_dim=shape_codes_dim,
                    N=self.reconstruction_res, max_batch=self.max_batch
                )

            COLOR_INTERP = (1 - alpha) * self.START_COLOR + alpha * self.END_COLOR
            ref_mesh = trimesh_to_open3d(ref_mesh, COLOR_INTERP)

            # o3d.visualization.draw_geometries([ref_mesh])
            
            self.ref_list.append(ref_mesh)

            # Increase counter of evaluated frames
            self.loaded_frames += 1

            print(f'Loaded {self.loaded_frames} frames')

            if self.loaded_frames == self.num_to_eval:
                print()
                print(f"Stopping early. Already loaded {self.loaded_frames}")
                print()
                break

            # break

        # ###############################################################################################
        # # Generate additional meshes.
        # ###############################################################################################
        # unit bbox
        p_min = -0.5
        p_max =  0.5
        self.unit_bbox = BBox.compute_bbox_from_min_point_and_max_point(
            np.array([p_min]*3), np.array([p_max]*3), color=[0.7, 0.7, 0.7]
        )

        # world frame
        self.world_frame = o3d.geometry.TriangleMesh.create_coordinate_frame(
            size=0.00001, origin=[0, 0, 0]
        )

    def update_ref(self, vis):
        param = vis.get_view_control().convert_to_pinhole_camera_parameters()

        if self.ref is not None:
            vis.remove_geometry(self.ref)
        
        self.ref = self.ref_list[self.time]
        vis.add_geometry(self.ref)

        ctr = vis.get_view_control()
        ctr.convert_from_pinhole_camera_parameters(param)

    def _load_render_and_viewpoint_option(self, vis, view):
        vis.get_render_option().load_from_json(self.render_json)
        
        # change viewpoint
        ctr = vis.get_view_control()
        if view == "frontal":
            param = o3d.io.read_pinhole_camera_parameters(self.viewpoint_json)
        elif view == "lateral":
            param = o3d.io.read_pinhole_camera_parameters(self.viewpoint_lateral_json)
        elif view == "lateral_left":
            param = o3d.io.read_pinhole_camera_parameters(self.viewpoint_lateral_left_json)
        else:
            exit()
        ctr.convert_from_pinhole_camera_parameters(param)

    def render_image(self, vis, out_filename):
        image_np = np.asarray(vis.capture_screen_float_buffer(False))
        h, w, _ = image_np.shape
        new_h, new_w = 1200, 1600
        image_np = image_np[(h-new_h)//2:(h+new_h)//2, (w-new_w)//2:(w+new_w)//2,:]
        plt.imsave(f"{self.out_dir}/{out_filename}.jpg", image_np)
        
    def run(self):

        def update_all(vis):
            self.update_ref(vis)
            return False

        # Define callbacks.
        def toggle_next(vis):
            self.time += 1
            if self.time >= self.loaded_frames:
                self.time = 0
            update_all(vis)
            return False
        
        def toggle_previous(vis):
            self.time -= 1
            if self.time < 0:
                self.time = self.loaded_frames - 1
            update_all(vis)
            return False

        def render(vis):
            print("::render")

            self._load_render_and_viewpoint_option(vis, self.view)

            ##################################################
            # Render the interpolated poses
            ##################################################
            self.time = 0
            self.show_ref = True 
            self.ref = self.ref_list[self.time]
            update_all(vis)
            vis.poll_events()
            vis.update_renderer()
            
            for i in range(len(self.ref_list)):
                # Render
                self.render_image(vis, f"interp_{str(i).zfill(2)}")
                toggle_next(vis)
                vis.poll_events()
                vis.update_renderer()
            self.show_src_refw = False 

            os.system(f"ffmpeg -r {self.frame_rate} -i {self.out_dir}/interp_%02d.jpg -c:v libx264 -vf fps=30 -pix_fmt yuv420p -y {self.out_dir}/{self.src_identity_name}__TO__{self.tgt_identity_name}__@{self.reconstruction_res}.mp4")
            exit() 

            return False

        def save_viewpoint_lateral_left(vis):
            print("::save_viewpoint")
            param = vis.get_view_control().convert_to_pinhole_camera_parameters()
            o3d.io.write_pinhole_camera_parameters(self.viewpoint_lateral_left_json, param)
            return False

        key_to_callback = {}
        key_to_callback[ord("D")] = toggle_next
        key_to_callback[ord("A")] = toggle_previous
        key_to_callback[ord("R")] = render
        key_to_callback[ord("'")] = save_viewpoint_lateral_left

        # Add mesh at initial time step.
        assert self.time < self.loaded_frames

        print("Showing time", self.time)

        # Start showing the tgt tpose
        self.ref = self.ref_list[self.time]

        o3d.visualization.draw_geometries_with_key_callbacks([self.world_frame, self.ref], key_to_callback)


################################################################################################################################
################################################################################################################################


if __name__ == "__main__":

    torch.backends.cudnn.benchmark = True

    ########################################################################################################################
    # Options
    ########################################################################################################################
    # import argparse
    # parser = argparse.ArgumentParser(
    #     description='Run Model'
    # )
    # parser.add_argument('-o', '--optimize_codes', action='store_true')
    # parser.add_argument('-e', '--extra_name', default="")
    # parser.add_argument('-v', '--viz', action='store_true')
    # parser.add_argument('-n', '--optim_name', default=None)

    # try:
    #     args = parser.parse_args()
    # except:
    #     args = parser.parse_known_args()[0]

    out_root_dir = "/cluster_HDD/lothlann/ppalafox/qualitative_results__interpolation_SHAPE"
    
    viz = False

    # ------------------------------------------- #
    DATASET_TYPE = "HUMAN"
    print("#"*30)
    print(f"DATASET_TYPE: {DATASET_TYPE}")
    print("#"*30)
    # input("Continue?")
    # ------------------------------------------- #

    if DATASET_TYPE == "HUMAN":
        from configs_eval.config_eval_HUMAN import *
    elif DATASET_TYPE == "MANO":
        from configs_eval.config_eval_MANO import *

    ########################################################################################################################
    ########################################################################################################################

    # Extract dataset name
    tmp = exp_name.split('__ON__')
    dataset_name = tmp[-1]

    from utils.parsing_utils import get_dataset_type_from_dataset_name
    dataset_type = get_dataset_type_from_dataset_name(dataset_name)
    splits_dir = f"{cfg.splits_dir}_{dataset_type}"

    labels_json       = os.path.join(data_dir, splits_dir, dataset_name, "labels.json")
    labels_tpose_json = os.path.join(data_dir, splits_dir, dataset_name, "labels_tpose.json")

    print("Reading from:")
    print(labels_json)
    print("Dataset name:")
    print(dataset_name)
    print()
    
    train_to_augmented_json = os.path.join(data_dir, splits_dir, dataset_name, "train_to_augmented.json")

    #######################################################################################################
    # Data
    #######################################################################################################
    with open(labels_json, "r") as f:
        labels = json.loads(f.read())

    with open(labels_tpose_json, "r") as f:
        labels_tpose = json.loads(f.read())

    train_to_augmented = None
    if os.path.isfile(train_to_augmented_json):
        with open(train_to_augmented_json, "r") as f:
            train_to_augmented = json.loads(f.read())

    batch_size = min(batch_size, len(labels))
    print("batch_size", batch_size)

    print("clamping distance", clamping_distance)

    num_identities = len(labels_tpose)
    num_frames = len(labels)

    print()
    print("#"*60)
    print("Num identities", num_identities)
    print("Num frames    ", num_frames)
    print()
    print('Interval', interval)
    print('Factor', factor)
    print("#"*60)
    print()

    ########################################################################################################################
    ########################################################################################################################

    # Pose MLP
    exp_dir = os.path.join(exps_dir, exp_name)
    checkpoint = nnutils.load_checkpoint(exp_dir, checkpoint_epoch)    

    ########################
    # Shape decoder
    ########################
    if checkpoint_tpose is None:
        checkpoint_tpose = checkpoint
    
    shape_decoder = ShapeDecoder(shape_codes_dim, **shape_network_specs).cuda()
    shape_decoder.load_state_dict(checkpoint_tpose['model_state_dict_shape_decoder'])
    for param in shape_decoder.parameters():
        param.requires_grad = False
    shape_decoder.eval()
    nnutils.print_num_parameters(shape_decoder)

    ########################
    # Pose decoder
    ########################
    if use_se3:
        print()
        print("Using SE(3) formulation for the PoseDecoder")
        pose_decoder = PoseDecoderSE3(
            pose_codes_dim + shape_codes_dim, **pose_network_specs
        ).cuda()
    else:
        print()
        print("Using normal (translation) formulation for the PoseDecoder")
        pose_decoder = PoseDecoder(
            pose_codes_dim + shape_codes_dim, **pose_network_specs
        ).cuda()
    pose_decoder.load_state_dict(checkpoint['model_state_dict_pose_decoder'])
    for param in pose_decoder.parameters():
        param.requires_grad = False
    pose_decoder.eval()
    nnutils.print_num_parameters(pose_decoder)
    
    ########################
    # SHAPE Codes
    ########################
    shape_codes = torch.ones(num_identities, 1, shape_codes_dim).normal_(0, 0.1).cuda()
    
    pretrained_shape_codes = checkpoint['shape_codes'].cuda().detach().clone()

    if shape_codes.shape[0] != pretrained_shape_codes.shape[0] and train_to_augmented is not None:
        print("Loading shape codes - Since shape_codes and pretrained_shapes_codes dont match in shape, have to compute mapping...")
        shape_codes = pretrained_shape_codes[list(train_to_augmented.values())].detach().clone()
        if len(shape_codes.shape) == 2:
            shape_codes = shape_codes.unsqueeze(0)
    else:
        print("Loading shape codes - Perfect: shapes match between pretrained and current shape_codes")
        shape_codes = checkpoint['shape_codes'].cuda().detach().clone()
    
    ##################################################################################################################
    ##################################################################################################################
    print()
    print()
    print("#######################################################################")
    print("Final visualization")
    print("#######################################################################")

    # -----------------------------------------------------------------

    # src_identity_name = "kate"
    # tgt_identity_name = "adam"

    src_identity_name = "suzie"
    tgt_identity_name = "racer"

    # src_identity_name = "shae"
    # tgt_identity_name = "regina"

    view = "frontal"

    # -----------------------------------------------------------------

    viewer = ViewerInterpolateShape(
        labels,
        labels_tpose,
        shape_codes,
        out_root_dir,
        num_to_eval=-1,
        view=view,
        dataset_class="mixamo_trans_all",
        src_identity_name=src_identity_name,
        tgt_identity_name=tgt_identity_name,
        num_iterpolations=60,
        frame_rate=15,
        res_mult=2
    )
    viewer.run()
# Find the identity's id # Recording options ################################################################################################################ # Prepare the start and end pose codes ################################################################################################################ # [bs, 1, C] # [bs, 1, C] ################################################################################################################ ################################################################################################################ # Go over the different poses ################################################################################################################ ################################################################################################################ ### Prepare INTERPOLATED shape code ### # o3d.visualization.draw_geometries([ref_mesh]) # Increase counter of evaluated frames # break # ############################################################################################### # # Generate additional meshes. # ############################################################################################### # unit bbox # world frame # change viewpoint # Define callbacks. ################################################## # Render the interpolated poses ################################################## # Render # Add mesh at initial time step. # Start showing the tgt tpose ################################################################################################################################ ################################################################################################################################ ######################################################################################################################## # Options ######################################################################################################################## # import argparse # parser = argparse.ArgumentParser( #     description='Run Model' # ) # parser.add_argument('-o', '--optimize_codes', action='store_true') # parser.add_argument('-e', '--extra_name', default="") # parser.add_argument('-v', '--viz', action='store_true') # parser.add_argument('-n', '--optim_name', default=None) # try: #     args = parser.parse_args() # except: #     args = parser.parse_known_args()[0] # ------------------------------------------- # # input("Continue?") # ------------------------------------------- # ######################################################################################################################## ######################################################################################################################## # Extract dataset name ####################################################################################################### # Data ####################################################################################################### ######################################################################################################################## ######################################################################################################################## # Pose MLP ######################## # Shape decoder ######################## ######################## # Pose decoder ######################## ######################## # SHAPE Codes ######################## ################################################################################################################## ################################################################################################################## ######################################################################") ######################################################################") # ----------------------------------------------------------------- # src_identity_name = "kate" # tgt_identity_name = "adam" # src_identity_name = "shae" # tgt_identity_name = "regina" # -----------------------------------------------------------------