huaichang commited on
Commit
10aeeff
·
verified ·
1 Parent(s): c627483

Delete pose2vid_offline.py

Browse files
Files changed (1) hide show
  1. pose2vid_offline.py +0 -254
pose2vid_offline.py DELETED
@@ -1,254 +0,0 @@
1
- import argparse
2
- import os
3
- import sys
4
- from datetime import datetime
5
- import mediapipe as mp
6
- import numpy as np
7
- import cv2
8
- import torch
9
- from skimage.transform import resize
10
- from diffusers import AutoencoderKLTemporalDecoder, AutoencoderKL, AutoencoderTiny
11
- from src.scheduler.scheduler_ddim import DDIMScheduler
12
- import random
13
- from omegaconf import OmegaConf
14
- from PIL import Image
15
- from torchvision import transforms
16
- from transformers import CLIPVisionModelWithProjection
17
- from src.models.unet_2d_condition import UNet2DConditionModel
18
- from src.models.unet_3d import UNet3DConditionModel
19
- from src.pipelines.pipeline_pose2vid import Pose2VideoPipeline
20
- from src.utils.util import save_videos_grid, crop_face
21
- from decord import VideoReader
22
- from diffusers.utils.import_utils import is_xformers_available
23
-
24
- from src.models.motion_encoder.encoder import MotEncoder
25
- from src.liveportrait.motion_extractor import MotionExtractor
26
- from src.models.pose_guider import PoseGuider
27
- from tqdm import tqdm
28
-
29
- def parse_args():
30
- parser = argparse.ArgumentParser()
31
- parser.add_argument("--config", type=str, default='configs/prompts/personalive_offline.yaml')
32
- parser.add_argument("--name", type=str, default='personalive_offline')
33
- parser.add_argument("-W", type=int, default=512)
34
- parser.add_argument("-H", type=int, default=512)
35
- parser.add_argument("-L", type=int, default=1500)
36
- parser.add_argument("--seed", type=int, default=42)
37
- parser.add_argument("--device", type=str, default="cuda")
38
- args = parser.parse_args()
39
-
40
- return args
41
-
42
- def main(args):
43
- device = args.device
44
- print('device', device)
45
- config = OmegaConf.load(args.config)
46
-
47
- if config.weight_dtype == "fp16":
48
- weight_dtype = torch.float16
49
- else:
50
- weight_dtype = torch.float32
51
-
52
- vae = AutoencoderKL.from_pretrained(config.vae_path).to(device, dtype=weight_dtype)
53
- # if use tiny VAE
54
- # vae_tiny = AutoencoderTiny.from_pretrained(config.vae_tiny_path).to(device, dtype=weight_dtype)
55
-
56
- infer_config = OmegaConf.load(config.inference_config)
57
- reference_unet = UNet2DConditionModel.from_pretrained(
58
- config.pretrained_base_model_path,
59
- subfolder="unet",
60
- ).to(device=device, dtype=weight_dtype)
61
- denoising_unet = UNet3DConditionModel.from_pretrained_2d(
62
- config.pretrained_base_model_path,
63
- "",
64
- subfolder="unet",
65
- unet_additional_kwargs=infer_config.unet_additional_kwargs,
66
- ).to(dtype=weight_dtype, device=device)
67
-
68
- motion_encoder = MotEncoder().to(dtype=weight_dtype, device=device).eval()
69
- pose_guider = PoseGuider().to(device=device, dtype=weight_dtype)
70
- pose_encoder = MotionExtractor(num_kp=21).to(device=device, dtype=weight_dtype).eval()
71
-
72
- image_enc = CLIPVisionModelWithProjection.from_pretrained(
73
- config.image_encoder_path
74
- ).to(dtype=weight_dtype, device=device)
75
-
76
- sched_kwargs = OmegaConf.to_container(
77
- OmegaConf.load(config.inference_config).noise_scheduler_kwargs
78
- )
79
- scheduler = DDIMScheduler(**sched_kwargs)
80
-
81
- generator = torch.manual_seed(args.seed)
82
- width, height = args.W, args.H
83
-
84
- # load pretrained weights
85
- denoising_unet.load_state_dict(
86
- torch.load(config.denoising_unet_path, map_location="cpu"), strict=False
87
- )
88
- reference_unet.load_state_dict(
89
- torch.load(
90
- config.denoising_unet_path.replace('denoising_unet', 'reference_unet'),
91
- map_location="cpu",
92
- ),
93
- strict=True,
94
- )
95
- motion_encoder.load_state_dict(
96
- torch.load(
97
- config.denoising_unet_path.replace('denoising_unet', 'motion_encoder'),
98
- map_location="cpu",
99
- ),
100
- strict=True,
101
- )
102
- pose_guider.load_state_dict(
103
- torch.load(
104
- config.denoising_unet_path.replace('denoising_unet', 'pose_guider'),
105
- map_location="cpu",
106
- ),
107
- strict=True,
108
- )
109
- denoising_unet.load_state_dict(
110
- torch.load(
111
- config.denoising_unet_path.replace('denoising_unet', 'temporal_module'),
112
- map_location="cpu",
113
- ),
114
- strict=False,
115
- )
116
- pose_encoder.load_state_dict(
117
- torch.load(
118
- config.denoising_unet_path.replace('denoising_unet', 'motion_extractor'),
119
- map_location="cpu",
120
- ),
121
- strict=False,
122
- )
123
-
124
- if is_xformers_available():
125
- reference_unet.enable_xformers_memory_efficient_attention()
126
- denoising_unet.enable_xformers_memory_efficient_attention()
127
- else:
128
- raise ValueError(
129
- "xformers is not available. Make sure it is installed correctly"
130
- )
131
-
132
- mp_face_mesh = mp.solutions.face_mesh
133
- face_mesh = mp_face_mesh.FaceMesh(static_image_mode=True, max_num_faces=1)
134
-
135
- pipe = Pose2VideoPipeline(
136
- vae=vae,
137
- # vae_tiny=vae_tiny,
138
- image_encoder=image_enc,
139
- reference_unet=reference_unet,
140
- denoising_unet=denoising_unet,
141
- motion_encoder=motion_encoder,
142
- pose_encoder=pose_encoder,
143
- pose_guider=pose_guider,
144
- scheduler=scheduler,
145
- )
146
- pipe = pipe.to(device)
147
-
148
- date_str = datetime.now().strftime("%Y%m%d")
149
- if args.name is None:
150
- time_str = datetime.now().strftime("%H%M")
151
- save_dir_name = f"{date_str}--{time_str}"
152
- else:
153
- save_dir_name = f"{date_str}--{args.name}"
154
- save_vid_dir = os.path.join('results', save_dir_name, 'concat_vid')
155
- os.makedirs(save_vid_dir, exist_ok=True)
156
- save_split_vid_dir = os.path.join('results', save_dir_name, 'split_vid')
157
- os.makedirs(save_split_vid_dir, exist_ok=True)
158
-
159
- pose_transform = transforms.Compose(
160
- [transforms.Resize((height, width)), transforms.ToTensor()]
161
- )
162
-
163
- args.test_cases = OmegaConf.load(args.config)["test_cases"]
164
-
165
- for ref_image_path in list(args.test_cases.keys()):
166
- for pose_video_path in args.test_cases[ref_image_path]:
167
- video_name = os.path.basename(pose_video_path).split(".")[0]
168
- source_name = os.path.basename(ref_image_path).split(".")[0]
169
-
170
- vid_name = f"{source_name}_{video_name}.mp4"
171
- save_vid_path = os.path.join(save_vid_dir, vid_name)
172
- print(save_vid_path)
173
- if os.path.exists(save_vid_path):
174
- continue
175
-
176
- if ref_image_path.endswith('.mp4'):
177
- src_vid = VideoReader(ref_image_path)
178
- ref_img = src_vid[0].asnumpy()
179
- ref_img = Image.fromarray(ref_img).convert("RGB")
180
- else:
181
- ref_img = Image.open(ref_image_path).convert("RGB")
182
-
183
- control = VideoReader(pose_video_path)
184
- video_length = min(len(control) // 4 * 4, args.L)
185
- sel_idx = range(len(control))[:video_length]
186
- control = control.get_batch([sel_idx]).asnumpy() # N, H, W, C
187
-
188
- ref_image_pil = ref_img.copy()
189
- ref_patch = crop_face(ref_image_pil, face_mesh)
190
- ref_face_pil = Image.fromarray(ref_patch).convert("RGB")
191
-
192
- size = args.H
193
- generator = torch.Generator(device=device)
194
- generator.manual_seed(42)
195
-
196
- dri_faces = []
197
- ori_pose_images = []
198
- for idx_control, pose_image_pil in tqdm(enumerate(control[:video_length]), total=video_length, desc='cropping faces'):
199
- pose_image_pil = Image.fromarray(pose_image_pil).convert("RGB")
200
- ori_pose_images.append(pose_image_pil)
201
- dri_face = crop_face(pose_image_pil, face_mesh)
202
- dri_face_pil = Image.fromarray(dri_face).convert("RGB")
203
- dri_faces.append(dri_face_pil)
204
-
205
- face_tensor_list = []
206
- ori_pose_tensor_list = []
207
- ref_tensor_list = []
208
-
209
- for idx, pose_image_pil in enumerate(ori_pose_images):
210
- face_tensor_list.append(pose_transform(dri_faces[idx]))
211
- ori_pose_tensor_list.append(pose_transform(pose_image_pil))
212
- ref_tensor_list.append(pose_transform(ref_image_pil))
213
-
214
- ref_tensor = torch.stack(ref_tensor_list, dim=0) # (f, c, h, w)
215
- ref_tensor = ref_tensor.transpose(0, 1).unsqueeze(0) # (c, f, h, w)
216
-
217
- face_tensor = torch.stack(face_tensor_list, dim=0) # (f, c, h, w)
218
- face_tensor = face_tensor.transpose(0, 1).unsqueeze(0)
219
-
220
- ori_pose_tensor = torch.stack(ori_pose_tensor_list, dim=0) # (f, c, h, w)
221
- ori_pose_tensor = ori_pose_tensor.transpose(0, 1).unsqueeze(0)
222
-
223
- gen_video = pipe(
224
- ori_pose_images,
225
- ref_image_pil,
226
- dri_faces,
227
- ref_face_pil,
228
- width,
229
- height,
230
- len(dri_faces),
231
- num_inference_steps=4,
232
- guidance_scale=1.0,
233
- generator=generator,
234
- temporal_window_size = 4,
235
- temporal_adaptive_step = 4,
236
- ).videos
237
-
238
- #Concat it with pose tensor
239
- video = torch.cat([ref_tensor, face_tensor, ori_pose_tensor, gen_video], dim=0)
240
-
241
- save_videos_grid(
242
- video,
243
- save_vid_path,
244
- n_rows=4,
245
- fps=25,
246
- )
247
-
248
- if True:
249
- save_vid_path = save_vid_path.replace(save_vid_dir, save_split_vid_dir)
250
- save_videos_grid(gen_video, save_vid_path, n_rows=1, fps=25, crf=18)
251
-
252
- if __name__ == "__main__":
253
- args = parse_args()
254
- main(args)