MogensR commited on
Commit
a24b923
Β·
1 Parent(s): 19adb9d

Update ui/ui_components.py

Browse files
Files changed (1) hide show
  1. ui/ui_components.py +102 -12
ui/ui_components.py CHANGED
@@ -6,6 +6,7 @@
6
  * All callbacks live in ui/callbacks.py
7
  * Adds live previews for the first frame of the uploaded video
8
  and for the custom background image
 
9
  """
10
 
11
  from __future__ import annotations
@@ -34,6 +35,11 @@
34
  .sm { font-size: 13px; opacity: 0.85; }
35
  #statusbox { min-height: 120px; }
36
  .preview-img { border-radius: var(--radius); border: 1px solid rgba(0,0,0,.08); }
 
 
 
 
 
37
  """
38
 
39
  # Keep in sync with utils/cv_processing.PROFESSIONAL_BACKGROUNDS
@@ -54,6 +60,9 @@ def create_interface() -> gr.Blocks:
54
  analytics_enabled=False,
55
  theme=gr.themes.Soft()
56
  ) as demo:
 
 
 
57
 
58
  # ------------------------------------------------------------------
59
  # HERO
@@ -96,12 +105,6 @@ def create_interface() -> gr.Blocks:
96
  interactive=True
97
  )
98
 
99
- custom_bg_preview_img = gr.Image(
100
- label="Custom Background Preview",
101
- interactive=False,
102
- elem_classes=["preview-img"]
103
- )
104
-
105
  # ── Advanced options accordion ───────────────────────
106
  with gr.Accordion("Advanced", open=False):
107
  use_two_stage = gr.Checkbox(
@@ -139,6 +142,15 @@ def create_interface() -> gr.Blocks:
139
 
140
  # ── Right column ──────────────────────────────────────────
141
  with gr.Column(scale=1):
 
 
 
 
 
 
 
 
 
142
  out_video = gr.Video(label="Processed Output", interactive=False)
143
  statusbox = gr.Textbox(label="Status", lines=8, elem_id="statusbox")
144
 
@@ -197,8 +209,36 @@ def create_interface() -> gr.Blocks:
197
  # ------------------------------------------------------------------
198
  # Callback wiring
199
  # ------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  btn_load.click(cb_load_models, outputs=statusbox)
201
 
 
202
  btn_run.click(
203
  cb_process_video,
204
  inputs=[
@@ -207,16 +247,21 @@ def create_interface() -> gr.Blocks:
207
  custom_bg,
208
  use_two_stage,
209
  chroma_preset,
210
- key_color_mode, # NEW
211
  preview_mask,
212
  preview_greenscreen,
213
  ],
214
- outputs=[out_video, statusbox],
215
  )
216
 
217
  btn_cancel.click(cb_cancel, outputs=statusbox)
218
  btn_refresh.click(cb_status, outputs=[model_status, cache_status])
219
- btn_clear.click(cb_clear, outputs=[out_video, statusbox, gen_preview, gen_path])
 
 
 
 
 
220
 
221
  # AI background generation
222
  btn_gen_bg.click(
@@ -224,10 +269,55 @@ def create_interface() -> gr.Blocks:
224
  inputs=[prompt, gen_width, gen_height, bokeh, vignette, contrast],
225
  outputs=[gen_preview, gen_path],
226
  )
227
- use_gen_as_custom.click(cb_use_gen_bg, inputs=[gen_path], outputs=[custom_bg])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
 
229
  # Live previews
230
  video.change(cb_video_changed, inputs=[video], outputs=[video_preview])
231
- custom_bg.change(cb_custom_bg_preview, inputs=[custom_bg], outputs=[custom_bg_preview_img])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
 
233
- return demo
 
6
  * All callbacks live in ui/callbacks.py
7
  * Adds live previews for the first frame of the uploaded video
8
  and for the custom background image
9
+ * UPDATED: Background preview persists during processing
10
  """
11
 
12
  from __future__ import annotations
 
35
  .sm { font-size: 13px; opacity: 0.85; }
36
  #statusbox { min-height: 120px; }
37
  .preview-img { border-radius: var(--radius); border: 1px solid rgba(0,0,0,.08); }
38
+ .bg-preview-persistent {
39
+ border: 2px solid rgba(0,120,255,0.3);
40
+ background: rgba(0,120,255,0.05);
41
+ min-height: 200px;
42
+ }
43
  """
44
 
45
  # Keep in sync with utils/cv_processing.PROFESSIONAL_BACKGROUNDS
 
60
  analytics_enabled=False,
61
  theme=gr.themes.Soft()
62
  ) as demo:
63
+
64
+ # State to hold the current background preview
65
+ background_state = gr.State()
66
 
67
  # ------------------------------------------------------------------
68
  # HERO
 
105
  interactive=True
106
  )
107
 
 
 
 
 
 
 
108
  # ── Advanced options accordion ───────────────────────
109
  with gr.Accordion("Advanced", open=False):
110
  use_two_stage = gr.Checkbox(
 
142
 
143
  # ── Right column ──────────────────────────────────────────
144
  with gr.Column(scale=1):
145
+ # Persistent background preview at the top
146
+ gr.Markdown("### πŸ“Œ Background Preview")
147
+ persistent_bg_preview = gr.Image(
148
+ label="Selected Background (stays visible during processing)",
149
+ interactive=False,
150
+ elem_classes=["preview-img", "bg-preview-persistent"],
151
+ show_label=True
152
+ )
153
+
154
  out_video = gr.Video(label="Processed Output", interactive=False)
155
  statusbox = gr.Textbox(label="Status", lines=8, elem_id="statusbox")
156
 
 
209
  # ------------------------------------------------------------------
210
  # Callback wiring
211
  # ------------------------------------------------------------------
212
+
213
+ # Modified callback to update persistent preview when custom background changes
214
+ def update_persistent_preview(custom_bg_file):
215
+ """Update both the temporary preview and persistent preview"""
216
+ if custom_bg_file is None:
217
+ return None, None, None
218
+ try:
219
+ import cv2
220
+ img = cv2.imread(custom_bg_file.name)
221
+ if img is not None:
222
+ img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
223
+ return img_rgb, img_rgb, custom_bg_file # Return for both previews and state
224
+ except:
225
+ pass
226
+ return None, None, None
227
+
228
+ # Update persistent preview when background style changes (for presets)
229
+ def update_preset_preview(bg_style_choice):
230
+ """Generate preview for preset backgrounds"""
231
+ try:
232
+ from utils.cv_processing import create_professional_background
233
+ # Create a small preview version
234
+ preview_bg = create_professional_background(bg_style_choice, 640, 360)
235
+ return preview_bg
236
+ except:
237
+ return None
238
+
239
  btn_load.click(cb_load_models, outputs=statusbox)
240
 
241
+ # Modified process callback to preserve background preview
242
  btn_run.click(
243
  cb_process_video,
244
  inputs=[
 
247
  custom_bg,
248
  use_two_stage,
249
  chroma_preset,
250
+ key_color_mode,
251
  preview_mask,
252
  preview_greenscreen,
253
  ],
254
+ outputs=[out_video, statusbox], # Note: NOT clearing persistent_bg_preview
255
  )
256
 
257
  btn_cancel.click(cb_cancel, outputs=statusbox)
258
  btn_refresh.click(cb_status, outputs=[model_status, cache_status])
259
+
260
+ # Modified clear to also clear the persistent preview
261
+ btn_clear.click(
262
+ cb_clear,
263
+ outputs=[out_video, statusbox, gen_preview, gen_path, persistent_bg_preview]
264
+ )
265
 
266
  # AI background generation
267
  btn_gen_bg.click(
 
269
  inputs=[prompt, gen_width, gen_height, bokeh, vignette, contrast],
270
  outputs=[gen_preview, gen_path],
271
  )
272
+
273
+ # Modified to update persistent preview when using generated background
274
+ def use_generated_as_custom(gen_path_value):
275
+ """Use generated background as custom and update persistent preview"""
276
+ if gen_path_value:
277
+ try:
278
+ import cv2
279
+ img = cv2.imread(gen_path_value)
280
+ if img is not None:
281
+ img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
282
+ # Create a file-like object for the custom_bg component
283
+ import tempfile
284
+ import shutil
285
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.png')
286
+ cv2.imwrite(temp_file.name, img)
287
+ temp_file.close()
288
+ return temp_file.name, img_rgb
289
+ except:
290
+ pass
291
+ return None, None
292
+
293
+ use_gen_as_custom.click(
294
+ use_generated_as_custom,
295
+ inputs=[gen_path],
296
+ outputs=[custom_bg, persistent_bg_preview]
297
+ )
298
 
299
  # Live previews
300
  video.change(cb_video_changed, inputs=[video], outputs=[video_preview])
301
+
302
+ # Update persistent preview when custom background changes
303
+ custom_bg.change(
304
+ update_persistent_preview,
305
+ inputs=[custom_bg],
306
+ outputs=[video_preview, persistent_bg_preview, background_state]
307
+ )
308
+
309
+ # Update persistent preview when background style dropdown changes
310
+ bg_style.change(
311
+ update_preset_preview,
312
+ inputs=[bg_style],
313
+ outputs=[persistent_bg_preview]
314
+ )
315
+
316
+ # Initialize with default background preview
317
+ demo.load(
318
+ update_preset_preview,
319
+ inputs=[bg_style],
320
+ outputs=[persistent_bg_preview]
321
+ )
322
 
323
+ return demo