dikdimon commited on
Commit
968462d
·
verified ·
1 Parent(s): 899ba56

Delete custom-hires-fix-for-automatic1111

Browse files
custom-hires-fix-for-automatic1111/README.md DELETED
@@ -1,29 +0,0 @@
1
- # Custom Hires Fix (webui Extension)
2
- ## Webui Extension for customizing highres fix and improve details (currently separated from original highres fix)
3
-
4
-
5
- #### Update 16.10.23:
6
- - added ControlNet support: choose preprocessor/model in CN settings, but don't enable unit
7
- - added Lora support: put Lora in extension prompt to enable Lora only for upscaling, put Lora in negative prompt to disable active Lora
8
-
9
- #### Update 02.07.23:
10
- - code rewritten again
11
- - simplified settings
12
- - fixed batch generation and image saving
13
-
14
- #### Update 13.06.23:
15
- - added gaussian noise instead of random
16
-
17
- #### Update 29.05.23:
18
- - added ToMe optomization in second pass, latest Auto1111 update required, controlled via "Token merging ratio for high-res pass" in settings
19
- - added "Sharp" setting, should be used only with "Smoothness" if image is too blurry
20
-
21
- #### Update 12.05.23:
22
- - added smoothness for negative, completely fix ghosting/smears/dirt on flat colors with high denoising
23
-
24
- #### Update 02.04.23:
25
- ###### Don't forget to clear ui-config.json!
26
- - upscale separated from original high-res fix
27
- - now works with img2img
28
- - many fixes
29
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
custom-hires-fix-for-automatic1111/config.yaml DELETED
File without changes
custom-hires-fix-for-automatic1111/scripts/__pycache__/custom_hires_fix.cpython-310.pyc DELETED
Binary file (14.4 kB)
 
custom-hires-fix-for-automatic1111/scripts/custom_hires_fix.py DELETED
@@ -1,443 +0,0 @@
1
- import math
2
- from os.path import exists
3
-
4
- from tqdm import trange
5
- from modules import scripts, shared, processing, sd_schedulers, sd_samplers, script_callbacks, rng
6
- from modules import images, devices, prompt_parser, sd_models, ui_components, sd_models, extra_networks
7
- import modules.images as images
8
- import k_diffusion
9
-
10
- import gradio as gr
11
- import numpy as np
12
- from PIL import Image, ImageEnhance
13
- import torch
14
- import importlib
15
- from copy import copy
16
- from PIL import Image
17
- import json
18
- import gradio as gr
19
-
20
- quote_swap = str.maketrans('\'"', '"\'')
21
-
22
- def safe_import(import_name, pkg_name = None):
23
- try:
24
- __import__(import_name)
25
- except Exception:
26
- pkg_name = pkg_name or import_name
27
- import pip
28
- if hasattr(pip, 'main'):
29
- pip.main(['install', pkg_name])
30
- else:
31
- pip._internal.main(['install', pkg_name])
32
- __import__(import_name)
33
-
34
-
35
- safe_import('kornia')
36
- safe_import('omegaconf')
37
- safe_import('pathlib')
38
- from omegaconf import DictConfig, OmegaConf
39
- from pathlib import Path
40
- import kornia
41
- from skimage import exposure
42
-
43
- config_path = Path(__file__).parent.resolve() / '../config.yaml'
44
-
45
-
46
- class CustomHiresFix(scripts.Script):
47
- def __init__(self):
48
- super().__init__()
49
- if not exists(config_path):
50
- open(config_path, 'w').close()
51
- self.config: DictConfig = OmegaConf.load(config_path)
52
- self.callback_set = False
53
- self.orig_clip_skip = None
54
- self.cfg = 0
55
- self.p: processing.StableDiffusionProcessing = None
56
- self.pp = None
57
- self.sampler = None
58
- self.cond = None
59
- self.uncond = None
60
- self.prompt = ""
61
- self.negative_prompt = ""
62
- self.step = None
63
- self.tv = None
64
- self.width = None
65
- self.height = None
66
- self.extra_data = None
67
- self.use_cn = False
68
- self.external_code = None
69
- self.cn_image = None
70
- self.cn_units = []
71
-
72
- def title(self):
73
- return "Custom Hires Fix"
74
-
75
- def show(self, is_img2img):
76
- return scripts.AlwaysVisible
77
-
78
- def ui(self, is_img2img):
79
- sampler_names = ['Restart + DPM++ 3M SDE'] + [x.name for x in sd_samplers.visible_samplers()]
80
- scheduler_names = ['Use same scheduler'] + [x.label for x in sd_schedulers.schedulers]
81
-
82
- with gr.Accordion(label='Custom hires fix', open=False):
83
- enable = gr.Checkbox(label='Enable extension', value=self.config.get('enable', False))
84
- with gr.Row():
85
- width = gr.Slider(minimum=512, maximum=2048, step=8,
86
- label="Upscale width to",
87
- value=self.config.get('width', 1024), allow_flagging='never', show_progress=False)
88
- height = gr.Slider(minimum=512, maximum=2048, step=8,
89
- label="Upscale height to",
90
- value=self.config.get('height', 0), allow_flagging='never', show_progress=False)
91
- steps = gr.Slider(minimum=8, maximum=25, step=1,
92
- label="Steps",
93
- value=self.config.get('steps', 15))
94
-
95
- with gr.Row():
96
- prompt = gr.Textbox(label='Prompt for upscale (added to generation prompt)',
97
- placeholder='Leave empty for using generation prompt',
98
- value=self.prompt)
99
- with gr.Row():
100
- negative_prompt = gr.Textbox(label='Negative prompt for upscale (replaces generation prompt)',
101
- placeholder='Leave empty for using generation negative prompt',
102
- value=self.negative_prompt)
103
- with gr.Row():
104
- first_upscaler = gr.Dropdown([*[x.name for x in shared.sd_upscalers
105
- if x.name not in ['None', 'Nearest', 'LDSR']]],
106
- label='First upscaler',
107
- value=self.config.get('first_upscaler', 'R-ESRGAN 4x+'))
108
- second_upscaler = gr.Dropdown([*[x.name for x in shared.sd_upscalers
109
- if x.name not in ['None', 'Nearest', 'LDSR']]],
110
- label='Second upscaler',
111
- value=self.config.get('second_upscaler', 'R-ESRGAN 4x+'))
112
- with gr.Row():
113
- first_latent = gr.Slider(minimum=0.0, maximum=1.0, step=0.01,
114
- label="Latent upscale ratio (1)",
115
- value=self.config.get('first_latent', 0.3))
116
- second_latent = gr.Slider(minimum=0.0, maximum=1.0, step=0.01,
117
- label="Latent upscale ratio (2)",
118
- value=self.config.get('second_latent', 0.1))
119
- with gr.Row():
120
- filter = gr.Dropdown(['Noise sync (sharp)', 'Morphological (smooth)', 'Combined (balanced)'],
121
- label='Filter mode',
122
- value=self.config.get('filter', 'Noise sync (sharp)'))
123
- strength = gr.Slider(minimum=1.0, maximum=3.5, step=0.1, label="Generation strength",
124
- value=self.config.get('strength', 2.0))
125
- denoise_offset = gr.Slider(minimum=-0.05, maximum=0.15, step=0.01,
126
- label="Denoise offset",
127
- value=self.config.get('denoise_offset', 0.05))
128
- with gr.Accordion(label='Extra', open=False):
129
- with gr.Row():
130
- filter_offset = gr.Slider(minimum=-1.0, maximum=1.0, step=0.1,
131
- label="Filter offset (higher - smoother)",
132
- value=self.config.get('filter_offset', 0.0))
133
- clip_skip = gr.Slider(minimum=0, maximum=5, step=1,
134
- label="Clip skip for upscale (0 - not change)",
135
- value=self.config.get('clip_skip', 0))
136
- with gr.Row():
137
- start_control_at = gr.Slider(minimum=0.0, maximum=0.7, step=0.01,
138
- label="CN start for enabled units",
139
- value=self.config.get('start_control_at', 0.0))
140
- cn_ref = gr.Checkbox(label='Use last image for reference', value=self.config.get('cn_ref', False))
141
- with gr.Row():
142
- sampler = gr.Dropdown(sampler_names, label='Sampler', value=sampler_names[0])
143
- scheduler = gr.Dropdown(
144
- label='Schedule type',
145
- elem_id="custom_hires_fix_scheduler",
146
- choices=scheduler_names,
147
- value=scheduler_names[0]
148
- )
149
- cfg = gr.Slider(minimum=0, maximum=30, step=0.5, label="CFG Scale", value=self.cfg)
150
-
151
-
152
- if is_img2img:
153
- width.change(fn=lambda x: gr.update(value=0), inputs=width, outputs=height)
154
- height.change(fn=lambda x: gr.update(value=0), inputs=height, outputs=width)
155
- else:
156
- width.change(fn=lambda x: gr.update(value=0), inputs=width, outputs=height)
157
- height.change(fn=lambda x: gr.update(value=0), inputs=height, outputs=width)
158
-
159
- ui = [enable, width, height, steps, first_upscaler, second_upscaler, first_latent, second_latent, prompt,
160
- negative_prompt, strength, filter, filter_offset, denoise_offset, clip_skip, sampler, cfg, scheduler, cn_ref, start_control_at]
161
- for elem in ui:
162
- setattr(elem, "do_not_save_to_config", True)
163
- return ui
164
-
165
- def process(self, p, *args, **kwargs):
166
- self.p = p
167
- self.cn_units = []
168
- try:
169
- self.external_code = importlib.import_module('extensions.sd-webui-controlnet.scripts.external_code', 'external_code')
170
- cn_units = self.external_code.get_all_units_in_processing(p)
171
- for unit in cn_units:
172
- self.cn_units += [unit]
173
- self.use_cn = len(self.cn_units) > 0
174
- except ImportError:
175
- self.use_cn = False
176
-
177
- def postprocess_image(self, p, pp: scripts.PostprocessImageArgs,
178
- enable, width, height, steps, first_upscaler, second_upscaler, first_latent, second_latent, prompt,
179
- negative_prompt, strength, filter, filter_offset, denoise_offset, clip_skip, sampler, cfg, scheduler, cn_ref, start_control_at
180
- ):
181
- if not enable:
182
- return
183
- self.step = 0
184
- self.pp = pp
185
- self.config.width = width
186
- self.config.height = height
187
- self.config.prompt = prompt.strip()
188
- self.config.negative_prompt = negative_prompt.strip()
189
- self.config.steps = steps
190
- self.config.first_upscaler = first_upscaler
191
- self.config.second_upscaler = second_upscaler
192
- self.config.first_latent = first_latent
193
- self.config.second_latent = second_latent
194
- self.config.strength = strength
195
- self.config.filter = filter
196
- self.config.filter_offset = filter_offset
197
- self.config.denoise_offset = denoise_offset
198
- self.config.clip_skip = clip_skip
199
- self.config.sampler = sampler
200
- self.config.cn_ref = cn_ref
201
- self.config.start_control_at = start_control_at
202
- self.orig_clip_skip = shared.opts.CLIP_stop_at_last_layers
203
- self.cfg = cfg if cfg else p.cfg_scale
204
-
205
- if clip_skip > 0:
206
- shared.opts.CLIP_stop_at_last_layers = clip_skip
207
- if 'Restart' in self.config.sampler:
208
- self.sampler = sd_samplers.create_sampler('Restart', p.sd_model)
209
- else:
210
- self.sampler = sd_samplers.create_sampler(sampler, p.sd_model)
211
-
212
- def denoise_callback(params: script_callbacks.CFGDenoiserParams):
213
- if params.sampling_step > 0:
214
- p.cfg_scale = self.cfg
215
- if self.step == 1 and self.config.strength != 1.0:
216
- params.sigma[-1] = params.sigma[0] * (1 - (1 - self.config.strength) / 100)
217
- elif self.step == 2 and self.config.filter == 'Noise sync (sharp)':
218
- params.sigma[-1] = params.sigma[0] * (1 - (self.tv - 1 + self.config.filter_offset - (self.config.denoise_offset * 5)) / 50)
219
- elif self.step == 2 and self.config.filter == 'Combined (balanced)':
220
- params.sigma[-1] = params.sigma[0] * (1 - (self.tv - 1 + self.config.filter_offset - (self.config.denoise_offset * 5)) / 100)
221
-
222
- if self.callback_set is False:
223
- script_callbacks.on_cfg_denoiser(denoise_callback)
224
- self.callback_set = True
225
-
226
- _, loras_act = extra_networks.parse_prompt(prompt)
227
- extra_networks.activate(p, loras_act)
228
- _, loras_deact = extra_networks.parse_prompt(negative_prompt)
229
- extra_networks.deactivate(p, loras_deact)
230
-
231
- self.cn_image = pp.image
232
-
233
- try:
234
- with devices.autocast():
235
- shared.state.nextjob()
236
- x = self.gen(pp.image)
237
- shared.state.nextjob()
238
- x = self.filter(x)
239
- sd_models.apply_token_merging(p.sd_model, p.get_token_merging_ratio())
240
- pp.image = x
241
- finally:
242
- # Always restore and cleanup even if an exception occurs mid-way.
243
- shared.opts.CLIP_stop_at_last_layers = self.orig_clip_skip
244
- extra_networks.deactivate(p, loras_act)
245
- OmegaConf.save(self.config, config_path)
246
-
247
- def enable_cn(self, image: np.ndarray):
248
- for unit in self.cn_units:
249
- if unit.model != 'None':
250
- unit.guidance_start = self.config.start_control_at if unit.enabled else unit.guidance_start
251
- # Use the smaller side of the image (height vs width)
252
- unit.processor_res = min(image.shape[0], image.shape[1])
253
- unit.enabled = True
254
- if unit.image is None:
255
- unit.image = image
256
- self.p.width = image.shape[1]
257
- self.p.height = image.shape[0]
258
- self.external_code.update_cn_script_in_processing(self.p, self.cn_units)
259
- for script in self.p.scripts.alwayson_scripts:
260
- if script.title().lower() == 'controlnet':
261
- script.controlnet_hack(self.p)
262
-
263
- def process_prompt(self):
264
- prompt = self.p.prompt.strip().split('AND', 1)[0]
265
- if self.config.prompt != '':
266
- prompt = f'{prompt} {self.config.prompt}'
267
-
268
- if self.config.negative_prompt != '':
269
- negative_prompt = self.config.negative_prompt
270
- else:
271
- negative_prompt = self.p.negative_prompt.strip()
272
-
273
- with devices.autocast():
274
- if self.width is not None and self.height is not None and hasattr(prompt_parser, 'SdConditioning'):
275
- c = prompt_parser.SdConditioning([prompt], False, self.width, self.height)
276
- uc = prompt_parser.SdConditioning([negative_prompt], False, self.width, self.height)
277
- else:
278
- c = [prompt]
279
- uc = [negative_prompt]
280
- self.cond = prompt_parser.get_multicond_learned_conditioning(shared.sd_model, c, self.config.steps)
281
- self.uncond = prompt_parser.get_learned_conditioning(shared.sd_model, uc, self.config.steps)
282
-
283
- def gen(self, x):
284
- self.step = 1
285
- ratio = x.width / x.height
286
- self.width = self.config.width if self.config.width > 0 else int(self.config.height * ratio)
287
- self.height = self.config.height if self.config.height > 0 else int(self.config.width / ratio)
288
- self.width = int((self.width - x.width) // 2 + x.width)
289
- self.height = int((self.height - x.height) // 2 + x.height)
290
- sd_models.apply_token_merging(self.p.sd_model, self.p.get_token_merging_ratio(for_hr=True) / 2)
291
-
292
- if self.use_cn:
293
- self.enable_cn(np.array(self.cn_image.resize((self.width, self.height))))
294
-
295
- with devices.autocast(), torch.inference_mode():
296
- self.process_prompt()
297
-
298
- x_big = None
299
- if self.config.first_latent > 0:
300
- image = np.array(x).astype(np.float32) / 255.0
301
- image = np.moveaxis(image, 2, 0)
302
- decoded_sample = torch.from_numpy(image)
303
- decoded_sample = decoded_sample.to(shared.device).to(devices.dtype_vae)
304
- decoded_sample = 2.0 * decoded_sample - 1.0
305
- encoded_sample = shared.sd_model.encode_first_stage(decoded_sample.unsqueeze(0).to(devices.dtype_vae))
306
- sample = shared.sd_model.get_first_stage_encoding(encoded_sample)
307
- x_big = torch.nn.functional.interpolate(sample, (self.height // 8, self.width // 8), mode='nearest')
308
-
309
- if self.config.first_latent < 1:
310
- x = images.resize_image(0, x, self.width, self.height,
311
- upscaler_name=self.config.first_upscaler)
312
- image = np.array(x).astype(np.float32) / 255.0
313
- image = np.moveaxis(image, 2, 0)
314
- decoded_sample = torch.from_numpy(image)
315
- decoded_sample = decoded_sample.to(shared.device).to(devices.dtype_vae)
316
- decoded_sample = 2.0 * decoded_sample - 1.0
317
- encoded_sample = shared.sd_model.encode_first_stage(decoded_sample.unsqueeze(0).to(devices.dtype_vae))
318
- sample = shared.sd_model.get_first_stage_encoding(encoded_sample)
319
- else:
320
- sample = x_big
321
- if x_big is not None and self.config.first_latent != 1:
322
- sample = (sample * (1 - self.config.first_latent)) + (x_big * self.config.first_latent)
323
- image_conditioning = self.p.img2img_image_conditioning(decoded_sample, sample)
324
-
325
- noise = torch.zeros_like(sample)
326
- noise = kornia.augmentation.RandomGaussianNoise(mean=0.0, std=1.0, p=1.0)(noise)
327
- steps = int(max(((self.p.steps - self.config.steps) / 2) + self.config.steps, self.config.steps))
328
- self.p.denoising_strength = 0.45 + self.config.denoise_offset * 0.2
329
- self.p.cfg_scale = self.cfg + 3
330
-
331
- def denoiser_override(n):
332
- sigmas = k_diffusion.sampling.get_sigmas_polyexponential(n, 0.01, 15, 0.5, devices.device)
333
- return sigmas
334
-
335
- self.p.rng = rng.ImageRNG(sample.shape[1:], self.p.seeds, subseeds=self.p.subseeds,
336
- subseed_strength=self.p.subseed_strength,
337
- seed_resize_from_h=self.p.seed_resize_from_h, seed_resize_from_w=self.p.seed_resize_from_w)
338
-
339
- self.p.sampler_noise_scheduler_override = denoiser_override
340
- self.p.batch_size = 1
341
- sample = self.sampler.sample_img2img(self.p, sample.to(devices.dtype), noise, self.cond, self.uncond,
342
- steps=steps, image_conditioning=image_conditioning).to(devices.dtype_vae)
343
- b, c, w, h = sample.size()
344
- self.tv = kornia.losses.TotalVariation()(sample).mean() / (w * h)
345
- devices.torch_gc()
346
- decoded_sample = processing.decode_first_stage(shared.sd_model, sample)
347
- if math.isnan(decoded_sample.min()):
348
- devices.torch_gc()
349
- sample = torch.clamp(sample, -3, 3)
350
- decoded_sample = processing.decode_first_stage(shared.sd_model, sample)
351
- decoded_sample = torch.clamp((decoded_sample + 1.0) / 2.0, min=0.0, max=1.0).squeeze()
352
- x_sample = 255. * np.moveaxis(decoded_sample.cpu().numpy(), 0, 2)
353
- x_sample = x_sample.astype(np.uint8)
354
- image = Image.fromarray(x_sample)
355
- return image
356
-
357
-
358
- def filter(self, x):
359
- # Choose sampler for the 2nd stage.
360
- if 'Restart' in self.config.sampler and 'DPM++ 3M SDE' in self.config.sampler:
361
- # UI option "Restart + DPM++ 3M SDE":
362
- # 1st pass uses Restart (см. postprocess_image), 2nd pass uses DPM++ 3M SDE.
363
- self.sampler = sd_samplers.create_sampler('DPM++ 3M SDE', shared.sd_model)
364
- else:
365
- # Otherwise, respect the chosen sampler as-is.
366
- self.sampler = sd_samplers.create_sampler(self.config.sampler, shared.sd_model)
367
- self.step = 2
368
- ratio = x.width / x.height
369
- self.width = self.config.width if self.config.width > 0 else int(self.config.height * ratio)
370
- self.height = self.config.height if self.config.height > 0 else int(self.config.width / ratio)
371
- sd_models.apply_token_merging(self.p.sd_model, self.p.get_token_merging_ratio(for_hr=True))
372
-
373
- if self.use_cn:
374
- self.cn_image = x if self.config.cn_ref else self.cn_image
375
- self.enable_cn(np.array(self.cn_image.resize((self.width, self.height))))
376
-
377
- with devices.autocast(), torch.inference_mode():
378
- self.process_prompt()
379
-
380
- x_big = None
381
- if self.config.second_latent > 0:
382
- image = np.array(x).astype(np.float32) / 255.0
383
- image = np.moveaxis(image, 2, 0)
384
- decoded_sample = torch.from_numpy(image)
385
- decoded_sample = decoded_sample.to(shared.device).to(devices.dtype_vae)
386
- decoded_sample = 2.0 * decoded_sample - 1.0
387
- encoded_sample = shared.sd_model.encode_first_stage(decoded_sample.unsqueeze(0).to(devices.dtype_vae))
388
- sample = shared.sd_model.get_first_stage_encoding(encoded_sample)
389
- x_big = torch.nn.functional.interpolate(sample, (self.height // 8, self.width // 8), mode='nearest')
390
-
391
- if self.config.second_latent < 1:
392
- x = images.resize_image(0, x, self.width, self.height, upscaler_name=self.config.second_upscaler)
393
- image = np.array(x).astype(np.float32) / 255.0
394
- image = np.moveaxis(image, 2, 0)
395
- decoded_sample = torch.from_numpy(image)
396
- decoded_sample = decoded_sample.to(shared.device).to(devices.dtype_vae)
397
- decoded_sample = 2.0 * decoded_sample - 1.0
398
- encoded_sample = shared.sd_model.encode_first_stage(decoded_sample.unsqueeze(0).to(devices.dtype_vae))
399
- sample = shared.sd_model.get_first_stage_encoding(encoded_sample)
400
- else:
401
- sample = x_big
402
- if x_big is not None and self.config.second_latent != 1:
403
- sample = (sample * (1 - self.config.second_latent)) + (x_big * self.config.second_latent)
404
- image_conditioning = self.p.img2img_image_conditioning(decoded_sample, sample)
405
-
406
- noise = torch.zeros_like(sample)
407
- noise = kornia.augmentation.RandomGaussianNoise(mean=0.0, std=1.0, p=1.0)(noise)
408
- self.p.denoising_strength = 0.45 + self.config.denoise_offset
409
- self.p.cfg_scale = self.cfg + 3
410
-
411
- if self.config.filter == 'Morphological (smooth)':
412
- noise_mask = kornia.morphology.gradient(sample, torch.ones(5, 5).to(devices.device))
413
- noise_mask = kornia.filters.median_blur(noise_mask, (3, 3))
414
- noise_mask = (0.1 + noise_mask / noise_mask.max()) * (max(
415
- (1.75 - (self.tv - 1) * 4), 1.75) - self.config.filter_offset)
416
- noise = noise * noise_mask
417
- elif self.config.filter == 'Combined (balanced)':
418
- noise_mask = kornia.morphology.gradient(sample, torch.ones(5, 5).to(devices.device))
419
- noise_mask = kornia.filters.median_blur(noise_mask, (3, 3))
420
- noise_mask = (0.1 + noise_mask / noise_mask.max()) * (max(
421
- (1.75 - (self.tv - 1) / 2), 1.75) - self.config.filter_offset)
422
- noise = noise * noise_mask
423
-
424
- def denoiser_override(n):
425
- return k_diffusion.sampling.get_sigmas_polyexponential(n, 0.01, 7, 0.5, devices.device)
426
-
427
- self.p.sampler_noise_scheduler_override = denoiser_override
428
- self.p.batch_size = 1
429
- samples = self.sampler.sample_img2img(self.p, sample.to(devices.dtype), noise, self.cond, self.uncond,
430
- steps=self.config.steps, image_conditioning=image_conditioning
431
- ).to(devices.dtype_vae)
432
- devices.torch_gc()
433
- self.p.iteration += 1
434
- decoded_sample = processing.decode_first_stage(shared.sd_model, samples)
435
- if math.isnan(decoded_sample.min()):
436
- devices.torch_gc()
437
- samples = torch.clamp(samples, -3, 3)
438
- decoded_sample = processing.decode_first_stage(shared.sd_model, samples)
439
- decoded_sample = torch.clamp((decoded_sample + 1.0) / 2.0, min=0.0, max=1.0).squeeze()
440
- x_sample = 255. * np.moveaxis(decoded_sample.cpu().numpy(), 0, 2)
441
- x_sample = x_sample.astype(np.uint8)
442
- image = Image.fromarray(x_sample)
443
- return image