IsshikiHugh commited on
Commit
fc9d64f
Β·
1 Parent(s): 4d80825

feat: init

Browse files
Files changed (10) hide show
  1. .gitignore +1 -0
  2. README.md +5 -4
  3. app.py +5 -6
  4. app/__init__.py +0 -0
  5. app/demo.py +310 -0
  6. app/entry.py +19 -0
  7. app/env.py +23 -0
  8. app/gui.py +32 -0
  9. app/handler.py +97 -0
  10. requirements.txt +46 -0
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ .DS_Store
README.md CHANGED
@@ -1,10 +1,11 @@
1
  ---
2
- title: GV HMR
3
- emoji: 😻
4
- colorFrom: yellow
5
- colorTo: yellow
6
  sdk: gradio
7
  sdk_version: 4.44.0
 
8
  app_file: app.py
9
  pinned: false
10
  ---
 
1
  ---
2
+ title: GV-HMR
3
+ emoji: πŸ’ƒ
4
+ colorFrom: pink
5
+ colorTo: blue
6
  sdk: gradio
7
  sdk_version: 4.44.0
8
+ python_version: 3.10
9
  app_file: app.py
10
  pinned: false
11
  ---
app.py CHANGED
@@ -1,7 +1,6 @@
1
- import gradio as gr
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
5
-
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
- demo.launch()
 
1
+ import os
2
+ from app.env import prepare_env
3
 
4
+ if __name__ == '__main__':
5
+ prepare_env()
6
+ os.system('python app/entry.py')
 
 
app/__init__.py ADDED
File without changes
app/demo.py ADDED
@@ -0,0 +1,310 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import torch
3
+ import pytorch_lightning as pl
4
+ import numpy as np
5
+ import argparse
6
+ from hmr4d.utils.pylogger import Log
7
+ import hydra
8
+ from hydra import initialize_config_module, compose
9
+ from pathlib import Path
10
+ from pytorch3d.transforms import quaternion_to_matrix
11
+
12
+ from hmr4d.configs import register_store_gvhmr
13
+ from hmr4d.utils.video_io_utils import (
14
+ get_video_lwh,
15
+ read_video_np,
16
+ save_video,
17
+ merge_videos_horizontal,
18
+ get_writer,
19
+ get_video_reader,
20
+ )
21
+ from hmr4d.utils.vis.cv2_utils import draw_bbx_xyxy_on_image_batch, draw_coco17_skeleton_batch
22
+
23
+ from hmr4d.utils.preproc import Tracker, Extractor, VitPoseExtractor, SLAMModel
24
+
25
+ from hmr4d.utils.geo.hmr_cam import get_bbx_xys_from_xyxy, estimate_K, convert_K_to_K4, create_camera_sensor
26
+ from hmr4d.utils.geo_transform import compute_cam_angvel
27
+ from hmr4d.model.gvhmr.gvhmr_pl_demo import DemoPL
28
+ from hmr4d.utils.net_utils import detach_to_cpu, to_cuda
29
+ from hmr4d.utils.smplx_utils import make_smplx
30
+ from hmr4d.utils.vis.renderer import Renderer, get_global_cameras_static, get_ground_params_from_points
31
+ from tqdm import tqdm
32
+ from hmr4d.utils.geo_transform import apply_T_on_points, compute_T_ayfz2ay
33
+ from einops import einsum, rearrange
34
+
35
+
36
+ CRF = 23 # 17 is lossless, every +6 halves the mp4 size
37
+
38
+
39
+ def parse_args_to_cfg():
40
+ # Put all args to cfg
41
+ parser = argparse.ArgumentParser()
42
+ parser.add_argument("--video", type=str, default="inputs/demo/dance_3.mp4")
43
+ parser.add_argument("--output_root", type=str, default=None, help="by default to outputs/demo")
44
+ parser.add_argument("-s", "--static_cam", action="store_true", help="If true, skip DPVO")
45
+ parser.add_argument("--verbose", action="store_true", help="If true, draw intermediate results")
46
+ args = parser.parse_args()
47
+
48
+ # Input
49
+ video_path = Path(args.video)
50
+ assert video_path.exists(), f"Video not found at {video_path}"
51
+ length, width, height = get_video_lwh(video_path)
52
+ Log.info(f"[Input]: {video_path}")
53
+ Log.info(f"(L, W, H) = ({length}, {width}, {height})")
54
+ # Cfg
55
+ with initialize_config_module(version_base="1.3", config_module=f"hmr4d.configs"):
56
+ overrides = [
57
+ f"video_name={video_path.stem}",
58
+ f"static_cam={args.static_cam}",
59
+ f"verbose={args.verbose}",
60
+ ]
61
+
62
+ # Allow to change output root
63
+ if args.output_root is not None:
64
+ overrides.append(f"output_root={args.output_root}")
65
+ register_store_gvhmr()
66
+ cfg = compose(config_name="demo", overrides=overrides)
67
+
68
+ # Output
69
+ Log.info(f"[Output Dir]: {cfg.output_dir}")
70
+ Path(cfg.output_dir).mkdir(parents=True, exist_ok=True)
71
+ Path(cfg.preprocess_dir).mkdir(parents=True, exist_ok=True)
72
+
73
+ # Copy raw-input-video to video_path
74
+ Log.info(f"[Copy Video] {video_path} -> {cfg.video_path}")
75
+ if not Path(cfg.video_path).exists() or get_video_lwh(video_path)[0] != get_video_lwh(cfg.video_path)[0]:
76
+ reader = get_video_reader(video_path)
77
+ writer = get_writer(cfg.video_path, fps=30, crf=CRF)
78
+ for img in tqdm(reader, total=get_video_lwh(video_path)[0], desc=f"Copy"):
79
+ writer.write_frame(img)
80
+ writer.close()
81
+ reader.close()
82
+
83
+ return cfg
84
+
85
+
86
+ @torch.no_grad()
87
+ def run_preprocess(cfg):
88
+ Log.info(f"[Preprocess] Start!")
89
+ tic = Log.time()
90
+ video_path = cfg.video_path
91
+ paths = cfg.paths
92
+ static_cam = cfg.static_cam
93
+ verbose = cfg.verbose
94
+
95
+ # Get bbx tracking result
96
+ if not Path(paths.bbx).exists():
97
+ tracker = Tracker()
98
+ bbx_xyxy = tracker.get_one_track(video_path).float() # (L, 4)
99
+ bbx_xys = get_bbx_xys_from_xyxy(bbx_xyxy, base_enlarge=1.2).float() # (L, 3) apply aspect ratio and enlarge
100
+ torch.save({"bbx_xyxy": bbx_xyxy, "bbx_xys": bbx_xys}, paths.bbx)
101
+ del tracker
102
+ else:
103
+ bbx_xys = torch.load(paths.bbx)["bbx_xys"]
104
+ Log.info(f"[Preprocess] bbx (xyxy, xys) from {paths.bbx}")
105
+ if verbose:
106
+ video = read_video_np(video_path)
107
+ bbx_xyxy = torch.load(paths.bbx)["bbx_xyxy"]
108
+ video_overlay = draw_bbx_xyxy_on_image_batch(bbx_xyxy, video)
109
+ save_video(video_overlay, cfg.paths.bbx_xyxy_video_overlay)
110
+
111
+ # Get VitPose
112
+ if not Path(paths.vitpose).exists():
113
+ vitpose_extractor = VitPoseExtractor()
114
+ vitpose = vitpose_extractor.extract(video_path, bbx_xys)
115
+ torch.save(vitpose, paths.vitpose)
116
+ del vitpose_extractor
117
+ else:
118
+ vitpose = torch.load(paths.vitpose)
119
+ Log.info(f"[Preprocess] vitpose from {paths.vitpose}")
120
+ if verbose:
121
+ video = read_video_np(video_path)
122
+ video_overlay = draw_coco17_skeleton_batch(video, vitpose, 0.5)
123
+ save_video(video_overlay, paths.vitpose_video_overlay)
124
+
125
+ # Get vit features
126
+ if not Path(paths.vit_features).exists():
127
+ extractor = Extractor()
128
+ vit_features = extractor.extract_video_features(video_path, bbx_xys)
129
+ torch.save(vit_features, paths.vit_features)
130
+ del extractor
131
+ else:
132
+ Log.info(f"[Preprocess] vit_features from {paths.vit_features}")
133
+
134
+ # Get DPVO results
135
+ if not static_cam: # use slam to get cam rotation
136
+ if not Path(paths.slam).exists():
137
+ length, width, height = get_video_lwh(cfg.video_path)
138
+ K_fullimg = estimate_K(width, height)
139
+ intrinsics = convert_K_to_K4(K_fullimg)
140
+ slam = SLAMModel(video_path, width, height, intrinsics, buffer=4000, resize=0.5)
141
+ bar = tqdm(total=length, desc="DPVO")
142
+ while True:
143
+ ret = slam.track()
144
+ if ret:
145
+ bar.update()
146
+ else:
147
+ break
148
+ slam_results = slam.process() # (L, 7), numpy
149
+ torch.save(slam_results, paths.slam)
150
+ else:
151
+ Log.info(f"[Preprocess] slam results from {paths.slam}")
152
+
153
+ Log.info(f"[Preprocess] End. Time elapsed: {Log.time()-tic:.2f}s")
154
+
155
+
156
+ def load_data_dict(cfg):
157
+ paths = cfg.paths
158
+ length, width, height = get_video_lwh(cfg.video_path)
159
+ if cfg.static_cam:
160
+ R_w2c = torch.eye(3).repeat(length, 1, 1)
161
+ else:
162
+ traj = torch.load(cfg.paths.slam)
163
+ traj_quat = torch.from_numpy(traj[:, [6, 3, 4, 5]])
164
+ R_w2c = quaternion_to_matrix(traj_quat).mT
165
+ K_fullimg = estimate_K(width, height).repeat(length, 1, 1)
166
+ # K_fullimg = create_camera_sensor(width, height, 26)[2].repeat(length, 1, 1)
167
+
168
+ data = {
169
+ "length": torch.tensor(length),
170
+ "bbx_xys": torch.load(paths.bbx)["bbx_xys"],
171
+ "kp2d": torch.load(paths.vitpose),
172
+ "K_fullimg": K_fullimg,
173
+ "cam_angvel": compute_cam_angvel(R_w2c),
174
+ "f_imgseq": torch.load(paths.vit_features),
175
+ }
176
+ return data
177
+
178
+
179
+ def render_incam(cfg):
180
+ incam_video_path = Path(cfg.paths.incam_video)
181
+ if incam_video_path.exists():
182
+ Log.info(f"[Render Incam] Video already exists at {incam_video_path}")
183
+ return
184
+
185
+ pred = torch.load(cfg.paths.hmr4d_results)
186
+ smplx = make_smplx("supermotion").cuda()
187
+ smplx2smpl = torch.load("hmr4d/utils/body_model/smplx2smpl_sparse.pt").cuda()
188
+ faces_smpl = make_smplx("smpl").faces
189
+
190
+ # smpl
191
+ smplx_out = smplx(**to_cuda(pred["smpl_params_incam"]))
192
+ pred_c_verts = torch.stack([torch.matmul(smplx2smpl, v_) for v_ in smplx_out.vertices])
193
+
194
+ # -- rendering code -- #
195
+ video_path = cfg.video_path
196
+ length, width, height = get_video_lwh(video_path)
197
+ K = pred["K_fullimg"][0]
198
+
199
+ # renderer
200
+ renderer = Renderer(width, height, device="cuda", faces=faces_smpl, K=K)
201
+ reader = get_video_reader(video_path) # (F, H, W, 3), uint8, numpy
202
+ bbx_xys_render = torch.load(cfg.paths.bbx)["bbx_xys"]
203
+
204
+ # -- render mesh -- #
205
+ verts_incam = pred_c_verts
206
+ writer = get_writer(incam_video_path, fps=30, crf=CRF)
207
+ for i, img_raw in tqdm(enumerate(reader), total=get_video_lwh(video_path)[0], desc=f"Rendering Incam"):
208
+ img = renderer.render_mesh(verts_incam[i].cuda(), img_raw, [0.8, 0.8, 0.8])
209
+
210
+ # # bbx
211
+ # bbx_xys_ = bbx_xys_render[i].cpu().numpy()
212
+ # lu_point = (bbx_xys_[:2] - bbx_xys_[2:] / 2).astype(int)
213
+ # rd_point = (bbx_xys_[:2] + bbx_xys_[2:] / 2).astype(int)
214
+ # img = cv2.rectangle(img, lu_point, rd_point, (255, 178, 102), 2)
215
+
216
+ writer.write_frame(img)
217
+ writer.close()
218
+ reader.close()
219
+
220
+
221
+ def render_global(cfg):
222
+ global_video_path = Path(cfg.paths.global_video)
223
+ if global_video_path.exists():
224
+ Log.info(f"[Render Global] Video already exists at {global_video_path}")
225
+ return
226
+
227
+ debug_cam = False
228
+ pred = torch.load(cfg.paths.hmr4d_results)
229
+ smplx = make_smplx("supermotion").cuda()
230
+ smplx2smpl = torch.load("hmr4d/utils/body_model/smplx2smpl_sparse.pt").cuda()
231
+ faces_smpl = make_smplx("smpl").faces
232
+ J_regressor = torch.load("hmr4d/utils/body_model/smpl_neutral_J_regressor.pt").cuda()
233
+
234
+ # smpl
235
+ smplx_out = smplx(**to_cuda(pred["smpl_params_global"]))
236
+ pred_ay_verts = torch.stack([torch.matmul(smplx2smpl, v_) for v_ in smplx_out.vertices])
237
+
238
+ def move_to_start_point_face_z(verts):
239
+ "XZ to origin, Start from the ground, Face-Z"
240
+ # position
241
+ verts = verts.clone() # (L, V, 3)
242
+ offset = einsum(J_regressor, verts[0], "j v, v i -> j i")[0] # (3)
243
+ offset[1] = verts[:, :, [1]].min()
244
+ verts = verts - offset
245
+ # face direction
246
+ T_ay2ayfz = compute_T_ayfz2ay(einsum(J_regressor, verts[[0]], "j v, l v i -> l j i"), inverse=True)
247
+ verts = apply_T_on_points(verts, T_ay2ayfz)
248
+ return verts
249
+
250
+ verts_glob = move_to_start_point_face_z(pred_ay_verts)
251
+ joints_glob = einsum(J_regressor, verts_glob, "j v, l v i -> l j i") # (L, J, 3)
252
+ global_R, global_T, global_lights = get_global_cameras_static(
253
+ verts_glob.cpu(),
254
+ beta=2.0,
255
+ cam_height_degree=20,
256
+ target_center_height=1.0,
257
+ )
258
+
259
+ # -- rendering code -- #
260
+ video_path = cfg.video_path
261
+ length, width, height = get_video_lwh(video_path)
262
+ _, _, K = create_camera_sensor(width, height, 24) # render as 24mm lens
263
+
264
+ # renderer
265
+ renderer = Renderer(width, height, device="cuda", faces=faces_smpl, K=K)
266
+ # renderer = Renderer(width, height, device="cuda", faces=faces_smpl, K=K, bin_size=0)
267
+
268
+ # -- render mesh -- #
269
+ scale, cx, cz = get_ground_params_from_points(joints_glob[:, 0], verts_glob)
270
+ renderer.set_ground(scale * 1.5, cx, cz)
271
+ color = torch.ones(3).float().cuda() * 0.8
272
+
273
+ render_length = length if not debug_cam else 8
274
+ writer = get_writer(global_video_path, fps=30, crf=CRF)
275
+ for i in tqdm(range(render_length), desc=f"Rendering Global"):
276
+ cameras = renderer.create_camera(global_R[i], global_T[i])
277
+ img = renderer.render_with_ground(verts_glob[[i]], color[None], cameras, global_lights)
278
+ writer.write_frame(img)
279
+ writer.close()
280
+
281
+
282
+ if __name__ == "__main__":
283
+ cfg = parse_args_to_cfg()
284
+ paths = cfg.paths
285
+ Log.info(f"[GPU]: {torch.cuda.get_device_name()}")
286
+ Log.info(f'[GPU]: {torch.cuda.get_device_properties("cuda")}')
287
+
288
+ # ===== Preprocess and save to disk ===== #
289
+ run_preprocess(cfg)
290
+ data = load_data_dict(cfg)
291
+
292
+ # ===== HMR4D ===== #
293
+ if not Path(paths.hmr4d_results).exists():
294
+ Log.info("[HMR4D] Predicting")
295
+ model: DemoPL = hydra.utils.instantiate(cfg.model, _recursive_=False)
296
+ model.load_pretrained_model(cfg.ckpt_path)
297
+ model = model.eval().cuda()
298
+ tic = Log.sync_time()
299
+ pred = model.predict(data, static_cam=cfg.static_cam)
300
+ pred = detach_to_cpu(pred)
301
+ data_time = data["length"] / 30
302
+ Log.info(f"[HMR4D] Elapsed: {Log.sync_time() - tic:.2f}s for data-length={data_time:.1f}s")
303
+ torch.save(pred, paths.hmr4d_results)
304
+
305
+ # ===== Render ===== #
306
+ render_incam(cfg)
307
+ render_global(cfg)
308
+ if not Path(paths.incam_global_horiz_video).exists():
309
+ Log.info("[Merge Videos]")
310
+ merge_videos_horizontal([paths.incam_video, paths.global_video], paths.incam_global_horiz_video)
app/entry.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+
3
+ from app.env import prepare_env
4
+ from app.gui import get_inputs_components, get_outputs_components, get_examples
5
+ from app.handler import handler
6
+
7
+
8
+ if __name__ == '__main__':
9
+ prepare_env()
10
+
11
+ demo = gr.Interface(
12
+ fn = handler,
13
+ inputs = get_inputs_components(),
14
+ outputs = get_outputs_components(),
15
+ # examples = get_examples(),
16
+ allow_flagging = 'never',
17
+ )
18
+
19
+ demo.launch()
app/env.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ REPO_ROOT = str(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
4
+
5
+ def run_cmds(cmds):
6
+ cmds = cmds.split('\n')
7
+ for cmd in cmds:
8
+ if len(cmd) == 0:
9
+ continue
10
+ os.system(cmd)
11
+
12
+
13
+ def prepare_env():
14
+ os.chdir(REPO_ROOT)
15
+ run_cmds(
16
+ f'''
17
+ git clone https://github.com/zju3dv/GVHMR --recursive
18
+ pip install -e .
19
+ mkdir inputs
20
+ mkdir outputs
21
+ ln -s {REPO_ROOT}/GVHMR/tools ./app/
22
+ '''
23
+ )
app/gui.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+
3
+
4
+ def get_inputs_components():
5
+ return [
6
+ gr.Video(
7
+ label = 'INPUT VIDEO',
8
+ show_label = True,
9
+ ),
10
+ gr.Radio(
11
+ choices = ['Static Camera', 'Dynamic Camera'],
12
+ label = 'Camera Status',
13
+ info = 'If the camera is static, DPVO will be skipped.'),
14
+ ]
15
+
16
+
17
+ def get_outputs_components():
18
+ return [
19
+ gr.PlayableVideo(
20
+ label = 'INCAM RESULT',
21
+ show_label = True,
22
+ ),
23
+ gr.PlayableVideo(
24
+ label = 'GLOBAL RESULT',
25
+ show_label = True,
26
+ ),
27
+ ]
28
+
29
+
30
+ def get_examples():
31
+ # TODO: Add examples.
32
+ return []
app/handler.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import spaces
2
+ import gradio as gr
3
+
4
+ from .demo import *
5
+
6
+
7
+ def prepare_cfg(is_static:bool, video_path:str, demo_id:str):
8
+ output_root = Path(video_path).parent / 'output'
9
+ output_root = str(output_root.absolute())
10
+
11
+ # Cfg
12
+ with initialize_config_module(version_base="1.3", config_module=f"hmr4d.configs"):
13
+ overrides = [
14
+ f"video_name={demo_id}",
15
+ f"static_cam={is_static}",
16
+ f"verbose={False}",
17
+ ]
18
+
19
+ # Allow to change output root
20
+ overrides.append(f"output_root={output_root}")
21
+ register_store_gvhmr()
22
+ cfg = compose(config_name="demo", overrides=overrides)
23
+
24
+ # Output
25
+ Log.info(f"[Output Dir]: {cfg.output_dir}")
26
+ Path(cfg.output_dir).mkdir(parents=True, exist_ok=True)
27
+ Path(cfg.preprocess_dir).mkdir(parents=True, exist_ok=True)
28
+
29
+ # Copy raw-input-video to video_path
30
+ Log.info(f"[Copy Video] {video_path} -> {cfg.video_path}")
31
+ if not Path(cfg.video_path).exists() or get_video_lwh(video_path)[0] != get_video_lwh(cfg.video_path)[0]:
32
+ reader = get_video_reader(video_path)
33
+ writer = get_writer(cfg.video_path, fps=30, crf=CRF)
34
+ for img in tqdm(reader, total=get_video_lwh(video_path)[0], desc=f"Copy"):
35
+ writer.write_frame(img)
36
+ writer.close()
37
+ reader.close()
38
+
39
+ return cfg
40
+
41
+
42
+ @spaces.GPU(duration=120)
43
+ def run_demo(cfg, progress):
44
+ paths = cfg.paths
45
+ Log.info(f"[GPU]: {torch.cuda.get_device_name()}")
46
+ Log.info(f'[GPU]: {torch.cuda.get_device_properties("cuda")}')
47
+
48
+ # ===== Preprocess and save to disk ===== #
49
+ run_preprocess(cfg)
50
+ data = load_data_dict(cfg)
51
+
52
+ # ===== HMR4D ===== #
53
+ if not Path(paths.hmr4d_results).exists():
54
+ Log.info("[HMR4D] Predicting")
55
+ model: DemoPL = hydra.utils.instantiate(cfg.model, _recursive_=False)
56
+ model.load_pretrained_model(cfg.ckpt_path)
57
+ model = model.eval().cuda()
58
+ tic = Log.sync_time()
59
+ pred = model.predict(data, static_cam=cfg.static_cam)
60
+ pred = detach_to_cpu(pred)
61
+ data_time = data["length"] / 30
62
+ Log.info(f"[HMR4D] Elapsed: {Log.sync_time() - tic:.2f}s for data-length={data_time:.1f}s")
63
+ torch.save(pred, paths.hmr4d_results)
64
+
65
+ # ===== Render ===== #
66
+ render_incam(cfg)
67
+ render_global(cfg)
68
+ if not Path(paths.incam_global_horiz_video).exists():
69
+ Log.info("[Merge Videos]")
70
+ merge_videos_horizontal([paths.incam_video, paths.global_video], paths.incam_global_horiz_video)
71
+
72
+ return
73
+
74
+ def handler(cam_status, video_path, progress=gr.Progress()):
75
+ # 0. Check validity of inputs.
76
+ if cam_status not in ['Static Camera', 'Dynamic Camera']:
77
+ raise gr.Error('Please define the camera status!', duration=5)
78
+ if video_path is None or not Path(video_path).exists():
79
+ raise gr.Error('Can not find the video!', duration=5)
80
+
81
+ # 1. Deal with APP inputs.
82
+ is_static = cam_status == 'Static Camera'
83
+ Log.info(f"[Input Args] is_static: {is_static}")
84
+ Log.info(f"[Input Args] video_path: {video_path}")
85
+
86
+ # 2. Prepare cfg.
87
+ Log.info(f"[Video]: {video_path}")
88
+ demo_id = f'{Path(video_path).stem}_{np.random.randint(0, 1024):04d}'
89
+ cfg = prepare_cfg(is_static, video_path, demo_id)
90
+
91
+ # 3. Run demo.
92
+ run_demo(cfg, progress)
93
+ from ipdb import set_trace
94
+ set_trace()
95
+
96
+ # 4. Prepare the output.
97
+ return cfg.paths.incam_video, cfg.paths.global_video
requirements.txt ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # PyTorch
2
+ --extra-index-url https://download.pytorch.org/whl/cu121
3
+ torch==2.3.0+cu121
4
+ torchvision==0.18.0+cu121
5
+ timm==0.9.12 # For HMR2.0a feature extraction
6
+
7
+ # Lightning + Hydra
8
+ lightning==2.3.0
9
+ hydra-core==1.3
10
+ hydra-zen
11
+ hydra_colorlog
12
+ rich
13
+
14
+ # Common utilities
15
+ numpy==1.23.5
16
+ jupyter
17
+ matplotlib
18
+ ipdb
19
+ setuptools>=68.0
20
+ black
21
+ tensorboardX
22
+ opencv-python
23
+ ffmpeg-python
24
+ scikit-image
25
+ termcolor
26
+ einops
27
+ imageio==2.34.1
28
+ av # imageio[pyav], improved performance over imageio[ffmpeg]
29
+ joblib
30
+
31
+ # Diffusion
32
+ # diffusers[torch]==0.19.3
33
+ # transformers==4.31.0
34
+
35
+ # 3D-Vision
36
+ pytorch3d @ https://dl.fbaipublicfiles.com/pytorch3d/packaging/wheels/py310_cu121_pyt230/pytorch3d-0.7.6-cp310-cp310-linux_x86_64.whl
37
+ trimesh
38
+ chumpy
39
+ smplx
40
+ # open3d==0.17.0
41
+ wis3d
42
+
43
+ # 2D-Pose
44
+ ultralytics==8.2.42 # YOLO
45
+ cython_bbox
46
+ lapx