| 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 |
|
|