ginipick commited on
Commit
4369019
·
verified ·
1 Parent(s): 281e5a1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +132 -101
app.py CHANGED
@@ -18,69 +18,66 @@ MAX_SEED = np.iinfo(np.int32).max
18
 
19
  pipe = FluxKontextPipeline.from_pretrained("black-forest-labs/FLUX.1-Kontext-dev", torch_dtype=torch.bfloat16).to("cuda")
20
 
21
- # Load LoRA data (you'll need to create this JSON file or modify to load your LoRAs)
22
- try:
23
- with open("flux_loras.json", "r") as file:
24
- data = json.load(file)
25
- flux_loras_raw = [
26
- {
27
- "image": item["image"],
28
- "title": item["title"],
29
- "repo": item["repo"],
30
- "trigger_word": item.get("trigger_word", ""),
31
- "trigger_position": item.get("trigger_position", "prepend"),
32
- "weights": item.get("weights", "pytorch_lora_weights.safetensors"),
33
- "likes": item.get("likes", 0),
34
- }
35
- for item in data
36
- ]
37
- print(f"Successfully loaded {len(flux_loras_raw)} LoRAs from JSON")
38
- except Exception as e:
39
- print(f"Error loading flux_loras.json: {e}")
40
- print("Using sample LoRA data instead...")
41
- # Sample LoRA data with working repositories
42
- flux_loras_raw = [
43
- {
44
- "image": "https://huggingface.co/alvdansen/flux-koda/resolve/main/images/photo-1586902197503-e71026292412.jpeg",
45
- "title": "Flux Koda",
46
- "repo": "alvdansen/flux-koda",
47
- "trigger_word": "flmft style",
48
- "weights": "flux_lora.safetensors",
49
- "likes": 100
50
- },
51
- {
52
- "image": "https://huggingface.co/multimodalart/flux-tarot-v1/resolve/main/images/e5f2761e5a474e52ab11b1c9246c9a30.png",
53
- "title": "Tarot Cards",
54
- "repo": "multimodalart/flux-tarot-v1",
55
- "trigger_word": "in the style of TOK a trtcrd tarot style",
56
- "weights": "flux_tarot_v1_lora.safetensors",
57
- "likes": 90
58
- },
59
- {
60
- "image": "https://huggingface.co/Norod78/Flux_1_Dev_LoRA_Paper-Cutout-Style/resolve/main/d13591878de740648a8f29b836e16ff2.jpeg",
61
- "title": "Paper Cutout",
62
- "repo": "Norod78/Flux_1_Dev_LoRA_Paper-Cutout-Style",
63
- "trigger_word": "Paper Cutout Style",
64
- "weights": "Flux_1_Dev_LoRA_Paper-Cutout-Style.safetensors",
65
- "likes": 80
66
- },
67
- {
68
- "image": "https://huggingface.co/alvdansen/frosting_lane_flux/resolve/main/images/content%20-%202024-08-11T010011.238.jpeg",
69
- "title": "Frosting Lane",
70
- "repo": "alvdansen/frosting_lane_flux",
71
- "trigger_word": "frstingln illustration",
72
- "weights": "flux_lora_frosting_lane_flux_000002500.safetensors",
73
- "likes": 70
74
- },
75
- {
76
- "image": "https://huggingface.co/davisbro/flux-watercolor/resolve/main/images/wc2.png",
77
- "title": "Watercolor",
78
- "repo": "davisbro/flux-watercolor",
79
- "trigger_word": "watercolor style",
80
- "weights": "flux_watercolor.safetensors",
81
- "likes": 60
82
- }
83
- ]
84
  # Global variables for LoRA management
85
  current_lora = None
86
  lora_cache = {}
@@ -136,11 +133,14 @@ def update_selection(selected_state: gr.SelectData, flux_loras):
136
  if selected_state.index >= len(flux_loras):
137
  return "### No LoRA selected", gr.update(), None
138
 
139
- lora_repo = flux_loras[selected_state.index]["repo"]
140
- trigger_word = flux_loras[selected_state.index]["trigger_word"]
 
 
141
 
142
- updated_text = f"### Selected: [{lora_repo}](https://huggingface.co/{lora_repo})"
143
- new_placeholder = f"optional description, e.g. 'a man with glasses and a beard'"
 
144
 
145
  return updated_text, gr.update(placeholder=new_placeholder), selected_state.index
146
 
@@ -188,17 +188,20 @@ def get_huggingface_lora(link):
188
  def load_custom_lora(link):
189
  """Load custom LoRA from user input"""
190
  if not link:
191
- return gr.update(visible=False), "", gr.update(visible=False), None, gr.Gallery(selected_index=None), "### Click on a LoRA in the gallery to select it", None
192
 
193
  try:
194
  repo_name, weights_file, trigger_word = get_huggingface_lora(link)
195
 
196
  card = f'''
197
- <div style="border: 1px solid #ddd; padding: 10px; border-radius: 8px; margin: 10px 0;">
198
- <span><strong>Loaded custom LoRA:</strong></span>
199
- <div style="margin-top: 8px;">
200
- <h4>{repo_name}</h4>
201
- <small>{"Using: <code><b>"+trigger_word+"</b></code> as trigger word" if trigger_word else "No trigger word found"}</small>
 
 
 
202
  </div>
203
  </div>
204
  '''
@@ -209,10 +212,10 @@ def load_custom_lora(link):
209
  "trigger_word": trigger_word
210
  }
211
 
212
- return gr.update(visible=True), card, gr.update(visible=True), custom_lora_data, gr.Gallery(selected_index=None), f"Custom: {repo_name}", None
213
 
214
  except Exception as e:
215
- return gr.update(visible=True), f"Error: {str(e)}", gr.update(visible=False), None, gr.update(), "### Click on a LoRA in the gallery to select it", None
216
 
217
  def remove_custom_lora():
218
  """Remove custom LoRA"""
@@ -224,16 +227,26 @@ def classify_gallery(flux_loras):
224
  sorted_gallery = sorted(flux_loras, key=lambda x: x.get("likes", 0), reverse=True)
225
  gallery_items = []
226
 
 
 
 
 
 
 
 
 
 
 
 
227
  for item in sorted_gallery:
228
  if "image" in item and "title" in item:
229
  image_url = item["image"]
230
  title = item["title"]
231
 
232
- # If image is a local file path that might not exist, use a placeholder URL
233
- if isinstance(image_url, str) and (image_url.startswith("/home/") or image_url.startswith("samples/") or not image_url.startswith("http")):
234
- print(f"Replacing local/invalid image path: {image_url}")
235
- # Use a more reliable placeholder
236
- image_url = f"https://via.placeholder.com/512x512/E0E7FF/818CF8?text={title.replace(' ', '+')}"
237
 
238
  gallery_items.append((image_url, title))
239
 
@@ -246,7 +259,7 @@ def classify_gallery(flux_loras):
246
  print(f"Error in classify_gallery: {e}")
247
  return [], []
248
 
249
- def infer_with_lora_wrapper(input_image, prompt, selected_index, custom_lora, seed=42, randomize_seed=False, guidance_scale=2.5, lora_scale=1.75, flux_loras=None, progress=gr.Progress(track_tqdm=True)):
250
  """Wrapper function to handle state serialization"""
251
  return infer_with_lora(input_image, prompt, selected_index, custom_lora, seed, randomize_seed, guidance_scale, lora_scale, flux_loras, progress)
252
 
@@ -257,7 +270,7 @@ def infer_with_lora(input_image, prompt, selected_index, custom_lora, seed=42, r
257
 
258
  # Check if input image is provided
259
  if input_image is None:
260
- gr.Warning("Please upload an image first!")
261
  return None, seed, gr.update(visible=False)
262
 
263
  if randomize_seed:
@@ -290,7 +303,7 @@ def infer_with_lora(input_image, prompt, selected_index, custom_lora, seed=42, r
290
  current_lora = lora_to_use
291
  else:
292
  print(f"Failed to load LoRA from {repo_id}")
293
- gr.Warning(f"Failed to load LoRA style. Please try a different one.")
294
  return None, seed, gr.update(visible=False)
295
 
296
  except Exception as e:
@@ -305,17 +318,33 @@ def infer_with_lora(input_image, prompt, selected_index, custom_lora, seed=42, r
305
  input_image = input_image.convert("RGB")
306
  except Exception as e:
307
  print(f"Error processing image: {e}")
308
- gr.Warning("Error processing the uploaded image. Please try a different image.")
309
  return None, seed, gr.update(visible=False)
310
 
311
  # Check if LoRA is selected
312
  if lora_to_use is None:
313
- gr.Warning("Please select a LoRA style from the gallery first!")
314
  return None, seed, gr.update(visible=False)
315
 
316
  # Add trigger word to prompt
317
  trigger_word = lora_to_use.get("trigger_word", "")
318
- if trigger_word == ", How2Draw":
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
  prompt = f"create a How2Draw sketch of the person of the photo {prompt}, maintain the facial identity of the person and general features"
320
  elif trigger_word == ", video game screenshot in the style of THSMS":
321
  prompt = f"create a video game screenshot in the style of THSMS with the person from the photo, {prompt}. maintain the facial identity of the person and general features"
@@ -571,10 +600,10 @@ with gr.Blocks(css=css) as demo:
571
  with gr.Row(elem_id="main_app"):
572
  with gr.Column(scale=4, elem_id="box_column"):
573
  with gr.Group(elem_id="gallery_box"):
574
- input_image = gr.Image(label="Upload a picture of yourself", type="pil", height=300)
575
 
576
  gallery = gr.Gallery(
577
- label="Pick a LoRA",
578
  allow_preview=False,
579
  columns=3,
580
  elem_id="gallery",
@@ -583,55 +612,57 @@ with gr.Blocks(css=css) as demo:
583
  )
584
 
585
  custom_model = gr.Textbox(
586
- label="Or enter a custom HuggingFace FLUX LoRA",
587
  placeholder="e.g., username/lora-name",
588
  visible=True
589
  )
590
  custom_model_card = gr.HTML(visible=False)
591
- custom_model_button = gr.Button("Remove custom LoRA", visible=False)
592
 
593
  with gr.Column(scale=5):
594
  with gr.Row():
595
  prompt = gr.Textbox(
596
- label="Editing Prompt",
597
  show_label=False,
598
  lines=1,
599
  max_lines=1,
600
- placeholder="optional description, e.g. 'a man with glasses and a beard'",
601
  elem_id="prompt"
602
  )
603
  run_button = gr.Button("Generate ✨", elem_id="run_button")
604
 
605
- result = gr.Image(label="Generated Image", interactive=False)
606
  reuse_button = gr.Button("🔄 Reuse this image", visible=False)
607
 
608
- with gr.Accordion("Advanced Settings", open=False):
609
  lora_scale = gr.Slider(
610
- label="LoRA Scale",
611
  minimum=0,
612
  maximum=2,
613
  step=0.1,
614
- value=1.5,
615
- info="Controls the strength of the LoRA effect"
616
  )
617
  seed = gr.Slider(
618
- label="Seed",
619
  minimum=0,
620
  maximum=MAX_SEED,
621
  step=1,
622
  value=0,
 
623
  )
624
- randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
625
  guidance_scale = gr.Slider(
626
- label="Guidance Scale",
627
  minimum=1,
628
  maximum=10,
629
  step=0.1,
630
  value=2.5,
 
631
  )
632
 
633
  prompt_title = gr.Markdown(
634
- value="### Click on a LoRA in the gallery to select it",
635
  visible=True,
636
  elem_id="selected_lora",
637
  )
 
18
 
19
  pipe = FluxKontextPipeline.from_pretrained("black-forest-labs/FLUX.1-Kontext-dev", torch_dtype=torch.bfloat16).to("cuda")
20
 
21
+ # Load LoRA data
22
+ flux_loras_raw = [
23
+ {
24
+ "image": "examples/1.png",
25
+ "title": "Studio Ghibli",
26
+ "repo": "openfree/flux-chatgpt-ghibli-lora",
27
+ "trigger_word": "ghibli",
28
+ "weights": "pytorch_lora_weights.safetensors",
29
+ "likes": 0
30
+ },
31
+ {
32
+ "image": "examples/2.png",
33
+ "title": "Winslow Homer",
34
+ "repo": "openfree/winslow-homer",
35
+ "trigger_word": "homer",
36
+ "weights": "pytorch_lora_weights.safetensors",
37
+ "likes": 0
38
+ },
39
+ {
40
+ "image": "examples/3.png",
41
+ "title": "Van Gogh",
42
+ "repo": "openfree/van-gogh",
43
+ "trigger_word": "gogh",
44
+ "weights": "pytorch_lora_weights.safetensors",
45
+ "likes": 0
46
+ },
47
+ {
48
+ "image": "examples/4.png",
49
+ "title": "Paul Cézanne",
50
+ "repo": "openfree/paul-cezanne",
51
+ "trigger_word": "Cezanne",
52
+ "weights": "pytorch_lora_weights.safetensors",
53
+ "likes": 0
54
+ },
55
+ {
56
+ "image": "examples/5.png",
57
+ "title": "Renoir",
58
+ "repo": "openfree/pierre-auguste-renoir",
59
+ "trigger_word": "Renoir",
60
+ "weights": "pytorch_lora_weights.safetensors",
61
+ "likes": 0
62
+ },
63
+ {
64
+ "image": "examples/6.png",
65
+ "title": "Claude Monet",
66
+ "repo": "openfree/claude-monet",
67
+ "trigger_word": "claude monet",
68
+ "weights": "pytorch_lora_weights.safetensors",
69
+ "likes": 0
70
+ },
71
+ {
72
+ "image": "examples/7.png",
73
+ "title": "Fantasy Art",
74
+ "repo": "openfree/myt-flux-fantasy",
75
+ "trigger_word": "fantasy",
76
+ "weights": "pytorch_lora_weights.safetensors",
77
+ "likes": 0
78
+ }
79
+ ]
80
+ print(f"Loaded {len(flux_loras_raw)} LoRAs")
 
 
 
81
  # Global variables for LoRA management
82
  current_lora = None
83
  lora_cache = {}
 
133
  if selected_state.index >= len(flux_loras):
134
  return "### No LoRA selected", gr.update(), None
135
 
136
+ lora = flux_loras[selected_state.index]
137
+ lora_title = lora["title"]
138
+ lora_repo = lora["repo"]
139
+ trigger_word = lora["trigger_word"]
140
 
141
+ # Create a more informative selected text
142
+ updated_text = f"### 🎨 Selected Style: {lora_title}"
143
+ new_placeholder = f"Describe additional details, e.g., 'wearing a red hat' or 'smiling'"
144
 
145
  return updated_text, gr.update(placeholder=new_placeholder), selected_state.index
146
 
 
188
  def load_custom_lora(link):
189
  """Load custom LoRA from user input"""
190
  if not link:
191
+ return gr.update(visible=False), "", gr.update(visible=False), None, gr.Gallery(selected_index=None), "### 🎨 Select an art style from the gallery", None
192
 
193
  try:
194
  repo_name, weights_file, trigger_word = get_huggingface_lora(link)
195
 
196
  card = f'''
197
+ <div class="custom_lora_card">
198
+ <div style="display: flex; align-items: center; margin-bottom: 12px;">
199
+ <span style="font-size: 18px; margin-right: 8px;">✅</span>
200
+ <strong style="font-size: 16px;">Custom LoRA Loaded!</strong>
201
+ </div>
202
+ <div style="background: rgba(255, 255, 255, 0.8); padding: 12px; border-radius: 8px;">
203
+ <h4 style="margin: 0 0 8px 0; color: #333;">{repo_name}</h4>
204
+ <small style="color: #666;">{"Trigger: <code style='background: #f0f0f0; padding: 2px 6px; border-radius: 4px;'><b>"+trigger_word+"</b></code>" if trigger_word else "No trigger word found"}</small>
205
  </div>
206
  </div>
207
  '''
 
212
  "trigger_word": trigger_word
213
  }
214
 
215
+ return gr.update(visible=True), card, gr.update(visible=True), custom_lora_data, gr.Gallery(selected_index=None), f"🎨 Custom Style: {repo_name}", None
216
 
217
  except Exception as e:
218
+ return gr.update(visible=True), f"Error: {str(e)}", gr.update(visible=False), None, gr.update(), "### 🎨 Select an art style from the gallery", None
219
 
220
  def remove_custom_lora():
221
  """Remove custom LoRA"""
 
227
  sorted_gallery = sorted(flux_loras, key=lambda x: x.get("likes", 0), reverse=True)
228
  gallery_items = []
229
 
230
+ # Color mapping for each style
231
+ style_colors = {
232
+ "Studio Ghibli": "81C784/FFFFFF", # Green
233
+ "Winslow Homer": "64B5F6/FFFFFF", # Blue
234
+ "Van Gogh": "FFD54F/333333", # Yellow
235
+ "Paul Cézanne": "FF8A65/FFFFFF", # Orange
236
+ "Renoir": "F06292/FFFFFF", # Pink
237
+ "Claude Monet": "9575CD/FFFFFF", # Purple
238
+ "Fantasy Art": "4FC3F7/FFFFFF" # Light Blue
239
+ }
240
+
241
  for item in sorted_gallery:
242
  if "image" in item and "title" in item:
243
  image_url = item["image"]
244
  title = item["title"]
245
 
246
+ # If image is a local file path, use a styled placeholder
247
+ if isinstance(image_url, str) and (image_url.startswith("examples/") or image_url.startswith("/home/") or image_url.startswith("samples/") or not image_url.startswith("http")):
248
+ color = style_colors.get(title, "E0E7FF/818CF8")
249
+ image_url = f"https://via.placeholder.com/512x512/{color}?text={title.replace(' ', '+')}"
 
250
 
251
  gallery_items.append((image_url, title))
252
 
 
259
  print(f"Error in classify_gallery: {e}")
260
  return [], []
261
 
262
+ def infer_with_lora_wrapper(input_image, prompt, selected_index, custom_lora, seed=42, randomize_seed=False, guidance_scale=2.5, lora_scale=1.0, flux_loras=None, progress=gr.Progress(track_tqdm=True)):
263
  """Wrapper function to handle state serialization"""
264
  return infer_with_lora(input_image, prompt, selected_index, custom_lora, seed, randomize_seed, guidance_scale, lora_scale, flux_loras, progress)
265
 
 
270
 
271
  # Check if input image is provided
272
  if input_image is None:
273
+ gr.Warning("Please upload your portrait photo first! 📸")
274
  return None, seed, gr.update(visible=False)
275
 
276
  if randomize_seed:
 
303
  current_lora = lora_to_use
304
  else:
305
  print(f"Failed to load LoRA from {repo_id}")
306
+ gr.Warning(f"Failed to load {lora_to_use.get('title', 'style')}. Please try a different art style.")
307
  return None, seed, gr.update(visible=False)
308
 
309
  except Exception as e:
 
318
  input_image = input_image.convert("RGB")
319
  except Exception as e:
320
  print(f"Error processing image: {e}")
321
+ gr.Warning("Error processing the uploaded image. Please try a different photo. 📸")
322
  return None, seed, gr.update(visible=False)
323
 
324
  # Check if LoRA is selected
325
  if lora_to_use is None:
326
+ gr.Warning("Please select an art style from the gallery first! 🎨")
327
  return None, seed, gr.update(visible=False)
328
 
329
  # Add trigger word to prompt
330
  trigger_word = lora_to_use.get("trigger_word", "")
331
+
332
+ # Special handling for different art styles
333
+ if trigger_word == "ghibli":
334
+ prompt = f"Create a Studio Ghibli anime style portrait of the person in the photo, {prompt}. Maintain the facial identity while transforming into whimsical anime art style."
335
+ elif trigger_word == "homer":
336
+ prompt = f"Paint the person in Winslow Homer's American realist style, {prompt}. Keep facial features while applying watercolor and marine art techniques."
337
+ elif trigger_word == "gogh":
338
+ prompt = f"Transform the portrait into Van Gogh's post-impressionist style with swirling brushstrokes, {prompt}. Maintain facial identity with expressive colors."
339
+ elif trigger_word == "Cezanne":
340
+ prompt = f"Render the person in Paul Cézanne's geometric post-impressionist style, {prompt}. Keep facial structure while applying structured brushwork."
341
+ elif trigger_word == "Renoir":
342
+ prompt = f"Paint the portrait in Pierre-Auguste Renoir's impressionist style with soft light, {prompt}. Maintain identity with luminous skin tones."
343
+ elif trigger_word == "claude monet":
344
+ prompt = f"Create an impressionist portrait in Claude Monet's style with visible brushstrokes, {prompt}. Keep facial features while using light and color."
345
+ elif trigger_word == "fantasy":
346
+ prompt = f"Transform into an epic fantasy character portrait, {prompt}. Maintain facial identity while adding magical and fantastical elements."
347
+ elif trigger_word == ", How2Draw":
348
  prompt = f"create a How2Draw sketch of the person of the photo {prompt}, maintain the facial identity of the person and general features"
349
  elif trigger_word == ", video game screenshot in the style of THSMS":
350
  prompt = f"create a video game screenshot in the style of THSMS with the person from the photo, {prompt}. maintain the facial identity of the person and general features"
 
600
  with gr.Row(elem_id="main_app"):
601
  with gr.Column(scale=4, elem_id="box_column"):
602
  with gr.Group(elem_id="gallery_box"):
603
+ input_image = gr.Image(label="Upload your portrait photo 📸", type="pil", height=300)
604
 
605
  gallery = gr.Gallery(
606
+ label="Choose Your Art Style",
607
  allow_preview=False,
608
  columns=3,
609
  elem_id="gallery",
 
612
  )
613
 
614
  custom_model = gr.Textbox(
615
+ label="🔗 Or use a custom LoRA from HuggingFace",
616
  placeholder="e.g., username/lora-name",
617
  visible=True
618
  )
619
  custom_model_card = gr.HTML(visible=False)
620
+ custom_model_button = gr.Button("Remove custom LoRA", visible=False)
621
 
622
  with gr.Column(scale=5):
623
  with gr.Row():
624
  prompt = gr.Textbox(
625
+ label="Additional Details (optional)",
626
  show_label=False,
627
  lines=1,
628
  max_lines=1,
629
+ placeholder="Describe additional details, e.g., 'wearing a red hat' or 'smiling'",
630
  elem_id="prompt"
631
  )
632
  run_button = gr.Button("Generate ✨", elem_id="run_button")
633
 
634
+ result = gr.Image(label="Your Artistic Portrait", interactive=False)
635
  reuse_button = gr.Button("🔄 Reuse this image", visible=False)
636
 
637
+ with gr.Accordion("⚙️ Advanced Settings", open=False):
638
  lora_scale = gr.Slider(
639
+ label="Style Strength",
640
  minimum=0,
641
  maximum=2,
642
  step=0.1,
643
+ value=1.0,
644
+ info="How strongly to apply the art style (1.0 = balanced)"
645
  )
646
  seed = gr.Slider(
647
+ label="Random Seed",
648
  minimum=0,
649
  maximum=MAX_SEED,
650
  step=1,
651
  value=0,
652
+ info="Set to 0 for random results"
653
  )
654
+ randomize_seed = gr.Checkbox(label="🎲 Randomize seed for each generation", value=True)
655
  guidance_scale = gr.Slider(
656
+ label="Image Guidance",
657
  minimum=1,
658
  maximum=10,
659
  step=0.1,
660
  value=2.5,
661
+ info="How closely to follow the input image (lower = more creative)"
662
  )
663
 
664
  prompt_title = gr.Markdown(
665
+ value="### 🎨 Select an art style from the gallery",
666
  visible=True,
667
  elem_id="selected_lora",
668
  )