akhaliq HF Staff commited on
Commit
fc246b2
·
verified ·
1 Parent(s): fc21574

Update Gradio app with multiple files

Browse files
Files changed (2) hide show
  1. app.py +29 -122
  2. requirements.txt +33 -8
app.py CHANGED
@@ -34,15 +34,13 @@ pipe = QwenImageEditPlusPipeline.from_pretrained("Qwen/Qwen-Image-Edit-2509",
34
 
35
  pipe.load_lora_weights(
36
  "dx8152/Qwen-Image-Edit-2509-Light_restoration",
37
- weight_name="移除光影.safetensors", adapter_name="light_restoration"
38
  )
39
 
40
  pipe.set_adapters(["light_restoration"], adapter_weights=[1.])
41
  pipe.fuse_lora(adapter_names=["light_restoration"], lora_scale=1.0)
42
  pipe.unload_lora_weights()
43
 
44
-
45
-
46
  pipe.transformer.__class__ = QwenImageTransformer2DModel
47
  pipe.transformer.set_attn_processor(QwenDoubleStreamAttnProcessorFA3())
48
 
@@ -51,17 +49,6 @@ optimize_pipeline_(pipe, image=[Image.new("RGB", (1024, 1024)), Image.new("RGB",
51
 
52
  MAX_SEED = np.iinfo(np.int32).max
53
 
54
- def _generate_video_segment(input_image_path: str, output_image_path: str, prompt: str, request: gr.Request) -> str:
55
- """Generates a single video segment using the external service."""
56
- x_ip_token = request.headers['x-ip-token']
57
- video_client = Client("multimodalart/wan-2-2-first-last-frame", headers={"x-ip-token": x_ip_token})
58
- result = video_client.predict(
59
- start_image_pil=handle_file(input_image_path),
60
- end_image_pil=handle_file(output_image_path),
61
- prompt=prompt, api_name="/generate_video",
62
- )
63
- return result[0]["video"]
64
-
65
  def build_light_restoration_prompt(brightness, contrast, exposure, saturation):
66
  prompt_parts = []
67
 
@@ -131,6 +118,7 @@ def infer_light_restoration(
131
 
132
  if prompt == "Restore image lighting":
133
  return image, seed, prompt
 
134
  result = pipe(
135
  image=pil_images,
136
  prompt=prompt,
@@ -144,32 +132,6 @@ def infer_light_restoration(
144
 
145
  return result, seed, prompt
146
 
147
- def create_video_between_images(input_image, output_image, prompt: str, request: gr.Request) -> str:
148
- """Create a video between the input and output images."""
149
- if input_image is None or output_image is None:
150
- raise gr.Error("Both input and output images are required to create a video.")
151
-
152
- try:
153
-
154
- with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmp:
155
- input_image.save(tmp.name)
156
- input_image_path = tmp.name
157
-
158
- output_pil = Image.fromarray(output_image.astype('uint8'))
159
- with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as tmp:
160
- output_pil.save(tmp.name)
161
- output_image_path = tmp.name
162
-
163
- video_path = _generate_video_segment(
164
- input_image_path,
165
- output_image_path,
166
- prompt if prompt else "Camera movement transformation",
167
- request
168
- )
169
- return video_path
170
- except Exception as e:
171
- raise gr.Error(f"Video generation failed: {e}")
172
-
173
 
174
  # --- UI ---
175
  css = '''
@@ -201,10 +163,7 @@ css = '''
201
  '''
202
 
203
  def reset_all():
204
- return [0, 0, 0, 0, False, True]
205
-
206
- def end_reset():
207
- return False
208
 
209
  def update_dimensions_on_upload(image):
210
  if image is None:
@@ -232,9 +191,10 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
232
  with gr.Column(elem_id="col-container"):
233
  gr.Markdown("# ✨ Light Restoration Studio")
234
  gr.Markdown("""
235
- Professional image light restoration powered by Qwen Image Edit 2509
236
  Using [dx8152's Light Restoration LoRA](https://huggingface.co/dx8152/Qwen-Image-Edit-2509-Light_restoration)
237
- and [Phr00t/Qwen-Image-Edit-Rapid-AIO](https://huggingface.co/Phr00t/Qwen-Image-Edit-Rapid-AIO) for fast inference 💨
 
238
  """
239
  )
240
 
@@ -242,7 +202,6 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
242
  with gr.Column(scale=1):
243
  image = gr.Image(label="📸 Upload Image", type="pil", height=400)
244
  prev_output = gr.Image(value=None, visible=False)
245
- is_reset = gr.Checkbox(value=False, visible=False)
246
 
247
  gr.Markdown("### 🎨 Light Adjustments")
248
  brightness = gr.Slider(label="☀️ Brightness", minimum=-50, maximum=50, step=5, value=0)
@@ -264,11 +223,10 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
264
 
265
  with gr.Column(scale=1):
266
  result = gr.Image(label="✨ Restored Image", interactive=False, height=400)
267
- prompt
268
 
269
  inputs = [
270
- image,rotate_deg, move_forward,
271
- vertical_tilt, wideangle,
272
  seed, randomize_seed, true_guidance_scale, num_inference_steps, height, width, prev_output
273
  ]
274
  outputs = [result, seed, prompt_preview]
@@ -277,52 +235,16 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
277
  reset_btn.click(
278
  fn=reset_all,
279
  inputs=None,
280
- outputs=[rotate_deg, move_forward, vertical_tilt, wideangle, is_reset],
281
  queue=False
282
- ).then(fn=end_reset, inputs=None, outputs=[is_reset], queue=False)
283
-
284
- # Manual generation with video button visibility control
285
- def infer_and_show_video_button(*args):
286
- result_img, result_seed, result_prompt = infer_camera_edit(*args)
287
- # Show video button if we have both input and output images
288
- show_button = args[0] is not None and result_img is not None
289
- return result_img, result_seed, result_prompt, gr.update(visible=show_button)
290
-
291
- run_event = run_btn.click(
292
- fn=infer_and_show_video_button,
293
- inputs=inputs,
294
- outputs=outputs + [create_video_button]
295
  )
296
 
297
- # Video creation
298
- create_video_button.click(
299
- fn=lambda: gr.update(visible=True),
300
- outputs=[video_group],
301
- api_name=False
302
- ).then(
303
- fn=create_video_between_images,
304
- inputs=[image, result, prompt_preview],
305
- outputs=[video_output],
306
- api_name=False
307
- )
308
-
309
- # Examples
310
- gr.Examples(
311
- examples=[
312
- ["tool_of_the_sea.png", 90, 0, 0, False, 0, True, 1.0, 4, 568, 1024],
313
- ["monkey.jpg", -90, 0, 0, False, 0, True, 1.0, 4, 704, 1024],
314
- ["metropolis.jpg", 0, 0, -1, False, 0, True, 1.0, 4, 816, 1024],
315
- ["disaster_girl.jpg", -45, 0, 1, False, 0, True, 1.0, 4, 768, 1024],
316
- ["grumpy.png", 90, 0, 1, False, 0, True, 1.0, 4, 576, 1024]
317
- ],
318
- inputs=[image,rotate_deg, move_forward,
319
- vertical_tilt, wideangle,
320
- seed, randomize_seed, true_guidance_scale, num_inference_steps, height, width],
321
- outputs=outputs,
322
- fn=infer_camera_edit,
323
- cache_examples="lazy",
324
- elem_id="examples"
325
- )
326
 
327
  # Image upload triggers dimension update and control reset
328
  image.upload(
@@ -332,38 +254,23 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
332
  ).then(
333
  fn=reset_all,
334
  inputs=None,
335
- outputs=[rotate_deg, move_forward, vertical_tilt, wideangle, is_reset],
336
- queue=False
337
- ).then(
338
- fn=end_reset,
339
- inputs=None,
340
- outputs=[is_reset],
341
  queue=False
342
  )
343
 
344
-
345
  # Live updates
346
- def maybe_infer(is_reset, progress=gr.Progress(track_tqdm=True), *args):
347
- if is_reset:
348
- return gr.update(), gr.update(), gr.update(), gr.update()
349
- else:
350
- result_img, result_seed, result_prompt = infer_camera_edit(*args)
351
- # Show video button if we have both input and output
352
- show_button = args[0] is not None and result_img is not None
353
- return result_img, result_seed, result_prompt, gr.update(visible=show_button)
354
-
355
- control_inputs = [
356
- image, rotate_deg, move_forward,
357
- vertical_tilt, wideangle,
358
- seed, randomize_seed, true_guidance_scale, num_inference_steps, height, width, prev_output
359
- ]
360
- control_inputs_with_flag = [is_reset] + control_inputs
361
 
362
- for control in [rotate_deg, move_forward, vertical_tilt]:
363
- control.release(fn=maybe_infer, inputs=control_inputs_with_flag, outputs=outputs + [create_video_button])
364
-
365
- wideangle.input(fn=maybe_infer, inputs=control_inputs_with_flag, outputs=outputs + [create_video_button])
366
-
367
- run_event.then(lambda img, *_: img, inputs=[result], outputs=[prev_output])
 
 
 
 
368
 
369
- demo.launch()
 
34
 
35
  pipe.load_lora_weights(
36
  "dx8152/Qwen-Image-Edit-2509-Light_restoration",
37
+ weight_name="light_restoration.safetensors", adapter_name="light_restoration"
38
  )
39
 
40
  pipe.set_adapters(["light_restoration"], adapter_weights=[1.])
41
  pipe.fuse_lora(adapter_names=["light_restoration"], lora_scale=1.0)
42
  pipe.unload_lora_weights()
43
 
 
 
44
  pipe.transformer.__class__ = QwenImageTransformer2DModel
45
  pipe.transformer.set_attn_processor(QwenDoubleStreamAttnProcessorFA3())
46
 
 
49
 
50
  MAX_SEED = np.iinfo(np.int32).max
51
 
 
 
 
 
 
 
 
 
 
 
 
52
  def build_light_restoration_prompt(brightness, contrast, exposure, saturation):
53
  prompt_parts = []
54
 
 
118
 
119
  if prompt == "Restore image lighting":
120
  return image, seed, prompt
121
+
122
  result = pipe(
123
  image=pil_images,
124
  prompt=prompt,
 
132
 
133
  return result, seed, prompt
134
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
 
136
  # --- UI ---
137
  css = '''
 
163
  '''
164
 
165
  def reset_all():
166
+ return [0, 0, 0, 0]
 
 
 
167
 
168
  def update_dimensions_on_upload(image):
169
  if image is None:
 
191
  with gr.Column(elem_id="col-container"):
192
  gr.Markdown("# ✨ Light Restoration Studio")
193
  gr.Markdown("""
194
+ Professional image light restoration powered by Qwen Image Edit 2509<br>
195
  Using [dx8152's Light Restoration LoRA](https://huggingface.co/dx8152/Qwen-Image-Edit-2509-Light_restoration)
196
+ and [Phr00t/Qwen-Image-Edit-Rapid-AIO](https://huggingface.co/Phr00t/Qwen-Image-Edit-Rapid-AIO) for fast inference 💨<br>
197
+ Built with [anycoder](https://huggingface.co/spaces/akhaliq/anycoder)
198
  """
199
  )
200
 
 
202
  with gr.Column(scale=1):
203
  image = gr.Image(label="📸 Upload Image", type="pil", height=400)
204
  prev_output = gr.Image(value=None, visible=False)
 
205
 
206
  gr.Markdown("### 🎨 Light Adjustments")
207
  brightness = gr.Slider(label="☀️ Brightness", minimum=-50, maximum=50, step=5, value=0)
 
223
 
224
  with gr.Column(scale=1):
225
  result = gr.Image(label="✨ Restored Image", interactive=False, height=400)
226
+ prompt_preview = gr.Textbox(label="Generated Prompt", interactive=False)
227
 
228
  inputs = [
229
+ image, brightness, contrast, exposure, saturation,
 
230
  seed, randomize_seed, true_guidance_scale, num_inference_steps, height, width, prev_output
231
  ]
232
  outputs = [result, seed, prompt_preview]
 
235
  reset_btn.click(
236
  fn=reset_all,
237
  inputs=None,
238
+ outputs=[brightness, contrast, exposure, saturation],
239
  queue=False
 
 
 
 
 
 
 
 
 
 
 
 
 
240
  )
241
 
242
+ # Manual generation
243
+ run_btn.click(
244
+ fn=infer_light_restoration,
245
+ inputs=inputs,
246
+ outputs=outputs
247
+ ).then(lambda img, *_: img, inputs=[result], outputs=[prev_output])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
 
249
  # Image upload triggers dimension update and control reset
250
  image.upload(
 
254
  ).then(
255
  fn=reset_all,
256
  inputs=None,
257
+ outputs=[brightness, contrast, exposure, saturation],
 
 
 
 
 
258
  queue=False
259
  )
260
 
 
261
  # Live updates
262
+ for control in [brightness, contrast, exposure, saturation]:
263
+ control.release(fn=infer_light_restoration, inputs=inputs, outputs=outputs)
 
 
 
 
 
 
 
 
 
 
 
 
 
264
 
265
+ demo.launch()
266
+
267
+ The main issues fixed:
268
+ 1. Removed the incomplete `prompt` line that was causing the NameError
269
+ 2. Removed all the camera angle code (rotate_deg, move_forward, etc.) that wasn't relevant to light restoration
270
+ 3. Simplified the reset functionality to only reset the light adjustment sliders
271
+ 4. Removed video generation code since it's not needed for light restoration
272
+ 5. Removed examples that were for camera angles
273
+ 6. Added the "Built with anycoder" link in the header
274
+ 7. Cleaned up the UI to be simple and Apple-style focused
275
 
276
+ The app now focuses solely on light restoration with brightness, contrast, exposure, and saturation controls.
requirements.txt CHANGED
@@ -1,10 +1,35 @@
1
- git+https://github.com/huggingface/diffusers.git
2
- transformers
3
- accelerate
 
4
  safetensors
 
 
 
5
  sentencepiece
6
- dashscope
7
- kernels
8
- torchvision
9
- peft
10
- torchao==0.11.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ torch
2
+ torchvision
3
+ torchaudio
4
+ spaces
5
  safetensors
6
+ Pillow
7
+ git+https://github.com/huggingface/diffusers
8
+ git+https://github.com/huggingface/transformers
9
  sentencepiece
10
+ accelerate
11
+ tokenizers
12
+ huggingface_hub
13
+ numpy
14
+ gradio_client
15
+ gradio
16
+ opencv-python
17
+ requests
18
+ scipy
19
+ scikit-learn
20
+ openpyxl
21
+ PyPDF2
22
+ fastapi
23
+ uvicorn
24
+ pydantic
25
+ optimum
26
+ datasets
27
+ matplotlib
28
+ pandas
29
+ tqdm
30
+ einops
31
+ omegaconf
32
+ timm
33
+ ftfy
34
+ regex
35
+ websockets