prithivMLmods commited on
Commit
14caa87
·
verified ·
1 Parent(s): c760d44

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +134 -98
app.py CHANGED
@@ -6,7 +6,7 @@ import spaces
6
  import torch
7
  import random
8
  from PIL import Image
9
- from typing import Iterable
10
 
11
  from diffusers import Flux2KleinPipeline
12
  from diffusers.utils import load_image
@@ -61,13 +61,24 @@ class OrangeRedTheme(Soft):
61
  orange_red_theme = OrangeRedTheme()
62
  MAX_SEED = np.iinfo(np.int32).max
63
 
64
- ADAPTER_SPECS = {
65
- "Klein-Delight-Style": {
 
 
 
 
 
 
 
 
 
 
66
  "repo": "linoyts/Flux2-Klein-Delight-LoRA",
67
  "weights": "pytorch_lora_weights.safetensors",
68
- "adapter_name": "klein-delight"
 
69
  },
70
- }
71
 
72
  LOADED_ADAPTERS = set()
73
 
@@ -94,11 +105,17 @@ def update_dimensions_on_upload(image):
94
 
95
  return new_width, new_height
96
 
 
 
 
 
 
 
97
  @spaces.GPU
98
  def infer(
99
  input_image,
100
  prompt,
101
- lora_adapter,
102
  seed=42,
103
  randomize_seed=True,
104
  guidance_scale=1.0,
@@ -110,35 +127,41 @@ def infer(
110
 
111
  if not input_image:
112
  raise gr.Error("Please upload an image to apply a style to.")
 
 
 
 
 
 
 
113
 
114
- if lora_adapter == "None":
115
- print("Selection is None. Disabling LoRA adapters.")
 
116
  pipe.disable_lora()
117
  else:
118
- spec = ADAPTER_SPECS.get(lora_adapter)
119
- if spec:
120
- adapter_name = spec["adapter_name"]
121
-
122
- if adapter_name not in LOADED_ADAPTERS:
123
- print(f"--- Downloading and Loading Adapter: {lora_adapter} ---")
124
- try:
125
- pipe.load_lora_weights(
126
- spec["repo"],
127
- weight_name=spec["weights"],
128
- adapter_name=adapter_name
129
- )
130
- LOADED_ADAPTERS.add(adapter_name)
131
- except Exception as e:
132
- raise gr.Error(f"Failed to load adapter {lora_adapter}: {e}")
133
- else:
134
- print(f"--- Adapter {lora_adapter} is already loaded. ---")
135
-
136
- print(f"Activating LoRA: {adapter_name}")
137
- pipe.set_adapters([adapter_name], adapter_weights=[1.0])
138
  else:
139
- print("Adapter not found in specs. Disabling LoRA.")
140
- pipe.disable_lora()
 
 
 
141
 
 
142
  if randomize_seed:
143
  seed = random.randint(0, MAX_SEED)
144
 
@@ -165,14 +188,17 @@ def infer(
165
  torch.cuda.empty_cache()
166
 
167
  @spaces.GPU
168
- def infer_example(input_image, prompt, lora_adapter):
169
- if input_image is None:
170
- return None, 0
171
-
 
 
 
172
  image, seed = infer(
173
  input_image=input_image,
174
  prompt=prompt,
175
- lora_adapter=lora_adapter,
176
  seed=0,
177
  randomize_seed=True,
178
  guidance_scale=1.0,
@@ -181,87 +207,97 @@ def infer_example(input_image, prompt, lora_adapter):
181
  return image, seed
182
 
183
  css="""
184
- #col-container { margin: 0 auto; max-width: 960px; }
185
- #main-title h1 { font-size: 2.2em !important; }
 
 
186
  """
187
 
188
  with gr.Blocks() as demo:
 
 
 
189
  with gr.Column(elem_id="col-container"):
190
  gr.Markdown("# **FLUX.2-Klein-LoRA-Studio**", elem_id="main-title")
191
  gr.Markdown("Perform diverse image edits using specialized [LoRAs](https://huggingface.co/models?other=base_model:adapter:black-forest-labs/FLUX.2-klein-9B) adapters for the [FLUX.2-Klein-Distilled](https://huggingface.co/black-forest-labs/FLUX.2-klein-9B) model.")
192
 
193
- with gr.Row(equal_height=True):
194
- with gr.Column():
195
- input_image = gr.Image(
196
- label="Upload Image",
197
- type="pil",
198
- height=290,
199
- sources=["upload", "webcam", "clipboard"]
200
- )
201
- with gr.Row():
202
  prompt = gr.Text(
203
  label="Edit Prompt",
204
- max_lines=1,
205
- show_label=True,
206
- placeholder="e.g., a man with a red superhero mask"
207
  )
208
-
209
- run_button = gr.Button("Apply Style", variant="primary")
210
-
211
- with gr.Accordion("Advanced Settings", open=False, visible=False):
212
- seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
213
- randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
214
- guidance_scale = gr.Slider(label="Guidance Scale", minimum=0.0, maximum=10.0, step=0.1, value=1.0)
215
- steps = gr.Slider(label="Steps", minimum=1, maximum=50, value=4, step=1)
216
-
217
- with gr.Column():
218
- output_image = gr.Image(label="Output Image", interactive=False, format="png", height=358)
219
  used_seed = gr.Textbox(label="Used Seed", interactive=False, visible=False)
220
 
221
- with gr.Row():
222
- # Hidden textbox to store the selected style name for the infer function
223
- lora_adapter = gr.Textbox(label="Selected Style", value="None", visible=False)
224
-
225
- # Preparing gallery data
226
- gallery_items = [("examples/1.jpg", "None")]
227
- for key in ADAPTER_SPECS.keys():
228
- # Using example image 2 as thumbnail for Klein style
229
- thumb = "examples/2.jpg" if key == "Klein-Delight-Style" else "examples/1.jpg"
230
- gallery_items.append((thumb, key))
231
-
232
- style_gallery = gr.Gallery(
233
- label="Edit Style Gallery",
234
- value=gallery_items,
235
- columns=3,
236
- allow_preview=False,
237
- show_label=True,
238
- height="auto"
239
- )
240
-
241
- # Event logic for gallery selection
242
- def on_style_select(evt: gr.SelectData):
243
- return gallery_items[evt.index][1]
244
 
245
- style_gallery.select(fn=on_style_select, inputs=None, outputs=lora_adapter)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246
 
247
- gr.Examples(
248
- examples=[
249
- ["examples/2.jpg", "Relight the image to remove all existing lighting conditions and replace them with neutral, uniform illumination. Apply soft, evenly distributed lighting with no directional shadows, no harsh highlights, and no dramatic contrast. Maintain the original identity of all subjects exactly—preserve facial structure, skin tone, proportions, expressions, hair, clothing, and textures. Do not alter pose, camera angle, background geometry, or image composition. Lighting should appear balanced, and studio-neutral, similar to diffuse overcast or a soft lightbox setup. Ensure consistent exposure across the entire image with realistic depth and subtle shading only where necessary for form.", "Klein-Delight-Style"],
250
- ["examples/1.jpg", "cinematic polaroid with soft grain subtle vignette gentle lighting white frame handwritten photographed by prithivMLmods preserving realistic texture and details", "None"],
251
- ],
252
- inputs=[input_image, prompt, lora_adapter],
253
- outputs=[output_image, used_seed],
254
- fn=infer_example,
255
- cache_examples=False,
256
  )
257
-
258
- gr.Markdown("[*](https://huggingface.co/black-forest-labs/FLUX.2-klein-9B)This is still an experimental Space for FLUX.2-Klein-9B. More adapters will be added soon.")
259
-
260
  run_button.click(
261
  fn=infer,
262
- inputs=[input_image, prompt, lora_adapter, seed, randomize_seed, guidance_scale, steps],
263
  outputs=[output_image, used_seed]
264
  )
265
 
266
  if __name__ == "__main__":
267
- demo.queue().launch(css=css, theme=orange_red_theme, show_error=True)
 
6
  import torch
7
  import random
8
  from PIL import Image
9
+ from typing import Iterable, List, Dict, Any
10
 
11
  from diffusers import Flux2KleinPipeline
12
  from diffusers.utils import load_image
 
61
  orange_red_theme = OrangeRedTheme()
62
  MAX_SEED = np.iinfo(np.int32).max
63
 
64
+ loras_list = [
65
+ {
66
+ "image": "https://huggingface.co/spaces/stabilityai/stable-diffusion/resolve/main/assets/0.png", # Placeholder for None
67
+ "title": "None (Base Model)",
68
+ "repo": None,
69
+ "weights": None,
70
+ "adapter_name": None,
71
+ "description": "Original FLUX.2 Klein model without modifications."
72
+ },
73
+ {
74
+ "image": "https://huggingface.co/linoyts/Flux2-Klein-Delight-LoRA/resolve/main/images/example_image.jpg", # Placeholder/Real if available
75
+ "title": "Klein Delight Style",
76
  "repo": "linoyts/Flux2-Klein-Delight-LoRA",
77
  "weights": "pytorch_lora_weights.safetensors",
78
+ "adapter_name": "klein-delight",
79
+ "description": "Removes existing lighting and applies neutral, studio-like illumination."
80
  },
81
+ ]
82
 
83
  LOADED_ADAPTERS = set()
84
 
 
105
 
106
  return new_width, new_height
107
 
108
+ def update_selection(evt: gr.SelectData):
109
+ """Updates the UI when a gallery item is selected."""
110
+ selected_lora = loras_list[evt.index]
111
+ info_text = f"### Selected: {selected_lora['title']}\n{selected_lora['description']}"
112
+ return evt.index, info_text
113
+
114
  @spaces.GPU
115
  def infer(
116
  input_image,
117
  prompt,
118
+ selected_index,
119
  seed=42,
120
  randomize_seed=True,
121
  guidance_scale=1.0,
 
127
 
128
  if not input_image:
129
  raise gr.Error("Please upload an image to apply a style to.")
130
+
131
+ # Ensure index is valid
132
+ if selected_index is None:
133
+ selected_index = 0
134
+
135
+ selected_lora = loras_list[selected_index]
136
+ repo = selected_lora["repo"]
137
 
138
+ # --- LoRA Loading Logic ---
139
+ if repo is None:
140
+ print("Selection is None (Base). Disabling LoRA adapters.")
141
  pipe.disable_lora()
142
  else:
143
+ adapter_name = selected_lora["adapter_name"]
144
+ weights = selected_lora["weights"]
145
+
146
+ if adapter_name not in LOADED_ADAPTERS:
147
+ print(f"--- Downloading and Loading Adapter: {selected_lora['title']} ---")
148
+ try:
149
+ pipe.load_lora_weights(
150
+ repo,
151
+ weight_name=weights,
152
+ adapter_name=adapter_name
153
+ )
154
+ LOADED_ADAPTERS.add(adapter_name)
155
+ except Exception as e:
156
+ raise gr.Error(f"Failed to load adapter {selected_lora['title']}: {e}")
 
 
 
 
 
 
157
  else:
158
+ print(f"--- Adapter {adapter_name} is already loaded. ---")
159
+
160
+ print(f"Activating LoRA: {adapter_name}")
161
+ # Enable specific adapter
162
+ pipe.set_adapters([adapter_name], adapter_weights=[1.0])
163
 
164
+ # --- Generation Logic ---
165
  if randomize_seed:
166
  seed = random.randint(0, MAX_SEED)
167
 
 
188
  torch.cuda.empty_cache()
189
 
190
  @spaces.GPU
191
+ def infer_example(input_image, prompt, selected_title_str):
192
+ idx = 0
193
+ for i, item in enumerate(loras_list):
194
+ if item["title"] == selected_title_str:
195
+ idx = i
196
+ break
197
+
198
  image, seed = infer(
199
  input_image=input_image,
200
  prompt=prompt,
201
+ selected_index=idx,
202
  seed=0,
203
  randomize_seed=True,
204
  guidance_scale=1.0,
 
207
  return image, seed
208
 
209
  css="""
210
+ #col-container { margin: 0 auto; max-width: 1024px; }
211
+ #main-title h1 { font-size: 2.5em !important; text-align: center; }
212
+ #gallery { min-height: 200px; }
213
+ .selected-info { margin-top: 10px; padding: 10px; background: rgba(0,0,0,0.05); border-radius: 8px; }
214
  """
215
 
216
  with gr.Blocks() as demo:
217
+
218
+ selected_index_state = gr.State(value=0)
219
+
220
  with gr.Column(elem_id="col-container"):
221
  gr.Markdown("# **FLUX.2-Klein-LoRA-Studio**", elem_id="main-title")
222
  gr.Markdown("Perform diverse image edits using specialized [LoRAs](https://huggingface.co/models?other=base_model:adapter:black-forest-labs/FLUX.2-klein-9B) adapters for the [FLUX.2-Klein-Distilled](https://huggingface.co/black-forest-labs/FLUX.2-klein-9B) model.")
223
 
224
+ with gr.Row():
225
+ with gr.Column(scale=3):
226
+ with gr.Group():
227
+ input_image = gr.Image(
228
+ label="Upload Image",
229
+ type="pil",
230
+ height=400,
231
+ sources=["upload", "webcam", "clipboard"]
232
+ )
233
  prompt = gr.Text(
234
  label="Edit Prompt",
235
+ max_lines=2,
236
+ placeholder="Describe the desired change (e.g., 'Relight the image with soft studio lighting')..."
 
237
  )
238
+
239
+ with gr.Column(scale=2):
240
+ output_image = gr.Image(label="Output Image", interactive=False, format="png", height=400)
 
 
 
 
 
 
 
 
241
  used_seed = gr.Textbox(label="Used Seed", interactive=False, visible=False)
242
 
243
+ # Gallery Selection Section
244
+ gr.Markdown("### 🎨 Edit Style Gallery", elem_id="gallery_header")
245
+ with gr.Row():
246
+ gallery = gr.Gallery(
247
+ value=[(item["image"], item["title"]) for item in loras_list],
248
+ label="Choose a Style",
249
+ allow_preview=False,
250
+ columns=4,
251
+ elem_id="gallery",
252
+ show_label=False,
253
+ height="auto"
254
+ )
255
+
256
+ selection_info = gr.Markdown("### Selected: None (Base Model)", elem_classes="selected-info")
257
+
258
+ run_button = gr.Button("✨ Apply Style", variant="primary", size="lg")
 
 
 
 
 
 
 
259
 
260
+ with gr.Accordion("Advanced Settings", open=False):
261
+ with gr.Row():
262
+ seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
263
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
264
+ with gr.Row():
265
+ guidance_scale = gr.Slider(label="Guidance Scale", minimum=0.0, maximum=10.0, step=0.1, value=1.0)
266
+ steps = gr.Slider(label="Steps", minimum=1, maximum=50, value=4, step=1)
267
+
268
+ # Examples
269
+ gr.Examples(
270
+ examples=[
271
+ [
272
+ "examples/2.jpg",
273
+ "Relight the image to remove all existing lighting conditions and replace them with neutral, uniform illumination. Apply soft, evenly distributed lighting with no directional shadows.",
274
+ "Klein Delight Style"
275
+ ],
276
+ [
277
+ "examples/1.jpg",
278
+ "cinematic polaroid with soft grain subtle vignette gentle lighting white frame handwritten photographed by prithivMLmods",
279
+ "None (Base Model)"
280
+ ],
281
+ ],
282
+ inputs=[input_image, prompt, gr.Textbox(visible=False)],
283
+ outputs=[output_image, used_seed],
284
+ fn=infer_example,
285
+ cache_examples=False,
286
+ )
287
+
288
+ gr.Markdown("[*](https://huggingface.co/black-forest-labs/FLUX.2-klein-9B) This is still an experimental Space for FLUX.2-Klein-9B. More adapters will be added soon.")
289
 
290
+ gallery.select(
291
+ fn=update_selection,
292
+ inputs=None,
293
+ outputs=[selected_index_state, selection_info]
 
 
 
 
 
294
  )
295
+
 
 
296
  run_button.click(
297
  fn=infer,
298
+ inputs=[input_image, prompt, selected_index_state, seed, randomize_seed, guidance_scale, steps],
299
  outputs=[output_image, used_seed]
300
  )
301
 
302
  if __name__ == "__main__":
303
+ demo.queue().launch(theme=orange_red_theme, css=css, show_error=True)