cbensimon HF Staff commited on
Commit
1017ac0
·
1 Parent(s): 1e98a9a
Files changed (3) hide show
  1. app.py +13 -10
  2. optimization.py +5 -3
  3. optimization_utils.py +18 -18
app.py CHANGED
@@ -54,24 +54,27 @@ default_prompt_i2v = "make this image come alive, cinematic motion, smooth anima
54
  default_negative_prompt = "Bright tones, overexposed, static, blurred details, subtitles, style, works, paintings, images, static, overall gray, worst quality, low quality, JPEG compression residue, ugly, incomplete, extra fingers, poorly drawn hands, poorly drawn faces, deformed, disfigured, misshapen limbs, fused fingers, still picture, messy background, three legs, many people in the background, walking backwards, watermark, text, signature"
55
 
56
 
57
- def fit_to_480p(image: Image.Image) -> Image.Image:
 
 
 
 
 
 
 
 
58
  target_aspect = LANDSCAPE_WIDTH / LANDSCAPE_HEIGHT
59
  width, height = image.size
60
  in_aspect = width / height
61
  if in_aspect > target_aspect:
62
- new_width = int(height * target_aspect)
63
  left = (width - new_width) // 2
64
  image = image.crop((left, 0, left + new_width, height))
65
  else:
66
- new_height = int(width / target_aspect)
67
  top = (height - new_height) // 2
68
  image = image.crop((0, top, width, top + new_height))
69
- target_width, target_height = (
70
- (LANDSCAPE_WIDTH, LANDSCAPE_HEIGHT)
71
- if in_aspect > target_aspect else
72
- (LANDSCAPE_HEIGHT, LANDSCAPE_WIDTH)
73
- )
74
- return image.resize((target_width, target_height), Image.LANCZOS)
75
 
76
  def get_duration(
77
  input_image,
@@ -147,7 +150,7 @@ def generate_video(
147
 
148
  num_frames = np.clip(int(round(duration_seconds * FIXED_FPS)), MIN_FRAMES_MODEL, MAX_FRAMES_MODEL)
149
  current_seed = random.randint(0, MAX_SEED) if randomize_seed else int(seed)
150
- resized_image = fit_to_480p(input_image)
151
 
152
  output_frames_list = pipe(
153
  image=resized_image,
 
54
  default_negative_prompt = "Bright tones, overexposed, static, blurred details, subtitles, style, works, paintings, images, static, overall gray, worst quality, low quality, JPEG compression residue, ugly, incomplete, extra fingers, poorly drawn hands, poorly drawn faces, deformed, disfigured, misshapen limbs, fused fingers, still picture, messy background, three legs, many people in the background, walking backwards, watermark, text, signature"
55
 
56
 
57
+ def resize_image(image: Image.Image) -> Image.Image:
58
+ if image.height > image.width:
59
+ transposed = image.transpose(Image.Transpose.ROTATE_90)
60
+ resized = resize_image_landscape(transposed)
61
+ return resized.transpose(Image.Transpose.ROTATE_270)
62
+ return resize_image_landscape(image)
63
+
64
+
65
+ def resize_image_landscape(image: Image.Image) -> Image.Image:
66
  target_aspect = LANDSCAPE_WIDTH / LANDSCAPE_HEIGHT
67
  width, height = image.size
68
  in_aspect = width / height
69
  if in_aspect > target_aspect:
70
+ new_width = round(height * target_aspect)
71
  left = (width - new_width) // 2
72
  image = image.crop((left, 0, left + new_width, height))
73
  else:
74
+ new_height = round(width / target_aspect)
75
  top = (height - new_height) // 2
76
  image = image.crop((0, top, width, top + new_height))
77
+ return image.resize((LANDSCAPE_WIDTH, LANDSCAPE_HEIGHT), Image.LANCZOS)
 
 
 
 
 
78
 
79
  def get_duration(
80
  input_image,
 
150
 
151
  num_frames = np.clip(int(round(duration_seconds * FIXED_FPS)), MIN_FRAMES_MODEL, MAX_FRAMES_MODEL)
152
  current_seed = random.randint(0, MAX_SEED) if randomize_seed else int(seed)
153
+ resized_image = resize_image(input_image)
154
 
155
  output_frames_list = pipe(
156
  image=resized_image,
optimization.py CHANGED
@@ -89,10 +89,12 @@ def optimize_pipeline_(pipeline: Callable[P, Any], *args: P.args, **kwargs: P.kw
89
  compiled_landscape = aoti_compile(exported_landscape, INDUCTOR_CONFIGS)
90
  print('compiled_landscape', -(t0 - (t0 := datetime.now())))
91
 
92
- compiled_portrait = aoti_compile(exported_portrait, INDUCTOR_CONFIGS) # TODO: weights_from=compiled_landscape
93
- compiled_portrait.weights.clear()
94
  print('compiled_portrait', -(t0 - (t0 := datetime.now())))
95
-
 
 
 
96
  return compiled_landscape, compiled_portrait
97
 
98
  compiled_landscape, compiled_portrait = compile_transformer()
 
89
  compiled_landscape = aoti_compile(exported_landscape, INDUCTOR_CONFIGS)
90
  print('compiled_landscape', -(t0 - (t0 := datetime.now())))
91
 
92
+ compiled_portrait = aoti_compile(exported_portrait, INDUCTOR_CONFIGS)
 
93
  print('compiled_portrait', -(t0 - (t0 := datetime.now())))
94
+
95
+ # Avoid weights duplication when serializing back to main process
96
+ compiled_portrait.weights = compiled_landscape.weights
97
+
98
  return compiled_landscape, compiled_portrait
99
 
100
  compiled_landscape, compiled_portrait = compile_transformer()
optimization_utils.py CHANGED
@@ -10,7 +10,6 @@ from unittest.mock import patch
10
  import torch
11
  from torch._inductor.package.package import package_aoti
12
  from torch.export.pt2_archive._package import AOTICompiledModel
13
- from torch.export.pt2_archive._package_weights import TensorProperties
14
  from torch.export.pt2_archive._package_weights import Weights
15
 
16
 
@@ -21,31 +20,31 @@ INDUCTOR_CONFIGS_OVERRIDES = {
21
  }
22
 
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  class ZeroGPUCompiledModel:
25
- def __init__(self, archive_file: torch.types.FileLike, weights: Weights, cuda: bool = False):
26
  self.archive_file = archive_file
27
  self.weights = weights
28
- if cuda:
29
- self.weights_to_cuda_()
30
  self.compiled_model: ContextVar[AOTICompiledModel | None] = ContextVar('compiled_model', default=None)
31
- def weights_to_cuda_(self):
32
- for name in self.weights:
33
- tensor, properties = self.weights.get_weight(name)
34
- self.weights[name] = (tensor.to('cuda'), properties)
35
  def __call__(self, *args, **kwargs):
36
  if (compiled_model := self.compiled_model.get()) is None:
37
- constants_map = {name: value[0] for name, value in self.weights.items()}
38
  compiled_model = cast(AOTICompiledModel, torch._inductor.aoti_load_package(self.archive_file))
39
- compiled_model.load_constants(constants_map, check_full_update=True, user_managed=True)
40
  self.compiled_model.set(compiled_model)
41
  return compiled_model(*args, **kwargs)
42
- def __reduce__(self):
43
- weight_dict: dict[str, tuple[torch.Tensor, TensorProperties]] = {}
44
- for name in self.weights:
45
- tensor, properties = self.weights.get_weight(name)
46
- tensor_ = torch.empty_like(tensor, device='cpu').pin_memory()
47
- weight_dict[name] = (tensor_.copy_(tensor).detach().share_memory_(), properties)
48
- return ZeroGPUCompiledModel, (self.archive_file, Weights(weight_dict), True)
49
 
50
 
51
  def aoti_compile(
@@ -61,7 +60,8 @@ def aoti_compile(
61
  files: list[str | Weights] = [file for file in artifacts if isinstance(file, str)]
62
  package_aoti(archive_file, files)
63
  weights, = (artifact for artifact in artifacts if isinstance(artifact, Weights))
64
- return ZeroGPUCompiledModel(archive_file, weights)
 
65
 
66
 
67
  @contextlib.contextmanager
 
10
  import torch
11
  from torch._inductor.package.package import package_aoti
12
  from torch.export.pt2_archive._package import AOTICompiledModel
 
13
  from torch.export.pt2_archive._package_weights import Weights
14
 
15
 
 
20
  }
21
 
22
 
23
+ class ZeroGPUWeights:
24
+ def __init__(self, constants_map: dict[str, torch.Tensor], to_cuda: bool = False):
25
+ if to_cuda:
26
+ self.constants_map = {name: tensor.to('cuda') for name, tensor in constants_map.items()}
27
+ else:
28
+ self.constants_map = constants_map
29
+ def __reduce__(self):
30
+ constants_map: dict[str, torch.Tensor] = {}
31
+ for name, tensor in self.constants_map.items():
32
+ tensor_ = torch.empty_like(tensor, device='cpu').pin_memory()
33
+ constants_map[name] = tensor_.copy_(tensor).detach().share_memory_()
34
+ return ZeroGPUWeights, (constants_map, True)
35
+
36
+
37
  class ZeroGPUCompiledModel:
38
+ def __init__(self, archive_file: torch.types.FileLike, weights: ZeroGPUWeights):
39
  self.archive_file = archive_file
40
  self.weights = weights
 
 
41
  self.compiled_model: ContextVar[AOTICompiledModel | None] = ContextVar('compiled_model', default=None)
 
 
 
 
42
  def __call__(self, *args, **kwargs):
43
  if (compiled_model := self.compiled_model.get()) is None:
 
44
  compiled_model = cast(AOTICompiledModel, torch._inductor.aoti_load_package(self.archive_file))
45
+ compiled_model.load_constants(self.weights.constants_map, check_full_update=True, user_managed=True)
46
  self.compiled_model.set(compiled_model)
47
  return compiled_model(*args, **kwargs)
 
 
 
 
 
 
 
48
 
49
 
50
  def aoti_compile(
 
60
  files: list[str | Weights] = [file for file in artifacts if isinstance(file, str)]
61
  package_aoti(archive_file, files)
62
  weights, = (artifact for artifact in artifacts if isinstance(artifact, Weights))
63
+ zerogpu_weights = ZeroGPUWeights({name: weights.get_weight(name)[0] for name in weights})
64
+ return ZeroGPUCompiledModel(archive_file, zerogpu_weights)
65
 
66
 
67
  @contextlib.contextmanager