Madiy commited on
Commit
729da97
·
verified ·
1 Parent(s): 7b748f3

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -34
app.py CHANGED
@@ -36,7 +36,7 @@ from transformers import T5EncoderModel, CLIPModel, CLIPProcessor
36
 
37
  from basicsr.archs.rrdbnet_arch import RRDBNet
38
  from realesrgan import RealESRGANer
39
- from codeformer.app import inference_app as codeformer_infer
40
 
41
  # Optional quality metrics imports
42
  try:
@@ -89,13 +89,14 @@ print("FLUX.1-Fill loaded.")
89
 
90
 
91
  # ================================================================
92
- # 3. LOAD CODEFORMER & REAL-ESRGAN (Photo & Face Restoration)
93
  # ================================================================
94
- print("Setting up CodeFormer & Real-ESRGAN...")
95
  weights_dir = "weights"
96
  os.makedirs(weights_dir, exist_ok=True)
97
- esrgan_path = f"{weights_dir}/RealESRGAN_x4plus.pth"
98
 
 
 
99
  if not os.path.exists(esrgan_path):
100
  url = "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth"
101
  urllib.request.urlretrieve(url, esrgan_path)
@@ -111,7 +112,22 @@ enhancer = RealESRGANer(
111
  device=torch.device("cuda" if torch.cuda.is_available() else "cpu"),
112
  )
113
 
114
- print("CodeFormer & Real-ESRGAN ready.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
 
116
 
117
  # ================================================================
@@ -184,11 +200,10 @@ def _colorfulness(image):
184
 
185
 
186
  # ================================================================
187
- # 7. ENHANCEMENT FUNCTION (Deblur & Old Photo Restoration)
188
  # ================================================================
189
- import tempfile
190
  @spaces.GPU(duration=45)
191
- def enhance_image(image, scale_factor, fidelity_weight=0.5, compute_metrics=False):
192
  if image is None:
193
  raise gr.Error("Please upload an image first.")
194
 
@@ -196,47 +211,44 @@ def enhance_image(image, scale_factor, fidelity_weight=0.5, compute_metrics=Fals
196
  gc.collect()
197
  torch.cuda.empty_cache()
198
 
199
- # 2. Cap image size to avoid out-of-memory errors
200
  if max(image.size) > 1200:
201
  image = cap_image(image, 1200)
202
 
203
- upscale = 4 if scale_factor == "4x" else 2
204
 
205
- # 3. Save to a temporary file path to prevent OpenCV string conversion errors
206
- with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp_file:
207
- tmp_path = tmp_file.name
208
- image.save(tmp_path)
209
 
210
  try:
211
- # Pass the valid file path to codeformer_infer
212
- restored_bgr = codeformer_infer(
213
- image=tmp_path,
214
- background_enhance=True,
215
- face_upsample=True,
216
- upscale=upscale,
217
- codeformer_fidelity=float(fidelity_weight)
 
 
 
218
  )
219
 
220
  if restored_bgr is not None:
221
  output_rgb = cv2.cvtColor(restored_bgr, cv2.COLOR_BGR2RGB)
222
  output_image = Image.fromarray(output_rgb)
223
  else:
224
- raise ValueError("CodeFormer returned None")
225
 
226
  except Exception as e:
227
- # Fallback to direct Real-ESRGAN upscaling if face processing fails
228
  try:
229
- rgb_np = np.array(image.convert("RGB"), dtype=np.uint8)
230
- input_bgr = cv2.cvtColor(rgb_np, cv2.COLOR_RGB2BGR)
231
- output_bgr, _ = enhancer.enhance(input_bgr, outscale=upscale)
232
  output_rgb = cv2.cvtColor(output_bgr, cv2.COLOR_BGR2RGB)
233
  output_image = Image.fromarray(output_rgb)
234
  except Exception as fallback_err:
235
  raise gr.Error(f"Enhancement error: {fallback_err}")
236
  finally:
237
- # Clean up temporary file & clear CUDA memory
238
- if os.path.exists(tmp_path):
239
- os.remove(tmp_path)
240
  gc.collect()
241
  torch.cuda.empty_cache()
242
 
@@ -467,7 +479,7 @@ with gr.Blocks(
467
  ) as demo:
468
 
469
  gr.Markdown("# CanvasAI\n*AI-powered image enhancement, colorization, and outpainting*")
470
- gr.Markdown("**Enhance** with CodeFormer & Real-ESRGAN | **Colorize** B&W photos | **Outpaint** with FLUX.1-Fill")
471
  gr.Markdown("---")
472
 
473
  with gr.Tabs() as tabs:
@@ -539,14 +551,14 @@ with gr.Blocks(
539
 
540
  # Enhance Tab UI
541
  with gr.Tab("✨ Enhance", id="tab_enhance"):
542
- gr.Markdown("## Restore old photos, deblur faces, and upscale up to 4x (CodeFormer + Real-ESRGAN).")
543
  with gr.Row(equal_height=True):
544
  with gr.Column(scale=1):
545
  enh_input = gr.Image(label="Upload Image", type="pil", height=350)
546
  enh_scale = gr.Radio(choices=["2x", "4x"], value="4x", label="Upscale Factor")
547
- enh_fidelity = gr.Slider(
548
  minimum=0.0, maximum=1.0, value=0.5, step=0.1,
549
- label="Restoration Fidelity (0 = Max Deblur/Restoration, 1 = Max Original Identity)"
550
  )
551
  enh_metrics = gr.Checkbox(label="📊 Compute quality metrics", value=False)
552
  enh_btn = gr.Button("Enhance & Deblur", variant="primary", size="lg")
@@ -556,7 +568,7 @@ with gr.Blocks(
556
 
557
  enh_btn.click(
558
  fn=enhance_image,
559
- inputs=[enh_input, enh_scale, enh_fidelity, enh_metrics],
560
  outputs=[enh_output, enh_info]
561
  )
562
 
 
36
 
37
  from basicsr.archs.rrdbnet_arch import RRDBNet
38
  from realesrgan import RealESRGANer
39
+ from gfpgan import GFPGANer
40
 
41
  # Optional quality metrics imports
42
  try:
 
89
 
90
 
91
  # ================================================================
92
+ # 3. LOAD GFPGAN & REAL-ESRGAN (Photo & Face Restoration)
93
  # ================================================================
94
+ print("Setting up GFPGAN & Real-ESRGAN...")
95
  weights_dir = "weights"
96
  os.makedirs(weights_dir, exist_ok=True)
 
97
 
98
+ # 1. Real-ESRGAN Weights Setup
99
+ esrgan_path = f"{weights_dir}/RealESRGAN_x4plus.pth"
100
  if not os.path.exists(esrgan_path):
101
  url = "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth"
102
  urllib.request.urlretrieve(url, esrgan_path)
 
112
  device=torch.device("cuda" if torch.cuda.is_available() else "cpu"),
113
  )
114
 
115
+ # 2. GFPGAN Weights Setup
116
+ gfpgan_path = f"{weights_dir}/GFPGANv1.3.pth"
117
+ if not os.path.exists(gfpgan_path):
118
+ url = "https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth"
119
+ urllib.request.urlretrieve(url, gfpgan_path)
120
+
121
+ gfpgan_restorer = GFPGANer(
122
+ model_path=gfpgan_path,
123
+ upscale=4,
124
+ arch="clean",
125
+ channel_multiplier=2,
126
+ bg_upsampler=enhancer,
127
+ device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
128
+ )
129
+
130
+ print("GFPGAN & Real-ESRGAN ready.")
131
 
132
 
133
  # ================================================================
 
200
 
201
 
202
  # ================================================================
203
+ # 7. ENHANCEMENT FUNCTION (GFPGAN + Real-ESRGAN)
204
  # ================================================================
 
205
  @spaces.GPU(duration=45)
206
+ def enhance_image(image, scale_factor, weight=0.5, compute_metrics=False):
207
  if image is None:
208
  raise gr.Error("Please upload an image first.")
209
 
 
211
  gc.collect()
212
  torch.cuda.empty_cache()
213
 
214
+ # 2. Cap image size
215
  if max(image.size) > 1200:
216
  image = cap_image(image, 1200)
217
 
218
+ target_scale = 4 if scale_factor == "4x" else 2
219
 
220
+ # 3. Format numpy BGR array for OpenCV/GFPGAN
221
+ rgb_np = np.array(image.convert("RGB"), dtype=np.uint8)
222
+ input_bgr = cv2.cvtColor(rgb_np, cv2.COLOR_RGB2BGR)
 
223
 
224
  try:
225
+ # Update target scale for GFPGAN restorer
226
+ gfpgan_restorer.upscale = target_scale
227
+
228
+ # Run GFPGAN enhancement (Restores face + upscales background via Real-ESRGAN)
229
+ cropped_faces, restored_faces, restored_bgr = gfpgan_restorer.enhance(
230
+ input_bgr,
231
+ has_aligned=False,
232
+ only_center_face=False,
233
+ paste_back=True,
234
+ weight=float(weight)
235
  )
236
 
237
  if restored_bgr is not None:
238
  output_rgb = cv2.cvtColor(restored_bgr, cv2.COLOR_BGR2RGB)
239
  output_image = Image.fromarray(output_rgb)
240
  else:
241
+ raise ValueError("GFPGAN returned empty array")
242
 
243
  except Exception as e:
244
+ # Fallback directly to Real-ESRGAN if face parsing fails
245
  try:
246
+ output_bgr, _ = enhancer.enhance(input_bgr, outscale=target_scale)
 
 
247
  output_rgb = cv2.cvtColor(output_bgr, cv2.COLOR_BGR2RGB)
248
  output_image = Image.fromarray(output_rgb)
249
  except Exception as fallback_err:
250
  raise gr.Error(f"Enhancement error: {fallback_err}")
251
  finally:
 
 
 
252
  gc.collect()
253
  torch.cuda.empty_cache()
254
 
 
479
  ) as demo:
480
 
481
  gr.Markdown("# CanvasAI\n*AI-powered image enhancement, colorization, and outpainting*")
482
+ gr.Markdown("**Enhance** with GFPGAN & Real-ESRGAN | **Colorize** B&W photos | **Outpaint** with FLUX.1-Fill")
483
  gr.Markdown("---")
484
 
485
  with gr.Tabs() as tabs:
 
551
 
552
  # Enhance Tab UI
553
  with gr.Tab("✨ Enhance", id="tab_enhance"):
554
+ gr.Markdown("## Restore old photos, deblur faces, and upscale up to 4x (GFPGAN + Real-ESRGAN).")
555
  with gr.Row(equal_height=True):
556
  with gr.Column(scale=1):
557
  enh_input = gr.Image(label="Upload Image", type="pil", height=350)
558
  enh_scale = gr.Radio(choices=["2x", "4x"], value="4x", label="Upscale Factor")
559
+ enh_weight = gr.Slider(
560
  minimum=0.0, maximum=1.0, value=0.5, step=0.1,
561
+ label="Face Restoration Weight (Higher = stronger facial reconstruction)"
562
  )
563
  enh_metrics = gr.Checkbox(label="📊 Compute quality metrics", value=False)
564
  enh_btn = gr.Button("Enhance & Deblur", variant="primary", size="lg")
 
568
 
569
  enh_btn.click(
570
  fn=enhance_image,
571
+ inputs=[enh_input, enh_scale, enh_weight, enh_metrics],
572
  outputs=[enh_output, enh_info]
573
  )
574