# Documentation - Class name: GrowMaskWithBlur - Category: KJNodes/masking - Output node: False - Repo Ref: https://github.com/comfyanonymous/ComfyUI GrowMaskWithBlur节点用于处理单个或批量掩码。它可以扩大或缩小掩码,可选择性地应用模糊效果,并执行各种其他变换,如翻转、填充孔洞和帧间插值。这个节点在掩码处理方面非常灵活,允许对掩码数据进行动态调整和增强。 # Input types ## Required - mask - 要处理的输入掩码或掩码批次。它是所有变换的主要数据来源。 - Comfy dtype: MASK - Python dtype: torch.Tensor - expand - 决定掩码将被扩展或收缩的程度。正值扩展掩码,负值收缩掩码。 - Comfy dtype: INT - Python dtype: int - incremental_expandrate - 指定每帧调整expand参数的比率,允许在一系列掩码上进行动态调整大小。 - Comfy dtype: FLOAT - Python dtype: float - tapered_corners - 启用时,在扩展或收缩过程中对掩码应用渐变角,影响处理后掩码的形状。 - Comfy dtype: BOOLEAN - Python dtype: bool - flip_input - 如果设置为true,在进行任何其他处理之前水平翻转输入掩码。 - Comfy dtype: BOOLEAN - Python dtype: bool - blur_radius - 使用指定半径对掩码应用模糊效果。大于0的值会激活此效果。 - Comfy dtype: FLOAT - Python dtype: float - lerp_alpha - 用于帧间线性插值的alpha值,实现动画掩码序列中的平滑过渡。 - Comfy dtype: FLOAT - Python dtype: float - decay_factor - 在帧之间应用于掩码的衰减因子,允许特征逐渐淡化或增强。 - Comfy dtype: FLOAT - Python dtype: float ## Optional - fill_holes - 启用时,填充掩码中的任何孔洞,这对创建更实心或连贯的掩码形状特别有用。 - Comfy dtype: BOOLEAN - Python dtype: bool # Output types - mask - 应用指定变换后的主要输出掩码。 - Comfy dtype: MASK - Python dtype: torch.Tensor - mask_inverted - 主要输出掩码的反转版本,提供另一种可视化或应用方式。 - Comfy dtype: MASK - Python dtype: torch.Tensor ## Usage tips - Infra type: `CPU` - Common nodes: unknown ## Source code ```python class GrowMaskWithBlur: @classmethod def INPUT_TYPES(cls): return { "required": { "mask": ("MASK",), "expand": ("INT", {"default": 0, "min": -MAX_RESOLUTION, "max": MAX_RESOLUTION, "step": 1}), "incremental_expandrate": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 100.0, "step": 0.1}), "tapered_corners": ("BOOLEAN", {"default": True}), "flip_input": ("BOOLEAN", {"default": False}), "blur_radius": ("FLOAT", { "default": 0.0, "min": 0.0, "max": 100, "step": 0.1 }), "lerp_alpha": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), "decay_factor": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), }, "optional": { "fill_holes": ("BOOLEAN", {"default": False}), }, } CATEGORY = "KJNodes/masking" RETURN_TYPES = ("MASK", "MASK",) RETURN_NAMES = ("mask", "mask_inverted",) FUNCTION = "expand_mask" DESCRIPTION = """ # GrowMaskWithBlur - mask: Input mask or mask batch - expand: Expand or contract mask or mask batch by a given amount - incremental_expandrate: increase expand rate by a given amount per frame - tapered_corners: use tapered corners - flip_input: flip input mask - blur_radius: value higher than 0 will blur the mask - lerp_alpha: alpha value for interpolation between frames - decay_factor: decay value for interpolation between frames - fill_holes: fill holes in the mask (slow)""" def expand_mask(self, mask, expand, tapered_corners, flip_input, blur_radius, incremental_expandrate, lerp_alpha, decay_factor, fill_holes=False): alpha = lerp_alpha decay = decay_factor if flip_input: mask = 1.0 - mask c = 0 if tapered_corners else 1 kernel = np.array([[c, 1, c], [1, 1, 1], [c, 1, c]]) growmask = mask.reshape((-1, mask.shape[-2], mask.shape[-1])).cpu() out = [] previous_output = None current_expand = expand for m in growmask: output = m.numpy() for _ in range(abs(round(current_expand))): if current_expand < 0: output = scipy.ndimage.grey_erosion(output, footprint=kernel) else: output = scipy.ndimage.grey_dilation(output, footprint=kernel) if current_expand < 0: current_expand -= abs(incremental_expandrate) else: current_expand += abs(incremental_expandrate) if fill_holes: binary_mask = output > 0 output = scipy.ndimage.binary_fill_holes(binary_mask) output = output.astype(np.float32) * 255 output = torch.from_numpy(output) if alpha < 1.0 and previous_output is not None: # Interpolate between the previous and current frame output = alpha * output + (1 - alpha) * previous_output if decay < 1.0 and previous_output is not None: # Add the decayed previous output to the current frame output += decay * previous_output output = output / output.max() previous_output = output out.append(output) if blur_radius != 0: # Convert the tensor list to PIL images, apply blur, and convert back for idx, tensor in enumerate(out): # Convert tensor to PIL image pil_image = tensor2pil(tensor.cpu().detach())[0] # Apply Gaussian blur pil_image = pil_image.filter(ImageFilter.GaussianBlur(blur_radius)) # Convert back to tensor out[idx] = pil2tensor(pil_image) blurred = torch.cat(out, dim=0) return (blurred, 1.0 - blurred) else: return (torch.stack(out, dim=0), 1.0 - torch.stack(out, dim=0),) ```