CoolFace
Apppublic

chencws/Stable-text-to-motion

sourceHugging Faceapache-2.0updated 3y agoView on Hugging Face
0likes
app.py330 linesDownload Raw Back to root
1import sys2import os3import OpenGL.GL as gl4os.environ["PYOPENGL_PLATFORM"] = "egl"5os.environ["MESA_GL_VERSION_OVERRIDE"] = "4.1"6os.system('pip install /home/user/app/pyrender')7 8sys.argv = ['VQ-Trans/GPT_eval_multi.py']9os.chdir('VQ-Trans')10 11sys.path.append('/home/user/app/VQ-Trans')12sys.path.append('/home/user/app/pyrender')13 14import options.option_transformer as option_trans15from huggingface_hub import snapshot_download16model_path = snapshot_download(repo_id="vumichien/T2M-GPT")17 18args = option_trans.get_args_parser()19 20args.dataname = 't2m'21args.resume_pth = f'{model_path}/VQVAE/net_last.pth'22args.resume_trans = f'{model_path}/VQTransformer_corruption05/net_best_fid.pth'23args.down_t = 224args.depth = 325args.block_size = 5126 27import clip28import torch29import numpy as np30import models.vqvae as vqvae31import models.t2m_trans as trans32from utils.motion_process import recover_from_ric33import visualization.plot_3d_global as plot_3d34from models.rotation2xyz import Rotation2xyz35import numpy as np36from trimesh import Trimesh37import gc38 39import torch40from visualize.simplify_loc2rot import joints2smpl41import pyrender42# import matplotlib.pyplot as plt43 44import io45import imageio46from shapely import geometry47import trimesh48from pyrender.constants import RenderFlags49import math50# import ffmpeg51# from PIL import Image52import hashlib53import gradio as gr54import moviepy.editor as mp55 56## load clip model and datasets57is_cuda = torch.cuda.is_available()58device = torch.device("cuda" if is_cuda else "cpu")59print(device)60clip_model, clip_preprocess = clip.load("ViT-B/32", device=device, jit=False, download_root='./')  # Must set jit=False for training61 62if is_cuda:63    clip.model.convert_weights(clip_model)64    65clip_model.eval()66for p in clip_model.parameters():67    p.requires_grad = False68 69net = vqvae.HumanVQVAE(args, ## use args to define different parameters in different quantizers70                       args.nb_code,71                       args.code_dim,72                       args.output_emb_width,73                       args.down_t,74                       args.stride_t,75                       args.width,76                       args.depth,77                       args.dilation_growth_rate)78 79 80trans_encoder = trans.Text2Motion_Transformer(num_vq=args.nb_code, 81                                embed_dim=1024, 82                                clip_dim=args.clip_dim, 83                                block_size=args.block_size, 84                                num_layers=9, 85                                n_head=16, 86                                drop_out_rate=args.drop_out_rate, 87                                fc_rate=args.ff_rate)88 89 90print('loading checkpoint from {}'.format(args.resume_pth))91ckpt = torch.load(args.resume_pth, map_location='cpu')92net.load_state_dict(ckpt['net'], strict=True)93net.eval()94    95print('loading transformer checkpoint from {}'.format(args.resume_trans))96ckpt = torch.load(args.resume_trans, map_location='cpu')97trans_encoder.load_state_dict(ckpt['trans'], strict=True)98trans_encoder.eval()99 100mean = torch.from_numpy(np.load(f'{model_path}/meta/mean.npy'))101std = torch.from_numpy(np.load(f'{model_path}/meta/std.npy'))102 103if is_cuda:104    net.cuda()105    trans_encoder.cuda()106    mean = mean.cuda()107    std = std.cuda()108 109def render(motions, device_id=0, name='test_vis'):110    frames, njoints, nfeats = motions.shape111    MINS = motions.min(axis=0).min(axis=0)112    MAXS = motions.max(axis=0).max(axis=0)113 114    height_offset = MINS[1]115    motions[:, :, 1] -= height_offset116    trajec = motions[:, 0, [0, 2]]117    is_cuda = torch.cuda.is_available()118    # device = torch.device("cuda" if is_cuda else "cpu")119    j2s = joints2smpl(num_frames=frames, device_id=0, cuda=is_cuda)120    rot2xyz = Rotation2xyz(device=device)121    faces = rot2xyz.smpl_model.faces122 123    if not os.path.exists(f'output/{name}_pred.pt'): 124        print(f'Running SMPLify, it may take a few minutes.')125        motion_tensor, opt_dict = j2s.joint2smpl(motions)  # [nframes, njoints, 3]126 127        vertices = rot2xyz(torch.tensor(motion_tensor).clone(), mask=None,128                                        pose_rep='rot6d', translation=True, glob=True,129                                        jointstype='vertices',130                                        vertstrans=True)131        vertices = vertices.detach().cpu()132        torch.save(vertices, f'output/{name}_pred.pt')133    else:134        vertices = torch.load(f'output/{name}_pred.pt')135    frames = vertices.shape[3] # shape: 1, nb_frames, 3, nb_joints136    print(vertices.shape)137    MINS = torch.min(torch.min(vertices[0], axis=0)[0], axis=1)[0]138    MAXS = torch.max(torch.max(vertices[0], axis=0)[0], axis=1)[0]139 140    out_list = []141    142    minx = MINS[0] - 0.5143    maxx = MAXS[0] + 0.5144    minz = MINS[2] - 0.5 145    maxz = MAXS[2] + 0.5146    polygon = geometry.Polygon([[minx, minz], [minx, maxz], [maxx, maxz], [maxx, minz]])147    polygon_mesh = trimesh.creation.extrude_polygon(polygon, 1e-5)148 149    vid = []150    for i in range(frames):151        if i % 10 == 0:152            print(i)153 154        mesh = Trimesh(vertices=vertices[0, :, :, i].squeeze().tolist(), faces=faces)155 156        base_color = (0.11, 0.53, 0.8, 0.5)157        ## OPAQUE rendering without alpha158        ## BLEND rendering consider alpha 159        material = pyrender.MetallicRoughnessMaterial(160            metallicFactor=0.7,161            alphaMode='OPAQUE',162            baseColorFactor=base_color163        )164 165 166        mesh = pyrender.Mesh.from_trimesh(mesh, material=material)167 168        polygon_mesh.visual.face_colors = [0, 0, 0, 0.21]169        polygon_render = pyrender.Mesh.from_trimesh(polygon_mesh, smooth=False)170 171        bg_color = [1, 1, 1, 0.8]172        scene = pyrender.Scene(bg_color=bg_color, ambient_light=(0.4, 0.4, 0.4))173        174        sx, sy, tx, ty = [0.75, 0.75, 0, 0.10]175 176        camera = pyrender.PerspectiveCamera(yfov=(np.pi / 3.0))177 178        light = pyrender.DirectionalLight(color=[1,1,1], intensity=300)179 180        scene.add(mesh)181 182        c = np.pi / 2183 184        scene.add(polygon_render, pose=np.array([[ 1, 0, 0, 0],185 186        [ 0, np.cos(c), -np.sin(c), MINS[1].cpu().numpy()],187 188        [ 0, np.sin(c), np.cos(c), 0],189 190        [ 0, 0, 0, 1]]))191 192        light_pose = np.eye(4)193        light_pose[:3, 3] = [0, -1, 1]194        scene.add(light, pose=light_pose.copy())195 196        light_pose[:3, 3] = [0, 1, 1]197        scene.add(light, pose=light_pose.copy())198 199        light_pose[:3, 3] = [1, 1, 2]200        scene.add(light, pose=light_pose.copy())201 202 203        c = -np.pi / 6204 205        scene.add(camera, pose=[[ 1, 0, 0, (minx+maxx).cpu().numpy()/2],206 207                                [ 0, np.cos(c), -np.sin(c), 1.5],208 209                                [ 0, np.sin(c), np.cos(c), max(4, minz.cpu().numpy()+(1.5-MINS[1].cpu().numpy())*2, (maxx-minx).cpu().numpy())],210 211                                [ 0, 0, 0, 1]212                                ])213        214        # render scene215        r = pyrender.OffscreenRenderer(960, 960)216 217        color, _ = r.render(scene, flags=RenderFlags.RGBA)218        # Image.fromarray(color).save(outdir+'/'+name+'_'+str(i)+'.png')219 220        vid.append(color)221 222        r.delete()223 224    out = np.stack(vid, axis=0)225    imageio.mimwrite(f'output/results.gif', out, duration=50)226    out_video = mp.VideoFileClip(f'output/results.gif')227    out_video.write_videofile("output/results.mp4")228    del out, vertices229    return f'output/results.mp4'230 231def predict(clip_text, method='fast'):232    gc.collect()233    print('prompt text instruction: {}'.format(clip_text))234    if torch.cuda.is_available():235        text = clip.tokenize([clip_text], truncate=True).cuda()236    else:237        text = clip.tokenize([clip_text], truncate=True)238    feat_clip_text = clip_model.encode_text(text).float()239    index_motion = trans_encoder.sample(feat_clip_text[0:1], False)240    pred_pose = net.forward_decoder(index_motion)241    pred_xyz = recover_from_ric((pred_pose*std+mean).float(), 22)242    output_name = hashlib.md5(clip_text.encode()).hexdigest()243    if method == 'fast':244        xyz = pred_xyz.reshape(1, -1, 22, 3)245        pose_vis = plot_3d.draw_to_batch(xyz.detach().cpu().numpy(), title_batch=None, outname=[f'output/results.gif'])246        out_video = mp.VideoFileClip("output/results.gif")247        out_video.write_videofile("output/results.mp4")248        return f'output/results.mp4'249    elif method == 'slow':250        output_path = render(pred_xyz.detach().cpu().numpy().squeeze(axis=0), device_id=0, name=output_name)251        return output_path252 253        254# ---- Gradio Layout -----255video_out = gr.Video(label="Motion", mirror_webcam=False, interactive=False) 256demo = gr.Blocks()257demo.encrypt = False258 259with demo:260    gr.Markdown('''261            <div>262            <h1 style='text-align: center'>Generating Human Motion from Textual Descriptions (T2M-GPT)</h1>263            This space uses <a href='https://mael-zys.github.io/T2M-GPT/' target='_blank'><b>T2M-GPT models</b></a> based on Vector Quantised-Variational AutoEncoder (VQ-VAE) and Generative Pre-trained Transformer (GPT) for human motion generation from textural descriptions🤗264            </div>265        ''')266    with gr.Row():267        with gr.Column():268            gr.Markdown('''269            <figure>270              <img src="https://huggingface.co/vumichien/T2M-GPT/resolve/main/demo_slow1.gif" alt="Demo Slow", width="425", height=480/>271              <figcaption> a man starts off in an up right position with botg arms extended out by his sides, he then brings his arms down to his body and claps his hands together. after this he wals down amd the the left where he proceeds to sit on a seat272              </figcaption>273            </figure>274            ''')275        with gr.Column():276            gr.Markdown('''277            <figure>278              <img src="https://huggingface.co/vumichien/T2M-GPT/resolve/main/demo_slow2.gif" alt="Demo Slow 2", width="425", height=480/>279              <figcaption> a person puts their hands together, leans forwards slightly then swings the arms from right to left280              </figcaption>281            </figure>282            ''')283        with gr.Column():284            gr.Markdown('''285            <figure>286              <img src="https://huggingface.co/vumichien/T2M-GPT/resolve/main/demo_slow3.gif" alt="Demo Slow 3", width="425", height=480/>287              <figcaption> a man is practicing the waltz with a partner288              </figcaption>289            </figure>290            ''')291    with gr.Row():292        with gr.Column():293            gr.Markdown('''294            ### Generate human motion by **T2M-GPT**295            ##### Step 1. Give prompt text describing human motion296            ##### Step 2. Choice method to render output (Fast: Sketch skeleton; Slow: SMPL mesh, only work with GPU and running time around 2 mins)297            ##### Step 3. Generate output and enjoy298            ''')299    with gr.Column():300        with gr.Row():301            text_prompt = gr.Textbox(label="Text prompt", lines=1, interactive=True)302            method = gr.Dropdown(["slow", "fast"], label="Method", value="slow")303        with gr.Row():304            generate_btn = gr.Button("Generate")305            generate_btn.click(predict, [text_prompt, method], [video_out], api_name="generate")306        with gr.Row():  307            video_out.render()308    with gr.Row(): 309        gr.Markdown('''310            ### You can test by following examples:311            ''')312    examples = gr.Examples(313            examples=[314                ["a person jogs in place, slowly at first, then increases speed. they then back up and squat down.", "slow"],315                ["a man steps forward and does a handstand", "slow"],316                ["a man rises from the ground, walks in a circle and sits back down on the ground", "slow"],317                ["a man starts off in an up right position with botg arms extended out by his sides, he then brings his arms down to his body and claps his hands together. after this he wals down amd the the left where he proceeds to sit on a seat", "slow"],318                ["a person puts their hands together, leans forwards slightly then swings the arms from right to left","slow"],319                ["a man is practicing the waltz with a partner","slow"],320            ],321            label="Examples", 322            inputs=[text_prompt, method],323            outputs=[video_out],324            fn=predict,325            cache_examples=True,326        )327 328        329demo.launch(debug=True)330