Files
CavinHuang-comfyui-nodes-docs/docs/easy preMaskDetailerFix.md
2024-05-26 20:35:16 +08:00

6.6 KiB

Documentation

preMaskDetailerFix是一个旨在增强图像处理流程中细节保留和编辑能力的节点。它专注于完善掩膜应用过程,确保图像的预期区域被准确定位。该节点通过考虑各种指导其行为的参数来运行,例如掩膜规格、引导尺寸和编辑配置。它在概念上以提高图像操作任务的保真度和精确性为中心,而不局限于具体的实现细节。

Input types

Required

  • pipe
    • ‘pipe’参数至关重要,因为它携带了整个图像处理流水线的状态,包括模型、图像和其他设置。对于节点的正确功能和处理工作流的连续性至关重要。
    • Comfy dtype: PIPE_LINE
    • Python dtype: Dict
  • mask
    • ‘mask’参数对于定义图像中需要增强或修改的感兴趣区域至关重要。它直接影响节点对目标区域应用详细修复的能力。
    • Comfy dtype: MASK
    • Python dtype: torch.Tensor
  • guide_size
    • ‘guide_size’参数很重要,因为它决定了用于细化细节修复过程的引导图的大小。它影响节点如何识别和处理需要关注的区域。
    • Comfy dtype: FLOAT
    • Python dtype: float

Output types

  • pipe
    • ‘pipe’输出是输入流水线的更新版本,现在应用了细节修复并增加了进一步处理的设置。这是一个关键的输出,因为它允许流水线继续使用增强的图像数据。
    • Comfy dtype: PIPE_LINE
    • Python dtype: Dict

Usage tips

  • Infra type: GPU

Source code

class preMaskDetailerFix:

    @classmethod
    def INPUT_TYPES(s):
        return {'required': {'pipe': ('PIPE_LINE',), 'mask': ('MASK',), 'guide_size': ('FLOAT', {'default': 384, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'guide_size_for': ('BOOLEAN', {'default': True, 'label_on': 'bbox', 'label_off': 'crop_region'}), 'max_size': ('FLOAT', {'default': 1024, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'mask_mode': ('BOOLEAN', {'default': True, 'label_on': 'masked only', 'label_off': 'whole'}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), '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.5, 'min': 0.0001, 'max': 1.0, 'step': 0.01}), 'feather': ('INT', {'default': 5, 'min': 0, 'max': 100, 'step': 1}), 'crop_factor': ('FLOAT', {'default': 3.0, 'min': 1.0, 'max': 10, 'step': 0.1}), 'drop_size': ('INT', {'min': 1, 'max': MAX_RESOLUTION, 'step': 1, 'default': 10}), 'refiner_ratio': ('FLOAT', {'default': 0.2, 'min': 0.0, 'max': 1.0}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 100}), 'cycle': ('INT', {'default': 1, 'min': 1, 'max': 10, 'step': 1})}, 'optional': {'optional_image': ('IMAGE',), 'inpaint_model': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'}), 'noise_mask_feather': ('INT', {'default': 20, 'min': 0, 'max': 100, 'step': 1})}}
    RETURN_TYPES = ('PIPE_LINE',)
    RETURN_NAMES = ('pipe',)
    OUTPUT_IS_LIST = (False,)
    FUNCTION = 'doit'
    CATEGORY = 'EasyUse/Fix'

    def doit(self, pipe, mask, guide_size, guide_size_for, max_size, mask_mode, seed, steps, cfg, sampler_name, scheduler, denoise, feather, crop_factor, drop_size, refiner_ratio, batch_size, cycle, optional_image=None, inpaint_model=False, noise_mask_feather=20):
        model = pipe['model'] if 'model' in pipe else None
        if model is None:
            raise Exception(f"[ERROR] pipe['model'] is missing")
        clip = pipe['clip'] if 'clip' in pipe else None
        if clip is None:
            raise Exception(f"[ERROR] pipe['clip'] is missing")
        vae = pipe['vae'] if 'vae' in pipe else None
        if vae is None:
            raise Exception(f"[ERROR] pipe['vae'] is missing")
        if optional_image is not None:
            images = optional_image
        else:
            images = pipe['images'] if 'images' in pipe else None
            if images is None:
                raise Exception(f"[ERROR] pipe['image'] is missing")
        positive = pipe['positive'] if 'positive' in pipe else None
        if positive is None:
            raise Exception(f"[ERROR] pipe['positive'] is missing")
        negative = pipe['negative'] if 'negative' in pipe else None
        if negative is None:
            raise Exception(f"[ERROR] pipe['negative'] is missing")
        latent = pipe['samples'] if 'samples' in pipe else None
        if latent is None:
            raise Exception(f"[ERROR] pipe['samples'] is missing")
        if 'noise_mask' not in latent:
            if images is None:
                raise Exception('No Images found')
            if vae is None:
                raise Exception('No VAE found')
            x = images.shape[1] // 8 * 8
            y = images.shape[2] // 8 * 8
            mask = torch.nn.functional.interpolate(mask.reshape((-1, 1, mask.shape[-2], mask.shape[-1])), size=(images.shape[1], images.shape[2]), mode='bilinear')
            pixels = images.clone()
            if pixels.shape[1] != x or pixels.shape[2] != y:
                x_offset = pixels.shape[1] % 8 // 2
                y_offset = pixels.shape[2] % 8 // 2
                pixels = pixels[:, x_offset:x + x_offset, y_offset:y + y_offset, :]
                mask = mask[:, :, x_offset:x + x_offset, y_offset:y + y_offset]
            mask_erosion = mask
            m = (1.0 - mask.round()).squeeze(1)
            for i in range(3):
                pixels[:, :, :, i] -= 0.5
                pixels[:, :, :, i] *= m
                pixels[:, :, :, i] += 0.5
            t = vae.encode(pixels)
            latent = {'samples': t, 'noise_mask': mask_erosion[:, :, :x, :y].round()}
        loader_settings = pipe['loader_settings'] if 'loader_settings' in pipe else {}
        new_pipe = {'images': images, 'model': model, 'clip': clip, 'vae': vae, 'positive': positive, 'negative': negative, 'seed': seed, 'mask': mask, 'loader_settings': loader_settings, 'detail_fix_settings': {'guide_size': guide_size, 'guide_size_for': guide_size_for, 'max_size': max_size, 'seed': seed, 'steps': steps, 'cfg': cfg, 'sampler_name': sampler_name, 'scheduler': scheduler, 'denoise': denoise, 'feather': feather, 'crop_factor': crop_factor, 'drop_size': drop_size, 'refiner_ratio': refiner_ratio, 'batch_size': batch_size, 'cycle': cycle}, 'mask_settings': {'mask_mode': mask_mode, 'inpaint_model': inpaint_model, 'noise_mask_feather': noise_mask_feather}}
        del pipe
        return (new_pipe,)