bill-jiang commited on
Commit
f0a0274
1 Parent(s): 90b88a3

Update render method

Browse files
Files changed (4) hide show
  1. .gitignore +0 -1
  2. app.py +9 -56
  3. mGPT/render/blender/render.py +177 -0
  4. render.py +76 -0
.gitignore CHANGED
@@ -8,7 +8,6 @@ __pycache__/
8
  .DS_Store
9
  pyglet
10
  app2.py
11
- render.py
12
  cache
13
 
14
  # Distribution / packaging
 
8
  .DS_Store
9
  pyglet
10
  app2.py
 
11
  cache
12
 
13
  # Distribution / packaging
app.py CHANGED
@@ -7,27 +7,18 @@ os.system('pip install pyglet==1.4.0a1')
7
  os.system('pip install triangle==20220202')
8
 
9
  import gradio as gr
10
- import random
11
  import torch
12
  import time
13
- import cv2
14
  import numpy as np
15
- import OpenGL.GL as gl
16
- import imageio
17
  import pytorch_lightning as pl
18
- import moviepy.editor as mp
19
  from pathlib import Path
20
  from mGPT.data.build_data import build_data
21
  from mGPT.models.build_model import build_model
22
  from mGPT.config import parse_args
23
- from scipy.spatial.transform import Rotation as RRR
24
- import mGPT.render.matplot.plot_3d_global as plot_3d
25
- from mGPT.render.pyrender.hybrik_loc2rot import HybrIKJointsToRotmat
26
- from mGPT.render.pyrender.smpl_render import SMPLRender
27
  from transformers import WhisperProcessor, WhisperForConditionalGeneration
28
  import librosa
29
  from huggingface_hub import snapshot_download
30
- import eventlet
31
 
32
  # Load model
33
  cfg = parse_args(phase="webui") # parse config file
@@ -105,55 +96,17 @@ def render_motion(data, feats, method='fast'):
105
  fname = time.strftime("%Y-%m-%d-%H_%M_%S", time.localtime(
106
  time.time())) + str(np.random.randint(10000, 99999))
107
  video_fname = fname + '.mp4'
108
- feats_fname = fname + '.npy'
 
109
  output_npy_path = os.path.join(output_dir, feats_fname)
 
110
  output_mp4_path = os.path.join(output_dir, video_fname)
111
  np.save(output_npy_path, feats)
112
-
113
- if method == 'slow':
114
- if len(data.shape) == 4:
115
- data = data[0]
116
- data = data - data[0, 0]
117
- pose_generator = HybrIKJointsToRotmat()
118
- pose = pose_generator(data)
119
- pose = np.concatenate([
120
- pose,
121
- np.stack([np.stack([np.eye(3)] * pose.shape[0], 0)] * 2, 1)
122
- ], 1)
123
- shape = [768, 768]
124
- render = SMPLRender(cfg.RENDER.SMPL_MODEL_PATH)
125
-
126
- r = RRR.from_rotvec(np.array([np.pi, 0.0, 0.0]))
127
- pose[:, 0] = np.matmul(r.as_matrix().reshape(1, 3, 3), pose[:, 0])
128
- vid = []
129
- aroot = data[:, 0]
130
- aroot[:, 1:] = -aroot[:, 1:]
131
- params = dict(pred_shape=np.zeros([1, 10]),
132
- pred_root=aroot,
133
- pred_pose=pose)
134
- render.init_renderer([shape[0], shape[1], 3], params)
135
- for i in range(data.shape[0]):
136
- renderImg = render.render(i)
137
- vid.append(renderImg)
138
-
139
- out = np.stack(vid, axis=0)
140
- output_gif_path = output_mp4_path[:-4] + '.gif'
141
- imageio.mimwrite(output_gif_path, out, duration=50)
142
- out_video = mp.VideoFileClip(output_gif_path)
143
- out_video.write_videofile(output_mp4_path)
144
- del out, render
145
-
146
- elif method == 'fast':
147
- output_gif_path = output_mp4_path[:-4] + '.gif'
148
- if len(data.shape) == 3:
149
- data = data[None]
150
- if isinstance(data, torch.Tensor):
151
- data = data.cpu().numpy()
152
- pose_vis = plot_3d.draw_to_batch(data, [''], [output_gif_path])
153
- out_video = mp.VideoFileClip(output_gif_path)
154
- out_video.write_videofile(output_mp4_path)
155
- del pose_vis
156
-
157
  return output_mp4_path, video_fname, output_npy_path, feats_fname
158
 
159
 
 
7
  os.system('pip install triangle==20220202')
8
 
9
  import gradio as gr
 
10
  import torch
11
  import time
 
12
  import numpy as np
 
 
13
  import pytorch_lightning as pl
14
+ import subprocess
15
  from pathlib import Path
16
  from mGPT.data.build_data import build_data
17
  from mGPT.models.build_model import build_model
18
  from mGPT.config import parse_args
 
 
 
 
19
  from transformers import WhisperProcessor, WhisperForConditionalGeneration
20
  import librosa
21
  from huggingface_hub import snapshot_download
 
22
 
23
  # Load model
24
  cfg = parse_args(phase="webui") # parse config file
 
96
  fname = time.strftime("%Y-%m-%d-%H_%M_%S", time.localtime(
97
  time.time())) + str(np.random.randint(10000, 99999))
98
  video_fname = fname + '.mp4'
99
+ feats_fname = f"{fname}_feats" + '.npy'
100
+ data_fname = f"{fname}_joints" + '.npy'
101
  output_npy_path = os.path.join(output_dir, feats_fname)
102
+ output_joints_path = os.path.join(output_dir, data_fname)
103
  output_mp4_path = os.path.join(output_dir, video_fname)
104
  np.save(output_npy_path, feats)
105
+ np.save(output_joints_path, data)
106
+
107
+ cmd3 = ["xvfb-run", "python", "-m", "render", "--joints_path", output_joints_path, "--method", method, "--output_mp4_path", output_mp4_path, "--smpl_model_path", cfg.RENDER.SMPL_MODEL_PATH]
108
+ subprocess.run(cmd3)
109
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  return output_mp4_path, video_fname, output_npy_path, feats_fname
111
 
112
 
mGPT/render/blender/render.py ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import os
3
+ import sys
4
+ import smplx
5
+ # import bpy
6
+ import numpy as np
7
+
8
+ from .camera import Camera
9
+ from .floor import get_trajectory, plot_floor, show_traj
10
+ from .sampler import get_frameidx
11
+ from .scene import setup_scene # noqa
12
+ from .tools import delete_objs, load_numpy_vertices_into_blender, style_detect
13
+ from .vertices import prepare_vertices
14
+ from mGPT.utils.joints import smplh_to_mmm_scaling_factor
15
+
16
+
17
+ def prune_begin_end(data, perc):
18
+ to_remove = int(len(data) * perc)
19
+ if to_remove == 0:
20
+ return data
21
+ return data[to_remove:-to_remove]
22
+
23
+
24
+ def render_current_frame(path):
25
+ bpy.context.scene.render.filepath = path
26
+ bpy.ops.render.render(use_viewport=True, write_still=True)
27
+
28
+
29
+ def render(npydata,
30
+ frames_folder,
31
+ *,
32
+ mode,
33
+ model_path,
34
+ faces_path,
35
+ gt=False,
36
+ exact_frame=None,
37
+ num=8,
38
+ downsample=True,
39
+ canonicalize=True,
40
+ always_on_floor=False,
41
+ denoising=True,
42
+ oldrender=True,
43
+ res="high",
44
+ init=True,
45
+ accelerator='gpu',
46
+ device=[0]):
47
+ if init:
48
+ # Setup the scene (lights / render engine / resolution etc)
49
+ setup_scene(res=res,
50
+ denoising=denoising,
51
+ oldrender=oldrender,
52
+ accelerator=accelerator,
53
+ device=device)
54
+
55
+ is_mesh, is_smplx, jointstype = style_detect(npydata)
56
+
57
+ if not is_mesh:
58
+ npydata = npydata * smplh_to_mmm_scaling_factor
59
+
60
+ if is_smplx:
61
+ smplx_model_male = smplx.create(model_path,
62
+ model_type='smplx',
63
+ gender='male',
64
+ ext='npz',
65
+ num_betas=10,
66
+ flat_hand_mean=True,
67
+ use_pca=False)
68
+ faces_path = smplx_model_male.faces
69
+
70
+
71
+
72
+ # Put everything in this folder
73
+ if mode == "video":
74
+ if always_on_floor:
75
+ frames_folder += "_of"
76
+ os.makedirs(frames_folder, exist_ok=True)
77
+ # if it is a mesh, it is already downsampled
78
+ if downsample and not is_mesh:
79
+ npydata = npydata[::8]
80
+ elif mode == "sequence":
81
+ img_name, ext = os.path.splitext(frames_folder)
82
+ if always_on_floor:
83
+ img_name += "_of"
84
+ img_path = f"{img_name}{ext}"
85
+
86
+ elif mode == "frame":
87
+ img_name, ext = os.path.splitext(frames_folder)
88
+ if always_on_floor:
89
+ img_name += "_of"
90
+ img_path = f"{img_name}_{exact_frame}{ext}"
91
+
92
+ # remove X% of begining and end
93
+ # as it is almost always static
94
+ # in this part
95
+ if mode == "sequence":
96
+ perc = 0.2
97
+ npydata = prune_begin_end(npydata, perc)
98
+
99
+ if is_mesh:
100
+ from .meshes import Meshes
101
+ data = Meshes(npydata,
102
+ gt=gt,
103
+ mode=mode,
104
+ faces_path=faces_path,
105
+ canonicalize=canonicalize,
106
+ always_on_floor=always_on_floor,
107
+ is_smplx=is_smplx)
108
+ else:
109
+ from .joints import Joints
110
+ data = Joints(npydata,
111
+ gt=gt,
112
+ mode=mode,
113
+ canonicalize=canonicalize,
114
+ always_on_floor=always_on_floor,
115
+ jointstype=jointstype)
116
+
117
+ # Number of frames possible to render
118
+ nframes = len(data)
119
+
120
+ # Show the trajectory
121
+ show_traj(data.trajectory)
122
+
123
+ # Create a floor
124
+ plot_floor(data.data, big_plane=False)
125
+
126
+ # initialize the camera
127
+ camera = Camera(first_root=data.get_root(0), mode=mode, is_mesh=is_mesh)
128
+
129
+ frameidx = get_frameidx(mode=mode,
130
+ nframes=nframes,
131
+ exact_frame=exact_frame,
132
+ frames_to_keep=num)
133
+
134
+ nframes_to_render = len(frameidx)
135
+
136
+ # center the camera to the middle
137
+ if mode == "sequence":
138
+ camera.update(data.get_mean_root())
139
+
140
+ imported_obj_names = []
141
+ for index, frameidx in enumerate(frameidx):
142
+ if mode == "sequence":
143
+ frac = index / (nframes_to_render - 1)
144
+ mat = data.get_sequence_mat(frac)
145
+ else:
146
+ mat = data.mat
147
+ camera.update(data.get_root(frameidx))
148
+
149
+ islast = index == (nframes_to_render - 1)
150
+
151
+ objname = data.load_in_blender(frameidx, mat)
152
+ name = f"{str(index).zfill(4)}"
153
+
154
+ if mode == "video":
155
+ path = os.path.join(frames_folder, f"frame_{name}.png")
156
+ else:
157
+ path = img_path
158
+
159
+ if mode == "sequence":
160
+ imported_obj_names.extend(objname)
161
+ elif mode == "frame":
162
+ camera.update(data.get_root(frameidx))
163
+
164
+ if mode != "sequence" or islast:
165
+ render_current_frame(path)
166
+ delete_objs(objname)
167
+
168
+ bpy.ops.wm.save_as_mainfile(filepath=frames_folder.replace('.png','.blend').replace('_frames','.blend'))
169
+
170
+ # remove every object created
171
+ delete_objs(imported_obj_names)
172
+ delete_objs(["Plane", "myCurve", "Cylinder"])
173
+
174
+ if mode == "video":
175
+ return frames_folder
176
+ else:
177
+ return img_path
render.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from argparse import ArgumentParser
3
+ import numpy as np
4
+ import OpenGL.GL as gl
5
+ import imageio
6
+ import cv2
7
+ import random
8
+ import torch
9
+ import moviepy.editor as mp
10
+ from scipy.spatial.transform import Rotation as RRR
11
+ import mGPT.render.matplot.plot_3d_global as plot_3d
12
+ from mGPT.render.pyrender.hybrik_loc2rot import HybrIKJointsToRotmat
13
+ from mGPT.render.pyrender.smpl_render import SMPLRender
14
+
15
+
16
+ if __name__ == '__main__':
17
+
18
+ parser = ArgumentParser()
19
+ parser.add_argument('--joints_path', type=str, help='Path to joints data')
20
+ parser.add_argument('--method', type=str, help='Method for rendering')
21
+ parser.add_argument('--output_mp4_path', type=str, help='Path to output MP4 file')
22
+ parser.add_argument('--smpl_model_path', type=str, help='Path to SMPL model')
23
+
24
+ args = parser.parse_args()
25
+
26
+ joints_path = args.joints_path
27
+ method = args.method
28
+ output_mp4_path = args.output_mp4_path
29
+ smpl_model_path = args.smpl_model_path
30
+
31
+
32
+ data = np.load(joints_path)
33
+
34
+ if method == 'slow':
35
+ if len(data.shape) == 4:
36
+ data = data[0]
37
+ data = data - data[0, 0]
38
+ pose_generator = HybrIKJointsToRotmat()
39
+ pose = pose_generator(data)
40
+ pose = np.concatenate([
41
+ pose,
42
+ np.stack([np.stack([np.eye(3)] * pose.shape[0], 0)] * 2, 1)
43
+ ], 1)
44
+ shape = [768, 768]
45
+ render = SMPLRender(smpl_model_path)
46
+
47
+ r = RRR.from_rotvec(np.array([np.pi, 0.0, 0.0]))
48
+ pose[:, 0] = np.matmul(r.as_matrix().reshape(1, 3, 3), pose[:, 0])
49
+ vid = []
50
+ aroot = data[:, 0]
51
+ aroot[:, 1:] = -aroot[:, 1:]
52
+ params = dict(pred_shape=np.zeros([1, 10]),
53
+ pred_root=aroot,
54
+ pred_pose=pose)
55
+ render.init_renderer([shape[0], shape[1], 3], params)
56
+ for i in range(data.shape[0]):
57
+ renderImg = render.render(i)
58
+ vid.append(renderImg)
59
+
60
+ out = np.stack(vid, axis=0)
61
+ output_gif_path = output_mp4_path[:-4] + '.gif'
62
+ imageio.mimwrite(output_gif_path, out, duration=50)
63
+ out_video = mp.VideoFileClip(output_gif_path)
64
+ out_video.write_videofile(output_mp4_path)
65
+ del out, render
66
+
67
+ elif method == 'fast':
68
+ output_gif_path = output_mp4_path[:-4] + '.gif'
69
+ if len(data.shape) == 3:
70
+ data = data[None]
71
+ if isinstance(data, torch.Tensor):
72
+ data = data.cpu().numpy()
73
+ pose_vis = plot_3d.draw_to_batch(data, [''], [output_gif_path])
74
+ out_video = mp.VideoFileClip(output_gif_path)
75
+ out_video.write_videofile(output_mp4_path)
76
+ del pose_vis