Files
CavinHuang-comfyui-nodes-docs/docs/HighRes-Fix Script.md
2024-07-04 08:39:03 +08:00

11 KiB

Documentation

  • Class name: HighRes-Fix Script
  • Category: Efficiency Nodes/Scripts
  • Output node: False

HighRes-Fix Script节点旨在以可定制的方式提升图像分辨率和质量。它利用各种放大技术、控制网络和预处理步骤来优化图像,提供种子一致性、去噪和迭代细化的选项。该节点与动画和控制网络脚本集成,适应特定的高分辨率增强需求,同时保持与不同放大模型和预处理器配合使用的灵活性。

Input types

Required

  • upscale_type
    • 指定要使用的放大方法,影响高分辨率输出的质量和方法。
    • Comfy dtype: COMBO[STRING]
    • Python dtype: str
  • hires_ckpt_name
    • 高分辨率模型的检查点名称,表示用于放大的特定模型版本或配置。
    • Comfy dtype: COMBO[STRING]
    • Python dtype: str
  • latent_upscaler
    • 标识潜在空间放大方法,在进行像素级调整之前在基础层面上增强图像细节。
    • Comfy dtype: COMBO[STRING]
    • Python dtype: str
  • pixel_upscaler
    • 定义像素级放大方法,在潜在空间增强后进一步细化图像细节。
    • Comfy dtype: COMBO[STRING]
    • Python dtype: str
  • upscale_by
    • 确定放大过程的缩放因子,直接影响最终图像的大小和细节。
    • Comfy dtype: FLOAT
    • Python dtype: float
  • use_same_seed
    • 控制是否在整个放大过程中使用相同的种子,确保随机元素的一致性。
    • Comfy dtype: BOOLEAN
    • Python dtype: bool
  • seed
    • 随机过程的初始种子值,为可重复性和变化控制提供起点。
    • Comfy dtype: INT
    • Python dtype: int
  • hires_steps
    • 指定在高分辨率增强过程中要执行的步骤数,影响细化的深度。
    • Comfy dtype: INT
    • Python dtype: int
  • denoise
    • 表示在放大过程中是否应用去噪,通过减少噪声来改善图像清晰度。
    • Comfy dtype: FLOAT
    • Python dtype: bool
  • iterations
    • 运行放大过程的迭代次数,允许多次细化。
    • Comfy dtype: INT
    • Python dtype: int
  • use_controlnet
    • 确定是否使用控制网络进行引导放大,影响增强的方向和质量。
    • Comfy dtype: BOOLEAN
    • Python dtype: bool
  • control_net_name
    • 要使用的控制网络的名称,指定用于引导放大的模型。
    • Comfy dtype: COMBO[STRING]
    • Python dtype: str
  • strength
    • 控制网络对放大过程影响的强度,调整引导的程度。
    • Comfy dtype: FLOAT
    • Python dtype: float
  • preprocessor
    • 用于准备图像进行放大的预处理方法,影响初始质量和兼容性。
    • Comfy dtype: COMBO[STRING]
    • Python dtype: str
  • preprocessor_imgs
    • 准备好进行放大的预处理图像,作为增强过程的输入。
    • Comfy dtype: BOOLEAN
    • Python dtype: list

Optional

  • script
    • 包含放大过程的附加参数或配置的可选脚本。
    • Comfy dtype: SCRIPT
    • Python dtype: dict

Output types

  • script
    • 应用高分辨率修复后产生的脚本配置,封装了过程中指定的所有参数和进行的调整。
    • Comfy dtype: SCRIPT
    • Python dtype: dict

Usage tips

  • Infra type: GPU
  • Common nodes:
    • [KSampler SDXL (Eff.)](../../efficiency-nodes-comfyui/Nodes/KSampler SDXL (Eff.).md)

Source code

class TSC_HighRes_Fix:

    default_latent_upscalers = LatentUpscaleBy.INPUT_TYPES()["required"]["upscale_method"][0]

    city96_upscale_methods =\
        ["city96." + ver for ver in city96_latent_upscaler.LatentUpscaler.INPUT_TYPES()["required"]["latent_ver"][0]]
    city96_scalings_raw = city96_latent_upscaler.LatentUpscaler.INPUT_TYPES()["required"]["scale_factor"][0]
    city96_scalings_float = [float(scale) for scale in city96_scalings_raw]

    ttl_nn_upscale_methods = \
        ["ttl_nn." + ver for ver in
         ttl_nn_latent_upscaler.NNLatentUpscale.INPUT_TYPES()["required"]["version"][0]]

    latent_upscalers = default_latent_upscalers + city96_upscale_methods + ttl_nn_upscale_methods
    pixel_upscalers = folder_paths.get_filename_list("upscale_models")

    @classmethod
    def INPUT_TYPES(cls):

        return {"required": {"upscale_type": (["latent","pixel","both"],),
                             "hires_ckpt_name": (["(use same)"] + folder_paths.get_filename_list("checkpoints"),),
                             "latent_upscaler": (cls.latent_upscalers,),
                             "pixel_upscaler": (cls.pixel_upscalers,),
                             "upscale_by": ("FLOAT", {"default": 1.25, "min": 0.01, "max": 8.0, "step": 0.05}),
                             "use_same_seed": ("BOOLEAN", {"default": True}),
                             "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
                             "hires_steps": ("INT", {"default": 12, "min": 1, "max": 10000}),
                             "denoise": ("FLOAT", {"default": .56, "min": 0.00, "max": 1.00, "step": 0.01}),
                             "iterations": ("INT", {"default": 1, "min": 0, "max": 5, "step": 1}),
                             "use_controlnet": use_controlnet_widget,
                             "control_net_name": (folder_paths.get_filename_list("controlnet"),),
                             "strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
                             "preprocessor": preprocessor_widget,
                             "preprocessor_imgs": ("BOOLEAN", {"default": False})
                             },
                "optional": {"script": ("SCRIPT",)},
                "hidden": {"my_unique_id": "UNIQUE_ID"}
                }

    RETURN_TYPES = ("SCRIPT",)
    FUNCTION = "hires_fix_script"
    CATEGORY = "Efficiency Nodes/Scripts"

    def hires_fix_script(self, upscale_type, hires_ckpt_name, latent_upscaler, pixel_upscaler, upscale_by,
                         use_same_seed, seed, hires_steps, denoise, iterations, use_controlnet, control_net_name,
                         strength, preprocessor, preprocessor_imgs, script=None, my_unique_id=None):
        latent_upscale_function = None
        latent_upscale_model = None
        pixel_upscale_model = None

        def float_to_string(num):
            if num == int(num):
                return "{:.1f}".format(num)
            else:
                return str(num)

        if iterations > 0 and upscale_by > 0:
            if upscale_type == "latent":
                # For latent methods from city96
                if latent_upscaler in self.city96_upscale_methods:
                    # Remove extra characters added
                    latent_upscaler = latent_upscaler.replace("city96.", "")

                    # Set function to city96_latent_upscaler.LatentUpscaler
                    latent_upscale_function = city96_latent_upscaler.LatentUpscaler

                    # Find the nearest valid scaling in city96_scalings_float
                    nearest_scaling = min(self.city96_scalings_float, key=lambda x: abs(x - upscale_by))

                    # Retrieve the index of the nearest scaling
                    nearest_scaling_index = self.city96_scalings_float.index(nearest_scaling)

                    # Use the index to get the raw string representation
                    nearest_scaling_raw = self.city96_scalings_raw[nearest_scaling_index]

                    upscale_by = float_to_string(upscale_by)

                    # Check if the input upscale_by value was different from the nearest valid value
                    if upscale_by != nearest_scaling_raw:
                        print(f"{warning('HighRes-Fix Warning:')} "
                              f"When using 'city96.{latent_upscaler}', 'upscale_by' must be one of {self.city96_scalings_raw}.\n"
                              f"Rounding to the nearest valid value ({nearest_scaling_raw}).\033[0m")
                        upscale_by = nearest_scaling_raw

                # For ttl upscale methods
                elif latent_upscaler in self.ttl_nn_upscale_methods:
                    # Remove extra characters added
                    latent_upscaler = latent_upscaler.replace("ttl_nn.", "")

                    # Bound to min/max limits
                    upscale_by_clamped = min(max(upscale_by, 1), 2)
                    if upscale_by != upscale_by_clamped:
                        print(f"{warning('HighRes-Fix Warning:')} "
                              f"When using 'ttl_nn.{latent_upscaler}', 'upscale_by' must be between 1 and 2.\n"
                              f"Rounding to the nearest valid value ({upscale_by_clamped}).\033[0m")
                    upscale_by = upscale_by_clamped

                    latent_upscale_function = ttl_nn_latent_upscaler.NNLatentUpscale

                # For default upscale methods
                elif latent_upscaler in self.default_latent_upscalers:
                    latent_upscale_function = LatentUpscaleBy

                else: # Default
                    latent_upscale_function = LatentUpscaleBy
                    latent_upscaler = self.default_latent_upscalers[0]
                    print(f"{warning('HiResFix Script Warning:')} Chosen latent upscale method not found! "
                          f"defaulting to '{latent_upscaler}'.\n")

                # Load Checkpoint if defined
                if hires_ckpt_name == "(use same)":
                    clear_cache(my_unique_id, 0, "ckpt")
                else:
                    latent_upscale_model, _, _ = \
                        load_checkpoint(hires_ckpt_name, my_unique_id, output_vae=False, cache=1, cache_overwrite=True)

            elif upscale_type == "pixel":
                pixel_upscale_model = UpscaleModelLoader().load_model(pixel_upscaler)[0]

            elif upscale_type == "both":
                latent_upscale_function = LatentUpscaleBy
                latent_upscaler = self.default_latent_upscalers[0]
                pixel_upscale_model = UpscaleModelLoader().load_model(pixel_upscaler)[0]

                if hires_ckpt_name == "(use same)":
                    clear_cache(my_unique_id, 0, "ckpt")
                else:
                    latent_upscale_model, _, _ = \
                        load_checkpoint(hires_ckpt_name, my_unique_id, output_vae=False, cache=1, cache_overwrite=True)

        control_net = ControlNetLoader().load_controlnet(control_net_name)[0] if use_controlnet is True else None

        # Construct the script output
        script = script or {}
        script["hiresfix"] = (upscale_type, latent_upscaler, upscale_by, use_same_seed, seed, hires_steps,
                              denoise, iterations, control_net, strength, preprocessor, preprocessor_imgs,
                              latent_upscale_function, latent_upscale_model, pixel_upscale_model)

        return (script,)