| | import time
|
| | import math
|
| | import logging
|
| | from PIL import Image, ImageDraw, ImageFilter
|
| | from backend.models.lcmdiffusion_setting import DiffusionTask
|
| | from context import Context
|
| | from constants import DEVICE
|
| |
|
| |
|
| | def generate_upscaled_image(
|
| | config,
|
| | input_path=None,
|
| | strength=0.3,
|
| | scale_factor=2.0,
|
| | tile_overlap=16,
|
| | upscale_settings=None,
|
| | context: Context = None,
|
| | output_path=None,
|
| | image_format="PNG",
|
| | ):
|
| | if config == None or (
|
| | input_path == None or input_path == "" and upscale_settings == None
|
| | ):
|
| | logging.error("Wrong arguments in tiled upscale function call!")
|
| | return
|
| |
|
| |
|
| |
|
| | if upscale_settings == None:
|
| | upscale_settings = {
|
| | "source_file": input_path,
|
| | "target_file": None,
|
| | "output_format": image_format,
|
| | "strength": strength,
|
| | "scale_factor": scale_factor,
|
| | "prompt": config.lcm_diffusion_setting.prompt,
|
| | "tile_overlap": tile_overlap,
|
| | "tile_size": 256,
|
| | "tiles": [],
|
| | }
|
| | source_image = Image.open(input_path)
|
| | else:
|
| | source_image = Image.open(upscale_settings["source_file"])
|
| |
|
| | upscale_settings["source_image"] = source_image
|
| |
|
| | if upscale_settings["target_file"]:
|
| | result = Image.open(upscale_settings["target_file"])
|
| | else:
|
| | result = Image.new(
|
| | mode="RGBA",
|
| | size=(
|
| | source_image.size[0] * int(upscale_settings["scale_factor"]),
|
| | source_image.size[1] * int(upscale_settings["scale_factor"]),
|
| | ),
|
| | color=(0, 0, 0, 0),
|
| | )
|
| | upscale_settings["target_image"] = result
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | if len(upscale_settings["tiles"]) == 0:
|
| | tile_size = upscale_settings["tile_size"]
|
| | scale_factor = upscale_settings["scale_factor"]
|
| | tile_overlap = upscale_settings["tile_overlap"]
|
| | total_cols = math.ceil(
|
| | source_image.size[0] / tile_size
|
| | )
|
| | total_rows = math.ceil(
|
| | source_image.size[1] / tile_size
|
| | )
|
| | for y in range(0, total_rows):
|
| | y_offset = tile_overlap if y > 0 else 0
|
| | for x in range(0, total_cols):
|
| | x_offset = tile_overlap if x > 0 else 0
|
| | x1 = x * tile_size
|
| | y1 = y * tile_size
|
| | w = tile_size + (tile_overlap if x < total_cols - 1 else 0)
|
| | h = tile_size + (tile_overlap if y < total_rows - 1 else 0)
|
| | mask_box = (
|
| | x_offset,
|
| | y_offset,
|
| | int(w * scale_factor),
|
| | int(h * scale_factor),
|
| | )
|
| | upscale_settings["tiles"].append(
|
| | {
|
| | "x": x1,
|
| | "y": y1,
|
| | "w": w,
|
| | "h": h,
|
| | "mask_box": mask_box,
|
| | "prompt": upscale_settings["prompt"],
|
| | "scale_factor": scale_factor,
|
| | }
|
| | )
|
| |
|
| |
|
| | for i in range(0, len(upscale_settings["tiles"])):
|
| | generate_upscaled_tile(
|
| | config,
|
| | i,
|
| | upscale_settings,
|
| | context=context,
|
| | )
|
| |
|
| |
|
| | if upscale_settings["output_format"].upper() == "JPEG":
|
| | result_rgb = result.convert("RGB")
|
| | result.close()
|
| | result = result_rgb
|
| | result.save(output_path)
|
| | result.close()
|
| | source_image.close()
|
| | return
|
| |
|
| |
|
| | def get_current_tile(
|
| | config,
|
| | context,
|
| | strength,
|
| | ):
|
| | config.lcm_diffusion_setting.strength = strength
|
| | config.lcm_diffusion_setting.diffusion_task = DiffusionTask.image_to_image.value
|
| | if (
|
| | config.lcm_diffusion_setting.use_tiny_auto_encoder
|
| | and config.lcm_diffusion_setting.use_openvino
|
| | ):
|
| | config.lcm_diffusion_setting.use_tiny_auto_encoder = False
|
| | current_tile = context.generate_text_to_image(
|
| | settings=config,
|
| | reshape=True,
|
| | device=DEVICE,
|
| | save_config=False,
|
| | )[0]
|
| | return current_tile
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | def generate_upscaled_tile(
|
| | config,
|
| | index,
|
| | upscale_settings,
|
| | context: Context = None,
|
| | ):
|
| | if config == None or upscale_settings == None:
|
| | logging.error("Wrong arguments in tile creation function call!")
|
| | return
|
| |
|
| | x = upscale_settings["tiles"][index]["x"]
|
| | y = upscale_settings["tiles"][index]["y"]
|
| | w = upscale_settings["tiles"][index]["w"]
|
| | h = upscale_settings["tiles"][index]["h"]
|
| | tile_prompt = upscale_settings["tiles"][index]["prompt"]
|
| | scale_factor = upscale_settings["scale_factor"]
|
| | tile_scale_factor = upscale_settings["tiles"][index]["scale_factor"]
|
| | target_width = int(w * tile_scale_factor)
|
| | target_height = int(h * tile_scale_factor)
|
| | strength = upscale_settings["strength"]
|
| | source_image = upscale_settings["source_image"]
|
| | target_image = upscale_settings["target_image"]
|
| | mask_image = generate_tile_mask(config, index, upscale_settings)
|
| |
|
| | config.lcm_diffusion_setting.number_of_images = 1
|
| | config.lcm_diffusion_setting.prompt = tile_prompt
|
| | config.lcm_diffusion_setting.image_width = target_width
|
| | config.lcm_diffusion_setting.image_height = target_height
|
| | config.lcm_diffusion_setting.init_image = source_image.crop((x, y, x + w, y + h))
|
| |
|
| | current_tile = None
|
| | print(f"[SD Upscale] Generating tile {index + 1}/{len(upscale_settings['tiles'])} ")
|
| | if tile_prompt == None or tile_prompt == "":
|
| | config.lcm_diffusion_setting.prompt = ""
|
| | config.lcm_diffusion_setting.negative_prompt = ""
|
| | current_tile = get_current_tile(config, context, strength)
|
| | else:
|
| |
|
| |
|
| |
|
| | current_tile = get_current_tile(config, context, strength)
|
| |
|
| | if math.isclose(scale_factor, tile_scale_factor):
|
| | target_image.paste(
|
| | current_tile, (int(x * scale_factor), int(y * scale_factor)), mask_image
|
| | )
|
| | else:
|
| | target_image.paste(
|
| | current_tile.resize((int(w * scale_factor), int(h * scale_factor))),
|
| | (int(x * scale_factor), int(y * scale_factor)),
|
| | mask_image.resize((int(w * scale_factor), int(h * scale_factor))),
|
| | )
|
| | mask_image.close()
|
| | current_tile.close()
|
| | config.lcm_diffusion_setting.init_image.close()
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | def generate_tile_mask(
|
| | config,
|
| | index,
|
| | upscale_settings,
|
| | ):
|
| | scale_factor = upscale_settings["scale_factor"]
|
| | tile_overlap = upscale_settings["tile_overlap"]
|
| | tile_scale_factor = upscale_settings["tiles"][index]["scale_factor"]
|
| | w = int(upscale_settings["tiles"][index]["w"] * tile_scale_factor)
|
| | h = int(upscale_settings["tiles"][index]["h"] * tile_scale_factor)
|
| |
|
| |
|
| |
|
| | w = w - (w % 8)
|
| | h = h - (h % 8)
|
| | mask_box = upscale_settings["tiles"][index]["mask_box"]
|
| | if mask_box == None:
|
| |
|
| | mask_box = (
|
| | tile_overlap,
|
| | tile_overlap,
|
| | w - tile_overlap,
|
| | h - tile_overlap,
|
| | )
|
| | mask_image = Image.new(mode="RGBA", size=(w, h), color=(0, 0, 0, 0))
|
| | mask_draw = ImageDraw.Draw(mask_image)
|
| | mask_draw.rectangle(tuple(mask_box), fill=(0, 0, 0))
|
| | mask_blur = mask_image.filter(ImageFilter.BoxBlur(tile_overlap - 1))
|
| | mask_image.close()
|
| | return mask_blur
|
| |
|