Nad54 commited on
Commit
e56bc06
·
verified ·
1 Parent(s): f395223

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -52
app.py CHANGED
@@ -1,9 +1,10 @@
1
  import sys, os
2
  sys.path.append("../")
3
 
4
- # --- anti-fragmentation VRAM : à définir AVANT toute init CUDA / modèles ---
5
  os.environ.setdefault("PYTORCH_CUDA_ALLOC_CONF", "expandable_segments:True")
6
 
 
7
  import spaces
8
  import torch
9
  import random
@@ -36,24 +37,23 @@ ghibli_style_lora_path = hf_hub_download("InstantX/FLUX.1-dev-LoRA-Ghibli", "ghi
36
  onepiece_style_lora_path = os.path.join(os.path.dirname(__file__), "onepiece_flux_v2.safetensors")
37
  ONEPIECE_TRIGGER = "onepiece style"
38
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  # --------------------------------------------
40
  # Init pipeline
41
  # --------------------------------------------
42
  pipe = InstantCharacterFluxPipeline.from_pretrained(base_model, torch_dtype=torch.bfloat16)
43
  pipe.to(device)
44
-
45
- # Offload / slicing / tiling pour réduire les pics VRAM
46
- try:
47
- if hasattr(pipe, "enable_sequential_cpu_offload"):
48
- pipe.enable_sequential_cpu_offload()
49
- if hasattr(pipe, "vae"):
50
- pipe.vae.enable_slicing()
51
- pipe.vae.enable_tiling()
52
- if hasattr(pipe, "enable_attention_slicing"):
53
- pipe.enable_attention_slicing()
54
- except Exception:
55
- pass
56
-
57
  pipe.init_adapter(
58
  image_encoder_path=image_encoder_path,
59
  image_encoder_2_path=image_encoder_2_path,
@@ -61,10 +61,10 @@ pipe.init_adapter(
61
  )
62
 
63
  # --------------------------------------------
64
- # Background remover (BiRefNet sur CPU par défaut)
65
  # --------------------------------------------
66
  birefnet = AutoModelForImageSegmentation.from_pretrained(birefnet_path, trust_remote_code=True)
67
- birefnet.to("cpu")
68
  birefnet.eval()
69
  birefnet_transform = transforms.Compose([
70
  transforms.Resize((1024, 1024)),
@@ -74,25 +74,9 @@ birefnet_transform = transforms.Compose([
74
 
75
  def remove_bkg(subject_image):
76
  def infer_matting(img_pil):
77
- run_dev = "cuda" if torch.cuda.is_available() else "cpu"
78
- try:
79
- birefnet.to(run_dev)
80
- except Exception:
81
- run_dev = "cpu"
82
- birefnet.to("cpu")
83
-
84
- inp = birefnet_transform(img_pil).unsqueeze(0).to(run_dev)
85
  with torch.no_grad():
86
  preds = birefnet(inp)[-1].sigmoid().cpu()
87
-
88
- # libère immédiatement la VRAM
89
- try:
90
- birefnet.to("cpu")
91
- except Exception:
92
- pass
93
- if torch.cuda.is_available():
94
- torch.cuda.empty_cache()
95
-
96
  pred = preds[0].squeeze()
97
  mask = transforms.ToPILImage()(pred).resize(img_pil.size)
98
  return np.array(mask)[..., None]
@@ -112,11 +96,7 @@ def remove_bkg(subject_image):
112
  sample_mask = np.stack([mask] * 3, axis=-1)
113
  obj = sample_mask / 255 * subject_np + (1 - sample_mask / 255) * 255
114
  cropped = pad_to_square(obj, 255)
115
-
116
- # redimensionne pour se rapprocher du ratio cible (évite étirements)
117
- img = Image.fromarray(cropped.astype(np.uint8))
118
- img = img.resize((1024, 780), Image.LANCZOS)
119
- return img
120
 
121
  # --------------------------------------------
122
  # Generation logic
@@ -126,10 +106,6 @@ def randomize_seed(seed, randomize):
126
 
127
  @spaces.GPU
128
  def create_image(input_image, prompt, scale, guidance_scale, num_inference_steps, seed, style_mode, negative_prompt=""):
129
- # purge VRAM avant
130
- if torch.cuda.is_available():
131
- torch.cuda.empty_cache()
132
-
133
  input_image = remove_bkg(input_image)
134
 
135
  if style_mode == "Makoto Shinkai style":
@@ -147,7 +123,7 @@ def create_image(input_image, prompt, scale, guidance_scale, num_inference_steps
147
  negative_prompt=negative_prompt,
148
  num_inference_steps=num_inference_steps,
149
  guidance_scale=guidance_scale,
150
- width=1024, height=768, # <<< sortie fixe 1024 x 768
151
  subject_image=input_image,
152
  subject_scale=scale,
153
  generator=generator,
@@ -157,10 +133,6 @@ def create_image(input_image, prompt, scale, guidance_scale, num_inference_steps
157
  result = pipe.with_style_lora(lora_file_path=lora_path, trigger=trigger, **common_args)
158
  else:
159
  result = pipe(**common_args)
160
-
161
- # purge VRAM après
162
- if torch.cuda.is_available():
163
- torch.cuda.empty_cache()
164
  return result.images
165
 
166
  # --------------------------------------------
@@ -172,10 +144,11 @@ def generate_fn(image, prompt, scale, style, guidance, steps, seed, randomize, n
172
 
173
  title = "🎨 InstantCharacter + One Piece LoRA"
174
  description = (
175
- "Upload your photo, describe your scene, choose **One Piece style**. "
176
- "Output is fixed to **1024×768**. API docs enabled (View API) for Make.com."
177
  )
178
 
 
179
  demo = gr.Interface(
180
  fn=generate_fn,
181
  inputs=[
@@ -194,10 +167,10 @@ demo = gr.Interface(
194
  title=title,
195
  description=description,
196
  examples=[
197
- ["./assets/girl.jpg", f"a girl playing guitar, {ONEPIECE_TRIGGER}", 0.9, "One Piece style", 3.5, 28, 123, False, ""],
198
- ["./assets/boy.jpg", f"a boy riding a bike, {ONEPIECE_TRIGGER}", 0.9, "One Piece style", 3.5, 28, 123, False, ""]
199
  ]
200
  )
201
 
202
- # Affiche la doc API (utile pour trouver l'endpoint /run/predict côté Make)
203
  demo.launch(show_api=True)
 
1
  import sys, os
2
  sys.path.append("../")
3
 
4
+ # ↓↓↓ ajoute ceci tout de suite après
5
  os.environ.setdefault("PYTORCH_CUDA_ALLOC_CONF", "expandable_segments:True")
6
 
7
+
8
  import spaces
9
  import torch
10
  import random
 
37
  onepiece_style_lora_path = os.path.join(os.path.dirname(__file__), "onepiece_flux_v2.safetensors")
38
  ONEPIECE_TRIGGER = "onepiece style"
39
 
40
+ # ---- Universal prompt (homme ou femme)
41
+ UNIVERSAL_PROMPT = (
42
+ "Upper-body anime portrait of a pirate character inspired by One Piece, confident and charismatic expression, "
43
+ "original and dynamic pose, expressive eyes with anime-style lighting, slightly windswept hair, preserving the subject’s "
44
+ "distinctive facial features and hairstyle (and facial hair if present), detailed anime rendering of the face, natural matte skin tone, "
45
+ "lips matching the skin color (no pink or gloss), wearing stylish pirate clothing appropriate to the subject (open shirt, coat, vest, "
46
+ "belts, scarves, cape, etc...), with optional pirate accessories (earrings, necklace, bandana or hat) only if they fit the subject’s style, "
47
+ "well-framed head and shoulders, centered and balanced, cinematic warm lighting, high-quality cel-shaded coloring and clean linework, "
48
+ "One Piece-style background (ship deck or ocean sky), designed to look cool, original and iconic like a real One Piece portrait character, "
49
+ "no frame, no text."
50
+ )
51
+
52
  # --------------------------------------------
53
  # Init pipeline
54
  # --------------------------------------------
55
  pipe = InstantCharacterFluxPipeline.from_pretrained(base_model, torch_dtype=torch.bfloat16)
56
  pipe.to(device)
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  pipe.init_adapter(
58
  image_encoder_path=image_encoder_path,
59
  image_encoder_2_path=image_encoder_2_path,
 
61
  )
62
 
63
  # --------------------------------------------
64
+ # Background remover
65
  # --------------------------------------------
66
  birefnet = AutoModelForImageSegmentation.from_pretrained(birefnet_path, trust_remote_code=True)
67
+ birefnet.to(device)
68
  birefnet.eval()
69
  birefnet_transform = transforms.Compose([
70
  transforms.Resize((1024, 1024)),
 
74
 
75
  def remove_bkg(subject_image):
76
  def infer_matting(img_pil):
77
+ inp = birefnet_transform(img_pil).unsqueeze(0).to(device)
 
 
 
 
 
 
 
78
  with torch.no_grad():
79
  preds = birefnet(inp)[-1].sigmoid().cpu()
 
 
 
 
 
 
 
 
 
80
  pred = preds[0].squeeze()
81
  mask = transforms.ToPILImage()(pred).resize(img_pil.size)
82
  return np.array(mask)[..., None]
 
96
  sample_mask = np.stack([mask] * 3, axis=-1)
97
  obj = sample_mask / 255 * subject_np + (1 - sample_mask / 255) * 255
98
  cropped = pad_to_square(obj, 255)
99
+ return Image.fromarray(cropped.astype(np.uint8))
 
 
 
 
100
 
101
  # --------------------------------------------
102
  # Generation logic
 
106
 
107
  @spaces.GPU
108
  def create_image(input_image, prompt, scale, guidance_scale, num_inference_steps, seed, style_mode, negative_prompt=""):
 
 
 
 
109
  input_image = remove_bkg(input_image)
110
 
111
  if style_mode == "Makoto Shinkai style":
 
123
  negative_prompt=negative_prompt,
124
  num_inference_steps=num_inference_steps,
125
  guidance_scale=guidance_scale,
126
+ width=1024, height=768, # <<< sortie fixe 1024 x 768
127
  subject_image=input_image,
128
  subject_scale=scale,
129
  generator=generator,
 
133
  result = pipe.with_style_lora(lora_file_path=lora_path, trigger=trigger, **common_args)
134
  else:
135
  result = pipe(**common_args)
 
 
 
 
136
  return result.images
137
 
138
  # --------------------------------------------
 
144
 
145
  title = "🎨 InstantCharacter + One Piece LoRA"
146
  description = (
147
+ "Upload your photo, use the universal One Piece prompt, choose **One Piece style**. "
148
+ "Output is fixed to **1024×780**. API is enabled for Make.com."
149
  )
150
 
151
+ # (ne PAS mettre api_open ici)
152
  demo = gr.Interface(
153
  fn=generate_fn,
154
  inputs=[
 
167
  title=title,
168
  description=description,
169
  examples=[
170
+ ["./assets/girl.jpg", f"A girl playing guitar, {ONEPIECE_TRIGGER}", 0.9, "One Piece style", 3.5, 28, 123, False, ""],
171
+ ["./assets/boy.jpg", f"A boy riding a bike, {ONEPIECE_TRIGGER}", 0.9, "One Piece style", 3.5, 28, 123, False, ""]
172
  ]
173
  )
174
 
175
+ # ⇩⇩⇩ utiliser show_api=True ici
176
  demo.launch(show_api=True)