aimutation05 commited on
Commit
597dbe0
1 Parent(s): f17d290

Upload ultimate-upscale.py

Browse files
Files changed (1) hide show
  1. ultimate-upscale.py +557 -0
ultimate-upscale.py ADDED
@@ -0,0 +1,557 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import gradio as gr
3
+ from PIL import Image, ImageDraw, ImageOps
4
+ from modules import processing, shared, images, devices, scripts
5
+ from modules.processing import StableDiffusionProcessing
6
+ from modules.processing import Processed
7
+ from modules.shared import opts, state
8
+ from enum import Enum
9
+
10
+ class USDUMode(Enum):
11
+ LINEAR = 0
12
+ CHESS = 1
13
+ NONE = 2
14
+
15
+ class USDUSFMode(Enum):
16
+ NONE = 0
17
+ BAND_PASS = 1
18
+ HALF_TILE = 2
19
+ HALF_TILE_PLUS_INTERSECTIONS = 3
20
+
21
+ class USDUpscaler():
22
+
23
+ def __init__(self, p, image, upscaler_index:int, save_redraw, save_seams_fix, tile_width, tile_height) -> None:
24
+ self.p:StableDiffusionProcessing = p
25
+ self.image:Image = image
26
+ self.scale_factor = math.ceil(max(p.width, p.height) / max(image.width, image.height))
27
+ self.upscaler = shared.sd_upscalers[upscaler_index]
28
+ self.redraw = USDURedraw()
29
+ self.redraw.save = save_redraw
30
+ self.redraw.tile_width = tile_width if tile_width > 0 else tile_height
31
+ self.redraw.tile_height = tile_height if tile_height > 0 else tile_width
32
+ self.seams_fix = USDUSeamsFix()
33
+ self.seams_fix.save = save_seams_fix
34
+ self.seams_fix.tile_width = tile_width if tile_width > 0 else tile_height
35
+ self.seams_fix.tile_height = tile_height if tile_height > 0 else tile_width
36
+ self.initial_info = None
37
+ self.rows = math.ceil(self.p.height / self.redraw.tile_height)
38
+ self.cols = math.ceil(self.p.width / self.redraw.tile_width)
39
+
40
+ def get_factor(self, num):
41
+ # Its just return, don't need elif
42
+ if num == 1:
43
+ return 2
44
+ if num % 4 == 0:
45
+ return 4
46
+ if num % 3 == 0:
47
+ return 3
48
+ if num % 2 == 0:
49
+ return 2
50
+ return 0
51
+
52
+ def get_factors(self):
53
+ scales = []
54
+ current_scale = 1
55
+ current_scale_factor = self.get_factor(self.scale_factor)
56
+ while current_scale_factor == 0:
57
+ self.scale_factor += 1
58
+ current_scale_factor = self.get_factor(self.scale_factor)
59
+ while current_scale < self.scale_factor:
60
+ current_scale_factor = self.get_factor(self.scale_factor // current_scale)
61
+ scales.append(current_scale_factor)
62
+ current_scale = current_scale * current_scale_factor
63
+ if current_scale_factor == 0:
64
+ break
65
+ self.scales = enumerate(scales)
66
+
67
+ def upscale(self):
68
+ # Log info
69
+ print(f"Canva size: {self.p.width}x{self.p.height}")
70
+ print(f"Image size: {self.image.width}x{self.image.height}")
71
+ print(f"Scale factor: {self.scale_factor}")
72
+ # Check upscaler is not empty
73
+ if self.upscaler.name == "None":
74
+ self.image = self.image.resize((self.p.width, self.p.height), resample=Image.LANCZOS)
75
+ return
76
+ # Get list with scale factors
77
+ self.get_factors()
78
+ # Upscaling image over all factors
79
+ for index, value in self.scales:
80
+ print(f"Upscaling iteration {index+1} with scale factor {value}")
81
+ self.image = self.upscaler.scaler.upscale(self.image, value, self.upscaler.data_path)
82
+ # Resize image to set values
83
+ self.image = self.image.resize((self.p.width, self.p.height), resample=Image.LANCZOS)
84
+
85
+ def setup_redraw(self, redraw_mode, padding, mask_blur):
86
+ self.redraw.mode = USDUMode(redraw_mode)
87
+ self.redraw.enabled = self.redraw.mode != USDUMode.NONE
88
+ self.redraw.padding = padding
89
+ self.p.mask_blur = mask_blur
90
+
91
+ def setup_seams_fix(self, padding, denoise, mask_blur, width, mode):
92
+ self.seams_fix.padding = padding
93
+ self.seams_fix.denoise = denoise
94
+ self.seams_fix.mask_blur = mask_blur
95
+ self.seams_fix.width = width
96
+ self.seams_fix.mode = USDUSFMode(mode)
97
+ self.seams_fix.enabled = self.seams_fix.mode != USDUSFMode.NONE
98
+
99
+ def save_image(self):
100
+ if type(self.p.prompt) != list:
101
+ images.save_image(self.image, self.p.outpath_samples, "", self.p.seed, self.p.prompt, opts.samples_format, info=self.initial_info, p=self.p)
102
+ else:
103
+ images.save_image(self.image, self.p.outpath_samples, "", self.p.seed, self.p.prompt[0], opts.samples_format, info=self.initial_info, p=self.p)
104
+
105
+ def calc_jobs_count(self):
106
+ redraw_job_count = (self.rows * self.cols) if self.redraw.enabled else 0
107
+ seams_job_count = 0
108
+ if self.seams_fix.mode == USDUSFMode.BAND_PASS:
109
+ seams_job_count = self.rows + self.cols - 2
110
+ elif self.seams_fix.mode == USDUSFMode.HALF_TILE:
111
+ seams_job_count = self.rows * (self.cols - 1) + (self.rows - 1) * self.cols
112
+ elif self.seams_fix.mode == USDUSFMode.HALF_TILE_PLUS_INTERSECTIONS:
113
+ seams_job_count = self.rows * (self.cols - 1) + (self.rows - 1) * self.cols + (self.rows - 1) * (self.cols - 1)
114
+
115
+ state.job_count = redraw_job_count + seams_job_count
116
+
117
+ def print_info(self):
118
+ print(f"Tile size: {self.redraw.tile_width}x{self.redraw.tile_height}")
119
+ print(f"Tiles amount: {self.rows * self.cols}")
120
+ print(f"Grid: {self.rows}x{self.cols}")
121
+ print(f"Redraw enabled: {self.redraw.enabled}")
122
+ print(f"Seams fix mode: {self.seams_fix.mode.name}")
123
+
124
+ def add_extra_info(self):
125
+ self.p.extra_generation_params["Ultimate SD upscale upscaler"] = self.upscaler.name
126
+ self.p.extra_generation_params["Ultimate SD upscale tile_width"] = self.redraw.tile_width
127
+ self.p.extra_generation_params["Ultimate SD upscale tile_height"] = self.redraw.tile_height
128
+ self.p.extra_generation_params["Ultimate SD upscale mask_blur"] = self.p.mask_blur
129
+ self.p.extra_generation_params["Ultimate SD upscale padding"] = self.redraw.padding
130
+
131
+ def process(self):
132
+ state.begin()
133
+ self.calc_jobs_count()
134
+ self.result_images = []
135
+ if self.redraw.enabled:
136
+ self.image = self.redraw.start(self.p, self.image, self.rows, self.cols)
137
+ self.initial_info = self.redraw.initial_info
138
+ self.result_images.append(self.image)
139
+ if self.redraw.save:
140
+ self.save_image()
141
+
142
+ if self.seams_fix.enabled:
143
+ self.image = self.seams_fix.start(self.p, self.image, self.rows, self.cols)
144
+ self.initial_info = self.seams_fix.initial_info
145
+ self.result_images.append(self.image)
146
+ if self.seams_fix.save:
147
+ self.save_image()
148
+ state.end()
149
+
150
+ class USDURedraw():
151
+
152
+ def init_draw(self, p, width, height):
153
+ p.inpaint_full_res = True
154
+ p.inpaint_full_res_padding = self.padding
155
+ p.width = math.ceil((self.tile_width+self.padding) / 64) * 64
156
+ p.height = math.ceil((self.tile_height+self.padding) / 64) * 64
157
+ mask = Image.new("L", (width, height), "black")
158
+ draw = ImageDraw.Draw(mask)
159
+ return mask, draw
160
+
161
+ def calc_rectangle(self, xi, yi):
162
+ x1 = xi * self.tile_width
163
+ y1 = yi * self.tile_height
164
+ x2 = xi * self.tile_width + self.tile_width
165
+ y2 = yi * self.tile_height + self.tile_height
166
+
167
+ return x1, y1, x2, y2
168
+
169
+ def linear_process(self, p, image, rows, cols):
170
+ mask, draw = self.init_draw(p, image.width, image.height)
171
+ for yi in range(rows):
172
+ for xi in range(cols):
173
+ if state.interrupted:
174
+ break
175
+ draw.rectangle(self.calc_rectangle(xi, yi), fill="white")
176
+ p.init_images = [image]
177
+ p.image_mask = mask
178
+ processed = processing.process_images(p)
179
+ draw.rectangle(self.calc_rectangle(xi, yi), fill="black")
180
+ if (len(processed.images) > 0):
181
+ image = processed.images[0]
182
+
183
+ p.width = image.width
184
+ p.height = image.height
185
+ self.initial_info = processed.infotext(p, 0)
186
+
187
+ return image
188
+
189
+ def chess_process(self, p, image, rows, cols):
190
+ mask, draw = self.init_draw(p, image.width, image.height)
191
+ tiles = []
192
+ # calc tiles colors
193
+ for yi in range(rows):
194
+ for xi in range(cols):
195
+ if state.interrupted:
196
+ break
197
+ if xi == 0:
198
+ tiles.append([])
199
+ color = xi % 2 == 0
200
+ if yi > 0 and yi % 2 != 0:
201
+ color = not color
202
+ tiles[yi].append(color)
203
+
204
+ for yi in range(len(tiles)):
205
+ for xi in range(len(tiles[yi])):
206
+ if state.interrupted:
207
+ break
208
+ if not tiles[yi][xi]:
209
+ tiles[yi][xi] = not tiles[yi][xi]
210
+ continue
211
+ tiles[yi][xi] = not tiles[yi][xi]
212
+ draw.rectangle(self.calc_rectangle(xi, yi), fill="white")
213
+ p.init_images = [image]
214
+ p.image_mask = mask
215
+ processed = processing.process_images(p)
216
+ draw.rectangle(self.calc_rectangle(xi, yi), fill="black")
217
+ if (len(processed.images) > 0):
218
+ image = processed.images[0]
219
+
220
+ for yi in range(len(tiles)):
221
+ for xi in range(len(tiles[yi])):
222
+ if state.interrupted:
223
+ break
224
+ if not tiles[yi][xi]:
225
+ continue
226
+ draw.rectangle(self.calc_rectangle(xi, yi), fill="white")
227
+ p.init_images = [image]
228
+ p.image_mask = mask
229
+ processed = processing.process_images(p)
230
+ draw.rectangle(self.calc_rectangle(xi, yi), fill="black")
231
+ if (len(processed.images) > 0):
232
+ image = processed.images[0]
233
+
234
+ p.width = image.width
235
+ p.height = image.height
236
+ self.initial_info = processed.infotext(p, 0)
237
+
238
+ return image
239
+
240
+ def start(self, p, image, rows, cols):
241
+ self.initial_info = None
242
+ if self.mode == USDUMode.LINEAR:
243
+ return self.linear_process(p, image, rows, cols)
244
+ if self.mode == USDUMode.CHESS:
245
+ return self.chess_process(p, image, rows, cols)
246
+
247
+ class USDUSeamsFix():
248
+
249
+ def init_draw(self, p):
250
+ self.initial_info = None
251
+ p.width = math.ceil((self.tile_width+self.padding) / 64) * 64
252
+ p.height = math.ceil((self.tile_height+self.padding) / 64) * 64
253
+
254
+ def half_tile_process(self, p, image, rows, cols):
255
+
256
+ self.init_draw(p)
257
+ processed = None
258
+
259
+ gradient = Image.linear_gradient("L")
260
+ row_gradient = Image.new("L", (self.tile_width, self.tile_height), "black")
261
+ row_gradient.paste(gradient.resize(
262
+ (self.tile_width, self.tile_height//2), resample=Image.BICUBIC), (0, 0))
263
+ row_gradient.paste(gradient.rotate(180).resize(
264
+ (self.tile_width, self.tile_height//2), resample=Image.BICUBIC),
265
+ (0, self.tile_height//2))
266
+ col_gradient = Image.new("L", (self.tile_width, self.tile_height), "black")
267
+ col_gradient.paste(gradient.rotate(90).resize(
268
+ (self.tile_width//2, self.tile_height), resample=Image.BICUBIC), (0, 0))
269
+ col_gradient.paste(gradient.rotate(270).resize(
270
+ (self.tile_width//2, self.tile_height), resample=Image.BICUBIC), (self.tile_width//2, 0))
271
+
272
+ p.denoising_strength = self.denoise
273
+ p.mask_blur = self.mask_blur
274
+
275
+ for yi in range(rows-1):
276
+ for xi in range(cols):
277
+ if state.interrupted:
278
+ break
279
+ p.width = self.tile_width
280
+ p.height = self.tile_height
281
+ p.inpaint_full_res = True
282
+ p.inpaint_full_res_padding = self.padding
283
+ mask = Image.new("L", (image.width, image.height), "black")
284
+ mask.paste(row_gradient, (xi*self.tile_width, yi*self.tile_height + self.tile_height//2))
285
+
286
+ p.init_images = [image]
287
+ p.image_mask = mask
288
+ processed = processing.process_images(p)
289
+ if (len(processed.images) > 0):
290
+ image = processed.images[0]
291
+
292
+ for yi in range(rows):
293
+ for xi in range(cols-1):
294
+ if state.interrupted:
295
+ break
296
+ p.width = self.tile_width
297
+ p.height = self.tile_height
298
+ p.inpaint_full_res = True
299
+ p.inpaint_full_res_padding = self.padding
300
+ mask = Image.new("L", (image.width, image.height), "black")
301
+ mask.paste(col_gradient, (xi*self.tile_width+self.tile_width//2, yi*self.tile_height))
302
+
303
+ p.init_images = [image]
304
+ p.image_mask = mask
305
+ processed = processing.process_images(p)
306
+ if (len(processed.images) > 0):
307
+ image = processed.images[0]
308
+
309
+ p.width = image.width
310
+ p.height = image.height
311
+ if processed is not None:
312
+ self.initial_info = processed.infotext(p, 0)
313
+
314
+ return image
315
+
316
+ def half_tile_process_corners(self, p, image, rows, cols):
317
+ fixed_image = self.half_tile_process(p, image, rows, cols)
318
+ processed = None
319
+ self.init_draw(p)
320
+ gradient = Image.radial_gradient("L").resize(
321
+ (self.tile_width, self.tile_height), resample=Image.BICUBIC)
322
+ gradient = ImageOps.invert(gradient)
323
+ p.denoising_strength = self.denoise
324
+ #p.mask_blur = 0
325
+ p.mask_blur = self.mask_blur
326
+
327
+ for yi in range(rows-1):
328
+ for xi in range(cols-1):
329
+ if state.interrupted:
330
+ break
331
+ p.width = self.tile_width
332
+ p.height = self.tile_height
333
+ p.inpaint_full_res = True
334
+ p.inpaint_full_res_padding = 0
335
+ mask = Image.new("L", (fixed_image.width, fixed_image.height), "black")
336
+ mask.paste(gradient, (xi*self.tile_width + self.tile_width//2,
337
+ yi*self.tile_height + self.tile_height//2))
338
+
339
+ p.init_images = [fixed_image]
340
+ p.image_mask = mask
341
+ processed = processing.process_images(p)
342
+ if (len(processed.images) > 0):
343
+ fixed_image = processed.images[0]
344
+
345
+ p.width = fixed_image.width
346
+ p.height = fixed_image.height
347
+ if processed is not None:
348
+ self.initial_info = processed.infotext(p, 0)
349
+
350
+ return fixed_image
351
+
352
+ def band_pass_process(self, p, image, cols, rows):
353
+
354
+ self.init_draw(p)
355
+ processed = None
356
+
357
+ p.denoising_strength = self.denoise
358
+ p.mask_blur = 0
359
+
360
+ gradient = Image.linear_gradient("L")
361
+ mirror_gradient = Image.new("L", (256, 256), "black")
362
+ mirror_gradient.paste(gradient.resize((256, 128), resample=Image.BICUBIC), (0, 0))
363
+ mirror_gradient.paste(gradient.rotate(180).resize((256, 128), resample=Image.BICUBIC), (0, 128))
364
+
365
+ row_gradient = mirror_gradient.resize((image.width, self.width), resample=Image.BICUBIC)
366
+ col_gradient = mirror_gradient.rotate(90).resize((self.width, image.height), resample=Image.BICUBIC)
367
+
368
+ for xi in range(1, rows):
369
+ if state.interrupted:
370
+ break
371
+ p.width = self.width + self.padding * 2
372
+ p.height = image.height
373
+ p.inpaint_full_res = True
374
+ p.inpaint_full_res_padding = self.padding
375
+ mask = Image.new("L", (image.width, image.height), "black")
376
+ mask.paste(col_gradient, (xi * self.tile_width - self.width // 2, 0))
377
+
378
+ p.init_images = [image]
379
+ p.image_mask = mask
380
+ processed = processing.process_images(p)
381
+ if (len(processed.images) > 0):
382
+ image = processed.images[0]
383
+ for yi in range(1, cols):
384
+ if state.interrupted:
385
+ break
386
+ p.width = image.width
387
+ p.height = self.width + self.padding * 2
388
+ p.inpaint_full_res = True
389
+ p.inpaint_full_res_padding = self.padding
390
+ mask = Image.new("L", (image.width, image.height), "black")
391
+ mask.paste(row_gradient, (0, yi * self.tile_height - self.width // 2))
392
+
393
+ p.init_images = [image]
394
+ p.image_mask = mask
395
+ processed = processing.process_images(p)
396
+ if (len(processed.images) > 0):
397
+ image = processed.images[0]
398
+
399
+ p.width = image.width
400
+ p.height = image.height
401
+ if processed is not None:
402
+ self.initial_info = processed.infotext(p, 0)
403
+
404
+ return image
405
+
406
+ def start(self, p, image, rows, cols):
407
+ if USDUSFMode(self.mode) == USDUSFMode.BAND_PASS:
408
+ return self.band_pass_process(p, image, rows, cols)
409
+ elif USDUSFMode(self.mode) == USDUSFMode.HALF_TILE:
410
+ return self.half_tile_process(p, image, rows, cols)
411
+ elif USDUSFMode(self.mode) == USDUSFMode.HALF_TILE_PLUS_INTERSECTIONS:
412
+ return self.half_tile_process_corners(p, image, rows, cols)
413
+ else:
414
+ return image
415
+
416
+ class Script(scripts.Script):
417
+ def title(self):
418
+ return "Ultimate SD upscale"
419
+
420
+ def show(self, is_img2img):
421
+ return is_img2img
422
+
423
+ def ui(self, is_img2img):
424
+
425
+ target_size_types = [
426
+ "From img2img2 settings",
427
+ "Custom size",
428
+ "Scale from image size"
429
+ ]
430
+
431
+ seams_fix_types = [
432
+ "None",
433
+ "Band pass",
434
+ "Half tile offset pass",
435
+ "Half tile offset pass + intersections"
436
+ ]
437
+
438
+ redrow_modes = [
439
+ "Linear",
440
+ "Chess",
441
+ "None"
442
+ ]
443
+
444
+ info = gr.HTML(
445
+ "<p style=\"margin-bottom:0.75em\">Will upscale the image depending on the selected target size type</p>")
446
+
447
+ with gr.Row():
448
+ target_size_type = gr.Dropdown(label="Target size type", choices=[k for k in target_size_types], type="index",
449
+ value=next(iter(target_size_types)))
450
+
451
+ custom_width = gr.Slider(label='Custom width', minimum=64, maximum=8192, step=64, value=2048, visible=False, interactive=True)
452
+ custom_height = gr.Slider(label='Custom height', minimum=64, maximum=8192, step=64, value=2048, visible=False, interactive=True)
453
+ custom_scale = gr.Slider(label='Scale', minimum=1, maximum=16, step=0.01, value=2, visible=False, interactive=True)
454
+
455
+ gr.HTML("<p style=\"margin-bottom:0.75em\">Redraw options:</p>")
456
+ with gr.Row():
457
+ upscaler_index = gr.Radio(label='Upscaler', choices=[x.name for x in shared.sd_upscalers],
458
+ value=shared.sd_upscalers[0].name, type="index")
459
+ with gr.Row():
460
+ redraw_mode = gr.Dropdown(label="Type", choices=[k for k in redrow_modes], type="index", value=next(iter(redrow_modes)))
461
+ tile_width = gr.Slider(minimum=0, maximum=2048, step=64, label='Tile width', value=512)
462
+ tile_height = gr.Slider(minimum=0, maximum=2048, step=64, label='Tile height', value=0)
463
+ mask_blur = gr.Slider(label='Mask blur', minimum=0, maximum=64, step=1, value=8)
464
+ padding = gr.Slider(label='Padding', minimum=0, maximum=128, step=1, value=32)
465
+ gr.HTML("<p style=\"margin-bottom:0.75em\">Seams fix:</p>")
466
+ with gr.Row():
467
+ seams_fix_type = gr.Dropdown(label="Type", choices=[k for k in seams_fix_types], type="index", value=next(iter(seams_fix_types)))
468
+ seams_fix_denoise = gr.Slider(label='Denoise', minimum=0, maximum=1, step=0.01, value=0.35, visible=False, interactive=True)
469
+ seams_fix_width = gr.Slider(label='Width', minimum=0, maximum=128, step=1, value=64, visible=False, interactive=True)
470
+ seams_fix_mask_blur = gr.Slider(label='Mask blur', minimum=0, maximum=64, step=1, value=4, visible=False, interactive=True)
471
+ seams_fix_padding = gr.Slider(label='Padding', minimum=0, maximum=128, step=1, value=16, visible=False, interactive=True)
472
+ gr.HTML("<p style=\"margin-bottom:0.75em\">Save options:</p>")
473
+ with gr.Row():
474
+ save_upscaled_image = gr.Checkbox(label="Upscaled", value=True)
475
+ save_seams_fix_image = gr.Checkbox(label="Seams fix", value=False)
476
+
477
+ def select_fix_type(fix_index):
478
+ all_visible = fix_index != 0
479
+ mask_blur_visible = fix_index == 2 or fix_index == 3
480
+ width_visible = fix_index == 1
481
+
482
+ return [gr.update(visible=all_visible),
483
+ gr.update(visible=width_visible),
484
+ gr.update(visible=mask_blur_visible),
485
+ gr.update(visible=all_visible)]
486
+
487
+ seams_fix_type.change(
488
+ fn=select_fix_type,
489
+ inputs=seams_fix_type,
490
+ outputs=[seams_fix_denoise, seams_fix_width, seams_fix_mask_blur, seams_fix_padding]
491
+ )
492
+
493
+ def select_scale_type(scale_index):
494
+ is_custom_size = scale_index == 1
495
+ is_custom_scale = scale_index == 2
496
+
497
+ return [gr.update(visible=is_custom_size),
498
+ gr.update(visible=is_custom_size),
499
+ gr.update(visible=is_custom_scale),
500
+ ]
501
+
502
+ target_size_type.change(
503
+ fn=select_scale_type,
504
+ inputs=target_size_type,
505
+ outputs=[custom_width, custom_height, custom_scale]
506
+ )
507
+
508
+ return [info, tile_width, tile_height, mask_blur, padding, seams_fix_width, seams_fix_denoise, seams_fix_padding,
509
+ upscaler_index, save_upscaled_image, redraw_mode, save_seams_fix_image, seams_fix_mask_blur,
510
+ seams_fix_type, target_size_type, custom_width, custom_height, custom_scale]
511
+
512
+ def run(self, p, _, tile_width, tile_height, mask_blur, padding, seams_fix_width, seams_fix_denoise, seams_fix_padding,
513
+ upscaler_index, save_upscaled_image, redraw_mode, save_seams_fix_image, seams_fix_mask_blur,
514
+ seams_fix_type, target_size_type, custom_width, custom_height, custom_scale):
515
+
516
+ # Init
517
+ processing.fix_seed(p)
518
+ devices.torch_gc()
519
+
520
+ p.do_not_save_grid = True
521
+ p.do_not_save_samples = True
522
+ p.inpaint_full_res = False
523
+
524
+ p.inpainting_fill = 1
525
+ p.n_iter = 1
526
+ p.batch_size = 1
527
+
528
+ seed = p.seed
529
+
530
+ # Init image
531
+ init_img = p.init_images[0]
532
+ if init_img == None:
533
+ return Processed(p, [], seed, "Empty image")
534
+ init_img = images.flatten(init_img, opts.img2img_background_color)
535
+
536
+ #override size
537
+ if target_size_type == 1:
538
+ p.width = custom_width
539
+ p.height = custom_height
540
+ if target_size_type == 2:
541
+ p.width = math.ceil((init_img.width * custom_scale) / 64) * 64
542
+ p.height = math.ceil((init_img.height * custom_scale) / 64) * 64
543
+
544
+ # Upscaling
545
+ upscaler = USDUpscaler(p, init_img, upscaler_index, save_upscaled_image, save_seams_fix_image, tile_width, tile_height)
546
+ upscaler.upscale()
547
+
548
+ # Drawing
549
+ upscaler.setup_redraw(redraw_mode, padding, mask_blur)
550
+ upscaler.setup_seams_fix(seams_fix_padding, seams_fix_denoise, seams_fix_mask_blur, seams_fix_width, seams_fix_type)
551
+ upscaler.print_info()
552
+ upscaler.add_extra_info()
553
+ upscaler.process()
554
+ result_images = upscaler.result_images
555
+
556
+ return Processed(p, result_images, seed, upscaler.initial_info if upscaler.initial_info is not None else "")
557
+