Spaces:
Runtime error
Runtime error
# ComfyUI Node for Ultimate SD Upscale by Coyote-A: https://github.com/Coyote-A/ultimate-upscale-for-automatic1111 | |
import logging | |
import torch | |
import comfy | |
from usdu_patch import usdu | |
from utils import tensor_to_pil, pil_to_tensor | |
from modules.processing import StableDiffusionProcessing | |
import modules.shared as shared | |
from modules.upscaler import UpscalerData | |
MAX_RESOLUTION = 8192 | |
# The modes available for Ultimate SD Upscale | |
MODES = { | |
"Linear": usdu.USDUMode.LINEAR, | |
"Chess": usdu.USDUMode.CHESS, | |
"None": usdu.USDUMode.NONE, | |
} | |
# The seam fix modes | |
SEAM_FIX_MODES = { | |
"None": usdu.USDUSFMode.NONE, | |
"Band Pass": usdu.USDUSFMode.BAND_PASS, | |
"Half Tile": usdu.USDUSFMode.HALF_TILE, | |
"Half Tile + Intersections": usdu.USDUSFMode.HALF_TILE_PLUS_INTERSECTIONS, | |
} | |
def USDU_base_inputs(): | |
required = [ | |
("image", ("IMAGE",)), | |
# Sampling Params | |
("model", ("MODEL",)), | |
("positive", ("CONDITIONING",)), | |
("negative", ("CONDITIONING",)), | |
("vae", ("VAE",)), | |
("upscale_by", ("FLOAT", {"default": 2, "min": 0.05, "max": 4, "step": 0.05})), | |
("seed", ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff})), | |
("steps", ("INT", {"default": 20, "min": 1, "max": 10000, "step": 1})), | |
("cfg", ("FLOAT", {"default": 8.0, "min": 0.0, "max": 100.0})), | |
("sampler_name", (comfy.samplers.KSampler.SAMPLERS,)), | |
("scheduler", (comfy.samplers.KSampler.SCHEDULERS,)), | |
("denoise", ("FLOAT", {"default": 0.2, "min": 0.0, "max": 1.0, "step": 0.01})), | |
# Upscale Params | |
("upscale_model", ("UPSCALE_MODEL",)), | |
("mode_type", (list(MODES.keys()),)), | |
("tile_width", ("INT", {"default": 512, "min": 64, "max": MAX_RESOLUTION, "step": 8})), | |
("tile_height", ("INT", {"default": 512, "min": 64, "max": MAX_RESOLUTION, "step": 8})), | |
("mask_blur", ("INT", {"default": 8, "min": 0, "max": 64, "step": 1})), | |
("tile_padding", ("INT", {"default": 32, "min": 0, "max": MAX_RESOLUTION, "step": 8})), | |
# Seam fix params | |
("seam_fix_mode", (list(SEAM_FIX_MODES.keys()),)), | |
("seam_fix_denoise", ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01})), | |
("seam_fix_width", ("INT", {"default": 64, "min": 0, "max": MAX_RESOLUTION, "step": 8})), | |
("seam_fix_mask_blur", ("INT", {"default": 8, "min": 0, "max": 64, "step": 1})), | |
("seam_fix_padding", ("INT", {"default": 16, "min": 0, "max": MAX_RESOLUTION, "step": 8})), | |
# Misc | |
("force_uniform_tiles", ("BOOLEAN", {"default": True})), | |
("tiled_decode", ("BOOLEAN", {"default": False})), | |
] | |
optional = [] | |
return required, optional | |
def prepare_inputs(required: list, optional: list = None): | |
inputs = {} | |
if required: | |
inputs["required"] = {} | |
for name, type in required: | |
inputs["required"][name] = type | |
if optional: | |
inputs["optional"] = {} | |
for name, type in optional: | |
inputs["optional"][name] = type | |
return inputs | |
def remove_input(inputs: list, input_name: str): | |
for i, (n, _) in enumerate(inputs): | |
if n == input_name: | |
del inputs[i] | |
break | |
def rename_input(inputs: list, old_name: str, new_name: str): | |
for i, (n, t) in enumerate(inputs): | |
if n == old_name: | |
inputs[i] = (new_name, t) | |
break | |
class UltimateSDUpscale: | |
def INPUT_TYPES(s): | |
required, optional = USDU_base_inputs() | |
return prepare_inputs(required, optional) | |
RETURN_TYPES = ("IMAGE",) | |
FUNCTION = "upscale" | |
CATEGORY = "image/upscaling" | |
def upscale(self, image, model, positive, negative, vae, upscale_by, seed, | |
steps, cfg, sampler_name, scheduler, denoise, upscale_model, | |
mode_type, tile_width, tile_height, mask_blur, tile_padding, | |
seam_fix_mode, seam_fix_denoise, seam_fix_mask_blur, | |
seam_fix_width, seam_fix_padding, force_uniform_tiles, tiled_decode, | |
custom_sampler=None, custom_sigmas=None): | |
# Store params | |
self.tile_width = tile_width | |
self.tile_height = tile_height | |
self.mask_blur = mask_blur | |
self.tile_padding = tile_padding | |
self.seam_fix_width = seam_fix_width | |
self.seam_fix_denoise = seam_fix_denoise | |
self.seam_fix_padding = seam_fix_padding | |
self.seam_fix_mode = seam_fix_mode | |
self.mode_type = mode_type | |
self.upscale_by = upscale_by | |
self.seam_fix_mask_blur = seam_fix_mask_blur | |
# | |
# Set up A1111 patches | |
# | |
# Upscaler | |
# An object that the script works with | |
shared.sd_upscalers[0] = UpscalerData() | |
# Where the actual upscaler is stored, will be used when the script upscales using the Upscaler in UpscalerData | |
shared.actual_upscaler = upscale_model | |
# Set the batch of images | |
shared.batch = [tensor_to_pil(image, i) for i in range(len(image))] | |
# Processing | |
self.sdprocessing = StableDiffusionProcessing( | |
tensor_to_pil(image), model, positive, negative, vae, | |
seed, steps, cfg, sampler_name, scheduler, denoise, upscale_by, force_uniform_tiles, tiled_decode, | |
custom_sampler, custom_sigmas | |
) | |
# Disable logging | |
logger = logging.getLogger() | |
old_level = logger.getEffectiveLevel() | |
logger.setLevel(logging.CRITICAL + 1) | |
try: | |
# | |
# Running the script | |
# | |
script = usdu.Script() | |
processed = script.run(p=self.sdprocessing, _=None, tile_width=self.tile_width, tile_height=self.tile_height, | |
mask_blur=self.mask_blur, padding=self.tile_padding, seams_fix_width=self.seam_fix_width, | |
seams_fix_denoise=self.seam_fix_denoise, seams_fix_padding=self.seam_fix_padding, | |
upscaler_index=0, save_upscaled_image=False, redraw_mode=MODES[self.mode_type], | |
save_seams_fix_image=False, seams_fix_mask_blur=self.seam_fix_mask_blur, | |
seams_fix_type=SEAM_FIX_MODES[self.seam_fix_mode], target_size_type=2, | |
custom_width=None, custom_height=None, custom_scale=self.upscale_by) | |
# Return the resulting images | |
images = [pil_to_tensor(img) for img in shared.batch] | |
tensor = torch.cat(images, dim=0) | |
return (tensor,) | |
finally: | |
# Restore the original logging level | |
logger.setLevel(old_level) | |
class UltimateSDUpscaleNoUpscale(UltimateSDUpscale): | |
def INPUT_TYPES(s): | |
required, optional = USDU_base_inputs() | |
remove_input(required, "upscale_model") | |
remove_input(required, "upscale_by") | |
rename_input(required, "image", "upscaled_image") | |
return prepare_inputs(required, optional) | |
RETURN_TYPES = ("IMAGE",) | |
FUNCTION = "upscale" | |
CATEGORY = "image/upscaling" | |
def upscale(self, upscaled_image, model, positive, negative, vae, seed, | |
steps, cfg, sampler_name, scheduler, denoise, | |
mode_type, tile_width, tile_height, mask_blur, tile_padding, | |
seam_fix_mode, seam_fix_denoise, seam_fix_mask_blur, | |
seam_fix_width, seam_fix_padding, force_uniform_tiles, tiled_decode): | |
upscale_by = 1.0 | |
return super().upscale(upscaled_image, model, positive, negative, vae, upscale_by, seed, | |
steps, cfg, sampler_name, scheduler, denoise, None, | |
mode_type, tile_width, tile_height, mask_blur, tile_padding, | |
seam_fix_mode, seam_fix_denoise, seam_fix_mask_blur, | |
seam_fix_width, seam_fix_padding, force_uniform_tiles, tiled_decode) | |
class UltimateSDUpscaleCustomSample(UltimateSDUpscale): | |
def INPUT_TYPES(s): | |
required, optional = USDU_base_inputs() | |
remove_input(required, "upscale_model") | |
optional.append(("upscale_model", ("UPSCALE_MODEL",))) | |
optional.append(("custom_sampler", ("SAMPLER",))) | |
optional.append(("custom_sigmas", ("SIGMAS",))) | |
return prepare_inputs(required, optional) | |
RETURN_TYPES = ("IMAGE",) | |
FUNCTION = "upscale" | |
CATEGORY = "image/upscaling" | |
def upscale(self, image, model, positive, negative, vae, upscale_by, seed, | |
steps, cfg, sampler_name, scheduler, denoise, | |
mode_type, tile_width, tile_height, mask_blur, tile_padding, | |
seam_fix_mode, seam_fix_denoise, seam_fix_mask_blur, | |
seam_fix_width, seam_fix_padding, force_uniform_tiles, tiled_decode, | |
upscale_model=None, | |
custom_sampler=None, custom_sigmas=None): | |
return super().upscale(image, model, positive, negative, vae, upscale_by, seed, | |
steps, cfg, sampler_name, scheduler, denoise, upscale_model, | |
mode_type, tile_width, tile_height, mask_blur, tile_padding, | |
seam_fix_mode, seam_fix_denoise, seam_fix_mask_blur, | |
seam_fix_width, seam_fix_padding, force_uniform_tiles, tiled_decode, | |
custom_sampler, custom_sigmas) | |
# A dictionary that contains all nodes you want to export with their names | |
# NOTE: names should be globally unique | |
NODE_CLASS_MAPPINGS = { | |
"UltimateSDUpscale": UltimateSDUpscale, | |
"UltimateSDUpscaleNoUpscale": UltimateSDUpscaleNoUpscale, | |
"UltimateSDUpscaleCustomSample": UltimateSDUpscaleCustomSample | |
} | |
# A dictionary that contains the friendly/humanly readable titles for the nodes | |
NODE_DISPLAY_NAME_MAPPINGS = { | |
"UltimateSDUpscale": "Ultimate SD Upscale", | |
"UltimateSDUpscaleNoUpscale": "Ultimate SD Upscale (No Upscale)", | |
"UltimateSDUpscaleCustomSample": "Ultimate SD Upscale (Custom Sample)" | |
} | |