theoracle commited on
Commit
2c740bc
Β·
1 Parent(s): 766704a

Fix step error handling and wire up error_box

Browse files
Files changed (1) hide show
  1. app.py +63 -103
app.py CHANGED
@@ -1,130 +1,90 @@
 
1
  import os
2
  import traceback
3
  from datetime import datetime
4
  import torch, gc
5
  from PIL import Image
6
  import gradio as gr
 
7
  from inference import generate_with_lora
8
  from background_edit import run_background_removal_and_inpaint
9
 
10
-
11
  # ───────────────────── Helpers ─────────────────────
12
  def _print_trace():
13
  traceback.print_exc()
14
 
15
- def safe_generate_with_lora(*a, **kw):
16
- try:
17
- return generate_with_lora(*a, **kw)
18
- except gr.Error:
19
- _print_trace()
20
- raise
21
- except Exception as e:
22
- _print_trace()
23
- raise gr.Error(f"Image generation failed: {e}")
24
-
25
  def unload_models():
26
  torch.cuda.empty_cache()
27
  gc.collect()
28
 
29
- def safe_run_background(image_path, *args, **kwargs):
30
  try:
31
- unload_models() # free VRAM before loading the inpainting model
32
- return run_background_removal_and_inpaint(image_path, *args, **kwargs)
33
- except Exception as e:
34
- _print_trace()
35
- raise gr.Error(f"[Step 2] Background replacement failed: {type(e).__name__}: {e}")
 
 
 
 
 
 
 
36
 
37
- def _save_to_disk(img):
38
- if img is None:
39
- return gr.skip()
40
-
41
- os.makedirs("./outputs", exist_ok=True)
42
- ts = datetime.now().strftime("%Y%m%d_%H%M%S")
43
- path = f"./outputs/step1_result_{ts}.png"
44
- img.save(path)
45
- return path
46
 
 
 
 
 
47
 
48
- # ───────────────────── UI ─────────────────────
49
- shared_output_path = gr.State() # holds file path to Step 1 output
50
- original_input = gr.State() # holds the original upload (if needed)
51
 
 
 
 
 
 
 
 
52
  with gr.Blocks() as demo:
53
- demo.queue()
54
-
55
- # ─────────── STEP 1: Headshot Refinement ───────────
56
- with gr.Tab("Step 1: Headshot Refinement"):
57
- with gr.Row():
58
- input_image = gr.Image(type="pil", label="Upload Headshot")
59
- output_image = gr.Image(type="pil", label="Refined Output")
60
-
61
- with gr.Row():
62
- prompt = gr.Textbox(
63
- label="Prompt",
64
- value="a professional corporate headshot of a confident woman in her 30s with blonde hair"
65
- )
66
- negative_prompt = gr.Textbox(
67
- label="Negative Prompt",
68
- value="deformed, cartoon, anime, illustration, painting, drawing, sketch, low resolution, blurry, out of focus, pixelated"
69
- )
70
-
71
- with gr.Row():
72
- strength = gr.Slider(0.1, 1.0, value=0.20, step=0.05, label="Strength")
73
- guidance = gr.Slider(1, 20, value=17.0, step=0.5, label="Guidance Scale")
74
-
75
- run_btn = gr.Button("Generate")
76
-
77
- event = (
78
- run_btn.click(
79
- fn=safe_generate_with_lora,
80
- inputs=[input_image, prompt, negative_prompt, strength, guidance],
81
- outputs=output_image,
82
- )
83
- .then(_save_to_disk, output_image, shared_output_path)
84
- .then(lambda x: x, input_image, original_input)
85
- )
86
 
87
- # ─────────── STEP 2: Background Replacement ───────────
88
- with gr.Tab("Step 2: Replace Background"):
89
- error_box = gr.Markdown(value="", visible=True)
90
-
91
- with gr.Row():
92
- inpaint_prompt = gr.Textbox(
93
- label="New Background Prompt",
94
- value="modern open-plan startup office background, natural lighting, glass walls, clean design, minimalistic decor"
95
- )
96
- inpaint_negative = gr.Textbox(
97
- label="Negative Prompt",
98
- value="dark lighting, cluttered background, fantasy elements, cartoon, anime, painting, low quality, distorted shapes"
99
- )
100
-
101
- with gr.Row():
102
- inpaint_result = gr.Image(type="pil", label="Inpainted Image")
103
-
104
- with gr.Row():
105
- inpaint_btn = gr.Button("Remove Background & Inpaint", interactive=False)
106
-
107
- def guarded_inpaint(image_path, prompt_bg, neg_bg):
108
- if not image_path or not os.path.isfile(image_path):
109
- return None, "**πŸ›‘ Error:** No valid headshot found β€” please run Step 1 first."
110
-
111
- try:
112
- print(f"[DEBUG] Loading image from: {image_path}", flush=True)
113
- result = safe_run_background(image_path, prompt_bg, neg_bg)
114
- return result, ""
115
- except gr.Error as e:
116
- print(f"[Step 2 gr.Error] {e}", flush=True)
117
- return None, f"**πŸ›‘ Step 2 Failed:** {str(e)}"
118
- except Exception as e:
119
- print(f"[Step 2 UNEXPECTED ERROR] {type(e).__name__}: {e}", flush=True)
120
- return None, f"**❌ Unexpected Error:** {type(e).__name__}: {e}"
121
-
122
- inpaint_btn.click(
123
- fn=guarded_inpaint,
124
- inputs=[shared_output_path, inpaint_prompt, inpaint_negative],
125
- outputs=[inpaint_result, error_box],
126
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
- event.then(lambda: gr.update(interactive=True), None, inpaint_btn)
 
 
 
 
129
 
130
- demo.launch(debug=True)
 
1
+
2
  import os
3
  import traceback
4
  from datetime import datetime
5
  import torch, gc
6
  from PIL import Image
7
  import gradio as gr
8
+
9
  from inference import generate_with_lora
10
  from background_edit import run_background_removal_and_inpaint
11
 
 
12
  # ───────────────────── Helpers ─────────────────────
13
  def _print_trace():
14
  traceback.print_exc()
15
 
 
 
 
 
 
 
 
 
 
 
16
  def unload_models():
17
  torch.cuda.empty_cache()
18
  gc.collect()
19
 
20
+ def safe_generate_and_inpaint(image, prompt, negative_prompt, strength, guidance_scale):
21
  try:
22
+ if image is None:
23
+ raise gr.Error("Please upload an image first.")
24
+
25
+ # Step 1: Refinement
26
+ print("[INFO] Step 1: Generating refined image...", flush=True)
27
+ refined = generate_with_lora(
28
+ image=image,
29
+ prompt=prompt,
30
+ negative_prompt=negative_prompt,
31
+ strength=strength,
32
+ guidance_scale=guidance_scale,
33
+ )
34
 
35
+ # Save to disk
36
+ os.makedirs("./outputs", exist_ok=True)
37
+ ts = datetime.now().strftime("%Y%m%d_%H%M%S")
38
+ path = f"./outputs/step1_result_{ts}.png"
39
+ refined.save(path)
 
 
 
 
40
 
41
+ # Step 2: Background removal and inpainting
42
+ print("[INFO] Step 2: Inpainting background...", flush=True)
43
+ unload_models()
44
+ result = run_background_removal_and_inpaint(path, prompt, negative_prompt)
45
 
46
+ return refined, result, ""
 
 
47
 
48
+ except gr.Error as e:
49
+ return None, None, f"πŸ›‘ {str(e)}"
50
+ except Exception as e:
51
+ _print_trace()
52
+ return None, None, f"❌ Unexpected Error: {type(e).__name__}: {str(e)}"
53
+
54
+ # ───────────────────── Gradio UI ─────────────────────
55
  with gr.Blocks() as demo:
56
+ gr.Markdown("## πŸ–ΌοΈ AI Headshot Enhancer + Background Replacer")
57
+ gr.Markdown("Upload a headshot, adjust the prompt, and click one button. We'll refine the image and replace the background automatically.")
58
+
59
+ with gr.Row():
60
+ input_image = gr.Image(type="pil", label="Upload Headshot")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
+ with gr.Row():
63
+ prompt = gr.Textbox(
64
+ label="Prompt",
65
+ value="a professional corporate headshot of a confident woman in her 30s with blonde hair"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  )
67
+ negative_prompt = gr.Textbox(
68
+ label="Negative Prompt",
69
+ value="deformed, cartoon, anime, illustration, painting, drawing, sketch, low resolution, blurry, out of focus, pixelated"
70
+ )
71
+
72
+ with gr.Row():
73
+ strength = gr.Slider(0.1, 1.0, value=0.20, step=0.05, label="Refinement Strength")
74
+ guidance = gr.Slider(1, 20, value=17.0, step=0.5, label="Guidance Scale")
75
+
76
+ go_btn = gr.Button("✨ Run Full Process (Refine + Inpaint)")
77
+
78
+ with gr.Row():
79
+ output_refined = gr.Image(type="pil", label="Step 1: Refined Headshot")
80
+ output_final = gr.Image(type="pil", label="Step 2: Final Image with Background")
81
+
82
+ error_box = gr.Markdown(label="Error", value="", visible=True)
83
 
84
+ go_btn.click(
85
+ fn=safe_generate_and_inpaint,
86
+ inputs=[input_image, prompt, negative_prompt, strength, guidance],
87
+ outputs=[output_refined, output_final, error_box]
88
+ )
89
 
90
+ demo.launch(debug=True)