cpuai commited on
Commit
f7ffd06
Β·
verified Β·
1 Parent(s): 1417cc8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +135 -32
app.py CHANGED
@@ -52,13 +52,13 @@ def load_lora_weights(repo_id, weights_filename):
52
  def update_selection(selected_state: gr.SelectData, flux_loras):
53
  """Update UI when a LoRA is selected"""
54
  if selected_state.index >= len(flux_loras):
55
- return "### No LoRA selected", gr.update(), None
56
 
57
  lora_repo = flux_loras[selected_state.index]["repo"]
58
  trigger_word = flux_loras[selected_state.index]["trigger_word"]
59
 
60
- updated_text = f"### Selected: [{lora_repo}](https://huggingface.co/{lora_repo})"
61
- new_placeholder = f"optional description, e.g. 'a man with glasses and a beard'"
62
 
63
  return updated_text, gr.update(placeholder=new_placeholder), selected_state.index
64
 
@@ -91,17 +91,17 @@ def get_huggingface_lora(link):
91
  def load_custom_lora(link):
92
  """Load custom LoRA from user input"""
93
  if not link:
94
- 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
95
 
96
  try:
97
  repo_name, weights_file, trigger_word = get_huggingface_lora(link)
98
 
99
  card = f'''
100
  <div style="border: 1px solid #ddd; padding: 10px; border-radius: 8px; margin: 10px 0;">
101
- <span><strong>Loaded custom LoRA:</strong></span>
102
  <div style="margin-top: 8px;">
103
  <h4>{repo_name}</h4>
104
- <small>{"Using: <code><b>"+trigger_word+"</b></code> as trigger word" if trigger_word else "No trigger word found"}</small>
105
  </div>
106
  </div>
107
  '''
@@ -112,10 +112,10 @@ def load_custom_lora(link):
112
  "trigger_word": trigger_word
113
  }
114
 
115
- return gr.update(visible=True), card, gr.update(visible=True), custom_lora_data, gr.Gallery(selected_index=None), f"Custom: {repo_name}", None
116
 
117
  except Exception as e:
118
- 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
119
 
120
  def remove_custom_lora():
121
  """Remove custom LoRA"""
@@ -224,27 +224,125 @@ css = """
224
  #gallery{
225
  overflow: scroll !important
226
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  """
228
 
229
  # Create Gradio interface
230
  with gr.Blocks(css=css) as demo:
231
  gr_flux_loras = gr.State(value=flux_loras_raw)
232
 
233
- title = gr.HTML(
234
- """<h1> FLUX.1 Kontext Portrait πŸ‘©πŸ»β€πŸŽ€
235
- <br><small style="font-size: 13px; opacity: 0.75;">Flux.1 Kontext [dev] + community Flux LoRAs πŸ€—</small></h1>""",
236
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
 
238
  selected_state = gr.State(value=None)
239
  custom_loaded_lora = gr.State(value=None)
240
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  with gr.Row(elem_id="main_app"):
242
  with gr.Column(scale=4, elem_id="box_column"):
243
  with gr.Group(elem_id="gallery_box"):
244
- input_image = gr.Image(label="Upload a picture of yourself", type="pil", height=300)
 
 
 
 
 
245
 
 
246
  gallery = gr.Gallery(
247
- label="Pick a LoRA",
248
  allow_preview=False,
249
  columns=3,
250
  elem_id="gallery",
@@ -258,53 +356,58 @@ with gr.Blocks(css=css) as demo:
258
  visible=False
259
  )
260
  custom_model_card = gr.HTML(visible=False)
261
- custom_model_button = gr.Button("Remove custom LoRA", visible=False)
262
 
263
  with gr.Column(scale=5):
 
 
 
 
 
 
264
  with gr.Row():
265
  prompt = gr.Textbox(
266
- label="Editing Prompt",
267
- show_label=False,
268
  lines=1,
269
  max_lines=1,
270
- placeholder="optional description, e.g. 'a man with glasses and a beard'",
271
  elem_id="prompt"
272
  )
273
- run_button = gr.Button("Generate", elem_id="run_button")
274
 
275
- result = gr.Image(label="Generated Image", interactive=False)
276
- reuse_button = gr.Button("Reuse this image", visible=False)
277
 
278
- with gr.Accordion("Advanced Settings", open=False):
279
  lora_scale = gr.Slider(
280
- label="LoRA Scale",
281
  minimum=0,
282
  maximum=2,
283
  step=0.1,
284
  value=1.5,
285
- info="Controls the strength of the LoRA effect"
286
  )
287
  seed = gr.Slider(
288
- label="Seed",
289
  minimum=0,
290
  maximum=MAX_SEED,
291
  step=1,
292
  value=0,
 
 
 
 
 
293
  )
294
- randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
295
  guidance_scale = gr.Slider(
296
  label="Guidance Scale",
297
  minimum=1,
298
  maximum=10,
299
  step=0.1,
300
  value=2.5,
 
301
  )
302
-
303
- prompt_title = gr.Markdown(
304
- value="### Click on a LoRA in the gallery to select it",
305
- visible=True,
306
- elem_id="selected_lora",
307
- )
308
 
309
  # Event handlers
310
  custom_model.input(
 
52
  def update_selection(selected_state: gr.SelectData, flux_loras):
53
  """Update UI when a LoRA is selected"""
54
  if selected_state.index >= len(flux_loras):
55
+ return "### πŸ“Œ No style selected yet", gr.update(), None
56
 
57
  lora_repo = flux_loras[selected_state.index]["repo"]
58
  trigger_word = flux_loras[selected_state.index]["trigger_word"]
59
 
60
+ updated_text = f"### βœ… Selected Style: {flux_loras[selected_state.index]['title']}"
61
+ new_placeholder = f"Optional: Add extra details, e.g., 'a man with glasses' or 'woman with long hair'"
62
 
63
  return updated_text, gr.update(placeholder=new_placeholder), selected_state.index
64
 
 
91
  def load_custom_lora(link):
92
  """Load custom LoRA from user input"""
93
  if not link:
94
+ return gr.update(visible=False), "", gr.update(visible=False), None, gr.Gallery(selected_index=None), "### πŸ“Œ Please click on a style from the gallery below", None
95
 
96
  try:
97
  repo_name, weights_file, trigger_word = get_huggingface_lora(link)
98
 
99
  card = f'''
100
  <div style="border: 1px solid #ddd; padding: 10px; border-radius: 8px; margin: 10px 0;">
101
+ <span><strong>Custom style loaded:</strong></span>
102
  <div style="margin-top: 8px;">
103
  <h4>{repo_name}</h4>
104
+ <small>{"Using trigger word: <code><b>"+trigger_word+"</b></code>" if trigger_word else "No trigger word found"}</small>
105
  </div>
106
  </div>
107
  '''
 
112
  "trigger_word": trigger_word
113
  }
114
 
115
+ return gr.update(visible=True), card, gr.update(visible=True), custom_lora_data, gr.Gallery(selected_index=None), f"βœ… Custom Style: {repo_name}", None
116
 
117
  except Exception as e:
118
+ return gr.update(visible=True), f"Error: {str(e)}", gr.update(visible=False), None, gr.update(), "### πŸ“Œ Please click on a style from the gallery below", None
119
 
120
  def remove_custom_lora():
121
  """Remove custom LoRA"""
 
224
  #gallery{
225
  overflow: scroll !important
226
  }
227
+ .app-intro {
228
+ background: linear-gradient(135deg, #f6f9fc 0%, #e9f3ff 100%);
229
+ border-radius: 12px;
230
+ padding: 20px;
231
+ margin-bottom: 20px;
232
+ border: 1px solid #e1e8f0;
233
+ }
234
+ .step-card {
235
+ background: white;
236
+ border: 1px solid #e2e8f0;
237
+ border-radius: 8px;
238
+ padding: 15px;
239
+ margin: 10px 0;
240
+ box-shadow: 0 2px 4px rgba(0,0,0,0.05);
241
+ }
242
+ .tips-box {
243
+ background: #fff8dc;
244
+ border: 1px solid #ffd700;
245
+ border-radius: 8px;
246
+ padding: 12px;
247
+ margin-top: 15px;
248
+ }
249
  """
250
 
251
  # Create Gradio interface
252
  with gr.Blocks(css=css) as demo:
253
  gr_flux_loras = gr.State(value=flux_loras_raw)
254
 
255
+ # App title and introduction
256
+ with gr.Column():
257
+ gr.HTML(
258
+ """
259
+ <div style="text-align: center; margin-bottom: 30px;">
260
+ <h1 style="font-size: 2.5em; margin-bottom: 10px;">
261
+ 🎨 AI Portrait Style Transfer Master
262
+ </h1>
263
+ <p style="font-size: 1.2em; color: #666;">
264
+ Transform your photos into various artistic styles while preserving facial features
265
+ </p>
266
+ </div>
267
+ """
268
+ )
269
+
270
+ # Application introduction card
271
+ with gr.Row():
272
+ gr.HTML(
273
+ """
274
+ <div class="app-intro">
275
+ <h2 style="margin-top: 0;">✨ Welcome to AI Portrait Style Transfer</h2>
276
+ <p style="line-height: 1.8;">
277
+ This is a powerful AI tool that can transform your portrait photos into various unique artistic styles.
278
+ Whether it's cartoon, oil painting, sketch, or other creative styles, it preserves your facial features
279
+ while giving your photos a completely new artistic expression.
280
+ </p>
281
+ <div style="margin-top: 15px;">
282
+ <strong>🎯 Key Features:</strong>
283
+ <ul style="margin-top: 8px; line-height: 1.8;">
284
+ <li>Preserves original facial features, ensuring person remains recognizable</li>
285
+ <li>Multiple preset artistic styles to choose from</li>
286
+ <li>Supports custom descriptions for fine-tuned effects</li>
287
+ <li>One-click generation, simple and fast operation</li>
288
+ </ul>
289
+ </div>
290
+ </div>
291
+ """
292
+ )
293
 
294
  selected_state = gr.State(value=None)
295
  custom_loaded_lora = gr.State(value=None)
296
 
297
+ # How to use
298
+ with gr.Accordion("πŸ“– How to Use (Click to expand)", open=False):
299
+ gr.HTML(
300
+ """
301
+ <div style="padding: 10px;">
302
+ <h3>πŸš€ Quick Start:</h3>
303
+ <div class="step-card">
304
+ <h4>Step 1: Upload Your Photo</h4>
305
+ <p>Click the upload area on the left and select a clear portrait photo. Front-facing photos work best.</p>
306
+ </div>
307
+ <div class="step-card">
308
+ <h4>Step 2: Choose an Art Style</h4>
309
+ <p>Browse the style gallery and click on the artistic style you like. Each style has a preview image for reference.</p>
310
+ </div>
311
+ <div class="step-card">
312
+ <h4>Step 3: Add Description (Optional)</h4>
313
+ <p>If needed, you can add extra descriptions in the text box, such as "wearing glasses", "smiling", etc.</p>
314
+ </div>
315
+ <div class="step-card">
316
+ <h4>Step 4: Generate Image</h4>
317
+ <p>Click the "Generate" button and wait for AI to process your photo. It usually takes 10-30 seconds.</p>
318
+ </div>
319
+
320
+ <div class="tips-box">
321
+ <h4>πŸ’‘ Pro Tips:</h4>
322
+ <ul style="margin-top: 8px; line-height: 1.8;">
323
+ <li><strong>Photo Requirements:</strong> Upload clear front-facing portrait photos with good lighting and unobstructed face</li>
324
+ <li><strong>Style Intensity:</strong> Adjust "LoRA Scale" in Advanced Settings to control the strength of style transfer</li>
325
+ <li><strong>Multiple Attempts:</strong> Enable "Randomize seed" to generate different variations</li>
326
+ <li><strong>Save Results:</strong> Right-click on the generated image to save it locally</li>
327
+ </ul>
328
+ </div>
329
+ </div>
330
+ """
331
+ )
332
+
333
  with gr.Row(elem_id="main_app"):
334
  with gr.Column(scale=4, elem_id="box_column"):
335
  with gr.Group(elem_id="gallery_box"):
336
+ input_image = gr.Image(
337
+ label="πŸ“Έ Upload Your Portrait Photo",
338
+ type="pil",
339
+ height=300,
340
+ elem_classes=["upload-area"]
341
+ )
342
 
343
+ gr.Markdown("### 🎨 Choose an Art Style")
344
  gallery = gr.Gallery(
345
+ label="Style Gallery (Click to select)",
346
  allow_preview=False,
347
  columns=3,
348
  elem_id="gallery",
 
356
  visible=False
357
  )
358
  custom_model_card = gr.HTML(visible=False)
359
+ custom_model_button = gr.Button("Remove custom style", visible=False)
360
 
361
  with gr.Column(scale=5):
362
+ prompt_title = gr.Markdown(
363
+ value="### πŸ“Œ Please click on a style from the gallery on the left",
364
+ visible=True,
365
+ elem_id="selected_lora",
366
+ )
367
+
368
  with gr.Row():
369
  prompt = gr.Textbox(
370
+ label="Additional Description (Optional)",
371
+ show_label=True,
372
  lines=1,
373
  max_lines=1,
374
+ placeholder="Optional: Add extra details, e.g., 'a man with glasses' or 'woman with long hair'",
375
  elem_id="prompt"
376
  )
377
+ run_button = gr.Button("🎨 Generate", elem_id="run_button", variant="primary")
378
 
379
+ result = gr.Image(label="Generated Result", interactive=False)
380
+ reuse_button = gr.Button("♻️ Use this image as new input", visible=False)
381
 
382
+ with gr.Accordion("βš™οΈ Advanced Settings", open=False):
383
  lora_scale = gr.Slider(
384
+ label="Style Intensity",
385
  minimum=0,
386
  maximum=2,
387
  step=0.1,
388
  value=1.5,
389
+ info="Controls the strength of the artistic style (recommended: 1.0-1.5)"
390
  )
391
  seed = gr.Slider(
392
+ label="Random Seed",
393
  minimum=0,
394
  maximum=MAX_SEED,
395
  step=1,
396
  value=0,
397
+ info="Same seed will generate the same result"
398
+ )
399
+ randomize_seed = gr.Checkbox(
400
+ label="Randomize seed (generate different effects each time)",
401
+ value=True
402
  )
 
403
  guidance_scale = gr.Slider(
404
  label="Guidance Scale",
405
  minimum=1,
406
  maximum=10,
407
  step=0.1,
408
  value=2.5,
409
+ info="Controls how closely the image follows the prompt"
410
  )
 
 
 
 
 
 
411
 
412
  # Event handlers
413
  custom_model.input(