throwaway74 commited on
Commit
fbffdb7
·
verified ·
1 Parent(s): 6bbc64b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +123 -65
app.py CHANGED
@@ -1,9 +1,7 @@
1
  import os
2
  import uuid
3
- import math
4
  import gradio as gr
5
  import spaces
6
- import numpy as np
7
  from PIL import Image
8
  from image_gen_aux import UpscaleWithModel
9
 
@@ -13,17 +11,16 @@ from image_gen_aux import UpscaleWithModel
13
 
14
  BASE_TMP_DIR = "/tmp/image_enhancer"
15
  ENHANCED_DIR = os.path.join(BASE_TMP_DIR, "enhanced")
16
-
17
  os.makedirs(ENHANCED_DIR, exist_ok=True)
18
 
19
  # ---------------------------------
20
  # Model configuration
21
  # ---------------------------------
 
22
 
23
- MODEL_MAP = {
24
- "Anime Enhancer": "OzzyGT/4xRemacri",
25
- "Photo Enhancer": "OzzyGT/4xNomosWebPhoto_RealPLKSR",
26
- }
27
 
28
  MODEL_CACHE = {}
29
 
@@ -37,18 +34,30 @@ RATIO_MAP = {
37
  "3:2": (3, 2),
38
  }
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  # ---------------------------------
41
  # Helpers
42
  # ---------------------------------
43
 
44
- def get_upscaler(enhancer_type: str):
45
  global MODEL_CACHE
46
-
47
- if enhancer_type not in MODEL_CACHE:
48
- model_id = MODEL_MAP[enhancer_type]
49
- MODEL_CACHE[enhancer_type] = UpscaleWithModel.from_pretrained(model_id).to("cuda")
50
-
51
- return MODEL_CACHE[enhancer_type]
52
 
53
 
54
  def get_tile_dimensions(ratio_name: str, tile_preset: str):
@@ -77,8 +86,7 @@ def update_tile_display(ratio_name: str, tile_preset: str):
77
 
78
 
79
  def format_megapixels(width: int, height: int) -> str:
80
- mp = (width * height) / 1_000_000
81
- return f"{mp:.2f} MP"
82
 
83
 
84
  def format_file_size(num_bytes: int) -> str:
@@ -98,25 +106,52 @@ def build_stats_markdown(
98
  enhanced_height: int,
99
  file_size_bytes: int,
100
  export_format: str,
101
- scale_mode: str,
 
 
102
  ):
 
 
103
  return (
104
  f"**Original Dimensions:** {original_width} × {original_height}px \n"
105
  f"**Original Megapixels:** {format_megapixels(original_width, original_height)} \n\n"
106
  f"**Enhanced Dimensions:** {enhanced_width} × {enhanced_height}px \n"
107
  f"**Enhanced Megapixels:** {format_megapixels(enhanced_width, enhanced_height)} \n\n"
108
- f"**Scale Mode:** {scale_mode} \n"
109
  f"**Export Format:** {export_format} \n"
 
110
  f"**Saved File Size:** {format_file_size(file_size_bytes)}"
111
  )
112
 
113
 
114
- def upscale_once_with_model(
115
- img: Image.Image,
116
- upscaler,
117
- tile_width: int,
118
- tile_height: int,
119
- ) -> Image.Image:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  out = upscaler(
121
  img,
122
  tiling=True,
@@ -130,31 +165,35 @@ def upscale_once_with_model(
130
  return out.convert("RGB")
131
 
132
 
133
- def run_scale_pipeline(
134
  img: Image.Image,
135
- upscaler,
 
136
  tile_width: int,
137
  tile_height: int,
138
- scale_mode: str,
139
- ) -> Image.Image:
140
- # 4x = one model pass
141
- if scale_mode == "4x":
142
- return upscale_once_with_model(img, upscaler, tile_width, tile_height)
 
 
 
 
143
 
144
- # 8x Experimental = one real 4x pass, then high-quality resize to 8x total
145
- if scale_mode == "8x Experimental":
146
- first = upscale_once_with_model(img, upscaler, tile_width, tile_height)
147
- target_w = img.width * 8
148
- target_h = img.height * 8
149
- return first.resize((target_w, target_h), Image.LANCZOS).convert("RGB")
150
 
151
- # 16x Experimental = two real 4x passes = 16x total
152
- if scale_mode == "16x Experimental":
153
- first = upscale_once_with_model(img, upscaler, tile_width, tile_height)
154
- second = upscale_once_with_model(first, upscaler, tile_width, tile_height)
155
- return second.convert("RGB")
156
 
157
- return upscale_once_with_model(img, upscaler, tile_width, tile_height)
158
 
159
 
160
  def save_output_image(output_img: Image.Image, export_format: str):
@@ -171,40 +210,45 @@ def save_output_image(output_img: Image.Image, export_format: str):
171
  return path
172
 
173
 
 
 
 
 
174
  # ---------------------------------
175
  # GPU function
176
  # ---------------------------------
177
 
178
  @spaces.GPU
179
  def enhance_image(
 
180
  enhancer_type,
 
181
  ratio_name,
182
  tile_preset,
183
- scale_mode,
184
  export_format,
185
  input_image,
186
  ):
187
  if input_image is None:
188
- return (
189
- None,
190
- None,
191
- "No stats available yet."
192
- )
193
 
194
  original_img = Image.fromarray(input_image).convert("RGB")
195
  original_width, original_height = original_img.size
196
 
197
  tile_width, tile_height = get_tile_dimensions(ratio_name, tile_preset)
198
- upscaler = get_upscaler(enhancer_type)
199
 
200
- enhanced_img = run_scale_pipeline(
201
  img=original_img,
202
- upscaler=upscaler,
 
203
  tile_width=tile_width,
204
  tile_height=tile_height,
205
- scale_mode=scale_mode,
206
  )
207
 
 
 
 
 
 
208
  enhanced_width, enhanced_height = enhanced_img.size
209
 
210
  output_path = save_output_image(enhanced_img, export_format)
@@ -217,7 +261,9 @@ def enhance_image(
217
  enhanced_height=enhanced_height,
218
  file_size_bytes=file_size_bytes,
219
  export_format=export_format,
220
- scale_mode=scale_mode,
 
 
221
  )
222
 
223
  return enhanced_img, output_path, stats_markdown
@@ -230,7 +276,18 @@ def enhance_image(
230
  with gr.Blocks() as demo:
231
  gr.Markdown("# Image Enhancer")
232
 
233
- # 1. Enhancer Type
 
 
 
 
 
 
 
 
 
 
 
234
  with gr.Group():
235
  enhancer_type = gr.Radio(
236
  choices=["Anime Enhancer", "Photo Enhancer"],
@@ -238,7 +295,13 @@ with gr.Blocks() as demo:
238
  label="Enhancer Type"
239
  )
240
 
241
- # 2. Combined Tile Settings box
 
 
 
 
 
 
242
  with gr.Group():
243
  gr.Markdown("### Tile Settings")
244
 
@@ -258,16 +321,10 @@ with gr.Blocks() as demo:
258
  value=update_tile_display("1:1", "768")
259
  )
260
 
261
- # Extra processing settings
262
  with gr.Group():
263
  gr.Markdown("### Output Settings")
264
 
265
- scale_mode = gr.Radio(
266
- choices=["4x", "8x Experimental", "16x Experimental"],
267
- value="4x",
268
- label="Scale Mode"
269
- )
270
-
271
  export_format = gr.Radio(
272
  choices=["PNG", "TIFF"],
273
  value="PNG",
@@ -300,7 +357,7 @@ with gr.Blocks() as demo:
300
  label="Download new enhanced image file"
301
  )
302
 
303
- # Stats box
304
  with gr.Group():
305
  gr.Markdown("### Image Stats")
306
  stats_box = gr.Markdown(
@@ -322,10 +379,11 @@ with gr.Blocks() as demo:
322
  run_button.click(
323
  fn=enhance_image,
324
  inputs=[
 
325
  enhancer_type,
 
326
  ratio_name,
327
  tile_preset,
328
- scale_mode,
329
  export_format,
330
  input_image,
331
  ],
 
1
  import os
2
  import uuid
 
3
  import gradio as gr
4
  import spaces
 
5
  from PIL import Image
6
  from image_gen_aux import UpscaleWithModel
7
 
 
11
 
12
  BASE_TMP_DIR = "/tmp/image_enhancer"
13
  ENHANCED_DIR = os.path.join(BASE_TMP_DIR, "enhanced")
 
14
  os.makedirs(ENHANCED_DIR, exist_ok=True)
15
 
16
  # ---------------------------------
17
  # Model configuration
18
  # ---------------------------------
19
+ # Swap only these repo IDs if you want to test different models later.
20
 
21
+ ANIME_HIFI_2X_MODEL = "Phips/2xHFA2kCompact"
22
+ FAST_ANIME_4X_MODEL = "OzzyGT/4xRemacri"
23
+ FAST_PHOTO_4X_MODEL = "OzzyGT/4xNomosWebPhoto_RealPLKSR"
 
24
 
25
  MODEL_CACHE = {}
26
 
 
34
  "3:2": (3, 2),
35
  }
36
 
37
+ MODE_CHOICES = [
38
+ "2x High Fidelity",
39
+ "4x High Fidelity",
40
+ "4x Fast / Medium Fidelity",
41
+ "8x Multi-Pass (Drift Likely)",
42
+ ]
43
+
44
+ REDUCTION_CHOICES = ["Off", "80%", "85%", "90%"]
45
+
46
+ REDUCTION_DISCLAIMER = (
47
+ "Hi-Fi Output offers Post-Processing Size Reduction to further improve results. "
48
+ "Mode is entirely Optional and is defaulted at Off. Please note, this does not work "
49
+ "with Fast modes. If toggled, it will not be applied."
50
+ )
51
+
52
  # ---------------------------------
53
  # Helpers
54
  # ---------------------------------
55
 
56
+ def get_model(model_id: str):
57
  global MODEL_CACHE
58
+ if model_id not in MODEL_CACHE:
59
+ MODEL_CACHE[model_id] = UpscaleWithModel.from_pretrained(model_id).to("cuda")
60
+ return MODEL_CACHE[model_id]
 
 
 
61
 
62
 
63
  def get_tile_dimensions(ratio_name: str, tile_preset: str):
 
86
 
87
 
88
  def format_megapixels(width: int, height: int) -> str:
89
+ return f"{(width * height) / 1_000_000:.2f} MP"
 
90
 
91
 
92
  def format_file_size(num_bytes: int) -> str:
 
106
  enhanced_height: int,
107
  file_size_bytes: int,
108
  export_format: str,
109
+ mode_name: str,
110
+ reduction_choice: str,
111
+ reduction_applied: bool,
112
  ):
113
+ reduction_status = reduction_choice if reduction_applied else "Ignored / Not Applied"
114
+
115
  return (
116
  f"**Original Dimensions:** {original_width} × {original_height}px \n"
117
  f"**Original Megapixels:** {format_megapixels(original_width, original_height)} \n\n"
118
  f"**Enhanced Dimensions:** {enhanced_width} × {enhanced_height}px \n"
119
  f"**Enhanced Megapixels:** {format_megapixels(enhanced_width, enhanced_height)} \n\n"
120
+ f"**Mode:** {mode_name} \n"
121
  f"**Export Format:** {export_format} \n"
122
+ f"**Hi-Fi Output Reduction:** {reduction_status} \n"
123
  f"**Saved File Size:** {format_file_size(file_size_bytes)}"
124
  )
125
 
126
 
127
+ def reduction_factor_from_choice(choice: str):
128
+ mapping = {
129
+ "80%": 0.80,
130
+ "85%": 0.85,
131
+ "90%": 0.90,
132
+ }
133
+ return mapping.get(choice, 1.0)
134
+
135
+
136
+ def apply_output_reduction(img: Image.Image, reduction_choice: str):
137
+ factor = reduction_factor_from_choice(reduction_choice)
138
+ if factor >= 1.0:
139
+ return img
140
+
141
+ new_width = max(2, int(round(img.width * factor)))
142
+ new_height = max(2, int(round(img.height * factor)))
143
+
144
+ new_width -= new_width % 2
145
+ new_height -= new_height % 2
146
+
147
+ new_width = max(2, new_width)
148
+ new_height = max(2, new_height)
149
+
150
+ return img.resize((new_width, new_height), Image.LANCZOS)
151
+
152
+
153
+ def upscale_once(img: Image.Image, model_id: str, tile_width: int, tile_height: int):
154
+ upscaler = get_model(model_id)
155
  out = upscaler(
156
  img,
157
  tiling=True,
 
165
  return out.convert("RGB")
166
 
167
 
168
+ def run_mode_pipeline(
169
  img: Image.Image,
170
+ enhancer_type: str,
171
+ mode_name: str,
172
  tile_width: int,
173
  tile_height: int,
174
+ ):
175
+ # Conservative Hi-Fi branch uses true 2x model.
176
+ if mode_name == "2x High Fidelity":
177
+ return upscale_once(img, ANIME_HIFI_2X_MODEL, tile_width, tile_height)
178
+
179
+ if mode_name == "4x High Fidelity":
180
+ first = upscale_once(img, ANIME_HIFI_2X_MODEL, tile_width, tile_height)
181
+ second = upscale_once(first, ANIME_HIFI_2X_MODEL, tile_width, tile_height)
182
+ return second
183
 
184
+ # Rough capability / direct 4x branch
185
+ if mode_name == "4x Fast / Medium Fidelity":
186
+ if enhancer_type == "Photo Enhancer":
187
+ return upscale_once(img, FAST_PHOTO_4X_MODEL, tile_width, tile_height)
188
+ return upscale_once(img, FAST_ANIME_4X_MODEL, tile_width, tile_height)
 
189
 
190
+ if mode_name == "8x Multi-Pass (Drift Likely)":
191
+ first = upscale_once(img, ANIME_HIFI_2X_MODEL, tile_width, tile_height)
192
+ second = upscale_once(first, ANIME_HIFI_2X_MODEL, tile_width, tile_height)
193
+ third = upscale_once(second, ANIME_HIFI_2X_MODEL, tile_width, tile_height)
194
+ return third
195
 
196
+ return upscale_once(img, ANIME_HIFI_2X_MODEL, tile_width, tile_height)
197
 
198
 
199
  def save_output_image(output_img: Image.Image, export_format: str):
 
210
  return path
211
 
212
 
213
+ def is_hifi_mode(mode_name: str):
214
+ return mode_name in {"2x High Fidelity", "4x High Fidelity"}
215
+
216
+
217
  # ---------------------------------
218
  # GPU function
219
  # ---------------------------------
220
 
221
  @spaces.GPU
222
  def enhance_image(
223
+ reduction_choice,
224
  enhancer_type,
225
+ mode_name,
226
  ratio_name,
227
  tile_preset,
 
228
  export_format,
229
  input_image,
230
  ):
231
  if input_image is None:
232
+ return None, None, "No stats available yet."
 
 
 
 
233
 
234
  original_img = Image.fromarray(input_image).convert("RGB")
235
  original_width, original_height = original_img.size
236
 
237
  tile_width, tile_height = get_tile_dimensions(ratio_name, tile_preset)
 
238
 
239
+ enhanced_img = run_mode_pipeline(
240
  img=original_img,
241
+ enhancer_type=enhancer_type,
242
+ mode_name=mode_name,
243
  tile_width=tile_width,
244
  tile_height=tile_height,
 
245
  )
246
 
247
+ reduction_applied = False
248
+ if is_hifi_mode(mode_name) and reduction_choice != "Off":
249
+ enhanced_img = apply_output_reduction(enhanced_img, reduction_choice)
250
+ reduction_applied = True
251
+
252
  enhanced_width, enhanced_height = enhanced_img.size
253
 
254
  output_path = save_output_image(enhanced_img, export_format)
 
261
  enhanced_height=enhanced_height,
262
  file_size_bytes=file_size_bytes,
263
  export_format=export_format,
264
+ mode_name=mode_name,
265
+ reduction_choice=reduction_choice,
266
+ reduction_applied=reduction_applied,
267
  )
268
 
269
  return enhanced_img, output_path, stats_markdown
 
276
  with gr.Blocks() as demo:
277
  gr.Markdown("# Image Enhancer")
278
 
279
+ # 0. Hi-Fi Output Reduction
280
+ with gr.Group():
281
+ gr.Markdown("### Hi-Fi Output Reduction")
282
+ gr.Markdown(REDUCTION_DISCLAIMER)
283
+
284
+ reduction_choice = gr.Radio(
285
+ choices=REDUCTION_CHOICES,
286
+ value="Off",
287
+ label="Reduction Amount"
288
+ )
289
+
290
+ # 1. Enhancer / Mode box
291
  with gr.Group():
292
  enhancer_type = gr.Radio(
293
  choices=["Anime Enhancer", "Photo Enhancer"],
 
295
  label="Enhancer Type"
296
  )
297
 
298
+ mode_name = gr.Radio(
299
+ choices=MODE_CHOICES,
300
+ value="2x High Fidelity",
301
+ label="Processing Mode"
302
+ )
303
+
304
+ # 2. Combined Tile Settings
305
  with gr.Group():
306
  gr.Markdown("### Tile Settings")
307
 
 
321
  value=update_tile_display("1:1", "768")
322
  )
323
 
324
+ # 2.5 Output Settings
325
  with gr.Group():
326
  gr.Markdown("### Output Settings")
327
 
 
 
 
 
 
 
328
  export_format = gr.Radio(
329
  choices=["PNG", "TIFF"],
330
  value="PNG",
 
357
  label="Download new enhanced image file"
358
  )
359
 
360
+ # Stats
361
  with gr.Group():
362
  gr.Markdown("### Image Stats")
363
  stats_box = gr.Markdown(
 
379
  run_button.click(
380
  fn=enhance_image,
381
  inputs=[
382
+ reduction_choice,
383
  enhancer_type,
384
+ mode_name,
385
  ratio_name,
386
  tile_preset,
 
387
  export_format,
388
  input_image,
389
  ],