Jds20001 commited on
Commit
ea17c8b
·
verified ·
1 Parent(s): 7c50306

Add Quick Start scenario pickers (Norma Jean + Marilyn) with per-scenario input-requirement hints

Browse files
Files changed (1) hide show
  1. app.py +143 -36
app.py CHANGED
@@ -342,25 +342,117 @@ css = """
342
  }
343
  """
344
 
345
- IDENTITY_PRESETS = [
346
- ("Face Close-up", "Same person, face close-up portrait, studio lighting, sharp focus, looking slightly left, clean solid background"),
347
- ("3/4 Angle", "Same person, three-quarter angle view, upper body, soft directional light from left, slight smile"),
348
- ("Full Body", "Same person, full body standing, neutral pose, studio lighting, solid gray background"),
349
- ("Over Shoulder", "Same person from behind, looking back over shoulder, natural light, upper body and face visible"),
350
- ("Shirtless", "Same person, shirtless, upper body, warm studio lighting, confident relaxed expression, simple background"),
351
- ("Golden Hour", "Same person, golden hour sunlight, outdoor, warm tones, half body, candid natural feel"),
352
- ("Dramatic Lit", "Same person, dramatic chiaroscuro side lighting, moody shadows, face and torso, high contrast, cinematic"),
353
- ("Mirror Shot", "Same person, casual mirror selfie, bathroom or bedroom, natural smartphone lighting, authentic and candid"),
354
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
355
 
356
- EXPLICIT_PRESETS = [
357
- ("Full Nude Stand", "same person, fully nude, full body standing, anatomically correct male, penis visible, studio lighting, solid neutral background, realistic, high quality"),
358
- ("Nude Reclining", "same person, nude, reclining on bed, relaxed natural pose, full body visible, anatomically detailed male, warm soft bedroom light, intimate, realistic"),
359
- ("Shower", "same person, nude, wet skin, standing in shower, water droplets, steam, full body, anatomically correct, natural lighting, realistic"),
360
- ("Nude Back", "same person, nude from behind, athletic back and buttocks visible, looking over shoulder, studio lighting, artistic, realistic"),
361
- ("Seated Nude", "same person, seated nude on chair, legs apart, confident relaxed pose, full body, anatomically detailed, studio lighting, realistic"),
362
- ("Morning Stretch", "same person, nude, stretching in morning light, full body, anatomically correct male, golden hour through window, natural, realistic"),
363
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
364
 
365
  with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
366
  gallery_state = gr.State([])
@@ -399,6 +491,17 @@ FLUX.1-dev has weaker safety training, so the NSFW LoRAs actually work here. Bes
399
  type="pil",
400
  height=300,
401
  )
 
 
 
 
 
 
 
 
 
 
 
402
  id_prompt = gr.Textbox(
403
  label="Variation Prompt",
404
  placeholder="Same person, shirtless, different angle...",
@@ -408,15 +511,6 @@ FLUX.1-dev has weaker safety training, so the NSFW LoRAs actually work here. Bes
408
  id_gen_btn = gr.Button("Generate", variant="primary", scale=2)
409
  id_gen_add_btn = gr.Button("Generate & Add", variant="secondary", scale=2)
410
 
411
- with gr.Accordion("Presets", open=True):
412
- for i in range(0, len(IDENTITY_PRESETS), 2):
413
- with gr.Row():
414
- for j in range(2):
415
- if i + j < len(IDENTITY_PRESETS):
416
- label, text = IDENTITY_PRESETS[i + j]
417
- btn = gr.Button(label, size="sm", min_width=120)
418
- btn.click(fn=make_preset_fn(text), outputs=[id_prompt])
419
-
420
  id_candid = gr.Checkbox(
421
  label="Candid realism mode (kills the AI gloss)",
422
  value=True,
@@ -472,6 +566,16 @@ FLUX.1-dev has weaker safety training, so the NSFW LoRAs actually work here. Bes
472
  lines=1,
473
  info="Gets prepended to every prompt. The more specific, the more the output looks like your guy.",
474
  )
 
 
 
 
 
 
 
 
 
 
475
  ex_prompt = gr.Textbox(
476
  label="Explicit Prompt",
477
  placeholder="same person, fully nude, anatomically correct...",
@@ -481,15 +585,6 @@ FLUX.1-dev has weaker safety training, so the NSFW LoRAs actually work here. Bes
481
  ex_gen_btn = gr.Button("Generate", variant="primary", scale=2)
482
  ex_gen_add_btn = gr.Button("Generate & Add", variant="secondary", scale=2)
483
 
484
- with gr.Accordion("Presets", open=True):
485
- for i in range(0, len(EXPLICIT_PRESETS), 2):
486
- with gr.Row():
487
- for j in range(2):
488
- if i + j < len(EXPLICIT_PRESETS):
489
- label, text = EXPLICIT_PRESETS[i + j]
490
- btn = gr.Button(label, size="sm", min_width=120)
491
- btn.click(fn=make_preset_fn(text), outputs=[ex_prompt])
492
-
493
  with gr.Accordion("Advanced", open=False):
494
  ex_seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
495
  ex_randomize = gr.Checkbox(label="Randomize seed", value=True)
@@ -551,6 +646,18 @@ FLUX.1-dev has weaker safety training, so the NSFW LoRAs actually work here. Bes
551
  "Train your character LoRAs here, animate them there.</p>"
552
  )
553
 
 
 
 
 
 
 
 
 
 
 
 
 
554
  # --- Identity tab events ---
555
  id_gen_btn.click(
556
  fn=generate_identity,
 
342
  }
343
  """
344
 
345
+ # ============ Quick Start Scenarios (one-click: sets prompt + every setting + tells
346
+ # you what the input should be) ============
347
+ # Identity (Norma Jean / Kontext) scenarios. Kontext re-poses from a reference, so the
348
+ # input hint is about what reference photo gives the cleanest result.
349
+ IDENTITY_SCENARIOS = {
350
+ "Face close-up (studio)": {
351
+ "prompt": "Same person, face close-up portrait, sharp focus, looking toward camera, even studio lighting, clean solid background",
352
+ "candid": False, "nsfw": 0.3, "realism": 1.0, "guidance": 2.5, "steps": 28,
353
+ "hint": "a clear, well-lit photo where the FACE is visible. Front-on or a slight angle is best.",
354
+ },
355
+ "3/4 angle portrait": {
356
+ "prompt": "Same person, three-quarter angle view, upper body, soft directional light from the left, subtle natural expression",
357
+ "candid": False, "nsfw": 0.3, "realism": 1.0, "guidance": 2.5, "steps": 28,
358
+ "hint": "any clear face photo. Head-and-shoulders works great.",
359
+ },
360
+ "Full body (training staple)": {
361
+ "prompt": "Same person, full body standing, neutral relaxed pose, even studio lighting, solid gray background",
362
+ "candid": False, "nsfw": 0.4, "realism": 1.0, "guidance": 2.5, "steps": 28,
363
+ "hint": "a photo that shows his build if you have one. Face-only still works — the body is inferred.",
364
+ },
365
+ "Shirtless torso": {
366
+ "prompt": "Same person, shirtless, upper body and torso, warm studio light, relaxed confident expression, simple background",
367
+ "candid": False, "nsfw": 1.0, "realism": 1.0, "guidance": 2.5, "steps": 28,
368
+ "hint": "face + upper body if possible. Kontext keeps the face and generates the torso.",
369
+ },
370
+ "Candid mirror selfie": {
371
+ "prompt": "Same person, casual mirror selfie, phone in hand, bedroom or bathroom, natural window light, authentic",
372
+ "candid": True, "nsfw": 0.5, "realism": 1.0, "guidance": 2.5, "steps": 28,
373
+ "hint": "any clear face photo. This one leans hardest on candid realism.",
374
+ },
375
+ "Golden hour outdoor": {
376
+ "prompt": "Same person, outdoors at golden hour, warm low sunlight, half body, relaxed candid feel",
377
+ "candid": True, "nsfw": 0.4, "realism": 1.0, "guidance": 2.5, "steps": 28,
378
+ "hint": "a clear face photo — the lighting gets replaced with golden hour.",
379
+ },
380
+ "Dramatic cinematic": {
381
+ "prompt": "Same person, dramatic side lighting, moody shadows, face and torso, high contrast, cinematic",
382
+ "candid": False, "nsfw": 0.5, "realism": 1.0, "guidance": 3.0, "steps": 30,
383
+ "hint": "a sharp, well-exposed face photo. Dramatic lighting needs clean features to work from.",
384
+ },
385
+ "Over-the-shoulder / back": {
386
+ "prompt": "Same person seen from behind, looking back over the shoulder, upper body and face visible, natural light",
387
+ "candid": False, "nsfw": 0.6, "realism": 1.0, "guidance": 2.5, "steps": 28,
388
+ "hint": "a front-facing face photo is fine — the model turns the pose for you.",
389
+ },
390
+ }
391
 
392
+ # Explicit (Marilyn / FLUX.1-dev img2img) scenarios. This is img2img: it KEEPS the
393
+ # composition of the starting image, so the input hint really matters here.
394
+ EXPLICIT_SCENARIOS = {
395
+ "Full nude standing": {
396
+ "prompt": "same person, fully nude, full body standing, anatomically correct male, penis visible, studio lighting, solid neutral background, realistic, high quality",
397
+ "strength": 0.80, "guidance": 3.5, "steps": 28, "nsfw": 1.0, "realism": 1.0, "candid": False,
398
+ "hint": "a FULL-BODY STANDING shot. Img2img keeps the pose start standing to get a standing nude.",
399
+ },
400
+ "Nude — reclining / lying down": {
401
+ "prompt": "same person, nude, reclining on bed, relaxed, full body visible, anatomically detailed male, warm soft bedroom light, intimate, realistic",
402
+ "strength": 0.80, "guidance": 3.5, "steps": 28, "nsfw": 1.0, "realism": 1.0, "candid": False,
403
+ "hint": "a shot where he is ALREADY LYING DOWN or reclining. Img2img won't cleanly turn a standing photo into a lying-down one.",
404
+ },
405
+ "Shower / wet": {
406
+ "prompt": "same person, nude, wet skin, standing in shower, water droplets, steam, full body, anatomically correct, natural lighting, realistic",
407
+ "strength": 0.80, "guidance": 3.5, "steps": 28, "nsfw": 1.0, "realism": 1.0, "candid": False,
408
+ "hint": "a STANDING full-body shot.",
409
+ },
410
+ "Nude from behind": {
411
+ "prompt": "same person, nude from behind, athletic back and buttocks visible, looking over shoulder, studio lighting, realistic",
412
+ "strength": 0.80, "guidance": 3.5, "steps": 28, "nsfw": 1.0, "realism": 1.0, "candid": False,
413
+ "hint": "a standing shot; a back or 3/4 view works best.",
414
+ },
415
+ "Keep-the-face light nude": {
416
+ "prompt": "same person, nude, natural relaxed pose, anatomically correct male, soft lighting, realistic",
417
+ "strength": 0.60, "guidance": 3.5, "steps": 28, "nsfw": 1.0, "realism": 1.0, "candid": False,
418
+ "hint": "your BEST identity shot. Low strength (0.60) preserves the face — also fill in the Character Description box.",
419
+ },
420
+ "Explicit — max freedom": {
421
+ "prompt": "same person, nude, explicit, anatomically detailed male, realistic, high quality",
422
+ "strength": 0.85, "guidance": 3.5, "steps": 28, "nsfw": 1.0, "realism": 1.0, "candid": False,
423
+ "hint": "a full-body shot. High strength (0.85) changes the body most — fill in the Character Description box to hold the face.",
424
+ },
425
+ }
426
+
427
+
428
+ def apply_identity_scenario(name):
429
+ s = IDENTITY_SCENARIOS.get(name)
430
+ if not s:
431
+ return (gr.update(),) * 7
432
+ return (
433
+ gr.update(value=s["prompt"]),
434
+ gr.update(value=s["candid"]),
435
+ gr.update(value=s["nsfw"]),
436
+ gr.update(value=s["realism"]),
437
+ gr.update(value=s["guidance"]),
438
+ gr.update(value=s["steps"]),
439
+ gr.update(value=f"**Best input for this scenario:** {s['hint']}"),
440
+ )
441
+
442
+
443
+ def apply_explicit_scenario(name):
444
+ s = EXPLICIT_SCENARIOS.get(name)
445
+ if not s:
446
+ return (gr.update(),) * 7
447
+ return (
448
+ gr.update(value=s["prompt"]),
449
+ gr.update(value=s["strength"]),
450
+ gr.update(value=s["nsfw"]),
451
+ gr.update(value=s["realism"]),
452
+ gr.update(value=s["guidance"]),
453
+ gr.update(value=s["steps"]),
454
+ gr.update(value=f"**Best input for this scenario:** {s['hint']}"),
455
+ )
456
 
457
  with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
458
  gallery_state = gr.State([])
 
491
  type="pil",
492
  height=300,
493
  )
494
+
495
+ with gr.Group():
496
+ gr.Markdown("**🚀 Quick Start — pick a scenario, everything gets set up for you**")
497
+ with gr.Row():
498
+ id_scenario_dd = gr.Dropdown(
499
+ choices=list(IDENTITY_SCENARIOS.keys()),
500
+ label="Scenario", value=None, scale=3,
501
+ )
502
+ id_scenario_btn = gr.Button("Apply", variant="secondary", scale=1)
503
+ id_scenario_hint = gr.Markdown("")
504
+
505
  id_prompt = gr.Textbox(
506
  label="Variation Prompt",
507
  placeholder="Same person, shirtless, different angle...",
 
511
  id_gen_btn = gr.Button("Generate", variant="primary", scale=2)
512
  id_gen_add_btn = gr.Button("Generate & Add", variant="secondary", scale=2)
513
 
 
 
 
 
 
 
 
 
 
514
  id_candid = gr.Checkbox(
515
  label="Candid realism mode (kills the AI gloss)",
516
  value=True,
 
566
  lines=1,
567
  info="Gets prepended to every prompt. The more specific, the more the output looks like your guy.",
568
  )
569
+ with gr.Group():
570
+ gr.Markdown("**🚀 Quick Start — pick a scenario, everything gets set up for you**")
571
+ with gr.Row():
572
+ ex_scenario_dd = gr.Dropdown(
573
+ choices=list(EXPLICIT_SCENARIOS.keys()),
574
+ label="Scenario", value=None, scale=3,
575
+ )
576
+ ex_scenario_btn = gr.Button("Apply", variant="secondary", scale=1)
577
+ ex_scenario_hint = gr.Markdown("")
578
+
579
  ex_prompt = gr.Textbox(
580
  label="Explicit Prompt",
581
  placeholder="same person, fully nude, anatomically correct...",
 
585
  ex_gen_btn = gr.Button("Generate", variant="primary", scale=2)
586
  ex_gen_add_btn = gr.Button("Generate & Add", variant="secondary", scale=2)
587
 
 
 
 
 
 
 
 
 
 
588
  with gr.Accordion("Advanced", open=False):
589
  ex_seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
590
  ex_randomize = gr.Checkbox(label="Randomize seed", value=True)
 
646
  "Train your character LoRAs here, animate them there.</p>"
647
  )
648
 
649
+ # --- Quick Start scenario events ---
650
+ id_scenario_btn.click(
651
+ fn=apply_identity_scenario,
652
+ inputs=[id_scenario_dd],
653
+ outputs=[id_prompt, id_candid, id_nsfw, id_realism, id_guidance, id_steps, id_scenario_hint],
654
+ )
655
+ ex_scenario_btn.click(
656
+ fn=apply_explicit_scenario,
657
+ inputs=[ex_scenario_dd],
658
+ outputs=[ex_prompt, ex_strength, ex_nsfw, ex_realism, ex_guidance, ex_steps, ex_scenario_hint],
659
+ )
660
+
661
  # --- Identity tab events ---
662
  id_gen_btn.click(
663
  fn=generate_identity,