FluttyProger commited on
Commit
c4c6c05
1 Parent(s): 61609fa

Upload ultimate-upscale.py

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