diff --git a/docs/3DImage.md b/docs/3DImage.md new file mode 100644 index 0000000..56804b9 --- /dev/null +++ b/docs/3DImage.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: Image3D +- Category: ♾️Mixlab/Image +- Output node: True +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +Image3D节点旨在处理和操作3D图像。它接受一个base64编码的图像和可选的材料作为输入,将它们转换为适合深度学习模型进一步处理的张量形式。该节点还处理掩码和背景图像的提取,提供一套全面的图像操作功能。 + +# Input types +## Required +- upload + - ‘upload’参数对于节点至关重要,因为它包含base64编码的图像数据和可选的材料进行处理。它对节点的执行至关重要,因为它提供了图像操作的主要输入。 + - Comfy dtype: Dict[str, str] + - Python dtype: Dict[str, Union[str, torch.Tensor]] +- material + - ‘material’参数是可选的,允许包含可以用于增强主要图像处理过程的额外图像数据。它通过启用补充视觉元素的使用,增加了节点功能的灵活性。 + - Comfy dtype: IMAGE + - Python dtype: Optional[torch.Tensor] + +# Output types +- IMAGE + - ‘IMAGE’输出代表以张量形式处理的3D图像,可用于机器学习或计算机视觉应用等下游任务。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- MASK + - ‘MASK’输出提供了从输入图像派生的二进制掩码,可用于分割或其他图像分析任务。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- BG_IMAGE + - ‘BG_IMAGE’输出是可选的背景图像,它补充了主要图像,为某些应用增强了上下文。 + - Comfy dtype: IMAGE + - Python dtype: Optional[torch.Tensor] +- MATERIAL + - ‘MATERIAL’输出是处理过的材料图像,可以与主要图像一起用于更复杂的图像处理任务。 + - Comfy dtype: IMAGE + - Python dtype: Optional[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Image3D: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'upload': ('THREED',)}, 'optional': {'material': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE', 'MASK', 'IMAGE', 'IMAGE') + RETURN_NAMES = ('IMAGE', 'MASK', 'BG_IMAGE', 'MATERIAL') + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Image' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False, False, False, False) + OUTPUT_NODE = True + + def run(self, upload, material=None): + image = base64_to_image(upload['image']) + mat = None + if 'material' in upload and upload['material']: + mat = base64_to_image(upload['material']) + mat = mat.convert('RGB') + mat = pil2tensor(mat) + mask = image.split()[3] + image = image.convert('RGB') + mask = mask.convert('L') + bg_image = None + if 'bg_image' in upload and upload['bg_image']: + bg_image = base64_to_image(upload['bg_image']) + bg_image = bg_image.convert('RGB') + bg_image = pil2tensor(bg_image) + mask = pil2tensor(mask) + image = pil2tensor(image) + m = [] + if not material is None: + m = create_temp_file(material[0]) + return {'ui': {'material': m}, 'result': (image, mask, bg_image, mat)} +``` \ No newline at end of file diff --git a/docs/ACN_AdvancedControlNetApply.md b/docs/ACN_AdvancedControlNetApply.md new file mode 100644 index 0000000..27e2ee8 --- /dev/null +++ b/docs/ACN_AdvancedControlNetApply.md @@ -0,0 +1,133 @@ +# Documentation +- Class name: AdvancedControlNetApply +- Category: Adv-ControlNet 🛂🅐🅒🅝 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +AdvancedControlNetApply节点旨在将控制信号应用于神经网络模型。它整合了正向和负向的调节输入以及控制网络,以影响模型的输出。该节点能够调整控制信号的强度和范围,确保对模型行为进行精细和精确的操控。 + +# Input types +## Required +- positive + - 正向调节输入对于引导模型朝向期望的结果至关重要。它作为模型在生成过程中学习和应用的参考。 + - Comfy dtype: CONDITIONING + - Python dtype: Union[Tensor, Iterable[Tuple[str, Dict]]] +- negative + - 负向调节输入通过在生成过程中提供应排除的示例,帮助模型避免不希望的输出。 + - Comfy dtype: CONDITIONING + - Python dtype: Union[Tensor, Iterable[Tuple[str, Dict]]] +- control_net + - 控制网络是一个关键组件,它决定了模型的输出如何被影响。它用于将特定的控制信号应用于模型的不同部分。 + - Comfy dtype: CONTROL_NET + - Python dtype: ControlBase +- image + - 图像输入为模型提供视觉上下文,这对于生成与提供的视觉信息一致的输出至关重要。 + - Comfy dtype: IMAGE + - Python dtype: Tensor +- strength + - 强度参数决定了施加在模型上的控制信号的强度。它允许微调控制网络对模型输出的影响。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_percent + - 开始百分比参数定义了控制信号影响的开始点,允许控制控制效果开始生效的时间。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_percent + - 结束百分比参数标记了控制信号影响的结束点,使控制效果的持续时间可控。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- mask_optional + - 可选的掩码输入可以用来选择性地将控制信号应用于模型输出的特定区域,提供了一种微调局部控制效果的手段。 + - Comfy dtype: MASK + - Python dtype: Optional[Tensor] +- model_optional + - model_optional参数允许提供另一个模型,该模型可以用来进一步细化应用于主模型的控制信号。 + - Comfy dtype: MODEL + - Python dtype: Optional[ModelPatcher] +- timestep_kf + - 时间步关键帧输入用于定义控制信号的时间结构,允许随时间动态控制。 + - Comfy dtype: TIMESTEP_KEYFRAME + - Python dtype: Optional[TimestepKeyframeGroup] +- latent_kf_override + - 潜在关键帧覆盖允许定制控制信号对模型潜在空间的影响,提供了一种直接影响模型内部表示的方法。 + - Comfy dtype: LATENT_KEYFRAME + - Python dtype: Optional[LatentKeyframeGroup] +- weights_override + - 权重覆盖参数允许指定控制网络的自定义权重,允许对控制信号的微调进行更高级别的控制。 + - Comfy dtype: CONTROL_NET_WEIGHTS + - Python dtype: Optional[ControlWeights] + +# Output types +- positive + - 正向输出代表了应用控制网络后的修改后的调节输入,反映了模型对期望结果的理解。 + - Comfy dtype: CONDITIONING + - Python dtype: Union[Tensor, Iterable[Tuple[str, Dict]]] +- negative + - 负向输出包括基于控制网络的影响,模型应该避免的修改后的调节输入。 + - Comfy dtype: CONDITIONING + - Python dtype: Union[Tensor, Iterable[Tuple[str, Dict]]] +- model_opt + - 可选的模型输出在应用控制网络期间提供了模型的任何更新或改进。 + - Comfy dtype: MODEL + - Python dtype: Optional[ModelPatcher] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class AdvancedControlNetApply: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'control_net': ('CONTROL_NET',), 'image': ('IMAGE',), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_percent': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001})}, 'optional': {'mask_optional': ('MASK',), 'timestep_kf': ('TIMESTEP_KEYFRAME',), 'latent_kf_override': ('LATENT_KEYFRAME',), 'weights_override': ('CONTROL_NET_WEIGHTS',), 'model_optional': ('MODEL',)}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING', 'MODEL') + RETURN_NAMES = ('positive', 'negative', 'model_opt') + FUNCTION = 'apply_controlnet' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝' + + def apply_controlnet(self, positive, negative, control_net, image, strength, start_percent, end_percent, mask_optional: Tensor=None, model_optional: ModelPatcher=None, timestep_kf: TimestepKeyframeGroup=None, latent_kf_override: LatentKeyframeGroup=None, weights_override: ControlWeights=None): + if strength == 0: + return (positive, negative, model_optional) + if model_optional: + model_optional = model_optional.clone() + control_hint = image.movedim(-1, 1) + cnets = {} + out = [] + for conditioning in [positive, negative]: + c = [] + for t in conditioning: + d = t[1].copy() + prev_cnet = d.get('control', None) + if prev_cnet in cnets: + c_net = cnets[prev_cnet] + else: + c_net = convert_to_advanced(control_net.copy()).set_cond_hint(control_hint, strength, (start_percent, end_percent)) + if is_advanced_controlnet(c_net): + c_net.disarm() + if c_net.require_model: + if not model_optional: + raise Exception(f"Type '{type(c_net).__name__}' requires model_optional input, but got None.") + c_net.patch_model(model=model_optional) + if timestep_kf is not None: + c_net.set_timestep_keyframes(timestep_kf) + if latent_kf_override is not None: + c_net.latent_keyframe_override = latent_kf_override + if weights_override is not None: + c_net.weights_override = weights_override + c_net.verify_all_weights() + if mask_optional is not None: + mask_optional = mask_optional.clone() + if len(mask_optional.shape) < 3: + mask_optional = mask_optional.unsqueeze(0) + c_net.set_cond_hint_mask(mask_optional) + c_net.set_previous_controlnet(prev_cnet) + cnets[prev_cnet] = c_net + d['control'] = c_net + d['control_apply_to_uncond'] = False + n = [t[0], d] + c.append(n) + out.append(c) + return (out[0], out[1], model_optional) +``` \ No newline at end of file diff --git a/docs/ACN_DefaultUniversalWeights.md b/docs/ACN_DefaultUniversalWeights.md new file mode 100644 index 0000000..eb83baf --- /dev/null +++ b/docs/ACN_DefaultUniversalWeights.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: DefaultWeights +- Category: Adv-ControlNet 🛂🅐🅒🅝/weights +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +DefaultWeights节点的'load_weights'方法旨在初始化并返回一组默认的控制权重和相应的时间步关键帧组。它是构建控制网络的基础组件,确保系统有一个操作的基线权重集。 + +# Input types + +# Output types +- CONTROL_NET_WEIGHTS + - CONTROL_NET_WEIGHTS输出参数代表网络的默认控制权重。它是塑造控制网络行为的关键元素,因为它定义了后续计算和调整中将使用初始权重。 + - Comfy dtype: ControlWeights + - Python dtype: ControlWeights +- TIMESTEP_KEYFRAME + - TIMESTEP_KEYFRAME输出参数封装了与控制权重相关联的关键帧组。它在控制网络的时间动态中起着重要作用,提供了一种结构化的方式来管理和随时间应用权重。 + - Comfy dtype: TimestepKeyframeGroup + - Python dtype: TimestepKeyframeGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DefaultWeights: + + @classmethod + def INPUT_TYPES(s): + return {} + RETURN_TYPES = ('CONTROL_NET_WEIGHTS', 'TIMESTEP_KEYFRAME') + RETURN_NAMES = WEIGHTS_RETURN_NAMES + FUNCTION = 'load_weights' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/weights' + + def load_weights(self): + weights = ControlWeights.default() + return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights))) +``` \ No newline at end of file diff --git a/docs/ACN_ReferenceControlNet.md b/docs/ACN_ReferenceControlNet.md new file mode 100644 index 0000000..988d9c9 --- /dev/null +++ b/docs/ACN_ReferenceControlNet.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: ReferenceControlNetNode +- Category: Adv-ControlNet 🛂🅐🅒🅝/Reference +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +ReferenceControlNetNode 类旨在管理控制网络的加载和应用,并带有参考选项。它封装了创建高级控制结构的逻辑,这些结构可用于引导生成模型的行为,基于用户定义的参考类型和风格保真度提供了一个灵活的接口来控制生成过程。 + +# Input types +## Required +- reference_type + - 参考类型参数决定了要使用的控制网络类型,这对生成输出的风格和行为有显著影响。它对定义控制机制的方法及其对最终结果的影响至关重要。 + - Comfy dtype: str + - Python dtype: str +- style_fidelity + - 风格保真度参数调整对参考风格的遵循程度,影响输出的风格一致性。它在平衡创造性输出与所需的风格控制水平方面发挥着重要作用。 + - Comfy dtype: float + - Python dtype: float +- ref_weight + - ref_weight 参数设置控制网络中参考的权重,直接影响应用控制的强度。对于微调控制对生成过程的影响至关重要。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- CONTROL_NET + - ReferenceControlNetNode 的输出是一个控制网络对象,它封装了高级控制逻辑。它对于通过应用指定的控制参数将生成模型引导到期望的结果具有重要意义。 + - Comfy dtype: ControlBase + - Python dtype: comfy.controlnet.ControlBase + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ReferenceControlNetNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'reference_type': (ReferenceType._LIST,), 'style_fidelity': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'ref_weight': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('CONTROL_NET',) + FUNCTION = 'load_controlnet' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/Reference' + + def load_controlnet(self, reference_type: str, style_fidelity: float, ref_weight: float): + ref_opts = ReferenceOptions.create_combo(reference_type=reference_type, style_fidelity=style_fidelity, ref_weight=ref_weight) + controlnet = ReferenceAdvanced(ref_opts=ref_opts, timestep_keyframes=None) + return (controlnet,) +``` \ No newline at end of file diff --git a/docs/ACN_ReferenceControlNetFinetune.md b/docs/ACN_ReferenceControlNetFinetune.md new file mode 100644 index 0000000..1163070 --- /dev/null +++ b/docs/ACN_ReferenceControlNetFinetune.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: ReferenceControlFinetune +- Category: Adv-ControlNet 🛂🅐🅒🅝/Reference +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +ReferenceControlFinetune 是一个用于高级图像处理任务的控制网络微调节点。它利用注意力和自适应实例归一化机制,在风格迁移和内容适应中实现高保真度。该节点在增强生成过程的控制中起着关键作用,允许对最终输出进行精细调整。 + +# Input types +## Required +- attn_style_fidelity + - attn_style_fidelity 参数控制应用风格转换时注意力机制的保真度。它对于平衡风格化效果和保留内容细节至关重要,从而影响整体的美学结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_ref_weight + - attn_ref_weight 参数确定注意力机制中参考的权重,影响风格转换受参考内容指导的程度。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_strength + - attn_strength 参数调整注意力机制对风格化过程的影响强度,允许控制应用风格的强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- adain_style_fidelity + - adain_style_fidelity 参数在应用风格时决定自适应实例归一化保真度级别,这对于在应用风格的同时保持原始图像特征的完整性至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- adain_ref_weight + - adain_ref_weight 参数设置自适应实例归一化中的参考权重,影响参考风格应用于图像的强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- adain_strength + - adain_strength 参数定义自适应实例归一化效果的总体强度,允许微调风格如何融入图像。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- control_net + - ReferenceControlFinetune 节点的输出是一个控制网络,它封装了微调后的参数和机制,用于高级风格控制和操作。它是后续图像生成任务的关键组件。 + - Comfy dtype: CONTROL_NET + - Python dtype: comfy.controlnet.ControlBase + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ReferenceControlFinetune: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'attn_style_fidelity': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'attn_ref_weight': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'attn_strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'adain_style_fidelity': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'adain_ref_weight': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'adain_strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('CONTROL_NET',) + FUNCTION = 'load_controlnet' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/Reference' + + def load_controlnet(self, attn_style_fidelity: float, attn_ref_weight: float, attn_strength: float, adain_style_fidelity: float, adain_ref_weight: float, adain_strength: float): + ref_opts = ReferenceOptions(reference_type=ReferenceType.ATTN_ADAIN, attn_style_fidelity=attn_style_fidelity, attn_ref_weight=attn_ref_weight, attn_strength=attn_strength, adain_style_fidelity=adain_style_fidelity, adain_ref_weight=adain_ref_weight, adain_strength=adain_strength) + controlnet = ReferenceAdvanced(ref_opts=ref_opts, timestep_keyframes=None) + return (controlnet,) +``` \ No newline at end of file diff --git a/docs/ACN_ReferencePreprocessor.md b/docs/ACN_ReferencePreprocessor.md new file mode 100644 index 0000000..0e2d15c --- /dev/null +++ b/docs/ACN_ReferencePreprocessor.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: ReferencePreprocessorNode +- Category: Adv-ControlNet 🛂🅐🅒🅝/Reference/preprocess +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +ReferencePreprocessorNode 旨在使用变分自编码器(VAE)将输入图像转换为潜在空间表示。它在为高级控制网络操作准备图像方面发挥着关键作用,通过将视觉内容编码为可以由下游节点进一步处理的格式。 + +# Input types +## Required +- image + - 图像参数对于节点的操作至关重要,因为它是需要被预处理的原始视觉输入。它是节点将转换为潜在表示的主要数据。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- vae + - VAE 参数指定了节点将用于将图像编码为潜在空间的变分自编码器模型。这个模型是节点功能的核心,因为它定义了图像如何被转换。 + - Comfy dtype: VAE + - Python dtype: comfy.sd.VAE +- latent_size + - latent_size 参数定义了图像将被编码的潜在空间的维度。它是一个关键组件,因为它决定了编码表示的规模和结构。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, Any] + +# Output types +- proc_IMAGE + - proc_IMAGE 输出是以潜在表示形式处理后的图像。它很重要,因为它作为控制网络中后续节点的输入,使得可以进行更高级的处理。 + - Comfy dtype: IMAGE + - Python dtype: comfy.utils.ReferencePreprocWrapper + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ReferencePreprocessorNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'vae': ('VAE',), 'latent_size': ('LATENT',)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('proc_IMAGE',) + FUNCTION = 'preprocess_images' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/Reference/preprocess' + + def preprocess_images(self, vae: VAE, image: Tensor, latent_size: Tensor): + image = image.movedim(-1, 1) + image = comfy.utils.common_upscale(image, latent_size['samples'].shape[3] * 8, latent_size['samples'].shape[2] * 8, 'nearest-exact', 'center') + image = image.movedim(1, -1) + try: + image = vae.vae_encode_crop_pixels(image) + except Exception: + image = VAEEncode.vae_encode_crop_pixels(image) + encoded = vae.encode(image[:, :, :, :3]) + return (ReferencePreprocWrapper(condhint=encoded),) +``` \ No newline at end of file diff --git a/docs/ACN_SparseCtrlIndexMethodNode.md b/docs/ACN_SparseCtrlIndexMethodNode.md new file mode 100644 index 0000000..2decc91 --- /dev/null +++ b/docs/ACN_SparseCtrlIndexMethodNode.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: SparseIndexMethodNode +- Category: Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +该节点用于通过提供一系列唯一的索引来检索稀疏控制网络的方法。它确保索引是有效的整数,并用于引用更大数据集或结构中的特定元素。 + +# Input types +## Required +- indexes + - “indexes”参数是一个由逗号分隔的整数字符串,用于唯一标识数据集中的元素。它对节点的操作至关重要,因为它直接影响到哪些元素被选中进行处理。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- method + - 输出的'method'是SparseIndexMethod的一个实例,根据提供的索引定制。它代表了SparseIndexMethodNode的核心功能,使得在稀疏控制网络中选择和处理特定元素成为可能。 + - Comfy dtype: SPARSE_METHOD + - Python dtype: SparseIndexMethod + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SparseIndexMethodNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'indexes': ('STRING', {'default': '0'})}} + RETURN_TYPES = ('SPARSE_METHOD',) + FUNCTION = 'get_method' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl' + + def get_method(self, indexes: str): + idxs = [] + unique_idxs = set() + str_idxs = [x.strip() for x in indexes.strip().split(',')] + for str_idx in str_idxs: + try: + idx = int(str_idx) + if idx in unique_idxs: + raise ValueError(f"'{idx}' is duplicated; indexes must be unique.") + idxs.append(idx) + unique_idxs.add(idx) + except ValueError: + raise ValueError(f"'{str_idx}' is not a valid integer index.") + if len(idxs) == 0: + raise ValueError(f'No indexes were listed in Sparse Index Method.') + return (SparseIndexMethod(idxs),) +``` \ No newline at end of file diff --git a/docs/ACN_SparseCtrlLoaderAdvanced.md b/docs/ACN_SparseCtrlLoaderAdvanced.md new file mode 100644 index 0000000..32b9cf8 --- /dev/null +++ b/docs/ACN_SparseCtrlLoaderAdvanced.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: SparseCtrlLoaderAdvanced +- Category: Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +SparseCtrlLoaderAdvanced节点旨在高效地加载和管理具有稀疏控制能力的高级控制网络。它抽象了处理稀疏控制数据的复杂性,使用户能够将运动特性无缝集成到他们的控制网络中。该节点简化了使用稀疏控制方法加载控制网络的过程,增强了系统的总体性能和功能。 + +# Input types +## Required +- sparsectrl_name + - sparsectrl_name参数对于识别要加载的特定控制网络至关重要。它通过确定访问和处理哪个控制网络的数据来影响节点的执行。 + - Comfy dtype: str + - Python dtype: str +## Optional +- use_motion + - use_motion参数决定是否将运动特性纳入控制网络。它在节点的功能中起着重要作用,通过启用或禁用控制网络的运动方面。 + - Comfy dtype: bool + - Python dtype: bool +- motion_strength + - motion_strength参数调整控制网络内运动特性的强度。它对于微调运动对控制网络最终输出的影响很重要。 + - Comfy dtype: float + - Python dtype: float +- motion_scale + - motion_scale参数调整控制网络中运动效应的大小。它对于控制运动对网络行为的影响程度至关重要。 + - Comfy dtype: float + - Python dtype: float +- sparse_method + - sparse_method参数定义了在控制网络内处理稀疏控制数据的方法。它对于确定处理和整合稀疏数据的策略至关重要。 + - Comfy dtype: SparseMethod + - Python dtype: SparseMethod +- tk_optional + - tk_optional参数提供了一种为控制网络指定可选时间步关键帧的方法。对于需要自定义控制网络时间方面特性的用户来说,这很重要。 + - Comfy dtype: TimestepKeyframeGroup + - Python dtype: TimestepKeyframeGroup + +# Output types +- CONTROL_NET + - CONTROL_NET输出代表了加载的高级控制网络,它结合了指定的稀疏控制设置和运动特性。它很重要,因为它是节点的主要输出,使得在系统中可以进行进一步的处理和利用。 + - Comfy dtype: ControlNetAdvanced + - Python dtype: ControlNetAdvanced + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SparseCtrlLoaderAdvanced: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'sparsectrl_name': (folder_paths.get_filename_list('controlnet'),), 'use_motion': ('BOOLEAN', {'default': True}), 'motion_strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'motion_scale': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001})}, 'optional': {'sparse_method': ('SPARSE_METHOD',), 'tk_optional': ('TIMESTEP_KEYFRAME',)}} + RETURN_TYPES = ('CONTROL_NET',) + FUNCTION = 'load_controlnet' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl' + + def load_controlnet(self, sparsectrl_name: str, use_motion: bool, motion_strength: float, motion_scale: float, sparse_method: SparseMethod=SparseSpreadMethod(), tk_optional: TimestepKeyframeGroup=None): + sparsectrl_path = folder_paths.get_full_path('controlnet', sparsectrl_name) + sparse_settings = SparseSettings(sparse_method=sparse_method, use_motion=use_motion, motion_strength=motion_strength, motion_scale=motion_scale) + sparsectrl = load_sparsectrl(sparsectrl_path, timestep_keyframe=tk_optional, sparse_settings=sparse_settings) + return (sparsectrl,) +``` \ No newline at end of file diff --git a/docs/ACN_SparseCtrlMergedLoaderAdvanced.md b/docs/ACN_SparseCtrlMergedLoaderAdvanced.md new file mode 100644 index 0000000..843e24d --- /dev/null +++ b/docs/ACN_SparseCtrlMergedLoaderAdvanced.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: SparseCtrlMergedLoaderAdvanced +- Category: Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl/experimental +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +SparseCtrlMergedLoaderAdvanced 节点旨在高效管理和加载具有稀疏控制特性的高级控制网络。它将运动特性集成到控制网络中,允许基于运动强度和规模参数进行动态和自适应控制。此节点对于需要对复杂系统进行精细控制的应用至关重要,确保了运动和控制的无缝融合,以提高性能。 + +# Input types +## Required +- sparsectrl_name + - 参数 'sparsectrl_name' 指定要加载的稀疏控制模型的名称,这对于识别和访问正确的控制设置至关重要。此参数对节点的操作至关重要,因为它直接影响应用的控制能力。 + - Comfy dtype: str + - Python dtype: str +- control_net_name + - 参数 'control_net_name' 用于定义控制网络模型的名称。它在节点的功能中扮演重要角色,因为它决定了要使用的特定控制网络,影响整体的控制策略。 + - Comfy dtype: str + - Python dtype: str +- use_motion + - 参数 'use_motion' 指示是否应将运动特性纳入控制网络。这是一个重要参数,因为它启用或禁用了基于运动的控制的动态适应,导致不同的控制行为。 + - Comfy dtype: bool + - Python dtype: bool +- motion_strength + - 参数 'motion_strength' 调整控制网络内运动效果的强度。这是一个关键参数,允许用户微调运动对控制结果的影响,从而定制控制响应。 + - Comfy dtype: float + - Python dtype: float +- motion_scale + - 参数 'motion_scale' 定义应用于控制网络的运动效果的规模。它是一个有影响力的参数,修改了运动整合的范围,影响了整体控制动态。 + - Comfy dtype: float + - Python dtype: float +## Optional +- sparse_method + - 参数 'sparse_method' 选择控制网络内处理稀疏数据的方法。虽然它是可选的,但它可以显著影响稀疏数据的处理方式,可能改变节点的性能。 + - Comfy dtype: SPARSE_METHOD + - Python dtype: SparseMethod +- tk_optional + - 提供的 'tk_optional' 参数可以提供控制网络中时间步关键帧的额外控制。这个可选参数可以用来指定特定的关键帧,以实现更细粒度的控制。 + - Comfy dtype: TIMESTEP_KEYFRAME + - Python dtype: TimestepKeyframeGroup + +# Output types +- CONTROL_NET + - 输出 'CONTROL_NET' 表示已加载的具有集成运动特性的控制网络。它是一个复杂的数据结构,封装了控制设置和运动参数,准备在更高级别的控制系统中应用。 + - Comfy dtype: CONTROL_NET + - Python dtype: ControlNetAdvanced + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SparseCtrlMergedLoaderAdvanced: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'sparsectrl_name': (folder_paths.get_filename_list('controlnet'),), 'control_net_name': (folder_paths.get_filename_list('controlnet'),), 'use_motion': ('BOOLEAN', {'default': True}), 'motion_strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'motion_scale': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001})}, 'optional': {'sparse_method': ('SPARSE_METHOD',), 'tk_optional': ('TIMESTEP_KEYFRAME',)}} + RETURN_TYPES = ('CONTROL_NET',) + FUNCTION = 'load_controlnet' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl/experimental' + + def load_controlnet(self, sparsectrl_name: str, control_net_name: str, use_motion: bool, motion_strength: float, motion_scale: float, sparse_method: SparseMethod=SparseSpreadMethod(), tk_optional: TimestepKeyframeGroup=None): + sparsectrl_path = folder_paths.get_full_path('controlnet', sparsectrl_name) + controlnet_path = folder_paths.get_full_path('controlnet', control_net_name) + sparse_settings = SparseSettings(sparse_method=sparse_method, use_motion=use_motion, motion_strength=motion_strength, motion_scale=motion_scale, merged=True) + controlnet = load_controlnet(controlnet_path, timestep_keyframe=tk_optional) + if controlnet is None or type(controlnet) != ControlNetAdvanced: + raise ValueError(f'controlnet_path must point to a normal ControlNet, but instead: {type(controlnet).__name__}') + sparsectrl = load_sparsectrl(sparsectrl_path, timestep_keyframe=tk_optional, sparse_settings=SparseSettings.default()) + new_state_dict = controlnet.control_model.state_dict() + for (key, value) in sparsectrl.control_model.motion_holder.motion_wrapper.state_dict().items(): + new_state_dict[key] = value + sparsectrl = load_sparsectrl(sparsectrl_path, controlnet_data=new_state_dict, timestep_keyframe=tk_optional, sparse_settings=sparse_settings) + return (sparsectrl,) +``` \ No newline at end of file diff --git a/docs/ACN_SparseCtrlRGBPreprocessor.md b/docs/ACN_SparseCtrlRGBPreprocessor.md new file mode 100644 index 0000000..f64fdf8 --- /dev/null +++ b/docs/ACN_SparseCtrlRGBPreprocessor.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: RgbSparseCtrlPreprocessor +- Category: Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl/preprocess +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +RgbSparseCtrlPreprocessor节点旨在为涉及稀疏控制机制的高级控制网络处理准备图像数据。它将输入图像放大以匹配潜在大小,将图像编码为潜在空间表示,并以特定于下游控制网络应用的预处理格式包装编码数据。 + +# Input types +## Required +- image + - 图像参数对于预处理阶段至关重要,因为它代表了将被放大和编码的原始输入。它是影响节点输出和控制网络中后续处理的基本元素。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- vae + - vae参数指定了变分自编码器(VAE)模型,该模型将用于将图像编码为潜在表示。这个模型对于节点将输入图像转换为适合高级控制网络操作的格式至关重要。 + - Comfy dtype: VAE + - Python dtype: comfy.sd.VAE +- latent_size + - latent_size参数定义了图像将被编码的潜在空间的维度。它是节点输出质量的关键决定因素,以及编码数据在控制网络框架内的后续适用性。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Output types +- proc_IMAGE + - proc_IMAGE输出是输入图像的预处理版本,编码为潜在空间表示。此输出专门设计为与高级控制网络节点兼容,不打算用于其他类型的图像输入。 + - Comfy dtype: IMAGE + - Python dtype: PreprocSparseRGBWrapper + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RgbSparseCtrlPreprocessor: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'vae': ('VAE',), 'latent_size': ('LATENT',)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('proc_IMAGE',) + FUNCTION = 'preprocess_images' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl/preprocess' + + def preprocess_images(self, vae: VAE, image: Tensor, latent_size: Tensor): + image = image.movedim(-1, 1) + image = comfy.utils.common_upscale(image, latent_size['samples'].shape[3] * 8, latent_size['samples'].shape[2] * 8, 'nearest-exact', 'center') + image = image.movedim(1, -1) + try: + image = vae.vae_encode_crop_pixels(image) + except Exception: + image = VAEEncode.vae_encode_crop_pixels(image) + encoded = vae.encode(image[:, :, :, :3]) + return (PreprocSparseRGBWrapper(condhint=encoded),) +``` \ No newline at end of file diff --git a/docs/ACN_SparseCtrlSpreadMethodNode.md b/docs/ACN_SparseCtrlSpreadMethodNode.md new file mode 100644 index 0000000..76c7a83 --- /dev/null +++ b/docs/ACN_SparseCtrlSpreadMethodNode.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: SparseSpreadMethodNode +- Category: Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +SparseSpreadMethodNode 类旨在生成和管理给定范围内的稀疏索引分布。它抽象地处理了不同扩散方法的逻辑,例如均匀、开始、结束和中心,允许灵活处理稀疏数据。 + +# Input types +## Required +- spread + - 参数 'spread' 决定了稀疏索引如何在整个长度范围内分布。它对节点的操作至关重要,因为它决定了稀疏数据生成的模式,这可能显著影响过程的结果。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- SPARSE_METHOD + - 输出参数 'SPARSE_METHOD' 表示用于扩散索引的方法。它很重要,因为它封装了所选扩散策略的逻辑,这对于依赖于稀疏索引分布的下游任务至关重要。 + - Comfy dtype: SparseSpreadMethod + - Python dtype: SparseSpreadMethod + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SparseSpreadMethodNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'spread': (SparseSpreadMethod.LIST,)}} + RETURN_TYPES = ('SPARSE_METHOD',) + FUNCTION = 'get_method' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl' + + def get_method(self, spread: str): + return (SparseSpreadMethod(spread=spread),) +``` \ No newline at end of file diff --git a/docs/ADE_AdjustPEFullStretch.md b/docs/ADE_AdjustPEFullStretch.md new file mode 100644 index 0000000..7e2613b --- /dev/null +++ b/docs/ADE_AdjustPEFullStretch.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: FullStretchPENode +- Category: Animate Diff 🎭🅐🅓/ad settings/pe adjust +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +FullStretchPENode 类旨在修改动画中角色私处的属性。它通过应用各种调整,如拉伸、偏移和限制初始长度来实现这一点。该节点的主要功能是通过这些修改增强动画的视觉效果和细节。 + +# Input types +## Required +- pe_stretch + - 'pe_stretch' 参数控制应用于角色私处的拉伸程度。这对于定义该区域动画的视觉范围和细节至关重要。 + - Comfy dtype: INT + - Python dtype: int +- print_adjustment + - 'print_adjustment' 参数决定是否将调整细节输出到控制台。这对于调试和理解正在做的调整很有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- prev_pe_adjust + - 'prev_pe_adjust' 参数允许对之前的私处设置进行调整。这对于根据之前的调整来完善动画很重要。 + - Comfy dtype: PE_ADJUST + - Python dtype: Union[AdjustGroup, None] + +# Output types +- PE_ADJUST + - 输出 'PE_ADJUST' 表示对角色私处所做的最终调整集。它封装了应用于动画的视觉增强。 + - Comfy dtype: PE_ADJUST + - Python dtype: AdjustGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FullStretchPENode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pe_stretch': ('INT', {'default': 0, 'min': 0, 'max': BIGMAX}), 'print_adjustment': ('BOOLEAN', {'default': False})}, 'optional': {'prev_pe_adjust': ('PE_ADJUST',)}} + RETURN_TYPES = ('PE_ADJUST',) + CATEGORY = 'Animate Diff 🎭🅐🅓/ad settings/pe adjust' + FUNCTION = 'get_pe_adjust' + + def get_pe_adjust(self, pe_stretch: int, print_adjustment: bool, prev_pe_adjust: AdjustGroup=None): + if prev_pe_adjust is None: + prev_pe_adjust = AdjustGroup() + prev_pe_adjust = prev_pe_adjust.clone() + adjust = AdjustPE(motion_pe_stretch=pe_stretch, print_adjustment=print_adjustment) + prev_pe_adjust.add(adjust) + return (prev_pe_adjust,) +``` \ No newline at end of file diff --git a/docs/ADE_AdjustPEManual.md b/docs/ADE_AdjustPEManual.md new file mode 100644 index 0000000..54dbe5a --- /dev/null +++ b/docs/ADE_AdjustPEManual.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: ManualAdjustPENode +- Category: Animate Diff 🎭🅐🅓/ad settings/pe adjust +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +该节点旨在手动调整与动画工作流中PE(个人能量)相关的参数。它允许微调初始和最终PE索引,插值到特定长度,并提供打印调整的选项。节点在自定义动画中的能量水平以实现所需效果中发挥着关键作用。 + +# Input types +## Required +- cap_initial_pe_length + - 此参数定义了要限制的PE的初始长度,这对于控制动画中的起始能量水平至关重要。它直接影响能量动态和整个动画序列的整体感觉。 + - Comfy dtype: INT + - Python dtype: int +- interpolate_pe_to_length + - 插值参数允许PE平滑过渡到指定长度,确保动画中能量的和谐流动。这是实现能量水平自然进展的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- initial_pe_idx_offset + - 此偏移参数用于调整PE的起始索引,可以显著改变动画的初始能量状态。它提供了一种在序列开始时微调能量输入的方法。 + - Comfy dtype: INT + - Python dtype: int +- final_pe_idx_offset + - 最终PE索引偏移对于定义动画的结束能量状态至关重要。它允许对动画序列结束时能量的解决方式进行精确控制。 + - Comfy dtype: INT + - Python dtype: int +- print_adjustment + - 这个布尔标志决定了对PE所做的调整是否会被打印出来。这对于调试和理解调整对动画的影响非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- prev_pe_adjust + - 以前的PE调整组提供了一种在现有调整基础上构建的方法,允许在动画中产生累积效果。它是一个可选参数,增强了节点功能的灵活性。 + - Comfy dtype: PE_ADJUST + - Python dtype: AdjustGroup + +# Output types +- PE_ADJUST + - 该节点的输出是一个包含对PE进行手动调整的AdjustGroup对象。它很重要,因为它直接影响最终的能量水平和动画的整体结果。 + - Comfy dtype: PE_ADJUST + - Python dtype: AdjustGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ManualAdjustPENode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'cap_initial_pe_length': ('INT', {'default': 0, 'min': 0, 'step': 1}), 'interpolate_pe_to_length': ('INT', {'default': 0, 'min': 0, 'step': 1}), 'initial_pe_idx_offset': ('INT', {'default': 0, 'min': 0, 'step': 1}), 'final_pe_idx_offset': ('INT', {'default': 0, 'min': 0, 'step': 1}), 'print_adjustment': ('BOOLEAN', {'default': False})}, 'optional': {'prev_pe_adjust': ('PE_ADJUST',)}} + RETURN_TYPES = ('PE_ADJUST',) + CATEGORY = 'Animate Diff 🎭🅐🅓/ad settings/pe adjust' + FUNCTION = 'get_pe_adjust' + + def get_pe_adjust(self, cap_initial_pe_length: int, interpolate_pe_to_length: int, initial_pe_idx_offset: int, final_pe_idx_offset: int, print_adjustment: bool, prev_pe_adjust: AdjustGroup=None): + if prev_pe_adjust is None: + prev_pe_adjust = AdjustGroup() + prev_pe_adjust = prev_pe_adjust.clone() + adjust = AdjustPE(cap_initial_pe_length=cap_initial_pe_length, interpolate_pe_to_length=interpolate_pe_to_length, initial_pe_idx_offset=initial_pe_idx_offset, final_pe_idx_offset=final_pe_idx_offset, print_adjustment=print_adjustment) + prev_pe_adjust.add(adjust) + return (prev_pe_adjust,) +``` \ No newline at end of file diff --git a/docs/ADE_AdjustPESweetspotStretch.md b/docs/ADE_AdjustPESweetspotStretch.md new file mode 100644 index 0000000..c531abb --- /dev/null +++ b/docs/ADE_AdjustPESweetspotStretch.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: SweetspotStretchPENode +- Category: Animate Diff 🎭🅐🅓/ad settings/pe adjust +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +SweetspotStretchPENode 类旨在通过拉伸或压缩峰值效果(PE)来调整动画的峰值效果。该节点允许对动画的动态进行微调,确保 PE 最佳地定位和缩放以实现所需的视觉效果。 + +# Input types +## Required +- sweetspot + - 'sweespot' 参数定义了动画中峰值效果的初始长度。这对于确定 PE 调整过程的起始点至关重要。 + - Comfy dtype: INT + - Python dtype: int +- new_sweetspot + - 'new_sweetspot' 参数指定了将峰值效果调整到的目标长度。它是控制动画 PE 最终外观的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- print_adjustment + - 'print_adjustment' 参数是一个布尔标志,当设置为 True 时,指示节点打印出 PE 调整过程的详细信息。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- prev_pe_adjust + - 'prev_pe_adjust' 参数是可选的以前调整的组,可以应用于当前的 PE 调整。它允许对复杂动画场景进行调整的链式处理。 + - Comfy dtype: PE_ADJUST + - Python dtype: Union[AdjustGroup, None] + +# Output types +- PE_ADJUST + - 节点的输出是一个包含新 PE 调整以及任何先前调整的 AdjustGroup 对象。此对象用于将 PE 调整应用于动画。 + - Comfy dtype: PE_ADJUST + - Python dtype: AdjustGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SweetspotStretchPENode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'sweetspot': ('INT', {'default': 16, 'min': 0, 'max': BIGMAX}), 'new_sweetspot': ('INT', {'default': 16, 'min': 0, 'max': BIGMAX}), 'print_adjustment': ('BOOLEAN', {'default': False})}, 'optional': {'prev_pe_adjust': ('PE_ADJUST',)}} + RETURN_TYPES = ('PE_ADJUST',) + CATEGORY = 'Animate Diff 🎭🅐🅓/ad settings/pe adjust' + FUNCTION = 'get_pe_adjust' + + def get_pe_adjust(self, sweetspot: int, new_sweetspot: int, print_adjustment: bool, prev_pe_adjust: AdjustGroup=None): + if prev_pe_adjust is None: + prev_pe_adjust = AdjustGroup() + prev_pe_adjust = prev_pe_adjust.clone() + adjust = AdjustPE(cap_initial_pe_length=sweetspot, interpolate_pe_to_length=new_sweetspot, print_adjustment=print_adjustment) + prev_pe_adjust.add(adjust) + return (prev_pe_adjust,) +``` \ No newline at end of file diff --git a/docs/ADE_AdjustWeightAllAdd.md b/docs/ADE_AdjustWeightAllAdd.md new file mode 100644 index 0000000..1fb766a --- /dev/null +++ b/docs/ADE_AdjustWeightAllAdd.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: WeightAdjustAllAddNode +- Category: Animate Diff 🎭🅐🅓/ad settings/weight adjust +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +在`WeightAdjustAllAddNode`类中,`get_weight_adjust`方法旨在对模型中的所有权重应用统一的调整。它通过接受一个加法值,并可选择性地打印调整细节来实现这一点。该方法在动画差异处理过程中微调模型权重至关重要,确保调整一致地应用于整个模型。 + +# Input types +## Required +- all_ADD + - 参数`all_ADD`指定了模型中所有权重应该调整的量。这是一个关键的输入,因为它直接影响权重调整的大小,从而影响调整后模型的性能。 + - Comfy dtype: FLOAT + - Python dtype: float +- print_adjustment + - 标志`print_adjustment`决定是否打印权重调整的详细信息。这对于调试或监控对模型权重所做的调整非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- prev_weight_adjust + - 参数`prev_weight_adjust`允许提供先前的权重调整组,可用于建立或修改现有的权重调整。这个参数是可选的,但可以增强权重调整过程的灵活性。 + - Comfy dtype: WEIGHT_ADJUST + - Python dtype: AdjustGroup + +# Output types +- WEIGHT_ADJUST + - `get_weight_adjust`方法的输出是一个`AdjustGroup`对象,它包含了应用指定的`all_ADD`值后的结果权重调整。这个对象很重要,因为它代表了调整后模型权重的更新状态。 + - Comfy dtype: WEIGHT_ADJUST + - Python dtype: AdjustGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WeightAdjustAllAddNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'all_ADD': ('FLOAT', {'default': 0.0, 'min': -2.0, 'max': 2.0, 'step': 1e-06}), 'print_adjustment': ('BOOLEAN', {'default': False})}, 'optional': {'prev_weight_adjust': ('WEIGHT_ADJUST',)}} + RETURN_TYPES = ('WEIGHT_ADJUST',) + CATEGORY = 'Animate Diff 🎭🅐🅓/ad settings/weight adjust' + FUNCTION = 'get_weight_adjust' + + def get_weight_adjust(self, all_ADD: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None): + if prev_weight_adjust is None: + prev_weight_adjust = AdjustGroup() + prev_weight_adjust = prev_weight_adjust.clone() + adjust = AdjustWeight(all_ADD=all_ADD, print_adjustment=print_adjustment) + prev_weight_adjust.add(adjust) + return (prev_weight_adjust,) +``` \ No newline at end of file diff --git a/docs/ADE_AdjustWeightAllMult.md b/docs/ADE_AdjustWeightAllMult.md new file mode 100644 index 0000000..662b7e0 --- /dev/null +++ b/docs/ADE_AdjustWeightAllMult.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: WeightAdjustAllMultNode +- Category: Animate Diff 🎭🅐🅓/ad settings/weight adjust +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +WeightAdjustAllMultNode类的'get_weight_adjust'方法旨在对模型中的所有权重应用统一的乘数,从而在不改变底层架构的情况下微调模型参数。它是调整模型权重整体规模的关键工具,特别适用于需要根据不同输入范围或灵敏度水平校准模型响应的场景。 + +# Input types +## Required +- all_MULT + - 参数'all_MULT'对于确定将应用于模型中所有权重的统一乘数至关重要。它允许对模型的权重进行简单的缩放,这可以显著影响模型的性能和行为。此参数对于调整模型对输入数据的敏感度非常关键。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- print_adjustment + - 参数'print_adjustment'是一个可选的标志,设置为True时启用记录权重调整的详细信息。这对于调试或希望在调整过程中跟踪对模型权重所做的调整的用户来说非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- prev_weight_adjust + - 参数'prev_weight_adjust'允许用户提供一个先前的权重调整组,然后方法将在此基础上构建。这对于增量调整非常有用,其中方法可以从先前建立的状态继续,而不是从头开始。 + - Comfy dtype: WEIGHT_ADJUST + - Python dtype: AdjustGroup + +# Output types +- WEIGHT_ADJUST + - 'get_weight_adjust'方法的输出是一个'WEIGHT_ADJUST'对象,它封装了对模型权重所做的调整。这个对象非常重要,因为它代表了权重调整过程后模型参数的更新状态,准备用于进一步的模型训练或推理。 + - Comfy dtype: WEIGHT_ADJUST + - Python dtype: AdjustGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WeightAdjustAllMultNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'all_MULT': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 1e-06}), 'print_adjustment': ('BOOLEAN', {'default': False})}, 'optional': {'prev_weight_adjust': ('WEIGHT_ADJUST',)}} + RETURN_TYPES = ('WEIGHT_ADJUST',) + CATEGORY = 'Animate Diff 🎭🅐🅓/ad settings/weight adjust' + FUNCTION = 'get_weight_adjust' + + def get_weight_adjust(self, all_MULT: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None): + if prev_weight_adjust is None: + prev_weight_adjust = AdjustGroup() + prev_weight_adjust = prev_weight_adjust.clone() + adjust = AdjustWeight(all_MULT=all_MULT, print_adjustment=print_adjustment) + prev_weight_adjust.add(adjust) + return (prev_weight_adjust,) +``` \ No newline at end of file diff --git a/docs/ADE_AdjustWeightIndivAdd.md b/docs/ADE_AdjustWeightIndivAdd.md new file mode 100644 index 0000000..da68c45 --- /dev/null +++ b/docs/ADE_AdjustWeightIndivAdd.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: WeightAdjustIndivAddNode +- Category: Animate Diff 🎭🅐🅓/ad settings/weight adjust +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +WeightAdjustIndivAddNode 旨在通过向不同类型的参数添加特定值来单独调整模型的权重。它封装了根据指定标准进行修改的逻辑,确保以结构化和模块化的方式应用这些调整。 + +# Input types +## Required +- pe_ADD + - pe_ADD 参数允许调整位置编码权重。它在微调模型对输入序列结构的理解中起着至关重要的作用,这对于依赖于元素顺序的任务至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_ADD + - attn_ADD 参数用于修改注意力机制的权重。通过调整此参数,可以增强模型聚焦输入的不同部分的能力,可能有助于提高模型在需要对上下文有细微理解的任务上的性能。 + - Comfy dtype: FLOAT + - Python dtype: float +- other_ADD + - other_ADD 参数用于调整不属于预定义类别的权重。它提供了微调模型的灵活性,以覆盖其他参数未涵盖的方式,允许进行更广泛的调整。 + - Comfy dtype: FLOAT + - Python dtype: float +- print_adjustment + - print_adjustment 标志控制是否将对权重所做的调整记录在日志中。这对于调试和理解调整对模型行为的影响非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- prev_weight_adjust + - prev_weight_adjust 参数是可选的先前调整组,可以应用于模型。这允许继续一系列调整或应用一组预定义的修改。 + - Comfy dtype: WEIGHT_ADJUST + - Python dtype: AdjustGroup + +# Output types +- weight_adjust + - WeightAdjustIndivAddNode 的输出是一个 WEIGHT_ADJUST 对象,它代表了对模型权重所做的集体调整。这个对象可以用来进一步完善模型或将调整应用于另一个模型实例。 + - Comfy dtype: WEIGHT_ADJUST + - Python dtype: AdjustGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WeightAdjustIndivAddNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pe_ADD': ('FLOAT', {'default': 0.0, 'min': -2.0, 'max': 2.0, 'step': 1e-06}), 'attn_ADD': ('FLOAT', {'default': 0.0, 'min': -2.0, 'max': 2.0, 'step': 1e-06}), 'other_ADD': ('FLOAT', {'default': 0.0, 'min': -2.0, 'max': 2.0, 'step': 1e-06}), 'print_adjustment': ('BOOLEAN', {'default': False})}, 'optional': {'prev_weight_adjust': ('WEIGHT_ADJUST',)}} + RETURN_TYPES = ('WEIGHT_ADJUST',) + CATEGORY = 'Animate Diff 🎭🅐🅓/ad settings/weight adjust' + FUNCTION = 'get_weight_adjust' + + def get_weight_adjust(self, pe_ADD: float, attn_ADD: float, other_ADD: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None): + if prev_weight_adjust is None: + prev_weight_adjust = AdjustGroup() + prev_weight_adjust = prev_weight_adjust.clone() + adjust = AdjustWeight(pe_ADD=pe_ADD, attn_ADD=attn_ADD, other_ADD=other_ADD, print_adjustment=print_adjustment) + prev_weight_adjust.add(adjust) + return (prev_weight_adjust,) +``` \ No newline at end of file diff --git a/docs/ADE_AdjustWeightIndivAttnAdd.md b/docs/ADE_AdjustWeightIndivAttnAdd.md new file mode 100644 index 0000000..54100a3 --- /dev/null +++ b/docs/ADE_AdjustWeightIndivAttnAdd.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: WeightAdjustIndivAttnAddNode +- Category: Animate Diff 🎭🅐🅓/ad settings/weight adjust +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +WeightAdjustIndivAttnAddNode 类旨在调整神经网络模型中各个注意力机制的权重。它提供了一种方法来微调注意力参数,例如查询(q)、键(k)和值(v)向量,以及输出权重和偏差。此节点允许根据特定用例或实验要求修改这些参数,以定制模型行为。 + +# Input types +## Required +- pe_ADD + - pe_ADD 参数用于调整模型的位置编码权重。它在模型解释序列顺序方面起着至关重要的作用,这可能显著影响模型在对输入数据顺序敏感的任务上的性能。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_ADD + - attn_ADD 参数允许调整模型内的一般注意力权重。这有助于强调或淡化输入数据的某些方面,从而影响模型的焦点,并可能增强其捕捉相关信息的能力。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_q_ADD + - attn_q_ADD 参数专门针对注意力机制的查询权重。通过微调此参数,可以引导模型更多地关注某些输入特征,这对于需要深入理解输入上下文的任务特别有用。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_k_ADD + - attn_k_ADD 参数负责调整注意力机制的键权重。修改此参数可以改变模型与输入数据的相关部分对齐的能力,这对于依赖准确上下文对齐的任务至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_v_ADD + - attn_v_ADD 参数影响注意力机制内的值权重。它对于确定每个输入元素对最终输出的贡献很重要,这对于需要精确表示输入数据的任务至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_out_weight_ADD + - attn_out_weight_ADD 参数用于调整注意力机制的输出权重。这有助于提炼模型的输出,使其更贴近期望的结果,这对于需要输出层高精度的任务特别重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_out_bias_ADD + - attn_out_bias_ADD 参数允许调整注意力机制内的输出偏差。这对于调整模型的预测以更好地符合预期结果很有用,特别是对于需要精确输出调整的任务。 + - Comfy dtype: FLOAT + - Python dtype: float +- other_ADD + - other_ADD 参数为模型内其他未指定的权重提供了一般性调整。它可以用来对模型的行为进行广泛的调整,这些调整不属于其他参数的具体类别。 + - Comfy dtype: FLOAT + - Python dtype: float +- print_adjustment + - print_adjustment 参数是一个布尔标志,设置为 True 时启用记录权重调整的详细信息。这对于调试和理解调整如何影响模型参数很有帮助。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- prev_weight_adjust + - prev_weight_adjust 参数是可选的先前权重调整组,可以应用于模型。这允许继续一系列调整或应用一组预定义的调整。 + - Comfy dtype: WEIGHT_ADJUST + - Python dtype: Union[AdjustGroup, None] + +# Output types +- weight_adjust + - weight_adjust 输出提供了将各个注意力调整应用于模型的结果。它包含了所有输入参数对模型权重的综合影响,提供了调整后权重的结构化表示。 + - Comfy dtype: WEIGHT_ADJUST + - Python dtype: AdjustGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WeightAdjustIndivAttnAddNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pe_ADD': ('FLOAT', {'default': 0.0, 'min': -2.0, 'max': 2.0, 'step': 1e-06}), 'attn_ADD': ('FLOAT', {'default': 0.0, 'min': -2.0, 'max': 2.0, 'step': 1e-06}), 'attn_q_ADD': ('FLOAT', {'default': 0.0, 'min': -2.0, 'max': 2.0, 'step': 1e-06}), 'attn_k_ADD': ('FLOAT', {'default': 0.0, 'min': -2.0, 'max': 2.0, 'step': 1e-06}), 'attn_v_ADD': ('FLOAT', {'default': 0.0, 'min': -2.0, 'max': 2.0, 'step': 1e-06}), 'attn_out_weight_ADD': ('FLOAT', {'default': 0.0, 'min': -2.0, 'max': 2.0, 'step': 1e-06}), 'attn_out_bias_ADD': ('FLOAT', {'default': 0.0, 'min': -2.0, 'max': 2.0, 'step': 1e-06}), 'other_ADD': ('FLOAT', {'default': 0.0, 'min': -2.0, 'max': 2.0, 'step': 1e-06}), 'print_adjustment': ('BOOLEAN', {'default': False})}, 'optional': {'prev_weight_adjust': ('WEIGHT_ADJUST',)}} + RETURN_TYPES = ('WEIGHT_ADJUST',) + CATEGORY = 'Animate Diff 🎭🅐🅓/ad settings/weight adjust' + FUNCTION = 'get_weight_adjust' + + def get_weight_adjust(self, pe_ADD: float, attn_ADD: float, attn_q_ADD: float, attn_k_ADD: float, attn_v_ADD: float, attn_out_weight_ADD: float, attn_out_bias_ADD: float, other_ADD: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None): + if prev_weight_adjust is None: + prev_weight_adjust = AdjustGroup() + prev_weight_adjust = prev_weight_adjust.clone() + adjust = AdjustWeight(pe_ADD=pe_ADD, attn_ADD=attn_ADD, attn_q_ADD=attn_q_ADD, attn_k_ADD=attn_k_ADD, attn_v_ADD=attn_v_ADD, attn_out_weight_ADD=attn_out_weight_ADD, attn_out_bias_ADD=attn_out_bias_ADD, other_ADD=other_ADD, print_adjustment=print_adjustment) + prev_weight_adjust.add(adjust) + return (prev_weight_adjust,) +``` \ No newline at end of file diff --git a/docs/ADE_AdjustWeightIndivAttnMult.md b/docs/ADE_AdjustWeightIndivAttnMult.md new file mode 100644 index 0000000..cdfdd23 --- /dev/null +++ b/docs/ADE_AdjustWeightIndivAttnMult.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: WeightAdjustIndivAttnMultNode +- Category: Animate Diff 🎭🅐🅓/ad settings/weight adjust +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +WeightAdjustIndivAttnMultNode 类旨在单独调整神经网络模型中注意力机制的权重。它允许通过将它们与指定的因子相乘来微调位置编码和注意力组件的影响。此节点对于通过调整注意力过程以满足特定任务需求来优化模型性能至关重要。 + +# Input types +## Required +- pe_MULT + - pe_MULT 参数对于缩放位置编码权重至关重要。它直接影响模型捕获输入的顺序的能力,这对于语言翻译或文本生成等任务至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_MULT + - attn_MULT 参数调整整体注意力权重,影响模型对输入序列不同部分的聚焦。这对于强调或淡化某些输入特征特别有用。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_q_MULT + - attn_q_MULT 参数专门针对注意力机制中的查询权重,允许修改模型查询输入数据不同元素的方式。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_k_MULT + - attn_k_MULT 参数影响注意力机制中的键权重,它决定了模型如何将输入序列与上下文对齐。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_v_MULT + - attn_v_MULT 参数修改注意力机制中的值权重,这对于模型衡量不同输入元素的重要性至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_out_weight_MULT + - attn_out_weight_MULT 参数缩放开了注意力机制的输出权重,这对于模型中输入序列的最终表示非常重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_out_bias_MULT + - attn_out_bias_MULT 参数调整注意力机制输出的偏置项,这有助于微调模型的预测。 + - Comfy dtype: FLOAT + - Python dtype: float +- other_MULT + - other_MULT 参数为模型中未明确分类的其他权重组件提供通用的缩放因子。 + - Comfy dtype: FLOAT + - Python dtype: float +- print_adjustment + - print_adjustment 参数决定节点是否输出详细说明对权重所做的调整的日志。这对于调试和理解调整的影响非常有帮助。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- prev_weight_adjust + - prev_weight_adjust 参数允许提供先前的权重调整组,使节点能够基于现有调整进行构建,或者重置并重新开始。 + - Comfy dtype: WEIGHT_ADJUST + - Python dtype: Union[AdjustGroup, None] + +# Output types +- weight_adjust + - 节点的输出是一个 WEIGHT_ADJUST 对象,它封装了对模型权重所做的调整。这个对象可以用来将这些调整应用于模型,或者在后续节点中进一步细化调整。 + - Comfy dtype: WEIGHT_ADJUST + - Python dtype: AdjustGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WeightAdjustIndivAttnMultNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pe_MULT': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 1e-06}), 'attn_MULT': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 1e-06}), 'attn_q_MULT': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 1e-06}), 'attn_k_MULT': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 1e-06}), 'attn_v_MULT': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 1e-06}), 'attn_out_weight_MULT': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 1e-06}), 'attn_out_bias_MULT': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 1e-06}), 'other_MULT': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 1e-06}), 'print_adjustment': ('BOOLEAN', {'default': False})}, 'optional': {'prev_weight_adjust': ('WEIGHT_ADJUST',)}} + RETURN_TYPES = ('WEIGHT_ADJUST',) + CATEGORY = 'Animate Diff 🎭🅐🅓/ad settings/weight adjust' + FUNCTION = 'get_weight_adjust' + + def get_weight_adjust(self, pe_MULT: float, attn_MULT: float, attn_q_MULT: float, attn_k_MULT: float, attn_v_MULT: float, attn_out_weight_MULT: float, attn_out_bias_MULT: float, other_MULT: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None): + if prev_weight_adjust is None: + prev_weight_adjust = AdjustGroup() + prev_weight_adjust = prev_weight_adjust.clone() + adjust = AdjustWeight(pe_MULT=pe_MULT, attn_MULT=attn_MULT, attn_q_MULT=attn_q_MULT, attn_k_MULT=attn_k_MULT, attn_v_MULT=attn_v_MULT, attn_out_weight_MULT=attn_out_weight_MULT, attn_out_bias_MULT=attn_out_bias_MULT, other_MULT=other_MULT, print_adjustment=print_adjustment) + prev_weight_adjust.add(adjust) + return (prev_weight_adjust,) +``` \ No newline at end of file diff --git a/docs/ADE_AdjustWeightIndivMult.md b/docs/ADE_AdjustWeightIndivMult.md new file mode 100644 index 0000000..5637a73 --- /dev/null +++ b/docs/ADE_AdjustWeightIndivMult.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: WeightAdjustIndivMultNode +- Category: Animate Diff 🎭🅐🅓/ad settings/weight adjust +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +WeightAdjustIndivMultNode 类旨在通过乘法单独修改模型的权重。它提供了一种方法,可以根据预定义的乘数(如 pe_MULT、attn_MULT 和 other_MULT)调整模型的不同部分的权重,允许对模型参数进行微调,而不会改变其底层结构。如果需要,该节点还支持打印调整细节,提供对权重修改过程的透明度。 + +# Input types +## Required +- pe_MULT + - pe_MULT 参数是一个乘数,用于调整模型中与位置编码(PE)相关的权重。它在微调模型对输入元素顺序的敏感度中起着关键作用,这可以显著影响模型在依赖序列顺序的任务上的性能。 + - Comfy dtype: FLOAT + - Python dtype: float +- attn_MULT + - attn_MULT 参数是模型中注意力机制权重的乘数。通过调整此值,可以控制注意力机制对模型输出的影响,这对于需要对上下文和元素之间的关系有细致理解的任务至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- other_MULT + - other_MULT 参数是一个通用乘数,可以应用于模型中未被 pe_MULT 或 attn_MULT 涵盖的其他权重。它为特定用例或实验设置中调整模型行为提供了灵活性。 + - Comfy dtype: FLOAT + - Python dtype: float +- print_adjustment + - print_adjustment 参数是一个布尔标志,设置为 True 时启用记录权重调整细节。这对于开发人员在调整过程中跟踪和验证对模型权重所做的更改非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- prev_weight_adjust + - prev_weight_adjust 参数允许提供先前的权重调整组,可用于在现有权重调整的基础上进行构建或修改。当需要在迭代调整中保留先前调整步骤的状态并进一步改进时,此参数特别有用。 + - Comfy dtype: WEIGHT_ADJUST + - Python dtype: AdjustGroup + +# Output types +- WEIGHT_ADJUST + - WeightAdjustIndivMultNode 的输出是一个 AdjustGroup 对象,它封装了应用于模型的结果权重调整。这个对象可以用来进一步完善模型或将调整应用于另一个模型实例。 + - Comfy dtype: WEIGHT_ADJUST + - Python dtype: AdjustGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WeightAdjustIndivMultNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pe_MULT': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 1e-06}), 'attn_MULT': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 1e-06}), 'other_MULT': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 1e-06}), 'print_adjustment': ('BOOLEAN', {'default': False})}, 'optional': {'prev_weight_adjust': ('WEIGHT_ADJUST',)}} + RETURN_TYPES = ('WEIGHT_ADJUST',) + CATEGORY = 'Animate Diff 🎭🅐🅓/ad settings/weight adjust' + FUNCTION = 'get_weight_adjust' + + def get_weight_adjust(self, pe_MULT: float, attn_MULT: float, other_MULT: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None): + if prev_weight_adjust is None: + prev_weight_adjust = AdjustGroup() + prev_weight_adjust = prev_weight_adjust.clone() + adjust = AdjustWeight(pe_MULT=pe_MULT, attn_MULT=attn_MULT, other_MULT=other_MULT, print_adjustment=print_adjustment) + prev_weight_adjust.add(adjust) + return (prev_weight_adjust,) +``` \ No newline at end of file diff --git a/docs/ADE_AnimateDiffKeyframe.md b/docs/ADE_AnimateDiffKeyframe.md new file mode 100644 index 0000000..dbf3424 --- /dev/null +++ b/docs/ADE_AnimateDiffKeyframe.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: ADKeyframeNode +- Category: Animate Diff 🎭🅐🅓 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +ADKeyframeNode 类用于管理动画差异的关键帧。它提供加载和操作关键帧的功能,确保动画序列的连贯性和明确性。此节点对于创建平滑过渡和维护整个动画序列的完整性至关重要。 + +# Input types +## Required +- start_percent + - start_percent 参数定义了关键帧在动画时间线中的起始位置。它对于确定动画的时机和确保关键帧序列的正确排序至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- prev_ad_keyframes + - prev_ad_keyframes 参数允许用户提供一组先前的关键帧,新的关键帧将被添加到这些关键帧中。这对于保持连续性并在现有动画框架上构建至关重要。 + - Comfy dtype: AD_KEYFRAMES + - Python dtype: ADKeyframeGroup +- scale_multival + - scale_multival 参数调整关键帧处动画的缩放。它对于控制动画变化的强度和在序列特定点的范围至关重要。 + - Comfy dtype: MULTIVAL + - Python dtype: Union[float, torch.Tensor] +- effect_multival + - effect_multival 参数用于修改关键帧处的效果强度。它在微调动画在特定时刻的视觉影响中起着至关重要的作用。 + - Comfy dtype: MULTIVAL + - Python dtype: Union[float, torch.Tensor] +- inherit_missing + - inherit_missing 参数决定关键帧是否应该从先前的关键帧继承属性,如果它们没有被明确定义的话。这对于维护整个序列中一致的动画风格至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- guarantee_steps + - guarantee_steps 参数确保关键帧之间的最小步数,这对于动画的平滑度和流畅性很重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- AD_KEYFRAMES + - ADKeyframeNode 的输出是一组关键帧,代表了带有新添加或修改的关键帧的动画序列。这个输出对于动画的后续处理和渲染非常重要。 + - Comfy dtype: AD_KEYFRAMES + - Python dtype: ADKeyframeGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ADKeyframeNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001})}, 'optional': {'prev_ad_keyframes': ('AD_KEYFRAMES',), 'scale_multival': ('MULTIVAL',), 'effect_multival': ('MULTIVAL',), 'inherit_missing': ('BOOLEAN', {'default': True}), 'guarantee_steps': ('INT', {'default': 1, 'min': 0, 'max': BIGMAX})}} + RETURN_TYPES = ('AD_KEYFRAMES',) + FUNCTION = 'load_keyframe' + CATEGORY = 'Animate Diff 🎭🅐🅓' + + def load_keyframe(self, start_percent: float, prev_ad_keyframes=None, scale_multival: Union[float, torch.Tensor]=None, effect_multival: Union[float, torch.Tensor]=None, inherit_missing: bool=True, guarantee_steps: int=1): + if not prev_ad_keyframes: + prev_ad_keyframes = ADKeyframeGroup() + prev_ad_keyframes = prev_ad_keyframes.clone() + keyframe = ADKeyframe(start_percent=start_percent, scale_multival=scale_multival, effect_multival=effect_multival, inherit_missing=inherit_missing, guarantee_steps=guarantee_steps) + prev_ad_keyframes.add(keyframe) + return (prev_ad_keyframes,) +``` \ No newline at end of file diff --git a/docs/ADE_AnimateDiffLoRALoader.md b/docs/ADE_AnimateDiffLoRALoader.md new file mode 100644 index 0000000..23cf522 --- /dev/null +++ b/docs/ADE_AnimateDiffLoRALoader.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: AnimateDiffLoraLoader +- Category: Animate Diff 🎭🅐🅓 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +AnimateDiffLoraLoader节点旨在方便地加载和应用运动Lora模型到主体上。它能够根据指定的强度混合不同的Lora模型,允许对动画进行精细控制。在需要将多个运动影响集成到一起的字符动画任务中,这个节点至关重要。 + +# Input types +## Required +- lora_name + - 参数'lora_name'对于识别要加载的特定运动Lora模型至关重要。它确保从可用选项中正确选择模型,这对于节点的操作和最终的动画效果至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- strength + - 参数'strength'决定运动Lora对动画影响的强度。它是微调动画以实现所需效果的关键因素,允许在不同的运动层之间保持平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- prev_motion_lora + - 参数'prev_motion_lora'用于提供之前运动Lora模型的状态。它对于保持动画序列的连贯性很重要,并允许为复杂的动画效果叠加多个Lora模型。 + - Comfy dtype: MOTION_LORA + - Python dtype: MotionLoraList + +# Output types +- MOTION_LORA + - 输出'MOTION_LORA'表示应用了指定强度并与任何之前的运动Lora模型混合后的结果运动Lora模型。它对后续的动画步骤很重要,并作为进一步角色动画的基础。 + - Comfy dtype: MOTION_LORA + - Python dtype: MotionLoraList + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AnimateDiffLoraLoader: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'lora_name': (get_available_motion_loras(),), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001})}, 'optional': {'prev_motion_lora': ('MOTION_LORA',)}} + RETURN_TYPES = ('MOTION_LORA',) + CATEGORY = 'Animate Diff 🎭🅐🅓' + FUNCTION = 'load_motion_lora' + + def load_motion_lora(self, lora_name: str, strength: float, prev_motion_lora: MotionLoraList=None): + if prev_motion_lora is None: + prev_motion_lora = MotionLoraList() + else: + prev_motion_lora = prev_motion_lora.clone() + lora_path = get_motion_lora_path(lora_name) + if not Path(lora_path).is_file(): + raise FileNotFoundError(f"Motion lora with name '{lora_name}' not found.") + lora_info = MotionLoraInfo(name=lora_name, strength=strength) + prev_motion_lora.add_lora(lora_info) + return (prev_motion_lora,) +``` \ No newline at end of file diff --git a/docs/ADE_AnimateDiffSamplingSettings.md b/docs/ADE_AnimateDiffSamplingSettings.md new file mode 100644 index 0000000..4a8bddd --- /dev/null +++ b/docs/ADE_AnimateDiffSamplingSettings.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: SampleSettingsNode +- Category: Animate Diff 🎭🅐🅓 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +SampleSettingsNode类的`create_settings`方法旨在为动画过程配置和生成采样设置。它封装了定义噪声生成行为、迭代选项和采样过程中其他可定制方面的参数。此方法在为动画工作流中的后续步骤准备基础方面发挥关键作用,确保正确建立设置以实现预期结果。 + +# Input types +## Required +- batch_offset + - 参数`batch_offset`对于管理噪声生成的批量处理至关重要。它允许系统偏移批量索引,这对于确保不同批次之间具有独特的噪声模式可能是必不可少的。此参数显著影响采样过程的执行和结果。 + - Comfy dtype: INT + - Python dtype: int +- noise_type + - 参数`noise_type`确定采样过程中使用的噪声层类型。它是形成生成噪声特征的关键因素,进而影响动画的整体质量和风格。为了在最终输出中实现所需的噪声轮廓,此参数不可或缺。 + - Comfy dtype: NoiseLayerType.LIST + - Python dtype: str +- seed_gen + - 参数`seed_gen`决定噪声层的种子生成方法。它对于确保生成的噪声模式的一致性和可重复性很重要。此参数对于在不同运行中保持噪声生成过程的完整性至关重要。 + - Comfy dtype: SeedNoiseGeneration.LIST + - Python dtype: str +- seed_offset + - 参数`seed_offset`用于调整噪声生成的种子值,这可以改变生成的噪声模式。它在定制噪声特性中扮演重要角色,对于在动画中实现特定的视觉效果至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- noise_layers + - 参数`noise_layers`允许在采样过程中指定要应用的自定义噪声层。它提供了高度的灵活性,可以根据特定的创意要求定制噪声特性。对于希望尝试不同噪声配置的用户来说,此参数特别有用。 + - Comfy dtype: NOISE_LAYERS + - Python dtype: NoiseLayerGroup +- iteration_opts + - 参数`iteration_opts`提供控制采样过程中迭代过程的选项。它可以用来微调采样程序,以优化速度、准确性或资源使用等因素。在动画中实现性能和质量之间的平衡至关重要。 + - Comfy dtype: ITERATION_OPTS + - Python dtype: IterationOptions +- seed_override + - 参数`seed_override`允许手动覆盖用于噪声生成的默认种子值。在需要特定噪声模式或复制先前运行的结果的场景中,这可能特别有用。该参数为噪声生成过程增加了额外的控制层。 + - Comfy dtype: INT + - Python dtype: Union[int, None] +- adapt_denoise_steps + - 参数`adapt_denoise_steps`是一个布尔标志,当设置为true时,允许系统在采样过程中自适应地调整去噪步骤。这可以导致更有效和高效的噪声减少,提高动画的整体质量。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- custom_cfg + - 参数`custom_cfg`允许使用可应用于采样过程的自定义配置关键帧。这提供了一种引入特定创意调整和微调动画以满足独特项目要求的方法。对于寻求对动画设置有更大控制权的高级用户来说,此参数特别有益。 + - Comfy dtype: CUSTOM_CFG + - Python dtype: CustomCFGKeyframeGroup +- sigma_schedule + - 参数`sigma_schedule`定义了噪声生成过程中使用的sigma值的时间表。它对于控制噪声的方差至关重要,并且可以显著影响动画的视觉结果。此参数提供了一种在采样过程的不同阶段应用不同级别噪声减少的方法。 + - Comfy dtype: SIGMA_SCHEDULE + - Python dtype: SigmaSchedule + +# Output types +- settings + - 输出`settings`提供了通过`create_settings`方法定制的采样设置。这些设置封装了在方法调用期间指定的所有参数和选项,并用于指导动画过程的后续步骤。 + - Comfy dtype: SAMPLE_SETTINGS + - Python dtype: SampleSettings + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SampleSettingsNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'batch_offset': ('INT', {'default': 0, 'min': 0, 'max': BIGMAX}), 'noise_type': (NoiseLayerType.LIST,), 'seed_gen': (SeedNoiseGeneration.LIST,), 'seed_offset': ('INT', {'default': 0, 'min': BIGMIN, 'max': BIGMAX})}, 'optional': {'noise_layers': ('NOISE_LAYERS',), 'iteration_opts': ('ITERATION_OPTS',), 'seed_override': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615, 'forceInput': True}), 'adapt_denoise_steps': ('BOOLEAN', {'default': False}), 'custom_cfg': ('CUSTOM_CFG',), 'sigma_schedule': ('SIGMA_SCHEDULE',)}} + RETURN_TYPES = ('SAMPLE_SETTINGS',) + RETURN_NAMES = ('settings',) + CATEGORY = 'Animate Diff 🎭🅐🅓' + FUNCTION = 'create_settings' + + def create_settings(self, batch_offset: int, noise_type: str, seed_gen: str, seed_offset: int, noise_layers: NoiseLayerGroup=None, iteration_opts: IterationOptions=None, seed_override: int=None, adapt_denoise_steps=False, custom_cfg: CustomCFGKeyframeGroup=None, sigma_schedule: SigmaSchedule=None): + sampling_settings = SampleSettings(batch_offset=batch_offset, noise_type=noise_type, seed_gen=seed_gen, seed_offset=seed_offset, noise_layers=noise_layers, iteration_opts=iteration_opts, seed_override=seed_override, adapt_denoise_steps=adapt_denoise_steps, custom_cfg=custom_cfg, sigma_schedule=sigma_schedule) + return (sampling_settings,) +``` \ No newline at end of file diff --git a/docs/ADE_AnimateDiffSettings.md b/docs/ADE_AnimateDiffSettings.md new file mode 100644 index 0000000..5bebeb6 --- /dev/null +++ b/docs/ADE_AnimateDiffSettings.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: AnimateDiffSettingsNode +- Category: Animate Diff 🎭🅐🅓/ad settings +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +AnimateDiffSettingsNode 旨在生成用于调整场景差异的动画设置。它封装了调整位置嵌入和权重的逻辑,这些对于动画过程至关重要。该节点的主要功能是提供一种结构化的方法来动画化差异,确保调整在整个动画序列中一致且有效地应用。 + +# Input types +## Optional +- pe_adjust + - pe_adjust 参数允许对动画中的位置嵌入进行微调。这对于实现动画元素所需的空间分布和运动至关重要。此参数直接影响动画的空间方面如何呈现,影响动画场景的整体质量和连贯性。 + - Comfy dtype: PE_ADJUST + - Python dtype: Union[AdjustGroup, None] +- weight_adjust + - weight_adjust 参数用于修改与动画元素相关联的权重。它在控制动画效果的强度和焦点方面起着重要作用。通过调整权重,节点可以增强或减弱动画的特定方面,从而获得更细致和针对性的视觉结果。 + - Comfy dtype: WEIGHT_ADJUST + - Python dtype: Union[AdjustGroup, None] + +# Output types +- ad_settings + - ad_settings 输出提供了一套根据输入参数调整的全面动画设置。这个输出对于动画流水线的后续步骤至关重要,因为它决定了动画差异将如何在最终渲染的场景中体现。 + - Comfy dtype: AD_SETTINGS + - Python dtype: AnimateDiffSettings + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AnimateDiffSettingsNode: + + @classmethod + def INPUT_TYPES(s): + return {'optional': {'pe_adjust': ('PE_ADJUST',), 'weight_adjust': ('WEIGHT_ADJUST',)}} + RETURN_TYPES = ('AD_SETTINGS',) + CATEGORY = 'Animate Diff 🎭🅐🅓/ad settings' + FUNCTION = 'get_ad_settings' + + def get_ad_settings(self, pe_adjust: AdjustGroup=None, weight_adjust: AdjustGroup=None): + return (AnimateDiffSettings(adjust_pe=pe_adjust, adjust_weight=weight_adjust),) +``` \ No newline at end of file diff --git a/docs/ADE_AnimateDiffUniformContextOptions.md b/docs/ADE_AnimateDiffUniformContextOptions.md new file mode 100644 index 0000000..ff38d80 --- /dev/null +++ b/docs/ADE_AnimateDiffUniformContextOptions.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: LegacyLoopedUniformContextOptionsNode +- Category: Context +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +LegacyLoopedUniformContextOptionsNode旨在为统一循环模式创建上下文选项提供便利。它抽象了设置上下文参数的复杂性,允许在系统中以简化的方法管理上下文。此节点强调了易用性和生成一致上下文配置的能力。 + +# Input types +## Required +- context_length + - context_length参数定义了上下文窗口的长度,这对于确定正在处理的数据的范围至关重要。它通过影响上下文的粒度,在节点的执行中起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- context_stride + - context_stride参数决定了连续上下文窗口之间的步长,这对于控制上下文的重叠和分布至关重要。它影响节点如何处理和组织上下文中的数据。 + - Comfy dtype: INT + - Python dtype: int +- context_overlap + - context_overlap参数指定相邻上下文窗口之间的重叠量,这对于确保连续性并减少数据覆盖中的间隙很重要。它是节点在跨上下文维护数据完整性能力的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- context_schedule + - context_schedule参数概述了处理上下文的时间表,这对于确定上下文操作的顺序和时间至关重要。它是节点有效协调上下文工作流程的能力的组成部分。 + - Comfy dtype: ContextSchedules.LEGACY_UNIFORM_SCHEDULE_LIST + - Python dtype: ContextSchedules +- closed_loop + - closed_loop参数指示上下文处理是否应在闭环中运行,这对于在上下文处理中建立循环模式非常重要。它影响节点管理重复上下文任务的方法。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- fuse_method + - fuse_method参数确定融合上下文的方法,当处理多个上下文时,这对于优化节点的性能可能很重要。它提供了在节点操作中如何组合上下文的灵活性。 + - Comfy dtype: ContextFuseMethod.LIST + - Python dtype: ContextFuseMethod +- use_on_equal_length + - use_on_equal_length参数指定当上下文长度相等时是否应采取特定行动,影响节点在上下文管理中的决策过程。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- start_percent + - start_percent参数设置上下文处理应开始的百分比,这可以影响数据集中上下文的起始点。 + - Comfy dtype: FLOAT + - Python dtype: float +- guarantee_steps + - guarantee_steps参数确保在上下文处理中至少采取一定数量的步骤,这对于保持节点在提供一致结果方面的可靠性至关重要。 + - Comfy dtype: INT + - Python dtype: int +- prev_context + - prev_context参数允许将先前的上下文选项纳入当前操作,使节点能够基于现有的上下文配置进行构建。 + - Comfy dtype: CONTEXT_OPTIONS + - Python dtype: ContextOptionsGroup +- view_opts + - view_opts参数为查看上下文提供选项,这对于在节点操作中展示和分析上下文数据可能很重要。 + - Comfy dtype: VIEW_OPTS + - Python dtype: ContextOptions + +# Output types +- CONTEXT_OPTS + - CONTEXT_OPTS输出代表了节点生成的配置上下文选项,包含了将指导后续上下文处理的参数和设置。 + - Comfy dtype: CONTEXT_OPTIONS + - Python dtype: ContextOptions + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LegacyLoopedUniformContextOptionsNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'context_length': ('INT', {'default': 16, 'min': 1, 'max': LENGTH_MAX}), 'context_stride': ('INT', {'default': 1, 'min': 1, 'max': STRIDE_MAX}), 'context_overlap': ('INT', {'default': 4, 'min': 0, 'max': OVERLAP_MAX}), 'context_schedule': (ContextSchedules.LEGACY_UNIFORM_SCHEDULE_LIST,), 'closed_loop': ('BOOLEAN', {'default': False})}, 'optional': {'fuse_method': (ContextFuseMethod.LIST, {'default': ContextFuseMethod.FLAT}), 'use_on_equal_length': ('BOOLEAN', {'default': False}), 'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'guarantee_steps': ('INT', {'default': 1, 'min': 0, 'max': BIGMAX}), 'prev_context': ('CONTEXT_OPTIONS',), 'view_opts': ('VIEW_OPTS',)}} + RETURN_TYPES = ('CONTEXT_OPTIONS',) + RETURN_NAMES = ('CONTEXT_OPTS',) + CATEGORY = '' + FUNCTION = 'create_options' + + def create_options(self, fuse_method: str=ContextFuseMethod.FLAT, context_schedule: str=None, **kwargs): + return LoopedUniformContextOptionsNode.create_options(self, fuse_method=fuse_method, **kwargs) +``` \ No newline at end of file diff --git a/docs/ADE_BatchedContextOptions.md b/docs/ADE_BatchedContextOptions.md new file mode 100644 index 0000000..d6c0497 --- /dev/null +++ b/docs/ADE_BatchedContextOptions.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: BatchedContextOptionsNode +- Category: Animate Diff 🎭🅐🅓/context opts +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +BatchedContextOptionsNode旨在管理和生成动画序列的上下文选项。它提供了一种结构化的方法来定义每个上下文的长度、起始百分比和保证步骤,确保动画工作流程的连贯性和效率。 + +# Input types +## Required +- context_length + - context_length参数指定上下文窗口的持续时间,这对于确定每个动画段的范围至关重要。它直接影响节点分段动画时间线的能力。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- start_percent + - start_percent参数指定动画序列中上下文的起始点,允许微调动画的初始焦点。它通过控制每个上下文的起始位置,在整体动画策略中扮演重要角色。 + - Comfy dtype: FLOAT + - Python dtype: float +- guarantee_steps + - guarantee_steps参数确保每个上下文至少处理的步数,提供防止过早终止的保护。它对于维护动画序列的完整性很重要。 + - Comfy dtype: INT + - Python dtype: int +- prev_context + - prev_context参数允许延续或修改现有的上下文选项,使节点能够在之前的状态上构建。这对于维护动画过程的连续性至关重要。 + - Comfy dtype: CONTEXT_OPTIONS + - Python dtype: ContextOptionsGroup + +# Output types +- CONTEXT_OPTS + - 输出CONTEXT_OPTS代表由节点生成或更新的上下文选项集合。这些选项对于指导动画过程中的后续步骤至关重要。 + - Comfy dtype: CONTEXT_OPTIONS + - Python dtype: ContextOptionsGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchedContextOptionsNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'context_length': ('INT', {'default': 16, 'min': 1, 'max': LENGTH_MAX})}, 'optional': {'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'guarantee_steps': ('INT', {'default': 1, 'min': 0, 'max': BIGMAX}), 'prev_context': ('CONTEXT_OPTIONS',)}} + RETURN_TYPES = ('CONTEXT_OPTIONS',) + RETURN_NAMES = ('CONTEXT_OPTS',) + CATEGORY = 'Animate Diff 🎭🅐🅓/context opts' + FUNCTION = 'create_options' + + def create_options(self, context_length: int, start_percent: float=0.0, guarantee_steps: int=1, prev_context: ContextOptionsGroup=None): + if prev_context is None: + prev_context = ContextOptionsGroup() + prev_context = prev_context.clone() + context_options = ContextOptions(context_length=context_length, context_overlap=0, context_schedule=ContextSchedules.BATCHED, start_percent=start_percent, guarantee_steps=guarantee_steps) + prev_context.add(context_options) + return (prev_context,) +``` \ No newline at end of file diff --git a/docs/ADE_CustomCFG.md b/docs/ADE_CustomCFG.md new file mode 100644 index 0000000..fe98723 --- /dev/null +++ b/docs/ADE_CustomCFG.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: CustomCFGNode +- Category: Animate Diff 🎭🅐🅓/sample settings +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +CustomCFGNode 是一个用于创建动画和采样设置的自定义控制流图(CFG)的节点。它允许用户定义具有特定多值配置的关键帧,这些配置决定了采样过程的行为。该节点为用户提供了一个高级接口,使用户能够自定义动画流程,而无需深入了解底层模型操作的细节。 + +# Input types +## Required +- cfg_multival + - cfg_multival 参数对于在动画中定义特定关键帧的多值配置至关重要。它决定了关键帧的属性如何影响采样过程。此参数对于实现所需的动画效果和控制生成样本中的可变性至关重要。 + - Comfy dtype: MULTIVAL + - Python dtype: Union[float, torch.Tensor] + +# Output types +- CUSTOM_CFG + - 输出 CUSTOM_CFG 表示已自定义的关键帧组,用于控制采样过程。它封装了多值配置及其对应的开始百分比,允许对动画的进展和不同样本的生成进行细粒度控制。 + - Comfy dtype: CUSTOM_CFG + - Python dtype: CustomCFGKeyframeGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CustomCFGNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'cfg_multival': ('MULTIVAL',)}} + RETURN_TYPES = ('CUSTOM_CFG',) + CATEGORY = 'Animate Diff 🎭🅐🅓/sample settings' + FUNCTION = 'create_custom_cfg' + + def create_custom_cfg(self, cfg_multival: Union[float, Tensor]): + keyframe = CustomCFGKeyframe(cfg_multival=cfg_multival) + cfg_custom = CustomCFGKeyframeGroup() + cfg_custom.add(keyframe) + return (cfg_custom,) +``` \ No newline at end of file diff --git a/docs/ADE_IterationOptsDefault.md b/docs/ADE_IterationOptsDefault.md new file mode 100644 index 0000000..b8b1e13 --- /dev/null +++ b/docs/ADE_IterationOptsDefault.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: IterationOptionsNode +- Category: Animate Diff 🎭🅐🅓/iteration opts +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +迭代选项节点类的 `create_iter_opts` 方法旨在为采样过程配置迭代设置。它允许用户指定迭代次数以及批次和种子的偏移量,这对于控制采样程序并确保生成多样化的输出至关重要。 + +# Input types +## Required +- iterations + - 参数 'iterations' 定义了采样过程将重复的次数。它是节点操作的一个基本方面,因为它直接影响生成的输出数量。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- iter_batch_offset + - 参数 'iter_batch_offset' 用于调整每次迭代的批次索引。它在采样过程中发挥作用,允许生成的输出序列中存在变化。 + - Comfy dtype: INT + - Python dtype: int +- iter_seed_offset + - 参数 'iter_seed_offset' 指定了每次迭代中使用的种子的偏移量。通过改变每次迭代的随机数生成的起始点,这可以在采样中引入多样性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- ITERATION_OPTS + - 输出 'ITERATION_OPTS' 表示采样过程的配置迭代选项。它封装了用户定义的设置,对于采样工作流中的后续步骤至关重要。 + - Comfy dtype: ITERATION_OPTS + - Python dtype: IterationOptions + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IterationOptionsNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'iterations': ('INT', {'default': 1, 'min': 1})}, 'optional': {'iter_batch_offset': ('INT', {'default': 0, 'min': 0, 'max': BIGMAX}), 'iter_seed_offset': ('INT', {'default': 0, 'min': BIGMIN, 'max': BIGMAX})}} + RETURN_TYPES = ('ITERATION_OPTS',) + CATEGORY = 'Animate Diff 🎭🅐🅓/iteration opts' + FUNCTION = 'create_iter_opts' + + def create_iter_opts(self, iterations: int, iter_batch_offset: int=0, iter_seed_offset: int=0): + iter_opts = IterationOptions(iterations=iterations, iter_batch_offset=iter_batch_offset, iter_seed_offset=iter_seed_offset) + return (iter_opts,) +``` \ No newline at end of file diff --git a/docs/ADE_IterationOptsFreeInit.md b/docs/ADE_IterationOptsFreeInit.md new file mode 100644 index 0000000..f7a2b31 --- /dev/null +++ b/docs/ADE_IterationOptsFreeInit.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: FreeInitOptionsNode +- Category: Animate Diff 🎭🅐🅓/iteration opts +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +FreeInitOptionsNode 旨在为动画过程创建迭代选项提供便利,专注于使用可定制的过滤器和参数对初始化阶段进行优化,以提高动画的质量和特性。 + +# Input types +## Required +- iterations + - 迭代次数对于确定动画过程的范围至关重要。它决定了过程将重复多少次,影响着动画的整体结果和细节水平。 + - Comfy dtype: INT + - Python dtype: int +- filter + - 过滤器参数对于应用特定类型的噪声至动画至关重要,它可以显著影响动画的风格化结果以及帧与帧之间过渡的平滑度。 + - Comfy dtype: FreeInitFilter.LIST + - Python dtype: Union[str, comfy.sample.FreeInitFilter] +- d_s + - d_s 参数在控制应用于动画的噪声的空间频率中起着关键作用,这可以影响最终输出的纹理和细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- d_t + - d_t 参数对于调整噪声的时间频率很重要,它影响着噪声随时间的变化以及对动画动态的贡献。 + - Comfy dtype: FLOAT + - Python dtype: float +- n_butterworth + - n_butterworth 参数对于定义要使用的巴特沃斯滤波器的数量很重要,它可以细化噪声的质量及其对动画清晰度的影响。 + - Comfy dtype: INT + - Python dtype: int +- sigma_step + - sigma_step 参数对于确定应用 sigma 值的步骤至关重要,它可以影响整个动画中噪声的强度和进展。 + - Comfy dtype: INT + - Python dtype: int +- apply_to_1st_iter + - apply_to_1st_iter 标志对于决定是否将初始化设置应用于第一次迭代很重要。这可以影响动画的起始点及其初始外观。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- init_type + - init_type 参数决定了用于动画的初始化方法,这可以显著改变动画的起始特性和整个动画过程的行为。 + - Comfy dtype: FreeInitOptions.LIST + - Python dtype: str +## Optional +- iter_batch_offset + - iter_batch_offset 参数虽然是可选的,但可以用来调整迭代的批次偏移量,这有助于管理动画帧的顺序及其处理顺序。 + - Comfy dtype: INT + - Python dtype: int +- iter_seed_offset + - iter_seed_offset 参数也是可选的,允许调整迭代的种子偏移量,这可以在动画序列中引入变化,并影响输出的随机性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- iteration_options + - 此节点生成的迭代选项对于指导动画过程的后续步骤至关重要,为帧的生成和优化设定了基础。 + - Comfy dtype: ITERATION_OPTS + - Python dtype: FreeInitOptions + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FreeInitOptionsNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'iterations': ('INT', {'default': 2, 'min': 1}), 'filter': (FreeInitFilter.LIST,), 'd_s': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'd_t': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'n_butterworth': ('INT', {'default': 4, 'min': 1, 'max': 100}), 'sigma_step': ('INT', {'default': 999, 'min': 1, 'max': 999}), 'apply_to_1st_iter': ('BOOLEAN', {'default': False}), 'init_type': (FreeInitOptions.LIST,)}, 'optional': {'iter_batch_offset': ('INT', {'default': 0, 'min': 0, 'max': BIGMAX}), 'iter_seed_offset': ('INT', {'default': 1, 'min': BIGMIN, 'max': BIGMAX})}} + RETURN_TYPES = ('ITERATION_OPTS',) + CATEGORY = 'Animate Diff 🎭🅐🅓/iteration opts' + FUNCTION = 'create_iter_opts' + + def create_iter_opts(self, iterations: int, filter: str, d_s: float, d_t: float, n_butterworth: int, sigma_step: int, apply_to_1st_iter: bool, init_type: str, iter_batch_offset: int=0, iter_seed_offset: int=1): + iter_opts = FreeInitOptions(iterations=iterations, step=sigma_step, apply_to_1st_iter=apply_to_1st_iter, filter=filter, d_s=d_s, d_t=d_t, n=n_butterworth, init_type=init_type, iter_batch_offset=iter_batch_offset, iter_seed_offset=iter_seed_offset) + return (iter_opts,) +``` \ No newline at end of file diff --git a/docs/ADE_LoopedUniformContextOptions.md b/docs/ADE_LoopedUniformContextOptions.md new file mode 100644 index 0000000..73dd1e3 --- /dev/null +++ b/docs/ADE_LoopedUniformContextOptions.md @@ -0,0 +1,81 @@ +# Documentation +- Class name: LoopedUniformContextOptionsNode +- Category: Animate Diff 🎭🅐🅓/context opts +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +LoopedUniformContextOptionsNode旨在为动画目的生成一系列上下文选项。它根据给定的参数创建基于上下文的均匀分布,确保动画帧的一致流动。该节点特别适用于创建动画循环,其中均匀性和连续性至关重要。 + +# Input types +## Required +- context_length + - context_length参数决定了动画序列中每个上文的长度。它对于定义每个上下文的范围至关重要,并影响动画的整体结构。 + - Comfy dtype: INT + - Python dtype: int +- context_stride + - context_stride参数指定连续上下文之间的步长。它影响每个上下文与其邻居的关联程度,影响动画序列的连贯性。 + - Comfy dtype: INT + - Python dtype: int +- context_overlap + - context_overlap参数定义了相邻上下文之间的重叠量。这对于确保动画中上下文之间的平滑过渡和保持视觉连续性很重要。 + - Comfy dtype: INT + - Python dtype: int +- closed_loop + - closed_loop参数指示动画是否应在最后一个上下文之后循环回到开头。这可以用来创建无缝、重复的动画。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- fuse_method + - fuse_method参数决定了动画中上下文是如何融合在一起的。它可以影响上下文的混合和合并,影响动画的最终外观。 + - Comfy dtype: ContextFuseMethod.LIST + - Python dtype: str +- use_on_equal_length + - use_on_equal_length参数指定是否仅在上下文的长度符合特定条件时才应使用上下文。这可以用来根据特定标准控制上下文的应用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- start_percent + - start_percent参数定义了动画序列中上下文的起始百分比。它用于控制每个上下文开始的时间。 + - Comfy dtype: FLOAT + - Python dtype: float +- guarantee_steps + - guarantee_steps参数确保每个上下文在动画中至少显示一定数量的步骤。这有助于保持每个上下文在序列中的可见性和影响力。 + - Comfy dtype: INT + - Python dtype: int +- view_opts + - view_opts参数提供了查看动画的选项。它可以包括影响动画显示或渲染的设置。 + - Comfy dtype: VIEW_OPTS + - Python dtype: ContextOptions +- prev_context + - prev_context参数允许延续之前的上下文序列。当扩展或修改现有的动画序列时使用。 + - Comfy dtype: CONTEXT_OPTIONS + - Python dtype: ContextOptionsGroup + +# Output types +- CONTEXT_OPTS + - 输出CONTEXT_OPTS提供了基于输入参数生成的一组结构化的上下文选项。这些选项可以直接用于动画过程。 + - Comfy dtype: CONTEXT_OPTIONS + - Python dtype: ContextOptionsGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoopedUniformContextOptionsNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'context_length': ('INT', {'default': 16, 'min': 1, 'max': LENGTH_MAX}), 'context_stride': ('INT', {'default': 1, 'min': 1, 'max': STRIDE_MAX}), 'context_overlap': ('INT', {'default': 4, 'min': 0, 'max': OVERLAP_MAX}), 'closed_loop': ('BOOLEAN', {'default': False})}, 'optional': {'fuse_method': (ContextFuseMethod.LIST,), 'use_on_equal_length': ('BOOLEAN', {'default': False}), 'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'guarantee_steps': ('INT', {'default': 1, 'min': 0, 'max': BIGMAX}), 'prev_context': ('CONTEXT_OPTIONS',), 'view_opts': ('VIEW_OPTS',)}} + RETURN_TYPES = ('CONTEXT_OPTIONS',) + RETURN_NAMES = ('CONTEXT_OPTS',) + CATEGORY = 'Animate Diff 🎭🅐🅓/context opts' + FUNCTION = 'create_options' + + def create_options(self, context_length: int, context_stride: int, context_overlap: int, closed_loop: bool, fuse_method: str=ContextFuseMethod.FLAT, use_on_equal_length=False, start_percent: float=0.0, guarantee_steps: int=1, view_opts: ContextOptions=None, prev_context: ContextOptionsGroup=None): + if prev_context is None: + prev_context = ContextOptionsGroup() + prev_context = prev_context.clone() + context_options = ContextOptions(context_length=context_length, context_stride=context_stride, context_overlap=context_overlap, context_schedule=ContextSchedules.UNIFORM_LOOPED, closed_loop=closed_loop, fuse_method=fuse_method, use_on_equal_length=use_on_equal_length, start_percent=start_percent, guarantee_steps=guarantee_steps, view_options=view_opts) + prev_context.add(context_options) + return (prev_context,) +``` \ No newline at end of file diff --git a/docs/ADE_LoopedUniformViewOptions.md b/docs/ADE_LoopedUniformViewOptions.md new file mode 100644 index 0000000..c33a6f4 --- /dev/null +++ b/docs/ADE_LoopedUniformViewOptions.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: LoopedUniformViewOptionsNode +- Category: Animate Diff 🎭🅐🅓/context opts/view opts +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +循环均匀视图选项节点旨在为循环动画生成一组均匀的视图选项。它提供了一种系统化的方法来定义闭环结构内视图的长度、步长和重叠,允许动画序列的可视化一致且连贯。 + +# Input types +## Required +- view_length + - 视图长度参数指定动画序列中每个视图的长度,这对于确定动画的整体范围和细节至关重要。它直接影响生成的帧数和循环视图的全面性。 + - Comfy dtype: INT + - Python dtype: int +- view_stride + - 视图步长参数定义动画中连续视图之间的间隔,影响帧与帧之间过渡的平滑度和连续性。它是创建连贯动画流程的重要因素。 + - Comfy dtype: INT + - Python dtype: int +- view_overlap + - 视图重叠参数确定循环中相邻视图之间的重叠程度,这对于保持视觉连续性并防止可能破坏观众体验的突然变化至关重要。 + - Comfy dtype: INT + - Python dtype: int +- closed_loop + - 闭环标志指示动画序列是否应形成一个闭环,这对于创建无缝过渡并确保动画可以无结束地连续循环播放至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- fuse_method + - 融合方法参数允许指定在组合视图时应用的融合技术,这可以提高动画的视觉质量和连贯性。 + - Comfy dtype: ContextFuseMethod.LIST + - Python dtype: str +- use_on_equal_length + - 当遇到等长视图时,use_on_equal_length参数决定是否应用特定条件,可能为某些场景优化动画。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- VIEW_OPTS + - VIEW_OPTS输出提供一组结构化的选项,定义循环动画视图的参数。这些选项包括长度、步长、重叠以及其他对动画执行和视觉结果至关重要的设置。 + - Comfy dtype: VIEW_OPTS + - Python dtype: ContextOptions + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoopedUniformViewOptionsNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'view_length': ('INT', {'default': 16, 'min': 1, 'max': LENGTH_MAX}), 'view_stride': ('INT', {'default': 1, 'min': 1, 'max': STRIDE_MAX}), 'view_overlap': ('INT', {'default': 4, 'min': 0, 'max': OVERLAP_MAX}), 'closed_loop': ('BOOLEAN', {'default': False})}, 'optional': {'fuse_method': (ContextFuseMethod.LIST,), 'use_on_equal_length': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('VIEW_OPTS',) + CATEGORY = 'Animate Diff 🎭🅐🅓/context opts/view opts' + FUNCTION = 'create_options' + + def create_options(self, view_length: int, view_overlap: int, view_stride: int, closed_loop: bool, fuse_method: str=ContextFuseMethod.PYRAMID, use_on_equal_length=False): + view_options = ContextOptions(context_length=view_length, context_stride=view_stride, context_overlap=view_overlap, context_schedule=ContextSchedules.UNIFORM_LOOPED, closed_loop=closed_loop, fuse_method=fuse_method, use_on_equal_length=use_on_equal_length) + return (view_options,) +``` \ No newline at end of file diff --git a/docs/ADE_MultivalDynamic.md b/docs/ADE_MultivalDynamic.md new file mode 100644 index 0000000..f5f129a --- /dev/null +++ b/docs/ADE_MultivalDynamic.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: MultivalDynamicNode +- Category: Animate Diff 🎭🅐🅓/multival +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +MultivalDynamicNode 类旨在动画框架中动态生成和操作多值数据。它是创建复杂动画的关键组件,允许用户指定一系列值,这些值可以应用于动画的不同方面,如角色运动或场景转换。该节点的功能围绕 'create_multival' 方法展开,该方法智能处理单个和可迭代输入值,并确保输出格式适合下游处理。 + +# Input types +## Required +- float_val + - 参数 'float_val' 对于定义节点将用于创建多值数据的基值或值序列至关重要。它既可以接受单个浮点数,也可以接受浮点数的可迭代对象,这在动画场景的不同方面提供了高度的灵活性。该参数对节点执行的影响很大,因为它直接影响输出值的范围和性质。 + - Comfy dtype: FLOAT + - Python dtype: Union[float, List[float]] +## Optional +- mask_optional + - 参数 'mask_optional' 用于将掩码应用于节点生成的多值数据。这是一个可选的张量,当提供时,允许在动画的不同元素上选择性地应用 'float_val'。这个参数通过启用条件或部分动画效果来增强节点的功能,为最终动画增添了深度。 + - Comfy dtype: MASK + - Python dtype: Optional[torch.Tensor] + +# Output types +- multival + - 输出 'multival' 表示已处理的多值数据,可供动画流水线使用。它是一个张量,包含了由 'float_val' 参数指定的动态值范围,可能会被 'mask_optional' 参数修改。这个输出很重要,因为它构成了进一步动画开发的基础,并且可以直接集成到渲染过程中。 + - Comfy dtype: MULTIVAL + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MultivalDynamicNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'float_val': ('FLOAT', {'default': 1.0, 'min': 0.0, 'step': 0.001})}, 'optional': {'mask_optional': ('MASK',)}} + RETURN_TYPES = ('MULTIVAL',) + CATEGORY = 'Animate Diff 🎭🅐🅓/multival' + FUNCTION = 'create_multival' + + def create_multival(self, float_val: Union[float, list[float]]=1.0, mask_optional: Tensor=None): + float_is_iterable = False + if isinstance(float_val, Iterable): + float_is_iterable = True + float_val = list(float_val) + if mask_optional is not None: + if len(float_val) < mask_optional.shape[0]: + float_val = float_val + float_val[-1] * (mask_optional.shape[0] - len(float_val)) + if mask_optional.shape[0] < len(float_val): + mask_optional = extend_to_batch_size(mask_optional, len(float_val)) + float_val = float_val[:mask_optional.shape[0]] + float_val: Tensor = torch.tensor(float_val).unsqueeze(-1).unsqueeze(-1) + if mask_optional is not None: + mask_optional = mask_optional.clone() + if float_is_iterable: + mask_optional = mask_optional[:] * float_val.to(mask_optional.dtype).to(mask_optional.device) + else: + mask_optional = mask_optional * float_val + return (mask_optional,) + else: + if not float_is_iterable: + return (float_val,) + float_len = float_val.shape[0] if float_is_iterable else 1 + shape = (float_len, 1, 1) + mask_optional = torch.ones(shape) + mask_optional = mask_optional[:] * float_val.to(mask_optional.dtype).to(mask_optional.device) + return (mask_optional,) +``` \ No newline at end of file diff --git a/docs/ADE_MultivalScaledMask.md b/docs/ADE_MultivalScaledMask.md new file mode 100644 index 0000000..132e615 --- /dev/null +++ b/docs/ADE_MultivalScaledMask.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: MultivalScaledMaskNode +- Category: Animate Diff 🎭🅐🅓/multival +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +MultivalScaledMaskNode 类旨在通过在指定范围内缩放给定的掩码张量来转换它。它根据所选的缩放类型应用线性转换或归一化,确保输出掩码适合在动画或可视化应用程序中进行进一步处理。 + +# Input types +## Required +- min_float_val + - 最小浮点值参数定义了掩码张量缩放范围的下限。它在设置掩码的缩放比例中起着至关重要的作用,确保缩放后的最小值如指定的那样。 + - Comfy dtype: FLOAT + - Python dtype: float +- max_float_val + - 最大浮点值参数设置了掩码张量缩放的上限。它对于确定掩码的缩放比例至关重要,确保缩放后的最大值与期望的最大值一致。 + - Comfy dtype: FLOAT + - Python dtype: float +- mask + - 掩码参数是一个张量,它将根据指定的最小和最大浮点值进行缩放。它是节点操作的核心元素,因为缩放直接应用于此张量以实现所需的多值效果。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- scaling + - 缩放参数确定要应用于掩码张量的缩放类型。它可以是绝对的或相对的,影响如何在指定范围内调整掩码值。 + - Comfy dtype: ScaleType.LIST + - Python dtype: str + +# Output types +- multival + - MultivalScaledMaskNode 的输出是一个多值张量,代表缩放后的掩码。它非常重要,因为它是节点操作的直接结果,可用于后续的动画或可视化任务。 + - Comfy dtype: MULTIVAL + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MultivalScaledMaskNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'min_float_val': ('FLOAT', {'default': 0.0, 'min': 0.0, 'step': 0.001}), 'max_float_val': ('FLOAT', {'default': 1.0, 'min': 0.0, 'step': 0.001}), 'mask': ('MASK',)}, 'optional': {'scaling': (ScaleType.LIST,)}} + RETURN_TYPES = ('MULTIVAL',) + CATEGORY = 'Animate Diff 🎭🅐🅓/multival' + FUNCTION = 'create_multival' + + def create_multival(self, min_float_val: float, max_float_val: float, mask: Tensor, scaling: str=ScaleType.ABSOLUTE): + if isinstance(min_float_val, Iterable): + raise ValueError(f'min_float_val must be type float (no lists allowed here), not {type(min_float_val).__name__}.') + if isinstance(max_float_val, Iterable): + raise ValueError(f'max_float_val must be type float (no lists allowed here), not {type(max_float_val).__name__}.') + if scaling == ScaleType.ABSOLUTE: + mask = linear_conversion(mask.clone(), new_min=min_float_val, new_max=max_float_val) + elif scaling == ScaleType.RELATIVE: + mask = normalize_min_max(mask.clone(), new_min=min_float_val, new_max=max_float_val) + else: + raise ValueError(f"scaling '{scaling}' not recognized.") + return MultivalDynamicNode.create_multival(self, mask_optional=mask) +``` \ No newline at end of file diff --git a/docs/ADE_NoiseLayerAdd.md b/docs/ADE_NoiseLayerAdd.md new file mode 100644 index 0000000..7d48ed5 --- /dev/null +++ b/docs/ADE_NoiseLayerAdd.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: NoiseLayerAddNode +- Category: Animate Diff 🎭🅐🅓/noise layers +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +NoiseLayerAddNode 类旨在管理向动画中添加噪声层。它负责根据指定的参数创建和组织噪声层,确保将噪声无缝集成到动画过程中,以增强多样性和细节。 + +# Input types +## Required +- batch_offset + - 批次偏移参数对于管理动画中的噪声层序列至关重要。它决定了噪声应用的起始点,从而影响整个动画中噪声的分布和模式。 + - Comfy dtype: INT + - Python dtype: int +- noise_type + - 噪声类型参数定义了要添加到动画中的噪声类别。它是塑造噪声视觉特征的关键决定因素,影响动画输出的最终美感。 + - Comfy dtype: NoiseLayerType.LIST + - Python dtype: str +- seed_gen_override + - 种子生成覆盖参数允许自定义噪声生成过程。它提供了一种控制噪声模式的随机性和独特性的方法,为动画的噪声特性提供了一层微调。 + - Comfy dtype: SeedNoiseGeneration.LIST_WITH_OVERRIDE + - Python dtype: str +- seed_offset + - 种子偏移参数在调整噪声模式的起始点方面起着重要作用。它可以显著改变初始噪声配置,从而导致动画噪声呈现的变化。 + - Comfy dtype: INT + - Python dtype: int +- noise_weight + - 噪声权重参数调整被添加到动画中的噪声强度。它是控制噪声效果显著性的一个关键因素,允许将噪声平衡地集成到动画中。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- prev_noise_layers + - 之前的噪声层参数指的是现有的噪声层集合。它很重要,因为它为新噪声层的集成提供了上下文,确保了动画噪声结构内的连续性和一致性。 + - Comfy dtype: NOISE_LAYERS + - Python dtype: Optional[NoiseLayerGroup] +- mask_optional + - 掩码可选参数用于为噪声层定义一个可选的掩码。它可以被用来选择性地将噪声应用于动画的特定区域,提供对噪声分布的一定程度的控制。 + - Comfy dtype: MASK + - Python dtype: Optional[torch.Tensor] +- seed_override + - 种子覆盖参数允许手动指定噪声生成的种子。它特别适用于复制或自定义动画中的特定噪声模式。 + - Comfy dtype: INT + - Python dtype: Optional[int] + +# Output types +- noise_layers + - 输出噪声层表示添加新噪声层后更新的噪声层集合。这个输出很重要,因为它反映了动画噪声结构的当前状态,为进一步的处理或分析提供了基础。 + - Comfy dtype: NOISE_LAYERS + - Python dtype: NoiseLayerGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class NoiseLayerAddNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'batch_offset': ('INT', {'default': 0, 'min': 0, 'max': BIGMAX}), 'noise_type': (NoiseLayerType.LIST,), 'seed_gen_override': (SeedNoiseGeneration.LIST_WITH_OVERRIDE,), 'seed_offset': ('INT', {'default': 0, 'min': BIGMIN, 'max': BIGMAX}), 'noise_weight': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 10.0, 'step': 0.001})}, 'optional': {'prev_noise_layers': ('NOISE_LAYERS',), 'mask_optional': ('MASK',), 'seed_override': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615, 'forceInput': True})}} + RETURN_TYPES = ('NOISE_LAYERS',) + CATEGORY = 'Animate Diff 🎭🅐🅓/noise layers' + FUNCTION = 'create_layers' + + def create_layers(self, batch_offset: int, noise_type: str, seed_gen_override: str, seed_offset: int, noise_weight: float, prev_noise_layers: NoiseLayerGroup=None, mask_optional: Tensor=None, seed_override: int=None): + if prev_noise_layers is None: + prev_noise_layers = NoiseLayerGroup() + prev_noise_layers = prev_noise_layers.clone() + layer = NoiseLayerAdd(noise_type=noise_type, batch_offset=batch_offset, seed_gen_override=seed_gen_override, seed_offset=seed_offset, seed_override=seed_override, mask=mask_optional, noise_weight=noise_weight) + prev_noise_layers.add_to_start(layer) + return (prev_noise_layers,) +``` \ No newline at end of file diff --git a/docs/ADE_NoiseLayerAddWeighted.md b/docs/ADE_NoiseLayerAddWeighted.md new file mode 100644 index 0000000..ce9109f --- /dev/null +++ b/docs/ADE_NoiseLayerAddWeighted.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: NoiseLayerAddWeightedNode +- Category: Animate Diff 🎭🅐🅓/noise layers +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +NoiseLayerAddWeightedNode 类旨在以加权方式操作和引入噪声到系统中。它是动画过程中的一个关键组件,允许微调噪声特征。该节点的主要功能是向现有组中添加噪声层,确保新噪声元素与现有元素的平衡集成,从而增强动画的整体多样性和复杂性。 + +# Input types +## Required +- batch_offset + - batch_offset 参数对于管理噪声层的处理顺序至关重要。它影响动画中噪声层的整体结构和组织,确保每个层在序列中正确定位。 + - Comfy dtype: INT + - Python dtype: int +- noise_type + - noise_type 参数定义了要添加到动画中的噪声类型。它在确定噪声的视觉和结构方面起着重要作用,从而影响动画的最终输出。 + - Comfy dtype: NoiseLayerType.LIST + - Python dtype: str +- seed_gen_override + - seed_gen_override 参数允许定制噪声生成过程。它对于创建独特的噪声模式和确保动画随机元素所需的随机性很重要。 + - Comfy dtype: SeedNoiseGeneration.LIST_WITH_OVERRIDE + - Python dtype: str +- seed_offset + - seed_offset 参数对于控制噪声生成中的随机性至关重要。它确保每个噪声层都有独特且不可预测的质量,有助于增加动画的多样性。 + - Comfy dtype: INT + - Python dtype: int +- noise_weight + - noise_weight 参数调整添加到动画中的噪声强度。它是实现所需视觉效果的关键因素,并确保噪声与动画的基本元素保持平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- balance_multiplier + - balance_multiplier 参数用于微调现有噪声与新增噪声之间的平衡。它确保整体噪声效果和谐并融入动画中。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- prev_noise_layers + - prev_noise_layers 参数是之前生成的噪声层的可选组。它允许在现有噪声结构的基础上继续和构建,保持动画的一致性和连贯性。 + - Comfy dtype: NOISE_LAYERS + - Python dtype: Optional[NoiseLayerGroup] +- mask_optional + - mask_optional 参数是一个可选的张量,可以用来选择性地将噪声应用于动画的特定区域。它提供了对噪声效果最突出位置的控制。 + - Comfy dtype: MASK + - Python dtype: Optional[torch.Tensor] +- seed_override + - seed_override 参数为噪声生成中使用的种子提供了一个可选的覆盖。它可以用来确保可重复性或将特定的噪声模式引入到动画中。 + - Comfy dtype: INT + - Python dtype: Optional[int] + +# Output types +- noise_layers + - NoiseLayerAddWeightedNode 的输出是修改后的噪声层组,其中包括新添加的加权噪声层。这个输出很重要,因为它构成了进一步处理和动画开发的基础。 + - Comfy dtype: NOISE_LAYERS + - Python dtype: NoiseLayerGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class NoiseLayerAddWeightedNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'batch_offset': ('INT', {'default': 0, 'min': 0, 'max': BIGMAX}), 'noise_type': (NoiseLayerType.LIST,), 'seed_gen_override': (SeedNoiseGeneration.LIST_WITH_OVERRIDE,), 'seed_offset': ('INT', {'default': 0, 'min': BIGMIN, 'max': BIGMAX}), 'noise_weight': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'balance_multiplier': ('FLOAT', {'default': 1.0, 'min': 0.0, 'step': 0.001})}, 'optional': {'prev_noise_layers': ('NOISE_LAYERS',), 'mask_optional': ('MASK',), 'seed_override': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615, 'forceInput': True})}} + RETURN_TYPES = ('NOISE_LAYERS',) + CATEGORY = 'Animate Diff 🎭🅐🅓/noise layers' + FUNCTION = 'create_layers' + + def create_layers(self, batch_offset: int, noise_type: str, seed_gen_override: str, seed_offset: int, noise_weight: float, balance_multiplier: float, prev_noise_layers: NoiseLayerGroup=None, mask_optional: Tensor=None, seed_override: int=None): + if prev_noise_layers is None: + prev_noise_layers = NoiseLayerGroup() + prev_noise_layers = prev_noise_layers.clone() + layer = NoiseLayerAddWeighted(noise_type=noise_type, batch_offset=batch_offset, seed_gen_override=seed_gen_override, seed_offset=seed_offset, seed_override=seed_override, mask=mask_optional, noise_weight=noise_weight, balance_multiplier=balance_multiplier) + prev_noise_layers.add_to_start(layer) + return (prev_noise_layers,) +``` \ No newline at end of file diff --git a/docs/ADE_NoiseLayerReplace.md b/docs/ADE_NoiseLayerReplace.md new file mode 100644 index 0000000..f73616b --- /dev/null +++ b/docs/ADE_NoiseLayerReplace.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: NoiseLayerReplaceNode +- Category: Animate Diff 🎭🅐🅓/noise layers +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +NoiseLayerReplaceNode旨在为动画目的在模型中操作和生成噪声层。它根据指定的参数用新的噪声替换现有的噪声,允许动态和多样化的动画效果。 + +# Input types +## Required +- batch_offset + - 批量偏移参数对于管理动画中的噪声层序列至关重要。它决定了数据批次中的起始点,这对于确保正确操作层非常关键。 + - Comfy dtype: INT + - Python dtype: int +- noise_type + - 噪声类型参数决定了将创建的噪声层的类型。它是整体噪声生成过程中的一个关键因素,影响噪声的特性和最终动画效果。 + - Comfy dtype: NoiseLayerType.LIST + - Python dtype: str +- seed_gen_override + - 种子生成覆盖参数允许定制噪声层的种子生成过程。当目标是在动画中实现特定的噪声模式或效果时,这可能特别重要。 + - Comfy dtype: SeedNoiseGeneration.LIST_WITH_OVERRIDE + - Python dtype: str +- seed_offset + - 种子偏移参数用于调整用于噪声生成的种子值。这可以显著影响生成的噪声模式,提供一种在动画中引入变化的方法。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- prev_noise_layers + - 先前的噪声层参数用于指定将被替换或修改的现有噪声层。它在动画中噪声的连续性和演变中扮演着关键角色。 + - Comfy dtype: NOISE_LAYERS + - Python dtype: NoiseLayerGroup +- mask_optional + - 掩码可选参数提供了一种方式,可以选择性地将噪声层应用于动画的某些部分。它可以用于引入针对性效果或保护某些区域免受噪声应用的影响。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- seed_override + - 种子覆盖参数允许手动控制用于噪声生成的种子值。这对于微调动画中噪声的特定方面可能特别有用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- noise_layers + - 噪声层输出包含已创建或修改并添加到动画中的噪声层。这些层对于动画序列的视觉外观和行为至关重要。 + - Comfy dtype: NOISE_LAYERS + - Python dtype: NoiseLayerGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class NoiseLayerReplaceNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'batch_offset': ('INT', {'default': 0, 'min': 0, 'max': BIGMAX}), 'noise_type': (NoiseLayerType.LIST,), 'seed_gen_override': (SeedNoiseGeneration.LIST_WITH_OVERRIDE,), 'seed_offset': ('INT', {'default': 0, 'min': BIGMIN, 'max': BIGMAX})}, 'optional': {'prev_noise_layers': ('NOISE_LAYERS',), 'mask_optional': ('MASK',), 'seed_override': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615, 'forceInput': True})}} + RETURN_TYPES = ('NOISE_LAYERS',) + CATEGORY = 'Animate Diff 🎭🅐🅓/noise layers' + FUNCTION = 'create_layers' + + def create_layers(self, batch_offset: int, noise_type: str, seed_gen_override: str, seed_offset: int, prev_noise_layers: NoiseLayerGroup=None, mask_optional: Tensor=None, seed_override: int=None): + if prev_noise_layers is None: + prev_noise_layers = NoiseLayerGroup() + prev_noise_layers = prev_noise_layers.clone() + layer = NoiseLayerReplace(noise_type=noise_type, batch_offset=batch_offset, seed_gen_override=seed_gen_override, seed_offset=seed_offset, seed_override=seed_override, mask=mask_optional) + prev_noise_layers.add_to_start(layer) + return (prev_noise_layers,) +``` \ No newline at end of file diff --git a/docs/ADE_StandardStaticContextOptions.md b/docs/ADE_StandardStaticContextOptions.md new file mode 100644 index 0000000..5cd2de0 --- /dev/null +++ b/docs/ADE_StandardStaticContextOptions.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: StandardStaticContextOptionsNode +- Category: Animate Diff 🎭🅐🅓/context opts +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +StandardStaticContextOptionsNode的`create_options`方法旨在为动画过程生成和配置上下文选项。它允许自定义上下文长度、重叠以及其他影响动画如何在帧之间区分的参数。此方法在设置动画上下文方面至关重要,确保生成的帧是连贯且具有上下文感知的。 + +# Input types +## Required +- context_length + - 参数`context_length`指定每个动画步骤中要考虑的上下文帧数。这对于确定每个帧对动画结果的影响范围至关重要。 + - Comfy dtype: INT + - Python dtype: int +- context_overlap + - 参数`context_overlap`定义了动画序列中相邻上下文之间的重叠。这对于确保动画中的平滑过渡和连续性具有重要意义。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- fuse_method + - 参数`fuse_method`确定动画过程中不同上下文如何合并或融合。它可能影响动画的整体连贯性和风格一致性。 + - Comfy dtype: str + - Python dtype: str +- use_on_equal_length + - 标志`use_on_equal_length`指示在动画帧长度相等时是否应该应用上下文选项。它可能影响动画中帧的分布。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- start_percent + - 参数`start_percent`设置上下文选项的起始百分比,这可能影响动画开始整合这些选项的时间。 + - Comfy dtype: FLOAT + - Python dtype: float +- guarantee_steps + - 参数`guarantee_steps`确保在动画过程中至少应用上下文选项的最小步数,为动画过程提供稳定性。 + - Comfy dtype: INT + - Python dtype: int +- view_opts + - 参数`view_opts`允许自定义上下文中的视图选项,这可以改变动画的视觉呈现。 + - Comfy dtype: VIEW_OPTS + - Python dtype: ContextOptions +- prev_context + - 参数`prev_context`用于将先前的上下文选项带入新的上下文,保持动画序列的连续性。 + - Comfy dtype: CONTEXT_OPTIONS + - Python dtype: ContextOptionsGroup + +# Output types +- CONTEXT_OPTS + - 输出`CONTEXT_OPTS`提供了在动画过程的后续步骤中将使用的配置上下文选项。 + - Comfy dtype: CONTEXT_OPTIONS + - Python dtype: ContextOptionsGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class StandardStaticContextOptionsNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'context_length': ('INT', {'default': 16, 'min': 1, 'max': LENGTH_MAX}), 'context_overlap': ('INT', {'default': 4, 'min': 0, 'max': OVERLAP_MAX})}, 'optional': {'fuse_method': (ContextFuseMethod.LIST_STATIC,), 'use_on_equal_length': ('BOOLEAN', {'default': False}), 'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'guarantee_steps': ('INT', {'default': 1, 'min': 0, 'max': BIGMAX}), 'prev_context': ('CONTEXT_OPTIONS',), 'view_opts': ('VIEW_OPTS',)}} + RETURN_TYPES = ('CONTEXT_OPTIONS',) + RETURN_NAMES = ('CONTEXT_OPTS',) + CATEGORY = 'Animate Diff 🎭🅐🅓/context opts' + FUNCTION = 'create_options' + + def create_options(self, context_length: int, context_overlap: int, fuse_method: str=ContextFuseMethod.PYRAMID, use_on_equal_length=False, start_percent: float=0.0, guarantee_steps: int=1, view_opts: ContextOptions=None, prev_context: ContextOptionsGroup=None): + if prev_context is None: + prev_context = ContextOptionsGroup() + prev_context = prev_context.clone() + context_options = ContextOptions(context_length=context_length, context_stride=None, context_overlap=context_overlap, context_schedule=ContextSchedules.STATIC_STANDARD, fuse_method=fuse_method, use_on_equal_length=use_on_equal_length, start_percent=start_percent, guarantee_steps=guarantee_steps, view_options=view_opts) + prev_context.add(context_options) + return (prev_context,) +``` \ No newline at end of file diff --git a/docs/ADE_StandardStaticViewOptions.md b/docs/ADE_StandardStaticViewOptions.md new file mode 100644 index 0000000..274b4bf --- /dev/null +++ b/docs/ADE_StandardStaticViewOptions.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: StandardStaticViewOptionsNode +- Category: Animate Diff 🎭🅐🅓/context opts/view opts +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +StandardStaticViewOptionsNode旨在为动画上下文中的静态视图生成一组选项。它允许自定义视图长度和重叠,确保动画体验的无缝和连贯性。该节点在定义动画中不同帧或片段如何呈现给观众方面起着关键作用。 + +# Input types +## Required +- view_length + - view_length参数决定了每个视图中显示的帧或元素的数量。它对于设置动画的范围和细节级别至关重要,影响整体的观看体验。 + - Comfy dtype: INT + - Python dtype: int +- view_overlap + - view_overlap参数指定相邻视图之间的重叠程度。这对于保持连续性很重要,并且可以帮助在动画的不同部分之间创建平滑的过渡。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- fuse_method + - fuse_method参数定义了在动画中组合或融合不同视图所使用的方法。它可能显著影响最终的外观以及通过动画序列传达信息的方式。 + - Comfy dtype: ContextFuseMethod.LIST + - Python dtype: str + +# Output types +- view_options + - view_options输出提供了一组结构化的选项,这些选项决定了动画中视图的配置方式。它封装了用户设置的参数,对动画的执行至关重要。 + - Comfy dtype: VIEW_OPTS + - Python dtype: ContextOptions + +# Usage tips +- Infra type: CPU + +# Source code +``` +class StandardStaticViewOptionsNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'view_length': ('INT', {'default': 16, 'min': 1, 'max': LENGTH_MAX}), 'view_overlap': ('INT', {'default': 4, 'min': 0, 'max': OVERLAP_MAX})}, 'optional': {'fuse_method': (ContextFuseMethod.LIST,)}} + RETURN_TYPES = ('VIEW_OPTS',) + CATEGORY = 'Animate Diff 🎭🅐🅓/context opts/view opts' + FUNCTION = 'create_options' + + def create_options(self, view_length: int, view_overlap: int, fuse_method: str=ContextFuseMethod.FLAT): + view_options = ContextOptions(context_length=view_length, context_stride=None, context_overlap=view_overlap, context_schedule=ContextSchedules.STATIC_STANDARD, fuse_method=fuse_method) + return (view_options,) +``` \ No newline at end of file diff --git a/docs/ADE_StandardUniformContextOptions.md b/docs/ADE_StandardUniformContextOptions.md new file mode 100644 index 0000000..55e07c8 --- /dev/null +++ b/docs/ADE_StandardUniformContextOptions.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: StandardUniformContextOptionsNode +- Category: Animate Diff 🎭🅐🅓/context opts +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +StandardUniformContextOptionsNode 类的 `create_options` 方法旨在为动画和差异化任务生成一组上下文选项。它配置了控制动画过程粒度和连续性的上下文参数,如长度、步长和重叠。此方法在建立动画如何在不同帧或阶段进行差异化的框架中起着关键作用。 + +# Input types +## Required +- context_length + - 参数 `context_length` 定义了上下文将覆盖的帧或数据点的范围。它对于确定每个上下文选项对动画结果的影响范围至关重要。此参数直接影响细节水平和不同动画阶段之间过渡的平滑度。 + - Comfy dtype: INT + - Python dtype: int +- context_stride + - 参数 `context_stride` 指定连续上下文帧之间的间隔。它对动画过程的效率很重要,因为它影响新上下文信息的引入频率。这个步长设置可以优化性能和动画中所需细节水平之间的平衡。 + - Comfy dtype: INT + - Python dtype: int +- context_overlap + - 参数 `context_overlap` 确定连续上下文的重叠程度。这种重叠对于保持动画序列的连续性至关重要,确保从一个上下文平滑过渡到下一个上下文。在处理需要逐渐过渡而不是突然变化的复杂转换时,这一点尤其重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- fuse_method + - 参数 `fuse_method` 确定在动画中合并或融合不同上下文的策略。它在构建整体上下文的方式中起着重要作用,并且可以显著影响最终动画的连贯性以及不同元素在其中的交互方式。 + - Comfy dtype: ContextFuseMethod.LIST + - Python dtype: str +- use_on_equal_length + - 参数 `use_on_equal_length` 是一个布尔标志,设置后表示仅在上下文长度相等时才应用上下文选项。这在确保动画过程中的一致性时很重要,特别是处理不同长度的数据时。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- start_percent + - 参数 `start_percent` 决定上下文在动画时间轴上的起始点。它对于将上下文与动画中的特定时刻或事件对齐至关重要,允许精确的时间控制和与其他元素的同步。 + - Comfy dtype: FLOAT + - Python dtype: float +- guarantee_steps + - 参数 `guarantee_steps` 设置上下文将被应用的最小步数。它确保每个上下文在动画中有一个确定的持续时间,有助于整体结构和动画序列的可预测性。 + - Comfy dtype: INT + - Python dtype: int +- view_opts + - 参数 `view_opts` 允许定制上下文中的视图选项。它可以用来调整渲染设置或显示偏好等视觉方面,增强动画的展示效果。 + - Comfy dtype: VIEW_OPTS + - Python dtype: ContextOptions +- prev_context + - 参数 `prev_context` 指的是动画中使用的前一个上下文选项组。它对于保持动画的连续性和流动性很重要,尤其是在基于前一个上下文构建或从一个上下文过渡到另一个上下文时。 + - Comfy dtype: CONTEXT_OPTIONS + - Python dtype: ContextOptionsGroup + +# Output types +- CONTEXT_OPTS + - 输出 `CONTEXT_OPTS` 表示已配置并准备应用于动画的一组上下文选项。这些选项封装了定义动画如何随时间差异化和演变的参数,确保动画序列结构化和连贯。 + - Comfy dtype: CONTEXT_OPTIONS + - Python dtype: ContextOptionsGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class StandardUniformContextOptionsNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'context_length': ('INT', {'default': 16, 'min': 1, 'max': LENGTH_MAX}), 'context_stride': ('INT', {'default': 1, 'min': 1, 'max': STRIDE_MAX}), 'context_overlap': ('INT', {'default': 4, 'min': 0, 'max': OVERLAP_MAX})}, 'optional': {'fuse_method': (ContextFuseMethod.LIST,), 'use_on_equal_length': ('BOOLEAN', {'default': False}), 'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'guarantee_steps': ('INT', {'default': 1, 'min': 0, 'max': BIGMAX}), 'prev_context': ('CONTEXT_OPTIONS',), 'view_opts': ('VIEW_OPTS',)}} + RETURN_TYPES = ('CONTEXT_OPTIONS',) + RETURN_NAMES = ('CONTEXT_OPTS',) + CATEGORY = 'Animate Diff 🎭🅐🅓/context opts' + FUNCTION = 'create_options' + + def create_options(self, context_length: int, context_stride: int, context_overlap: int, fuse_method: str=ContextFuseMethod.PYRAMID, use_on_equal_length=False, start_percent: float=0.0, guarantee_steps: int=1, view_opts: ContextOptions=None, prev_context: ContextOptionsGroup=None): + if prev_context is None: + prev_context = ContextOptionsGroup() + prev_context = prev_context.clone() + context_options = ContextOptions(context_length=context_length, context_stride=context_stride, context_overlap=context_overlap, context_schedule=ContextSchedules.UNIFORM_STANDARD, closed_loop=False, fuse_method=fuse_method, use_on_equal_length=use_on_equal_length, start_percent=start_percent, guarantee_steps=guarantee_steps, view_options=view_opts) + prev_context.add(context_options) + return (prev_context,) +``` \ No newline at end of file diff --git a/docs/ADE_StandardUniformViewOptions.md b/docs/ADE_StandardUniformViewOptions.md new file mode 100644 index 0000000..3acae49 --- /dev/null +++ b/docs/ADE_StandardUniformViewOptions.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: StandardUniformViewOptionsNode +- Category: Animate Diff 🎭🅐🅓/context opts/view opts +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +StandardUniformViewOptionsNode 旨在为动画差异化生成一组统一的视图选项。它专注于为动画过程创建一种结构化的方法,确保动画过程中的一致性和统一性。该节点抽象了视图调度的复杂性,为用户提供了一种直接的方法来定义和应用视图参数。 + +# Input types +## Required +- view_length + - view_length 参数定义了动画序列中每个视图的长度。它对于确定每个单独视图的范围和细节至关重要,从而影响整体动画的质量和构成。 + - Comfy dtype: INT + - Python dtype: int +- view_stride + - view_stride 参数指定动画中连续视图之间的间隔。它在控制动画节奏和确保视图之间的过渡连贯且视觉上吸引人方面起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- view_overlap + - view_overlap 参数指示动画中相邻视图之间的重叠量。这对于创建无缝且平滑的动画体验很重要,其中视图之间的过渡不会突然。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- fuse_method + - fuse_method 参数确定在动画中融合视图时使用的方法。它在视图如何组合方面提供了灵活性,允许不同的视觉效果和对最终输出的创造性控制。 + - Comfy dtype: ContextFuseMethod.LIST + - Python dtype: str + +# Output types +- view_options + - view_options 输出提供了一组定义动画中视图特性的结构化选项。它封装了诸如视图长度、步长和重叠等参数,这些参数对于动画的执行和最终外观至关重要。 + - Comfy dtype: VIEW_OPTS + - Python dtype: ContextOptions + +# Usage tips +- Infra type: CPU + +# Source code +``` +class StandardUniformViewOptionsNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'view_length': ('INT', {'default': 16, 'min': 1, 'max': LENGTH_MAX}), 'view_stride': ('INT', {'default': 1, 'min': 1, 'max': STRIDE_MAX}), 'view_overlap': ('INT', {'default': 4, 'min': 0, 'max': OVERLAP_MAX})}, 'optional': {'fuse_method': (ContextFuseMethod.LIST,)}} + RETURN_TYPES = ('VIEW_OPTS',) + CATEGORY = 'Animate Diff 🎭🅐🅓/context opts/view opts' + FUNCTION = 'create_options' + + def create_options(self, view_length: int, view_overlap: int, view_stride: int, fuse_method: str=ContextFuseMethod.PYRAMID): + view_options = ContextOptions(context_length=view_length, context_stride=view_stride, context_overlap=view_overlap, context_schedule=ContextSchedules.UNIFORM_STANDARD, fuse_method=fuse_method) + return (view_options,) +``` \ No newline at end of file diff --git a/docs/ADE_ViewsOnlyContextOptions.md b/docs/ADE_ViewsOnlyContextOptions.md new file mode 100644 index 0000000..ea86433 --- /dev/null +++ b/docs/ADE_ViewsOnlyContextOptions.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: ViewAsContextOptionsNode +- Category: Animate Diff 🎭🅐🅓/context opts +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved.git + +ViewAsContextOptionsNode类的'create_options'方法旨在生成一组上下文选项,这些选项决定了视图的上下文如何处理和动画化。它允许自定义动画的开始百分比和保证步骤的数量,确保在不同上下文之间平滑渡。 + +# Input types +## Required +- view_opts_req + - 参数'view_opts_req'对于定义动画上下文所需的视图选项至关重要。它为上下文在动画框架内的解释和操作奠定了基础。 + - Comfy dtype: VIEW_OPTS + - Python dtype: ContextOptions +## Optional +- start_percent + - 参数'start_percent'指定了动画的开始百分比,允许用户控制动画的初始状态。这是一个可选参数,可以微调动画的开始。 + - Comfy dtype: FLOAT + - Python dtype: float +- guarantee_steps + - 参数'guarantee_steps'确保动画运行的最小步数,提供了一种保持动画连续性和稳定性的机制。 + - Comfy dtype: INT + - Python dtype: int +- prev_context + - 参数'prev_context'允许将先前的上下文选项包含到新的集合中,使方法能够在现有的上下文状态上构建,并促进更复杂或分层的动画设置。 + - Comfy dtype: CONTEXT_OPTIONS + - Python dtype: ContextOptionsGroup + +# Output types +- CONTEXT_OPTS + - 输出'CONTEXT_OPTS'代表新创建或更新的上下文选项集,这些选项将用于影响随后的动画或处理步骤。 + - Comfy dtype: CONTEXT_OPTIONS + - Python dtype: ContextOptionsGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ViewAsContextOptionsNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'view_opts_req': ('VIEW_OPTS',)}, 'optional': {'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'guarantee_steps': ('INT', {'default': 1, 'min': 0, 'max': BIGMAX}), 'prev_context': ('CONTEXT_OPTIONS',)}} + RETURN_TYPES = ('CONTEXT_OPTIONS',) + RETURN_NAMES = ('CONTEXT_OPTS',) + CATEGORY = 'Animate Diff 🎭🅐🅓/context opts' + FUNCTION = 'create_options' + + def create_options(self, view_opts_req: ContextOptions, start_percent: float=0.0, guarantee_steps: int=1, prev_context: ContextOptionsGroup=None): + if prev_context is None: + prev_context = ContextOptionsGroup() + prev_context = prev_context.clone() + context_options = ContextOptions(context_schedule=ContextSchedules.VIEW_AS_CONTEXT, start_percent=start_percent, guarantee_steps=guarantee_steps, view_options=view_opts_req, use_on_equal_length=True) + prev_context.add(context_options) + return (prev_context,) +``` \ No newline at end of file diff --git a/docs/AIGC-Grounding-SAM.md b/docs/AIGC-Grounding-SAM.md new file mode 100644 index 0000000..9fdece8 --- /dev/null +++ b/docs/AIGC-Grounding-SAM.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: AIGCImageRemoveBackgroundRembg +- Category: AIGC +- Output node: False +- Repo Ref: https://github.com/esheep/esheep_custom_nodes.git + +AIGCImageRemoveBackgroundRembg节点旨在使用先进的图像分割技术无缝去除图像背景。它利用SAM(Segment Anything Model)和GroundingDINO模型实现高质量的背景去除,为用户提供了用于进一步使用的干净前景对象。 + +# Input types +## Required +- image + - 图像参数对于节点的操作至关重要,因为它是将从中移除背景的来源。图像的质量和格式直接影响节点的执行和生成的掩码的准确性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- text + - 文本参数用于指导分割过程,确保正确识别并保留感兴趣的区域。它在节点理解和处理图像内容的能力中起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +- sam_model_name + - sam_model_name参数指定用于分割的预训练SAM模型。模型的选择可以影响节点的性能和分割结果的质量。 + - Comfy dtype: COMBO["sam_vit_h_4b8939.pth", "sam_vit_l_0b3195.pth", "sam_vit_b_01ec64.pth"] + - Python dtype: str +- groundingdino_model_name + - groundingdino_model_name参数决定了应用于识别图像内感兴趣区域的GroundingDINO模型。此参数对于精确的对象识别和分割至关重要。 + - Comfy dtype: COMBO["GroundingDINO_SwinT_OGC", "GroundingDINO_SwinB"] + - Python dtype: str +## Optional +- dino_box_threshold + - dino_box_threshold参数用于设置GroundingDINO模型输出的阈值。它影响节点决定考虑哪些区域进行分割。 + - Comfy dtype: FLOAT + - Python dtype: float +- highest_confidence_mode + - highest_confidence_mode参数控制节点关于基于置信度分数选择分割掩码的行为。它是决定最终输出质量的一个重要因素。 + - Comfy dtype: INT + - Python dtype: int +- return_index + - return_index参数指示应返回生成的掩码中的哪一个。它允许用户从多个分割结果中选择所需的输出。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- new_image + - new_image输出包含处理过的图像,背景已去除,可供进一步使用或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - mask输出提供分割的二进制表示,突出显示已从原始图像中移除的区域。 + - Comfy dtype: MASK + - Python dtype: np.ndarray + +# Usage tips +- Infra type: GPU + +# Source code +``` +class AIGCImageRemoveBackgroundRembg: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'text': ('STRING', {'multiline': False}), 'sam_model_name': (['sam_vit_h_4b8939.pth', 'sam_vit_l_0b3195.pth', 'sam_vit_b_01ec64.pth'],), 'groundingdino_model_name': (['GroundingDINO_SwinT_OGC', 'GroundingDINO_SwinB'],), 'dino_box_threshold': ('FLOAT', {'default': 0.3, 'min': -100.0, 'max': 100.0, 'step': 0.1}), 'highest_confidence_mode': ('INT', {'default': 0, 'min': 0, 'max': 1, 'step': 1}), 'return_index': ('INT', {'default': 0})}} + RETURN_TYPES = ('IMAGE', 'MASK') + FUNCTION = 'sam' + CATEGORY = 'AIGC' + + def sam(self, image, text: str, sam_model_name: str, groundingdino_model_name: str, dino_box_threshold: float, highest_confidence_mode: int, return_index: int): + (new_image, mask) = sam_with_groundingdino(image, text, sam_model_name, groundingdino_model_name, dino_box_threshold, bool(highest_confidence_mode), return_index) + return (new_image, mask) +``` \ No newline at end of file diff --git a/docs/AMT VFI.md b/docs/AMT VFI.md new file mode 100644 index 0000000..87fb149 --- /dev/null +++ b/docs/AMT VFI.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: AMT_VFI +- Category: ComfyUI-Frame-Interpolation/VFI +- Output node: False +- Repo Ref: https://github.com/Fannovel16/ComfyUI-Frame-Interpolation + +AMT_VFI节点旨在执行视频帧插值,增强帧之间过渡的平滑度,并有效提高视频序列的帧率。它利用预训练模型生成原始素材中不存在的中间帧,为更流畅的视觉效果做出贡献。 + +# Input types +## Required +- ckpt_name + - 检查点名称参数对于识别用于帧插值的特定模型配置至关重要。它将节点指向正确的预训练模型,确保所需的输出质量和性能。 + - Comfy dtype: str + - Python dtype: str +- frames + - frames参数是必需的,因为它表示节点将处理插值的输入视频帧。输入帧的质量和分辨率直接影响最终的插值输出。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +## Optional +- clear_cache_after_n_frames + - clear_cache_after_n_frames参数用于通过在处理指定数量的帧后清除缓存来优化内存使用。这有助于防止在密集的帧插值任务期间内存过载。 + - Comfy dtype: int + - Python dtype: int +- multiplier + - multiplier参数决定了在两个现有帧之间生成的中间帧的数量。数值越高,输出视频的帧率越高,但也可能增加计算复杂性。 + - Comfy dtype: int + - Python dtype: int +- optional_interpolation_states + - optional_interpolation_states参数提供对帧插值过程的额外控制,允许为特定帧定制插值行为。 + - Comfy dtype: InterpolationStateList + - Python dtype: InterpolationStateList + +# Output types +- interpolated_frames + - interpolated_frames输出包含原始视频帧以及新生成的中间帧,从而产生更平滑且帧率更高的视频序列。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class AMT_VFI: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (list(CKPT_CONFIGS.keys()),), 'frames': ('IMAGE',), 'clear_cache_after_n_frames': ('INT', {'default': 1, 'min': 1, 'max': 100}), 'multiplier': ('INT', {'default': 2, 'min': 2, 'max': 1000})}, 'optional': {'optional_interpolation_states': ('INTERPOLATION_STATES',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'vfi' + CATEGORY = 'ComfyUI-Frame-Interpolation/VFI' + + def vfi(self, ckpt_name: typing.AnyStr, frames: torch.Tensor, clear_cache_after_n_frames: typing.SupportsInt=1, multiplier: typing.SupportsInt=2, optional_interpolation_states: InterpolationStateList=None, **kwargs): + model_path = load_file_from_direct_url(MODEL_TYPE, f'https://huggingface.co/lalala125/AMT/resolve/main/{ckpt_name}') + ckpt_config = CKPT_CONFIGS[ckpt_name] + interpolation_model = ckpt_config['network'](**ckpt_config['params']) + interpolation_model.load_state_dict(torch.load(model_path)['state_dict']) + interpolation_model.eval().to(get_torch_device()) + frames = preprocess_frames(frames) + padder = InputPadder(frames.shape, 16) + frames = padder.pad(frames) + + def return_middle_frame(frame_0, frame_1, timestep, model): + return model(frame_0, frame_1, embt=torch.FloatTensor([timestep] * frame_0.shape[0]).view(frame_0.shape[0], 1, 1, 1).to(get_torch_device()), scale_factor=1.0, eval=True)['imgt_pred'] + args = [interpolation_model] + out = generic_frame_loop(frames, clear_cache_after_n_frames, multiplier, return_middle_frame, *args, interpolation_states=optional_interpolation_states, dtype=torch.float32) + out = padder.unpad(out) + out = postprocess_frames(out) + return (out,) +``` \ No newline at end of file diff --git a/docs/APISR_Lterative_Zho.md b/docs/APISR_Lterative_Zho.md new file mode 100644 index 0000000..1076819 --- /dev/null +++ b/docs/APISR_Lterative_Zho.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: APISR_Lterative_Zho +- Category: 🔎APISR +- Output node: False +- Repo Ref: https://github.com/ZHO-ZHO-ZHO/ComfyUI-APISR.git + +该节点旨在使用指定模型增强图像分辨率,专注于提高输入图像的清晰度和细节。 + +# Input types +## Required +- pipe + - ‘pipe’参数至关重要,它代表了用于图像超分辨率的模型。它是节点功能的核心,直接影响输出质量。 + - Comfy dtype: APISRMODEL + - Python dtype: torch.nn.Module +- image + - ‘image’参数是必不可少的,它是超分辨率过程的输入。其质量和特性影响分辨率提升的有效性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- dtype + - ‘dtype’参数决定了用于处理的数据类型,这会影响超分辨率算法的性能和精度。 + - Comfy dtype: COMBO[float32, float16] + - Python dtype: str +## Optional +- crop_for_4x + - ‘crop_for_4x’参数是一个可选设置,用于调整输入图像以适应4倍缩放要求,确保兼容性和最佳处理。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- processed_images + - ‘processed_images’输出包含超分辨率图像,代表节点操作的主要结果,细节和清晰度得到增强。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class APISR_Lterative_Zho: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('APISRMODEL',), 'image': ('IMAGE',), 'crop_for_4x': ('BOOLEAN', {'default': True}), 'dtype': (['float32', 'float16'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'sr_image' + CATEGORY = '🔎APISR' + + def sr_image(self, pipe, image, crop_for_4x, dtype): + if dtype == 'float32': + weight_dtype = torch.float32 + elif dtype == 'float16': + weight_dtype = torch.float16 + pipe = pipe.to(device=device, dtype=weight_dtype) + processed_images = [] + for img_tensor in image: + img_tensor = img_tensor.to(device=device, dtype=weight_dtype).unsqueeze(0).permute(0, 3, 1, 2) + if crop_for_4x: + (_, _, h, w) = img_tensor.shape + if h % 4 != 0: + img_tensor = img_tensor[:, :, :4 * (h // 4), :] + if w % 4 != 0: + img_tensor = img_tensor[:, :, :, :4 * (w // 4)] + with torch.no_grad(): + super_resolved_img = pipe(img_tensor) + super_resolved_img_nhwc = super_resolved_img.permute(0, 2, 3, 1).squeeze(0).cpu() + processed_images.append(super_resolved_img_nhwc) + return (processed_images,) +``` \ No newline at end of file diff --git a/docs/APISR_ModelLoader_Zho.md b/docs/APISR_ModelLoader_Zho.md new file mode 100644 index 0000000..ce5ad62 --- /dev/null +++ b/docs/APISR_ModelLoader_Zho.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: APISR_ModelLoader_Zho +- Category: APISR +- Output node: False +- Repo Ref: https://github.com/ZHO-ZHO-ZHO/ComfyUI-APISR.git + +APISR_ModelLoader_Zho 是一个用于加载和管理各种图像超分辨率模型的节点。它抽象了模型初始化的复杂性,使用户能够无缝地将不同的超分辨率算法集成到他们的应用中。该节点强调灵活性和易用性,提供了一个统一的接口来处理不同的模型架构。 + +# Input types +## Required +- apisr_model + - apisr_model 参数对于指定要加载的模型文件至关重要。它指导节点到正确的模型架构和权重文件,使节点能够实例化适当的超分辨率生成器。此参数对于节点的执行及其产生的结果质量至关重要。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- pipe + - 输出参数 'pipe' 表示已加载的超分辨率模型生成器。它很重要,因为它是节点的主要输出,为用户提供了一个用于图像放大任务的即用型模型。生成器的性能直接影响超分辨率过程的有效性。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class APISR_ModelLoader_Zho: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'apisr_model': (folder_paths.get_filename_list('apisr'),)}} + RETURN_TYPES = ('APISRMODEL',) + RETURN_NAMES = ('pipe',) + FUNCTION = 'load_model' + CATEGORY = '🔎APISR' + + def load_model(self, apisr_model): + if not apisr_model: + raise ValueError('Please provide the apisr_model parameter with the name of the model file.') + apisr_path = folder_paths.get_full_path('apisr', apisr_model) + if apisr_model == '4x_APISR_GRL_GAN_generator.pth': + generator = load_grl(apisr_path, scale=4) + elif apisr_model == '2x_APISR_RRDB_GAN_generator.pth': + generator = load_rrdb(apisr_path, scale=2) + else: + raise gr.Error(error) + return [generator] +``` \ No newline at end of file diff --git a/docs/APISR_Zho.md b/docs/APISR_Zho.md new file mode 100644 index 0000000..ca21513 --- /dev/null +++ b/docs/APISR_Zho.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: APISR_Zho +- Category: 🔎APISR +- Output node: False +- Repo Ref: https://github.com/ZHO-ZHO-ZHO/ComfyUI-APISR.git + +该节点旨在使用指定模型提高图像分辨率,专注于改善输入图像的清晰度和细节。它调整图像以满足模型的要求,并应用增强过程,从而产生一张超分辨率图像。 + +# Input types +## Required +- pipe + - ‘pipe’参数代表用于图像超分辨率的模型。它至关重要,因为它定义了将应用于增强图像的基础架构和学习成果。 + - Comfy dtype: APISRMODEL + - Python dtype: torch.nn.Module +- image + - ‘image’参数是要由节点处理的输入图像。其质量和尺寸直接影响超分辨率的输出结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +- dtype + - ‘dtype’参数指定了模型权重和输入图像张量的数据类型。它影响计算的精度,并可能影响超分辨率图像的质量。 + - Comfy dtype: COMBO[float32, float16] + - Python dtype: str +## Optional +- crop_for_4x + - ‘crop_for_4x’参数决定输入图像是否应被裁剪至4的倍数尺寸,以优化特定模型的处理过程。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- super_resolved_img + - ‘super_resolved_img’参数是节点的输出,代表增强后的图像,具有改善的分辨率。它是将模型的超分辨率能力应用于输入图像的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class APISR_Zho: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('APISRMODEL',), 'image': ('IMAGE',), 'crop_for_4x': ('BOOLEAN', {'default': True}), 'dtype': (['float32', 'float16'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'sr_image' + CATEGORY = '🔎APISR' + + def sr_image(self, pipe, image, crop_for_4x, dtype): + if dtype == 'float32': + weight_dtype = torch.float32 + elif dtype == 'float16': + weight_dtype = torch.float16 + pipe = pipe.to(device=device, dtype=weight_dtype) + img_tensor = image.permute(0, 3, 1, 2).to(device=device, dtype=weight_dtype) + if crop_for_4x: + (_, _, h, w) = img_tensor.shape + if h % 4 != 0: + img_tensor = img_tensor[:, :, :4 * (h // 4), :] + if w % 4 != 0: + img_tensor = img_tensor[:, :, :, :4 * (w // 4)] + super_resolved_img = pipe(img_tensor) + super_resolved_img_nhwc = super_resolved_img.permute(0, 2, 3, 1).cpu() + return (super_resolved_img_nhwc,) +``` \ No newline at end of file diff --git a/docs/AbsCosWave.md b/docs/AbsCosWave.md new file mode 100644 index 0000000..04607b4 --- /dev/null +++ b/docs/AbsCosWave.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: AbsCosWave +- Category: FizzNodes 📅🅕🅝/WaveNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +该节点基于一组输入参数生成波形模式,模拟具有可调节特性的振荡行为。 + +# Input types +## Required +- phase + - 相位参数决定了波浪振荡的间隔,影响波浪模式的频率和周期。 + - Comfy dtype: FLOAT + - Python dtype: float +- amplitude + - 振幅控制波浪的大小,决定了波浪模式中峰值和谷值的大小。 + - Comfy dtype: FLOAT + - Python dtype: float +- x_translation + - X_translation 沿着 x 轴水平移动波浪,改变波浪模式的位置而不改变其形状。 + - Comfy dtype: FLOAT + - Python dtype: float +- max_value + - 最大值参数设置了波浪的上限,确保输出保持在定义的范围内。 + - Comfy dtype: FLOAT + - Python dtype: float +- current_frame + - 当前帧表示波浪随时间的进展,每一帧对应波浪周期中的一个点。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - 输出代表当前帧波浪的计算值,反映了节点对输入参数的处理。 + - Comfy dtype: FLOAT + - Python dtype: float +- int_output + - 整型输出是波浪计算输出的四舍五入值,提供了波浪模式的离散表示。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AbsCosWave: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'phase': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'amplitude': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.1}), 'x_translation': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'max_value': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.05}), 'current_frame': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('FLOAT', 'INT') + FUNCTION = 'Wave' + CATEGORY = 'FizzNodes 📅🅕🅝/WaveNodes' + + def Wave(self, phase, amplitude, x_translation, max_value, current_frame): + output = max_value - np.abs(np.cos(current_frame / phase)) * amplitude + print(output) + return (output, int(output)) +``` \ No newline at end of file diff --git a/docs/AbsSinWave.md b/docs/AbsSinWave.md new file mode 100644 index 0000000..866bdea --- /dev/null +++ b/docs/AbsSinWave.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: AbsSinWave +- Category: FizzNodes 📅🅕🅝/WaveNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +生成一个绝对正弦波模式,该模式在指定的最大值和零之间振荡,受相位、振幅和转换参数的影响。此节点旨在为信号处理或动画等各种应用提供多功能波形。 + +# Input types +## Required +- phase + - 相位参数决定了正弦波的周期,影响波的频率和整体模式。这对于调整波形中振荡的时间至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- amplitude + - 振幅设置正弦波的高度,控制振荡的幅度。它是定义波形强度的基本参数。 + - Comfy dtype: FLOAT + - Python dtype: float +- x_translation + - x_translation参数沿x轴移动波形,允许在波形模式内进行水平移动。它对于在给定上下文中定位波形非常重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- max_value + - max_value建立了波的上限,定义了正弦波可以达到的最大点。它是设置波振荡规模的关键参数。 + - Comfy dtype: FLOAT + - Python dtype: float +- current_frame + - current_frame参数表示时间或序列中的当前位置,波函数使用它来计算其输出。对于在特定时刻生成正确的波形至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - 输出提供了当前帧绝对正弦波的计算值,代表波形的y坐标。 + - Comfy dtype: FLOAT + - Python dtype: float +- int_output + - int_output是输出的整数表示,对于需要离散值而非连续值的应用非常有用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AbsSinWave: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'phase': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'amplitude': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.1}), 'x_translation': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'max_value': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.05}), 'current_frame': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('FLOAT', 'INT') + FUNCTION = 'Wave' + CATEGORY = 'FizzNodes 📅🅕🅝/WaveNodes' + + def Wave(self, phase, amplitude, x_translation, max_value, current_frame): + output = max_value - np.abs(np.sin(current_frame / phase)) * amplitude + print(output) + return (output, int(output)) +``` \ No newline at end of file diff --git a/docs/Add To Playlist (mtb).md b/docs/Add To Playlist (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/AddMask.md b/docs/AddMask.md new file mode 100644 index 0000000..f2247c1 --- /dev/null +++ b/docs/AddMask.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: AddMask +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +AddMask节点旨在对两个二进制掩码执行逐像素加法。它用于以保留原始掩码完整性的方式组合掩码图像,同时创建一个新的掩码,代表它们的联合。 + +# Input types +## Required +- mask1 + - 第一个要添加的掩码。它是一个关键组件,因为它有助于形成结果掩码,决定了将包含在最终组合掩码中的区域。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- mask2 + - 第二个要添加的掩码。像第一个掩码一样,它在定义输出掩码方面起着重要作用,通过贡献包含在组合结果中的区域。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- mask + - 输出是一个新的二进制掩码,由输入掩码相加得到。它表示两个输入掩码的联合,指示两个掩码重叠的区域。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AddMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask1': ('MASK',), 'mask2': ('MASK',)}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, mask1, mask2): + mask = add_masks(mask1, mask2) + return (mask,) +``` \ No newline at end of file diff --git a/docs/AddMetaData.md b/docs/AddMetaData.md new file mode 100644 index 0000000..14b8202 --- /dev/null +++ b/docs/AddMetaData.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: AddMetaData +- Category: Mikey/Meta +- Output node: True +- Repo Ref: https://github.com/bash-j/mikey_nodes + +AddMetaData节点旨在通过附加文本信息来丰富图像数据。它通过将指定的文本值附加到图像的元数据中来实现这一点,其中可以包括日期或工作流中其他节点的数据等动态元素。该节点在创建全面的元数据方面发挥着关键作用,可以增强图像的实用性和上下文,适用于各种应用场景。 + +# Input types +## Required +- image + - 图像参数是必不可少的,因为它是节点操作的主要数据对象。它代表了将添加元数据的图像。节点的执行围绕这张图像进行,使其成为过程中的一个基本组成部分。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or similar image object +- label + - 标签参数作为元数据的描述符。它是一个必需字段,为附加到图像的元数据提供文本标识符。这个标签很重要,因为它对正在添加的元数据进行分类和描述。 + - Comfy dtype: STRING + - Python dtype: str +- text_value + - 文本值参数对节点的功能至关重要,因为它定义了将包含在图像元数据中的特定文本。此文本可以是静态的或动态的,允许以灵活的方式丰富元数据。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- prompt + - 可选的提示参数可以用来将动态数据注入到元数据中。当元数据需要来自工作流中其他节点或组件的信息时,它特别有用,允许进行更具交互性和上下文感知的元数据创建过程。 + - Comfy dtype: PROMPT + - Python dtype: dict or str +- extra_pnginfo + - 额外的PNG信息参数虽然是可选的,但可以提供特定于图像的额外上下文或详细信息。它可以用来存储不属于主要元数据直接部分但对某些应用或分析仍相关的额外信息。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: dict or str + +# Output types +- image_with_metadata + - AddMetaData节点的输出是带有添加元数据的原始图像。这个输出代表了节点处理的成果,其中图像现在已用指定的文本值丰富,准备用于进一步使用或分发。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or similar image object + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AddMetaData: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'label': ('STRING', {'multiline': False, 'placeholder': 'Label for metadata'}), 'text_value': ('STRING', {'multiline': True, 'placeholder': 'Text to add to metadata'})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'add_metadata' + CATEGORY = 'Mikey/Meta' + OUTPUT_NODE = True + + def add_metadata(self, image, label, text_value, prompt=None, extra_pnginfo=None): + label = search_and_replace(label, extra_pnginfo, prompt) + text_value = search_and_replace(text_value, extra_pnginfo, prompt) + if extra_pnginfo is None: + extra_pnginfo = {} + if label in extra_pnginfo: + extra_pnginfo[label] += ', ' + text_value + else: + extra_pnginfo[label] = text_value + return (image,) +``` \ No newline at end of file diff --git a/docs/AnimateDiffCombine.md b/docs/AnimateDiffCombine.md new file mode 100644 index 0000000..a39de30 --- /dev/null +++ b/docs/AnimateDiffCombine.md @@ -0,0 +1,115 @@ +# Documentation +- Class name: AnimateDiffCombine +- Category: Animate Diff +- Output node: True +- Repo Ref: https://github.com/ArtVentureX/comfyui-animatediff.git + +AnimateDiffCombine节点旨在从一系列图像生成动画GIF。它处理输入图像,通过调整帧率和循环次数来创建连贯的动画,允许对最终输出进行自定义控制。该节点还提供了保存生成的GIF的选项,并包括创建乒乓效应的功能,增强了动画的视觉效果。 + +# Input types +## Required +- images + - 'image'参数是节点用来生成动画帧的图像张量序列。它对节点的操作至关重要,因为它直接影响输出GIF的内容和质量。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +## Optional +- frame_rate + - 'frame_rate'参数决定了动画播放的速度。它是设置GIF节奏的重要因素,影响帧与帧之间的过渡速度。 + - Comfy dtype: INT + - Python dtype: int +- loop_count + - 'loop_count'参数指定动画应该循环多少次。它在控制GIF的行为时很重要,特别是当确定它是否应该无限循环或设置循环次数时。 + - Comfy dtype: INT + - Python dtype: int +- save_image + - 'save_image'参数指示是否应将生成的GIF保存到输出目录。它在节点的功能中发挥作用,决定最终产品是否要保存以供将来使用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- filename_prefix + - 'filename_prefix'参数为保存的GIF文件名提供前缀。它对于识别和组织输出文件至关重要,确保它们易于与其他文件区分开来。 + - Comfy dtype: STRING + - Python dtype: str +- format + - 'format'参数定义了输出GIF的文件格式。它很重要,因为它决定了将创建的文件类型,影响动画在不同平台上的兼容性和外观。 + - Comfy dtype: COMBO[image/gif, image/webp] + - Python dtype: str +- pingpong + - 'pingpong'参数,当设置为True时,会在动画中创建一个乒乓效应,反转帧的顺序,为GIF添加一个独特的视觉元素。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- prompt + - 'prompt'参数用于向GIF添加文本描述或元数据,这对于提供有关动画的上下文或附加信息非常有用。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - 'extra_pnginfo'参数允许在构成GIF的PNG文件中包含额外的元数据。它可以增强输出文件的信息丰富度。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, str] + +# Output types +- ui + - 'ui'参数在输出中是一个包含有关生成的GIF的信息的字典,包括文件路径和格式。它很重要,因为它为用户提供了对输出文件的引用,以便进一步使用或共享。 + - Comfy dtype: DICT + - Python dtype: Dict[str, List[Dict[str, Union[str, Dict[str, str]]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AnimateDiffCombine: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'frame_rate': ('INT', {'default': 8, 'min': 1, 'max': 24, 'step': 1}), 'loop_count': ('INT', {'default': 0, 'min': 0, 'max': 100, 'step': 1}), 'save_image': ('BOOLEAN', {'default': True}), 'filename_prefix': ('STRING', {'default': 'animate_diff'}), 'format': (['image/gif', 'image/webp'] + video_formats,), 'pingpong': ('BOOLEAN', {'default': False})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = () + OUTPUT_NODE = True + CATEGORY = 'Animate Diff' + FUNCTION = 'generate_gif' + + def generate_gif(self, images, frame_rate: int, loop_count: int, save_image=True, filename_prefix='AnimateDiff', format='image/gif', pingpong=False, prompt=None, extra_pnginfo=None): + frames: List[Image.Image] = [] + for image in images: + img = 255.0 * image.cpu().numpy() + img = Image.fromarray(np.clip(img, 0, 255).astype(np.uint8)) + frames.append(img) + output_dir = folder_paths.get_output_directory() if save_image else folder_paths.get_temp_directory() + (full_output_folder, filename, counter, subfolder, _) = folder_paths.get_save_image_path(filename_prefix, output_dir) + metadata = PngInfo() + if prompt is not None: + metadata.add_text('prompt', json.dumps(prompt)) + if extra_pnginfo is not None: + for x in extra_pnginfo: + metadata.add_text(x, json.dumps(extra_pnginfo[x])) + file = f'{filename}_{counter:05}_.png' + file_path = os.path.join(full_output_folder, file) + frames[0].save(file_path, pnginfo=metadata, compress_level=4) + if pingpong: + frames = frames + frames[-2:0:-1] + (format_type, format_ext) = format.split('/') + if format_type == 'image': + file = f'{filename}_{counter:05}_.{format_ext}' + file_path = os.path.join(full_output_folder, file) + frames[0].save(file_path, format=format_ext.upper(), save_all=True, append_images=frames[1:], duration=round(1000 / frame_rate), loop=loop_count, compress_level=4) + else: + import shutil + import subprocess + ffmpeg_path = shutil.which('ffmpeg') + if ffmpeg_path is None: + raise ProcessLookupError('Could not find ffmpeg') + video_format_path = os.path.join(video_formats_dir, format_ext + '.json') + with open(video_format_path, 'r') as stream: + video_format = json.load(stream) + file = f"{filename}_{counter:05}_.{video_format['extension']}" + file_path = os.path.join(full_output_folder, file) + dimensions = f'{frames[0].width}x{frames[0].height}' + args = [ffmpeg_path, '-v', 'error', '-f', 'rawvideo', '-pix_fmt', 'rgb24', '-s', dimensions, '-r', str(frame_rate), '-i', '-'] + video_format['main_pass'] + [file_path] + env = os.environ + if 'environment' in video_format: + env.update(video_format['environment']) + with subprocess.Popen(args, stdin=subprocess.PIPE, env=env) as proc: + for frame in frames: + proc.stdin.write(frame.tobytes()) + previews = [{'filename': file, 'subfolder': subfolder, 'type': 'output' if save_image else 'temp', 'format': format}] + return {'ui': {'videos': previews}} +``` \ No newline at end of file diff --git a/docs/AnimateDiffLoraLoader.md b/docs/AnimateDiffLoraLoader.md new file mode 100644 index 0000000..1b62bb3 --- /dev/null +++ b/docs/AnimateDiffLoraLoader.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: AnimateDiffLoraLoader +- Category: Animate Diff +- Output node: False +- Repo Ref: https://github.com/ArtVentureX/comfyui-animatediff.git + +该节点旨在通过加载和处理Lora文件,将动画差异集成到模型中,为模型的外观或行为添加动态元素。它专注于无缝集成运动和变换数据,提高整体动画质量,同时不损害模型的结构完整性。 + +# Input types +## Required +- lora_name + - lora_name参数至关重要,因为它指定了要加载的Lora文件的唯一标识符,其中包含动画过程所需的运动和变换数据。正确使用此参数确保准确选择和应用所需的动画差异。 + - Comfy dtype: STRING + - Python dtype: str +- alpha + - alpha参数控制应用于模型的动画效果的强度。它对于调整最终输出中动画差异的显著性至关重要,允许微调视觉影响。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- lora_stack + - lora_stack参数是一个可选列表,用于累积Lora数据及其对应alpha值的元组。它在管理多个动画差异层方面发挥作用,提供了一种有结构的方式来处理和组织动画序列。 + - Comfy dtype: LIST[tuple] + - Python dtype: List[Tuple[str, float]] + +# Output types +- lora_stack + - 输出的lora_stack是一个包含处理过的Lora数据及其相应alpha值的元组列表。这个列表对于进一步处理和集成到模型中至关重要,作为动画差异的主要输出。 + - Comfy dtype: LIST[tuple] + - Python dtype: List[Tuple[str, float]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AnimateDiffLoraLoader: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'lora_name': (get_available_loras(),), 'alpha': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001})}, 'optional': {'lora_stack': ('MOTION_LORA_STACK',)}} + RETURN_TYPES = ('MOTION_LORA_STACK',) + CATEGORY = 'Animate Diff' + FUNCTION = 'load_lora' + + def load_lora(self, lora_name: str, alpha: float, lora_stack: List=None): + if not lora_stack: + lora_stack = [] + lora = load_lora(lora_name) + lora_stack.append((lora, alpha)) + return (lora_stack,) +``` \ No newline at end of file diff --git a/docs/AnimateDiffModuleLoader.md b/docs/AnimateDiffModuleLoader.md new file mode 100644 index 0000000..6a0841d --- /dev/null +++ b/docs/AnimateDiffModuleLoader.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: AnimateDiffModuleLoader +- Category: Animate Diff +- Output node: False +- Repo Ref: https://github.com/ArtVentureX/comfyui-animatediff.git + +该节点旨在动画框架内管理和操作运动模块,专注于集成和应用高级运动技术,以增强动画的动态性和流畅性。 + +# Input types +## Required +- model_name + - 模型名称对于识别要加载和操作的特定运动模块至关重要。它决定了动画资产的来源,并为后续操作奠定了基础。 + - Comfy dtype: string + - Python dtype: str +## Optional +- lora_stack + - LoRa堆栈是一个可选参数,提供后允许通过逐层调整来微调运动模块。它增强了动画适应性和定制性,以满足特定要求。 + - Comfy dtype: list + - Python dtype: List[Tuple[Dict[str, torch.Tensor], float]] + +# Output types +- motion_module + - 输出的运动模块是节点处理的结果,代表最终确定和优化的动画模块,准备在动画流程中使用。 + - Comfy dtype: object + - Python dtype: MotionWrapper + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AnimateDiffModuleLoader: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model_name': (get_available_models(),)}, 'optional': {'lora_stack': ('MOTION_LORA_STACK',)}} + RETURN_TYPES = ('MOTION_MODULE',) + CATEGORY = 'Animate Diff' + FUNCTION = 'load_motion_module' + + def inject_loras(self, motion_module: MotionWrapper, lora_stack: List[Tuple[Dict[str, Tensor], float]]): + for lora in lora_stack: + (state_dict, alpha) = lora + for key in state_dict: + layer_infos = key.split('.') + curr_layer = motion_module + while len(layer_infos) > 0: + temp_name = layer_infos.pop(0) + curr_layer = curr_layer.__getattr__(temp_name) + curr_layer.weight.data += alpha * state_dict[key].to(curr_layer.weight.data.device) + + def eject_loras(self, motion_module: MotionWrapper, lora_stack: List[Tuple[float, Dict[str, Tensor]]]): + lora_stack.reverse() + for lora in lora_stack: + (state_dict, alpha) = lora + for key in state_dict: + layer_infos = key.split('.') + curr_layer = motion_module + while len(layer_infos) > 0: + temp_name = layer_infos.pop(0) + curr_layer = curr_layer.__getattr__(temp_name) + curr_layer.weight.data -= alpha * state_dict[key].to(curr_layer.weight.data.device) + + def load_motion_module(self, model_name: str, lora_stack: List=None): + motion_module = load_motion_module(model_name) + if motion_module.is_v2: + if hasattr(motion_module, 'lora_stack') and isinstance(motion_module.lora_stack, list): + self.eject_loras(motion_module, motion_module.lora_stack) + delattr(motion_module, 'lora_stack') + if isinstance(lora_stack, list): + self.inject_loras(motion_module, lora_stack) + setattr(motion_module, 'lora_stack', lora_stack) + elif isinstance(lora_stack, list): + logger.warning('LoRA is provided but only motion module v2 is supported.') + return (motion_module,) +``` \ No newline at end of file diff --git a/docs/AnimateDiffSampler.md b/docs/AnimateDiffSampler.md new file mode 100644 index 0000000..ecc46d9 --- /dev/null +++ b/docs/AnimateDiffSampler.md @@ -0,0 +1,114 @@ +# Documentation +- Class name: AnimateDiffSampler +- Category: Animate Diff +- Output node: False +- Repo Ref: https://github.com/ArtVentureX/comfyui-animatediff.git + +AnimateDiffSampler是一个旨在通过引入运动模块来增强生成模型采样过程的节点,这些运动模块将动态元素引入到生成内容中。该节点旨在通过改善输出中动画的流畅性和连贯性,提供更加栩栩如生的体验。它通过将运动数据注入模型的扩散过程并相应地调整采样设置来实现这一点,而不会深入到底层方法或参数的具体细节。 + +# Input types +## Required +- motion_module + - 运动模块参数对于AnimateDiffSampler至关重要,因为它提供了使生成动画内容成为可能的动态数据。它是节点功能的核心,影响模型如何感知和生成输出中的运动。 + - Comfy dtype: MOTION_MODULE + - Python dtype: MotionWrapper +- inject_method + - 注入方法参数决定了AnimateDiffSampler如何将运动模块集成到模型的扩散过程中。这对于确定运动集成的有效性以及动画结果的质量至关重要。 + - Comfy dtype: COMBO + - Python dtype: str +- frame_number + - 帧数参数是AnimateDiffSampler中的一个关键因素,因为它定义了要生成的动画的长度。它通过确定将生成的帧数来直接影响节点的输出,从而影响动画的总体持续时间和范围。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- samples + - AnimateDiffSampler的输出样本代表生成的动画帧。它是节点处理的最终成果,包含了为了创建动画内容而应用的运动和扩散过程。 + - Comfy dtype: TORCH_TENSOR + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class AnimateDiffSampler(KSampler): + + @classmethod + def INPUT_TYPES(s): + inputs = {'required': {'motion_module': ('MOTION_MODULE',), 'inject_method': (['default', 'legacy'],), 'frame_number': ('INT', {'default': 16, 'min': 2, 'max': 10000, 'step': 1})}} + inputs['required'].update(KSampler.INPUT_TYPES()['required']) + inputs['optional'] = {'sliding_window_opts': ('SLIDING_WINDOW_OPTS',)} + return inputs + FUNCTION = 'animatediff_sample' + CATEGORY = 'Animate Diff' + + def __init__(self) -> None: + super().__init__() + self.model_sampling = None + + def override_beta_schedule(self, model: BaseModel): + self.model_sampling = model.model_sampling + model.model_sampling = model_sampling(ModelSamplingConfig(beta_schedule='sqrt_linear'), model_type=model.model_type) + + def restore_beta_schedule(self, model: BaseModel): + model.model_sampling = self.model_sampling + self.model_sampling = None + + def inject_motion_module(self, model, motion_module: MotionWrapper, inject_method: str, frame_number: int): + model = model.clone() + unet = model.model.diffusion_model + logger.info(f'Injecting motion module with method {inject_method}.') + motion_module.set_video_length(frame_number) + injectors[inject_method](unet, motion_module) + self.override_beta_schedule(model.model) + openaimodel.forward_timestep_embed = forward_timestep_embed + if not motion_module.is_v2: + logger.info(f'Hacking GroupNorm.forward function.') + torch.nn.GroupNorm.forward = groupnorm_mm_factory(frame_number) + return model + + def inject_sliding_sampler(self, video_length, sliding_window_opts: SlidingContext=None): + ctx = sliding_window_opts.copy() if sliding_window_opts else SlidingContext() + ctx.video_length = video_length + inject_sampling_function(ctx) + + def eject_motion_module(self, model, inject_method): + unet = model.model.diffusion_model + self.restore_beta_schedule(model.model) + openaimodel.forward_timestep_embed = orig_forward_timestep_embed + if not unet.motion_module.is_v2: + logger.info(f'Restore GroupNorm.forward function.') + torch.nn.GroupNorm.forward = orig_groupnorm_forward + logger.info(f'Ejecting motion module with method {inject_method}.') + ejectors[inject_method](unet) + + def eject_sliding_sampler(self): + eject_sampling_function() + + def animatediff_sample(self, motion_module, inject_method, frame_number, model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=1.0, sliding_window_opts: SlidingContext=None, **kwargs): + samples = latent_image['samples'] + init_frames = len(samples) + if init_frames < frame_number: + last_frame = samples[-1].clone().cpu().unsqueeze(0) + repeated_last_frames = last_frame.repeat(frame_number - init_frames, 1, 1, 1) + samples = torch.cat((samples, repeated_last_frames), dim=0) + latent_image = {'samples': samples} + context_length = sliding_window_opts.context_length if sliding_window_opts else SLIDING_CONTEXT_LENGTH + is_sliding = frame_number > context_length + video_length = context_length if is_sliding else frame_number + if video_length > motion_module.encoding_max_len: + error = f"{('context_length' if is_sliding else 'frame_number')} = {video_length}" + raise ValueError(f'AnimateDiff model {motion_module.mm_type} has upper limit of {motion_module.encoding_max_len} frames, but received {error}.') + model = self.inject_motion_module(model, motion_module, inject_method, video_length) + if is_sliding: + self.inject_sliding_sampler(frame_number, sliding_window_opts=sliding_window_opts) + try: + return super().sample(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise, **kwargs) + except: + raise + finally: + self.eject_motion_module(model, inject_method) + if is_sliding: + self.eject_sliding_sampler() +``` \ No newline at end of file diff --git a/docs/AnimateDiffSlidingWindowOptions.md b/docs/AnimateDiffSlidingWindowOptions.md new file mode 100644 index 0000000..343e08e --- /dev/null +++ b/docs/AnimateDiffSlidingWindowOptions.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: AnimateDiffSlidingWindowOptions +- Category: Animate Diff +- Output node: False +- Repo Ref: https://github.com/ArtVentureX/comfyui-animatediff.git + +该节点类封装了设置滑动窗口动画所需的配置选项。它旨在管理控制视频序列中帧生成的参数,确保动画流畅连贯。节点的目的是提供一种结构化的方式来定义动画的时间和空间特征,如上下文的长度、帧之间的步长以及连续上下文之间的重叠程度。 + +# Input types +## Required +- context_length + - context_length参数规定了在动画的每一步中要考虑的连续帧数。它对于确定模型操作的上下文范围至关重要,从而影响生成动画的连贯性和连续性。 + - Comfy dtype: INT + - Python dtype: int +- context_stride + - context_stride参数指定了滑动窗口中帧之间的间隔。它影响了动画从一个上下文过渡到下一个上下文的方式,有助于整体动画的节奏和步调。 + - Comfy dtype: INT + - Python dtype: int +- context_overlap + - context_overlap参数定义了连续滑动窗口之间的重叠帧数。这对于保持平滑过渡和确保动画不会出现不连贯或不稳定的外观至关重要。 + - Comfy dtype: INT + - Python dtype: int +- context_schedule + - context_schedule参数控制滑动窗口中帧的分布,允许使用各种模式,如均匀或非均匀排列。这影响了动画的视觉动态和叙事流程。 + - Comfy dtype: ENUM + - Python dtype: ContextSchedules.CONTEXT_SCHEDULE_ENUM +- closed_loop + - closed_loop参数决定了动画在到达结尾后是否应该循环回到开头。这影响了动画的整体结构和呈现方式,可能会创造出无缝或循环的叙事。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- sliding_window_opts + - 输出代表一个配置好的SlidingContext对象,封装了动画过程中所需的所有参数。它是生成连贯且平滑过渡的视频序列的关键组成部分。 + - Comfy dtype: OBJECT + - Python dtype: SlidingContext + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AnimateDiffSlidingWindowOptions: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'context_length': ('INT', {'default': SLIDING_CONTEXT_LENGTH, 'min': 2, 'max': 32}), 'context_stride': ('INT', {'default': 1, 'min': 1, 'max': 32}), 'context_overlap': ('INT', {'default': 4, 'min': 0, 'max': 32}), 'context_schedule': (ContextSchedules.CONTEXT_SCHEDULE_LIST, {'default': ContextSchedules.UNIFORM}), 'closed_loop': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('SLIDING_WINDOW_OPTS',) + FUNCTION = 'init_options' + CATEGORY = 'Animate Diff' + + def init_options(self, context_length, context_stride, context_overlap, context_schedule, closed_loop): + ctx = SlidingContext(context_length=context_length, context_stride=context_stride, context_overlap=context_overlap, context_schedule=context_schedule, closed_loop=closed_loop) + return (ctx,) +``` \ No newline at end of file diff --git a/docs/Animation Builder (mtb).md b/docs/Animation Builder (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/AnimeLineArt_Preprocessor_Provider_for_SEGS %2F%2FInspire.md b/docs/AnimeLineArt_Preprocessor_Provider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..da52def --- /dev/null +++ b/docs/AnimeLineArt_Preprocessor_Provider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: AnimeLineArt_Preprocessor_Provider_for_SEGS +- Category: InspirePack/SEGS/ControlNet +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +此类节点负责将输入的图像转换为动漫风格的线稿,这对于以动漫美学一致的方式风格化视觉效果至关重要。它利用机器学习模型的力量,从源图像生成详细且富有表现力的线条图,增强艺术生成任务中的创作过程。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它是衍生动漫线稿的来源。输入图像的质量和分辨率直接影响生成的线稿的细节和准确性。 + - Comfy dtype: image + - Python dtype: PIL.Image or numpy.ndarray +## Optional +- mask + - 掩码参数虽然是可选的,但可以通过指定在线条艺术转换过程中应该优先考虑或排除的图像区域来细化预处理。 + - Comfy dtype: mask + - Python dtype: numpy.ndarray + +# Output types +- SEGS_PREPROCESSOR + - 此节点的输出是已被转换为动漫线稿的图像。这是在创建风格化内容时的关键组成部分,视觉吸引力和艺术质量至关重要。 + - Comfy dtype: image + - Python dtype: numpy.ndarray + +# Usage tips +- Infra type: GPU + +# Source code +``` +class AnimeLineArt_Preprocessor_Provider_for_SEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}} + RETURN_TYPES = ('SEGS_PREPROCESSOR',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/SEGS/ControlNet' + + def doit(self): + obj = AnimeLineArt_Preprocessor_wrapper() + return (obj,) +``` \ No newline at end of file diff --git a/docs/Any To String (mtb).md b/docs/Any To String (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/AppInfo.md b/docs/AppInfo.md new file mode 100644 index 0000000..78a1c97 --- /dev/null +++ b/docs/AppInfo.md @@ -0,0 +1,89 @@ +# Documentation +- Class name: AppInfo +- Category: ♾️Mixlab +- Output node: True +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +AppInfo是一个旨在管理和组织应用程序信息的节点,它便于在系统中设置和运行各种应用程序。它简化了应用程序细节的输入和输出,确保高效处理应用程序数据。该节点在概念上专注于提供结构化的应用程序信息管理方法,而不绑定于具体的实现细节。 + +# Input types +## Required +- name + - 名称参数对于在系统中识别应用程序至关重要。它作为一个唯一标识符,有助于组织和检索与应用程序相关的数据。名称影响应用程序在系统中的引用和管理方式。 + - Comfy dtype: STRING + - Python dtype: str +- input_ids + - 输入ID在跟踪应用程序的组成部分或模块中起着关键作用。它们对于系统性地分析和管理应用程序的结构至关重要,确保每个部分都被记录并可以根据需要访问。 + - Comfy dtype: STRING + - Python dtype: str +- output_ids + - 输出ID对于映射应用程序的结果和成果至关重要。它们定义了输出数据的结构和格式,使得应用程序的输出能够被有效监控和利用。正确管理输出ID对于应用程序的成功运行和与其他系统组件的集成至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- IMAGE + - 图像提供了应用程序的视觉表现,增强了理解和沟通。它们可以用于显示应用程序的界面、图标或其他视觉元素,这对于用户交互和品牌塑造非常重要。包含图像可以显著改善用户体验和对应用程序的感知。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- description + - 描述参数对于提供应用程序的上下文和背景信息至关重要。它有助于传达应用程序的目的、特点和使用场景,对用户和开发者都有益。清晰简洁的描述可以极大地帮助应用程序的文档编写和推广。 + - Comfy dtype: STRING + - Python dtype: str +- version + - 版本参数对于跟踪应用程序的发展和更新至关重要。它有助于记录变化和改进,从而更好地管理应用程序的开发周期。版本号是用户和开发者在解决问题或规划新功能时的关键参考点。 + - Comfy dtype: INT + - Python dtype: int +- share_prefix + - 共享前缀对于定义应用程序的数据和资源如何共享和访问非常重要。它为系统内的数据交换和协作奠定了基础,确保应用程序的共享机制与整体系统架构保持一致。 + - Comfy dtype: STRING + - Python dtype: str +- link + - 链接参数对于引导用户获取与应用程序相关的额外资源或内容非常重要。它可以提供对文档、支持或补充材料的访问,这对于增强用户对应用程序的理解和参与非常有价值。 + - Comfy dtype: STRING + - Python dtype: str +- category + - 类别参数有助于将应用程序归类到特定的领域或类型中,这对于组织和导航非常有用。它有助于将相似的应用程序分组在一起,使用户更容易找到并选择适合他们需求的应用程序。 + - Comfy dtype: STRING + - Python dtype: str +- auto_save + - 自动保存参数对于确定应用程序的数据持久性和恢复行为非常重要。它决定了应用程序的状态是否应该在固定时间间隔自动保存,确保用户在中断或系统故障的情况下可以恢复他们的工作。 + - Comfy dtype: COMBO['enable', 'disable'] + - Python dtype: str + +# Output types +- ui.json + - ui.json输出是应用程序信息的结构化表示,包括其名称、图像和各种ID。它作为一个全面的摘要,可以用于系统的进一步处理或显示。这个输出对于将应用程序的数据与其他组件集成以及提供应用程序状态的清晰概览非常重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AppInfo: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'name': ('STRING', {'multiline': False, 'default': 'Mixlab-App', 'dynamicPrompts': False}), 'input_ids': ('STRING', {'multiline': True, 'default': '\n'.join(['1', '2', '3']), 'dynamicPrompts': False}), 'output_ids': ('STRING', {'multiline': True, 'default': '\n'.join(['5', '9']), 'dynamicPrompts': False})}, 'optional': {'IMAGE': ('IMAGE',), 'description': ('STRING', {'multiline': True, 'default': '', 'dynamicPrompts': False}), 'version': ('INT', {'default': 1, 'min': 1, 'max': 10000, 'step': 1, 'display': 'number'}), 'share_prefix': ('STRING', {'multiline': False, 'default': '', 'dynamicPrompts': False}), 'link': ('STRING', {'multiline': False, 'default': 'https://', 'dynamicPrompts': False}), 'category': ('STRING', {'multiline': False, 'default': '', 'dynamicPrompts': False}), 'auto_save': (['enable', 'disable'],)}} + RETURN_TYPES = () + FUNCTION = 'run' + CATEGORY = '♾️Mixlab' + OUTPUT_NODE = True + INPUT_IS_LIST = True + + def run(self, name, input_ids, output_ids, IMAGE, description, version, share_prefix, link, category, auto_save): + name = name[0] + im = None + if IMAGE: + im = IMAGE[0][0] + im = create_temp_file(im) + input_ids = input_ids[0] + output_ids = output_ids[0] + description = description[0] + version = version[0] + share_prefix = share_prefix[0] + link = link[0] + category = category[0] + return {'ui': {'json': [name, im, input_ids, output_ids, description, version, share_prefix, link, category]}, 'result': ()} +``` \ No newline at end of file diff --git a/docs/Apply Text Template (mtb).md b/docs/Apply Text Template (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ApplyInstantID.md b/docs/ApplyInstantID.md new file mode 100644 index 0000000..bf6186b --- /dev/null +++ b/docs/ApplyInstantID.md @@ -0,0 +1,176 @@ +# Documentation +- Class name: ApplyInstantID +- Category: InstantID +- Output node: False +- Repo Ref: https://github.com/cubiq/ComfyUI_InstantID.git + +ApplyInstantID节点旨在整合面部识别和图像处理功能,利用先进的机器学习模型提高输入图像的质量和相关性。它通过对输入图像应用一系列变换,并根据特定面部特征对模型进行条件化,最终提高输出的准确性和细节。 + +# Input types +## Required +- instantid + - instantid参数对节点的运行至关重要,因为它提供了处理所需的必要面部识别数据和模型结构。没有它,节点无法执行其预期的面部分析和增强任务。 + - Comfy dtype: INSTANTID + - Python dtype: Dict[str, Any] +- insightface + - insightface参数对节点至关重要,因为它包含了用于从输入图像中提取和处理面部特征的面部分析模型。此参数直接影响面部特征检测的准确性和质量。 + - Comfy dtype: FACEANALYSIS + - Python dtype: Any +- control_net + - control_net参数是节点的一个关键组成部分,它允许节点管理和调整应用于模型的条件化过程。它有助于微调输出以满足特定要求,并提高面部特征增强的整体性能。 + - Comfy dtype: CONTROL_NET + - Python dtype: Any +- image + - image参数是节点功能的基础,它作为面部特征提取和增强的输入。图像的质量和分辨率直接影响面部识别的有效性和最终输出。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray +- model + - model参数是节点操作的核心,提供了执行面部特征分析和增强的基础机器学习模型。模型的选择和质量显著影响节点的性能和输出。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- positive + - positive参数在节点的运行中起着至关重要的作用,通过提供正向条件数据来指导增强过程。它有助于完善面部特征,并确保输出符合期望的特征。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[Any, Dict[str, Any]]] +- negative + - negative参数与positive参数同等重要,提供负向条件数据,帮助节点避免输出中不希望的特征。它有助于面部特征增强过程的精确性。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[Any, Dict[str, Any]]] +## Optional +- weight + - weight参数影响应用于模型的条件强度,影响最终输出中期望特征的显著程度。它提供了一种控制输入条件与模型固有能力之间平衡的方法。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_at + - start_at参数定义了条件过程的起点,决定了面部特征增强的开始时间。它对于控制特征增强的时间和顺序至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_at + - end_at参数设置了条件过程的终点,决定了面部特征增强的结束时间。它与start_at协同工作,确保面部特征增强的间隔受控且精确。 + - Comfy dtype: FLOAT + - Python dtype: float +- image_kps + - image_kps参数提供面部特征的关键点数据,用于指导模型准确定位和增强特定的面部元素。它有助于提高面部特征增强的精确度和准确性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray +- mask + - mask参数用于对面部特征增强过程应用特定的限制或聚焦区域。它允许有针对性的调整和改进,确保增强只应用于图像的期望区域。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- MODEL + - 输出模型是经过输入数据条件化以提高面部特征提取的准确性和质量的增强机器学习模型。它代表了节点处理的成果,准备用于进一步的使用或分析。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- positive + - 正面输出代表了成功增强和条件化的正面面部特征,可以作为后续过程的参考或输入。它是节点输出的关键部分,表明面部特征增强已成功应用。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[Any, Dict[str, Any]]] +- negative + - 负面输出包括已调整的条件化负面面部特征,以防止不希望的特征出现在最终输出中。它反映了节点对输出进行细化和控制以满足特定要求的能力。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[Any, Dict[str, Any]]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ApplyInstantID: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'instantid': ('INSTANTID',), 'insightface': ('FACEANALYSIS',), 'control_net': ('CONTROL_NET',), 'image': ('IMAGE',), 'model': ('MODEL',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'weight': ('FLOAT', {'default': 0.8, 'min': 0.0, 'max': 5.0, 'step': 0.01}), 'start_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_at': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001})}, 'optional': {'image_kps': ('IMAGE',), 'mask': ('MASK',)}} + RETURN_TYPES = ('MODEL', 'CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('MODEL', 'positive', 'negative') + FUNCTION = 'apply_instantid' + CATEGORY = 'InstantID' + + def apply_instantid(self, instantid, insightface, control_net, image, model, positive, negative, start_at, end_at, weight=0.8, ip_weight=None, cn_strength=None, noise=0.35, image_kps=None, mask=None): + self.dtype = torch.float16 if comfy.model_management.should_use_fp16() else torch.float32 + self.device = comfy.model_management.get_torch_device() + ip_weight = weight if ip_weight is None else ip_weight + cn_strength = weight if cn_strength is None else cn_strength + output_cross_attention_dim = instantid['ip_adapter']['1.to_k_ip.weight'].shape[1] + is_sdxl = output_cross_attention_dim == 2048 + cross_attention_dim = 1280 + clip_extra_context_tokens = 16 + face_embed = extractFeatures(insightface, image) + if face_embed is None: + raise Exception('Reference Image: No face detected.') + face_kps = extractFeatures(insightface, image_kps if image_kps is not None else image[0].unsqueeze(0), extract_kps=True) + if face_kps is None: + face_kps = torch.zeros_like(image) if image_kps is None else image_kps + print(f'\x1b[33mWARNING: No face detected in the keypoints image!\x1b[0m') + clip_embed = face_embed + if clip_embed.shape[0] > 1: + clip_embed = torch.mean(clip_embed, dim=0).unsqueeze(0) + if noise > 0: + seed = int(torch.sum(clip_embed).item()) % 1000000007 + torch.manual_seed(seed) + clip_embed_zeroed = noise * torch.rand_like(clip_embed) + else: + clip_embed_zeroed = torch.zeros_like(clip_embed) + clip_embeddings_dim = face_embed.shape[-1] + self.instantid = InstantID(instantid, cross_attention_dim=cross_attention_dim, output_cross_attention_dim=output_cross_attention_dim, clip_embeddings_dim=clip_embeddings_dim, clip_extra_context_tokens=clip_extra_context_tokens) + self.instantid.to(self.device, dtype=self.dtype) + (image_prompt_embeds, uncond_image_prompt_embeds) = self.instantid.get_image_embeds(clip_embed.to(self.device, dtype=self.dtype), clip_embed_zeroed.to(self.device, dtype=self.dtype)) + image_prompt_embeds = image_prompt_embeds.to(self.device, dtype=self.dtype) + uncond_image_prompt_embeds = uncond_image_prompt_embeds.to(self.device, dtype=self.dtype) + work_model = model.clone() + sigma_start = work_model.model.model_sampling.percent_to_sigma(start_at) + sigma_end = work_model.model.model_sampling.percent_to_sigma(end_at) + if mask is not None: + mask = mask.to(self.device) + patch_kwargs = {'number': 0, 'weight': ip_weight, 'ipadapter': self.instantid, 'cond': image_prompt_embeds, 'uncond': uncond_image_prompt_embeds, 'mask': mask, 'sigma_start': sigma_start, 'sigma_end': sigma_end, 'weight_type': 'original'} + if not is_sdxl: + for id in [1, 2, 4, 5, 7, 8]: + _set_model_patch_replace(work_model, patch_kwargs, ('input', id)) + patch_kwargs['number'] += 1 + for id in [3, 4, 5, 6, 7, 8, 9, 10, 11]: + _set_model_patch_replace(work_model, patch_kwargs, ('output', id)) + patch_kwargs['number'] += 1 + _set_model_patch_replace(work_model, patch_kwargs, ('middle', 0)) + else: + for id in [4, 5, 7, 8]: + block_indices = range(2) if id in [4, 5] else range(10) + for index in block_indices: + _set_model_patch_replace(work_model, patch_kwargs, ('input', id, index)) + patch_kwargs['number'] += 1 + for id in range(6): + block_indices = range(2) if id in [3, 4, 5] else range(10) + for index in block_indices: + _set_model_patch_replace(work_model, patch_kwargs, ('output', id, index)) + patch_kwargs['number'] += 1 + for index in range(10): + _set_model_patch_replace(work_model, patch_kwargs, ('middle', 0, index)) + patch_kwargs['number'] += 1 + if mask is not None and len(mask.shape) < 3: + mask = mask.unsqueeze(0) + cnets = {} + cond_uncond = [] + is_cond = True + for conditioning in [positive, negative]: + c = [] + for t in conditioning: + d = t[1].copy() + prev_cnet = d.get('control', None) + if prev_cnet in cnets: + c_net = cnets[prev_cnet] + else: + c_net = control_net.copy().set_cond_hint(face_kps.movedim(-1, 1), cn_strength, (start_at, end_at)) + c_net.set_previous_controlnet(prev_cnet) + cnets[prev_cnet] = c_net + d['control'] = c_net + d['control_apply_to_uncond'] = False + d['cross_attn_controlnet'] = image_prompt_embeds.to(comfy.model_management.intermediate_device()) if is_cond else uncond_image_prompt_embeds.to(comfy.model_management.intermediate_device()) + if mask is not None and is_cond: + d['mask'] = mask + d['set_area_to_bounds'] = False + n = [t[0], d] + c.append(n) + cond_uncond.append(c) + is_cond = False + return (work_model, cond_uncond[0], cond_uncond[1]) +``` \ No newline at end of file diff --git a/docs/ApplyInstantIDAdvanced.md b/docs/ApplyInstantIDAdvanced.md new file mode 100644 index 0000000..731ac62 --- /dev/null +++ b/docs/ApplyInstantIDAdvanced.md @@ -0,0 +1,81 @@ +# Documentation +- Class name: ApplyInstantIDAdvanced +- Category: ImageProcessing +- Output node: False +- Repo Ref: https://github.com/cubiq/ComfyUI_InstantID.git + +ApplyInstantIDAdvanced节点通过使用控制网络和调节输入来应用高级图像处理技术,以增强面部识别能力。 + +# Input types +## Required +- instantid + - InstantID对于在图像数据中识别和跟踪个体至关重要,作为节点处理的唯一标识符。 + - Comfy dtype: INSTANTID + - Python dtype: str +- insightface + - InsightFace提供了面部特征提取和识别所需的分析框架,这对节点的功能至关重要。 + - Comfy dtype: FACEANALYSIS + - Python dtype: str +- control_net + - 控制网络对于指导节点的面部分析至关重要,确保面部特征的准确和高效处理。 + - Comfy dtype: CONTROL_NET + - Python dtype: str +- image + - 图像输入对节点的操作至关重要,提供了面部识别和增强的视觉数据。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- model + - 模型参数对于节点应用高级面部识别算法和提高结果准确性至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- positive + - 正向调节输入对于完善面部识别过程至关重要,确保节点输出准确和相关的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- negative + - 负向调节输入有助于过滤掉不相关或不正确的面部特征,提高节点产生精确结果的能力。 + - Comfy dtype: CONDITIONING + - Python dtype: str +## Optional +- ip_weight + - IP权重参数影响面部识别过程中对InstantID的重视程度,影响结果的整体准确性和相关性。 + - Comfy dtype: FLOAT + - Python dtype: float +- cn_strength + - 控制网强度参数调整控制网对面部分析的影响,影响节点操作的精确性和有效性。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_at + - start_at参数定义了面部特征分析范围的开始,这对于将节点的处理集中在图像的特定区域很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_at + - end_at参数指定了面部特征分析范的结束,确保节点的处理限制在图像的相关部分。 + - Comfy dtype: FLOAT + - Python dtype: float +- noise + - 噪声参数在面部识别过程中引入受控的随机性,这可以帮助提高节点结果的鲁棒性。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output_image + - 输出图像是节点操作的结果,展示了增强的面部特征和改进的识别能力。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- output_results + - 输出结果包含有关面部识别过程的详细信息,包括识别的特征及其对应的置信度分数。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ApplyInstantIDAdvanced(ApplyInstantID): + + @classmethod + def INPUT_TYPES(s): + return {'required': {'instantid': ('INSTANTID',), 'insightface': ('FACEANALYSIS',), 'control_net': ('CONTROL_NET',), 'image': ('IMAGE',), 'model': ('MODEL',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'ip_weight': ('FLOAT', {'default': 0.8, 'min': 0.0, 'max': 3.0, 'step': 0.01}), 'cn_strength': ('FLOAT', {'default': 0.8, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'start_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_at': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'noise': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.1})}, 'optional': {'image_kps': ('IMAGE',), 'mask': ('MASK',)}} +``` \ No newline at end of file diff --git a/docs/ApplyInstantIDControlNet.md b/docs/ApplyInstantIDControlNet.md new file mode 100644 index 0000000..c7e418b --- /dev/null +++ b/docs/ApplyInstantIDControlNet.md @@ -0,0 +1,111 @@ +# Documentation +- Class name: ApplyInstantIDControlNet +- Category: InstantID +- Output node: False +- Repo Ref: https://github.com/cubiq/ComfyUI_InstantID.git + +该节点基于给定的嵌入和关键点信息应用控制网络来修改图像中的面部特征。它根据指定的正面和负面调节输入调整面部外观,允许微调面部表情和结构。 + +# Input types +## Required +- face_embeds + - 该参数包含面部嵌入,对于节点的操作至关重要,因为它们提供了将要被操作的面部的基础表示。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] +- control_net + - 控制网络对于应用面部特征的更改至关重要。它根据调节输入作为修改的指南。 + - Comfy dtype: CONTROL_NET + - Python dtype: torch.nn.Module +- image_kps + - 图像的关键点信息至关重要,因为它提供了面部特征的空间上下文,确保根据控制网络进行精确调整。 + - Comfy dtype: IMAGE + - Python dtype: np.ndarray +- positive + - 正面调节输入作为期望的面部特征的参考,指导节点实现预期的外观。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict[str, Any]]] +- negative + - 负面调节输入通过与正面输入形成对比,帮助避免不希望的特征,提高面部调整的精确度。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict[str, Any]]] +- strength + - 强度参数决定了控制网络对面部特征影响的强度,允许根据输入值进行微妙或显著的变化。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_at + - 该参数定义了控制网络影响的起点,使节点能够逐渐或从一开始就应用更改。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_at + - 结束点参数指定何时结束控制网络的调整,确保面部特征修改的控制过渡。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- mask + - 当提供掩码参数时,它允许通过指定应应用或排除更改的图像区域来进行有针对性的调整。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- positive + - 输出的正面参数代表基于输入正面调节的修改后的面部特征,反映了节点的调整。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict[str, Any]]] +- negative + - 输出的负面参数显示了对输入负面调节所做的更改,展示了节点在完善面部特征的同时避免不希望的特质的能力。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict[str, Any]]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ApplyInstantIDControlNet: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'face_embeds': ('FACE_EMBEDS',), 'control_net': ('CONTROL_NET',), 'image_kps': ('IMAGE',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'start_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_at': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001})}, 'optional': {'mask': ('MASK',)}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('positive', 'negative') + FUNCTION = 'apply_controlnet' + CATEGORY = 'InstantID' + + def apply_controlnet(self, face_embeds, control_net, image_kps, positive, negative, strength, start_at, end_at, mask=None): + self.device = comfy.model_management.get_torch_device() + if strength == 0: + return (positive, negative) + if mask is not None: + mask = mask.to(self.device) + if mask is not None and len(mask.shape) < 3: + mask = mask.unsqueeze(0) + image_prompt_embeds = face_embeds['cond'] + uncond_image_prompt_embeds = face_embeds['uncond'] + cnets = {} + cond_uncond = [] + control_hint = image_kps.movedim(-1, 1) + is_cond = True + for conditioning in [positive, negative]: + c = [] + for t in conditioning: + d = t[1].copy() + prev_cnet = d.get('control', None) + if prev_cnet in cnets: + c_net = cnets[prev_cnet] + else: + c_net = control_net.copy().set_cond_hint(control_hint, strength, (start_at, end_at)) + c_net.set_previous_controlnet(prev_cnet) + cnets[prev_cnet] = c_net + d['control'] = c_net + d['control_apply_to_uncond'] = False + d['cross_attn_controlnet'] = image_prompt_embeds.to(comfy.model_management.intermediate_device()) if is_cond else uncond_image_prompt_embeds.to(comfy.model_management.intermediate_device()) + if mask is not None and is_cond: + d['mask'] = mask + d['set_area_to_bounds'] = False + n = [t[0], d] + c.append(n) + cond_uncond.append(c) + is_cond = False + print(cond_uncond[0]) + return (cond_uncond[0], cond_uncond[1]) +``` \ No newline at end of file diff --git a/docs/ApplyRegionalIPAdapters %2F%2FInspire.md b/docs/ApplyRegionalIPAdapters %2F%2FInspire.md new file mode 100644 index 0000000..a5d49ce --- /dev/null +++ b/docs/ApplyRegionalIPAdapters %2F%2FInspire.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: ApplyRegionalIPAdapters +- Category: InspirePack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +‘ApplyRegionalIPAdapters’节点旨在将一组区域性IP适配器集成并应用于给定的模型管道中。它通过动态地根据指定区域整合各种适配器来简化增强模型功能的过程。该节点旨在优化模型针对特定区域特征的性能,从而提高模型输出的准确性和相关性。 + +# Input types +## Required +- ipadapter_pipe + - ‘ipadapter_pipe’参数是将IP适配器集成管道传递给节点的关键通道。它包含了包括IP适配器本身、模型和其他辅助工具在内的必要组件,这些组件对于节点有效地执行其区域适功能至关重要。 + - Comfy dtype: TUPLE + - Python dtype: Tuple[IPAdapter, Model, ClipVision, InsightFace, LoraLoader] +## Optional +- regional_ipadapter1 + - ‘regional_ipadapter1’参数允许根据区域需求定制IP适配器。它提供了灵活性,以更好地适应特定区域环境,从而增强模型的功能,提高节点的适应性和有效性。 + - Comfy dtype: REGIONAL_IPADAPTER + - Python dtype: RegionalIPAdapter + +# Output types +- MODEL + - 输出‘MODEL’代表已经用区域性IP适配器进行了适配的模型。它标志着节点处理的完成,此时模型已经能够更加熟练地处理区域特定的任务。 + - Comfy dtype: MODEL + - Python dtype: Model + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ApplyRegionalIPAdapters: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ipadapter_pipe': ('IPADAPTER_PIPE',), 'regional_ipadapter1': ('REGIONAL_IPADAPTER',)}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Regional' + + def doit(self, **kwargs): + ipadapter_pipe = kwargs['ipadapter_pipe'] + (ipadapter, model, clip_vision, insightface, lora_loader) = ipadapter_pipe + del kwargs['ipadapter_pipe'] + for (k, v) in kwargs.items(): + ipadapter_pipe = (ipadapter, model, clip_vision, insightface, lora_loader) + model = v.doit(ipadapter_pipe) + return (model,) +``` \ No newline at end of file diff --git a/docs/ApplyStableSRUpscaler.md b/docs/ApplyStableSRUpscaler.md new file mode 100644 index 0000000..3ba053b --- /dev/null +++ b/docs/ApplyStableSRUpscaler.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: ApplyStableSRUpscaler +- Category: image/upscaling +- Output node: False +- Repo Ref: https://github.com/Arthurzhangsheng/Comfyui-StableSR.git + +该节点利用StableSR模型的能力,提高输入图像的分辨率,同时保持其视觉完整性。它专注于应用先进的上采样技术,以产生高质量、详细的图像,而不损害原始内容。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了节点将操作的基础结构和功能。对于上采样过程来说,拥有一个有效的模型是确保正确应用StableSR技术的关键。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- stablesr_model + - stablesr_model参数至关重要,因为它指定了StableSR模型检查点的路径,其中包含上采样过程所需的预训练权重。没有一个正确且可访问的模型路径,节点无法执行其预期功能。 + - Comfy dtype: COMBO[folder_paths.get_filename_list('stablesr')] + - Python dtype: str +## Optional +- latent_image + - 当提供latent_image参数时,允许节点将额外信息纳入上采样过程。这可以通过考虑输入的潜在特征来完善输出,有可能带来更好的视觉结果。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Output types +- model_sr + - 输出模型model_sr是将StableSR上采样技术应用于输入模型的结果。它代表了原始模型的增强版本,具有更高的分辨率和细节,准备用于进一步的使用或分析。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ApplyStableSRUpscaler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'stablesr_model': (folder_paths.get_filename_list('stablesr'),)}, 'optional': {'latent_image': ('LATENT',)}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'apply_stable_sr_upscaler' + CATEGORY = 'image/upscaling' + + def apply_stable_sr_upscaler(self, model, stablesr_model, latent_image=None): + stablesr_model_path = folder_paths.get_full_path('stablesr', stablesr_model) + if not os.path.isfile(stablesr_model_path): + raise Exception(f'[StableSR] Invalid StableSR model reference') + upscaler = StableSR(stablesr_model_path, dtype=comfy.model_management.unet_dtype(), device='cpu') + if latent_image != None: + latent_image = model.model.process_latent_in(latent_image['samples']) + upscaler.set_latent_image(latent_image) + else: + upscaler.set_auto_set_latent(True) + model_sr = model.clone() + model_sr.set_model_unet_function_wrapper(upscaler) + return (model_sr,) +``` \ No newline at end of file diff --git a/docs/AreaToMask.md b/docs/AreaToMask.md new file mode 100644 index 0000000..d7ae0a3 --- /dev/null +++ b/docs/AreaToMask.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: AreaToMask +- Category: ♾️Mixlab/Mask +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点将带有RGBA通道的图像转换为掩码,专注于通过移除透明度和应用切割技术来隔离感兴趣的特定区域。它强调在图像处理领域内对视觉数据进行转换以进行进一步的分析或操作。 + +# Input types +## Required +- RGBA + - RGBA输入至关重要,因为它提供了节点执行转换为掩码所需的原始图像数据。它是节点操作的基础,决定了结果掩码的质量和范围。 + - Comfy dtype: image + - Python dtype: PIL.Image + +# Output types +- MASK + - 输出掩码是节点操作的重要产物,代表了输入图像中感兴趣的隔离区域。它作为后续图像处理任务的关键组成部分,使得精确的操作和分析成为可能。 + - Comfy dtype: tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AreaToMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'RGBA': ('RGBA',)}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Mask' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False,) + + def run(self, RGBA): + mask = AreaToMask_run(RGBA) + return (mask,) +``` \ No newline at end of file diff --git a/docs/ArithmeticBlend.md b/docs/ArithmeticBlend.md new file mode 100644 index 0000000..1262e81 --- /dev/null +++ b/docs/ArithmeticBlend.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: ArithmeticBlend +- Category: postprocessing/Blends +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +该节点通过算术运算实现两幅图像的合成,通过选择的混合模式(blend_mode)来创建视觉效果,实现对image1和image2的融合。 + +# Input types +## Required +- image1 + - 要混合的第一幅图像,对于算术运算的发生至关重要,并影响最终输出结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image2 + - 参与混合过程的第二幅图像,与image1相互作用,决定了生成的混合图像的特征。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- blend_mode + - 算术运算的模式,决定了如何组合image1和image2,显著影响最终的视觉结果。 + - Comfy dtype: COMBO['add', 'subtract', 'difference'] + - Python dtype: str + +# Output types +- blended_image + - 算术混合过程后的生成图像,包含了所选混合模式的视觉效应。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ArithmeticBlend: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image1': ('IMAGE',), 'image2': ('IMAGE',), 'blend_mode': (['add', 'subtract', 'difference'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'arithmetic_blend_images' + CATEGORY = 'postprocessing/Blends' + + def arithmetic_blend_images(self, image1: torch.Tensor, image2: torch.Tensor, blend_mode: str): + if blend_mode == 'add': + blended_image = self.add(image1, image2) + elif blend_mode == 'subtract': + blended_image = self.subtract(image1, image2) + elif blend_mode == 'difference': + blended_image = self.difference(image1, image2) + else: + raise ValueError(f'Unsupported arithmetic blend mode: {blend_mode}') + blended_image = torch.clamp(blended_image, 0, 1) + return (blended_image,) + + def add(self, img1, img2): + return img1 + img2 + + def subtract(self, img1, img2): + return img1 - img2 + + def difference(self, img1, img2): + return torch.abs(img1 - img2) +``` \ No newline at end of file diff --git a/docs/AsciiArt.md b/docs/AsciiArt.md new file mode 100644 index 0000000..a25e0fb --- /dev/null +++ b/docs/AsciiArt.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: AsciiArt +- Category: postprocessing/Effects +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +AsciiArt节点对输入图像应用ASCII艺术效果,将其转换成使用预定义字符集的样式化表示。它利用像素强度来选择适当的字符,从而创建图像内容的文本表示。 + +# Input types +## Required +- image + - 要应用ASCII艺术效果的输入图像。它应该是表示图像数据的张量。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- char_size + - ASCII艺术表示中使用的字符大小。此参数决定了ASCII艺术效果的粒度。 + - Comfy dtype: int + - Python dtype: int +- font_size + - 用于ASCII艺术字符的字体大小。这影响最终ASCII艺术图像的外观。 + - Comfy dtype: int + - Python dtype: int + +# Output types +- result + - 应用ASCII艺术效果后的结果图像。它是表示输入图像样式化ASCII艺术版本的张量。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AsciiArt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'char_size': ('INT', {'default': 12, 'min': 0, 'max': 64, 'step': 2}), 'font_size': ('INT', {'default': 12, 'min': 0, 'max': 64, 'step': 2})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'apply_ascii_art_effect' + CATEGORY = 'postprocessing/Effects' + + def apply_ascii_art_effect(self, image: torch.Tensor, char_size: int, font_size: int): + (batch_size, height, width, channels) = image.shape + result = torch.zeros_like(image) + for b in range(batch_size): + img_b = image[b] * 255.0 + img_b = Image.fromarray(img_b.numpy().astype('uint8'), 'RGB') + result_b = ascii_art_effect(img_b, char_size, font_size) + result_b = torch.tensor(np.array(result_b)) / 255.0 + result[b] = result_b + return (result,) +``` \ No newline at end of file diff --git a/docs/Asymmetric Tiled KSampler.md b/docs/Asymmetric Tiled KSampler.md new file mode 100644 index 0000000..751e23b --- /dev/null +++ b/docs/Asymmetric Tiled KSampler.md @@ -0,0 +1,118 @@ +# Documentation +- Class name: Asymmetric_Tiled_KSampler +- Category: Sampling/Tiled +- Output node: False +- Repo Ref: https://github.com/FlyingFireCo/tiled_ksampler.git + +Asymmetric_Tiled_KSampler 节点旨在对潜在空间执行高效且可定制的采样操作。它通过对模型的卷积层应用不对称平铺来实现这一点,从而允许生成具有无缝纹理的图像。该节点特别适用于通过平铺较小的图像段来创建大型、高分辨率的图像。它强调了采样过程中的灵活性和控制性,满足了各种创意和技术需求,而不涉及底层方法的具体细节。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了用于采样过程的神经网络架构。它直接影响节点生成图像的能力和产生的结果质量。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +## Optional +- seed + - 种子参数对于采样过程的可重复性很重要。它确保相同的初始条件将导致相同的结果,这对于调试和一致的输出生成非常有价值。 + - Comfy dtype: INT + - Python dtype: int +- tileX + - tileX 参数决定了沿 X 轴的平铺行为。它对于控制图像如何被划分为用于生成无缝纹理的段至关重要。 + - Comfy dtype: INT + - Python dtype: int +- tileY + - tileY 参数控制沿 Y 轴的平铺,与 tileX 类似,但用于垂直方向。它在整体图像构图中扮演着重要角色。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步骤参数指定了采样过程将经历的迭代次数。它是决定细节水平和最终输出外观的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg 参数,代表配置规模,用于调整采样过程对条件输入的敏感度。它是微调输出以满足特定要求的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name 参数从预定义的选项集中选择要使用的采样方法。对于将采样技术定制到手头任务的特定需求至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- scheduler + - scheduler 参数确定将指导采样过程的调度算法。它是采样操作效率和有效性的一个显著因素。 + - Comfy dtype: STRING + - Python dtype: str +- positive + - positive 参数向模型提供正向条件信息,用于指导采样过程朝着期望的结果发展。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- negative + - negative 参数提供负向条件,有助于避免在生成的图像中出现不需要的特征或伪影。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- latent_image + - latent_image 参数是采样过程的一个输入,代表要生成图像的初始状态或编码表示。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- denoise + - denoise 参数调整采样过程中应用的降噪水平。它是平衡图像细节和噪声之间权衡的重要控制。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- latent + - latent 输出代表采样过程后图像在潜在空间中的最终状态。它很重要,因为它可以被进一步处理或用于生成最终图像。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class Asymmetric_Tiled_KSampler: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('MODEL',), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'tileX': ('INT', {'default': 1, 'min': 0, 'max': 1}), 'tileY': ('INT', {'default': 1, 'min': 0, 'max': 1}), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'sample' + CATEGORY = 'Sampling/Tiled' + + def apply_asymmetric_tiling(self, model, tileX, tileY): + for layer in [layer for layer in model.modules() if isinstance(layer, torch.nn.Conv2d)]: + layer.padding_modeX = 'circular' if tileX else 'constant' + layer.padding_modeY = 'circular' if tileY else 'constant' + layer.paddingX = (layer._reversed_padding_repeated_twice[0], layer._reversed_padding_repeated_twice[1], 0, 0) + layer.paddingY = (0, 0, layer._reversed_padding_repeated_twice[2], layer._reversed_padding_repeated_twice[3]) + print(layer.paddingX, layer.paddingY) + + def __hijackConv2DMethods(self, model, tileX: bool, tileY: bool): + for layer in [l for l in model.modules() if isinstance(l, torch.nn.Conv2d)]: + layer.padding_modeX = 'circular' if tileX else 'constant' + layer.padding_modeY = 'circular' if tileY else 'constant' + layer.paddingX = (layer._reversed_padding_repeated_twice[0], layer._reversed_padding_repeated_twice[1], 0, 0) + layer.paddingY = (0, 0, layer._reversed_padding_repeated_twice[2], layer._reversed_padding_repeated_twice[3]) + + def make_bound_method(method, current_layer): + + def bound_method(self, *args, **kwargs): + return method(current_layer, *args, **kwargs) + return bound_method + bound_method = make_bound_method(self.__replacementConv2DConvForward, layer) + layer._conv_forward = bound_method.__get__(layer, type(layer)) + + def __replacementConv2DConvForward(self, layer, input: torch.Tensor, weight: torch.Tensor, bias: Optional[torch.Tensor]): + working = torch.nn.functional.pad(input, layer.paddingX, mode=layer.padding_modeX) + working = torch.nn.functional.pad(working, layer.paddingY, mode=layer.padding_modeY) + return torch.nn.functional.conv2d(working, weight, bias, layer.stride, (0, 0), layer.dilation, layer.groups) + + def __restoreConv2DMethods(self, model): + for layer in [l for l in model.modules() if isinstance(l, torch.nn.Conv2d)]: + layer._conv_forward = torch.nn.Conv2d._conv_forward.__get__(layer, torch.nn.Conv2d) + + def sample(self, model, seed, tileX, tileY, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=1.0): + self.__hijackConv2DMethods(model.model, tileX == 1, tileY == 1) + result = nodes.common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise) + self.__restoreConv2DMethods(model.model) + return result +``` \ No newline at end of file diff --git a/docs/Auto Pan Equilateral (mtb).md b/docs/Auto Pan Equilateral (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/AutoNegativePrompt.md b/docs/AutoNegativePrompt.md new file mode 100644 index 0000000..9185390 --- /dev/null +++ b/docs/AutoNegativePrompt.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: AutoNegativePrompt +- Category: OneButtonPrompt +- Output node: False +- Repo Ref: https://github.com/AIrjen/OneButtonPrompt + +该节点旨在基于给定的正面提示自动生成负面提示,增强两者之间的对比。它通过将输入文本中的正面情感替换为负面情感来创造性地修改文本,旨在提供鲜明的对比或对立点。节点的功能不仅限于直接文本反转,还包括使用预定义的负面属性列表来增强负面情感的能力。 + +# Input types +## Required +- postive_prompt + - 正面提示是节点操作的基础。它是将被转换成负面对应物的文本。此参数至关重要,因为它决定了生成负面提示的上下文和主题内容。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- base_negative + - 此参数提供了一个默认的负面提示,用作转换过程的起点。它对于建立节点可以进一步细化和增强的初始负面上下文很重要。 + - Comfy dtype: STRING + - Python dtype: str +- enhancenegative + - 此参数控制应用于负面提示的增强级别,加强负面属性,使与正面提示的对比更加明显。它影响生成的负面提示的总体语气和严重程度。 + - Comfy dtype: INT + - Python dtype: int +- insanitylevel + - 疯狂等级参数在转换过程中引入了随机性元素,模拟更混乱或不可预测的负面提示。它影响最终输出中包含的负面词汇的多样性和创造性。 + - Comfy dtype: INT + - Python dtype: int +- seed + - 种子参数通过为随机数生成器设置一个固定点来确保结果的可重复性。它对于保持节点操作的一致性至关重要,特别是在需要多次运行以进行测试或比较时。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- negative_prompt + - 该节点的输出是一个与原始正面提示形成对比的精炼负面提示。它封装了转换过程的本质,提供了创造性和细腻的负面情感表达。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AutoNegativePrompt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'postive_prompt': ('STRING', {'default': '', 'multiline': True})}, 'optional': {'base_negative': ('STRING', {'multiline': True, 'default': 'text, watermark'}), 'enhancenegative': ('INT', {'default': 0, 'min': 0, 'max': 1, 'step': 1}), 'insanitylevel': ('INT', {'default': 0, 'min': 0, 'max': 10, 'step': 1}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('negative_prompt',) + FUNCTION = 'Comfy_OBP_AutoNegativePrompt' + CATEGORY = 'OneButtonPrompt' + + def Comfy_OBP_AutoNegativePrompt(self, postive_prompt, insanitylevel, enhancenegative, base_negative, seed): + generatedprompt = build_dynamic_negative(postive_prompt, insanitylevel, enhancenegative, base_negative) + print('Generated negative prompt: ' + generatedprompt) + return (generatedprompt,) +``` \ No newline at end of file diff --git a/docs/BBoxListItemSelect(FaceParsing).md b/docs/BBoxListItemSelect(FaceParsing).md new file mode 100644 index 0000000..bd146c7 --- /dev/null +++ b/docs/BBoxListItemSelect(FaceParsing).md @@ -0,0 +1,46 @@ +# Documentation +- Class name: BBoxListItemSelect +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +该节点能够根据提供的索引值从列表中选取特定的边界框,同时确保选择过程不会超出列表界限。它旨在简化在较大数据集中访问单个边界框数据的过程。 + +# Input types +## Required +- bbox_list + - 该参数是一个边界框列表,作为根据索引选取所需边界框的数据集。它对节点的运行至关重要,因为它定义了可能选择的范围。 + - Comfy dtype: BBOX_LIST + - Python dtype: List[Dict[str, Union[int, float]]] +- index + - 该参数决定了从列表中选择边界框的位置。它非常重要,因为它直接影响最终从边界框列表中检索的项目。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- BBOX + - 输出是一个单一的边界框,代表根据提供的索引从输入列表中选择的项目。它是节点操作的结果,对进一步处理具有重要价值。 + - Comfy dtype: BBOX + - Python dtype: Dict[str, Union[int, float]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BBoxListItemSelect: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'bbox_list': ('BBOX_LIST', {}), 'index': ('INT', {'default': 0, 'min': 0, 'step': 1})}} + RETURN_TYPES = ('BBOX',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, bbox_list: list, index: int): + item = bbox_list[index if index < len(bbox_list) - 1 else len(bbox_list) - 1] + return (item,) +``` \ No newline at end of file diff --git a/docs/BBoxResize(FaceParsing).md b/docs/BBoxResize(FaceParsing).md new file mode 100644 index 0000000..a98353c --- /dev/null +++ b/docs/BBoxResize(FaceParsing).md @@ -0,0 +1,67 @@ +# Documentation +- Class name: BBoxResize +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +BBoxResize节点旨在将边界框(BBOX)的尺寸调整为适应新的图像尺寸。它执行一个缩放操作,确保边界框坐标按比例调整大小,同时不改变它们在图像中的相对位置。此节点对于在不同图像分辨率下保持对象检测的完整性至关重要。 + +# Input types +## Required +- bbox + - 参数'bbox'代表需要调整大小的边界框坐标。它对节点的操作至关重要,因为它决定了对象在图像中的初始位置和大小。 + - Comfy dtype: BBOX + - Python dtype: torch.Tensor +- width_old + - 参数'width_old'指定了相对于边界框坐标的原始图像宽度。它对于计算新尺寸的正确缩放因子是必要的。 + - Comfy dtype: INT + - Python dtype: int +- height_old + - 参数'height_old'定义了图像的原始高度。它在调整大小的过程中起着关键作用,确保边界框的垂直比例得以保持。 + - Comfy dtype: INT + - Python dtype: int +- width + - 参数'width'表示调整大小后图像的新宽度。它是节点计算调整后的边界框坐标的关键输入。 + - Comfy dtype: INT + - Python dtype: int +- height + - 参数'height'表示图像调整大小后的新高度。它对于在调整大小过程中保持边界框的纵横比至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- BBOX + - 输出'BBOX'是调整大小后的边界框坐标,已调整以适应新的图像尺寸。它很重要,因为它提供了调整大小后的图像中对象的更新位置和大小。 + - Comfy dtype: BBOX + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BBoxResize: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'bbox': ('BBOX', {}), 'width_old': ('INT', {}), 'height_old': ('INT', {}), 'width': ('INT', {}), 'height': ('INT', {})}} + RETURN_TYPES = ('BBOX',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, bbox: Tensor, width_old: int, height_old: int, width: int, height: int): + newBbox = bbox.clone() + bbox_values = newBbox.float() + l = bbox_values[0] / width_old * width + t = bbox_values[1] / height_old * height + r = bbox_values[2] / width_old * width + b = bbox_values[3] / height_old * height + newBbox[0] = l + newBbox[1] = t + newBbox[2] = r + newBbox[3] = b + return (newBbox,) +``` \ No newline at end of file diff --git a/docs/BLIP Analyze Image.md b/docs/BLIP Analyze Image.md new file mode 100644 index 0000000..00484a6 --- /dev/null +++ b/docs/BLIP Analyze Image.md @@ -0,0 +1,112 @@ +# Documentation +- Class name: WAS_BLIP_Analyze_Image +- Category: WAS Suite/Text/AI +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_BLIP_Analyze_Image节点旨在使用BLIP(Bootstrapped Language Image Pretraining)模型分析和解释图像内容。它提供了生成标题和用自然语言问题询问图像的功能,提供了对输入图像的视觉和上下文方面的洞察。 + +# Input types +## Required +- image + - 图像参数对节点的操作至关重要,因为它是模型分析以生成标题或回答问题的输入。它直接影响输出和分析质量。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +- mode + - 模式参数确定节点将对图像执行的分析类型。它可以是'caption'以生成描述,或者是'interrogate'以回答有关图像内容的问题。 + - Comfy dtype: COMBO['caption', 'interrogate'] + - Python dtype: str +## Optional +- question + - 当模式设置为'interrogate'时,使用问题参数。它指定了模型将根据图像内容尝试回答的查询。问题的措辞可以影响答案的准确性和相关性。 + - Comfy dtype: STRING + - Python dtype: str +- blip_model + - blip_model参数允许用户为节点提供预加载的BLIP模型,而不是下载新模型。这可以提高效率,并且在多次运行节点时特别有用。 + - Comfy dtype: BLIP_MODEL + - Python dtype: Tuple[torch.nn.Module, str] + +# Output types +- output + - 输出参数代表节点分析的结果,可以是描述图像的标题或对提出的询问性问题的回答。它概括了节点对图像内容的理解。 + - Comfy dtype: TEXT + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WAS_BLIP_Analyze_Image: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'mode': (['caption', 'interrogate'],), 'question': ('STRING', {'default': 'What does the background consist of?', 'multiline': True})}, 'optional': {'blip_model': ('BLIP_MODEL',)}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'blip_caption_image' + CATEGORY = 'WAS Suite/Text/AI' + + def blip_caption_image(self, image, mode, question, blip_model=None): + + def transformImage(input_image, image_size, device): + raw_image = input_image.convert('RGB') + raw_image = raw_image.resize((image_size, image_size)) + transform = transforms.Compose([transforms.Resize(raw_image.size, interpolation=InterpolationMode.BICUBIC), transforms.ToTensor(), transforms.Normalize((0.48145466, 0.4578275, 0.40821073), (0.26862954, 0.26130258, 0.27577711))]) + image = transform(raw_image).unsqueeze(0).to(device) + return image.view(1, -1, image_size, image_size) + from torchvision import transforms + from torchvision.transforms.functional import InterpolationMode + device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + conf = getSuiteConfig() + image = tensor2pil(image) + size = 384 + tensor = transformImage(image, size, device) + if blip_model: + mode = blip_model[1] + if mode == 'caption': + if blip_model: + model = blip_model[0].to(device) + else: + from .modules.BLIP.blip_module import blip_decoder + blip_dir = os.path.join(MODELS_DIR, 'blip') + if not os.path.exists(blip_dir): + os.makedirs(blip_dir, exist_ok=True) + torch.hub.set_dir(blip_dir) + if conf.__contains__('blip_model_url'): + model_url = conf['blip_model_url'] + else: + model_url = 'https://storage.googleapis.com/sfr-vision-language-research/BLIP/models/model_base_capfilt_large.pth' + model = blip_decoder(pretrained=model_url, image_size=size, vit='base') + model.eval() + model = model.to(device) + with torch.no_grad(): + caption = model.generate(tensor, sample=False, num_beams=6, max_length=74, min_length=20) + cstr(f'\x1b[33mBLIP Caption:\x1b[0m {caption[0]}').msg.print() + return (caption[0],) + elif mode == 'interrogate': + if blip_model: + model = blip_model[0].to(device) + else: + from .modules.BLIP.blip_module import blip_vqa + blip_dir = os.path.join(MODELS_DIR, 'blip') + if not os.path.exists(blip_dir): + os.makedirs(blip_dir, exist_ok=True) + torch.hub.set_dir(blip_dir) + if conf.__contains__('blip_model_vqa_url'): + model_url = conf['blip_model_vqa_url'] + else: + model_url = 'https://storage.googleapis.com/sfr-vision-language-research/BLIP/models/model_base_vqa_capfilt_large.pth' + model = blip_vqa(pretrained=model_url, image_size=size, vit='base') + model.eval() + model = model.to(device) + with torch.no_grad(): + answer = model(tensor, question, train=False, inference='generate') + cstr(f'\x1b[33m BLIP Answer:\x1b[0m {answer[0]}').msg.print() + return (answer[0],) + else: + cstr(f'The selected mode `{mode}` is not a valid selection!').error.print() + return ('Invalid BLIP mode!',) +``` \ No newline at end of file diff --git a/docs/BLIP Model Loader.md b/docs/BLIP Model Loader.md new file mode 100644 index 0000000..02dd620 --- /dev/null +++ b/docs/BLIP Model Loader.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: WAS_BLIP_Model_Loader +- Category: WAS Suite/Loaders +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_BLIP_Model_Loader节点旨在高效地加载和管理用于标题生成和询问任务的BLIP模型。它确保必要的包已安装,并处理BLIP模型的检索和初始化,在WAS套件内提供模型访问的简化接口。 + +# Input types +## Required +- blip_model + - 参数'blip_model'对于指定要加载的BLIP模型类型至关重要。它决定了节点将初始化用于标题生成还是询问的模型,从而影响整体功能和预期结果。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- BLIP_MODEL + - 输出BLIP_MODEL代表已加载的BLIP模型,准备用于标题生成或询问任务。它封装了模型的功能,是应用程序内进一步处理的中心组件。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WAS_BLIP_Model_Loader: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'blip_model': (['caption', 'interrogate'],)}} + RETURN_TYPES = ('BLIP_MODEL',) + FUNCTION = 'blip_model' + CATEGORY = 'WAS Suite/Loaders' + + def blip_model(self, blip_model): + if 'timm' not in packages() or 'transformers' not in packages() or 'fairscale' not in packages(): + cstr(f"Modules or packages are missing to use BLIP models. Please run the `{os.path.join(WAS_SUITE_ROOT, 'requirements.txt')}` through ComfyUI's python executable.").error.print() + exit + if 'transformers==4.26.1' not in packages(True): + cstr(f"`transformers==4.26.1` is required for BLIP models. Please run the `{os.path.join(WAS_SUITE_ROOT, 'requirements.txt')}` through ComfyUI's python executable.").error.print() + exit + device = 'cpu' + conf = getSuiteConfig() + size = 384 + if blip_model == 'caption': + from .modules.BLIP.blip_module import blip_decoder + blip_dir = os.path.join(MODELS_DIR, 'blip') + if not os.path.exists(blip_dir): + os.makedirs(blip_dir, exist_ok=True) + torch.hub.set_dir(blip_dir) + if conf.__contains__('blip_model_url'): + model_url = conf['blip_model_url'] + else: + model_url = 'https://storage.googleapis.com/sfr-vision-language-research/BLIP/models/model_base_capfilt_large.pth' + model = blip_decoder(pretrained=model_url, image_size=size, vit='base') + model.eval() + model = model.to(device) + elif blip_model == 'interrogate': + from .modules.BLIP.blip_module import blip_vqa + blip_dir = os.path.join(MODELS_DIR, 'blip') + if not os.path.exists(blip_dir): + os.makedirs(blip_dir, exist_ok=True) + torch.hub.set_dir(blip_dir) + if conf.__contains__('blip_model_vqa_url'): + model_url = conf['blip_model_vqa_url'] + else: + model_url = 'https://storage.googleapis.com/sfr-vision-language-research/BLIP/models/model_base_vqa_capfilt_large.pth' + model = blip_vqa(pretrained=model_url, image_size=size, vit='base') + model.eval() + model = model.to(device) + result = (model, blip_model) + return (result,) +``` \ No newline at end of file diff --git a/docs/BLVAEEncode.md b/docs/BLVAEEncode.md new file mode 100644 index 0000000..910b291 --- /dev/null +++ b/docs/BLVAEEncode.md @@ -0,0 +1,137 @@ +# Documentation +- Class name: BLVAEEncode +- Category: latent +- Output node: False +- Repo Ref: https://github.com/WASasquatch/WAS_Extras + +BLVAEEncode节点旨在使用变分自编码器(VAE)将图像编码为潜在空间表示。它提供了加载现有潜在表示或从输入图像编码新表示的功能。该节点还提供了管理潜在数据的选项,例如存储它以备将来使用或从工作流中删除它。 + +# Input types +## Required +- vae + - VAE参数对于编码过程至关重要,因为它代表了将用于将输入图像转换为潜在表示的变分自编码器模型。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +## Optional +- tiled + - tiled参数决定是否应以平铺方式执行编码过程,这对于处理较大的图像可能有益,因为这些图像在整体编码时可能无法全部装入内存。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- tile_size + - tile_size参数指定了图像将被划分为平铺编码的瓦片大小。当处理需要平铺方法的大型图像时,这是一个重要参数。 + - Comfy dtype: INT + - Python dtype: int +- store_or_load_latent + - store_or_load_latent参数控制节点是否应尝试从工作流加载潜在表示,或将新编码的潜在表示存储回工作流以供将来使用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- remove_latent_on_load + - 当设置为true时,remove_latent_on_load参数指示节点在成功加载潜在表示后从工作流中删除它,以释放空间和资源。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- delete_workflow_latent + - 当设置为true时,delete_workflow_latent参数指示节点删除工作流中的任何现有潜在表示,无论是否正在编码新的表示。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- image + - image参数是要编码到潜在空间的输入图像。当没有现有的潜在表示可以从工作流中加载时,这是一个强制性参数。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- extra_pnginfo + - extra_pnginfo参数用于存储和检索与图像相关的附加信息,例如元数据或编码过程可能需要的其他辅助数据。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, Any] +- unique_id + - unique_id参数是工作流中节点实例的唯一标识符,用于管理潜在表示的存储和检索。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- latent + - latent参数代表输入图像的编码潜在空间表示。它是BLVAEEncode节点的主要输出,并用于工作流中的进一步处理或分析。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class BLVAEEncode: + + def __init__(self): + self.VAEEncode = nodes.VAEEncode() + self.VAEEncodeTiled = nodes.VAEEncodeTiled() + self.last_hash = None + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'vae': ('VAE',), 'tiled': ('BOOLEAN', {'default': False}), 'tile_size': ('INT', {'default': 512, 'min': 320, 'max': 4096, 'step': 64}), 'store_or_load_latent': ('BOOLEAN', {'default': True}), 'remove_latent_on_load': ('BOOLEAN', {'default': True}), 'delete_workflow_latent': ('BOOLEAN', {'default': False})}, 'optional': {'image': ('IMAGE',)}, 'hidden': {'extra_pnginfo': 'EXTRA_PNGINFO', 'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('LATENT',) + RETURN_NAMES = ('latent',) + FUNCTION = 'encode' + CATEGORY = 'latent' + + def encode(self, vae, tiled, tile_size, store_or_load_latent, remove_latent_on_load, delete_workflow_latent, image=None, extra_pnginfo=None, unique_id=None): + workflow_latent = None + latent_key = f'latent_{unique_id}' + if self.last_hash and torch.is_tensor(image): + if self.last_hash is not self.sha256(image): + delete_workflow_latent = True + if torch.is_tensor(image): + self.last_hash = self.sha256(image) + if delete_workflow_latent: + if extra_pnginfo['workflow']['extra'].__contains__(latent_key): + try: + del extra_pnginfo['workflow']['extra'][latent_key] + except Exception: + print(f'Unable to delete latent image from workflow node: {unqiue_id}') + pass + if store_or_load_latent and unique_id: + if latent_key in extra_pnginfo['workflow']['extra']: + print(f'Loading latent image from workflow node: {unique_id}') + try: + workflow_latent = self.deserialize(extra_pnginfo['workflow']['extra'][latent_key]) + except Exception as e: + print('There was an issue extracting the latent tensor from the workflow. Is it corrupted?') + workflow_latent = None + if not torch.is_tensor(image): + raise ValueError(f'Node {unique_id}: There was no image provided, and workflow latent missing. Unable to proceed.') + if workflow_latent and remove_latent_on_load: + try: + del extra_pnginfo['workflow']['extra'][latent_key] + except Exception: + pass + if workflow_latent: + print(f'Loaded workflow latent from node: {unique_id}') + return (workflow_latent, {'extra_pnginfo': extra_pnginfo}) + if not torch.is_tensor(image): + raise ValueError(f'Node {unique_id}: No workflow latent was loaded, and no image provided to encode. Unable to proceed. ') + if tiled: + encoded = self.VAEEncodeTiled.encode(pixels=image, tile_size=tile_size, vae=vae) + else: + encoded = self.VAEEncode.encode(pixels=image, vae=vae) + if store_or_load_latent and unique_id: + print(f'Saving latent to workflow node {unique_id}') + new_workflow_latent = self.serialize(encoded[0]) + extra_pnginfo['workflow']['extra'][latent_key] = new_workflow_latent + return (encoded[0], {'extra_pnginfo': extra_pnginfo}) + + def sha256(self, tensor): + tensor_bytes = tensor.cpu().contiguous().numpy().tobytes() + hash_obj = hashlib.sha256() + hash_obj.update(tensor_bytes) + return hash_obj.hexdigest() + + def serialize(self, obj): + json_str = json.dumps(obj, default=lambda o: {'__tensor__': True, 'value': o.cpu().numpy().tolist()} if torch.is_tensor(o) else o.__dict__) + compressed_data = zlib.compress(json_str.encode('utf-8')) + base64_encoded = base64.b64encode(compressed_data).decode('utf-8') + return base64_encoded + + def deserialize(self, base64_str): + compressed_data = base64.b64decode(base64_str) + json_str = zlib.decompress(compressed_data).decode('utf-8') + obj = json.loads(json_str, object_hook=lambda d: torch.tensor(d['value']) if '__tensor__' in d else d) + return obj +``` \ No newline at end of file diff --git a/docs/BNK_AddCLIPSDXLParams.md b/docs/BNK_AddCLIPSDXLParams.md new file mode 100644 index 0000000..8e47abb --- /dev/null +++ b/docs/BNK_AddCLIPSDXLParams.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: AddCLIPSDXLParams +- Category: conditioning/advanced +- Output node: False +- Repo Ref: https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb + +AddCLIPSDXLParams节点旨在为高级编码任务处理和增强条件数据。它接受与图像尺寸和裁剪相关的各种参数,并将这些参数应用于条件输入,以准备后续编码步骤。该节点在确保编码过程适应目标应用的特定要求(如图像分辨率和裁剪规范)中发挥着关键作用。 + +# Input types +## Required +- conditioning + - 条件参数对节点至关重要,因为它提供了将被操作和准备进行编码的基础数据。这是一个关键的输入,它直接影响节点的输出和随后的编码过程。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Any] +- width + - 宽度参数指定要处理的图像的宽度。这是一个重要的输入,因为它决定了图像的水平分辨率,这可以显著影响编码质量和性能。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数定义了图像的垂直分辨率。它是一个关键的输入,与宽度一起决定了图像的整体大小,对编码过程至关重要。 + - Comfy dtype: INT + - Python dtype: int +- target_width + - target_width参数设置最终编码图像的期望宽度。这是一个重要的参数,它影响编码后图像的缩放和纵横比。 + - Comfy dtype: INT + - Python dtype: int +- target_height + - target_height参数设定最终编码图像的期望高度。它与target_width一起使用,以保持编码后图像的预期纵横比和尺寸。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- crop_w + - crop_w参数指示图像中裁剪区域的宽度。它是一个可选输入,可用于调整编码过程中图像中的兴趣区域。 + - Comfy dtype: INT + - Python dtype: int +- crop_h + - crop_h参数指定裁剪区域的高度。它与crop_w一起工作,以定义裁剪区域的尺寸,这对于将编码聚焦在图像的特定部分可能很重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- encoded_conditioning + - encoded_conditioning输出代表处理和增强的条件数据,可供编码流水线的后续阶段使用。它包含基于输入参数对原始条件进行的修改。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AddCLIPSDXLParams: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'conditioning': ('CONDITIONING',), 'width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'crop_w': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION}), 'crop_h': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION}), 'target_width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'target_height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION})}} + RETURN_TYPES = ('CONDITIONING',) + FUNCTION = 'encode' + CATEGORY = 'conditioning/advanced' + + def encode(self, conditioning, width, height, crop_w, crop_h, target_width, target_height): + c = [] + for t in conditioning: + n = [t[0], t[1].copy()] + n[1]['width'] = width + n[1]['height'] = height + n[1]['crop_w'] = crop_w + n[1]['crop_h'] = crop_h + n[1]['target_width'] = target_width + n[1]['target_height'] = target_height + c.append(n) + return (c,) +``` \ No newline at end of file diff --git a/docs/BNK_AddCLIPSDXLRParams.md b/docs/BNK_AddCLIPSDXLRParams.md new file mode 100644 index 0000000..d436e50 --- /dev/null +++ b/docs/BNK_AddCLIPSDXLRParams.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: AddCLIPSDXLRParams +- Category: conditioning/advanced +- Output node: False +- Repo Ref: https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb + +AddCLIPSDXLRParams节点旨在为高级编码任务增强输入条件数据。它接收条件数据,并将指定的尺寸和审美分数应用于每个元素,为后续处理做准备。 + +# Input types +## Required +- conditioning + - conditioning参数对于提供将由节点转换的初始数据至关重要。它是决定节点后续处理和输出的核心输入。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Any] +- width + - width参数指定要应用于条件数据中每个元素的宽度尺寸。它在确定编码数据的分辨率中起着关键作用。 + - Comfy dtype: INT + - Python dtype: float +- height + - height参数为条件数据中的元素设置高度尺寸。它对于控制编码输出的垂直分辨率很重要。 + - Comfy dtype: INT + - Python dtype: float +- ascore + - aesthetic_score参数为每个元素分配一个审美值,这可以根据所需的审美标准影响编码过程。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- conditioning + - 输出的conditioning是输入的转换版本,现在配备了指定的尺寸和审美分数,准备进行高级编码。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AddCLIPSDXLRParams: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'conditioning': ('CONDITIONING',), 'width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'ascore': ('FLOAT', {'default': 6.0, 'min': 0.0, 'max': 1000.0, 'step': 0.01})}} + RETURN_TYPES = ('CONDITIONING',) + FUNCTION = 'encode' + CATEGORY = 'conditioning/advanced' + + def encode(self, conditioning, width, height, ascore): + c = [] + for t in conditioning: + n = [t[0], t[1].copy()] + n[1]['width'] = width + n[1]['height'] = height + n[1]['aesthetic_score'] = ascore + c.append(n) + return (c,) +``` \ No newline at end of file diff --git a/docs/BNK_CLIPTextEncodeAdvanced.md b/docs/BNK_CLIPTextEncodeAdvanced.md new file mode 100644 index 0000000..9842d08 --- /dev/null +++ b/docs/BNK_CLIPTextEncodeAdvanced.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: AdvancedCLIPTextEncode +- Category: conditioning/advanced +- Output node: False +- Repo Ref: https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb + +AdvancedCLIPTextEncode节点旨在将文本输入处理和编码成可用于高级条件任务的形式。它利用CLIP模型的能力生成捕获文本语义属性的嵌入。该节点特别适用于需要对输入文本有更深入理解的应用,如生成模型或需要对输入文本有更深入理解的自然语言处理任务。 + +# Input types +## Required +- text + - 'text'参数是节点的主要输入,代表需要编码的文本。它应该是一个字符串,并且可以包含多行文本,允许处理更复杂和更长的文本输入。此参数至关重要,因为编码的质量在很大程度上取决于所提供文本的准确性和丰富性。 + - Comfy dtype: STRING + - Python dtype: str +- clip + - 'clip'参数指定用于文本编码的CLIP模型。它是一个必需的输入,因为节点依赖于CLIP模型的架构和能力,从文本输入生成有意义的嵌入。 + - Comfy dtype: CLIP + - Python dtype: Any +- token_normalization + - 'token_normalization'参数确定在编码之前文本中的标记是如何规范化的。它可以采用不同的策略,如'none'、'mean'、'length'或'length+mean',这会影响标记嵌入的分布和尺度。这个参数对于控制嵌入中的方差很重要,并且可以影响条件性能。 + - Comfy dtype: COMBO[none, mean, length, length+mean] + - Python dtype: str +- weight_interpretation + - 'weight_interpretation'参数影响编码过程中标记权重的解释方式。它提供各种选项,如'comfy'、'A1111'、'compel'、'comfy++'或'down_weight',每种选项都可能导致对文本某些方面的不同强调。此参数对于微调编码以符合下游任务的具体要求至关重要。 + - Comfy dtype: COMBO[comfy, A1111, compel, comfy++, down_weight] + - Python dtype: str +## Optional +- affect_pooled + - 'affect_pooled'参数是一个可选输入,用于控制是否应通过编码过程影响CLIP模型的池化输出。它接受'enable'或'disable'的值,这决定了池化输出是否包含在最终嵌入中。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- CONDITIONING + - AdvancedCLIPTextEncode节点的输出是一个张量,代表编码后的文本。这个张量用作进一步处理或生成任务的条件输入。它包含了从文本中提取的语义信息,提供了丰富和细致的表示,可以指导工作流程中的后续步骤。 + - Comfy dtype: TENSOR + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AdvancedCLIPTextEncode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True}), 'clip': ('CLIP',), 'token_normalization': (['none', 'mean', 'length', 'length+mean'],), 'weight_interpretation': (['comfy', 'A1111', 'compel', 'comfy++', 'down_weight'],)}} + RETURN_TYPES = ('CONDITIONING',) + FUNCTION = 'encode' + CATEGORY = 'conditioning/advanced' + + def encode(self, clip, text, token_normalization, weight_interpretation, affect_pooled='disable'): + (embeddings_final, pooled) = advanced_encode(clip, text, token_normalization, weight_interpretation, w_max=1.0, apply_to_pooled=affect_pooled == 'enable') + return ([[embeddings_final, {'pooled_output': pooled}]],) +``` \ No newline at end of file diff --git a/docs/BNK_CLIPTextEncodeSDXLAdvanced.md b/docs/BNK_CLIPTextEncodeSDXLAdvanced.md new file mode 100644 index 0000000..9a38a5e --- /dev/null +++ b/docs/BNK_CLIPTextEncodeSDXLAdvanced.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: AdvancedCLIPTextEncodeSDXL +- Category: conditioning/advanced +- Output node: False +- Repo Ref: https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb + +AdvancedCLIPTextEncodeSDXL节点旨在将文本输入处理和编码成可用于高级条件任务的形式。它利用SDXLClipModel的能力生成嵌入,这些嵌入捕获了文本的语义信息。此节点特别适用于需要对文本内容有细微理解的应用,例如自然语言处理或基于内容的过滤系统。 + +# Input types +## Required +- text_l + - 'text_l'参数是一个字符串,表示要编码的主要文本。这是一个关键的输入,因为文本的语义丰富度直接影响生成的嵌入的质量,这对于节点的下游任务至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- text_g + - 'text_g'参数作为节点的次要文本输入。它与'text_l'一起使用,以提供更全面的编码,同时考虑额外的文本上下文。这个参数对于从更广泛的文本细微差别中受益的应用至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- clip + - 'clip'参数是SDXLClipModel的一个实例,用于执行文本编码。这是一个强制性输入,因为模型是基于提供的文本输入生成嵌入的核心组件。 + - Comfy dtype: CLIP + - Python dtype: SDXLClipModel +## Optional +- token_normalization + - 'token_normalization'参数决定了在将标记嵌入聚合到最终嵌入之前,如何对它们进行归一化。它提供了不同的策略,这些策略可以影响生成的嵌入的分布和重要性,从而影响节点在下游任务中的性能。 + - Comfy dtype: COMBO[none, mean, length, length+mean] + - Python dtype: str +- weight_interpretation + - 'weight_interpretation'参数定义了在编码过程中解释与文本标记相关联的权重的方法。它可以显著改变对文本不同部分的强调,这对于需要特别关注文本元素的应用来说很重要。 + - Comfy dtype: COMBO[comfy, A1111, compel, comfy++, down_weight] + - Python dtype: str +- balance + - 'balance'参数在编码过程中调整文本的一般和特定方面的平衡。它是一个浮点值,允许微调编码,以更好地适应当前应用的要求。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- CONDITIONING + - AdvancedCLIPTextEncodeSDXL节点的输出是一个包含编码嵌入的'CONDITIONING'对象。这个输出很重要,因为它构成了高级条件任务的基础,允许进行更复杂和上下文感知的处理。 + - Comfy dtype: CONDITIONING + - Python dtype: Tuple[torch.Tensor, Dict[str, torch.Tensor]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AdvancedCLIPTextEncodeSDXL: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text_l': ('STRING', {'multiline': True}), 'text_g': ('STRING', {'multiline': True}), 'clip': ('CLIP',), 'token_normalization': (['none', 'mean', 'length', 'length+mean'],), 'weight_interpretation': (['comfy', 'A1111', 'compel', 'comfy++', 'down_weight'],), 'balance': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('CONDITIONING',) + FUNCTION = 'encode' + CATEGORY = 'conditioning/advanced' + + def encode(self, clip, text_l, text_g, token_normalization, weight_interpretation, balance, affect_pooled='disable'): + (embeddings_final, pooled) = advanced_encode_XL(clip, text_l, text_g, token_normalization, weight_interpretation, w_max=1.0, clip_balance=balance, apply_to_pooled=affect_pooled == 'enable') + return ([[embeddings_final, {'pooled_output': pooled}]],) +``` \ No newline at end of file diff --git a/docs/BNK_GetSigma.md b/docs/BNK_GetSigma.md new file mode 100644 index 0000000..f3e1ced --- /dev/null +++ b/docs/BNK_GetSigma.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: GetSigma +- Category: latent/noise +- Output node: False +- Repo Ref: https://github.com/BlenderNeko/ComfyUI_Noise.git + +该节点旨在计算sigma值,这是在生成模型上下文中衡量噪声或信噪比的指标。它处理模型在指定步骤范围内的输出,以确定sigma的变化,提供对模型行为和噪声特性的洞察。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了要分析的生成模型。它通过确定用于计算sigma值的数据来源,影响整个处理过程。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_management.Model +- sampler_name + - 采样器名称决定了从模型中采样的方法,这反过来影响了sigma的计算,因为它影响了采样数据的质量和分布。 + - Comfy dtype: COMBO[comfy.samplers.KSampler.SAMPLERS] + - Python dtype: str +- scheduler + - 调度器参数至关重要,因为它控制采样过程,包括去噪过程,这直接影响sigma的计算,通过改变采样数据中的噪声水平。 + - Comfy dtype: COMBO[comfy.samplers.KSampler.SCHEDULERS] + - Python dtype: str +- steps + - 步骤参数定义了计算sigma值的迭代范围,影响噪声分析的全面性。 + - Comfy dtype: INT + - Python dtype: int +- start_at_step + - 该参数指定了sigma计算的起始点,确定了噪声分析的初始状态及其在指定步骤中的演变。 + - Comfy dtype: INT + - Python dtype: int +- end_at_step + - 结束步骤参数设置了sigma计算的终点,影响了噪声分析的最终状态以及在步骤范围内sigma的整体变化。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- sigma + - 输出的sigma值代表了在指定步骤范围内噪声特性的变化,提供了模型在噪声减少和信号清晰度方面的性能度量。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: GPU + +# Source code +``` +class GetSigma: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'steps': ('INT', {'default': 10000, 'min': 0, 'max': 10000}), 'start_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'end_at_step': ('INT', {'default': 10000, 'min': 1, 'max': 10000})}} + RETURN_TYPES = ('FLOAT',) + FUNCTION = 'calc_sigma' + CATEGORY = 'latent/noise' + + def calc_sigma(self, model, sampler_name, scheduler, steps, start_at_step, end_at_step): + device = comfy.model_management.get_torch_device() + end_at_step = min(steps, end_at_step) + start_at_step = min(start_at_step, end_at_step) + real_model = None + comfy.model_management.load_model_gpu(model) + real_model = model.model + sampler = comfy.samplers.KSampler(real_model, steps=steps, device=device, sampler=sampler_name, scheduler=scheduler, denoise=1.0, model_options=model.model_options) + sigmas = sampler.sigmas + sigma = sigmas[start_at_step] - sigmas[end_at_step] + sigma /= model.model.latent_format.scale_factor + return (sigma.cpu().numpy(),) +``` \ No newline at end of file diff --git a/docs/BNK_InjectNoise.md b/docs/BNK_InjectNoise.md new file mode 100644 index 0000000..e658610 --- /dev/null +++ b/docs/BNK_InjectNoise.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: InjectNoise +- Category: latent/noise +- Output node: False +- Repo Ref: https://github.com/BlenderNeko/ComfyUI_Noise.git + +InjectNoise节点旨在向一组潜在表示中引入噪声,从而模拟噪声对生成过程的影响。它的作用是通过控制的变异性增强数据,这可以提高生成输出的鲁棒性和多样性。 + +# Input types +## Required +- latents + - latents参数至关重要,因为它包含将要进行噪声注入的原始潜在表示。它直接影响噪声增强过程的结果。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- strength + - strength参数决定了要注入到latents中的噪声的强度。它对于控制引入数据的变异程度至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- noise + - 可选的noise参数提供了要应用于latents的噪声源。它很重要,因为它允许定制噪声特性。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- mask + - 当提供mask参数时,它指定latents的哪些区域应该受到噪声的影响。这对于针对性的噪声应用很重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- latents + - 输出的latents是已经注入了噪声的修改后的潜在表示,准备进行进一步的处理或生成。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class InjectNoise: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latents': ('LATENT',), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 200.0, 'step': 0.01})}, 'optional': {'noise': ('LATENT',), 'mask': ('MASK',)}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'inject_noise' + CATEGORY = 'latent/noise' + + def inject_noise(self, latents, strength, noise=None, mask=None): + s = latents.copy() + if noise is None: + return (s,) + if latents['samples'].shape != noise['samples'].shape: + print('warning, shapes in InjectNoise not the same, ignoring') + return (s,) + noised = s['samples'].clone() + noise['samples'].clone() * strength + if mask is not None: + mask = prepare_mask(mask, noised.shape) + noised = mask * noised + (1 - mask) * latents['samples'] + s['samples'] = noised + return (s,) +``` \ No newline at end of file diff --git a/docs/BNK_NoisyLatentImage.md b/docs/BNK_NoisyLatentImage.md new file mode 100644 index 0000000..605232f --- /dev/null +++ b/docs/BNK_NoisyLatentImage.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: NoisyLatentImage +- Category: latent/noise +- Output node: False +- Repo Ref: https://github.com/BlenderNeko/ComfyUI_Noise.git + +该节点生成嘈杂的潜在变量,这对于各种生成模型产生图像至关重要。它在潜在空间中引入噪声,有助于从训练好的模型中创建多样化的输出。该节点的设计确保噪声是按程序生成的,并且能够适应不同模型的需求。 + +# Input types +## Required +- source + - source参数决定计算是在CPU还是GPU上执行。这个选择显著影响节点的性能,GPU能够加快涉及大量数据和复杂计算任务的执行速度。 + - Comfy dtype: COMBO[('CPU', 'GPU'),] + - Python dtype: str +- seed + - seed参数对于噪声生成过程的可重复性至关重要。它确保每次执行节点时使用同一套随机数,从而得到一致的结果。 + - Comfy dtype: INT + - Python dtype: int +- width + - width参数指定生成图像的期望宽度。它影响分辨率,进而影响生成过程中的细节级别和所需的计算资源。 + - Comfy dtype: INT + - Python dtype: int +- height + - height参数设置要生成图像的高度。与宽度类似,它影响分辨率和计算需求,更高的值会导致更详细的图像和增加的处理需求。 + - Comfy dtype: INT + - Python dtype: int +- batch_size + - 批处理大小决定了并行处理的图像数量。增加批处理大小可以提高效率,但需要更多的内存和计算资源。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- samples + - samples输出包含生成的嘈杂潜在变量,它们作为后续生成模型的输入。这些潜在变量是创建多样化输出范围的基础,它们的质量和特征对最终结果至关重要。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class NoisyLatentImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'source': (['CPU', 'GPU'],), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'width': ('INT', {'default': 512, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'height': ('INT', {'default': 512, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'create_noisy_latents' + CATEGORY = 'latent/noise' + + def create_noisy_latents(self, source, seed, width, height, batch_size): + torch.manual_seed(seed) + if source == 'CPU': + device = 'cpu' + else: + device = comfy.model_management.get_torch_device() + noise = torch.randn((batch_size, 4, height // 8, width // 8), dtype=torch.float32, device=device).cpu() + return ({'samples': noise},) +``` \ No newline at end of file diff --git a/docs/BNK_SlerpLatent.md b/docs/BNK_SlerpLatent.md new file mode 100644 index 0000000..2ee6467 --- /dev/null +++ b/docs/BNK_SlerpLatent.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: LatentSlerp +- Category: latent +- Output node: False +- Repo Ref: https://github.com/BlenderNeko/ComfyUI_Noise.git + +该节点在两组潜在向量之间执行球面线性插值(slerp),能够在不同的潜在状态之间提供平滑的过渡。这对于在连续潜在空间中生成中间表示特别有用。 + +# Input types +## Required +- latents1 + - 第一组潜在向量,作为插值的起始点。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- factor + - 插值因子,决定了在两组潜在集之间路径上的位置。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- latents2 + - 第二组潜在向量,代表插值的终点。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- mask + - 一个可选的掩码,可以用来选择性地将插值应用于潜在向量的某些元素。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- slerped_latents + - 插值后的潜在向量结果,代表输入潜在集之间的平滑过渡。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LatentSlerp: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latents1': ('LATENT',), 'factor': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01})}, 'optional': {'latents2': ('LATENT',), 'mask': ('MASK',)}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'slerp_latents' + CATEGORY = 'latent' + + def slerp_latents(self, latents1, factor, latents2=None, mask=None): + s = latents1.copy() + if latents2 is None: + return (s,) + if latents1['samples'].shape != latents2['samples'].shape: + print('warning, shapes in LatentSlerp not the same, ignoring') + return (s,) + slerped = slerp(factor, latents1['samples'].clone(), latents2['samples'].clone()) + if mask is not None: + mask = prepare_mask(mask, slerped.shape) + slerped = mask * slerped + (1 - mask) * latents1['samples'] + s['samples'] = slerped + return (s,) +``` \ No newline at end of file diff --git a/docs/BNK_TiledKSampler.md b/docs/BNK_TiledKSampler.md new file mode 100644 index 0000000..1bedbca --- /dev/null +++ b/docs/BNK_TiledKSampler.md @@ -0,0 +1,87 @@ +# Documentation +- Class name: TiledKSampler +- Category: sampling +- Output node: False +- Repo Ref: https://github.com/BlenderNeko/ComfyUI_TiledKSampler.git + +TiledKSampler节点旨在通过将任务划分为更小、更易管理的部分(称为瓦片)来促进高分辨率图像的生成。它通过应用用户定义的瓦片策略,并在多个步骤中迭代地完善图像,从而允许对采样过程进行复杂的控制,并能够整合各种条件输入来指导生成过程。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了用于生成图像样本的基础生成模型。它是决定输出类型和质量的核心组件。 + - Comfy dtype: MODEL + - Python dtype: comfy.sd.Model +- seed + - 种子用于初始化随机数生成器,确保图像采样过程在不同运行之间可复现和一致。 + - Comfy dtype: INT + - Python dtype: int +- tile_width + - 瓦片宽度决定了每个瓦片的水平维度,影响采样过程的粒度和最终图像的细节水平。 + - Comfy dtype: INT + - Python dtype: int +- tile_height + - 瓦片高度决定了每个瓦片的垂直维度,直接影响生成图像的整体结构和构图。 + - Comfy dtype: INT + - Python dtype: int +- tiling_strategy + - 瓦片策略参数定义了将图像划分为瓦片的方法,这可以显著改变采样过程的效率和质量。 + - Comfy dtype: COMBO + - Python dtype: str +- steps + - 步骤数量参数决定了迭代细化过程,更高的值导致更详细和细腻的图像生成。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数通常与模型特定设置相关,对图像采样的整体性能和输出质量起着关键作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 采样器名称参数指定了要使用的采样器类型,这可以极大地影响生成图像的风格和特征。 + - Comfy dtype: COMBO + - Python dtype: str +- scheduler + - 调度器参数定义了随时间调整采样过程的策略,影响图像生成的收敛性和稳定性。 + - Comfy dtype: COMBO + - Python dtype: str +- positive + - 正面条件输入用于引导图像生成朝向期望的特征或特性,对塑造最终输出起着关键作用。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Dict[str, Any]] +- negative + - 负面条件输入用于排除图像生成中的某些特征或特性,允许获得更受控和特定的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Dict[str, Any]] +- latent_image + - 潜在图像参数包含图像的初始潜在表示,通过采样过程迭代细化以生成最终图像。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, Any] +- denoise + - 去噪参数控制采样过程中应用的噪声减少水平,影响生成图像的清晰度和质量。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- latent_image + - 输出潜在图像包含采样过程后细化的潜在表示,封装了最终生成的图像及其相关的元数据。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class TiledKSampler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'tile_width': ('INT', {'default': 512, 'min': 256, 'max': MAX_RESOLUTION, 'step': 64}), 'tile_height': ('INT', {'default': 512, 'min': 256, 'max': MAX_RESOLUTION, 'step': 64}), 'tiling_strategy': (['random', 'random strict', 'padded', 'simple'],), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'sample' + CATEGORY = 'sampling' + + def sample(self, model, seed, tile_width, tile_height, tiling_strategy, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise): + steps_total = int(steps / denoise) + return sample_common(model, 'enable', seed, tile_width, tile_height, tiling_strategy, steps_total, cfg, sampler_name, scheduler, positive, negative, latent_image, steps_total - steps, steps_total, 'disable', denoise=1.0, preview=True) +``` \ No newline at end of file diff --git a/docs/BNK_TiledKSamplerAdvanced.md b/docs/BNK_TiledKSamplerAdvanced.md new file mode 100644 index 0000000..1dd7519 --- /dev/null +++ b/docs/BNK_TiledKSamplerAdvanced.md @@ -0,0 +1,102 @@ +# Documentation +- Class name: TiledKSamplerAdvanced +- Category: sampling +- Output node: False +- Repo Ref: https://github.com/BlenderNeko/ComfyUI_TiledKSampler.git + +TiledKSamplerAdvanced类通过将采样空间划分为独立的瓦片并单独处理它们,从而实现高级采样程序。这种方法提高了采样过程的效率和控制能力,允许对生成的样本进行精细的操作。它整合了噪声管理、瓦片策略和条件输入,以实现高质量和细致的输出。 + +# Input types +## Required +- model + - 模型参数对于采样过程至关重要,它定义了采样过程的基础架构和参数。它决定了可以处理的数据类型和输出的质量。 + - Comfy dtype: MODEL + - Python dtype: comfy.sd.Model +- add_noise + - 此参数控制是否在采样过程中引入噪声,从而影响生成样本的多样性和随机性。这对于实现多样化的结果至关重要。 + - Comfy dtype: COMBO + - Python dtype: str +- noise_seed + - 噪声种子参数在确保噪声生成过程的可重复性方面起着重要作用。当使用相同的种子时,它允许产生一致的结果。 + - Comfy dtype: INT + - Python dtype: int +- tile_width + - 瓦片宽度参数决定了每个瓦片的水平维度,影响了采样过程的粒度。它在实现对生成样本空间分布的详细控制方面非常关键。 + - Comfy dtype: INT + - Python dtype: int +- tile_height + - 瓦片高度参数设置了每个瓦片的垂直维度,影响了采样过程的粒度和长宽比。它对于微调输出的空间排列非常重要。 + - Comfy dtype: INT + - Python dtype: int +- tiling_strategy + - 瓦片策略参数决定了用于划分采样空间的方法,这可以显著影响采样过程的效率和一致性。 + - Comfy dtype: COMBO + - Python dtype: str +- steps + - 步骤参数定义了采样过程将要经历的迭代次数。它直接影响最终输出的复杂性和精细度。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数调整采样器的配置设置,影响采样过程的行为和性能。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 采样器名称参数指定了要使用的采样器类型,这决定了样本生成的基本方法,并影响整体结果。 + - Comfy dtype: COMBO + - Python dtype: str +- scheduler + - 调度器参数决定了采样器的调度策略,影响了采样过程的进展和节奏。 + - Comfy dtype: COMBO + - Python dtype: str +- positive + - 正面参数提供了正面的条件输入,引导采样过程朝着期望的结果发展,塑造生成样本的特征。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Dict[str, Any]] +- negative + - 负面参数提供负面的条件输入,通过避免不希望的结果来帮助完善采样过程。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Dict[str, Any]] +- latent_image + - 潜在图像参数包含图像的潜在表示,这是采样过程的核心输入。它直接影响生成样本的质量和特性。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, Any] +- start_at_step + - 开始步骤参数指定了采样过程的初始步骤,设置了样本生成的起点。 + - Comfy dtype: INT + - Python dtype: int +- end_at_step + - 结束步骤参数定义了采样过程的最终步骤,决定了样本生成的终点。 + - Comfy dtype: INT + - Python dtype: int +- return_with_leftover_noise + - 返回剩余噪声参数控制是否在最终输出中包含残余噪声,这可以影响生成样本的纹理和外观。 + - Comfy dtype: COMBO + - Python dtype: str +- preview + - 预览参数启用或禁用采样过程中的预览图像生成,提供关于进度的视觉反馈。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- preview + - 预览参数启用或禁用采样过程中的预览图像生成,提供关于进度的视觉反馈。 + - Comfy dtype: COMBO + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class TiledKSamplerAdvanced: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'add_noise': (['enable', 'disable'],), 'noise_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'tile_width': ('INT', {'default': 512, 'min': 256, 'max': MAX_RESOLUTION, 'step': 64}), 'tile_height': ('INT', {'default': 512, 'min': 256, 'max': MAX_RESOLUTION, 'step': 64}), 'tiling_strategy': (['random', 'random strict', 'padded', 'simple'],), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'start_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'end_at_step': ('INT', {'default': 10000, 'min': 0, 'max': 10000}), 'return_with_leftover_noise': (['disable', 'enable'],), 'preview': (['disable', 'enable'],)}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'sample' + CATEGORY = 'sampling' + + def sample(self, model, add_noise, noise_seed, tile_width, tile_height, tiling_strategy, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, start_at_step, end_at_step, return_with_leftover_noise, preview, denoise=1.0): + return sample_common(model, add_noise, noise_seed, tile_width, tile_height, tiling_strategy, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, start_at_step, end_at_step, return_with_leftover_noise, denoise=1.0, preview=preview == 'enable') +``` \ No newline at end of file diff --git a/docs/BNK_Unsampler.md b/docs/BNK_Unsampler.md new file mode 100644 index 0000000..237e336 --- /dev/null +++ b/docs/BNK_Unsampler.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: Unsampler +- Category: sampling +- Output node: False +- Repo Ref: https://github.com/BlenderNeko/ComfyUI_Noise.git + +Unsampler类通过迭代细化潜在空间来促进从给定模型生成高保真样本的过程。它旨在通过控制的采样过程改善生成图像的质量,并允许使用条件输入来指导生成。这个节点对于需要详细控制采样过程和有能力整合各种条件因素的应用至关重要。 + +# Input types +## Required +- model + - 模型参数至关重要,它定义了Unsampler操作的生成基础。它是决定输出样本类型和质量的核心组件。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- steps + - 步骤参数对于采样过程至关重要,它决定了Unsampler将执行的迭代次数,以细化潜在空间并生成最终样本。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数影响Unsampler的配置,在采样过程中调整模型参数以达到期望的输出特征。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数在定义Unsampler使用的采样策略中起着关键作用。它决定了用于遍历潜在空间的方法,直接影响生成样本的多样性和质量。 + - Comfy dtype: COMBO + - Python dtype: str +- positive + - positive参数作为Unsampler的正向条件输入,引导生成过程朝着输出样本中期望的特征或特征发展。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative + - negative参数作为负向条件输入,帮助Unsampler避免在生成的样本中出现不希望的特征或特征。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- latent_image + - latent_image参数至关重要,因为它提供了Unsampler开始其细化过程的潜在空间中的初始点,显著影响最终输出。 + - Comfy dtype: LATENT + - Python dtype: dict + +# Output types +- samples + - samples输出代表最终精炼的潜在空间点,是Unsampler迭代过程的结果。这些点对于生成满足期望条件的高质量图像至关重要。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class Unsampler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'end_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'cfg': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 100.0}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'normalize': (['disable', 'enable'],), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',)}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'unsampler' + CATEGORY = 'sampling' + + def unsampler(self, model, cfg, sampler_name, steps, end_at_step, scheduler, normalize, positive, negative, latent_image): + normalize = normalize == 'enable' + device = comfy.model_management.get_torch_device() + latent = latent_image + latent_image = latent['samples'] + end_at_step = min(end_at_step, steps - 1) + end_at_step = steps - end_at_step + noise = torch.zeros(latent_image.size(), dtype=latent_image.dtype, layout=latent_image.layout, device='cpu') + noise_mask = None + if 'noise_mask' in latent: + noise_mask = comfy.sampler_helpers.prepare_mask(latent['noise_mask'], noise.shape, device) + noise = noise.to(device) + latent_image = latent_image.to(device) + conds0 = {'positive': comfy.sampler_helpers.convert_cond(positive), 'negative': comfy.sampler_helpers.convert_cond(negative)} + conds = {} + for k in conds0: + conds[k] = list(map(lambda a: a.copy(), conds0[k])) + (models, inference_memory) = comfy.sampler_helpers.get_additional_models(conds, model.model_dtype()) + comfy.model_management.load_models_gpu([model] + models, model.memory_required(noise.shape) + inference_memory) + sampler = comfy.samplers.KSampler(model, steps=steps, device=device, sampler=sampler_name, scheduler=scheduler, denoise=1.0, model_options=model.model_options) + sigmas = sampler.sigmas.flip(0) + 0.0001 + pbar = comfy.utils.ProgressBar(steps) + + def callback(step, x0, x, total_steps): + pbar.update_absolute(step + 1, total_steps) + samples = sampler.sample(noise, positive, negative, cfg=cfg, latent_image=latent_image, force_full_denoise=False, denoise_mask=noise_mask, sigmas=sigmas, start_step=0, last_step=end_at_step, callback=callback) + if normalize: + samples -= samples.mean() + samples /= samples.std() + samples = samples.cpu() + comfy.sampler_helpers.cleanup_additional_models(models) + out = latent.copy() + out['samples'] = samples + return (out,) +``` \ No newline at end of file diff --git a/docs/BasicPipeToDetailerPipe.md b/docs/BasicPipeToDetailerPipe.md new file mode 100644 index 0000000..e125672 --- /dev/null +++ b/docs/BasicPipeToDetailerPipe.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: BasicPipeToDetailerPipe +- Category: ImpactPack/Pipe +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +BasicPipeToDetailerPipe 节点旨在将基本管道结构转换为更详细的管道,增强后续任务的处理能力。它通过整合各种组件,如bbox_detector、通配符和可选模型,共同完善输入数据以进行更复杂的分析。 + +# Input types +## Required +- basic_pipe + - basic_pipe 参数至关重要,因为它提供了节点操作所需的基础数据结构。它是节点促进的转换过程的先决条件。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, ...] +- bbox_detector + - bbox_detector 是识别和定位数据中兴趣区域的关键组件。其整合允许在节点的工作流程中进行更精确的操控和分析。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: Any +- wildcard + - wildcard 参数通过允许在执行期间动态替换占位符,为节点的处理引入了灵活性。这一特性增强了节点对各种数据场景的适应性。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- Select to add LoRA + - LoRA 选择参数提供了对节点功能的可选增强,允许将额外的抽象层或复杂性纳入处理管道中。 + - Comfy dtype: COMBO[Select the LoRA to add to the text] + - Python dtype: Union[str, None] +- Select to add Wildcard + - 此可选参数允许用户在处理流程中引入额外的通配符,可用于更动态和多样化的数据操作。 + - Comfy dtype: COMBO[Select the Wildcard to add to the text] + - Python dtype: Union[str, None] +- sam_model_opt + - 可选的 sam_model_opt 参数使节点能够使用高级模型进行更复杂的分析,以防默认处理不够充分。 + - Comfy dtype: SAM_MODEL + - Python dtype: Union[Any, None] +- segm_detector_opt + - 当提供 segm_detector_opt 参数时,允许在节点操作中进行更细粒度的分割检测,可能提高结果的准确性。 + - Comfy dtype: SEGM_DETECTOR + - Python dtype: Union[Any, None] +- detailer_hook + - detailer_hook 是一个可选参数,可用于自定义或扩展节点的功能,允许针对特定用例进行定制处理。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: Union[Any, None] + +# Output types +- detailer_pipe + - detailer_pipe 输出代表了节点处理后得到的增强型管道。它是一个准备用于进一步分析或下游任务的详细结构。 + - Comfy dtype: DETAILER_PIPE + - Python dtype: Tuple[Any, ...] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BasicPipeToDetailerPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'basic_pipe': ('BASIC_PIPE',), 'bbox_detector': ('BBOX_DETECTOR',), 'wildcard': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'Select to add LoRA': (['Select the LoRA to add to the text'] + folder_paths.get_filename_list('loras'),), 'Select to add Wildcard': (['Select the Wildcard to add to the text'],)}, 'optional': {'sam_model_opt': ('SAM_MODEL',), 'segm_detector_opt': ('SEGM_DETECTOR',), 'detailer_hook': ('DETAILER_HOOK',)}} + RETURN_TYPES = ('DETAILER_PIPE',) + RETURN_NAMES = ('detailer_pipe',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Pipe' + + def doit(self, *args, **kwargs): + basic_pipe = kwargs['basic_pipe'] + bbox_detector = kwargs['bbox_detector'] + wildcard = kwargs['wildcard'] + sam_model_opt = kwargs.get('sam_model_opt', None) + segm_detector_opt = kwargs.get('segm_detector_opt', None) + detailer_hook = kwargs.get('detailer_hook', None) + (model, clip, vae, positive, negative) = basic_pipe + pipe = (model, clip, vae, positive, negative, wildcard, bbox_detector, segm_detector_opt, sam_model_opt, detailer_hook, None, None, None, None) + return (pipe,) +``` \ No newline at end of file diff --git a/docs/BasicPipeToDetailerPipeSDXL.md b/docs/BasicPipeToDetailerPipeSDXL.md new file mode 100644 index 0000000..57f68fd --- /dev/null +++ b/docs/BasicPipeToDetailerPipeSDXL.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: BasicPipeToDetailerPipeSDXL +- Category: ImpactPack/Pipe +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +BasicPipeToDetailerPipeSDXL 节点旨在将基础管道结构转换为适合高级处理阶段的更详细形式。它通过整合各种组件,如 bbox_detector、LoRA 和 Wildcard 选择,增强了管道在分割和细化等任务中的能力。 + +# Input types +## Required +- base_basic_pipe + - base_basic_pipe 参数是必需的,因为它提供了节点运行所需的基础管道结构。这是一个关键输入,直接影响节点处理和转换数据的能力。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, ...] +- refiner_basic_pipe + - refiner_basic_pipe 参数用于细化基础管道,提供额外的处理能力层。它是提高管道输出细节和准确性的关键组件。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, ...] +- bbox_detector + - bbox_detector 是识别和定位数据中感兴趣区域的关键组件。其作用对于使节点能够执行空间分析和对象检测任务至关重要。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: Any +- wildcard + - wildcard 参数允许动态输入模式,增强了节点的灵活性。它对于适应各种数据格式和处理需求具有重要意义。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- sam_model_opt + - 可选的 sam_model_opt 参数可用于指定用于语义注释的模型,增加了节点分析能力的深度。 + - Comfy dtype: SAM_MODEL + - Python dtype: Optional[Any] +- segm_detector_opt + - 提供的 segm_detector_opt 参数使节点能够执行分割任务,有助于对数据进行更详细的分析。 + - Comfy dtype: SEGM_DETECTOR + - Python dtype: Optional[Any] +- detailer_hook + - detailer_hook 参数是可选特性,允许定制节点的处理管道,以满足特定的用例或需求。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: Optional[Any] + +# Output types +- detailer_pipe + - detailer_pipe 输出是节点生成的经过细化和详细化的管道结构。它很重要,因为它为进一步的高级处理和分析奠定了基础。 + - Comfy dtype: DETAILER_PIPE + - Python dtype: Tuple[Any, ...] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BasicPipeToDetailerPipeSDXL: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_basic_pipe': ('BASIC_PIPE',), 'refiner_basic_pipe': ('BASIC_PIPE',), 'bbox_detector': ('BBOX_DETECTOR',), 'wildcard': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'Select to add LoRA': (['Select the LoRA to add to the text'] + folder_paths.get_filename_list('loras'),), 'Select to add Wildcard': (['Select the Wildcard to add to the text'],)}, 'optional': {'sam_model_opt': ('SAM_MODEL',), 'segm_detector_opt': ('SEGM_DETECTOR',), 'detailer_hook': ('DETAILER_HOOK',)}} + RETURN_TYPES = ('DETAILER_PIPE',) + RETURN_NAMES = ('detailer_pipe',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Pipe' + + def doit(self, *args, **kwargs): + base_basic_pipe = kwargs['base_basic_pipe'] + refiner_basic_pipe = kwargs['refiner_basic_pipe'] + bbox_detector = kwargs['bbox_detector'] + wildcard = kwargs['wildcard'] + sam_model_opt = kwargs.get('sam_model_opt', None) + segm_detector_opt = kwargs.get('segm_detector_opt', None) + detailer_hook = kwargs.get('detailer_hook', None) + (model, clip, vae, positive, negative) = base_basic_pipe + (refiner_model, refiner_clip, refiner_vae, refiner_positive, refiner_negative) = refiner_basic_pipe + pipe = (model, clip, vae, positive, negative, wildcard, bbox_detector, segm_detector_opt, sam_model_opt, detailer_hook, refiner_model, refiner_clip, refiner_positive, refiner_negative) + return (pipe,) +``` \ No newline at end of file diff --git a/docs/Batch Crop Image.md b/docs/Batch Crop Image.md new file mode 100644 index 0000000..bdb46a3 --- /dev/null +++ b/docs/Batch Crop Image.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: BatchCropImage +- Category: Mikey/Image +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +BatchCropImage节点的`batch`方法旨在处理一个目录中的图像,通过将每个图像裁剪到指定大小来保持长宽比。它能够处理各种图像格式,并将裁剪后的图像转换为适合进一步处理的张量格式。 + +# Input types +## Required +- image_directory + - 参数`image_directory`指定包含要裁剪图像的目录的路径。这是一个关键参数,因为节点的执行取决于此目录的存在和可访问性。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- crop_amount + - 参数`crop_amount`确定要裁剪的图像比例。它很重要,因为它直接影响结果裁剪图像的尺寸,影响后续的分析或处理。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- image + - 输出`image`由转换为张量格式的裁剪图像列表组成。这个输出很重要,因为它代表了准备好用于下游任务(如机器学习或图像分析)的已处理数据。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchCropImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image_directory': ('STRING', {'multiline': False, 'placeholder': 'Image Directory'}), 'crop_amount': ('FLOAT', {'default': 0.05})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'batch' + CATEGORY = 'Mikey/Image' + OUTPUT_IS_LIST = (True,) + + def batch(self, image_directory, crop_amount): + if not os.path.exists(image_directory): + raise Exception(f'Image directory {image_directory} does not exist') + images = [] + for file in os.listdir(image_directory): + if file.endswith('.png') or file.endswith('.jpg') or file.endswith('.jpeg') or file.endswith('.webp') or file.endswith('.bmp') or file.endswith('.gif'): + img = Image.open(os.path.join(image_directory, file)) + (width, height) = img.size + pixels = int(width * crop_amount) // 8 * 8 + left = pixels + upper = pixels + right = width - pixels + lower = height - pixels + cropped_img = img.crop((left, upper, right, lower)) + img = pil2tensor(cropped_img) + images.append(img) + return (images,) +``` \ No newline at end of file diff --git a/docs/Batch Crop Resize Inplace.md b/docs/Batch Crop Resize Inplace.md new file mode 100644 index 0000000..a67fa0c --- /dev/null +++ b/docs/Batch Crop Resize Inplace.md @@ -0,0 +1,118 @@ +# Documentation +- Class name: BatchCropResizeInplace +- Category: Mikey/Image +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +BatchCropResizeInplace节点旨在通过应用裁剪、调整大小和上采样操作来处理一批图像文件。它高效地处理目录中的图像转换,提供了一种流线化的方法来增强图像质量和尺寸,同时可以选择替换原始文件。 + +# Input types +## Required +- image_directory + - image_directory参数指定包含需要处理的图像文件的目录的路径。对于节点定位和访问批量操作的图像至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- subdirectories + - subdirectories参数决定是否包括指定的image_directory内子目录中的图像文件。这影响批量处理的范围。 + - Comfy dtype: COMBO[true, false] + - Python dtype: str +- replace_original + - replace_original参数指示是否应将原始图像文件替换为处理后的图像。这对所做的更改的永久性有重要影响。 + - Comfy dtype: COMBO[true, false] + - Python dtype: str +- replace_suffix + - replace_suffix参数定义了在处理后的图像不替换原始文件时附加到图像文件名的后缀。这对于区分原始图像和处理后的图像很重要。 + - Comfy dtype: STRING + - Python dtype: str +- upscale_method + - upscale_method参数选择用于放大图像的算法。方法的选择可以显著影响放大图像的质量。 + - Comfy dtype: COMBO[nearest-exact, bilinear, area, bicubic] + - Python dtype: str +- crop + - crop参数确定要应用于图像的裁剪方法。它可以禁用裁剪或根据指定的crop_amount应用中心裁剪。 + - Comfy dtype: COMBO[disabled, center] + - Python dtype: str +- crop_amount + - crop_amount参数指定要从每侧裁剪的图像比例。它是控制裁剪操作范围的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- prompt + - prompt参数用于某些图像处理任务可能需要的额外指令或上下文。它可以影响节点解释和处理图像的方式。 + - Comfy dtype: STRING + - Python dtype: str +- extra_pnginfo + - extra_pnginfo参数提供可用于自定义PNG图像处理过程的额外信息。当需要考虑特定的元数据或属性时,它特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- job_done + - job_done参数表示批量处理的完成,并提供已处理图像数量的摘要。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchCropResizeInplace: + crop_methods = ['disabled', 'center'] + upscale_methods = ['nearest-exact', 'bilinear', 'area', 'bicubic'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image_directory': ('STRING', {'multiline': False, 'placeholder': 'Image Directory'}), 'subdirectories': (['true', 'false'], {'default': 'false'}), 'replace_original': (['true', 'false'], {'default': 'false'}), 'replace_suffix': ('STRING', {'default': '_cropped_resized'}), 'upscale_method': (s.upscale_methods,), 'crop': (s.crop_methods,), 'crop_amount': ('FLOAT', {'default': 0.05})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('job_done',) + FUNCTION = 'batch' + CATEGORY = 'Mikey/Image' + + def crop(self, image, crop_amount): + (width, height) = image.size + pixels = int(width * crop_amount) // 8 * 8 + left = pixels + upper = pixels + right = width - pixels + lower = height - pixels + cropped_img = image.crop((left, upper, right, lower)) + return cropped_img + + def upscale(self, image, upscale_method, width, height, crop): + samples = image.movedim(-1, 1) + s = comfy.utils.common_upscale(samples, width, height, upscale_method, crop) + s = s.movedim(1, -1) + return (s,) + + def resize(self, image, upscale_method, crop): + image = pil2tensor(image) + (w, h) = find_latent_size(image.shape[2], image.shape[1]) + img = self.upscale(image, upscale_method, w, h, crop)[0] + img = tensor2pil(img) + return img + + def get_files_from_directory(self, image_directory, subdirectories): + if subdirectories == 'true': + files = [os.path.join(root, name) for (root, dirs, files) in os.walk(image_directory) for name in files if name.endswith(('.png', '.jpg', '.jpeg', '.webp', '.bmp', '.gif'))] + else: + files = [os.path.join(image_directory, f) for f in os.listdir(image_directory) if os.path.isfile(os.path.join(image_directory, f)) and f.endswith(('.png', '.jpg', '.jpeg', '.webp', '.bmp', '.gif'))] + return files + + def batch(self, image_directory, subdirectories, replace_original, replace_suffix, upscale_method, crop, crop_amount, prompt, extra_pnginfo): + if not os.path.exists(image_directory): + raise Exception(f'Image directory {image_directory} does not exist') + files = self.get_files_from_directory(image_directory, subdirectories) + for file in tqdm(files, desc='Processing images'): + img = Image.open(file) + if crop != 'disabled': + img = self.crop(img, crop_amount) + img = self.resize(img, upscale_method, crop) + if replace_original == 'true': + img.save(file) + else: + replace_suffix = search_and_replace(replace_suffix, extra_pnginfo, prompt) + (filename, file_extension) = os.path.splitext(file) + img.save(filename + replace_suffix + file_extension) + return (f'Job done, {len(files)} images processed',) +``` \ No newline at end of file diff --git a/docs/Batch Float (mtb).md b/docs/Batch Float (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Batch Float Assemble (mtb).md b/docs/Batch Float Assemble (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Batch Float Fill (mtb).md b/docs/Batch Float Fill (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Batch Float Fit (mtb).md b/docs/Batch Float Fit (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Batch Float Normalize (mtb).md b/docs/Batch Float Normalize (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Batch Make (mtb).md b/docs/Batch Make (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Batch Merge (mtb).md b/docs/Batch Merge (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Batch Resize Image for SDXL.md b/docs/Batch Resize Image for SDXL.md new file mode 100644 index 0000000..536d454 --- /dev/null +++ b/docs/Batch Resize Image for SDXL.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: BatchResizeImageSDXL +- Category: Mikey/Image +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +BatchResizeImageSDXL 节点旨在根据指定参数批量处理图像,通过调整大小来优化它们。它支持多种裁剪和放大方法,确保图像能够准确高效地调整尺寸。这个节点特别适用于为进一步处理或展示准备图像数据集。 + +# Input types +## Required +- image_directory + - image_directory 参数指定了要调整大小的图像存储的位置。这对于节点定位和访问图像进行处理至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- upscale_method + - upscale_method 参数决定了用于放大图像的算法。它对调整后图像的质量和外观有显著影响。 + - Comfy dtype: COMBO['nearest-exact', 'bilinear', 'area', 'bicubic'] + - Python dtype: str +- crop + - crop 参数指示在调整大小后是否以及如何裁剪图像。这对于保持长宽比或关注图像的特定部分可能很重要。 + - Comfy dtype: COMBO['disabled', 'center'] + - Python dtype: str + +# Output types +- image + - BatchResizeImageSDXL 节点输出的 image 是一个调整过大小的图像列表。每个图像都根据输入参数进行了处理,使其准备好进行应用或分析的下一阶段。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchResizeImageSDXL(ResizeImageSDXL): + crop_methods = ['disabled', 'center'] + upscale_methods = ['nearest-exact', 'bilinear', 'area', 'bicubic'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image_directory': ('STRING', {'multiline': False, 'placeholder': 'Image Directory'}), 'upscale_method': (s.upscale_methods,), 'crop': (s.crop_methods,)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'batch' + CATEGORY = 'Mikey/Image' + OUTPUT_IS_LIST = (True,) + + def batch(self, image_directory, upscale_method, crop): + if not os.path.exists(image_directory): + raise Exception(f'Image directory {image_directory} does not exist') + images = [] + for file in os.listdir(image_directory): + if file.endswith('.png') or file.endswith('.jpg') or file.endswith('.jpeg') or file.endswith('.webp') or file.endswith('.bmp') or file.endswith('.gif'): + img = Image.open(os.path.join(image_directory, file)) + img = pil2tensor(img) + img = self.resize(img, upscale_method, crop)[0] + images.append(img) + return (images,) +``` \ No newline at end of file diff --git a/docs/Batch Shake (mtb).md b/docs/Batch Shake (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Batch Shape (mtb).md b/docs/Batch Shape (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Batch Time Wrap (mtb).md b/docs/Batch Time Wrap (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Batch Transform (mtb).md b/docs/Batch Transform (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Batch Unsampler(ttulttul%2FComfyUI-Iterative-Mixer).md b/docs/Batch Unsampler(ttulttul%2FComfyUI-Iterative-Mixer).md new file mode 100644 index 0000000..e74b7e0 --- /dev/null +++ b/docs/Batch Unsampler(ttulttul%2FComfyUI-Iterative-Mixer).md @@ -0,0 +1,85 @@ +# Documentation +- Class name: BatchUnsampler +- Category: tests +- Output node: False +- Repo Ref: https://github.com/ttulttul/ComfyUI-Iterative-Mixer + +BatchUnsampler 类旨在逆向工程应用于一批潜在变量的噪声计划,从给定的潜在图像开始,逐步向后工作。它利用模型的噪声计划生成一系列逐渐去噪的潜在变量,这在理解模型的内部表示和噪声动态方面可能非常有用。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了用于取消采样操作的基础架构和噪声计划。它是生成去噪潜在变量序列的基础,对节点的功能至关重要。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_management.Model +- sampler_name + - sampler_name 参数很重要,因为它决定了在取消采样过程中使用的采样方法类型。它影响生成的潜在变量的质量和特性,从而影响去噪序列的整体结果。 + - Comfy dtype: COMBO[comfy.samplers.KSampler.SAMPLERS] + - Python dtype: str +- scheduler + - scheduler 参数至关重要,因为它决定了在取消采样操作中应用的噪声级别的调度策略。它影响去噪潜在序列的平滑性和连贯性,这对于准确表示至关重要。 + - Comfy dtype: COMBO[comfy.samplers.KSampler.SCHEDULERS] + - Python dtype: str +- steps + - steps 参数很重要,因为它定义了用于取消采样潜在变量的中间步骤的数量。它直接影响去噪潜在序列的分辨率和粒度,影响节点捕捉噪声计划中细节的能力。 + - Comfy dtype: INT + - Python dtype: int +- start_at_step + - start_at_step 参数指定了取消采样开始的初始步骤。它设置了去噪序列的起点,对于控制生成的潜在变量的范围至关重要。 + - Comfy dtype: INT + - Python dtype: int +- end_at_step + - end_at_step 参数标记了取消采样结束的最终步骤。它建立了去噪序列的终点,影响了潜在变量去噪的程度。 + - Comfy dtype: INT + - Python dtype: int +- latent_image + - latent_image 参数至关重要,因为它提供了取消采样开始的源潜在图像。它是生成整个潜在变量序列的基础,对节点的操作不可或缺。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, Any] +## Optional +- normalize + - 当启用 normalize 参数时,会将生成的潜在变量调整为平均值为零,这对于某些下游应用可能是有益的。它修改了取消采样的输出,有可能增强去噪潜在变量的可比性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- latent_batch + - latent_batch 输出包含去噪的潜在变量序列,代表了对原始潜在图像应用的噪声计划的逆向工程。它是 BatchUnsampler 操作的重要结果,提供了模型内部噪声动态的宝贵见解。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchUnsampler: + """ + Unsample a latent step by step back to the start of the noise schedule. + """ + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'steps': ('INT', {'default': 10000, 'min': 0, 'max': 10000}), 'start_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'end_at_step': ('INT', {'default': 10000, 'min': 1, 'max': 10000}), 'latent_image': ('LATENT',), 'normalize': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('LATENT',) + RETURN_NAMES = ('latent_batch',) + FUNCTION = 'unsampler' + CATEGORY = 'tests' + + @torch.no_grad() + def unsampler(self, model, sampler_name, scheduler, steps, start_at_step, end_at_step, latent_image, normalize=False): + """ + Generate a batch of latents representing each z[i] in the + progressively noised sequence of latents stemming from the + source latent_image, using the model's noising schedule (sigma) + in reverse and applying normal noise at each step in the manner + prescribed by the original latent diffusion paper. + """ + latent = latent_image + latent_image = latent['samples'] + sigmas = calc_sigmas(model, sampler_name, scheduler, steps, start_at_step, end_at_step) + sigmas = sigmas.flip(0) + z = generate_noised_latents(latent_image, sigmas, normalize=normalize) + out = {'samples': z} + return (out,) +``` \ No newline at end of file diff --git a/docs/Batch Unsampler.md b/docs/Batch Unsampler.md new file mode 100644 index 0000000..a27e660 --- /dev/null +++ b/docs/Batch Unsampler.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: BatchUnsampler +- Category: tests +- Output node: False +- Repo Ref: https://github.com/deroberon/demofusion-comfyui + +BatchUnsampler节点旨在从给定的潜在图像开始,生成一系列逆序的潜在表示。它使用模型的噪声计划逐步添加噪声,模拟原始论文中描述的潜在扩散的逆过程。该节点对于测试和分析在各种噪声条件和采样策略下扩散模型的行为至关重要。 + +# Input types +## Required +- model + - 模型参数对于BatchUnsampler节点至关重要,因为它提供了节点将用来生成潜在表示的基础扩散模型。模型的噪声计划对于模拟逆向扩散过程特别重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- steps + - 步骤参数决定了将生成的中间潜在表示的数量。它是控制逆向扩散过程的粒度和生成的潜在序列的详细程度的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- sampler_name + - sampler_name参数指定BatchUnsampler节点使用的采样器类型。这种选择影响添加到潜在表示中的噪声方法,从而影响生成序列的特征。 + - Comfy dtype: STRING + - Python dtype: str +- latent_image + - latent_image参数是BatchUnsampler节点的关键输入,因为它代表了将生成噪声潜在序列的源潜在图像。这张图像是逆向扩散过程的起点。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Output types +- latent_batch + - BatchUnsampler节点的latent_batch输出包含通过逆向扩散过程生成的一批潜在表示。这些潜在表示对于进一步分析或作为扩散模型管道中其他节点的输入非常重要。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class BatchUnsampler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'end_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'step_increment': ('INT', {'default': 1, 'min': 1, 'max': 10000}), 'cfg': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 100.0}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'normalize': (['disable', 'enable'],), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',)}} + RETURN_TYPES = ('LATENT',) + RETURN_NAMES = ('latent_batch',) + FUNCTION = 'unsampler' + CATEGORY = 'tests' + + def unsampler(self, model, cfg, sampler_name, steps, end_at_step, step_increment, scheduler, normalize, positive, negative, latent_image): + """ + Generate a batch of latents representing each z[i] in the + progressively noised sequence of latents stemming from the + source latent_image, using the model's noising schedule (sigma) + in reverse and applying normal noise at each step in the manner + prescribed by the original latent diffusion paper. + """ + normalize = normalize == 'enable' + device = comfy.model_management.get_torch_device() + latent = latent_image + latent_image = latent['samples'] + batch_of_latents = [] + end_at_step = min(end_at_step, steps - 1) + end_at_step = steps - end_at_step + noise = torch.zeros(latent_image.size(), dtype=latent_image.dtype, layout=latent_image.layout, device='cpu') + noise_mask = None + if 'noise_mask' in latent: + noise_mask = comfy.sampler_helpers.prepare_mask(latent['noise_mask'], noise, device) + real_model = model.model + noise = noise.to(device) + latent_image = latent_image.to(device) + positive = comfy.sampler_helpers.convert_cond(positive) + negative = comfy.sampler_helpers.convert_cond(negative) + (models, inference_memory) = comfy.sampler_helpers.get_additional_models({'positive': positive, 'negative': negative}, model.model_dtype()) + comfy.model_management.load_models_gpu([model] + models, model.memory_required(noise.shape) + inference_memory) + sampler = comfy.samplers.KSampler(real_model, steps=steps, device=device, sampler=sampler_name, scheduler=scheduler, denoise=1.0, model_options=model.model_options) + sigmas = sampler.sigmas.flip(0) + z = generate_noised_latents(latent_image, sigmas) + logger.warning(f'latent_image.shape={latent_image.shape}') + logger.warning(f'z.shape={z.shape}') + out = {'samples': z} + comfy.sampler_helpers.cleanup_additional_models(models) + return (out,) +``` \ No newline at end of file diff --git a/docs/BatchCount+.md b/docs/BatchCount+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/BatchCreativeInterpolation.md b/docs/BatchCreativeInterpolation.md new file mode 100644 index 0000000..f5a2cb6 --- /dev/null +++ b/docs/BatchCreativeInterpolation.md @@ -0,0 +1,383 @@ +# Documentation +- Class name: BatchCreativeInterpolationNode +- Category: Steerable-Motion +- Output node: False +- Repo Ref: https://github.com/banodoco/steerable-motion + +BatchCreativeInterpolationNode旨在对一批图像执行创意插值。它利用各种参数来控制插值过程中帧的分布、关键帧影响和强度值。该节点特别适用于在不同图像状态之间生成平滑过渡,并且它提供了对最终输出的高控制度,使其适用于广泛的创意应用。 + +# Input types +## Required +- positive + - 正面条件图像是一个关键输入,它影响插值的方向和风格。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- negative + - 负面条件图像用于限制或引导插值,使其与正面图像的方向相反。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- images + - 将被插值的输入图像。此参数至关重要,因为它定义了将要被转换的内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- model + - 用于插值过程的模型。对于生成连贯的转换至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- ipadapter + - IPA适配器用于在插值期间对图像应用特定的转换或风格。 + - Comfy dtype: IPADAPTER + - Python dtype: dict +- clip_vision + - CLIP Vision模型被用来以支持插值的方式分析和处理图像。 + - Comfy dtype: CLIP_VISION + - Python dtype: torch.nn.Module +- type_of_frame_distribution + - 确定插值的帧分布方法,可以是线性的或使用动态值。 + - Comfy dtype: COMBO[linear, dynamic] + - Python dtype: str +- type_of_key_frame_influence + - 指定关键帧的影响是线性的还是遵循动态模式。 + - Comfy dtype: COMBO[linear, dynamic] + - Python dtype: str +- type_of_strength_distribution + - 指示插值的强度分布类型,可以是线性或动态。 + - Comfy dtype: COMBO[linear, dynamic] + - Python dtype: str +## Optional +- linear_frame_distribution_value + - 用于线性帧分布的值。仅当帧分布类型设置为'linear'时才相关。 + - Comfy dtype: INT + - Python dtype: int +- dynamic_frame_distribution_values + - 定义动态帧分布的逗号分隔值字符串。如果帧分布类型为'dynamic',则需要此参数。 + - Comfy dtype: STRING + - Python dtype: str +- linear_key_frame_influence_value + - 确定关键帧线性影响的值。如果关键帧影响类型为'linear',则适用。 + - Comfy dtype: STRING + - Python dtype: str +- dynamic_key_frame_influence_values + - 表示关键帧的动态影响值的字符串,当关键帧影响类型为'dynamic'时使用。 + - Comfy dtype: STRING + - Python dtype: str +- linear_strength_value + - 如果选择了线性强度分布,用于插值的线性强度值。 + - Comfy dtype: STRING + - Python dtype: str +- dynamic_strength_values + - 定义帧的动态强度分布的逗号分隔值字符串。 + - Comfy dtype: STRING + - Python dtype: str +- buffer + - 缓冲值向关键帧位置添加填充,影响插值的范围。 + - Comfy dtype: INT + - Python dtype: int +- high_detail_mode + - 启用时,高细节模式会调整IPA设置,以获得更详细和精细的插值。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- base_ipa_advanced_settings + - 基本IPA应用的高级设置,允许微调插值过程。 + - Comfy dtype: ADVANCED_IPA_SETTINGS + - Python dtype: dict +- detail_ipa_advanced_settings + - 详细IPA应用的高级设置,在使用高细节模式时使用。 + - Comfy dtype: ADVANCED_IPA_SETTINGS + - Python dtype: dict + +# Output types +- GRAPH + - GRAPH输出可视化插值过程中应用的权重比较,提供对不同帧如何受到影响的洞察。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- POSITIVE + - POSITIVE输出反映了插值中使用的正面条件,捕捉了过程的指导方向。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- NEGATIVE + - NEGATIVE输出代表负面条件,它以期望的方式限制插值。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- MODEL + - MODEL输出是插值后修改的模型,包含了应用于输入图像的创意转换。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- KEYFRAME_POSITIONS + - KEYFRAME_POSITIONS输出提供了用于插值的稀疏索引方法,详细说明了关键帧的位置。 + - Comfy dtype: SPARSE_METHOD + - Python dtype: SparseIndexMethodImport +- BATCH_SIZE + - BATCH_SIZE输出指示了插值期间处理的批次大小,反映了转换的图像数量。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: GPU + +# Source code +``` +class BatchCreativeInterpolationNode: + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') + + @classmethod + def INPUT_TYPES(s): + return {'required': {'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'images': ('IMAGE',), 'model': ('MODEL',), 'ipadapter': ('IPADAPTER',), 'clip_vision': ('CLIP_VISION',), 'type_of_frame_distribution': (['linear', 'dynamic'],), 'linear_frame_distribution_value': ('INT', {'default': 16, 'min': 4, 'max': 64, 'step': 1}), 'dynamic_frame_distribution_values': ('STRING', {'multiline': True, 'default': '0,10,26,40'}), 'type_of_key_frame_influence': (['linear', 'dynamic'],), 'linear_key_frame_influence_value': ('STRING', {'multiline': False, 'default': '(1.0,1.0)'}), 'dynamic_key_frame_influence_values': ('STRING', {'multiline': True, 'default': '(1.0,1.0),(1.0,1.5)(1.0,0.5)'}), 'type_of_strength_distribution': (['linear', 'dynamic'],), 'linear_strength_value': ('STRING', {'multiline': False, 'default': '(0.3,0.4)'}), 'dynamic_strength_values': ('STRING', {'multiline': True, 'default': '(0.0,1.0),(0.0,1.0),(0.0,1.0),(0.0,1.0)'}), 'buffer': ('INT', {'default': 4, 'min': 1, 'max': 16, 'step': 1}), 'high_detail_mode': ('BOOLEAN', {'default': True})}, 'optional': {'base_ipa_advanced_settings': ('ADVANCED_IPA_SETTINGS',), 'detail_ipa_advanced_settings': ('ADVANCED_IPA_SETTINGS',)}} + RETURN_TYPES = ('IMAGE', 'CONDITIONING', 'CONDITIONING', 'MODEL', 'SPARSE_METHOD', 'INT') + RETURN_NAMES = ('GRAPH', 'POSITIVE', 'NEGATIVE', 'MODEL', 'KEYFRAME_POSITIONS', 'BATCH_SIZE') + FUNCTION = 'combined_function' + CATEGORY = 'Steerable-Motion' + + def combined_function(self, positive, negative, images, model, ipadapter, clip_vision, type_of_frame_distribution, linear_frame_distribution_value, dynamic_frame_distribution_values, type_of_key_frame_influence, linear_key_frame_influence_value, dynamic_key_frame_influence_values, type_of_strength_distribution, linear_strength_value, dynamic_strength_values, buffer, high_detail_mode, base_ipa_advanced_settings=None, detail_ipa_advanced_settings=None): + + def get_keyframe_positions(type_of_frame_distribution, dynamic_frame_distribution_values, images, linear_frame_distribution_value): + if type_of_frame_distribution == 'dynamic': + if isinstance(dynamic_frame_distribution_values, str): + return sorted([int(kf.strip()) for kf in dynamic_frame_distribution_values.split(',')]) + elif isinstance(dynamic_frame_distribution_values, list): + return sorted(dynamic_frame_distribution_values) + else: + return [i * linear_frame_distribution_value for i in range(len(images))] + + def create_mask_batch(last_key_frame_position, weights, frames): + (width, height) = (512, 512) + frame_to_weight = {frame: weights[i] for (i, frame) in enumerate(frames)} + masks = [] + for frame_number in range(last_key_frame_position): + strength = frame_to_weight.get(frame_number, 0.0) + mask = torch.full((height, width), strength) + masks.append(mask) + masks_tensor = torch.stack(masks, dim=0) + return masks_tensor + + def plot_weight_comparison(cn_frame_numbers, cn_weights, ipadapter_frame_numbers, ipadapter_weights, buffer): + plt.figure(figsize=(12, 8)) + colors = ['b', 'g', 'r', 'c', 'm', 'y', 'k'] + cn_frame_numbers = cn_frame_numbers if cn_frame_numbers is not None else [] + cn_weights = cn_weights if cn_weights is not None else [] + ipadapter_frame_numbers = ipadapter_frame_numbers if ipadapter_frame_numbers is not None else [] + ipadapter_weights = ipadapter_weights if ipadapter_weights is not None else [] + max_length = max(len(cn_frame_numbers), len(ipadapter_frame_numbers)) + label_counter = 1 if buffer < 0 else 0 + for i in range(max_length): + if i < len(cn_frame_numbers): + label = 'cn_strength_buffer' if i == 0 and buffer > 0 else f'cn_strength_{label_counter}' + plt.plot(cn_frame_numbers[i], cn_weights[i], marker='o', color=colors[i % len(colors)], label=label) + if i < len(ipadapter_frame_numbers): + label = 'ipa_strength_buffer' if i == 0 and buffer > 0 else f'ipa_strength_{label_counter}' + plt.plot(ipadapter_frame_numbers[i], ipadapter_weights[i], marker='x', linestyle='--', color=colors[i % len(colors)], label=label) + if label_counter == 0 or buffer < 0 or i > 0: + label_counter += 1 + plt.legend() + all_weights = cn_weights + ipadapter_weights + max_weight = max((max(sublist) for sublist in all_weights if sublist)) * 1.5 + plt.ylim(0, max_weight) + buffer_io = BytesIO() + plt.savefig(buffer_io, format='png', bbox_inches='tight') + plt.close() + buffer_io.seek(0) + img = Image.open(buffer_io) + img_tensor = transforms.ToTensor()(img) + img_tensor = img_tensor.unsqueeze(0) + img_tensor = img_tensor.permute([0, 2, 3, 1]) + return (img_tensor,) + + def extract_strength_values(type_of_key_frame_influence, dynamic_key_frame_influence_values, keyframe_positions, linear_key_frame_influence_value): + if type_of_key_frame_influence == 'dynamic': + if isinstance(dynamic_key_frame_influence_values, str): + dynamic_values = eval(dynamic_key_frame_influence_values) + else: + dynamic_values = dynamic_key_frame_influence_values + dynamic_values_corrected = [] + for value in dynamic_values: + if len(value) == 2: + value = (value[0], value[1], value[0]) + dynamic_values_corrected.append(value) + return dynamic_values_corrected + else: + if len(linear_key_frame_influence_value) == 2: + linear_key_frame_influence_value = (linear_key_frame_influence_value[0], linear_key_frame_influence_value[1], linear_key_frame_influence_value[0]) + return [linear_key_frame_influence_value for _ in range(len(keyframe_positions) - 1)] + + def extract_influence_values(type_of_key_frame_influence, dynamic_key_frame_influence_values, keyframe_positions, linear_key_frame_influence_value): + if isinstance(linear_key_frame_influence_value, str) and linear_key_frame_influence_value[0] == '(': + linear_key_frame_influence_value = eval(linear_key_frame_influence_value) + if not isinstance(linear_key_frame_influence_value, tuple): + if isinstance(linear_key_frame_influence_value, (float, str)): + try: + value = float(linear_key_frame_influence_value) + linear_key_frame_influence_value = (value, value) + except ValueError: + raise ValueError('linear_key_frame_influence_value must be a float or a string representing a float') + number_of_outputs = len(keyframe_positions) - 1 + if type_of_key_frame_influence == 'dynamic': + if all((isinstance(x, float) for x in dynamic_key_frame_influence_values)): + dynamic_values = [(value, value) for value in dynamic_key_frame_influence_values] + elif isinstance(dynamic_key_frame_influence_values[0], str) and dynamic_key_frame_influence_values[0] == '(': + string_representation = ''.join(dynamic_key_frame_influence_values) + dynamic_values = eval(f'[{string_representation}]') + else: + dynamic_values = dynamic_key_frame_influence_values if isinstance(dynamic_key_frame_influence_values, list) else [dynamic_key_frame_influence_values] + return dynamic_values[:number_of_outputs] + else: + return [linear_key_frame_influence_value for _ in range(number_of_outputs)] + + def calculate_weights(batch_index_from, batch_index_to, strength_from, strength_to, interpolation, revert_direction_at_midpoint, last_key_frame_position, i, number_of_items, buffer): + range_start = batch_index_from + range_end = batch_index_to + if i == number_of_items - 1: + range_end = last_key_frame_position + steps = range_end - range_start + diff = strength_to - strength_from + index = np.linspace(0, 1, steps // 2 + 1) if revert_direction_at_midpoint else np.linspace(0, 1, steps) + if interpolation == 'linear': + weights = np.linspace(strength_from, strength_to, len(index)) + elif interpolation == 'ease-in': + weights = diff * np.power(index, 2) + strength_from + elif interpolation == 'ease-out': + weights = diff * (1 - np.power(1 - index, 2)) + strength_from + elif interpolation == 'ease-in-out': + weights = diff * ((1 - np.cos(index * np.pi)) / 2) + strength_from + if revert_direction_at_midpoint: + weights = np.concatenate([weights, weights[::-1]]) + frame_numbers = np.arange(range_start, range_start + len(weights)) + if range_start < 0 and i > 0: + drop_count = abs(range_start) + weights = weights[drop_count:] + frame_numbers = frame_numbers[drop_count:] + if range_end > last_key_frame_position and i < number_of_items - 1: + drop_count = range_end - last_key_frame_position + weights = weights[:-drop_count] + frame_numbers = frame_numbers[:-drop_count] + return (weights, frame_numbers) + + def process_weights(frame_numbers, weights, multiplier): + adjusted_weights = [min(max(weight * multiplier, 0.0), 1.0) for weight in weights] + filtered_frames_and_weights = [(frame, weight) for (frame, weight) in zip(frame_numbers, adjusted_weights) if weight > 0.0] + (filtered_frame_numbers, filtered_weights) = zip(*filtered_frames_and_weights) if filtered_frames_and_weights else ([], []) + return (list(filtered_frame_numbers), list(filtered_weights)) + + def calculate_influence_frame_number(key_frame_position, next_key_frame_position, distance): + key_frame_distance = abs(next_key_frame_position - key_frame_position) + extended_distance = key_frame_distance * distance + if key_frame_position < next_key_frame_position: + influence_frame_number = key_frame_position + extended_distance + else: + influence_frame_number = key_frame_position - extended_distance + return round(influence_frame_number) + keyframe_positions = get_keyframe_positions(type_of_frame_distribution, dynamic_frame_distribution_values, images, linear_frame_distribution_value) + shifted_keyframes_position = [position + buffer - 2 for position in keyframe_positions] + shifted_keyframe_positions_string = ','.join((str(pos) for pos in shifted_keyframes_position)) + sparseindexmethod = SparseIndexMethodNodeImport() + (sparse_indexes,) = sparseindexmethod.get_method(shifted_keyframe_positions_string) + if buffer > 0: + keyframe_positions = [position + buffer - 1 for position in keyframe_positions] + keyframe_positions.insert(0, 0) + last_position_with_buffer = keyframe_positions[-1] + buffer - 1 + keyframe_positions.append(last_position_with_buffer) + if base_ipa_advanced_settings is None: + if high_detail_mode: + base_ipa_advanced_settings = {'ipa_starts_at': 0.0, 'ipa_ends_at': 0.3, 'ipa_weight_type': 'ease in-out', 'ipa_weight': 1.0, 'ipa_embeds_scaling': 'V only', 'ipa_noise_strength': 0.0, 'use_image_for_noise': False, 'type_of_noise': 'fade', 'noise_blur': 0} + else: + base_ipa_advanced_settings = {'ipa_starts_at': 0.0, 'ipa_ends_at': 0.75, 'ipa_weight_type': 'ease in-out', 'ipa_weight': 1.0, 'ipa_embeds_scaling': 'V only', 'ipa_noise_strength': 0.0, 'use_image_for_noise': False, 'type_of_noise': 'fade', 'noise_blur': 0} + if detail_ipa_advanced_settings is None: + if high_detail_mode: + detail_ipa_advanced_settings = {'ipa_starts_at': 0.25, 'ipa_ends_at': 0.75, 'ipa_weight_type': 'ease in-out', 'ipa_weight': 1.0, 'ipa_embeds_scaling': 'V only', 'ipa_noise_strength': 0.0, 'use_image_for_noise': False, 'type_of_noise': 'fade', 'noise_blur': 0} + strength_values = extract_strength_values(type_of_strength_distribution, dynamic_strength_values, keyframe_positions, linear_strength_value) + strength_values = [literal_eval(val) if isinstance(val, str) else val for val in strength_values] + corrected_strength_values = [] + for val in strength_values: + if len(val) == 2: + val = (val[0], val[1], val[0]) + corrected_strength_values.append(val) + strength_values = corrected_strength_values + key_frame_influence_values = extract_influence_values(type_of_key_frame_influence, dynamic_key_frame_influence_values, keyframe_positions, linear_key_frame_influence_value) + key_frame_influence_values = [literal_eval(val) if isinstance(val, str) else val for val in key_frame_influence_values] + last_key_frame_position = keyframe_positions[-1] + 1 + all_cn_frame_numbers = [] + all_cn_weights = [] + all_ipa_weights = [] + all_ipa_frame_numbers = [] + for i in range(len(keyframe_positions)): + keyframe_position = keyframe_positions[i] + interpolation = 'ease-in-out' + if i == 0: + image = images[0] + strength_from = strength_to = strength_values[0][1] + batch_index_from = 0 + batch_index_to_excl = buffer + (weights, frame_numbers) = calculate_weights(batch_index_from, batch_index_to_excl, strength_from, strength_to, interpolation, False, last_key_frame_position, i, len(keyframe_positions), buffer) + elif i == 1: + image = images[i - 1] + (key_frame_influence_from, key_frame_influence_to) = key_frame_influence_values[i - 1] + (start_strength, mid_strength, end_strength) = strength_values[i - 1] + keyframe_position = keyframe_positions[i] + next_key_frame_position = keyframe_positions[i + 1] + batch_index_from = keyframe_position + batch_index_to_excl = calculate_influence_frame_number(keyframe_position, next_key_frame_position, key_frame_influence_to) + (weights, frame_numbers) = calculate_weights(batch_index_from, batch_index_to_excl, mid_strength, end_strength, interpolation, False, last_key_frame_position, i, len(keyframe_positions), buffer) + elif i == len(keyframe_positions) - 2: + image = images[i - 1] + (key_frame_influence_from, key_frame_influence_to) = key_frame_influence_values[i - 1] + (start_strength, mid_strength, end_strength) = strength_values[i - 1] + keyframe_position = keyframe_positions[i] + previous_key_frame_position = keyframe_positions[i - 1] + batch_index_from = calculate_influence_frame_number(keyframe_position, previous_key_frame_position, key_frame_influence_from) + batch_index_to_excl = keyframe_position + (weights, frame_numbers) = calculate_weights(batch_index_from, batch_index_to_excl, start_strength, mid_strength, interpolation, False, last_key_frame_position, i, len(keyframe_positions), buffer) + elif i == len(keyframe_positions) - 1: + image = images[i - 2] + strength_from = strength_to = strength_values[i - 2][1] + batch_index_from = keyframe_positions[i - 1] + batch_index_to_excl = last_key_frame_position + (weights, frame_numbers) = calculate_weights(batch_index_from, batch_index_to_excl, strength_from, strength_to, interpolation, False, last_key_frame_position, i, len(keyframe_positions), buffer) + else: + image = images[i - 1] + (key_frame_influence_from, key_frame_influence_to) = key_frame_influence_values[i - 1] + (start_strength, mid_strength, end_strength) = strength_values[i - 1] + keyframe_position = keyframe_positions[i] + previous_key_frame_position = keyframe_positions[i - 1] + batch_index_from = calculate_influence_frame_number(keyframe_position, previous_key_frame_position, key_frame_influence_from) + batch_index_to_excl = keyframe_position + (first_half_weights, first_half_frame_numbers) = calculate_weights(batch_index_from, batch_index_to_excl, start_strength, mid_strength, interpolation, False, last_key_frame_position, i, len(keyframe_positions), buffer) + next_key_frame_position = keyframe_positions[i + 1] + batch_index_from = keyframe_position + batch_index_to_excl = calculate_influence_frame_number(keyframe_position, next_key_frame_position, key_frame_influence_to) + (second_half_weights, second_half_frame_numbers) = calculate_weights(batch_index_from, batch_index_to_excl, mid_strength, end_strength, interpolation, False, last_key_frame_position, i, len(keyframe_positions), buffer) + weights = np.concatenate([first_half_weights, second_half_weights]) + frame_numbers = np.concatenate([first_half_frame_numbers, second_half_frame_numbers]) + (ipa_frame_numbers, ipa_weights) = process_weights(frame_numbers, weights, 1.0) + prepare_for_clip_vision = PrepImageForClipVisionImport() + (prepped_image,) = prepare_for_clip_vision.prep_image(image=image.unsqueeze(0), interpolation='LANCZOS', crop_position='pad', sharpening=0.1) + mask = create_mask_batch(last_key_frame_position, ipa_weights, ipa_frame_numbers) + if base_ipa_advanced_settings['ipa_noise_strength'] > 0: + if base_ipa_advanced_settings['use_image_for_noise']: + noise_image = prepped_image + else: + noise_image = None + ipa_noise = IPAdapterNoiseImport() + (negative_noise,) = ipa_noise.make_noise(type=base_ipa_advanced_settings['type_of_noise'], strength=base_ipa_advanced_settings['ipa_noise_strength'], blur=base_ipa_advanced_settings['noise_blur'], image_optional=noise_image) + else: + negative_noise = None + ipadapter_application = IPAdapterAdvancedImport() + (model,) = ipadapter_application.apply_ipadapter(model=model, ipadapter=ipadapter, image=prepped_image, weight=base_ipa_advanced_settings['ipa_weight'], weight_type=base_ipa_advanced_settings['ipa_weight_type'], start_at=base_ipa_advanced_settings['ipa_starts_at'], end_at=base_ipa_advanced_settings['ipa_ends_at'], clip_vision=clip_vision, attn_mask=mask, image_negative=negative_noise, embeds_scaling=base_ipa_advanced_settings['ipa_embeds_scaling']) + if high_detail_mode: + if detail_ipa_advanced_settings['ipa_noise_strength'] > 0: + if detail_ipa_advanced_settings['use_image_for_noise']: + noise_image = image.unsqueeze(0) + else: + noise_image = None + ipa_noise = IPAdapterNoiseImport() + (negative_noise,) = ipa_noise.make_noise(type=detail_ipa_advanced_settings['type_of_noise'], strength=detail_ipa_advanced_settings['ipa_noise_strength'], blur=detail_ipa_advanced_settings['noise_blur'], image_optional=noise_image) + else: + negative_noise = None + tiled_ipa_application = IPAdapterTiledImport() + (model, *_) = tiled_ipa_application.apply_tiled(model=model, ipadapter=ipadapter, image=image.unsqueeze(0), weight=detail_ipa_advanced_settings['ipa_weight'], weight_type=detail_ipa_advanced_settings['ipa_weight_type'], start_at=detail_ipa_advanced_settings['ipa_starts_at'], end_at=detail_ipa_advanced_settings['ipa_ends_at'], clip_vision=clip_vision, attn_mask=mask, sharpening=0.1, image_negative=negative_noise, embeds_scaling=detail_ipa_advanced_settings['ipa_embeds_scaling']) + all_ipa_frame_numbers.append(ipa_frame_numbers) + all_ipa_weights.append(ipa_weights) + (comparison_diagram,) = plot_weight_comparison(all_cn_frame_numbers, all_cn_weights, all_ipa_frame_numbers, all_ipa_weights, buffer) + return (comparison_diagram, positive, negative, model, sparse_indexes, last_key_frame_position) +``` \ No newline at end of file diff --git a/docs/BatchCropFromMask.md b/docs/BatchCropFromMask.md new file mode 100644 index 0000000..7bfb295 --- /dev/null +++ b/docs/BatchCropFromMask.md @@ -0,0 +1,129 @@ +# Documentation +- Class name: BatchCropFromMask +- Category: KJNodes/masking +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +BatchCropFromMask节点旨在处理一批图像及其对应的掩码,以产生裁剪后的图像。它根据掩码识别图像中的兴趣区域,并应用裁剪操作以专注于这些区域。该节点还平滑了边界框的大小和中心,以增强批量中不同图像裁剪过程的一致性。 + +# Input types +## Required +- original_images + - original_images参数至关重要,因为它代表了将由节点处理的图像批次。该节点将使用这些图像与提供的掩码结合,以确定要裁剪的区域。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +- masks + - masks参数定义了对应于原始图像中兴趣区域的二进制掩码。这些掩码对于节点识别裁剪后应保留图像的哪些部分至关重要。 + - Comfy dtype: MASK + - Python dtype: List[torch.Tensor] +## Optional +- crop_size_mult + - crop_size_mult参数允许通过将此因子与边界框尺寸相乘来调整裁剪区域的大小。它在控制裁剪操作的范围方面提供了灵活性。 + - Comfy dtype: FLOAT + - Python dtype: float +- bbox_smooth_alpha + - bbox_smooth_alpha参数控制批次中连续图像之间边界框大小的平滑度。它有助于保持一致的裁剪大小,这对于批量处理非常重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- original_images + - original_images输出包含输入到节点的原始图像批次,未改变且以其原始形式存在。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +- cropped_images + - cropped_images输出提供了根据相应掩码识别的区域进行裁剪的图像批次。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- bboxes + - bboxes输出包括用于确定批次中每张图像裁剪区域的边界框。 + - Comfy dtype: BBOX + - Python dtype: List[Tuple[int, int, int, int]] +- width + - width输出表示平滑和乘法处理后的边界框宽度,指示裁剪区域的水平范围。 + - Comfy dtype: INT + - Python dtype: int +- height + - height输出对应于平滑和乘法处理后的边界框高度,指示裁剪区域的垂直范围。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchCropFromMask: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'original_images': ('IMAGE',), 'masks': ('MASK',), 'crop_size_mult': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'bbox_smooth_alpha': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE', 'IMAGE', 'BBOX', 'INT', 'INT') + RETURN_NAMES = ('original_images', 'cropped_images', 'bboxes', 'width', 'height') + FUNCTION = 'crop' + CATEGORY = 'KJNodes/masking' + + def smooth_bbox_size(self, prev_bbox_size, curr_bbox_size, alpha): + if alpha == 0: + return prev_bbox_size + return round(alpha * curr_bbox_size + (1 - alpha) * prev_bbox_size) + + def smooth_center(self, prev_center, curr_center, alpha=0.5): + if alpha == 0: + return prev_center + return (round(alpha * curr_center[0] + (1 - alpha) * prev_center[0]), round(alpha * curr_center[1] + (1 - alpha) * prev_center[1])) + + def crop(self, masks, original_images, crop_size_mult, bbox_smooth_alpha): + bounding_boxes = [] + cropped_images = [] + self.max_bbox_width = 0 + self.max_bbox_height = 0 + curr_max_bbox_width = 0 + curr_max_bbox_height = 0 + for mask in masks: + _mask = tensor2pil(mask)[0] + non_zero_indices = np.nonzero(np.array(_mask)) + (min_x, max_x) = (np.min(non_zero_indices[1]), np.max(non_zero_indices[1])) + (min_y, max_y) = (np.min(non_zero_indices[0]), np.max(non_zero_indices[0])) + width = max_x - min_x + height = max_y - min_y + curr_max_bbox_width = max(curr_max_bbox_width, width) + curr_max_bbox_height = max(curr_max_bbox_height, height) + self.max_bbox_width = self.smooth_bbox_size(self.max_bbox_width, curr_max_bbox_width, bbox_smooth_alpha) + self.max_bbox_height = self.smooth_bbox_size(self.max_bbox_height, curr_max_bbox_height, bbox_smooth_alpha) + self.max_bbox_width = round(self.max_bbox_width * crop_size_mult) + self.max_bbox_height = round(self.max_bbox_height * crop_size_mult) + bbox_aspect_ratio = self.max_bbox_width / self.max_bbox_height + for (i, (mask, img)) in enumerate(zip(masks, original_images)): + _mask = tensor2pil(mask)[0] + non_zero_indices = np.nonzero(np.array(_mask)) + (min_x, max_x) = (np.min(non_zero_indices[1]), np.max(non_zero_indices[1])) + (min_y, max_y) = (np.min(non_zero_indices[0]), np.max(non_zero_indices[0])) + center_x = np.mean(non_zero_indices[1]) + center_y = np.mean(non_zero_indices[0]) + curr_center = (round(center_x), round(center_y)) + if not hasattr(self, 'prev_center'): + self.prev_center = curr_center + if i > 0: + center = self.smooth_center(self.prev_center, curr_center, bbox_smooth_alpha) + else: + center = curr_center + self.prev_center = center + half_box_width = round(self.max_bbox_width / 2) + half_box_height = round(self.max_bbox_height / 2) + min_x = max(0, center[0] - half_box_width) + max_x = min(img.shape[1], center[0] + half_box_width) + min_y = max(0, center[1] - half_box_height) + max_y = min(img.shape[0], center[1] + half_box_height) + bounding_boxes.append((min_x, min_y, max_x - min_x, max_y - min_y)) + cropped_img = img[min_y:max_y, min_x:max_x, :] + new_height = min(cropped_img.shape[0], self.max_bbox_height) + new_width = round(new_height * bbox_aspect_ratio) + resize_transform = Resize((new_height, new_width)) + resized_img = resize_transform(cropped_img.permute(2, 0, 1)) + crop_transform = CenterCrop((self.max_bbox_height, self.max_bbox_width)) + cropped_resized_img = crop_transform(resized_img) + cropped_images.append(cropped_resized_img.permute(1, 2, 0)) + cropped_out = torch.stack(cropped_images, dim=0) + return (original_images, cropped_out, bounding_boxes, self.max_bbox_width, self.max_bbox_height) +``` \ No newline at end of file diff --git a/docs/BatchCropFromMaskAdvanced.md b/docs/BatchCropFromMaskAdvanced.md new file mode 100644 index 0000000..f1875de --- /dev/null +++ b/docs/BatchCropFromMaskAdvanced.md @@ -0,0 +1,174 @@ +# Documentation +- Class name: BatchCropFromMaskAdvanced +- Category: KJNodes/masking +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +BatchCropFromMaskAdvanced 节点的 'crop' 方法旨在根据提供的掩码智能裁剪图像。它计算每个掩码的边界框,平滑边界框大小和中心,然后将图像和掩码裁剪到统一大小,同时保持掩码区域的完整性。当需要为进一步处理准备图像且需要一致的图像尺寸时,此节点特别有用。 + +# Input types +## Required +- original_images + - original_images 参数是包含将由节点处理的原始图像数据的关键输入。它对节点的执行至关重要,因为它直接影响裁剪操作和最终输出图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- masks + - masks 参数定义了在裁剪过程中需要保留的图像中的兴趣区域。它在确保裁剪时不会丢失图像的重要部分中起着至关重要的作用。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- crop_size_mult + - crop_size_mult 参数用于调整裁剪图像的大小。这是一个可选输入,允许用户控制最终裁剪大小与原始图像尺寸的比例。 + - Comfy dtype: FLOAT + - Python dtype: float +- bbox_smooth_alpha + - bbox_smooth_alpha 参数负责控制连续图像之间边界框大小的平滑度。它提供了一种保持不同裁剪之间一致大小的方法,这对于某些类型的图像分析可能很重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- original_images + - original_images 输出包含作为输入提供给节点的原始图像数据。它作为用户参考,用于比较裁剪操作前后的效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- cropped_images + - cropped_images 输出由根据掩码和指定参数裁剪的图像组成。这些是节点操作的主要结果,已准备好进行进一步的处理或分析。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- cropped_masks + - cropped_masks 输出包括与裁剪后的图像相对应的掩码。它确保掩码识别的兴趣区域保留在最终输出中。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- combined_crop_image + - combined_crop_image 输出是所有输入裁剪图像的组合。它可以用于可视化目的,快速评估不同图像裁剪的一致性和质量。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- combined_crop_masks + - combined_crop_masks 输出代表所有裁剪图像的组合掩码。对于需要对掩码区域进行进一步分析的应用,此输出可能很有用。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- bboxes + - bboxes 输出为每个单独裁剪图像提供边界框坐标。对于需要精确定位图像内区域的应用,这些信息可能很重要。 + - Comfy dtype: BBOX + - Python dtype: List[Tuple[int, int, int, int]] +- combined_bounding_box + - combined_bounding_box 输出提供了组合裁剪图像的边界框。当需要一个单一的边界框来封装所有裁剪区域以进行进一步处理或分析时,它很有用。 + - Comfy dtype: BBOX + - Python dtype: List[Tuple[int, int, int, int]] +- bbox_width + - bbox_width 输出表示组合裁剪图像的边界框宽度。它是裁剪区域水平范围的度量,可用于尺寸计算。 + - Comfy dtype: INT + - Python dtype: int +- bbox_height + - bbox_height 输出表示组合裁剪图像的边界框高度。它是裁剪区域垂直范围的度量,可用于尺寸计算。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: GPU + +# Source code +``` +class BatchCropFromMaskAdvanced: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'original_images': ('IMAGE',), 'masks': ('MASK',), 'crop_size_mult': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'bbox_smooth_alpha': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE', 'IMAGE', 'MASK', 'IMAGE', 'MASK', 'BBOX', 'BBOX', 'INT', 'INT') + RETURN_NAMES = ('original_images', 'cropped_images', 'cropped_masks', 'combined_crop_image', 'combined_crop_masks', 'bboxes', 'combined_bounding_box', 'bbox_width', 'bbox_height') + FUNCTION = 'crop' + CATEGORY = 'KJNodes/masking' + + def smooth_bbox_size(self, prev_bbox_size, curr_bbox_size, alpha): + return round(alpha * curr_bbox_size + (1 - alpha) * prev_bbox_size) + + def smooth_center(self, prev_center, curr_center, alpha=0.5): + return (round(alpha * curr_center[0] + (1 - alpha) * prev_center[0]), round(alpha * curr_center[1] + (1 - alpha) * prev_center[1])) + + def crop(self, masks, original_images, crop_size_mult, bbox_smooth_alpha): + bounding_boxes = [] + combined_bounding_box = [] + cropped_images = [] + cropped_masks = [] + cropped_masks_out = [] + combined_crop_out = [] + combined_cropped_images = [] + combined_cropped_masks = [] + + def calculate_bbox(mask): + non_zero_indices = np.nonzero(np.array(mask)) + (min_x, max_x, min_y, max_y) = (0, 0, 0, 0) + if len(non_zero_indices[1]) > 0 and len(non_zero_indices[0]) > 0: + (min_x, max_x) = (np.min(non_zero_indices[1]), np.max(non_zero_indices[1])) + (min_y, max_y) = (np.min(non_zero_indices[0]), np.max(non_zero_indices[0])) + width = max_x - min_x + height = max_y - min_y + bbox_size = max(width, height) + return (min_x, max_x, min_y, max_y, bbox_size) + combined_mask = torch.max(masks, dim=0)[0] + _mask = tensor2pil(combined_mask)[0] + (new_min_x, new_max_x, new_min_y, new_max_y, combined_bbox_size) = calculate_bbox(_mask) + center_x = (new_min_x + new_max_x) / 2 + center_y = (new_min_y + new_max_y) / 2 + half_box_size = round(combined_bbox_size // 2) + new_min_x = max(0, round(center_x - half_box_size)) + new_max_x = min(original_images[0].shape[1], round(center_x + half_box_size)) + new_min_y = max(0, round(center_y - half_box_size)) + new_max_y = min(original_images[0].shape[0], round(center_y + half_box_size)) + combined_bounding_box.append((new_min_x, new_min_y, new_max_x - new_min_x, new_max_y - new_min_y)) + self.max_bbox_size = 0 + curr_max_bbox_size = max((calculate_bbox(tensor2pil(mask)[0])[-1] for mask in masks)) + self.max_bbox_size = self.smooth_bbox_size(self.max_bbox_size, curr_max_bbox_size, bbox_smooth_alpha) + self.max_bbox_size = round(self.max_bbox_size * crop_size_mult) + self.max_bbox_size = math.ceil(self.max_bbox_size / 16) * 16 + if self.max_bbox_size > original_images[0].shape[0] or self.max_bbox_size > original_images[0].shape[1]: + self.max_bbox_size = math.floor(min(original_images[0].shape[0], original_images[0].shape[1]) / 2) * 2 + for (i, (mask, img)) in enumerate(zip(masks, original_images)): + _mask = tensor2pil(mask)[0] + non_zero_indices = np.nonzero(np.array(_mask)) + if len(non_zero_indices[0]) > 0 and len(non_zero_indices[1]) > 0: + (min_x, max_x) = (np.min(non_zero_indices[1]), np.max(non_zero_indices[1])) + (min_y, max_y) = (np.min(non_zero_indices[0]), np.max(non_zero_indices[0])) + center_x = np.mean(non_zero_indices[1]) + center_y = np.mean(non_zero_indices[0]) + curr_center = (round(center_x), round(center_y)) + if not hasattr(self, 'prev_center'): + self.prev_center = curr_center + if i > 0: + center = self.smooth_center(self.prev_center, curr_center, bbox_smooth_alpha) + else: + center = curr_center + self.prev_center = center + half_box_size = self.max_bbox_size // 2 + min_x = max(0, center[0] - half_box_size) + max_x = min(img.shape[1], center[0] + half_box_size) + min_y = max(0, center[1] - half_box_size) + max_y = min(img.shape[0], center[1] + half_box_size) + bounding_boxes.append((min_x, min_y, max_x - min_x, max_y - min_y)) + cropped_img = img[min_y:max_y, min_x:max_x, :] + cropped_mask = mask[min_y:max_y, min_x:max_x] + new_size = max(cropped_img.shape[0], cropped_img.shape[1]) + resize_transform = Resize(new_size, interpolation=InterpolationMode.NEAREST, max_size=max(img.shape[0], img.shape[1])) + resized_mask = resize_transform(cropped_mask.unsqueeze(0).unsqueeze(0)).squeeze(0).squeeze(0) + resized_img = resize_transform(cropped_img.permute(2, 0, 1)) + crop_transform = CenterCrop((min(self.max_bbox_size, resized_img.shape[1]), min(self.max_bbox_size, resized_img.shape[2]))) + cropped_resized_img = crop_transform(resized_img) + cropped_images.append(cropped_resized_img.permute(1, 2, 0)) + cropped_resized_mask = crop_transform(resized_mask) + cropped_masks.append(cropped_resized_mask) + combined_cropped_img = original_images[i][new_min_y:new_max_y, new_min_x:new_max_x, :] + combined_cropped_images.append(combined_cropped_img) + combined_cropped_mask = masks[i][new_min_y:new_max_y, new_min_x:new_max_x] + combined_cropped_masks.append(combined_cropped_mask) + else: + bounding_boxes.append((0, 0, img.shape[1], img.shape[0])) + cropped_images.append(img) + cropped_masks.append(mask) + combined_cropped_images.append(img) + combined_cropped_masks.append(mask) + cropped_out = torch.stack(cropped_images, dim=0) + combined_crop_out = torch.stack(combined_cropped_images, dim=0) + cropped_masks_out = torch.stack(cropped_masks, dim=0) + combined_crop_mask_out = torch.stack(combined_cropped_masks, dim=0) + return (original_images, cropped_out, cropped_masks_out, combined_crop_out, combined_crop_mask_out, bounding_boxes, combined_bounding_box, self.max_bbox_size, self.max_bbox_size) +``` \ No newline at end of file diff --git a/docs/BatchPromptSchedule.md b/docs/BatchPromptSchedule.md new file mode 100644 index 0000000..7147101 --- /dev/null +++ b/docs/BatchPromptSchedule.md @@ -0,0 +1,93 @@ +# Documentation +- Class name: BatchPromptSchedule +- Category: FizzNodes 📅🅕🅝/BatchScheduleNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +BatchPromptSchedule节点旨在批量处理环境中管理和动画提示。它接受各种参数以自定义动画过程,包括文本、剪辑引用和帧规范。节点的主要功能是协调动画序列,通过应用权重和条件确保帧之间平滑过渡。它特别适用于创建需要对每帧内容进行精确控制的复杂动画。 + +# Input types +## Required +- text + - 'text'参数是一个包含动画提示的字符串。它对于定义动画的内容和顺序至关重要。此输入驱动动画输出的整体叙述和结构。 + - Comfy dtype: STRING + - Python dtype: str +- clip + - 'clip'参数是对在动画过程中使用的多媒体剪辑的引用。它在动画的视觉表现方式中起着重要作用,并且对于将视听元素整合到动画中至关重要。 + - Comfy dtype: CLIP + - Python dtype: Any +- max_frames + - 'max_frames'参数指定动画序列的最大帧数。它是动画持续时间和节奏的关键决定因素,影响动画的整体时间和流程。 + - Comfy dtype: INT + - Python dtype: int +- print_output + - 'print_output'参数是一个布尔标志,设置为True时,将打印动画过程的中间结果。这对于调试和理解节点的操作很有帮助。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- pre_text + - 'pre_text'参数是一个可选字符串,为动画提示提供额外的上下文或设置。它可以用于引入或框架动画的内容。 + - Comfy dtype: STRING + - Python dtype: str +- app_text + - 'app_text'参数是一个可选字符串,为动画提示添加结束语或结束声明。它有助于完成或总结动画的信息。 + - Comfy dtype: STRING + - Python dtype: str +- start_frame + - 'start_frame'参数是一个可选整数,它设置动画的起始帧。它允许自定义动画序列的起始点。 + - Comfy dtype: INT + - Python dtype: int +- pw_a + - 'pw_a'参数是一个可选的浮点数,表示应用于动画提示的权重。它用于调整动画中某些提示的影响。 + - Comfy dtype: FLOAT + - Python dtype: float +- pw_b + - 'pw_b'参数是另一个可选的浮点数,用作动画提示的次要权重。它根据分配的权重进一步细化对动画内容的控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- pw_c + - 'pw_c'参数是一个可选的浮点数,作为动画提示的第三权重。它有助于动画进展的细微控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- pw_d + - 'pw_d'参数是一个可选的浮点数,代表动画提示的四元权重。它为动画的细节提供了额外的控制层。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- POS + - 'POS'输出提供从动画提示派生的正面条件数据。它对于将动画的方向和基调引导到更有利的结果具有重要意义。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] +- NEG + - 'NEG'输出提供从动画提示中提取的负面条件数据。它对于通过突出较不受欢迎的元素,在动画中建立对比和平衡至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchPromptSchedule: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True, 'default': defaultPrompt}), 'clip': ('CLIP',), 'max_frames': ('INT', {'default': 120.0, 'min': 1.0, 'max': 999999.0, 'step': 1.0}), 'print_output': ('BOOLEAN', {'default': False})}, 'optional': {'pre_text': ('STRING', {'multiline': True}), 'app_text': ('STRING', {'multiline': True}), 'start_frame': ('INT', {'default': 0, 'min': 0, 'max': 9999, 'step': 1}), 'pw_a': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_b': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_c': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_d': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('POS', 'NEG') + FUNCTION = 'animate' + CATEGORY = 'FizzNodes 📅🅕🅝/BatchScheduleNodes' + + def animate(self, text, max_frames, print_output, clip, start_frame, pw_a, pw_b, pw_c, pw_d, pre_text='', app_text=''): + inputText = str('{' + text + '}') + inputText = re.sub(',\\s*}', '}', inputText) + max_frames += start_frame + animation_prompts = json.loads(inputText.strip()) + (pos, neg) = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text) + (pos_cur_prompt, pos_nxt_prompt, weight) = interpolate_prompt_series(pos, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) + pc = BatchPoolAnimConditioning(pos_cur_prompt, pos_nxt_prompt, weight, clip) + (neg_cur_prompt, neg_nxt_prompt, weight) = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) + nc = BatchPoolAnimConditioning(neg_cur_prompt, neg_nxt_prompt, weight, clip) + return (pc, nc) +``` \ No newline at end of file diff --git a/docs/BatchPromptScheduleEncodeSDXL.md b/docs/BatchPromptScheduleEncodeSDXL.md new file mode 100644 index 0000000..755d703 --- /dev/null +++ b/docs/BatchPromptScheduleEncodeSDXL.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: BatchPromptScheduleEncodeSDXL +- Category: FizzNodes 📅🅕🅝/BatchScheduleNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +BatchPromptScheduleEncodeSDXL 节点旨在处理并为图像或视频生成动画化一系列提示。它接收各种参数,如文本提示、尺寸和插值权重,以创建动态的提示序列,然后对这些提示进行编码,以便在生成模型中使用。该节点在动画流水线中扮演着关键角色,通过生成必要的条件数据,实现帧与帧之间连贯和平滑的过渡。 + +# Input types +## Required +- width + - 宽度参数对于定义生成媒体的尺寸至关重要。它与高度参数一起工作,确保输出遵守所需的纵横比和分辨率。 + - Comfy dtype: INT + - Python dtype: int +- text_g + - text_g 输入包含用于生成动画的图形提示的字符串。它是塑造动画序列视觉输出的关键组成部分。 + - Comfy dtype: STRING + - Python dtype: str +- max_frames + - max_frames 参数规定了为动画生成的最大帧数。它是决定最终输出长度和复杂度的关键因素。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- pw_a + - pw_a 参数是插值过程中使用的可选权重因子。它允许微调动画序列中某些提示的影响。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- POS + - POS 输出提供了从提示中派生的正面条件数据,用于引导生成过程朝着更有利的结果发展。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- NEG + - NEG 输出包含负面条件数据,通过提供反例或约束,有助于引导生成过程避免不希望的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class BatchPromptScheduleEncodeSDXL: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'crop_w': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION}), 'crop_h': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION}), 'target_width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'target_height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'text_g': ('STRING', {'multiline': True}), 'clip': ('CLIP',), 'text_l': ('STRING', {'multiline': True}), 'clip': ('CLIP',), 'max_frames': ('INT', {'default': 120.0, 'min': 1.0, 'max': 999999.0, 'step': 1.0}), 'print_output': ('BOOLEAN', {'default': False})}, 'optional': {'pre_text_G': ('STRING', {'multiline': True}), 'app_text_G': ('STRING', {'multiline': True}), 'pre_text_L': ('STRING', {'multiline': True}), 'app_text_L': ('STRING', {'multiline': True}), 'pw_a': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_b': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_c': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_d': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('POS', 'NEG') + FUNCTION = 'animate' + CATEGORY = 'FizzNodes 📅🅕🅝/BatchScheduleNodes' + + def animate(self, clip, width, height, crop_w, crop_h, target_width, target_height, text_g, text_l, app_text_G, app_text_L, pre_text_G, pre_text_L, max_frames, print_output, pw_a, pw_b, pw_c, pw_d): + inputTextG = str('{' + text_g + '}') + inputTextL = str('{' + text_l + '}') + inputTextG = re.sub(',\\s*}', '}', inputTextG) + inputTextL = re.sub(',\\s*}', '}', inputTextL) + animation_promptsG = json.loads(inputTextG.strip()) + animation_promptsL = json.loads(inputTextL.strip()) + (posG, negG) = batch_split_weighted_subprompts(animation_promptsG, pre_text_G, app_text_G) + (posL, negL) = batch_split_weighted_subprompts(animation_promptsL, pre_text_L, app_text_L) + (pc, pn, pw) = BatchInterpolatePromptsSDXL(posG, posL, max_frames, clip, app_text_G, app_text_L, pre_text_G, pre_text_L, pw_a, pw_b, pw_c, pw_d, width, height, crop_w, crop_h, target_width, target_height, print_output) + p = BatchPoolAnimConditioningSDXL(pc, pn, pw) + (nc, nn, nw) = BatchInterpolatePromptsSDXL(negG, negL, max_frames, clip, app_text_G, app_text_L, pre_text_G, pre_text_L, pw_a, pw_b, pw_c, pw_d, width, height, crop_w, crop_h, target_width, target_height, print_output) + n = BatchPoolAnimConditioningSDXL(nc, nn, nw) + return (p, n) +``` \ No newline at end of file diff --git a/docs/BatchPromptScheduleLatentInput.md b/docs/BatchPromptScheduleLatentInput.md new file mode 100644 index 0000000..deb4449 --- /dev/null +++ b/docs/BatchPromptScheduleLatentInput.md @@ -0,0 +1,82 @@ +# Documentation +- Class name: BatchPromptScheduleLatentInput +- Category: FizzNodes 📅🅕🅝/BatchScheduleNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +BatchPromptScheduleLatentInput节点的`animate`方法旨在处理和生成动画提示,这些提示用于在批量处理环境中创建动画序列。它接受各种参数,如文本、潜在数量和权重,以控制跨帧提示的插值。该节点的主要功能是创建一系列提示,这些提示可用于动画序列,具有使用提供的权重调整每个提示影响的能力。此方法对于动画过程至关重要,因为它为每个帧的动画设置了条件。 + +# Input types +## Required +- text + - 'text'参数是一个包含动画基础提示的字符串。它是动画过程的基本部分,因为它定义了动画序列的初始条件。预期文本格式是节点能够解释并用于生成提示的格式。 + - Comfy dtype: STRING + - Python dtype: str +- num_latents + - 'num_latents'参数指定了动画过程中使用的潜在变量。它对于确定动画帧的范围和多样性至关重要。此参数影响如何探索和利用潜在空间来创建动画。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +## Optional +- print_output + - 'print_output'参数是一个布尔标志,设置为True时,将把动画提示的输出打印到控制台。这对于调试目的或在生成提示时直观检查提示非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- start_frame + - 'start_frame'参数决定了动画序列开始的帧。这是一个可选参数,允许定制动画的起始点。 + - Comfy dtype: INT + - Python dtype: int +- pw_a + - 'pw_a'参数是一个浮点数,表示用于动画提示插值的权重。它影响帧之间的过渡,并有助于动画的平滑度。 + - Comfy dtype: FLOAT + - Python dtype: float +- pre_text + - 'pre_text'参数是一个可选字符串,可用于在每个动画提示前添加文本。这对于在每个提示的开头添加一致的元素非常有用。 + - Comfy dtype: STRING + - Python dtype: str +- app_text + - 'app_text'参数是一个可选字符串,可用于在每个动画提示后添加文本。它允许在每个提示的末尾添加一致的元素。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- POS + - 'POS'输出为每个帧的动画提供正向条件信息。它来源于正向提示的插值,对于引导动画达到预期结果至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- NEG + - 'NEG'输出为每个帧的动画提供负向条件信息。它来源于负向提示的插值,并有助于通过引导动画远离不希望的结果来细化动画。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- INPUT_LATENTS + - 'INPUT_LATENTS'输出包含动画过程中使用的潜在变量。这些潜在变量对于生成动画帧至关重要,代表了用于创建最终动画的底层数据。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchPromptScheduleLatentInput: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True, 'default': defaultPrompt}), 'clip': ('CLIP',), 'num_latents': ('LATENT',), 'print_output': ('BOOLEAN', {'default': False})}, 'optional': {'pre_text': ('STRING', {'multiline': True}), 'app_text': ('STRING', {'multiline': True}), 'start_frame': ('INT', {'default': 0.0, 'min': 0, 'max': 9999, 'step': 1}), 'pw_a': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_b': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_c': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_d': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING', 'LATENT') + RETURN_NAMES = ('POS', 'NEG', 'INPUT_LATENTS') + FUNCTION = 'animate' + CATEGORY = 'FizzNodes 📅🅕🅝/BatchScheduleNodes' + + def animate(self, text, num_latents, print_output, clip, start_frame, pw_a, pw_b, pw_c, pw_d, pre_text='', app_text=''): + max_frames = sum((tensor.size(0) for tensor in num_latents.values())) + max_frames += start_frame + inputText = str('{' + text + '}') + inputText = re.sub(',\\s*}', '}', inputText) + animation_prompts = json.loads(inputText.strip()) + (pos, neg) = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text) + (pos_cur_prompt, pos_nxt_prompt, weight) = interpolate_prompt_series(pos, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) + pc = BatchPoolAnimConditioning(pos_cur_prompt, pos_nxt_prompt, weight, clip) + (neg_cur_prompt, neg_nxt_prompt, weight) = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) + nc = BatchPoolAnimConditioning(neg_cur_prompt, neg_nxt_prompt, weight, clip) + return (pc, nc, num_latents) +``` \ No newline at end of file diff --git a/docs/BatchPromptScheduleSDXLLatentInput.md b/docs/BatchPromptScheduleSDXLLatentInput.md new file mode 100644 index 0000000..59e69ea --- /dev/null +++ b/docs/BatchPromptScheduleSDXLLatentInput.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: BatchPromptScheduleEncodeSDXLLatentInput +- Category: FizzNodes 📅🅕🅝/BatchScheduleNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +BatchPromptScheduleEncodeSDXLLatentInput 节点旨在将一批提示处理并编码成适合在生成模型中使用的潜在表示。它处理提示插值和条件化的复杂性,抽象化了过程的细节,提供了一个简化的接口来生成潜在输入。 + +# Input types +## Required +- width + - 宽度参数对于定义输入图像的尺寸至关重要。它在节点的操作中起着关键作用,决定了图像处理的分辨率。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数与宽度类似,对于指定输入图像的垂直尺寸至关重要,影响节点如何处理和编码图像数据。 + - Comfy dtype: INT + - Python dtype: int +- text_g + - text_g 输入是一个包含生成模型提示的字符串。它是节点功能的关键组成部分,因为它直接影响潜在表示的生成。 + - Comfy dtype: STRING + - Python dtype: str +- num_latents + - num_latents 参数指定由节点生成的潜在向量的数量。它很重要,因为它决定了潜在空间表示的输出大小。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Output types +- POS + - POS 输出为生成模型提供正向条件数据,这对于将生成过程引向期望的结果具有重要意义。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- NEG + - NEG 输出包含负向条件数据,用于引导生成过程远离不希望的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- LATENT + - LATENT 输出表示由节点生成的潜在向量,用作进一步处理或直接在生成模型中使用的输入。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchPromptScheduleEncodeSDXLLatentInput: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'crop_w': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION}), 'crop_h': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION}), 'target_width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'target_height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'text_g': ('STRING', {'multiline': True}), 'clip': ('CLIP',), 'text_l': ('STRING', {'multiline': True}), 'clip': ('CLIP',), 'num_latents': ('LATENT',), 'print_output': ('BOOLEAN', {'default': False})}, 'optional': {'pre_text_G': ('STRING', {'multiline': True}), 'app_text_G': ('STRING', {'multiline': True}), 'pre_text_L': ('STRING', {'multiline': True}), 'app_text_L': ('STRING', {'multiline': True}), 'pw_a': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_b': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_c': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_d': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING', 'LATENT') + RETURN_NAMES = ('POS', 'NEG') + FUNCTION = 'animate' + CATEGORY = 'FizzNodes 📅🅕🅝/BatchScheduleNodes' + + def animate(self, clip, width, height, crop_w, crop_h, target_width, target_height, text_g, text_l, app_text_G, app_text_L, pre_text_G, pre_text_L, num_latents, print_output, pw_a, pw_b, pw_c, pw_d): + max_frames = sum((tensor.size(0) for tensor in num_latents.values())) + inputTextG = str('{' + text_g + '}') + inputTextL = str('{' + text_l + '}') + inputTextG = re.sub(',\\s*}', '}', inputTextG) + inputTextL = re.sub(',\\s*}', '}', inputTextL) + animation_promptsG = json.loads(inputTextG.strip()) + animation_promptsL = json.loads(inputTextL.strip()) + (posG, negG) = batch_split_weighted_subprompts(animation_promptsG, pre_text_G, app_text_G) + (posL, negL) = batch_split_weighted_subprompts(animation_promptsL, pre_text_L, app_text_L) + (pc, pn, pw) = BatchInterpolatePromptsSDXL(posG, posL, max_frames, clip, app_text_G, app_text_L, pre_text_G, pre_text_L, pw_a, pw_b, pw_c, pw_d, width, height, crop_w, crop_h, target_width, target_height, print_output) + p = BatchPoolAnimConditioningSDXL(pc, pn, pw) + (nc, nn, nw) = BatchInterpolatePromptsSDXL(negG, negL, max_frames, clip, app_text_G, app_text_L, pre_text_G, pre_text_L, pw_a, pw_b, pw_c, pw_d, width, height, crop_w, crop_h, target_width, target_height, print_output) + n = BatchPoolAnimConditioningSDXL(nc, nn, nw) + return (p, n, num_latents) +``` \ No newline at end of file diff --git a/docs/BatchStringSchedule.md b/docs/BatchStringSchedule.md new file mode 100644 index 0000000..e552879 --- /dev/null +++ b/docs/BatchStringSchedule.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: BatchStringSchedule +- Category: FizzNodes 📅🅕🅝/BatchScheduleNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +BatchStringSchedule节点的`animate`方法旨在基于结构化输入文本处理并生成文本动画。它利用一系列加权子提示来创建可以用于动画或生成基于文本的内容的动态提示序列。该方法对于需要在一系列帧或步骤中转换或操作文本的应用程序至关重要。 + +# Input types +## Required +- text + - 'text'参数是节点的主要输入,包含定义动画序列的结构化文本。它至关重要,因为它直接影响输出提示和整个动画过程。 + - Comfy dtype: STRING + - Python dtype: str +- max_frames + - 'max_frames'参数指定动画序列的最大帧数。它在确定动画的持续时间和粒度方面起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- print_output + - 'print_output'参数设置为True时,将打印动画过程的中间结果到控制台。这对于调试和理解动画生成流程非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- pre_text + - 'pre_text'参数用于在动画序列中每个提示的开头添加额外的上下文。这对于设置动画的初始状态或条件可能很重要。 + - Comfy dtype: STRING + - Python dtype: str +- app_text + - 'app_text'参数被追加在动画序列中每个提示的末尾,可能为生成的提示添加更多的上下文或指令。 + - Comfy dtype: STRING + - Python dtype: str +- pw_a + - 'pw_a'参数是影响动画序列中提示插值和混合的权重参数之一。它有助于帧与帧之间的平滑度和过渡。 + - Comfy dtype: FLOAT + - Python dtype: float +- pw_b + - 'pw_b'参数是另一个权重参数,它在插值过程中发挥作用,影响动画帧中提示元素的平衡和分布。 + - Comfy dtype: FLOAT + - Python dtype: float +- pw_c + - 'pw_c'参数是一个权重参数,它有助于微调动画的插值,允许对输出提示进行更精细的控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- pw_d + - 'pw_d'参数是影响插值的最终权重参数,它提供了对动画过程中提示如何演变的额外控制。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- POS + - 'POS'输出包含由动画过程生成的正面提示,代表文本动画的建设性或期望方面。 + - Comfy dtype: STRING + - Python dtype: str +- NEG + - 'NEG'输出包含由动画过程生成的负面提示,代表文本动画中要最小化或避免的方面。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchStringSchedule: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True, 'default': defaultPrompt}), 'max_frames': ('INT', {'default': 120.0, 'min': 1.0, 'max': 999999.0, 'step': 1.0}), 'print_output': ('BOOLEAN', {'default': False})}, 'optional': {'pre_text': ('STRING', {'multiline': True}), 'app_text': ('STRING', {'multiline': True}), 'pw_a': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_b': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_c': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_d': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('POS', 'NEG') + FUNCTION = 'animate' + CATEGORY = 'FizzNodes 📅🅕🅝/BatchScheduleNodes' + + def animate(self, text, max_frames, pw_a=0, pw_b=0, pw_c=0, pw_d=0, pre_text='', app_text='', print_output=False): + inputText = str('{' + text + '}') + inputText = re.sub(',\\s*}', '}', inputText) + start_frame = 0 + animation_prompts = json.loads(inputText.strip()) + (pos, neg) = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text) + (pos_cur_prompt, pos_nxt_prompt, weight) = interpolate_prompt_series(pos, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) + (neg_cur_prompt, neg_nxt_prompt, weight) = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) + return (pos_cur_prompt, neg_cur_prompt) +``` \ No newline at end of file diff --git a/docs/BatchUncrop.md b/docs/BatchUncrop.md new file mode 100644 index 0000000..5e32a4d --- /dev/null +++ b/docs/BatchUncrop.md @@ -0,0 +1,121 @@ +# Documentation +- Class name: BatchUncrop +- Category: KJNodes/masking +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +BatchUncrop节点旨在将裁剪后的图像恢复到其原始大小和形状。它通过调整大小和混合裁剪区域与原始图像来智能处理取消裁剪过程,同时考虑边框混合和缩放因子,以确保无缝集成。此节点在数据增强工作流程中扮演着关键角色,其中图像的原始上下文对于下游任务至关重要。 + +# Input types +## Required +- original_images + - original_images参数至关重要,因为它保存了裁剪前的图像引用。这对于节点准确恢复裁剪后的图像到其原始状态至关重要。此输入直接影响取消裁剪过程的结果。 + - Comfy dtype: IMAGE + - Python dtype: List[Image.Image] +- cropped_images + - cropped_images输入代表已裁剪并需要恢复的图像。它是BatchUncrop节点的关键组成部分,因为它提供了取消裁剪操作的源材料。 + - Comfy dtype: IMAGE + - Python dtype: List[Image.Image] +- bboxes + - bboxes参数定义了原始图像中被裁剪出的区域。它对于节点在取消裁剪过程中正确识别和恢复这些区域很重要。 + - Comfy dtype: BBOX + - Python dtype: List[Tuple[int, int, int, int]] +## Optional +- border_blending + - border_blending参数控制取消裁剪过程中裁剪和原始图像边框的混合效果。它对于实现图像之间的平滑过渡非常重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- crop_rescale + - crop_rescale参数调整将裁剪区域粘贴回原始图像之前的缩放比例。它影响取消裁剪区域的最终大小。 + - Comfy dtype: FLOAT + - Python dtype: float +- border_top + - border_top参数决定在取消裁剪过程中是否应在图像顶部添加边框。它有助于恢复图像的整体外观。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- border_bottom + - border_bottom参数指定在取消裁剪时是否应在图像底部包括边框。它影响图像的最终视觉效果。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- border_left + - border_left参数控制取消裁剪期间是否应在图像左侧添加边框。它是节点自定义图像边框功能的一部分。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- border_right + - border_right参数指示在执行取消裁剪时是否应将边框添加到图像的右侧。这对于保持图像的美学完整性至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- uncropped_images + - uncropped_images输出包含取消裁剪过程后的最终图像。它代表了恢复的图像,原始上下文保持不变,可供进一步使用或分析。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchUncrop: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'original_images': ('IMAGE',), 'cropped_images': ('IMAGE',), 'bboxes': ('BBOX',), 'border_blending': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'crop_rescale': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'border_top': ('BOOLEAN', {'default': True}), 'border_bottom': ('BOOLEAN', {'default': True}), 'border_left': ('BOOLEAN', {'default': True}), 'border_right': ('BOOLEAN', {'default': True})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'uncrop' + CATEGORY = 'KJNodes/masking' + + def uncrop(self, original_images, cropped_images, bboxes, border_blending, crop_rescale, border_top, border_bottom, border_left, border_right): + + def inset_border(image, border_width, border_color, border_top, border_bottom, border_left, border_right): + draw = ImageDraw.Draw(image) + (width, height) = image.size + if border_top: + draw.rectangle((0, 0, width, border_width), fill=border_color) + if border_bottom: + draw.rectangle((0, height - border_width, width, height), fill=border_color) + if border_left: + draw.rectangle((0, 0, border_width, height), fill=border_color) + if border_right: + draw.rectangle((width - border_width, 0, width, height), fill=border_color) + return image + if len(original_images) != len(cropped_images): + raise ValueError(f'The number of original_images ({len(original_images)}) and cropped_images ({len(cropped_images)}) should be the same') + if len(bboxes) > len(original_images): + print(f'Warning: Dropping excess bounding boxes. Expected {len(original_images)}, but got {len(bboxes)}') + bboxes = bboxes[:len(original_images)] + elif len(bboxes) < len(original_images): + raise ValueError('There should be at least as many bboxes as there are original and cropped images') + input_images = tensor2pil(original_images) + crop_imgs = tensor2pil(cropped_images) + out_images = [] + for i in range(len(input_images)): + img = input_images[i] + crop = crop_imgs[i] + bbox = bboxes[i] + (bb_x, bb_y, bb_width, bb_height) = bbox + paste_region = bbox_to_region((bb_x, bb_y, bb_width, bb_height), img.size) + scale_x = crop_rescale + scale_y = crop_rescale + paste_region = (round(paste_region[0] * scale_x), round(paste_region[1] * scale_y), round(paste_region[2] * scale_x), round(paste_region[3] * scale_y)) + crop = crop.resize((round(paste_region[2] - paste_region[0]), round(paste_region[3] - paste_region[1]))) + crop_img = crop.convert('RGB') + if border_blending > 1.0: + border_blending = 1.0 + elif border_blending < 0.0: + border_blending = 0.0 + blend_ratio = max(crop_img.size) / 2 * float(border_blending) + blend = img.convert('RGBA') + mask = Image.new('L', img.size, 0) + mask_block = Image.new('L', (paste_region[2] - paste_region[0], paste_region[3] - paste_region[1]), 255) + mask_block = inset_border(mask_block, round(blend_ratio / 2), 0, border_top, border_bottom, border_left, border_right) + mask.paste(mask_block, paste_region) + blend.paste(crop_img, paste_region) + mask = mask.filter(ImageFilter.BoxBlur(radius=blend_ratio / 4)) + mask = mask.filter(ImageFilter.GaussianBlur(radius=blend_ratio / 4)) + blend.putalpha(mask) + img = Image.alpha_composite(img.convert('RGBA'), blend) + out_images.append(img.convert('RGB')) + return (pil2tensor(out_images),) +``` \ No newline at end of file diff --git a/docs/BatchUncropAdvanced.md b/docs/BatchUncropAdvanced.md new file mode 100644 index 0000000..a42acee --- /dev/null +++ b/docs/BatchUncropAdvanced.md @@ -0,0 +1,131 @@ +# Documentation +- Class name: BatchUncropAdvanced +- Category: KJNodes/masking +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +BatchUncropAdvanced 节点旨在通过使用边界框坐标和掩码将裁剪后的图像精确放回原始图像的上下文中,从而恢复其原始状态。它考虑了边框混合和缩放因子,以实现自然的外观,确保裁剪部分与原始图像的无缝集成。 + +# Input types +## Required +- original_images + - 原始图像作为基础画布,裁剪后的图像将重新插入其中。它们对于保持最终输出的整体上下文和结构至关重要。 + - Comfy dtype: IMAGE + - Python dtype: List[Image.Image] +- cropped_images + - 需要还原到原始图像中的裁剪图像。这些图像携带了将要重新整合到原始上下文中的修改或专注的内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- cropped_masks + - 与裁剪图像对应的掩码,定义了将重新整合回原始图像的兴趣区域。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- combined_crop_mask + - 一个可选的组合掩码,可以用来代替单独的裁剪掩码,以实现裁剪区域的统一整合。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- bboxes + - 边界框提供原始图像中裁剪区域的坐标,对于精确放置至关重要。 + - Comfy dtype: BBOX + - Python dtype: List[Tuple[int, int, int, int]] +- border_blending + - 一个浮点值,用于确定原始图像和裁剪图像之间的边框混合强度,以实现平滑过渡。 + - Comfy dtype: FLOAT + - Python dtype: float +- crop_rescale + - 在裁剪图像调整大小并重新插入原始图像之前应用的缩放因子。 + - Comfy dtype: FLOAT + - Python dtype: float +- use_combined_mask + - 一个布尔标志,指示在取消裁剪操作中是否使用组合掩码而不是单独的裁剪掩码。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- use_square_mask + - 一个布尔标志,设置后在混合过程中使用正方形掩码而不是原始掩码形状。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- combined_bounding_box + - 一个可选参数,它提供了组合掩码的预定义边界框,覆盖了各个边界框。 + - Comfy dtype: BBOX + - Python dtype: Tuple[int, int, int, int]=None + +# Output types +- output_images + - BatchUncropAdvanced 节点的输出是原始图像,裁剪区域已还原到其原始位置,实现了图像的无缝恢复。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchUncropAdvanced: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'original_images': ('IMAGE',), 'cropped_images': ('IMAGE',), 'cropped_masks': ('MASK',), 'combined_crop_mask': ('MASK',), 'bboxes': ('BBOX',), 'border_blending': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'crop_rescale': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'use_combined_mask': ('BOOLEAN', {'default': False}), 'use_square_mask': ('BOOLEAN', {'default': True})}, 'optional': {'combined_bounding_box': ('BBOX', {'default': None})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'uncrop' + CATEGORY = 'KJNodes/masking' + + def uncrop(self, original_images, cropped_images, cropped_masks, combined_crop_mask, bboxes, border_blending, crop_rescale, use_combined_mask, use_square_mask, combined_bounding_box=None): + + def inset_border(image, border_width=20, border_color=0): + (width, height) = image.size + bordered_image = Image.new(image.mode, (width, height), border_color) + bordered_image.paste(image, (0, 0)) + draw = ImageDraw.Draw(bordered_image) + draw.rectangle((0, 0, width - 1, height - 1), outline=border_color, width=border_width) + return bordered_image + if len(original_images) != len(cropped_images): + raise ValueError(f'The number of original_images ({len(original_images)}) and cropped_images ({len(cropped_images)}) should be the same') + if len(bboxes) > len(original_images): + print(f'Warning: Dropping excess bounding boxes. Expected {len(original_images)}, but got {len(bboxes)}') + bboxes = bboxes[:len(original_images)] + elif len(bboxes) < len(original_images): + raise ValueError('There should be at least as many bboxes as there are original and cropped images') + crop_imgs = tensor2pil(cropped_images) + input_images = tensor2pil(original_images) + out_images = [] + for i in range(len(input_images)): + img = input_images[i] + crop = crop_imgs[i] + bbox = bboxes[i] + if use_combined_mask: + (bb_x, bb_y, bb_width, bb_height) = combined_bounding_box[0] + paste_region = bbox_to_region((bb_x, bb_y, bb_width, bb_height), img.size) + mask = combined_crop_mask[i] + else: + (bb_x, bb_y, bb_width, bb_height) = bbox + paste_region = bbox_to_region((bb_x, bb_y, bb_width, bb_height), img.size) + mask = cropped_masks[i] + scale_x = scale_y = crop_rescale + paste_region = (round(paste_region[0] * scale_x), round(paste_region[1] * scale_y), round(paste_region[2] * scale_x), round(paste_region[3] * scale_y)) + crop = crop.resize((round(paste_region[2] - paste_region[0]), round(paste_region[3] - paste_region[1]))) + crop_img = crop.convert('RGB') + if border_blending > 1.0: + border_blending = 1.0 + elif border_blending < 0.0: + border_blending = 0.0 + blend_ratio = max(crop_img.size) / 2 * float(border_blending) + blend = img.convert('RGBA') + if use_square_mask: + mask = Image.new('L', img.size, 0) + mask_block = Image.new('L', (paste_region[2] - paste_region[0], paste_region[3] - paste_region[1]), 255) + mask_block = inset_border(mask_block, round(blend_ratio / 2), 0) + mask.paste(mask_block, paste_region) + else: + original_mask = tensor2pil(mask)[0] + original_mask = original_mask.resize((paste_region[2] - paste_region[0], paste_region[3] - paste_region[1])) + mask = Image.new('L', img.size, 0) + mask.paste(original_mask, paste_region) + mask = mask.filter(ImageFilter.BoxBlur(radius=blend_ratio / 4)) + mask = mask.filter(ImageFilter.GaussianBlur(radius=blend_ratio / 4)) + blend.paste(crop_img, paste_region) + blend.putalpha(mask) + img = Image.alpha_composite(img.convert('RGBA'), blend) + out_images.append(img.convert('RGB')) + return (pil2tensor(out_images),) +``` \ No newline at end of file diff --git a/docs/BatchValueSchedule.md b/docs/BatchValueSchedule.md new file mode 100644 index 0000000..0c23339 --- /dev/null +++ b/docs/BatchValueSchedule.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: BatchValueSchedule +- Category: FizzNodes 📅🅕🅝/BatchScheduleNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +BatchValueSchedule节点旨在管理和插值指定帧范围内的关键帧值。它处理表示关键帧的文本输入,并为每个帧插值,直到达到最大帧数,提供指定值之间的平滑过渡。这个节点特别适用于创建动态序列,其中每个帧的确切值不是预先确定的,而是基于给定的关键帧进行计算。 + +# Input types +## Required +- text + - text参数是一个定义动画关键帧的字符串。它至关重要,因为它直接影响将在帧序列中进行插值的值。格式应该正确结构化,以确保准确的插值。 + - Comfy dtype: STRING + - Python dtype: str +- max_frames + - max_frames参数指定要考虑插值的帧数的上限。它是一个重要的参数,因为它决定了关键帧值分布的范围。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- print_output + - print_output参数是一个可选的布尔值,设置为True时,将打印插值结果到控制台。这对于调试很有帮助,可以验证插值的输出。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- interpolated_values + - interpolated_values输出提供了基于关键帧和插值方法计算的每个帧的值。这个输出很重要,因为它代表了节点生成的最终值序列。 + - Comfy dtype: FLOAT + - Python dtype: List[float] +- frame_numbers + - frame_numbers输出是与插值值相对应的帧号列表。它对于将生成的值映射回各自的帧以进行进一步处理或分析很有用。 + - Comfy dtype: INT + - Python dtype: List[int] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchValueSchedule: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True, 'default': defaultValue}), 'max_frames': ('INT', {'default': 120.0, 'min': 1.0, 'max': 999999.0, 'step': 1.0}), 'print_output': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('FLOAT', 'INT') + FUNCTION = 'animate' + CATEGORY = 'FizzNodes 📅🅕🅝/BatchScheduleNodes' + + def animate(self, text, max_frames, print_output): + t = batch_get_inbetweens(batch_parse_key_frames(text, max_frames), max_frames) + if print_output is True: + print('ValueSchedule: ', t) + return (t, list(map(int, t))) +``` \ No newline at end of file diff --git a/docs/BatchValueScheduleLatentInput.md b/docs/BatchValueScheduleLatentInput.md new file mode 100644 index 0000000..538c932 --- /dev/null +++ b/docs/BatchValueScheduleLatentInput.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: BatchValueScheduleLatentInput +- Category: FizzNodes 📅🅕🅝/BatchScheduleNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +BatchValueScheduleLatentInput节点旨在根据给定的文本时间表处理和动画一批潜在输入。它解释文本以生成关键帧,并相应地插值这些值,提供关键帧之间的平稳过渡。这个节点特别适用于创建动画或转换,其中需要潜在变量的平滑进展。 + +# Input types +## Required +- text + - 参数'text'定义了潜在输入动画的时间表。它是一个字符串,指定关键帧及其相应的值,用于生成动画序列。此参数至关重要,因为它决定了动画的模式以及潜在输入在过程中将采用的值。 + - Comfy dtype: STRING + - Python dtype: str +- num_latents + - 参数'num_latents'是一个包含要动画化的潜在变量的字典。字典中的每个键对应不同的潜在变量,值是表示这些变量初始状态的张量。此参数至关重要,因为它为动画提供了起点,并定义了随时间将被操作的变量。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +## Optional +- print_output + - 参数'print_output'是一个布尔标志,设置为True时,会将生成的关键帧及其插值结果打印到控制台。这对于调试或在进一步处理之前可视化动画序列非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- t + - 输出't'表示从输入文本时间表生成的插值关键帧。它是一系列浮点数,指示动画随时间的进展。 + - Comfy dtype: FLOAT + - Python dtype: pandas.Series +- list(map(int, t)) + - 此输出是从插值关键帧派生的整数列表。它提供了动画序列的离散化版本,对于需要整数值而不是浮点数的应用非常有用。 + - Comfy dtype: INT + - Python dtype: List[int] +- num_latents + - 输出'num_latents'是根据输入时间表动画化的潜在变量字典。它包含动画过程后潜在变量的更新状态。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchValueScheduleLatentInput: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True, 'default': defaultValue}), 'num_latents': ('LATENT',), 'print_output': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('FLOAT', 'INT', 'LATENT') + FUNCTION = 'animate' + CATEGORY = 'FizzNodes 📅🅕🅝/BatchScheduleNodes' + + def animate(self, text, num_latents, print_output): + num_elements = sum((tensor.size(0) for tensor in num_latents.values())) + max_frames = num_elements + t = batch_get_inbetweens(batch_parse_key_frames(text, max_frames), max_frames) + if print_output is True: + print('ValueSchedule: ', t) + return (t, list(map(int, t)), num_latents) +``` \ No newline at end of file diff --git a/docs/Bbox (mtb).md b/docs/Bbox (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Bbox From Mask (mtb).md b/docs/Bbox From Mask (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/BboxDetectorCombined_v2.md b/docs/BboxDetectorCombined_v2.md new file mode 100644 index 0000000..4ed016e --- /dev/null +++ b/docs/BboxDetectorCombined_v2.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: BboxDetectorCombined +- Category: Detection +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +BboxDetectorCombined节点旨在使用预训练的边界框检测器检测并分割图像中的对象。它处理输入图像以识别兴趣区域并生成一个掩码,该掩码描绘了这些区域。此节点对于需要精确对象定位和分割的应用至关重要,例如在监控、机器人技术和自主系统中。 + +# Input types +## Required +- bbox_detector + - bbox_detector参数对于节点的操作至关重要,因为它提供了用于检测图像中对象的预训练模型。它是一个关键组件,使节点能够准确识别和定位对象。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: torch.nn.Module +- image + - image参数是节点处理以检测和分割对象的输入。它是节点功能的基础,节点的性能在很大程度上依赖于输入图像的质量和分辨率。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- threshold + - threshold参数用于设置对象检测的置信度水平。它在过滤假阳性和确保只有置信度高于某个水平的对象被检测中起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- dilation + - dilation参数应用于检测到的对象掩码,以扩展它们的边界。这对于细化分割很有用,确保掩码包含整个对象,即使对象的边缘没有被完美检测到。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- mask + - mask输出是表示输入图像中检测到的对象分割的二进制图像。它是节点操作的重要结果,为进一步分析或处理提供了对象的清晰划分。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class BboxDetectorCombined(SegmDetectorCombined): + + @classmethod + def INPUT_TYPES(s): + return {'required': {'bbox_detector': ('BBOX_DETECTOR',), 'image': ('IMAGE',), 'threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'dilation': ('INT', {'default': 4, 'min': -512, 'max': 512, 'step': 1})}} + + def doit(self, bbox_detector, image, threshold, dilation): + mask = bbox_detector.detect_combined(image, threshold, dilation) + if mask is None: + mask = torch.zeros((image.shape[2], image.shape[1]), dtype=torch.float32, device='cpu') + return (mask.unsqueeze(0),) +``` \ No newline at end of file diff --git a/docs/BboxDetectorSEGS.md b/docs/BboxDetectorSEGS.md new file mode 100644 index 0000000..ab9aa32 --- /dev/null +++ b/docs/BboxDetectorSEGS.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: BboxDetectorForEach +- Category: ImpactPack/Detector +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +BboxDetectorForEach节点旨在使用指定的检测器为图像中的每个段检测边界框。它使用给定的阈值处理图像,并应用膨胀来细化检测。该节点还允许通过诸如裁剪因子和下降尺寸之类的参数进行定制,使用户可以根据其特定需求调整检测。它通过识别和隔离图像中的感兴趣区域,为整体分割过程做出贡献。 + +# Input types +## Required +- bbox_detector + - bbox_detector参数对于BboxDetectorForEach节点至关重要,因为它定义了将用于识别图像内边界框的检测器。它在节点的执行和检测结果的准确性中起着关键作用。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: torch.nn.Module +- image + - 图像参数是BboxDetectorForEach节点的基本输入,代表将被处理以进行边界框检测的视觉数据。它是节点操作的主要信息源,直接影响检测结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- threshold + - 阈值参数对于控制边界框检测的灵敏度至关重要。它决定了检测器识别潜在段的水平,影响节点区分图像中相关和不相关区域的能力。 + - Comfy dtype: FLOAT + - Python dtype: float +- dilation + - 膨胀参数对于通过扩展边界来细化检测到的边界框很重要。它允许对检测到的段的大小和形状进行调整,当处理不同分辨率的图像或需要更高级别的细节时特别有用。 + - Comfy dtype: INT + - Python dtype: int +- crop_factor + - 裁剪因子参数影响图像中用于检测的部分。它可以用于专注于图像中的特定感兴趣区域或排除不相关区域,从而提高检测过程的效率和准确性。 + - Comfy dtype: FLOAT + - Python dtype: float +- drop_size + - drop_size参数决定了在检测过程中被丢弃的段的大小。它是控制检测粒度的关键因素,允许在检测到的段的数量和所需的计算资源之间取得平衡。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- labels + - labels参数允许用户指定他们感兴趣的段类型。它通过过滤不需要的段来实现选择性检测,可以简化后续处理步骤,专注于图像中最重要的部分。 + - Comfy dtype: STRING + - Python dtype: str +- detailer_hook + - detailer_hook参数提供了一种使用附加细节或后处理步骤定制检测过程的机制。它对于将节点与其他系统集成或将特定领域的逻辑应用于检测结果特别有用。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: Callable + +# Output types +- segs + - segs输出代表图像中检测到的段的集合。它是BboxDetectorForEach节点操作的主要果,包含每个段的边界框和相关元数据。 + - Comfy dtype: SEGS + - Python dtype: List[impact.core.SEG] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BboxDetectorForEach: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'bbox_detector': ('BBOX_DETECTOR',), 'image': ('IMAGE',), 'threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'dilation': ('INT', {'default': 10, 'min': -512, 'max': 512, 'step': 1}), 'crop_factor': ('FLOAT', {'default': 3.0, 'min': 1.0, 'max': 100, 'step': 0.1}), 'drop_size': ('INT', {'min': 1, 'max': MAX_RESOLUTION, 'step': 1, 'default': 10}), 'labels': ('STRING', {'multiline': True, 'default': 'all', 'placeholder': 'List the types of segments to be allowed, separated by commas'})}, 'optional': {'detailer_hook': ('DETAILER_HOOK',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detector' + + def doit(self, bbox_detector, image, threshold, dilation, crop_factor, drop_size, labels=None, detailer_hook=None): + if len(image) > 1: + raise Exception('[Impact Pack] ERROR: BboxDetectorForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.') + segs = bbox_detector.detect(image, threshold, dilation, crop_factor, drop_size, detailer_hook) + if labels is not None and labels != '': + labels = labels.split(',') + if len(labels) > 0: + (segs, _) = segs_nodes.SEGSLabelFilter.filter(segs, labels) + return (segs,) +``` \ No newline at end of file diff --git a/docs/BindImageListPromptList %2F%2FInspire.md b/docs/BindImageListPromptList %2F%2FInspire.md new file mode 100644 index 0000000..3bbcca4 --- /dev/null +++ b/docs/BindImageListPromptList %2F%2FInspire.md @@ -0,0 +1,81 @@ +# Documentation +- Class name: BindImageListPromptList +- Category: InspirePack/Prompt +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在处理和组织图像数据及其对应的文本提示,确保每张图像都与正面和负面的文本响应相关联。它通过调整提示以匹配图像数量来管理输入数据长度的差异,从而为图像-文本配对任务提供流畅的工作流程。 + +# Input types +## Required +- images + - 图像参数是节点操作的基础,非常关键。它是一组将与文本提示配对的图像数据,影响节点的执行和输出质量。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image.Image] +- zipped_prompts + - 该参数保存了一个元组列表,每个元组包含一对正面和负面的文本提示。这对节点的功能至关重要,因为它直接影响每张图像产生的文本关联。 + - Comfy dtype: ZIPPED_PROMPT + - Python dtype: List[Tuple[str, str, str]] +- default_positive + - 默认正面文本用于填充图像多于提示的情况。它确保每张图像都有一个对应的正面提示,保持节点输出的一致性。 + - Comfy dtype: STRING + - Python dtype: List[str] +- default_negative + - 与默认正面文本类似,此参数为没有对应提示的图像提供默认负面文本。它有助于节点生成完整的图像-文本对。 + - Comfy dtype: STRING + - Python dtype: List[str] + +# Output types +- image + - 输出图像是节点处理的直接结果,保留了原始图像数据,但现在与相关的文本提示配对。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image.Image] +- positive + - 此输出包含与每张图像相关的正面文本提示,可用于进一步分析或作为更大的图像-文本数据集的一部分。 + - Comfy dtype: STRING + - Python dtype: List[str] +- negative + - 负面文本提示与正面的一起输出,为每张图像提供对比,并增强了图像-文本配对的全面性。 + - Comfy dtype: STRING + - Python dtype: List[str] +- prompt_label + - 这个输出标签指示与每张图像相关的提示类型,无论是默认的还是特别提供的,有助于图像-文本对的组织和分类。 + - Comfy dtype: STRING + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BindImageListPromptList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'zipped_prompts': ('ZIPPED_PROMPT',), 'default_positive': ('STRING', {'multiline': True, 'placeholder': 'default positive'}), 'default_negative': ('STRING', {'multiline': True, 'placeholder': 'default negative'})}} + INPUT_IS_LIST = True + RETURN_TYPES = ('IMAGE', 'STRING', 'STRING', 'STRING') + RETURN_NAMES = ('image', 'positive', 'negative', 'prompt_label') + OUTPUT_IS_LIST = (True, True, True) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Prompt' + + def doit(self, images, zipped_prompts, default_positive, default_negative): + positives = [] + negatives = [] + prompt_labels = [] + if len(images) < len(zipped_prompts): + zipped_prompts = zipped_prompts[:len(images)] + elif len(images) > len(zipped_prompts): + lack = len(images) - len(zipped_prompts) + default_prompt = (default_positive[0], default_negative[0], 'default') + zipped_prompts = zipped_prompts[:] + for i in range(lack): + zipped_prompts.append(default_prompt) + for prompt in zipped_prompts: + (a, b, c) = prompt + positives.append(a) + negatives.append(b) + prompt_labels.append(c) + return (images, positives, negatives, prompt_labels) +``` \ No newline at end of file diff --git a/docs/BitwiseAndMask.md b/docs/BitwiseAndMask.md new file mode 100644 index 0000000..d8a8a7c --- /dev/null +++ b/docs/BitwiseAndMask.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: BitwiseAndMask +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +BitwiseAndMask节点的'doit'方法旨在对两个输入掩码执行按位与操作。它对于需要组合掩码层的应用至关重要,例如在图像分割或数据过滤过程中。此方法确保在输出中仅保留两个掩码的共同元素,有助于获得更精细和精确的结果。 + +# Input types +## Required +- mask1 + - 参数'mask1'是按位与操作的第一个输入掩码。它通过贡献其结构和内容,在确定最终掩码中起着关键作用。节点的执行直接受到'mask1'属性的影响,它必须与'mask2'在形状上对齐才能进行有效的按位操作。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- mask2 + - 参数'mask2'是与'mask1'一起用于按位与操作的第二个输入掩码。它的重要性等同于'mask1',因为它也定义了结果掩码中将出现的共同区域。节点的功能依赖于'mask1'和'mask2'之间的形状兼容性。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- mask + - 'mask'输出是'mask1'和'mask2'之间按位与操作的结果。它表示两个输入掩码中都存在的共同区域,对于需要单一组合掩码表示的进一步处理或分析至关重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BitwiseAndMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask1': ('MASK',), 'mask2': ('MASK',)}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, mask1, mask2): + mask = bitwise_and_masks(mask1, mask2) + return (mask,) +``` \ No newline at end of file diff --git a/docs/BitwiseAndMaskForEach.md b/docs/BitwiseAndMaskForEach.md new file mode 100644 index 0000000..2f9ffc9 --- /dev/null +++ b/docs/BitwiseAndMaskForEach.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: BitwiseAndMaskForEach +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +BitwiseAndMaskForEach节点的'doit'方法对段进行位运算,使用掩码确定重叠区域。它处理每个基础段与一组掩码段,识别重叠区域,并对非重叠区域应用掩码以消除它们。此方法对于细化分割结果至关重要,确保只保留真正重叠的区域。 + +# Input types +## Required +- base_segs + - 'base_segs'参数是一系列将由节点处理的分割对象集合。它至关重要,因为它构成了与掩码段进行位运算的基础。该参数直接影响节点执行的结果,决定了哪些段被考虑用于重叠检测。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +- mask_segs + - 'mask_segs'参数由作为位运算掩码的分割对象组成。它至关重要,因为它定义了操作后要保留的区域。该参数在塑造节点的最终输出方面起着重要作用,通过指定要考虑重叠并应在操作后保留的区域。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] + +# Output types +- result + - 'result'输出是经过位运算处理的分割对象列表。它只包含基础段和掩码段之间有重叠的段。这个输出很重要,因为它代表了操作后细化的分割数据。 + - Comfy dtype: SEGS + - Python dtype: Tuple[str, List[SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BitwiseAndMaskForEach: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_segs': ('SEGS',), 'mask_segs': ('SEGS',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, base_segs, mask_segs): + result = [] + for bseg in base_segs[1]: + cropped_mask1 = bseg.cropped_mask.copy() + crop_region1 = bseg.crop_region + for mseg in mask_segs[1]: + cropped_mask2 = mseg.cropped_mask + crop_region2 = mseg.crop_region + intersect_region = (max(crop_region1[0], crop_region2[0]), max(crop_region1[1], crop_region2[1]), min(crop_region1[2], crop_region2[2]), min(crop_region1[3], crop_region2[3])) + overlapped = False + for i in range(intersect_region[0], intersect_region[2]): + for j in range(intersect_region[1], intersect_region[3]): + if cropped_mask1[j - crop_region1[1], i - crop_region1[0]] == 1 and cropped_mask2[j - crop_region2[1], i - crop_region2[0]] == 1: + overlapped = True + pass + else: + cropped_mask1[j - crop_region1[1], i - crop_region1[0]] = 0 + if overlapped: + item = SEG(bseg.cropped_image, cropped_mask1, bseg.confidence, bseg.crop_region, bseg.bbox, bseg.label, None) + result.append(item) + return ((base_segs[0], result),) +``` \ No newline at end of file diff --git a/docs/Blend Latents.md b/docs/Blend Latents.md new file mode 100644 index 0000000..01fbce7 --- /dev/null +++ b/docs/Blend Latents.md @@ -0,0 +1,129 @@ +# Documentation +- Class name: WAS_Blend_Latents +- Category: WAS Suite/Latent +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Blend_Latents 类的 `latent_blend` 方法旨在使用多种混合操作来组合两个潜在表示。此方法对于从单独的潜在输入生成复合输出至关重要,它可以在图像合成和风格迁移等不同应用中非常有用。它强调了节点在创建两个潜在空间的无缝混合中的作用,突出了其灵活性和适应不同混合模式的能力。 + +# Input types +## Required +- latent_a + - 参数 `latent_a` 表示要混合的第一个潜在向量。它在混合过程中起着关键作用,因为它构成了复合潜在输出的基础。这个参数的重要性在于它对混合的初始状态的贡献,这对最终结果有显著影响。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- latent_b + - 参数 `latent_b` 是要与 `latent_a` 混合的第二个潜在向量。它在混合过程中同样重要,因为它为最终混合的潜在表示引入了变化和额外的特征。`latent_a` 和 `latent_b` 之间的相互作用最终决定了混合的结果。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- operation + - 参数 `operation` 确定在组合 `latent_a` 和 `latent_b` 时应用的混合模式。它是节点功能的关键方面,因为它决定了两个潜在向量如何相互作用。操作的选择可以极大地改变混合输出的性质,使这个参数在节点的整体执行中具有很高的影响力。 + - Comfy dtype: COMBO['add', 'multiply', 'divide', 'subtract', 'overlay', 'hard_light', 'soft_light', 'screen', 'linear_dodge', 'difference', 'exclusion', 'random'] + - Python dtype: str +## Optional +- blend + - 参数 `blend` 控制两个潜在向量之间的混合程度。它是一个可选参数,允许微调 `latent_a` 和 `latent_b` 之间的平衡。`blend` 参数很重要,因为它提供了调整混合强度的手段,对最终输出提供了一定程度的控制。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- samples + - 输出参数 `samples` 表示应用所选混合操作后得到的混合潜在表示。它包含了输入潜在向量的组合特征,提供了一个单一的输出,反映了两个输入的本质。这个输出很重要,因为它是节点混合过程的顶点,用于进一步的处理或分析。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Blend_Latents: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'latent_a': ('LATENT',), 'latent_b': ('LATENT',), 'operation': (['add', 'multiply', 'divide', 'subtract', 'overlay', 'hard_light', 'soft_light', 'screen', 'linear_dodge', 'difference', 'exclusion', 'random'],), 'blend': ('FLOAT', {'default': 0.5, 'min': 0.01, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'latent_blend' + CATEGORY = 'WAS Suite/Latent' + + def latent_blend(self, latent_a, latent_b, operation, blend): + return ({'samples': self.blend_latents(latent_a['samples'], latent_b['samples'], operation, blend)},) + + def blend_latents(self, latent1, latent2, mode='add', blend_percentage=0.5): + + def overlay_blend(latent1, latent2, blend_factor): + low = 2 * latent1 * latent2 + high = 1 - 2 * (1 - latent1) * (1 - latent2) + blended_latent = latent1 * blend_factor * low + latent2 * blend_factor * high + return blended_latent + + def screen_blend(latent1, latent2, blend_factor): + inverted_latent1 = 1 - latent1 + inverted_latent2 = 1 - latent2 + blended_latent = 1 - inverted_latent1 * inverted_latent2 * (1 - blend_factor) + return blended_latent + + def difference_blend(latent1, latent2, blend_factor): + blended_latent = abs(latent1 - latent2) * blend_factor + return blended_latent + + def exclusion_blend(latent1, latent2, blend_factor): + blended_latent = (latent1 + latent2 - 2 * latent1 * latent2) * blend_factor + return blended_latent + + def hard_light_blend(latent1, latent2, blend_factor): + blended_latent = torch.where(latent2 < 0.5, 2 * latent1 * latent2, 1 - 2 * (1 - latent1) * (1 - latent2)) * blend_factor + return blended_latent + + def linear_dodge_blend(latent1, latent2, blend_factor): + blended_latent = torch.clamp(latent1 + latent2, 0, 1) * blend_factor + return blended_latent + + def soft_light_blend(latent1, latent2, blend_factor): + low = 2 * latent1 * latent2 + latent1 ** 2 - 2 * latent1 * latent2 * latent1 + high = 2 * latent1 * (1 - latent2) + torch.sqrt(latent1) * (2 * latent2 - 1) + blended_latent = latent1 * blend_factor * low + latent2 * blend_factor * high + return blended_latent + + def random_noise(latent1, latent2, blend_factor): + noise1 = torch.randn_like(latent1) + noise2 = torch.randn_like(latent2) + noise1 = (noise1 - noise1.min()) / (noise1.max() - noise1.min()) + noise2 = (noise2 - noise2.min()) / (noise2.max() - noise2.min()) + blended_noise = latent1 * blend_factor * noise1 + latent2 * blend_factor * noise2 + blended_noise = torch.clamp(blended_noise, 0, 1) + return blended_noise + blend_factor1 = blend_percentage + blend_factor2 = 1 - blend_percentage + if mode == 'add': + blended_latent = latent1 * blend_factor1 + latent2 * blend_factor2 + elif mode == 'multiply': + blended_latent = latent1 * blend_factor1 * (latent2 * blend_factor2) + elif mode == 'divide': + blended_latent = latent1 * blend_factor1 / (latent2 * blend_factor2) + elif mode == 'subtract': + blended_latent = latent1 * blend_factor1 - latent2 * blend_factor2 + elif mode == 'overlay': + blended_latent = overlay_blend(latent1, latent2, blend_factor1) + elif mode == 'screen': + blended_latent = screen_blend(latent1, latent2, blend_factor1) + elif mode == 'difference': + blended_latent = difference_blend(latent1, latent2, blend_factor1) + elif mode == 'exclusion': + blended_latent = exclusion_blend(latent1, latent2, blend_factor1) + elif mode == 'hard_light': + blended_latent = hard_light_blend(latent1, latent2, blend_factor1) + elif mode == 'linear_dodge': + blended_latent = linear_dodge_blend(latent1, latent2, blend_factor1) + elif mode == 'soft_light': + blended_latent = soft_light_blend(latent1, latent2, blend_factor1) + elif mode == 'random': + blended_latent = random_noise(latent1, latent2, blend_factor1) + else: + raise ValueError("Unsupported blending mode. Please choose from 'add', 'multiply', 'divide', 'subtract', 'overlay', 'screen', 'difference', 'exclusion', 'hard_light', 'linear_dodge', 'soft_light', 'custom_noise'.") + blended_latent = self.normalize(blended_latent) + return blended_latent + + def normalize(self, latent): + return (latent - latent.min()) / (latent.max() - latent.min()) +``` \ No newline at end of file diff --git a/docs/Blend.md b/docs/Blend.md new file mode 100644 index 0000000..22053cf --- /dev/null +++ b/docs/Blend.md @@ -0,0 +1,93 @@ +# Documentation +- Class name: Blend +- Category: postprocessing/Blends +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +Blend节点使用不同的混合模式将两张图片结合起来,根据指定的因子调整最终输出,以创建复合视觉效果。 + +# Input types +## Required +- image1 + - 主要图像作为混合操作的基础层,显著影响合成图像的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image2 + - 次要图像是与基础图像交互的覆盖层,影响混合后的最终视觉效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- blend_factor + - 该参数控制覆盖图像在最终混合中的影响,较高的值使覆盖图像更为主导。 + - Comfy dtype: FLOAT + - Python dtype: float +- blend_mode + - 确定用于组合图像的混合模式,改变基础层和覆盖层之间的交互,以实现不同的视觉效果。 + - Comfy dtype: COMBO['normal', 'multiply', 'screen', 'overlay', 'soft_light'] + - Python dtype: str + +# Output types +- blended_image + - 混合过程后的生成图像,代表根据指定参数输入图像的和谐融合。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class Blend: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image1': ('IMAGE',), 'image2': ('IMAGE',), 'blend_factor': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'blend_mode': (['normal', 'multiply', 'screen', 'overlay', 'soft_light'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'blend_images' + CATEGORY = 'postprocessing/Blends' + + def blend_images(self, image1: torch.Tensor, image2: torch.Tensor, blend_factor: float, blend_mode: str): + if image1.shape != image2.shape: + image2 = self.crop_and_resize(image2, image1.shape) + blended_image = self.blend_mode(image1, image2, blend_mode) + blended_image = image1 * (1 - blend_factor) + blended_image * blend_factor + blended_image = torch.clamp(blended_image, 0, 1) + return (blended_image,) + + def blend_mode(self, img1, img2, mode): + if mode == 'normal': + return img2 + elif mode == 'multiply': + return img1 * img2 + elif mode == 'screen': + return 1 - (1 - img1) * (1 - img2) + elif mode == 'overlay': + return torch.where(img1 <= 0.5, 2 * img1 * img2, 1 - 2 * (1 - img1) * (1 - img2)) + elif mode == 'soft_light': + return torch.where(img2 <= 0.5, img1 - (1 - 2 * img2) * img1 * (1 - img1), img1 + (2 * img2 - 1) * (self.g(img1) - img1)) + else: + raise ValueError(f'Unsupported blend mode: {mode}') + + def g(self, x): + return torch.where(x <= 0.25, ((16 * x - 12) * x + 4) * x, torch.sqrt(x)) + + def crop_and_resize(self, img: torch.Tensor, target_shape: tuple): + (batch_size, img_h, img_w, img_c) = img.shape + (_, target_h, target_w, _) = target_shape + img_aspect_ratio = img_w / img_h + target_aspect_ratio = target_w / target_h + if img_aspect_ratio > target_aspect_ratio: + new_width = int(img_h * target_aspect_ratio) + left = (img_w - new_width) // 2 + img = img[:, :, left:left + new_width, :] + else: + new_height = int(img_w / target_aspect_ratio) + top = (img_h - new_height) // 2 + img = img[:, top:top + new_height, :, :] + img = img.permute(0, 3, 1, 2) + img = F.interpolate(img, size=(target_h, target_w), mode='bilinear', align_corners=False) + img = img.permute(0, 2, 3, 1) + return img +``` \ No newline at end of file diff --git a/docs/Blur (mtb).md b/docs/Blur (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Blur(EllangoK%2FComfyUI-post-processing-nodes).md b/docs/Blur(EllangoK%2FComfyUI-post-processing-nodes).md new file mode 100644 index 0000000..10f0a6f --- /dev/null +++ b/docs/Blur(EllangoK%2FComfyUI-post-processing-nodes).md @@ -0,0 +1,57 @@ +# Documentation +- Class name: Blur +- Category: postprocessing/Filters +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +模糊节点对图像应用高斯模糊,有效地减少噪声并平滑边缘,这在图像分析和增强的后处理步骤中非常有用。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它是模糊操作的主要输入。它决定了将由节点处理的源数据。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- blur_radius + - 模糊半径决定了模糊效果的程度。较大的半径会导致更明显的模糊,这对整体视觉效果可能很重要。 + - Comfy dtype: INT + - Python dtype: int +- sigma + - sigma参数影响高斯核的标准差,直接影响模糊的平滑度。这是实现所需美学效果的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- blurred_image + - 输出是模糊后的图像,这是应用高斯模糊后输入图像的处理结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Blur: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'blur_radius': ('INT', {'default': 1, 'min': 1, 'max': 15, 'step': 1}), 'sigma': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 10.0, 'step': 0.1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'blur' + CATEGORY = 'postprocessing/Filters' + + def blur(self, image: torch.Tensor, blur_radius: int, sigma: float): + if blur_radius == 0: + return (image,) + (batch_size, height, width, channels) = image.shape + kernel_size = blur_radius * 2 + 1 + kernel = gaussian_kernel(kernel_size, sigma).repeat(channels, 1, 1).unsqueeze(1) + image = image.permute(0, 3, 1, 2) + blurred = F.conv2d(image, kernel, padding=kernel_size // 2, groups=channels) + blurred = blurred.permute(0, 2, 3, 1) + return (blurred,) +``` \ No newline at end of file diff --git a/docs/Blur.md b/docs/Blur.md new file mode 100644 index 0000000..ce5f546 --- /dev/null +++ b/docs/Blur.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: BlurNode +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +BlurNode 类旨在对图像应用高斯模糊效果,模拟摄影和图像处理中常用的柔焦效果。它利用高斯核的概念来平滑图像,减少细节的可见性,创造出更美观的视觉效果。 + +# Input types +## Required +- image + - 图像参数是节点将处理的输入图像。它至关重要,因为它是节点操作以实现模糊效果的主要数据。图像的质量和内容显著影响节点的执行和最终结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- radius + - 半径参数定义了模糊效果的范围。它至关重要,因为它直接影响用于模糊的高斯核的大小,从而影响应用于图像的模糊程度。 + - Comfy dtype: INT + - Python dtype: int +- sigma_factor + - sigma_factor 参数调整高斯核的标准差,允许控制模糊的平滑度。它在微调模糊效果以满足特定视觉要求方面起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- blurred_image + - blurred_image 输出参数代表应用了高斯模糊效果的处理后的图像。它是节点操作的结果,并反映了模糊后输入图像修改后的视觉外观。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class BlurNode: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'radius': ('INT', {'default': 10, 'min': 0, 'max': 48, 'step': 1}), 'sigma_factor': ('FLOAT', {'default': 1.0, 'min': 0.01, 'max': 3.0, 'step': 0.01})}} + + def gaussian_blur(self, image, kernel_size, sigma): + kernel = torch.Tensor(kernel_size, kernel_size).to(device=image.device) + center = kernel_size // 2 + variance = sigma ** 2 + for i in range(kernel_size): + for j in range(kernel_size): + x = i - center + y = j - center + kernel[i, j] = math.exp(-(x ** 2 + y ** 2) / (2 * variance)) + kernel /= kernel.sum() + padding = (kernel_size - 1) // 2 + input_pad = torch.nn.functional.pad(image, (padding, padding, padding, padding), mode='reflect') + (batch_size, num_channels, height, width) = image.shape + input_reshaped = input_pad.reshape(batch_size * num_channels, 1, height + padding * 2, width + padding * 2) + output_reshaped = torch.nn.functional.conv2d(input_reshaped, kernel.unsqueeze(0).unsqueeze(0)) + output_tensor = output_reshaped.reshape(batch_size, num_channels, height, width) + return output_tensor + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'blur' + CATEGORY = 'Masquerade Nodes' + + def blur(self, image, radius, sigma_factor): + if len(image.size()) == 3: + image = image.unsqueeze(3) + image = image.permute(0, 3, 1, 2) + kernel_size = radius * 2 + 1 + sigma = sigma_factor * (0.6 * radius - 0.3) + result = self.gaussian_blur(image, kernel_size, sigma).permute(0, 2, 3, 1) + if result.size()[3] == 1: + result = result[:, :, :, 0] + return (result,) +``` \ No newline at end of file diff --git a/docs/Boolean To Text.md b/docs/Boolean To Text.md new file mode 100644 index 0000000..2921cf4 --- /dev/null +++ b/docs/Boolean To Text.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: WAS_Boolean_To_Text +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Boolean_To_Text节点旨在将布尔值转换为'True'或'False'的文本表示。它作为一个简单而有效的桥梁,将布尔逻辑与文本输出相连接,促进了布尔运算与基于文本的系统或流程的整合。 + +# Input types +## Required +- boolean + - 参数'boolean'对节点的操作至关重要,因为它是决定节点输出的输入。它直接影响节点的执行,通过指示返回文本'True'或'False'来决定。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- text + - 输出参数'text'代表输入布尔值的文本等价物。它很重要,因为它提供了一种清晰直接的方式来将布尔逻辑转换为人类可读的格式。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Boolean_To_Text: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'boolean': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'do' + CATEGORY = 'WAS Suite/Logic' + + def do(self, boolean): + if boolean: + return ('True',) + return ('False',) +``` \ No newline at end of file diff --git a/docs/Bounded Image Blend with Mask.md b/docs/Bounded Image Blend with Mask.md new file mode 100644 index 0000000..6cfcd02 --- /dev/null +++ b/docs/Bounded Image Blend with Mask.md @@ -0,0 +1,97 @@ +# Documentation +- Class name: WAS_Bounded_Image_Blend_With_Mask +- Category: WAS Suite/Image/Bound +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 'bounded_image_blend_with_mask' 旨在使用遮罩控制混合过程,将源图像与目标图像在指定的边界内进行混合。它智能地应用混合因子来确定混合的程度,并可选地,使用羽化效果平滑图像之间的过渡。 + +# Input types +## Required +- target + - 目标图像是源图像将被混合的图像。它作为整个混合操作的基础,对最终输出至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- target_mask + - 定义目标图像中将发生混合的区域的遮罩。它在确定目标图像的哪些部分受源图像影响中起着关键作用。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- target_bounds + - 指定目标图像内混合将发生的边界。它对于将混合效果限制在特定区域至关重要。 + - Comfy dtype: IMAGE_BOUNDS + - Python dtype: Tuple[int, int, int, int] +- source + - 将被混合到目标上的图像。其视觉内容和属性显著影响混合过程的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- blend_factor + - 控制源图像和目标图像之间混合强度的因子。它允许微调混合效果以实现所需的视觉效果。 + - Comfy dtype: FLOAT + - Python dtype: float +- feathering + - 应用于遮罩的羽化量,它平滑混合区域的边缘,以实现更自然的过渡。它提高了混合图像的美学质量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result_image + - 混合过程后的生成图像,反映了在指定的边界和遮罩内源图像和目标图像的组合视觉元素。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Bounded_Image_Blend_With_Mask: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + return {'required': {'target': ('IMAGE',), 'target_mask': ('MASK',), 'target_bounds': ('IMAGE_BOUNDS',), 'source': ('IMAGE',), 'blend_factor': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0}), 'feathering': ('INT', {'default': 16, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'bounded_image_blend_with_mask' + CATEGORY = 'WAS Suite/Image/Bound' + + def bounded_image_blend_with_mask(self, target, target_mask, target_bounds, source, blend_factor, feathering): + target = target.unsqueeze(0) if target.dim() == 3 else target + source = source.unsqueeze(0) if source.dim() == 3 else source + target_mask = target_mask.unsqueeze(0) if target_mask.dim() == 2 else target_mask + tgt_mask_len = 1 if len(target_mask) != len(source) else len(source) + tgt_len = 1 if len(target) != len(source) else len(source) + bounds_len = 1 if len(target_bounds) != len(source) else len(source) + tgt_arr = [tensor2pil(tgt) for tgt in target[:tgt_len]] + src_arr = [tensor2pil(src) for src in source] + tgt_mask_arr = [] + for m_idx in range(tgt_mask_len): + np_array = np.clip(target_mask[m_idx].cpu().numpy().squeeze() * 255.0, 0, 255) + tgt_mask_arr.append(Image.fromarray(np_array.astype(np.uint8), mode='L')) + result_tensors = [] + for idx in range(len(src_arr)): + src = src_arr[idx] + if tgt_len == 1 and idx == 0 or tgt_len > 1: + tgt = tgt_arr[idx] + if bounds_len == 1 and idx == 0 or bounds_len > 1: + (rmin, rmax, cmin, cmax) = target_bounds[idx] + (height, width) = (rmax - rmin + 1, cmax - cmin + 1) + if tgt_mask_len == 1 and idx == 0 or tgt_mask_len > 1: + tgt_mask = tgt_mask_arr[idx] + if tgt_mask_len == 1 and bounds_len == 1 and (idx == 0) or (tgt_mask_len > 1 or bounds_len > 1): + if tgt_mask.size != tgt.size: + mask_extended_canvas = Image.new('L', tgt.size, 0) + mask_extended_canvas.paste(tgt_mask, (cmin, rmin)) + tgt_mask = mask_extended_canvas + if feathering > 0: + tgt_mask = tgt_mask.filter(ImageFilter.GaussianBlur(radius=feathering)) + tgt_mask = tgt_mask.point(lambda p: p * blend_factor) + src_resized = src.resize((width, height), Image.Resampling.LANCZOS) + src_positioned = Image.new(tgt.mode, tgt.size) + src_positioned.paste(src_resized, (cmin, rmin)) + result = Image.composite(src_positioned, tgt, tgt_mask) + result_tensors.append(pil2tensor(result)) + return (torch.cat(result_tensors, dim=0),) +``` \ No newline at end of file diff --git a/docs/Bounded Image Blend.md b/docs/Bounded Image Blend.md new file mode 100644 index 0000000..6d0eec6 --- /dev/null +++ b/docs/Bounded Image Blend.md @@ -0,0 +1,86 @@ +# Documentation +- Class name: WAS_Bounded_Image_Blend +- Category: WAS Suite/Image/Bound +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 `bounded_image_blend` 旨在将源图像无缝地混合到目标图像中,且限定在特定的边界内。通过应用混合因子和可选的羽化效果,它在图像之间创建平滑的过渡,确保了视觉上的连贯性。 + +# Input types +## Required +- target + - 目标图像,源图像将被混合到其中。它作为混合操作的背景,对于确定合成图像的最终外观至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- target_bounds + - 定义目标图像内源图像将被混合的区域的坐标。这些边界对于指定操作的兴趣区域至关重要。 + - Comfy dtype: IMAGE_BOUNDS + - Python dtype: Tuple[int, int, int, int] +- source + - 将被混合到目标上的图像。它是将被合并到目标图像中的主要视觉元素,且在指定的边界内。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- blend_factor + - 一个浮点值,用于确定源图像和目标图像之间的混合程度。它影响源图像在混合区域内的透明度。 + - Comfy dtype: FLOAT + - Python dtype: float +- feathering + - 应用于混合区域边缘的羽化量,以创建平滑过渡。更高的值会导致更渐进的混合。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result_image + - 输出图像,代表在指定边界内源图像和目标图像的混合结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Bounded_Image_Blend: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + return {'required': {'target': ('IMAGE',), 'target_bounds': ('IMAGE_BOUNDS',), 'source': ('IMAGE',), 'blend_factor': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0}), 'feathering': ('INT', {'default': 16, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'bounded_image_blend' + CATEGORY = 'WAS Suite/Image/Bound' + + def bounded_image_blend(self, target, target_bounds, source, blend_factor, feathering): + target = target.unsqueeze(0) if target.dim() == 3 else target + source = source.unsqueeze(0) if source.dim() == 3 else source + tgt_len = 1 if len(target) != len(source) else len(source) + bounds_len = 1 if len(target_bounds) != len(source) else len(source) + tgt_arr = [tensor2pil(tgt) for tgt in target[:tgt_len]] + src_arr = [tensor2pil(src) for src in source] + result_tensors = [] + for idx in range(len(src_arr)): + src = src_arr[idx] + if tgt_len == 1 and idx == 0 or tgt_len > 1: + tgt = tgt_arr[idx] + if bounds_len == 1 and idx == 0 or bounds_len > 1: + (rmin, rmax, cmin, cmax) = target_bounds[idx] + (height, width) = (rmax - rmin + 1, cmax - cmin + 1) + if feathering > 0: + inner_mask = Image.new('L', (width - 2 * feathering, height - 2 * feathering), 255) + inner_mask = ImageOps.expand(inner_mask, border=feathering, fill=0) + inner_mask = inner_mask.filter(ImageFilter.GaussianBlur(radius=feathering)) + else: + inner_mask = Image.new('L', (width, height), 255) + inner_mask = inner_mask.point(lambda p: p * blend_factor) + tgt_mask = Image.new('L', tgt.size, 0) + tgt_mask.paste(inner_mask, (cmin, rmin)) + src_resized = src.resize((width, height), Image.Resampling.LANCZOS) + src_positioned = Image.new(tgt.mode, tgt.size) + src_positioned.paste(src_resized, (cmin, rmin)) + result = Image.composite(src_positioned, tgt, tgt_mask) + result_tensors.append(pil2tensor(result)) + return (torch.cat(result_tensors, dim=0),) +``` \ No newline at end of file diff --git a/docs/Bounded Image Crop with Mask.md b/docs/Bounded Image Crop with Mask.md new file mode 100644 index 0000000..156656f --- /dev/null +++ b/docs/Bounded Image Crop with Mask.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: WAS_Bounded_Image_Crop_With_Mask +- Category: WAS Suite/Image/Bound +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 `bounded_image_crop_with_mask` 旨在根据对应的掩码定义的边界智能裁剪图像。它通过关注掩码所描绘的感兴趣区域来增强图像,同时应用填充以确保裁剪区域保持所需的纵横比或大小。 + +# Input types +## Required +- image + - 将要按照掩码进行裁剪的输入图像。它是操作的主要对象,并决定了裁剪后将保留的内容。 + - Comfy dtype: IMAGE + - Python dtype: Union[torch.Tensor, PIL.Image.Image] +- mask + - 定义图像内感兴趣区域的掩码。它用于识别裁剪操作的边界,对于确定图像的哪些部分是重要的至关重要。 + - Comfy dtype: MASK + - Python dtype: Union[torch.Tensor, PIL.Image.Image] +## Optional +- padding_left + - 要添加到裁剪图像左侧的填充量。此参数是可选的,可以调整以控制裁剪区域的最终宽度。 + - Comfy dtype: INT + - Python dtype: int +- padding_right + - 要添加到裁剪图像右侧的填充量。它与左侧的填充一起工作,以确保裁剪后的图像满足特定的尺寸。 + - Comfy dtype: INT + - Python dtype: int +- padding_top + - 要添加到裁剪图像顶部的填充量。这种填充有助于保持裁剪部分的纵横比或实现所需的高度。 + - Comfy dtype: INT + - Python dtype: int +- padding_bottom + - 要添加到裁剪图像底部的填充量。它确保裁剪后的图像在掩码定义的感兴趣区域下方有足够的空间。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- cropped_image + - 裁剪操作后的图像结果,包括由掩码定义的感兴趣区域和应用的填充。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image_bounds + - 定义原始图像中裁剪区域边界的坐标。 + - Comfy dtype: IMAGE_BOUNDS + - Python dtype: List[Tuple[int, int, int, int]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Bounded_Image_Crop_With_Mask: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + return {'required': {'image': ('IMAGE',), 'mask': ('MASK',), 'padding_left': ('INT', {'default': 64, 'min': 0, 'max': 18446744073709551615}), 'padding_right': ('INT', {'default': 64, 'min': 0, 'max': 18446744073709551615}), 'padding_top': ('INT', {'default': 64, 'min': 0, 'max': 18446744073709551615}), 'padding_bottom': ('INT', {'default': 64, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('IMAGE', 'IMAGE_BOUNDS') + FUNCTION = 'bounded_image_crop_with_mask' + CATEGORY = 'WAS Suite/Image/Bound' + + def bounded_image_crop_with_mask(self, image, mask, padding_left, padding_right, padding_top, padding_bottom): + image = image.unsqueeze(0) if image.dim() == 3 else image + mask = mask.unsqueeze(0) if mask.dim() == 2 else mask + mask_len = 1 if len(image) != len(mask) else len(image) + cropped_images = [] + all_bounds = [] + for i in range(len(image)): + if mask_len == 1 and i == 0 or mask_len > 0: + rows = torch.any(mask[i], dim=1) + cols = torch.any(mask[i], dim=0) + (rmin, rmax) = torch.where(rows)[0][[0, -1]] + (cmin, cmax) = torch.where(cols)[0][[0, -1]] + rmin = max(rmin - padding_top, 0) + rmax = min(rmax + padding_bottom, mask[i].shape[0] - 1) + cmin = max(cmin - padding_left, 0) + cmax = min(cmax + padding_right, mask[i].shape[1] - 1) + all_bounds.append([rmin, rmax, cmin, cmax]) + cropped_images.append(image[i][rmin:rmax + 1, cmin:cmax + 1, :]) + return (torch.stack(cropped_images), all_bounds) +``` \ No newline at end of file diff --git a/docs/Bounded Image Crop.md b/docs/Bounded Image Crop.md new file mode 100644 index 0000000..35e39c1 --- /dev/null +++ b/docs/Bounded Image Crop.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: WAS_Bounded_Image_Crop +- Category: WAS Suite/Image/Bound +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +函数 `bounded_image_crop` 旨在根据指定的边界智能裁剪图像,确保裁剪区域在图像的有效尺寸内。它在图像预处理中扮演着关键角色,通过专注于兴趣区域而不扭曲整个图像结构。 + +# Input types +## Required +- image + - 参数 'image' 是节点的核心输入,代表将要被裁剪的图像数据。它对节点的执行至关重要,因为它决定了将要处理的内容。图像的尺寸和质量直接影响裁剪操作的结果。 + - Comfy dtype: IMAGE + - Python dtype: Union[torch.Tensor, PIL.Image.Image] +- image_bounds + - 参数 'image_bounds' 定义了图像中将要被裁剪的区域。它对于指定裁剪操作的确切坐标至关重要。这些边界的正确性非常关键,因为它们决定了裁剪后图像的最终外观。 + - Comfy dtype: IMAGE_BOUNDS + - Python dtype: List[Tuple[int, int, int, int]] + +# Output types +- cropped_image + - 输出参数 'cropped_image' 代表裁剪操作的结果。它很重要,因为它是节点功能的直接输出,包含了输入图像裁剪区域的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Bounded_Image_Crop: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + return {'required': {'image': ('IMAGE',), 'image_bounds': ('IMAGE_BOUNDS',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'bounded_image_crop' + CATEGORY = 'WAS Suite/Image/Bound' + + def bounded_image_crop(self, image, image_bounds): + image = image.unsqueeze(0) if image.dim() == 3 else image + bounds_len = 1 if len(image_bounds) != len(image) else len(image) + cropped_images = [] + for idx in range(len(image)): + if bounds_len == 1 and idx == 0 or bounds_len > 1: + (rmin, rmax, cmin, cmax) = image_bounds[idx] + if rmin > rmax or cmin > cmax: + raise ValueError('Invalid bounds provided. Please make sure the bounds are within the image dimensions.') + cropped_images.append(image[idx][rmin:rmax + 1, cmin:cmax + 1, :]) + return (torch.stack(cropped_images, dim=0),) +``` \ No newline at end of file diff --git a/docs/BrushMotion.md b/docs/BrushMotion.md new file mode 100644 index 0000000..245e5f9 --- /dev/null +++ b/docs/BrushMotion.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: BrushMotion +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +BrushMotion节点通过根据指定的掩码缩放和插值输入的运动数据,实现对视觉内容的动态调整,从而生成运动效果。 + +# Input types +## Required +- model + - 模型参数至关重要,它定义了要生成的运动效果的基础结构和特征。 + - Comfy dtype: DragNUWA + - Python dtype: torchvision.models.video.DragNUWA +- motion_brush + - 运动刷子参数对于提供原始运动数据至关重要,这些数据将根据掩码进行处理和缩放。 + - Comfy dtype: MotionBrush + - Python dtype: torch.Tensor +- brush_mask + - 画笔掩码参数很重要,因为它决定了将要修改的运动效果区域,确保对视觉调整有精确的控制。 + - Comfy dtype: MASK + - Python dtype: numpy.ndarray + +# Output types +- results + - 结果参数包含了最终的运动效果,展示了根据输入掩码和模型规格调整后的运动。 + - Comfy dtype: MotionBrush + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BrushMotion: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('DragNUWA',), 'motion_brush': ('MotionBrush',), 'brush_mask': ('MASK',)}} + RETURN_TYPES = ('MotionBrush',) + FUNCTION = 'run_inference' + CATEGORY = 'DragNUWA' + + def run_inference(self, model, motion_brush, brush_mask): + from torchvision.ops import masks_to_boxes + boxes = masks_to_boxes(brush_mask) + box = boxes[0].int().tolist() + print(box) + xratio = (box[2] - box[0]) / motion_brush.shape[2] + yratio = (box[3] - box[1]) / motion_brush.shape[1] + xmotionbrush = motion_brush[:, :, :, :1] + ymotionbrush = motion_brush[:, :, :, 1:] + xmotionbrush = xmotionbrush * xratio + ymotionbrush = ymotionbrush * yratio + motionbrush = torch.cat([xmotionbrush, ymotionbrush], 3) + results = torch.zeros(model.model_length - 1, model.height, model.width, 2) + for i in range(model.model_length - 1): + temp = F.interpolate(motionbrush[i].unsqueeze(0).permute(0, 3, 1, 2).float(), size=(box[3] - box[1], box[2] - box[0]), mode='bilinear', align_corners=True).squeeze().permute(1, 2, 0) + for x in range(box[0], box[2]): + for y in range(box[1], box[3]): + if brush_mask[0][y][x]: + results[i][y][x][0] = temp[y - box[1]][x - box[0]][0] + results[i][y][x][1] = temp[y - box[1]][x - box[0]][1] + return (results,) +``` \ No newline at end of file diff --git a/docs/Build Filename String (WLSH).md b/docs/Build Filename String (WLSH).md new file mode 100644 index 0000000..381ad8b --- /dev/null +++ b/docs/Build Filename String (WLSH).md @@ -0,0 +1,60 @@ +# Documentation +- Class name: WLSH_Build_Filename_String +- Category: WLSH Nodes/text +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点通过将时间戳、模型名称、种子和计数器合并到可定制的模板中来生成唯一的文件名字符串。它旨在为各种应用创建可识别和有组织的文件名。 + +# Input types +## Required +- filename + - 基础名称,最终文件名基于此构建。它作为插入其他参数的模板。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- modelname + - 模型的名称,用于标识并纳入文件名中。 + - Comfy dtype: STRING + - Python dtype: str +- seed + - 用于增加文件名的多样性和唯一性的数值。 + - Comfy dtype: INT + - Python dtype: int +- counter + - 一个整数,当与相同的基础文件名和参数一起使用时,用于创建一系列文件名。 + - Comfy dtype: SEED + - Python dtype: int +- time_format + - 定义时间戳插入文件名的格式。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- filename + - 最终输出是一个格式化的字符串,代表构建的文件名,包含所有提供的参数。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Build_Filename_String: + + def __init__(s): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'filename': ('STRING', {'%time_%seed': 'info', 'multiline': False})}, 'optional': {'modelname': ('STRING', {'default': '', 'multiline': False}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'counter': ('SEED', {'default': 0}), 'time_format': ('STRING', {'default': '%Y-%m-%d-%H%M%S', 'multiline': False})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('filename',) + FUNCTION = 'build_filename' + CATEGORY = 'WLSH Nodes/text' + + def build_filename(self, filename='ComfyUI', modelname='model', time_format='%Y-%m-%d-%H%M%S', seed=0, counter=0): + filename = make_filename(filename, seed, modelname, counter, time_format) + return filename +``` \ No newline at end of file diff --git a/docs/Bus Node.md b/docs/Bus Node.md new file mode 100644 index 0000000..9afc933 --- /dev/null +++ b/docs/Bus Node.md @@ -0,0 +1,95 @@ +# Documentation +- Class name: WAS_Bus +- Category: WAS Suite/Utilities +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Bus节点作为WAS套件中管理和协调各种组件的中心枢纽。它确保模型、剪辑和其他实用工具在系统的不同部分之间高效传递,促进无缝工作流程。 + +# Input types +## Optional +- bus + - “bus”参数作为一个容器,持有模型、剪辑、vae、正向和负向等可选元素。它对节点的操作至关重要,因为它允许将相关组件捆绑在一起,从而提高系统内部数据传输的效率。 + - Comfy dtype: TUPLE[None, None, None, None, None] + - Python dtype: Tuple[Optional[Any], Optional[Any], Optional[Any], Optional[Any], Optional[Any]] +- model + - “model”参数是节点功能的关键,因为它代表了核心的机器学习组件。它用于处理和分析数据,其存在对于节点成功执行其任务至关重要。 + - Comfy dtype: MODEL + - Python dtype: Optional[torch.nn.Module] +- clip + - “clip”参数非常重要,因为它涉及节点操作的多媒体方面。它对于处理和管理视频或音频剪辑至关重要,这些通常是处理流程的关键部分。 + - Comfy dtype: CLIP + - Python dtype: Optional[Any] +- vae + - “vae”参数对于节点执行高级数据处理任务的能力至关重要。它代表了一种生成模型,对于创建和操作数据表示至关重要。 + - Comfy dtype: VAE + - Python dtype: Optional[Any] +- positive + - “positive”参数在节点的条件处理能力中起着至关重要的作用。它提供了关于期望结果的指导,引导节点的操作朝着实现特定结果的方向前进。 + - Comfy dtype: CONDITIONING + - Python dtype: Optional[Any] +- negative + - “negative”参数是节点过滤掉不需要的元素或结果的能力的关键。它通过指定操作中应避免或排除的内容,有助于完善节点的处理。 + - Comfy dtype: CONDITIONING + - Python dtype: Optional[Any] + +# Output types +- bus + - “bus”输出封装了处理过的组件,提供了一种结构化的方式来访问模型、剪辑、vae和条件元素。它很重要,因为它允许有组织地检索和进一步使用这些组件。 + - Comfy dtype: TUPLE[MODEL, CLIP, VAE, CONDITIONING, CONDITIONING] + - Python dtype: Tuple[torch.nn.Module, Any, Any, Any, Any] +- model + - “model”输出是处理过的机器学习组件,准备用于进一步分析或用于后续任务。它是节点输出的关键元素,因为它携带了从输入数据派生的计算智能。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - “clip”输出代表已经被节点处理或增强的多媒体数据。对于需要音频或视频操作和分析的应用程序来说,它非常重要。 + - Comfy dtype: CLIP + - Python dtype: Any +- vae + - “vae”输出是在节点操作中使用过的生成模型。它对于生成新数据实例或执行数据增强任务很重要。 + - Comfy dtype: VAE + - Python dtype: Any +- positive + - “positive”输出反映了用来引导节点朝向期望结果的指导。对于需要基于特定标准进行条件处理的应用程序来说,它至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- negative + - “negative”输出表示根据节点操作过滤掉或排除的元素。对于涉及移除或避免某些数据点的应用程序来说,它很重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Bus: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'bus': ('BUS',), 'model': ('MODEL',), 'clip': ('CLIP',), 'vae': ('VAE',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',)}} + RETURN_TYPES = ('BUS', 'MODEL', 'CLIP', 'VAE', 'CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('bus', 'model', 'clip', 'vae', 'positive', 'negative') + FUNCTION = 'bus_fn' + CATEGORY = 'WAS Suite/Utilities' + + def bus_fn(self, bus=(None, None, None, None, None), model=None, clip=None, vae=None, positive=None, negative=None): + (bus_model, bus_clip, bus_vae, bus_positive, bus_negative) = bus + out_model = model or bus_model + out_clip = clip or bus_clip + out_vae = vae or bus_vae + out_positive = positive or bus_positive + out_negative = negative or bus_negative + out_bus = (out_model, out_clip, out_vae, out_positive, out_negative) + if not out_model: + raise ValueError('Either model or bus containing a model should be supplied') + if not out_clip: + raise ValueError('Either clip or bus containing a clip should be supplied') + if not out_vae: + raise ValueError('Either vae or bus containing a vae should be supplied') + return (out_bus, out_model, out_clip, out_vae, out_positive, out_negative) +``` \ No newline at end of file diff --git a/docs/CAIN VFI.md b/docs/CAIN VFI.md new file mode 100644 index 0000000..7e5f26e --- /dev/null +++ b/docs/CAIN VFI.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: CAIN_VFI +- Category: ComfyUI-Frame-Interpolation/VFI +- Output node: False +- Repo Ref: https://github.com/Fannovel16/ComfyUI-Frame-Interpolation + +CAIN_VFI节点旨在对一系列图像执行帧插值,增强帧之间过渡的平滑度和连续性。它利用CAIN架构生成原始序列中不存在的中间帧,从而创建更密集、更详细的运动表示。 + +# Input types +## Required +- ckpt_name + - 检查点名称对于加载帧插值所需的预训练模型权重至关重要。它标识了在操作中要使用的特定模型。 + - Comfy dtype: str + - Python dtype: str +- frames + - 输入帧表示将被处理以进行帧插值的图像序列。这个输入是必不可少的,因为它构成了生成新帧的基础。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +## Optional +- clear_cache_after_n_frames + - 此参数确定在处理过程中清除缓存的频率,以管理内存使用情况。它影响节点的性能和内存效率。 + - Comfy dtype: int + - Python dtype: int +- multiplier + - 乘数因子决定了要在每对输入帧之间生成的中间帧的数量。它直接影响输出帧序列的密度。 + - Comfy dtype: int + - Python dtype: int +- optional_interpolation_states + - 这个可选参数提供了对帧插值过程的额外控制,允许定制插值状态。 + - Comfy dtype: InterpolationStateList + - Python dtype: InterpolationStateList + +# Output types +- output_frames + - output_frames参数包含生成的插值帧序列,其中包括原始帧和新创建的中间帧。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CAIN_VFI: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (CKPT_NAMES,), 'frames': ('IMAGE',), 'clear_cache_after_n_frames': ('INT', {'default': 10, 'min': 1, 'max': 1000}), 'multiplier': ('INT', {'default': 2, 'min': 2, 'max': 1000})}, 'optional': {'optional_interpolation_states': ('INTERPOLATION_STATES',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'vfi' + CATEGORY = 'ComfyUI-Frame-Interpolation/VFI' + + def vfi(self, ckpt_name: typing.AnyStr, frames: torch.Tensor, clear_cache_after_n_frames: typing.SupportsInt=1, multiplier: typing.SupportsInt=2, optional_interpolation_states: InterpolationStateList=None, **kwargs): + from .cain_arch import CAIN + model_path = load_file_from_github_release(MODEL_TYPE, ckpt_name) + sd = torch.load(model_path)['state_dict'] + sd = {key.replace('module.', ''): value for (key, value) in sd.items()} + global interpolation_model + interpolation_model = CAIN(depth=3) + interpolation_model.load_state_dict(sd) + interpolation_model.eval().to(get_torch_device()) + del sd + frames = preprocess_frames(frames) + + def return_middle_frame(frame_0, frame_1, timestep, model): + return model(frame_0.detach().clone(), frame_1.detach().clone())[0] + args = [interpolation_model] + out = postprocess_frames(generic_frame_loop(frames, clear_cache_after_n_frames, multiplier, return_middle_frame, *args, interpolation_states=optional_interpolation_states, use_timestep=False, dtype=torch.float32)) + return (out,) +``` \ No newline at end of file diff --git a/docs/CLIP +%2F- w%2FText Unified (WLSH).md b/docs/CLIP +%2F- w%2FText Unified (WLSH).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/CLIP Input Switch.md b/docs/CLIP Input Switch.md new file mode 100644 index 0000000..1d6192d --- /dev/null +++ b/docs/CLIP Input Switch.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: WAS_CLIP_Input_Switch +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 `clip_switch` 设计用于根据一个布尔标志有条件地选择两个提供的 CLIP 对象中的一个。它在工作流中充当逻辑开关,根据布尔值的真实性来指导数据流的方向。 + +# Input types +## Required +- clip_a + - 当布尔参数为 true 时被条件选择的第一个 CLIP 对象。它在节点的决策过程中起着关键作用,根据布尔标志的状态确定输出。 + - Comfy dtype: CLIP + - Python dtype: Union[torch.Tensor, comfy.sd.CLIP] +- clip_b + - 当布尔参数为 false 时被条件选择的第二个 CLIP 对象。它在节点的操作中至关重要,当布尔条件未满足时提供替代输出。 + - Comfy dtype: CLIP + - Python dtype: Union[torch.Tensor, comfy.sd.CLIP] +## Optional +- boolean + - 决定将返回哪个 CLIP 对象的布尔标志。它是一个关键参数,因为它直接影响节点的输出选择逻辑。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- selected_clip + - 节点的输出是一个单一的 CLIP 对象,根据布尔参数的值,可以是 `clip_a` 或 `clip_b`。这个输出很重要,因为它代表了节点条件逻辑的结果。 + - Comfy dtype: CLIP + - Python dtype: Union[torch.Tensor, comfy.sd.CLIP] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_CLIP_Input_Switch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'clip_a': ('CLIP',), 'clip_b': ('CLIP',), 'boolean': ('BOOLEAN', {'forceInput': True})}} + RETURN_TYPES = ('CLIP',) + FUNCTION = 'clip_switch' + CATEGORY = 'WAS Suite/Logic' + + def clip_switch(self, clip_a, clip_b, boolean=True): + if boolean: + return (clip_a,) + else: + return (clip_b,) +``` \ No newline at end of file diff --git a/docs/CLIP Positive-Negative (WLSH).md b/docs/CLIP Positive-Negative (WLSH).md new file mode 100644 index 0000000..ed7ee20 --- /dev/null +++ b/docs/CLIP Positive-Negative (WLSH).md @@ -0,0 +1,51 @@ +# Documentation +- Class name: WLSH_CLIP_Positive_Negative +- Category: WLSH Nodes/conditioning +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点旨在处理文本输入并生成可用于进一步分析或比较的编码表示。它在工作流中扮演关键角色,为基于文本的特征提取提供了基础。 + +# Input types +## Required +- clip + - clip参数对节点的运行至关重要,它提供了编码文本的机制。它是将原始文本转换为结构化格式的核心组件。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- positive_text + - 这个参数是一个与编码过程正面相关的文本输入。它很重要,因为它为编码设置了上下文,影响了最终的表示。 + - Comfy dtype: STRING + - Python dtype: str +- negative_text + - 与positive_text类似,这个参数为编码过程引入了一个负面上下文。它对于创建编码表示中的对比非常关键,这对于某些类型的分析是有益的。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- positive + - 正面输出代表正面文本的编码形式,作为系统内比较或进一步处理的参考。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative + - 负面输出是负面文本的编码表示,与正面输出相比较,可以提供对编码过程差异和细微差别的洞察。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_CLIP_Positive_Negative: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'clip': ('CLIP',), 'positive_text': ('STRING', {'default': f'', 'multiline': True}), 'negative_text': ('STRING', {'default': f'', 'multiline': True})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('positive', 'negative') + FUNCTION = 'encode' + CATEGORY = 'WLSH Nodes/conditioning' + + def encode(self, clip, positive_text, negative_text): + return ([[clip.encode(positive_text), {}]], [[clip.encode(negative_text), {}]]) +``` \ No newline at end of file diff --git a/docs/CLIP Positive-Negative XL (WLSH).md b/docs/CLIP Positive-Negative XL (WLSH).md new file mode 100644 index 0000000..26ced1f --- /dev/null +++ b/docs/CLIP Positive-Negative XL (WLSH).md @@ -0,0 +1,73 @@ +# Documentation +- Class name: WLSH_CLIP_Positive_Negative_XL +- Category: WLSH Nodes/conditioning +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点旨在为对比学习处理和编码正负图像对。它利用CLIP模型提取视觉特征,并将其与文本描述对齐,促进有意义的图像-文本关联的创建。 + +# Input types +## Required +- width + - 宽度是定义输入图像水平分辨率的关键参数。它对于节点正确处理和调整图像尺寸至关重要,确保从正确的维度提取编码特征。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度与宽度类似,是指定输入图像垂直分辨率的重要参数。它与宽度一起工作,以确保准确的图像处理和特征编码。 + - Comfy dtype: INT + - Python dtype: int +- positive_g + - positive_g参数是与正面图像相关联的文本描述。它对于节点在图像内容和文本之间创建语义连接至关重要,这对于编码过程非常重要。 + - Comfy dtype: STRING + - Python dtype: str +- negative_g + - negative_g是负面图像的文本描述。这个参数很重要,因为它为正面图像提供了必要的对比,增强了节点从两个不同的图像-文本对中区分和学习的能力。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- positive + - 正面输出包含正面图像的编码特征和元数据。它是节点输出的关键部分,因为它代表了对比学习过程的一方面。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Dict[str, Union[str, torch.Tensor]]] +- negative + - 负面输出与正面输出相对应,但针对的是负面图像。它同样重要,因为它提供了有效对比学习所必需的对比视角。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Dict[str, Union[str, torch.Tensor]]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WLSH_CLIP_Positive_Negative_XL: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'crop_w': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION}), 'crop_h': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION}), 'target_width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'target_height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'positive_g': ('STRING', {'multiline': True, 'default': 'POS_G'}), 'positive_l': ('STRING', {'multiline': True, 'default': 'POS_L'}), 'negative_g': ('STRING', {'multiline': True, 'default': 'NEG_G'}), 'negative_l': ('STRING', {'multiline': True, 'default': 'NEG_L'}), 'clip': ('CLIP',)}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('positive', 'negative') + FUNCTION = 'encode' + CATEGORY = 'WLSH Nodes/conditioning' + + def encode(self, clip, width, height, crop_w, crop_h, target_width, target_height, positive_g, positive_l, negative_g, negative_l): + tokens = clip.tokenize(positive_g) + tokens['l'] = clip.tokenize(positive_l)['l'] + if len(tokens['l']) != len(tokens['g']): + empty = clip.tokenize('') + while len(tokens['l']) < len(tokens['g']): + tokens['l'] += empty['l'] + while len(tokens['l']) > len(tokens['g']): + tokens['g'] += empty['g'] + (condP, pooledP) = clip.encode_from_tokens(tokens, return_pooled=True) + tokensN = clip.tokenize(negative_g) + tokensN['l'] = clip.tokenize(negative_l)['l'] + if len(tokensN['l']) != len(tokensN['g']): + empty = clip.tokenize('') + while len(tokensN['l']) < len(tokensN['g']): + tokensN['l'] += empty['l'] + while len(tokensN['l']) > len(tokensN['g']): + tokensN['g'] += empty['g'] + (condN, pooledN) = clip.encode_from_tokens(tokensN, return_pooled=True) + return ([[condP, {'pooled_output': pooledP, 'width': width, 'height': height, 'crop_w': crop_w, 'crop_h': crop_h, 'target_width': target_width, 'target_height': target_height}]], [[condN, {'pooled_output': pooledP, 'width': width, 'height': height, 'crop_w': crop_w, 'crop_h': crop_h, 'target_width': target_width, 'target_height': target_height}]]) +``` \ No newline at end of file diff --git a/docs/CLIP Positive-Negative XL w%2FText (WLSH).md b/docs/CLIP Positive-Negative XL w%2FText (WLSH).md new file mode 100644 index 0000000..76d9c89 --- /dev/null +++ b/docs/CLIP Positive-Negative XL w%2FText (WLSH).md @@ -0,0 +1,112 @@ +# Documentation +- Class name: WLSH_CLIP_Text_Positive_Negative_XL +- Category: WLSH Nodes/conditioning +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_CLIP_Text_Positive_Negative_XL 节点旨在将文本输入处理并编码为适用于条件生成模型的格式。它接收正面和负面的文本示例,并将它们转换成编码表示,这些表示可用于引导生成过程。该节点在塑造生成模型的输出中起着关键作用,通过基于文本输入提供上下文线索。 + +# Input types +## Required +- width + - 宽度参数为节点的图像处理组件定义了宽度维度。它对于设置适当的分辨率并确保输出图像符合所需规格至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数指定要处理的图像的垂直维度。它与宽度参数一起工作,以确定图像的总体分辨率。 + - Comfy dtype: INT + - Python dtype: int +- target_width + - target_width 参数设置最终输出图像的期望宽度。它是节点内调整大小和缩放操作的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- target_height + - target_height 参数设定最终输出图像的期望高度,确保图像在处理后满足所需的尺寸。 + - Comfy dtype: INT + - Python dtype: int +- positive_g + - positive_g 参数接受表示正面引导文本的字符串。它对于将生成过程的方向引导至更有利的结果至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- positive_l + - positive_l 参数提供额外的文本以补充正面引导文本。它有助于为生成模型细化正面条件线索。 + - Comfy dtype: STRING + - Python dtype: str +- negative_g + - negative_g 参数包含负面引导文本,用于引导生成过程避免不希望的结果。 + - Comfy dtype: STRING + - Python dtype: str +- negative_l + - negative_l 参数补充了负面引导文本,进一步定义了生成输出中要避免的内容的界限。 + - Comfy dtype: STRING + - Python dtype: str +- clip + - clip 参数应该是 CLIP 模型的一个实例,这对于节点内文本编码至关重要。它使得文本输入能够转换成生成模型可以使用的形式。 + - Comfy dtype: CLIP + - Python dtype: Any +## Optional +- crop_w + - crop_w 参数用于定义图像中裁剪区域的宽度。它允许对图像的特定区域进行选择性关注以进行进一步处理。 + - Comfy dtype: INT + - Python dtype: int +- crop_h + - crop_h 参数确定图像中裁剪区域的高度。它用于提取图像的特定部分进行更详细的分析或处理。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- positive + - 正面输出提供正面引导文本的编码表示,用于引导生成过程朝向期望的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Any] +- negative + - 负面输出包含负面引导文本的编码表示,用于指导生成过程避免不希望的方向。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Any] +- positive_text + - positive_text 输出是正面引导文本的连接字符串,提供了生成过程中使用的正面线索的可读形式。 + - Comfy dtype: STRING + - Python dtype: str +- negative_text + - negative_text 输出是负面引导文本的连接字符串,提供了生成过程中用来避免某些结果的负面线索的可读形式。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_CLIP_Text_Positive_Negative_XL: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'crop_w': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION}), 'crop_h': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION}), 'target_width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'target_height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'positive_g': ('STRING', {'multiline': True, 'default': 'POS_G'}), 'positive_l': ('STRING', {'multiline': True, 'default': 'POS_L'}), 'negative_g': ('STRING', {'multiline': True, 'default': 'NEG_G'}), 'negative_l': ('STRING', {'multiline': True, 'default': 'NEG_L'}), 'clip': ('CLIP',)}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING', 'STRING', 'STRING') + RETURN_NAMES = ('positive', 'negative', 'positive_text', 'negative_text') + FUNCTION = 'encode' + CATEGORY = 'WLSH Nodes/conditioning' + + def encode(self, clip, width, height, crop_w, crop_h, target_width, target_height, positive_g, positive_l, negative_g, negative_l): + tokens = clip.tokenize(positive_g) + tokens['l'] = clip.tokenize(positive_l)['l'] + if len(tokens['l']) != len(tokens['g']): + empty = clip.tokenize('') + while len(tokens['l']) < len(tokens['g']): + tokens['l'] += empty['l'] + while len(tokens['l']) > len(tokens['g']): + tokens['g'] += empty['g'] + (condP, pooledP) = clip.encode_from_tokens(tokens, return_pooled=True) + tokensN = clip.tokenize(negative_g) + tokensN['l'] = clip.tokenize(negative_l)['l'] + if len(tokensN['l']) != len(tokensN['g']): + empty = clip.tokenize('') + while len(tokensN['l']) < len(tokensN['g']): + tokensN['l'] += empty['l'] + while len(tokensN['l']) > len(tokensN['g']): + tokensN['g'] += empty['g'] + (condN, pooledN) = clip.encode_from_tokens(tokensN, return_pooled=True) + positive_text = positive_g + ', ' + positive_l + negative_text = negative_g + ', ' + negative_l + return ([[condP, {'pooled_output': pooledP, 'width': width, 'height': height, 'crop_w': crop_w, 'crop_h': crop_h, 'target_width': target_width, 'target_height': target_height}]], [[condN, {'pooled_output': pooledP, 'width': width, 'height': height, 'crop_w': crop_w, 'crop_h': crop_h, 'target_width': target_width, 'target_height': target_height}]], positive_text, negative_text) +``` \ No newline at end of file diff --git a/docs/CLIP Positive-Negative w%2FText (WLSH).md b/docs/CLIP Positive-Negative w%2FText (WLSH).md new file mode 100644 index 0000000..a1e3715 --- /dev/null +++ b/docs/CLIP Positive-Negative w%2FText (WLSH).md @@ -0,0 +1,59 @@ +# Documentation +- Class name: WLSH_CLIP_Text_Positive_Negative +- Category: WLSH Nodes/conditioning +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_CLIP_Text_Positive_Negative节点的`encode`方法旨在通过CLIP模型处理文本输入,将其编码为嵌入向量。该节点将文本数据转换为可用于进一步分析或作为机器学习模型输入的形式,扮演着关键角色。它强调节点能够处理正面和负面文本样本的能力,这对于需要进行情感分析或对比学习的任务至关重要。 + +# Input types +## Required +- positive + - 参数'positive'是一个文本输入,代表正面情感或上下文。它是节点操作的基础,因为它构成了情感分析和对比学习的基础,在这些学习中,节点区分正面和负面的文本样本。 + - Comfy dtype: STRING + - Python dtype: str +- negative + - 参数'negative'是一个文本输入,代表负面情感或上下文。它与'positive'参数结合使用,为节点内的编码和分析提供比较基础。 + - Comfy dtype: STRING + - Python dtype: str +- clip + - 参数'clip'是CLIP模型的一个实例,用于将文本输入编码为嵌入向量。它是节点的关键组件,因为它直接影响编码过程的质量和准确性。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module + +# Output types +- positive + - 输出'positive'是正面文本输入的编码表示。它是后续需要情感分析或理解正面上下文的机器学习任务的关键元素。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative + - 输出'negative'是负面文本输入的编码表示。它对于涉及情感分析或模型范围内负面上下文理解的应用具有重要意义。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- positive_text + - 输出'positive_text'是提供给节点的原始正面文本输入。它有助于在进一步处理或分析时,将原始文本数据与编码的嵌入向量一起保留参考。 + - Comfy dtype: STRING + - Python dtype: str +- negative_text + - 输出'negative_text'是提供给节点的原始负面文本输入。它保留了原始文本数据,可能与编码的嵌入向量结合用于后续任务。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WLSH_CLIP_Text_Positive_Negative: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'positive': ('STRING', {'multiline': True}), 'negative': ('STRING', {'multiline': True}), 'clip': ('CLIP',)}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING', 'STRING', 'STRING') + RETURN_NAMES = ('positive', 'negative', 'positive_text', 'negative_text') + FUNCTION = 'encode' + CATEGORY = 'WLSH Nodes/conditioning' + + def encode(self, clip, positive, negative): + return ([[clip.encode(positive), {}]], [[clip.encode(negative), {}]], positive, negative) +``` \ No newline at end of file diff --git a/docs/CLIP Vision Input Switch.md b/docs/CLIP Vision Input Switch.md new file mode 100644 index 0000000..ce8c885 --- /dev/null +++ b/docs/CLIP Vision Input Switch.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: WAS_CLIP_Vision_Input_Switch +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法'clip_vision_switch'旨在基于布尔标志有条件地选择两个输入图像。它在工作流程中充当决策节点,允许根据提供的布尔值将图像数据路由到系统的不同部分。 + +# Input types +## Required +- clip_vision_a + - 参数'clip_vision_a'表示节点可以选择的第一个图像选项。它对于决策过程至关重要,因为它根据布尔标志决定了潜在输出之一。 + - Comfy dtype: CLIP_VISION + - Python dtype: Union[Image.Image, PIL.PngImagePlugin.PngImageFile] +- clip_vision_b + - 参数'clip_vision_b'是当布尔标志为false时节点可能选择的替代图像选项。它在节点的功能中扮演重要角色,通过提供次要的输出选项。 + - Comfy dtype: CLIP_VISION + - Python dtype: Union[Image.Image, PIL.PngImagePlugin.PngImageFile] +## Optional +- boolean + - 参数'boolean'充当开关,决定节点返回哪张图像。它对于控制系统中图像数据的流向至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- CLIP_VISION + - 方法'clip_vision_switch'的输出是由布尔标志确定的单个图像。它代表了节点决策过程的结果,对下游处理至关重要。 + - Comfy dtype: CLIP_VISION + - Python dtype: Union[Image.Image, PIL.PngImagePlugin.PngImageFile] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_CLIP_Vision_Input_Switch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'clip_vision_a': ('CLIP_VISION',), 'clip_vision_b': ('CLIP_VISION',), 'boolean': ('BOOLEAN', {'forceInput': True})}} + RETURN_TYPES = ('CLIP_VISION',) + FUNCTION = 'clip_vision_switch' + CATEGORY = 'WAS Suite/Logic' + + def clip_vision_switch(self, clip_vision_a, clip_vision_b, boolean=True): + if boolean: + return (clip_vision_a,) + else: + return clip_vision_b +``` \ No newline at end of file diff --git a/docs/CLIPSeg Batch Masking.md b/docs/CLIPSeg Batch Masking.md new file mode 100644 index 0000000..cdb4606 --- /dev/null +++ b/docs/CLIPSeg Batch Masking.md @@ -0,0 +1,124 @@ +# Documentation +- Class name: WAS_CLIPSeg_Batch +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_CLIPSeg_Batch节点的CLIPSeg_images方法旨在根据文本提示执行图像分割。它利用CLIPSeg模型生成与图像中描述的实体相对应的掩码。该节点能够处理多个图像和文本,为需要理解视觉和文本输入的语义内容的复杂分割任务提供了强大的解决方案。 + +# Input types +## Required +- image_a + - image_a参数是分割过程所需的主要图像输入。它至关重要,因为它直接影响模型理解和分割图像中所需元素的能力。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- text_a + - text_a参数提供了引导分割模型识别和分割图像特定部分的文本提示。它的重要性在于它能够通过专注于所提供的文本描述来细化分割过程。 + - Comfy dtype: STRING + - Python dtype: str +- image_b + - image_b参数是与image_a一起使用的次要图像输入,可用于更复杂的分割场景。它允许考虑额外的视觉上下文,从而增强分割结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- text_b + - text_b参数是补充text_a的另一个文本提示,为分割模型提供替代或额外的指导。它增强了节点处理多样化分割任务的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- image_c + - 可选的image_c参数允许在分割过程中包含另一个图像。为了使模型能够正确处理,它的尺寸应该与image_a相同。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- text_c + - 可选的text_c参数扩展了分割模型的文本指导,提供了进一步的描述,可以帮助完成更复杂的分割任务。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGES_BATCH + - IMAGES_BATCH输出包含由节点处理的输入图像批次。它很重要,因为它允许在分割后审查和进一步分析原始图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- MASKS_BATCH + - MASKS_BATCH输出提供了与输入图像中感兴趣区域对应的生成掩码。这些掩码对于隔离和进一步处理文本提示描述的特定部分至关重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- MASK_IMAGES_BATCH + - MASK_IMAGES_BATCH输出包括已经被掩码处理的图像,根据文本提示突出显示了分割区域。它是可视化分割过程结果的重要输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WAS_CLIPSeg_Batch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image_a': ('IMAGE',), 'image_b': ('IMAGE',), 'text_a': ('STRING', {'default': '', 'multiline': False}), 'text_b': ('STRING', {'default': '', 'multiline': False})}, 'optional': {'image_c': ('IMAGE',), 'image_d': ('IMAGE',), 'image_e': ('IMAGE',), 'image_f': ('IMAGE',), 'text_c': ('STRING', {'default': '', 'multiline': False}), 'text_d': ('STRING', {'default': '', 'multiline': False}), 'text_e': ('STRING', {'default': '', 'multiline': False}), 'text_f': ('STRING', {'default': '', 'multiline': False})}} + RETURN_TYPES = ('IMAGE', 'MASK', 'IMAGE') + RETURN_NAMES = ('IMAGES_BATCH', 'MASKS_BATCH', 'MASK_IMAGES_BATCH') + FUNCTION = 'CLIPSeg_images' + CATEGORY = 'WAS Suite/Image/Masking' + + def CLIPSeg_images(self, image_a, image_b, text_a, text_b, image_c=None, image_d=None, image_e=None, image_f=None, text_c=None, text_d=None, text_e=None, text_f=None): + from transformers import CLIPSegProcessor, CLIPSegForImageSegmentation + import torch.nn.functional as F + images_pil = [tensor2pil(image_a), tensor2pil(image_b)] + if image_c is not None: + if image_c.shape[-2:] != image_a.shape[-2:]: + cstr('Size of image_c is different from image_a.').error.print() + return + images_pil.append(tensor2pil(image_c)) + if image_d is not None: + if image_d.shape[-2:] != image_a.shape[-2:]: + cstr('Size of image_d is different from image_a.').error.print() + return + images_pil.append(tensor2pil(image_d)) + if image_e is not None: + if image_e.shape[-2:] != image_a.shape[-2:]: + cstr('Size of image_e is different from image_a.').error.print() + return + images_pil.append(tensor2pil(image_e)) + if image_f is not None: + if image_f.shape[-2:] != image_a.shape[-2:]: + cstr('Size of image_f is different from image_a.').error.print() + return + images_pil.append(tensor2pil(image_f)) + images_tensor = [torch.from_numpy(np.array(img.convert('RGB')).astype(np.float32) / 255.0).unsqueeze(0) for img in images_pil] + images_tensor = torch.cat(images_tensor, dim=0) + prompts = [text_a, text_b] + if text_c: + prompts.append(text_c) + if text_d: + prompts.append(text_d) + if text_e: + prompts.append(text_e) + if text_f: + prompts.append(text_f) + cache = os.path.join(MODELS_DIR, 'clipseg') + inputs = CLIPSegProcessor.from_pretrained('CIDAS/clipseg-rd64-refined', cache_dir=cache) + model = CLIPSegForImageSegmentation.from_pretrained('CIDAS/clipseg-rd64-refined', cache_dir=cache) + with torch.no_grad(): + result = model(**inputs(text=prompts, images=images_pil, padding=True, return_tensors='pt')) + masks = [] + mask_images = [] + for (i, res) in enumerate(result.logits): + tensor = torch.sigmoid(res) + mask = 1.0 - (tensor - tensor.min()) / tensor.max() + mask = mask.unsqueeze(0) + mask = tensor2pil(mask).convert('L') + mask = mask.resize(images_pil[0].size) + mask_batch = pil2mask(mask) + masks.append(mask_batch.unsqueeze(0).unsqueeze(1)) + mask_images.append(pil2tensor(ImageOps.invert(mask.convert('RGB'))).squeeze(0)) + masks_tensor = torch.cat(masks, dim=0) + mask_images_tensor = torch.stack(mask_images, dim=0) + del inputs, model, result, tensor, masks, mask_images, images_pil + return (images_tensor, masks_tensor, mask_images_tensor) +``` \ No newline at end of file diff --git a/docs/CLIPSeg Masking.md b/docs/CLIPSeg Masking.md new file mode 100644 index 0000000..4f05118 --- /dev/null +++ b/docs/CLIPSeg Masking.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: WAS_CLIPSeg +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +CLIPSeg_image 方法旨在使用文本提示执行图像分割。它利用 CLIPSeg 模型生成一个掩码,该掩码隔离了文本描述的图像中的主体。此方法对于需要基于文本描述进行精确对象分割的应用场景特别有用。 + +# Input types +## Required +- image + - 图像参数对于分割过程至关重要,因为它是模型将分析的输入,以识别和隔离所需的主体。图像的质量和分辨率可以显著影响生成的掩码的准确性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- text + - 文本参数提供了一个描述,指导分割过程。它是可选的,但可以通过指定模型应在图像中关注的内容来提高分割的精度。 + - Comfy dtype: STRING + - Python dtype: str +- clipseg_model + - clipseg_model 参数允许用户为分割提供预训练的 CLIPSeg 模型。这对于使用已针对特定任务或数据集进行了微调的自定义模型可能是有益的。 + - Comfy dtype: CLIPSEG_MODEL + - Python dtype: Tuple[str, transformers.CLIPSegForImageSegmentation] + +# Output types +- MASK + - MASK 输出是一个二进制掩码,根据提供的文本描述将分割的主体与图像的其余部分分开。它对于需要对象分离或背景移除的应用场景至关重要。 + - Comfy dtype: MASK + - Python dtype: np.ndarray +- MASK_IMAGE + - MASK_IMAGE 输出是一个被掩码突出显示的分割主体的反转图像。它可以用于视觉验证或需要分割的图像表示的进一步处理步骤。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WAS_CLIPSeg: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'text': ('STRING', {'default': '', 'multiline': False})}, 'optional': {'clipseg_model': ('CLIPSEG_MODEL',)}} + RETURN_TYPES = ('MASK', 'IMAGE') + RETURN_NAMES = ('MASK', 'MASK_IMAGE') + FUNCTION = 'CLIPSeg_image' + CATEGORY = 'WAS Suite/Image/Masking' + + def CLIPSeg_image(self, image, text=None, clipseg_model=None): + from transformers import CLIPSegProcessor, CLIPSegForImageSegmentation + image = tensor2pil(image) + cache = os.path.join(MODELS_DIR, 'clipseg') + if clipseg_model: + inputs = clipseg_model[0] + model = clipseg_model[1] + else: + inputs = CLIPSegProcessor.from_pretrained('CIDAS/clipseg-rd64-refined', cache_dir=cache) + model = CLIPSegForImageSegmentation.from_pretrained('CIDAS/clipseg-rd64-refined', cache_dir=cache) + with torch.no_grad(): + result = model(**inputs(text=text, images=image, padding=True, return_tensors='pt')) + tensor = torch.sigmoid(result[0]) + mask = 1.0 - (tensor - tensor.min()) / tensor.max() + mask = mask.unsqueeze(0) + mask = tensor2pil(mask).convert('L') + mask = mask.resize(image.size) + return (pil2mask(mask), pil2tensor(ImageOps.invert(mask.convert('RGB')))) +``` \ No newline at end of file diff --git a/docs/CLIPSeg Model Loader.md b/docs/CLIPSeg Model Loader.md new file mode 100644 index 0000000..52320d4 --- /dev/null +++ b/docs/CLIPSeg Model Loader.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: WAS_CLIPSeg_Model_Loader +- Category: WAS Suite/Loaders +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_CLIPSeg_Model_Loader节点是工作流程中的关键组件,旨在高效地加载和集成CLIPSeg模型到系统中。它简化了模型初始化过程,确保模型为后续任务(如图像分割)正确设置。通过抽象加载和缓存模型的复杂性,该节点简化了整体操作并增强了用户体验。 + +# Input types +## Required +- model + - ‘model’参数对于指定要加载的CLIPSeg模型至关重要。它指导节点到正确的预训练模型,这对于节点的执行和分割结果的质量至关重要。该参数确保分配适当的资源,并确保模型在系统中按预期运行。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- clipseg_model + - 'clipseg_model'输出提供了已加载的CLIPSeg模型,准备用于图像分割任务。它代表了节点操作的成果,封装了模型的下游应用能力。此输出非常重要,因为它使得进一步的处理和分析成为可能,充当了模型加载和实际使用之间的桥梁。 + - Comfy dtype: CLIPSEG_MODEL + - Python dtype: Tuple[CLIPSegProcessor, CLIPSegForImageSegmentation] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_CLIPSeg_Model_Loader: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('STRING', {'default': 'CIDAS/clipseg-rd64-refined', 'multiline': False})}} + RETURN_TYPES = ('CLIPSEG_MODEL',) + RETURN_NAMES = ('clipseg_model',) + FUNCTION = 'clipseg_model' + CATEGORY = 'WAS Suite/Loaders' + + def clipseg_model(self, model): + from transformers import CLIPSegProcessor, CLIPSegForImageSegmentation + cache = os.path.join(MODELS_DIR, 'clipseg') + inputs = CLIPSegProcessor.from_pretrained(model, cache_dir=cache) + model = CLIPSegForImageSegmentation.from_pretrained(model, cache_dir=cache) + return ((inputs, model),) +``` \ No newline at end of file diff --git a/docs/CLIPSegDetectorProvider.md b/docs/CLIPSegDetectorProvider.md new file mode 100644 index 0000000..3f4b0ed --- /dev/null +++ b/docs/CLIPSegDetectorProvider.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: CLIPSegDetectorProvider +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +CLIPSegDetectorProvider节点旨在基于CLIPSeg模型创建一个边界框检测器。它处理输入文本和图像数据,以在图像中感兴趣的对象周围生成边界框。该节点特别适用于需要基于文本提示进行引导的对象检测功能的应用程序。 + +# Input types +## Required +- text + - 文本参数对于通过提供要检测对象的文本描述来指导检测过程至关重要。它在生成的边界框的准确性和相关性中起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- blur + - 模糊参数调整要应用于图像的模糊程度,这可能影响检测精度。它是一个可选参数,允许根据图像的特性微调检测过程。 + - Comfy dtype: FLOAT + - Python dtype: float +- threshold + - 阈值参数确定对象检测的截止点。它是一个可选输入,可用于控制检测的灵敏度,影响哪些对象被识别为相关。 + - Comfy dtype: FLOAT + - Python dtype: float +- dilation_factor + - 膨胀因子用于扩大检测到的对象的边界。它是一个可选参数,可以增强图像中较大或更分散的对象的检测。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- BBOX_DETECTOR + - CLIPSegDetectorProvider的输出是一个BBOX_DETECTOR对象,它包含基于提供的文本提示检测和生成图像中对象周围的边界框的逻辑。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: BBoxDetectorBasedOnCLIPSeg + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CLIPSegDetectorProvider: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': False}), 'blur': ('FLOAT', {'min': 0, 'max': 15, 'step': 0.1, 'default': 7}), 'threshold': ('FLOAT', {'min': 0, 'max': 1, 'step': 0.05, 'default': 0.4}), 'dilation_factor': ('INT', {'min': 0, 'max': 10, 'step': 1, 'default': 4})}} + RETURN_TYPES = ('BBOX_DETECTOR',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, text, blur, threshold, dilation_factor): + if 'CLIPSeg' in nodes.NODE_CLASS_MAPPINGS: + return (core.BBoxDetectorBasedOnCLIPSeg(text, blur, threshold, dilation_factor),) + else: + print("[ERROR] CLIPSegToBboxDetector: CLIPSeg custom node isn't installed. You must install biegert/ComfyUI-CLIPSeg extension to use this node.") +``` \ No newline at end of file diff --git a/docs/CLIPSeg_.md b/docs/CLIPSeg_.md new file mode 100644 index 0000000..fa39113 --- /dev/null +++ b/docs/CLIPSeg_.md @@ -0,0 +1,123 @@ +# Documentation +- Class name: CLIPSeg +- Category: ♾️Mixlab/Mask +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-CLIPSeg + +CLIPSeg节点旨在使用文本提示和图像输入执行图像分割。它利用CLIPSeg模型的力量创建与所提供的文本描述一致的分割掩码。该节点擅长生成可以进一步处理以用于各种应用的掩码,例如对象识别、图像编辑和数据分析。 + +# Input types +## Required +- image + - 图像参数对于节点的操作至关重要,因为它是分割的主要输入。它决定了将根据提供的文本提示进行分析和分割的内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- text + - 文本参数是必需的,因为它提供了指导分割过程的描述性提示。它使节点能够专注于图像中与文本描述相关的特定元素。 + - Comfy dtype: STRING + - Python dtype: str +- blur + - 模糊参数允许调整分割掩码的平滑度。它有助于细化掩码的边缘并提高分割的整体质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- threshold + - 阈值参数用于将连续的分割掩码转换为二进制掩码。它决定了分割中对象和背景之间的截止点。 + - Comfy dtype: FLOAT + - Python dtype: float +- dilation_factor + - 膨胀因子对于扩展分割掩码的边界很重要。它可以用来确保分割区域覆盖目标对象的全部。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- Mask + - 掩码输出提供了图像分割过程产生的二进制分割掩码。对于需要对象识别或与背景分离的应用来说,这是一个关键的输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- Heatmap Mask + - 热图掩码输出是分割掩码的视觉表示,其中颜色的强度对应于分割的置信度水平。它适用于视觉分析和调试目的。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- BW Mask + - 黑白掩码输出是分割掩码的二值化版本,为分割的对象和背景提供了直接的区分。它通常用于进一步处理或作为分割的简化表示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CLIPSeg: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + """ + Return a dictionary which contains config for all input fields. + Some types (string): "MODEL", "VAE", "CLIP", "CONDITIONING", "LATENT", "IMAGE", "INT", "STRING", "FLOAT". + Input types "INT", "STRING" or "FLOAT" are special values for fields on the node. + The type can be a list for selection. + + Returns: `dict`: + - Key input_fields_group (`string`): Can be either required, hidden or optional. A node class must have property `required` + - Value input_fields (`dict`): Contains input fields config: + * Key field_name (`string`): Name of a entry-point method's argument + * Value field_config (`tuple`): + + First value is a string indicate the type of field or a list for selection. + + Secound value is a config for type "INT", "STRING" or "FLOAT". + """ + return {'required': {'image': ('IMAGE',), 'text': ('STRING', {'multiline': False, 'dynamicPrompts': False})}, 'optional': {'blur': ('FLOAT', {'min': 0, 'max': 15, 'step': 0.1, 'default': 3}), 'threshold': ('FLOAT', {'min': 0, 'max': 1, 'step': 0.05, 'default': 0.3}), 'dilation_factor': ('INT', {'min': 0, 'max': 10, 'step': 1, 'default': 4})}} + CATEGORY = '♾️Mixlab/Mask' + RETURN_TYPES = ('MASK', 'IMAGE', 'IMAGE') + RETURN_NAMES = ('Mask', 'Heatmap Mask', 'BW Mask') + OUTPUT_IS_LIST = (False, False, False) + FUNCTION = 'segment_image' + + def segment_image(self, image: torch.Tensor, text: str, blur: float, threshold: float, dilation_factor: int) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: + """Create a segmentation mask from an image and a text prompt using CLIPSeg. + + Args: + image (torch.Tensor): The image to segment. + text (str): The text prompt to use for segmentation. + blur (float): How much to blur the segmentation mask. + threshold (float): The threshold to use for binarizing the segmentation mask. + dilation_factor (int): How much to dilate the segmentation mask. + + Returns: + Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: The segmentation mask, the heatmap mask, and the binarized mask. + """ + image_np = image.numpy().squeeze() + image_np = (image_np * 255).astype(np.uint8) + i = Image.fromarray(image_np, mode='RGB') + processor = CLIPSegProcessor.from_pretrained(clipseg_model_dir) + model = CLIPSegForImageSegmentation.from_pretrained(clipseg_model_dir) + prompt = text + input_prc = processor(text=prompt, images=i, padding='max_length', return_tensors='pt') + with torch.no_grad(): + outputs = model(**input_prc) + tensor = torch.sigmoid(outputs[0]) + thresh = threshold + tensor_thresholded = torch.where(tensor > thresh, tensor, torch.tensor(0, dtype=torch.float)) + sigma = blur + tensor_smoothed = gaussian_filter(tensor_thresholded.numpy(), sigma=sigma) + tensor_smoothed = torch.from_numpy(tensor_smoothed) + mask_normalized = (tensor_smoothed - tensor_smoothed.min()) / (tensor_smoothed.max() - tensor_smoothed.min()) + mask_dilated = dilate_mask(mask_normalized, dilation_factor) + heatmap = apply_colormap(mask_dilated, cm.viridis) + binary_mask = apply_colormap(mask_dilated, cm.Greys_r) + dimensions = (image_np.shape[1], image_np.shape[0]) + heatmap_resized = resize_image(heatmap, dimensions) + binary_mask_resized = resize_image(binary_mask, dimensions) + (alpha_heatmap, alpha_binary) = (0.5, 1) + overlay_heatmap = overlay_image(image_np, heatmap_resized, alpha_heatmap) + overlay_binary = overlay_image(image_np, binary_mask_resized, alpha_binary) + image_out_heatmap = numpy_to_tensor(overlay_heatmap) + image_out_binary = numpy_to_tensor(overlay_binary) + binary_mask_image = Image.fromarray(binary_mask_resized[..., 0]) + tensor_bw = binary_mask_image.convert('L') + tensor_bw = pil2tensor(tensor_bw) + return (tensor_bw, image_out_heatmap, image_out_binary) +``` \ No newline at end of file diff --git a/docs/CLIPTextEncodeList.md b/docs/CLIPTextEncodeList.md new file mode 100644 index 0000000..4b84478 --- /dev/null +++ b/docs/CLIPTextEncodeList.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: CLIPTextEncodeSequence +- Category: conditioning +- Output node: False +- Repo Ref: https://github.com/WASasquatch/WAS_Extras + +CLIPTextEncodeSequence节点旨在将一系列文本行编码成一组条件序列,这些序列可以用于神经网络中的进一步处理。它考虑了标记归一化和权重解释方法,以产生文本的有意义的表示。 + +# Input types +## Required +- clip + - 'clip'参数对于编码过程至关重要,因为它提供了用于文本编码的上下文或模型。它直接影响文本如何被转换为数值表示。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- token_normalization + - 'token_normalization'参数决定了文本中的标记在编码前如何被归一化。它在确保编码后的文本保持一致的规模方面起着关键作用,这对于后续的神经网络操作非常重要。 + - Comfy dtype: COMBO[none, mean, length, length+mean] + - Python dtype: str +- weight_interpretation + - 'weight_interpretation'参数定义了在编码过程中与文本标记相关联的权重的解释方法。它影响着生成的编码序列的质量和特征。 + - Comfy dtype: COMBO[comfy, A1111, compel, comfy++] + - Python dtype: str +- text + - 'text'参数是节点处理的原始文本输入。它是多行的,可以包一系列文本行,每行都将被编码成条件序列。文本的内容和结构显著影响节点的输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- conditioning_sequence + - 'conditioning_sequence'输出是一系列编码后的文本行,每行都表示为索引和编码向量的一对。这个输出很重要,因为它为需要基于文本的条件的下游神经网络模型提供了必要的输入。 + - Comfy dtype: CONDITIONING_SEQ + - Python dtype: List[Tuple[int, List[float]]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CLIPTextEncodeSequence: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'clip': ('CLIP',), 'token_normalization': (['none', 'mean', 'length', 'length+mean'],), 'weight_interpretation': (['comfy', 'A1111', 'compel', 'comfy++'],), 'text': ('STRING', {'multiline': True, 'default': '0:A portrait of a rosebud\n5:A portrait of a blooming rosebud\n10:A portrait of a blooming rose\n15:A portrait of a rose'})}} + RETURN_TYPES = ('CONDITIONING_SEQ',) + RETURN_NAMES = ('conditioning_sequence',) + IS_LIST_OUTPUT = (True,) + FUNCTION = 'encode' + CATEGORY = 'conditioning' + + def encode(self, clip, text, token_normalization, weight_interpretation): + text = text.strip() + conditionings = [] + for l in text.splitlines(): + match = re.match('(\\d+):', l) + if match: + idx = int(match.group(1)) + (_, line) = l.split(':', 1) + line = line.strip() + if USE_BLK: + encoded = blk_adv.encode(clip=clip, text=line, token_normalization=token_normalization, weight_interpretation=weight_interpretation) + else: + encoded = CLIPTextEncode.encode(clip=clip, text=line) + conditioning = (idx, [encoded[0][0][0], encoded[0][0][1]]) + conditionings.append(conditioning) + return (conditionings,) +``` \ No newline at end of file diff --git a/docs/CLIPTextEncodeSDXL+.md b/docs/CLIPTextEncodeSDXL+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/CLIPTextEncodeSequence2.md b/docs/CLIPTextEncodeSequence2.md new file mode 100644 index 0000000..df0315b --- /dev/null +++ b/docs/CLIPTextEncodeSequence2.md @@ -0,0 +1,99 @@ +# Documentation +- Class name: CLIPTextEncodeSequence2 +- Category: conditioning +- Output node: False +- Repo Ref: https://github.com/WASasquatch/WAS_Extras + +CLIPTextEncodeSequence2节点旨在将文本序列编码成可用于生成模型中进一步处理的条件序列。它处理每行文本以创建一组条件向量,然后根据指定的关键帧类型对这些向量进行转换,以与所需的帧数对齐。 + +# Input types +## Required +- clip + - clip参数至关重要,因为它为文本编码过程提供了必要的上下文。它影响文本如何被转换成条件向量序列。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- frame_count + - 帧数参数指定要生成的总帧数。它是一个基本参数,直接影响输出条件序列的规模。 + - Comfy dtype: INT + - Python dtype: int +- text + - 文本参数是编码过程的原始输入。它是将被转换成条件序列的信息来源。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- token_normalization + - 令牌归一化是一种用于稳定编码过程的技术。它决定了文本编码中令牌的归一化方式,这可能会影响生成的条件序列的质量。 + - Comfy dtype: COMBO[none, mean, length, length+mean] + - Python dtype: str +- weight_interpretation + - 权重解释参数定义了解译编码文本权重的方法。它对编码过程的准确性和可靠性至关重要。 + - Comfy dtype: COMBO[comfy, A1111, compel, comfy++] + - Python dtype: str +- cond_keyframes_type + - cond_keyframes_type参数决定条件关键帧如何分布在帧数上。它对于将文本编码与所需的时间结构对齐非常重要。 + - Comfy dtype: COMBO[linear, sinus, sinus_inverted, half_sinus, half_sinus_inverted] + - Python dtype: str + +# Output types +- conditioning_sequence + - 条件序列是编码文本表示的列表,用作生成模型的输入。它是指导生成过程的关键组成部分。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[int, torch.Tensor]] +- cond_keyframes + - cond_keyframes代表生成序列中与编码文本对应的特定帧。它们对于同步文本编码和视觉输出非常重要。 + - Comfy dtype: INT + - Python dtype: List[int] +- frame_count + - 帧数表示生成的总帧数,提供了输出范围的度量。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CLIPTextEncodeSequence2: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'clip': ('CLIP',), 'token_normalization': (['none', 'mean', 'length', 'length+mean'],), 'weight_interpretation': (['comfy', 'A1111', 'compel', 'comfy++'],), 'cond_keyframes_type': (['linear', 'sinus', 'sinus_inverted', 'half_sinus', 'half_sinus_inverted'],), 'frame_count': ('INT', {'default': 100, 'min': 1, 'max': 1024, 'step': 1}), 'text': ('STRING', {'multiline': True, 'default': 'A portrait of a rosebud\nA portrait of a blooming rosebud\nA portrait of a blooming rose\nA portrait of a rose'})}} + RETURN_TYPES = ('CONDITIONING', 'INT', 'INT') + RETURN_NAMES = ('conditioning_sequence', 'cond_keyframes', 'frame_count') + IS_LIST_OUTPUT = (True, True, False) + FUNCTION = 'encode' + CATEGORY = 'conditioning' + + def encode(self, clip, text, cond_keyframes_type, frame_count, token_normalization, weight_interpretation): + text = text.strip() + conditionings = [] + for line in text.splitlines(): + if USE_BLK: + encoded = blk_adv.encode(clip=clip, text=line, token_normalization=token_normalization, weight_interpretation=weight_interpretation) + else: + encoded = CLIPTextEncode.encode(clip=clip, text=line) + conditionings.append([encoded[0][0][0], encoded[0][0][1]]) + conditioning_count = len(conditionings) + cond_keyframes = self.calculate_cond_keyframes(cond_keyframes_type, frame_count, conditioning_count) + return (conditionings, cond_keyframes, frame_count) + + def calculate_cond_keyframes(self, type, frame_count, conditioning_count): + if type == 'linear': + return np.linspace(frame_count // conditioning_count, frame_count, conditioning_count, dtype=int).tolist() + elif type == 'sinus': + t = np.linspace(0, np.pi, conditioning_count) + sinus_values = np.sin(t) + normalized_values = (sinus_values - sinus_values.min()) / (sinus_values.max() - sinus_values.min()) + scaled_values = normalized_values * (frame_count - 1) + 1 + unique_keyframes = np.round(scaled_values).astype(int) + unique_keyframes = np.unique(unique_keyframes, return_index=True)[1] + return sorted(unique_keyframes.tolist()) + elif type == 'sinus_inverted': + return (np.cos(np.linspace(0, np.pi, conditioning_count)) * (frame_count - 1) + 1).astype(int).tolist() + elif type == 'half_sinus': + return (np.sin(np.linspace(0, np.pi / 2, conditioning_count)) * (frame_count - 1) + 1).astype(int).tolist() + elif type == 'half_sinus_inverted': + return (np.cos(np.linspace(0, np.pi / 2, conditioning_count)) * (frame_count - 1) + 1).astype(int).tolist() + else: + raise ValueError('Unsupported cond_keyframes_type: ' + type) +``` \ No newline at end of file diff --git a/docs/CLIPTextEncodeWithWeight %2F%2FInspire.md b/docs/CLIPTextEncodeWithWeight %2F%2FInspire.md new file mode 100644 index 0000000..5789aa3 --- /dev/null +++ b/docs/CLIPTextEncodeWithWeight %2F%2FInspire.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: CLIPTextEncodeWithWeight +- Category: InspirePack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在使用CLIP模型处理文本数据,具有调整编码强度和对标记应用额外权重的能力,从而允许对文本编码过程进行细微控制。 + +# Input types +## Required +- text + - 文本参数是必需的,因为它提供了节点处理的原始文本输入。它是编码和权重调整的基础。 + - Comfy dtype: STRING + - Python dtype: str +- clip + - clip参数代表将用于标记化和编码输入文本的CLIP模型。它对于节点的功能至关重要,因为它决定了编码过程。 + - Comfy dtype: CLIP + - Python dtype: CLIP +## Optional +- strength + - 强度参数允许调整文本标记的编码强度。它修改编码过程,以更好地适应手头任务的特定要求。 + - Comfy dtype: FLOAT + - Python dtype: float +- add_weight + - add_weight参数提供了在编码过程中对标记应用额外权重的能力。这可以用来根据任务的需要进一步微调编码。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- pooled_output + - pooled_output参数代表编码文本的聚合和浓缩表示,这是节点处理的结果。它封装了文本的精髓以供进一步使用。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CLIPTextEncodeWithWeight: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True}), 'clip': ('CLIP',), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'add_weight': ('FLOAT', {'default': 0.0, 'min': -10.0, 'max': 10.0, 'step': 0.01})}} + RETURN_TYPES = ('CONDITIONING',) + FUNCTION = 'encode' + CATEGORY = 'InspirePack/Util' + + def encode(self, clip, text, strength, add_weight): + tokens = clip.tokenize(text) + if add_weight != 0 or strength != 1: + for v in tokens.values(): + for vv in v: + for i in range(0, len(vv)): + vv[i] = (vv[i][0], vv[i][1] * strength + add_weight) + (cond, pooled) = clip.encode_from_tokens(tokens, return_pooled=True) + return ([[cond, {'pooled_output': pooled}]],) +``` \ No newline at end of file diff --git a/docs/CM_BoolBinaryOperation.md b/docs/CM_BoolBinaryOperation.md new file mode 100644 index 0000000..b798338 --- /dev/null +++ b/docs/CM_BoolBinaryOperation.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: BoolBinaryOperation +- Category: math/bool +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +BoolBinaryOperation节点旨在对布尔值执行二元运算。它接受两个布尔输入和一个表示要执行操作的字符串,并返回操作的结果。此节点对于系统中的逻辑计算和决策过程至关重要。 + +# Input types +## Required +- op + - ‘op’参数是一个字符串,用于指定要对布尔输入执行的二元运算。它对于确定操作的逻辑和最终结果至关重要。 + - Comfy dtype: str + - Python dtype: str +- a + - ‘a’参数是二元运算中的第一个操作数。它是一个布尔值,在计算过程中起着重要作用。 + - Comfy dtype: bool + - Python dtype: bool +- b + - ‘b’参数是二元运算中的第二个操作数。它也是一个布尔值,对计算结果有贡献。 + - Comfy dtype: bool + - Python dtype: bool + +# Output types +- result + - 布尔二元运算的结果,是一个单一的布尔值,代表操作的结果。 + - Comfy dtype: bool + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BoolBinaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(BOOL_BINARY_OPERATIONS.keys()),), 'a': DEFAULT_BOOL, 'b': DEFAULT_BOOL}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/bool' + + def op(self, op: str, a: bool, b: bool) -> tuple[bool]: + return (BOOL_BINARY_OPERATIONS[op](a, b),) +``` \ No newline at end of file diff --git a/docs/CM_BoolToInt.md b/docs/CM_BoolToInt.md new file mode 100644 index 0000000..69660e9 --- /dev/null +++ b/docs/CM_BoolToInt.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: BoolToInt +- Category: math/conversion +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +BoolToInt节点旨在将布尔值转换为其整数等价物。在需要布尔状态的数值表示的情况下,例如数学运算或数据处理工作流中,它发挥着关键作用。 + +# Input types +## Required +- a + - 'a'参数是节点期待的布尔输入。它对于转换过程至关重要,因为节点的目的是将这个布尔值转换为整数。输入的布尔特性直接影响输出的整数值,'True'映射为1,'False'映射为0。 + - Comfy dtype: BOOL + - Python dtype: bool + +# Output types +- op + - 'op'输出提供了输入布尔值的整数转换。它很重要,因为它代表了节点操作的直接结果,概括了从布尔到整数的转换过程的本质。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BoolToInt: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'a': ('BOOL', {'default': False})}} + RETURN_TYPES = ('INT',) + FUNCTION = 'op' + CATEGORY = 'math/conversion' + + def op(self, a: bool) -> tuple[int]: + return (int(a),) +``` \ No newline at end of file diff --git a/docs/CM_BoolUnaryOperation.md b/docs/CM_BoolUnaryOperation.md new file mode 100644 index 0000000..ddc75d2 --- /dev/null +++ b/docs/CM_BoolUnaryOperation.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: BoolUnaryOperation +- Category: math/bool +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +BoolUnaryOperation节点旨在对布尔值执行一元操作。它接受一个布尔输入,应用指定的一元操作,并产生一个布尔输出。该节点对于以一种流线化和高效的方式操纵布尔逻辑至关重要。 + +# Input types +## Required +- op + - 参数'op'指定将应用于布尔输入的一元操作。它对于确定节点将处理的逻辑至关重要。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'表示将应用一元操作的布尔值。它在节点的执行中扮演中心角色,因为它是操作的对象。 + - Comfy dtype: bool + - Python dtype: bool + +# Output types +- result + - 参数'result'是输入布尔值执行的一元操作的输出。它标志着节点内逻辑操作的结果。 + - Comfy dtype: bool + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BoolUnaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(BOOL_UNARY_OPERATIONS.keys()),), 'a': DEFAULT_BOOL}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/bool' + + def op(self, op: str, a: bool) -> tuple[bool]: + return (BOOL_UNARY_OPERATIONS[op](a),) +``` \ No newline at end of file diff --git a/docs/CM_BreakoutVec2.md b/docs/CM_BreakoutVec2.md new file mode 100644 index 0000000..80c648c --- /dev/null +++ b/docs/CM_BreakoutVec2.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: BreakoutVec2 +- Category: math/conversion +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +BreakoutVec2节点旨在将二维向量分解为其各个组成部分。它在向量操作中扮演基础角色,通过提供对Vec2对象单独元素的访问,这些元素随后可以独立用于进一步的计算或操作。 + +# Input types +## Required +- a + - 参数'a'是一个二维向量,是节点操作的对象。它至关重要,因为它是决定节点输出的主要输入。节点将这个向量分解为其组成部分,然后这些部分就可以供其他过程使用。 + - Comfy dtype: VEC2 + - Python dtype: Vec2 + +# Output types +- x + - 输出'x'代表输入向量经过节点处理后的第一个分量。它很重要,因为它允许分离和单独处理向量元素,这在各种数学和几何计算中可能至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- y + - 输出'y'对应于输入向量的第二个分量。它与'x'输出同样重要,适用于需要分别操作或分析向量分量的应用,例如在图形渲染或物理模拟中。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BreakoutVec2: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'a': ('VEC2', {'default': VEC2_ZERO})}} + RETURN_TYPES = ('FLOAT', 'FLOAT') + FUNCTION = 'op' + CATEGORY = 'math/conversion' + + def op(self, a: Vec2) -> tuple[float, float]: + return (a[0], a[1]) +``` \ No newline at end of file diff --git a/docs/CM_BreakoutVec3.md b/docs/CM_BreakoutVec3.md new file mode 100644 index 0000000..2e8d0cf --- /dev/null +++ b/docs/CM_BreakoutVec3.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: BreakoutVec3 +- Category: math/conversion +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +BreakoutVec3节点旨在将三维向量分解为其各个分量。它在需要进一步处理或分析的数学运算中扮演着基础角色,其中向量元素的分离是必要的。 + +# Input types +## Required +- a + - 'a'参数是一个三维向量,节点对其进行操作。它对节点的功能至关重要,因为它是将被分解为其组成部分的输入向量。 + - Comfy dtype: VEC3 + - Python dtype: Vec3 + +# Output types +- result + - BreakoutVec3节点的输出是一个包含输入向量三个独立分量的元组。每个分量是一个浮点数,代表向量的一个维度。 + - Comfy dtype: FLOAT + - Python dtype: Tuple[float, float, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BreakoutVec3: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'a': ('VEC3', {'default': VEC3_ZERO})}} + RETURN_TYPES = ('FLOAT', 'FLOAT', 'FLOAT') + FUNCTION = 'op' + CATEGORY = 'math/conversion' + + def op(self, a: Vec3) -> tuple[float, float, float]: + return (a[0], a[1], a[2]) +``` \ No newline at end of file diff --git a/docs/CM_BreakoutVec4.md b/docs/CM_BreakoutVec4.md new file mode 100644 index 0000000..1b8d67b --- /dev/null +++ b/docs/CM_BreakoutVec4.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: BreakoutVec4 +- Category: math/conversion +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +BreakoutVec4节点旨在将四维向量分解为其各个组成部分。它的作用是促进需要单独操作Vec4对象中每个元素的操作。该节点在数学转换中扮演着关键角色,特别是当上下文要求分别处理向量分量时。 + +# Input types +## Required +- a + - 参数'a'是节点将分解的输入四维向量。它对节点的操作至关重要,因为它是正在处理的主要数据结构。节点的功能集中在将这个向量分解为其组成部分,以供进一步使用。 + - Comfy dtype: VEC4 + - Python dtype: Vec4 + +# Output types +- a components + - BreakoutVec4节点的输出由四个独立的浮点数组成,每个数代表原始Vec4输入的一个分量。此输出允许对向量分量进行单独分析和操作,这对于各种数学和计算应用来说都是重要的。 + - Comfy dtype: FLOAT + - Python dtype: Tuple[float, float, float, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BreakoutVec4: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'a': ('VEC4', {'default': VEC4_ZERO})}} + RETURN_TYPES = ('FLOAT', 'FLOAT', 'FLOAT', 'FLOAT') + FUNCTION = 'op' + CATEGORY = 'math/conversion' + + def op(self, a: Vec4) -> tuple[float, float, float, float]: + return (a[0], a[1], a[2], a[3]) +``` \ No newline at end of file diff --git a/docs/CM_ComposeVec2.md b/docs/CM_ComposeVec2.md new file mode 100644 index 0000000..5892b08 --- /dev/null +++ b/docs/CM_ComposeVec2.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: ComposeVec2 +- Category: math/conversion +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +ComposeVec2节点旨在将两个标量值组合成一个单一的二维向量。它在向量数学中扮演着关键角色,通过允许从单独的分量创建Vec2对象,然后可以在进一步的几何或数学运算中使用这些对象。 + +# Input types +## Required +- x + - 参数'x'表示二维向量的第一个分量。它对于在笛卡尔坐标系中定义水平位置至关重要,并且对向量的总体方向和大小有重要贡献。 + - Comfy dtype: FLOAT + - Python dtype: float +- y + - 参数'y'表示二维向量的第二个分量,表示坐标系中的垂直位置。它对于建立向量的垂直方向至关重要,并且与'x'一起决定了向量的总体轨迹。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- Vec2 + - ComposeVec2节点的输出是一个Vec2对象,它将提供的'x'和'y'分量封装成一个连贯的二维向量。这个向量可以用于广泛的数学和几何计算。 + - Comfy dtype: VEC2 + - Python dtype: Vec2 + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ComposeVec2: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'x': ('FLOAT', {'default': 0.0}), 'y': ('FLOAT', {'default': 0.0})}} + RETURN_TYPES = ('VEC2',) + FUNCTION = 'op' + CATEGORY = 'math/conversion' + + def op(self, x: float, y: float) -> tuple[Vec2]: + return ((x, y),) +``` \ No newline at end of file diff --git a/docs/CM_ComposeVec3.md b/docs/CM_ComposeVec3.md new file mode 100644 index 0000000..1a1b704 --- /dev/null +++ b/docs/CM_ComposeVec3.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: ComposeVec3 +- Category: math/conversion +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +该节点从三个独立的浮点值合成一个Vec3对象,便于在数学或几何上下文中创建和操作三维向量。 + +# Input types +## Required +- x + - 向量的x坐标是一个基本参数,它定义了三维空间中沿水平轴的位置,影响向量的方向和大小。 + - Comfy dtype: FLOAT + - Python dtype: float +- y + - 向量的y坐标决定了它在三维空间中垂直轴上的位置,这对于建立向量在坐标系统中的方向和影响至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- z + - 向量的z坐标决定了它在三维空间中深度轴上的位置,这对向量的整体空间表示起着至关重要的作用。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- Vec3 + - 输出是一个Vec3对象,封装了三个输入值,代表三维空间中的一个向量,可以用于各种数学和几何操作。 + - Comfy dtype: VEC3 + - Python dtype: Vec3 + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ComposeVec3: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'x': ('FLOAT', {'default': 0.0}), 'y': ('FLOAT', {'default': 0.0}), 'z': ('FLOAT', {'default': 0.0})}} + RETURN_TYPES = ('VEC3',) + FUNCTION = 'op' + CATEGORY = 'math/conversion' + + def op(self, x: float, y: float, z: float) -> tuple[Vec3]: + return ((x, y, z),) +``` \ No newline at end of file diff --git a/docs/CM_ComposeVec4.md b/docs/CM_ComposeVec4.md new file mode 100644 index 0000000..3c4ee00 --- /dev/null +++ b/docs/CM_ComposeVec4.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: ComposeVec4 +- Category: math/conversion +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +ComposeVec4节点旨在将四个单独的浮点数值组合成一个Vec4对象。它在数学运算中转换和聚合空间或颜色数据中扮演着关键角色。该节点简化了从标量组件创建四维向量的过程,这对于各种计算几何和图形应用至关重要。 + +# Input types +## Required +- x + - 参数'x'代表四维向量的首个分量。它对于定义生成的Vec4对象中的空间方向或颜色强度至关重要。此参数直接影响向量组合的结果,是节点功能中不可或缺的一部分。 + - Comfy dtype: FLOAT + - Python dtype: float +- y + - 参数'y'表示Vec4的第二个分量,有助于向量的整体结构。它对于需要全面表示空间或颜色数据的应用至关重要,确保了节点在生成一个定义良好的向量中的作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- z + - 参数'z'表示四维向量的第三个分量。它是向量构造中的关键元素,特别是在三维空间表示或涉及颜色通道时。'z'值对于节点从各个分量生成有意义的向量的能力至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- w + - 参数'w'是Vec4对象的第四个也是最后一个分量。它通常表示额外信息,如在齐次坐标系统中的透视或颜色数据中的alpha通道。包含'w'可以完成向量,允许在各种数学和图形上下文中完整表示。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- Vec4 + - ComposeVec4节点的输出是一个Vec4对象,它将四个输入参数封装成一致的结构。这个输出非常重要,因为它为下游操作中的进一步处理或分析提供了统一的表示,促进了向量数据在计算工作流中的无缝集成。 + - Comfy dtype: VEC4 + - Python dtype: Vec4 + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ComposeVec4: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'x': ('FLOAT', {'default': 0.0}), 'y': ('FLOAT', {'default': 0.0}), 'z': ('FLOAT', {'default': 0.0}), 'w': ('FLOAT', {'default': 0.0})}} + RETURN_TYPES = ('VEC4',) + FUNCTION = 'op' + CATEGORY = 'math/conversion' + + def op(self, x: float, y: float, z: float, w: float) -> tuple[Vec4]: + return ((x, y, z, w),) +``` \ No newline at end of file diff --git a/docs/CM_FloatBinaryCondition.md b/docs/CM_FloatBinaryCondition.md new file mode 100644 index 0000000..4123592 --- /dev/null +++ b/docs/CM_FloatBinaryCondition.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: FloatBinaryCondition +- Category: math/float +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +这个节点提供了一个对浮点数执行二元运算的机制。它旨在基于两个浮点数的比较结果确定一个布尔输出。节点的功能集中在评估数学条件上,从而支持依赖数值阈值的决策过程。 + +# Input types +## Required +- op + - 操作参数定义了要评估的二元条件类型。它是一个关键元素,因为它决定了将在输入浮点数上执行的具体比较或操作。操作的选择直接影响节点的决策能力。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数 'a' 表示二元条件中的第一个操作数。它对节点的操作至关重要,因为它是将被比较或操作的两个值之一。'a' 的值在确定条件检查的结果中起着重要作用。 + - Comfy dtype: float + - Python dtype: float +- b + - 参数 'b' 是二元条件中的第二个操作数。它的重要性与 'a' 相当,因为它是参与比较或操作的第二个值。节点的功能依赖于 'a' 和 'b' 来产生正确的布尔结果。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- result + - 节点的输出是一个布尔值,代表二元条件操作的结果。它表示由 'op' 参数指定的条件对于给定的输入浮点数 'a' 和 'b' 是否成立。 + - Comfy dtype: bool + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FloatBinaryCondition: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(FLOAT_BINARY_CONDITIONS.keys()),), 'a': DEFAULT_FLOAT, 'b': DEFAULT_FLOAT}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/float' + + def op(self, op: str, a: float, b: float) -> tuple[bool]: + return (FLOAT_BINARY_CONDITIONS[op](a, b),) +``` \ No newline at end of file diff --git a/docs/CM_FloatBinaryOperation.md b/docs/CM_FloatBinaryOperation.md new file mode 100644 index 0000000..83e853c --- /dev/null +++ b/docs/CM_FloatBinaryOperation.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: FloatBinaryOperation +- Category: math/float +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +FloatBinaryOperation节点旨在对浮点数执行二元运算。它接收两个输入'a'和'b',应用指定的操作'op'以产生一个单一的浮点结果。此节点对于需要通过二元运算结合两个数字的数学计算至关重要。 + +# Input types +## Required +- op + - 参数'op'指定了要在输入'a'和'b'上执行的二元运算。它至关重要,因为它决定了将应用于输入的数学函数,直接影响节点的输出。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'是二元运算中的第一个操作数。它是输入的重要组成部分,因为它与第二个操作数'b'结合时,对运算的最终结果有所贡献。 + - Comfy dtype: float + - Python dtype: float +- b + - 参数'b'是二元运算中的第二个操作数。它在计算中扮演重要角色,因为它与第一个操作数'a'结合以产生最终结果。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- result + - 参数'result'代表将二元运算'op'应用于输入'a'和'b'的结果。它是一个单一的浮点数,包含了两个操作数的联合效应。 + - Comfy dtype: float + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FloatBinaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(FLOAT_BINARY_OPERATIONS.keys()),), 'a': DEFAULT_FLOAT, 'b': DEFAULT_FLOAT}} + RETURN_TYPES = ('FLOAT',) + FUNCTION = 'op' + CATEGORY = 'math/float' + + def op(self, op: str, a: float, b: float) -> tuple[float]: + return (FLOAT_BINARY_OPERATIONS[op](a, b),) +``` \ No newline at end of file diff --git a/docs/CM_FloatToInt.md b/docs/CM_FloatToInt.md new file mode 100644 index 0000000..cd96fdf --- /dev/null +++ b/docs/CM_FloatToInt.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: FloatToInt +- Category: math/conversion +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +FloatToInt节点旨在将浮点数转换为它们的整数等价物。在需要将精确的小数值转换为整数的情境中,它扮演着至关重要的角色,促进了需要整数输入的操作。 + +# Input types +## Required +- a + - 'a'参数是要被节点转换为整数的浮点数。它对节点的操作至关重要,因为它直接影响输出,决定了转换过程的起始值。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- result + - 'result'输出是输入浮点数的整数表示。它标志着转换过程的结果,提供了一个可以在随后的基于整数的计算中使用的整数。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FloatToInt: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'a': ('FLOAT', {'default': 0.0})}} + RETURN_TYPES = ('INT',) + FUNCTION = 'op' + CATEGORY = 'math/conversion' + + def op(self, a: float) -> tuple[int]: + return (int(a),) +``` \ No newline at end of file diff --git a/docs/CM_FloatToNumber.md b/docs/CM_FloatToNumber.md new file mode 100644 index 0000000..e9f9059 --- /dev/null +++ b/docs/CM_FloatToNumber.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: FloatToNumber +- Category: math/conversion +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +FloatToNumber节点旨在将浮点数值转换为更通用的数字表示形式。它在数据类型转换中扮演着关键角色,确保了数学或计算工作流程的不同部分之间的兼容性。 + +# Input types +## Required +- a + - 'a'参数是一个浮点数,该节点旨在进行转换。它对节点的操作至关重要,因为它决定了需要转换的输入数据类型。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- result + - 'result'输出是由输入浮点值转换得到的数字。它标志着从特定数据类型成功转换为更通用的数字形式。 + - Comfy dtype: NUMBER + - Python dtype: number + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FloatToNumber: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'a': ('FLOAT', {'default': 0.0})}} + RETURN_TYPES = ('NUMBER',) + FUNCTION = 'op' + CATEGORY = 'math/conversion' + + def op(self, a: float) -> tuple[number]: + return (a,) +``` \ No newline at end of file diff --git a/docs/CM_FloatUnaryCondition.md b/docs/CM_FloatUnaryCondition.md new file mode 100644 index 0000000..264e18c --- /dev/null +++ b/docs/CM_FloatUnaryCondition.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: FloatUnaryCondition +- Category: math/float +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +该节点旨在对浮点数评估一个单操作数数学条件。它提供了一种执行条件检查的方法,例如检查一个数字是否为正数、负数或零,而无需在代码中直接实现逻辑。 + +# Input types +## Required +- op + - 操作参数定义了要应用于输入浮点数的单操作数条件。它至关重要,因为它决定了将对输入值执行的检查类型。 + - Comfy dtype: str + - Python dtype: str +- a + - 'a' 参数代表将评估单操作数条件的浮点数。它至关重要,因为整个操作都围绕这个值进行。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- result + - 操作的结果是一个布尔值,指示应用于输入浮点数的单操作数条件是真还是假。 + - Comfy dtype: bool + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FloatUnaryCondition: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(FLOAT_UNARY_CONDITIONS.keys()),), 'a': DEFAULT_FLOAT}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/float' + + def op(self, op: str, a: float) -> tuple[bool]: + return (FLOAT_UNARY_CONDITIONS[op](a),) +``` \ No newline at end of file diff --git a/docs/CM_FloatUnaryOperation.md b/docs/CM_FloatUnaryOperation.md new file mode 100644 index 0000000..ed76388 --- /dev/null +++ b/docs/CM_FloatUnaryOperation.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: FloatUnaryOperation +- Category: math/float +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +FloatUnaryOperation节点对单个浮点数应用数学运算,将其转换为另一个浮点值。它旨在处理各种一元运算,使其在数据处理流程中用于数学计算非常灵活。 + +# Input types +## Required +- op + - 参数'op'指定要执行的一元数学运算。它至关重要,因为它决定了应用于输入浮点值的转换类型。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'表示将应用一元运算的输入浮点值。它是节点操作的基本组成部分,因为它是数学变换的主题。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- result + - 输出'result'提供了应用指定一元运算后的转换浮点值。它很重要,因为它代表了节点执行的数学计算的结果。 + - Comfy dtype: float + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FloatUnaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(FLOAT_UNARY_OPERATIONS.keys()),), 'a': DEFAULT_FLOAT}} + RETURN_TYPES = ('FLOAT',) + FUNCTION = 'op' + CATEGORY = 'math/float' + + def op(self, op: str, a: float) -> tuple[float]: + return (FLOAT_UNARY_OPERATIONS[op](a),) +``` \ No newline at end of file diff --git a/docs/CM_IntBinaryCondition.md b/docs/CM_IntBinaryCondition.md new file mode 100644 index 0000000..4d990cf --- /dev/null +++ b/docs/CM_IntBinaryCondition.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: IntBinaryCondition +- Category: math/int +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +IntBinaryCondition节点旨在评估两个整数值之间的二元条件。它通过将指定的操作应用于输入并确定结果条件的真值来工作。该节点在数学计算中的决策过程至关重要,其中的结果是依赖于两个整数之间的关系。 + +# Input types +## Required +- op + - 参数'op'定义了要在整数输入上执行的二元操作。它至关重要,因为它决定了正在评估的条件的性质。操作的选择直接影响节点在数学上下文中的决策能力。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'代表二元条件中的第一个整数。它的值很重要,因为它有助于条件评估的结果。整数'a'在节点的决策过程中起着关键作用。 + - Comfy dtype: int + - Python dtype: int +- b + - 参数'b'表示二元条件中涉及的第二个整数。它至关重要,因为它与'a'一起决定了条件的最终结果。整数'b'是节点评估过程中的一个关键因素。 + - Comfy dtype: int + - Python dtype: int + +# Output types +- result + - 'result'输出表示节点评估的二元条件的布尔结果。它很重要,因为它代表了条件的真值,可以用于数学或逻辑工作流中的进一步处理或决策。 + - Comfy dtype: bool + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IntBinaryCondition: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(INT_BINARY_CONDITIONS.keys()),), 'a': DEFAULT_INT, 'b': DEFAULT_INT}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/int' + + def op(self, op: str, a: int, b: int) -> tuple[bool]: + return (INT_BINARY_CONDITIONS[op](a, b),) +``` \ No newline at end of file diff --git a/docs/CM_IntBinaryOperation.md b/docs/CM_IntBinaryOperation.md new file mode 100644 index 0000000..1699ab0 --- /dev/null +++ b/docs/CM_IntBinaryOperation.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: IntBinaryOperation +- Category: math/int +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +IntBinaryOperation节点旨在执行各种整数二元运算。它接收两个整数和一个表示要执行的操作的字符串,并返回操作的结果。此节点对于涉及整数的数学计算至关重要,为以编程方式执行基本算术运算提供了一种直接的方法。 + +# Input types +## Required +- op + - 参数'op'是一个字符串,指定要在两个整数上执行的二元运算。它非常重要,因为它决定了将执行的算术运算类型。操作的选择直接影响节点执行的结果。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'代表二元运算中的第一个操作数。作为运算的一个整体部分,它在数学计算中扮演着重要角色。'a'的值直接影响操作的最终结果。 + - Comfy dtype: int + - Python dtype: int +- b + - 参数'b'表示二元运算中的第二个操作数。它对于完成运算并获得正确结果至关重要。'b'的值与'a'一样,在影响计算结果方面同样重要。 + - Comfy dtype: int + - Python dtype: int + +# Output types +- result + - 参数'result'是节点执行的二元运算的结果。它包含了基于输入操作数和指定操作计算出的最终值,是节点的主要输出。 + - Comfy dtype: int + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IntBinaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(INT_BINARY_OPERATIONS.keys()),), 'a': DEFAULT_INT, 'b': DEFAULT_INT}} + RETURN_TYPES = ('INT',) + FUNCTION = 'op' + CATEGORY = 'math/int' + + def op(self, op: str, a: int, b: int) -> tuple[int]: + return (INT_BINARY_OPERATIONS[op](a, b),) +``` \ No newline at end of file diff --git a/docs/CM_IntToBool.md b/docs/CM_IntToBool.md new file mode 100644 index 0000000..7cc11f8 --- /dev/null +++ b/docs/CM_IntToBool.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: IntToBool +- Category: math/conversion +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +IntToBool节点旨在将整数值转换为布尔表示。在数值的存在与否至关重要的情况下,它作为一个基本的实用工具,从数值数据中抽象出真值概念。此节点在数据类型转换中扮演着关键角色,确保数值输入在布尔上下文中得到适当的解释。 + +# Input types +## Required +- a + - 参数'a'是节点将处理的输入整数。它对节点的操作至关重要,因为它根据值是否非零来确定布尔输出。此参数直接影响节点的执行和生成的布尔值。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- op + - 'op'输出是一个布尔值,表示输入整数的真值。它之所以重要,是因为它在布尔上下文中提供了对数值输入的清晰和直接的解释,这通常在系统的进一步处理或决策中是必需的。 + - Comfy dtype: BOOL + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IntToBool: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'a': ('INT', {'default': 0})}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/conversion' + + def op(self, a: int) -> tuple[bool]: + return (a != 0,) +``` \ No newline at end of file diff --git a/docs/CM_IntToFloat.md b/docs/CM_IntToFloat.md new file mode 100644 index 0000000..216f1d4 --- /dev/null +++ b/docs/CM_IntToFloat.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: IntToFloat +- Category: math/conversion +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +IntToFloat节点旨在将整数值转换为其浮点数等价物。它在数值运算中扮演着关键角色,确保在需要准确结果的情况下进行计算时数据类型保持一致,从而保证了计算的精度。 + +# Input types +## Required +- a + - 参数'a'表示要转换为浮点数的整数值。它对节点的操作至关重要,因为它决定了转换过程的起始点。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result + - 输出'result'是输入整数的浮点表示。它很重要,因为它提供了可以用于后续数值计算的转换后的值。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IntToFloat: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'a': ('INT', {'default': 0})}} + RETURN_TYPES = ('FLOAT',) + FUNCTION = 'op' + CATEGORY = 'math/conversion' + + def op(self, a: int) -> tuple[float]: + return (float(a),) +``` \ No newline at end of file diff --git a/docs/CM_IntToNumber.md b/docs/CM_IntToNumber.md new file mode 100644 index 0000000..050d6d7 --- /dev/null +++ b/docs/CM_IntToNumber.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: IntToNumber +- Category: math/conversion +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +该节点将整数输入转换为适合进一步处理的数字格式,强调在计算工作流中数据类型转换的重要性。 + +# Input types +## Required +- a + - 参数'a'是一个关键的输入,它为节点提供整数值。正确输入对于节点准确执行转换和影响最终结果至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result + - 该节点的输出是输入整数的数字表示形式,对于需要数值数据的后续操作至关重要。 + - Comfy dtype: NUMBER + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IntToNumber: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'a': ('INT', {'default': 0})}} + RETURN_TYPES = ('NUMBER',) + FUNCTION = 'op' + CATEGORY = 'math/conversion' + + def op(self, a: int) -> tuple[number]: + return (a,) +``` \ No newline at end of file diff --git a/docs/CM_IntUnaryCondition.md b/docs/CM_IntUnaryCondition.md new file mode 100644 index 0000000..7ebab39 --- /dev/null +++ b/docs/CM_IntUnaryCondition.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: IntUnaryCondition +- Category: math/int +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +IntUnaryCondition节点旨在根据一组一元条件评估单个整数。它是更复杂数学操作的基本构建块,允许确定一个整数是否满足特定条件,而不会改变其值。 + +# Input types +## Required +- op + - 参数'op'是一个字符串,定义了要检查整数'a'的一元条件。它对节点的操作至关重要,因为它决定了要评估的具体条件。 + - Comfy dtype: STRING + - Python dtype: str +- a + - 参数'a'表示将根据参数'op'指定的一元条件进行评估的整数。它是节点的一个基本输入,因为它是条件检查的对象。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- BOOL + - IntUnaryCondition节点的输出是一个布尔值,指示整数'a'是否满足由'op'指定的一元条件。这个结果对于后续操作中的决策过程很重要。 + - Comfy dtype: BOOL + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IntUnaryCondition: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(INT_UNARY_CONDITIONS.keys()),), 'a': DEFAULT_INT}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/int' + + def op(self, op: str, a: int) -> tuple[bool]: + return (INT_UNARY_CONDITIONS[op](a),) +``` \ No newline at end of file diff --git a/docs/CM_IntUnaryOperation.md b/docs/CM_IntUnaryOperation.md new file mode 100644 index 0000000..cc36876 --- /dev/null +++ b/docs/CM_IntUnaryOperation.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: IntUnaryOperation +- Category: math/int +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +IntUnaryOperation节点旨在对整数输入执行多种一元运算,提供一种灵活高效的方式来操作数值数据。它强调了节点通过一组预定义的数学运算来转换整数值的能力,而不改变输入的基本性质。 + +# Input types +## Required +- op + - 参数'op'至关重要,因为它决定了要应用于整数输入的特定一元运算。它通过指定将使用的数学函数,影响节点的执行,从而影响操作的结果。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'代表一元运算的整数输入。它的值直接影响操作的结果,因为它是所有数学函数将应用的操作数。 + - Comfy dtype: int + - Python dtype: int + +# Output types +- result + - 输出参数'result'表示将一元运算应用于输入整数的结果。它封装了操作后转换的值,反映了节点的主要功能——数值操作。 + - Comfy dtype: int + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IntUnaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(INT_UNARY_OPERATIONS.keys()),), 'a': DEFAULT_INT}} + RETURN_TYPES = ('INT',) + FUNCTION = 'op' + CATEGORY = 'math/int' + + def op(self, op: str, a: int) -> tuple[int]: + return (INT_UNARY_OPERATIONS[op](a),) +``` \ No newline at end of file diff --git a/docs/CM_NearestSDXLResolution.md b/docs/CM_NearestSDXLResolution.md new file mode 100644 index 0000000..137b23b --- /dev/null +++ b/docs/CM_NearestSDXLResolution.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: NearestSDXLResolution +- Category: math/graphics +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +NearestSDXLResolution节点旨在选择与输入图像分辨率最接近的受支持分辨率。它通过计算输入图像的宽高比并将其与支持的分辨率列表进行比较,然后选择差异最小的分辨率来实现这一点。该节点的功能对于确保图形处理应用中的兼容性和最佳显示质量至关重要。 + +# Input types +## Required +- image + - 'image'参数至关重要,因为它作为节点的输入。这是其分辨率要与支持的分辨率匹配的图像。节点的操作完全依赖于这个输入,因为它决定了最近支持分辨率的选择。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- width + - 'width'参数表示所选分辨率的宽度。它是一个关键的输出,因为它定义了分辨率匹配过程后图像的水平维度。对于依赖图像尺寸的任何后续图形操作来说,这个输出非常重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 'height'参数表示所选分辨率的高度。与'width'参数类似,它是一个重要的输出,它为进一步处理确定了图像的垂直维度。它确保了分辨率选择后图像的宽高比得以保持。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class NearestSDXLResolution: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'image': ('IMAGE',)}} + RETURN_TYPES = ('INT', 'INT') + RETURN_NAMES = ('width', 'height') + FUNCTION = 'op' + CATEGORY = 'math/graphics' + + def op(self, image) -> tuple[int, int]: + image_width = image.size()[2] + image_height = image.size()[1] + print(f'Input image resolution: {image_width}x{image_height}') + image_ratio = image_width / image_height + differences = [(abs(image_ratio - resolution[2]), resolution) for resolution in SDXL_SUPPORTED_RESOLUTIONS] + smallest = None + for difference in differences: + if smallest is None: + smallest = difference + elif difference[0] < smallest[0]: + smallest = difference + if smallest is not None: + width = smallest[1][0] + height = smallest[1][1] + else: + width = 1024 + height = 1024 + print(f'Selected SDXL resolution: {width}x{height}') + return (width, height) +``` \ No newline at end of file diff --git a/docs/CM_NumberBinaryCondition.md b/docs/CM_NumberBinaryCondition.md new file mode 100644 index 0000000..423b2f1 --- /dev/null +++ b/docs/CM_NumberBinaryCondition.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: NumberBinaryCondition +- Category: math/float +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +`NumberBinaryCondition` 节点旨在评估两个数字输入之间的二元条件。它执行用户指定的比较操作,并返回一个布尔结果,指示条件的结果。 + +# Input types +## Required +- op + - 参数 'op' 定义了要评估的二元条件。它至关重要,因为它决定了两个数字之间执行的比较类型。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数 'a' 表示二元条件中的第一个数字。它起着重要作用,因为它是比较操作中的一个操作数。 + - Comfy dtype: number + - Python dtype: Union[int, float] +- b + - 参数 'b' 表示二元条件中的第二个数字。它至关重要,因为它是另一个比较操作中的操作数。 + - Comfy dtype: number + - Python dtype: Union[int, float] + +# Output types +- result + - 输出 'result' 提供了二元条件评估的布尔结果,指示条件是成立还是不成立。 + - Comfy dtype: bool + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class NumberBinaryCondition: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(FLOAT_BINARY_CONDITIONS.keys()),), 'a': DEFAULT_NUMBER, 'b': DEFAULT_NUMBER}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/float' + + def op(self, op: str, a: number, b: number) -> tuple[bool]: + return (FLOAT_BINARY_CONDITIONS[op](float(a), float(b)),) +``` \ No newline at end of file diff --git a/docs/CM_NumberBinaryOperation.md b/docs/CM_NumberBinaryOperation.md new file mode 100644 index 0000000..23f2cbe --- /dev/null +++ b/docs/CM_NumberBinaryOperation.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: NumberBinaryOperation +- Category: math/number +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +NumberBinaryOperation 节点旨在对数值输入执行二元运算。它封装了各种可以在两个数字之间应用的算术运算,在一个简化的接口中促进复杂的数学计算。 + +# Input types +## Required +- op + - 参数 'op' 决定了要执行的具体二元运算。它至关重要,因为它决定了节点将执行的数学函数,从而影响计算的结果。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数 'a' 表示二元运算中的第一个操作数。它至关重要,因为它构成了算术计算所需的一半输入。 + - Comfy dtype: number + - Python dtype: Union[int, float] +- b + - 参数 'b' 表示二元运算中的第二个操作数。它至关重要,因为它完成了算术过程所需的输入集。 + - Comfy dtype: number + - Python dtype: Union[int, float] + +# Output types +- result + - 输出 'result' 提供了在输入 'a' 和 'b' 上执行的二元运算的结果。它很重要,因为它代表了从指定操作派生的最终计算值。 + - Comfy dtype: float + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class NumberBinaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(FLOAT_BINARY_OPERATIONS.keys()),), 'a': DEFAULT_NUMBER, 'b': DEFAULT_NUMBER}} + RETURN_TYPES = ('NUMBER',) + FUNCTION = 'op' + CATEGORY = 'math/number' + + def op(self, op: str, a: number, b: number) -> tuple[float]: + return (FLOAT_BINARY_OPERATIONS[op](float(a), float(b)),) +``` \ No newline at end of file diff --git a/docs/CM_NumberToFloat.md b/docs/CM_NumberToFloat.md new file mode 100644 index 0000000..2a46105 --- /dev/null +++ b/docs/CM_NumberToFloat.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: NumberToFloat +- Category: math/conversion +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +NumberToFloat节点旨在将输入数字转换为浮点格式。它在确保不同数据类型之间的数值计算保持精度和一致性中发挥着关键作用。 + +# Input types +## Required +- a + - 'a'参数是节点打算转换为浮点值的输入数字。它对节点的操作至关重要,因为它直接影响输出的数值表示。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float, str] + +# Output types +- result + - 'result'输出是从输入派生的转换后的浮点数。它很重要,因为它代表了节点的主要输出和转换过程的最终结果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class NumberToFloat: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'a': ('NUMBER', {'default': 0.0})}} + RETURN_TYPES = ('FLOAT',) + FUNCTION = 'op' + CATEGORY = 'math/conversion' + + def op(self, a: number) -> tuple[float]: + return (float(a),) +``` \ No newline at end of file diff --git a/docs/CM_NumberToInt.md b/docs/CM_NumberToInt.md new file mode 100644 index 0000000..b7b9c2d --- /dev/null +++ b/docs/CM_NumberToInt.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: NumberToInt +- Category: math/conversion +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +NumberToInt节点旨在将数值输入转换为整数形式。在不需要浮点数的精度且更倾向于整数的简单性和效率的场景中,它发挥着关键作用。 + +# Input types +## Required +- a + - 'a'参数是节点将转换为整数的数值输入。它对节点的操作至关重要,因为它决定了转换过程的起点。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float] + +# Output types +- op + - 'op'输出提供了输入参数'a'的整数转换。它很重要,因为它代表了可以用于进一步处理的最终转换值。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class NumberToInt: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'a': ('NUMBER', {'default': 0.0})}} + RETURN_TYPES = ('INT',) + FUNCTION = 'op' + CATEGORY = 'math/conversion' + + def op(self, a: number) -> tuple[int]: + return (int(a),) +``` \ No newline at end of file diff --git a/docs/CM_NumberUnaryCondition.md b/docs/CM_NumberUnaryCondition.md new file mode 100644 index 0000000..9ed6396 --- /dev/null +++ b/docs/CM_NumberUnaryCondition.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: NumberUnaryCondition +- Category: math/number +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +`NumberUnaryCondition` 节点旨在评估单个操作数与一组一元条件之间的关系,确定在数学上下文中条件的有效性。它作为更复杂数值运算的基本构建块,确保在进行进一步计算之前满足数值条件。 + +# Input types +## Required +- op + - 参数 'op' 定义了要应用于操作数 'a' 的一元条件。它至关重要,因为它决定了将执行的数学条件检查类型,直接影响节点的输出。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数 'a' 表示将应用一元条件的操作数。它的值至关重要,因为它是条件检查的对象,决定了节点评估的结果。 + - Comfy dtype: number + - Python dtype: Union[int, float] + +# Output types +- result + - 输出 'result' 表示一元条件检查的结果。它是一个布尔值,指示操作数 'a' 是否满足由 'op' 定义的条件。 + - Comfy dtype: bool + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class NumberUnaryCondition: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(FLOAT_UNARY_CONDITIONS.keys()),), 'a': DEFAULT_NUMBER}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/number' + + def op(self, op: str, a: number) -> tuple[bool]: + return (FLOAT_UNARY_CONDITIONS[op](float(a)),) +``` \ No newline at end of file diff --git a/docs/CM_NumberUnaryOperation.md b/docs/CM_NumberUnaryOperation.md new file mode 100644 index 0000000..3760832 --- /dev/null +++ b/docs/CM_NumberUnaryOperation.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: NumberUnaryOperation +- Category: math/number +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +NumberUnaryOperation节点旨在对数值输入执行各种一元运算。它接受一个单一的操作标识符和一个数值,将相应的数学函数应用于生成结果。此节点在工作流程中简化数学计算中起着关键作用,提供了一种简洁高效的方式来处理数值数据。 + +# Input types +## Required +- op + - 参数'op'是一个字符串,指定要执行的一元运算。它对于确定将应用于输入数字的数学函数至关重要。操作的选择直接影响节点执行的结果。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'代表将应用一元运算的数值。它是节点功能的重要组成部分,因为操作的结果取决于这个输入值。该参数确保节点可以处理广泛的数值数据类型。 + - Comfy dtype: number + - Python dtype: Union[int, float] + +# Output types +- result + - 'result'输出参数代表将一元运算应用于输入数字的结果。它包含了操作执行后得到的最终数值,标志着节点对数据处理序列的贡献。 + - Comfy dtype: float + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class NumberUnaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(FLOAT_UNARY_OPERATIONS.keys()),), 'a': DEFAULT_NUMBER}} + RETURN_TYPES = ('NUMBER',) + FUNCTION = 'op' + CATEGORY = 'math/number' + + def op(self, op: str, a: number) -> tuple[float]: + return (FLOAT_UNARY_OPERATIONS[op](float(a)),) +``` \ No newline at end of file diff --git a/docs/CM_SDXLResolution.md b/docs/CM_SDXLResolution.md new file mode 100644 index 0000000..a3b083b --- /dev/null +++ b/docs/CM_SDXLResolution.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: SDXLResolution +- Category: math/graphics +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +该节点旨在解析分辨率字符串并将其转换为相应的宽度和高度的整数值。它在确保图形输出遵循指定尺寸方面发挥关键作用,促进视觉元素在系统中的无缝集成。 + +# Input types +## Required +- resolution + - 分辨率参数至关重要,因为它定义了图形输出的尺寸。预期它是一个格式为'宽度x高度'的字符串,节点随后将将其分解为单独的宽度和高度值。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- width + - 宽度输出参数代表图形分辨率的水平维度。它很重要,因为它直接影响应用程序或显示中视觉内容的缩放和布局。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度输出参数表示图形分辨率的垂直维度。它对于确定视觉内容的垂直范围和确保适当的显示格式至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLResolution: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'resolution': ([f'{res[0]}x{res[1]}' for res in SDXL_SUPPORTED_RESOLUTIONS],)}} + RETURN_TYPES = ('INT', 'INT') + RETURN_NAMES = ('width', 'height') + FUNCTION = 'op' + CATEGORY = 'math/graphics' + + def op(self, resolution: str) -> tuple[int, int]: + (width, height) = resolution.split('x') + return (int(width), int(height)) +``` \ No newline at end of file diff --git a/docs/CM_Vec2BinaryCondition.md b/docs/CM_Vec2BinaryCondition.md new file mode 100644 index 0000000..d07794c --- /dev/null +++ b/docs/CM_Vec2BinaryCondition.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: Vec2BinaryCondition +- Category: math/vec2 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec2BinaryCondition节点旨在对二维向量执行二元运算,提供一种比较和评估基于指定条件的向量对的方法。它在数学运算中非常重要,其中结果是一个布尔值,表示应用的二元条件的结果。 + +# Input types +## Required +- op + - 参数'op'定义了要应用于向量输入的二元条件。它至关重要,因为它决定了执行的比较或操作的性质,直接影响节点的输出。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'代表二元操作中的第一个向量。它至关重要,因为它构成了比较或操作的一半,节点的功能取决于此向量中的值。 + - Comfy dtype: Vec2 + - Python dtype: Vec2 +- b + - 参数'b'表示二元操作中涉及的第二个向量。它很重要,因为它完成了操作所需的配对,节点的有效性依赖于'a'和'b'之间的相互作用。 + - Comfy dtype: Vec2 + - Python dtype: Vec2 + +# Output types +- result + - 输出'result'表示应用于输入向量的二元条件的结果。它是一个布尔值,包含了条件检查的成功或失败。 + - Comfy dtype: BOOL + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec2BinaryCondition: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_BINARY_CONDITIONS.keys()),), 'a': DEFAULT_VEC2, 'b': DEFAULT_VEC2}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/vec2' + + def op(self, op: str, a: Vec2, b: Vec2) -> tuple[bool]: + return (VEC_BINARY_CONDITIONS[op](numpy.array(a), numpy.array(b)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec2BinaryOperation.md b/docs/CM_Vec2BinaryOperation.md new file mode 100644 index 0000000..fec1e00 --- /dev/null +++ b/docs/CM_Vec2BinaryOperation.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: Vec2BinaryOperation +- Category: math/vec2 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec2BinaryOperation节点旨在对二维向量执行二元运算。它能够处理各种向量运算,如加法、减法、乘法和除法,为应用程序内的向量数学提供了多功能工具。此节点在操作向量数据中扮演着关键角色,使用户能够轻松而精确地执行复杂计算。 + +# Input types +## Required +- op + - 参数'op'定义了要在输入向量上执行的二元运算类型。它对于确定节点将执行的数学运算至关重要,从而直接影响计算结果。运算的选择可以显著影响结果以及随后的分析或处理步骤。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'代表二元运算中的第一个向量。它是一个必要的输入,因为它构成了向量运算所需的一半操作数。向量'a'的值和特性将极大地影响计算的最终结果,使其成为节点功能中的关键要素。 + - Comfy dtype: Vec2 + - Python dtype: Tuple[float, float] +- b + - 参数'b'表示参与二元运算的第二个向量。与'a'一样,它是一个必需的输入,它完成了向量运算所需的操作数集合。向量'b'中的属性和值对计算过程以及节点产生准确和有意义的结果的能力至关重要。 + - Comfy dtype: Vec2 + - Python dtype: Tuple[float, float] + +# Output types +- result + - 输出参数'result'包含了对输入向量执行的二元运算的结果。它是一个关键的输出,因为它传达了最终计算的值,代表了节点在计算工作流程中的主要功能和目的。 + - Comfy dtype: Vec2 + - Python dtype: Tuple[float, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec2BinaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_BINARY_OPERATIONS.keys()),), 'a': DEFAULT_VEC2, 'b': DEFAULT_VEC2}} + RETURN_TYPES = ('VEC2',) + FUNCTION = 'op' + CATEGORY = 'math/vec2' + + def op(self, op: str, a: Vec2, b: Vec2) -> tuple[Vec2]: + return (_vec2_from_numpy(VEC_BINARY_OPERATIONS[op](numpy.array(a), numpy.array(b))),) +``` \ No newline at end of file diff --git a/docs/CM_Vec2ScalarOperation.md b/docs/CM_Vec2ScalarOperation.md new file mode 100644 index 0000000..17c64e9 --- /dev/null +++ b/docs/CM_Vec2ScalarOperation.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: Vec2ScalarOperation +- Category: math/vec2 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec2ScalarOperation节点旨在执行二维向量(Vec2)和标量(float)之间的各种数学运算。它封装了应用各种向量-标量操作的功能,这些操作在计算几何和线性代数中至关重要。此节点在数学上下文中操纵向量数据中发挥关键作用。 + +# Input types +## Required +- op + - ‘op’参数指定要在向量和标量之间执行的数学运算类型。它对于确定节点将执行的计算性质至关重要。运算的选择直接影响向量-标量交互的结果。 + - Comfy dtype: str + - Python dtype: str +- a + - ‘a’参数表示将在运算中使用的二维向量(Vec2)。作为一个基本输入,它对数学过程至关重要,并且直接促成了计算的最终结果。根据指定的运算,向量的分量将被操作。 + - Comfy dtype: Vec2 + - Python dtype: Tuple[float, float] +- b + - ‘b’参数是将与向量‘a’一起用于运算的标量值。它的重要性在于它作为乘数或运算数在向量-标量运算中的作用,影响计算的最终结果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- result + - ‘result’输出是应用了指定运算后的变换二维向量(Vec2)。它代表了向量-标量计算的最终结果,直接反映了输入参数和所选运算。 + - Comfy dtype: VEC2 + - Python dtype: Tuple[float, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec2ScalarOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_SCALAR_OPERATION.keys()),), 'a': DEFAULT_VEC2, 'b': ('FLOAT',)}} + RETURN_TYPES = ('VEC2',) + FUNCTION = 'op' + CATEGORY = 'math/vec2' + + def op(self, op: str, a: Vec2, b: float) -> tuple[Vec2]: + return (_vec2_from_numpy(VEC_SCALAR_OPERATION[op](numpy.array(a), b)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec2ToScalarBinaryOperation.md b/docs/CM_Vec2ToScalarBinaryOperation.md new file mode 100644 index 0000000..63f9f30 --- /dev/null +++ b/docs/CM_Vec2ToScalarBinaryOperation.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: Vec2ToScalarBinaryOperation +- Category: math/vec2 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec2ToScalarBinaryOperation节点旨在对二维向量执行二元运算,将其转换为标量值。它将向量算术的本质封装在单一操作中,提供了一种简化的方式来操作向量数据并派生出有意义的标量输出。 + +# Input types +## Required +- op + - 参数'op'至关重要,因为它决定了要在输入向量上执行的二元运算类型。它决定了将应用的数学逻辑,从而影响最终的标量结果。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'表示二元运算中的第一个向量。它是节点功能的一个基本组成部分,因为运算的结果取决于此向量内的值。 + - Comfy dtype: Vec2 + - Python dtype: numpy.ndarray +- b + - 参数'b'表示参与二元运算的第二个向量。它的值在形成操作结果方面同样重要,确保对向量对进行全面分析。 + - Comfy dtype: Vec2 + - Python dtype: numpy.ndarray + +# Output types +- result + - 'result'输出是从输入向量上执行的二元运算派生的标量值。它是节点处理的最终结果,代表了数学运算后的最终输出。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec2ToScalarBinaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_TO_SCALAR_BINARY_OPERATION.keys()),), 'a': DEFAULT_VEC2, 'b': DEFAULT_VEC2}} + RETURN_TYPES = ('FLOAT',) + FUNCTION = 'op' + CATEGORY = 'math/vec2' + + def op(self, op: str, a: Vec2, b: Vec2) -> tuple[float]: + return (VEC_TO_SCALAR_BINARY_OPERATION[op](numpy.array(a), numpy.array(b)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec2ToScalarUnaryOperation.md b/docs/CM_Vec2ToScalarUnaryOperation.md new file mode 100644 index 0000000..88ee495 --- /dev/null +++ b/docs/CM_Vec2ToScalarUnaryOperation.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: Vec2ToScalarUnaryOperation +- Category: math/vec2 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec2ToScalarUnaryOperation节点旨在对二维向量执行多种一元运算,将其转换为标量值。它封装了可以应用于向量的数学运算,强调了该节点在数学计算中向量-标量转换的作用。 + +# Input types +## Required +- op + - 参数'op'定义了要在向量'a'上执行的一元运算。它至关重要,因为它决定了将应用的特定数学函数,从而影响节点执行的结果。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'表示将要在其上执行一元运算的二维向量。它的重要性在于它是节点操作以产生标量结果的主要输入。 + - Comfy dtype: Vec2 + - Python dtype: numpy.ndarray + +# Output types +- result + - 输出'result'是将指定的一元运算应用于输入向量'a'后获得的标量值。它标志着节点数学处理的结果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec2ToScalarUnaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_TO_SCALAR_UNARY_OPERATION.keys()),), 'a': DEFAULT_VEC2}} + RETURN_TYPES = ('FLOAT',) + FUNCTION = 'op' + CATEGORY = 'math/vec2' + + def op(self, op: str, a: Vec2) -> tuple[float]: + return (VEC_TO_SCALAR_UNARY_OPERATION[op](numpy.array(a)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec2UnaryCondition.md b/docs/CM_Vec2UnaryCondition.md new file mode 100644 index 0000000..f45ea90 --- /dev/null +++ b/docs/CM_Vec2UnaryCondition.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: Vec2UnaryCondition +- Category: math/vec2 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec2UnaryCondition节点旨在对二维向量执行各种一元操作。它对向量的每个元素应用指定的条件,并返回一个布尔结果,指示每个元素操作的结果。 + +# Input types +## Required +- op + - 参数'op'定义了将应用于向量元素的一元条件。它对于确定操作的性质和预期结果至关重要。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'代表将在其上评估一元条件的二维向量。它是节点执行的关键,因为它为操作提供了输入数据。 + - Comfy dtype: Vec2 + - Python dtype: Vec2 + +# Output types +- result + - 输出'result'是一个布尔值的元组,对应于对输入向量每个元素的一元条件的评估。 + - Comfy dtype: tuple[bool] + - Python dtype: Tuple[bool] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec2UnaryCondition: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_UNARY_CONDITIONS.keys()),), 'a': DEFAULT_VEC2}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/vec2' + + def op(self, op: str, a: Vec2) -> tuple[bool]: + return (VEC_UNARY_CONDITIONS[op](numpy.array(a)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec2UnaryOperation.md b/docs/CM_Vec2UnaryOperation.md new file mode 100644 index 0000000..776584d --- /dev/null +++ b/docs/CM_Vec2UnaryOperation.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: Vec2UnaryOperation +- Category: math/vec2 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec2UnaryOperation节点旨在对二维向量执行多种一元运算。它接受一个操作作为输入,该操作是一个字符串,表示一个数学函数,并将该函数应用于向量'a',从而得到一个变换后的向量。此节点在数学和计算上下文中的向量代数中至关重要,其中可能需要进行否定、反转或绝对值等运算。 + +# Input types +## Required +- op + - 参数'op'指定要应用于向量'a'的一元运算。它是一个字符串,对应于一个预定义的数学函数。此参数至关重要,因为它决定了输入向量将经历的变换的性质。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'是二维向量,将要应用一元运算。这是一个关键的输入,因为整个运算都是围绕根据指定的数学函数变换这个向量进行的。 + - Comfy dtype: VEC2 + - Python dtype: Tuple[float, float] + +# Output types +- result + - 输出'result'是在输入向量'a'上应用由'op'指定的一元运算后的变换向量。它代表了数学变换的结果,是Vec2UnaryOperation节点的主要输出。 + - Comfy dtype: VEC2 + - Python dtype: Tuple[float, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec2UnaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_UNARY_OPERATIONS.keys()),), 'a': DEFAULT_VEC2}} + RETURN_TYPES = ('VEC2',) + FUNCTION = 'op' + CATEGORY = 'math/vec2' + + def op(self, op: str, a: Vec2) -> tuple[Vec2]: + return (_vec2_from_numpy(VEC_UNARY_OPERATIONS[op](numpy.array(a))),) +``` \ No newline at end of file diff --git a/docs/CM_Vec3BinaryCondition.md b/docs/CM_Vec3BinaryCondition.md new file mode 100644 index 0000000..50c3c33 --- /dev/null +++ b/docs/CM_Vec3BinaryCondition.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: Vec3BinaryCondition +- Category: math/vec3 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec3BinaryCondition节点旨在对两个三维向量执行二元运算。它评估由'op'参数指定的条件,并返回一个布尔结果,指示给定向量'a'和'b'的条件是否成立。 + +# Input types +## Required +- op + - 参数'op'定义了要评估的二元条件类型。它至关重要,因为它决定了将在输入向量上执行的具体操作。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'代表参与二元运算的第一个三维向量。它的值对条件评估的结果有显著影响。 + - Comfy dtype: Vec3 + - Python dtype: numpy.ndarray +- b + - 参数'b'代表二元运算中的第二个三维向量。它与'a'一起工作,以确定条件检查的结果。 + - Comfy dtype: Vec3 + - Python dtype: numpy.ndarray + +# Output types +- result + - 'result'输出是一个布尔值,表示由'op'参数指定的二元条件是否由输入向量'a'和'b'满足。 + - Comfy dtype: BOOL + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec3BinaryCondition: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_BINARY_CONDITIONS.keys()),), 'a': DEFAULT_VEC3, 'b': DEFAULT_VEC3}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/vec3' + + def op(self, op: str, a: Vec3, b: Vec3) -> tuple[bool]: + return (VEC_BINARY_CONDITIONS[op](numpy.array(a), numpy.array(b)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec3BinaryOperation.md b/docs/CM_Vec3BinaryOperation.md new file mode 100644 index 0000000..f497895 --- /dev/null +++ b/docs/CM_Vec3BinaryOperation.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: Vec3BinaryOperation +- Category: math/vec3 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec3BinaryOperation节点旨在对两个三维向量执行二元运算。它是向量数学的基础构建块,允许执行加法、减法和标量乘法等操作。在几何计算中,该节点对于建模和分析至关重要,其中向量运算是必不可少的。 + +# Input types +## Required +- op + - 参数'op'指定在输入向量上执行的二元运算。它是一组预定义的向量操作中的一个键,对于确定节点将执行的计算类型至关重要。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'表示操作中的第一个三维向量。它是一个基本输入,直接影响节点执行的二元运算的结果。 + - Comfy dtype: tuple[float, float, float] + - Python dtype: Tuple[float, float, float] +- b + - 参数'b'表示参与二元运算的第二个三维向量。它是一个关键输入,与'a'一起决定了计算的最终结果。 + - Comfy dtype: tuple[float, float, float] + - Python dtype: Tuple[float, float, float] + +# Output types +- result + - 输出'result'是从输入向量'a'和'b'上执行的二元运算得到的三维向量。它包含了向量计算的结果,并且是指定操作'op'的直接反映。 + - Comfy dtype: tuple[float, float, float] + - Python dtype: Tuple[float, float, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec3BinaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_BINARY_OPERATIONS.keys()),), 'a': DEFAULT_VEC3, 'b': DEFAULT_VEC3}} + RETURN_TYPES = ('VEC3',) + FUNCTION = 'op' + CATEGORY = 'math/vec3' + + def op(self, op: str, a: Vec3, b: Vec3) -> tuple[Vec3]: + return (_vec3_from_numpy(VEC_BINARY_OPERATIONS[op](numpy.array(a), numpy.array(b))),) +``` \ No newline at end of file diff --git a/docs/CM_Vec3ScalarOperation.md b/docs/CM_Vec3ScalarOperation.md new file mode 100644 index 0000000..667c8e9 --- /dev/null +++ b/docs/CM_Vec3ScalarOperation.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: Vec3ScalarOperation +- Category: math/vec3 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec3ScalarOperation节点旨在对三维向量执行各种标量运算。它通过将指定的操作应用于向量的每个元素与给定的标量值来实现这一点。该节点对于涉及三维空间中向量的数学运算至关重要,提供了一种简单直接的方式来操作向量分量。 + +# Input types +## Required +- op + - 参数'op'定义了要在向量上执行的特定标量操作。它至关重要,因为它决定了将对向量的分量执行的数学操作类型。操作的选择直接影响节点执行的结果。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'表示将应用操作的三维向量。作为核心输入,它对节点的功能至关重要,节点的输出取决于此向量内的值。 + - Comfy dtype: Vec3 + - Python dtype: Tuple[float, float, float] +- b + - 参数'b'是在操作期间与向量'a'相互作用的标量值。它的作用至关重要,因为它是将与向量的每个元素一起用于指定操作的数值。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- result + - 输出'result'是已经进行了指定标量操作的三维向量。它包含了节点计算的结果,反映了通过操作对原始向量'a'所做的更改。 + - Comfy dtype: VEC3 + - Python dtype: Tuple[float, float, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec3ScalarOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_SCALAR_OPERATION.keys()),), 'a': DEFAULT_VEC3, 'b': ('FLOAT',)}} + RETURN_TYPES = ('VEC3',) + FUNCTION = 'op' + CATEGORY = 'math/vec3' + + def op(self, op: str, a: Vec3, b: float) -> tuple[Vec3]: + return (_vec3_from_numpy(VEC_SCALAR_OPERATION[op](numpy.array(a), b)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec3ToScalarBinaryOperation.md b/docs/CM_Vec3ToScalarBinaryOperation.md new file mode 100644 index 0000000..bd4a4fd --- /dev/null +++ b/docs/CM_Vec3ToScalarBinaryOperation.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: Vec3ToScalarBinaryOperation +- Category: math/vec3 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec3ToScalarBinaryOperation节点旨在对两个三维向量执行二元运算,结果为一个标量值。它封装了向量运算的数学逻辑,并针对计算效率进行了优化,确保该节点通过提供准确可靠的向量计算为整个系统做出贡献。 + +# Input types +## Required +- op + - 参数'op'定义了要在输入向量上执行的二元运算。它至关重要,因为它决定了应用于向量的数学函数,影响节点计算的结果。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'代表二元运算中的第一个向量。它对于提供向量计算所需的一个操作数至关重要,影响最终的标量结果。 + - Comfy dtype: Vec3 + - Python dtype: numpy.ndarray +- b + - 参数'b'表示二元运算中涉及的第二个向量。它对于提供向量计算所需的另一个操作数不可或缺,直接影响节点的输出。 + - Comfy dtype: Vec3 + - Python dtype: numpy.ndarray + +# Output types +- result + - 'result'输出提供了对输入向量执行二元运算所得到的标量值。它很重要,因为它包含了节点数学处理的结果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec3ToScalarBinaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_TO_SCALAR_BINARY_OPERATION.keys()),), 'a': DEFAULT_VEC3, 'b': DEFAULT_VEC3}} + RETURN_TYPES = ('FLOAT',) + FUNCTION = 'op' + CATEGORY = 'math/vec3' + + def op(self, op: str, a: Vec3, b: Vec3) -> tuple[float]: + return (VEC_TO_SCALAR_BINARY_OPERATION[op](numpy.array(a), numpy.array(b)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec3ToScalarUnaryOperation.md b/docs/CM_Vec3ToScalarUnaryOperation.md new file mode 100644 index 0000000..b04be4f --- /dev/null +++ b/docs/CM_Vec3ToScalarUnaryOperation.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: Vec3ToScalarUnaryOperation +- Category: math/vec3 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec3ToScalarUnaryOperation节点旨在对三维向量执行多种一元运算,将其转换为标量值。此节点对于需要将向量的大小或方向属性简化为单个数值表示以进行进一步分析或决策过程的应用至关重要。 + +# Input types +## Required +- op + - 'op'参数是一个字符串,用于指定要在输入向量上执行的一元运算。它对于确定标量输出的性质以及应用于向量的数学变换至关重要。 + - Comfy dtype: str + - Python dtype: str +- a + - 'a'参数表示将在其上执行一元运算的三维向量。这是一个必要的输入,因为整个操作都围绕着将这个向量转换为标量值。 + - Comfy dtype: Vec3 + - Python dtype: numpy.ndarray + +# Output types +- result + - 'result'输出是从输入向量上执行的一元运算派生的标量值。它以单一数值形式概括了向量的本质,便于在随后的计算任务中使用。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec3ToScalarUnaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_TO_SCALAR_UNARY_OPERATION.keys()),), 'a': DEFAULT_VEC3}} + RETURN_TYPES = ('FLOAT',) + FUNCTION = 'op' + CATEGORY = 'math/vec3' + + def op(self, op: str, a: Vec3) -> tuple[float]: + return (VEC_TO_SCALAR_UNARY_OPERATION[op](numpy.array(a)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec3UnaryCondition.md b/docs/CM_Vec3UnaryCondition.md new file mode 100644 index 0000000..40d4789 --- /dev/null +++ b/docs/CM_Vec3UnaryCondition.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: Vec3UnaryCondition +- Category: math/vec3 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec3UnaryCondition节点旨在对三维向量执行向量化的一元运算。它对向量的每个元素应用指定的条件,并返回一个布尔结果,指示条件的结果。该节点对于需要对向量元素进行条件逻辑的数学运算至关重要,例如过滤或阈值处理。 + +# Input types +## Required +- op + - 参数'op'定义了要应用于向量每个元素的一元条件。它是预定义的向量一元条件集的一个键。此参数至关重要,因为它决定了节点将评估的特定条件。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'表示将应用一元条件的三维向量。这是一个关键输入,因为节点的操作直接依赖于这个向量内的值。节点根据指定的条件处理每个元素以产生布尔结果。 + - Comfy dtype: Vec3 + - Python dtype: Vec3 + +# Output types +- result + - 输出'result'是一个布尔值,表示将一元条件应用于输入向量的结果。它表明条件是否对向量中的每个元素都成立,根据指定的条件提供对向量状态的清晰和简洁的评估。 + - Comfy dtype: BOOL + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec3UnaryCondition: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_UNARY_CONDITIONS.keys()),), 'a': DEFAULT_VEC3}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/vec3' + + def op(self, op: str, a: Vec3) -> tuple[bool]: + return (VEC_UNARY_CONDITIONS[op](numpy.array(a)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec3UnaryOperation.md b/docs/CM_Vec3UnaryOperation.md new file mode 100644 index 0000000..339edd5 --- /dev/null +++ b/docs/CM_Vec3UnaryOperation.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: Vec3UnaryOperation +- Category: math/vec3 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec3UnaryOperation 类设计用于对三维向量执行一元运算。它封装了各种向量操作的逻辑,为三维空间中的数学操作提供了一个灵活的接口。 + +# Input types +## Required +- op + - 参数 'op' 指定了要在向量上执行的一元运算。它至关重要,因为它决定了将应用于向量每个分量的数学函数类型。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数 'a' 表示将执行一元运算的三维向量。它是一个必要的输入,因为它是数学操作的对象。 + - Comfy dtype: Vec3 + - Python dtype: Tuple[float, float, float] + +# Output types +- result + - 输出 'result' 是应用指定的一元运算后的变换三维向量。它很重要,因为它代表了数学过程的结果。 + - Comfy dtype: VEC3 + - Python dtype: Tuple[float, float, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec3UnaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_UNARY_OPERATIONS.keys()),), 'a': DEFAULT_VEC3}} + RETURN_TYPES = ('VEC3',) + FUNCTION = 'op' + CATEGORY = 'math/vec3' + + def op(self, op: str, a: Vec3) -> tuple[Vec3]: + return (_vec3_from_numpy(VEC_UNARY_OPERATIONS[op](numpy.array(a))),) +``` \ No newline at end of file diff --git a/docs/CM_Vec4BinaryCondition.md b/docs/CM_Vec4BinaryCondition.md new file mode 100644 index 0000000..5557bb7 --- /dev/null +++ b/docs/CM_Vec4BinaryCondition.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: Vec4BinaryCondition +- Category: math/vec4 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec4BinaryCondition节点旨在对四个分量的向量执行二元运算。它对两个输入向量应用指定的操作,产生一个布尔结果,指示条件的有效性。此节点在数学领域的向量分析和比较中起着关键作用。 + +# Input types +## Required +- op + - 参数'op'定义了要应用于输入向量的二元条件。它对于确定节点执行的比较或操作的性质至关重要,直接影响过程的结果。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'表示二元操作中的第一个向量。作为基本输入,它在节点的执行中扮演重要角色,根据'op'指定的条件影响最终的布尔结果。 + - Comfy dtype: Vec4 + - Python dtype: Vec4 +- b + - 参数'b'表示参与二元操作的第二个向量。它对于节点计算与'a'一起的比较或操作至关重要,其值对节点的输出至关重要。 + - Comfy dtype: Vec4 + - Python dtype: Vec4 + +# Output types +- result + - 'result'输出是一个布尔值,代表应用于输入向量的二元条件的结果。它表示由'op'参数指定的条件对于给定向量是否成立。 + - Comfy dtype: BOOL + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec4BinaryCondition: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_BINARY_CONDITIONS.keys()),), 'a': DEFAULT_VEC4, 'b': DEFAULT_VEC4}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/vec4' + + def op(self, op: str, a: Vec4, b: Vec4) -> tuple[bool]: + return (VEC_BINARY_CONDITIONS[op](numpy.array(a), numpy.array(b)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec4BinaryOperation.md b/docs/CM_Vec4BinaryOperation.md new file mode 100644 index 0000000..394936f --- /dev/null +++ b/docs/CM_Vec4BinaryOperation.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: Vec4BinaryOperation +- Category: math/vec4 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec4BinaryOperation节点旨在对两个四维向量(Vec4)执行二元运算。它能够处理由'op'参数指定的各种运算,允许在向量'a'和'b'之间进行逐元素运算。此节点在数学和计算上下文中的向量代数中至关重要,使用户能够有效地操作和分析向量数据。 + +# Input types +## Required +- op + - 参数'op'决定了要在输入向量上执行的二元运算类型。它至关重要,因为它决定了应用于向量的数学函数,从而影响节点执行的结果。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'表示二元运算中的第一个四维向量(Vec4)。它扮演着重要的角色,因为它是向量运算中的一个操作数,直接影响最终结果。 + - Comfy dtype: Vec4 + - Python dtype: Tuple[float, float, float, float] +- b + - 参数'b'表示参与二元运算的第二个四维向量(Vec4)。它很重要,因为它是向量运算中的第二个操作数,影响着节点的输出。 + - Comfy dtype: Vec4 + - Python dtype: Tuple[float, float, float, float] + +# Output types +- result + - 参数'result'保存输入向量'a'和'b'之间二元运算的结果。它很重要,因为它代表了运算应用后计算出的最终向量。 + - Comfy dtype: Vec4 + - Python dtype: Tuple[float, float, float, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec4BinaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_BINARY_OPERATIONS.keys()),), 'a': DEFAULT_VEC4, 'b': DEFAULT_VEC4}} + RETURN_TYPES = ('VEC4',) + FUNCTION = 'op' + CATEGORY = 'math/vec4' + + def op(self, op: str, a: Vec4, b: Vec4) -> tuple[Vec4]: + return (_vec4_from_numpy(VEC_BINARY_OPERATIONS[op](numpy.array(a), numpy.array(b))),) +``` \ No newline at end of file diff --git a/docs/CM_Vec4ScalarOperation.md b/docs/CM_Vec4ScalarOperation.md new file mode 100644 index 0000000..04f1d53 --- /dev/null +++ b/docs/CM_Vec4ScalarOperation.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: Vec4ScalarOperation +- Category: math/vec4 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec4ScalarOperation节点对四维向量执行标量运算,提供了一种通过各种数学运算来操作向量数据的方法。它旨在灵活高效,允许在需要向量算术的场景中直接应用。 + +# Input types +## Required +- op + - 操作参数定义了要在向量上执行的特定标量运算。它至关重要,因为它决定了应用于向量每个分量的数学函数。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'代表将在其上执行标量运算的四维向量。它至关重要,因为它是节点操作以产生结果的主要输入。 + - Comfy dtype: Vec4 + - Python dtype: Tuple[float, float, float, float] +- b + - 标量'b'是将与向量'a'一起用于由'op'定义的操作的浮点数。它在计算中扮演重要角色,因为它直接影响向量变换的结果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- result + - 对输入向量'a'执行的标量运算的结果。它包含了将指定的数学函数应用于向量每个分量后的结果。 + - Comfy dtype: VEC4 + - Python dtype: Tuple[float, float, float, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec4ScalarOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_SCALAR_OPERATION.keys()),), 'a': DEFAULT_VEC4, 'b': ('FLOAT',)}} + RETURN_TYPES = ('VEC4',) + FUNCTION = 'op' + CATEGORY = 'math/vec4' + + def op(self, op: str, a: Vec4, b: float) -> tuple[Vec4]: + return (_vec4_from_numpy(VEC_SCALAR_OPERATION[op](numpy.array(a), b)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec4ToScalarBinaryOperation.md b/docs/CM_Vec4ToScalarBinaryOperation.md new file mode 100644 index 0000000..bb151e2 --- /dev/null +++ b/docs/CM_Vec4ToScalarBinaryOperation.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: Vec4ToScalarBinaryOperation +- Category: math/vec4 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec4ToScalarBinaryOperation节点旨在对两个四维向量(Vec4)执行二元运算,结果为一个标量值。它封装了执行此类运算所需的数学逻辑,抽象了复杂性,并为基于向量的计算提供了一个直观的接口。 + +# Input types +## Required +- op + - 参数'op'定义了要在输入向量上执行的二元运算。它至关重要,因为它决定了将应用于向量的数学函数,直接影响运算的结果。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'表示二元运算中的第一个四维向量(Vec4)。它是一个必要的输入,因为它构成了操作的一个操作数,对最终的标量结果有所贡献。 + - Comfy dtype: Vec4 + - Python dtype: List[float] +- b + - 参数'b'表示参与二元运算的第二个四维向量(Vec4)。它是一个必需的输入,因为它补充了第一个向量以完成运算,影响结果的标量值。 + - Comfy dtype: Vec4 + - Python dtype: List[float] + +# Output types +- result + - 参数'result'是输入向量上执行的二元运算的标量输出。它代表了数学过程的最终结果,将运算的结果封装在一个单一的数值中。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec4ToScalarBinaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_TO_SCALAR_BINARY_OPERATION.keys()),), 'a': DEFAULT_VEC4, 'b': DEFAULT_VEC4}} + RETURN_TYPES = ('FLOAT',) + FUNCTION = 'op' + CATEGORY = 'math/vec4' + + def op(self, op: str, a: Vec4, b: Vec4) -> tuple[float]: + return (VEC_TO_SCALAR_BINARY_OPERATION[op](numpy.array(a), numpy.array(b)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec4ToScalarUnaryOperation.md b/docs/CM_Vec4ToScalarUnaryOperation.md new file mode 100644 index 0000000..9f1a6a0 --- /dev/null +++ b/docs/CM_Vec4ToScalarUnaryOperation.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: Vec4ToScalarUnaryOperation +- Category: math/vec4 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +该节点对四维向量执行数学运算,将其转换为标量值。它旨在封装一系列可以应用于向量每个元素的一元运算,从而以一种简化和高效的方式实现复杂的数学转换。 + +# Input types +## Required +- op + - 参数 'op' 指定要应用于输入向量每个元素的一元运算。它至关重要,因为它决定了将执行的数学转换类型。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数 'a' 表示节点将处理的四维向量。这是一个基本输入,因为节点的功能围绕在这个向量上执行运算。 + - Comfy dtype: Vec4 + - Python dtype: numpy.ndarray + +# Output types +- result + - 参数 'result' 是节点的输出,它是通过对输入向量应用指定的一元运算得到的标量值。它标志着节点数学处理的完成。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec4ToScalarUnaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_TO_SCALAR_UNARY_OPERATION.keys()),), 'a': DEFAULT_VEC4}} + RETURN_TYPES = ('FLOAT',) + FUNCTION = 'op' + CATEGORY = 'math/vec4' + + def op(self, op: str, a: Vec4) -> tuple[float]: + return (VEC_TO_SCALAR_UNARY_OPERATION[op](numpy.array(a)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec4UnaryCondition.md b/docs/CM_Vec4UnaryCondition.md new file mode 100644 index 0000000..a854982 --- /dev/null +++ b/docs/CM_Vec4UnaryCondition.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: Vec4UnaryCondition +- Category: math/vec4 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec4UnaryCondition节点旨在对四维向量执行一元运算。它评估向量每个分量上的条件,返回一个单一的布尔结果,指示所有分量是否满足条件。此节点在需要条件逻辑的基于向量的数学运算中至关重要。 + +# Input types +## Required +- op + - 参数'op'定义了要应用于向量每个分量的一元条件。它非常重要,因为它决定了节点执行的条件检查的性质。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'表示将评估一元条件的四维向量。它是一个关键的输入,因为节点的操作完全依赖于这个向量内的值。 + - Comfy dtype: Vec4 + - Python dtype: Vec4 + +# Output types +- result + - 输出'result'是一个布尔值,表示应用于输入向量所有分量的一元条件是否计算为真。 + - Comfy dtype: BOOL + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec4UnaryCondition: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_UNARY_CONDITIONS.keys()),), 'a': DEFAULT_VEC4}} + RETURN_TYPES = ('BOOL',) + FUNCTION = 'op' + CATEGORY = 'math/vec4' + + def op(self, op: str, a: Vec4) -> tuple[bool]: + return (VEC_UNARY_CONDITIONS[op](numpy.array(a)),) +``` \ No newline at end of file diff --git a/docs/CM_Vec4UnaryOperation.md b/docs/CM_Vec4UnaryOperation.md new file mode 100644 index 0000000..699a2ec --- /dev/null +++ b/docs/CM_Vec4UnaryOperation.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: Vec4UnaryOperation +- Category: math/vec4 +- Output node: False +- Repo Ref: https://github.com/evanspearman/ComfyMath + +Vec4UnaryOperation节点旨在对四维向量执行各种一元操作。它能够对向量应用不同的数学变换,这在图形、物理或其他数学应用中的基于向量的计算中可能至关重要。 + +# Input types +## Required +- op + - 参数'op'指定了要在向量'a'上执行的一元操作。它是一个字符串,代表操作本身,对于确定应用于向量的变化至关重要。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'表示将应用一元操作的四维向量。这是一个基本输入,因为操作的效果直接体现在这个向量的变换中。 + - Comfy dtype: Vec4 + - Python dtype: Tuple[float, float, float, float] + +# Output types +- result + - 参数'result'代表对输入向量'a'应用一元操作的结果。它是经过变换的向量,包含了操作的效果。 + - Comfy dtype: Vec4 + - Python dtype: Tuple[float, float, float, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vec4UnaryOperation: + + @classmethod + def INPUT_TYPES(cls) -> Mapping[str, Any]: + return {'required': {'op': (list(VEC_UNARY_OPERATIONS.keys()),), 'a': DEFAULT_VEC4}} + RETURN_TYPES = ('VEC4',) + FUNCTION = 'op' + CATEGORY = 'math/vec4' + + def op(self, op: str, a: Vec4) -> tuple[Vec4]: + return (_vec4_from_numpy(VEC_UNARY_OPERATIONS[op](numpy.array(a))),) +``` \ No newline at end of file diff --git a/docs/CR 8 Channel In.md b/docs/CR 8 Channel In.md new file mode 100644 index 0000000..9f8c1cb --- /dev/null +++ b/docs/CR 8 Channel In.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: CR_8ChannelIn +- Category: Comfyroll/Pipe/Bus +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_8ChannelIn节点旨在高效地管理和组织多通道数据输入。它通过将来自八个不同通道的数据加载和组合成单一的管道结构,从而简化了后续数据处理任务的工作流程。 + +# Input types +## Optional +- pipe + - 当提供'pipe'参数时,它直接为所有八个通道提供数据,绕过了单独通道输入的需要。它是一个包含每个通道数据的元组,对于维护通道间的数据完整性和连续性至关重要。 + - Comfy dtype: any_type + - Python dtype: Tuple[Any, ...] +- ch1 + - 'ch1'参数代表输入数据的第一个通道。它是可选的,只有在提供时才会被使用;否则,如果可用,将使用'pipe'输入中对应的值。 + - Comfy dtype: any_type + - Python dtype: Any +- ch2 + - 'ch2'参数用于数据输入的第二个通道。它的运作方式类似于'ch1',允许单独指定通道数据,同时也可以通过'pipe'输入替换。 + - Comfy dtype: any_type + - Python dtype: Any +- ch3 + - 'ch3'参数代表输入数据的第三个通道,其运作方式与'ch1'和'ch2'相同,能够被集体的'pipe'输入覆盖。 + - Comfy dtype: any_type + - Python dtype: Any +- ch4 + - 'ch4'参数用于数据输入的第四个通道,遵循与前三个通道相同的操作原则。 + - Comfy dtype: any_type + - Python dtype: Any +- ch5 + - 'ch5'参数代表输入数据的第五个通道,保持了单独通道输入的灵活性,同时受到'pipe'输入的集体数据的影响。 + - Comfy dtype: any_type + - Python dtype: Any +- ch6 + - 'ch6'参数用于数据输入的第六个通道,遵循与之前通道相同的模式,并受到'pipe'输入的影响。 + - Comfy dtype: any_type + - Python dtype: Any +- ch7 + - 'ch7'参数代表输入数据的第七个通道,延续了通道输入的一致方法,并且可以通过'pipe'输入替换。 + - Comfy dtype: any_type + - Python dtype: Any +- ch8 + - 'ch8'参数用于数据输入的第八个,也就是最后一个通道,遵循已建立的输入模式,并是'pipe'输入集体数据管理的一部分。 + - Comfy dtype: any_type + - Python dtype: Any + +# Output types +- pipe + - 'pipe'输出是一个包含所有八个输入通道组合数据的元组。它是节点的主要输出,代表了进一步处理的结构化数据流。 + - Comfy dtype: any_type + - Python dtype: Tuple[Any, ...] +- show_help + - 'show_help'输出提供了指向节点文档页面的URL链接,使用户能够直接访问有关使用该节点的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_8ChannelIn: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}, 'optional': {'pipe': (any_type,), 'ch1': (any_type,), 'ch2': (any_type,), 'ch3': (any_type,), 'ch4': (any_type,), 'ch5': (any_type,), 'ch6': (any_type,), 'ch7': (any_type,), 'ch8': (any_type,)}} + RETURN_TYPES = ('PIPE_LINE', 'STRING') + RETURN_NAMES = ('pipe', 'show_help') + FUNCTION = 'load_data' + CATEGORY = icons.get('Comfyroll/Pipe/Bus') + + def load_data(self, ch1=None, ch2=None, ch3=None, ch4=None, ch5=None, ch6=None, ch7=None, ch8=None, pipe=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pipe-Nodes#cr-8-channel-in' + (new_ch1, new_ch2, new_ch3, new_ch4, new_ch5, new_ch6, new_ch7, new_ch8) = (None, None, None, None, None, None, None, None) + if pipe is not None: + (new_ch1, new_ch2, new_ch3, new_ch4, new_ch5, new_ch6, new_ch7, new_ch8) = pipe + new_ch1 = ch1 if ch1 is not None else new_ch1 + new_ch2 = ch2 if ch2 is not None else new_ch2 + new_ch3 = ch3 if ch3 is not None else new_ch3 + new_ch4 = ch4 if ch4 is not None else new_ch4 + new_ch5 = ch5 if ch5 is not None else new_ch5 + new_ch6 = ch6 if ch6 is not None else new_ch6 + new_ch7 = ch7 if ch7 is not None else new_ch7 + new_ch8 = ch8 if ch8 is not None else new_ch8 + new_pipe = (new_ch1, new_ch2, new_ch3, new_ch4, new_ch5, new_ch6, new_ch7, new_ch8) + return (new_pipe, show_help) +``` \ No newline at end of file diff --git a/docs/CR 8 Channel Out.md b/docs/CR 8 Channel Out.md new file mode 100644 index 0000000..6607c42 --- /dev/null +++ b/docs/CR 8 Channel Out.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: CR_8ChannelOut +- Category: Comfyroll/Pipe/Bus +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_8ChannelOut节点旨在管理和分发数据到八个不同的通道。它在确保信息流在管道中顺畅进行中起着关键作用,确保每个通道都能接收到适当的数据以进行进一步处理或分析。 + +# Input types +## Required +- pipe + - 'pipe'参数至关重要,因为它作为数据传递和随后在八个通道中分配的通道。其正确配置对节点的操作和数据流的完整性至关重要。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple[Any, ...] + +# Output types +- pipe + - 'pipe'输出代表原始数据管道,已经处理完毕,现在准备好供下游节点进一步使用或分析。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple[Any, ...] +- ch1 + - 通道1 'ch1' 是接收 'pipe' 中数据部分的八个通道之一。它对于专门处理或处理与此通道相关的数据具有重要意义。 + - Comfy dtype: any_type + - Python dtype: Any +- ch2 + - 通道2 'ch2' 是另一个处理数据特定部分的通道。它适用于节点操作中为这个特定通道指定的任务。 + - Comfy dtype: any_type + - Python dtype: Any +- ch3 + - 通道3 'ch3' 用于进一步分流数据,允许并行处理或专门处理不同的数据段。 + - Comfy dtype: any_type + - Python dtype: Any +- ch4 + - 通道4 'ch4' 是节点管理的多个通道之一,每个通道在数据分配和处理中都扮演着不同的角色。 + - Comfy dtype: any_type + - Python dtype: Any +- ch5 + - 通道5 'ch5' 被指定用于特定类型的数据处理,确保节点的功能与工作流程的特定要求保持一致。 + - Comfy dtype: any_type + - Python dtype: Any +- ch6 + - 通道6 'ch6' 是节点多通道架构的一部分,满足复杂系统中多样化的数据处理需求。 + - Comfy dtype: any_type + - Python dtype: Any +- ch7 + - 通道7 'ch7' 是节点内的一个专用通道,优化以处理特定的数据流以提高工作流程的效率。 + - Comfy dtype: any_type + - Python dtype: Any +- ch8 + - 通道8 'ch8' 是节点套件中的最后一个通道,完成了数据在所有指定通道中的分配,以进行全面处理。 + - Comfy dtype: any_type + - Python dtype: Any +- show_help + - 'show_help'输出提供了指向节点文档的URL链接,为用户提供了直接参考节点指南和使用说明的途径。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_8ChannelOut: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',)}} + RETURN_TYPES = ('PIPE_LINE', any_type, any_type, any_type, any_type, any_type, any_type, any_type, any_type, 'STRING') + RETURN_NAMES = ('pipe', 'ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6', 'ch7', 'ch8', 'show_help') + FUNCTION = 'data_out' + CATEGORY = icons.get('Comfyroll/Pipe/Bus') + + def data_out(self, ch1=None, ch2=None, ch3=None, ch4=None, ch5=None, ch6=None, ch7=None, ch8=None, pipe=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pipe-Nodes#cr-8-channel-out' + (new_ch1, new_ch2, new_ch3, new_ch4, new_ch5, new_ch6, new_ch7, new_ch8) = pipe + return (pipe, new_ch1, new_ch2, new_ch3, new_ch4, new_ch5, new_ch6, new_ch7, new_ch8, show_help) +``` \ No newline at end of file diff --git a/docs/CR Apply ControlNet.md b/docs/CR Apply ControlNet.md new file mode 100644 index 0000000..221ea82 --- /dev/null +++ b/docs/CR Apply ControlNet.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: CR_ApplyControlNet +- Category: ControlNet +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ApplyControlNet 节点旨在将控制网络集成到图像生成过程中,允许应用特定条件和调整以完善输出。它通过利用强度参数和开关机制,在增强生成图像的可控性和质量方面发挥关键作用。 + +# Input types +## Required +- conditioning + - 条件参数对于定义图像生成的初始状态或上下文至关重要。它为控制网络的操作奠定了基础,并对最终输出的特征产生重大影响。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict[str, Any]]] +- control_net + - 控制网络参数作为一个指导框架,指导如何根据提供的条件下生成图像。它是实现节点操作所需结果的关键组件。 + - Comfy dtype: CONTROL_NET + - Python dtype: comfy.controlnet.ControlNet +- image + - 图像输入是控制网络将处理的原始材料。它是节点功能的基础,因为它是在控制网络的影响下将被转换的实体。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- switch + - 开关参数决定是否应用控制网络的影响。它作为启用或禁用节点核心功能的切换器,从而控制节点的行为。 + - Comfy dtype: COMBO[On, Off] + - Python dtype: str +- strength + - 强度参数调节控制网络对图像生成过程的影响强度。它允许微调控制网络的效果,以实现控制和创造力之间的平衡。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- CONDITIONING + - 输出条件提供了应用控制网络后的转换状态或上下文,封装了进一步处理或分析的精细条件。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict[str, Any]]] +- show_help + - show_help 输出提供了文档链接,以进一步协助和指导有效使用节点。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ApplyControlNet: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'conditioning': ('CONDITIONING',), 'control_net': ('CONTROL_NET',), 'image': ('IMAGE',), 'switch': (['On', 'Off'],), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01})}} + RETURN_TYPES = ('CONDITIONING', 'STRING') + RETURN_NAMES = ('CONDITIONING', 'show_help') + FUNCTION = 'apply_controlnet' + CATEGORY = icons.get('Comfyroll/ControlNet') + + def apply_controlnet(self, conditioning, control_net, image, switch, strength): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/ControlNet-Nodes#cr-apply-controlnet' + if strength == 0 or switch == 'Off': + return (conditioning, show_help) + c = [] + control_hint = image.movedim(-1, 1) + for t in conditioning: + n = [t[0], t[1].copy()] + c_net = control_net.copy().set_cond_hint(control_hint, strength) + if 'control' in t[1]: + c_net.set_previous_controlnet(t[1]['control']) + n[1]['control'] = c_net + c.append(n) + return (c, show_help) +``` \ No newline at end of file diff --git a/docs/CR Apply LoRA Stack.md b/docs/CR Apply LoRA Stack.md new file mode 100644 index 0000000..b58049d --- /dev/null +++ b/docs/CR Apply LoRA Stack.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: CR_ApplyLoRAStack +- Category: Comfyroll/LoRA +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ApplyLoRAStack 节点旨在将一系列 LoRA(低秩适应)修改应用于模型及其相关剪辑。它通过叠加多个 LoRA 调整来增强模型的能力,允许对特定特征进行微调,而不会显著增加模型的大小或计算负载。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它代表了 LoRA 修改的主要对象。它是 LoRA 栈操作的基础,栈中的每一层都可能改变其行为。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - 剪辑参数是必不可少的,因为它通过提供上下文信息来补充模型,这些信息可以与 LoRA 栈一起使用,影响最终输出。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +## Optional +- lora_stack + - lora_stack 参数是系列 LoRA 配置的集合,它决定了如何调整模型和剪辑。栈中的每个元素都有助于整体转换。 + - Comfy dtype: LORA_STACK + - Python dtype: List[Tuple[str, float, float]] + +# Output types +- MODEL + - 输出模型代表了应用 LoRA 栈后输入模型的修改版本。它包含了通过 LoRA 调整所做的增强。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- CLIP + - 输出剪辑是输入剪辑的修改版本,已与模型一起调整,以反映 LoRA 栈的影响。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个 URL 链接到文档,以进一步协助和理解 LoRA 栈应用过程。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CR_ApplyLoRAStack: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'lora_stack': ('LORA_STACK',)}} + RETURN_TYPES = ('MODEL', 'CLIP', 'STRING') + RETURN_NAMES = ('MODEL', 'CLIP', 'show_help') + FUNCTION = 'apply_lora_stack' + CATEGORY = icons.get('Comfyroll/LoRA') + + def apply_lora_stack(self, model, clip, lora_stack=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/LoRA-Nodes#cr-apply-lora-stack' + lora_params = list() + if lora_stack: + lora_params.extend(lora_stack) + else: + return (model, clip, show_help) + model_lora = model + clip_lora = clip + for tup in lora_params: + (lora_name, strength_model, strength_clip) = tup + lora_path = folder_paths.get_full_path('loras', lora_name) + lora = comfy.utils.load_torch_file(lora_path, safe_load=True) + (model_lora, clip_lora) = comfy.sd.load_lora_for_models(model_lora, clip_lora, lora, strength_model, strength_clip) + return (model_lora, clip_lora, show_help) +``` \ No newline at end of file diff --git a/docs/CR Apply Model Merge.md b/docs/CR Apply Model Merge.md new file mode 100644 index 0000000..2c839e2 --- /dev/null +++ b/docs/CR Apply Model Merge.md @@ -0,0 +1,110 @@ +# Documentation +- Class name: CR_ApplyModelMerge +- Category: Comfyroll/Model Merge +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ApplyModelMerge节点旨在方便地将多个模型合并为一个单一的统一模型。它通过智能地组合模型比例和剪贴比例,在必要时进行归一化,并应用指定的合并方法来创建所选模型的和谐混合。该节点对于高级模型管理至关重要,使用户能够尝试不同的模型组合和比例以实现期望的结果。 + +# Input types +## Required +- model_stack + - 模型栈参数至关重要,因为它定义了要合并的模型序列。它在节点的执行中起着核心作用,决定了将贡献给最终合并模型的模型。 + - Comfy dtype: MODEL_STACK + - Python dtype: List[Tuple[str, float, float]] +- merge_method + - 合并方法参数决定了模型的组合方式。它是节点功能的关键因素,因为它决定了用于合并的算法,这可以显著影响结果模型的特性。 + - Comfy dtype: COMBO['Recursive', 'Weighted'] + - Python dtype: str +- normalise_ratios + - normalise_ratios参数很重要,因为它指示是否应将比例归一化。这对于确保比例准确反映每个模型对合并结果的预期贡献非常重要。 + - Comfy dtype: COMBO['Yes', 'No'] + - Python dtype: str +- weight_factor + - 权重因子参数影响合并过程中模型的权重。它对于微调每个模型对最终合并模型的贡献至关重要,允许对结果进行精确控制。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- MODEL + - MODEL输出提供了应用合并方法和指定参数后得到的合并模型。它代表了节点处理的顶点,对用户的工作流程至关重要。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_management.Model +- CLIP + - CLIP输出提供了与合并模型相关的CLIP模型。它很重要,因为它使得使用CLIP模型框架进行进一步的处理或分析成为可能。 + - Comfy dtype: CLIP + - Python dtype: comfy.model_management.CLIP +- model_mix_info + - model_mix_info输出提供了合并过程的详细报告,包括所使用的模型的名称和比例。这些信息对于理解合并模型的组成和记录合并过程非常有价值。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - show_help输出提供了一个链接到文档的链接,以获得进一步的帮助。对于寻求如何有效使用节点的更多信息的用户来说,这是一个有用的资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ApplyModelMerge: + + @classmethod + def INPUT_TYPES(s): + merge_methods = ['Recursive', 'Weighted'] + return {'required': {'model_stack': ('MODEL_STACK',), 'merge_method': (merge_methods,), 'normalise_ratios': (['Yes', 'No'],), 'weight_factor': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('MODEL', 'CLIP', 'STRING', 'STRING') + RETURN_NAMES = ('MODEL', 'CLIP', 'model_mix_info', 'show_help') + FUNCTION = 'merge' + CATEGORY = icons.get('Comfyroll/Model Merge') + + def merge(self, model_stack, merge_method, normalise_ratios, weight_factor): + sum_clip_ratio = 0 + sum_model_ratio = 0 + model_mix_info = str('Merge Info:\n') + if len(model_stack) == 0: + print(f'[Warning] Apply Model Merge: No active models selected in the model merge stack') + return () + if len(model_stack) == 1: + print(f'[Warning] Apply Model Merge: Only one active model found in the model merge stack. At least 2 models are normally needed for merging. The active model will be output.') + (model_name, model_ratio, clip_ratio) = model_stack[0] + ckpt_path = folder_paths.get_full_path('checkpoints', model_name) + return comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths('embeddings')) + for (i, model_tuple) in enumerate(model_stack): + (model_name, model_ratio, clip_ratio) = model_tuple + sum_model_ratio += model_ratio + sum_clip_ratio += clip_ratio + model_mix_info = model_mix_info + 'Ratios are applied using the Recursive method\n\n' + for (i, model_tuple) in enumerate(model_stack): + (model_name, model_ratio, clip_ratio) = model_tuple + ckpt_path = folder_paths.get_full_path('checkpoints', model_name) + merge_model = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths('embeddings')) + print(f'Apply Model Merge: Model Name {model_name}, Model Ratio {model_ratio}, CLIP Ratio {clip_ratio}') + if sum_model_ratio != 1 and normalise_ratios == 'Yes': + print(f'[Warning] Apply Model Merge: Sum of model ratios != 1. Ratios will be normalised') + model_ratio = round(model_ratio / sum_model_ratio, 2) + clip_ratio = round(clip_ratio / sum_clip_ratio, 2) + if merge_method == 'Weighted': + if i == 1: + model_ratio = 1 - weight_factor + weight_factor * model_ratio + clip_ratio = 1 - weight_factor + weight_factor * clip_ratio + if i == 0: + model1 = merge_model[0].clone() + clip1 = merge_model[1].clone() + model_mix_info = model_mix_info + 'Base Model Name: ' + model_name + else: + model2 = merge_model[0].clone() + kp = model2.get_key_patches('diffusion_model.') + for k in kp: + model1.add_patches({k: kp[k]}, model_ratio, 1.0 - model_ratio) + clip2 = merge_model[1].clone() + kp = clip2.get_key_patches() + for k in kp: + if k.endswith('.position_ids') or k.endswith('.logit_scale'): + continue + clip1.add_patches({k: kp[k]}, clip_ratio, 1.0 - clip_ratio) + model_mix_info = model_mix_info + '\nModel Name: ' + model_name + '\nModel Ratio: ' + str(model_ratio) + '\nCLIP Ratio: ' + str(clip_ratio) + '\n' + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Model-Merge-Nodes#cr-apply-model-merge' + return (model1, clip1, model_mix_info, show_help) +``` \ No newline at end of file diff --git a/docs/CR Apply Multi Upscale.md b/docs/CR Apply Multi Upscale.md new file mode 100644 index 0000000..bc52f97 --- /dev/null +++ b/docs/CR Apply Multi Upscale.md @@ -0,0 +1,81 @@ +# Documentation +- Class name: CR_ApplyMultiUpscale +- Category: Comfyroll/Upscale +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ApplyMultiUpscale 是一个旨在通过多阶段放大过程提高图像分辨率的节点。它利用一系列升频模型顺序地细化图像质量。该节点能够调整重采样方法和舍入模数,为用户提供对放大过程的精细控制。其主要目标是提供具有改进清晰度和细节的高分辨率图像。 + +# Input types +## Required +- image + - 输入图像是节点处理的主要数据。它是所有放大操作的起点,其质量直接影响最终输出。图像参数是必需的,因为它决定了增强的主题。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- resampling_method + - 重采样方法决定了在放大过程中图像是如何插值的。它是一个关键参数,影响着放大图像的平滑度和清晰度,允许用户选择不同的算法以获得最佳结果。 + - Comfy dtype: COMBO[lanczos, nearest, bilinear, bicubic] + - Python dtype: str +- supersample + - Supersample 参数允许在放大过程中控制过采样。它非常重要,因为它可以增强图像的细节和清晰度,特别适用于高分辨率输出。 + - Comfy dtype: COMBO[true, false] + - Python dtype: bool +- rounding_modulus + - 舍入模数用于确定放大过程中的舍入行为。它是一个重要的参数,确保放大图像的尺寸一致且优化,以便于显示或进一步处理。 + - Comfy dtype: INT + - Python dtype: int +- upscale_stack + - 放大堆栈是定义放大操作序列的模型和因素的集合。它至关重要,因为它决定了模型应用于图像的复杂性和顺序,显著影响最终结果。 + - Comfy dtype: UPSCALE_STACK + - Python dtype: List[Tuple[str, float]] + +# Output types +- IMAGE + - 放大后的图像是节点的主要输出,代表多阶段放大过程的最终结果。它很重要,因为它是节点操作的直接结果,用于进一步处理或显示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个文档的 URL,用于进一步帮助。它对于需要更多关于节点操作信息或需要故障排除指导的用户来说很有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CR_ApplyMultiUpscale: + + @classmethod + def INPUT_TYPES(s): + resampling_methods = ['lanczos', 'nearest', 'bilinear', 'bicubic'] + return {'required': {'image': ('IMAGE',), 'resampling_method': (resampling_methods,), 'supersample': (['true', 'false'],), 'rounding_modulus': ('INT', {'default': 8, 'min': 8, 'max': 1024, 'step': 8}), 'upscale_stack': ('UPSCALE_STACK',)}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'apply' + CATEGORY = icons.get('Comfyroll/Upscale') + + def apply(self, image, resampling_method, supersample, rounding_modulus, upscale_stack): + pil_img = tensor2pil(image) + (original_width, original_height) = pil_img.size + params = list() + params.extend(upscale_stack) + for tup in params: + (upscale_model, rescale_factor) = tup + print(f'[Info] CR Apply Multi Upscale: Applying {upscale_model} and rescaling by factor {rescale_factor}') + up_model = load_model(upscale_model) + up_image = upscale_with_model(up_model, image) + pil_img = tensor2pil(up_image) + (upscaled_width, upscaled_height) = pil_img.size + if upscaled_width == original_width and rescale_factor == 1: + image = up_image + else: + scaled_images = [] + mode = 'rescale' + resize_width = 1024 + for img in up_image: + scaled_images.append(pil2tensor(apply_resize_image(tensor2pil(img), original_width, original_height, rounding_modulus, mode, supersample, rescale_factor, resize_width, resampling_method))) + image = torch.cat(scaled_images, dim=0) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Upscale-Nodes#cr-apply-multi-upscale' + return (image, show_help) +``` \ No newline at end of file diff --git a/docs/CR Apply Multi-ControlNet.md b/docs/CR Apply Multi-ControlNet.md new file mode 100644 index 0000000..f35672f --- /dev/null +++ b/docs/CR Apply Multi-ControlNet.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: CR_ApplyControlNetStack +- Category: Comfyroll/ControlNet +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ApplyControlNetStack节点旨在将一系列ControlNet应用于一对基础图像,增强生成过程的控制。它根据用户定义的参数管理多个ControlNet的集成,确保对最终输出进行细粒度控制。 + +# Input types +## Required +- base_positive + - base_positive参数是一个关键输入,代表正面条件图像。它被用作参考,以指导ControlNet的应用,显著影响生成输出的方向和质量。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- base_negative + - base_negative参数作为负面条件图像,通过与base_positive图像形成对比,帮助细化生成过程。它在引导输出远离不希望的特征方面起着至关重要的作用。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- switch + - switch参数是一个开关,决定是否激活ControlNet堆栈应用。它对于启用或禁用ControlNet对生成过程的影响至关重要。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +## Optional +- controlnet_stack + - controlnet_stack参数是一个可选输入,一旦提供,允许将预定义的ControlNet集合应用于基础图像。堆栈中的每个ControlNet都有助于整体条件化,增强了生成的特异性和精确度。 + - Comfy dtype: CONTROL_NET_STACK + - Python dtype: List[Tuple[str, torch.Tensor, float, float, float]] + +# Output types +- base_pos + - base_pos输出是在应用ControlNet堆栈后修改的正面条件图像。它包含了所有应用的ControlNet的集体效应,代表了生成过程的精细指南。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- base_neg + - base_neg输出对应于在应用ControlNet堆栈期间修改的负面条件图像。它在塑造最终输出方面起着工具性作用,通过引导它避免不希望的特性。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- show_help + - show_help输出提供了一个URL,链接到CR_ApplyControlNetStack节点的文档,以获得更多帮助和使用指导。对于寻求有关节点功能和用法的更多信息的用户来说,这是一个有用的资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CR_ApplyControlNetStack: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_positive': ('CONDITIONING',), 'base_negative': ('CONDITIONING',), 'switch': (['Off', 'On'],), 'controlnet_stack': ('CONTROL_NET_STACK',)}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING', 'STRING') + RETURN_NAMES = ('base_pos', 'base_neg', 'show_help') + FUNCTION = 'apply_controlnet_stack' + CATEGORY = icons.get('Comfyroll/ControlNet') + + def apply_controlnet_stack(self, base_positive, base_negative, switch, controlnet_stack=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/ControlNet-Nodes#cr-apply-multi-controlnet-stack' + if switch == 'Off': + return (base_positive, base_negative, show_help) + if controlnet_stack is not None: + for controlnet_tuple in controlnet_stack: + (controlnet_name, image, strength, start_percent, end_percent) = controlnet_tuple + if type(controlnet_name) == str: + controlnet_path = folder_paths.get_full_path('controlnet', controlnet_name) + controlnet = comfy.sd.load_controlnet(controlnet_path) + else: + controlnet = controlnet_name + controlnet_conditioning = ControlNetApplyAdvanced().apply_controlnet(base_positive, base_negative, controlnet, image, strength, start_percent, end_percent) + (base_positive, base_negative) = (controlnet_conditioning[0], controlnet_conditioning[1]) + return (base_positive, base_negative, show_help) +``` \ No newline at end of file diff --git a/docs/CR Aspect Ratio Banners.md b/docs/CR Aspect Ratio Banners.md new file mode 100644 index 0000000..2458500 --- /dev/null +++ b/docs/CR Aspect Ratio Banners.md @@ -0,0 +1,125 @@ +# Documentation +- Class name: CR_AspectRatioBanners +- Category: Comfyroll/Aspect Ratio +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_AspectRatioBanners 节点旨在方便创建和操作符合各种宽高比的图像横幅。它允许用户输入自定义尺寸或从预定义的横幅大小列表中选择。该节点还提供了交换尺寸和应用缩放因子的选项,以满足特定要求。其主要目标是简化生成视觉上一致且适用于多样化显示目的的横幅的过程。 + +# Input types +## Required +- width + - 宽度参数指定横幅所需的宽度。它在确定输出图像的整体尺寸中起着关键作用,确保横幅适应所需的约束条件。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数定义横幅的垂直范围。它对于保持宽高比和实现横幅所需的外观至关重要。 + - Comfy dtype: INT + - Python dtype: int +- aspect_ratio + - 宽高比确定了横幅宽度和高度之间的比例关系。它是确保横幅尺寸在视觉上吸引人且适合预期用途的关键因素。 + - Comfy dtype: STRING + - Python dtype: str +- swap_dimensions + - swap_dimensions 参数允许宽度和高度值的可交换性,提供了在解释和使用横幅尺寸方面的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- upscale_factor + - upscale_factor 参数用于增加横幅的尺寸,而不改变其宽高比,从而提高横幅在较大显示设备上的视觉质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- prescale_factor + - prescale_factor 参数允许在进一步处理之前调整横幅的尺寸,从而优化图像的大小和性能。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - batch_size 参数定义了同时处理的横幅数量,这在处理多个横幅创建任务时可以显著提高效率。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- width + - 宽度输出提供了应用所选宽高比和缩放因子后横幅的最终宽度。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度输出给出了考虑到宽高比和缩放调整后的横幅的最终高度。 + - Comfy dtype: INT + - Python dtype: int +- upscale_factor + - upscale_factor 输出反映了用于放大横幅尺寸的缩放因子。 + - Comfy dtype: FLOAT + - Python dtype: float +- prescale_factor + - prescale_factor 输出表明在处理之前应用于横幅尺寸的初始缩放因子。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - batch_size 输出表示当前操作中处理的横幅数量。 + - Comfy dtype: INT + - Python dtype: int +- empty_latent + - empty_latent 输出是用于进一步处理或分析横幅的潜在表示的占位符。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- show_help + - show_help 输出提供了一个链接到文档的链接,以获得有关使用该节点的进一步指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_AspectRatioBanners: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + aspect_ratios = ['custom', 'Large Rectangle - 336x280', 'Medium Rectangle - 300x250', 'Small Rectangle - 180x150', 'Square - 250x250', 'Small Square - 200x200', 'Button - 125x125', 'Half Page - 300x600', 'Vertical Banner - 120x240', 'Wide Skyscraper - 160x600', 'Skyscraper - 120x600', 'Billboard - 970x250', 'Portrait - 300x1050', 'Banner - 468x60', 'Leaderboard - 728x90'] + return {'required': {'width': ('INT', {'default': 1024, 'min': 64, 'max': 8192}), 'height': ('INT', {'default': 1024, 'min': 64, 'max': 8192}), 'aspect_ratio': (aspect_ratios,), 'swap_dimensions': (['Off', 'On'],), 'upscale_factor': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 100.0, 'step': 0.1}), 'prescale_factor': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 100.0, 'step': 0.1}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}} + RETURN_TYPES = ('INT', 'INT', 'FLOAT', 'FLOAT', 'INT', 'LATENT', 'STRING') + RETURN_NAMES = ('width', 'height', 'upscale_factor', 'prescale_factor', 'batch_size', 'empty_latent', 'show_help') + FUNCTION = 'Aspect_Ratio' + CATEGORY = icons.get('Comfyroll/Aspect Ratio') + + def Aspect_Ratio(self, width, height, aspect_ratio, swap_dimensions, upscale_factor, prescale_factor, batch_size): + if aspect_ratio == 'Large Rectangle - 336x280': + (width, height) = (336, 280) + elif aspect_ratio == 'Medium Rectangle - 300x250': + (width, height) = (300, 250) + elif aspect_ratio == 'Small Rectangle - 180x150': + (width, height) = (180, 150) + elif aspect_ratio == 'Square - 250x250': + (width, height) = (250, 250) + elif aspect_ratio == 'Small Square - 200x200': + (width, height) = (200, 200) + elif aspect_ratio == 'Button - 125x125': + (width, height) = (125, 125) + elif aspect_ratio == 'Half Page - 300x600': + (width, height) = (300, 600) + elif aspect_ratio == 'Vertical Banner - 120x240': + (width, height) = (120, 240) + elif aspect_ratio == 'Wide Skyscraper - 160x600': + (width, height) = (160, 600) + elif aspect_ratio == 'Skyscraper - 120x600': + (width, height) = (120, 600) + elif aspect_ratio == 'Billboard - 970x250': + (width, height) = (970, 250) + elif aspect_ratio == 'Portrait - 300x1050': + (width, height) = (300, 1050) + elif aspect_ratio == 'Banner - 468x60': + (width, height) = (168, 60) + elif aspect_ratio == 'Leaderboard - 728x90': + (width, height) = (728, 90) + if swap_dimensions == 'On': + (width, height) = (height, width) + width = int(width * prescale_factor) + height = int(height * prescale_factor) + latent = torch.zeros([batch_size, 4, height // 8, width // 8]) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Aspect-Ratio-Nodes#cr-aspect-ratio-banners' + return (width, height, upscale_factor, prescale_factor, batch_size, {'samples': latent}, show_help) +``` \ No newline at end of file diff --git a/docs/CR Aspect Ratio SDXL.md b/docs/CR Aspect Ratio SDXL.md new file mode 100644 index 0000000..52332ed --- /dev/null +++ b/docs/CR Aspect Ratio SDXL.md @@ -0,0 +1,109 @@ +# Documentation +- Class name: CR_AspectRatio_SDXL +- Category: Comfyroll/Essential/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_AspectRatio_SDXL 节点旨在根据指定的纵横比管理和调整图像尺寸。它允许选择预定义的纵横比或自定义输入,并提供交换维度和放大图像的选项。该节点确保图像正确格式化,以适应各种显示目的,增强了媒体处理任务的工作流程。 + +# Input types +## Required +- width + - 宽度参数定义了图像的水平尺寸。它对于设置初始尺寸和计算正确的纵横比至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置图像的垂直尺寸,与宽度一起工作以确定整个图像的大小。 + - Comfy dtype: INT + - Python dtype: int +- aspect_ratio + - aspect_ratio 参数确定图像尺寸之间的关系。它允许选择常见比例或自定义输入以满足特定要求。 + - Comfy dtype: COMBO['custom', '1:1 square 1024x1024', '3:4 portrait 896x1152', '5:8 portrait 832x1216', '9:16 portrait 768x1344', '9:21 portrait 640x1536', '4:3 landscape 1152x896', '3:2 landscape 1216x832', '16:9 landscape 1344x768', '21:9 landscape 1536x640'] + - Python dtype: str +## Optional +- swap_dimensions + - swap_dimensions 参数提供了交换宽度和高度值的选项,适用于需要反转图像方向的场景。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +- upscale_factor1 + - upscale_factor1 参数控制图像的第一级放大,允许在不改变纵横比的情况下调整图像大小。 + - Comfy dtype: FLOAT + - Python dtype: float +- upscale_factor2 + - upscale_factor2 参数管理图像的第二级放大,提供对图像最终尺寸的进一步控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - batch_size 参数指定同时处理多少张图像,这可以优化批量图像处理任务的性能。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- width + - 宽度输出反映了应用选定的纵横比和任何放大因子后图像调整后的水平尺寸。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度输出对应于考虑到纵横比和放大设置后图像调整的垂直尺寸。 + - Comfy dtype: INT + - Python dtype: int +- upscale_factor1 + - upscale_factor1 输出提供了应用于图像宽度的放大因子,影响最终分辨率。 + - Comfy dtype: FLOAT + - Python dtype: float +- upscale_factor2 + - upscale_factor2 输出指示应用于图像高度的次级放大因子,进一步细化分辨率。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - batch_size 输出表示每个周期内处理的图像数量,影响大规模图像处理的效率。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - show_help 输出提供了一个 URL 链接到文档,以获取有关节点功能的进一步帮助和信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_AspectRatio_SDXL: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 1024, 'min': 64, 'max': 2048}), 'height': ('INT', {'default': 1024, 'min': 64, 'max': 2048}), 'aspect_ratio': (['custom', '1:1 square 1024x1024', '3:4 portrait 896x1152', '5:8 portrait 832x1216', '9:16 portrait 768x1344', '9:21 portrait 640x1536', '4:3 landscape 1152x896', '3:2 landscape 1216x832', '16:9 landscape 1344x768', '21:9 landscape 1536x640'],), 'swap_dimensions': (['Off', 'On'],), 'upscale_factor1': ('FLOAT', {'default': 1, 'min': 1, 'max': 2000}), 'upscale_factor2': ('FLOAT', {'default': 1, 'min': 1, 'max': 2000}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}} + RETURN_TYPES = ('INT', 'INT', 'FLOAT', 'FLOAT', 'INT', 'STRING') + RETURN_NAMES = ('INT', 'INT', 'FLOAT', 'FLOAT', 'INT', 'show_help') + FUNCTION = 'Aspect_Ratio' + CATEGORY = icons.get('Comfyroll/Essential/Legacy') + + def Aspect_Ratio(self, width, height, aspect_ratio, swap_dimensions, upscale_factor1, upscale_factor2, batch_size): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Legacy-Nodes#cr-aspect-ratio-sdxl' + if aspect_ratio == '1:1 square 1024x1024': + (width, height) = (1024, 1024) + elif aspect_ratio == '3:4 portrait 896x1152': + (width, height) = (896, 1152) + elif aspect_ratio == '5:8 portrait 832x1216': + (width, height) = (832, 1216) + elif aspect_ratio == '9:16 portrait 768x1344': + (width, height) = (768, 1344) + elif aspect_ratio == '9:21 portrait 640x1536': + (width, height) = (640, 1536) + elif aspect_ratio == '4:3 landscape 1152x896': + (width, height) = (1152, 896) + elif aspect_ratio == '3:2 landscape 1216x832': + (width, height) = (1216, 832) + elif aspect_ratio == '16:9 landscape 1344x768': + (width, height) = (1344, 768) + elif aspect_ratio == '21:9 landscape 1536x640': + (width, height) = (1536, 640) + if swap_dimensions == 'On': + return (height, width, upscale_factor1, upscale_factor2, batch_size, show_help) + else: + return (width, height, upscale_factor1, upscale_factor2, batch_size, show_help) +``` \ No newline at end of file diff --git a/docs/CR Aspect Ratio Social Media.md b/docs/CR Aspect Ratio Social Media.md new file mode 100644 index 0000000..be9e32c --- /dev/null +++ b/docs/CR Aspect Ratio Social Media.md @@ -0,0 +1,127 @@ +# Documentation +- Class name: CR_AspectRatioSocialMedia +- Category: icons.get('Comfyroll/Aspect Ratio') +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +该节点旨在根据特定社交媒体平台的要求处理和调整图像尺寸,确保最佳展示效果和用户参与度。 + +# Input types +## Required +- width + - 宽度是决定图像水平维度的基本参数,影响其在不同社交媒体平台上的长宽比和整体外观。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度是定义图像垂直维度的关键参数,与宽度一起工作,以满足社交媒体平台的长宽比要求。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- aspect_ratio + - 长宽比预设允许快速选择针对各种社交媒体平台优化的尺寸,简化图像准备过程。 + - Comfy dtype: COMBO + - Python dtype: str +- swap_dimensions + - 交换维度选项使得宽度和高度可以互换,提供了满足某些社交媒体平台特定要求的灵活性。 + - Comfy dtype: COMBO + - Python dtype: str +- upscale_factor + - 放大因子用于扩大图像尺寸,可以提高在社交媒体平台上展示时的图像质量和可见度。 + - Comfy dtype: FLOAT + - Python dtype: float +- prescale_factor + - 预缩放因子用于在进一步处理之前调整初始图像大小,影响最终输出的分辨率和在社交媒体上的性能。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - 批处理大小决定了同时处理的图像数量,可以提高在处理多个社交媒体图像调整时的效率和吞吐量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- width + - 调整后的图像宽度,针对所选社交媒体平台进行优化,确保正确的显示和参与度。 + - Comfy dtype: INT + - Python dtype: int +- height + - 调整后的图像高度,为满足所选社交媒体平台的要求而定制,以实现最佳展示效果。 + - Comfy dtype: INT + - Python dtype: int +- upscale_factor + - 用于图像的原始放大因子,指示应用于尺寸的放大程度,以实现社交媒体的最佳显示。 + - Comfy dtype: FLOAT + - Python dtype: float +- prescale_factor + - 用于图像的原始预缩放因子,表示在进一步处理之前进行的初始大小调整,以实现社交媒体优化。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - 批处理中处理的图像数量,反映了处理多个社交媒体平台图像调整的效率。 + - Comfy dtype: INT + - Python dtype: int +- empty_latent + - 图像的占位潜在表示,用于在社交媒体优化工作流程中进行潜在的进一步处理或分析。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- show_help + - 一个链接到文档的链接,用于进一步指导和了解如何使用节点进行社交媒体长宽比优化。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_AspectRatioSocialMedia: + + @classmethod + def INPUT_TYPES(s): + aspect_ratios = ['custom', 'Instagram Portrait - 1080x1350', 'Instagram Square - 1080x1080', 'Instagram Landscape - 1080x608', 'Instagram Stories/Reels - 1080x1920', 'Facebook Landscape - 1080x1350', 'Facebook Marketplace - 1200x1200', 'Facebook Stories - 1080x1920', 'TikTok - 1080x1920', 'YouTube Banner - 2560×1440', 'LinkedIn Profile Banner - 1584x396', 'LinkedIn Page Cover - 1128x191', 'LinkedIn Post - 1200x627', 'Pinterest Pin Image - 1000x1500', 'CivitAI Cover - 1600x400', 'OpenArt App - 1500x1000'] + return {'required': {'width': ('INT', {'default': 1024, 'min': 64, 'max': 8192}), 'height': ('INT', {'default': 1024, 'min': 64, 'max': 8192}), 'aspect_ratio': (aspect_ratios,), 'swap_dimensions': (['Off', 'On'],), 'upscale_factor': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 100.0, 'step': 0.1}), 'prescale_factor': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 100.0, 'step': 0.1}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}} + RETURN_TYPES = ('INT', 'INT', 'FLOAT', 'FLOAT', 'INT', 'LATENT', 'STRING') + RETURN_NAMES = ('width', 'height', 'upscale_factor', 'prescale_factor', 'batch_size', 'empty_latent', 'show_help') + FUNCTION = 'Aspect_Ratio' + CATEGORY = icons.get('Comfyroll/Aspect Ratio') + + def Aspect_Ratio(self, width, height, aspect_ratio, swap_dimensions, upscale_factor, prescale_factor, batch_size): + if aspect_ratio == 'Instagram Portrait - 1080x1350': + (width, height) = (1080, 1350) + elif aspect_ratio == 'Instagram Square - 1080x1080': + (width, height) = (1080, 1080) + elif aspect_ratio == 'Instagram Landscape - 1080x608': + (width, height) = (1080, 608) + elif aspect_ratio == 'Instagram Stories/Reels - 1080x1920': + (width, height) = (1080, 1920) + elif aspect_ratio == 'Facebook Landscape - 1080x1350': + (width, height) = (1080, 1350) + elif aspect_ratio == 'Facebook Marketplace - 1200x1200': + (width, height) = (1200, 1200) + elif aspect_ratio == 'Facebook Stories - 1080x1920': + (width, height) = (1080, 1920) + elif aspect_ratio == 'TikTok - 1080x1920': + (width, height) = (1080, 1920) + elif aspect_ratio == 'YouTube Banner - 2560×1440': + (width, height) = (2560, 1440) + elif aspect_ratio == 'LinkedIn Profile Banner - 1584x396': + (width, height) = (1584, 396) + elif aspect_ratio == 'LinkedIn Page Cover - 1128x191': + (width, height) = (1584, 396) + elif aspect_ratio == 'LinkedIn Post - 1200x627': + (width, height) = (1200, 627) + elif aspect_ratio == 'Pinterest Pin Image - 1000x1500': + (width, height) = (1000, 1500) + elif aspect_ratio == 'Pinterest Cover Image - 1920x1080': + (width, height) = (1920, 1080) + elif aspect_ratio == 'CivitAI Cover - 1600x400': + (width, height) = (1600, 400) + elif aspect_ratio == 'OpenArt App - 1500x1000': + (width, height) = (1500, 1000) + if swap_dimensions == 'On': + (width, height) = (height, width) + width = int(width * prescale_factor) + height = int(height * prescale_factor) + latent = torch.zeros([batch_size, 4, height // 8, width // 8]) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Aspect-Ratio-Nodes#cr-aspect-ratio-scial-media' + return (width, height, upscale_factor, prescale_factor, batch_size, {'samples': latent}, show_help) +``` \ No newline at end of file diff --git a/docs/CR Aspect Ratio.md b/docs/CR Aspect Ratio.md new file mode 100644 index 0000000..ce8d1aa --- /dev/null +++ b/docs/CR Aspect Ratio.md @@ -0,0 +1,133 @@ +# Documentation +- Class name: CR_AspectRatio +- Category: Comfyroll/Aspect Ratio +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_AspectRatio节点旨在操作和定义图像的纵横比。它提供了各种预设的纵横比,并允许自定义尺寸。该节点的功能使用户能够选择一个纵横比,选择是否交换维度,并应用缩放因子以实现所需的输出尺寸。它还支持批量处理以提高效率。 + +# Input types +## Required +- width + - “width”参数指定了图像的期望宽度。它在确定图像的纵横比和最终尺寸中起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- height + - “height”参数定义了图像的期望高度。它与“width”参数一起工作,以建立图像的纵横比。 + - Comfy dtype: INT + - Python dtype: int +- aspect_ratio + - “aspect_ratio”参数允许用户从预定义的纵横比列表中选择或输入自定义的纵横比。它是节点操作的核心,因为它决定了输出图像的比例。 + - Comfy dtype: STRING + - Python dtype: str +- swap_dimensions + - “swap_dimensions”参数提供了一个选项来交换宽度和高度值。这在某些图像操作中非常有用,其中图像的方向很重要。 + - Comfy dtype: STRING + - Python dtype: str +- upscale_factor + - “upscale_factor”参数用于增加图像的大小。它将当前尺寸乘以指定的因子,提高分辨率。 + - Comfy dtype: FLOAT + - Python dtype: float +- prescale_factor + - “prescale_factor”参数应用于调整任何其他转换之前的初始尺寸。它可以用于优化处理或实现特定的设计要求。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - “batch_size”参数决定了单次操作中处理的图像数量。它对于管理计算资源和提高工作流程效率至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- width + - “width”输出提供了应用所有转换后图像的最终宽度。 + - Comfy dtype: INT + - Python dtype: int +- height + - “height”输出给出了处理后图像的最终高度。 + - Comfy dtype: INT + - Python dtype: int +- upscale_factor + - “upscale_factor”输出反映了用于放大图像的缩放因子。 + - Comfy dtype: FLOAT + - Python dtype: float +- prescale_factor + - “prescale_factor”输出指示应用于图像尺寸的初始缩放因子。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - “batch_size”输出表示操作中处理的图像数量。 + - Comfy dtype: INT + - Python dtype: int +- empty_latent + - “empty_latent”输出是用于后续图像处理任务中可能使用的潜在表示的占位符。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- show_help + - “show_help”输出提供了一个URL链接到文档,以获得进一步的指导和帮助。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_AspectRatio: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + aspect_ratios = ['custom', 'SD1.5 - 1:1 square 512x512', 'SD1.5 - 2:3 portrait 512x768', 'SD1.5 - 3:4 portrait 512x682', 'SD1.5 - 3:2 landscape 768x512', 'SD1.5 - 4:3 landscape 682x512', 'SD1.5 - 16:9 cinema 910x512', 'SD1.5 - 1.85:1 cinema 952x512', 'SD1.5 - 2:1 cinema 1024x512', 'SDXL - 1:1 square 1024x1024', 'SDXL - 3:4 portrait 896x1152', 'SDXL - 5:8 portrait 832x1216', 'SDXL - 9:16 portrait 768x1344', 'SDXL - 9:21 portrait 640x1536', 'SDXL - 4:3 landscape 1152x896', 'SDXL - 3:2 landscape 1216x832', 'SDXL - 16:9 landscape 1344x768', 'SDXL - 21:9 landscape 1536x640'] + return {'required': {'width': ('INT', {'default': 1024, 'min': 64, 'max': 8192}), 'height': ('INT', {'default': 1024, 'min': 64, 'max': 8192}), 'aspect_ratio': (aspect_ratios,), 'swap_dimensions': (['Off', 'On'],), 'upscale_factor': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 100.0, 'step': 0.1}), 'prescale_factor': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 100.0, 'step': 0.1}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}} + RETURN_TYPES = ('INT', 'INT', 'FLOAT', 'FLOAT', 'INT', 'LATENT', 'STRING') + RETURN_NAMES = ('width', 'height', 'upscale_factor', 'prescale_factor', 'batch_size', 'empty_latent', 'show_help') + FUNCTION = 'Aspect_Ratio' + CATEGORY = icons.get('Comfyroll/Aspect Ratio') + + def Aspect_Ratio(self, width, height, aspect_ratio, swap_dimensions, upscale_factor, prescale_factor, batch_size): + if aspect_ratio == 'SD1.5 - 1:1 square 512x512': + (width, height) = (512, 512) + elif aspect_ratio == 'SD1.5 - 2:3 portrait 512x768': + (width, height) = (512, 768) + elif aspect_ratio == 'SD1.5 - 16:9 cinema 910x512': + (width, height) = (910, 512) + elif aspect_ratio == 'SD1.5 - 3:4 portrait 512x682': + (width, height) = (512, 682) + elif aspect_ratio == 'SD1.5 - 3:2 landscape 768x512': + (width, height) = (768, 512) + elif aspect_ratio == 'SD1.5 - 4:3 landscape 682x512': + (width, height) = (682, 512) + elif aspect_ratio == 'SD1.5 - 1.85:1 cinema 952x512': + (width, height) = (952, 512) + elif aspect_ratio == 'SD1.5 - 2:1 cinema 1024x512': + (width, height) = (1024, 512) + elif aspect_ratio == 'SD1.5 - 2.39:1 anamorphic 1224x512': + (width, height) = (1224, 512) + if aspect_ratio == 'SDXL - 1:1 square 1024x1024': + (width, height) = (1024, 1024) + elif aspect_ratio == 'SDXL - 3:4 portrait 896x1152': + (width, height) = (896, 1152) + elif aspect_ratio == 'SDXL - 5:8 portrait 832x1216': + (width, height) = (832, 1216) + elif aspect_ratio == 'SDXL - 9:16 portrait 768x1344': + (width, height) = (768, 1344) + elif aspect_ratio == 'SDXL - 9:21 portrait 640x1536': + (width, height) = (640, 1536) + elif aspect_ratio == 'SDXL - 4:3 landscape 1152x896': + (width, height) = (1152, 896) + elif aspect_ratio == 'SDXL - 3:2 landscape 1216x832': + (width, height) = (1216, 832) + elif aspect_ratio == 'SDXL - 16:9 landscape 1344x768': + (width, height) = (1344, 768) + elif aspect_ratio == 'SDXL - 21:9 landscape 1536x640': + (width, height) = (1536, 640) + if swap_dimensions == 'On': + (width, height) = (height, width) + width = int(width * prescale_factor) + height = int(height * prescale_factor) + latent = torch.zeros([batch_size, 4, height // 8, width // 8]) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Aspect-Ratio-Nodes#cr-aspect-ratio' + return (width, height, upscale_factor, prescale_factor, batch_size, {'samples': latent}, show_help) +``` \ No newline at end of file diff --git a/docs/CR Batch Images From List.md b/docs/CR Batch Images From List.md new file mode 100644 index 0000000..c6425f4 --- /dev/null +++ b/docs/CR Batch Images From List.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: CR_MakeBatchFromImageList +- Category: Comfyroll/List/Utils +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_MakeBatchFromImageList节点旨在接收一系列图像,并将它们高效地合并成一个批次张量。这一过程简化了图像数据的处理,使得图像处理工作流程更加高效。该节点的功能在优化从单个图像文件到适合批量操作的格式的转换中起着关键作用,从而提高了图像处理流程的整体性能和效率。 + +# Input types +## Required +- image_list + - image_list参数是节点的关键输入,代表需要批处理的图像数据集合。此参数通过确定输出批次张量的内容和结构,直接影响节点的操作。image_list对于节点执行其创建图像批次以进行进一步处理的预期功能至关重要。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Output types +- image_batch + - image_batch输出是节点生成的代表图像批次的连接张量。它是节点操作的直接结果,对于需要批量数据的后续图像处理任务具有重要意义。此输出使得图像处理流程能够以必要的批量格式无缝继续。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help输出提供了一个指向文档的URL链接,以供进一步帮助。它作为用户可能需要额外指导的有用资源,以了解如何使用节点或理解其功能。这个输出对于新用户或当解决与节点操作相关的问题时特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_MakeBatchFromImageList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image_list': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image_batch', 'show_help') + INPUT_IS_LIST = True + FUNCTION = 'make_batch' + CATEGORY = icons.get('Comfyroll/List/Utils') + + def make_batch(self, image_list): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-binary-to-list' + if len(image_list) <= 1: + return (image_list,) + batched_images = torch.cat(image_list, dim=0) + return (batched_images, show_help) +``` \ No newline at end of file diff --git a/docs/CR Batch Process Switch.md b/docs/CR Batch Process Switch.md new file mode 100644 index 0000000..6ad0adb --- /dev/null +++ b/docs/CR Batch Process Switch.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CR_BatchProcessSwitch +- Category: Comfyroll/Utils/Process +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_BatchProcessSwitch 节点旨在提供一种机制,用于在不同类型的图像输入之间进行切换。它基于输入选择智能地路由处理流程,允许处理单个图像和图像批次。在需要根据输入类型动态适应处理逻辑的场景中,该节点至关重要,确保了图像处理工作流程的灵活性和效率。 + +# Input types +## Required +- Input + - 'Input' 参数至关重要,因为它决定了要执行的图像处理类型。它决定了节点将处理单个图像还是图像批次,从而影响工作流中的后续步骤和输出。 + - Comfy dtype: COMBO[image, image batch] + - Python dtype: str +## Optional +- image + - 'image' 参数用于处理单个图像时使用。它很重要,因为它代表了单个图像处理任务的输入,使节点能够处理特定于图像的操作。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] +- image_batch + - 'image_batch' 参数对于处理一组图像至关重要。它允许节点有效地管理和处理图像批次,适用于需要批量操作的场景。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, List[torch.Tensor]] + +# Output types +- IMAGE + - 'IMAGE' 输出参数表示根据输入选择处理后的图像或图像批次。它是节点操作的关键结果,包含了图像处理任务的结果。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor, List[torch.Tensor]] +- show_help + - 'show_help' 输出提供了一个文档链接,用于进一步的帮助。它很重要,因为它为用户提供了一个资源,以更详细地了解节点的功能和用法。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_BatchProcessSwitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': (['image', 'image batch'],)}, 'optional': {'image': ('IMAGE',), 'image_batch': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Utils/Process') + + def switch(self, Input, image=None, image_batch=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Process-Nodes#cr-batch-process-switch' + if Input == 'image': + return (image, show_help) + else: + return (image_batch, show_help) +``` \ No newline at end of file diff --git a/docs/CR Binary Pattern.md b/docs/CR Binary Pattern.md new file mode 100644 index 0000000..8c31b05 --- /dev/null +++ b/docs/CR Binary Pattern.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: CR_BinaryPattern +- Category: Comfyroll/Graphics/Pattern +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_BinaryPattern 节点旨在从二进制字符串生成视觉图案。它接受二进制模式输入,将其渲染为彩色方块的网格,提供了一种将二进制数据以图形格式可视化的方法。这个节点特别适用于基于二进制序列创建复杂的设计和图案,提供了一种独特的数据可视化方式。 + +# Input types +## Required +- binary_pattern + - 二进制模式输入是节点的关键参数,因为它直接决定了视觉输出。这是一个表示用于构建模式的一系列二进制数字的多行字符串。最终模式的复杂性和设计在很大程度上受此输入的影响。 + - Comfy dtype: STRING + - Python dtype: str +- width + - 宽度参数决定了输出图像的宽度,以像素为单位,这对于设置图案的整体尺寸至关重要。它与高度参数协同工作,以确保图案被适当缩放以适应所需的长宽比。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置输出图像的垂直尺寸,与宽度参数一起确定图案的大小。它是控制图案整体外观和可缩放性的关键因素。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- background_color + - 背景颜色参数允许自定义图案的背景,影响渲染图案的整体视觉吸引力和对比度。它可以设置为各种预定义颜色或自定义的十六进制颜色值。 + - Comfy dtype: COLORS + - Python dtype: str +- outline_color + - 轮廓颜色参数定义了方块轮廓的颜色,增加了一层细节,并增强了图案与背景的可见性。它可以调整以匹配或与图案的颜色形成对比,以实现风格化的目的。 + - Comfy dtype: COLORS + - Python dtype: str + +# Output types +- IMAGE + - IMAGE 输出提供了渲染后的二进制模式作为图像,可以用于进一步处理或显示。它代表了节点功能的顶点,展示了输入二进制模式的视觉表示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了指向节点文档页面的 URL,为用户提供了关于如何有效使用节点的额外信息和指导。它是了解节点能力和潜在用例的有用资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_BinaryPattern: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'binary_pattern': ('STRING', {'multiline': True, 'default': '10101'}), 'width': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'background_color': (COLORS,), 'color_0': (COLORS,), 'color_1': (COLORS,), 'outline_thickness': ('INT', {'default': 0, 'min': 0, 'max': 1024}), 'outline_color': (COLORS,), 'jitter_distance': ('INT', {'default': 0, 'min': 0, 'max': 1024}), 'bias': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.05})}, 'optional': {'bg_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'color0_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'color1_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'outline_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'draw_pattern' + CATEGORY = icons.get('Comfyroll/Graphics/Pattern') + + def draw_pattern(self, binary_pattern, width, height, background_color, outline_color, color_0='white', color_1='black', outline_thickness=0, color0_hex='#000000', color1_hex='#000000', bg_color_hex='#000000', outline_color_hex='#000000', jitter_distance=0, bias=0.5): + color0 = get_color_values(color_0, color0_hex, color_mapping) + color1 = get_color_values(color_1, color1_hex, color_mapping) + bg_color = get_color_values(background_color, bg_color_hex, color_mapping) + outline_color = get_color_values(outline_color, outline_color_hex, color_mapping) + rows = binary_pattern.strip().split('\n') + grid = [[int(bit) for bit in row.strip()] for row in rows] + square_width = width / len(rows[0]) + square_height = height / len(rows) + image = Image.new('RGB', (width, height), color=bg_color) + draw = ImageDraw.Draw(image) + x_jitter = 0 + y_jitter = 0 + for (row_index, row) in enumerate(grid): + for (col_index, bit) in enumerate(row): + if jitter_distance != 0: + x_jitter = random.uniform(0, jitter_distance) + y_jitter = random.uniform(0, jitter_distance) + x1 = col_index * square_width + x_jitter + y1 = row_index * square_height + y_jitter + x2 = x1 + square_width + x_jitter + y2 = y1 + square_height + y_jitter + if random.uniform(0, 1) < abs(bias): + color = color1 + else: + color = color0 + draw.rectangle([x1, y1, x2, y2], fill=color, outline=outline_color, width=outline_thickness) + image_out = pil2tensor(image) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pattern-Nodes-2#cr-binary-pattern' + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Binary To Bit List.md b/docs/CR Binary To Bit List.md new file mode 100644 index 0000000..2643074 --- /dev/null +++ b/docs/CR Binary To Bit List.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: CR_BinaryToBitList +- Category: Comfyroll/List +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_BinaryToBitList 节点旨在将二进制字符串转换为单个位的列表。它接受一个二进制字符串作为输入,输出一个列表,其中每个元素对应输入字符串中的一个位。这个节点特别适用于以更细致和易于访问的方式处理二进制数据。 + +# Input types +## Required +- bit_string + - “bit_string”参数是一个必填输入,期望一个包含二进制数据的字符串。这个字符串是节点操作的主要数据源,将其转换为位列表是节点的核心功能。二进制字符串的正确格式化对于节点按预期工作至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- list_out + - “list_out”输出是一个字符串列表,其中每个字符串代表从输入的二进制字符串派生出的一位。此输出允许用户在位级别上操作和分析二进制数据,促进诸如数据编码、解码或转换等操作。 + - Comfy dtype: STRING + - Python dtype: List[str] +- show_help + - “show_help”输出提供了一个URL链接,用于获取更多帮助信息的文档。它将用户引导到GitHub wiki页面,在那里他们可以找到有关如何使用该节点及其相关特性的更多信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_BinaryToBitList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'bit_string': ('STRING', {'multiline': True, 'default': ''})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + OUTPUT_IS_LIST = (True, False) + FUNCTION = 'make_list' + CATEGORY = icons.get('Comfyroll/List') + + def make_list(self, bit_string): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-binary-to-list' + list_out = [str(bit) for bit in bit_string] + return (list_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Bit Schedule.md b/docs/CR Bit Schedule.md new file mode 100644 index 0000000..8dcefcf --- /dev/null +++ b/docs/CR Bit Schedule.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: CR_BitSchedule +- Category: Comfyroll/Animation/Schedule +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_BitSchedule 节点旨在根据二进制字符串输入生成一个时间表,能够指定间隔和循环次数。它处理二进制字符串以创建一系列预定事件,这在项目中的动画和时间安排上特别有用。 + +# Input types +## Required +- binary_string + - 二进制字符串是节点用来创建时间表的二进制数字(0和1)序列。字符串中的每个位对应时间表中的一个事件,时间表将根据指定的循环次数重复。 + - Comfy dtype: STRING + - Python dtype: str +- interval + - 间隔参数决定了序列中预定事件之间的间距。它是一个直接影响时间表时间的整数值。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- loops + - 循环参数指定时间表应该重复多少次。它是一个可选的整数,允许定制时间表的持续时间。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- SCHEDULE + - 输出时间表是一个字符串,代表基于输入的二进制字符串、间隔和循环生成的预定事件序列。它用于应用内的进一步处理或显示。 + - Comfy dtype: STRING + - Python dtype: str +- show_text + - show_text 输出提供了一个指向帮助文档的 URL,该文档提供了关于如何使用节点生成的时间表的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_BitSchedule: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'binary_string': ('STRING', {'multiline': True, 'default': ''}), 'interval': ('INT', {'default': 1, 'min': 1, 'max': 99999}), 'loops': ('INT', {'default': 1, 'min': 1, 'max': 99999})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('SCHEDULE', 'show_text') + FUNCTION = 'bit_schedule' + CATEGORY = icons.get('Comfyroll/Animation/Schedule') + + def bit_schedule(self, binary_string, interval, loops=1): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Schedule-Nodes#cr-bit-schedule' + schedule = [] + binary_string = binary_string.replace(' ', '').replace('\n', '') + '\n for i in range(len(binary_string) * loops):\n index = i % len(binary_string) # Use modulo to ensure the index continues in a single sequence\n bit = int(binary_string[index])\n schedule.append(f"{i},{bit}")\n ' + for i in range(len(binary_string) * loops): + schedule_index = i * interval + bit_index = i % len(binary_string) + bit = int(binary_string[bit_index]) + schedule.append(f'{schedule_index},{bit}') + schedule_out = '\n'.join(schedule) + return (schedule_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Central Schedule.md b/docs/CR Central Schedule.md new file mode 100644 index 0000000..be448d8 --- /dev/null +++ b/docs/CR Central Schedule.md @@ -0,0 +1,102 @@ +# Documentation +- Class name: CR_CentralSchedule +- Category: Animation/Schedule +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +该节点通过整合多种类型的输入,包括文本、提示和模型,来创建和管理复杂的动画时间表,以生成动画执行的连贯和动态时间线。 + +# Input types +## Required +- schedule_1 + - 主要的调度文本,概述动画动作的顺序。它是节点操作的核心,因为它为时间表构建提供了基础。 + - Comfy dtype: STRING + - Python dtype: str +- schedule_type1 + - 指定时间表的类型,影响节点如何解释和处理输入文本,影响动画时间表的整体结构和执行。 + - Comfy dtype: COMBO + - Python dtype: str +- schedule_format + - 决定最终时间表的呈现格式,影响动画时间表的可读性和可用性,以供进一步处理或审查。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- schedule_alias1 + - 第一个时间表的别名,可用于参考或标记目的,提高动画时间表的可读性和组织性。 + - Comfy dtype: STRING + - Python dtype: str +- schedule_2 + - 补充主要时间表的额外时间表文本,允许更复杂的动画序列和动作层叠。 + - Comfy dtype: STRING + - Python dtype: str +- schedule_type2 + - 为第二个时间表定义类型,指导节点处理并将其与主要时间表整合,形成一个全面的动画计划。 + - Comfy dtype: COMBO + - Python dtype: str +- schedule_alias2 + - 第二个时间表的别名,有助于在动画时间线内识别和管理多个时间表。 + - Comfy dtype: STRING + - Python dtype: str +- schedule_3 + - 第三个时间表文本,进一步扩展动画序列,使节点能够处理具有多个层和复杂时间的复杂动画。 + - Comfy dtype: STRING + - Python dtype: str +- schedule_type3 + - 指示第三个时间表的类型,帮助节点在整体时间表内组织和执行额外的动画层。 + - Comfy dtype: COMBO + - Python dtype: str +- schedule_alias3 + - 第三个时间表的别名,为涉及多个时间表的复杂动画序列提供清晰度和易于管理。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- SCHEDULE + - 编译和格式化的动画时间表,以结构化格式封装动作和时间的顺序,用于动画系统中的执行。 + - Comfy dtype: SCHEDULE + - Python dtype: Tuple[str, List[Tuple[str, str]]] +- show_text + - 动画时间表的人类可读表示,提供序列和细节的清晰概览,供审查和参考。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_CentralSchedule: + + @classmethod + def INPUT_TYPES(cls): + schedule_types = ['Value', 'Text', 'Prompt', 'Prompt Weight', 'Model', 'LoRA', 'ControlNet', 'Style', 'Upscale', 'Camera', 'Job'] + return {'required': {'schedule_1': ('STRING', {'multiline': True, 'default': 'schedule'}), 'schedule_type1': (schedule_types,), 'schedule_alias1': ('STRING', {'multiline': False, 'default': ''}), 'schedule_2': ('STRING', {'multiline': True, 'default': 'schedule'}), 'schedule_type2': (schedule_types,), 'schedule_alias2': ('STRING', {'multiline': False, 'default': ''}), 'schedule_3': ('STRING', {'multiline': True, 'default': 'schedule'}), 'schedule_type3': (schedule_types,), 'schedule_alias3': ('STRING', {'multiline': False, 'default': ''}), 'schedule_format': (['CR', 'Deforum'],)}, 'optional': {'schedule': ('SCHEDULE',)}} + RETURN_TYPES = ('SCHEDULE', 'STRING') + RETURN_NAMES = ('SCHEDULE', 'show_text') + FUNCTION = 'build_schedule' + CATEGORY = icons.get('Comfyroll/Animation/Schedule') + + def build_schedule(self, schedule_1, schedule_type1, schedule_alias1, schedule_2, schedule_type2, schedule_alias2, schedule_3, schedule_type3, schedule_alias3, schedule_format, schedule=None): + schedules = list() + schedule_text = list() + if schedule is not None: + schedules.extend([l for l in schedule]) + (schedule_text.extend([l for l in schedule]),) + if schedule_1 != '' and schedule_alias1 != '': + lines = schedule_1.split('\n') + for line in lines: + (schedules.extend([(schedule_alias1, line)]),) + (schedule_text.extend([schedule_alias1 + ',' + schedule_1 + '\n']),) + if schedule_2 != '' and schedule_alias2 != '': + lines = schedule_2.split('\n') + for line in lines: + (schedules.extend([(schedule_alias2, line)]),) + (schedule_text.extend([schedule_alias2 + ',' + schedule_2 + '\n']),) + if schedule_3 != '' and schedule_alias3 != '': + lines = schedule_3.split('\n') + for line in lines: + (schedules.extend([(schedule_alias3, line)]),) + (schedule_text.extend([schedule_alias3 + ',' + schedule_3 + '\n']),) + show_text = ''.join(schedule_text) + return (schedules, show_text) +``` \ No newline at end of file diff --git a/docs/CR Checker Pattern.md b/docs/CR Checker Pattern.md new file mode 100644 index 0000000..fce66c2 --- /dev/null +++ b/docs/CR Checker Pattern.md @@ -0,0 +1,109 @@ +# Documentation +- Class name: CR_CheckerPattern +- Category: Comfyroll/Graphics/Pattern +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_CheckerPattern 是一个用于生成可定制参数的棋盘格模式的节点。它允许用户定义图案的模式、输出图像的尺寸以及图案中使用的颜色。该节点的功能集中在创建具有交替颜色的视觉网格图案表示,为图形设计和可视化提供了一个多功能工具。 + +# Input types +## Required +- mode + - 模式参数决定了图案的布局,可以是'regular'标准的棋盘格或'stepped'错位模式。这个选择显著影响节点的视觉输出,允许不同的设计选项。 + - Comfy dtype: MODE + - Python dtype: str +- width + - 宽度参数设置了生成图像的宽度,以像素为单位。它是决定图案整体大小和分辨率的关键因素,影响图案在各种应用中的显示和使用。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置了生成图像的高度,以像素为单位。它与宽度一起定义了画布的尺寸,这对于图案的比例和长宽比至关重要。 + - Comfy dtype: INT + - Python dtype: int +- color_1 + - Color_1 用于定义棋盘格图案的第一种颜色。它在图案的整体外观中起着重要作用,允许对设计的美学进行创造性控制。 + - Comfy dtype: COLOR + - Python dtype: str +- color_2 + - Color_2 用于定义棋盘格图案的第二种颜色。它与 Color_1 配合使用,创造出棋盘格设计特有的对比色块。 + - Comfy dtype: COLOR + - Python dtype: str +- grid_frequency + - grid_frequency 参数指示棋盘格图案中每行/每列的方格数。它是图案密度和单个方格大小的关键决定因素。 + - Comfy dtype: INT + - Python dtype: int +- step + - 步长参数在 'stepped' 模式中使用,用于控制方格的错位。它影响图案的复杂性和棋盘格的视觉节奏。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- color1_hex + - color1_hex 参数允许为 Color_1 使用自定义的十六进制颜色值。这为需要使用预定义颜色选项中没有的具体颜色阴影的用户提供了额外的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- color2_hex + - color2_hex 参数允许为 Color_2 使用自定义十六进制颜色值。它为用户提供了微调图案的次要颜色以满足其设计要求的能力。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - IMAGE 输出提供了生成分的棋盘格图案作为图像文件。这是节点操作的主要结果,也是节点创建视觉图案目的的心。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了指向节点文档页面的 URL 链接,以获取更多指导和信息。对于寻求有关节点功能和使用详细信息的用户来说,这是一个有用的资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_CheckerPattern: + + @classmethod + def INPUT_TYPES(s): + modes = ['regular', 'stepped'] + return {'required': {'mode': (modes,), 'width': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'color_1': (COLORS,), 'color_2': (COLORS,), 'grid_frequency': ('INT', {'default': 8, 'min': 1, 'max': 200, 'step': 1}), 'step': ('INT', {'default': 2, 'min': 2, 'max': 200, 'step': 1})}, 'optional': {'color1_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'color2_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'draw' + CATEGORY = icons.get('Comfyroll/Graphics/Pattern') + + def draw(self, mode, width, height, color_1, color_2, grid_frequency, step, color1_hex='#000000', color2_hex='#000000'): + if color_1 == 'custom': + color1_rgb = hex_to_rgb(color1_hex) + else: + color1_rgb = color_mapping.get(color_1, (255, 255, 255)) + if color_2 == 'custom': + color2_rgb = hex_to_rgb(color2_hex) + else: + color2_rgb = color_mapping.get(color_2, (0, 0, 0)) + canvas = np.zeros((height, width, 3), dtype=np.uint8) + grid_size = width / grid_frequency + for i in range(width): + for j in range(height): + if mode == 'regular': + if i // grid_size % 2 == j // grid_size % 2: + canvas[j, i] = color1_rgb + else: + canvas[j, i] = color2_rgb + elif mode == 'stepped': + if i // grid_size % step != j // grid_size % step: + canvas[j, i] = color1_rgb + else: + canvas[j, i] = color2_rgb + (fig, ax) = plt.subplots(figsize=(width / 100, height / 100)) + ax.imshow(canvas) + plt.axis('off') + plt.tight_layout(pad=0, w_pad=0, h_pad=0) + plt.autoscale(tight=True) + img_buf = io.BytesIO() + plt.savefig(img_buf, format='png') + img = Image.open(img_buf) + image_out = pil2tensor(img.convert('RGB')) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pattern-Nodes#cr-checker-pattern' + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Clamp Value.md b/docs/CR Clamp Value.md new file mode 100644 index 0000000..8a72180 --- /dev/null +++ b/docs/CR Clamp Value.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: CR_ClampValue +- Category: Comfyroll/Utils/Other +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ClampValue节点旨在确保给定值保持在指定范围内。它通过将输入值'a'限制在'range_min'和'range_max'之间来操作,从而确保输出始终在用户定义的可接受限制范围内。此功能对于维护数值稳定性和防止可能导致后续操作中的错误或意外行为的极端值至关重要。 + +# Input types +## Required +- a + - 参数'a'表示要被限制的值。这是一个关键的输入,因为节点的主要功能是确保这个值遵守指定的范围限制。节点的操作直接受到'a'的大小的影响,使其成为限制过程中的中心组件。 + - Comfy dtype: FLOAT + - Python dtype: float +- range_min + - 参数'range_min'定义了输入值'a'的可接受范围的下限。它在限制操作中起着重要作用,因为它设置了'a'可以达到的最小限制。这个参数对于防止输出低于期望的阈值至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- range_max + - 参数'range_max'在限制操作中设定了输入值'a'的上限。它至关重要,因为它决定了'a'可以取的最大值,从而防止输出超出设定的限制,并控制节点的结果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- a + - 输出'a'是被限制的值,已被调整以落在指定范围内。它是节点限制功能的直接结果,代表了在被'range_min'和'range_max'限制之后的'a'的值。这个输出很重要,因为它是节点操作的主要成果。 + - Comfy dtype: FLOAT + - Python dtype: float +- show_help + - 输出'show_help'提供了一个URL链接到文档,以获取有关节点使用的进一步帮助或信息。它作为对可能需要额外指导以有效使用节点的用户的有用资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ClampValue: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'a': ('FLOAT', {'default': 1, 'min': -18446744073709551615, 'max': 18446744073709551615}), 'range_min': ('FLOAT', {'default': 1, 'min': -18446744073709551615, 'max': 18446744073709551615}), 'range_max': ('FLOAT', {'default': 1, 'min': -18446744073709551615, 'max': 18446744073709551615})}} + RETURN_TYPES = ('FLOAT', 'STRING') + RETURN_NAMES = ('a', 'show_help') + FUNCTION = 'clamp_value' + CATEGORY = icons.get('Comfyroll/Utils/Other') + + def clamp_value(self, a, range_min, range_max): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-clamp-value' + a = max(range_min, min(a, range_max)) + return (a, show_help) +``` \ No newline at end of file diff --git a/docs/CR Clip Input Switch.md b/docs/CR Clip Input Switch.md new file mode 100644 index 0000000..755d906 --- /dev/null +++ b/docs/CR Clip Input Switch.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CR_ClipInputSwitch +- Category: Comfyroll/Utils/Logic +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ClipInputSwitch 是一个实用工具节点,旨在提供两个输入剪辑之间的条件切换机制。它基于单个输入参数运行,允许用户根据输入的值在两个提供的剪辑之间进行选择。该节点的功能集中在其能力上,通过智能选择适当的剪辑来简化工作流程,以进行进一步的处理或展示。 + +# Input types +## Required +- Input + - ‘Input’参数对于节点的操作至关重要,因为它决定了将返回哪个剪辑。当‘Input’的值为1时,选择‘clip1’;否则,选择‘clip2’。这个参数的作用在根据用户的特定需求确定节点输出时至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- clip1 + - ‘clip1’参数是一个可选输入,代表节点可以选择的第一个剪辑。当‘Input’参数设置为1时,它在进一步处理中扮演重要角色,因为它是被选择的输出。 + - Comfy dtype: CLIP + - Python dtype: Clip +- clip2 + - ‘clip2’参数是另一个可选输入,代表节点可以选择的第二个剪辑。当‘Input’参数不为1时,它的重要性显现出来,使‘clip2’成为后续操作的输出。 + - Comfy dtype: CLIP + - Python dtype: Clip + +# Output types +- CLIP + - ‘CLIP’输出基于‘Input’参数的值代表所选择的剪辑。它是节点的主要输出,并用于进一步的视频处理或展示。 + - Comfy dtype: CLIP + - Python dtype: Clip +- show_help + - ‘show_help’输出提供了指向节点文档的URL链接,以提供额外的指导。它是一个次要输出,为用户提供了轻松访问有关节点使用和功能更多信息的途径。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ClipInputSwitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': ('INT', {'default': 1, 'min': 1, 'max': 2})}, 'optional': {'clip1': ('CLIP',), 'clip2': ('CLIP',)}} + RETURN_TYPES = ('CLIP', 'STRING') + RETURN_NAMES = ('CLIP', 'show_help') + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Utils/Logic') + + def switch(self, Input, clip1=None, clip2=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Logic-Nodes#cr-clip-input-switch' + if Input == 1: + return (clip1, show_help) + else: + return (clip2, show_help) +``` \ No newline at end of file diff --git a/docs/CR Color Bars.md b/docs/CR Color Bars.md new file mode 100644 index 0000000..8c2453c --- /dev/null +++ b/docs/CR Color Bars.md @@ -0,0 +1,135 @@ +# Documentation +- Class name: CR_ColorBars +- Category: Comfyroll/Graphics/Pattern +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ColorBars 节点旨在生成具有可定制参数的颜色条的可视化表示。它允许用户指定条的朝向、频率和颜色,提供了一个多功能工具,用于创建图案或测试显示设备。此节点通过提供一种简单方法来产生和操作颜色条模式,为整个工作流程做出了贡献。 + +# Input types +## Required +- mode + - 模式参数决定了要生成的颜色条的类型。它对于设置图案的初始风格至关重要,并影响输出的整体外观。 + - Comfy dtype: COMBO['2-color'] + - Python dtype: str +- width + - 宽度参数设置了颜色条图案的宽度。它是节点功能的一个重要方面,因为它直接影响输出图像的尺寸。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数定义了颜色条图案的高度。与宽度类似,它是确定生成图像大小和比例的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- color_1 + - 颜色1参数指定了颜色条中使用的第一颜色。它在图案的视觉结果中扮演着重要角色,允许对颜色方案进行创造性控制。 + - Comfy dtype: COLORS + - Python dtype: str +- color_2 + - 颜色2参数设置了颜色条的第二种颜色。它与颜色1协同工作,创造出增强图案视觉冲击力的对比度。 + - Comfy dtype: COLORS + - Python dtype: str +- orientation + - 方向参数决定了颜色条排列的方向。它是一个基本设置,决定了图案的布局。 + - Comfy dtype: COMBO['vertical', 'horizontal', 'diagonal', 'alt_diagonal'] + - Python dtype: str +- bar_frequency + - 条频率参数控制颜色条的频率。它是决定图案中条的密度和间距的重要因素。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- offset + - 偏移参数调整颜色条的起始位置,允许微调图案的对齐方式。 + - Comfy dtype: FLOAT + - Python dtype: float +- color1_hex + - 颜色1十六进制参数允许用户输入第一种颜色的自定义十六进制颜色值,提供更大的灵活性和颜色选择的精确度。 + - Comfy dtype: STRING + - Python dtype: str +- color2_hex + - 颜色2十六进制参数使用户能够为第二种颜色指定自定义的十六进制颜色值,增强了节点产生广泛颜色组合的能力。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - 图像输出提供了作为图像生成的颜色条图案。它是节点执行的主要结果,对节点的目的至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个链接到文档的链接,以获取有关使用节点的进一步帮助和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ColorBars: + + @classmethod + def INPUT_TYPES(s): + modes = ['2-color'] + return {'required': {'mode': (modes,), 'width': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'color_1': (COLORS,), 'color_2': (COLORS,), 'orientation': (['vertical', 'horizontal', 'diagonal', 'alt_diagonal'],), 'bar_frequency': ('INT', {'default': 5, 'min': 1, 'max': 200, 'step': 1}), 'offset': ('FLOAT', {'default': 0, 'min': 0, 'max': 20, 'step': 0.05})}, 'optional': {'color1_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'color2_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'draw' + CATEGORY = icons.get('Comfyroll/Graphics/Pattern') + + def draw(self, mode, width, height, color_1, color_2, orientation, bar_frequency, offset=0, color1_hex='#000000', color2_hex='#000000'): + if color_1 == 'custom': + color1_rgb = hex_to_rgb(color1_hex) + else: + color1_rgb = color_mapping.get(color_1, (255, 255, 255)) + if color_2 == 'custom': + color2_rgb = hex_to_rgb(color2_hex) + else: + color2_rgb = color_mapping.get(color_2, (0, 0, 0)) + canvas = np.zeros((height, width, 3), dtype=np.uint8) + bar_width = width / bar_frequency + bar_height = height / bar_frequency + offset_pixels = int(offset * max(width, height)) + if orientation == 'vertical': + for j in range(height): + for i in range(width): + if (i + offset_pixels) // bar_width % 2 == 0: + canvas[j, i] = color1_rgb + else: + canvas[j, i] = color2_rgb + elif orientation == 'horizontal': + for j in range(height): + for i in range(width): + if (j + offset_pixels) // bar_height % 2 == 0: + canvas[j, i] = color1_rgb + else: + canvas[j, i] = color2_rgb + elif orientation == 'diagonal': + bar_width = int(bar_height / np.tan(np.pi / 4)) * 2 + for j in range(height): + for i in range(width): + bar_number = (i + j + offset_pixels) // bar_width + if bar_number % 2 == 0: + canvas[j, i] = color1_rgb + else: + canvas[j, i] = color2_rgb + elif orientation == 'alt_diagonal': + bar_width = int(bar_height / np.tan(np.pi / 4)) * 2 + for j in range(height): + for i in range(width): + bar_number = (i - j + width + offset_pixels) // bar_width + if bar_number % 2 == 0: + canvas[j, i] = color1_rgb + else: + canvas[j, i] = color2_rgb + (fig, ax) = plt.subplots(figsize=(width / 100, height / 100)) + ax.imshow(canvas) + plt.axis('off') + plt.tight_layout(pad=0, w_pad=0, h_pad=0) + plt.autoscale(tight=True) + img_buf = io.BytesIO() + plt.savefig(img_buf, format='png') + img = Image.open(img_buf) + image_out = pil2tensor(img.convert('RGB')) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pattern-Nodes#cr-color-bars' + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Color Gradient.md b/docs/CR Color Gradient.md new file mode 100644 index 0000000..715f098 --- /dev/null +++ b/docs/CR Color Gradient.md @@ -0,0 +1,121 @@ +# Documentation +- Class name: CR_ColorGradient +- Category: Comfyroll/Graphics/Pattern +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ColorGradient 节点旨在在两个指定颜色之间生成平滑的颜色渐变,可以水平或垂直地跨越画布。它允许自定义渐变的过渡和距离,为用户提供了一个多功能的工具,用于为各种应用创建视觉上吸引人的渐变。 + +# Input types +## Required +- width + - 宽度参数决定了渐变画布的宽度。它是设置输出图像尺寸的关键因素,影响渐变图案的整体规模。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置了画布的垂直尺寸,与宽度一起定义了画布的大小,并直接影响渐变的展示。 + - Comfy dtype: INT + - Python dtype: int +- start_color + - 开始颜色参数指定了渐变的初始颜色。它是一个基本输入,为颜色过渡的开始设定了基调。 + - Comfy dtype: COLORS + - Python dtype: str +- end_color + - 结束颜色参数决定了渐变的最终颜色。它与开始颜色一起工作,以在两种颜色之间创建一个无缝的过渡。 + - Comfy dtype: COLORS + - Python dtype: str +- orientation + - 方向参数决定了渐变是水平还是垂直渲染。这个选择显著改变了画布上颜色过渡的方向。 + - Comfy dtype: COMBO['vertical', 'horizontal'] + - Python dtype: str +## Optional +- linear_transition + - 线性过渡参数控制渐变过渡的中点,允许微调渐变在画布上的扩散。 + - Comfy dtype: FLOAT + - Python dtype: float +- gradient_distance + - 渐变距离参数调整渐变过渡发生的长度,影响颜色混合的平滑度和范围。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_color_hex + - 开始颜色十六进制参数允许使用自定义的十六进制颜色值作为渐变的起始颜色,为颜色选择提供了更大的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- end_color_hex + - 结束颜色十六进制参数允许指定渐变结束颜色的自定义十六进制颜色值,增强了用户定义颜色范围的能力。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - 图像输出提供了生成的颜色渐变作为图像,可以用于进一步的处理或展示目的。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - 帮助输出提供了一个链接到文档,以获得有关如何使用节点和理解其功能的进一步指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ColorGradient: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'start_color': (COLORS,), 'end_color': (COLORS,), 'gradient_distance': ('FLOAT', {'default': 1, 'min': 0, 'max': 2, 'step': 0.05}), 'linear_transition': ('FLOAT', {'default': 0.5, 'min': 0, 'max': 1, 'step': 0.05}), 'orientation': (['vertical', 'horizontal'],)}, 'optional': {'start_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'end_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'draw' + CATEGORY = icons.get('Comfyroll/Graphics/Pattern') + + def draw(self, width, height, start_color, end_color, orientation, linear_transition=0.5, gradient_distance=1, start_color_hex='#000000', end_color_hex='#000000'): + if start_color == 'custom': + color1_rgb = hex_to_rgb(start_color_hex) + else: + color1_rgb = color_mapping.get(start_color, (255, 255, 255)) + if end_color == 'custom': + color2_rgb = hex_to_rgb(end_color_hex) + else: + color2_rgb = color_mapping.get(end_color, (0, 0, 0)) + canvas = np.zeros((height, width, 3), dtype=np.uint8) + transition_pixel = int(linear_transition * (width if orientation == 'horizontal' else height)) + + def get_gradient_value(pos, length, linear_transition, gradient_distance): + transition_length = length * gradient_distance + transition_start = linear_transition * length - transition_length / 2 + transition_end = linear_transition * length + transition_length / 2 + if pos < transition_start: + return 0 + elif pos > transition_end: + return 1 + else: + return (pos - transition_start) / transition_length + if orientation == 'horizontal': + x = [0, width * linear_transition - 0.5 * width * gradient_distance, width * linear_transition + 0.5 * width * gradient_distance, width] + y = [0, 0, 1, 1] + t_values = np.interp(np.arange(width), x, y) + for (i, t) in enumerate(t_values): + interpolated_color = [int(c1 * (1 - t) + c2 * t) for (c1, c2) in zip(color1_rgb, color2_rgb)] + canvas[:, i] = interpolated_color + elif orientation == 'vertical': + x = [0, height * linear_transition - 0.5 * height * gradient_distance, height * linear_transition + 0.5 * height * gradient_distance, height] + y = [0, 0, 1, 1] + t_values = np.interp(np.arange(height), x, y) + for (j, t) in enumerate(t_values): + interpolated_color = [int(c1 * (1 - t) + c2 * t) for (c1, c2) in zip(color1_rgb, color2_rgb)] + canvas[j, :] = interpolated_color + (fig, ax) = plt.subplots(figsize=(width / 100, height / 100)) + ax.imshow(canvas) + plt.axis('off') + plt.tight_layout(pad=0, w_pad=0, h_pad=0) + plt.autoscale(tight=True) + img_buf = io.BytesIO() + plt.savefig(img_buf, format='png') + img = Image.open(img_buf) + image_out = pil2tensor(img.convert('RGB')) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pattern-Nodes#cr-color-gradient' + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Color Panel.md b/docs/CR Color Panel.md new file mode 100644 index 0000000..181c73d --- /dev/null +++ b/docs/CR Color Panel.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: CR_ColorPanel +- Category: Comfyroll/Graphics/Layout +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ColorPanel 是一个用于生成纯色面板的节点。它允许用户指定面板的尺寸和颜色,然后可以将其用作图像输出。这个节点非常多功能,可以作为更复杂的图像组合的基础,或者作为一个独立的视觉效果元素。 + +# Input types +## Required +- panel_width + - panel_width 参数定义了颜色面板的宽度。它对于设置输出图像的水平尺寸至关重要,并在与其他视觉元素结合使用时影响整体构图。 + - Comfy dtype: INT + - Python dtype: int +- panel_height + - panel_height 参数决定了颜色面板的高度。与 panel_width 一起,它确定了图像的整体大小,这对于创建视觉上平衡的布局至关重要。 + - Comfy dtype: INT + - Python dtype: int +- fill_color + - fill_color 参数决定了填充面板的颜色。它是节点功能的关键方面,允许定制面板的外观以满足特定的设计要求。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- fill_color_hex + - fill_color_hex 参数提供了使用十六进制值指定填充颜色的另一种方式。这允许精确控制颜色,特别是当需要一种特定色调时,这种色调可能在预定义的颜色选项中并不直接可用。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- image + - 图像输出是作为张量渲染的颜色面板。它代表了节点操作的视觉结果,可以用作进一步图像处理的输入或直接显示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了指向节点文档的 URL 链接。这对于寻求如何有效使用节点的额外指导或信息的用户来说非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ColorPanel: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'panel_width': ('INT', {'default': 512, 'min': 8, 'max': 4096}), 'panel_height': ('INT', {'default': 512, 'min': 8, 'max': 4096}), 'fill_color': (COLORS,)}, 'optional': {'fill_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image', 'show_help') + FUNCTION = 'make_panel' + CATEGORY = icons.get('Comfyroll/Graphics/Layout') + + def make_panel(self, panel_width, panel_height, fill_color, fill_color_hex='#000000'): + fill_color = get_color_values(fill_color, fill_color_hex, color_mapping) + size = (panel_width, panel_height) + panel = Image.new('RGB', size, fill_color) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Layout-Nodes#cr-color-panel' + return (pil2tensor(panel), show_help) +``` \ No newline at end of file diff --git a/docs/CR Color Tint.md b/docs/CR Color Tint.md new file mode 100644 index 0000000..cb0aefe --- /dev/null +++ b/docs/CR Color Tint.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: CR_ColorTint +- Category: Comfyroll/Graphics/Filter +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ColorTint节点旨在为图像应用颜色色调,通过叠加所选颜色增强其视觉吸引力。该节点提供了一种多功能的颜色操作方法,允许用户从预定义的颜色集中选择或输入自定义颜色十六进制值。它针对自定义颜色应用和批量处理进行了优化,确保了多张图像的效率和一致性。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它是节点将处理的输入。它是应用颜色色调效果的基础,是节点操作的关键组成部分。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- strength + - 强度参数控制应用于图像的颜色色调的强度。它允许微调效果以实现所需的视觉结果,是节点功能的重要方面。 + - Comfy dtype: FLOAT + - Python dtype: float +- mode + - 模式参数确定要应用的颜色色调类型。它提供了一系列的预设选项,使用户可以选择适合他们创意视野的特定颜色音调。 + - Comfy dtype: COMBO['custom', 'white', 'black', 'sepia', 'red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'purple', 'orange', 'warm', 'cool', 'lime', 'navy', 'vintage', 'rose', 'teal', 'maroon', 'peach', 'lavender', 'olive'] + - Python dtype: str +- tint_color_hex + - 当选择自定义颜色时,使用tint_color_hex参数。它允许用户指定用于色调的确切颜色十六进制值,为节点的操作提供了高度的定制性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - IMAGE输出是应用了颜色色调的处理后的图像。它代表了节点操作的最终结果,是进一步使用或展示的主要输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help输出提供了指向节点文档的URL。它是寻求有效使用节点的用户的有用资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ColorTint: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + tints = ['custom', 'white', 'black', 'sepia', 'red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'purple', 'orange', 'warm', 'cool', 'lime', 'navy', 'vintage', 'rose', 'teal', 'maroon', 'peach', 'lavender', 'olive'] + return {'required': {'image': ('IMAGE',), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 1.0, 'step': 0.1}), 'mode': (tints,)}, 'optional': {'tint_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'color_tint' + CATEGORY = icons.get('Comfyroll/Graphics/Filter') + + def color_tint(self, image: torch.Tensor, strength, mode: str='sepia', tint_color_hex='#000000'): + if strength == 0: + return (image,) + tint_color = get_color_values(mode, tint_color_hex, color_mapping) + color_rgb = tuple([value / 255 for value in tint_color]) + sepia_weights = torch.tensor([0.2989, 0.587, 0.114]).view(1, 1, 1, 3).to(image.device) + mode_filters = {'custom': torch.tensor([color_rgb[0], color_rgb[1], color_rgb[2]]), 'white': torch.tensor([1, 1, 1]), 'black': torch.tensor([0, 0, 0]), 'sepia': torch.tensor([1.0, 0.8, 0.6]), 'red': torch.tensor([1.0, 0.6, 0.6]), 'green': torch.tensor([0.6, 1.0, 0.6]), 'blue': torch.tensor([0.6, 0.8, 1.0]), 'cyan': torch.tensor([0.6, 1.0, 1.0]), 'magenta': torch.tensor([1.0, 0.6, 1.0]), 'yellow': torch.tensor([1.0, 1.0, 0.6]), 'purple': torch.tensor([0.8, 0.6, 1.0]), 'orange': torch.tensor([1.0, 0.7, 0.3]), 'warm': torch.tensor([1.0, 0.9, 0.7]), 'cool': torch.tensor([0.7, 0.9, 1.0]), 'lime': torch.tensor([0.7, 1.0, 0.3]), 'navy': torch.tensor([0.3, 0.4, 0.7]), 'vintage': torch.tensor([0.9, 0.85, 0.7]), 'rose': torch.tensor([1.0, 0.8, 0.9]), 'teal': torch.tensor([0.3, 0.8, 0.8]), 'maroon': torch.tensor([0.7, 0.3, 0.5]), 'peach': torch.tensor([1.0, 0.8, 0.6]), 'lavender': torch.tensor([0.8, 0.6, 1.0]), 'olive': torch.tensor([0.6, 0.7, 0.4])} + scale_filter = mode_filters[mode].view(1, 1, 1, 3).to(image.device) + grayscale = torch.sum(image * sepia_weights, dim=-1, keepdim=True) + tinted = grayscale * scale_filter + result = tinted * strength + image * (1 - strength) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Filter-Nodes#cr-color-tint' + return (result, show_help) +``` \ No newline at end of file diff --git a/docs/CR Combine Prompt.md b/docs/CR Combine Prompt.md new file mode 100644 index 0000000..d53dd5e --- /dev/null +++ b/docs/CR Combine Prompt.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: CR_CombinePrompt +- Category: Essential +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_CombinePrompt节点用于将多个字符串输入连接成一个单一的输出字符串。它旨在通过使用指定的分隔符结合各种文本元素,简化复杂提示的创建过程。 + +# Input types +## Optional +- part1 + - 最终输出中要结合的第一个文本段。它是构成提示整体结构的基本组成部分。 + - Comfy dtype: STRING + - Python dtype: str +- part2 + - 输出字符串中包含的第二个文本段。它在塑造提示的细节方面发挥作用。 + - Comfy dtype: STRING + - Python dtype: str +- part3 + - 构成提示的第三个文本段。这是一个可选元素,可以根据用户的需求包含在内。 + - Comfy dtype: STRING + - Python dtype: str +- part4 + - 合并到提示中的第四个也是最后一个文本段。它完成了信息的传递,并为整体提示结构提供了闭合。 + - Comfy dtype: STRING + - Python dtype: str +- separator + - 用于分隔提示的各个部分的字符或字符串。它决定了组合输出的结构和可读性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- prompt + - 通过使用指定的分隔符结合输入部分形成的字符串。它代表节点的最终输出,准备好进行进一步的处理或显示。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - 一个指向节点使用帮助文档页面的URL链接。它为用户提供了一个参考资源,以便在需要时进行咨询。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_CombinePrompt: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}, 'optional': {'part1': ('STRING', {'default': '', 'multiline': True}), 'part2': ('STRING', {'default': '', 'multiline': True}), 'part3': ('STRING', {'default': '', 'multiline': True}), 'part4': ('STRING', {'default': '', 'multiline': True}), 'separator': ('STRING', {'default': ',', 'multiline': False})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('prompt', 'show_help') + FUNCTION = 'get_value' + CATEGORY = icons.get('Comfyroll/Essential/Core') + + def get_value(self, part1='', part2='', part3='', part4='', separator=''): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Core-Nodes#cr-prompt-parts' + prompt = part1 + separator + part2 + separator + part3 + separator + part4 + return (prompt, show_help) +``` \ No newline at end of file diff --git a/docs/CR Combine Schedules.md b/docs/CR Combine Schedules.md new file mode 100644 index 0000000..45e7df2 --- /dev/null +++ b/docs/CR Combine Schedules.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: CR_CombineSchedules +- Category: Animation/Schedule +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_CombineSchedules节点旨在将多个动画时间表合并为一个单一的、连贯的时间表。它通过整合提供的日程安排,确保不同动画阶段之间的平稳过渡而不发生冲突来实现这一点。这个节点在简化动画工作流程中发挥着关键作用,特别适用于需要同步多个时间表的复杂动画。 + +# Input types +## Optional +- schedule_1 + - 要组合的第一个动画时间表。这是一个关键的输入,因为它为合并后的时间表设置了初始结构。节点智能地整合这个时间表,同时确保与后续输入的兼容性。 + - Comfy dtype: SCHEDULE + - Python dtype: List[str] +- schedule_2 + - 要合并的第二个动画时间表。这个输入允许进一步定制和扩展组合的时间表,增加更多的动画控制层。 + - Comfy dtype: SCHEDULE + - Python dtype: List[str] +- schedule_3 + - 第三可选动画时间表,可以包含在组合过程中。它为整个动画序列提供了额外的灵活性。 + - Comfy dtype: SCHEDULE + - Python dtype: List[str] +- schedule_4 + - 第四个可选动画时间表,可以集成到最终组合的时间表中。它提供了在时间表合并之前的最后一层定制。 + - Comfy dtype: SCHEDULE + - Python dtype: List[str] + +# Output types +- SCHEDULE + - 合并过程产生的组合时间表。它代表了准备应用的统一动画指令序列。 + - Comfy dtype: SCHEDULE + - Python dtype: List[str] +- show_text + - 组合时间表的文本表示,适用于调试和可视化目的。它提供了合并后的动画指令的人类可读格式。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_CombineSchedules: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'schedule_1': ('SCHEDULE',), 'schedule_2': ('SCHEDULE',), 'schedule_3': ('SCHEDULE',), 'schedule_4': ('SCHEDULE',)}} + RETURN_TYPES = ('SCHEDULE', 'STRING') + RETURN_NAMES = ('SCHEDULE', 'show_text') + FUNCTION = 'combine' + CATEGORY = icons.get('Comfyroll/Animation/Schedule') + + def combine(self, schedule_1=None, schedule_2=None, schedule_3=None, schedule_4=None): + schedules = list() + schedule_text = list() + if schedule_1 is not None: + (schedules.extend([l for l in schedule_1]),) + (schedule_text.extend(schedule_1),) + if schedule_2 is not None: + (schedules.extend([l for l in schedule_2]),) + (schedule_text.extend(schedule_2),) + if schedule_3 is not None: + (schedules.extend([l for l in schedule_3]),) + (schedule_text.extend(schedule_3),) + if schedule_4 is not None: + (schedules.extend([l for l in schedule_4]),) + (schedule_text.extend(schedule_4),) + print(f'[Debug] CR Combine Schedules: {schedules}') + show_text = ''.join(str(schedule_text)) + return (schedules, show_text) +``` \ No newline at end of file diff --git a/docs/CR Comic Panel Templates.md b/docs/CR Comic Panel Templates.md new file mode 100644 index 0000000..b5b2e7c --- /dev/null +++ b/docs/CR Comic Panel Templates.md @@ -0,0 +1,143 @@ +# Documentation +- Class name: CR_ComicPanelTemplates +- Category: Comfyroll/Graphics/Template +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ComicPanelTemplates 是一个用于从一组图片创建漫画面板布局的节点。它允许自定义面板布局、阅读方向以及边框、轮廓和背景的颜色。该节点能够处理预定义和自定义的面板布局,以创建漫画条效果。 + +# Input types +## Required +- page_width + - page_width 参数决定了漫画面板布局的宽度。它对于设置输出的总体尺寸至关重要,并影响布局内面板的间距和排列。 + - Comfy dtype: INT + - Python dtype: int +- page_height + - page_height 参数设置漫画面板布局的高度。它与 page_width 一起工作,以确定漫画条的整体画布大小。 + - Comfy dtype: INT + - Python dtype: int +- template + - template 参数指定漫画面板的预定义或自定义布局。它是一个关键输入,决定了最终输出的结构。 + - Comfy dtype: STRING + - Python dtype: str +- reading_direction + - reading_direction 参数决定了漫画面板的阅读流向,可以是从左到右或从右到左,这对于正确顺序阅读面板至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- border_thickness + - border_thickness 参数定义了每个漫画面板周围边框的厚度。它有助于提高各个面板的美观度和清晰度。 + - Comfy dtype: INT + - Python dtype: int +- outline_thickness + - outline_thickness 参数设置了每个面板周围轮廓的厚度,增强了面板之间的视觉区分。 + - Comfy dtype: INT + - Python dtype: int +- outline_color + - outline_color 参数指定了每个漫画面板周围轮廓的颜色,它在布局的整体视觉风格中扮演着角色。 + - Comfy dtype: STRING + - Python dtype: str +- panel_color + - panel_color 参数决定了每个漫画面板的背景颜色,为内部的艺术作品设定了基调。 + - Comfy dtype: STRING + - Python dtype: str +- background_color + - background_color 参数设置了整个漫画面板布局的背景颜色,为面板提供了一个背景画布。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- images + - images 参数是一个可选的图像张量列表,将用于填充漫画面板。它允许在布局中进行动态内容填充。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +- custom_panel_layout + - custom_panel_layout 参数接受一个字符串,定义了面板的自定义网格布局。当选择 'custom' 模板时使用。 + - Comfy dtype: STRING + - Python dtype: str +- outline_color_hex + - outline_color_hex 参数提供了轮廓的十六进制颜色值,提供了指定轮廓颜色的另一种方式。 + - Comfy dtype: STRING + - Python dtype: str +- panel_color_hex + - panel_color_hex 参数允许为面板背景指定一个十六进制颜色值,提供了颜色选择上的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- bg_color_hex + - bg_color_hex 参数设置了整个布局背景的十六进制颜色值,提供了输入背景颜色的直接方法。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- image + - image 输出包含渲染后的漫画面板布局作为图像张量,可供进一步处理或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个指向文档页面的 URL,以获取有关使用该节点的额外指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ComicPanelTemplates: + + @classmethod + def INPUT_TYPES(s): + directions = ['left to right', 'right to left'] + templates = ['custom', 'G22', 'G33', 'H2', 'H3', 'H12', 'H13', 'H21', 'H23', 'H31', 'H32', 'V2', 'V3', 'V12', 'V13', 'V21', 'V23', 'V31', 'V32'] + return {'required': {'page_width': ('INT', {'default': 512, 'min': 8, 'max': 4096}), 'page_height': ('INT', {'default': 512, 'min': 8, 'max': 4096}), 'template': (templates,), 'reading_direction': (directions,), 'border_thickness': ('INT', {'default': 5, 'min': 0, 'max': 1024}), 'outline_thickness': ('INT', {'default': 2, 'min': 0, 'max': 1024}), 'outline_color': (COLORS,), 'panel_color': (COLORS,), 'background_color': (COLORS,)}, 'optional': {'images': ('IMAGE',), 'custom_panel_layout': ('STRING', {'multiline': False, 'default': 'H123'}), 'outline_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'panel_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'bg_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image', 'show_help') + FUNCTION = 'layout' + CATEGORY = icons.get('Comfyroll/Graphics/Template') + + def layout(self, page_width, page_height, template, reading_direction, border_thickness, outline_thickness, outline_color, panel_color, background_color, images=None, custom_panel_layout='G44', outline_color_hex='#000000', panel_color_hex='#000000', bg_color_hex='#000000'): + panels = [] + k = 0 + len_images = 0 + if images is not None: + images = [tensor2pil(image) for image in images] + len_images = len(images) + outline_color = get_color_values(outline_color, outline_color_hex, color_mapping) + panel_color = get_color_values(panel_color, panel_color_hex, color_mapping) + bg_color = get_color_values(background_color, bg_color_hex, color_mapping) + size = (page_width - 2 * border_thickness, page_height - 2 * border_thickness) + page = Image.new('RGB', size, bg_color) + draw = ImageDraw.Draw(page) + if template == 'custom': + template = custom_panel_layout + first_char = template[0] + if first_char == 'G': + rows = int(template[1]) + columns = int(template[2]) + panel_width = (page.width - 2 * columns * (border_thickness + outline_thickness)) // columns + panel_height = (page.height - 2 * rows * (border_thickness + outline_thickness)) // rows + for i in range(rows): + for j in range(columns): + create_and_paste_panel(page, border_thickness, outline_thickness, panel_width, panel_height, page.width, panel_color, bg_color, outline_color, images, i, j, k, len_images, reading_direction) + k += 1 + elif first_char == 'H': + rows = len(template) - 1 + panel_height = (page.height - 2 * rows * (border_thickness + outline_thickness)) // rows + for i in range(rows): + columns = int(template[i + 1]) + panel_width = (page.width - 2 * columns * (border_thickness + outline_thickness)) // columns + for j in range(columns): + create_and_paste_panel(page, border_thickness, outline_thickness, panel_width, panel_height, page.width, panel_color, bg_color, outline_color, images, i, j, k, len_images, reading_direction) + k += 1 + elif first_char == 'V': + columns = len(template) - 1 + panel_width = (page.width - 2 * columns * (border_thickness + outline_thickness)) // columns + for j in range(columns): + rows = int(template[j + 1]) + panel_height = (page.height - 2 * rows * (border_thickness + outline_thickness)) // rows + for i in range(rows): + create_and_paste_panel(page, border_thickness, outline_thickness, panel_width, panel_height, page.width, panel_color, bg_color, outline_color, images, i, j, k, len_images, reading_direction) + k += 1 + if border_thickness > 0: + page = ImageOps.expand(page, border_thickness, bg_color) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Template-Nodes#cr-comic-panel-templates' + return (pil2tensor(page), show_help) +``` \ No newline at end of file diff --git a/docs/CR Composite Text.md b/docs/CR Composite Text.md new file mode 100644 index 0000000..cf3f0fd --- /dev/null +++ b/docs/CR Composite Text.md @@ -0,0 +1,102 @@ +# Documentation +- Class name: CR_CompositeText +- Category: Graphics/Text +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_CompositeText节点旨在将文本叠加到图像背景上。它提供了一套全面的功能来自定义文本的外观,包括字体选择、大小、对齐和旋转。该节点的主要目的是创建视觉上吸引人的带有文本的复合图像,可用于各种用途,如平面设计、品牌推广或社交媒体内容。 + +# Input types +## Required +- image_text + - image_text参数是源图像,文本将被合成到此图像上。它在确定输出图像的最终外观中起着关键作用,因为文本将放置在此图像上。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image_background + - image_background参数指定了在合成中将使用的背景图像。这对于设置文本出现的上下文至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- text + - text参数包含将渲染到图像上的实际文本。它是一个基本输入,因为它直接影响最终合成图像所传达的信息。 + - Comfy dtype: STRING + - Python dtype: str +- font_name + - font_name参数用于选择用于文本的字体。它对于控制合成图像中文本的样式和可读性很重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- font_size + - font_size参数决定了文本的大小。这是影响文本在合成中的视觉突出度和可读性的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- margins + - margins参数指定了文本周围的空间。这对于确保文本不显得拥挤,并保持干净和专业的外观很重要。 + - Comfy dtype: INT + - Python dtype: int +- line_spacing + - line_spacing参数控制文本行之间的垂直空间。它影响多行文本的整体布局和可读性。 + - Comfy dtype: INT + - Python dtype: int +- position_x + - position_x参数设置文本在图像上的水平位置。这对于在合成中对齐文本以实现所需的美学效果至关重要。 + - Comfy dtype: INT + - Python dtype: int +- position_y + - position_y参数设置文本在图像上的垂直位置。它与position_x一起工作,以准确地在合成中放置文本。 + - Comfy dtype: INT + - Python dtype: int +- align + - align参数决定文本的水平对齐方式。这对于整体构图和图像中文本的视觉平衡至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- justify + - justify参数控制文本在图像内的分布,影响文本如何跨越可用宽度进行展开。 + - Comfy dtype: STRING + - Python dtype: str +- rotation_angle + - rotation_angle参数指定文本将旋转的角度。这是一个重要特性,用于为合成图像中的文本添加动态外观。 + - Comfy dtype: FLOAT + - Python dtype: float +- rotation_options + - rotation_options参数确定文本旋转的参考点,可以是文本中心或图像中心。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - IMAGE输出提供了带有文本覆盖的最终合成图像。它是节点操作的主要结果,代表了所有输入参数和设置的综合成果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help输出提供了一个URL,链接到文档页面以获得进一步的帮助或有关节点使用详情。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_CompositeText: + + @classmethod + def INPUT_TYPES(s): + font_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'fonts') + file_list = [f for f in os.listdir(font_dir) if os.path.isfile(os.path.join(font_dir, f)) and f.lower().endswith('.ttf')] + return {'required': {'image_text': ('IMAGE',), 'image_background': ('IMAGE',), 'text': ('STRING', {'multiline': True, 'default': 'text'}), 'font_name': (file_list,), 'font_size': ('INT', {'default': 50, 'min': 1, 'max': 1024}), 'align': (ALIGN_OPTIONS,), 'justify': (JUSTIFY_OPTIONS,), 'margins': ('INT', {'default': 0, 'min': -1024, 'max': 1024}), 'line_spacing': ('INT', {'default': 0, 'min': -1024, 'max': 1024}), 'position_x': ('INT', {'default': 0, 'min': -4096, 'max': 4096}), 'position_y': ('INT', {'default': 0, 'min': -4096, 'max': 4096}), 'rotation_angle': ('FLOAT', {'default': 0.0, 'min': -360.0, 'max': 360.0, 'step': 0.1}), 'rotation_options': (ROTATE_OPTIONS,)}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'composite_text' + CATEGORY = icons.get('Comfyroll/Graphics/Text') + + def composite_text(self, image_text, image_background, text, font_name, font_size, margins, line_spacing, position_x, position_y, align, justify, rotation_angle, rotation_options): + image_text_3d = image_text[0, :, :, :] + image_back_3d = image_background[0, :, :, :] + text_image = tensor2pil(image_text_3d) + back_image = tensor2pil(image_back_3d) + text_mask = Image.new('L', back_image.size) + rotated_text_mask = draw_masked_text(text_mask, text, font_name, font_size, margins, line_spacing, position_x, position_y, align, justify, rotation_angle, rotation_options) + image_out = Image.composite(text_image, back_image, rotated_text_mask) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Text-Nodes#cr-composite-text' + return (pil2tensor(image_out), show_help) +``` \ No newline at end of file diff --git a/docs/CR Conditioning Input Switch.md b/docs/CR Conditioning Input Switch.md new file mode 100644 index 0000000..016cc6f --- /dev/null +++ b/docs/CR Conditioning Input Switch.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CR_ConditioningInputSwitch +- Category: Comfyroll/Utils/Logic +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ConditioningInputSwitch 节点旨在根据条件输入管理数据流。它允许根据 'Input' 参数的值选择两个条件输入中的一个。该节点在复杂工作流中起着关键作用,可以指导数据流,实现条件逻辑,而无需使用嵌套结构。 + +# Input types +## Required +- Input + - 'Input' 参数对于确定将选择哪个条件数据至关重要。它作为一个开关,其中值为 1 时选择 'conditioning1',其他任何值则选择 'conditioning2'。此参数直接影响节点的输出,在工作流中促进决策过程。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- conditioning1 + - 'conditioning1' 参数是可选输入之一,当 'Input' 参数等于 1 时将使用它。它代表一组条件数据,当满足指定条件时可以使用,允许将特定于上下文的信息无缝集成到工作流中。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- conditioning2 + - 'conditioning2' 参数是 'conditioning1' 的替代输入,当 'Input' 参数不等于 1 时将被调用。它允许根据不同的条件提供不同的条件数据,确保节点在不同场景中的灵活性和适应性。 + - Comfy dtype: CONDITIONING + - Python dtype: Any + +# Output types +- CONDITIONING + - 'CONDITIONING' 输出是基于 'Input' 参数值选择的条件数据。它代表了节点条件逻辑的结果,为工作流中的后续步骤提供必要的信息。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- show_help + - 'show_help' 输出提供了指向节点文档的 URL 链接,使用户能够快速访问有关如何有效使用节点的附加信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ConditioningInputSwitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': ('INT', {'default': 1, 'min': 1, 'max': 2})}, 'optional': {'conditioning1': ('CONDITIONING',), 'conditioning2': ('CONDITIONING',)}} + RETURN_TYPES = ('CONDITIONING', 'STRING') + RETURN_NAMES = ('CONDITIONING', 'show_help') + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Utils/Logic') + + def switch(self, Input, conditioning1=None, conditioning2=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Logic-Nodes#cr-conditioning-input-switch' + if Input == 1: + return (conditioning1, show_help) + else: + return (conditioning2, show_help) +``` \ No newline at end of file diff --git a/docs/CR Conditioning Mixer.md b/docs/CR Conditioning Mixer.md new file mode 100644 index 0000000..7188cde --- /dev/null +++ b/docs/CR Conditioning Mixer.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: CR_ConditioningMixer +- Category: Comfyroll/Essential/Core +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ConditioningMixer节点旨在混合或组合不同的条件输入。它为合并或平均条件数据提供了一种方法,这对于某些机器学习应用至关重要,其中输入条件是模型性能的关键因素。节点的功能被抽象化以确保灵活性,允许用户选择组合、平均或连接条件输入以实现所需的结果。 + +# Input types +## Required +- conditioning_1 + - 第一个条件输入对于节点的操作至关重要,因为它代表了将与另一个条件输入操作或组合的主要数据源之一。它在确定节点的最终输出中起着关键作用。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] +- conditioning_2 + - 第二个条件输入是节点功能的另一个关键元素。它与第一个条件输入一起使用,根据选定的混合方法创建混合或混合输出。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] +- mix_method + - 混合方法参数定义了如何组合条件输入。它是节点操作的关键决定因素,允许使用不同的策略,如组合、平均或连接输入。 + - Comfy dtype: COMBO['Combine', 'Average', 'Concatenate'] + - Python dtype: str +## Optional +- average_strength + - 当混合方法设置为'Average'时,使用平均强度参数。它控制两个条件输入之间的混合比例,根据指定的强度影响最终输出。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- CONDITIONING + - 输出条件是将所选混合方法应用于输入条件的结果。它包含了准备好供机器学习管道中进一步使用的综合或处理过的数据。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] +- show_help + - show_help输出提供指向节点文档的URL链接。它是用户寻求有关如何有效使用节点的更多信息的有用参考。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ConditioningMixer: + + @classmethod + def INPUT_TYPES(cls): + mix_methods = ['Combine', 'Average', 'Concatenate'] + return {'required': {'conditioning_1': ('CONDITIONING',), 'conditioning_2': ('CONDITIONING',), 'mix_method': (mix_methods,), 'average_strength': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('CONDITIONING', 'STRING') + RETURN_NAMES = ('CONDITIONING', 'show_help') + FUNCTION = 'conditioning' + CATEGORY = icons.get('Comfyroll/Essential/Core') + + def conditioning(self, mix_method, conditioning_1, conditioning_2, average_strength): + conditioning_from = conditioning_1 + conditioning_to = conditioning_2 + conditioning_to_strength = average_strength + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Core-Nodes#cr-conditioning-mixer' + if mix_method == 'Combine': + return (conditioning_1 + conditioning_2, show_help) + if mix_method == 'Average': + out = [] + if len(conditioning_from) > 1: + print('Warning: ConditioningAverage conditioning_from contains more than 1 cond, only the first one will actually be applied to conditioning_to.') + cond_from = conditioning_from[0][0] + pooled_output_from = conditioning_from[0][1].get('pooled_output', None) + for i in range(len(conditioning_to)): + t1 = conditioning_to[i][0] + pooled_output_to = conditioning_to[i][1].get('pooled_output', pooled_output_from) + t0 = cond_from[:, :t1.shape[1]] + if t0.shape[1] < t1.shape[1]: + t0 = torch.cat([t0] + [torch.zeros((1, t1.shape[1] - t0.shape[1], t1.shape[2]))], dim=1) + tw = torch.mul(t1, conditioning_to_strength) + torch.mul(t0, 1.0 - conditioning_to_strength) + t_to = conditioning_to[i][1].copy() + if pooled_output_from is not None and pooled_output_to is not None: + t_to['pooled_output'] = torch.mul(pooled_output_to, conditioning_to_strength) + torch.mul(pooled_output_from, 1.0 - conditioning_to_strength) + elif pooled_output_from is not None: + t_to['pooled_output'] = pooled_output_from + n = [tw, t_to] + out.append(n) + return (out, show_help) + if mix_method == 'Concatenate': + out = [] + if len(conditioning_from) > 1: + print('Warning: ConditioningConcat conditioning_from contains more than 1 cond, only the first one will actually be applied to conditioning_to.') + cond_from = conditioning_from[0][0] + for i in range(len(conditioning_to)): + t1 = conditioning_to[i][0] + tw = torch.cat((t1, cond_from), 1) + n = [tw, conditioning_to[i][1].copy()] + out.append(n) + return (out, show_help) +``` \ No newline at end of file diff --git a/docs/CR ControlNet Input Switch.md b/docs/CR ControlNet Input Switch.md new file mode 100644 index 0000000..4bd6538 --- /dev/null +++ b/docs/CR ControlNet Input Switch.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CR_ControlNetInputSwitch +- Category: Comfyroll/Utils/Logic +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ControlNetInputSwitch 节点旨在为控制网络提供条件切换机制。它允许用户根据输入值在两个控制网络之间进行选择,从而方便地将数据路由到所需的网络路径。 + +# Input types +## Required +- Input + - ‘Input’参数对于决定使用哪个控制网络至关重要。它通过指定要选定的控制网络的索引,决定了节点内部的执行流程。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- control_net1 + - ‘control_net1’参数代表节点可以选择的第一个控制网络。当‘Input’参数设置为1时,它在节点的决策过程中扮演着重要角色。 + - Comfy dtype: CONTROL_NET + - Python dtype: str +- control_net2 + - ‘control_net2’参数代表节点可以选择的第二个控制网络。当‘Input’参数设置为2时,它变得相关,指导节点的选择。 + - Comfy dtype: CONTROL_NET + - Python dtype: str + +# Output types +- CONTROL_NET + - ‘CONTROL_NET’输出提供了基于输入值选定的控制网络。它是主要的输出,将节点做出的决策向前推进到工作流中。 + - Comfy dtype: CONTROL_NET + - Python dtype: str +- show_help + - ‘show_help’输出是一个URL,提供了如何有效使用节点的额外信息和指导。它是次要输出,为用户提供了访问节点文档的途径。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ControlNetInputSwitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': ('INT', {'default': 1, 'min': 1, 'max': 2}), 'control_net1': ('CONTROL_NET',), 'control_net2': ('CONTROL_NET',)}, 'optional': {'control_net1': ('CONTROL_NET',), 'control_net2': ('CONTROL_NET',)}} + RETURN_TYPES = ('CONTROL_NET', 'STRING') + RETURN_NAMES = ('CONTROL_NET', 'show_help') + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Utils/Logic') + + def switch(self, Input, control_net1=None, control_net2=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Logic-Nodes#cr-controlnet-input-switch' + if Input == 1: + return (control_net1, show_help) + else: + return (control_net2, show_help) +``` \ No newline at end of file diff --git a/docs/CR Current Frame.md b/docs/CR Current Frame.md new file mode 100644 index 0000000..68d2c94 --- /dev/null +++ b/docs/CR Current Frame.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: CR_CurrentFrame +- Category: Comfyroll/Animation/Utils +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_CurrentFrame 节点旨在便于在控制台环境中记录和显示当前帧索引。它为开发者提供了一个工具,用于追踪动画或一系列帧的进度。 + +# Input types +## Required +- index + - ‘index’参数表示动画序列中的当前帧索引。它对节点至关重要,因为它决定了正在记录或监控的特定帧。 + - Comfy dtype: INT + - Python dtype: int +- print_to_console + - ‘print_to_console’参数决定是否应将当前帧索引打印到控制台。它是控制节点输出可见性的重要开关。 + - Comfy dtype: COMBO['Yes', 'No'] + - Python dtype: str + +# Output types +- index + - ‘index’输出提供了节点处理的当前帧索引,可以在动画工作流程中用于进一步的操作或分析。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_CurrentFrame: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'index': ('INT', {'default': 1, 'min': -10000, 'max': 10000}), 'print_to_console': (['Yes', 'No'],)}} + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('index',) + FUNCTION = 'to_console' + CATEGORY = icons.get('Comfyroll/Animation/Utils') + + def to_console(self, index, print_to_console): + if print_to_console == 'Yes': + print(f'[Info] CR Current Frame:{index}') + return (index,) +``` \ No newline at end of file diff --git a/docs/CR Cycle Images Simple.md b/docs/CR Cycle Images Simple.md new file mode 100644 index 0000000..928c71b --- /dev/null +++ b/docs/CR Cycle Images Simple.md @@ -0,0 +1,86 @@ +# Documentation +- Class name: CR_CycleImagesSimple +- Category: Animation +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_CycleImagesSimple 节点旨在通过顺序或随机方式循环遍历图像列表,创建动画效果。它允许指定帧间隔、循环次数和当前帧来控制动画序列。该节点特别适用于从一组图像生成动态视觉内容。 + +# Input types +## Required +- mode + - 模式参数确定图像循环的顺序。它可以设置为'Sequential'以特定顺序循环图像,或者在未来更新中支持随机模式。此设置直接影响动画序列和用户体验。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- frame_interval + - frame_interval 参数指定动画中每次图像变化之间的帧数。它影响图像循环的速度,对于正确控制动画节奏至关重要。 + - Comfy dtype: INT + - Python dtype: int +- loops + - loops 参数设置动画重复的次数。它对于定义动画序列的持续时间很重要,并且可以用来创建连续或有限的动画。 + - Comfy dtype: INT + - Python dtype: int +- current_frame + - current_frame 参数指示动画的起始点。它对于将动画与其它元素同步或为设置动画序列的特定点以开始至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- image_1 + - image_1 参数是可以在动画循环中包含的第一张图像。它很重要,因为它有助于丰富动画序列的内容和多样性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- image_list_simple + - image_list_simple 参数是可以在动画循环中包含的图像列表。它在向序列中添加多个图像时提供了灵活性,并增强了整体动画效果。 + - Comfy dtype: IMAGE_LIST_SIMPLE + - Python dtype: List[PIL.Image.Image] + +# Output types +- IMAGE + - IMAGE 输出提供了动画循环中的当前图像。它是节点操作的主要视觉结果,对于显示动画至关重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- show_help + - show_help 输出提供了文档的URL,以获取有关节点功能的进一步帮助和信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_CycleImagesSimple: + + @classmethod + def INPUT_TYPES(s): + modes = ['Sequential'] + return {'required': {'mode': (modes,), 'frame_interval': ('INT', {'default': 30, 'min': 0, 'max': 999, 'step': 1}), 'loops': ('INT', {'default': 1, 'min': 1, 'max': 1000}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}, 'optional': {'image_1': ('IMAGE',), 'image_2': ('IMAGE',), 'image_3': ('IMAGE',), 'image_4': ('IMAGE',), 'image_5': ('IMAGE',), 'image_list_simple': ('IMAGE_LIST_SIMPLE',)}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'cycle_image' + CATEGORY = icons.get('Comfyroll/Animation/Legacy') + + def cycle_image(self, mode, frame_interval, loops, current_frame, image_1=None, image_2=None, image_3=None, image_4=None, image_5=None, image_list_simple=None): + image_params = list() + image_list = list() + if image_1 != None: + (image_list.append(image_1),) + if image_2 != None: + (image_list.append(image_2),) + if image_3 != None: + (image_list.append(image_3),) + if image_4 != None: + (image_list.append(image_4),) + if image_5 != None: + (image_list.append(image_5),) + for _ in range(loops): + if image_list_simple: + image_params.extend(image_list_simple) + image_params.extend(image_list) + if mode == 'Sequential': + current_image_index = current_frame // frame_interval % len(image_params) + print(f'[Debug] CR Cycle Text:{current_image_index}') + current_image_item = image_params[current_image_index] + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Cycler-Nodes#cr-cycle-images-simple' + return (current_image_item, show_help) +``` \ No newline at end of file diff --git a/docs/CR Cycle Images.md b/docs/CR Cycle Images.md new file mode 100644 index 0000000..bb9840b --- /dev/null +++ b/docs/CR Cycle Images.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: CR_CycleImages +- Category: Comfyroll/Animation/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_CycleImages节点旨在循环遍历图像列表,提供一种机制以指定的帧间隔顺序显示图像。它特别适用于从图像集合中创建动画或幻灯片。该节点通过根据'loops'参数确定的次数迭代图像列表,并基于'current_frame'和'frame_interval'参数选择当前图像来操作。 + +# Input types +## Required +- mode + - 模式参数决定了图像循环的顺序。目前仅支持'Sequential'模式,它确保图像按照它们在图像列表中出现的顺序显示。 + - Comfy dtype: STRING + - Python dtype: str +- image_list + - image_list 是要循环播放的图像集合。列表中的每个条目都应该是包含图像别名和图像对象本身的元组。 + - Comfy dtype: IMAGE_LIST + - Python dtype: List[Tuple[str, Image.Image]] +## Optional +- frame_interval + - frame_interval 参数指定每张图像显示之间的帧延迟。它对于控制动画或幻灯片的速度至关重要。 + - Comfy dtype: INT + - Python dtype: int +- loops + - loops 参数决定了图像列表将被循环多少次。它允许控制动画或幻灯片的持续时间。 + - Comfy dtype: INT + - Python dtype: int +- current_frame + - current_frame 参数指示循环中的当前位置,用于确定在任何给定时刻显示哪张图像。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - IMAGE 输出提供了基于输入参数的当前循环图像。它是节点操作的视觉结果,是节点功能的核心。 + - Comfy dtype: IMAGE + - Python dtype: Image.Image +- show_help + - show_help 输出提供了一个链接到文档页面的URL,以获取关于节点使用的进一步帮助或详细信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_CycleImages: + + @classmethod + def INPUT_TYPES(s): + modes = ['Sequential'] + return {'required': {'mode': (modes,), 'image_list': ('IMAGE_LIST',), 'frame_interval': ('INT', {'default': 30, 'min': 0, 'max': 999, 'step': 1}), 'loops': ('INT', {'default': 1, 'min': 1, 'max': 1000}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'cycle' + CATEGORY = icons.get('Comfyroll/Animation/Legacy') + + def cycle(self, mode, image_list, frame_interval, loops, current_frame): + image_params = list() + if image_list: + for _ in range(loops): + image_params.extend(image_list) + if mode == 'Sequential': + current_image_index = current_frame // frame_interval % len(image_params) + print(f'[Debug] CR Cycle Image:{current_image_index}') + current_image_params = image_params[current_image_index] + (image_alias, current_image_item) = current_image_params + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Cycler-Nodes#cr-cycle-images' + return (current_image_item, show_help) +``` \ No newline at end of file diff --git a/docs/CR Cycle LoRAs.md b/docs/CR Cycle LoRAs.md new file mode 100644 index 0000000..7c315d3 --- /dev/null +++ b/docs/CR Cycle LoRAs.md @@ -0,0 +1,90 @@ +# Documentation +- Class name: CR_CycleLoRAs +- Category: Comfyroll/Animation/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_CycleLoRAs节点旨在管理和循环遍历模型和剪辑的LoRA(低秩适应)参数列表,用于指定的动画框架中。它通过顺序应用不同的LoRA调整来增强生成动画的多样性和动态性。该节点通过迭代预定义的LoRA参数列表,根据当前帧和帧间隔以循环方式应用它们,从而实现复杂且不断演变的视觉效果的创建。 + +# Input types +## Required +- mode + - 模式参数决定了节点的操作行为。它决定了节点是处于'关闭'状态,什么也不做,还是处于'顺序'模式,循环遍历LoRA参数。这个选择显著影响节点如何处理输入和结果动画序列。 + - Comfy dtype: COMBO['Off', 'Sequential'] + - Python dtype: str +- model + - 模型参数至关重要,因为它代表了节点将使用指定的LoRA参数进行操作的核心模型。模型对LoRA调整的适应性是实现所需动画效果的关键。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - 剪辑参数对于提供节点将与模型一起工作的视觉上下文至关重要。它用于与模型一起应用LoRA调整,以创建一个连贯的动画。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- lora_list + - lora_list参数是节点将循环遍历的LoRA参数列表。此列表中的每个元素代表可以应用于模型和剪辑的一组不同的调整,有助于动画的多样性。 + - Comfy dtype: LORA_LIST + - Python dtype: List[Tuple[str, str, float, float]] +## Optional +- frame_interval + - frame_interval参数定义了节点循环遍历LoRA参数的频率。它对控制动画序列的节奏和时间至关重要。 + - Comfy dtype: INT + - Python dtype: int +- loops + - loops参数指定节点将整个LoRA参数列表循环的次数。它影响动画效果的持续时间和重复性。 + - Comfy dtype: INT + - Python dtype: int +- current_frame + - current_frame参数指示动画序列中的当前位置。它用于确定在任何给定时刻应用哪个LoRA参数。 + - Comfy dtype: INT + - Python dtype: float + +# Output types +- MODEL + - 输出MODEL代表了根据当前帧和帧间隔应用了LoRA调整的模型。这是主要的输出,承载着动画预期的视觉变化。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- CLIP + - 输出CLIP是与MODEL一起使用LoRA参数调整的视觉表示。它补充MODEL以提供完整的动画序列。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- show_help + - show_help输出提供了一个URL链接到文档,以获取有关节点操作的进一步帮助或信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_CycleLoRAs: + + @classmethod + def INPUT_TYPES(s): + modes = ['Off', 'Sequential'] + return {'required': {'mode': (modes,), 'model': ('MODEL',), 'clip': ('CLIP',), 'lora_list': ('LORA_LIST',), 'frame_interval': ('INT', {'default': 30, 'min': 0, 'max': 999, 'step': 1}), 'loops': ('INT', {'default': 1, 'min': 1, 'max': 1000}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('MODEL', 'CLIP', 'STRING') + RETURN_NAMES = ('MODEL', 'CLIP', 'show_help') + FUNCTION = 'cycle' + CATEGORY = icons.get('Comfyroll/Animation/Legacy') + + def cycle(self, mode, model, clip, lora_list, frame_interval, loops, current_frame): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Cycler-Nodes#cr-cycle-loras' + lora_params = list() + if lora_list: + for _ in range(loops): + lora_params.extend(lora_list) + else: + return (model, clip, show_help) + if mode == 'Sequential': + current_lora_index = current_frame // frame_interval % len(lora_params) + current_lora_params = lora_params[current_lora_index] + (lora_alias, lora_name, model_strength, clip_strength) = current_lora_params + lora_path = folder_paths.get_full_path('loras', lora_name) + lora = comfy.utils.load_torch_file(lora_path, safe_load=True) + print(f'[Info] CR_CycleLoRAs: Current LoRA is {lora_name}') + (model_lora, clip_lora) = comfy.sd.load_lora_for_models(model, clip, lora, model_strength, clip_strength) + return (model_lora, clip_lora, show_help) + else: + return (model, clip, show_help) +``` \ No newline at end of file diff --git a/docs/CR Cycle Models.md b/docs/CR Cycle Models.md new file mode 100644 index 0000000..dedc58e --- /dev/null +++ b/docs/CR Cycle Models.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: CR_CycleModels +- Category: Comfyroll/Animation/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_CycleModels节点旨在根据指定参数(如模式、帧间隔和循环次数)管理和循环遍历模型列表。它提供了按顺序选择和处理模型的功能,或基于预定义列表,使其成为需要模型转换的动画工作流程中的多功能工具。 + +# Input types +## Required +- mode + - 模式参数决定了模型的循环行为。它可以设置为'Off'或'Sequential',影响节点如何遍历模型列表。 + - Comfy dtype: COMBO[string] + - Python dtype: str +- model + - 模型参数代表动画序列中使用的初始模型。它对于设置后续模型转换的基准至关重要。 + - Comfy dtype: MODEL + - Python dtype: Any +- clip + - 剪辑参数用于保存对动画中特定剪辑的引用,可以在模型循环时进行操作或替换。 + - Comfy dtype: CLIP + - Python dtype: Any +- frame_interval + - frame_interval参数指定了动画中模型循环的间隔。它是控制模型转换节奏的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- loops + - loops参数定义了模型列表应循环的次数。它对于控制动画序列的持续时间至关重要。 + - Comfy dtype: INT + - Python dtype: int +- current_frame + - current_frame参数指示动画序列中的当前帧。它用于确定在任何给定时间使用哪个模型。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- model_list + - model_list参数是一个模型列表,节点可以循环遍历这些模型。它在定义动画中使用的模型序列时提供了灵活性。 + - Comfy dtype: MODEL_LIST + - Python dtype: List[Any] + +# Output types +- MODEL + - 输出MODEL代表在通过模型列表循环后,在动画序列中使用的当前模型。 + - Comfy dtype: MODEL + - Python dtype: Any +- CLIP + - 输出CLIP是处理模型转换后与动画相关联的当前剪辑。 + - Comfy dtype: CLIP + - Python dtype: Any +- VAE + - VAE输出为选定模型提供了变分自编码器配置,可用于进一步处理或分析。 + - Comfy dtype: VAE + - Python dtype: Any +- show_help + - show_help输出是指向节点文档的URL链接,提供有关其使用的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_CycleModels: + + @classmethod + def INPUT_TYPES(s): + modes = ['Off', 'Sequential'] + return {'required': {'mode': (modes,), 'model': ('MODEL',), 'clip': ('CLIP',), 'model_list': ('MODEL_LIST',), 'frame_interval': ('INT', {'default': 30, 'min': 0, 'max': 999, 'step': 1}), 'loops': ('INT', {'default': 1, 'min': 1, 'max': 1000}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('MODEL', 'CLIP', 'VAE', 'STRING') + RETURN_NAMES = ('MODEL', 'CLIP', 'VAE', 'show_help') + FUNCTION = 'cycle_models' + CATEGORY = icons.get('Comfyroll/Animation/Legacy') + + def cycle_models(self, mode, model, clip, model_list, frame_interval, loops, current_frame): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Cycler-Nodes#cr-cycle-models' + model_params = list() + if model_list: + for _ in range(loops): + model_params.extend(model_list) + if mode == 'Off': + return (model, clip, show_help) + elif mode == 'Sequential': + if current_frame == 0: + return (model, clip, show_help) + else: + current_model_index = current_frame // frame_interval % len(model_params) + current_model_params = model_params[current_model_index] + (model_alias, ckpt_name) = current_model_params + print(f'[Info] CR Cycle Models: Current model is {ckpt_name}') + ckpt_path = folder_paths.get_full_path('checkpoints', ckpt_name) + out = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths('embeddings')) + return (out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Cycle Text Simple.md b/docs/CR Cycle Text Simple.md new file mode 100644 index 0000000..a3480d4 --- /dev/null +++ b/docs/CR Cycle Text Simple.md @@ -0,0 +1,85 @@ +# Documentation +- Class name: CR_CycleTextSimple +- Category: Comfyroll/Animation/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_CycleTextSimple 是一个设计用于顺序循环文本字符串列表的节点。它能够处理多个文本输入,并根据指定的帧间隔和循环次数进行循环。这个节点特别适用于在 Comfy UI 环境中创建动态文本动画。 + +# Input types +## Required +- mode + - 模式参数决定了文本字符串的循环顺序。它对于定义文本动画的顺序和模式至关重要。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- frame_interval + - 帧间隔决定了文本字符串循环的速率,影响动画的速度。 + - Comfy dtype: int + - Python dtype: int +- loops + - 循环次数参数指定了文本字符串将循环的次数,影响动画的持续时间。 + - Comfy dtype: int + - Python dtype: int +- current_frame + - 当前帧指示动画序列中的当前位置,用于确定显示哪个文本字符串。 + - Comfy dtype: int + - Python dtype: int +## Optional +- text_1 + - Text_1 是列表中第一个文本字符串的可选输入。它为循环提供了多样化的文本内容。 + - Comfy dtype: str + - Python dtype: str +- text_list_simple + - Text_list_simple 是一个可选参数,它允许简化输入多个文本字符串,简化了添加文本内容的过程。 + - Comfy dtype: TEXT_LIST_SIMPLE + - Python dtype: List[str] + +# Output types +- current_text_item + - 当前文本项代表当前正在显示的文本字符串,作为文本循环动画的一部分。 + - Comfy dtype: str + - Python dtype: str +- show_help + - show_help 输出提供了一个 URL 链接到文档,以获取有关节点使用的进一步帮助和信息。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_CycleTextSimple: + + @classmethod + def INPUT_TYPES(s): + modes = ['Sequential'] + return {'required': {'mode': (modes,), 'frame_interval': ('INT', {'default': 30, 'min': 0, 'max': 999, 'step': 1}), 'loops': ('INT', {'default': 1, 'min': 1, 'max': 1000}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}, 'optional': {'text_1': ('STRING', {'multiline': False, 'default': ''}), 'text_2': ('STRING', {'multiline': False, 'default': ''}), 'text_3': ('STRING', {'multiline': False, 'default': ''}), 'text_4': ('STRING', {'multiline': False, 'default': ''}), 'text_5': ('STRING', {'multiline': False, 'default': ''}), 'text_list_simple': ('TEXT_LIST_SIMPLE',)}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + FUNCTION = 'cycle_text' + CATEGORY = icons.get('Comfyroll/Animation/Legacy') + + def cycle_text(self, mode, frame_interval, loops, current_frame, text_1, text_2, text_3, text_4, text_5, text_list_simple=None): + text_params = list() + text_list = list() + if text_1 != '': + text_list.append(text_1) + if text_2 != '': + text_list.append(text_2) + if text_3 != '': + text_list.append(text_3) + if text_4 != '': + text_list.append(text_4) + if text_5 != '': + text_list.append(text_5) + for _ in range(loops): + if text_list_simple: + text_params.extend(text_list_simple) + text_params.extend(text_list) + if mode == 'Sequential': + current_text_index = current_frame // frame_interval % len(text_params) + current_text_item = text_params[current_text_index] + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Cycler-Nodes#cr-cycle-text-simple' + return (current_text_item, show_help) +``` \ No newline at end of file diff --git a/docs/CR Cycle Text.md b/docs/CR Cycle Text.md new file mode 100644 index 0000000..b4ace93 --- /dev/null +++ b/docs/CR Cycle Text.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: CR_CycleText +- Category: Comfyroll/Animation/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_CycleText节点旨在以指定的时间间隔循环遍历预定义的文本项列表,创建动画文本序列。它以连续模式运行,迭代文本列表以产生动态的文本显示。该节点特别适用于需要基于文本的动画的应用,例如演示或交互式显示。 + +# Input types +## Required +- mode + - 模式参数决定了文本项的循环顺序。它对于确定文本动画的顺序和模式至关重要。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- text_list + - text_list参数是节点将循环遍历的文本项列表。它是必需的,因为它定义了动画的内容。 + - Comfy dtype: TEXT_LIST + - Python dtype: List[str] +## Optional +- frame_interval + - frame_interval参数指定动画中每次文本更改之间的时间间隔。它影响文本循环的速度。 + - Comfy dtype: INT + - Python dtype: int +- loops + - loops参数确定将循环遍历文本列表的次数。它控制动画序列的持续时间。 + - Comfy dtype: INT + - Python dtype: int +- current_frame + - current_frame参数表示文本动画中的当前位置。它用于跟踪动画的进度。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- STRING + - STRING输出提供了正在循环的文本列表中的当前文本项。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - show_help输出提供了一个链接到文档,以获取关于节点操作的进一步帮助或详细信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_CycleText: + + @classmethod + def INPUT_TYPES(s): + modes = ['Sequential'] + return {'required': {'mode': (modes,), 'text_list': ('TEXT_LIST',), 'frame_interval': ('INT', {'default': 30, 'min': 0, 'max': 999, 'step': 1}), 'loops': ('INT', {'default': 1, 'min': 1, 'max': 1000}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + FUNCTION = 'cycle_text' + CATEGORY = icons.get('Comfyroll/Animation/Legacy') + + def cycle_text(self, mode, text_list, frame_interval, loops, current_frame): + text_params = list() + if text_list: + for _ in range(loops): + text_params.extend(text_list) + if mode == 'Sequential': + current_text_index = current_frame // frame_interval % len(text_params) + current_text_params = text_params[current_text_index] + print(f'[Debug] CR Cycle Text:{current_text_params}') + (text_alias, current_text_item) = current_text_params + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Cycler-Nodes#cr-cycle-text' + return (current_text_item, show_help) +``` \ No newline at end of file diff --git a/docs/CR Data Bus In.md b/docs/CR Data Bus In.md new file mode 100644 index 0000000..eb5a7e7 --- /dev/null +++ b/docs/CR Data Bus In.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: CR_DataBusIn +- Category: Comfyroll/Pipe/Bus +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_DataBusIn是一个用于管理和路由数据流的节点。它通过管道系统传输各种类型的数据,确保数据流在管道架构内有序且高效。此节点在数据流整合中发挥关键作用,允许进行复杂的数据操作和处理工作流程。 + +# Input types +## Optional +- pipe + - 'pipe'参数是节点操作的关键元素,它代表了用于传输信息的数据管道。其灵活性允许处理各种数据类型,增强了节点在处理不同数据场景时的多功能性。 + - Comfy dtype: any + - Python dtype: Any +- any1 + - 'any1'参数是一个可选输入,用于将额外的数据注入到管道中。它增强了节点处理多种数据输入的能力,有助于提升系统的整体数据处理能力。 + - Comfy dtype: any + - Python dtype: Any +- any2 + - 'any2'参数是另一个可选输入,它补充了数据管道,允许管理更复杂的数据结构。它在节点处理和路由更多种类数据类型的能力中起着重要作用。 + - Comfy dtype: any + - Python dtype: Any +- any3 + - 'any3'参数用于将更多的数据元素引入到管道中。这是一个可选输入,有助于节点在处理各种数据时的适应性,从而扩展了节点在不同数据处理任务中的实用性。 + - Comfy dtype: any + - Python dtype: Any +- any4 + - 'any4'参数作为节点的另一个可选输入,提供了将更多数据纳入管道的手段。它强调了节点设计中容纳各种数据输入的能力,这对于全面数据处理需求至关重要。 + - Comfy dtype: any + - Python dtype: Any + +# Output types +- pipe + - 'pipe'输出是一个包含处理后数据元素的元组,代表了节点数据路由和处理活动的成果。它标志着经过操作的信息流已经结构化,现在已准备好在管道系统中进一步使用。 + - Comfy dtype: tuple + - Python dtype: Tuple[Any, ...] +- show_help + - 'show_help'输出提供了指向节点文档的URL链接,为用户提供了直接参考节点指南和帮助的途径。它是理解节点功能并在数据管道中有效利用它的重要工具。 + - Comfy dtype: string + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_DataBusIn: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}, 'optional': {'pipe': (any_type,), 'any1': (any_type,), 'any2': (any_type,), 'any3': (any_type,), 'any4': (any_type,)}} + RETURN_TYPES = ('PIPE_LINE', 'STRING') + RETURN_NAMES = ('pipe', 'show_help') + FUNCTION = 'load_data' + CATEGORY = icons.get('Comfyroll/Pipe/Bus') + + def load_data(self, any1=None, any2=None, any3=None, any4=None, pipe=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pipe-Nodes#cr-data-bus-in' + (new_any1, new_any2, new_any3, new_any4) = (None, None, None, None) + if pipe is not None: + (new_any1, new_any2, new_any3, new_any4) = pipe + new_any1 = any1 if any1 is not None else new_any1 + new_any2 = any2 if any2 is not None else new_any2 + new_any3 = any3 if any3 is not None else new_any3 + new_any4 = any4 if any4 is not None else new_any4 + new_pipe = (new_any1, new_any2, new_any3, new_any4) + return (new_pipe, show_help) +``` \ No newline at end of file diff --git a/docs/CR Data Bus Out.md b/docs/CR Data Bus Out.md new file mode 100644 index 0000000..08c7e0b --- /dev/null +++ b/docs/CR Data Bus Out.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: CR_DataBusOut +- Category: Comfyroll/Pipe/Bus +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_DataBusOut 是一个用于通过管道系统无缝输出数据的节点。它作为数据处理工作流中的关键组件,确保数据能够从一个阶段高效地传输到下一个阶段。该节点的功能集中在管理和促进数据流动上,突出了其在维护系统内部信息交换的完整性和连续性方面的作用。 + +# Input types +## Required +- pipe + - ‘pipe’ 参数对于 CR_DataBusOut 节点的运作至关重要,因为它代表了用于传输数据的管道。它是一个通道,允许信息的有序传递,强调了它在节点执行中的重要性。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple[Any, ...] + +# Output types +- pipe + - ‘pipe’ 输出参数表示携带处理后数据的管道。它是节点功能的关键元素,因为它负责将数据传递到工作流中的后续阶段。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple[Any, ...] +- any1 + - ‘any1’ 输出参数代表由节点处理的通用数据元素。它展示了节点处理各种数据类型的能力,有助于数据处理管道的灵活性。 + - Comfy dtype: Any + - Python dtype: Any +- any2 + - ‘any2’ 输出参数是节点处理不同类型数据的多功能性的另一个例子。它进一步强调了节点在管道中适应不同数据结构的作用。 + - Comfy dtype: Any + - Python dtype: Any +- any3 + - ‘any3’ 输出参数,像 ‘any1’ 和 ‘any2’ 一样,表明了节点处理和传递各种数据元素的能力。它是节点采用的更广泛数据管理策略的一部分。 + - Comfy dtype: Any + - Python dtype: Any +- any4 + - ‘any4’ 输出参数继续展示了节点在管理各种数据输入方面的适应性。它对节点全面的数据处理方法至关重要。 + - Comfy dtype: Any + - Python dtype: Any +- show_help + - ‘show_help’ 输出提供了一个链接到文档的链接,以供进一步帮助。对于寻求有关节点操作和功能的更多信息的用户来说,这是一个宝贵的资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_DataBusOut: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',)}} + RETURN_TYPES = ('PIPE_LINE', any_type, any_type, any_type, any_type, 'STRING') + RETURN_NAMES = ('pipe', 'any1', 'any2', 'any3', 'any4', 'show_help') + FUNCTION = 'data_out' + CATEGORY = icons.get('Comfyroll/Pipe/Bus') + + def data_out(self, any1=None, any2=None, any3=None, any4=None, pipe=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pipe-Nodes#cr-data-bus-out' + (new_any1, new_any2, new_any3, new_any4) = pipe + return (pipe, new_any1, new_any2, new_any3, new_any4, show_help) +``` \ No newline at end of file diff --git a/docs/CR Debatch Frames.md b/docs/CR Debatch Frames.md new file mode 100644 index 0000000..7b2952a --- /dev/null +++ b/docs/CR Debatch Frames.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: CR_DebatchFrames +- Category: Comfyroll/Animation/Utils +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_DebatchFrames 节点旨在处理并拆分输入数据为单独的帧。它在动画工作流程中准备数据进行进一步分析或处理中扮演着关键角色,确保每个帧都能独立处理。 + +# Input types +## Required +- frames + - ‘frames’参数至关重要,因为它代表了节点将处理的图像帧批次。它通过确定将被拆分为单独帧的输入数据来影响节点的执行。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- debatched_frames + - ‘debatched_frames’输出由从输入批次中提取的单独帧组成。这个输出很重要,因为它构成了动画流水线中后续操作的基础。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_DebatchFrames: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'frames': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('debatched_frames',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'debatch' + CATEGORY = icons.get('Comfyroll/Animation/Utils') + + def debatch(self, frames): + images = [frames[i:i + 1, ...] for i in range(frames.shape[0])] + return (images,) +``` \ No newline at end of file diff --git a/docs/CR Diamond Panel.md b/docs/CR Diamond Panel.md new file mode 100644 index 0000000..57878eb --- /dev/null +++ b/docs/CR Diamond Panel.md @@ -0,0 +1,85 @@ +# Documentation +- Class name: CR_DiamondPanel +- Category: Graphics/Layout +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_DiamondPanel 是一个用于从图像创建视觉吸引人的菱形面板的节点。它通过提供图案设计增强了布局功能,可以无缝集成到各种图形应用中。这个节点专注于图像的美学展示,允许在面板排列和设计中自由创作。 + +# Input types +## Required +- image + - 图像参数是 CR_DiamondPanel 节点的核心输入,用于生成菱形面板。它至关重要,因为它决定了输出面板的视觉内容。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- pattern + - 图案参数决定了应用于面板的设计类型。它很重要,因为它允许用户选择标准或菱形图案,影响布局的最终外观。 + - Comfy dtype: COMBO['none', 'diamond'] + - Python dtype: str +## Optional +- drop_percentage + - drop_percentage 参数调整菱形面板之间的间距。它在整体构图中起着至关重要的作用,通过控制布局中面板的密度和排列方式。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- image + - CR_DiamondPanel 节点的图像输出代表了最终的菱形图案布局。它是输入图像和所选图案的结合,可供进一步使用或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个链接到文档的链接,以供进一步帮助。对于寻求如何使用节点或解决故障的用户来说,这是一个有用的资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_DiamondPanel: + + @classmethod + def INPUT_TYPES(s): + patterns = ['none', 'diamond'] + return {'required': {'image': ('IMAGE',), 'pattern': (patterns,)}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image', 'show_help') + FUNCTION = 'make_panel' + CATEGORY = icons.get('Comfyroll/Graphics/Layout') + + def make_panel(self, image, pattern, drop_percentage=0.5): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Layout-Nodes#cr-diamond-panel' + if pattern == 'none': + return (image, show_help) + pil_img = tensor2pil(image) + pil_img = pil_img.convert('RGBA') + (x, y) = pil_img.size + aspect_ratio = x / y + d = int(drop_percentage * 100) + panel_image = Image.new('RGBA', (x * 2, y * 2)) + if pattern == 'diamond': + diamond_size = min(x, y) + diamond_width = min(x, y * aspect_ratio) + diamond_height = min(y, x / aspect_ratio) + diamond_mask = Image.new('L', (x, y), 0) + draw = ImageDraw.Draw(diamond_mask) + draw.polygon([(x // 2, 0), (x, y // 2), (x // 2, y), (0, y // 2)], fill=255) + diamond_image = pil_img.copy() + diamond_image.putalpha(diamond_mask) + panel_image.paste(diamond_image, (-x // 2, (d - 100) * y // 100), diamond_image) + panel_image.paste(diamond_image, (-x // 2, d * y // 100), diamond_image) + panel_image.paste(diamond_image, (-x // 2, y + d * y // 100), diamond_image) + panel_image.paste(diamond_image, (0, 0), diamond_image) + panel_image.paste(diamond_image, (0, y), diamond_image) + panel_image.paste(diamond_image, (x // 2, (d - 100) * y // 100), diamond_image) + panel_image.paste(diamond_image, (x // 2, d * y // 100), diamond_image) + panel_image.paste(diamond_image, (x // 2, y + d * y // 100), diamond_image) + panel_image.paste(diamond_image, (x, 0), diamond_image) + panel_image.paste(diamond_image, (x, y), diamond_image) + panel_image.paste(diamond_image, (3 * x // 2, (d - 100) * y // 100), diamond_image) + panel_image.paste(diamond_image, (3 * x // 2, d * y // 100), diamond_image) + panel_image.paste(diamond_image, (3 * x // 2, y + d * y // 100), diamond_image) + image_out = pil2tensor(panel_image.convert('RGB')) + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Draw Pie.md b/docs/CR Draw Pie.md new file mode 100644 index 0000000..d0964a2 --- /dev/null +++ b/docs/CR Draw Pie.md @@ -0,0 +1,104 @@ +# Documentation +- Class name: CR_DrawPie +- Category: Comfyroll/Graphics/Shape +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_DrawPie是一个设计用来生成饼图视觉表示的节点。它允许定制饼图的外观,包括其尺寸、起始和结束角度、颜色和旋转。该节点的功能集中在创建数据段的图形表示上,使其成为可视化比例和分布的多功能工具。 + +# Input types +## Required +- width + - 宽度决定了饼图的宽度,是设置输出图像整体尺寸的关键参数。它直接影响饼图可视化的比例和宽高比。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度设置了饼图的垂直范围,与宽度一起确定图表的比例。它在饼图的最终外观中扮演重要角色,确保视觉表示平衡。 + - Comfy dtype: INT + - Python dtype: int +- pie_start + - 饼图起始是饼图分段开始的初始角度。它对于定义分段的起始位置至关重要,并有助于整体饼图的构图。 + - Comfy dtype: FLOAT + - Python dtype: float +- pie_stop + - 饼图结束是饼图分段结束的角度。它与饼图起始一起工作,以确定饼图中分段的大小和范围。 + - Comfy dtype: FLOAT + - Python dtype: float +- shape_color + - 形状颜色定义了饼图分段的颜色,允许用户自定义数据表示的外观。这是视觉设计的关键方面,可以传达不同的含义或类别。 + - Comfy dtype: COLORS + - Python dtype: str +- back_color + - 背景颜色设置了饼图的背景颜色,为形状颜色提供对比或互补的色调。它是增强图表视觉吸引力和清晰度的重要参数。 + - Comfy dtype: COLORS + - Python dtype: str +## Optional +- x_offset + - X偏移用于调整画布内饼图的水平位置。它可以用于对齐多个图表或为了美观目的定位图表。 + - Comfy dtype: INT + - Python dtype: int +- y_offset + - Y偏移用于调整画布内饼图的垂直位置。与X偏移类似,它有助于为最佳视觉展示定位图表。 + - Comfy dtype: INT + - Python dtype: int +- zoom + - 缩放是一个调整饼图相对于其原始尺寸大小的比例因子。它可以用来强调图表或将其适应于特定空间。 + - Comfy dtype: FLOAT + - Python dtype: float +- rotation + - 旋转允许围绕饼图的中心旋转。这可以用来将图表定向到特定方向或创建动态视觉效果。 + - Comfy dtype: FLOAT + - Python dtype: float +- shape_color_hex + - 形状颜色十六进制提供了饼图分段的十六进制颜色代码,提供了对使用颜色的精确控制。它是形状颜色参数的替代方案,适用于需要特定颜色值的用户。 + - Comfy dtype: STRING + - Python dtype: str +- bg_color_hex + - 背景颜色十六进制为饼图的背景指定了十六进制颜色代码,允许微调背景颜色以满足特定的设计要求。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - IMAGE输出提供了生成的饼图作为图像文件。这是节点操作的主结果,包含了数据输入的视觉表示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help输出提供了一个URL链接到文档页面,以获取有关节点使用和功能的进一步帮助或信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_DrawPie: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'width': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'pie_start': ('FLOAT', {'default': 30.0, 'min': 0.0, 'max': 9999.0, 'step': 0.1}), 'pie_stop': ('FLOAT', {'default': 330.0, 'min': 0.0, 'max': 9999.0, 'step': 0.1}), 'shape_color': (COLORS,), 'back_color': (COLORS,), 'x_offset': ('INT', {'default': 0, 'min': -2048, 'max': 2048}), 'y_offset': ('INT', {'default': 0, 'min': -2048, 'max': 2048}), 'zoom': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.05}), 'rotation': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 3600.0, 'step': 0.1})}, 'optional': {'shape_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'bg_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'make_shape' + CATEGORY = icons.get('Comfyroll/Graphics/Shape') + + def make_shape(self, width, height, rotation, pie_start, pie_stop, shape_color, back_color, x_offset=0, y_offset=0, zoom=1.0, shape_color_hex='#000000', bg_color_hex='#000000'): + bg_color = get_color_values(back_color, bg_color_hex, color_mapping) + shape_color = get_color_values(shape_color, shape_color_hex, color_mapping) + back_img = Image.new('RGB', (width, height), color=bg_color) + shape_img = Image.new('RGBA', (width, height), color=(0, 0, 0, 0)) + draw = ImageDraw.Draw(shape_img, 'RGBA') + center_x = width // 2 + x_offset + center_y = height // 2 + y_offset + size = min(width - x_offset, height - y_offset) * zoom + aspect_ratio = width / height + num_rays = 16 + color = 'white' + draw.pieslice([(center_x - size / 2, center_y - size / 2), (center_x + size / 2, center_y + size / 2)], start=pie_start, end=pie_stop, fill=color, outline=None) + shape_img = shape_img.rotate(rotation, center=(center_x, center_y)) + result_image = Image.alpha_composite(back_img.convert('RGBA'), shape_img) + image_out = pil2tensor(result_image.convert('RGB')) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pattern-Nodes-2#cr-draw-pie' + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Draw Shape.md b/docs/CR Draw Shape.md new file mode 100644 index 0000000..afaf3a8 --- /dev/null +++ b/docs/CR Draw Shape.md @@ -0,0 +1,98 @@ +# Documentation +- Class name: CR_DrawShape +- Category: Comfyroll/Graphics/Shape +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_DrawShape 是一个多功能节点,旨在生成多种几何形状,并允许自定义属性。它强调在形状创建中的灵活性,使用户能够定义形状的尺寸、颜色和方向。该节点的功能扩展到修改背景,并应用旋转和缩放等转换,以实现定制化的视觉输出。 + +# Input types +## Required +- width + - 宽度决定了形状画布的水平范围,影响输出图像的整体规模。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度设置了画布的垂直尺寸,与宽度一起确定画布的大小。 + - Comfy dtype: INT + - Python dtype: int +- shape + - 形状定义了要绘制的几何形状,提供了多种标准形状供选择。 + - Comfy dtype: STRING + - Python dtype: str +- shape_color + - 形状颜色决定了形状本身的色调,使其具有视觉区分度和美学吸引力。 + - Comfy dtype: STRING + - Python dtype: str +- back_color + - 背景颜色为画布设定基调,为形状提供对比或补充的背景。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- x_offset + - X偏移调整形状的水平位置,允许在画布上精确放置。 + - Comfy dtype: INT + - Python dtype: int +- y_offset + - Y偏移修改垂直位置,提供对形状在画布上位置的控制。 + - Comfy dtype: INT + - Python dtype: int +- zoom + - 缩放控制形状的比例因子,影响其在画布上的大小,而不影响画布的尺寸。 + - Comfy dtype: FLOAT + - Python dtype: float +- rotation + - 旋转为形状应用一定程度的旋转,增强其视觉动态效果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- IMAGE + - IMAGE输出提供渲染的形状作为图像,可供进一步处理或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help输出提供了指向节点文档的URL,以获取更多指导和信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_DrawShape: + + @classmethod + def INPUT_TYPES(cls): + shapes = ['circle', 'oval', 'square', 'diamond', 'triangle', 'hexagon', 'octagon', 'quarter circle', 'half circle', 'quarter circle', 'starburst', 'star', 'cross', 'diagonal regions'] + return {'required': {'width': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'shape': (shapes,), 'shape_color': (COLORS,), 'back_color': (COLORS,), 'x_offset': ('INT', {'default': 0, 'min': -2048, 'max': 2048}), 'y_offset': ('INT', {'default': 0, 'min': -2048, 'max': 2048}), 'zoom': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.05}), 'rotation': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 3600.0, 'step': 0.1})}, 'optional': {'shape_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'bg_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'make_shape' + CATEGORY = icons.get('Comfyroll/Graphics/Shape') + + def make_shape(self, width, height, rotation, shape, shape_color, back_color, x_offset=0, y_offset=0, zoom=1.0, shape_color_hex='#000000', bg_color_hex='#000000'): + bg_color = get_color_values(back_color, bg_color_hex, color_mapping) + shape_color = get_color_values(shape_color, shape_color_hex, color_mapping) + back_img = Image.new('RGB', (width, height), color=bg_color) + shape_img = Image.new('RGB', (width, height), color=shape_color) + shape_mask = Image.new('L', (width, height)) + draw = ImageDraw.Draw(shape_mask) + center_x = width // 2 + x_offset + center_y = height // 2 + y_offset + size = min(width - x_offset, height - y_offset) * zoom + aspect_ratio = width / height + color = 'white' + shape_functions = {'circle': draw_circle, 'oval': draw_oval, 'diamond': draw_diamond, 'square': draw_square, 'triangle': draw_triangle, 'hexagon': draw_hexagon, 'octagon': draw_octagon, 'quarter circle': draw_quarter_circle, 'half circle': draw_half_circle, 'starburst': draw_starburst, 'star': draw_star, 'cross': draw_cross} + if shape in shape_functions: + shape_function = shape_functions.get(shape) + shape_function(draw, center_x, center_y, size, aspect_ratio, color) + if shape == 'diagonal regions': + draw.polygon([(width, 0), (width, height), (0, height)], fill=color) + shape_mask = shape_mask.rotate(rotation, center=(center_x, center_y)) + result_image = Image.composite(shape_img, back_img, shape_mask) + image_out = pil2tensor(result_image) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pattern-Nodes-2#cr-draw-shape' + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Draw Text.md b/docs/CR Draw Text.md new file mode 100644 index 0000000..35550cc --- /dev/null +++ b/docs/CR Draw Text.md @@ -0,0 +1,110 @@ +# Documentation +- Class name: CR_DrawText +- Category: Comfyroll/Graphics/Text +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_DrawText 节点旨在将文本渲染到图像上。它允许自定义字体、颜色和位置,以创建视觉上吸引人的文本覆盖。这个节点功能多样,可以在需要将文本动态添加到图像的各种应用中使用。 + +# Input types +## Required +- image_width + - 文本将被绘制在其上的图像的宽度。这是一个关键参数,决定了输出图像的整体大小。 + - Comfy dtype: INT + - Python dtype: int +- image_height + - 图像的高度。它与宽度一起工作,设置文本将被渲染的画布的尺寸。 + - Comfy dtype: INT + - Python dtype: int +- text + - 要绘制到图像上的实际文本内容。它可以包含多行文本以适应段落或列表。 + - Comfy dtype: STRING + - Python dtype: str +- font_name + - 用于文本的字体名称。它必须是指定字体目录中可用的有效.ttf字体文件。 + - Comfy dtype: STRING + - Python dtype: str +- font_size + - 字体的大小,以点为单位。它影响文本在图像中的可读性和视觉突出度。 + - Comfy dtype: INT + - Python dtype: int +- font_color + - 字体的颜色。它由一个名称指定,该名称对应于预定义颜色映射中的一种颜色。 + - Comfy dtype: STRING + - Python dtype: str +- background_color + - 文本区域的背景颜色。它用于创建与文本形成对比的背景,使文本更加突出。 + - Comfy dtype: STRING + - Python dtype: str +- align + - 文本的水平对齐方式。它决定了文本如何分布在图像的宽度上。 + - Comfy dtype: STRING + - Python dtype: str +- justify + - 文本的对齐方式。它控制文本中单词和字符之间的间距。 + - Comfy dtype: STRING + - Python dtype: str +- margins + - 文本周围的空间,以像素为单位。它在文本和图像边缘之间添加了一个缓冲区。 + - Comfy dtype: INT + - Python dtype: int +- line_spacing + - 文本行之间的空间,它影响多行文本的整体可读性和布局。 + - Comfy dtype: INT + - Python dtype: int +- position_x + - 文本将开始的水平位置。它以像素为单位,从图像的左侧边缘开始计算。 + - Comfy dtype: INT + - Python dtype: int +- position_y + - 文本将开始的垂直位置。它以像素为单位,从图像的顶部边缘开始计算。 + - Comfy dtype: INT + - Python dtype: int +- rotation_angle + - 文本将被旋转的角度。它可以用来通过倾斜文本来创建风格化的效果。 + - Comfy dtype: FLOAT + - Python dtype: float +- rotation_options + - 确定文本旋转的支点。它可以是文本的中心或图像的中心。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - 绘制了文本的结果图像。它是节点的主要输出,代表了最终的视觉产品。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- show_help + - 指向节点文档的URL链接。它提供了关于如何有效使用节点的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_DrawText: + + @classmethod + def INPUT_TYPES(s): + font_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'fonts') + file_list = [f for f in os.listdir(font_dir) if os.path.isfile(os.path.join(font_dir, f)) and f.lower().endswith('.ttf')] + return {'required': {'image_width': ('INT', {'default': 512, 'min': 64, 'max': 2048}), 'image_height': ('INT', {'default': 512, 'min': 64, 'max': 2048}), 'text': ('STRING', {'multiline': True, 'default': 'text'}), 'font_name': (file_list,), 'font_size': ('INT', {'default': 50, 'min': 1, 'max': 1024}), 'font_color': (COLORS,), 'background_color': (COLORS,), 'align': (ALIGN_OPTIONS,), 'justify': (JUSTIFY_OPTIONS,), 'margins': ('INT', {'default': 0, 'min': -1024, 'max': 1024}), 'line_spacing': ('INT', {'default': 0, 'min': -1024, 'max': 1024}), 'position_x': ('INT', {'default': 0, 'min': -4096, 'max': 4096}), 'position_y': ('INT', {'default': 0, 'min': -4096, 'max': 4096}), 'rotation_angle': ('FLOAT', {'default': 0.0, 'min': -360.0, 'max': 360.0, 'step': 0.1}), 'rotation_options': (ROTATE_OPTIONS,)}, 'optional': {'font_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'bg_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'draw_text' + CATEGORY = icons.get('Comfyroll/Graphics/Text') + + def draw_text(self, image_width, image_height, text, font_name, font_size, font_color, background_color, margins, line_spacing, position_x, position_y, align, justify, rotation_angle, rotation_options, font_color_hex='#000000', bg_color_hex='#000000'): + text_color = get_color_values(font_color, font_color_hex, color_mapping) + bg_color = get_color_values(background_color, bg_color_hex, color_mapping) + size = (image_width, image_height) + text_image = Image.new('RGB', size, text_color) + back_image = Image.new('RGB', size, bg_color) + text_mask = Image.new('L', back_image.size) + rotated_text_mask = draw_masked_text(text_mask, text, font_name, font_size, margins, line_spacing, position_x, position_y, align, justify, rotation_angle, rotation_options) + image_out = Image.composite(text_image, back_image, rotated_text_mask) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Text-Nodes#cr-draw-text' + return (pil2tensor(image_out), show_help) +``` \ No newline at end of file diff --git a/docs/CR Encode Scheduled Prompts.md b/docs/CR Encode Scheduled Prompts.md new file mode 100644 index 0000000..a28ed19 --- /dev/null +++ b/docs/CR Encode Scheduled Prompts.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: CR_EncodeScheduledPrompts +- Category: Comfyroll/Animation/Prompt +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_EncodeScheduledPrompts 节点旨在管理动画序列中提示的编码。它根据指定的权重智能地混合当前提示和下一个提示,确保状态之间的平滑过渡。此节点对于创建连贯且内容丰富的动画至关重要。 + +# Input types +## Required +- clip + - clip 参数至关重要,因为它代表了编码过程的核心输入。它是将被标记化和编码以生成提示的原始数据。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- current_prompt + - current_prompt 参数作为当前动画中使用的文本输入。它是编码过程中的关键组成部分,因为它定义了过渡的起点。 + - Comfy dtype: STRING + - Python dtype: str +- next_prompt + - next_prompt 参数表示动画中将过渡到的即将到来的文本输入。它在确定提示编码的方向中起着至关重要的作用。 + - Comfy dtype: STRING + - Python dtype: str +- weight + - weight 参数用于控制当前提示和下一个提示的混合。它通过确定过渡的强度直接影响编码过程。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- CONDITIONING + - CONDITIONING 输出代表已编码的提示,准备用于动画中。它是一个关键的输出,因为它为后续的动画步骤提供了必要的数据。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] +- show_help + - show_help 输出提供了一个 URL 链接到文档,以进一步协助和理解如何有效地使用该节点。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CR_EncodeScheduledPrompts: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'clip': ('CLIP',), 'current_prompt': ('STRING', {'multiline': True}), 'next_prompt': ('STRING', {'multiline': True}), 'weight': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.01})}} + RETURN_TYPES = ('CONDITIONING', 'STRING') + RETURN_NAMES = ('CONDITIONING', 'show_help') + FUNCTION = 'condition' + CATEGORY = icons.get('Comfyroll/Animation/Prompt') + + def condition(self, clip, current_prompt, next_prompt, weight): + tokens = clip.tokenize(str(next_prompt)) + (cond_from, pooled_from) = clip.encode_from_tokens(tokens, return_pooled=True) + tokens = clip.tokenize(str(current_prompt)) + (cond_to, pooled_to) = clip.encode_from_tokens(tokens, return_pooled=True) + print(weight) + conditioning_to_strength = weight + conditioning_from = [[cond_from, {'pooled_output': pooled_from}]] + conditioning_to = [[cond_to, {'pooled_output': pooled_to}]] + out = [] + if len(conditioning_from) > 1: + print('Warning: Conditioning from contains more than 1 cond, only the first one will actually be applied to conditioning_to.') + cond_from = conditioning_from[0][0] + pooled_output_from = conditioning_from[0][1].get('pooled_output', None) + for i in range(len(conditioning_to)): + t1 = conditioning_to[i][0] + pooled_output_to = conditioning_to[i][1].get('pooled_output', pooled_output_from) + t0 = cond_from[:, :t1.shape[1]] + if t0.shape[1] < t1.shape[1]: + t0 = torch.cat([t0] + [torch.zeros((1, t1.shape[1] - t0.shape[1], t1.shape[2]))], dim=1) + tw = torch.mul(t1, conditioning_to_strength) + torch.mul(t0, 1.0 - conditioning_to_strength) + t_to = conditioning_to[i][1].copy() + if pooled_output_from is not None and pooled_output_to is not None: + t_to['pooled_output'] = torch.mul(pooled_output_to, conditioning_to_strength) + torch.mul(pooled_output_from, 1.0 - conditioning_to_strength) + elif pooled_output_from is not None: + t_to['pooled_output'] = pooled_output_from + n = [tw, t_to] + out.append(n) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Prompt-Nodes#cr-encode-scheduled-prompts' + return (out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Feathered Border.md b/docs/CR Feathered Border.md new file mode 100644 index 0000000..11d94e5 --- /dev/null +++ b/docs/CR Feathered Border.md @@ -0,0 +1,98 @@ +# Documentation +- Class name: CR_FeatheredBorder +- Category: Comfyroll/Graphics/Layout +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_FeatheredBorder节点旨在为图像添加羽化边框,提供图像与其周围环境之间的柔和且视觉吸引力强的过渡。它允许自定义边框的厚度和颜色,为用户提供对图像最终外观的高度控制。 + +# Input types +## Required +- image + - 图像参数是节点的核心输入,表示将应用羽化边框的图像。它对节点的执行至关重要,因为它决定了要添加边框效果的基础内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- top_thickness + - top_thickness参数指定应用于图像顶部边缘的边框厚度。它在定义带有边框的最终图像的整体尺寸方面起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- bottom_thickness + - bottom_thickness参数设置图像底部边缘的边框厚度,有助于整体边框外观和图像的最终大小。 + - Comfy dtype: INT + - Python dtype: int +- left_thickness + - left_thickness参数确定图像左侧边框的厚度,影响带有边框的图像的最终展示。 + - Comfy dtype: INT + - Python dtype: int +- right_thickness + - right_thickness参数控制图像右侧边框的厚度,影响包括边框在内的图像的总宽度。 + - Comfy dtype: INT + - Python dtype: int +- border_color + - border_color参数对于定义将应用于图像的边框颜色至关重要。它显著影响最终输出的视觉美感。 + - Comfy dtype: COLOR + - Python dtype: str +- feather_amount + - feather_amount参数决定边框边缘的柔和度,在图像和边框之间创建平滑过渡。它是实现专业和精致外观的关键。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- border_color_hex + - border_color_hex参数允许使用自定义的十六进制颜色值用于边框,为用户提供了实现特定颜色方案的额外灵活性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- image + - 图像输出参数代表应用了羽化边框的最终图像。它是节点执行的主要结果,也是节点目的的核心。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help输出提供指向节点文档页面的URL,为用户提供了如何有效使用该节点的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_FeatheredBorder: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'top_thickness': ('INT', {'default': 0, 'min': 0, 'max': 4096}), 'bottom_thickness': ('INT', {'default': 0, 'min': 0, 'max': 4096}), 'left_thickness': ('INT', {'default': 0, 'min': 0, 'max': 4096}), 'right_thickness': ('INT', {'default': 0, 'min': 0, 'max': 4096}), 'border_color': (COLORS,), 'feather_amount': ('INT', {'default': 0, 'min': 0, 'max': 1024})}, 'optional': {'border_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image', 'show_help') + FUNCTION = 'make_border' + CATEGORY = icons.get('Comfyroll/Graphics/Layout') + + def make_border(self, image, top_thickness, bottom_thickness, left_thickness, right_thickness, border_color, feather_amount, border_color_hex='#000000'): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Layout-Nodes#cr-feathered-border' + images = [] + border_color = get_color_values(border_color, border_color_hex, color_mapping) + for img in image: + im = tensor2pil(img) + RADIUS = feather_amount + diam = 2 * RADIUS + back = Image.new('RGB', (im.size[0] + diam, im.size[1] + diam), border_color) + back.paste(im, (RADIUS, RADIUS)) + mask = Image.new('L', back.size, 0) + draw = ImageDraw.Draw(mask) + (x0, y0) = (0, 0) + (x1, y1) = back.size + for d in range(diam + RADIUS): + (x1, y1) = (x1 - 1, y1 - 1) + alpha = 255 if d < RADIUS else int(255 * (diam + RADIUS - d) / diam) + draw.rectangle([x0, y0, x1, y1], outline=alpha) + (x0, y0) = (x0 + 1, y0 + 1) + blur = back.filter(ImageFilter.GaussianBlur(RADIUS / 2)) + back.paste(blur, mask=mask) + if left_thickness > 0 or right_thickness > 0 or top_thickness > 0 or (bottom_thickness > 0): + img = ImageOps.expand(back, (left_thickness, top_thickness, right_thickness, bottom_thickness), fill=border_color) + else: + img = back + images.append(pil2tensor(img)) + images = torch.cat(images, dim=0) + return (images, show_help) +``` \ No newline at end of file diff --git a/docs/CR Float Range List.md b/docs/CR Float Range List.md new file mode 100644 index 0000000..3330579 --- /dev/null +++ b/docs/CR Float Range List.md @@ -0,0 +1,106 @@ +# Documentation +- Class name: CR_FloatRangeList +- Category: Comfyroll/List +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_FloatRangeList 节点旨在生成指定范围内的浮点数列表,可应用可选的数学运算和格式化。它通过参数如开始值、结束值、步长和操作提供了定制化选项,为用户提供了一个多功能工具,用于创建特定需求的数值序列。 + +# Input types +## Required +- start + - 开始值参数定义了范围的初始值。它非常重要,因为它为节点生成的数字序列设定了起始点,对整体输出有显著影响。 + - Comfy dtype: FLOAT + - Python dtype: float +- end + - 结束值参数指定了范围的最终值。它很关键,因为它决定了序列的终点,直接影响生成列表的长度和最后一个值。 + - Comfy dtype: FLOAT + - Python dtype: float +- step + - 步长参数决定了范围内每个值之间的增量。它在数值序列的密度中起着重要作用,控制生成的值的数量及其分布。 + - Comfy dtype: FLOAT + - Python dtype: float +- operation + - 操作参数允许对范围内的每个值应用三角函数。这可以转换序列,引入非线性特征,并启用更复杂的模式。 + - Comfy dtype: COMBO[none, sin, cos, tan] + - Python dtype: str +- decimal_places + - 小数位数参数通过指定小数点后的位数来控制浮点数的精度。它对控制输出值的粒度非常重要。 + - Comfy dtype: INT + - Python dtype: int +- ignore_first_value + - 忽略第一个值参数决定是否从输出中排除范围的初始值。当起始点不感兴趣或需要在后续处理中省略时,这可能很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- max_values_per_loop + - 每个循环的最大值参数设置每个循环迭代生成的最大值数量。它是控制节点产生值的总数的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- loops + - 循环次数参数指定应重复执行范围操作的次数。对于创建多个序列或扩展输出列表很重要。 + - Comfy dtype: INT + - Python dtype: int +- ping_pong + - 乒乓参数引入了一种行为,即每隔一个循环序列就反向,产生“乒乓”效果。这可以用来生成对称或振荡模式。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- FLOAT + - FLOAT 输出提供了应用了指定操作和格式化后的生成浮点数列表。它代表了节点功能的主要结果。 + - Comfy dtype: FLOAT + - Python dtype: List[float] +- show_help + - show_help 输出提供了指向节点文档页面的 URL,为用户提供了关于如何有效使用节点的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_FloatRangeList: + + @classmethod + def INPUT_TYPES(s): + operations = ['none', 'sin', 'cos', 'tan'] + return {'required': {'start': ('FLOAT', {'default': 0.0, 'min': -99999.99, 'max': 99999.99, 'step': 0.01}), 'end': ('FLOAT', {'default': 1.0, 'min': -99999.99, 'max': 99999.99, 'step': 0.01}), 'step': ('FLOAT', {'default': 1.0, 'min': -99999.99, 'max': 99999.99, 'step': 0.01}), 'operation': (operations,), 'decimal_places': ('INT', {'default': 2, 'min': 0, 'max': 10}), 'ignore_first_value': ('BOOLEAN', {'default': True}), 'max_values_per_loop': ('INT', {'default': 128, 'min': 1, 'max': 99999}), 'loops': ('INT', {'default': 1, 'min': 1, 'max': 999}), 'ping_pong': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('FLOAT', 'STRING') + RETURN_NAMES = ('FLOAT', 'show_help') + OUTPUT_IS_LIST = (True, False) + FUNCTION = 'make_range' + CATEGORY = icons.get('Comfyroll/List') + + def make_range(self, start, end, step, max_values_per_loop, operation, decimal_places, ignore_first_value, loops, ping_pong): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-float-range-list' + range_values = list() + for i in range(loops): + if end < start and step > 0: + step = -step + current_range = list(np.arange(start, end + step, step)) + if operation == 'sin': + current_range = [math.sin(value) for value in current_range] + elif operation == 'cos': + current_range = [math.cos(value) for value in current_range] + elif operation == 'tan': + current_range = [math.tan(value) for value in current_range] + current_range = [round(value, decimal_places) for value in current_range] + if ping_pong: + if i % 2 == 1: + if ignore_first_value: + current_range = current_range[:-1] + current_range = current_range[:max_values_per_loop] + range_values += reversed(current_range) + else: + if ignore_first_value: + current_range = current_range[1:] + current_range = current_range[:max_values_per_loop] + range_values += current_range + else: + if ignore_first_value: + current_range = current_range[1:] + current_range = current_range[:max_values_per_loop] + range_values += current_range + return (range_values, show_help) +``` \ No newline at end of file diff --git a/docs/CR Float To Integer.md b/docs/CR Float To Integer.md new file mode 100644 index 0000000..617b01e --- /dev/null +++ b/docs/CR Float To Integer.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: CR_FloatToInteger +- Category: Comfyroll/Utils/Conversion +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_FloatToInteger节点旨在将浮点数转换为它们的整数等价物。它通过确保不同计算任务中的数值一致性和兼容性,在数据处理中发挥关键作用。当只有整数值是可接受或必需的情况下,这个节点尤其有用。 + +# Input types +## Required +- _float + - _float参数对于节点的操作至关重要,因为它是需要被转换为整数的输入浮点数。它的转换对于需要整数输入的各种数学和逻辑操作是必不可少的。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- INT + - INT输出代表了输入浮点数的整数转换。它是重要的,因为它提供了一个离散的数值,可以用于只有整数值才允许的计算中。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - show_help输出提供了一个URL链接到文档,以供进一步帮助。它作为用户寻求有关节点功能和用法的更多信息的有用资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_FloatToInteger: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'_float': ('FLOAT', {'default': 0.0, 'forceInput': True, 'forceInput': True})}} + RETURN_TYPES = ('INT', 'STRING') + RETURN_NAMES = ('INT', 'show_help') + FUNCTION = 'convert' + CATEGORY = icons.get('Comfyroll/Utils/Conversion') + + def convert(self, _float): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Conversion-Nodes#cr-float-to-integer' + return (int(_float), show_help) +``` \ No newline at end of file diff --git a/docs/CR Float To String.md b/docs/CR Float To String.md new file mode 100644 index 0000000..447d597 --- /dev/null +++ b/docs/CR Float To String.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: CR_FloatToString +- Category: Comfyroll/Utils/Conversion +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_FloatToString节点旨在将浮点数转换为它们的字符串表示形式。这种转换对于各种需要以文本格式显示或处理数值数据的应用场景至关重要。该节点在数据预处理中扮演着核心角色,适用于生成报告、与需要文本输入的系统进行接口对接,或与存储数值数据为字符串的数据库进行集成等任务。 + +# Input types +## Required +- float_ + - 'float_'参数是一个浮点数,节点将将其转换为字符串。这是一个基本输入,因为节点的全部操作都围绕这个数值进行。转换过程确保数值数据可以在需要字符串格式的上下文中使用。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- STRING + - 'STRING'输出提供了输入浮点数的字符串表示。这个输出很重要,因为它是节点操作的主要结果,允许用户在后续的流程或应用中使用转换后的字符串。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - 'show_help'输出是一个URL字符串,它将用户指向节点的帮助文档。它作为用户需要额外信息或有效使用节点的指导时的便捷参考。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_FloatToString: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'float_': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1000000.0, 'forceInput': True})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + FUNCTION = 'convert' + CATEGORY = icons.get('Comfyroll/Utils/Conversion') + + def convert(self, float_): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Conversion-Nodes#cr-float-to-string' + return (f'{float_}', show_help) +``` \ No newline at end of file diff --git a/docs/CR Font File List.md b/docs/CR Font File List.md new file mode 100644 index 0000000..c3ee830 --- /dev/null +++ b/docs/CR Font File List.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: CR_FontFileList +- Category: Comfyroll/List/IO +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_FontFileList是一个用于生成指定目录中字体文件列表的节点。它可以从系统的字体目录、特定于Comfyroll的目录或用户定义的文件夹中获取字体。该节点能够处理大量的字体文件,并提供选项来指定开始索引和要列出的最大行数,确保了高效的数据处理和检索。 + +# Input types +## Required +- source_folder + - source_folder参数决定了将列出字体文件的目录。它可以设置为'system'以列出系统字体目录中的字体,'Comfyroll'以列出Comfyroll目录中的字体,或者'from folder'以指定自定义文件夹路径。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- start_index + - start_index参数用于指定字体文件列表中的起始点。它允许从列表的开始选择字体的子集,这对于大型字体集合特别有用。 + - Comfy dtype: INT + - Python dtype: int +- max_rows + - max_rows参数设置要列出的字体文件的最大数量。它是一个关键的设置,用于控制输出列表的大小并有效管理内存使用。 + - Comfy dtype: INT + - Python dtype: int +- folder_path + - folder_path参数是一个可选输入,当source_folder设置为'from folder'时,允许用户指定自定义目录路径。它使节点能够从用户定义的位置列出字体文件。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- LIST + - LIST输出提供了基于输入参数从指定目录中选择的字体文件名列表。它是应用程序内进一步处理或显示的关键输出。 + - Comfy dtype: STRING + - Python dtype: List[str] +- show_help + - show_help输出提供了一个URL链接到文档,以获得有关使用该节点的额外指导。对于寻求更多信息或故障排除的用户来说,它特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_FontFileList: + + @classmethod + def INPUT_TYPES(s): + comfyroll_font_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'fonts') + comfyroll_file_list = [f for f in os.listdir(comfyroll_font_dir) if os.path.isfile(os.path.join(comfyroll_font_dir, f)) and f.lower().endswith('.ttf')] + sources = ['system', 'Comfyroll', 'from folder'] + return {'required': {'source_folder': (sources,), 'start_index': ('INT', {'default': 0, 'min': 0, 'max': 9999}), 'max_rows': ('INT', {'default': 1000, 'min': 1, 'max': 9999})}, 'optional': {'folder_path': ('STRING', {'default': 'C:\\Windows\\Fonts', 'multiline': False})}} + RETURN_TYPES = (any_type, 'STRING') + RETURN_NAMES = ('LIST', 'show_help') + OUTPUT_IS_LIST = (True, False) + FUNCTION = 'make_list' + CATEGORY = icons.get('Comfyroll/List/IO') + + def make_list(self, source_folder, start_index, max_rows, folder_path='C:\\Windows\\Fonts'): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-font-file-list' + if source_folder == 'system': + system_root = os.environ.get('SystemRoot') + system_font_dir = os.path.join(system_root, 'Fonts') + file_list = [f for f in os.listdir(system_font_dir) if os.path.isfile(os.path.join(system_font_dir, f)) and f.lower().endswith('.ttf')] + elif source_folder == 'Comfyroll': + comfyroll_font_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'fonts') + file_list = [f for f in os.listdir(comfyroll_font_dir) if os.path.isfile(os.path.join(comfyroll_font_dir, f)) and f.lower().endswith('.ttf')] + elif source_folder == 'from folder': + if folder_path != '' and folder_path is not None: + if not os.path.exists(folder_path): + print(f'[Warning] CR Font File List: The folder_path `{folder_path}` does not exist') + return None + font_dir = folder_path + file_list = [f for f in os.listdir(font_dir) if os.path.isfile(os.path.join(font_dir, f)) and f.lower().endswith('.ttf')] + else: + print(f'[Warning] CR Font File List: No folder_path entered') + return None + else: + pass + start_index = max(0, min(start_index, len(file_list) - 1)) + end_index = min(start_index + max_rows, len(file_list)) + selected_files = file_list[start_index:end_index] + return (selected_files, show_help) +``` \ No newline at end of file diff --git a/docs/CR Get Parameter From Prompt.md b/docs/CR Get Parameter From Prompt.md new file mode 100644 index 0000000..d7f4bca --- /dev/null +++ b/docs/CR Get Parameter From Prompt.md @@ -0,0 +1,96 @@ +# Documentation +- Class name: CR_GetParameterFromPrompt +- Category: Comfyroll/Utils/Other +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_GetParameterFromPrompt 节点旨在从给定的提示字符串中提取特定参数。它在提示中搜索指定的搜索字符串,并在找到它时尝试解析随后的值。该节点特别适用于处理嵌入在文本字符串中的配置设置或参数,提供了一种灵活的方式来管理和检索信息。 + +# Input types +## Required +- prompt + - prompt 参数是一个包含节点将搜索并提取参数的文本的字符串。它对节点的操作至关重要,因为它定义了要解析的数据的上下文和来源。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- search_string + - search_string 参数定义了节点将在提示中查找的特定关键字或模式。它在识别要提取的参数中起着关键作用,允许进行有针对性的数据检索。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- prompt + - 修改后的提示,已识别的参数及其值已被移除,允许输出一个没有被搜索参数的清洁文本。 + - Comfy dtype: STRING + - Python dtype: str +- text + - 与搜索字符串关联的提取值,可以是字符串、数字或布尔值,具体取决于在提示中找到的格式。 + - Comfy dtype: STRING + - Python dtype: Union[str, int, float, bool] +- float + - 如果提取的值是数值,则将其转换为浮点数,以便进行进一步的数值运算或分析。 + - Comfy dtype: FLOAT + - Python dtype: float +- boolean + - 提取值的布尔表示,根据找到的内容提供直接的真或假解释。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- show_help + - 指向节点文档或帮助页面的 URL 链接,为用户提供有关如何有效使用节点的额外信息或指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_GetParameterFromPrompt: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'prompt': ('STRING', {'multiline': True, 'default': 'prompt', 'forceInput': True}), 'search_string': ('STRING', {'multiline': False, 'default': '!findme'})}} + RETURN_TYPES = ('STRING', any_type, 'FLOAT', 'BOOLEAN', 'STRING') + RETURN_NAMES = ('prompt', 'text', 'float', 'boolean', 'show_help') + FUNCTION = 'get_string' + CATEGORY = icons.get('Comfyroll/Utils/Other') + + def get_string(self, prompt, search_string): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-find-string-in-prompt' + return_string = '' + return_value = 0 + return_boolean = False + return_prompt = prompt + index = prompt.find(search_string) + if index != -1: + if prompt[index + len(search_string)] == '=': + if prompt[index + len(search_string) + 1] == '"': + start_quote = index + len(search_string) + 2 + end_quote = prompt.find('"', start_quote + 1) + if end_quote != -1: + return_string = prompt[start_quote:end_quote] + print(return_string) + else: + space_index = prompt.find(' ', index + len(search_string)) + if space_index != -1: + return_string = prompt[index + len(search_string):space_index] + else: + return_string = prompt[index + len(search_string):] + else: + return_string = search_string[1:] + if return_string == '': + return (return_prompt, return_string, return_value, return_boolean, show_help) + if return_string.startswith('='): + return_string = return_string[1:] + return_boolean = return_string.lower() == 'true' + try: + return_value = int(return_string) + except ValueError: + try: + return_value = float(return_string) + except ValueError: + return_value = 0 + remove_string = ' ' + search_string + '=' + return_string + return_prompt = prompt.replace(remove_string, '') + return (return_prompt, return_string, return_value, return_boolean, show_help) +``` \ No newline at end of file diff --git a/docs/CR Gradient Float.md b/docs/CR Gradient Float.md new file mode 100644 index 0000000..362008c --- /dev/null +++ b/docs/CR Gradient Float.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: CR_GradientFloat +- Category: Comfyroll/Animation/Interpolate +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_GradientFloat节点旨在在指定的持续时间内生成两个浮点值之间的平滑过渡。它根据开始和结束值、过渡开始的帧以及过渡的总持续时间计算当前值。这个节点特别适用于在时间上为动画参数创建动态变化。 + +# Input types +## Required +- start_value + - 开始值参数定义了渐变的初始值。它对于设置过渡开始的基点至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_value + - 结束值参数指定了渐变在过渡结束时将达到的最终值。它对于确定变化的范围至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_frame + - 开始帧参数指示渐变过渡将开始的帧号。它对于定时动画效果的开始很重要。 + - Comfy dtype: INT + - Python dtype: int +- frame_duration + - 帧持续时间参数决定了渐变过渡发生的帧数。它影响过渡的速度。 + - Comfy dtype: INT + - Python dtype: int +- current_frame + - 当前帧参数表示序列中的当前帧号。它用于计算此时点渐变的当前状态。 + - Comfy dtype: INT + - Python dtype: int +- gradient_profile + - 渐变配置文件参数定义了用于渐变的插值方法类型。它影响开始和结束之间值的计算方式。 + - Comfy dtype: COMBO['Lerp'] + - Python dtype: str + +# Output types +- FLOAT + - FLOAT输出提供了当前帧渐变的计算值,代表过渡的当前状态。 + - Comfy dtype: FLOAT + - Python dtype: float +- show_help + - show_help输出提供了指向节点文档页面的URL,提供有关其用法的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_GradientFloat: + + @classmethod + def INPUT_TYPES(s): + gradient_profiles = ['Lerp'] + return {'required': {'start_value': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 0.01}), 'end_value': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 0.01}), 'start_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'frame_duration': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'gradient_profile': (gradient_profiles,)}} + RETURN_TYPES = ('FLOAT', 'STRING') + RETURN_NAMES = ('FLOAT', 'show_help') + FUNCTION = 'gradient' + CATEGORY = icons.get('Comfyroll/Animation/Interpolate') + + def gradient(self, start_value, end_value, start_frame, frame_duration, current_frame, gradient_profile): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Interpolation-Nodes#cr-gradient-float' + if current_frame < start_frame: + return (start_value, show_help) + if current_frame > start_frame + frame_duration: + return (end_value, show_help) + step = (end_value - start_value) / frame_duration + current_step = current_frame - start_frame + float_out = start_value + current_step * step + return (float_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Gradient Integer.md b/docs/CR Gradient Integer.md new file mode 100644 index 0000000..4b9099e --- /dev/null +++ b/docs/CR Gradient Integer.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: CR_GradientInteger +- Category: Comfyroll/Animation/Interpolate +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_GradientInteger节点提供了一种方法,用于在指定的持续时间内,通过起始帧和帧持续时间,对两个整数值进行插值。它旨在提供从起始值到结束值的平滑过渡,这在动画和基于时间的视觉效果中特别有用。 + +# Input types +## Required +- start_value + - 起始整数值,插值从这个值开始。它对于建立过渡的初始条件至关重要。 + - Comfy dtype: INT + - Python dtype: int +- end_value + - 插值旨在达到的结束整数值。它定义了帧持续时间过后过渡的最终状态。 + - Comfy dtype: INT + - Python dtype: int +- start_frame + - 插值应该开始的帧号。它对于将过渡与动画或序列的时间线同步至关重要。 + - Comfy dtype: INT + - Python dtype: int +- frame_duration + - 插值发生的总帧数。它决定了起始值和结束值之间过渡的长度。 + - Comfy dtype: INT + - Python dtype: int +- current_frame + - 要进行插值的序列中的当前帧。它用于计算过渡过程中的当前步骤。 + - Comfy dtype: INT + - Python dtype: int +- gradient_profile + - 插值配置文件,定义了起始值和结束值之间变化的速率。它影响过渡随时间的进展方式。 + - Comfy dtype: COMBO['Lerp'] + - Python dtype: str + +# Output types +- INT + - 当前帧的插值整数值,是起始值和结束值之间过渡的结果。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - 提供对插值过程的附加文档或帮助的URL字符串。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_GradientInteger: + + @classmethod + def INPUT_TYPES(s): + gradient_profiles = ['Lerp'] + return {'required': {'start_value': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'end_value': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'start_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'frame_duration': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'gradient_profile': (gradient_profiles,)}} + RETURN_TYPES = ('INT', 'STRING') + RETURN_NAMES = ('INT', 'show_help') + FUNCTION = 'gradient' + CATEGORY = icons.get('Comfyroll/Animation/Interpolate') + + def gradient(self, start_value, end_value, start_frame, frame_duration, current_frame, gradient_profile): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Interpolation-Nodes#cr-gradient-integer' + if current_frame < start_frame: + return (start_value, show_help) + if current_frame > start_frame + frame_duration: + return (end_value, show_help) + step = (end_value - start_value) / frame_duration + current_step = current_frame - start_frame + int_out = start_value + int(current_step * step) + return (int_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Half Drop Panel.md b/docs/CR Half Drop Panel.md new file mode 100644 index 0000000..a8d56b7 --- /dev/null +++ b/docs/CR Half Drop Panel.md @@ -0,0 +1,81 @@ +# Documentation +- Class name: CR_HalfDropPanel +- Category: Comfyroll/Graphics/Layout +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_HalfDropPanel 是一个用于根据指定模式操作和转换图像的节点,创建可以自定义百分比值的下落效果。它通过应用半下落、四分之一下落或自定义下落模式增强图像的视觉呈现,为用户提供了一种灵活的方式来调整他们的图像布局和美学,以满足各种设计目的。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它是节点处理的基础输入。它决定了下落面板效果的源材料,对节点的执行至关重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- pattern + - 模式参数决定了要应用于图像的下落效果类型。它对于定义节点将执行的特定视觉转换至关重要。 + - Comfy dtype: COMBO['none', 'half drop', 'quarter drop', 'custom drop %'] + - Python dtype: str +## Optional +- drop_percentage + - drop_percentage 参数是可选的,但在选择自定义下落模式时非常重要。它允许用户控制下落效果的范围,为图像转换提供一定程度的定制化。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- image + - 转换后的图像输出是节点操作的主要结果。它代表了应用了下落模式的图像,作为进一步使用或展示的视觉输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个链接到文档的链接,以供进一步帮助。对于寻求如何使用节点或解决故障的用户来说,这是一个有用的资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_HalfDropPanel: + + @classmethod + def INPUT_TYPES(s): + patterns = ['none', 'half drop', 'quarter drop', 'custom drop %'] + return {'required': {'image': ('IMAGE',), 'pattern': (patterns,)}, 'optional': {'drop_percentage': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image', 'show_help') + FUNCTION = 'make_panel' + CATEGORY = icons.get('Comfyroll/Graphics/Layout') + + def make_panel(self, image, pattern, drop_percentage=0.5): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Layout-Nodes#cr-half-drop-panel' + if pattern == 'none': + return (image, show_help) + pil_img = tensor2pil(image) + pil_img = pil_img.convert('RGBA') + (x, y) = pil_img.size + aspect_ratio = x / y + d = int(drop_percentage * 100) + panel_image = Image.new('RGBA', (x * 2, y * 2)) + if pattern == 'half drop': + panel_image.paste(pil_img, (0, 0)) + panel_image.paste(pil_img, (0, y)) + panel_image.paste(pil_img, (x, -y // 2)) + panel_image.paste(pil_img, (x, y // 2)) + panel_image.paste(pil_img, (x, 3 * y // 2)) + elif pattern == 'quarter drop': + panel_image.paste(pil_img, (0, 0)) + panel_image.paste(pil_img, (0, y)) + panel_image.paste(pil_img, (x, -3 * y // 4)) + panel_image.paste(pil_img, (x, y // 4)) + panel_image.paste(pil_img, (x, 5 * y // 4)) + elif pattern == 'custom drop %': + panel_image.paste(pil_img, (0, 0)) + panel_image.paste(pil_img, (0, y)) + panel_image.paste(pil_img, (x, (d - 100) * y // 100)) + panel_image.paste(pil_img, (x, d * y // 100)) + panel_image.paste(pil_img, (x, y + d * y // 100)) + image_out = pil2tensor(panel_image.convert('RGB')) + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Halftone Filter.md b/docs/CR Halftone Filter.md new file mode 100644 index 0000000..a65756e --- /dev/null +++ b/docs/CR Halftone Filter.md @@ -0,0 +1,190 @@ +# Documentation +- Class name: CR_HalftoneFilter +- Category: Comfyroll/Graphics/Filter +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_HalftoneFilter 节点为图像应用半色调效果,模拟打印点的外观。它提供了对点形状、大小和分辨率的定制,以创建各种半色调风格。该节点旨在增强图形设计和艺术应用的视觉效果,使用户能够实现复古或风格化的外观。 + +# Input types +## Required +- image + - 要应用半色调效果的输入图像。它是节点处理的基础,并决定了半色调转换的主题。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- dot_size + - 半色调效果中使用的点的大小,影响最终图像的粒度。较大的点大小会导致更粗糙的外观,而较小的尺寸则提供更精细的细节。 + - Comfy dtype: INT + - Python dtype: int +- dot_shape + - 确定半色调图案中点的形状。在椭圆和矩形之间的选择可以改变输出图像的视觉纹理,提供了一种调整半色调效果美感的手段。 + - Comfy dtype: COMBO['ellipse', 'rectangle'] + - Python dtype: str +- resolution + - 控制半色调效果的分辨率。'hi-res'选项将输出大小加倍,为半色调图案提供更高的定义,但代价是增加处理时间和资源使用。 + - Comfy dtype: COMBO['normal', 'hi-res (2x output size)'] + - Python dtype: str +- angle_c + - 指定CMYK颜色空间中青色通道的角度,影响半色调图案中青色点的方向。 + - Comfy dtype: INT + - Python dtype: int +- angle_m + - 指定CMYK颜色空间中品红色通道的角度,影响品红色点的方向。 + - Comfy dtype: INT + - Python dtype: int +- angle_y + - 指定CMYK颜色空间中黄色通道的角度,确定黄色点的方向。 + - Comfy dtype: INT + - Python dtype: int +- angle_k + - 指定CMYK颜色空间中关键(黑色)通道的角度,影响黑色点的方向。 + - Comfy dtype: INT + - Python dtype: int +- greyscale + - 一个标志,指示是否应该以灰度处理输入图像。启用时,半色调效果仅应用于亮度通道,将输出简化为单色色调。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- antialias + - 启用或禁用抗锯齿,平滑半色调点的边缘并减少视觉伪影。这可以使最终图像的外观更自然、更精细。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- antialias_scale + - 控制应用于半色调点的抗锯齿级别。更高的值会使外观更平滑,但可能会增加处理时间。 + - Comfy dtype: INT + - Python dtype: int +- border_blending + - 启用时,边框混合平滑了图像边缘附近半色调点之间的过渡,防止出现锐利的分界线,并促进更统一的外观。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- IMAGE + - 应用了半色调效果的输出图像,可供进一步处理或展示。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- show_help + - 提供文档或帮助页面的链接,以便进一步指导如何使用该节点。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_HalftoneFilter: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + shapes = ['ellipse', 'rectangle'] + rez = ['normal', 'hi-res (2x output size)'] + return {'required': {'image': ('IMAGE',), 'dot_size': ('INT', {'default': 5, 'min': 1, 'max': 30, 'step': 1}), 'dot_shape': (shapes, {'default': 'ellipse'}), 'resolution': (rez, {'default': 'normal'}), 'angle_c': ('INT', {'default': 75, 'min': 0, 'max': 360, 'step': 1}), 'angle_m': ('INT', {'default': 45, 'min': 0, 'max': 360, 'step': 1}), 'angle_y': ('INT', {'default': 15, 'min': 0, 'max': 360, 'step': 1}), 'angle_k': ('INT', {'default': 0, 'min': 0, 'max': 360, 'step': 1}), 'greyscale': ('BOOLEAN', {'default': True}), 'antialias': ('BOOLEAN', {'default': True}), 'antialias_scale': ('INT', {'default': 2, 'min': 1, 'max': 4, 'step': 1}), 'border_blending': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'halftone_effect' + CATEGORY = icons.get('Comfyroll/Graphics/Filter') + + def tensor_to_pil(self, tensor): + if tensor.ndim == 4 and tensor.shape[0] == 1: + tensor = tensor.squeeze(0) + if tensor.dtype == torch.float32: + tensor = tensor.mul(255).byte() + elif tensor.dtype != torch.uint8: + tensor = tensor.byte() + numpy_image = tensor.cpu().numpy() + if tensor.ndim == 3: + if tensor.shape[2] == 1: + mode = 'L' + elif tensor.shape[2] == 3: + mode = 'RGB' + elif tensor.shape[2] == 4: + mode = 'RGBA' + else: + raise ValueError(f'Unsupported channel number: {tensor.shape[2]}') + else: + raise ValueError(f'Unexpected tensor shape: {tensor.shape}') + pil_image = Image.fromarray(numpy_image, mode) + return pil_image + + def pil_to_tensor(self, pil_image): + numpy_image = np.array(pil_image) + tensor = torch.from_numpy(numpy_image).float().div(255) + tensor = tensor.unsqueeze(0) + return tensor + + def halftone_effect(self, image, dot_size, dot_shape, resolution, angle_c, angle_m, angle_y, angle_k, greyscale, antialias, border_blending, antialias_scale): + sample = dot_size + shape = dot_shape + resolution_to_scale = {'normal': 1, 'hi-res (2x output size)': 2} + scale = resolution_to_scale.get(resolution, 1) + if isinstance(image, torch.Tensor): + image = self.tensor_to_pil(image) + if not isinstance(image, Image.Image): + raise TypeError('The provided image is neither a PIL Image nor a PyTorch tensor.') + pil_image = image + if greyscale: + pil_image = pil_image.convert('L') + channel_images = [pil_image] + angles = [angle_k] + else: + pil_image = pil_image.convert('CMYK') + channel_images = list(pil_image.split()) + angles = [angle_c, angle_m, angle_y, angle_k] + halftone_images = self._halftone_pil(pil_image, channel_images, sample, scale, angles, antialias, border_blending, antialias_scale, shape) + if greyscale: + new_image = halftone_images[0].convert('RGB') + else: + new_image = Image.merge('CMYK', halftone_images).convert('RGB') + result_tensor = self.pil_to_tensor(new_image) + print('Final tensor shape:', result_tensor.shape) + return (result_tensor, show_help) + + def _halftone_pil(self, im, cmyk, sample, scale, angles, antialias, border_blending, antialias_scale, shape): + antialias_res = antialias_scale if antialias else 1 + scale = scale * antialias_res + dots = [] + for (channel_index, (channel, angle)) in enumerate(zip(cmyk, angles)): + channel = channel.rotate(angle, expand=1) + size = (channel.size[0] * scale, channel.size[1] * scale) + half_tone = Image.new('L', size) + draw = ImageDraw.Draw(half_tone) + for x in range(0, channel.size[0], sample): + for y in range(0, channel.size[1], sample): + if border_blending and angle % 90 != 0 and (x < sample or y < sample or x > channel.size[0] - sample or (y > channel.size[1] - sample)): + neighboring_pixels = channel.crop((max(x - 1, 0), max(y - 1, 0), min(x + 2, channel.size[0]), min(y + 2, channel.size[1]))) + pixels = list(neighboring_pixels.getdata()) + weights = [0.5 if i in [0, len(pixels) - 1] else 1 for i in range(len(pixels))] + weighted_mean = sum((p * w for (p, w) in zip(pixels, weights))) / sum(weights) + mean = weighted_mean + else: + box = channel.crop((x, y, x + sample, y + sample)) + mean = ImageStat.Stat(box).mean[0] + size = (mean / 255) ** 0.5 + box_size = sample * scale + draw_size = size * box_size + (box_x, box_y) = (x * scale, y * scale) + x1 = box_x + (box_size - draw_size) / 2 + y1 = box_y + (box_size - draw_size) / 2 + x2 = x1 + draw_size + y2 = y1 + draw_size + draw_method = getattr(draw, shape, None) + if draw_method: + draw_method([(x1, y1), (x2, y2)], fill=255) + half_tone = half_tone.rotate(-angle, expand=1) + (width_half, height_half) = half_tone.size + xx1 = (width_half - im.size[0] * scale) / 2 + yy1 = (height_half - im.size[1] * scale) / 2 + xx2 = xx1 + im.size[0] * scale + yy2 = yy1 + im.size[1] * scale + half_tone = half_tone.crop((xx1, yy1, xx2, yy2)) + if antialias: + w = int((xx2 - xx1) / antialias_scale) + h = int((yy2 - yy1) / antialias_scale) + half_tone = half_tone.resize((w, h), resample=Image.LANCZOS) + dots.append(half_tone) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Filter-Nodes#cr-halftone-filter' + return (dots, show_help) +``` \ No newline at end of file diff --git a/docs/CR Halftone Grid.md b/docs/CR Halftone Grid.md new file mode 100644 index 0000000..670125e --- /dev/null +++ b/docs/CR Halftone Grid.md @@ -0,0 +1,98 @@ +# Documentation +- Class name: CR_HalftoneGrid +- Category: Comfyroll/Graphics/Pattern +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_HalftoneGrid 是一个用于创建半色调网格图案的节点,具有可定制的参数。它允许用户设置网格的宽度、高度、点样式、频率和位置,为图形设计目的提供了一种多功能的方式来生成视觉上吸引人的图案。节点的功能集中在产生半色调效果上,这是一种使用大小和间距不同的点来模拟不同灰度阴影的图像渲染方法。 + +# Input types +## Required +- width + - 宽度决定了半色调网格的水平范围。这是一个关键参数,因为它直接影响生成的图案的整体尺寸和比例。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度设置了网格的垂直大小,这对于控制图案的垂直尺寸并确保其适应所需的布局至关重要。 + - Comfy dtype: INT + - Python dtype: int +- dot_style + - 点样式定义了网格内点的视觉外观,允许定制图案的美学特性。 + - Comfy dtype: STYLES + - Python dtype: str +- reverse_dot_style + - 反转点样式提供了一个选项来反转点图案,创建一个镜像效果,可以增强网格的视觉兴趣。 + - Comfy dtype: COMBO['No', 'Yes'] + - Python dtype: str +- dot_frequency + - 点频率控制网格内点的数量,影响半色调图案的粒度和细节水平。 + - Comfy dtype: INT + - Python dtype: int +- background_color + - 背景颜色设置了网格的背景颜色,可以自定义或设置为默认颜色以补充图案。 + - Comfy dtype: COLORS + - Python dtype: str +- x_pos + - X位置决定了网格内点图案的水平位置,允许精确控制图案的对齐方式。 + - Comfy dtype: FLOAT + - Python dtype: float +- y_pos + - Y位置设置了点图案的垂直位置,这对于在网格的垂直空间内对齐图案非常重要。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- bg_color_hex + - 背景颜色十六进制允许为网格的背景使用自定义的十六进制颜色,提供了在颜色选择上的额外灵活性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - IMAGE输出提供了生成的半色调网格图案作为图像,可供进一步处理或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help输出提供了一个URL链接到文档页面,以获取有关使用CR_HalftoneGrid节点的进一步帮助和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_HalftoneGrid: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'dot_style': (STYLES,), 'reverse_dot_style': (['No', 'Yes'],), 'dot_frequency': ('INT', {'default': 50, 'min': 1, 'max': 200, 'step': 1}), 'background_color': (COLORS,), 'x_pos': ('FLOAT', {'default': 0.5, 'min': 0, 'max': 1, 'step': 0.01}), 'y_pos': ('FLOAT', {'default': 0.5, 'min': 0, 'max': 1, 'step': 0.01})}, 'optional': {'bg_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'halftone' + CATEGORY = icons.get('Comfyroll/Graphics/Pattern') + + def halftone(self, width, height, dot_style, reverse_dot_style, dot_frequency, background_color, x_pos, y_pos, bg_color_hex='#000000'): + if background_color == 'custom': + bgc = bg_color_hex + else: + bgc = background_color + reverse = '' + if reverse_dot_style == 'Yes': + reverse = '_r' + (fig, ax) = plt.subplots(figsize=(width / 100, height / 100)) + dotsx = np.linspace(0, 1, dot_frequency) + dotsy = np.linspace(0, 1, dot_frequency) + (X, Y) = np.meshgrid(dotsx, dotsy) + dist = np.sqrt((X - x_pos) ** 2 + (Y - y_pos) ** 2) + fig.patch.set_facecolor(bgc) + ax.scatter(X, Y, c=dist, cmap=dot_style + reverse) + plt.axis('off') + plt.tight_layout(pad=0, w_pad=0, h_pad=0) + plt.autoscale(tight=True) + img_buf = io.BytesIO() + plt.savefig(img_buf, format='png') + img = Image.open(img_buf) + image_out = pil2tensor(img.convert('RGB')) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pattern-Nodes#cr-halftone-grid' + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Hires Fix Process Switch.md b/docs/CR Hires Fix Process Switch.md new file mode 100644 index 0000000..23daabb --- /dev/null +++ b/docs/CR Hires Fix Process Switch.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CR_HiResFixProcessSwitch +- Category: Comfyroll/Utils/Process +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_HiResFixProcessSwitch节点作为一个决策单元,根据提供的输入选择两种放大处理过程之一。它旨在通过智能地将处理过程路由到潜在的或图像放大方法,从而提高图像处理任务的效率和灵活性。 + +# Input types +## Required +- Input + - ‘Input’参数至关重要,因为它决定了放大处理的选择路径。它决定了节点将调用潜在的还是图像放大方法,从而影响后续的处理和输出。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- latent_upscale + - 当‘Input’参数指定潜在放大过程时,使用‘latent_upscale’参数。它很重要,因为它携带了将被放大的潜在表示,影响最终输出的质量和分辨率。 + - Comfy dtype: LATENT + - Python dtype: Any +- image_upscale + - 当‘Input’参数指示图像放大过程时,使用‘image_upscale’参数。它至关重要,因为它包含将被处理以进行放大的图像数据,直接影响输出的视觉增强。 + - Comfy dtype: LATENT + - Python dtype: Any + +# Output types +- LATENT + - ‘LATENT’输出代表了所选放大处理的结果,无论是来自潜在的还是图像放大。它包含了经过指定增强处理的数据,可供进一步使用或分析。 + - Comfy dtype: LATENT + - Python dtype: Any +- STRING + - ‘STRING’输出提供了指向节点帮助文档的URL链接。这对于寻求额外指导或了解节点功能和用法的用户来说特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_HiResFixProcessSwitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': (['latent_upscale', 'image_upscale'],)}, 'optional': {'latent_upscale': ('LATENT',), 'image_upscale': ('LATENT',)}} + RETURN_TYPES = ('LATENT', 'STRING') + RETURN_NAMES = ('LATENT', 'STRING') + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Utils/Process') + + def switch(self, Input, latent_upscale=None, image_upscale=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Process-Nodes#cr-hires-fix-process-switch' + if Input == 'latent_upscale': + return (latent_upscale, show_help) + else: + return (image_upscale, show_help) +``` \ No newline at end of file diff --git a/docs/CR Image Border.md b/docs/CR Image Border.md new file mode 100644 index 0000000..d834f64 --- /dev/null +++ b/docs/CR Image Border.md @@ -0,0 +1,87 @@ +# Documentation +- Class name: CR_ImageBorder +- Category: Comfyroll/Graphics/Layout +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ImageBorder 节点旨在为图像添加装饰性边框,以增强其在各种布局中的视觉效果。它允许自定义边框的厚度和颜色,还可以选择添加轮廓以进行额外强调。在需要专业和精致外观的图像展示图形设计工作流程中,这个节点发挥着关键作用。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它定义了将应用边框的基础视觉内容。输入图像的质量和分辨率直接影响最终输出,使其成为节点执行中的基本元素。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- top_thickness + - top_thickness 参数指定应用于图像顶部边缘的边框厚度。它允许微调边框的外观以满足设计要求,有助于整体图像的美观。 + - Comfy dtype: INT + - Python dtype: int +- bottom_thickness + - bottom_thickness 参数决定图像底部边缘的边框厚度。调整此参数可以帮助实现平衡对称的边框设计,增强图像的视觉和谐。 + - Comfy dtype: INT + - Python dtype: int +- left_thickness + - left_thickness 参数控制图像左侧边框的厚度。在设计边框时,这是一个重要方面,以确保图像在所有边缘上都具有统一和一致的外观。 + - Comfy dtype: INT + - Python dtype: int +- right_thickness + - right_thickness 参数设置图像右侧边框的厚度。它在整体边框设计中发挥作用,确保图像的边缘在视觉上与布局的其余部分保持一致。 + - Comfy dtype: INT + - Python dtype: int +- border_color + - border_color 参数用于定义边框的颜色。它是设置图像边框的色调和风格的关键元素,影响最终图像的整体氛围和呈现。 + - Comfy dtype: COLOR + - Python dtype: str +- outline_thickness + - outline_thickness 参数指定要在图像周围添加的轮廓线厚度。这可以为图像添加深度和重点,使其在组合中更加突出。 + - Comfy dtype: INT + - Python dtype: int +- outline_color + - outline_color 参数决定围绕图像的轮廓线颜色。对于希望与 border_color 和图像本身创建对比或和谐感的设计师来说,这是一个重要选择。 + - Comfy dtype: COLOR + - Python dtype: str +- border_color_hex + - border_color_hex 参数允许使用自定义的十六进制颜色值来设置边框颜色,为设计师提供了更大的灵活性和对所需确切颜色阴影的控制。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- image + - CR_ImageBorder 节点的图像输出是应用了边框和可选轮廓的处理后的图像。它代表了节点操作的最终视觉结果,可供进一步使用或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个到文档页面的 URL 链接,以获取有关使用 CR_ImageBorder 节点的进一步帮助或指导。对于寻求更多信息的用户来说,这是一个有用的资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ImageBorder: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'top_thickness': ('INT', {'default': 0, 'min': 0, 'max': 4096}), 'bottom_thickness': ('INT', {'default': 0, 'min': 0, 'max': 4096}), 'left_thickness': ('INT', {'default': 0, 'min': 0, 'max': 4096}), 'right_thickness': ('INT', {'default': 0, 'min': 0, 'max': 4096}), 'border_color': (COLORS,), 'outline_thickness': ('INT', {'default': 0, 'min': 0, 'max': 1024}), 'outline_color': (COLORS[1:],)}, 'optional': {'border_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image', 'show_help') + FUNCTION = 'make_panel' + CATEGORY = icons.get('Comfyroll/Graphics/Layout') + + def make_panel(self, image, top_thickness, bottom_thickness, left_thickness, right_thickness, border_color, outline_thickness, outline_color, border_color_hex='#000000'): + images = [] + border_color = get_color_values(border_color, border_color_hex, color_mapping) + for img in image: + img = tensor2pil(img) + if outline_thickness > 0: + img = ImageOps.expand(img, outline_thickness, fill=outline_color) + if left_thickness > 0 or right_thickness > 0 or top_thickness > 0 or (bottom_thickness > 0): + img = ImageOps.expand(img, (left_thickness, top_thickness, right_thickness, bottom_thickness), fill=border_color) + images.append(pil2tensor(img)) + images = torch.cat(images, dim=0) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Layout-Nodes#cr-image-border' + return (images, show_help) +``` \ No newline at end of file diff --git a/docs/CR Image Grid Panel.md b/docs/CR Image Grid Panel.md new file mode 100644 index 0000000..3ea6083 --- /dev/null +++ b/docs/CR Image Grid Panel.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: CR_ImageGridPanel +- Category: Comfyroll/Graphics/Layout +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ImageGridPanel是一个设计用来高效创建和组织图像网格的节点。它接受一系列图像并将它们排列成结构化的网格布局,可以用于预览或组合显示等多种用途。该节点提供了边框和轮廓设置的定制选项,以增强网格的视觉吸引力。它特别适用于需要将图像批量处理成单一、连贯网格的工作流程。 + +# Input types +## Required +- images + - ‘images’参数是一系列图像张量,这些图像将被排列成一个网格。此输入至关重要,因为它定义了最终网格的内容。这些图像被处理并组合以形成网格布局。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +## Optional +- border_thickness + - ‘border_thickness’参数指定应用于网格中每张图像周围的边框厚度。它允许定制网格的外观,并可以根据所需的美学进行调整。 + - Comfy dtype: INT + - Python dtype: int +- border_color + - ‘border_color’参数确定围绕每张图像的边框颜色。它是节点定制的重要方面,允许用户将边框颜色与整体设计主题相匹配。 + - Comfy dtype: COLOR + - Python dtype: str +- outline_thickness + - ‘outline_thickness’参数设置每张图像周围轮廓的厚度。这是一个可选特性,可以用来使网格中的图像更加突出。 + - Comfy dtype: INT + - Python dtype: int +- outline_color + - ‘outline_color’参数定义每张图像周围轮廓的颜色。它补充了边框,并增强了网格中每张图像的视觉区分度。 + - Comfy dtype: COLOR + - Python dtype: str +- max_columns + - ‘max_columns’参数指示网格中的最大列数。它是一个关键参数,控制网格的布局并影响图像的分布。 + - Comfy dtype: INT + - Python dtype: int +- border_color_hex + - ‘border_color_hex’参数允许使用自定义的十六进制颜色值来设置边框颜色。它为用户提供了额外的灵活性,允许用户指定可能不在预定义颜色选项中的确切边框颜色。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- image + - ‘image’输出是由输入图像组成的结果网格面板,以结构化布局排列。它代表了节点操作的最终产品,可供进一步使用或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - ‘show_help’输出提供了一个URL链接到文档页面,以获取关于节点使用和功能的额外指导和信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ImageGridPanel: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'border_thickness': ('INT', {'default': 0, 'min': 0, 'max': 1024}), 'border_color': (COLORS,), 'outline_thickness': ('INT', {'default': 0, 'min': 0, 'max': 1024}), 'outline_color': (COLORS[1:],), 'max_columns': ('INT', {'default': 5, 'min': 0, 'max': 256})}, 'optional': {'border_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image', 'show_help') + FUNCTION = 'make_panel' + CATEGORY = icons.get('Comfyroll/Graphics/Layout') + + def make_panel(self, images, border_thickness, border_color, outline_thickness, outline_color, max_columns, border_color_hex='#000000'): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Layout-Nodes#cr-image-grid-panel' + border_color = get_color_values(border_color, border_color_hex, color_mapping) + images = [tensor2pil(image) for image in images] + images = apply_outline_and_border(images, outline_thickness, outline_color, border_thickness, border_color) + combined_image = make_grid_panel(images, max_columns) + image_out = pil2tensor(combined_image) + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Image Input Switch (4 way).md b/docs/CR Image Input Switch (4 way).md new file mode 100644 index 0000000..b3ed6d8 --- /dev/null +++ b/docs/CR Image Input Switch (4 way).md @@ -0,0 +1,71 @@ +# Documentation +- Class name: CR_ImageInputSwitch4way +- Category: Comfyroll/Utils/Logic +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ImageInputSwitch4way 节点旨在根据整数输入条件性地选择图像输入。它通过逻辑开关机制促进图像数据的路由,确保选择并传递适当的图像。在需要动态选择图像且不希望增加额外条件逻辑的情境中,此节点至关重要。 + +# Input types +## Required +- Input + - ‘Input’ 参数至关重要,因为它决定了将选择四个可能的图像输入中的哪一个。它作为一个开关操作,整数值对应于要通过节点路由的图像的索引。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- image1 + - ‘image1’ 参数表示第一个可选图像输入,根据‘Input’参数,可以被节点选择。当‘Input’设置为1时,它在节点的操作中扮演重要角色,成为主要的输出图像。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] +- image2 + - ‘image2’ 参数是节点根据‘Input’值可以选择的第二个可选图像输入。当‘Input’为2时,它变得相关,此时它是节点输出的图像。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] +- image3 + - ‘image3’ 参数是节点选择过程中的第三个可选图像输入。当‘Input’值为3时,它被使用,成为通过节点的选定图像。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] +- image4 + - ‘image4’ 参数是节点可以输出的第四个也是最后一个可选图像输入。仅当‘Input’设置为4时,它才被考虑,在这种情况下,它成为节点的输出图像。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] + +# Output types +- IMAGE + - ‘IMAGE’ 输出参数代表基于输入整数值选择的图像。它是节点操作的主要结果,对于继续图像处理工作流程至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - ‘show_help’ 输出提供了指向节点文档的URL,为用户提供了如何有效使用该节点的指导。它是了解节点功能和目的的有用资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ImageInputSwitch4way: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': ('INT', {'default': 1, 'min': 1, 'max': 4})}, 'optional': {'image1': ('IMAGE',), 'image2': ('IMAGE',), 'image3': ('IMAGE',), 'image4': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Utils/Logic') + + def switch(self, Input, image1=None, image2=None, image3=None, image4=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Logic-Nodes#cr-text-input-switch-4-way' + if Input == 1: + return (image1, show_help) + elif Input == 2: + return (image2, show_help) + elif Input == 3: + return (image3, show_help) + else: + return (image4, show_help) +``` \ No newline at end of file diff --git a/docs/CR Image Input Switch.md b/docs/CR Image Input Switch.md new file mode 100644 index 0000000..3d56223 --- /dev/null +++ b/docs/CR Image Input Switch.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CR_ImageInputSwitch +- Category: Comfyroll/Utils/Logic +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ImageInputSwitch 节点旨在根据单个整数输入有条件地选择两个图像输入之一。它通过评估整数值并返回相应的图像来操作,确保输出与输入选择一致。该节点在需要根据用户输入或其他条件逻辑动态改变图像数据流的场景中特别有用。 + +# Input types +## Required +- Input + - ‘Input’ 参数是一个关键的整数,它决定了将选择哪个图像作为输出。它直接影响节点的决策过程,允许有条件地路由图像数据。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- image1 + - ‘image1’ 参数表示节点可以选择的第一个图像选项。当‘Input’值使得‘image1’是指定的输出时,它扮演着重要的角色。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray +- image2 + - ‘image2’ 参数是节点可选择的第二个图像选项。当‘Input’值指示‘image2’应该是输出图像时,它变得重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray + +# Output types +- IMAGE + - ‘IMAGE’ 输出是基于 ‘Input’ 参数选择的图像。它代表了节点条件逻辑的结果,对工作流中的进一步处理至关重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray +- show_help + - ‘show_help’ 输出提供了指向节点文档的 URL,为用户提供了如何有效使用该节点的指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ImageInputSwitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': ('INT', {'default': 1, 'min': 1, 'max': 2})}, 'optional': {'image1': ('IMAGE',), 'image2': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Utils/Logic') + + def switch(self, Input, image1=None, image2=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Logic-Nodes#cr-image-input-switch' + if Input == 1: + return (image1, show_help) + else: + return (image2, show_help) +``` \ No newline at end of file diff --git a/docs/CR Image List Simple.md b/docs/CR Image List Simple.md new file mode 100644 index 0000000..d6bb250 --- /dev/null +++ b/docs/CR Image List Simple.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: CR_ImageListSimple +- Category: Comfyroll/Animation/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ImageListSimple节点旨在将多个图像输入编译成单一的结构化格式。它通过将多个图像源整合成一份连贯的列表,简化了处理多个图像来源的过程,从而便于后续的图像处理任务。 + +# Input types +## Optional +- image_1 + - 'image_1'参数是可选的图像输入之一,可以提供给节点。它在将图像聚合成列表中发挥作用,有助于最终输出。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] +- image_2 + - 'image_2'参数是节点的另一个可选图像输入。它对于增加图像列表的多样性至关重要,确保了视觉数据的全面收集。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] +- image_3 + - 'image_3'参数用于向节点的处理流程中引入另一个可选图像。它的包含丰富了图像列表,增强了节点的功能。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] +- image_4 + - 'image_4'参数允许包含一个额外的可选图像。它对于扩展可以由节点处理的图像范围具有重要意义。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] +- image_5 + - 'image_5'参数是节点可以接受的最后一个可选图像输入。它确保节点可以处理广泛的图像输入,最大化其多功能性。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] +- image_list_simple + - 'image_list_simple'参数是一个可选输入,允许将预先存在的图像列表输入到节点中。对于希望使用策划好的图像列表而不是单独输入的用户来说,它是必不可少的。 + - Comfy dtype: IMAGE_LIST_SIMPLE + - Python dtype: Union[List[str], List[torch.Tensor]] + +# Output types +- IMAGE_LIST_SIMPLE + - 'IMAGE_LIST_SIMPLE'输出是节点处理后的图像的整合列表。它很重要,因为它构成了进一步图像操作或分析的基础。 + - Comfy dtype: IMAGE_LIST_SIMPLE + - Python dtype: List[torch.Tensor] +- show_help + - 'show_help'输出提供了一个文档的URL链接,以便进一步帮助。对于需要额外指导如何有效使用节点的用户来说,它是有用的。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ImageListSimple: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'image_1': ('IMAGE',), 'image_2': ('IMAGE',), 'image_3': ('IMAGE',), 'image_4': ('IMAGE',), 'image_5': ('IMAGE',), 'image_list_simple': ('IMAGE_LIST_SIMPLE',)}} + RETURN_TYPES = ('IMAGE_LIST_SIMPLE', 'STRING') + RETURN_NAMES = ('IMAGE_LIST_SIMPLE', 'show_help') + FUNCTION = 'image_list_simple' + CATEGORY = icons.get('Comfyroll/Animation/Legacy') + + def image_list_simple(self, image_1=None, image_2=None, image_3=None, image_4=None, image_5=None, image_list_simple=None): + images = list() + if image_list_simple is not None: + images.append((l for l in image_list_simple)) + if image_1 != None: + (images.append(image_1),) + if image_2 != None: + images.append(image_2) + if image_3 != None: + images.append(image_3) + if image_4 != None: + (images.append(image_4),) + if image_5 != None: + (images.append(image_5),) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-image-list-simple' + return (images, show_help) +``` \ No newline at end of file diff --git a/docs/CR Image List.md b/docs/CR Image List.md new file mode 100644 index 0000000..7653884 --- /dev/null +++ b/docs/CR Image List.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: CR_ImageList +- Category: Comfyroll/Animation/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ImageList 节点旨在管理和组织图像列表。它允许用户输入单独的图像及其对应的别名,并将它们组合成单个图像列表。这个节点特别适用于需要一起处理或显示图像集合的应用程序。 + +# Input types +## Optional +- image_1 + - 'image_1' 参数表示可以添加到图像列表中的第一个图像。它在节点的操作中起着关键作用,通过贡献给节点管理的最终图像集合。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] +- alias1 + - 'alias1' 参数是一个可选的字符串,可用于为 'image_1' 提供别名。这对于以更易读的格式引用图像非常有用。 + - Comfy dtype: STRING + - Python dtype: str +- image_list + - 'image_list' 参数是一个包含别名和图像的元组列表。这个参数至关重要,因为它允许节点处理一个预先存在的图像和别名集合。 + - Comfy dtype: image_LIST + - Python dtype: List[Tuple[str, Union[str, torch.Tensor]]] + +# Output types +- IMAGE_LIST + - 'IMAGE_LIST' 输出是图像别名与其对应图像配对的列表。它代表了节点处理的所有输入图像和别名的集合。 + - Comfy dtype: image_LIST + - Python dtype: List[Tuple[str, Union[str, torch.Tensor]]] +- show_help + - 'show_help' 输出提供了一个链接到文档的URL,以获得更多帮助。这对于寻求如何有效使用节点的更多信息的用户特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ImageList: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'image_1': ('IMAGE',), 'alias1': ('STRING', {'multiline': False, 'default': ''}), 'image_2': ('IMAGE',), 'alias2': ('STRING', {'multiline': False, 'default': ''}), 'image_3': ('IMAGE',), 'alias3': ('STRING', {'multiline': False, 'default': ''}), 'image_4': ('IMAGE',), 'alias4': ('STRING', {'multiline': False, 'default': ''}), 'image_5': ('IMAGE',), 'alias5': ('STRING', {'multiline': False, 'default': ''}), 'image_list': ('image_LIST',)}} + RETURN_TYPES = ('IMAGE_LIST', 'STRING') + RETURN_NAMES = ('IMAGE_LIST', 'show_help') + FUNCTION = 'image_list' + CATEGORY = icons.get('Comfyroll/Animation/Legacy') + + def image_list(self, image_1=None, alias1=None, image_2=None, alias2=None, image_3=None, alias3=None, image_4=None, alias4=None, image_5=None, alias5=None, image_list=None): + images = list() + if image_list is not None: + image_tup = [(alias1, image_1)] + images.extend([l for l in image_list]) + if image_1 != None: + (images.extend([(alias1, image_1)]),) + if image_2 != None: + (images.extend([(alias2, image_2)]),) + if image_3 != None: + (images.extend([(alias3, image_3)]),) + if image_4 != None: + (images.extend([(alias4, image_4)]),) + if image_5 != None: + (images.extend([(alias5, image_5)]),) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-image-list' + return (images, show_help) +``` \ No newline at end of file diff --git a/docs/CR Image Output.md b/docs/CR Image Output.md new file mode 100644 index 0000000..980403e --- /dev/null +++ b/docs/CR Image Output.md @@ -0,0 +1,140 @@ +# Documentation +- Class name: CR_ImageOutput +- Category: Comfyroll/Essential/Core +- Output node: True +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ImageOutput 是一个用于管理图像数据输出的节点,提供保存或预览图像的功能,并允许自定义文件命名和格式。它在图像处理工作流的最后阶段扮演着关键角色,确保结果易于访问且组织良好。 + +# Input types +## Required +- images + - 'image' 参数至关重要,因为它定义了节点将处理的输入图像数据。它通过决定将保存或预览的内容来影响节点的执行。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- output_type + - “output_type”参数决定节点是将图像保存到磁盘还是预览它们。它很重要,因为它将节点的主要功能引向任一输出方法。 + - Comfy dtype: COMBO['Preview', 'Save', 'UI (no batch)'] + - Python dtype: str +- file_format + - “file_format”参数指定了图像将被保存的格式,影响输出文件的质量和兼容性。 + - Comfy dtype: COMBO['png', 'jpg', 'webp', 'tif'] + - Python dtype: str +## Optional +- filename_prefix + - “filename_prefix”参数设置输出文件的基本名称,这对于组织和识别保存的图像很重要。 + - Comfy dtype: STRING + - Python dtype: str +- prefix_presets + - “prefix_presets”允许在文件名前添加基于日期的前缀,这对于按时间顺序排序和归档很有用。 + - Comfy dtype: COMBO[None, 'yyyyMMdd'] + - Python dtype: str +- trigger + - 当设置为 True 时,“trigger”参数在工作流中启动一个动作或信号,可能触发后续流程。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- prompt + - “prompt”参数用于存储与图像相关的描述或注释,这对于元数据目的很有帮助。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - “extra_pnginfo”参数允许在PNG文件中嵌入额外的元数据,增强与图像相关的信息。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, Any] + +# Output types +- ui + - “ui”输出包含带有元数据的图像对象列表,这对于为用户界面提供已处理图像的必要视觉和上下文信息很重要。 + - Comfy dtype: COMBO[{'images': List[Dict[str, Any]]}] + - Python dtype: Dict[str, Any] +- result + - “result”输出表示节点操作的完成状态,并在需要时提供用于进一步帮助的 URL。 + - Comfy dtype: COMBO[Tuple[BOOLEAN, str]] + - Python dtype: Tuple[bool, str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ImageOutput: + + def __init__(self): + self.output_dir = folder_paths.get_output_directory() + self.type = 'output' + + @classmethod + def INPUT_TYPES(cls): + presets = ['None', 'yyyyMMdd'] + return {'required': {'images': ('IMAGE',), 'output_type': (['Preview', 'Save', 'UI (no batch)'],), 'filename_prefix': ('STRING', {'default': 'CR'}), 'prefix_presets': (presets,), 'file_format': (['png', 'jpg', 'webp', 'tif'],)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}, 'optional': {'trigger': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('BOOLEAN',) + RETURN_NAMES = ('trigger',) + FUNCTION = 'save_images' + OUTPUT_NODE = True + CATEGORY = icons.get('Comfyroll/Essential/Core') + + def save_images(self, images, file_format, prefix_presets, filename_prefix='CR', trigger=False, output_type='Preview', prompt=None, extra_pnginfo=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Core-Nodes#cr-image-output' + + def map_filename(filename): + prefix_len = len(os.path.basename(filename_prefix)) + prefix = filename[:prefix_len + 1] + try: + digits = int(filename[prefix_len + 1:].split('_')[0]) + except: + digits = 0 + return (digits, prefix) + if output_type == 'Save': + self.output_dir = folder_paths.get_output_directory() + self.type = 'output' + elif output_type == 'Preview': + self.output_dir = folder_paths.get_temp_directory() + self.type = 'temp' + date_formats = {'yyyyMMdd': lambda d: '{}{:02d}{:02d}'.format(str(d.year), d.month, d.day)} + current_datetime = datetime.datetime.now() + for (format_key, format_lambda) in date_formats.items(): + preset_prefix = f'{format_lambda(current_datetime)}' + if prefix_presets != 'None': + filename_prefix = filename_prefix + '_' + preset_prefix + if filename_prefix[0] == '_': + filename_prefix = filename_prefix[1:] + subfolder = os.path.dirname(os.path.normpath(filename_prefix)) + filename = os.path.basename(os.path.normpath(filename_prefix)) + full_output_folder = os.path.join(self.output_dir, subfolder) + if os.path.commonpath((self.output_dir, os.path.abspath(full_output_folder))) != self.output_dir: + return {} + try: + counter = max(filter(lambda a: a[1][:-1] == filename and a[1][-1] == '_', map(map_filename, os.listdir(full_output_folder))))[0] + 1 + except ValueError: + counter = 1 + except FileNotFoundError: + os.makedirs(full_output_folder, exist_ok=True) + counter = 1 + if output_type == 'UI (no batch)': + results = [] + for tensor in images: + array = 255.0 * tensor.cpu().numpy() + image = Image.fromarray(np.clip(array, 0, 255).astype(np.uint8)) + server = PromptServer.instance + server.send_sync(BinaryEventTypes.UNENCODED_PREVIEW_IMAGE, ['PNG', image, None], server.client_id) + results.append({'source': 'websocket', 'content-type': 'image/png', 'type': 'output'}) + return {'ui': {'images': results}} + else: + results = list() + for image in images: + i = 255.0 * image.cpu().numpy() + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) + metadata = PngInfo() + if prompt is not None: + metadata.add_text('prompt', json.dumps(prompt)) + if extra_pnginfo is not None: + for x in extra_pnginfo: + metadata.add_text(x, json.dumps(extra_pnginfo[x])) + file_name = f'{filename}_{counter:05}_.{file_format}' + img_params = {'png': {'compress_level': 4}, 'webp': {'method': 6, 'lossless': False, 'quality': 80}, 'jpg': {'format': 'JPEG'}, 'tif': {'format': 'TIFF'}} + resolved_image_path = os.path.join(full_output_folder, file_name) + img.save(resolved_image_path, **img_params[file_format], pnginfo=metadata) + results.append({'filename': file_name, 'subfolder': subfolder, 'type': self.type}) + counter += 1 + return {'ui': {'images': results}, 'result': (trigger, show_help)} +``` \ No newline at end of file diff --git a/docs/CR Image Panel.md b/docs/CR Image Panel.md new file mode 100644 index 0000000..f4a2c99 --- /dev/null +++ b/docs/CR Image Panel.md @@ -0,0 +1,93 @@ +# Documentation +- Class name: CR_ImagePanel +- Category: Comfyroll/Graphics/Layout +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ImagePanel节点用于将多个图像按照指定的布局方向组合成一个图像面板。它支持为图像添加边框和轮廓,增强视觉效果,并允许自定义颜色。适用于创建图像网格或将多个预览图像组织成单一图像条带,广泛应用于图像展示和布局设计。 + +# Input types +## Required +- image_1 + - 第一个要组合的图像,它是构建图像面板的基础。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- border_thickness + - 边框的厚度,用于定义图像边框的宽度,增强图像边缘的视觉效果。 + - Comfy dtype: INT + - Python dtype: int +- border_color + - 边框的颜色,允许用户自定义边框颜色,以适应不同的设计需求。 + - Comfy dtype: COLOR + - Python dtype: str +- outline_thickness + - 轮廓的厚度,定义了图像轮廓的宽度,用于增强图像的可视边界。 + - Comfy dtype: INT + - Python dtype: int +- outline_color + - 轮廓的颜色,用户可以自定义轮廓颜色以匹配设计主题。 + - Comfy dtype: COLOR + - Python dtype: str +- layout_direction + - 布局方向,决定了图像是水平还是垂直组合,影响最终图像面板的布局结构。 + - Comfy dtype: COMBO[horizontal, vertical] + - Python dtype: str +## Optional +- image_2 + - 第二个可选图像,用于在图像面板中与第一个图像一起展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image_3 + - 第三个可选图像,用于在图像面板中与前两个图像一起展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image_4 + - 第四个可选图像,用于在图像面板中与前三个图像一起展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- border_color_hex + - 边框颜色的十六进制值,提供另一种方式来精确指定边框颜色。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- image + - 组合后的图像面板,包含了所有输入图像按照指定的布局方向和样式组合而成的最终图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - 提供帮助文档的链接,用户可以通过此链接获取关于如何使用该节点的更多信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ImagePanel: + + @classmethod + def INPUT_TYPES(s): + directions = ['horizontal', 'vertical'] + return {'required': {'image_1': ('IMAGE',), 'border_thickness': ('INT', {'default': 0, 'min': 0, 'max': 1024}), 'border_color': (COLORS,), 'outline_thickness': ('INT', {'default': 0, 'min': 0, 'max': 1024}), 'outline_color': (COLORS[1:],), 'layout_direction': (directions,)}, 'optional': {'image_2': ('IMAGE',), 'image_3': ('IMAGE',), 'image_4': ('IMAGE',), 'border_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image', 'show_help') + FUNCTION = 'make_panel' + CATEGORY = icons.get('Comfyroll/Graphics/Layout') + + def make_panel(self, image_1, border_thickness, border_color, outline_thickness, outline_color, layout_direction, image_2=None, image_3=None, image_4=None, border_color_hex='#000000'): + border_color = get_color_values(border_color, border_color_hex, color_mapping) + images = [] + images.append(tensor2pil(image_1)) + if image_2 is not None: + images.append(tensor2pil(image_2)) + if image_3 is not None: + images.append(tensor2pil(image_3)) + if image_4 is not None: + images.append(tensor2pil(image_4)) + images = apply_outline_and_border(images, outline_thickness, outline_color, border_thickness, border_color) + combined_image = combine_images(images, layout_direction) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Layout-Nodes#cr-image-panel' + return (pil2tensor(combined_image), show_help) +``` \ No newline at end of file diff --git a/docs/CR Image Pipe Edit.md b/docs/CR Image Pipe Edit.md new file mode 100644 index 0000000..bf13ded --- /dev/null +++ b/docs/CR Image Pipe Edit.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: CR_ImagePipeEdit +- Category: Comfyroll/Pipe/Image +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ImagePipeEdit 节点旨在管道结构内便于编辑和增强图像数据。它允许用户修改图像的属性,如宽度、高度和放大因子,确保输出图像满足所需的规格。该节点在图像处理工作流中扮演关键角色,允许微调视觉内容,而不会破坏整体管道的完整性。 + +# Input types +## Required +- pipe + - ‘pipe’参数是必需的,因为它代表了将由节点编辑的图像管道。这是一个关键输入,它决定了所有后续图像修改和处理的起点。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple[str, int, int, float] +## Optional +- image + - 可选的‘image’参数允许用户替换管道中的当前图像。当需要特定图像内容进行进一步处理或分析时,它特别有用。 + - Comfy dtype: IMAGE + - Python dtype: str +- width + - ‘width’参数用于指定图像的新宽度。它是一个可选输入,可以根据不同显示或输出介质的要求进行调整。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’参数决定了图像的新高度。与宽度类似,它是可选的,并且可以设置以实现所需的纵横比或适应特定的展示需求。 + - Comfy dtype: INT + - Python dtype: int +- upscale_factor + - ‘upscale_factor’参数是可选的,定义了图像放大的缩放因子。对于在不损害原始分辨率的情况下增强图像质量,它尤其重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- pipe + - ‘pipe’输出代表了修改后的图像管道,包括更新后的图像及其属性,如宽度、高度和放大因子。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple[str, int, int, float] +- show_help + - ‘show_help’输出提供了一个链接到文档页面的URL,以获取有关节点使用的进一步帮助或信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ImagePipeEdit: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',)}, 'optional': {'image': ('IMAGE',), 'width': ('INT', {'default': 512, 'min': 64, 'max': 2048, 'forceInput': True}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 2048, 'forceInput': True}), 'upscale_factor': ('FLOAT', {'default': 1, 'min': 1, 'max': 2000, 'forceInput': True})}} + RETURN_TYPES = ('PIPE_LINE', 'STRING') + RETURN_NAMES = ('pipe', 'show_help') + FUNCTION = 'pipe_edit' + CATEGORY = icons.get('Comfyroll/Pipe/Image') + + def pipe_edit(self, pipe, image=None, width=None, height=None, upscale_factor=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pipe-Nodes#cr-image-pipe-edit' + (new_image, new_width, new_height, new_upscale_factor) = pipe + if image is not None: + new_image = image + if width is not None: + new_width = width + if height is not None: + new_height = height + if upscale_factor is not None: + new_upscale_factor = upscale_factor + pipe = (new_image, new_width, new_height, new_upscale_factor) + return (pipe, show_help) +``` \ No newline at end of file diff --git a/docs/CR Image Pipe In.md b/docs/CR Image Pipe In.md new file mode 100644 index 0000000..632fe1a --- /dev/null +++ b/docs/CR Image Pipe In.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: CR_ImagePipeIn +- Category: Comfyroll/Pipe/Image +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ImagePipeIn 节点旨在促进图像输入到数据管道的过程。它在准备图像数据以供后续处理阶段使用方面扮演着关键角色,确保图像根据指定的参数正确格式化和缩放。 + +# Input types +## Optional +- image + - 图像参数对于节点至关重要,因为它定义了将被处理的输入图像。这是节点操作的主要数据源,影响后续步骤的执行方式。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, bytes, Image.Image] +- width + - 宽度参数指定了处理后图像的期望宽度。它对于控制输出图像的尺寸并在也指定高度时保持纵横比很重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置处理后图像的期望高度。它与宽度参数一起工作,以确定图像的最终大小。 + - Comfy dtype: INT + - Python dtype: int +- upscale_factor + - upscale_factor 参数用于提高图像的分辨率。在放大过程中,它对于提高图像质量而不丢失重要细节具有重要意义。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- pipe + - pipe 输出是一个结构化数据类型,它封装了处理后的图像及其相关参数。它作为图像数据传递到管道下一阶段的通道。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple[Any, int, int, float] +- show_help + - show_help 输出提供了一个文档的URL链接,以供进一步帮助。对于寻求有关节点功能和用法的更多信息的用户来说,它特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ImagePipeIn: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}, 'optional': {'image': ('IMAGE',), 'width': ('INT', {'default': 512, 'min': 64, 'max': 2048}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 2048}), 'upscale_factor': ('FLOAT', {'default': 1, 'min': 1, 'max': 2000})}} + RETURN_TYPES = ('PIPE_LINE', 'STRING') + RETURN_NAMES = ('pipe', 'show_help') + FUNCTION = 'pipe_in' + CATEGORY = icons.get('Comfyroll/Pipe/Image') + + def pipe_in(self, image=0, width=0, height=0, upscale_factor=0): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pipe-Nodes#cr-image-pipe-in' + pipe_line = (image, width, height, upscale_factor) + return (pipe_line, show_help) +``` \ No newline at end of file diff --git a/docs/CR Image Pipe Out.md b/docs/CR Image Pipe Out.md new file mode 100644 index 0000000..392cd0d --- /dev/null +++ b/docs/CR Image Pipe Out.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: CR_ImagePipeOut +- Category: Comfyroll/Pipe/Image +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ImagePipeOut节点旨在促进流水线架构中图像数据的输出过程。它在图像处理工作流的最后阶段扮演着关键角色,确保图像数据正确地从系统中流出。该节点擅长处理图像数据从处理流水线到输出接口的过渡,为图像数据传播提供了一个无缝集成点。 + +# Input types +## Required +- pipe + - ‘pipe’参数对于CR_ImagePipeOut节点至关重要,因为它代表了携带要输出的图像数据的流水线。正是通过这个参数,节点接收图像信息,然后将其处理为输出。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple[str, int, int, float] + +# Output types +- pipe + - ‘pipe’输出参数表示图像数据处理完毕并准备好输出后流水线的延续。它维护了数据流的完整性,并确保后续流程可以顺利进行。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple[str, int, int, float] +- image + - ‘image’输出参数是由CR_ImagePipeOut节点输出的处理后的图像。它代表了图像处理流水线的成果,并且是呈现给最终用户或后续系统最终产品。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- width + - ‘width’输出参数提供了输出图像的宽度,以像素为单位。这个信息对于理解图像的尺寸以及任何进一步的图像操作或显示目的至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’输出参数指示输出图像的高度,以像素为单位。它与宽度一起定义了图像的整体大小,对于正确的图像展示至关重要。 + - Comfy dtype: INT + - Python dtype: int +- upscale_factor + - ‘upscale_factor’输出参数代表了在处理过程中应用于图像的缩放因子。它是图像质量评估的重要指标,并且可以影响后续图像处理决策。 + - Comfy dtype: FLOAT + - Python dtype: float +- show_help + - ‘show_help’输出参数提供了与CR_ImagePipeOut节点相关联的文档或帮助页面的URL链接。它作为用户寻求有关使用该节点的更多信息或帮助的快速参考。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ImagePipeOut: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',)}} + RETURN_TYPES = ('PIPE_LINE', 'IMAGE', 'INT', 'INT', 'FLOAT', 'STRING') + RETURN_NAMES = ('pipe', 'image', 'width', 'height', 'upscale_factor', 'show_help') + FUNCTION = 'pipe_out' + CATEGORY = icons.get('Comfyroll/Pipe/Image') + + def pipe_out(self, pipe): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pipe-Nodes#cr-image-pipe-out' + (image, width, height, upscale_factor) = pipe + return (pipe, image, width, height, upscale_factor, show_help) +``` \ No newline at end of file diff --git a/docs/CR Image Size.md b/docs/CR Image Size.md new file mode 100644 index 0000000..f5e78eb --- /dev/null +++ b/docs/CR Image Size.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: CR_ImageSize +- Category: Comfyroll/Essential/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ImageSize 节点旨在调整图像的尺寸。它提供了指定图像宽度和高度的功能,并通过可调节的因子允许进行放大。在需要尺寸调整的图像处理工作流程中,此节点至关重要,确保图像满足进一步处理或显示所需的尺寸。 + +# Input types +## Required +- width + - ‘width’参数对于定义图像的期望宽度至关重要。它在确定处理后图像的最终尺寸中起着关键作用。‘width’设置直接影响图像的宽高比和整体外观。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’参数用于设置图像的垂直尺寸。它是控制图像输出大小的关键因素,确保其符合特定的要求或限制。‘height’值对于保持图像内容的完整性具有重要意义。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- upscale_factor + - ‘upscale_factor’参数是可选的,用于增加图像的大小。它是一个乘数,可以按比例放大原始尺寸,允许更高的分辨率输出。当增强图像细节或为更大的显示器准备图像时,这个因子特别有用。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- Width + - ‘Width’输出反映了应用节点调整大小功能后图像的处理宽度。对于依赖图像确切尺寸的下游流程来说,它是重要的。 + - Comfy dtype: INT + - Python dtype: int +- Height + - ‘Height’输出提供了图像的处理高度,这对于保持预期的宽高比和确保图像适合指定的显示区域至关重要。 + - Comfy dtype: INT + - Python dtype: int +- upscale_factor + - ‘upscale_factor’输出是应用于图像的缩放因子。它表明原始尺寸增加了多少,这对于质量评估或进一步的图像操作可能很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- show_help + - ‘show_help’输出是指向节点使用说明页面的 URL 链接。对于寻求如何有效使用节点的更多信息的用户来说,它特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ImageSize: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 64, 'max': 2048}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 2048}), 'upscale_factor': ('FLOAT', {'default': 1, 'min': 1, 'max': 2000})}} + RETURN_TYPES = ('INT', 'INT', 'FLOAT', 'STRING') + RETURN_NAMES = ('Width', 'Height', 'upscale_factor', 'show_help') + FUNCTION = 'ImageSize' + CATEGORY = icons.get('Comfyroll/Essential/Legacy') + + def ImageSize(self, width, height, upscale_factor): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Legacy-Nodes#cr-image-size' + return (width, height, upscale_factor, show_help) +``` \ No newline at end of file diff --git a/docs/CR Img2Img Process Switch.md b/docs/CR Img2Img Process Switch.md new file mode 100644 index 0000000..e305c17 --- /dev/null +++ b/docs/CR Img2Img Process Switch.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CR_Img2ImgProcessSwitch +- Category: Comfyroll/Utils/Process +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_Img2ImgProcessSwitch 节点在 ComfyUI 工作流中充当决策组件。它旨在根据输入类型智能地路由图像数据的处理,无论是文本到图像的转换还是图像到图像的转换。此节点对于简化图像处理流程至关重要,确保将适当的处理方法应用于输入数据以获得最佳结果。 + +# Input types +## Required +- Input + - ‘Input’ 参数至关重要,因为它决定了工作流中图像处理的路径。它指示节点将执行文本到图像的转换还是图像到图像的转换,从而影响整个处理序列。 + - Comfy dtype: COMBO['txt2img', 'img2img'] + - Python dtype: str +## Optional +- txt2img + - 当‘Input’参数设置为‘txt2img’时,使用‘txt2img’参数。它表示文本到图像过程的潜在表示,这对于进行转换至关重要。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- img2img + - 当‘Input’参数设置为‘img2img’时,‘img2img’参数变得相关。它保存了图像到图像转换过程所需的潜在数据。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Output types +- LATENT + - ‘LATENT’输出包含处理后的潜在数据,这是基于输入选择的文本到图像或图像到图像转换的结果。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- show_help + - ‘show_help’输出提供了一个 URL 到文档,以获取有关如何有效使用该节点的进一步帮助或指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_Img2ImgProcessSwitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': (['txt2img', 'img2img'],)}, 'optional': {'txt2img': ('LATENT',), 'img2img': ('LATENT',)}} + RETURN_TYPES = ('LATENT', 'STRING') + RETURN_NAMES = ('LATENT', 'show_help') + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Utils/Process') + + def switch(self, Input, txt2img=None, img2img=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Process-Nodes#cr-img2img-process-switch' + if Input == 'txt2img': + return (txt2img, show_help) + else: + return (img2img, show_help) +``` \ No newline at end of file diff --git a/docs/CR Increment Float.md b/docs/CR Increment Float.md new file mode 100644 index 0000000..4021e6c --- /dev/null +++ b/docs/CR Increment Float.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: CR_IncrementFloat +- Category: Comfyroll/Animation/Interpolate +- Output node: True +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_IncrementFloat 是一个设计用来在指定的持续时间内逐步调整浮点数值的节点。它在动画时间轴内的当前帧基础上,平滑地过渡从一个起始值到一个递增的值,促进了动态和基于时间的动画的创建。 + +# Input types +## Required +- start_value + - 增量开始的初始值。它作为节点操作的参考点,影响动画序列的起始点。 + - Comfy dtype: FLOAT + - Python dtype: float +- step + - 增量步长值,定义了每个帧浮点数的变化。它在确定动画中增加或减少的速率方面至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_frame + - 增量过程开始的帧号。它决定了动画增量变化开始的时间。 + - Comfy dtype: INT + - Python dtype: int +- frame_duration + - 增量发生的总帧数。它设置了增量动画效果的持续时间。 + - Comfy dtype: INT + - Python dtype: int +- current_frame + - 动画时间轴中的当前帧。它用于根据帧的进展计算增量的当前值。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- FLOAT + - 在当前帧的基础上应用增量逻辑后得到的递增浮点数值的结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- show_help + - 指向节点文档的URL链接,以获取有关其使用的进一步帮助和信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_IncrementFloat: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'start_value': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 0.001}), 'step': ('FLOAT', {'default': 0.1, 'min': -9999.0, 'max': 9999.0, 'step': 0.001}), 'start_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'frame_duration': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('FLOAT', 'STRING') + RETURN_NAMES = ('FLOAT', 'show_help') + OUTPUT_NODE = True + FUNCTION = 'increment' + CATEGORY = icons.get('Comfyroll/Animation/Interpolate') + + def increment(self, start_value, step, start_frame, frame_duration, current_frame): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Interpolation-Nodes#cr-increment-float' + if current_frame < start_frame: + return (start_value, show_help) + current_value = start_value + (current_frame - start_frame) * step + if current_frame <= start_frame + frame_duration: + current_value += step + return (current_value, show_help) + return (current_value, show_help) +``` \ No newline at end of file diff --git a/docs/CR Increment Integer.md b/docs/CR Increment Integer.md new file mode 100644 index 0000000..089fc80 --- /dev/null +++ b/docs/CR Increment Integer.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: CR_IncrementInteger +- Category: Comfyroll/Animation/Interpolate +- Output node: True +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_IncrementInteger 节点旨在在指定的帧持续时间内从一个给定的帧开始递增一个整数值。它特别适用于创建动画,其中数值需要随时间逐步增加。 + +# Input types +## Required +- start_value + - start_value 参数定义了递增开始的初始整数值。它对于设置动画序列的起始点至关重要。 + - Comfy dtype: INT + - Python dtype: int +- step + - step 参数指定了每个帧start_value递增的量。它决定了整个动画中整数值的变化速率。 + - Comfy dtype: INT + - Python dtype: int +- start_frame + - start_frame 参数指示递增开始的帧号。它对于定时动画的开始至关重要。 + - Comfy dtype: INT + - Python dtype: int +- frame_duration + - frame_duration 参数设置了递增发生的帧数。它决定了动画序列的长度。 + - Comfy dtype: INT + - Python dtype: int +- current_frame + - current_frame 参数代表动画中的当前帧号。它用于根据帧的进展计算整数值的当前值。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- INT + - INT 输出提供了递增后的当前整数值,反映了当前帧动画的进度。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - show_help 输出是一个包含指向节点文档URL的字符串,提供有关其用法的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_IncrementInteger: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'start_value': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'step': ('INT', {'default': 1.0, 'min': -9999.0, 'max': 9999.0, 'step': 1.0}), 'start_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'frame_duration': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('INT', 'STRING') + RETURN_NAMES = ('INT', 'show_help') + OUTPUT_NODE = True + FUNCTION = 'increment' + CATEGORY = icons.get('Comfyroll/Animation/Interpolate') + + def increment(self, start_value, step, start_frame, frame_duration, current_frame): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Interpolation-Nodes#cr-increment-integer' + if current_frame < start_frame: + return (start_value, show_help) + current_value = start_value + (current_frame - start_frame) * step + if current_frame <= start_frame + frame_duration: + current_value += step + return (current_value, show_help) + return (current_value, show_help) +``` \ No newline at end of file diff --git a/docs/CR Index Increment.md b/docs/CR Index Increment.md new file mode 100644 index 0000000..07fb09c --- /dev/null +++ b/docs/CR Index Increment.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: CR_IncrementIndex +- Category: Comfyroll/Utils/Index +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_IncrementIndex 节点旨在执行数据处理和迭代任务中的一个简单但关键的操作。它接受一个初始索引和一个间隔值,然后将索引按指定的间隔增加。此功能对于浏览列表、数组或任何顺序数据结构的位置至关重要。该节点还提供了一个链接到文档的链接,以便用户在需要时可以获取更多指导。 + +# Input types +## Required +- index + - “index”参数是增量操作的起始点。它之所以重要,是因为它决定了增量开始的位置。此参数对于确保后续操作中正确的序列顺序和索引至关重要。 + - Comfy dtype: INT + - Python dtype: int +- interval + - “interval”参数定义了索引将增加的步长大小。它之所以重要,是因为它决定了增量值之间的间距,影响数字序列的生成方式。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- index + - “index”输出反映了通过间隔增加原始索引后的新位置。它对于维护通过数据序列的正确进展至关重要。 + - Comfy dtype: INT + - Python dtype: int +- interval + - “interval”输出与输入间隔相同,表示用于增量的步长大小。它可以在需要间隔值的进一步操作中使用。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - “show_help”输出提供了指向节点文档的URL链接,为用户提供了更多详细信息和如何有效使用该节点的指导的直接参考。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_IncrementIndex: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'index': ('INT', {'default': 1, 'min': -10000, 'max': 10000, 'forceInput': True}), 'interval': ('INT', {'default': 1, 'min': -10000, 'max': 10000})}} + RETURN_TYPES = ('INT', 'INT', 'STRING') + RETURN_NAMES = ('index', 'interval', 'show_help') + FUNCTION = 'increment' + CATEGORY = icons.get('Comfyroll/Utils/Index') + + def increment(self, index, interval): + index += interval + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Index-Nodes#cr-index-increment' + return (index, show_help) +``` \ No newline at end of file diff --git a/docs/CR Index Multiply.md b/docs/CR Index Multiply.md new file mode 100644 index 0000000..7eb6111 --- /dev/null +++ b/docs/CR Index Multiply.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: CR_MultiplyIndex +- Category: Comfyroll/Utils/Index +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_MultiplyIndex节点旨在对索引值进行乘法操作,通过给定的因子进行计算。这是一个实用工具节点,它增强了工作流程中索引操作的功能,提供了一种直接的方法来按需扩展或调整索引值。 + +# Input types +## Required +- index + - ‘index’参数是将乘以‘factor’的基数。它在确定节点的最终输出中起着关键作用,因为它是乘法操作的起点。 + - Comfy dtype: INT + - Python dtype: int +- factor + - ‘factor’参数是将应用于‘index’的乘数。它对节点的操作至关重要,因为它决定了乘法对索引值的影响程度。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- index + - ‘index’输出代表了输入‘index’和‘factor’之间乘法操作的结果。它表示乘法过程后新的缩放索引值。 + - Comfy dtype: INT + - Python dtype: int +- factor + - ‘factor’输出是在乘法操作中使用的乘数。它被包含在输出中,以保持与输入参数的一致性,并提供对执行操作的透明度。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - ‘show_help’输出提供了一个URL链接到文档,以获取有关节点使用情况的额外指导或帮助。对于寻求有关节点功能更多信息的用户来说,这是一个有用的资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_MultiplyIndex: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'index': ('INT', {'default': 1, 'min': 0, 'max': 10000, 'forceInput': True}), 'factor': ('INT', {'default': 1, 'min': 0, 'max': 10000})}} + RETURN_TYPES = ('INT', 'INT', 'STRING') + RETURN_NAMES = ('index', 'factor', 'show_help') + FUNCTION = 'multiply' + CATEGORY = icons.get('Comfyroll/Utils/Index') + + def multiply(self, index, factor): + index = index * factor + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Index-Nodes#cr-index-multiply' + return (index, factor, show_help) +``` \ No newline at end of file diff --git a/docs/CR Index Reset.md b/docs/CR Index Reset.md new file mode 100644 index 0000000..80f1723 --- /dev/null +++ b/docs/CR Index Reset.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: CR_IndexReset +- Category: Comfyroll/Utils/Index +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_IndexReset 节点旨在将给定的索引重置为指定的值,确保系统内索引操作的连续性和正确性。它通过提供一种直接的机制来重新初始化索引计数器,在维护数据序列的完整性中发挥着关键作用。 + +# Input types +## Required +- index + - ‘index’参数对于识别需要在数据集或操作中重置的特定位置或序列号至关重要。它通过确定将哪个索引重新分配给‘reset_to’值,直接影响节点的执行。 + - Comfy dtype: INT + - Python dtype: int +- reset_to + - ‘reset_to’参数定义了重置操作后索引的新起始点。它对于设置‘index’在重置后将被分配到的正确初始值至关重要,从而影响系统随后的行为。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- index + - ‘index’输出反映了重置操作后更新的索引值,表示数据集或操作中的新位置或序列号。 + - Comfy dtype: INT + - Python dtype: int +- reset_to + - ‘reset_to’输出是索引被重置到的值,指示了系统内索引的新初始点。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - ‘show_help’输出提供了一个URL链接到文档,以获取有关节点操作的进一步帮助或信息。这对于寻求如何有效使用节点的额外指导的用户来说尤其有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_IndexReset: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'index': ('INT', {'default': 1, 'min': 0, 'max': 10000, 'forceInput': True}), 'reset_to': ('INT', {'default': 1, 'min': 0, 'max': 10000})}} + RETURN_TYPES = ('INT', 'INT', 'STRING') + RETURN_NAMES = ('index', 'reset_to', 'show_help') + FUNCTION = 'reset' + CATEGORY = icons.get('Comfyroll/Utils/Index') + + def reset(self, index, reset_to): + index = reset_to + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Index-Nodes#cr-index-reset' + return (index, reset_to, show_help) +``` \ No newline at end of file diff --git a/docs/CR Index.md b/docs/CR Index.md new file mode 100644 index 0000000..a771e09 --- /dev/null +++ b/docs/CR Index.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: CR_Index +- Category: Comfyroll/Utils/Index +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_Index节点旨在从给定数据集中管理和检索特定索引。它提供高效索引大型数据集的功能,满足各种数据操作和分析任务的需求。该节点强调简单性和灵活性,确保用户可以轻松地将其集成到他们的工作流程中,实现流程化操作。 + +# Input types +## Required +- index + - ‘index’参数对于指定节点将从中检索信息的数据集内的位置至关重要。它通过确定将访问的确切数据点直接影响节点的输出。此参数对于工作流内的数据选择和过滤过程至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- print_to_console + - ‘print_to_console’参数允许用户切换控制台输出。当设置为‘Yes’时,它使节点能够将当前索引值打印到控制台,在执行期间提供实时反馈。这个特性对于调试和监控数据索引操作的进度特别有用。 + - Comfy dtype: COMBO['Yes', 'No'] + - Python dtype: str + +# Output types +- INT + - 'INT'输出提供了从数据集中检索到的索引值,可以进一步用于下游流程。这个输出很重要,因为它为后续的数据操作和分析奠定了基础,确保了工作流的完整性和连续性。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - 'show_help'输出提供了指向节点文档的URL链接,使用户能够访问有关如何有效使用该节点的额外信息和指导。这对于新用户或当需要进一步澄清节点功能时特别有益。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_Index: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'index': ('INT', {'default': 1, 'min': 0, 'max': 10000}), 'print_to_console': (['Yes', 'No'],)}} + RETURN_TYPES = ('INT', 'STRING') + RETURN_NAMES = ('INT', 'show_help') + FUNCTION = 'index' + CATEGORY = icons.get('Comfyroll/Utils/Index') + + def index(self, index, print_to_console): + if print_to_console == 'Yes': + print(f'[Info] CR Index:{index}') + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Index-Nodes#cr-index' + return (index, show_help) +``` \ No newline at end of file diff --git a/docs/CR Integer Multiple.md b/docs/CR Integer Multiple.md new file mode 100644 index 0000000..cd29451 --- /dev/null +++ b/docs/CR Integer Multiple.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: CR_IntegerMultipleOf +- Category: Comfyroll/Utils/Other +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_IntegerMultipleOf 是一个设计用来将整数乘以指定的倍数,确保结果是给定因子的整数倍的节点。这个节点在需要保持一致的增量或缩放因子的情况下特别有用,例如在数学计算或数据处理任务中。它通过提供一种简单而有效的方式来根据预定义的倍数操作整数,从而为工作流程做出贡献。 + +# Input types +## Required +- integer + - ‘integer’参数是要乘以‘multiple’参数的基数。它在节点的操作中扮演着基础角色,因为它决定了乘法过程的起点。节点的执行和结果直接受此参数的值影响。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- multiple + - ‘multiple’参数定义了‘integer’将乘以的因子。它的重要性在于它决定了基数整数的缩放。节点的结果在很大程度上依赖于这个参数,它允许控制计算中所需增量级别。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- INT + - ‘INT’输出代表输入整数乘以指定倍数的结果。它是节点的主要输出,反映了节点基于给定因子进行整数乘法的核心功能。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - ‘show_help’输出提供了指向节点文档的URL链接,为用户提供了如何有效使用节点的额外信息和指导。这个辅助输出通过提供易于访问的帮助资源,增强了用户体验。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_IntegerMultipleOf: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'integer': ('INT', {'default': 1, 'min': -18446744073709551615, 'max': 18446744073709551615}), 'multiple': ('FLOAT', {'default': 8, 'min': 1, 'max': 18446744073709551615})}} + RETURN_TYPES = ('INT', 'STRING') + RETURN_NAMES = ('INT', 'show_help') + FUNCTION = 'int_multiple_of' + CATEGORY = icons.get('Comfyroll/Utils/Other') + + def int_multiple_of(self, integer, multiple=8): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-integer-multiple' + if multiple == 0: + return (int(integer), show_help) + integer = integer * multiple + return (int(integer), show_help) +``` \ No newline at end of file diff --git a/docs/CR Integer Range List.md b/docs/CR Integer Range List.md new file mode 100644 index 0000000..f14aa12 --- /dev/null +++ b/docs/CR Integer Range List.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: CR_IntegerRangeList +- Category: Comfyroll/List +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_IntegerRangeList节点旨在生成一个指定范围内的整数列表,具有可自定义的起始、结束和步长参数。它还可以适应“乒乓”行为,在交替迭代中反转范围,以获得更多样化的输出。此节点在需要序列整数值进行进一步处理或迭代的场景中扮演着关键角色。 + +# Input types +## Required +- start + - ‘start’参数定义了整数范围的开始。它至关重要,因为它决定了节点生成的数字序列的起始点,影响着整体输出序列。 + - Comfy dtype: INT + - Python dtype: int +- end + - ‘end’参数指定了整数范围的终点。它很关键,因为它决定了生成序列中的最后一个数字,从而影响范围的长度和范围。 + - Comfy dtype: INT + - Python dtype: int +- step + - ‘step’参数设置了范围内每个整数之间的增量。它很重要,因为它控制数字之间的间距,影响生成序列的密度。 + - Comfy dtype: INT + - Python dtype: int +- loops + - ‘loops’参数决定了将重复或迭代范围的次数。它很重要,因为它影响节点产生的数字总数。 + - Comfy dtype: INT + - Python dtype: int +- ping_pong + - ‘ping_pong’参数引入了一个交替模式,在每次迭代中范围都会反转。它很重要,因为它可以在序列中引入变化性,这对于某些应用可能是必要的。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- INT + - ‘INT’输出提供了基于输入参数在指定范围内生成的整数值列表。它很重要,因为它代表了节点的主要输出,准备用于进一步使用或分析。 + - Comfy dtype: INT + - Python dtype: List[int] +- show_help + - ‘show_help’输出提供了一个URL链接,用于获取更多帮助的文档。对于寻求如何有效使用节点的额外信息或指导的用户来说,这是有用的。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_IntegerRangeList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'start': ('INT', {'default': 0, 'min': -99999, 'max': 99999}), 'end': ('INT', {'default': 0, 'min': -99999, 'max': 99999}), 'step': ('INT', {'default': 1, 'min': 1, 'max': 99999}), 'loops': ('INT', {'default': 1, 'min': 1, 'max': 999}), 'ping_pong': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('INT', 'STRING') + RETURN_NAMES = ('INT', 'show_help') + OUTPUT_IS_LIST = (True, False) + FUNCTION = 'make_range' + CATEGORY = icons.get('Comfyroll/List') + + def make_range(self, start, end, step, loops, ping_pong): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-list-schedule' + range_values = list() + for i in range(loops): + current_range = list(range(start, end, step)) + if ping_pong: + if i % 2 == 1: + range_values += reversed(current_range) + else: + range_values += current_range + else: + range_values += current_range + return (range_values, show_help) +``` \ No newline at end of file diff --git a/docs/CR Integer To String.md b/docs/CR Integer To String.md new file mode 100644 index 0000000..05730c5 --- /dev/null +++ b/docs/CR Integer To String.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: CR_IntegerToString +- Category: Comfyroll/Utils/Conversion +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_IntegerToString节点旨在将整数值无缝转换为相应的字符串表示形式。在需要将数值数据以文本格式解释或显示的场景中,此转换过程至关重要。该节点在数据操作和转换任务中发挥关键作用,确保从数值到文本形式的转换准确可靠。 + +# Input types +## Required +- int_ + - ‘int_’参数是节点的核心输入,代表需要转换为字符串的整数值。它的转换对节点的操作至关重要,因为它直接影响输出和数据的后续处理。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- STRING + - ‘STRING’输出参数代表输入整数的字符串形式。它是节点转换过程的主要结果,标志着数值数据成功转换为人类可读的格式。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - ‘show_help’输出提供文档的URL链接,以供进一步帮助。它是用户寻求有关节点功能和用法的更多信息的有用资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_IntegerToString: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'int_': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615, 'forceInput': True})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + FUNCTION = 'convert' + CATEGORY = icons.get('Comfyroll/Utils/Conversion') + + def convert(self, int_): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Conversion-Nodes#cr-integer-to-string' + return (f'{int_}', show_help) +``` \ No newline at end of file diff --git a/docs/CR Interpolate Latents.md b/docs/CR Interpolate Latents.md new file mode 100644 index 0000000..ba99242 --- /dev/null +++ b/docs/CR Interpolate Latents.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: CR_InterpolateLatents +- Category: Comfyroll/Animation/Interpolate +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_InterpolateLatents 是一个用于在两个潜在表示之间执行插值的节点,它在状态之间提供平滑的过渡。此节点对于在给定数据空间内创建无缝动画或转换至关重要。 + +# Input types +## Required +- latent1 + - 用作插值过程起始点的第一个潜在表示。它对于定义动画或转换的初始状态至关重要。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- latent2 + - 作为插值端点的第二个潜在表示。它定义了插值旨在实现的最终状态。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- weight + - 权重参数影响两个潜在状态之间插值的程度。它对于控制过渡的速度和范围至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- method + - 插值方法确定用于在潜在状态之间转换的算法。它是执行的插值类型的关键因素。 + - Comfy dtype: COMBO['lerp'] + - Python dtype: str + +# Output types +- LATENT + - 由插值过程产生的输出潜在状态,代表输入潜在状态的混合。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- show_help + - 一个链接到文档的URL,用于进一步协助和理解插值过程。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_InterpolateLatents: + + @classmethod + def INPUT_TYPES(cls): + interpolation_methods = ['lerp'] + return {'required': {'latent1': ('LATENT',), 'latent2': ('LATENT',), 'weight': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'method': (interpolation_methods,)}} + RETURN_TYPES = ('LATENT', 'STRING') + RETURN_NAMES = ('LATENT', 'show_help') + FUNCTION = 'interpolate' + CATEGORY = icons.get('Comfyroll/Animation/Interpolate') + + def interpolate(self, latent1, latent2, weight, method): + a = latent1.copy() + b = latent2.copy() + c = {} + if method == 'lerp': + torch.lerp(a['samples'], b['samples'], weight, out=a['samples']) + elif method == 'slerp': + dot_products = torch.sum(latent1['samples'] * latent2['samples'], dim=(2, 3)) + dot_products = torch.clamp(dot_products, -1, 1) + angles = torch.acos(dot_products) + sin_angles = torch.sin(angles) + weight1 = torch.sin((1 - weight) * angles) / sin_angles + weight2 = torch.sin(weight * angles) / sin_angles + weight1 = weight1.unsqueeze(-1).unsqueeze(-1) + weight2 = weight2.unsqueeze(-1).unsqueeze(-1) + interpolated_samples = weight1 * latent1['samples'] + weight2 * latent2['samples'] + a['samples'] = interpolated_samples + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Interpolation-Nodes#cr-interpolate-latents' + return (a, show_help) +``` \ No newline at end of file diff --git a/docs/CR Intertwine Lists.md b/docs/CR Intertwine Lists.md new file mode 100644 index 0000000..599befd --- /dev/null +++ b/docs/CR Intertwine Lists.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: CR_IntertwineLists +- Category: Comfyroll/List/Utils +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_IntertwineLists 是一个实用工具节点,旨在将两个列表组合成单个列表,其中每个元素是输入列表中对应元素的连接。它用于将多个数据流交织成连贯的结构,促进复杂的数据操作和分析。 + +# Input types +## Required +- list1 + - list1 是将与第二个列表组合的第一个输入列表。它在节点的操作中起着至关重要的作用,因为它构成了最终组合列表的一半。 + - Comfy dtype: STRING + - Python dtype: List[str] +- list2 + - list2 是将与第一个列表交织的第二个输入列表。它的重要性与 list1 相等,因为它补充了 list1,以创建一个具有组合元素的新列表。 + - Comfy dtype: STRING + - Python dtype: List[str] + +# Output types +- combined_list + - 组合列表是节点的输出,它包含通过交织输入列表得到的元素。它很重要,因为它代表了用于进一步处理的综合数据结构。 + - Comfy dtype: STRING + - Python dtype: List[str] +- show_help + - show_help 输出提供了一个 URL 链接到文档,以获得进一步的帮助和指导,了解如何有效地使用该节点。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_IntertwineLists: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'list1': ('STRING', {'multiline': True, 'default': '', 'forceInput': True}), 'list2': ('STRING', {'multiline': True, 'default': '', 'forceInput': True})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + OUTPUT_IS_LIST = (True, False) + FUNCTION = 'make_list' + CATEGORY = icons.get('Comfyroll/List/Utils') + + def make_list(self, list1, list2): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-intertwine-lists' + min_length = min(len(list1), len(list2)) + combined_list = [] + combined_element = str(list1) + ', ' + str(list2) + combined_list.append(combined_element) + return (combined_list, show_help) +``` \ No newline at end of file diff --git a/docs/CR Keyframe List.md b/docs/CR Keyframe List.md new file mode 100644 index 0000000..4c42ef9 --- /dev/null +++ b/docs/CR Keyframe List.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: CR_KeyframeList +- Category: Comfyroll/Animation/Prompt +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_KeyframeList 节点旨在管理和处理关键帧列表,这些是定义动画时间线的帧序列。它通过允许用户输入关键帧数据并指定格式以进行正确解释,在动画工作流程中发挥着关键作用。 + +# Input types +## Required +- keyframe_list + - 关键帧列表是一个包含定义动画的帧序列的字符串。它对节点至关重要,因为它直接影响输出的动画序列。 + - Comfy dtype: STRING + - Python dtype: str +- keyframe_format + - 关键帧格式参数决定了如何解释关键帧列表。它对于确保节点正确理解并处理关键帧数据很重要。 + - Comfy dtype: COMBO['Deforum', 'CR'] + - Python dtype: str + +# Output types +- keyframe_list + - 已根据指定的关键帧格式格式化的已处理关键帧列表,准备用于动画序列。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - 一个链接到文档页面的URL,提供有关使用关键帧列表功能的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_KeyframeList: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'keyframe_list': ('STRING', {'multiline': True, 'default': 'keyframes'}), 'keyframe_format': (['Deforum', 'CR'],)}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('keyframe_list', 'show_help') + FUNCTION = 'keyframelist' + CATEGORY = icons.get('Comfyroll/Animation/Prompt') + + def keyframelist(self, keyframe_list, keyframe_format): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Prompt-Nodes#cr-keyframe-list' + return (keyframe_list, show_help) +``` \ No newline at end of file diff --git a/docs/CR Latent Batch Size.md b/docs/CR Latent Batch Size.md new file mode 100644 index 0000000..9578015 --- /dev/null +++ b/docs/CR Latent Batch Size.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: CR_LatentBatchSize +- Category: Comfyroll/Essential/Core +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_LatentBatchSize节点旨在处理和管理潜在表示的批量大小。它高效地处理复制和连接潜在样本,以达到指定的批量大小,确保下游流程可以一致地运行,无论原始样本数量如何。 + +# Input types +## Required +- latent + - latent参数非常关键,因为它包含了需要批量处理的潜在表示。这是节点的主要输入,直接影响节点的操作和生成的批量数据。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +## Optional +- batch_size + - batch_size参数决定了每个批量中的样本数。如果未提供,它是一个可选输入,默认值为2。这个参数显著影响节点的输出,因为它决定了从潜在样本创建的批量的大小。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- samples + - samples输出是已连接的潜在表示张量,已调整以匹配所需的批量大小。这个输出对于确保与期望具有特定批量维度的后续处理步骤的兼容性至关重要。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_LatentBatchSize: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latent': ('LATENT',), 'batch_size': ('INT', {'default': 2, 'min': 1, 'max': 999, 'step': 1})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'batchsize' + CATEGORY = icons.get('Comfyroll/Essential/Core') + + def batchsize(self, latent: tg.Sequence[tg.Mapping[tg.Text, torch.Tensor]], batch_size: int): + samples = latent['samples'] + shape = samples.shape + sample_list = [samples] + [torch.clone(samples) for _ in range(batch_size - 1)] + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Core-Nodes#cr-latent-batch-size' + return ({'samples': torch.cat(sample_list)},) +``` \ No newline at end of file diff --git a/docs/CR Latent Input Switch.md b/docs/CR Latent Input Switch.md new file mode 100644 index 0000000..75ea1f7 --- /dev/null +++ b/docs/CR Latent Input Switch.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CR_LatentInputSwitch +- Category: Comfyroll/Utils/Logic +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_LatentInputSwitch 节点旨在根据输入值管理两种潜在状态之间的选择。它在工作流中作为一个决策组件,允许数据通过系统进行条件路由。在需要动态选择不同的潜在表示的场景中,该节点的功能至关重要。 + +# Input types +## Required +- Input + - ‘Input’参数至关重要,因为它决定了节点将选择哪个潜在状态。它是一个整数,范围应在1到2之间,其中1对应第一个潜在状态,2对应第二个。这个决策变量对节点的操作至关重要,因为它直接影响输出选择。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- latent1 + - ‘latent1’参数代表节点可以选择的第一个潜在状态。它是可选的,并且当‘Input’参数设置为1时变得重要,在这种情况下,‘latent1’是节点将返回的输出。 + - Comfy dtype: LATENT + - Python dtype: Union[torch.Tensor, None] +- latent2 + - ‘latent2’参数表示可供选择的第二个潜在状态。它也是可选的,当‘Input’参数设置为2时被考虑,导致‘latent2’成为节点返回的输出。 + - Comfy dtype: LATENT + - Python dtype: Union[torch.Tensor, None] + +# Output types +- LATENT + - ‘LATENT’输出代表了基于‘Input’参数选择的潜在状态。它是节点的主要输出,并携带了从‘latent1’或‘latent2’中条件选择的潜在数据。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- show_help + - ‘show_help’输出提供了一个URL链接到节点的文档页面,以获得更多帮助。它作为次要输出被包含,以指导用户寻求有关节点使用和功能的更多信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_LatentInputSwitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': ('INT', {'default': 1, 'min': 1, 'max': 2})}, 'optional': {'latent1': ('LATENT',), 'latent2': ('LATENT',)}} + RETURN_TYPES = ('LATENT', 'STRING') + RETURN_NAMES = ('LATENT', 'show_help') + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Utils/Logic') + + def switch(self, Input, latent1=None, latent2=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Logic-Nodes#cr-latent-input-switch' + if Input == 1: + return (latent1, show_help) + else: + return (latent2, show_help) +``` \ No newline at end of file diff --git a/docs/CR LoRA List.md b/docs/CR LoRA List.md new file mode 100644 index 0000000..e11c4ff --- /dev/null +++ b/docs/CR LoRA List.md @@ -0,0 +1,111 @@ +# Documentation +- Class name: CR_LoRAList +- Category: Comfyroll/Animation/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_LoRAList节点旨在管理和编译LoRA(低秩适应)配置列表。它允许用户指定多个LoRA设置,每个设置都有别名、模型强度和剪辑强度,然后将它们组合成一个单一的列表。该节点在通过LoRA技术定制和增强模型行为中发挥着关键作用。 + +# Input types +## Required +- lora_name1 + - 参数'lora_name1'对于指定第一个LoRA配置至关重要。它决定了要使用的LoRA文件,并且显著影响节点的定制能力。 + - Comfy dtype: STRING + - Python dtype: str +- model_strength_1 + - 参数'model_strength_1'调整第一个LoRA配置对模型的影响,允许对模型行为进行微调。 + - Comfy dtype: FLOAT + - Python dtype: float +- clip_strength_1 + - 参数'clip_strength_1'控制第一个LoRA配置的剪辑强度,这对于在训练期间保持模型的稳定性至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- alias1 + - 参数'alias1'为第一个LoRA配置提供用户定义的名称,增强了LoRA列表中的可读性和可管理性。 + - Comfy dtype: STRING + - Python dtype: str +- lora_name2 + - 参数'lora_name2'类似于'lora_name1',指定要包含在列表中的第二个LoRA配置,提供更多的定制选项。 + - Comfy dtype: STRING + - Python dtype: str +- alias2 + - 参数'alias2'为第二个LoRA配置分配别名,以便在编译的列表中更容易引用和管理。 + - Comfy dtype: STRING + - Python dtype: str +- model_strength_2 + - 参数'model_strength_2'用于调整第二个LoRA配置的影响,使用户能够控制模型的适应性。 + - Comfy dtype: FLOAT + - Python dtype: float +- clip_strength_2 + - 参数'clip_strength_2'设置第二个LoRA配置的剪辑强度,在模型训练稳定性中发挥作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- lora_name3 + - 参数'lora_name3'定义了要考虑列入列表的第三个LoRA配置,进一步扩大了定制范围。 + - Comfy dtype: STRING + - Python dtype: str +- alias3 + - 参数'alias3'允许用户为第三个LoRA配置分配自定义名称,以便于在列表中更好地识别和组织。 + - Comfy dtype: STRING + - Python dtype: str +- model_strength_3 + - 参数'model_strength_3'修改第三个LoRA配置的效果,允许对模型性能进行精细控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- clip_strength_3 + - 参数'clip_strength_3'确定第三个LoRA配置的剪辑强度,这对于模型的稳健训练过程至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- lora_list + - 参数'lora_list'是可选的,允许用户提供一个现有的LoRA配置列表,由节点追加或修改。 + - Comfy dtype: LORA_LIST + - Python dtype: List[Tuple[str, str, float, float]] + +# Output types +- LORA_LIST + - 'LORA_LIST'输出包含编译后的LoRA配置列表,可以直接用于后续的模型操作。 + - Comfy dtype: LORA_LIST + - Python dtype: List[Tuple[str, str, float, float]] +- show_text + - 'show_text'输出提供LoRA列表的文本表示,这对于显示或记录目的非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_LoRAList: + + @classmethod + def INPUT_TYPES(cls): + lora_files = ['None'] + folder_paths.get_filename_list('loras') + return {'required': {'lora_name1': (lora_files,), 'alias1': ('STRING', {'multiline': False, 'default': ''}), 'model_strength_1': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'clip_strength_1': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'lora_name2': (lora_files,), 'alias2': ('STRING', {'multiline': False, 'default': ''}), 'model_strength_2': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'clip_strength_2': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'lora_name3': (lora_files,), 'alias3': ('STRING', {'multiline': False, 'default': ''}), 'model_strength_3': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'clip_strength_3': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01})}, 'optional': {'lora_list': ('lora_LIST',)}} + RETURN_TYPES = ('LORA_LIST', 'STRING') + RETURN_NAMES = ('LORA_LIST', 'show_text') + FUNCTION = 'lora_list' + CATEGORY = icons.get('Comfyroll/Animation/Legacy') + + def lora_list(self, lora_name1, model_strength_1, clip_strength_1, alias1, lora_name2, model_strength_2, clip_strength_2, alias2, lora_name3, model_strength_3, clip_strength_3, alias3, lora_list=None): + loras = list() + lora_text = list() + if lora_list is not None: + loras.extend([l for l in lora_list if l[0] != None]) + lora_text += '\n'.join(map(str, lora_list)) + '\n' + if lora_name1 != 'None': + lora1_tup = [(alias1, lora_name1, model_strength_1, clip_strength_1)] + (loras.extend(lora1_tup),) + lora_text += '\n'.join(map(str, lora1_tup)) + '\n' + if lora_name2 != 'None': + lora2_tup = [(alias2, lora_name2, model_strength_2, clip_strength_2)] + (loras.extend(lora2_tup),) + lora_text += '\n'.join(map(str, lora2_tup)) + '\n' + if lora_name3 != 'None': + lora3_tup = [(alias3, lora_name3, model_strength_3, clip_strength_3)] + (loras.extend(lora3_tup),) + lora_text += '\n'.join(map(str, lora3_tup)) + '\n' + show_text = ''.join(lora_text) + return (loras, show_text) +``` \ No newline at end of file diff --git a/docs/CR LoRA Stack.md b/docs/CR LoRA Stack.md new file mode 100644 index 0000000..647fd8a --- /dev/null +++ b/docs/CR LoRA Stack.md @@ -0,0 +1,103 @@ +# Documentation +- Class name: CR_LoRAStack +- Category: Comfyroll/LoRA +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_LoRAStack节点旨在管理和组合多个LoRA(低秩适应)层到一个单一的栈中。它允许用户切换每个LoRA层的包含,设置模型权重,并剪辑权重以微调每个层对最终输出的贡献。该节点的功能集中在堆叠LoRA层以增强模型性能,而不会显著增加计算成本。 + +# Input types +## Required +- switch_1 + - 开关参数决定是否将第一个LoRA层包含在栈中。它对控制最终LoRA栈的组成至关重要。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +- lora_name_1 + - lora_name_1参数指定了可能包含在栈中的第一个LoRA层的名称。它在识别堆叠过程中的特定LoRA层中起着重要作用。 + - Comfy dtype: STRING + - Python dtype: str +- model_weight_1 + - model_weight_1参数调整第一个LoRA层对最终输出的影响。对于微调每个层的贡献至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- clip_weight_1 + - clip_weight_1参数用于剪辑或限制第一个LoRA层的权重,防止其过度支配最终输出。 + - Comfy dtype: FLOAT + - Python dtype: float +- switch_2 + - 第二个LoRA层的开关参数决定其是否包含在栈中。它在决定LoRA栈的最终结构中起着关键作用。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +- lora_name_2 + - lora_name_2参数指明要考虑加入栈的第二个LoRA层的名称。它是识别堆叠LoRA层的一个关键因素。 + - Comfy dtype: STRING + - Python dtype: str +- model_weight_2 + - model_weight_2参数修改第二个LoRA层对最终结果的影响。它对于校准该层的贡献是不可或缺的。 + - Comfy dtype: FLOAT + - Python dtype: float +- clip_weight_2 + - clip_weight_2参数负责剪辑第二个LoRA层的权重,以保持最终输出的平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- switch_3 + - 第三个LoRA层的开关参数控制其在栈中的存在。它是LoRA栈形成中的一个关键元素。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +- lora_name_3 + - lora_name_3参数识别可能包含在栈中的第三个LoRA层。它对于LoRA层的选择过程至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- model_weight_3 + - model_weight_3参数影响第三个LoRA层对最终结果的影响。对于调整该层的影响至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- clip_weight_3 + - clip_weight_3参数剪辑第三个LoRA层的权重,以确保它不会对最终栈的输出产生不成比例的影响。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- lora_stack + - lora_stack参数允许使用现有层预填充LoRA栈。它适用于从先前状态继续工作。 + - Comfy dtype: LORA_STACK + - Python dtype: List[Tuple[str, float, float]] + +# Output types +- LORA_STACK + - LORA_STACK输出是一个元组列表,表示堆叠的LoRA层及其相应的权重和剪辑值。这是节点操作的主要结果。 + - Comfy dtype: LORA_STACK + - Python dtype: List[Tuple[str, float, float]] +- show_help + - show_help输出提供了一个URL链接到文档,以获取有关节点使用的更多帮助和信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_LoRAStack: + + @classmethod + def INPUT_TYPES(cls): + loras = ['None'] + folder_paths.get_filename_list('loras') + return {'required': {'switch_1': (['Off', 'On'],), 'lora_name_1': (loras,), 'model_weight_1': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'clip_weight_1': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'switch_2': (['Off', 'On'],), 'lora_name_2': (loras,), 'model_weight_2': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'clip_weight_2': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'switch_3': (['Off', 'On'],), 'lora_name_3': (loras,), 'model_weight_3': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'clip_weight_3': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01})}, 'optional': {'lora_stack': ('LORA_STACK',)}} + RETURN_TYPES = ('LORA_STACK', 'STRING') + RETURN_NAMES = ('LORA_STACK', 'show_help') + FUNCTION = 'lora_stacker' + CATEGORY = icons.get('Comfyroll/LoRA') + + def lora_stacker(self, lora_name_1, model_weight_1, clip_weight_1, switch_1, lora_name_2, model_weight_2, clip_weight_2, switch_2, lora_name_3, model_weight_3, clip_weight_3, switch_3, lora_stack=None): + lora_list = list() + if lora_stack is not None: + lora_list.extend([l for l in lora_stack if l[0] != 'None']) + if lora_name_1 != 'None' and switch_1 == 'On': + (lora_list.extend([(lora_name_1, model_weight_1, clip_weight_1)]),) + if lora_name_2 != 'None' and switch_2 == 'On': + (lora_list.extend([(lora_name_2, model_weight_2, clip_weight_2)]),) + if lora_name_3 != 'None' and switch_3 == 'On': + (lora_list.extend([(lora_name_3, model_weight_3, clip_weight_3)]),) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/LoRA-Nodes#cr-lora-stack' + return (lora_list, show_help) +``` \ No newline at end of file diff --git a/docs/CR Load Animation Frames.md b/docs/CR Load Animation Frames.md new file mode 100644 index 0000000..a51a347 --- /dev/null +++ b/docs/CR Load Animation Frames.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: CR_LoadAnimationFrames +- Category: Comfyroll/Animation/IO +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_LoadAnimationFrames 是一个用于从指定目录加载和处理图像序列的节点,它允许在工作流中操纵和分析帧数据。它促进了图像文件的转换,使其适合进一步处理,例如动画或视频编辑任务。 + +# Input types +## Required +- image_sequence_folder + - image_sequence_folder 参数指定包含要加载的图像序列的目录。对于节点来说,定位和访问正确的图像序列以进行处理至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- start_index + - start_index 参数确定要加载的图像序列的起始点。它对于控制序列的开始帧很重要,允许选择性地加载序列中的帧。 + - Comfy dtype: INT + - Python dtype: int +- max_frames + - max_frames 参数设置了从图像序列中加载的最大帧数。它在限制处理的数据量方面发挥着重要作用,这对于优化资源使用和工作流效率至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - IMAGE 输出提供了作为帧堆栈的加载图像序列,允许在工作流中进行下游处理和分析。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个链接到文档,以获取有关使用节点和理解其功能的进一步指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_LoadAnimationFrames: + input_dir = folder_paths.input_directory + + @classmethod + def INPUT_TYPES(s): + image_folder = [name for name in os.listdir(s.input_dir) if os.path.isdir(os.path.join(s.input_dir, name)) and len(os.listdir(os.path.join(s.input_dir, name))) != 0] + return {'required': {'image_sequence_folder': (sorted(image_folder),), 'start_index': ('INT', {'default': 1, 'min': 1, 'max': 10000}), 'max_frames': ('INT', {'default': 1, 'min': 1, 'max': 10000})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'load_image_sequence' + CATEGORY = icons.get('Comfyroll/Animation/IO') + + def load_image_sequence(self, image_sequence_folder, start_index, max_frames): + image_path = os.path.join(self.input_dir, image_sequence_folder) + file_list = sorted(os.listdir(image_path), key=lambda s: sum(((s, int(n)) for (s, n) in re.findall('(\\D+)(\\d+)', 'a%s0' % s)), ())) + sample_frames = [] + sample_frames_mask = [] + sample_index = list(range(start_index - 1, len(file_list), 1))[:max_frames] + for num in sample_index: + i = Image.open(os.path.join(image_path, file_list[num])) + image = i.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + image = image.squeeze() + sample_frames.append(image) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/IO-Nodes#cr-load-animation-frames' + return (torch.stack(sample_frames), show_help) +``` \ No newline at end of file diff --git a/docs/CR Load Flow Frames.md b/docs/CR Load Flow Frames.md new file mode 100644 index 0000000..37f02a4 --- /dev/null +++ b/docs/CR Load Flow Frames.md @@ -0,0 +1,112 @@ +# Documentation +- Class name: CR_LoadFlowFrames +- Category: Comfyroll/Animation/IO +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_LoadFlowFrames 节点旨在为动画目的加载和处理图像序列。它能够根据用户定义的标准对目录中的帧进行排序和选择,确保动画帧逐帧操作的流畅工作流程。 + +# Input types +## Required +- input_folder + - input_folder 参数指定包含图像序列的目录。它在确定动画图像的来源中起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +- sort_by + - sort_by 参数确定输入文件夹中图像文件的排序方法。它对于维护动画序列中帧的正确顺序至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- current_frame + - current_frame 参数指示图像加载过程的起始帧。它对于控制节点在动画序列中开始操作的位置至关重要。 + - Comfy dtype: INT + - Python dtype: int +- skip_start_frames + - skip_start_frames 参数允许用户在序列开头跳过一定数量的帧。这对于排除动画不需要的初始帧非常有用。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- input_path + - 可选的 input_path 参数提供了一个特定的路径到图像文件,如果它们不在默认的输入目录中。它为动画过程提供了文件位置的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- file_pattern + - file_pattern 参数用于定义输入文件夹内文件选择的模式。它有助于筛选动画所需的特定类型的图像文件。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- current_image + - current_image 输出提供了从图像序列中加载的最新帧。它对于持续的动画操作和显示非常重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- previous_image + - previous_image 输出提供了序列中当前帧之前的帧。它可以用于动画中的比较或过渡效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- current_frame + - current_frame 输出指示当前正在处理的帧编号。这些信息对于跟踪动画序列中的进度非常有用。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - show_help 输出提供了一个链接到文档的链接,以获取有关如何使用该节点的进一步指导。这对于寻求有关节点功能更多信息的用户特别有帮助。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_LoadFlowFrames: + + @classmethod + def INPUT_TYPES(s): + sort_methods = ['Index', 'Alphabetic'] + input_dir = folder_paths.input_directory + input_folders = [name for name in os.listdir(input_dir) if os.path.isdir(os.path.join(input_dir, name)) and len(os.listdir(os.path.join(input_dir, name))) != 0] + return {'required': {'input_folder': (sorted(input_folders),), 'sort_by': (sort_methods,), 'current_frame': ('INT', {'default': 0, 'min': 0, 'max': 10000, 'forceInput': True}), 'skip_start_frames': ('INT', {'default': 0, 'min': 0, 'max': 10000})}, 'optional': {'input_path': ('STRING', {'default': '', 'multiline': False}), 'file_pattern': ('STRING', {'default': '*.png', 'multiline': False})}} + CATEGORY = icons.get('Comfyroll/Animation/IO') + RETURN_TYPES = ('IMAGE', 'IMAGE', 'INT', 'STRING') + RETURN_NAMES = ('current_image', 'previous_image', 'current_frame', 'show_help') + FUNCTION = 'load_images' + + def load_images(self, file_pattern, skip_start_frames, input_folder, sort_by, current_frame, input_path=''): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/IO-Nodes#cr-load-flow-frames' + input_dir = folder_paths.input_directory + current_frame = current_frame + skip_start_frames + print(f'[Info] CR Load Flow Frames: current_frame {current_frame}') + if input_path != '': + if not os.path.exists(input_path): + print(f'[Warning] CR Load Flow Frames: The input_path `{input_path}` does not exist') + return ('',) + image_path = os.path.join('', input_path) + else: + image_path = os.path.join(input_dir, input_folder) + print(f'[Info] CR Load Flow Frames: ComfyUI Input directory is `{image_path}`') + file_list = get_files(image_path, sort_by, file_pattern) + if os.path.exists(image_path + '.DS_Store'): + file_list.remove('.DS_Store') + if len(file_list) == 0: + print(f'[Warning] CR Load Flow Frames: No matching files found for loading') + return () + remaining_files = len(file_list) - current_frame + print(f'[Info] CR Load Flow Frames: {remaining_files} input files remaining for processing') + img = Image.open(os.path.join(image_path, file_list[current_frame])) + cur_image = img.convert('RGB') + cur_image = np.array(cur_image).astype(np.float32) / 255.0 + cur_image = torch.from_numpy(cur_image)[None,] + print(f'[Debug] CR Load Flow Frames: Current image {file_list[current_frame]}') + if current_frame == 0 and skip_start_frames == 0: + img = Image.open(os.path.join(image_path, file_list[current_frame])) + pre_image = img.convert('RGB') + pre_image = np.array(pre_image).astype(np.float32) / 255.0 + pre_image = torch.from_numpy(pre_image)[None,] + print(f'[Debug] CR Load Flow Frames: Previous image {file_list[current_frame]}') + else: + img = Image.open(os.path.join(image_path, file_list[current_frame - 1])) + pre_image = img.convert('RGB') + pre_image = np.array(pre_image).astype(np.float32) / 255.0 + pre_image = torch.from_numpy(pre_image)[None,] + print(f'[Debug] CR Load Flow Frames: Previous image {file_list[current_frame - 1]}') + return (cur_image, pre_image, current_frame, show_help) +``` \ No newline at end of file diff --git a/docs/CR Load GIF As List.md b/docs/CR Load GIF As List.md new file mode 100644 index 0000000..0ace7a1 --- /dev/null +++ b/docs/CR Load GIF As List.md @@ -0,0 +1,98 @@ +# Documentation +- Class name: CR_LoadGIFAsList +- Category: Comfyroll/List/IO +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_LoadGIFAsList 是一个用于加载和处理 GIF 文件的节点,它能够提取单独的帧及其对应的遮罩。该节点能够通过指定起始帧和最大帧数来处理一系列 GIF 文件。在 Comfyroll Studio 环境中,这个节点对于准备进一步操作和分析的 GIF 数据至关重要。 + +# Input types +## Required +- input_folder + - input_folder 参数指定包含要加载的 GIF 文件的目录。对于节点来说,定位和访问正确的 GIF 文件以进行处理至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- gif_filename + - gif_filename 参数定义了要加载的 GIF 文件的名称。它在众多选项中识别特定 GIF 文件中起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +- start_frame + - start_frame 参数指示节点应从哪个帧号开始加载 GIF 帧。它在控制帧提取过程的起始点上具有重要意义。 + - Comfy dtype: INT + - Python dtype: int +- max_frames + - max_frames 参数设置从 GIF 中提取的最大帧数。它在限制帧提取的范围和管理资源使用方面很重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- input_path + - 可选的 input_path 参数允许指定 GIF 文件的自定义路径,覆盖默认的目录结构。它为特定用例提供了文件位置的灵活性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - IMAGE 输出包含从 GIF 文件加载的帧,以便在 Comfyroll Studio 工作流中进行进一步处理或可视化。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +- MASK + - MASK 输出提供与每一帧对应的遮罩,可用于需要透明度信息的分割或其他图像处理任务。 + - Comfy dtype: MASK + - Python dtype: List[torch.Tensor] +- show_help + - show_help 输出提供了一个链接到文档,以便在使用节点时获得进一步的帮助和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_LoadGIFAsList: + + @classmethod + def INPUT_TYPES(cls): + input_dir = folder_paths.input_directory + image_folder = [name for name in os.listdir(input_dir) if os.path.isdir(os.path.join(input_dir, name))] + return {'required': {'input_folder': (sorted(image_folder),), 'gif_filename': ('STRING', {'multiline': False, 'default': 'text'}), 'start_frame': ('INT', {'default': 0, 'min': 0, 'max': 99999}), 'max_frames': ('INT', {'default': 1, 'min': 1, 'max': 99999})}, 'optional': {'input_path': ('STRING', {'default': '', 'multiline': False})}} + RETURN_TYPES = ('IMAGE', 'MASK', 'STRING') + RETURN_NAMES = ('IMAGE', 'MASK', 'show_help') + OUTPUT_IS_LIST = (True, True, False) + FUNCTION = 'load_gif' + CATEGORY = icons.get('Comfyroll/List/IO') + + def load_gif(self, input_folder, gif_filename, start_frame, max_frames, input_path=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-load-gif-images' + if input_path != '' and input_path is not None: + if not os.path.exists(input_path): + print(f'[Warning] CR Image List: The input_path `{input_path}` does not exist') + return ('',) + in_path = input_path + else: + input_dir = folder_paths.input_directory + in_path = os.path.join(input_dir, input_folder) + gif_file_path = os.path.join(in_path, gif_filename) + frames_list = [] + masks_list = [] + try: + with Image.open(gif_file_path) as gif_image: + for (i, frame) in enumerate(ImageSequence.Iterator(gif_image)): + if i < start_frame: + continue + if max_frames is not None and i >= start_frame + max_frames: + break + img = frame.copy() + (width, height) = img.size + frames_list.append(pil2tensor(img.convert('RGB'))) + tensor_img = pil2tensor(img) + masks_list.append(tensor2rgba(tensor_img)[:, :, :, 0]) + images = torch.cat(frames_list, dim=0) + images_out = [images[i:i + 1, ...] for i in range(images.shape[0])] + masks = torch.cat(masks_list, dim=0) + masks_out = [masks[i:i + 1, ...] for i in range(masks.shape[0])] + return (images_out, masks_out, show_help) + except Exception as e: + print(f'Error: {e}') + return (None, None, show_help) +``` \ No newline at end of file diff --git a/docs/CR Load Image List Plus.md b/docs/CR Load Image List Plus.md new file mode 100644 index 0000000..58a4d84 --- /dev/null +++ b/docs/CR Load Image List Plus.md @@ -0,0 +1,121 @@ +# Documentation +- Class name: CR_LoadImageListPlus +- Category: Comfyroll/List/IO +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_LoadImageListPlus 是一个用于从指定目录高效加载和处理图像列表的节点。它能够处理大量图像批次,对它们进行排序,并提供文件名和尺寸等附加元数据。该节点旨在简化在 ComfyUI 工作流中进一步处理或显示图像的过程。 + +# Input types +## Required +- input_folder + - input_folder 参数指定了将加载图像的目录。对于节点的操作至关重要,因为它决定了图像的来源。 + - Comfy dtype: STRING + - Python dtype: List[str] +- start_index + - start_index 参数确定在图像列表中开始加载的起始点。它很重要,因为它允许从列表中选择特定范围的图像。 + - Comfy dtype: INT + - Python dtype: int +- max_images + - max_images 参数设置从目录中加载的最大图像数量。它在控制处理批次大小时起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- input_path + - 可选的 input_path 参数允许指定图像目录的替代路径。如果默认目录不符合用户的要求,它提供了灵活性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - IMAGE 输出提供了适合进一步处理或分析的加载图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- MASK + - MASK 输出包括从图像派生的二进制掩码,可用于分割或其他目的。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- index + - index 输出表示每个图像在原始列表中的位置,提供了图像顺序的参考。 + - Comfy dtype: INT + - Python dtype: List[int] +- filename + - filename 输出提供了加载图像的名称,这对于识别和记录保持非常有用。 + - Comfy dtype: STRING + - Python dtype: List[str] +- width + - width 输出指示图像的宽度,这对于了解加载图像的尺寸至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - height 输出指示图像的高度,与宽度相辅相成,以全面了解图像的尺寸。 + - Comfy dtype: INT + - Python dtype: int +- list_length + - list_length 输出提供了从目录中加载的图像的总数,这对于跟踪数据集的围很重要。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - show_help 输出提供了文档链接,以获取有关如何使用节点的进一步指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_LoadImageListPlus: + + @classmethod + def INPUT_TYPES(s): + input_dir = folder_paths.input_directory + image_folder = [name for name in os.listdir(input_dir) if os.path.isdir(os.path.join(input_dir, name))] + return {'required': {'input_folder': (sorted(image_folder),), 'start_index': ('INT', {'default': 0, 'min': 0, 'max': 99999}), 'max_images': ('INT', {'default': 1, 'min': 1, 'max': 99999})}, 'optional': {'input_path': ('STRING', {'default': '', 'multiline': False})}} + RETURN_TYPES = ('IMAGE', 'MASK', 'INT', 'STRING', 'INT', 'INT', 'INT', 'STRING') + RETURN_NAMES = ('IMAGE', 'MASK', 'index', 'filename', 'width', 'height', 'list_length', 'show_help') + OUTPUT_IS_LIST = (True, True, True, True, False, False, False, False) + FUNCTION = 'make_list' + CATEGORY = icons.get('Comfyroll/List/IO') + + def make_list(self, start_index, max_images, input_folder, input_path=None, vae=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-image-list-plus' + if input_path != '' and input_path is not None: + if not os.path.exists(input_path): + print(f'[Warning] CR Image List: The input_path `{input_path}` does not exist') + return ('',) + in_path = input_path + else: + input_dir = folder_paths.input_directory + in_path = os.path.join(input_dir, input_folder) + if not os.listdir(in_path): + print(f'[Warning] CR Image List: The folder `{in_path}` is empty') + return None + file_list = sorted(os.listdir(in_path), key=lambda s: sum(((s, int(n)) for (s, n) in re.findall('(\\D+)(\\d+)', 'a%s0' % s)), ())) + image_list = [] + mask_list = [] + index_list = [] + filename_list = [] + exif_list = [] + start_index = max(0, min(start_index, len(file_list) - 1)) + end_index = min(start_index + max_images, len(file_list) - 1) + for num in range(start_index, end_index): + filename = file_list[num] + img_path = os.path.join(in_path, filename) + img = Image.open(os.path.join(in_path, file_list[num])) + image_list.append(pil2tensor(img.convert('RGB'))) + tensor_img = pil2tensor(img) + mask_list.append(tensor2rgba(tensor_img)[:, :, :, 0]) + index_list.append(num) + filename_list.append(filename) + if not image_list: + print('CR Load Image List: No images found.') + return None + (width, height) = Image.open(os.path.join(in_path, file_list[start_index])).size + images = torch.cat(image_list, dim=0) + images_out = [images[i:i + 1, ...] for i in range(images.shape[0])] + masks = torch.cat(mask_list, dim=0) + mask_out = [masks[i:i + 1, ...] for i in range(masks.shape[0])] + list_length = end_index - start_index + return (images_out, mask_out, index_list, filename_list, index_list, width, height, list_length, show_help) +``` \ No newline at end of file diff --git a/docs/CR Load Image List.md b/docs/CR Load Image List.md new file mode 100644 index 0000000..ebf8132 --- /dev/null +++ b/docs/CR Load Image List.md @@ -0,0 +1,84 @@ +# Documentation +- Class name: CR_LoadImageList +- Category: Comfyroll/List/IO +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_LoadImageList 是一个用于从指定目录加载和处理图像文件列表的节点。它提供基于起始索引和要加载的最大图像数量检索图像子集的功能,确保操作高效并满足用户需求。该节点的主要目标是在 ComfyUI 框架内简化图像加载过程,以便进行进一步的操作或分析。 + +# Input types +## Required +- input_folder + - input_folder 参数指定包含要加载图像的目录。它在确定节点将操作的图像列表的范围中起着关键作用,因此直接影响节点的执行和生成的图像列表。 + - Comfy dtype: STRING + - Python dtype: str +- start_index + - start_index 参数指示节点将从中开始加载图像的排序后的图像列表中的位置。它对于控制要处理的图像子集至关重要,允许对图像序列进行精确操作。 + - Comfy dtype: INT + - Python dtype: int +- max_images + - max_images 参数设置节点将从指定的 start_index 开始加载的最大图像数量。它是一个关键参数,用于限制图像列表的大小,确保节点的操作针对性能和资源管理进行了优化。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- input_path + - 可选的 input_path 参数允许用户指定一个自定义路径到图像目录,覆盖默认的输入目录。这提供了在选择图像列表来源方面的灵活性,并且可以用来整合来自不同位置的图像。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - IMAGE 输出提供已加载的图像数据作为张量,可以在 ComfyUI 框架内进一步处理或分析。它代表了 CR_LoadImageList 节点的主要输出,体现了节点加载和准备图像的核心功能。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个指向文档页面的 URL 链接,以供进一步的指导和帮助。它是用户寻求如何有效使用节点的更多信息的有用资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_LoadImageList: + + @classmethod + def INPUT_TYPES(s): + input_dir = folder_paths.input_directory + image_folder = [name for name in os.listdir(input_dir) if os.path.isdir(os.path.join(input_dir, name))] + return {'required': {'input_folder': (sorted(image_folder),), 'start_index': ('INT', {'default': 0, 'min': 0, 'max': 9999}), 'max_images': ('INT', {'default': 1, 'min': 1, 'max': 9999})}, 'optional': {'input_path': ('STRING', {'default': '', 'multiline': False})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + OUTPUT_IS_LIST = (True, False) + FUNCTION = 'make_list' + CATEGORY = icons.get('Comfyroll/List/IO') + + def make_list(self, start_index, max_images, input_folder, input_path=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-image-list' + if input_path != '' and input_path is not None: + if not os.path.exists(input_path): + print(f'[Warning] CR Image List: The input_path `{input_path}` does not exist') + return ('',) + in_path = input_path + else: + input_dir = folder_paths.input_directory + in_path = os.path.join(input_dir, input_folder) + if not os.listdir(in_path): + print(f'[Warning] CR Image List: The folder `{in_path}` is empty') + return None + file_list = sorted(os.listdir(in_path), key=lambda s: sum(((s, int(n)) for (s, n) in re.findall('(\\D+)(\\d+)', 'a%s0' % s)), ())) + image_list = [] + start_index = max(0, min(start_index, len(file_list) - 1)) + end_index = min(start_index + max_images, len(file_list) - 1) + for num in range(start_index, end_index): + img = Image.open(os.path.join(in_path, file_list[num])) + image = img.convert('RGB') + image_list.append(pil2tensor(image)) + if not image_list: + print('CR Load Image List: No images found.') + return None + images = torch.cat(image_list, dim=0) + images_out = [images[i:i + 1, ...] for i in range(images.shape[0])] + return (images_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Load LoRA.md b/docs/CR Load LoRA.md new file mode 100644 index 0000000..5cdcfa9 --- /dev/null +++ b/docs/CR Load LoRA.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: CR_LoraLoader +- Category: Comfyroll/LoRA +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_LoraLoader 是一个用于管理和应用 Lora 修改到模型和剪辑的节点。它负责加载 Lora 文件并根据指定的 Lora 名称和强度参数调整模型和剪辑。 + +# Input types +## Required +- model + - 模型参数对于节点的操作至关重要,因为它代表了将由 Lora 修改的基础模型。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - 剪辑参数是必不可少的,因为它定义了将被 Lora 处理和可能被修改的剪辑。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- switch + - 开关参数决定是否将 Lora 修改应用于模型和剪辑。 + - Comfy dtype: ['On', 'Off'] + - Python dtype: str +- lora_name + - Lora 名称参数很重要,因为它标识将用于修改的 Lora 文件。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- strength_model + - 模型强度参数影响 Lora 对模型的效应强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- strength_clip + - 剪辑强度参数控制 Lora 对剪辑的效应强度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- MODEL + - 已使用选定的 Lora 处理的修改后的模型。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- CLIP + - 已使用选定的 Lora 处理的修改后的剪辑。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- show_help + - 提供指向节点帮助文档链接的字符串。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_LoraLoader: + + def __init__(self): + self.loaded_lora = None + + @classmethod + def INPUT_TYPES(s): + file_list = folder_paths.get_filename_list('loras') + file_list.insert(0, 'None') + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'switch': (['On', 'Off'],), 'lora_name': (file_list,), 'strength_model': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'strength_clip': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01})}} + RETURN_TYPES = ('MODEL', 'CLIP', 'STRING') + RETURN_NAMES = ('MODEL', 'CLIP', 'show_help') + FUNCTION = 'load_lora' + CATEGORY = icons.get('Comfyroll/LoRA') + + def load_lora(self, model, clip, switch, lora_name, strength_model, strength_clip): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/LoRA-Nodes#cr-load-lora' + if strength_model == 0 and strength_clip == 0: + return (model, clip, show_help) + if switch == 'Off' or lora_name == 'None': + return (model, clip, show_help) + lora_path = folder_paths.get_full_path('loras', lora_name) + lora = None + if self.loaded_lora is not None: + if self.loaded_lora[0] == lora_path: + lora = self.loaded_lora[1] + else: + del self.loaded_lora + if lora is None: + lora = comfy.utils.load_torch_file(lora_path, safe_load=True) + self.loaded_lora = (lora_path, lora) + (model_lora, clip_lora) = comfy.sd.load_lora_for_models(model, clip, lora, strength_model, strength_clip) + return (model_lora, clip_lora, show_help) +``` \ No newline at end of file diff --git a/docs/CR Load Schedule From File.md b/docs/CR Load Schedule From File.md new file mode 100644 index 0000000..5d214c5 --- /dev/null +++ b/docs/CR Load Schedule From File.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: CR_LoadScheduleFromFile +- Category: Comfyroll/Animation/Schedule +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_LoadScheduleFromFile 是一个用于从文件导入调度数据的节点,它便于管理和组织动画序列。它充当文件系统和动画工作流程之间的桥梁,允许用户将关键帧或提示数据加载并解析成可在动画流程中进一步处理的可用格式。 + +# Input types +## Required +- input_file_path + - input_file_path 参数指定了调度文件所在的目录。这对于节点正确识别和访问包含调度数据的文件至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- file_name + - file_name 参数表示要加载的调度文件的名称。它在文件识别中起着重要作用,对于节点处理正确的数据集至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- file_extension + - file_extension 参数确定调度文件的格式,允许节点应用正确的解析方法。它是确保数据被准确读取和解释的重要因素。 + - Comfy dtype: COMBO['txt', 'csv'] + - Python dtype: str + +# Output types +- SCHEDULE + - SCHEDULE 输出提供了调度文件解析后的内容,可在动画环境中使用。它代表了从文件中提取的结构化数据。 + - Comfy dtype: STRING + - Python dtype: List[List[str]] +- show_text + - show_text 输出提供了解析后的调度数据的文本表示,可用于应用程序中的显示或调试目的。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_LoadScheduleFromFile: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input_file_path': ('STRING', {'multiline': False, 'default': ''}), 'file_name': ('STRING', {'multiline': False, 'default': ''}), 'file_extension': (['txt', 'csv'],)}} + RETURN_TYPES = ('SCHEDULE', 'STRING') + RETURN_NAMES = ('SCHEDULE', 'show_text') + FUNCTION = 'csvinput' + CATEGORY = icons.get('Comfyroll/Animation/Schedule') + + def csvinput(self, input_file_path, file_name, file_extension): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Schedule-Nodes#cr-load-schedule-from-file' + filepath = input_file_path + '\\' + file_name + '.' + file_extension + print(f'CR Load Schedule From File: Loading {filepath}') + lists = [] + if file_extension == 'csv': + with open(filepath, 'r') as csv_file: + reader = csv.reader(csv_file) + for row in reader: + lists.append(row) + else: + with open(filepath, 'r') as txt_file: + for row in txt_file: + parts = row.strip().split(',', 1) + if len(parts) >= 2: + second_part = parts[1].strip('"') + lists.append([parts[0], second_part]) + return (lists, str(lists)) +``` \ No newline at end of file diff --git a/docs/CR Load Scheduled LoRAs.md b/docs/CR Load Scheduled LoRAs.md new file mode 100644 index 0000000..6277812 --- /dev/null +++ b/docs/CR Load Scheduled LoRAs.md @@ -0,0 +1,129 @@ +# Documentation +- Class name: CR_LoadScheduledLoRAs +- Category: Comfyroll/Animation/Schedulers +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_LoadScheduledLoRAs 是一个用于管理和应用预定计划的 LoRAs(低秩适应)到模型和剪辑的节点。它允许用户指定操作模式,包括禁该功能、加载默认 LoRA 或遵循自定义计划的选项。该节点根据当前帧动态选择适当的 LoRA,确保根据用户的计划增强或修改模型和剪辑。 + +# Input types +## Required +- mode + - 模式参数决定了节点如何处理LoRA加载。它可以设置为关闭、加载默认LoRA或根据计划加载。 + - Comfy dtype: COMBO + - Python dtype: str +- model + - 需要处理的模型。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - 需要处理的clip。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- current_frame + - 当前的帧数,用于确定根据计划加载哪个LoRA。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- schedule_alias + - 计划别名,用于快速选择一组预定义的LoRA加载计划。 + - Comfy dtype: STRING + - Python dtype: str +- default_lora + - 当没有为当前帧指定LoRA时,将使用的默认LoRA名称。 + - Comfy dtype: STRING + - Python dtype: str +- strength_model + - 模型的强度因子,用于调整LoRA对模型的影响程度。 + - Comfy dtype: FLOAT + - Python dtype: float +- strength_clip + - clip的强度因子,用于调整LoRA对clip的影响程度。 + - Comfy dtype: FLOAT + - Python dtype: float +- schedule_format + - 计划的格式,决定了如何解析和应用LoRA加载计划。 + - Comfy dtype: COMBO + - Python dtype: str +- lora_list + - 可选的LoRA列表,提供了一系列的LoRA选项供计划选择。 + - Comfy dtype: LORA_LIST + - Python dtype: List[str] +- schedule + - 自定义的LoRA加载计划,详细指定了每一帧应加载的LoRA及其参数。 + - Comfy dtype: SCHEDULE + - Python dtype: List[Tuple[str, str]] + +# Output types +- MODEL + - 处理后的模型,可能已经应用了LoRA。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- CLIP + - 处理后的clip,可能已经应用了LoRA。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- show_help + - 提供帮助文档的链接,供用户查阅更多关于如何使用该节点的信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_LoadScheduledLoRAs: + + @classmethod + def INPUT_TYPES(s): + modes = ['Off', 'Load default LoRA', 'Schedule'] + return {'required': {'mode': (modes,), 'model': ('MODEL',), 'clip': ('CLIP',), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'schedule_alias': ('STRING', {'default': '', 'multiline': False}), 'default_lora': (folder_paths.get_filename_list('loras'),), 'strength_model': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'strength_clip': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'schedule_format': (['CR', 'Deforum'],)}, 'optional': {'lora_list': ('LORA_LIST',), 'schedule': ('SCHEDULE',)}} + RETURN_TYPES = ('MODEL', 'CLIP', 'STRING') + RETURN_NAMES = ('MODEL', 'CLIP', 'show_help') + FUNCTION = 'schedule' + CATEGORY = icons.get('Comfyroll/Animation/Schedulers') + + def schedule(self, mode, model, clip, current_frame, schedule_alias, default_lora, strength_model, strength_clip, schedule_format, lora_list=None, schedule=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-load-scheduled-loras' + if mode == 'Off': + print(f'[Info] CR Load Scheduled LoRAs. Disabled.') + return (model, clip, show_help) + if mode == 'Load default LoRA': + if default_lora == None: + return (model, clip, show_help) + if strength_model == 0 and strength_clip == 0: + return (model, clip, show_help) + (model, clip) = LoraLoader().load_lora(model, clip, default_lora, strength_model, strength_clip) + print(f'[Info] CR Load Scheduled LoRAs. Loading default LoRA {lora_name}.') + return (model, clip, show_help) + params = keyframe_scheduler(schedule, schedule_alias, current_frame) + if params == '': + print(f'[Warning] CR Load Scheduled LoRAs. No LoRA specified in schedule for frame {current_frame}. Using default lora.') + if default_lora != None: + (model, clip) = LoraLoader().load_lora(model, clip, default_lora, strength_model, strength_clip) + return (model, clip, show_help) + else: + parts = params.split(',') + if len(parts) == 3: + s_lora_alias = parts[0].strip() + s_strength_model = float(parts[1].strip()) + s_strength_clip = float(parts[1].strip()) + else: + print(f'[Warning] CR Simple Value Scheduler. Skipped invalid line: {line}') + return () + for (l_lora_alias, l_lora_name, l_strength_model, l_strength_clip) in lora_list: + print(l_lora_alias, l_lora_name, l_strength_model, l_strength_clip) + if l_lora_alias == s_lora_alias: + print(f'[Info] CR Load Scheduled LoRAs. LoRA alias match found for {s_lora_alias}') + lora_name = l_lora_name + break + if lora_name == '': + print(f'[Info] CR Load Scheduled LoRAs. No LoRA alias match found for {s_lora_alias}. Frame {current_frame}.') + return () + else: + print(f'[Info] CR Load Scheduled LoRAs. LoRA {lora_name}') + (model, clip) = LoraLoader().load_lora(model, clip, lora_name, s_strength_model, s_strength_clip) + print(f'[Debug] CR Load Scheduled LoRAs. Loading new LoRA {lora_name}') + return (model, clip, show_help) +``` \ No newline at end of file diff --git a/docs/CR Load Scheduled Models.md b/docs/CR Load Scheduled Models.md new file mode 100644 index 0000000..d55b14e --- /dev/null +++ b/docs/CR Load Scheduled Models.md @@ -0,0 +1,107 @@ +# Documentation +- Class name: CR_LoadScheduledModels +- Category: Comfyroll/Animation/Schedulers +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_LoadScheduledModels节点旨在根据预定义的时间表管理模型的加载。它允许选择默认模型或在指定的帧动态加载不同的模型,增强了模型在各种场景下使用的灵活性和适应性。 + +# Input types +## Required +- mode + - 模式参数决定是加载默认模型还是按照时间表选择模型。它对节点的操作至关重要,因为它决定了模型的加载行为。 + - Comfy dtype: COMBO[string] + - Python dtype: str +- current_frame + - 当前帧参数指定动画或序列中的当前帧,这对于根据时间表确定要加载的模型至关重要。 + - Comfy dtype: INT + - Python dtype: int +- default_model + - 默认模型参数设置当前帧未安排特定模型时使用的后备模型。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- schedule_alias + - 时间表别名参数为节点内特定时间表提供标识符,影响节点如何解释和应用时间表以加载模型。 + - Comfy dtype: STRING + - Python dtype: str +- schedule_format + - 时间表格式参数定义了节点用于模型加载的时间表的结构和格式。 + - Comfy dtype: COMBO[string] + - Python dtype: str +- model_list + - 模型列表参数包含具有各自别名的模型列表,用于根据时间表别名匹配和加载模型。 + - Comfy dtype: MODEL_LIST + - Python dtype: List[Tuple[str, str]] +- schedule + - 时间表参数代表要在特定帧加载的模型的实际时间表,指导节点的操作。 + - Comfy dtype: SCHEDULE + - Python dtype: str + +# Output types +- MODEL + - MODEL输出提供基于时间表或默认设置加载的模型,这是节点功能的核心。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- CLIP + - CLIP输出与上下文图像处理模型相关联,该模型补充了主模型在理解和生成图像方面的功能。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- VAE + - VAE输出代表变分自编码器组件,这对于模型生成新数据点的能力至关重要。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- show_help + - show_help输出提供了文档的URL,以便在使用节点时提供进一步的帮助和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_LoadScheduledModels: + + @classmethod + def INPUT_TYPES(s): + modes = ['Load default Model', 'Schedule'] + return {'required': {'mode': (modes,), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'schedule_alias': ('STRING', {'default': '', 'multiline': False}), 'default_model': (folder_paths.get_filename_list('checkpoints'),), 'schedule_format': (['CR', 'Deforum'],)}, 'optional': {'model_list': ('MODEL_LIST',), 'schedule': ('SCHEDULE',)}} + RETURN_TYPES = ('MODEL', 'CLIP', 'VAE', 'STRING') + RETURN_NAMES = ('MODEL', 'CLIP', 'VAE', 'show_help') + FUNCTION = 'schedule' + CATEGORY = icons.get('Comfyroll/Animation/Schedulers') + + def schedule(self, mode, current_frame, schedule_alias, default_model, schedule_format, model_list=None, schedule=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-load-scheduled-models' + if mode == 'Load default Model': + ckpt_path = folder_paths.get_full_path('checkpoints', default_model) + out = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths('embeddings')) + print(f'[Debug] CR Load Scheduled Models. Loading default model.') + return (out[:3], show_help) + params = keyframe_scheduler(schedule, schedule_alias, current_frame) + if params == '': + print(f'[Warning] CR Load Scheduled Models. No model specified in schedule for frame {current_frame}. Using default model.') + ckpt_path = folder_paths.get_full_path('checkpoints', default_model) + out = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths('embeddings')) + return (out[:3], show_help) + else: + try: + model_alias = str(params) + except ValueError: + print(f'[Warning] CR Load Scheduled Models. Invalid params: {params}') + return () + for (ckpt_alias, ckpt_name) in model_list: + if ckpt_alias == model_alias: + model_name = ckpt_name + break + if model_name == '': + print(f'[Info] CR Load Scheduled Models. No model alias match found for {model_alias}. Frame {current_frame} will produce an error.') + return () + else: + print(f'[Info] CR Load Scheduled Models. Model alias {model_alias} matched to {model_name}') + ckpt_path = folder_paths.get_full_path('checkpoints', model_name) + out = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths('embeddings')) + print(f'[Info] CR Load Scheduled Models. Loading new checkpoint model {model_name}') + return (out[:3], show_help) +``` \ No newline at end of file diff --git a/docs/CR Load Text List.md b/docs/CR Load Text List.md new file mode 100644 index 0000000..62383ef --- /dev/null +++ b/docs/CR Load Text List.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: CR_LoadTextList +- Category: List +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_LoadTextList节点旨在将文本数据从文件加载到列表格式中。它能够处理CSV和TXT文件扩展名,为进一步处理提供了一种多功能的方式来吸收文本信息。此节点在数据准备中扮演着关键角色,适用于需要文本输入的各种应用。 + +# Input types +## Required +- input_file_path + - input_file_path参数指定了文本文件所在的目录。这对于节点成功定位和读取文件至关重要,因此影响节点的执行和加载的文本数据列表的结果。 + - Comfy dtype: STRING + - Python dtype: str +- file_name + - file_name参数表示要加载的文本文件的名称,不包括其扩展名。它是识别给定目录中特定文件的关键组件,影响节点的操作和加载的文本数据。 + - Comfy dtype: STRING + - Python dtype: str +- file_extension + - file_extension参数指示要加载的文本文件类型,可以是'txt'或'csv'。这个选择决定了节点处理文件的方式,影响结果文本列表的结构和格式。 + - Comfy dtype: COMBO['txt', 'csv'] + - Python dtype: Literal['txt', 'csv'] + +# Output types +- list + - list输出参数表示以字符串列表形式组织的加载的文本数据。每个元素对应文本文件中的一行,提供了一种直接的方式来访问和操作文本数据。 + - Comfy dtype: STRING + - Python dtype: List[str] +- show_help + - show_help输出提供了一个文档URL,用于进一步的帮助。对于寻求有关节点使用和功能的更多信息的用户来说,这非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_LoadTextList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input_file_path': ('STRING', {'multiline': False, 'default': ''}), 'file_name': ('STRING', {'multiline': False, 'default': ''}), 'file_extension': (['txt', 'csv'],)}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + OUTPUT_IS_LIST = (True, False) + FUNCTION = 'load_list' + CATEGORY = icons.get('Comfyroll/List') + + def load_list(self, input_file_path, file_name, file_extension): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-load-value-list' + filepath = input_file_path + '\\' + file_name + '.' + file_extension + print(f'CR Load Values: Loading {filepath}') + list = [] + if file_extension == 'csv': + with open(filepath, 'r') as csv_file: + for row in csv_file: + list.append(row) + elif file_extension == 'txt': + with open(filepath, 'r') as txt_file: + for row in txt_file: + list.append(row) + else: + pass + return (list, show_help) +``` \ No newline at end of file diff --git a/docs/CR Mask Text.md b/docs/CR Mask Text.md new file mode 100644 index 0000000..ba2fdfb --- /dev/null +++ b/docs/CR Mask Text.md @@ -0,0 +1,107 @@ +# Documentation +- Class name: CR_MaskText +- Category: Graphics/Text +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_MaskText节点旨在以风格化的方式将文本叠加到图像上。它允许自定义字体、大小、颜色和位置,以创建视觉上吸引人的文本覆盖。该节点强调将文本集成在图形元素中,旨在增强图像的整体美感。 + +# Input types +## Required +- image + - 将被遮罩文本的图像。它作为整个操作的基础,文本将直接应用在它上面。图像的选择对最终视觉效果有重要影响。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- text + - 要被遮罩到图像上的文本内容。文本的内容和结构可以极大地改变最终图像传达的信息,使其成为节点功能的关键参数。 + - Comfy dtype: STRING + - Python dtype: str +- font_name + - 用于渲染文本的特定字体文件。不同的字体可以极大地改变文本的风格和可读性,因此在节点执行中扮演着重要角色。 + - Comfy dtype: STRING + - Python dtype: str +- font_size + - 用于文本的字体大小。字体大小直接影响图像中文本的可读性和显著性。 + - Comfy dtype: INT + - Python dtype: int +- background_color + - 文本背后背景的颜色。这可以是预定义的颜色或自定义的十六进制颜色,影响文本覆盖的对比度和视觉吸引力。 + - Comfy dtype: STRING + - Python dtype: str +- align + - 文本的水平对齐方式。它决定了文本在图像宽度内的定位,影响整体布局。 + - Comfy dtype: STRING + - Python dtype: str +- justify + - 文本的对齐方式。它控制单词之间的间距,影响文本块外观的均匀性。 + - Comfy dtype: STRING + - Python dtype: str +- margins + - 文本周围的空间,即边距。它在文本周围增加了一个缓冲区域,这对于文本的可见性和图像的构图可能很重要。 + - Comfy dtype: INT + - Python dtype: int +- line_spacing + - 文本行之间的垂直空间。它影响多行文本的可读性和整体紧凑性。 + - Comfy dtype: INT + - Python dtype: int +- position_x + - 文本从图像左边缘的水平位置。对于在图像内精确放置文本至关重要。 + - Comfy dtype: INT + - Python dtype: int +- position_y + - 文本从图像顶部边缘的垂直位置。它与水平位置结合使用,以精确放置文本。 + - Comfy dtype: INT + - Python dtype: int +- rotation_angle + - 文本旋转的角度。它提供了以各种方向定位文本的方法,为图像增添了动态元素。 + - Comfy dtype: FLOAT + - Python dtype: float +- rotation_options + - 确定旋转支点的位置,可以是文本中心或图像中心。这影响文本的方向如何相对于图像被感知。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- bg_color_hex + - 背景的自定义十六进制颜色。它允许进一步自定义文本的背景,增强了节点功能的灵活性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - 应用了遮罩文本的输出图像。它是节点处理的结果,代表了最终的视觉产品。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - 指向文档的URL链接,用于进一步帮助。它为用户提供了额外的资源,以理解和排除节点功能的故障。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_MaskText: + + @classmethod + def INPUT_TYPES(s): + font_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'fonts') + file_list = [f for f in os.listdir(font_dir) if os.path.isfile(os.path.join(font_dir, f)) and f.lower().endswith('.ttf')] + return {'required': {'image': ('IMAGE',), 'text': ('STRING', {'multiline': True, 'default': 'text'}), 'font_name': (file_list,), 'font_size': ('INT', {'default': 50, 'min': 1, 'max': 1024}), 'background_color': (COLORS,), 'align': (ALIGN_OPTIONS,), 'justify': (JUSTIFY_OPTIONS,), 'margins': ('INT', {'default': 0, 'min': -1024, 'max': 1024}), 'line_spacing': ('INT', {'default': 0, 'min': -1024, 'max': 1024}), 'position_x': ('INT', {'default': 0, 'min': -4096, 'max': 4096}), 'position_y': ('INT', {'default': 0, 'min': -4096, 'max': 4096}), 'rotation_angle': ('FLOAT', {'default': 0.0, 'min': -360.0, 'max': 360.0, 'step': 0.1}), 'rotation_options': (ROTATE_OPTIONS,)}, 'optional': {'bg_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'mask_text' + CATEGORY = icons.get('Comfyroll/Graphics/Text') + + def mask_text(self, image, text, font_name, font_size, margins, line_spacing, position_x, position_y, background_color, align, justify, rotation_angle, rotation_options, bg_color_hex='#000000'): + bg_color = get_color_values(background_color, bg_color_hex, color_mapping) + image_3d = image[0, :, :, :] + text_image = tensor2pil(image_3d) + text_mask = Image.new('L', text_image.size) + background_image = Image.new('RGB', text_mask.size, bg_color) + rotated_text_mask = draw_masked_text(text_mask, text, font_name, font_size, margins, line_spacing, position_x, position_y, align, justify, rotation_angle, rotation_options) + text_mask = ImageOps.invert(rotated_text_mask) + image_out = Image.composite(background_image, text_image, text_mask) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Text-Nodes#cr-mask-text' + return (pil2tensor(image_out), show_help) +``` \ No newline at end of file diff --git a/docs/CR Math Operation.md b/docs/CR Math Operation.md new file mode 100644 index 0000000..1c3fef8 --- /dev/null +++ b/docs/CR Math Operation.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: CR_MathOperation +- Category: Comfyroll/Utils/Other +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_MathOperation 节点旨在对给定输入值执行多种数学运算。它抽象了数学函数的复杂性,使用户能够轻松应用正弦、余弦和对数等运算。该节点强调简单易用性,确保数学转换易于访问,而无需深入了解底层算法细节。 + +# Input types +## Required +- a + - 参数 'a' 表示将执行数学运算的输入值。它是节点功能的核心,因为它直接影响运算的结果。这个值的选择可以显著影响结果,使其成为节点执行的关键组成部分。 + - Comfy dtype: FLOAT + - Python dtype: float +- operation + - 参数 'operation' 指示将应用于输入值的数学函数。它至关重要,因为它决定了将发生的变换类型。选择一个操作对于实现节点执行的预期结果是关键的。 + - Comfy dtype: COMBO['sin', 'cos', 'tan', 'sqrt', 'exp', 'log', 'neg', 'abs'] + - Python dtype: str +- decimal_places + - 参数 'decimal_places' 指定结果将被四舍五入到的小数位数。它在确定输出精度方面起着关键作用,允许用户控制最终结果的细节水平。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- a + - 输出 'a' 提供了数学运算结果在被四舍五入到指定小数位数后的值。它很重要,因为它代表了节点处理的最终结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- show_help + - 输出 'show_help' 提供了指向节点文档页面的 URL 链接,为用户提供了关于如何有效使用该节点的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_MathOperation: + + @classmethod + def INPUT_TYPES(cls): + operations = ['sin', 'cos', 'tan', 'sqrt', 'exp', 'log', 'neg', 'abs'] + return {'required': {'a': ('FLOAT', {'default': 1.0}), 'operation': (operations,), 'decimal_places': ('INT', {'default': 2, 'min': 0, 'max': 10})}} + RETURN_TYPES = ('FLOAT', 'STRING') + RETURN_NAMES = ('a', 'show_help') + FUNCTION = 'do_math' + CATEGORY = icons.get('Comfyroll/Utils/Other') + + def do_math(self, a, operation, decimal_places): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-math-operation' + if operation == 'sin': + result = math.sin(a) + elif operation == 'cos': + result = math.cos(a) + elif operation == 'tan': + result = math.cos(a) + elif operation == 'sqrt': + result = math.sqrt(a) + elif operation == 'exp': + result = math.exp(a) + elif operation == 'log': + result = math.log(a) + elif operation == 'neg': + result = -a + elif operation == 'abs': + result = abs(a) + else: + raise ValueError('CR Math Operation: Unsupported operation.') + result = round(result, decimal_places) + return (result, show_help) +``` \ No newline at end of file diff --git a/docs/CR Model Input Switch.md b/docs/CR Model Input Switch.md new file mode 100644 index 0000000..00dff41 --- /dev/null +++ b/docs/CR Model Input Switch.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CR_ModelInputSwitch +- Category: Comfyroll/Utils/Logic +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ModelInputSwitch 节点旨在根据输入值在两个提供的模型之间进行选择。它在工作流中简化模型选择过程方面发挥关键作用,允许在没有复杂分支逻辑的情况下进行条件模型署。 + +# Input types +## Required +- Input + - ‘Input’ 参数对于决定选择哪个模型至关重要。它指导节点的逻辑根据其值选择 ‘model1’ 或 ‘model2’,从而影响节点的输出。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- model1 + - ‘model1’ 参数代表节点可以选择的第一个模型。当 ‘Input’ 参数设置为 1 时,它是一个可选输入,变得重要。 + - Comfy dtype: MODEL + - Python dtype: Any +- model2 + - ‘model2’ 参数代表节点可以选择的第二个模型。当 ‘Input’ 参数不等于 1 时,它被考虑,在这种情况下决定输出。 + - Comfy dtype: MODEL + - Python dtype: Any + +# Output types +- MODEL + - ‘MODEL’ 输出是基于 ‘Input’ 参数选择的模型。它代表了节点关于提供哪个模型的决策过程的结果。 + - Comfy dtype: MODEL + - Python dtype: Any +- show_help + - ‘show_help’ 输出提供了指向节点文档的 URL,提供关于如何有效使用节点的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ModelInputSwitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': ('INT', {'default': 1, 'min': 1, 'max': 2})}, 'optional': {'model1': ('MODEL',), 'model2': ('MODEL',)}} + RETURN_TYPES = ('MODEL', 'STRING') + RETURN_NAMES = ('MODEL', 'show_help') + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Utils/Logic') + + def switch(self, Input, model1=None, model2=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Logic-Nodes#cr-model-input-switch' + if Input == 1: + return (model1, show_help) + else: + return (model2, show_help) +``` \ No newline at end of file diff --git a/docs/CR Model List.md b/docs/CR Model List.md new file mode 100644 index 0000000..799db30 --- /dev/null +++ b/docs/CR Model List.md @@ -0,0 +1,87 @@ +# Documentation +- Class name: CR_ModelList +- Category: Comfyroll/Animation/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ModelList节点旨在管理和编译模型列表,每个模型都与一个检查点文件和一个别名相关联。它便于组织和检索模型检查点,以便进一步处理或动画任务。该节点通过使用户能够指定多个检查点及其相应的别名,从而在模型管理中发挥关键作用,提高了工作流程的效率。 + +# Input types +## Required +- ckpt_name1 + - ckpt_name1参数对于识别与模型相关联的第一个检查点文件至关重要。它是节点操作的关键组成部分,因为它直接影响列表中模型检查点的选择和组织。 + - Comfy dtype: STRING + - Python dtype: str +- alias1 + - alias1作为第一个检查点的替代名称或标识符,允许在模型列表中更容易地引用和管理。它通过为检查点提供用户友好的命名约定,增强了节点的功能。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- ckpt_name2 + - ckpt_name2参数是可选的,可以用来指定模型列表中的第二个检查点文件。它通过允许在模型管理过程中包含额外的检查点,扩展了节点的能力。 + - Comfy dtype: STRING + - Python dtype: str +- alias2 + - alias2是一个可选参数,它为第二个检查点提供替代名称,通过为检查点提供可定制的命名选项,增强了节点的灵活性和用户友好性。 + - Comfy dtype: STRING + - Python dtype: str +- model_list + - model_list参数是可选的,允许用户输入一个预先存在的模型列表。这个参数通过使外部模型列表能够集成到节点的操作中,增强了节点的适应性。 + - Comfy dtype: MODEL_LIST + - Python dtype: List[Tuple[str, str]] + +# Output types +- MODEL_LIST + - MODEL_LIST输出参数代表了编译后的模型列表,包括与之相关的检查点和别名。它是一个重要的输出,因为它涵盖了节点组织和管理模型检查点的主要功能。 + - Comfy dtype: MODEL_LIST + - Python dtype: List[Tuple[str, str]] +- show_text + - show_text输出参数提供了模型列表的文本表示,这对于显示或记录目的非常有用。它反映了节点生成模型检查点的人类可读摘要的能力。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ModelList: + + @classmethod + def INPUT_TYPES(cls): + checkpoint_files = ['None'] + folder_paths.get_filename_list('checkpoints') + return {'required': {'ckpt_name1': (checkpoint_files,), 'alias1': ('STRING', {'multiline': False, 'default': ''}), 'ckpt_name2': (checkpoint_files,), 'alias2': ('STRING', {'multiline': False, 'default': ''}), 'ckpt_name3': (checkpoint_files,), 'alias3': ('STRING', {'multiline': False, 'default': ''}), 'ckpt_name4': (checkpoint_files,), 'alias4': ('STRING', {'multiline': False, 'default': ''}), 'ckpt_name5': (checkpoint_files,), 'alias5': ('STRING', {'multiline': False, 'default': ''})}, 'optional': {'model_list': ('MODEL_LIST',)}} + RETURN_TYPES = ('MODEL_LIST', 'STRING') + RETURN_NAMES = ('MODEL_LIST', 'show_text') + FUNCTION = 'model_list' + CATEGORY = icons.get('Comfyroll/Animation/Legacy') + + def model_list(self, ckpt_name1, alias1, ckpt_name2, alias2, ckpt_name3, alias3, ckpt_name4, alias4, ckpt_name5, alias5, model_list=None): + models = list() + model_text = list() + if model_list is not None: + models.extend([l for l in model_list if l[0] != None]) + model_text += '\n'.join(map(str, model_list)) + '\n' + if ckpt_name1 != 'None': + model1_tup = [(alias1, ckpt_name1)] + (models.extend(model1_tup),) + model_text += '\n'.join(map(str, model1_tup)) + '\n' + if ckpt_name2 != 'None': + model2_tup = [(alias2, ckpt_name2)] + (models.extend(model2_tup),) + model_text += '\n'.join(map(str, model2_tup)) + '\n' + if ckpt_name3 != 'None': + model3_tup = [(alias3, ckpt_name3)] + (models.extend(model3_tup),) + model_text += '\n'.join(map(str, model3_tup)) + '\n' + if ckpt_name4 != 'None': + model4_tup = [(alias4, ckpt_name4)] + (models.extend(model4_tup),) + model_text += '\n'.join(map(str, model4_tup)) + '\n' + if ckpt_name5 != 'None': + model5_tup = [(alias5, ckpt_name5)] + (models.extend(model5_tup),) + model_text += '\n'.join(map(str, model5_tup)) + '\n' + show_text = ''.join(model_text) + return (models, show_text) +``` \ No newline at end of file diff --git a/docs/CR Model Merge Stack.md b/docs/CR Model Merge Stack.md new file mode 100644 index 0000000..582a1db --- /dev/null +++ b/docs/CR Model Merge Stack.md @@ -0,0 +1,103 @@ +# Documentation +- Class name: CR_ModelMergeStack +- Category: Comfyroll/Model Merge +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ModelMergeStack节点旨在将多个模型检查点合并为一个统一的栈。它允许用户切换包含每个检查点,并调整模型和剪辑组件的贡献比例,为基于特定需求合并不同模型提供了灵活的方法。 + +# Input types +## Required +- switch_1 + - switch_1参数决定是否将第一个检查点包含在模型栈中。它在节点的操作中起着关键作用,通过启用或禁用特定检查点的集成来发挥作用。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +- ckpt_name1 + - ckpt_name1参数指定要潜在包含在模型栈中的第一个检查点文件的名称。这对于识别要合并的特定模型至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- model_ratio1 + - model_ratio1参数调整第一个检查点的模型组件在合并栈中的贡献权重。它对于微调每个模型在最终输出中的影响很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- clip_ratio1 + - clip_ratio1参数设置第一个检查点的剪辑组件的贡献权重。它对于平衡剪辑指导在合并模型栈中的整体影响很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- switch_2 + - switch_2参数控制第二个检查点是否包含在模型栈中。与switch_1类似,它对于选择哪些检查点被集成到最终栈中至关重要。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +- ckpt_name2 + - ckpt_name2参数识别可能包含在模型栈中的第二个检查点文件。它是确定要合并的模型的关键因素。 + - Comfy dtype: STRING + - Python dtype: str +- model_ratio2 + - model_ratio2参数修改第二个检查点的模型组件在栈中的权重。它影响该模型的特征在合并输出中的显著程度。 + - Comfy dtype: FLOAT + - Python dtype: float +- clip_ratio2 + - clip_ratio2参数定义第二个检查点的剪辑组件的权重,影响剪辑指导在合并的模型栈中被考虑的程度。 + - Comfy dtype: FLOAT + - Python dtype: float +- switch_3 + - switch_3参数决定是否将第三个检查点包含在模型栈中。它是控制最终栈组成的另一个关键开关。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +- ckpt_name3 + - ckpt_name3参数指定可能是模型栈一部分的第三个检查点文件。将特定模型包含在合并过程中至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- model_ratio3 + - model_ratio3参数调整第三个检查点的模型组件在合并栈中的影响。它对模型贡献的总体平衡很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- clip_ratio3 + - clip_ratio3参数设置第三个检查点的剪辑组件在栈中的影响水平。它对合并模型栈中剪辑指导的最终混合很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- model_stack + - 可选的model_stack参数允许用户提供一个要合并的初始模型列表。它对于在现有模型栈的基础上构建很有用。 + - Comfy dtype: MODEL_STACK + - Python dtype: List[Tuple[str, float, float]] + +# Output types +- MODEL_STACK + - MODEL_STACK输出包含具有各自比率的合并模型检查点列表。它是节点操作的主要结果,代表了合并的模型栈。 + - Comfy dtype: MODEL_STACK + - Python dtype: List[Tuple[str, float, float]] +- show_help + - show_help输出提供了一个指向文档的URL链接,以获取更多帮助。它将用户引导到外部资源,以获取有关节点功能更多信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ModelMergeStack: + + @classmethod + def INPUT_TYPES(cls): + checkpoint_files = ['None'] + folder_paths.get_filename_list('checkpoints') + return {'required': {'switch_1': (['Off', 'On'],), 'ckpt_name1': (checkpoint_files,), 'model_ratio1': ('FLOAT', {'default': 1.0, 'min': -100.0, 'max': 100.0, 'step': 0.01}), 'clip_ratio1': ('FLOAT', {'default': 1.0, 'min': -100.0, 'max': 100.0, 'step': 0.01}), 'switch_2': (['Off', 'On'],), 'ckpt_name2': (checkpoint_files,), 'model_ratio2': ('FLOAT', {'default': 1.0, 'min': -100.0, 'max': 100.0, 'step': 0.01}), 'clip_ratio2': ('FLOAT', {'default': 1.0, 'min': -100.0, 'max': 100.0, 'step': 0.01}), 'switch_3': (['Off', 'On'],), 'ckpt_name3': (checkpoint_files,), 'model_ratio3': ('FLOAT', {'default': 1.0, 'min': -100.0, 'max': 100.0, 'step': 0.01}), 'clip_ratio3': ('FLOAT', {'default': 1.0, 'min': -100.0, 'max': 100.0, 'step': 0.01})}, 'optional': {'model_stack': ('MODEL_STACK',)}} + RETURN_TYPES = ('MODEL_STACK', 'STRING') + RETURN_NAMES = ('MODEL_STACK', 'show_help') + FUNCTION = 'list_checkpoints' + CATEGORY = icons.get('Comfyroll/Model Merge') + + def list_checkpoints(self, switch_1, ckpt_name1, model_ratio1, clip_ratio1, switch_2, ckpt_name2, model_ratio2, clip_ratio2, switch_3, ckpt_name3, model_ratio3, clip_ratio3, model_stack=None): + model_list = list() + if model_stack is not None: + model_list.extend([l for l in model_stack if l[0] != 'None']) + if ckpt_name1 != 'None' and switch_1 == 'On': + (model_list.extend([(ckpt_name1, model_ratio1, clip_ratio1)]),) + if ckpt_name2 != 'None' and switch_2 == 'On': + (model_list.extend([(ckpt_name2, model_ratio2, clip_ratio2)]),) + if ckpt_name3 != 'None' and switch_3 == 'On': + (model_list.extend([(ckpt_name3, model_ratio3, clip_ratio3)]),) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Model-Merge-Nodes#cr-model-stack' + return (model_list, show_help) +``` \ No newline at end of file diff --git a/docs/CR Module Input.md b/docs/CR Module Input.md new file mode 100644 index 0000000..43701e6 --- /dev/null +++ b/docs/CR Module Input.md @@ -0,0 +1,81 @@ +# Documentation +- Class name: CR_ModuleInput +- Category: Comfyroll/Pipe/Module +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ModuleInput 是一个用于处理和处理模块输入数据的节点。它在初始化和管理数据通过系统流动中起着关键作用,确保必要的组件被输入到模块操作的后续阶段。 + +# Input types +## Required +- pipe + - “pipe”参数是必需的,因为它代表了节点操作的主要数据结构。正是通过这个参数,节点接收输入数据,然后这些数据在模块的工作流程中被处理和使用。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple[Any, ...] + +# Output types +- pipe + - “pipe”输出是数据流的延续,封装了输入阶段的所有处理信息。它作为数据传递给后续节点或模块组件的通道。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple[Any, ...] +- model + - “model”输出表示节点在模块操作中可能使用的机器学习或AI模型。它是模块设计执行的任何预测或分析任务的关键组件。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- pos + - “pos”输出代表正面条件数据,可用于引导模块内的生成或处理朝着更有利的结果发展。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- neg + - “neg”输出表示负面条件数据,用于引导模块的操作远离不希望的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- latent + - “latent”输出指的是数据的潜在空间表示,在许多机器学习模型中是一个关键概念,特别是在生成模型的上下文中。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- vae + - “vae”输出与模块中的变分自编码器组件相关,它在编码和解码潜在空间内的信息中起着重要作用。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- clip + - “clip”输出涉及模块内CLIP模型的集成,它有助于将生成的内容与文本描述对齐。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- controlnet + - “controlnet”输出代表了模块内的控制网络,它负责管理生成过程的方向和重点。 + - Comfy dtype: CONTROL_NET + - Python dtype: torch.nn.Module +- image + - “image”输出是数据的视觉表示,通常是模块图像生成或处理任务的最终结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- seed + - “seed”输出提供了用于初始化随机数生成器的随机数或种子,确保随机过程中的可重复性。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - “show_help”输出是指向节点文档的URL链接,为用户提供了如何有效使用该节点的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ModuleInput: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',)}} + RETURN_TYPES = ('PIPE_LINE', 'MODEL', 'CONDITIONING', 'CONDITIONING', 'LATENT', 'VAE', 'CLIP', 'CONTROL_NET', 'IMAGE', 'INT', 'STRING') + RETURN_NAMES = ('pipe', 'model', 'pos', 'neg', 'latent', 'vae', 'clip', 'controlnet', 'image', 'seed', 'show_help') + FUNCTION = 'flush' + CATEGORY = icons.get('Comfyroll/Pipe/Module') + + def flush(self, pipe): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pipe-Nodes#cr-module-input' + (model, pos, neg, latent, vae, clip, controlnet, image, seed) = pipe + return (pipe, model, pos, neg, latent, vae, clip, controlnet, image, seed, show_help) +``` \ No newline at end of file diff --git a/docs/CR Module Output.md b/docs/CR Module Output.md new file mode 100644 index 0000000..7fe5cb7 --- /dev/null +++ b/docs/CR Module Output.md @@ -0,0 +1,101 @@ +# Documentation +- Class name: CR_ModuleOutput +- Category: Comfyroll/Pipe/Module +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ModuleOutput是一个旨在管理和修改流水线输出的节点,确保根据特定条件和输入来指导和优化数据流。 + +# Input types +## Required +- pipe + - pipe参数是必要的,因为它代表了正在被节点处理和转换的主要数据流。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple +## Optional +- model + - model参数允许调整流水线中的底层模型,影响节点的处理能力。 + - Comfy dtype: MODEL + - Python dtype: Any +- pos + - pos参数作为一个调节输入,根据积极强化或期望的结果来精炼输出。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- neg + - neg参数引入了负面调节,使节点能够避免输出中不希望的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- latent + - latent参数用于将潜变量纳入节点的操作中,为输出增加了复杂性和细微差别。 + - Comfy dtype: LATENT + - Python dtype: Any +- vae + - vae参数用于整合变分自编码器功能,增强节点处理无监督学习任务的能力。 + - Comfy dtype: VAE + - Python dtype: Any +- clip + - clip参数使节点能够应用CLIP模型特性,提高输出中的上下文理解和生成能力。 + - Comfy dtype: CLIP + - Python dtype: Any +- controlnet + - controlnet参数用于引入控制机制,可以指导节点的行为并精炼其输出。 + - Comfy dtype: CONTROL_NET + - Python dtype: Any +- image + - image参数允许节点纳入视觉数据,增强输出的多模态能力。 + - Comfy dtype: IMAGE + - Python dtype: Any +- seed + - seed参数对于确保节点随机操作的可复现性和一致性至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- pipe + - 输出pipe是输入的修改版,现已优化并定制以满足节点设定的特定要求和条件。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple +- show_help + - show_help输出提供了一个参考链接到文档,以便进一步理解和指导使用该节点。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ModuleOutput: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',)}, 'optional': {'model': ('MODEL',), 'pos': ('CONDITIONING',), 'neg': ('CONDITIONING',), 'latent': ('LATENT',), 'vae': ('VAE',), 'clip': ('CLIP',), 'controlnet': ('CONTROL_NET',), 'image': ('IMAGE',), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('PIPE_LINE', 'STRING') + RETURN_NAMES = ('pipe', 'show_help') + FUNCTION = 'pipe_output' + CATEGORY = icons.get('Comfyroll/Pipe/Module') + + def pipe_output(self, pipe, model=None, pos=None, neg=None, latent=None, vae=None, clip=None, controlnet=None, image=None, seed=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pipe-Nodes#cr-module-output' + (new_model, new_pos, new_neg, new_latent, new_vae, new_clip, new_controlnet, new_image, new_seed) = pipe + if model is not None: + new_model = model + if pos is not None: + new_pos = pos + if neg is not None: + new_neg = neg + if latent is not None: + new_latent = latent + if vae is not None: + new_vae = vae + if clip is not None: + new_clip = clip + if controlnet is not None: + new_controlnet = controlnet + if image is not None: + new_image = image + if seed is not None: + new_seed = seed + pipe = (new_model, new_pos, new_neg, new_latent, new_vae, new_clip, new_controlnet, new_image, new_seed) + return (pipe, show_help) +``` \ No newline at end of file diff --git a/docs/CR Module Pipe Loader.md b/docs/CR Module Pipe Loader.md new file mode 100644 index 0000000..5af2d56 --- /dev/null +++ b/docs/CR Module Pipe Loader.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: CR_ModulePipeLoader +- Category: Comfyroll/Pipe/Module +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ModulePipeLoader 是一个旨在将各种模型和数据类型统一加载和集成到一个管道中的节点。它便于模型、潜在表示和其他条件因素的无缝处理,使得复杂的操作能够以结构化和高效的方式执行。 + +# Input types +## Optional +- model + - 模型参数对于定义节点操作的核心算法结构至关重要。它决定了要加载的模型类型,因此显著影响节点的处理能力和结果。 + - Comfy dtype: MODEL + - Python dtype: Union[str, Path] +- pos + - 正向调节输入对于需要方向性指导或增强的节点至关重要。它提供了一个正向参考,有助于将节点的功能引导至期望的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: Union[str, List[str]] +- neg + - 负向调节参数作为正向输入的平衡,允许节点通过纳入抑制信号来微调其响应并避免不希望的效果。 + - Comfy dtype: CONDITIONING + - Python dtype: Union[str, List[str]] +- latent + - 潜在表示对于处理降维或特征提取的节点至关重要。此参数使节点能够使用压缩的数据表示,提高数据处理的效率。 + - Comfy dtype: LATENT + - Python dtype: Union[torch.Tensor, List[torch.Tensor]] +- vae + - 变分自编码器(VAE)参数对于使用生成模型进行数据合成的节点至关重要。它允许节点利用VAE的能力来创建新的数据实例。 + - Comfy dtype: VAE + - Python dtype: Union[str, Path] +- clip + - CLIP参数对于使用多模态学习方法的节点至关重要,特别是涉及视觉和文本数据的任务。它使节点能够整合CLIP模型以增强跨模态交互。 + - Comfy dtype: CLIP + - Python dtype: Union[str, Path] +- controlnet + - 控制网参数对于需要结构化控制流或条件执行路径的节点至关重要。它提供了一个基于预定义条件管理节点操作逻辑的框架。 + - Comfy dtype: CONTROL_NET + - Python dtype: Union[str, Path] +- image + - 图像输入对于处理视觉数据的节点是基础性的。它允许节点摄取和操作视觉内容,这对于广泛的基于图像的应用至关重要。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, Path, PIL.Image] +- seed + - 种子参数通过为随机数生成提供固定点来确保结果的可复现性。在需要一致结果的随机过程中,它尤其重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- pipe + - 管道输出代表了构建的管道,它封装了提供给节点的所有输入和设置。它是系统内进一步处理或分析的关键组件。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple[Any, ...] +- show_help + - show_help 输出提供了指向节点文档的链接,为用户提供了如何有效使用该节点的指导。它是了解节点功能和潜在用例的重要资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ModulePipeLoader: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}, 'optional': {'model': ('MODEL',), 'pos': ('CONDITIONING',), 'neg': ('CONDITIONING',), 'latent': ('LATENT',), 'vae': ('VAE',), 'clip': ('CLIP',), 'controlnet': ('CONTROL_NET',), 'image': ('IMAGE',), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('PIPE_LINE', 'STRING') + RETURN_NAMES = ('pipe', 'show_help') + FUNCTION = 'pipe_input' + CATEGORY = icons.get('Comfyroll/Pipe/Module') + + def pipe_input(self, model=0, pos=0, neg=0, latent=0, vae=0, clip=0, controlnet=0, image=0, seed=0): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pipe-Nodes#cr-module-pipe-loader' + pipe_line = (model, pos, neg, latent, vae, clip, controlnet, image, seed) + return (pipe_line, show_help) +``` \ No newline at end of file diff --git a/docs/CR Multi Upscale Stack.md b/docs/CR Multi Upscale Stack.md new file mode 100644 index 0000000..14d6ca4 --- /dev/null +++ b/docs/CR Multi Upscale Stack.md @@ -0,0 +1,92 @@ +# Documentation +- Class name: CR_MultiUpscaleStack +- Category: Comfyroll/Upscale +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_MultiUpscaleStack 是一个旨在通过一系列上采样模型提高图像质量和分辨率的节点。它允许用户切换和选择不同的上采样模型,应用特定的重新缩放因子,并将它们的效果结合起来,以实现更优的结果。此节点对于需要高分辨率输出的任务至关重要,例如打印或在高DPI屏幕上显示。 + +# Input types +## Required +- switch_1 + - 开关参数决定第一个上采样模型是否在栈中被激活。它至关重要,因为它控制了模型在上采样过程中的包含,从而影响最终输出的质量。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- upscale_model_1 + - 选择上采样栈中使用的第一个模型。模型的选择对上采样结果有显著影响,因为不同的模型可能针对不同类型的图像或质量要求进行了优化。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- rescale_factor_1 + - 定义第一个上采样模型的缩放因子。这个参数至关重要,因为它决定了上采样的程度,直接影响结果图像的分辨率和清晰度。 + - Comfy dtype: FLOAT + - Python dtype: float +- switch_2 + - 栈中第二个模型的开关参数。它与switch_1扮演类似的角色,允许根据用户的选择有条件地应用第二个模型。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- upscale_model_2 + - 指定上采样过程中要考虑的第二个模型。选择可以改变栈的整体效果,特别是与其他模型结合使用时。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- rescale_factor_2 + - 设置第二个上采样模型的缩放因子。它与模型选择一起工作,根据用户的需求微调上采样过程。 + - Comfy dtype: FLOAT + - Python dtype: float +- switch_3 + - 控制第三个上采样模型是否包含在栈中。这个决定可以是策略性的,因为它允许选择性地提高图像质量。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- upscale_model_3 + - 识别栈中要应用的第三个上采样模型。模型的有效性可能因其与图像的兼容性以及预期结果的不同而有所不同。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- rescale_factor_3 + - 调整第三个上采样模型的缩放因子,允许精确控制栈的第三层的上采样强度。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- upscale_stack + - 一个可选参数,允许用户输入一个预先存在的上采样模型栈及其因子。这可以通过在先前的配置基础上构建来简化上采样过程。 + - Comfy dtype: UPSCALE_STACK + - Python dtype: List[Tuple[str, float]] + +# Output types +- UPSCALE_STACK + - 输出是一个结构化的列表,包含了通过节点处理激活和组合的上采样模型及其相应的重新缩放因子。这个输出很重要,因为它代表了上采样栈的最终配置。 + - Comfy dtype: UPSCALE_STACK + - Python dtype: List[Tuple[str, float]] +- show_help + - 提供文档的URL链接,以进一步协助和指导有效使用该节点。这对于新用户或需要额外信息时特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CR_MultiUpscaleStack: + + @classmethod + def INPUT_TYPES(s): + mix_methods = ['Combine', 'Average', 'Concatenate'] + up_models = ['None'] + folder_paths.get_filename_list('upscale_models') + return {'required': {'switch_1': (['On', 'Off'],), 'upscale_model_1': (up_models,), 'rescale_factor_1': ('FLOAT', {'default': 2, 'min': 0.01, 'max': 16.0, 'step': 0.01}), 'switch_2': (['On', 'Off'],), 'upscale_model_2': (up_models,), 'rescale_factor_2': ('FLOAT', {'default': 2, 'min': 0.01, 'max': 16.0, 'step': 0.01}), 'switch_3': (['On', 'Off'],), 'upscale_model_3': (up_models,), 'rescale_factor_3': ('FLOAT', {'default': 2, 'min': 0.01, 'max': 16.0, 'step': 0.01})}, 'optional': {'upscale_stack': ('UPSCALE_STACK',)}} + RETURN_TYPES = ('UPSCALE_STACK', 'STRING') + RETURN_NAMES = ('UPSCALE_STACK', 'show_help') + FUNCTION = 'stack' + CATEGORY = icons.get('Comfyroll/Upscale') + + def stack(self, switch_1, upscale_model_1, rescale_factor_1, switch_2, upscale_model_2, rescale_factor_2, switch_3, upscale_model_3, rescale_factor_3, upscale_stack=None): + upscale_list = list() + if upscale_stack is not None: + upscale_list.extend([l for l in upscale_stack if l[0] != 'None']) + if upscale_model_1 != 'None' and switch_1 == 'On': + (upscale_list.extend([(upscale_model_1, rescale_factor_1)]),) + if upscale_model_2 != 'None' and switch_2 == 'On': + (upscale_list.extend([(upscale_model_2, rescale_factor_2)]),) + if upscale_model_3 != 'None' and switch_3 == 'On': + (upscale_list.extend([(upscale_model_3, rescale_factor_3)]),) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Upscale-Nodes#cr-multi-upscale-stack' + return (upscale_list, show_help) +``` \ No newline at end of file diff --git a/docs/CR Multi-ControlNet Stack.md b/docs/CR Multi-ControlNet Stack.md new file mode 100644 index 0000000..7b7fafa --- /dev/null +++ b/docs/CR Multi-ControlNet Stack.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: CR_ControlNetStack +- Category: Comfyroll/ControlNet +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ControlNetStack 是一个用于管理和应用多个 ControlNet 配置的节点,以顺序方式进行。它允许用户切换各个 ControlNet 的开关,调整它们的影响力度,并定义它们应该应用的范围。这个节点对于微调图像生成过程的控制和方向至关重要,确保了高度的定制化和精确度。 + +# Input types +## Optional +- switch_1 + - 开关参数决定第一个 ControlNet 是否在栈中激活。它在控制节点内控制信号流中起着关键作用,可以启用或禁用特定的影响层。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +- controlnet_1 + - controlnet_1 参数指定了栈中要使用的第一个 ControlNet。它对于定义要应用的控制类型至关重要,并且对图像生成过程的结果有显著影响。 + - Comfy dtype: COMBO[] + - Python dtype: str +- controlnet_strength_1 + - controlnet_strength_1 参数调整第一个 ControlNet 影响的强度。它是微调节点内不同控制层之间平衡的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_percent_1 + - start_percent_1 参数定义了图像生成过程中第一个 ControlNet 开始生效的起始百分比。它对于控制控制信号的空间分布很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_percent_1 + - end_percent_1 参数标志着图像生成过程中第一个 ControlNet 影响结束的百分比。它对于确定控制应用的范围至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- image_1 + - image_1 参数代表与第一个 ControlNet 相关联的图像。它对于为控制机制提供视觉上下文和指导至关重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Output types +- CONTROLNET_STACK + - CONTROLNET_STACK 输出包含已编译的激活 ControlNets 列表及其各自的设置,准备应用于图像生成过程。 + - Comfy dtype: CONTROL_NET_STACK + - Python dtype: List[Tuple[comfy.controlnet.ControlNet, PIL.Image, float, float, float]] +- show_help + - show_help 输出提供了一个 URL 到文档,以获取有关使用 CR_ControlNetStack 节点的进一步指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ControlNetStack: + controlnets = ['None'] + folder_paths.get_filename_list('controlnet') + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'switch_1': (['Off', 'On'],), 'controlnet_1': (cls.controlnets,), 'controlnet_strength_1': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'start_percent_1': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_percent_1': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'switch_2': (['Off', 'On'],), 'controlnet_2': (cls.controlnets,), 'controlnet_strength_2': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'start_percent_2': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_percent_2': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'switch_3': (['Off', 'On'],), 'controlnet_3': (cls.controlnets,), 'controlnet_strength_3': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'start_percent_3': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_percent_3': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'image_1': ('IMAGE',), 'image_2': ('IMAGE',), 'image_3': ('IMAGE',), 'controlnet_stack': ('CONTROL_NET_STACK',)}} + RETURN_TYPES = ('CONTROL_NET_STACK', 'STRING') + RETURN_NAMES = ('CONTROLNET_STACK', 'show_help') + FUNCTION = 'controlnet_stacker' + CATEGORY = icons.get('Comfyroll/ControlNet') + + def controlnet_stacker(self, switch_1, controlnet_1, controlnet_strength_1, start_percent_1, end_percent_1, switch_2, controlnet_2, controlnet_strength_2, start_percent_2, end_percent_2, switch_3, controlnet_3, controlnet_strength_3, start_percent_3, end_percent_3, image_1=None, image_2=None, image_3=None, controlnet_stack=None): + controlnet_list = [] + if controlnet_stack is not None: + controlnet_list.extend([l for l in controlnet_stack if l[0] != 'None']) + if controlnet_1 != 'None' and switch_1 == 'On' and (image_1 is not None): + controlnet_path = folder_paths.get_full_path('controlnet', controlnet_1) + controlnet_1 = comfy.controlnet.load_controlnet(controlnet_path) + (controlnet_list.extend([(controlnet_1, image_1, controlnet_strength_1, start_percent_1, end_percent_1)]),) + if controlnet_2 != 'None' and switch_2 == 'On' and (image_2 is not None): + controlnet_path = folder_paths.get_full_path('controlnet', controlnet_2) + controlnet_2 = comfy.controlnet.load_controlnet(controlnet_path) + (controlnet_list.extend([(controlnet_2, image_2, controlnet_strength_2, start_percent_2, end_percent_2)]),) + if controlnet_3 != 'None' and switch_3 == 'On' and (image_3 is not None): + controlnet_path = folder_paths.get_full_path('controlnet', controlnet_3) + controlnet_3 = comfy.controlnet.load_controlnet(controlnet_path) + (controlnet_list.extend([(controlnet_3, image_3, controlnet_strength_3, start_percent_3, end_percent_3)]),) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/ControlNet-Nodes#cr-multi-controlnet-stack' + return (controlnet_list, show_help) +``` \ No newline at end of file diff --git a/docs/CR Multiline Text.md b/docs/CR Multiline Text.md new file mode 100644 index 0000000..aad84e5 --- /dev/null +++ b/docs/CR Multiline Text.md @@ -0,0 +1,97 @@ +# Documentation +- Class name: CR_MultilineText +- Category: Comfyroll/Utils/Text +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_MultilineText节点旨在处理和操作文本数据,提供将文本从CSV格式转换、根据指定分隔符拆分字符串以及移除不需要的字符等功能。它在各种应用的文本预处理中扮演着关键角色,确保文本为下游任务正确格式化。 + +# Input types +## Required +- text + - ‘text’参数是节点的主要输入,可以包含多行文本或CSV格式的数据。它对节点的操作至关重要,因为它决定了将被处理和转换的内容。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- convert_from_csv + - ‘convert_from_csv’参数允许用户指定输入文本是否应被视为CSV数据。启用时,节点将根据CSV规则解析文本,这对于将表格数据转换为可用格式很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- csv_quote_char + - ‘csv_quote_char’参数定义了在CSV数据中用于引用字段的字符,这在解析CSV文本以确保准确性以及处理包含逗号或换行符的字段时至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- remove_chars + - ‘remove_chars’参数指示是否应从文本中移除某些字符。这对于清理文本并为其进一步分析或处理做准备很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- chars_to_remove + - ‘chars_to_remove’参数指定在启用‘remove_chars’选项时需要从文本中移除的字符。它在自定义文本清理过程中起着重要作用。 + - Comfy dtype: STRING + - Python dtype: str +- split_string + - ‘split_string’参数决定输入文本是否应根据分隔符拆分成单独的值。这个功能对于将复杂的字符串分解成可管理的部分至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- multiline_text + - ‘multiline_text’输出包含应用所有转换后的文本。它代表了文本的最终状态,准备好用于后续操作。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - ‘show_help’输出提供了与节点相关联的文档或帮助页面的链接。它作为用户寻求有关如何使用节点的更多信息或帮助的快速参考。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_MultilineText: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {'default': '', 'multiline': True}), 'convert_from_csv': ('BOOLEAN', {'default': False}), 'csv_quote_char': ('STRING', {'default': "'", 'choices': ["'", '"']}), 'remove_chars': ('BOOLEAN', {'default': False}), 'chars_to_remove': ('STRING', {'multiline': False, 'default': ''}), 'split_string': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = (any_type, 'STRING') + RETURN_NAMES = ('multiline_text', 'show_help') + FUNCTION = 'text_multiline' + CATEGORY = icons.get('Comfyroll/Utils/Text') + + def text_multiline(self, text, chars_to_remove, split_string=False, remove_chars=False, convert_from_csv=False, csv_quote_char="'"): + new_text = [] + text = text.rstrip(',') + if convert_from_csv: + csv_reader = csv.reader(io.StringIO(text), quotechar=csv_quote_char) + for row in csv_reader: + new_text.extend(row) + if split_string: + if text.startswith("'") and text.endswith("'"): + text = text[1:-1] + values = [value.strip() for value in text.split("', '")] + new_text.extend(values) + elif text.startswith('"') and text.endswith('"'): + text = text[1:-1] + values = [value.strip() for value in text.split('", "')] + new_text.extend(values) + elif ',' in text and text.count("'") % 2 == 0: + text = text.replace("'", '') + values = [value.strip() for value in text.split(',')] + new_text.extend(values) + elif ',' in text and text.count('"') % 2 == 0: + text = text.replace('"', '') + values = [value.strip() for value in text.split(',')] + new_text.extend(values) + if convert_from_csv == False and split_string == False: + for line in io.StringIO(text): + if not line.strip().startswith('#'): + if not line.strip().startswith('\n'): + line = line.replace('\n', '') + if remove_chars: + line = line.replace(chars_to_remove, '') + new_text.append(line) + new_text = '\n'.join(new_text) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-multiline-text' + return (new_text, show_help) +``` \ No newline at end of file diff --git a/docs/CR Output Flow Frames.md b/docs/CR Output Flow Frames.md new file mode 100644 index 0000000..52d9657 --- /dev/null +++ b/docs/CR Output Flow Frames.md @@ -0,0 +1,96 @@ +# Documentation +- Class name: CR_OutputFlowFrames +- Category: Comfyroll/Animation/IO +- Output node: True +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_OutputFlowFrames节点旨在管理图像帧的输出过程,便于将图像保存到指定的目录。它支持直接图像输出和插值图像,确保帧之间的平滑过渡。该节点在图像处理流水线的最后阶段扮演着关键角色,专注于高效存储和组织生成的帧。 + +# Input types +## Required +- output_folder + - output_folder参数指定了将要保存图像帧的目录。这对于组织输出并确保帧存储在正确的位置至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- current_image + - current_image参数代表将要保存的当前帧图像。它是节点操作的基本输入,因为它是将要写入文件系统的实际内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- current_frame + - current_frame参数表示当前正在处理的帧编号。它对于按反映处理顺序的序列命名和排序保存的图像至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- filename_prefix + - filename_prefix参数用于定义保存图像的文件名的起始部分。它有助于为输出文件创建一致的命名约定,这对于后来的识别和处理可能是有益的。 + - Comfy dtype: STRING + - Python dtype: str +- interpolated_img + - interpolated_img参数提供了在输出中包含插值图像的选项。这可以增强帧之间的视觉过渡,提供更流畅的动画效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- output_path + - output_path参数允许指定一个替代路径来保存图像,覆盖默认的输出目录。它在管理输出图像的存储位置方面提供了灵活性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- ui + - 输出中的ui参数包含有关保存的图像的信息,包括它们的文件名、子文件夹位置和输出类型。这些数据可用于用户界面显示或进一步处理。 + - Comfy dtype: COMBO[Dict[str, List[Dict[str, Union[str, Dict[str, str]]]]]] + - Python dtype: Dict[str, List[Dict[str, Union[str, Dict[str, str]]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_OutputFlowFrames: + + def __init__(self): + self.type = 'output' + + @classmethod + def INPUT_TYPES(cls): + output_dir = folder_paths.output_directory + output_folders = [name for name in os.listdir(output_dir) if os.path.isdir(os.path.join(output_dir, name)) and len(os.listdir(os.path.join(output_dir, name))) != 0] + return {'required': {'output_folder': (sorted(output_folders),), 'current_image': ('IMAGE',), 'filename_prefix': ('STRING', {'default': 'CR'}), 'current_frame': ('INT', {'default': 0, 'min': 0, 'max': 9999999, 'forceInput': True})}, 'optional': {'interpolated_img': ('IMAGE',), 'output_path': ('STRING', {'default': '', 'multiline': False})}} + RETURN_TYPES = () + FUNCTION = 'save_images' + OUTPUT_NODE = True + CATEGORY = icons.get('Comfyroll/Animation/IO') + + def save_images(self, output_folder, current_image, current_frame, output_path='', filename_prefix='CR', interpolated_img=None): + output_dir = folder_paths.get_output_directory() + out_folder = os.path.join(output_dir, output_folder) + if output_path != '': + if not os.path.exists(output_path): + print(f'[Warning] CR Output Flow Frames: The input_path `{output_path}` does not exist') + return ('',) + out_path = output_path + else: + out_path = os.path.join(output_dir, out_folder) + print(f'[Info] CR Output Flow Frames: Output path is `{out_path}`') + if interpolated_img is not None: + output_image0 = current_image[0].cpu().numpy() + output_image1 = interpolated_img[0].cpu().numpy() + img0 = Image.fromarray(np.clip(output_image0 * 255.0, 0, 255).astype(np.uint8)) + img1 = Image.fromarray(np.clip(output_image1 * 255.0, 0, 255).astype(np.uint8)) + output_filename0 = f'{filename_prefix}_{current_frame:05}_0.png' + output_filename1 = f'{filename_prefix}_{current_frame:05}_1.png' + print(f'[Warning] CR Output Flow Frames: Saved {filename_prefix}_{current_frame:05}_0.png') + print(f'[Warning] CR Output Flow Frames: Saved {filename_prefix}_{current_frame:05}_1.png') + resolved_image_path0 = out_path + '/' + output_filename0 + resolved_image_path1 = out_path + '/' + output_filename1 + img0.save(resolved_image_path0, pnginfo='', compress_level=4) + img1.save(resolved_image_path1, pnginfo='', compress_level=4) + else: + output_image0 = current_image[0].cpu().numpy() + img0 = Image.fromarray(np.clip(output_image0 * 255.0, 0, 255).astype(np.uint8)) + output_filename0 = f'{filename_prefix}_{current_frame:05}.png' + resolved_image_path0 = out_path + '/' + output_filename0 + img0.save(resolved_image_path0, pnginfo='', compress_level=4) + print(f'[Info] CR Output Flow Frames: Saved {filename_prefix}_{current_frame:05}.png') + result = {'ui': {'images': [{'filename': output_filename0, 'subfolder': out_path, 'type': self.type}]}} + return result +``` \ No newline at end of file diff --git a/docs/CR Output Schedule To File.md b/docs/CR Output Schedule To File.md new file mode 100644 index 0000000..388482a --- /dev/null +++ b/docs/CR Output Schedule To File.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: CR_OutputScheduleToFile +- Category: Comfyroll/Animation/Schedule +- Output node: True +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_OutputScheduleToFile节点旨在将调度数据输出到文件中进行管理。它接收输出文件路径、文件名、调度和文件扩展名等参数,然后生成指定格式的文件,确保文件名唯一以避免覆盖现有文件。 + +# Input types +## Required +- output_file_path + - output_file_path参数指定了输出文件将要保存的目录。它对于确定文件的位置至关重要,对于节点的操作也是必需的,因为它指导了输出应该存储在哪里。 + - Comfy dtype: STRING + - Python dtype: str +- file_name + - file_name参数定义了输出文件的基本名称,不包括扩展名。它在标识文件中起着重要作用,对于节点创建一个不与目录中现有文件冲突的唯一文件名是必要的。 + - Comfy dtype: STRING + - Python dtype: str +- schedule + - schedule参数包含将要写入文件的数据。它是一个关键的输入,因为它代表了节点负责输出的内容。预期schedule数据的格式可以写入文本或CSV文件。 + - Comfy dtype: SCHEDULE + - Python dtype: List[Any] +## Optional +- file_extension + - file_extension参数决定了输出文件的格式。它是可选的,但很重要,因为它决定了文件将具有的数据结构类型。节点支持'txt'和'csv'扩展名,这些扩展名对应于不同的文本格式。 + - Comfy dtype: COMBO['txt', 'csv'] + - Python dtype: str + +# Output types + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_OutputScheduleToFile: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'output_file_path': ('STRING', {'multiline': False, 'default': ''}), 'file_name': ('STRING', {'multiline': False, 'default': ''}), 'file_extension': (['txt', 'csv'],), 'schedule': ('SCHEDULE',)}} + RETURN_TYPES = () + OUTPUT_NODE = True + FUNCTION = 'csvoutput' + CATEGORY = icons.get('Comfyroll/Animation/Schedule') + + def csvoutput(self, output_file_path, file_name, schedule, file_extension): + filepath = output_file_path + '\\' + file_name + '.' + file_extension + index = 2 + if output_file_path == '' or file_name == '': + print(f'[Warning] CR Output Schedule To File. No file details found. No file output.') + return () + while os.path.exists(filepath): + if os.path.exists(filepath): + filepath = output_file_path + '\\' + file_name + str(index) + '.' + file_extension + index = index + 1 + else: + break + print(f'[Info] CR Output Schedule To File: Saving to {filepath}') + if file_extension == 'csv': + with open(filepath, 'w', newline='') as csv_file: + csv_writer = csv.writer(csv_file) + csv_writer.writerows(schedule) + else: + with open(filepath, 'w', newline='') as text_writer: + for line in schedule: + str_item = f'{line[0]},"{line[1]}"\n' + text_writer.write(str_item) + return () +``` \ No newline at end of file diff --git a/docs/CR Overlay Text.md b/docs/CR Overlay Text.md new file mode 100644 index 0000000..3d1307e --- /dev/null +++ b/docs/CR Overlay Text.md @@ -0,0 +1,106 @@ +# Documentation +- Class name: CR_OverlayText +- Category: Comfyroll/Graphics/Text +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_OverlayText 节点旨在将文本叠加到图片上,提供了一系列定制选项,如字体大小、颜色和旋转。它通过以用户定义的方式整合文本元素,增强了图片的视觉效果和信息密度。 + +# Input types +## Required +- image + - 将要叠加文本的基础图片。它作为文本可视化的画布。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- text + - 要叠加在图片上的文本内容。它可以包含多行文本,是节点功能的核心。 + - Comfy dtype: STRING + - Python dtype: str +- font_name + - 指定用于文本叠加的字体。字体的选择影响文本的风格和可读性。 + - Comfy dtype: STRING + - Python dtype: str +- font_size + - 确定文本的字体大小。较大的尺寸可以使文本更加突出,而较小的尺寸可以创造一种微妙的效果。 + - Comfy dtype: INT + - Python dtype: int +- font_color + - 设置用于文本叠加的字体颜色。颜色的选择可以影响文本在图片上的对比度和视觉冲击力。 + - Comfy dtype: STRING + - Python dtype: str +- align + - 控制文本在图片上的水平对齐方式。这对于以审美方式定位文本至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- justify + - 决定文本在指定边距内的对齐方式。它影响每行单词之间的间距。 + - Comfy dtype: STRING + - Python dtype: str +- margins + - 设置文本周围的边距。适当的边距可以防止文本显得拥挤,提高可读性。 + - Comfy dtype: INT + - Python dtype: int +- line_spacing + - 控制文本行之间的间距。适当的行间距可以提高文本的可读性。 + - Comfy dtype: INT + - Python dtype: int +- position_x + - 指定文本在图片上开始的水平位置(x坐标)。 + - Comfy dtype: INT + - Python dtype: int +- position_y + - 指定文本在图片上开始的垂直位置(y坐标)。 + - Comfy dtype: INT + - Python dtype: int +- rotation_angle + - 定义文本的旋转角度。这可以用来以各种角度定位文本,以创造创意效果。 + - Comfy dtype: FLOAT + - Python dtype: float +- rotation_options + - 确定文本的旋转点。它可以是文本的中心或图片的中心。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- font_color_hex + - 为字体提供十六进制颜色代码。这允许使用预定义颜色选项中没有的自定义颜色。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - 应用了文本叠加的结果图片。它代表了节点操作的最终视觉输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - 提供文档链接,以便进一步指导如何使用该节点。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_OverlayText: + + @classmethod + def INPUT_TYPES(s): + font_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'fonts') + file_list = [f for f in os.listdir(font_dir) if os.path.isfile(os.path.join(font_dir, f)) and f.lower().endswith('.ttf')] + return {'required': {'image': ('IMAGE',), 'text': ('STRING', {'multiline': True, 'default': 'text'}), 'font_name': (file_list,), 'font_size': ('INT', {'default': 50, 'min': 1, 'max': 1024}), 'font_color': (COLORS,), 'align': (ALIGN_OPTIONS,), 'justify': (JUSTIFY_OPTIONS,), 'margins': ('INT', {'default': 0, 'min': -1024, 'max': 1024}), 'line_spacing': ('INT', {'default': 0, 'min': -1024, 'max': 1024}), 'position_x': ('INT', {'default': 0, 'min': -4096, 'max': 4096}), 'position_y': ('INT', {'default': 0, 'min': -4096, 'max': 4096}), 'rotation_angle': ('FLOAT', {'default': 0.0, 'min': -360.0, 'max': 360.0, 'step': 0.1}), 'rotation_options': (ROTATE_OPTIONS,)}, 'optional': {'font_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'overlay_text' + CATEGORY = icons.get('Comfyroll/Graphics/Text') + + def overlay_text(self, image, text, font_name, font_size, font_color, margins, line_spacing, position_x, position_y, align, justify, rotation_angle, rotation_options, font_color_hex='#000000'): + text_color = get_color_values(font_color, font_color_hex, color_mapping) + image_3d = image[0, :, :, :] + back_image = tensor2pil(image_3d) + text_image = Image.new('RGB', back_image.size, text_color) + text_mask = Image.new('L', back_image.size) + rotated_text_mask = draw_masked_text(text_mask, text, font_name, font_size, margins, line_spacing, position_x, position_y, align, justify, rotation_angle, rotation_options) + image_out = Image.composite(text_image, back_image, rotated_text_mask) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Text-Nodes#cr-overlay-text' + return (pil2tensor(image_out), show_help) +``` \ No newline at end of file diff --git a/docs/CR Overlay Transparent Image.md b/docs/CR Overlay Transparent Image.md new file mode 100644 index 0000000..f563975 --- /dev/null +++ b/docs/CR Overlay Transparent Image.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: CR_OverlayTransparentImage +- Category: Comfyroll/Graphics/Layout +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_OverlayTransparentImage 节点旨在将一个透明的覆盖图像与背景图像混合。它调整覆盖层的透明度、位置、旋转和缩放,以实现所需的视觉效果,为图像处理中的创意应用提供了广泛的可能性。 + +# Input types +## Required +- back_image + - 背景图像,覆盖图像将放置在其上。它作为合成图像创建的画布。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- overlay_image + - 将带有透明度覆盖在背景上的图像。它是最终输出中将被操作的主要视觉元素。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- transparency + - 应用于覆盖图像的透明度级别,0.0表示完全不透明,1.0表示完全透明。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- offset_x + - 应用于覆盖图像的水平偏移量,从其中心位置开始,允许精确放置。 + - Comfy dtype: INT + - Python dtype: int +- offset_y + - 应用于覆盖图像的垂直偏移量,从其中心位置开始,允许精确放置。 + - Comfy dtype: INT + - Python dtype: int +- rotation_angle + - 覆盖图像将旋转的角度,以度数为单位,提供一种按需定向图像的方法。 + - Comfy dtype: FLOAT + - Python dtype: float +- overlay_scale_factor + - 覆盖图像将被缩放的因子;大于1.0的值放大图像,而小于1.0的值缩小图像。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output_image + - 最终合成图像,覆盖图像应用于背景,反映了通过节点参数进行的所有修改。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_OverlayTransparentImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'back_image': ('IMAGE',), 'overlay_image': ('IMAGE',), 'transparency': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.1}), 'offset_x': ('INT', {'default': 0, 'min': -4096, 'max': 4096}), 'offset_y': ('INT', {'default': 0, 'min': -4096, 'max': 4096}), 'rotation_angle': ('FLOAT', {'default': 0.0, 'min': -360.0, 'max': 360.0, 'step': 0.1}), 'overlay_scale_factor': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 100.0, 'step': 0.001})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'overlay_image' + CATEGORY = icons.get('Comfyroll/Graphics/Layout') + + def overlay_image(self, back_image, overlay_image, transparency, offset_x, offset_y, rotation_angle, overlay_scale_factor=1.0): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Layout-Nodes#cr-overlay-transparent-image' + back_image = tensor2pil(back_image) + overlay_image = tensor2pil(overlay_image) + overlay_image.putalpha(int(255 * (1 - transparency))) + overlay_image = overlay_image.rotate(rotation_angle, expand=True) + (overlay_width, overlay_height) = overlay_image.size + new_size = (int(overlay_width * overlay_scale_factor), int(overlay_height * overlay_scale_factor)) + overlay_image = overlay_image.resize(new_size, Image.Resampling.LANCZOS) + center_x = back_image.width // 2 + center_y = back_image.height // 2 + position_x = center_x - overlay_image.width // 2 + offset_x + position_y = center_y - overlay_image.height // 2 + offset_y + back_image.paste(overlay_image, (position_x, position_y), overlay_image) + return (pil2tensor(back_image),) +``` \ No newline at end of file diff --git a/docs/CR Page Layout.md b/docs/CR Page Layout.md new file mode 100644 index 0000000..36d2af3 --- /dev/null +++ b/docs/CR Page Layout.md @@ -0,0 +1,129 @@ +# Documentation +- Class name: CR_PageLayout +- Category: Comfyroll/Graphics/Layout +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_PageLayout 节点旨在通过添加自定义的标题和页脚文本来生成图像的结构化布局。它允许操作字体属性、颜色,并添加边框,以创建视觉上吸引人的组合。 + +# Input types +## Required +- layout_options + - 布局选项定义了最终图像中将包含哪些部分的布局。这个选择影响输出的整体结构和组成。 + - Comfy dtype: COMBO['header', 'footer', 'header and footer', 'no header or footer'] + - Python dtype: str +- image_panel + - 主要的图像面板,作为布局的中心组件。它是将要添加标题和页脚的图像。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- header_height + - 指定标题部分的高度。这个参数对于确定标题在布局中的间距和大小至关重要。 + - Comfy dtype: INT + - Python dtype: int +- header_text + - 标题部分的文本内容。它影响标题的视觉展示和它所传达的信息。 + - Comfy dtype: STRING + - Python dtype: str +- header_align + - 确定标题的文本对齐方式。它影响标题文本在标题部分内的位置。 + - Comfy dtype: JUSTIFY_OPTIONS + - Python dtype: str +- footer_height + - 指定页脚部分的高度。它是设置布局中页脚间距和大小的重要参数。 + - Comfy dtype: INT + - Python dtype: int +- footer_text + - 页脚部分的文本内容。它决定了页脚的信息和视觉风格。 + - Comfy dtype: STRING + - Python dtype: str +- footer_align + - 定义页脚的文本对齐方式。它控制页脚文本在页脚部分内的位置。 + - Comfy dtype: JUSTIFY_OPTIONS + - Python dtype: str +- font_name + - 选择用于标题和页脚文本的字体。字体的选择可以显著影响布局的整体美感。 + - Comfy dtype: FONT_LIST + - Python dtype: str +- font_color + - 设置标题和页脚文本的字体颜色。它在文本的可读性和视觉吸引力中起着关键作用。 + - Comfy dtype: COLORS + - Python dtype: str +- header_font_size + - 定义标题文本的字体大小。它影响标题在布局中的突出度和可读性。 + - Comfy dtype: INT + - Python dtype: int +- footer_font_size + - 指定页脚文本的字体大小。它对于页脚在布局中的可见性和突出性很重要。 + - Comfy dtype: INT + - Python dtype: int +- border_thickness + - 确定布局周围边框的厚度。它有助于整体框架和布局边缘的定义。 + - Comfy dtype: INT + - Python dtype: int +- border_color + - 设置布局周围边框的颜色。它在布局的视觉边界和风格中起着重要作用。 + - Comfy dtype: COLORS + - Python dtype: str +- background_color + - 定义布局的背景颜色。它为所有其他元素提供了基本的视觉背景。 + - Comfy dtype: COLORS + - Python dtype: str + +# Output types +- image + - 最终组合的图像,包括根据输入参数指定的任何标题、页脚和边框。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - 提供文档链接,以获得进一步的帮助和关于节点功能的详细信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_PageLayout: + + @classmethod + def INPUT_TYPES(s): + font_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'fonts') + file_list = [f for f in os.listdir(font_dir) if os.path.isfile(os.path.join(font_dir, f)) and f.lower().endswith('.ttf')] + layout_options = ['header', 'footer', 'header and footer', 'no header or footer'] + return {'required': {'layout_options': (layout_options,), 'image_panel': ('IMAGE',), 'header_height': ('INT', {'default': 0, 'min': 0, 'max': 1024}), 'header_text': ('STRING', {'multiline': True, 'default': 'text'}), 'header_align': (JUSTIFY_OPTIONS,), 'footer_height': ('INT', {'default': 0, 'min': 0, 'max': 1024}), 'footer_text': ('STRING', {'multiline': True, 'default': 'text'}), 'footer_align': (JUSTIFY_OPTIONS,), 'font_name': (file_list,), 'font_color': (COLORS,), 'header_font_size': ('INT', {'default': 150, 'min': 0, 'max': 1024}), 'footer_font_size': ('INT', {'default': 50, 'min': 0, 'max': 1024}), 'border_thickness': ('INT', {'default': 0, 'min': 0, 'max': 1024}), 'border_color': (COLORS,), 'background_color': (COLORS,)}, 'optional': {'font_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'border_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'bg_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image', 'show_help') + FUNCTION = 'layout' + CATEGORY = icons.get('Comfyroll/Graphics/Layout') + + def layout(self, layout_options, image_panel, border_thickness, border_color, background_color, header_height, header_text, header_align, footer_height, footer_text, footer_align, font_name, font_color, header_font_size, footer_font_size, font_color_hex='#000000', border_color_hex='#000000', bg_color_hex='#000000'): + font_color = get_color_values(font_color, font_color_hex, color_mapping) + border_color = get_color_values(border_color, border_color_hex, color_mapping) + bg_color = get_color_values(background_color, bg_color_hex, color_mapping) + main_panel = tensor2pil(image_panel) + image_width = main_panel.width + image_height = main_panel.height + margins = 50 + line_spacing = 0 + position_x = 0 + position_y = 0 + align = 'center' + rotation_angle = 0 + rotation_options = 'image center' + font_outline_thickness = 0 + font_outline_color = 'black' + images = [] + if layout_options == 'header' or layout_options == 'header and footer': + header_panel = text_panel(image_width, header_height, header_text, font_name, header_font_size, font_color, font_outline_thickness, font_outline_color, bg_color, margins, line_spacing, position_x, position_y, align, header_align, rotation_angle, rotation_options) + images.append(header_panel) + images.append(main_panel) + if layout_options == 'footer' or layout_options == 'header and footer': + footer_panel = text_panel(image_width, footer_height, footer_text, font_name, footer_font_size, font_color, font_outline_thickness, font_outline_color, bg_color, margins, line_spacing, position_x, position_y, align, footer_align, rotation_angle, rotation_options) + images.append(footer_panel) + combined_image = combine_images(images, 'vertical') + if border_thickness > 0: + combined_image = ImageOps.expand(combined_image, border_thickness, border_color) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Layout-Nodes#cr-page-layout' + return (pil2tensor(combined_image), show_help) +``` \ No newline at end of file diff --git a/docs/CR Pipe Switch.md b/docs/CR Pipe Switch.md new file mode 100644 index 0000000..5e5224a --- /dev/null +++ b/docs/CR Pipe Switch.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CR_InputSwitchPipe +- Category: Comfyroll/Pipe +- Output node: True +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_InputSwitchPipe节点旨在根据选择输入管理不同处理管道之间的数据流。它通过评估'Input'参数来确定在后续工作流中应该使用提供的两个管道中的哪一个,'pipe1'或'pipe2'。此节点在创建基于输入条件需要不同处理路径的条件工作流中起着关键作用。 + +# Input types +## Required +- Input + - ‘Input’参数对于确定活动管道至关重要。它接受一个整数值,其中1表示将使用‘pipe1’,任何其他值表示‘pipe2’。这种选择机制对于通过所需的处理路径指导工作流至关重要。 + - Comfy dtype: INT + - Python dtype: int +- pipe1 + - ‘pipe1’参数表示节点可用的第一个管道选项。如果‘Input’参数设置为1,它将是一个被激活的管道对象。这允许将预定义的处理路径无缝集成到工作流中。 + - Comfy dtype: PIPE_LINE + - Python dtype: Any +- pipe2 + - ‘pipe2’参数是提供给节点的替代管道选项。当‘Input’参数不等于1时,它变得活跃,为工作流内的数据处理提供了一个次要路径。 + - Comfy dtype: PIPE_LINE + - Python dtype: Any + +# Output types +- PIPE_LINE + - ‘PIPE_LINE’输出是基于‘Input’参数选择的管道。它是将被传递给进一步处理的输出,代表根据输入选择的‘pipe1’或‘pipe2’。 + - Comfy dtype: PIPE_LINE + - Python dtype: Any +- show_help + - ‘show_help’输出提供了一个指向文档页面的URL以供进一步帮助。它是一个常量字符串,始终指向CR_InputSwitchPipe节点的GitHub wiki页面,为用户提供了关于节点使用和功能的直接链接。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_InputSwitchPipe: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': ('INT', {'default': 1, 'min': 1, 'max': 2}), 'pipe1': ('PIPE_LINE',), 'pipe2': ('PIPE_LINE',)}} + RETURN_TYPES = ('PIPE_LINE', 'STRING') + RETURN_NAMES = ('PIPE_LINE', 'show_help') + OUTPUT_NODE = True + FUNCTION = 'switch_pipe' + CATEGORY = icons.get('Comfyroll/Pipe') + + def switch_pipe(self, Input, pipe1, pipe2): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pipe-Nodes#cr-pipe-switch' + if Input == 1: + return (pipe1, show_help) + else: + return (pipe2, show_help) +``` \ No newline at end of file diff --git a/docs/CR Polygons.md b/docs/CR Polygons.md new file mode 100644 index 0000000..4d2ce6a --- /dev/null +++ b/docs/CR Polygons.md @@ -0,0 +1,121 @@ +# Documentation +- Class name: CR_Polygons +- Category: Comfyroll/Graphics/Pattern +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_Polygons 是一个用于生成由六边形或三角形组成的几何图案的节点。它允许自定义多边形的颜色、背景和线条属性,以创建视觉上独特的图案。这个节点特别适用于为各种应用创建背景纹理或复杂设计。 + +# Input types +## Required +- mode + - 模式参数决定了要绘制的多边形的形状,可以是六边形或三角形。这个选择显著影响节点生成的总体图案,为用户提供了对输出的几何风格的控制。 + - Comfy dtype: COMBO['hexagons', 'triangles'] + - Python dtype: str +- width + - 宽度参数设置了图案的宽度,以像素为单位。它是决定图案比例的关键因素,直接影响输出图像的最终尺寸。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置了图案的高度,以像素为单位。它与宽度一起工作,以确定图案的总体大小,这对于将设计适应特定的显示要求至关重要。 + - Comfy dtype: INT + - Python dtype: int +- rows + - 行参数指定了要在图案内绘制的多边形行数。它影响多边形的密度和布局,从而影响最终设计的复杂性。 + - Comfy dtype: INT + - Python dtype: int +- columns + - 列参数决定了要在图案内绘制的多边形列数。它与行参数一起工作,以定义图案的总体网格结构。 + - Comfy dtype: INT + - Python dtype: int +- face_color + - 面颜色参数定义了填充多边形内部的颜色。它在确定图案的视觉吸引力和主题一致性方面起着重要作用。 + - Comfy dtype: COLORS + - Python dtype: str +- background_color + - 背景颜色参数设置了多边形背后的背景颜色。它对于提供对比度并确保图案在其背景上突出显示至关重要。 + - Comfy dtype: COLORS + - Python dtype: str +- line_color + - 线条颜色参数决定了勾勒多边形的线条颜色。它是定义图案边界和增强整体视觉清晰度的关键方面。 + - Comfy dtype: COLORS + - Python dtype: str +- line_width + - 线条宽度参数指定了用于绘制多边形轮廓的线条的粗细。它影响图案边缘的突出程度,并有助于整体设计的审美。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- face_color_hex + - 面颜色十六进制参数允许为多边形内部使用自定义的十六进制颜色代码。它为用户提供了微调图案色彩方案的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- bg_color_hex + - 背景颜色十六进制参数允许指定背景的自定义十六进制颜色代码。它确保用户可以自定义背景颜色以匹配他们的设计偏好。 + - Comfy dtype: STRING + - Python dtype: str +- line_color_hex + - 线条颜色十六进制参数允许使用自定义的十六进制颜色代码来定义多边形的线条。它为用户提供了调整线条颜色以实现所需视觉效果的能力。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - IMAGE 输出提供了渲染的几何图案作为图像。这是节点操作的主要结果,可以用于进一步处理或显示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个 URL 链接到文档页面,以获取有关节点使用和功能的进一步帮助和信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_Polygons: + + @classmethod + def INPUT_TYPES(s): + modes = ['hexagons', 'triangles'] + return {'required': {'mode': (modes,), 'width': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'rows': ('INT', {'default': 5, 'min': 1, 'max': 512}), 'columns': ('INT', {'default': 5, 'min': 1, 'max': 512}), 'face_color': (COLORS,), 'background_color': (COLORS,), 'line_color': (COLORS,), 'line_width': ('INT', {'default': 2, 'min': 0, 'max': 512})}, 'optional': {'face_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'bg_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'line_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'draw' + CATEGORY = icons.get('Comfyroll/Graphics/Pattern') + + def draw(self, mode, width, height, rows, columns, face_color, background_color, line_color, line_width, face_color_hex='#000000', bg_color_hex='#000000', line_color_hex='#000000'): + if face_color == 'custom': + face_color = face_color_hex + if line_color == 'custom': + line_color = line_color_hex + if background_color == 'custom': + background_color = bg_color_hex + (fig, ax) = plt.subplots(figsize=(width / 100, height / 100)) + fig.set_facecolor(background_color) + plt.xlim(0, width / 100) + plt.ylim(0, height / 100) + plt.axis('off') + plt.tight_layout(pad=0, w_pad=0, h_pad=0) + plt.autoscale(False) + if mode == 'hexagons': + vertices = 6 + elif mode == 'triangles': + vertices = 3 + cell_width = width / 100 / columns + cell_height = width / height * np.sqrt(3) * (height / 100) / (2 * columns) + for row in range(rows + 2): + for col in range(columns + 2): + x = col * cell_width + y = row * cell_height + if row % 2 == 1: + x += cell_width / 2 + hexagon = RegularPolygon((x, y), numVertices=vertices, radius=cell_width / 1.732, edgecolor=line_color, linewidth=line_width, facecolor=face_color) + ax.add_patch(hexagon) + img_buf = io.BytesIO() + plt.savefig(img_buf, format='png') + img = Image.open(img_buf) + image_out = pil2tensor(img.convert('RGB')) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pattern-Nodes#cr-polygons' + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Prompt List Keyframes.md b/docs/CR Prompt List Keyframes.md new file mode 100644 index 0000000..9dc3370 --- /dev/null +++ b/docs/CR Prompt List Keyframes.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: CR_PromptListKeyframes +- Category: Comfyroll/Animation/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_PromptListKeyframes 节点旨在从提示列表生成关键帧。它处理输入的提示列表,遵循特定的关键帧格式,以创建可以在动画工作流中使用的关键帧序列。此节点对于自动化关键帧创建过程至关重要,确保在生成动画序列时保持一致性和效率。 + +# Input types +## Required +- prompt_list + - 提示列表是节点的重要输入,因为它包含将被转换为关键帧的提示。列表中的每个提示都是关键帧的一部分,节点通过这个列表迭代以生成最终的关键帧序列。 + - Comfy dtype: PROMPT_LIST + - Python dtype: List[Tuple[str, str, str, str, int, int]] +## Optional +- keyframe_format + - 关键帧格式参数决定了生成的关键帧的结构和样式。尽管节点默认使用 'Deforum' 格式,但这个参数允许在未来需要支持其他格式时具有灵活性。 + - Comfy dtype: COMBO['Deforum'] + - Python dtype: Literal['Deforum'] + +# Output types +- keyframe_list + - 关键帧列表是节点的主要输出,表示格式化后的关键帧字符串。这个输出可以直接用于动画软件中定义动画关键帧的序列。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - 显示帮助输出提供了一个指向与节点相关联的文档或帮助页面的URL链接。这对于寻求更多信息或指导如何有效使用节点的用户来说非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_PromptListKeyframes: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompt_list': ('PROMPT_LIST',), 'keyframe_format': (['Deforum'],)}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('keyframe_list', 'show_help') + FUNCTION = 'make_keyframes' + CATEGORY = icons.get('Comfyroll/Animation/Legacy') + + def make_keyframes(self, prompt_list, keyframe_format): + keyframe_format = 'Deforum' + keyframe_list = list() + i = 0 + for (index, prompt_tuple) in enumerate(prompt_list): + (prompt, transition_type, transition_speed, transition_profile, keyframe_interval, loops) = prompt_tuple + if i == 0: + keyframe_list.extend(['"0": "' + prompt + '",\n']) + i += keyframe_interval + continue + new_keyframe = '"' + str(i) + '": "' + prompt + '",\n' + keyframe_list.extend([new_keyframe]) + i += keyframe_interval + keyframes_out = ''.join(keyframe_list)[:-2] + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Prompt-Nodes#cr-prompt-list-keyframes' + return (keyframes_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Prompt List.md b/docs/CR Prompt List.md new file mode 100644 index 0000000..dd2401e --- /dev/null +++ b/docs/CR Prompt List.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: CR_PromptList +- Category: Comfyroll/List +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_PromptList 节点旨在处理和操作列表形式的文本数据。它接受多行文本输入,并允许用户在每行文本前后添加文本,并通过指定起始索引和最大行数来选择列表中的行范围。该节点的功能主要集中在从输入文本创建提示列表和正文文本列表,这些列表可以用于各种目的,如为 AI 模型生成提示或组织文本数据。 + +# Input types +## Required +- multiline_text + - multiline_text 参数是节点的主要输入,包含将被拆分为列表的文本。它支持多行输入,允许处理复杂和详细的文本数据。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- prepend_text + - prepend_text 参数允许用户指定一个字符串,该字符串将被添加到输出列表中每行的开头。这可以用来自定义列表的格式或向文本添加上下文。 + - Comfy dtype: STRING + - Python dtype: str +- append_text + - append_text 参数使用户能够在输出列表中每行的末尾添加一个字符串,这对于扩展文本或添加额外信息非常有用。 + - Comfy dtype: STRING + - Python dtype: str +- start_index + - start_index 参数确定列表中节点将从中开始选择行的位置。它提供了对将被处理的列表子集的控制。 + - Comfy dtype: INT + - Python dtype: int +- max_rows + - max_rows 参数设置将包含在输出列表中的行的最大数量。它有助于限制列表的大小和管理正在处理的数据量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- prompt + - prompt 输出是一个字符串列表,其中每个字符串由前置文本、输入多行文本中的一行和后置文本组成。这可以用于为 AI 应用程序创建提示。 + - Comfy dtype: STRING + - Python dtype: List[str] +- body_text + - body_text 输出是一个字符串列表,代表从输入多行文本中选择的行。它作为进一步处理或分析的主要内容。 + - Comfy dtype: STRING + - Python dtype: List[str] +- show_help + - show_help 输出提供了一个指向与节点功能相关的文档或帮助页面的 URL 链接。这对于寻求有关如何使用节点的更多信息的用户非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_PromptList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prepend_text': ('STRING', {'multiline': False, 'default': ''}), 'multiline_text': ('STRING', {'multiline': True, 'default': 'body_text'}), 'append_text': ('STRING', {'multiline': False, 'default': ''}), 'start_index': ('INT', {'default': 0, 'min': 0, 'max': 9999}), 'max_rows': ('INT', {'default': 1000, 'min': 1, 'max': 9999})}} + RETURN_TYPES = ('STRING', 'STRING', 'STRING') + RETURN_NAMES = ('prompt', 'body_text', 'show_help') + OUTPUT_IS_LIST = (True, True, False) + FUNCTION = 'make_list' + CATEGORY = icons.get('Comfyroll/List') + + def make_list(self, multiline_text, prepend_text='', append_text='', start_index=0, max_rows=9999): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-prompt-list' + lines = multiline_text.split('\n') + start_index = max(0, min(start_index, len(lines) - 1)) + end_index = min(start_index + max_rows, len(lines)) + selected_rows = lines[start_index:end_index] + prompt_list_out = [prepend_text + line + append_text for line in selected_rows] + body_list_out = selected_rows + return (prompt_list_out, body_list_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Prompt Scheduler.md b/docs/CR Prompt Scheduler.md new file mode 100644 index 0000000..03c6985 --- /dev/null +++ b/docs/CR Prompt Scheduler.md @@ -0,0 +1,128 @@ +# Documentation +- Class name: CR_PromptScheduler +- Category: Comfyroll/Animation/Schedulers +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_PromptScheduler 是一个用于管理和根据关键帧或预定义的时间表调度提示的节点。它允许用户设置默认提示,插值提示之间,并自定义调度格式以满足各种需求。该节点的功能集中在为动画或其他基于时间的应用程序提供一种处理动态提示的无缝方式。 + +# Input types +## Required +- mode + - 模式决定了节点使用的调度方法。它决定了是应用默认提示,遵循关键帧列表,还是实现了更复杂的调度。 + - Comfy dtype: COMBO['Default Prompt', 'Keyframe List', 'Schedule'] + - Python dtype: str +- current_frame + - 当前帧是调度器确定要应用哪个提示的参考点。它对节点的执行至关重要,因为它直接影响根据提供的时间表选择提示。 + - Comfy dtype: INT + - Python dtype: int +- default_prompt + - 默认提示在当前帧没有安排特定提示时作为备用文本。它确保即使在没有定义的时间表的情况下,也总是有一个可用的提示。 + - Comfy dtype: STRING + - Python dtype: str +- schedule_format + - 时间表格式指定了输入时间表数据的结构。它很重要,因为它通知节点如何解释和处理用户提供的时间表信息。 + - Comfy dtype: COMBO['CR', 'Deforum'] + - Python dtype: str +- interpolate_prompt + - 插值提示确定节点是否应该在提示之间进行插值,以实现更平滑的过渡。这可以增强使用提示的动画或应用程序的流畅性。 + - Comfy dtype: COMBO['Yes', 'No'] + - Python dtype: str +## Optional +- keyframe_list + - 关键帧列表提供多行输入,用于定义关键帧及其关联的提示。当模式设置为'关键帧列表'时使用,对于创建特定帧的提示至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- prepend_text + - 前置文本允许用户在提示前添加自定义文本。这对于在主要提示旁边包含额外的上下文或信息非常有用。 + - Comfy dtype: STRING + - Python dtype: str +- append_text + - 追加文本允许在提示后添加自定义文本。它提供了灵活性,可以扩展提示以包含更多详细信息,或者用特定的结尾结束提示。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- current_prompt + - 当前提示代表根据调度器的评估当前处于活动状态的提示。它是在应用程序或动画中直接使用的输出。 + - Comfy dtype: STRING + - Python dtype: str +- next_prompt + - 下一个提示指示下一帧将处于活动状态的提示。这对于预览或准备提示序列中即将发生的变化非常有用。 + - Comfy dtype: STRING + - Python dtype: str +- weight + - 权重是一个浮点值,代表提示之间的过渡进度。当插值提示设置为'是'时,它特别相关,表示插值的程度。 + - Comfy dtype: FLOAT + - Python dtype: float +- show_help + - 显示帮助提供与节点相关联的文档或帮助页面的URL链接。它作为用户寻求有关节点的更多信息或帮助的快速参考。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_PromptScheduler: + + @classmethod + def INPUT_TYPES(s): + modes = ['Default Prompt', 'Keyframe List', 'Schedule'] + return {'required': {'mode': (modes,), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'default_prompt': ('STRING', {'multiline': False, 'default': 'default prompt'}), 'schedule_format': (['CR', 'Deforum'],), 'interpolate_prompt': (['Yes', 'No'],)}, 'optional': {'schedule': ('SCHEDULE',), 'schedule_alias': ('STRING', {'default prompt': '', 'multiline': False}), 'keyframe_list': ('STRING', {'multiline': True, 'default': 'keyframe list'}), 'prepend_text': ('STRING', {'multiline': True, 'default': 'prepend text'}), 'append_text': ('STRING', {'multiline': True, 'default': 'append text'})}} + RETURN_TYPES = ('STRING', 'STRING', 'FLOAT', 'STRING') + RETURN_NAMES = ('current_prompt', 'next_prompt', 'weight', 'show_help') + FUNCTION = 'schedule' + CATEGORY = icons.get('Comfyroll/Animation/Schedulers') + + def schedule(self, mode, prepend_text, append_text, current_frame, schedule_alias, default_prompt, schedule_format, interpolate_prompt, keyframe_list='', schedule=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-prompt-scheduler' + schedule_lines = list() + if mode == 'Default Prompt': + print(f'[Info] CR Prompt Scheduler: Scheduler {schedule_alias} is disabled') + return (default_prompt, default_prompt, 1.0, show_help) + if mode == 'Keyframe List': + if keyframe_list == '': + print(f'[Error] CR Prompt Scheduler: No keyframe list found.') + return () + else: + lines = keyframe_list.split('\n') + for line in lines: + if schedule_format == 'Deforum': + line = line.replace(':', ',') + line = line.rstrip(',') + line = line.lstrip() + if not line.strip(): + print(f'[Warning] CR Simple Prompt Scheduler. Skipped blank line at line {i}') + continue + schedule_lines.extend([(schedule_alias, line)]) + schedule = schedule_lines + if mode == 'Schedule': + if schedule is None: + print(f'[Error] CR Prompt Scheduler: No schedule found.') + return () + if schedule_format == 'Deforum': + for item in schedule: + (alias, line) = item + line = line.replace(':', ',') + line = line.rstrip(',') + schedule_lines.extend([(schedule_alias, line)]) + schedule = schedule_lines + (current_prompt, next_prompt, current_keyframe, next_keyframe) = prompt_scheduler(schedule, schedule_alias, current_frame) + if current_prompt == '': + print(f'[Warning] CR Simple Prompt Scheduler. No prompt found for frame. Schedules should start at frame 0.') + else: + try: + current_prompt_out = prepend_text + ', ' + str(current_prompt) + ', ' + append_text + next_prompt_out = prepend_text + ', ' + str(next_prompt) + ', ' + append_text + from_index = int(current_keyframe) + to_index = int(next_keyframe) + except ValueError: + print(f'[Warning] CR Simple Text Scheduler. Invalid keyframe at frame {current_frame}') + if from_index == to_index or interpolate_prompt == 'No': + weight_out = 1.0 + else: + weight_out = (to_index - current_frame) / (to_index - from_index) + return (current_prompt_out, next_prompt_out, weight_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Prompt Text.md b/docs/CR Prompt Text.md new file mode 100644 index 0000000..761e7c2 --- /dev/null +++ b/docs/CR Prompt Text.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: CR_PromptText +- Category: Comfyroll/Essential/Core +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_PromptText节点旨在通过提示框简化获取用户输入的过程。它是交互式应用程序中的基本组件,对于引导应用程序行为至关重要。该节点的主要功能是向用户展示提示,并返回输入以及一个用于获取更多帮助的URL,通过提供上下文帮助来增强用户体验。 + +# Input types +## Required +- prompt + - 参数'prompt'对于定义向用户显示的查询或语句至关重要。它为用户的输入设定了上下文,对节点的操作至关重要,因为它直接影响与用户的交互。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- prompt + - 输出参数'prompt'代表用户对初始查询的响应。它很重要,因为它捕获了用户的输入,然后可以由应用程序进一步处理。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - 输出参数'show_help'提供了一个链接到wiki页面的URL,用户可以在该页面上找到与提示相关的更多信息或帮助。这对于指导用户完成复杂或不熟悉的任务特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_PromptText: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompt': ('STRING', {'default': 'prompt', 'multiline': True})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('prompt', 'show_help') + FUNCTION = 'get_value' + CATEGORY = icons.get('Comfyroll/Essential/Core') + + def get_value(self, prompt): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Core-Nodes#cr-prompt-text' + return (prompt, show_help) +``` \ No newline at end of file diff --git a/docs/CR Radial Gradient.md b/docs/CR Radial Gradient.md new file mode 100644 index 0000000..0b6bb7a --- /dev/null +++ b/docs/CR Radial Gradient.md @@ -0,0 +1,105 @@ +# Documentation +- Class name: CR_RadialGradient +- Category: Comfyroll/Graphics/Pattern +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_RadialGradient 节点旨在生成径向渐变图像。它提供了一种无缝的方式,可以在指定的宽度和高度上从起始颜色渐变到结束颜色,同时可以自定义径向中心和渐变距离。 + +# Input types +## Required +- width + - 宽度参数定义了输出图像的宽度。它至关重要,因为它决定了渐变图案的水平范围。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置输出图像的高度。它很关键,因为它决定了渐变图案的垂直范围。 + - Comfy dtype: INT + - Python dtype: int +- start_color + - 起始颜色参数指定径向渐变的初始颜色。它在确定渐变效果的整体外观中起着重要作用。 + - Comfy dtype: COLORS + - Python dtype: str +- end_color + - 结束颜色参数确定径向渐变的最终颜色。它在设置渐变过渡中的目的地颜色时很重要。 + - Comfy dtype: COLORS + - Python dtype: str +## Optional +- radial_center_x + - 径向中心 x 参数调整径向渐变中心的水平位置。它影响图像上颜色的分布。 + - Comfy dtype: FLOAT + - Python dtype: float +- radial_center_y + - 径向中心 y 参数设置径向渐变中心的垂直位置。它影响渐变颜色在图像上的扩散方式。 + - Comfy dtype: FLOAT + - Python dtype: float +- gradient_distance + - 渐变距离参数控制渐变的扩散,决定颜色从起始颜色到结束颜色的过渡速度。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_color_hex + - 起始颜色十六进制参数允许设置自定义的十六进制颜色作为起始颜色,为精确的颜色规格提供灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- end_color_hex + - 结束颜色十六进制参数允许指定结束颜色的自定义十六进制颜色,提供对渐变端点使用的确切颜色的控制。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - IMAGE 输出提供生成的径向渐变图像,这是节点执行的主要结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_Help + - show_Help 输出提供了一个链接到文档的链接,以获取有关使用该节点的进一步指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_RadialGradient: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'start_color': (COLORS,), 'end_color': (COLORS,), 'gradient_distance': ('FLOAT', {'default': 1, 'min': 0, 'max': 2, 'step': 0.05}), 'radial_center_x': ('FLOAT', {'default': 0.5, 'min': 0, 'max': 1, 'step': 0.05}), 'radial_center_y': ('FLOAT', {'default': 0.5, 'min': 0, 'max': 1, 'step': 0.05})}, 'optional': {'start_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'end_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_Help') + FUNCTION = 'draw' + CATEGORY = icons.get('Comfyroll/Graphics/Pattern') + + def draw(self, width, height, start_color, end_color, radial_center_x=0.5, radial_center_y=0.5, gradient_distance=1, start_color_hex='#000000', end_color_hex='#000000'): + if start_color == 'custom': + color1_rgb = hex_to_rgb(start_color_hex) + else: + color1_rgb = color_mapping.get(start_color, (255, 255, 255)) + if end_color == 'custom': + color2_rgb = hex_to_rgb(end_color_hex) + else: + color2_rgb = color_mapping.get(end_color, (0, 0, 0)) + canvas = np.zeros((height, width, 3), dtype=np.uint8) + center_x = int(radial_center_x * width) + center_y = int(radial_center_y * height) + max_distance = np.sqrt(max(center_x, width - center_x) ** 2 + max(center_y, height - center_y) ** 2) * gradient_distance + for i in range(width): + for j in range(height): + distance_to_center = np.sqrt((i - center_x) ** 2 + (j - center_y) ** 2) + t = distance_to_center / max_distance + t = max(0, min(t, 1)) + interpolated_color = [int(c1 * (1 - t) + c2 * t) for (c1, c2) in zip(color1_rgb, color2_rgb)] + canvas[j, i] = interpolated_color + (fig, ax) = plt.subplots(figsize=(width / 100, height / 100)) + ax.imshow(canvas) + plt.axis('off') + plt.tight_layout(pad=0, w_pad=0, h_pad=0) + plt.autoscale(tight=True) + img_buf = io.BytesIO() + plt.savefig(img_buf, format='png') + img = Image.open(img_buf) + image_out = pil2tensor(img.convert('RGB')) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pattern-Nodes#cr-radial-gradiant' + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Random Hex Color.md b/docs/CR Random Hex Color.md new file mode 100644 index 0000000..746e97a --- /dev/null +++ b/docs/CR Random Hex Color.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: CR_RandomHexColor +- Category: Comfyroll/Utils/Random +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_RandomHexColor 节点旨在生成随机的十六进制颜色代码。它的目的是为用户提供一组独特且随机生成的颜色,这些颜色可以用于各种图形设计或视觉应用中。该节点强调在颜色选择中创造多样性,无需手动指定,从而简化了设计过程,并提供了一种方便的方式来尝试颜色变化。 + +# Input types +## Required +- seed + - “seed”参数对节点的操作至关重要,因为它初始化了随机数生成器,确保生成的颜色是可复现的。这个特性对于在不同运行中保持一致性或用于调试目的特别重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- hex_color1 + - “hex_color1”输出提供了第一个随机生成的十六进制颜色代码。它之所以重要,是因为它代表了节点可以产生的多样化颜色选项之一,适用于直接在与颜色相关的应用中使用。 + - Comfy dtype: STRING + - Python dtype: str +- hex_color2 + - “hex_color2”输出提供了第二个独特的十六进制颜色代码。与“hex_color1”一样,它旨在为用户提供不同的颜色选择,扩大了他们的项目可用的颜色范围。 + - Comfy dtype: STRING + - Python dtype: str +- hex_color3 + - “hex_color3”输出生成了第三个不同的十六进制颜色代码。这个输出进一步增强了可以使用的颜色的多样性,为创意工作提供了更多的选择。 + - Comfy dtype: STRING + - Python dtype: str +- hex_color4 + - “hex_color4”输出代表了第四个随机生成的十六进制颜色代码。它继续扩大颜色选择的范围,确保用户在设计需求中有多种选项可供选择。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - “show_help”输出提供了一个指向文档页面的URL链接,以供进一步帮助。对于可能需要额外指导或有关节点功能信息的用户来说,这是一个有用的资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_RandomHexColor: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('STRING', 'STRING', 'STRING', 'STRING', 'STRING') + RETURN_NAMES = ('hex_color1', 'hex_color2', 'hex_color3', 'hex_color4', 'show_help') + FUNCTION = 'get_colors' + CATEGORY = icons.get('Comfyroll/Utils/Random') + + def get_colors(self, seed): + random.seed(seed) + hex_color1 = random_hex_color() + hex_color2 = random_hex_color() + hex_color3 = random_hex_color() + hex_color4 = random_hex_color() + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-random-hex-color' + return (hex_color1, hex_color2, hex_color3, hex_color4, show_help) +``` \ No newline at end of file diff --git a/docs/CR Random LoRA Stack.md b/docs/CR Random LoRA Stack.md new file mode 100644 index 0000000..dcbaf18 --- /dev/null +++ b/docs/CR Random LoRA Stack.md @@ -0,0 +1,229 @@ +# Documentation +- Class name: CR_RandomLoRAStack +- Category: Comfyroll/LoRA +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_RandomLoRAStack节点旨在将LoRA(低秩适应)模块随机堆叠到基础模型上。它根据指定的权重、机会和独占性设置智能地处理LoRA模块的选择和应用,确保模型能力的多样化和可控增强。 + +# Input types +## Required +- exclusive_mode + - 独占模式决定是否一次只能应用一个LoRA。设置为'On'时,它强制执行互斥性,确保节点的操作是非冗余且专注的。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +- stride + - 步长定义了节点重新评估LoRA堆叠的间隔。它对于控制LoRA应用的频率至关重要,从而影响节点的整体性能。 + - Comfy dtype: INT + - Python dtype: int +- force_randomize_after_stride + - 启用此参数后,节点会在一定数量的步长后随机化LoRA选择,为节点的操作增加了不可预测性的元素。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +- lora_name_1 + - 要考虑堆叠的第一个LoRA模块。它的选择可以显著改变节点的功能,引入新特性或修改现有特性。 + - Comfy dtype: STRING + - Python dtype: str +- chance_1 + - 应用第一个LoRA模块的概率。它在节点操作的随机性中扮演着关键角色,允许一定程度的可控不可预测性。 + - Comfy dtype: FLOAT + - Python dtype: float +- model_weight_1 + - 分配给第一个LoRA模块的权重,影响它对节点最终输出的影响程度。它是微调节点行为的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- clip_weight_1 + - 第一个LoRA模块的剪辑权重,可以帮助控制LoRA对节点输出影响的强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- switch_1 + - 决定第一个LoRA模块是否激活的开关。它是一种简单而有效的方法,用于在节点操作中切换LoRA模块的包含。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +## Optional +- lora_name_2 + - 可以考虑用于堆叠的第二个LoRA模块,为增强节点的能力提供额外选项。 + - Comfy dtype: STRING + - Python dtype: str +- chance_2 + - 与第二个LoRA模块相关联的概率,进一步促成了节点的随机行为。 + - Comfy dtype: FLOAT + - Python dtype: float +- model_weight_2 + - 第二个LoRA模块的权重,允许对它对节点输出的贡献进行细微控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- clip_weight_2 + - 第二个LoRA模块的剪辑权重,提供了一种调整其对节点结果影响的机制。 + - Comfy dtype: FLOAT + - Python dtype: float +- switch_2 + - 第二个LoRA模块的开关,允许在节点过程中灵活控制其激活。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +- lora_name_3 + - 堆叠的第三个LoRA模块选项,为节点的潜在功能提供进一步的多样性。 + - Comfy dtype: STRING + - Python dtype: str +- chance_3 + - 第三个LoRA模块的概率,为节点的操作增加了另一层随机性。 + - Comfy dtype: FLOAT + - Python dtype: float +- model_weight_3 + - 分配给第三个LoRA模块的权重,影响它在堆叠中对节点输出的效果。 + - Comfy dtype: FLOAT + - Python dtype: float +- clip_weight_3 + - 第三个LoRA模块的剪辑权重,允许对它对节点最终结果的影响进行细粒度控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- switch_3 + - 第三个LoRA模块的开关,提供包含或排除它在节点操作中的选项。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +- lora_stack + - 可以预应用于节点的LoRA模块的可选堆叠。这允许在进一步随机化之前进行自定义和预设LoRA堆叠。 + - Comfy dtype: LORA_STACK + - Python dtype: List[Tuple[str, float, float]] + +# Output types +- lora_stack + - 输出是已根据输入参数随机选择和加权的LoRA模块堆叠。这个堆叠在根据节点配置修改基础模型的行为方面起着关键作用。 + - Comfy dtype: LORA_STACK + - Python dtype: List[Tuple[str, float, float]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_RandomLoRAStack: + + @classmethod + def INPUT_TYPES(cls): + loras = ['None'] + folder_paths.get_filename_list('loras') + return {'required': {'exclusive_mode': (['Off', 'On'],), 'stride': ('INT', {'default': 1, 'min': 1, 'max': 1000}), 'force_randomize_after_stride': (['Off', 'On'],), 'lora_name_1': (loras,), 'switch_1': (['Off', 'On'],), 'chance_1': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'model_weight_1': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'clip_weight_1': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'lora_name_2': (loras,), 'switch_2': (['Off', 'On'],), 'chance_2': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'model_weight_2': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'clip_weight_2': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'lora_name_3': (loras,), 'switch_3': (['Off', 'On'],), 'chance_3': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'model_weight_3': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'clip_weight_3': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01})}, 'optional': {'lora_stack': ('LORA_STACK',)}} + RETURN_TYPES = ('LORA_STACK',) + FUNCTION = 'random_lora_stacker' + CATEGORY = icons.get('Comfyroll/LoRA') + UsedLorasMap = {} + StridesMap = {} + LastHashMap = {} + + @staticmethod + def getIdHash(lora_name_1: str, lora_name_2: str, lora_name_3: str) -> int: + id_set = set([lora_name_1, lora_name_2, lora_name_3]) + id_hash = hash(frozenset(id_set)) + return id_hash + + @staticmethod + def deduplicateLoraNames(lora_name_1: str, lora_name_2: str, lora_name_3: str): + is_same_1 = False + is_same_2 = False + is_same_3 = False + if lora_name_1 == lora_name_2: + is_same_1 = True + is_same_2 = True + if lora_name_1 == lora_name_3: + is_same_1 = True + is_same_3 = True + if lora_name_2 == lora_name_3: + is_same_2 = True + is_same_3 = True + if is_same_1: + lora_name_1 = lora_name_1 + 'CR_RandomLoRAStack_1' + if is_same_2: + lora_name_2 = lora_name_2 + 'CR_RandomLoRAStack_2' + if is_same_3: + lora_name_3 = lora_name_3 + 'CR_RandomLoRAStack_3' + return (lora_name_1, lora_name_2, lora_name_3) + + @staticmethod + def cleanLoraName(lora_name) -> str: + if 'CR_RandomLoRAStack_1' in lora_name: + lora_name = lora_name.replace('CR_RandomLoRAStack_1', '') + elif 'CR_RandomLoRAStack_2' in lora_name: + lora_name = lora_name.replace('CR_RandomLoRAStack_2', '') + elif 'CR_RandomLoRAStack_3' in lora_name: + lora_name = lora_name.replace('CR_RandomLoRAStack_3', '') + return lora_name + + @classmethod + def IS_CHANGED(cls, exclusive_mode, stride, force_randomize_after_stride, lora_name_1, model_weight_1, clip_weight_1, switch_1, chance_1, lora_name_2, model_weight_2, clip_weight_2, switch_2, chance_2, lora_name_3, model_weight_3, clip_weight_3, switch_3, chance_3, lora_stack=None): + lora_set = set() + (lora_name_1, lora_name_2, lora_name_3) = CR_RandomLoRAStack.deduplicateLoraNames(lora_name_1, lora_name_2, lora_name_3) + id_hash = CR_RandomLoRAStack.getIdHash(lora_name_1, lora_name_2, lora_name_3) + if id_hash not in CR_RandomLoRAStack.StridesMap: + CR_RandomLoRAStack.StridesMap[id_hash] = 0 + CR_RandomLoRAStack.StridesMap[id_hash] += 1 + if stride > 1 and CR_RandomLoRAStack.StridesMap[id_hash] < stride and (id_hash in CR_RandomLoRAStack.LastHashMap): + return CR_RandomLoRAStack.LastHashMap[id_hash] + else: + CR_RandomLoRAStack.StridesMap[id_hash] = 0 + total_on = 0 + if lora_name_1 != 'None' and switch_1 == 'On' and (chance_1 > 0.0): + total_on += 1 + if lora_name_2 != 'None' and switch_2 == 'On' and (chance_2 > 0.0): + total_on += 1 + if lora_name_3 != 'None' and switch_3 == 'On' and (chance_3 > 0.0): + total_on += 1 + + def perform_randomization() -> set: + _lora_set = set() + rand_1 = random() + rand_2 = random() + rand_3 = random() + apply_1 = True if rand_1 <= chance_1 and switch_1 == 'On' else False + apply_2 = True if rand_2 <= chance_2 and switch_2 == 'On' else False + apply_3 = True if rand_3 <= chance_3 and switch_3 == 'On' else False + num_to_apply = sum([apply_1, apply_2, apply_3]) + if exclusive_mode == 'On' and num_to_apply > 1: + rand_dict = {} + if apply_1: + rand_dict[1] = rand_1 + if apply_2: + rand_dict[2] = rand_2 + if apply_3: + rand_dict[3] = rand_3 + sorted_rands = sorted(rand_dict.keys(), key=lambda k: rand_dict[k]) + if sorted_rands[0] == 1: + apply_2 = False + apply_3 = False + elif sorted_rands[0] == 2: + apply_1 = False + apply_3 = False + elif sorted_rands[0] == 3: + apply_1 = False + apply_2 = False + if lora_name_1 != 'None' and switch_1 == 'On' and apply_1: + _lora_set.add(lora_name_1) + if lora_name_2 != 'None' and switch_2 == 'On' and apply_2: + _lora_set.add(lora_name_2) + if lora_name_3 != 'None' and switch_3 == 'On' and apply_3: + _lora_set.add(lora_name_3) + return _lora_set + last_lora_set = CR_RandomLoRAStack.UsedLorasMap.get(id_hash, set()) + lora_set = perform_randomization() + if force_randomize_after_stride == 'On' and len(last_lora_set) > 0 and (total_on > 1): + while lora_set == last_lora_set: + lora_set = perform_randomization() + CR_RandomLoRAStack.UsedLorasMap[id_hash] = lora_set + hash_str = str(hash(frozenset(lora_set))) + CR_RandomLoRAStack.LastHashMap[id_hash] = hash_str + return hash_str + + def random_lora_stacker(self, exclusive_mode, stride, force_randomize_after_stride, lora_name_1, model_weight_1, clip_weight_1, switch_1, chance_1, lora_name_2, model_weight_2, clip_weight_2, switch_2, chance_2, lora_name_3, model_weight_3, clip_weight_3, switch_3, chance_3, lora_stack=None): + lora_list = list() + if lora_stack is not None: + lora_list.extend([l for l in lora_stack if l[0] != 'None']) + (lora_name_1, lora_name_2, lora_name_3) = CR_RandomLoRAStack.deduplicateLoraNames(lora_name_1, lora_name_2, lora_name_3) + id_hash = CR_RandomLoRAStack.getIdHash(lora_name_1, lora_name_2, lora_name_3) + used_loras = CR_RandomLoRAStack.UsedLorasMap.get(id_hash, set()) + if lora_name_1 != 'None' and switch_1 == 'On' and (lora_name_1 in used_loras): + (lora_list.extend([(CR_RandomLoRAStack.cleanLoraName(lora_name_1), model_weight_1, clip_weight_1)]),) + if lora_name_2 != 'None' and switch_2 == 'On' and (lora_name_2 in used_loras): + (lora_list.extend([(CR_RandomLoRAStack.cleanLoraName(lora_name_2), model_weight_2, clip_weight_2)]),) + if lora_name_3 != 'None' and switch_3 == 'On' and (lora_name_3 in used_loras): + (lora_list.extend([(CR_RandomLoRAStack.cleanLoraName(lora_name_3), model_weight_3, clip_weight_3)]),) + return (lora_list,) +``` \ No newline at end of file diff --git a/docs/CR Random Multiline Colors.md b/docs/CR Random Multiline Colors.md new file mode 100644 index 0000000..4573351 --- /dev/null +++ b/docs/CR Random Multiline Colors.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: CR_RandomMultilineColors +- Category: Comfyroll/Utils/Random +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_RandomMultilineColors节点旨在生成一个包含随机颜色代码的多行字符串。它的目的是提供一组多样化的颜色代码,这些代码可以用于各种应用,如设计、可视化或任何需要随机颜色调色板的场景。节点的功能集中在基于指定的值类型创建不同格式的颜色代码,使其具有多功能性和适应性,以满足不同的需求。 + +# Input types +## Required +- seed + - 种子参数对于确保随机颜色生成过程的可重复性至关重要。通过设置种子,用户可以在不同的运行中获得相同的一组随机颜色,这对于测试或需要一致结果时特别有用。 + - Comfy dtype: INT + - Python dtype: int +- value_type + - value_type参数决定了节点生成的颜色代码的格式。它允许用户指定他们是否希望颜色以十六进制格式、RGB格式,或者使用matplotlib xkcd颜色集中的颜色。这种灵活性迎合了广泛的用例和偏好。 + - Comfy dtype: COMBO['rgb', 'hex color', 'matplotlib xkcd'] + - Python dtype: str +- rows + - rows参数决定了节点将生成的颜色代码行数。这允许用户控制生成的颜色代码的数量,可以根据应用程序或项目的具体要求进行调整。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- multiline_text + - multiline_text输出包含生成的随机颜色代码字符串。每一行代表由value_type参数指定格式的单独颜色代码。这个输出很重要,因为它是节点操作的主要结果,为用户提供了所需的随机颜色调色板。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - show_help输出提供了指向节点文档页面的URL链接。这对于需要额外信息或指导的用户来说特别有用,他们可能需要了解如何使用节点或解释其结果。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_RandomMultilineColors: + + @classmethod + def INPUT_TYPES(cls): + types = ['rgb', 'hex color', 'matplotlib xkcd'] + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'value_type': (types,), 'rows': ('INT', {'default': 5, 'min': 1, 'max': 2048})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('multiline_text', 'show_help') + FUNCTION = 'generate' + CATEGORY = icons.get('Comfyroll/Utils/Random') + + def generate(self, value_type, rows, seed): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-random-multiline-colors' + random.seed(seed) + xkcd_colors = mcolors.XKCD_COLORS + if value_type == 'hex color': + choice_str = '0123456789ABCDEF' + if value_type == 'hex color': + multiline_text = '\n'.join(['#' + ''.join((random.choice(choice_str) for _ in range(6))) for _ in range(rows)]) + elif value_type == 'rgb': + multiline_text = '\n'.join([f'{random.randint(0, 255)},{random.randint(0, 255)},{random.randint(0, 255)}' for _ in range(rows)]) + elif value_type == 'matplotlib xkcd': + multiline_text = '\n'.join([random.choice(list(xkcd_colors.keys())).replace('xkcd:', '') for _ in range(rows)]) + else: + pass + return (multiline_text, show_help) +``` \ No newline at end of file diff --git a/docs/CR Random Multiline Values.md b/docs/CR Random Multiline Values.md new file mode 100644 index 0000000..e431602 --- /dev/null +++ b/docs/CR Random Multiline Values.md @@ -0,0 +1,84 @@ +# Documentation +- Class name: CR_RandomMultilineValues +- Category: Comfyroll/Utils/Random +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_RandomMultilineValues 节点旨在根据指定的值类型和格式化选项生成随机多行文本。它可以产生各种格式的字符串,如二进制、十进制、自然数、十六进制、字母、字母数字或自定义。节点允许设置行数和每行字符串的长度,确保输出根据不同用例进行调整,具有高度的通用性。 + +# Input types +## Required +- seed + - seed 参数用于初始化随机数生成器以产生可重复的结果。它对于确保生成的随机文本的一致性至关重要,尤其是在调试或需要相同序列的随机值时。 + - Comfy dtype: INT + - Python dtype: int +- value_type + - 值类型参数决定了生成文本的格式。它可以设置为二进制、十进制、自然数、十六进制、字母、字母数字或自定义,这决定了用于随机文本生成的字符集。 + - Comfy dtype: STRING + - Python dtype: str +- rows + - 行数参数指定了生成文本中的行数。它直接影响输出的长度,允许用户控制生成的数据量。 + - Comfy dtype: INT + - Python dtype: int +- string_length + - 字符串长度参数定义了生成文本中每行的字符数。它对于设置各个文本字符串的粒度至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- custom_values + - 当值类型设置为自定义时,custom_values 参数允许用户定义自己的字符集以生成随机文本。这为需要非标准字符集的特定用例提供了灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- prepend_text + - prepend_text 参数在生成的文本的每一行开头添加一个固定字符串。这对于添加输出的前缀非常有用,这对于格式化或上下文目的可能很重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- multiline_text + - multiline_text 输出包含生成的随机文本,根据指定的行数和字符串长度参数格式化为多行。它代表了节点操作的主要结果。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - show_help 输出提供了指向节点文档页面的 URL 链接,为用户提供了关于如何有效使用该节点的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_RandomMultilineValues: + + @classmethod + def INPUT_TYPES(cls): + types = ['binary', 'decimal', 'natural', 'hexadecimal', 'alphabetic', 'alphanumeric', 'custom'] + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'value_type': (types,), 'rows': ('INT', {'default': 5, 'min': 1, 'max': 2048}), 'string_length': ('INT', {'default': 5, 'min': 1, 'max': 1024}), 'custom_values': ('STRING', {'multiline': False, 'default': '123ABC'}), 'prepend_text': ('STRING', {'multiline': False, 'default': ''})}} + RETURN_TYPES = (any_type, 'STRING') + RETURN_NAMES = ('multiline_text', 'show_help') + FUNCTION = 'generate' + CATEGORY = icons.get('Comfyroll/Utils/Random') + + def generate(self, value_type, rows, string_length, custom_values, seed, prepend_text): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-random-multiline-values' + random.seed(seed) + if value_type == 'binary': + choice_str = '01' + elif value_type == 'decimal': + choice_str = '0123456789' + elif value_type == 'natural': + choice_str = '123456789' + elif value_type == 'hexadecimal': + choice_str = '0123456789ABCDEF' + elif value_type == 'alphabetic': + choice_str = string.ascii_letters + elif value_type == 'alphanumeric': + choice_str = string.ascii_letters + string.digits + elif value_type == 'custom': + choice_str = custom_values + else: + pass + multiline_text = '\n'.join([prepend_text + ''.join((random.choice(choice_str) for _ in range(string_length))) for _ in range(rows)]) + return (multiline_text, show_help) +``` \ No newline at end of file diff --git a/docs/CR Random Panel Codes.md b/docs/CR Random Panel Codes.md new file mode 100644 index 0000000..da9f7d2 --- /dev/null +++ b/docs/CR Random Panel Codes.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: CR_RandomPanelCodes +- Category: Comfyroll/Utils/Random +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_RandomPanelCodes 是一个用于生成基于用户定义参数的随机面板代码列表的节点。它通过创建指定数量的行,每行包含给定长度的字符字符串来运行。该节点通过使用随机数生成器的种子确保输出的随机性,并允许定制用于形成代码的字符集。 + +# Input types +## Required +- seed + - seed 参数初始化随机数生成器,确保生成的随机代码是可重现的。它在节点的执行中起着关键作用,通过为随机化过程提供一个一致的起点,这对于在不同运行中生成相同的代码集至关重要。 + - Comfy dtype: INT + - Python dtype: int +- rows + - rows 参数确定生成的面板代码中的行数。它直接影响节点生成的代码数量。调整此参数允许用户控制输出的大小,满足他们对代码生成的具体需求。 + - Comfy dtype: INT + - Python dtype: int +- string_length + - string_length 参数指定生成的面板代码中每个字符串的长度。它很重要,因为它决定了每个代码的复杂性和唯一性。通过改变这个参数,用户可以影响所产生代码的细节水平。 + - Comfy dtype: INT + - Python dtype: int +- values + - values 参数定义了构建面板代码的字符集。它至关重要,因为它决定了用于生成代码的字符池。此参数允许定制代码的组成,适应不同应用的各种需求。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- multiline_text + - multiline_text 输出包含在多行中排列的生成的面板代码,为用户提供了一种可读且有序的格式。这个输出很重要,因为它代表了节点操作的主要结果,以结构化的方式封装了随机代码。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - show_help 输出提供了指向节点文档的 URL 链接。这对于寻求有关如何有效使用节点的额外信息或指导的用户来说很有用。它作为节点文档的直接参考,方便了使用和理解。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_RandomPanelCodes: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'rows': ('INT', {'default': 5, 'min': 1, 'max': 2048}), 'string_length': ('INT', {'default': 5, 'min': 1, 'max': 1024}), 'values': ('STRING', {'multiline': False, 'default': '123'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('multiline_text', 'show_help') + FUNCTION = 'generate' + CATEGORY = icons.get('Comfyroll/Utils/Random') + + def generate(self, rows, string_length, values, seed): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-random-panel-codes' + random.seed(seed) + start_letter = random.choice('HV') + value_range = random.choice(values) + codes = [] + for _ in range(rows): + number = ''.join((random.choice(values) for _ in range(string_length))) + codes.append(f'{start_letter}{number}') + multiline_text = '\n'.join(codes) + return (multiline_text, show_help) +``` \ No newline at end of file diff --git a/docs/CR Random RGB Gradient.md b/docs/CR Random RGB Gradient.md new file mode 100644 index 0000000..fc83029 --- /dev/null +++ b/docs/CR Random RGB Gradient.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: CR_RandomRGBGradient +- Category: Comfyroll/Utils/Random +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_RandomRGBGradient 是一个用于生成随机 RGB 渐变的节点。它通过创建一系列平滑过渡的 RGB 值来操作,从一个颜色过渡到下一个颜色,确保了视觉上吸引人的渐变效果。该节点特别适用于需要为项目提供动态和多样化配色方案的设计师和开发者。 + +# Input types +## Required +- seed + - “seed”参数对于节点的随机数生成过程至关重要。它确保生成的 RGB 值是可复现的,允许在不同运行中获得一致的结果。这在需要多次生成相同渐变的场景中尤为重要。 + - Comfy dtype: INT + - Python dtype: int +- rows + - “rows”参数决定了生成渐变中的颜色停止数量。较高的值会导致更详细的渐变,其中包含更多的中间颜色,而较低的值则会导致更简单的渐变,颜色过渡较少。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- multiline_text + - “multiline_text”输出包含以多行格式生成的 RGB 渐变数据。每一行代表渐变中的一个颜色停止,RGB 值由逗号分隔。这种格式方便在需要逐行输入渐变数据的各种应用程序中使用。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - “show_help”输出提供了指向节点文档页面的 URL 链接。这对于需要额外信息或有效使用节点的指导的用户非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_RandomRGBGradient: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'rows': ('INT', {'default': 5, 'min': 1, 'max': 2048})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('multiline_text', 'show_help') + FUNCTION = 'generate' + CATEGORY = icons.get('Comfyroll/Utils/Random') + + def generate(self, rows, seed): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-random-RGB-gradient' + random.seed(seed) + temp = 0 + multiline_text = '' + for i in range(1, rows + 1): + print(temp) + if temp <= 99 - rows + i: + upper_bound = min(99, temp + (99 - temp) // (rows - i + 1)) + current_value = random.randint(temp, upper_bound) + multiline_text += f'{current_value}:{random.randint(0, 255)},{random.randint(0, 255)},{random.randint(0, 255)}\n' + temp = current_value + 1 + return (multiline_text, show_help) +``` \ No newline at end of file diff --git a/docs/CR Random RGB.md b/docs/CR Random RGB.md new file mode 100644 index 0000000..74f255c --- /dev/null +++ b/docs/CR Random RGB.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: CR_RandomRGB +- Category: Comfyroll/Utils/Random +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_RandomRGB节点旨在生成随机的RGB颜色代码。它作为需要随机颜色生成的应用程序的实用工具,例如在图形设计或视觉效果中。该节点确保每次执行都产生一组独特的颜色,增强了颜色选择的多样性和随机性。 + +# Input types +## Required +- seed + - 种子参数对于初始化随机数生成器以确保生成的随机RGB颜色的可重复性至关重要。它允许用户控制随机性并在需要时获得相同的颜色集,这对于不同执行中一致的颜色方案至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- rgb_1 + - 第一个输出参数'rgb_1'提供了一个随机生成的RGB颜色代码的字符串表示。它被格式化为三个整数的逗号分隔列表,每个整数的范围从0到255,分别代表颜色的红色、绿色和蓝色组件。 + - Comfy dtype: STRING + - Python dtype: str +- rgb_2 + - 第二个输出参数'rgb_2'提供了另一个不同随机生成的RGB颜色代码的字符串表示,类似于'rgb_1',但具有不同的值,以确保颜色选择的多样性。 + - Comfy dtype: STRING + - Python dtype: str +- rgb_3 + - 第三个输出参数'rgb_3'提供了另一个独特的随机生成的RGB颜色代码的字符串表示,进一步增强了不同应用程序可用颜色的多样性。 + - Comfy dtype: STRING + - Python dtype: str +- rgb_4 + - 第四个输出参数'rgb_4'提供了另一个不同RGB颜色代码的字符串表示,增加了可以在各种场景中使用的随机颜色集合。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - 'show_help'输出参数提供了一个URL链接到文档页面,以获取有关节点功能和使用的进一步帮助和信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_RandomRGB: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('STRING', 'STRING', 'STRING', 'STRING', 'STRING') + RETURN_NAMES = ('rgb_1', 'rgb_2', 'rgb_3', 'rgb_4', 'show_help') + FUNCTION = 'get_colors' + CATEGORY = icons.get('Comfyroll/Utils/Random') + + def get_colors(self, seed): + random.seed(seed) + rgb_1 = random_rgb() + rgb_2 = random_rgb() + rgb_3 = random_rgb() + rgb_4 = random_rgb() + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-random-rgb' + return (rgb_1, rgb_2, rgb_3, rgb_4, show_help) +``` \ No newline at end of file diff --git a/docs/CR Random Shape Pattern.md b/docs/CR Random Shape Pattern.md new file mode 100644 index 0000000..97fc855 --- /dev/null +++ b/docs/CR Random Shape Pattern.md @@ -0,0 +1,89 @@ +# Documentation +- Class name: CR_RandomShapePattern +- Category: Comfyroll/Graphics/Shape +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_RandomShapePattern 是一个用于生成由随机放置的形状组成的图案图像的节点。它提供了一种创造性的方法来制作视觉上多样化和结构化的图案,适用于艺术表达或数据可视化目的。该节点利用随机性来选择形状、颜色和位置,确保每个输出都是独一无二的。 + +# Input types +## Required +- width + - 宽度决定了输出图像的水平范围。这是一个关键参数,因为它决定了图案的整体规模以及图案中单个形状的大小。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度设置了生成图像的垂直尺寸,影响图案内形状的垂直间距和排列。 + - Comfy dtype: INT + - Python dtype: int +- num_rows + - 行数决定了图案网格的垂直结构,影响形状沿图像高度的分布。 + - Comfy dtype: INT + - Python dtype: int +- num_cols + - 列数指定了图案网格的水平结构,决定了形状在图像宽度上的分布。 + - Comfy dtype: INT + - Python dtype: int +- color1 + - 颜色1是用于随机填充图案内形状的两种颜色之一。它有助于整体配色方案和生成图像的视觉对比度。 + - Comfy dtype: COLORS + - Python dtype: str +- color2 + - 颜色2是用于填充图案中形状的第二种颜色选项。它与颜色1一起使用,以创建多样化且视觉上吸引人的颜色组合。 + - Comfy dtype: COLORS + - Python dtype: str +## Optional +- color1_hex + - 颜色1十六进制允许为颜色1使用自定义的十六进制颜色值,为形状的颜色选择提供更大的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- color2_hex + - 颜色2十六进制提供了一种为颜色2指定自定义十六进制颜色值的方法,增强了节点产生各种颜色组合的能力。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - 图像输出是节点的主要结果,展示了由不同颜色和大小的随机放置形状组成的图案图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个 URL 链接到文档页面,以获取有关节点使用和功能的更多帮助和信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_RandomShapePattern: + + @classmethod + def INPUT_TYPES(cls): + shapes = ['circle', 'oval', 'square', 'diamond', 'triangle', 'hexagon', 'octagon', 'half circle', 'quarter circle', 'starburst', 'star', 'cross'] + return {'required': {'width': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'num_rows': ('INT', {'default': 5, 'min': 1, 'max': 128}), 'num_cols': ('INT', {'default': 5, 'min': 1, 'max': 128}), 'color1': (COLORS,), 'color2': (COLORS,)}, 'optional': {'color1_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'color2_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'plot_random_shapes' + CATEGORY = icons.get('Comfyroll/Graphics/Shape') + + def plot_random_shapes(self, num_rows, num_cols, width, height, color1, color2, color1_hex='#000000', color2_hex='#000000'): + color1 = get_color_values(color1, color1_hex, color_mapping) + color2 = get_color_values(color2, color2_hex, color_mapping) + image = Image.new('RGB', (width, height), color='white') + draw = ImageDraw.Draw(image) + shape_functions = [draw_circle, draw_oval, draw_diamond, draw_square, draw_triangle, draw_hexagon, draw_octagon, draw_half_circle, draw_quarter_circle, draw_starburst, draw_star, draw_cross] + for row in range(num_rows): + for col in range(num_cols): + shape_function = random.choice(shape_functions) + color = random.choice([color1, color2]) + size = random.uniform(20, min(width, height) / 2) + aspect_ratio = random.uniform(0.5, 2.0) + center_x = col * (width / num_cols) + width / num_cols / 2 + center_y = row * (height / num_rows) + height / num_rows / 2 + shape_function(draw, center_x, center_y, size, aspect_ratio, color) + image_out = pil2tensor(image) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pattern-Nodes-2#cr-random-shape-pattern' + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Random Weight LoRA.md b/docs/CR Random Weight LoRA.md new file mode 100644 index 0000000..b497ad4 --- /dev/null +++ b/docs/CR Random Weight LoRA.md @@ -0,0 +1,107 @@ +# Documentation +- Class name: CR_RandomWeightLoRA +- Category: Comfyroll/LoRA +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_RandomWeightLoRA 节点旨在为神经网络模型中的 LoRA(低秩适应)层动态分配随机权重。它通过调整特定 LoRA 层的影响,提供了一种将可变性和定制性引入模型性能的机制。该节点通过为给定参数集生成唯一哈希值来操作,然后使用该哈希值来确定是否应分配新的随机权重。这种方法确保了模型在适应不同输入条件的同时,其输出保持一定程度的不可预测性。 + +# Input types +## Required +- stride + - 步幅参数对于确定节点操作的步长至关重要。它影响节点处理输入数据的频率,并且可以显著影响节点执行的效率和结果。 + - Comfy dtype: INT + - Python dtype: int +- force_randomize_after_stride + - 此参数指示节点是否应在一定数量的步幅后强制随机化权重。它对于控制随机性并确保节点不会陷入可预测的模式非常重要。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +- lora_name + - LoRA 名称参数指定节点将针对哪个低秩适应层。这个选择至关重要,因为它决定了将对其权重进行随机化的特定层。 + - Comfy dtype: STRING + - Python dtype: str +- switch + - 开关参数作为启用或禁用节点随机权重分配特性的开关。它通过控制随机化过程是否激活,在节点的功能中扮演关键角色。 + - Comfy dtype: COMBO['Off', 'On'] + - Python dtype: str +- weight_min + - weight_min 参数为可以分配给 LoRA 层的随机权重范围设定了下限。它对于定义节点操作的范围至关重要,并影响节点输出的可变性。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight_max + - weight_max 参数设置了随机权重范围的上限。它与 weight_min 配合使用,确保分配的权重落在指定的区间内,从而控制节点的行为。 + - Comfy dtype: FLOAT + - Python dtype: float +- clip_weight + - clip_weight 参数用于将分配的权重剪切或限制在某个特定值。它确保权重不会超过预定义的阈值,这对于维护节点操作的稳定性至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- lora_stack + - 可选的 lora_stack 参数允许将额外的 LoRA 层包含在节点处理中。它提供了一种扩展节点能力并根据手头任务的具体要求定制其行为的方法。 + - Comfy dtype: LORA_STACK + - Python dtype: List[Tuple[str, float, float]] + +# Output types +- lora_stack + - lora_stack 输出参数代表了节点执行后带有分配权重的修改后的 LoRA 层列表。它很重要,因为它传达了节点的最终输出,反映了应用于模型的定制。 + - Comfy dtype: LORA_STACK + - Python dtype: List[Tuple[str, float, float]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CR_RandomWeightLoRA: + + @classmethod + def INPUT_TYPES(cls): + loras = ['None'] + folder_paths.get_filename_list('loras') + return {'required': {'stride': ('INT', {'default': 1, 'min': 1, 'max': 1000}), 'force_randomize_after_stride': (['Off', 'On'],), 'lora_name': (loras,), 'switch': (['Off', 'On'],), 'weight_min': ('FLOAT', {'default': 0.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'weight_max': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'clip_weight': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01})}, 'optional': {'lora_stack': ('LORA_STACK',)}} + RETURN_TYPES = ('LORA_STACK',) + FUNCTION = 'random_weight_lora' + CATEGORY = icons.get('Comfyroll/LoRA') + LastWeightMap = {} + StridesMap = {} + LastHashMap = {} + + @staticmethod + def getIdHash(lora_name: str, force_randomize_after_stride, stride, weight_min, weight_max, clip_weight) -> int: + fl_str = f'{lora_name}_{force_randomize_after_stride}_{stride}_{weight_min:.2f}_{weight_max:.2f}_{clip_weight:.2f}' + return hashlib.sha256(fl_str.encode('utf-8')).hexdigest() + + @classmethod + def IS_CHANGED(cls, stride, force_randomize_after_stride, lora_name, switch, weight_min, weight_max, clip_weight, lora_stack=None): + id_hash = CR_RandomWeightLoRA.getIdHash(lora_name, force_randomize_after_stride, stride, weight_min, weight_max, clip_weight) + if switch == 'Off': + return id_hash + '_Off' + if lora_name == 'None': + return id_hash + if id_hash not in CR_RandomWeightLoRA.StridesMap: + CR_RandomWeightLoRA.StridesMap[id_hash] = 0 + CR_RandomWeightLoRA.StridesMap[id_hash] += 1 + if stride > 1 and CR_RandomWeightLoRA.StridesMap[id_hash] < stride and (id_hash in CR_RandomWeightLoRA.LastHashMap): + return CR_RandomWeightLoRA.LastHashMap[id_hash] + else: + CR_RandomWeightLoRA.StridesMap[id_hash] = 0 + last_weight = CR_RandomWeightLoRA.LastWeightMap.get(id_hash, None) + weight = uniform(weight_min, weight_max) + if last_weight is not None: + while weight == last_weight: + weight = uniform(weight_min, weight_max) + CR_RandomWeightLoRA.LastWeightMap[id_hash] = weight + hash_str = f'{id_hash}_{weight:.3f}' + CR_RandomWeightLoRA.LastHashMap[id_hash] = hash_str + return hash_str + + def random_weight_lora(self, stride, force_randomize_after_stride, lora_name, switch, weight_min, weight_max, clip_weight, lora_stack=None): + id_hash = CR_RandomWeightLoRA.getIdHash(lora_name, force_randomize_after_stride, stride, weight_min, weight_max, clip_weight) + lora_list = list() + if lora_stack is not None: + lora_list.extend([l for l in lora_stack if l[0] != 'None']) + weight = CR_RandomWeightLoRA.LastWeightMap.get(id_hash, 0.0) + if lora_name != 'None' and switch == 'On': + (lora_list.extend([(lora_name, weight, clip_weight)]),) + return (lora_list,) +``` \ No newline at end of file diff --git a/docs/CR Repeater.md b/docs/CR Repeater.md new file mode 100644 index 0000000..0a45aee --- /dev/null +++ b/docs/CR Repeater.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: CR_Repeater +- Category: Comfyroll/List/Utils +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_Repeater 是一个实用工具节点,旨在将列表中的项重复指定的次数。它接收一个项列表和一个表示重复次数的整数,然后输出一个新列表,其中每个项根据给定的计数重复。这个节点特别适用于需要多次处理相同数据而不改变原始列表的场景。 + +# Input types +## Required +- input_data + - ‘input_data’参数代表要重复的项列表。它是节点操作的基本部分,因为它决定了将要生成的新列表的内容。这个参数的影响是直接的,因为它决定了将重复什么,从而影响最终的输出列表。 + - Comfy dtype: any_type + - Python dtype: List[Any] +- repeats + - ‘repeats’参数指定‘input_data’列表中每个项应该重复的次数。它是一个关键元素,因为它直接影响输出列表的长度。‘repeats’的值必须是一个正整数,确保重复过程是有意义的,并且输出列表正确形成。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- list + - ‘list’输出参数是重复过程的结果,包含从‘input_data’重复‘repeats’次的每个项。它很重要,因为它代表了原始列表的转换版本,这是节点功能的主要目标。 + - Comfy dtype: STRING + - Python dtype: List[str] +- show_help + - ‘show_help’输出提供了一个URL链接到与CR_Repeater节点相关联的文档或帮助页面。它作为用户寻求有关如何有效使用节点的更多信息或帮助的快速参考。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_Repeater: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input_data': (any_type,), 'repeats': ('INT', {'default': 1, 'min': 1, 'max': 99999})}} + RETURN_TYPES = (any_type, 'STRING') + RETURN_NAMES = ('list', 'show_help') + OUTPUT_IS_LIST = (True, False) + FUNCTION = 'repeat_list_items' + CATEGORY = icons.get('Comfyroll/List/Utils') + + def repeat_list_items(self, input_data, repeats): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-repeater' + new_list = [] + if isinstance(input_data, list): + new_list = [] + for item in input_data: + new_list.extend([item] * repeats) + return (new_list, show_help) + else: + return ([input_data] * repeats, show_help) +``` \ No newline at end of file diff --git a/docs/CR SD1.5 Aspect Ratio.md b/docs/CR SD1.5 Aspect Ratio.md new file mode 100644 index 0000000..eb6bc33 --- /dev/null +++ b/docs/CR SD1.5 Aspect Ratio.md @@ -0,0 +1,107 @@ +# Documentation +- Class name: CR_AspectRatioSD15 +- Category: Comfyroll/Aspect Ratio +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_AspectRatioSD15 是一个用于管理和调整图像宽高比的节点。它允许用户选择预定义的宽高比或输入自定义尺寸,并提供交换尺寸和放大图像的选项。该节点的主要功能是确保图像被正确缩放和定向,以满足各种显示或打印需求。 + +# Input types +## Required +- width + - 宽度是一个关键参数,它定义了图像的水平尺寸。它与高度参数一起工作,以确定图像的宽高比。节点使用这个值来计算输出的正确缩放和尺寸。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度是一个关键参数,它设置了图像的垂直尺寸。当与宽度参数配对时,它对于保持所需的宽高比至关重要。节点利用这个参数确保图像的垂直缩放是准确的。 + - Comfy dtype: INT + - Python dtype: int +- aspect_ratio + - 宽高比参数至关重要,因为它决定了图像宽度和高度之间的比例关系。它提供了预定义比率的选择或自定义输入的选项,允许在图像格式设置中具有灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- swap_dimensions + - swap_dimensions 参数允许用户在宽度和高度值之间切换。当宽高比需要不同的方向或用户需要手动切换尺寸时,此功能非常有用。 + - Comfy dtype: STRING + - Python dtype: str +- upscale_factor + - upscale_factor 参数对于控制图像的放大倍数很重要。它将原始尺寸相乘以实现更大的图像尺寸,同时不影响宽高比。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - 批量大小是一个重要的参数,它决定了同时处理的图像数量。当处理大量图像时,它对于优化性能特别有用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- width + - 宽度输出参数表示在应用所选宽高比和任何缩放因子后图像的最终水平尺寸。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度输出参数表示在考虑宽高比和缩放调整后图像的最终垂直尺寸。 + - Comfy dtype: INT + - Python dtype: int +- upscale_factor + - upscale_factor 输出反映了应用于图像的放大级别,以增加其大小。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - 批量大小输出参数表明在单个批次中处理的图像数量,这对于了解节点的吞吐量至关重要。 + - Comfy dtype: INT + - Python dtype: int +- empty_latent + - empty_latent 输出参数为图像批次提供了一个空的潜在空间表示,它可以用于下游任务中的进一步处理或分析。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- show_help + - show_help 输出参数提供了一个链接到文档页面的 URL,以获取有关使用该节点的额外指导和信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_AspectRatioSD15: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + aspect_ratios = ['custom', '1:1 square 512x512', '1:1 square 1024x1024', '2:3 portrait 512x768', '3:4 portrait 512x682', '3:2 landscape 768x512', '4:3 landscape 682x512', '16:9 cinema 910x512', '1.85:1 cinema 952x512', '2:1 cinema 1024x512', '2.39:1 anamorphic 1224x512'] + return {'required': {'width': ('INT', {'default': 512, 'min': 64, 'max': 8192}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 8192}), 'aspect_ratio': (aspect_ratios,), 'swap_dimensions': (['Off', 'On'],), 'upscale_factor': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 100.0, 'step': 0.1}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}} + RETURN_TYPES = ('INT', 'INT', 'FLOAT', 'INT', 'LATENT', 'STRING') + RETURN_NAMES = ('width', 'height', 'upscale_factor', 'batch_size', 'empty_latent', 'show_help') + FUNCTION = 'Aspect_Ratio' + CATEGORY = icons.get('Comfyroll/Aspect Ratio') + + def Aspect_Ratio(self, width, height, aspect_ratio, swap_dimensions, upscale_factor, batch_size): + if aspect_ratio == '2:3 portrait 512x768': + (width, height) = (512, 768) + elif aspect_ratio == '3:2 landscape 768x512': + (width, height) = (768, 512) + elif aspect_ratio == '1:1 square 512x512': + (width, height) = (512, 512) + elif aspect_ratio == '1:1 square 1024x1024': + (width, height) = (1024, 1024) + elif aspect_ratio == '16:9 cinema 910x512': + (width, height) = (910, 512) + elif aspect_ratio == '3:4 portrait 512x682': + (width, height) = (512, 682) + elif aspect_ratio == '4:3 landscape 682x512': + (width, height) = (682, 512) + elif aspect_ratio == '1.85:1 cinema 952x512': + (width, height) = (952, 512) + elif aspect_ratio == '2:1 cinema 1024x512': + (width, height) = (1024, 512) + elif aspect_ratio == '2.39:1 anamorphic 1224x512': + (width, height) = (1224, 512) + if swap_dimensions == 'On': + (width, height) = (height, width) + latent = torch.zeros([batch_size, 4, height // 8, width // 8]) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Aspect-Ratio-Nodes#cr-sd15-aspect-ratio' + return (width, height, upscale_factor, batch_size, {'samples': latent}, show_help) +``` \ No newline at end of file diff --git a/docs/CR SDXL Aspect Ratio.md b/docs/CR SDXL Aspect Ratio.md new file mode 100644 index 0000000..6e9630a --- /dev/null +++ b/docs/CR SDXL Aspect Ratio.md @@ -0,0 +1,105 @@ +# Documentation +- Class name: CR_SDXLAspectRatio +- Category: Comfyroll/Aspect Ratio +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SDXLAspectRatio节点旨在根据指定的纵横比调整图像尺寸。它允许用户从预定义的纵横比列表中选择或输入自定义尺寸。该节点还提供选项来交换维度并应用放大因子到结果图像大小。其主要功能是确保输出符合所需的纵横比,从而促进需要特定尺寸的图像处理任务。 + +# Input types +## Required +- width + - ‘width’参数设置图像的宽度,以像素为单位。这是一个关键组件,因为它直接影响图像的纵横比和最终尺寸。在图像处理工作流程中,此参数对于实现所需的视觉输出至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’参数定义图像的高度,以像素为单位。与‘width’参数一起,它决定了图像的整体纵横比。‘height’对于使图像尺寸与特定要求或标准保持一致至关重要。 + - Comfy dtype: INT + - Python dtype: int +- aspect_ratio + - ‘aspect_ratio’参数允许用户选择一个预定义的纵横比或输入一个自定义的纵横比。它在根据所需格式塑造图像尺寸方面起着重要作用,这对于各种图像处理和显示目的至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- swap_dimensions + - ‘swap_dimensions’参数提供了一个交换宽度和高度值的选项。当输入的纵横比与图像的预期方向不一致时,此功能可以很有用,允许在尺寸操作中具有灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- upscale_factor + - ‘upscale_factor’参数用于通过指定因子增加图像的大小。这是一个重要的特性,可以在不改变纵横比的情况下增强图像分辨率,这对于高质量的图像输出非常有益。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - ‘batch_size’参数决定了单次操作中处理的图像数量。它对于优化计算资源和提高图像处理任务的效率至关重要,尤其是在处理大量图像时。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- width + - ‘width’输出提供了应用所选纵横比以及任何维度交换或放大因子后图像的最终宽度。它是节点操作的关键结果,对于后续的图像处理步骤至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’输出提供了节点设置后处理的图像的最终高度。它是确保图像满足显示或进一步处理所需尺寸的关键信息。 + - Comfy dtype: INT + - Python dtype: int +- upscale_factor + - ‘upscale_factor’输出反映了应用于图像的缩放因子。它有助于跟踪图像的原始大小和当前大小之间的关系。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - ‘batch_size’输出表明了被处理的图像数量。对于需要了解批量大小以进行适当对齐或进一步计算的下游任务来说,这可能很重要。 + - Comfy dtype: INT + - Python dtype: int +- empty_latent + - ‘empty_latent’输出是用于更高级图像处理应用程序中可能使用的潜在表示的占位符。它标志着节点与复杂工作流程集成的能力,尽管在此上下文中,它被返回为一个空结构。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- show_help + - ‘show_help’输出提供了指向节点文档页面的URL链接。它是寻求如何有效使用节点的更多信息或帮助的用户的一个有用资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SDXLAspectRatio: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + aspect_ratios = ['custom', '1:1 square 1024x1024', '3:4 portrait 896x1152', '5:8 portrait 832x1216', '9:16 portrait 768x1344', '9:21 portrait 640x1536', '4:3 landscape 1152x896', '3:2 landscape 1216x832', '16:9 landscape 1344x768', '21:9 landscape 1536x640'] + return {'required': {'width': ('INT', {'default': 1024, 'min': 64, 'max': 8192}), 'height': ('INT', {'default': 1024, 'min': 64, 'max': 8192}), 'aspect_ratio': (aspect_ratios,), 'swap_dimensions': (['Off', 'On'],), 'upscale_factor': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 100.0, 'step': 0.1}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}} + RETURN_TYPES = ('INT', 'INT', 'FLOAT', 'INT', 'LATENT', 'STRING') + RETURN_NAMES = ('width', 'height', 'upscale_factor', 'batch_size', 'empty_latent', 'show_help') + FUNCTION = 'Aspect_Ratio' + CATEGORY = icons.get('Comfyroll/Aspect Ratio') + + def Aspect_Ratio(self, width, height, aspect_ratio, swap_dimensions, upscale_factor, batch_size): + if aspect_ratio == '1:1 square 1024x1024': + (width, height) = (1024, 1024) + elif aspect_ratio == '3:4 portrait 896x1152': + (width, height) = (896, 1152) + elif aspect_ratio == '5:8 portrait 832x1216': + (width, height) = (832, 1216) + elif aspect_ratio == '9:16 portrait 768x1344': + (width, height) = (768, 1344) + elif aspect_ratio == '9:21 portrait 640x1536': + (width, height) = (640, 1536) + elif aspect_ratio == '4:3 landscape 1152x896': + (width, height) = (1152, 896) + elif aspect_ratio == '3:2 landscape 1216x832': + (width, height) = (1216, 832) + elif aspect_ratio == '16:9 landscape 1344x768': + (width, height) = (1344, 768) + elif aspect_ratio == '21:9 landscape 1536x640': + (width, height) = (1536, 640) + if swap_dimensions == 'On': + (width, height) = (height, width) + latent = torch.zeros([batch_size, 4, height // 8, width // 8]) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Aspect-Ratio-Nodes#cr-sdxl-aspect-ratio' + return (width, height, upscale_factor, batch_size, {'samples': latent}, show_help) +``` \ No newline at end of file diff --git a/docs/CR SDXL Base Prompt Encoder.md b/docs/CR SDXL Base Prompt Encoder.md new file mode 100644 index 0000000..4b295dd --- /dev/null +++ b/docs/CR SDXL Base Prompt Encoder.md @@ -0,0 +1,138 @@ +# Documentation +- Class name: CR_SDXLBasePromptEncoder +- Category: icons.get('Comfyroll/SDXL') +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SDXLBasePromptEncoder类旨在处理和编码用于生成具有特定属性的图像的提示。它管理正面和负面提示的编码,确保生成的图像符合所需特征并避免不需要的特征。 + +# Input types +## Required +- base_clip + - base_clip参数对于编码过程至关重要,它为图像生成提供了基础。它用于标记和编码输入提示,然后这些提示被用来引导图像的创建。 + - Comfy dtype: CLIP + - Python dtype: PIL.Image +- pos_g + - pos_g参数代表正面引导文本,对于指定生成图像中所需特征至关重要。它有助于将图像生成过程引向预期的结果。 + - Comfy dtype: STRING + - Python dtype: str +- pos_l + - pos_l参数是正面语言文本,它补充了引导文本。它提供了额外的上下文来细化图像生成过程,确保所需属性被清晰传达。 + - Comfy dtype: STRING + - Python dtype: str +- neg_g + - neg_g参数包含负面引导文本,它指定了生成图像中要避免的特征。它在确保最终输出符合用户偏好方面发挥着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +- neg_l + - neg_l参数代表负面语言文本,通过指定不需要的特征来进一步细化图像生成。这对于实现符合用户期望的最终图像非常重要。 + - Comfy dtype: STRING + - Python dtype: str +- preset + - preset参数允许用户选择预定义的正面和负面提示组合进行图像生成。它通过提供平衡所需和不期望特征包含的选项,简化了过程。 + - Comfy dtype: COMBO[preset A, preset B, preset C] + - Python dtype: str +- base_width + - base_width参数定义了用于编码的基础图像的宽度。它是确定生成图像的分辨率和宽高比的重要因素。 + - Comfy dtype: INT + - Python dtype: int +- base_height + - base_height参数指定了基础图像的高度,与base_width一起,决定了编码过程产生的图像的整体尺寸。 + - Comfy dtype: INT + - Python dtype: int +- crop_w + - crop_w参数指示从基础图像中裁剪区域的宽度。它在将编码聚焦于图像的特定区域以符合期望输出方面发挥作用。 + - Comfy dtype: INT + - Python dtype: int +- crop_h + - crop_h参数定义了裁剪区域的高度,与crop_w一起工作,确定基础图像中被编码和用于图像生成的精确部分。 + - Comfy dtype: INT + - Python dtype: int +- target_width + - target_width参数设置了最终生成图像的期望宽度。它是实现输出的预期分辨率和宽高比的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- target_height + - target_height参数指定了最终图像的期望高度,确保输出在尺寸和构图方面符合用户的要求。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- base_positive + - base_positive输出包含正面提示的编码表示,用于引导生成具有所需属性的图像。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict[str, Any]]] +- base_negative + - base_negative输出代表编码后的负面提示,用于从生成的图像中排除不需要的特征。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict[str, Any]]] +- show_help + - show_help输出提供了一个链接到文档,以便进一步协助和理解节点的功能和用法。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SDXLBasePromptEncoder: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_clip': ('CLIP',), 'pos_g': ('STRING', {'multiline': True, 'default': 'POS_G'}), 'pos_l': ('STRING', {'multiline': True, 'default': 'POS_L'}), 'neg_g': ('STRING', {'multiline': True, 'default': 'NEG_G'}), 'neg_l': ('STRING', {'multiline': True, 'default': 'NEG_L'}), 'preset': (['preset A', 'preset B', 'preset C'],), 'base_width': ('INT', {'default': 4096.0, 'min': 0, 'max': MAX_RESOLUTION, 'step': 64}), 'base_height': ('INT', {'default': 4096.0, 'min': 0, 'max': MAX_RESOLUTION, 'step': 64}), 'crop_w': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION, 'step': 64}), 'crop_h': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION, 'step': 64}), 'target_width': ('INT', {'default': 4096.0, 'min': 0, 'max': MAX_RESOLUTION, 'step': 64}), 'target_height': ('INT', {'default': 4096.0, 'min': 0, 'max': MAX_RESOLUTION, 'step': 64})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING', 'STRING') + RETURN_NAMES = ('base_positive', 'base_negative', 'show_help') + FUNCTION = 'encode' + CATEGORY = icons.get('Comfyroll/SDXL') + + def encode(self, base_clip, pos_g, pos_l, neg_g, neg_l, base_width, base_height, crop_w, crop_h, target_width, target_height, preset): + empty = base_clip.tokenize('') + tokens1 = base_clip.tokenize(pos_g) + tokens1['l'] = base_clip.tokenize(pos_l)['l'] + if len(tokens1['l']) != len(tokens1['g']): + while len(tokens1['l']) < len(tokens1['g']): + tokens1['l'] += empty['l'] + while len(tokens1['l']) > len(tokens1['g']): + tokens1['g'] += empty['g'] + (cond1, pooled1) = base_clip.encode_from_tokens(tokens1, return_pooled=True) + res1 = [[cond1, {'pooled_output': pooled1, 'width': base_width, 'height': base_height, 'crop_w': crop_w, 'crop_h': crop_h, 'target_width': target_width, 'target_height': target_height}]] + tokens2 = base_clip.tokenize(neg_g) + tokens2['l'] = base_clip.tokenize(neg_l)['l'] + if len(tokens2['l']) != len(tokens2['g']): + while len(tokens2['l']) < len(tokens2['g']): + tokens2['l'] += empty['l'] + while len(tokens2['l']) > len(tokens2['g']): + tokens2['g'] += empty['g'] + (cond2, pooled2) = base_clip.encode_from_tokens(tokens2, return_pooled=True) + res2 = [[cond2, {'pooled_output': pooled2, 'width': base_width, 'height': base_height, 'crop_w': crop_w, 'crop_h': crop_h, 'target_width': target_width, 'target_height': target_height}]] + tokens2 = base_clip.tokenize(pos_l) + tokens2['l'] = base_clip.tokenize(neg_l)['l'] + if len(tokens2['l']) != len(tokens2['g']): + while len(tokens2['l']) < len(tokens2['g']): + tokens2['l'] += empty['l'] + while len(tokens2['l']) > len(tokens2['g']): + tokens2['g'] += empty['g'] + (cond2, pooled2) = base_clip.encode_from_tokens(tokens2, return_pooled=True) + res3 = [[cond2, {'pooled_output': pooled2, 'width': base_width, 'height': base_height, 'crop_w': crop_w, 'crop_h': crop_h, 'target_width': target_width, 'target_height': target_height}]] + tokens2 = base_clip.tokenize(neg_l) + tokens2['l'] = base_clip.tokenize(neg_l)['l'] + if len(tokens2['l']) != len(tokens2['g']): + while len(tokens2['l']) < len(tokens2['g']): + tokens2['l'] += empty['l'] + while len(tokens2['l']) > len(tokens2['g']): + tokens2['g'] += empty['g'] + (cond2, pooled2) = base_clip.encode_from_tokens(tokens2, return_pooled=True) + res4 = [[cond2, {'pooled_output': pooled2, 'width': base_width, 'height': base_height, 'crop_w': crop_w, 'crop_h': crop_h, 'target_width': target_width, 'target_height': target_height}]] + if preset == 'preset A': + base_positive = res1 + base_negative = res2 + elif preset == 'preset B': + base_positive = res3 + base_negative = res4 + elif preset == 'preset C': + base_positive = res1 + res3 + base_negative = res2 + res4 + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/SDXL-Nodes#cr-sdxl-base-prompt-encoder' + return (base_positive, base_negative, show_help) +``` \ No newline at end of file diff --git a/docs/CR SDXL Prompt Mix Presets.md b/docs/CR SDXL Prompt Mix Presets.md new file mode 100644 index 0000000..3e2fccf --- /dev/null +++ b/docs/CR SDXL Prompt Mix Presets.md @@ -0,0 +1,118 @@ +# Documentation +- Class name: CR_PromptMixPresets +- Category: Comfyroll/SDXL +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_PromptMixPresets是一个用于组合和操作生成模型的提示和风格的节点。它提供了多种预设选项来混合正面和负面提示以及风格文本,增强了对生成过程的控制,并允许对输出进行微调。 + +# Input types +## Optional +- prompt_positive + - 正面提示是一个关键输入,它定义了生成内容的期望属性。它影响生成过程的总体方向,将输出引向指定的特征。 + - Comfy dtype: STRING + - Python dtype: str +- prompt_negative + - 负面提示用于从生成内容中排除某些元素。它通过指定不应包含的内容来细化生成,从而更精确地塑造最终输出。 + - Comfy dtype: STRING + - Python dtype: str +- style_positive + - 正面风格输入允许将风格元素融入正面提示中。它通过添加特定的风格特征,增强了生成内容的美学质量。 + - Comfy dtype: STRING + - Python dtype: str +- style_negative + - 负面风格输入通过提供要避免的风格元素来补充正面风格,确保生成的内容遵循所需的风格指南,同时不包含不希望的属性。 + - Comfy dtype: STRING + - Python dtype: str +- preset + - 预设参数决定了提示和风格的混合策略。它提供了不同的方法来组合输入,影响生成内容的平衡和重点。 + - Comfy dtype: COMBO['default with no style text', 'default with style text', 'style boost 1', 'style boost 2', 'style text to refiner'] + - Python dtype: str + +# Output types +- pos_g + - 生成的正面全局提示,包含了所需的属性和风格,准备在生成模型中使用以指导创作过程。 + - Comfy dtype: STRING + - Python dtype: str +- pos_l + - 生成的正面局部提示,专注于要在生成内容中包含的特定细节,为生成提供更细微的方向。 + - Comfy dtype: STRING + - Python dtype: str +- pos_r + - 生成的正面细化提示,进一步细化生成过程,为期望的输出添加一层细节。 + - Comfy dtype: STRING + - Python dtype: str +- neg_g + - 生成的负面全局提示,指定要从生成内容中排除的元素,确保最终输出与预期的愿景一致。 + - Comfy dtype: STRING + - Python dtype: str +- neg_l + - 生成的负面局部提示,针对生成中要避免的特定不需要的细节,提高了排除的精确度。 + - Comfy dtype: STRING + - Python dtype: str +- neg_r + - 生成的负面细化提示,为生成过程添加了进一步的排除,确保对最终输出有更高水平的控制。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - 一个URL链接,指向文档,用于获取有关有效使用节点的额外指导和信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_PromptMixPresets: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {}, 'optional': {'prompt_positive': ('STRING', {'multiline': True, 'default': 'prompt_pos'}), 'prompt_negative': ('STRING', {'multiline': True, 'default': 'prompt_neg'}), 'style_positive': ('STRING', {'multiline': True, 'default': 'style_pos'}), 'style_negative': ('STRING', {'multiline': True, 'default': 'style_neg'}), 'preset': (['default with no style text', 'default with style text', 'style boost 1', 'style boost 2', 'style text to refiner'],)}} + RETURN_TYPES = ('STRING', 'STRING', 'STRING', 'STRING', 'STRING', 'STRING', 'STRING') + RETURN_NAMES = ('pos_g', 'pos_l', 'pos_r', 'neg_g', 'neg_l', 'neg_r', 'show_help') + FUNCTION = 'mixer' + CATEGORY = icons.get('Comfyroll/SDXL') + + def mixer(self, prompt_positive, prompt_negative, style_positive, style_negative, preset): + if preset == 'default with no style text': + pos_g = prompt_positive + pos_l = prompt_positive + pos_r = prompt_positive + neg_g = prompt_negative + neg_l = prompt_negative + neg_r = prompt_negative + elif preset == 'default with style text': + pos_g = prompt_positive + style_positive + pos_l = prompt_positive + style_positive + pos_r = prompt_positive + style_positive + neg_g = prompt_negative + style_negative + neg_l = prompt_negative + style_negative + neg_r = prompt_negative + style_negative + elif preset == 'style boost 1': + pos_g = prompt_positive + pos_l = style_positive + pos_r = prompt_positive + neg_g = prompt_negative + neg_l = style_negative + neg_r = prompt_negative + elif preset == 'style boost 2': + pos_g = style_positive + pos_l = prompt_positive + pos_r = style_positive + neg_g = style_negative + neg_l = prompt_negative + neg_r = style_negative + elif preset == 'style text to refiner': + pos_g = prompt_positive + pos_l = prompt_positive + pos_r = style_positive + neg_g = prompt_negative + neg_l = prompt_negative + neg_r = style_negative + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/SDXL-Nodes#cr-sdxl-prompt-mix-presets' + return (pos_g, pos_l, pos_r, neg_g, neg_l, neg_r, show_help) +``` \ No newline at end of file diff --git a/docs/CR SDXL Prompt Mixer.md b/docs/CR SDXL Prompt Mixer.md new file mode 100644 index 0000000..986c2c7 --- /dev/null +++ b/docs/CR SDXL Prompt Mixer.md @@ -0,0 +1,114 @@ +# Documentation +- Class name: CR_PromptMixer +- Category: Comfyroll/Essential/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_PromptMixer 是一个旨在混合不同提示和风格以生成精炼输出的节点。它通过接收正面和负面提示以及风格输入,然后应用选定的预设来以特定的方式混合这些输入。该节点的功能集中在通过智能组合各种文本元素来提高生成文本的质量和一致性。 + +# Input types +## Optional +- prompt_positive + - 正面提示是文本生成过程中的关键输入,它提供了一个建设性的例子或指导方针。它在引导输出朝着期望的质量和属性方向发展中起着至关重要的作用。 + - Comfy dtype: STRING + - Python dtype: str +- prompt_negative + - 负面提示用于提供文本生成中应避免的例子或指导方针。它在塑造输出方面起着重要作用,通过指定要排除的内容。 + - Comfy dtype: STRING + - Python dtype: str +- style_positive + - 正面风格输入用于通过添加被认为有利的风格元素来完善文本生成。它以特定的风格特征增强输出。 + - Comfy dtype: STRING + - Python dtype: str +- style_negative + - 负面风格输入允许指定应从文本生成中省略的风格元素。这对于确保最终输出与预期的风格一致非常重要。 + - Comfy dtype: STRING + - Python dtype: str +- preset + - 预设参数决定了应用于输入的特定混合策略。每个预设代表了一种不同的方法来组合正面和负面的提示和风格。 + - Comfy dtype: COMBO['preset 1', 'preset 2', 'preset 3', 'preset 4', 'preset 5'] + - Python dtype: str + +# Output types +- pos_g + - 'pos_g' 输出代表了根据所选预设生成的混合正面提示。它是最终输出的关键组成部分,反映了输入的组合效果。 + - Comfy dtype: STRING + - Python dtype: str +- pos_l + - 'pos_l' 输出是另一个混合正面提示,反映了输入混合过程的不同方面。它有助于整体的连贯性和生成文本的质量。 + - Comfy dtype: STRING + - Python dtype: str +- pos_r + - 'pos_r' 输出表示混合正面提示的进一步变化,为文本生成过程提供了额外的深度。 + - Comfy dtype: STRING + - Python dtype: str +- neg_g + - 'neg_g' 输出是一个混合负面提示,已被处理以排除最终文本生成中不需要的元素。 + - Comfy dtype: STRING + - Python dtype: str +- neg_l + - 'neg_l' 输出代表了另一个混合负面提示,确保从文本生成中排除特定的不需要的风格元素。 + - Comfy dtype: STRING + - Python dtype: str +- neg_r + - 'neg_r' 输出是混合负面提示的最终变化,为文本生成提供了全面排除不需要的元素。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_PromptMixer: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {}, 'optional': {'prompt_positive': ('STRING', {'multiline': True, 'default': 'BASE_POSITIVE'}), 'prompt_negative': ('STRING', {'multiline': True, 'default': 'BASE_NEGATIVE'}), 'style_positive': ('STRING', {'multiline': True, 'default': 'REFINER_POSTIVE'}), 'style_negative': ('STRING', {'multiline': True, 'default': 'REFINER_NEGATIVE'}), 'preset': (['preset 1', 'preset 2', 'preset 3', 'preset 4', 'preset 5'],)}} + RETURN_TYPES = ('STRING', 'STRING', 'STRING', 'STRING', 'STRING', 'STRING') + RETURN_NAMES = ('pos_g', 'pos_l', 'pos_r', 'neg_g', 'neg_l', 'neg_r') + FUNCTION = 'mixer' + CATEGORY = icons.get('Comfyroll/Essential/Legacy') + + def mixer(self, prompt_positive, prompt_negative, style_positive, style_negative, preset): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Legacy-Nodes#cr-prompt-mixer' + if preset == 'preset 1': + pos_g = prompt_positive + pos_l = prompt_positive + pos_r = prompt_positive + neg_g = prompt_negative + neg_l = prompt_negative + neg_r = prompt_negative + elif preset == 'preset 2': + pos_g = prompt_positive + pos_l = style_positive + pos_r = prompt_positive + neg_g = prompt_negative + neg_l = style_negative + neg_r = prompt_negative + elif preset == 'preset 3': + pos_g = style_positive + pos_l = prompt_positive + pos_r = style_positive + neg_g = style_negative + neg_l = prompt_negative + neg_r = style_negative + elif preset == 'preset 4': + pos_g = prompt_positive + style_positive + pos_l = prompt_positive + style_positive + pos_r = prompt_positive + style_positive + neg_g = prompt_negative + style_negative + neg_l = prompt_negative + style_negative + neg_r = prompt_negative + style_negative + elif preset == 'preset 5': + pos_g = prompt_positive + pos_l = prompt_positive + pos_r = style_positive + neg_g = prompt_negative + neg_l = prompt_negative + neg_r = style_negative + return (pos_g, pos_l, pos_r, neg_g, neg_l, neg_r) +``` \ No newline at end of file diff --git a/docs/CR SDXL Style Text.md b/docs/CR SDXL Style Text.md new file mode 100644 index 0000000..3778600 --- /dev/null +++ b/docs/CR SDXL Style Text.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: CR_SDXLStyleText +- Category: Comfyroll/SDXL +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SDXLStyleText 节点旨在处理和管理与风格相关的文本输入,特别适用于图像处理工作流中的风格转换操作。它巧妙地处理正面和负面的风格描述,使用户能够定义他们希望在输出中增强或抑制的风格属性。该节点在引导图像转换的风格方向中发挥关键作用,确保实现所需的审美结果。 + +# Input types +## Required +- positive_style + - positive_style 参数对于定义用户希望在最终图像中突出的风格特征至关重要。它允许详细描述,这可以显著影响风格转换过程的创意方向。 + - Comfy dtype: STRING + - Python dtype: str +- negative_style + - negative_style 参数用于指定用户希望在图像输出中避免或最小化的风格元素。这个输入对于微调风格以满足用户的期望以及省略不需要的特征至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- positive_prompt_text_l + - positive_prompt_text_l 输出包含已处理的正面风格文本,将用于指导图像处理朝着期望的风格增强方向发展。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_l + - negative_prompt_text_l 输出保存了已处理的负面风格文本,这对于引导图像处理远离不需要的风格特征至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - show_help 输出提供了一个文档的URL链接,以便在使用节点时获得进一步的帮助和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SDXLStyleText: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'positive_style': ('STRING', {'default': 'POS_STYLE', 'multiline': True}), 'negative_style': ('STRING', {'default': 'NEG_STYLE', 'multiline': True})}} + RETURN_TYPES = ('STRING', 'STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_l', 'negative_prompt_text_l', 'show_help') + FUNCTION = 'get_value' + CATEGORY = icons.get('Comfyroll/SDXL') + + def get_value(self, positive_style, negative_style): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/SDXL-Nodes#cr-sdxl-style-text' + return (positive_style, negative_style, show_help) +``` \ No newline at end of file diff --git a/docs/CR Save Text To File.md b/docs/CR Save Text To File.md new file mode 100644 index 0000000..b647067 --- /dev/null +++ b/docs/CR Save Text To File.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: CR_SaveTextToFile +- Category: Comfyroll/Utils/Text +- Output node: True +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SaveTextToFile节点旨在将文本数据保存到文件中。它提供处理多行文本的功能,并将文本写入指定的文件路径,使用给定的文件名和扩展名,确保文件具有唯一名称以避免覆盖现有文件。 + +# Input types +## Required +- multiline_text + - 参数'multiline_text'保存需要保存的文本内容。它至关重要,因为它是节点将处理并写入文件的主要数据。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- output_file_path + - 参数'output_file_path'指定了文件将被保存的目录。它是可选的,如果没有提供,将使用默认路径。 + - Comfy dtype: STRING + - Python dtype: str +- file_name + - 参数'file_name'定义了要创建的文件的名称。它对于识别文件和确保其唯一性很重要。 + - Comfy dtype: STRING + - Python dtype: str +- file_extension + - 参数'file_extension'确定要保存的文件的格式。它可以是'txt'或'csv',影响文本数据在文件中的结构。 + - Comfy dtype: COMBO['txt', 'csv'] + - Python dtype: str + +# Output types +- show_help + - 输出'show_help'提供了一个URL链接到文档,以获取有关使用该节点的进一步帮助或指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SaveTextToFile: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'multiline_text': ('STRING', {'multiline': True, 'default': ''}), 'output_file_path': ('STRING', {'multiline': False, 'default': ''}), 'file_name': ('STRING', {'multiline': False, 'default': ''}), 'file_extension': (['txt', 'csv'],)}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('show_help',) + OUTPUT_NODE = True + FUNCTION = 'save_list' + CATEGORY = icons.get('Comfyroll/Utils/Text') + + def save_list(self, multiline_text, output_file_path, file_name, file_extension): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-save-text-to-file' + filepath = output_file_path + '\\' + file_name + '.' + file_extension + index = 1 + if output_file_path == '' or file_name == '': + print(f'[Warning] CR Save Text List. No file details found. No file output.') + return () + while os.path.exists(filepath): + if os.path.exists(filepath): + filepath = output_file_path + '\\' + file_name + '_' + str(index) + '.' + file_extension + index = index + 1 + else: + break + print(f'[Info] CR Save Text List: Saving to {filepath}') + if file_extension == 'csv': + text_list = [] + for i in multiline_text.split('\n'): + text_list.append(i.strip()) + with open(filepath, 'w', newline='') as csv_file: + csv_writer = csv.writer(csv_file) + for line in text_list: + csv_writer.writerow([line]) + else: + with open(filepath, 'w', newline='') as text_file: + for line in multiline_text: + text_file.write(line) + return (show_help,) +``` \ No newline at end of file diff --git a/docs/CR Schedule Input Switch.md b/docs/CR Schedule Input Switch.md new file mode 100644 index 0000000..aad0c3c --- /dev/null +++ b/docs/CR Schedule Input Switch.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: Comfyroll_ScheduleInputSwitch +- Category: Comfyroll/Animation/Schedule +- Output node: True +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +Comfyroll_ScheduleInputSwitch 节点旨在根据输入值在两个不同的时间表之间进行选择。它允许在工作流程中进行条件执行,使用户能够根据提供的输入指导操作流程。此节点在编排复杂动画中发挥关键作用,通过确定要遵循的时间表来实现。 + +# Input types +## Required +- Input + - ‘Input’参数对于确定将执行哪个时间表至关重要。它根据其值决定动画的流程,该值可以是1到2。此参数对于节点的决策过程至关重要,直接影响操作的结果。 + - Comfy dtype: INT + - Python dtype: int +- schedule1 + - ‘schedule1’参数代表节点可以选择的第一个时间表。它是节点决策过程中的关键组成部分,当输入值为1时,为动画序列提供替代路径。 + - Comfy dtype: SCHEDULE + - Python dtype: Schedule +- schedule2 + - ‘schedule2’参数是节点可用的第二个时间表选项。当输入值不为1时,它变得重要,并根据此时间表指导动画的后续步骤。 + - Comfy dtype: SCHEDULE + - Python dtype: Schedule + +# Output types +- SCHEDULE + - ‘SCHEDULE’输出是基于提供给节点的输入选定的时间表。它是节点操作的核心结果,指导动画工作流中的后续步骤。 + - Comfy dtype: SCHEDULE + - Python dtype: Schedule +- show_help + - 'show_help'输出提供了一个指向wiki页面的URL,该页面提供了关于节点功能的额外指导和信息。它作为寻求如何有效使用节点的用户的资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Comfyroll_ScheduleInputSwitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': ('INT', {'default': 1, 'min': 1, 'max': 2}), 'schedule1': ('SCHEDULE',), 'schedule2': ('SCHEDULE',)}} + RETURN_TYPES = ('SCHEDULE', 'STRING') + RETURN_NAMES = ('SCHEDULE', 'show_help') + OUTPUT_NODE = True + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Animation/Schedule') + + def switch(self, Input, schedule1, schedule2): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Schedule-Nodes#cr-schedule-input-switch' + if Input == 1: + return (schedule1, show_help) + else: + return (schedule2, show_help) +``` \ No newline at end of file diff --git a/docs/CR Seamless Checker.md b/docs/CR Seamless Checker.md new file mode 100644 index 0000000..97cca2c --- /dev/null +++ b/docs/CR Seamless Checker.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: CR_SeamlessChecker +- Category: Comfyroll/Graphics/Template +- Output node: True +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SeamlessChecker节点用于检查图像的无缝拼接效果。该节点通过调整图像大小、生成网格布局,并展示多个图像的缩放版本,使用户能够识别和评估图像的拼接质量。它广泛应用于图形设计和图像处理领域,确保最终的视觉效果实现无缝衔接。 + +# Input types +## Required +- image + - 图像参数是节点处理的主要对象,它直接影响节点的执行和检查结果,是进行无缝拼接检查的源数据。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image 或 torch.Tensor +- rescale_factor + - 缩放因子参数用于调整图像尺寸,对于评估图像的无缝拼接效果非常关键。用户可以通过此参数控制图像的缩放程度,以便更精确地查看拼接的细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- grid_options + - 网格选项参数用于定义图像在网格中的布局方式,它决定了在进行无缝拼接检查时展示的图像数量。此参数对于展示多个图像的缩放版本以及评估整个网格的拼接效果具有重要意义。 + - Comfy dtype: COMBO['2x2', '3x3', '4x4', '5x5', '6x6'] + - Python dtype: str + +# Output types +- show_help + - 帮助信息提供了节点使用指南和进一步的资源链接,以便用户能够更有效地理解和操作节点。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SeamlessChecker: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'rescale_factor': ('FLOAT', {'default': 0.25, 'min': 0.1, 'max': 1.0, 'step': 0.01}), 'grid_options': (['2x2', '3x3', '4x4', '5x5', '6x6'],)}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('show_help',) + OUTPUT_NODE = True + FUNCTION = 'thumbnail' + CATEGORY = icons.get('Comfyroll/Graphics/Template') + + def thumbnail(self, image, rescale_factor, grid_options): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-seamless-checker' + outline_thickness = 0 + pil_img = tensor2pil(image) + (original_width, original_height) = pil_img.size + rescaled_img = apply_resize_image(tensor2pil(image), original_width, original_height, 8, 'rescale', 'false', rescale_factor, 256, 'lanczos') + outlined_img = ImageOps.expand(rescaled_img, outline_thickness, fill='black') + max_columns = int(grid_options[0]) + repeat_images = [outlined_img] * max_columns ** 2 + combined_image = make_grid_panel(repeat_images, max_columns) + images_out = pil2tensor(combined_image) + results = [] + for tensor in images_out: + array = 255.0 * tensor.cpu().numpy() + image = Image.fromarray(np.clip(array, 0, 255).astype(np.uint8)) + server = PromptServer.instance + server.send_sync(BinaryEventTypes.UNENCODED_PREVIEW_IMAGE, ['PNG', image, None], server.client_id) + results.append({'source': 'websocket', 'content-type': 'image/png', 'type': 'output'}) + return {'ui': {'images': results}, 'result': (show_help,)} +``` \ No newline at end of file diff --git a/docs/CR Seed to Int.md b/docs/CR Seed to Int.md new file mode 100644 index 0000000..ebcf7f6 --- /dev/null +++ b/docs/CR Seed to Int.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: CR_SeedToInt +- Category: Comfyroll/Essential/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SeedToInt节点旨在将种子对象转换为整数。它在转换过程中扮演着关键角色,确保数据的完整性和可用性。该节点抽象了种子转换的复杂性,为进一步的数据操作和分析提供了一个简单的接口。 + +# Input types +## Required +- seed + - 种子参数对节点的操作至关重要,因为它是节点处理的原始输入。它直接影响节点的输出,通过确定转换为整数的初始值。 + - Comfy dtype: SEED + - Python dtype: Dict[str, Any] + +# Output types +- INT + - INT输出代表从输入种子派生的转换后的整数值。它很重要,因为它是节点功能的主要结果,可用于后续的计算任务。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - show_help输出提供了一个URL链接到文档,以供进一步帮助。对于寻求有关节点操作及其在更广泛系统中上下文的更多信息的用户来说,这是有用的。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SeedToInt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'seed': ('SEED',)}} + RETURN_TYPES = ('INT', 'STRING') + RETURN_NAMES = ('INT', 'show_help') + FUNCTION = 'seed_to_int' + CATEGORY = icons.get('Comfyroll/Essential/Legacy') + + def seed_to_int(self, seed): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Conversion-Nodes#cr-seed-to-int' + return (seed.get('seed'), show_help) +``` \ No newline at end of file diff --git a/docs/CR Seed.md b/docs/CR Seed.md new file mode 100644 index 0000000..8e824e2 --- /dev/null +++ b/docs/CR Seed.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: CR_Seed +- Category: Essential/Core +- Output node: True +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_Seed节点旨在初始化和管理计算过程中用于随机数生成的种子。通过设置特定的种子值,它确保结果是可重现的,这对于调试和不同运行之间的一致性测试至关重要。 + +# Input types +## Required +- seed + - 种子参数对于初始化随机数生成器至关重要。它决定了随机数生成的起始点,从而影响结果的可重复性。种子值应该是指定范围内的非负整数。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- seed + - 输出种子与输入种子相同,表示用于初始化随机数生成器的值。它对于跟踪和确保过程的可重复性很重要。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - show_help输出提供了一个指向与节点相关联的文档或帮助页面的URL链接。这对于需要关于如何有效使用节点的额外指导或信息的用户来说可能很有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_Seed: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('INT', 'STRING') + RETURN_NAMES = ('seed', 'show_help') + FUNCTION = 'seedint' + OUTPUT_NODE = True + CATEGORY = icons.get('Comfyroll/Essential/Core') + + @staticmethod + def seedint(seed): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Core-Nodes#cr-seed' + return (seed, show_help) +``` \ No newline at end of file diff --git a/docs/CR Select Font.md b/docs/CR Select Font.md new file mode 100644 index 0000000..294bbb6 --- /dev/null +++ b/docs/CR Select Font.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: CR_SelectFont +- Category: Comfyroll/Graphics/Text +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SelectFont 节点旨在允许用户从预定义的可用 TrueType 字体列表中选择字体。它在设置文本渲染中的字体方面起着至关重要的作用。此节点通过为用户选择所需的字体提供直接的接口,抽象化了字体管理的复杂性,确保了不同操作系统之间的兼容性和易用性。 + +# Input types +## Required +- font_name + - ‘font_name’ 参数对于指定用户希望用于文本渲染的确切字体至关重要。它直接影响渲染文本的视觉输出和风格,是实现所需审美和可读性的关键选择。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- font_name + - ‘font_name’ 输出参数表示将在后续文本渲染过程中使用的选定字体。它标志着成功选择了一种字体,对于整个工作流程中文本样式的连续性和一致性至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - ‘show_help’ 输出提供了一个文档的 URL 链接,以供进一步的帮助。对于需要额外指导如何使用选定字体或更多了解字体选择过程的用户来说,它特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SelectFont: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + if platform.system() == 'Windows': + system_root = os.environ.get('SystemRoot') + font_dir = os.path.join(system_root, 'Fonts') if system_root else None + elif platform.system() == 'Linux': + font_dir = '/usr/share/fonts/truetype' + elif platform.system() == 'Darwin': + font_dir = '/System/Library/Fonts' + file_list = [f for f in os.listdir(font_dir) if os.path.isfile(os.path.join(font_dir, f)) and f.lower().endswith('.ttf')] + return {'required': {'font_name': (file_list,)}} + RETURN_TYPES = (any_type, 'STRING') + RETURN_NAMES = ('font_name', 'show_help') + FUNCTION = 'select_font' + CATEGORY = icons.get('Comfyroll/Graphics/Text') + + def select_font(self, font_name): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Text-Nodes#cr-select-font' + return (font_name, show_help) +``` \ No newline at end of file diff --git a/docs/CR Select ISO Size.md b/docs/CR Select ISO Size.md new file mode 100644 index 0000000..fef1c50 --- /dev/null +++ b/docs/CR Select ISO Size.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: CR_SelectISOSize +- Category: Comfyroll/Utils/Other +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SelectISOSize 节点旨在为用户选择的 ISO 纸张大小提供相应的尺寸。它在需要标准纸张大小的应用程序中扮演着重要角色,确保输出符合国际标准。 + +# Input types +## Required +- iso_size + - 参数 'iso_size' 对于确定特定的 ISO 纸张尺寸至关重要。它通过指定将返回的尺寸集来影响节点的执行。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- width + - 输出 'width' 表示所选 ISO 纸张大小的宽度尺寸。对于需要精确纸张尺寸规格的应用程序来说,它非常重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 输出 'height' 提供了所选 ISO 纸张大小的高度尺寸。它对于确保纸张大小满足各种打印或设计任务所需的规格至关重要。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - 输出 'show_help' 提供了一个指向有关 ISO 纸张大小的更多信息的帮助页面的 URL 链接。对于寻求有关该主题的额外指导或澄清的用户来说,这是有用的。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SelectISOSize: + + @classmethod + def INPUT_TYPES(cls): + sizes = list(iso_sizes.keys()) + return {'required': {'iso_size': (sizes,)}} + RETURN_TYPES = ('INT', 'INT', 'STRING') + RETURN_NAMES = ('width', 'height', 'show_help') + FUNCTION = 'get_size' + CATEGORY = icons.get('Comfyroll/Utils/Other') + + def get_size(self, iso_size): + if iso_size in iso_sizes: + (width, height) = iso_sizes[iso_size] + else: + print('Size not found.') + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-select-iso-size' + return (width, height, show_help) +``` \ No newline at end of file diff --git a/docs/CR Select Model.md b/docs/CR Select Model.md new file mode 100644 index 0000000..5e850a6 --- /dev/null +++ b/docs/CR Select Model.md @@ -0,0 +1,93 @@ +# Documentation +- Class name: CR_SelectModel +- Category: Comfyroll/Essential/Core +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SelectModel 是一个用于根据用户定义的标准选择和加载模型的节点。它允许指定多个检查点文件,并根据用户提供的索引选择适当的模型。该节点能够处理不同的检查点文件,并返回一个包含所选模型、其关联的clip和vae对象、检查点名称以及指向文档的链接以供进一步帮助的元组。 + +# Input types +## Required +- ckpt_name1 + - 参数 'ckpt_name1' 是用户可以选择的第一个检查点文件名。它在节点的操作中起着至关重要的作用,因为它决定了节点可以加载的潜在模型之一。 + - Comfy dtype: STRING + - Python dtype: str +- ckpt_name2 + - 参数 'ckpt_name2' 是用户可以选择的第二个检查点文件名。它在为用户提供选择模型时的选择项中起着重要作用。 + - Comfy dtype: STRING + - Python dtype: str +- ckpt_name3 + - 参数 'ckpt_name3' 是用户可以选择的第三个检查点文件名。它有助于增加节点可以处理的模型的多样性。 + - Comfy dtype: STRING + - Python dtype: str +- ckpt_name4 + - 参数 'ckpt_name4' 是用户可以选择的第四个检查点文件名。它是模型选择可用选项集的一部分。 + - Comfy dtype: STRING + - Python dtype: str +- ckpt_name5 + - 参数 'ckpt_name5' 是用户可以选择的第五个检查点文件名。它增加了节点能够加载的模型的范围。 + - Comfy dtype: STRING + - Python dtype: str +- select_model + - 参数 'select_model' 是一个整数,它决定将使用哪个检查点文件来加载模型。它非常重要,因为它直接影响节点选择并随后加载的模型。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MODEL + - 输出 'MODEL' 是根据用户选择加载的模型对象。它很重要,因为它代表了节点的核心功能,使进一步的处理或分析成为可能。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- CLIP + - 输出 'CLIP' 是与所选模型相关的clip对象。它对于提供与模型相关的额外上下文或功能很重要。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- VAE + - 输出 'VAE' 是模型架构中的变分自编码器对象。它对于涉及生成模型或潜在空间操作的任务很重要。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- ckpt_name + - 输出 'ckpt_name' 提供了用于加载模型的检查点文件的名称。它对于跟踪目的或进一步的模型管理很有用。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - 输出 'show_help' 是一个链接到节点文档的URL。它对于需要关于节点使用额外指导或信息的用户很有帮助。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SelectModel: + + @classmethod + def INPUT_TYPES(cls): + checkpoint_files = ['None'] + folder_paths.get_filename_list('checkpoints') + return {'required': {'ckpt_name1': (checkpoint_files,), 'ckpt_name2': (checkpoint_files,), 'ckpt_name3': (checkpoint_files,), 'ckpt_name4': (checkpoint_files,), 'ckpt_name5': (checkpoint_files,), 'select_model': ('INT', {'default': 1, 'min': 1, 'max': 5})}} + RETURN_TYPES = ('MODEL', 'CLIP', 'VAE', 'STRING', 'STRING') + RETURN_NAMES = ('MODEL', 'CLIP', 'VAE', 'ckpt_name', 'show_help') + FUNCTION = 'select_model' + CATEGORY = icons.get('Comfyroll/Essential/Core') + + def select_model(self, ckpt_name1, ckpt_name2, ckpt_name3, ckpt_name4, ckpt_name5, select_model): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Core-Nodes#cr-select-model' + model_list = list() + if select_model == 1: + model_name = ckpt_name1 + elif select_model == 2: + model_name = ckpt_name2 + elif select_model == 3: + model_name = ckpt_name3 + elif select_model == 4: + model_name = ckpt_name4 + elif select_model == 5: + model_name = ckpt_name5 + if model_name == 'None': + print(f'CR Select Model: No model selected') + return () + ckpt_path = folder_paths.get_full_path('checkpoints', model_name) + (model, clip, vae, clipvision) = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths('embeddings')) + return (model, clip, vae, model_name, show_help) +``` \ No newline at end of file diff --git a/docs/CR Select Resize Method.md b/docs/CR Select Resize Method.md new file mode 100644 index 0000000..cf9f7ae --- /dev/null +++ b/docs/CR Select Resize Method.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: CR_SelectResizeMethod +- Category: Comfyroll/Utils/Other +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SelectResizeMethod 节点旨在为不同的图像缩放方法提供选择机制,例如'Fit'和'Crop'。它在图像理工作流中充当决策点,允许用户根据其对图像操作的具体需求选择方法。 + +# Input types +## Required +- method + - ‘method’参数对于确定用于调整图像大小的方法至关重要。它决定了图像是会被调整大小以适应给定的尺寸,还是会被裁剪以完全匹配这些尺寸。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- method + - 输出‘method’代表用户选择的图像缩放方法。它是图像处理流程后续步骤的关键决定因素。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - ‘show_help’输出提供了一个文档的URL链接,用于进一步的帮助。对于需要更多关于缩放方法或节点功能信息的用户来说,它特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SelectResizeMethod: + + @classmethod + def INPUT_TYPES(cls): + methods = ['Fit', 'Crop'] + return {'required': {'method': (methods,)}} + RETURN_TYPES = (any_type, 'STRING') + RETURN_NAMES = ('method', 'show_help') + FUNCTION = 'set_switch' + CATEGORY = icons.get('Comfyroll/Utils/Other') + + def set_switch(self, method): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-select-resize-method' + return (method, show_help) +``` \ No newline at end of file diff --git a/docs/CR Set Switch From String.md b/docs/CR Set Switch From String.md new file mode 100644 index 0000000..acefb8e --- /dev/null +++ b/docs/CR Set Switch From String.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: CR_SetSwitchFromString +- Category: Comfyroll/Utils/Conditional +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SetSwitchFromString 节点旨在将给定的文本输入与一组预定义的字符串选项进行评估,根据匹配项确定一个整数值开关。它作为工作流中的关键决策组件,允许根据输入字符串进行条件分支或触发特定动作。 + +# Input types +## Required +- text + - ‘text’参数是节点与之比较的输入文本,对于提供的开关选项至关重要。它在确定节点输出中起着关键作用,因为匹配过程是节点功能的核心。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- switch_1 + - ‘switch_1’参数代表节点可以与输入文本匹配的开关选项之一。它是决策过程的一部分,根据输入对结果产生影响。 + - Comfy dtype: STRING + - Python dtype: str +- switch_2 + - ‘switch_2’参数是节点评估的另一个潜在开关选项。它对于扩展节点可以响应的条件范围至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- switch_3 + - ‘switch_3’参数作为节点决定其输出的另一个附加开关选项。它增强了节点在处理各种输入场景时的多功能性。 + - Comfy dtype: STRING + - Python dtype: str +- switch_4 + - ‘switch_4’参数是节点考虑的最后一个开关选项。它完成了节点执行其比较和决策任务的选项集。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- switch + - ‘switch’输出代表节点在将输入文本与提供的开关选项进行比较后确定的整数值。它标志着节点决策过程的结果。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - ‘show_help’输出提供指向节点文档页面的URL链接,为寻求了解节点功能的用户提供免费的指导和信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SetSwitchFromString: + + @classmethod + def INPUT_TYPES(cls): + methods = ['Fit', 'Crop'] + return {'required': {'text': ('STRING', {'multiline': False, 'default': '', 'forceInput': True})}, 'optional': {'switch_1': ('STRING', {'multiline': False, 'default': ''}), 'switch_2': ('STRING', {'multiline': False, 'default': ''}), 'switch_3': ('STRING', {'multiline': False, 'default': ''}), 'switch_4': ('STRING', {'multiline': False, 'default': ''})}} + RETURN_TYPES = ('INT', 'STRING') + RETURN_NAMES = ('switch', 'show_help') + FUNCTION = 'set_switch' + CATEGORY = icons.get('Comfyroll/Utils/Conditional') + + def set_switch(self, text, switch_1='', switch_2='', switch_3='', switch_4=''): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-set-switch-from-string' + if text == switch_1: + switch = 1 + elif text == switch_2: + switch = 2 + elif text == switch_3: + switch = 3 + elif text == switch_4: + switch = 4 + else: + pass + return (switch, show_help) +``` \ No newline at end of file diff --git a/docs/CR Set Value On Binary.md b/docs/CR Set Value On Binary.md new file mode 100644 index 0000000..44a93cf --- /dev/null +++ b/docs/CR Set Value On Binary.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CR_SetValueOnBinary +- Category: Comfyroll/Utils/Conditional +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SetValueOnBinary节点旨在根据二进制输入的状态条件性地分配一个值。它的工作原理非常简单:如果二进制输入为真(1),它将返回为真情况指定的值;如果为假(0),它将返回假情况的值。此功能对于在工作流中实现条件逻辑至关重要,允许基于二进制条件对数据流进行简单的操作。 + +# Input types +## Required +- binary + - ‘binary’参数是一个关键输入,它决定了节点的行为。它作为节点决定返回哪个值的条件。二进制输入必须是一个整数,可以是0或1,不接受其他值,确保了一个清晰且明确的条件检查。 + - Comfy dtype: INT + - Python dtype: int +- value_if_1 + - ‘value_if_1’参数定义了当二进制输入为真时将返回的值。它是一个浮点数,可以表示广泛的值,允许在基于二进制条件进行条件分配时具有灵活性。 + - Comfy dtype: FLOAT + - Python dtype: float +- value_if_0 + - ‘value_if_0’参数设定了当二进制输入为假时要返回的值。像‘value_if_1’一样,它也是一个浮点数,确保了节点可以返回的值的类型一致性,无论二进制条件如何。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- INT + - ‘INT’输出提供了二进制输入值的整数表示,作为条件结果的直接和明确的反映。 + - Comfy dtype: INT + - Python dtype: int +- FLOAT + - ‘FLOAT’输出返回与二进制输入条件相关联的值。它是基于二进制输入为真或假而在工作流下游使用的值。 + - Comfy dtype: FLOAT + - Python dtype: float +- show_help + - ‘show_help’输出提供了指向节点文档页面的URL链接,使用户能够轻松访问有关如何有效使用该节点的更详细信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SetValueOnBinary: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'binary': ('INT', {'default': 1, 'min': 0, 'max': 1, 'forceInput': True}), 'value_if_1': ('FLOAT', {'default': 1, 'min': -18446744073709551615, 'max': 18446744073709551615}), 'value_if_0': ('FLOAT', {'default': 0, 'min': -18446744073709551615, 'max': 18446744073709551615})}} + RETURN_TYPES = ('INT', 'FLOAT', 'STRING') + RETURN_NAMES = ('INT', 'FLOAT', 'show_help') + FUNCTION = 'set_value' + CATEGORY = icons.get('Comfyroll/Utils/Conditional') + + def set_value(self, binary, value_if_1, value_if_0): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-set-value-on-boolean' + if binary == 1: + return (int(value_if_1), value_if_1, show_help) + else: + return (int(value_if_0), value_if_0, show_help) +``` \ No newline at end of file diff --git a/docs/CR Set Value On Boolean.md b/docs/CR Set Value On Boolean.md new file mode 100644 index 0000000..07f60ae --- /dev/null +++ b/docs/CR Set Value On Boolean.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CR_SetValueOnBoolean +- Category: Comfyroll/Utils/Conditional +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SetValueOnBoolean节点旨在根据布尔条件的评估来分配一个值。它提供了一个简单的机制,根据输入布尔值为真或假,返回两个值中的一个,从而在工作流中促进条件逻辑。 + +# Input types +## Required +- boolean + - “boolean”参数至关重要,因为它决定了节点逻辑的流程。它根据其真值来决定将返回哪个值。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- value_if_true + - “value_if_true”参数定义了当“boolean”参数被评估为真时返回的值。它在节点的条件输出中扮演着关键角色。 + - Comfy dtype: FLOAT + - Python dtype: float +- value_if_false + - “value_if_false”参数设定了当“boolean”参数被评估为假时返回的值。它对于节点的替代条件输出至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- INT + - “INT”输出代表了根据布尔条件对应的“value_if_true”或“value_if_false”参数的整数值。 + - Comfy dtype: INT + - Python dtype: int +- FLOAT + - “FLOAT”输出提供了基于布尔条件返回值的浮点表示。 + - Comfy dtype: FLOAT + - Python dtype: float +- show_help + - “show_help”输出提供了指向节点文档的URL链接,以供进一步指导和信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SetValueOnBoolean: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'boolean': ('BOOLEAN', {'default': True, 'forceInput': True}), 'value_if_true': ('FLOAT', {'default': 1, 'min': -18446744073709551615, 'max': 18446744073709551615}), 'value_if_false': ('FLOAT', {'default': 0, 'min': -18446744073709551615, 'max': 18446744073709551615})}} + RETURN_TYPES = ('INT', 'FLOAT', 'STRING') + RETURN_NAMES = ('INT', 'FLOAT', 'show_help') + FUNCTION = 'set_value' + CATEGORY = icons.get('Comfyroll/Utils/Conditional') + + def set_value(self, boolean, value_if_true, value_if_false): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-set-value-on-boolean' + if boolean == True: + return (int(value_if_true), value_if_true, show_help) + else: + return (int(value_if_false), value_if_false, show_help) +``` \ No newline at end of file diff --git a/docs/CR Set Value on String.md b/docs/CR Set Value on String.md new file mode 100644 index 0000000..a73bfdf --- /dev/null +++ b/docs/CR Set Value on String.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: CR_SetValueOnString +- Category: Comfyroll/Utils/Conditional +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SetValueOnString 是一个根据特定子字符串的存在条件替换字符串部分的节点。它评估输入文本中给定的测试字符串,并根据是否找到测试字符串,将文本替换为一个值或另一个值。这个节点适用于在满足某些条件时创建动态文本。 + +# Input types +## Required +- text + - 'text' 参数是节点将评估的主要内容。它至关重要,因为它是确定是否存在 'test_string' 以及将使用哪个替换值的基础。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- test_string + - 'test_string' 参数是节点在 'text' 中搜索的子字符串。如果找到,则使用 'value_if_true' 作为替换;否则,使用 'value_if_false'。 + - Comfy dtype: STRING + - Python dtype: str +- value_if_true + - 'value_if_true' 参数指定了如果在 'text' 中找到 'test_string',则将替换 'text' 的字符串。 + - Comfy dtype: STRING + - Python dtype: str +- value_if_false + - 'value_if_false' 参数定义了如果未在 'text' 中找到 'test_string',则将用于替换 'text' 的字符串。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- STRING + - 输出 'STRING' 是条件替换过程的结果。如果输入文本中存在 'test_string',则为 'value_if_true';如果不存在,则为 'value_if_false'。 + - Comfy dtype: STRING + - Python dtype: str +- BOOLEAN + - 'BOOLEAN' 输出指示是否在输入文本中找到了 'test_string'。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- show_help + - 'show_help' 输出提供了指向节点文档的 URL 链接,以供进一步帮助。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SetValueOnString: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {'multiline': False, 'default': '', 'forceInput': True})}, 'optional': {'test_string': ('STRING', {'multiline': False, 'default': ''}), 'value_if_true': ('STRING', {'multiline': False, 'default': ''}), 'value_if_false': ('STRING', {'multiline': False, 'default': ''})}} + RETURN_TYPES = (any_type, 'BOOLEAN', 'STRING') + RETURN_NAMES = ('STRING', 'BOOLEAN', 'show_help') + FUNCTION = 'replace_text' + CATEGORY = icons.get('Comfyroll/Utils/Conditional') + + def replace_text(self, text, test_string, value_if_true, value_if_false): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-set-value-on-string' + if test_string in text: + text_out = value_if_true + bool_out = True + else: + text_out = value_if_false + bool_out = False + return (text_out, bool_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Simple Banner.md b/docs/CR Simple Banner.md new file mode 100644 index 0000000..1a4c842 --- /dev/null +++ b/docs/CR Simple Banner.md @@ -0,0 +1,105 @@ +# Documentation +- Class name: CR_SimpleBanner +- Category: Comfyroll/Graphics/Template +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SimpleBanner 节点旨在从提供的图像和文本创建视觉吸引力强的横幅。它智能地调整文本的大小和位置,确保横幅既易读又美观,提供字体、颜色和轮廓的定制选项以满足不同的设计需求。 + +# Input types +## Required +- image + - 图像参数对于横幅创建过程至关重要,因为它构成了输出的视觉基础。它决定了文本将被渲染的画布。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- banner_text + - 横幅文本是一个关键输入,它传达了旨在传达给观众的信息或消息。这是将被样式化并在横幅上显示的主要内容。 + - Comfy dtype: STRING + - Python dtype: str +- font_name + - 字体名称参数决定了横幅上文本的风格,影响最终输出的整体感觉。它是为横幅消息设定基调的关键因素。 + - Comfy dtype: STRING + - Python dtype: str +- max_font_size + - 最大字体大小参数确保文本在保持易读性的同时适合横幅的尺寸。这是布局和设计横幅文本的一个关键因素。 + - Comfy dtype: INT + - Python dtype: int +- font_color + - 字体颜色参数允许定制文本的外观,确保它在横幅背景上突出显示,以实现最大的视觉冲击力。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- outline_thickness + - 轮廓厚度参数在文本周围添加边框,增强其可见性并赋予其更明确的外观。这是一个可选特性,可以根据设计偏好进行调整。 + - Comfy dtype: INT + - Python dtype: int +- outline_color + - 轮廓颜色参数通过定义文本边框的颜色来补充文本,有助于横幅的整体美学吸引力。 + - Comfy dtype: STRING + - Python dtype: str +- margin_size + - 边距大小参数调整文本周围的间距,提供平衡的外观,并确保文本在横幅上看起来既不显得过于拥挤也不过于稀疏。 + - Comfy dtype: INT + - Python dtype: int +- font_color_hex + - 字体颜色十六进制参数允许使用十六进制值对文本进行精确的颜色定制,为横幅的文本提供了广泛的颜色选择。 + - Comfy dtype: STRING + - Python dtype: str +- outline_color_hex + - 轮廓颜色十六进制参数指定了文本轮廓的十六进制颜色值,允许进行详细的颜色调整,并增强了横幅的视觉设计。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- image + - 输出图像是最终的横幅,它结合了风格化的文本和设计元素。它代表了所有输入参数和对横幅所做的定制的成果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - 显示帮助参数提供了一个链接到文档的链接,以获得有关如何有效使用该节点的进一步指导和帮助。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SimpleBanner: + + @classmethod + def INPUT_TYPES(s): + font_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'fonts') + file_list = [f for f in os.listdir(font_dir) if os.path.isfile(os.path.join(font_dir, f)) and f.lower().endswith('.ttf')] + return {'required': {'image': ('IMAGE',), 'banner_text': ('STRING', {'multiline': True, 'default': 'text'}), 'font_name': (file_list,), 'max_font_size': ('INT', {'default': 150, 'min': 20, 'max': 2048}), 'font_color': (COLORS,), 'outline_thickness': ('INT', {'default': 0, 'min': 0, 'max': 500}), 'outline_color': (COLORS,), 'margin_size': ('INT', {'default': 0, 'min': 0, 'max': 500})}, 'optional': {'font_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'outline_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image', 'show_help') + FUNCTION = 'make_banner' + CATEGORY = icons.get('Comfyroll/Graphics/Template') + + def make_banner(self, image, banner_text, font_name, max_font_size, font_color, outline_thickness, outline_color, margin_size, font_color_hex='#000000', outline_color_hex='#000000'): + text_color = get_color_values(font_color, font_color_hex, color_mapping) + outline_color = get_color_values(outline_color, outline_color_hex, color_mapping) + total_images = [] + for img in image: + back_image = tensor2pil(img).convert('RGBA') + size = (back_image.width, back_image.height) + font_file = os.path.join('fonts', font_name) + resolved_font_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), font_file) + draw = ImageDraw.Draw(back_image) + area_width = back_image.width - margin_size * 2 + area_height = back_image.width - margin_size * 2 + font = get_font_size(draw, banner_text, area_width, area_height, resolved_font_path, max_font_size) + x = back_image.width // 2 + y = back_image.height // 2 + if outline_thickness > 0: + draw.text((x, y), banner_text, fill=text_color, font=font, anchor='mm', stroke_width=outline_thickness, stroke_fill=outline_color) + else: + draw.text((x, y), banner_text, fill=text_color, font=font, anchor='mm') + out_image = np.array(back_image.convert('RGB')).astype(np.float32) / 255.0 + out_image = torch.from_numpy(out_image).unsqueeze(0) + total_images.append(out_image) + images_out = torch.cat(total_images, 0) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Template-Nodes#cr-simple-banner' + return (images_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Simple Binary Pattern.md b/docs/CR Simple Binary Pattern.md new file mode 100644 index 0000000..6d85c79 --- /dev/null +++ b/docs/CR Simple Binary Pattern.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: CR_BinaryPatternSimple +- Category: Comfyroll/Graphics/Pattern +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_BinaryPatternSimple 节点旨在解析二进制模式并将其渲染为可视网格。它接受一个二进制数字的字符串,并将其转换为图像,其中每个位点代表网格中一个方块的颜色,从而创建二进制数据的可视化表示。 + +# Input types +## Required +- binary_pattern + - 二进制模式是一个由二进制数字(0和1)组成的字符串,定义了要绘制的模式。位的每一行对应输出图像中的一行。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- width + - 宽度决定了输出图像的宽度,以像素为单位。它应该是一个正整数,并会影响网格中每个方块的大小。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度决定了输出图像的高度,以像素为单位。与宽度类似,它应该是一个正整数,并定义了网格的垂直尺寸。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - 输出图像是输入的二进制模式的可视化表示。它由一个方格网格组成,每个方格对应模式中的一个位。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - 提供文档的URL链接,以获取有关使用该节点的更多信息和帮助。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_BinaryPatternSimple: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'binary_pattern': ('STRING', {'multiline': True, 'default': '10101'}), 'width': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 4096})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'draw_pattern' + CATEGORY = icons.get('Comfyroll/Graphics/Pattern') + + def draw_pattern(self, binary_pattern, width, height): + rows = binary_pattern.strip().split('\n') + grid = [[int(bit) for bit in row.strip()] for row in rows] + square_width = width // len(rows[0]) + square_height = height // len(rows) + image = Image.new('RGB', (width, height), color='black') + draw = ImageDraw.Draw(image) + for (row_index, row) in enumerate(grid): + for (col_index, bit) in enumerate(row): + x1 = col_index * square_width + y1 = row_index * square_height + x2 = x1 + square_width + y2 = y1 + square_height + color = 'black' if bit == 1 else 'white' + draw.rectangle([x1, y1, x2, y2], fill=color, outline='black') + image_out = pil2tensor(image) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pattern-Nodes-2#cr-simple-binary-pattern' + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Simple Image Compare.md b/docs/CR Simple Image Compare.md new file mode 100644 index 0000000..c60f960 --- /dev/null +++ b/docs/CR Simple Image Compare.md @@ -0,0 +1,119 @@ +# Documentation +- Class name: CR_SimpleImageCompare +- Category: Comfyroll/Graphics/Template +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SimpleImageCompare节点旨在将两张图片并排比较,并在图片上叠加文字。它提供了一种直观的方式来视觉评估图片之间的差异,并包括了文字、字体和布局的定制选项。 + +# Input types +## Required +- text1 + - 要叠加在第一张图片上的第一段文字。这对于提供被比较图片的上下文或描述至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- text2 + - 要叠加在第二张图片上的第二段文字。它与'text1'有类似的作用,提供一种方式来注释或描述比较中的第二张图片。 + - Comfy dtype: STRING + - Python dtype: str +- footer_height + - 放置文字的页脚高度。此参数对于控制分配给文字叠加的垂直空间至关重要。 + - Comfy dtype: INT + - Python dtype: int +- font_name + - 用于文字叠加的字体名称。这影响文字的视觉外观,是样式化输出的关键参数。 + - Comfy dtype: STRING + - Python dtype: str +- font_size + - 文字叠加的字体大小。它决定了文字在图片上的显著程度,是调整文字可读性的重要参数。 + - Comfy dtype: INT + - Python dtype: int +- mode + - 文字和背景颜色的显示模式。它允许用户在浅色或暗色主题之间选择,以获得更好的对比度和可见性。 + - Comfy dtype: COMBO['normal', 'dark'] + - Python dtype: str +- border_thickness + - 围绕图片的边框厚度。这是一个重要的参数,用于定义正在比较的图片的分隔和框架。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- image1 + - 要比较的第一张图片。它是节点功能的核心输入,因为节点旨在比较和展示图片。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- image2 + - 要比较的第二张图片。它与'image1'一起工作,为用户提供并排比较。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Output types +- image + - 包含两张输入图片并排比较及叠加文字的结果图片。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - 一个URL链接,指向该节点的文档,以获取如何使用该节点的进一步指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SimpleImageCompare: + + @classmethod + def INPUT_TYPES(s): + font_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'fonts') + file_list = [f for f in os.listdir(font_dir) if os.path.isfile(os.path.join(font_dir, f)) and f.lower().endswith('.ttf')] + return {'required': {'text1': ('STRING', {'multiline': True, 'default': 'text'}), 'text2': ('STRING', {'multiline': True, 'default': 'text'}), 'footer_height': ('INT', {'default': 100, 'min': 0, 'max': 1024}), 'font_name': (file_list,), 'font_size': ('INT', {'default': 50, 'min': 0, 'max': 1024}), 'mode': (['normal', 'dark'],), 'border_thickness': ('INT', {'default': 20, 'min': 0, 'max': 1024})}, 'optional': {'image1': ('IMAGE',), 'image2': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image', 'show_help') + FUNCTION = 'layout' + CATEGORY = icons.get('Comfyroll/Graphics/Template') + + def layout(self, text1, text2, footer_height, font_name, font_size, mode, border_thickness, image1=None, image2=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Layout-Nodes#cr-simple-image-compare' + if mode == 'normal': + font_color = 'black' + bg_color = 'white' + else: + font_color = 'white' + bg_color = 'black' + if image1 is not None and image2 is not None: + img1 = tensor2pil(image1) + img2 = tensor2pil(image2) + (image_width, image_height) = (img1.width, img1.height) + if img2.width != img1.width or img2.height != img1.height: + img2 = apply_resize_image(img2, image_width, image_height, 8, 'rescale', 'false', 1, 256, 'lanczos') + margins = 50 + line_spacing = 0 + position_x = 0 + position_y = 0 + align = 'center' + rotation_angle = 0 + rotation_options = 'image center' + font_outline_thickness = 0 + font_outline_color = 'black' + align = 'center' + footer_align = 'center' + outline_thickness = border_thickness // 2 + border_thickness = border_thickness // 2 + if footer_height > 0: + text_panel1 = text_panel(image_width, footer_height, text1, font_name, font_size, font_color, font_outline_thickness, font_outline_color, bg_color, margins, line_spacing, position_x, position_y, align, footer_align, rotation_angle, rotation_options) + combined_img1 = combine_images([img1, text_panel1], 'vertical') + if outline_thickness > 0: + combined_img1 = ImageOps.expand(combined_img1, outline_thickness, fill=bg_color) + if footer_height > 0: + text_panel2 = text_panel(image_width, footer_height, text2, font_name, font_size, font_color, font_outline_thickness, font_outline_color, bg_color, margins, line_spacing, position_x, position_y, align, footer_align, rotation_angle, rotation_options) + combined_img2 = combine_images([img2, text_panel2], 'vertical') + if outline_thickness > 0: + combined_img2 = ImageOps.expand(combined_img2, outline_thickness, fill=bg_color) + result_img = combine_images([combined_img1, combined_img2], 'horizontal') + else: + result_img = Image.new('RGB', (512, 512), bg_color) + if border_thickness > 0: + result_img = ImageOps.expand(result_img, border_thickness, bg_color) + return (pil2tensor(result_img), show_help) +``` \ No newline at end of file diff --git a/docs/CR Simple List.md b/docs/CR Simple List.md new file mode 100644 index 0000000..d957f0a --- /dev/null +++ b/docs/CR Simple List.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: CR_SimpleList +- Category: Comfyroll/List +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SimpleList 节点旨在处理和操作字符串列表。其主要功能是对提供的列表值执行交叉连接操作,有效地以各种方式组合元素。该节点旨在简化列表操作过程,为用户提供一个与列表数据交互的直接界面。 + +# Input types +## Required +- list_values + - list_values 参数至关重要,因为它是节点处理的输入列表。它应该是一个包含多行的字符串,其中每一行代表列表中的一个单独元素。节点利用此参数执行其交叉连接功能。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- LIST + - LIST 输出参数代表由节点的 cross_join 函数处理后的列表。它是经过处理的字符串列表,已经去除了首尾空白字符,并过滤掉了任何空行。 + - Comfy dtype: STRING + - Python dtype: List[str] +- show_help + - show_help 输出提供了一个文档的 URL 链接以供进一步帮助。它是一个包含网址的字符串,用户可以在该网址找到有关如何使用 CR_SimpleList 节点及其特性的更多信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SimpleList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'list_values': ('STRING', {'multiline': True, 'default': 'text'})}} + RETURN_TYPES = (any_type, 'STRING') + RETURN_NAMES = ('LIST', 'show_help') + OUTPUT_IS_LIST = (True, False) + FUNCTION = 'cross_join' + CATEGORY = icons.get('Comfyroll/List') + + def cross_join(self, list_values): + lines = list_values.split('\n') + list_out = [i.strip() for i in lines if i.strip()] + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-simple-list' + return (list_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Simple Meme Template.md b/docs/CR Simple Meme Template.md new file mode 100644 index 0000000..020c999 --- /dev/null +++ b/docs/CR Simple Meme Template.md @@ -0,0 +1,149 @@ +# Documentation +- Class name: CR_SimpleMemeTemplate +- Category: Comfyroll/Graphics/Template +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SimpleMemeTemplate 是一个用于生成自定义模因模板的节点。它允许用户输入一张图片,选择模因结构的预设,并在图片的顶部和底部添加文字。该节点还提供了字体、文字颜色以及在文字上方和下方添加装饰性条的定制选项。这个节点的主要目的是使用简单易用的用户界面促进模因图片的创建,使其易于被广泛的用户群体用来进行模因创作。 + +# Input types +## Required +- image + - 图片参数是必需的,因为它定义了将要应用模因模板的基础图片。图片的选择直接影响模因的最终外观,使其成为节点操作中的关键元素。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- preset + - 预设参数决定了模因模板的结构和预定义文本。它通过允许用户从常见的模因格式中选择,从而简化了定制过程。 + - Comfy dtype: COMBO['custom', 'One Does Not Simply ... MEME IN COMFY', 'This is fine.', 'Good Morning ... No Such Thing!'] + - Python dtype: str +- text_top + - text_top 参数允许用户输入将出现在模因图片顶部的文本。它在传达模因的预期信息或主题中起着重要作用。 + - Comfy dtype: STRING + - Python dtype: str +- text_bottom + - text_bottom 参数用于显示在模因图片底部的文本。它补充了顶部文本,并有助于模因的整体构图。 + - Comfy dtype: STRING + - Python dtype: str +- font_name + - font_name 参数使用户能够为模因上的文本选择字体样式。字体的选择可以显著影响模因的可读性和视觉吸引力,因此它是一个重要的定制选项。 + - Comfy dtype: COMBO[file_list] + - Python dtype: str +- max_font_size + - max_font_size 参数为模因模板中的文本字体设置最大尺寸。它是确定模因布局内文本的可读性和视觉平衡的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- font_color + - font_color 参数指定模因模板中文本的颜色。它是节点功能的关键方面,因为它影响文本的可见性以及模因的整体视觉冲击力。 + - Comfy dtype: COMBO[COLORS] + - Python dtype: str +- font_outline + - font_outline 参数为文本添加轮廓效果,可以提高模因图片背景上文本的可见性。轮廓样式的选择还可以为模因的设计增添装饰性。 + - Comfy dtype: COMBO['none', 'thin', 'thick', 'extra thick'] + - Python dtype: str +- bar_color + - bar_color 参数确定模因模板中可能添加在文本上方和下方的装饰性条的颜色。这有助于吸引对文本的注意并提供对比背景。 + - Comfy dtype: COMBO[COLORS] + - Python dtype: str +- bar_options + - bar_options 参数决定是否向模因模板添加装饰性条以及它们相对于文本的位置。这可以影响模因的整体设计和对文本的强调。 + - Comfy dtype: COMBO['no bars', 'top', 'bottom', 'top and bottom'] + - Python dtype: str + +# Output types +- image + - 图片输出包含节点生成的最终模因模板。它代表了用户所做的所有输入参数和定制的成果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了与节点相关联的文档或帮助页面的链接。这对于寻求有关如何使用节点的额外指导或信息的用户可能是有用的。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SimpleMemeTemplate: + + @classmethod + def INPUT_TYPES(s): + font_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'fonts') + file_list = [f for f in os.listdir(font_dir) if os.path.isfile(os.path.join(font_dir, f)) and f.lower().endswith('.ttf')] + bar_opts = ['no bars', 'top', 'bottom', 'top and bottom'] + simple_meme_presets = ['custom', 'One Does Not Simply ... MEME IN COMFY', 'This is fine.', 'Good Morning ... No Such Thing!'] + return {'required': {'image': ('IMAGE',), 'preset': (simple_meme_presets,), 'text_top': ('STRING', {'multiline': True, 'default': 'text_top'}), 'text_bottom': ('STRING', {'multiline': True, 'default': 'text_bottom'}), 'font_name': (file_list,), 'max_font_size': ('INT', {'default': 150, 'min': 20, 'max': 2048}), 'font_color': (COLORS,), 'font_outline': (['none', 'thin', 'thick', 'extra thick'],), 'bar_color': (COLORS,), 'bar_options': (bar_opts,)}, 'optional': {'font_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'bar_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image', 'show_help') + FUNCTION = 'make_meme' + CATEGORY = icons.get('Comfyroll/Graphics/Template') + + def make_meme(self, image, preset, text_top, text_bottom, font_name, max_font_size, font_color, font_outline, bar_color, bar_options, font_color_hex='#000000', bar_color_hex='#000000'): + text_color = get_color_values(font_color, font_color_hex, color_mapping) + bar_color = get_color_values(bar_color, bar_color_hex, color_mapping) + total_images = [] + for img in image: + if bar_options == 'top': + height_factor = 1.2 + elif bar_options == 'bottom': + height_factor = 1.2 + elif bar_options == 'top and bottom': + height_factor = 1.4 + else: + height_factor = 1.0 + if preset == 'One Does Not Simply ... MEME IN COMFY': + text_top = 'One Does Not Simply' + text_bottom = 'MEME IN COMFY' + if preset == 'This is fine.': + text_top = 'This is fine.' + text_bottom = '' + if preset == 'Good Morning ... No Such Thing!': + text_top = 'Good Morning' + text_bottom = '"No Such Thing!"' + back_image = tensor2pil(img) + size = (back_image.width, int(back_image.height * height_factor)) + result_image = Image.new('RGB', size) + font_file = os.path.join('fonts', font_name) + resolved_font_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), font_file) + draw = ImageDraw.Draw(result_image) + bar_width = back_image.width + bar_height = back_image.height // 5 + top_bar = Image.new('RGB', (bar_width, bar_height), bar_color) + bottom_bar = Image.new('RGB', (bar_width, bar_height), bar_color) + if bar_options == 'top' or bar_options == 'top and bottom': + image_out = result_image.paste(back_image, (0, bar_height)) + else: + image_out = result_image.paste(back_image, (0, 0)) + if bar_options == 'top' or bar_options == 'top and bottom': + result_image.paste(top_bar, (0, 0)) + font_top = get_font_size(draw, text_top, bar_width, bar_height, resolved_font_path, max_font_size) + draw_text_on_image(draw, 0, bar_width, bar_height, text_top, font_top, text_color, font_outline) + if bar_options == 'bottom' or bar_options == 'top and bottom': + result_image.paste(bottom_bar, (0, result_image.height - bar_height)) + font_bottom = get_font_size(draw, text_bottom, bar_width, bar_height, resolved_font_path, max_font_size) + if bar_options == 'bottom': + y_position = back_image.height + else: + y_position = bar_height + back_image.height + draw_text_on_image(draw, y_position, bar_width, bar_height, text_bottom, font_bottom, text_color, font_outline) + if bar_options == 'bottom' and text_top > '': + font_top = get_font_size(draw, text_top, bar_width, bar_height, resolved_font_path, max_font_size) + draw_text_on_image(draw, 0, bar_width, bar_height, text_top, font_top, text_color, font_outline) + if (bar_options == 'top' or bar_options == 'none') and text_bottom > '': + font_bottom = get_font_size(draw, text_bottom, bar_width, bar_height, resolved_font_path, max_font_size) + y_position = back_image.height + draw_text_on_image(draw, y_position, bar_width, bar_height, text_bottom, font_bottom, text_color, font_outline) + if bar_options == 'no bars' and text_bottom > '': + font_bottom = get_font_size(draw, text_bottom, bar_width, bar_height, resolved_font_path, max_font_size) + y_position = back_image.height - bar_height + draw_text_on_image(draw, y_position, bar_width, bar_height, text_bottom, font_bottom, text_color, font_outline) + if bar_options == 'no bars' and text_top > '': + font_top = get_font_size(draw, text_top, bar_width, bar_height, resolved_font_path, max_font_size) + draw_text_on_image(draw, 0, bar_width, bar_height, text_top, font_top, text_color, font_outline) + out_image = np.array(result_image.convert('RGB')).astype(np.float32) / 255.0 + out_image = torch.from_numpy(out_image).unsqueeze(0) + total_images.append(out_image) + images_out = torch.cat(total_images, 0) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Template-Nodes#cr-simple-meme-template' + return (images_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Simple Prompt List Keyframes.md b/docs/CR Simple Prompt List Keyframes.md new file mode 100644 index 0000000..e23cedb --- /dev/null +++ b/docs/CR Simple Prompt List Keyframes.md @@ -0,0 +1,85 @@ +# Documentation +- Class name: CR_SimplePromptListKeyframes +- Category: Comfyroll/Animation/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SimplePromptListKeyframes 是一个用于从提示列表生成一系列关键帧的节点。它通过迭代提示列表并为每个关键帧应用指定的时间间隔来编排关键帧数据的创建。该节点能够处理多个循环和过渡,允许定制动画序列。 + +# Input types +## Required +- simple_prompt_list + - simple_prompt_list 参数是一个提示集合,用于生成关键帧。列表中的每个提示对应最终输出中的一个关键帧。 + - Comfy dtype: STRING + - Python dtype: List[str] +## Optional +- keyframe_interval + - keyframe_interval 参数定义了每个关键帧之间的时间增量。它对控制动画序列的节奏至关重要,可以调整以控制过渡的速度。 + - Comfy dtype: INT + - Python dtype: int +- loops + - loops 参数指定关键帧序列应重复的次数。它是创建重复或循环动画的一个基本方面。 + - Comfy dtype: INT + - Python dtype: int +- transition_type + - transition_type 参数确定关键帧之间过渡的风格。它影响动画的视觉流动性,可以设置为 'Default' 或其他预定义选项。 + - Comfy dtype: COMBO['Default'] + - Python dtype: str +- transition_speed + - transition_speed 参数指示关键帧之间过渡的速度。它可以设置为 'Default' 或其他选项,以控制过渡的快慢。 + - Comfy dtype: COMBO['Default'] + - Python dtype: str +- transition_profile + - transition_profile 参数设置过渡的轮廓,这可以影响过渡随时间的显示方式。它设置为 'Default' 或其他轮廓以实现不同的效果。 + - Comfy dtype: COMBO['Default'] + - Python dtype: str +- keyframe_format + - keyframe_format 参数指定关键帧的展示格式。'Deforum' 选项用于确保与某些动画系统的兼容性。 + - Comfy dtype: COMBO['Deforum'] + - Python dtype: str + +# Output types +- keyframe_list + - keyframe_list 输出是生成的关键帧的字符串表示。它的格式可以直接用于动画系统中。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - show_help 输出提供了一个文档的URL链接,以进一步协助和理解如何有效地使用该节点。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SimplePromptListKeyframes: + + @classmethod + def INPUT_TYPES(s): + transition_types = ['Default'] + transition_speeds = ['Default'] + transition_profiles = ['Default'] + return {'required': {'simple_prompt_list': ('SIMPLE_PROMPT_LIST',), 'keyframe_interval': ('INT', {'default': 30, 'min': 0, 'max': 999, 'step': 1}), 'loops': ('INT', {'default': 1, 'min': 1, 'max': 1000}), 'transition_type': (transition_types,), 'transition_speed': (transition_speeds,), 'transition_profile': (transition_profiles,), 'keyframe_format': (['Deforum'],)}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('keyframe_list', 'show_help') + FUNCTION = 'make_keyframes' + CATEGORY = icons.get('Comfyroll/Animation/Legacy') + + def make_keyframes(self, simple_prompt_list, keyframe_interval, loops, transition_type, transition_speed, transition_profile, keyframe_format): + keyframe_format = 'Deforum' + keyframe_list = list() + i = 0 + for j in range(1, loops + 1): + for (index, prompt) in enumerate(simple_prompt_list): + if i == 0: + keyframe_list.extend(['"0": "' + prompt + '",\n']) + i += keyframe_interval + continue + new_keyframe = '"' + str(i) + '": "' + prompt + '",\n' + keyframe_list.extend([new_keyframe]) + i += keyframe_interval + keyframes_out = ' '.join(keyframe_list)[:-2] + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Prompt-Nodes#cr-simple-prompt-list-keyframes' + return (keyframes_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Simple Prompt List.md b/docs/CR Simple Prompt List.md new file mode 100644 index 0000000..3cb47bf --- /dev/null +++ b/docs/CR Simple Prompt List.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: CR_SimplePromptList +- Category: Comfyroll/Animation/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SimplePromptList 是一个设计用来高效聚合和管理提示列表的节点。它的目的是将多个提示堆叠成一个单一的列表,这些列表可以用于下游的各种处理任务。节点的功能集中在合并文本提示上,强调其在为动画工作流程简化提示管理方面的作用。 + +# Input types +## Required +- prompt_1 + - prompt_1 是节点的第一个文本输入,允许用户将特定的提示注入到处理流程中。它的包含至关重要,因为它直接贡献于最终聚合的提示列表,影响节点的输出和后续操作。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- simple_prompt_list + - simple_prompt_list 是一个可选参数,它允许节点接受一个预先存在的提示列表。这个特性通过允许用户用额外的条目扩展或修改提示列表,增强了节点的灵活性,从而影响整体的提示聚合过程。 + - Comfy dtype: SIMPLE_PROMPT_LIST + - Python dtype: List[str] + +# Output types +- SIMPLE_PROMPT_LIST + - SIMPLE_PROMPT_LIST 输出代表了节点操作产生的聚合提示列表。它是一个关键组件,因为它构成了动画工作流程中进一步处理或分析的基础,突出了节点在提示管理方面的贡献。 + - Comfy dtype: SIMPLE_PROMPT_LIST + - Python dtype: List[str] +- show_help + - show_help 输出提供了一个链接到文档页面的URL,以供进一步帮助。它作为一个有用的资源,供用户寻求如何有效地在他们的动画项目中使用节点的更多信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SimplePromptList: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'prompt_1': ('STRING', {'multiline': True, 'default': 'prompt'}), 'prompt_2': ('STRING', {'multiline': True, 'default': 'prompt'}), 'prompt_3': ('STRING', {'multiline': True, 'default': 'prompt'}), 'prompt_4': ('STRING', {'multiline': True, 'default': 'prompt'}), 'prompt_5': ('STRING', {'multiline': True, 'default': 'prompt'})}, 'optional': {'simple_prompt_list': ('SIMPLE_PROMPT_LIST',)}} + RETURN_TYPES = ('SIMPLE_PROMPT_LIST', 'STRING') + RETURN_NAMES = ('SIMPLE_PROMPT_LIST', 'show_help') + FUNCTION = 'prompt_stacker' + CATEGORY = icons.get('Comfyroll/Animation/Legacy') + + def prompt_stacker(self, prompt_1, prompt_2, prompt_3, prompt_4, prompt_5, simple_prompt_list=None): + prompts = list() + if simple_prompt_list is not None: + prompts.extend([l for l in simple_prompt_list]) + if prompt_1 != '': + (prompts.extend([prompt_1]),) + if prompt_2 != '': + (prompts.extend([prompt_2]),) + if prompt_3 != '': + (prompts.extend([prompt_3]),) + if prompt_4 != '': + (prompts.extend([prompt_4]),) + if prompt_5 != '': + (prompts.extend([prompt_5]),) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Prompt-Nodes#cr-simple-prompt-list' + return (prompts, show_help) +``` \ No newline at end of file diff --git a/docs/CR Simple Prompt Scheduler.md b/docs/CR Simple Prompt Scheduler.md new file mode 100644 index 0000000..e471cf9 --- /dev/null +++ b/docs/CR Simple Prompt Scheduler.md @@ -0,0 +1,89 @@ +# Documentation +- Class name: CR_SimplePromptScheduler +- Category: Comfyroll/Animation/Schedulers +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SimplePromptScheduler 是一个用于管理和根据关键帧列表调度提示的节点。它允许在特定帧自动更改提示,从而在不需要手动干预的情况下促进动态和特定帧内容的创建。这个节点对于简化画过程至关重要,特别是当处理需要精确提示调整的复杂序列时。 + +# Input types +## Required +- keyframe_list + - 关键帧列表是一个关键参数,它定义了提示及其对应的帧的顺序。它使节点能够有效地调度提示,确保在动画的正确时间显示正确的提示。 + - Comfy dtype: STRING + - Python dtype: str +- current_frame + - 当前帧参数至关重要,因为它指示动画时间轴上的当前点。节点使用这些信息来确定关键帧列表中哪个提示应该对正在进行的帧处于激活状态。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- keyframe_format + - 关键帧格式参数指定了关键帧数据的结构,允许节点正确解析和解释关键帧列表。对于保持调度提示的完整性和准确性很重要。 + - Comfy dtype: COMBO['CR', 'Deforum'] + - Python dtype: str + +# Output types +- current_prompt + - 当前提示输出提供了当前帧的激活提示。它很重要,因为它直接影响着动画中显示或处理的内容。 + - Comfy dtype: STRING + - Python dtype: str +- next_prompt + - 下一个提示输出指示将在下一帧中激活的提示。这允许对即将到来的内容进行预期,并可用于提示之间的平滑过渡。 + - Comfy dtype: STRING + - Python dtype: str +- weight + - 权重输出表示当前提示和下一个提示之间的过渡权重。它用于插值提示,以实现逐渐变化,增强动画的流畅性。 + - Comfy dtype: FLOAT + - Python dtype: float +- show_help + - 显示帮助输出提供了一个链接到文档以获得进一步帮助。对于需要更多关于节点功能信息或需要故障排除支持的用户来说,这是有用的。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SimplePromptScheduler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'keyframe_list': ('STRING', {'multiline': True, 'default': 'frame_number, text'}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'keyframe_format': (['CR', 'Deforum'],)}} + RETURN_TYPES = ('STRING', 'STRING', 'FLOAT', 'STRING') + RETURN_NAMES = ('current_prompt', 'next_prompt', 'weight', 'show_help') + FUNCTION = 'simple_schedule' + CATEGORY = icons.get('Comfyroll/Animation/Schedulers') + + def simple_schedule(self, keyframe_list, keyframe_format, current_frame): + keyframes = list() + if keyframe_list == '': + print(f'[Error] CR Simple Prompt Scheduler. No lines in keyframe list') + return () + lines = keyframe_list.split('\n') + for line in lines: + if keyframe_format == 'Deforum': + line = line.replace(':', ',') + line = line.rstrip(',') + if not line.strip(): + print(f'[Warning] CR Simple Prompt Scheduler. Skipped blank line at line {i}') + continue + keyframes.extend([('SIMPLE', line)]) + (current_prompt, next_prompt, current_keyframe, next_keyframe) = prompt_scheduler(keyframes, 'SIMPLE', current_frame) + if current_prompt == '': + print(f'[Warning] CR Simple Prompt Scheduler. No prompt found for frame. Simple schedules must start at frame 0.') + else: + try: + current_prompt_out = str(current_prompt) + next_prompt_out = str(next_prompt) + from_index = int(current_keyframe) + to_index = int(next_keyframe) + except ValueError: + print(f'[Warning] CR Simple Text Scheduler. Invalid keyframe at frame {current_frame}') + if from_index == to_index: + weight_out = 1.0 + else: + weight_out = (to_index - current_frame) / (to_index - from_index) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-simple-prompt-scheduler' + return (current_prompt_out, next_prompt_out, weight_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Simple Schedule.md b/docs/CR Simple Schedule.md new file mode 100644 index 0000000..fba7bd1 --- /dev/null +++ b/docs/CR Simple Schedule.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: CR_SimpleSchedule +- Category: Comfyroll/Animation/Schedule +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SimpleSchedule 是一个用于管理和组织动画工作流程中各种任务的时间表的节点。它处理输入的时间表,根据类型对它们进行分类,并为在不同上下文中使用进行格式化,确保了在 Comfyroll 中安排时间表的流程化方法。 + +# Input types +## Required +- schedule + - ‘schedule’参数对于定义时间表的内容至关重要。它应该是一个包含多行的字符串,每行代表一个不同的时间表项目。此输入通过提供将被处理和格式化的原始数据来驱动节点的核心功能。 + - Comfy dtype: STRING + - Python dtype: str +- schedule_type + - ‘schedule_type’参数决定了时间表项的类别。它是一个关键组件,因为它决定了时间表在系统中的解释和使用方式。每种类型可能对应不同的处理机制或处理逻辑。 + - Comfy dtype: COMBO['Value', 'Text', 'Prompt', 'Prompt Weight', 'Model', 'LoRA', 'ControlNet', 'Style', 'Upscale', 'Camera', 'Job'] + - Python dtype: str +## Optional +- schedule_alias + - ‘schedule_alias’参数为时间表提供了一个替代名称或标识符,这对于在更大的工作流程中引用或组织时间表非常有用。虽然不是必需的,但它为调度过程增加了一层灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- schedule_format + - ‘schedule_format’参数指定了时间表的期望输出格式。它允许用户在不同的格式化样式之间进行选择,这对于与各种系统的兼容性或用户偏好至关重要。 + - Comfy dtype: COMBO['CR', 'Deforum'] + - Python dtype: str + +# Output types +- SCHEDULE + - ‘SCHEDULE’输出是包含元组的列表,每个元组包含一个时间表别名和输入时间表的相应行。此输出代表已处理和格式化的时间表,可供下游应用程序或系统使用。 + - Comfy dtype: LIST[Tuple[str, str]] + - Python dtype: List[Tuple[str, str]] +- show_help + - ‘show_help’输出提供了一个指向文档的URL链接,以获取更多帮助。对于需要更多关于如何使用节点或了解其功能信息的用户来说,这非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SimpleSchedule: + + @classmethod + def INPUT_TYPES(s): + schedule_types = ['Value', 'Text', 'Prompt', 'Prompt Weight', 'Model', 'LoRA', 'ControlNet', 'Style', 'Upscale', 'Camera', 'Job'] + return {'required': {'schedule': ('STRING', {'multiline': True, 'default': 'frame_number, item_alias, [attr_value1, attr_value2]'}), 'schedule_type': (schedule_types,), 'schedule_alias': ('STRING', {'default': '', 'multiline': False}), 'schedule_format': (['CR', 'Deforum'],)}} + RETURN_TYPES = ('SCHEDULE', 'STRING') + RETURN_NAMES = ('SCHEDULE', 'show_help') + FUNCTION = 'send_schedule' + CATEGORY = icons.get('Comfyroll/Animation/Schedule') + + def send_schedule(self, schedule, schedule_type, schedule_alias, schedule_format): + schedule_lines = list() + if schedule != '' and schedule_alias != '': + lines = schedule.split('\n') + for line in lines: + if not line.strip(): + print(f'[Warning] CR Simple Schedule. Skipped blank line: {line}') + continue + schedule_lines.extend([(schedule_alias, line)]) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Schedule-Nodes#cr-simple-schedule' + return (schedule_lines, show_help) +``` \ No newline at end of file diff --git a/docs/CR Simple Text Panel.md b/docs/CR Simple Text Panel.md new file mode 100644 index 0000000..7b9a81d --- /dev/null +++ b/docs/CR Simple Text Panel.md @@ -0,0 +1,96 @@ +# Documentation +- Class name: CR_SimpleTextPanel +- Category: Comfyroll/Graphics/Layout +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SimpleTextPanel 旨在创建具有可定制字体、颜色和布局选项的视觉上吸引人的文本面板。它允许将文本渲染到图像背景上,并具有各种样式功能,如字体轮廓和对齐方式,以增强文本信息的展示效果。 + +# Input types +## Required +- panel_width + - 文本面板的宽度决定了输出图像的水平范围。这是一个关键参数,因为它决定了文本内容可用的空间,影响整体布局和外观。 + - Comfy dtype: INT + - Python dtype: int +- panel_height + - 文本面板的高度设置了面板的垂直尺寸,这对于控制文本的垂直空间并确保文本适应图像边界至关重要。 + - Comfy dtype: INT + - Python dtype: int +- text + - 文本参数是面板上要显示的实际内容。它可以包含多行文本,这对于更长的段落或当需要更复杂的布局时特别有用。 + - Comfy dtype: STRING + - Python dtype: str +- font_name + - 字体名称参数指定用于文本的字体类型。字体的选择可以显著影响面板内文本的风格和可读性。 + - Comfy dtype: STRING + - Python dtype: str +- font_color + - 字体颜色决定了文本的颜色,允许用户将文本与背景或特定设计主题相匹配。它在确保文本可读性和视觉对比度方面起着至关重要的作用。 + - Comfy dtype: STRING + - Python dtype: str +- font_size + - 字体大小控制文本的规模,这对于可读性和调整文本以适应指定的面板尺寸是一个重要因素。 + - Comfy dtype: INT + - Python dtype: int +- font_outline_thickness + - 字体轮廓的厚度增加了文本的强调效果,并可以提高其在复杂背景上的可见性。这是一个可选的风格选择,可以增强文本的外观。 + - Comfy dtype: INT + - Python dtype: int +- font_outline_color + - 字体轮廓颜色提供了一个对比边界,可以增强文本的定义,并在背景中脱颖而出,特别是当字体颜色和背景相似时。 + - Comfy dtype: STRING + - Python dtype: str +- background_color + - 背景颜色为文本面板设置了基本色调,可以影响设计的总体氛围和美感。它是创建和谐视觉组合的关键要素。 + - Comfy dtype: STRING + - Python dtype: str +- align + - 对齐参数决定了文本在面板内的水平对齐方式,这可以影响设计的对称性和平衡。 + - Comfy dtype: STRING + - Python dtype: str +- justify + - 对齐选项控制单词和字符之间的间距,确保文本沿左右边距均匀对齐。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- image + - 结果图像是 CR_SimpleTextPanel 节点的主要输出,包含在指定背景上布局的样式化文本。它代表了节点功能最终的视觉产品。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个 URL 链接到文档页面,以获取关于节点使用和功能的进一步帮助或信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SimpleTextPanel: + + @classmethod + def INPUT_TYPES(s): + font_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'fonts') + file_list = [f for f in os.listdir(font_dir) if os.path.isfile(os.path.join(font_dir, f)) and f.lower().endswith('.ttf')] + return {'required': {'panel_width': ('INT', {'default': 512, 'min': 8, 'max': 4096}), 'panel_height': ('INT', {'default': 512, 'min': 8, 'max': 4096}), 'text': ('STRING', {'multiline': True, 'default': 'text'}), 'font_name': (file_list,), 'font_color': (COLORS,), 'font_size': ('INT', {'default': 100, 'min': 0, 'max': 1024}), 'font_outline_thickness': ('INT', {'default': 0, 'min': 0, 'max': 50}), 'font_outline_color': (COLORS,), 'background_color': (COLORS,), 'align': (ALIGN_OPTIONS,), 'justify': (JUSTIFY_OPTIONS,)}, 'optional': {'font_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'bg_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image', 'show_help') + FUNCTION = 'layout' + CATEGORY = icons.get('Comfyroll/Graphics/Layout') + + def layout(self, panel_width, panel_height, text, align, justify, font_name, font_color, font_size, font_outline_thickness, font_outline_color, background_color, font_color_hex='#000000', font_outline_color_hex='#000000', bg_color_hex='#000000'): + font_color = get_color_values(font_color, font_color_hex, color_mapping) + outline_color = get_color_values(font_outline_color, font_outline_color_hex, color_mapping) + bg_color = get_color_values(background_color, bg_color_hex, color_mapping) + margins = 50 + line_spacing = 0 + position_x = 0 + position_y = 0 + rotation_angle = 0 + rotation_options = 'image center' + panel = text_panel(panel_width, panel_height, text, font_name, font_size, font_color, font_outline_thickness, outline_color, bg_color, margins, line_spacing, position_x, position_y, align, justify, rotation_angle, rotation_options) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Layout-Nodes#cr-simple-text-panel' + return (pil2tensor(panel), show_help) +``` \ No newline at end of file diff --git a/docs/CR Simple Text Scheduler.md b/docs/CR Simple Text Scheduler.md new file mode 100644 index 0000000..2943edd --- /dev/null +++ b/docs/CR Simple Text Scheduler.md @@ -0,0 +1,63 @@ +# Documentation +- Class name: CR_SimpleTextScheduler +- Category: Comfyroll/Animation/Schedulers +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SimpleTextScheduler 是一个用于管理和调度文本输出的节点,它基于预定义的关键帧集合和动画序列中的当前帧。该节点为用户提供了一个简单的接口,用于输入一个时间表,并为给定的帧检索相应的文本,确保在动画中无缝集成动态文本元素。 + +# Input types +## Required +- schedule + - schedule 参数是一个包含文本调度器关键帧信息的字符串。它对于定义整个动画中文本变化的顺序至关重要。multiline 属性允许更复杂时间表的定义,可以跨多行输入。 + - Comfy dtype: STRING + - Python dtype: str +- current_frame + - current_frame 参数指示动画序列中的当前位置。它对于确定在任何给定时刻应该显示时间表中的哪个文本至关重要。整数类型确保了精确的帧跟踪。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- text_out + - text_out 参数代表当前帧计划显示的文本。这是节点的主要输出,提供了与动画进展相一致的动态文本内容。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - show_help 参数提供了一个文档的 URL 链接,用于进一步的帮助。对于需要更多关于如何使用节点或解决故障信息的用户来说,它特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SimpleTextScheduler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'schedule': ('STRING', {'multiline': True, 'default': 'frame_number, text'}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + FUNCTION = 'simple_schedule' + CATEGORY = icons.get('Comfyroll/Animation/Schedulers') + + def simple_schedule(self, schedule, current_frame): + schedule_lines = list() + if schedule == '': + print(f'[Warning] CR Simple Text Scheduler. No lines in schedule') + return () + lines = schedule.split('\n') + for line in lines: + schedule_lines.extend([('SIMPLE', line)]) + params = keyframe_scheduler(schedule_lines, 'SIMPLE', current_frame) + if params == '': + print(f'[Warning] CR Simple Text Scheduler. No schedule found for frame. Simple schedules must start at frame 0.') + else: + try: + text_out = str(params) + except ValueError: + print(f'[Warning] CR Simple Text Scheduler. Invalid params {params} at frame {current_frame}') + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-simple-text-scheduler' + return (text_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Simple Text Watermark.md b/docs/CR Simple Text Watermark.md new file mode 100644 index 0000000..cac5db3 --- /dev/null +++ b/docs/CR Simple Text Watermark.md @@ -0,0 +1,116 @@ +# Documentation +- Class name: CR_SimpleTextWatermark +- Category: Comfyroll/Graphics/Text +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SimpleTextWatermark 节点旨在将文本作为水印叠加在图像上。它允许自定义文本属性,如对齐方式、不透明度和字体样式,以使水印与图像内容无缝融合。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它定义了将应用水印文本的基础媒体。选择的图像直接影响水印在图像上下文中的最终外观。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- text + - 文本参数指定了将叠加在图像上的水印内容。文本的信息和样式对于向观众传达预期的信息或品牌至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- align + - 对齐参数决定了水印文本相对于图像的位置。这对于确保文本被放置在一个视觉上吸引人且适当的位置至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- font_name + - 字体名称参数选择水印文本的字体类型。字体的选择可以显著影响文本在图像中的可读性和视觉吸引力。 + - Comfy dtype: STRING + - Python dtype: str +- font_size + - 字体大小参数设置水印文本的大小。这个属性很重要,因为它影响文本在图像上显示时的突出度和易读性。 + - Comfy dtype: INT + - Python dtype: int +- font_color + - 字体颜色参数定义了水印文本的颜色。它在确保文本在图像背景中脱颖而出,同时保持一致的视觉主题方面起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +- opacity + - 不透明度参数调整水印文本的透明度级别。它很重要,因为它允许文本可见,而不会压倒底层图像内容。 + - Comfy dtype: FLOAT + - Python dtype: float +- x_margin + - x_margin 参数指定了图像边缘到水印文本的水平间距。这对于实现平衡布局并防止文本看起来太靠近图像边缘很重要。 + - Comfy dtype: INT + - Python dtype: int +- y_margin + - y_margin 参数指定了图像边缘到水印文本的垂直间距。这对于保持视觉上吸引人的布局并确保文本不会被其他图像元素遮挡至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- font_color_hex + - font_color_hex 参数允许为水印文本使用自定义的十六进制颜色值。这对于与品牌或设计规范进行精确的颜色匹配可能很重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - IMAGE 输出提供了应用了水印的最终图像。它是所有节点参数协同工作以产生所需视觉效果的成果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了指向节点文档的 URL,以供进一步指导或帮助。对于寻求如何有效使用节点的更多信息的用户来说,这是一个宝贵的资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SimpleTextWatermark: + + @classmethod + def INPUT_TYPES(s): + font_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'fonts') + file_list = [f for f in os.listdir(font_dir) if os.path.isfile(os.path.join(font_dir, f)) and f.lower().endswith('.ttf')] + ALIGN_OPTIONS = ['center', 'top left', 'top center', 'top right', 'bottom left', 'bottom center', 'bottom right'] + return {'required': {'image': ('IMAGE',), 'text': ('STRING', {'multiline': False, 'default': '@ your name'}), 'align': (ALIGN_OPTIONS,), 'opacity': ('FLOAT', {'default': 0.3, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'font_name': (file_list,), 'font_size': ('INT', {'default': 50, 'min': 1, 'max': 1024}), 'font_color': (COLORS,), 'x_margin': ('INT', {'default': 20, 'min': -1024, 'max': 1024}), 'y_margin': ('INT', {'default': 20, 'min': -1024, 'max': 1024})}, 'optional': {'font_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'overlay_text' + CATEGORY = icons.get('Comfyroll/Graphics/Text') + + def overlay_text(self, image, text, align, font_name, font_size, font_color, opacity, x_margin, y_margin, font_color_hex='#000000'): + text_color = get_color_values(font_color, font_color_hex, color_mapping) + total_images = [] + for img in image: + img = tensor2pil(img) + textlayer = Image.new('RGBA', img.size) + draw = ImageDraw.Draw(textlayer) + font_file = os.path.join('fonts', str(font_name)) + resolved_font_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), font_file) + font = ImageFont.truetype(str(resolved_font_path), size=font_size) + textsize = get_text_size(draw, text, font) + if align == 'center': + textpos = [(img.size[0] - textsize[0]) // 2, (img.size[1] - textsize[1]) // 2] + elif align == 'top left': + textpos = [x_margin, y_margin] + elif align == 'top center': + textpos = [(img.size[0] - textsize[0]) // 2, y_margin] + elif align == 'top right': + textpos = [img.size[0] - textsize[0] - x_margin, y_margin] + elif align == 'bottom left': + textpos = [x_margin, img.size[1] - textsize[1] - y_margin] + elif align == 'bottom center': + textpos = [(img.size[0] - textsize[0]) // 2, img.size[1] - textsize[1] - y_margin] + elif align == 'bottom right': + textpos = [img.size[0] - textsize[0] - x_margin, img.size[1] - textsize[1] - y_margin] + draw.text(textpos, text, font=font, fill=text_color) + if opacity != 1: + textlayer = reduce_opacity(textlayer, opacity) + out_image = Image.composite(textlayer, img, textlayer) + out_image = np.array(out_image.convert('RGB')).astype(np.float32) / 255.0 + out_image = torch.from_numpy(out_image).unsqueeze(0) + total_images.append(out_image) + images_out = torch.cat(total_images, 0) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Text-Nodes#cr-simple-text-watermark' + return (images_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Simple Value Scheduler.md b/docs/CR Simple Value Scheduler.md new file mode 100644 index 0000000..0d57ca4 --- /dev/null +++ b/docs/CR Simple Value Scheduler.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: CR_SimpleValueScheduler +- Category: Comfyroll/Animation/Schedulers +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SimpleValueScheduler 是一个用于管理和插值关键帧时间表的节点,用于值的调度。它在创建帧之间的平滑过渡和动态变化中起着关键作用,为用户提供了一种简单直接的方式来安排和随时间变化地操作值。 + +# Input types +## Required +- schedule + - schedule 输入对于定义随时间变化的关键帧值至关重要。它允许在不同帧上指定不同的值,使节点能够在它们之间进行插值。 + - Comfy dtype: STRING + - Python dtype: str +- current_frame + - current_frame 参数指示动画时间线中的当前位置。它对于确定在任何给定时刻应用哪个预定值至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- INT + - INT 输出提供了当前帧预定值的整数表示,可以用于动画流水线中的数值运算。 + - Comfy dtype: INT + - Python dtype: int +- FLOAT + - FLOAT 输出提供了预定值的浮点数解释,适用于动画过程中更精确的计算和调整。 + - Comfy dtype: FLOAT + - Python dtype: float +- show_help + - show_help 输出提供了文档链接,以便在使用 CR_SimpleValueScheduler 节点时获得进一步的指导和帮助。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SimpleValueScheduler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'schedule': ('STRING', {'multiline': True, 'default': 'frame_number, value'}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('INT', 'FLOAT', 'STRING') + RETURN_NAMES = ('INT', 'FLOAT', 'show_help') + FUNCTION = 'simple_schedule' + CATEGORY = icons.get('Comfyroll/Animation/Schedulers') + + def simple_schedule(self, schedule, current_frame): + schedule_lines = list() + if schedule == '': + print(f'[Warning] CR Simple Value Scheduler. No lines in schedule') + return () + lines = schedule.split('\n') + for line in lines: + schedule_lines.extend([('SIMPLE', line)]) + params = keyframe_scheduler(schedule_lines, 'SIMPLE', current_frame) + if params == '': + print(f'[Warning] CR Simple Value Scheduler. No schedule found for frame. Simple schedules must start at frame 0.') + else: + try: + int_out = int(params.split('.')[0]) + float_out = float(params) + except ValueError: + print(f'[Warning] CR Simple Value Scheduler. Invalid params {params} at frame {current_frame}') + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-simple-value-scheduler' + return (int_out, float_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Split String.md b/docs/CR Split String.md new file mode 100644 index 0000000..02f09ad --- /dev/null +++ b/docs/CR Split String.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: CR_SplitString +- Category: Comfyroll/Utils/Text +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_SplitString 节点旨在根据指定的分隔符将给定的文本字符串分割成多个子字符串。它特别适用于处理和组织由一致的字符或字符序列分隔的文本数据。该节点的功能在于其能够通过将复杂的文本结构分解为更易于管理的组件来简化复杂文本的处理。 + +# Input types +## Required +- text + - 'text' 参数是节点的主要输入,表示将要被分割的字符串。它是核心组件,因为节点的所有操作都围绕着将这段文本分割成子字符串进行。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- delimiter + - 'delimiter' 参数定义了用于分割输入文本的字符或字符序列。虽然它是可选的,但在确定如何将文本分割为子字符串方面起着关键作用,从而影响节点的输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- string_1 + - 'string_1' 输出包含分割操作得到的第一个子字符串。它代表原始文本的一部分,作为节点功能的主要结果之一,具有重要意义。 + - Comfy dtype: STRING + - Python dtype: str +- string_2 + - 'string_2' 输出保存了分割操作得到的第二个子字符串。它是原始文本的另一个片段,对于提供输入文本的详细分解很重要。 + - Comfy dtype: STRING + - Python dtype: str +- string_3 + - 'string_3' 输出在文本被分割后提供第三个子字符串。它延续了分割文本部分的序列,是节点全面文本处理能力的一部分。 + - Comfy dtype: STRING + - Python dtype: str +- string_4 + - 'string_4' 输出包括从分割操作中得到的第四个子字符串。它是分割文本的另一部分,有助于节点的整体文本操作功能。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - 'show_help' 输出提供了指向节点文档页面的 URL 链接,为用户提供了如何有效使用该节点的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_SplitString: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': False, 'default': 'text'})}, 'optional': {'delimiter': ('STRING', {'multiline': False, 'default': ','})}} + RETURN_TYPES = (any_type, any_type, any_type, any_type, 'STRING') + RETURN_NAMES = ('string_1', 'string_2', 'string_3', 'string_4', 'show_help') + FUNCTION = 'split' + CATEGORY = icons.get('Comfyroll/Utils/Text') + + def split(self, text, delimiter=''): + parts = text.split(delimiter) + strings = [part.strip() for part in parts[:4]] + (string_1, string_2, string_3, string_4) = strings + [''] * (4 - len(strings)) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-split-string' + return (string_1, string_2, string_3, string_4, show_help) +``` \ No newline at end of file diff --git a/docs/CR Starburst Colors.md b/docs/CR Starburst Colors.md new file mode 100644 index 0000000..3e04c88 --- /dev/null +++ b/docs/CR Starburst Colors.md @@ -0,0 +1,122 @@ +# Documentation +- Class name: CR_StarburstColors +- Category: Comfyroll/Graphics/Pattern +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_StarburstColors 节点旨在生成具有可定制颜色和几何属性的视觉效果吸引人的星暴图案。它提供了一种创造性的方法来制作可以用于各种图形应用的复杂设计。 + +# Input types +## Required +- width + - 宽度参数决定了生成图像的宽度,这对于设置星暴图案的整体尺寸至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置了图像的垂直范围,与宽度一起工作,以建立星暴图案的画布大小。 + - Comfy dtype: INT + - Python dtype: int +- num_triangles + - 三角形的数量决定了星暴图案的复杂性和细节,影响整体视觉效果。 + - Comfy dtype: INT + - Python dtype: int +- color_1 + - 第一种颜色参数允许用户选择星暴的主要颜色,这显著影响图案的最终美感。 + - Comfy dtype: COLORS + - Python dtype: str +- color_2 + - 第二种颜色参数用于定义星暴中的次要颜色,为设计提供对比元素。 + - Comfy dtype: COLORS + - Python dtype: str +- center_x + - center_x 确定了星暴中心的 x 坐标,这对于在图像内定位图案至关重要。 + - Comfy dtype: INT + - Python dtype: int +- center_y + - center_y 设置星暴中心的 y 坐标,确保图案在画布上垂直对齐。 + - Comfy dtype: INT + - Python dtype: int +- bbox_factor + - 边界框因子决定了星暴图案的缩放,影响图像内三角形的大小。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- rotation + - 旋转为星暴图案添加了旋转效果,允许设计中出现动态变化。 + - Comfy dtype: FLOAT + - Python dtype: float +- color1_hex + - color1_hex 是一个可选参数,允许为星暴的第一个颜色输入自定义的十六进制颜色,提供高级颜色定制。 + - Comfy dtype: STRING + - Python dtype: str +- color2_hex + - color2_hex 是一个可选参数,用于为星暴的第二种颜色指定自定义的十六进制颜色,增强设计灵活性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - IMAGE 输出提供了渲染后的星暴图案作为图像,可以进一步处理或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个 URL 链接到文档,以便进一步指导如何使用该节点。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_StarburstColors: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'num_triangles': ('INT', {'default': 6, 'min': 1, 'max': 512}), 'color_1': (COLORS,), 'color_2': (COLORS,), 'center_x': ('INT', {'default': 0, 'min': 0, 'max': 512}), 'center_y': ('INT', {'default': 0, 'min': 0, 'max': 512}), 'rotation': ('FLOAT', {'default': 0, 'min': 0, 'max': 720}), 'bbox_factor': ('FLOAT', {'default': 2, 'min': 0, 'max': 2, 'step': 0.01})}, 'optional': {'color1_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'color2_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'draw' + CATEGORY = icons.get('Comfyroll/Graphics/Pattern') + + def draw(self, width, height, num_triangles, color_1, color_2, center_x, center_y, bbox_factor, rotation=0, color1_hex='#000000', color2_hex='#000000'): + if color_1 == 'custom': + color_1 = color1_hex + else: + color_1 = color_1 + if color_2 == 'custom': + color_2 = color2_hex + else: + color_2 = color_2 + (fig, ax) = plt.subplots() + x = width / 100 + y = height / 100 + (fig, ax) = plt.subplots(figsize=(x, y)) + plt.xlim(-x / 2, x / 2) + plt.ylim(-y / 2, y / 2) + plt.axis('off') + plt.tight_layout(pad=0, w_pad=0, h_pad=0) + plt.autoscale(False) + box_width = bbox_factor * x + box_height = bbox_factor * y + colors = [color_1, color_2] + tri = num_triangles + for i in range(tri): + x1 = center_x / 100 + y1 = center_y / 100 + x2_unrotated = box_width / 2 * np.cos(np.radians(i * 360 / tri)) + y2_unrotated = box_height / 2 * np.sin(np.radians(i * 360 / tri)) + x3_unrotated = box_width / 2 * np.cos(np.radians((i + 1) * 360 / tri)) + y3_unrotated = box_height / 2 * np.sin(np.radians((i + 1) * 360 / tri)) + x2 = x2_unrotated * np.cos(np.radians(rotation)) - y2_unrotated * np.sin(np.radians(rotation)) + y2 = x2_unrotated * np.sin(np.radians(rotation)) + y2_unrotated * np.cos(np.radians(rotation)) + x3 = x3_unrotated * np.cos(np.radians(rotation)) - y3_unrotated * np.sin(np.radians(rotation)) + y3 = x3_unrotated * np.sin(np.radians(rotation)) + y3_unrotated * np.cos(np.radians(rotation)) + ax.fill([x1, x2, x3, x1], [y1, y2, y3, y1], color=colors[i % 2]) + img_buf = io.BytesIO() + plt.savefig(img_buf, format='png') + img = Image.open(img_buf) + image_out = pil2tensor(img.convert('RGB')) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pattern-Nodes#cr-starburst-colors' + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Starburst Lines.md b/docs/CR Starburst Lines.md new file mode 100644 index 0000000..eee25b6 --- /dev/null +++ b/docs/CR Starburst Lines.md @@ -0,0 +1,117 @@ +# Documentation +- Class name: CR_StarburstLines +- Category: Comfyroll/Graphics/Pattern +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_StarburstLines节点旨在生成一个视觉上吸引人的星暴图案,由从中心点均匀分布的线组成。它允许自定义各种参数,如线条数量、线长和颜色,以创建一个独特且对称的设计。 + +# Input types +## Required +- width + - 宽度参数决定了生成图像的宽度。它对于设置星暴图案的整体尺寸并确保其适应所需的画布大小至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置图像的高度,与宽度一起确定星暴图案的完整画布大小。 + - Comfy dtype: INT + - Python dtype: int +- num_lines + - 线条数量决定了将形成星暴的线条数量,影响最终图案的复杂性和视觉对称性。 + - Comfy dtype: INT + - Python dtype: int +- line_length + - 线条长度指定了每条线从中心延伸的长度,有助于星暴的整体视觉冲击力和径向分布。 + - Comfy dtype: FLOAT + - Python dtype: float +- line_width + - 线条宽度参数控制星暴中每条线的粗细,影响图案外观的显著性和细节。 + - Comfy dtype: INT + - Python dtype: int +- line_color + - 线条颜色定义了星暴中线条的颜色,允许在设计中进行创意表达和视觉对比。 + - Comfy dtype: COLORS + - Python dtype: str +- background_color + - 背景颜色设置了星暴背后画布的颜色,提供了一个补充图案并增强其可见性的背景。 + - Comfy dtype: COLORS + - Python dtype: str +- center_x + - 中心x指定了星暴线条发出的中心点的x坐标,影响图案在画布上的对齐。 + - Comfy dtype: INT + - Python dtype: int +- center_y + - 中心y决定了星暴中心的y坐标,影响图案的垂直位置。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- rotation + - 旋转允许通过指定的度数调整星暴图案的方向,提供对图案方向的控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- line_color_hex + - 线条颜色十六进制提供了自定义线条颜色的十六进制颜色代码,使得星暴线条的颜色选择更加精确。 + - Comfy dtype: STRING + - Python dtype: str +- bg_color_hex + - 背景颜色十六进制提供了自定义背景颜色的十六进制颜色代码,允许个性化画布背景。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - IMAGE输出包含渲染后的星暴图案作为图像文件,可供进一步使用或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help输出提供了一个链接到文档的链接,以获取有关使用CR_StarburstLines节点的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_StarburstLines: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'num_lines': ('INT', {'default': 6, 'min': 1, 'max': 500}), 'line_length': ('FLOAT', {'default': 5, 'min': 0, 'max': 100, 'step': 0.1}), 'line_width': ('INT', {'default': 5, 'min': 1, 'max': 512}), 'line_color': (COLORS,), 'background_color': (COLORS,), 'center_x': ('INT', {'default': 0, 'min': 0, 'max': 1024}), 'center_y': ('INT', {'default': 0, 'min': 0, 'max': 1024}), 'rotation': ('FLOAT', {'default': 0, 'min': 0, 'max': 720})}, 'optional': {'line_color_hex': ('STRING', {'multiline': False, 'default': '#000000'}), 'bg_color_hex': ('STRING', {'multiline': False, 'default': '#000000'})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'draw' + CATEGORY = icons.get('Comfyroll/Graphics/Pattern') + + def draw(self, width, height, num_lines, line_length, line_width, line_color, background_color, center_x, center_y, rotation=0, line_color_hex='#000000', bg_color_hex='#000000'): + if line_color == 'custom': + line_color = line_color_hex + else: + line_color = line_color + if background_color == 'custom': + bgc = bg_color_hex + else: + bgc = background_color + angle = 360 / num_lines + (fig, ax) = plt.subplots(figsize=(width / 100, height / 100)) + plt.xlim(-width / 100, width / 100) + plt.ylim(-height / 100, height / 100) + plt.axis('off') + plt.tight_layout(pad=0, w_pad=0, h_pad=0) + plt.autoscale(False) + center_x = center_x / 100 + center_y = center_y / 100 + for i in range(num_lines): + x_unrotated = center_x + line_length * np.cos(np.radians(i * angle)) + y_unrotated = center_y + line_length * np.sin(np.radians(i * angle)) + x = center_x + x_unrotated * np.cos(np.radians(rotation)) - y_unrotated * np.sin(np.radians(rotation)) + y = center_y + x_unrotated * np.sin(np.radians(rotation)) + y_unrotated * np.cos(np.radians(rotation)) + fig.patch.set_facecolor(bgc) + ax.plot([center_x, x], [center_y, y], color=line_color, linewidth=line_width) + img_buf = io.BytesIO() + plt.savefig(img_buf, format='png') + img = Image.open(img_buf) + image_out = pil2tensor(img.convert('RGB')) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pattern-Nodes#cr-starburst-lines' + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR String To Boolean.md b/docs/CR String To Boolean.md new file mode 100644 index 0000000..f382fbd --- /dev/null +++ b/docs/CR String To Boolean.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: CR_StringToBoolean +- Category: Comfyroll/Utils/Conversion +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_StringToBoolean 节点旨在将布尔值的字符串表示转换为相应的布尔数据类型。它在数据预处理中扮演着关键角色,通过确保工作流程中布尔信息的准确性,促进了文本输入与基于布尔的决策过程的无缝集成。 + +# Input types +## Required +- text + - ‘text’参数对于节点的操作至关重要,因为它表示需要转换为布尔值的字符串。正确输入对于节点有效运行和产生准确的布尔输出至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- BOOLEAN + - ‘BOOLEAN’输出提供了从输入文本派生的转换后的布尔值。它很重要,因为它直接影响依赖工作流程中布尔逻辑的后续操作。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- show_help + - ‘show_help’输出提供了指向节点文档页面的URL链接,这对于寻求如何有效使用节点的额外指导或信息的用户来说可能很有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_StringToBoolean: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {'multiline': False, 'default': '', 'forceInput': True})}} + RETURN_TYPES = ('BOOLEAN', 'STRING') + RETURN_NAMES = ('BOOLEAN', 'show_help') + FUNCTION = 'convert' + CATEGORY = icons.get('Comfyroll/Utils/Conversion') + + def convert(self, text): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Conversion-Nodes#cr-string-to-boolean' + if text == 'True' or text == 'true': + boolean_out = True + if text == 'False' or text == 'false': + boolean_out = False + else: + pass + return (boolean_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR String To Combo.md b/docs/CR String To Combo.md new file mode 100644 index 0000000..56171ac --- /dev/null +++ b/docs/CR String To Combo.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: CR_StringToCombo +- Category: Comfyroll/Utils/Conversion +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_StringToCombo 节点旨在将文本字符串转换为值的列表,提供了一种更有效地处理和操作文本数据的方法。它在数据转换过程中扮演着关键角色,特别是在处理逗号分隔值时。 + +# Input types +## Required +- text + - ‘text’参数对于节点的操作至关重要,因为它是待转换的输入文本。它的重要性在于确定输出列表的内容和结构,使其成为转换过程的基本部分。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- any + - ‘any’输出代表从输入文本派生出的转换后的值列表。它很重要,因为它是节点转换功能的主要结果,包含了转换后的数据以供进一步使用。 + - Comfy dtype: STRING + - Python dtype: List[str] +- show_help + - ‘show_help’输出提供了指向节点文档页面的URL链接,为用户提供了直接参考,以便有效使用该节点的进一步信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_StringToCombo: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {'multiline': False, 'default': '', 'forceInput': True})}} + RETURN_TYPES = (any, 'STRING') + RETURN_NAMES = ('any', 'show_help') + FUNCTION = 'convert' + CATEGORY = icons.get('Comfyroll/Utils/Conversion') + + def convert(self, text): + text_list = list() + if text != '': + values = text.split(',') + text_list = values[0] + print(text_list) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Conversion-Nodes#cr-string-to-combo' + return (text_list, show_help) +``` \ No newline at end of file diff --git a/docs/CR String To Number.md b/docs/CR String To Number.md new file mode 100644 index 0000000..511e82f --- /dev/null +++ b/docs/CR String To Number.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: CR_StringToNumber +- Category: Comfyroll/Utils/Conversion +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_StringToNumber节点旨在将给定的字符串转换为数字格式,可以是整数或浮点数。它通过提供舍入选项来处理数字字符串,从而确保输出满足特定要求,提供了灵活性。 + +# Input types +## Required +- text + - ‘text’参数是需要转换为数字的字符串。它是节点操作的基本输入,因为它直接影响转换过程和最终的数字结果。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- round_integer + - ‘round_integer’参数决定了如果需要,字符串如何四舍五入为整数。它可以设置为‘round’进行标准四舍五入,‘round down’始终向下取整,或‘round up’始终向上取整,影响整数输出的精度和准确性。 + - Comfy dtype: COMBO['round', 'round down', 'round up'] + - Python dtype: str + +# Output types +- INT + - ‘INT’输出代表根据指定的舍入方法转换为整数的字符串。对于需要整数数值的应用程序来说,它是重要的。 + - Comfy dtype: INT + - Python dtype: int +- FLOAT + - ‘FLOAT’输出是转换为浮点数的字符串。它保留了原始字符串的小数精度,对于需要精确数值的应用程序非常有用。 + - Comfy dtype: FLOAT + - Python dtype: float +- show_help + - ‘show_help’输出提供了一个URL链接到文档以获得进一步的帮助。对于寻求如何使用节点或解决问题的用户的来说,它特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_StringToNumber: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': False, 'default': 'text', 'forceInput': True}), 'round_integer': (['round', 'round down', 'round up'],)}} + RETURN_TYPES = ('INT', 'FLOAT', 'STRING') + RETURN_NAMES = ('INT', 'FLOAT', 'show_help') + FUNCTION = 'convert' + CATEGORY = icons.get('Comfyroll/Utils/Conversion') + + def convert(self, text, round_integer): + if text.startswith('-') and text[1:].replace('.', '', 1).isdigit(): + float_out = -float(text[1:]) + elif text.replace('.', '', 1).isdigit(): + float_out = float(text) + else: + print(f'[Error] CR String To Number. Not a number.') + return {} + if round_integer == 'round up': + if text.startswith('-'): + int_out = int(float_out) + else: + int_out = int(float_out) + 1 + elif round_integer == 'round down': + if text.startswith('-'): + int_out = int(float_out) - 1 + else: + int_out = int(float_out) + else: + int_out = round(float_out) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Conversion-Nodes#cr-string-to-number' + return (int_out, float_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Style Bars.md b/docs/CR Style Bars.md new file mode 100644 index 0000000..9a7bf62 --- /dev/null +++ b/docs/CR Style Bars.md @@ -0,0 +1,97 @@ +# Documentation +- Class name: CR_StyleBars +- Category: Comfyroll/Graphics/Pattern +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_StyleBars 是一个用于生成条形视觉图案的节点,这些图案可以用于各种图形应用。它提供了一种创建条形样式和方向范围的方法,通过模式、宽度、高度、条形样式和频率等参数提供定制化。该节点的功能主要集中在创建一个风格化的图像输出,可以用于图案设计或作为其他上下文中的视觉辅助工具。 + +# Input types +## Required +- mode + - 模式参数决定了节点将生成的视觉图案类型。它可以设置为'color bars'(彩色条)、'sin wave'(正弦波)或'gradient bars'(渐变条),每种都产生不同的视觉效果。这个参数至关重要,因为它决定了输出图像的基本外观。 + - Comfy dtype: COMBO['color bars', 'sin wave', 'gradient bars'] + - Python dtype: str +- width + - 宽度参数指定生成图像的宽度,以像素为单位。它是节点功能的一个重要方面,因为它直接影响输出图像的尺寸,影响其视觉呈现。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置生成图像的高度,以像素为单位。像宽度一样,它是图像尺寸的关键决定因素,在最终图案的显示方式中起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- bar_style + - 条形样式参数定义了应用于生成图像中条形的颜色映射。它影响条形的视觉美感,允许表示各种风格。 + - Comfy dtype: STYLES + - Python dtype: str +- orientation + - 方向参数决定生成图像中的条形是垂直排列还是水平排列。这个选择影响图像中图案的布局和流向。 + - Comfy dtype: COMBO['vertical', 'horizontal'] + - Python dtype: str +- bar_frequency + - 条形频率参数控制生成图像中条形出现的频率。它是决定条形密度和间距的重要因素,有助于形成整体视觉纹理。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - 图像输出提供了作为图像的生成图案。它是节点操作的主要结果,对于图案在图形设计或其他应用中的后续使用至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个 URL 链接到文档,以获得进一步的帮助或指导如何有效地使用该节点。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_StyleBars: + + @classmethod + def INPUT_TYPES(s): + modes = ['color bars', 'sin wave', 'gradient bars'] + return {'required': {'mode': (modes,), 'width': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'height': ('INT', {'default': 512, 'min': 64, 'max': 4096}), 'bar_style': (STYLES,), 'orientation': (['vertical', 'horizontal'],), 'bar_frequency': ('INT', {'default': 5, 'min': 1, 'max': 200, 'step': 1})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'draw' + CATEGORY = icons.get('Comfyroll/Graphics/Pattern') + + def draw(self, mode, width, height, bar_style, orientation, bar_frequency): + if orientation == 'vertical': + x = np.linspace(0, 1, width) + y = np.zeros((height, width)) + elif orientation == 'horizontal': + x = np.zeros((height, width)) + y = np.linspace(0, 1, height) + (X, Y) = np.meshgrid(x, y) + if mode == 'color bars': + bar_width = 1 / bar_frequency + if orientation == 'vertical': + colors = X // bar_width % 2 + elif orientation == 'horizontal': + colors = Y // bar_width % 2 + elif mode == 'sin wave': + if orientation == 'vertical': + colors = np.sin(2 * np.pi * bar_frequency * X) + elif orientation == 'horizontal': + colors = np.sin(2 * np.pi * bar_frequency * Y) + elif mode == 'gradient bars': + if orientation == 'vertical': + colors = X * bar_frequency * 2 % 2 + elif orientation == 'horizontal': + colors = Y * bar_frequency * 2 % 2 + (fig, ax) = plt.subplots(figsize=(width / 100, height / 100)) + ax.imshow(colors, cmap=bar_style, aspect='auto') + plt.axis('off') + plt.tight_layout(pad=0, w_pad=0, h_pad=0) + plt.autoscale(tight=True) + img_buf = io.BytesIO() + plt.savefig(img_buf, format='png') + img = Image.open(img_buf) + image_out = pil2tensor(img.convert('RGB')) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Pattern-Nodes#cr-style-bars' + return (image_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Switch Model and CLIP.md b/docs/CR Switch Model and CLIP.md new file mode 100644 index 0000000..e5b342c --- /dev/null +++ b/docs/CR Switch Model and CLIP.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: CR_ModelAndCLIPInputSwitch +- Category: Comfyroll/Utils/Logic +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ModelAndCLIPInputSwitch 是一个用于基于二进制输入选择两组模型和CLIP输入的节点。它作为一个决策节点,允许用户在两种不同的模型及其对应的CLIP表示之间进行选择。在需要条件逻辑来确定在后续处理步骤中使用哪个模型和CLIP的场景中,该节点的功能至关重要。 + +# Input types +## Required +- Input + - 'Input' 参数是一个关键的二进制选择器,它决定了节点将使用哪组模型和CLIP输入。它直接影响节点的决策过程,根据其值启用基于条件的输入路由。 + - Comfy dtype: INT + - Python dtype: int +- model1 + - 'model1' 参数代表当 'Input' 参数设置为 1 时使用的第一种模型输入。它在节点的操作中扮演着重要角色,因为它定义了满足第一个条件时要处理的模型。 + - Comfy dtype: MODEL + - Python dtype: Any +- clip1 + - 'clip1' 参数对应于与第一种模型相关联的CLIP输入。它是节点执行的关键,因为它提供了当选择第一种模型时所需的CLIP表示。 + - Comfy dtype: CLIP + - Python dtype: Any +- model2 + - 'model2' 参数表示当 'Input' 参数设置为 2 时使用第二种模型输入。它对节点的功能至关重要,因为它决定了在满足第二个条件时需要处理的模型。 + - Comfy dtype: MODEL + - Python dtype: Any +- clip2 + - 'clip2' 参数是与第二种模型配对的CLIP输入。它是节点功能不可或缺的一部分,因为它提供了当选择第二种模型时所需的CLIP表示。 + - Comfy dtype: CLIP + - Python dtype: Any + +# Output types +- MODEL + - 'MODEL' 输出根据 'Input' 参数提供所选模型。它是节点输出的关键组成部分,确保适当的模型被转发以供进一步处理。 + - Comfy dtype: MODEL + - Python dtype: Any +- CLIP + - 'CLIP' 输出提供与所选模型相对应的CLIP表示。它在确保节点输出全面,包括模型及其相关联的CLIP方面发挥着重要作用。 + - Comfy dtype: CLIP + - Python dtype: Any +- show_help + - 'show_help' 输出提供了指向节点文档页面的URL链接,使用户能够轻松访问有关如何有效使用节点的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ModelAndCLIPInputSwitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': ('INT', {'default': 1, 'min': 1, 'max': 2}), 'model1': ('MODEL',), 'clip1': ('CLIP',), 'model2': ('MODEL',), 'clip2': ('CLIP',)}} + RETURN_TYPES = ('MODEL', 'CLIP', 'STRING') + RETURN_NAMES = ('MODEL', 'CLIP', 'show_help') + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Utils/Logic') + + def switch(self, Input, clip1, clip2, model1, model2): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Logic-Nodes#cr-switch-model-and-clip' + if Input == 1: + return (model1, clip1, show_help) + else: + return (model2, clip2, show_help) +``` \ No newline at end of file diff --git a/docs/CR Text Blacklist.md b/docs/CR Text Blacklist.md new file mode 100644 index 0000000..6e97b67 --- /dev/null +++ b/docs/CR Text Blacklist.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: CR_TextBlacklist +- Category: Comfyroll/Utils/Text +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_TextBlacklist 是一个文本处理工具节点,用于通过替换指定的黑名单词汇来净化文本内容,使其符合内容规范或个人偏好。 + +# Input types +## Required +- text + - 参数 'text' 是节点要处理的输入文本。它至关重要,因为它是将被扫描以查找黑名单词汇并可能被修改的内容。 + - Comfy dtype: STRING + - Python dtype: str +- blacklist_words + - 参数 'blacklist_words' 包含输入文本中需要被替换的词汇。参数中的每行代表一个要加入黑名单的单独词汇。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- replacement_text + - 参数 'replacement_text' 指定了将用于替换输入中发现的任何黑名单词汇的文本。它提供了一种自定义输出文本以满足特定需求的方式。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- STRING + - CR_TextBlacklist 节点的输出是已修改的文本,其中黑名单词汇已被指定替换。它代表了文本处理操作的最终结果。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - 参数 'show_help' 提供了一个文档的 URL 链接,以获取关于节点使用方面的进一步帮助或信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_TextBlacklist: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {'multiline': True, 'default': '', 'forceInput': True}), 'blacklist_words': ('STRING', {'multiline': True, 'default': ''})}, 'optional': {'replacement_text': ('STRING', {'multiline': False, 'default': ''})}} + RETURN_TYPES = (any_type, 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + FUNCTION = 'replace_text' + CATEGORY = icons.get('Comfyroll/Utils/Text') + + def replace_text(self, text, blacklist_words, replacement_text=''): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-text-blacklist' + text_out = text + for line in blacklist_words.split('\n'): + if line.strip(): + text_out = text_out.replace(line.strip(), replacement_text) + return (text_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Text Concatenate.md b/docs/CR Text Concatenate.md new file mode 100644 index 0000000..d9a291f --- /dev/null +++ b/docs/CR Text Concatenate.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: CR_TextConcatenate +- Category: Comfyroll/Utils/Text +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_TextConcatenate节点旨在将两个独立的文本字符串合并为一个单一的字符串。它通过在两个输入文本之间插入指定的分隔符来实现这一点,有效地将它们合并为一个连贯的序列。这个节点在从多个来源创建统一的文本块时特别有用,这在各种文本处理任务中可以发挥关键作用。 + +# Input types +## Required +- text1 + - 参数'text1'表示要连接的第一个文本字符串。它在确定最终输出的初始内容中起着关键作用。节点的执行直接受到此参数的内容和长度的影响。 + - Comfy dtype: STRING + - Python dtype: str +- text2 + - 参数'text2'是将与'text1'连接的第二个文本字符串。它在形成最终输出时至关重要,因为它提供了文本序列的后续部分。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- separator + - 参数'separator'定义了将被插入'text1'和'text2'之间的字符串。它在控制连接文本的格式方面很重要,允许用户根据需要自定义空格和分隔符。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- STRING + - 输出'STRING'是使用提供的'separator'连接'text1'和'text2'的结果。它代表了组合后的文本,是节点功能的主要输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_TextConcatenate: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'text1': ('STRING', {'multiline': False, 'default': '', 'forceInput': True}), 'text2': ('STRING', {'multiline': False, 'default': '', 'forceInput': True}), 'separator': ('STRING', {'multiline': False, 'default': ''})}} + RETURN_TYPES = (any_type, 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + FUNCTION = 'concat_text' + CATEGORY = icons.get('Comfyroll/Utils/Text') + + def concat_text(self, text1='', text2='', separator=''): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-save-text-to-file' + return (text1 + separator + text2,) +``` \ No newline at end of file diff --git a/docs/CR Text Cycler.md b/docs/CR Text Cycler.md new file mode 100644 index 0000000..c5a0224 --- /dev/null +++ b/docs/CR Text Cycler.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: CR_TextCycler +- Category: Comfyroll/List +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_TextCycler 节点旨在在给定的循环结构内复制文本行指定的次数。它用于自动化文本复制过程,以提高文本处理工作流程的效率。 + +# Input types +## Required +- text + - 'text' 参数是需要循环的输入文本。它可以包含多行,对于节点的操作至关重要,因为它决定了将被重复的内容。 + - Comfy dtype: STRING + - Python dtype: str +- repeats + - 'repeats' 参数指示每行文本将被复制的次数。它是一个关键元素,直接影响输出文本的数量。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- loops + - 'loops' 参数指定整个文本块将通过其重复次数循环的次数。它为文本处理增加了额外的重复层。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- show_text + - 'show_text' 输出在所有重复和循环处理完成后提供最终的循环文本。它代表了节点文本操作能力的结果。 + - Comfy dtype: STRING + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_TextCycler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True, 'default': ''}), 'repeats': ('INT', {'default': 1, 'min': 1, 'max': 99999}), 'loops': ('INT', {'default': 1, 'min': 1, 'max': 99999})}} + RETURN_TYPES = (any_type, 'STRING') + RETURN_NAMES = ('STRING', 'show_text') + OUTPUT_IS_LIST = (True, False) + FUNCTION = 'cycle' + CATEGORY = icons.get('Comfyroll/List') + + def cycle(self, text, repeats, loops=1): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-text-cycler' + lines = text.split('\n') + list_out = [] + for i in range(loops): + for text_item in lines: + for _ in range(repeats): + list_out.append(text_item) + return (list_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Text Input Switch (4 way).md b/docs/CR Text Input Switch (4 way).md new file mode 100644 index 0000000..a6f9b6c --- /dev/null +++ b/docs/CR Text Input Switch (4 way).md @@ -0,0 +1,71 @@ +# Documentation +- Class name: CR_TextInputSwitch4way +- Category: Logic +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_TextInputSwitch4way 是一个实用工具节点,旨在根据输入选择管理条件性文本输出。它允许从四个提供的文本字符串中选择一个,从而在工作流中促进基于文本的信息流分支。节点通过评估 'Input' 参数来确定要输出的文本字符串,从而实现动态内容展示。 + +# Input types +## Required +- Input + - 'Input' 参数至关重要,因为它决定了四个文本字符串中哪一个将被选择用于输出。它作为节点内的决策因素,根据其整数值指导文本信息的流向。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- text1 + - 'text1' 参数是节点可以使用的可选文本输入之一。它代表当 'Input' 设置为 1 时输出的文本字符串,允许根据用户定义的标准提供定制内容。 + - Comfy dtype: STRING + - Python dtype: str +- text2 + - 'text2' 参数是节点的另一个可选文本输入。当 'Input' 设置为 2 时使用,确保节点可以作为条件输出的一部分提供不同的文本字符串。 + - Comfy dtype: STRING + - Python dtype: str +- text3 + - 'text3' 参数作为节点的另一个可选文本输入。当 'Input' 设置为 3 时变得相关,使节点能够在工作流中展示一个不同的文本片段。 + - Comfy dtype: STRING + - Python dtype: str +- text4 + - 'text4' 参数是节点的最后一个可选文本输入。当 'Input' 设置为 4 时被选择用于输出,完成了节点内可用的条件文本选项集。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- STRING + - 节点的主要输出是一个文本字符串,由 'Input' 参数决定。它代表了基于用户选择的选定文本,提供了节点操作的清晰和直接结果。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - 次要输出 'show_help' 提供指向节点文档页面的 URL 链接。这对于寻求有关如何有效使用节点的额外信息或指导的用户非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_TextInputSwitch4way: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': ('INT', {'default': 1, 'min': 1, 'max': 4})}, 'optional': {'text1': ('STRING', {'forceInput': True}), 'text2': ('STRING', {'forceInput': True}), 'text3': ('STRING', {'forceInput': True}), 'text4': ('STRING', {'forceInput': True})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Utils/Logic') + + def switch(self, Input, text1=None, text2=None, text3=None, text4=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Logic-Nodes#cr-text-input-switch-4-way' + if Input == 1: + return (text1, show_help) + elif Input == 2: + return (text2, show_help) + elif Input == 3: + return (text3, show_help) + else: + return (text4, show_help) +``` \ No newline at end of file diff --git a/docs/CR Text Input Switch.md b/docs/CR Text Input Switch.md new file mode 100644 index 0000000..2e270c4 --- /dev/null +++ b/docs/CR Text Input Switch.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CR_TextInputSwitch +- Category: Comfyroll/Utils/Logic +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_TextInputSwitch节点旨在根据给定的整数输入促进文本输入的条件选择。它提供了一个简单的机制,用于在两个文本输入之间切换,这在需要根据输入值选择不同文本输出的场景中特别有用。 + +# Input types +## Required +- Input + - 'Input'参数至关重要,因为它决定了将选择哪个文本输入。它在整数范围内工作,其中1的输入对应于'text1',2的输入对应于'text2',从而控制节点的输出。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- text1 + - 'text1'参数是一个可选的字符串输入,它表示当'Input'参数设置为1时要返回的文本。它在定义可能的输入条件之一的输出中起着重要作用。 + - Comfy dtype: STRING + - Python dtype: str +- text2 + - 'text2'参数是另一个可选的字符串输入,它表示当'Input'参数设置为2时要返回的文本。它通过为不同的输入条件提供替代文本输出,补充了'text1'参数。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- STRING + - 节点的主要输出是一个字符串,根据'Input'参数的值,它对应于'text1'或'text2'。这个输出很重要,因为它代表了条件切换后选定的文本。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - 'show_help'输出提供了一个指向节点文档页面的URL链接,使用户可以轻松获取有关如何有效使用该节点的更多信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_TextInputSwitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': ('INT', {'default': 1, 'min': 1, 'max': 2})}, 'optional': {'text1': ('STRING', {'forceInput': True}), 'text2': ('STRING', {'forceInput': True})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Utils/Logic') + + def switch(self, Input, text1=None, text2=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Logic-Nodes#cr-text-input-switch' + if Input == 1: + return (text1, show_help) + else: + return (text2, show_help) +``` \ No newline at end of file diff --git a/docs/CR Text Length.md b/docs/CR Text Length.md new file mode 100644 index 0000000..3bbc672 --- /dev/null +++ b/docs/CR Text Length.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: CR_TextLength +- Category: Comfyroll/Utils/Text +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_TextLength节点旨在测量给定文本字符串的长度。它作为文本处理工作流程中的基本工具,提供了一种直接的方法来确定输入文本中的字符数。此节点对于需要考虑文本长度的任务至关重要,例如数据清洗或格式化。 + +# Input types +## Required +- text + - 'text'参数是将要确定长度的输入文本。这是一个关键元素,因为节点的操作完全依赖于这段文本的内容。节点处理这个输入以提供文本的长度,这对于各种文本分析或处理任务可能是必不可少的。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- INT + - 'INT'输出代表了输入文本的长度,即文本字符串内的字符数。这个输出很重要,因为它直接反映了节点主要功能的结果,允许用户利用这些信息进行进一步的处理或在其应用程序中做出决策。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - 'show_help'输出提供了一个URL链接到节点的文档页面,以供进一步帮助。这个输出对于可能需要额外指导或有关节点功能信息的用户来说很有用,提供了直接访问节点wiki页面的参考。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_TextLength: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {'multiline': False, 'default': '', 'forceInput': True})}} + RETURN_TYPES = ('INT', 'STRING') + RETURN_NAMES = ('INT', 'show_help') + FUNCTION = 'len_text' + CATEGORY = icons.get('Comfyroll/Utils/Text') + + def len_text(self, text): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-text-length' + int_out = len(text) + return (int_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Text List Simple.md b/docs/CR Text List Simple.md new file mode 100644 index 0000000..188b780 --- /dev/null +++ b/docs/CR Text List Simple.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: CR_TextListSimple +- Category: Comfyroll/Animation/Legacy +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_TextListSimple 节点旨在高效地管理和组合多个文本输入到一个单一的列表中。它适用于需要文本聚合的应用程序,例如准备批量处理的数据或生成组合文本输出。该节点以其简单性和灵活性而著称,允许轻松地将各种文本源集成到一个统一的结构中。 + +# Input types +## Optional +- text_1 + - 参数 'text_1' 是一个可选输入,允许用户向列表中贡献一行文本。它在聚合过程中起着重要作用,增强了节点处理多样化文本输入的能力。 + - Comfy dtype: STRING + - Python dtype: str +- text_2 + - 参数 'text_2' 是另一个可选输入,用于向列表中添加一行文本。在需要多个文本条目以形成全面数据集的场景中,它至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- text_3 + - 参数 'text_3' 用于在列表中包含另一行文本。它通过为用户提供更多的文本内容选项,为节点的整体功能做出贡献。 + - Comfy dtype: STRING + - Python dtype: str +- text_4 + - 参数 'text_4' 允许在列表中包含另一行文本,进一步扩展了可以由节点整合的文本输入范围。 + - Comfy dtype: STRING + - Python dtype: str +- text_5 + - 参数 'text_5' 是一个可选字段,用户可以向列表中添加另一行文本。它是节点设计的重要组成部分,以适应各种文本输入。 + - Comfy dtype: STRING + - Python dtype: str +- text_list_simple + - 参数 'text_list_simple' 是一个可选输入,允许包含一个预先存在的文本行列表。对于希望扩展或修改现有文本列表而不必从头开始的用户来说,这非常有用。 + - Comfy dtype: TEXT_LIST_SIMPLE + - Python dtype: List[str] + +# Output types +- TEXT_LIST_SIMPLE + - 输出 'TEXT_LIST_SIMPLE' 是提供给节点的所有文本输入的合并列表。它代表了节点操作的主要结果,作为准备进一步处理或分析的聚合文本数据集。 + - Comfy dtype: TEXT_LIST_SIMPLE + - Python dtype: List[str] +- show_help + - 输出 'show_help' 提供了指向节点文档页面的 URL 链接,使用户能够直接访问有关有效使用节点的额外信息和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_TextListSimple: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'text_1': ('STRING', {'multiline': False, 'default': ''}), 'text_2': ('STRING', {'multiline': False, 'default': ''}), 'text_3': ('STRING', {'multiline': False, 'default': ''}), 'text_4': ('STRING', {'multiline': False, 'default': ''}), 'text_5': ('STRING', {'multiline': False, 'default': ''}), 'text_list_simple': ('TEXT_LIST_SIMPLE',)}} + RETURN_TYPES = ('TEXT_LIST_SIMPLE', 'STRING') + RETURN_NAMES = ('TEXT_LIST_SIMPLE', 'show_help') + FUNCTION = 'text_list_simple' + CATEGORY = icons.get('Comfyroll/Animation/Legacy') + + def text_list_simple(self, text_1, text_2, text_3, text_4, text_5, text_list_simple=None): + texts = list() + if text_list_simple is not None: + texts.extend((l for l in text_list_simple)) + if text_1 != '' and text_1 != None: + (texts.append(text_1),) + if text_2 != '' and text_2 != None: + texts.append(text_2) + if text_3 != '' and text_3 != None: + texts.append(text_3) + if text_4 != '' and text_4 != None: + (texts.append(text_4),) + if text_5 != '' and text_5 != None: + (texts.append(text_5),) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-text-list-simple' + return (texts, show_help) +``` \ No newline at end of file diff --git a/docs/CR Text List To String.md b/docs/CR Text List To String.md new file mode 100644 index 0000000..eca860c --- /dev/null +++ b/docs/CR Text List To String.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: CR_TextListToString +- Category: Comfyroll/List/Utils +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_TextListToString节点旨在将字符串列表连接成一个单独的字符串,每个字符串之间用换行符分隔。它用于简化将多个文本条目转换为易于管理和显示的连贯统一格式的过程。 + +# Input types +## Required +- text_list + - 参数'text_list'是一个字符串列表,节点将这些字符串连接成一个单独的字符串。它在确定最终输出中起着关键作用,因为它直接影响结果字符串的内容和结构。 + - Comfy dtype: STRING + - Python dtype: List[str] + +# Output types +- STRING + - 'STRING'输出是由输入文本列表的所有元素通过换行符连接形成的串联字符串。它代表了节点操作的主要结果。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - 'show_help'输出提供了一个URL链接,指向节点功能的文档,以供进一步的帮助或信息。它是用户寻求额外指导的有用资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_TextListToString: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text_list': ('STRING', {'forceInput': True})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + INPUT_IS_LIST = True + FUNCTION = 'joinlist' + CATEGORY = icons.get('Comfyroll/List/Utils') + + def joinlist(self, text_list): + string_out = '\n'.join(text_list) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-text-list-to-string' + return (string_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Text List.md b/docs/CR Text List.md new file mode 100644 index 0000000..9fffdd1 --- /dev/null +++ b/docs/CR Text List.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: CR_TextList +- Category: Comfyroll/List +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_TextList节点旨在处理和操作文本数据,特别是用于从多行文本输入创建列表。它使用户能够根据起始索引和要包含的最大行数来选择文本行的子集,为Comfyroll框架内文本列表管理提供了一种简化的方法。 + +# Input types +## Required +- multiline_text + - ‘multiline_text’参数是节点的主要输入,接受可能包含多行的文本块。它在确定将生成列表的源材料中起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- start_index + - ‘start_index’参数指定了文本中列表生成应开始的位置。它对于控制最终列表中包含的文本行的起始点很重要。 + - Comfy dtype: INT + - Python dtype: int +- max_rows + - ‘max_rows’参数设置了要包含在列表中的文本行数的限制。它对于定义节点处理和返回的文本数据的范围很重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- selected_rows + - ‘selected_rows’输出包含根据输入参数选择的文本行。它代表了节点操作的核心结果,封装了处理后的文本数据。 + - Comfy dtype: STRING + - Python dtype: List[str] +- show_help + - ‘show_help’输出提供了一个URL链接到文档,以获取有关使用节点的进一步帮助或指导。对于寻求有关节点功能更多信息的用户来说,这是一个宝贵的资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_TextList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'multiline_text': ('STRING', {'multiline': True, 'default': 'text'}), 'start_index': ('INT', {'default': 0, 'min': 0, 'max': 9999}), 'max_rows': ('INT', {'default': 1000, 'min': 1, 'max': 9999})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + OUTPUT_IS_LIST = (True, False) + FUNCTION = 'make_list' + CATEGORY = icons.get('Comfyroll/List') + + def make_list(self, multiline_text, start_index, max_rows, loops): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-text-list' + lines = multiline_text.split('\n') + start_index = max(0, min(start_index, len(lines) - 1)) + end_index = min(start_index + max_rows, len(lines)) + selected_rows = lines[start_index:end_index] + return (selected_rows, show_help) +``` \ No newline at end of file diff --git a/docs/CR Text Operation.md b/docs/CR Text Operation.md new file mode 100644 index 0000000..8f85166 --- /dev/null +++ b/docs/CR Text Operation.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: CR_TextOperation +- Category: Comfyroll/Utils/Text +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_TextOperation 节点旨在执行多种文本操作。它接受一个字符串输入,并应用指定的操作,例如将文本转换为大写、小写或首字母大写。该节点还处理更复杂的操作,如反转大小写、反转文本、修剪空白和完全删除空格。它是工作流中预处理和转换文本数据的多功能工具。 + +# Input types +## Required +- text + - ‘text’参数是节点的主要输入,对于所有文本操作都是必不可少的。它决定了将根据所选操作进行操作的数据。节点的功能直接与所提供文本的内容和格式相关联。 + - Comfy dtype: STRING + - Python dtype: str +- operation + - ‘operation’参数指示要执行的特定文本操作。它是一个关键组件,因为它定义了将应用于输入文本的转换类型,影响节点的最终输出。 + - Comfy dtype: COMBO['uppercase', 'lowercase', 'capitalize', 'invert_case', 'reverse', 'trim', 'remove_spaces'] + - Python dtype: str + +# Output types +- STRING + - ‘STRING’输出参数表示文本操作的结果。它是在应用了指定操作之后转换后的文本,展示了节点的操作能力。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - ‘show_help’输出提供文档的URL链接,以供进一步帮助。对于寻求有关节点操作或故障排除的更多信息的用户来说,它特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_TextOperation: + + @classmethod + def INPUT_TYPES(cls): + operations = ['uppercase', 'lowercase', 'capitalize', 'invert_case', 'reverse', 'trim', 'remove_spaces'] + return {'required': {'text': ('STRING', {'multiline': False, 'default': '', 'forceInput': True}), 'operation': (operations,)}} + RETURN_TYPES = (any_type, 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + FUNCTION = 'text_operation' + CATEGORY = icons.get('Comfyroll/Utils/Text') + + def text_operation(self, text, operation): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-text_operation' + if operation == 'uppercase': + text_out = text.upper() + elif operation == 'lowercase': + text_out = text.lower() + elif operation == 'capitalize': + text_out = text.capitalize() + elif operation == 'invert_case': + text_out = text.swapcase() + elif operation == 'reverse': + text_out = text[::-1] + elif operation == 'trim': + text_out = text.strip() + elif operation == 'remove_spaces': + text_out = text.replace(' ', '') + else: + return 'CR Text Operation: Invalid operation.' + return (text_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Text Replace.md b/docs/CR Text Replace.md new file mode 100644 index 0000000..34c10ef --- /dev/null +++ b/docs/CR Text Replace.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: CR_TextReplace +- Category: Comfyroll/Utils/Text +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_TextReplace 是一个用于执行文本替换操作的节点。它能够高效地在给定的文本中替换指定的字符串。这个节点特别适用于预处理文本数据,其中需要在数据集中一致地更改某些模式或字符串。 + +# Input types +## Required +- text + - ‘text’参数是节点的主要输入。它是将经历替换操作的文本数据。此参数至关重要,因为它是将由节点修改的内容。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- find1 + - ‘find1’参数是一个可选的字符串,用于指定文本中要替换的第一个子字符串。它与‘replace1’一起使用,以定义第一次替换操作。 + - Comfy dtype: STRING + - Python dtype: str +- replace1 + - ‘replace1’参数是将替换文本中‘find1’子字符串的字符串。它是一个可选参数,与‘find1’一起工作。 + - Comfy dtype: STRING + - Python dtype: str +- find2 + - ‘find2’参数用于指定需要替换的第二个子字符串。它是节点内第二组查找和替换操作的一部分。 + - Comfy dtype: STRING + - Python dtype: str +- replace2 + - ‘replace2’参数定义了将替换文本中‘find2’子字符串的字符串。它是第二对替换中的一个可选组件。 + - Comfy dtype: STRING + - Python dtype: str +- find3 + - ‘find3’参数用于指定打算替换的第三个子字符串。它完成了节点内的第三组查找和替换动作。 + - Comfy dtype: STRING + - Python dtype: str +- replace3 + - ‘replace3’参数是将替换文本中‘find3’子字符串的字符串。它是可选替换参数的最后一部分。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- STRING + - ‘STRING’输出参数表示所有替换操作完成后的文本。它是节点执行的主要结果。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - ‘show_help’输出参数提供了一个链接到节点文档页面的URL,如果需要,可以提供进一步的帮助。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_TextReplace: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {'multiline': True, 'default': '', 'forceInput': True})}, 'optional': {'find1': ('STRING', {'multiline': False, 'default': ''}), 'replace1': ('STRING', {'multiline': False, 'default': ''}), 'find2': ('STRING', {'multiline': False, 'default': ''}), 'replace2': ('STRING', {'multiline': False, 'default': ''}), 'find3': ('STRING', {'multiline': False, 'default': ''}), 'replace3': ('STRING', {'multiline': False, 'default': ''})}} + RETURN_TYPES = (any_type, 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + FUNCTION = 'replace_text' + CATEGORY = icons.get('Comfyroll/Utils/Text') + + def replace_text(self, text, find1='', replace1='', find2='', replace2='', find3='', replace3=''): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-text-replace' + text = text.replace(find1, replace1) + text = text.replace(find2, replace2) + text = text.replace(find3, replace3) + return (text, show_help) +``` \ No newline at end of file diff --git a/docs/CR Text Scheduler.md b/docs/CR Text Scheduler.md new file mode 100644 index 0000000..1edf1ab --- /dev/null +++ b/docs/CR Text Scheduler.md @@ -0,0 +1,81 @@ +# Documentation +- Class name: CR_TextScheduler +- Category: Comfyroll/Animation/Schedulers +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_TextScheduler是一个用于管理和根据时间表插值文本提示的节点。它允许用户定义默认文本和时间表格式,从而能够根据预定义的关键帧列表,创建随项目或场景进展而变化的动态提示。此节点对于生成能够适应项目或场景进展的上下文感知文本至关重要。 + +# Input types +## Required +- mode + - 模式参数决定调度器是在默认文本模式下运行还是在调度模式下运行。这个选择影响节点如何处理输入以生成输出文本。 + - Comfy dtype: COMBO['Default Text', 'Schedule'] + - Python dtype: str +- current_frame + - 当前帧参数指定了需要生成文本提示的时间点或动画的当前点。对于调度器来说,根据关键帧列表确定正确的文本至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- schedule_alias + - 时间表别名参数用于在调度器中识别特定时间表。当同时管理多个时间表时,这一点尤其重要。 + - Comfy dtype: STRING + - Python dtype: str +- default_text + - 默认文本参数设置了在当前帧没有安排特定文本时使用的初始或备用文本。 + - Comfy dtype: STRING + - Python dtype: str +- schedule_format + - 时间表格式参数决定了时间表数据的结构和语法。对于正确解析和解释关键帧列表至关重要。 + - Comfy dtype: COMBO['CR', 'Deforum'] + - Python dtype: str +- schedule + - 时间表参数包含了定义调度器要遵循的时间线和相关文本提示的关键帧列表。 + - Comfy dtype: SCHEDULE + - Python dtype: List[str] + +# Output types +- text_out + - text_out参数代表了调度器根据当前帧和定义的时间表生成的文本提示的结果。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - show_help参数提供了一个指向与节点操作相关的文档或帮助页面的URL链接,为用户提供了额外的指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_TextScheduler: + + @classmethod + def INPUT_TYPES(s): + modes = ['Default Text', 'Schedule'] + return {'required': {'mode': (modes,), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'schedule_alias': ('STRING', {'default': '', 'multiline': False}), 'default_text': ('STRING', {'multiline': False, 'default': 'default text'}), 'schedule_format': (['CR', 'Deforum'],)}, 'optional': {'schedule': ('SCHEDULE',)}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('STRING', 'show_help') + FUNCTION = 'schedule' + CATEGORY = icons.get('Comfyroll/Animation/Schedulers') + + def schedule(self, mode, current_frame, schedule_alias, default_text, schedule_format, schedule=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-text-scheduler' + if mode == 'Default Text': + print(f'[Info] CR Text Scheduler: Scheduler {schedule_alias} is disabled') + text_out = default_text + return (text_out, show_help) + params = keyframe_scheduler(schedule, schedule_alias, current_frame) + if params == '': + if current_frame == 0: + print(f'[Warning] CR Text Scheduler. No frame 0 found in schedule. Starting with default value at frame 0') + text_out = (default_value,) + else: + try: + text_out = params + except ValueError: + print(f'[Warning] CR Text Scheduler. Invalid params: {params}') + return () + return (text_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Text.md b/docs/CR Text.md new file mode 100644 index 0000000..832f457 --- /dev/null +++ b/docs/CR Text.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: CR_Text +- Category: Comfyroll/Utils/Text +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_Text节点旨在处理和处理文本数据,提供有效管理多行文本输入的功能。它特别适用于需要文本操作和与外部文档交互能力的应用。 + +# Input types +## Required +- text + - ‘text’参数对于节点的操作至关重要,因为它是文本处理的主要输入。它允许多行输入,增强了节点处理各种文本格式的多功能性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- text + - ‘text’输出参数代表处理后的文本数据,可能包括节点内部函数所做的修改或增强。它是依赖文本更新状态的下游应用的关键元素。 + - Comfy dtype: STRING + - Python dtype: str +- show_help + - ‘show_help’输出提供了一个指向外部文档的URL链接,为用户提供了额外的资源来理解节点的功能和使用方式。对于寻求更多信息或帮助的用户来说,这是一个宝贵的工具。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_Text: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {'default': '', 'multiline': True})}} + RETURN_TYPES = (any_type, 'STRING') + RETURN_NAMES = ('text', 'show_help') + FUNCTION = 'text_multiline' + CATEGORY = icons.get('Comfyroll/Utils/Text') + + def text_multiline(self, text): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-text' + return (text, show_help) +``` \ No newline at end of file diff --git a/docs/CR Thumbnail Preview.md b/docs/CR Thumbnail Preview.md new file mode 100644 index 0000000..4b9c6ff --- /dev/null +++ b/docs/CR Thumbnail Preview.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: CR_ThumbnailPreview +- Category: Comfyroll/Graphics/Template +- Output node: True +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ThumbnailPreview节点旨在处理并展示一系列图像作为缩略图。它将图像缩小到指定大小,添加边框以视觉区分,并以网格格式排列它们,便于审查。该节点特别适用于需要紧凑显示多个图像的应用场景,如预览或画廊。 + +# Input types +## Required +- image + - 'image'参数是表示要处理的图像的输入张量。它是节点操作的基础,因为它是将被转换成缩略图预览的原始数据。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- rescale_factor + - 'rescale_factor'参数决定了图像的缩放比例。它对于控制缩略图的大小至关重要,允许用户根据需要调整预览大小。 + - Comfy dtype: FLOAT + - Python dtype: float +- max_columns + - 'max_columns'参数指定了缩略图网格布局中的最大列数。它影响图像的排列方式,对于整体网格的展示效果很重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- ui + - 'ui'输出参数是一个包含以网格排列的图像的字典。它很重要,因为它为显示目的提供了缩略图的最终视觉表示。 + - Comfy dtype: DICT + - Python dtype: Dict[str, List[Dict[str, Union[str, torch.Tensor]]]] +- result + - 'result'输出参数是一个包含指向帮助文档URL的元组。对于需要有关节点功能额外指导或信息的用户来说,它是有用的。 + - Comfy dtype: TUPLE + - Python dtype: Tuple[str,] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ThumbnailPreview: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'rescale_factor': ('FLOAT', {'default': 0.25, 'min': 0.1, 'max': 1.0, 'step': 0.01}), 'max_columns': ('INT', {'default': 5, 'min': 0, 'max': 256})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('show_help',) + OUTPUT_NODE = True + FUNCTION = 'thumbnail' + CATEGORY = icons.get('Comfyroll/Graphics/Template') + + def thumbnail(self, image, rescale_factor, max_columns): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Template-Nodes#cr-thumbnail-preview' + result_images = [] + outline_thickness = 1 + for img in image: + pil_img = tensor2pil(img) + (original_width, original_height) = pil_img.size + rescaled_img = apply_resize_image(tensor2pil(img), original_width, original_height, 8, 'rescale', 'false', rescale_factor, 256, 'lanczos') + outlined_img = ImageOps.expand(rescaled_img, outline_thickness, fill='black') + result_images.append(outlined_img) + combined_image = make_grid_panel(result_images, max_columns) + images_out = pil2tensor(combined_image) + results = [] + for tensor in images_out: + array = 255.0 * tensor.cpu().numpy() + image = Image.fromarray(np.clip(array, 0, 255).astype(np.uint8)) + server = PromptServer.instance + server.send_sync(BinaryEventTypes.UNENCODED_PREVIEW_IMAGE, ['PNG', image, None], server.client_id) + results.append({'source': 'websocket', 'content-type': 'image/png', 'type': 'output'}) + return {'ui': {'images': results}, 'result': (show_help,)} +``` \ No newline at end of file diff --git a/docs/CR Trigger.md b/docs/CR Trigger.md new file mode 100644 index 0000000..096efce --- /dev/null +++ b/docs/CR Trigger.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: CR_Trigger +- Category: Comfyroll/Utils/Index +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_Trigger节点旨在执行条件检查,确定给定的索引是否匹配指定的触发值。它在控制系统中的数据流和执行方面起着关键作用,允许基于索引条件进行选择性处理。 + +# Input types +## Required +- index + - ‘index’参数对于节点的操作至关重要,因为它表示正在评估的序列中的当前位置或标识符。它用于建立一个条件,当该条件满足时,节点将触发响应。 + - Comfy dtype: INT + - Python dtype: int +- trigger_value + - ‘trigger_value’参数定义了索引必须匹配的特定值,以便节点将条件视为满足。它是节点决策过程中的关键决定因素,并直接影响节点的输出。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- index + - ‘index’输出反映了节点评估的当前索引值。它很重要,因为它提供了被检查的序列中的位置的参考。 + - Comfy dtype: INT + - Python dtype: int +- trigger + - ‘trigger’输出是一个布尔值,指示索引是否与触发值匹配。对于依赖于知道条件是否满足的下游流程至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- show_help + - ‘show_help’输出提供了指向节点文档的URL链接,为用户提供了直接参考该节点使用指南和额外信息的途径。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_Trigger: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'index': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'trigger_value': ('INT', {'default': 1, 'min': 0, 'max': 10000})}} + RETURN_TYPES = ('INT', 'BOOLEAN', 'STRING') + RETURN_NAMES = ('index', 'trigger', 'show_help') + FUNCTION = 'trigger' + CATEGORY = icons.get('Comfyroll/Utils/Index') + + def trigger(self, index, trigger_value): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Index-Nodes#cr-trigger' + return (index, index == trigger_value, show_help) +``` \ No newline at end of file diff --git a/docs/CR Upscale Image.md b/docs/CR Upscale Image.md new file mode 100644 index 0000000..5c981ac --- /dev/null +++ b/docs/CR Upscale Image.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: CR_UpscaleImage +- Category: Comfyroll/Upscale +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_UpscaleImage 是一个旨在使用选定的放大模型提高输入图像分辨率的节点。它提供了一系列参数来控制缩放过程,确保输出的高质量图像满足用户对图像分辨率和细节的要求。 + +# Input types +## Required +- image + - 输入图像是 CR_UpscaleImage 节点所需的主要数据。它是将被处理并放大到更高分辨率的源材料。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- upscale_model + - 放大模型参数决定了将使用哪个预训练模型来放大图像。这个选择显著影响放大输出的质量和风格。 + - Comfy dtype: COMBO[folder_paths.get_filename_list('upscale_models')] + - Python dtype: str +- mode + - 模式参数决定图像将被重新缩放还是调整大小。这个决定影响缩放技术以及图像的最终尺寸。 + - Comfy dtype: COMBO[['rescale', 'resize']] + - Python dtype: str +## Optional +- rescale_factor + - 重新缩放因子是应用于图像原始尺寸的乘数,以确定新的大小。这是控制放大程度的关键参数。 + - Comfy dtype: FLOAT + - Python dtype: float +- resize_width + - 调整大小宽度参数指定了调整大小后图像的新宽度。当模式设置为'resize'时,这一点尤其重要。 + - Comfy dtype: INT + - Python dtype: int +- resampling_method + - 重新采样方法在图像处理期间使用,以确定图像插值的算法。它影响放大图像的平滑度和清晰度。 + - Comfy dtype: COMBO[['lanczos', 'nearest', 'bilinear', 'bicubic']] + - Python dtype: str +- supersample + - 超采样参数指示在调整大小之前是否应该首先对图像进行过采样。这可以提高最终图像的质量。 + - Comfy dtype: COMBO[['true', 'false']] + - Python dtype: str +- rounding_modulus + - 在放大过程中,舍入模数用于调整图像的尺寸,以确保它们可以被特定数字整除,通常可以增强最终结果与某些显示标准的兼容性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - 放大后的图像是 CR_UpscaleImage 节点的主要输出。它代表了根据指定参数处理和放大后的输入图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - show_help 输出提供了一个 URL 链接到文档,以获取有关节点操作的进一步帮助或信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CR_UpscaleImage: + + @classmethod + def INPUT_TYPES(s): + resampling_methods = ['lanczos', 'nearest', 'bilinear', 'bicubic'] + return {'required': {'image': ('IMAGE',), 'upscale_model': (folder_paths.get_filename_list('upscale_models'),), 'mode': (['rescale', 'resize'],), 'rescale_factor': ('FLOAT', {'default': 2, 'min': 0.01, 'max': 16.0, 'step': 0.01}), 'resize_width': ('INT', {'default': 1024, 'min': 1, 'max': 48000, 'step': 1}), 'resampling_method': (resampling_methods,), 'supersample': (['true', 'false'],), 'rounding_modulus': ('INT', {'default': 8, 'min': 8, 'max': 1024, 'step': 8})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'upscale' + CATEGORY = icons.get('Comfyroll/Upscale') + + def upscale(self, image, upscale_model, rounding_modulus=8, loops=1, mode='rescale', supersample='true', resampling_method='lanczos', rescale_factor=2, resize_width=1024): + up_model = load_model(upscale_model) + up_image = upscale_with_model(up_model, image) + for img in image: + pil_img = tensor2pil(img) + (original_width, original_height) = pil_img.size + for img in up_image: + pil_img = tensor2pil(img) + (upscaled_width, upscaled_height) = pil_img.size + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Upscale-Nodes#cr-upscale-image' + if upscaled_width == original_width and rescale_factor == 1: + return (up_image, show_help) + scaled_images = [] + for img in up_image: + scaled_images.append(pil2tensor(apply_resize_image(tensor2pil(img), original_width, original_height, rounding_modulus, mode, supersample, rescale_factor, resize_width, resampling_method))) + images_out = torch.cat(scaled_images, dim=0) + return (images_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR VAE Decode.md b/docs/CR VAE Decode.md new file mode 100644 index 0000000..6b38e33 --- /dev/null +++ b/docs/CR VAE Decode.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: CR_VAEDecode +- Category: Comfyroll/Essential/Core +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_VAEDecode节点旨在使用预训练的变分自编码器(VAE)将潜在表示解码成图像。它是生成模型中的基本组件,能够从压缩的潜在向量重建图像。该节点特别适用于可视化潜在空间和生成新样本,这些样本可以用于进一步分析或创意应用。 + +# Input types +## Required +- samples + - ‘samples’参数至关重要,因为它包含节点将解码成图像的潜在表示。它直接影响输出,决定了生成图像的多样性和质量。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- vae + - ‘vae’参数指定节点将用于解码潜在样本的预训练变分自编码器模型。VAE模型的选择对于节点的功能至关重要,因为它决定了解码过程的结构和能力。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +## Optional +- tiled + - ‘tiled’参数是一个可选的布尔标志,当设置为True时,指示节点以平铺方式解码样本。这对于处理更大的图像或当需要特定解码模式时可能有益。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- circular + - ‘circular’是另一个可选的布尔参数,启用时,它将循环填充模式应用于VAE模型中的卷积层。这对于保持图像特征在边界处的连续性可能很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- IMAGE + - ‘IMAGE’输出包含从输入潜在样本生成的解码图像。它代表了解码过程的主要结果,对视觉分析和进一步的图像操作具有重要意义。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - ‘show_help’输出提供了一个URL链接到文档页面,以获得有关节点操作的进一步帮助和详细信息。这对于寻求额外指导或了解节点能力的用户非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CR_VAEDecode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'samples': ('LATENT',), 'vae': ('VAE',), 'tiled': ('BOOLEAN', {'default': False}), 'circular': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('IMAGE', 'show_help') + FUNCTION = 'vae_decode' + CATEGORY = icons.get('Comfyroll/Essential/Core') + + def vae_decode(self, samples, vae, circular=False, tiled=False): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Core-Nodes#cr-vae-decode' + if circular == True: + for layer in [layer for layer in vae.first_stage_model.modules() if isinstance(layer, torch.nn.Conv2d)]: + layer.padding_mode = 'circular' + if tiled == True: + c = vae.decode_tiled(samples['samples'], tile_x=512, tile_y=512) + else: + c = vae.decode(samples['samples']) + return (c, show_help) +``` \ No newline at end of file diff --git a/docs/CR VAE Input Switch.md b/docs/CR VAE Input Switch.md new file mode 100644 index 0000000..176272a --- /dev/null +++ b/docs/CR VAE Input Switch.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CR_VAEInputSwitch +- Category: Comfyroll/Utils/Logic +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_VAEInputSwitch 是一个用于根据指定的选择输入在两个不同的变分自编码器(VAE)模型之间有条件地路由输入的节点。它通过评估 'Input' 参数并相应地引导流程来操作,从而实现两个不同VAE配置之间的无缝集成和切换。 + +# Input types +## Required +- Input + - ‘Input’ 参数在确定节点将使用哪个 VAE 模型中起着关键作用。它作为一个开关,决定了数据在可用选项之间的流动,其中‘1’对应于 VAE1,‘2’对应于 VAE2。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- VAE1 + - ‘VAE1’ 参数表示节点可以选择的第一个 VAE 模型。当‘Input’参数设置为‘1’时,它是一个可选输入,允许在工作流程中使用这个特定的模型。 + - Comfy dtype: VAE + - Python dtype: VAE model object +- VAE2 + - ‘VAE2’ 参数表示节点可以选择的第二个 VAE 模型。当‘Input’参数设置为‘2’时,它是一个可选输入,允许在这个过程中使用这个替代模型。 + - Comfy dtype: VAE + - Python dtype: VAE model object + +# Output types +- VAE + - ‘VAE’ 输出根据 ‘Input’ 参数提供所选的 VAE 模型,允许在下游节点中进行进一步的处理或分析。 + - Comfy dtype: VAE + - Python dtype: VAE model object +- show_help + - ‘show_help’ 输出提供了一个 URL 链接到文档页面,以获取有关节点功能的额外指导或信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_VAEInputSwitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'Input': ('INT', {'default': 1, 'min': 1, 'max': 2})}, 'optional': {'VAE1': ('VAE', {'forceInput': True}), 'VAE2': ('VAE', {'forceInput': True})}} + RETURN_TYPES = ('VAE', 'STRING') + RETURN_NAMES = ('VAE', 'show_help') + FUNCTION = 'switch' + CATEGORY = icons.get('Comfyroll/Utils/Logic') + + def switch(self, Input, VAE1=None, VAE2=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Logic-Nodes#cr-vae-input-switch' + if Input == 1: + return (VAE1, show_help) + else: + return (VAE2, show_help) +``` \ No newline at end of file diff --git a/docs/CR Value Cycler.md b/docs/CR Value Cycler.md new file mode 100644 index 0000000..61e7f9b --- /dev/null +++ b/docs/CR Value Cycler.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: CR_ValueCycler +- Category: Comfyroll/List +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ValueCycler 是一个节点,旨在迭代一个字符串值列表,将每个字符串转换为浮点数和整数表示。它循环遍历提供的文本值,重复指定次数的过程,并在设置的迭代次数内循环遍历列表。这个节点特别适用于处理文本格式的数值数据,使其在后续操作中更容易处理和分析。 + +# Input types +## Required +- values + - ‘values’参数是一个多行字符串,包含要处理的数值数据。它至关重要,因为它作为节点迭代和转换为数值格式的输入数据集。 + - Comfy dtype: STRING + - Python dtype: str +- repeats + - ‘repeats’参数指示节点将为列表中的每个项目重复循环处理的次数。它很重要,因为它控制数据处理的范围,并且可能会影响输出大小。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- loops + - ‘loops’参数指定循环处理将发生的总次数。它是一个可选设置,可用于进一步控制节点的操作和输出生成。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- FLOAT + - ‘FLOAT’输出提供将输入文本值转换为浮点数的列表,便于进行数值分析和处理。 + - Comfy dtype: FLOAT + - Python dtype: List[float] +- INT + - ‘INT’输出由输入文本值转换为整数组成,为数据处理提供了另一种数值格式。 + - Comfy dtype: INT + - Python dtype: List[int] +- show_text + - ‘show_text’输出是一个字符串,提供了指向节点文档的链接,帮助用户理解节点的功能和用法。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ValueCycler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'values': ('STRING', {'multiline': True, 'default': ''}), 'repeats': ('INT', {'default': 1, 'min': 1, 'max': 99999}), 'loops': ('INT', {'default': 1, 'min': 1, 'max': 99999})}} + RETURN_TYPES = ('FLOAT', 'INT', 'STRING') + RETURN_NAMES = ('FLOAT', 'INT', 'show_text') + OUTPUT_IS_LIST = (True, True, False) + FUNCTION = 'cycle' + CATEGORY = icons.get('Comfyroll/List') + + def cycle(self, values, repeats, loops=1): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-value-cycler' + lines = values.split('\n') + float_list_out = [] + int_list_out = [] + for i in range(loops): + for _ in range(repeats): + for text_item in lines: + if all((char.isdigit() or char == '.' for char in text_item.strip())): + float_list_out.append(float(text_item)) + int_list_out.append(int(float(text_item))) + return (float_list_out, int_list_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Value Scheduler.md b/docs/CR Value Scheduler.md new file mode 100644 index 0000000..c4971c8 --- /dev/null +++ b/docs/CR Value Scheduler.md @@ -0,0 +1,86 @@ +# Documentation +- Class name: CR_ValueScheduler +- Category: Animation/Schedulers +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_ValueScheduler是一个用于在动画工作流中管理值调度的节点。它允许选择默认值或根据当前帧应用计划值。该节点提供了一种灵活的方式来处理不同的值分配模式,确保根据指定的计划或默认设置正确设置动画参数。 + +# Input types +## Required +- mode + - 模式参数决定节点是否应该使用默认值或计划值。它对于定义调度程序的操作模式至关重要,并影响动画中值的分配方式。 + - Comfy dtype: COMBO['Default Value', 'Schedule'] + - Python dtype: str +- current_frame + - 当前帧参数指定动画时间轴中的当前帧。它对于节点确定从计划中应用的正确值或在当前帧没有计划值时使用默认值至关重要。 + - Comfy dtype: INT + - Python dtype: int +- default_value + - 默认值参数设置节点将在模式设置为“默认值”或当前帧没有可用的计划值时使用的值。它在确保动画具有一致的起始点或后备值方面起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- schedule_alias + - 计划别名参数用于引用动画中的特定计划。当节点以“计划”模式运行时,它很重要,因为它有助于识别应考虑哪些关键帧和参数进行值分配。 + - Comfy dtype: STRING + - Python dtype: str +- schedule_format + - 计划格式参数定义节点将解释的计划格式。它对于确保节点正确理解并处理计划数据很重要,计划数据可能在不同的格式中。 + - Comfy dtype: COMBO['CR', 'Deforum'] + - Python dtype: str +- schedule + - 计划参数为节点提供了将用于确定当前帧值的实际计划数据。当节点处于“计划”模式时,它非常重要,因为它直接影响被分配的值。 + - Comfy dtype: SCHEDULE + - Python dtype: Schedule + +# Output types +- int_out + - int_out参数表示节点输出的整数值,可以是应用计划或默认值的结果。对于需要整数值的动画参数来说,它很重要。 + - Comfy dtype: INT + - Python dtype: int +- float_out + - float_out参数表示节点输出的浮点数值,也可以是应用计划或默认值的结果。对于需要浮点精度的动画参数来说,它很关键。 + - Comfy dtype: FLOAT + - Python dtype: float +- show_help + - show_help参数提供了指向节点文档的URL链接,可用于进一步指导或了解如何有效地使用该节点。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_ValueScheduler: + + @classmethod + def INPUT_TYPES(s): + modes = ['Default Value', 'Schedule'] + return {'required': {'mode': (modes,), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'schedule_alias': ('STRING', {'default': '', 'multiline': False}), 'default_value': ('FLOAT', {'default': 1.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.01}), 'schedule_format': (['CR', 'Deforum'],)}, 'optional': {'schedule': ('SCHEDULE',)}} + RETURN_TYPES = ('INT', 'FLOAT', 'STRING') + RETURN_NAMES = ('INT', 'FLOAT', 'show_help') + FUNCTION = 'schedule' + CATEGORY = icons.get('Comfyroll/Animation/Schedulers') + + def schedule(self, mode, current_frame, schedule_alias, default_value, schedule_format, schedule=None): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-value-scheduler' + if mode == 'Default Value': + print(f'[Info] CR Value Scheduler: Scheduler {schedule_alias} is disabled') + (int_out, float_out) = (int(default_value), float(default_value)) + return (int_out, float_out, show_help) + params = keyframe_scheduler(schedule, schedule_alias, current_frame) + if params == '': + if current_frame == 0: + print(f'[Warning] CR Value Scheduler. No frame 0 found in schedule. Starting with default value at frame 0') + (int_out, float_out) = (int(default_value), float(default_value)) + else: + try: + value = float(params) + (int_out, float_out) = (int(value), float(value)) + except ValueError: + print(f'[Warning] CR Value Scheduler. Invalid params: {params}') + return () + return (int_out, float_out, show_help) +``` \ No newline at end of file diff --git a/docs/CR Value.md b/docs/CR Value.md new file mode 100644 index 0000000..497376b --- /dev/null +++ b/docs/CR Value.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: CR_Value +- Category: Comfyroll/Utils/Other +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_Value节点旨在提供一个多功能的接口,用于将输入值转换为不同的数据类型。它强调数据操作的灵活性和实用性,允许用户从单一输入中提取数值和文本表示,从而增强节点在各种工作流程中的适应性。 + +# Input types +## Required +- value + - ‘value’参数至关重要,因为它是节点转换过程的主要输入。它是派生浮点数和整数表示的来源,使其成为节点操作中的基本元素。 + - Comfy dtype: FLOAT + - Python dtype: Union[float, str] + +# Output types +- FLOAT + - ‘FLOAT’输出提供了输入值的浮点表示,这对于需要精确小数值的数值计算和分析非常有用。 + - Comfy dtype: FLOAT + - Python dtype: float +- INT + - ‘INT’输出提供了输入值的整数形式,适用于只需要整数的情况,从而简化了计算并降低了复杂性。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - ‘show_help’输出提供了指向节点文档的URL链接,对于寻求有关节点功能额外指导或信息的用户来说非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_Value: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'value': ('FLOAT', {'default': 1.0})}} + RETURN_TYPES = ('FLOAT', 'INT', 'STRING') + RETURN_NAMES = ('FLOAT', 'INT', 'show_help') + CATEGORY = icons.get('Comfyroll/Utils/Other') + FUNCTION = 'get_value' + + def get_value(self, value): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Other-Nodes#cr-value' + return (float(value), int(value), show_help) +``` \ No newline at end of file diff --git a/docs/CR Vignette Filter.md b/docs/CR Vignette Filter.md new file mode 100644 index 0000000..b293bde --- /dev/null +++ b/docs/CR Vignette Filter.md @@ -0,0 +1,128 @@ +# Documentation +- Class name: CR_VignetteFilter +- Category: Comfyroll/Graphics/Filter +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_VignetteFilter是一个用于对图像应用称为晕影的视觉效果的节点。这种效果逐渐使图像的角落变暗,从而在中心区域到边缘之间创建一个柔和的焦点过渡。它增强了视觉深度并吸引了对图像中心的注意,通常用于摄影和电影中。 + +# Input types +## Required +- image + - 要应用晕影效果的输入图像。这是节点将处理的主要数据,最终输出的质量很大程度上取决于此输入图像的特性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- vignette_shape + - 确定要应用于图像的晕影的形状。形状的选择可以显著影响最终图像的美学吸引力和传达的情感反应。 + - Comfy dtype: COMBO['circle', 'oval', 'square', 'diamond'] + - Python dtype: str +- feather_amount + - 控制晕影边缘的柔和度。较高的羽化量会使得从暗角到图像中心的过渡更加渐进,而较低的量则使得过渡更加突然。 + - Comfy dtype: INT + - Python dtype: int +- x_offset + - 允许水平调整晕影的中心。这可以改变图像中的焦点区域,创造出构图上的微妙变化。 + - Comfy dtype: INT + - Python dtype: int +- y_offset + - 允许垂直调整晕影的中心。与x_offset类似,它可以用来微调图像内的视觉焦点。 + - Comfy dtype: INT + - Python dtype: int +- zoom + - 此参数调整晕影效果的大小。较高的缩放值会增加晕影的大小,使其更加突出,而较低的值则会减少其大小。 + - Comfy dtype: FLOAT + - Python dtype: float +- reverse + - 如果设置为'yes',则反转晕影效果。不是使边缘变暗,而是使图像中心变暗,创造出对比鲜明的视觉风格。 + - Comfy dtype: COMBO['no', 'yes'] + - Python dtype: str + +# Output types +- IMAGE + - 应用了晕影效果的结果图像。这是主要的输出,反映了通过节点参数所做的创造性调整。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- MASK + - 表示晕影透明度的alpha遮罩。它可以用于进一步的图像处理或作为后期制作中的选择工具。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- show_help + - 提供文档链接,以获取有关使用节点的进一步指导。对于寻求有关节点功能和选项的更多信息的用户来说,这非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_VignetteFilter: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'vignette_shape': (['circle', 'oval', 'square', 'diamond'],), 'feather_amount': ('INT', {'default': 100, 'min': 0, 'max': 1024}), 'x_offset': ('INT', {'default': 0, 'min': -2048, 'max': 2048}), 'y_offset': ('INT', {'default': 0, 'min': -2048, 'max': 2048}), 'zoom': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.1}), 'reverse': (['no', 'yes'],)}} + RETURN_TYPES = ('IMAGE', 'MASK', 'STRING') + RETURN_NAMES = ('IMAGE', 'MASK', 'show_help') + FUNCTION = 'make_vignette' + CATEGORY = icons.get('Comfyroll/Graphics/Filter') + + def make_vignette(self, image, feather_amount, reverse, vignette_shape='circle', x_offset=0, y_offset=0, zoom=1.0): + images = [] + masks = [] + vignette_color = 'black' + for img in image: + im = tensor2pil(img) + RADIUS = feather_amount + alpha_mask = Image.new('L', im.size, 255) + draw = ImageDraw.Draw(alpha_mask) + center_x = im.size[0] // 2 + x_offset + center_y = im.size[1] // 2 + y_offset + radius = min(center_x, center_y) * zoom + size_x = (im.size[0] - RADIUS) * zoom + size_y = (im.size[1] - RADIUS) * zoom + if vignette_shape == 'circle': + if reverse == 'no': + draw.ellipse([(center_x - radius, center_y - radius), (center_x + radius, center_y + radius)], fill=0) + elif reverse == 'yes': + draw.rectangle([(0, 0), im.size], fill=0) + draw.ellipse([(center_x - radius, center_y - radius), (center_x + radius, center_y + radius)], fill=255) + else: + raise ValueError("Invalid value for reverse. Use 'yes' or 'no'.") + elif vignette_shape == 'oval': + if reverse == 'no': + draw.ellipse([(center_x - size_x / 2, center_y - size_y / 2), (center_x + size_x / 2, center_y + size_y / 2)], fill=0) + elif reverse == 'yes': + draw.rectangle([(0, 0), im.size], fill=0) + draw.ellipse([(center_x - size_x / 2, center_y - size_y / 2), (center_x + size_x / 2, center_y + size_y / 2)], fill=255) + elif vignette_shape == 'diamond': + if reverse == 'no': + size = min(im.size[0] - x_offset, im.size[1] - y_offset) * zoom + draw.polygon([(center_x, center_y - size / 2), (center_x + size / 2, center_y), (center_x, center_y + size / 2), (center_x - size / 2, center_y)], fill=0) + elif reverse == 'yes': + size = min(im.size[0] - x_offset, im.size[1] - y_offset) * zoom + draw.rectangle([(0, 0), im.size], fill=0) + draw.polygon([(center_x, center_y - size / 2), (center_x + size / 2, center_y), (center_x, center_y + size / 2), (center_x - size / 2, center_y)], fill=255) + elif vignette_shape == 'square': + if reverse == 'no': + size = min(im.size[0] - x_offset, im.size[1] - y_offset) * zoom + draw.rectangle([(center_x - size / 2, center_y - size / 2), (center_x + size / 2, center_y + size / 2)], fill=0) + elif reverse == 'yes': + size = min(im.size[0] - x_offset, im.size[1] - y_offset) * zoom + draw.rectangle([(0, 0), im.size], fill=0) + draw.rectangle([(center_x - size / 2, center_y - size / 2), (center_x + size / 2, center_y + size / 2)], fill=255) + else: + raise ValueError("Invalid value for reverse. Use 'yes' or 'no'.") + else: + raise ValueError("Invalid vignette_shape. Use 'circle', 'oval', or 'square'.") + alpha_mask = alpha_mask.filter(ImageFilter.GaussianBlur(RADIUS)) + masks.append(pil2tensor(alpha_mask).unsqueeze(0)) + vignette_img = Image.new('RGBA', im.size, vignette_color) + vignette_img.putalpha(alpha_mask) + result_img = Image.alpha_composite(im.convert('RGBA'), vignette_img) + images.append(pil2tensor(result_img.convert('RGB'))) + images = torch.cat(images, dim=0) + masks = torch.cat(masks, dim=0) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Layout-Nodes#cr-vignette-filter' + return (images, masks, show_help) +``` \ No newline at end of file diff --git a/docs/CR XY From Folder.md b/docs/CR XY From Folder.md new file mode 100644 index 0000000..a5793e5 --- /dev/null +++ b/docs/CR XY From Folder.md @@ -0,0 +1,112 @@ +# Documentation +- Class name: CR_XYFromFolder +- Category: Comfyroll/XY Grid +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_XYFromFolder 节点旨在从指定文件夹处理和组织图片到网格布局中。它通过允许用户为每个图片指定注释、设置字体大小以及控制图片之间的间距,来促进创建一个视觉上结构化的网格。这个节点特别适用于生成用于演示、目录或数据可视化等不同目的的带注释的图片网格。 + +# Input types +## Required +- image_folder + - 图片文件夹参数对于定义将组织成网格的图片来源至关重要。它决定了节点检索和处理图片的目录。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- start_index + - 开始索引是一个可选参数,它决定了选择图片过程的起始点。它允许控制哪些图片被包括在网格中,从特定位置开始。 + - Comfy dtype: INT + - Python dtype: int +- end_index + - 结束索引参数指定了选择图片的结束点。它用于定义最终网格布局中将包含的图片范围。 + - Comfy dtype: INT + - Python dtype: int +- max_columns + - 最大列数参数决定了网格中的列数。它对于定义网格的结构并确保视觉上的平衡布局至关重要。 + - Comfy dtype: INT + - Python dtype: int +- x_annotation + - x_annotation 参数用于为网格的列提供注释。它为图片的视觉表示增加了一层信息和上下文。 + - Comfy dtype: STRING + - Python dtype: str +- y_annotation + - y_annotation 参数类似于 x_annotation,但用于网格的行。它确保每一行都被正确地标记和注释。 + - Comfy dtype: STRING + - Python dtype: str +- font_size + - 字体大小参数控制注释所用文字的大小。它是节点功能的重要方面,因为它影响网格的可读性和美观性。 + - Comfy dtype: INT + - Python dtype: int +- gap + - 间隔参数定义了网格中图片之间的间距。它在整体视觉展示中发挥作用,确保图片不会过于拥挤。 + - Comfy dtype: INT + - Python dtype: int +- trigger + - 触发器参数是一个可选的开关,当被激活时,它会启动图片处理和网格创建。它提供了一种控制节点操作何时执行的方式。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- IMAGE + - IMAGE 输出提供了带有注释的最终图片网格,准备用于各种应用程序。它代表了节点处理和布局工作的成果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- trigger + - 触发器输出表明节点的操作是否根据输入的触发器执行。它作为节点激活状态的反馈机制。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- show_help + - show_help 输出提供了指向节点文档页面的 URL 链接。它为用户提供了轻松访问有关使用节点的额外信息和指导的途径。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_XYFromFolder: + + @classmethod + def INPUT_TYPES(cls) -> dict[str, t.Any]: + input_dir = folder_paths.output_directory + image_folder = [name for name in os.listdir(input_dir) if os.path.isdir(os.path.join(input_dir, name))] + return {'required': {'image_folder': (sorted(image_folder),), 'start_index': ('INT', {'default': 1, 'min': 0, 'max': 10000}), 'end_index': ('INT', {'default': 1, 'min': 1, 'max': 10000}), 'max_columns': ('INT', {'default': 1, 'min': 1, 'max': 10000}), 'x_annotation': ('STRING', {'multiline': True}), 'y_annotation': ('STRING', {'multiline': True}), 'font_size': ('INT', {'default': 50, 'min': 1}), 'gap': ('INT', {'default': 0, 'min': 0})}, 'optional': {'trigger': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('IMAGE', 'BOOLEAN', 'STRING') + RETURN_NAMES = ('IMAGE', 'trigger', 'show_help') + FUNCTION = 'load_images' + CATEGORY = icons.get('Comfyroll/XY Grid') + + def load_images(self, image_folder, start_index, end_index, max_columns, x_annotation, y_annotation, font_size, gap, trigger=False): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/XY-Grid-Nodes#cr-xy-from-folder' + if trigger == False: + return ((), False, show_help) + input_dir = folder_paths.output_directory + image_path = os.path.join(input_dir, image_folder) + file_list = sorted(os.listdir(image_path), key=lambda s: sum(((s, int(n)) for (s, n) in re.findall('(\\D+)(\\d+)', 'a%s0' % s)), ())) + sample_frames = [] + pillow_images = [] + if len(file_list) < end_index: + end_index = len(file_list) + for num in range(start_index, end_index + 1): + i = Image.open(os.path.join(image_path, file_list[num - 1])) + image = i.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + image = image.squeeze() + sample_frames.append(image) + resolved_font_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'fonts\\Roboto-Regular.ttf') + font = ImageFont.truetype(str(resolved_font_path), size=font_size) + start_x_ann = start_index % max_columns - 1 + start_y_ann = int(start_index / max_columns) + column_list = x_annotation.split(';')[start_x_ann:] + row_list = y_annotation.split(';')[start_y_ann:] + column_list = [item.strip() for item in column_list] + row_list = [item.strip() for item in row_list] + annotation = Annotation(column_texts=column_list, row_texts=row_list, font=font) + images = torch.stack(sample_frames) + pillow_images = [tensor_to_pillow(i) for i in images] + pillow_grid = create_images_grid_by_columns(images=pillow_images, gap=gap, annotation=annotation, max_columns=max_columns) + tensor_grid = pillow_to_tensor(pillow_grid) + return (tensor_grid, trigger, show_help) +``` \ No newline at end of file diff --git a/docs/CR XY Index.md b/docs/CR XY Index.md new file mode 100644 index 0000000..fafbf13 --- /dev/null +++ b/docs/CR XY Index.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: CR_XYIndex +- Category: Comfyroll/XY Grid +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_XYIndex 节点旨在根据给定的索引值计算网格结构中对应的 x 和 y 坐标。它作为将线性索引映射到二维网格空间的实用工具,对于图像处理或数据索引等各种应用至关重要。 + +# Input types +## Required +- x_columns + - 参数 'x_columns' 指定了网格中的列数。它是确定网格布局的关键元素,因此也是计算给定索引的 x 和 y 坐标的决定因素。 + - Comfy dtype: INT + - Python dtype: int +- y_rows + - 参数 'y_rows' 定义了网格中的行数。与 'x_columns' 一起,它决定了网格的整体结构,对于准确计算网格索引至关重要。 + - Comfy dtype: INT + - Python dtype: int +- index + - 参数 'index' 是需要被转换为网格坐标的线性索引。它是节点操作的核心,因为它是所有计算的起点。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- x + - 输出 'x' 表示根据提供的索引计算出的网格内的 x 坐标。它是节点功能的关键结果,指示水平位置。 + - Comfy dtype: INT + - Python dtype: int +- y + - 输出 'y' 表示根据提供的索引计算出的网格内的 y 坐标。它对于确定索引在网格结构中的垂直位置至关重要。 + - Comfy dtype: INT + - Python dtype: int +- show_help + - 输出 'show_help' 提供了一个文档的 URL 链接,以供进一步帮助。它作为用户寻求有关节点功能更多信息的有用资源。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_XYIndex: + + @classmethod + def INPUT_TYPES(s): + gradient_profiles = ['Lerp'] + return {'required': {'x_columns': ('INT', {'default': 5.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'y_rows': ('INT', {'default': 5.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'index': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('INT', 'INT', 'STRING') + RETURN_NAMES = ('x', 'y', 'show_help') + FUNCTION = 'index' + CATEGORY = icons.get('Comfyroll/XY Grid') + + def index(self, x_columns, y_rows, index): + index -= 1 + x = index % x_columns + y = int(index / x_columns) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/XY-Grid-Nodes#cr-xy-index' + return (x, y, show_help) +``` \ No newline at end of file diff --git a/docs/CR XY Interpolate.md b/docs/CR XY Interpolate.md new file mode 100644 index 0000000..fc2a38c --- /dev/null +++ b/docs/CR XY Interpolate.md @@ -0,0 +1,122 @@ +# Documentation +- Class name: CR_XYInterpolate +- Category: Comfyroll/XY Grid +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_XYInterpolate节点旨在XY网格上生成梯度。它沿X轴和Y轴计算插值,提供在指定的起点和终点之间的平滑过渡。此节点特别适用于创建复杂的渐变图案,并且能够使用自定义标签注释网格点。 + +# Input types +## Required +- x_columns + - x_columns参数定义了网格中的列数。它对于确定网格布局的水平间距和整体结构至关重要。 + - Comfy dtype: INT + - Python dtype: int +- x_start_value + - x_start_value设置X轴插值的初始值。它很重要,因为它为网格列上的梯度计算建立了起始点。 + - Comfy dtype: FLOAT + - Python dtype: float +- x_step + - x_step参数指定网格中连续X值之间的增量。它对于控制沿水平轴的变化速率至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- y_rows + - y_rows参数指定网格中的行数。它对于建立网格内的垂直结构和间距至关重要。 + - Comfy dtype: INT + - Python dtype: int +- y_start_value + - y_start_value设置Y轴插值的初始值。它是一个关键参数,用于确定网格行上的梯度计算的起始点。 + - Comfy dtype: FLOAT + - Python dtype: float +- y_step + - y_step参数确定网格中连续Y值之间的增量。它对于控制垂直梯度的进展很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- index + - index参数用于引用网格内的具体位置。它决定了计算和返回哪些插值。 + - Comfy dtype: INT + - Python dtype: int +- gradient_profile + - gradient_profile参数选择要使用的梯度配置文件类型。它影响网格上插值的执行方式。 + - Comfy dtype: COMBO['Lerp'] + - Python dtype: str +## Optional +- x_annotation_prepend + - x_annotation_prepend允许向每个X注释添加自定义前缀。这可以用来在注释中包含额外的上下文或信息。 + - Comfy dtype: STRING + - Python dtype: str +- y_annotation_prepend + - y_annotation_prepend参数允许向每个Y注释添加自定义前缀,通过额外的细节或上下文增强注释。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- X + - X输出提供指定网格位置的插值X值。它是梯度计算过程的关键结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- Y + - Y输出提供指定网格位置的插值Y值。它代表梯度插值的一个重要结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- x_annotation + - x_annotation输出返回表示网格上X值注释的字符串。它用于标记网格点并提供上下文。 + - Comfy dtype: STRING + - Python dtype: str +- y_annotation + - y_annotation输出为网格中Y值的注释生成一个字符串。它有助于识别和情境化网格的垂直点。 + - Comfy dtype: STRING + - Python dtype: str +- trigger + - trigger输出指示何时满足特定条件,例如到达最后一个网格点。它可以用来启动进一步的动作或流程。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- show_help + - show_help输出提供指向节点文档页面的URL链接。它为用户提供了直接访问更详细信息和使用节点的指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_XYInterpolate: + + @classmethod + def INPUT_TYPES(s): + gradient_profiles = ['Lerp'] + return {'required': {'x_columns': ('INT', {'default': 5.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'x_start_value': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 0.01}), 'x_step': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 0.01}), 'x_annotation_prepend': ('STRING', {'multiline': False, 'default': ''}), 'y_rows': ('INT', {'default': 5.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'y_start_value': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 0.01}), 'y_step': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 0.01}), 'y_annotation_prepend': ('STRING', {'multiline': False, 'default': ''}), 'index': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'gradient_profile': (gradient_profiles,)}} + RETURN_TYPES = ('FLOAT', 'FLOAT', 'STRING', 'STRING', 'BOOLEAN', 'STRING') + RETURN_NAMES = ('X', 'Y', 'x_annotation', 'y_annotation', 'trigger', 'show_help') + FUNCTION = 'gradient' + CATEGORY = icons.get('Comfyroll/XY Grid') + + def gradient(self, x_columns, x_start_value, x_step, x_annotation_prepend, y_rows, y_start_value, y_step, y_annotation_prepend, index, gradient_profile): + index -= 1 + trigger = False + grid_size = x_columns * y_rows + x = index % x_columns + y = int(index / x_columns) + x_float_out = round(x_start_value + x * x_step, 3) + y_float_out = round(y_start_value + y * y_step, 3) + x_ann_out = '' + y_ann_out = '' + if index + 1 == grid_size: + for i in range(0, x_columns): + x = index % x_columns + x_float_out = x_start_value + i * x_step + x_float_out = round(x_float_out, 3) + x_ann_out = x_ann_out + x_annotation_prepend + str(x_float_out) + '; ' + for j in range(0, y_rows): + y = int(index / x_columns) + y_float_out = y_start_value + j * y_step + y_float_out = round(y_float_out, 3) + y_ann_out = y_ann_out + y_annotation_prepend + str(y_float_out) + '; ' + x_ann_out = x_ann_out[:-1] + y_ann_out = y_ann_out[:-1] + print(x_ann_out, y_ann_out) + trigger = True + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/XY-Grid-Nodes#cr-xy-interpolate' + return (x_float_out, y_float_out, x_ann_out, y_ann_out, trigger, show_help) +``` \ No newline at end of file diff --git a/docs/CR XY List.md b/docs/CR XY List.md new file mode 100644 index 0000000..da3516b --- /dev/null +++ b/docs/CR XY List.md @@ -0,0 +1,114 @@ +# Documentation +- Class name: CR_XYList +- Category: Comfyroll/XY Grid +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_XYList 节点旨在对两个列表执行交叉连接操作,生成组合的网格。它能够向列表元素添加前缀和后缀字符串,增强了输出的灵活性。该节点还提供注释和触发机制,以指示网格生成的完成。 + +# Input types +## Required +- index + - 索引参数对于确定当前组合在网格中的位置至关重要。它通过决定选择输入列表中的哪些元素进行输出,影响节点的执行。 + - Comfy dtype: INT + - Python dtype: int +- list1 + - List1 是交叉连接操作的第一个输入列表。它在节点的功能中起着关键作用,通过为网格的水平元素的生成做出贡献。 + - Comfy dtype: STRING + - Python dtype: str +- list2 + - List2 是交叉连接操作的第二个输入列表,对于创建网格的垂直元素至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- x_prepend + - x_prepend 参数允许在 list1 中的每个元素前添加前缀。这可以用来自定义输出格式或为元素添加上下文。 + - Comfy dtype: STRING + - Python dtype: str +- x_append + - x_append 参数用于在 list1 中的每个元素后追加后缀,提供对输出元素的进一步自定义。 + - Comfy dtype: STRING + - Python dtype: str +- x_annotation_prepend + - x_annotation_prepend 参数用于在生成注释时为 list1 中的每个元素添加注释前缀。它增强了注释的描述性。 + - Comfy dtype: STRING + - Python dtype: str +- y_prepend + - y_prepend 参数允许在 list2 中的每个元素前添加前缀,允许自定义垂直元素的输出。 + - Comfy dtype: STRING + - Python dtype: str +- y_append + - y_append 参数用于在 list2 中的每个元素后追加后缀,提供对垂直元素最终格式的额外控制。 + - Comfy dtype: STRING + - Python dtype: str +- y_annotation_prepend + - y_annotation_prepend 参数允许在生成注释时为 list2 中的每个元素添加注释前缀,增强了注释的信息量。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- X + - X 输出代表当前索引下 list1 的水平组合元素。它是网格行的关键组成部分。 + - Comfy dtype: STRING + - Python dtype: str +- Y + - Y 输出代表相应索引下 list2 的垂直组合元素。它是网格列的关键组成部分。 + - Comfy dtype: STRING + - Python dtype: str +- x_annotation + - x_annotation 输出在网格生成完成时提供 list1 元素的注释版本,增强了结果的可解释性。 + - Comfy dtype: STRING + - Python dtype: str +- y_annotation + - y_annotation 输出在网格生成完成时提供 list2 元素的注释版本,为结果的解释增添了上下文。 + - Comfy dtype: STRING + - Python dtype: str +- trigger + - trigger 输出指示网格生成何时完成,标志着交叉连接过程的结束。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- show_help + - show_help 输出提供了一个 URL 链接到文档,以获得关于使用该节点的进一步帮助和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_XYList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'index': ('INT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'list1': ('STRING', {'multiline': True, 'default': 'x'}), 'x_prepend': ('STRING', {'multiline': False, 'default': ''}), 'x_append': ('STRING', {'multiline': False, 'default': ''}), 'x_annotation_prepend': ('STRING', {'multiline': False, 'default': ''}), 'list2': ('STRING', {'multiline': True, 'default': 'y'}), 'y_prepend': ('STRING', {'multiline': False, 'default': ''}), 'y_append': ('STRING', {'multiline': False, 'default': ''}), 'y_annotation_prepend': ('STRING', {'multiline': False, 'default': ''})}} + RETURN_TYPES = ('STRING', 'STRING', 'STRING', 'STRING', 'BOOLEAN', 'STRING') + RETURN_NAMES = ('X', 'Y', 'x_annotation', 'y_annotation', 'trigger', 'show_help') + FUNCTION = 'cross_join' + CATEGORY = icons.get('Comfyroll/XY Grid') + + def cross_join(self, list1, list2, x_prepend, x_append, x_annotation_prepend, y_prepend, y_append, y_annotation_prepend, index): + index -= 1 + trigger = False + listx = re.split(',(?=(?:[^"]*"[^"]*")*[^"]*$)', list1) + listy = re.split(',(?=(?:[^"]*"[^"]*")*[^"]*$)', list2) + listx = [item.strip() for item in listx] + listy = [item.strip() for item in listy] + lenx = len(listx) + leny = len(listy) + grid_size = lenx * leny + x = index % lenx + y = int(index / lenx) + x_out = x_prepend + listx[x] + x_append + y_out = y_prepend + listy[y] + y_append + x_ann_out = '' + y_ann_out = '' + if index + 1 == grid_size: + x_ann_out = [x_annotation_prepend + item + ';' for item in listx] + y_ann_out = [y_annotation_prepend + item + ';' for item in listy] + x_ann_out = ''.join([str(item) for item in x_ann_out]) + y_ann_out = ''.join([str(item) for item in y_ann_out]) + trigger = True + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/XY-Grid-Nodes#cr-xy-list' + return (x_out, y_out, x_ann_out, y_ann_out, trigger, show_help) +``` \ No newline at end of file diff --git a/docs/CR XY Product.md b/docs/CR XY Product.md new file mode 100644 index 0000000..390f4f3 --- /dev/null +++ b/docs/CR XY Product.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: CR_XYProduct +- Category: Comfyroll/List/Utils +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_XYProduct 节点旨在对两个字符串列表执行交叉连接操作。它接受两个多行文本输入,并生成两个列表中元素的所有可能组合,创建一个笛卡尔积。这个节点在需要探索两个数据集之间所有可能配对的场景中特别有用。 + +# Input types +## Required +- text_x + - 参数 'text_x' 是一个多行文本输入,表示要在交叉连接操作中使用的首个字符串列表。它在确定将与 'text_y' 中的元素结合的元素方面起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +- text_y + - 参数 'text_y' 是另一个多行文本输入,表示要在交叉连接操作中使用的第二个字符串列表。它与 'text_x' 一起工作,以产生笛卡尔积。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- x_values + - 输出 'x_values' 是一个字符串列表,代表交叉连接操作后第一个输入列表中的元素。它包含每个唯一组合的第一个元素。 + - Comfy dtype: STRING + - Python dtype: List[str] +- y_values + - 输出 'y_values' 是一个字符串列表,代表交叉连接操作后第二个输入列表中的元素。它包含每个唯一组合的第二个元素。 + - Comfy dtype: STRING + - Python dtype: List[str] +- show_help + - 输出 'show_help' 提供了一个 URL 链接,用于获取有关节点操作的进一步帮助或信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_XYProduct: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text_x': ('STRING', {'multiline': True}), 'text_y': ('STRING', {'multiline': True})}} + RETURN_TYPES = (any_type, any_type, 'STRING') + RETURN_NAMES = ('x_values', 'y_values', 'show_help') + OUTPUT_IS_LIST = (True, True, False) + FUNCTION = 'cross_join' + CATEGORY = icons.get('Comfyroll/List/Utils') + + def cross_join(self, text_x, text_y): + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/List-Nodes#cr-xy-product' + list1 = text_x.strip().split('\n') + list2 = text_y.strip().split('\n') + cartesian_product = list(product(list1, list2)) + (x_values, y_values) = zip(*cartesian_product) + return (list(x_values), list(y_values), show_help) +``` \ No newline at end of file diff --git a/docs/CR XY Save Grid Image.md b/docs/CR XY Save Grid Image.md new file mode 100644 index 0000000..a545d05 --- /dev/null +++ b/docs/CR XY Save Grid Image.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: CR_XYSaveGridImage +- Category: Comfyroll/XY Grid +- Output node: True +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_XYSaveGridImage是一个设计用来将网格图像保存到指定输出目录的节点。它可以处理不同的保存或预览图像模式,并支持多种文件格式。该节点确保每个保存的图像都基于前缀和一个数字计数器唯一命名,便于图像的组织和检索。 + +# Input types +## Required +- mode + - 模式参数决定节点是处于'保存'模式以永久保存图像还是'预览'模式以临时保存图像供审查。这个选择影响节点的行为和保存图像的目的地。 + - Comfy dtype: COMBO['Save', 'Preview'] + - Python dtype: str +- output_folder + - 输出文件夹参数指定了图像将被保存的输出目录内的目录。这对于组织保存的图像并确保它们存储在正确的位置至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- image + - 图像参数是节点将处理并保存的实际图像数据。它是节点操作的中心输入,因为节点的主要目的是处理这张图像的保存。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- file_format + - 文件格式参数定义了图像将被保存的格式。它支持各种格式,允许在图像的存储和使用方式上具有灵活性。 + - Comfy dtype: COMBO['webp', 'jpg', 'png', 'tif'] + - Python dtype: str +## Optional +- filename_prefix + - 文件名前缀参数提供了保存图像文件命名的基础。它与数字计数器结合使用,以确保文件名的唯一性,这对于防止文件覆盖和维护文件组织非常重要。 + - Comfy dtype: STRING + - Python dtype: str +- output_path + - 输出路径参数允许指定一个自定义路径来保存图像,覆盖默认的输出目录。它提供了对保存图像位置的额外控制。 + - Comfy dtype: STRING + - Python dtype: str +- trigger + - 触发器参数是一个布尔标志,当设置为True时,启动图像保存过程。它作为一个控制机制,以确定何时节点应该执行其主要功能。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- preview + - 预览输出提供了保存图像的结构化表示,包括其文件名和位置。这个输出对于在用户界面中显示图像以供审查非常有用。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_XYSaveGridImage: + + def __init__(self): + self.type = 'output' + + @classmethod + def INPUT_TYPES(cls): + output_dir = folder_paths.output_directory + output_folders = [name for name in os.listdir(output_dir) if os.path.isdir(os.path.join(output_dir, name))] + return {'required': {'mode': (['Save', 'Preview'],), 'output_folder': (sorted(output_folders),), 'image': ('IMAGE',), 'filename_prefix': ('STRING', {'default': 'CR'}), 'file_format': (['webp', 'jpg', 'png', 'tif'],)}, 'optional': {'output_path': ('STRING', {'default': '', 'multiline': False}), 'trigger': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = () + FUNCTION = 'save_image' + OUTPUT_NODE = True + CATEGORY = icons.get('Comfyroll/XY Grid') + + def save_image(self, mode, output_folder, image, file_format, output_path='', filename_prefix='CR', trigger=False): + if trigger == False: + return () + output_dir = folder_paths.get_output_directory() + out_folder = os.path.join(output_dir, output_folder) + if output_path != '': + if not os.path.exists(output_path): + print(f'[Warning] CR Save XY Grid Image: The input_path `{output_path}` does not exist') + return ('',) + out_path = output_path + else: + out_path = os.path.join(output_dir, out_folder) + if mode == 'Preview': + out_path = folder_paths.temp_directory + print(f'[Info] CR Save XY Grid Image: Output path is `{out_path}`') + counter = find_highest_numeric_value(out_path, filename_prefix) + 1 + output_image = image[0].cpu().numpy() + img = Image.fromarray(np.clip(output_image * 255.0, 0, 255).astype(np.uint8)) + output_filename = f'{filename_prefix}_{counter:05}' + img_params = {'png': {'compress_level': 4}, 'webp': {'method': 6, 'lossless': False, 'quality': 80}, 'jpg': {'format': 'JPEG'}, 'tif': {'format': 'TIFF'}} + self.type = 'output' if mode == 'Save' else 'temp' + resolved_image_path = os.path.join(out_path, f'{output_filename}.{file_format}') + img.save(resolved_image_path, **img_params[file_format]) + print(f'[Info] CR Save XY Grid Image: Saved to {output_filename}.{file_format}') + out_filename = f'{output_filename}.{file_format}' + preview = {'ui': {'images': [{'filename': out_filename, 'subfolder': out_path, 'type': self.type}]}} + return preview +``` \ No newline at end of file diff --git a/docs/CR_Aspect Ratio For Print.md b/docs/CR_Aspect Ratio For Print.md new file mode 100644 index 0000000..582f685 --- /dev/null +++ b/docs/CR_Aspect Ratio For Print.md @@ -0,0 +1,97 @@ +# Documentation +- Class name: CR_AspectRatioForPrint +- Category: Comfyroll/Aspect Ratio +- Output node: False +- Repo Ref: https://github.com/RockOfFire/ComfyUI_Comfyroll_CustomNodes + +CR_AspectRatioForPrint节点旨在根据指定的宽高比计算和调整图像或打印的尺寸。它允许交换维度并应用缩放因子以实现所需的输出大小,满足各种打印需求。 + +# Input types +## Required +- width + - 宽度参数决定了图像或打印的水平尺寸。对于保持宽高比和正确缩放图像至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置图像或打印的垂直尺寸。它与宽度一起工作,以确保保持宽高比。 + - Comfy dtype: INT + - Python dtype: int +- aspect_ratio + - 宽高比定义了宽度和高度之间的比例关系。它是计算最终尺寸的关键因素。 + - Comfy dtype: STRING + - Python dtype: str +- swap_dimensions + - swap_dimensions参数允许用户在需要时交换宽度和高度值,提供尺寸调整的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- upscale_factor + - upscale_factor用于放大图像尺寸。对于高分辨率打印或数字放大,这是一个重要参数。 + - Comfy dtype: FLOAT + - Python dtype: float +- prescale_factor + - prescale_factor参数应用于宽高比调整之前,允许对图像尺寸进行初步缩放。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - batch_size参数指定一次处理的图像数量。对于高效处理大量图像至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- width + - 输出宽度是在应用宽高比和缩放因子后图像或打印的水平尺寸。 + - Comfy dtype: INT + - Python dtype: int +- height + - 输出高度是在应用宽高比和缩放因子后图像或打印的垂直尺寸。 + - Comfy dtype: INT + - Python dtype: int +- upscale_factor + - upscale_factor输出反映了用于放大图像尺寸的缩放因子。 + - Comfy dtype: FLOAT + - Python dtype: float +- prescale_factor + - prescale_factor输出表明在宽高比调整之前应用的初始缩放因子。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - batch_size输出显示当前操作中处理的图像数量。 + - Comfy dtype: INT + - Python dtype: int +- empty_latent + - empty_latent输出为处理后的图像提供空的潜在表示,可用于进一步的图像处理任务。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- show_help + - show_help输出提供了一个链接到文档,以获得关于使用该节点的进一步帮助和指导。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CR_AspectRatioForPrint: + + @classmethod + def INPUT_TYPES(cls): + aspect_ratios = list(PRINT_SIZES.keys()) + return {'required': {'width': ('INT', {'default': 1024, 'min': 64, 'max': 8192}), 'height': ('INT', {'default': 1024, 'min': 64, 'max': 8192}), 'aspect_ratio': (aspect_ratios,), 'swap_dimensions': (['Off', 'On'],), 'upscale_factor': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 100.0, 'step': 0.1}), 'prescale_factor': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 100.0, 'step': 0.1}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}} + RETURN_TYPES = ('INT', 'INT', 'FLOAT', 'FLOAT', 'INT', 'LATENT', 'STRING') + RETURN_NAMES = ('width', 'height', 'upscale_factor', 'prescale_factor', 'batch_size', 'empty_latent', 'show_help') + FUNCTION = 'Aspect_Ratio' + CATEGORY = icons.get('Comfyroll/Aspect Ratio') + + def Aspect_Ratio(self, width, height, aspect_ratio, swap_dimensions, upscale_factor, prescale_factor, batch_size): + if aspect_ratio in PRINT_SIZES: + (width, height) = PRINT_SIZES[aspect_ratio] + if swap_dimensions == 'On': + (width, height) = (height, width) + width = int(width * prescale_factor) + height = int(height * prescale_factor) + print(f'Width: {width}, Height: {height}') + latent = torch.zeros([batch_size, 4, height // 8, width // 8]) + show_help = 'https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Aspect-Ratio-Nodes#cr-aspect-ratio-scial-media' + return (width, height, upscale_factor, prescale_factor, batch_size, {'samples': latent}, show_help) +``` \ No newline at end of file diff --git a/docs/Cache Node.md b/docs/Cache Node.md new file mode 100644 index 0000000..4111e09 --- /dev/null +++ b/docs/Cache Node.md @@ -0,0 +1,107 @@ +# Documentation +- Class name: WAS_Cache +- Category: WAS Suite/IO +- Output node: True +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Cache节点旨在为WAS套件高效地管理和存储输入数据。它缓存潜在向量、图像和条件数据,确保数据在后续处理阶段随时可用。该节点通过减少重新计算或重新获取数据的需求,在优化工作流程中发挥着关键作用,从而提高系统的整体性能。 + +# Input types +## Required +- latent_suffix + - latent_suffix参数用于定义缓存的潜在向量的文件名后缀。这对于区分不同的潜在向量集至关重要,对于节点管理和检索正确数据的能力非常关键。 + - Comfy dtype: STRING + - Python dtype: str +- image_suffix + - image_suffix参数指定缓存图像的文件名后缀。这个后缀对于节点在需要时正确识别和访问图像数据至关重要,有助于有组织地处理视觉信息。 + - Comfy dtype: STRING + - Python dtype: str +- conditioning_suffix + - conditioning_suffix参数应用于缓存条件数据的文件名后缀。它是节点组织和维护条件信息访问策略的关键要素,对于工作流程中的后续步骤至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- output_path + - output_path参数决定了缓存数据将被存储的目录。它在选择存储位置方面提供了灵活性,对节点的操作非常重要,特别是在数据需要存储在特定目录以进行进一步处理的场景中。 + - Comfy dtype: STRING + - Python dtype: str +- latent + - latent参数表示要缓存的潜在向量。它是节点的重要输入,因为它直接影响将要存储并在工作流程的后续阶段中使用的数据。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- image + - image参数包含节点预期要缓存的图像数据。它是一个关键输入,因为它涉及到需要在系统内保留以备将来使用的视觉内容。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- conditioning + - conditioning参数负责提供要缓存的条件数据。这些数据对于指导生成过程至关重要,是节点功能的重要输入。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor + +# Output types +- latent_filename + - latent_filename输出提供了缓存的潜在向量的文件名。这很重要,因为它允许在需要时轻松引用和检索潜在数据。 + - Comfy dtype: STRING + - Python dtype: str +- image_filename + - image_filename输出表示缓存的图像数据的文件名。这是一个重要的信息片段,它便于在后续操作中访问和使用图像内容。 + - Comfy dtype: STRING + - Python dtype: str +- conditioning_filename + - conditioning_filename输出指示缓存的条件数据的文件名。这个输出对于系统在生成过程中正确定位和使用条件信息至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Cache: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'latent_suffix': ('STRING', {'default': str(random.randint(999999, 99999999)) + '_cache', 'multiline': False}), 'image_suffix': ('STRING', {'default': str(random.randint(999999, 99999999)) + '_cache', 'multiline': False}), 'conditioning_suffix': ('STRING', {'default': str(random.randint(999999, 99999999)) + '_cache', 'multiline': False})}, 'optional': {'output_path': ('STRING', {'default': os.path.join(WAS_SUITE_ROOT, 'cache'), 'multiline': False}), 'latent': ('LATENT',), 'image': ('IMAGE',), 'conditioning': ('CONDITIONING',)}} + RETURN_TYPES = (TEXT_TYPE, TEXT_TYPE, TEXT_TYPE) + RETURN_NAMES = ('latent_filename', 'image_filename', 'conditioning_filename') + FUNCTION = 'cache_input' + OUTPUT_NODE = True + CATEGORY = 'WAS Suite/IO' + + def cache_input(self, latent_suffix='_cache', image_suffix='_cache', conditioning_suffix='_cache', output_path=None, latent=None, image=None, conditioning=None): + if 'joblib' not in packages(): + install_package('joblib') + import joblib + output = os.path.join(WAS_SUITE_ROOT, 'cache') + if output_path: + if output_path.strip() not in ['', 'none', 'None']: + output = output_path + if not os.path.isabs(output): + output = os.path.abspath(output) + if not os.path.exists(output): + os.makedirs(output, exist_ok=True) + l_filename = '' + i_filename = '' + c_filename = '' + tokens = TextTokens() + output = tokens.parseTokens(output) + if latent != None: + l_filename = f'{tokens.parseTokens(latent_suffix)}.latent' + out_file = os.path.join(output, l_filename) + joblib.dump(latent, out_file) + cstr(f'Latent saved to: {out_file}').msg.print() + if image != None: + i_filename = f'{tokens.parseTokens(image_suffix)}.image' + out_file = os.path.join(output, i_filename) + joblib.dump(image, out_file) + cstr(f'Tensor batch saved to: {out_file}').msg.print() + if conditioning != None: + c_filename = f'{tokens.parseTokens(conditioning_suffix)}.conditioning' + out_file = os.path.join(output, c_filename) + joblib.dump(conditioning, os.path.join(output, out_file)) + cstr(f'Conditioning saved to: {out_file}').msg.print() + return (l_filename, i_filename, c_filename) +``` \ No newline at end of file diff --git a/docs/CacheBackendData %2F%2FInspire.md b/docs/CacheBackendData %2F%2FInspire.md new file mode 100644 index 0000000..1bfc7e5 --- /dev/null +++ b/docs/CacheBackendData %2F%2FInspire.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: CacheBackendData +- Category: InspirePack/Backend +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +此类节点管理后端缓存系统中数据的存储和检索,便于高效的数据访问和工作流过程的优化。 + +# Input types +## Required +- key + - key参数对于在缓存中唯一标识数据至关重要。它用于索引和检索相关数据,确保访问和处理正确的信息。 + - Comfy dtype: STRING + - Python dtype: str +- tag + - tag参数作为数据的描述性标签,有助于数据分类和快速引用。它增强了缓存内的组织,并支持高效的数据管理。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- data + - data参数代表要缓存的实际内容。它是节点操作的基础,因为它保存了将被存储和稍后访问的值。 + - Comfy dtype: ANY + - Python dtype: Any + +# Output types +- data opt + - 输出提供原始输入的数据,确保整个过程中数据流得到维持。它确认数据已成功存储,可供将来使用。 + - Comfy dtype: ANY + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CacheBackendData: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'key': ('STRING', {'multiline': False, 'placeholder': "Input data key (e.g. 'model a', 'chunli lora', 'girl latent 3', ...)"}), 'tag': ('STRING', {'multiline': False, 'placeholder': 'Tag: short description'}), 'data': (any_typ,)}} + RETURN_TYPES = (any_typ,) + RETURN_NAMES = ('data opt',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Backend' + OUTPUT_NODE = True + + def doit(self, key, tag, data): + global cache + if key == '*': + print(f"[Inspire Pack] CacheBackendData: '*' is reserved key. Cannot use that key") + cache[key] = (tag, (False, data)) + return (data,) +``` \ No newline at end of file diff --git a/docs/CacheBackendDataList %2F%2FInspire.md b/docs/CacheBackendDataList %2F%2FInspire.md new file mode 100644 index 0000000..10bda48 --- /dev/null +++ b/docs/CacheBackendDataList %2F%2FInspire.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CacheBackendDataList +- Category: InspirePack/Backend +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点管理后端系统中数据的检索和存储,便于高效的数据访问和组织。 + +# Input types +## Required +- key + - key参数对于在缓存中识别特定的数据条目至关重要。它作为一个唯一标识符,允许节点准确检索或存储相关数据。 + - Comfy dtype: STRING + - Python dtype: str +- tag + - tag参数提供了一种对缓存中的数据进行分类和描述的手段。它有助于数据的组织和过滤,提高了系统的整体效率。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- data + - data参数代表实际要存储或从缓存中检索的内容。这是一个多功能字段,可以根据用例包含各种类型的信息。 + - Comfy dtype: ANY + - Python dtype: Any + +# Output types +- data + - 输出数据代表从缓存中检索到的信息。它是节点操作的主要结果,展示了节点在管理和提供存储数据访问方面的有效性。 + - Comfy dtype: ANY + - Python dtype: Any +- opt + - opt参数,作为输出的一部分,可能包含与检索数据相关的额外选项或元数据。它补充了主要的数据输出,提供了进一步的上下文或实用工具。 + - Comfy dtype: ANY + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CacheBackendDataList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'key': ('STRING', {'multiline': False, 'placeholder': "Input data key (e.g. 'model a', 'chunli lora', 'girl latent 3', ...)"}), 'tag': ('STRING', {'multiline': False, 'placeholder': 'Tag: short description'}), 'data': (any_typ,)}} + INPUT_IS_LIST = True + RETURN_TYPES = (any_typ,) + RETURN_NAMES = ('data opt',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Backend' + OUTPUT_NODE = True + + def doit(self, key, tag, data): + global cache + if key == '*': + print(f"[Inspire Pack] CacheBackendDataList: '*' is reserved key. Cannot use that key") + cache[key[0]] = (tag[0], (True, data)) + return (data,) +``` \ No newline at end of file diff --git a/docs/CacheBackendDataNumberKey %2F%2FInspire.md b/docs/CacheBackendDataNumberKey %2F%2FInspire.md new file mode 100644 index 0000000..738aa08 --- /dev/null +++ b/docs/CacheBackendDataNumberKey %2F%2FInspire.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: CacheBackendDataNumberKey +- Category: InspirePack/Backend +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在缓存系统中管理和存储数据,使用唯一的数值键进行识别和检索。它在维护后端基础设施中数据流的效率和组织方面发挥着至关重要的作用。 + +# Input types +## Required +- key + - ‘key’参数对于节点的运行至关重要,因为它在缓存中唯一标识数据。它是影响节点准确存储和检索信息能力的关键组成部分。 + - Comfy dtype: INT + - Python dtype: int +- data + - ‘data’参数代表要缓存的实际内容。它是节点处理和存储的主要输入,确保信息随时可用。 + - Comfy dtype: ANY + - Python dtype: Any +## Optional +- tag + - ‘tag’参数作为数据的描述符,提供了一个简短的描述,可用于对缓存信息进行分类或筛选。它通过提供一种更有效地组织和访问数据的方式,增强了节点的功能。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- data opt + - 输出‘data opt’表示在缓存过程中返回的原始数据以及可能发生的任何附加信息或修改。这确保用户收到预期的完整数据集。 + - Comfy dtype: ANY + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CacheBackendDataNumberKey: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'key': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'tag': ('STRING', {'multiline': False, 'placeholder': 'Tag: short description'}), 'data': (any_typ,)}} + RETURN_TYPES = (any_typ,) + RETURN_NAMES = ('data opt',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Backend' + OUTPUT_NODE = True + + def doit(self, key, tag, data): + global cache + cache[key] = (tag, (False, data)) + return (data,) +``` \ No newline at end of file diff --git a/docs/CacheBackendDataNumberKeyList %2F%2FInspire.md b/docs/CacheBackendDataNumberKeyList %2F%2FInspire.md new file mode 100644 index 0000000..ef67583 --- /dev/null +++ b/docs/CacheBackendDataNumberKeyList %2F%2FInspire.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: CacheBackendDataNumberKeyList +- Category: InspirePack/Backend +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +CacheBackendDataNumberKeyList节点旨在高效管理和存储后端系统中与数值键关联的数据。它作为缓存机制的关键组件,确保能够快速访问频繁使用的数据,而无需进行冗余的检索过程。 + +# Input types +## Required +- key + - “key”参数是用于引用和访问缓存中存储的数据的数值标识符。它在节点的操作中起着关键作用,因为它直接影响数据检索的效率和准确性。 + - Comfy dtype: INT + - Python dtype: int +- tag + - “tag”参数是一个字符串,为与键关联的数据提供简短的描述或标签。它有助于组织和识别缓存的数据,增强节点的整体功能。 + - Comfy dtype: STRING + - Python dtype: str +- data + - “data”参数表示要缓存的实际数据。它对节点的操作至关重要,因为它是将被存储并在请求时检索的主要内容。 + - Comfy dtype: any_typ + - Python dtype: Any + +# Output types +- data opt + - “data opt”输出提供缓存中请求的数据,确保节点实现其高效数据检索和存储的目的。 + - Comfy dtype: any_typ + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CacheBackendDataNumberKeyList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'key': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'tag': ('STRING', {'multiline': False, 'placeholder': 'Tag: short description'}), 'data': (any_typ,)}} + INPUT_IS_LIST = True + RETURN_TYPES = (any_typ,) + RETURN_NAMES = ('data opt',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Backend' + OUTPUT_NODE = True + + def doit(self, key, tag, data): + global cache + cache[key[0]] = (tag[0], (True, data)) + return (data,) +``` \ No newline at end of file diff --git a/docs/CalculateFrameOffset.md b/docs/CalculateFrameOffset.md new file mode 100644 index 0000000..5fdae60 --- /dev/null +++ b/docs/CalculateFrameOffset.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: CalculateFrameOffset +- Category: FizzNodes 📅🅕🅝/HelperNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +CalculateFrameOffset 节点旨在根据当前帧、最大帧数和潜在输入数量计算并分配序列中的帧编号。它在管理与帧相关的操作的序列顺序中发挥着关键作用。 + +# Input types +## Required +- current_frame + - current_frame 参数指定帧序列中的当前位置。这对于确定帧编号分配的起始点至关重要。 + - Comfy dtype: INT + - Python dtype: int +- max_frames + - max_frames 参数设置了帧编号的上限。这对于确保帧编号保持在有效范围内至关重要。 + - Comfy dtype: INT + - Python dtype: int +- num_latent_inputs + - num_latent_inputs 参数指示用于帧计算的潜在输入数量。它显著影响序列内帧编号的分配方式。 + - Comfy dtype: INT + - Python dtype: int +- index + - index 参数代表潜在输入中的具体索引。它用于计算分配帧编号的偏移量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- frame_offset + - frame_offset 输出代表给定输入计算出的帧编号。它对于序列中帧的后续处理和处理具有重要意义。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CalculateFrameOffset: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'current_frame': ('INT', {'default': 0, 'min': 0}), 'max_frames': ('INT', {'default': 18, 'min': 0}), 'num_latent_inputs': ('INT', {'default': 4, 'min': 0}), 'index': ('INT', {'default': 4, 'min': 0})}} + RETURN_TYPES = ('INT',) + FUNCTION = 'assignFrameNum' + CATEGORY = 'FizzNodes 📅🅕🅝/HelperNodes' + + def assignFrameNum(self, current_frame, max_frames, num_latent_inputs, index): + if current_frame == 0: + return (index,) + else: + start_frame = (current_frame - 1) * (num_latent_inputs - 1) + (num_latent_inputs - 1) + return ((start_frame + index) % max_frames,) +``` \ No newline at end of file diff --git a/docs/CannyEdgeMask.md b/docs/CannyEdgeMask.md new file mode 100644 index 0000000..0cc0dbb --- /dev/null +++ b/docs/CannyEdgeMask.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: CannyEdgeMask +- Category: postprocessing/Masks +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +此类节点封装了对输入图像应用Canny边缘检测算法的功能,根据指定的阈值生成突出显示图像中边缘的二值边缘掩码。 + +# Input types +## Required +- image + - 要应用Canny边缘检测的输入图像。它是节点操作的关键,因为它是算法处理以产生边缘掩码的主要数据。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- lower_threshold + - 下阈值参数对于控制边缘检测的灵敏度至关重要。它与上阈值一起工作,以确定哪些边缘足够强以包含在最终的边缘掩码中。 + - Comfy dtype: INT + - Python dtype: int +- upper_threshold + - 上阈值参数与下阈值一起,在定义边缘检测的标准中起着重要作用。它通过只包括达到或超过此阈值的边缘来帮助细化边缘。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- edge_mask + - 输出是一个二值边缘掩码,代表Canny算法检测到的边缘。这个掩码非常重要,因为它用于进一步的图像处理或分析。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CannyEdgeMask: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'lower_threshold': ('INT', {'default': 100, 'min': 0, 'max': 500, 'step': 10}), 'upper_threshold': ('INT', {'default': 200, 'min': 0, 'max': 500, 'step': 10})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'canny' + CATEGORY = 'postprocessing/Masks' + + def canny(self, image: torch.Tensor, lower_threshold: int, upper_threshold: int): + (batch_size, height, width, _) = image.shape + result = torch.zeros(batch_size, height, width) + for b in range(batch_size): + tensor_image = image[b].numpy().copy() + gray_image = (cv2.cvtColor(tensor_image, cv2.COLOR_RGB2GRAY) * 255).astype(np.uint8) + canny = cv2.Canny(gray_image, lower_threshold, upper_threshold) + tensor = torch.from_numpy(canny) + result[b] = tensor + return (result,) +``` \ No newline at end of file diff --git a/docs/Canny_Preprocessor_Provider_for_SEGS %2F%2FInspire.md b/docs/Canny_Preprocessor_Provider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..c0ee297 --- /dev/null +++ b/docs/Canny_Preprocessor_Provider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: Canny_Preprocessor_Provider_for_SEGS +- Category: InspirePack/SEGS/ControlNet +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +Canny_Preprocessor_Provider_for_SEGS 节点旨在通过应用 Canny 边缘检测算法来预处理图像,以便进行分割任务。它增强了图像的边缘,这可以通过为后续的分割模型提供更详细的结构信息,显著提高它们的性能。 + +# Input types +## Required +- low_threshold + - low_threshold 参数对于 Canny 边缘检测算法至关重要,因为它决定了边缘检测的下限。它影响算法对噪声的敏感度以及检测到的边缘的精细度。 + - Comfy dtype: FLOAT + - Python dtype: float +- high_threshold + - high_threshold 参数在 Canny 边缘检测过程中起着关键作用,它设置了边缘链接的上限。它定义了边缘的证据必须有多强才能被认为是显著的。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- SEGS_PREPROCESSOR + - SEGS_PREPROCESSOR 输出是经过增强边缘的预处理图像,适用于分割任务。它是使用指定的阈值应用 Canny 边缘检测的结果。 + - Comfy dtype: SEGS_PREPROCESSOR + - Python dtype: Canny_Preprocessor_wrapper + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Canny_Preprocessor_Provider_for_SEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'low_threshold': ('FLOAT', {'default': 0.4, 'min': 0.01, 'max': 0.99, 'step': 0.01}), 'high_threshold': ('FLOAT', {'default': 0.8, 'min': 0.01, 'max': 0.99, 'step': 0.01})}} + RETURN_TYPES = ('SEGS_PREPROCESSOR',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/SEGS/ControlNet' + + def doit(self, low_threshold, high_threshold): + obj = Canny_Preprocessor_wrapper(low_threshold, high_threshold) + return (obj,) +``` \ No newline at end of file diff --git a/docs/CenterImage.md b/docs/CenterImage.md new file mode 100644 index 0000000..d62dc54 --- /dev/null +++ b/docs/CenterImage.md @@ -0,0 +1,63 @@ +# Documentation +- Class name: CenterImage +- Category: ♾️Mixlab/Layer +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +CenterImage节点旨在将图像处理并居中放置在给定的画布内,重点关注指定的区域。它通过计算所需的坐标和尺寸来实现这一点,同时考虑所提供的边距。该节点的功能不仅限于简单的放置;它还生成一个与居中区域相对应的掩码,增强了其在各种图像处理任务中的适用性。 + +# Input types +## Required +- canvas + - 画布参数是必需的,因为它代表了将执行居中操作的基础图像。它是节点执行的基础,直接影响输出的网格和掩码。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- left + - left参数指定了居中操作的左边距。它对于确定图像在画布中的确切位置至关重要,并有助于最终居中的外观。 + - Comfy dtype: INT + - Python dtype: int +- top + - top参数定义了居中过程中的上边距。它在图像的垂直放置中起着重要作用,并影响整体的居中布局。 + - Comfy dtype: INT + - Python dtype: int +- right + - right参数设置了画布内图像的右边距。它是水平定位的重要因素,并有助于精确地构建居中图像的框架。 + - Comfy dtype: INT + - Python dtype: int +- bottom + - bottom参数指示了图像居中所需的下边距。它对于垂直对齐至关重要,并确保图像正确地包含在画布边界内。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- grid + - 网格输出提供了画布内居中图像的坐标和尺寸。这些信息对于进一步的图像处理或操作任务至关重要。 + - Comfy dtype: _GRID + - Python dtype: Tuple[int, int, int, int] +- mask + - 掩码输出是一个二进制图像,它描绘了居中图像的区域。它在图像处理工作流程中的掩蔽、过滤或分割等应用中非常重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CenterImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'canvas': ('IMAGE',), 'left': ('INT', {'default': 24, 'min': 0, 'max': 5000, 'step': 1, 'display': 'number'}), 'top': ('INT', {'default': 24, 'min': 0, 'max': 5000, 'step': 1, 'display': 'number'}), 'right': ('INT', {'default': 24, 'min': 0, 'max': 5000, 'step': 1, 'display': 'number'}), 'bottom': ('INT', {'default': 24, 'min': 0, 'max': 5000, 'step': 1, 'display': 'number'})}} + RETURN_TYPES = ('_GRID', 'MASK') + RETURN_NAMES = ('grid', 'mask') + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Layer' + INPUT_IS_LIST = False + + def run(self, canvas, left, top, right, bottom): + canvas = tensor2pil(canvas) + grid = centerImage((left, top, right, bottom), canvas) + mask = createMask(canvas, left, top, canvas.width - left - right, canvas.height - top - bottom) + return (grid, pil2tensor(mask)) +``` \ No newline at end of file diff --git a/docs/CfgScheduleHookProvider.md b/docs/CfgScheduleHookProvider.md new file mode 100644 index 0000000..78cf84f --- /dev/null +++ b/docs/CfgScheduleHookProvider.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: CfgScheduleHookProvider +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +CfgScheduleHookProvider节点旨在管理和提供迭代过程的配置进度表。它通过提供一个简单的接口来检索基于指定迭代和目标配置的钩子,从而抽象化了处理不同调度策略的复杂性。 + +# Input types +## Required +- schedule_for_iteration + - schedule_for_iteration参数决定了迭代过程将使用哪个进度表。它至关重要,因为它决定了配置随时间调整的方法,影响整个过程的最终结果。 + - Comfy dtype: STRING + - Python dtype: str +- target_cfg + - target_cfg参数设置了过程旨在达到的期望配置值。它很重要,因为它直接影响迭代过程中应用的最终配置。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- hook + - hook输出提供了一个配置好的钩子对象,可以在迭代过程中用于管理调度。它封装了随时间调整配置所需的逻辑。 + - Comfy dtype: PK_HOOK + - Python dtype: PixelKSampleHook + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CfgScheduleHookProvider: + schedules = ['simple'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'schedule_for_iteration': (s.schedules,), 'target_cfg': ('FLOAT', {'default': 3.0, 'min': 0.0, 'max': 100.0})}} + RETURN_TYPES = ('PK_HOOK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + def doit(self, schedule_for_iteration, target_cfg): + hook = None + if schedule_for_iteration == 'simple': + hook = hooks.SimpleCfgScheduleHook(target_cfg) + return (hook,) +``` \ No newline at end of file diff --git a/docs/Change Channel Count.md b/docs/Change Channel Count.md new file mode 100644 index 0000000..a5d3433 --- /dev/null +++ b/docs/Change Channel Count.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: ChangeChannelCount +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +ChangeChannelCount节点旨在修改图像张量的通道数。它能够智能地处理不同类型的图像,例如掩码、RGBA和RGB,并根据指定的类型进行转换。在需要进行通道操作以实现兼容性或风格化目的的图像处理工作流程中,此节点发挥着关键作用。 + +# Input types +## Required +- image + - 图像参数是表示图像数据的输入张量。它至关重要,因为它是节点将处理的主要数据。节点的操作取决于此图像张量的维度和内容,这直接影响输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- kind + - kind参数指示应用于输入图像张量的通道转换类型。它至关重要,因为它决定了图像通道的输出格式。根据指定的通道转换类型,kind参数可以显著改变节点的执行和最终结果。 + - Comfy dtype: COMBO['mask', 'RGB', 'RGBA'] + - Python dtype: str + +# Output types +- output_image + - output_image是通道转换过程的结果。它很重要,因为它代表了节点的最终输出,即根据指定的kind具有修改过的通道数的图像张量。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ChangeChannelCount: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'kind': (['mask', 'RGB', 'RGBA'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'change_channels' + CATEGORY = 'Masquerade Nodes' + + def change_channels(self, image, kind): + image_size = image.size() + if kind == 'mask': + return (tensor2mask(image),) + elif kind == 'RGBA': + return (tensor2rgba(image),) + else: + return (tensor2rgb(image),) +``` \ No newline at end of file diff --git a/docs/ChangeImageBatchSize %2F%2FInspire.md b/docs/ChangeImageBatchSize %2F%2FInspire.md new file mode 100644 index 0000000..b93c37b --- /dev/null +++ b/docs/ChangeImageBatchSize %2F%2FInspire.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: ChangeImageBatchSize +- Category: InspirePack/image +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在调整给定图像集的批量大小,确保输出符合指定的批量大小要求。它通过复制最后一个图像以填充批次或根据需要截断批次来实现这一点,具体取决于输入。该节点对于预处理图像数据以满足后续处理步骤的输入要求至关重要。 + +# Input types +## Required +- image + - 图像参数代表需要调整大小或调整以满足特定批量大小的一批图像。这是一个关键的输入,因为节点的整个操作都围绕着操纵这些图像数据以实现期望的输出批量大小。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- batch_size + - 批量大小参数规定了输出批次中期望的图像数量。这是一个关键因素,决定了输入图像的处理方式,无论是通过复制还是截断,以达到指定的大小。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- mode + - 模式参数决定了调整批量大小所使用的方法。在这种情况下,'简单'模式是唯一支持的选项,它概述了通过复制最后一个图像或截断批次来满足批量大小要求的过程。 + - Comfy dtype: COMBO[simple] + - Python dtype: str + +# Output types +- image + - 输出图像参数是批量大小调整过程的结果。它包含已调整的图像集,现在符合指定的批量大小,准备进行进一步的处理或分析。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ChangeImageBatchSize: + + @classmethod + def INPUT_TYPES(s): + input_dir = folder_paths.get_input_directory() + files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))] + return {'required': {'image': ('IMAGE',), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 4096, 'step': 1}), 'mode': (['simple'],)}} + CATEGORY = 'InspirePack/image' + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'load_image' + + def load_image(self, image, batch_size, mode): + if mode == 'simple': + if len(image) < batch_size: + last_frame = image[-1].unsqueeze(0).expand(batch_size - len(image), -1, -1, -1) + image = torch.concat((image, last_frame), dim=0) + else: + image = image[:batch_size, :, :, :] + return (image,) + else: + print(f'[WARN] ChangeImageBatchSize: Unknown mode `{mode}` - ignored') + return (image,) +``` \ No newline at end of file diff --git a/docs/CharacterInText.md b/docs/CharacterInText.md new file mode 100644 index 0000000..c4a4a4a --- /dev/null +++ b/docs/CharacterInText.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: CharacterInText +- Category: ♾️Mixlab/GPT +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点便于识别文本中特定字符的存在,并计算其出现索引。它处理文本数据以确定给定字符的频率,从指定的索引开始,并通过对字符出现频率提供简单而有效的度量,为文本分析任务做出贡献。 + +# Input types +## Required +- text + - 文本参数至关重要,因为它是要验证字符存在的来源。它是节点处理的主要输入,用于实现其目的。 + - Comfy dtype: STRING + - Python dtype: str +- character + - 字符参数对于节点来说至关重要,它决定了节点在文本中寻找哪个特定的字符。它决定了搜索的重点,并影响节点操作的结果。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- start_index + - 起始索引参数定义了节点在文本中开始搜索字符的起点。它影响了搜索的范围和结果索引值。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result + - 结果输出代表指定字符在文本中的出现索引,从给定的起始索引开始。它是直接输出,反映了节点的主要功能,并提供了字符存在的定量度量。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CharacterInText: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'character': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'start_index': ('INT', {'default': 1, 'min': 0, 'max': 1024, 'step': 1, 'display': 'number'})}} + INPUT_IS_LIST = False + RETURN_TYPES = ('INT',) + FUNCTION = 'run' + OUTPUT_IS_LIST = (False,) + CATEGORY = '♾️Mixlab/GPT' + + def run(self, text, character, start_index): + b = 1 if character.lower() in text.lower() else 0 + return (b + start_index,) +``` \ No newline at end of file diff --git a/docs/ChatGPTOpenAI.md b/docs/ChatGPTOpenAI.md new file mode 100644 index 0000000..02664a8 --- /dev/null +++ b/docs/ChatGPTOpenAI.md @@ -0,0 +1,107 @@ +# Documentation +- Class name: ChatGPTNode +- Category: ♾️Mixlab/GPT +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +ChatGPTNode 类旨在使用 OpenAI 提供的大型语言模型生成上下文感知文本。它管理会话历史以保持对话流程,从而允许更连贯和相关的响应。该节点擅长与各种模型和 API 集成,确保在不同应用场景中的灵活性和适应性。 + +# Input types +## Required +- api_key + - API 密钥对于验证和授权访问语言模型服务至关重要。它在确保与 API 的安全通信中起着核心作用,使节点能够获取和处理语言模型的响应。 + - Comfy dtype: KEY + - Python dtype: str +- api_url + - API URL 指定了语言模型服务的端点。它对于将节点的请求指向正确的服务至关重要,影响节点与语言模型的交互以及从语言模型检索数据的能力。 + - Comfy dtype: URL + - Python dtype: str +- prompt + - 提示是语言模型用来生成响应的输入查询或语句。它是节点操作的关键元素,因为它直接影响生成文本的内容和方向。 + - Comfy dtype: STRING + - Python dtype: str +- system_content + - 系统内容为语言模型提供系统的指令或上下文,这可以影响生成响应的风格和语调。它是一个可选参数,可用于定制节点的行为。 + - Comfy dtype: STRING + - Python dtype: str +- model + - 模型参数选择节点使用的特定语言模型。它决定了语言模型交互的复杂性和能力,影响生成的响应的质量和类型。 + - Comfy dtype: COMBO[gpt-3.5-turbo, gpt-35-turbo, gpt-3.5-turbo-16k, gpt-3.5-turbo-16k-0613, gpt-4-0613, gpt-4-1106-preview, glm-4] + - Python dtype: str +- seed + - 种子为语言模型中使用的随机数生成提供了起始点。它可以用来通过确保模型的随机过程的一致初始状态来产生可重复的结果。 + - Comfy dtype: INT + - Python dtype: int +- context_size + - 上下文大小决定了节点在生成响应时将考虑的先前交换的数量。它影响对话上下文的深度和生成文本的相关性。 + - Comfy dtype: INT + - Python dtype: int +- unique_id + - 唯一 ID 是一个可选的标识符,可用于跟踪或引用与语言模型的特定交互。它不影响节点的执行,但可能对记录或调试目的有用。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +- extra_pnginfo + - 额外的 PNG 信息是一个可选参数,可以为语言模型提供额外的上下文或数据。它的使用特定于某些应用程序,并且可以增强节点生成更详细或特定响应的能力。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: str + +# Output types +- text + - 文本输出代表了语言模型对输入提示的响应。它是节点操作的主要结果,反映了节点生成连贯且上下文相关文本的能力。 + - Comfy dtype: STRING + - Python dtype: str +- messages + - 消息输出是一个 JSON 格式的字符串,包含了当前响之前的对话历史。它包括系统指令、用户提示和助手回复,提供了交互的全面视图。 + - Comfy dtype: STRING + - Python dtype: str +- session_history + - 会话历史输出是一个 JSON 格式的字符串,记录了与语言模型的整个对话会话。它作为对话的记录,可用于分析或在多次交互中保持上下文。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ChatGPTNode: + + def __init__(self): + self.session_history = [] + self.system_content = 'You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible.' + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'api_key': ('KEY', {'default': '', 'multiline': True, 'dynamicPrompts': False}), 'api_url': ('URL', {'default': '', 'multiline': True, 'dynamicPrompts': False}), 'prompt': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'system_content': ('STRING', {'default': 'You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible.', 'multiline': True, 'dynamicPrompts': False}), 'model': (['gpt-3.5-turbo', 'gpt-35-turbo', 'gpt-3.5-turbo-16k', 'gpt-3.5-turbo-16k-0613', 'gpt-4-0613', 'gpt-4-1106-preview', 'glm-4'], {'default': 'gpt-3.5-turbo'}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615, 'step': 1}), 'context_size': ('INT', {'default': 1, 'min': 0, 'max': 30, 'step': 1})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = ('STRING', 'STRING', 'STRING') + RETURN_NAMES = ('text', 'messages', 'session_history') + FUNCTION = 'generate_contextual_text' + CATEGORY = '♾️Mixlab/GPT' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False, False, False) + + def generate_contextual_text(self, api_key, api_url, prompt, system_content, model, seed, context_size, unique_id=None, extra_pnginfo=None): + if system_content: + self.system_content = system_content + if is_azure_url(api_url): + client = azure_client(api_key, api_url) + elif model == 'glm-4': + client = ZhipuAI_client(api_key) + print('using Zhipuai interface') + else: + client = openai_client(api_key, api_url) + print('using ChatGPT interface') + + def crop_list_tail(lst, size): + if size >= len(lst): + return lst + elif size == 0: + return [] + else: + return lst[-size:] + session_history = crop_list_tail(self.session_history, context_size) + messages = [{'role': 'system', 'content': self.system_content}] + session_history + [{'role': 'user', 'content': prompt}] + response_content = chat(client, model, messages) + self.session_history = self.session_history + [{'role': 'user', 'content': prompt}] + [{'role': 'assistant', 'content': response_content}] + return (response_content, json.dumps(messages, indent=4), json.dumps(self.session_history, indent=4)) +``` \ No newline at end of file diff --git a/docs/Checkpoint Loader (Simple).md b/docs/Checkpoint Loader (Simple).md new file mode 100644 index 0000000..74ecfac --- /dev/null +++ b/docs/Checkpoint Loader (Simple).md @@ -0,0 +1,62 @@ +# Documentation +- Class name: WAS_Checkpoint_Loader_Simple +- Category: WAS Suite/Loaders +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +load_checkpoint 方法旨在高效地检索和初始化指定检查点的各个组件,便于其在工作流中的无缝集成。它作为存储模型与应用之间的关键链接,确保后续操作所需的必要元素随时可用。 + +# Input types +## Required +- ckpt_name + - 检查点名称参数对于识别要加载的特定检查点至关重要。它指导节点找到正确的文件,从而检索相关的模型和配置。 + - Comfy dtype: str + - Python dtype: str +## Optional +- output_vae + - output_vae 参数决定是否从检查点加载变分自编码器(VAE)组件。它允许根据当前任务的需求选择性地加载组件。 + - Comfy dtype: bool + - Python dtype: bool +- output_clip + - output_clip 参数决定在检索检查点的过程中是否应加载 CLIP 模型。它提供了在加载的组件中包含或排除 CLIP 模型的灵活性。 + - Comfy dtype: bool + - Python dtype: bool + +# Output types +- MODEL + - MODEL 输出代表从检查点加载的主要神经网络架构,它对后续的处理和分析任务至关重要。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- CLIP + - CLIP 输出表示与主要模型一起加载的条件语言-图像预训练模型,它增强了节点处理多模态任务的能力。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- VAE + - VAE 输出表示可以检索的变分自编码器组件,在节点的操作范围内提供强大的生成模型和数据编码工具。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- NAME_STRING + - NAME_STRING 输出提供检查点的名称作为字符串,这对于日志记录、识别或工作流中的进一步处理非常有用。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Checkpoint_Loader_Simple: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (comfy_paths.get_filename_list('checkpoints'),)}} + RETURN_TYPES = ('MODEL', 'CLIP', 'VAE', TEXT_TYPE) + RETURN_NAMES = ('MODEL', 'CLIP', 'VAE', 'NAME_STRING') + FUNCTION = 'load_checkpoint' + CATEGORY = 'WAS Suite/Loaders' + + def load_checkpoint(self, ckpt_name, output_vae=True, output_clip=True): + ckpt_path = comfy_paths.get_full_path('checkpoints', ckpt_name) + out = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=comfy_paths.get_folder_paths('embeddings')) + return (out[0], out[1], out[2], os.path.splitext(os.path.basename(ckpt_name))[0]) +``` \ No newline at end of file diff --git a/docs/Checkpoint Loader Simple Mikey.md b/docs/Checkpoint Loader Simple Mikey.md new file mode 100644 index 0000000..c0a67dc --- /dev/null +++ b/docs/Checkpoint Loader Simple Mikey.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: CheckpointLoaderSimpleMikey +- Category: Mikey/Loaders +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +CheckpointLoaderSimpleMikey节点旨在简化机器学习工作流中检查点的加载和管理过程。它提供了一个简单的接口,用于从指定的检查点目录检索模型状态、相关剪辑和变分自编码器(VAE)。该节点还计算并返回检查点文件的哈希值,确保数据的完整性和可追溯性。 + +# Input types +## Required +- ckpt_name + - 参数'ckpt_name'对于识别要加载的特定检查点至关重要。节点使用它在检查点目录中定位和访问相关的模型状态和配置文件。 + - Comfy dtype: str + - Python dtype: str +## Optional +- output_vae + - 参数'output_vae'决定是否加载与检查点相关联的变分自编码器。它在节点的操作中提供了灵活性,允许用户控制检索检查点的组件。 + - Comfy dtype: bool + - Python dtype: bool +- output_clip + - 参数'output_clip'控制加载与检查点相关联的clip。它允许节点根据用户的需求选择性地包含或排除clip。 + - Comfy dtype: bool + - Python dtype: bool +- unique_id + - 参数'unique_id'用于节点操作中的额外识别目的。在某些应用中,可能需要通过文件名之外的方式区分多个检查点,这时'unique_id'就变得相关了。 + - Comfy dtype: str + - Python dtype: str +- extra_pnginfo + - 参数'extra_pnginfo'旨在为节点内的某些操作提供可能需要的额外信息。它的使用是可选的,并且依赖于上下文,增强了节点对各种场景的适应性。 + - Comfy dtype: str + - Python dtype: str +- prompt + - 参数'prompt'用于根据用户输入引导节点的行为。它可以影响检查点的处理方式或返回的信息,为节点的执行提供了一定程度的定制化。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- model + - 输出'model'代表从检查点加载的机器学习模型状态。它是节点功能的核心组件,使得模型的训练过程可以继续或进行分析。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - 输出'clip'对应于与检查点相关联的加载的clip。它是一个可选组件,可以根据'output_clip'参数包括,为某些应用提供额外的上下文或功能。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- vae + - 输出'vae'表示从检查点加载的变分自编码器。它是节点输出的可选部分,由'output_vae'参数控制,可以用于生成任务或进一步分析。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- ckpt_name + - 输出'ckpt_name'提供了被加载的检查点文件的名称。这对于记录、跟踪或在后续操作中引用特定检查点非常有用。 + - Comfy dtype: str + - Python dtype: str +- ckpt_hash + - 输出'ckpt_hash'是派生自检查点文件的哈希值。它作为检查点的唯一标识符,对于验证加载数据的完整性或用于记录目的非常有用。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CheckpointLoaderSimpleMikey: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (folder_paths.get_filename_list('checkpoints'),)}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('MODEL', 'CLIP', 'VAE', 'STRING', 'STRING') + RETURN_NAMES = ('model', 'clip', 'vae', 'ckpt_name', 'ckpt_hash') + FUNCTION = 'load_checkpoint' + CATEGORY = 'Mikey/Loaders' + + def load_checkpoint(self, ckpt_name, output_vae=True, output_clip=True, unique_id=None, extra_pnginfo=None, prompt=None): + ckpt_path = folder_paths.get_full_path('checkpoints', ckpt_name) + out = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths('embeddings')) + hash = get_file_hash(ckpt_path) + ckpt_name = os.path.basename(ckpt_name) + return out[:3] + (ckpt_name, hash) +``` \ No newline at end of file diff --git a/docs/Checkpoint Loader w%2FName (WLSH).md b/docs/Checkpoint Loader w%2FName (WLSH).md new file mode 100644 index 0000000..b4d35db --- /dev/null +++ b/docs/Checkpoint Loader w%2FName (WLSH).md @@ -0,0 +1,65 @@ +# Documentation +- Class name: WLSH_Checkpoint_Loader_Model_Name +- Category: WLSH Nodes/loaders +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_Checkpoint_Loader_Model_Name节点旨在加载和管理工作流中的检查点。它对于机器学习实验的连续性和可重复性至关重要,确保了保存的模型状态的无缝集成和使用。该节点抽象了检查点检索的复杂性,为模型、CLIP和VAE组件提供了一个直接的接口。 + +# Input types +## Required +- ckpt_name + - 'ckpt_name'参数对于识别要加载的特定检查点至关重要。它指导节点到正确的文件路径,对于成功地从保存的检查点恢复模型的状态至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- MODEL + - 'MODEL'输出提供了加载的模型状态,可以用于工作流后续阶段的进一步处理或推断。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- CLIP + - 'CLIP'输出提供了检查点中的上下文语言嵌入,便于在应用中实现高级语言模型功能。 + - Comfy dtype: CLIP + - Python dtype: Any +- VAE + - 'VAE'输出代表了从检查点检索的变分自编码器组件,这对于涉及生成模型或降维任务至关重要。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- modelname + - 'modelname'输出返回解析后的检查点名称,这对于记录、识别或作为需要模型名称的其他节点的输入非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Checkpoint_Loader_Model_Name: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (folder_paths.get_filename_list('checkpoints'),)}} + RETURN_TYPES = ('MODEL', 'CLIP', 'VAE', 'STRING') + RETURN_NAMES = ('MODEL', 'CLIP', 'VAE', 'modelname') + FUNCTION = 'load_checkpoint' + CATEGORY = 'WLSH Nodes/loaders' + + def load_checkpoint(self, ckpt_name, output_vae=True, output_clip=True): + ckpt_path = folder_paths.get_full_path('checkpoints', ckpt_name) + name = self.parse_name(ckpt_name) + out = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths('embeddings')) + new_out = list(out) + new_out.pop() + new_out.append(name) + out = tuple(new_out) + return out + + def parse_name(self, ckpt_name): + path = ckpt_name + filename = path.split('/')[-1] + filename = filename.split('.')[:-1] + filename = '.'.join(filename) + return filename +``` \ No newline at end of file diff --git a/docs/Checkpoint Loader.md b/docs/Checkpoint Loader.md new file mode 100644 index 0000000..9709360 --- /dev/null +++ b/docs/Checkpoint Loader.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: WAS_Checkpoint_Loader +- Category: WAS Suite/Loaders/Advanced +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 `load_checkpoint` 旨在高效地检索和加载指定检查点的预训练模型、CLIP模型和VAE模型。它是初始化复杂机器学习架构及其相应配置和权重的工作流程中的关键组成部分。 + +# Input types +## Required +- config_name + - 参数 `config_name` 至关重要,因为它标识了模型所需的特定配置设置。它确保在加载过程中应用正确的模型架构和超参数。 + - Comfy dtype: str + - Python dtype: str +- ckpt_name + - 参数 `ckpt_name` 对于定位包含模型学习权重的检查点文件至关重要。它是一个关键输入,指导加载过程到模型的正确权重集。 + - Comfy dtype: str + - Python dtype: str +## Optional +- output_vae + - 标志 `output_vae` 决定是否应该加载模型的变分自编码器(VAE)组件。它根据手头任务的具体需求提供加载过程中的灵活性。 + - Comfy dtype: bool + - Python dtype: bool +- output_clip + - 标志 `output_clip` 控制 CLIP 模型组件的加载。它允许根据应用或分析的需求选择性地加载模型部件。 + - Comfy dtype: bool + - Python dtype: bool + +# Output types +- MODEL + - 输出 `MODEL` 提供了加载的模型架构。它非常重要,因为它代表了进一步处理或推理任务所需的核心组件。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- CLIP + - 当请求时,输出 `CLIP` 提供了 CLIP 模型组件。对于涉及文本到图像或图像到文本功能的任务,它是必不可少的部分。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- VAE + - 如果指定,输出 `VAE` 包括模型的变分自编码器部分。对于需要生成能力或潜在空间操作的任务,它是至关重要的。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- NAME_STRING + - 输出 `NAME_STRING` 返回没有文件扩展名的检查点的基本名称。它作为检查点的标识符,对于日志记录或记录保存目的非常有用。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Checkpoint_Loader: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'config_name': (comfy_paths.get_filename_list('configs'),), 'ckpt_name': (comfy_paths.get_filename_list('checkpoints'),)}} + RETURN_TYPES = ('MODEL', 'CLIP', 'VAE', TEXT_TYPE) + RETURN_NAMES = ('MODEL', 'CLIP', 'VAE', 'NAME_STRING') + FUNCTION = 'load_checkpoint' + CATEGORY = 'WAS Suite/Loaders/Advanced' + + def load_checkpoint(self, config_name, ckpt_name, output_vae=True, output_clip=True): + config_path = comfy_paths.get_full_path('configs', config_name) + ckpt_path = comfy_paths.get_full_path('checkpoints', ckpt_name) + out = comfy.sd.load_checkpoint(config_path, ckpt_path, output_vae=True, output_clip=True, embedding_directory=comfy_paths.get_folder_paths('embeddings')) + return (out[0], out[1], out[2], os.path.splitext(os.path.basename(ckpt_name))[0]) +``` \ No newline at end of file diff --git a/docs/CheckpointHash.md b/docs/CheckpointHash.md new file mode 100644 index 0000000..72923e5 --- /dev/null +++ b/docs/CheckpointHash.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: CheckpointHash +- Category: Mikey/Loaders +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +CheckpointHash 节点旨在为指定的检查点文件生成和检索加密哈希。它通过哈希其内容来确保检查点的完整性和唯一性。此节点在加载过程中验证检查点的真实性方面发挥着关键作用。 + +# Input types +## Required +- ckpt_name + - 检查点名称是一个关键参数,用于识别将要生成哈希的特定检查点文件。它用于在检查点目录中匹配文件。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- extra_pnginfo + - 与PNG文件格式相关的额外信息,可能用于检查点之外的额外处理或元数据存储。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Any +- prompt + - prompt 对象用于存储和检索与检查点相关的信息,例如唯一标识符和计算出的哈希,以便在工作流程中后续使用。 + - Comfy dtype: PROMPT + - Python dtype: Dict[str, Dict[str, Any]] +- unique_id + - 检查点的唯一标识符,可用于在系统中跟踪和引用检查点。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- ckpt_hash + - 检查点文件的加密哈希确保了其完整性,并作为验证的手段。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CheckpointHash: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': ('STRING', {'forceInput': True})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('ckpt_hash',) + FUNCTION = 'get_hash' + CATEGORY = 'Mikey/Loaders' + + def get_hash(self, ckpt_name, extra_pnginfo, prompt, unique_id): + file_list = folder_paths.get_filename_list('checkpoints') + matching_file = [s for s in file_list if ckpt_name in s][0] + ckpt_path = folder_paths.get_full_path('checkpoints', matching_file) + hash = get_file_hash(ckpt_path) + ckpt_name = os.path.basename(ckpt_name) + prompt.get(str(unique_id))['inputs']['output_ckpt_hash'] = hash + prompt.get(str(unique_id))['inputs']['output_ckpt_name'] = ckpt_name + return (get_file_hash(ckpt_path),) +``` \ No newline at end of file diff --git a/docs/CheckpointLoaderSimpleShared %2F%2FInspire.md b/docs/CheckpointLoaderSimpleShared %2F%2FInspire.md new file mode 100644 index 0000000..86d558a --- /dev/null +++ b/docs/CheckpointLoaderSimpleShared %2F%2FInspire.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: CheckpointLoaderSimpleShared +- Category: InspirePack/Backend +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点便于检索和缓存模型检查点,确保高效访问模型同时最小化不必要的加载操作。通过智能管理基于提供键和检查点名称的缓存,它简化了模型使用流程。 + +# Input types +## Required +- ckpt_name + - 检查点名称对于识别要加载的特定模型至关重要。它在缓存系统中作为唯一参考,允许节点检索或存储相应的模型数据。 + - Comfy dtype: COMBO[folder_paths.get_filename_list('checkpoints'),] + - Python dtype: Union[str, None] +## Optional +- key_opt + - 这个可选参数允许用户指定一个自定义键来缓存检查点。如果不提供,则默认使用检查点名称,提供了缓存组织和访问方式的灵活性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- model + - 模型输出代表已加载的机器学习或深度学习模型,准备进行进一步的处理或推理。它是节点功能的核心组成部分,使得下游任务成为可能。 + - Comfy dtype: ANY + - Python dtype: Any +- clip + - clip输出与特定模型组件相关联,通常用于辅助任务或额外处理。它补充了主模型输出,增强了节点的整体能力。 + - Comfy dtype: ANY + - Python dtype: Any +- vae + - VAE,即变分自编码器,是一种生成模型,可能由该节点加载。它在根据学习到的分布生成新的数据点或特征方面发挥着重要作用。 + - Comfy dtype: ANY + - Python dtype: Any +- cache_key + - 缓存键是用于在系统中引用缓存的检查点的唯一标识符。对于缓存机制内检查点的管理和检索至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CheckpointLoaderSimpleShared(nodes.CheckpointLoaderSimple): + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (folder_paths.get_filename_list('checkpoints'),), 'key_opt': ('STRING', {'multiline': False, 'placeholder': "If empty, use 'ckpt_name' as the key."})}} + RETURN_TYPES = ('MODEL', 'CLIP', 'VAE', 'STRING') + RETURN_NAMES = ('model', 'clip', 'vae', 'cache key') + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Backend' + + def doit(self, ckpt_name, key_opt): + if key_opt.strip() == '': + key = ckpt_name + else: + key = key_opt.strip() + if key not in cache: + res = self.load_checkpoint(ckpt_name) + cache[key] = ('ckpt', (False, res)) + print(f"[Inspire Pack] CheckpointLoaderSimpleShared: Ckpt '{ckpt_name}' is cached to '{key}'.") + else: + (_, (_, res)) = cache[key] + print(f"[Inspire Pack] CheckpointLoaderSimpleShared: Cached ckpt '{key}' is loaded. (Loading skip)") + (model, clip, vae) = res + return (model, clip, vae, key) +``` \ No newline at end of file diff --git a/docs/ChromaticAberration.md b/docs/ChromaticAberration.md new file mode 100644 index 0000000..7ae9666 --- /dev/null +++ b/docs/ChromaticAberration.md @@ -0,0 +1,75 @@ +# Documentation +- Class name: ChromaticAberration +- Category: postprocessing/Effects +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +该节点模拟图像的色差效果,通过水平或垂直移动颜色通道来改变感知颜色,从而创建逼真的失真效果。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它作为施加色差效果的基础。它是决定输出视觉效果的主要输入。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- red_shift + - red_shift参数调整红色通道的水平或垂直位置,有助于整体色差效果的产生。 + - Comfy dtype: INT + - Python dtype: int +- green_shift + - green_shift参数影响绿色通道的位置,增强或修改色差效果以达到预期的视觉影响。 + - Comfy dtype: INT + - Python dtype: int +- blue_shift + - blue_shift参数控制蓝色通道的位移,这对于创建令人信服的色差效果至关重要。 + - Comfy dtype: INT + - Python dtype: int +- red_direction + - red_direction参数指定红色通道移动的方向,水平或垂直,以达到预期的色差效果。 + - Comfy dtype: COMBO + - Python dtype: str +- green_direction + - green_direction参数决定了绿色通道移动的方向,这对于准确模拟色差至关重要。 + - Comfy dtype: COMBO + - Python dtype: str +- blue_direction + - blue_direction参数规定了蓝色通道移动的方向,有助于整体色差效果的产生。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- output + - 输出参数代表应用了色差效果的最终图像,展示了节点操作的视觉影响。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ChromaticAberration: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'red_shift': ('INT', {'default': 0, 'min': -20, 'max': 20, 'step': 1}), 'red_direction': (['horizontal', 'vertical'],), 'green_shift': ('INT', {'default': 0, 'min': -20, 'max': 20, 'step': 1}), 'green_direction': (['horizontal', 'vertical'],), 'blue_shift': ('INT', {'default': 0, 'min': -20, 'max': 20, 'step': 1}), 'blue_direction': (['horizontal', 'vertical'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'chromatic_aberration' + CATEGORY = 'postprocessing/Effects' + + def chromatic_aberration(self, image: torch.Tensor, red_shift: int, green_shift: int, blue_shift: int, red_direction: str, green_direction: str, blue_direction: str): + + def get_shift(direction, shift): + shift = -shift if direction == 'vertical' else shift + return (shift, 0) if direction == 'vertical' else (0, shift) + x = image.permute(0, 3, 1, 2) + shifts = [get_shift(direction, shift) for (direction, shift) in zip([red_direction, green_direction, blue_direction], [red_shift, green_shift, blue_shift])] + channels = [torch.roll(x[:, i, :, :], shifts=shifts[i], dims=(1, 2)) for i in range(3)] + output = torch.stack(channels, dim=1) + output = output.permute(0, 2, 3, 1) + return (output,) +``` \ No newline at end of file diff --git a/docs/CinematicLook.md b/docs/CinematicLook.md new file mode 100644 index 0000000..e00abc6 --- /dev/null +++ b/docs/CinematicLook.md @@ -0,0 +1,89 @@ +# Documentation +- Class name: CinematicLook +- Category: Mikey/Image +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +CinematicLook节点旨在通过应用各种风格化调整来提升图像的视觉吸引力,模仿常见于电影和专业摄影作品中的高质量外观。该节点利用颜色分级和其他视觉效果将普通图像转变为具有电影质感的图像,适用于从专业作品集到社交媒体帖子的广泛用途。 + +# Input types +## Required +- image + - 图像参数是节点处理的源素材。它至关重要,因为它作为所有后续转换和增强的基础。输入图像的质量和特性直接影响最终输出,影响整体的审美和视觉冲击力。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- look + - 外观参数决定了图像转换的风格方向。它在确定处理后图像的最终视觉色调和情绪上至关重要。不同的外观满足不同的创意愿景和应用,允许得到与期望的审美相一致的定制结果。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- result_img + - result_img输出是应用了电影外观的转换后的图像。它代表了节点处理的成果,包含了对输入图像所做的风格增强和调整。这是创意工作流中准备使用或进一步处理的最终产品。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CinematicLook: + + @classmethod + def INPUT_TYPES(s): + s.haldclut_files = read_cluts() + s.file_names = [os.path.basename(f) for f in s.haldclut_files] + return {'required': {'image': ('IMAGE', {'default': None}), 'look': (['modern', 'retro', 'clipped', 'broadcast', 'black and white', 'black and white - warm'],)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('result_img',) + FUNCTION = 'cinematic_look' + CATEGORY = 'Mikey/Image' + + def apply_haldclut(self, image, hald_clut, gamma_correction): + hald_img = Image.open(self.haldclut_files[self.file_names.index(hald_clut)]) + img = tensor2pil(image) + if gamma_correction == 'True': + corrected_img = gamma_correction_pil(img, 1.0 / 2.2) + else: + corrected_img = img + filtered_image = apply_hald_clut(hald_img, corrected_img).convert('RGB') + return filtered_image + + @apply_to_batch + def cinematic_look(self, image, look): + if look == 'modern': + image = self.apply_haldclut(image, 'modern.png', 'False') + elif look == 'retro': + image = self.apply_haldclut(image, 'retro.png', 'False') + elif look == 'clipped': + image = self.apply_haldclut(image, 'clipped.png', 'False') + elif look == 'broadcast': + image = self.apply_haldclut(image, 'broadcast.png', 'False') + elif look == 'black and white': + image = self.apply_haldclut(image, 'bw.png', 'False') + elif look == 'black and white - warm': + image = self.apply_haldclut(image, 'bw_warm.png', 'False') + p = os.path.dirname(os.path.realpath(__file__)) + if look in ['black and white']: + noise_img = os.path.join(p, 'noise_bw.png') + else: + noise_img = os.path.join(p, 'noise.png') + noise = Image.open(noise_img) + IO = ImageOverlay() + image = pil2tensor(image) + noise = pil2tensor(noise) + if look == 'modern': + image = IO.overlay(image, noise, 0.3)[0] + if look == 'retro': + image = IO.overlay(image, noise, 0.4)[0] + if look == 'clipped': + image = IO.overlay(image, noise, 0.25)[0] + if look == 'broadcast': + image = IO.overlay(image, noise, 0.3)[0] + if look == 'black and white': + image = IO.overlay(image, noise, 0.25)[0] + if look == 'black and white - warm': + image = IO.overlay(image, noise, 0.25)[0] + return image +``` \ No newline at end of file diff --git a/docs/Circular VAEDecode.md b/docs/Circular VAEDecode.md new file mode 100644 index 0000000..304948f --- /dev/null +++ b/docs/Circular VAEDecode.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: CircularVAEDecode +- Category: latent +- Output node: False +- Repo Ref: https://github.com/FlyingFireCo/tiled_ksampler.git + +CircularVAEDecode节点旨在使用变分自编码器(VAE)将潜在表示解码回图像。它特别将VAE中卷积层的填充模式修改为'circular',这有助于处理边缘效应,特别适用于图像生成任务。节点的主要功能是将潜在空间数据转换为视觉格式,便于解释和可视化编码信息。 + +# Input types +## Required +- samples + - 'samles'参数至关重要,因为它保存了节点将解码成图像的潜在表示。这是一个强制性输入,直接影响节点的输出,决定了生成图像的质量和特性。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- vae + - 'vae'参数代表变分自编码器模型,节点将使用该模型来解码潜在样本。这是一个必要的输入,决定了解码过程的结构和功能方面。 + - Comfy dtype: VAE + - Python dtype: comfy.sd.VAE + +# Output types +- image + - 'image'输出是节点的主要结果,代表从潜在样本生成的解码图像。它标志着潜在空间数据成功转换为人类可解释的视觉格式。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CircularVAEDecode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'samples': ('LATENT',), 'vae': ('VAE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'decode' + CATEGORY = 'latent' + + def decode(self, vae, samples): + for layer in [layer for layer in vae.first_stage_model.modules() if isinstance(layer, torch.nn.Conv2d)]: + layer.padding_mode = 'circular' + return (vae.decode(samples['samples']),) +``` \ No newline at end of file diff --git a/docs/CircularVAEDecode(jags111%2FComfyUI_Jags_VectorMagic).md b/docs/CircularVAEDecode(jags111%2FComfyUI_Jags_VectorMagic).md new file mode 100644 index 0000000..fa0b48e --- /dev/null +++ b/docs/CircularVAEDecode(jags111%2FComfyUI_Jags_VectorMagic).md @@ -0,0 +1,44 @@ +# Documentation +- Class name: CircularVAEDecode +- Category: Jags_vector/latent +- Output node: False +- Repo Ref: https://github.com/jags111/ComfyUI_Jags_VectorMagic + +该节点通过为变分自编码器(VAE)的解码过程准备模型的卷积层以处理循环填充,确保生成的图像在边界处保持一致性。 + +# Input types +## Required +- samples + - 输入样本代表VAE编码器的潜在向量,这对于生成图像至关重要。它驱动整个解码过程,并直接影响输出图像的质量和特征。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- vae + - VAE参数指的是用于将潜在样本解码成图像的变分自编码器模型。它对于节点的功能至关重要,因为它封装了学习到的数据分布。 + - Comfy dtype: VAE + - Python dtype: comfy.sd.VAE + +# Output types +- image + - 输出图像是使用VAE模型解码输入潜在样本的结果。它代表了编码数据的视觉表现,是节点操作的直接产物。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CircularVAEDecode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'samples': ('LATENT',), 'vae': ('VAE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'decode' + CATEGORY = 'Jags_vector/latent' + + def decode(self, vae, samples): + for layer in [layer for layer in vae.first_stage_model.modules() if isinstance(layer, torch.nn.Conv2d)]: + layer.padding_mode = 'circular' + return (vae.decode(samples['samples']),) +``` \ No newline at end of file diff --git a/docs/CircularVAEDecode.md b/docs/CircularVAEDecode.md new file mode 100644 index 0000000..208b640 --- /dev/null +++ b/docs/CircularVAEDecode.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: CircularVAEDecode +- Category: latent +- Output node: False +- Repo Ref: https://github.com/spinagon/ComfyUI-seamless-tiling + +CircularVAEDecode节点旨在执行变分自编码器(VAE)的解码过程,并能够对卷积层应用循环填充,以增强生成图像的平铺特性。该节点旨在通过考虑输入数据的空间周期性来提高解码图像的连贯性和视觉质量。 + +# Input types +## Required +- samples + - “samples”参数至关重要,因为它提供了节点用于重构图像的潜在表示。这是一个关键的输入,直接影响节点的输出,决定了生成图像的质量和特性。 + - Comfy dtype: LATENT + - Python dtype: Tensor +- vae + - “vae”参数代表预训练的VAE模型,节点使用它来执行解码过程。它是节点操作的基本组成部分,因为模型的架构和训练直接影响节点生成高质量图像的能力。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- tiling + - “tiling”参数控制VAE模型中卷积层循环填充的应用,这可以显著影响生成图像的平铺特性。它允许根据输出图像的期望特性定制节点的行为。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- IMAGE + - CircularVAEDecode节点的输出是通过解码提供的潜在表示生成的图像。这个图像是节点操作的直接结果,反映了VAE模型和所选平铺参数在重构图像方面的有效性。 + - Comfy dtype: IMAGE + - Python dtype: Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class CircularVAEDecode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'samples': ('LATENT',), 'vae': ('VAE',), 'tiling': (['enable', 'x_only', 'y_only', 'disable'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'decode' + CATEGORY = 'latent' + + def decode(self, samples, vae, tiling): + vae_copy = copy.deepcopy(vae) + if tiling == 'enable': + make_circular_asymm(vae_copy.first_stage_model, True, True) + elif tiling == 'x_only': + make_circular_asymm(vae_copy.first_stage_model, True, False) + elif tiling == 'y_only': + make_circular_asymm(vae_copy.first_stage_model, False, True) + else: + make_circular_asymm(vae_copy.first_stage_model, False, False) + result = (vae_copy.decode(samples['samples']),) + return result +``` \ No newline at end of file diff --git a/docs/CkptNames_.md b/docs/CkptNames_.md new file mode 100644 index 0000000..3e34110 --- /dev/null +++ b/docs/CkptNames_.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: CreateCkptNames +- Category: ♾️Mixlab/Utils +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点促进了机器学习项目中检查点名称的组织和管理,使用户能够处理和筛选检查点名称列表,以进行进一步的分析或恢复。 + +# Input types +## Required +- ckpt_names + - 输入参数是检查点名称的字符串,对于节点识别和处理检查点至关重要。它通过确定被过滤和组织的内容来影响节点的操作。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- ckpt_names + - 输出是处理过的检查点名称列表,对于进一步的操作如加载特定检查点或分析其分布具有重要意义。 + - Comfy dtype: LIST[STRING] + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CreateCkptNames: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'ckpt_names': ('STRING', {'multiline': True, 'default': '\n'.join(folder_paths.get_filename_list('checkpoints')), 'dynamicPrompts': False})}} + RETURN_TYPES = (any_type,) + RETURN_NAMES = ('ckpt_names',) + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (True,) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Utils' + + def run(self, ckpt_names): + ckpt_names = ckpt_names.split('\n') + ckpt_names = [name for name in ckpt_names if name.strip()] + return (ckpt_names,) +``` \ No newline at end of file diff --git a/docs/Color Correct (mtb).md b/docs/Color Correct (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Color.md b/docs/Color.md new file mode 100644 index 0000000..20b3cff --- /dev/null +++ b/docs/Color.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: ColorInput +- Category: ♾️Mixlab/Utils +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点便于处理和提取输入颜色信息,并以结构化格式提供颜色组成部分的详细分析。 + +# Input types +## Required +- color + - 颜色参数对于节点的运行至关重要,因为它是颜色分析的主要数据来源。 + - Comfy dtype: TCOLOR + - Python dtype: Dict[str, Union[str, int]] + +# Output types +- hex + - 十六进制输出代表十六进制颜色代码,是网页和图形设计中的标准表示方法。 + - Comfy dtype: STRING + - Python dtype: str +- r + - r输出表示颜色的红色分量,对整体色调和饱和度有贡献。 + - Comfy dtype: INT + - Python dtype: int +- g + - g输出表示绿色分量,影响颜色的中间色调。 + - Comfy dtype: INT + - Python dtype: int +- b + - b输出对应蓝色分量,影响颜色的冷度或暖度。 + - Comfy dtype: INT + - Python dtype: int +- a + - a输出代表alpha通道,指示颜色的透明度级别。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ColorInput: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'color': ('TCOLOR',)}} + RETURN_TYPES = ('STRING', 'INT', 'INT', 'INT', 'FLOAT') + RETURN_NAMES = ('hex', 'r', 'g', 'b', 'a') + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Utils' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False, False, False, False, False) + + def run(self, color): + h = color['hex'] + r = color['r'] + g = color['g'] + b = color['b'] + a = color['a'] + return (h, r, g, b, a) +``` \ No newline at end of file diff --git a/docs/ColorAdjust(FaceParsing).md b/docs/ColorAdjust(FaceParsing).md new file mode 100644 index 0000000..c166e56 --- /dev/null +++ b/docs/ColorAdjust(FaceParsing).md @@ -0,0 +1,73 @@ +# Documentation +- Class name: ColorAdjust +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +ColorAdjust 节点旨在通过调整图像的对比度、亮度、饱和度、色相和伽马值来修改图像的视觉特征。该节点增强了图像的外观,并可用于纠正或为各种应用风格化视觉输出。 + +# Input types +## Required +- image + - 图像参数对于 ColorAdjust 节点至关重要,因为它是将要进行颜色调整的输入。它通过确定节点将处理的基本视觉内容来影响执行。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- contrast + - 对比度参数允许用户增加或减少图像中最暗和最亮元素之间的差异。它在增强图像的视觉清晰度和深度方面起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- brightness + - 亮度调整可以使图像看起来更明亮或更暗,这由亮度参数控制。它对于改变视觉内容的整体亮度或暗度至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- saturation + - 饱和度参数控制图像中颜色的强度。对于想要实现更鲜艳或更柔和的调色板的用户来说,它很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- hue + - 调整色相会使图像中的颜色向色谱的不同部分移动。这个参数在改变视觉内容的整体色调方面起着关键作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- gamma + - 伽马参数影响图像的整体亮度。它特别适用于以非线性方式调整图像的感知亮度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- result + - 结果参数代表 ColorAdjust 节点的输出,即应用了颜色调整的修改后的图像。它很重要,因为它反映了节点处理的最终视觉结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ColorAdjust: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'contrast': ('FLOAT', {'default': 1.0, 'min': 0, 'max': 255, 'step': 0.01, 'round': 0.001, 'display': 'number'}), 'brightness': ('FLOAT', {'default': 1.0, 'min': -255, 'max': 255, 'step': 0.01, 'round': 0.001, 'display': 'number'}), 'saturation': ('FLOAT', {'default': 1.0, 'min': 0, 'max': 255, 'step': 0.01, 'round': 0.001, 'display': 'number'}), 'hue': ('FLOAT', {'default': 0, 'min': -0.5, 'max': 0.5, 'step': 0.001, 'round': 0.001, 'display': 'number'}), 'gamma': ('FLOAT', {'default': 1.0, 'min': 0, 'max': 255, 'step': 0.01, 'round': 0.001, 'display': 'number'})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, image: Tensor, contrast: float=1, brightness: float=1, saturation: float=1, hue: float=0, gamma: float=1): + permutedImage = image.permute(0, 3, 1, 2) + if contrast != 1: + permutedImage = functional.adjust_contrast(permutedImage, contrast) + if brightness != 1: + permutedImage = functional.adjust_brightness(permutedImage, brightness) + if saturation != 1: + permutedImage = functional.adjust_saturation(permutedImage, saturation) + if hue != 0: + permutedImage = functional.adjust_hue(permutedImage, hue) + if gamma != 1: + permutedImage = functional.adjust_gamma(permutedImage, gamma) + result = permutedImage.permute(0, 2, 3, 1) + return (result,) +``` \ No newline at end of file diff --git a/docs/ColorCorrect(EllangoK%2FComfyUI-post-processing-nodes).md b/docs/ColorCorrect(EllangoK%2FComfyUI-post-processing-nodes).md new file mode 100644 index 0000000..50566db --- /dev/null +++ b/docs/ColorCorrect(EllangoK%2FComfyUI-post-processing-nodes).md @@ -0,0 +1,98 @@ +# Documentation +- Class name: ColorCorrect +- Category: postprocessing/Color Adjustments +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +ColorCorrect节点旨在调整图像的颜色属性,增强其视觉吸引力并纠正颜色不平衡。它通过调整温度、色调、亮度、对比度、饱和度和伽马等不同方面来实现期望的外观,提高图像质量并确保一组图像间的一致性。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它是节点颜色校正过程的主要输入。它是所有调整的基础,其特征直接影响最终输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- temperature + - 温度参数用于调整图像的颜色调,模拟更暖或更冷的颜色效果。它在设定图像的情绪和整体外观方面起着重要作用,有助于图像的视觉叙事。 + - Comfy dtype: FLOAT + - Python dtype: float +- hue + - 色调参数改变图像的颜色谱,允许在不改变亮度或饱和度的情况下改变主导颜色。它影响图像的整体颜色平衡,并可用于匹配期望的审美。 + - Comfy dtype: FLOAT + - Python dtype: float +- brightness + - 亮度参数控制图像的整体亮度水平。通过调整这个参数,节点可以纠正曝光不足或过度曝光的问题,确保图像的细节清晰可见且平衡良好。 + - Comfy dtype: FLOAT + - Python dtype: float +- contrast + - 对比度参数调整图像最亮和最暗部分之间的差异,增强视觉冲击力和深度。它对于使图像更加突出和引人注目至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- saturation + - 饱和度参数增强或减少图像中颜色的活力。它对于达到期望的颜色丰富度水平很重要,并且可以显著改变图像的情绪。 + - Comfy dtype: FLOAT + - Python dtype: float +- gamma + - 伽马参数调整图像的整体色调范围,影响中间调和阴影的渲染。它对于实现自然和视觉上令人愉悦的颜色校正至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- image + - 输出图像是颜色校正过程的结果,反映了对输入图像进行的所有调整。它代表了最终产品,展示了增强的视觉吸引力和纠正的颜色平衡。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ColorCorrect: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'temperature': ('FLOAT', {'default': 0, 'min': -100, 'max': 100, 'step': 5}), 'hue': ('FLOAT', {'default': 0, 'min': -90, 'max': 90, 'step': 5}), 'brightness': ('FLOAT', {'default': 0, 'min': -100, 'max': 100, 'step': 5}), 'contrast': ('FLOAT', {'default': 0, 'min': -100, 'max': 100, 'step': 5}), 'saturation': ('FLOAT', {'default': 0, 'min': -100, 'max': 100, 'step': 5}), 'gamma': ('FLOAT', {'default': 1, 'min': 0.2, 'max': 2.2, 'step': 0.1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'color_correct' + CATEGORY = 'postprocessing/Color Adjustments' + + def color_correct(self, image: torch.Tensor, temperature: float, hue: float, brightness: float, contrast: float, saturation: float, gamma: float): + (batch_size, height, width, _) = image.shape + result = torch.zeros_like(image) + brightness /= 100 + contrast /= 100 + saturation /= 100 + temperature /= 100 + brightness = 1 + brightness + contrast = 1 + contrast + saturation = 1 + saturation + for b in range(batch_size): + tensor_image = image[b].numpy() + modified_image = Image.fromarray((tensor_image * 255).astype(np.uint8)) + modified_image = ImageEnhance.Brightness(modified_image).enhance(brightness) + modified_image = ImageEnhance.Contrast(modified_image).enhance(contrast) + modified_image = np.array(modified_image).astype(np.float32) + if temperature > 0: + modified_image[:, :, 0] *= 1 + temperature + modified_image[:, :, 1] *= 1 + temperature * 0.4 + elif temperature < 0: + modified_image[:, :, 2] *= 1 - temperature + modified_image = np.clip(modified_image, 0, 255) / 255 + modified_image = np.clip(np.power(modified_image, gamma), 0, 1) + hls_img = cv2.cvtColor(modified_image, cv2.COLOR_RGB2HLS) + hls_img[:, :, 2] = np.clip(saturation * hls_img[:, :, 2], 0, 1) + modified_image = cv2.cvtColor(hls_img, cv2.COLOR_HLS2RGB) * 255 + hsv_img = cv2.cvtColor(modified_image, cv2.COLOR_RGB2HSV) + hsv_img[:, :, 0] = (hsv_img[:, :, 0] + hue) % 360 + modified_image = cv2.cvtColor(hsv_img, cv2.COLOR_HSV2RGB) + modified_image = modified_image.astype(np.uint8) + modified_image = modified_image / 255 + modified_image = torch.from_numpy(modified_image).unsqueeze(0) + result[b] = modified_image + return (result,) +``` \ No newline at end of file diff --git a/docs/ColorTint.md b/docs/ColorTint.md new file mode 100644 index 0000000..2323fcd --- /dev/null +++ b/docs/ColorTint.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: ColorTint +- Category: postprocessing/Color Adjustments +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +ColorTint节点旨在调整图像的颜色色调,增强或改变其视觉吸引力。它根据选择的模式应用颜色晕染,有效地改变图像的情绪和风格。该节点适用于需要进行颜色调整的后期处理任务,以匹配所需的美学或纠正颜色不平衡。 + +# Input types +## Required +- image + - 图像参数是ColorTint节点的主要输入。它是将要进行颜色调整的源图像。图像的质量和特性直接影响最终输出,使其成为实现所需视觉效果的关键组成部分。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- strength + - 强度参数控制应用于图像的颜色晕染效果的强度。它是一个浮点数,决定了颜色变化的显著程度。较高的值会增加效果,而较低的值则使其更为微妙。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- mode + - 模式参数决定了要应用于图像的特定颜色晕染。它提供了多种预设选项,每种选项都创造了独特的视觉风格。模式的选择显著影响处理图像的整体情绪和美学。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- result + - 结果参数是ColorTint节点的输出。它是经过颜色晕染修改的图像,反映了输入设置。这个输出对于继续进一步处理或最终展示至关重要,包含了节点所做的创造性调整。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ColorTint: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 1.0, 'step': 0.1}), 'mode': (['sepia', 'red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'purple', 'orange', 'warm', 'cool', 'lime', 'navy', 'vintage', 'rose', 'teal', 'maroon', 'peach', 'lavender', 'olive'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'color_tint' + CATEGORY = 'postprocessing/Color Adjustments' + + def color_tint(self, image: torch.Tensor, strength: float, mode: str='sepia'): + if strength == 0: + return (image,) + sepia_weights = torch.tensor([0.2989, 0.587, 0.114]).view(1, 1, 1, 3).to(image.device) + mode_filters = {'sepia': torch.tensor([1.0, 0.8, 0.6]), 'red': torch.tensor([1.0, 0.6, 0.6]), 'green': torch.tensor([0.6, 1.0, 0.6]), 'blue': torch.tensor([0.6, 0.8, 1.0]), 'cyan': torch.tensor([0.6, 1.0, 1.0]), 'magenta': torch.tensor([1.0, 0.6, 1.0]), 'yellow': torch.tensor([1.0, 1.0, 0.6]), 'purple': torch.tensor([0.8, 0.6, 1.0]), 'orange': torch.tensor([1.0, 0.7, 0.3]), 'warm': torch.tensor([1.0, 0.9, 0.7]), 'cool': torch.tensor([0.7, 0.9, 1.0]), 'lime': torch.tensor([0.7, 1.0, 0.3]), 'navy': torch.tensor([0.3, 0.4, 0.7]), 'vintage': torch.tensor([0.9, 0.85, 0.7]), 'rose': torch.tensor([1.0, 0.8, 0.9]), 'teal': torch.tensor([0.3, 0.8, 0.8]), 'maroon': torch.tensor([0.7, 0.3, 0.5]), 'peach': torch.tensor([1.0, 0.8, 0.6]), 'lavender': torch.tensor([0.8, 0.6, 1.0]), 'olive': torch.tensor([0.6, 0.7, 0.4])} + scale_filter = mode_filters[mode].view(1, 1, 1, 3).to(image.device) + grayscale = torch.sum(image * sepia_weights, dim=-1, keepdim=True) + tinted = grayscale * scale_filter + result = tinted * strength + image * (1 - strength) + return (result,) +``` \ No newline at end of file diff --git a/docs/Color_Preprocessor_Provider_for_SEGS %2F%2FInspire.md b/docs/Color_Preprocessor_Provider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..63aed2e --- /dev/null +++ b/docs/Color_Preprocessor_Provider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: Color_Preprocessor_Provider_for_SEGS +- Category: InspirePack/SEGS/ControlNet +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +Color_Preprocessor_Provider_for_SEGS 类旨在通过应用颜色预处理技术来增强图像分割任务。该节点智能调整输入图像的颜色属性,以提高分割模型的性能,确保处理后的图像针对后续的分割过程进行了优化。 + +# Input types +## Required +- image + - 图像参数对于 Color_Preprocessor_Provider_for_SEGS 节点至关重要,因为它作为预处理算法的输入。图像的质量和分辨率直接影响预处理的有效性和结果分割的准确性。 + - Comfy dtype: image + - Python dtype: PIL.Image or numpy.ndarray +## Optional +- mask + - 掩码参数虽然是可选的,但可以为预处理步骤提供额外的上下文,允许对图像进行更有针对性的调整。它可以通过专注于图像的特定区域来帮助细化分割过程。 + - Comfy dtype: mask + - Python dtype: numpy.ndarray + +# Output types +- SEGS_PREPROCESSOR + - Color_Preprocessor_Provider_for_SEGS 节点的输出是针对分割任务优化的预处理图像。此输出作为后续分割节点的输入,确保分割过程从增强的颜色属性中受益。 + - Comfy dtype: preprocessor + - Python dtype: numpy.ndarray + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Color_Preprocessor_Provider_for_SEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}} + RETURN_TYPES = ('SEGS_PREPROCESSOR',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/SEGS/ControlNet' + + def doit(self): + obj = Color_Preprocessor_wrapper() + return (obj,) +``` \ No newline at end of file diff --git a/docs/Colored Image (mtb).md b/docs/Colored Image (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Combine Masks.md b/docs/Combine Masks.md new file mode 100644 index 0000000..c2bc76b --- /dev/null +++ b/docs/Combine Masks.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: MaskCombineOp +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +MaskCombineOp节点旨在对两个输入图像执行各种操作,如并集、交集和乘法,以将它们组合成单个图像。它能够处理不同类型的操作以实现所需的视觉效果,这在图像处理和计算机视觉任务中非常有用。 + +# Input types +## Required +- image1 + - 要与另一张图像组合的第一张图像。它在确定节点操作的最终输出中起着关键作用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image2 + - 将与第一张图像组合的第二张图像。对于实现所需的组合效果至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- op + - 要在两张图像上执行的操作。它定义了图像如何组合,是节点功能的关键参数。 + - Comfy dtype: COMBO['union (max)', 'intersection (min)', 'difference', 'multiply', 'multiply_alpha', 'add', 'greater_or_equal', 'greater'] + - Python dtype: str +- clamp_result + - 确定操作后是否应将结果限制在一定范围内。限制可以防止某些操作可能产生的极端值。 + - Comfy dtype: COMBO['yes', 'no'] + - Python dtype: str +- round_result + - 指定操作后是否应将结果四舍五入到最近的整数。四舍五入对于某些类型的图像处理很有用。 + - Comfy dtype: COMBO['no', 'yes'] + - Python dtype: str + +# Output types +- result + - 由节点执行的操作产生的组合图像。它代表了组合过程的视觉结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MaskCombineOp: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image1': ('IMAGE',), 'image2': ('IMAGE',), 'op': (['union (max)', 'intersection (min)', 'difference', 'multiply', 'multiply_alpha', 'add', 'greater_or_equal', 'greater'],), 'clamp_result': (['yes', 'no'],), 'round_result': (['no', 'yes'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'combine' + CATEGORY = 'Masquerade Nodes' + + def combine(self, image1, image2, op, clamp_result, round_result): + (image1, image2) = tensors2common(image1, image2) + if op == 'union (max)': + result = torch.max(image1, image2) + elif op == 'intersection (min)': + result = torch.min(image1, image2) + elif op == 'difference': + result = image1 - image2 + elif op == 'multiply': + result = image1 * image2 + elif op == 'multiply_alpha': + image1 = tensor2rgba(image1) + image2 = tensor2mask(image2) + result = torch.cat((image1[:, :, :, :3], (image1[:, :, :, 3] * image2).unsqueeze(3)), dim=3) + elif op == 'add': + result = image1 + image2 + elif op == 'greater_or_equal': + result = torch.where(image1 >= image2, 1.0, 0.0) + elif op == 'greater': + result = torch.where(image1 > image2, 1.0, 0.0) + if clamp_result == 'yes': + result = torch.min(torch.max(result, torch.tensor(0.0)), torch.tensor(1.0)) + if round_result == 'yes': + result = torch.round(result) + return (result,) +``` \ No newline at end of file diff --git a/docs/CombineMasks_.md b/docs/CombineMasks_.md new file mode 100644 index 0000000..babb297 --- /dev/null +++ b/docs/CombineMasks_.md @@ -0,0 +1,85 @@ +# Documentation +- Class name: CombineMasks +- Category: ♾️Mixlab/Mask +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-CLIPSeg + +CombineMasks是一个旨在将多个掩码张量整合为一个综合掩码的节点,增强了底层数据的表示。该节点不仅合并掩码,还生成如热图和二值叠加等视觉表示,提供了对掩码内容更详细的分析。 + +# Input types +## Required +- input_image + - 输入图像参数至关重要,因为它作为掩码组合过程的基础层。它提供了节点正确叠加和可视化掩码所需的空间上下文。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask_1 + - 第一个掩码是组合过程中不可或缺的组成部分,代表了将与后续掩码一起增强的初始分割信息层。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- mask_2 + - 第二个掩码增加了额外的分割层,有助于提高组合掩码的复杂性和细节。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- mask_3 + - 可选的第三个掩码通过引入更细粒度的细节来进一步细化分割,增强了整体掩码的表示。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- Combined Mask + - 组合掩码是节点的主要输出,代表了所有输入掩码融合为单一、统一表示的结果。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- Heatmap Mask + - 热图掩码可视化了组合分割,提供了彩色表示,增强了分割结果的可解释性和分析。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- BW Mask + - 二值掩码提供了一个简化的黑白视图,强调核心元素,并提供了一个清晰、直接的分析工具。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CombineMasks: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input_image': ('IMAGE',), 'mask_1': ('MASK',), 'mask_2': ('MASK',)}, 'optional': {'mask_3': ('MASK',)}} + CATEGORY = '♾️Mixlab/Mask' + RETURN_TYPES = ('MASK', 'IMAGE', 'IMAGE') + RETURN_NAMES = ('Combined Mask', 'Heatmap Mask', 'BW Mask') + FUNCTION = 'combine_masks' + + def combine_masks(self, input_image: torch.Tensor, mask_1: torch.Tensor, mask_2: torch.Tensor, mask_3: Optional[torch.Tensor]=None) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: + """A method that combines two or three masks into one mask. Takes in tensors and returns the mask as a tensor, as well as the heatmap and binary mask as tensors.""" + if mask_1 is not None: + mask_1 = mask_1.squeeze() + if mask_2 is not None: + mask_2 = mask_2.squeeze() + if mask_3 is not None: + mask_3 = mask_3.squeeze() + print(mask_1.shape, mask_2.shape, mask_3.shape) + combined_mask = mask_1 + mask_2 + mask_3 if mask_3 is not None else mask_1 + mask_2 + image_np = tensor_to_numpy(input_image) + heatmap = apply_colormap(combined_mask, cm.viridis) + binary_mask = apply_colormap(combined_mask, cm.Greys_r) + dimensions = (image_np.shape[1], image_np.shape[0]) + if dimensions is None or dimensions[0] == 0 or dimensions[1] == 0: + raise ValueError('Invalid dimensions') + heatmap_resized = resize_image(heatmap, dimensions) + binary_mask_resized = resize_image(binary_mask, dimensions) + (alpha_heatmap, alpha_binary) = (0.5, 1) + overlay_heatmap = overlay_image(image_np, heatmap_resized, alpha_heatmap) + overlay_binary = overlay_image(image_np, binary_mask_resized, alpha_binary) + image_out_heatmap = numpy_to_tensor(overlay_heatmap) + image_out_binary = numpy_to_tensor(overlay_binary) + return (combined_mask, image_out_heatmap, image_out_binary) +``` \ No newline at end of file diff --git a/docs/CombineRegionalPrompts.md b/docs/CombineRegionalPrompts.md new file mode 100644 index 0000000..bf35556 --- /dev/null +++ b/docs/CombineRegionalPrompts.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: CombineRegionalPrompts +- Category: ImpactPack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +CombineRegionalPrompts节点旨在将多组区域提示合并为一个统一的集合。它在简化区域数据输入流程中发挥关键作用,确保所有相关的提示都能高效地聚合在一起,没有冗余,从而促进对区域信息进行更连贯和全面的分析。 + +# Input types +## Required +- regional_prompts1 + - regional_prompts1参数对于CombineRegionalPrompts节点至关重要,因为它是主要输入,包含需要合并的区域提示。它对节点的执行至关重要,因为聚合提示的质量和相关性直接影响后续的分析和结果。 + - Comfy dtype: REGIONAL_PROMPTS + - Python dtype: List[str] + +# Output types +- combined_prompts + - combined_prompts输出参数代表将多个区域提示合并为一个连贯列表的结果。这个输出很重要,因为它为ImpactPack/Regional类别内的进一步处理和分析奠定了基础,确保合并后的数据可供后续操作使用。 + - Comfy dtype: REGIONAL_PROMPTS + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CombineRegionalPrompts: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'regional_prompts1': ('REGIONAL_PROMPTS',)}} + RETURN_TYPES = ('REGIONAL_PROMPTS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Regional' + + def doit(self, **kwargs): + res = [] + for (k, v) in kwargs.items(): + res += v + return (res,) +``` \ No newline at end of file diff --git a/docs/ComfyWordCloud.md b/docs/ComfyWordCloud.md new file mode 100644 index 0000000..dccca11 --- /dev/null +++ b/docs/ComfyWordCloud.md @@ -0,0 +1,187 @@ +# Documentation +- Class name: ComfyWordCloud +- Category: 😺dzNodes/WordCloud +- Output node: True +- Repo Ref: https://github.com/chflame163/ComfyUI_WordCloud.git + +ComfyWordCloud节点旨在通过生成词云来可视化文本数据,这是一种在主题上表示输入文本中单词出现频率的图形表示。该节点有助于识别最常见的单词及其在上下文中的重要性,提供了一个可以轻松理解和分析的视觉摘要。 + +# Input types +## Required +- text + - 文本参数是节点的主要输入,包含将要处理以生成词云的文本数据。它非常重要,因为它直接影响词云中单词的内容和分布。 + - Comfy dtype: STRING + - Python dtype: str +- width + - 宽度参数定义了生成的词云图像的宽度,影响视觉表示的布局和缩放。它对于调整画布大小以适应期望的宽高比和显示尺寸很重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度数设置了词云图像的高度,与宽度参数一起决定了输出可视化的整体大小和宽高比。 + - Comfy dtype: INT + - Python dtype: int +- scale + - 比例参数通过按比例增加或减少单词的字体大小来调整词云的整体大小。这对于微调词云的密度和外观至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- margin + - 边距参数指定要在词云图像边缘保留的空白空间量,这可以增强对中心内容的清晰度和关注。 + - Comfy dtype: INT + - Python dtype: int +- font_path + - 字体路径参数对于定义词云中使用的字体样式和特征至关重要。它影响词云内文本的视觉美感和可读性。 + - Comfy dtype: FONT_PATH + - Python dtype: str +- min_font_size + - 最小字体大小参数设置了词云中使用的最小字体大小,确保较少出现的单词以较小的尺寸显示,有助于整体层次结构和对更常见单词的强调。 + - Comfy dtype: INT + - Python dtype: int +- max_font_size + - 最大字体大小参数决定了词云中最大的字体大小,这对于突出出现频率最高的单词和确立文本的视觉显著性至关重要。 + - Comfy dtype: INT + - Python dtype: int +- relative_scaling + - 相对缩放参数根据单词频率调整字体大小缩放,有助于控制词云中对更常见单词的强调程度。 + - Comfy dtype: FLOAT + - Python dtype: float +- colormap + - 色彩映射参数对于定义词云的颜色方案至关重要,影响视觉吸引力和通过颜色变化传达不同单词频率的能力。 + - Comfy dtype: COLOR_MAP + - Python dtype: str +- background_color + - 背景颜色参数设置了词云的背景颜色,对整体视觉对比度和文本的显著性起着作用。 + - Comfy dtype: STRING + - Python dtype: str +- transparent_background + - 透明背景参数决定了词云的背景是否透明,这对于将词云叠加在其他图像或元素上可能很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- prefer_horizontal + - 更优先水平参数影响词云中单词的方向,较高的值促进更水平的分布,这可能会影响整体布局和可读性。 + - Comfy dtype: FLOAT + - Python dtype: float +- max_words + - 最大单词数参数限制了在词云中显示的单词数量,有助于关注最相关和最常见的术语,也会影响可视化的清晰度。 + - Comfy dtype: INT + - Python dtype: int +- repeat + - 重复参数控制一个单词是否可以在词云中出现多次,这可能会影响单词频率的视觉表示和词云的整体密度。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- include_numbers + - 包含数字参数决定是否应该在词云中包含数值,这对于某些类型的文本数据分析可能很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- random_state + - 随机状态参数在词云中单词的定位中引入随机性,这可能导致不同的视觉结果,并增加布局的变化性。 + - Comfy dtype: INT + - Python dtype: int +- stopwords + - 停用词参数允许排除可能不携带重大意义的常见词,从而优化词云以强调更相关的术语。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- color_ref_image + - 颜色参考图像参数使用参考图像来定义词云的颜色板,产生视觉上连贯且与上下文相关的表示。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- mask_image + - 掩码图像参数提供了一个形状或模式,用于限制词云的布局,确保单词位于定义的掩码边界内。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- contour_width + - 轮廓宽度参数调整环绕词云的轮廓的宽度,可以增强词云的定义和与背景的分离。 + - Comfy dtype: FLOAT + - Python dtype: float +- contour_color + - 轮廓颜色参数设置了环绕词云的轮廓的颜色,有助于整体视觉对比度和美感。 + - Comfy dtype: STRING + - Python dtype: str +- keynote_words + - 主题词参数允许指定在词云中应强调的单词,可能突出文本中的关键主题或话题。 + - Comfy dtype: STRING + - Python dtype: str +- keynote_weight + - 主题权重参数调整分配给主题词的权重,影响它们在词云中的显著性和大小。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 图像输出提供了生成的词云,作为输入文本的视觉表示,单词的大小和颜色根据它们的频率和重要性进行调整。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- mask + - 掩码输出是一个二进制表示,勾勒出词云的形状和边界,可以用于进一步的图像处理或分析。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ComfyWordCloud: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + return {'required': {'text': ('STRING', {'default': '', 'multiline': True}), 'width': ('INT', {'default': 512}), 'height': ('INT', {'default': 512}), 'scale': ('FLOAT', {'default': 1, 'min': 0.1, 'max': 1000.0, 'step': 0.01}), 'margin': ('INT', {'default': 0}), 'font_path': (font_list,), 'min_font_size': ('INT', {'default': 4}), 'max_font_size': ('INT', {'default': 128}), 'relative_scaling': ('FLOAT', {'default': 0.5, 'min': 0.01, 'max': 1.0, 'step': 0.01}), 'colormap': (COLOR_MAP,), 'background_color': ('STRING', {'default': '#FFFFFF'}), 'transparent_background': ('BOOLEAN', {'default': True}), 'prefer_horizontal': ('FLOAT', {'default': 0.9, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'max_words': ('INT', {'default': 200}), 'repeat': ('BOOLEAN', {'default': False}), 'include_numbers': ('BOOLEAN', {'default': False}), 'random_state': ('INT', {'default': -1, 'min': -1, 'max': 18446744073709551615}), 'stopwords': ('STRING', {'default': ''})}, 'optional': {'color_ref_image': ('IMAGE',), 'mask_image': ('IMAGE',), 'contour_width': ('FLOAT', {'default': 0, 'min': 0, 'max': 9999, 'step': 0.1}), 'contour_color': ('STRING', {'default': '#000000'}), 'keynote_words': ('STRING', {'default': ''}), 'keynote_weight': ('INT', {'default': 60})}} + RETURN_TYPES = ('IMAGE', 'MASK') + RETURN_NAMES = ('image', 'mask') + FUNCTION = 'wordcloud' + CATEGORY = '😺dzNodes/WordCloud' + OUTPUT_NODE = True + + def wordcloud(self, text, width, height, margin, scale, font_path, min_font_size, max_font_size, relative_scaling, colormap, background_color, transparent_background, prefer_horizontal, max_words, repeat, include_numbers, random_state, stopwords, color_ref_image=None, mask_image=None, contour_width=None, contour_color=None, keynote_words=None, keynote_weight=None): + if text == '': + text = default_text + log(f'text input not found, use demo string.') + freq_dict = WordCloud().process_text(' '.join(jieba.cut(text))) + if not keynote_words == '': + keynote_list = list(re.split('[,,\\s*]', keynote_words)) + keynote_list = [x for x in keynote_list if x != ''] + keynote_dict = {keynote_list[i]: keynote_weight + max(freq_dict.values()) for i in range(len(keynote_list))} + freq_dict.update(keynote_dict) + log(f'word frequencies dict generated, include {len(freq_dict)} words.') + font_path = font_dict[font_path] + if not os.path.exists(font_path): + font_path = os.path.join(os.path.join(os.path.dirname(os.path.dirname(os.path.normpath(__file__))), 'font'), 'Alibaba-PuHuiTi-Heavy.ttf') + log(f'font_path not found, use {font_path}') + else: + log(f'font_path = {font_path}') + stopwords_set = set('') + if not stopwords == '': + stopwords_list = re.split('[,,\\s*]', stopwords) + stopwords_set = set([x for x in stopwords_list if x != '']) + for item in stopwords_set: + if item in freq_dict.keys(): + del freq_dict[item] + bg_color = background_color + mode = 'RGB' + if transparent_background: + bg_color = None + mode = 'RGBA' + if random_state == -1: + random_state = None + mask = None + image_width = width + image_height = height + if not mask_image == None: + p_mask = tensor2pil(mask_image) + mask = np.array(img_whitebackground(p_mask)) + image_width = p_mask.width + image_height = p_mask.height + wc = WordCloud(width=width, height=height, scale=scale, margin=margin, font_path=font_path, min_font_size=min_font_size, max_font_size=max_font_size, relative_scaling=relative_scaling, colormap=colormap, mode=mode, background_color=bg_color, prefer_horizontal=prefer_horizontal, max_words=max_words, repeat=repeat, include_numbers=include_numbers, random_state=random_state, stopwords=stopwords_set, mask=mask, contour_width=contour_width, contour_color=contour_color) + wc.generate_from_frequencies(freq_dict) + if not color_ref_image == None: + p_color_ref_image = tensor2pil(color_ref_image) + p_color_ref_image = p_color_ref_image.resize((image_width, image_height)) + image_colors = ImageColorGenerator(np.array(p_color_ref_image)) + wc.recolor(color_func=image_colors) + ret_image = wc.to_image().convert('RGBA') + ret_mask = getRGBAmask(ret_image) + return (pil2tensor(ret_image), ret_mask) +``` \ No newline at end of file diff --git a/docs/CompositeMotionBrush.md b/docs/CompositeMotionBrush.md new file mode 100644 index 0000000..267f9f4 --- /dev/null +++ b/docs/CompositeMotionBrush.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: CompositeMotionBrush +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +该节点将多个运动层集成到单一的复合层中,应用一种基于预定义模式的混合算法,优先考虑某些运动向量,从而增强整体运动表示。 + +# Input types +## Required +- model + - 模型参数定义了运动层的结构基础,决定了输入运动数据的维度和长度,这对节点的运行至关重要。 + - Comfy dtype: DragNUWA + - Python dtype: DragNUWA +- motion_brush_layer0 + - 该参数代表运动信息的基础层,作为节点混合过程的初始输入,显著影响最终复合运动输出。 + - Comfy dtype: MotionBrush + - Python dtype: MotionBrush +- motion_brush_layer1 + - 次级运动层,在混合过程中提供额外的运动向量供考虑,通过引入新的运动元素影响最终的复合运动。 + - Comfy dtype: MotionBrush + - Python dtype: MotionBrush +- mode + - 该参数决定了节点用于集成运动层的混合策略,默认设置为'override',这决定了如何在最终输出中优先考虑运动向量。 + - Comfy dtype: CompositeMotionBrushMode + - Python dtype: CompositeMotionBrushMode + +# Output types +- results + - 输出代表复合运动层,是根据指定模式混合输入运动层的结果,提供了运动的增强表示。 + - Comfy dtype: MotionBrush + - Python dtype: MotionBrush + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CompositeMotionBrush: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('DragNUWA',), 'motion_brush_layer0': ('MotionBrush',), 'motion_brush_layer1': ('MotionBrush',), 'mode': (CompositeMotionBrushMode, {'default': 'override'})}} + RETURN_TYPES = ('MotionBrush',) + FUNCTION = 'run_inference' + CATEGORY = 'DragNUWA' + + def run_inference(self, model, motion_brush_layer0, motion_brush_layer1, mode): + results = motion_brush_layer0 + for i in range(model.model_length): + for x in range(0, model.width): + masked = False + for y in range(0, model.height): + premasked = masked + masked = False + if abs(float(motion_brush_layer1[i][y][x][0])) > 0.0001 or abs(float(motion_brush_layer1[i][y][x][1])) > 0.0001: + masked = True + elif premasked and y + 1 < model.height: + y1max = model.height + if y + 50 < y1max: + y1max = y + 50 + for y1 in range(y + 1, y1max): + if abs(float(motion_brush_layer1[i][y1][x][0])) > 0.0001 or abs(float(motion_brush_layer1[i][y1][x][1])) > 0.0001: + masked = True + if masked: + results[i][y][x][0] = motion_brush_layer1[i][y][x][0] + results[i][y][x][1] = motion_brush_layer1[i][y][x][1] + else: + results[i][y][x][0] = motion_brush_layer0[i][y][x][0] + results[i][y][x][1] = motion_brush_layer0[i][y][x][1] + return (results,) +``` \ No newline at end of file diff --git a/docs/CompositeMotionBrushWithoutModel.md b/docs/CompositeMotionBrushWithoutModel.md new file mode 100644 index 0000000..b05d25f --- /dev/null +++ b/docs/CompositeMotionBrushWithoutModel.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: CompositeMotionBrushWithoutModel +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +该节点整合两层运动信息以产生复合运动刷效果。它基于定义的操作模式,优先考虑某些层的运动数据融合原则。节点的目的是通过对输入层的合理结合,增强运动表示,创造出连贯且视觉上吸引人的效果。 + +# Input types +## Required +- motion_brush_layer0 + - 第一层运动信息,作为复合效果的基础层。它在建立将与第二层结合进一步细化的运动初始表示中至关重要。 + - Comfy dtype: MotionBrush + - Python dtype: numpy.ndarray +- motion_brush_layer1 + - 第二层运动信息,提供与基础层混合的额外运动线索。它的重要性在于能够引入新的运动元素并调整整体的复合效果。 + - Comfy dtype: MotionBrush + - Python dtype: numpy.ndarray +- mode + - 模式参数决定了两层运动信息如何结合。它在控制最终输出中至关重要,因为它决定了哪些运动元素优先以及它们在复合中如何相互作用。 + - Comfy dtype: CompositeMotionBrushMode + - Python dtype: CompositeMotionBrushMode + +# Output types +- results + - 输出代表最终的复合运动刷,它是根据指定模式对两个输入层的混合。它封装了集成的运动数据,准备进行进一步的处理或可视化。 + - Comfy dtype: MotionBrush + - Python dtype: numpy.ndarray + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CompositeMotionBrushWithoutModel: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'motion_brush_layer0': ('MotionBrush',), 'motion_brush_layer1': ('MotionBrush',), 'mode': (CompositeMotionBrushMode, {'default': 'override'})}} + RETURN_TYPES = ('MotionBrush',) + FUNCTION = 'run_inference' + CATEGORY = 'DragNUWA' + + def run_inference(self, motion_brush_layer0, motion_brush_layer1, mode): + model_length = motion_brush_layer0.shape[0] + height = motion_brush_layer0.shape[1] + width = motion_brush_layer0.shape[2] + results = motion_brush_layer0 + for i in range(model_length): + xmasked = False + for x in range(0, width): + xpremasked = xmasked + xmasked = False + masked = False + for y in range(0, height): + premasked = masked + masked = False + if abs(float(motion_brush_layer1[i][y][x][0])) > 0.0001 or abs(float(motion_brush_layer1[i][y][x][1])) > 0.0001: + masked = True + xmasked = True + elif premasked and y + 1 < height: + y1max = height + if y + 50 < y1max: + y1max = y + 50 + for y1 in range(y + 1, y1max): + if abs(float(motion_brush_layer1[i][y1][x][0])) > 0.0001 or abs(float(motion_brush_layer1[i][y1][x][1])) > 0.0001: + masked = True + xmasked = True + if masked: + results[i][y][x][0] = motion_brush_layer1[i][y][x][0] + results[i][y][x][1] = motion_brush_layer1[i][y][x][1] + else: + if xpremasked and x + 1 < width: + x1max = width + if x + 50 < x1max: + x1max = x + 50 + for x1 in range(x + 1, x1max): + if abs(float(motion_brush_layer1[i][y][x1][0])) > 0.0001 or abs(float(motion_brush_layer1[i][y][x1][1])) > 0.0001: + masked = True + xmasked = True + if masked: + results[i][y][x][0] = motion_brush_layer1[i][y][x][0] + results[i][y][x][1] = motion_brush_layer1[i][y][x][1] + else: + results[i][y][x][0] = motion_brush_layer0[i][y][x][0] + results[i][y][x][1] = motion_brush_layer0[i][y][x][1] + return (results,) +``` \ No newline at end of file diff --git a/docs/Concat Images (mtb).md b/docs/Concat Images (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ConcatConditioningsWithMultiplier %2F%2FInspire.md b/docs/ConcatConditioningsWithMultiplier %2F%2FInspire.md new file mode 100644 index 0000000..a6bf3ed --- /dev/null +++ b/docs/ConcatConditioningsWithMultiplier %2F%2FInspire.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: ConcatConditioningsWithMultiplier +- Category: InspirePack/__for_testing +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +ConcatConditioningsWithMultiplier节点旨在通过将条件输入乘以指定因子来增强它们,允许在复杂工作流中调整条件强度。 + +# Input types +## Required +- conditioning1 + - 主要的条件输入是至关重要的,因为它构成了节点内部后续乘法和连接操作的基础。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +## Optional +- multiplier1 + - 乘数参数对于调整条件输入的强度至关重要,使得节点的输出可以进行微调。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output + - 输出代表增强后的条件数据,它是原始输入与各自乘以因子的附加条件的组合。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Any]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ConcatConditioningsWithMultiplier: + + @classmethod + def INPUT_TYPES(s): + flex_inputs = {} + stack = inspect.stack() + if stack[1].function == 'get_input_data': + for x in range(0, 100): + flex_inputs[f'multiplier{x}'] = ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}) + else: + flex_inputs['multiplier1'] = ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}) + return {'required': {'conditioning1': ('CONDITIONING',)}, 'optional': flex_inputs} + RETURN_TYPES = ('CONDITIONING',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/__for_testing' + + def doit(self, **kwargs): + if 'ConditioningMultiplier_PoP' in nodes.NODE_CLASS_MAPPINGS: + obj = nodes.NODE_CLASS_MAPPINGS['ConditioningMultiplier_PoP']() + else: + utils.try_install_custom_node('https://github.com/picturesonpictures/comfy_PoP', "To use 'ConcatConditioningsWithMultiplier' node, 'comfy_PoP' extension is required.") + raise Exception("'comfy_PoP' node isn't installed.") + conditioning_to = kwargs['conditioning1'] + conditioning_to = obj.multiply_conditioning_strength(conditioning=conditioning_to, multiplier=float(kwargs['multiplier1']))[0] + out = None + for (k, conditioning_from) in kwargs.items(): + if k == 'conditioning1' or not k.startswith('conditioning'): + continue + out = [] + if len(conditioning_from) > 1: + print(f'Warning: ConcatConditioningsWithMultiplier {k} contains more than 1 cond, only the first one will actually be applied to conditioning1.') + mkey = 'multiplier' + k[12:] + multiplier = float(kwargs[mkey]) + conditioning_from = obj.multiply_conditioning_strength(conditioning=conditioning_from, multiplier=multiplier)[0] + cond_from = conditioning_from[0][0] + for i in range(len(conditioning_to)): + t1 = conditioning_to[i][0] + tw = torch.cat((t1, cond_from), 1) + n = [tw, conditioning_to[i][1].copy()] + out.append(n) + conditioning_to = out + if out is None: + return (kwargs['conditioning1'],) + else: + return (out,) +``` \ No newline at end of file diff --git a/docs/ConcatStringSingle.md b/docs/ConcatStringSingle.md new file mode 100644 index 0000000..b6fa16f --- /dev/null +++ b/docs/ConcatStringSingle.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: ConcatStringSingle +- Category: FizzNodes 📅🅕🅝/HelperNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +此节点旨在将两个字符串合并为一个单一的字符串。它作为文本操作中的基础工具,使用户能够无缝地合并文本数据。 + +# Input types +## Required +- string_a + - 要连接的第一个字符串。它在确定最终输出中起着关键作用,因为它构成了组合字符串的初始部分。 + - Comfy dtype: STRING + - Python dtype: str +- string_b + - 要连接的第二个字符串。它很重要,因为它提供了最终输出中跟在第一个字符串后面的字符串部分。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- concatenated_string + - 输出是 'string_a' 和 'string_b' 连接后产生的组合字符串。它代表了合并后的文本数据。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ConcatStringSingle: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'string_a': ('STRING', {'forceInput': True, 'default': '', 'multiline': True}), 'string_b': ('STRING', {'forceInput': True, 'default': '', 'multiline': True})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'concat' + CATEGORY = 'FizzNodes 📅🅕🅝/HelperNodes' + + def concat(self, string_a, string_b): + c = string_a + string_b + return (c,) +``` \ No newline at end of file diff --git a/docs/Conditioning Input Switch.md b/docs/Conditioning Input Switch.md new file mode 100644 index 0000000..25ab826 --- /dev/null +++ b/docs/Conditioning Input Switch.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: WAS_Conditioning_Input_Switch +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 `conditioning_input_switch` 设计用于根据布尔标志有条件地在两个输入条件之间进行选择。它在工作流中充当逻辑开关,允许根据指定的条件动态路由数据,在复杂系统中控制信息流方面至关重要。 + +# Input types +## Required +- conditioning_a + - 参数 'conditioning_a' 表示当布尔标志为真时将被选择的第一个输入条件。它在确定节点输出方面起着关键作用,因为它直接影响系统通过的数据。 + - Comfy dtype: CONDITIONING + - Python dtype: Union[str, comfy.sd.CONDITIONING] +- conditioning_b + - 参数 'conditioning_b' 是当布尔标志为假时将使用的替代输入条件。当条件未满足时,它对于提供数据流的替代路径至关重要,确保节点在处理不同场景时的灵活性。 + - Comfy dtype: CONDITIONING + - Python dtype: Union[str, comfy.sd.CONDITIONING] +## Optional +- boolean + - 参数 'boolean' 作为控制信号,用以决定选择哪个条件输入。当设置为真时,选择 'conditioning_a';当设置为假时,选择 'conditioning_b'。它是一个关键参数,因为它直接决定节点的行为。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- selected_conditioning + - 输出 'selected_conditioning' 表示根据提供的布尔标志选择的输入条件。它非常重要,因为它决定了工作流中的后续步骤和过程,可能影响最终结果。 + - Comfy dtype: CONDITIONING + - Python dtype: Union[str, comfy.sd.CONDITIONING] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Conditioning_Input_Switch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'conditioning_a': ('CONDITIONING',), 'conditioning_b': ('CONDITIONING',), 'boolean': ('BOOLEAN', {'forceInput': True})}} + RETURN_TYPES = ('CONDITIONING',) + FUNCTION = 'conditioning_input_switch' + CATEGORY = 'WAS Suite/Logic' + + def conditioning_input_switch(self, conditioning_a, conditioning_b, boolean=True): + if boolean: + return (conditioning_a,) + else: + return (conditioning_b,) +``` \ No newline at end of file diff --git a/docs/ConditioningBlend.md b/docs/ConditioningBlend.md new file mode 100644 index 0000000..216cf7f --- /dev/null +++ b/docs/ConditioningBlend.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: WAS_ConditioningBlend +- Category: conditioning +- Output node: False +- Repo Ref: https://github.com/WASasquatch/WAS_Extras + +WAS_ConditioningBlend节点旨在使用指定的混合模式和强度将两个条件输入无缝混合,确保两个输入的和谐整合。此节点在生成条件输出中发挥关键作用,通过结合不同条件信号并自定义影响程度来实现。 + +# Input types +## Required +- conditioning_a + - 第一个要与另一个条件输入混合的条件输入。它是一个关键组件,因为它构成了混合的一半,并显著影响最终的条件输出。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] +- conditioning_b + - 第二个条件输入,在混合过程中补充第一个。它至关重要,因为它有助于最终混合,影响条件输出的特征。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] +- blending_mode + - 混合模式决定了两个条件输入如何组合。它是一个关键参数,因为它决定了用于混合的算法,从而影响最终输出的性质。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- blending_strength + - 混合强度参数控制混合效果的强度。它很重要,因为它允许微调混合中两个条件输入之间的平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - 节点内用于随机数生成的种子。它通过在执行过程中保持一致的随机状态,确保结果的可复现性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- conditioning + - WAS_ConditioningBlend节点的输出是一个单一的条件张量,代表了两个输入条件张量的混合结果。它很重要,因为它作为需要条件数据的后续节点的输入。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_ConditioningBlend: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'conditioning_a': ('CONDITIONING',), 'conditioning_b': ('CONDITIONING',), 'blending_mode': (list(blending_modes.keys()),), 'blending_strength': ('FLOAT', {'default': 0.5, 'min': -10.0, 'max': 10.0, 'step': 0.001}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('CONDITIONING',) + RETURN_NAMES = ('conditioning',) + FUNCTION = 'combine' + CATEGORY = 'conditioning' + + def combine(self, conditioning_a, conditioning_b, blending_mode, blending_strength, seed): + if seed > 0: + torch.manual_seed(seed) + a = conditioning_a[0][0].clone() + b = conditioning_b[0][0].clone() + pa = conditioning_a[0][1]['pooled_output'].clone() + pb = conditioning_b[0][1]['pooled_output'].clone() + cond = normalize(blending_modes[blending_mode](a, b, 1 - blending_strength)) + pooled = normalize(blending_modes[blending_mode](pa, pb, 1 - blending_strength)) + conditioning = [[cond, {'pooled_output': pooled}]] + return (conditioning,) +``` \ No newline at end of file diff --git a/docs/ConsoleDebug+.md b/docs/ConsoleDebug+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Constant Mask.md b/docs/Constant Mask.md new file mode 100644 index 0000000..43c4ecf --- /dev/null +++ b/docs/Constant Mask.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: ConstantMask +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +ConstantMask节点旨在生成一个在其维度上具有统一值的掩码。它在定义掩码大小时提供了灵活性,可以显式定义,也可以通过复制现有图像的尺寸,从而确保数据预处理流程中的一致性。 + +# Input types +## Required +- value + - 参数'value'指定了填充掩码的常数值。它在确定输出掩码的均匀性中起着关键作用,影响图像的后续处理。 + - Comfy dtype: FLOAT + - Python dtype: float +- explicit_height + - 参数'explicit_height'在不从图像复制时设置掩码的高度。它对于定义掩码的垂直维度很重要。 + - Comfy dtype: INT + - Python dtype: int +- explicit_width + - 参数'explicit_width'在不从图像复制时设置掩码的宽度。它对于定义掩码的水平维度至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- copy_image_size + - 参数'copy_image_size'允许掩码采用所提供图像的尺寸,避免了需要指定显式尺寸的需要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor + +# Output types +- result + - 'result'输出是填充了指定常数值的生成掩码。它对于需要统一掩码进行进一步图像操作的应用来说非常重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ConstantMask: + """ + Creates a mask filled with a constant value. If copy_image_size is provided, the explicit_height and explicit_width parameters are ignored and the size of the given images will be used instead. + """ + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'value': ('FLOAT', {'default': 0.0, 'min': -8.0, 'max': 8.0, 'step': 0.01}), 'explicit_height': ('INT', {'default': 0, 'min': 0, 'max': VERY_BIG_SIZE, 'step': 1}), 'explicit_width': ('INT', {'default': 0, 'min': 0, 'max': VERY_BIG_SIZE, 'step': 1})}, 'optional': {'copy_image_size': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'constant_mask' + CATEGORY = 'Masquerade Nodes' + + def constant_mask(self, value, explicit_height, explicit_width, copy_image_size=None): + height = explicit_height + width = explicit_width + if copy_image_size is not None: + size = copy_image_size.size() + height = size[1] + width = size[2] + elif explicit_height == 0 or explicit_width == 0: + height = 16 + width = 16 + result = torch.zeros([1, height, width]) + result[:, :, :] = value + return (result,) +``` \ No newline at end of file diff --git a/docs/Constant Number.md b/docs/Constant Number.md new file mode 100644 index 0000000..0b5ef62 --- /dev/null +++ b/docs/Constant Number.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: WAS_Constant_Number +- Category: WAS Suite/Number +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Constant_Number节点旨在根据指定的类型生成一个常数。它提供了一种灵活的方式,可以根据输入参数以不同的格式(如整数、浮点数或布尔值)返回一个数字。这个节点特别适用于需要一个常数值进行进一步处理或分析的场景。 + +# Input types +## Required +- number_type + - 参数'number_type'定义了要生成的常数的类型。它至关重要,因为它决定了输出的格式。节点将根据此参数生成整数、浮点数或布尔值。 + - Comfy dtype: COMBO['integer', 'float', 'bool'] + - Python dtype: str +- number + - 参数'number'是节点用来生成常数的基础数值。它在确定节点的最终输出中起着重要作用,因为返回的值是从这个输入派生出来的。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- number_as_text + - 可选参数'number_as_text'允许节点将输入解释为数字的文本表示,然后可以将其转换为指定的数字类型。这为数字输入提供了灵活性。 + - Comfy dtype: str + - Python dtype: Optional[str] + +# Output types +- constant_number + - 输出'constant_number'表示以指定类型生成的常数。它是节点操作的主要结果,对于任何需要这个常数值的后续任务都很重要。 + - Comfy dtype: COMBO[INT, FLOAT, NUMBER] + - Python dtype: Union[int, float, bool] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Constant_Number: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number_type': (['integer', 'float', 'bool'],), 'number': ('FLOAT', {'default': 0, 'min': -18446744073709551615, 'max': 18446744073709551615})}, 'optional': {'number_as_text': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False})}} + RETURN_TYPES = ('NUMBER', 'FLOAT', 'INT') + FUNCTION = 'return_constant_number' + CATEGORY = 'WAS Suite/Number' + + def return_constant_number(self, number_type, number, number_as_text=None): + if number_as_text: + if number_type == 'integer': + number = int(number_as_text) + elif number_type == 'float': + number = float(number_as_text) + else: + number = bool(number_as_text) + if number_type: + if number_type == 'integer': + return (int(number), float(number), int(number)) + elif number_type == 'integer': + return (float(number), float(number), int(number)) + elif number_type == 'bool': + boolean = 1 if float(number) > 0.5 else 0 + return (int(boolean), float(boolean), int(boolean)) + else: + return (number, float(number), int(number)) +``` \ No newline at end of file diff --git a/docs/ConstrainImage.md b/docs/ConstrainImage.md new file mode 100644 index 0000000..5a11c25 --- /dev/null +++ b/docs/ConstrainImage.md @@ -0,0 +1,89 @@ +# Documentation +- Class name: ConstrainImage +- Category: image +- Output node: False +- Repo Ref: https://github.com/esheep/esheep_custom_nodes.git + +该节点旨在将图像尺寸调整到指定边界内,同时保持图像的纵横比。它通过将图像缩放到最接近的最大和最小尺寸的尺寸来操作,如有必要,还会裁剪图像以确保它完全适合定义的约束条件。 + +# Input types +## Required +- images + - 图像参数是必需的,因为它提供了将被约束的输入图像。它通过确定节点将处理和转换的数据直接影响节点的操作。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- max_width + - 最大宽度参数规定了图像变换后宽度的上限。它在确保图像不超出期望尺寸,从而保持预期的纵横比方面发挥着至关重要的作用。 + - Comfy dtype: INT + - Python dtype: int +- max_height + - 与最大宽度类似,最大高度参数设置了图像高度的上限。它在确保图像在变换过程中垂直尺寸得到适当约束方面至关重要。 + - Comfy dtype: INT + - Python dtype: int +- min_width + - 最小宽度参数确保图像不会缩小到某个阈值以下,这对于保持图像的完整性和防止图像变得太小而无法有效查看或分析非常重要。 + - Comfy dtype: INT + - Python dtype: int +- min_height + - 最小高度参数用于维持图像高度的基线,确保即使在缩放以适应指定的约束条件时,图像仍然保持可见和可读。 + - Comfy dtype: INT + - Python dtype: int +- crop_if_required + - 如果需要,crop_if_required参数是一个决策点,用于确定在缩放后如果图像不符合指定的约束条件是否应该裁剪图像。这个选择会影响图像变换的最终结果。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- IMAGE + - 输出图像是约束过程的结果,代表已调整以适应指定的最大和最小尺寸的输入图像,同时保持其纵横比。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ConstrainImage: + """ + A node that constrains an image to a maximum and minimum size while maintaining aspect ratio. + """ + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'max_width': ('INT', {'default': 1024, 'min': 0}), 'max_height': ('INT', {'default': 1024, 'min': 0}), 'min_width': ('INT', {'default': 0, 'min': 0}), 'min_height': ('INT', {'default': 0, 'min': 0}), 'crop_if_required': (['yes', 'no'], {'default': 'no'})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'constrain_image' + CATEGORY = 'image' + OUTPUT_IS_LIST = (True,) + + def constrain_image(self, images, max_width, max_height, min_width, min_height, crop_if_required): + crop_if_required = crop_if_required == 'yes' + results = [] + for image in images: + i = 255.0 * image.cpu().numpy() + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)).convert('RGB') + (current_width, current_height) = img.size + aspect_ratio = current_width / current_height + constrained_width = max(min(current_width, min_width), max_width) + constrained_height = max(min(current_height, min_height), max_height) + if constrained_width / constrained_height > aspect_ratio: + constrained_width = max(int(constrained_height * aspect_ratio), min_width) + if crop_if_required: + constrained_height = int(current_height / (current_width / constrained_width)) + else: + constrained_height = max(int(constrained_width / aspect_ratio), min_height) + if crop_if_required: + constrained_width = int(current_width / (current_height / constrained_height)) + resized_image = img.resize((constrained_width, constrained_height), Image.LANCZOS) + if crop_if_required and (constrained_width > max_width or constrained_height > max_height): + left = max((constrained_width - max_width) // 2, 0) + top = max((constrained_height - max_height) // 2, 0) + right = min(constrained_width, max_width) + left + bottom = min(constrained_height, max_height) + top + resized_image = resized_image.crop((left, top, right, bottom)) + resized_image = np.array(resized_image).astype(np.float32) / 255.0 + resized_image = torch.from_numpy(resized_image)[None,] + results.append(resized_image) + return (results,) +``` \ No newline at end of file diff --git a/docs/Control Net Model Input Switch.md b/docs/Control Net Model Input Switch.md new file mode 100644 index 0000000..fd45ca6 --- /dev/null +++ b/docs/Control Net Model Input Switch.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: WAS_Control_Net_Input_Switch +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +‘control_net_switch’方法旨在根据布尔条件智能选择两个控制网络中的一个。它作为工作流程中的决策节点,确保在任何给定时间使用适当的控制网络,从而增强系统的灵活性和适应性。 + +# Input types +## Required +- control_net_a + - ‘control_net_a’参数代表节点可以切换到的第一个控制网络选项。它在决策过程中起着关键作用,因为当布尔条件满足时,节点将选择此网络。 + - Comfy dtype: CONTROL_NET + - Python dtype: Optional[Union[comfy.sd.CONTROL_NET, torch.Tensor]] +- control_net_b + - ‘control_net_b’参数是布尔条件不满足时节点可能选择的替代控制网络。它对节点的功能至关重要,为控制网络提供了一个备选方案。 + - Comfy dtype: CONTROL_NET + - Python dtype: Optional[Union[comfy.sd.CONTROL_NET, torch.Tensor]] +## Optional +- boolean + - ‘boolean’参数作为一个条件开关,决定了返回‘control_net_a’还是‘control_net_b’。它的重要性在于,它的真值直接决定了节点的输出。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- selected_control_net + - ‘selected_control_net’输出代表节点根据布尔条件选择的控制网络。它至关重要,因为它决定了工作流程中随后的处理步骤。 + - Comfy dtype: CONTROL_NET + - Python dtype: Union[comfy.sd.CONTROL_NET, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Control_Net_Input_Switch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'control_net_a': ('CONTROL_NET',), 'control_net_b': ('CONTROL_NET',), 'boolean': ('BOOLEAN', {'forceInput': True})}} + RETURN_TYPES = ('CONTROL_NET',) + FUNCTION = 'control_net_switch' + CATEGORY = 'WAS Suite/Logic' + + def control_net_switch(self, control_net_a, control_net_b, boolean=True): + if boolean: + return (control_net_a,) + else: + return (control_net_b,) +``` \ No newline at end of file diff --git a/docs/ControlNetLoaderAdvanced.md b/docs/ControlNetLoaderAdvanced.md new file mode 100644 index 0000000..f835832 --- /dev/null +++ b/docs/ControlNetLoaderAdvanced.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: ControlNetLoaderAdvanced +- Category: Adv-ControlNet 🛂🅐🅒🅝 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +ControlNetLoaderAdvanced节点的`load_controlnet`方法旨在高效地加载和管理控制网络配置。它是系统中的关键组件,能够无缝地将控制网络集成到工作流程中。该方法抽象了加载和处理控制网络的复杂性,为用户提供了一个简单直观的接口来访问这些网络。 + +# Input types +## Required +- control_net_name + - 参数`control_net_name`对于识别要加载的特定控制网络至关重要。它在节点的执行中起着关键作用,决定了系统中将使用哪个控制网络配置。 + - Comfy dtype: str + - Python dtype: str +## Optional +- timestep_keyframe + - 可选参数`timestep_keyframe`允许指定与时间步骤相关的关键帧,这可以影响控制网络在时间变化过程中的应用方式。 + - Comfy dtype: TimestepKeyframeGroup + - Python dtype: TimestepKeyframeGroup + +# Output types +- CONTROL_NET + - 输出`CONTROL_NET`代表已加载的控制网络,是系统操作中的一个核心元素。它封装了网络的结构和参数,准备用于各种任务和分析。 + - Comfy dtype: Tensor + - Python dtype: Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ControlNetLoaderAdvanced: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'control_net_name': (folder_paths.get_filename_list('controlnet'),)}, 'optional': {'timestep_keyframe': ('TIMESTEP_KEYFRAME',)}} + RETURN_TYPES = ('CONTROL_NET',) + FUNCTION = 'load_controlnet' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝' + + def load_controlnet(self, control_net_name, timestep_keyframe: TimestepKeyframeGroup=None): + controlnet_path = folder_paths.get_full_path('controlnet', control_net_name) + controlnet = load_controlnet(controlnet_path, timestep_keyframe) + return (controlnet,) +``` \ No newline at end of file diff --git a/docs/Convert Color Space.md b/docs/Convert Color Space.md new file mode 100644 index 0000000..fd3adb0 --- /dev/null +++ b/docs/Convert Color Space.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: ConvertColorSpace +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +ConvertColorSpace节点旨在将图像从一个颜色空间转换到另一个颜色空间。它提供了一个高级接口,用于在RGB、HSV和HSL颜色空间之间无缝转换图像,允许更有效地操作和分析图像数据。 + +# Input types +## Required +- in_space + - ‘in_space’参数定义了输入图像的当前颜色空间,这对于确定适当的转换算法至关重要。它通过指定颜色空间转换的起点来影响节点的执行。 + - Comfy dtype: COMBO['RGB', 'HSV', 'HSL'] + - Python dtype: str +- out_space + - ‘out_space’参数指定了输出图像所需的颜色空间。它是节点操作的关键决定因素,因为它决定了颜色空间转换过程的目标格式。 + - Comfy dtype: COMBO['RGB', 'HSV', 'HSL'] + - Python dtype: str +- image + - ‘image’参数表示需要转换的输入图像数据。它对节点的功能至关重要,因为它是颜色空间转换的主要数据对象。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- IMAGE + - 输出‘IMAGE’表示在指定颜色空间中转换后的图像。它是节点操作的最终结果,对于进一步的图像处理或分析任务具有重要价值。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ConvertColorSpace: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'in_space': (['RGB', 'HSV', 'HSL'],), 'out_space': (['RGB', 'HSV', 'HSL'],), 'image': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'convert_color_space' + CATEGORY = 'Masquerade Nodes' + + def convert_color_space(self, in_space, out_space, image): + if in_space == out_space: + return (image,) + image = tensor2rgb(image) + if in_space == 'HSV': + hsv = image + if in_space == 'RGB': + hsv = rgb2hsv(image) + elif in_space == 'HSL': + hsv = hsl2hsv(image) + if out_space == 'HSV': + return (hsv,) + elif out_space == 'RGB': + return (hsv2rgb(hsv),) + else: + assert out_space == 'HSL' + return (hsv2hsl(hsv),) +``` \ No newline at end of file diff --git a/docs/Convert Masks to Images.md b/docs/Convert Masks to Images.md new file mode 100644 index 0000000..332b124 --- /dev/null +++ b/docs/Convert Masks to Images.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: WAS_Mask_To_Image +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_To_Image节点旨在将掩码数据转换为图像格式。它能够智能地处理各种维度的掩码输入,确保与不同类型的掩码数据兼容。此节点在转换过程中发挥关键作用,使得从掩码表示到视觉图像的过渡变得无缝。 + +# Input types +## Required +- masks + - 'masks'参数对于节点的操作至关重要,因为它定义了需要转换为图像的输入掩码数据。该参数对节点执行的影响很大,因为它直接影响输出图像的质量和表示。 + - Comfy dtype: MASK + - Python dtype: Union[torch.Tensor, List[torch.Tensor]] + +# Output types +- IMAGES + - 'IMAGES'输出参数代表从输入掩码转换得到的图像数据。它是一个关键的输出,因为它标志着掩码数据成功转换为可以进一步处理或显示的可视化格式。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_To_Image: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',)}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('IMAGES',) + FUNCTION = 'mask_to_image' + + def mask_to_image(self, masks): + if masks.ndim == 4: + tensor = masks.permute(0, 2, 3, 1) + tensor_rgb = torch.cat([tensor] * 3, dim=-1) + return (tensor_rgb,) + elif masks.ndim == 3: + tensor = masks.unsqueeze(-1) + tensor_rgb = torch.cat([tensor] * 3, dim=-1) + return (tensor_rgb,) + elif masks.ndim == 2: + tensor = masks.unsqueeze(0).unsqueeze(-1) + tensor_rgb = torch.cat([tensor] * 3, dim=-1) + return (tensor_rgb,) + else: + cstr('Invalid input shape. Expected [N, C, H, W] or [H, W].').error.print() + return masks +``` \ No newline at end of file diff --git a/docs/CoreMLDetailerHookProvider.md b/docs/CoreMLDetailerHookProvider.md new file mode 100644 index 0000000..fe51add --- /dev/null +++ b/docs/CoreMLDetailerHookProvider.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: CoreMLDetailerHookProvider +- Category: ImpactPack/Detailer +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +CoreMLDetailerHookProvider节点旨在促进CoreML模型在ImpactPack/Detailer类别中的集成。它提供了一种方法来生成一个钩子,该钩子可用于自定义模型在图像处理任务中的行为。此节点特别适用于调整图像的分辨率和宽高比以满足CoreML模型的要求。 + +# Input types +## Required +- mode + - mode参数指定了图像处理的分辨率和宽高比。它至关重要,因为它决定了CoreML模型将如何处理输入图像。节点使用这些信息来调整图像的尺寸以适应模型的要求。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- DETAILER_HOOK + - 该节点的输出是一个CoreMLHook对象,这是一个专为与CoreML模型一起工作而设计的专用钩子。它包括用于预处理和后处理样本的方法,以确保它们与模型预期的输入和输出格式兼容。 + - Comfy dtype: CoreMLHook + - Python dtype: CoreMLHook + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CoreMLDetailerHookProvider: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mode': (['512x512', '768x768', '512x768', '768x512'],)}} + RETURN_TYPES = ('DETAILER_HOOK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detailer' + + def doit(self, mode): + hook = hooks.CoreMLHook(mode) + return (hook,) +``` \ No newline at end of file diff --git a/docs/CosWave.md b/docs/CosWave.md new file mode 100644 index 0000000..7078f7c --- /dev/null +++ b/docs/CosWave.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: CosWave +- Category: FizzNodes 📅🅕🅝/WaveNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +CosWave节点通过各种参数生成余弦波形,可以调整这些参数以实现所需的变换。它主要用于创建可以与基于时间的变量同步的振荡效果。 + +# Input types +## Required +- phase + - 相位参数决定了余弦波的周期,影响振荡的频率。它是塑造波的时间特性的关键要素。 + - Comfy dtype: FLOAT + - Python dtype: float +- amplitude + - 振幅设置了波的峰值,控制振荡从其平均位置的范围。它对于定义波的强度至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- x_translation + - X平移允许沿X轴水平移动波形,提供对波位置的控制,而不影响其形状。 + - Comfy dtype: FLOAT + - Python dtype: float +- y_translation + - Y平移调整波沿Y轴的垂直位置,允许微调波的起始点。 + - Comfy dtype: FLOAT + - Python dtype: float +- current_frame + - 当前帧参数用于将波的相位与序列或动画的进展同步,允许随时间动态变化。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - CosWave节点的输出代表了在指定帧下的结果波形值,可以用于进一步的处理或可视化。 + - Comfy dtype: FLOAT + - Python dtype: float +- int_output + - 整数输出是波形值转换为整数的版本,对于需要离散值的应用非常有用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CosWave: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'phase': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'amplitude': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.1}), 'x_translation': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'y_translation': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.05}), 'current_frame': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('FLOAT', 'INT') + FUNCTION = 'Wave' + CATEGORY = 'FizzNodes 📅🅕🅝/WaveNodes' + + def Wave(self, phase, amplitude, x_translation, y_translation, current_frame): + output = y_translation + amplitude * np.cos(2 * np.pi * current_frame / phase - x_translation) + print(output) + return (output, int(output)) +``` \ No newline at end of file diff --git a/docs/Create Grid Image from Batch.md b/docs/Create Grid Image from Batch.md new file mode 100644 index 0000000..9eec571 --- /dev/null +++ b/docs/Create Grid Image from Batch.md @@ -0,0 +1,104 @@ +# Documentation +- Class name: WAS_Image_Grid_Image_Batch +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Grid_Image_Batch节点的'smart_grid_image'函数旨在将一批图像智能地排列成网格布局。它动态调整每个图像的大小以适应指定的最大单元格大小,同时保持原始的宽高比。该节点还提供选项以在每个图像周围添加有色边框,以更好地进行视觉区分。其主要目标是启用创建视觉吸引人且组织良好的图像网格,这对于演示和图像集合特别有用。 + +# Input types +## Required +- images + - 'image'参数是节点将处理以创建网格的图像张量集合。这是一个关键的输入,因为节点的所有操作都围绕着排列这些图像。该参数直接影响输出网格的组成和视觉结果。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +## Optional +- number_of_columns + - 'number_of_columns'参数指定生成的网格中的列数。它在确定网格布局方面起着重要作用,影响图像如何分布在网格的宽度上。默认值为6,但可以根据所需的网格配置进行调整。 + - Comfy dtype: INT + - Python dtype: int +- max_cell_size + - 'max_cell_size'参数设置网格中每个单元格的最大尺寸(以像素为单位)。它对于控制网格的总体大小以及确保图像被适当缩放非常重要。默认值为256像素,但可以根据不同的显示需求进行修改。 + - Comfy dtype: INT + - Python dtype: int +- add_border + - 'add_border'参数是一个布尔标志,当设置为True时,指示节点在网格中的每个图像周围添加边框。这可以增强图像之间的视觉分离,特别适用于需要区分单个图像的网格。 + - Comfy dtype: BOOL + - Python dtype: bool +- border_red + - 'border_red'参数定义了为图像添加边框时边框颜色的红色分量。它有助于定制边框的外观,并与'border_green'和'border_blue'一起使用以创建完整的边框颜色。 + - Comfy dtype: INT + - Python dtype: int +- border_green + - 'border_green'参数设置边框颜色的绿色分量。当启用'add_border'时,它与'border_red'和'border_blue'一起工作,以确定边框的确切色调。 + - Comfy dtype: INT + - Python dtype: int +- border_blue + - 'border_blue'参数指定边框颜色的蓝色分量。它是三种颜色分量之一,与'border_red'和'border_green'一起,决定了边框应用于图像时的视觉样式。 + - Comfy dtype: INT + - Python dtype: int +- border_width + - 'border_width'参数确定每个图像周围边框的厚度。它是一个重要的样式元素,可以影响网格的整体外观,使图像更加突出。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output_image + - 'output_image'是排列成结构化布局的输入图像组成的结果网格图像。它代表了节点处理的最终成果,包含了通过输入参数所做的视觉排列和样式选择。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Grid_Image_Batch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'border_width': ('INT', {'default': 3, 'min': 0, 'max': 100, 'step': 1}), 'number_of_columns': ('INT', {'default': 6, 'min': 1, 'max': 24, 'step': 1}), 'max_cell_size': ('INT', {'default': 256, 'min': 32, 'max': 2048, 'step': 1}), 'border_red': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1}), 'border_green': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1}), 'border_blue': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'smart_grid_image' + CATEGORY = 'WAS Suite/Image/Process' + + def smart_grid_image(self, images, number_of_columns=6, max_cell_size=256, add_border=False, border_red=255, border_green=255, border_blue=255, border_width=3): + cols = number_of_columns + border_color = (border_red, border_green, border_blue) + images_resized = [] + max_row_height = 0 + for tensor_img in images: + img = tensor2pil(tensor_img) + (img_w, img_h) = img.size + aspect_ratio = img_w / img_h + if img_w > img_h: + cell_w = min(img_w, max_cell_size) + cell_h = int(cell_w / aspect_ratio) + else: + cell_h = min(img_h, max_cell_size) + cell_w = int(cell_h * aspect_ratio) + img_resized = img.resize((cell_w, cell_h)) + if add_border: + img_resized = ImageOps.expand(img_resized, border=border_width // 2, fill=border_color) + images_resized.append(img_resized) + max_row_height = max(max_row_height, cell_h) + max_row_height = int(max_row_height) + total_images = len(images_resized) + rows = math.ceil(total_images / cols) + grid_width = cols * max_cell_size + (cols - 1) * border_width + grid_height = rows * max_row_height + (rows - 1) * border_width + new_image = Image.new('RGB', (grid_width, grid_height), border_color) + for (i, img) in enumerate(images_resized): + x = i % cols * (max_cell_size + border_width) + y = i // cols * (max_row_height + border_width) + (img_w, img_h) = img.size + paste_x = x + (max_cell_size - img_w) // 2 + paste_y = y + (max_row_height - img_h) // 2 + new_image.paste(img, (paste_x, paste_y, paste_x + img_w, paste_y + img_h)) + if add_border: + new_image = ImageOps.expand(new_image, border=border_width, fill=border_color) + return (pil2tensor(new_image),) +``` \ No newline at end of file diff --git a/docs/Create Grid Image.md b/docs/Create Grid Image.md new file mode 100644 index 0000000..8d79ef6 --- /dev/null +++ b/docs/Create Grid Image.md @@ -0,0 +1,134 @@ +# Documentation +- Class name: WAS_Image_Grid_Image +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Grid_Image节点旨在将一系列图片处理成单个网格图片。它智能地将图片组织成指定数量的列,将它们缩放到最大单元格大小,并可选择性地为每个图片周围添加彩色边框以区分视觉效果。该节点特别适用于从图片目录创建拼贴画或缩略图。 + +# Input types +## Required +- images_path + - 参数'images_path'指定了要处理的图片所在的目录路径。这个路径至关重要,因为它指导节点到将被组织成网格的图片的源位置。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- pattern_glob + - 参数'pattern_glob'用于匹配目录中的特定文件。它允许基于某种模式过滤图片,这在目录中的所有文件并非都是图片或需要一组特定图片时非常有用。 + - Comfy dtype: STRING + - Python dtype: str +- include_subfolders + - 参数'include_subfolders'决定是否在创建网格的过程中包含子目录中的图片。将其设置为'true'将使节点扫描并包含指定路径下所有子目录中的图片。 + - Comfy dtype: COMBO[false, true] + - Python dtype: Union[str, bool] +- number_of_columns + - 参数'number_of_columns'定义了结果网格图片中的列数。它决定了图片将如何分布在网格的宽度上,影响整体布局。 + - Comfy dtype: INT + - Python dtype: int +- max_cell_size + - 参数'max_cell_size'设置了网格中每个图片单元的最大尺寸(以像素为单位)。这确保在处理后没有图片会超出这些尺寸,保持网格中的外观一致性。 + - Comfy dtype: INT + - Python dtype: int +- border_width + - 参数'border_width'指定在网格中每个图片周围添加的边框宽度,如果包含边框的话。值为0表示没有边框。 + - Comfy dtype: INT + - Python dtype: int +- border_red + - 参数'border_red'连同'border_green'和'border_blue'一起,通过指定RGB颜色值的红色分量来确定每个图片周围边框的颜色。 + - Comfy dtype: INT + - Python dtype: int +- border_green + - 参数'border_green'指定边框颜色的RGB颜色值中的绿色分量。 + - Comfy dtype: INT + - Python dtype: int +- border_blue + - 参数'border_blue'指定边框颜色的RGB颜色值中的蓝色分量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- grid_image + - 'grid_image'输出是包含处理过的图片网格的结果图片。它代表了根据输入参数指定的最终视觉布局。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Grid_Image: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images_path': ('STRING', {'default': './ComfyUI/input/', 'multiline': False}), 'pattern_glob': ('STRING', {'default': '*', 'multiline': False}), 'include_subfolders': (['false', 'true'],), 'border_width': ('INT', {'default': 3, 'min': 0, 'max': 100, 'step': 1}), 'number_of_columns': ('INT', {'default': 6, 'min': 1, 'max': 24, 'step': 1}), 'max_cell_size': ('INT', {'default': 256, 'min': 32, 'max': 1280, 'step': 1}), 'border_red': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1}), 'border_green': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1}), 'border_blue': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'create_grid_image' + CATEGORY = 'WAS Suite/Image/Process' + + def create_grid_image(self, images_path, pattern_glob='*', include_subfolders='false', number_of_columns=6, max_cell_size=256, border_width=3, border_red=0, border_green=0, border_blue=0): + if not os.path.exists(images_path): + cstr(f'The grid image path `{images_path}` does not exist!').error.print() + return (pil2tensor(Image.new('RGB', (512, 512), (0, 0, 0))),) + paths = glob.glob(os.path.join(images_path, pattern_glob), recursive=False if include_subfolders == 'false' else True) + image_paths = [] + for path in paths: + if path.lower().endswith(ALLOWED_EXT) and os.path.exists(path): + image_paths.append(path) + grid_image = self.smart_grid_image(image_paths, int(number_of_columns), (int(max_cell_size), int(max_cell_size)), False if border_width <= 0 else True, (int(border_red), int(border_green), int(border_blue)), int(border_width)) + return (pil2tensor(grid_image),) + + def smart_grid_image(self, images, cols=6, size=(256, 256), add_border=False, border_color=(0, 0, 0), border_width=3): + (max_width, max_height) = size + row_height = 0 + images_resized = [] + for image in images: + img = Image.open(image).convert('RGB') + (img_w, img_h) = img.size + aspect_ratio = img_w / img_h + if aspect_ratio > 1: + thumb_w = min(max_width, img_w - border_width) + thumb_h = thumb_w / aspect_ratio + else: + thumb_h = min(max_height, img_h - border_width) + thumb_w = thumb_h * aspect_ratio + pad_w = max_width - int(thumb_w) + pad_h = max_height - int(thumb_h) + left = pad_w // 2 + top = pad_h // 2 + right = pad_w - left + bottom = pad_h - top + padding = (left, top, right, bottom) + img_resized = ImageOps.expand(img.resize((int(thumb_w), int(thumb_h))), padding) + if add_border: + img_resized_bordered = ImageOps.expand(img_resized, border=border_width // 2, fill=border_color) + images_resized.append(img_resized) + row_height = max(row_height, img_resized.size[1]) + row_height = int(row_height) + total_images = len(images_resized) + rows = math.ceil(total_images / cols) + new_image = Image.new('RGB', (cols * size[0] + (cols - 1) * border_width, rows * row_height + (rows - 1) * border_width), border_color) + for (i, img) in enumerate(images_resized): + if add_border: + border_img = ImageOps.expand(img, border=border_width // 2, fill=border_color) + x = i % cols * (size[0] + border_width) + y = i // cols * (row_height + border_width) + if border_img.size == (size[0], size[1]): + new_image.paste(border_img, (x, y, x + size[0], y + size[1])) + else: + border_img = border_img.resize((size[0], size[1])) + new_image.paste(border_img, (x, y, x + size[0], y + size[1])) + else: + x = i % cols * (size[0] + border_width) + y = i // cols * (row_height + border_width) + if img.size == (size[0], size[1]): + new_image.paste(img, (x, y, x + img.size[0], y + img.size[1])) + else: + img = img.resize((size[0], size[1])) + new_image.paste(img, (x, y, x + size[0], y + size[1])) + new_image = ImageOps.expand(new_image, border=border_width, fill=border_color) + return new_image +``` \ No newline at end of file diff --git a/docs/Create Morph Image.md b/docs/Create Morph Image.md new file mode 100644 index 0000000..2647b0a --- /dev/null +++ b/docs/Create Morph Image.md @@ -0,0 +1,119 @@ +# Documentation +- Class name: WAS_Image_Morph_GIF +- Category: WAS Suite/Animation +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Morph_GIF 节点旨在创建两个图像之间的变形动画。它在一个指定的帧数上平滑地从一个图像过渡到另一个图像,允许定制过渡属性,如帧延迟和循环设置。这个节点特别适用于生成像 GIF 或 APNG 这样的动画序列,可以用于各种多媒体演示或应用程序中。 + +# Input types +## Required +- image_a + - 用于变形动画的第一张图像。它设置了过渡的起点,并且对最终输出的外观至关重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- image_b + - 动画变形到的第二张图像。这张图像定义了过渡的结束状态,对变形的整体效果有所贡献。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +## Optional +- transition_frames + - 用于两个图像之间过渡的帧数。数量越多,过渡越平滑,但动画时间也更长。 + - Comfy dtype: INT + - Python dtype: int +- still_image_delay_ms + - 在开始变形过渡之前的每个静态帧的延迟时间(以毫秒为单位)。 + - Comfy dtype: FLOAT + - Python dtype: float +- duration_ms + - 变形过渡期间每帧的持续时间(以毫秒为单位)。 + - Comfy dtype: FLOAT + - Python dtype: float +- loops + - 动画应该循环的次数。值为 0 表示动画将无限循环。 + - Comfy dtype: INT + - Python dtype: int +- max_size + - 输出图像的最大尺寸(以像素为单位)。可能会调整大小以适应此限制,同时保持纵横比。 + - Comfy dtype: INT + - Python dtype: int +- output_path + - 保存输出 GIF 文件的路径。如果未指定,默认为 './ComfyUI/output'。 + - Comfy dtype: STRING + - Python dtype: str +- filename + - 输出 GIF 文件的期望名称。如果未提供,默认为 'morph'。 + - Comfy dtype: STRING + - Python dtype: str +- filetype + - 输出动画的文件格式。支持 'GIF' 或 'APNG'。 + - Comfy dtype: COMBO['GIF', 'APNG'] + - Python dtype: str + +# Output types +- image_a_pass + - 第一个输入图像,未改变,包含在输出中以保持连贯性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- image_b_pass + - 第二个输入图像,未改变,包含在输出中以保持连贯性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- filepath_text + - 创建的 GIF 文件的完整路径。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str +- filename_text + - 创建的 GIF 的文件名。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Morph_GIF: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image_a': ('IMAGE',), 'image_b': ('IMAGE',), 'transition_frames': ('INT', {'default': 30, 'min': 2, 'max': 60, 'step': 1}), 'still_image_delay_ms': ('FLOAT', {'default': 2500.0, 'min': 0.1, 'max': 60000.0, 'step': 0.1}), 'duration_ms': ('FLOAT', {'default': 0.1, 'min': 0.1, 'max': 60000.0, 'step': 0.1}), 'loops': ('INT', {'default': 0, 'min': 0, 'max': 100, 'step': 1}), 'max_size': ('INT', {'default': 512, 'min': 128, 'max': 1280, 'step': 1}), 'output_path': ('STRING', {'default': './ComfyUI/output', 'multiline': False}), 'filename': ('STRING', {'default': 'morph', 'multiline': False}), 'filetype': (['GIF', 'APNG'],)}} + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') + RETURN_TYPES = ('IMAGE', 'IMAGE', TEXT_TYPE, TEXT_TYPE) + RETURN_NAMES = ('image_a_pass', 'image_b_pass', 'filepath_text', 'filename_text') + FUNCTION = 'create_morph_gif' + CATEGORY = 'WAS Suite/Animation' + + def create_morph_gif(self, image_a, image_b, transition_frames=10, still_image_delay_ms=10, duration_ms=0.1, loops=0, max_size=512, output_path='./ComfyUI/output', filename='morph', filetype='GIF'): + tokens = TextTokens() + WTools = WAS_Tools_Class() + if 'imageio' not in packages(): + install_package('imageio') + if filetype not in ['APNG', 'GIF']: + filetype = 'GIF' + if output_path.strip() in [None, '', '.']: + output_path = './ComfyUI/output' + output_path = tokens.parseTokens(os.path.join(*output_path.split('/'))) + if not os.path.exists(output_path): + os.makedirs(output_path, exist_ok=True) + if image_a == None: + image_a = pil2tensor(Image.new('RGB', (512, 512), (0, 0, 0))) + if image_b == None: + image_b = pil2tensor(Image.new('RGB', (512, 512), (255, 255, 255))) + if transition_frames < 2: + transition_frames = 2 + elif transition_frames > 60: + transition_frames = 60 + if duration_ms < 0.1: + duration_ms = 0.1 + elif duration_ms > 60000.0: + duration_ms = 60000.0 + output_file = WTools.morph_images([tensor2pil(image_a), tensor2pil(image_b)], steps=int(transition_frames), max_size=int(max_size), loop=int(loops), still_duration=int(still_image_delay_ms), duration=int(duration_ms), output_path=output_path, filename=tokens.parseTokens(filename), filetype=filetype) + return (image_a, image_b, output_file) +``` \ No newline at end of file diff --git a/docs/Create QR Code.md b/docs/Create QR Code.md new file mode 100644 index 0000000..256d56e --- /dev/null +++ b/docs/Create QR Code.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: CreateQRCodeNode +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +CreateQRCodeNode 类旨在从文本输入生成 QR 码。它封装了将字符串转换为 QR 码图像的功能,遵循指定的大小、版本、纠错级别、格子大小和边框参数。此节点在创建各种应用中所需的信息的视觉表示形式的 QR 码中扮演着关键角色。 + +# Input types +## Required +- text + - ‘text’ 参数至关重要,因为它是要编码成 QR 码的信息源。它可以是一个多行字符串,允许包含更复杂的数据。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- size + - ‘size’ 参数决定了 QR 码图像的尺寸。它很重要,因为它影响 QR 码的规模和可读性,默认值设置为确保大小和细节之间的平衡。 + - Comfy dtype: INT + - Python dtype: int +- qr_version + - ‘qr_version’ 参数控制 QR 码的版本,这对应于其纠错能力和数据存储容量。它对于确保 QR 码能够处理所提供的数据量至关重要。 + - Comfy dtype: INT + - Python dtype: int +- error_correction + - ‘error_correction’ 参数设置 QR 码的错误纠正级别。它至关重要,因为它定义了 QR 码对损坏的韧性以及在不同距离下的可读性。 + - Comfy dtype: COMBO['L', 'M', 'Q', 'H'] + - Python dtype: str +- box_size + - ‘box_size’ 参数指定 QR 网格中每个盒子的大小。它很重要,因为它影响 QR 码的视觉外观以及扫描 QR 码所需的精度。 + - Comfy dtype: INT + - Python dtype: int +- border + - ‘border’ 参数设置 QR 码周围边框的宽度。它很重要,因为它为 QR 码与其周围区域提供了清晰的界限,增强了其可扫描性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - ‘IMAGE’ 输出是由输入参数生成的 QR 码图像结果。它很重要,因为它是节点的主要交付物,以视觉格式表示编码的信息。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CreateQRCodeNode: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {'multiline': True}), 'size': ('INT', {'default': 512, 'min': 64, 'max': 4096, 'step': 64}), 'qr_version': ('INT', {'default': 1, 'min': 1, 'max': 40, 'step': 1}), 'error_correction': (['L', 'M', 'Q', 'H'], {'default': 'H'}), 'box_size': ('INT', {'default': 10, 'min': 1, 'max': 100, 'step': 1}), 'border': ('INT', {'default': 4, 'min': 0, 'max': 100, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'create_qr_code' + CATEGORY = 'Masquerade Nodes' + + def create_qr_code(self, text, size, qr_version, error_correction, box_size, border): + ensure_package('qrcode') + import qrcode + if error_correction == 'L': + error_level = qrcode.constants.ERROR_CORRECT_L + elif error_correction == 'M': + error_level = qrcode.constants.ERROR_CORRECT_M + elif error_correction == 'Q': + error_level = qrcode.constants.ERROR_CORRECT_Q + else: + error_level = qrcode.constants.ERROR_CORRECT_H + qr = qrcode.QRCode(version=qr_version, error_correction=error_level, box_size=box_size, border=border) + qr.add_data(text) + qr.make(fit=True) + img = qr.make_image(fill_color='black', back_color='white') + img = img.resize((size, size)) + tensor = torch.from_numpy(np.array(img)) + return (tensor2rgb(tensor.unsqueeze(0)),) +``` \ No newline at end of file diff --git a/docs/Create Rect Mask.md b/docs/Create Rect Mask.md new file mode 100644 index 0000000..9fd2dae --- /dev/null +++ b/docs/Create Rect Mask.md @@ -0,0 +1,96 @@ +# Documentation +- Class name: CreateRectMask +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +CreateRectMask 节点旨在根据指定的参数生成矩形掩码。它计算掩码角落的坐标,考虑到测量模式(百分比或像素)、矩形的原点以及提供的尺寸。该节点非常灵活,允许自定义掩码相对于应用图像的位置和大小。它还提供了一个选项来复制图像大小,以实现动态掩码创建。 + +# Input types +## Required +- mode + - mode 参数确定掩码尺寸的测量单位。它可以是 'percent' 表示基于百分比的坐标,或者是 'pixels' 表示绝对像素值。 + - Comfy dtype: str + - Python dtype: str +- origin + - origin 参数决定了计算掩码位置的参考点。它可以是 'topleft'、'bottomleft'、'topleft' 或 'bottomright' 中的一个。 + - Comfy dtype: str + - Python dtype: str +- x + - x 参数指定掩码起始点的水平位置。它与模式和原点一起使用,以确定掩码的位置。 + - Comfy dtype: float + - Python dtype: float +- y + - y 参数指定掩码起始点的垂直位置。它与 x 参数和其他设置一起工作,以建立掩码的坐标。 + - Comfy dtype: float + - Python dtype: float +- width + - width 参数设置掩码的宽度。这是一个关键的尺寸,与高度一起定义了掩码的形状和覆盖区域。 + - Comfy dtype: float + - Python dtype: float +- height + - height 参数设置掩码的垂直范围。它在确定掩码的总体大小和它所包含的区域方面至关重要。 + - Comfy dtype: float + - Python dtype: float +- image_width + - image_width 参数定义了将应用掩码的图像的宽度。如果模式设置为 'percent',它对于确保掩码尺寸正确缩放非常重要。 + - Comfy dtype: int + - Python dtype: int +- image_height + - image_height 参数定义了图像的高度。它与 image_width 类似,在根据图像大小缩放掩码尺寸方面起着类似的作用。 + - Comfy dtype: int + - Python dtype: int +## Optional +- copy_image_size + - 可选的 copy_image_size 参数允许掩码采用所提供图像的尺寸。这对于创建基于所应用图像的动态尺寸的掩码非常有用。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor + +# Output types +- mask + - 输出掩码是一个二进制图像,表示由输入参数定义的矩形区域。它是各种图像处理任务(如对象分割或掩码)的关键组件。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CreateRectMask: + """ + Creates a rectangle mask. If copy_image_size is provided, the image_width and image_height parameters are ignored and the size of the given images will be used instead. + """ + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'mode': (['percent', 'pixels'],), 'origin': (['topleft', 'bottomleft', 'topright', 'bottomright'],), 'x': ('FLOAT', {'default': 0, 'min': 0, 'max': VERY_BIG_SIZE, 'step': 1}), 'y': ('FLOAT', {'default': 0, 'min': 0, 'max': VERY_BIG_SIZE, 'step': 1}), 'width': ('FLOAT', {'default': 50, 'min': 0, 'max': VERY_BIG_SIZE, 'step': 1}), 'height': ('FLOAT', {'default': 50, 'min': 0, 'max': VERY_BIG_SIZE, 'step': 1}), 'image_width': ('INT', {'default': 512, 'min': 64, 'max': VERY_BIG_SIZE, 'step': 64}), 'image_height': ('INT', {'default': 512, 'min': 64, 'max': VERY_BIG_SIZE, 'step': 64})}, 'optional': {'copy_image_size': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'create_mask' + CATEGORY = 'Masquerade Nodes' + + def create_mask(self, mode, origin, x, y, width, height, image_width, image_height, copy_image_size=None): + min_x = x + min_y = y + max_x = min_x + width + max_y = min_y + height + if copy_image_size is not None: + size = copy_image_size.size() + image_width = size[2] + image_height = size[1] + if mode == 'percent': + min_x = min_x / 100.0 * image_width + max_x = max_x / 100.0 * image_width + min_y = min_y / 100.0 * image_height + max_y = max_y / 100.0 * image_height + if origin == 'bottomleft' or origin == 'bottomright': + (min_y, max_y) = (image_height - max_y, image_height - min_y) + if origin == 'topright' or origin == 'bottomright': + (min_x, max_x) = (image_width - max_x, image_width - min_x) + mask = torch.zeros((image_height, image_width)) + mask[int(min_y):int(max_y) + 1, int(min_x):int(max_x) + 1] = 1 + return (mask.unsqueeze(0),) +``` \ No newline at end of file diff --git a/docs/CreateAudioMask.md b/docs/CreateAudioMask.md new file mode 100644 index 0000000..328ff67 --- /dev/null +++ b/docs/CreateAudioMask.md @@ -0,0 +1,91 @@ +# Documentation +- Class name: CreateAudioMask +- Category: KJNodes/deprecated +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +CreateAudioMask节点旨在将音频信号转换为视觉表示,具体是创建与音频频率内容相对应的掩码。它使用librosa库从音频文件生成频谱图,然后将该频谱图可视化为一系列圆圈,其大小与不同频率下音频的幅度成比例。该节点通过提供一种可视化音频频率随时间演变的方法,为音频到视觉的转换过程做出了贡献。 + +# Input types +## Required +- invert + - ‘invert’参数决定生成的掩码在颜色上是否应该被反转。在掩码和背景之间对比度至关重要的应用中,这可能非常重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- frames + - ‘frames’参数指定从音频文件处理的帧数。它对于控制音频到视觉转换的时间分辨率至关重要。 + - Comfy dtype: INT + - Python dtype: int +- scale + - ‘scale’参数调整生成掩码中圆圈的大小,与音频帧的平均幅度成比例。它在音频频率内容的视觉表示中起着至关重要的作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- audio_path + - ‘audio_path’参数定义了用于生成掩码的音频文件的路径。它是一个关键输入,因为它直接影响生成的掩码的内容和质量。 + - Comfy dtype: STRING + - Python dtype: str +- width + - ‘width’参数设置输出图像的宽度,以像素为单位。它是定义视觉表示空间维度的一个重要参数。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’参数设置输出图像的高度,以像素为单位。它与‘width’参数协同工作,以确定视觉表示的整体形状。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output_image + - 'output_image' 是音频数据的视觉表示,作为音频到视觉转换过程的结果生成。它在一个单一图像中封装了音频的时间和频率特征。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 'mask'输出提供了音频频率内容的二进制表示,突出显示了音频信号中幅度显著的区域。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CreateAudioMask: + + def __init__(self): + try: + import librosa + self.librosa = librosa + except ImportError: + print("Can not import librosa. Install it with 'pip install librosa'") + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'createaudiomask' + CATEGORY = 'KJNodes/deprecated' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'invert': ('BOOLEAN', {'default': False}), 'frames': ('INT', {'default': 16, 'min': 1, 'max': 255, 'step': 1}), 'scale': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 2.0, 'step': 0.01}), 'audio_path': ('STRING', {'default': 'audio.wav'}), 'width': ('INT', {'default': 256, 'min': 16, 'max': 4096, 'step': 1}), 'height': ('INT', {'default': 256, 'min': 16, 'max': 4096, 'step': 1})}} + + def createaudiomask(self, frames, width, height, invert, audio_path, scale): + batch_size = frames + out = [] + masks = [] + if audio_path == 'audio.wav': + audio_path = os.path.join(script_directory, audio_path) + (audio, sr) = self.librosa.load(audio_path) + spectrogram = np.abs(self.librosa.stft(audio)) + for i in range(batch_size): + image = Image.new('RGB', (width, height), 'black') + draw = ImageDraw.Draw(image) + frame = spectrogram[:, i] + circle_radius = int(height * np.mean(frame)) + circle_radius *= scale + circle_center = (width // 2, height // 2) + draw.ellipse([(circle_center[0] - circle_radius, circle_center[1] - circle_radius), (circle_center[0] + circle_radius, circle_center[1] + circle_radius)], fill='white') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + mask = image[:, :, :, 0] + masks.append(mask) + out.append(image) + if invert: + return (1.0 - torch.cat(out, dim=0),) + return (torch.cat(out, dim=0), torch.cat(masks, dim=0)) +``` \ No newline at end of file diff --git a/docs/CreateFadeMask.md b/docs/CreateFadeMask.md new file mode 100644 index 0000000..0d9f15b --- /dev/null +++ b/docs/CreateFadeMask.md @@ -0,0 +1,111 @@ +# Documentation +- Class name: CreateFadeMask +- Category: KJNodes/deprecated +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +CreateFadeMask 节点旨在生成一系列渐变遮罩,平滑地从一种不透明度过渡到另一种。它利用插值技术创建视觉上吸引人的渐变效果,特别适用于视觉效果和图像处理应用。 + +# Input types +## Required +- invert + - ‘invert’参数决定是否需要反转渐变遮罩,这对于某些需要反转不透明度过渡的视觉效果至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- frames + - ‘frames’参数指定渐变遮罩序列中的帧数,这直接影响渐变效果的持续时间和间隔。 + - Comfy dtype: INT + - Python dtype: int +- width + - ‘width’参数设置渐变遮罩中每个帧的宽度,影响输出的整体尺寸。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’参数定义渐变遮罩中每个帧的高度,这对于保持输出的纵横比和视觉一致性至关重要。 + - Comfy dtype: INT + - Python dtype: int +- interpolation + - ‘interpolation’参数选择用于渐变效果的插值类型,这可以显著改变不透明度级别之间过渡的外观。 + - Comfy dtype: COMBO['linear', 'ease_in', 'ease_out', 'ease_in_out'] + - Python dtype: str +- start_level + - ‘start_level’参数设定渐变遮罩的初始不透明度级别,这是确定渐变效果起始点的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- midpoint_level + - ‘midpoint_level’参数指示渐变遮罩序列中点的不透明度级别,有助于控制过渡中心处的渐变速度。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_level + - ‘end_level’参数决定渐变遮罩的最终不透明度级别,这决定了渐变效果如何结束。 + - Comfy dtype: FLOAT + - Python dtype: float +- midpoint_frame + - ‘midpoint_frame’参数指定渐变效果中点发生的帧,允许对过渡的时机进行精确控制。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- mask + - 输出‘mask’是一系列渐变遮罩,它们代表了从开始级别到结束级别的不透明度过渡,根据指定的参数创建。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CreateFadeMask: + RETURN_TYPES = ('MASK',) + FUNCTION = 'createfademask' + CATEGORY = 'KJNodes/deprecated' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'invert': ('BOOLEAN', {'default': False}), 'frames': ('INT', {'default': 2, 'min': 2, 'max': 255, 'step': 1}), 'width': ('INT', {'default': 256, 'min': 16, 'max': 4096, 'step': 1}), 'height': ('INT', {'default': 256, 'min': 16, 'max': 4096, 'step': 1}), 'interpolation': (['linear', 'ease_in', 'ease_out', 'ease_in_out'],), 'start_level': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'midpoint_level': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'end_level': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'midpoint_frame': ('INT', {'default': 0, 'min': 0, 'max': 4096, 'step': 1})}} + + def createfademask(self, frames, width, height, invert, interpolation, start_level, midpoint_level, end_level, midpoint_frame): + + def ease_in(t): + return t * t + + def ease_out(t): + return 1 - (1 - t) * (1 - t) + + def ease_in_out(t): + return 3 * t * t - 2 * t * t * t + batch_size = frames + out = [] + image_batch = np.zeros((batch_size, height, width), dtype=np.float32) + if midpoint_frame == 0: + midpoint_frame = batch_size // 2 + for i in range(batch_size): + if i <= midpoint_frame: + t = i / midpoint_frame + if interpolation == 'ease_in': + t = ease_in(t) + elif interpolation == 'ease_out': + t = ease_out(t) + elif interpolation == 'ease_in_out': + t = ease_in_out(t) + color = start_level - t * (start_level - midpoint_level) + else: + t = (i - midpoint_frame) / (batch_size - midpoint_frame) + if interpolation == 'ease_in': + t = ease_in(t) + elif interpolation == 'ease_out': + t = ease_out(t) + elif interpolation == 'ease_in_out': + t = ease_in_out(t) + color = midpoint_level - t * (midpoint_level - end_level) + color = np.clip(color, 0, 255) + image = np.full((height, width), color, dtype=np.float32) + image_batch[i] = image + output = torch.from_numpy(image_batch) + mask = output + out.append(mask) + if invert: + return (1.0 - torch.cat(out, dim=0),) + return (torch.cat(out, dim=0),) +``` \ No newline at end of file diff --git a/docs/CreateFluidMask.md b/docs/CreateFluidMask.md new file mode 100644 index 0000000..d319e32 --- /dev/null +++ b/docs/CreateFluidMask.md @@ -0,0 +1,116 @@ +# Documentation +- Class name: CreateFluidMask +- Category: KJNodes/masking/generate +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +CreateFluidMask 节点旨在生成流体动画效果,可用于创建动态且视觉上吸引人的遮罩覆盖层。它利用流体动力学的原理来模拟指定分辨率和持续时间内的流入和染料运动,生成一系列图像及其对应的遮罩。 + +# Input types +## Required +- frames + - 'frames' 参数决定了要为流体遮罩动画生成的总帧数。它至关重要,因为它决定了动画序列的长度,并通过流体运动影响整体的视觉叙事。 + - Comfy dtype: INT + - Python dtype: int +- width + - 'width' 参数设置了生成的流体遮罩的宽度,以像素为单位。它是一个重要参数,因为它定义了沿 x 轴的空间分辨率,影响输出的细节和质量。 + - Comfy dtype: INT + - Python dtype: int +- height + - 'height' 参数指定了生成的流体遮罩的高度,以像素为单位。它在建立输出的垂直分辨率方面起着重要作用,影响动画中可见的细节水平。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- invert + - 'invert' 参数允许对生成的遮罩进行反转。当设置为 True 时,它会翻转遮罩,创造出用于同视觉结果的对比效果。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- inflow_count + - 'inflow_count' 参数决定了在流体模拟中要考虑的流入点的数量。它影响流体流动的复杂性和分布,有助于整体遮罩的美学。 + - Comfy dtype: INT + - Python dtype: int +- inflow_velocity + - 'inflow_velocity' 参数设置了流入点的速度,影响流体在模拟中的移动和分散速度。它是控制流体动画动态的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- inflow_radius + - 'inflow_radius' 参数定义了每个流入点的影响半径,决定了流入影响的区域。它在塑造流体遮罩的外观中起着至关重要的作用。 + - Comfy dtype: INT + - Python dtype: int +- inflow_padding + - 'inflow_padding' 参数在流入点周围添加填充,以防止流体直接撞击遮罩的边缘。它有助于在边界处为流体流动创建更平滑的过渡。 + - Comfy dtype: INT + - Python dtype: int +- inflow_duration + - 'inflow_duration' 参数指定了流入在模拟期间将活跃的持续时间。它对于控制动画序列内流体效果的时间至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - 'IMAGE' 输出提供了由流体模拟生成的图像序列。每个图像代表动画中的一帧,展示了随时间变化的流体运动和染料分散。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- MASK + - 'MASK' 输出由与 'IMAGE' 输出中每一帧对应的二进制遮罩组成。这些遮罩描绘了流体存在的区域,为流体和背景之间提供了清晰的区分。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CreateFluidMask: + RETURN_TYPES = ('IMAGE', 'MASK') + FUNCTION = 'createfluidmask' + CATEGORY = 'KJNodes/masking/generate' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'invert': ('BOOLEAN', {'default': False}), 'frames': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1}), 'width': ('INT', {'default': 256, 'min': 16, 'max': 4096, 'step': 1}), 'height': ('INT', {'default': 256, 'min': 16, 'max': 4096, 'step': 1}), 'inflow_count': ('INT', {'default': 3, 'min': 0, 'max': 255, 'step': 1}), 'inflow_velocity': ('INT', {'default': 1, 'min': 0, 'max': 255, 'step': 1}), 'inflow_radius': ('INT', {'default': 8, 'min': 0, 'max': 255, 'step': 1}), 'inflow_padding': ('INT', {'default': 50, 'min': 0, 'max': 255, 'step': 1}), 'inflow_duration': ('INT', {'default': 60, 'min': 0, 'max': 255, 'step': 1})}} + + def createfluidmask(self, frames, width, height, invert, inflow_count, inflow_velocity, inflow_radius, inflow_padding, inflow_duration): + from .fluid import Fluid + from scipy.spatial import erf + out = [] + masks = [] + RESOLUTION = (width, height) + DURATION = frames + INFLOW_PADDING = inflow_padding + INFLOW_DURATION = inflow_duration + INFLOW_RADIUS = inflow_radius + INFLOW_VELOCITY = inflow_velocity + INFLOW_COUNT = inflow_count + print('Generating fluid solver, this may take some time.') + fluid = Fluid(RESOLUTION, 'dye') + center = np.floor_divide(RESOLUTION, 2) + r = np.min(center) - INFLOW_PADDING + points = np.linspace(-np.pi, np.pi, INFLOW_COUNT, endpoint=False) + points = tuple((np.array((np.cos(p), np.sin(p))) for p in points)) + normals = tuple((-p for p in points)) + points = tuple((r * p + center for p in points)) + inflow_velocity = np.zeros_like(fluid.velocity) + inflow_dye = np.zeros(fluid.shape) + for (p, n) in zip(points, normals): + mask = np.linalg.norm(fluid.indices - p[:, None, None], axis=0) <= INFLOW_RADIUS + inflow_velocity[:, mask] += n[:, None] * INFLOW_VELOCITY + inflow_dye[mask] = 1 + for f in range(DURATION): + print(f'Computing frame {f + 1} of {DURATION}.') + if f <= INFLOW_DURATION: + fluid.velocity += inflow_velocity + fluid.dye += inflow_dye + curl = fluid.step()[1] + curl = (erf(curl * 2) + 1) / 4 + color = np.dstack((curl, np.ones(fluid.shape), fluid.dye)) + color = (np.clip(color, 0, 1) * 255).astype('uint8') + image = np.array(color).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + mask = image[:, :, :, 0] + masks.append(mask) + out.append(image) + if invert: + return (1.0 - torch.cat(out, dim=0), 1.0 - torch.cat(masks, dim=0)) + return (torch.cat(out, dim=0), torch.cat(masks, dim=0)) +``` \ No newline at end of file diff --git a/docs/CreateGradientMask.md b/docs/CreateGradientMask.md new file mode 100644 index 0000000..a05bde3 --- /dev/null +++ b/docs/CreateGradientMask.md @@ -0,0 +1,63 @@ +# Documentation +- Class name: CreateGradientMask +- Category: KJNodes/masking/generate +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +CreateGradientMask 节点旨在生成可用于各种图像处理任务的渐变蒙版。它通过计算图像宽度上的线性渐变来创建蒙版,然后根据帧序列中的当前帧对渐变进行调整。这允许实现可以随着时间变化或在图像的不同部分变化的动态遮罩效果。 + +# Input types +## Required +- invert + - 'invert' 参数决定是否需要将渐变蒙版反转。这对于创建互补蒙版或基于蒙版的方向应用不同的效果非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- frames + - 'frames' 参数指定了要生成蒙版的帧数。它直接影响输出的批次大小,对于创建动画或时间变化效果至关重要。 + - Comfy dtype: INT + - Python dtype: int +- width + - 'width' 参数以像素为单位设置渐变蒙版的宽度。它对于定义蒙版的空间分辨率和影响渐变的粒度至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 'height' 参数以像素为单位设置渐变蒙版的高度。它与 'width' 参数一起工作,以确定蒙版的总体大小。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MASK + - 输出的 MASK 是表示渐变蒙版的张量。它是后续图像操作和效果应用的关键组件。 + - Comfy dtype: TORCH.TENSOR + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CreateGradientMask: + RETURN_TYPES = ('MASK',) + FUNCTION = 'createmask' + CATEGORY = 'KJNodes/masking/generate' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'invert': ('BOOLEAN', {'default': False}), 'frames': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1}), 'width': ('INT', {'default': 256, 'min': 16, 'max': 4096, 'step': 1}), 'height': ('INT', {'default': 256, 'min': 16, 'max': 4096, 'step': 1})}} + + def createmask(self, frames, width, height, invert): + batch_size = frames + out = [] + image_batch = np.zeros((batch_size, height, width), dtype=np.float32) + for i in range(batch_size): + gradient = np.linspace(1.0, 0.0, width, dtype=np.float32) + time = i / frames + offset_gradient = gradient - time + image_batch[i] = offset_gradient.reshape(1, -1) + output = torch.from_numpy(image_batch) + mask = output + out.append(mask) + if invert: + return (1.0 - torch.cat(out, dim=0),) + return (torch.cat(out, dim=0),) +``` \ No newline at end of file diff --git a/docs/CreateMagicMask.md b/docs/CreateMagicMask.md new file mode 100644 index 0000000..d996ab1 --- /dev/null +++ b/docs/CreateMagicMask.md @@ -0,0 +1,96 @@ +# Documentation +- Class name: CreateMagicMask +- Category: KJNodes/masking/generate +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +CreateMagicMask 节点旨在生成一对具有不同复杂度和细节的遮罩。它利用程序化生成的原理,创造出视觉上引人入胜的图案,可以用于从视觉效果到艺术作品的广泛应用。该节点通过使用一组参数来操作,这些参数定义了生成遮罩的特征,例如帧数、过渡、深度、扭曲、种子和帧尺寸。结果是动态的、可定制的遮罩,可以反转以产生多种效果。 + +# Input types +## Required +- frames + - ‘frames’参数决定了为遮罩序列生成的总帧数。它是定义动画长度和复杂度的关键因素。帧数越多,过渡越平滑,图案越复杂,但这也增加了计算负载。 + - Comfy dtype: INT + - Python dtype: int +- transitions + - ‘transitions’参数指定了遮罩序列内的过渡次数。每次过渡都会引入图案的变化,有助于整体视觉动态。它影响遮罩外观随时间演变的多样性和速度。 + - Comfy dtype: INT + - Python dtype: int +- depth + - ‘depth’参数通过指定应用于基础坐标的变换次数来控制生成遮罩的细节水平。更大的深度值增强了图案的复杂性,创造出更多嵌套和复杂的结构。 + - Comfy dtype: INT + - Python dtype: int +- distortion + - ‘distortion’参数影响遮罩图案的不规则程度。它为生成的形状和形式引入了可变性,允许广泛的视觉效果。更高的扭曲值可以导致更抽象和不可预测的图案。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - ‘seed’参数用于初始化随机数生成器,确保遮罩生成过程的可重复性。当使用相同设置重新运行节点时,获得一致结果至关重要。 + - Comfy dtype: INT + - Python dtype: int +- frame_width + - ‘frame_width’参数定义了遮罩序列中每个帧的宽度。它在确定视觉输出的分辨率和规模方面起着重要作用。更大的帧宽度可以容纳更多细节,但可能需要更多的内存和处理能力。 + - Comfy dtype: INT + - Python dtype: int +- frame_height + - ‘frame_height’参数设置了遮罩序列中每个帧的高度,与frame_width相辅相成,建立视觉画布的整体尺寸。它是展示和框架生成内容的关键因素。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- mask + - 'mask' 输出提供了作为帧堆叠的生成遮罩序列,每一帧代表遮罩演变的一个阶段。它是进一步处理或在视觉应用中直接使用的关键组成部分。 + - Comfy dtype: TORCH_TENSOR + - Python dtype: torch.Tensor +- mask_inverted + - 'mask_inverted' 输出展示了生成遮罩序列的反转,提供了一种可以用于创建对比或突出内容不同方面的替代视觉效果。 + - Comfy dtype: TORCH_TENSOR + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CreateMagicMask: + RETURN_TYPES = ('MASK', 'MASK') + RETURN_NAMES = ('mask', 'mask_inverted') + FUNCTION = 'createmagicmask' + CATEGORY = 'KJNodes/masking/generate' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'frames': ('INT', {'default': 16, 'min': 2, 'max': 4096, 'step': 1}), 'depth': ('INT', {'default': 12, 'min': 1, 'max': 500, 'step': 1}), 'distortion': ('FLOAT', {'default': 1.5, 'min': 0.0, 'max': 100.0, 'step': 0.01}), 'seed': ('INT', {'default': 123, 'min': 0, 'max': 99999999, 'step': 1}), 'transitions': ('INT', {'default': 1, 'min': 1, 'max': 20, 'step': 1}), 'frame_width': ('INT', {'default': 512, 'min': 16, 'max': 4096, 'step': 1}), 'frame_height': ('INT', {'default': 512, 'min': 16, 'max': 4096, 'step': 1})}} + + def createmagicmask(self, frames, transitions, depth, distortion, seed, frame_width, frame_height): + from .magictex import coordinate_grid, random_transform, magic + rng = np.random.default_rng(seed) + out = [] + coords = coordinate_grid((frame_width, frame_height)) + frames_per_transition = frames // transitions + base_params = {'coords': random_transform(coords, rng), 'depth': depth, 'distortion': distortion} + for t in range(transitions): + params1 = base_params.copy() + params2 = base_params.copy() + params1['coords'] = random_transform(coords, rng) + params2['coords'] = random_transform(coords, rng) + for i in range(frames_per_transition): + alpha = i / frames_per_transition + params = params1.copy() + params['coords'] = (1 - alpha) * params1['coords'] + alpha * params2['coords'] + tex = magic(**params) + dpi = frame_width / 10 + fig = plt.figure(figsize=(10, 10), dpi=dpi) + ax = fig.add_subplot(111) + plt.subplots_adjust(left=0, right=1, bottom=0, top=1) + ax.get_yaxis().set_ticks([]) + ax.get_xaxis().set_ticks([]) + ax.imshow(tex, aspect='auto') + fig.canvas.draw() + img = np.array(fig.canvas.renderer._renderer) + plt.close(fig) + pil_img = Image.fromarray(img).convert('L') + mask = torch.tensor(np.array(pil_img)) / 255.0 + out.append(mask) + return (torch.stack(out, dim=0), 1.0 - torch.stack(out, dim=0)) +``` \ No newline at end of file diff --git a/docs/CreatePromptVariant.md b/docs/CreatePromptVariant.md new file mode 100644 index 0000000..a045351 --- /dev/null +++ b/docs/CreatePromptVariant.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: CreatePromptVariant +- Category: OneButtonPrompt +- Output node: False +- Repo Ref: https://github.com/AIrjen/OneButtonPrompt + +CreatePromptVariant节点旨在根据用户输入和附加参数生成多样化和富有创造力的文本提示。它通过操作和组合各种元素,如对象、角色和场景,构建独特且引人入胜的文本提示,适用于内容创作和创意生成的广泛应用。 + +# Input types +## Required +- prompt_input + - 输入提示是节点操作的基础,提供了生成内容的上下文和主题。它对于设定生成内容的初始方向和范围至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- insanitylevel + - 疯狂等级参数控制应用于输入提示的变化和创造性程度。更高的等级会产生更多样化且可能非常规的输出,引入更广泛的想法和可能性。 + - Comfy dtype: INT + - Python dtype: int +- seed + - 种子参数用于确保节点输出的可复现性。通过指定一个种子,用户可以在不同的运行中生成一致的结果,这对于测试和调试非常有益。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- prompt + - 输出是基于输入参数进行了修改和增强的原始提示的版本。它包含了各种元素和调整,代表了可以激发进一步开发和探索的新创意方向。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CreatePromptVariant: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompt_input': ('STRING', {'default': '', 'multiline': True})}, 'optional': {'insanitylevel': ('INT', {'default': 5, 'min': 1, 'max': 10, 'step': 1}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('prompt',) + FUNCTION = 'Comfy_OBP_PromptVariant' + CATEGORY = 'OneButtonPrompt' + + def Comfy_OBP_PromptVariant(self, prompt_input, insanitylevel, seed): + generatedprompt = createpromptvariant(prompt_input, insanitylevel) + print(generatedprompt) + return (generatedprompt,) +``` \ No newline at end of file diff --git a/docs/CreateVoronoiMask.md b/docs/CreateVoronoiMask.md new file mode 100644 index 0000000..a6074ab --- /dev/null +++ b/docs/CreateVoronoiMask.md @@ -0,0 +1,95 @@ +# Documentation +- Class name: CreateVoronoiMask +- Category: KJNodes/masking/generate +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +方法 'createvoronoi' 旨在生成一个Voronoi遮罩,这是一种几何图案,可用于各种图像处理任务。它利用Voronoi图的随机性来创建独特和复杂的图案,这些图案可以根据点的数量、线宽以及起始点和结束点之间的转换速度进行调整。 + +# Input types +## Required +- frames + - 参数 'frames' 确定在Voronoi遮罩序列中生成的帧数。它对于定义输出动画或图案的长度至关重要。 + - Comfy dtype: INT + - Python dtype: int +- num_points + - 参数 'num_points' 指定用于创建Voronoi图的点的数量。它直接影响生成的遮罩的复杂性和细节。 + - Comfy dtype: INT + - Python dtype: int +- line_width + - 参数 'line_width' 控制Voronoi遮罩中线的粗细。它是确定图案特征可见性和突出度的重要因素。 + - Comfy dtype: INT + - Python dtype: int +- speed + - 参数 'speed' 决定点从起始位置过渡到结束位置的速率。它影响遮罩序列中的动态运动。 + - Comfy dtype: FLOAT + - Python dtype: float +- frame_width + - 参数 'frame_width' 设置遮罩序列中每个帧的宽度。它对于定义输出的纵横比和整体尺寸至关重要。 + - Comfy dtype: INT + - Python dtype: int +- frame_height + - 参数 'frame_height' 确定遮罩序列中每个帧的高度。它与 'frame_width' 一起工作,以确定输出的整体形状。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- mask + - 输出参数 'mask' 表示生成的Voronoi遮罩作为张量。这是一个二进制图像,其中遮罩的图案已编码,准备进行进一步处理或应用。 + - Comfy dtype: TORCH.TENSOR + - Python dtype: torch.Tensor +- mask_inverted + - 输出参数 'mask_inverted' 提供了生成的Voronoi遮罩的反转版本。这对于在图像处理中创建补充图案或效果非常有用。 + - Comfy dtype: TORCH.TENSOR + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CreateVoronoiMask: + RETURN_TYPES = ('MASK', 'MASK') + RETURN_NAMES = ('mask', 'mask_inverted') + FUNCTION = 'createvoronoi' + CATEGORY = 'KJNodes/masking/generate' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'frames': ('INT', {'default': 16, 'min': 2, 'max': 4096, 'step': 1}), 'num_points': ('INT', {'default': 15, 'min': 1, 'max': 4096, 'step': 1}), 'line_width': ('INT', {'default': 4, 'min': 1, 'max': 4096, 'step': 1}), 'speed': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'frame_width': ('INT', {'default': 512, 'min': 16, 'max': 4096, 'step': 1}), 'frame_height': ('INT', {'default': 512, 'min': 16, 'max': 4096, 'step': 1})}} + + def createvoronoi(self, frames, num_points, line_width, speed, frame_width, frame_height): + from scipy.spatial import Voronoi + batch_size = frames + out = [] + aspect_ratio = frame_width / frame_height + start_points = np.random.rand(num_points, 2) + start_points[:, 0] *= aspect_ratio + end_points = np.random.rand(num_points, 2) + end_points[:, 0] *= aspect_ratio + for i in range(batch_size): + t = i * speed / (batch_size - 1) + t = np.clip(t, 0, 1) + points = (1 - t) * start_points + t * end_points + points[:, 0] *= aspect_ratio + vor = Voronoi(points) + (fig, ax) = plt.subplots() + plt.subplots_adjust(left=0, right=1, bottom=0, top=1) + ax.set_xlim([0, aspect_ratio]) + ax.set_ylim([0, 1]) + ax.axis('off') + ax.margins(0, 0) + fig.set_size_inches(aspect_ratio * frame_height / 100, frame_height / 100) + ax.fill_between([0, 1], [0, 1], color='white') + for simplex in vor.ridge_vertices: + simplex = np.asarray(simplex) + if np.all(simplex >= 0): + plt.plot(vor.vertices[simplex, 0], vor.vertices[simplex, 1], 'k-', linewidth=line_width) + fig.canvas.draw() + img = np.array(fig.canvas.renderer._renderer) + plt.close(fig) + pil_img = Image.fromarray(img).convert('L') + mask = torch.tensor(np.array(pil_img)) / 255.0 + out.append(mask) + return (torch.stack(out, dim=0), 1.0 - torch.stack(out, dim=0)) +``` \ No newline at end of file diff --git a/docs/Crop (mtb).md b/docs/Crop (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/CropFace.md b/docs/CropFace.md new file mode 100644 index 0000000..212afc2 --- /dev/null +++ b/docs/CropFace.md @@ -0,0 +1,82 @@ +# Documentation +- Class name: CropFace +- Category: facerestore_cf +- Output node: False +- Repo Ref: https://github.com/mav-rik/facerestore_cf + +CropFace节点旨在从输入的图像中提取和处理面部区域。它利用检测模型来识别面部,然后根据预定义的模板裁剪和对齐它们。该节点的主要功能是通过确保面部被隔离并按大小和方向标准化,为进一步的处理(如恢复或识别)准备面部图像。 + +# Input types +## Required +- image + - 输入图像对于节点执行面部检测和裁剪至关重要。它是提取和处理面部区域的来源。没有有效的图像,节点无法执行其预期功能。 + - Comfy dtype: IMAGE + - Python dtype: numpy.ndarray +## Optional +- facedetection + - facedetection参数指定用于在输入图像中识别面部的检测模型。它影响面部检测过程的准确性和效率,进而影响裁剪面部图像的质量。 + - Comfy dtype: COMBO[retinaface_resnet50, retinaface_mobile0.25, YOLOv5l, YOLOv5n] + - Python dtype: str + +# Output types +- IMAGE + - 输出包括裁剪和对齐的面部图像,这些图像准备好进行进一步处理。这些输出是节点面部检测和图像处理能力的成果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CropFace: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'facedetection': (['retinaface_resnet50', 'retinaface_mobile0.25', 'YOLOv5l', 'YOLOv5n'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'crop_face' + CATEGORY = 'facerestore_cf' + + def __init__(self): + self.face_helper = None + + def crop_face(self, image, facedetection): + device = model_management.get_torch_device() + if self.face_helper is None: + self.face_helper = FaceRestoreHelper(1, face_size=512, crop_ratio=(1, 1), det_model=facedetection, save_ext='png', use_parse=True, device=device) + image_np = 255.0 * image.cpu().numpy() + total_images = image_np.shape[0] + out_images = np.ndarray(shape=(total_images, 512, 512, 3)) + next_idx = 0 + for i in range(total_images): + cur_image_np = image_np[i, :, :, ::-1] + original_resolution = cur_image_np.shape[0:2] + if self.face_helper is None: + return image + self.face_helper.clean_all() + self.face_helper.read_image(cur_image_np) + self.face_helper.get_face_landmarks_5(only_center_face=False, resize=640, eye_dist_threshold=5) + self.face_helper.align_warp_face() + faces_found = len(self.face_helper.cropped_faces) + if faces_found == 0: + next_idx += 1 + if out_images.shape[0] < next_idx + faces_found: + print(out_images.shape) + print((next_idx + faces_found, 512, 512, 3)) + print('aaaaa') + out_images = np.resize(out_images, (next_idx + faces_found, 512, 512, 3)) + print(out_images.shape) + for j in range(faces_found): + cropped_face_1 = self.face_helper.cropped_faces[j] + cropped_face_2 = img2tensor(cropped_face_1 / 255.0, bgr2rgb=True, float32=True) + normalize(cropped_face_2, (0.5, 0.5, 0.5), (0.5, 0.5, 0.5), inplace=True) + cropped_face_3 = cropped_face_2.unsqueeze(0).to(device) + cropped_face_4 = tensor2img(cropped_face_3, rgb2bgr=True, min_max=(-1, 1)).astype('uint8') + cropped_face_5 = cv2.cvtColor(cropped_face_4, cv2.COLOR_BGR2RGB) + out_images[next_idx] = cropped_face_5 + next_idx += 1 + cropped_face_6 = np.array(out_images).astype(np.float32) / 255.0 + cropped_face_7 = torch.from_numpy(cropped_face_6) + return (cropped_face_7,) +``` \ No newline at end of file diff --git a/docs/CrossFadeImages.md b/docs/CrossFadeImages.md new file mode 100644 index 0000000..0b2e6d6 --- /dev/null +++ b/docs/CrossFadeImages.md @@ -0,0 +1,115 @@ +# Documentation +- Class name: CrossFadeImages +- Category: KJNodes/image +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +CrossFadeImages节点旨在使用交叉淡化技术无缝地混合两组图像。它应用了一种过渡效果,平滑地在起始图像和结束图像之间进行插值,创建出视觉上吸引人的变形序列。当需要从一张图像逐渐变化到另一张图像时,此节点特别有用,适用于创建动画过渡或视觉效果。 + +# Input types +## Required +- images_1 + - 过渡期间将逐渐淡出的第一组图像。这些图像构成了交叉淡化效果的起点,对于初始视觉表现至关重要。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +- images_2 + - 过渡期间将逐渐显现的第二组图像。这些图像代表了交叉淡化的结束状态,对最终视觉效果至关重要。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +## Optional +- interpolation + - 用于交叉淡化效果的插值类型。此参数决定了图像之间变化的速率,可以显著影响过渡的视觉动态。 + - Comfy dtype: COMBO['linear', 'ease_in', 'ease_out', 'ease_in_out', 'bounce', 'elastic', 'glitchy', 'exponential_ease_out'] + - Python dtype: str +- transition_start_index + - 交叉淡化过渡开始的索引。此参数允许控制图像序列中淡入过程的起始点。 + - Comfy dtype: INT + - Python dtype: int +- transitioning_frames + - 交叉淡化过渡发生的帧数。此参数定义了动画序列中过渡效果的持续时间。 + - Comfy dtype: INT + - Python dtype: int +- start_level + - 交叉淡化的起始alpha级别,它决定了images_2相对于images_1的初始不透明度。值为0.0意味着images_1将完全不透明,而images_2将完全透明。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_level + - 交叉淡化的结束alpha级别,它决定了images_2相对于images_1的最终不透明度。值为1.0意味着images_2将完全不透明,而images_1将完全透明。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- crossfade_images + - 节点的输出是代表交叉淡化过渡的图像序列。序列中的每张图像都是输入图像的混合,混合程度由指定的alpha级别和缓动函数确定。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CrossFadeImages: + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'crossfadeimages' + CATEGORY = 'KJNodes/image' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images_1': ('IMAGE',), 'images_2': ('IMAGE',), 'interpolation': (['linear', 'ease_in', 'ease_out', 'ease_in_out', 'bounce', 'elastic', 'glitchy', 'exponential_ease_out'],), 'transition_start_index': ('INT', {'default': 1, 'min': 0, 'max': 4096, 'step': 1}), 'transitioning_frames': ('INT', {'default': 1, 'min': 0, 'max': 4096, 'step': 1}), 'start_level': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'end_level': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + + def crossfadeimages(self, images_1, images_2, transition_start_index, transitioning_frames, interpolation, start_level, end_level): + + def crossfade(images_1, images_2, alpha): + crossfade = (1 - alpha) * images_1 + alpha * images_2 + return crossfade + + def ease_in(t): + return t * t + + def ease_out(t): + return 1 - (1 - t) * (1 - t) + + def ease_in_out(t): + return 3 * t * t - 2 * t * t * t + + def bounce(t): + if t < 0.5: + return self.ease_out(t * 2) * 0.5 + else: + return self.ease_in((t - 0.5) * 2) * 0.5 + 0.5 + + def elastic(t): + return math.sin(13 * math.pi / 2 * t) * math.pow(2, 10 * (t - 1)) + + def glitchy(t): + return t + 0.1 * math.sin(40 * t) + + def exponential_ease_out(t): + return 1 - (1 - t) ** 4 + easing_functions = {'linear': lambda t: t, 'ease_in': ease_in, 'ease_out': ease_out, 'ease_in_out': ease_in_out, 'bounce': bounce, 'elastic': elastic, 'glitchy': glitchy, 'exponential_ease_out': exponential_ease_out} + crossfade_images = [] + alphas = torch.linspace(start_level, end_level, transitioning_frames) + for i in range(transitioning_frames): + alpha = alphas[i] + image1 = images_1[i + transition_start_index] + image2 = images_2[i + transition_start_index] + easing_function = easing_functions.get(interpolation) + alpha = easing_function(alpha) + crossfade_image = crossfade(image1, image2, alpha) + crossfade_images.append(crossfade_image) + crossfade_images = torch.stack(crossfade_images, dim=0) + last_frame = crossfade_images[-1] + remaining_frames = len(images_2) - (transition_start_index + transitioning_frames) + for i in range(remaining_frames): + alpha = alphas[-1] + image1 = images_1[i + transition_start_index + transitioning_frames] + image2 = images_2[i + transition_start_index + transitioning_frames] + easing_function = easing_functions.get(interpolation) + alpha = easing_function(alpha) + crossfade_image = crossfade(image1, image2, alpha) + crossfade_images = torch.cat([crossfade_images, crossfade_image.unsqueeze(0)], dim=0) + beginning_images_1 = images_1[:transition_start_index] + crossfade_images = torch.cat([beginning_images_1, crossfade_images], dim=0) + return (crossfade_images,) +``` \ No newline at end of file diff --git a/docs/Curve (mtb).md b/docs/Curve (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Curve To Float (mtb).md b/docs/Curve To Float (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/CustomControlNetWeights.md b/docs/CustomControlNetWeights.md new file mode 100644 index 0000000..032454f --- /dev/null +++ b/docs/CustomControlNetWeights.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: CustomControlNetWeights +- Category: Adv-ControlNet 🛂🅐🅒🅝/weights/ControlNet +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +CustomControlNetWeights 类用于管理和应用自定义权重到控制网络中,允许微调网络的行为。它封装了加载和处理权重的逻辑,确保权重正确地集成到网络的运行中。 + +# Input types +## Required +- weight_00 + - 权重参数对于调整网络内特定控制机制的影响至关重要。它允许对网络如何响应输入数据的不同方面进行精确控制。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- flip_weights + - flip_weights 参数决定在处理过程中是否应翻转权重,这对于网络内的某些类型的转换或调整可能很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- weights + - 权重输出代表处理过的和自定义的控制网络权重,准备应用于网络以执行特定任务或转换。 + - Comfy dtype: CONTROL_NET_WEIGHTS + - Python dtype: ControlWeights +- timestep_keyframe + - timestep_keyframe 输出提供了控制网络在特定时间点的状态的结构化表示,可用于网络运行中精确的时间控制。 + - Comfy dtype: TIMESTEP_KEYFRAME + - Python dtype: TimestepKeyframe + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CustomControlNetWeights: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'weight_00': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_01': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_02': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_03': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_04': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_05': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_06': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_07': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_08': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_09': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_10': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_11': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_12': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'flip_weights': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('CONTROL_NET_WEIGHTS', 'TIMESTEP_KEYFRAME') + RETURN_NAMES = WEIGHTS_RETURN_NAMES + FUNCTION = 'load_weights' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/weights/ControlNet' + + def load_weights(self, weight_00, weight_01, weight_02, weight_03, weight_04, weight_05, weight_06, weight_07, weight_08, weight_09, weight_10, weight_11, weight_12, flip_weights): + weights = [weight_00, weight_01, weight_02, weight_03, weight_04, weight_05, weight_06, weight_07, weight_08, weight_09, weight_10, weight_11, weight_12] + weights = ControlWeights.controlnet(weights, flip_weights=flip_weights) + return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights))) +``` \ No newline at end of file diff --git a/docs/CustomT2IAdapterWeights.md b/docs/CustomT2IAdapterWeights.md new file mode 100644 index 0000000..f8418ce --- /dev/null +++ b/docs/CustomT2IAdapterWeights.md @@ -0,0 +1,63 @@ +# Documentation +- Class name: CustomT2IAdapterWeights +- Category: Adv-ControlNet 🛂🅐🅒🅝/weights/T2IAdapter +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +CustomT2IAdapterWeights节点旨在管理和调整控制网络的权重,特别适用于将输入数据转换为所需的输出形状。它强调了在不同关键帧上定制权重分布,以实现对转换过程的精确控制。 + +# Input types +## Required +- weight_00 + - weight_00参数对于定义转换的初始影响至关重要。它为输入数据在控制网络中的初始权重设定了一个基线,影响转换过程的整体平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight_01 + - weight_01参数通过调整中间权重值来进一步完善转换过程。它在形成关键帧之间的过渡中起着重要作用,确保转换平滑且连贯。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight_02 + - weight_02参数对于控制转换后期的权重分布至关重要。它确保转换在朝向最终关键帧的过程中保持其预期的方向和强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight_03 + - weight_03参数决定了转换的最终影响,确保输出紧密匹配所需的形状。它是实现转换过程最后阶段所需精度的关键组成部分。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- flip_weights + - flip_weights参数允许权重分布的反转,为转换方向提供了额外的控制层。当转换需要反转标准权重应用顺序时,这可能特别有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- CONTROL_NET_WEIGHTS + - CONTROL_NET_WEIGHTS输出代表了为控制网络定制和排列的适应性权重。这些权重在引导网络的转换能力以实现所需输出形状方面至关重要。 + - Comfy dtype: ControlWeights + - Python dtype: ControlWeights +- TIMESTEP_KEYFRAME + - TIMESTEP_KEYFRAME输出是一系列对应于转换过程中特定时间点的关键帧。这些关键帧在定义转换的时间结构和进度方面起着重要作用。 + - Comfy dtype: TimestepKeyframeGroup + - Python dtype: TimestepKeyframeGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CustomT2IAdapterWeights: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'weight_00': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_01': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_02': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_03': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'flip_weights': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('CONTROL_NET_WEIGHTS', 'TIMESTEP_KEYFRAME') + RETURN_NAMES = WEIGHTS_RETURN_NAMES + FUNCTION = 'load_weights' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/weights/T2IAdapter' + + def load_weights(self, weight_00, weight_01, weight_02, weight_03, flip_weights): + weights = [weight_00, weight_01, weight_02, weight_03] + weights = get_properly_arranged_t2i_weights(weights) + weights = ControlWeights.t2iadapter(weights, flip_weights=flip_weights) + return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights))) +``` \ No newline at end of file diff --git a/docs/Cut By Mask.md b/docs/Cut By Mask.md new file mode 100644 index 0000000..41fac6d --- /dev/null +++ b/docs/Cut By Mask.md @@ -0,0 +1,109 @@ +# Documentation +- Class name: CutByMask +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +CutByMask节点旨在根据掩码的边界框裁剪图像。如果提供了特定的宽度和高度,则能够将图像调整到这些尺寸。此外,它还可以处理多个掩码,从单个图像中提取不同的部分,使其成为图像处理任务中的多功能工具。 + +# Input types +## Required +- image + - 图像参数代表将根据掩码裁剪的输入图像。它是节点操作的基本部分,因为它决定了将要调整大小和处理的内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 掩码参数用于定义裁剪过程后将保留的图像区域。它在确定节点的最终输出中起着关键作用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- force_resize_width + - force_resize_width参数允许调整结果图像的宽度。它是可选的,当需要为输出指定特定宽度时可以使用。 + - Comfy dtype: INT + - Python dtype: int +- force_resize_height + - force_resize_height参数使能调整结果图像的高度。与force_resize_width类似,它是可选的,用于控制输出的垂直尺寸。 + - Comfy dtype: INT + - Python dtype: int +- mask_mapping_optional + - 当提供多个掩码时,使用mask_mapping_optional参数,允许节点根据每个掩码处理图像的不同部分。它增强了节点批量处理的功能。 + - Comfy dtype: MASK_MAPPING + - Python dtype: List[torch.Tensor] + +# Output types +- result + - 结果参数代表CutByMask节点的最终输出,即根据输入参数和掩码裁剪和调整大小后的图像或图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CutByMask: + """ + Cuts the image to the bounding box of the mask. If force_resize_width or force_resize_height are provided, the image will be resized to those dimensions. The `mask_mapping_optional` input can be provided from a 'Separate Mask Components' node to cut multiple pieces out of a single image in a batch. + """ + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'mask': ('IMAGE',), 'force_resize_width': ('INT', {'default': 0, 'min': 0, 'max': VERY_BIG_SIZE, 'step': 1}), 'force_resize_height': ('INT', {'default': 0, 'min': 0, 'max': VERY_BIG_SIZE, 'step': 1})}, 'optional': {'mask_mapping_optional': ('MASK_MAPPING',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'cut' + CATEGORY = 'Masquerade Nodes' + + def cut(self, image, mask, force_resize_width, force_resize_height, mask_mapping_optional=None): + if len(image.shape) < 4: + C = 1 + else: + C = image.shape[3] + image = tensor2rgba(image) + mask = tensor2mask(mask) + if mask_mapping_optional is not None: + image = image[mask_mapping_optional] + (B, H, W, _) = image.shape + mask = torch.nn.functional.interpolate(mask.unsqueeze(1), size=(H, W), mode='nearest')[:, 0, :, :] + (MB, _, _) = mask.shape + if MB < B: + assert B % MB == 0 + mask = mask.repeat(B // MB, 1, 1) + is_empty = ~torch.gt(torch.max(torch.reshape(mask, [MB, H * W]), dim=1).values, 0.0) + mask[is_empty, 0, 0] = 1.0 + boxes = masks_to_boxes(mask) + mask[is_empty, 0, 0] = 0.0 + min_x = boxes[:, 0] + min_y = boxes[:, 1] + max_x = boxes[:, 2] + max_y = boxes[:, 3] + width = max_x - min_x + 1 + height = max_y - min_y + 1 + use_width = int(torch.max(width).item()) + use_height = int(torch.max(height).item()) + if force_resize_width > 0: + use_width = force_resize_width + if force_resize_height > 0: + use_height = force_resize_height + alpha_mask = torch.ones((B, H, W, 4)) + alpha_mask[:, :, :, 3] = mask + image = image * alpha_mask + result = torch.zeros((B, use_height, use_width, 4)) + for i in range(0, B): + if not is_empty[i]: + ymin = int(min_y[i].item()) + ymax = int(max_y[i].item()) + xmin = int(min_x[i].item()) + xmax = int(max_x[i].item()) + single = image[i, ymin:ymax + 1, xmin:xmax + 1, :].unsqueeze(0) + resized = torch.nn.functional.interpolate(single.permute(0, 3, 1, 2), size=(use_height, use_width), mode='bicubic').permute(0, 2, 3, 1) + result[i] = resized[0] + if C == 1: + return (tensor2mask(result),) + elif C == 3 and torch.min(result[:, :, :, 3]) == 1: + return (tensor2rgb(result),) + else: + return (result,) +``` \ No newline at end of file diff --git a/docs/DPCombinatorialGenerator.md b/docs/DPCombinatorialGenerator.md new file mode 100644 index 0000000..39ed580 --- /dev/null +++ b/docs/DPCombinatorialGenerator.md @@ -0,0 +1,37 @@ +# Documentation +- Class name: DPCombinatorialGenerator +- Category: sampling +- Output node: False +- Repo Ref: https://github.com/adieyal/comfyui-dynamicprompts.git + +DPCombinatorialGenerator节点旨在基于给定的上下文生成提示的组合。它利用SamplingContext来确定生成提示的适当方法,在必要时确保采取组合方法。此节点在需要详尽的输入组合以进行彻底抽样的场景中至关重要。 + +# Input types +## Required +- wildcard_manager + - 通配符管理器对于处理提示模板中的占位符至关重要。它影响节点如何解释和替换通配符,因此直接影响生成过程和输出提示的多样性。 + - Comfy dtype: WildcardManager + - Python dtype: WildcardManager +- default_sampling_method + - 默认的抽样方法决定了在没有指定特定方法时用于生成提示的方法。它很重要,因为它为节点的抽样行为设定了基础,影响了提示生成的整体策略。 + - Comfy dtype: SamplingMethod + - Python dtype: SamplingMethod + +# Output types +- prompts + - 输出提示代表了基于输入上下文和抽样方法生成的组合。它们很重要,因为它们是节点操作的直接结果,包含了组合生成过程的精髓。 + - Comfy dtype: Iterable[str] + - Python dtype: Iterable[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DPCombinatorialGenerator(DPAbstractSamplerNode): + + @property + @lru_cache(maxsize=1) + def context(self) -> SamplingContext: + return SamplingContext(wildcard_manager=self._wildcard_manager, default_sampling_method=SamplingMethod.COMBINATORIAL) +``` \ No newline at end of file diff --git a/docs/DPFeelingLucky.md b/docs/DPFeelingLucky.md new file mode 100644 index 0000000..9f2f916 --- /dev/null +++ b/docs/DPFeelingLucky.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: DPFeelingLucky +- Category: Sampling +- Output node: False +- Repo Ref: https://github.com/adieyal/comfyui-dynamicprompts.git + +该节点旨在通过利用随机种子和幸运感觉方法生成富有创意和潜在意外的提示。它旨在引入变异性和新颖性到采样过程中,为输出结果的多样性做出贡献。 + +# Input types +## Required +- text + - 输入文本是生成提示的基础。它至关重要,因为它为节点提供了上下文和内容,直接影响生成提示的相关性和创造性。 + - Comfy dtype: str + - Python dtype: str +## Optional +- seed + - 种子参数对于控制生成提示的随机性至关重要。它确保当种子固定时,相同的输入文本将产生一致的结果,这对于调试和可复现性非常有用。 + - Comfy dtype: int + - Python dtype: int +- autorefresh + - 自动刷新参数可用于确定节点是否应根据输入文本的变化自动生成新的提示。它影响节点的响应性和内容生成过程的动态性。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- prompt + - 输出是一个生成的提示,是节点操作的结果。它代表了从输入文本和种子引入的随机性中派生出的创造性和潜在新颖的内容。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DPFeelingLucky(DPAbstractSamplerNode): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._random_generator = RandomPromptGenerator(wildcard_manager=self._wildcard_manager) + self._prompt_generator = FeelingLuckyGenerator(generator=self._random_generator) + + def get_prompt(self, text: str, seed: int, autorefresh: str) -> tuple[str]: + """ + Main entrypoint for this node. + Using the sampling context, generate a new prompt. + """ + if seed > 0: + self.context.rand.seed(seed) + if text.strip() == '': + return ('',) + try: + prompt = self._prompt_generator.generate(text, 1)[0] + return (str(prompt),) + except Exception as e: + logger.exception(e) + return ('',) + + @property + def context(self) -> SamplingContext: + return self._random_generator._context +``` \ No newline at end of file diff --git a/docs/DPJinja.md b/docs/DPJinja.md new file mode 100644 index 0000000..13fd2b3 --- /dev/null +++ b/docs/DPJinja.md @@ -0,0 +1,33 @@ +# Documentation +- Class name: DPJinja +- Category: Prompt Generation +- Output node: False +- Repo Ref: https://github.com/adieyal/comfyui-dynamicprompts.git + +DPJinja节点旨在使用Jinja模板语法生成提示。它利用JinjaGenerator基于提供的文本和模板配置创建一组提示,提供了一种灵活的方法来生成根据特定需求量身定制的动态提示。 + +# Input types +## Required +- text + - “text”参数是Jinja模板将生成提示的源材料。它至关重要,因为它直接影响生成提示的内容和多样性。 + - Comfy dtype: "str" + - Python dtype: str + +# Output types +- prompts + - “prompts”输出是基于输入文本和Jinja模板生成的提示列表。它代表了节点功能的主要结果,包含了提示生成过程的动态特性。 + - Comfy dtype: COMBO["str"] + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DPJinja(DPGeneratorNode): + + def generate_prompt(self, text): + prompt_generator = JinjaGenerator() + all_prompts = prompt_generator.generate(text, 1) or [''] + return str(all_prompts[0]) +``` \ No newline at end of file diff --git a/docs/DPMagicPrompt.md b/docs/DPMagicPrompt.md new file mode 100644 index 0000000..7c4aa99 --- /dev/null +++ b/docs/DPMagicPrompt.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: DPMagicPrompt +- Category: Sampling +- Output node: False +- Repo Ref: https://github.com/adieyal/comfyui-dynamicprompts.git + +DPMagicPrompt是一个旨在使用随机和魔法生成技术生成创意和与上下文相关的提示的节点。它利用预训练语言模型的力量,根据提供的输入文本和参数生成多样化和引人入胜的文本内容。 + +# Input types +## Required +- text + - 输入文本是节点操作的基础,指导提示的生成。它非常重要,因为它直接影响生成内容的上下文和相关性。 + - Comfy dtype: str + - Python dtype: str +## Optional +- seed + - 种子参数对于控制提示生成中的随机性至关重要,确保不同运行之间的可复现性和一致性。 + - Comfy dtype: int + - Python dtype: int +- autorefresh + - 自动刷新参数用于确定节点是否应根据最新的输入文本生成新的提示,有助于内容创作的动态性。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- prompt + - 输出提示是节点操作的结果,包含了既具有创造性又与输入文本相关的生成内容。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class DPMagicPrompt(DPAbstractSamplerNode): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._random_generator = RandomPromptGenerator(wildcard_manager=self._wildcard_manager) + self._prompt_generator = MagicPromptGenerator(prompt_generator=self._random_generator) + + def get_prompt(self, text: str, seed: int, autorefresh: str) -> tuple[str]: + """ + Main entrypoint for this node. + Using the sampling context, generate a new prompt. + """ + if seed > 0: + self.context.rand.seed(seed) + if text.strip() == '': + return ('',) + try: + prompt = self._prompt_generator.generate(text, 1)[0] + return (str(prompt),) + except Exception as e: + logger.exception(e) + return ('',) + + @property + def context(self) -> SamplingContext: + return self._random_generator._context +``` \ No newline at end of file diff --git a/docs/DPOutput.md b/docs/DPOutput.md new file mode 100644 index 0000000..9c54492 --- /dev/null +++ b/docs/DPOutput.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: OutputString +- Category: utils +- Output node: True +- Repo Ref: https://github.com/adieyal/comfyui-dynamicprompts.git + +该节点旨在处理和输出文本数据,在需要字符串操作或显示的各种工作流中充当重要的实用工具。 + +# Input types +## Required +- text + - 文本输入至关重要,因为它是节点操作的主要数据。它影响节点的整个输出,决定了结果字符串的内容和结构。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- ui.string + - 输出代表处理后的文本数据,是节点对输入字符串操作的结果。它很重要,因为它传达了节点功能的最终结果。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class OutputString: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {})}} + RETURN_TYPES = () + FUNCTION = 'output_string' + OUTPUT_NODE = True + CATEGORY = 'utils' + + def output_string(self, string): + return ({'ui': {'string': string}},) +``` \ No newline at end of file diff --git a/docs/DPRandomGenerator.md b/docs/DPRandomGenerator.md new file mode 100644 index 0000000..d665384 --- /dev/null +++ b/docs/DPRandomGenerator.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: DPRandomGenerator +- Category: Sampling +- Output node: False +- Repo Ref: https://github.com/adieyal/comfyui-dynamicprompts.git + +DPRandomGenerator节点旨在根据一组给定的规则和变量产生多种输出。它通过解释命令结构并使用抽样方法来生成多样化的结果,确保对可能的结果进行广泛的探索。 + +# Input types +## Required +- command + - 命令参数至关重要,因为它定义了节点将生成的提示的结构和内容。它是采样过程的蓝图,直接影响输出的多样性和性质。 + - Comfy dtype: Command + - Python dtype: dynamicprompts.commands.Command +## Optional +- num_prompts + - num_prompts参数规定了节点将生成的提示的最大数量。它在控制输出范围方面起着重要作用,根据设定的值允许输出范围集中或广泛。 + - Comfy dtype: int + - Python dtype: int + +# Output types +- prompts + - 输出提示是节点执行的结果,反映了输入命令和抽样方法的应用。它们代表了基于初始输入成功生成的多样化和相关的结果。 + - Comfy dtype: List[SamplingResult] + - Python dtype: List[dynamicprompts.SamplingResult] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DPRandomGenerator(DPAbstractSamplerNode): + + @property + @lru_cache(maxsize=1) + def context(self) -> SamplingContext: + return SamplingContext(wildcard_manager=self._wildcard_manager, default_sampling_method=SamplingMethod.RANDOM) +``` \ No newline at end of file diff --git a/docs/DWPreprocessor_Provider_for_SEGS %2F%2FInspire.md b/docs/DWPreprocessor_Provider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..4e06a4c --- /dev/null +++ b/docs/DWPreprocessor_Provider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: DWPreprocessor_Provider_for_SEGS +- Category: InspirePack/SEGS/ControlNet +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +DWPreprocessor_Provider_for_SEGS 类旨在通过使用先进的姿态估计技术来促进图像的语义分割任务预处理。它与 ComfyUI 平台集成,通过检测和处理手、身体和面部等关键特征来增强分割的准确性。该节点通过为分割模型提供详细和精炼的输入,从而提高了输出分割的质量,为整体图像分析工作流程做出贡献。 + +# Input types +## Required +- detect_hand + - 此参数控制预处理阶段是否启用手部检测功能。启用此功能可以通过识别和处理与手相关的特征显著提高分割的准确性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- detect_body + - 此参数在预处理过程中启用或禁用身体检测。身体检测对于语义分割至关重要,因为它有助于识别图像的整体结构和布局,这对于准确的分割是必不可少的。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- detect_face + - 面部检测参数允许在预处理阶段识别和处理面部特征。对于面部特征是分割任务关键组成部分的应用来说,这特别有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- resolution_upscale_by + - 此参数通过指定的缩放因子调整输入图像的分辨率。放大可以增强图像的细节和清晰度,从而可能带来更好的分割结果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- SEGS_PREPROCESSOR + - 该节点的输出是一个包含预处理后的图像数据的字典,现在已准备好进行语义分割。预处理包括手、身体和面部的检测,还可能涉及分辨率放大,所有这些都有助于提高分割的质量。 + - Comfy dtype: DICTIONARY + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DWPreprocessor_Provider_for_SEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'detect_hand': ('BOOLEAN', {'default': True, 'label_on': 'enable', 'label_off': 'disable'}), 'detect_body': ('BOOLEAN', {'default': True, 'label_on': 'enable', 'label_off': 'disable'}), 'detect_face': ('BOOLEAN', {'default': True, 'label_on': 'enable', 'label_off': 'disable'}), 'resolution_upscale_by': ('FLOAT', {'default': 1.0, 'min': 0.5, 'max': 100, 'step': 0.1})}} + RETURN_TYPES = ('SEGS_PREPROCESSOR',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/SEGS/ControlNet' + + def doit(self, detect_hand, detect_body, detect_face, resolution_upscale_by): + obj = DWPreprocessor_wrapper(detect_hand, detect_body, detect_face, upscale_factor=resolution_upscale_by, bbox_detector='yolox_l.onnx', pose_estimator='dw-ll_ucoco_384_bs5.torchscript.pt') + return (obj,) +``` \ No newline at end of file diff --git a/docs/DZ_Face_Detailer.md b/docs/DZ_Face_Detailer.md new file mode 100644 index 0000000..296d23b --- /dev/null +++ b/docs/DZ_Face_Detailer.md @@ -0,0 +1,107 @@ +# Documentation +- Class name: FaceDetailer +- Category: face_detailer +- Output node: False +- Repo Ref: https://github.com/friendlymilo/DZ-FaceDetailer.git + +FaceDetailer是一个旨在通过使用先进的机器学习模型和图像处理技术来增强图像中面部特征的节点。它通过应用掩码和去噪操作来专注于细化面部的细节,旨在提高面部数据的质量和清晰度。 + +# Input types +## Required +- model + - 模型参数对于FaceDetailer节点至关重要,因为它决定了用于面部细节增强的机器学习架构。这对于节点的正确功能和产生准确的面部特征增强至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- seed + - 种子参数对于FaceDetailer节点很重要,因为它在面部特征增强过程中引入了随机性。它确保节点可以生成各种面部细节,有助于输出的多样性。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步骤参数影响FaceDetailer节点在面部增强过程中执行的迭代次数。它影响最终输出中实现的细节和精炼程度,更多的步骤可能导致更高质量的增强。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数是一个配置值,用于调整面部特征增强过程的强度。它在确定节点输出方面起着重要作用,较高的值可能导致更明显的面部细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数对于FaceDetailer节点至关重要,因为它选择了用于生成面部细节的采样方法。它影响面部特征的多样性和随机性,有助于节点输出的独特性。 + - Comfy dtype: COMBO + - Python dtype: str +- scheduler + - 调度器参数对于FaceDetailer节点至关重要,因为它管理着增强过程的流程。它影响节点随时间应用面部特征增强的方式,确保平滑高效的转换。 + - Comfy dtype: COMBO + - Python dtype: str +- positive + - 正面参数作为FaceDetailer节点确定哪些面部特征进行增强的指导。它在塑造最终输出方面起着关键作用,确保所需的特征得到强调和改进。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- negative + - 负面参数被FaceDetailer节点用来识别应该减少或降低突出程度的面部特征。它通过确保不需要的特征被降低,从而有助于整体面部细节增强。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- latent_image + - latent_image参数对于FaceDetailer节点至关重要,因为它提供了面部特征增强的初始数据。它是节点构建和细化面部细节的基础,直接影响输出的质量。 + - Comfy dtype: LATENT + - Python dtype: dict +- denoise + - 去噪参数对于FaceDetailer节点很重要,因为它控制了在面部增强过程中应用的降噪水平。它有助于实现更清晰、更精细的面部细节输出。 + - Comfy dtype: FLOAT + - Python dtype: float +- vae + - vae参数对于FaceDetailer节点至关重要,因为它代表了用于解码和生成面部图像的变分自编码器模型。它是节点能够产生高质量面部细节增强的关键组成部分。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- mask_blur + - mask_blur参数对于FaceDetailer节点很重要,因为它决定了应用于面部掩码的模糊程度。它影响掩码的平滑度和精确度,进而影响面部细节增强的质量。 + - Comfy dtype: INT + - Python dtype: int +- mask_type + - mask_type参数对于FaceDetailer节点至关重要,因为它指定了用于面部特征增强的掩码类型。它直接影响面部细节增强过程的有效性和准确性。 + - Comfy dtype: MASK_TYPE + - Python dtype: str +- mask_control + - mask_control参数对于FaceDetailer节点至关重要,因为它管理着面部掩码的操作。它影响掩码的最终外观,进而影响面部特征增强的质量。 + - Comfy dtype: MASK_CONTROL + - Python dtype: str +- dilate_mask_value + - dilate_mask_value参数对于FaceDetailer节点很重要,因为它定义了应用于面部掩码的掩码膨胀程度。它影响掩码面部区域的大小和形状,这对于精确的面部特征增强至关重要。 + - Comfy dtype: INT + - Python dtype: int +- erode_mask_value + - erode_mask_value参数对于FaceDetailer节点很重要,因为它设置了应用于面部掩码的掩码腐蚀程度。它影响掩码面部特征的定义和边界,有助于面部细节增强的准确性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- latent + - latent参数代表FaceDetailer节点提取的精炼和增强的面部特征。这是一个关键的输出,封装了详细的面部信息,准备供进一步使用或分析。 + - Comfy dtype: LATENT + - Python dtype: dict +- mask + - mask参数是FaceDetailer节点的一个输出,提供了增强过程中使用的面部掩码。它是任何后续面部特征操作或分析的重要组件。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class FaceDetailer: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), '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, 'step': 0.1, 'round': 0.01}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'latent_image': ('LATENT',), 'vae': ('VAE',), 'mask_blur': ('INT', {'default': 0, 'min': 0, 'max': 100}), 'mask_type': (MASK_TYPE,), 'mask_control': (MASK_CONTROL,), 'dilate_mask_value': ('INT', {'default': 3, 'min': 0, 'max': 100}), 'erode_mask_value': ('INT', {'default': 3, 'min': 0, 'max': 100})}} + RETURN_TYPES = ('LATENT', 'MASK') + FUNCTION = 'detailer' + CATEGORY = 'face_detailer' + + def detailer(self, model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise, vae, mask_blur, mask_type, mask_control, dilate_mask_value, erode_mask_value): + tensor_img = vae.decode(latent_image['samples']) + batch_size = tensor_img.shape[0] + mask = Detection().detect_faces(tensor_img, batch_size, mask_type, mask_control, mask_blur, dilate_mask_value, erode_mask_value) + latent_mask = set_mask(latent_image, mask) + latent = nodes.common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_mask, denoise=denoise) + return (latent[0], latent[0]['noise_mask']) +``` \ No newline at end of file diff --git a/docs/Debug (mtb).md b/docs/Debug (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Debug Number to Console.md b/docs/Debug Number to Console.md new file mode 100644 index 0000000..217ceb2 --- /dev/null +++ b/docs/Debug Number to Console.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: WAS_Debug_Number_to_Console +- Category: WAS Suite/Debug +- Output node: True +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +“debug_to_console”方法作为开发者的实用工具,允许他们将数字打印到控制台,并附带自定义标签以供调试之用。它通过为输出应用颜色编码来增强调试信息的可见性。 + +# Input types +## Required +- number + - “number”参数对于节点的操作至关重要,因为它是将被打印到控制台的值。它在调试过程中扮演着关键角色,通过提供需要检查的特定数据点。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float] +## Optional +- label + - “label”参数用于在数字前加上描述性文本,使其更容易识别调试消息的上下文。当在脚本中使用多个调试语句时,它特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- result + - “result”参数代表用于调试的原始数字。它被返回以维持数据通过节点的流动,如果需要,允许进行进一步处理。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Debug_Number_to_Console: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number': ('NUMBER',), 'label': ('STRING', {'default': 'Debug to Console', 'multiline': False})}} + RETURN_TYPES = ('NUMBER',) + OUTPUT_NODE = True + FUNCTION = 'debug_to_console' + CATEGORY = 'WAS Suite/Debug' + + def debug_to_console(self, number, label): + if label.strip() != '': + cstr(f'\x1b[33m{label}\x1b[0m:\n{number}\n').msg.print() + else: + cstr(f'\x1b[33mDebug to Console\x1b[0m:\n{number}\n').msg.print() + return (number,) + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') +``` \ No newline at end of file diff --git a/docs/DebugInput.md b/docs/DebugInput.md new file mode 100644 index 0000000..7e1fa76 --- /dev/null +++ b/docs/DebugInput.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: WAS_DebugThis +- Category: debug +- Output node: True +- Repo Ref: https://github.com/WASasquatch/WAS_Extras + +在'WAS_DebugThis'节点中的'debug'方法作为开发者检查和理解输入数据结构和内容的基本工具。它提供清晰、简洁的输入打印输出,有助于识别任何异常或意外行为。在开发阶段,此方法对于调试目的特别有用,确保输入符合预期格式,并有助于系统的整体质量保证。 + +# Input types +## Required +- input + - 在'debug'方法中,'input'参数至关重要,因为它是将要被检查和打印出来的数据。它可以是任何类型,允许对广泛的数据进行调试。该方法能够处理各种数据类型的能力对于其在调试场景中的实用性至关重要,因为它可以提供对复杂对象和数据结构的洞察。 + - Comfy dtype: wildcard + - Python dtype: Any + +# Output types +- None + - 'debug'方法不返回任何值,其主要功能是打印输入数据及其属性(如果输入是对象)。这允许开发者检查输入,而不会改变程序的流程或输入数据的状态。 + - Comfy dtype: None + - Python dtype: NoneType + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_DebugThis: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'input': (wildcard, {})}} + RETURN_TYPES = () + OUTPUT_NODE = True + FUNCTION = 'debug' + CATEGORY = 'debug' + + def debug(self, input): + print('Debug:') + print(input) + if isinstance(input, object) and (not isinstance(input, (str, int, float, bool, list, dict, tuple))): + print('Objects directory listing:') + pprint(dir(input), indent=4) + return () +``` \ No newline at end of file diff --git a/docs/DebugTensorShape+.md b/docs/DebugTensorShape+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Deep Bump (mtb).md b/docs/Deep Bump (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Demofusion From Single File.md b/docs/Demofusion From Single File.md new file mode 100644 index 0000000..c094985 --- /dev/null +++ b/docs/Demofusion From Single File.md @@ -0,0 +1,79 @@ +# Documentation +- Class name: DemofusionFromSingleFile +- Category: tests +- Output node: False +- Repo Ref: https://github.com/deroberon/demofusion-comfyui + +该节点促进了图像生成的扩散模型的执行,利用预训练的检查点根据文本提示合成新的视觉内容。它强调节点在创意AI应用中的作用,聚焦于生成过程而不深入具体实施细节。 + +# Input types +## Required +- ckpt_name + - 检查点名称参数对于指定用于图像生成的预训练模型至关重要。它指导节点定位和加载适当的模型权重和配置,这对于后续的生成过程至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- positive + - 正面参数作为一个文本提示,指导图像生成过程。它的重要性在于为输出设定了主题方向,影响了合成图像的整体风格和内容。 + - Comfy dtype: STRING + - Python dtype: str +- negative + - 负面参数作为图像生成的排除性过滤器,使输出远离某些元素或主题。它通过指定最终结果中应避免的方面来细化创作方向。 + - Comfy dtype: STRING + - Python dtype: str +- width + - 宽度参数决定了生成图像的水平分辨率,影响整体的细节和质量。它在确定输出的比例和尺寸方面起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置了图像的垂直分辨率,与宽度一起确定生成过程的画布大小。它是输出最终尺寸的组成部分。 + - Comfy dtype: INT + - Python dtype: int +- inference_steps + - 推理步数参数控制扩散过程中使用的迭代次数,直接影响生成图像的复杂性和精细度。它是实现期望细节水平的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数调整模型的配置设置,微调生成过程以实现特定的视觉效果。它影响生成内容的风格输出和一致性。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - 种子参数通过使用固定值初始化随机数生成器来确保结果的可复现性。它对于在不同运行中进行一致的实验和结果比较至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 输出图像是节点功能的顶峰,封装了基于提供的文本提示和模型配置生成的视觉内容。它是创作过程的主要结果,展示了节点合成新图像的能力。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: GPU + +# Source code +``` +class DemofusionFromSingleFile: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (folder_paths.get_filename_list('checkpoints'),), 'positive': ('STRING', {'multiline': True, 'default': ''}), 'negative': ('STRING', {'multiline': True, 'default': ''}), 'width': ('INT', {'default': 2048, 'min': 2048, 'max': 4096, 'step': 64, 'display': 'number'}), 'height': ('INT', {'default': 2048, 'min': 2048, 'max': 4096, 'step': 64, 'display': 'number'}), 'inference_steps': ('INT', {'default': 40, 'min': 1, 'max': 100, 'step': 1, 'display': 'number'}), 'cfg': ('FLOAT', {'default': 7.5, 'min': 1.0, 'max': 20.0, 'step': 0.5, 'round': 0.001, 'display': 'number'}), 'seed': ('INT', {'default': 522, 'display': 'number'})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'execute' + CATEGORY = 'tests' + + def execute(self, ckpt_name, positive, negative, width, height, inference_steps, cfg, seed): + ckpt_path = folder_paths.get_full_path('checkpoints', ckpt_name) + pipe = DemoFusionSDXLStableDiffusionPipeline.from_single_file(ckpt_path, torch_dtype=torch.float16, use_safetensors=True) + pipe = pipe.to('cuda') + generator = torch.Generator(device='cuda') + generator = generator.manual_seed(seed) + images = pipe(str(positive), negative_prompt=str(negative), height=height, width=width, view_batch_size=4, stride=64, num_inference_steps=inference_steps, guidance_scale=cfg, cosine_scale_1=3, cosine_scale_2=1, cosine_scale_3=1, sigma=0.8, multi_decoder=True, show_image=False) + image = images[len(images) - 1] + image = image.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + return (image,) +``` \ No newline at end of file diff --git a/docs/Demofusion.md b/docs/Demofusion.md new file mode 100644 index 0000000..1723092 --- /dev/null +++ b/docs/Demofusion.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: Demofusion +- Category: tests +- Output node: False +- Repo Ref: https://github.com/deroberon/demofusion-comfyui + +该节点使用预训练的扩散模型执行图像生成,结合文本提示引导创作过程,并生成高分辨率输出。 + +# Input types +## Required +- ckpt_name + - 检查点名称对于选择用于图像生成的预训练模型至关重要。它指导节点访问指定的模型架构和权重。 + - Comfy dtype: STRING + - Python dtype: str +- positive + - 正面提示作为指导文本,增强生成图像中期望的特征,将输出引向特定的视觉元素。 + - Comfy dtype: STRING + - Python dtype: str +- negative + - 负面提示有助于从生成的图像中排除不需要的元素,使输出更加符合预期的创作愿景。 + - Comfy dtype: STRING + - Python dtype: str +- width + - 宽度决定了生成图像的水平分辨率,影响输出的整体细节和质量。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度决定了生成图像的垂直分辨率,影响最终产品的规模和宽高比。 + - Comfy dtype: INT + - Python dtype: int +- inference_steps + - 推理步骤定义了模型执行以完善图像的迭代次数,直接影响最终结果的细节和清晰度水平。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数(或cfg)调整模型的指导比例,控制文本提示对图像生成的影响强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - 种子为随机数生成提供值,确保在不同运行中使用相同的种子时结果的可复现性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - 输出是一张高分辨率的图像,包含了文本提示所提供的创作方向,代表了扩散模型生成能力的顶峰。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: GPU + +# Source code +``` +class Demofusion: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': ('STRING', {'multiline': False, 'default': 'stabilityai/stable-diffusion-xl-base-1.0'}), 'positive': ('STRING', {'multiline': True, 'default': ''}), 'negative': ('STRING', {'multiline': True, 'default': ''}), 'width': ('INT', {'default': 2048, 'min': 2048, 'max': 4096, 'step': 64, 'display': 'number'}), 'height': ('INT', {'default': 2048, 'min': 2048, 'max': 4096, 'step': 64, 'display': 'number'}), 'inference_steps': ('INT', {'default': 40, 'min': 1, 'max': 100, 'step': 1, 'display': 'number'}), 'cfg': ('FLOAT', {'default': 7.5, 'min': 1.0, 'max': 20.0, 'step': 0.5, 'round': 0.001, 'display': 'number'}), 'seed': ('INT', {'default': 522, 'display': 'number'})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'execute' + CATEGORY = 'tests' + + def execute(self, ckpt_name, positive, negative, width, height, inference_steps, cfg, seed): + pipe = DemoFusionSDXLStableDiffusionPipeline.from_pretrained(ckpt_name, torch_dtype=torch.float16) + pipe = pipe.to('cuda') + generator = torch.Generator(device='cuda') + generator = generator.manual_seed(seed) + images = pipe(str(positive), negative_prompt=str(negative), height=height, width=width, view_batch_size=4, stride=64, num_inference_steps=inference_steps, guidance_scale=cfg, cosine_scale_1=3, cosine_scale_2=1, cosine_scale_3=1, sigma=0.8, multi_decoder=True, show_image=False) + image = images[len(images) - 1] + image = image.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + return (image,) +``` \ No newline at end of file diff --git a/docs/DenoiseScheduleHookProvider.md b/docs/DenoiseScheduleHookProvider.md new file mode 100644 index 0000000..65444de --- /dev/null +++ b/docs/DenoiseScheduleHookProvider.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: DenoiseScheduleHookProvider +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +DenoiseScheduleHookProvider节点旨在管理和应用去噪计划到图像处理任务中。它提供了一个简单的计划,在放大过程中调整去噪级别以提高图像质量。 + +# Input types +## Required +- schedule_for_iteration + - schedule_for_iteration参数决定了在放大过程中应用哪种去噪计划。对于选择正确的策略以提高图像质量至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- target_denoise + - target_denoise参数设置要达到的期望去噪级别。它是放大图像最终质量的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- hook + - hook输出提供了配置好的去噪计划钩子,用于控制放大过程中的去噪级别。 + - Comfy dtype: PK_HOOK + - Python dtype: PixelKSampleHook + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DenoiseScheduleHookProvider: + schedules = ['simple'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'schedule_for_iteration': (s.schedules,), 'target_denoise': ('FLOAT', {'default': 0.2, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('PK_HOOK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + def doit(self, schedule_for_iteration, target_denoise): + hook = None + if schedule_for_iteration == 'simple': + hook = hooks.SimpleDenoiseScheduleHook(target_denoise) + return (hook,) +``` \ No newline at end of file diff --git a/docs/DenoiseSchedulerDetailerHookProvider.md b/docs/DenoiseSchedulerDetailerHookProvider.md new file mode 100644 index 0000000..d9f6f36 --- /dev/null +++ b/docs/DenoiseSchedulerDetailerHookProvider.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: DenoiseSchedulerDetailerHookProvider +- Category: ImpactPack/Detailer +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +DenoiseSchedulerDetailerHookProvider节点旨在管理细化过程的去噪计划。它提供了一种机制,在过程的不同阶段调整应用的去噪水平,确保从有噪声到详细状态的平滑过渡。 + +# Input types +## Required +- schedule_for_cycle + - schedule_for_cycle参数决定了细化周期内要遵循的去噪计划。它至关重要,因为它决定了去噪步骤的顺序,从而影响最终输出的质量。 + - Comfy dtype: STRING + - Python dtype: str +- target_denoise + - target_denoise参数指定了所需的去噪水平。它很重要,因为它直接影响最终输出的清晰度和细节。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- DETAILER_HOOK + - DenoiseSchedulerDetailerHookProvider的输出是一个封装了去噪计划的细化钩子。它很重要,因为它直接影响细化器在去噪过程中的行为。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: DetailerHook + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DenoiseSchedulerDetailerHookProvider: + schedules = ['simple'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'schedule_for_cycle': (s.schedules,), 'target_denoise': ('FLOAT', {'default': 0.3, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('DETAILER_HOOK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detailer' + + def doit(self, schedule_for_cycle, target_denoise): + hook = hooks.SimpleDetailerDenoiseSchedulerHook(target_denoise) + return (hook,) +``` \ No newline at end of file diff --git a/docs/Densepose Subject Estimation.md b/docs/Densepose Subject Estimation.md new file mode 100644 index 0000000..b03a483 --- /dev/null +++ b/docs/Densepose Subject Estimation.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: DenseposeSubjectEstimation +- Category: util +- Output node: False +- Repo Ref: https://github.com/esheep/esheep_custom_nodes.git + +DenseposeSubjectEstimation节点旨在处理和分析输入图像中的摆姿,通过一系列过滤器来选择基于指定标准最相关的摆姿。它通过将输入数据精炼到满足所需主题和体质要求的更专注的摆姿集合,从而为摆姿估计的高级任务做出贡献。 + +# Input types +## Required +- openpose_image + - openpose_image参数至关重要,因为它是摆姿检测的视觉输入。它是节点进行分析的基础,决定了身体部位的存在和可见性,这随后影响摆姿的选择。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- subject + - subject参数定义了用于过滤摆姿的特定主题标准。它在缩小到与感兴趣的主题相关的摆姿方面起着重要作用,从而增强了节点提供针对性结果的能力。 + - Comfy dtype: STRING + - Python dtype: str +- densepose_select_every_nth + - densepose_select_every_nth参数是一个可选的整数,它决定了从过滤后的摆姿中选择摆姿的频率。它提供了一种控制输出摆姿密度的机制,允许在细节和计算效率之间取得平衡。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- DENSEPOSE + - DENSEPOSE输出代表了输入图像中经过一系列基于主题和体质的过滤器精炼后最终选定的摆姿。它标志着节点分析的高潮,是用于进一步使用或展示的主要输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- DENSEPOSE_NAME + - DENSEPOSE_NAME输出提供了选定摆姿的标识符或名称,提供了一个文本参考,可用于记录、标记或在节点主要功能范围之外进行额外处理。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DenseposeSubjectEstimation: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'openpose_image': ('IMAGE',), 'subject': (['科目三'],), 'densepose_select_every_nth': ('INT', {'default': 1, 'min': 1, 'step': 1})}} + RETURN_TYPES = ['IMAGE', 'STRING'] + RETURN_NAMES = ['DENSEPOSE', 'DENSEPOSE_NAME'] + FUNCTION = 'main' + CATEGORY = 'util' + + def apply_physique_filter(self, poses): + return poses + + def apply_region_filter(self, openpose_image, poses): + batch_size = openpose_image.shape[0] + if batch_size != 1: + raise ValueError('Batch size must be 1') + limb_colors = {'left_foot': (85, 0, 255), 'left_lower_leg': (0, 51, 153), 'left_knee': (0, 0, 255), 'left_upper_leg': (0, 102, 153), 'right_foot': (0, 170, 255), 'right_lower_leg': (0, 153, 102), 'right_knee': (0, 255, 255), 'right_upper_leg': (0, 153, 51)} + image_tensor = (openpose_image * 255).to(torch.uint8) + limb_pixel_count = {} + for (limb, color) in limb_colors.items(): + count = count_color_pixels(image_tensor, color) + limb_pixel_count[limb] = count + foot_visible = limb_pixel_count['left_foot'] > 0 and limb_pixel_count['right_foot'] > 0 + upper_leg_visible = limb_pixel_count['left_upper_leg'] > 0 and limb_pixel_count['right_upper_leg'] > 0 + lower_leg_visible = limb_pixel_count['left_lower_leg'] > 0 and limb_pixel_count['right_lower_leg'] > 0 + knee_visible = limb_pixel_count['left_knee'] > 0 and limb_pixel_count['right_knee'] > 0 + if foot_visible and upper_leg_visible and lower_leg_visible: + return self.filter_poses(poses, 'full_body') + if upper_leg_visible: + return self.filter_poses(poses, 'knee_body') + return self.filter_poses(poses, 'upper_body') + + @staticmethod + def filter_poses(poses, positive_tag=None): + res = [] + for (i, pose) in enumerate(poses): + if positive_tag is not None and positive_tag not in pose['tags']: + continue + res.append(pose) + return res + + def main(self, openpose_image, subject, densepose_select_every_nth=1): + all_poses = self.filter_poses(densepose_subject_presets, subject) + poses = self.filter_poses(all_poses) + poses = self.apply_region_filter(openpose_image, poses) + poses = self.apply_physique_filter(poses) + print('filtered densepose tags', list(set((tag for pose in poses for tag in pose['tags'])))) + if len(poses) == 0: + poses = self.filter_poses(all_poses, 'fallback') + pose = random.choice(poses) + densepose_name = pose.get('name') + densepose = load_densepose(densepose_name, densepose_select_every_nth=densepose_select_every_nth) + print(f'selected densepose is {densepose_name}') + return (densepose, densepose_name) +``` \ No newline at end of file diff --git a/docs/DetailerForEach.md b/docs/DetailerForEach.md new file mode 100644 index 0000000..2bf6762 --- /dev/null +++ b/docs/DetailerForEach.md @@ -0,0 +1,138 @@ +# Documentation +- Class name: DetailerForEach +- Category: ImpactPack/Detailer +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +DetailerForEach节点旨在增强图像中各个部分的细节。它通过对每个部分应用详细的增强过程来工作,包括放大、去噪和将增强的部分粘贴回原始图像。该节点特别适用于提高具有需要更详细表示的不同区域的图像的视觉质量。 + +# Input types +## Required +- image + - 要应用细节增强过程的输入图像。它作为节点内所有后续操作的基础。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- segs + - 在图像中定义的一系列段,每个段代表要增强的区域。这些段对于节点识别图像的哪些部分需要详细处理至关重要。 + - Comfy dtype: SEGS + - Python dtype: List[Segment] +- model + - 用于增强过程的模型,通常是一个能够理解和生成详细图像的深度学习模型。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - CLIP模型或类似的模型,通过提供图像内容的文本描述,协助生成具有上下文感知能力的图像增强。 + - Comfy dtype: CLIP + - Python dtype: Any +- vae + - 变分自编码器,负责编码和解码图像数据,这对于细节增强过程至关重要。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- guide_size + - 引导尺寸参数决定了细节增强所关注的尺度。它是控制每个段应用的细节层次的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- steps + - 在采样过程中要执行的步数,这直接影响最终增强图像的质量和细节。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- enhanced_image + - 输出是具有改进细节的增强图像,其中每个段都经过单独处理,以获得更高的分辨率和清晰度。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class DetailerForEach: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'segs': ('SEGS',), 'model': ('MODEL',), 'clip': ('CLIP',), 'vae': ('VAE',), 'guide_size': ('FLOAT', {'default': 384, 'min': 64, 'max': nodes.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': nodes.MAX_RESOLUTION, 'step': 8}), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'denoise': ('FLOAT', {'default': 0.5, 'min': 0.0001, 'max': 1.0, 'step': 0.01}), 'feather': ('INT', {'default': 5, 'min': 0, 'max': 100, 'step': 1}), 'noise_mask': ('BOOLEAN', {'default': True, 'label_on': 'enabled', 'label_off': 'disabled'}), 'force_inpaint': ('BOOLEAN', {'default': True, 'label_on': 'enabled', 'label_off': 'disabled'}), 'wildcard': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'cycle': ('INT', {'default': 1, 'min': 1, 'max': 10, 'step': 1})}, 'optional': {'detailer_hook': ('DETAILER_HOOK',), '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 = ('IMAGE',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detailer' + + @staticmethod + def do_detail(image, segs, model, clip, vae, guide_size, guide_size_for_bbox, max_size, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, wildcard_opt=None, detailer_hook=None, refiner_ratio=None, refiner_model=None, refiner_clip=None, refiner_positive=None, refiner_negative=None, cycle=1, inpaint_model=False, noise_mask_feather=0): + if len(image) > 1: + raise Exception('[Impact Pack] ERROR: DetailerForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.') + image = image.clone() + enhanced_alpha_list = [] + enhanced_list = [] + cropped_list = [] + cnet_pil_list = [] + segs = core.segs_scale_match(segs, image.shape) + new_segs = [] + wildcard_concat_mode = None + if wildcard_opt is not None: + if wildcard_opt.startswith('[CONCAT]'): + wildcard_concat_mode = 'concat' + wildcard_opt = wildcard_opt[8:] + (wmode, wildcard_chooser) = wildcards.process_wildcard_for_segs(wildcard_opt) + else: + (wmode, wildcard_chooser) = (None, None) + if wmode in ['ASC', 'DSC']: + if wmode == 'ASC': + ordered_segs = sorted(segs[1], key=lambda x: (x.bbox[0], x.bbox[1])) + else: + ordered_segs = sorted(segs[1], key=lambda x: (x.bbox[0], x.bbox[1]), reverse=True) + else: + ordered_segs = segs[1] + for (i, seg) in enumerate(ordered_segs): + cropped_image = crop_ndarray4(image.numpy(), seg.crop_region) + cropped_image = to_tensor(cropped_image) + mask = to_tensor(seg.cropped_mask) + mask = tensor_gaussian_blur_mask(mask, feather) + is_mask_all_zeros = (seg.cropped_mask == 0).all().item() + if is_mask_all_zeros: + print(f'Detailer: segment skip [empty mask]') + continue + if noise_mask: + cropped_mask = seg.cropped_mask + else: + cropped_mask = None + if wildcard_chooser is not None and wmode != 'LAB': + (seg_seed, wildcard_item) = wildcard_chooser.get(seg) + elif wildcard_chooser is not None and wmode == 'LAB': + (seg_seed, wildcard_item) = (None, wildcard_chooser.get(seg)) + else: + (seg_seed, wildcard_item) = (None, None) + seg_seed = seed + i if seg_seed is None else seg_seed + cropped_positive = [[condition, {k: core.crop_condition_mask(v, image, seg.crop_region) if k == 'mask' else v for (k, v) in details.items()}] for (condition, details) in positive] + cropped_negative = [[condition, {k: core.crop_condition_mask(v, image, seg.crop_region) if k == 'mask' else v for (k, v) in details.items()}] for (condition, details) in negative] + (enhanced_image, cnet_pils) = core.enhance_detail(cropped_image, model, clip, vae, guide_size, guide_size_for_bbox, max_size, seg.bbox, seg_seed, steps, cfg, sampler_name, scheduler, cropped_positive, cropped_negative, denoise, cropped_mask, force_inpaint, wildcard_opt=wildcard_item, wildcard_opt_concat_mode=wildcard_concat_mode, detailer_hook=detailer_hook, refiner_ratio=refiner_ratio, refiner_model=refiner_model, refiner_clip=refiner_clip, refiner_positive=refiner_positive, refiner_negative=refiner_negative, control_net_wrapper=seg.control_net_wrapper, cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + if cnet_pils is not None: + cnet_pil_list.extend(cnet_pils) + if not enhanced_image is None: + image = image.cpu() + enhanced_image = enhanced_image.cpu() + tensor_paste(image, enhanced_image, (seg.crop_region[0], seg.crop_region[1]), mask) + enhanced_list.append(enhanced_image) + if detailer_hook is not None: + detailer_hook.post_paste(image) + if not enhanced_image is None: + enhanced_image_alpha = tensor_convert_rgba(enhanced_image) + new_seg_image = enhanced_image.numpy() + mask = tensor_resize(mask, *tensor_get_size(enhanced_image)) + tensor_putalpha(enhanced_image_alpha, mask) + enhanced_alpha_list.append(enhanced_image_alpha) + else: + new_seg_image = None + cropped_list.append(cropped_image) + new_seg = SEG(new_seg_image, seg.cropped_mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, seg.control_net_wrapper) + new_segs.append(new_seg) + image_tensor = tensor_convert_rgb(image) + cropped_list.sort(key=lambda x: x.shape, reverse=True) + enhanced_list.sort(key=lambda x: x.shape, reverse=True) + enhanced_alpha_list.sort(key=lambda x: x.shape, reverse=True) + return (image_tensor, cropped_list, enhanced_list, enhanced_alpha_list, cnet_pil_list, (segs[0], new_segs)) + + def doit(self, image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, wildcard, cycle=1, detailer_hook=None, inpaint_model=False, noise_mask_feather=0): + (enhanced_img, *_) = DetailerForEach.do_detail(image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, wildcard, detailer_hook, cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + return (enhanced_img,) +``` \ No newline at end of file diff --git a/docs/DetailerForEachDebug.md b/docs/DetailerForEachDebug.md new file mode 100644 index 0000000..c13f697 --- /dev/null +++ b/docs/DetailerForEachDebug.md @@ -0,0 +1,156 @@ +# Documentation +- Class name: DetailerForEachTest +- Category: ImpactPack/Detailer +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +DetailerForEachTest节点旨在过单独处理每个图像段来增强图像细节。它利用先进的模型和技术来细化和增强图像质量,专注于图像内的感兴趣区域。该节点的目标是在不损害原始图像完整性的情况下提高视觉清晰度和细节。 + +# Input types +## Required +- image + - 输入图像张量,节点将处理以增强其细节。这是一个基本参数,因为节点的所有操作都围绕这张图像展开。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- segs + - 分割数据,定义了图像内的感兴趣区域。对于节点来说,确定图像的哪些部分需要集中进行细节增强至关重要。 + - Comfy dtype: List[seg] + - Python dtype: List[Any] +- model + - 用于细节增强的模型。它在节点根据输入参数细化和增强图像细节的能力中扮演重要角色。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- guide_size + - 引导尺寸参数,决定了细节增强的尺度。它对于控制节点将应用于图像的细节级别至关重要。 + - Comfy dtype: int + - Python dtype: int +- guide_size_for + - 引导尺寸用于参数,指定细节增强过程的参考尺寸。这对于将增强与期望的输出尺寸对齐很重要。 + - Comfy dtype: int + - Python dtype: int +- max_size + - 最大尺寸参数,限制了增强图像的分辨率。它确保增强后的图像不会超过一定的尺寸,这对于性能或存储考虑可能很重要。 + - Comfy dtype: int + - Python dtype: int +- seed + - 用于初始化节点内随机过程的随机种子。它确保当节点用相同的参数运行时,结果的可重复性。 + - Comfy dtype: int + - Python dtype: int +- steps + - 运行增强过程的步数。它影响增强的彻底性和完成操作所需的时间。 + - Comfy dtype: int + - Python dtype: int +- cfg + - 控制增强过程各个方面的配置设置。这是一个关键参数,允许微调节点的行为以实现期望的结果。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] +- sampler_name + - 在增强过程中用于选择样本的采样器名称。它影响采样策略,可能会影响增强图像的质量。 + - Comfy dtype: str + - Python dtype: str +- scheduler + - 在模型训练期间使用的学习率调度器。它对于随时间调整学习率以提高训练效率和模型性能很重要。 + - Comfy dtype: torch.optim.lr_scheduler + - Python dtype: torch.optim.lr_scheduler +- positive + - 指导增强过程朝着期望结果的正向条件及其相关细节的列表。这是一个关键参数,用于引导节点的行为。 + - Comfy dtype: List[condition_details] + - Python dtype: List[Tuple[str, Dict[str, Any]]] +- negative + - 在增强过程中防止不希望出现的结果的负面条件及其相关细节的列表。这对于控制节点的行为以避免不希望的结果至关重要。 + - Comfy dtype: List[condition_details] + - Python dtype: List[Tuple[str, Dict[str, Any]]] +## Optional +- clip + - CLIP张量,提供上下文信息以指导增强过程。这是一个可选参数,可用于影响增强图像的风格和内容。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- vae + - 用于生成或细化图像细节的变分自编码器(VAE)。这是一个可选组件,可以用来引入或改进图像中的特定特征。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- denoise + - 去噪开关,决定是否对增强后的图像应用去噪步骤。它可以通过减少噪声来提高视觉质量。 + - Comfy dtype: bool + - Python dtype: bool +- feather + - 羽化参数,控制增强图像边缘的平滑度。它对于在图像的增强区域和原始区域之间创建自然过渡很重要。 + - Comfy dtype: float + - Python dtype: float +- noise_mask + - 噪声掩码张量,定义了要应用噪声减少的图像区域。这是一个可选参数,可用于选择性地减少图像某些部分的噪声。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- force_inpaint + - 强制修复开关,决定是否强制对图像执行修复操作。它可以用来填充图像中缺失或损坏的区域。 + - Comfy dtype: bool + - Python dtype: bool +- wildcard + - 通配符参数,允许基于某些条件动态选择增强选项。它在节点如何对图像的不同段应用增强提供了灵活性。 + - Comfy dtype: str + - Python dtype: str +- detailer_hook + - 一个可选的钩子函数,可用于在细节增强过程之后执行自定义操作。它允许对图像应用额外的处理。 + - Comfy dtype: Callable + - Python dtype: Callable[..., Any] +- cycle + - 重复增强过程的周期数。它可以用来应用多次增强迭代,以获得更精细的结果。 + - Comfy dtype: int + - Python dtype: int +- inpaint_model + - 一个可选的修复模型,可以在增强过程中用来填充图像中缺失或损坏的区域。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- noise_mask_feather + - 噪声掩码的羽化值,控制噪声减少边缘的平滑度。它有助于在降噪和原始区域之间创建更平滑的过渡。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- enhanced_img + - 细节增强过程生成的增强图像张量。它代表了节点的主要输出,展示了提高的视觉清晰度和细节。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- cropped + - 已处理以进行细节增强的裁剪图像张量列表。这些张量代表了图像中被专注于增强的部分。 + - Comfy dtype: List[torch.Tensor] + - Python dtype: List[torch.Tensor] +- cropped_enhanced + - 增强的裁剪图像张量列表。每个张量对应原始图像的一个增强部分,展示了经过改进的细节。 + - Comfy dtype: List[torch.Tensor] + - Python dtype: List[torch.Tensor] +- cropped_enhanced_alpha + - 带有alpha通道的增强裁剪图像张量列表。这些张量包含透明度信息,可用于进一步处理或叠加。 + - Comfy dtype: List[torch.Tensor] + - Python dtype: List[torch.Tensor] +- cnet_images + - 在增强过程中由控制网生成的PIL图像列表。这些图像可以提供视觉反馈或用于额外分析。 + - Comfy dtype: List[PIL.Image] + - Python dtype: List[PIL.Image] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class DetailerForEachTest(DetailerForEach): + RETURN_TYPES = ('IMAGE', 'IMAGE', 'IMAGE', 'IMAGE', 'IMAGE') + RETURN_NAMES = ('image', 'cropped', 'cropped_refined', 'cropped_refined_alpha', 'cnet_images') + OUTPUT_IS_LIST = (False, True, True, True, True) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detailer' + + def doit(self, image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, wildcard, detailer_hook=None, cycle=1, inpaint_model=False, noise_mask_feather=0): + if len(image) > 1: + raise Exception('[Impact Pack] ERROR: DetailerForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.') + (enhanced_img, cropped, cropped_enhanced, cropped_enhanced_alpha, cnet_pil_list, new_segs) = DetailerForEach.do_detail(image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, wildcard, detailer_hook, cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + if len(cropped) == 0: + cropped = [empty_pil_tensor()] + if len(cropped_enhanced) == 0: + cropped_enhanced = [empty_pil_tensor()] + if len(cropped_enhanced_alpha) == 0: + cropped_enhanced_alpha = [empty_pil_tensor()] + if len(cnet_pil_list) == 0: + cnet_pil_list = [empty_pil_tensor()] + return (enhanced_img, cropped, cropped_enhanced, cropped_enhanced_alpha, cnet_pil_list) +``` \ No newline at end of file diff --git a/docs/DetailerForEachDebugPipe.md b/docs/DetailerForEachDebugPipe.md new file mode 100644 index 0000000..c7685e3 --- /dev/null +++ b/docs/DetailerForEachDebugPipe.md @@ -0,0 +1,133 @@ +# Documentation +- Class name: DetailerForEachTestPipe +- Category: ImpactPack/Detailer +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +DetailerForEachTestPipe类的'doit'方法旨在对单个图像输入执行详细的图像处理任务。它通过利用各种模型和参数增强图像,并输出包括原始图像、裁剪和增强版本的多种类型的处理过的图像。该方法是图像增强流水线的核心部分,专注于提高输入图像的视觉质量和细节。 + +# Input types +## Required +- image + - 'image'参数是节点的主要输入,代表将要处理的图像。它对节点的执行至关重要,因为它决定了增强的对象。图像的质量和内容显著影响节点的输出结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- segs + - 'segs'参数提供图像的分割信息,这对于特定区域内的目标增强和处理至关重要。它影响节点如何处理和细化图像的不同部分。 + - Comfy dtype: SEGS + - Python dtype: List[Segmentation] +- guide_size + - 'guide_size'参数指定增强过程中的引导大小。它在确定节点在图像增强期间将关注的细节层次的规模上起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- max_size + - 'max_size'参数设置图像处理操作的最大尺寸。它对于控制节点执行的分辨率和计算负载很重要。 + - Comfy dtype: INT + - Python dtype: int +- seed + - 'seed'参数用于初始化随机数生成器,确保节点的随机过程的可重复性。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 'steps'参数定义了在增强过程中要采取的迭代次数或步骤数。它直接影响增强的彻底性。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 'cfg'参数包含应用于节点处理的配置设置。它对于定制节点的行为以满足特定的增强要求至关重要。 + - Comfy dtype: CONFIG + - Python dtype: Configuration +- sampler_name + - 'sampler_name'参数标识节点在增强期间要使用的采样策略。它对于确定处理图像细节的方法很重要。 + - Comfy dtype: STRING + - Python dtype: str +- scheduler + - 'scheduler'参数负责控制执行增强步骤的速度或节奏。它影响节点操作的效率和结果。 + - Comfy dtype: SCHEDULER + - Python dtype: Scheduler +- denoise + - 'denoise'参数指示是否应该对图像应用去噪操作。它对于提高图像清晰度和减少噪声伪影很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- feather + - 'feather'参数控制处理图像中边缘的柔和度。它对于实现图像不同区域之间的自然过渡很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- noise_mask + - 'noise_mask'参数确定在增强期间是否应用噪声掩码。对于需要噪声管理的某些增强技术来说,这可能很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- force_inpaint + - 'force_inpaint'参数决定是否强制对图像应用修复操作。对于填充图像中缺失或损坏的区域来说,这可能是关键的。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- basic_pipe + - 'basic_pipe'参数封装了用于图像的基本处理流水线,包括模型和其他组件。它对于图像增强的初始阶段至关重要。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, Any, Any, Any] +## Optional +- wildcard + - 'wildcard'参数通过提供通配符选项,允许在处理中增加额外的灵活性。它可以用于将可变性或特殊条件引入节点的操作中。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- enhanced_img + - 'enhanced_img'输出是图像增强过程的结果,展示了提高的视觉质量和细节。这是一个关键的输出,因为它代表了节点功能的主要目标。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- new_segs + - 'new_segs'输出包含增强过程后的更新分割信息。对于需要了解图像增强后分段区域的应用来说,这是重要的。 + - Comfy dtype: SEGS + - Python dtype: List[Segmentation] +- basic_pipe + - 'basic_pipe'输出反映了使用的基本处理流水线,它可能在图像处理工作流的后续阶段的进一步处理或分析中有用。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, Any, Any, Any] +- cropped + - 'cropped'输出由从原始输入派生的裁剪图像列表组成。这些图像可以用于特定区域的集中增强或分析。 + - Comfy dtype: LIST[IMAGE] + - Python dtype: List[torch.Tensor] +- cropped_enhanced + - 'cropped_enhanced'输出提供了增强的裁剪图像列表,突出了对每个分段所做的详细改进。 + - Comfy dtype: LIST[IMAGE] + - Python dtype: List[torch.Tensor] +- cropped_enhanced_alpha + - 'cropped_enhanced_alpha'输出包括具有alpha通道的图像,该通道代表增强区域的透明度,适用于进一步图像处理中的层叠或合成。 + - Comfy dtype: LIST[IMAGE] + - Python dtype: List[torch.Tensor] +- cnet_images + - 'cnet_images'输出是由控制网处理的图像列表,对于涉及基于神经网络的图像控制的应用来说,这可能很重要。 + - Comfy dtype: LIST[IMAGE] + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class DetailerForEachTestPipe(DetailerForEachPipe): + RETURN_TYPES = ('IMAGE', 'SEGS', 'BASIC_PIPE', 'IMAGE', 'IMAGE', 'IMAGE', 'IMAGE') + RETURN_NAMES = ('image', 'segs', 'basic_pipe', 'cropped', 'cropped_refined', 'cropped_refined_alpha', 'cnet_images') + OUTPUT_IS_LIST = (False, False, False, True, True, True, True) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detailer' + + def doit(self, image, segs, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, denoise, feather, noise_mask, force_inpaint, basic_pipe, wildcard, cycle=1, refiner_ratio=None, detailer_hook=None, refiner_basic_pipe_opt=None, inpaint_model=False, noise_mask_feather=0): + if len(image) > 1: + raise Exception('[Impact Pack] ERROR: DetailerForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.') + (model, clip, vae, positive, negative) = basic_pipe + if refiner_basic_pipe_opt is None: + (refiner_model, refiner_clip, refiner_positive, refiner_negative) = (None, None, None, None) + else: + (refiner_model, refiner_clip, _, refiner_positive, refiner_negative) = refiner_basic_pipe_opt + (enhanced_img, cropped, cropped_enhanced, cropped_enhanced_alpha, cnet_pil_list, new_segs) = DetailerForEach.do_detail(image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, wildcard, detailer_hook, refiner_ratio=refiner_ratio, refiner_model=refiner_model, refiner_clip=refiner_clip, refiner_positive=refiner_positive, refiner_negative=refiner_negative, cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + if len(cropped) == 0: + cropped = [empty_pil_tensor()] + if len(cropped_enhanced) == 0: + cropped_enhanced = [empty_pil_tensor()] + if len(cropped_enhanced_alpha) == 0: + cropped_enhanced_alpha = [empty_pil_tensor()] + if len(cnet_pil_list) == 0: + cnet_pil_list = [empty_pil_tensor()] + return (enhanced_img, new_segs, basic_pipe, cropped, cropped_enhanced, cropped_enhanced_alpha, cnet_pil_list) +``` \ No newline at end of file diff --git a/docs/DetailerForEachPipe.md b/docs/DetailerForEachPipe.md new file mode 100644 index 0000000..527182b --- /dev/null +++ b/docs/DetailerForEachPipe.md @@ -0,0 +1,86 @@ +# Documentation +- Class name: DetailerForEachPipe +- Category: ImpactPack/Detailer +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +DetailerForEachPipe 节点旨在通过应用一系列图像处理技术来增强图像的细节。它专注于通过高级算法提炼图像中各个部分的视觉质量,以实现更高水平的细节。在强调图像内容细节的后处理流程中,该节点扮演着关键角色。 + +# Input types +## Required +- image + - 输入图像是节点将处理的主要数据。它对于节点的执行至关重要,因为它决定了细节增强的对象。图像的特性直接影响节点的操作和输出的质量。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- segs + - 分割数据为节点提供了图像内的兴趣区域。这对于节点理解图像的哪些部分需要详细增强至关重要。分割数据指导节点的处理,确保只有相关区域经过增强。 + - Comfy dtype: SEGS + - Python dtype: List[torch.Tensor] +- guide_size + - 引导尺寸参数决定了应用细节增强的尺度。它是决定最终输出中可见细节水平的关键因素。必须仔细选择引导尺寸,以平衡细节和计算资源之间的权衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- max_size + - 最大尺寸参数为处理的图像段的尺寸设置了上限。它对于控制计算负载和确保节点在可用资源内运行很重要。此参数有助于防止增强过程中的内存过度使用。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - 种子参数用于初始化随机数生成器,确保节点操作的可重复性。当希望在节点的多次运行中获得一致的结果时,它尤其重要。种子为增强过程中的随机元素提供了一定程度的控制。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步骤参数指定增强算法将执行的迭代次数。它是最终输出质量和细节的关键决定因素。步骤数量越多,通常结果越好,但计算时间也会增加。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数调整增强算法的设置以微调输出。它是实现所需细节水平的关键因素,可以显著影响增强图像的视觉结果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- image + - 输出图像是细节增强过程的结果。它包含了原始图像,并添加了细节和提高了视觉质量。这是用户期望从节点操作中获得的主要输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- segs + - 输出分割数据提供了有关图像内增强区域的信息。这对于需要了解图像分割区域的进一步处理或分析非常有用。 + - Comfy dtype: SEGS + - Python dtype: List[torch.Tensor] +- basic_pipe + - 基本管道输出是增强过程中使用的一些模型和参数的集合。它可以用于额外的操作,或者在图像处理工作流的不同阶段保持一致性。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, ...] +- cnet_images + - 控制网图像输出是在增强过程中由控制网处理的图像列表。这些图像可以用于审查或进一步操作。 + - Comfy dtype: COMBO[IMAGE] + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class DetailerForEachPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'segs': ('SEGS',), 'guide_size': ('FLOAT', {'default': 384, 'min': 64, 'max': nodes.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': nodes.MAX_RESOLUTION, 'step': 8}), '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}), 'noise_mask': ('BOOLEAN', {'default': True, 'label_on': 'enabled', 'label_off': 'disabled'}), 'force_inpaint': ('BOOLEAN', {'default': True, 'label_on': 'enabled', 'label_off': 'disabled'}), 'basic_pipe': ('BASIC_PIPE',), 'wildcard': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'refiner_ratio': ('FLOAT', {'default': 0.2, 'min': 0.0, 'max': 1.0}), 'cycle': ('INT', {'default': 1, 'min': 1, 'max': 10, 'step': 1})}, 'optional': {'detailer_hook': ('DETAILER_HOOK',), 'refiner_basic_pipe_opt': ('BASIC_PIPE',), '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 = ('IMAGE', 'SEGS', 'BASIC_PIPE', 'IMAGE') + RETURN_NAMES = ('image', 'segs', 'basic_pipe', 'cnet_images') + OUTPUT_IS_LIST = (False, False, False, True) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detailer' + + def doit(self, image, segs, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, denoise, feather, noise_mask, force_inpaint, basic_pipe, wildcard, refiner_ratio=None, detailer_hook=None, refiner_basic_pipe_opt=None, cycle=1, inpaint_model=False, noise_mask_feather=0): + if len(image) > 1: + raise Exception('[Impact Pack] ERROR: DetailerForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.') + (model, clip, vae, positive, negative) = basic_pipe + if refiner_basic_pipe_opt is None: + (refiner_model, refiner_clip, refiner_positive, refiner_negative) = (None, None, None, None) + else: + (refiner_model, refiner_clip, _, refiner_positive, refiner_negative) = refiner_basic_pipe_opt + (enhanced_img, cropped, cropped_enhanced, cropped_enhanced_alpha, cnet_pil_list, new_segs) = DetailerForEach.do_detail(image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, wildcard, detailer_hook, refiner_ratio=refiner_ratio, refiner_model=refiner_model, refiner_clip=refiner_clip, refiner_positive=refiner_positive, refiner_negative=refiner_negative, cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + if len(cnet_pil_list) == 0: + cnet_pil_list = [empty_pil_tensor()] + return (enhanced_img, new_segs, basic_pipe, cnet_pil_list) +``` \ No newline at end of file diff --git a/docs/DetailerForEachPipeForAnimateDiff.md b/docs/DetailerForEachPipeForAnimateDiff.md new file mode 100644 index 0000000..b06c7a7 --- /dev/null +++ b/docs/DetailerForEachPipeForAnimateDiff.md @@ -0,0 +1,113 @@ +# Documentation +- Class name: DetailerForEachPipeForAnimateDiff +- Category: ImpactPack/Detailer +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +DetailerForEachPipeForAnimateDiff 节点旨在通过利用分割信息增强图像帧的细节。它单独处理每个段,以提高动画差异的视觉质量,专注于由边界框或裁剪区域定义的区域。该节点利用先进的采样技术和降噪策略,在输出中实现更高水平的细节。 + +# Input types +## Required +- image_frames + - image_frames 参数至关重要,因为它提供了节点将处理的原始图像数据。它是应用细节增强的基础,其质量直接影响最终输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- segs + - segs 参数定义了节点用于识别图像的不同区域进行处理的分割信息。对于节点理解图像的哪些部分需要细节增强至关重要。 + - Comfy dtype: SEGS + - Python dtype: Tuple[torch.Tensor, List[SEG]] +- guide_size + - guide_size 参数决定了用于细节增强的引导图像的大小。它是控制添加到图像帧中细节级别的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- max_size + - max_size 参数设置了图像帧的最大尺寸,确保增强的细节不会超过某个分辨率。它在优化处理和保持细节与性能之间的平衡方面发挥作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - seed 参数用于节点内的随机数生成,确保结果的可重复性。当希望在多次运行中获得一致的结果时,这是一个重要的方面。 + - Comfy dtype: INT + - Python dtype: int +- steps + - steps 参数指定节点将执行的细节增强迭代次数。更多的步骤通常会导致更高质量的输出,但可能会增加处理时间。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg 参数调整细节增强过程的配置设置。它是一个关键参数,影响节点的整体行为和增强细节的最终外观。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name 参数选择在细节增强期间使用的采样方法。不同的采样方法在细节质量和处理速度方面可以产生不同的结果。 + - Comfy dtype: STRING + - Python dtype: str +- scheduler + - scheduler 参数确定用于细节增强过程的调度算法。它影响节点如何管理增强步骤以实现最佳结果。 + - Comfy dtype: STRING + - Python dtype: str +- denoise + - denoise 参数控制应用于图像帧的降噪级别。这是一个重要的设置,用于实现干净清晰的输出,同时不损害增强的细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- feather + - feather 参数用于软化增强段的边缘,提供详细区域与图像其余部分之间的更平滑过渡。 + - Comfy dtype: INT + - Python dtype: int +- basic_pipe + - basic_pipe 参数提供了细节增强过程所必需的基础模型和组件。它是一个关键的输入,使节点能够执行其功能。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, Any, Any, Any, Any] +- refiner_ratio + - refiner_ratio 参数指定了细化模型对细节增强的贡献比例。它允许微调增强过程,以达到所需的细节水平。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- image + - image 输出参数表示具有改进细节的最终增强图像帧。它是节点处理的主要结果,反映了应用的细节增强技术的有效性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- segs + - segs 输出参数提供了细节增强过程后的更新分割信息。它包括将增强细节集成到原始分割数据中的新段。 + - Comfy dtype: SEGS + - Python dtype: Tuple[torch.Tensor, List[SEG]] +- basic_pipe + - basic_pipe 输出参数返回了在细节增强期间使用的基础模型和组件。它对于进一步的处理或分析目的可能有用。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, Any, Any, Any, Any] +- cnet_images + - cnet_images 输出参数包含在细节增强过程中生成的控制网图像列表。这些图像可以提供对增强中间阶段的洞察,并有助于调试和质量评估。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class DetailerForEachPipeForAnimateDiff: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image_frames': ('IMAGE',), 'segs': ('SEGS',), 'guide_size': ('FLOAT', {'default': 384, 'min': 64, 'max': nodes.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': nodes.MAX_RESOLUTION, 'step': 8}), '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}), 'basic_pipe': ('BASIC_PIPE',), 'refiner_ratio': ('FLOAT', {'default': 0.2, 'min': 0.0, 'max': 1.0})}, 'optional': {'detailer_hook': ('DETAILER_HOOK',), 'refiner_basic_pipe_opt': ('BASIC_PIPE',)}} + RETURN_TYPES = ('IMAGE', 'SEGS', 'BASIC_PIPE', 'IMAGE') + RETURN_NAMES = ('image', 'segs', 'basic_pipe', 'cnet_images') + OUTPUT_IS_LIST = (False, False, False, True) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detailer' + + @staticmethod + def doit(image_frames, segs, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, denoise, feather, basic_pipe, refiner_ratio=None, detailer_hook=None, refiner_basic_pipe_opt=None, inpaint_model=False, noise_mask_feather=0): + enhanced_segs = [] + cnet_image_list = [] + for sub_seg in segs[1]: + single_seg = (segs[0], [sub_seg]) + (enhanced_seg, cnet_images) = SEGSDetailerForAnimateDiff().do_detail(image_frames, single_seg, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, denoise, basic_pipe, refiner_ratio, refiner_basic_pipe_opt, inpaint_model, noise_mask_feather) + image_frames = SEGSPaste.doit(image_frames, enhanced_seg, feather, alpha=255)[0] + if cnet_images is not None: + cnet_image_list.extend(cnet_images) + if detailer_hook is not None: + detailer_hook.post_paste(image_frames) + enhanced_segs += enhanced_seg[1] + new_segs = (segs[0], enhanced_segs) + return (image_frames, new_segs, basic_pipe, cnet_image_list) +``` \ No newline at end of file diff --git a/docs/DetailerHookCombine.md b/docs/DetailerHookCombine.md new file mode 100644 index 0000000..8c3f408 --- /dev/null +++ b/docs/DetailerHookCombine.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: DetailerHookCombine +- Category: PixelKSampleHookCombine +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +DetailerHookCombine节点在像素级采样过程中充当两个独立钩子的协调器。它确保每个钩子依次应用于潜在空间、分割和粘贴图像,从而增强生成输出的细节和一致性。 + +# Input types +## Required +- latent + - “latent”参数表示正在处理的潜在空间向量。它是一个关键组件,因为它携带了细节增强过程所需的编码信息。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- segs + - “segs”参数是用于细化图像细节的分割张量列表。列表中的每个张量对应图像的不同部分。 + - Comfy dtype: List[torch.Tensor] + - Python dtype: List[torch.Tensor] +- image + - “image”参数是代表将要进行进一步处理以增强其视觉细节的粘贴图像的张量。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Output types +- cycled_latent + - “cycled_latent”输出是将两个钩子应用于输入潜在向量的结果,旨在提高潜在表示中的细节水平。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- refined_segs + - “refined_segs”输出由两个钩子处理过的分割张量组成,以实现对图像进行更详细和准确的分割。 + - Comfy dtype: List[torch.Tensor] + - Python dtype: List[torch.Tensor] +- processed_image + - “processed_image”输出是在两个钩子增强后的最终图像张量,结果是具有改进视觉质量和细节的图像。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DetailerHookCombine(PixelKSampleHookCombine): + + def cycle_latent(self, latent): + latent = self.hook1.cycle_latent(latent) + latent = self.hook2.cycle_latent(latent) + return latent + + def post_detection(self, segs): + segs = self.hook1.post_detection(segs) + segs = self.hook2.post_detection(segs) + return segs + + def post_paste(self, image): + image = self.hook1.post_paste(image) + image = self.hook2.post_paste(image) + return image +``` \ No newline at end of file diff --git a/docs/DetailerPipeToBasicPipe.md b/docs/DetailerPipeToBasicPipe.md new file mode 100644 index 0000000..f6ea55a --- /dev/null +++ b/docs/DetailerPipeToBasicPipe.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: DetailerPipeToBasicPipe +- Category: ImpactPack/Pipe +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +DetailerPipeToBasicPipe节点旨在将详细的管道结构转换为更基本的形式。它通过提取详细管道的基本组成部分并将它们重新格式化为标准、更易于管理的结构,在简化复杂数据处理工作流程中发挥着关键作用。 + +# Input types +## Required +- detailer_pipe + - detailer_pipe参数对于节点的操作至关重要,因为它提供了需要转换的详细管道结构。它是主要的输入参数,决定了节点的处理和输出的形成。 + - Comfy dtype: DETAILER_PIPE + - Python dtype: Tuple[torch.nn.Module, torch.Tensor, torch.nn.Module, torch.Tensor, torch.Tensor] + +# Output types +- base_basic_pipe + - base_basic_pipe是输入管道的简化版本,专注于基本操作所需的核心元素。它很重要,因为它允许流程化处理和更容易地集成到更广泛的系统中。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, torch.Tensor, torch.nn.Module, torch.Tensor, torch.Tensor] +- refiner_basic_pipe + - refiner_basic_pipe是另一个输出,它代表从详细结构派生出的精炼的基本管道。对于需要更专注和优化处理管道的应用来说,它是必不可少的。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, torch.Tensor, torch.nn.Module, torch.Tensor, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DetailerPipeToBasicPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'detailer_pipe': ('DETAILER_PIPE',)}} + RETURN_TYPES = ('BASIC_PIPE', 'BASIC_PIPE') + RETURN_NAMES = ('base_basic_pipe', 'refiner_basic_pipe') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Pipe' + + def doit(self, detailer_pipe): + (model, clip, vae, positive, negative, _, _, _, _, _, refiner_model, refiner_clip, refiner_positive, refiner_negative) = detailer_pipe + pipe = (model, clip, vae, positive, negative) + refiner_pipe = (refiner_model, refiner_clip, vae, refiner_positive, refiner_negative) + return (pipe, refiner_pipe) +``` \ No newline at end of file diff --git a/docs/Dictionary to Console.md b/docs/Dictionary to Console.md new file mode 100644 index 0000000..1115710 --- /dev/null +++ b/docs/Dictionary to Console.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: WAS_Dictionary_To_Console +- Category: WAS Suite/Debug +- Output node: True +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Dictionary_To_Console节点旨在通过将字典的内容输出到控制台来促进调试过程。它通过格式化打印增强了数据的可见性,使得更容易审查和分析字典的结构和值。 + +# Input types +## Required +- dictionary + - 字典参数对于节点的操作至关重要,因为它是将被打印到控制台的数据结构。它是必需的,并在节点的功能中扮演中心角色,决定了用于调试目的显示的信息。 + - Comfy dtype: DICT + - Python dtype: Dict[Any, Any] +## Optional +- label + - 标签参数用于为输出提供描述性标题,增强控制台输出的可读性。虽然它不是必需的,但在同时调试多个字典输出时,它增加了清晰度。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- dictionary + - 节点的输出是传入的原始字典。这允许在需要时进行进一步的处理或调试,确保数据在工作流中的后续操作中仍然可用。 + - Comfy dtype: DICT + - Python dtype: Dict[Any, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Dictionary_To_Console: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'dictionary': ('DICT',), 'label': ('STRING', {'default': f'Dictionary Output', 'multiline': False})}} + RETURN_TYPES = ('DICT',) + OUTPUT_NODE = True + FUNCTION = 'text_to_console' + CATEGORY = 'WAS Suite/Debug' + + def text_to_console(self, dictionary, label): + if label.strip() != '': + print(f'\x1b[34mWAS Node Suite \x1b[33m{label}\x1b[0m:\n') + from pprint import pprint + pprint(dictionary, indent=4) + print('') + else: + cstr(f'\x1b[33mText to Console\x1b[0m:\n') + pprint(dictionary, indent=4) + print('') + return (dictionary,) +``` \ No newline at end of file diff --git a/docs/DiffControlNetLoaderAdvanced.md b/docs/DiffControlNetLoaderAdvanced.md new file mode 100644 index 0000000..a9f962c --- /dev/null +++ b/docs/DiffControlNetLoaderAdvanced.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: DiffControlNetLoaderAdvanced +- Category: Adv-ControlNet 🛂🅐🅒🅝 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +DiffControlNetLoaderAdvanced节点旨在加载和管理高级控制网络,用于复杂的模型操作。它确保与模型预期的权重类型兼容,并验证控制网络权重的完整性。 + +# Input types +## Required +- model + - 模型参数对于节点至关重要,因为它定义了将应用控制网络的基础模型。它通过确定控制网络运行的上下文,直接影响节点的执行。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- control_net_name + - control_net_name参数指定要加载的控制网络的名称。它在识别模型的正确控制网络配置中起着关键作用,影响节点的功能和控制应用的结果。 + - Comfy dtype: CONTROLNET + - Python dtype: str +## Optional +- timestep_keyframe + - 可选的timestep_keyframe参数允许指定控制网络中与时间相关的关键帧。它能够细化控制网络随时间的行为,提供对模型操作过程更精细的控制。 + - Comfy dtype: TIMESTEP_KEYFRAME + - Python dtype: TimestepKeyframeGroup + +# Output types +- CONTROL_NET + - 输出CONTROL_NET代表已加载的控制网络,准备应用于模型。它封装了控制网络的配置和权重,是后续模型操作的基本组成部分。 + - Comfy dtype: CONTROLNET + - Python dtype: ControlNet + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DiffControlNetLoaderAdvanced: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'control_net_name': (folder_paths.get_filename_list('controlnet'),)}, 'optional': {'timestep_keyframe': ('TIMESTEP_KEYFRAME',)}} + RETURN_TYPES = ('CONTROL_NET',) + FUNCTION = 'load_controlnet' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝' + + def load_controlnet(self, control_net_name, model, timestep_keyframe: TimestepKeyframeGroup=None): + controlnet_path = folder_paths.get_full_path('controlnet', control_net_name) + controlnet = load_controlnet(controlnet_path, timestep_keyframe, model) + if is_advanced_controlnet(controlnet): + controlnet.verify_all_weights() + return (controlnet,) +``` \ No newline at end of file diff --git a/docs/Diffusers Hub Model Down-Loader.md b/docs/Diffusers Hub Model Down-Loader.md new file mode 100644 index 0000000..c6b24c8 --- /dev/null +++ b/docs/Diffusers Hub Model Down-Loader.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: WAS_Diffusers_Hub_Model_Loader +- Category: WAS Suite/Loaders/Advanced +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Diffusers_Hub_Model_Loader节点旨在方便从Hugging Face模型中心加载高级机器学习模型。它简化了下载和初始化模型、clips和VAEs的过程,使用户能够快速将这些组件集成到他们的工作流程中。此节点对于需要复杂模型能力的自然语言处理和生成性AI等任务至关重要。 + +# Input types +## Required +- repo_id + - repo_id参数对于识别Hugging Face hub上的具体模型存储库至关重要。它在节点的执行中起着关键作用,通过将下载过程指向正确的来源,确保准确检索所需的模型。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- revision + - revision参数允许指定存储库中模型的特定版本。对于需要特定模型迭代以完成其任务的用户来说,它很重要,确保了模型性能的可重复性和一致性。 + - Comfy dtype: STRING + - Python dtype: Union[str, None] + +# Output types +- model + - 模型输出提供了加载的机器学习模型,可供推理或进一步处理使用。它是节点功能的核心组件,为用户提供了直接访问模型预测能力的机会。 + - Comfy dtype: MODEL + - Python dtype: Any +- clip + - clip输出是通常与模型一起使用的组件,用于涉及文本和图像交互的任务。对于利用该节点进行高级自然语言处理应用的用户来说,它非常重要。 + - Comfy dtype: CLIP + - Python dtype: Any +- vae + - vae输出是一种变分自编码器,用于生成任务的神经网络类型。对于希望基于学习到的数据集分布生成新数据实例的用户来说,它是一个宝贵的资产。 + - Comfy dtype: VAE + - Python dtype: Any +- name_string + - name_string输出以字符串形式返回存储库ID,为加载的模型提供人类可读的标识符。它在工作流中的引用和记录目的中非常有用。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Diffusers_Hub_Model_Loader: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'repo_id': ('STRING', {'multiline': False}), 'revision': ('STRING', {'default': 'None', 'multiline': False})}} + RETURN_TYPES = ('MODEL', 'CLIP', 'VAE', TEXT_TYPE) + RETURN_NAMES = ('MODEL', 'CLIP', 'VAE', 'NAME_STRING') + FUNCTION = 'load_hub_checkpoint' + CATEGORY = 'WAS Suite/Loaders/Advanced' + + def load_hub_checkpoint(self, repo_id=None, revision=None): + if revision in ['', 'None', 'none', None]: + revision = None + model_path = comfy_paths.get_folder_paths('diffusers')[0] + self.download_diffusers_model(repo_id, model_path, revision) + diffusersLoader = nodes.DiffusersLoader() + (model, clip, vae) = diffusersLoader.load_checkpoint(os.path.join(model_path, repo_id)) + return (model, clip, vae, repo_id) + + def download_diffusers_model(self, repo_id, local_dir, revision=None): + if 'huggingface-hub' not in packages(): + install_package('huggingface_hub') + from huggingface_hub import snapshot_download + model_path = os.path.join(local_dir, repo_id) + ignore_patterns = ['*.ckpt', '*.safetensors', '*.onnx'] + snapshot_download(repo_id=repo_id, repo_type='model', local_dir=model_path, revision=revision, use_auth_token=False, ignore_patterns=ignore_patterns) +``` \ No newline at end of file diff --git a/docs/Diffusers Model Loader.md b/docs/Diffusers Model Loader.md new file mode 100644 index 0000000..e8d9084 --- /dev/null +++ b/docs/Diffusers Model Loader.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: WAS_Diffusers_Loader +- Category: WAS Suite/Loaders/Advanced +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 `load_checkpoint` 旨在从指定目录加载和管理预训练模型。它能够智能地遍历文件系统以定位和加载所需的模型,并确保如果需要,VAE 和 CLIP 等必要组件也可用。此方法在应用程序中初始化模型基础设施至关重要,为下游任务提供了模型组件的无缝集成。 + +# Input types +## Required +- model_path + - 参数 `model_path` 对于在文件系统中识别要加载的特定模型至关重要。它指导节点到正确的位置,使模型的数据和结构能够被检索和使用。此参数对于节点的执行至关重要,因为它决定了将在后续操作中使用的模型的来源。 + - Comfy dtype: str + - Python dtype: str +## Optional +- output_vae + - 参数 `output_vae` 决定是否应将模型的变分自编码器(VAE)组件与主模型一起加载。这个决定可以影响节点的功能,特别是如果下游任务需要 VAE 的生成能力。因此,根据应用的具体需求,包含或排除 VAE 可以是一个战略性的选择。 + - Comfy dtype: bool + - Python dtype: bool +- output_clip + - 参数 `output_clip` 控制加载 CLIP 组件,该组件通常用于图像-文本匹配任务。根据应用的需求,启用或禁用此参数可以影响节点执行此类任务的能力。它是确保节点与项目更广泛目标一致的重要考虑因素。 + - Comfy dtype: bool + - Python dtype: bool + +# Output types +- MODEL + - 输出 `MODEL` 代表了加载的模型的核心结构,是执行机器学习任务的主要组件。它封装了模型的架构和学习到的参数,因此是系统中任何后续基于模型的操作的基本输出。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- CLIP + - 当存在 `CLIP` 输出时,它提供了图像-文本匹配功能的接口。它是一个可选组件,可以根据应用的需求加载,为涉及将图像与文本描述关联的任务提供额外的能力。 + - Comfy dtype: Optional[torch.nn.Module] + - Python dtype: Optional[torch.nn.Module] +- VAE + - 输出 `VAE` 是模型的变分自编码器部分,负责模型的生成方面。它是一个可选输出,可以根据应用的任务是否需要生成能力来包含。 + - Comfy dtype: Optional[torch.nn.Module] + - Python dtype: Optional[torch.nn.Module] +- NAME_STRING + - 输出 `NAME_STRING` 提供了加载模型的基本名称,这对于应用中的日志记录、识别或引用非常有用。它作为一个人类可读的标签,可以帮助跟踪和管理模型的使用。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Diffusers_Loader: + + @classmethod + def INPUT_TYPES(cls): + paths = [] + for search_path in comfy_paths.get_folder_paths('diffusers'): + if os.path.exists(search_path): + paths += next(os.walk(search_path))[1] + return {'required': {'model_path': (paths,)}} + RETURN_TYPES = ('MODEL', 'CLIP', 'VAE', TEXT_TYPE) + RETURN_NAMES = ('MODEL', 'CLIP', 'VAE', 'NAME_STRING') + FUNCTION = 'load_checkpoint' + CATEGORY = 'WAS Suite/Loaders/Advanced' + + def load_checkpoint(self, model_path, output_vae=True, output_clip=True): + for search_path in comfy_paths.get_folder_paths('diffusers'): + if os.path.exists(search_path): + paths = next(os.walk(search_path))[1] + if model_path in paths: + model_path = os.path.join(search_path, model_path) + break + out = comfy.diffusers_convert.load_diffusers(model_path, fp16=comfy.model_management.should_use_fp16(), output_vae=output_vae, output_clip=output_clip, embedding_directory=comfy_paths.get_folder_paths('embeddings')) + return (out[0], out[1], out[2], os.path.basename(model_path)) +``` \ No newline at end of file diff --git a/docs/Dissolve.md b/docs/Dissolve.md new file mode 100644 index 0000000..25b8bf0 --- /dev/null +++ b/docs/Dissolve.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: Dissolve +- Category: postprocessing/Blends +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +Dissolve节点旨在根据指定的溶解因子将两张图像无缝混合。它通过生成点阵图案并使用它来确定每张图像对最终输出的贡献,从而在两张图像之间创建平滑的过渡。 + +# Input types +## Required +- image1 + - image1 是要与第二张图像混合的第一张输入图像。它在最终混合图像的初始组合中起着至关重要的作用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image2 + - image2 是要与第一张图像混合的第二张输入图像。它的视觉元素将与 image1 的元素结合,以创建最终输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- dissolve_factor + - 溶解因子是一个浮点值,用于确定 image1 和 image2 之间的混合比例。它影响最终结果中每张图像的可见程度,值为 0.0 时仅显示 image1,值为 1.0 时仅显示 image2。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- dissolve_image + - Dissolve节点的输出是一张单一的图像,代表了使用指定的溶解因子混合 image1 和 image2 的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Dissolve: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image1': ('IMAGE',), 'image2': ('IMAGE',), 'dissolve_factor': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'dissolve_images' + CATEGORY = 'postprocessing/Blends' + + def dissolve_images(self, image1: torch.Tensor, image2: torch.Tensor, dissolve_factor: float): + dither_pattern = torch.rand_like(image1) + mask = (dither_pattern < dissolve_factor).float() + dissolved_image = image1 * mask + image2 * (1 - mask) + dissolved_image = torch.clamp(dissolved_image, 0, 1) + return (dissolved_image,) +``` \ No newline at end of file diff --git a/docs/DodgeAndBurn.md b/docs/DodgeAndBurn.md new file mode 100644 index 0000000..03907c7 --- /dev/null +++ b/docs/DodgeAndBurn.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: DodgeAndBurn +- Category: postprocessing/Blends +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +DodgeAndBurn节点旨在通过应用 dodge 和 burn 技术来增强图像,这些技术可以操纵图像中特定区域的亮度和对比度。通过使用遮罩和调整强度,此节点可以选择性地变亮或变暗区域,创建深度并吸引人们对特定区域的注意。 + +# Input types +## Required +- image + - 图像参数是 DodgeAndBurn 节点的主要输入,它将成为通过 dodging 和 burning 技术修改的基础层。其质量和内容直接影响最终输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 遮罩参数决定了图像中哪些区域将受到 dodge 和 burn 过程的影响。它在控制对图像进行的调整的精确性方面起着至关重要的作用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- intensity + - 强度是一个关键参数,它控制应用于图像的变亮或变暗的程度。调整此值会影响 dodge 和 burn 技术的整体影响。 + - Comfy dtype: FLOAT + - Python dtype: float +- mode + - 模式参数决定了要应用的特定 dodge 和 burn 技术。它影响图像调整的方式,满足不同的创意或风格偏好。 + - Comfy dtype: COMBO[ ['dodge', 'burn', 'dodge_and_burn', 'burn_and_dodge', 'color_dodge', 'color_burn', 'linear_dodge', 'linear_burn'],] + - Python dtype: str + +# Output types +- output_image + - 输出图像代表 dodge 和 burn 过程的最终结果,反映了基于输入参数对原始图像所做的调整。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DodgeAndBurn: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'mask': ('IMAGE',), 'intensity': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'mode': (['dodge', 'burn', 'dodge_and_burn', 'burn_and_dodge', 'color_dodge', 'color_burn', 'linear_dodge', 'linear_burn'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'dodge_and_burn' + CATEGORY = 'postprocessing/Blends' + + def dodge_and_burn(self, image: torch.Tensor, mask: torch.Tensor, intensity: float, mode: str): + if mode in ['dodge', 'color_dodge', 'linear_dodge']: + dodged_image = self.dodge(image, mask, intensity, mode) + return (dodged_image,) + elif mode in ['burn', 'color_burn', 'linear_burn']: + burned_image = self.burn(image, mask, intensity, mode) + return (burned_image,) + elif mode == 'dodge_and_burn': + dodged_image = self.dodge(image, mask, intensity, 'dodge') + burned_image = self.burn(dodged_image, mask, intensity, 'burn') + return (burned_image,) + elif mode == 'burn_and_dodge': + burned_image = self.burn(image, mask, intensity, 'burn') + dodged_image = self.dodge(burned_image, mask, intensity, 'dodge') + return (dodged_image,) + else: + raise ValueError(f'Unsupported dodge and burn mode: {mode}') + + def dodge(self, img, mask, intensity, mode): + if mode == 'dodge': + return img / (1 - mask * intensity + 1e-07) + elif mode == 'color_dodge': + return torch.where(mask < 1, img / (1 - mask * intensity), img) + elif mode == 'linear_dodge': + return torch.clamp(img + mask * intensity, 0, 1) + else: + raise ValueError(f'Unsupported dodge mode: {mode}') + + def burn(self, img, mask, intensity, mode): + if mode == 'burn': + return 1 - (1 - img) / (mask * intensity + 1e-07) + elif mode == 'color_burn': + return torch.where(mask > 0, 1 - (1 - img) / (mask * intensity), img) + elif mode == 'linear_burn': + return torch.clamp(img - mask * intensity, 0, 1) + else: + raise ValueError(f'Unsupported burn mode: {mode}') +``` \ No newline at end of file diff --git a/docs/DragNUWA Run MotionBrush.md b/docs/DragNUWA Run MotionBrush.md new file mode 100644 index 0000000..70fd07a --- /dev/null +++ b/docs/DragNUWA Run MotionBrush.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: DragNUWARunMotionBrush +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +该节点通过将从画笔输入推断出的运动应用到静态图像上,模拟动态效果,旨在增强图像中运动的视觉表现力,通过整合用户提供的运动数据,使得创建动态或交互式视觉内容成为可能。 + +# Input types +## Required +- model + - 模型参数对于节点的运行至关重要,因为它定义了用于处理图像和应用运动效果的基础架构和参数。 + - Comfy dtype: DragNUWA + - Python dtype: DragNUWA +- image + - 图像参数是必需的,因为它提供了节点将要操作的基础视觉内容,以模拟运动。其属性直接影响输出的质量以及运动模拟的有效性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- motion_brush + - motion_brush参数对于节点的功能至关重要,因为它提供了将要应用到图像上的运动数据。其结构和内容直接影响最终的运动效果。 + - Comfy dtype: MotionBrush + - Python dtype: MotionBrush +- inference_batch_size + - 该参数通过控制推理过程中的批处理大小来优化节点的处理,影响运动模拟的计算效率和速度。 + - Comfy dtype: INT + - Python dtype: int +- motion_bucket_id + - motion_bucket_id参数很重要,因为它标识了运动桶中要用于模拟的具体运动数据,指导节点创建所需的视觉结果。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - 该节点的输出是增强后的图像或一系列图像,它们在视觉上代表了应用到输入图像的运动效果,展示了节点模拟动态视觉内容的能力。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: GPU + +# Source code +``` +class DragNUWARunMotionBrush: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('DragNUWA',), 'image': ('IMAGE',), 'motion_brush': ('MotionBrush',), 'inference_batch_size': ('INT', {'default': 1, 'min': 1, 'max': 1}), 'motion_bucket_id': ('INT', {'default': 4, 'min': 1, 'max': 100})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'run_inference' + CATEGORY = 'DragNUWA' + + def run_inference(self, model, image, motion_brush, inference_batch_size, motion_bucket_id): + image = 255.0 * image[0].cpu().numpy() + image_pil = Image.fromarray(np.clip(image, 0, 255).astype(np.uint8)) + (raw_w, raw_h) = image_pil.size + resize_ratio = max(model.width / raw_w, model.height / raw_h) + image_pil = image_pil.resize((int(raw_w * resize_ratio), int(raw_h * resize_ratio)), Image.BILINEAR) + image_pil = transforms.CenterCrop((model.height, model.width))(image_pil.convert('RGB')) + return model.run_brush(image_pil, motion_brush, inference_batch_size, motion_bucket_id) +``` \ No newline at end of file diff --git a/docs/DragNUWA Run.md b/docs/DragNUWA Run.md new file mode 100644 index 0000000..4a1576a --- /dev/null +++ b/docs/DragNUWA Run.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: DragNUWARun +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +DragNUWARun节点旨在执行高级图像处理和推理任务,利用预定义模型根据跟踪点和其他输入参数分析和操作图像数据。它旨在通过应用运动估计和光流技术来增强图像序列,有助于生成高质量的视觉输出。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了用于图像处理任务的基础架构和预训练权重。它决定了节点根据学习到的模式和特征解释和转换输入图像的能力。 + - Comfy dtype: DragNUWA + - Python dtype: torch.nn.Module +- image + - 图像输入对于节点执行其主要功能——图像分析和推理至关重要。它是模型将要处理的原始数据,其内容直接影响节点输出的质量和准确性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray +- tracking_points + - 跟踪点对于节点至关重要,因为它们提供了模型理解和预测图像序列中运动所需的空间信息。它们用于指导转换和增强过程,确保输出与期望的运动动态一致。 + - Comfy dtype: STRING + - Python dtype: str +- inference_batch_size + - 推理批次大小参数通过确定同时处理多少图像来优化节点的处理效率。它影响计算资源和处理速度之间的权衡,从而影响节点的整体性能。 + - Comfy dtype: INT + - Python dtype: int +- motion_bucket_id + - 运动桶ID是一个关键参数,用于对运动类型进行分类,以便模型应用特定的转换。它通过从预定义集合中选择适当的运动配置文件,有助于在输出中实现期望的运动效果。 + - Comfy dtype: INT + - Python dtype: int +- use_optical_flow + - 使用光流参数启用或禁用光流技术的应用于运动估计。对于节点准确预测和模拟图像序列中的复杂运动非常重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- directory + - 目录参数指定存储或检索光流数据的位置。对于节点访问必要的运动信息至关重要,这对于准确执行图像处理任务至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- output + - 输出参数代表节点操作产生的最终处理过的图像或图像序列。它封装了节点转换和增强输入数据的能力,反映了应用模型和算法的有效性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray + +# Usage tips +- Infra type: GPU + +# Source code +``` +class DragNUWARun: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('DragNUWA',), 'image': ('IMAGE',), 'tracking_points': ('STRING', {'multiline': True, 'default': '[[[25,25],[128,128]]]'}), 'inference_batch_size': ('INT', {'default': 1, 'min': 1, 'max': 1}), 'motion_bucket_id': ('INT', {'default': 4, 'min': 1, 'max': 100}), 'use_optical_flow': ('BOOLEAN', {'default': False}), 'directory': ('STRING', {'default': 'X://path/to/optical_flow', 'vhs_path_extensions': []})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'run_inference' + CATEGORY = 'DragNUWA' + + def run_inference(self, model, image, tracking_points, inference_batch_size, motion_bucket_id, use_optical_flow, directory): + image = 255.0 * image[0].cpu().numpy() + image_pil = Image.fromarray(np.clip(image, 0, 255).astype(np.uint8)) + (raw_w, raw_h) = image_pil.size + resize_ratio = max(model.width / raw_w, model.height / raw_h) + image_pil = image_pil.resize((int(raw_w * resize_ratio), int(raw_h * resize_ratio)), Image.BILINEAR) + image_pil = transforms.CenterCrop((model.height, model.width))(image_pil.convert('RGB')) + tracking_points = json.loads(tracking_points) + return model.run_2(image_pil, tracking_points, inference_batch_size, motion_bucket_id, use_optical_flow, directory) +``` \ No newline at end of file diff --git a/docs/DrawText+.md b/docs/DrawText+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/DynamicDelayProcessor.md b/docs/DynamicDelayProcessor.md new file mode 100644 index 0000000..19ccf33 --- /dev/null +++ b/docs/DynamicDelayProcessor.md @@ -0,0 +1,82 @@ +# Documentation +- Class name: DynamicDelayProcessor +- Category: ♾️Mixlab/Utils +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +DynamicDelayProcessor是一个旨在流程中引入可控延迟的节点。它允许根据输入参数调整执行时间,为处理时间敏感操作提供灵活性。该节点特别适用于需要将输出生成的时间与外部事件同步或控制以匹配特定速度的场景。 + +# Input types +## Required +- delay_seconds + - delay_seconds参数决定了节点在处理输入之前将引入的基本延迟持续时间。它是节点操作的一个基本方面,因为它直接影响节点执行的时机和输出生成的时刻。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- delay_by_text + - delay_by_text参数允许根据提供的文本长度调整延迟。这是一个可选功能,为节点的延迟功能增加了一层定制化,使其能够适应各种基于文本的输入及其相关的延迟。 + - Comfy dtype: STRING + - Python dtype: str +- words_per_seconds + - words_per_seconds参数与delay_by_text一起使用,根据文本的长度计算额外的延迟。它在微调节点的延迟行为以适应不同的文本长度和节奏要求方面发挥着关键作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- replace_output + - replace_output参数决定了延迟后节点的输出是否应替换为指定的值。这个功能提供了对输出的额外控制水平,允许节点要么传递原始输入,要么用预定义的值替换它。 + - Comfy dtype: COMBO + - Python dtype: Union[str, None] +- replace_value + - replace_value参数指定了如果replace_output参数设置为'enable'时要使用的值。它对于实现替换功能至关重要,确保输出根据用户的规格准确修改。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - output参数代表节点操作的结果。根据配置,它可以是原始输入的传递,或者是replace_output和replace_value参数指定的替换值。它封装了节点延迟处理的最终结果。 + - Comfy dtype: ANY + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DynamicDelayProcessor: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'delay_seconds': ('INT', {'default': 1, 'min': 0, 'max': 1000000})}, 'optional': {'any_input': (any_type,), 'delay_by_text': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'words_per_seconds': ('FLOAT', {'default': 1.5, 'min': 0.0, 'max': 1000.0, 'display': 'Chars per second?'}), 'replace_output': (['disable', 'enable'],), 'replace_value': ('INT', {'default': -1, 'min': 0, 'max': 1000000, 'display': 'Replacement value'})}} + + @classmethod + def calculate_words_length(cls, text): + chinese_char_pattern = re.compile('[\\u4e00-\\u9fff]') + english_word_pattern = re.compile('\\b[a-zA-Z]+\\b') + number_pattern = re.compile('\\b[0-9]+\\b') + words_length = 0 + for segment in text.split(): + if chinese_char_pattern.search(segment): + words_length += len(segment) + elif number_pattern.match(segment): + words_length += len(segment) + elif english_word_pattern.match(segment): + words_length += 1 + return words_length + FUNCTION = 'run' + RETURN_TYPES = (any_type,) + RETURN_NAMES = ('output',) + CATEGORY = '♾️Mixlab/Utils' + + def run(self, any_input, delay_seconds, delay_by_text, words_per_seconds, replace_output, replace_value): + start_time = time.time() + delay_time = delay_seconds + if delay_by_text and isinstance(delay_by_text, str) and (words_per_seconds > 0): + words_length = self.calculate_words_length(delay_by_text) + print(f'Delay text: {delay_by_text}, Length: {words_length}') + delay_time += words_length / words_per_seconds + print(f'延迟执行: {delay_time}') + time.sleep(delay_time) + end_time = time.time() + elapsed_time = end_time - start_time + print(f'实际延迟时间: {elapsed_time} 秒') + return (max(0, replace_value),) if replace_output == 'enable' else (any_input,) +``` \ No newline at end of file diff --git a/docs/DynamicThresholdingFull.md b/docs/DynamicThresholdingFull.md new file mode 100644 index 0000000..5dbc223 --- /dev/null +++ b/docs/DynamicThresholdingFull.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: DynamicThresholdingComfyNode +- Category: advanced/mcmonkey +- Output node: False +- Repo Ref: https://github.com/mcmonkeyprojects/sd-dynamic-thresholding + +该节点动态调整模型的阈值处理过程,以达到期望的模仿水平,并控制生成的输出。它通过解释规模和变异性度量来细化模型的响应,从而根据指定的参数优化生成过程。 + +# Input types +## Required +- model + - 模型参数是必不可少的,它定义了节点操作的基础。它是应用动态阈值处理过程的基础,其特征直接影响输出结果。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- mimic_scale + - mimic_scale参数对于控制输出中的模仿程度至关重要。它调整阈值处理过程的强度,从而影响生成内容的最终质量和相似度。 + - Comfy dtype: FLOAT + - Python dtype: float +- threshold_percentile + - threshold_percentile参数在确定生成内容的变异性方面起着重要作用。它根据分位数值设定一个阈值,用于控制特征的动态缩放。 + - Comfy dtype: FLOAT + - Python dtype: float +- mimic_mode + - mimic_mode参数规定了阈值处理过程中的缩放模式。它在定义模型如何适应输入并相应调整其输出方面起着关键作用。 + - Comfy dtype: ENUM + - Python dtype: str +- cfg_mode + - cfg_mode参数指定了动态阈值的配置模式。它在指导节点如何解释和应用特征调整的缩放因子方面至关重要。 + - Comfy dtype: ENUM + - Python dtype: str + +# Output types +- model + - 输出模型是动态阈值处理过程的结果。它已根据输入参数进行了优化和调整,提供了符合期望模仿和质量标准的优化和受控输出。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class DynamicThresholdingComfyNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'mimic_scale': ('FLOAT', {'default': 7.0, 'min': 0.0, 'max': 100.0, 'step': 0.5}), 'threshold_percentile': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'mimic_mode': (DynThresh.Modes,), 'mimic_scale_min': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 100.0, 'step': 0.5}), 'cfg_mode': (DynThresh.Modes,), 'cfg_scale_min': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 100.0, 'step': 0.5}), 'sched_val': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 100.0, 'step': 0.01}), 'separate_feature_channels': (['enable', 'disable'],), 'scaling_startpoint': (DynThresh.Startpoints,), 'variability_measure': (DynThresh.Variabilities,), 'interpolate_phi': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'patch' + CATEGORY = 'advanced/mcmonkey' + + def patch(self, model, mimic_scale, threshold_percentile, mimic_mode, mimic_scale_min, cfg_mode, cfg_scale_min, sched_val, separate_feature_channels, scaling_startpoint, variability_measure, interpolate_phi): + dynamic_thresh = DynThresh(mimic_scale, threshold_percentile, mimic_mode, mimic_scale_min, cfg_mode, cfg_scale_min, sched_val, 0, 999, separate_feature_channels == 'enable', scaling_startpoint, variability_measure, interpolate_phi) + + def sampler_dyn_thresh(args): + input = args['input'] + cond = input - args['cond'] + uncond = input - args['uncond'] + cond_scale = args['cond_scale'] + time_step = model.model.model_sampling.timestep(args['sigma']) + time_step = time_step[0].item() + dynamic_thresh.step = 999 - time_step + return input - dynamic_thresh.dynthresh(cond, uncond, cond_scale, None) + m = model.clone() + m.set_model_sampler_cfg_function(sampler_dyn_thresh) + return (m,) +``` \ No newline at end of file diff --git a/docs/DynamicThresholdingSimple.md b/docs/DynamicThresholdingSimple.md new file mode 100644 index 0000000..7fd071e --- /dev/null +++ b/docs/DynamicThresholdingSimple.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: DynamicThresholdingSimpleComfyNode +- Category: advanced/mcmonkey +- Output node: False +- Repo Ref: https://github.com/mcmonkeyprojects/sd-dynamic-thresholding + +该节点根据指定的百分位数和缩放因子动态调整模型的阈值设定,使得模型输出能够符合期望的特征。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了将要对其输出进行动态阈值设定的神经网络的基础架构和参数。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- mimic_scale + - 该参数调整模型输出修改为匹配目标特征的程度,对节点的整体效果有重大影响。 + - Comfy dtype: FLOAT + - Python dtype: float +- threshold_percentile + - 阈值百分位数确定了用于调整模型输出的相对阈值,这对于实现期望的输出分布至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- model + - 输出模型是输入模型的修改版本,现在具有根据指定目标特征调整的阈值参数。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class DynamicThresholdingSimpleComfyNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'mimic_scale': ('FLOAT', {'default': 7.0, 'min': 0.0, 'max': 100.0, 'step': 0.5}), 'threshold_percentile': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'patch' + CATEGORY = 'advanced/mcmonkey' + + def patch(self, model, mimic_scale, threshold_percentile): + dynamic_thresh = DynThresh(mimic_scale, threshold_percentile, 'CONSTANT', 0, 'CONSTANT', 0, 0, 0, 999, False, 'MEAN', 'AD', 1) + + def sampler_dyn_thresh(args): + input = args['input'] + cond = input - args['cond'] + uncond = input - args['uncond'] + cond_scale = args['cond_scale'] + time_step = model.model.model_sampling.timestep(args['sigma']) + time_step = time_step[0].item() + dynamic_thresh.step = 999 - time_step + return input - dynamic_thresh.dynthresh(cond, uncond, cond_scale, None) + m = model.clone() + m.set_model_sampler_cfg_function(sampler_dyn_thresh) + return (m,) +``` \ No newline at end of file diff --git a/docs/ESAM_ModelLoader_Zho.md b/docs/ESAM_ModelLoader_Zho.md new file mode 100644 index 0000000..f49a344 --- /dev/null +++ b/docs/ESAM_ModelLoader_Zho.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: ESAM_ModelLoader_Zho +- Category: 🔎YOLOWORLD_ESAM +- Output node: False +- Repo Ref: https://github.com/ZHO-ZHO-ZHO/ComfyUI-YoloWorld-EfficientSAM.git + +该节点旨在加载针对GPU或CPU环境定制的ESAM模型,确保与执行平台的兼容性。 + +# Input types +## Required +- device + - 设备参数决定了要加载ESAM模型的硬件环境,这对于模型的正确执行至关重要。 + - Comfy dtype: COMBO['CUDA', 'CPU'] + - Python dtype: Union[str, torch.device] + +# Output types +- esam_model + - 输出代表加载的ESAM模型,这对于系统内的进一步处理和推理任务至关重要。 + - Comfy dtype: torch.jit.ScriptModule + - Python dtype: torch.jit.ScriptModule + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ESAM_ModelLoader_Zho: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'device': (['CUDA', 'CPU'],)}} + RETURN_TYPES = ('ESAMMODEL',) + RETURN_NAMES = ('esam_model',) + FUNCTION = 'load_esam_model' + CATEGORY = '🔎YOLOWORLD_ESAM' + + def load_esam_model(self, device): + new_current_directory = os.path.join(current_directory, 'models') + if device == 'CUDA': + model_path = os.path.join(new_current_directory, 'efficient_sam_s_gpu.jit') + else: + model_path = os.path.join(new_current_directory, 'efficient_sam_s_cpu.jit') + EFFICIENT_SAM_MODEL = torch.jit.load(model_path) + return [EFFICIENT_SAM_MODEL] +``` \ No newline at end of file diff --git a/docs/EditBasicPipe.md b/docs/EditBasicPipe.md new file mode 100644 index 0000000..cf0d754 --- /dev/null +++ b/docs/EditBasicPipe.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: EditBasicPipe +- Category: ImpactPack/Pipe +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +EditBasicPipe类的'doit'方法旨在修改基本管道的组成部分。它允许有选择性地用新值替换模型、剪辑、VAE和条件输入等元素,如果提供了新值。该方法的灵活性确保了管道可以根据特定需求进行调整,而不需要改变基础结构。 + +# Input types +## Required +- basic_pipe + - 'basic_pipe'参数是一个包含管道核心元素的元组。它至关重要,因为它构成了修改的基础。该方法利用此输入来保留现有的结构或根据指定集成新组件。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, ...] +## Optional +- model + - 'model'参数是一个可选输入,允许用户为管道指定一个新模型。如果提供,它将替换管道中的现有模型,从而实现定制以适应不同的分析或预测任务。 + - Comfy dtype: MODEL + - Python dtype: Optional[Any] +- clip + - 'clip'参数是另一个可以更新的可选元素。当管道需要不同的裁剪机制或与各种数据处理技术集成时,它特别有用。 + - Comfy dtype: CLIP + - Python dtype: Optional[Any] +- vae + - 'vae'参数允许在管道中包含或更新变分自编码器。这对于涉及降维或生成模型的任务可能非常重要。 + - Comfy dtype: VAE + - Python dtype: Optional[Any] +- positive + - 'positive'参数表示一个条件输入,如果必要可以被替换。当任务涉及强化学习或需要对模型行为进行特定指导时,它在管道中扮演着重要角色。 + - Comfy dtype: CONDITIONING + - Python dtype: Optional[Any] +- negative + - 'negative'参数用于为管道指定一个负面条件输入。当模型需要从不应该做的事情的例子中学习时,这很重要,这对于某些类型的对比学习是必不可少的。 + - Comfy dtype: CONDITIONING + - Python dtype: Optional[Any] + +# Output types +- basic_pipe + - 输出'basic_pipe'是输入管道的修改版本,反映了对其组件所做的任何更新。它很重要,因为它代表了带有新配置的管道,准备用于进一步使用或部署。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, ...] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class EditBasicPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'basic_pipe': ('BASIC_PIPE',)}, 'optional': {'model': ('MODEL',), 'clip': ('CLIP',), 'vae': ('VAE',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',)}} + RETURN_TYPES = ('BASIC_PIPE',) + RETURN_NAMES = ('basic_pipe',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Pipe' + + def doit(self, basic_pipe, model=None, clip=None, vae=None, positive=None, negative=None): + (res_model, res_clip, res_vae, res_positive, res_negative) = basic_pipe + if model is not None: + res_model = model + if clip is not None: + res_clip = clip + if vae is not None: + res_vae = vae + if positive is not None: + res_positive = positive + if negative is not None: + res_negative = negative + pipe = (res_model, res_clip, res_vae, res_positive, res_negative) + return (pipe,) +``` \ No newline at end of file diff --git a/docs/EditDetailerPipe.md b/docs/EditDetailerPipe.md new file mode 100644 index 0000000..ad5f38f --- /dev/null +++ b/docs/EditDetailerPipe.md @@ -0,0 +1,149 @@ +# Documentation +- Class name: EditDetailerPipe +- Category: ImpactPack/Pipe +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +EditDetailerPipe 是一个旨在通过整合各种模型和组件来增强文本细节级别的节点。它允许通过使用 LoRA 和通配符来定制文本生成过程,并通过可选参数如模型、clip 和 VAE 进一步细化。该节点的主要目标是提供一个灵活且详细的文本编辑框架,可以根据具体需求进行调整。 + +# Input types +## Required +- detailer_pipe + - detailer_pipe 参数对于 EditDetailerPipe 节点的运行至关重要,因为它代表了文本编辑管道的初始配置或状态。正是通过这个参数,节点接收到进一步处理和定制所需的基础组件。 + - Comfy dtype: DETAILER_PIPE + - Python dtype: Tuple[Any, ...] +- wildcard + - wildcard 参数在文本编辑过程中起着关键作用,允许插入动态文本元素。它的 multiline 和 dynamicPrompts 属性表明可以生成的文本的灵活性和互动性,使其成为实现所需细节水平的关键组件。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- Select to add LoRA + - LoRA 选择参数使用户能够选择特定的 LoRA 模型来增强文本的细节和细微差别。这种选择可以显著影响生成文本的丰富度和深度,使其成为定制过程中的一个重要方面。 + - Comfy dtype: COMBO[Select the LoRA to add to the text] + - Python dtype: str +- Select to add Wildcard + - 此参数允许选择要包含在文本中的通配符,为文本生成过程中引入变化性和不可预测性提供了一种机制。通配符的选择可以极大地影响最终结果,使其成为节点运行中的一个重要因素。 + - Comfy dtype: COMBO[Select the Wildcard to add to the text] + - Python dtype: str +- model + - model 参数是一个可选输入,可用于指定文本编辑过程中的特定模型。这允许根据手头任务的具体要求定制节点的功能。 + - Comfy dtype: MODEL + - Python dtype: Any +- clip + - clip 参数是另一个可选输入,可用于将特定的 CLIP 模型引入文本编辑管道。这可以改变文本的处理和详细化方式,为节点的输出提供额外的控制。 + - Comfy dtype: CLIP + - Python dtype: Any +- vae + - vae 参数提供了一种可选的方式,将变分自编码器(VAE)包含在文本编辑过程中。这可以在节点的操作中引入抽象和表示学习的水平,可能提高生成文本的质量。 + - Comfy dtype: VAE + - Python dtype: Any +- positive + - positive 参数用于指定正面条件输入,引导文本生成过程朝着期望的结果发展。这在引导节点行为生成具有特定特征的文本时特别有用。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- negative + - negative 参数用于定义负面条件输入,阻止生成某些文本特征。这有助于通过过滤掉不需要的元素来细化节点的输出。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- bbox_detector + - bbox_detector 参数是一个可选组件,可以集成到节点中以执行边界框检测,这对于涉及空间或几何文本分析的应用非常有用。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: Any +- sam_model + - sam_model 参数允许包含一个 SAM(基于得分的对抗模型),可用于引导文本生成过程朝着更连贯和上下文相关的输出发展。 + - Comfy dtype: SAM_MODEL + - Python dtype: Any +- segm_detector + - segm_detector 参数是将分割检测器纳入节点的可选输入,它可以协助识别和分离文本的不同部分或组件。 + - Comfy dtype: SEGM_DETECTOR + - Python dtype: Any +- detailer_hook + - detailer_hook 参数提供了一种定制节点行为的方法,允许在文本编辑过程中插入自定义钩子或回调。这可以使得高级用户能够实现特定的功能或修改。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: Any +- refiner_model + - refiner_model 参数是一个可选输入,它通过指定一个次级模型来进一步细化文本编辑过程。这对于需要多阶段文本增强的应用特别有用。 + - Comfy dtype: REFINER_MODEL + - Python dtype: Any +- refiner_clip + - refiner_clip 参数允许可选集成一个次级 CLIP 模型以增强文本的细节和连贯性。它为用户提供了一个额外的控制层,以微调节点的输出。 + - Comfy dtype: REFINER_CLIP + - Python dtype: Any +- refiner_positive + - refiner_positive 参数用于为次级文本细化阶段提供正面条件输入。这有助于引导节点以更集中的方式产生具有所需属性的文本。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- refiner_negative + - refiner_negative 参数用于指定次级文本细化过程的负面条件输入。它有助于在文本编辑的最后阶段避免不需要的文本特征。 + - Comfy dtype: CONDITIONING + - Python dtype: Any + +# Output types +- detailer_pipe + - 输出的 detailer_pipe 代表通过 EditDetailerPipe 节点处理后的细化和定制的文本编辑管道。它封装了对初始管道所做的所有修改和增强,提供了一个详细且富有细微差别的文本生成框架。 + - Comfy dtype: DETAILER_PIPE + - Python dtype: Tuple[Any, ...] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class EditDetailerPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'detailer_pipe': ('DETAILER_PIPE',), 'wildcard': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'Select to add LoRA': (['Select the LoRA to add to the text'] + folder_paths.get_filename_list('loras'),), 'Select to add Wildcard': (['Select the Wildcard to add to the text'],)}, 'optional': {'model': ('MODEL',), 'clip': ('CLIP',), 'vae': ('VAE',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'bbox_detector': ('BBOX_DETECTOR',), 'sam_model': ('SAM_MODEL',), 'segm_detector': ('SEGM_DETECTOR',), 'detailer_hook': ('DETAILER_HOOK',)}} + RETURN_TYPES = ('DETAILER_PIPE',) + RETURN_NAMES = ('detailer_pipe',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Pipe' + + def doit(self, *args, **kwargs): + detailer_pipe = kwargs['detailer_pipe'] + wildcard = kwargs['wildcard'] + model = kwargs.get('model', None) + clip = kwargs.get('clip', None) + vae = kwargs.get('vae', None) + positive = kwargs.get('positive', None) + negative = kwargs.get('negative', None) + bbox_detector = kwargs.get('bbox_detector', None) + sam_model = kwargs.get('sam_model', None) + segm_detector = kwargs.get('segm_detector', None) + detailer_hook = kwargs.get('detailer_hook', None) + refiner_model = kwargs.get('refiner_model', None) + refiner_clip = kwargs.get('refiner_clip', None) + refiner_positive = kwargs.get('refiner_positive', None) + refiner_negative = kwargs.get('refiner_negative', None) + (res_model, res_clip, res_vae, res_positive, res_negative, res_wildcard, res_bbox_detector, res_segm_detector, res_sam_model, res_detailer_hook, res_refiner_model, res_refiner_clip, res_refiner_positive, res_refiner_negative) = detailer_pipe + if model is not None: + res_model = model + if clip is not None: + res_clip = clip + if vae is not None: + res_vae = vae + if positive is not None: + res_positive = positive + if negative is not None: + res_negative = negative + if bbox_detector is not None: + res_bbox_detector = bbox_detector + if segm_detector is not None: + res_segm_detector = segm_detector + if wildcard != '': + res_wildcard = wildcard + if sam_model is not None: + res_sam_model = sam_model + if detailer_hook is not None: + res_detailer_hook = detailer_hook + if refiner_model is not None: + res_refiner_model = refiner_model + if refiner_clip is not None: + res_refiner_clip = refiner_clip + if refiner_positive is not None: + res_refiner_positive = refiner_positive + if refiner_negative is not None: + res_refiner_negative = refiner_negative + pipe = (res_model, res_clip, res_vae, res_positive, res_negative, res_wildcard, res_bbox_detector, res_segm_detector, res_sam_model, res_detailer_hook, res_refiner_model, res_refiner_clip, res_refiner_positive, res_refiner_negative) + return (pipe,) +``` \ No newline at end of file diff --git a/docs/EditDetailerPipeSDXL.md b/docs/EditDetailerPipeSDXL.md new file mode 100644 index 0000000..750c49a --- /dev/null +++ b/docs/EditDetailerPipeSDXL.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: EditDetailerPipeSDXL +- Category: text_processing +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +EditDetailerPipeSDXL是一个旨在通过整合LoRA和通配符等额外元素来增强文本输出的特定性和细节的节点。它在文本生成过程中扮演着关键角色,允许创建更细腻和详细的内容。 + +# Input types +## Required +- detailer_pipe + - detailer_pipe参数对于定义节点将操作的基础文本处理管道至关重要。它为文本增强设置了基础,对节点的功能至关重要。 + - Comfy dtype: DETAILER_PIPE + - Python dtype: str +- wildcard + - wildcard参数允许用户输入可以在文本生成过程中被替换或操作的动态文本段。它在定制输出以满足特定要求中起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- Select to add LoRA + - LoRA选择参数允许向文本中添加细化层次,增强模型生成详细且内容丰富的能力。这是一个可选特性,能显著提升节点的能力。 + - Comfy dtype: COMBO[loras] + - Python dtype: str +- Select to add Wildcard + - 此参数提供了一种将通配符引入文本生成的机制,提供了输出的灵活性和适应性。它是一个可选特性,可以根据不同的用例进行定制。 + - Comfy dtype: COMBO[STRING] + - Python dtype: str +- model + - model参数用于指定节点将用于文本处理的机器学习模型。这是一个可选输入,通过正确的模型选择可以增强节点的性能。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Output types +- refined_text + - refined_text输出是节点操作的结果,提供了输入文本的详细和增强版本。它代表了节点文本处理能力的成果。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class EditDetailerPipeSDXL(EditDetailerPipe): + + @classmethod + def INPUT_TYPES(s): + return {'required': {'detailer_pipe': ('DETAILER_PIPE',), 'wildcard': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'Select to add LoRA': (['Select the LoRA to add to the text'] + folder_paths.get_filename_list('loras'),), 'Select to add Wildcard': (['Select the Wildcard to add to the text'],)}, 'optional': {'model': ('MODEL',), 'clip': ('CLIP',), 'vae': ('VAE',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'refiner_model': ('MODEL',), 'refiner_clip': ('CLIP',), 'refiner_positive': ('CONDITIONING',), 'refiner_negative': ('CONDITIONING',), 'bbox_detector': ('BBOX_DETECTOR',), 'sam_model': ('SAM_MODEL',), 'segm_detector': ('SEGM_DETECTOR',), 'detailer_hook': ('DETAILER_HOOK',)}} +``` \ No newline at end of file diff --git a/docs/EditableCLIPEncode.md b/docs/EditableCLIPEncode.md new file mode 100644 index 0000000..f911f2d --- /dev/null +++ b/docs/EditableCLIPEncode.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: EditableCLIPEncode +- Category: promptcontrol/old +- Output node: False +- Repo Ref: https://github.com/asagi4/comfyui-prompt-control.git + +该节点旨在将文本输入处理并转换为CLIP模型可用的结构化格式。它通过解析文本中的指定过滤器,并将要转换的结构转换为适合CLIP模型的条件格式来实现这一目标。 + +# Input types +## Required +- clip + - “clip”参数是必要的,因为它提供了节点将用于处理输入文本的基本模型。没有这个参数,节点无法执行其预期功能。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- text + - “text”参数对节点至关重要,因为它包含了节点将要解析和转换的输入数据。“text”的质量和格式直接影响节点的输出。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- filter_tags + - “filter_tags”参数用于细化输入文本的解析过程。它允许指定节点在文本处理过程中应考虑或忽略的特定标签。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- CONDITIONING + - “CONDITIONING”输出代表了输入文本的处理和结构化格式,适用于与CLIP模型一起使用。它封装了解析文本的精髓,允许与模型进行有效的交互。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Dict[str, Any]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class EditableCLIPEncode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'clip': ('CLIP',), 'text': ('STRING', {'multiline': True})}, 'optional': {'filter_tags': ('STRING', {'default': ''})}} + RETURN_TYPES = ('CONDITIONING',) + CATEGORY = 'promptcontrol/old' + FUNCTION = 'parse' + + def parse(self, clip, text, filter_tags=''): + parsed = parse_prompt_schedules(text).with_filters(filter_tags) + return (control_to_clip_common(clip, parsed),) +``` \ No newline at end of file diff --git a/docs/EmbeddingPrompt.md b/docs/EmbeddingPrompt.md new file mode 100644 index 0000000..fbf340c --- /dev/null +++ b/docs/EmbeddingPrompt.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: EmbeddingPrompt +- Category: ♾️Mixlab/Prompt +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点类基于嵌入和相关权重生成提示,使用户能够调整特定嵌入在输出中的影响。 + +# Input types +## Required +- embedding + - 嵌入参数至关重要,因为它定义了生成提示的基础上下文或主题。它从可用嵌入的列表中选择,确保提示与所选上下文相关。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- weight + - 权重参数调整所选嵌入对最终提示的影响,允许对输出强调嵌入上下文的细微控制。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- prompt + - 输出提示是一个字符串,整合了所选嵌入及其权重,形成了一个简洁且针对性的声明,可作为各种应用的输入。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class EmbeddingPrompt: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'embedding': (get_files_with_extension(embeddings_path, '.pt'),), 'weight': ('FLOAT', {'default': 1, 'min': -2, 'max': 2, 'step': 0.01, 'display': 'slider'})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Prompt' + OUTPUT_IS_LIST = (False,) + + def run(self, embedding, weight): + weight = round(weight, 3) + prompt = 'embedding:' + embedding + if weight != 1: + prompt = '(' + prompt + ':' + str(weight) + ')' + prompt = ' ' + prompt + ' ' + return (prompt,) +``` \ No newline at end of file diff --git a/docs/Empty Latent Ratio Custom SDXL.md b/docs/Empty Latent Ratio Custom SDXL.md new file mode 100644 index 0000000..862d858 --- /dev/null +++ b/docs/Empty Latent Ratio Custom SDXL.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: EmptyLatentRatioCustom +- Category: Mikey/Latent +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +EmptyLatentRatioCustom节点旨在为给定的一组维度和批量大小生成潜在表示。它根据预定义的比率或用户自定义的比率智能确定适当的潜在大小,确保输出的潜在空间最适合进一步处理或生成任务。 + +# Input types +## Required +- width + - 宽度参数对于定义输入空间的水平维度至关重要。它直接影响潜在大小的计算,这对于节点的输出是必不可少的。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数指定输入空间的垂直维度。它与宽度参数一起工作,以确定潜在大小,这是节点功能的关键因素。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- batch_size + - 批量大小参数允许用户指定一次处理的样本数量。这是一个可选参数,可以影响节点执行的效率。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- samples + - 样本输出提供生成的潜在表示。它很重要,因为它为工作流中的后续操作或分析奠定了基础。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class EmptyLatentRatioCustom: + + @classmethod + def INPUT_TYPES(s): + (s.ratio_sizes, s.ratio_dict) = read_ratios() + return {'required': {'width': ('INT', {'default': 1024, 'min': 1, 'max': 8192, 'step': 1}), 'height': ('INT', {'default': 1024, 'min': 1, 'max': 8192, 'step': 1}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'generate' + CATEGORY = 'Mikey/Latent' + + def generate(self, width, height, batch_size=1): + if width == 1 and height == 1 or width == height: + (w, h) = (1024, 1024) + if f'{width}:{height}' in self.ratio_dict: + (w, h) = self.ratio_dict[f'{width}:{height}'] + else: + (w, h) = find_latent_size(width, height) + latent = torch.zeros([batch_size, 4, h // 8, w // 8]) + return ({'samples': latent},) +``` \ No newline at end of file diff --git a/docs/Empty Latent Ratio Select SDXL.md b/docs/Empty Latent Ratio Select SDXL.md new file mode 100644 index 0000000..3d1e402 --- /dev/null +++ b/docs/Empty Latent Ratio Select SDXL.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: EmptyLatentRatioSelector +- Category: Mikey/Latent +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +EmptyLatentRatioSelector 节点旨在为一组给定的比率尺寸生成潜在表示。它在潜在空间操作的初始阶段扮演着关键角色,为进一步处理提供了一个结构化的起点。该节点确保潜在空间得到适当的初始化,为后续操作奠定了基础。 + +# Input types +## Required +- ratio_selected + - ‘ratio_selected’参数对于确定用于潜在生成的特定比率尺寸至关重要。它决定了潜在空间的维度,是节点操作的一个基本方面,直接影响输出的结构。 + - Comfy dtype: str + - Python dtype: str +## Optional +- batch_size + - ‘batch_size’参数允许指定在单个操作中生成的潜在样本的数量。它是一个可选参数,可以根据计算资源和手头任务的具体要求进行调整。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- samples + - ‘samples’输出参数代表生成的潜在表示。它是一个张量,包含了潜在空间的信息,这对于系统中的后续处理和分析至关重要。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class EmptyLatentRatioSelector: + + @classmethod + def INPUT_TYPES(s): + (s.ratio_sizes, s.ratio_dict) = read_ratios() + return {'required': {'ratio_selected': (s.ratio_sizes,), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'generate' + CATEGORY = 'Mikey/Latent' + + def generate(self, ratio_selected, batch_size=1): + width = self.ratio_dict[ratio_selected]['width'] + height = self.ratio_dict[ratio_selected]['height'] + latent = torch.zeros([batch_size, 4, height // 8, width // 8]) + return ({'samples': latent},) +``` \ No newline at end of file diff --git a/docs/Empty Latent by Pixels (WLSH).md b/docs/Empty Latent by Pixels (WLSH).md new file mode 100644 index 0000000..aa2ff76 --- /dev/null +++ b/docs/Empty Latent by Pixels (WLSH).md @@ -0,0 +1,79 @@ +# Documentation +- Class name: WLSH_Empty_Latent_Image_By_Pixels +- Category: WLSH Nodes/latent +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_Empty_Latent_Image_By_Pixels 节点的 'generate' 方法旨在根据指定的像素尺寸和纵横比创建一个空的潜在图像表示。它智能地计算潜在图像的宽度和高度,以适应所需的百万像素和方向,确保维度针对处理效率进行了优化。 + +# Input types +## Required +- aspect + - “aspect”参数定义了潜在图像的纵横比。它至关重要,因为它直接影响生成图像的形状和尺寸,进而影响后续的处理和分析阶段。 + - Comfy dtype: STRING + - Python dtype: str +- direction + - “direction”参数指定图像应为横向或纵向模式。这一点很重要,因为它决定了潜在图像的方向,对于需要特定方向的某些应用来说是必不可少的。 + - Comfy dtype: STRING + - Python dtype: str +- megapixels + - “megapixels”参数以百万像素为单位设置潜在图像的分辨率。它是一个重要因素,因为它决定了图像的细节水平以及所需的计算资源。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- batch_size + - “batch_size”参数决定了单次迭代中处理的图像数量。它对于优化计算效率很重要,可以根据可用资源进行调整。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- latent + - “latent”输出提供了生成的潜在图像表示。它是一个关键组件,因为它构成了系统内进一步图像处理和分析的基础。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- width + - “width”输出表示以像素为单位计算出的潜在图像的宽度。它很重要,因为它提供了图像操作和显示所需的空间维度信息。 + - Comfy dtype: INT + - Python dtype: int +- height + - “height”输出表示以像素为单位计算出的潜在图像的高度。与宽度一起,它对于理解图像的整体尺寸以用于各种应用至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Empty_Latent_Image_By_Pixels: + aspects = ['1:1', '5:4', '4:3', '3:2', '16:10', '16:9', '19:9', '21:9', '2:1', '3:1', '4:1'] + direction = ['landscape', 'portrait'] + + def __init__(self, device='cpu'): + self.device = device + + @classmethod + def INPUT_TYPES(s): + return {'required': {'aspect': (s.aspects,), 'direction': (s.direction,), 'megapixels': ('FLOAT', {'default': 1.0, 'min': 0.01, 'max': 16.0, 'step': 0.01}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}} + RETURN_TYPES = ('LATENT', 'INT', 'INT') + RETURN_NAMES = ('latent', 'width', 'height') + FUNCTION = 'generate' + CATEGORY = 'WLSH Nodes/latent' + + def generate(self, aspect, direction, megapixels, batch_size=1): + (x, y) = aspect.split(':') + x = int(x) + y = int(y) + ratio = x / y + total = int(megapixels * 1024 * 1024) + width = int(np.sqrt(ratio * total)) + width = width + 63 & -64 + height = int(np.sqrt(1 / ratio * total)) + height = height + 63 & -64 + if direction == 'portrait': + (width, height) = (height, width) + adj_width = width // 8 + adj_height = height // 8 + latent = torch.zeros([batch_size, 4, adj_height, adj_width]) + return ({'samples': latent}, adj_width * 8, adj_height * 8) +``` \ No newline at end of file diff --git a/docs/Empty Latent by Ratio (WLSH).md b/docs/Empty Latent by Ratio (WLSH).md new file mode 100644 index 0000000..965670a --- /dev/null +++ b/docs/Empty Latent by Ratio (WLSH).md @@ -0,0 +1,77 @@ +# Documentation +- Class name: WLSH_Empty_Latent_Image_By_Ratio +- Category: WLSH Nodes/latent +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_Empty_Latent_Image_By_Ratio节点的'generate'方法旨在根据指定的宽高比和方向创建一个空的潜在图像。它计算潜在图像的尺寸并将其初始化为零,这可以作为进一步图像处理任务的起点。 + +# Input types +## Required +- aspect + - 参数'aspect'定义了要生成的潜在图像的宽高比。它至关重要,因为它直接影响输出图像的尺寸。 + - Comfy dtype: str + - Python dtype: str +- direction + - 参数'direction'指定图像应为横向还是纵向方向,这影响宽度和高度的分配。 + - Comfy dtype: str + - Python dtype: str +- shortside + - 参数'shortside'决定了图像较短边的长度,它用于根据宽高比计算完整的尺寸。 + - Comfy dtype: int + - Python dtype: int +## Optional +- batch_size + - 参数'batch_size'指示在单个操作中生成的图像数量,提高了一次处理多个图像的效率。 + - Comfy dtype: int + - Python dtype: int + +# Output types +- latent + - 输出'latent'是一个张量,代表根据输入参数计算出的尺寸的空潜在图像。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- width + - 输出'width'提供了在考虑宽高比和方向后计算出的潜在图像的宽度。 + - Comfy dtype: int + - Python dtype: int +- height + - 输出'height'提供了在考虑宽高比和方向后计算出的潜在图像的高度。 + - Comfy dtype: int + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Empty_Latent_Image_By_Ratio: + aspects = ['1:1', '6:5', '5:4', '4:3', '3:2', '16:10', '16:9', '19:9', '21:9', '2:1', '3:1', '4:1'] + direction = ['landscape', 'portrait'] + + def __init__(self, device='cpu'): + self.device = device + + @classmethod + def INPUT_TYPES(s): + return {'required': {'aspect': (s.aspects,), 'direction': (s.direction,), 'shortside': ('INT', {'default': 512, 'min': 64, 'max': MAX_RESOLUTION, 'step': 64}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}} + RETURN_TYPES = ('LATENT', 'INT', 'INT') + RETURN_NAMES = ('latent', 'width', 'height') + FUNCTION = 'generate' + CATEGORY = 'WLSH Nodes/latent' + + def generate(self, aspect, direction, shortside, batch_size=1): + (x, y) = aspect.split(':') + x = int(x) + y = int(y) + ratio = x / y + width = int(shortside * ratio) + width = width + 63 & -64 + height = shortside + if direction == 'portrait': + (width, height) = (height, width) + adj_width = width // 8 + adj_height = height // 8 + latent = torch.zeros([batch_size, 4, adj_height, adj_width]) + return ({'samples': latent}, adj_width * 8, adj_height * 8) +``` \ No newline at end of file diff --git a/docs/Empty Latent by Size (WLSH).md b/docs/Empty Latent by Size (WLSH).md new file mode 100644 index 0000000..4eaf2c6 --- /dev/null +++ b/docs/Empty Latent by Size (WLSH).md @@ -0,0 +1,62 @@ +# Documentation +- Class name: WLSH_Empty_Latent_Image_By_Resolution +- Category: WLSH Nodes/latent +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_Empty_Latent_Image_By_Resolution节点的'generate'方法旨在为给定的分辨率创建一个空的潜在图像空间。它通过提供一个简单的接口来抽象生成潜在空间的复杂性,该接口接受宽度、高度和批量大小作为输入,并输出一个潜在张量以及调整后的维度。 + +# Input types +## Required +- width + - ‘width’参数指定了潜在图像的宽度,以像素为单位。它在确定生成的潜在空间的分辨率方面起着关键作用,这直接影响最终图像的质量和细节。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’参数决定了潜在图像的高度,以像素为单位。与宽度类似,它对于建立分辨率以及生成潜在图像的保真度至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- batch_size + - ‘batch_size’参数是可选的,它决定了在一次操作中生成的潜在图像的数量。它可以用来有效地一次处理多个图像,提高节点的吞吐量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- latent + - ‘latent’输出是一个张量,代表生成的潜在图像空间。它是后续图像处理和生成任务的关键组成部分,为这些操作提供了所需的基础数据。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- width + - ‘width’输出反映了生成过程后潜在图像的调整宽度。它对于理解生成的潜在空间的实际尺寸很重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’输出提供了潜在图像的调整高度,与宽度类似,它对于了解生成的潜在空间的确切尺寸至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Empty_Latent_Image_By_Resolution: + + def __init__(self, device='cpu'): + self.device = device + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 16, 'max': MAX_RESOLUTION, 'step': 8}), 'height': ('INT', {'default': 512, 'min': 16, 'max': MAX_RESOLUTION, 'step': 8}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 4096})}} + RETURN_TYPES = ('LATENT', 'INT', 'INT') + RETURN_NAMES = ('latent', 'width', 'height') + FUNCTION = 'generate' + CATEGORY = 'WLSH Nodes/latent' + + def generate(self, width, height, batch_size=1): + adj_width = width // 8 + adj_height = height // 8 + latent = torch.zeros([batch_size, 4, adj_height, adj_width]) + return ({'samples': latent}, adj_width * 8, adj_height * 8) +``` \ No newline at end of file diff --git a/docs/EmptyLatentImagePresets.md b/docs/EmptyLatentImagePresets.md new file mode 100644 index 0000000..a523293 --- /dev/null +++ b/docs/EmptyLatentImagePresets.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: EmptyLatentImagePresets +- Category: KJNodes +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +EmptyLatentImagePresets节点旨在生成潜在图像的预设。它接收诸如尺寸、反转状态和批量大小等参数,以产生潜在图像数组以及相应的宽度和高度。 + +# Input types +## Required +- dimensions + - 尺寸参数指定要生成的潜在图像的大小。它至关重要,因为它决定了输出图像的空间分辨率。 + - Comfy dtype: STRING + - Python dtype: str +- batch_size + - 批量大小参数定义了在单个批次中要生成的潜在图像的数量。在处理大量数据时,它对于优化计算资源很重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- invert + - 反转参数允许用户反转潜在图像的宽度和高度尺寸。在某些图像方向重要的应用中,这可能很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- Latent + - 潜在参数代表生成的潜在图像数组。它很重要,因为它构成了节点功能的核心输出。 + - Comfy dtype: ARRAY + - Python dtype: torch.Tensor +- Width + - 宽度参数指示生成的潜在图像的宽度。对于进一步的图像处理任务,这是一条重要的信息。 + - Comfy dtype: INT + - Python dtype: int +- Height + - 高度参数指示生成的潜在图像的高度。与宽度一起,它提供了潜在图像的完整尺寸。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class EmptyLatentImagePresets: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'dimensions': (['512 x 512', '768 x 512', '960 x 512', '1024 x 512', '1536 x 640', '1344 x 768', '1216 x 832', '1152 x 896', '1024 x 1024'], {'default': '512 x 512'}), 'invert': ('BOOLEAN', {'default': False}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 4096})}} + RETURN_TYPES = ('LATENT', 'INT', 'INT') + RETURN_NAMES = ('Latent', 'Width', 'Height') + FUNCTION = 'generate' + CATEGORY = 'KJNodes' + + def generate(self, dimensions, invert, batch_size): + from nodes import EmptyLatentImage + result = [x.strip() for x in dimensions.split('x')] + if invert: + width = int(result[1].split(' ')[0]) + height = int(result[0]) + else: + width = int(result[0]) + height = int(result[1].split(' ')[0]) + latent = EmptyLatentImage().generate(width, height, batch_size)[0] + return (latent, int(width), int(height)) +``` \ No newline at end of file diff --git a/docs/EmptySegs.md b/docs/EmptySegs.md new file mode 100644 index 0000000..2127206 --- /dev/null +++ b/docs/EmptySegs.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: EmptySEGS +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +EmptySEGS节点的'doit'方法旨在生成一个空的分割结构。它的目的是在没有实际分割数据可用时提供基线或占位符。当输入数据不需要详细分割时,此节点至关重要,它确保了工作流程的完整性,同时避免了不必要的复杂性引入。 + +# Input types +## Optional +- input_data + - 尽管'input_data'参数不是必需的,但如果需要,它可以用来向EmptySEGS节点传递额外的上下文或数据。它的作用可能是增强节点的功能或与其他可能需要输入数据以进行操作的系统进行集成。 + - Comfy dtype: Any + - Python dtype: Any + +# Output types +- SEGS + - 输出参数'SEGS'代表了EmptySEGS节点操作的结果。它提供了一个空元组,其中第一个元素是表示分割维度的形状,第二个元素是一个通常包含分割数据但在这种情况下为空的列表。这种输出格式允许与期望分割结果的系统无缝集成,即使没有执行实际的分割。 + - Comfy dtype: Tuple[int, List[Any]] + - Python dtype: Tuple[int, List[Any]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class EmptySEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self): + shape = (0, 0) + return ((shape, []),) +``` \ No newline at end of file diff --git a/docs/EnhanceImage.md b/docs/EnhanceImage.md new file mode 100644 index 0000000..8b97478 --- /dev/null +++ b/docs/EnhanceImage.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: EnhanceImage +- Category: ♾️Mixlab/Image +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点旨在通过调整图像的对比度水平来提高图像的视觉质量,从而增强视觉内容的清晰度和深度,而不改变输入图像的基本特征。 + +# Input types +## Required +- image + - 图像输入是至关重要的,因为它提供了节点将处理的基础视觉数据。它通过确定对比度增强的起点来影响整个操作。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or list[PIL.Image] +- contrast + - 对比度参数在增强过程中起着重要作用,因为它直接影响输出图像的动态范围和视觉冲击力。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- image + - 输出图像代表输入的增强版本,具有更好的对比度和深度,提供了更丰富的视觉体验。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or list[PIL.Image] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class EnhanceImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'contrast': ('FLOAT', {'default': 0.5, 'min': 0, 'max': 10, 'step': 0.01, 'display': 'slider'})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Image' + INPUT_IS_LIST = True + OUTPUT_IS_LIST = (True,) + + def run(self, image, contrast): + contrast = contrast[0] + res = [] + for ims in image: + for im in ims: + image = tensor2pil(im) + image = enhance_depth_map(image, contrast) + image = pil2tensor(image) + res.append(image) + return (res,) +``` \ No newline at end of file diff --git a/docs/Esheep_Split_Image.md b/docs/Esheep_Split_Image.md new file mode 100644 index 0000000..a3874eb --- /dev/null +++ b/docs/Esheep_Split_Image.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: EsheepImageSplit +- Category: tests +- Output node: False +- Repo Ref: https://github.com/esheep/esheep_custom_nodes.git + +该节点旨在根据指定的列和行将图像分割成网格状的瓦片,便于以更易于管理的方式处理大型图像。通过将图像分解成更小的部分,它增强了工作流程,允许进行更集中的分析和操作。 + +# Input types +## Required +- images + - 图像参数至关重要,因为它提供了节点操作的源数据。它是主要的输入,决定了后续的处理和输出瓦片的生成。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +- columns + - 列数决定了图像水平分割的方式,直接影响到生成的瓦片的排列和数量。它是控制图像分割粒度的一个重要参数。 + - Comfy dtype: INT + - Python dtype: int +- lines + - 与列数类似,行数决定了图像的垂直分割,影响瓦片的形状和数量。它与列数参数共同定义了网格结构。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - 输出是由输入图像分割生成的瓦片集合。它代表了节点操作的主要结果,以一种可以在下游任务中进一步利用的格式封装了处理后的数据。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class EsheepImageSplit: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'columns': ('INT', {'default': 2, 'min': 1, 'max': 100, 'step': 1, 'display': 'number'}), 'lines': ('INT', {'default': 3, 'min': 1, 'max': 100, 'step': 1, 'display': 'number'})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'execute' + CATEGORY = 'tests' + + def execute(self, images, columns, lines): + image = images[0] + i = 255.0 * image.cpu().numpy() + pil_image = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) + imgwidth = pil_image.size[0] + imgheight = pil_image.size[1] + M = int(imgwidth / columns) + N = int(imgheight / lines) + tiles = [] + for i in range(0, imgheight - imgheight % N, N): + for j in range(0, imgwidth - imgwidth % M, M): + box = (j, i, j + M, i + N) + tiles.append(pil_image.crop(box)) + t_tiles = [] + for tile in tiles: + t_tile = tile.convert('RGB') + t_tile = np.array(t_tile).astype(np.float32) / 255.0 + t_tile = torch.from_numpy(t_tile)[None,] + t_tiles.append(t_tile) + s = t_tiles[0] + for i in range(1, len(t_tiles)): + s = torch.cat((s, t_tiles[i]), dim=0) + return (s,) +``` \ No newline at end of file diff --git a/docs/EvalFloats.md b/docs/EvalFloats.md new file mode 100644 index 0000000..2237363 --- /dev/null +++ b/docs/EvalFloats.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: EvalFloats +- Category: Mikey/Math +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +EvalFloats节点旨在评估作为字符串提供的数学表达式,使用两个浮点数作为公式中的变量。它作为一个多功能工具,用于执行可以动态定义的计算,提供了在数学运算中的灵活性,无需硬编码表达式。 + +# Input types +## Required +- a + - 参数'a'是一个浮点数,代表数学公式中的一个变量。它对于定义计算的初始状态至关重要,并直接影响评估表达式的结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- b + - 参数'b'是另一个浮点数,与'a'一起在数学表达式中使用。它在计算中扮演重要角色,因为它有助于从公式派生出最终结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- formula + - 参数'formula'是一个包含要评估的数学表达式的字符串。它至关重要,因为它决定了对输入变量'a'和'b'执行的操作,确定了计算的性质。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- result_float + - 输出'result_float'提供了评估数学表达式的浮点结果。它很重要,因为它代表了基于输入变量和公式的计算的直接结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- result_int + - 输出'result_int'是评估结果的整数表示。当需要从计算中获得整数值时,它很有用,提供了计算结果的一个离散版本。 + - Comfy dtype: INT + - Python dtype: int +- result_str + - 输出'result_str'是评估结果的字符串表示。它特别适用于以人类可读格式显示结果,或在需要字符串的进一步处理中使用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class EvalFloats: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'a': ('FLOAT', {'default': 0.0}), 'b': ('FLOAT', {'default': 0.0}), 'formula': ('STRING', {'multiline': False, 'default': 'a + b'})}} + RETURN_TYPES = ('FLOAT',) + RETURN_NAMES = ('result_float', 'result_int', 'result_str') + FUNCTION = 'process' + CATEGORY = 'Mikey/Math' + + def process(self, a, b, formula): + formula = formula.replace('a', str(a)) + formula = formula.replace('b', str(b)) + result = eval(formula) + return (result, int(result), str(result)) +``` \ No newline at end of file diff --git a/docs/Export API.md b/docs/Export API.md new file mode 100644 index 0000000..7ce8947 --- /dev/null +++ b/docs/Export API.md @@ -0,0 +1,99 @@ +# Documentation +- Class name: WAS_Export_API +- Category: WAS Suite/Debug +- Output node: True +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Export_API节点便于以结构化和有序的方式导出提示数据,确保输出以适当的命名约定和文件路径保存,便于检索和进一步分析。 + +# Input types +## Required +- save_prompt_api + - 此参数控制API是否应保存提示数据。这对于维护工作流中使用的提示的记录非常重要,这对于调试和审查目的至关重要。 + - Comfy dtype: COMBO[[['true', 'true']]] + - Python dtype: str +- output_path + - 输出路径是必不可少的,因为它定义了将保存提示数据的目录。这确保了数据的组织性,并便于将来参考。 + - Comfy dtype: STRING + - Python dtype: str +- filename_prefix + - 文件名前缀用于为导出文件的命名提供一个一致的起点。它有助于在输出目录内更有效地分类和识别文件。 + - Comfy dtype: STRING + - Python dtype: str +- filename_delimiter + - 分隔符是一个关键元素,它将文件名前缀与数字计数器分开,确保导出的文件有一个系统化和有序的命名约定。 + - Comfy dtype: STRING + - Python dtype: str +- filename_number_padding + - 数字填充参数决定了数字计数器的格式,确保文件名整齐对齐,便于按时间或数字顺序排序。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- parse_text_tokens + - 启用此功能时,它会解析并用相应值替换提示文本中的标记,这对于定制和个性化导出的数据至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- ui + - 输出提供了格式化的提示数据的JSON表示形式,这对于确保导出的信息既有结构又可被机器读取至关重要。 + - Comfy dtype: COMBO[[{'string': 'Prompt JSON'}]] + - Python dtype: Dict[str, str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Export_API: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'save_prompt_api': (['true', 'true'],), 'output_path': ('STRING', {'default': './ComfyUI/output/', 'multiline': False}), 'filename_prefix': ('STRING', {'default': 'ComfyUI_Prompt'}), 'filename_delimiter': ('STRING', {'default': '_'}), 'filename_number_padding': ('INT', {'default': 4, 'min': 2, 'max': 9, 'step': 1}), 'parse_text_tokens': ('BOOLEAN', {'default': False})}, 'hidden': {'prompt': 'PROMPT'}} + OUTPUT_NODE = True + RETURN_TYPES = () + FUNCTION = 'export_api' + CATEGORY = 'WAS Suite/Debug' + + def export_api(self, output_path=None, filename_prefix='ComfyUI', filename_number_padding=4, filename_delimiter='_', prompt=None, save_prompt_api='true', parse_text_tokens=False): + delimiter = filename_delimiter + number_padding = filename_number_padding if filename_number_padding > 1 else 4 + tokens = TextTokens() + if output_path in [None, '', 'none', '.']: + output_path = comfy_paths.output_directory + else: + output_path = tokens.parseTokens(output_path) + pattern = f'{re.escape(filename_prefix)}{re.escape(filename_delimiter)}(\\d{{{number_padding}}})' + existing_counters = [int(re.search(pattern, filename).group(1)) for filename in os.listdir(output_path) if re.match(pattern, filename)] + existing_counters.sort(reverse=True) + if existing_counters: + counter = existing_counters[0] + 1 + else: + counter = 1 + file = f'{filename_prefix}{filename_delimiter}{counter:0{number_padding}}.json' + output_file = os.path.abspath(os.path.join(output_path, file)) + if prompt: + if parse_text_tokens: + prompt = self.parse_prompt(prompt, tokens, keys_to_parse) + prompt_json = json.dumps(prompt, indent=4) + cstr('Prompt API JSON').msg.print() + print(prompt_json) + if save_prompt_api == 'true': + with open(output_file, 'w') as f: + f.write(prompt_json) + cstr(f'Output file path: {output_file}').msg.print() + return {'ui': {'string': prompt_json}} + + def parse_prompt(self, obj, tokens, keys_to_parse): + if isinstance(obj, dict): + return {key: self.parse_prompt(value, tokens, keys_to_parse) if key in keys_to_parse else value for (key, value) in obj.items()} + elif isinstance(obj, list): + return [self.parse_prompt(element, tokens, keys_to_parse) for element in obj] + elif isinstance(obj, str): + return tokens.parseTokens(obj) + else: + return obj +``` \ No newline at end of file diff --git a/docs/Export With Ffmpeg (mtb).md b/docs/Export With Ffmpeg (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ExtractKeyframes+.md b/docs/ExtractKeyframes+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/FILM VFI.md b/docs/FILM VFI.md new file mode 100644 index 0000000..a9ac034 --- /dev/null +++ b/docs/FILM VFI.md @@ -0,0 +1,84 @@ +# Documentation +- Class name: FILM_VFI +- Category: ComfyUI-Frame-Interpolation/VFI +- Output node: False +- Repo Ref: https://github.com/Fannovel16/ComfyUI-Frame-Interpolation + +FILM_VFI节点旨在通过插帧增强视频内容,从而提高帧率和平滑度,同时不牺牲视觉质量。它通过一个复杂的模型实现这一点,该模型利用机器学习技术在现有帧之间生成中间帧,为视频序列带来更流畅、更逼真的运动效果。 + +# Input types +## Required +- ckpt_name + - ckpt名称是一个关键参数,用于指定用于帧插值的预训练模型。它直接影响插值帧的质量和准确性,因为不同的模型可能在不同的数据集上训练或使用不同的算法。 + - Comfy dtype: STRING + - Python dtype: str +- frames + - 输入帧是帧插值过程的源材料。它们是必不可少的,因为它们提供了节点生成额外帧的视觉上下文,从而增强整个视频序列。这些输入帧的质量和分辨率在决定输出的视觉保真度方面起着重要作用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- clear_cache_after_n_frames + - 该参数通过指定在帧插值过程中应多久清除一次缓存来帮助管理计算资源。它间接影响节点的性能和内存使用情况,确保其在可用系统资源内运行。 + - Comfy dtype: INT + - Python dtype: int +- multiplier + - 乘数参数决定了在每对输入帧之间要生成的额外帧数。它对于控制输出视频的密度至关重要,较高的值可以带来更平滑的运动,但代价是增加计算复杂性。 + - Comfy dtype: INT + - Python dtype: int +- optional_interpolation_states + - 此参数通过指定哪些帧应跳过或不跳过来允许定制帧插值过程。它提供了对最终输出的一定控制水平,使节点能够迎合视频内容的特定要求或限制。 + - Comfy dtype: INTERPOLATION_STATES + - Python dtype: InterpolationStateList + +# Output types +- output_frames + - output_frames代表帧插值过程的结果,包括原始输入帧和新生成的中间帧。这个输出很重要,因为它提供了更高帧率的视频,增强了视觉体验和运动的平滑度。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class FILM_VFI: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (['film_net_fp32.pt'],), 'frames': ('IMAGE',), 'clear_cache_after_n_frames': ('INT', {'default': 10, 'min': 1, 'max': 1000}), 'multiplier': ('INT', {'default': 2, 'min': 2, 'max': 1000})}, 'optional': {'optional_interpolation_states': ('INTERPOLATION_STATES',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'vfi' + CATEGORY = 'ComfyUI-Frame-Interpolation/VFI' + + def vfi(self, ckpt_name: typing.AnyStr, frames: torch.Tensor, clear_cache_after_n_frames=10, multiplier: typing.SupportsInt=2, optional_interpolation_states: InterpolationStateList=None, **kwargs): + interpolation_states = optional_interpolation_states + model_path = load_file_from_github_release(MODEL_TYPE, ckpt_name) + model = torch.jit.load(model_path, map_location='cpu') + model.eval() + model = model.to(DEVICE) + dtype = torch.float32 + frames = preprocess_frames(frames) + number_of_frames_processed_since_last_cleared_cuda_cache = 0 + output_frames = [] + for frame_itr in range(len(frames) - 1): + if interpolation_states is not None and interpolation_states.is_frame_skipped(frame_itr): + continue + frame_0 = frames[frame_itr:frame_itr + 1].to(DEVICE).float() + frame_1 = frames[frame_itr + 1:frame_itr + 2].to(DEVICE).float() + relust = inference(model, frame_0, frame_1, multiplier - 1) + output_frames.extend([frame.detach().cpu().to(dtype=dtype) for frame in relust[:-1]]) + number_of_frames_processed_since_last_cleared_cuda_cache += 1 + if number_of_frames_processed_since_last_cleared_cuda_cache >= clear_cache_after_n_frames: + print('Comfy-VFI: Clearing cache...') + soft_empty_cache() + number_of_frames_processed_since_last_cleared_cuda_cache = 0 + print('Comfy-VFI: Done cache clearing') + gc.collect() + output_frames.append(frames[-1:].to(dtype=dtype)) + output_frames = [frame.cpu() for frame in output_frames] + out = torch.cat(output_frames, dim=0) + print('Comfy-VFI: Final clearing cache...') + soft_empty_cache() + print('Comfy-VFI: Done cache clearing') + return (postprocess_frames(out),) +``` \ No newline at end of file diff --git a/docs/FLAVR VFI.md b/docs/FLAVR VFI.md new file mode 100644 index 0000000..3664039 --- /dev/null +++ b/docs/FLAVR VFI.md @@ -0,0 +1,100 @@ +# Documentation +- Class name: FLAVR_VFI +- Category: ComfyUI-Frame-Interpolation/VFI +- Output node: False +- Repo Ref: https://github.com/Fannovel16/ComfyUI-Frame-Interpolation + +FLAVR_VFI节点旨在对输入帧序列执行帧插值,增强动画的平滑度和连续性。它使用底层模型生成中间帧,有效地将帧率翻倍。此节点对于需要流畅运动而无需大量计算资源的应用至关重要。 + +# Input types +## Required +- ckpt_name + - 检查点名称参数对于识别用于帧插值的特定模型权重至关重要。它确保加载正确的模型配置以处理帧。 + - Comfy dtype: str + - Python dtype: str +- frames + - frames参数是一个关键输入,包含要进行插值的图像序列。它构成了插值过程的基础,节点在提供的帧之间生成额外的帧,以实现更平滑的过渡。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +## Optional +- clear_cache_after_n_frames + - clear_cache_after_n_frames参数决定了在处理期间多久清除一次GPU缓存以保持最佳性能。它有助于有效管理内存使用,防止由于内存过载而导致的潜在减速或崩溃。 + - Comfy dtype: int + - Python dtype: int +- multiplier + - multiplier参数指定应增加帧率的倍数。目前,节点仅支持乘数为2,这将输入序列的帧率翻倍。 + - Comfy dtype: int + - Python dtype: int +- duplicate_first_last_frames + - 当设置为true时,duplicate_first_last_frames参数会在输出序列中复制第一帧和最后一帧。这对于保持插值动画的一致开头和结尾非常有用。 + - Comfy dtype: bool + - Python dtype: bool +- optional_interpolation_states + - optional_interpolation_states参数提供了一种通过指定应跳过或包含哪些帧来自定义插值过程的方法。这允许微调插值以满足特定的创意要求。 + - Comfy dtype: InterpolationStateList + - Python dtype: InterpolationStateList + +# Output types +- interpolated_frames + - interpolated_frames输出包含插值过程后的帧序列结果。这些帧包括原始输入帧以及新生成的中间帧,提供了更平滑、更连续的视觉输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class FLAVR_VFI: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (CKPT_NAMES,), 'frames': ('IMAGE',), 'clear_cache_after_n_frames': ('INT', {'default': 10, 'min': 1, 'max': 1000}), 'multiplier': ('INT', {'default': 2, 'min': 2, 'max': 2}), 'duplicate_first_last_frames': ('BOOLEAN', {'default': False})}, 'optional': {'optional_interpolation_states': ('INTERPOLATION_STATES',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'vfi' + CATEGORY = 'ComfyUI-Frame-Interpolation/VFI' + + def vfi(self, ckpt_name: typing.AnyStr, frames: torch.Tensor, clear_cache_after_n_frames=10, multiplier: typing.SupportsInt=2, duplicate_first_last_frames: bool=False, optional_interpolation_states: InterpolationStateList=None, **kwargs): + if multiplier != 2: + warnings.warn('Currently, FLAVR only supports 2x interpolation. The process will continue but please set multiplier=2 afterward') + assert_batch_size(frames, batch_size=4, vfi_name='ST-MFNet') + interpolation_states = optional_interpolation_states + model_path = load_file_from_github_release(MODEL_TYPE, ckpt_name) + model = build_flavr(model_path) + frames = preprocess_frames(frames) + padder = InputPadder(frames.shape, 16) + frames = padder.pad(frames) + number_of_frames_processed_since_last_cleared_cuda_cache = 0 + output_frames = [] + for frame_itr in range(len(frames) - 3): + if interpolation_states is not None and interpolation_states.is_frame_skipped(frame_itr) and interpolation_states.is_frame_skipped(frame_itr + 1): + continue + (frame0, frame1, frame2, frame3) = (frames[frame_itr:frame_itr + 1].float(), frames[frame_itr + 1:frame_itr + 2].float(), frames[frame_itr + 2:frame_itr + 3].float(), frames[frame_itr + 3:frame_itr + 4].float()) + new_frame = model([frame0.to(device), frame1.to(device), frame2.to(device), frame3.to(device)])[0].detach().cpu() + number_of_frames_processed_since_last_cleared_cuda_cache += 2 + if frame_itr == 0: + output_frames.append(frame0) + if duplicate_first_last_frames: + output_frames.append(frame0) + output_frames.append(frame1) + output_frames.append(new_frame) + output_frames.append(frame2) + if frame_itr == len(frames) - 4: + output_frames.append(frame3) + if duplicate_first_last_frames: + output_frames.append(frame3) + if number_of_frames_processed_since_last_cleared_cuda_cache >= clear_cache_after_n_frames: + print('Comfy-VFI: Clearing cache...', end=' ') + soft_empty_cache() + number_of_frames_processed_since_last_cleared_cuda_cache = 0 + print('Done cache clearing') + gc.collect() + dtype = torch.float32 + output_frames = [frame.cpu().to(dtype=dtype) for frame in output_frames] + out = torch.cat(output_frames, dim=0) + out = padder.unpad(out) + print('Comfy-VFI: Final clearing cache...', end=' ') + soft_empty_cache() + print('Done cache clearing') + return (postprocess_frames(out),) +``` \ No newline at end of file diff --git a/docs/Face Swap (mtb).md b/docs/Face Swap (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/FaceAnalysisModels.md b/docs/FaceAnalysisModels.md new file mode 100644 index 0000000..834e700 --- /dev/null +++ b/docs/FaceAnalysisModels.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: FaceAnalysisModels +- Category: FaceAnalysis +- Output node: False +- Repo Ref: https://github.com/cubiq/ComfyUI_FaceAnalysis.git + +方法 `load_models` 旨在初始化并加载面部分析任务所需的模型。它对于设置具有适当模型和提供者的运行环境至关重要,确保可以有效地执行后续的面部分析操作。 + +# Input types +## Required +- library + - 参数 `library` 指定要使用的面部分析库。它对于确定将加载哪些模型和算法进行面部检测和识别任务至关重要。 + - Comfy dtype: "str" + - Python dtype: str +- provider + - 参数 `provider` 指定用于执行模型的后端。它很重要,因为它影响模型的性能和与系统硬件的兼容性。 + - Comfy dtype: COMBO["CPU", "CUDA", "DirectML", "OpenVINO", "ROCM", "CoreML"] + - Python dtype: str + +# Output types +- out + - 参数 `out` 包含了加载的模型和相关信息。它很重要,因为它为后续的面部分析操作提供了必要的工具。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Union[FaceAnalysis, dlib.face_detector, dlib.shape_predictor, dlib.face_recognition_model_v1]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class FaceAnalysisModels: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'library': (INSTALLED_LIBRARIES,), 'provider': (['CPU', 'CUDA', 'DirectML', 'OpenVINO', 'ROCM', 'CoreML'],)}} + RETURN_TYPES = ('ANALYSIS_MODELS',) + FUNCTION = 'load_models' + CATEGORY = 'FaceAnalysis' + + def load_models(self, library, provider): + out = {} + if library == 'insightface': + out = {'library': library, 'detector': FaceAnalysis(name='buffalo_l', root=INSIGHTFACE_DIR, providers=[provider + 'ExecutionProvider'])} + out['detector'].prepare(ctx_id=0, det_size=(640, 640)) + else: + out = {'library': library, 'detector': dlib.get_frontal_face_detector(), 'shape_predict': dlib.shape_predictor(os.path.join(DLIB_DIR, 'shape_predictor_68_face_landmarks.dat')), 'face_recog': dlib.face_recognition_model_v1(os.path.join(DLIB_DIR, 'dlib_face_recognition_resnet_model_v1.dat'))} + return (out,) +``` \ No newline at end of file diff --git a/docs/FaceBBoxDetect(FaceParsing).md b/docs/FaceBBoxDetect(FaceParsing).md new file mode 100644 index 0000000..4b7cbd3 --- /dev/null +++ b/docs/FaceBBoxDetect(FaceParsing).md @@ -0,0 +1,69 @@ +# Documentation +- Class name: FaceBBoxDetect +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +FaceBBoxDetect节点旨在使用预训练的边界框检测器识别和定位图像中的面部。它处理输入图像以检测面部,并对边界框进行调整,以确保它们在图像边界内,从而提供经过提炼的面部边界框列表。 + +# Input types +## Required +- bbox_detector + - bbox_detector参数是用于检测输入图像中面部边界框的预训练模型。它对节点的功能至关重要,因为它直接影响面部检测过程的准确性和可靠性。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: YOLO +- image + - image参数表示将执行面部检测操作的输入图像数据。它至关重要,因为它是节点识别面部的主要信息来源。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- threshold + - threshold参数用于设置面部检测的置信度水平。它影响节点是否将检测到的面部包含在最终结果中的决定,从而影响检测的精度。 + - Comfy dtype: FLOAT + - Python dtype: float +- dilation + - dilation参数用于调整检测到的边界框的大小。它很重要,因为它可以帮助微调边界框坐标的准确性,以更好地适应面部的实际大小。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- bbox_list + - bbox_list输出包含检测到的面部周围的精炼边界框列表。它很重要,因为它代表了面部检测过程的直接结果,为进一步分析或处理提供了有价值的数据。 + - Comfy dtype: BBOX_LIST + - Python dtype: List[Tuple[int, int, int, int]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FaceBBoxDetect: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'bbox_detector': ('BBOX_DETECTOR', {}), 'image': ('IMAGE', {}), 'threshold': ('FLOAT', {'default': 0.3, 'min': 0, 'max': 1, 'step': 0.01}), 'dilation': ('INT', {'default': 8, 'min': -512, 'max': 512, 'step': 1})}} + RETURN_TYPES = ('BBOX_LIST',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, bbox_detector: YOLO, image: Tensor, threshold: float, dilation: int): + results = [] + transform = T.ToPILImage() + for item in image: + image_pil = transform(item.permute(2, 0, 1)) + pred = bbox_detector(image_pil, conf=threshold) + bboxes = pred[0].boxes.xyxy.cpu() + for bbox in bboxes: + bbox[0] = bbox[0] - dilation + bbox[1] = bbox[1] - dilation + bbox[2] = bbox[2] + dilation + bbox[3] = bbox[3] + dilation + bbox[0] = bbox[0] if bbox[0] > 0 else 0 + bbox[1] = bbox[1] if bbox[1] > 0 else 0 + bbox[2] = bbox[2] if bbox[2] < item.shape[1] else item.shape[1] + bbox[3] = bbox[3] if bbox[3] < item.shape[0] else item.shape[0] + results.append(bbox) + return (results,) +``` \ No newline at end of file diff --git a/docs/FaceBBoxDetectorLoader(FaceParsing).md b/docs/FaceBBoxDetectorLoader(FaceParsing).md new file mode 100644 index 0000000..ed79e51 --- /dev/null +++ b/docs/FaceBBoxDetectorLoader(FaceParsing).md @@ -0,0 +1,46 @@ +# Documentation +- Class name: FaceBBoxDetectorLoader +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +FaceBBoxDetectorLoader节点旨在加载和管理面部检测模型,使得输入数据能够用于识别和定位图像中的面部。它封装了初始化基于YOLO的模型的功能,这对于后续的面部相关分析任务至关重要。 + +# Input types +## Required +- model_name + - model_name参数对于指定节点使用的面部检测模型至关重要。它决定了模型的架构,从而影响了检测的准确性和性能。模型的选择直接影响节点处理和分析面部数据的能力。 + - Comfy dtype: COMBO['bbox/face_yolov5s.pt', 'bbox/face_yolov5m.pt', ...] + - Python dtype: Union[str, List[str] + +# Output types +- BBOX_DETECTOR + - FaceBBoxDetectorLoader节点的输出是一个配置好的面部检测模型,准备应用于面部图像。这个输出非常重要,因为它为进一步的面部分析奠定了基础,使得下游任务能够有效进行。 + - Comfy dtype: Tuple[YOLO] + - Python dtype: Tuple[YOLO] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FaceBBoxDetectorLoader: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + files = folder_paths.get_filename_list('ultralytics_bbox') + face_detect_models = list(filter(lambda x: 'face' in x, files)) + bboxs = ['bbox/' + x for x in face_detect_models] + return {'required': {'model_name': (bboxs, {})}} + RETURN_TYPES = ('BBOX_DETECTOR',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, model_name): + model_path = folder_paths.get_full_path('ultralytics', model_name) + model = YOLO(model_path) + return (model,) +``` \ No newline at end of file diff --git a/docs/FaceBoundingBox.md b/docs/FaceBoundingBox.md new file mode 100644 index 0000000..d9d750f --- /dev/null +++ b/docs/FaceBoundingBox.md @@ -0,0 +1,122 @@ +# Documentation +- Class name: FaceBoundingBox +- Category: FaceAnalysis +- Output node: False +- Repo Ref: https://github.com/cubiq/ComfyUI_FaceAnalysis.git + +该节点旨在分析图像并检测面部边界框,在需要面部检测和分析的图像处理应用中提供关键功能。 + +# Input types +## Required +- analysis_models + - 此参数包含用于图像中面部检测的模型和库,对节点处理和分析输入数据的能力有重大影响。 + - Comfy dtype: DICT[str, Any] + - Python dtype: Dict[str, Any] +- image + - 图像参数对节点的运行至关重要,因为它是面部边界框检测的主要输入,直接影响分析的准确性和有效性。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- padding + - 填充是一个重要的参数,它确保检测到的面部有足够的边界,防止切割问题,提高检测的整体质量。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- index + - 索引参数允许从多个检测中选择特定的面部,将节点的输出集中在所需的面部边界框上。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - 输出图像张量代表检测到的面部的裁剪和处理后的图像,对于进一步分析或显示目的来说是一个重要组成部分。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- x + - 边界框左上角的x坐标提供了面部检测的参考点,有助于精确定位图像中的面部。 + - Comfy dtype: INT + - Python dtype: int +- y + - 边界框左上角的y坐标对于在图像上下文中准确定位检测到的面部至关重要。 + - Comfy dtype: INT + - Python dtype: int +- width + - 边界框的宽度很重要,因为它决定了检测到的面部的大小,影响输出的分辨率和细节水平。 + - Comfy dtype: INT + - Python dtype: int +- height + - 边界框的高度对于保持检测到的面部的宽高比和比例至关重要,确保输出中面部特征的完整性。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FaceBoundingBox: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'analysis_models': ('ANALYSIS_MODELS',), 'image': ('IMAGE',), 'padding': ('INT', {'default': 0, 'min': 0, 'max': 4096, 'step': 1}), 'index': ('INT', {'default': -1, 'min': -1, 'max': 4096, 'step': 1})}} + RETURN_TYPES = ('IMAGE', 'INT', 'INT', 'INT', 'INT') + RETURN_NAMES = ('IMAGE', 'x', 'y', 'width', 'height') + FUNCTION = 'bbox' + CATEGORY = 'FaceAnalysis' + + def bbox(self, analysis_models, image, padding, index=-1): + out_img = [] + out_x = [] + out_y = [] + out_w = [] + out_h = [] + for i in image: + img = T.ToPILImage()(i.permute(2, 0, 1)).convert('RGB') + if analysis_models['library'] == 'insightface': + faces = analysis_models['detector'].get(np.array(img)) + for face in faces: + (x, y, w, h) = face.bbox.astype(int) + w = w - x + h = h - y + x = max(0, x - padding) + y = max(0, y - padding) + w = min(img.width, w + 2 * padding) + h = min(img.height, h + 2 * padding) + crop = img.crop((x, y, x + w, y + h)) + out_img.append(T.ToTensor()(crop).permute(1, 2, 0)) + out_x.append(x) + out_y.append(y) + out_w.append(w) + out_h.append(h) + else: + faces = analysis_models['detector'](np.array(img), 1) + for face in faces: + (x, y, w, h) = (face.left(), face.top(), face.width(), face.height()) + x = max(0, x - padding) + y = max(0, y - padding) + w = min(img.width, w + 2 * padding) + h = min(img.height, h + 2 * padding) + crop = img.crop((x, y, x + w, y + h)) + out_img.append(T.ToTensor()(crop).permute(1, 2, 0)) + out_x.append(x) + out_y.append(y) + out_w.append(w) + out_h.append(h) + if not out_img: + raise Exception('No face detected in image.') + if len(out_img) == 1: + index = 0 + if index > len(out_img) - 1: + index = len(out_img) - 1 + if index != -1: + out_img = out_img[index].unsqueeze(0) + out_x = out_x[index] + out_y = out_y[index] + out_w = out_w[index] + out_h = out_h[index] + else: + w = out_img[0].shape[1] + h = out_img[0].shape[0] + out_img = [comfy.utils.common_upscale(img.unsqueeze(0).movedim(-1, 1), w, h, 'bilinear', 'center').movedim(1, -1).squeeze(0) for img in out_img] + out_img = torch.stack(out_img) + return (out_img, out_x, out_y, out_w, out_h) +``` \ No newline at end of file diff --git a/docs/FaceDetailer.md b/docs/FaceDetailer.md new file mode 100644 index 0000000..030a2ad --- /dev/null +++ b/docs/FaceDetailer.md @@ -0,0 +1,106 @@ +# Documentation +- Class name: FaceDetailer +- Category: ImpactPack/Simple +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +FaceDetailer 节点旨在增强和细化图像中的面部细节。它结合使用多种模型和算法来检测面部,应用详细的增强效果,并输出具有改进面部特征的精细图像。在图像后期处理工作流程中,当需要高质量的面部细节时,该节点发挥着关键作用。 + +# Input types +## Required +- image + - 输入图像,将在此图像上执行面部细节增强。它是节点处理的主要数据源。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- model + - 用于面部细节增强的模型。它是一个关键组件,定义了应用于输入图像的增强质量和风格。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - 与面部细节模型一起使用的 CLIP 模型,以确保增强图像的连贯性和相关性。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- guide_size + - 引导尺寸参数影响模型在增强过程中关注的面部特征的尺度。这是一个重要的调整参数,用于控制输出图像中的细节水平。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- enhanced_image + - 经过 FaceDetailer 节点处理后,具有增强面部细节的结果图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- cropped_enhanced + - 在输入图像中检测到的一系列裁剪并可能增强的面部片段。 + - Comfy dtype: COMBO[IMAGE] + - Python dtype: List[torch.Tensor] +- mask + - 表示已经被增强的面部区域的掩码。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class FaceDetailer: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'model': ('MODEL',), 'clip': ('CLIP',), 'vae': ('VAE',), 'guide_size': ('FLOAT', {'default': 384, 'min': 64, 'max': nodes.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': nodes.MAX_RESOLUTION, 'step': 8}), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'denoise': ('FLOAT', {'default': 0.5, 'min': 0.0001, 'max': 1.0, 'step': 0.01}), 'feather': ('INT', {'default': 5, 'min': 0, 'max': 100, 'step': 1}), 'noise_mask': ('BOOLEAN', {'default': True, 'label_on': 'enabled', 'label_off': 'disabled'}), 'force_inpaint': ('BOOLEAN', {'default': True, 'label_on': 'enabled', 'label_off': 'disabled'}), 'bbox_threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'bbox_dilation': ('INT', {'default': 10, 'min': -512, 'max': 512, 'step': 1}), 'bbox_crop_factor': ('FLOAT', {'default': 3.0, 'min': 1.0, 'max': 10, 'step': 0.1}), 'sam_detection_hint': (['center-1', 'horizontal-2', 'vertical-2', 'rect-4', 'diamond-4', 'mask-area', 'mask-points', 'mask-point-bbox', 'none'],), 'sam_dilation': ('INT', {'default': 0, 'min': -512, 'max': 512, 'step': 1}), 'sam_threshold': ('FLOAT', {'default': 0.93, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'sam_bbox_expansion': ('INT', {'default': 0, 'min': 0, 'max': 1000, 'step': 1}), 'sam_mask_hint_threshold': ('FLOAT', {'default': 0.7, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'sam_mask_hint_use_negative': (['False', 'Small', 'Outter'],), 'drop_size': ('INT', {'min': 1, 'max': MAX_RESOLUTION, 'step': 1, 'default': 10}), 'bbox_detector': ('BBOX_DETECTOR',), 'wildcard': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'cycle': ('INT', {'default': 1, 'min': 1, 'max': 10, 'step': 1})}, 'optional': {'sam_model_opt': ('SAM_MODEL',), 'segm_detector_opt': ('SEGM_DETECTOR',), 'detailer_hook': ('DETAILER_HOOK',), '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 = ('IMAGE', 'IMAGE', 'IMAGE', 'MASK', 'DETAILER_PIPE', 'IMAGE') + RETURN_NAMES = ('image', 'cropped_refined', 'cropped_enhanced_alpha', 'mask', 'detailer_pipe', 'cnet_images') + OUTPUT_IS_LIST = (False, True, True, False, False, True) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Simple' + + @staticmethod + def enhance_face(image, model, clip, vae, guide_size, guide_size_for_bbox, max_size, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, bbox_threshold, bbox_dilation, bbox_crop_factor, sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion, sam_mask_hint_threshold, sam_mask_hint_use_negative, drop_size, bbox_detector, segm_detector=None, sam_model_opt=None, wildcard_opt=None, detailer_hook=None, refiner_ratio=None, refiner_model=None, refiner_clip=None, refiner_positive=None, refiner_negative=None, cycle=1, inpaint_model=False, noise_mask_feather=0): + bbox_detector.setAux('face') + segs = bbox_detector.detect(image, bbox_threshold, bbox_dilation, bbox_crop_factor, drop_size, detailer_hook=detailer_hook) + bbox_detector.setAux(None) + if sam_model_opt is not None: + sam_mask = core.make_sam_mask(sam_model_opt, segs, image, sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion, sam_mask_hint_threshold, sam_mask_hint_use_negative) + segs = core.segs_bitwise_and_mask(segs, sam_mask) + elif segm_detector is not None: + segm_segs = segm_detector.detect(image, bbox_threshold, bbox_dilation, bbox_crop_factor, drop_size) + if hasattr(segm_detector, 'override_bbox_by_segm') and segm_detector.override_bbox_by_segm and (not (detailer_hook is not None and (not hasattr(detailer_hook, 'override_bbox_by_segm')))): + segs = segm_segs + else: + segm_mask = core.segs_to_combined_mask(segm_segs) + segs = core.segs_bitwise_and_mask(segs, segm_mask) + if len(segs[1]) > 0: + (enhanced_img, _, cropped_enhanced, cropped_enhanced_alpha, cnet_pil_list, new_segs) = DetailerForEach.do_detail(image, segs, model, clip, vae, guide_size, guide_size_for_bbox, max_size, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, wildcard_opt, detailer_hook, refiner_ratio=refiner_ratio, refiner_model=refiner_model, refiner_clip=refiner_clip, refiner_positive=refiner_positive, refiner_negative=refiner_negative, cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + else: + enhanced_img = image + cropped_enhanced = [] + cropped_enhanced_alpha = [] + cnet_pil_list = [] + mask = core.segs_to_combined_mask(segs) + if len(cropped_enhanced) == 0: + cropped_enhanced = [empty_pil_tensor()] + if len(cropped_enhanced_alpha) == 0: + cropped_enhanced_alpha = [empty_pil_tensor()] + if len(cnet_pil_list) == 0: + cnet_pil_list = [empty_pil_tensor()] + return (enhanced_img, cropped_enhanced, cropped_enhanced_alpha, mask, cnet_pil_list) + + def doit(self, image, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, bbox_threshold, bbox_dilation, bbox_crop_factor, sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion, sam_mask_hint_threshold, sam_mask_hint_use_negative, drop_size, bbox_detector, wildcard, cycle=1, sam_model_opt=None, segm_detector_opt=None, detailer_hook=None, inpaint_model=False, noise_mask_feather=0): + result_img = None + result_mask = None + result_cropped_enhanced = [] + result_cropped_enhanced_alpha = [] + result_cnet_images = [] + if len(image) > 1: + print(f'[Impact Pack] WARN: FaceDetailer is not a node designed for video detailing. If you intend to perform video detailing, please use Detailer For AnimateDiff.') + for (i, single_image) in enumerate(image): + (enhanced_img, cropped_enhanced, cropped_enhanced_alpha, mask, cnet_pil_list) = FaceDetailer.enhance_face(single_image.unsqueeze(0), model, clip, vae, guide_size, guide_size_for, max_size, seed + i, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, bbox_threshold, bbox_dilation, bbox_crop_factor, sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion, sam_mask_hint_threshold, sam_mask_hint_use_negative, drop_size, bbox_detector, segm_detector_opt, sam_model_opt, wildcard, detailer_hook, cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + result_img = torch.cat((result_img, enhanced_img), dim=0) if result_img is not None else enhanced_img + result_mask = torch.cat((result_mask, mask), dim=0) if result_mask is not None else mask + result_cropped_enhanced.extend(cropped_enhanced) + result_cropped_enhanced_alpha.extend(cropped_enhanced_alpha) + result_cnet_images.extend(cnet_pil_list) + pipe = (model, clip, vae, positive, negative, wildcard, bbox_detector, segm_detector_opt, sam_model_opt, detailer_hook, None, None, None, None) + return (result_img, result_cropped_enhanced, result_cropped_enhanced_alpha, result_mask, pipe, result_cnet_images) +``` \ No newline at end of file diff --git a/docs/FaceDetailerPipe.md b/docs/FaceDetailerPipe.md new file mode 100644 index 0000000..0fc186a --- /dev/null +++ b/docs/FaceDetailerPipe.md @@ -0,0 +1,81 @@ +# Documentation +- Class name: FaceDetailerPipe +- Category: ImpactPack/Simple +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +FaceDetailerPipe 节点旨在增强图像中面部的细节。它处理输入图像以细化面部特征并提高整体质量,利用一系列先进的图像处理技术和模型。其主要目标是提供更详细和精细的视觉输出,特别适用于需要高质量面部表示的应用。 + +# Input types +## Required +- image + - 输入图像是节点执行面部细化所需的主要数据。它是所有后续处理和增强活动的基础。输入图像的质量和分辨率直接影响最终输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- detailer_pipe + - detailer_pipe 是指导面部细化过程的模型和参数集合。它包括模型、clip 和 vae 等重要组件,这些对于实现所需的细节增强水平至关重要。 + - Comfy dtype: DETAILER_PIPE + - Python dtype: Tuple[Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any] +- guide_size + - guide_size 参数确定用于面部细化的引导图像的大小。这是一个关键因素,它影响最终输出中可以实现的细节水平。较大的引导尺寸通常允许更详细的增强。 + - Comfy dtype: FLOAT + - Python dtype: float +- max_size + - max_size 参数设置了输入图像的最大尺寸。这是一个重要的考虑因素,因为较大的图像可以显著增加处理时间和资源需求,对性能和内存使用有影响。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- image + - 增强的图像输出是 FaceDetailerPipe 节点的主要结果。它包含了从原始输入图像中提炼和改进的面部细节。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- cropped_refined + - cropped_refined 输出包含从增强图像中裁剪出的一系列细化的面部图像。它们可以用于进一步处理或作为独立的详细图像。 + - Comfy dtype: LIST[IMAGE] + - Python dtype: List[torch.Tensor] +- mask + - mask 输出是一个二进制图像,它描绘了已经被增强的面部区域。这对于隔离详细区域以进行额外的处理或分析非常有用。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class FaceDetailerPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'detailer_pipe': ('DETAILER_PIPE',), 'guide_size': ('FLOAT', {'default': 384, 'min': 64, 'max': nodes.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': nodes.MAX_RESOLUTION, 'step': 8}), '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}), 'noise_mask': ('BOOLEAN', {'default': True, 'label_on': 'enabled', 'label_off': 'disabled'}), 'force_inpaint': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'}), 'bbox_threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'bbox_dilation': ('INT', {'default': 10, 'min': -512, 'max': 512, 'step': 1}), 'bbox_crop_factor': ('FLOAT', {'default': 3.0, 'min': 1.0, 'max': 10, 'step': 0.1}), 'sam_detection_hint': (['center-1', 'horizontal-2', 'vertical-2', 'rect-4', 'diamond-4', 'mask-area', 'mask-points', 'mask-point-bbox', 'none'],), 'sam_dilation': ('INT', {'default': 0, 'min': -512, 'max': 512, 'step': 1}), 'sam_threshold': ('FLOAT', {'default': 0.93, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'sam_bbox_expansion': ('INT', {'default': 0, 'min': 0, 'max': 1000, 'step': 1}), 'sam_mask_hint_threshold': ('FLOAT', {'default': 0.7, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'sam_mask_hint_use_negative': (['False', 'Small', 'Outter'],), 'drop_size': ('INT', {'min': 1, 'max': MAX_RESOLUTION, 'step': 1, 'default': 10}), 'refiner_ratio': ('FLOAT', {'default': 0.2, 'min': 0.0, 'max': 1.0}), 'cycle': ('INT', {'default': 1, 'min': 1, 'max': 10, 'step': 1})}, 'optional': {'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 = ('IMAGE', 'IMAGE', 'IMAGE', 'MASK', 'DETAILER_PIPE', 'IMAGE') + RETURN_NAMES = ('image', 'cropped_refined', 'cropped_enhanced_alpha', 'mask', 'detailer_pipe', 'cnet_images') + OUTPUT_IS_LIST = (False, True, True, False, False, True) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Simple' + + def doit(self, image, detailer_pipe, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, denoise, feather, noise_mask, force_inpaint, bbox_threshold, bbox_dilation, bbox_crop_factor, sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion, sam_mask_hint_threshold, sam_mask_hint_use_negative, drop_size, refiner_ratio=None, cycle=1, inpaint_model=False, noise_mask_feather=0): + result_img = None + result_mask = None + result_cropped_enhanced = [] + result_cropped_enhanced_alpha = [] + result_cnet_images = [] + if len(image) > 1: + print(f'[Impact Pack] WARN: FaceDetailer is not a node designed for video detailing. If you intend to perform video detailing, please use Detailer For AnimateDiff.') + (model, clip, vae, positive, negative, wildcard, bbox_detector, segm_detector, sam_model_opt, detailer_hook, refiner_model, refiner_clip, refiner_positive, refiner_negative) = detailer_pipe + for (i, single_image) in enumerate(image): + (enhanced_img, cropped_enhanced, cropped_enhanced_alpha, mask, cnet_pil_list) = FaceDetailer.enhance_face(single_image.unsqueeze(0), model, clip, vae, guide_size, guide_size_for, max_size, seed + i, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, bbox_threshold, bbox_dilation, bbox_crop_factor, sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion, sam_mask_hint_threshold, sam_mask_hint_use_negative, drop_size, bbox_detector, segm_detector, sam_model_opt, wildcard, detailer_hook, refiner_ratio=refiner_ratio, refiner_model=refiner_model, refiner_clip=refiner_clip, refiner_positive=refiner_positive, refiner_negative=refiner_negative, cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + result_img = torch.cat((result_img, enhanced_img), dim=0) if result_img is not None else enhanced_img + result_mask = torch.cat((result_mask, mask), dim=0) if result_mask is not None else mask + result_cropped_enhanced.extend(cropped_enhanced) + result_cropped_enhanced_alpha.extend(cropped_enhanced_alpha) + result_cnet_images.extend(cnet_pil_list) + if len(result_cropped_enhanced) == 0: + result_cropped_enhanced = [empty_pil_tensor()] + if len(result_cropped_enhanced_alpha) == 0: + result_cropped_enhanced_alpha = [empty_pil_tensor()] + if len(result_cnet_images) == 0: + result_cnet_images = [empty_pil_tensor()] + return (result_img, result_cropped_enhanced, result_cropped_enhanced_alpha, result_mask, detailer_pipe, result_cnet_images) +``` \ No newline at end of file diff --git a/docs/FaceEmbedDistance.md b/docs/FaceEmbedDistance.md new file mode 100644 index 0000000..e276265 --- /dev/null +++ b/docs/FaceEmbedDistance.md @@ -0,0 +1,141 @@ +# Documentation +- Class name: FaceEmbedDistance +- Category: FaceAnalysis +- Output node: False +- Repo Ref: https://github.com/cubiq/ComfyUI_FaceAnalysis.git + +FaceEmbedDistance节点旨在使用欧几里得和余弦距离度量来分析和比较面部特征。它处理输入图像和参考图像以确定相似性,促进面部的识别和验证。该节点的主要目标是通过提供面部嵌入的全面分析,增强面部识别任务。 + +# Input types +## Required +- analysis_models + - 此参数包含用于面部检测和嵌入提取所需的模型,对于节点执行面部分析功能至关重要。 + - Comfy dtype: DICTIONARY + - Python dtype: Dict[str, Any] +- reference + - 参考图像对于与输入图像进行比较至关重要。它们作为计算距离和识别匹配的基线,对节点分析面部相似性的能力有着显著影响。 + - Comfy dtype: LIST + - Python dtype: List[PIL.Image.Image] +- image + - 这些是将被分析并与参考图像进行比较的图像。这些图像的质量和相关性直接影响节点的输出及其在面部识别中的有效性。 + - Comfy dtype: LIST + - Python dtype: List[PIL.Image.Image] +## Optional +- filter_thresh_eucl + - 欧几里得距离阈值用于过滤掉过于不相似的图像。它在控制面部相似性评估的严格程度方面起着关键作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- filter_thresh_cos + - 余弦距离阈值与欧几里得阈值一起使用,以细化面部相似性评估,专注于面部嵌入的方向性而不仅仅是它们的幅度。 + - Comfy dtype: FLOAT + - Python dtype: float +- generate_image_overlay + - 启用此选项时,它会在输入图像上生成一个覆盖层,显示距离度量,从而提供面部分析结果的视觉表示。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- IMAGE + - 输出图像,可能包含覆盖层,代表了分析后的输入图像。它们对于视觉验证和进一步分析至关重要。 + - Comfy dtype: LIST + - Python dtype: List[PIL.Image.Image] +- euclidean + - 此输出提供欧几里得距离值,量化了参考图像和输入图像之间的差异程度,有助于评估面部相似性。 + - Comfy dtype: FLOAT + - Python dtype: float +- cosine + - 余弦距离值提供了面部嵌入之间方向性差异的度量,补充了欧几里得距离,以便进行更细致的面部相似性评估。 + - Comfy dtype: FLOAT + - Python dtype: float +- csv + - CSV输出包含面部分析的结构化记录,包括距离度量,可用于进一步的统计分析和报告。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FaceEmbedDistance: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'analysis_models': ('ANALYSIS_MODELS',), 'reference': ('IMAGE',), 'image': ('IMAGE',), 'filter_thresh_eucl': ('FLOAT', {'default': 1.0, 'min': 0.001, 'max': 2.0, 'step': 0.001}), 'filter_thresh_cos': ('FLOAT', {'default': 1.0, 'min': 0.001, 'max': 2.0, 'step': 0.001}), 'generate_image_overlay': ('BOOLEAN', {'default': True})}} + RETURN_TYPES = ('IMAGE', 'FLOAT', 'FLOAT', 'STRING') + RETURN_NAMES = ('IMAGE', 'euclidean', 'cosine', 'csv') + OUTPUT_NODE = True + FUNCTION = 'analize' + CATEGORY = 'FaceAnalysis' + + def analize(self, analysis_models, reference, image, filter_thresh_eucl=1.0, filter_thresh_cos=1.0, generate_image_overlay=True): + if generate_image_overlay: + font = ImageFont.truetype(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Inconsolata.otf'), 32) + background_color = ImageColor.getrgb('#000000AA') + txt_height = font.getmask('Q').getbbox()[3] + font.getmetrics()[1] + self.analysis_models = analysis_models + ref = [] + for i in reference: + ref_emb = self.get_descriptor(np.array(T.ToPILImage()(i.permute(2, 0, 1)).convert('RGB'))) + if ref_emb is not None: + ref.append(torch.from_numpy(ref_emb)) + if ref == []: + raise Exception('No face detected in reference image') + ref = torch.stack(ref) + ref = np.array(torch.mean(ref, dim=0)) + out = [] + out_eucl = [] + out_cos = [] + for i in image: + img = np.array(T.ToPILImage()(i.permute(2, 0, 1)).convert('RGB')) + img = self.get_descriptor(img) + if img is None: + eucl_dist = 1.0 + cos_dist = 1.0 + elif np.array_equal(ref, img): + eucl_dist = 0.0 + cos_dist = 0.0 + else: + eucl_dist = np.float64(np.linalg.norm(ref - img)) + cos_dist = 1 - np.dot(ref, img) / (np.linalg.norm(ref) * np.linalg.norm(img)) + if eucl_dist <= filter_thresh_eucl and cos_dist <= filter_thresh_cos: + print(f'\x1b[96mFace Analysis: Euclidean: {eucl_dist}, Cosine: {cos_dist}\x1b[0m') + if generate_image_overlay: + tmp = T.ToPILImage()(i.permute(2, 0, 1)).convert('RGBA') + txt = Image.new('RGBA', (image.shape[2], txt_height), color=background_color) + draw = ImageDraw.Draw(txt) + draw.text((0, 0), f'EUC: {round(eucl_dist, 3)} | COS: {round(cos_dist, 3)}', font=font, fill=(255, 255, 255, 255)) + composite = Image.new('RGBA', tmp.size) + composite.paste(txt, (0, tmp.height - txt.height)) + composite = Image.alpha_composite(tmp, composite) + out.append(T.ToTensor()(composite).permute(1, 2, 0)) + else: + out.append(i) + out_eucl.append(eucl_dist) + out_cos.append(cos_dist) + if not out: + raise Exception('No image matches the filter criteria.') + img = torch.stack(out) + csv = 'id,euclidean,cosine\n' + if len(out_eucl) == 1: + out_eucl = out_eucl[0] + out_cos = out_cos[0] + csv += f'0,{out_eucl},{out_cos}\n' + else: + for (id, (eucl, cos)) in enumerate(zip(out_eucl, out_cos)): + csv += f'{id},{eucl},{cos}\n' + return (img, out_eucl, out_cos, csv) + + def get_descriptor(self, image): + embeds = None + if self.analysis_models['library'] == 'insightface': + faces = self.analysis_models['detector'].get(image) + if len(faces) > 0: + embeds = faces[0].normed_embedding + else: + faces = self.analysis_models['detector'](image) + if len(faces) > 0: + shape = self.analysis_models['shape_predict'](image, faces[0]) + embeds = np.array(self.analysis_models['face_recog'].compute_face_descriptor(image, shape)) + return embeds +``` \ No newline at end of file diff --git a/docs/FaceFixerOpenCV.md b/docs/FaceFixerOpenCV.md new file mode 100644 index 0000000..45b2a67 --- /dev/null +++ b/docs/FaceFixerOpenCV.md @@ -0,0 +1,218 @@ +# Documentation +- Class name: FaceFixerOpenCV +- Category: Mikey/Utils +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +FaceFixerOpenCV节点旨在使用一系列面部检测和图像处理技术增强和修正图像中的面部特征。它利用OpenCV进行面部检测,并应用先进算法来细化和融合面部,确保在原始图像中修正后的面部能够无缝集成。 + +# Input types +## Required +- image + - 输入图像是将执行面部修正操作的对象。它作为节点内所有后续处理和分析的基础。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- base_model + - 基础模型用于节点内的特征提取和处理。它在确定面部特征增强的质量和准确性方面起着关键作用。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- vae + - 变分自编码器(VAE)用于编码和解码面部特征。它在节点内的特征转换和重建过程中至关重要。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- positive_cond_base + - 正向调节基础,用于引导面部特征增强过程朝着期望的结果发展。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative_cond_base + - 负向调节基础,用于在增强过程中抑制某些面部特征或特征。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +## Optional +- seed + - 用于面部特征增强过程中随机元素的随机种子。它确保了结果的可复现性。 + - Comfy dtype: INT + - Python dtype: int +- face_img_resolution + - 处理面部图像的分辨率。它影响细节水平和计算负载。 + - Comfy dtype: INT + - Python dtype: int +- padding + - 在处理前应用于检测到的面部的填充量。它有助于保留边缘的面部细节。 + - Comfy dtype: INT + - Python dtype: int +- scale_factor + - 面部检测期间使用的缩放因子,用于调整检测窗口的大小。 + - Comfy dtype: FLOAT + - Python dtype: float +- min_neighbors + - 保留检测到的面部所需的最小邻居数。这是面部检测算法的一个参数。 + - Comfy dtype: INT + - Python dtype: int +- denoise + - 应用于重建面部特征的去噪水平。它平衡了细节保留和噪声减少。 + - Comfy dtype: FLOAT + - Python dtype: float +- classifier + - 用于面部检测的分类器类型。它决定了应用于图像中检测面部的算法和模型。 + - Comfy dtype: STRING + - Python dtype: str +- sampler_name + - VAE解码过程中使用的采样器名称。它影响生成样本的随机性和多样性。 + - Comfy dtype: STRING + - Python dtype: str +- scheduler + - 用于控制VAE解码过程中采样进度的调度器。它影响采样步骤的插值和进度。 + - Comfy dtype: STRING + - Python dtype: str +- cfg + - VAE采样过程中的配置参数。它微调采样算法的行为。 + - Comfy dtype: FLOAT + - Python dtype: float +- steps + - VAE采样过程中的步骤数。它决定了采样的持续时间和彻底性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 具有增强和修正面部特征的输出图像。它是节点处理的结果,代表了面部增强后输入图像的最终状态。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FaceFixerOpenCV: + + @classmethod + def INPUT_TYPES(s): + classifiers = ['animeface', 'combined', 'haarcascade_frontalface_default.xml', 'haarcascade_profileface.xml', 'haarcascade_frontalface_alt.xml', 'haarcascade_frontalface_alt2.xml', 'haarcascade_upperbody.xml', 'haarcascade_fullbody.xml', 'haarcascade_lowerbody.xml', 'haarcascade_frontalcatface.xml', 'hands'] + return {'required': {'image': ('IMAGE',), 'base_model': ('MODEL',), 'vae': ('VAE',), 'positive_cond_base': ('CONDITIONING',), 'negative_cond_base': ('CONDITIONING',), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'face_img_resolution': ('INT', {'default': 1024, 'min': 512, 'max': 2048}), 'padding': ('INT', {'default': 32, 'min': 0, 'max': 512}), 'scale_factor': ('FLOAT', {'default': 1.2, 'min': 0.1, 'max': 10.0, 'step': 0.1}), 'min_neighbors': ('INT', {'default': 8, 'min': 1, 'max': 100}), 'denoise': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'classifier': (classifiers, {'default': 'combined'}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS, {'default': 'dpmpp_2m_sde'}), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS, {'default': 'karras'}), 'cfg': ('FLOAT', {'default': 7.0, 'min': 0.0, 'max': 1000.0, 'step': 0.1}), 'steps': ('INT', {'default': 30, 'min': 1, 'max': 1000})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'run' + CATEGORY = 'Mikey/Utils' + + def calculate_iou(self, box1, box2): + """ + Calculate the Intersection over Union (IoU) of two bounding boxes. + + Parameters: + box1, box2: The bounding boxes, each defined as [x, y, width, height] + + Returns: + iou: Intersection over Union as a float. + """ + (x1_min, y1_min, x1_max, y1_max) = (box1[0], box1[1], box1[0] + box1[2], box1[1] + box1[3]) + (x2_min, y2_min, x2_max, y2_max) = (box2[0], box2[1], box2[0] + box2[2], box2[1] + box2[3]) + intersect_x_min = max(x1_min, x2_min) + intersect_y_min = max(y1_min, y2_min) + intersect_x_max = min(x1_max, x2_max) + intersect_y_max = min(y1_max, y2_max) + intersect_area = max(0, intersect_x_max - intersect_x_min) * max(0, intersect_y_max - intersect_y_min) + box1_area = (x1_max - x1_min) * (y1_max - y1_min) + box2_area = (x2_max - x2_min) * (y2_max - y2_min) + union_area = box1_area + box2_area - intersect_area + iou = intersect_area / union_area if union_area != 0 else 0 + return iou + + def detect_faces(self, image, classifier, scale_factor, min_neighbors): + try: + import cv2 + except ImportError: + raise Exception('OpenCV is not installed. Please install it using "pip install opencv-python"') + if classifier == 'animeface': + p = os.path.dirname(os.path.realpath(__file__)) + p = os.path.join(p, 'haar_cascade_models/animeface.xml') + elif classifier == 'hands': + p = os.path.dirname(os.path.realpath(__file__)) + p = os.path.join(p, 'haar_cascade_models/hand_gesture.xml') + else: + p = cv2.data.haarcascades + classifier + face_cascade = cv2.CascadeClassifier(p) + image_np = np.clip(255.0 * image.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + gray = cv2.cvtColor(image_np, cv2.COLOR_BGR2GRAY) + faces = face_cascade.detectMultiScale(gray, scaleFactor=scale_factor, minNeighbors=min_neighbors, minSize=(32, 32)) + return faces + + def combo_detection(self, image, scale_factor, min_neighbors): + front_faces = self.detect_faces(image, 'haarcascade_frontalface_default.xml', scale_factor, min_neighbors) + profile_faces = self.detect_faces(image, 'haarcascade_profileface.xml', scale_factor, min_neighbors) + anime_faces = self.detect_faces(image, 'animeface', scale_factor, min_neighbors) + if front_faces == () and profile_faces == () and (anime_faces == ()): + return front_faces + if front_faces == () and profile_faces != () and (anime_faces == ()): + return profile_faces + if front_faces != () and profile_faces == () and (anime_faces == ()): + return front_faces + if front_faces == () and profile_faces == () and (anime_faces != ()): + return anime_faces + arrays = [] + if front_faces != (): + arrays.append(front_faces) + if profile_faces != (): + arrays.append(profile_faces) + if anime_faces != (): + arrays.append(anime_faces) + combined_faces = np.concatenate(arrays, axis=0) + iou_threshold = 0.2 + faces = [] + for face in combined_faces: + if len(faces) == 0: + faces.append(face) + else: + iou = [self.calculate_iou(face, f) for f in faces] + if max(iou) < iou_threshold: + faces.append(face) + return faces + + def run(self, image, base_model, vae, positive_cond_base, negative_cond_base, seed, face_img_resolution=768, padding=8, scale_factor=1.2, min_neighbors=6, denoise=0.25, classifier='haarcascade_frontalface_default.xml', sampler_name='dpmpp_3m_sde_gpu', scheduler='exponential', cfg=7.0, steps=30): + image_scaler = ImageScale() + vaeencoder = VAEEncode() + vaedecoder = VAEDecode() + if classifier == 'combined': + faces = self.combo_detection(image, scale_factor, min_neighbors) + else: + faces = self.detect_faces(image, classifier, scale_factor, min_neighbors) + if faces == (): + return (image,) + result = image.clone() + for (x, y, w, h) in faces: + x -= padding + y -= padding + w += padding * 2 + h += padding * 2 + x = max(0, x) + y = max(0, y) + w = min(w, image.shape[2] - x) + h = min(h, image.shape[1] - y) + og_crop = image[:, y:y + h, x:x + w] + (org_width, org_height) = (og_crop.shape[2], og_crop.shape[1]) + crop = image_scaler.upscale(og_crop, 'lanczos', face_img_resolution, face_img_resolution, 'center')[0] + samples = vaeencoder.encode(vae, crop)[0] + samples = common_ksampler(base_model, seed, steps, cfg, sampler_name, scheduler, positive_cond_base, negative_cond_base, samples, start_step=int((1 - steps * denoise) // 1), last_step=steps, force_full_denoise=False)[0] + crop = vaedecoder.decode(vae, samples)[0] + crop = image_scaler.upscale(crop, 'lanczos', org_width, org_height, 'center')[0] + feather = crop.shape[2] // 8 + mask = torch.ones(1, crop.shape[1], crop.shape[2], crop.shape[3]) + for t in range(feather): + mask[:, t:t + 1, :] *= 1.0 / feather * (t + 1) + for t in range(feather): + mask[:, :, t:t + 1] *= 1.0 / feather * (t + 1) + for t in range(feather): + right_edge_start = crop.shape[2] - feather + t + mask[:, :, right_edge_start:right_edge_start + 1] *= 1.0 - 1.0 / feather * (t + 1) + for t in range(feather): + bottom_edge_start = crop.shape[1] - feather + t + mask[:, bottom_edge_start:bottom_edge_start + 1, :] *= 1.0 - 1.0 / feather * (t + 1) + crop = crop * mask + original_area = result[:, y:y + h, x:x + w] + inverse_mask = 1 - mask + original_area = original_area * inverse_mask + blended_face = original_area + crop + result[:, y:y + h, x:x + w] = blended_face + return (result,) +``` \ No newline at end of file diff --git a/docs/FaceKeypointsPreprocessor.md b/docs/FaceKeypointsPreprocessor.md new file mode 100644 index 0000000..317e4e1 --- /dev/null +++ b/docs/FaceKeypointsPreprocessor.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: FaceKeypointsPreprocessor +- Category: InstantID +- Output node: False +- Repo Ref: https://github.com/cubiq/ComfyUI_InstantID.git + +FaceKeypointsPreprocessor节点旨在通过预处理图像来提取和利用面部关键点,从而增强面部识别任务。该节点利用先进的面部分析技术来识别和处理面部特征,这对于提高后续面部识别模型的准确性和效率至关重要。通过专注于提取关键的面部点,该节点有助于更细致地理解面部结构,从而促进更有效的面部分析。 + +# Input types +## Required +- faceanalysis + - faceanalysis参数是必需的,因为它提供了图像预处理所需的面部分析模型及其相关特征。它在检测和提取面部关键点中发挥关键作用,直接影响预处理的有效性。 + - Comfy dtype: FACEANALYSIS + - Python dtype: InsightFaceModel +- image + - image参数是FaceKeypointsPreprocessor处理的输入图像。它是节点操作的基础,是提取面部关键点的来源。图像的质量和分辨率直接影响面部特征检测的准确性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Output types +- face_kps + - FaceKeypointsPreprocessor的输出,face_kps,是从输入图像中提取的面部关键点的表示。这些关键点非常重要,因为它们为后续的面部识别和分析任务提供了基础,使得面部特征的识别和理解更加精确。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FaceKeypointsPreprocessor: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'faceanalysis': ('FACEANALYSIS',), 'image': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'preprocess_image' + CATEGORY = 'InstantID' + + def preprocess_image(self, faceanalysis, image): + face_kps = extractFeatures(faceanalysis, image, extract_kps=True) + if face_kps is None: + face_kps = torch.zeros_like(image) + print(f'\x1b[33mWARNING: no face detected, unable to extract the keypoints!\x1b[0m') + return (face_kps,) +``` \ No newline at end of file diff --git a/docs/FaceParse(FaceParsing).md b/docs/FaceParse(FaceParsing).md new file mode 100644 index 0000000..97e3c20 --- /dev/null +++ b/docs/FaceParse(FaceParsing).md @@ -0,0 +1,69 @@ +# Documentation +- Class name: FaceParse +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +FaceParse节点旨在从输入的图像中分析和解析面部特征。它利用预训练的模型来识别和分割面部的各个元素,例如眼睛、鼻子和嘴巴。该节点的主要功能是将输入图像转换为详细的面部解析图,可用于进一步分析或可视化。这一过程增强了对面部结构的理解,对于面部表情识别或面部特征跟踪等应用非常有用。 + +# Input types +## Required +- model + - 模型参数对于FaceParse节点至关重要,因为它定义了用于面部解析的预训练神经网络架构。它是节点功能的基础,使得能够识别和分割面部特征。没有模型,节点无法执行其预期任务。 + - Comfy dtype: FACE_PARSING_MODEL + - Python dtype: torch.nn.Module +- processor + - 处理器参数对于预处理输入图像以兼容模型的格式至关重要。它确保图像格式正确,并为模型执行面部解析做好了准备。处理器是使模型能够有效处理输入的关键组件。 + - Comfy dtype: FACE_PARSING_PROCESSOR + - Python dtype: object +- image + - 图像参数是FaceParse节点的主要输入。它包含需要分析的面部图像。图像的质量和分辨率直接影响面部解析结果的准确性和细节程度。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- IMAGE + - 输出图像是面部解析结果的可视化,不同的面部特征用不同的颜色突出显示。这提供了对面部结构和模型预测准确性的直观理解。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- FACE_PARSING_RESULT + - 面部解析结果是输入图像的分割表示,其中每个像素都被分配一个对应特定面部特征的标签。这个输出对于进一步分析至关重要,可以用于各种应用,如面部表情分析或面部特征跟踪。 + - Comfy dtype: FACE_PARSING_RESULT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class FaceParse: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('FACE_PARSING_MODEL', {}), 'processor': ('FACE_PARSING_PROCESSOR', {}), 'image': ('IMAGE', {})}} + RETURN_TYPES = ('IMAGE', 'FACE_PARSING_RESULT') + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, model, processor, image: Tensor): + images = [] + results = [] + transform = T.ToPILImage() + colormap = cm.get_cmap('viridis', 19) + for item in image: + size = item.shape[:2] + inputs = processor(images=transform(item.permute(2, 0, 1)), return_tensors='pt') + outputs = model(**inputs) + logits = outputs.logits.cpu() + upsampled_logits = nn.functional.interpolate(logits, size=size, mode='bilinear', align_corners=False) + pred_seg = upsampled_logits.argmax(dim=1)[0] + pred_seg_np = pred_seg.detach().numpy().astype(np.uint8) + results.append(torch.tensor(pred_seg_np)) + colored = colormap(pred_seg_np) + colored_sliced = colored[:, :, :3] + images.append(torch.tensor(colored_sliced)) + return (torch.cat(images, dim=0).unsqueeze(0), torch.cat(results, dim=0).unsqueeze(0)) +``` \ No newline at end of file diff --git a/docs/FaceParsingModelLoader(FaceParsing).md b/docs/FaceParsingModelLoader(FaceParsing).md new file mode 100644 index 0000000..87e970e --- /dev/null +++ b/docs/FaceParsingModelLoader(FaceParsing).md @@ -0,0 +1,43 @@ +# Documentation +- Class name: FaceParsingModelLoader +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +FaceParsingModelLoader节点旨在高效加载并使用特定于面部解析任务的预训练语义分割模型。它抽象了模型初始化的复杂性,允许用户将面部解析功能无缝集成到他们的应用程序中。该节点确保模型被正确实例化并准备好进行推理,专注于促进高级面部特征提取,而不深入模型加载过程的细节。 + +# Input types +## Required +- face_parsing_path + - 参数'face_parsing_path'指定了预训练面部解析模型的文件路径。此路径至关重要,因为它指导节点加载正确的模型,从而启用后续的面部解析任务。该参数确保所使用的模型适用于预期的应用程序,从而影响面部解析操作的准确性和性能。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- FACE_PARSING_MODEL + - 'FACE_PARSING_MODEL'输出提供了已加载的预训练面部解析模型,适用于语义分割任务。此输出非常重要,因为它代表了面部特征提取的主要资产,允许对面部数据进行下游处理和分析。模型的输出确保用户可以访问一个强大的工具,用于解析和理解图像中的面部结构。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class FaceParsingModelLoader: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}} + RETURN_TYPES = ('FACE_PARSING_MODEL',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self): + from transformers import AutoModelForSemanticSegmentation + model = AutoModelForSemanticSegmentation.from_pretrained(face_parsing_path) + return (model,) +``` \ No newline at end of file diff --git a/docs/FaceParsingProcessorLoader(FaceParsing).md b/docs/FaceParsingProcessorLoader(FaceParsing).md new file mode 100644 index 0000000..2269c98 --- /dev/null +++ b/docs/FaceParsingProcessorLoader(FaceParsing).md @@ -0,0 +1,43 @@ +# Documentation +- Class name: FaceParsingProcessorLoader +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +FaceParsingProcessorLoader 是一个用于加载和初始化面部解析处理器的节点。它抽象了设置面部解析模型的复杂性,允许用户将面部解析功能无缝集成到他们的应用程序中,而无需深入了解底层模型架构或预处理步骤。 + +# Input types +## Required +- face_parsing_path + - face_parsing_path 参数对于 FaceParsingProcessorLoader 节点至关重要,因为它指定了加载面部解析处理器的位置。这个路径对于节点访问面部解析操作所需的模型文件和配置至关重要。 + - Comfy dtype: "str" + - Python dtype: str + +# Output types +- processor + - FaceParsingProcessorLoader 节点的输出是一个已初始化并准备好用于面部解析任务的处理器对象。这个处理器封装了面部解析模型所需的预处理图像的功能,使开发人员更容易使用这些模型。 + - Comfy dtype: SegformerImageProcessor + - Python dtype: transformers.SegformerImageProcessor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FaceParsingProcessorLoader: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}} + RETURN_TYPES = ('FACE_PARSING_PROCESSOR',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self): + from transformers import SegformerImageProcessor + processor = SegformerImageProcessor.from_pretrained(face_parsing_path) + return (processor,) +``` \ No newline at end of file diff --git a/docs/FaceParsingResultsParser(FaceParsing).md b/docs/FaceParsingResultsParser(FaceParsing).md new file mode 100644 index 0000000..038d685 --- /dev/null +++ b/docs/FaceParsingResultsParser(FaceParsing).md @@ -0,0 +1,161 @@ +# Documentation +- Class name: FaceParsingResultsParser +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +该节点类封装了解析和解释面部解析结果的逻辑,能够从输入数据中提取各种面部属性。它是面部分析任务流程中的核心组件,专注于不同面部特征的分割和识别。 + +# Input types +## Required +- result + - 结果参数至关重要,因为它包含了节点将要处理的原始面部解析数据。它是主要的输入,决定了后续操作和面部特征提取的准确性。 + - Comfy dtype: FACE_PARSING_RESULT + - Python dtype: torch.Tensor +## Optional +- background + - 该参数控制是否在解析过程中考虑背景分割。包含或排除背景可以显著影响整体面部掩码的组成和面部特征的清晰度。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- skin + - 皮肤参数对于识别面部区域的皮肤区域至关重要。它在隔离皮肤以进行进一步分析或处理(如皮肤状况评估)中发挥着至关重要的作用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- nose + - 通过启用或禁用鼻子参数,节点可以专注于鼻子区域,这对于基于特征的面部识别或美颜效果非常重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- eye_g + - eye_g参数用于包含或排除一般眼睛区域,这对于像目光追踪或眼镜推荐这样的任务很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- r_eye + - r_eye参数允许特定地包含或排除右眼,这对于详细的面部表情分析或不对称检测至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- l_eye + - 同样地,l_eye参数用于特定地包含或排除左眼,在面部分析中扮演与右眼参数相似的角色。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- r_brow + - r_brow参数用于右眉区域,这对于理解面部表情和情感分析很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- l_brow + - l_brow参数对应左眉区域,在传达面部表情和情感方面与右眉发挥类似作用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- r_ear + - r_ear参数用于右耳区域,对于一些音视频应用或助听器集成可能很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- l_ear + - l_ear参数对应左耳区域,在音视频应用中扮演与右耳相似的角色。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- mouth + - 嘴巴参数对于识别嘴巴区域至关重要,这对于像读唇或语音识别这样的任务非常重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- u_lip + - u_lip参数专注于上唇区域,这对于详细的面部表情分析和美容相关应用很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- l_lip + - l_lip参数用于下唇区域,在面部表情分析中扮演与上唇相似的角色。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- hair + - 头发参数用于包含或排除头发区域,这对于风格分析或头发相关产品推荐可能很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- hat + - 帽子参数允许特定地包含或排除帽子区域,这对于时尚分析或配饰推荐很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- ear_r + - ear_r参数用于右耳区域,对于助听器集成或耳部健康监测可能很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- neck_l + - neck_l参数对应左颈部区域,在姿势分析或服装适配推荐中可能很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- neck + - 脖子参数用于颈部区域,在姿势分析等任务中很重要,有助于整体身体语言的解释。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- cloth + - 衣服参数用于包含或排除服装区域,这对于时尚分析或虚拟试衣很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- MASK + - 输出掩码是一个二进制表示,根据输入参数分割和识别各种面部特征。它是进一步面部分析的关键输出,可用于多种应用,如面部表情识别、美容分析等。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FaceParsingResultsParser: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'result': ('FACE_PARSING_RESULT', {}), 'background': ('BOOLEAN', {'default': False}), 'skin': ('BOOLEAN', {'default': True}), 'nose': ('BOOLEAN', {'default': True}), 'eye_g': ('BOOLEAN', {'default': True}), 'r_eye': ('BOOLEAN', {'default': True}), 'l_eye': ('BOOLEAN', {'default': True}), 'r_brow': ('BOOLEAN', {'default': True}), 'l_brow': ('BOOLEAN', {'default': True}), 'r_ear': ('BOOLEAN', {'default': True}), 'l_ear': ('BOOLEAN', {'default': True}), 'mouth': ('BOOLEAN', {'default': True}), 'u_lip': ('BOOLEAN', {'default': True}), 'l_lip': ('BOOLEAN', {'default': True}), 'hair': ('BOOLEAN', {'default': True}), 'hat': ('BOOLEAN', {'default': True}), 'ear_r': ('BOOLEAN', {'default': True}), 'neck_l': ('BOOLEAN', {'default': True}), 'neck': ('BOOLEAN', {'default': True}), 'cloth': ('BOOLEAN', {'default': True})}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, result: Tensor, background: bool, skin: bool, nose: bool, eye_g: bool, r_eye: bool, l_eye: bool, r_brow: bool, l_brow: bool, r_ear: bool, l_ear: bool, mouth: bool, u_lip: bool, l_lip: bool, hair: bool, hat: bool, ear_r: bool, neck_l: bool, neck: bool, cloth: bool): + masks = [] + for item in result: + mask = torch.zeros(item.shape, dtype=torch.uint8) + if background: + mask = mask | torch.where(item == 0, 1, 0) + if skin: + mask = mask | torch.where(item == 1, 1, 0) + if nose: + mask = mask | torch.where(item == 2, 1, 0) + if eye_g: + mask = mask | torch.where(item == 3, 1, 0) + if r_eye: + mask = mask | torch.where(item == 4, 1, 0) + if l_eye: + mask = mask | torch.where(item == 5, 1, 0) + if r_brow: + mask = mask | torch.where(item == 6, 1, 0) + if l_brow: + mask = mask | torch.where(item == 7, 1, 0) + if r_ear: + mask = mask | torch.where(item == 8, 1, 0) + if l_ear: + mask = mask | torch.where(item == 9, 1, 0) + if mouth: + mask = mask | torch.where(item == 10, 1, 0) + if u_lip: + mask = mask | torch.where(item == 11, 1, 0) + if l_lip: + mask = mask | torch.where(item == 12, 1, 0) + if hair: + mask = mask | torch.where(item == 13, 1, 0) + if hat: + mask = mask | torch.where(item == 14, 1, 0) + if ear_r: + mask = mask | torch.where(item == 15, 1, 0) + if neck_l: + mask = mask | torch.where(item == 16, 1, 0) + if neck: + mask = mask | torch.where(item == 17, 1, 0) + if cloth: + mask = mask | torch.where(item == 18, 1, 0) + masks.append(mask.float()) + final = torch.cat(masks, dim=0).unsqueeze(0) + return (final,) +``` \ No newline at end of file diff --git a/docs/FaceRestoreCFWithModel.md b/docs/FaceRestoreCFWithModel.md new file mode 100644 index 0000000..edafe2e --- /dev/null +++ b/docs/FaceRestoreCFWithModel.md @@ -0,0 +1,96 @@ +# Documentation +- Class name: FaceRestoreCFWithModel +- Category: facerestore_cf +- Output node: False +- Repo Ref: https://github.com/mav-rik/facerestore_cf + +该节点旨在使用先进的深度学习模型提高和恢复面部图像的质量。它通过检测面孔、对齐以及应用恢复技术来处理输入图像,以提高整体清晰度和细节。该节点的主要目标是生成适合各种应用的高质量面部图像,如照片增强、身份验证和社交媒体分享。 + +# Input types +## Required +- facerestore_model + - 此参数指定用于面部恢复的深度学习模型。它对节点的运行至关重要,因为它决定了特定模型的能力以及恢复输出的质量。 + - Comfy dtype: string + - Python dtype: str +- image + - 将要应用面部恢复过程的输入图像。它是直接影响输出质量和恢复效果的主要数据输入。 + - Comfy dtype: image + - Python dtype: PIL.Image or numpy.ndarray +- facedetection + - 选择用于识别和定位输入图像中面部的面部检测模型。模型的选择影响面部检测的准确性和可靠性,进而影响后续的恢复过程。 + - Comfy dtype: combo + - Python dtype: str +## Optional +- codeformer_fidelity + - 调整恢复过程的保真度,其中较高的值表示更接近原始图像细节。此参数允许微调质量与计算效率之间的平衡。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- image + - 输出是经过处理以提高其质量和清晰度的恢复面部图像。这是节点操作的主要结果,代表了恢复过程的最终成果。 + - Comfy dtype: image + - Python dtype: PIL.Image or numpy.ndarray + +# Usage tips +- Infra type: GPU + +# Source code +``` +class FaceRestoreCFWithModel: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'facerestore_model': ('FACERESTORE_MODEL',), 'image': ('IMAGE',), 'facedetection': (['retinaface_resnet50', 'retinaface_mobile0.25', 'YOLOv5l', 'YOLOv5n'],), 'codeformer_fidelity': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1, 'step': 0.05})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'restore_face' + CATEGORY = 'facerestore_cf' + + def __init__(self): + self.face_helper = None + + def restore_face(self, facerestore_model, image, facedetection, codeformer_fidelity): + print(f'\tStarting restore_face with codeformer_fidelity: {codeformer_fidelity}') + device = model_management.get_torch_device() + facerestore_model.to(device) + if self.face_helper is None: + self.face_helper = FaceRestoreHelper(1, face_size=512, crop_ratio=(1, 1), det_model=facedetection, save_ext='png', use_parse=True, device=device) + image_np = 255.0 * image.cpu().numpy() + total_images = image_np.shape[0] + out_images = np.ndarray(shape=image_np.shape) + for i in range(total_images): + cur_image_np = image_np[i, :, :, ::-1] + original_resolution = cur_image_np.shape[0:2] + if facerestore_model is None or self.face_helper is None: + return image + self.face_helper.clean_all() + self.face_helper.read_image(cur_image_np) + self.face_helper.get_face_landmarks_5(only_center_face=False, resize=640, eye_dist_threshold=5) + self.face_helper.align_warp_face() + restored_face = None + for (idx, cropped_face) in enumerate(self.face_helper.cropped_faces): + cropped_face_t = img2tensor(cropped_face / 255.0, bgr2rgb=True, float32=True) + normalize(cropped_face_t, (0.5, 0.5, 0.5), (0.5, 0.5, 0.5), inplace=True) + cropped_face_t = cropped_face_t.unsqueeze(0).to(device) + try: + with torch.no_grad(): + output = facerestore_model(cropped_face_t, w=codeformer_fidelity)[0] + restored_face = tensor2img(output, rgb2bgr=True, min_max=(-1, 1)) + del output + torch.cuda.empty_cache() + except Exception as error: + print(f'\tFailed inference for CodeFormer: {error}', file=sys.stderr) + restored_face = tensor2img(cropped_face_t, rgb2bgr=True, min_max=(-1, 1)) + restored_face = restored_face.astype('uint8') + self.face_helper.add_restored_face(restored_face) + self.face_helper.get_inverse_affine(None) + restored_img = self.face_helper.paste_faces_to_input_image() + restored_img = restored_img[:, :, ::-1] + if original_resolution != restored_img.shape[0:2]: + restored_img = cv2.resize(restored_img, (0, 0), fx=original_resolution[1] / restored_img.shape[1], fy=original_resolution[0] / restored_img.shape[0], interpolation=cv2.INTER_LINEAR) + self.face_helper.clean_all() + out_images[i] = restored_img + restored_img_np = np.array(out_images).astype(np.float32) / 255.0 + restored_img_tensor = torch.from_numpy(restored_img_np) + return (restored_img_tensor,) +``` \ No newline at end of file diff --git a/docs/FaceRestoreModelLoader.md b/docs/FaceRestoreModelLoader.md new file mode 100644 index 0000000..72dfb64 --- /dev/null +++ b/docs/FaceRestoreModelLoader.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: FaceRestoreModelLoader +- Category: facerestore_cf +- Output node: False +- Repo Ref: https://github.com/mav-rik/facerestore_cf + +该节点旨在根据提供的模型名称加载和初始化面部恢复模型,确保适当的模型准备好用于面部恢复任务中的进一步处理。 + +# Input types +## Required +- model_name + - 模型名称参数至关重要,因为它指定了要加载的面部恢复模型的唯一标识符。它影响整个加载过程和模型的后续性能。 + - Comfy dtype: folder_paths.get_filename_list('facerestore_models') + - Python dtype: List[str] + +# Output types +- FACERESTORE_MODEL + - 输出是加载的面部恢复模型,对于执行高质量的面部恢复任务至关重要。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class FaceRestoreModelLoader: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model_name': (folder_paths.get_filename_list('facerestore_models'),)}} + RETURN_TYPES = ('FACERESTORE_MODEL',) + FUNCTION = 'load_model' + CATEGORY = 'facerestore_cf' + + def load_model(self, model_name): + if 'codeformer' in model_name.lower(): + print(f'\tLoading CodeFormer: {model_name}') + model_path = folder_paths.get_full_path('facerestore_models', model_name) + device = model_management.get_torch_device() + codeformer_net = ARCH_REGISTRY.get('CodeFormer')(dim_embd=512, codebook_size=1024, n_head=8, n_layers=9, connect_list=['32', '64', '128', '256']).to(device) + checkpoint = torch.load(model_path)['params_ema'] + codeformer_net.load_state_dict(checkpoint) + out = codeformer_net.eval() + return (out,) + else: + model_path = folder_paths.get_full_path('facerestore_models', model_name) + sd = comfy.utils.load_torch_file(model_path, safe_load=True) + out = model_loading.load_state_dict(sd).eval() + return (out,) +``` \ No newline at end of file diff --git a/docs/FaceToMask.md b/docs/FaceToMask.md new file mode 100644 index 0000000..53fd971 --- /dev/null +++ b/docs/FaceToMask.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: FaceToMask +- Category: ♾️Mixlab/Mask +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点使用图像处理技术从输入图像中识别和隔离面部特征,专注于绿色通道以创建突出显示检测到的面部的掩码。 + +# Input types +## Required +- image + - 输入图像对于节点的操作至关重要,因为它是提取面部特征和生成掩码的来源。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Output types +- MASK + - 输出掩码代表输入图像中的面部区域,使用绿色通道数据来指示面部的存在。 + - Comfy dtype: TENSOR + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FaceToMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',)}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Mask' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False,) + + def run(self, image): + im = tensor2pil(image) + mask = detect_faces(im) + mask = pil2tensor(mask) + channels = ['red', 'green', 'blue', 'alpha'] + mask = mask[:, :, :, channels.index('green')] + return (mask,) +``` \ No newline at end of file diff --git a/docs/FakeScribblePreprocessor_Provider_for_SEGS %2F%2FInspire.md b/docs/FakeScribblePreprocessor_Provider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..2a73d49 --- /dev/null +++ b/docs/FakeScribblePreprocessor_Provider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: FakeScribblePreprocessor_Provider_for_SEGS +- Category: Image Processing +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +FakeScribblePreprocessor_Provider_for_SEGS 节点旨在通过应用模拟涂鸦的预处理步骤来增强图像分割任务。该节点利用 HED(全卷积边缘检测)算法的能力来创建提示图像,这有助于分割过程。它特别适用于通过为分割模型提供额外的上下文信息来生成详细和清晰的分割图。 + +# Input types +## Required +- safe + - 'safty' 参数决定是否应该在应用预处理时采取安全措施,以防止潜在的数据损坏或丢失。这对于确保预处理阶段输入数据的完整性至关重要。 + - Comfy dtype: bool + - Python dtype: bool + +# Output types +- result + - FakeScribblePreprocessor_Provider_for_SEGS 节点的输出是经过预处理步骤的图像。这个图像可以直接用作分割模型的输入,增强模型产生准确分割的能力。 + - Comfy dtype: image + - Python dtype: PIL.Image or numpy.ndarray + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FakeScribblePreprocessor_Provider_for_SEGS(HEDPreprocessor_Provider_for_SEGS): + + def doit(self, safe): + obj = HED_Preprocessor_wrapper(safe, 'FakeScribblePreprocessor') + return (obj,) +``` \ No newline at end of file diff --git a/docs/FeatheredMask.md b/docs/FeatheredMask.md new file mode 100644 index 0000000..7b66134 --- /dev/null +++ b/docs/FeatheredMask.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: FeatheredMask +- Category: ♾️Mixlab/Mask +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +FeatheredMask 节点旨在通过应用羽化效果来处理和增强遮罩图像,使遮罩边缘与周围图像内容更自然、无缝地融合。该节点接受输入遮罩并对其进行细化,以创建更自然和无缝的混合效果。 + +# Input types +## Required +- mask + - ‘mask’参数是节点的主要输入,代表将被处理的图像遮罩。它在确定节点的最终输出中起着关键作用,因为羽化效果直接应用于此遮罩。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- start_offset + - ‘start_offset’参数控制从遮罩边缘开始羽化效果的初始距离。它很重要,因为它决定了平滑过渡的起始点,从而影响羽化遮罩的整体外观。 + - Comfy dtype: INT + - Python dtype: int +- feathering_weight + - ‘feathering_weight’参数调整羽化效果的强度。它很重要,因为它允许微调遮罩边缘的柔和度和混合度,确保结果在视觉上令人愉悦。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- masks + - ‘masks’输出包含已应用羽化效果的遮罩图像。它很重要,因为它代表了节点操作的最终产品,可供进一步使用或展示。 + - Comfy dtype: LIST[IMAGE] + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FeatheredMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'start_offset': ('INT', {'default': 1, 'min': -150, 'max': 150, 'step': 1, 'display': 'slider'}), 'feathering_weight': ('FLOAT', {'default': 0.1, 'min': 0.0, 'max': 1, 'step': 0.1, 'display': 'slider'})}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Mask' + OUTPUT_IS_LIST = (True,) + + def run(self, mask, start_offset, feathering_weight): + (num, _, _) = mask.size() + masks = [] + for i in range(num): + mm = mask[i] + image = tensor2pil(mm) + image = image.convert('L') + if start_offset > 0: + image = ImageOps.invert(image) + image_np = np.array(image) + edges = cv2.Canny(image_np, 30, 150) + for i in range(0, abs(start_offset)): + a = int(abs(start_offset) * 0.1 * i) + kernel = np.ones((a, a), np.uint8) + dilated_edges = cv2.dilate(edges, kernel, iterations=1) + smoothed_edges = cv2.GaussianBlur(dilated_edges, (5, 5), 0) + feathering_weight = max(0, min(feathering_weight, 1)) + image_np = cv2.addWeighted(image_np, 1, smoothed_edges, feathering_weight, feathering_weight) + result_image = Image.fromarray(np.uint8(image_np)) + result_image = result_image.convert('L') + if start_offset > 0: + result_image = ImageOps.invert(result_image) + result_image = result_image.convert('L') + mt = pil2tensor(result_image) + masks.append(mt) + return (masks,) +``` \ No newline at end of file diff --git a/docs/FileNamePrefix.md b/docs/FileNamePrefix.md new file mode 100644 index 0000000..98e20ab --- /dev/null +++ b/docs/FileNamePrefix.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: FileNamePrefix +- Category: Mikey/Meta +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +FileNamePrefix节点负责根据当前日期、自定义目录名称和自定义文本输入生成标准化的文件名前缀。它确保文件名是唯一的,并根据指定的标准进行组织,从而便于文件管理和检索。 + +# Input types +## Required +- date + - 参数'date'决定是否在文件名前缀中包含当前日期。它在按时间顺序组织文件和确保每个文件都有基于日期的唯一标识符中起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +- date_directory + - 参数'date_directory'指定是否根据当前日期创建目录。这对于维护一个按日期分类文件的层次化文件结构至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- custom_directory + - 参数'custom_directory'允许在文件名前缀中包含用户定义的目录名称。它在根据特定项目或用户需求组织文件方面提供了灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- custom_text + - 参数'custom_text'允许在文件名前缀中添加用户定义的文本字符串。这可以用来添加与文件内容相关的特定标签或标识符。 + - Comfy dtype: STRING + - Python dtype: str +- prompt + - 参数'prompt'用于通过附加元数据高级定制文件名前缀。当需要将动态元素纳入文件命名约定时,它特别有用。 + - Comfy dtype: PROMPT + - Python dtype: dict +- extra_pnginfo + - 参数'extra_pnginfo'提供补充信息,可用于进一步完善文件名前缀。它通常与'prompt'参数一起使用,以包含更详细的上下文数据。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: dict + +# Output types +- filename_prefix + - 'filename_prefix'输出是最终生成的前缀,它将所有输入参数组合成一个连贯且标准化的字符串。它是系统内使用的文件命名约定的基础。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FileNamePrefix: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'date': (['true', 'false'], {'default': 'true'}), 'date_directory': (['true', 'false'], {'default': 'true'}), 'custom_directory': ('STRING', {'default': ''}), 'custom_text': ('STRING', {'default': ''})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('filename_prefix',) + FUNCTION = 'get_filename_prefix' + CATEGORY = 'Mikey/Meta' + + def get_filename_prefix(self, date, date_directory, custom_directory, custom_text, prompt=None, extra_pnginfo=None): + filename_prefix = '' + if custom_directory: + custom_directory = search_and_replace(custom_directory, extra_pnginfo, prompt) + filename_prefix += custom_directory + '/' + if date_directory == 'true': + ts_str = datetime.datetime.now().strftime('%y%m%d') + filename_prefix += ts_str + '/' + if date == 'true': + ts_str = datetime.datetime.now().strftime('%y%m%d%H%M%S') + filename_prefix += ts_str + if custom_text != '': + custom_text = search_and_replace(custom_text, extra_pnginfo, prompt) + custom_text = re.sub('[<>:"/\\\\|?*]', '', custom_text) + filename_prefix += '_' + custom_text + return (filename_prefix,) +``` \ No newline at end of file diff --git a/docs/FileNamePrefixDateDirFirst.md b/docs/FileNamePrefixDateDirFirst.md new file mode 100644 index 0000000..283d319 --- /dev/null +++ b/docs/FileNamePrefixDateDirFirst.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: FileNamePrefixDateDirFirst +- Category: Mikey/Meta +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +FileNamePrefixDateDirFirst节点旨在根据当前日期和时间生成文件名前缀,并提供包含自定义目录和文本的选项。它提供了一种系统化的方法来命名文件,可以根据特定要求进行定制。 + +# Input types +## Required +- date + - 日期参数决定是否在文件名前缀中包含当前日期。它在确保生成的前缀反映所需的时间上下文方面起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +- date_directory + - date_directory参数控制是否应该在文件名前缀中加入以当前日期命名的目录。这对于将文件组织在基于日期的层级结构中至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- custom_directory + - 自定义目录参数允许在文件名前缀中包含用户定义的目录。它通过启用目录定制来增强节点的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- custom_text + - 自定义文本参数允许向文件名前缀中添加特定文本。它提供了一种将唯一标识符或描述性文本纳入前缀的方法。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- filename_prefix + - 文件名前缀输出提供了可以作为文件名一部分的生成前缀。它包含了输入参数指定的日期、目录和自定义文本元素。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FileNamePrefixDateDirFirst: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'date': (['true', 'false'], {'default': 'true'}), 'date_directory': (['true', 'false'], {'default': 'true'}), 'custom_directory': ('STRING', {'default': ''}), 'custom_text': ('STRING', {'default': ''})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('filename_prefix',) + FUNCTION = 'get_filename_prefix' + CATEGORY = 'Mikey/Meta' + + def get_filename_prefix(self, date, date_directory, custom_directory, custom_text, prompt=None, extra_pnginfo=None): + filename_prefix = '' + if date_directory == 'true': + ts_str = datetime.datetime.now().strftime('%y%m%d') + filename_prefix += ts_str + '/' + if custom_directory: + custom_directory = search_and_replace(custom_directory, extra_pnginfo, prompt) + filename_prefix += custom_directory + '/' + if date == 'true': + ts_str = datetime.datetime.now().strftime('%y%m%d%H%M%S') + filename_prefix += ts_str + if custom_text != '': + custom_text = search_and_replace(custom_text, extra_pnginfo, prompt) + custom_text = re.sub('[<>:"/\\\\|?*]', '', custom_text) + filename_prefix += '_' + custom_text + return (filename_prefix,) +``` \ No newline at end of file diff --git a/docs/FilmGrain.md b/docs/FilmGrain.md new file mode 100644 index 0000000..0a97520 --- /dev/null +++ b/docs/FilmGrain.md @@ -0,0 +1,129 @@ +# Documentation +- Class name: FilmGrain +- Category: postprocessing/Effects +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +FilmGrain节点向图像中引入随机噪声模式,模拟胶片颗粒的纹理。这一过程通过增加深度和纹理感,增强了视觉美学效果,常用于艺术性和风格化的后期处理。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它是将要应用电影颗粒效果的基础媒体。它决定了输出的视觉质量,是整个操作的基础。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- intensity + - 强度控制应用于图像的噪声的大小。它影响颗粒效果的显著性,较高的值会导致更明显的颗粒图案。 + - Comfy dtype: FLOAT + - Python dtype: float +- scale + - 比例调整噪声图案相对于图像的大小。较大的比例会导致更明显的噪声特征,这可以为电影颗粒外观增添更戏剧性的效果。 + - Comfy dtype: FLOAT + - Python dtype: float +- temperature + - 温度调整图像的颜色平衡,为最终输出增加温暖或凉爽感。这个参数可以微妙地改变图像的情绪和整体感觉。 + - Comfy dtype: FLOAT + - Python dtype: float +- vignette + - 晕影控制图像边缘褪色的强度,创造出更集中和戏剧性的视觉效果。它可以引导观众的注意力向图像中心。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output_image + - 输出图像是应用电影颗粒效果后的结果,包括调整过的强度、比例、温度和晕影参数。它代表了节点的最终创意输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FilmGrain: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'intensity': ('FLOAT', {'default': 0.2, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'scale': ('FLOAT', {'default': 10, 'min': 1, 'max': 100, 'step': 1}), 'temperature': ('FLOAT', {'default': 0.0, 'min': -100, 'max': 100, 'step': 1}), 'vignette': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 10.0, 'step': 1.0})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'film_grain' + CATEGORY = 'postprocessing/Effects' + + def film_grain(self, image: torch.Tensor, intensity: float, scale: float, temperature: float, vignette: float): + (batch_size, height, width, _) = image.shape + result = torch.zeros_like(image) + for b in range(batch_size): + tensor_image = image[b].numpy() + noise = self.generate_perlin_noise((height, width), scale) + noise = (noise - np.min(noise)) / (np.max(noise) - np.min(noise)) + noise = (noise * 2 - 1) * intensity + grain_image = np.clip(tensor_image + noise[:, :, np.newaxis], 0, 1) + grain_image = self.apply_temperature(grain_image, temperature) + grain_image = self.apply_vignette(grain_image, vignette) + tensor = torch.from_numpy(grain_image).unsqueeze(0) + result[b] = tensor + return (result,) + + def generate_perlin_noise(self, shape, scale, octaves=4, persistence=0.5, lacunarity=2): + + def smoothstep(t): + return t * t * (3.0 - 2.0 * t) + + def lerp(t, a, b): + return a + t * (b - a) + + def gradient(h, x, y): + vectors = np.array([[1, 1], [-1, 1], [1, -1], [-1, -1]]) + g = vectors[h % 4] + return g[:, :, 0] * x + g[:, :, 1] * y + (height, width) = shape + noise = np.zeros(shape) + for octave in range(octaves): + octave_scale = scale * lacunarity ** octave + x = np.linspace(0, 1, width, endpoint=False) + y = np.linspace(0, 1, height, endpoint=False) + (X, Y) = np.meshgrid(x, y) + (X, Y) = (X * octave_scale, Y * octave_scale) + xi = X.astype(int) + yi = Y.astype(int) + xf = X - xi + yf = Y - yi + u = smoothstep(xf) + v = smoothstep(yf) + n00 = gradient(np.random.randint(0, 4, (height, width)), xf, yf) + n01 = gradient(np.random.randint(0, 4, (height, width)), xf, yf - 1) + n10 = gradient(np.random.randint(0, 4, (height, width)), xf - 1, yf) + n11 = gradient(np.random.randint(0, 4, (height, width)), xf - 1, yf - 1) + x1 = lerp(u, n00, n10) + x2 = lerp(u, n01, n11) + y1 = lerp(v, x1, x2) + noise += y1 * persistence ** octave + return noise / (1 - persistence ** octaves) + + def apply_temperature(self, image, temperature): + if temperature == 0: + return image + temperature /= 100 + new_image = image.copy() + if temperature > 0: + new_image[:, :, 0] *= 1 + temperature + new_image[:, :, 1] *= 1 + temperature * 0.4 + else: + new_image[:, :, 2] *= 1 - temperature + return np.clip(new_image, 0, 1) + + def apply_vignette(self, image, vignette_strength): + if vignette_strength == 0: + return image + (height, width, _) = image.shape + x = np.linspace(-1, 1, width) + y = np.linspace(-1, 1, height) + (X, Y) = np.meshgrid(x, y) + radius = np.sqrt(X ** 2 + Y ** 2) + mapped_vignette_strength = 1.8 - (vignette_strength - 1) * 0.1 + vignette = 1 - np.clip(radius / mapped_vignette_strength, 0, 1) + return np.clip(image * vignette[..., np.newaxis], 0, 1) +``` \ No newline at end of file diff --git a/docs/Filter Z (mtb).md b/docs/Filter Z (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/FilterSchedule.md b/docs/FilterSchedule.md new file mode 100644 index 0000000..3738764 --- /dev/null +++ b/docs/FilterSchedule.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: FilterSchedule +- Category: promptcontrol +- Output node: False +- Repo Ref: https://github.com/asagi4/comfyui-prompt-control.git + +FilterSchedule类提供了一种根据指定条件细化和缩小一组提示的方法,提高了选择过程的精确性,并确保输出与期望的参数一致。 + +# Input types +## Required +- prompt_schedule + - prompt_schedule参数是必要的,它定义了将要被过滤的提示的基本集。它是过滤过程的起点,决定了将要进行精炼选择的内容池。 + - Comfy dtype: PROMPT_SCHEDULE + - Python dtype: +## Optional +- tags + - tags参数作为一个过滤器,允许用户指定用于缩小提示选择的特定关键词。它在将输出引向更有针对性的内容集方面发挥着至关重要的作用。 + - Comfy dtype: STRING + - Python dtype: str +- start + - start参数用于定义选择提示的范围的开始。它与end参数一起工作,限制选择过程,确保只考虑指定范围内的提示。 + - Comfy dtype: FLOAT + - Python dtype: float +- end + - end参数与start参数一起使用,设置了可以选择的提示范围的上限。它通过专注于内容的特定子集来进一步细化输出。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- filtered_prompt_schedule + - 输出filtered_prompt_schedule是将过滤条件应用于原始提示计划的结果。它代表了一组经过精炼且更符合用户指定偏好的提示。 + - Comfy dtype: PROMPT_SCHEDULE + - Python dtype: + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FilterSchedule: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompt_schedule': ('PROMPT_SCHEDULE',)}, 'optional': {'tags': ('STRING', {'default': ''}), 'start': ('FLOAT', {'min': 0.0, 'max': 1.0, 'default': 0.0, 'step': 0.01}), 'end': ('FLOAT', {'min': 0.0, 'max': 1.0, 'default': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('PROMPT_SCHEDULE',) + CATEGORY = 'promptcontrol' + FUNCTION = 'apply' + + def apply(self, prompt_schedule, tags='', start=0.0, end=1.0): + p = prompt_schedule.with_filters(tags, start=start, end=end) + log.debug(f'Filtered {prompt_schedule.parsed_prompt} with: ({tags}, {start}, {end}); the result is %s', p.parsed_prompt) + return (p,) +``` \ No newline at end of file diff --git a/docs/Fit Number (mtb).md b/docs/Fit Number (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/FizzFrame.md b/docs/FizzFrame.md new file mode 100644 index 0000000..f096006 --- /dev/null +++ b/docs/FizzFrame.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: NodeFrame +- Category: FizzNodes 📅🅕🅝/FrameNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +NodeFrame 类旨在管理和创建结构化数据流中的框架。它便于将文本输入与现有框架集成,生成包含正面和负面文本情感的新框架。该节点在通过系统塑造数据的叙述流程中发挥关键作用,通过结合和对比不同的文本视角。 + +# Input types +## Required +- frame + - ‘frame’参数至关重要,因为它标识了节点将操作的数据结构中的具体框架。它确保了正确框架被定位以进行操作或数据检索,从而维护了数据流的完整性和顺序。 + - Comfy dtype: INT + - Python dtype: int +- previous_frame + - ‘previous_frame’参数是必需的,因为它提供了前一个框架的上下文,节点用它来构建。这是一个强制性输入,确保了框架创建过程中的连续性和一致性。 + - Comfy dtype: FIZZFRAME + - Python dtype: NodeFrame +- positive_text + - ‘positive_text’参数是引入正面情感至框架创建过程中的关键元素。它允许表达乐观或肯定的观点,以建设性的角度丰富叙述。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- negative_text + - ‘negative_text’参数虽然是可选的,但它用于引入对比观点到框架中,通过在正面情感旁边包含潜在的批评或缺点,提供一种平衡的视角。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- FIZZFRAME + - 输出 'FIZZFRAME' 表示新创建的框架,它包含了集成的正面和负面文本情感。这是一个重要的输出,因为它为后续的数据处理和分析奠定了基础。 + - Comfy dtype: FIZZFRAME + - Python dtype: NodeFrame +- CONDITIONING + - ‘CONDITIONING’输出提供了正面和负面文本的编码表示,这对于系统内进一步处理至关重要。这些调节输出允许根据文本输入对数据进行操作和细化。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Union[torch.Tensor, Dict[str, torch.Tensor]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class NodeFrame: + + def __init__(self): + self.frames = {} + self.thisFrame = {} + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'frame': ('INT', {'default': 0, 'min': 0}), 'previous_frame': ('FIZZFRAME', {'forceInput': True}), 'positive_text': ('STRING', {'multiline': True})}, 'optional': {'negative_text': ('STRING', {'multiline': True})}} + RETURN_TYPES = ('FIZZFRAME', 'CONDITIONING', 'CONDITIONING') + FUNCTION = 'create_frame' + CATEGORY = 'FizzNodes 📅🅕🅝/FrameNodes' + + def create_frame(self, frame, previous_frame, positive_text, negative_text=None): + self.frames = previous_frame.frames + prev_frame = previous_frame.thisFrame + new_positive_text = f"{positive_text}, {prev_frame['general_positive']}" + new_negative_text = f"{negative_text}, {prev_frame['general_negative']}" + pos_tokens = prev_frame['clip'].tokenize(new_positive_text) + (pos_cond, pos_pooled) = prev_frame['clip'].encode_from_tokens(pos_tokens, return_pooled=True) + neg_tokens = prev_frame['clip'].tokenize(new_negative_text) + (neg_cond, neg_pooled) = prev_frame['clip'].encode_from_tokens(neg_tokens, return_pooled=True) + new_frame = {'positive_text': positive_text, 'negative_text': negative_text, 'general_positive': prev_frame['general_positive'], 'general_negative': prev_frame['general_negative'], 'clip': prev_frame['clip'], 'pos_conditioning': {'cond': pos_cond, 'pooled': pos_pooled}, 'neg_conditioning': {'cond': neg_cond, 'pooled': neg_pooled}} + self.thisFrame = new_frame + self.frames[frame] = new_frame + return (self, [[pos_cond, {'pooled_output': pos_pooled}]], [[neg_cond, {'pooled_output': neg_pooled}]]) +``` \ No newline at end of file diff --git a/docs/FizzFrameConcatenate.md b/docs/FizzFrameConcatenate.md new file mode 100644 index 0000000..3dfa5d9 --- /dev/null +++ b/docs/FizzFrameConcatenate.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: FrameConcatenate +- Category: FizzNodes 📅🅕🅝/FrameNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +FrameConcatenate 是一个旨在将帧数据合并为单一字符串表示的节点。它接受一个结构化的帧对象作为输入,并将每个帧数字关联的正面和负面文本串联起来,创建一个全面的文本摘要。这个节点在将复杂的帧数据转换为可读格式以进行进一步分析或展示中发挥着关键作用。 + +# Input types +## Required +- frame + - ‘frame’参数对于FrameConcatenate节点至关重要,因为它作为主要输入,包含需要被串联的框架数据。节点依赖此参数来生成所需的输出,使其成为节点功能的基本组成部分。 + - Comfy dtype: FIZZFRAME + - Python dtype: A custom object that contains frame data structured in a specific way, expected to be compatible with the Fizz framework. + +# Output types +- text_list + - ‘text_list’输出是一个字符串,代表串联起来的帧数据。它是节点处理的结果,包含了与每个帧数字关联的正面和负面文本。这个输出很重要,因为它提供了一个格式化的摘要,可以很容易地用于后续任务。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FrameConcatenate: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'frame': ('FIZZFRAME', {'forceInput': True})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'frame_concatenate' + CATEGORY = 'FizzNodes 📅🅕🅝/FrameNodes' + + def frame_concatenate(self, frame): + text_list = '' + for frame_digit in frame.frames: + new_frame = frame.frames[frame_digit] + text_list += f'''"{frame_digit}": "{new_frame['positive_text']}''' + if new_frame.get('general_positive'): + text_list += f", {new_frame['general_positive']}" + if new_frame.get('negative_text') or new_frame.get('general_negative'): + text_list += f', --neg ' + if new_frame.get('negative_text'): + text_list += f", {new_frame['negative_text']}" + if new_frame.get('general_negative'): + text_list += f", {new_frame['general_negative']}" + text_list += f'",\n' + text_list = text_list[:-2] + return (text_list,) +``` \ No newline at end of file diff --git a/docs/FlipSigmasAdjusted.md b/docs/FlipSigmasAdjusted.md new file mode 100644 index 0000000..d83b37a --- /dev/null +++ b/docs/FlipSigmasAdjusted.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: FlipSigmasAdjusted +- Category: KJNodes/noise +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +‘FlipSigmasAdjusted’节点旨在处理和调整一组西格玛值。它翻转输入西格玛的顺序,可选地通过最后一个西格玛值进行除法操作,并根据偏移量和指定的除数调整每个西格玛。该节点还确保没有西格玛值变为零,如果必要,将用一个最小的正值代替。结果是一组转换后的西格玛值,以及用于可视化目的的字符串表示。 + +# Input types +## Required +- sigmas + - ‘sigmas’参数是表示噪声分布标准差的值序列。它对节点的操作至关重要,因为它决定了要被操作的基础数据。翻转和调整过程直接影响节点执行的结果。 + - Comfy dtype: FLOAT + - Python dtype: torch.Tensor +## Optional +- divide_by_last_sigma + - ‘divide_by_last_sigma’参数是一个布尔标志,当设置为真时,会导致节点将序列中的每个西格玛除以最后一个西格玛。这个操作归一化了西格玛值,在某些噪声减少或图像处理任务中可能非常重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- divide_by + - ‘divide_by’参数是一个浮点数,用于缩放调整后的西格玛值。它在控制西格玛调整的大小方面起着关键作用,特别是当为特定应用微调节点输出时尤为重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- offset_by + - ‘offset_by’参数是一个整数,它将每个西格玛的索引移动给定的数量。这可以向西格玛序列引入一种变换或扭曲,这对于某些类型的数据分析或信号处理可能是有用的。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- SIGMAS + - ‘SIGMAS’输出提供了节点应用所有操作后的调整西格玛值。对于依赖这些转换值的后续处理步骤来说,这是一个关键的输出。 + - Comfy dtype: FLOAT + - Python dtype: torch.Tensor +- sigmas_string + - ‘sigmas_string’输出是调整后的西格玛值的字符串表示。它对于可视化或记录目的很有用,提供了数据的人类可读格式。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FlipSigmasAdjusted: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'sigmas': ('SIGMAS',), 'divide_by_last_sigma': ('BOOLEAN', {'default': False}), 'divide_by': ('FLOAT', {'default': 1, 'min': 1, 'max': 255, 'step': 0.01}), 'offset_by': ('INT', {'default': 1, 'min': -100, 'max': 100, 'step': 1})}} + RETURN_TYPES = ('SIGMAS', 'STRING') + RETURN_NAMES = ('SIGMAS', 'sigmas_string') + CATEGORY = 'KJNodes/noise' + FUNCTION = 'get_sigmas_adjusted' + + def get_sigmas_adjusted(self, sigmas, divide_by_last_sigma, divide_by, offset_by): + sigmas = sigmas.flip(0) + if sigmas[0] == 0: + sigmas[0] = 0.0001 + adjusted_sigmas = sigmas.clone() + for i in range(1, len(sigmas)): + offset_index = i - offset_by + if 0 <= offset_index < len(sigmas): + adjusted_sigmas[i] = sigmas[offset_index] + else: + adjusted_sigmas[i] = 0.0001 + if adjusted_sigmas[0] == 0: + adjusted_sigmas[0] = 0.0001 + if divide_by_last_sigma: + adjusted_sigmas = adjusted_sigmas / adjusted_sigmas[-1] + sigma_np_array = adjusted_sigmas.numpy() + array_string = np.array2string(sigma_np_array, precision=2, separator=', ', threshold=np.inf) + adjusted_sigmas = adjusted_sigmas / divide_by + return (adjusted_sigmas, array_string) +``` \ No newline at end of file diff --git a/docs/Float To Floats (mtb).md b/docs/Float To Floats (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Float To Number (mtb).md b/docs/Float To Number (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Float to String.md b/docs/Float to String.md new file mode 100644 index 0000000..1a83d62 --- /dev/null +++ b/docs/Float to String.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: FLOATtoSTRING +- Category: Mikey/Utils +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +FLOATtoSTRING节点旨在将浮点数转换为字符串表示形式。它提供了格式化数字的功能,可以选择是否使用逗号,这在显示数字数据时非常有用,可以使数据更易于阅读。 + +# Input types +## Required +- float_ + - 'float_'参数是需要被转换为字符串的浮点数。它在节点的操作中扮演着关键角色,因为它是转换过程的主要输入。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- use_commas + - 'use_commas'参数决定输出的字符串是否应该包含作为千位分隔符的逗号。这可以提高数字的可读性,特别是对于较大的数值。 + - Comfy dtype: COMBO['true', 'false'] + - Python dtype: str + +# Output types +- STRING + - FLOATtoSTRING节点的输出是输入浮点数的字符串表示。字符串的格式受'use_commas'参数的影响,如果设置为'true',则可以包含作为千位分隔符的逗号。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FLOATtoSTRING: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'float_': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1000000.0}), 'use_commas': (['true', 'false'], {'default': 'false'})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'convert' + CATEGORY = 'Mikey/Utils' + + def convert(self, float_, use_commas): + if use_commas == 'true': + return (f'{float_:,}',) + else: + return (f'{float_}',) +``` \ No newline at end of file diff --git a/docs/FloatConstant.md b/docs/FloatConstant.md new file mode 100644 index 0000000..3bebed9 --- /dev/null +++ b/docs/FloatConstant.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: FloatConstant +- Category: KJNodes/constants +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +FloatConstant节点旨在数据处理或机器学习流程中提供一个常量浮点数值。它确保一个一致且预定义的数值可用于后续操作,有助于系统性能的稳定性和可预测性。 + +# Input types +## Required +- value + - 参数'value'是FloatConstant节点的核心,定义了将被输出的特定浮点数。它在节点的操作中起着关键作用,因为它直接影响节点的结果,无需进一步计算。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- value + - 输出'value'代表了FloatConstant节点提供的常量浮点数。它很重要,因为它作为工作流中下游过程的可靠和不变的输入。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FloatConstant: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'value': ('FLOAT', {'default': 0.0, 'min': -18446744073709551615, 'max': 18446744073709551615, 'step': 0.001})}} + RETURN_TYPES = ('FLOAT',) + RETURN_NAMES = ('value',) + FUNCTION = 'get_value' + CATEGORY = 'KJNodes/constants' + + def get_value(self, value): + return (value,) +``` \ No newline at end of file diff --git a/docs/FloatRange %2F%2FInspire.md b/docs/FloatRange %2F%2FInspire.md new file mode 100644 index 0000000..83eb465 --- /dev/null +++ b/docs/FloatRange %2F%2FInspire.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: FloatRange +- Category: InspirePack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点在指定范围内生成一系列浮点数,根据用户定义的参数调整间隔,以便于进行各种数学和计算任务。 + +# Input types +## Required +- start + - 序列的起始值。它设置了节点开始生成数字的初始点,这对于定义序列的下界至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- stop + - 序列的结束值。它标记了范围的上限,决定了节点何时应停止生成数字。 + - Comfy dtype: FLOAT + - Python dtype: float +- step + - 序列中每个数字之间的增量。它决定了间距,并且对于控制范围内生成数字的密度至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- limit + - 生成的最大值数量。它限制了总输出,确保序列不会超过预定义的长度。 + - Comfy dtype: INT + - Python dtype: int +- ensure_end + - 一个标志,指示是否在序列中包括结束值。如果启用,它通过确保序列包括指定的停止值来影响最终输出。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- sequence + - 在指定范围内生成的浮点数字列表,代表节点操作的输出。 + - Comfy dtype: FLOAT + - Python dtype: List[float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FloatRange: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'start': ('FLOAT', {'default': 0.0, 'min': -100.0, 'max': 100.0, 'step': 1e-09}), 'stop': ('FLOAT', {'default': 1.0, 'min': -100.0, 'max': 100.0, 'step': 1e-09}), 'step': ('FLOAT', {'default': 0.01, 'min': 0.0, 'max': 100.0, 'step': 1e-09}), 'limit': ('INT', {'default': 100, 'min': 2, 'max': 4096, 'step': 1}), 'ensure_end': ('BOOLEAN', {'default': True, 'label_on': 'enable', 'label_off': 'disable'})}} + RETURN_TYPES = ('FLOAT',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Util' + + def doit(self, start, stop, step, limit, ensure_end): + if start >= stop or step == 0: + return ([start],) + res = [] + x = start + last = x + while x <= stop and limit > 0: + res.append(x) + last = x + limit -= 1 + x += step + if ensure_end and last != stop: + if len(res) >= limit: + res.pop() + res.append(stop) + return (res,) +``` \ No newline at end of file diff --git a/docs/FloatSlider.md b/docs/FloatSlider.md new file mode 100644 index 0000000..ff8a724 --- /dev/null +++ b/docs/FloatSlider.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: FloatSlider +- Category: ♾️Mixlab/Utils +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +FloatSlider节点旨在将给定的数字规范化到指定的范围内,确保它落在最小值和最大值之间。它将输入数字缩放到一个标准刻度上,提供可以用于各种计算上下文中的归一化值,其中相对位置至关重要。 + +# Input types +## Required +- number + - 参数'number'表示要在指定范围内归一化的值。它至关重要,因为它直接影响节点的输出,决定了归一化数字在标准刻度上的位置。 + - Comfy dtype: FLOAT + - Python dtype: float +- min_value + - 参数'min_value'定义了归一化数字的范围的下限。它在确保输出值受到期望限制内起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- max_value + - 参数'max_value'设置归一化范围的上限。它在缩放输入数字以确保不超过指定的最大值方面至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- step + - 参数'step'用于控制数字归一化的粒度。它影响数字在范围内的调整方式,影响归一化值的精度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- scaled_number + - 输出'scaled_number'表示输入数字的归一化值,缩放到适合指定范围内。它很重要,因为它提供了一个可以用于进一步分析或处理的标准度量。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FloatSlider: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'number': ('FLOAT', {'default': 0, 'min': 0, 'max': 18446744073709551615, 'step': 0.001, 'display': 'slider'}), 'min_value': ('FLOAT', {'default': 0, 'min': -18446744073709551615, 'max': 18446744073709551615, 'step': 0.001, 'display': 'number'}), 'max_value': ('FLOAT', {'default': 1, 'min': -18446744073709551615, 'max': 18446744073709551615, 'step': 0.001, 'display': 'number'}), 'step': ('FLOAT', {'default': 0.001, 'min': -18446744073709551615, 'max': 18446744073709551615, 'step': 0.001, 'display': 'number'})}} + RETURN_TYPES = ('FLOAT',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Utils' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False,) + + def run(self, number, min_value, max_value, step): + if number < min_value: + number = min_value + elif number > max_value: + number = max_value + scaled_number = (number - min_value) / (max_value - min_value) + return (scaled_number,) +``` \ No newline at end of file diff --git a/docs/Floats To Float (mtb).md b/docs/Floats To Float (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Floats To Ints (mtb).md b/docs/Floats To Ints (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Font.md b/docs/Font.md new file mode 100644 index 0000000..0544f78 --- /dev/null +++ b/docs/Font.md @@ -0,0 +1,40 @@ +# Documentation +- Class name: FontInput +- Category: ♾️Mixlab/Utils +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点根据指定的字体名称检索字体文件,为在各种图形或文本处理任务中访问和使用字体提供了一种简化的方法。 + +# Input types +## Required +- font + - ‘font’参数至关重要,因为它标识了系统中要使用的具体字体。它直接影响节点的操作和结果输出,确保将正确的字体应用到当前任务中。 + - Comfy dtype: list + - Python dtype: list + +# Output types +- font_file + - 输出‘font_file’代表与输入字体参数相关的检索到的字体文件,这对于应用程序中进一步的图形或文本处理至关重要。 + - Comfy dtype: list + - Python dtype: list + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FontInput: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'font': (list(font_files.keys()),)}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Utils' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False,) + + def run(self, font): + return (font_files[font],) +``` \ No newline at end of file diff --git a/docs/FooocusPromptExpansion.md b/docs/FooocusPromptExpansion.md new file mode 100644 index 0000000..12e97d9 --- /dev/null +++ b/docs/FooocusPromptExpansion.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: FooocusPromptExpansion +- Category: prompt +- Output node: True +- Repo Ref: https://github.com/esheep/esheep_custom_nodes.git + +该节点旨在根据输入文本和种子值扩展和生成新文本,种子值引入了随机性,旨在增强生成内容的多样性和创造性,同时通过种子值保持一定程度的可控性。 + +# Input types +## Required +- text + - 文本参数是节点文本扩展过程的源材料。它至关重要,因为它为新内容的生成提供了上下文和基础。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- seed + - 种子参数为文本扩展过程引入随机性,允许从相同的输入文本生成多样化的输出。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result + - 结果参数包含扩展后的文本,是节点文本扩展过程的输出。 + - Comfy dtype: STRING + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FooocusPromptExpansion: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'main' + CATEGORY = 'prompt' + OUTPUT_IS_LIST = (True,) + OUTPUT_NODE = True + + @staticmethod + def scale_seed(seed): + return seed % (2 ** 32 - 1) + + def main(self, text, seed): + seed = FooocusPromptExpansion.scale_seed(seed) + res = do_expansion(text, seed) + logger.info(f'[FooocusPromptExpansion] (seed={seed}) expand |{text}| to |{res}|') + return {'ui': {'result': [res]}, 'result': ([res],)} +``` \ No newline at end of file diff --git a/docs/FreeU (Advanced).md b/docs/FreeU (Advanced).md new file mode 100644 index 0000000..bf15366 --- /dev/null +++ b/docs/FreeU (Advanced).md @@ -0,0 +1,151 @@ +# Documentation +- Class name: WAS_FreeU +- Category: _for_testing +- Output node: False +- Repo Ref: https://github.com/WASasquatch/FreeU_Advanced + +WAS_FreeU类包含一种旨在通过应用打补丁技术来修改和增强模型行为的方法。该方法称为'patch',旨在根据预定义的参数和模式改进模型的性能或调整其输出特征。该节点的功能集中在操纵模型的内部表示上,允许对模型优化采取更细致和针对性的方法。 + +# Input types +## Required +- model + - 模型参数是必需的,因为它定义了将要应用打补丁过程的基础结构和权重。它是主要的输入,其特征和性能将由节点的操作所改变。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- target_block + - target_block参数决定了打补丁操作将集中在模型的哪一部分。它在确定节点所做的修改的范围和影响方面至关重要。 + - Comfy dtype: COMBO[output_block, middle_block, input_block, all] + - Python dtype: str +- multiscale_mode + - multiscale_mode参数影响打补丁过程的复杂性和粒度。它在节点如何调整其行为以适应模型特征的不同尺度方面发挥着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- multiscale_strength + - 这个参数控制多尺度打补丁的强度。它很重要,因为它直接影响节点在不同尺度上修改模型特征的程度。 + - Comfy dtype: FLOAT + - Python dtype: float +- slice_b1 + - slice_b1参数指定了打补丁过程中第一片的大小。它是确定将受到修改的模型部分的一个关键因素。 + - Comfy dtype: INT + - Python dtype: int +- slice_b2 + - 这个参数定义了打补丁中涉及的第二片的大小。它与slice_b1一起工作,以建立节点将针对的模型特征范围。 + - Comfy dtype: INT + - Python dtype: int +- b1 + - b1参数用于调整打补丁过程中第一片的影响。它很重要,因为它允许节点控制应用于模型特征的修改的程度。 + - Comfy dtype: FLOAT + - Python dtype: float +- b2 + - 这个参数负责在打补丁过程中调整第二片的影响。它在塑造节点如何在指定范围内改变模型特征方面至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- s1 + - s1参数对于设置第一个过滤操作的规模至关重要。它决定了节点如何根据其重要性强调或抑制模型的某些特征。 + - Comfy dtype: FLOAT + - Python dtype: float +- s2 + - 这个参数决定了第二个过滤操作的规模。它在微调节点在目标范围内改进模型特征的能力方面发挥关键作用。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- b1_mode + - b1_mode参数规定了第一片的混合模式。它对于定义打补丁操作如何将修改集成到模型现有特征中很重要。 + - Comfy dtype: COMBO[add, subtract, multiply, divide, average, max, min] + - Python dtype: str +- b1_blend + - 这个参数调整第一片的混合强度。它很重要,因为它允许节点控制原始特征和修改后特征之间过渡的平滑度。 + - Comfy dtype: FLOAT + - Python dtype: float +- b2_mode + - b2_mode参数设置了第二片的混合模式。它对于确定节点如何将修补的特征与模型的其余部分协调一致至关重要。 + - Comfy dtype: COMBO[add, subtract, multiply, divide, average, max, min] + - Python dtype: str +- b2_blend + - 这个参数微调第二片的混合强度。它在确保节点无缝地将修改集成到模型现有结构中方面至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- threshold + - 阈值参数用于定义过滤操作的兴趣区域。它对于集中节点的注意力在模型的特定特征上很重要。 + - Comfy dtype: INT + - Python dtype: int +- use_override_scales + - use_override_scales参数允许对傅里叶滤波器进行自定义缩放。它很重要,因为它提供了节点根据特定需求调整过滤过程的灵活性。 + - Comfy dtype: COMBO[false, true] + - Python dtype: str +- override_scales + - 这个参数提供了一种手动指定傅里叶滤波器的比例值的方法。它对于将用户定义的过滤标准应用于模型的特征很重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- MODEL + - 输出是应用了打补丁操作的修改后的模型。它代表了输入模型的增强或变更版本,反映了节点所做的更改。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WAS_FreeU: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'target_block': (['output_block', 'middle_block', 'input_block', 'all'],), 'multiscale_mode': (list(mscales.keys()),), 'multiscale_strength': ('FLOAT', {'default': 1.0, 'max': 1.0, 'min': 0, 'step': 0.001}), 'slice_b1': ('INT', {'default': 640, 'min': 64, 'max': 1280, 'step': 1}), 'slice_b2': ('INT', {'default': 320, 'min': 64, 'max': 640, 'step': 1}), 'b1': ('FLOAT', {'default': 1.1, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'b2': ('FLOAT', {'default': 1.2, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 's1': ('FLOAT', {'default': 0.9, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 's2': ('FLOAT', {'default': 0.2, 'min': 0.0, 'max': 10.0, 'step': 0.001})}, 'optional': {'b1_mode': (list(blending_modes.keys()),), 'b1_blend': ('FLOAT', {'default': 1.0, 'max': 100, 'min': 0, 'step': 0.001}), 'b2_mode': (list(blending_modes.keys()),), 'b2_blend': ('FLOAT', {'default': 1.0, 'max': 100, 'min': 0, 'step': 0.001}), 'threshold': ('INT', {'default': 1.0, 'max': 10, 'min': 1, 'step': 1}), 'use_override_scales': (['false', 'true'],), 'override_scales': ('STRING', {'default': '# OVERRIDE SCALES\n\n# Sharpen\n# 10, 1.5', 'multiline': True})}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'patch' + CATEGORY = '_for_testing' + + def patch(self, model, target_block, multiscale_mode, multiscale_strength, slice_b1, slice_b2, b1, b2, s1, s2, b1_mode='add', b1_blend=1.0, b2_mode='add', b2_blend=1.0, threshold=1.0, use_override_scales='false', override_scales=''): + min_slice = 64 + max_slice_b1 = 1280 + max_slice_b2 = 640 + slice_b1 = max(min(max_slice_b1, slice_b1), min_slice) + slice_b2 = max(min(min(slice_b1, max_slice_b2), slice_b2), min_slice) + scales_list = [] + if use_override_scales == 'true': + if override_scales.strip() != '': + scales_str = override_scales.strip().splitlines() + for line in scales_str: + if not line.strip().startswith('#') and (not line.strip().startswith('!')) and (not line.strip().startswith('//')): + scale_values = line.split(',') + if len(scale_values) == 2: + scales_list.append((int(scale_values[0]), float(scale_values[1]))) + if use_override_scales == 'true' and (not scales_list): + print('No valid override scales found. Using default scale.') + scales_list = None + scales = mscales[multiscale_mode] if use_override_scales == 'false' else scales_list + print(f'FreeU Plate Portions: {slice_b1} over {slice_b2}') + print(f'FreeU Multi-Scales: {scales}') + + def block_patch(h, transformer_options): + if h.shape[1] == 1280: + h_t = h[:, :slice_b1] + h_r = h_t * b1 + h[:, :slice_b1] = blending_modes[b1_mode](h_t, h_r, b1_blend) + if h.shape[1] == 640: + h_t = h[:, :slice_b2] + h_r = h_t * b2 + h[:, :slice_b2] = blending_modes[b2_mode](h_t, h_r, b2_blend) + return h + + def block_patch_hsp(h, hsp, transformer_options): + if h.shape[1] == 1280: + h = block_patch(h, transformer_options) + hsp = Fourier_filter(hsp, threshold=threshold, scale=s1, scales=scales, strength=multiscale_strength) + if h.shape[1] == 640: + h = block_patch(h, transformer_options) + hsp = Fourier_filter(hsp, threshold=threshold, scale=s2, scales=scales, strength=multiscale_strength) + return (h, hsp) + print(f'Patching {target_block}') + m = model.clone() + if target_block == 'all' or target_block == 'output_block': + m.set_model_output_block_patch(block_patch_hsp) + if target_block == 'all' or target_block == 'input_block': + m.set_model_input_block_patch(block_patch) + if target_block == 'all' or target_block == 'middle_block': + m.set_model_patch(block_patch, 'middle_block_patch') + return (m,) +``` \ No newline at end of file diff --git a/docs/FreeU_V2 (Advanced).md b/docs/FreeU_V2 (Advanced).md new file mode 100644 index 0000000..644f95a --- /dev/null +++ b/docs/FreeU_V2 (Advanced).md @@ -0,0 +1,149 @@ +# Documentation +- Class name: WAS_FreeU_V2 +- Category: _for_testing +- Output node: False +- Repo Ref: https://github.com/WASasquatch/FreeU_Advanced + +这个节点类旨在对模型的块应用打补丁机制,通过提供的参数调整输入、中间或输出块,以增强模型的性能。它专注于通过多尺度调整和切片技术来精炼模型的内部表示。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了将被补丁过程修改的神经网络结构。它是节点操作的主要对象,其特征直接影响补丁结果。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- multiscale_mode + - multiscale_mode参数对于定义补丁过程中使用的多尺度方法至关重要。它影响模型特征在不同尺度上的调整方式,这对于微调模型的性能至关重要。 + - Comfy dtype: LIST + - Python dtype: list +- multiscale_strength + - multiscale_strength参数控制多尺度调整的强度。它是决定补丁过程的有效性以及结果模型对各种数据尺度的适应性的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- slice_b1 + - slice_b1参数定义了模型隐藏层第一个维度中要调整的切片的大小。它对于将补丁工作集中在模型的特定区域很重要,从而优化其内部特征提取机制。 + - Comfy dtype: INT + - Python dtype: int +- slice_b2 + - slice_b2参数设置了模型隐藏层第二个维度的切片大小。这个参数在通过针对层内特定特征空间来精炼模型的表现能力方面具有重要意义。 + - Comfy dtype: INT + - Python dtype: int +- b1 + - b1参数影响应用于隐藏层第一个维度的缩放因子。它是控制应用于模型内部特征的转换程度的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- b2 + - b2参数决定了隐藏层第二个维度的缩放因子。调整这个参数可以对模型捕获和处理此维度内的特征的能力产生重大影响。 + - Comfy dtype: FLOAT + - Python dtype: float +- s1 + - s1参数设置了补丁过程中应用的傅里叶滤波器第一个维度的阈值。它在过滤不相关的频率和仅保留最相关特征方面起着关键作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- s2 + - s2参数定义了傅里叶滤波器第二个维度的阈值。通过调整这个参数,可以控制模型在数据表示中保留的细节水平。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- input_block + - input_block参数决定是否应将补丁应用于模型的输入块。它在数据处理的初始阶段起着关键作用,并且可以显著影响补丁后模型的整体性能。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- middle_block + - middle_block参数指定是否应将补丁应用于模型的中间层。这些层对模型的学习过程至关重要,它们的调整可以提高模型的表现能力。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- output_block + - output_block参数指示是否应将补丁目标定位于模型的输出块。修改这个块可以直接影响模型预测的质量和准确性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- threshold + - 阈值参数用于确定傅里叶滤波器的敏感度。更高的阈值可以导致更激进的过滤,可能会去除更多的噪声,但也可能丢弃重要信息。 + - Comfy dtype: INT + - Python dtype: int +- use_override_scales + - use_override_scales参数允许应用自定义的缩放值,而不是默认值。这提供了灵活性,可以根据特定要求或实验设置来定制补丁过程。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- override_scales + - 当use_override_scales设置为true时,override_scales参数包含一个自定义缩放值的字符串,用于覆盖默认值。它允许用户在特定数据特征下对模型的响应进行微调,这对于细粒度调整非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- model + - 补丁化的模型是节点的主要输出,代表了应用了修改的神经网络。这个输出非常重要,因为它体现了补丁后模型的增强能力和调整后的内部机制。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WAS_FreeU_V2: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'input_block': ('BOOLEAN', {'default': False}), 'middle_block': ('BOOLEAN', {'default': False}), 'output_block': ('BOOLEAN', {'default': False}), 'multiscale_mode': (list(mscales.keys()),), 'multiscale_strength': ('FLOAT', {'default': 1.0, 'max': 1.0, 'min': 0, 'step': 0.001}), 'slice_b1': ('INT', {'default': 640, 'min': 64, 'max': 1280, 'step': 1}), 'slice_b2': ('INT', {'default': 320, 'min': 64, 'max': 640, 'step': 1}), 'b1': ('FLOAT', {'default': 1.1, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'b2': ('FLOAT', {'default': 1.2, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 's1': ('FLOAT', {'default': 0.9, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 's2': ('FLOAT', {'default': 0.2, 'min': 0.0, 'max': 10.0, 'step': 0.001})}, 'optional': {'threshold': ('INT', {'default': 1.0, 'max': 10, 'min': 1, 'step': 1}), 'use_override_scales': (['false', 'true'],), 'override_scales': ('STRING', {'default': '# OVERRIDE SCALES\n\n# Sharpen\n# 10, 1.5', 'multiline': True})}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'patch' + CATEGORY = '_for_testing' + + def patch(self, model, input_block, middle_block, output_block, multiscale_mode, multiscale_strength, slice_b1, slice_b2, b1, b2, s1, s2, threshold=1.0, use_override_scales='false', override_scales=''): + min_slice = 64 + max_slice_b1 = 1280 + max_slice_b2 = 640 + slice_b1 = max(min(max_slice_b1, slice_b1), min_slice) + slice_b2 = max(min(min(slice_b1, max_slice_b2), slice_b2), min_slice) + scales_list = [] + if use_override_scales == 'true': + if override_scales.strip() != '': + scales_str = override_scales.strip().splitlines() + for line in scales_str: + if not line.strip().startswith('#') and (not line.strip().startswith('!')) and (not line.strip().startswith('//')): + scale_values = line.split(',') + if len(scale_values) == 2: + scales_list.append((int(scale_values[0]), float(scale_values[1]))) + if use_override_scales == 'true' and (not scales_list): + print('No valid override scales found. Using default scale.') + scales_list = None + scales = mscales[multiscale_mode] if use_override_scales == 'false' else scales_list + + def _hidden_mean(h): + hidden_mean = h.mean(1).unsqueeze(1) + B = hidden_mean.shape[0] + (hidden_max, _) = torch.max(hidden_mean.view(B, -1), dim=-1, keepdim=True) + (hidden_min, _) = torch.min(hidden_mean.view(B, -1), dim=-1, keepdim=True) + hidden_mean = (hidden_mean - hidden_min.unsqueeze(2).unsqueeze(3)) / (hidden_max - hidden_min).unsqueeze(2).unsqueeze(3) + return hidden_mean + + def block_patch(h, transformer_options): + if h.shape[1] == 1280: + hidden_mean = _hidden_mean(h) + h[:, :slice_b1] = h[:, :slice_b1] * ((b1 - 1) * hidden_mean + 1) + if h.shape[1] == 640: + hidden_mean = _hidden_mean(h) + h[:, :slice_b2] = h[:, :slice_b2] * ((b2 - 1) * hidden_mean + 1) + return h + + def block_patch_hsp(h, hsp, transformer_options): + if h.shape[1] == 1280: + h = block_patch(h, transformer_options) + hsp = Fourier_filter(hsp, threshold=threshold, scale=s1, scales=scales, strength=multiscale_strength) + if h.shape[1] == 640: + h = block_patch(h, transformer_options) + hsp = Fourier_filter(hsp, threshold=threshold, scale=s2, scales=scales, strength=multiscale_strength) + return (h, hsp) + m = model.clone() + if output_block: + print('Patching output block') + m.set_model_output_block_patch(block_patch_hsp) + if input_block: + print('Patching input block') + m.set_model_input_block_patch(block_patch) + if middle_block: + print('Patching middle block') + m.set_model_patch(block_patch, 'middle_block_patch') + return (m,) +``` \ No newline at end of file diff --git a/docs/FromBasicPipe.md b/docs/FromBasicPipe.md new file mode 100644 index 0000000..46e6e98 --- /dev/null +++ b/docs/FromBasicPipe.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: FromBasicPipe +- Category: ImpactPack/Pipe +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +FromBasicPipe 节点的 'doit' 方法是数据处理管道中的关键通道,负责提取和组织模型、剪辑和变分自编码器(VAE)等核心元素。它确保必要的数据结构被高效地检索和准备,以便在工作流程中无缝集成不同的数据组件。 + +# Input types +## Required +- basic_pipe + - 'basic_pipe' 参数对于 'doit' 方法至关重要,因为它包含了节点操作所需的基础数据结构。它作为一个通道,通过它模型、剪辑和 VAE 组件被引导,突出了它在使节点有效运行中的关键作用。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, Any, Any, Any, Any] + +# Output types +- model + - 'model' 输出表示节点数据处理框架中的关键组件,代表对节点功能至关重要的机器学习模型。它在塑造节点对工作流程的整体贡献中起着重要作用,强调了其在数据管道中的重要性。 + - Comfy dtype: MODEL + - Python dtype: Any +- clip + - 'clip' 输出代表了对节点操作至关重要的数据片段。它用于提取和操作信息的特定部分,强调了它在节点有效处理和管理数据能力中的重要性。 + - Comfy dtype: CLIP + - Python dtype: Any +- vae + - 'vae' 输出表示节点架构中存在变分自编码器,是编码和解码数据表示的关键组件。它的包含对于节点转换和解释复杂数据结构的能力至关重要。 + - Comfy dtype: VAE + - Python dtype: Any +- positive + - 'positive' 输出表明了一个用于引导节点处理逻辑的条件因素。它在引导节点生成期望结果方面扮演着重要角色,突出了它在节点操作中的战略重要性。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- negative + - 'negative' 输出代表了对节点决策过程至关重要的相反条件因素。它在定义节点操作的边界并确保节点的执行与预期目标一致方面至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FromBasicPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'basic_pipe': ('BASIC_PIPE',)}} + RETURN_TYPES = ('MODEL', 'CLIP', 'VAE', 'CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('model', 'clip', 'vae', 'positive', 'negative') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Pipe' + + def doit(self, basic_pipe): + (model, clip, vae, positive, negative) = basic_pipe + return (model, clip, vae, positive, negative) +``` \ No newline at end of file diff --git a/docs/FromBasicPipe_v2.md b/docs/FromBasicPipe_v2.md new file mode 100644 index 0000000..7bdb904 --- /dev/null +++ b/docs/FromBasicPipe_v2.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: FromBasicPipe_v2 +- Category: ImpactPack/Pipe +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +FromBasicPipe_v2节点的'doit'方法旨在从给定的基本管道中处理并返回结构化输出。它封装了ImpactPack中数据流的精髓,确保了模型、剪辑和VAE等必要组件为下游任务准备就绪。 + +# Input types +## Required +- basic_pipe + - ‘basic_pipe’参数是节点的关键输入,因为它代表了包含处理所必需的基本元素的基础管道。它对节点的执行至关重要,并直接影响操作的结果。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, ...] + +# Output types +- basic_pipe + - ‘basic_pipe’输出是输入的反映,标志着节点操作中成功处理和保留基础管道。它是依赖于初始数据结构完整性的后续任务的关键组件。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, ...] +- model + - ‘model’输出表示从基础管道派生的机器学习模型,对于系统内的预测分析和决策过程至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - ‘clip’输出代表了一个可能涉及数据特征操作或提取的组件,在节点的整体功能中扮演着重要角色。 + - Comfy dtype: CLIP + - Python dtype: Any +- vae + - ‘vae’输出标志着节点中存在变分自编码器,这对于涉及无监督学习和数据降维的任务至关重要。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- positive + - ‘positive’输出表明了一个正向调节因素,可能用于指导或影响节点内后续过程的行为。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- negative + - ‘negative’输出对应于一个负向调节因素,这在控制或修改后续操作的方向上可能至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FromBasicPipe_v2: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'basic_pipe': ('BASIC_PIPE',)}} + RETURN_TYPES = ('BASIC_PIPE', 'MODEL', 'CLIP', 'VAE', 'CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('basic_pipe', 'model', 'clip', 'vae', 'positive', 'negative') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Pipe' + + def doit(self, basic_pipe): + (model, clip, vae, positive, negative) = basic_pipe + return (basic_pipe, model, clip, vae, positive, negative) +``` \ No newline at end of file diff --git a/docs/FromDetailerPipe.md b/docs/FromDetailerPipe.md new file mode 100644 index 0000000..2a72c8b --- /dev/null +++ b/docs/FromDetailerPipe.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: FromDetailerPipe +- Category: ImpactPack/Pipe +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +FromDetailerPipe节点的'doit'方法旨在编排从细节化管道中提取和组织各种组件。它作为将模型、剪辑和检测器等不同元素集成到冲击分析工作流程后续阶段的管道。 + +# Input types +## Required +- detailer_pipe + - 参数'detailer_pipe'是必需的,因为它提供了包含节点工作所需所有组件的输入管道。它是节点提取模型、剪辑和其他相关数据以进行进一步处理的主要来源。 + - Comfy dtype: DETAILER_PIPE + - Python dtype: Tuple[Any, ...] + +# Output types +- model + - 'model'输出代表管道内使用的计算模型的核心,它在数据分析和处理中起着关键作用。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - 'clip'输出是生成和操作视觉表示的关键组件,通常与模型一起用于特征提取。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- vae + - 'vae'输出表示变分自编码器模型,它对于涉及数据表示编码和解码的任务至关重要。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- positive + - 'positive'输出作为条件数据的一种形式,对后续模型或算法的行为产生积极影响。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative + - 'negative'输出与'positive'输出类似,但提供的条件数据对模型的行为产生负面影响。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- bbox_detector + - 'bbox_detector'输出负责识别和定位图像内的兴趣区域,通常用于目标检测任务。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: torch.nn.Module +- sam_model_opt + - 'sam_model_opt'输出指的是一个可选的场景感知模型,它可以用于更复杂的场景分析和理解。 + - Comfy dtype: SAM_MODEL + - Python dtype: Optional[torch.nn.Module] +- segm_detector_opt + - 'segm_detector_opt'输出是图像分割的可选组件,有助于需要详细图像分析的任务。 + - Comfy dtype: SEGM_DETECTOR + - Python dtype: Optional[torch.nn.Module] +- detailer_hook + - 'detailer_hook'输出是一个额外的钩子,可用于扩展或定制节点的功能以适应特定用例。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FromDetailerPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'detailer_pipe': ('DETAILER_PIPE',)}} + RETURN_TYPES = ('MODEL', 'CLIP', 'VAE', 'CONDITIONING', 'CONDITIONING', 'BBOX_DETECTOR', 'SAM_MODEL', 'SEGM_DETECTOR', 'DETAILER_HOOK') + RETURN_NAMES = ('model', 'clip', 'vae', 'positive', 'negative', 'bbox_detector', 'sam_model_opt', 'segm_detector_opt', 'detailer_hook') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Pipe' + + def doit(self, detailer_pipe): + (model, clip, vae, positive, negative, wildcard, bbox_detector, segm_detector_opt, sam_model_opt, detailer_hook, _, _, _, _) = detailer_pipe + return (model, clip, vae, positive, negative, bbox_detector, sam_model_opt, segm_detector_opt, detailer_hook) +``` \ No newline at end of file diff --git a/docs/FromDetailerPipeSDXL.md b/docs/FromDetailerPipeSDXL.md new file mode 100644 index 0000000..29c2c4b --- /dev/null +++ b/docs/FromDetailerPipeSDXL.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: FromDetailerPipe_SDXL +- Category: ImpactPack/Pipe +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +FromDetailerPipe_SDXL 节点的 'doit' 方法旨在通过从 detailer pipe 中解包和组织各种组件(如模型、条件器和检测器)来编排处理管道。它在 ImpactPack 框架内的数据和功能流程中发挥关键作用,确保不同模块之间的无缝集成。 + +# Input types +## Required +- detailer_pipe + - 参数 'detailer_pipe' 是必需的,因为它作为节点接收其操作所需组件的结构化集合的通道。它是主要输入,决定了节点的执行路径和随后的输出。 + - Comfy dtype: DETAILER_PIPE + - Python dtype: Tuple[DETAILER_PIPE, MODEL, CLIP, VAE, CONDITIONING, CONDITIONING, BBOX_DETECTOR, SAM_MODEL, SEGM_DETECTOR, DETAILER_HOOK] + +# Output types +- detailer_pipe + - 输出 'detailer_pipe' 是由节点处理和组织的结构化组件集合。它很重要,因为它构成了管道后续阶段进一步处理的基础。 + - Comfy dtype: DETAILER_PIPE + - Python dtype: DETAILER_PIPE +- model + - 输出 'model' 表示节点处理管道中使用的一个机器学习模型。对于需要预测分析或模式识别的任务来说,它是一个关键组件。 + - Comfy dtype: MODEL + - Python dtype: MODEL +- clip + - 输出 'clip' 是一个可能涉及文本或图像处理的组件,有助于节点处理和解释上下文数据的能力。 + - Comfy dtype: CLIP + - Python dtype: CLIP +- vae + - 输出 'vae' 代表变分自编码器,这是一种用于无监督学习任务的神经网络类型。它在节点生成或重建数据的能力中起着重要作用。 + - Comfy dtype: VAE + - Python dtype: VAE +- bbox_detector + - 输出 'bbox_detector' 是一个负责在图像或视频中检测边界框的模块。对于需要空间定位对象或感兴趣区域的应用来说,它非常重要。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: BBOX_DETECTOR +- sam_model_opt + - 输出 'sam_model_opt' 是场景注意力模型的优化版本,它增强了节点专注于并处理数据中特定区域的能力。 + - Comfy dtype: SAM_MODEL + - Python dtype: SAM_MODEL +- segm_detector_opt + - 输出 'segm_detector_opt' 是一个优化的分割检测器,对于涉及识别和分离图像内不同区域的任务至关重要。 + - Comfy dtype: SEGM_DETECTOR + - Python dtype: SEGM_DETECTOR +- detailer_hook + - 输出 'detailer_hook' 是一种机制,允许定制或扩展节点的功能,提供处理特定用例的灵活性。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: DETAILER_HOOK +- refiner_model + - 输出 'refiner_model' 是另一个机器学习模型,可能用于完善或增强节点工作流程中主模型的输出。 + - Comfy dtype: MODEL + - Python dtype: MODEL + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FromDetailerPipe_SDXL: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'detailer_pipe': ('DETAILER_PIPE',)}} + RETURN_TYPES = ('DETAILER_PIPE', 'MODEL', 'CLIP', 'VAE', 'CONDITIONING', 'CONDITIONING', 'BBOX_DETECTOR', 'SAM_MODEL', 'SEGM_DETECTOR', 'DETAILER_HOOK', 'MODEL', 'CLIP', 'CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('detailer_pipe', 'model', 'clip', 'vae', 'positive', 'negative', 'bbox_detector', 'sam_model_opt', 'segm_detector_opt', 'detailer_hook', 'refiner_model', 'refiner_clip', 'refiner_positive', 'refiner_negative') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Pipe' + + def doit(self, detailer_pipe): + (model, clip, vae, positive, negative, wildcard, bbox_detector, segm_detector_opt, sam_model_opt, detailer_hook, refiner_model, refiner_clip, refiner_positive, refiner_negative) = detailer_pipe + return (detailer_pipe, model, clip, vae, positive, negative, bbox_detector, sam_model_opt, segm_detector_opt, detailer_hook, refiner_model, refiner_clip, refiner_positive, refiner_negative) +``` \ No newline at end of file diff --git a/docs/FromDetailerPipe_v2.md b/docs/FromDetailerPipe_v2.md new file mode 100644 index 0000000..8eaf60d --- /dev/null +++ b/docs/FromDetailerPipe_v2.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: FromDetailerPipe_v2 +- Category: ImpactPack/Pipe +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +FromDetailerPipe_v2节点旨在协调复杂处理管道中的信息和资源流动。它作为模型、检测器和钩子等各个组件的通道,确保它们在系统中得到适当的集成和利用。该节点在简化操作和提高管道整体效率方面发挥着关键作用。 + +# Input types +## Required +- detailer_pipe + - detailer_pipe参数至关重要,因为它封装了节点操作所需的核心组件。它作为一个管道,向节点提供必要的数据和配置以进行处理。有效处理此参数对于节点有效运作并实现其预期目的至关重要。 + - Comfy dtype: DETAILER_PIPE + - Python dtype: Tuple[Any, ...] + +# Output types +- detailer_pipe + - 输出的detailer_pipe是一个关键元素,它封装了处理后的数据和配置,准备传递给管道的后续阶段。它代表了节点处理的成果,对于保持工作流程的连续性和完整性至关重要。 + - Comfy dtype: DETAILER_PIPE + - Python dtype: Tuple[Any, ...] +- model + - 模型输出表示管道中使用的机器学习或统计模型。它是一个基本组件,为系统的分析能力做出贡献,允许根据输入数据进行预测、分类或其他推断。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - clip输出表示已提取用于特定分析或处理的数据片段或部分。它是节点操作中的一个重要元素,通常用于需要完整数据子集的专注任务。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- vae + - vae输出指的是变分自编码器,这是一种能够学习和将数据编码成低维表示的神经网络类型。它通过提供压缩和解压缩信息的有效手段,在节点的功能中扮演着重要角色。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- positive + - positive输出表示影响节点处理的一组正面条件或因素。它用于引导节点在系统中生成或识别期望的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative + - negative输出表示在节点操作期间考虑的一组负面条件或因素。它通过提供与正面条件的对比,有助于完善节点的决策过程。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- bbox_detector + - bbox_detector输出负责识别和定位图像或数据集中的兴趣区域。它是需要对象检测或空间感知的任务的关键组件。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: torch.nn.Module +- sam_model_opt + - sam_model_opt输出指的是样本模型的可选实例,可能用于管道内采样或生成数据点。它通过允许结合采样技术,为节点的能力增加了灵活性。 + - Comfy dtype: SAM_MODEL + - Python dtype: Optional[torch.nn.Module] +- segm_detector_opt + - segm_detector_opt输出是一个可选组件,专门用于将图像或数据的部分进行分割以进行进一步分析。它通过启用对视觉或结构化数据的更细粒度处理,增强了节点的功能。 + - Comfy dtype: SEGM_DETECTOR + - Python dtype: Optional[torch.nn.Module] +- detailer_hook + - detailer_hook输出是一个可定制的钩子,允许将额外的功能或扩展集成到节点中。它提供了一种方法,可以根据特定的用例或要求定制节点的行为。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: Callable[..., Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FromDetailerPipe_v2: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'detailer_pipe': ('DETAILER_PIPE',)}} + RETURN_TYPES = ('DETAILER_PIPE', 'MODEL', 'CLIP', 'VAE', 'CONDITIONING', 'CONDITIONING', 'BBOX_DETECTOR', 'SAM_MODEL', 'SEGM_DETECTOR', 'DETAILER_HOOK') + RETURN_NAMES = ('detailer_pipe', 'model', 'clip', 'vae', 'positive', 'negative', 'bbox_detector', 'sam_model_opt', 'segm_detector_opt', 'detailer_hook') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Pipe' + + def doit(self, detailer_pipe): + (model, clip, vae, positive, negative, wildcard, bbox_detector, segm_detector_opt, sam_model_opt, detailer_hook, _, _, _, _) = detailer_pipe + return (detailer_pipe, model, clip, vae, positive, negative, bbox_detector, sam_model_opt, segm_detector_opt, detailer_hook) +``` \ No newline at end of file diff --git a/docs/FromIPAdapterPipe %2F%2FInspire.md b/docs/FromIPAdapterPipe %2F%2FInspire.md new file mode 100644 index 0000000..ddffe70 --- /dev/null +++ b/docs/FromIPAdapterPipe %2F%2FInspire.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: FromIPAdapterPipe +- Category: InspirePack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点负责协调各种组件的集成过程,如IP适配器、机器学习模型和面部识别系统,以简化给定管道中的数据管理和分析。 + +# Input types +## Required +- ipadapter_pipe + - 该参数是必要的,因为它作为主要输入,包含了节点将处理和用于其操作的一系列互联元素。 + - Comfy dtype: IPADAPTER_PIPE + - Python dtype: Tuple[IPADAPTER_PIPE] + +# Output types +- ipadapter + - 输出的关键组件,IP适配器促进系统内的通信,确保数据在不同模块之间有效传输。 + - Comfy dtype: IPADAPTER + - Python dtype: IPADAPTER +- model + - 模型输出代表了机器学习组件,这对于根据学习到的模式进行预测和数据处理至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip_vision + - 该输出对于视觉数据解释非常重要,因为它利用视觉系统来分析和理解图像内容。 + - Comfy dtype: CLIP_VISION + - Python dtype: CLIP_VISION +- insight_face + - 洞察面部输出在面部识别任务中至关重要,提供了根据面部特征识别和验证个人身份的手段。 + - Comfy dtype: INSIGHTFACE + - Python dtype: INSIGHTFACE + +# Usage tips +- Infra type: CPU + +# Source code +``` +class FromIPAdapterPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ipadapter_pipe': ('IPADAPTER_PIPE',)}} + RETURN_TYPES = ('IPADAPTER', 'MODEL', 'CLIP_VISION', 'INSIGHTFACE') + RETURN_NAMES = ('ipadapter', 'model', 'clip_vision', 'insight_face') + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Util' + + def doit(self, ipadapter_pipe): + (ipadapter, model, clip_vision, insightface, _) = ipadapter_pipe + return (ipadapter, model, clip_vision, insightface) +``` \ No newline at end of file diff --git a/docs/GMFSS Fortuna VFI.md b/docs/GMFSS Fortuna VFI.md new file mode 100644 index 0000000..adbbb65 --- /dev/null +++ b/docs/GMFSS Fortuna VFI.md @@ -0,0 +1,85 @@ +# Documentation +- Class name: GMFSS_Fortuna_VFI +- Category: ComfyUI-Frame-Interpolation/VFI +- Output node: False +- Repo Ref: https://github.com/Fannovel16/ComfyUI-Frame-Interpolation + +GMFSS_Fortuna_VFI节点旨在使用深度学习模型执行视频帧插值。它接收输入视频帧,并通过在现有帧之间生成额外的帧来提高帧率,从而创建更平滑的过渡和更高质量的视频输出。 + +# Input types +## Required +- ckpt_name + - 检查点名称至关重要,因为它决定了用于帧插值过程的特定模型权重和架构。它影响插值帧的质量和风格。 + - Comfy dtype: str + - Python dtype: str +- frames + - 输入视频帧是插值所需的主要数据。它们被处理以生成中间帧,这对于实现所需的视频增强至关重要。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +## Optional +- clear_cache_after_n_frames + - 此参数决定了在处理过程中CUDA缓存被清除的频率,以防止内存溢出。它在内存使用和处理时间之间进行平衡。 + - Comfy dtype: int + - Python dtype: int +- multiplier + - 乘数决定了在每对输入帧之间生成多少帧。乘数越高,输出帧率越高。 + - Comfy dtype: int + - Python dtype: int +- optional_interpolation_states + - 这个可选参数允许对插值过程进行自定义控制,例如跳过某些帧或应用特定的插值技术。 + - Comfy dtype: InterpolationStateList + - Python dtype: InterpolationStateList + +# Output types +- output_frames + - output_frames参数包含插值后的视频帧。这些帧是帧插值过程的结果,代表了增强后的视频序列。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class GMFSS_Fortuna_VFI: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (list(CKPTS_PATH_CONFIG.keys()),), 'frames': ('IMAGE',), 'clear_cache_after_n_frames': ('INT', {'default': 10, 'min': 1, 'max': 1000}), 'multiplier': ('INT', {'default': 2, 'min': 2, 'max': 1000})}, 'optional': {'optional_interpolation_states': ('INTERPOLATION_STATES',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'vfi' + CATEGORY = 'ComfyUI-Frame-Interpolation/VFI' + + def vfi(self, ckpt_name: typing.AnyStr, frames: torch.Tensor, clear_cache_after_n_frames=10, multiplier: typing.SupportsInt=2, optional_interpolation_states: InterpolationStateList=None, **kwargs): + """ + Perform video frame interpolation using a given checkpoint model. + + Args: + ckpt_name (str): The name of the checkpoint model to use. + frames (torch.Tensor): A tensor containing input video frames. + clear_cache_after_n_frames (int, optional): The number of frames to process before clearing CUDA cache + to prevent memory overflow. Defaults to 10. Lower numbers are safer but mean more processing time. + How high you should set it depends on how many input frames there are, input resolution (after upscaling), + how many times you want to multiply them, and how long you're willing to wait for the process to complete. + multiplier (int, optional): The multiplier for each input frame. 60 input frames * 2 = 120 output frames. Defaults to 2. + + Returns: + tuple: A tuple containing the output interpolated frames. + + Note: + This method interpolates frames in a video sequence using a specified checkpoint model. + It processes each frame sequentially, generating interpolated frames between them. + + To prevent memory overflow, it clears the CUDA cache after processing a specified number of frames. + """ + interpolation_model = CommonModelInference(model_type=ckpt_name) + interpolation_model.eval().to(get_torch_device()) + frames = preprocess_frames(frames) + + def return_middle_frame(frame_0, frame_1, timestep, model, scale): + return model(frame_0, frame_1, timestep, scale) + scale = 1 + args = [interpolation_model, scale] + out = postprocess_frames(generic_frame_loop(frames, clear_cache_after_n_frames, multiplier, return_middle_frame, *args, interpolation_states=optional_interpolation_states, dtype=torch.float32)) + return (out,) +``` \ No newline at end of file diff --git a/docs/Generate Border Mask (WLSH).md b/docs/Generate Border Mask (WLSH).md new file mode 100644 index 0000000..ae5dfdb --- /dev/null +++ b/docs/Generate Border Mask (WLSH).md @@ -0,0 +1,70 @@ +# Documentation +- Class name: WLSH_Generate_Edge_Mask +- Category: WLSH Nodes/inpainting +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_Generate_Edge_Mask节点负责根据给定的方向和图像生成边缘遮罩。它创建一个掩码,可用于修复任务,确保掩蔽区域与指定的方向对齐,例如'up'、'down'、'left'或'right'。节点的功能对于需要选择性掩蔽的图像处理应用至关重要。 + +# Input types +## Required +- image + - 图像参数对于节点至关重要,因为它是生成边缘掩码的基础。节点处理此图像以创建与指定方向相对应的掩码,在节点的整体功能中起着关键作用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- direction + - 方向参数决定了要生成的掩码的方向。它是一个关键的输入,因为它决定了掩码将如何应用于图像,影响修复过程的最终结果。 + - Comfy dtype: STRING + - Python dtype: str +- pixels + - 像素参数指定掩码边缘的大小,以像素为单位,这是控制掩蔽区域范围的重要因素。此参数直接影响节点的执行和生成的掩码的精度。 + - Comfy dtype: INT + - Python dtype: int +- overlap + - 重叠参数定义了掩码边缘的厚度,这对于确保掩蔽区域和未掩蔽区域之间的平滑过渡非常重要。它通过防止边缘突变,有助于提高修复结果的质量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- mask + - 输出掩码是节点操作的关键结果。它代表了将要进行修复处理的区域,其质量和对齐方式直接影响最终图像输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Generate_Edge_Mask: + directions = ['left', 'right', 'up', 'down'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'direction': (s.directions,), 'pixels': ('INT', {'default': 128, 'min': 32, 'max': 512, 'step': 32}), 'overlap': ('INT', {'default': 64, 'min': 16, 'max': 256, 'step': 16})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'gen_second_mask' + CATEGORY = 'WLSH Nodes/inpainting' + + def gen_second_mask(self, direction, image, pixels, overlap): + image = tensor2pil(image) + (new_width, new_height) = image.size + mask2 = Image.new('RGBA', (new_width, new_height), (0, 0, 0, 255)) + mask_thickness = overlap + if direction == 'up': + new_mask = Image.new('RGBA', (new_width, mask_thickness), (0, 122, 0, 255)) + mask2.paste(new_mask, (0, pixels - int(mask_thickness / 2))) + elif direction == 'down': + new_mask = Image.new('RGBA', (new_width, mask_thickness), (0, 122, 0, 255)) + mask2.paste(new_mask, (0, new_height - pixels - int(mask_thickness / 2))) + elif direction == 'left': + new_mask = Image.new('RGBA', (mask_thickness, new_height), (0, 122, 0, 255)) + mask2.paste(new_mask, (pixels - int(mask_thickness / 2), 0)) + elif direction == 'right': + new_mask = Image.new('RGBA', (mask_thickness, new_height), (0, 122, 0, 255)) + mask2.paste(new_mask, (new_width - pixels - int(mask_thickness / 2), 0)) + mask2 = mask2.filter(ImageFilter.GaussianBlur(radius=5)) + mask2 = np.array(mask2).astype(np.float32) / 255.0 + mask2 = torch.from_numpy(mask2)[None,] + return (mask2,) +``` \ No newline at end of file diff --git a/docs/Get Batch From History (mtb).md b/docs/Get Batch From History (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Get First Image.md b/docs/Get First Image.md new file mode 100644 index 0000000..01b9124 --- /dev/null +++ b/docs/Get First Image.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: GetFirstImage +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +该节点旨在从一批图像中提取特定的子集,专注于选择过程并确保所需图像被隔离以供进一步处理。 + +# Input types +## Required +- images + - 图像参数至关重要,因为它是节点操作的主要输入。预期它是一个包含一批图像的张量,节点将根据定义的标准从这些图像中选择特定的图像。 + - Comfy dtype: COMBO[torch.Tensor] + - Python dtype: torch.Tensor + +# Output types +- images + - 该节点的输出是根据指定标准选择的输入图像的精炼子集。这个子集旨在进行进一步的分析或处理。 + - Comfy dtype: COMBO[torch.Tensor] + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GetFirstImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'run' + OUTPUT_NODE = False + CATEGORY = 'DragNUWA' + + def run(self, images: torch.Tensor): + shape = images.shape + len_first_dim = shape[0] + selected_indexes = f'0' + selected_index: list[int] = [] + total_indexes: list[int] = list(range(len_first_dim)) + for s in selected_indexes.strip().split(','): + try: + if ':' in s: + _li = s.strip().split(':', maxsplit=1) + _start = _li[0] + _end = _li[1] + if _start and _end: + selected_index.extend(total_indexes[int(_start):int(_end)]) + elif _start: + selected_index.extend(total_indexes[int(_start):]) + elif _end: + selected_index.extend(total_indexes[:int(_end)]) + else: + x: int = int(s.strip()) + if x < len_first_dim: + selected_index.append(x) + except: + pass + return (images[selected_index, :, :, :],) +``` \ No newline at end of file diff --git a/docs/Get Image Size.md b/docs/Get Image Size.md new file mode 100644 index 0000000..d19a7fb --- /dev/null +++ b/docs/Get Image Size.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: GetImageSize +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +GetImageSize节点旨在提取图像的尺寸,提供宽度和高度作为输出。它在图像处理任务中扮演着关键角色,其中图像的空间尺寸对于进一步操作(如调整大小、裁剪或数据分析)至关重要。 + +# Input types +## Required +- image + - 图像参数对节点至关重要,因为它是待确定尺寸的来源。节点依赖此输入来计算并返回图像的宽度和高度,这可以显著影响后续的图像操作和分析。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- width + - 宽度输出提供了处理后图像的水平尺寸。这是一个关键的信息,可用于多种目的,如确定纵横比或与其他图像处理系统的兼容性检查。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度输出代表了图像的垂直尺寸。这是一个基本参数,用于需要了解图像空间结构的任务,如调整大小以适应特定框架或显示目的。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GetImageSize: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',)}} + RETURN_TYPES = ('INT', 'INT') + RETURN_NAMES = ('width', 'height') + FUNCTION = 'get_size' + CATEGORY = 'Masquerade Nodes' + + def get_size(self, image): + image_size = image.size() + image_width = int(image_size[2]) + image_height = int(image_size[1]) + return (image_width, image_height) +``` \ No newline at end of file diff --git a/docs/Get Last Image.md b/docs/Get Last Image.md new file mode 100644 index 0000000..91285de --- /dev/null +++ b/docs/Get Last Image.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: GetLastImage +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +该节点旨在从一批图像中提取最后一张图像,确保输出是序列中的最终视觉表示。 + +# Input types +## Required +- images + - 输入参数'images'对于节点的操作至关重要,因为它提供了节点处理的图像数据批次,以选择最后一张图像。 + - Comfy dtype: COMBO[torch.Tensor] + - Python dtype: torch.Tensor + +# Output types +- images + - 输出是输入批次中的最后一张图像,这很重要,因为它代表了节点提取的最终视觉数据。 + - Comfy dtype: COMBO[torch.Tensor] + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GetLastImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'run' + OUTPUT_NODE = False + CATEGORY = 'DragNUWA' + + def run(self, images: torch.Tensor): + shape = images.shape + len_first_dim = shape[0] + selected_indexes = f'{len_first_dim - 1}' + selected_index: list[int] = [] + total_indexes: list[int] = list(range(len_first_dim)) + for s in selected_indexes.strip().split(','): + try: + if ':' in s: + _li = s.strip().split(':', maxsplit=1) + _start = _li[0] + _end = _li[1] + if _start and _end: + selected_index.extend(total_indexes[int(_start):int(_end)]) + elif _start: + selected_index.extend(total_indexes[int(_start):]) + elif _end: + selected_index.extend(total_indexes[:int(_end)]) + else: + x: int = int(s.strip()) + if x < len_first_dim: + selected_index.append(x) + except: + pass + return (images[selected_index, :, :, :],) +``` \ No newline at end of file diff --git a/docs/GetImageSize+.md b/docs/GetImageSize+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/GetImageSize_.md b/docs/GetImageSize_.md new file mode 100644 index 0000000..9539866 --- /dev/null +++ b/docs/GetImageSize_.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: GetImageSize_ +- Category: ♾️Mixlab/Image +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点旨在提取并可选地调整图像的尺寸,确保其满足最小宽度要求。它处理图像以保持其宽高比,并返回原始尺寸和调整后的尺寸,有助于在工作流中全面了解图像属性。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它是节点操作的主要输入。它是节点获取宽度和高度信息的来源,并可能将其调整大小以满足指定的最小宽度标准。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +## Optional +- min_width + - min_width参数非常重要,因为它设定了图像的最小宽度要求。如果图像的宽度小于这个值,节点将调整图像大小以满足这个标准,确保为进一步的图像处理提供一个一致的起点。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- width + - 宽度输出代表输入图像的原始宽度。这是理解图像尺寸的基础信息,对于任何后续的图像操作或分析都至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度输出对应输入图像的原始高度,为图像大小和宽高比提供重要背景,这对于在处理过程中保持图像完整性至关重要。 + - Comfy dtype: INT + - Python dtype: int +- min_width + - min_width输出指示调整大小后的图像的最小宽度。它确保图像满足进一步处理或显示所需的尺寸,符合工作流的规范。 + - Comfy dtype: INT + - Python dtype: int +- min_height + - min_height输出表示调整大小以满足最小宽度标准后的图像高度。这对于理解图像如何被调整以及确保正确显示或进一步处理非常重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GetImageSize_: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',)}, 'optional': {'min_width': ('INT', {'default': 512, 'min': 1, 'max': 2048, 'step': 8, 'display': 'number'})}} + RETURN_TYPES = ('INT', 'INT', 'INT', 'INT') + RETURN_NAMES = ('width', 'height', 'min_width', 'min_height') + FUNCTION = 'get_size' + CATEGORY = '♾️Mixlab/Image' + + def get_size(self, image, min_width): + (_, height, width, _) = image.shape + if min_width > width: + im = tensor2pil(image) + im = resize_image(im, 'width', min_width, min_width, 'white') + im = im.convert('RGB') + (min_width, min_height) = im.size + else: + min_width = width + min_height = height + return (width, height, min_width, min_height) +``` \ No newline at end of file diff --git a/docs/GlobalSampler %2F%2FInspire.md b/docs/GlobalSampler %2F%2FInspire.md new file mode 100644 index 0000000..34871fe --- /dev/null +++ b/docs/GlobalSampler %2F%2FInspire.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: GlobalSampler +- Category: InspirePack/Prompt +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +GlobalSampler节点抽象地表示了一个从给定集合中均匀抽样元素的系统,确保每个元素被选中的概率相等。它的设计是为了在过程中引入随机性,以公正无偏的方式,这对于需要随机行为或结果多样性的应用至关重要。 + +# Input types +## Required +- sampler_name + - sampler_name参数至关重要,因为它决定了要使用的抽样方法。它通过确定将使用哪种抽样算法直接影响节点的操作,从而塑造结果的多样性和随机性。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- scheduler + - scheduler参数对于管理抽样过程的执行流程至关重要。它影响节点如何协调抽样的时机和频率,确保有效地引入随机性,而不会影响整个过程。 + - Comfy dtype: COMBO[str] + - Python dtype: str + +# Output types +- sampled_data + - sampled_data输出包含了抽样过程的结果,代表了被选中的元素。它是关键的输出,因为它直接反映了抽样方法的有效性和实现的随机性质量。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GlobalSampler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,)}} + RETURN_TYPES = () + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Prompt' + OUTPUT_NODE = True + + def doit(self, **kwargs): + return {} +``` \ No newline at end of file diff --git a/docs/GlobalSeed %2F%2FInspire.md b/docs/GlobalSeed %2F%2FInspire.md new file mode 100644 index 0000000..c4ab21d --- /dev/null +++ b/docs/GlobalSeed %2F%2FInspire.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: GlobalSeed +- Category: InspirePack/Prompt +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +GlobalSeed节点旨在通过使用种子值来管理和控制生成过程。它允许用户通过不同的模式来决定生成的随机性,确保输出的一致性或多样性。 + +# Input types +## Required +- value + - “value”参数对于设置生成过程的种子至关重要。通过改变种子,可以控制输出的变异性,从而产生可复现或多样化的结果。 + - Comfy dtype: INT + - Python dtype: int +- mode + - “mode”参数决定种子值如何影响生成过程。它提供了多种模式,如'fixed'、'increment'和'randomize',每种模式对输出的影响不同,为生成过程提供了灵活性。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- action + - “action”参数提供了一组选项,进一步细化种子对生成的影响。它与“mode”参数协同工作,允许对结果的随机性和一致性进行精细控制。 + - Comfy dtype: COMBO + - Python dtype: str +- last_seed + - “last_seed”参数用于从之前的生成中继承一个种子,使得不同生成过程的运行之间具有连续性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- output + - GlobalSeed节点的输出提供了生成过程的结果,包含了输入参数控制的随机性。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GlobalSeed: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'value': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'mode': ('BOOLEAN', {'default': True, 'label_on': 'control_before_generate', 'label_off': 'control_after_generate'}), 'action': (['fixed', 'increment', 'decrement', 'randomize', 'increment for each node', 'decrement for each node', 'randomize for each node'],), 'last_seed': ('STRING', {'default': ''})}} + RETURN_TYPES = () + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Prompt' + OUTPUT_NODE = True + + def doit(self, **kwargs): + return {} +``` \ No newline at end of file diff --git a/docs/Glow.md b/docs/Glow.md new file mode 100644 index 0000000..99e919b --- /dev/null +++ b/docs/Glow.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: Glow +- Category: postprocessing/Effects +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +该节点为图像应用发光效果,通过增加可调节强度的模糊图像版本来增强其视觉吸引力。它旨在改善后处理阶段图像的美观性,提供一种主题性的光芒,可以吸引人们对某些特征的注意或创造梦幻般的氛围。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它是应用发光效果的基础输入。它决定了最终输出的内容和结构,发光效果直接受到图像特征和质量的影响。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- intensity + - 强度参数控制发光效果的显著程度,数值越高,发光越明显。它在调整效果的视觉影响力方面至关重要,允许微调发光的强度以达到所需的美学效果。 + - Comfy dtype: FLOAT + - Python dtype: float +- blur_radius + - 模糊半径参数规定了为发光效果应用到图像的模糊程度。它影响发光的扩散和平滑度,较大的半径会导致更分散和广泛的亮度。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- glowing_image + - 生成的发光图像是该节点的主要输出,代表增强了发光效果的原始图像。它包含了输入参数的综合视觉修改,提供了输入图像视觉上引人入胜的呈现。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class Glow: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'intensity': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 5.0, 'step': 0.01}), 'blur_radius': ('INT', {'default': 5, 'min': 1, 'max': 50, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'apply_glow' + CATEGORY = 'postprocessing/Effects' + + def apply_glow(self, image: torch.Tensor, intensity: float, blur_radius: int): + blurred_image = self.gaussian_blur(image, 2 * blur_radius + 1) + glowing_image = self.add_glow(image, blurred_image, intensity) + glowing_image = torch.clamp(glowing_image, 0, 1) + return (glowing_image,) + + def gaussian_blur(self, image: torch.Tensor, kernel_size: int): + (batch_size, height, width, channels) = image.shape + sigma = (kernel_size - 1) / 6 + kernel = gaussian_kernel(kernel_size, sigma).repeat(channels, 1, 1).unsqueeze(1) + image = image.permute(0, 3, 1, 2) + blurred = F.conv2d(image, kernel, padding=kernel_size // 2, groups=channels) + blurred = blurred.permute(0, 2, 3, 1) + return blurred + + def add_glow(self, img, blurred_img, intensity): + return img + blurred_img * intensity +``` \ No newline at end of file diff --git a/docs/GradientImage.md b/docs/GradientImage.md new file mode 100644 index 0000000..8517cbb --- /dev/null +++ b/docs/GradientImage.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: GradientImage +- Category: ♾️Mixlab/Image +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +GradientImage节点旨在从指定的起始颜色生成到结束颜色的渐变图像。它与图像处理库无缝集成,创建出视觉上吸引人的渐变效果,可用于各种应用,如背景或设计元素。 + +# Input types +## Required +- width + - 宽度参数决定了生成的渐变图像的宽度。它是设置图像尺寸的关键因素,进而影响整体的视觉布局和设计。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置渐变图像的垂直尺寸。它与宽度一起工作,以确定图像的整体大小,这对于将图像适应特定的设计空间至关重要。 + - Comfy dtype: INT + - Python dtype: int +- start_color_hex + - start_color_hex参数指定渐变开始处的十六进制颜色代码。它是一个基本输入,决定了渐变图像中颜色过渡的起始点。 + - Comfy dtype: STRING + - Python dtype: str +- end_color_hex + - end_color_hex参数定义渐变结束处的十六进制颜色代码。它对于确定渐变中的最终颜色至关重要,从而完成颜色过渡效果。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE + - IMAGE输出提供生成的渐变图像,可用于各种用途,如视觉演示或图形设计项目。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- MASK + - MASK输出包括一个遮罩图像,可用于选择性编辑或对渐变图像的特定区域应用特定效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GradientImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 1, 'max': 8192, 'step': 1, 'display': 'number'}), 'height': ('INT', {'default': 512, 'min': 1, 'max': 8192, 'step': 1, 'display': 'number'}), 'start_color_hex': ('STRING', {'multiline': False, 'default': '#FFFFFF', 'dynamicPrompts': False}), 'end_color_hex': ('STRING', {'multiline': False, 'default': '#000000', 'dynamicPrompts': False})}} + RETURN_TYPES = ('IMAGE', 'MASK') + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Image' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False, False) + + def run(self, width, height, start_color_hex, end_color_hex): + (im, mask) = generate_gradient_image(width, height, start_color_hex, end_color_hex) + output_dir = folder_paths.get_temp_directory() + (full_output_folder, filename, counter, subfolder, _) = folder_paths.get_save_image_path('tmp_', output_dir) + image_file = f'{filename}_{counter:05}.png' + image_path = os.path.join(full_output_folder, image_file) + im.save(image_path, compress_level=6) + im = pil2tensor(im) + mask = pil2tensor(mask) + return {'ui': {'images': [{'filename': image_file, 'subfolder': subfolder, 'type': 'temp'}]}, 'result': (im, mask)} +``` \ No newline at end of file diff --git a/docs/Grayscale Image (WLSH).md b/docs/Grayscale Image (WLSH).md new file mode 100644 index 0000000..bf0258f --- /dev/null +++ b/docs/Grayscale Image (WLSH).md @@ -0,0 +1,44 @@ +# Documentation +- Class name: WLSH_Image_Grayscale +- Category: WLSH Nodes/image +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点旨在将彩色图像转换为灰度图像,这是图像处理中的一项基本操作,通过去除颜色信息来降低图像的复杂性,从而专注于图像的结构和亮度方面。 + +# Input types +## Required +- original + - 原始图像是进行灰度转换过程所需的输入。它至关重要,因为它是转换的对象,原始图像的质量和分辨率直接影响结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray + +# Output types +- grayscale + - 输出是输入图像的灰度版本,已处理以专注于亮度和结构细节,不受颜色的干扰。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Image_Grayscale: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'original': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('grayscale',) + FUNCTION = 'make_grayscale' + CATEGORY = 'WLSH Nodes/image' + + def make_grayscale(self, original): + image = tensor2pil(original) + image = ImageOps.grayscale(image) + image = image.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + return (image,) +``` \ No newline at end of file diff --git a/docs/GridOutput.md b/docs/GridOutput.md new file mode 100644 index 0000000..46a7f95 --- /dev/null +++ b/docs/GridOutput.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: GridOutput +- Category: ♾️Mixlab/Layer +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点类封装了处理和输出网格坐标及尺寸的功能,便于在基于网格的系统中进行操作和定位。 + +# Input types +## Required +- grid + - grid参数代表网格系统中元素的坐标和尺寸。它对于确定元素的位置和大小至关重要。 + - Comfy dtype: tuple[int, int, int, int] + - Python dtype: Tuple[int, int, int, int] + +# Output types +- x + - 网格的x坐标,表示元素在网格中的水平位置。 + - Comfy dtype: int + - Python dtype: int +- y + - 网格的y坐标,表示元素在网格中的垂直位置。 + - Comfy dtype: int + - Python dtype: int +- width + - 网格中元素的宽度,定义了其水平延伸的范围。 + - Comfy dtype: int + - Python dtype: int +- height + - 网格中元素的高度,定义了其垂直延伸的范围。 + - Comfy dtype: int + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GridOutput: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'grid': ('_GRID',)}} + RETURN_TYPES = ('INT', 'INT', 'INT', 'INT') + RETURN_NAMES = ('x', 'y', 'width', 'height') + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Layer' + INPUT_IS_LIST = False + + def run(self, grid): + (x, y, w, h) = grid + return (x, y, w, h) +``` \ No newline at end of file diff --git a/docs/GroundingDinoModelLoader (segment anything).md b/docs/GroundingDinoModelLoader (segment anything).md new file mode 100644 index 0000000..4287875 --- /dev/null +++ b/docs/GroundingDinoModelLoader (segment anything).md @@ -0,0 +1,39 @@ +# Documentation +- Class name: GroundingDinoModelLoader +- Category: segment_anything +- Output node: False +- Repo Ref: https://github.com/storyicon/comfyui_segment_anything + +该节点旨在加载和准备一个GroundingDino模型,用于图像的分割和理解。它封装了选择模型、加载其配置和初始化模型结构的过程。节点通过将模型放置在适当的设备上并将其设置为评估模式,确保模型准备好进行进一步的处理。 + +# Input types +## Required +- model_name + - 模型名称参数至关重要,因为它决定了将要加载哪个GroundingDino模型进行处理。它通过指定模型架构及其相关权重来影响整个操作,这对于模型在图像分割任务中的性能至关重要。 + - Comfy dtype: list + - Python dtype: str + +# Output types +- GROUNDING_DINO_MODEL + - 输出提供了一个完全初始化并准备使用的GroundingDino模型。它封装了模型的架构、学习到的权重,并且为在图像分割任务中的部署做好了准备,标志着其在流程中的重要性。 + - Comfy dtype: model + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class GroundingDinoModelLoader: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model_name': (list_groundingdino_model(),)}} + CATEGORY = 'segment_anything' + FUNCTION = 'main' + RETURN_TYPES = ('GROUNDING_DINO_MODEL',) + + def main(self, model_name): + dino_model = load_groundingdino_model(model_name) + return (dino_model,) +``` \ No newline at end of file diff --git a/docs/GroundingDinoSAMSegment (segment anything).md b/docs/GroundingDinoSAMSegment (segment anything).md new file mode 100644 index 0000000..2955414 --- /dev/null +++ b/docs/GroundingDinoSAMSegment (segment anything).md @@ -0,0 +1,73 @@ +# Documentation +- Class name: GroundingDinoSAMSegment +- Category: segment_anything +- Output node: False +- Repo Ref: https://github.com/storyicon/comfyui_segment_anything + +GroundingDinoSAMSegment节点旨在通过基于文本提示的图像分割来处理图像。它利用SAM(Segment Anything Model)和GroundingDino模型的能力来识别和隔离图像中的对象,提供分割后的图像及其对应的掩码。该节点特别适用于需要从视觉和文本输入中理解对象级别的应用程序。 + +# Input types +## Required +- sam_model + - SAM模型对于分割过程至关重要,提供了识别和分离图像中对象的核心功能。它在节点根据输入图像和提示执行精确分割的能力中起着关键作用。 + - Comfy dtype: SAM_MODEL + - Python dtype: torch.nn.Module +- grounding_dino_model + - GroundingDino模型用于根据文本提示预测图像中对象的边界框。它是初始对象检测步骤的关键组件,为后续的分割过程奠定了基础。 + - Comfy dtype: GROUNDING_DINO_MODEL + - Python dtype: torch.nn.Module +- image + - 输入图像是节点操作的主要数据源。它是分割过程的对象,节点的目标是根据提供的提示识别和分离其中包含的对象。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- prompt + - 提示作为文本描述,指导节点在图像中识别感兴趣的对象。它是一个重要的输入,帮助节点将其分割工作集中在图像的相关部分上。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- threshold + - 阈值参数用于确定对象检测的置信度水平。它影响节点基于grounding预测决定要分割哪些对象,允许控制最终输出中包含的对象。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- IMAGE + - 输出图像是分割过程的结果,显示了从输入图像中分离出的对象。它代表了节点的主要视觉输出,根据提供的提示和模型能力突出了分割成功。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- MASK + - 掩码输出提供了分割的二进制表示,概述了图像中与分割对象相对应的精确区域。对于需要详细对象勾画的应用程序来说,它是一个关键组件。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class GroundingDinoSAMSegment: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'sam_model': ('SAM_MODEL', {}), 'grounding_dino_model': ('GROUNDING_DINO_MODEL', {}), 'image': ('IMAGE', {}), 'prompt': ('STRING', {}), 'threshold': ('FLOAT', {'default': 0.3, 'min': 0, 'max': 1.0, 'step': 0.01})}} + CATEGORY = 'segment_anything' + FUNCTION = 'main' + RETURN_TYPES = ('IMAGE', 'MASK') + + def main(self, grounding_dino_model, sam_model, image, prompt, threshold): + res_images = [] + res_masks = [] + for item in image: + item = Image.fromarray(np.clip(255.0 * item.cpu().numpy(), 0, 255).astype(np.uint8)).convert('RGBA') + boxes = groundingdino_predict(grounding_dino_model, item, prompt, threshold) + if boxes.shape[0] == 0: + break + (images, masks) = sam_segment(sam_model, item, boxes) + res_images.extend(images) + res_masks.extend(masks) + if len(res_images) == 0: + (_, height, width, _) = image.size() + empty_mask = torch.zeros((1, height, width), dtype=torch.uint8, device='cpu') + return (empty_mask, empty_mask) + return (torch.cat(res_images, dim=0), torch.cat(res_masks, dim=0)) +``` \ No newline at end of file diff --git a/docs/GuidedFilter(FaceParsing).md b/docs/GuidedFilter(FaceParsing).md new file mode 100644 index 0000000..dc1875d --- /dev/null +++ b/docs/GuidedFilter(FaceParsing).md @@ -0,0 +1,62 @@ +# Documentation +- Class name: GuidedFilter +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +GuidedFilter节点应用了一种非线性过滤技术,该技术利用引导图像来影响过滤过程,旨在在去除噪声或平滑外观的同时保留原始图像的结构和边缘。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它提供了将在其上执行引导过滤操作的输入图像数据,这对输出质量和细节有重大影响。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- radius + - 半径参数决定了滤波器考虑的局部邻域的大小,影响了滤波器在保留边缘的同时平滑图像的程度。 + - Comfy dtype: INT + - Python dtype: int +- eps + - eps参数控制引导滤波器的灵敏度,较低的值导致更激进的平滑,较高的值保留更多的细节。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- guide + - 当提供引导参数时,它作为参考图像引导过滤过程,允许基于引导内容的选择性增强或抑制特征。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- output_image + - 输出图像是引导滤波操作的结果,反映了输入图像与引导图像(如果有的话)提供的指导的结合。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GuidedFilter: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'radius': ('INT', {'default': 3, 'min': 0, 'step': 1}), 'eps': ('FLOAT', {'default': 125, 'min': 0, 'step': 1})}, 'optional': {'guide': ('IMAGE', {'default': None})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'guided_filter' + CATEGORY = 'face_parsing' + + def guided_filter(self, image: Tensor, radius: int, eps: float, guide: Tensor | None=None): + results = [] + for item in image: + image_cv2 = cv2.cvtColor(item.mul(255).byte().numpy(), cv2.COLOR_RGB2BGR) + guide_cv2 = image_cv2 if guide is None else cv2.cvtColor(guide.numpy(), cv2.COLOR_RGB2BGR) + result_cv2 = cv2.ximgproc.guidedFilter(guide_cv2, image_cv2, radius, eps) + result_cv2_rgb = cv2.cvtColor(result_cv2, cv2.COLOR_BGR2RGB) + result = torch.tensor(result_cv2_rgb).float().div(255) + results.append(result) + return (torch.cat(results, dim=0).unsqueeze(0),) +``` \ No newline at end of file diff --git a/docs/HEDPreprocessor_Provider_for_SEGS %2F%2FInspire.md b/docs/HEDPreprocessor_Provider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..2255a2f --- /dev/null +++ b/docs/HEDPreprocessor_Provider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: HEDPreprocessor_Provider_for_SEGS +- Category: InspirePack/SEGS/ControlNet +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +HEDPreprocessor_Provider_for_SEGS 类旨在为图像分割应用提供 HED(全嵌套边缘检测)算法。它利用 HED 预处理器增强图像边缘,这对于分割和识别图像内的区域至关重要。该节点对于需要详细边缘检测的任务是不可或缺的,并且是 SEGS(语义边缘引导分割)工作流程的一部分。 + +# Input types +## Required +- safe + - ‘safe’参数是一个布尔标志,用于确定在预处理阶段是否启用或禁用某些安全特性。它在确保图像处理的稳定性和可靠性方面发挥着关键作用,同时防止在边缘检测过程中可能出现的潜在错误或伪影。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- SEGS_PREPROCESSOR + - HEDPreprocessor_Provider_for_SEGS 的输出是使用 HED 算法增强边缘的预处理图像。这个输出是分割过程中的关键步骤,因为它提供了图像结构的详细表示,这对于准确的分割至关重要。 + - Comfy dtype: SEGS_PREPROCESSOR + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class HEDPreprocessor_Provider_for_SEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'safe': ('BOOLEAN', {'default': True, 'label_on': 'enable', 'label_off': 'disable'})}} + RETURN_TYPES = ('SEGS_PREPROCESSOR',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/SEGS/ControlNet' + + def doit(self, safe): + obj = HED_Preprocessor_wrapper(safe, 'HEDPreprocessor') + return (obj,) +``` \ No newline at end of file diff --git a/docs/HSVThresholdMask.md b/docs/HSVThresholdMask.md new file mode 100644 index 0000000..394f610 --- /dev/null +++ b/docs/HSVThresholdMask.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: HSVThresholdMask +- Category: postprocessing/Masks +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +该节点类封装了HSV颜色空间内的阈值操作功能,能够基于特定的色调、饱和度或亮度范围创建二值掩码。这对于图像中分割和隔离感兴趣区域至关重要,促进了对象识别和降噪等多种图像处理任务的进行。 + +# Input types +## Required +- image + - 图像参数对于HSV阈值处理过程至关重要,因为它提供了进行阈值分割的源数据。它通过决定图像的哪些区域将受到掩码标准的处理,从而影响整个操作。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- low_threshold + - 低阈值参数设置了HSV通道值的下限,对于定义将被考虑用于掩码的像素值范围起着至关重要的作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- high_threshold + - 高阈值参数建立了HSV通道值的上限,与低阈值一起决定了最终的掩码。 + - Comfy dtype: FLOAT + - Python dtype: float +- hsv_channel + - hsv_channel参数指示在HSV颜色空间中将使用哪个通道进行阈值处理,这对生成的掩码及其在手头图像处理任务中的适用性有着重大影响。 + - Comfy dtype: COMBO['hue', 'saturation', 'value'] + - Python dtype: str + +# Output types +- result + - 结果参数代表通过应用HSV阈值标准生成的二值掩码,是进一步图像分析和操作的重要工具。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class HSVThresholdMask: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'low_threshold': ('FLOAT', {'default': 0.2, 'min': 0, 'max': 1, 'step': 0.1}), 'high_threshold': ('FLOAT', {'default': 0.7, 'min': 0, 'max': 1, 'step': 0.1}), 'hsv_channel': (['hue', 'saturation', 'value'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'hsv_threshold' + CATEGORY = 'postprocessing/Masks' + + def hsv_threshold(self, image: torch.Tensor, low_threshold: float, high_threshold: float, hsv_channel: str): + (batch_size, height, width, _) = image.shape + result = torch.zeros(batch_size, height, width) + if hsv_channel == 'hue': + channel = 0 + (low_threshold, high_threshold) = (int(low_threshold * 180), int(high_threshold * 180)) + elif hsv_channel == 'saturation': + channel = 1 + (low_threshold, high_threshold) = (int(low_threshold * 255), int(high_threshold * 255)) + elif hsv_channel == 'value': + channel = 2 + (low_threshold, high_threshold) = (int(low_threshold * 255), int(high_threshold * 255)) + for b in range(batch_size): + tensor_image = (image[b].numpy().copy() * 255).astype(np.uint8) + hsv_image = cv2.cvtColor(tensor_image, cv2.COLOR_RGB2HSV) + mask = cv2.inRange(hsv_image[:, :, channel], low_threshold, high_threshold) + tensor = torch.from_numpy(mask).float() / 255.0 + result[b] = tensor + return (result,) +``` \ No newline at end of file diff --git a/docs/HaldCLUT .md b/docs/HaldCLUT .md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Hina.PoseEditor3D.md b/docs/Hina.PoseEditor3D.md new file mode 100644 index 0000000..566f15c --- /dev/null +++ b/docs/Hina.PoseEditor3D.md @@ -0,0 +1,122 @@ +# Documentation +- Class name: PoseEditor3D +- Category: image +- Output node: False +- Repo Ref: https://github.com/hinablue/ComfyUI_3dPoseEditor.git + +PoseEditor3D类便于从图像中操作和处理3D姿态,使得可以提取和分析姿态数据以用于各种应用。 + +# Input types +## Optional +- pose + - 姿态参数对于从图像中初始化3D姿态至关重要,允许节点专注于特定的人物形象。 + - Comfy dtype: COMBO[sorted(os.listdir(temp_dir),)] + - Python dtype: Union[str, None] +- depth + - 深度图像为3D重建过程提供重要信息,提高了姿态估计的准确性。 + - Comfy dtype: COMBO[sorted(os.listdir(temp_dir),)] + - Python dtype: Union[str, None] +- normal + - 法线图像有助于理解3D形象的表面方向,改善了姿态的视觉表示。 + - Comfy dtype: COMBO[sorted(os.listdir(temp_dir),)] + - Python dtype: Union[str, None] +- canny + - Canny图像用于边缘检测,这对于识别3D姿态的轮廓和边界至关重要。 + - Comfy dtype: COMBO[sorted(os.listdir(temp_dir),)] + - Python dtype: Union[str, None] + +# Output types +- OpenPose + - OpenPose输出提供了3D姿态的详细表示,这对于进一步的分析和处理至关重要。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- Depth + - Depth输出包含处理后的深度信息,对于3D重建和理解场景的空间关系至关重要。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- Normal + - Normal输出代表3D形象的表面方向,提高了姿态的视觉准确性。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- Canny + - Canny输出提供边缘检测数据,这对于识别3D姿态的轮廓和边界至关重要。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PoseEditor3D(object): + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + temp_dir = folder_paths.get_temp_directory() + temp_dir = os.path.join(temp_dir, '3dposeeditor') + if not os.path.isdir(temp_dir): + os.makedirs(temp_dir) + return {'required': {}, 'optional': {'pose': (sorted(os.listdir(temp_dir)),), 'depth': (sorted(os.listdir(temp_dir)),), 'normal': (sorted(os.listdir(temp_dir)),), 'canny': (sorted(os.listdir(temp_dir)),)}} + RETURN_TYPES = ('IMAGE', 'IMAGE', 'IMAGE', 'IMAGE') + RETURN_NAMES = ('OpenPose', 'Depth', 'Normal', 'Canny') + FUNCTION = 'output_pose' + CATEGORY = 'image' + + def output_pose(self, pose=None, depth=None, normal=None, canny=None): + if pose is None: + return (None, None, None, None) + temp_dir = folder_paths.get_temp_directory() + temp_dir = os.path.join(temp_dir, '3dposeeditor') + image_path = os.path.join(temp_dir, pose) + if pose.startswith('http'): + from worker.components.utils import util + i = util.get_image_from_uri(pose) + else: + i = Image.open(image_path) + poseImage = i.convert('RGB') + poseImage = np.array(poseImage).astype(np.float32) / 255.0 + poseImage = torch.from_numpy(poseImage)[None,] + image_path = os.path.join(temp_dir, depth) + if depth.startswith('http'): + from worker.components.utils import util + i = util.get_image_from_uri(depth) + else: + i = Image.open(image_path) + depthImage = i.convert('RGB') + depthImage = np.array(depthImage).astype(np.float32) / 255.0 + depthImage = torch.from_numpy(depthImage)[None,] + image_path = os.path.join(temp_dir, normal) + if normal.startswith('http'): + from worker.components.utils import util + i = util.get_image_from_uri(normal) + else: + i = Image.open(image_path) + normalImage = i.convert('RGB') + normalImage = np.array(normalImage).astype(np.float32) / 255.0 + normalImage = torch.from_numpy(normalImage)[None,] + image_path = os.path.join(temp_dir, canny) + if canny.startswith('http'): + from worker.components.utils import util + i = util.get_image_from_uri(canny) + else: + i = Image.open(image_path) + cannyImage = i.convert('RGB') + cannyImage = np.array(cannyImage).astype(np.float32) / 255.0 + cannyImage = torch.from_numpy(cannyImage)[None,] + return (poseImage, depthImage, normalImage, cannyImage) + + @staticmethod + def IS_CHANGED(self, pose=None, depth=None, normal=None, canny=None): + if pose is None: + return False + temp_dir = folder_paths.get_temp_directory() + temp_dir = os.path.join(temp_dir, '3dposeeditor') + image_path = os.path.join(temp_dir, pose) + m = hashlib.sha256() + with open(image_path, 'rb') as f: + m.update(f.read()) + return m.digest().hex() +``` \ No newline at end of file diff --git a/docs/HyperTile %2F%2FInspire.md b/docs/HyperTile %2F%2FInspire.md new file mode 100644 index 0000000..7b10930 --- /dev/null +++ b/docs/HyperTile %2F%2FInspire.md @@ -0,0 +1,97 @@ +# Documentation +- Class name: HyperTileInspire +- Category: InspirePack/__for_testing +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +HyperTileInspire节点旨在通过动态调整给定模型的特征平铺来增强模型的功能。它通过引入一种随机但系统化的方法来修改模型输入的空间维度,这对于优化模型在从不同输入分辨率中受益的任务上的性能特别有用。该节点旨在提供一种灵活高效的方式,探索不同的平铺策略,而无需手动干预或预定义配置。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它代表了将通过平铺过程得到增强的机器学习模型。节点修改模型输入平铺的能力直接影响模型处理和学习数据的方式,可能在某些任务上带来性能提升。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- tile_size + - tile_size参数决定了模型输入将被划分成的平铺的基础大小。它在平铺过程中起着关键作用,因为它为输入空间的划分设定了初始尺度。此参数允许定制平铺的粒度,可以根据不同任务的具体需求进行调整。 + - Comfy dtype: INT + - Python dtype: int +- swap_size + - swap_size参数规定了可以用来调整平铺尺寸的最大除数大小。它是平铺随机化过程中的一个重要因素,因为它控制了平铺可能大小的范围。这为节点的操作增加了变化性,对于需要多样化输入配置的任务可能有益。 + - Comfy dtype: INT + - Python dtype: int +- max_depth + - max_depth参数指定可以递归应用平铺过程的最大次数。它是控制平铺操作复杂性的关键因素。通过调整此参数,用户可以管理平铺细节水平和执行操作所需的计算资源之间的权衡。 + - Comfy dtype: INT + - Python dtype: int +- scale_depth + - scale_depth参数是一个布尔标志,当设置为True时,它允许根据平铺过程的深度来缩放平铺尺寸。这可以导致更细致和自适应的平铺策略,允许模型更好地适应输入数据中的不同细节水平。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- seed + - seed参数用于初始化随机数生成器,确保平铺过程是可复现的。这在希望节点在多次运行中获得一致结果的场景中尤其重要。通过提供种子,用户可以控制平铺中的随机性以实现特定的结果。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- model + - 输出模型是输入模型的增强版本,其注意力机制被修改以包含输入的动态平铺。这允许模型在不同尺度上处理信息,这对于某些类型的分析或特征提取至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class HyperTileInspire: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'tile_size': ('INT', {'default': 256, 'min': 1, 'max': 2048}), 'swap_size': ('INT', {'default': 2, 'min': 1, 'max': 128}), 'max_depth': ('INT', {'default': 0, 'min': 0, 'max': 10}), 'scale_depth': ('BOOLEAN', {'default': False}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'patch' + CATEGORY = 'InspirePack/__for_testing' + + def patch(self, model, tile_size, swap_size, max_depth, scale_depth, seed): + latent_tile_size = max(32, tile_size) // 8 + temp = None + rand_obj = random.Random() + rand_obj.seed(seed) + + def hypertile_in(q, k, v, extra_options): + nonlocal temp + model_chans = q.shape[-2] + orig_shape = extra_options['original_shape'] + apply_to = [] + for i in range(max_depth + 1): + apply_to.append(orig_shape[-2] / 2 ** i * (orig_shape[-1] / 2 ** i)) + if model_chans in apply_to: + shape = extra_options['original_shape'] + aspect_ratio = shape[-1] / shape[-2] + hw = q.size(1) + (h, w) = (round(math.sqrt(hw * aspect_ratio)), round(math.sqrt(hw / aspect_ratio))) + factor = 2 ** apply_to.index(model_chans) if scale_depth else 1 + nh = random_divisor(h, latent_tile_size * factor, swap_size, rand_obj) + nw = random_divisor(w, latent_tile_size * factor, swap_size, rand_obj) + print(f'factor: {factor} <--- params.depth: {apply_to.index(model_chans)} / scale_depth: {scale_depth} / latent_tile_size={latent_tile_size}') + if nh * nw > 1: + q = rearrange(q, 'b (nh h nw w) c -> (b nh nw) (h w) c', h=h // nh, w=w // nw, nh=nh, nw=nw) + temp = (nh, nw, h, w) + print(f'q={q} / k={k} / v={v}') + return (q, k, v) + return (q, k, v) + + def hypertile_out(out, extra_options): + nonlocal temp + if temp is not None: + (nh, nw, h, w) = temp + temp = None + out = rearrange(out, '(b nh nw) hw c -> b nh nw hw c', nh=nh, nw=nw) + out = rearrange(out, 'b nh nw (h w) c -> b (nh h nw w) c', h=h // nh, w=w // nw) + return out + m = model.clone() + m.set_model_attn1_patch(hypertile_in) + m.set_model_attn1_output_patch(hypertile_out) + return (m,) +``` \ No newline at end of file diff --git a/docs/IFRNet VFI.md b/docs/IFRNet VFI.md new file mode 100644 index 0000000..cd563d3 --- /dev/null +++ b/docs/IFRNet VFI.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: IFRNet_VFI +- Category: ComfyUI-Frame-Interpolation/VFI +- Output node: False +- Repo Ref: https://github.com/Fannovel16/ComfyUI-Frame-Interpolation + +IFRNet_VFI节点旨在执行视频帧插值,增强视频序列中帧之间过渡的平滑度。它利用深度学习模型生成中间帧,从而在不牺牲视觉质量的情况下增加帧率。该节点特别适用于需要高帧率视频以获得更好运动清晰度的应用。 + +# Input types +## Required +- ckpt_name + - 检查点名称参数对于加载帧插值过程所需的预训练模型权重至关重要。它决定了节点要使用的特定模型架构及其相应的权重。 + - Comfy dtype: str + - Python dtype: str +- frames + - frames参数是必需的,因为它代表了节点将处理插值的输入视频帧。输入帧的质量和分辨率直接影响帧插值的输出。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +## Optional +- clear_cache_after_n_frames + - clear_cache_after_n_frames参数用于优化帧插值过程中的内存使用。它指定了清空缓存以释放内存的帧数。 + - Comfy dtype: int + - Python dtype: int +- multiplier + - multiplier参数定义了在原始帧之间插入新帧的速率。更高的乘数会导致输出视频的帧率更高。 + - Comfy dtype: int + - Python dtype: int +- scale_factor + - scale_factor参数用于在处理之前调整输入帧的分辨率。它可以用来根据需要放大或缩小帧。 + - Comfy dtype: float + - Python dtype: float +- optional_interpolation_states + - optional_interpolation_states参数提供了对帧插值过程的额外控制。它允许在插值期间为某些帧指定自定义状态或条件。 + - Comfy dtype: InterpolationStateList + - Python dtype: InterpolationStateList + +# Output types +- output_frames + - output_frames参数代表帧插值过程的结果。它包含原始帧以及新生成的中间帧,从而产生更平滑的视频序列。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class IFRNet_VFI: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (CKPT_NAMES,), 'frames': ('IMAGE',), 'clear_cache_after_n_frames': ('INT', {'default': 10, 'min': 1, 'max': 1000}), 'multiplier': ('INT', {'default': 2, 'min': 2, 'max': 1000}), 'scale_factor': ([0.25, 0.5, 1.0, 2.0, 4.0], {'default': 1.0})}, 'optional': {'optional_interpolation_states': ('INTERPOLATION_STATES',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'vfi' + CATEGORY = 'ComfyUI-Frame-Interpolation/VFI' + + def vfi(self, ckpt_name: typing.AnyStr, frames: torch.Tensor, clear_cache_after_n_frames: typing.SupportsInt=1, multiplier: typing.SupportsInt=2, scale_factor: typing.SupportsFloat=1.0, optional_interpolation_states: InterpolationStateList=None, **kwargs): + from .IFRNet_S_arch import IRFNet_S + from .IFRNet_L_arch import IRFNet_L + model_path = load_file_from_github_release(MODEL_TYPE, ckpt_name) + interpolation_model = IRFNet_S() if 'S' in ckpt_name else IRFNet_L() + interpolation_model.load_state_dict(torch.load(model_path)) + interpolation_model.eval().to(get_torch_device()) + frames = preprocess_frames(frames) + + def return_middle_frame(frame_0, frame_1, timestep, model, scale_factor): + return model(frame_0, frame_1, timestep, scale_factor) + args = [interpolation_model, scale_factor] + out = postprocess_frames(generic_frame_loop(frames, clear_cache_after_n_frames, multiplier, return_middle_frame, *args, interpolation_states=optional_interpolation_states, dtype=torch.float32)) + return (out,) +``` \ No newline at end of file diff --git a/docs/IFUnet VFI.md b/docs/IFUnet VFI.md new file mode 100644 index 0000000..2666bdf --- /dev/null +++ b/docs/IFUnet VFI.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: IFUnet_VFI +- Category: ComfyUI-Frame-Interpolation/VFI +- Output node: False +- Repo Ref: https://github.com/Fannovel16/ComfyUI-Frame-Interpolation + +IFUnet_VFI节点旨在执行视频帧插值,通过生成中间帧来增强视频过渡的平滑度和连续性。它利用深度学习模型来预测并插入现有帧之间的帧,从而提高视频序列的整体视觉质量和流畅性。 + +# Input types +## Required +- ckpt_name + - 检查点名称参数对于识别用于帧插值的特定模型权重至关重要。它将节点指向正确的预训练模型,确保帧生成过程的准确性和效率。 + - Comfy dtype: str + - Python dtype: str +- frames + - frames参数是必需的,因为它提供了节点将处理插值的输入视频帧。输入帧的质量和分辨率直接影响输出帧的视觉外观。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- clear_cache_after_n_frames + - clear_cache_after_n_frames参数在帧插值过程中管理内存使用方面非常重要。它通过在处理一定数量的帧后清除缓存,有助于维护系统性能。 + - Comfy dtype: INT + - Python dtype: int +- multiplier + - multiplier参数决定了在连续帧之间生成的中间帧的数量。它是控制插值帧的密度,进而控制视频平滑度的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- scale_factor + - scale_factor参数在处理前调整输入帧的缩放比例。这是一个重要因素,可以影响插值帧的细节和分辨率。 + - Comfy dtype: FLOAT + - Python dtype: float +- ensemble + - ensemble参数启用集成方法来提高插值帧的稳定性和质量。它是一个可选特性,可以在某些条件下增强节点的性能。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- optional_interpolation_states + - optional_interpolation_states参数提供了对插值过程的额外控制,允许根据特定要求或约束定制帧生成。 + - Comfy dtype: INTERPOLATION_STATES + - Python dtype: InterpolationStateList + +# Output types +- output_frames + - output_frames参数代表帧插值过程的结果。它包含原始帧以及新生成的中间帧,增强了视频的连续性和视觉吸引力。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class IFUnet_VFI: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (CKPT_NAMES,), 'frames': ('IMAGE',), 'clear_cache_after_n_frames': ('INT', {'default': 10, 'min': 1, 'max': 1000}), 'multiplier': ('INT', {'default': 2, 'min': 2, 'max': 1000}), 'scale_factor': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 100, 'step': 0.1}), 'ensemble': ('BOOLEAN', {'default': True})}, 'optional': {'optional_interpolation_states': ('INTERPOLATION_STATES',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'vfi' + CATEGORY = 'ComfyUI-Frame-Interpolation/VFI' + + def vfi(self, ckpt_name: typing.AnyStr, frames: torch.Tensor, clear_cache_after_n_frames: typing.SupportsInt=1, multiplier: typing.SupportsInt=2, scale_factor: typing.SupportsFloat=1.0, ensemble: bool=True, optional_interpolation_states: InterpolationStateList=None, **kwargs): + from .IFUNet_arch import IFUNetModel + model_path = load_file_from_github_release(MODEL_TYPE, ckpt_name) + interpolation_model = IFUNetModel() + interpolation_model.load_state_dict(torch.load(model_path)) + interpolation_model.eval().to(get_torch_device()) + frames = preprocess_frames(frames) + + def return_middle_frame(frame_0, frame_1, timestep, model, scale_factor, ensemble): + return model(frame_0, frame_1, timestep=timestep, scale=scale_factor, ensemble=ensemble) + args = [interpolation_model, scale_factor, ensemble] + out = postprocess_frames(generic_frame_loop(frames, clear_cache_after_n_frames, multiplier, return_middle_frame, *args, interpolation_states=optional_interpolation_states, dtype=torch.float32)) + return (out,) +``` \ No newline at end of file diff --git a/docs/INPAINT_ApplyFooocusInpaint.md b/docs/INPAINT_ApplyFooocusInpaint.md new file mode 100644 index 0000000..f34d3d7 --- /dev/null +++ b/docs/INPAINT_ApplyFooocusInpaint.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: ApplyFooocusInpaint +- Category: inpaint +- Output node: False +- Repo Ref: https://github.com/Acly/comfyui-inpaint-nodes + +该节点通过向给定模型应用补丁来促进图像修复过程,专注于填充数据中缺失或损坏的部分。它利用潜在表示和补丁技术,增强模型在目标区域生成连贯且上下文合适内容的能力。 + +# Input types +## Required +- model + - 模型参数对于图像修复过程至关重要。它是应用补丁和集成修复特性的基础。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_patcher.ModelPatcher +- patch + - 补丁参数对于图像修复过程至关重要,因为它包含了生成将应用于模型的补丁所需的特定修复头和设置。 + - Comfy dtype: INPAINT_PATCH + - Python dtype: Tuple[InpaintHead, dict[str, Tensor]] +- latent + - 潜在参数对于图像修复过程非常关键,因为它包含了用于生成缺失区域内容的编码信息。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, Any] + +# Output types +- MODEL + - 输出是经过补丁处理的模型,现在包含了修复的内容,有效地用上下文合适的数据填充了之前缺失或损坏的部分。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_patcher.ModelPatcher + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ApplyFooocusInpaint: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'patch': ('INPAINT_PATCH',), 'latent': ('LATENT',)}} + RETURN_TYPES = ('MODEL',) + CATEGORY = 'inpaint' + FUNCTION = 'patch' + + def patch(self, model: ModelPatcher, patch: tuple[InpaintHead, dict[str, Tensor]], latent: dict[str, Any]): + base_model: BaseModel = model.model + latent_pixels = base_model.process_latent_in(latent['samples']) + noise_mask = latent['noise_mask'].round() + latent_mask = F.max_pool2d(noise_mask, (8, 8)).round().to(latent_pixels) + (inpaint_head_model, inpaint_lora) = patch + feed = torch.cat([latent_mask, latent_pixels], dim=1) + inpaint_head_model.to(device=feed.device, dtype=feed.dtype) + inpaint_head_feature = inpaint_head_model(feed) + + def input_block_patch(h, transformer_options): + if transformer_options['block'][1] == 0: + h = h + inpaint_head_feature.to(h) + return h + lora_keys = comfy.lora.model_lora_keys_unet(model.model, {}) + lora_keys.update({x: x for x in base_model.state_dict().keys()}) + loaded_lora = load_fooocus_patch(inpaint_lora, lora_keys) + m = model.clone() + m.set_model_input_block_patch(input_block_patch) + patched = m.add_patches(loaded_lora, 1.0) + not_patched_count = sum((1 for x in loaded_lora if x not in patched)) + if not_patched_count > 0: + print(f'[ApplyFooocusInpaint] Failed to patch {not_patched_count} keys') + inject_patched_calculate_weight() + return (m,) +``` \ No newline at end of file diff --git a/docs/INPAINT_InpaintWithModel.md b/docs/INPAINT_InpaintWithModel.md new file mode 100644 index 0000000..c1042b1 --- /dev/null +++ b/docs/INPAINT_InpaintWithModel.md @@ -0,0 +1,63 @@ +# Documentation +- Class name: InpaintWithModel +- Category: inpaint +- Output node: False +- Repo Ref: https://github.com/Acly/comfyui-inpaint-nodes + +该节点使用深度学习模型执行图像修复,有效地填充图像中缺失或被遮罩的区域,并生成与周围内容相适应的内容。它适应不同的模型架构,并确保输出与原始图像无缝集成。 + +# Input types +## Required +- inpaint_model + - 修复模型对于节点的功能至关重要,它定义了用于生成修复内容的具体深度学习架构。模型的架构直接影响修复结果的质量和准确性。 + - Comfy dtype: INPAINT_MODEL + - Python dtype: PyTorchModel +- image + - 输入图像是节点操作的主要数据,修复过程旨在在填充缺失部分的同时保持其整体结构和美感。图像的质量和尺寸直接影响修复结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 遮罩定义了图像中需要修复的区域。它是一个关键参数,因为它指导模型专注于特定区域,确保修复是有针对性和相关的。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- output_image + - 输出图像是修复过程的结果,最初被遮罩或缺失的区域现在填充了与周围内容相匹配的内容。它代表节点的主要输出,对于进一步的图像分析或显示至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class InpaintWithModel: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'inpaint_model': ('INPAINT_MODEL',), 'image': ('IMAGE',), 'mask': ('MASK',)}} + RETURN_TYPES = ('IMAGE',) + CATEGORY = 'inpaint' + FUNCTION = 'inpaint' + + def inpaint(self, inpaint_model: PyTorchModel, image: Tensor, mask: Tensor): + if inpaint_model.model_arch == 'MAT': + required_size = 512 + elif inpaint_model.model_arch == 'LaMa': + required_size = 256 + else: + raise ValueError(f'Unknown model_arch {inpaint_model.model_arch}') + (image, mask) = to_torch(image, mask) + image_device = image.device + (original_image, original_mask) = (image, mask) + (image, mask, original_size) = resize_square(image, mask, required_size) + mask = mask.floor() + device = get_torch_device() + inpaint_model.to(device) + image = inpaint_model(image.to(device), mask.to(device)) + inpaint_model.cpu() + image = undo_resize_square(image.to(image_device), original_size) + image = original_image + (image - original_image) * original_mask.floor() + return (to_comfy(image),) +``` \ No newline at end of file diff --git a/docs/INPAINT_LoadFooocusInpaint.md b/docs/INPAINT_LoadFooocusInpaint.md new file mode 100644 index 0000000..c841bc9 --- /dev/null +++ b/docs/INPAINT_LoadFooocusInpaint.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: LoadFooocusInpaint +- Category: inpaint +- Output node: False +- Repo Ref: https://github.com/Acly/comfyui-inpaint-nodes + +该节点旨在加载并整合用于图像修复任务的两个关键组件:头部模型和补丁数据。它协调从保存的状态字典中加载头部模型和从指定文件中加载补丁数据的过程,确保这两个组件准备就绪,可用于图像修复过程。 + +# Input types +## Required +- head + - ‘head’参数指定头部模型的文件路径,这对于图像修复过程至关重要。它用于引导生成修复的内容。 + - Comfy dtype: str + - Python dtype: str +- patch + - ‘patch’参数表示补丁数据的文件路径,这对于图像修复任务是不可或缺的。它提供了模型理解待修复区域上下文所需的信息。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- INPAINT_PATCH + - 输出包含一对:已加载的头部模型和补丁数据。这些对于图像修复过程至关重要,因为它们提供了生成最终修复结果所需的结构和上下文信息。 + - Comfy dtype: COMBO[(torch.nn.Module, Any)] + - Python dtype: Tuple[torch.nn.Module, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadFooocusInpaint: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'head': (folder_paths.get_filename_list('inpaint'),), 'patch': (folder_paths.get_filename_list('inpaint'),)}} + RETURN_TYPES = ('INPAINT_PATCH',) + CATEGORY = 'inpaint' + FUNCTION = 'load' + + def load(self, head: str, patch: str): + head_file = folder_paths.get_full_path('inpaint', head) + inpaint_head_model = InpaintHead() + sd = torch.load(head_file, map_location='cpu') + inpaint_head_model.load_state_dict(sd) + patch_file = folder_paths.get_full_path('inpaint', patch) + inpaint_lora = comfy.utils.load_torch_file(patch_file, safe_load=True) + return ((inpaint_head_model, inpaint_lora),) +``` \ No newline at end of file diff --git a/docs/INPAINT_LoadInpaintModel.md b/docs/INPAINT_LoadInpaintModel.md new file mode 100644 index 0000000..a020284 --- /dev/null +++ b/docs/INPAINT_LoadInpaintModel.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: LoadInpaintModel +- Category: inpaint +- Output node: False +- Repo Ref: https://github.com/Acly/comfyui-inpaint-nodes + +LoadInpaintModel 类旨在方便加载修复模型,这些是专门用于填充图像中缺失或损坏部分的神经网络架构。它抽象了模型加载的复杂性,确保加载过程是流畅和可靠的。该节点的功能对于初始化修复过程至关重要,为进一步的图像操作提供了基础。 + +# Input types +## Required +- model_name + - 参数 'model_name' 非常重要,因为它标识了要加载的特定修复模型。它通过确定将用于修复任务的神经网络架构,影响节点的执行。正确的模型名称对于实现所需的图像恢复结果至关重要。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- INPAINT_MODEL + - 输出 'INPAINT_MODEL' 代表已加载的修复模型,可供后续图像处理任务使用。它封装了模型的已训练权重和架构,标志着加载过程的完成,并使模型能够执行其指定功能。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadInpaintModel: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model_name': (folder_paths.get_filename_list('inpaint'),)}} + RETURN_TYPES = ('INPAINT_MODEL',) + CATEGORY = 'inpaint' + FUNCTION = 'load' + + def load(self, model_name: str): + model_file = folder_paths.get_full_path('inpaint', model_name) + if model_file is None: + raise RuntimeError(f'Model file not found: {model_name}') + if model_file.endswith('.pt'): + sd = torch.jit.load(model_file, map_location='cpu').state_dict() + else: + sd = comfy.utils.load_torch_file(model_file, safe_load=True) + if 'synthesis.first_stage.conv_first.conv.resample_filter' in sd: + model = mat.load(sd) + else: + model = comfy_extras.chainner_models.model_loading.load_state_dict(sd) + model = model.eval() + return (model,) +``` \ No newline at end of file diff --git a/docs/INPAINT_MaskedBlur.md b/docs/INPAINT_MaskedBlur.md new file mode 100644 index 0000000..7365aa3 --- /dev/null +++ b/docs/INPAINT_MaskedBlur.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: MaskedBlur +- Category: inpaint +- Output node: False +- Repo Ref: https://github.com/Acly/comfyui-inpaint-nodes + +MaskedBlur 节点旨在使用复杂的图像修复技术填充图像中缺失或不需要的部分。它对遮罩区域应用选择性模糊,使它们与周围图像内容无缝融合。该节点特别适用于基于内容的图像编辑和修复。 + +# Input types +## Required +- image + - 将由节点处理的输入图像。它是图像修复操作的主要数据源,其质量直接影响最终结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 遮罩定义了图像中应该被模糊和填充的区域。它是一个关键参数,决定了图像的哪些部分将经历修复过程。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- blur + - 模糊参数控制应用于遮罩区域的模糊效果的程度。这是一个重要的设置,它影响填充区域与图像其余部分之间的过渡平滑度。 + - Comfy dtype: INT + - Python dtype: int +- falloff + - 衰减参数决定了模糊效果在遮罩区域边缘处减弱的速率。它用于创建从模糊到未模糊区域的更自然和渐进的过渡。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output_image + - 输出图像是图像修复过程的结果。它包含了原始图像,其中遮罩区域已填充并模糊以匹配周围区域。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MaskedBlur: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'mask': ('MASK',), 'blur': ('INT', {'default': 255, 'min': 3, 'max': 8191, 'step': 1}), 'falloff': ('INT', {'default': 0, 'min': 0, 'max': 8191, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + CATEGORY = 'inpaint' + FUNCTION = 'fill' + + def fill(self, image: Tensor, mask: Tensor, blur: int, falloff: int): + blur = make_odd(blur) + falloff = min(make_odd(falloff), blur - 2) + (image, mask) = to_torch(image, mask) + original = image.clone() + alpha = mask.floor() + if falloff > 0: + erosion = binary_erosion(alpha, falloff) + alpha = alpha * gaussian_blur(erosion, falloff) + alpha = alpha.repeat(1, 3, 1, 1) + image = gaussian_blur(image, blur) + image = original + (image - original) * alpha + return (to_comfy(image),) +``` \ No newline at end of file diff --git a/docs/INPAINT_MaskedFill.md b/docs/INPAINT_MaskedFill.md new file mode 100644 index 0000000..cf7e150 --- /dev/null +++ b/docs/INPAINT_MaskedFill.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: MaskedFill +- Category: inpaint +- Output node: False +- Repo Ref: https://github.com/Acly/comfyui-inpaint-nodes + +该节点通过使用不同的算法填充图像中缺失或遮蔽的区域,并与周围上下文相匹配,从而执行图像修复,使填充区域与原始图像无缝融合。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它提供了图像修复过程的基础输入。它是节点操作的主要数据,用于实现所需的图像修复效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 遮罩参数定义了需要进行图像修复的图像区域。它作为节点的指南,用于确定图像内容需要填充或修改的位置。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- fill + - 填充参数决定了要使用的图像修复方法,这对填充内容的质量和风格有重大影响。它对于实现期望的视觉结果至关重要。 + - Comfy dtype: COMBO[('neutral', 'telea', 'navier-stokes')] + - Python dtype: str +## Optional +- falloff + - 衰减参数通过控制侵蚀和模糊操作的半径来影响图像修复过渡的平滑度,从而决定了填充区域与原始图像的融合方式。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 输出图像是图像修复过程的结果,其中遮蔽区域已填充与周围上下文相匹配的内容,提供了一个无缝且视觉上连贯的最终图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MaskedFill: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'mask': ('MASK',), 'fill': (['neutral', 'telea', 'navier-stokes'],), 'falloff': ('INT', {'default': 0, 'min': 0, 'max': 8191, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + CATEGORY = 'inpaint' + FUNCTION = 'fill' + + def fill(self, image: Tensor, mask: Tensor, fill: str, falloff: int): + alpha = mask.expand(1, *mask.shape[-2:]).floor() + falloff = make_odd(falloff) + if falloff > 0: + erosion = binary_erosion(alpha, falloff) + alpha = alpha * gaussian_blur(erosion, falloff) + if fill == 'neutral': + image = image.detach().clone() + m = (1.0 - alpha).squeeze(1) + for i in range(3): + image[:, :, :, i] -= 0.5 + image[:, :, :, i] *= m + image[:, :, :, i] += 0.5 + else: + import cv2 + method = cv2.INPAINT_TELEA if fill == 'telea' else cv2.INPAINT_NS + alpha_np = alpha.squeeze(0).cpu().numpy() + alpha_bc = alpha_np.reshape(*alpha_np.shape, 1) + for slice in image: + image_np = slice.cpu().numpy() + filled_np = cv2.inpaint((255.0 * image_np).astype(np.uint8), (255.0 * alpha_np).astype(np.uint8), 3, method) + filled_np = filled_np.astype(np.float32) / 255.0 + filled_np = image_np * (1.0 - alpha_bc) + filled_np * alpha_bc + slice.copy_(torch.from_numpy(filled_np)) + return (image,) +``` \ No newline at end of file diff --git a/docs/INPAINT_VAEEncodeInpaintConditioning.md b/docs/INPAINT_VAEEncodeInpaintConditioning.md new file mode 100644 index 0000000..78bbf6f --- /dev/null +++ b/docs/INPAINT_VAEEncodeInpaintConditioning.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: VAEEncodeInpaintConditioning +- Category: inpaint +- Output node: False +- Repo Ref: https://github.com/Acly/comfyui-inpaint-nodes + +使用变分自编码器(VAE)将输入图像编码为潜在表示,特别适用于修复任务。此节点在生成过程中扮演关键角色,通过在正负样本上进行条件化编码,使模型能够学习到数据的更精细表示。 + +# Input types +## Required +- positive + - 正样本对于引导编码过程朝向期望结果至关重要。它们为模型提供了一个参考,说明了在修复任务的上下文中什么是“正”的或正确的状态。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- negative + - 负样本与正样本形成对比,帮助模型区分正确与不正确的表示。这对于完善模型的理解并提高修复结果的质量至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- vae + - VAE模型是负责将输入图像编码到潜在空间的核心组件。它是一个关键的输入,因为它直接影响编码过程的质量和准确性。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- pixels + - 像素数据构成了VAE模型的输入,对编码过程至关重要。正是通过这些像素,模型学习表示和重建视觉信息。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 掩码参数用于标识图像中需要修复的区域。它是一个关键组件,在编码过程中引导模型专注于图像的特定区域。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- positive + - 正输出代表正样本的条件潜在表示,用于进一步处理或作为修复任务的参考。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] +- negative + - 负输出对应于负样本的条件潜在表示,与正输出形成对比,并有助于区分正确的表示。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] +- latent_inpaint + - 潜在修复输出是一种特定类型的潜在表示,包括图像样本和噪声掩码,这对于修复过程至关重要。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- latent_samples + - 潜在样本输出提供了一组来自潜在空间的随机样本,可以用来生成新实例或进一步分析模型的编码能力。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class VAEEncodeInpaintConditioning: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'vae': ('VAE',), 'pixels': ('IMAGE',), 'mask': ('MASK',)}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING', 'LATENT', 'LATENT') + RETURN_NAMES = ('positive', 'negative', 'latent_inpaint', 'latent_samples') + FUNCTION = 'encode' + CATEGORY = 'inpaint' + + def encode(self, positive, negative, vae, pixels, mask): + (positive, negative, latent) = nodes.InpaintModelConditioning().encode(positive, negative, pixels, vae, mask) + latent_inpaint = dict(samples=positive[0][1]['concat_latent_image'], noise_mask=latent['noise_mask'].round()) + return (positive, negative, latent_inpaint, latent) +``` \ No newline at end of file diff --git a/docs/INTConstant.md b/docs/INTConstant.md new file mode 100644 index 0000000..e72a873 --- /dev/null +++ b/docs/INTConstant.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: INTConstant +- Category: KJNodes/constants +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +INTConstant节点旨在网络中提供一个常量整数值。当操作需要一个固定的整数时,如索引、阈值或任何需要常量值的场景,它都会被使用。此节点确保在执行过程中该值保持不变,提供一个稳定且可预测的整数引用。 + +# Input types +## Required +- value + - ‘value’参数是INTConstant节点的核心,代表将被输出的常量整数。它在节点操作中扮演着关键角色,因为它定义了要提供给网络的固定整数值。此参数的重要性在于其能够为各种计算任务提供一致且不变的整数引用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- value + - 来自INTConstant节点的‘value’输出是被设置为输入的常量整数。它作为网络中下游操作的固定整数的可靠来源,确保该值保持恒定,不受外部影响而改变。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class INTConstant: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'value': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('value',) + FUNCTION = 'get_value' + CATEGORY = 'KJNodes/constants' + + def get_value(self, value): + return (value,) +``` \ No newline at end of file diff --git a/docs/IPAdapterModelHelper %2F%2FInspire.md b/docs/IPAdapterModelHelper %2F%2FInspire.md new file mode 100644 index 0000000..749c8e5 --- /dev/null +++ b/docs/IPAdapterModelHelper %2F%2FInspire.md @@ -0,0 +1,166 @@ +# Documentation +- Class name: IPAdapterModelHelper +- Category: InspirePack/models +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +IPAdapterModelHelper节点是InspirePack套件中的一个关键组件,它促进了各种模型和预设的无缝集成和应用。它巧妙地管理了模型加载的复杂性并确保了兼容性,使用户能够以最小的摩擦力利用不同模型的强大功能。该节点旨在简化模型使用过程,为访问多样化功能提供统一的接口。 + +# Input types +## Required +- model + - 模型参数对于节点的操作至关重要,因为它定义了要使用的核心技术模型。它显著影响节点的执行和产生的结果质量,使其成为节点功能的一个基本方面。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - clip参数通过提供图像处理所需的上下文,在节点的功能中发挥着重要作用。它对于节点根据输入数据生成准确和相关的输出至关重要。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- preset + - 预设参数允许用户选择预定义的设置,将节点的行为调整为特定用例。它是根据用户需求定制节点操作的关键元素。 + - Comfy dtype: COMBO[list(model_preset.keys())] + - Python dtype: str +- lora_strength_model + - lora_strength_model参数调整LoRA模型对节点输出的影响。它是一个重要的调整因素,可以显著影响最终结果,允许对节点行为进行细粒度控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- lora_strength_clip + - lora_strength_clip参数微调CLIP模型对节点处理的影响。对于需要控制CLIP模型影响与其他因素之间平衡的用户来说,它是一个关键参数。 + - Comfy dtype: FLOAT + - Python dtype: float +- insightface_provider + - insightface_provider参数指定用于InsightFace模型的后端,这对于面部识别任务至关重要。这是一个重要的选择,可以影响节点的性能和与用户系统的兼容性。 + - Comfy dtype: COMBO[['CPU', 'CUDA', 'ROCM']] + - Python dtype: str +- cache_mode + - cache_mode参数确定节点的缓存策略,可以通过减少冗余操作来提高性能。对于优化节点的效率,这是一个重要的考虑因素。 + - Comfy dtype: COMBO[['insightface only', 'clip_vision only', 'all', 'none']] + - Python dtype: str +- unique_id + - unique_id参数用于在系统中跟踪和识别节点,这对于调试和管理节点的多个实例特别有用。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- IPADAPTER_PIPE + - IPADAPTER_PIPE输出是一个复合结构,封装了处理后的数据和模型,为进一步分析或利用提供了全面的流水线。 + - Comfy dtype: IPADAPTER_PIPE + - Python dtype: Tuple[torch.nn.Module, torch.Tensor, torch.Tensor, Any, Callable[[torch.nn.Module], torch.nn.Module]] +- IPADAPTER + - IPADAPTER输出代表已加载的IPAdapter模型,可用于后续图像处理任务中的应用。 + - Comfy dtype: IPADAPTER + - Python dtype: torch.nn.Module +- CLIP_VISION + - CLIP_VISION输出提供了已加载的CLIP模型,这对于从图像生成上下文嵌入至关重要。 + - Comfy dtype: CLIP_VISION + - Python dtype: torch.Tensor +- INSIGHTFACE + - INSIGHTFACE输出提供了InsightFace模型,该模型专门用于节点操作中的面部识别和分析。 + - Comfy dtype: INSIGHTFACE + - Python dtype: Any +- MODEL + - MODEL输出指的是已被节点增强或修改的主要模型,可供进一步处理或直接应用。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- CLIP + - CLIP输出表示处理过的CLIP数据,可用于涉及图像和文本交互的各种下游任务。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- insightface_cache_key + - insightface_cache_key输出是用于缓存InsightFace模型的唯一标识符,它优化了节点重复使用时的性能。 + - Comfy dtype: STRING + - Python dtype: str +- clip_vision_cache_key + - clip_vision_cache_key输出为CLIP Vision模型提供了一个用于缓存的唯一标识符,这有助于提高节点在重复任务中的效率。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class IPAdapterModelHelper: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'preset': (list(model_preset.keys()),), 'lora_strength_model': ('FLOAT', {'default': 1.0, 'min': -20.0, 'max': 20.0, 'step': 0.01}), 'lora_strength_clip': ('FLOAT', {'default': 1.0, 'min': -20.0, 'max': 20.0, 'step': 0.01}), 'insightface_provider': (['CPU', 'CUDA', 'ROCM'],), 'cache_mode': (['insightface only', 'clip_vision only', 'all', 'none'], {'default': 'insightface only'})}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('IPADAPTER_PIPE', 'IPADAPTER', 'CLIP_VISION', 'INSIGHTFACE', 'MODEL', 'CLIP', 'STRING', 'STRING') + RETURN_NAMES = ('IPADAPTER_PIPE', 'IPADAPTER', 'CLIP_VISION', 'INSIGHTFACE', 'MODEL', 'CLIP', 'insightface_cache_key', 'clip_vision_cache_key') + FUNCTION = 'doit' + CATEGORY = 'InspirePack/models' + + def doit(self, model, clip, preset, lora_strength_model, lora_strength_clip, insightface_provider, cache_mode='none', unique_id=None): + if 'IPAdapterApply' not in nodes.NODE_CLASS_MAPPINGS: + utils.try_install_custom_node('https://github.com/cubiq/ComfyUI_IPAdapter_plus', "To use 'IPAdapterModelHelper' node, 'ComfyUI IPAdapter Plus' extension is required.") + raise Exception(f"[ERROR] To use IPAdapterModelHelper, you need to install 'ComfyUI IPAdapter Plus'") + is_sdxl_preset = 'SDXL' in preset + is_sdxl_model = isinstance(clip.tokenizer, sdxl_clip.SDXLTokenizer) + if is_sdxl_preset != is_sdxl_model: + server.PromptServer.instance.send_sync('inspire-node-output-label', {'node_id': unique_id, 'output_idx': 1, 'label': 'IPADAPTER (fail)'}) + server.PromptServer.instance.send_sync('inspire-node-output-label', {'node_id': unique_id, 'output_idx': 2, 'label': 'CLIP_VISION (fail)'}) + server.PromptServer.instance.send_sync('inspire-node-output-label', {'node_id': unique_id, 'output_idx': 3, 'label': 'INSIGHTFACE (fail)'}) + server.PromptServer.instance.send_sync('inspire-node-output-label', {'node_id': unique_id, 'output_idx': 4, 'label': 'MODEL (fail)'}) + server.PromptServer.instance.send_sync('inspire-node-output-label', {'node_id': unique_id, 'output_idx': 5, 'label': 'CLIP (fail)'}) + print(f'[ERROR] IPAdapterModelHelper: You cannot mix SDXL and SD1.5 in the checkpoint and IPAdapter.') + raise Exception('[ERROR] You cannot mix SDXL and SD1.5 in the checkpoint and IPAdapter.') + (ipadapter, clipvision, lora, is_insightface) = model_preset[preset] + (ipadapter, ok1) = lookup_model('ipadapter', ipadapter) + (clipvision, ok2) = lookup_model('clip_vision', clipvision) + (lora, ok3) = lookup_model('loras', lora) + if ok1 == 'OK': + ok1 = 'IPADAPTER' + else: + ok1 = f'IPADAPTER ({ok1})' + if ok2 == 'OK': + ok2 = 'CLIP_VISION' + else: + ok2 = f'CLIP_VISION ({ok2})' + server.PromptServer.instance.send_sync('inspire-node-output-label', {'node_id': unique_id, 'output_idx': 1, 'label': ok1}) + server.PromptServer.instance.send_sync('inspire-node-output-label', {'node_id': unique_id, 'output_idx': 2, 'label': ok2}) + if ok3 == 'FAIL': + server.PromptServer.instance.send_sync('inspire-node-output-label', {'node_id': unique_id, 'output_idx': 4, 'label': 'MODEL (fail)'}) + server.PromptServer.instance.send_sync('inspire-node-output-label', {'node_id': unique_id, 'output_idx': 5, 'label': 'CLIP (fail)'}) + else: + server.PromptServer.instance.send_sync('inspire-node-output-label', {'node_id': unique_id, 'output_idx': 4, 'label': 'MODEL'}) + server.PromptServer.instance.send_sync('inspire-node-output-label', {'node_id': unique_id, 'output_idx': 5, 'label': 'CLIP'}) + if ok1 == 'FAIL' or ok2 == 'FAIL' or ok3 == 'FAIL': + raise Exception('ERROR: Failed to load several models in IPAdapterModelHelper.') + if ipadapter is not None: + ipadapter = nodes.NODE_CLASS_MAPPINGS['IPAdapterModelLoader']().load_ipadapter_model(ipadapter_file=ipadapter)[0] + ccache_key = '' + if clipvision is not None: + if cache_mode in ['clip_vision only', 'all']: + ccache_key = clipvision + if ccache_key not in backend_support.cache: + backend_support.cache[ccache_key] = (False, nodes.CLIPVisionLoader().load_clip(clip_name=clipvision)[0]) + clipvision = backend_support.cache[ccache_key][1] + else: + clipvision = nodes.CLIPVisionLoader().load_clip(clip_name=clipvision)[0] + if lora is not None: + (model, clip) = nodes.LoraLoader().load_lora(model=model, clip=clip, lora_name=lora, strength_model=lora_strength_model, strength_clip=lora_strength_clip) + + def f(x): + return nodes.LoraLoader().load_lora(model=x, clip=clip, lora_name=lora, strength_model=lora_strength_model, strength_clip=lora_strength_clip) + lora_loader = f + else: + + def f(x): + return x + lora_loader = f + icache_key = '' + if is_insightface: + if cache_mode in ['insightface only', 'all']: + icache_key = 'insightface-' + insightface_provider + if icache_key not in backend_support.cache: + backend_support.cache[icache_key] = (False, nodes.NODE_CLASS_MAPPINGS['InsightFaceLoader']().load_insight_face(insightface_provider)[0]) + insightface = backend_support.cache[icache_key][1] + else: + insightface = nodes.NODE_CLASS_MAPPINGS['InsightFaceLoader']().load_insight_face(insightface_provider)[0] + server.PromptServer.instance.send_sync('inspire-node-output-label', {'node_id': unique_id, 'output_idx': 3, 'label': 'INSIGHTFACE'}) + else: + insightface = None + server.PromptServer.instance.send_sync('inspire-node-output-label', {'node_id': unique_id, 'output_idx': 3, 'label': 'INSIGHTFACE (N/A)'}) + pipe = (ipadapter, model, clipvision, insightface, lora_loader) + return (pipe, ipadapter, clipvision, insightface, model, clip, icache_key, ccache_key) +``` \ No newline at end of file diff --git a/docs/Image Analyze.md b/docs/Image Analyze.md new file mode 100644 index 0000000..47b5080 --- /dev/null +++ b/docs/Image Analyze.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: WAS_Image_Analyze +- Category: WAS Suite/Image/Analyze +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Analyze节点旨在执行各种图像分析操作,包括黑白水平调整、RGB通道频率分析和无缝纹理生成。它是一个全面的工具,用于增强图像质量并为进一步处理或可视化准备图像。 + +# Input types +## Required +- image + - 输入图像是节点将处理的图像。它作为节点执行的所有分析和转换操作的基本数据。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- mode + - 模式参数确定要应用于输入图像的特定分析或转换。它影响节点的操作,指导其执行调整黑白水平或分析通道频率等任务。 + - Comfy dtype: COMBO['Black White Levels', 'RGB Levels'] + - Python dtype: str + +# Output types +- result_image + - 结果图像是节点分析或转换过程的输出。它包含了根据指定的模式和参数对输入图像所做的更改。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Analyze: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'mode': (['Black White Levels', 'RGB Levels'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_analyze' + CATEGORY = 'WAS Suite/Image/Analyze' + + def image_analyze(self, image, mode='Black White Levels'): + image = tensor2pil(image) + WTools = WAS_Tools_Class() + if mode: + if mode == 'Black White Levels': + image = WTools.black_white_levels(image) + elif mode == 'RGB Levels': + image = WTools.channel_frequency(image) + else: + image = image + return (pil2tensor(image),) +``` \ No newline at end of file diff --git a/docs/Image Aspect Ratio.md b/docs/Image Aspect Ratio.md new file mode 100644 index 0000000..b3c76f1 --- /dev/null +++ b/docs/Image Aspect Ratio.md @@ -0,0 +1,82 @@ +# Documentation +- Class name: WAS_Image_Aspect_Ratio +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Aspect_Ratio节点的`aspect`方法旨在计算并返回图像的多种比例表示形式。它确定图像是横屏还是竖屏模式,并以简化形式提供常见比例。此节点对于图像操作和分析任务至关重要,其中比例考虑是关键。 + +# Input types +## Optional +- image + - 'image'参数是一个可选输入,允许节点在没有提供显式尺寸时自动派生图像的宽度和高度。当提供图像张量时,它对于节点准确计算纵横比的能力至关重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- width + - 'width'参数是一个可选的数字输入,指定图像的宽度。当没有提供图像张量时,它与'height'参数一起用于计算纵横比。 + - Comfy dtype: NUMBER + - Python dtype: int +- height + - 'height'参数是一个可选的数字输入,指定图像的高度。与'width'参数一起,当没有提供图像张量时,它是确定纵横比所必需的。 + - Comfy dtype: NUMBER + - Python dtype: int + +# Output types +- aspect_number + - 'aspect_number'输出提供了图像的原始数字纵横比,计算为宽度除以高度。 + - Comfy dtype: NUMBER + - Python dtype: float +- aspect_float + - 'aspect_float'输出是纵横比的另一种表示形式,也是按宽度除以高度计算的,但作为浮点数返回。 + - Comfy dtype: FLOAT + - Python dtype: float +- is_landscape_bool + - 'is_landscape_bool'输出是一个布尔值,指示图像是否处于横屏模式。对于横屏返回1,对于竖屏或正方形纵横比返回0。 + - Comfy dtype: NUMBER + - Python dtype: int +- aspect_ratio_common + - 'aspect_ratio_common'输出以简化形式表示图像的常见纵横比,例如'16:9',这是从宽度和高度的最大公约数派生出来的。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str +- aspect_type + - 'aspect_type'输出根据计算出的纵横比值描述纵横比的类型,可以是'landscape'(横屏)、'portrait'(竖屏)或'square'(正方形)。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Aspect_Ratio: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'image': ('IMAGE',), 'width': ('NUMBER',), 'height': ('NUMBER',)}} + RETURN_TYPES = ('NUMBER', 'FLOAT', 'NUMBER', TEXT_TYPE, TEXT_TYPE) + RETURN_NAMES = ('aspect_number', 'aspect_float', 'is_landscape_bool', 'aspect_ratio_common', 'aspect_type') + FUNCTION = 'aspect' + CATEGORY = 'WAS Suite/Logic' + + def aspect(self, boolean=True, image=None, width=None, height=None): + if width and height: + width = width + height = height + elif image is not None: + (width, height) = tensor2pil(image).size + else: + raise Exception('WAS_Image_Aspect_Ratio must have width and height provided if no image tensori supplied.') + aspect_ratio = width / height + aspect_type = 'landscape' if aspect_ratio > 1 else 'portrait' if aspect_ratio < 1 else 'square' + landscape_bool = 0 + if aspect_type == 'landscape': + landscape_bool = 1 + gcd = math.gcd(width, height) + gcd_w = width // gcd + gcd_h = height // gcd + aspect_ratio_common = f'{gcd_w}:{gcd_h}' + return (aspect_ratio, aspect_ratio, landscape_bool, aspect_ratio_common, aspect_type) +``` \ No newline at end of file diff --git a/docs/Image Batch.md b/docs/Image Batch.md new file mode 100644 index 0000000..6b8d9dc --- /dev/null +++ b/docs/Image Batch.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: WAS_Image_Batch +- Category: WAS Suite/Image +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Batch节点旨在处理并批量处理多个图像以进行进一步操作。它确保所有输入图像具有匹配的尺寸,然后将它们合并成单个张量,从而促进批量高效处理图像数据。 + +# Input types +## Optional +- images_a + - 参数'images_a'用于提供要批量处理的一组图像。它在节点的操作中起着至关重要的作用,因为它直接影响将要处理的内容。 + - Comfy dtype: IMAGE + - Python dtype: Union[torch.Tensor, List[torch.Tensor]] +- images_b + - 参数'images_b'是批量中的可选图像源。它很重要,因为它允许将其他图像与'images_a'一起处理。 + - Comfy dtype: IMAGE + - Python dtype: Union[torch.Tensor, List[torch.Tensor]] +- images_c + - 参数'images_c'是另一个可选的图像输入,增强了节点的灵活性,以适应更多的图像数据进行批量处理。 + - Comfy dtype: IMAGE + - Python dtype: Union[torch.Tensor, List[torch.Tensor]] +- images_d + - 参数'images_d'提供了进一步的可选图像输入能力,允许节点在单个批量操作中处理更广泛的图像数组。 + - Comfy dtype: IMAGE + - Python dtype: Union[torch.Tensor, List[torch.Tensor]] + +# Output types +- image + - 'image'输出代表已处理和连接的图像张量。对于需要统一图像数据批次的下游任务至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Batch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'images_a': ('IMAGE',), 'images_b': ('IMAGE',), 'images_c': ('IMAGE',), 'images_d': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'image_batch' + CATEGORY = 'WAS Suite/Image' + + def _check_image_dimensions(self, tensors, names): + reference_dimensions = tensors[0].shape[1:] + mismatched_images = [names[i] for (i, tensor) in enumerate(tensors) if tensor.shape[1:] != reference_dimensions] + if mismatched_images: + raise ValueError(f'WAS Image Batch Warning: Input image dimensions do not match for images: {mismatched_images}') + + def image_batch(self, **kwargs): + batched_tensors = [kwargs[key] for key in kwargs if kwargs[key] is not None] + image_names = [key for key in kwargs if kwargs[key] is not None] + if not batched_tensors: + raise ValueError('At least one input image must be provided.') + self._check_image_dimensions(batched_tensors, image_names) + batched_tensors = torch.cat(batched_tensors, dim=0) + return (batched_tensors,) +``` \ No newline at end of file diff --git a/docs/Image Blank.md b/docs/Image Blank.md new file mode 100644 index 0000000..8065ce3 --- /dev/null +++ b/docs/Image Blank.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: WAS_Image_Blank +- Category: WAS Suite/Image +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Blank节点旨在生成具有指定大小和颜色的空白图像。它在创建进一步图像处理任务的视觉画布中发挥着关键作用。该节点对于初始化具有所需尺寸和颜色属性的图像至关重要,然后可以对图像进行操作或用作各种图像相关操作的起点。 + +# Input types +## Required +- width + - ‘width’参数定义了要生成的空白图像的宽度。这是一个基本属性,决定了图像的水平范围。‘width’对于设置图像的尺寸以及影响任何后续图像处理的整体组成和布局至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’参数设置了空白图像的垂直尺寸。它在定义图像的整体形状和结构方面与宽度同等重要。此参数确保生成的图像具有所需的垂直范围,这对于与其它视觉元素对齐或满足特定的显示要求很重要。 + - Comfy dtype: INT + - Python dtype: int +- red + - ‘red’参数指定了空白图像中红色通道的强度。它是决定图像整体颜色的关键组成部分。通过调整‘red’值,用户可以创建具有特定红色阴影的图像,这些图像可以用于各种目的,如背景颜色或颜色过滤。 + - Comfy dtype: INT + - Python dtype: int +- green + - ‘green’参数控制图像中绿色通道的强度。它与红色和蓝色参数协同工作,产生空白图像的最终颜色。‘green’值对于实现所需的颜色平衡和色调非常重要,这对于某些设计或视觉需求可能是必不可少的。 + - Comfy dtype: INT + - Python dtype: int +- blue + - ‘blue’参数决定蓝色通道的强度,有助于形成空白图像的整体颜色。它是颜色混合过程中的一个基本元素,允许用户微调图像的颜色以满足特定的视觉或审美标准。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - ‘IMAGE’输出提供了具有指定尺寸和颜色的生成空白图像。它为任何后续的图像操作或处理任务提供了基础层。这个输出很重要,因为它代表了节点功能的主要结果,准备用于下游工作流程。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Blank: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'width': ('INT', {'default': 512, 'min': 8, 'max': 4096, 'step': 1}), 'height': ('INT', {'default': 512, 'min': 8, 'max': 4096, 'step': 1}), 'red': ('INT', {'default': 255, 'min': 0, 'max': 255, 'step': 1}), 'green': ('INT', {'default': 255, 'min': 0, 'max': 255, 'step': 1}), 'blue': ('INT', {'default': 255, 'min': 0, 'max': 255, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'blank_image' + CATEGORY = 'WAS Suite/Image' + + def blank_image(self, width, height, red, green, blue): + width = width // 8 * 8 + height = height // 8 * 8 + blank = Image.new(mode='RGB', size=(width, height), color=(red, green, blue)) + return (pil2tensor(blank),) +``` \ No newline at end of file diff --git a/docs/Image Blend by Mask.md b/docs/Image Blend by Mask.md new file mode 100644 index 0000000..ef7df19 --- /dev/null +++ b/docs/Image Blend by Mask.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: WAS_Image_Blend_Mask +- Category: WAS Suite/Image +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Blend_Mask 节点旨在使用提供的遮罩和混合百分比无缝混合两张图像。它利用图像合成的能力,创建一个视觉上连贯的结果,其中一个图像的遮罩区域根据指定的混合级别被另一个图像的相应区域替换。 + +# Input types +## Required +- image_a + - 图像 A 是将与图像 B 混合的主图像。它是一个关键输入,因为它构成了最终合成图像的基础层。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- image_b + - 图像 B 是次要图像,其遮罩区域将被混合到图像 A 上。它通过将特定部分覆盖在基础图像上,从而对最终外观做出贡献。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- mask + - 遮罩是一个二进制图像,它定义了图像 B 的哪些部分应在最终混合中可见。它在确定要被图像 B 替换的图像 A 的区域方面起着关键作用。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +## Optional +- blend_percentage + - 混合百分比确定了图像 B 的遮罩区域与图像 A 混合的程度。它是一个可选参数,允许微调混合效果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- result_image + - 结果图像是混合过程的最终输出,它根据遮罩和混合百分比结合了图像 A 和图像 B。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Blend_Mask: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image_a': ('IMAGE',), 'image_b': ('IMAGE',), 'mask': ('IMAGE',), 'blend_percentage': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_blend_mask' + CATEGORY = 'WAS Suite/Image' + + def image_blend_mask(self, image_a, image_b, mask, blend_percentage): + img_a = tensor2pil(image_a) + img_b = tensor2pil(image_b) + mask = ImageOps.invert(tensor2pil(mask).convert('L')) + masked_img = Image.composite(img_a, img_b, mask.resize(img_a.size)) + blend_mask = Image.new(mode='L', size=img_a.size, color=round(blend_percentage * 255)) + blend_mask = ImageOps.invert(blend_mask) + img_result = Image.composite(img_a, masked_img, blend_mask) + del img_a, img_b, blend_mask, mask + return (pil2tensor(img_result),) +``` \ No newline at end of file diff --git a/docs/Image Blend.md b/docs/Image Blend.md new file mode 100644 index 0000000..1418f38 --- /dev/null +++ b/docs/Image Blend.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: WAS_Image_Blend +- Category: WAS Suite/Image +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Blend 节点的 'image_blend' 方法旨在将两张图片无缝融合。它通过利用 blend_percentage 参数控制融合的程度,创建一个视觉和谐的复合图像,反映出输入图片之间的平衡。 + +# Input types +## Required +- image_a + - 要混合的第一张图片。它在确定混合图像的初始视觉上下文方面起着至关重要的作用。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- image_b + - 要与第一张图片混合的第二张图片。它通过在基础图片上叠加视觉元素,为最终的外观做出贡献。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- blend_percentage + - blend_percentage 参数决定了在最终混合中 image_b 的可见度。它是一个浮点值,范围从 0.0 到 1.0,其中 0.0 表示只有 image_a 是可见的,而 1.0 表示只有 image_b 是可见的。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- image + - 输出是一个混合图像,根据指定的 blend_percentage 将两个输入图像的元素视觉地结合起来。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Blend: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image_a': ('IMAGE',), 'image_b': ('IMAGE',), 'blend_percentage': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'image_blend' + CATEGORY = 'WAS Suite/Image' + + def image_blend(self, image_a, image_b, blend_percentage): + img_a = tensor2pil(image_a) + img_b = tensor2pil(image_b) + blend_mask = Image.new(mode='L', size=img_a.size, color=round(blend_percentage * 255)) + blend_mask = ImageOps.invert(blend_mask) + img_result = Image.composite(img_a, img_b, blend_mask) + del img_a, img_b, blend_mask + return (pil2tensor(img_result),) +``` \ No newline at end of file diff --git a/docs/Image Blending Mode.md b/docs/Image Blending Mode.md new file mode 100644 index 0000000..652db88 --- /dev/null +++ b/docs/Image Blending Mode.md @@ -0,0 +1,95 @@ +# Documentation +- Class name: WAS_Image_Blending_Mode +- Category: WAS Suite/Image +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Blending_Mode 节点旨在使用各种混合模式将两张图像混合在一起,提供了一种多功能的方式来组合视觉元素。它强调图像处理的创造性方面,允许通过选择不同的混合技术实现广泛的效果。 + +# Input types +## Required +- image_a + - 图像A是将与图像B混合的第一个输入图像。它在确定混合结果的最终外观中起着至关重要的作用,因为它是被组合的主要视觉元素之一。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- image_b + - 图像B是将与图像A混合的第二个输入图像。它在影响最终输出方面同样重要,有助于整体外观和感觉的混合图像。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- mode + - 混合模式决定了图像A和图像B的颜色如何混合。每种模式都提供了不同的视觉效果,允许在混合过程中进行高度定制。 + - Comfy dtype: COMBO['add', 'color', 'color_burn', 'color_dodge', 'darken', 'difference', 'exclusion', 'hard_light', 'hue', 'lighten', 'multiply', 'overlay', 'screen', 'soft_light'] + - Python dtype: str +- blend_percentage + - 混合百分比控制混合效果的强度。它允许微调混合效果,从而可以实现两个图像的微妙或显著混合。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- image + - 输出图像是使用指定的混合模式和混合百分比混合图像A和图像B的结果。它封装了输入图像的组合视觉元素,反映了混合操作的创意意图。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Blending_Mode: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image_a': ('IMAGE',), 'image_b': ('IMAGE',), 'mode': (['add', 'color', 'color_burn', 'color_dodge', 'darken', 'difference', 'exclusion', 'hard_light', 'hue', 'lighten', 'multiply', 'overlay', 'screen', 'soft_light'],), 'blend_percentage': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'image_blending_mode' + CATEGORY = 'WAS Suite/Image' + + def image_blending_mode(self, image_a, image_b, mode='add', blend_percentage=1.0): + if 'pilgram' not in packages(): + install_package('pilgram') + import pilgram + img_a = tensor2pil(image_a) + img_b = tensor2pil(image_b) + if mode: + if mode == 'color': + out_image = pilgram.css.blending.color(img_a, img_b) + elif mode == 'color_burn': + out_image = pilgram.css.blending.color_burn(img_a, img_b) + elif mode == 'color_dodge': + out_image = pilgram.css.blending.color_dodge(img_a, img_b) + elif mode == 'darken': + out_image = pilgram.css.blending.darken(img_a, img_b) + elif mode == 'difference': + out_image = pilgram.css.blending.difference(img_a, img_b) + elif mode == 'exclusion': + out_image = pilgram.css.blending.exclusion(img_a, img_b) + elif mode == 'hard_light': + out_image = pilgram.css.blending.hard_light(img_a, img_b) + elif mode == 'hue': + out_image = pilgram.css.blending.hue(img_a, img_b) + elif mode == 'lighten': + out_image = pilgram.css.blending.lighten(img_a, img_b) + elif mode == 'multiply': + out_image = pilgram.css.blending.multiply(img_a, img_b) + elif mode == 'add': + out_image = pilgram.css.blending.normal(img_a, img_b) + elif mode == 'overlay': + out_image = pilgram.css.blending.overlay(img_a, img_b) + elif mode == 'screen': + out_image = pilgram.css.blending.screen(img_a, img_b) + elif mode == 'soft_light': + out_image = pilgram.css.blending.soft_light(img_a, img_b) + else: + out_image = img_a + out_image = out_image.convert('RGB') + blend_mask = Image.new(mode='L', size=img_a.size, color=round(blend_percentage * 255)) + blend_mask = ImageOps.invert(blend_mask) + out_image = Image.composite(img_a, out_image, blend_mask) + return (pil2tensor(out_image),) +``` \ No newline at end of file diff --git a/docs/Image Bloom Filter.md b/docs/Image Bloom Filter.md new file mode 100644 index 0000000..a378438 --- /dev/null +++ b/docs/Image Bloom Filter.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: WAS_Image_Bloom_Filter +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Bloom_Filter节点对图像应用了一种bloom效果,通过模拟光线的散射来增强其视觉吸引力。它调整图像的亮度以创建发光效果,这对于各种图像处理任务非常有用。 + +# Input types +## Required +- image + - 将应用bloom滤镜的输入图像。它是节点处理的主要对象,直接影响最终输出。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- radius + - 半径参数控制用于创建bloom效果的高斯模糊的范围。它是确定bloom柔和度的重要因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- intensity + - 强度参数调整bloom效果的亮度。较高的值会导致更明显的bloom,而较低的值则产生更微妙的效果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output_image + - output_image是应用了bloom滤镜的处理后的图像。它代表了节点操作的最终视觉结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Bloom_Filter: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'radius': ('FLOAT', {'default': 10, 'min': 0.0, 'max': 1024, 'step': 0.1}), 'intensity': ('FLOAT', {'default': 1, 'min': 0.0, 'max': 1.0, 'step': 0.1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_bloom' + CATEGORY = 'WAS Suite/Image/Filter' + + def image_bloom(self, image, radius=0.5, intensity=1.0): + return (pil2tensor(self.apply_bloom_filter(tensor2pil(image), radius, intensity)),) + + def apply_bloom_filter(self, input_image, radius, bloom_factor): + blurred_image = input_image.filter(ImageFilter.GaussianBlur(radius=radius)) + high_pass_filter = ImageChops.subtract(input_image, blurred_image) + bloom_filter = high_pass_filter.filter(ImageFilter.GaussianBlur(radius=radius * 2)) + bloom_filter = ImageEnhance.Brightness(bloom_filter).enhance(2.0) + bloom_filter = ImageChops.multiply(bloom_filter, Image.new('RGB', input_image.size, (int(255 * bloom_factor), int(255 * bloom_factor), int(255 * bloom_factor)))) + blended_image = ImageChops.screen(input_image, bloom_filter) + return blended_image +``` \ No newline at end of file diff --git a/docs/Image Bounds to Console.md b/docs/Image Bounds to Console.md new file mode 100644 index 0000000..7d1fe5c --- /dev/null +++ b/docs/Image Bounds to Console.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: WAS_Image_Bounds_to_Console +- Category: WAS Suite/Debug +- Output node: True +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Bounds_to_Console节点旨在通过将图像边界信息输出到控制台来促进调试过程。它通过提供清晰、格式化的边界显示,增强了图像处理阶段的可见性,有助于分析和验证图像操作工作流程。 + +# Input types +## Required +- image_bounds + - image_bounds参数对于节点的操作至关重要,因为它定义了图像内的兴趣区域。它用于识别和隔离图像的特定部分以进行进一步处理或分析,因此在节点的执行和它产生的结果中扮演着重要角色。 + - Comfy dtype: IMAGE_BOUNDS + - Python dtype: List[Tuple[int, int, int, int]] +## Optional +- label + - label参数作为调试输出的描述性标识符。虽然不是强制性的,但它可以用来自定义控制台输出,使其更容易区分不同的调试消息,在复杂的调试场景中特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- image_bounds + - 输出的image_bounds参数保留了输入的图像边界数据,确保调试信息在控制台输出中准确反映。这个参数很重要,因为它允许在节点处理后验证图像边界。 + - Comfy dtype: IMAGE_BOUNDS + - Python dtype: List[Tuple[int, int, int, int]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Bounds_to_Console: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image_bounds': ('IMAGE_BOUNDS',), 'label': ('STRING', {'default': 'Debug to Console', 'multiline': False})}} + RETURN_TYPES = ('IMAGE_BOUNDS',) + OUTPUT_NODE = True + FUNCTION = 'debug_to_console' + CATEGORY = 'WAS Suite/Debug' + + def debug_to_console(self, image_bounds, label): + label_out = 'Debug to Console' + if label.strip() != '': + label_out = label + bounds_out = 'Empty' + if len(bounds_out) > 0: + bounds_out = ', \n '.join(('\t(rmin={}, rmax={}, cmin={}, cmax={})'.format(a, b, c, d) for (a, b, c, d) in image_bounds)) + cstr(f'\x1b[33m{label_out}\x1b[0m:\n[\n{bounds_out}\n]\n').msg.print() + return (image_bounds,) + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') +``` \ No newline at end of file diff --git a/docs/Image Bounds.md b/docs/Image Bounds.md new file mode 100644 index 0000000..0662e14 --- /dev/null +++ b/docs/Image Bounds.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: WAS_Image_Bounds +- Category: WAS Suite/Image/Bound +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Bounds 节点的 `image_bounds` 方法旨在计算图像的边界,提供用于各种图像处理任务的基本空间信息。它确保在确定图像边界之前正确格式化图像,从而可以准确执行后续操作。 + +# Input types +## Required +- image + - 'image' 参数对于节点的操作至关重要,因为它是节点将处理以确定边界的数据源。它是节点功能构建的基础,没有它,节点无法执行其预定任务。 + - Comfy dtype: IMAGE + - Python dtype: Union[torch.Tensor, PIL.Image.Image] + +# Output types +- image_bounds + - 'image_bounds' 输出提供了定义输入图像边界的空间坐标。这些信息对于需要空间感知的任务至关重要,例如裁剪、调整大小或在图像内定位元素。 + - Comfy dtype: COMBO[Tuple[int, int, int, int]] + - Python dtype: List[Tuple[int, int, int, int]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Bounds: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + return {'required': {'image': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE_BOUNDS',) + FUNCTION = 'image_bounds' + CATEGORY = 'WAS Suite/Image/Bound' + + def image_bounds(self, image): + image = image.unsqueeze(0) if image.dim() == 3 else image + return ([(0, img.shape[0] - 1, 0, img.shape[1] - 1) for img in image],) +``` \ No newline at end of file diff --git a/docs/Image Canny Filter.md b/docs/Image Canny Filter.md new file mode 100644 index 0000000..840e725 --- /dev/null +++ b/docs/Image Canny Filter.md @@ -0,0 +1,118 @@ +# Documentation +- Class name: WAS_Canny_Filter +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Canny_Filter 节点旨在对输入图像应用Canny边缘检测算法,增强图像数据中边缘的可见性。它通过使用包括高斯模糊、梯度计算和阈值处理的多阶段算法来处理每个图像,以识别和突出重要边缘。 + +# Input types +## Required +- images + - ‘images’参数至关重要,因为它是Canny边缘检测过程的输入。它是节点将处理以识别和增强边缘的原始图像数据。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- enable_threshold + - ‘enable_threshold’参数决定是否在Canny算法中应用阈值步骤。这对于控制边缘检测的灵敏度很重要。 + - Comfy dtype: COMBO['false', 'true'] + - Python dtype: str +- threshold_low + - ‘threshold_low’参数设置边缘检测的下限阈值。它是决定哪些边缘足够强以包含在最终输出中的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- threshold_high + - ‘threshold_high’参数设置边缘检测的上限阈值。它与下限阈值一起工作,以微调边缘检测过程。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- images + - ‘images’输出参数包含使用Canny滤波器突出显示边缘的已处理图像。这个输出很重要,因为它代表了边缘检测操作的最终结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Canny_Filter: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'enable_threshold': (['false', 'true'],), 'threshold_low': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'threshold_high': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('images',) + FUNCTION = 'canny_filter' + CATEGORY = 'WAS Suite/Image/Filter' + + def canny_filter(self, images, threshold_low, threshold_high, enable_threshold): + if enable_threshold == 'false': + threshold_low = None + threshold_high = None + batch_tensor = [] + for image in images: + image_canny = Image.fromarray(self.Canny_detector(255.0 * image.cpu().numpy().squeeze(), threshold_low, threshold_high)).convert('RGB') + batch_tensor.append(pil2tensor(image_canny)) + batch_tensor = torch.cat(batch_tensor, dim=0) + return (pil2tensor(image_canny),) + + def Canny_detector(self, img, weak_th=None, strong_th=None): + import cv2 + img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + img = cv2.GaussianBlur(img, (5, 5), 1.4) + gx = cv2.Sobel(np.float32(img), cv2.CV_64F, 1, 0, 3) + gy = cv2.Sobel(np.float32(img), cv2.CV_64F, 0, 1, 3) + (mag, ang) = cv2.cartToPolar(gx, gy, angleInDegrees=True) + mag_max = np.max(mag) + if not weak_th: + weak_th = mag_max * 0.1 + if not strong_th: + strong_th = mag_max * 0.5 + (height, width) = img.shape + for i_x in range(width): + for i_y in range(height): + grad_ang = ang[i_y, i_x] + grad_ang = abs(grad_ang - 180) if abs(grad_ang) > 180 else abs(grad_ang) + (neighb_1_x, neighb_1_y) = (-1, -1) + (neighb_2_x, neighb_2_y) = (-1, -1) + if grad_ang <= 22.5: + (neighb_1_x, neighb_1_y) = (i_x - 1, i_y) + (neighb_2_x, neighb_2_y) = (i_x + 1, i_y) + elif grad_ang > 22.5 and grad_ang <= 22.5 + 45: + (neighb_1_x, neighb_1_y) = (i_x - 1, i_y - 1) + (neighb_2_x, neighb_2_y) = (i_x + 1, i_y + 1) + elif grad_ang > 22.5 + 45 and grad_ang <= 22.5 + 90: + (neighb_1_x, neighb_1_y) = (i_x, i_y - 1) + (neighb_2_x, neighb_2_y) = (i_x, i_y + 1) + elif grad_ang > 22.5 + 90 and grad_ang <= 22.5 + 135: + (neighb_1_x, neighb_1_y) = (i_x - 1, i_y + 1) + (neighb_2_x, neighb_2_y) = (i_x + 1, i_y - 1) + elif grad_ang > 22.5 + 135 and grad_ang <= 22.5 + 180: + (neighb_1_x, neighb_1_y) = (i_x - 1, i_y) + (neighb_2_x, neighb_2_y) = (i_x + 1, i_y) + if width > neighb_1_x >= 0 and height > neighb_1_y >= 0: + if mag[i_y, i_x] < mag[neighb_1_y, neighb_1_x]: + mag[i_y, i_x] = 0 + continue + if width > neighb_2_x >= 0 and height > neighb_2_y >= 0: + if mag[i_y, i_x] < mag[neighb_2_y, neighb_2_x]: + mag[i_y, i_x] = 0 + weak_ids = np.zeros_like(img) + strong_ids = np.zeros_like(img) + ids = np.zeros_like(img) + for i_x in range(width): + for i_y in range(height): + grad_mag = mag[i_y, i_x] + if grad_mag < weak_th: + mag[i_y, i_x] = 0 + elif strong_th > grad_mag >= weak_th: + ids[i_y, i_x] = 1 + else: + ids[i_y, i_x] = 2 + return mag +``` \ No newline at end of file diff --git a/docs/Image Caption.md b/docs/Image Caption.md new file mode 100644 index 0000000..1e370be --- /dev/null +++ b/docs/Image Caption.md @@ -0,0 +1,128 @@ +# Documentation +- Class name: ImageCaption +- Category: Mikey/Image +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +ImageCaption节点旨在生成并叠加图像上的标题。它接受一个图像、一个字体和一个标题字符串作为输入,并输出一个在原始图像下方带有包装标题文本的图像。这个节点特别适用于创建带有描述性标题的注释图像或社交媒体帖子。 + +# Input types +## Required +- image + - 图像参数是将要添加标题的基础图像。这是一个关键组件,因为整个标题过程在视觉上是锚定在这张图像上的。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- font + - 字体参数指定用于标题文本的字体类型。它影响文本的风格和可读性,这对于标题在传达信息方面的有效性至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- caption + - 标题参数是将要放置在图像上的文本。它是一个核心元素,因为它提供了伴随图像的描述性或解释性内容。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- extra_pnginfo + - extra_pnginfo参数用于提供某些操作可能需要的额外信息,例如元数据或标题过程的特定指令。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: dict +- prompt + - 提示参数用于指导标题过程,可能通过提供上下文或节点在生成标题时应遵循的特定指令。 + - Comfy dtype: PROMPT + - Python dtype: dict + +# Output types +- image + - 输出图像是标题过程的结果,其中包括添加了标题文本的原始图像。这是最终产品,可以用于展示或进一步处理。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageCaption: + + @classmethod + def INPUT_TYPES(cls): + if os.path.exists(os.path.join(folder_paths.base_path, 'fonts')): + cls.font_dir = os.path.join(folder_paths.base_path, 'fonts') + cls.font_files = [os.path.join(cls.font_dir, f) for f in os.listdir(cls.font_dir) if os.path.isfile(os.path.join(cls.font_dir, f))] + cls.font_file_names = [os.path.basename(f) for f in cls.font_files] + return {'required': {'image': ('IMAGE',), 'font': (cls.font_file_names, {'default': cls.font_file_names[0]}), 'caption': ('STRING', {'multiline': True, 'default': 'Caption'})}, 'hidden': {'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + else: + cls.font_dir = None + cls.font_files = None + cls.font_file_names = None + return {'required': {'image': ('IMAGE',), 'font': ('STRING', {'default': 'Path to font file'}), 'caption': ('STRING', {'multiline': True, 'default': 'Caption'})}, 'hidden': {'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'caption' + CATEGORY = 'Mikey/Image' + + def get_text_size(self, font, text): + """ + Get width and height of a text string with given font. + + Parameters: + font (ImageFont.FreeTypeFont): A font object. + text (str): Text to measure. + + Returns: + (int, int): Width and height of the text. + """ + (left, top, right, bottom) = font.getbbox(text) + width = right - left + height = bottom - top + return (width, height) + + def wrap_text(self, text, font, max_width): + """Wrap text to fit inside a specified width when rendered.""" + wrapped_lines = [] + for line in text.split('\n'): + words = line.split(' ') + new_line = words[0] + for word in words[1:]: + if int(font.getlength(new_line + ' ' + word)) <= max_width: + new_line += ' ' + word + else: + wrapped_lines.append(new_line) + new_line = word + wrapped_lines.append(new_line) + return wrapped_lines + + @apply_to_batch + def caption(self, image, font, caption, extra_pnginfo=None, prompt=None): + if extra_pnginfo is None: + extra_pnginfo = {} + caption = search_and_replace(caption, extra_pnginfo, prompt) + orig_image = tensor2pil(image) + (width, height) = orig_image.size + if self.font_dir is None: + font_file = font + if not os.path.isfile(font_file): + raise Exception('Font file does not exist: ' + font_file) + else: + font_file = os.path.join(self.font_dir, font) + font = ImageFont.truetype(font_file, 32) + max_width = width + wrapped_lines = self.wrap_text(caption, font, max_width) + (_, text_height) = self.get_text_size(font, 'Hg') + wrapped_text_height = len(wrapped_lines) * text_height + padding = 15 + caption_height = wrapped_text_height + padding * 2 + text_image = Image.new('RGB', (width, caption_height), (0, 0, 0)) + draw = ImageDraw.Draw(text_image) + line_spacing = 5 + y_position = padding + for line in wrapped_lines: + text_width = font.getlength(line) + x_position = (width - int(text_width)) // 2 + draw.text((x_position, y_position), line, (255, 255, 255), font=font) + (_, text_height) = self.get_text_size(font, line) + y_position += text_height + line_spacing + combined_image = Image.new('RGB', (width, height + caption_height + line_spacing), (0, 0, 0)) + combined_image.paste(text_image, (0, height)) + combined_image.paste(orig_image, (0, 0)) + return pil2tensor(combined_image) +``` \ No newline at end of file diff --git a/docs/Image Chromatic Aberration.md b/docs/Image Chromatic Aberration.md new file mode 100644 index 0000000..b6daf18 --- /dev/null +++ b/docs/Image Chromatic Aberration.md @@ -0,0 +1,116 @@ +# Documentation +- Class name: WAS_Image_Chromatic_Aberration +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Chromatic_Aberration节点旨在对输入图像应用色差效果,模拟由于镜头未能将所有颜色聚焦在同一点而导致图像边缘颜色模糊的光学现象。这种效果可以为图像添加独特的视觉风格,通常在摄影和电影中用于创造特定的美学效果。 + +# Input types +## Required +- image + - 图像参数是节点的核心输入,代表将应用色差效果的图像。这张图像的质量和特性直接影响最终输出,决定了色差的范围和外观。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- red_offset + - red_offset参数允许调整红色通道的偏移量,通过移动图像的红色分量来创建色差效果。它是实现所需视觉失真的重要部分。 + - Comfy dtype: INT + - Python dtype: int +- green_offset + - green_offset参数用于微调绿色通道对色差的贡献。通过调整此值,节点可以控制绿色在图像中的模糊方式。 + - Comfy dtype: INT + - Python dtype: int +- blue_offset + - blue_offset参数决定了蓝色通道在色差过程中的位移。这对于控制蓝色在失真图像中的扩散程度至关重要。 + - Comfy dtype: INT + - Python dtype: int +- intensity + - 强度参数控制色差效果的强度。较高的值将产生更明显的效应,而较低的值将产生更微妙的失真。 + - Comfy dtype: FLOAT + - Python dtype: float +- fade_radius + - fade_radius参数定义了图像边缘的淡出效果半径。它有助于在色差和未失真的图像中心之间创建平滑的过渡。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 输出图像是将色差效果应用于输入图像后的结果。它反映了调整后的偏移量和强度,提供了原始图像的创造性失真版本。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Chromatic_Aberration: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'red_offset': ('INT', {'default': 2, 'min': -255, 'max': 255, 'step': 1}), 'green_offset': ('INT', {'default': -1, 'min': -255, 'max': 255, 'step': 1}), 'blue_offset': ('INT', {'default': 1, 'min': -255, 'max': 255, 'step': 1}), 'intensity': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'fade_radius': ('INT', {'default': 12, 'min': 0, 'max': 1024, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_chromatic_aberration' + CATEGORY = 'WAS Suite/Image/Filter' + + def image_chromatic_aberration(self, image, red_offset=4, green_offset=2, blue_offset=0, intensity=1, fade_radius=12): + return (pil2tensor(self.apply_chromatic_aberration(tensor2pil(image), red_offset, green_offset, blue_offset, intensity, fade_radius)),) + + def apply_chromatic_aberration(self, img, r_offset, g_offset, b_offset, intensity, fade_radius): + + def lingrad(size, direction, white_ratio): + image = Image.new('RGB', size) + draw = ImageDraw.Draw(image) + if direction == 'vertical': + black_end = size[1] - white_ratio + range_start = 0 + range_end = size[1] + range_step = 1 + for y in range(range_start, range_end, range_step): + color_ratio = y / size[1] + if y <= black_end: + color = (0, 0, 0) + else: + color_value = int((y - black_end) / (size[1] - black_end) * 255) + color = (color_value, color_value, color_value) + draw.line([(0, y), (size[0], y)], fill=color) + elif direction == 'horizontal': + black_end = size[0] - white_ratio + range_start = 0 + range_end = size[0] + range_step = 1 + for x in range(range_start, range_end, range_step): + color_ratio = x / size[0] + if x <= black_end: + color = (0, 0, 0) + else: + color_value = int((x - black_end) / (size[0] - black_end) * 255) + color = (color_value, color_value, color_value) + draw.line([(x, 0), (x, size[1])], fill=color) + return image.convert('L') + + def create_fade_mask(size, fade_radius): + mask = Image.new('L', size, 255) + left = ImageOps.invert(lingrad(size, 'horizontal', int(fade_radius * 2))) + right = left.copy().transpose(Image.FLIP_LEFT_RIGHT) + top = ImageOps.invert(lingrad(size, 'vertical', int(fade_radius * 2))) + bottom = top.copy().transpose(Image.FLIP_TOP_BOTTOM) + mask = ImageChops.multiply(mask, left) + mask = ImageChops.multiply(mask, right) + mask = ImageChops.multiply(mask, top) + mask = ImageChops.multiply(mask, bottom) + mask = ImageChops.multiply(mask, mask) + return mask + (r, g, b) = img.split() + r_offset_img = ImageChops.offset(r, r_offset, 0) + g_offset_img = ImageChops.offset(g, 0, g_offset) + b_offset_img = ImageChops.offset(b, 0, b_offset) + merged = Image.merge('RGB', (r_offset_img, g_offset_img, b_offset_img)) + fade_mask = create_fade_mask(img.size, fade_radius) + result = Image.composite(merged, img, fade_mask).convert('RGB') + return result +``` \ No newline at end of file diff --git a/docs/Image Color Palette.md b/docs/Image Color Palette.md new file mode 100644 index 0000000..75af216 --- /dev/null +++ b/docs/Image Color Palette.md @@ -0,0 +1,75 @@ +# Documentation +- Class name: WAS_Image_Color_Palette +- Category: WAS Suite/Image/Analyze +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Color_Palette 节点旨在分析和处理图像数据以生成颜色调色板。它接受一个图像作为输入,并返回一个转换后的图像以及从原始图像中提取的颜色调色板列表。该节点特别适用于需要从图像中提取和表示颜色数据的应用场景,例如设计、图像编辑或任何需要图像颜色数据的过程。 + +# Input types +## Required +- image + - 要生成颜色调色板的输入图像。该图像将由节点处理以提取颜色信息并创建调色板的视觉表示。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +## Optional +- colors + - 生成调色板中要包含的颜色数量。它提供了一种控制从图像派生的颜色方案的粒度的方法。 + - Comfy dtype: INT + - Python dtype: int +- mode + - 颜色调色板的显示模式。它决定了调色板的视觉展示方式,提供了诸如图表或背靠背排列的选项。 + - Comfy dtype: COMBO['Chart', 'back_to_back'] + - Python dtype: str + +# Output types +- image + - 转换后的图像,其中颜色调色板根据输入图像和提供的参数以视觉方式嵌入或更改。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- color_palettes + - 从输入图像中提取的颜色调色板列表。列表中的每个条目代表一个颜色,以字符串十六进制代码的形式表示。 + - Comfy dtype: LIST + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Color_Palette: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'colors': ('INT', {'default': 16, 'min': 8, 'max': 256, 'step': 1}), 'mode': (['Chart', 'back_to_back'],)}} + RETURN_TYPES = ('IMAGE', 'LIST') + RETURN_NAMES = ('image', 'color_palettes') + FUNCTION = 'image_generate_palette' + CATEGORY = 'WAS Suite/Image/Analyze' + + def image_generate_palette(self, image, colors=16, mode='chart'): + WTools = WAS_Tools_Class() + res_dir = os.path.join(WAS_SUITE_ROOT, 'res') + font = os.path.join(res_dir, 'font.ttf') + if not os.path.exists(font): + font = None + elif mode == 'Chart': + cstr(f'Found font at `{font}`').msg.print() + if len(image) > 1: + palette_strings = [] + palette_images = [] + for img in image: + img = tensor2pil(img) + (palette_image, palette) = WTools.generate_palette(img, colors, 128, 10, font, 15, mode.lower()) + palette_images.append(pil2tensor(palette_image)) + palette_strings.append(palette) + palette_images = torch.cat(palette_images, dim=0) + return (palette_images, palette_strings) + else: + image = tensor2pil(image) + (palette_image, palette) = WTools.generate_palette(image, colors, 128, 10, font, 15, mode.lower()) + return (pil2tensor(palette_image), [palette]) +``` \ No newline at end of file diff --git a/docs/Image Compare (mtb).md b/docs/Image Compare (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Image Crop Face.md b/docs/Image Crop Face.md new file mode 100644 index 0000000..e2176b3 --- /dev/null +++ b/docs/Image Crop Face.md @@ -0,0 +1,127 @@ +# Documentation +- Class name: WAS_Image_Crop_Face +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Crop_Face 节点旨在智能检测并裁剪图像中的面部。它使用预定义的级联分类器来定位面部,并允许围绕检测到的面部区域进行填充调整。该节点能够处理各种面部检测场景,并返回一个裁剪后的面部图像以及原始图像大小和裁剪坐标。 + +# Input types +## Required +- image + - 输入图像,将从中检测并裁剪面部。这是一个强制性参数,因为节点的操作基本上依赖于图像的存在。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- crop_padding_factor + - 填充因子决定了围绕检测到的面部的填充量。填充因子为0.25意味着将面部大小的25%用作填充。这是可选的,如果没有提供,默认为0.25。 + - Comfy dtype: FLOAT + - Python dtype: float +- cascade_xml + - 用于面部检测的级联XML文件。如果使用第一个XML文件未检测到面部,节点将尝试使用多个级联文件。该参数是可选的,如果没有指定,节点将使用默认的级联文件。 + - Comfy dtype: COMBO[lbpcascade_animeface.xml, haarcascade_frontalface_default.xml, haarcascade_frontalface_alt.xml, haarcascade_frontalface_alt2.xml, haarcascade_frontalface_alt_tree.xml, haarcascade_profileface.xml, haarcascade_upperbody.xml] + - Python dtype: str + +# Output types +- cropped_face_image + - 输出是裁剪后的面部图像,根据需要进行了调整大小和填充,从输入图像中提取。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- crop_data + - 此输出提供有关面部裁剪的元数据,包括图像中面部的原始大小和裁剪框的坐标。 + - Comfy dtype: COMBO[original_size, (left, top, right, bottom)] + - Python dtype: Tuple[Tuple[int, int], Tuple[int, int, int, int]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Crop_Face: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'crop_padding_factor': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 2.0, 'step': 0.01}), 'cascade_xml': (['lbpcascade_animeface.xml', 'haarcascade_frontalface_default.xml', 'haarcascade_frontalface_alt.xml', 'haarcascade_frontalface_alt2.xml', 'haarcascade_frontalface_alt_tree.xml', 'haarcascade_profileface.xml', 'haarcascade_upperbody.xml', 'haarcascade_eye.xml'],)}} + RETURN_TYPES = ('IMAGE', 'CROP_DATA') + FUNCTION = 'image_crop_face' + CATEGORY = 'WAS Suite/Image/Process' + + def image_crop_face(self, image, cascade_xml=None, crop_padding_factor=0.25): + return self.crop_face(tensor2pil(image), cascade_xml, crop_padding_factor) + + def crop_face(self, image, cascade_name=None, padding=0.25): + import cv2 + img = np.array(image.convert('RGB')) + face_location = None + cascades = [os.path.join(os.path.join(WAS_SUITE_ROOT, 'res'), 'lbpcascade_animeface.xml'), os.path.join(os.path.join(WAS_SUITE_ROOT, 'res'), 'haarcascade_frontalface_default.xml'), os.path.join(os.path.join(WAS_SUITE_ROOT, 'res'), 'haarcascade_frontalface_alt.xml'), os.path.join(os.path.join(WAS_SUITE_ROOT, 'res'), 'haarcascade_frontalface_alt2.xml'), os.path.join(os.path.join(WAS_SUITE_ROOT, 'res'), 'haarcascade_frontalface_alt_tree.xml'), os.path.join(os.path.join(WAS_SUITE_ROOT, 'res'), 'haarcascade_profileface.xml'), os.path.join(os.path.join(WAS_SUITE_ROOT, 'res'), 'haarcascade_upperbody.xml')] + if cascade_name: + for cascade in cascades: + if os.path.basename(cascade) == cascade_name: + cascades.remove(cascade) + cascades.insert(0, cascade) + break + faces = None + if not face_location: + for cascade in cascades: + if not os.path.exists(cascade): + cstr(f'Unable to find cascade XML file at `{cascade}`. Did you pull the latest files from https://github.com/WASasquatch/was-node-suite-comfyui repo?').error.print() + return (pil2tensor(Image.new('RGB', (512, 512), (0, 0, 0))), False) + face_cascade = cv2.CascadeClassifier(cascade) + gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5) + if len(faces) != 0: + cstr(f'Face found with: {os.path.basename(cascade)}').msg.print() + break + if len(faces) == 0: + cstr('No faces found in the image!').warning.print() + return (pil2tensor(Image.new('RGB', (512, 512), (0, 0, 0))), False) + else: + cstr('Face found with: face_recognition model').warning.print() + faces = face_location + (x, y, w, h) = faces[0] + left_adjust = max(0, -x) + right_adjust = max(0, x + w - img.shape[1]) + top_adjust = max(0, -y) + bottom_adjust = max(0, y + h - img.shape[0]) + if left_adjust < w: + x += right_adjust + elif right_adjust < w: + x -= left_adjust + if top_adjust < h: + y += bottom_adjust + elif bottom_adjust < h: + y -= top_adjust + w -= left_adjust + right_adjust + h -= top_adjust + bottom_adjust + face_size = min(h, w) + y_pad = int(face_size * padding) + x_pad = int(face_size * padding) + center_x = x + w // 2 + center_y = y + h // 2 + half_size = (face_size + max(x_pad, y_pad)) // 2 + top = max(0, center_y - half_size) + bottom = min(img.shape[0], center_y + half_size) + left = max(0, center_x - half_size) + right = min(img.shape[1], center_x + half_size) + crop_size = min(right - left, bottom - top) + left = center_x - crop_size // 2 + right = center_x + crop_size // 2 + top = center_y - crop_size // 2 + bottom = center_y + crop_size // 2 + face_img = img[top:bottom, left:right, :] + size = max(face_img.copy().shape[:2]) + pad_h = (size - face_img.shape[0]) // 2 + pad_w = (size - face_img.shape[1]) // 2 + face_img = cv2.copyMakeBorder(face_img, pad_h, pad_h, pad_w, pad_w, cv2.BORDER_CONSTANT, value=[0, 0, 0]) + min_size = 64 + if size < min_size: + size = min_size + face_img = cv2.resize(face_img, (size, size)) + face_img = Image.fromarray(face_img) + original_size = face_img.size + face_img.resize((face_img.size[0] // 64 * 64 + 64, face_img.size[1] // 64 * 64 + 64)) + return (pil2tensor(face_img.convert('RGB')), (original_size, (left, top, right, bottom))) +``` \ No newline at end of file diff --git a/docs/Image Crop Location.md b/docs/Image Crop Location.md new file mode 100644 index 0000000..b1658de --- /dev/null +++ b/docs/Image Crop Location.md @@ -0,0 +1,75 @@ +# Documentation +- Class name: WAS_Image_Crop_Location +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 `image_crop_location` 旨在根据指定的坐标对图像进行精确裁剪。它允许通过定义顶部、左侧、右侧和底部边界来选择图像中的矩形区域。此方法对于聚焦图像内的兴趣区域至关重要,可能通过集中于相关视觉内容,增强后续图像处理任务。 + +# Input types +## Required +- image + - 输入图像是节点操作的主要数据对象。它对节点的功能至关重要,因为整个操作都围绕着对这张图像进行操作。图像参数直接影响节点的执行和最终产生的裁剪图像。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +## Optional +- top + - 参数 'top' 指定裁剪操作的垂直起始点。它很重要,因为它决定了裁剪区域的上边界。此参数与 'bottom' 配合使用,定义了裁剪的高度。 + - Comfy dtype: INT + - Python dtype: int +- left + - 参数 'left' 设置裁剪的横向起始点。它很重要,因为它建立了要裁剪区域的左边界。与 'right' 一起,它有助于确定最终裁剪部分的宽度。 + - Comfy dtype: INT + - Python dtype: int +- right + - 参数 'right' 定义裁剪的横向结束点。它对于通过计算 'right' 和 'left' 之间的差异来确定裁剪的宽度至关重要。它确保在裁剪后的图像中保持正确的宽度。 + - Comfy dtype: INT + - Python dtype: int +- bottom + - 参数 'bottom' 指示裁剪的垂直结束点。它至关重要,因为它设置了裁剪的下边界。与 'top' 一起,它决定了裁剪区域的垂直范围。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- cropped_image + - 输出 'cropped_image' 是裁剪操作的结果。它代表了输入图像中位于指定边界内的区域。这个输出很重要,因为它是节点功能的主要产出,提供了图像内容的聚焦视图。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- crop_data + - 输出 'crop_data' 提供了有关裁剪操作的元数据,包括裁剪图像的大小和裁剪区域的坐标。这些信息对于理解裁剪的具体细节很有价值,并且可以用于进一步的处理或分析。 + - Comfy dtype: CROP_DATA + - Python dtype: Tuple[int, Tuple[int, int, int, int]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Crop_Location: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'top': ('INT', {'default': 0, 'max': 10000000, 'min': 0, 'step': 1}), 'left': ('INT', {'default': 0, 'max': 10000000, 'min': 0, 'step': 1}), 'right': ('INT', {'default': 256, 'max': 10000000, 'min': 0, 'step': 1}), 'bottom': ('INT', {'default': 256, 'max': 10000000, 'min': 0, 'step': 1})}} + RETURN_TYPES = ('IMAGE', 'CROP_DATA') + FUNCTION = 'image_crop_location' + CATEGORY = 'WAS Suite/Image/Process' + + def image_crop_location(self, image, top=0, left=0, right=256, bottom=256): + image = tensor2pil(image) + (img_width, img_height) = image.size + crop_top = max(top, 0) + crop_left = max(left, 0) + crop_bottom = min(bottom, img_height) + crop_right = min(right, img_width) + crop_width = crop_right - crop_left + crop_height = crop_bottom - crop_top + if crop_width <= 0 or crop_height <= 0: + raise ValueError('Invalid crop dimensions. Please check the values for top, left, right, and bottom.') + crop = image.crop((crop_left, crop_top, crop_right, crop_bottom)) + crop_data = (crop.size, (crop_left, crop_top, crop_right, crop_bottom)) + crop = crop.resize((crop.size[0] // 8 * 8, crop.size[1] // 8 * 8)) + return (pil2tensor(crop), crop_data) +``` \ No newline at end of file diff --git a/docs/Image Crop Square Location.md b/docs/Image Crop Square Location.md new file mode 100644 index 0000000..c322258 --- /dev/null +++ b/docs/Image Crop Square Location.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: WAS_Image_Crop_Square_Location +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Crop_Square_Location节点旨在通过基于指定位置坐标裁剪图像来处理图像,将其裁剪成正方形。它智能地调整裁剪区域,以确保结果图像是正方形的,即使指定的区域不是完全正方形。这个节点特别适用于需要统一图像尺寸的应用,例如社交媒体帖子或机器学习模型的数据输入。 + +# Input types +## Required +- image + - 图像参数是节点将处理的输入图像。它对节点的操作至关重要,因为它是裁剪操作的对象。图像的内容和尺寸将直接影响裁剪过程的结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +## Optional +- x + - x参数指定了裁剪操作将从中心开始的水平坐标。它在确定图像中裁剪区域的位置方面起着关键作用。如果没有提供特定值,则默认值设置为确保中心裁剪。 + - Comfy dtype: INT + - Python dtype: int +- y + - y参数定义了裁剪操作将从中心开始的垂直坐标。与x参数类似,它对于精确定位图像中的裁剪位置至关重要。如果没有用户指定的值,则默认值确保中心裁剪。 + - Comfy dtype: INT + - Python dtype: int +- size + - size参数决定了裁剪图像的正方形边长。它是实现所需输出尺寸的关键决定因素。节点确保裁剪尽可能接近此尺寸,同时不超过图像边界。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- cropped_image + - 裁剪后的图像输出是裁剪过程的结果。它是从输入图像派生出的正方形图像,以指定的位置坐标为中心。这个输出对于需要标准化图像格式的应用来说非常重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- crop_data + - crop_data输出提供了有关裁剪过程的元数据,包括裁剪图像的大小和裁剪区域的坐标。这些信息对于进一步的图像处理或分析可能很有用。 + - Comfy dtype: CROP_DATA + - Python dtype: Tuple[int, Tuple[int, int, int, int]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Crop_Square_Location: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'x': ('INT', {'default': 0, 'max': 24576, 'min': 0, 'step': 1}), 'y': ('INT', {'default': 0, 'max': 24576, 'min': 0, 'step': 1}), 'size': ('INT', {'default': 256, 'max': 4096, 'min': 5, 'step': 1})}} + RETURN_TYPES = ('IMAGE', 'CROP_DATA') + FUNCTION = 'image_crop_location' + CATEGORY = 'WAS Suite/Image/Process' + + def image_crop_location(self, image, x=256, y=256, size=512): + image = tensor2pil(image) + (img_width, img_height) = image.size + exp_size = size // 2 + left = max(x - exp_size, 0) + top = max(y - exp_size, 0) + right = min(x + exp_size, img_width) + bottom = min(y + exp_size, img_height) + if right - left < size: + if right < img_width: + right = min(right + size - (right - left), img_width) + elif left > 0: + left = max(left - (size - (right - left)), 0) + if bottom - top < size: + if bottom < img_height: + bottom = min(bottom + size - (bottom - top), img_height) + elif top > 0: + top = max(top - (size - (bottom - top)), 0) + crop = image.crop((left, top, right, bottom)) + crop_data = (crop.size, (left, top, right, bottom)) + crop = crop.resize((crop.size[0] // 8 * 8, crop.size[1] // 8 * 8)) + return (pil2tensor(crop), crop_data) +``` \ No newline at end of file diff --git a/docs/Image Displacement Warp.md b/docs/Image Displacement Warp.md new file mode 100644 index 0000000..302f668 --- /dev/null +++ b/docs/Image Displacement Warp.md @@ -0,0 +1,81 @@ +# Documentation +- Class name: WAS_Image_Displacement_Warp +- Category: WAS Suite/Image/Transform +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Displacement_Warp节点旨在对给定的一组图像应用位移变形效果。它使用位移映射和振幅因子来确定变形的程度,从而产生视觉上扭曲的输出,可以用于各种创意和技术应用。 + +# Input types +## Required +- images + - 要应用位移变形效果的输入图像。这些图像构成了变换过程的基础层。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +- displacement_maps + - 位移映射指示应用于输入图像的变形效果的方向和强度。地图中的每个像素值对应一个位移向量。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +## Optional +- amplitude + - 振幅参数控制位移效果的强度。值越高,变形越明显;值越低,效果越微妙。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- images + - 输出图像是将位移变形效果应用于输入图像的结果,使用指定的位移映射和振幅。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Displacement_Warp: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'displacement_maps': ('IMAGE',), 'amplitude': ('FLOAT', {'default': 25.0, 'min': -4096, 'max': 4096, 'step': 0.1})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('images',) + FUNCTION = 'displace_image' + CATEGORY = 'WAS Suite/Image/Transform' + + def displace_image(self, images, displacement_maps, amplitude): + WTools = WAS_Tools_Class() + displaced_images = [] + for i in range(len(images)): + img = tensor2pil(images[i]) + if i < len(displacement_maps): + disp = tensor2pil(displacement_maps[i]) + else: + disp = tensor2pil(displacement_maps[-1]) + disp = self.resize_and_crop(disp, img.size) + displaced_images.append(pil2tensor(WTools.displace_image(img, disp, amplitude))) + displaced_images = torch.cat(displaced_images, dim=0) + return (displaced_images,) + + def resize_and_crop(self, image, target_size): + (width, height) = image.size + (target_width, target_height) = target_size + aspect_ratio = width / height + target_aspect_ratio = target_width / target_height + if aspect_ratio > target_aspect_ratio: + new_height = target_height + new_width = int(new_height * aspect_ratio) + else: + new_width = target_width + new_height = int(new_width / aspect_ratio) + image = image.resize((new_width, new_height)) + left = (new_width - target_width) // 2 + top = (new_height - target_height) // 2 + right = left + target_width + bottom = top + target_height + image = image.crop((left, top, right, bottom)) + return image +``` \ No newline at end of file diff --git a/docs/Image Dragan Photography Filter.md b/docs/Image Dragan Photography Filter.md new file mode 100644 index 0000000..639ab20 --- /dev/null +++ b/docs/Image Dragan Photography Filter.md @@ -0,0 +1,79 @@ +# Documentation +- Class name: WAS_Dragon_Filter +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Dragon_Filter 节点旨在应用一系列图像处理技术,模拟风格化的龙的外观。它通过调整饱和度、对比度、锐度和亮度增强图像的视觉吸引力,同时应用高通滤波器来添加纹理细节。该节点能够对最终输出进行上色,为处理后的图像提供丰富和鲜明的外观。 + +# Input types +## Required +- image + - 输入图像,将由节点处理。它作为节点执行的所有后续图像操作和增强的基础。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- saturation + - 图像的饱和度调整因子。它控制图像内颜色的强度,值越高饱和度增加,值越低饱和度减少。 + - Comfy dtype: FLOAT + - Python dtype: float +- contrast + - 图像的对比度调整因子。它影响图像最暗和最亮区域之间的差异,创建更多或更少的明显色调范围。 + - Comfy dtype: FLOAT + - Python dtype: float +- sharpness + - 图像的锐度调整因子。它控制图像边缘的清晰度和定义度,值越高产生更锐利的图像。 + - Comfy dtype: FLOAT + - Python dtype: float +- brightness + - 图像的亮度调整因子。它控制图像的整体亮度或明度,根据需要使其更亮或更暗。 + - Comfy dtype: FLOAT + - Python dtype: float +- highpass_radius + - 高通滤波器的半径参数。它决定了最终图像中保留的纹理细节的范围。 + - Comfy dtype: FLOAT + - Python dtype: float +- highpass_samples + - 高通滤波器应用于图像的次数。通过多次应用滤波器可以增加纹理细节。 + - Comfy dtype: INT + - Python dtype: int +- highpass_strength + - 高通滤波器效果的强度。它控制最终图像中纹理细节的强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- colorize + - 一个布尔标志,决定最终图像是否应该上色。设置为 true 时,它应用颜色混合效果以增强视觉吸引力。 + - Comfy dtype: COMBO[true, false] + - Python dtype: bool + +# Output types +- output_image + - 应用龙过滤器效果后的结果图像。它是一种结合了各种图像处理技术的样式化表示,创造出独特且视觉上吸引人的结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Dragon_Filter: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'saturation': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 16.0, 'step': 0.01}), 'contrast': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 16.0, 'step': 0.01}), 'brightness': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 16.0, 'step': 0.01}), 'sharpness': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 6.0, 'step': 0.01}), 'highpass_radius': ('FLOAT', {'default': 6.0, 'min': 0.0, 'max': 255.0, 'step': 0.01}), 'highpass_samples': ('INT', {'default': 1, 'min': 0, 'max': 6.0, 'step': 1}), 'highpass_strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 3.0, 'step': 0.01}), 'colorize': (['true', 'false'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'apply_dragan_filter' + CATEGORY = 'WAS Suite/Image/Filter' + + def apply_dragan_filter(self, image, saturation, contrast, sharpness, brightness, highpass_radius, highpass_samples, highpass_strength, colorize): + WTools = WAS_Tools_Class() + tensor_images = [] + for img in image: + tensor_images.append(pil2tensor(WTools.dragan_filter(tensor2pil(img), saturation, contrast, sharpness, brightness, highpass_radius, highpass_samples, highpass_strength, colorize))) + tensor_images = torch.cat(tensor_images, dim=0) + return (tensor_images,) +``` \ No newline at end of file diff --git a/docs/Image Edge Detection Filter.md b/docs/Image Edge Detection Filter.md new file mode 100644 index 0000000..75fb7c0 --- /dev/null +++ b/docs/Image Edge Detection Filter.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: WAS_Image_Edge +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +`image_edges` 方法旨在对输入图像应用边缘检测。它使用 'normal' 或 'laplacian' 模式处理图像,以突出图像内的边缘,增强视觉特征,以便进行进一步的分析或处理。 + +# Input types +## Required +- image + - 'image' 参数至关重要,因为它是节点将处理的输入。它通过确定将要检测边缘的内容来影响节点的执行。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mode + - 'mode' 参数指示要应用的边缘检测类型。它对节点的功能至关重要,因为它决定了用于在图像中查找边缘的算法。 + - Comfy dtype: COMBO[normal, laplacian] + - Python dtype: str + +# Output types +- edges_image + - 'edges_image' 输出包含根据所选模式突出显示边缘的处理后的图像。它很重要,因为它代表了节点操作的直接结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Edge: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'mode': (['normal', 'laplacian'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_edges' + CATEGORY = 'WAS Suite/Image/Filter' + + def image_edges(self, image, mode): + image = tensor2pil(image) + if mode: + if mode == 'normal': + image = image.filter(ImageFilter.FIND_EDGES) + elif mode == 'laplacian': + image = image.filter(ImageFilter.Kernel((3, 3), (-1, -1, -1, -1, 8, -1, -1, -1, -1), 1, 0)) + else: + image = image + return (torch.from_numpy(np.array(image).astype(np.float32) / 255.0).unsqueeze(0),) +``` \ No newline at end of file diff --git a/docs/Image Film Grain.md b/docs/Image Film Grain.md new file mode 100644 index 0000000..1bc325a --- /dev/null +++ b/docs/Image Film Grain.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: WAS_Film_Grain +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Film_Grain节点旨在为图像添加电影颗粒效果,增强其视觉纹理,并创造出类似于传统电影摄影的审美吸引力。它通过应用具有可调密度和强度的灰度噪声来实现这一点,使用户能够控制最终图像中颗粒的显著性。 + +# Input types +## Required +- image + - 图像参数是将要应用电影颗粒效果的输入图像。它是节点操作的基本组成部分,因为整个过程围绕操纵此图像以实现所需的视觉效果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- density + - 密度参数控制应用于图像的噪声浓度。它对于调整电影颗粒效果的强度至关重要,允许微调以适应不同的视觉偏好。 + - Comfy dtype: FLOAT + - Python dtype: float +- intensity + - 强度参数确定电影颗粒覆盖在原始图像上的力量。它是实现平衡效果的重要因素,确保颗粒明显但不会压倒图像的细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- highlights + - 高光参数调整图像的亮度,特别针对较亮的区域。它在增强对比度和使电影颗粒效果在图像的明亮部分更加显著方面起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- supersample_factor + - supersample_factor参数在应用噪声之前增加图像的分辨率,这可以导致更详细和更高质量的电影颗粒效果。对于寻求对最终输出外观有更大控制权的用户来说,这是一个可选设置。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- film_grain_image + - film_grain_image输出参数代表应用了电影颗粒效果的最终图像。它是所有节点处理的顶点,反映了用户对密度、强度和高光选择的设置。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Film_Grain: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'density': ('FLOAT', {'default': 1.0, 'min': 0.01, 'max': 1.0, 'step': 0.01}), 'intensity': ('FLOAT', {'default': 1.0, 'min': 0.01, 'max': 1.0, 'step': 0.01}), 'highlights': ('FLOAT', {'default': 1.0, 'min': 0.01, 'max': 255.0, 'step': 0.01}), 'supersample_factor': ('INT', {'default': 4, 'min': 1, 'max': 8, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'film_grain' + CATEGORY = 'WAS Suite/Image/Filter' + + def film_grain(self, image, density, intensity, highlights, supersample_factor): + return (pil2tensor(self.apply_film_grain(tensor2pil(image), density, intensity, highlights, supersample_factor)),) + + def apply_film_grain(self, img, density=0.1, intensity=1.0, highlights=1.0, supersample_factor=4): + """ + Apply grayscale noise with specified density, intensity, and highlights to a PIL image. + """ + img_gray = img.convert('L') + original_size = img.size + img_gray = img_gray.resize((img.size[0] * supersample_factor, img.size[1] * supersample_factor), Image.Resampling(2)) + num_pixels = int(density * img_gray.size[0] * img_gray.size[1]) + noise_pixels = [] + for i in range(num_pixels): + x = random.randint(0, img_gray.size[0] - 1) + y = random.randint(0, img_gray.size[1] - 1) + noise_pixels.append((x, y)) + for (x, y) in noise_pixels: + value = random.randint(0, 255) + img_gray.putpixel((x, y), value) + img_noise = img_gray.convert('RGB') + img_noise = img_noise.filter(ImageFilter.GaussianBlur(radius=0.125)) + img_noise = img_noise.resize(original_size, Image.Resampling(1)) + img_noise = img_noise.filter(ImageFilter.EDGE_ENHANCE_MORE) + img_final = Image.blend(img, img_noise, intensity) + enhancer = ImageEnhance.Brightness(img_final) + img_highlights = enhancer.enhance(highlights) + return img_highlights +``` \ No newline at end of file diff --git a/docs/Image Filter Adjustments.md b/docs/Image Filter Adjustments.md new file mode 100644 index 0000000..8d186ea --- /dev/null +++ b/docs/Image Filter Adjustments.md @@ -0,0 +1,138 @@ +# Documentation +- Class name: WAS_Image_Filters +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Filters节点旨在对输入图像应用一系列全面的图像处理滤镜,以增强或修改图像的视觉特征。它提供的功能包括调整亮度、对比度和饱和度,以及应用锐化、模糊、边缘增强和细节增强效果。该节点的目的是提供一个多功能的图像处理工具,可以用于从简单调整到更复杂的视觉转换的各种应用。 + +# Input types +## Required +- image + - 'image'参数是节点的主要输入,代表将经历过滤的图像数据。它至关重要,因为它决定了所有后续增强和修改将应用的基础内容。输入图像的质量和格式直接影响节点的执行和最终输出的外观。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- brightness + - '亮度'参数允许用户调整图像的整体亮度。它很重要,因为它可以在光线不足的条件下增强可见性或创造风格化效果。这个参数的值直接影响节点的输出,数值越高,亮度增加;数值越低,亮度减少。 + - Comfy dtype: FLOAT + - Python dtype: float +- contrast + - '对比度'参数用于修改图像各部分之间的颜色或色调差异。它在使图像看起来更生动或减少颜色强度以达到更柔和的外观方面起着重要作用。这种调整可以显著改变最终图像的视觉冲击力。 + - Comfy dtype: FLOAT + - Python dtype: float +- saturation + - 'saturation'参数控制图像中颜色的强度。它对于创建更丰富多彩和丰富的图像或制作更去饱和、复古的视觉效果至关重要。饱和度的水平可以极大地影响对图像的情感反应和其整体的美学吸引力。 + - Comfy dtype: FLOAT + - Python dtype: float +- sharpness + - '锐度'参数负责增强图像内的边缘,使它们更加清晰。它对于提高图像的清晰度很重要,特别是当图像看起来模糊或焦点不清晰时尤其有用。增加锐度可以使细节更加突出。 + - Comfy dtype: FLOAT + - Python dtype: float +- blur + - '模糊'参数对图像应用模糊效果,可以用来创造深度感或有意地软化图像。在需要不太锐利的外观的场景中,它很重要,例如出于美学目的或减少图像噪声。 + - Comfy dtype: INT + - Python dtype: int +- gaussian_blur + - '高斯模糊'参数对图像应用高斯模糊,这是一种减少细节和噪声的平滑技术。它特别适用于创建平滑、模糊的外观,并通过模糊效果的半径来控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- edge_enhance + - '边缘增强'参数用于强调图像内的边缘,使它们更加引人注目。它在突出细节方面起着重要作用,并且可以创造性地用于改变图像的视觉风格。 + - Comfy dtype: FLOAT + - Python dtype: float +- detail_enhance + - '细节增强'参数,当设置为true时,对图像应用细节增强滤镜。这可以使微妙的细节更加可见,特别适用于需要更高清晰度和定义的图像。 + - Comfy dtype: COMBO['false', 'true'] + - Python dtype: Union[str, Literal['false', 'true']] + +# Output types +- output_image + - 'output_image'参数代表应用了所有指定滤镜后的处理图像。它是节点功能的最高表现,包含了图像处理过程的结果。此输出很重要,因为它是节点的主要交付物,反映了所有调整的集体影响。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Filters: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'brightness': ('FLOAT', {'default': 0.0, 'min': -1.0, 'max': 1.0, 'step': 0.01}), 'contrast': ('FLOAT', {'default': 1.0, 'min': -1.0, 'max': 2.0, 'step': 0.01}), 'saturation': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 5.0, 'step': 0.01}), 'sharpness': ('FLOAT', {'default': 1.0, 'min': -5.0, 'max': 5.0, 'step': 0.01}), 'blur': ('INT', {'default': 0, 'min': 0, 'max': 16, 'step': 1}), 'gaussian_blur': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1024.0, 'step': 0.1}), 'edge_enhance': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'detail_enhance': (['false', 'true'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_filters' + CATEGORY = 'WAS Suite/Image/Filter' + + def image_filters(self, image, brightness, contrast, saturation, sharpness, blur, gaussian_blur, edge_enhance, detail_enhance): + tensors = [] + if len(image) > 1: + for img in image: + pil_image = None + if brightness > 0.0 or brightness < 0.0: + img = np.clip(img + brightness, 0.0, 1.0) + if contrast > 1.0 or contrast < 1.0: + img = np.clip(img * contrast, 0.0, 1.0) + if saturation > 1.0 or saturation < 1.0: + pil_image = tensor2pil(img) + pil_image = ImageEnhance.Color(pil_image).enhance(saturation) + if sharpness > 1.0 or sharpness < 1.0: + pil_image = pil_image if pil_image else tensor2pil(img) + pil_image = ImageEnhance.Sharpness(pil_image).enhance(sharpness) + if blur > 0: + pil_image = pil_image if pil_image else tensor2pil(img) + for _ in range(blur): + pil_image = pil_image.filter(ImageFilter.BLUR) + if gaussian_blur > 0.0: + pil_image = pil_image if pil_image else tensor2pil(img) + pil_image = pil_image.filter(ImageFilter.GaussianBlur(radius=gaussian_blur)) + if edge_enhance > 0.0: + pil_image = pil_image if pil_image else tensor2pil(img) + edge_enhanced_img = pil_image.filter(ImageFilter.EDGE_ENHANCE_MORE) + blend_mask = Image.new(mode='L', size=pil_image.size, color=round(edge_enhance * 255)) + pil_image = Image.composite(edge_enhanced_img, pil_image, blend_mask) + del blend_mask, edge_enhanced_img + if detail_enhance == 'true': + pil_image = pil_image if pil_image else tensor2pil(img) + pil_image = pil_image.filter(ImageFilter.DETAIL) + out_image = pil2tensor(pil_image) if pil_image else img + tensors.append(out_image) + tensors = torch.cat(tensors, dim=0) + else: + pil_image = None + img = image + if brightness > 0.0 or brightness < 0.0: + img = np.clip(img + brightness, 0.0, 1.0) + if contrast > 1.0 or contrast < 1.0: + img = np.clip(img * contrast, 0.0, 1.0) + if saturation > 1.0 or saturation < 1.0: + pil_image = tensor2pil(img) + pil_image = ImageEnhance.Color(pil_image).enhance(saturation) + if sharpness > 1.0 or sharpness < 1.0: + pil_image = pil_image if pil_image else tensor2pil(img) + pil_image = ImageEnhance.Sharpness(pil_image).enhance(sharpness) + if blur > 0: + pil_image = pil_image if pil_image else tensor2pil(img) + for _ in range(blur): + pil_image = pil_image.filter(ImageFilter.BLUR) + if gaussian_blur > 0.0: + pil_image = pil_image if pil_image else tensor2pil(img) + pil_image = pil_image.filter(ImageFilter.GaussianBlur(radius=gaussian_blur)) + if edge_enhance > 0.0: + pil_image = pil_image if pil_image else tensor2pil(img) + edge_enhanced_img = pil_image.filter(ImageFilter.EDGE_ENHANCE_MORE) + blend_mask = Image.new(mode='L', size=pil_image.size, color=round(edge_enhance * 255)) + pil_image = Image.composite(edge_enhanced_img, pil_image, blend_mask) + del blend_mask, edge_enhanced_img + if detail_enhance == 'true': + pil_image = pil_image if pil_image else tensor2pil(img) + pil_image = pil_image.filter(ImageFilter.DETAIL) + out_image = pil2tensor(pil_image) if pil_image else img + tensors = out_image + return (tensors,) +``` \ No newline at end of file diff --git a/docs/Image Flip.md b/docs/Image Flip.md new file mode 100644 index 0000000..ff9014f --- /dev/null +++ b/docs/Image Flip.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: WAS_Image_Flip +- Category: WAS Suite/Image/Transform +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +图像翻转方法旨在通过水平或垂直翻转对一组图像进行变换。此操作对于机器学习任务中的数据增强至关重要,它提供了训练数据的多样性,可以提高模型的鲁棒性和泛化能力。 + +# Input types +## Required +- images + - 参数 'images' 是要翻转的图像集合。它在节点的操作中起着核心作用,因为转换直接应用于这些图像。节点的结果严重依赖于输入图像的内容和格式。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +- mode + - 参数 'mode' 决定了输入图像将被翻转的方向。它非常重要,因为它决定了应用于图像的转换类型。在 'horizontal' 和 'vertical' 之间的选择直接影响图像处理的最终结果。 + - Comfy dtype: COMBO['horizontal', 'vertical'] + - Python dtype: str + +# Output types +- images + - 输出 'images' 代表翻转变换后的图像。它很重要,因为它是节点操作的直接结果,并用于工作流后续阶段的进一步处理或分析。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Flip: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'mode': (['horizontal', 'vertical'],)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('images',) + FUNCTION = 'image_flip' + CATEGORY = 'WAS Suite/Image/Transform' + + def image_flip(self, images, mode): + batch_tensor = [] + for image in images: + image = tensor2pil(image) + if mode == 'horizontal': + image = image.transpose(0) + if mode == 'vertical': + image = image.transpose(1) + batch_tensor.append(pil2tensor(image)) + batch_tensor = torch.cat(batch_tensor, dim=0) + return (batch_tensor,) +``` \ No newline at end of file diff --git a/docs/Image Generate Gradient.md b/docs/Image Generate Gradient.md new file mode 100644 index 0000000..8efc8de --- /dev/null +++ b/docs/Image Generate Gradient.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: WAS_Image_Generate_Gradient +- Category: WAS Suite/Image/Generate +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Generate_Gradient 节点旨在从一组给定的颜色停止生成无缝渐变纹理。它智能地处理颜色之间的过渡,以确保平滑的渐变,可以平铺而没有可见的接缝。这对于生成需要无缝图案的游戏或3D建模等应用的背景纹理特别有用。 + +# Input types +## Required +- gradient_stops + - gradient_stops 参数定义了用于创建渐变的颜色停止。每个停止点都指定为渐变长度的百分比,后跟RGB颜色值,由冒号分隔。此参数对于确定渐变的颜色和分布至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- width + - width 参数设置生成的渐变图像的宽度。它是一个重要的参数,因为它决定了输出图像的水平分辨率。 + - Comfy dtype: INT + - Python dtype: int +- height + - height 参数设置生成的渐变图像的高度。它是一个重要的参数,因为它决定了输出图像的垂直分辨率。 + - Comfy dtype: INT + - Python dtype: int +- direction + - direction 参数指定渐变的方向。它可以是 'horizontal' 或 'vertical',影响输出图像中颜色渐变的布局。 + - Comfy dtype: COMBO['horizontal', 'vertical'] + - Python dtype: str +- tolerance + - tolerance 参数用于调整渐变边缘的混合。更高的容差值可以在颜色之间产生更平滑的过渡,但可能导致渐变不太明显。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - WAS_Image_Generate_Gradient 节点的输出是一个无缝渐变图像,可以用作纹理。它很重要,因为它提供了节点操作的最终视觉结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Generate_Gradient: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + gradient_stops = '0:255,0,0\n25:255,255,255\n50:0,255,0\n75:0,0,255' + return {'required': {'width': ('INT', {'default': 512, 'max': 4096, 'min': 64, 'step': 1}), 'height': ('INT', {'default': 512, 'max': 4096, 'min': 64, 'step': 1}), 'direction': (['horizontal', 'vertical'],), 'tolerance': ('INT', {'default': 0, 'max': 255, 'min': 0, 'step': 1}), 'gradient_stops': ('STRING', {'default': gradient_stops, 'multiline': True})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_gradient' + CATEGORY = 'WAS Suite/Image/Generate' + + def image_gradient(self, gradient_stops, width=512, height=512, direction='horizontal', tolerance=0): + import io + WTools = WAS_Tools_Class() + colors_dict = {} + stops = io.StringIO(gradient_stops.strip().replace(' ', '')) + for stop in stops: + parts = stop.split(':') + colors = parts[1].replace('\n', '').split(',') + colors_dict[parts[0].replace('\n', '')] = colors + image = WTools.gradient((width, height), direction, colors_dict, tolerance) + return (pil2tensor(image),) +``` \ No newline at end of file diff --git a/docs/Image Gradient Map.md b/docs/Image Gradient Map.md new file mode 100644 index 0000000..f53f936 --- /dev/null +++ b/docs/Image Gradient Map.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: WAS_Image_Gradient_Map +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Gradient_Map 节点旨在对输入图像应用渐变贴图,允许创建视觉上引人注目和多样的颜色效果。它利用 PIL 库处理图像的能力和 numpy 库进行数组操作,实现了高度的灵活性和对图像操作的控制。节点的主要功能是获取输入图像和渐变图像,可选择性地翻转它们,然后产生一个结果,其中渐变根据输入图像的亮度进行映射。这个功能特别适用于生成需要颜色平滑过渡的图像效果,或者用于创建响应底层图像内容的纹理。 + +# Input types +## Required +- image + - 输入图像,其颜色将被渐变所替换。此参数至关重要,因为它定义了将经历渐变映射过程的基础图像。节点将以反映此输入图像的亮度值的方式应用渐变。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- gradient_image + - 将用于映射到输入图像的渐变图像。此图像决定了将应用于输入的颜色过渡。应仔细选择它以确保实现所需的视觉效果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- flip_left_right + - 一个布尔标志,设置为 true 时,在处理之前将左右翻转输入和渐变图像。这可以用来在最终输出中创建镜像效果。 + - Comfy dtype: COMBO['false', 'true'] + - Python dtype: bool + +# Output types +- output_image + - 渐变映射过程后的生成图像。此图像显示了输入图像的亮度值转换为渐变图像提供的渐变颜色。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Gradient_Map: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'gradient_image': ('IMAGE',), 'flip_left_right': (['false', 'true'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_gradient_map' + CATEGORY = 'WAS Suite/Image/Filter' + + def image_gradient_map(self, image, gradient_image, flip_left_right='false'): + image = tensor2pil(image) + gradient_image = tensor2pil(gradient_image) + WTools = WAS_Tools_Class() + image = WTools.gradient_map(image, gradient_image, True if flip_left_right == 'true' else False) + return (pil2tensor(image),) +``` \ No newline at end of file diff --git a/docs/Image High Pass Filter.md b/docs/Image High Pass Filter.md new file mode 100644 index 0000000..826243f --- /dev/null +++ b/docs/Image High Pass Filter.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: WAS_Image_High_Pass_Filter +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_High_Pass_Filter 节点旨在增强图像的高频细节,有效去除低频噪声或模糊。它对输入图像应用高通滤波器,使细节更加突出。节点可以调整强度和半径,以控制过滤效果的强度和尺度。 + +# Input types +## Required +- images + - 要由高通滤波器处理的输入图像。此参数至关重要,因为它定义了节点操作以增强高频分量的数据。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image.Image] +## Optional +- radius + - 半径参数决定了高通滤波器要移除的模糊程度。它影响输出图像中保留的细节的尺度。 + - Comfy dtype: INT + - Python dtype: int +- strength + - 强度参数控制高通滤波器效果的强度。更高的值将导致高频细节的增强更加明显。 + - Comfy dtype: FLOAT + - Python dtype: float +- color_output + - color_output 参数指定输出应为彩色(RGB)还是灰度(L)。这影响过滤图像的视觉外观。 + - Comfy dtype: COMBO['true', 'false'] + - Python dtype: Union[str, Literal['true', 'false']] +- neutral_background + - neutral_background 参数确定是否应向图像添加中性颜色背景。在需要中性背景板以获得更好视觉对比度的情况下,这可能会有所帮助。 + - Comfy dtype: COMBO['true', 'false'] + - Python dtype: Union[str, Literal['true', 'false']] + +# Output types +- images + - 包含增强了高频细节的处理图像的输出参数。这些图像已经滤除了低频分量,强调了细节。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_High_Pass_Filter: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'radius': ('INT', {'default': 10, 'min': 1, 'max': 500, 'step': 1}), 'strength': ('FLOAT', {'default': 1.5, 'min': 0.0, 'max': 255.0, 'step': 0.1}), 'color_output': (['true', 'false'],), 'neutral_background': (['true', 'false'],)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('images',) + FUNCTION = 'high_pass' + CATEGORY = 'WAS Suite/Image/Filter' + + def high_pass(self, images, radius=10, strength=1.5, color_output='true', neutral_background='true'): + batch_tensor = [] + for image in images: + transformed_image = self.apply_hpf(tensor2pil(image), radius, strength, color_output, neutral_background) + batch_tensor.append(pil2tensor(transformed_image)) + batch_tensor = torch.cat(batch_tensor, dim=0) + return (batch_tensor,) + + def apply_hpf(self, img, radius=10, strength=1.5, color_output='true', neutral_background='true'): + img_arr = np.array(img).astype('float') + blurred_arr = np.array(img.filter(ImageFilter.GaussianBlur(radius=radius))).astype('float') + hpf_arr = img_arr - blurred_arr + hpf_arr = np.clip(hpf_arr * strength, 0, 255).astype('uint8') + if color_output == 'true': + high_pass = Image.fromarray(hpf_arr, mode='RGB') + else: + grayscale_arr = np.mean(hpf_arr, axis=2).astype('uint8') + high_pass = Image.fromarray(grayscale_arr, mode='L') + if neutral_background == 'true': + neutral_color = (128, 128, 128) if high_pass.mode == 'RGB' else 128 + neutral_bg = Image.new(high_pass.mode, high_pass.size, neutral_color) + high_pass = ImageChops.screen(neutral_bg, high_pass) + return high_pass.convert('RGB') +``` \ No newline at end of file diff --git a/docs/Image History Loader.md b/docs/Image History Loader.md new file mode 100644 index 0000000..dadf4c5 --- /dev/null +++ b/docs/Image History Loader.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: WAS_Image_History +- Category: WAS Suite/History +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_History 节点旨在管理和检索存储在 WASDatabase 中的历史图像。它提供访问和显示历史记录中的图像的功能,确保用户可以查看过去的图像状态或数据。 + +# Input types +## Required +- image + - 'image' 参数对于指定用户想要访问的历史图像至关重要。节点使用它来定位并从数据库中检索正确的图像。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- image + - 'image' 输出参数表示以张量形式检索到的历史图像,适用于进一步处理或显示目的。 + - Comfy dtype: COMBO[str, torch.Tensor] + - Python dtype: Union[str, torch.Tensor] +- filename_text + - 'filename_text' 输出参数提供检索到的图像的文件名,这对于记录、引用或额外的元数据目的非常有用。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_History: + + def __init__(self): + self.HDB = WASDatabase(WAS_HISTORY_DATABASE) + self.conf = getSuiteConfig() + + @classmethod + def INPUT_TYPES(cls): + HDB = WASDatabase(WAS_HISTORY_DATABASE) + conf = getSuiteConfig() + paths = ['No History'] + if HDB.catExists('History') and HDB.keyExists('History', 'Images'): + history_paths = HDB.get('History', 'Images') + if conf.__contains__('history_display_limit'): + history_paths = history_paths[-conf['history_display_limit']:] + paths = [] + for path_ in history_paths: + paths.append(os.path.join('...' + os.sep + os.path.basename(os.path.dirname(path_)), os.path.basename(path_))) + return {'required': {'image': (paths,)}} + RETURN_TYPES = ('IMAGE', TEXT_TYPE) + RETURN_NAMES = ('image', 'filename_text') + FUNCTION = 'image_history' + CATEGORY = 'WAS Suite/History' + + def image_history(self, image): + self.HDB = WASDatabase(WAS_HISTORY_DATABASE) + paths = {} + if self.HDB.catExists('History') and self.HDB.keyExists('History', 'Images'): + history_paths = self.HDB.get('History', 'Images') + for path_ in history_paths: + paths.update({os.path.join('...' + os.sep + os.path.basename(os.path.dirname(path_)), os.path.basename(path_)): path_}) + if os.path.exists(paths[image]) and paths.__contains__(image): + return (pil2tensor(Image.open(paths[image]).convert('RGB')), os.path.basename(paths[image])) + else: + cstr(f'The image `{image}` does not exist!').error.print() + return (pil2tensor(Image.new('RGB', (512, 512), (0, 0, 0, 0))), 'null') + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') +``` \ No newline at end of file diff --git a/docs/Image Input Switch.md b/docs/Image Input Switch.md new file mode 100644 index 0000000..2aae173 --- /dev/null +++ b/docs/Image Input Switch.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: WAS_Image_Input_Switch +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 `image_input_switch` 旨在根据布尔标志有条件地在两个图像输入之间进行选择。它在图像处理工作流中充当逻辑开关,允许根据提供的布尔条件动态路由图像数据。 + +# Input types +## Required +- image_a + - 当布尔标志为真时将返回的第一个图像输入。这是一个关键参数,因为它决定了开关处于“开”状态时的结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- image_b + - 当布尔标志为假时将返回的第二个图像输入。当开关处于“关”状态时,它起着关键作用,决定了该情况下的输出。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- boolean + - 决定选择哪个图像输入的布尔标志。当为真时,返回 `image_a`;当为假时,返回 `image_b`。这个参数对节点的决策过程至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- selected_image + - 由布尔标志确定的输出图像。它代表了逻辑开关操作的结果,根据输入条件提供选定的图像。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Input_Switch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image_a': ('IMAGE',), 'image_b': ('IMAGE',), 'boolean': ('BOOLEAN', {'forceInput': True})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_input_switch' + CATEGORY = 'WAS Suite/Logic' + + def image_input_switch(self, image_a, image_b, boolean=True): + if boolean: + return (image_a,) + else: + return (image_b,) +``` \ No newline at end of file diff --git a/docs/Image Levels Adjustment.md b/docs/Image Levels Adjustment.md new file mode 100644 index 0000000..1471fa5 --- /dev/null +++ b/docs/Image Levels Adjustment.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: WAS_Image_Levels +- Category: WAS Suite/Image/Adjustment +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +该节点旨在通过调整图像的黑、中、白水平来调整图像的色调范围,从而增强图像的整体对比度和视觉吸引力。 + +# Input types +## Required +- image + - 图像参数对于节点处理和调整视觉内容至关重要。它作为输入,其色调水平将根据指定的黑、中、白水平进行修改。 + - Comfy dtype: COMBO[Image] + - Python dtype: PIL.Image +- black_level + - 黑水平参数对于设定图像中最暗的点至关重要,它影响整体对比度和色调范围。它有助于定义图像中的阴影和最深的黑色。 + - Comfy dtype: FLOAT + - Python dtype: float +- mid_level + - 中水平参数在确定色调范围的中点方面起着关键作用,影响图像中色调的整体平衡和分布。 + - Comfy dtype: FLOAT + - Python dtype: float +- white_level + - 白水平参数对于定义图像中最亮的点很重要,它有助于高光和最亮的白色。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- image + - 输出图像是色调调整的结果,展示了通过操纵黑、中、白水平而出现的增强对比度和精细视觉细节。 + - Comfy dtype: COMBO[Image] + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Levels: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'black_level': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 255.0, 'step': 0.1}), 'mid_level': ('FLOAT', {'default': 127.5, 'min': 0.0, 'max': 255.0, 'step': 0.1}), 'white_level': ('FLOAT', {'default': 255, 'min': 0.0, 'max': 255.0, 'step': 0.1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'apply_image_levels' + CATEGORY = 'WAS Suite/Image/Adjustment' + + def apply_image_levels(self, image, black_level, mid_level, white_level): + tensor_images = [] + for img in image: + img = tensor2pil(img) + levels = self.AdjustLevels(black_level, mid_level, white_level) + tensor_images.append(pil2tensor(levels.adjust(img))) + tensor_images = torch.cat(tensor_images, dim=0) + return (tensor_images,) + + class AdjustLevels: + + def __init__(self, min_level, mid_level, max_level): + self.min_level = min_level + self.mid_level = mid_level + self.max_level = max_level + + def adjust(self, im): + im_arr = np.array(im) + im_arr[im_arr < self.min_level] = self.min_level + im_arr = (im_arr - self.min_level) * (255 / (self.max_level - self.min_level)) + im_arr[im_arr < 0] = 0 + im_arr[im_arr > 255] = 255 + im_arr = im_arr.astype(np.uint8) + im = Image.fromarray(im_arr) + im = ImageOps.autocontrast(im, cutoff=self.max_level) + return im +``` \ No newline at end of file diff --git a/docs/Image Load with Metadata (WLSH).md b/docs/Image Load with Metadata (WLSH).md new file mode 100644 index 0000000..30e5dab --- /dev/null +++ b/docs/Image Load with Metadata (WLSH).md @@ -0,0 +1,168 @@ +# Documentation +- Class name: WLSH_Read_Prompt +- Category: WLSH Nodes/image +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点旨在通过提取和解释嵌入的元数据来处理图像数据,其中包括指导图像生成过程的提示和其他参数。它在确保图像数据正确格式化并为系统中后续操作做好准备方面发挥着关键作用。 + +# Input types +## Required +- verbose + - ‘verbose’参数控制输出信息的详细程度。当设置为‘true’时,它启用全面的节点操作日志记录,为调试和优化提供有价值的洞察。 + - Comfy dtype: COMBO[bool] + - Python dtype: str +- image + - ‘image’参数至关重要,因为它指定了节点将要处理的源图像文件。它直接影响后续步骤中使用的图像数据的质量和特性。 + - Comfy dtype: COMBO[str] + - Python dtype: str + +# Output types +- image + - ‘image’输出是输入图像的预处理张量表示,准备在系统内进行进一步的操作和分析。它是所有后续与图像相关的操作的基础,是一个关键组成部分。 + - Comfy dtype: COMBO[torch.Tensor] + - Python dtype: torch.Tensor +- positive + - ‘positive’输出提供了与图像相关的积极提示,这对于理解图像生成过程的期望结果至关重要。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- negative + - ‘negative’输出包含负面提示,概述了图像生成中要避免的方面。它对于引导生成朝预期方向发展至关重要。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- seed + - ‘seed’输出表示用于生成过程的随机种子。它确保结果的可重复性和一致性,这对于实验和比较分析至关重要。 + - Comfy dtype: COMBO[int] + - Python dtype: int +- steps + - ‘steps’输出表示图像生成过程中所采取的迭代次数或步骤数。它影响最终输出的细节和精炼程度。 + - Comfy dtype: COMBO[int] + - Python dtype: int +- cfg + - ‘cfg’输出指的是调整图像生成设置的配置比例或参数。它在控制生成图像的整体风格和质量方面发挥着重要作用。 + - Comfy dtype: COMBO[float] + - Python dtype: float +- width + - ‘width’输出指定了生成图像的水平分辨率。它是决定图像的宽高比和整体尺寸的关键因素。 + - Comfy dtype: COMBO[int] + - Python dtype: int +- height + - ‘height’输出定义了图像的垂直分辨率。它与‘width’一起工作,以确定图像的最终大小和布局。 + - Comfy dtype: COMBO[int] + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Read_Prompt: + + @classmethod + def INPUT_TYPES(s): + input_dir = folder_paths.get_input_directory() + files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))] + return {'required': {'verbose': (['true', 'false'],), 'image': (sorted(files), {'image_upload': True})}} + CATEGORY = 'WLSH Nodes/image' + ' Return order:\n positive prompt(string), negative prompt(string), seed(int), steps(int), cfg(float), \n width(int), height(int)\n ' + RETURN_TYPES = ('IMAGE', 'STRING', 'STRING', 'INT', 'INT', 'FLOAT', 'INT', 'INT') + RETURN_NAMES = ('image', 'positive', 'negative', 'seed', 'steps', 'cfg', 'width', 'height') + FUNCTION = 'get_image_data' + + def get_image_data(self, image, verbose): + image_path = folder_paths.get_annotated_filepath(image) + with open(image_path, 'rb') as file: + img = Image.open(file) + extension = image_path.split('.')[-1] + image = img.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + parameters = '' + comfy = False + if extension.lower() == 'png': + try: + parameters = img.info['parameters'] + if not parameters.startswith('Positive prompt'): + parameters = 'Positive prompt: ' + parameters + except: + parameters = '' + print('Error loading prompt info from png') + elif extension.lower() in ('jpg', 'jpeg', 'webp'): + try: + exif = piexif.load(img.info['exif']) + parameters = (exif or {}).get('Exif', {}).get(piexif.ExifIFD.UserComment, b'') + parameters = piexif.helper.UserComment.load(parameters) + if not parameters.startswith('Positive prompt'): + parameters = 'Positive prompt: ' + parameters + except: + try: + parameters = str(img.info['comment']) + comfy = True + parameters = parameters.replace('Positive Prompt', 'Positive prompt') + parameters = parameters.replace('Negative Prompt', 'Negative prompt') + parameters = parameters.replace('Start at Step', 'Start at step') + parameters = parameters.replace('End at Step', 'End at step') + parameters = parameters.replace('Denoising Strength', 'Denoising strength') + except: + parameters = '' + print('Error loading prompt info from jpeg') + if comfy and extension.lower() == 'jpeg': + parameters = parameters.replace('\\n', ' ') + else: + parameters = parameters.replace('\n', ' ') + patterns = ['Positive prompt: ', 'Negative prompt: ', 'Steps: ', 'Start at step: ', 'End at step: ', 'Sampler: ', 'Scheduler: ', 'CFG scale: ', 'Seed: ', 'Size: ', 'Model: ', 'Model hash: ', 'Denoising strength: ', 'Version: ', 'ControlNet 0', 'Controlnet 1', 'Batch size: ', 'Batch pos: ', 'Hires upscale: ', 'Hires steps: ', 'Hires upscaler: ', 'Template: ', 'Negative Template: '] + if comfy and extension.lower() == 'jpeg': + parameters = parameters[2:] + parameters = parameters[:-1] + keys = re.findall('|'.join(patterns), parameters) + values = re.split('|'.join(patterns), parameters) + values = [x for x in values if x] + results = {} + result_string = '' + for item in range(len(keys)): + result_string += keys[item] + values[item].rstrip(', ') + result_string += '\n' + results[keys[item].replace(': ', '')] = values[item].rstrip(', ') + if verbose == 'true': + print(result_string) + try: + positive = results['Positive prompt'] + except: + positive = '' + try: + negative = results['Negative prompt'] + except: + negative = '' + try: + seed = int(results['Seed']) + except: + seed = -1 + try: + steps = int(results['Steps']) + except: + steps = 20 + try: + cfg = float(results['CFG scale']) + except: + cfg = 8.0 + try: + (width, height) = img.size + except: + (width, height) = (512, 512) + ' Return order:\n positive prompt(string), negative prompt(string), seed(int), steps(int), cfg(float), \n width(int), height(int)\n ' + return (image, positive, negative, seed, steps, cfg, width, height) + + @classmethod + def IS_CHANGED(s, image, verbose): + image_path = folder_paths.get_annotated_filepath(image) + m = hashlib.sha256() + with open(image_path, 'rb') as f: + m.update(f.read()) + return m.digest().hex() + + @classmethod + def VALIDATE_INPUTS(s, image, verbose): + if not folder_paths.exists_annotated_filepath(image): + return 'Invalid image file: {}'.format(image) + return True +``` \ No newline at end of file diff --git a/docs/Image Load.md b/docs/Image Load.md new file mode 100644 index 0000000..c1e3eff --- /dev/null +++ b/docs/Image Load.md @@ -0,0 +1,111 @@ +# Documentation +- Class name: WAS_Load_Image +- Category: WAS Suite/IO +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Load_Image节点旨在高效地加载和处理来自指定路径或URL的图像。它处理图像转换为所需格式,并提供创建来自alpha通道的掩码和提取文件名等附加功能。 + +# Input types +## Required +- image_path + - image_path参数至关重要,因为它决定了要加载的图像的来源。它可以是本地文件路径或在线图像的URL。此参数直接影响节点访问和处理图像数据的能力。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- RGBA + - RGBA参数指定是否应加载带有alpha通道的图像。这会影响图像的透明度,对于某些图像处理任务可能非常重要。 + - Comfy dtype: ['false', 'true'] + - Python dtype: str +- filename_text_extension + - filename_text_extension参数决定是否在文件名文本中包含文件扩展名。这对于需要特定命名约定的下游流程可能很重要。 + - Comfy dtype: ['true', 'false'] + - Python dtype: str + +# Output types +- image + - 图像输出提供已加载和处理的图像数据。它是任何后续图像分析或操作任务的基础输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 掩码输出来源于图像的alpha通道(如果存在),用于区分图像中的透明区域。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- filename_text + - filename_text输出是图像文件名的文本表示。它可以用于记录、显示或其他基于文本的操作。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Load_Image: + + def __init__(self): + self.input_dir = comfy_paths.input_directory + self.HDB = WASDatabase(WAS_HISTORY_DATABASE) + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image_path': ('STRING', {'default': './ComfyUI/input/example.png', 'multiline': False}), 'RGBA': (['false', 'true'],)}, 'optional': {'filename_text_extension': (['true', 'false'],)}} + RETURN_TYPES = ('IMAGE', 'MASK', TEXT_TYPE) + RETURN_NAMES = ('image', 'mask', 'filename_text') + FUNCTION = 'load_image' + CATEGORY = 'WAS Suite/IO' + + def load_image(self, image_path, RGBA='false', filename_text_extension='true'): + RGBA = RGBA == 'true' + if image_path.startswith('http'): + from io import BytesIO + i = self.download_image(image_path) + else: + try: + i = Image.open(image_path) + except OSError: + cstr(f"The image `{image_path.strip()}` specified doesn't exist!").error.print() + i = Image.new(mode='RGB', size=(512, 512), color=(0, 0, 0)) + if not i: + return + update_history_images(image_path) + image = i + if not RGBA: + image = image.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + if 'A' in i.getbands(): + mask = np.array(i.getchannel('A')).astype(np.float32) / 255.0 + mask = 1.0 - torch.from_numpy(mask) + else: + mask = torch.zeros((64, 64), dtype=torch.float32, device='cpu') + if filename_text_extension == 'true': + filename = os.path.basename(image_path) + else: + filename = os.path.splitext(os.path.basename(image_path))[0] + return (image, mask, filename) + + def download_image(self, url): + try: + response = requests.get(url) + response.raise_for_status() + img = Image.open(BytesIO(response.content)) + return img + except requests.exceptions.HTTPError as errh: + cstr(f'HTTP Error: ({url}): {errh}').error.print() + except requests.exceptions.ConnectionError as errc: + cstr(f'Connection Error: ({url}): {errc}').error.print() + except requests.exceptions.Timeout as errt: + cstr(f'Timeout Error: ({url}): {errt}').error.print() + except requests.exceptions.RequestException as err: + cstr(f'Request Exception: ({url}): {err}').error.print() + + @classmethod + def IS_CHANGED(cls, image_path): + if image_path.startswith('http'): + return float('NaN') + m = hashlib.sha256() + with open(image_path, 'rb') as f: + m.update(f.read()) + return m.digest().hex() +``` \ No newline at end of file diff --git a/docs/Image Lucy Sharpen.md b/docs/Image Lucy Sharpen.md new file mode 100644 index 0000000..91f5efe --- /dev/null +++ b/docs/Image Lucy Sharpen.md @@ -0,0 +1,75 @@ +# Documentation +- Class name: WAS_Lucy_Sharpen +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Lucy_Sharpen 节点旨在通过应用锐化滤波器来增强图像的清晰度和细节。它使用迭代过程来细化图像,使边缘和细节更加清晰,而不引入显著的伪影。这个节点特别适用于提高可能已经模糊或软化的图像的视觉质量,有助于产生更清晰、更定义明确的输出。 + +# Input types +## Required +- images + - ‘images’参数对于节点的操作至关重要,因为它指定了需要锐化的输入图像。锐化效果的质量直接受这些图像的初始状态影响,使这个参数对于实现期望的结果至关重要。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image.Image] +## Optional +- iterations + - ‘iterations’参数决定了对每个图像通道应用锐化处理的次数。迭代次数越多,锐化效果可能越明显,但同时也会增加计算负载。这是一个可选参数,允许用户控制锐化的强度。 + - Comfy dtype: INT + - Python dtype: int +- kernel_size + - ‘kernel_size’参数定义了锐化过程中使用的卷积核的大小。更大的核大小可以捕获更多上下文,但也可能引入更多的模糊。这是一个可选参数,影响输出图像中锐度和平滑度之间的平衡。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- sharpened_images + - ‘sharpened_images’输出参数包含了应用锐化处理后的图像结果。与输入图像相比,这些图像预期具有更好的清晰度和细节,边缘和纹理得到增强。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Lucy_Sharpen: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'iterations': ('INT', {'default': 2, 'min': 1, 'max': 12, 'step': 1}), 'kernel_size': ('INT', {'default': 3, 'min': 1, 'max': 16, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'sharpen' + CATEGORY = 'WAS Suite/Image/Filter' + + def sharpen(self, images, iterations, kernel_size): + tensors = [] + if len(images) > 1: + for img in images: + tensors.append(pil2tensor(self.lucy_sharpen(tensor2pil(img), iterations, kernel_size))) + tensors = torch.cat(tensors, dim=0) + else: + return (pil2tensor(self.lucy_sharpen(tensor2pil(images), iterations, kernel_size)),) + return (tensors,) + + def lucy_sharpen(self, image, iterations=10, kernel_size=3): + from scipy.signal import convolve2d + image_array = np.array(image, dtype=np.float32) / 255.0 + kernel = np.ones((kernel_size, kernel_size), dtype=np.float32) / kernel_size ** 2 + sharpened_channels = [] + padded_image_array = np.pad(image_array, ((kernel_size, kernel_size), (kernel_size, kernel_size), (0, 0)), mode='edge') + for channel in range(3): + channel_array = padded_image_array[:, :, channel] + for _ in range(iterations): + blurred_channel = convolve2d(channel_array, kernel, mode='same') + ratio = channel_array / (blurred_channel + 1e-06) + channel_array *= convolve2d(ratio, kernel, mode='same') + sharpened_channels.append(channel_array) + cropped_sharpened_image_array = np.stack(sharpened_channels, axis=-1)[kernel_size:-kernel_size, kernel_size:-kernel_size, :] + sharpened_image_array = np.clip(cropped_sharpened_image_array * 255.0, 0, 255).astype(np.uint8) + sharpened_image = Image.fromarray(sharpened_image_array) + return sharpened_image +``` \ No newline at end of file diff --git a/docs/Image Median Filter.md b/docs/Image Median Filter.md new file mode 100644 index 0000000..290d38e --- /dev/null +++ b/docs/Image Median Filter.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: WAS_Image_Median_Filter +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Median_Filter 节点对输入图像应用中值滤波器,这是一种非线性操作,将每个像素替换为周围像素的中值。这在减少图像噪声的同时保留边缘非常有用。该节点旨在处理一批图像,为图像预处理任务提供强大的解决方案。 + +# Input types +## Required +- image + - 图像参数是节点的核心输入,代表将要处理的图像数据。它对节点的执行至关重要,因为它决定了中值滤波操作的对象。输入图像的质量和特性直接影响滤波过程的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- diameter + - 直径参数指定了中值滤波过程中使用的滤波器核的大小。这是一个重要的调整参数,它影响噪声减少的程度和图像细节的保留。直径越大,噪声抑制效果越强,但也可能导致更细微细节的丢失。 + - Comfy dtype: INT + - Python dtype: int +- sigma_color + - sigma_color 参数定义了滤波器对图像内颜色变化的敏感度。这是控制滤波过程颜色方面的一个关键参数,允许根据输入图像的特定特性进行调整。 + - Comfy dtype: FLOAT + - Python dtype: float +- sigma_space + - sigma_space 参数控制滤波器对图像内空间变化的敏感度。它对于微调中值滤波的空间方面至关重要,确保操作适应图像的内容和结构。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output_image + - output_image 是对输入图像应用中值滤波器的结果。它代表了经过处理的图像,具有降低的噪声和保留的边缘,适合进一步分析或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Median_Filter: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'diameter': ('INT', {'default': 2.0, 'min': 0.1, 'max': 255, 'step': 1}), 'sigma_color': ('FLOAT', {'default': 10.0, 'min': -255.0, 'max': 255.0, 'step': 0.1}), 'sigma_space': ('FLOAT', {'default': 10.0, 'min': -255.0, 'max': 255.0, 'step': 0.1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'apply_median_filter' + CATEGORY = 'WAS Suite/Image/Filter' + + def apply_median_filter(self, image, diameter, sigma_color, sigma_space): + tensor_images = [] + for img in image: + img = tensor2pil(img) + tensor_images.append(pil2tensor(medianFilter(img, diameter, sigma_color, sigma_space))) + tensor_images = torch.cat(tensor_images, dim=0) + return (tensor_images,) +``` \ No newline at end of file diff --git a/docs/Image Mix RGB Channels.md b/docs/Image Mix RGB Channels.md new file mode 100644 index 0000000..b442d05 --- /dev/null +++ b/docs/Image Mix RGB Channels.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: WAS_Image_RGB_Merge +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_RGB_Merge节点旨在将单独的彩色通道合并为单个RGB图像。它通过合并红色、绿色和蓝色通道来生成全彩图像,从而在图像处理中发挥关键作用,增强了进一步分析或显示时的视觉输出。 + +# Input types +## Required +- red_channel + - red_channel参数至关重要,因为它代表了最终RGB图像的红色分量。它显著影响合并图像的色平衡和整体外观,对节点的核心功能做出了贡献。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- green_channel + - green_channel参数对于创建RGB图像至关重要,因为它决定了绿色分量。它对于实现所需的颜色表示和最终输出的视觉质量是不可或缺的。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- blue_channel + - blue_channel参数定义了RGB图像的蓝色分量。它是节点操作中的关键元素,确保了正确的色调,并增强了最终合并结果中的图像现实感。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Output types +- merged_image + - merged_image输出参数代表了节点的最终产品,一个完全合并的RGB图像。它很重要,因为它概括了节点的目的,以连贯且视觉上令人愉悦的方式展示了组合的视觉数据。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_RGB_Merge: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'red_channel': ('IMAGE',), 'green_channel': ('IMAGE',), 'blue_channel': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'merge_channels' + CATEGORY = 'WAS Suite/Image/Process' + + def merge_channels(self, red_channel, green_channel, blue_channel): + image = self.mix_rgb_channels(tensor2pil(red_channel).convert('L'), tensor2pil(green_channel).convert('L'), tensor2pil(blue_channel).convert('L')) + return (pil2tensor(image),) + + def mix_rgb_channels(self, red, green, blue): + (width, height) = red.size + merged_img = Image.new('RGB', (width, height)) + merged_img = Image.merge('RGB', (red, green, blue)) + return merged_img +``` \ No newline at end of file diff --git a/docs/Image Monitor Effects Filter.md b/docs/Image Monitor Effects Filter.md new file mode 100644 index 0000000..aba164e --- /dev/null +++ b/docs/Image Monitor Effects Filter.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: WAS_Image_Monitor_Distortion_Filter +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Monitor_Distortion_Filter 节点旨在对图像应用各种失真效果,模拟不同类型的监视器或信号失真。它根据所选模式处理输入图像,可以是'Digital Distortion'、'Signal Distortion'或'TV Distortion',并使用振幅和偏移等参数来控制失真的强度。该节点非常多功能,适用于从视觉效果到艺术图像转换的广泛应用。 + +# Input types +## Required +- image + - 将要经历失真处理的输入图像。它作为节点应用所选失真效果的基础,其质量和特性对最终输出有显著影响。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- mode + - 确定要应用于图像的失真效果类型。每种模式代表不同的失真风格,影响处理后图像的整体外观和感觉。 + - Comfy dtype: COMBO['Digital Distortion', 'Signal Distortion', 'TV Distortion'] + - Python dtype: str +- amplitude + - 控制失真效果的强度。较高的振幅值会导致更明显的失真,而较低的值则产生更微妙的效果。 + - Comfy dtype: INT + - Python dtype: int +- offset + - 调整失真效果的位置,允许微调失真的外观。它移动失真图案,可以改变最终结果的视觉动态。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 输出是经过处理的图像,应用了失真效果。它反映了输入图像的特性,同时展示了所选择的失真风格,可供进一步使用或展示。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Monitor_Distortion_Filter: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'mode': (['Digital Distortion', 'Signal Distortion', 'TV Distortion'],), 'amplitude': ('INT', {'default': 5, 'min': 1, 'max': 255, 'step': 1}), 'offset': ('INT', {'default': 10, 'min': 1, 'max': 255, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'image_monitor_filters' + CATEGORY = 'WAS Suite/Image/Filter' + + def image_monitor_filters(self, image, mode='Digital Distortion', amplitude=5, offset=5): + image = tensor2pil(image) + WTools = WAS_Tools_Class() + if mode: + if mode == 'Digital Distortion': + image = WTools.digital_distortion(image, amplitude, offset) + elif mode == 'Signal Distortion': + image = WTools.signal_distortion(image, amplitude) + elif mode == 'TV Distortion': + image = WTools.tv_vhs_distortion(image, amplitude) + else: + image = image + return (pil2tensor(image),) +``` \ No newline at end of file diff --git a/docs/Image Nova Filter.md b/docs/Image Nova Filter.md new file mode 100644 index 0000000..ba55104 --- /dev/null +++ b/docs/Image Nova Filter.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: WAS_Image_Nova_Filter +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Nova_Filter 类的 `nova_sine` 方法对图像应用正弦波失真,通过波浪状图案增强其视觉特征。这种方法旨在为图像处理工作流程引入一种创造性和艺术性效果,允许通过调整振幅和频率来控制失真的强度和尺度。 + +# Input types +## Required +- image + - 'image' 参数对于节点的操作至关重要,因为它是将要处理的输入图像。它直接影响节点的执行和最终结果,决定了正弦波失真的对象。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- amplitude + - 'amplitude' 参数控制应用于图像的正弦波失真的强度。它是决定视觉效果的关键因素,允许用户根据个人喜好微调效果。 + - Comfy dtype: FLOAT + - Python dtype: float +- frequency + - 'frequency' 参数决定应用于图像的正弦波模式的尺度。它对于调整波的周期至关重要,进而影响失真的整体外观。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output_image + - 'output_image' 是将正弦波失真应用于输入图像的结果。它代表了最终视觉上被改变的图像,带有节点功能所预期的创造性效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Nova_Filter: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'amplitude': ('FLOAT', {'default': 0.1, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'frequency': ('FLOAT', {'default': 3.14, 'min': 0.0, 'max': 100.0, 'step': 0.001})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'nova_sine' + CATEGORY = 'WAS Suite/Image/Filter' + + def nova_sine(self, image, amplitude, frequency): + img = tensor2pil(image) + img_array = np.array(img) + + def sine(x, freq, amp): + return amp * np.sin(2 * np.pi * freq * x) + resolution = img.info.get('dpi') + physical_size = img.size + if resolution is not None: + ppm = 25.4 / resolution + physical_size = tuple((int(pix * ppm) for pix in physical_size)) + max_freq = img.width / 2 + if frequency > max_freq: + frequency = max_freq + for i in range(img_array.shape[0]): + for j in range(img_array.shape[1]): + for k in range(img_array.shape[2]): + img_array[i, j, k] = int(sine(img_array[i, j, k] / 255, frequency, amplitude) * 255) + return (torch.from_numpy(img_array.astype(np.float32) / 255.0).unsqueeze(0),) +``` \ No newline at end of file diff --git a/docs/Image Padding.md b/docs/Image Padding.md new file mode 100644 index 0000000..11f9c37 --- /dev/null +++ b/docs/Image Padding.md @@ -0,0 +1,104 @@ +# Documentation +- Class name: WAS_Image_Padding +- Category: WAS Suite/Image/Transform +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Padding 节点旨在通过向图像边缘添加填充来增强图像,这对于各种图像处理任务(如数据增强或为机器学习模型准备图像)非常有用。它提供了一个高级功能,允许添加填充并可选地应用羽化效果,平滑地将填充边缘与原始图像混合。 + +# Input types +## Required +- image + - 图像参数是节点将处理的输入图像。它在节点的操作中起着核心作用,因为整个填充和羽化过程都应用于此图像。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- feathering + - 羽化参数决定了应用于图像填充边缘的羽化效果的程度。这是一个可选参数,可以增强填充的视觉平滑度。 + - Comfy dtype: INT + - Python dtype: int +- feather_second_pass + - feather_second_pass 参数控制是否对图像应用第二次羽化。这可以为填充的边缘增加额外的平滑度层。 + - Comfy dtype: COMBO[true, false] + - Python dtype: bool +- left_padding + - left_padding 参数指定要添加到图像左侧的填充量。它是一个重要参数,因为它直接影响图像的最终尺寸。 + - Comfy dtype: INT + - Python dtype: int +- right_padding + - right_padding 参数指定要添加到图像右侧的填充量。它对于控制填充图像的总宽度至关重要。 + - Comfy dtype: INT + - Python dtype: int +- top_padding + - top_padding 参数确定要添加到图像顶部的填充量。它是调整图像垂直尺寸的关键参数。 + - Comfy dtype: INT + - Python dtype: int +- bottom_padding + - bottom_padding 参数设置要添加到图像底部的填充量。它对于修改图像的总高度至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- padded_image + - padded_image 参数是节点的输出,即应用了指定填充的原始图像。它代表了图像填充过程的最终结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- padding_mask + - padding_mask 参数是额外的输出,提供了应用于图像的填充的视觉表示。它可以用于进一步处理或视觉检查。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Padding: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'feathering': ('INT', {'default': 120, 'min': 0, 'max': 2048, 'step': 1}), 'feather_second_pass': (['true', 'false'],), 'left_padding': ('INT', {'default': 512, 'min': 8, 'max': 48000, 'step': 1}), 'right_padding': ('INT', {'default': 512, 'min': 8, 'max': 48000, 'step': 1}), 'top_padding': ('INT', {'default': 512, 'min': 8, 'max': 48000, 'step': 1}), 'bottom_padding': ('INT', {'default': 512, 'min': 8, 'max': 48000, 'step': 1})}} + RETURN_TYPES = ('IMAGE', 'IMAGE') + FUNCTION = 'image_padding' + CATEGORY = 'WAS Suite/Image/Transform' + + def image_padding(self, image, feathering, left_padding, right_padding, top_padding, bottom_padding, feather_second_pass=True): + padding = self.apply_image_padding(tensor2pil(image), left_padding, right_padding, top_padding, bottom_padding, feathering, second_pass=True) + return (pil2tensor(padding[0]), pil2tensor(padding[1])) + + def apply_image_padding(self, image, left_pad=100, right_pad=100, top_pad=100, bottom_pad=100, feather_radius=50, second_pass=True): + mask = Image.new('L', image.size, 255) + draw = ImageDraw.Draw(mask) + draw.rectangle((0, 0, feather_radius * 2, image.height), fill=0) + draw.rectangle((image.width - feather_radius * 2, 0, image.width, image.height), fill=0) + draw.rectangle((0, 0, image.width, feather_radius * 2), fill=0) + draw.rectangle((0, image.height - feather_radius * 2, image.width, image.height), fill=0) + mask = mask.filter(ImageFilter.GaussianBlur(radius=feather_radius)) + if second_pass: + mask2 = Image.new('L', image.size, 255) + draw2 = ImageDraw.Draw(mask2) + feather_radius2 = int(feather_radius / 4) + draw2.rectangle((0, 0, feather_radius2 * 2, image.height), fill=0) + draw2.rectangle((image.width - feather_radius2 * 2, 0, image.width, image.height), fill=0) + draw2.rectangle((0, 0, image.width, feather_radius2 * 2), fill=0) + draw2.rectangle((0, image.height - feather_radius2 * 2, image.width, image.height), fill=0) + mask2 = mask2.filter(ImageFilter.GaussianBlur(radius=feather_radius2)) + feathered_im = Image.new('RGBA', image.size, (0, 0, 0, 0)) + feathered_im.paste(image, (0, 0), mask) + feathered_im.paste(image, (0, 0), mask) + feathered_im.paste(image, (0, 0), mask2) + feathered_im.paste(image, (0, 0), mask2) + else: + feathered_im = Image.new('RGBA', image.size, (0, 0, 0, 0)) + feathered_im.paste(image, (0, 0), mask) + new_size = (feathered_im.width + left_pad + right_pad, feathered_im.height + top_pad + bottom_pad) + new_im = Image.new('RGBA', new_size, (0, 0, 0, 0)) + new_im.paste(feathered_im, (left_pad, top_pad)) + padding_mask = Image.new('L', new_size, 0) + gradient = [int(255 * (1 - p[3] / 255)) if p[3] != 0 else 255 for p in new_im.getdata()] + padding_mask.putdata(gradient) + return (new_im, padding_mask.convert('RGB')) +``` \ No newline at end of file diff --git a/docs/Image Paste Crop by Location.md b/docs/Image Paste Crop by Location.md new file mode 100644 index 0000000..4e8bfe0 --- /dev/null +++ b/docs/Image Paste Crop by Location.md @@ -0,0 +1,114 @@ +# Documentation +- Class name: WAS_Image_Paste_Crop_Location +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Paste_Crop_Location 节点旨在通过在指定位置粘贴一张图片到另一张上,然后裁剪结果来操作和整合图片。它允许微调粘贴图片的混合度和锐度,从而在目标图片中提供无缝集成。 + +# Input types +## Required +- image + - 主图像,crop_image将被粘贴到其上。它作为操作的画布。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- crop_image + - 将被粘贴到主图像上的图片。它是粘贴和裁剪过程的主要对象。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- top + - 粘贴的图片在主图像上放置的垂直位置。它对于确定粘贴图片的确切位置至关重要。 + - Comfy dtype: INT + - Python dtype: int +- left + - 粘贴的图片在主图像上放置的水平位置。它与top参数一起工作,以设置粘贴位置。 + - Comfy dtype: INT + - Python dtype: int +- right + - 裁剪操作的右边界。它与left参数一起定义了裁剪区域的宽度。 + - Comfy dtype: INT + - Python dtype: int +- bottom + - 裁剪操作的下边界。它与top参数一起定义了裁剪区域的高度。 + - Comfy dtype: INT + - Python dtype: int +- crop_blending + - 粘贴图片的混合因子。它控制粘贴图片与主图片的混合程度,影响最终的视觉外观。 + - Comfy dtype: FLOAT + - Python dtype: float +- crop_sharpening + - 粘贴图片的锐化级别。增加此值将增强粘贴图片的锐度,使其更加突出。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result_image + - 粘贴和裁剪过程后的最终图像,包括集成了粘贴并裁剪图片的主图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- result_mask + - 由混合过程产生的遮罩图像,可以用于进一步的图像操作或作为透明度遮罩。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Paste_Crop_Location: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'crop_image': ('IMAGE',), 'top': ('INT', {'default': 0, 'max': 10000000, 'min': 0, 'step': 1}), 'left': ('INT', {'default': 0, 'max': 10000000, 'min': 0, 'step': 1}), 'right': ('INT', {'default': 256, 'max': 10000000, 'min': 0, 'step': 1}), 'bottom': ('INT', {'default': 256, 'max': 10000000, 'min': 0, 'step': 1}), 'crop_blending': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'crop_sharpening': ('INT', {'default': 0, 'min': 0, 'max': 3, 'step': 1})}} + RETURN_TYPES = ('IMAGE', 'IMAGE') + FUNCTION = 'image_paste_crop_location' + CATEGORY = 'WAS Suite/Image/Process' + + def image_paste_crop_location(self, image, crop_image, top=0, left=0, right=256, bottom=256, crop_blending=0.25, crop_sharpening=0): + (result_image, result_mask) = self.paste_image(tensor2pil(image), tensor2pil(crop_image), top, left, right, bottom, crop_blending, crop_sharpening) + return (result_image, result_mask) + + def paste_image(self, image, crop_image, top=0, left=0, right=256, bottom=256, blend_amount=0.25, sharpen_amount=1): + image = image.convert('RGBA') + crop_image = crop_image.convert('RGBA') + + def inset_border(image, border_width=20, border_color=0): + (width, height) = image.size + bordered_image = Image.new(image.mode, (width, height), border_color) + bordered_image.paste(image, (0, 0)) + draw = ImageDraw.Draw(bordered_image) + draw.rectangle((0, 0, width - 1, height - 1), outline=border_color, width=border_width) + return bordered_image + (img_width, img_height) = image.size + top = min(max(top, 0), img_height) + left = min(max(left, 0), img_width) + bottom = min(max(bottom, 0), img_height) + right = min(max(right, 0), img_width) + crop_size = (right - left, bottom - top) + crop_img = crop_image.resize(crop_size) + crop_img = crop_img.convert('RGBA') + if sharpen_amount > 0: + for _ in range(sharpen_amount): + crop_img = crop_img.filter(ImageFilter.SHARPEN) + if blend_amount > 1.0: + blend_amount = 1.0 + elif blend_amount < 0.0: + blend_amount = 0.0 + blend_ratio = max(crop_size) / 2 * float(blend_amount) + blend = image.copy() + mask = Image.new('L', image.size, 0) + mask_block = Image.new('L', crop_size, 255) + mask_block = inset_border(mask_block, int(blend_ratio / 2), 0) + Image.Image.paste(mask, mask_block, (left, top)) + blend.paste(crop_img, (left, top), crop_img) + mask = mask.filter(ImageFilter.BoxBlur(radius=blend_ratio / 4)) + mask = mask.filter(ImageFilter.GaussianBlur(radius=blend_ratio / 4)) + blend.putalpha(mask) + image = Image.alpha_composite(image, blend) + return (pil2tensor(image), pil2tensor(mask.convert('RGB'))) +``` \ No newline at end of file diff --git a/docs/Image Paste Crop.md b/docs/Image Paste Crop.md new file mode 100644 index 0000000..33e48dd --- /dev/null +++ b/docs/Image Paste Crop.md @@ -0,0 +1,127 @@ +# Documentation +- Class name: WAS_Image_Paste_Crop +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Paste_Crop节点旨在通过将一个次级图像粘贴到主图像上,然后进行裁剪和混合来集成和操作图像。它允许微调混合和锐化效果,以实现图像的无缝集成。 + +# Input types +## Required +- image + - 主图像,次级图像将被粘贴到其上。它作为整个操作的基础,其属性影响最终输出。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- crop_image + - 将被粘贴到主图像上的次级图像。根据提供的裁剪数据进行调整大小和定位。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- crop_data + - 定义裁剪操作的大小和位置。对于确定次级图像如何集成到主图像中至关重要。 + - Comfy dtype: CROP_DATA + - Python dtype: Tuple[int, Tuple[int, int, int, int]] +## Optional +- crop_blending + - 控制图像之间的混合量。较高的值会在图像之间产生更平滑的过渡,而较低的值则使次级图像更加突出。 + - Comfy dtype: FLOAT + - Python dtype: float +- crop_sharpening + - 调整应用于次级图像的锐化级别。增加此值可以增强图像细节,这对于使粘贴的图像更加清晰非常有用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result_image + - 粘贴和裁剪操作后最终处理的图像。它代表了次级图像与主图像的无缝集成以及应用的效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- result_mask + - 由裁剪操作生成的遮罩,可用于进一步的图像处理任务,或将粘贴的图像与主图像隔离开来。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Paste_Crop: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'crop_image': ('IMAGE',), 'crop_data': ('CROP_DATA',), 'crop_blending': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'crop_sharpening': ('INT', {'default': 0, 'min': 0, 'max': 3, 'step': 1})}} + RETURN_TYPES = ('IMAGE', 'IMAGE') + FUNCTION = 'image_paste_crop' + CATEGORY = 'WAS Suite/Image/Process' + + def image_paste_crop(self, image, crop_image, crop_data=None, crop_blending=0.25, crop_sharpening=0): + if crop_data == False: + cstr('No valid crop data found!').error.print() + return (image, pil2tensor(Image.new('RGB', tensor2pil(image).size, (0, 0, 0)))) + (result_image, result_mask) = self.paste_image(tensor2pil(image), tensor2pil(crop_image), crop_data, crop_blending, crop_sharpening) + return (result_image, result_mask) + + def paste_image(self, image, crop_image, crop_data, blend_amount=0.25, sharpen_amount=1): + + def lingrad(size, direction, white_ratio): + image = Image.new('RGB', size) + draw = ImageDraw.Draw(image) + if direction == 'vertical': + black_end = int(size[1] * (1 - white_ratio)) + range_start = 0 + range_end = size[1] + range_step = 1 + for y in range(range_start, range_end, range_step): + color_ratio = y / size[1] + if y <= black_end: + color = (0, 0, 0) + else: + color_value = int((y - black_end) / (size[1] - black_end) * 255) + color = (color_value, color_value, color_value) + draw.line([(0, y), (size[0], y)], fill=color) + elif direction == 'horizontal': + black_end = int(size[0] * (1 - white_ratio)) + range_start = 0 + range_end = size[0] + range_step = 1 + for x in range(range_start, range_end, range_step): + color_ratio = x / size[0] + if x <= black_end: + color = (0, 0, 0) + else: + color_value = int((x - black_end) / (size[0] - black_end) * 255) + color = (color_value, color_value, color_value) + draw.line([(x, 0), (x, size[1])], fill=color) + return image.convert('L') + (crop_size, (left, top, right, bottom)) = crop_data + crop_image = crop_image.resize(crop_size) + if sharpen_amount > 0: + for _ in range(int(sharpen_amount)): + crop_image = crop_image.filter(ImageFilter.SHARPEN) + blended_image = Image.new('RGBA', image.size, (0, 0, 0, 255)) + blended_mask = Image.new('L', image.size, 0) + crop_padded = Image.new('RGBA', image.size, (0, 0, 0, 0)) + blended_image.paste(image, (0, 0)) + crop_padded.paste(crop_image, (left, top)) + crop_mask = Image.new('L', crop_image.size, 0) + if top > 0: + gradient_image = ImageOps.flip(lingrad(crop_image.size, 'vertical', blend_amount)) + crop_mask = ImageChops.screen(crop_mask, gradient_image) + if left > 0: + gradient_image = ImageOps.mirror(lingrad(crop_image.size, 'horizontal', blend_amount)) + crop_mask = ImageChops.screen(crop_mask, gradient_image) + if right < image.width: + gradient_image = lingrad(crop_image.size, 'horizontal', blend_amount) + crop_mask = ImageChops.screen(crop_mask, gradient_image) + if bottom < image.height: + gradient_image = lingrad(crop_image.size, 'vertical', blend_amount) + crop_mask = ImageChops.screen(crop_mask, gradient_image) + crop_mask = ImageOps.invert(crop_mask) + blended_mask.paste(crop_mask, (left, top)) + blended_mask = blended_mask.convert('L') + blended_image.paste(crop_padded, (0, 0), blended_mask) + return (pil2tensor(blended_image.convert('RGB')), pil2tensor(blended_mask.convert('RGB'))) +``` \ No newline at end of file diff --git a/docs/Image Paste Face.md b/docs/Image Paste Face.md new file mode 100644 index 0000000..a101318 --- /dev/null +++ b/docs/Image Paste Face.md @@ -0,0 +1,128 @@ +# Documentation +- Class name: WAS_Image_Paste_Face_Crop +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Paste_Face_Crop 节点旨在将裁剪过的人脸图像整合到更大的图像中,增强最终输出的视觉吸引力和一致性。它采用先进的融合技术,确保图像之间的无缝融合,并能够调整融合和锐化参数以获得最佳效果。 + +# Input types +## Required +- image + - 要将人脸图像粘贴进去的主图像。此参数至关重要,因为它定义了操作的画布并影响最终的构图。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- crop_image + - 将被粘贴到主图像上的人脸图像。此图像的质量和分辨率直接影响最终结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- crop_data + - 定义人脸图像裁剪区域的数据,包括大小和位置。此参数对于确定人脸图像在主图像内的位置至关重要。 + - Comfy dtype: CROP_DATA + - Python dtype: Tuple[int, Tuple[int, int, int, int]] +- crop_blending + - 将人脸图像粘贴到主图像时的混合因子。它控制图像之间的过渡,以获得更自然的外观。 + - Comfy dtype: FLOAT + - Python dtype: float +- crop_sharpening + - 在粘贴之前要应用于人脸图像的图像锐化级别。数值越高,人脸图像越清晰、定义越明确。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - 最终图像,将人脸图像粘贴到主图像上,展示了混合和锐化过程的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- MASK_IMAGE + - 表示透明度和受混合过程影响区域的遮罩图像,适用于进一步的图像操作。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Paste_Face_Crop: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'crop_image': ('IMAGE',), 'crop_data': ('CROP_DATA',), 'crop_blending': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'crop_sharpening': ('INT', {'default': 0, 'min': 0, 'max': 3, 'step': 1})}} + RETURN_TYPES = ('IMAGE', 'IMAGE') + RETURN_NAMES = ('IMAGE', 'MASK_IMAGE') + FUNCTION = 'image_paste_face' + CATEGORY = 'WAS Suite/Image/Process' + + def image_paste_face(self, image, crop_image, crop_data=None, crop_blending=0.25, crop_sharpening=0): + if crop_data == False: + cstr('No valid crop data found!').error.print() + return (image, pil2tensor(Image.new('RGB', tensor2pil(image).size, (0, 0, 0)))) + (result_image, result_mask) = self.paste_image(tensor2pil(image), tensor2pil(crop_image), crop_data, crop_blending, crop_sharpening) + return (result_image, result_mask) + + def paste_image(self, image, crop_image, crop_data, blend_amount=0.25, sharpen_amount=1): + + def lingrad(size, direction, white_ratio): + image = Image.new('RGB', size) + draw = ImageDraw.Draw(image) + if direction == 'vertical': + black_end = int(size[1] * (1 - white_ratio)) + range_start = 0 + range_end = size[1] + range_step = 1 + for y in range(range_start, range_end, range_step): + color_ratio = y / size[1] + if y <= black_end: + color = (0, 0, 0) + else: + color_value = int((y - black_end) / (size[1] - black_end) * 255) + color = (color_value, color_value, color_value) + draw.line([(0, y), (size[0], y)], fill=color) + elif direction == 'horizontal': + black_end = int(size[0] * (1 - white_ratio)) + range_start = 0 + range_end = size[0] + range_step = 1 + for x in range(range_start, range_end, range_step): + color_ratio = x / size[0] + if x <= black_end: + color = (0, 0, 0) + else: + color_value = int((x - black_end) / (size[0] - black_end) * 255) + color = (color_value, color_value, color_value) + draw.line([(x, 0), (x, size[1])], fill=color) + return image.convert('L') + (crop_size, (top, left, right, bottom)) = crop_data + crop_image = crop_image.resize(crop_size) + if sharpen_amount > 0: + for _ in range(int(sharpen_amount)): + crop_image = crop_image.filter(ImageFilter.SHARPEN) + blended_image = Image.new('RGBA', image.size, (0, 0, 0, 255)) + blended_mask = Image.new('L', image.size, 0) + crop_padded = Image.new('RGBA', image.size, (0, 0, 0, 0)) + blended_image.paste(image, (0, 0)) + crop_padded.paste(crop_image, (top, left)) + crop_mask = Image.new('L', crop_image.size, 0) + if top > 0: + gradient_image = ImageOps.flip(lingrad(crop_image.size, 'vertical', blend_amount)) + crop_mask = ImageChops.screen(crop_mask, gradient_image) + if left > 0: + gradient_image = ImageOps.mirror(lingrad(crop_image.size, 'horizontal', blend_amount)) + crop_mask = ImageChops.screen(crop_mask, gradient_image) + if right < image.width: + gradient_image = lingrad(crop_image.size, 'horizontal', blend_amount) + crop_mask = ImageChops.screen(crop_mask, gradient_image) + if bottom < image.height: + gradient_image = lingrad(crop_image.size, 'vertical', blend_amount) + crop_mask = ImageChops.screen(crop_mask, gradient_image) + crop_mask = ImageOps.invert(crop_mask) + blended_mask.paste(crop_mask, (top, left)) + blended_mask = blended_mask.convert('L') + blended_image.paste(crop_padded, (0, 0), blended_mask) + return (pil2tensor(blended_image.convert('RGB')), pil2tensor(blended_mask.convert('RGB'))) +``` \ No newline at end of file diff --git a/docs/Image Perlin Noise.md b/docs/Image Perlin Noise.md new file mode 100644 index 0000000..8e9edfe --- /dev/null +++ b/docs/Image Perlin Noise.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: WAS_Image_Perlin_Noise +- Category: WAS Suite/Image/Generate/Noise +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Perlin_Noise 节点旨在生成 Perlin 噪声模式,这些模式可以用于各种图形应用程序中,用于创建自然纹理。它通过利用 Python 成像库根据指定的参数(如宽度、高度、缩放、八度、持续性和可选的随机种子)生成具有程序性噪声的图像。这个节点对于寻求在项目中引入有机和多样化纹理的用户非常有益,无需外部图像资产。 + +# Input types +## Required +- width + - ‘宽度’参数决定了生成的噪声图像的水平分辨率。这是定义输出尺寸的关键因素,影响噪声模式在图形应用程序中的显示和使用方式。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘高度’参数设置噪声图像的垂直分辨率。与‘宽度’一起,它建立了Perlin噪声将被渲染的图像画布,影响查看噪声细节的比例。 + - Comfy dtype: INT + - Python dtype: int +- scale + - ‘缩放’参数调整Perlin噪声单元的大小。它改变了噪声模式的密度,较高的值会导致更复杂和更小的噪声单元,而较低的值则产生更稀疏和更大的单元。 + - Comfy dtype: INT + - Python dtype: int +- octaves + - ‘八度’参数控制构建噪声模式所使用的频率级别数量。更多的八度为噪声增添复杂性和细节,创造出更自然和多样化的纹理。 + - Comfy dtype: INT + - Python dtype: int +- persistence + - ‘持续性’参数定义了振幅在连续八度之间降低的速率。它影响不同噪声层之间的对比度,有助于整体纹理特征的形成。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- seed + - ‘种子’参数是用于初始化随机数生成器的可选整数,确保可重复的噪声模式。当使用相同的种子值时,它允许产生一致的结果。 + - Comfy dtype: INT + - Python dtype: Optional[int] + +# Output types +- image + - '图像'输出提供生成的Perlin噪声作为图像。它可以进一步操作或直接用于图形应用程序中的纹理目的。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Perlin_Noise: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'width': ('INT', {'default': 512, 'max': 2048, 'min': 64, 'step': 1}), 'height': ('INT', {'default': 512, 'max': 2048, 'min': 64, 'step': 1}), 'scale': ('INT', {'default': 100, 'max': 2048, 'min': 2, 'step': 1}), 'octaves': ('INT', {'default': 4, 'max': 8, 'min': 0, 'step': 1}), 'persistence': ('FLOAT', {'default': 0.5, 'max': 100.0, 'min': 0.01, 'step': 0.01}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'perlin_noise' + CATEGORY = 'WAS Suite/Image/Generate/Noise' + + def perlin_noise(self, width, height, scale, octaves, persistence, seed): + WTools = WAS_Tools_Class() + image = WTools.perlin_noise(width, height, octaves, persistence, scale, seed) + return (pil2tensor(image),) +``` \ No newline at end of file diff --git a/docs/Image Perlin Power Fractal.md b/docs/Image Perlin Power Fractal.md new file mode 100644 index 0000000..d09e27f --- /dev/null +++ b/docs/Image Perlin Power Fractal.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: WAS_Image_Perlin_Power_Fractal +- Category: WAS Suite/Image/Generate/Noise +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Perlin_Power_Fractal 节点旨在程序化生成分形噪声模式,这些模式可用于创建复杂纹理。它利用 Perlin 噪声算法产生自然和谐且无缝的噪声结构,可以无限平铺。该节点特别适用于为3D模型、游戏环境或任何需要连贯且可重复纹理的应用生成纹理。 + +# Input types +## Required +- width + - 宽度参数定义了生成纹理的宽度,以像素为单位。它对于设置输出图像的水平分辨率和影响纹理的整体尺寸至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数确定了生成纹理的垂直范围,以像素为单位。它与宽度参数一起工作,以确定输出图像的完整分辨率。 + - Comfy dtype: INT + - Python dtype: int +- scale + - 比例参数影响生成纹理的细节水平。较高的比例值会产生更详细且更小的噪声模式,而较低的值则产生更粗糙且更广泛的模式。 + - Comfy dtype: INT + - Python dtype: int +- octaves + - 八度参数控制生成分形噪声所使用的频率数量。更多的八度会创造出更复杂和详细的纹理,但也会提高计算成本。 + - Comfy dtype: INT + - Python dtype: int +- persistence + - 持续性参数定义了每个连续的八度对整体噪声模式的贡献程度。它影响不同噪声层之间的对比度。 + - Comfy dtype: FLOAT + - Python dtype: float +- lacunarity + - 间隙率参数规定了连续八度之间的频率间隔。较高的间隙率值会在较小尺度上产生更碎片化和详细的纹理。 + - Comfy dtype: FLOAT + - Python dtype: float +- exponent + - 指数参数调整分形噪声中每个八度的振幅。它塑造了整体噪声模式,并可用于创建更精细的纹理。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- seed + - 种子参数用于生成确定性的噪声模式。它确保相同的种子始终产生相同的纹理,促进多张图像或应用之间的一致性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 输出图像是由 Perlin 功率分形函数生成的无缝且可平铺的纹理。它可以直接用于图形应用程序,或根据特定需求进行进一步处理。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Perlin_Power_Fractal: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'width': ('INT', {'default': 512, 'max': 8192, 'min': 64, 'step': 1}), 'height': ('INT', {'default': 512, 'max': 8192, 'min': 64, 'step': 1}), 'scale': ('INT', {'default': 100, 'max': 2048, 'min': 2, 'step': 1}), 'octaves': ('INT', {'default': 4, 'max': 8, 'min': 0, 'step': 1}), 'persistence': ('FLOAT', {'default': 0.5, 'max': 100.0, 'min': 0.01, 'step': 0.01}), 'lacunarity': ('FLOAT', {'default': 2.0, 'max': 100.0, 'min': 0.01, 'step': 0.01}), 'exponent': ('FLOAT', {'default': 2.0, 'max': 100.0, 'min': 0.01, 'step': 0.01}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'perlin_power_fractal' + CATEGORY = 'WAS Suite/Image/Generate/Noise' + + def perlin_power_fractal(self, width, height, scale, octaves, persistence, lacunarity, exponent, seed): + WTools = WAS_Tools_Class() + image = WTools.perlin_power_fractal(width, height, octaves, persistence, lacunarity, exponent, scale, seed) + return (pil2tensor(image),) +``` \ No newline at end of file diff --git a/docs/Image Pixelate.md b/docs/Image Pixelate.md new file mode 100644 index 0000000..6e776f6 --- /dev/null +++ b/docs/Image Pixelate.md @@ -0,0 +1,277 @@ +# Documentation +- Class name: WAS_Image_Pixelate +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Pixelate 节点旨在将图像转换为像素化艺术风格。它通过减少图像中使用的颜色数量并应用各种像素化技术来实现这一点。节点可以处理一系列参数以定制像素化过程,包括大小、颜色计数和抖动选项,从而为最终输出提供了高度的创意控制。 + +# Input types +## Required +- images + - 输入图像将由节点处理。这些图像将经历像素化转换,以创建风格化的像素化版本。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or List[PIL.Image.Image] +## Optional +- pixelation_size + - 像素化效果的目标大小。较大的值会导致更明显的像素化,而较小的值则创造出更精细、像素化程度较低的外观。 + - Comfy dtype: FLOAT + - Python dtype: float +- num_colors + - 将图像减少到的颜色数量。此参数直接影响像素化结果的复杂性,数值越低,导致更抽象的表现。 + - Comfy dtype: FLOAT + - Python dtype: float +- init_mode + - 用于确定像素化图像颜色的k-means聚类算法的初始化模式。 + - Comfy dtype: COMBO['k-means++', 'random', 'none'] + - Python dtype: str +- max_iterations + - k-means聚类算法运行的最大迭代次数。更多的迭代可以导致更好的颜色聚类,但可能会增加处理时间。 + - Comfy dtype: FLOAT + - Python dtype: float +- dither + - 一个布尔标志,用于确定是否对像素化图像应用抖动。抖动可以帮助在颜色之间创建更平滑的过渡,但可能会牺牲一些细节。 + - Comfy dtype: COMBO['False', 'True'] + - Python dtype: bool +- dither_mode + - 如果启用了抖动,则应用的抖动模式。不同的模式可以在最终图像中产生不同的视觉效果。 + - Comfy dtype: COMBO['FloydSteinberg', 'Ordered'] + - Python dtype: str +- color_palettes + - 用于像素化的可选自定义调色板。每个调色板应该是一个十六进制颜色字符串的列表。 + - Comfy dtype: LIST + - Python dtype: List[str] +- color_palette_mode + - 从调色板映射颜色到像素化图像时使用的模式。 + - Comfy dtype: COMBO['Brightness', 'BrightnessAndTonal', 'Linear', 'Tonal'] + - Python dtype: str +- reverse_palette + - 一个标志,指示在应用于像素化图像时是否反转调色板中颜色的顺序。 + - Comfy dtype: COMBO['False', 'True'] + - Python dtype: bool + +# Output types +- images + - 使用指定参数处理后的像素化图像的结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or List[PIL.Image.Image] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Pixelate: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'pixelation_size': ('FLOAT', {'default': 164, 'min': 16, 'max': 480, 'step': 1}), 'num_colors': ('FLOAT', {'default': 16, 'min': 2, 'max': 256, 'step': 1}), 'init_mode': (['k-means++', 'random', 'none'],), 'max_iterations': ('FLOAT', {'default': 100, 'min': 1, 'max': 256, 'step': 1}), 'dither': (['False', 'True'],), 'dither_mode': (['FloydSteinberg', 'Ordered'],)}, 'optional': {'color_palettes': ('LIST', {'forceInput': True}), 'color_palette_mode': (['Brightness', 'BrightnessAndTonal', 'Linear', 'Tonal'],), 'reverse_palette': (['False', 'True'],)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('images',) + FUNCTION = 'image_pixelate' + CATEGORY = 'WAS Suite/Image/Process' + + def image_pixelate(self, images, pixelation_size=164, num_colors=16, init_mode='random', max_iterations=100, color_palettes=None, color_palette_mode='Linear', reverse_palette='False', dither='False', dither_mode='FloydSteinberg'): + if 'scikit-learn' not in packages(): + install_package('scikit-learn') + pixelation_size = int(pixelation_size) + num_colors = int(num_colors) + max_iterations = int(max_iterations) + color_palette_mode = color_palette_mode + dither = dither == 'True' + color_palettes_list = [] + if color_palettes: + for palette in color_palettes: + color_palettes_list.append([color.strip() for color in palette.splitlines() if not color.startswith('//') or not color.startswith(';')]) + reverse_palette = True if reverse_palette == 'True' else False + return (self.pixel_art_batch(images, pixelation_size, num_colors, init_mode, max_iterations, 42, color_palettes_list if color_palettes_list else None, color_palette_mode, reverse_palette, dither, dither_mode),) + + def pixel_art_batch(self, batch, min_size, num_colors=16, init_mode='random', max_iter=100, random_state=42, palette=None, palette_mode='Linear', reverse_palette=False, dither=False, dither_mode='FloydSteinberg'): + from sklearn.cluster import KMeans + hex_palette_to_rgb = lambda hex: tuple((int(hex[i:i + 2], 16) for i in (0, 2, 4))) + + def flatten_colors(image, num_colors, init_mode='random', max_iter=100, random_state=42): + np_image = np.array(image) + pixels = np_image.reshape(-1, 3) + kmeans = KMeans(n_clusters=num_colors, init=init_mode, max_iter=max_iter, tol=0.001, random_state=random_state, n_init='auto') + labels = kmeans.fit_predict(pixels) + colors = kmeans.cluster_centers_.astype(np.uint8) + flattened_pixels = colors[labels] + flattened_image = flattened_pixels.reshape(np_image.shape) + return Image.fromarray(flattened_image) + + def dither_image(image, mode, nc): + + def clamp(value, min_value=0, max_value=255): + return max(min(value, max_value), min_value) + + def get_new_val(old_val, nc): + return np.round(old_val * (nc - 1)) / (nc - 1) + + def fs_dither(img, nc): + arr = np.array(img, dtype=float) / 255 + (new_width, new_height) = img.size + for ir in range(new_height): + for ic in range(new_width): + old_val = arr[ir, ic].copy() + new_val = get_new_val(old_val, nc) + arr[ir, ic] = new_val + err = old_val - new_val + if ic < new_width - 1: + arr[ir, ic + 1] += err * 7 / 16 + if ir < new_height - 1: + if ic > 0: + arr[ir + 1, ic - 1] += err * 3 / 16 + arr[ir + 1, ic] += err * 5 / 16 + if ic < new_width - 1: + arr[ir + 1, ic + 1] += err / 16 + carr = np.array(arr * 255, dtype=np.uint8) + return Image.fromarray(carr) + + def ordered_dither(img, nc): + (width, height) = img.size + dither_matrix = [[0, 8, 2, 10], [12, 4, 14, 6], [3, 11, 1, 9], [15, 7, 13, 5]] + dithered_image = Image.new('RGB', (width, height)) + num_colors = min(2 ** int(np.log2(nc)), 16) + for y in range(height): + for x in range(width): + old_pixel = img.getpixel((x, y)) + threshold = dither_matrix[x % 4][y % 4] * num_colors + new_pixel = tuple((int(c * num_colors / 256) * (256 // num_colors) for c in old_pixel)) + error = tuple((old - new for (old, new) in zip(old_pixel, new_pixel))) + dithered_image.putpixel((x, y), new_pixel) + if x < width - 1: + neighboring_pixel = img.getpixel((x + 1, y)) + neighboring_pixel = tuple((int(c * num_colors / 256) * (256 // num_colors) for c in neighboring_pixel)) + neighboring_error = tuple((neighboring - new for (neighboring, new) in zip(neighboring_pixel, new_pixel))) + neighboring_pixel = tuple((int(clamp(pixel + error * 7 / 16)) for (pixel, error) in zip(neighboring_pixel, neighboring_error))) + img.putpixel((x + 1, y), neighboring_pixel) + if x < width - 1 and y < height - 1: + neighboring_pixel = img.getpixel((x + 1, y + 1)) + neighboring_pixel = tuple((int(c * num_colors / 256) * (256 // num_colors) for c in neighboring_pixel)) + neighboring_error = tuple((neighboring - new for (neighboring, new) in zip(neighboring_pixel, new_pixel))) + neighboring_pixel = tuple((int(clamp(pixel + error * 1 / 16)) for (pixel, error) in zip(neighboring_pixel, neighboring_error))) + img.putpixel((x + 1, y + 1), neighboring_pixel) + if y < height - 1: + neighboring_pixel = img.getpixel((x, y + 1)) + neighboring_pixel = tuple((int(c * num_colors / 256) * (256 // num_colors) for c in neighboring_pixel)) + neighboring_error = tuple((neighboring - new for (neighboring, new) in zip(neighboring_pixel, new_pixel))) + neighboring_pixel = tuple((int(clamp(pixel + error * 5 / 16)) for (pixel, error) in zip(neighboring_pixel, neighboring_error))) + img.putpixel((x, y + 1), neighboring_pixel) + if x > 0 and y < height - 1: + neighboring_pixel = img.getpixel((x - 1, y + 1)) + neighboring_pixel = tuple((int(c * num_colors / 256) * (256 // num_colors) for c in neighboring_pixel)) + neighboring_error = tuple((neighboring - new for (neighboring, new) in zip(neighboring_pixel, new_pixel))) + neighboring_pixel = tuple((int(clamp(pixel + error * 3 / 16)) for (pixel, error) in zip(neighboring_pixel, neighboring_error))) + img.putpixel((x - 1, y + 1), neighboring_pixel) + return dithered_image + if mode == 'FloydSteinberg': + return fs_dither(image, nc) + elif mode == 'Ordered': + return ordered_dither(image, nc) + else: + cstr(f'Inavlid dithering mode `{mode}` selected.').error.print() + return image + return image + + def color_palette_from_hex_lines(image, colors, palette_mode='Linear', reverse_palette=False): + + def color_distance(color1, color2): + (r1, g1, b1) = color1 + (r2, g2, b2) = color2 + return np.sqrt((r1 - r2) ** 2 + (g1 - g2) ** 2 + (b1 - b2) ** 2) + + def find_nearest_color_index(color, palette): + distances = [color_distance(color, palette_color) for palette_color in palette] + return distances.index(min(distances)) + + def find_nearest_color_index_tonal(color, palette): + distances = [color_distance_tonal(color, palette_color) for palette_color in palette] + return distances.index(min(distances)) + + def find_nearest_color_index_both(color, palette): + distances = [color_distance_both(color, palette_color) for palette_color in palette] + return distances.index(min(distances)) + + def color_distance_tonal(color1, color2): + (r1, g1, b1) = color1 + (r2, g2, b2) = color2 + l1 = 0.299 * r1 + 0.587 * g1 + 0.114 * b1 + l2 = 0.299 * r2 + 0.587 * g2 + 0.114 * b2 + return abs(l1 - l2) + + def color_distance_both(color1, color2): + (r1, g1, b1) = color1 + (r2, g2, b2) = color2 + l1 = 0.299 * r1 + 0.587 * g1 + 0.114 * b1 + l2 = 0.299 * r2 + 0.587 * g2 + 0.114 * b2 + return abs(l1 - l2) + sum((abs(c1 - c2) for (c1, c2) in zip(color1, color2))) + + def color_distance(color1, color2): + return sum((abs(c1 - c2) for (c1, c2) in zip(color1, color2))) + color_palette = [hex_palette_to_rgb(color.lstrip('#')) for color in colors] + if reverse_palette: + color_palette = color_palette[::-1] + np_image = np.array(image) + labels = np_image.reshape(image.size[1], image.size[0], -1) + (width, height) = image.size + new_image = Image.new('RGB', image.size) + if palette_mode == 'Linear': + color_palette_indices = list(range(len(color_palette))) + elif palette_mode == 'Brightness': + color_palette_indices = sorted(range(len(color_palette)), key=lambda i: sum(color_palette[i]) / 3) + elif palette_mode == 'Tonal': + color_palette_indices = sorted(range(len(color_palette)), key=lambda i: color_distance(color_palette[i], (128, 128, 128))) + elif palette_mode == 'BrightnessAndTonal': + color_palette_indices = sorted(range(len(color_palette)), key=lambda i: (sum(color_palette[i]) / 3, color_distance(color_palette[i], (128, 128, 128)))) + else: + raise ValueError(f'Unsupported mapping mode: {palette_mode}') + for x in range(width): + for y in range(height): + pixel_color = labels[y, x, :] + if palette_mode == 'Linear': + color_index = pixel_color[0] % len(color_palette) + elif palette_mode == 'Brightness': + color_index = find_nearest_color_index(pixel_color, [color_palette[i] for i in color_palette_indices]) + elif palette_mode == 'Tonal': + color_index = find_nearest_color_index_tonal(pixel_color, [color_palette[i] for i in color_palette_indices]) + elif palette_mode == 'BrightnessAndTonal': + color_index = find_nearest_color_index_both(pixel_color, [color_palette[i] for i in color_palette_indices]) + else: + raise ValueError(f'Unsupported mapping mode: {palette_mode}') + color = color_palette[color_palette_indices[color_index]] + new_image.putpixel((x, y), color) + return new_image + pil_images = [tensor2pil(image) for image in batch] + pixel_art_images = [] + original_sizes = [] + total_images = len(pil_images) + for image in pil_images: + (width, height) = image.size + original_sizes.append((width, height)) + if max(width, height) > min_size: + if width > height: + new_width = min_size + new_height = int(height * (min_size / width)) + else: + new_height = min_size + new_width = int(width * (min_size / height)) + pixel_art_images.append(image.resize((new_width, int(new_height)), Image.NEAREST)) + else: + pixel_art_images.append(image) + if init_mode != 'none': + pixel_art_images = [flatten_colors(image, num_colors, init_mode) for image in pixel_art_images] + if dither: + pixel_art_images = [dither_image(image, dither_mode, num_colors) for image in pixel_art_images] + if palette: + pixel_art_images = [color_palette_from_hex_lines(pixel_art_image, palette[i], palette_mode, reverse_palette) for (i, pixel_art_image) in enumerate(pixel_art_images)] + else: + pixel_art_images = pixel_art_images + pixel_art_images = [image.resize(size, Image.NEAREST) for (image, size) in zip(pixel_art_images, original_sizes)] + tensor_images = [pil2tensor(image) for image in pixel_art_images] + batch_tensor = torch.cat(tensor_images, dim=0) + return batch_tensor +``` \ No newline at end of file diff --git a/docs/Image Power Noise.md b/docs/Image Power Noise.md new file mode 100644 index 0000000..965a515 --- /dev/null +++ b/docs/Image Power Noise.md @@ -0,0 +1,192 @@ +# Documentation +- Class name: WAS_Image_Power_Noise +- Category: WAS Suite/Image/Generate/Noise +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +power_noise 方法旨在生成可用作图像处理或作为数字纹理的不同类型的噪声模式。它提供创建白色、灰色、粉红、绿色、蓝色或混合噪声的功能,基于指定的参数,如宽度、高度、频率和衰减,提供了一个根据不同需求定制噪声生成的多功能工具。 + +# Input types +## Required +- width + - width 参数定义了要生成的噪声图像的宽度。它至关重要,因为它决定了输出图像的水平分辨率,影响整体细节和纵横比。 + - Comfy dtype: INT + - Python dtype: int +- height + - height 参数设置了噪声图像的垂直尺寸。它对于建立图像的垂直分辨率至关重要,并且与宽度一起定义了输出的整体形状。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- frequency + - frequency 参数用于调整噪声模式的尺度。它对于粉红、绿色和蓝色噪声类型特别重要,影响噪声的频谱内容,从而影响视觉纹理。 + - Comfy dtype: FLOAT + - Python dtype: float +- attenuation + - 衰减通过调整灰噪声生成过程中的标准偏差来影响噪声的对比度。这是一个重要的参数,控制着噪声模式的可见性和强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- noise_type + - 要生成的噪声类型,选项包括灰色、白色、粉红、蓝色、绿色或这些的混合。每种类型产生不同的视觉效果,提供适用于不同应用的一系列噪声特性。 + - Comfy dtype: COMBO[grey, white, pink, blue, green, mix] + - Python dtype: str +- seed + - seed 参数用于初始化随机数生成器,确保噪声模式的可重复性。它是一个可选参数,为噪声的随机性提供控制,以获得一致的结果。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 输出图像参数表示生成的噪声模式作为图像。它是 power_noise 方法的主要结果,将指定的噪声特性封装在视觉格式中。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Power_Noise: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'width': ('INT', {'default': 512, 'max': 4096, 'min': 64, 'step': 1}), 'height': ('INT', {'default': 512, 'max': 4096, 'min': 64, 'step': 1}), 'frequency': ('FLOAT', {'default': 0.5, 'max': 10.0, 'min': 0.0, 'step': 0.01}), 'attenuation': ('FLOAT', {'default': 0.5, 'max': 10.0, 'min': 0.0, 'step': 0.01}), 'noise_type': (['grey', 'white', 'pink', 'blue', 'green', 'mix'],), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'power_noise' + CATEGORY = 'WAS Suite/Image/Generate/Noise' + + def power_noise(self, width, height, frequency, attenuation, noise_type, seed): + noise_image = self.generate_power_noise(width, height, frequency, attenuation, noise_type, seed) + return (pil2tensor(noise_image),) + + def generate_power_noise(self, width, height, frequency=None, attenuation=None, noise_type='white', seed=None): + + def white_noise(width, height): + noise = np.random.random((height, width)) + return noise + + def grey_noise(width, height, attenuation): + noise = np.random.normal(0, attenuation, (height, width)) + return noise + + def blue_noise(width, height, frequency, attenuation): + noise = grey_noise(width, height, attenuation) + scale = 1.0 / (width * height) + fy = np.fft.fftfreq(height)[:, np.newaxis] ** 2 + fx = np.fft.fftfreq(width) ** 2 + f = fy + fx + power = np.sqrt(f) + power[0, 0] = 1 + noise = np.fft.ifft2(np.fft.fft2(noise) / power) + noise *= scale / noise.std() + return np.real(noise) + + def green_noise(width, height, frequency, attenuation): + noise = grey_noise(width, height, attenuation) + scale = 1.0 / (width * height) + fy = np.fft.fftfreq(height)[:, np.newaxis] ** 2 + fx = np.fft.fftfreq(width) ** 2 + f = fy + fx + power = np.sqrt(f) + power[0, 0] = 1 + noise = np.fft.ifft2(np.fft.fft2(noise) / np.sqrt(power)) + noise *= scale / noise.std() + return np.real(noise) + + def pink_noise(width, height, frequency, attenuation): + noise = grey_noise(width, height, attenuation) + scale = 1.0 / (width * height) + fy = np.fft.fftfreq(height)[:, np.newaxis] ** 2 + fx = np.fft.fftfreq(width) ** 2 + f = fy + fx + power = np.sqrt(f) + power[0, 0] = 1 + noise = np.fft.ifft2(np.fft.fft2(noise) * power) + noise *= scale / noise.std() + return np.real(noise) + + def blue_noise_mask(width, height, frequency, attenuation, seed, num_masks=3): + masks = [] + for i in range(num_masks): + mask_seed = seed + i + np.random.seed(mask_seed) + mask = blue_noise(width, height, frequency, attenuation) + masks.append(mask) + return masks + + def blend_noise(width, height, masks, noise_types, attenuations): + blended_image = Image.new('L', (width, height), color=0) + fy = np.fft.fftfreq(height)[:, np.newaxis] ** 2 + fx = np.fft.fftfreq(width) ** 2 + f = fy + fx + i = 0 + for (mask, noise_type, attenuation) in zip(masks, noise_types, attenuations): + mask = Image.fromarray((255 * (mask - np.min(mask)) / (np.max(mask) - np.min(mask))).astype(np.uint8).real) + if noise_type == 'white': + noise = white_noise(width, height) + noise = Image.fromarray((255 * (noise - np.min(noise)) / (np.max(noise) - np.min(noise))).astype(np.uint8).real) + elif noise_type == 'grey': + noise = grey_noise(width, height, attenuation) + noise = Image.fromarray((255 * (noise - np.min(noise)) / (np.max(noise) - np.min(noise))).astype(np.uint8).real) + elif noise_type == 'pink': + noise = pink_noise(width, height, frequency, attenuation) + noise = Image.fromarray((255 * (noise - np.min(noise)) / (np.max(noise) - np.min(noise))).astype(np.uint8).real) + elif noise_type == 'green': + noise = green_noise(width, height, frequency, attenuation) + noise = Image.fromarray((255 * (noise - np.min(noise)) / (np.max(noise) - np.min(noise))).astype(np.uint8).real) + elif noise_type == 'blue': + noise = blue_noise(width, height, frequency, attenuation) + noise = Image.fromarray((255 * (noise - np.min(noise)) / (np.max(noise) - np.min(noise))).astype(np.uint8).real) + blended_image = Image.composite(blended_image, noise, mask) + i += 1 + return np.asarray(blended_image) + + def shorten_to_range(value, min_value, max_value): + range_length = max_value - min_value + 1 + return (value - min_value) % range_length + min_value + if seed is not None: + if seed > 4294967294: + seed = shorten_to_range(seed, 0, 4294967293) + cstr(f'Seed too large for power noise; rescaled to: {seed}').warning.print() + np.random.seed(seed) + if noise_type == 'white': + noise = white_noise(width, height) + elif noise_type == 'grey': + noise = grey_noise(width, height, attenuation) + elif noise_type == 'pink': + if frequency is None: + cstr('Pink noise requires a frequency value.').error.print() + return None + noise = pink_noise(width, height, frequency, attenuation) + elif noise_type == 'green': + if frequency is None: + cstr('Green noise requires a frequency value.').error.print() + return None + noise = green_noise(width, height, frequency, attenuation) + elif noise_type == 'blue': + if frequency is None: + cstr('Blue noise requires a frequency value.').error.print() + return None + noise = blue_noise(width, height, frequency, attenuation) + elif noise_type == 'mix': + if frequency is None: + cstr('Mix noise requires a frequency value.').error.print() + return None + if seed is None: + cstr('Mix noise requires a seed value.').error.print() + return None + blue_noise_masks = blue_noise_mask(width, height, frequency, attenuation, seed=seed, num_masks=3) + noise_types = ['white', 'grey', 'pink', 'green', 'blue'] + attenuations = [attenuation] * len(noise_types) + noise = blend_noise(width, height, blue_noise_masks, noise_types, attenuations) + else: + cstr(f'Unsupported noise type `{noise_type}`').error.print() + return None + if noise_type != 'mix': + noise = 255 * (noise - np.min(noise)) / (np.max(noise) - np.min(noise)) + noise_image = Image.fromarray(noise.astype(np.uint8).real) + return noise_image.convert('RGB') +``` \ No newline at end of file diff --git a/docs/Image Premultiply (mtb).md b/docs/Image Premultiply (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Image Rembg (Remove Background).md b/docs/Image Rembg (Remove Background).md new file mode 100644 index 0000000..ed0f456 --- /dev/null +++ b/docs/Image Rembg (Remove Background).md @@ -0,0 +1,117 @@ +# Documentation +- Class name: WAS_Remove_Rembg +- Category: WAS Suite/Image/AI +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Remove_Rembg 节点旨在使用先进的 AI 算法无缝去除图像的背景。它专注于提供一种干净高效的方式来隔离主题和背景,增强图像在各种应用中的可用性,如平面设计、内容创作等。 + +# Input types +## Required +- images + - ‘images’参数至关重要,因为它定义了将要移除背景的输入图像。这些图像的质量和分辨率直接影响节点的输出,决定了主题分离的清晰度和精确度。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image.Image] +## Optional +- transparency + - ‘transparency’参数决定在移除背景后是否应该使背景变得透明。这对于将要叠加在其他图形或背景上的图像特别有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- model + - ‘model’参数用于选择用于背景移除的 AI 模型。不同的模型可能提供不同程度的细节和准确性,因此这个选择对于实现期望的结果至关重要。 + - Comfy dtype: COMBO[u2net, u2netp, u2net_human_seg, silueta, isnet-general-use, isnet-anime] + - Python dtype: str +- post_processing + - 启用‘post_processing’时,对输出应用额外的图像增强,可能提高最终结果的视觉吸引力。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- only_mask + - 当设置为 true 时,‘only_mask’参数只返回遮罩,而不将背景移除过程应用于原始图像。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- alpha_matting + - ‘alpha_matting’参数激活 alpha matting 技术,以细化遮罩的边缘,使其看起来更自然。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- alpha_matting_foreground_threshold + - 这个参数以及与 alpha matting 相关的其他参数,微调了遮罩的边缘检测。它决定了被认为是前景的阈值。 + - Comfy dtype: INT + - Python dtype: int +- alpha_matting_background_threshold + - 它与前景阈值一起工作,定义了 alpha matting 过程中什么构成了背景。 + - Comfy dtype: INT + - Python dtype: int +- alpha_matting_erode_size + - ‘alpha_matting_erode_size’参数控制应用于遮罩的腐蚀效果的大小,这有助于细化遮罩的边缘。 + - Comfy dtype: INT + - Python dtype: int +- background_color + - ‘background_color’参数允许用户指定一个纯色,用作移除原始背景后的新的背景。 + - Comfy dtype: COMBO[none, black, white, magenta, chroma green, chroma blue] + - Python dtype: str + +# Output types +- images + - ‘images’输出参数代表处理过的图像,其中背景已被移除。它是节点操作的成果,对于使用这些图像的下游任务来说非常重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Remove_Rembg: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'transparency': ('BOOLEAN', {'default': True}), 'model': (['u2net', 'u2netp', 'u2net_human_seg', 'silueta', 'isnet-general-use', 'isnet-anime'],), 'post_processing': ('BOOLEAN', {'default': False}), 'only_mask': ('BOOLEAN', {'default': False}), 'alpha_matting': ('BOOLEAN', {'default': False}), 'alpha_matting_foreground_threshold': ('INT', {'default': 240, 'min': 0, 'max': 255}), 'alpha_matting_background_threshold': ('INT', {'default': 10, 'min': 0, 'max': 255}), 'alpha_matting_erode_size': ('INT', {'default': 10, 'min': 0, 'max': 255}), 'background_color': (['none', 'black', 'white', 'magenta', 'chroma green', 'chroma blue'],)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('images',) + FUNCTION = 'image_rembg' + CATEGORY = 'WAS Suite/Image/AI' + + def __convertToBool(self, x): + if type(x) == str: + x = x.strip() + if x.lower() == 'false' or x.lower() == 'none' or x == '0' or (x == '0.0') or (x == '0j') or (x == "''") or (x == '""') or (x == '()') or (x == '[]') or (x == '{}') or (x.lower() == 'decimal(0)') or (x.lower() == 'fraction(0,1)') or (x.lower() == 'set()') or (x.lower() == 'range(0)'): + return False + else: + return True + return bool(x) + + def image_rembg(self, images, transparency=True, model='u2net', alpha_matting=False, alpha_matting_foreground_threshold=240, alpha_matting_background_threshold=10, alpha_matting_erode_size=10, post_processing=False, only_mask=False, background_color='none'): + transparency = transparency if type(transparency) is bool else self.__convertToBool(transparency) + alpha_matting = alpha_matting if type(alpha_matting) is bool else self.__convertToBool(alpha_matting) + post_processing = post_processing if type(post_processing) is bool else self.__convertToBool(post_processing) + only_mask = only_mask if type(only_mask) is bool else self.__convertToBool(only_mask) + if 'rembg' not in packages(): + install_package('rembg') + from rembg import remove, new_session + os.environ['U2NET_HOME'] = os.path.join(MODELS_DIR, 'rembg') + os.makedirs(os.environ['U2NET_HOME'], exist_ok=True) + bgrgba = None + if background_color == 'black': + bgrgba = [0, 0, 0, 255] + elif background_color == 'white': + bgrgba = [255, 255, 255, 255] + elif background_color == 'magenta': + bgrgba = [255, 0, 255, 255] + elif background_color == 'chroma green': + bgrgba = [0, 177, 64, 255] + elif background_color == 'chroma blue': + bgrgba = [0, 71, 187, 255] + else: + bgrgba = None + if transparency and bgrgba is not None: + bgrgba[3] = 0 + batch_tensor = [] + for image in images: + image = tensor2pil(image) + batch_tensor.append(pil2tensor(remove(image, session=new_session(model), post_process_mask=post_processing, alpha_matting=alpha_matting, alpha_matting_foreground_threshold=alpha_matting_foreground_threshold, alpha_matting_background_threshold=alpha_matting_background_threshold, alpha_matting_erode_size=alpha_matting_erode_size, only_mask=only_mask, bgcolor=bgrgba).convert('RGBA' if transparency else 'RGB'))) + batch_tensor = torch.cat(batch_tensor, dim=0) + return (batch_tensor,) +``` \ No newline at end of file diff --git a/docs/Image Remove Background (Alpha).md b/docs/Image Remove Background (Alpha).md new file mode 100644 index 0000000..d5fa2b0 --- /dev/null +++ b/docs/Image Remove Background (Alpha).md @@ -0,0 +1,73 @@ +# Documentation +- Class name: WAS_Remove_Background +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Remove_Background节点旨在通过移除背景来处理图像,实现前景提取。它通过将图像转换为灰度图,应用高斯模糊,并使用二值阈值来创建一个掩膜,以隔离所需的元素。该节点特别适用于需要无背景干扰的干净前景对象的任务。 + +# Input types +## Required +- images + - ‘images’参数对于节点至关重要,因为它代表了节点将处理的输入图像。节点的功能围绕操作这些图像以移除背景,使此参数对节点的执行至关重要。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image.Image] +## Optional +- mode + - ‘mode’参数决定节点将移除图像的背景还是前景。这是一个可选参数,可以根据期望的结果影响节点的行为,允许在处理不同类型的图像时具有灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- threshold + - ‘threshold’参数在控制背景移除过程的灵敏度方面至关重要。它设置了灰度值被认为是背景或前景的水平,直接影响节点区分两者的能力。 + - Comfy dtype: INT + - Python dtype: int +- threshold_tolerance + - ‘threshold_tolerance’参数定义了在应用阈值之前用于平滑图像的高斯模糊的半径。它影响节点处理图像中的噪声和细节的能力,在最终输出的质量中起着重要作用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- images + - ‘images’输出参数包含移除背景后的处理图像。它是节点操作的最终结果,代表了图像处理任务的主要结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Remove_Background: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'mode': (['background', 'foreground'],), 'threshold': ('INT', {'default': 127, 'min': 0, 'max': 255, 'step': 1}), 'threshold_tolerance': ('INT', {'default': 2, 'min': 1, 'max': 24, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('images',) + FUNCTION = 'image_remove_background' + CATEGORY = 'WAS Suite/Image/Process' + + def image_remove_background(self, images, mode='background', threshold=127, threshold_tolerance=2): + return (self.remove_background(images, mode, threshold, threshold_tolerance),) + + def remove_background(self, image, mode, threshold, threshold_tolerance): + images = [] + image = [tensor2pil(img) for img in image] + for img in image: + grayscale_image = img.convert('L') + if mode == 'background': + grayscale_image = ImageOps.invert(grayscale_image) + threshold = 255 - threshold + blurred_image = grayscale_image.filter(ImageFilter.GaussianBlur(radius=threshold_tolerance)) + binary_image = blurred_image.point(lambda x: 0 if x < threshold else 255, '1') + mask = binary_image.convert('L') + inverted_mask = ImageOps.invert(mask) + transparent_image = img.copy() + transparent_image.putalpha(inverted_mask) + images.append(pil2tensor(transparent_image)) + batch = torch.cat(images, dim=0) + return batch +``` \ No newline at end of file diff --git a/docs/Image Remove Background Rembg (mtb).md b/docs/Image Remove Background Rembg (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Image Remove Color.md b/docs/Image Remove Color.md new file mode 100644 index 0000000..3778e7f --- /dev/null +++ b/docs/Image Remove Color.md @@ -0,0 +1,79 @@ +# Documentation +- Class name: WAS_Image_Remove_Color +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Remove_Color节点旨在根据用户定义的标准处理图像,移除特定颜色。它允许识别并用指定的替换颜色替换目标颜色,以增强图像以供进一步分析或美化用途。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它是节点将处理的输入。它决定了颜色移除操作的内容和格式。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- target_red + - target_red参数指定要移除的颜色的红色分量。它在确定颜色移除过程的准确性中起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- target_green + - target_green参数定义了要移除的颜色的绿色分量,影响节点隔离和替换目标颜色的能力。 + - Comfy dtype: INT + - Python dtype: int +- target_blue + - target_blue参数设置要替换的颜色的蓝色分量,这对于实现颜色移除任务中所需的结果至关重要。 + - Comfy dtype: INT + - Python dtype: int +- replace_red + - replace_red参数确定替换颜色的红色分量,这对于修改后图像的最终外观非常重要。 + - Comfy dtype: INT + - Python dtype: int +- replace_green + - replace_green参数设置用于替换目标颜色的颜色的绿色分量,影响节点的输出。 + - Comfy dtype: INT + - Python dtype: int +- replace_blue + - replace_blue参数指定将替换原始颜色的颜色的蓝色分量,这对于节点的颜色更改功能至关重要。 + - Comfy dtype: INT + - Python dtype: int +- clip_threshold + - clip_threshold参数设定颜色差异的阈值,这对于节点区分目标颜色和其他颜色的能力至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output_image + - output_image代表已处理的图像,其中指定的颜色已被移除,展示了节点改变视觉内容的能力。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Remove_Color: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'target_red': ('INT', {'default': 255, 'min': 0, 'max': 255, 'step': 1}), 'target_green': ('INT', {'default': 255, 'min': 0, 'max': 255, 'step': 1}), 'target_blue': ('INT', {'default': 255, 'min': 0, 'max': 255, 'step': 1}), 'replace_red': ('INT', {'default': 255, 'min': 0, 'max': 255, 'step': 1}), 'replace_green': ('INT', {'default': 255, 'min': 0, 'max': 255, 'step': 1}), 'replace_blue': ('INT', {'default': 255, 'min': 0, 'max': 255, 'step': 1}), 'clip_threshold': ('INT', {'default': 10, 'min': 0, 'max': 255, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_remove_color' + CATEGORY = 'WAS Suite/Image/Process' + + def image_remove_color(self, image, clip_threshold=10, target_red=255, target_green=255, target_blue=255, replace_red=255, replace_green=255, replace_blue=255): + return (pil2tensor(self.apply_remove_color(tensor2pil(image), clip_threshold, (target_red, target_green, target_blue), (replace_red, replace_green, replace_blue))),) + + def apply_remove_color(self, image, threshold=10, color=(255, 255, 255), rep_color=(0, 0, 0)): + color_image = Image.new('RGB', image.size, color) + diff_image = ImageChops.difference(image, color_image) + gray_image = diff_image.convert('L') + mask_image = gray_image.point(lambda x: 255 if x > threshold else 0) + mask_image = ImageOps.invert(mask_image) + result_image = Image.composite(Image.new('RGB', image.size, rep_color), image, mask_image) + return result_image +``` \ No newline at end of file diff --git a/docs/Image Resize Factor (mtb).md b/docs/Image Resize Factor (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Image Resize.md b/docs/Image Resize.md new file mode 100644 index 0000000..7e8cffc --- /dev/null +++ b/docs/Image Resize.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: WAS_Image_Rescale +- Category: WAS Suite/Image/Transform +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Rescale节点旨在通过根据指定的因子缩放图像或将图像调整为设定的宽度和高度来转换图像。它提供了选择缩放模式的灵活性,无论是简单的重新缩放还是带有超采样的调整大小以提高质量。该节点能够处理各种重采样过滤器,以满足不同的图像质量要求。 + +# Input types +## Required +- image + - 输入图像是转换过程的核心元素。它决定了缩放或调整大小操作的对象。输入图像的质量和尺寸直接影响节点执行的结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- mode + - 模式参数决定图像将通过因子缩放还是调整到特定尺寸。它对于设置节点将执行的转换类型至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- supersample + - 当supersample参数设置为'true'时,它通过先将图像缩放到更大的尺寸,然后再将其调整到目标尺寸,从而启用更高质量的调整大小过程。 + - Comfy dtype: STRING + - Python dtype: str +- resampling + - 重采样参数选择用于调整图像大小的过滤器。不同的过滤器在图像质量和清晰度方面可以产生不同的结果。 + - Comfy dtype: STRING + - Python dtype: str +- rescale_factor + - rescale_factor定义了图像的缩放因子。它是一个乘数,决定了图像尺寸调整的程度。 + - Comfy dtype: FLOAT + - Python dtype: float +- resize_width + - resize_width设置了调整大小后的图像的目标宽度。当模式设置为'resize'时,这是一个重要参数,它决定了图像的新宽度。 + - Comfy dtype: INT + - Python dtype: int +- resize_height + - resize_height设置了调整大小后的图像的目标高度。它与resize_width一起工作,以确定在'resize'模式下图像的最终尺寸。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- scaled_image + - scaled_image是节点的输出,代表应用缩放或调整大小操作后转换的图像。它是重要的,因为它反映了节点预期功能的成果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Rescale: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'mode': (['rescale', 'resize'],), 'supersample': (['true', 'false'],), 'resampling': (['lanczos', 'nearest', 'bilinear', 'bicubic'],), 'rescale_factor': ('FLOAT', {'default': 2, 'min': 0.01, 'max': 16.0, 'step': 0.01}), 'resize_width': ('INT', {'default': 1024, 'min': 1, 'max': 48000, 'step': 1}), 'resize_height': ('INT', {'default': 1536, 'min': 1, 'max': 48000, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_rescale' + CATEGORY = 'WAS Suite/Image/Transform' + + def image_rescale(self, image, mode='rescale', supersample='true', resampling='lanczos', rescale_factor=2, resize_width=1024, resize_height=1024): + scaled_images = [] + for img in image: + scaled_images.append(pil2tensor(self.apply_resize_image(tensor2pil(img), mode, supersample, rescale_factor, resize_width, resize_height, resampling))) + scaled_images = torch.cat(scaled_images, dim=0) + return (scaled_images,) + + def apply_resize_image(self, image: Image.Image, mode='scale', supersample='true', factor: int=2, width: int=1024, height: int=1024, resample='bicubic'): + (current_width, current_height) = image.size + if mode == 'rescale': + (new_width, new_height) = (int(current_width * factor), int(current_height * factor)) + else: + new_width = width if width % 8 == 0 else width + (8 - width % 8) + new_height = height if height % 8 == 0 else height + (8 - height % 8) + resample_filters = {'nearest': 0, 'bilinear': 2, 'bicubic': 3, 'lanczos': 1} + if supersample == 'true': + image = image.resize((new_width * 8, new_height * 8), resample=Image.Resampling(resample_filters[resample])) + resized_image = image.resize((new_width, new_height), resample=Image.Resampling(resample_filters[resample])) + return resized_image +``` \ No newline at end of file diff --git a/docs/Image Rotate Hue.md b/docs/Image Rotate Hue.md new file mode 100644 index 0000000..3321131 --- /dev/null +++ b/docs/Image Rotate Hue.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: WAS_Image_Rotate_Hue +- Category: WAS Suite/Image/Adjustment +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Rotate_Hue节点旨在调整图像的色相,提供了一种改变图像整体色调的方法,而不会改变图像的亮度或饱和度。它特别适用于为视觉效果或颜色校正目的创建图像的变体。 + +# Input types +## Required +- image + - 图像参数对于节点的操作至关重要,因为它是将进行色相调整的输入。它是节点将处理以实现所需颜色转换的主要数据。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +## Optional +- hue_shift + - hue_shift参数允许微调图像中的颜色旋转。它是一个浮点数,影响色相偏移的程度,从而影响图像的最终视觉效果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- rotated_image + - rotated_image输出代表了将色相旋转应用于输入图像的结果。它是经过颜色调整的转换图像,可供进一步处理或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Rotate_Hue: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'hue_shift': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'rotate_hue' + CATEGORY = 'WAS Suite/Image/Adjustment' + + def rotate_hue(self, image, hue_shift=0.0): + if hue_shift > 1.0 or hue_shift < 0.0: + cstr(f'The hue_shift `{cstr.color.LIGHTYELLOW}{hue_shift}{cstr.color.END}` is out of range. Valid range is {cstr.color.BOLD}0.0 - 1.0{cstr.color.END}').error.print() + hue_shift = 0.0 + shifted_hue = pil2tensor(self.hue_rotation(image, hue_shift)) + return (shifted_hue,) + + def hue_rotation(self, image, hue_shift=0.0): + import colorsys + if hue_shift > 1.0 or hue_shift < 0.0: + print(f"The hue_shift '{hue_shift}' is out of range. Valid range is 0.0 - 1.0") + hue_shift = 0.0 + pil_image = tensor2pil(image) + (width, height) = pil_image.size + rotated_image = Image.new('RGB', (width, height)) + for x in range(width): + for y in range(height): + (r, g, b) = pil_image.getpixel((x, y)) + (h, l, s) = colorsys.rgb_to_hls(r / 255, g / 255, b / 255) + h = (h + hue_shift) % 1.0 + (r, g, b) = colorsys.hls_to_rgb(h, l, s) + (r, g, b) = (int(r * 255), int(g * 255), int(b * 255)) + rotated_image.putpixel((x, y), (r, g, b)) + return rotated_image +``` \ No newline at end of file diff --git a/docs/Image Rotate.md b/docs/Image Rotate.md new file mode 100644 index 0000000..37088dc --- /dev/null +++ b/docs/Image Rotate.md @@ -0,0 +1,79 @@ +# Documentation +- Class name: WAS_Image_Rotate +- Category: WAS Suite/Image/Transform +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +图像旋转方法旨在对一批图像应用指定的旋转。它通过将角度调整到最近的90度来智能处理旋转,并使用指定的重采样过滤器以保持图像质量。该节点的功能在图像预处理和需要进行方向调整的图像操作任务中至关重要。 + +# Input types +## Required +- images + - 参数 'images' 是将要旋转的图像批次。它起着至关重要的作用,因为节点的所有操作都围绕这个输入进行。这些图像的质量和格式直接影响旋转过程的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- rotation + - 参数 'rotation' 指定旋转角度,单位为度。它至关重要,因为它决定了应用于图像的旋转程度。任何不能被90整除的旋转值都将调整为最近的90的倍数以进行标准处理。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- mode + - 参数 'mode' 确定旋转策略:'internal' 用于标准旋转,'transpose' 用于使用图像转置方法的旋转。它很重要,因为它决定了旋转所使用的底层算法。 + - Comfy dtype: COMBO['transpose', 'internal'] + - Python dtype: str +- sampler + - 参数 'sampler' 定义了旋转期间使用的重采样过滤器。它很重要,因为它影响旋转后图像的质量。不同的采样器在速度和图像保真度之间提供不同的权衡。 + - Comfy dtype: COMBO['nearest', 'bilinear', 'bicubic'] + - Python dtype: str + +# Output types +- images + - 输出 'images' 包含旋转后的图像批次。它是节点操作的主要结果,很重要,因为它代表了可以用于进一步处理或分析的转换后数据。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Rotate: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'mode': (['transpose', 'internal'],), 'rotation': ('INT', {'default': 0, 'min': 0, 'max': 360, 'step': 90}), 'sampler': (['nearest', 'bilinear', 'bicubic'],)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('images',) + FUNCTION = 'image_rotate' + CATEGORY = 'WAS Suite/Image/Transform' + + def image_rotate(self, images, mode, rotation, sampler): + batch_tensor = [] + for image in images: + image = tensor2pil(image) + if rotation > 360: + rotation = int(360) + if rotation % 90 != 0: + rotation = int(rotation // 90 * 90) + if sampler: + if sampler == 'nearest': + sampler = Image.NEAREST + elif sampler == 'bicubic': + sampler = Image.BICUBIC + elif sampler == 'bilinear': + sampler = Image.BILINEAR + else: + sampler == Image.BILINEAR + if mode == 'internal': + image = image.rotate(rotation, sampler) + else: + rot = int(rotation / 90) + for _ in range(rot): + image = image.transpose(2) + batch_tensor.append(pil2tensor(image)) + batch_tensor = torch.cat(batch_tensor, dim=0) + return (batch_tensor,) +``` \ No newline at end of file diff --git a/docs/Image SSAO (Ambient Occlusion).md b/docs/Image SSAO (Ambient Occlusion).md new file mode 100644 index 0000000..4d50dfa --- /dev/null +++ b/docs/Image SSAO (Ambient Occlusion).md @@ -0,0 +1,146 @@ +# Documentation +- Class name: WAS_Image_Ambient_Occlusion +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Ambient_Occlusion 节点旨在通过应用环境光遮蔽效果来增强图像的视觉深度和真实感。它根据输入图像的深度和颜色信息智能计算遮蔽,创造出更自然、更沉浸的视觉效果。 + +# Input types +## Required +- images + - 输入图像参数对于节点的操作至关重要,因为它提供了将应用环境光遮蔽效果的原始视觉数据。这些图像的质量和分辨率直接影响最终输出。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +- depth_images + - 深度图像对于准确确定场景内的遮蔽级别至关重要。它们提供深度信息,补充输入图像,增强环境光遮蔽效果的真实性。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +## Optional +- strength + - 强度参数允许用户控制环境光遮蔽效果的强度。调整此参数可以微调遮蔽的视觉影响,根据创意需求使其更加或不那么明显。 + - Comfy dtype: FLOAT + - Python dtype: float +- radius + - 半径参数定义了在每个像素周围进行遮蔽计算的区域。较大的半径会导致更渐进和广泛的遮蔽效果,而较小的半径则创造出更紧密、更局部的效果。 + - Comfy dtype: FLOAT + - Python dtype: float +- ao_blur + - ao_blur 参数负责应用于遮蔽图像的模糊程度。它可以平滑遮蔽效果,创造出更微妙和自然的外观。 + - Comfy dtype: FLOAT + - Python dtype: float +- specular_threshold + - specular_threshold 参数用于确定镜面高光的截止值,这会影响遮蔽与图像中明亮区域的交互方式。 + - Comfy dtype: INT + - Python dtype: int +- enable_specular_masking + - 通过 enable_specular_masking 参数启用镜面遮罩允许选择性地应用遮蔽效果,绕过高镜面反射区域。 + - Comfy dtype: COMBO[True, False] + - Python dtype: bool +- tile_size + - tile_size 参数通过将图像划分为多个小块来优化环境光遮蔽的处理。这可以通过允许并行处理,特别是对于大型图像,从而提高性能。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- composited_images + - composited_images 输出参数表示应用了环境光遮蔽效果的最终渲染图像。它是输入图像和计算出的遮蔽的组合,从而呈现出更加立体的外观。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- ssao_images + - ssao_images 输出参数提供了在过程中计算出的独立环境光遮蔽图像。这些可以用于进一步分析或额外的视觉效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- specular_mask_images + - specular_mask_images 输出参数包含生成的用于应用镜面遮罩的遮罩。这些遮罩决定了哪些图像区域将根据镜面反射值应用遮蔽效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Ambient_Occlusion: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'depth_images': ('IMAGE',), 'strength': ('FLOAT', {'min': 0.0, 'max': 5.0, 'default': 1.0, 'step': 0.01}), 'radius': ('FLOAT', {'min': 0.01, 'max': 1024, 'default': 30, 'step': 0.01}), 'ao_blur': ('FLOAT', {'min': 0.01, 'max': 1024, 'default': 2.5, 'step': 0.01}), 'specular_threshold': ('INT', {'min': 0, 'max': 255, 'default': 25, 'step': 1}), 'enable_specular_masking': (['True', 'False'],), 'tile_size': ('INT', {'min': 1, 'max': 512, 'default': 1, 'step': 1})}} + RETURN_TYPES = ('IMAGE', 'IMAGE', 'IMAGE') + RETURN_NAMES = ('composited_images', 'ssao_images', 'specular_mask_images') + FUNCTION = 'ambient_occlusion' + CATEGORY = 'WAS Suite/Image/Filter' + + def ambient_occlusion(self, images, depth_images, strength, radius, ao_blur, specular_threshold, enable_specular_masking, tile_size): + enable_specular_masking = enable_specular_masking == 'True' + composited = [] + occlusions = [] + speculars = [] + for (i, image) in enumerate(images): + cstr(f'Processing SSAO image {i + 1}/{len(images)} ...').msg.print() + (composited_image, occlusion_image, specular_mask) = self.create_ambient_occlusion(tensor2pil(image), tensor2pil(depth_images[i if len(depth_images) >= i else -1]), strength=strength, radius=radius, ao_blur=ao_blur, spec_threshold=specular_threshold, enable_specular_masking=enable_specular_masking, tile_size=tile_size) + composited.append(pil2tensor(composited_image)) + occlusions.append(pil2tensor(occlusion_image)) + speculars.append(pil2tensor(specular_mask)) + composited = torch.cat(composited, dim=0) + occlusions = torch.cat(occlusions, dim=0) + speculars = torch.cat(speculars, dim=0) + return (composited, occlusions, speculars) + + def process_tile(self, tile_rgb, tile_depth, tile_x, tile_y, radius): + tile_occlusion = calculate_ambient_occlusion_factor(tile_rgb, tile_depth, tile_rgb.shape[0], tile_rgb.shape[1], radius) + return (tile_x, tile_y, tile_occlusion) + + def create_ambient_occlusion(self, rgb_image, depth_image, strength=1.0, radius=30, ao_blur=5, spec_threshold=200, enable_specular_masking=False, tile_size=1): + import concurrent.futures + if depth_image.size != rgb_image.size: + depth_image = depth_image.resize(rgb_image.size) + rgb_normalized = np.array(rgb_image, dtype=np.float32) / 255.0 + depth_normalized = np.array(depth_image, dtype=np.float32) / 255.0 + (height, width, _) = rgb_normalized.shape + if tile_size <= 1: + print('Processing single-threaded AO (highest quality) ...') + occlusion_array = calculate_ambient_occlusion_factor(rgb_normalized, depth_normalized, height, width, radius) + else: + tile_size = (tile_size if tile_size <= 8 else 8) if tile_size > 1 else 1 + num_tiles_x = (width - 1) // tile_size + 1 + num_tiles_y = (height - 1) // tile_size + 1 + occlusion_array = np.zeros((height, width), dtype=np.uint8) + with concurrent.futures.ThreadPoolExecutor() as executor: + futures = [] + with tqdm(total=num_tiles_y * num_tiles_x) as pbar: + for tile_y in range(num_tiles_y): + for tile_x in range(num_tiles_x): + tile_left = tile_x * tile_size + tile_upper = tile_y * tile_size + tile_right = min(tile_left + tile_size, width) + tile_lower = min(tile_upper + tile_size, height) + tile_rgb = rgb_normalized[tile_upper:tile_lower, tile_left:tile_right] + tile_depth = depth_normalized[tile_upper:tile_lower, tile_left:tile_right] + future = executor.submit(self.process_tile, tile_rgb, tile_depth, tile_x, tile_y, radius) + futures.append(future) + for future in concurrent.futures.as_completed(futures): + (tile_x, tile_y, tile_occlusion) = future.result() + tile_left = tile_x * tile_size + tile_upper = tile_y * tile_size + tile_right = min(tile_left + tile_size, width) + tile_lower = min(tile_upper + tile_size, height) + occlusion_array[tile_upper:tile_lower, tile_left:tile_right] = tile_occlusion + pbar.update(1) + occlusion_array = (occlusion_array * strength).clip(0, 255).astype(np.uint8) + occlusion_image = Image.fromarray(occlusion_array, mode='L') + occlusion_image = occlusion_image.filter(ImageFilter.GaussianBlur(radius=ao_blur)) + occlusion_image = occlusion_image.filter(ImageFilter.SMOOTH) + occlusion_image = ImageChops.multiply(occlusion_image, ImageChops.multiply(occlusion_image, occlusion_image)) + mask = rgb_image.convert('L') + mask = mask.point(lambda x: x > spec_threshold, mode='1') + mask = mask.convert('RGB') + mask = mask.filter(ImageFilter.GaussianBlur(radius=2.5)).convert('L') + if enable_specular_masking: + occlusion_image = Image.composite(Image.new('L', rgb_image.size, 255), occlusion_image, mask) + occlsuion_result = ImageChops.multiply(rgb_image, occlusion_image.convert('RGB')) + return (occlsuion_result, occlusion_image, mask) +``` \ No newline at end of file diff --git a/docs/Image SSDO (Direct Occlusion).md b/docs/Image SSDO (Direct Occlusion).md new file mode 100644 index 0000000..d38800e --- /dev/null +++ b/docs/Image SSDO (Direct Occlusion).md @@ -0,0 +1,142 @@ +# Documentation +- Class name: WAS_Image_Direct_Occlusion +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Direct_Occlusion节点旨在处理图像和深度图,以创建直接遮挡效果,通过模拟光线与物体的相互作用来增强图像的视觉真实感。它识别光源,并根据深度和颜色差异应用遮挡,从而生成具有更立体外观的图像。 + +# Input types +## Required +- images + - 输入图像参数对于节点的操作至关重要,因为它是生成遮挡效果的主要数据源。它直接影响最终结果,通过确定将被处理以产生遮挡的视觉内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- depth_images + - depth_images参数提供了计算遮挡效果所必需的深度信息。它对于确定光线如何根据图像不同部分的深度进行交互至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- strength + - strength参数控制遮挡效果的强度。它很重要,因为它允许用户调整应用于图像的遮挡程度,从而微调最终输出的视觉影响。 + - Comfy dtype: FLOAT + - Python dtype: float +- radius + - radius参数定义了在计算遮挡时每个像素的影响区域。它很重要,因为它决定了每个像素周围遮挡效果的范围,影响图像的整体纹理和细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- specular_threshold + - specular_threshold参数用于识别图像中最亮的区域,这些区域有助于光源的识别。它在确定哪些图像部分将被视为遮挡计算中的光源中起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- colored_occlusion + - colored_occlusion参数决定是否将以彩色或灰度效果应用遮挡效果。这个选择影响遮挡的视觉风格,允许进行更微妙或更显著的视觉变化。 + - Comfy dtype: COMBO[True, False] + - Python dtype: bool + +# Output types +- composited_images + - composited_images输出参数代表了应用了直接遮挡效果的最终图像。它很重要,因为它是节点处理的主要结果,用于进一步的可视化或分析。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- ssdo_images + - ssdo_images输出参数提供了合成前带有遮挡效果的图像。它对于单独检查遮挡效果以及用于调试目的很有用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- ssdo_image_masks + - ssdo_image_masks输出参数包括与图像中的遮挡区域相对应的掩码。这些掩码可以用于进一步的图像处理或隔离遮挡效果的特定区域。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- light_source_image_masks + - light_source_image_masks输出参数包含标识图像中被视为光源区域的掩码。这些掩码对于理解图像的哪些部分有助于遮挡效果至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WAS_Image_Direct_Occlusion: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'depth_images': ('IMAGE',), 'strength': ('FLOAT', {'min': 0.0, 'max': 5.0, 'default': 1.0, 'step': 0.01}), 'radius': ('FLOAT', {'min': 0.01, 'max': 1024, 'default': 30, 'step': 0.01}), 'specular_threshold': ('INT', {'min': 0, 'max': 255, 'default': 128, 'step': 1}), 'colored_occlusion': (['True', 'False'],)}} + RETURN_TYPES = ('IMAGE', 'IMAGE', 'IMAGE', 'IMAGE') + RETURN_NAMES = ('composited_images', 'ssdo_images', 'ssdo_image_masks', 'light_source_image_masks') + FUNCTION = 'direct_occlusion' + CATEGORY = 'WAS Suite/Image/Filter' + + def direct_occlusion(self, images, depth_images, strength, radius, specular_threshold, colored_occlusion): + composited = [] + occlusions = [] + occlusion_masks = [] + light_sources = [] + for (i, image) in enumerate(images): + cstr(f'Processing SSDO image {i + 1}/{len(images)} ...').msg.print() + (composited_image, occlusion_image, occlusion_mask, light_source) = self.create_direct_occlusion(tensor2pil(image), tensor2pil(depth_images[i if len(depth_images) >= i else -1]), strength=strength, radius=radius, threshold=specular_threshold, colored=True) + composited.append(pil2tensor(composited_image)) + occlusions.append(pil2tensor(occlusion_image)) + occlusion_masks.append(pil2tensor(occlusion_mask)) + light_sources.append(pil2tensor(light_source)) + composited = torch.cat(composited, dim=0) + occlusions = torch.cat(occlusions, dim=0) + occlusion_masks = torch.cat(occlusion_masks, dim=0) + light_sources = torch.cat(light_sources, dim=0) + return (composited, occlusions, occlusion_masks, light_sources) + + def find_light_source(self, rgb_normalized, threshold): + from skimage.measure import regionprops + from skimage import measure + rgb_uint8 = (rgb_normalized * 255).astype(np.uint8) + rgb_to_grey = Image.fromarray(rgb_uint8, mode='RGB') + dominant = self.dominant_region(rgb_to_grey, threshold) + grayscale_image = np.array(dominant.convert('L'), dtype=np.float32) / 255.0 + regions = measure.label(grayscale_image > 0) + if np.max(regions) > 0: + region_sums = measure.regionprops(regions, intensity_image=grayscale_image) + brightest_region = max(region_sums, key=lambda r: r.mean_intensity) + (light_y, light_x) = brightest_region.centroid + light_mask = (regions == brightest_region.label).astype(np.uint8) + light_mask_cluster = light_mask + else: + (light_x, light_y) = (np.nan, np.nan) + light_mask_cluster = np.zeros_like(dominant, dtype=np.uint8) + return (light_mask_cluster, light_x, light_y) + + def dominant_region(self, image, threshold=128): + from scipy.ndimage import label + image = ImageOps.invert(image.convert('L')) + binary_image = image.point(lambda x: 255 if x > threshold else 0, mode='1') + (l, n) = label(np.array(binary_image)) + sizes = np.bincount(l.flatten()) + dominant = 0 + try: + dominant = np.argmax(sizes[1:]) + 1 + except ValueError: + pass + dominant_region_mask = (l == dominant).astype(np.uint8) * 255 + result = Image.fromarray(dominant_region_mask, mode='L') + return result.convert('RGB') + + def create_direct_occlusion(self, rgb_image, depth_image, strength=1.0, radius=10, threshold=200, colored=False): + rgb_normalized = np.array(rgb_image, dtype=np.float32) / 255.0 + depth_normalized = np.array(depth_image, dtype=np.float32) / 255.0 + (height, width, _) = rgb_normalized.shape + (light_mask, light_x, light_y) = self.find_light_source(rgb_normalized, threshold) + occlusion_array = calculate_direct_occlusion_factor(rgb_normalized, depth_normalized, height, width, radius) + occlusion_scaled = ((occlusion_array - np.min(occlusion_array)) / (np.max(occlusion_array) - np.min(occlusion_array)) * 255).astype(np.uint8) + occlusion_image = Image.fromarray(occlusion_scaled, mode='L') + occlusion_image = occlusion_image.filter(ImageFilter.GaussianBlur(radius=0.5)) + occlusion_image = occlusion_image.filter(ImageFilter.SMOOTH_MORE) + if colored: + occlusion_result = Image.composite(Image.new('RGB', rgb_image.size, (0, 0, 0)), rgb_image, occlusion_image) + occlusion_result = ImageOps.autocontrast(occlusion_result, cutoff=(0, strength)) + else: + occlusion_result = Image.blend(occlusion_image, occlusion_image, strength) + light_image = ImageOps.invert(Image.fromarray(light_mask * 255, mode='L')) + direct_occlusion_image = ImageChops.screen(rgb_image, occlusion_result.convert('RGB')) + return (direct_occlusion_image, occlusion_result, occlusion_image, light_image) +``` \ No newline at end of file diff --git a/docs/Image Save with Prompt (WLSH).md b/docs/Image Save with Prompt (WLSH).md new file mode 100644 index 0000000..2be7a4f --- /dev/null +++ b/docs/Image Save with Prompt (WLSH).md @@ -0,0 +1,112 @@ +# Documentation +- Class name: WLSH_Image_Save_With_Prompt +- Category: WLSH Nodes/IO +- Output node: True +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点旨在便于保存图像数据,并能够包含额外的提示和元数据,增强保存图像的组织和描述能力。 + +# Input types +## Required +- images + - 图像参数是必需的,因为它提供了需要保存的原始图像数据。它直接影响节点保存图像的主要功能。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- filename + - 文件名参数对于定义保存图像的基础名称至关重要。它在图像保存后的组织和检索中扮演了重要角色。 + - Comfy dtype: STRING + - Python dtype: str +- extension + - 扩展名参数决定了图像将被保存的文件格式,影响了保存图像的兼容性和可用性。 + - Comfy dtype: COMBO + - Python dtype: ['png', 'jpeg', 'tiff', 'gif'] +- quality + - 质量参数在保存支持质量级别的格式(如JPEG)的图像时非常重要。它影响图像的压缩和文件大小。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- path + - 路径参数指定了图像将被保存的目录。它对于组织文件结构和管理存储位置很重要。 + - Comfy dtype: STRING + - Python dtype: str +- prompt + - 提示参数允许将额外的上下文信息与图像一起保存,增强描述性元数据并有助于未来的参考。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- ui + - ui输出提供了保存图像的结构化表示,包括它们的路径和其他相关的元数据,这对于保存后图像的管理和参考至关重要。 + - Comfy dtype: DICTIONARY + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Image_Save_With_Prompt: + + def __init__(self): + self.type = 'output' + self.output_dir = folder_paths.output_directory + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'filename': ('STRING', {'default': f'%time_%seed', 'multiline': False}), 'path': ('STRING', {'default': '', 'multiline': False}), 'extension': (['png', 'jpeg', 'tiff', 'gif'],), 'quality': ('INT', {'default': 100, 'min': 1, 'max': 100, 'step': 1})}, 'optional': {'positive': ('STRING', {'multiline': True, 'forceInput': True}), 'negative': ('STRING', {'multiline': True, 'forceInput': True}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615, 'forceInput': True}), 'modelname': ('STRING', {'default': '', 'multiline': False, 'forceInput': True}), 'counter': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'time_format': ('STRING', {'default': '%Y-%m-%d-%H%M%S', 'multiline': False})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = () + FUNCTION = 'save_files' + OUTPUT_NODE = True + CATEGORY = 'WLSH Nodes/IO' + + def save_files(self, images, positive='unknown', negative='unknown', seed=-1, modelname='unknown', counter=0, filename='', path='', time_format='%Y-%m-%d-%H%M%S', extension='png', quality=100, prompt=None, extra_pnginfo=None): + filename = make_filename(filename, seed, modelname, counter, time_format) + comment = make_comment(positive, negative, modelname, seed, info=None) + output_path = os.path.join(self.output_dir, path) + if output_path.strip() != '': + if not os.path.exists(output_path.strip()): + print(f"The path `{output_path.strip()}` specified doesn't exist! Creating directory.") + os.makedirs(output_path, exist_ok=True) + paths = self.save_images(images, output_path, path, filename, comment, extension, quality, prompt, extra_pnginfo) + return {'ui': {'images': paths}} + + def save_images(self, images, output_path, path, filename_prefix='ComfyUI', comment='', extension='png', quality=100, prompt=None, extra_pnginfo=None): + + def map_filename(filename): + prefix_len = len(filename_prefix) + prefix = filename[:prefix_len + 1] + try: + digits = int(filename[prefix_len + 1:].split('_')[0]) + except: + digits = 0 + return (digits, prefix) + imgCount = 1 + paths = list() + for image in images: + i = 255.0 * image.cpu().numpy() + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) + metadata = PngInfo() + if prompt is not None: + metadata.add_text('prompt', json.dumps(prompt)) + if extra_pnginfo is not None: + for x in extra_pnginfo: + metadata.add_text(x, json.dumps(extra_pnginfo[x])) + metadata.add_text('parameters', comment) + metadata.add_text('comment', comment) + if images.size()[0] > 1: + filename_prefix += '_{:02d}'.format(imgCount) + file = f'{filename_prefix}.{extension}' + if extension == 'png': + img.save(os.path.join(output_path, file), comment=comment, pnginfo=metadata, optimize=True) + elif extension == 'webp': + img.save(os.path.join(output_path, file), quality=quality) + elif extension == 'jpeg': + img.save(os.path.join(output_path, file), quality=quality, comment=comment, optimize=True) + elif extension == 'tiff': + img.save(os.path.join(output_path, file), quality=quality, optimize=True) + else: + img.save(os.path.join(output_path, file)) + paths.append({'filename': file, 'subfolder': path, 'type': self.type}) + imgCount += 1 + return paths +``` \ No newline at end of file diff --git a/docs/Image Save with Prompt%2FInfo File (WLSH).md b/docs/Image Save with Prompt%2FInfo File (WLSH).md new file mode 100644 index 0000000..5f7bdf1 --- /dev/null +++ b/docs/Image Save with Prompt%2FInfo File (WLSH).md @@ -0,0 +1,119 @@ +# Documentation +- Class name: WLSH_Image_Save_With_File_Info +- Category: WLSH Nodes/IO +- Output node: True +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_Image_Save_With_File_Info 节点旨在将图片保存到文件系统,并附加文件信息。它提供保存图片的功能,允许自定义文件名、扩展名和质量设置,并能够包含元数据,如提示和模型信息。 + +# Input types +## Required +- images + - 图片参数对于节点至关重要,因为它定义了需要保存的输入图片。节点根据提供的其他参数处理并保存这些图片。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- filename + - 文件名参数允许用户为保存的文件指定一个基本名称。它在组织输出文件中起着重要作用,因为它决定了文件名的初始部分。 + - Comfy dtype: STRING + - Python dtype: str +- path + - 路径参数决定了将保存图片的目录。它对于将保存的文件组织到特定文件夹中很重要。 + - Comfy dtype: STRING + - Python dtype: str +- extension + - 扩展名参数决定了图片将被保存的文件格式。它对于定义输出图片要使用的文件扩展类型至关重要。 + - Comfy dtype: COMBO['png', 'jpeg', 'tiff', 'gif'] + - Python dtype: str +- quality + - 质量参数对于设置保存图片的压缩级别很重要,特别是对于像JPEG或WebP这样的格式,它影响图片质量和文件大小之间的平衡。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- ui + - 输出中的 ui 参数包含保存图片的路径,为用户提供了图片存储位置的参考。 + - Comfy dtype: DICT + - Python dtype: Dict[str, List[Dict[str, str]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Image_Save_With_File_Info: + + def __init__(self): + self.output_dir = folder_paths.output_directory + self.type = 'output' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'filename': ('STRING', {'default': f'%time_%seed', 'multiline': False}), 'path': ('STRING', {'default': '', 'multiline': False}), 'extension': (['png', 'jpeg', 'tiff', 'gif'],), 'quality': ('INT', {'default': 100, 'min': 1, 'max': 100, 'step': 1})}, 'optional': {'positive': ('STRING', {'default': '', 'multiline': True, 'forceInput': True}), 'negative': ('STRING', {'default': '', 'multiline': True, 'forceInput': True}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615, 'forceInput': True}), 'modelname': ('STRING', {'default': '', 'multiline': False, 'forceInput': True}), 'counter': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'time_format': ('STRING', {'default': '%Y-%m-%d-%H%M%S', 'multiline': False}), 'info': ('INFO',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = () + FUNCTION = 'save_files' + OUTPUT_NODE = True + CATEGORY = 'WLSH Nodes/IO' + + def save_files(self, images, positive='unknown', negative='unknown', seed=-1, modelname='unknown', info=None, counter=0, filename='', path='', time_format='%Y-%m-%d-%H%M%S', extension='png', quality=100, prompt=None, extra_pnginfo=None): + filename = make_filename(filename, seed, modelname, counter, time_format) + comment = make_comment(positive, negative, modelname, seed, info) + output_path = os.path.join(self.output_dir, path) + if output_path.strip() != '': + if not os.path.exists(output_path.strip()): + print(f"The path `{output_path.strip()}` specified doesn't exist! Creating directory.") + os.makedirs(output_path, exist_ok=True) + paths = self.save_images(images, output_path, path, filename, comment, extension, quality, prompt, extra_pnginfo) + self.save_text_file(filename, output_path, comment, seed, modelname) + return {'ui': {'images': paths}} + + def save_images(self, images, output_path, path, filename_prefix='ComfyUI', comment='', extension='png', quality=100, prompt=None, extra_pnginfo=None): + + def map_filename(filename): + prefix_len = len(filename_prefix) + prefix = filename[:prefix_len + 1] + try: + digits = int(filename[prefix_len + 1:].split('_')[0]) + except: + digits = 0 + return (digits, prefix) + imgCount = 1 + paths = list() + for image in images: + i = 255.0 * image.cpu().numpy() + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) + metadata = PngInfo() + if prompt is not None: + metadata.add_text('prompt', json.dumps(prompt)) + if extra_pnginfo is not None: + for x in extra_pnginfo: + metadata.add_text(x, json.dumps(extra_pnginfo[x])) + metadata.add_text('parameters', comment) + if images.size()[0] > 1: + filename_prefix += '_{:02d}'.format(imgCount) + file = f'{filename_prefix}.{extension}' + if extension == 'png': + img.save(os.path.join(output_path, file), comment=comment, pnginfo=metadata, optimize=True) + elif extension == 'webp': + img.save(os.path.join(output_path, file), quality=quality) + elif extension == 'jpeg': + img.save(os.path.join(output_path, file), quality=quality, comment=comment, optimize=True) + elif extension == 'tiff': + img.save(os.path.join(output_path, file), quality=quality, optimize=True) + else: + img.save(os.path.join(output_path, file)) + paths.append({'filename': file, 'subfolder': path, 'type': self.type}) + imgCount += 1 + return paths + + def save_text_file(self, filename, output_path, comment='', seed=0, modelname=''): + self.writeTextFile(os.path.join(output_path, filename + '.txt'), comment) + return + + def writeTextFile(self, file, content): + try: + with open(file, 'w') as f: + f.write(content) + except OSError: + print('Unable to save file `{file}`') +``` \ No newline at end of file diff --git a/docs/Image Save.md b/docs/Image Save.md new file mode 100644 index 0000000..5df72cd --- /dev/null +++ b/docs/Image Save.md @@ -0,0 +1,230 @@ +# Documentation +- Class name: WAS_Image_Save +- Category: WAS Suite/IO +- Output node: True +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Save节点负责将图片保存到指定的输出目录。它处理各种文件格式,并提供命名和组织保存图片的选项,确保了图像输出管理的流程化。 + +# Input types +## Required +- images + - 图片参数是必需的,它定义了需要保存的输入图片。它在节点的执行中起着关键作用,因为它直接影响输出。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image.Image] +## Optional +- output_path + - output_path参数指定了保存图片的目录。它在确定文件系统内保存文件的最终位置时非常重要。 + - Comfy dtype: STRING + - Python dtype: str +- filename_prefix + - filename_prefix用于为保存的图片创建一致的命名约定,这对于组织和识别文件非常有益。 + - Comfy dtype: STRING + - Python dtype: str +- filename_delimiter + - filename_delimiter是一个字符,用于在保存的图像文件名中分隔前缀和数字标识符。 + - Comfy dtype: STRING + - Python dtype: str +- filename_number_padding + - filename_number_padding参数确定文件名中用于数字标识符的位数,确保文件命名方案的一致性。 + - Comfy dtype: INT + - Python dtype: int +- extension + - extension参数指示图片将被保存的文件格式,允许产生不同类型的图片文件。 + - Comfy dtype: COMBO['png', 'jpg', 'jpeg', 'gif', 'tiff', 'webp', 'bmp'] + - Python dtype: str +- quality + - quality参数用于设置保存图片的压缩级别,这可能会影响文件大小和图片质量之间的平衡。 + - Comfy dtype: INT + - Python dtype: int +- lossless_webp + - lossless_webp参数指定是否应使用无损压缩保存WEBP图片,这保留了更多的图像数据,但代价是文件大小更大。 + - Comfy dtype: COMBO[false, true] + - Python dtype: bool +- overwrite_mode + - overwrite_mode参数确定节点如何处理同名的现有文件,可以覆盖它们,或者使用文件名前缀作为新文件名的一部分。 + - Comfy dtype: COMBO[false, prefix_as_filename] + - Python dtype: str +- show_history + - show_history参数控制是否显示保存图片的历史记录,这对于查看过去的输出非常有用。 + - Comfy dtype: COMBO[false, true] + - Python dtype: bool +- show_history_by_prefix + - 当show_history_by_prefix参数为true时,它将显示的图片历史记录过滤为仅显示具有相同文件名前缀的图片,增强了组织性。 + - Comfy dtype: COMBO[true, false] + - Python dtype: bool +- embed_workflow + - embed_workflow参数指示是否应在图像文件中包含工作流元数据,提供有关图像创建过程的额外上下文和信息。 + - Comfy dtype: COMBO[true, false] + - Python dtype: bool +- show_previews + - show_previews参数决定保存后是否显示图片预览,提供了一种快速查看操作结果的方法。 + - Comfy dtype: COMBO[true, false] + - Python dtype: bool + +# Output types +- ui + - ui参数包含保存图片后显示的用户界面元素,包括预览和历史记录(如果启用了这些选项)。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Union[List[Dict[str, Union[str, pathlib.Path]]], List[]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Save: + + def __init__(self): + self.output_dir = comfy_paths.output_directory + self.type = 'output' + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'output_path': ('STRING', {'default': '[time(%Y-%m-%d)]', 'multiline': False}), 'filename_prefix': ('STRING', {'default': 'ComfyUI'}), 'filename_delimiter': ('STRING', {'default': '_'}), 'filename_number_padding': ('INT', {'default': 4, 'min': 1, 'max': 9, 'step': 1}), 'filename_number_start': (['false', 'true'],), 'extension': (['png', 'jpg', 'jpeg', 'gif', 'tiff', 'webp', 'bmp'],), 'quality': ('INT', {'default': 100, 'min': 1, 'max': 100, 'step': 1}), 'lossless_webp': (['false', 'true'],), 'overwrite_mode': (['false', 'prefix_as_filename'],), 'show_history': (['false', 'true'],), 'show_history_by_prefix': (['true', 'false'],), 'embed_workflow': (['true', 'false'],), 'show_previews': (['true', 'false'],)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = () + FUNCTION = 'was_save_images' + OUTPUT_NODE = True + CATEGORY = 'WAS Suite/IO' + + def was_save_images(self, images, output_path='', filename_prefix='ComfyUI', filename_delimiter='_', extension='png', quality=100, lossless_webp='false', prompt=None, extra_pnginfo=None, overwrite_mode='false', filename_number_padding=4, filename_number_start='false', show_history='false', show_history_by_prefix='true', embed_workflow='true', show_previews='true'): + delimiter = filename_delimiter + number_padding = filename_number_padding + lossless_webp = lossless_webp == 'true' + tokens = TextTokens() + original_output = self.output_dir + filename_prefix = tokens.parseTokens(filename_prefix) + if output_path in [None, '', 'none', '.']: + output_path = self.output_dir + else: + output_path = tokens.parseTokens(output_path) + if not os.path.isabs(output_path): + output_path = os.path.join(self.output_dir, output_path) + base_output = os.path.basename(output_path) + if output_path.endswith('ComfyUI/output') or output_path.endswith('ComfyUI\\output'): + base_output = '' + if output_path.strip() != '': + if not os.path.isabs(output_path): + output_path = os.path.join(comfy_paths.output_directory, output_path) + if not os.path.exists(output_path.strip()): + cstr(f"The path `{output_path.strip()}` specified doesn't exist! Creating directory.").warning.print() + os.makedirs(output_path, exist_ok=True) + if filename_number_start == 'true': + pattern = f'(\\d+){re.escape(delimiter)}{re.escape(filename_prefix)}' + else: + pattern = f'{re.escape(filename_prefix)}{re.escape(delimiter)}(\\d+)' + existing_counters = [int(re.search(pattern, filename).group(1)) for filename in os.listdir(output_path) if re.match(pattern, os.path.basename(filename))] + existing_counters.sort(reverse=True) + if existing_counters: + counter = existing_counters[0] + 1 + else: + counter = 1 + if existing_counters: + counter = existing_counters[0] + 1 + else: + counter = 1 + file_extension = '.' + extension + if file_extension not in ALLOWED_EXT: + cstr(f"The extension `{extension}` is not valid. The valid formats are: {', '.join(sorted(ALLOWED_EXT))}").error.print() + file_extension = 'png' + results = list() + for image in images: + i = 255.0 * image.cpu().numpy() + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) + if extension == 'webp': + img_exif = img.getexif() + workflow_metadata = '' + prompt_str = '' + if prompt is not None: + prompt_str = json.dumps(prompt) + img_exif[271] = 'Prompt:' + prompt_str + if extra_pnginfo is not None: + for x in extra_pnginfo: + workflow_metadata += json.dumps(extra_pnginfo[x]) + img_exif[270] = 'Workflow:' + workflow_metadata + exif_data = img_exif.tobytes() + else: + metadata = PngInfo() + if embed_workflow == 'true': + if prompt is not None: + metadata.add_text('prompt', json.dumps(prompt)) + if extra_pnginfo is not None: + for x in extra_pnginfo: + metadata.add_text(x, json.dumps(extra_pnginfo[x])) + exif_data = metadata + if overwrite_mode == 'prefix_as_filename': + file = f'{filename_prefix}{file_extension}' + else: + if filename_number_start == 'true': + file = f'{counter:0{number_padding}}{delimiter}{filename_prefix}{file_extension}' + else: + file = f'{filename_prefix}{delimiter}{counter:0{number_padding}}{file_extension}' + if os.path.exists(os.path.join(output_path, file)): + counter += 1 + try: + output_file = os.path.abspath(os.path.join(output_path, file)) + if extension in ['jpg', 'jpeg']: + img.save(output_file, quality=quality, optimize=True) + elif extension == 'webp': + img.save(output_file, quality=quality, lossless=lossless_webp, exif=exif_data) + elif extension == 'png': + img.save(output_file, pnginfo=exif_data, optimize=True) + elif extension == 'bmp': + img.save(output_file) + elif extension == 'tiff': + img.save(output_file, quality=quality, optimize=True) + else: + img.save(output_file, pnginfo=exif_data, optimize=True) + cstr(f'Image file saved to: {output_file}').msg.print() + if show_history != 'true' and show_previews == 'true': + subfolder = self.get_subfolder_path(output_file, original_output) + results.append({'filename': file, 'subfolder': subfolder, 'type': self.type}) + update_history_output_images(output_file) + except OSError as e: + cstr(f'Unable to save file to: {output_file}').error.print() + print(e) + except Exception as e: + cstr('Unable to save file due to the to the following error:').error.print() + print(e) + if overwrite_mode == 'false': + counter += 1 + filtered_paths = [] + if show_history == 'true' and show_previews == 'true': + HDB = WASDatabase(WAS_HISTORY_DATABASE) + conf = getSuiteConfig() + if HDB.catExists('History') and HDB.keyExists('History', 'Output_Images'): + history_paths = HDB.get('History', 'Output_Images') + else: + history_paths = None + if history_paths: + for image_path in history_paths: + image_subdir = self.get_subfolder_path(image_path, self.output_dir) + current_subdir = self.get_subfolder_path(output_file, self.output_dir) + if not os.path.exists(image_path): + continue + if show_history_by_prefix == 'true' and image_subdir != current_subdir: + continue + if show_history_by_prefix == 'true' and (not os.path.basename(image_path).startswith(filename_prefix)): + continue + filtered_paths.append(image_path) + if conf.__contains__('history_display_limit'): + filtered_paths = filtered_paths[-conf['history_display_limit']:] + filtered_paths.reverse() + if filtered_paths: + for image_path in filtered_paths: + subfolder = self.get_subfolder_path(image_path, self.output_dir) + image_data = {'filename': os.path.basename(image_path), 'subfolder': subfolder, 'type': self.type} + results.append(image_data) + if show_previews == 'true': + return {'ui': {'images': results}} + else: + return {'ui': {'images': []}} + + def get_subfolder_path(self, image_path, output_path): + output_parts = output_path.strip(os.sep).split(os.sep) + image_parts = image_path.strip(os.sep).split(os.sep) + common_parts = os.path.commonprefix([output_parts, image_parts]) + subfolder_parts = image_parts[len(common_parts):] + subfolder_path = os.sep.join(subfolder_parts[:-1]) + return subfolder_path +``` \ No newline at end of file diff --git a/docs/Image Scale By Factor (WLSH).md b/docs/Image Scale By Factor (WLSH).md new file mode 100644 index 0000000..2466ebb --- /dev/null +++ b/docs/Image Scale By Factor (WLSH).md @@ -0,0 +1,55 @@ +# Documentation +- Class name: WLSH_Image_Scale_By_Factor +- Category: WLSH Nodes/upscaling +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_Image_Scale_By_Factor 节点的 'upscale' 方法旨在通过指定的因子增加输入图像的尺寸。它支持多种放大方法,以在放大过程中保持或提高图像的质量。此节点在需要放大图像的图像处理工作流程中扮演着关键角色。 + +# Input types +## Required +- original + - ‘original’ 参数是需要被缩放的输入图像。它是操作的核心,因为节点的所有操作都围绕这张图像进行。原始图像的质量和内容直接影响缩放后输出的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- upscale_method + - ‘upscale_method’ 参数决定了用于缩放图像的算法。它对于控制放大图像的质量和特性至关重要。不同的方法可能会产生不同的结果,方法的选择可以显著影响最终的外观。 + - Comfy dtype: COMBO['nearest-exact', 'bilinear', 'area'] + - Python dtype: str +- factor + - ‘factor’ 参数定义了原始图像尺寸乘以的缩放比例。它是一个关键参数,因为它决定了放大图像的最终大小。因子的选择将直接影响细节水平和整体尺寸。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- upscaled_image + - ‘upscaled_image’ 输出是放大过程的结果,反映了按指定因子缩放的输入图像。它很重要,因为它代表了节点操作的直接结果,并用于进一步处理或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WLSH_Image_Scale_By_Factor: + upscale_methods = ['nearest-exact', 'bilinear', 'area'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'original': ('IMAGE',), 'upscale_method': (s.upscale_methods,), 'factor': ('FLOAT', {'default': 2.0, 'min': 0.1, 'max': 8.0, 'step': 0.1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'upscale' + CATEGORY = 'WLSH Nodes/upscaling' + + def upscale(self, original, upscale_method, factor): + old_width = original.shape[2] + old_height = original.shape[1] + new_width = int(old_width * factor) + new_height = int(old_height * factor) + print('Processing image with shape: ', old_width, 'x', old_height, 'to ', new_width, 'x', new_height) + samples = original.movedim(-1, 1) + s = comfy.utils.common_upscale(samples, new_width, new_height, upscale_method, crop='disabled') + s = s.movedim(1, -1) + return (s,) +``` \ No newline at end of file diff --git a/docs/Image Scale by Shortside (WLSH).md b/docs/Image Scale by Shortside (WLSH).md new file mode 100644 index 0000000..7cbeaf7 --- /dev/null +++ b/docs/Image Scale by Shortside (WLSH).md @@ -0,0 +1,66 @@ +# Documentation +- Class name: WLSH_Image_Scale_By_Shortside +- Category: WLSH Nodes/upscaling +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_Image_Scale_By_Shortside 节点的 'upscale' 方法旨在通过指定的短边长度来调整图像大小。它基于图像的原始尺寸智能确定缩放因子,并应用所选的上采样方法以保持或提高图像质量。 + +# Input types +## Required +- original + - “original”参数代表要上采样的图像。它至关重要,因为它是节点执行其操作的来源。节点处理此图像以实现所需的短边长度。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- upscale_method + - “upscale_method”参数定义了用于上采样图像的算法。它显著影响缩放处理后生成的图像的质量和特性。 + - Comfy dtype: COMBO['nearest-exact', 'bilinear', 'area'] + - Python dtype: str +- shortside + - “shortside”参数决定了上采样后图像较短边的目标长度。它是缩放过程中的关键决定因素,直接影响图像的最终尺寸。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - 'IMAGE' 输出是上采样过程的结果,提供了具有指定短边长度的变换图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- width + - 'width' 输出表示上采样图像的新宽度,是缩放操作的结果。 + - Comfy dtype: INT + - Python dtype: int +- height + - 'height' 输出表示上采样图像的新高度,也是缩放过程的结果。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Image_Scale_By_Shortside: + upscale_methods = ['nearest-exact', 'bilinear', 'area'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'original': ('IMAGE',), 'upscale_method': (s.upscale_methods,), 'shortside': ('INT', {'default': 512, 'min': 32, 'max': 4096, 'step': 32})}} + RETURN_TYPES = ('IMAGE', 'INT', 'INT') + RETURN_NAMES = ('IMAGE', 'width', 'height') + FUNCTION = 'upscale' + CATEGORY = 'WLSH Nodes/upscaling' + + def upscale(self, original, upscale_method, shortside): + old_width = original.shape[2] + old_height = original.shape[1] + old_shortside = min(old_width, old_height) + factor = shortside / max(1, old_shortside) + new_width = int(old_width * factor) + new_height = int(old_height * factor) + print('Processing image with shape: ', old_width, 'x', old_height, 'to ', new_width, 'x', new_height) + samples = original.movedim(-1, 1) + s = comfy.utils.common_upscale(samples, new_width, new_height, upscale_method, crop='disabled') + s = s.movedim(1, -1) + return (s, new_width, new_height) +``` \ No newline at end of file diff --git a/docs/Image Seamless Texture.md b/docs/Image Seamless Texture.md new file mode 100644 index 0000000..0f7078d --- /dev/null +++ b/docs/Image Seamless Texture.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: WAS_Image_Make_Seamless +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +make_seamless 方法旨在处理一组图像,将它们转换成无缝纹理。它通过对图像边缘应用混合技术来实现这一点,经过处理的图像可以平铺而不显示可见的接缝。这个功能特别适用于创建可以在游戏开发、合成和3D建模等各种图形应用程序中使用的纹理。 + +# Input types +## Required +- images + - 需要被处理成无缝纹理的输入图像。这些图像是节点将要处理以创建无缝输出的原始材料。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image.Image] +- blending + - 混合因子决定了要在图像边缘应用的混合程度。值越高,过渡越平滑,但同时也会减小图像大小。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- tiled + - tiled 参数指示输出应该是单个无缝图像还是2x2平铺版本,以便更好地可视化无缝效果。 + - Comfy dtype: COMBO[true, false] + - Python dtype: bool +- tiles + - 平铺输出中每个方向(水平和垂直)上的平铺数量。当 tiled 参数设置为 true 时使用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- images + - 处理后的无缝纹理图像结果。这些图像可以平铺而不显示可见的接缝,使它们适合在各种图形应用程序中使用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Make_Seamless: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'blending': ('FLOAT', {'default': 0.4, 'max': 1.0, 'min': 0.0, 'step': 0.01}), 'tiled': (['true', 'false'],), 'tiles': ('INT', {'default': 2, 'max': 6, 'min': 2, 'step': 2})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('images',) + FUNCTION = 'make_seamless' + CATEGORY = 'WAS Suite/Image/Process' + + def make_seamless(self, images, blending, tiled, tiles): + WTools = WAS_Tools_Class() + seamless_images = [] + for image in images: + seamless_images.append(pil2tensor(WTools.make_seamless(tensor2pil(image), blending, tiled, tiles))) + seamless_images = torch.cat(seamless_images, dim=0) + return (seamless_images,) +``` \ No newline at end of file diff --git a/docs/Image Select Channel.md b/docs/Image Select Channel.md new file mode 100644 index 0000000..bef2f05 --- /dev/null +++ b/docs/Image Select Channel.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: WAS_Image_Select_Channel +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Select_Channel 节点旨在从图像中分离出特定的颜色通道以进行进一步的处理或分析。它允许用户选择 'red'(红色)、'green'(绿色)或 'blue'(蓝色)通道,并将图像转换为单通道表示,通过将所选通道复制到所有三个颜色通道中。 + +# Input types +## Required +- image + - 输入图像是节点将处理的主要数据。它对节点的操作至关重要,因为它决定了将要被选择和处理的通道的内容。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- channel + - 通道参数指定从图像中提取哪种颜色通道。它很重要,因为它决定了节点操作的最终结果,决定了在输出图像中保留的颜色信息。 + - Comfy dtype: COMBO['red', 'green', 'blue'] + - Python dtype: str + +# Output types +- selected_image + - 输出是处理后的图像,其中包含一个选定的单色通道。这个图像可以用于各种只需要一个颜色通道的应用中,或者用于进一步的图像处理任务。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Select_Channel: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'channel': (['red', 'green', 'blue'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'select_channel' + CATEGORY = 'WAS Suite/Image/Process' + + def select_channel(self, image, channel='red'): + image = self.convert_to_single_channel(tensor2pil(image), channel) + return (pil2tensor(image),) + + def convert_to_single_channel(self, image, channel='red'): + image = image.convert('RGB') + if channel == 'red': + channel_img = image.split()[0].convert('L') + elif channel == 'green': + channel_img = image.split()[1].convert('L') + elif channel == 'blue': + channel_img = image.split()[2].convert('L') + else: + raise ValueError("Invalid channel option. Please choose 'red', 'green', or 'blue'.") + channel_img = Image.merge('RGB', (channel_img, channel_img, channel_img)) + return channel_img +``` \ No newline at end of file diff --git a/docs/Image Select Color.md b/docs/Image Select Color.md new file mode 100644 index 0000000..cf5e406 --- /dev/null +++ b/docs/Image Select Color.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: WAS_Image_Select_Color +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Select_Color 节点旨在通过选择与指定颜色及其容差范围内匹配的像素来处理图像。它通过专注于所需的颜色范围来增强图像,允许对特定视觉元素进行主题或风格上的强调。 + +# Input types +## Required +- image + - 图像参数对于节点的操作至关重要,因为它是将要被处理的输入。它决定了节点将根据指定的颜色标准分析和操作的视觉内容。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- red + - 红色参数定义了图像中要选取的颜色的红色分量。它通过指定要考虑的红色值范围,在确定最终视觉结果方面起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- green + - 绿色参数指定了目标颜色的绿色分量。它对于实现所需的颜色选择很重要,并有助于整体颜色过滤过程。 + - Comfy dtype: INT + - Python dtype: int +- blue + - 蓝色参数设置要选取的颜色的蓝色分量。它是颜色选择过程中的一个关键因素,确保只有处于指定蓝色范围内的像素被包含。 + - Comfy dtype: INT + - Python dtype: int +- variance + - 容差参数通过定义可接受的颜色偏差范围,允许颜色选择具有一定的灵活性。它对于处理图像内颜色强度的轻微变化具有重要意义。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- selected_image + - 选定的图像输出代表了处理后的图像,其中仅保留了符合指定颜色标准的像素。它是节点操作的成果,并反映了预期的主题焦点。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Select_Color: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'red': ('INT', {'default': 255.0, 'min': 0.0, 'max': 255.0, 'step': 0.1}), 'green': ('INT', {'default': 255.0, 'min': 0.0, 'max': 255.0, 'step': 0.1}), 'blue': ('INT', {'default': 255.0, 'min': 0.0, 'max': 255.0, 'step': 0.1}), 'variance': ('INT', {'default': 10, 'min': 0, 'max': 255, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'select_color' + CATEGORY = 'WAS Suite/Image/Process' + + def select_color(self, image, red=255, green=255, blue=255, variance=10): + image = self.color_pick(tensor2pil(image), red, green, blue, variance) + return (pil2tensor(image),) + + def color_pick(self, image, red=255, green=255, blue=255, variance=10): + image = image.convert('RGB') + selected_color = Image.new('RGB', image.size, (0, 0, 0)) + (width, height) = image.size + for x in range(width): + for y in range(height): + pixel = image.getpixel((x, y)) + (r, g, b) = pixel + if r >= red - variance and r <= red + variance and (g >= green - variance) and (g <= green + variance) and (b >= blue - variance) and (b <= blue + variance): + selected_color.putpixel((x, y), (r, g, b)) + return selected_color +``` \ No newline at end of file diff --git a/docs/Image Shadows and Highlights.md b/docs/Image Shadows and Highlights.md new file mode 100644 index 0000000..94c7104 --- /dev/null +++ b/docs/Image Shadows and Highlights.md @@ -0,0 +1,82 @@ +# Documentation +- Class name: WAS_Shadow_And_Highlight_Adjustment +- Category: WAS Suite/Image/Adjustment +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Shadow_And_Highlight_Adjustment节点旨在通过调整图像的阴影和高光来修改其对比度和色调范围。该节点通过增强图像中较暗和较亮区域的细节,允许更好的视觉定义和更平衡的曝光。它通过分别对阴影和高光应用不同的阈值和因子来操作,并可选择性地平滑这些区域,以获得更自然的外观。该节点特别适用于后期处理图像,其中动态范围需要针对更好的视觉吸引力或满足特定技术要求进行优化。 + +# Input types +## Required +- image + - 要应用阴影和高光调整的输入图像。此参数至关重要,因为它决定了节点将处理的基本视觉内容。节点的执行和结果严重依赖于输入图像的质量和特性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- shadow_threshold + - 像素值被视为阴影部分的阈值。调整此参数会影响图像中阴影的修改程度。这是一个重要的参数,用于控制最终输出中阴影的强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- shadow_factor + - 用于增加图像阴影区域强度的乘法因子。这是一个关键参数,用于增强图像暗部的细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- shadow_smoothing + - 要应用于阴影遮罩的平滑度。较高的值会在阴影和非阴影区域之间产生更平滑的过渡,这可能更适合更自然的外观,但可能会降低阴影中的对比度。 + - Comfy dtype: FLOAT + - Python dtype: float +- highlight_threshold + - 像素值被视为高光部分的阈值。此参数对于确定图像的哪些部分将被视为高光并随后进行调整至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- highlight_factor + - 用于减少图像高光区域强度的乘法因子。这是一个关键参数,用于控制高光的烧毁程度,并防止图像中较亮部分的细节丢失。 + - Comfy dtype: FLOAT + - Python dtype: float +- highlight_smoothing + - 要应用于高光遮罩的平滑度。与阴影平滑类似,它有助于在高光和非高光区域之间实现更渐进的过渡。 + - Comfy dtype: FLOAT + - Python dtype: float +- simplify_isolation + - 要应用于阴影和高光遮罩隔离的简化量。它可以用于减少遮罩的复杂性,这对于性能原因或实现特定视觉效果可能很有帮助。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- image + - 最终调整后的图像,具有增强的阴影和高光。它代表了节点的主要输出,展示了对输入图像进行的所有调整的累积效果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- shadow_map + - 作为调整过程的一部分生成的阴影图。它是一个灰度图像,其中较暗的值表示已被修改的阴影区域。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- highlight_map + - 作为调整过程的一部分生成的高光图。它是一个灰度图像,其中较亮的值指示已被修改的高光区域。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Shadow_And_Highlight_Adjustment: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'shadow_threshold': ('FLOAT', {'default': 75, 'min': 0.0, 'max': 255.0, 'step': 0.1}), 'shadow_factor': ('FLOAT', {'default': 1.5, 'min': -12.0, 'max': 12.0, 'step': 0.1}), 'shadow_smoothing': ('FLOAT', {'default': 0.25, 'min': -255.0, 'max': 255.0, 'step': 0.1}), 'highlight_threshold': ('FLOAT', {'default': 175, 'min': 0.0, 'max': 255.0, 'step': 0.1}), 'highlight_factor': ('FLOAT', {'default': 0.5, 'min': -12.0, 'max': 12.0, 'step': 0.1}), 'highlight_smoothing': ('FLOAT', {'default': 0.25, 'min': -255.0, 'max': 255.0, 'step': 0.1}), 'simplify_isolation': ('FLOAT', {'default': 0, 'min': -255.0, 'max': 255.0, 'step': 0.1})}} + RETURN_TYPES = ('IMAGE', 'IMAGE', 'IMAGE') + RETURN_NAMES = ('image', 'shadow_map', 'highlight_map') + FUNCTION = 'apply_shadow_and_highlight' + CATEGORY = 'WAS Suite/Image/Adjustment' + + def apply_shadow_and_highlight(self, image, shadow_threshold=30, highlight_threshold=220, shadow_factor=1.5, highlight_factor=0.5, shadow_smoothing=0, highlight_smoothing=0, simplify_isolation=0): + WTools = WAS_Tools_Class() + (result, shadows, highlights) = WTools.shadows_and_highlights(tensor2pil(image), shadow_threshold, highlight_threshold, shadow_factor, highlight_factor, shadow_smoothing, highlight_smoothing, simplify_isolation) + (result, shadows, highlights) = WTools.shadows_and_highlights(tensor2pil(image), shadow_threshold, highlight_threshold, shadow_factor, highlight_factor, shadow_smoothing, highlight_smoothing, simplify_isolation) + return (pil2tensor(result), pil2tensor(shadows), pil2tensor(highlights)) +``` \ No newline at end of file diff --git a/docs/Image Size to Number.md b/docs/Image Size to Number.md new file mode 100644 index 0000000..8a4dedd --- /dev/null +++ b/docs/Image Size to Number.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: WAS_Image_Size_To_Number +- Category: WAS Suite/Number/Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Size_To_Number 节点旨在提取图像的尺寸并将其转换为数值。它提供了一种直接的方法来获取图像的宽度和高度,以不同的格式,便于进一步的处理或分析,这需要数值化的尺寸信息。 + +# Input types +## Required +- image + - 图像参数对于节点的操作至关重要,因为它是提取尺寸的来源。它直接影响节点的输出,通过确定返回的数值。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or numpy.ndarray + +# Output types +- width_num + - width_num 表示图像宽度的整数值。它很重要,因为它提供了图像宽度的数值度量,可以用于各种目的,如调整大小或布局计算。 + - Comfy dtype: NUMBER + - Python dtype: int +- height_num + - height_num 表示图像高度的整数值。对于需要知道图像垂直范围的应用来说,它是至关重要的,例如打印或显示调整。 + - Comfy dtype: NUMBER + - Python dtype: int +- width_float + - width_float 提供了图像宽度的浮点数值,允许在必要时进行更精确的测量和计算。 + - Comfy dtype: FLOAT + - Python dtype: float +- height_float + - height_float 提供了图像高度的浮点数值,对于需要在垂直测量中具有高度精确度的应用非常有用。 + - Comfy dtype: FLOAT + - Python dtype: float +- width_int + - width_int 是图像宽度的另一种整数值表示,提供了可以与width_num用于不同应用的可互换的数值。 + - Comfy dtype: INT + - Python dtype: int +- height_int + - height_int 是图像高度的另一种整数值表示,为可能更喜欢或需要这种特定格式的应用提供了另一种数值。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Size_To_Number: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',)}} + RETURN_TYPES = ('NUMBER', 'NUMBER', 'FLOAT', 'FLOAT', 'INT', 'INT') + RETURN_NAMES = ('width_num', 'height_num', 'width_float', 'height_float', 'width_int', 'height_int') + FUNCTION = 'image_width_height' + CATEGORY = 'WAS Suite/Number/Operations' + + def image_width_height(self, image): + image = tensor2pil(image) + if image.size: + return (image.size[0], image.size[1], float(image.size[0]), float(image.size[1]), image.size[0], image.size[1]) + return (0, 0, 0, 0, 0, 0) +``` \ No newline at end of file diff --git a/docs/Image Stitch.md b/docs/Image Stitch.md new file mode 100644 index 0000000..0bf24a9 --- /dev/null +++ b/docs/Image Stitch.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: WAS_Image_Stitch +- Category: WAS Suite/Image/Transform +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Stitch 节点旨在根据指定的缝合方向无缝地组合两张图像。它应用羽化效果以在图像之间创建平滑过渡,这对于创建全景图像或纹理特别有用。该节点能够处理不同的缝合模式,例如'top'、'left'、'bottom'和'right',允许灵活的图像组合。 + +# Input types +## Required +- image_a + - 要缝合的第一张图像。它作为缝合操作的基础层,并决定了最终缝合图像的初始部分。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- image_b + - 要缝合的第二张图像。它将根据指定的缝合模式与第一张图像对齐,并混合以创建无缝的组合。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- stitch + - 两张图像应缝合在一起的方向。可以是'top'、'left'、'bottom'或'right',定义了缝合的方向以及图像组合的方式。 + - Comfy dtype: COMBO[top, left, bottom, right] + - Python dtype: str +- feathering + - 在缝合边界应用的羽化量。更高的值会在图像之间产生更柔和、更渐进的过渡,但也会减小输出图像的大小。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- stitched_image + - 缝合过程后的结果图像。它根据指定的缝合模式和羽化将两个输入图像组合成单个、无缝的图像。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Stitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image_a': ('IMAGE',), 'image_b': ('IMAGE',), 'stitch': (['top', 'left', 'bottom', 'right'],), 'feathering': ('INT', {'default': 50, 'min': 0, 'max': 2048, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_stitching' + CATEGORY = 'WAS Suite/Image/Transform' + + def image_stitching(self, image_a, image_b, stitch='right', feathering=50): + valid_stitches = ['top', 'left', 'bottom', 'right'] + if stitch not in valid_stitches: + cstr(f"The stitch mode `{stitch}` is not valid. Valid sitch modes are {', '.join(valid_stitches)}").error.print() + if feathering > 2048: + cstr(f'The stitch feathering of `{feathering}` is too high. Please choose a value between `0` and `2048`').error.print() + WTools = WAS_Tools_Class() + stitched_image = WTools.stitch_image(tensor2pil(image_a), tensor2pil(image_b), stitch, feathering) + return (pil2tensor(stitched_image),) +``` \ No newline at end of file diff --git a/docs/Image Style Filter.md b/docs/Image Style Filter.md new file mode 100644 index 0000000..2179890 --- /dev/null +++ b/docs/Image Style Filter.md @@ -0,0 +1,108 @@ +# Documentation +- Class name: WAS_Image_Style_Filter +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Style_Filter节点旨在对输入图像应用多种预定义风格,模拟各种模仿流行摄影应用外观的滤镜。它通过根据所选风格调整图像的颜色色调、对比度和其他视觉方面来增强图像,允许在没有详细了解图像处理技术的情况下实现广泛的创意效果。 + +# Input types +## Required +- image + - 要应用风格的输入图像。它作为节点执行其风格化操作的基础。图像的内容和属性影响最终的风格化结果,使其成为节点执行的基本参数。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or list[PIL.Image.Image] +- style + - 要应用于输入图像的风格。每种风格对应一组特定的视觉调整,根据所选的审美标准转换图像。风格的选择至关重要,因为它决定了输出图像的整体外观和感觉。 + - Comfy dtype: COMBO['1977', 'aden', 'brannan', 'brooklyn', 'clarendon', 'earlybird', 'fairy tale', 'gingham', 'hudson', 'inkwell', 'kelvin', 'lark', 'lofi', 'maven', 'mayfair', 'moon', 'nashville', 'perpetua', 'reyes', 'rise', 'slumber', 'stinson', 'toaster', 'valencia', 'walden', 'willow', 'xpro2'] + - Python dtype: str + +# Output types +- styled_image + - 应用风格后的结果是图像。它反映了节点所做的创造性转换,体现了所选风格的视觉效果。此输出很重要,因为它代表了节点功能最终产物。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Style_Filter: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'style': (['1977', 'aden', 'brannan', 'brooklyn', 'clarendon', 'earlybird', 'fairy tale', 'gingham', 'hudson', 'inkwell', 'kelvin', 'lark', 'lofi', 'maven', 'mayfair', 'moon', 'nashville', 'perpetua', 'reyes', 'rise', 'slumber', 'stinson', 'toaster', 'valencia', 'walden', 'willow', 'xpro2'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_style_filter' + CATEGORY = 'WAS Suite/Image/Filter' + + def image_style_filter(self, image, style): + if 'pilgram' not in packages(): + install_package('pilgram') + import pilgram + WTools = WAS_Tools_Class() + tensors = [] + for img in image: + if style == '1977': + tensors.append(pil2tensor(pilgram._1977(tensor2pil(img)))) + elif style == 'aden': + tensors.append(pil2tensor(pilgram.aden(tensor2pil(img)))) + elif style == 'brannan': + tensors.append(pil2tensor(pilgram.brannan(tensor2pil(img)))) + elif style == 'brooklyn': + tensors.append(pil2tensor(pilgram.brooklyn(tensor2pil(img)))) + elif style == 'clarendon': + tensors.append(pil2tensor(pilgram.clarendon(tensor2pil(img)))) + elif style == 'earlybird': + tensors.append(pil2tensor(pilgram.earlybird(tensor2pil(img)))) + elif style == 'fairy tale': + tensors.append(pil2tensor(WTools.sparkle(tensor2pil(img)))) + elif style == 'gingham': + tensors.append(pil2tensor(pilgram.gingham(tensor2pil(img)))) + elif style == 'hudson': + tensors.append(pil2tensor(pilgram.hudson(tensor2pil(img)))) + elif style == 'inkwell': + tensors.append(pil2tensor(pilgram.inkwell(tensor2pil(img)))) + elif style == 'kelvin': + tensors.append(pil2tensor(pilgram.kelvin(tensor2pil(img)))) + elif style == 'lark': + tensors.append(pil2tensor(pilgram.lark(tensor2pil(img)))) + elif style == 'lofi': + tensors.append(pil2tensor(pilgram.lofi(tensor2pil(img)))) + elif style == 'maven': + tensors.append(pil2tensor(pilgram.maven(tensor2pil(img)))) + elif style == 'mayfair': + tensors.append(pil2tensor(pilgram.mayfair(tensor2pil(img)))) + elif style == 'moon': + tensors.append(pil2tensor(pilgram.moon(tensor2pil(img)))) + elif style == 'nashville': + tensors.append(pil2tensor(pilgram.nashville(tensor2pil(img)))) + elif style == 'perpetua': + tensors.append(pil2tensor(pilgram.perpetua(tensor2pil(img)))) + elif style == 'reyes': + tensors.append(pil2tensor(pilgram.reyes(tensor2pil(img)))) + elif style == 'rise': + tensors.append(pil2tensor(pilgram.rise(tensor2pil(img)))) + elif style == 'slumber': + tensors.append(pil2tensor(pilgram.slumber(tensor2pil(img)))) + elif style == 'stinson': + tensors.append(pil2tensor(pilgram.stinson(tensor2pil(img)))) + elif style == 'toaster': + tensors.append(pil2tensor(pilgram.toaster(tensor2pil(img)))) + elif style == 'valencia': + tensors.append(pil2tensor(pilgram.valencia(tensor2pil(img)))) + elif style == 'walden': + tensors.append(pil2tensor(pilgram.walden(tensor2pil(img)))) + elif style == 'willow': + tensors.append(pil2tensor(pilgram.willow(tensor2pil(img)))) + elif style == 'xpro2': + tensors.append(pil2tensor(pilgram.xpro2(tensor2pil(img)))) + else: + tensors.append(img) + tensors = torch.cat(tensors, dim=0) + return (tensors,) +``` \ No newline at end of file diff --git a/docs/Image Threshold.md b/docs/Image Threshold.md new file mode 100644 index 0000000..5e46527 --- /dev/null +++ b/docs/Image Threshold.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: WAS_Image_Threshold +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Threshold 节点旨在通过应用阈值来处理图像,这对于从灰度输入创建二进制图像非常有用。它在图像分割和特征提取任务中发挥关键作用,通过指定的阈值简化图像为其核心结构。 + +# Input types +## Required +- image + - 图像参数对于节点的操作至关重要,因为它是将被处理的输入。它通过确定将经历阈值处理的内容影响执行,这对于最终输出的清晰度和细节至关重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- threshold + - 阈值参数非常重要,因为它决定了图像中像素值分类的截止点。它通过控制灰度值转换为黑色或白色(基于它们是否满足或超过阈值)直接影响节点的输出。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- thresholded_image + - 阈值化图像输出代表了应用阈值后输入图像的处理结果。它很重要,因为它提供了输入的二进制版本,通常用于进一步分析或作为更复杂的图像处理工作流程中的一步。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Threshold: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_threshold' + CATEGORY = 'WAS Suite/Image/Process' + + def image_threshold(self, image, threshold=0.5): + return (pil2tensor(self.apply_threshold(tensor2pil(image), threshold)),) + + def apply_threshold(self, input_image, threshold=0.5): + grayscale_image = input_image.convert('L') + threshold_value = int(threshold * 255) + thresholded_image = grayscale_image.point(lambda x: 255 if x >= threshold_value else 0, mode='L') + return thresholded_image +``` \ No newline at end of file diff --git a/docs/Image Tile Offset (mtb).md b/docs/Image Tile Offset (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Image Tiled.md b/docs/Image Tiled.md new file mode 100644 index 0000000..3ca201b --- /dev/null +++ b/docs/Image Tiled.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: WAS_Image_Tile_Batch +- Category: WAS Suite/Image/Process +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Tile_Batch 节点的 `tile_image` 方法旨在将单个图像划分为指定数量的较小图块。它智能地管理划分,以保持纵横比,并确保在图像上平等地分布图块。这种功能特别适用于需要详细查看图像或以更易管理的方式处理大图像的应用。 + +# Input types +## Required +- image + - 'image' 参数是节点的主要输入,代表要被划分为图块的图像。它的作用至关重要,因为节点的整个操作都围绕处理这张图像展开。输入图像的质量和特性直接影响输出的图块。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- num_tiles + - 'num_tiles' 参数决定了输入图像将被划分为的图块总数。它是一个可选参数,默认值为6,允许用户指定平铺过程的粒度。这个参数显著影响输出图块的大小和数量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGES + - 'IMAGES' 输出参数代表从输入图像生成的图块集合。每个图块都是原始图像的一部分,集合的排列反映了由 'num_tiles' 参数定义的结构。这个输出很重要,因为它是节点处理的直接结果。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Tile_Batch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'num_tiles': ('INT', {'default': 4, 'max': 64, 'min': 2, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('IMAGES',) + FUNCTION = 'tile_image' + CATEGORY = 'WAS Suite/Image/Process' + + def tile_image(self, image, num_tiles=6): + image = tensor2pil(image.squeeze(0)) + (img_width, img_height) = image.size + num_rows = int(num_tiles ** 0.5) + num_cols = (num_tiles + num_rows - 1) // num_rows + tile_width = img_width // num_cols + tile_height = img_height // num_rows + tiles = [] + for y in range(0, img_height, tile_height): + for x in range(0, img_width, tile_width): + tile = image.crop((x, y, x + tile_width, y + tile_height)) + tiles.append(pil2tensor(tile)) + tiles = torch.stack(tiles, dim=0).squeeze(1) + return (tiles,) +``` \ No newline at end of file diff --git a/docs/Image To Mask.md b/docs/Image To Mask.md new file mode 100644 index 0000000..dd07954 --- /dev/null +++ b/docs/Image To Mask.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: ImageToMask +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +ImageToMask节点旨在将输入图像转换为掩码表示。它提供了一种基于强度或alpha值转换图像的方法,有助于从输入数据创建二进制或单通道掩码,这对于各种图像处理任务(如分割)至关重要。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它是节点的主要输入。它通过确定要生成的掩码的来源来影响节点的执行。预期图像以张量格式存在,节点将处理该张量以产生所需的掩码输出。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- method + - 方法参数决定了节点采用的转换策略。它很重要,因为它决定了掩码是基于强度还是alpha值派生,这反过来又影响了最终掩码的特性和适用于下游应用的适宜性。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- MASK + - MASK输出是一个张量,表示从输入图像派生的掩码。它是一个关键的输出,因为它是节点转换过程的直接结果将转换后的图像数据封装成适合于分割或其他基于掩码的应用的格式。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageToMask: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'method': (['intensity', 'alpha'],)}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'convert' + CATEGORY = 'Masquerade Nodes' + + def convert(self, image, method): + if method == 'intensity': + if len(image.shape) > 3 and image.shape[3] == 4: + image = tensor2rgb(image) + return (tensor2mask(image),) + else: + return (tensor2rgba(image)[:, :, :, 0],) +``` \ No newline at end of file diff --git a/docs/Image Transpose.md b/docs/Image Transpose.md new file mode 100644 index 0000000..730c04d --- /dev/null +++ b/docs/Image Transpose.md @@ -0,0 +1,87 @@ +# Documentation +- Class name: WAS_Image_Transpose +- Category: WAS Suite/Image/Transform +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Transpose节点旨在执行图像操作任务,特别通过旋转和调整大小来转换图像。它允许将一个图像叠加到另一个图像上,可以指定输出的宽度和高度、叠加的位置以及旋转的程度。此外,它还提供了羽化功能,用于软化叠加层的边缘,以实现更自然的混合效果。此节点对于创建具有精确控制元素位置和外观的复合图像至关重要。 + +# Input types +## Required +- image + - 作为将应用叠加的基础图像。它作为合成图像创建的画布。选择此图像显著影响输出的最终外观。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image_overlay + - 将叠加在基础图像上的图像。根据指定的参数对其进行操作,以便与基础图像无缝融合。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- width + - 输出图像的期望宽度。它决定了基础和叠加图像的缩放,以适应指定的尺寸。 + - Comfy dtype: INT + - Python dtype: int +- height + - 输出图像的期望高度。与宽度一起,它决定了最终合成图像的大小。 + - Comfy dtype: INT + - Python dtype: int +- X + - 叠加图像放置在基础图像上的位置的X坐标。 + - Comfy dtype: INT + - Python dtype: int +- Y + - 叠加图像放置在基础图像上的位置的Y坐标。 + - Comfy dtype: INT + - Python dtype: int +- rotation + - 在叠加图像放置到基础图像上之前要应用的旋转度数。 + - Comfy dtype: INT + - Python dtype: int +- feathering + - 应用于叠加图像边缘的羽化量,以便与基础图像更平滑地混合。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output_image + - 根据指定的参数,由基础图像和叠加图像转换得到的最终合成图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Transpose: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'image_overlay': ('IMAGE',), 'width': ('INT', {'default': 512, 'min': -48000, 'max': 48000, 'step': 1}), 'height': ('INT', {'default': 512, 'min': -48000, 'max': 48000, 'step': 1}), 'X': ('INT', {'default': 0, 'min': -48000, 'max': 48000, 'step': 1}), 'Y': ('INT', {'default': 0, 'min': -48000, 'max': 48000, 'step': 1}), 'rotation': ('INT', {'default': 0, 'min': -360, 'max': 360, 'step': 1}), 'feathering': ('INT', {'default': 0, 'min': 0, 'max': 4096, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_transpose' + CATEGORY = 'WAS Suite/Image/Transform' + + def image_transpose(self, image: torch.Tensor, image_overlay: torch.Tensor, width: int, height: int, X: int, Y: int, rotation: int, feathering: int=0): + return (pil2tensor(self.apply_transpose_image(tensor2pil(image), tensor2pil(image_overlay), (width, height), (X, Y), rotation, feathering)),) + + def apply_transpose_image(self, image_bg, image_element, size, loc, rotate=0, feathering=0): + image_element = image_element.rotate(rotate, expand=True) + image_element = image_element.resize(size) + if feathering > 0: + mask = Image.new('L', image_element.size, 255) + draw = ImageDraw.Draw(mask) + for i in range(feathering): + alpha_value = int(255 * (i + 1) / feathering) + draw.rectangle((i, i, image_element.size[0] - i, image_element.size[1] - i), fill=alpha_value) + alpha_mask = Image.merge('RGBA', (mask, mask, mask, mask)) + image_element = Image.composite(image_element, Image.new('RGBA', image_element.size, (0, 0, 0, 0)), alpha_mask) + new_image = Image.new('RGBA', image_bg.size, (0, 0, 0, 0)) + new_image.paste(image_element, loc) + image_bg = image_bg.convert('RGBA') + image_bg.paste(new_image, (0, 0), new_image) + return image_bg +``` \ No newline at end of file diff --git a/docs/Image Voronoi Noise Filter.md b/docs/Image Voronoi Noise Filter.md new file mode 100644 index 0000000..8fd8091 --- /dev/null +++ b/docs/Image Voronoi Noise Filter.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: WAS_Image_Voronoi_Noise_Filter +- Category: WAS Suite/Image/Generate/Noise +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Voronoi_Noise_Filter节点旨在从输入图像生成Voronoi噪声模式。它可以用于为进一步的图像处理或艺术目的创建独特的纹理或图案。该节点利用Voronoi图的原理产生噪声模式,可以根据宽度、高度、密度和调制器等参数进行调整,提供了一个用于噪声生成的多功能工具。 + +# Input types +## Required +- width + - 宽度参数定义了输出图像的宽度。它对于确定生成的噪声模式的整体尺寸至关重要。此设置通过规定输出的水平范围直接影响节点的执行。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置输出图像的高度。它与宽度一起工作,以建立噪声模式的完整分辨率。此参数对于控制噪声纹理的垂直尺寸至关重要。 + - Comfy dtype: INT + - Python dtype: int +- density + - 密度参数影响噪声模式中Voronoi单元的浓度。更高的密度值会产生更精细、更详细的噪声纹理。该参数对于调整输出中的细节级别非常重要。 + - Comfy dtype: INT + - Python dtype: int +- modulator + - 调制器参数调整噪声模式中的变化。它可以通过改变Voronoi单元的分布,引入不同级别的复杂性到噪声中。这个参数是微调噪声纹理视觉外观的关键。 + - Comfy dtype: INT + - Python dtype: int +- seed + - 种子参数用于初始化随机数生成器,确保每次使用相同的种子值运行节点时都能得到可重复的模式。它在生成每个特定种子的可预测和一致的噪声纹理中起着至关重要的作用。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- flat + - 平坦参数决定噪声纹理是否应具有平坦或更传统的Voronoi外观。这个可选设置可以用来根据期望的结果实现不同的美学效果。 + - Comfy dtype: COMBO[False, True] + - Python dtype: bool +- RGB_output + - RGB_output参数指定输出图像是否应为RGB格式。设置为True时,节点生成RGB图像;设置为False时,它产生灰度图像。这个选项允许在图像输出类型上具有灵活性。 + - Comfy dtype: COMBO[True, False] + - Python dtype: bool + +# Output types +- image + - 输出图像参数代表节点生成的Voronoi噪声模式的结果。它是一个重要的输出,因为它是节点执行的主要结果,可以用于进一步处理或显示。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Voronoi_Noise_Filter: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'width': ('INT', {'default': 512, 'max': 4096, 'min': 64, 'step': 1}), 'height': ('INT', {'default': 512, 'max': 4096, 'min': 64, 'step': 1}), 'density': ('INT', {'default': 50, 'max': 256, 'min': 10, 'step': 2}), 'modulator': ('INT', {'default': 0, 'max': 8, 'min': 0, 'step': 1}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'optional': {'flat': (['False', 'True'],), 'RGB_output': (['True', 'False'],)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'voronoi_noise_filter' + CATEGORY = 'WAS Suite/Image/Generate/Noise' + + def voronoi_noise_filter(self, width, height, density, modulator, seed, flat='False', RGB_output='True'): + WTools = WAS_Tools_Class() + image = WTools.worley_noise(height=height, width=width, density=density, option=modulator, use_broadcast_ops=True, seed=seed, flat=flat == 'True').image + if RGB_output == 'True': + image = image.convert('RGB') + else: + image = image.convert('L') + return (pil2tensor(image),) +``` \ No newline at end of file diff --git a/docs/Image fDOF Filter.md b/docs/Image fDOF Filter.md new file mode 100644 index 0000000..00babb6 --- /dev/null +++ b/docs/Image fDOF Filter.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: WAS_Image_fDOF +- Category: WAS Suite/Image/Filter +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_fDOF节点的fdof_composite函数旨在对图像应用景深效果,通过模糊背景来增强对主体的视觉焦点。它通过结合不同的图像处理技术实现这一效果,这些技术适用于不同的模式,如模拟、高斯或盒状模糊,并通过诸如半径和样本数等参数进行定制。 + +# Input types +## Required +- image + - 图像参数对于节点的操作至关重要,因为它是将要应用景深效果的输入图像。它通过确定将要处理的视觉内容,显著影响节点执行的最终结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- depth + - 深度参数提供了一个深度图,用于确定图像中应该聚焦或模糊的区域。它在节点的执行中起着关键作用,通过指导景深效果的应用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- mode + - 模式参数确定要应用于图像的模糊类型。它很重要,因为它决定了景深效果的风格,提供了模拟、高斯或盒状模糊等选项。 + - Comfy dtype: COMBO['mock', 'gaussian', 'box'] + - Python dtype: str +- radius + - 半径参数定义了模糊效果的范围,对于控制景深的强度很重要。它直接影响输出图像中模糊区域的外观。 + - Comfy dtype: INT + - Python dtype: int +- samples + - 样本参数指定了模糊效果应用的次数,这可以增加模糊的平滑度。它通过确定最终合成图像中的细节水平来影响节点的执行。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output_image + - 输出图像参数代表了应用了景深效果的最终处理图像。它很重要,因为它是节点操作的直接结果,并反映了应用的过滤器的创意意图。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_fDOF: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'depth': ('IMAGE',), 'mode': (['mock', 'gaussian', 'box'],), 'radius': ('INT', {'default': 8, 'min': 1, 'max': 128, 'step': 1}), 'samples': ('INT', {'default': 1, 'min': 1, 'max': 3, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'fdof_composite' + CATEGORY = 'WAS Suite/Image/Filter' + + def fdof_composite(self, image, depth, radius, samples, mode): + import cv2 as cv + tensor_images = [] + for i in range(len(image)): + if i <= len(image): + img = tensor2pil(image[i]) + else: + img = tensor2pil(image[-1]) + if i <= len(depth): + dpth = tensor2pil(depth[i]) + else: + dpth = tensor2pil(depth[-1]) + tensor_images.append(pil2tensor(self.portraitBlur(img, dpth, radius, samples, mode))) + tensor_images = torch.cat(tensor_images, dim=0) + return (tensor_images,) + + def portraitBlur(self, img, mask, radius, samples, mode='mock'): + mask = mask.resize(img.size).convert('L') + bimg: Optional[Image.Image] = None + if mode == 'mock': + bimg = medianFilter(img, radius, radius * 1500, 75) + elif mode == 'gaussian': + bimg = img.filter(ImageFilter.GaussianBlur(radius=radius)) + elif mode == 'box': + bimg = img.filter(ImageFilter.BoxBlur(radius)) + else: + return + bimg.convert(img.mode) + rimg: Optional[Image.Image] = None + if samples > 1: + for i in range(samples): + if not rimg: + rimg = Image.composite(img, bimg, mask) + else: + rimg = Image.composite(rimg, bimg, mask) + else: + rimg = Image.composite(img, bimg, mask).convert('RGB') + return rimg +``` \ No newline at end of file diff --git a/docs/Image to Latent Mask.md b/docs/Image to Latent Mask.md new file mode 100644 index 0000000..9c10a07 --- /dev/null +++ b/docs/Image to Latent Mask.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: WAS_Image_To_Mask +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +`image_to_mask` 方法旨在从一组图像中提取特定的颜色通道并将其转换为掩码。这一过程对于需要隔离图像特定组成部分的应用至关重要,例如在图像分割或对象识别任务中。该节点通过选择所需的通道并将其转换为二进制掩码来操作,然后可以对掩码进行进一步的分析或操作。 + +# Input types +## Required +- images + - ‘images’ 参数至关重要,因为它代表了节点将处理的输入图像。它是节点运行所需的,并且直接影响输出掩码,它决定了掩码操作的源材料。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +- channel + - ‘channel’ 参数决定将提取哪个颜色通道以形成掩码。这是一个关键的选择,它影响最终掩码的外观以及在后续处理步骤中的实用性。 + - Comfy dtype: COMBO['alpha', 'red', 'green', 'blue'] + - Python dtype: str + +# Output types +- MASKS + - ‘MASKS’ 输出由从输入图像的选定颜色通道派生的生成掩码组成。这些掩码对于涉及隔离和分析图像特定部分的任务非常重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_To_Mask: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'channel': (['alpha', 'red', 'green', 'blue'],)}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'image_to_mask' + + def image_to_mask(self, images, channel): + mask_images = [] + for image in images: + image = tensor2pil(image).convert('RGBA') + (r, g, b, a) = image.split() + if channel == 'red': + channel_image = r + elif channel == 'green': + channel_image = g + elif channel == 'blue': + channel_image = b + elif channel == 'alpha': + channel_image = a + mask = torch.from_numpy(np.array(channel_image.convert('L')).astype(np.float32) / 255.0) + mask_images.append(mask) + return (torch.cat(mask_images, dim=0),) +``` \ No newline at end of file diff --git a/docs/Image to Noise.md b/docs/Image to Noise.md new file mode 100644 index 0000000..537376a --- /dev/null +++ b/docs/Image to Noise.md @@ -0,0 +1,100 @@ +# Documentation +- Class name: WAS_Image_To_Noise +- Category: WAS Suite/Image/Generate/Noise +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_To_Noise节点旨在将输入图像转换为噪声模式。它通过量化颜色、随机化像素数据,并可选择性地与高斯模糊混合,以实现一种嘈杂的美学效果。此节点作为生成基于噪声的图像的创意工具,可用于艺术表达或数据增强等多种应用。 + +# Input types +## Required +- images + - ‘images’参数至关重要,因为它定义了节点将处理成噪声模式的输入图像。这种转换对最终输出有显著影响,使得此参数对节点的执行和生成图像的质量至关重要。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image.Image] +## Optional +- num_colors + - ‘num_colors’参数决定了对图像进行量化的颜色数量,这影响了噪声模式的复杂性。它在节点的操作中起着重要作用,通过控制颜色深度和生成的视觉噪声效果。 + - Comfy dtype: INT + - Python dtype: int +- black_mix + - ‘black_mix’参数控制混合到图像中的黑色噪声量,为噪声模式增加了一层复杂性。它对于实现输出图像中所需噪声水平非常重要。 + - Comfy dtype: INT + - Python dtype: int +- gaussian_mix + - ‘gaussian_mix’参数指定要应用的高斯模糊程度,这可以平滑噪声并创建更微妙的噪声效果。它是微调噪声视觉外观的重要因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- brightness + - ‘brightness’参数调整噪声图像的亮度,可以增强或减少噪声模式的对比度。它是控制噪声效果整体外观的重要因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- output_mode + - ‘output_mode’参数决定输出的格式。选择‘batch’会将图像合并为单个张量,而‘list’会将它们保持为单独图像的列表。这影响结果如何为下游任务构建。 + - Comfy dtype: COMBO['batch', 'list'] + - Python dtype: Literal['batch', 'list'] +- seed + - ‘seed’参数用于初始化随机数生成器,确保噪声模式的可重复性。它对于在不同运行中生成一致的结果非常重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - ‘image’输出参数代表转换后的噪声图像。它是节点功能的主要结果,包含了从输入图像生成的噪声模式。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_To_Noise: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'num_colors': ('INT', {'default': 16, 'max': 256, 'min': 2, 'step': 2}), 'black_mix': ('INT', {'default': 0, 'max': 20, 'min': 0, 'step': 1}), 'gaussian_mix': ('FLOAT', {'default': 0.0, 'max': 1024, 'min': 0, 'step': 0.1}), 'brightness': ('FLOAT', {'default': 1.0, 'max': 2.0, 'min': 0.0, 'step': 0.01}), 'output_mode': (['batch', 'list'],), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + OUTPUT_IS_LIST = (False,) + FUNCTION = 'image_to_noise' + CATEGORY = 'WAS Suite/Image/Generate/Noise' + + def image_to_noise(self, images, num_colors, black_mix, gaussian_mix, brightness, output_mode, seed): + noise_images = [] + for image in images: + noise_images.append(pil2tensor(self.image2noise(tensor2pil(image), num_colors, black_mix, brightness, gaussian_mix, seed))) + if output_mode == 'list': + self.OUTPUT_IS_LIST = (True,) + else: + noise_images = torch.cat(noise_images, dim=0) + return (noise_images,) + + def image2noise(self, image, num_colors=16, black_mix=0, brightness=1.0, gaussian_mix=0, seed=0): + random.seed(int(seed)) + image = image.quantize(colors=num_colors) + image = image.convert('RGBA') + pixel_data = list(image.getdata()) + random.shuffle(pixel_data) + randomized_image = Image.new('RGBA', image.size) + randomized_image.putdata(pixel_data) + (width, height) = image.size + black_noise = Image.new('RGBA', (width, height), (0, 0, 0, 0)) + for _ in range(black_mix): + for x in range(width): + for y in range(height): + if random.randint(0, 1) == 1: + black_noise.putpixel((x, y), (0, 0, 0, 255)) + randomized_image = Image.alpha_composite(randomized_image, black_noise) + enhancer = ImageEnhance.Brightness(randomized_image) + randomized_image = enhancer.enhance(brightness) + if gaussian_mix > 0: + original_noise = randomized_image.copy() + randomized_gaussian = randomized_image.filter(ImageFilter.GaussianBlur(radius=gaussian_mix)) + randomized_image = Image.blend(randomized_image, randomized_gaussian, 0.65) + randomized_image = Image.blend(randomized_image, original_noise, 0.25) + return randomized_image +``` \ No newline at end of file diff --git a/docs/Image to Seed.md b/docs/Image to Seed.md new file mode 100644 index 0000000..130fa0d --- /dev/null +++ b/docs/Image to Seed.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: WAS_Image_To_Seed +- Category: WAS Suite/Image/Analyze +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +函数`image_to_seed`旨在将一系列图像转换成相应的种子集合。它利用每张图像的固有属性生成一个唯一标识符,这些标识符可以用于各种应用,如图像索引或检索系统。该节点在分析流程中扮演关键角色,使得视觉数据能够转换成既紧凑又能够代表原始内容的形式。 + +# Input types +## Required +- images + - 参数'images'对于节点的操作至关重要,因为它是节点处理的输入数据。每张图像通过一系列操作被转换成一个种子。输入图像的质量和特性直接影响生成的种子及其后续应用。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Output types +- seeds + - 输出'seeds'是代表从输入图像派生的种子的整数列表。每个种子都是图像内容的基于哈希的摘要,提供了简洁且独特的表示。这个输出很重要,因为它为下游任务中的进一步处理或分析奠定了基础。 + - Comfy dtype: INT + - Python dtype: List[int] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_To_Seed: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',)}} + RETURN_TYPES = ('INT',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'image_to_seed' + CATEGORY = 'WAS Suite/Image/Analyze' + + def image_to_seed(self, images): + seeds = [] + for image in images: + image = tensor2pil(image) + seeds.append(image2seed(image)) + return (seeds,) +``` \ No newline at end of file diff --git a/docs/ImageApplyLUT+.md b/docs/ImageApplyLUT+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ImageBatchSplitter %2F%2FInspire.md b/docs/ImageBatchSplitter %2F%2FInspire.md new file mode 100644 index 0000000..4eca66f --- /dev/null +++ b/docs/ImageBatchSplitter %2F%2FInspire.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: ImageBatchSplitter +- Category: InspirePack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +ImageBatchSplitter节点旨在通过根据用户定义的计数将图像批次拆分成更小的子集来高效管理和操作图像批次。它确保批处理大小与指定的计数对齐,即使图像的总数不能被分割计数完美整除。该节点在准备数据以进行进一步处理(需要统一的批处理大小)时发挥着至关重要的作用,并有助于机器学习或图像处理工作流中的整体数据管道管理。 + +# Input types +## Required +- images + - 'image'参数是ImageBatchSplitter节点的主要输入,代表需要处理的图像数据集合。该参数直接影响节点的操作和输出质量,因为节点根据'split_count'将这些图像操作和组织成子集。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image] +## Optional +- split_count + - ‘split_count’参数对于ImageBatchSplitter节点的功能至关重要。它决定了输入图像被划分为多少个期望的子集。该参数影响了输出的粒度,并且对于确保处理后的数据满足下游机器学习模型或图像处理任务的要求至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - ImageBatchSplitter节点的输出是一个包含处理后的图像的元组,根据'split_count'参数组织成子集。这个输出对于后续需要统一批处理大小的操作至关重要,促进了数据在流程中的顺畅流动。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageBatchSplitter: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'split_count': ('INT', {'default': 4, 'min': 0, 'max': 50, 'step': 1})}} + RETURN_TYPES = ByPassTypeTuple(('IMAGE',)) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Util' + + def doit(self, images, split_count): + cnt = min(split_count, len(images)) + res = [image.unsqueeze(0) for image in images[:cnt]] + if split_count >= len(images): + lack_cnt = split_count - cnt + 1 + empty_image = empty_pil_tensor() + for x in range(0, lack_cnt): + res.append(empty_image) + elif cnt < len(images): + remained_cnt = len(images) - cnt + remained_image = images[-remained_cnt:] + res.append(remained_image) + return tuple(res) +``` \ No newline at end of file diff --git a/docs/ImageBatchTestPattern.md b/docs/ImageBatchTestPattern.md new file mode 100644 index 0000000..b8b4108 --- /dev/null +++ b/docs/ImageBatchTestPattern.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: ImageBatchTestPattern +- Category: KJNodes/text +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +ImageBatchTestPattern 节点旨在生成一批带有文本模式的图像。它通过使用指定的字体和字号在黑色背景上绘制数字来创建图像。该节点特别适用于测试和可视化不同字体和大小如何影响图像中文本的外观。 + +# Input types +## Required +- batch_size + - batch_size 参数决定了要生成的图像数量。它对于控制输出数据的体积至关重要,并且与节点执行的计算负载直接相关。 + - Comfy dtype: INT + - Python dtype: int +- start_from + - start_from 参数设置了要在图像上绘制的数字序列的起始数字。它对于定义将在生成的模式中显示的数字范围具有重要意义。 + - Comfy dtype: INT + - Python dtype: int +- text_x + - text_x 参数指定了文本将在图像上绘制的 x 坐标。它是一个重要的参数,因为它决定了文本在图像中的水平位置。 + - Comfy dtype: INT + - Python dtype: int +- text_y + - text_y 参数指定了文本将在图像上绘制的 y 坐标。它控制文本的垂直位置,对于在图像内对齐文本至关重要。 + - Comfy dtype: INT + - Python dtype: int +- width + - width 参数定义了生成图像的宽度。它是一个关键参数,影响输出图像的整体尺寸,并与文本的纵横比和视觉呈现密切相关。 + - Comfy dtype: INT + - Python dtype: int +- height + - height 参数定义了生成图像的高度。它与 width 参数一起工作,以确定输出图像的整体大小和形状。 + - Comfy dtype: INT + - Python dtype: int +- font + - font 参数选择用于图像中文本的字体类型。它是一个关键参数,因为它显著影响图像中文本的风格和可读性。 + - Comfy dtype: STRING + - Python dtype: str +- font_size + - font_size 参数设置了图像中文本使用的字体大小。它是确定图像中文本的突出性和可见性的重要因素。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - IMAGE 输出包含一批具有指定文本模式的生成图像。每个图像是一个表示视觉数据的张量,可以用于进一步处理或可视化。 + - Comfy dtype: COMBO[torch.Tensor] + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageBatchTestPattern: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 255, 'step': 1}), 'start_from': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1}), 'text_x': ('INT', {'default': 256, 'min': 0, 'max': 4096, 'step': 1}), 'text_y': ('INT', {'default': 256, 'min': 0, 'max': 4096, 'step': 1}), 'width': ('INT', {'default': 512, 'min': 16, 'max': 4096, 'step': 1}), 'height': ('INT', {'default': 512, 'min': 16, 'max': 4096, 'step': 1}), 'font': (folder_paths.get_filename_list('kjnodes_fonts'),), 'font_size': ('INT', {'default': 255, 'min': 8, 'max': 4096, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'generatetestpattern' + CATEGORY = 'KJNodes/text' + + def generatetestpattern(self, batch_size, font, font_size, start_from, width, height, text_x, text_y): + out = [] + numbers = np.arange(start_from, start_from + batch_size) + font_path = folder_paths.get_full_path('kjnodes_fonts', font) + for number in numbers: + image = Image.new('RGB', (width, height), color='black') + draw = ImageDraw.Draw(image) + font_color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) + font = ImageFont.truetype(font_path, font_size) + text = str(number) + try: + draw.text((text_x, text_y), text, font=font, fill=font_color, features=['-liga']) + except: + draw.text((text_x, text_y), text, font=font, fill=font_color) + image_np = np.array(image).astype(np.float32) / 255.0 + image_tensor = torch.from_numpy(image_np).unsqueeze(0) + out.append(image_tensor) + out_tensor = torch.cat(out, dim=0) + return (out_tensor,) +``` \ No newline at end of file diff --git a/docs/ImageBorder.md b/docs/ImageBorder.md new file mode 100644 index 0000000..9465849 --- /dev/null +++ b/docs/ImageBorder.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: ImageBorder +- Category: Mikey/Image +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +ImageBorder节点旨在为图像添加装饰性边框,增强其视觉吸引力。它支持各种边框样式,如棋盘格、模糊或纯色,允许定制以适应不同的设计需求。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它是将应用边框的基础输入。它直接影响最终输出的外观。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- border_width + - border_width参数定义了要添加在图像周围的边框的厚度,这显著影响带边框图像的整体美学。 + - Comfy dtype: INT + - Python dtype: int +- border_color + - border_color参数允许用户指定边框的颜色,可以是纯色、棋盘格图案或模糊效果,以获得更精致的外观。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- image + - 输出图像包括带有新应用边框的原始图像,可供进一步处理或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageBorder: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'border_width': ('INT', {'default': 10, 'min': 0, 'max': 1000}), 'border_color': ('STRING', {'default': 'black'})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'border' + CATEGORY = 'Mikey/Image' + + def blur_border(self, image, border_width): + scale_factor = (image.width + border_width * 2) / image.width + border_image = image.resize((int(image.width * scale_factor), int(image.height * scale_factor))) + border_image = border_image.filter(ImageFilter.GaussianBlur(radius=border_width * 0.5)) + border_image.paste(image, (border_width, border_width)) + return pil2tensor(border_image)[None, :, :, :] + + @apply_to_batch + def border(self, image, border_width, border_color): + orig_image = tensor2pil(image) + (width, height) = orig_image.size + if border_color == 'checkerboard': + return checkerboard_border(image, border_width, 'black') + if border_color == 'blur': + return self.blur_border(orig_image, border_width) + if border_color.startswith('(') and border_color.endswith(')'): + border_color = border_color[1:-1] + border_color = tuple(map(int, border_color.split(','))) + border_image = Image.new('RGB', (width + border_width * 2, height + border_width * 2), border_color) + border_image.paste(orig_image, (border_width, border_width)) + return pil2tensor(border_image) +``` \ No newline at end of file diff --git a/docs/ImageCASharpening+.md b/docs/ImageCASharpening+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ImageColorTransfer.md b/docs/ImageColorTransfer.md new file mode 100644 index 0000000..0187dff --- /dev/null +++ b/docs/ImageColorTransfer.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: ImageColorTransfer +- Category: ♾️Mixlab/Image +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +ImageColorTransfer 节点旨在通过从一个图像传递调色板到另一个图像来重新上色图像。它通过利用颜色转移算法实现这一点,该算法操作源图像的颜色分布以匹配目标图像,从而产生视觉上连贯且风格化变换的输出。 + +# Input types +## Required +- source + - source 参数是要被替换颜色的图像。它在颜色转移过程中起着关键作用,因为它决定了将要被改变的原始颜色调色板。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- target + - target 参数代表其颜色调色板将应用于源图像的图像。它对于定义输出图像应反映的所需颜色方案至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- result + - result 参数是经过颜色转移的输出图像。它标志着节点操作的最终产品,展示了具有从目标图像适应颜色的源图像。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageColorTransfer: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'source': ('IMAGE',), 'target': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Image' + INPUT_IS_LIST = True + OUTPUT_IS_LIST = (True,) + + def run(self, source, target): + res = [] + target = target[0][0] + print(target.shape) + target = tensor2pil(target) + for ims in source: + for im in ims: + image = tensor2pil(im) + image = color_transfer(image, target) + image = pil2tensor(image) + res.append(image) + return (res,) +``` \ No newline at end of file diff --git a/docs/ImageCompositeFromMaskBatch+.md b/docs/ImageCompositeFromMaskBatch+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ImageCrop+.md b/docs/ImageCrop+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ImageCropByAlpha.md b/docs/ImageCropByAlpha.md new file mode 100644 index 0000000..4000fb8 --- /dev/null +++ b/docs/ImageCropByAlpha.md @@ -0,0 +1,101 @@ +# Documentation +- Class name: ImageCropByAlpha +- Category: ♾️Mixlab/Image +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +ImageCropByAlpha 节点旨在基于图像的 alpha 通道智能裁剪图像,有效地隔离图像的不透明区域。它通过提供一种精确和自动化的内容提取方法,增强了图像处理工作流程,特别适用于涉及复杂图像组合或需要清晰分离图像元素的应用程序。 + +# Input types +## Required +- image + - 'image' 参数是节点的主要输入,代表将要处理的原始图像。它的重要性在于它是根据 alpha 通道裁剪的来源。节点的执行和生成的图像严重依赖于这个输入图像的内容和质量。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- RGBA + - 'RGBA' 参数是一个必要的输入,它提供了裁剪过程中必需的 alpha 通道信息。这个参数直接影响节点如何识别和隔离图像的非透明区域,因此在确定最终裁剪图像中起着关键作用。 + - Comfy dtype: RGBA + - Python dtype: torch.Tensor + +# Output types +- IMAGE + - 'IMAGE' 输出是裁剪操作的结果,为用户提供了基于 alpha 通道隔离的图像内容。它很重要,因为它代表了节点功能的主要内容,展示了图像处理任务的有效性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- MASK + - 'MASK' 输出是对应于原始图像非透明区域的二进制掩码,作为裁剪操作的视觉指南。它对于需要精确空间信息的应用程序来说很重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- AREA_MASK + - 'AREA_MASK' 输出是一个掩码,它描绘了被识别为非透明的图像区域。这对于可能需要了解图像内特定区域的进一步图像分析或处理步骤非常有用。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- x + - 'x' 输出提供了裁剪区域左上角的 x 坐标,这对于理解裁剪内容在原始图像中的空间位置至关重要。 + - Comfy dtype: INT + - Python dtype: int +- y + - 'y' 输出提供了裁剪区域左上角的 y 坐标,进一步定义了裁剪内容的空间位置。 + - Comfy dtype: INT + - Python dtype: int +- width + - 'width' 输出表示裁剪区域的宽度,这是了解隔离图像内容尺寸的关键测量。 + - Comfy dtype: INT + - Python dtype: int +- height + - 'height' 输出表示裁剪区域的高度,与宽度相辅相成,完整描述了提取的图像段的大小。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageCropByAlpha: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'RGBA': ('RGBA',)}} + RETURN_TYPES = ('IMAGE', 'MASK', 'MASK', 'INT', 'INT', 'INT', 'INT') + RETURN_NAMES = ('IMAGE', 'MASK', 'AREA_MASK', 'x', 'y', 'width', 'height') + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Image' + INPUT_IS_LIST = True + OUTPUT_IS_LIST = (True, True, True, True, True, True, True) + + def run(self, image, RGBA): + image = image[0] + RGBA = RGBA[0] + bf_im = tensor2pil(image) + im = tensor2pil(RGBA) + im = im.convert('RGBA') + (red, green, blue, alpha) = im.split() + im = naive_cutout(bf_im, alpha) + (x, y, w, h) = get_not_transparent_area(im) + x = min(x, image.shape[2] - 1) + y = min(y, image.shape[1] - 1) + to_x = w + x + to_y = h + y + x_1 = x + y_1 = y + width_1 = w + height_1 = h + img = image[:, y:to_y, x:to_x, :] + ori = RGBA[:, y:to_y, x:to_x, :] + ori = tensor2pil(ori) + new_image = Image.new('RGBA', ori.size) + pixel_data = ori.load() + new_pixel_data = new_image.load() + for y in range(ori.size[1]): + for x in range(ori.size[0]): + (r, g, b, a) = pixel_data[x, y] + if a != 0: + new_pixel_data[x, y] = (255, 255, 255, 255) + else: + new_pixel_data[x, y] = (0, 0, 0, 0) + ori = new_image.convert('L') + ori = pil2tensor(ori) + b_image = AreaToMask_run(RGBA) + return ([img], [ori], [b_image], [x_1], [y_1], [width_1], [height_1]) +``` \ No newline at end of file diff --git a/docs/ImageCropWithBBox(FaceParsing).md b/docs/ImageCropWithBBox(FaceParsing).md new file mode 100644 index 0000000..b2fa539 --- /dev/null +++ b/docs/ImageCropWithBBox(FaceParsing).md @@ -0,0 +1,60 @@ +# Documentation +- Class name: ImageCropWithBBox +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +ImageCropWithBBox 节点旨在根据边界框坐标处理图像,通过裁剪出感兴趣的区域。它在将计算资源集中在图像的特定区域,从而提高后续图像分析任务的效率方面发挥着关键作用。 + +# Input types +## Required +- bbox + - ‘bbox’参数至关重要,因为它定义了图像中要被裁剪的区域。它通过指定裁剪过程的坐标,直接影响节点的操作。 + - Comfy dtype: Tensor + - Python dtype: torch.Tensor +- image + - ‘image’参数是ImageCropWithBBox节点的基本输入,因为它代表了将要处理的原始图像数据。图像数据的质量和格式对于裁剪操作的准确性至关重要。 + - Comfy dtype: Tensor + - Python dtype: torch.Tensor + +# Output types +- cropped_image + - ‘cropped_image’输出包含裁剪操作的结果。它很重要,因为它呈现了由‘bbox’参数指定的原始图像的区域,可供进一步分析或处理。 + - Comfy dtype: Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageCropWithBBox: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'bbox': ('BBOX', {}), 'image': ('IMAGE', {})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, bbox: Tensor, image: Tensor): + results = [] + image_permuted = image.permute(0, 3, 1, 2) + for image_item in image_permuted: + bbox_int = bbox.int() + l = bbox_int[0] + t = bbox_int[1] + r = bbox_int[2] + b = bbox_int[3] + cropped_image = functional.crop(image_item, t, l, b - t, r - l) + result = cropped_image.permute(1, 2, 0).unsqueeze(0) + results.append(result) + try: + final = torch.cat(results, dim=0) + except: + final = results + return (final,) +``` \ No newline at end of file diff --git a/docs/ImageDesaturate+.md b/docs/ImageDesaturate+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ImageEnhanceDifference+.md b/docs/ImageEnhanceDifference+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ImageExpandBatch+.md b/docs/ImageExpandBatch+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ImageFlip+.md b/docs/ImageFlip+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ImageFromBatch+.md b/docs/ImageFromBatch+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ImageInsertWithBBox(FaceParsing).md b/docs/ImageInsertWithBBox(FaceParsing).md new file mode 100644 index 0000000..0223426 --- /dev/null +++ b/docs/ImageInsertWithBBox(FaceParsing).md @@ -0,0 +1,63 @@ +# Documentation +- Class name: ImageInsertWithBBox +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +该节点旨在将一张图片插入到另一张图片的指定边界框位置,这对于人脸解析和对象跟踪等应用至关重要。它处理了调整大小、填充和掩蔽的过程,以确保源图像无缝插入目标图像,有助于对视觉内容的整体理解和分析。 + +# Input types +## Required +- bbox + - 边界框参数对于定义图像插入的区域至关重要。它直接影响图像在目标中的裁剪和放置,确保精确的定位和集成。 + - Comfy dtype: BBOX + - Python dtype: torch.Tensor +- image_src + - 源图像是将插入目标图像的主要视觉内容。其质量和尺寸对最终输出至关重要,因为它决定了插入图像如何与背景融合。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image + - 图像参数代表源图像将被插入的目标图像。该图像的特性,如分辨率和色彩空间,对整体处理和最终结果很重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- result + - 输出是源图像插入指定边界框后的最终图像。它代表了两个视觉元素的成功集成,这对于进一步的分析和可视化任务至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ImageInsertWithBBox: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'bbox': ('BBOX', {}), 'image_src': ('IMAGE', {}), 'image': ('IMAGE', {})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, bbox: Tensor, image_src: Tensor, image: Tensor): + bbox_int = bbox.int() + l = bbox_int[0] + t = bbox_int[1] + r = bbox_int[2] + b = bbox_int[3] + image_permuted = image.permute(0, 3, 1, 2) + resized = functional.resize(image_permuted, [b - t, r - l]) + (_, h, w, c) = image_src.shape + padded = functional.pad(resized, [l, t, w - r, h - b]) + src_permuted = image_src.permute(0, 3, 1, 2) + mask = torch.zeros(src_permuted.shape) + mask[:, :, t:b, l:r] = 1 + result = torch.where(mask == 0, src_permuted, padded) + final = result.permute(0, 2, 3, 1) + return (final,) +``` \ No newline at end of file diff --git a/docs/ImageListSelect(FaceParsing).md b/docs/ImageListSelect(FaceParsing).md new file mode 100644 index 0000000..d275dba --- /dev/null +++ b/docs/ImageListSelect(FaceParsing).md @@ -0,0 +1,50 @@ +# Documentation +- Class name: ImageListSelect +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +ImageListSelect节点可以根据提供的索引从图像列表中选择特定的图像,使得能够对批量中的单个图像进行集中分析或处理。 + +# Input types +## Required +- images + - images参数至关重要,它作为节点操作的输入数据集。它允许节点根据提供的索引识别和选择目标图像。 + - Comfy dtype: IMAGE + - Python dtype: List[Image] +- index + - index参数决定了从列表中选择哪一张图像。它在指导节点进行正确的选择以进行进一步处理方面至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- selected_image + - selected_image代表节点的输出,即根据提供的索引从输入列表中选择的图像。它是节点操作的结果,并准备好进行后续处理。 + - Comfy dtype: IMAGE + - Python dtype: Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageListSelect: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE', {}), 'index': ('INT', {'default': 0, 'min': 0, 'step': 1})}} + INPUT_IS_LIST = True + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, images, index): + index = index[0] + if images is Tensor: + return (images[index].unsqueeze(0),) + else: + return (images[index],) +``` \ No newline at end of file diff --git a/docs/ImageListToBatch+.md b/docs/ImageListToBatch+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ImageListToImageBatch.md b/docs/ImageListToImageBatch.md new file mode 100644 index 0000000..26a2ee5 --- /dev/null +++ b/docs/ImageListToImageBatch.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: ImageListToImageBatch +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +该节点旨在将图像列表高效地转换为单个图像批次。它通过在第一维度上连接图像来实现这一点,确保批次中的所有图像具有相同的形状。节点在准备图像数据以进行进一步处理(如基于批次的神经网络操作)中发挥着关键作用。 + +# Input types +## Required +- images + - 'image' 参数是节点将处理的图像张量列表。它对节点的操作至关重要,因为它直接影响图像批次的创建。该参数确保所有图像都兼容,可以连接成单个批次。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Output types +- image_batch + - 该节点的输出是一个表示图像批次的单个图像张量。这个批次是通过在第一维度上连接输入图像创建的,使其适合需要批量图像数据的下游任务。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ImageListToImageBatch: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',)}} + INPUT_IS_LIST = True + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, images): + if len(images) <= 1: + return (images,) + else: + image1 = images[0] + for image2 in images[1:]: + if image1.shape[1:] != image2.shape[1:]: + image2 = comfy.utils.common_upscale(image2.movedim(-1, 1), image1.shape[2], image1.shape[1], 'lanczos', 'center').movedim(1, -1) + image1 = torch.cat((image1, image2), dim=0) + return (image1,) +``` \ No newline at end of file diff --git a/docs/ImageMaskSwitch.md b/docs/ImageMaskSwitch.md new file mode 100644 index 0000000..99c28f8 --- /dev/null +++ b/docs/ImageMaskSwitch.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: ImageMaskSwitch +- Category: ImpactPack/Util +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImageMaskSwitch节点旨在根据选择参数选择性地路由图像和掩码输入。它便于在进一步处理或分析中选择多个图像-掩码对,确保只有所需的对被传递到工作流程中。 + +# Input types +## Required +- select + - 'select'参数决定将使用哪组图像-掩码对。它至关重要,因为它根据其整数值直接通过选择适当的对来影响节点的输出。 + - Comfy dtype: INT + - Python dtype: int +- images1 + - 'images1'参数表示要考虑用于开关操作的第一组图像。当'select'设置为1时,它在节点的功能中扮演重要角色,因为它将变成输出的图像集。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +## Optional +- mask1_opt + - 'mask1_opt'参数是对应于'images1'的可选掩码。当'select'为1并且希望在输出中包含图像的掩码时,它变得相关。 + - Comfy dtype: MASK + - Python dtype: PIL.Image or torch.Tensor +- images2_opt + - 'images2_opt'参数表示开关操作的第二组可选图像。当'select'设置为2并且需要替代图像集作为输出时使用。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +- mask2_opt + - 'mask2_opt'参数是对应于'images2_opt'的可选掩码。当'select'为2并且输出需要与图像一起的掩码时,会考虑它。 + - Comfy dtype: MASK + - Python dtype: PIL.Image or torch.Tensor +- images3_opt + - 'images3_opt'参数表示开关操作的第三组可选图像。当'select'设置为3并且需要第三组图像作为输出时使用。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +- mask3_opt + - 'mask3_opt'参数是对应于'images3_opt'的可选掩码。当'select'为3并且输出需要与图像一起的掩码时,会使用它。 + - Comfy dtype: MASK + - Python dtype: PIL.Image or torch.Tensor +- images4_opt + - 'images4_opt'参数表示开关操作的第四组可选图像。当'select'设置为4并且需要第四组图像作为输出时使用。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +- mask4_opt + - 'mask4_opt'参数是对应于'images4_opt'的可选掩码。当'select'为4并且希望在输出中包含图像的掩码时,会考虑它。 + - Comfy dtype: MASK + - Python dtype: PIL.Image or torch.Tensor + +# Output types +- IMAGE + - 输出'IMAGE'代表基于'select'输入参数选择的图像集。它是节点功能的关键元素,因为它决定了系统内视觉数据的流向。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +- MASK + - 输出'MASK'对应于所选图像集的掩码。当需要与图像一起进行分析或处理时,它很重要。 + - Comfy dtype: MASK + - Python dtype: PIL.Image or torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageMaskSwitch: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'select': ('INT', {'default': 1, 'min': 1, 'max': 4, 'step': 1}), 'images1': ('IMAGE',)}, 'optional': {'mask1_opt': ('MASK',), 'images2_opt': ('IMAGE',), 'mask2_opt': ('MASK',), 'images3_opt': ('IMAGE',), 'mask3_opt': ('MASK',), 'images4_opt': ('IMAGE',), 'mask4_opt': ('MASK',)}} + RETURN_TYPES = ('IMAGE', 'MASK') + OUTPUT_NODE = True + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, select, images1, mask1_opt=None, images2_opt=None, mask2_opt=None, images3_opt=None, mask3_opt=None, images4_opt=None, mask4_opt=None): + if select == 1: + return (images1, mask1_opt) + elif select == 2: + return (images2_opt, mask2_opt) + elif select == 3: + return (images3_opt, mask3_opt) + else: + return (images4_opt, mask4_opt) +``` \ No newline at end of file diff --git a/docs/ImageOverlay.md b/docs/ImageOverlay.md new file mode 100644 index 0000000..48e1ff5 --- /dev/null +++ b/docs/ImageOverlay.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: ImageOverlay +- Category: Mikey/Image +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +ImageOverlay节点类根据指定的不透明度水平,将前景图像无缝集成到背景图像上,创建一个合成图像,结合了两个来源的视觉元素。 + +# Input types +## Required +- background_image + - 背景图像作为应用叠加的基础画布。它对于建立最终合成图像的上下文和尺寸至关重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- foreground_image + - 前景图像是要叠加到背景上的元素。其视觉特征和位置对于在合成图像中实现期望效果至关重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- opacity + - 不透明度决定了前景图像与背景图像融合的程度。这是一个关键参数,影响合成图像的整体外观和透明度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- result_img + - result_img代表最终的合成图像,其中前景图像已根据指定的不透明度叠加到背景图像上。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageOverlay: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'background_image': ('IMAGE', {'default': None}), 'foreground_image': ('IMAGE', {'default': None}), 'opacity': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('result_img',) + FUNCTION = 'overlay' + CATEGORY = 'Mikey/Image' + + def overlay(self, background_image, foreground_image, opacity): + background_image = tensor2pil(background_image) + foreground_image = tensor2pil(foreground_image) + background_image = background_image.convert('RGB') + foreground_image = foreground_image.convert('RGB') + cropped_fg = Image.new('RGB', (background_image.size[0], background_image.size[1])) + cropped_fg.paste(foreground_image, (int((background_image.size[0] - foreground_image.size[0]) / 2), int((background_image.size[1] - foreground_image.size[1]) / 2))) + bg_array = np.array(background_image, dtype=np.float32) / 255 + fg_array = np.array(cropped_fg, dtype=np.float32) / 255 + mask = bg_array < 0.5 + overlay = np.zeros_like(bg_array) + overlay[mask] = 2 * bg_array[mask] * fg_array[mask] + overlay[~mask] = 1 - 2 * (1 - bg_array[~mask]) * (1 - fg_array[~mask]) + result = (1 - opacity) * bg_array + opacity * overlay + result_img = Image.fromarray((result * 255).astype(np.uint8)) + result_img = pil2tensor(result_img) + return (result_img,) +``` \ No newline at end of file diff --git a/docs/ImagePadForOutpaintMasked.md b/docs/ImagePadForOutpaintMasked.md new file mode 100644 index 0000000..01bf164 --- /dev/null +++ b/docs/ImagePadForOutpaintMasked.md @@ -0,0 +1,96 @@ +# Documentation +- Class name: ImagePadForOutpaintMasked +- Category: image +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +ImagePadForOutpaintMasked节点旨在扩展图像的边界,这一过程称为外延。它通过添加额外的像素来实现这一点,这些像素被智能计算以与原始内容无缝融合。该节点的功能在图像边缘之外的上下文很重要的场景中特别有用,例如在图像编辑或数据增强任务中。 + +# Input types +## Required +- image + - 图像参数是节点的主要输入,表示将被扩展的图像。它对节点的操作至关重要,因为整个过程都围绕着为此图像添加填充。最终输出的质量严重依赖于原始图像的内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- left + - left参数指定在图像左侧填充的像素数。它在确定扩展图像的最终尺寸和外延区域的整体外观中起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- top + - top参数决定在图像顶部填充的像素数。它是控制垂直填充的重要输入,直接影响结果图像的高度。 + - Comfy dtype: INT + - Python dtype: int +- right + - right参数设置在图像右侧填充的像素数。它对于实现扩展图像的所需宽度至关重要,并影响外延区域的视觉连贯性。 + - Comfy dtype: INT + - Python dtype: int +- bottom + - bottom参数确定在图像底部填充的像素数。它是建立扩展图像最终高度的关键因素,并影响填充区域的整体外观。 + - Comfy dtype: INT + - Python dtype: int +- feathering + - feathering参数控制原始图像与填充区域之间过渡的平滑度。它对于创建自然和无缝的混合特别重要,增强了外延图像的视觉效果。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- mask + - mask参数是可选输入,用于定义图像的遮罩。它用于指定在图像外延过程中应保留的图像区域,确保这些区域保持不变。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- new_image + - new_image输出参数代表带有添加填充的扩展图像。它是节点操作的主要结果,包含原始图像与新填充区域的无缝集成。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- new_mask + - new_mask输出参数是对应于扩展图像的更新后的遮罩。它在保持外延过程中特定区域的完整性方面很重要,并且在需要进一步图像操作时特别有用。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImagePadForOutpaintMasked: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'left': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION, 'step': 8}), 'top': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION, 'step': 8}), 'right': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION, 'step': 8}), 'bottom': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION, 'step': 8}), 'feathering': ('INT', {'default': 40, 'min': 0, 'max': MAX_RESOLUTION, 'step': 1})}, 'optional': {'mask': ('MASK',)}} + RETURN_TYPES = ('IMAGE', 'MASK') + FUNCTION = 'expand_image' + CATEGORY = 'image' + + def expand_image(self, image, left, top, right, bottom, feathering, mask=None): + (B, H, W, C) = image.size() + new_image = torch.ones((B, H + top + bottom, W + left + right, C), dtype=torch.float32) * 0.5 + new_image[:, top:top + H, left:left + W, :] = image + if mask is None: + new_mask = torch.ones((H + top + bottom, W + left + right), dtype=torch.float32) + t = torch.zeros((H, W), dtype=torch.float32) + else: + mask = F.pad(mask, (left, right, top, bottom), mode='constant', value=0) + mask = 1 - mask + t = torch.zeros_like(mask) + if feathering > 0 and feathering * 2 < H and (feathering * 2 < W): + for i in range(H): + for j in range(W): + dt = i if top != 0 else H + db = H - i if bottom != 0 else H + dl = j if left != 0 else W + dr = W - j if right != 0 else W + d = min(dt, db, dl, dr) + if d >= feathering: + continue + v = (feathering - d) / feathering + if mask is None: + t[i, j] = v * v + else: + t[:, top + i, left + j] = v * v + if mask is None: + mask = new_mask.squeeze(0) + mask[top:top + H, left:left + W] = t + mask = mask.unsqueeze(0) + return (new_image, mask) +``` \ No newline at end of file diff --git a/docs/ImagePadWithBBox(FaceParsing).md b/docs/ImagePadWithBBox(FaceParsing).md new file mode 100644 index 0000000..0944bf4 --- /dev/null +++ b/docs/ImagePadWithBBox(FaceParsing).md @@ -0,0 +1,61 @@ +# Documentation +- Class name: ImagePadWithBBox +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +该节点便于对带有边界框的图像进行精确填充,确保图像适当地被框架化并为进一步分析或处理做好准备。 + +# Input types +## Required +- bbox + - 边界框参数对于确定图像中的兴趣区域至关重要。它决定了图像将从哪些坐标处被裁剪并相应地进行填充。 + - Comfy dtype: BBOX + - Python dtype: torch.Tensor +- width + - 宽度参数指定了填充后输出图像的期望宽度,影响最终产品的总体尺寸和长宽比。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数定义了填充后输出图像的期望高度,这直接影响图像的最终展示和布局。 + - Comfy dtype: INT + - Python dtype: int +- image + - 图像参数是主要的输入,节点基于提供的边界框和尺寸对这一输入进行操作,执行填充。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- output_image + - 输出图像是填充过程的结果,展示了一个适当框架和尺寸的图像,准备好进行后续的处理阶段。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImagePadWithBBox: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'bbox': ('BBOX', {}), 'width': ('INT', {}), 'height': ('INT', {}), 'image': ('IMAGE', {})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, bbox: Tensor, width: int, height: int, image: Tensor): + image_permuted = image.permute(0, 3, 1, 2) + bbox_int = bbox.int() + l = bbox_int[0] + t = bbox_int[1] + r = bbox_int[2] + b = bbox_int[3] + cropped_image = functional.pad(image_permuted, [l, t, width - r, height - b]) + final = cropped_image.permute(0, 2, 3, 1) + return (final,) +``` \ No newline at end of file diff --git a/docs/ImagePaste.md b/docs/ImagePaste.md new file mode 100644 index 0000000..4ab650c --- /dev/null +++ b/docs/ImagePaste.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: ImagePaste +- Category: Mikey/Image +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +ImagePaste节点旨在将前景图像无缝集成到背景图像上的指定位置。它通过将图像的张量表示转换为PIL图像,操作alpha通道以实现透明度,并在确切坐标处将前景粘贴到背景上,从而实现此目的。该节点对于需要精确控制图像放置的图像合成任务至关重要。 + +# Input types +## Required +- background_image + - 背景图像是前景将被粘贴的地方。它作为合成的画布,对输出图像的最终外观至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- foreground_image + - 将放置在背景图像上的图像。它很重要,因为它定义了最终图像中在视觉上突出的主题或元素。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- x_position + - 在背景上,前景图像左上角将被放置的水平位置。它很重要,因为它决定了图像在组合中的具体放置位置。 + - Comfy dtype: INT + - Python dtype: int +- y_position + - 在背景上,前景图像左上角将被放置的垂直位置。它与x_position一起工作,以设定粘贴图像的精确位置。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 在指定位置将前景粘贴到背景上后得到的图像结果。它代表了最终的组合,是节点的主要输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImagePaste: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'background_image': ('IMAGE',), 'foreground_image': ('IMAGE',), 'x_position': ('INT', {'default': 0, 'min': -10000, 'max': 10000}), 'y_position': ('INT', {'default': 0, 'min': -10000, 'max': 10000})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'paste' + CATEGORY = 'Mikey/Image' + + def tensor2pil(self, image): + image_np = np.clip(255.0 * image.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + if image_np.shape[0] == 4: + return Image.fromarray(image_np.transpose(1, 2, 0), 'RGBA') + else: + return Image.fromarray(image_np.transpose(1, 2, 0), 'RGB') + + def paste(self, background_image, foreground_image, x_position, y_position): + background_image = tensor2pil(background_image) + foreground_image = tensor2pil(foreground_image) + if foreground_image.mode != 'RGBA': + foreground_image = foreground_image.convert('RGBA') + (r, g, b, alpha) = foreground_image.split() + background_image.paste(foreground_image, (x_position, y_position), mask=alpha) + return (pil2tensor(background_image),) +``` \ No newline at end of file diff --git a/docs/ImagePosterize+.md b/docs/ImagePosterize+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ImageReceiver.md b/docs/ImageReceiver.md new file mode 100644 index 0000000..34169e1 --- /dev/null +++ b/docs/ImageReceiver.md @@ -0,0 +1,95 @@ +# Documentation +- Class name: ImageReceiver +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImageReceiver节点旨在处理和接收图像数据,提供解码、转换和准备图像数据的功能,以便在工作流中进行进一步分析或处理。它强调处理不同图像格式,并确保将图像数据正确转换为适合下游任务的格式。 + +# Input types +## Required +- image + - 'image'参数对于节点至关重要,因为它指定了图像数据的来源。它可以是文件路径或对存储在其他地方的图像的引用。此参数直接影响节点检索和处理图像的能力。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- link_id + - 'link_id'参数用作将图像数据与工作流中的其他元素链接或关联的标识符。其值可以从0到最大整数值,提供了在如何链接或引用图像方面的灵活性。 + - Comfy dtype: INT + - Python dtype: int +- save_to_workflow + - 'save_to_workflow'参数决定了是否应将图像数据保存为工作流的一部分以供将来使用。这对于跨工作流的不同阶段持久化数据而无需重新处理非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- image_data + - 'image_data'参数包含编码后的图像数据,节点将对其进行解码和处理。它应该是表示base64编码图像内容的字符串,然后将其转换为可用的图像格式。 + - Comfy dtype: STRING + - Python dtype: str +- trigger_always + - 'trigger_always'参数是一个布尔标志,当设置为true时,表示节点应无条件地处理图像。这可以用来确保图像总是被处理,即使其他参数表明它可能不需要被处理。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- IMAGE + - 'IMAGE'输出提供了以张量格式处理的图像数据,适用于工作流中的进一步分析或处理。它代表了ImageReceiver节点在图像数据成功解码和转换后的主要输出。 + - Comfy dtype: TENSOR + - Python dtype: torch.Tensor +- MASK + - 'MASK'输出是一个可选的张量,代表从图像数据派生的掩码。它可以用于分割或识别图像中感兴趣的特定区域的任务。 + - Comfy dtype: TENSOR + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageReceiver: + + @classmethod + def INPUT_TYPES(s): + input_dir = folder_paths.get_input_directory() + files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))] + return {'required': {'image': (sorted(files),), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'save_to_workflow': ('BOOLEAN', {'default': False}), 'image_data': ('STRING', {'multiline': False}), 'trigger_always': ('BOOLEAN', {'default': False, 'label_on': 'enable', 'label_off': 'disable'})}} + FUNCTION = 'doit' + RETURN_TYPES = ('IMAGE', 'MASK') + CATEGORY = 'ImpactPack/Util' + + def doit(self, image, link_id, save_to_workflow, image_data, trigger_always): + if save_to_workflow: + try: + image_data = base64.b64decode(image_data.split(',')[1]) + i = Image.open(BytesIO(image_data)) + i = ImageOps.exif_transpose(i) + image = i.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + if 'A' in i.getbands(): + mask = np.array(i.getchannel('A')).astype(np.float32) / 255.0 + mask = 1.0 - torch.from_numpy(mask) + else: + mask = torch.zeros((64, 64), dtype=torch.float32, device='cpu') + return (image, mask.unsqueeze(0)) + except Exception as e: + print(f"[WARN] ComfyUI-Impact-Pack: ImageReceiver - invalid 'image_data'") + mask = torch.zeros((64, 64), dtype=torch.float32, device='cpu') + return (empty_pil_tensor(64, 64), mask) + else: + return nodes.LoadImage().load_image(image) + + @classmethod + def VALIDATE_INPUTS(s, image, link_id, save_to_workflow, image_data, trigger_always): + if image != '#DATA' and (not folder_paths.exists_annotated_filepath(image)) or image.startswith('/') or '..' in image: + return 'Invalid image file: {}'.format(image) + return True + + @classmethod + def IS_CHANGED(s, image, link_id, save_to_workflow, image_data, trigger_always): + if trigger_always: + return float('NaN') + elif save_to_workflow: + return hash(image_data) + else: + return hash(image) +``` \ No newline at end of file diff --git a/docs/ImageRemoveBackground+.md b/docs/ImageRemoveBackground+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ImageResize+.md b/docs/ImageResize+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ImageResize.md b/docs/ImageResize.md new file mode 100644 index 0000000..f205896 --- /dev/null +++ b/docs/ImageResize.md @@ -0,0 +1,186 @@ +# Documentation +- Class name: ImageResize +- Category: image +- Output node: False +- Repo Ref: https://github.com/palant/image-resize-comfyui + +ImageResize节点旨在根据指定的标准调整图像尺寸,确保输出图像满足所需的大小和宽高比要求。它提供多种调整大小的操作,如裁剪、填充和缩放,并通过调整图像的分辨率适应不同的用例。 + +# Input types +## Required +- pixels + - 输入的图像数据,将由节点进行调整大小或处理。它是节点操作的关键,因为它作为所有转换操作的基础。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- action + - 确定要在输入图像上执行的调整大小操作类型。此参数至关重要,因为它规定了图像被修改的方法,以满足所需的输出规格。 + - Comfy dtype: COMBO[ACTION_TYPE_RESIZE, ACTION_TYPE_CROP, ACTION_TYPE_PAD] + - Python dtype: str +## Optional +- smaller_side + - 指定调整大小后图像的较短边长度。它在控制输出图像的尺寸方面起着重要作用,特别是在缩小或放大输入图像时。 + - Comfy dtype: INT + - Python dtype: int +- larger_side + - 定义调整大小后图像的较长边长度。当使用此参数时,它与'smaller_side'一起工作,以确定调整大小后图像的最终尺寸。 + - Comfy dtype: INT + - Python dtype: int +- scale_factor + - 对输入图像应用一个统一的缩放因子,这对于在不改变其宽高比的情况下均匀增加或减少图像大小非常重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- resize_mode + - 控制调整大小操作的方向,是缩小、放大还是根据'scale_factor'进行非均匀调整大小。此参数在管理节点的缩放行为方面至关重要。 + - Comfy dtype: COMBO[RESIZE_MODE_DOWNSCALE, RESIZE_MODE_UPSCALE, RESIZE_MODE_ANY] + - Python dtype: str +- side_ratio + - 设置输出图像的期望宽高比。此参数非常重要,因为它确保图像保持特定的形状,这对于与各种显示或处理要求的兼容性至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- crop_pad_position + - 影响图像中裁剪或填充的位置,这对于微调视觉输出以满足特定的美学或功能需求至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- pad_feathering + - 调整应用于填充的羽化效果,这对于在图像的原始区域和填充区域之间创建平滑过渡,提高整体视觉质量非常重要。 + - Comfy dtype: INT + - Python dtype: int +- mask_optional + - 一个可选的掩码,可以应用于图像以控制哪些部分的图像被处理。这对于需要选择性图像操作的场景非常重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- pixels + - 经过调整大小操作处理后的图像。这是节点的主要输出,代表了图像处理过程的最终结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 与处理后的图像对应的可选输出掩码,可以根据掩蔽区域应用进一步的操作或效果。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageResize: + + def __init__(self): + pass + ACTION_TYPE_RESIZE = 'resize only' + ACTION_TYPE_CROP = 'crop to ratio' + ACTION_TYPE_PAD = 'pad to ratio' + RESIZE_MODE_DOWNSCALE = 'reduce size only' + RESIZE_MODE_UPSCALE = 'increase size only' + RESIZE_MODE_ANY = 'any' + RETURN_TYPES = ('IMAGE', 'MASK') + FUNCTION = 'resize' + CATEGORY = 'image' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pixels': ('IMAGE',), 'action': ([s.ACTION_TYPE_RESIZE, s.ACTION_TYPE_CROP, s.ACTION_TYPE_PAD],), 'smaller_side': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 8}), 'larger_side': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 8}), 'scale_factor': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 10.0, 'step': 0.1}), 'resize_mode': ([s.RESIZE_MODE_DOWNSCALE, s.RESIZE_MODE_UPSCALE, s.RESIZE_MODE_ANY],), 'side_ratio': ('STRING', {'default': '4:3'}), 'crop_pad_position': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'pad_feathering': ('INT', {'default': 20, 'min': 0, 'max': 8192, 'step': 1})}, 'optional': {'mask_optional': ('MASK',)}} + + @classmethod + def VALIDATE_INPUTS(s, action, smaller_side, larger_side, scale_factor, resize_mode, side_ratio, **_): + if side_ratio is not None: + if action != s.ACTION_TYPE_RESIZE and s.parse_side_ratio(side_ratio) is None: + return f'Invalid side ratio: {side_ratio}' + if smaller_side is not None and larger_side is not None and (scale_factor is not None): + if int(smaller_side > 0) + int(larger_side > 0) + int(scale_factor > 0) > 1: + return f'At most one scaling rule (smaller_side, larger_side, scale_factor) should be enabled by setting a non-zero value' + if scale_factor is not None: + if resize_mode == s.RESIZE_MODE_DOWNSCALE and scale_factor > 1.0: + return f'For resize_mode {s.RESIZE_MODE_DOWNSCALE}, scale_factor should be less than one but got {scale_factor}' + if resize_mode == s.RESIZE_MODE_UPSCALE and scale_factor > 0.0 and (scale_factor < 1.0): + return f'For resize_mode {s.RESIZE_MODE_UPSCALE}, scale_factor should be larger than one but got {scale_factor}' + return True + + @classmethod + def parse_side_ratio(s, side_ratio): + try: + (x, y) = map(int, side_ratio.split(':', 1)) + if x < 1 or y < 1: + raise Exception('Ratio factors have to be positive numbers') + return float(x) / float(y) + except: + return None + + def resize(self, pixels, action, smaller_side, larger_side, scale_factor, resize_mode, side_ratio, crop_pad_position, pad_feathering, mask_optional=None): + validity = self.VALIDATE_INPUTS(action, smaller_side, larger_side, scale_factor, resize_mode, side_ratio) + if validity is not True: + raise Exception(validity) + (height, width) = pixels.shape[1:3] + if mask_optional is None: + mask = torch.zeros(1, height, width, dtype=torch.float32) + else: + mask = mask_optional + if mask.shape[1] != height or mask.shape[2] != width: + mask = torch.nn.functional.interpolate(mask.unsqueeze(0), size=(height, width), mode='bicubic').squeeze(0).clamp(0.0, 1.0) + (crop_x, crop_y, pad_x, pad_y) = (0.0, 0.0, 0.0, 0.0) + if action == self.ACTION_TYPE_CROP: + target_ratio = self.parse_side_ratio(side_ratio) + if height * target_ratio < width: + crop_x = width - height * target_ratio + else: + crop_y = height - width / target_ratio + elif action == self.ACTION_TYPE_PAD: + target_ratio = self.parse_side_ratio(side_ratio) + if height * target_ratio > width: + pad_x = height * target_ratio - width + else: + pad_y = width / target_ratio - height + if smaller_side > 0: + if width + pad_x - crop_x > height + pad_y - crop_y: + scale_factor = float(smaller_side) / (height + pad_y - crop_y) + else: + scale_factor = float(smaller_side) / (width + pad_x - crop_x) + if larger_side > 0: + if width + pad_x - crop_x > height + pad_y - crop_y: + scale_factor = float(larger_side) / (width + pad_x - crop_x) + else: + scale_factor = float(larger_side) / (height + pad_y - crop_y) + if resize_mode == self.RESIZE_MODE_DOWNSCALE and scale_factor >= 1.0 or (resize_mode == self.RESIZE_MODE_UPSCALE and scale_factor <= 1.0): + scale_factor = 0.0 + if scale_factor > 0.0: + pixels = torch.nn.functional.interpolate(pixels.movedim(-1, 1), scale_factor=scale_factor, mode='bicubic', antialias=True).movedim(1, -1).clamp(0.0, 1.0) + mask = torch.nn.functional.interpolate(mask.unsqueeze(0), scale_factor=scale_factor, mode='bicubic', antialias=True).squeeze(0).clamp(0.0, 1.0) + (height, width) = pixels.shape[1:3] + crop_x *= scale_factor + crop_y *= scale_factor + pad_x *= scale_factor + pad_y *= scale_factor + if crop_x > 0.0 or crop_y > 0.0: + remove_x = (round(crop_x * crop_pad_position), round(crop_x * (1 - crop_pad_position))) if crop_x > 0.0 else (0, 0) + remove_y = (round(crop_y * crop_pad_position), round(crop_y * (1 - crop_pad_position))) if crop_y > 0.0 else (0, 0) + pixels = pixels[:, remove_y[0]:height - remove_y[1], remove_x[0]:width - remove_x[1], :] + mask = mask[:, remove_y[0]:height - remove_y[1], remove_x[0]:width - remove_x[1]] + elif pad_x > 0.0 or pad_y > 0.0: + add_x = (round(pad_x * crop_pad_position), round(pad_x * (1 - crop_pad_position))) if pad_x > 0.0 else (0, 0) + add_y = (round(pad_y * crop_pad_position), round(pad_y * (1 - crop_pad_position))) if pad_y > 0.0 else (0, 0) + new_pixels = torch.zeros(pixels.shape[0], height + add_y[0] + add_y[1], width + add_x[0] + add_x[1], pixels.shape[3], dtype=torch.float32) + new_pixels[:, add_y[0]:height + add_y[0], add_x[0]:width + add_x[0], :] = pixels + pixels = new_pixels + new_mask = torch.ones(mask.shape[0], height + add_y[0] + add_y[1], width + add_x[0] + add_x[1], dtype=torch.float32) + new_mask[:, add_y[0]:height + add_y[0], add_x[0]:width + add_x[0]] = mask + mask = new_mask + if pad_feathering > 0: + for i in range(mask.shape[0]): + for j in range(pad_feathering): + feather_strength = (1 - j / pad_feathering) * (1 - j / pad_feathering) + if add_x[0] > 0 and j < width: + for k in range(height): + mask[i, k, add_x[0] + j] = max(mask[i, k, add_x[0] + j], feather_strength) + if add_x[1] > 0 and j < width: + for k in range(height): + mask[i, k, width + add_x[0] - j - 1] = max(mask[i, k, width + add_x[0] - j - 1], feather_strength) + if add_y[0] > 0 and j < height: + for k in range(width): + mask[i, add_y[0] + j, k] = max(mask[i, add_y[0] + j, k], feather_strength) + if add_y[1] > 0 and j < height: + for k in range(width): + mask[i, height + add_y[0] - j - 1, k] = max(mask[i, height + add_y[0] - j - 1, k], feather_strength) + return (pixels, mask) +``` \ No newline at end of file diff --git a/docs/ImageResizeCalculator(FaceParsing).md b/docs/ImageResizeCalculator(FaceParsing).md new file mode 100644 index 0000000..cd00c7b --- /dev/null +++ b/docs/ImageResizeCalculator(FaceParsing).md @@ -0,0 +1,82 @@ +# Documentation +- Class name: ImageResizeCalculator +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +ImageResizeCalculator节点旨在在保持图像纵横比的同时智能调整图像大小,满足特定要求,如目标尺寸和对齐到8的倍数,这对于某些图像处理任务至关重要。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它是节点操作的主要输入。它决定了将要处理的源材料,影响节点的输出尺寸和计算。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- target_size + - 目标尺寸参数指定了调整大小后的图像的期望尺寸。它在调整大小的过程中起着至关重要的作用,直接影响最终的尺寸和缩放计算。 + - Comfy dtype: INT + - Python dtype: int +- force_8x + - force_8x参数决定调整后的尺寸是否应该对齐到8的倍数。这对于某些从这种对齐中受益的图像处理算法来说尤其重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- width + - 宽度输出提供了调整大小后图像的新宽度,这是节点调整大小计算的直接结果。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度输出对应于调整大小后图像的新高度,这是调整大小过程的另一个关键结果。 + - Comfy dtype: INT + - Python dtype: int +- min + - 最小值输出指示调整大小后的两个维度中较小的一个,提供了调整大小后图像的宽高比的洞察。 + - Comfy dtype: INT + - Python dtype: int +- scale + - 缩放输出表示从原始宽度到新宽度的缩放因子,对于理解调整大小变换来说是一个关键值。 + - Comfy dtype: FLOAT + - Python dtype: float +- scale_r + - scale_r输出表示从原始高度到新高度的缩放因子的倒数,提供了对垂直调整大小方面的全面理解。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageResizeCalculator: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE', {}), 'target_size': ('INT', {'default': 512, 'min': 1, 'step': 1}), 'force_8x': ('BOOLEAN', {'default': True})}} + RETURN_TYPES = ('INT', 'INT', 'INT', 'FLOAT', 'FLOAT') + RETURN_NAMES = ('width', 'height', 'min', 'scale', 'scale_r') + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, image: Tensor, target_size: int, force_8x: bool): + w = image[0].shape[1] + h = image[0].shape[0] + ratio = h * 1.0 / w + if w >= h: + w_new = target_size + h_new = target_size * ratio + if force_8x: + w_new = int(w_new / 8) * 8 + h_new = int(h_new / 8) * 8 + return (w_new, int(h_new), h_new, w_new * 1.0 / w, w * 1.0 / w_new) + else: + w_new = target_size / ratio + h_new = target_size + if force_8x: + w_new = int(w_new / 8) * 8 + h_new = int(h_new / 8) * 8 + return (int(w_new), h_new, w_new, h_new * 1.0 / h, h * 1.0 / h_new) +``` \ No newline at end of file diff --git a/docs/ImageResizeWithBBox(FaceParsing).md b/docs/ImageResizeWithBBox(FaceParsing).md new file mode 100644 index 0000000..841d29e --- /dev/null +++ b/docs/ImageResizeWithBBox(FaceParsing).md @@ -0,0 +1,51 @@ +# Documentation +- Class name: ImageResizeWithBBox +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +该节点旨在在调整图像大小的同时保持边界框的宽高比和位置,确保图像内的关键元素适当缩放并保持用于进一步处理。 + +# Input types +## Required +- bbox + - 边界框参数对于定义图像内的兴趣区域至关重要。它决定了图像的裁剪方式,并确保在调整大小过程中重要特征居中并得到维护。 + - Comfy dtype: BBOX + - Python dtype: torch.Tensor +- image + - 图像参数是这个节点的主要输入,它将根据指定的调整大小要求进行处理。它对于提供将要被转换和分析的视觉数据至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- resized_image + - 该节点的输出是调整大小后的图像,其已调整为满足期望的尺寸,同时保持边界框的位置和宽高比不变,以便进行进一步的分析或显示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageResizeWithBBox: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'bbox': ('BBOX', {}), 'image': ('IMAGE', {})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, bbox: Tensor, image: Tensor): + bbox_int = bbox.int() + l = bbox_int[0] + t = bbox_int[1] + r = bbox_int[2] + b = bbox_int[3] + resized_image = functional.resize(image.permute(0, 3, 1, 2), [b - t, r - l]).permute(0, 2, 3, 1) + return (resized_image,) +``` \ No newline at end of file diff --git a/docs/ImageSeamCarving+.md b/docs/ImageSeamCarving+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ImageSender.md b/docs/ImageSender.md new file mode 100644 index 0000000..a5f5a52 --- /dev/null +++ b/docs/ImageSender.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: ImageSender +- Category: ImpactPack/Util +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImageSender节点旨在方便图像数据的传输。它处理一系列图像,为它们的文件名分配前缀,并将它们发送到指定的服务器端点。此节点在工作流程中扮演着关键角色,通过实现系统间视觉内容的无缝交换。 + +# Input types +## Required +- images + - 'image'参数对于ImageSender节点至关重要,因为它代表了要被处理和传输的视觉数据集合。其适当的选择和格式直接影响节点执行任务的能力。 + - Comfy dtype: IMAGE + - Python dtype: List[bytes] +## Optional +- filename_prefix + - 使用'filename_prefix'参数为正在处理的图像的文件名定义一个共同的前缀。这有助于在接收系统中以系统化的方式组织和识别图像。 + - Comfy dtype: STRING + - Python dtype: str +- link_id + - 'link_id'参数是一个标识符,用于将图像与接收系统中的特定链接或上下文关联起来。它有助于图像数据的目标化传递和引用。 + - Comfy dtype: INT + - Python dtype: int +- prompt + - 'prompt'参数虽然是可选的,但可以用来为图像处理提供额外的上下文或指令。它通过允许对图像处理进行更细微的控制,增强了节点的功能。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - 'extra_pnginfo'参数允许在PNG图像中包含额外的元数据或信息。这对于用接收系统可能需要的额外细节增强图像数据非常有用。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, Any] + +# Output types +- result + - ImageSender节点的'result'输出包含了图像传输过程的结果。它包括了已发送的图像和任何相关的元数据,提供了节点操作的全面概述。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageSender(nodes.PreviewImage): + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'filename_prefix': ('STRING', {'default': 'ImgSender'}), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + OUTPUT_NODE = True + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, images, filename_prefix='ImgSender', link_id=0, prompt=None, extra_pnginfo=None): + result = nodes.PreviewImage().save_images(images, filename_prefix, prompt, extra_pnginfo) + PromptServer.instance.send_sync('img-send', {'link_id': link_id, 'images': result['ui']['images']}) + return result +``` \ No newline at end of file diff --git a/docs/ImageSize(FaceParsing).md b/docs/ImageSize(FaceParsing).md new file mode 100644 index 0000000..2a17ec1 --- /dev/null +++ b/docs/ImageSize(FaceParsing).md @@ -0,0 +1,48 @@ +# Documentation +- Class name: ImageSize +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +ImageSize节点旨在提取并提供输入图像的尺寸,特别是其宽度和高度。它在图像处理工作流中作为一个基本组件,确保理解图像的空间属性,并可以在后续操作中使用。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它是将要确定尺寸的输入图像。它显著影响节点的输出,决定了将计算并返回的宽度和高度的值。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- width + - 宽度输出代表输入图像沿其水平轴的空间范围。这是进一步图像分析和操作的基本信息。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度输出对应输入图像沿其垂直轴的空间范围。这个测量对于理解图像的布局和后续的图像处理任务至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageSize: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE', {})}} + RETURN_TYPES = ('INT', 'INT') + RETURN_NAMES = ('width', 'height') + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, image: Tensor): + w = image.shape[2] + h = image.shape[1] + return (w, h) +``` \ No newline at end of file diff --git a/docs/ImageSizeAndBatchSize.md b/docs/ImageSizeAndBatchSize.md new file mode 100644 index 0000000..50742f1 --- /dev/null +++ b/docs/ImageSizeAndBatchSize.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: ImageSizeAndBatchSize +- Category: Animate Diff/Utils +- Output node: False +- Repo Ref: https://github.com/ArtVentureX/comfyui-animatediff.git + +此类节点旨在提取并返回关键的图像属性,如大小和批量维度,便于系统内进行进一步的处理和分析。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它是节点执行功能的主输入。它通过确定输出的尺寸和批量大小来影响节点的操作。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- width + - 宽度参数代表图像的水平维度,是图像分析和处理的一个基本方面。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数表示图像的垂直维度,在结构理解和操作图像数据中起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- batch_size + - 批量大小参数指示一批图像中图像的数量,这对于优化计算效率和在图像处理期间管理资源至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageSizeAndBatchSize: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',)}} + CATEGORY = 'Animate Diff/Utils' + RETURN_TYPES = ('INT', 'INT', 'INT') + RETURN_NAMES = ('width', 'height', 'batch_size') + FUNCTION = 'batch_size' + + def batch_size(self, image: Tensor): + (batch_size, height, width) = image.shape[0:3] + return (width, height, batch_size) +``` \ No newline at end of file diff --git a/docs/Images to Linear.md b/docs/Images to Linear.md new file mode 100644 index 0000000..0882342 --- /dev/null +++ b/docs/Images to Linear.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: WAS_Images_To_Linear +- Category: WAS Suite/Image +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Images_To_Linear节点旨在将图像数据转换为线性格式。它在图像处理工作流中扮演着关键角色,确保图像数据被适当地转换以便于后续的计算任务。该节点的功能在准备图像进行分析或在线性代数框架内进行操作时至关重要。 + +# Input types +## Required +- images + - “images”参数对于节点的操作至关重要,因为它作为图像到线性转换过程的输入。它直接影响节点的执行,通过确定将被转换的图像的来源。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image.Image] + +# Output types +- linear_images + - “linear_images”输出参数代表图像到线性转换的结果。它很重要,因为它提供了准备好的图像数据,用于进一步的线性分析或操作。 + - Comfy dtype: IMAGE + - Python dtype: Union[torch.Tensor, List[torch.Tensor]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Images_To_Linear: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_to_linear' + CATEGORY = 'WAS Suite/Image' + + def image_to_linear(self, images): + if len(images) > 1: + tensors = [] + for image in images: + tensors.append(pil2tensor(tensor2pil(image).convert('L'))) + tensors = torch.cat(tensors, dim=0) + return (tensors,) + else: + return (pil2tensor(tensor2pil(images).convert('L')),) +``` \ No newline at end of file diff --git a/docs/Images to RGB.md b/docs/Images to RGB.md new file mode 100644 index 0000000..3da617a --- /dev/null +++ b/docs/Images to RGB.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: WAS_Images_To_RGB +- Category: WAS Suite/Image +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Images_To_RGB节点的`image_to_rgb`方法旨在将一系列图像转换为它们的RGB表示形式。它通过将每个图像转换为张量,然后将其转换为RGB格式,最后如果提供了多个图像,则将结果张量堆叠起来来操作。这个过程对于在WAS套件内准备图像进行进一步处理或分析至关重要。 + +# Input types +## Required +- images + - 'image'参数对于节点的操作至关重要,因为它代表了需要转换为RGB格式的图像集合。节点逐个处理每个图像,并确保最终输出是适合下游任务的张量表示。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Output types +- tensors + - 'tensors'输出是代表输入图像RGB格式的张量或张量堆叠。这个输出很重要,因为它允许与WAS套件中需要RGB图像数据进行进一步处理的其他节点无缝集成。 + - Comfy dtype: IMAGE + - Python dtype: Union[torch.Tensor, List[torch.Tensor]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Images_To_RGB: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_to_rgb' + CATEGORY = 'WAS Suite/Image' + + def image_to_rgb(self, images): + if len(images) > 1: + tensors = [] + for image in images: + tensors.append(pil2tensor(tensor2pil(image).convert('RGB'))) + tensors = torch.cat(tensors, dim=0) + return (tensors,) + else: + return (pil2tensor(tensor2pil(images).convert('RGB')),) +``` \ No newline at end of file diff --git a/docs/ImagesFromBatchSchedule.md b/docs/ImagesFromBatchSchedule.md new file mode 100644 index 0000000..1f0e08c --- /dev/null +++ b/docs/ImagesFromBatchSchedule.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: ImagesFromBatchSchedule +- Category: FizzNodes 📅🅕🅝/ScheduleNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +ImagesFromBatchSchedule节点的'animate'方法旨在根据提供的文本提示和当前帧生成一系列图像,并在指定的最大帧范围内。它处理输入文本以创建一系列提示,并为每个帧选择适当的图像,确保动画果中帧与帧之间的平滑过渡。 + +# Input types +## Required +- images + - 'image'参数是节点用来生成动画的图像数据集合。它对节点的操作至关重要,因为它直接影响输出的动画序列。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- text + - 'text'参数包含描述性文本,节点使用该文本来解释和生成动画提示。它非常重要,因为它定义了动画的内容和风格。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- current_frame + - 'current_frame'参数指定节点当前正在处理的帧。它很重要,因为它决定了为动画选择图像的起始点。 + - Comfy dtype: INT + - Python dtype: int +- max_frames + - 'max_frames'参数设置动画中帧数的上限。它很重要,因为它限制了节点生成动画序列的操作范围。 + - Comfy dtype: INT + - Python dtype: int +- print_output + - 'print_output'参数是一个标志,当设置为True时,指示节点将输出打印到控制台。这对于调试目的很有用,可以查看动画生成过程的中间结果。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- selected_images + - 'selected_images'输出包含为动画的当前帧所选择的图像。这个输出很重要,因为它代表了节点对给定帧操作的视觉结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImagesFromBatchSchedule: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'text': ('STRING', {'multiline': True, 'default': defaultPrompt}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 999999.0, 'step': 1.0}), 'max_frames': ('INT', {'default': 120.0, 'min': 1.0, 'max': 999999.0, 'step': 1.0}), 'print_output': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'animate' + CATEGORY = 'FizzNodes 📅🅕🅝/ScheduleNodes' + + def animate(self, images, text, current_frame, max_frames, print_output): + inputText = str('{' + text + '}') + inputText = re.sub(',\\s*}', '}', inputText) + start_frame = 0 + animation_prompts = json.loads(inputText.strip()) + (pos_cur_prompt, pos_nxt_prompt, weight) = interpolate_prompt_series(animation_prompts, max_frames, 0, '', '', 0, 0, 0, 0, print_output) + selImages = selectImages(images, pos_cur_prompt[current_frame]) + return selImages +``` \ No newline at end of file diff --git a/docs/ImpactAssembleSEGS.md b/docs/ImpactAssembleSEGS.md new file mode 100644 index 0000000..7a7cc9f --- /dev/null +++ b/docs/ImpactAssembleSEGS.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: AssembleSEGS +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +AssembleSEGS节点旨在将分割头和元素组合成一个连贯的结构。它在聚合分割数据的过程中扮演着关键角色,确保头和元素被正确地组装成一个完整的分割集。 + +# Input types +## Required +- seg_header + - ‘seg_header’参数对于定义分割过程的元数据至关重要。它决定了分割元素在最终输出中的解释和结构方式。 + - Comfy dtype: SEGS_HEADER + - Python dtype: List[str] +- seg_elt + - ‘seg_elt’参数是必需的,因为它包含了需要被分割的实际数据元素。它通过确定最终分割将包含的内容,影响节点的执行。 + - Comfy dtype: SEG_ELT + - Python dtype: List[Any] + +# Output types +- output + - AssembleSEGS节点的输出是一个结构化的分割集,是将分割头和元素结合的结果。它很重要,因为它代表了分割数据的最终形式,准备进行进一步的处理或分析。 + - Comfy dtype: SEGS + - Python dtype: Tuple[List[str], List[Any]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AssembleSEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'seg_header': ('SEGS_HEADER',), 'seg_elt': ('SEG_ELT',)}} + INPUT_IS_LIST = True + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, seg_header, seg_elt): + return ((seg_header[0], seg_elt),) +``` \ No newline at end of file diff --git a/docs/ImpactCombineConditionings.md b/docs/ImpactCombineConditionings.md new file mode 100644 index 0000000..806f1e4 --- /dev/null +++ b/docs/ImpactCombineConditionings.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: CombineConditionings +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +CombineConditionings是一个实用工具节点,旨在将多个条件输入合并为单个输出。它在简化将各种条件因素整合到复杂数据操作任务中的过程中发挥关键作用。此节点确保不同的条件输入被有效整合,从而促进下游应用中的无缝工作流程。 + +# Input types +## Required +- conditioning1 + - 参数'conditioning1'是节点结合其他输入的主要条件输入。它对节点的操作至关重要,因为它构成了最终组合条件输出的基础。节点的有效性在很大程度上依赖于所提供的条件数据的相关性和质量。 + - Comfy dtype: CONDITIONING + - Python dtype: Any + +# Output types +- combined_conditioning + - 输出'combined_conditioning'表示将所有输入条件聚合到一个统一的结构中。它包含了各个条件的集体影响,使其适合在工作流程的后续阶段进行进一步处理。 + - Comfy dtype: CONDITIONING + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CombineConditionings: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'conditioning1': ('CONDITIONING',)}} + RETURN_TYPES = ('CONDITIONING',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, **kwargs): + res = [] + for (k, v) in kwargs.items(): + res += v + return (res,) +``` \ No newline at end of file diff --git a/docs/ImpactCompare.md b/docs/ImpactCompare.md new file mode 100644 index 0000000..9384255 --- /dev/null +++ b/docs/ImpactCompare.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: ImpactCompare +- Category: ImpactPack/Logic +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactCompare节点旨在基于指定的比较运算符评估并比较两个输入'a'和'b'。它作为一个基本的逻辑工具,使用户能够执行各种关系检查,并返回与所做比较相对应的布尔结果。 + +# Input types +## Required +- cmp + - 参数'cmp'定义了输入'a'和'b'之间的比较类型。它至关重要,因为它决定了应用于比较的逻辑,并直接影响节点执行的结果。 + - Comfy dtype: str + - Python dtype: str +- a + - 参数'a'代表比较中的第一个操作数。它的值和数据类型可以显著影响节点的执行和节点返回的布尔值结果。 + - Comfy dtype: any + - Python dtype: Any +- b + - 参数'b'是比较中的第二个操作数。它与'a'一起工作,以确定基于指定的比较运算符的最终布尔结果。 + - Comfy dtype: any + - Python dtype: Any + +# Output types +- result + - 'result'输出反映了'a'和'b'之间比较的结果,作为一个布尔值。它很重要,因为它是节点逻辑操作的直接输出,并用于通知后续的流程或决策。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactCompare: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'cmp': (['a = b', 'a <> b', 'a > b', 'a < b', 'a >= b', 'a <= b', 'tt', 'ff'],), 'a': (any_typ,), 'b': (any_typ,)}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic' + RETURN_TYPES = ('BOOLEAN',) + + def doit(self, cmp, a, b): + if cmp == 'a = b': + return (a == b,) + elif cmp == 'a <> b': + return (a != b,) + elif cmp == 'a > b': + return (a > b,) + elif cmp == 'a < b': + return (a < b,) + elif cmp == 'a >= b': + return (a >= b,) + elif cmp == 'a <= b': + return (a <= b,) + elif cmp == 'tt': + return (True,) + else: + return (False,) +``` \ No newline at end of file diff --git a/docs/ImpactConcatConditionings.md b/docs/ImpactConcatConditionings.md new file mode 100644 index 0000000..83fd2d0 --- /dev/null +++ b/docs/ImpactConcatConditionings.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: ConcatConditionings +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +该节点旨在将多个条件输入合并为单个输出。它通过将每个条件输入的第一个元素与主要条件输入连接起来,有效地结合了它们的影响。该节点在整合不同的条件信号以引导后续模型行为中发挥着关键作用。 + +# Input types +## Required +- conditioning1 + - 主要的条件输入,将与其他条件输入结合。它至关重要,因为它构成了合并输出的基础,影响着应用于模型的最终条件。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Any]] +## Optional +- conditioning_from + - 将与主要条件输入连接的额外条件输入。每个输入都预期对整体条件效果有所贡献,但如果存在多个条件,则会发出警告,表明只有第一个将被应用。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Any]] + +# Output types +- out + - 节点的输出是合并后的条件对列表,其中每对由主条件张量和附加条件张量连接而成的张量,以及原始条件对中次要元素的副本组成。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Any]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ConcatConditionings: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'conditioning1': ('CONDITIONING',)}} + RETURN_TYPES = ('CONDITIONING',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, **kwargs): + conditioning_to = list(kwargs.values())[0] + for (k, conditioning_from) in list(kwargs.items())[1:]: + out = [] + if len(conditioning_from) > 1: + print('Warning: ConcatConditionings {k} contains more than 1 cond, only the first one will actually be applied to conditioning1.') + cond_from = conditioning_from[0][0] + for i in range(len(conditioning_to)): + t1 = conditioning_to[i][0] + tw = torch.cat((t1, cond_from), 1) + n = [tw, conditioning_to[i][1].copy()] + out.append(n) + conditioning_to = out + return (out,) +``` \ No newline at end of file diff --git a/docs/ImpactConditionalBranch.md b/docs/ImpactConditionalBranch.md new file mode 100644 index 0000000..8d84663 --- /dev/null +++ b/docs/ImpactConditionalBranch.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: ImpactConditionalBranch +- Category: ImpactPack/Logic +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactConditionalBranch节点的'doit'方法旨在根据提供的布尔条件条件性地执行逻辑。它允许根据条件的真值选择两个值中的一个,从而促进了程序中控制流的实现。 + +# Input types +## Required +- cond + - 'cond'参数是一个布尔值,它决定了'doit'方法内执行流程的方向。它至关重要,因为它决定了返回'tt_value'还是'ff_value'。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- tt_value + - 'tt_value'参数表示如果'cond'参数评估为true,则要返回的值。它在节点的条件逻辑中扮演重要角色。 + - Comfy dtype: any_typ + - Python dtype: Any +- ff_value + - 'ff_value'参数是当'cond'参数为false时返回的值。它对于定义节点条件操作中的替代结果是必不可少的。 + - Comfy dtype: any_typ + - Python dtype: Any + +# Output types +- result + - 'result'参数是'doit'方法的结果,将根据'cond'参数的评估是'tt_value'或'ff_value'中的一个。 + - Comfy dtype: any_typ + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactConditionalBranch: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'cond': ('BOOLEAN',), 'tt_value': (any_typ,), 'ff_value': (any_typ,)}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic' + RETURN_TYPES = (any_typ,) + + def doit(self, cond, tt_value, ff_value): + if cond: + return (tt_value,) + else: + return (ff_value,) +``` \ No newline at end of file diff --git a/docs/ImpactConditionalBranchSelMode.md b/docs/ImpactConditionalBranchSelMode.md new file mode 100644 index 0000000..992b068 --- /dev/null +++ b/docs/ImpactConditionalBranchSelMode.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: ImpactConditionalBranchSelMode +- Category: ImpactPack/Logic +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactConditionalBranchSelMode节点的'doit'方法在工作流中充当条件开关。它评估'cond'输入来决定是返回'tt_value'(真值)还是'ff_value'(假值),从而根据条件指导执行流程。 + +# Input types +## Required +- cond + - 参数'cond'是一个布尔值,它决定了节点的执行路径。它至关重要,因为它直接影响返回'tt_value'还是'ff_value',从而影响下游操作。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- sel_mode + - 参数'sel_mode'指示节点应基于提示还是执行进行选择。它很重要,因为它可以在不改变条件的情况下改变节点的行为,提供决策过程中的灵活性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- tt_value + - 当条件为真时,'tt_value'是返回的值。它的重要性在于为肯定情况定义节点的结果,这对工作流中的后续步骤至关重要。 + - Comfy dtype: any_typ + - Python dtype: Any +- ff_value + - 当条件为假时,'ff_value'是返回的值。它很重要,因为它为否定情况设置了节点的输出,这对于后续工作流程的连续性和逻辑可能至关重要。 + - Comfy dtype: any_typ + - Python dtype: Any + +# Output types +- result + - 'result'输出表示条件执行的结果。如果条件为真,它是'tt_value';如果条件为假,它是'ff_value',为后续操作提供关键数据。 + - Comfy dtype: any_typ + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactConditionalBranchSelMode: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'cond': ('BOOLEAN',), 'sel_mode': ('BOOLEAN', {'default': True, 'label_on': 'select_on_prompt', 'label_off': 'select_on_execution'})}, 'optional': {'tt_value': (any_typ,), 'ff_value': (any_typ,)}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic' + RETURN_TYPES = (any_typ,) + + def doit(self, cond, sel_mode, tt_value=None, ff_value=None): + print(f'tt={tt_value is None}\nff={ff_value is None}') + if cond: + return (tt_value,) + else: + return (ff_value,) +``` \ No newline at end of file diff --git a/docs/ImpactConditionalStopIteration.md b/docs/ImpactConditionalStopIteration.md new file mode 100644 index 0000000..eac8aa1 --- /dev/null +++ b/docs/ImpactConditionalStopIteration.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: ImpactConditionalStopIteration +- Category: ImpactPack/Logic +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactConditionalStopIteration节点的'doit'方法旨在根据条件检查控制执行流程。当以真条件调用时,它会发送一个信号来停止迭代过程。该节点在工作流中管理执行流程中起着关键作用,允许在满足某些条件时进行条件性中断。 + +# Input types +## Required +- cond + - 参数'cond'是一个布尔值,它决定了是否应该停止迭代。它对节点的操作至关重要,因为它直接影响关于迭代继续或终止的决策过程。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- None + - 'doit'方法不返回任何输出。它是一个无返回值的方法,其唯一目的是在条件为真时发送一个'stop-iteration'信号,从而影响程序的控制流程。 + - Comfy dtype: DICT + - Python dtype: Dict + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactConditionalStopIteration: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'cond': ('BOOLEAN', {'forceInput': True})}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic' + RETURN_TYPES = () + OUTPUT_NODE = True + + def doit(self, cond): + if cond: + PromptServer.instance.send_sync('stop-iteration', {}) + return {} +``` \ No newline at end of file diff --git a/docs/ImpactControlBridge.md b/docs/ImpactControlBridge.md new file mode 100644 index 0000000..3572000 --- /dev/null +++ b/docs/ImpactControlBridge.md @@ -0,0 +1,105 @@ +# Documentation +- Class name: ImpactControlBridge +- Category: ImpactPack/Logic/_for_test +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactControlBridge节点的'doit'方法旨在管理工作流中节点的操作状态。它确保节点根据提供的条件和行为处于激活、静音或旁路状态,从而控制系统内数据和执行的流程。 + +# Input types +## Required +- value + - 'value'参数对于节点的决策过程至关重要,因为它决定了影响工作流中后续操作的初始状态。 + - Comfy dtype: any_typ + - Python dtype: Any +- mode + - 'mode'参数指示节点是否应该在工作流中强制执行某种操作状态,影响执行路径。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- behavior + - 'behavior'参数允许在节点内应用条件逻辑,根据满足的具体条件修改其响应。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- unique_id + - 'unique_id'参数用于识别工作流中的特定节点,实现目标控制和操作。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +- prompt + - 'prompt'参数提供上下文信息,这对于节点在工作流中做出明智的决策可能是必要的。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - 'extra_pnginfo'参数包含节点有效执行其操作可能需要的额外数据。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, Any] + +# Output types +- value + - 'value'输出反映了节点处理后的最终状态,包含了节点操作的结果。 + - Comfy dtype: any_typ + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactControlBridge: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'value': (any_typ,), 'mode': ('BOOLEAN', {'default': True, 'label_on': 'Active', 'label_off': 'Mute/Bypass'}), 'behavior': ('BOOLEAN', {'default': True, 'label_on': 'Mute', 'label_off': 'Bypass'})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic/_for_test' + RETURN_TYPES = (any_typ,) + RETURN_NAMES = ('value',) + OUTPUT_NODE = True + + @classmethod + def IS_CHANGED(self, value, mode, behavior=True, unique_id=None, prompt=None, extra_pnginfo=None): + (nodes, links) = workflow_to_map(extra_pnginfo['workflow']) + next_nodes = [] + for link in nodes[unique_id]['outputs'][0]['links']: + node_id = str(links[link][2]) + impact.utils.collect_non_reroute_nodes(nodes, links, next_nodes, node_id) + return next_nodes + + def doit(self, value, mode, behavior=True, unique_id=None, prompt=None, extra_pnginfo=None): + global error_skip_flag + (nodes, links) = workflow_to_map(extra_pnginfo['workflow']) + active_nodes = [] + mute_nodes = [] + bypass_nodes = [] + for link in nodes[unique_id]['outputs'][0]['links']: + node_id = str(links[link][2]) + next_nodes = [] + impact.utils.collect_non_reroute_nodes(nodes, links, next_nodes, node_id) + for next_node_id in next_nodes: + node_mode = nodes[next_node_id]['mode'] + if node_mode == 0: + active_nodes.append(next_node_id) + elif node_mode == 2: + mute_nodes.append(next_node_id) + elif node_mode == 4: + bypass_nodes.append(next_node_id) + if mode: + should_be_active_nodes = mute_nodes + bypass_nodes + if len(should_be_active_nodes) > 0: + PromptServer.instance.send_sync('impact-bridge-continue', {'node_id': unique_id, 'actives': list(should_be_active_nodes)}) + error_skip_flag = True + raise Exception('IMPACT-PACK-SIGNAL: STOP CONTROL BRIDGE\nIf you see this message, your ComfyUI-Manager is outdated. Please update it.') + elif behavior: + should_be_mute_nodes = active_nodes + bypass_nodes + if len(should_be_mute_nodes) > 0: + PromptServer.instance.send_sync('impact-bridge-continue', {'node_id': unique_id, 'mutes': list(should_be_mute_nodes)}) + error_skip_flag = True + raise Exception('IMPACT-PACK-SIGNAL: STOP CONTROL BRIDGE\nIf you see this message, your ComfyUI-Manager is outdated. Please update it.') + else: + should_be_bypass_nodes = active_nodes + mute_nodes + if len(should_be_bypass_nodes) > 0: + PromptServer.instance.send_sync('impact-bridge-continue', {'node_id': unique_id, 'bypasses': list(should_be_bypass_nodes)}) + error_skip_flag = True + raise Exception('IMPACT-PACK-SIGNAL: STOP CONTROL BRIDGE\nIf you see this message, your ComfyUI-Manager is outdated. Please update it.') + return (value,) +``` \ No newline at end of file diff --git a/docs/ImpactControlNetApplyAdvancedSEGS.md b/docs/ImpactControlNetApplyAdvancedSEGS.md new file mode 100644 index 0000000..b96115c --- /dev/null +++ b/docs/ImpactControlNetApplyAdvancedSEGS.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: ControlNetApplyAdvancedSEGS +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ControlNetApplyAdvancedSEGS 节点旨在通过应用控制网络来增强分割过程,以细化分割掩码。它通过调整控制网络在整个图像中的影响,确保从一个区域到另一个区域的平滑过渡,而不出现可见的接缝。这个节点特别适用于需要精确控制分割输出的场景。 + +# Input types +## Required +- segs + - 'segs' 参数至关重要,因为它提供了节点将处理的初始分割数据。它直接影响节点的执行,通过确定控制网络细化的起点。 + - Comfy dtype: SEGS + - Python dtype: List[Tuple[Image, List[NamedTuple], BoundingBox, Label, ControlNetAdvancedWrapper]] +- control_net + - 'control_net' 参数定义了将用于指导分割过程的控制网络。它对节点的功能至关重要,因为它决定了如何细化分割掩码。 + - Comfy dtype: CONTROL_NET + - Python dtype: torch.nn.Module +- strength + - 'strength' 参数调整控制网络对分割的影响强度。它是确定分割输出最终质量的关键因素,允许微调控制网络的影响。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_percent + - 'start_percent' 参数指定控制网络效果的起始百分比。它对于控制分割过程开始时的过渡区域很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_percent + - 'end_percent' 参数定义了控制网络效果的结束百分比。它对于管理分割过程结束时的过渡区域至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- segs_preprocessor + - 可选的 'segs_preprocessor' 参数允许在将分割数据输入控制网络之前进行预处理。它可以通过以更有利于控制网络细化过程的方式准备数据来提高节点的性能。 + - Comfy dtype: SEGS_PREPROCESSOR + - Python dtype: Callable +- control_image + - 可选的 'control_image' 参数提供了一个可以用来影响控制网络决策的额外图像。当需要额外的上下文以实现更准确的分割时,它特别有用。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Output types +- segs + - 'segs' 输出包含应用控制网络后的细化分割数据。它代表了节点操作的最终结果,对下游处理很重要。 + - Comfy dtype: SEGS + - Python dtype: List[Tuple[Image, List[NamedTuple], BoundingBox, Label, ControlNetAdvancedWrapper]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ControlNetApplyAdvancedSEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',), 'control_net': ('CONTROL_NET',), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_percent': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001})}, 'optional': {'segs_preprocessor': ('SEGS_PREPROCESSOR',), 'control_image': ('IMAGE',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, segs, control_net, strength, start_percent, end_percent, segs_preprocessor=None, control_image=None): + new_segs = [] + for seg in segs[1]: + control_net_wrapper = core.ControlNetAdvancedWrapper(control_net, strength, start_percent, end_percent, segs_preprocessor, seg.control_net_wrapper, original_size=segs[0], crop_region=seg.crop_region, control_image=control_image) + new_seg = SEG(seg.cropped_image, seg.cropped_mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, control_net_wrapper) + new_segs.append(new_seg) + return ((segs[0], new_segs),) +``` \ No newline at end of file diff --git a/docs/ImpactControlNetApplySEGS.md b/docs/ImpactControlNetApplySEGS.md new file mode 100644 index 0000000..d984e3d --- /dev/null +++ b/docs/ImpactControlNetApplySEGS.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: ControlNetApplySEGS +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ControlNetApplySEGS节点旨在通过应用控制网络来增强分割过程,以细化分割掩码。它通过根据指定的强度参数调整控制网络的影响,确保控制网络的输出与分割结果的无缝集成。 + +# Input types +## Required +- segs + - ‘segs’参数至关重要,因为它提供了节点将处理的初始分割数据。它对节点的执行至关重要,因为它构成了应用控制网络的基础。 + - Comfy dtype: SEGS + - Python dtype: List[impact.core.SEG] +- control_net + - ‘control_net’参数对节点至关重要,因为它定义了用于细化分割的控制网络。它直接影响最终分割输出的质量和准确性。 + - Comfy dtype: CONTROL_NET + - Python dtype: impact.core.ControlNet +- strength + - ‘strength’参数决定了控制网络对分割过程的影响程度。它是平衡分割细化与原始分割数据之间的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- segs_preprocessor + - 可选的‘segs_preprocessor’参数允许在控制网络使用之前对分割数据进行预处理。这对于确保输入数据处于正确的格式或已经过必要的转换可能很重要。 + - Comfy dtype: SEGS_PREPROCESSOR + - Python dtype: Callable +- control_image + - 提供的‘control_image’参数用于通过提供额外的图像上下文来增强控制网络的应用。这可以提高节点对分割进行更明智调整的能力。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Output types +- SEGS + - 输出'SEGS'包含应用控制网络后的细化分割掩码。它代表了节点处理的成果,对进一步分析或下游任务具有重要意义。 + - Comfy dtype: SEGS + - Python dtype: Tuple[str, List[impact.core.SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ControlNetApplySEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',), 'control_net': ('CONTROL_NET',), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01})}, 'optional': {'segs_preprocessor': ('SEGS_PREPROCESSOR',), 'control_image': ('IMAGE',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, segs, control_net, strength, segs_preprocessor=None, control_image=None): + new_segs = [] + for seg in segs[1]: + control_net_wrapper = core.ControlNetWrapper(control_net, strength, segs_preprocessor, seg.control_net_wrapper, original_size=segs[0], crop_region=seg.crop_region, control_image=control_image) + new_seg = SEG(seg.cropped_image, seg.cropped_mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, control_net_wrapper) + new_segs.append(new_seg) + return ((segs[0], new_segs),) +``` \ No newline at end of file diff --git a/docs/ImpactControlNetClearSEGS.md b/docs/ImpactControlNetClearSEGS.md new file mode 100644 index 0000000..6b3c386 --- /dev/null +++ b/docs/ImpactControlNetClearSEGS.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: ControlNetClearSEGS +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ControlNetClearSEGS节点的'doit'方法旨在通过创建具有某些属性设置为None的新SEG实例来处理SEG对象集合。它在预处理或修改分段数据以进行进一步分析或在ImpactPack实用程序套件内进行操作中起着关键作用。 + +# Input types +## Required +- segs + - 'segs'参数是节点将处理的SEG对象集合。它对节点的操作至关重要,因为它定义了将被转换为新格式的输入数据。 + - Comfy dtype: SEGS + - Python dtype: Tuple[SEG, List[SEG]] + +# Output types +- new_segs + - 'new_segs'输出是节点修改后的SEG对象列表。此列表中的每个SEG对象都有特定的属性设置为None,这对于某些类型的后续处理或分析可能很重要。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ControlNetClearSEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, segs): + new_segs = [] + for seg in segs[1]: + new_seg = SEG(seg.cropped_image, seg.cropped_mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, None) + new_segs.append(new_seg) + return ((segs[0], new_segs),) +``` \ No newline at end of file diff --git a/docs/ImpactConvertDataType.md b/docs/ImpactConvertDataType.md new file mode 100644 index 0000000..02c79db --- /dev/null +++ b/docs/ImpactConvertDataType.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: ImpactConvertDataType +- Category: ImpactPack/Logic +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactConvertDataType节点旨在将输入数据转换为各种数据类型。它智能地判断输入是否可以解释为数字,并将其转换为字符串、浮点数、整数和布尔值表示。该节点在数据预处理中扮演着关键角色,适用于需要不同输入之间保持一致数据类型的应用程序。 + +# Input types +## Required +- value + - ‘value’参数是ImpactConvertDataType节点的核心输入。它可以是任何数据类型,对于节点的操作至关重要,因为它决定了转换过程的源材料。节点的功能在很大程度上依赖于这个输入,以准确地执行其类型转换。 + - Comfy dtype: any + - Python dtype: Any + +# Output types +- converted_value + - ‘converted_value’输出来自ImpactConvertDataType节点,提供了一个包含原始字符串值及其转换形式(浮点数、整数和布尔值)的元组。这种全面的输出满足了各种下游处理需求,确保数据被适当地格式化以供进一步分析或操作。 + - Comfy dtype: COMBO[string, float, int, boolean] + - Python dtype: Tuple[str, float, int, bool] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactConvertDataType: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'value': (any_typ,)}} + RETURN_TYPES = ('STRING', 'FLOAT', 'INT', 'BOOLEAN') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic' + + @staticmethod + def is_number(string): + pattern = re.compile('^[-+]?[0-9]*\\.?[0-9]+$') + return bool(pattern.match(string)) + + def doit(self, value): + if self.is_number(str(value)): + num = value + elif str.lower(str(value)) != 'false': + num = 1 + else: + num = 0 + return (str(value), float(num), int(float(num)), bool(float(num))) +``` \ No newline at end of file diff --git a/docs/ImpactDecomposeSEGS.md b/docs/ImpactDecomposeSEGS.md new file mode 100644 index 0000000..a5845a7 --- /dev/null +++ b/docs/ImpactDecomposeSEGS.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: DecomposeSEGS +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +DecomposeSEGS节点旨在将复杂的SEGS数据分解为更易于管理的组件。它的目的是简化SEGS数据结构,便于分析和操作。该节点在数据预处理流程中扮演着重要角色,确保SEGS数据被正确分解以供后续处理阶段使用。 + +# Input types +## Required +- segs + - 'segs'参数对于DecomposeSEGS节点至关重要,因为它代表了需要被分解的输入数据。这是一个关键组件,直接影响节点的操作和输出质量。 + - Comfy dtype: SEGS + - Python dtype: Type[impact.core.SEG] + +# Output types +- SEGS_HEADER + - SEGS_HEADER输出提供了从SEGS数据中提取的头部信息的结构化表示。它对于理解SEGS数据相关的上下文和元数据非常重要。 + - Comfy dtype: SEGS_HEADER + - Python dtype: Dict[str, Any] +- SEG_ELT + - SEG_ELT输出包含SEGS数据的分解元素。它是进一步分析的关键输出,对于需要详细段信息的下游任务至关重要。 + - Comfy dtype: SEG_ELT + - Python dtype: List[impact.core.SEG] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DecomposeSEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',)}} + RETURN_TYPES = ('SEGS_HEADER', 'SEG_ELT') + OUTPUT_IS_LIST = (False, True) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, segs): + return segs +``` \ No newline at end of file diff --git a/docs/ImpactDilateMask.md b/docs/ImpactDilateMask.md new file mode 100644 index 0000000..5408525 --- /dev/null +++ b/docs/ImpactDilateMask.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: DilateMask +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +DilateMask节点旨在对二进制掩码执行形态学膨胀,扩展掩码前景对象的边界。它特别适用于通过增加分段区域的大小来细化分割掩码,这对于对象检测和分割细化等任务非常有益。 + +# Input types +## Required +- mask + - ‘mask’参数是一个二进制掩码,定义了图像内的兴趣区域。它对于膨胀过程至关重要,因为它决定了哪些区域将被扩展。膨胀结果的质量在很大程度上取决于输入掩码的准确性。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- dilation + - ‘dilation’参数指定要应用于掩码的膨胀量。正值会导致掩码边缘扩展,而负值会导致它们收缩。这个参数对于控制膨胀效果的范围至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- dilated_mask + - ‘dilated_mask’输出是将膨胀操作应用于输入掩码的结果。它是一个二进制掩码,其中前景对象已根据指定的膨胀因子进行了扩展。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DilateMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'dilation': ('INT', {'default': 10, 'min': -512, 'max': 512, 'step': 1})}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, mask, dilation): + mask = core.dilate_mask(mask.numpy(), dilation) + mask = torch.from_numpy(mask) + mask = utils.make_3d_mask(mask) + return (mask,) +``` \ No newline at end of file diff --git a/docs/ImpactDilateMaskInSEGS.md b/docs/ImpactDilateMaskInSEGS.md new file mode 100644 index 0000000..1dd2eab --- /dev/null +++ b/docs/ImpactDilateMaskInSEGS.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: DilateMaskInSEGS +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +DilateMaskInSEGS 节点旨在对分割掩码执行形态学膨胀操作。它通过扩展分割区域的边界来增强分割效果。当分割区域的边界定义不明确或需要更稳健的表示时,此过程特别有用。 + +# Input types +## Required +- segs + - ‘segs’参数是节点将要处理的分割对象集合。它对节点的操作至关重要,因为它定义了将应用膨胀操作的输入数据。分割的质量和准确性直接影响膨胀过程的结果。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +- dilation + - ‘dilation’参数指定要应用于分割掩码的膨胀量。它是确定边界扩展程度的关键因素。较大的值会导致更显著的扩展,这对于某些应用可能是有益的,但如果过度使用也可能引入不准确之处。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- new_segs + - ‘new_segs’输出包含应用膨胀后修改的分割对象。这些对象现在具有扩展的边界,可以用于工作流程后续步骤的进一步分析或处理。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DilateMaskInSEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',), 'dilation': ('INT', {'default': 10, 'min': -512, 'max': 512, 'step': 1})}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, segs, dilation): + new_segs = [] + for seg in segs[1]: + mask = core.dilate_mask(seg.cropped_mask, dilation) + seg = SEG(seg.cropped_image, mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, seg.control_net_wrapper) + new_segs.append(seg) + return ((segs[0], new_segs),) +``` \ No newline at end of file diff --git a/docs/ImpactDilate_Mask_SEG_ELT.md b/docs/ImpactDilate_Mask_SEG_ELT.md new file mode 100644 index 0000000..a22e07b --- /dev/null +++ b/docs/ImpactDilate_Mask_SEG_ELT.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: Dilate_SEG_ELT +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +Dilate_SEG_ELT节点旨在对分割掩码执行形态学膨胀,这是图像处理中扩展检测对象边界的关键步骤。该节点通过应用指定因子的膨胀操作来增强分割掩码,从而可能提高后续阶段中对象检测的准确性。 + +# Input types +## Required +- seg_elt + - seg_elt参数是将要处理的分割元素的关键输入。它包含裁剪后的图像、掩码、置信度分数、裁剪区域、边界框、标签和控制网包装器,这些对于正确执行膨胀操作至关重要。 + - Comfy dtype: SEG_ELT + - Python dtype: SEG +## Optional +- dilation + - dilation参数决定了应用于掩码的膨胀效果的程度。较大的值会导致掩码边界的更显著扩展,这对于某些图像分析任务可能很重要。默认值设置为确保平衡的膨胀效果。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- seg_elt + - 输出的seg_elt是具有反映膨胀操作的更新掩码的处理后的分割元素。这个输出很重要,因为它构成了图像处理流水线中进一步分析或可视化的基础。 + - Comfy dtype: SEG_ELT + - Python dtype: SEG + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Dilate_SEG_ELT: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'seg_elt': ('SEG_ELT',), 'dilation': ('INT', {'default': 10, 'min': -512, 'max': 512, 'step': 1})}} + RETURN_TYPES = ('SEG_ELT',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, seg, dilation): + mask = core.dilate_mask(seg.cropped_mask, dilation) + seg = SEG(seg.cropped_image, mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, seg.control_net_wrapper) + return (seg,) +``` \ No newline at end of file diff --git a/docs/ImpactDummyInput.md b/docs/ImpactDummyInput.md new file mode 100644 index 0000000..b73aa02 --- /dev/null +++ b/docs/ImpactDummyInput.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: ImpactDummyInput +- Category: ImpactPack/Debug +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactDummyInput节点的'doit'方法在ImpactPack/Debug类别中充当占位符函数。它旨在执行一个简单的操作,通常用于测试或调试目的,而不会影响主工作流程。 + +# Input types +## Required +- required + - ‘required’参数是一个字典,它指定了ImpactDummyInput节点的必需输入。这对于节点的操作至关重要,因为它决定了必须提供的数据,以便'doit'方法能够正确执行。 + - Comfy dtype: Dict[str, any_typ] + - Python dtype: Dict[str, any_typ] + +# Output types +- output + - 'output'参数代表'doit'方法的结果,在这种情况下,是一个简单的字符串,指示虚拟操作的结果。它很重要,因为它在调试过程中提供了节点执行的直接反馈。 + - Comfy dtype: str + - Python dtype: Tuple[str, ...] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactDummyInput: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}} + CATEGORY = 'ImpactPack/Debug' + RETURN_TYPES = (any_typ,) + FUNCTION = 'doit' + + def doit(self): + return ('DUMMY',) +``` \ No newline at end of file diff --git a/docs/ImpactEdit_SEG_ELT.md b/docs/ImpactEdit_SEG_ELT.md new file mode 100644 index 0000000..d803975 --- /dev/null +++ b/docs/ImpactEdit_SEG_ELT.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: Edit_SEG_ELT +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +Edit_SEG_ELT 节点的 'doit' 方法是 ImpactPack/Util 类别中的关键组件,它用于操作和细化分割元素。该方法能够巧妙地整合各种可选输入,以增强分割过程,并确保输出满足特定任务需求。 + +# Input types +## Required +- seg_elt + - 参数 'seg_elt' 是 Edit_SEG_ELT 节点的核心输入,代表将要处理的分割元素。它对节点的操作至关重要,因为它提供了用于操作的初始数据。 + - Comfy dtype: SEG_ELT + - Python dtype: SEG_ELT 类型的对象 +## Optional +- cropped_image_opt + - 参数 'cropped_image_opt' 允许输入一个可选的裁剪图像,可以用来修改分割元素的视觉方面。 + - Comfy dtype: IMAGE + - Python dtype: Union[torch.Tensor, None] +- cropped_mask_opt + - 参数 'cropped_mask_opt' 是一个可选输入,它提供了裁剪区域的掩码,增强了分割过程的精度。 + - Comfy dtype: MASK + - Python dtype: Union[torch.Tensor, None] +- confidence_opt + - 参数 'confidence_opt' 是一个可选的浮点数值,可以用来调整分割元素的置信度水平,影响分割结果的可靠性。 + - Comfy dtype: FLOAT + - Python dtype: Union[float, None] +- crop_region_opt + - 参数 'crop_region_opt' 是一个可选输入,它指定了裁剪的兴趣区域,可以细化分割的焦点。 + - Comfy dtype: SEG_ELT_crop_region + - Python dtype: Union[Tuple[int, int, int, int], None] +- bbox_opt + - 参数 'bbox_opt' 是一个可选输入,它提供了分割元素的边界框坐标,可以用来定义分割的空间范围。 + - Comfy dtype: SEG_ELT_bbox + - Python dtype: Union[Tuple[int, int, int, int], None] +- label_opt + - 参数 'label_opt' 是一个可选的字符串输入,可以用来给分割元素分配一个标签,有助于对分割段进行分类和识别。 + - Comfy dtype: STRING + - Python dtype: Union[str, None] +- control_net_wrapper_opt + - 参数 'control_net_wrapper_opt' 是一个可选输入,它封装了控制网络信息,可以用来影响分割行为。 + - Comfy dtype: SEG_ELT_control_net_wrapper + - Python dtype: Union[ControlNetWrapper, None] + +# Output types +- seg + - 输出 'seg' 代表 Edit_SEG_ELT 节点处理后的细化分割元素。它封装了更新后的分割数据,准备用于下游任务。 + - Comfy dtype: SEG_ELT + - Python dtype: SEG_ELT 类型的对象 + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Edit_SEG_ELT: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'seg_elt': ('SEG_ELT',)}, 'optional': {'cropped_image_opt': ('IMAGE',), 'cropped_mask_opt': ('MASK',), 'crop_region_opt': ('SEG_ELT_crop_region',), 'bbox_opt': ('SEG_ELT_bbox',), 'control_net_wrapper_opt': ('SEG_ELT_control_net_wrapper',), 'confidence_opt': ('FLOAT', {'min': 0, 'max': 1.0, 'step': 0.1, 'forceInput': True}), 'label_opt': ('STRING', {'multiline': False, 'forceInput': True})}} + RETURN_TYPES = ('SEG_ELT',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, seg_elt, cropped_image_opt=None, cropped_mask_opt=None, confidence_opt=None, crop_region_opt=None, bbox_opt=None, label_opt=None, control_net_wrapper_opt=None): + cropped_image = seg_elt.cropped_image if cropped_image_opt is None else cropped_image_opt + cropped_mask = seg_elt.cropped_mask if cropped_mask_opt is None else cropped_mask_opt + confidence = seg_elt.confidence if confidence_opt is None else confidence_opt + crop_region = seg_elt.crop_region if crop_region_opt is None else crop_region_opt + bbox = seg_elt.bbox if bbox_opt is None else bbox_opt + label = seg_elt.label if label_opt is None else label_opt + control_net_wrapper = seg_elt.control_net_wrapper if control_net_wrapper_opt is None else control_net_wrapper_opt + cropped_image = cropped_image.numpy() if cropped_image is not None else None + if isinstance(cropped_mask, torch.Tensor): + if len(cropped_mask.shape) == 3: + cropped_mask = cropped_mask.squeeze(0) + cropped_mask = cropped_mask.numpy() + seg = SEG(cropped_image, cropped_mask, confidence, crop_region, bbox, label, control_net_wrapper) + return (seg,) +``` \ No newline at end of file diff --git a/docs/ImpactFloat.md b/docs/ImpactFloat.md new file mode 100644 index 0000000..a021e54 --- /dev/null +++ b/docs/ImpactFloat.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: ImpactFloat +- Category: ImpactPack/Logic +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactFloat节点的'doit'方法作为一个基础的处理单元,用于操作浮点数。它旨在以精确的方式处理数值输入,确保节点的计算是健壮和可靠的,这对于ImpactPack套件内的数学运算和数据分析至关重要。 + +# Input types +## Required +- value + - 参数'value'是一个浮点数,节点在其上进行操作。它对节点的功能至关重要,因为它直接影响'doit'方法的结果。该参数对于执行数学计算至关重要,必须提供此参数才能正确执行节点。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- result + - 'doit'方法的输出是一个浮点数,它是输入'value'的处理结果。这个输出很重要,因为它代表了节点计算的结果,可以用于进一步分析或作为工作流中后续节点的输入。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactFloat: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'value': ('FLOAT', {'default': 1.0, 'min': -3.402823466e+38, 'max': 3.402823466e+38})}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic' + RETURN_TYPES = ('FLOAT',) + + def doit(self, value): + return (value,) +``` \ No newline at end of file diff --git a/docs/ImpactFrom_SEG_ELT.md b/docs/ImpactFrom_SEG_ELT.md new file mode 100644 index 0000000..dcfe503 --- /dev/null +++ b/docs/ImpactFrom_SEG_ELT.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: From_SEG_ELT +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +From_SEG_ELT 节点旨在将 SEG_ELT 对象处理并转换为包含图像、掩码和各种元数据的结构化格式。它在准备数据以供 ImpactPack 实用程序套件中进一步分析和操作中发挥着关键作用。 + +# Input types +## Required +- seg_elt + - seg_elt 参数至关重要,因为它代表了节点的核心输入。它包含用于处理的图像数据和相关元数据。节点的功能在很大程度上依赖于 seg_elt 输入的完整性和格式。 + - Comfy dtype: SEG_ELT + - Python dtype: SEG_ELT + +# Output types +- seg_elt + - seg_elt 输出是传递过节点的原始 SEG_ELT 对象,可能在处理期间进行了增强或修改。 + - Comfy dtype: SEG_ELT + - Python dtype: SEG_ELT +- cropped_image + - cropped_image 输出提供了图像数据的张量表示,这对于需要张量输入格式的机器学习模型至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- cropped_mask + - cropped_mask 输出是一个张量,它描绘了图像内的兴趣区域,是涉及分割任务的关键组成部分。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- crop_region + - crop_region 输出指定了图像中裁剪区域的坐标和尺寸,这对于理解数据的空间上下文至关重要。 + - Comfy dtype: SEG_ELT_crop_region + - Python dtype: Tuple[int, int, int, int] +- bbox + - bbox 输出提供了图像中感兴趣对象的边界框坐标,这对于对象检测和定位任务至关重要。 + - Comfy dtype: SEG_ELT_bbox + - Python dtype: List[int] +- control_net_wrapper + - control_net_wrapper 输出封装了可能需要用于高级处理或分析的额外控制信息或参数。 + - Comfy dtype: SEG_ELT_control_net_wrapper + - Python dtype: Any +- confidence + - confidence 输出反映了分割或分类结果的确定性,这对于评估模型输出的可靠性很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- label + - label 输出为处理后的数据分配一个分类标识符,这对于分类和注释目的至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class From_SEG_ELT: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'seg_elt': ('SEG_ELT',)}} + RETURN_TYPES = ('SEG_ELT', 'IMAGE', 'MASK', 'SEG_ELT_crop_region', 'SEG_ELT_bbox', 'SEG_ELT_control_net_wrapper', 'FLOAT', 'STRING') + RETURN_NAMES = ('seg_elt', 'cropped_image', 'cropped_mask', 'crop_region', 'bbox', 'control_net_wrapper', 'confidence', 'label') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, seg_elt): + cropped_image = to_tensor(seg_elt.cropped_image) if seg_elt.cropped_image is not None else None + return (seg_elt, cropped_image, to_tensor(seg_elt.cropped_mask), seg_elt.crop_region, seg_elt.bbox, seg_elt.control_net_wrapper, seg_elt.confidence, seg_elt.label) +``` \ No newline at end of file diff --git a/docs/ImpactFrom_SEG_ELT_bbox.md b/docs/ImpactFrom_SEG_ELT_bbox.md new file mode 100644 index 0000000..08e9e97 --- /dev/null +++ b/docs/ImpactFrom_SEG_ELT_bbox.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: From_SEG_ELT_bbox +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +From_SEG_ELT_bbox节点的'doit'方法旨在处理并返回特定元素的边界框坐标。它在ImpactPack工具集中的空间数据操作中发挥着关键作用,确保了元素的精确定位以供进一步处理。 + +# Input types +## Required +- bbox + - 参数'bbox'对于节点的操作至关重要,因为它定义了要处理的元素的空间边界。它直接影响节点输出的准确性和相关性,通过确定感兴趣的特定区域。 + - Comfy dtype: SEG_ELT_bbox + - Python dtype: Tuple[int, int, int, int] + +# Output types +- left + - 参数'left'代表边界框最左边的坐标,标志着水平跨度的起始。它在定义被处理数据中元素的空间范围方面至关重要。 + - Comfy dtype: INT + - Python dtype: int +- top + - 参数'top'表示边界框最上方的坐标,指示垂直跨度的开始。它对于在数据集中确定元素的垂直位置非常重要。 + - Comfy dtype: INT + - Python dtype: int +- right + - 参数'right'表示边界框最右边的坐标,标志着水平跨度的结束。它在确定元素的宽度及其在数据集中的空间边界方面至关重要。 + - Comfy dtype: INT + - Python dtype: int +- bottom + - 参数'bottom'代表边界框最下方的坐标,标志着垂直跨度的结束。它在确定元素的高度及其在处理数据中的完整垂直范围方面至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class From_SEG_ELT_bbox: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'bbox': ('SEG_ELT_bbox',)}} + RETURN_TYPES = ('INT', 'INT', 'INT', 'INT') + RETURN_NAMES = ('left', 'top', 'right', 'bottom') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, bbox): + return bbox +``` \ No newline at end of file diff --git a/docs/ImpactFrom_SEG_ELT_crop_region.md b/docs/ImpactFrom_SEG_ELT_crop_region.md new file mode 100644 index 0000000..2c52720 --- /dev/null +++ b/docs/ImpactFrom_SEG_ELT_crop_region.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: From_SEG_ELT_crop_region +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +节点'From_SEG_ELT_crop_region'的'doit'方法旨在处理分割图中的特定兴趣区域。它专注于提取定义该区域边界的坐标,这对于在ImpactPack工具集中进行进一步分析或操作至关重要。 + +# Input types +## Required +- crop_region + - 参数'crop_region'至关重要,因为它指定了需要裁剪的分割图中的区域。它直接影响节点的操作,通过确定将被处理和返回的地图的确切部分。 + - Comfy dtype: SEG_ELT_crop_region + - Python dtype: ImpactPack SEG_ELT_crop_region object + +# Output types +- left + - 参数'left'表示裁剪区域的左边界坐标。它很重要,因为它提供了定义分割图中裁剪段位置和范围所需的四个基本坐标之一。 + - Comfy dtype: INT + - Python dtype: int +- top + - 参数'top'表示裁剪区域的顶部边界坐标。与其他三个参数一起,它对于确定从分割图中提取的段的确切位置和尺寸至关重要。 + - Comfy dtype: INT + - Python dtype: int +- right + - 参数'right'表示裁剪区域的右边界坐标。它是确定分割图中段的空间边界的关键组成部分,确保为后续操作隔离正确的部分。 + - Comfy dtype: INT + - Python dtype: int +- bottom + - 参数'bottom'表示裁剪区域的底部边界坐标。它与'left'、'top'和'right'参数一起,构成了在分割图中划定裁剪段所需的坐标集。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class From_SEG_ELT_crop_region: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'crop_region': ('SEG_ELT_crop_region',)}} + RETURN_TYPES = ('INT', 'INT', 'INT', 'INT') + RETURN_NAMES = ('left', 'top', 'right', 'bottom') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, crop_region): + return crop_region +``` \ No newline at end of file diff --git a/docs/ImpactGaussianBlurMask.md b/docs/ImpactGaussianBlurMask.md new file mode 100644 index 0000000..f70bda0 --- /dev/null +++ b/docs/ImpactGaussianBlurMask.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: GaussianBlurMask +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +GaussianBlurMask 节点对输入的遮罩应用高斯模糊效果,软化其边缘并减少噪声。它旨在通过平滑轮廓来增强遮罩的视觉质量,使其适合进一步处理或展示。 + +# Input types +## Required +- mask + - 输入遮罩是节点的关键参数,它决定了将被模糊的图像内容。遮罩的尺寸和格式直接影响高斯模糊的应用方式以及对图像的最终效果。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor or np.ndarray +## Optional +- kernel_size + - 核大小参数决定了高斯模糊效果的范围。它控制了计算模糊的区域大小,值越大,模糊效果越明显。 + - Comfy dtype: INT + - Python dtype: int +- sigma + - sigma 参数定义了高斯核的标准差,它决定了模糊的程度。较高的 sigma 值会导致更强的模糊效果,而较低的值则产生更微妙的模糊。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- blurred_mask + - 输出是输入遮罩的模糊版本,已经通过高斯模糊处理以实现更平滑的外观。这个输出对于需要精细遮罩边缘的应用场景至关重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GaussianBlurMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'kernel_size': ('INT', {'default': 10, 'min': 0, 'max': 100, 'step': 1}), 'sigma': ('FLOAT', {'default': 10.0, 'min': 0.1, 'max': 100.0, 'step': 0.1})}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, mask, kernel_size, sigma): + mask = make_3d_mask(mask) + mask = torch.unsqueeze(mask, dim=-1) + mask = utils.tensor_gaussian_blur_mask(mask, kernel_size, sigma) + mask = torch.squeeze(mask, dim=-1) + return (mask,) +``` \ No newline at end of file diff --git a/docs/ImpactGaussianBlurMaskInSEGS.md b/docs/ImpactGaussianBlurMaskInSEGS.md new file mode 100644 index 0000000..c08a6b1 --- /dev/null +++ b/docs/ImpactGaussianBlurMaskInSEGS.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: GaussianBlurMaskInSEGS +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +GaussianBlurMaskInSEGS节点对SEG对象列表中每个段的掩码部分应用高斯模糊。这个操作增强了掩码边缘的平滑度,对于某些需要更扩散掩码的图像分割任务来说,这可能是有益的。 + +# Input types +## Required +- segs + - segs参数是节点将处理的SEG对象列表。每个SEG对象包含图像数据、掩码和其他对节点操作至关重要的相关信息。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +- kernel_size + - kernel_size参数决定了高斯模糊核的大小。较大的核大小会导致更明显的模糊效果,这可以更显著地平滑掩码边缘。 + - Comfy dtype: INT + - Python dtype: int +- sigma + - sigma参数控制高斯核的标准差,影响模糊的范围。较高的sigma值将产生更强的模糊,而较低的值将导致更温和的效果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- segs + - 输出的segs是原始SEG对象,它们的掩码已经通过高斯模糊操作进行了修改。这允许对平滑后的掩码数据进行后续处理或分析。 + - Comfy dtype: SEGS + - Python dtype: Tuple[List[SEG], List[SEG]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class GaussianBlurMaskInSEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',), 'kernel_size': ('INT', {'default': 10, 'min': 0, 'max': 100, 'step': 1}), 'sigma': ('FLOAT', {'default': 10.0, 'min': 0.1, 'max': 100.0, 'step': 0.1})}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, segs, kernel_size, sigma): + new_segs = [] + for seg in segs[1]: + mask = utils.tensor_gaussian_blur_mask(seg.cropped_mask, kernel_size, sigma) + mask = torch.squeeze(mask, dim=-1).squeeze(0).numpy() + seg = SEG(seg.cropped_image, mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, seg.control_net_wrapper) + new_segs.append(seg) + return ((segs[0], new_segs),) +``` \ No newline at end of file diff --git a/docs/ImpactHFTransformersClassifierProvider.md b/docs/ImpactHFTransformersClassifierProvider.md new file mode 100644 index 0000000..2a5b13f --- /dev/null +++ b/docs/ImpactHFTransformersClassifierProvider.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: HF_TransformersClassifierProvider +- Category: ImpactPack/HuggingFace +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +HF_TransformersClassifierProvider节点旨在使用Hugging Face Transformers库中的模型来促进创建和使用文本分类器。它抽象了模型选择和设备分配的复杂性,使用户能够专注于手头的分类任务。节点的主要功能是简化获取分类器的过程,该分类器可以立即应用于给定的文本数据集。 + +# Input types +## Required +- preset_repo_id + - preset_repo_id参数对于从Hugging Face模型中心识别预配置的模型存储库至关重要。它通过提供一组预定义的选项来简化模型选择过程。此参数在确定分类器将基于的基础模型中起着关键作用,因此直接影响分类性能。 + - Comfy dtype: STRING + - Python dtype: Union[str, List[str]] +- device_mode + - device_mode参数决定了用于模型推理的计算设备。它提供自动选择设备、如果可用则优先选择GPU,或明确选择CPU的选项。这个参数很重要,因为它可以影响分类过程的速度和效率,特别是对于大型模型或数据集。 + - Comfy dtype: STRING + - Python dtype: Literal['AUTO', 'Prefer GPU', 'CPU'] +## Optional +- manual_repo_id + - 当preset_repo_id设置为'Manual repo id'时,manual_repo_id参数允许指定自定义模型存储库ID。这为希望使用预定义选项之外的模型的用户提供了灵活性,使节点能够适应更广泛的分类任务。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- TRANSFORMERS_CLASSIFIER + - TRANSFORMERS_CLASSIFIER输出提供了一个来自Hugging Face Transformers库的预训练模型,用于文本分类任务。它封装了模型的推理能力,允许无缝集成到下游应用中。 + - Comfy dtype: TRANSFORMERS_CLASSIFIER + - Python dtype: Any + +# Usage tips +- Infra type: GPU + +# Source code +``` +class HF_TransformersClassifierProvider: + + @classmethod + def INPUT_TYPES(s): + global hf_transformer_model_urls + return {'required': {'preset_repo_id': (hf_transformer_model_urls + ['Manual repo id'],), 'manual_repo_id': ('STRING', {'multiline': False}), 'device_mode': (['AUTO', 'Prefer GPU', 'CPU'],)}} + RETURN_TYPES = ('TRANSFORMERS_CLASSIFIER',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/HuggingFace' + + def doit(self, preset_repo_id, manual_repo_id, device_mode): + from transformers import pipeline + if preset_repo_id == 'Manual repo id': + url = manual_repo_id + else: + url = preset_repo_id + if device_mode != 'CPU': + device = comfy.model_management.get_torch_device() + else: + device = 'cpu' + classifier = pipeline(model=url, device=device) + return (classifier,) +``` \ No newline at end of file diff --git a/docs/ImpactIPAdapterApplySEGS.md b/docs/ImpactIPAdapterApplySEGS.md new file mode 100644 index 0000000..a53d8b0 --- /dev/null +++ b/docs/ImpactIPAdapterApplySEGS.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: IPAdapterApplySEGS +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +IPAdapterApplySEGS节点旨在集成并应用分段掩码,是ImpactPack工具套件的一部分。它利用IPAdapter框架的力量,根据参考图像调节图像生成,允许传输主题或风格。此节点对于需要精确控制生成过程的任务至关重要,确保输出紧密遵循所需的美学或主题元素。 + +# Input types +## Required +- segs + - ‘segs’参数至关重要,因为它定义了节点将处理的分段掩码。这些掩码对于引导生成符合特定标准或约束的图像至关重要。参数的正确应用直接影响节点生成准确和相关输出的能力。 + - Comfy dtype: SEGS + - Python dtype: List[NamedTuple] +- ipadapter_pipe + - ‘ipadapter_pipe’参数是实现IPAdapter模型集成的关键组件。它负责无缝应用图像到图像的调节,这对于在生成的图像中实现所需的风格或主题转移至关重要。 + - Comfy dtype: IPADAPTER_PIPE + - Python dtype: Tuple[Any, ...] +- weight + - ‘weight’参数在调整参考图像对生成过程的影响中起着重要作用。它允许微调风格或主题转移的程度,确保最终输出满足用户的期望,而不会被参考图像过度支配。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- SEGS + - 输出‘SEGS’代表经过IPAdapter模型调节的处理过的分段掩码。这个输出很重要,因为它包含了节点完善和调整输入掩码以更好地符合所需生成标准的能力。 + - Comfy dtype: SEGS + - Python dtype: List[NamedTuple] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class IPAdapterApplySEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',), 'ipadapter_pipe': ('IPADAPTER_PIPE',), 'weight': ('FLOAT', {'default': 0.7, 'min': -1, 'max': 3, 'step': 0.05}), 'noise': ('FLOAT', {'default': 0.4, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'weight_type': (['original', 'linear', 'channel penalty'], {'default': 'channel penalty'}), 'start_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_at': ('FLOAT', {'default': 0.9, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'unfold_batch': ('BOOLEAN', {'default': False}), 'faceid_v2': ('BOOLEAN', {'default': False}), 'weight_v2': ('FLOAT', {'default': 1.0, 'min': -1, 'max': 3, 'step': 0.05}), 'context_crop_factor': ('FLOAT', {'default': 1.2, 'min': 1.0, 'max': 100, 'step': 0.1}), 'reference_image': ('IMAGE',)}, 'optional': {'combine_embeds': (['concat', 'add', 'subtract', 'average', 'norm average'],), 'neg_image': ('IMAGE',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, segs, ipadapter_pipe, weight, noise, weight_type, start_at, end_at, unfold_batch, faceid_v2, weight_v2, context_crop_factor, reference_image, combine_embeds='concat', neg_image=None): + if len(ipadapter_pipe) == 4: + print(f'[Impact Pack] IPAdapterApplySEGS: Installed Inspire Pack is outdated.') + raise Exception('Inspire Pack is outdated.') + new_segs = [] + (h, w) = segs[0] + if reference_image.shape[2] != w or reference_image.shape[1] != h: + reference_image = tensor_resize(reference_image, w, h) + for seg in segs[1]: + context_crop_region = make_crop_region(w, h, seg.crop_region, context_crop_factor) + cropped_image = crop_image(reference_image, context_crop_region) + control_net_wrapper = core.IPAdapterWrapper(ipadapter_pipe, weight, noise, weight_type, start_at, end_at, unfold_batch, weight_v2, cropped_image, neg_image=neg_image, prev_control_net=seg.control_net_wrapper, combine_embeds=combine_embeds) + new_seg = SEG(seg.cropped_image, seg.cropped_mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, control_net_wrapper) + new_segs.append(new_seg) + return ((segs[0], new_segs),) +``` \ No newline at end of file diff --git a/docs/ImpactIfNone.md b/docs/ImpactIfNone.md new file mode 100644 index 0000000..da2b91c --- /dev/null +++ b/docs/ImpactIfNone.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: ImpactIfNone +- Category: ImpactPack/Logic +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactIfNone节点旨在评估输入的存在性。它返回输入本身以及一个布尔值,指示输入是否已提供。此节点在工作流程中充当条件检查,确保只有在有所需数据时才继续操作。 + +# Input types +## Optional +- signal + - ‘signal’参数是一个可选输入,可以是任何类型。它用于表示节点将评估其存在的数据。该参数的重要性在于其作为节点条件逻辑的主题的作用。 + - Comfy dtype: any_typ + - Python dtype: Any +- any_input + - ‘any_input’参数是另一个可选输入,也是任何类型。它作为节点的通用输入,可以用来触发节点的操作或为‘signal’参数提供额外的上下文。 + - Comfy dtype: any_typ + - Python dtype: Any + +# Output types +- signal_opt + - ‘signal_opt’输出是节点评估过的原始输入。它代表了根据节点逻辑确定为存在或不存在的数据。 + - Comfy dtype: any_typ + - Python dtype: Any +- bool + - ‘bool’输出是一个布尔值,指示是否提供了‘any_input’参数。它作为下游操作的一个明确指示,以决定是否根据输入数据的可用性进行操作。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactIfNone: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'signal': (any_typ,), 'any_input': (any_typ,)}} + RETURN_TYPES = (any_typ, 'BOOLEAN') + RETURN_NAMES = ('signal_opt', 'bool') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic' + + def doit(self, signal=None, any_input=None): + if any_input is None: + return (signal, False) + else: + return (signal, True) +``` \ No newline at end of file diff --git a/docs/ImpactImageBatchToImageList.md b/docs/ImpactImageBatchToImageList.md new file mode 100644 index 0000000..2029d22 --- /dev/null +++ b/docs/ImpactImageBatchToImageList.md @@ -0,0 +1,40 @@ +# Documentation +- Class name: ImageBatchToImageList +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImageBatchToImageList节点旨在将一批图像转换为单个图像的列表。它作为ImpactPack类别中的一个实用工具,促进了从批量处理到单个图像处理的转换,这对于某些需要逐个图像操作的下游任务至关重要。 + +# Input types +## Required +- image + - 'image'参数是要处理的输入图像批次。它至关重要,因为它决定了将被转换为单个图像列表的内容。节点的功能直接依赖于输入图像的质量和格式。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- images + - 'images'输出是由输入批次派生出的单个图像列表。列表中的每个图像对应原始批次中的一个元素,适用于需要单独图像操作或分析的应用程序。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageBatchToImageList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, image): + images = [image[i:i + 1, ...] for i in range(image.shape[0])] + return (images,) +``` \ No newline at end of file diff --git a/docs/ImpactImageInfo.md b/docs/ImpactImageInfo.md new file mode 100644 index 0000000..63aec89 --- /dev/null +++ b/docs/ImpactImageInfo.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: ImpactImageInfo +- Category: ImpactPack/Logic/_for_test +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactImageInfo节点的'doit'方法旨在提供关键的图像信息。它对于理解图像数据集的维度和结构至关重要,这对于下游处理和分析任务至关重要。该方法抽象地传达了节点提取并返回输入图像的批量大小、高度、宽度和通道数的能力。 + +# Input types +## Required +- value + - ‘value’参数是节点处理的输入图像数据。它的作用是基础性的,因为它直接影响到关于图像尺寸的输出信息。这个参数对于节点的执行至关重要,因为它是确定批量大小、高度、宽度和通道数的基础。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- batch + - ‘batch’参数表示在单个批次中处理的图像数量。它很重要,因为它指示了一次处理的数据量,这对于优化计算资源和理解分析的范围非常重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’参数表示输入图像的垂直维度。它是决定空间分辨率的关键因素,对于图像的操纵和显示目的至关重要。 + - Comfy dtype: INT + - Python dtype: int +- width + - ‘width’参数表示输入图像的水平维度。它在整体图像分辨率中扮演着关键角色,对于确保正确的宽高比和显示格式至关重要。 + - Comfy dtype: INT + - Python dtype: int +- channel + - ‘channel’参数指的是图像中的颜色分量数量,对于RGB图像通常是三个。它是颜色深度的决定因素,对于颜色处理和图像增强任务至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactImageInfo: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'value': ('IMAGE',)}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic/_for_test' + RETURN_TYPES = ('INT', 'INT', 'INT', 'INT') + RETURN_NAMES = ('batch', 'height', 'width', 'channel') + + def doit(self, value): + return (value.shape[0], value.shape[1], value.shape[2], value.shape[3]) +``` \ No newline at end of file diff --git a/docs/ImpactInt.md b/docs/ImpactInt.md new file mode 100644 index 0000000..abd400f --- /dev/null +++ b/docs/ImpactInt.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: ImpactInt +- Category: ImpactPack/Logic +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactInt节点的'doit'方法旨在执行一个基本的逻辑操作。它被设计为接收一个整数输入并返回相同的整数值,作为ImpactPack套件中的基本传递函数。此节点在必须保持输入数据完整性的场景中至关重要,确保信息流在计算过程中保持不变。 + +# Input types +## Required +- value + - ‘value’参数是ImpactInt节点操作的一个整体部分。它是节点所需的唯一输入,对于节点执行其传递函数至关重要。节点保持输入完整性的能力取决于此参数的正确提供,突显了其在整个节点功能中的重要作用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result + - ImpactInt节点的‘result’输出参数是输入‘value’的直接反映。它标志着节点成功执行和保持输入数据完整性。该输出很重要,因为它提供了输入整数的可靠且未修改的版本,确保了计算工作流中后续操作的连续性和准确性。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactInt: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'value': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1})}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic' + RETURN_TYPES = ('INT',) + + def doit(self, value): + return (value,) +``` \ No newline at end of file diff --git a/docs/ImpactInversedSwitch.md b/docs/ImpactInversedSwitch.md new file mode 100644 index 0000000..c8656f4 --- /dev/null +++ b/docs/ImpactInversedSwitch.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: GeneralInversedSwitch +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +GeneralInversedSwitch节点旨在根据选择参数选择性地处理输入数据。它通过迭代由'select'输入确定的范围,并根据条件将'input'数据添加到结果列表中来操作。该节点的功能是在迭代计数与'select'值匹配时返回原始输入,否则它将添加'None'。这个节点在需要在不改变原始数据结构的情况下进行条件性数据展示或过滤的场景中特别有用。 + +# Input types +## Required +- select + - 参数'select'决定了节点操作中的迭代次数。它至关重要,因为它决定了何时将'input'数据包含在节点的输出中。'select'的重要性在于其能够控制数据通过节点的流程,从而根据迭代索引实现条件性处理。 + - Comfy dtype: INT + - Python dtype: int +- input + - 参数'input'代表节点可能处理并在某些条件下包含在其输出中的数据。它的重要性在于它是节点条件逻辑的主题,节点决定追加'input'还是'None'是基于'select'的值。 + - Comfy dtype: any_typ + - Python dtype: Any +## Optional +- unique_id + - 参数'unique_id'作为节点操作的标识符。虽然它不直接影响节点的主要功能,但可能用于在更广泛的系统中跟踪或将节点的输出与特定实例或标识符关联起来。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- result + - 输出'result'是一个列表,根据'select'参数的值和迭代索引,它包含原始的'input'数据或'None'。这个输出很重要,因为它概括了节点的决策过程,反映了节点条件性数据包含的目的。 + - Comfy dtype: COMBO[any_typ] + - Python dtype: List[Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GeneralInversedSwitch: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'select': ('INT', {'default': 1, 'min': 1, 'max': 999999, 'step': 1}), 'input': (any_typ,)}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ByPassTypeTuple((any_typ,)) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, select, input, unique_id): + res = [] + for i in range(0, select): + if select == i + 1: + res.append(input) + else: + res.append(None) + return res +``` \ No newline at end of file diff --git a/docs/ImpactIsNotEmptySEGS.md b/docs/ImpactIsNotEmptySEGS.md new file mode 100644 index 0000000..ea40ef4 --- /dev/null +++ b/docs/ImpactIsNotEmptySEGS.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: ImpactNotEmptySEGS +- Category: ImpactPack/Logic +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactNotEmptySEGS节点的'doit'方法用于检查给定的段落列表是否为空,特别关注列表中的第二个元素。在需要进一步处理或在逻辑流程中做出决策时,数据在特定段落中的存在至关重要。 + +# Input types +## Required +- segs + - 'segs'参数是一个包含数据段落的列表。检查其内容对于'doit'方法的操作至关重要,因为它决定了第二个段落是否非空,这对于节点的决策过程至关重要。 + - Comfy dtype: SEGS + - Python dtype: List[Any] + +# Output types +- result + - 'result'输出表示'segs'列表中的第二个元素是否非空。它是一个布尔值,根据'doit'方法执行的条件检查,直接影响后续的逻辑或操作。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactNotEmptySEGS: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'segs': ('SEGS',)}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic' + RETURN_TYPES = ('BOOLEAN',) + + def doit(self, segs): + return (segs[1] != [],) +``` \ No newline at end of file diff --git a/docs/ImpactKSamplerAdvancedBasicPipe.md b/docs/ImpactKSamplerAdvancedBasicPipe.md new file mode 100644 index 0000000..38af06d --- /dev/null +++ b/docs/ImpactKSamplerAdvancedBasicPipe.md @@ -0,0 +1,97 @@ +# Documentation +- Class name: KSamplerAdvancedBasicPipe +- Category: sampling +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +KSamplerAdvancedBasicPipe节点旨在框架内促进高级采样技术。它利用KSamplerAdvanced的能力执行复杂的采样操作,确保对采样过程有高度的控制和定制化。该节点在生成多样化和高质量的潜在表示方面至关重要,这些表示可以进一步细化或用于下游任务。 + +# Input types +## Required +- basic_pipe + - basic_pipe参数对于节点的操作至关重要,因为它包含了采样所需的核心组件,包括模型、clip和VAE。它是构建采样过程的基础,对于节点的正确功能至关重要。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, Any, torch.nn.Module, Any, Any] +- latent_image + - latent_image参数是一个关键输入,它为采样过程提供了初始潜在状态。它显著影响生成样本的起点和轨迹。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +## Optional +- add_noise + - add_noise参数决定在采样过程中是否引入噪声。这会影响生成样本的多样性和质量,是实现期望结果的关键因素。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- noise_seed + - noise_seed参数用于初始化噪声添加的随机数生成器,确保采样过程的可重复性。它在控制节点操作的随机元素中起着至关重要的作用。 + - Comfy dtype: INT + - Python dtype: int +- steps + - steps参数指定在采样过程中执行的迭代次数。它直接影响生成样本的收敛和细节,是节点执行的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数调整采样过程的配置设置,允许微调节点的行为。对于实现最佳性能和结果至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数从预定义的采样器集合中选择要使用的特定采样方法。它是塑造生成样本特征的关键决定因素。 + - Comfy dtype: KSampler.SAMPLERS + - Python dtype: str +- scheduler + - scheduler参数定义了采样过程中要使用的调度算法。它对于管理采样迭代的进度和节奏至关重要。 + - Comfy dtype: KSampler.SCHEDULERS + - Python dtype: str +- start_at_step + - start_at_step参数设置采样过程开始的初始步骤。它允许定制采样轨迹,对于实现特定结果很重要。 + - Comfy dtype: INT + - Python dtype: int +- end_at_step + - end_at_step参数确定采样过程结束的最终步骤。它在确定采样迭代的范围和持续时间方面起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- return_with_leftover_noise + - return_with_leftover_noise参数决定节点是否应在最后一步后返回带有任何剩余噪声的样本。这对于后处理或进一步分析是一个重要考虑因素。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- basic_pipe + - basic_pipe输出提供用于采样的原始组件,可以用于进一步处理或分析。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, Any, torch.nn.Module, Any, Any] +- latent + - latent输出代表模型的采样潜在状态,是采样过程的关键结果,可以作为后续任务或模型的输入。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- vae + - vae输出包括采样过程中使用的变分自编码器,可能对进一步研究或应用有兴趣。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class KSamplerAdvancedBasicPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'basic_pipe': ('BASIC_PIPE',), 'add_noise': ('BOOLEAN', {'default': True, 'label_on': 'enable', 'label_off': 'disable'}), 'noise_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,), 'latent_image': ('LATENT',), 'start_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'end_at_step': ('INT', {'default': 10000, 'min': 0, 'max': 10000}), 'return_with_leftover_noise': ('BOOLEAN', {'default': False, 'label_on': 'enable', 'label_off': 'disable'})}} + RETURN_TYPES = ('BASIC_PIPE', 'LATENT', 'VAE') + FUNCTION = 'sample' + CATEGORY = 'sampling' + + def sample(self, basic_pipe, add_noise, noise_seed, steps, cfg, sampler_name, scheduler, latent_image, start_at_step, end_at_step, return_with_leftover_noise, denoise=1.0): + (model, clip, vae, positive, negative) = basic_pipe + if add_noise: + add_noise = 'enable' + else: + add_noise = 'disable' + if return_with_leftover_noise: + return_with_leftover_noise = 'enable' + else: + return_with_leftover_noise = 'disable' + latent = nodes.KSamplerAdvanced().sample(model, add_noise, noise_seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, start_at_step, end_at_step, return_with_leftover_noise, denoise)[0] + return (basic_pipe, latent, vae) +``` \ No newline at end of file diff --git a/docs/ImpactKSamplerBasicPipe.md b/docs/ImpactKSamplerBasicPipe.md new file mode 100644 index 0000000..e7dc764 --- /dev/null +++ b/docs/ImpactKSamplerBasicPipe.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: KSamplerBasicPipe +- Category: sampling +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +KSamplerBasicPipe节点旨在使用指定的采样器和调度器执行采样操作。它在从初始图像生成新的潜在表示方面发挥着关键作用,这些潜在表示可以进一步处理或用于创建新图像。该节点封装了采样的复杂性,为用户提供了一个简单直观的接口,以获取高质量的潜在样本。 + +# Input types +## Required +- basic_pipe + - basic_pipe参数是一个复合结构,包含了采样所需的基本组件,包括模型、clip、vae以及正/负样本。它在采样过程中起着关键作用,为生成潜在图像提供了上下文。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, Any, torch.nn.Module, Any, Any] +- seed + - seed参数初始化随机数生成器,确保采样过程的可重复性。它对于在不同运行中获得一致的结果至关重要,这在实验和比较研究中尤其重要。 + - Comfy dtype: INT + - Python dtype: int +- steps + - steps参数决定了采样过程将进行的迭代次数。增加步骤的数量可以导致更精细的潜在表示,但同时也增加了计算成本。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数,表示配置,用于控制采样过程。它可以影响收敛和生成的潜在图像的质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数指定了采样过程中要使用的采样器类型。不同的采样器可能会产生不同的结果,选择可以基于期望的结果或数据的特定特征。 + - Comfy dtype: KSampler.SAMPLERS + - Python dtype: str +- scheduler + - scheduler参数定义了采样过程的调度策略。它对于管理采样步骤的进展至关重要,可以影响采样的效率和效果。 + - Comfy dtype: KSampler.SCHEDULERS + - Python dtype: str +- latent_image + - latent_image参数是采样过程将作用的初始潜在表示。它作为生成新潜在图像的起点。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +## Optional +- denoise + - denoise参数控制应用于生成的潜在图像的去噪水平。调整此值可以帮助提高最终输出的质量。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- basic_pipe + - basic_pipe输出包含用于采样的原始组件,可以用于进一步处理或分析。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, Any, torch.nn.Module, Any, Any] +- latent + - latent输出代表从采样过程中新生成的潜在图像,可以用于各种下游任务。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- vae + - vae输出提供了采样过程中使用的变分自编码器模型,可以用于额外的操作或洞察。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KSamplerBasicPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'basic_pipe': ('BASIC_PIPE',), '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,), 'latent_image': ('LATENT',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('BASIC_PIPE', 'LATENT', 'VAE') + FUNCTION = 'sample' + CATEGORY = 'sampling' + + def sample(self, basic_pipe, seed, steps, cfg, sampler_name, scheduler, latent_image, denoise=1.0): + (model, clip, vae, positive, negative) = basic_pipe + latent = nodes.KSampler().sample(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise)[0] + return (basic_pipe, latent, vae) +``` \ No newline at end of file diff --git a/docs/ImpactLatentInfo.md b/docs/ImpactLatentInfo.md new file mode 100644 index 0000000..87ec7dc --- /dev/null +++ b/docs/ImpactLatentInfo.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: ImpactLatentInfo +- Category: ImpactPack/Logic/_for_test +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactLatentInfo节点的'doit'方法旨在通过确定给定输入样本的维度来处理潜在信息。它抽象地操作潜在空间以派生空间维度,这在图像相关任务的进一步处理或可视化中至关重要。 + +# Input types +## Required +- value + - 参数'value'至关重要,因为它包含节点操作所需的潜在样本。它直接影响节点计算输入数据的空间维度的能力。 + - Comfy dtype: Dict[str, torch.Tensor] + - Python dtype: Dict[str, torch.Tensor] + +# Output types +- batch + - 参数'batch'代表一批中的样本数量,这是机器学习应用中批量处理的一个基本方面。 + - Comfy dtype: INT + - Python dtype: int +- height + - 参数'height'表示处理后的图像的垂直维度,这是图像分辨率和空间分析的一个关键因素。 + - Comfy dtype: INT + - Python dtype: int +- width + - 参数'width'表示图像的水平维度,与高度一起决定了图像的整体空间范围。 + - Comfy dtype: INT + - Python dtype: int +- channel + - 参数'channel'表示图像中的颜色通道数,这对于理解图像数据的复杂性和组成至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactLatentInfo: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'value': ('LATENT',)}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic/_for_test' + RETURN_TYPES = ('INT', 'INT', 'INT', 'INT') + RETURN_NAMES = ('batch', 'height', 'width', 'channel') + + def doit(self, value): + shape = value['samples'].shape + return (shape[0], shape[2] * 8, shape[3] * 8, shape[1]) +``` \ No newline at end of file diff --git a/docs/ImpactLogger.md b/docs/ImpactLogger.md new file mode 100644 index 0000000..44f7823 --- /dev/null +++ b/docs/ImpactLogger.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: ImpactLogger +- Category: ImpactPack/Debug +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactLogger节点旨在提供日志记录功能,用于捕获和输出正在处理的数据信息。它特别适用于调试目的,允许开发人员在工作流程的不同阶段检查数据的形状和内容。 + +# Input types +## Required +- data + - ‘data’参数对于日志记录过程至关重要,因为它代表了ImpactLogger节点设计用来记录的核心数据。正是通过这个参数,节点捕获并打印数据的形状和内容以供调试。 + - Comfy dtype: any_typ + - Python dtype: Any +## Optional +- prompt + - ‘prompt’参数作为一个可选的描述符,可以用来为正在记录的数据提供额外的上下文或特定的标识符。当跟踪多个数据点或日志输出用于进一步分析时,这可能特别有用。 + - Comfy dtype: str + - Python dtype: str +- extra_pnginfo + - ‘extra_pnginfo’参数允许包含对日志记录过程可能相关的额外信息。这可能包括元数据或任何其他与正在记录的核心‘data’不直接相关但对调试过程仍具有重要意义的辅助细节。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- output + - ImpactLogger节点的‘output’是一个空字典,表明节点的主要功能是记录信息,而不是产生将传递给后续节点的重要输出。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactLogger: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'data': (any_typ, '')}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + CATEGORY = 'ImpactPack/Debug' + OUTPUT_NODE = True + RETURN_TYPES = () + FUNCTION = 'doit' + + def doit(self, data, prompt, extra_pnginfo): + shape = '' + if hasattr(data, 'shape'): + shape = f'{data.shape} / ' + print(f'[IMPACT LOGGER]: {shape}{data}') + print(f' PROMPT: {prompt}') + return {} +``` \ No newline at end of file diff --git a/docs/ImpactLogicalOperators.md b/docs/ImpactLogicalOperators.md new file mode 100644 index 0000000..ad7ddca --- /dev/null +++ b/docs/ImpactLogicalOperators.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: ImpactLogicalOperators +- Category: ImpactPack/Logic +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactLogicalOperators节点的'doit'方法旨在对两个布尔输入执行逻辑运算。它抽象地代表了逻辑推理的基本概念,其中节点处理输入以根据指定的运算符产生单个布尔输出。该节点在决策过程中起着关键作用,其中结果取决于两个条件之间的逻辑关系。 + +# Input types +## Required +- operator + - ‘operator’参数决定了要执行的逻辑操作类型。它至关重要,因为它决定了节点将在两个布尔输入之间建立的逻辑关系,从而影响节点的执行和最终输出结果。 + - Comfy dtype: STRING + - Python dtype: str +- bool_a + - ‘bool_a’参数代表逻辑操作的第一个布尔输入。它的作用很重要,因为它构成了节点设计用来评估的逻辑比较或连接的一半。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- bool_b + - ‘bool_b’参数是逻辑操作的第二个输入。它至关重要,因为它补充了第一个布尔输入‘bool_a’,以完成节点处理的逻辑表达式。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- result + - ‘result’参数是由节点执行的逻辑操作的布尔结果。它表示在评估两个输入布尔值之间的逻辑关系后得到的最终输出。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactLogicalOperators: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'operator': (['and', 'or', 'xor'],), 'bool_a': ('BOOLEAN', {'forceInput': True}), 'bool_b': ('BOOLEAN', {'forceInput': True})}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic' + RETURN_TYPES = ('BOOLEAN',) + + def doit(self, operator, bool_a, bool_b): + if operator == 'and': + return (bool_a and bool_b,) + elif operator == 'or': + return (bool_a or bool_b,) + else: + return (bool_a != bool_b,) +``` \ No newline at end of file diff --git a/docs/ImpactMakeImageBatch.md b/docs/ImpactMakeImageBatch.md new file mode 100644 index 0000000..425fe40 --- /dev/null +++ b/docs/ImpactMakeImageBatch.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: MakeImageBatch +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +‘MakeImageBatch’节点旨在高效地将多个图像组合成一个单一的批次以供进一步处理。它通过在必要时调整大小以确保批次中的所有图像具有相同的尺寸,并将它们沿批次维度连接起来。该节点在准备图像处理任务的统一数据集方面发挥着关键作用,例如批量神经网络训练或批量图像操作。 + +# Input types +## Required +- image1 + - ‘image1’参数是用作图像批次尺寸参考的第一个图像。它至关重要,因为如果后续图像的尺寸不同,它们将被调整以匹配其尺寸。节点的功能依赖于此参数来创建用于下游任务的统一批次。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- kwargs + - ‘kwargs’参数允许在批次中包含额外的图像。通过此参数提供的每个图像都以与‘image1’相同的方式进行处理,确保批次的一致性。‘kwargs’的灵活性使节点能够适应不同场景中的可变数量的图像,增强了其实用性。 + - Comfy dtype: COMBO[str, IMAGE] + - Python dtype: Dict[str, torch.Tensor] + +# Output types +- image_batch + - ‘image_batch’输出是已连接的图像批次,这些图像已被调整大小以保持批次内的一致性。这个输出很重要,因为它为后续的图像处理任务奠定了基础,确保批次准备好进行如神经网络输入或批量图像编辑等操作。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MakeImageBatch: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image1': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, **kwargs): + image1 = kwargs['image1'] + del kwargs['image1'] + images = [value for value in kwargs.values()] + if len(images) == 0: + return (image1,) + else: + for image2 in images: + if image1.shape[1:] != image2.shape[1:]: + image2 = comfy.utils.common_upscale(image2.movedim(-1, 1), image1.shape[2], image1.shape[1], 'lanczos', 'center').movedim(1, -1) + image1 = torch.cat((image1, image2), dim=0) + return (image1,) +``` \ No newline at end of file diff --git a/docs/ImpactMakeImageList.md b/docs/ImpactMakeImageList.md new file mode 100644 index 0000000..df42125 --- /dev/null +++ b/docs/ImpactMakeImageList.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: MakeImageList +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +‘MakeImageList’节点旨在将图像数据聚合到一个列表中,以便批量处理图像。它通过确保图像以与下游操作兼容的方式组织,从而在图像相关任务的工作流程中发挥着至关重要的作用。 + +# Input types +## Required +- image1 + - ‘image1’参数至关重要,因为它代表了要包含在列表中的第一个图像。它的包含对于节点的正确运作是必需的,突出了它在节点整体操作中的重要性。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] + +# Output types +- images + - ‘images’输出是由节点编译的图像数据列表。它很重要,因为它作为后续图像处理任务的输入,是图像操作流程中的重要环节。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MakeImageList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image1': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, **kwargs): + images = [] + for (k, v) in kwargs.items(): + images.append(v) + return (images,) +``` \ No newline at end of file diff --git a/docs/ImpactMakeTileSEGS.md b/docs/ImpactMakeTileSEGS.md new file mode 100644 index 0000000..3ae324d --- /dev/null +++ b/docs/ImpactMakeTileSEGS.md @@ -0,0 +1,194 @@ +# Documentation +- Class name: MakeTileSEGS +- Category: ImpactPack/__for_testing +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +MakeTileSEGS节点旨在根据指定参数处理和分割图像成块。它智能地处理重叠区域,并应用过滤器以包含或排除某些段,确保一个无缝的分割过程,满足高级图像分析的需求。 + +# Input types +## Required +- images + - 输入图像参数对于节点的操作至关重要,因为它作为分割的原始数据。它直接影响节点的执行和生成的段的质量。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- bbox_size + - bbox_size参数定义了用于图像分割的边界框大小,这对于确定每个块的尺寸至关重要。它在分割过程中和最终输出中扮演着重要角色。 + - Comfy dtype: INT + - Python dtype: int +- crop_factor + - crop_factor参数用于调整裁剪区域相对于边界框的大小,影响每个段中捕获的细节。这是微调分割输出的重要参数。 + - Comfy dtype: FLOAT + - Python dtype: float +- min_overlap + - min_overlap参数指定相邻块之间的最小重叠量,确保段之间的平滑过渡。这对于保持分割区域的连续性至关重要。 + - Comfy dtype: INT + - Python dtype: int +- filter_segs_dilation + - filter_segs_dilation参数控制分割掩码的膨胀,允许调整分割区域的大小和形状。它是细化分割细节的关键。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- mask_irregularity + - mask_irregularity参数在分割掩码中引入不规则性,这对于需要非均匀分割的某些应用非常有用。它为分割过程增加了可变性。 + - Comfy dtype: FLOAT + - Python dtype: float +- irregular_mask_mode + - irregular_mask_mode参数确定用于在掩码中生成不规则性的方法是,提供不同质量和速度级别的掩码生成过程。 + - Comfy dtype: COMBO['Reuse fast', 'Reuse quality', 'All random fast', 'All random quality'] + - Python dtype: str +- filter_in_segs_opt + - filter_in_segs_opt参数允许在分割过程中包含特定段,提供一种专注于图像中感兴趣区域的方法。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +- filter_out_segs_opt + - filter_out_segs_opt参数使从分割过程中排除某些段成为可能,允许从最终分割中移除不需要的区域。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] + +# Output types +- result + - result参数封装了分割过程的输出,提供了分割图像块的详细和结构化表示。 + - Comfy dtype: SEGS + - Python dtype: Tuple[int, List[SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MakeTileSEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'bbox_size': ('INT', {'default': 512, 'min': 64, 'max': 4096, 'step': 8}), 'crop_factor': ('FLOAT', {'default': 3.0, 'min': 1.0, 'max': 10, 'step': 0.1}), 'min_overlap': ('INT', {'default': 5, 'min': 0, 'max': 512, 'step': 1}), 'filter_segs_dilation': ('INT', {'default': 20, 'min': -255, 'max': 255, 'step': 1}), 'mask_irregularity': ('FLOAT', {'default': 0, 'min': 0, 'max': 1.0, 'step': 0.01}), 'irregular_mask_mode': (['Reuse fast', 'Reuse quality', 'All random fast', 'All random quality'],)}, 'optional': {'filter_in_segs_opt': ('SEGS',), 'filter_out_segs_opt': ('SEGS',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/__for_testing' + + def doit(self, images, bbox_size, crop_factor, min_overlap, filter_segs_dilation, mask_irregularity=0, irregular_mask_mode='Reuse fast', filter_in_segs_opt=None, filter_out_segs_opt=None): + if bbox_size <= 2 * min_overlap: + new_min_overlap = bbox_size / 2 + print(f'[MakeTileSEGS] min_overlap should be greater than bbox_size. (value changed: {min_overlap} => {new_min_overlap})') + min_overlap = new_min_overlap + (_, ih, iw, _) = images.size() + mask_cache = None + mask_quality = 512 + if mask_irregularity > 0: + if irregular_mask_mode == 'Reuse fast': + mask_quality = 128 + mask_cache = np.zeros((128, 128)).astype(np.float32) + core.random_mask(mask_cache, (0, 0, 128, 128), factor=mask_irregularity, size=mask_quality) + elif irregular_mask_mode == 'Reuse quality': + mask_quality = 512 + mask_cache = np.zeros((512, 512)).astype(np.float32) + core.random_mask(mask_cache, (0, 0, 512, 512), factor=mask_irregularity, size=mask_quality) + elif irregular_mask_mode == 'All random fast': + mask_quality = 512 + if mask_irregularity > 0: + compensate = max(6, int(mask_quality * mask_irregularity / 4)) + min_overlap += compensate + bbox_size += compensate * 2 + if filter_out_segs_opt is not None: + exclusion_mask = core.segs_to_combined_mask(filter_out_segs_opt) + exclusion_mask = utils.make_3d_mask(exclusion_mask) + exclusion_mask = utils.resize_mask(exclusion_mask, (ih, iw)) + exclusion_mask = dilate_mask(exclusion_mask.cpu().numpy(), filter_segs_dilation) + else: + exclusion_mask = None + if filter_in_segs_opt is not None: + and_mask = core.segs_to_combined_mask(filter_in_segs_opt) + and_mask = utils.make_3d_mask(and_mask) + and_mask = utils.resize_mask(and_mask, (ih, iw)) + and_mask = dilate_mask(and_mask.cpu().numpy(), filter_segs_dilation) + (a, b) = core.mask_to_segs(and_mask, True, 1.0, False, 0) + if len(b) == 0: + return ((a, b),) + (start_x, start_y, c, d) = b[0].crop_region + w = c - start_x + h = d - start_y + else: + start_x = 0 + start_y = 0 + (h, w) = (ih, iw) + and_mask = None + if bbox_size > h or bbox_size > w: + new_bbox_size = min(bbox_size, min(w, h)) + print(f'[MaskTileSEGS] bbox_size is greater than resolution (value changed: {bbox_size} => {new_bbox_size}') + bbox_size = new_bbox_size + n_horizontal = math.ceil(w / (bbox_size - min_overlap)) + n_vertical = math.ceil(h / (bbox_size - min_overlap)) + w_overlap_sum = bbox_size * n_horizontal - w + if w_overlap_sum < 0: + n_horizontal += 1 + w_overlap_sum = bbox_size * n_horizontal - w + w_overlap_size = 0 if n_horizontal == 1 else int(w_overlap_sum / (n_horizontal - 1)) + h_overlap_sum = bbox_size * n_vertical - h + if h_overlap_sum < 0: + n_vertical += 1 + h_overlap_sum = bbox_size * n_vertical - h + h_overlap_size = 0 if n_vertical == 1 else int(h_overlap_sum / (n_vertical - 1)) + new_segs = [] + if w_overlap_size == bbox_size: + n_horizontal = 1 + if h_overlap_size == bbox_size: + n_vertical = 1 + y = start_y + for j in range(0, n_vertical): + x = start_x + for i in range(0, n_horizontal): + x1 = x + y1 = y + if x + bbox_size < iw - 1: + x2 = x + bbox_size + else: + x2 = iw + x1 = iw - bbox_size + if y + bbox_size < ih - 1: + y2 = y + bbox_size + else: + y2 = ih + y1 = ih - bbox_size + bbox = (x1, y1, x2, y2) + crop_region = make_crop_region(iw, ih, bbox, crop_factor) + (cx1, cy1, cx2, cy2) = crop_region + mask = np.zeros((cy2 - cy1, cx2 - cx1)).astype(np.float32) + rel_left = x1 - cx1 + rel_top = y1 - cy1 + rel_right = x2 - cx1 + rel_bot = y2 - cy1 + if mask_irregularity > 0: + if mask_cache is not None: + core.adaptive_mask_paste(mask, mask_cache, (rel_left, rel_top, rel_right, rel_bot)) + else: + core.random_mask(mask, (rel_left, rel_top, rel_right, rel_bot), factor=mask_irregularity, size=mask_quality) + if rel_left == 0: + pad = int((x2 - x1) / 8) + mask[rel_top:rel_bot, :pad] = 1.0 + if rel_top == 0: + pad = int((y2 - y1) / 8) + mask[:pad, rel_left:rel_right] = 1.0 + if rel_right == mask.shape[1]: + pad = int((x2 - x1) / 8) + mask[rel_top:rel_bot, -pad:] = 1.0 + if rel_bot == mask.shape[0]: + pad = int((y2 - y1) / 8) + mask[-pad:, rel_left:rel_right] = 1.0 + else: + mask[rel_top:rel_bot, rel_left:rel_right] = 1.0 + mask = torch.tensor(mask) + if exclusion_mask is not None: + exclusion_mask_cropped = exclusion_mask[cy1:cy2, cx1:cx2] + mask[exclusion_mask_cropped != 0] = 0.0 + if and_mask is not None: + and_mask_cropped = and_mask[cy1:cy2, cx1:cx2] + mask[and_mask_cropped == 0] = 0.0 + is_mask_zero = torch.all(mask == 0.0).item() + if not is_mask_zero: + item = SEG(None, mask.numpy(), 1.0, crop_region, bbox, '', None) + new_segs.append(item) + x += bbox_size - w_overlap_size + y += bbox_size - h_overlap_size + res = ((ih, iw), new_segs) + return (res,) +``` \ No newline at end of file diff --git a/docs/ImpactMinMax.md b/docs/ImpactMinMax.md new file mode 100644 index 0000000..496b5a8 --- /dev/null +++ b/docs/ImpactMinMax.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: ImpactMinMax +- Category: ImpactPack/Logic/_for_test +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactMinMax节点的'doit'方法旨在执行一个基本操作,即确定两个输入值之间的最大值或最小值。它在工作流程中的决策制定和比较中扮演着关键角色,提供了直接但至关重要的功能。 + +# Input types +## Required +- mode + - ‘mode’参数对于节点的操作至关重要,因为它决定了是要返回最大值还是最小值。它直接影响节点的决策过程,使其能够根据指定的模式执行正确的比较。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- a + - ‘a’参数代表比较中的第一个操作数。它是节点功能的基本部分,因为‘a’和‘b’之间的比较决定了输出。‘a’的性质可以非常广泛,允许节点在应用中具有很高的灵活性。 + - Comfy dtype: any_typ + - Python dtype: Any +- b + - ‘b’参数代表比较中的第二个操作数。像‘a’一样,它是节点操作的关键组件,因为‘a’和‘b’之间的比较产生了节点的输出。‘b’的多样性确保了节点可以适应比较中的各种输入类型。 + - Comfy dtype: any_typ + - Python dtype: Any + +# Output types +- result + - ‘result’输出提供了两个输入之间比较的结果。它很重要,因为它代表了节点的最终输出,这基于‘mode’参数,是最大值或最小值。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactMinMax: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'mode': ('BOOLEAN', {'default': True, 'label_on': 'max', 'label_off': 'min'}), 'a': (any_typ,), 'b': (any_typ,)}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic/_for_test' + RETURN_TYPES = ('INT',) + + def doit(self, mode, a, b): + if mode: + return (max(a, b),) + else: + return (min(a, b),) +``` \ No newline at end of file diff --git a/docs/ImpactNeg.md b/docs/ImpactNeg.md new file mode 100644 index 0000000..36627f7 --- /dev/null +++ b/docs/ImpactNeg.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: ImpactNeg +- Category: ImpactPack/Logic +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactNeg节点的'doit'方法旨在反转布尔输入的逻辑状态。它是逻辑操作中的基本构建块,在ImpactPack套件中提供了直接但至关重要的功能。此节点的作用是确保输出是输入的相反数,通过提供一种否定条件的方式来为更广泛的逻辑框架做出贡献。 + +# Input types +## Required +- value + - ‘value’参数是ImpactNeg节点功能的核心组成部分。它代表了节点将要否定的布尔条件。这个参数的重要性在于它直接影响节点的输出,因为结果完全取决于输入值的逻辑状态。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- result + - ‘result’参数是ImpactNeg节点操作的结果。它是输入‘value’的逻辑非布尔值。这个输出很重要,因为它直接反映了节点的否定目的,为逻辑表达式或条件的进一步使用提供了一个清晰、简洁的布尔结果。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactNeg: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'value': ('BOOLEAN', {'forceInput': True})}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic' + RETURN_TYPES = ('BOOLEAN',) + + def doit(self, value): + return (not value,) +``` \ No newline at end of file diff --git a/docs/ImpactNodeSetMuteState.md b/docs/ImpactNodeSetMuteState.md new file mode 100644 index 0000000..221100c --- /dev/null +++ b/docs/ImpactNodeSetMuteState.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: ImpactNodeSetMuteState +- Category: ImpactPack/Logic/_for_test +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactNodeSetMuteState节点的'doit'方法旨在控制信号处理节点的静音状态。它允许用户根据提供的'set_state'参数激活或静音节点,从而影响系统中信号的流动。 + +# Input types +## Required +- signal + - ‘signal’参数代表节点将处理的输入信号。它是节点操作的基本部分,因为它决定了将受到静音状态变化影响的数据。 + - Comfy dtype: ANY + - Python dtype: Any +- node_id + - ‘node_id’参数指定了要改变静音状态的节点的唯一标识符。在多个节点的网络中准确定位目标节点至关重要。 + - Comfy dtype: INT + - Python dtype: int +- set_state + - ‘set_state’参数决定节点应设置为激活还是静音状态。它是一个关键输入,因为它直接控制节点在系统中的操作状态。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- signal_opt + - ‘signal_opt’输出代表静音状态更改后可选修改的信号。它标志着节点操作的结果,反映了信号是否已被处理或静音。 + - Comfy dtype: ANY + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactNodeSetMuteState: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'signal': (any_typ,), 'node_id': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'set_state': ('BOOLEAN', {'default': True, 'label_on': 'active', 'label_off': 'mute'})}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic/_for_test' + RETURN_TYPES = (any_typ,) + RETURN_NAMES = ('signal_opt',) + OUTPUT_NODE = True + + def doit(self, signal, node_id, set_state): + PromptServer.instance.send_sync('impact-node-mute-state', {'node_id': node_id, 'is_active': set_state}) + return (signal,) +``` \ No newline at end of file diff --git a/docs/ImpactQueueTrigger.md b/docs/ImpactQueueTrigger.md new file mode 100644 index 0000000..7fd365b --- /dev/null +++ b/docs/ImpactQueueTrigger.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: ImpactQueueTrigger +- Category: ImpactPack/Logic/_for_test +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactQueueTrigger节点的'doit'方法旨在管理系统中操作的触发。当使用信号和模式调用时,它通过向PromptServer的实例发送命令来决定是否激活特定进程。该节点在控制任务流程和基于预定义条件启动操作中发挥关键作用。 + +# Input types +## Required +- signal + - “signal”参数对于节点的操作至关重要,因为它代表了决定触发进程条件的输入。它的出现对于节点正确运行是必需的,并且它直接影响关于启动后续操作的决策过程。 + - Comfy dtype: any_typ + - Python dtype: Any +## Optional +- mode + - “mode”参数是一个可选的切换器,它指定节点是否应该触发相关操作。它有一个默认值设置为True,这意味着默认情况下会触发操作。此参数允许在不改变主要输入信号的情况下控制节点的行为。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- signal_opt + - “signal_opt”输出代表节点执行后优化或处理的信号。它封装了触发决策的结果,并将信号转发用于系统内的进一步使用或分析。 + - Comfy dtype: any_typ + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactQueueTrigger: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'signal': (any_typ,), 'mode': ('BOOLEAN', {'default': True, 'label_on': 'Trigger', 'label_off': "Don't trigger"})}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic/_for_test' + RETURN_TYPES = (any_typ,) + RETURN_NAMES = ('signal_opt',) + OUTPUT_NODE = True + + def doit(self, signal, mode): + if mode: + PromptServer.instance.send_sync('impact-add-queue', {}) + return (signal,) +``` \ No newline at end of file diff --git a/docs/ImpactQueueTriggerCountdown.md b/docs/ImpactQueueTriggerCountdown.md new file mode 100644 index 0000000..9e205f4 --- /dev/null +++ b/docs/ImpactQueueTriggerCountdown.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: ImpactQueueTriggerCountdown +- Category: ImpactPack/Logic/_for_test +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactQueueTriggerCountdown节点的'doit'方法旨在管理队列系统中的倒计时和触发机制。它推进计数并根据总计数和当前模式决定是否触发事件。该节点在控制基于队列的工作流中的操作流程中起着关键作用。 + +# Input types +## Required +- count + - 参数'count'用于跟踪倒计时序列中的当前位置。它对于确定队列的进度和触发事件的时机至关重要。 + - Comfy dtype: INT + - Python dtype: int +- total + - 参数'total'定义了在满足触发条件之前的最大计数。它对于设置倒计时过程中预期的步骤数很重要。 + - Comfy dtype: INT + - Python dtype: int +- mode + - 参数'mode'决定节点是否应该触发事件。它是一个控制倒计时机制激活状态的重要开关。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- unique_id + - 参数'unique_id'用于在系统中标识节点,以便进行反馈和队列管理。它在确保工作流中准确的通信和跟踪中起着至关重要的作用。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +- signal + - 参数'signal'是一个可选输入,可用于向节点传递额外的信息或控制。它为节点的操作提供了灵活性。 + - Comfy dtype: ANY + - Python dtype: Any + +# Output types +- signal_opt + - 输出'signal_opt'允许节点可选地传递信号,该信号可用于系统的进一步处理或通信。 + - Comfy dtype: ANY + - Python dtype: Any +- count + - 输出'count'反映了节点操作后更新的计数。它对于跟踪队列中倒计时的进度很重要。 + - Comfy dtype: INT + - Python dtype: int +- total + - 输出'total'提供了总计数值,这对于理解倒计时序列中剩余的步骤至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactQueueTriggerCountdown: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'count': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'total': ('INT', {'default': 10, 'min': 1, 'max': 18446744073709551615}), 'mode': ('BOOLEAN', {'default': True, 'label_on': 'Trigger', 'label_off': "Don't trigger"})}, 'optional': {'signal': (any_typ,)}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic/_for_test' + RETURN_TYPES = (any_typ, 'INT', 'INT') + RETURN_NAMES = ('signal_opt', 'count', 'total') + OUTPUT_NODE = True + + def doit(self, count, total, mode, unique_id, signal=None): + if mode: + if count < total - 1: + PromptServer.instance.send_sync('impact-node-feedback', {'node_id': unique_id, 'widget_name': 'count', 'type': 'int', 'value': count + 1}) + PromptServer.instance.send_sync('impact-add-queue', {}) + if count >= total - 1: + PromptServer.instance.send_sync('impact-node-feedback', {'node_id': unique_id, 'widget_name': 'count', 'type': 'int', 'value': 0}) + return (signal, count, total) +``` \ No newline at end of file diff --git a/docs/ImpactRemoteBoolean.md b/docs/ImpactRemoteBoolean.md new file mode 100644 index 0000000..6a859cd --- /dev/null +++ b/docs/ImpactRemoteBoolean.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: ImpactRemoteBoolean +- Category: ImpactPack/Logic/_for_test +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +该节点作为远程执行的逻辑组件,能够在分布式系统中传输和评估布尔值。它旨在评估输入条件的真实性,并将结果传播到其他节点,在控制数据流和执行路径中起着关键作用。 + +# Input types +## Required +- node_id + - node_id参数对于在系统中唯一标识节点至关重要。它确保正确的节点接收输入,并且结果与正确的实例准确关联。 + - Comfy dtype: INT + - Python dtype: int +- widget_name + - widget_name参数对于用户界面至关重要,因为它标记了布尔值的输入字段。该参数影响用户与系统的交互以及界面的清晰度。 + - Comfy dtype: STRING + - Python dtype: str +- value + - value参数是这个节点的核心元素,代表要评估的布尔条件。它是驱动节点功能和后续动作的主要输入。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactRemoteBoolean: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'node_id': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'widget_name': ('STRING', {'multiline': False}), 'value': ('BOOLEAN', {'default': True, 'label_on': 'True', 'label_off': 'False'})}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic/_for_test' + RETURN_TYPES = () + OUTPUT_NODE = True + + def doit(self, **kwargs): + return {} +``` \ No newline at end of file diff --git a/docs/ImpactRemoteInt.md b/docs/ImpactRemoteInt.md new file mode 100644 index 0000000..6bc016b --- /dev/null +++ b/docs/ImpactRemoteInt.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: ImpactRemoteInt +- Category: ImpactPack/Logic/_for_test +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +该节点作为ImpactPack逻辑套件中的测试工具,旨在通过定义的接口评估和展示远程交互的功能。 + +# Input types +## Required +- node_id + - node_id参数对于在系统中唯一标识节点至关重要,它使得目标通信和处理成为可能。 + - Comfy dtype: INT + - Python dtype: int +- widget_name + - widget_name参数指定了要交互的小部件名称,将节点的操作指向正确的接口。 + - Comfy dtype: STRING + - Python dtype: str +- value + - value参数保存在远程交互期间要处理或传输的数据,是节点功能的核心。 + - Comfy dtype: INT + - Python dtype: int + +# Output types + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactRemoteInt: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'node_id': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'widget_name': ('STRING', {'multiline': False}), 'value': ('INT', {'default': 0, 'min': -18446744073709551615, 'max': 18446744073709551615})}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic/_for_test' + RETURN_TYPES = () + OUTPUT_NODE = True + + def doit(self, **kwargs): + return {} +``` \ No newline at end of file diff --git a/docs/ImpactSEGSClassify.md b/docs/ImpactSEGSClassify.md new file mode 100644 index 0000000..19500ae --- /dev/null +++ b/docs/ImpactSEGSClassify.md @@ -0,0 +1,131 @@ +# Documentation +- Class name: SEGS_Classify +- Category: ImpactPack/HuggingFace +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGS_Classify节点旨在使用预训练的变换器模型对图像的段进行分类。它处理段,根据来自分类器的分数评估它们是否满足某个条件,并将段过滤为两个类别:满足条件的段和不满足条件的段。该节点在基于段的图像分析中扮演着关键角色,能够基于复杂标准对图像内容进行分类。 + +# Input types +## Required +- classifier + - 分类器参数对节点的操作至关重要,因为它定义了用于对段进行分类的预训练模型。分类的效力直接取决于分类器的质量和适用性。 + - Comfy dtype: TRANSFORMERS_CLASSIFIER + - Python dtype: transformers.pipeline +- segs + - segs参数保存需要分类的图像段。这是一个基本输入,因为节点的所有处理都围绕这些段进行。 + - Comfy dtype: SEGS + - Python dtype: List[Segment] +- preset_expr + - preset_expr参数允许用户选择用于分类的预定义表达式或选择手动表达式。它决定了将用于分类段的条件。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- manual_expr + - 当preset_expr设置为'Manual expr'时,此参数用于输入用于分类段的自定义表达式。它为用户定义自己的分类标准提供了灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- ref_image_opt + - 可选的ref_image_opt参数提供了一个参考图像,如果段的cropped_image属性不可用,则可以使用该参考图像来裁剪段。它通过在需要时提供段图像的替代来源,增强了节点的功能。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Output types +- filtered_SEGS + - filtered_SEGS输出包含满足用户指定的分类条件的段。它是节点操作的关键结果,代表了基于分类标准过滤的内容。 + - Comfy dtype: SEGS + - Python dtype: Tuple[Segment, List[Segment]] +- remained_SEGS + - remained_SEGS输出包括不满足分类条件的段。它是filtered_SEGS的补充结果,提供了对未根据指定标准进行分类的段的洞察。 + - Comfy dtype: SEGS + - Python dtype: Tuple[Segment, List[Segment]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SEGS_Classify: + + @classmethod + def INPUT_TYPES(s): + global preset_classify_expr + return {'required': {'classifier': ('TRANSFORMERS_CLASSIFIER',), 'segs': ('SEGS',), 'preset_expr': (preset_classify_expr + ['Manual expr'],), 'manual_expr': ('STRING', {'multiline': False})}, 'optional': {'ref_image_opt': ('IMAGE',)}} + RETURN_TYPES = ('SEGS', 'SEGS') + RETURN_NAMES = ('filtered_SEGS', 'remained_SEGS') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/HuggingFace' + + @staticmethod + def lookup_classified_label_score(score_infos, label): + global symbolic_label_map + if label.startswith('#'): + if label not in symbolic_label_map: + return None + else: + label = symbolic_label_map[label] + else: + label = {label} + for x in score_infos: + if x['label'] in label: + return x['score'] + return None + + def doit(self, classifier, segs, preset_expr, manual_expr, ref_image_opt=None): + if preset_expr == 'Manual expr': + expr_str = manual_expr + else: + expr_str = preset_expr + match = re.match(classify_expr_pattern, expr_str) + if match is None: + return ((segs[0], []), segs) + a = match.group(1) + op = match.group(2) + b = match.group(3) + a_is_lab = not is_numeric_string(a) + b_is_lab = not is_numeric_string(b) + classified = [] + remained_SEGS = [] + for seg in segs[1]: + cropped_image = None + if seg.cropped_image is not None: + cropped_image = seg.cropped_image + elif ref_image_opt is not None: + cropped_image = crop_image(ref_image_opt, seg.crop_region) + if cropped_image is not None: + cropped_image = to_pil(cropped_image) + res = classifier(cropped_image) + classified.append((seg, res)) + else: + remained_SEGS.append(seg) + filtered_SEGS = [] + for (seg, res) in classified: + if a_is_lab: + avalue = SEGS_Classify.lookup_classified_label_score(res, a) + else: + avalue = a + if b_is_lab: + bvalue = SEGS_Classify.lookup_classified_label_score(res, b) + else: + bvalue = b + if avalue is None or bvalue is None: + remained_SEGS.append(seg) + continue + avalue = float(avalue) + bvalue = float(bvalue) + if op == '>': + cond = avalue > bvalue + elif op == '<': + cond = avalue < bvalue + elif op == '>=': + cond = avalue >= bvalue + elif op == '<=': + cond = avalue <= bvalue + else: + cond = avalue == bvalue + if cond: + filtered_SEGS.append(seg) + else: + remained_SEGS.append(seg) + return ((segs[0], filtered_SEGS), (segs[0], remained_SEGS)) +``` \ No newline at end of file diff --git a/docs/ImpactSEGSConcat.md b/docs/ImpactSEGSConcat.md new file mode 100644 index 0000000..34a8f59 --- /dev/null +++ b/docs/ImpactSEGSConcat.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: SEGSConcat +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSConcat节点旨在将多个分割(SEGS)合并为一个统一的分割。它高效地合并分割数据,确保生成的分割是连贯的,并且保持原始数据形状的完整性。 + +# Input types +## Required +- segs1 + - 'segs1'参数是要被连接的分割集合。它在定义节点的输入数据中起着关键作用,这些数据将被合并为单个分割输出。 + - Comfy dtype: SEGS + - Python dtype: List[Tuple[Tuple[int, int], List[Any]]] + +# Output types +- output + - 'output'参数代表合并过程生成的连接分割。它很重要,因为它是节点的主要输出,包含了合并后的分割数据。 + - Comfy dtype: SEGS + - Python dtype: Tuple[Tuple[int, int], List[Any]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEGSConcat: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs1': ('SEGS',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, **kwargs): + dim = None + res = None + for (k, v) in list(kwargs.items()): + if v[0] == (0, 0) or len(v[1]) == 0: + continue + if dim is None: + dim = v[0] + res = v[1] + elif v[0] == dim: + res = res + v[1] + else: + print(f"ERROR: source shape of 'segs1'{dim} and '{k}'{v[0]} are different. '{k}' will be ignored") + if dim is None: + empty_segs = ((0, 0), []) + return (empty_segs,) + else: + return ((dim, res),) +``` \ No newline at end of file diff --git a/docs/ImpactSEGSLabelAssign.md b/docs/ImpactSEGSLabelAssign.md new file mode 100644 index 0000000..1cdd575 --- /dev/null +++ b/docs/ImpactSEGSLabelAssign.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: SEGSLabelAssign +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSLabelAssign节点旨在为一系列段落分配标签。它接收一个段落列表和相应的标签,确保每个段落根据它们的顺序与正确的标签相关联。该节点在组织和分类数据以进行进一步处理和分析中发挥着关键作用。 + +# Input types +## Required +- segs + - 'segs'参数是需要被标记的段落集合。它对节点的操作至关重要,因为它定义了将接收分配标签的数据。该参数直接影响节点的输出,决定了将被分类的段落。 + - Comfy dtype: SEGS + - Python dtype: Tuple[Any, List[impact.core.SEG]] +- labels + - 'labels'参数是一个包含由逗号分隔的标签的字符串。它对节点的执行至关重要,因为它指定了将分配给段落的标签。参数的内容决定了段落如何被分类,影响节点的总体输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- SEGS + - 输出'SEGS'是经过分配过程后标记的段落集合。它代表了节点的主要结果,包含了带有新分配标签的段落,这些标签对于后续任务至关重要。 + - Comfy dtype: SEGS + - Python dtype: Tuple[Any, List[impact.core.SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEGSLabelAssign: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',), 'labels': ('STRING', {'multiline': True, 'placeholder': 'List the label to be assigned in order of segs, separated by commas'})}} + RETURN_TYPES = ('SEGS',) + RETURN_NAMES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + @staticmethod + def assign(segs, labels): + labels = [label.strip() for label in labels] + if len(labels) != len(segs[1]): + print(f'Warning (SEGSLabelAssign): length of labels ({len(labels)}) != length of segs ({len(segs[1])})') + labeled_segs = [] + idx = 0 + for x in segs[1]: + if len(labels) > idx: + x = x._replace(label=labels[idx]) + labeled_segs.append(x) + idx += 1 + return ((segs[0], labeled_segs),) + + def doit(self, segs, labels): + labels = labels.split(',') + return SEGSLabelAssign.assign(segs, labels) +``` \ No newline at end of file diff --git a/docs/ImpactSEGSLabelFilter.md b/docs/ImpactSEGSLabelFilter.md new file mode 100644 index 0000000..8b414e5 --- /dev/null +++ b/docs/ImpactSEGSLabelFilter.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: SEGSLabelFilter +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSLabelFilter节点旨在根据预定义的标签集处理和过滤段。它允许包含特定的段类型,并处理将段分类为两组:符合指定标签的段和不符合的段。此节点在ImpactPack实用程序套件中用于进一步分析或处理的段选择中扮演关键角色。 + +# Input types +## Required +- segs + - 'segs'参数至关重要,因为它代表了要被过滤的段集合。它通过确定处理的输入数据集直接影响节点的操作。 + - Comfy dtype: SEGS + - Python dtype: Tuple[Any, List[impact.core.SEG]] +- preset + - 'preset'参数指定节点将用于过滤段的预设检测标签列表。它是定义过滤标准的关键组成部分。 + - Comfy dtype: STRING + - Python dtype: str +- labels + - 'labels'参数是一个多行字符串,允许用户列出他们希望允许的段类型。它之所以重要,是因为它根据用户输入设置了过滤标准。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- filtered_SEGS + - 'filtered_SEGS'输出包含符合指定标签的段,这是过滤过程的主要结果。 + - Comfy dtype: SEGS + - Python dtype: Tuple[Any, List[impact.core.SEG]] +- remained_SEGS + - 'remained_SEGS'输出包括不符合指定标签的段,作为节点操作的次要结果。 + - Comfy dtype: SEGS + - Python dtype: Tuple[Any, List[impact.core.SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEGSLabelFilter: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',), 'preset': (['all'] + defs.detection_labels,), 'labels': ('STRING', {'multiline': True, 'placeholder': 'List the types of segments to be allowed, separated by commas'})}} + RETURN_TYPES = ('SEGS', 'SEGS') + RETURN_NAMES = ('filtered_SEGS', 'remained_SEGS') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + @staticmethod + def filter(segs, labels): + labels = set([label.strip() for label in labels]) + if 'all' in labels: + return (segs, (segs[0], [])) + else: + res_segs = [] + remained_segs = [] + for x in segs[1]: + if x.label in labels: + res_segs.append(x) + elif 'eyes' in labels and x.label in ['left_eye', 'right_eye']: + res_segs.append(x) + elif 'eyebrows' in labels and x.label in ['left_eyebrow', 'right_eyebrow']: + res_segs.append(x) + elif 'pupils' in labels and x.label in ['left_pupil', 'right_pupil']: + res_segs.append(x) + else: + remained_segs.append(x) + return ((segs[0], res_segs), (segs[0], remained_segs)) + + def doit(self, segs, preset, labels): + labels = labels.split(',') + return SEGSLabelFilter.filter(segs, labels) +``` \ No newline at end of file diff --git a/docs/ImpactSEGSOrderedFilter.md b/docs/ImpactSEGSOrderedFilter.md new file mode 100644 index 0000000..7eaa19d --- /dev/null +++ b/docs/ImpactSEGSOrderedFilter.md @@ -0,0 +1,92 @@ +# Documentation +- Class name: SEGSOrderedFilter +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSOrderedFilter节点旨在根据指定的标准(如面积、宽度、高度或坐标)对SEGS(Semantically Enriched Geographic Segments,语义丰富的地理分段)集合进行处理和排序。它允许用户定义排序顺序和要提取的SEGS范围。该节点的功能集中在以有意义的方式组织SEGS,以便进行进一步的分析或可视化。 + +# Input types +## Required +- segs + - ‘segs’参数是节点将处理的SEGS对象集合。它至关重要,因为它构成了节点执行的所有排序操作的基础。此参数直接影响节点执行的结果,决定了哪些SEGS被排序以及它们的排序方式。 + - Comfy dtype: SEGS + - Python dtype: List[impact.core.SEG] +- target + - ‘target’参数决定了将根据SEGS的哪个属性进行排序。它可以是裁剪区域的面积、宽度、高度或其角落的坐标。这个参数至关重要,因为它决定了排序标准,影响最终排序的SEGS列表。 + - Comfy dtype: COMBO['area(=w*h)', 'width', 'height', 'x1', 'y1', 'x2', 'y2'] + - Python dtype: str +## Optional +- order + - ‘order’参数指定根据‘target’属性进行排序时,排序是降序还是升序。它很重要,因为它控制了排序的方向,对于某些应用场景来说,SEGS的顺序至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- take_start + - ‘take_start’参数定义了排序后节点将从哪个起始索引开始提取SEGS。它很重要,因为它允许从排序后的列表中选择特定的SEGS范围,这对于关注数据的特定子集非常有用。 + - Comfy dtype: INT + - Python dtype: int +- take_count + - ‘take_count’参数指定从‘take_start’索引开始,从排序后的列表中提取的SEGS数量。它很重要,因为它决定了将提取的SEGS子集的大小,这对于管理处理的数据量很重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- filtered_SEGS + - 'filtered_SEGS'输出包含根据‘take_start’和‘take_count’参数排序和选择的SEGS子集。它很重要,因为它代表了节点操作的主要结果,提供了输入数据的过滤视图。 + - Comfy dtype: SEGS + - Python dtype: Tuple[impact.core.SEG, List[impact.core.SEG]] +- remained_SEGS + - 'remained_SEGS'输出包括节点过滤过程未选择的SEGS。这些是在提取‘filtered_SEGS’之后的剩余SEGS。这个输出对于需要考虑选定和未选定数据的应用场景很重要。 + - Comfy dtype: SEGS + - Python dtype: Tuple[impact.core.SEG, List[impact.core.SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEGSOrderedFilter: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',), 'target': (['area(=w*h)', 'width', 'height', 'x1', 'y1', 'x2', 'y2'],), 'order': ('BOOLEAN', {'default': True, 'label_on': 'descending', 'label_off': 'ascending'}), 'take_start': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'take_count': ('INT', {'default': 1, 'min': 0, 'max': sys.maxsize, 'step': 1})}} + RETURN_TYPES = ('SEGS', 'SEGS') + RETURN_NAMES = ('filtered_SEGS', 'remained_SEGS') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, segs, target, order, take_start, take_count): + segs_with_order = [] + for seg in segs[1]: + x1 = seg.crop_region[0] + y1 = seg.crop_region[1] + x2 = seg.crop_region[2] + y2 = seg.crop_region[3] + if target == 'area(=w*h)': + value = (y2 - y1) * (x2 - x1) + elif target == 'width': + value = x2 - x1 + elif target == 'height': + value = y2 - y1 + elif target == 'x1': + value = x1 + elif target == 'x2': + value = x2 + elif target == 'y1': + value = y1 + else: + value = y2 + segs_with_order.append((value, seg)) + if order: + sorted_list = sorted(segs_with_order, key=lambda x: x[0], reverse=True) + else: + sorted_list = sorted(segs_with_order, key=lambda x: x[0], reverse=False) + result_list = [] + remained_list = [] + for (i, item) in enumerate(sorted_list): + if take_start <= i < take_start + take_count: + result_list.append(item[1]) + else: + remained_list.append(item[1]) + return ((segs[0], result_list), (segs[0], remained_list)) +``` \ No newline at end of file diff --git a/docs/ImpactSEGSPicker.md b/docs/ImpactSEGSPicker.md new file mode 100644 index 0000000..ec7adee --- /dev/null +++ b/docs/ImpactSEGSPicker.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: SEGSPicker +- Category: ImpactPack/Util +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSPicker节点旨在处理和选择一系列分段中的片段。它接收一个选择的列表,这些是对应于要被选择的分段的索引,以及一组分段。如果提供了备用图像,则该节点将分段缩放到与备用图像匹配,对裁剪后的图像应用掩码,然后根据选择返回一组新的选定分段。它在简化分段选择过程和确保输出符合应用程序的具体要求方面发挥着关键作用。 + +# Input types +## Required +- picks + - ‘picks’参数是一个字符串,包含用逗号分隔的索引列表,表示要被选择的分段。它对节点的功能至关重要,因为它决定了输入集合中哪些分段将被处理并返回为输出。 + - Comfy dtype: STRING + - Python dtype: str +- segs + - ‘segs’参数是节点将处理的分段对象集合。这是一个必需的输入,因为节点的目的是根据不同的选择来操作和选择这些分段。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +## Optional +- fallback_image_opt + - ‘fallback_image_opt’参数是一个可选的图像,如果提供了该参数,节点将使用它来缩放分段。它可以通过确保分段的大小适当,以便于进一步处理或显示,从而影响节点的输出。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- unique_id + - ‘unique_id’参数是一个隐藏字段,节点内部使用它来跟踪和管理分段。它不直接影响节点的执行,但对于维护数据的完整性很重要。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- segs + - ‘segs’输出参数代表基于节点接收的选择生成的新的选定分段集合。它是节点处理的最终结果,并且很重要,因为它代表了进一步使用或分析的最终输出。 + - Comfy dtype: SEGS + - Python dtype: Tuple[List[SEG], List[SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEGSPicker: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'picks': ('STRING', {'multiline': True, 'dynamicPrompts': False, 'pysssss.autocomplete': False}), 'segs': ('SEGS',)}, 'optional': {'fallback_image_opt': ('IMAGE',)}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('SEGS',) + OUTPUT_NODE = True + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, picks, segs, fallback_image_opt=None, unique_id=None): + if fallback_image_opt is not None: + segs = core.segs_scale_match(segs, fallback_image_opt.shape) + cands = [] + for seg in segs[1]: + if seg.cropped_image is not None: + cropped_image = seg.cropped_image + elif fallback_image_opt is not None: + cropped_image = crop_image(fallback_image_opt, seg.crop_region) + else: + cropped_image = empty_pil_tensor() + mask_array = seg.cropped_mask.copy() + mask_array[mask_array < 0.3] = 0.3 + mask_array = mask_array[None, ..., None] + cropped_image = cropped_image * mask_array + cands.append(cropped_image) + impact.impact_server.segs_picker_map[unique_id] = cands + pick_ids = set() + for pick in picks.split(','): + try: + pick_ids.add(int(pick) - 1) + except Exception: + pass + new_segs = [] + for i in pick_ids: + if 0 <= i < len(segs[1]): + new_segs.append(segs[1][i]) + return ((segs[0], new_segs),) +``` \ No newline at end of file diff --git a/docs/ImpactSEGSRangeFilter.md b/docs/ImpactSEGSRangeFilter.md new file mode 100644 index 0000000..d2adbe5 --- /dev/null +++ b/docs/ImpactSEGSRangeFilter.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: SEGSRangeFilter +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSRangeFilter节点旨在根据与它们的空间特征相关的特定标准来处理和过滤段(SEGS)。它允许选择或排除符合特定属性值范围的段,例如面积、宽度、高度或长度百分比。该节点通过评估每个段以满足所提供的标准,并相应地将它们归类为过滤或保留的段。 + +# Input types +## Required +- segs + - 'segs'参数至关重要,因为它代表了将由节点过滤的段。这是一系列段对象,节点将根据定义的标准对其进行处理。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +- target + - 'target'参数决定了将用于过滤的段的特定属性。它可以是几个选项之一,每个选项对应段的不同空间特征。 + - Comfy dtype: COMBO['area(=w*h)', 'width', 'height', 'x1', 'y1', 'x2', 'y2', 'length_percent'] + - Python dtype: str +- mode + - 'mode'参数决定在指定值范围内的段是包含在过滤输出中还是被排除。它作为布尔开关在'inside'和'outside'范围内操作。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- min_value + - 'min_value'参数设置将与之比较的段的值范围的下限。它在确定基于目标属性过滤哪些段中起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- max_value + - 'max_value'参数确定用于过滤段的值范围的上限。它与'min_value'一起工作,以定义段属性的包含范围。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- filtered_SEGS + - 'filtered_SEGS'输出包含符合基于指定目标属性和值范围的过滤标准的段。它代表了节点操作的主要结果。 + - Comfy dtype: SEGS + - Python dtype: Tuple[SEG, List[SEG]] +- remained_SEGS + - 'remained_SEGS'输出包括不满足过滤标准的段。这些是落在指定值范围之外且未包含在过滤输出中的段。 + - Comfy dtype: SEGS + - Python dtype: Tuple[SEG, List[SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEGSRangeFilter: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',), 'target': (['area(=w*h)', 'width', 'height', 'x1', 'y1', 'x2', 'y2', 'length_percent'],), 'mode': ('BOOLEAN', {'default': True, 'label_on': 'inside', 'label_off': 'outside'}), 'min_value': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'max_value': ('INT', {'default': 67108864, 'min': 0, 'max': sys.maxsize, 'step': 1})}} + RETURN_TYPES = ('SEGS', 'SEGS') + RETURN_NAMES = ('filtered_SEGS', 'remained_SEGS') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, segs, target, mode, min_value, max_value): + new_segs = [] + remained_segs = [] + for seg in segs[1]: + x1 = seg.crop_region[0] + y1 = seg.crop_region[1] + x2 = seg.crop_region[2] + y2 = seg.crop_region[3] + if target == 'area(=w*h)': + value = (y2 - y1) * (x2 - x1) + elif target == 'length_percent': + h = y2 - y1 + w = x2 - x1 + value = max(h / w, w / h) * 100 + print(f'value={value}') + elif target == 'width': + value = x2 - x1 + elif target == 'height': + value = y2 - y1 + elif target == 'x1': + value = x1 + elif target == 'x2': + value = x2 + elif target == 'y1': + value = y1 + else: + value = y2 + if mode and min_value <= value <= max_value: + print(f'[in] value={value} / {mode}, {min_value}, {max_value}') + new_segs.append(seg) + elif not mode and (value < min_value or value > max_value): + print(f'[out] value={value} / {mode}, {min_value}, {max_value}') + new_segs.append(seg) + else: + remained_segs.append(seg) + print(f'[filter] value={value} / {mode}, {min_value}, {max_value}') + return ((segs[0], new_segs), (segs[0], remained_segs)) +``` \ No newline at end of file diff --git a/docs/ImpactSEGSToMaskBatch.md b/docs/ImpactSEGSToMaskBatch.md new file mode 100644 index 0000000..a661277 --- /dev/null +++ b/docs/ImpactSEGSToMaskBatch.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: SEGSToMaskBatch +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSToMaskBatch节点旨在将分割数据转换为一批掩码。它在图像处理流程中充当重要的中间体,将分割输出转换为后续操作可以高效处理的格式。该节点抽象了处理单个分割的复杂性,允许掩码的批量处理流程化。 + +# Input types +## Required +- segs + - 'segs'参数对于节点的操作至关重要,因为它提供了需要转换为掩码的分割数据。这个输入显著影响节点的执行和生成的掩码的质量。 + - Comfy dtype: SEGS + - Python dtype: List[NamedTuple] + +# Output types +- mask_batch + - 'mask_batch'输出是由输入分割数据派生的掩码集合。它代表了节点的主要输出,对于工作流程中的进一步分析或处理具有重要意义。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEGSToMaskBatch: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',)}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, segs): + masks = core.segs_to_masklist(segs) + masks = [utils.make_3d_mask(mask) for mask in masks] + mask_batch = torch.concat(masks) + return (mask_batch,) +``` \ No newline at end of file diff --git a/docs/ImpactSEGSToMaskList.md b/docs/ImpactSEGSToMaskList.md new file mode 100644 index 0000000..31940bd --- /dev/null +++ b/docs/ImpactSEGSToMaskList.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: SEGSToMaskList +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSToMaskList节点旨在将分割对象转换为掩码列表。它作为ImpactPack/Util类别中的一个工具,帮助将分割数据转换为更易于用于可视化或进一步分析的格式。 + +# Input types +## Required +- segs + - 参数'segs'对于节点的操作至关重要,因为它提供了需要转换为掩码的分割数据。此参数的重要性在于其作为主要输入的角色,决定了节点的输出。 + - Comfy dtype: SEGS + - Python dtype: List[core.SEG] + +# Output types +- masks + - 输出'masks'是来自输入分割数据的掩码列表。每个掩码代表一个不同的段,这个输出很重要,因为它使得对分割区域进行进一步处理或分析成为可能。 + - Comfy dtype: MASK + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEGSToMaskList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',)}} + RETURN_TYPES = ('MASK',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, segs): + masks = core.segs_to_masklist(segs) + if len(masks) == 0: + empty_mask = torch.zeros(segs[0], dtype=torch.float32, device='cpu') + masks = [empty_mask] + masks = [utils.make_3d_mask(mask) for mask in masks] + return (masks,) +``` \ No newline at end of file diff --git a/docs/ImpactScaleBy_BBOX_SEG_ELT.md b/docs/ImpactScaleBy_BBOX_SEG_ELT.md new file mode 100644 index 0000000..2988e40 --- /dev/null +++ b/docs/ImpactScaleBy_BBOX_SEG_ELT.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: SEG_ELT_BBOX_ScaleBy +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEG_ELT_BBOX_ScaleBy 节点旨在通过指定的因子调整分割元素(SEG_ELT)的规模。它通过缩放 SEG_ELT 的边界框,然后应用零填充到掩码上,以保持分割的完整性。这个节点对于调整分割的大小而不丢失任何细节或引入伪影至关重要。 + +# Input types +## Required +- seg + - 'seg' 参数是需要缩放的分割元素(SEG_ELT)。它非常重要,因为它定义了节点操作的输入数据,并直接影响输出分割的尺寸和属性。 + - Comfy dtype: SEG_ELT + - Python dtype: SEG_ELT +- scale_by + - 'scale_by' 参数决定了 SEG_ELT 的边界框的缩放因子。它是一个浮点数,用于调整分割元素的大小,对最终输出的分辨率和覆盖范围有影响。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- scaled_seg + - 'scaled_seg' 输出是将缩放操作应用于输入 SEG_ELT 的结果。它包括缩放后的边界框和调整后的掩码,确保分割被正确地调整大小,并且在过程中没有丢失信息。 + - Comfy dtype: SEG_ELT + - Python dtype: SEG_ELT + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEG_ELT_BBOX_ScaleBy: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'seg': ('SEG_ELT',), 'scale_by': ('FLOAT', {'default': 1.0, 'min': 0.01, 'max': 8.0, 'step': 0.01})}} + RETURN_TYPES = ('SEG_ELT',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + @staticmethod + def fill_zero_outside_bbox(mask, crop_region, bbox): + (cx1, cy1, _, _) = crop_region + (x1, y1, x2, y2) = bbox + (x1, y1, x2, y2) = (x1 - cx1, y1 - cy1, x2 - cx1, y2 - cy1) + (h, w) = mask.shape + x1 = min(w - 1, max(0, x1)) + x2 = min(w - 1, max(0, x2)) + y1 = min(h - 1, max(0, y1)) + y2 = min(h - 1, max(0, y2)) + mask_cropped = mask.copy() + mask_cropped[:, :x1] = 0 + mask_cropped[:, x2:] = 0 + mask_cropped[:y1, :] = 0 + mask_cropped[y2:, :] = 0 + return mask_cropped + + def doit(self, seg, scale_by): + (x1, y1, x2, y2) = seg.bbox + w = x2 - x1 + h = y2 - y1 + dw = int((w * scale_by - w) / 2) + dh = int((h * scale_by - h) / 2) + bbox = (x1 - dw, y1 - dh, x2 + dw, y2 + dh) + cropped_mask = SEG_ELT_BBOX_ScaleBy.fill_zero_outside_bbox(seg.cropped_mask, seg.crop_region, bbox) + seg = SEG(seg.cropped_image, cropped_mask, seg.confidence, seg.crop_region, bbox, seg.label, seg.control_net_wrapper) + return (seg,) +``` \ No newline at end of file diff --git a/docs/ImpactSegsAndMask.md b/docs/ImpactSegsAndMask.md new file mode 100644 index 0000000..ada1816 --- /dev/null +++ b/docs/ImpactSegsAndMask.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: SegsBitwiseAndMask +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SegsBitwiseAndMask节点的'doit'方法对提供的分割(segs)和掩码进行按位与操作,生成仅包含分割和掩码重叠区域的精炼分割。此操作对于需要精确空间过滤的应用至关重要,例如在医学成像或在图像的特定区域内进行对象检测。 + +# Input types +## Required +- segs + - 'segs'参数是节点将要处理的分割对象集合。它对于定义将通过按位与操作与掩码结合的初始分割至关重要。'segs'的质量和准确性直接影响节点操作的结果。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +- mask + - 'mask'参数是一个二进制掩码,将用于过滤'segs'提供的分割。它是一个关键组件,因为它决定了按位与操作后将保留的分割区域。掩码应准确定义以确保所需的过滤效果。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- result + - 'result'输出是经过与提供的掩码进行按位与操作过滤后的精炼分割集合。它代表了节点的最终输出,其中仅包含符合掩码标准的分割区域。 + - Comfy dtype: SEGS + - Python dtype: Tuple[List[SEG], List[SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SegsBitwiseAndMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',), 'mask': ('MASK',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, segs, mask): + return (core.segs_bitwise_and_mask(segs, mask),) +``` \ No newline at end of file diff --git a/docs/ImpactSegsAndMaskForEach.md b/docs/ImpactSegsAndMaskForEach.md new file mode 100644 index 0000000..176ff7a --- /dev/null +++ b/docs/ImpactSegsAndMaskForEach.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: SegsBitwiseAndMaskForEach +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SegsBitwiseAndMaskForEach节点的'doit'方法对每个分割掩码和提供的掩码执行按位与操作,从而生成一组细化的分割掩码。此操作对于过滤掉分割过程中不需要的区域至关重要,确保只保留感兴趣的区域。 + +# Input types +## Required +- segs + - 'segs'参数代表将由节点处理的分割对象集合。它对节点的操作至关重要,因为它决定了将与掩码进行按位与操作的输入数据。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +- masks + - 'masks'参数是一个张量,包含要应用于每个分割的掩码。它在节点的功能中扮演重要角色,通过定义最终分割输出中要包含或排除的区域。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- output + - 'doit'方法的输出是一个包含原始分割和一个细化分割对象列表的元组,每个对象都带有通过按位与操作更新的掩码。 + - Comfy dtype: SEGS + - Python dtype: Tuple[SEG, List[SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SegsBitwiseAndMaskForEach: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',), 'masks': ('MASK',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, segs, masks): + return (core.apply_mask_to_each_seg(segs, masks),) +``` \ No newline at end of file diff --git a/docs/ImpactSetWidgetValue.md b/docs/ImpactSetWidgetValue.md new file mode 100644 index 0000000..c657c6a --- /dev/null +++ b/docs/ImpactSetWidgetValue.md @@ -0,0 +1,82 @@ +# Documentation +- Class name: ImpactSetWidgetValue +- Category: ImpactPack/Logic/_for_test +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactSetWidgetValue节点的'doit'方法旨在处理将不同数据类型赋值给指定的控件。它通过确定数据类型,然后将相应的值应用到控件上,抽象地管理设置控件值的复杂性,从而简化了在ImpactPack套件内与控件交互的过程。 + +# Input types +## Required +- signal + - ‘signal’参数对于节点的操作至关重要,因为它代表了触发控件值赋值过程的控制信号。节点要正确运行,其存在是必需的。 + - Comfy dtype: any_typ + - Python dtype: Any +- node_id + - ‘node_id’参数至关重要,因为它在系统中唯一标识节点,使得控件值赋值能够精确定位。它在确保控件被准确操作中起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- widget_name + - ‘widget_name’参数对于节点的功能至关重要,因为它指定了将被赋值的控件的名称。它是节点目的成功执行的关键信息。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- boolean_value + - 当提供‘boolean_value’参数时,允许节点将布尔值赋给指定的控件,增强了节点操作的多功能性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- int_value + - 当使用‘int_value’参数时,使节点能够为控件设置整数值,有助于节点处理各种数据类型的能力。 + - Comfy dtype: INT + - Python dtype: int +- float_value + - 如果提供‘float_value’参数,指示节点将浮点数赋给控件,展示了节点管理不同数值格式的能力。 + - Comfy dtype: FLOAT + - Python dtype: float +- string_value + - 当提供‘string_value’参数时,使节点能够将字符串赋给控件,突出了节点在处理控件配置的字符串数据方面的灵活性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- signal_opt + - ‘signal_opt’输出参数代表节点在控件值赋值后可能返回的可选控制信号,表示操作的完成。 + - Comfy dtype: any_typ + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactSetWidgetValue: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'signal': (any_typ,), 'node_id': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'widget_name': ('STRING', {'multiline': False})}, 'optional': {'boolean_value': ('BOOLEAN', {'forceInput': True}), 'int_value': ('INT', {'forceInput': True}), 'float_value': ('FLOAT', {'forceInput': True}), 'string_value': ('STRING', {'forceInput': True})}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic/_for_test' + RETURN_TYPES = (any_typ,) + RETURN_NAMES = ('signal_opt',) + OUTPUT_NODE = True + + def doit(self, signal, node_id, widget_name, boolean_value=None, int_value=None, float_value=None, string_value=None): + kind = None + if boolean_value is not None: + value = boolean_value + kind = 'BOOLEAN' + elif int_value is not None: + value = int_value + kind = 'INT' + elif float_value is not None: + value = float_value + kind = 'FLOAT' + elif string_value is not None: + value = string_value + kind = 'STRING' + else: + value = None + if value is not None: + PromptServer.instance.send_sync('impact-node-feedback', {'node_id': node_id, 'widget_name': widget_name, 'type': kind, 'value': value}) + return (signal,) +``` \ No newline at end of file diff --git a/docs/ImpactSimpleDetectorSEGS.md b/docs/ImpactSimpleDetectorSEGS.md new file mode 100644 index 0000000..31370f7 --- /dev/null +++ b/docs/ImpactSimpleDetectorSEGS.md @@ -0,0 +1,105 @@ +# Documentation +- Class name: SimpleDetectorForEach +- Category: ImpactPack/Detector +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SimpleDetectorForEach节点旨在使用边界框(bbox)检测器对单个图像执行对象检测。它处理输入图像以识别和定位对象,应用各种阈值和膨胀技术来完善检测过程。该节点能够与语义感知掩码(SAM)模型集成,以提高检测精度,并且也可以与分割检测器协同工作,以进行更详细的分析。输出是一组分段对象,每个对象都具有相关的元数据,如置信度分数和边界框。 + +# Input types +## Required +- bbox_detector + - bbox_detector参数对于检测过程至关重要,因为它定义了节点在输入图像中识别和定位对象的机制。它在节点的执行中起着关键作用,并直接影响检测结果的准确性和质量。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: impact.core.BBoxDetector +- image + - image参数是SimpleDetectorForEach节点的主要输入。它代表了节点将分析用于对象检测的图像数据。图像的质量和分辨率直接影响节点准确检测对象的能力。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- bbox_threshold + - bbox_threshold参数用于设置检测边界框的置信度水平。它是决定哪些检测到的对象被认为是有效的并因此包含在最终输出中的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- bbox_dilation + - bbox_dilation参数控制检测到的边界框的扩展。这是一个重要的参数,用于调整检测区域的大小,以更好地适应实际对象。 + - Comfy dtype: INT + - Python dtype: int +- crop_factor + - crop_factor参数用于确定围绕检测到的对象的裁剪区域的缩放因子。它影响裁剪区域的大小,因此影响分割中的细节水平。 + - Comfy dtype: FLOAT + - Python dtype: float +- drop_size + - drop_size参数指定检测过程中使用的步幅或步进大小。它影响检测的粒度,允许节点在不同尺度上检测对象。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- sub_threshold + - sub_threshold参数用于微调检测过程,特别是与分割检测器一起工作时。它通过为对象识别设置次级阈值来帮助细检测。 + - Comfy dtype: FLOAT + - Python dtype: float +- sub_dilation + - sub_dilation参数通过控制检测到的分割的膨胀来允许对分割过程进行调整。这对于细化检测到的对象的边界特别有用。 + - Comfy dtype: INT + - Python dtype: int +- sub_bbox_expansion + - sub_bbox_expansion参数用于在分割过程中扩展检测到的对象的边界框。它可以帮助确保整个对象包含在分割掩码内。 + - Comfy dtype: INT + - Python dtype: int +- sam_mask_hint_threshold + - sam_mask_hint_threshold参数用于与SAM模型集成以生成掩码时。它设置了使用检测到的分割的提示来创建更准确掩码的阈值。 + - Comfy dtype: FLOAT + - Python dtype: float +- post_dilation + - post_dilation参数在检测过程后对分割掩码应用最终膨胀。它可以用来平滑掩码的边缘,并确保更好地覆盖对象。 + - Comfy dtype: INT + - Python dtype: int +- sam_model_opt + - sam_model_opt参数是当使用SAM模型生成掩码时节点的可选配置。它指定用于创建更详细分割掩码的模型。 + - Comfy dtype: SAM_MODEL + - Python dtype: impact.core.SAMModel +- segm_detector_opt + - segm_detector_opt参数允许将分割检测器集成到检测过程中。它提供了一个选项,用于对某些类型的对象或场景使用更专业的检测器。 + - Comfy dtype: SEGM_DETECTOR + - Python dtype: impact.core.SegmDetector + +# Output types +- segs + - segs输出参数代表节点检测到的分段对象集合。每个分段包括裁剪后的图像、掩码、置信度分数、裁剪区域、边界框和标签等详细信息。 + - Comfy dtype: SEGS + - Python dtype: Tuple[impact.core.SEG, List[impact.core.SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SimpleDetectorForEach: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'bbox_detector': ('BBOX_DETECTOR',), 'image': ('IMAGE',), 'bbox_threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'bbox_dilation': ('INT', {'default': 0, 'min': -512, 'max': 512, 'step': 1}), 'crop_factor': ('FLOAT', {'default': 3.0, 'min': 1.0, 'max': 100, 'step': 0.1}), 'drop_size': ('INT', {'min': 1, 'max': MAX_RESOLUTION, 'step': 1, 'default': 10}), 'sub_threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'sub_dilation': ('INT', {'default': 0, 'min': -512, 'max': 512, 'step': 1}), 'sub_bbox_expansion': ('INT', {'default': 0, 'min': 0, 'max': 1000, 'step': 1}), 'sam_mask_hint_threshold': ('FLOAT', {'default': 0.7, 'min': 0.0, 'max': 1.0, 'step': 0.01})}, 'optional': {'post_dilation': ('INT', {'default': 0, 'min': -512, 'max': 512, 'step': 1}), 'sam_model_opt': ('SAM_MODEL',), 'segm_detector_opt': ('SEGM_DETECTOR',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detector' + + @staticmethod + def detect(bbox_detector, image, bbox_threshold, bbox_dilation, crop_factor, drop_size, sub_threshold, sub_dilation, sub_bbox_expansion, sam_mask_hint_threshold, post_dilation=0, sam_model_opt=None, segm_detector_opt=None, detailer_hook=None): + if len(image) > 1: + raise Exception('[Impact Pack] ERROR: SimpleDetectorForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.') + if segm_detector_opt is not None and hasattr(segm_detector_opt, 'bbox_detector') and (segm_detector_opt.bbox_detector == bbox_detector): + segs = segm_detector_opt.detect(image, sub_threshold, sub_dilation, crop_factor, drop_size, detailer_hook=detailer_hook) + else: + segs = bbox_detector.detect(image, bbox_threshold, bbox_dilation, crop_factor, drop_size, detailer_hook=detailer_hook) + if sam_model_opt is not None: + mask = core.make_sam_mask(sam_model_opt, segs, image, 'center-1', sub_dilation, sub_threshold, sub_bbox_expansion, sam_mask_hint_threshold, False) + segs = core.segs_bitwise_and_mask(segs, mask) + elif segm_detector_opt is not None: + segm_segs = segm_detector_opt.detect(image, sub_threshold, sub_dilation, crop_factor, drop_size, detailer_hook=detailer_hook) + mask = core.segs_to_combined_mask(segm_segs) + segs = core.segs_bitwise_and_mask(segs, mask) + segs = core.dilate_segs(segs, post_dilation) + return (segs,) + + def doit(self, bbox_detector, image, bbox_threshold, bbox_dilation, crop_factor, drop_size, sub_threshold, sub_dilation, sub_bbox_expansion, sam_mask_hint_threshold, post_dilation=0, sam_model_opt=None, segm_detector_opt=None): + return SimpleDetectorForEach.detect(bbox_detector, image, bbox_threshold, bbox_dilation, crop_factor, drop_size, sub_threshold, sub_dilation, sub_bbox_expansion, sam_mask_hint_threshold, post_dilation=post_dilation, sam_model_opt=sam_model_opt, segm_detector_opt=segm_detector_opt) +``` \ No newline at end of file diff --git a/docs/ImpactSimpleDetectorSEGSPipe.md b/docs/ImpactSimpleDetectorSEGSPipe.md new file mode 100644 index 0000000..2b0ed59 --- /dev/null +++ b/docs/ImpactSimpleDetectorSEGSPipe.md @@ -0,0 +1,82 @@ +# Documentation +- Class name: SimpleDetectorForEachPipe +- Category: ImpactPack/Detector +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SimpleDetectorForEachPipe节点旨在通过预定义的检测管道处理图像。它考虑了各种影响检测过程的参数,如边界框阈值和膨胀,以提高检测精度。该节点的功能集中在识别和定位图像中的物体,有助于实现图像分析和物体识别的更广泛目标。 + +# Input types +## Required +- detailer_pipe + - detailer_pipe参数对于节点的操作至关重要,因为它定义了应用于输入图像以进行检测的一系列操作或管道。它是一个关键组件,决定了节点的行为和检测结果的质量。 + - Comfy dtype: DETAILER_PIPE + - Python dtype: Tuple[Any, ...] +- image + - 图像参数是节点的主要输入,代表将被处理用于目标检测的数据。它的重要性在于它是检测操作的对象,节点的性能和结果直接依赖于输入图像的质量和特性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- bbox_threshold + - bbox_threshold参数决定了边界框被认为是有效检测的置信度水平。它在过滤出误报和确保只有高置信度的检测包含在输出中起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- bbox_dilation + - bbox_dilation参数控制应用于边界框的膨胀量,这有助于调整检测到的物体的大小。这个参数对于微调检测精度以更好地满足应用程序的具体要求很重要。 + - Comfy dtype: INT + - Python dtype: int +- crop_factor + - crop_factor参数用于确定将考虑用于检测的图像部分。它很重要,因为它可以帮助将检测过程集中在图像最相关的区域,可能提高节点操作的效率和精度。 + - Comfy dtype: FLOAT + - Python dtype: float +- drop_size + - drop_size参数指定了为检测目的将图像划分的网格单元的大小。它影响检测的粒度,对于确定检测结果的详细程度至关重要。 + - Comfy dtype: INT + - Python dtype: int +- sub_threshold + - sub_threshold参数设置了次要检测的阈值,可以用来通过专注于图像中的较小或不太突出的物体来细化检测过程。 + - Comfy dtype: FLOAT + - Python dtype: float +- sub_dilation + - sub_dilation参数允许通过应用膨胀来调整次要检测的大小。它对于控制检测到的物体的规模很重要,可以用来针对特定场景优化检测。 + - Comfy dtype: INT + - Python dtype: int +- sub_bbox_expansion + - sub_bbox_expansion参数控制次要检测的边界框的扩展。它很重要,因为它可以帮助捕获围绕较小物体的更广泛上下文,可能提高检测精度。 + - Comfy dtype: INT + - Python dtype: int +- sam_mask_hint_threshold + - sam_mask_hint_threshold参数用于定义由SAM模型生成的掩码提示的阈值。它对于控制分割掩码中的细节水平很重要,可以影响最终的检测结果。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- post_dilation + - post_dilation参数通过在主要检测过程之后允许膨胀,提供了对最终边界框的额外控制层。它可以用于针对特定用例微调检测结果。 + - Comfy dtype: INT + - Python dtype: Optional[int] + +# Output types +- segs + - segs输出参数代表在输入图像中检测到的分割区域。它很重要,因为它包含了检测过程的主要结果,为图像的组成和结构提供了宝贵的见解。 + - Comfy dtype: SEGS + - Python dtype: Tuple[torch.Tensor, ...] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SimpleDetectorForEachPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'detailer_pipe': ('DETAILER_PIPE',), 'image': ('IMAGE',), 'bbox_threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'bbox_dilation': ('INT', {'default': 0, 'min': -512, 'max': 512, 'step': 1}), 'crop_factor': ('FLOAT', {'default': 3.0, 'min': 1.0, 'max': 100, 'step': 0.1}), 'drop_size': ('INT', {'min': 1, 'max': MAX_RESOLUTION, 'step': 1, 'default': 10}), 'sub_threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'sub_dilation': ('INT', {'default': 0, 'min': -512, 'max': 512, 'step': 1}), 'sub_bbox_expansion': ('INT', {'default': 0, 'min': 0, 'max': 1000, 'step': 1}), 'sam_mask_hint_threshold': ('FLOAT', {'default': 0.7, 'min': 0.0, 'max': 1.0, 'step': 0.01})}, 'optional': {'post_dilation': ('INT', {'default': 0, 'min': -512, 'max': 512, 'step': 1})}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detector' + + def doit(self, detailer_pipe, image, bbox_threshold, bbox_dilation, crop_factor, drop_size, sub_threshold, sub_dilation, sub_bbox_expansion, sam_mask_hint_threshold, post_dilation=0): + if len(image) > 1: + raise Exception('[Impact Pack] ERROR: SimpleDetectorForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.') + (model, clip, vae, positive, negative, wildcard, bbox_detector, segm_detector_opt, sam_model_opt, detailer_hook, refiner_model, refiner_clip, refiner_positive, refiner_negative) = detailer_pipe + return SimpleDetectorForEach.detect(bbox_detector, image, bbox_threshold, bbox_dilation, crop_factor, drop_size, sub_threshold, sub_dilation, sub_bbox_expansion, sam_mask_hint_threshold, post_dilation=post_dilation, sam_model_opt=sam_model_opt, segm_detector_opt=segm_detector_opt, detailer_hook=detailer_hook) +``` \ No newline at end of file diff --git a/docs/ImpactSimpleDetectorSEGS_for_AD.md b/docs/ImpactSimpleDetectorSEGS_for_AD.md new file mode 100644 index 0000000..cbeb236 --- /dev/null +++ b/docs/ImpactSimpleDetectorSEGS_for_AD.md @@ -0,0 +1,185 @@ +# Documentation +- Class name: SimpleDetectorForAnimateDiff +- Category: ImpactPack/Detector +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SimpleDetectorForAnimateDiff 节点旨在检测和处理一系列图像中的动画差异。它利用边界框检测和可选的语义分割模型来识别和分割感兴趣的区域。该节点能够处理多种操作模式,包括使用单个帧作为参考、组合邻近帧或独立分割每个帧。它强调检测重大变化并创建掩码以隔离这些变化以进行进一步分析。 + +# Input types +## Required +- bbox_detector + - bbox_detector 参数对于在图像帧中最初检测边界框至关重要。它为进一步的分析和分割过程奠定了基础。bbox_detector 的有效性直接影响后续步骤的准确性,使其成为节点操作中的关键组件。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: torch.nn.Module +- image_frames + - image_frames 参数至关重要,因为它代表了节点的输入数据。它包含节点将分析的图像序列,以检测动画差异。image_frames 的质量和分辨率直接影响节点检测和准确分割变化的能力。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- bbox_threshold + - bbox_threshold 参数定义了边界框检测的置信度水平。它是决定哪些边界框被考虑进行进一步处理的关键因素。调整此阈值可以显著影响节点的检测能力和随后的分割结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- bbox_dilation + - bbox_dilation 参数用于扩大检测到的边界框的大小。这种扩展对于确保分割过程捕获整个感兴趣的区域非常重要,特别是当边界框靠近物体边缘或彼此靠近时。 + - Comfy dtype: INT + - Python dtype: int +- crop_factor + - crop_factor 参数非常重要,因为它决定了围绕检测区域裁剪图像的程度。这有助于将分析集中在图像最相关的部分,并减少周围区域的噪声。 + - Comfy dtype: FLOAT + - Python dtype: float +- drop_size + - drop_size 参数在分割过程中决定了被丢弃区域的大小。它在微调分割掩码中起着至关重要的作用,以确保它准确地表示感兴趣的区域,而没有不必要的细节。 + - Comfy dtype: INT + - Python dtype: int +- sub_threshold + - sub_threshold 参数对微调分割过程很重要。它有助于确定分割掩码中捕获的细节水平,在精度和包含相关信息之间取得平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- sub_dilation + - sub_dilation 参数用于控制分割掩码的扩展。它是确保掩码完全封装感兴趣的区域的关键因素,考虑到初始检测中可能存在的任何潜在不准确性。 + - Comfy dtype: INT + - Python dtype: int +- sub_bbox_expansion + - sub_bbox_expansion 参数允许扩展用于分割过程中的边界框。这对于捕获可能比初始检测建议的区域略大的区域特别有用,确保更全面的分割。 + - Comfy dtype: INT + - Python dtype: int +- sam_mask_hint_threshold + - sam_mask_hint_threshold 参数与 SAM(语义注释模型)一起使用,以细化分割掩码。它有助于控制掩码中的细节水平,确保掩码与所需的感兴趣区域紧密匹配。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- SEGS + - 输出 SEGS(语义注释片段)参数表示节点分析的结果。它包含在输入图像帧中识别的感兴趣的分段区域。这些片段对于进一步的处理和分析至关重要,例如跟踪变化或识别动画中的特定特征。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SimpleDetectorForAnimateDiff: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'bbox_detector': ('BBOX_DETECTOR',), 'image_frames': ('IMAGE',), 'bbox_threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'bbox_dilation': ('INT', {'default': 0, 'min': -255, 'max': 255, 'step': 1}), 'crop_factor': ('FLOAT', {'default': 3.0, 'min': 1.0, 'max': 100, 'step': 0.1}), 'drop_size': ('INT', {'min': 1, 'max': MAX_RESOLUTION, 'step': 1, 'default': 10}), 'sub_threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'sub_dilation': ('INT', {'default': 0, 'min': -255, 'max': 255, 'step': 1}), 'sub_bbox_expansion': ('INT', {'default': 0, 'min': 0, 'max': 1000, 'step': 1}), 'sam_mask_hint_threshold': ('FLOAT', {'default': 0.7, 'min': 0.0, 'max': 1.0, 'step': 0.01})}, 'optional': {'masking_mode': (['Pivot SEGS', 'Combine neighboring frames', "Don't combine"],), 'segs_pivot': (['Combined mask', '1st frame mask'],), 'sam_model_opt': ('SAM_MODEL',), 'segm_detector_opt': ('SEGM_DETECTOR',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detector' + + @staticmethod + def detect(bbox_detector, image_frames, bbox_threshold, bbox_dilation, crop_factor, drop_size, sub_threshold, sub_dilation, sub_bbox_expansion, sam_mask_hint_threshold, masking_mode='Pivot SEGS', segs_pivot='Combined mask', sam_model_opt=None, segm_detector_opt=None): + h = image_frames.shape[1] + w = image_frames.shape[2] + segs_by_frames = [] + for image in image_frames: + image = image.unsqueeze(0) + segs = bbox_detector.detect(image, bbox_threshold, bbox_dilation, crop_factor, drop_size) + if sam_model_opt is not None: + mask = core.make_sam_mask(sam_model_opt, segs, image, 'center-1', sub_dilation, sub_threshold, sub_bbox_expansion, sam_mask_hint_threshold, False) + segs = core.segs_bitwise_and_mask(segs, mask) + elif segm_detector_opt is not None: + segm_segs = segm_detector_opt.detect(image, sub_threshold, sub_dilation, crop_factor, drop_size) + mask = core.segs_to_combined_mask(segm_segs) + segs = core.segs_bitwise_and_mask(segs, mask) + segs_by_frames.append(segs) + + def get_masked_frames(): + masks_by_frame = [] + for (i, segs) in enumerate(segs_by_frames): + masks_in_frame = segs_nodes.SEGSToMaskList().doit(segs)[0] + current_frame_mask = (masks_in_frame[0] * 255).to(torch.uint8) + for mask in masks_in_frame[1:]: + current_frame_mask |= (mask * 255).to(torch.uint8) + current_frame_mask = (current_frame_mask / 255.0).to(torch.float32) + current_frame_mask = utils.to_binary_mask(current_frame_mask, 0.1)[0] + masks_by_frame.append(current_frame_mask) + return masks_by_frame + + def get_empty_mask(): + return torch.zeros((h, w), dtype=torch.float32, device='cpu') + + def get_neighboring_mask_at(i, masks_by_frame): + prv = masks_by_frame[i - 1] if i > 1 else get_empty_mask() + cur = masks_by_frame[i] + nxt = masks_by_frame[i - 1] if i > 1 else get_empty_mask() + prv = prv if prv is not None else get_empty_mask() + cur = cur.clone() if cur is not None else get_empty_mask() + nxt = nxt if nxt is not None else get_empty_mask() + return (prv, cur, nxt) + + def get_merged_neighboring_mask(masks_by_frame): + if len(masks_by_frame) <= 1: + return masks_by_frame + result = [] + for i in range(0, len(masks_by_frame)): + (prv, cur, nxt) = get_neighboring_mask_at(i, masks_by_frame) + cur = (cur * 255).to(torch.uint8) + cur |= (prv * 255).to(torch.uint8) + cur |= (nxt * 255).to(torch.uint8) + cur = (cur / 255.0).to(torch.float32) + cur = utils.to_binary_mask(cur, 0.1)[0] + result.append(cur) + return result + + def get_whole_merged_mask(): + all_masks = [] + for segs in segs_by_frames: + all_masks += segs_nodes.SEGSToMaskList().doit(segs)[0] + merged_mask = (all_masks[0] * 255).to(torch.uint8) + for mask in all_masks[1:]: + merged_mask |= (mask * 255).to(torch.uint8) + merged_mask = (merged_mask / 255.0).to(torch.float32) + merged_mask = utils.to_binary_mask(merged_mask, 0.1)[0] + return merged_mask + + def get_pivot_segs(): + if segs_pivot == '1st frame mask': + return segs_by_frames[0][1] + else: + merged_mask = get_whole_merged_mask() + return segs_nodes.MaskToSEGS().doit(merged_mask, False, crop_factor, False, drop_size, contour_fill=True)[0] + + def get_merged_neighboring_segs(): + pivot_segs = get_pivot_segs() + masks_by_frame = get_masked_frames() + masks_by_frame = get_merged_neighboring_mask(masks_by_frame) + new_segs = [] + for seg in pivot_segs[1]: + cropped_mask = torch.zeros(seg.cropped_mask.shape, dtype=torch.float32, device='cpu').unsqueeze(0) + pivot_mask = torch.from_numpy(seg.cropped_mask) + (x1, y1, x2, y2) = seg.crop_region + for mask in masks_by_frame: + cropped_mask_at_frame = (mask[y1:y2, x1:x2] * pivot_mask).unsqueeze(0) + cropped_mask = torch.cat((cropped_mask, cropped_mask_at_frame), dim=0) + if len(cropped_mask) > 1: + cropped_mask = cropped_mask[1:] + new_seg = SEG(seg.cropped_image, cropped_mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, seg.control_net_wrapper) + new_segs.append(new_seg) + return (pivot_segs[0], new_segs) + + def get_separated_segs(): + pivot_segs = get_pivot_segs() + masks_by_frame = get_masked_frames() + new_segs = [] + for seg in pivot_segs[1]: + cropped_mask = torch.zeros(seg.cropped_mask.shape, dtype=torch.float32, device='cpu').unsqueeze(0) + (x1, y1, x2, y2) = seg.crop_region + for mask in masks_by_frame: + cropped_mask_at_frame = mask[y1:y2, x1:x2] + cropped_mask = torch.cat((cropped_mask, cropped_mask_at_frame), dim=0) + new_seg = SEG(seg.cropped_image, cropped_mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, seg.control_net_wrapper) + new_segs.append(new_seg) + return (pivot_segs[0], new_segs) + if masking_mode == 'Pivot SEGS': + return (get_pivot_segs(),) + elif masking_mode == 'Combine neighboring frames': + return (get_merged_neighboring_segs(),) + else: + return (get_separated_segs(),) + + def doit(self, bbox_detector, image_frames, bbox_threshold, bbox_dilation, crop_factor, drop_size, sub_threshold, sub_dilation, sub_bbox_expansion, sam_mask_hint_threshold, masking_mode='Pivot SEGS', segs_pivot='Combined mask', sam_model_opt=None, segm_detector_opt=None): + return SimpleDetectorForAnimateDiff.detect(bbox_detector, image_frames, bbox_threshold, bbox_dilation, crop_factor, drop_size, sub_threshold, sub_dilation, sub_bbox_expansion, sam_mask_hint_threshold, masking_mode, segs_pivot, sam_model_opt, segm_detector_opt) +``` \ No newline at end of file diff --git a/docs/ImpactSleep.md b/docs/ImpactSleep.md new file mode 100644 index 0000000..43d0ff3 --- /dev/null +++ b/docs/ImpactSleep.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: ImpactSleep +- Category: ImpactPack/Logic/_for_test +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactSleep节点的'doit'方法旨在引入执行流程中的延迟。它接受一个信号和一个以秒为单位的持续时间,然后在指定的时间内暂停进程,允许其他任务被调度或并发执行。这个节点特别适用于控制更大工作流中操作的时间。 + +# Input types +## Required +- signal + - ‘signal’参数是一个通用输入,可用于将控制或状态信息传递到节点中。它很重要,因为它的值可能影响工作流中随后的步骤。 + - Comfy dtype: any_typ + - Python dtype: Any +- seconds + - ‘seconds’参数指定了节点将引入的延迟持续时间。对于时间敏感的操作来说至关重要,并且可以影响系统的整体性能。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- signal_opt + - ‘signal_opt’输出在引入延迟后提供原始信号,确保工作流可以以相同的控制或状态信息无缝继续。 + - Comfy dtype: any_typ + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactSleep: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'signal': (any_typ,), 'seconds': ('FLOAT', {'default': 0.5, 'min': 0, 'max': 3600})}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic/_for_test' + RETURN_TYPES = (any_typ,) + RETURN_NAMES = ('signal_opt',) + OUTPUT_NODE = True + + def doit(self, signal, seconds): + time.sleep(seconds) + return (signal,) +``` \ No newline at end of file diff --git a/docs/ImpactStringSelector.md b/docs/ImpactStringSelector.md new file mode 100644 index 0000000..c955fa6 --- /dev/null +++ b/docs/ImpactStringSelector.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: StringSelector +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +StringSelector节点旨在处理并从给定输入中选择特定的字符串。它可以处理多行字符串,并提供启用或禁用多行处理的选项。该节点的主要目的是根据选择标准提取特定的字符串,为ImpactPack实用程序套件内提供一种多功能的字符串操作方法。 + +# Input types +## Required +- strings + - ‘strings’参数是节点的主要输入,包含要处理的字符串数据。它在节点操作中起着关键作用,因为它是将从中提取选定字符串的来源。多行选项允许处理跨越多行的字符串,增强了节点处理不同字符串格式的多功能性。 + - Comfy dtype: STRING + - Python dtype: str +- select + - ‘select’参数用于指定要从输入中选择的字符串或行的索引。它对于确定输入数据的哪一部分将是节点的输出至关重要。选择索引应用于行或元素的数量的模运算,确保如果它超过可用选项,它将循环。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- multiline + - ‘multiline’参数决定节点是否应将输入字符串作为单个实体处理,还是作为多行处理。启用时,它允许节点处理带有换行符的字符串,并根据这些行中的内容进行选择。此参数显著影响节点的行为和字符串选择过程的结果。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- selected_string + - ‘selected_string’输出代表了基于输入参数选择的字符串。它是节点处理的成果,反映了节点执行的字符串操作的结果。这个输出很重要,因为它是节点操作的最终产品。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class StringSelector: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'strings': ('STRING', {'multiline': True}), 'multiline': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'}), 'select': ('INT', {'min': 0, 'max': sys.maxsize, 'step': 1, 'default': 0})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, strings, multiline, select): + lines = strings.split('\n') + if multiline: + result = [] + current_string = '' + for line in lines: + if line.startswith('#'): + if current_string: + result.append(current_string.strip()) + current_string = '' + current_string += line + '\n' + if current_string: + result.append(current_string.strip()) + if len(result) == 0: + selected = strings + else: + selected = result[select % len(result)] + if selected.startswith('#'): + selected = selected[1:] + elif len(lines) == 0: + selected = strings + else: + selected = lines[select % len(lines)] + return (selected,) +``` \ No newline at end of file diff --git a/docs/ImpactSwitch.md b/docs/ImpactSwitch.md new file mode 100644 index 0000000..0710d15 --- /dev/null +++ b/docs/ImpactSwitch.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: GeneralSwitch +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +GeneralSwitch节点旨在通过选择特定索引的输入来管理工作流中的数据流。它通过评估提供的索引并确定相应的输入进行处理来操作。该节点在系统中的决策过程中发挥关键作用,确保正确的数据被引导到后续操作中。 + +# Input types +## Required +- select + - 'select'参数至关重要,因为它决定了将由节点处理的输入。它作为决策因素,允许节点从可用选项中识别并选择适当的输入。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- sel_mode + - 'sel_mode'参数用于确定选择是基于提示还是执行上下文。它在节点解释和对选择标准做出反应的方式上提供了灵活性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- input1 + - 'input1'参数是一个可选输入,可以提供给节点。它允许处理的数据类型更加灵活,增强了节点在各种工作流中的适应性。 + - Comfy dtype: ANY + - Python dtype: Any +- unique_id + - 'unique_id'参数是一个隐藏字段,有助于在工作流中识别特定节点。它对于内部跟踪很重要,并确保节点的操作与其在工作流中的位置正确关联。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +- extra_pnginfo + - 'extra_pnginfo'参数包含与节点操作相关的额外信息,如工作流详细信息。它在内部用于促进节点与更广泛系统的交互。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, Any] + +# Output types +- selected_value + - 'selected_value'输出代表了节点根据提供的索引选择的数据。这是一个关键的输出,因为它决定了数据流向工作流中后续节点的过程。 + - Comfy dtype: ANY + - Python dtype: Any +- selected_label + - 'selected_label'输出提供了与选定输入关联的标签。这对于调试和提供节点决策过程的上下文非常有用。 + - Comfy dtype: STRING + - Python dtype: str +- selected_index + - 'selected_index'输出指示用于选择输入的索引。它作为节点所做的决定的记录,对于审计和跟踪目的可能很重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GeneralSwitch: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'select': ('INT', {'default': 1, 'min': 1, 'max': 999999, 'step': 1}), 'sel_mode': ('BOOLEAN', {'default': True, 'label_on': 'select_on_prompt', 'label_off': 'select_on_execution', 'forceInput': False})}, 'optional': {'input1': (any_typ,)}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = (any_typ, 'STRING', 'INT') + RETURN_NAMES = ('selected_value', 'selected_label', 'selected_index') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, *args, **kwargs): + selected_index = int(kwargs['select']) + input_name = f'input{selected_index}' + selected_label = input_name + node_id = kwargs['unique_id'] + nodelist = kwargs['extra_pnginfo']['workflow']['nodes'] + for node in nodelist: + if str(node['id']) == node_id: + inputs = node['inputs'] + for slot in inputs: + if slot['name'] == input_name and 'label' in slot: + selected_label = slot['label'] + break + if input_name in kwargs: + return (kwargs[input_name], selected_label, selected_index) + else: + print(f'ImpactSwitch: invalid select index (ignored)') + return (None, '', selected_index) +``` \ No newline at end of file diff --git a/docs/ImpactValueReceiver.md b/docs/ImpactValueReceiver.md new file mode 100644 index 0000000..bb6117a --- /dev/null +++ b/docs/ImpactValueReceiver.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: ImpactValueReceiver +- Category: ImpactPack/Logic +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactValueReceiver节点的'doit'方法旨在根据指定的类型处理和转换输入值。它在确保输入系统的数据格式正确方面发挥着关键作用,从而促进数据在ImpactPack框架内的无缝集成和运行。 + +# Input types +## Required +- typ + - 参数'typ'指示'doit'方法将对输入'value'执行哪种类型的转换。它对节点的执行至关重要,因为它决定了输入数据的处理和转换方式。 + - Comfy dtype: STRING + - Python dtype: str +- value + - 参数'value'表示将由'doit'方法转换的数据。正确输入对于节点产生预期输出至关重要,因为它直接影响节点的操作和产生的结果。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- link_id + - 参数'link_id'在系统中作为连接的可选标识符。它可以用于跟踪或引用特定的数据点,并有助于整体组织和管理节点的执行。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- converted_value + - 输出参数'converted_value'代表'doit'方法转换过程的结果。它非常重要,因为它反映了节点根据指定类型准确转换输入数据的能力,确保了输出的完整性和可用性。 + - Comfy dtype: COMBO[STRING, INT, FLOAT, BOOLEAN] + - Python dtype: Union[str, int, float, bool] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactValueReceiver: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'typ': (['STRING', 'INT', 'FLOAT', 'BOOLEAN'],), 'value': ('STRING', {'default': ''}), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1})}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic' + RETURN_TYPES = (any_typ,) + + def doit(self, typ, value, link_id=0): + if typ == 'INT': + return (int(value),) + elif typ == 'FLOAT': + return (float(value),) + elif typ == 'BOOLEAN': + return (value.lower() == 'true',) + else: + return (value,) +``` \ No newline at end of file diff --git a/docs/ImpactValueSender.md b/docs/ImpactValueSender.md new file mode 100644 index 0000000..4fffbf3 --- /dev/null +++ b/docs/ImpactValueSender.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: ImpactValueSender +- Category: ImpactPack/Logic +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +“ImpactValueSender”节点旨在将影响值传输到指定的服务器。它是数据流中的关键组件,确保影响值被有效地传达以进行进一步的处理或分析。 + +# Input types +## Required +- value + - “value”参数对于节点的操作至关重要,因为它代表了要发送的影响值。它在节点的功能中起着核心作用,决定了将传输的数据。 + - Comfy dtype: any_typ + - Python dtype: Any +## Optional +- link_id + - “link_id”参数是连接的可选标识符。它有助于区分不同的数据流或连接,增强了节点管理和组织传输过程的能力。 + - Comfy dtype: INT + - Python dtype: int +- signal_opt + - “signal_opt”参数是一个可选输入,可以用来修改节点的行为。它为传输过程提供了额外的控制,允许根据特定需求进行定制。 + - Comfy dtype: any_typ + - Python dtype: Any + +# Output types +- signal + - “signal”输出表示传输过程的结果。它是节点成功操作的关键指标,可以用于进一步处理或作为系统中的反馈。 + - Comfy dtype: any_typ + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactValueSender: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'value': (any_typ,), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1})}, 'optional': {'signal_opt': (any_typ,)}} + OUTPUT_NODE = True + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Logic' + RETURN_TYPES = (any_typ,) + RETURN_NAMES = ('signal',) + + def doit(self, value, link_id=0, signal_opt=None): + PromptServer.instance.send_sync('value-send', {'link_id': link_id, 'value': value}) + return (signal_opt,) +``` \ No newline at end of file diff --git a/docs/ImpactWildcardEncode.md b/docs/ImpactWildcardEncode.md new file mode 100644 index 0000000..633987a --- /dev/null +++ b/docs/ImpactWildcardEncode.md @@ -0,0 +1,90 @@ +# Documentation +- Class name: ImpactWildcardEncode +- Category: ImpactPack/Prompt +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +“ImpactWildcardEncode”节点旨在将文本数据与模型和剪辑进行整合和操作。它专门处理包含通配符的文本,并利用LoRA等高级技术进行文本修改。此节点对于动态文本生成和模型调节至关重要的应用场景是核心所在。 + +# Input types +## Required +- model + - “model”参数对于节点的操作至关重要,因为它定义了将用于文本处理的模型。这是一个基本组件,直接影响节点生成和操作文本数据的能力。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - “clip”参数是必需的,因为它代表将与文本一起处理的多媒体剪辑。它在节点如何整合文本和多媒体内容中扮演着重要角色。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- wildcard_text + - “wildcard_text”参数允许在文本中包含占位符,这些占位符可以根据上下文动态填充。对于需要灵活文本输入的应用来说,这是一个关键特性。 + - Comfy dtype: STRING + - Python dtype: str +- populated_text + - “populated_text”参数是待处理的实际文本所在的位置。它很重要,因为它是文本操作的主要输入,直接影响输出。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- mode + - “mode”参数决定文本将被填充还是保持固定。这是一个重要的开关,它根据期望的结果改变节点的行为。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- Select to add LoRA + - “Select to add LoRA”参数允许向文本中添加LoRA,这可以显著增强文本在模型上下文中的表现力和适应性。 + - Comfy dtype: COMBO[Select the LoRA to add to the text] + - Python dtype: str +- Select to add Wildcard + - “Select to add Wildcard”参数用于向文本中引入通配符,提供了一种动态文本插入和修改的机制。 + - Comfy dtype: COMBO[Select the Wildcard to add to the text] + - Python dtype: str +- seed + - “seed”参数对于确保节点操作的可重复性很重要,特别是在处理随机过程时。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- model + - “model”输出代表处理文本和剪辑后的更新模型,可供进一步使用或分析。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - “clip”输出是已与文本数据集成的已处理多媒体剪辑。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- conditioning + - “conditioning”输出提供了从文本和剪辑派生的上下文信息,可用于指导进一步的模型操作。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- populated_text + - “populated_text”输出是所有处理步骤之后的最终文本,反映了节点执行期间所做的动态更改。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactWildcardEncode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'wildcard_text': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'populated_text': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'mode': ('BOOLEAN', {'default': True, 'label_on': 'Populate', 'label_off': 'Fixed'}), 'Select to add LoRA': (['Select the LoRA to add to the text'] + folder_paths.get_filename_list('loras'),), 'Select to add Wildcard': (['Select the Wildcard to add to the text'],), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + CATEGORY = 'ImpactPack/Prompt' + RETURN_TYPES = ('MODEL', 'CLIP', 'CONDITIONING', 'STRING') + RETURN_NAMES = ('model', 'clip', 'conditioning', 'populated_text') + FUNCTION = 'doit' + + @staticmethod + def process_with_loras(**kwargs): + return impact.wildcards.process_with_loras(**kwargs) + + @staticmethod + def get_wildcard_list(): + return impact.wildcards.get_wildcard_list() + + def doit(self, *args, **kwargs): + populated = kwargs['populated_text'] + (model, clip, conditioning) = impact.wildcards.process_with_loras(populated, kwargs['model'], kwargs['clip']) + return (model, clip, conditioning, populated) +``` \ No newline at end of file diff --git a/docs/ImpactWildcardProcessor.md b/docs/ImpactWildcardProcessor.md new file mode 100644 index 0000000..2d84777 --- /dev/null +++ b/docs/ImpactWildcardProcessor.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: ImpactWildcardProcessor +- Category: ImpactPack/Prompt +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ImpactWildcardProcessor节点旨在管理和处理文本输入中的通配符。它基于给定模式促进通配符的动态插入或填充,增强了文本操作任务的灵活性。该节点在制作能够通过利用通配符概念适应各种输入的提示中发挥关键作用。 + +# Input types +## Required +- wildcard_text + - 通配符文本参数对于定义文本中的占位符至关重要,这些占位符可以动态填充。它影响最终输出文本的结构,允许根据特定需求定制提示。 + - Comfy dtype: STRING + - Python dtype: str +- populated_text + - 填充后的文本作为可能包含通配符的初始输入文本。这个参数至关重要,因为它决定了将处理通配符的基础文本,影响通配符处理后文本的结果。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- mode + - 模式参数决定是否应该填充通配符或保持固定。它很重要,因为它控制了通配符处理的行为,允许动态内容生成或保留静态文本。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- seed + - 种子参数用于初始化随机数生成器,确保在处理通配符时结果可重复。它在维护节点多次执行时的一致性方面发挥着重要作用,特别适用于调试和测试目的。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- processed_text + - 处理后的文本是ImpactWildcardProcessor节点的主要输出,代表了在指定模式下所有通配符已被适当填充或保持原样后的最终文本。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImpactWildcardProcessor: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'wildcard_text': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'populated_text': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'mode': ('BOOLEAN', {'default': True, 'label_on': 'Populate', 'label_off': 'Fixed'}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'Select to add Wildcard': (['Select the Wildcard to add to the text'],)}} + CATEGORY = 'ImpactPack/Prompt' + RETURN_TYPES = ('STRING',) + FUNCTION = 'doit' + + @staticmethod + def process(**kwargs): + return impact.wildcards.process(**kwargs) + + def doit(self, *args, **kwargs): + populated_text = kwargs['populated_text'] + return (populated_text,) +``` \ No newline at end of file diff --git a/docs/Init FizzFrame.md b/docs/Init FizzFrame.md new file mode 100644 index 0000000..e13bc35 --- /dev/null +++ b/docs/Init FizzFrame.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: InitNodeFrame +- Category: FizzNodes 📅🅕🅝/FrameNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +方法 `create_frame` 负责初始化和管理节点中的框架。它通过结合正面和负面文本输入以及可选的一般情感和先前框架的上下文来构建一个新的框架。该节点的功能集中在创建一个结构化表示,封装文本数据,以便在框架内进行进一步的处理和分析。 + +# Input types +## Required +- frame + - 参数 'frame' 对于标识节点操作中的具体框架至关重要。它在组织和区分不同框架中起着关键作用,因此影响节点的执行和它创建的结构化表示。 + - Comfy dtype: INT + - Python dtype: int +- positive_text + - 参数 'positive_text' 是定义框架积极情感的关键组成部分。它显著影响节点处理和表示文本数据中情感的能力,塑造了整体情感分析的结果。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- negative_text + - 虽然 'negative_text' 参数是可选的,但它通过提供负面上下文,有助于全面的情感分析。它丰富了节点对情感谱系的理解,提高了情感表示的准确性。 + - Comfy dtype: STRING + - Python dtype: str +- general_positive + - 参数 'general_positive' 允许包含可以与框架关联的一般性正面陈述。它通过将更广泛的正面情感融入框架的上下文中,为情感分析增添了深度。 + - Comfy dtype: STRING + - Python dtype: str +- general_negative + - 参数 'general_negative' 用于包含可能影响框架的一般性负面情感。它对于提供情感的平衡视角很重要,确保节点能够捕捉到情感表达的全部范围。 + - Comfy dtype: STRING + - Python dtype: str +- previous_frame + - 参数 'previous_frame' 用于引用先前的框架,允许节点继承并建立在其上下文之上。它对于在节点操作中保持框架之间的连续性和一致性具有重要意义。 + - Comfy dtype: FIZZFRAME + - Python dtype: FIZZFRAME +- clip + - 参数 'clip' 对于将文本数据编码成节点可以处理的标记化格式至关重要。它在将原始文本转换为情感分析的结构化表示中起着工具性作用。 + - Comfy dtype: CLIP + - Python dtype: CLIP + +# Output types +- FIZZFRAME + - 输出 'FIZZFRAME' 提供了新创建的框架及其相关的情感和上下文。它很重要,因为它代表了节点操作的成果,封装了结构化数据以供进一步使用。 + - Comfy dtype: FIZZFRAME + - Python dtype: FIZZFRAME +- CONDITIONING + - 输出 'CONDITIONING' 包括从文本输入派生的编码正面和负面调节数据。它对于情感分析至关重要,因为它提供了下游处理所需的结构化表示。 + - Comfy dtype: COMBO[torch.Tensor, Dict[str, torch.Tensor]] + - Python dtype: Tuple[torch.Tensor, Dict[str, torch.Tensor]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class InitNodeFrame: + + def __init__(self): + self.frames = {} + self.thisFrame = {} + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'frame': ('INT', {'default': 0, 'min': 0}), 'positive_text': ('STRING', {'multiline': True})}, 'optional': {'negative_text': ('STRING', {'multiline': True}), 'general_positive': ('STRING', {'multiline': True}), 'general_negative': ('STRING', {'multiline': True}), 'previous_frame': ('FIZZFRAME', {'forceInput': True}), 'clip': ('CLIP',)}} + RETURN_TYPES = ('FIZZFRAME', 'CONDITIONING', 'CONDITIONING') + FUNCTION = 'create_frame' + CATEGORY = 'FizzNodes 📅🅕🅝/FrameNodes' + + def create_frame(self, frame, positive_text, negative_text=None, general_positive=None, general_negative=None, previous_frame=None, clip=None): + new_frame = {'positive_text': positive_text, 'negative_text': negative_text} + if previous_frame: + prev_frame = previous_frame.thisFrame + new_frame['general_positive'] = prev_frame['general_positive'] + new_frame['general_negative'] = prev_frame['general_negative'] + new_frame['clip'] = prev_frame['clip'] + self.frames = previous_frame.frames + if general_positive: + new_frame['general_positive'] = general_positive + if general_negative: + new_frame['general_negative'] = general_negative + new_positive_text = f"{positive_text}, {new_frame['general_positive']}" + new_negative_text = f"{negative_text}, {new_frame['general_negative']}" + if clip: + new_frame['clip'] = clip + pos_tokens = new_frame['clip'].tokenize(new_positive_text) + (pos_cond, pos_pooled) = new_frame['clip'].encode_from_tokens(pos_tokens, return_pooled=True) + new_frame['pos_conditioning'] = {'cond': pos_cond, 'pooled': pos_pooled} + neg_tokens = new_frame['clip'].tokenize(new_negative_text) + (neg_cond, neg_pooled) = new_frame['clip'].encode_from_tokens(neg_tokens, return_pooled=True) + new_frame['neg_conditioning'] = {'cond': neg_cond, 'pooled': neg_pooled} + self.frames[frame] = new_frame + self.thisFrame = new_frame + return (self, [[pos_cond, {'pooled_output': pos_pooled}]], [[neg_cond, {'pooled_output': neg_pooled}]]) +``` \ No newline at end of file diff --git a/docs/InjectNoiseToLatent.md b/docs/InjectNoiseToLatent.md new file mode 100644 index 0000000..0648a8c --- /dev/null +++ b/docs/InjectNoiseToLatent.md @@ -0,0 +1,84 @@ +# Documentation +- Class name: InjectNoiseToLatent +- Category: KJNodes/noise +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +InjectNoiseToLatent节点旨在将噪声引入潜在空间表示中,从而模拟噪声对生成过程的影响。它通过向潜在样本添加指定强度的噪声来操作,可以选择性地对结果进行归一化并应用掩码以控制受噪声影响的区域。该节点对于涉及对噪声的鲁棒性实验和探索生成模型对输入扰动的敏感性至关重要。 + +# Input types +## Required +- latents + - latents参数至关重要,因为它包含将要进行噪声注入的原始潜在空间表示。这是一个关键输入,它决定了节点处理的数据的基本结构。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- strength + - strength参数决定了注入到潜在样本中的噪声的强度。它在确定应用于数据的扰动程度中起着重要作用,从而影响最终输出。 + - Comfy dtype: FLOAT + - Python dtype: float +- noise + - noise输入表示要添加到潜在空间的噪声模式。它是噪声注入过程中的一个关键组成部分,影响噪声在最终输出中的表现形式。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +## Optional +- normalize + - 当normalize参数设置为True时,将对噪声化的潜在样本进行归一化,确保噪声注入后分布不会过度偏斜。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- mask + - 可选的mask参数可用于指定应在潜在空间的哪些区域应用噪声。它提供了一种控制噪声空间分布的手段。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- mix_randn_amount + - mix_randn_amount参数允许将随机噪声与现有的噪声模式混合,提供了一种将额外变异性引入噪声的方法。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - 提供的seed参数确保了噪声生成过程中的随机性是可复现的,这对于一致的实验结果非常有用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- latents + - 输出的latents是经过噪声注入过程修改后的潜在空间表示。它们很重要,因为它们为后续的生成步骤奠定了基础。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class InjectNoiseToLatent: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latents': ('LATENT',), 'strength': ('FLOAT', {'default': 0.1, 'min': 0.0, 'max': 200.0, 'step': 0.0001}), 'noise': ('LATENT',), 'normalize': ('BOOLEAN', {'default': False}), 'average': ('BOOLEAN', {'default': False})}, 'optional': {'mask': ('MASK',), 'mix_randn_amount': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1000.0, 'step': 0.001}), 'seed': ('INT', {'default': 123, 'min': 0, 'max': 18446744073709551615, 'step': 1})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'injectnoise' + CATEGORY = 'KJNodes/noise' + + def injectnoise(self, latents, strength, noise, normalize, average, mix_randn_amount=0, seed=None, mask=None): + samples = latents.copy() + if latents['samples'].shape != noise['samples'].shape: + raise ValueError('InjectNoiseToLatent: Latent and noise must have the same shape') + if average: + noised = (samples['samples'].clone() + noise['samples'].clone()) / 2 + else: + noised = samples['samples'].clone() + noise['samples'].clone() * strength + if normalize: + noised = noised / noised.std() + if mask is not None: + mask = torch.nn.functional.interpolate(mask.reshape((-1, 1, mask.shape[-2], mask.shape[-1])), size=(noised.shape[2], noised.shape[3]), mode='bilinear') + mask = mask.expand((-1, noised.shape[1], -1, -1)) + if mask.shape[0] < noised.shape[0]: + mask = mask.repeat((noised.shape[0] - 1) // mask.shape[0] + 1, 1, 1, 1)[:noised.shape[0]] + noised = mask * noised + (1 - mask) * latents['samples'] + if mix_randn_amount > 0: + if seed is not None: + torch.manual_seed(seed) + rand_noise = torch.randn_like(noised) + noised = ((1 - mix_randn_amount) * noised + mix_randn_amount * rand_noise) / (mix_randn_amount ** 2 + (1 - mix_randn_amount) ** 2) ** 0.5 + samples['samples'] = noised + return (samples,) +``` \ No newline at end of file diff --git a/docs/InpaintPreprocessor_Provider_for_SEGS %2F%2FInspire.md b/docs/InpaintPreprocessor_Provider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..6857b49 --- /dev/null +++ b/docs/InpaintPreprocessor_Provider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: InpaintPreprocessor_Provider_for_SEGS +- Category: InspirePack/SEGS/ControlNet +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点促进了图像修复过程,该过程用于填充图像中缺失或被遮罩的区域,并用与周围上下文相匹配的内容填充。它利用ControlNet辅助处理器的修复能力,与ComfyUI生态系统无缝集成。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它提供了将执行修复操作的输入图像。输入图像的质量和分辨率直接影响修复过程的有效性。 + - Comfy dtype: COMBO[torch.Tensor] + - Python dtype: torch.Tensor +## Optional +- mask + - 遮罩参数,当提供时,指定了需要进行修复的图像区域。它是一个二值遮罩,有助于引导修复过程专注于目标区域。 + - Comfy dtype: COMBO[torch.Tensor] + - Python dtype: torch.Tensor + +# Output types +- output + - 修复过程的输出是一个图像,其中遮罩区域已经被填充。这个图像现在有了更完整的原始场景表示,修复的内容与图像的其余部分自然融合。 + - Comfy dtype: COMBO[torch.Tensor] + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class InpaintPreprocessor_Provider_for_SEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}} + RETURN_TYPES = ('SEGS_PREPROCESSOR',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/SEGS/ControlNet' + + def doit(self): + obj = InpaintPreprocessor_wrapper() + return (obj,) +``` \ No newline at end of file diff --git a/docs/Input Trigger.md b/docs/Input Trigger.md new file mode 100644 index 0000000..c8347a2 --- /dev/null +++ b/docs/Input Trigger.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: Trigger +- Category: 😺dzNodes +- Output node: True +- Repo Ref: https://github.com/chflame163/ComfyUI_MSSpeech_TTS + +该节点充当条件门,评估输入以确定它们是否满足指定条件,从而控制数据流经系统。 + +# Input types +## Required +- always_true + - 一个布尔标志,当为真时,直接触发节点的动作。它是一个关键参数,因为它代表了节点激活的主要条件。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- anything + - 一个可选输入,如果存在,可以有助于触发节点,为节点激活所需的条件增加了灵活性。 + - Comfy dtype: ANY + - Python dtype: Any + +# Output types +- ret + - 节点评估的结果,指示激活条件是否已满足。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Trigger: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'always_true': ('BOOLEAN', {'default': False})}, 'optional': {'anything': (any, {})}} + RETURN_TYPES = ('BOOLEAN',) + FUNCTION = 'check_input' + OUTPUT_NODE = True + CATEGORY = '😺dzNodes' + + def check_input(self, always_true, anything=None): + ret = False + if always_true or anything is not None: + ret = True + print(f'# 😺dzNodes: Input Trigger: {ret}') + return (ret,) +``` \ No newline at end of file diff --git a/docs/Inset Image Bounds.md b/docs/Inset Image Bounds.md new file mode 100644 index 0000000..820debb --- /dev/null +++ b/docs/Inset Image Bounds.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: WAS_Inset_Image_Bounds +- Category: WAS Suite/Image/Bound +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Inset_Image_Bounds 节点旨在通过插入值调整图像的边界,确保修改后的图像保持其结构完整性。它通过增加或减少指定的边界来操作,注意验证生成的图像边界是否逻辑上合理,并且不会超过原始尺寸。 + +# Input types +## Required +- image_bounds + - image_bounds 参数定义了将要应用插入值的图像的初始边界。这对于确定图像尺寸修改的起始点至关重要。 + - Comfy dtype: IMAGE_BOUNDS + - Python dtype: List[Tuple[int, int, int, int]] +- inset_left + - inset_left 参数指定了图像左侧边界应该插入的数量。它在确定处理后图像的新左边缘时起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- inset_right + - inset_right 参数规定了图像右侧边界应该插入的数量。这对于建立调整后图像的新右边缘很重要。 + - Comfy dtype: INT + - Python dtype: int +- inset_top + - inset_top 参数指示了图像顶部边界应该插入的数量。在应用插入后设置图像的新顶部边缘至关重要。 + - Comfy dtype: INT + - Python dtype: int +- inset_bottom + - inset_bottom 参数确定图像底部边界应该插入的数量。这对于定义调整后图像的新底部边缘至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- inset_bounds + - inset_bounds 输出表示应用插入后图像的新边界。它很重要,因为它反映了处理后图像的最终尺寸。 + - Comfy dtype: IMAGE_BOUNDS + - Python dtype: List[Tuple[int, int, int, int]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Inset_Image_Bounds: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + return {'required': {'image_bounds': ('IMAGE_BOUNDS',), 'inset_left': ('INT', {'default': 64, 'min': 0, 'max': 18446744073709551615}), 'inset_right': ('INT', {'default': 64, 'min': 0, 'max': 18446744073709551615}), 'inset_top': ('INT', {'default': 64, 'min': 0, 'max': 18446744073709551615}), 'inset_bottom': ('INT', {'default': 64, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('IMAGE_BOUNDS',) + FUNCTION = 'inset_image_bounds' + CATEGORY = 'WAS Suite/Image/Bound' + + def inset_image_bounds(self, image_bounds, inset_left, inset_right, inset_top, inset_bottom): + inset_bounds = [] + for (rmin, rmax, cmin, cmax) in image_bounds: + rmin += inset_top + rmax -= inset_bottom + cmin += inset_left + cmax -= inset_right + if rmin > rmax or cmin > cmax: + raise ValueError('Invalid insets provided. Please make sure the insets do not exceed the image bounds.') + inset_bounds.append((rmin, rmax, cmin, cmax)) + return (inset_bounds,) +``` \ No newline at end of file diff --git a/docs/InstantCameraMotionBrush.md b/docs/InstantCameraMotionBrush.md new file mode 100644 index 0000000..e482c55 --- /dev/null +++ b/docs/InstantCameraMotionBrush.md @@ -0,0 +1,172 @@ +# Documentation +- Class name: InstantCameraMotionBrush +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +InstantCameraMotionBrush旨在模拟虚拟环境中的摄像机运动效果。通过生成表示摄像机在帧中移动轨迹的运动刷子来实现此目的。该节点的主要功能是创建摄像机动作的动态视觉表示,例如平移、缩放和倾斜,可以用于增强场景的真实感或在后期制作中添加艺术效果。 + +# Input types +## Required +- model_length + - 模型长度参数决定了摄像机运动序列的持续时间。它对于确定运动刷效果的范围以及随时间的展开方式至关重要。较长的序列允许更复杂的运动路径,而较短的序列则导致更快、更突然的移动。 + - Comfy dtype: INT + - Python dtype: int +- width + - 宽度参数指定了将要应用摄像机运动的水平分辨率。这对于将运动刷准确缩放到场景的尺寸非常重要,确保运动在帧的上下文中看起来自然和比例恰当。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数定义了帧的垂直分辨率。与宽度类似,它对于正确缩放运动刷以适应帧的尺寸很重要,有助于运动效果的整体连贯性和视觉吸引力。 + - Comfy dtype: INT + - Python dtype: int +- action + - 动作参数决定了要模拟的摄像机运动类型。它影响运动轨迹和运动刷将代表摄像机运动的方式,满足视觉内容中不同的创意需求和叙事目的。 + - Comfy dtype: COMBO + - Python dtype: str +- speed + - 速度参数调整摄像机移动的速度。它直接影响运动效果的强度和节奏,允许对最终视觉结果进行细微控制。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- MotionBrush + - 输出MotionBrush是一个表示计算摄像机运动轨迹的张量。它包含了摄像机运动的精髓,为进一步处理和集成到视觉作品中提供了基础。 + - Comfy dtype: Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class InstantCameraMotionBrush: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model_length': ('INT', {'default': 14}), 'width': ('INT', {'default': 576}), 'height': ('INT', {'default': 320}), 'action': (['left', 'right', 'up', 'down', 'zoomin', 'zoomout'], {'default': 'left'}), 'speed': ('FLOAT', {'default': 1})}} + RETURN_TYPES = ('MotionBrush',) + FUNCTION = 'run_inference' + CATEGORY = 'DragNUWA' + + def run_inference(self, model_length, width, height, action, speed): + motion_brush = torch.zeros(model_length - 1, height, width, 2) + xmotionbrush = motion_brush[:, :, :, :1] + ymotionbrush = motion_brush[:, :, :, 1:] + xcount = 10 + ycount = 10 + if width < xcount: + xcount = width + if height < ycount: + ycount = height + xratio = width / xcount + yratio = height / ycount + model_width = width + model_height = height + box = [0, 0, width, height] + tracking_points = [] + if action == 'zoomin': + for j in range(ycount - 1): + for k in range(xcount - 1): + item = [] + for i in range(model_length - 1): + xi = int(k * xratio) + i * speed / (width / 2) * (k * xratio - width / 2) + yi = int(j * yratio) + i * speed / (height / 2) * (j * yratio - height / 2) + if xi > model_width - 1: + xi = model_width - 1 + if yi > model_height - 1: + yi = model_height - 1 + if xi < 0: + xi = 0 + if yi < 0: + yi = 0 + item.append([xi, yi]) + tracking_points.append(item) + elif action == 'zoomout': + for j in range(ycount - 1): + for k in range(xcount - 1): + item = [] + for i in range(model_length - 1): + xi = int(k * xratio) + i * -speed / (width / 2) * (k * xratio - width / 2) + yi = int(j * yratio) + i * -speed / (height / 2) * (j * yratio - height / 2) + if xi > model_width - 1: + xi = model_width - 1 + if yi > model_height - 1: + yi = model_height - 1 + if xi < 0: + xi = 0 + if yi < 0: + yi = 0 + item.append([xi, yi]) + tracking_points.append(item) + elif action == 'left': + for j in range(ycount - 1): + for k in range(xcount - 1): + item = [] + for i in range(model_length - 1): + xi = int(k * xratio) + i * -speed + yi = int(j * yratio) + if xi > model_width - 1: + xi = model_width - 1 + if yi > model_height - 1: + yi = model_height - 1 + if xi < 0: + xi = 0 + if yi < 0: + yi = 0 + item.append([xi, yi]) + tracking_points.append(item) + elif action == 'right': + for j in range(ycount - 1): + for k in range(xcount - 1): + item = [] + for i in range(model_length - 1): + xi = int(k * xratio) + i * speed + yi = int(j * yratio) + if xi > model_width - 1: + xi = model_width - 1 + if yi > model_height - 1: + yi = model_height - 1 + if xi < 0: + xi = 0 + if yi < 0: + yi = 0 + item.append([xi, yi]) + tracking_points.append(item) + elif action == 'up': + for j in range(ycount - 1): + for k in range(xcount - 1): + item = [] + for i in range(model_length - 1): + xi = int(k * xratio) + yi = int(j * yratio) + i * -speed + if xi > model_width - 1: + xi = model_width - 1 + if yi > model_height - 1: + yi = model_height - 1 + if xi < 0: + xi = 0 + if yi < 0: + yi = 0 + item.append([xi, yi]) + tracking_points.append(item) + elif action == 'down': + for j in range(ycount - 1): + for k in range(xcount - 1): + item = [] + for i in range(model_length - 1): + xi = int(k * xratio) + yi = int(j * yratio) + i * speed + if xi > model_width - 1: + xi = model_width - 1 + if yi > model_height - 1: + yi = model_height - 1 + if xi < 0: + xi = 0 + if yi < 0: + yi = 0 + item.append([xi, yi]) + tracking_points.append(item) + motion_brush = load_motionbrush_from_tracking_points_without_model(model_length, model_width, model_height, tracking_points) + return (motion_brush,) +``` \ No newline at end of file diff --git a/docs/InstantIDAttentionPatch.md b/docs/InstantIDAttentionPatch.md new file mode 100644 index 0000000..98762ad --- /dev/null +++ b/docs/InstantIDAttentionPatch.md @@ -0,0 +1,129 @@ +# Documentation +- Class name: InstantIDAttentionPatch +- Category: InstantID +- Output node: False +- Repo Ref: https://github.com/cubiq/ComfyUI_InstantID.git + +InstantIDAttentionPatch是一个旨在增强神经网络模型中注意力机制的类,特别为图像处理任务定制。它与InstantID模型集成,以提高模型对图像中相关特征的聚焦能力,从而提高输出嵌入的质量。该节点抽象了注意力补丁的复杂性,并强调了模型特征检测和表示能力的总体增强。 + +# Input types +## Required +- instantid + - instantid参数至关重要,因为它提供了注意力补丁操作所需的基础模型架构。它是应用注意力机制和特征增强的基础,直接影响节点在提炼模型输出方面的有效性。 + - Comfy dtype: INSTANTID + - Python dtype: dict +- insightface + - insightface参数对节点至关重要,因为它提供了面部分析组件,这对于图像数据处理至关重要。它使节点能够准确检测和分析面部特征,这是图像处理任务的关键方面。 + - Comfy dtype: FACEANALYSIS + - Python dtype: object +- image + - image参数对节点的运作至关重要,因为它引入了将被处理的原始图像数据。图像的质量和分辨率直接影响节点提取和利用相关特征的能力,从而影响图像处理任务的整体性能。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- model + - model参数是节点将通过应用注意力补丁来增强的神经网络模型。它是一个关键组件,因为它决定了节点构建其特征增强和注意力机制的基础。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- weight + - weight参数是一个浮点值,用于调整注意力补丁对模型输出的影响。它很重要,因为它允许对模型对特定特征的关注进行微调,直接影响提取特征的质量和相关性。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_at + - start_at参数定义了注意力补丁开始施加影响的初始点。它很重要,因为它设置了特征增强过程的起始条件,影响模型最初如何聚焦输入图像。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_at + - end_at参数指定了注意力补丁结束其影响的最终点。它很重要,因为它决定了特征增强的结束条件,影响模型对输入图像的持续关注。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- noise + - noise参数在注意力补丁的操作中引入了一定程度的随机性,这有助于多样化模型的特征提取。它通过在特征表示中引入变异性,增强了模型的鲁棒性和创造力。 + - Comfy dtype: FLOAT + - Python dtype: float +- mask + - 当提供mask参数时,它允许有选择地将注意力补丁应用于图像的特定区域。它通过确定在特征增强过程中哪些图像区域被优先考虑或忽略,影响节点的操作。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- model + - 输出模型是应用注意力补丁后增强的神经网络。它代表了节点努力提炼和集中模型特征提取能力的成果,提供了对输入图像更准确和细致的表示。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- FACE_EMBEDS + - FACE_EMBEDS输出由输入图像中提取的面部嵌入组成,这些嵌入已通过注意力补丁得到增强。这些嵌入捕捉了面部数据的基本特征,提供了丰富而详细的表示,可用于进一步的分析或比较。 + - Comfy dtype: FACE_EMBEDS + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class InstantIDAttentionPatch: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'instantid': ('INSTANTID',), 'insightface': ('FACEANALYSIS',), 'image': ('IMAGE',), 'model': ('MODEL',), 'weight': ('FLOAT', {'default': 1.0, 'min': -1.0, 'max': 3.0, 'step': 0.01}), 'start_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_at': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'noise': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.1})}, 'optional': {'mask': ('MASK',)}} + RETURN_TYPES = ('MODEL', 'FACE_EMBEDS') + FUNCTION = 'patch_attention' + CATEGORY = 'InstantID' + + def patch_attention(self, instantid, insightface, image, model, weight, start_at, end_at, noise=0.0, mask=None): + self.dtype = torch.float16 if comfy.model_management.should_use_fp16() else torch.float32 + self.device = comfy.model_management.get_torch_device() + output_cross_attention_dim = instantid['ip_adapter']['1.to_k_ip.weight'].shape[1] + is_sdxl = output_cross_attention_dim == 2048 + cross_attention_dim = 1280 + clip_extra_context_tokens = 16 + face_embed = extractFeatures(insightface, image) + if face_embed is None: + raise Exception('Reference Image: No face detected.') + clip_embed = face_embed + if clip_embed.shape[0] > 1: + clip_embed = torch.mean(clip_embed, dim=0).unsqueeze(0) + if noise > 0: + seed = int(torch.sum(clip_embed).item()) % 1000000007 + torch.manual_seed(seed) + clip_embed_zeroed = noise * torch.rand_like(clip_embed) + else: + clip_embed_zeroed = torch.zeros_like(clip_embed) + clip_embeddings_dim = face_embed.shape[-1] + self.instantid = InstantID(instantid, cross_attention_dim=cross_attention_dim, output_cross_attention_dim=output_cross_attention_dim, clip_embeddings_dim=clip_embeddings_dim, clip_extra_context_tokens=clip_extra_context_tokens) + self.instantid.to(self.device, dtype=self.dtype) + (image_prompt_embeds, uncond_image_prompt_embeds) = self.instantid.get_image_embeds(clip_embed.to(self.device, dtype=self.dtype), clip_embed_zeroed.to(self.device, dtype=self.dtype)) + image_prompt_embeds = image_prompt_embeds.to(self.device, dtype=self.dtype) + uncond_image_prompt_embeds = uncond_image_prompt_embeds.to(self.device, dtype=self.dtype) + if weight == 0: + return (model, {'cond': image_prompt_embeds, 'uncond': uncond_image_prompt_embeds}) + work_model = model.clone() + sigma_start = work_model.model.model_sampling.percent_to_sigma(start_at) + sigma_end = work_model.model.model_sampling.percent_to_sigma(end_at) + if mask is not None: + mask = mask.to(self.device) + patch_kwargs = {'number': 0, 'weight': weight, 'ipadapter': self.instantid, 'cond': image_prompt_embeds, 'uncond': uncond_image_prompt_embeds, 'mask': mask, 'sigma_start': sigma_start, 'sigma_end': sigma_end, 'weight_type': 'original'} + if not is_sdxl: + for id in [1, 2, 4, 5, 7, 8]: + _set_model_patch_replace(work_model, patch_kwargs, ('input', id)) + patch_kwargs['number'] += 1 + for id in [3, 4, 5, 6, 7, 8, 9, 10, 11]: + _set_model_patch_replace(work_model, patch_kwargs, ('output', id)) + patch_kwargs['number'] += 1 + _set_model_patch_replace(work_model, patch_kwargs, ('middle', 0)) + else: + for id in [4, 5, 7, 8]: + block_indices = range(2) if id in [4, 5] else range(10) + for index in block_indices: + _set_model_patch_replace(work_model, patch_kwargs, ('input', id, index)) + patch_kwargs['number'] += 1 + for id in range(6): + block_indices = range(2) if id in [3, 4, 5] else range(10) + for index in block_indices: + _set_model_patch_replace(work_model, patch_kwargs, ('output', id, index)) + patch_kwargs['number'] += 1 + for index in range(10): + _set_model_patch_replace(work_model, patch_kwargs, ('middle', 0, index)) + patch_kwargs['number'] += 1 + return (work_model, {'cond': image_prompt_embeds, 'uncond': uncond_image_prompt_embeds}) +``` \ No newline at end of file diff --git a/docs/InstantIDFaceAnalysis.md b/docs/InstantIDFaceAnalysis.md new file mode 100644 index 0000000..c9d7bb6 --- /dev/null +++ b/docs/InstantIDFaceAnalysis.md @@ -0,0 +1,40 @@ +# Documentation +- Class name: InstantIDFaceAnalysis +- Category: InstantID +- Output node: False +- Repo Ref: https://github.com/cubiq/ComfyUI_InstantID.git + +InstantIDFaceAnalysis是一个用于执行高级面部分析的节点,它利用预训练的模型来识别和分析面部特征和属性,适用于需要精确面部识别和人口统计分析的应用场景。 + +# Input types +## Required +- provider + - provider参数对于面部分析节点的执行环境至关重要。它决定了将用于面部分析任务的计算后端,影响节点的性能和效率。 + - Comfy dtype: COMBO['CPU', 'CUDA', 'ROCM'] + - Python dtype: str + +# Output types +- FACEANALYSIS + - InstantIDFaceAnalysis节点的输出是详细的面部分析结果,包含了从输入的面部数据中得出的洞察。这个输出非常重要,因为它为进一步的分析或决策过程提供了基础。 + - Comfy dtype: Tuple[FaceAnalysis] + - Python dtype: Tuple[FaceAnalysis] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class InstantIDFaceAnalysis: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'provider': (['CPU', 'CUDA', 'ROCM'],)}} + RETURN_TYPES = ('FACEANALYSIS',) + FUNCTION = 'load_insight_face' + CATEGORY = 'InstantID' + + def load_insight_face(self, provider): + model = FaceAnalysis(name='antelopev2', root=INSIGHTFACE_DIR, providers=[provider + 'ExecutionProvider']) + model.prepare(ctx_id=0, det_size=(640, 640)) + return (model,) +``` \ No newline at end of file diff --git a/docs/InstantIDModelLoader.md b/docs/InstantIDModelLoader.md new file mode 100644 index 0000000..456e1b6 --- /dev/null +++ b/docs/InstantIDModelLoader.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: InstantIDModelLoader +- Category: InstantID +- Output node: False +- Repo Ref: https://github.com/cubiq/ComfyUI_InstantID.git + +该节点旨在高效加载和管理InstantID特定模型,确保检索并准备适当的模型以供系统内使用。 + +# Input types +## Required +- instantid_file + - 该参数对于指定要加载的确切InstantID模型文件至关重要。它决定了后续操作中将使用模型的身份和版本。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- INSTANTID + - 输出代表加载的InstantID模型,这对于系统执行与模型功能相关的任务至关重要。 + - Comfy dtype: DICTIONARY + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class InstantIDModelLoader: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'instantid_file': (folder_paths.get_filename_list('instantid'),)}} + RETURN_TYPES = ('INSTANTID',) + FUNCTION = 'load_model' + CATEGORY = 'InstantID' + + def load_model(self, instantid_file): + ckpt_path = folder_paths.get_full_path('instantid', instantid_file) + model = comfy.utils.load_torch_file(ckpt_path, safe_load=True) + if ckpt_path.lower().endswith('.safetensors'): + st_model = {'image_proj': {}, 'ip_adapter': {}} + for key in model.keys(): + if key.startswith('image_proj.'): + st_model['image_proj'][key.replace('image_proj.', '')] = model[key] + elif key.startswith('ip_adapter.'): + st_model['ip_adapter'][key.replace('ip_adapter.', '')] = model[key] + model = st_model + return (model,) +``` \ No newline at end of file diff --git a/docs/InstantObjectMotionBrush.md b/docs/InstantObjectMotionBrush.md new file mode 100644 index 0000000..de6f93f --- /dev/null +++ b/docs/InstantObjectMotionBrush.md @@ -0,0 +1,192 @@ +# Documentation +- Class name: InstantObjectMotionBrush +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +InstantObjectMotionBrush旨在为图像或视频中的对象生成运动效果。该节点识别对象的轨迹,并根据指定的参数应用运动刷效果,以创造性或真实感的方式增强运动的视觉表现。 + +# Input types +## Required +- model_length + - 模型长度决定了运动效果的持续时间,影响运动轨迹的平滑度和细节。 + - Comfy dtype: INT + - Python dtype: int +- brush_mask + - 画笔遮罩对于定义图像中将应用运动效果的兴趣区域至关重要,确保对运动效果的应用进行精确控制。 + - Comfy dtype: MASK + - Python dtype: numpy.ndarray +- action + - 动作参数决定了将模拟的运动类型,例如放大、缩小、向左移动、向右移动、向上或向下,这直接影响运动轨迹和运动效果的视觉结果。 + - Comfy dtype: COMBO + - Python dtype: str +- speed + - 速度调整运动效果执行的速度,影响运动的强度和真实感。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- motion_brush + - 输出的运动刷表示计算出的运动轨迹和位移信息,这对于渲染最终的运动效果至关重要。 + - Comfy dtype: MOTIONBRUSH + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class InstantObjectMotionBrush: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model_length': ('INT', {'default': 14}), 'brush_mask': ('MASK',), 'action': (['left', 'right', 'up', 'down', 'zoomin', 'zoomout'], {'default': 'left'}), 'speed': ('FLOAT', {'default': 5})}} + RETURN_TYPES = ('MotionBrush',) + FUNCTION = 'run_inference' + CATEGORY = 'DragNUWA' + + def run_inference(self, model_length, brush_mask, action, speed): + model_width = brush_mask.shape[2] + model_height = brush_mask.shape[1] + from torchvision.ops import masks_to_boxes + boxes = masks_to_boxes(brush_mask) + box = boxes[0].int().tolist() + print(f'model_width{model_width}model_height{model_height}box{box}') + xcount = 10 + ycount = 10 + if box[2] - box[0] < xcount: + xcount = box[2] - box[0] + if box[3] - box[1] < ycount: + ycount = box[3] - box[1] + xratio = (box[2] - box[0]) / xcount + yratio = (box[3] - box[1]) / ycount + tracking_points = [] + if action == 'zoomin': + for j in range(ycount - 1): + for k in range(xcount - 1): + if not bool(brush_mask[0][box[1] + int(j * yratio)][box[0] + int(k * xratio)]): + continue + item = [] + for i in range(model_length - 1): + width = box[2] - box[0] + height = box[3] - box[1] + xi = box[0] + int(k * xratio) + i * speed / (width / 2) * (k * xratio - width / 2) + yi = box[1] + int(j * yratio) + i * speed / (height / 2) * (j * yratio - height / 2) + if xi > model_width - 1: + xi = model_width - 1 + if yi > model_height - 1: + yi = model_height - 1 + if xi < 0: + xi = 0 + if yi < 0: + yi = 0 + item.append([xi, yi]) + tracking_points.append(item) + elif action == 'zoomout': + for j in range(ycount - 1): + for k in range(xcount - 1): + if not bool(brush_mask[0][box[1] + int(j * yratio)][box[0] + int(k * xratio)]): + continue + item = [] + for i in range(model_length - 1): + width = box[2] - box[0] + height = box[3] - box[1] + xi = box[0] + int(k * xratio) + i * -speed / (width / 2) * (k * xratio - width / 2) + yi = box[1] + int(j * yratio) + i * -speed / (height / 2) * (j * yratio - height / 2) + if xi > model_width - 1: + xi = model_width - 1 + if yi > model_height - 1: + yi = model_height - 1 + if xi < 0: + xi = 0 + if yi < 0: + yi = 0 + item.append([xi, yi]) + tracking_points.append(item) + elif action == 'left': + for j in range(ycount - 1): + for k in range(xcount - 1): + if not bool(brush_mask[0][box[1] + int(j * yratio)][box[0] + int(k * xratio)]): + continue + item = [] + for i in range(model_length - 1): + width = box[2] - box[0] + height = box[3] - box[1] + xi = box[0] + int(k * xratio) + i * -speed + yi = box[1] + int(j * yratio) + if xi > model_width - 1: + xi = model_width - 1 + if yi > model_height - 1: + yi = model_height - 1 + if xi < 0: + xi = 0 + if yi < 0: + yi = 0 + item.append([xi, yi]) + tracking_points.append(item) + elif action == 'right': + for j in range(ycount - 1): + for k in range(xcount - 1): + if not bool(brush_mask[0][box[1] + int(j * yratio)][box[0] + int(k * xratio)]): + continue + item = [] + for i in range(model_length - 1): + width = box[2] - box[0] + height = box[3] - box[1] + xi = box[0] + int(k * xratio) + i * speed + yi = box[1] + int(j * yratio) + if xi > model_width - 1: + xi = model_width - 1 + if yi > model_height - 1: + yi = model_height - 1 + if xi < 0: + xi = 0 + if yi < 0: + yi = 0 + item.append([xi, yi]) + tracking_points.append(item) + elif action == 'up': + for j in range(ycount - 1): + for k in range(xcount - 1): + if not bool(brush_mask[0][box[1] + int(j * yratio)][box[0] + int(k * xratio)]): + continue + item = [] + for i in range(model_length - 1): + width = box[2] - box[0] + height = box[3] - box[1] + xi = box[0] + int(k * xratio) + yi = box[1] + int(j * yratio) + i * -speed + if xi > model_width - 1: + xi = model_width - 1 + if yi > model_height - 1: + yi = model_height - 1 + if xi < 0: + xi = 0 + if yi < 0: + yi = 0 + item.append([xi, yi]) + tracking_points.append(item) + elif action == 'down': + for j in range(ycount - 1): + for k in range(xcount - 1): + if not bool(brush_mask[0][box[1] + int(j * yratio)][box[0] + int(k * xratio)]): + continue + item = [] + for i in range(model_length - 1): + width = box[2] - box[0] + height = box[3] - box[1] + xi = box[0] + int(k * xratio) + yi = box[1] + int(j * yratio) + i * speed + if xi > model_width - 1: + xi = model_width - 1 + if yi > model_height - 1: + yi = model_height - 1 + if xi < 0: + xi = 0 + if yi < 0: + yi = 0 + item.append([xi, yi]) + tracking_points.append(item) + motion_brush = load_motionbrush_from_tracking_points_without_model(model_length, model_width, model_height, tracking_points) + return (motion_brush,) +``` \ No newline at end of file diff --git a/docs/Int To Bool (mtb).md b/docs/Int To Bool (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Int To Number (mtb).md b/docs/Int To Number (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Int to String.md b/docs/Int to String.md new file mode 100644 index 0000000..f06207e --- /dev/null +++ b/docs/Int to String.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: INTtoSTRING +- Category: Mikey/Utils +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +INTtoSTRING节点旨在将整数值转换为它们的字符串表示形式。它提供格式化字符串的功能,可选择是否使用逗号,以适应不同的用例,为数值数据展示提供了一种多功能的方法。 + +# Input types +## Required +- int_ + - 参数'int_'是需要被转换为字符串的整数。它在节点的操作中起着关键作用,因为它是转换过程的主要输入。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- use_commas + - 参数'use_commas'决定输出的字符串是否应该包含作为千位分隔符的逗号。它影响数字数据在字符串格式中的可读性。 + - Comfy dtype: COMBO['true', 'false'] + - Python dtype: str + +# Output types +- STRING + - INTtoSTRING节点的输出是输入整数的字符串表示。它很重要,因为它直接反映了节点主要功能的转换结果。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class INTtoSTRING: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'int_': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'use_commas': (['true', 'false'], {'default': 'false'})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'convert' + CATEGORY = 'Mikey/Utils' + + def convert(self, int_, use_commas): + if use_commas == 'true': + return (f'{int_:,}',) + else: + return (f'{int_}',) +``` \ No newline at end of file diff --git a/docs/IntNumber.md b/docs/IntNumber.md new file mode 100644 index 0000000..945e65f --- /dev/null +++ b/docs/IntNumber.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: IntNumber +- Category: ♾️Mixlab/Utils +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点对数字输入进行分类和限制,确保输出符合定义的范围和增量。 + +# Input types +## Required +- number + - 节点评估的中心输入,确保它落在指定的最小和最大界限内。 + - Comfy dtype: INT + - Python dtype: int +- min_value + - 节点使用的下限,如果输入数字低于此阈值,则将其限制在此下限内。 + - Comfy dtype: INT + - Python dtype: int +- max_value + - 节点使用的上限,如果输入数字超过此限制,则将其限制在此上限内。 + - Comfy dtype: INT + - Python dtype: int +- step + - 节点在指定范围内调整输入数字时考虑的增量值。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- number + - 受到限制并调整后的数字输出,它落在定义的范围内,并遵循指定的增量步骤。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IntNumber: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'number': ('INT', {'default': 0, 'min': -1, 'max': 18446744073709551615, 'step': 1, 'display': 'number'}), 'min_value': ('INT', {'default': 0, 'min': -18446744073709551615, 'max': 18446744073709551615, 'step': 1, 'display': 'number'}), 'max_value': ('INT', {'default': 1, 'min': -18446744073709551615, 'max': 18446744073709551615, 'step': 1, 'display': 'number'}), 'step': ('INT', {'default': 1, 'min': -18446744073709551615, 'max': 18446744073709551615, 'step': 1, 'display': 'number'})}} + RETURN_TYPES = ('INT',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Utils' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False,) + + def run(self, number, min_value, max_value, step): + if number < min_value: + number = min_value + elif number > max_value: + number = max_value + return (number,) +``` \ No newline at end of file diff --git a/docs/Integer place counter.md b/docs/Integer place counter.md new file mode 100644 index 0000000..92e6ed1 --- /dev/null +++ b/docs/Integer place counter.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_Integer_Place_Counter +- Category: WAS Suite/Integer +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +该节点旨在计算一个整数值中的位数。它作为基础工具,用于需要进行位数计数操作的应用,例如数值分析或数据处理。 + +# Input types +## Required +- int_input + - 要确定位数的整数输入。它是节点操作的主要数据元素,直接影响结果。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- INT_PLACES + - 输出代表提供的整数中的位数计数。对于需要知道数字位数长度的应用来说,它是重要的。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Integer_Place_Counter: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'int_input': ('INT', {'default': 0, 'min': 0, 'max': 10000000, 'step': 1})}} + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('INT_PLACES',) + FUNCTION = 'count_places' + CATEGORY = 'WAS Suite/Integer' + + def count_places(self, int_input): + output = len(str(int_input)) + cstr('\nInteger Places Count: ' + str(output)).msg.print() + return (output,) +``` \ No newline at end of file diff --git a/docs/InvCosWave.md b/docs/InvCosWave.md new file mode 100644 index 0000000..17c1890 --- /dev/null +++ b/docs/InvCosWave.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: InvCosWave +- Category: FizzNodes 📅🅕🅝/WaveNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +InvCosWave节点基于反余弦函数生成波形。它旨在提供可由相位、振幅和位移参数调整的周期性输出。该节点特别适用于需要随时间平滑振荡模式的应用。 + +# Input types +## Required +- phase + - 相位参数决定了波形的周期。它影响波形振荡的频率,对于设置模式的时间频率至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- amplitude + - 振幅参数控制波形的峰值。它对于定义振荡的幅度很重要,可以调整以缩放输出。 + - Comfy dtype: FLOAT + - Python dtype: float +- x_translation + - x_translation参数沿x轴移动波形。它对于在给定帧或空间内定位波形模式至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- y_translation + - y_translation参数调整波形的垂直位置。它对于将波形模式与其它视觉元素或数据点对齐很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- current_frame + - current_frame参数代表动画或序列中的当前时间步。它对于在任何给定时刻生成波形的正确相位至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - InvCosWave节点的输出是一个浮点数,代表在指定帧处波形的当前值。它对于进一步处理或可视化波形模式很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- int_output + - int_output是波形值的整数表示,当需要索引或需要整数精度时非常有用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class InvCosWave: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'phase': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'amplitude': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.1}), 'x_translation': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'y_translation': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.05}), 'current_frame': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('FLOAT', 'INT') + FUNCTION = 'Wave' + CATEGORY = 'FizzNodes 📅🅕🅝/WaveNodes' + + def Wave(self, phase, amplitude, x_translation, y_translation, current_frame): + output = y_translation + amplitude * -np.cos(-1 * (2 * np.pi * current_frame / phase - x_translation)) + print(output) + return (output, int(output)) +``` \ No newline at end of file diff --git a/docs/InvSinWave.md b/docs/InvSinWave.md new file mode 100644 index 0000000..697a450 --- /dev/null +++ b/docs/InvSinWave.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: InvSinWave +- Category: FizzNodes 📅🅕🅝/WaveNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +InvSinWave节点旨在生成一个倒置的正弦波模式。它通过操作波的相位、振幅和平移来实现所需的输出,这在信号处理和波形分析应用中特别有用。 + +# Input types +## Required +- phase + - 相位参数决定了波的周期,影响波在给定时间框架内完成一个完整周期的次数。它对于控制波的频率至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- amplitude + - 振幅设置波峰的高度,影响波振荡的强度。它是调整波形大小的一个重要参数。 + - Comfy dtype: FLOAT + - Python dtype: float +- x_translation + - X平移沿X轴水平移动波,允许在给定空间内定位波。它对于将波形与特定坐标对齐具有重要意义。 + - Comfy dtype: FLOAT + - Python dtype: float +- y_translation + - Y平移沿Y轴垂直移动波,影响波振荡的起始点。它对于调整波形的垂直位置很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- current_frame + - 当前帧参数指定时间序列中的当前位置,对于在动画或模拟的特定时刻生成波至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - 输出是在指定参数下计算出的倒置正弦波的值,可以用于进一步分析或作为其他节点的输入。 + - Comfy dtype: FLOAT + - Python dtype: float +- int_output + - 整数输出是波计算值的整数版本,对于需要离散值而非连续值的应用可能很有用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class InvSinWave: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'phase': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'amplitude': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.1}), 'x_translation': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'y_translation': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.05}), 'current_frame': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('FLOAT', 'INT') + FUNCTION = 'Wave' + CATEGORY = 'FizzNodes 📅🅕🅝/WaveNodes' + + def Wave(self, phase, amplitude, x_translation, y_translation, current_frame): + output = y_translation + amplitude * -np.sin(-1 * (2 * np.pi * current_frame / phase - x_translation)) + print(output) + return (output, int(output)) +``` \ No newline at end of file diff --git a/docs/InvertMask (segment anything).md b/docs/InvertMask (segment anything).md new file mode 100644 index 0000000..20d8ce0 --- /dev/null +++ b/docs/InvertMask (segment anything).md @@ -0,0 +1,39 @@ +# Documentation +- Class name: InvertMask +- Category: segment_anything +- Output node: False +- Repo Ref: https://github.com/storyicon/comfyui_segment_anything + +InvertMask节点旨在反转二值掩码的值。它在各种图像分割任务中扮演着关键角色,其中反转掩码以突出不同的兴趣区域是必要的。该节点通过从输入掩码中减去1来操作,有效地翻转掩码的极性。 + +# Input types +## Required +- mask + - ‘mask’参数是一个二值掩码,节点将对其进行反转。它对节点的操作至关重要,因为它直接决定了输出。反转后的掩码用于识别或隔离图像中的某些区域,这对于分割目的至关重要。 + - Comfy dtype: np.ndarray + - Python dtype: numpy.ndarray + +# Output types +- MASK + - ‘MASK’输出是输入掩码的反转版本。它很重要,因为它代表了节点操作的结果,提供了一个具有反转值的二进制掩码,可以用于分割工作流中的进一步处理或分析。 + - Comfy dtype: np.ndarray + - Python dtype: numpy.ndarray + +# Usage tips +- Infra type: CPU + +# Source code +``` +class InvertMask: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'mask': ('MASK',)}} + CATEGORY = 'segment_anything' + FUNCTION = 'main' + RETURN_TYPES = ('MASK',) + + def main(self, mask): + out = 1.0 - mask + return (out,) +``` \ No newline at end of file diff --git a/docs/IpaConfiguration.md b/docs/IpaConfiguration.md new file mode 100644 index 0000000..577c1f2 --- /dev/null +++ b/docs/IpaConfiguration.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: IpaConfigurationNode +- Category: Steerable-Motion +- Output node: False +- Repo Ref: https://github.com/banodoco/steerable-motion + +IpaConfigurationNode类封装了一个节点的配置逻辑,该节点管理影响可控制运动模型行为的参数。它处理输入以根据用户偏好微调模型的性能,专注于控制与自然运动之间的平衡。 + +# Input types +## Required +- ipa_starts_at + - “ipa_starts_at”参数规定了运动的起始点,这对定义动画的初始条件至关重要。它影响整体轨迹并确保运动从所需位置平稳开始。 + - Comfy dtype: FLOAT + - Python dtype: float +- ipa_ends_at + - “ipa_ends_at”参数指定了运动的结束点,这对确定动画的最终状态至关重要。它确保运动在预期位置结束,有助于动画序列的连贯性。 + - Comfy dtype: FLOAT + - Python dtype: float +- ipa_weight_type + - “ipa_weight_type”参数影响沿运动路径的权重分布,影响动画的平滑度和视觉吸引力。它是实现运动不同阶段之间自然过渡的关键因素。 + - Comfy dtype: ENUM + - Python dtype: str +- ipa_weight + - “ipa_weight”参数调整权重设置对运动的整体影响,这对于微调动画的动态非常重要。它有助于实现不同运动元素之间期望的平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- ipa_embeds_scaling + - “ipa_embeds_scaling”参数控制运动模型中使用的嵌入的缩放,这对于调整模型对用户输入的响应性至关重要。它在运动的精确性和适应性方面发挥着重要作用。 + - Comfy dtype: ENUM + - Python dtype: str +- ipa_noise_strength + - “ipa_noise_strength”参数决定了应用于运动的噪声强度,这可以为动画增加真实性和变化性。它是创建更具动态性和不可预测性的运动序列的重要方面。 + - Comfy dtype: FLOAT + - Python dtype: float +- use_image_for_noise + - “use_image_for_noise”参数启用使用图像作为噪声源,这可以向动画中引入更复杂和视觉上丰富的噪声模式。它增强了运动的多样性和审美质量。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- type_of_noise + - “type_of_noise”参数定义了要应用的噪声类型,这显著影响动画的视觉特征和风格。它是实现期望的审美和风格成果的关键元素。 + - Comfy dtype: ENUM + - Python dtype: str +- noise_blur + - “noise_blur”参数调整应用噪声的模糊程度,影响动画中噪声模式的平滑度和连贯性。它在定义整体视觉质感和质量方面发挥作用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- configuration + - 输出'configuration'是一组经过处理和优化的参数,用于可控制运动模型。它封装了所有用户定义的设置,确保模型根据指定的偏好运行。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IpaConfigurationNode: + WEIGHT_TYPES = ['linear', 'ease in', 'ease out', 'ease in-out', 'reverse in-out', 'weak input', 'weak output', 'weak middle', 'strong middle'] + IPA_EMBEDS_SCALING_OPTIONS = ['V only', 'K+V', 'K+V w/ C penalty', 'K+mean(V) w/ C penalty'] + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'ipa_starts_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'ipa_ends_at': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'ipa_weight_type': (cls.WEIGHT_TYPES,), 'ipa_weight': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 0.01}), 'ipa_embeds_scaling': (cls.IPA_EMBEDS_SCALING_OPTIONS,), 'ipa_noise_strength': ('FLOAT', {'default': 0.3, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'use_image_for_noise': ('BOOLEAN', {'default': False}), 'type_of_noise': (['fade', 'dissolve', 'gaussian', 'shuffle'],), 'noise_blur': ('INT', {'default': 0, 'min': 0, 'max': 32, 'step': 1})}, 'optional': {}} + FUNCTION = 'process_inputs' + RETURN_TYPES = ('ADVANCED_IPA_SETTINGS',) + RETURN_NAMES = ('configuration',) + CATEGORY = 'Steerable-Motion' + + @classmethod + def process_inputs(cls, ipa_starts_at, ipa_ends_at, ipa_weight_type, ipa_weight, ipa_embeds_scaling, ipa_noise_strength, use_image_for_noise, type_of_noise, noise_blur): + return ({'ipa_starts_at': ipa_starts_at, 'ipa_ends_at': ipa_ends_at, 'ipa_weight_type': ipa_weight_type, 'ipa_weight': ipa_weight, 'ipa_embeds_scaling': ipa_embeds_scaling, 'ipa_noise_strength': ipa_noise_strength, 'use_image_for_noise': use_image_for_noise, 'type_of_noise': type_of_noise, 'noise_blur': noise_blur},) +``` \ No newline at end of file diff --git a/docs/IsMaskEmpty.md b/docs/IsMaskEmpty.md new file mode 100644 index 0000000..d8cd15c --- /dev/null +++ b/docs/IsMaskEmpty.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: IsMaskEmptyNode +- Category: util +- Output node: False +- Repo Ref: https://github.com/esheep/esheep_custom_nodes.git + +IsMaskEmptyNode 类旨在评估掩码张量的内部内容,确定它是否完全由零值组成。这个节点在图像处理和机器学习工作流程中扮演着关键角色,其中空掩码的存在具有重要意义。它抽象地为决策过程贡献了一个二进制结果,可以用来触发后续动作或过滤掉不必要的数据。 + +# Input types +## Required +- mask + - 参数 'mask' 是一个张量,代表要评估的掩码。它对节点的操作至关重要,因为它直接影响掩码是否被视为空的。张量应该包含数值,其中零表示空或不重要的区域。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Output types +- boolean_number + - 输出 'boolean_number' 是一个布尔值的数值表示,它指示输入掩码是否为空。值为1表示掩码为空(全部为零),而值为0表示掩码包含非零元素。 + - Comfy dtype: int + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IsMaskEmptyNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',)}} + RETURN_TYPES = ['NUMBER'] + RETURN_NAMES = ['boolean_number'] + FUNCTION = 'main' + CATEGORY = 'util' + + def main(self, mask): + return (torch.all(mask == 0).int().item(),) +``` \ No newline at end of file diff --git a/docs/Iterative Mixing KSampler Advanced.md b/docs/Iterative Mixing KSampler Advanced.md new file mode 100644 index 0000000..7283176 --- /dev/null +++ b/docs/Iterative Mixing KSampler Advanced.md @@ -0,0 +1,122 @@ +# Documentation +- Class name: IterativeMixingKSamplerAdv +- Category: test +- Output node: False +- Repo Ref: https://github.com/ttulttul/ComfyUI-Iterative-Mixer + +该节点通过逐步引入一组预定义的潜在向量来改进一批噪声潜在表示,旨在提高生成样本的质量和一致性。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了用于去噪和精炼潜在表示的生成网络。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_management.Model +- seed + - 种子对于去噪和采样步骤中涉及的随机过程至关重要,确保输出的可重复性和多样性。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数很重要,因为它调整采样过程的行为,影响生成样本的质量和特性。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 采样器名称决定了使用的采样方法,这对迭代混合过程和最终输出至关重要。 + - Comfy dtype: COMBO + - Python dtype: str +- scheduler + - 调度器参数是去噪过程中的关键,控制迭代中噪声减少的速率。 + - Comfy dtype: COMBO + - Python dtype: str +- positive + - 正向调节为生成过程提供了重要的上下文,引导生成朝着期望的结果发展。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- negative + - 负向调节对于限制采样空间至关重要,防止不希望的伪影,并确保结果的一致性。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- latent_image_batch + - 潜在图像批次是迭代混合过程的起点,每个元素都会影响精炼的轨迹。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- denoise + - 去噪参数对于控制每一步的降噪程度至关重要,平衡精炼和防止伪影。 + - Comfy dtype: FLOAT + - Python dtype: float +- alpha_1 + - Alpha-1影响混合计划,决定了指导潜在向量如何混合到去噪过程中以获得最佳结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- reverse_input_batch + - 反转输入批次参数改变了潜在向量的顺序,影响了迭代混合的进展和一致性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- blending_schedule + - 混合计划在确定指导潜在向量合并的速率方面起着重要作用,影响最终样本的质量。 + - Comfy dtype: COMBO + - Python dtype: str +- stop_blending_at_pct + - 该参数决定了混合停止的百分比,平衡了指导潜在向量的影响,并确保了期望的细节水平。 + - Comfy dtype: FLOAT + - Python dtype: float +- clamp_blending_at_pct + - 夹紧混合百分比参数限制了混合的影响,防止过度混合并保持生成样本的完整性。 + - Comfy dtype: FLOAT + - Python dtype: float +- blending_function + - 混合函数定义了用于组合指导潜在向量和去噪样本的数学运算,影响输出的最终外观。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- mixed_latents + - 混合潜在向量代表了迭代精炼的潜在表示,这是该节点输出的核心。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- noised_latents + - 噪声潜在向量捕捉批次的初始噪声状态,为去噪过程提供参考。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- intermediate_latents + - 这些中间潜在向量记录了迭代混合过程的进展,提供了精炼轨迹的见解。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- plot_image + - 绘图图像可视化混合计划,提供了迭代混合过程的图形表示。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: GPU + +# Source code +``` +class IterativeMixingKSamplerAdv: + """ + Take a batch of latents, z_prime, and progressively de-noise them + step by step from z_prime[0] to z_prime[steps], mixing in a weighted + fraction of z_prime[i] at each step so that de-noising is guided by + the z_prime latents. This batch sampler assumes that the number of steps + is just the length of z_prime, so there is no steps parameter. The parameter + latent_image_batch should come from the Batch Unsampler node. The parameter + alpha_1 controls an exponential cosine function that schedules how much + of the noised latents to mix with the de-noised latents at each step. + Small values cause more of the noised latents to be mixed in at each step, + which provides more guidance to the diffusion, but which may result in more + artifacts. Large values (i.e. >1.0) can cause output to be grainy. Your + mileage may vary. + """ + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'cfg': ('FLOAT', {'default': 8.0, 'min': 0.0, 'max': 100.0, 'step': 0.1, 'round': 0.01}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image_batch': ('LATENT',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'alpha_1': ('FLOAT', {'default': 2.4, 'min': 0.05, 'max': 100.0, 'step': 0.05}), 'reverse_input_batch': ('BOOLEAN', {'default': True}), 'blending_schedule': (list(BLENDING_SCHEDULE_MAP.keys()), {'default': 'cosine'}), 'stop_blending_at_pct': ('FLOAT', {'default': 1.0}), 'clamp_blending_at_pct': ('FLOAT', {'default': 1.0}), 'blending_function': (list(BLENDING_FUNCTION_MAP.keys()), {'default': 'addition'})}} + RETURN_TYPES = ('LATENT', 'LATENT', 'LATENT', 'IMAGE') + RETURN_NAMES = ('mixed_latents', 'noised_latents', 'intermediate_latents', 'plot_image') + FUNCTION = 'sample' + CATEGORY = 'test' + + def sample(self, model, seed, cfg, sampler_name, scheduler, positive, negative, latent_image_batch, denoise=1.0, alpha_1=0.1, reverse_input_batch=True, blending_schedule='cosine', stop_blending_at_pct=1.0, clamp_blending_at_pct=1.0, blending_function=list(BLENDING_FUNCTION_MAP.keys())[0]): + sampler = IterativeMixingKSampler() + return sampler(model, seed, cfg, sampler_name, scheduler, positive, negative, latent_image_batch, denoise=denoise, alpha_1=alpha_1, reverse_input_batch=True, blending_schedule=blending_schedule, stop_blending_at_pct=stop_blending_at_pct, clamp_blending_at_pct=clamp_blending_at_pct, blending_function=blending_function) +``` \ No newline at end of file diff --git a/docs/Iterative Mixing KSampler(ttulttul%2FComfyUI-Iterative-Mixer).md b/docs/Iterative Mixing KSampler(ttulttul%2FComfyUI-Iterative-Mixer).md new file mode 100644 index 0000000..6442112 --- /dev/null +++ b/docs/Iterative Mixing KSampler(ttulttul%2FComfyUI-Iterative-Mixer).md @@ -0,0 +1,101 @@ +# Documentation +- Class name: IterativeMixingKSamplerSimple +- Category: test +- Output node: False +- Repo Ref: https://github.com/ttulttul/ComfyUI-Iterative-Mixer + +该节点简化了迭代混合和采样过程,使得在单一框架内高效地添加和移除噪声成为可能。它旨在为那些希望尝试迭代采样技术但不想面对多个节点复杂性用户提供简化的工作流程。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了采样过程的基础。它影响生成样本的质量和特性,是节点功能的核心组成部分。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_management.Model +- positive + - 正向调节输入对于引导采样过程朝向期望结果是必不可少的。它影响生成样本的方向和性质,使其符合指定条件。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative + - 负向调节输入通过避免不良结果来帮助完善采样过程。它在引导生成远离不需要的特性方面发挥着关键作用。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- latent_image + - 潜在图像参数对于迭代混合过程至关重要,因为它代表了添加和移除噪声的起点。它显著影响样本的初始状态和演变。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- seed + - 种子参数对于确保采样过程的可重复性和一致性很重要。它初始化随机数生成,进而影响输出样本的变异性和多样性。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步骤参数决定了采样过程中的迭代次数,直接影响生成样本的复杂性和精细度。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数(或cfg)对于调整采样过程的内部设置至关重要。它影响节点的整体行为和性能,使其能够进行微调以获得最佳结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 采样器名称参数对于选择适当的采样方法至关重要。它决定了用于生成样本的策略,这可以显著改变最终输出。 + - Comfy dtype: COMBO[comfy.samplers.KSampler.SAMPLERS] + - Python dtype: str +- scheduler + - 调度器参数对于管理采样过程的进展至关重要。它控制迭代的步伐和时机,影响结果的效率和质量。 + - Comfy dtype: COMBO[comfy.samplers.KSampler.SCHEDULERS] + - Python dtype: str +- denoise + - 去噪参数在生成样本的精炼中扮演重要角色。它调整噪声减少的水平,可以提高最终输出的清晰度和质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- alpha_1 + - alpha_1参数在控制采样过程中的混合进度中至关重要。它影响样本的混合和融合方式,影响输出的最终外观和特性。 + - Comfy dtype: FLOAT + - Python dtype: float +- blending_schedule + - 混合进度参数是定义样本之间过渡的关键。它决定了混合策略,这可以显著影响生成序列的平滑性和连贯性。 + - Comfy dtype: COMBO[list(BLENDING_SCHEDULE_MAP.keys())] + - Python dtype: str +- blending_function + - 混合函数参数对于确定迭代过程中样本如何结合至关重要。它通过控制样本合并的方式影响最终结果。 + - Comfy dtype: COMBO[list(BLENDING_FUNCTION_MAP.keys())] + - Python dtype: str +- normalize_on_mean + - 均值归一化参数对于调整数据预处理步骤很重要。它影响输入数据的归一化,可以影响采样过程和生成样本的特性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- samples + - 输出样本代表了迭代混合和采样过程的最终结果。它们包含了输入参数和节点功能的精髓,展示了节点生成复杂和细腻数据模式的能力。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IterativeMixingKSamplerSimple: + """ + A simplified version of IterativeMixingKSamplerAdv, this node + does the noising (unsampling) and de-noising (sampling) all within + one node with easy settings. + """ + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'steps': ('INT', {'default': 40, 'min': 0, 'max': 10000}), 'cfg': ('FLOAT', {'default': 8.0, 'min': 0.0, 'max': 100.0, 'step': 0.1, 'round': 0.01}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'alpha_1': ('FLOAT', {'default': 2.4, 'min': 0.05, 'max': 100.0, 'step': 0.05}), 'blending_schedule': (list(BLENDING_SCHEDULE_MAP.keys()), {'default': 'cosine'}), 'blending_function': (list(BLENDING_FUNCTION_MAP.keys()), {'default': 'addition'}), 'normalize_on_mean': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'sample' + CATEGORY = 'test' + + def __init__(self): + self.batch_unsampler = BatchUnsampler() + + def sample(self, model, positive, negative, latent_image, seed, steps, cfg, sampler_name, scheduler, denoise, alpha_1, blending_schedule, blending_function, normalize_on_mean): + (z_primes,) = self.batch_unsampler.unsampler(model, sampler_name, scheduler, steps, 0, steps, latent_image, normalize=normalize_on_mean) + sampler = IterativeMixingKSampler() + (z_out, _, _, _) = sampler(model, seed, cfg, sampler_name, scheduler, positive, negative, z_primes, denoise=denoise, alpha_1=alpha_1, reverse_input_batch=True, blending_schedule=blending_schedule, blending_function=blending_function, stop_blending_at_pct=1.0) + return ({'samples': z_out['samples'][-1:]},) +``` \ No newline at end of file diff --git a/docs/Iterative Mixing KSampler.md b/docs/Iterative Mixing KSampler.md new file mode 100644 index 0000000..94cde2e --- /dev/null +++ b/docs/Iterative Mixing KSampler.md @@ -0,0 +1,92 @@ +# Documentation +- Class name: IterativeMixingKSampler +- Category: test +- Output node: False +- Repo Ref: https://github.com/deroberon/demofusion-comfyui + +该节点通过逐步引入一组参考潜在表示的指导,来细化一批潜在表示,旨在通过迭代混合提高生成样本的质量。 + +# Input types +## Required +- model + - 用于去噪和细化潜在表示的生成模型。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- seed + - 用于初始化噪声生成的随机数生成器的种子值。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 影响去噪过程的配置参数。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 用于迭代去噪过程的采样器名称。 + - Comfy dtype: ENUM + - Python dtype: str +- scheduler + - 用于随时间调整去噪过程的调度策略。 + - Comfy dtype: ENUM + - Python dtype: str +- step_increment + - 在每次去噪过程迭代中增加的步数。 + - Comfy dtype: INT + - Python dtype: int +- positive + - 用于指导去噪过程的正向调节数据。 + - Comfy dtype: CONDITIONING + - Python dtype: dict +- negative + - 用于进一步细化去噪过程的负向调节数据。 + - Comfy dtype: CONDITIONING + - Python dtype: dict +- latent_image_batch + - 需要被去噪和细化的潜在表示批次。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- denoise + - 控制每一步应用的去噪程度的参数。 + - Comfy dtype: FLOAT + - Python dtype: float +- alpha_1 + - 影响参考潜在表示与去噪样本之间混合速率的参数。 + - Comfy dtype: FLOAT + - Python dtype: float +- reverse_batch + - 一个标志,指示在处理之前是否应反转批次。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- latent_image_batch + - 经过迭代去噪过程后细化的潜在表示批次。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IterativeMixingKSampler: + """ + Take a batch of latents, z_prime, and progressively de-noise them + step by step from z_prime[0] to z_prime[steps], mixing in a weighted + fraction of z_prime[i] at each step so that de-noising is guided by + the z_prime latents. This batch sampler assumes that the number of steps + is just the length of z_prime, so there is no steps parameter. The parameter + latent_image_batch should come from the Batch Unsampler node. + """ + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'cfg': ('FLOAT', {'default': 8.0, 'min': 0.0, 'max': 100.0, 'step': 0.1, 'round': 0.01}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'step_increment': ('INT', {'default': 1, 'min': 1, 'max': 10000}), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image_batch': ('LATENT',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'alpha_1': ('FLOAT', {'default': 3.0, 'min': 0.1, 'max': 10.0}), 'reverse_batch': ('BOOLEAN', {'default': True})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'sample' + CATEGORY = 'test' + + def sample(self, model, seed, cfg, sampler_name, scheduler, step_increment, positive, negative, latent_image_batch, denoise=1.0, alpha_1=3.0, reverse_batch=True): + if reverse_batch: + latent_image_batch['samples'] = torch.flip(latent_image_batch['samples'], [0]) + return batched_ksampler(model, seed, cfg, sampler_name, scheduler, step_increment, positive, negative, latent_image_batch, denoise=denoise, alpha_1=alpha_1) +``` \ No newline at end of file diff --git a/docs/IterativeImageUpscale.md b/docs/IterativeImageUpscale.md new file mode 100644 index 0000000..e8e5aa8 --- /dev/null +++ b/docs/IterativeImageUpscale.md @@ -0,0 +1,82 @@ +# Documentation +- Class name: IterativeImageUpscale +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +IterativeImageUpscale节点的'doit'方法旨在执行迭代图像放大。它接收一张图像,并通过一系列细化步骤逐步提高其分辨率。该节点利用潜在空间模型对图像进行编码和解码,应用放大因子并在指定的步骤数上迭代,以实现所需的细节水平。 + +# Input types +## Required +- pixels + - 'pixels'参数表示需要放大的输入图像。这是一个关键元素,因为整个操作围绕通过迭代处理提高此图像的分辨率展开。 + - Comfy dtype: IMAGE + - Python dtype: np.ndarray +- upscale_factor + - 'upscale_factor'参数定义了放大过程中的放大级别。它决定了输入图像在处理后将被放大多少。 + - Comfy dtype: FLOAT + - Python dtype: float +- steps + - 'steps'参数表示在放大过程中要执行的迭代步骤数。更多的步骤通常会导致更平滑、更详细的放大图像。 + - Comfy dtype: INT + - Python dtype: int +- upscaler + - 'upscaler'参数指的是将应用于增加图像分辨率的放大方法或模型。它是放大过程的重要组成部分。 + - Comfy dtype: UPSCALER + - Python dtype: Any +- vae + - 'vae'参数是变分自编码器(VAE)的一个实例,用于在放大过程中对图像数据进行编码和解码。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +## Optional +- temp_prefix + - 'temp_prefix'参数用于指定在放大过程中存储中间结果的临时文件前缀。可以留空以使用默认行为。 + - Comfy dtype: STRING + - Python dtype: str +- step_mode + - 'step_mode'参数确定在每个步骤中用于缩放图像的方法。它可以是'simple'用于线性缩放,或者'geometric'用于指数缩放。 + - Comfy dtype: COMBO[simple, geometric] + - Python dtype: str +- unique_id + - 'unique_id'参数用于内部跟踪放大操作的进度和状态。它通常对用户隐藏,并自动分配。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- image + - 'image'输出参数代表了通过迭代放大过程得到的放大图像。它是节点功能的最终产物。 + - Comfy dtype: IMAGE + - Python dtype: np.ndarray + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IterativeImageUpscale: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pixels': ('IMAGE',), 'upscale_factor': ('FLOAT', {'default': 1.5, 'min': 1, 'max': 10000, 'step': 0.1}), 'steps': ('INT', {'default': 3, 'min': 1, 'max': 10000, 'step': 1}), 'temp_prefix': ('STRING', {'default': ''}), 'upscaler': ('UPSCALER',), 'vae': ('VAE',), 'step_mode': (['simple', 'geometric'], {'default': 'simple'})}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + def doit(self, pixels, upscale_factor, steps, temp_prefix, upscaler, vae, step_mode='simple', unique_id=None): + if temp_prefix == '': + temp_prefix = None + core.update_node_status(unique_id, 'VAEEncode (first)', 0) + if upscaler.is_tiled: + latent = nodes.VAEEncodeTiled().encode(vae, pixels, upscaler.tile_size)[0] + else: + latent = nodes.VAEEncode().encode(vae, pixels)[0] + refined_latent = IterativeLatentUpscale().doit(latent, upscale_factor, steps, temp_prefix, upscaler, step_mode, unique_id) + core.update_node_status(unique_id, 'VAEDecode (final)', 1.0) + if upscaler.is_tiled: + pixels = nodes.VAEDecodeTiled().decode(vae, refined_latent[0], upscaler.tile_size)[0] + else: + pixels = nodes.VAEDecode().decode(vae, refined_latent[0])[0] + core.update_node_status(unique_id, '', None) + return (pixels,) +``` \ No newline at end of file diff --git a/docs/IterativeLatentUpscale.md b/docs/IterativeLatentUpscale.md new file mode 100644 index 0000000..77c4c65 --- /dev/null +++ b/docs/IterativeLatentUpscale.md @@ -0,0 +1,97 @@ +# Documentation +- Class name: IterativeLatentUpscale +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +IterativeLatentUpscale节点的'doit'方法旨在通过指定数量的迭代步骤逐步放大样本的潜在表示。它智能地应用放大因子来增强潜在空间的分辨率,可能导致放大输出中的细节得到改善。此方法通过迭代细化潜在空间,旨在实现更高质量的放大,同时不损害底层结构,从而为整个过程做出贡献。 + +# Input types +## Required +- samples + - “samples”参数至关重要,因为它提供了节点将要放大的初始潜在表示。其质量和维度直接影响节点产生高分辨率输出的能力。这个参数对于迭代放大过程至关重要,并决定了增强的起点。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- upscale_factor + - “upscale_factor”参数决定了潜在样本将被放大的程度。它是控制放大输出最终分辨率的关键因素。此参数允许微调潜在空间的规模,以满足所需的输出尺寸。 + - Comfy dtype: FLOAT + - Python dtype: float +- steps + - “steps”参数定义了要执行的迭代放大步骤的数量。它很重要,因为它决定了迭代过程的粒度,允许对潜在空间进行更受控和渐进的增强。增加步骤的数量可以导致更平滑、更精细的放大结果。 + - Comfy dtype: INT + - Python dtype: int +- upscaler + - “upscaler”参数是一个必要的输入,它提供了放大潜在样本的机制。它包含了迭代放大过程所必需的逻辑和操作,对于确定节点功能的效率和效果至关重要。 + - Comfy dtype: UPSCALER + - Python dtype: comfy_extras.nodes_upscale_model.Upscaler +## Optional +- temp_prefix + - “temp_prefix”参数用于指定在放大过程中可能创建的临时文件的前缀。虽然不是必需的,但在组织或识别中间文件时可能很有用,特别是在涉及多个节点的复杂工作流程中。 + - Comfy dtype: STRING + - Python dtype: str +- step_mode + - “step_mode”参数规定了在迭代放大过程的每一步中增加规模的方法。它提供了简单线性进展或几何进展的选择,这可以显著影响放大输出中细节的分布。 + - Comfy dtype: COMBO[simple, geometric] + - Python dtype: str +- unique_id + - “unique_id”参数虽然是可选的,但可以用来跟踪节点在更大工作流程中的进度和状态。当同时运行节点的多个实例时,它特别有用,允许区分和监控各个节点的执行。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- latent + - “latent”输出代表了由迭代过程产生的放大的潜在表示。它是输入样本的精炼版本,具有增加的分辨率,可以用于进一步的处理或分析。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- vae + - “vae”输出提供了与放大的潜在表示相关的变分自编码器(VAE)模型。这个模型可以用于生成新样本对潜在空间进行进一步分析等其他任务。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class IterativeLatentUpscale: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'samples': ('LATENT',), 'upscale_factor': ('FLOAT', {'default': 1.5, 'min': 1, 'max': 10000, 'step': 0.1}), 'steps': ('INT', {'default': 3, 'min': 1, 'max': 10000, 'step': 1}), 'temp_prefix': ('STRING', {'default': ''}), 'upscaler': ('UPSCALER',), 'step_mode': (['simple', 'geometric'], {'default': 'simple'})}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('LATENT', 'VAE') + RETURN_NAMES = ('latent', 'vae') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + def doit(self, samples, upscale_factor, steps, temp_prefix, upscaler, step_mode='simple', unique_id=None): + w = samples['samples'].shape[3] * 8 + h = samples['samples'].shape[2] * 8 + if temp_prefix == '': + temp_prefix = None + if step_mode == 'geometric': + upscale_factor_unit = pow(upscale_factor, 1.0 / steps) + else: + upscale_factor_unit = max(0, (upscale_factor - 1.0) / steps) + current_latent = samples + scale = 1 + for i in range(steps - 1): + if step_mode == 'geometric': + scale *= upscale_factor_unit + else: + scale += upscale_factor_unit + new_w = w * scale + new_h = h * scale + core.update_node_status(unique_id, f'{i + 1}/{steps} steps | x{scale:.2f}', (i + 1) / steps) + print(f'IterativeLatentUpscale[{i + 1}/{steps}]: {new_w:.1f}x{new_h:.1f} (scale:{scale:.2f}) ') + step_info = (i, steps) + current_latent = upscaler.upscale_shape(step_info, current_latent, new_w, new_h, temp_prefix) + if scale < upscale_factor: + new_w = w * upscale_factor + new_h = h * upscale_factor + core.update_node_status(unique_id, f'Final step | x{upscale_factor:.2f}', 1.0) + print(f'IterativeLatentUpscale[Final]: {new_w:.1f}x{new_h:.1f} (scale:{upscale_factor:.2f}) ') + step_info = (steps - 1, steps) + current_latent = upscaler.upscale_shape(step_info, current_latent, new_w, new_h, temp_prefix) + core.update_node_status(unique_id, '', None) + return (current_latent, upscaler.vae) +``` \ No newline at end of file diff --git a/docs/IterativeMixingSampler.md b/docs/IterativeMixingSampler.md new file mode 100644 index 0000000..8b49919 --- /dev/null +++ b/docs/IterativeMixingSampler.md @@ -0,0 +1,125 @@ +# Documentation +- Class name: IterativeMixingSamplerNode +- Category: sampling/custom_sampling/samplers +- Output node: False +- Repo Ref: https://github.com/ttulttul/ComfyUI-Iterative-Mixer + +该节点通过迭代混合潜在变量来增强生成样本的多样性和质量。它通过逐步调整不同潜在变量在采样过程中的影响,实现了对生成输出的精细控制。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了采样器将使用的生成网络。它决定了节点将利用的基础架构和学习成果,以创建新的样本。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_management.Model +- sampler + - 采样器参数对于确定采样策略至关重要。它影响潜在变量的混合和交互方式,进而影响生成样本的多样性和一致性。 + - Comfy dtype: COMBO + - Python dtype: str +- alpha_1 + - Alpha_1 控制混合过程中主要潜在变量的初始影响。调整此参数可以显著改变生成内容的特点,使其成为实现预期结果的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- blending_schedule + - 混合进度定义了混合过程随时间的进展。它在确保不同潜在影响之间平滑过渡方面至关重要,有助于生成样本的自然演变。 + - Comfy dtype: COMBO + - Python dtype: str +- blending_function + - 该函数决定了在混合过程中潜在变量的组合方式。它在塑造生成样本的最终特征方面起着关键作用,因为它控制了它们的总体构成。 + - Comfy dtype: COMBO + - Python dtype: str +- normalize_on_mean + - 启用此参数后,确保潜在变量基于它们的均值进行归一化。这有助于实现更加平衡和可预测的混合过程,对于保持输出的一致性至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- start_blending_at_pct + - 此参数规定了混合过程的起点,作为总采样步骤的百分比。它对于调整混合的引入时机很重要,这影响了样本的整体质量和多样性。 + - Comfy dtype: FLOAT + - Python dtype: float +- stop_blending_at_pct + - 定义混合过程的停止点,此参数有助于控制混合的持续时间,从而影响生成样本的最终特征。 + - Comfy dtype: FLOAT + - Python dtype: float +- clamp_blending_at_pct + - 此参数将混合影响限制在指定的百分比内,确保混合不会压倒基础潜在变量,并在生成过程中保持平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- blend_min + - blend_min 参数设置了混合的最小值,确保混合潜在变量的贡献不是太微妙,并在塑造输出方面保持有效。 + - Comfy dtype: FLOAT + - Python dtype: float +- blend_max + - 通过设置混合的上限,blend_max 确保混合潜在变量的影响不会超过某个阈值,在不损害基础模型的完整性的情况下保持多样性。 + - Comfy dtype: FLOAT + - Python dtype: float +- perlin_mode + - perlin_mode 参数在混合过程中引入噪声模式,增加了随机性,这可以增强生成样本的创造性和可变性。 + - Comfy dtype: COMBO + - Python dtype: str +- perlin_strength + - Perlin 强度决定了噪声模式的强度,直接影响混合过程中变化的程度,从而影响输出的多样性。 + - Comfy dtype: FLOAT + - Python dtype: float +- perlin_scale + - Perlin 噪声的规模影响了噪声模式的粒度,进而影响了生成样本的细部细节和纹理。 + - Comfy dtype: FLOAT + - Python dtype: float +- rewind + - 启用回放功能后,节点可以重新访问采样过程中的先前步骤,提供了对迭代混合的更多控制,并可能导致更精细的结果。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- rewind_min + - rewind_min 设置了回放过程的下限,确保节点不会在采样步骤中回退太远,这可能会破坏已取得的进展。 + - Comfy dtype: FLOAT + - Python dtype: float +- rewind_max + - rewind_max 确定了回放过程的上限,防止过度回溯可能导致生成样本中期望特征的丢失。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- sampler + - 输出采样器是一个配置好的采样策略实例,它结合了各种参数以产生多样化和高质量的生成样本,反映了潜在变量的精细混合。 + - Comfy dtype: SAMPLER + - Python dtype: comfy.samplers.KSampler + +# Usage tips +- Infra type: GPU + +# Source code +``` +class IterativeMixingSamplerNode: + """ + A sampler implementing iterative mixing of latents. + Use this with the SamplerCustom node. + """ + PERLIN_MODES = ['masks', 'latents', 'matched_noise'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'sampler': (list(SAMPLERS_MAP.keys()), {'default': 'euler'}), 'alpha_1': ('FLOAT', {'default': 2.4, 'min': 0.05, 'max': 100.0, 'step': 0.05}), 'blending_schedule': (list(BLENDING_SCHEDULE_MAP.keys()), {'default': 'cosine'}), 'blending_function': (list(BLENDING_FUNCTION_MAP.keys()), {'default': 'addition'}), 'normalize_on_mean': ('BOOLEAN', {'default': False}), 'start_blending_at_pct': ('FLOAT', {'default': 0.0, 'min': 0.0, 'step': 0.01}), 'stop_blending_at_pct': ('FLOAT', {'default': 1.0, 'min': 0.0, 'step': 0.01}), 'clamp_blending_at_pct': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'blend_min': ('FLOAT', {'default': 0.0, 'step': 0.01}), 'blend_max': ('FLOAT', {'default': 1.0, 'step': 0.01}), 'perlin_mode': (s.PERLIN_MODES, {'default': 'masks'}), 'perlin_strength': ('FLOAT', {'default': 0.75, 'step': 0.001}), 'perlin_scale': ('FLOAT', {'default': 10.0, 'min': 0.1, 'max': 400.0}), 'rewind': ('BOOLEAN', {'default': False}), 'rewind_min': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 0.99}), 'rewind_max': ('FLOAT', {'default': 0.8, 'min': 0.01, 'max': 0.99})}} + RETURN_TYPES = ('SAMPLER',) + CATEGORY = 'sampling/custom_sampling/samplers' + FUNCTION = 'get_sampler' + + def set_steps(self, steps, denoise=None): + self.steps = steps + if denoise is None or denoise > 0.9999: + self.sigmas = self.calculate_sigmas(steps).to(self.device) + else: + new_steps = int(steps / denoise) + sigmas = self.calculate_sigmas(new_steps).to(self.device) + self.sigmas = sigmas[-(steps + 1):] + + def get_sampler(self, model, sampler, alpha_1, blending_schedule, blending_function, normalize_on_mean, start_blending_at_pct, stop_blending_at_pct, clamp_blending_at_pct, blend_min, blend_max, perlin_mode, perlin_strength, perlin_scale, rewind, rewind_min, rewind_max): + extras = {k: v for (k, v) in locals().items() if k != 'self'} + extras['model_node'] = extras['model'] + del extras['model'] + if sampler not in SAMPLERS_MAP: + raise ValueError(f'invalid sampler: {sampler}') + sampler_obj = SAMPLERS_MAP[sampler]() + sampler_fn = functools.partial(sampler_obj.__call__) + del extras['sampler'] + sampler = comfy.samplers.KSAMPLER(sampler_fn, extra_options=extras) + return (sampler,) +``` \ No newline at end of file diff --git a/docs/IterativeMixingScheduler.md b/docs/IterativeMixingScheduler.md new file mode 100644 index 0000000..cc42088 --- /dev/null +++ b/docs/IterativeMixingScheduler.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: IterativeMixingScheduler +- Category: sampling/custom_sampling/schedulers +- Output node: False +- Repo Ref: https://github.com/ttulttul/ComfyUI-Iterative-Mixer + +迭代混合调度器节点旨在生成一系列噪声水平,即sigmas,这些在从模型采样的迭代混合过程中使用。它利用调度器控制噪声水平的进展,并且能够根据去噪参数调整步数,以微调采样过程。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它代表了从中抽取样本的生成模型。它是决定采样过程底层结构和能力的基石组件。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_management.Model +- scheduler + - 调度器参数定义了在采样过程中调整噪声水平的策略。它在确定生成样本的质量和收敛性方面起着重要作用。 + - Comfy dtype: SCHEDULER_NAMES + - Python dtype: str +- steps + - 步数参数指定了采样过程中的迭代次数。它直接影响噪声水平的粒度,进而影响最终样本的细节和准确性。 + - Comfy dtype: INT + - Python dtype: int +- denoise + - 去噪参数通过调整去除噪声的速率,允许对采样过程进行微调。它可能显著影响生成样本的清晰度和细节。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- sigmas + - sigmas输出提供了指导迭代采样过程的计算出的噪声水平序列。这是一个关键的输出,直接影响最终样本的生成。 + - Comfy dtype: SIGMAS + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IterativeMixingScheduler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'scheduler': (comfy.samplers.SCHEDULER_NAMES,), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('SIGMAS',) + CATEGORY = 'sampling/custom_sampling/schedulers' + FUNCTION = 'get_sigmas' + + @torch.no_grad() + def get_sigmas(self, model, scheduler, steps, denoise): + sigmas = None + cs = comfy.samplers.calculate_sigmas_scheduler + if denoise is None or denoise > 0.9999: + sigmas = cs(model.model, scheduler, steps).cpu() + else: + new_steps = int(steps / denoise) + sigmas = cs(model.model, scheduler, new_steps).cpu() + sigmas = sigmas[-(steps + 1):] + return (sigmas,) +``` \ No newline at end of file diff --git a/docs/IterativeMixingSchedulerAdvanced.md b/docs/IterativeMixingSchedulerAdvanced.md new file mode 100644 index 0000000..560c5e7 --- /dev/null +++ b/docs/IterativeMixingSchedulerAdvanced.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: IterativeMixingSchedulerAdvanced +- Category: sampling/custom_sampling/schedulers +- Output node: False +- Repo Ref: https://github.com/ttulttul/ComfyUI-Iterative-Mixer + +IterativeMixingSchedulerAdvanced节点旨在为迭代采样过程生成一系列噪声水平,即sigmas。它根据去噪参数智能调整采样步骤,确保输出精细调整到所需的噪声减少水平。该节点在控制高级迭代采样技术的采样计划中发挥关键作用,有助于提高采样过程的整体质量和效率。 + +# Input types +## Required +- model + - 模型参数对节点的操作至关重要,因为它定义了将要应用调度器的生成模型。它直接影响生成的sigmas的质量和类型,这对于采样过程至关重要。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_management.Model +- scheduler + - 调度器参数决定了采样过程中将使用的调度策略。它是计算sigmas的关键因素,因此影响迭代采样的整体性能。 + - Comfy dtype: SCHEDULER_NAMES + - Python dtype: str +- steps + - steps参数指定了采样过程中要进行的迭代次数或步骤数。它是控制采样计划持续时间和粒度的重要因素。 + - Comfy dtype: INT + - Python dtype: int +- start_at_step + - start_at_step参数允许自定义采样计划的起始点。它可以用来跳过初始步骤或在过程的特定点开始采样。 + - Comfy dtype: INT + - Python dtype: int +- end_at_step + - end_at_step参数定义了采样计划的终点。它可以用来限制执行的步骤数,在预定点停止采样过程。 + - Comfy dtype: INT + - Python dtype: int +- denoise + - denoise参数在采样过程中调整噪声减少的水平。它是确定最终输出质量的关键因素,通过控制去噪步骤的强度来实现。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- sigmas + - sigmas输出代表了节点生成的噪声水平序列。这些值在迭代采样过程中起着指导作用,引导模型产生更高质量的输出。 + - Comfy dtype: SIGMAS + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IterativeMixingSchedulerAdvanced: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'scheduler': (comfy.samplers.SCHEDULER_NAMES,), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'start_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'end_at_step': ('INT', {'default': 10000, 'min': 0, 'max': 10000}), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('SIGMAS',) + CATEGORY = 'sampling/custom_sampling/schedulers' + FUNCTION = 'get_sigmas' + + @torch.no_grad() + def get_sigmas(self, model, scheduler, steps, start_at_step, end_at_step, denoise): + sigmas = None + cs = comfy.samplers.calculate_sigmas_scheduler + if denoise is None or denoise > 0.9999: + sigmas = cs(model.model, scheduler, steps).cpu() + else: + new_steps = int(steps / denoise) + sigmas = cs(model.model, scheduler, new_steps).cpu() + sigmas = sigmas[-(steps + 1):] + if end_at_step is not None and end_at_step < len(sigmas) - 1: + sigmas = sigmas[:end_at_step + 1] + if start_at_step is not None: + if start_at_step < len(sigmas) - 1: + sigmas = sigmas[start_at_step:] + else: + return torch.Tensor([]) + return (sigmas,) +``` \ No newline at end of file diff --git a/docs/JDC_AutoContrast.md b/docs/JDC_AutoContrast.md new file mode 100644 index 0000000..cbcfb1d --- /dev/null +++ b/docs/JDC_AutoContrast.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: AutoContrast +- Category: image/postprocessing +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +该节点通过拉伸图像的强度值范围来增强图像的对比度,使其跨越一个期望的范围,提高了图像的视觉吸引力和清晰度,同时不会改变其基本特征。 + +# Input types +## Required +- IMAGE + - 输入图像,其对比度将由节点进行调整,作为增强过程的基础。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +## Optional +- cutoff + - 该参数控制应用于图像的对比度增强程度,较高的值会导致对比度变化更加明显。 + - Comfy dtype: FLOAT + - Python dtype: float +- min_value + - 该参数设置图像中不受对比度调整影响的最小值,保留了阴影部分的细节。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - 输出是对比度提高的图像,适合进一步处理或显示。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class AutoContrast: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'IMAGE': ('IMAGE',), 'cutoff': ('FLOAT', {'default': 2, 'min': 0, 'max': 100, 'step': 0.01}), 'min_value': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'process_image' + CATEGORY = 'image/postprocessing' + + def process_image(self, IMAGE, cutoff, min_value): + cimg = conv_tensor_pil(IMAGE) + if min_value >= 0: + return conv_pil_tensor(ImageOps.autocontrast(cimg, cutoff=cutoff, ignore=min_value)) + else: + return conv_pil_tensor(ImageOps.autocontrast(cimg, cutoff=cutoff)) +``` \ No newline at end of file diff --git a/docs/JDC_BlendImages.md b/docs/JDC_BlendImages.md new file mode 100644 index 0000000..415fb71 --- /dev/null +++ b/docs/JDC_BlendImages.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: BlendImages +- Category: image/postprocessing +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +BlendImages类实现了将两张图片无缝融合的功能,通过调整一张图片的透明度并将其覆盖在另一张图片上,从而创造出在原始元素之间平滑过渡的复合图片。 + +# Input types +## Required +- IMAGE_A + - IMAGE_A是作为融合过程基础层的第一张输入图片。其视觉元素对确定最终组合的基础和整体美学起着至关重要的作用。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- IMAGE_B + - IMAGE_B是要融合到由IMAGE_A提供的基础层上的第二张输入图片。它在为最终图片增加深度和复杂性方面至关重要,有助于合成图像的丰富性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- blend + - blend参数控制IMAGE_B覆盖在IMAGE_A上时的透明度水平。该参数在平衡两张图片、确保自然和视觉上令人愉悦的融合中至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- IMAGE + - 输出的IMAGE代表了融合过程的最终结果,将两张输入图片的视觉元素结合成一张单一的、连贯的图片。这证明了该节点将不同的元素融合成一个和谐整体的能力。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BlendImages: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'IMAGE_A': ('IMAGE',), 'IMAGE_B': ('IMAGE',), 'blend': ('FLOAT', {'default': 0.5, 'min': 0, 'max': 1, 'step': 0.001})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'process_image' + CATEGORY = 'image/postprocessing' + + def process_image(self, IMAGE_A, IMAGE_B, blend): + source_a = conv_tensor_pil(IMAGE_A) + source_b = conv_tensor_pil(IMAGE_B) + (aw, ah) = (source_a.width, source_a.height) + (bw, bh) = (source_b.width, source_b.height) + img_a = Image.new('RGB', (aw, ah)) + img_a.paste(source_a) + img_b = Image.new('RGB', (bw, bh)) + img_b.paste(source_b) + if aw != bw or ah != bh: + img_b.resize((aw, ah), resample=get_pil_resampler('lanczos')) + return conv_pil_tensor(Image.blend(img_a, img_b, blend)) +``` \ No newline at end of file diff --git a/docs/JDC_BrownNoise.md b/docs/JDC_BrownNoise.md new file mode 100644 index 0000000..e61d709 --- /dev/null +++ b/docs/JDC_BrownNoise.md @@ -0,0 +1,142 @@ +# Documentation +- Class name: BrownNoise +- Category: image/noise +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +BrownNoise节点旨在生成具有棕色噪声的图像,这是一种模拟自然变化的视觉噪声类型。它有助于创建随机但和谐的视觉效果,可用于多种目的,如视觉效果或图像处理任务中的数据增强。 + +# Input types +## Required +- width + - 宽度参数定义了生成的噪声图像的宽度。它对于确定输出图像的尺寸至关重要,因此影响整体视觉效果。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置噪声图像的高度。它与宽度一起工作,以确定图像的总体大小,影响最终的展示效果。 + - Comfy dtype: INT + - Python dtype: int +- value_min + - value_min参数允许设置噪声强度的最小值。它提供对噪声值下限的控制,影响图像的整体暗度。 + - Comfy dtype: INT + - Python dtype: int +- value_max + - value_max参数设置了噪声强度的上限。它对于控制图像中噪声值的亮度和范围很重要。 + - Comfy dtype: INT + - Python dtype: int +- red_min + - red_min参数指定了噪声中红色通道的最小强度。它在调整输出图像的颜色平衡,使其偏向红色调方面发挥作用。 + - Comfy dtype: INT + - Python dtype: int +- red_max + - red_max参数决定了红色通道的最大强度。它对于设置噪声图像中红色调的上限至关重要。 + - Comfy dtype: INT + - Python dtype: int +- green_min + - green_min参数设置了绿色通道强度的下限。它通过允许噪声模式中有更多的绿色或更少的绿色来影响颜色组成。 + - Comfy dtype: INT + - Python dtype: int +- green_max + - green_max参数定义了绿色通道强度的上限。它控制噪声图像中绿色调的存在。 + - Comfy dtype: INT + - Python dtype: int +- blue_min + - blue_min参数建立了蓝色通道噪声的最小值。它是微调噪声图像中蓝色阴影的关键。 + - Comfy dtype: INT + - Python dtype: int +- blue_max + - blue_max参数设置了蓝色通道噪声的最大值。它对于生成图像中蓝色饱和度的总体水平很重要。 + - Comfy dtype: INT + - Python dtype: int +- seed + - seed参数用于初始化随机数生成器,确保噪声模式的可重复性。它对于在不同运行中获得一致的结果至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - IMAGE输出提供了生成的棕色噪声图像。它很重要,因为它是节点操作的主要结果,包含了视觉噪声效果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BrownNoise: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 128, 'max': 8192, 'step': 8}), 'height': ('INT', {'default': 512, 'min': 128, 'max': 8192, 'step': 8}), 'value_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'value_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'red_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'red_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'green_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'green_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'blue_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'blue_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'generate_noise' + CATEGORY = 'image/noise' + + def generate_noise(self, width, height, value_min, value_max, red_min, red_max, green_min, green_max, blue_min, blue_max, seed): + w = width + h = height + aw = copy.deepcopy(w) + ah = copy.deepcopy(h) + outimage = Image.new('RGB', (aw, ah)) + random.seed(seed) + clamp_v_min = value_min + clamp_v_max = value_max + clamp_r_min = red_min + clamp_r_max = red_max + clamp_g_min = green_min + clamp_g_max = green_max + clamp_b_min = blue_min + clamp_b_max = blue_max + lv = 0 + mv = 0 + if clamp_v_min == -1: + lv = 0 + else: + lv = clamp_v_min + if clamp_v_max == -1: + mv = 255 + else: + mv = clamp_v_max + lr = 0 + mr = 0 + if clamp_r_min == -1: + lr = lv + else: + lr = clamp_r_min + if clamp_r_max == -1: + mr = mv + else: + mr = clamp_r_max + lg = 0 + mg = 0 + if clamp_g_min == -1: + lg = lv + else: + lg = clamp_g_min + if clamp_g_max == -1: + mg = mv + else: + mg = clamp_g_max + lb = 0 + mb = 0 + if clamp_b_min == -1: + lb = lv + else: + lb = clamp_b_min + if clamp_b_max == -1: + mb = mv + else: + mb = clamp_b_max + pbar = comfy.utils.ProgressBar(ah) + step = 0 + for y in range(ah): + for x in range(aw): + nr = clamp(int(np.power(np.power(random.randint(lr, mr) / 255, 1 / 3), 1 / 3) * 255), 0, 255) + ng = clamp(int(np.power(np.power(random.randint(lg, mg) / 255, 1 / 3), 1 / 3) * 255), 0, 255) + nb = clamp(int(np.power(np.power(random.randint(lb, mb) / 255, 1 / 3), 1 / 3) * 255), 0, 255) + outimage.putpixel((x, y), (nr, ng, nb)) + step += 1 + pbar.update_absolute(step, ah) + return conv_pil_tensor(outimage) +``` \ No newline at end of file diff --git a/docs/JDC_Contrast.md b/docs/JDC_Contrast.md new file mode 100644 index 0000000..f292e94 --- /dev/null +++ b/docs/JDC_Contrast.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: ImageContrast +- Category: image/postprocessing +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +该节点旨在通过调整图像的对比度和亮度来提升其视觉吸引力。它增强图像的对比度以改善其光影元素之间的区分度,从而产生更加醒目的视觉输出。此外,它还调整亮度,允许修改图像的整体明亮度或暗度,这对于各种视觉效果或满足特定的美学要求至关重要。 + +# Input types +## Required +- IMAGE + - 图像参数是必需的,因为它是节点处理的主要输入。它是节点应用其对比度和亮度调整的媒介,输入的质量和分辨率直接影响最终输出。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +## Optional +- contrast + - 对比度参数在节点操作中扮演重要角色,因为它控制图像对比度的增强。通过调整此参数,节点可以使图像的光暗区域更加分明,从而改善整体视觉冲击。 + - Comfy dtype: FLOAT + - Python dtype: float +- brightness + - 亮度参数对于调整图像的整体明亮度或暗度至关重要。它可以用于创造特定的情绪或效果,其调整直接影响图像的最终外观。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- IMAGE + - 输出图像是节点处理的结果,反映了对输入图像对比度和亮度所做的调整。它是节点功能的结晶,并作为进一步图像处理或分析的基础。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageContrast: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'IMAGE': ('IMAGE',), 'contrast': ('FLOAT', {'default': 1, 'min': 0, 'max': 10, 'step': 0.01}), 'brightness': ('FLOAT', {'default': 1, 'min': 0, 'max': 10, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'process_image' + CATEGORY = 'image/postprocessing' + + def process_image(self, IMAGE, contrast, brightness): + cimg = conv_tensor_pil(IMAGE) + (w, h) = cimg.size + pbar = comfy.utils.ProgressBar(2) + step = 0 + cnt = ImageEnhance.Contrast(cimg) + cimg = cnt.enhance(contrast) + step += 1 + pbar.update_absolute(step, h) + brt = ImageEnhance.Brightness(cimg) + cimg = brt.enhance(brightness) + step += 1 + pbar.update_absolute(step, h) + return conv_pil_tensor(cimg) +``` \ No newline at end of file diff --git a/docs/JDC_EqualizeGrey.md b/docs/JDC_EqualizeGrey.md new file mode 100644 index 0000000..2c0f458 --- /dev/null +++ b/docs/JDC_EqualizeGrey.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: Equalize +- Category: image/postprocessing +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +该节点类旨在通过调整图像的直方图来增强对比度,这通过分散像素强度值来改善图像的视觉清晰度和细节,使其更适合进一步分析或可视化,确保结果更加清晰和视觉上吸引人。 + +# Input types +## Required +- IMAGE + - IMAGE参数是必不可少的,因为它提供了将由节点处理的输入图像。它直接影响输出,决定了增强图像的质量和外观。没有这个输入,节点无法执行其预期功能。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Output types +- IMAGE + - 输出的IMAGE代表输入的加工版本,具有更好的对比度和视觉清晰度。它是节点功能直接的结果,对后续的图像分析或显示至关重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Equalize: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'IMAGE': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'process_image' + CATEGORY = 'image/postprocessing' + + def process_image(self, IMAGE): + cimg = conv_tensor_pil(IMAGE) + return conv_pil_tensor(ImageOps.equalize(cimg)) +``` \ No newline at end of file diff --git a/docs/JDC_GaussianBlur.md b/docs/JDC_GaussianBlur.md new file mode 100644 index 0000000..d718608 --- /dev/null +++ b/docs/JDC_GaussianBlur.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: GaussianBlur +- Category: image/postprocessing +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +该节点对图像应用高斯模糊,常用于降低噪声或创建柔和效果。它强调节点在提高图像质量以及通过平滑图像外观为进一步处理做准备的作用。 + +# Input types +## Required +- IMAGE + - 图像参数是必需的,因为它是高斯模糊操作的主要输入。它决定了处理后输出的质量和特征。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +## Optional +- blur_radius + - 模糊半径参数控制模糊效果的程度。它影响最终图像的平滑度,较大的半径会导致更明显的模糊。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- IMAGE + - 输出图像是应用高斯模糊后的结果。它代表了输入图像的转换,现在具有减少的噪声和更柔和的外观。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GaussianBlur: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'IMAGE': ('IMAGE',), 'blur_radius': ('FLOAT', {'default': 1, 'min': 1, 'max': 1024, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'process_image' + CATEGORY = 'image/postprocessing' + + def process_image(self, IMAGE, blur_radius): + img = conv_tensor_pil(IMAGE) + return conv_pil_tensor(img.filter(ImageFilter.GaussianBlur(blur_radius))) +``` \ No newline at end of file diff --git a/docs/JDC_GreyNoise.md b/docs/JDC_GreyNoise.md new file mode 100644 index 0000000..70f73d1 --- /dev/null +++ b/docs/JDC_GreyNoise.md @@ -0,0 +1,144 @@ +# Documentation +- Class name: GreyNoise +- Category: image/noise +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +GreyNoise类用于按需生成噪声图像,并通过可定制的参数提供工具以支持各种图像处理任务和噪声分析。 + +# Input types +## Required +- width + - 宽度决定了生成的噪声图像的水平维度,并显著影响噪声生成的整体画布。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度设置了噪声图像的垂直维度,这对定义图像的结构和布局至关重要。 + - Comfy dtype: INT + - Python dtype: int +- seed + - 种子用于初始化随机数生成器,确保可重复的噪声模式以获得一致的实验结果。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- value_min + - 值最小值设定了噪声强度的下限,影响了图像中可能的最小噪声水平。 + - Comfy dtype: INT + - Python dtype: int +- value_max + - 值最大值设定了噪声强度的上限,控制最大噪声水平以实现期望的视觉效果。 + - Comfy dtype: INT + - Python dtype: int +- red_min + - 红色最小值指定了红色通道的最小值,影响噪声图像中的整体色调和颜色分布。 + - Comfy dtype: INT + - Python dtype: int +- red_max + - 红色最大值定义了红色通道的最大值,规定了颜色范围的上限并有助于最终的外观表现。 + - Comfy dtype: INT + - Python dtype: int +- green_min + - 绿色通道最小值设定了绿色通道的最小值,影响中程色调和整体颜色平衡。 + - Comfy dtype: INT + - Python dtype: int +- green_max + - 绿色通道最大值设定了绿色通道的最大值,控制中程色调的上限。 + - Comfy dtype: INT + - Python dtype: int +- blue_min + - 蓝色最小值指定了蓝色通道的最小值,影响噪声图像的整体冷度或暖度。 + - Comfy dtype: INT + - Python dtype: int +- blue_max + - 蓝色最大值定义了蓝色通道的最大值,决定了最终图像中冷度或暖度的上限。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - 输出是一个反映输入参数的噪声图像,作为按需生成的噪声的视觉表示。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GreyNoise: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 128, 'max': 8192, 'step': 8}), 'height': ('INT', {'default': 512, 'min': 128, 'max': 8192, 'step': 8}), 'value_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'value_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'red_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'red_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'green_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'green_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'blue_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'blue_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'generate_noise' + CATEGORY = 'image/noise' + + def generate_noise(self, width, height, value_min, value_max, red_min, red_max, green_min, green_max, blue_min, blue_max, seed): + w = width + h = height + aw = copy.deepcopy(w) + ah = copy.deepcopy(h) + outimage = Image.new('RGB', (aw, ah)) + random.seed(seed) + clamp_v_min = value_min + clamp_v_max = value_max + clamp_r_min = red_min + clamp_r_max = red_max + clamp_g_min = green_min + clamp_g_max = green_max + clamp_b_min = blue_min + clamp_b_max = blue_max + lv = 0 + mv = 0 + if clamp_v_min == -1: + lv = 0 + else: + lv = clamp_v_min + if clamp_v_max == -1: + mv = 255 + else: + mv = clamp_v_max + lr = 0 + mr = 0 + if clamp_r_min == -1: + lr = lv + else: + lr = clamp_r_min + if clamp_r_max == -1: + mr = mv + else: + mr = clamp_r_max + lg = 0 + mg = 0 + if clamp_g_min == -1: + lg = lv + else: + lg = clamp_g_min + if clamp_g_max == -1: + mg = mv + else: + mg = clamp_g_max + lb = 0 + mb = 0 + if clamp_b_min == -1: + lb = lv + else: + lb = clamp_b_min + if clamp_b_max == -1: + mb = mv + else: + mb = clamp_b_max + pbar = comfy.utils.ProgressBar(ah) + step = 0 + for y in range(ah): + for x in range(aw): + nv = random.randint(lv, mv) + nr = int(remap(nv, lv, mv, lr, mr)) + ng = int(remap(nv, lv, mv, lg, mg)) + nb = int(remap(nv, lv, mv, lb, mb)) + outimage.putpixel((x, y), (nr, ng, nb)) + step += 1 + pbar.update_absolute(step, ah) + return conv_pil_tensor(outimage) +``` \ No newline at end of file diff --git a/docs/JDC_Greyscale.md b/docs/JDC_Greyscale.md new file mode 100644 index 0000000..e462721 --- /dev/null +++ b/docs/JDC_Greyscale.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: GreyScale +- Category: image/postprocessing +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +该节点旨在将输入的彩色图像转换为灰度图像,通过关注亮度变化来增强视觉细节的清晰度。它是图像处理流程中的基础步骤,使得后续的任务,如特征提取和图像分析,能够在简化的灰度数据上更有效地进行。 + +# Input types +## Required +- IMAGE + - IMAGE参数是必要的,因为它提供了灰度转换过程的原始输入。它影响节点的整体操作,决定了输出图像的尺寸和质量。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Output types +- IMAGE + - 输出的IMAGE是输入图像的灰度处理版本,对于后续的图像分析任务至关重要,并作为图像处理栈中的基础层。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GreyScale: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'IMAGE': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'process_image' + CATEGORY = 'image/postprocessing' + + def process_image(self, IMAGE): + cimg = conv_tensor_pil(IMAGE) + gimg = ImageOps.grayscale(cimg) + rgbimg = Image.new('RGB', (gimg.width, gimg.height)) + rgbimg.paste(gimg) + return conv_pil_tensor(rgbimg) +``` \ No newline at end of file diff --git a/docs/JDC_ImageLoader.md b/docs/JDC_ImageLoader.md new file mode 100644 index 0000000..176f73a --- /dev/null +++ b/docs/JDC_ImageLoader.md @@ -0,0 +1,82 @@ +# Documentation +- Class name: LoadImagePath +- Category: image +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +LoadImagePath节点旨在从指定的路径或URL获取和处理图像数据。它可以处理在线图像(通过下载)和本地图像(直接打开文件)。该节点能够将图像转换为适合进一步处理的格式,包括归一化和转换为张量,如果可用,还会提取掩码。这个节点对于启动工作流中的基于图像的操作至关重要。 + +# Input types +## Required +- image + - 'image'参数至关重要,因为它定义了图像数据的来源。它可以是本地文件路径或指向在线图像的URL。节点使用此输入来相应地检索和处理图像,使其成为节点操作的关键元素。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- image + - 'image'输出是输入图像的加工版本,转换为适合进一步计算任务的张量格式。它是节点功能的关键结果,使得后续的图像分析和操作成为可能。 + - Comfy dtype: TENSOR + - Python dtype: torch.Tensor +- mask + - 当存在'mack'输出时,它以二进制掩码的形式提供了额外信息,该掩码从输入图像中派生而来。这个掩码可以用于图像处理工作流中的各种目的,如分割或对象识别。 + - Comfy dtype: TENSOR + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadImagePath: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('STRING', {'default': ''})}} + CATEGORY = 'image' + RETURN_TYPES = ('IMAGE', 'MASK') + FUNCTION = 'load_image' + + def load_image(self, image): + image_path = str(image) + image_path = image_path.replace('"', '') + i = None + if image_path.startswith('http'): + response = requests.get(image_path) + i = Image.open(BytesIO(response.content)).convert('RGB') + else: + i = Image.open(image_path) + i = ImageOps.exif_transpose(i) + image = i.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + if 'A' in i.getbands(): + mask = np.array(i.getchannel('A')).astype(np.float32) / 255.0 + mask = 1.0 - torch.from_numpy(mask) + else: + mask = torch.zeros((64, 64), dtype=torch.float32, device='cpu') + return (image, mask) + + @classmethod + def IS_CHANGED(s, image): + image_path = str(image) + image_path = image_path.replace('"', '') + m = hashlib.sha256() + if not image_path.startswith('http'): + with open(image_path, 'rb') as f: + m.update(f.read()) + return m.digest().hex() + else: + m.update(image.encode('utf-8')) + return m.digest().hex() + + @classmethod + def VALIDATE_INPUTS(s, image): + image_path = str(image) + image_path = image_path.replace('"', '') + if image_path.startswith('http'): + return True + if not os.path.isfile(image_path): + return 'No file found: {}'.format(image_path) + return True +``` \ No newline at end of file diff --git a/docs/JDC_ImageLoaderMeta.md b/docs/JDC_ImageLoaderMeta.md new file mode 100644 index 0000000..7dc43fc --- /dev/null +++ b/docs/JDC_ImageLoaderMeta.md @@ -0,0 +1,118 @@ +# Documentation +- Class name: LoadImagePathWithMetadata +- Category: image +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +LoadImagePathWithMetadata节点旨在加载图像文件及其相关元数据。它能够处理本地和远程图像路径,从各种图像格式中提取提示和负面提示,并返回图像数据数组、掩码、提示、负面提示、宽度和高度。 + +# Input types +## Required +- image + - 'image'参数是要处理的图像文件的路径。这是一个关键输入,因为节点的功能围绕从此路径加载和操作图像数据。图像可以是本地文件路径或远程图像的URL。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- image + - 'image'输出是输入图像的加工版本,转换为适合进一步分析或操作的格式。它是节点输出的关键组成部分,为下游任务提供了必要的视觉数据。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 如果可用,'mask'输出是从图像中提取的alpha通道,可用于分割目的。它代表了图像的透明度信息,特别适用于需要隔离背景的应用场景。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- prompt + - 'prompt'输出包含嵌入在图像元数据中的任何积极或创造性的指令。这些信息可用于指导后续图像处理或生成任务,为图像的预期用途提供上下文。 + - Comfy dtype: STRING + - Python dtype: str +- negative + - 'negative'输出包括任何旨在指导远离某些图像特征或属性的指令。这对于通过指定应避免的内容来细化图像生成算法的输出特别有用。 + - Comfy dtype: STRING + - Python dtype: str +- width + - 'width'输出提供了加载图像的宽度,以像素为单位,这是了解图像尺寸和纵横比的基本信息。 + - Comfy dtype: INT + - Python dtype: int +- height + - 'height'输出给出了加载图像的高度,以像素为单位,与宽度相辅相成,以全面了解图像的尺寸。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadImagePathWithMetadata: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('STRING', {'default': ''})}} + CATEGORY = 'image' + RETURN_TYPES = ('IMAGE', 'MASK', 'STRING', 'STRING', 'INT', 'INT') + RETURN_NAMES = ('image', 'mask', 'PROMPT', 'NEGATIVE', 'WIDTH', 'HEIGHT') + FUNCTION = 'load_image' + + def load_image(self, image): + image_path = str(image) + image_path = image_path.replace('"', '') + i = None + if image_path.startswith('http'): + response = requests.get(image_path) + i = Image.open(BytesIO(response.content)).convert('RGB') + else: + i = Image.open(image_path) + prompt = '' + negative = '' + width = i.width + height = i.height + if i.format == 'PNG': + if 'parameters' in i.info: + params = i.info.get('parameters') + (prompt, negative) = handle_auto1111(params) + elif 'negative_prompt' in i.info or 'Negative Prompt' in i.info: + params = str(i.info).replace("'", '"') + (prompt, negative) = handle_ezdiff(params) + elif 'sd-metadata' in i.info: + (prompt, negative) = handle_invoke_modern(i.info) + elif 'Dream' in i.info: + (prompt, negative) = handle_invoke_legacy(i.info) + elif i.info.get('Software') == 'NovelAI': + (prompt, negative) = handle_novelai(i.info) + elif 'XML:com.adobe.xmp' in i.info: + (prompt, negative) = handle_drawthings(i.info) + i = ImageOps.exif_transpose(i) + image = i.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + if 'A' in i.getbands(): + mask = np.array(i.getchannel('A')).astype(np.float32) / 255.0 + mask = 1.0 - torch.from_numpy(mask) + else: + mask = torch.zeros((64, 64), dtype=torch.float32, device='cpu') + return (image, mask, prompt, negative, width, height) + + @classmethod + def IS_CHANGED(s, image): + image_path = str(image) + image_path = image_path.replace('"', '') + m = hashlib.sha256() + if not image_path.startswith('http'): + with open(image_path, 'rb') as f: + m.update(f.read()) + return m.digest().hex() + else: + m.update(image.encode('utf-8')) + return m.digest().hex() + + @classmethod + def VALIDATE_INPUTS(s, image): + image_path = str(image) + image_path = image_path.replace('"', '') + if image_path.startswith('http'): + return True + if not os.path.isfile(image_path): + return 'No file found: {}'.format(image_path) + return True +``` \ No newline at end of file diff --git a/docs/JDC_PinkNoise.md b/docs/JDC_PinkNoise.md new file mode 100644 index 0000000..bb206b1 --- /dev/null +++ b/docs/JDC_PinkNoise.md @@ -0,0 +1,143 @@ +# Documentation +- Class name: PinkNoise +- Category: image/noise +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +PinkNoise节点旨在根据指定的尺寸和颜色范围生成带有噪声模式的图像,该模式模拟了粉红噪声谱。该节点特别适用于创建具有自然、非均匀像素强度分布的视觉内容,可应用于图像处理、计算机图形学和机器学习数据增强等多种场景。 + +# Input types +## Required +- width + - 宽度决定了输出图像的水平维度,这对于定义噪声模式将生成的画布至关重要。它直接影响生成图像的整体大小和分辨率。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度设置了输出图像的垂直维度,与宽度参数协同工作,确定图像的分辨率和整体尺寸。它是决定噪声模式规模的重要因素。 + - Comfy dtype: INT + - Python dtype: int +- seed + - 种子值用于初始化随机数生成器,确保噪声模式在节点的不同运行中是可复现和一致的。该参数对于保持噪声生成过程的可靠性和可预测性至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- value_min + - 值最小值设定了生成噪声的强度值的下限,允许控制噪声模式的最小亮度或暗度。该参数影响噪声的整体视觉效果,有助于实现所需的美学或效果。 + - Comfy dtype: INT + - Python dtype: int +- value_max + - 值最大值设定了噪声的强度值的上限,确保噪声模式不会超过一定的亮度水平。该参数在实现平衡和可控的噪声分布方面至关重要。 + - Comfy dtype: INT + - Python dtype: int +- red_min + - 红色最小值指定了噪声模式中红色通道的最小允许值,使得可以微调颜色谱,并确保生成的噪声满足特定的颜色要求。 + - Comfy dtype: INT + - Python dtype: int +- red_max + - 红色最大值设定了红色通道的最大值,控制噪声模式中红色色调的上限,并有助于整体颜色平衡。 + - Comfy dtype: INT + - Python dtype: int +- green_min + - 绿色最小值定义了噪声中绿色通道的最小值,允许对噪声的绿色成分进行精确控制,并确保最终图像与期望的颜色配置一致。 + - Comfy dtype: INT + - Python dtype: int +- green_max + - 绿色最大值设定了绿色通道的最大值,确保噪声模式中的绿色色调不超过某个阈值,并有助于整体颜色的和谐。 + - Comfy dtype: INT + - Python dtype: int +- blue_min + - 蓝色最小值设定了蓝色通道的最小值,允许用户控制噪声模式中蓝色的存在,并实现特定的视觉效果。 + - Comfy dtype: INT + - Python dtype: int +- blue_max + - 蓝色最大值定义了蓝色通道的最大值,确保噪声模式中的蓝色色调在期望的范围内,并有助于整体的颜色方案。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - 输出是根据指定参数生成的带有粉红噪声模式的图像。这个图像可以作为纹理、背景或输入用于进一步处理在各种应用中。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PinkNoise: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 128, 'max': 8192, 'step': 8}), 'height': ('INT', {'default': 512, 'min': 128, 'max': 8192, 'step': 8}), 'value_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'value_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'red_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'red_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'green_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'green_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'blue_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'blue_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'generate_noise' + CATEGORY = 'image/noise' + + def generate_noise(self, width, height, value_min, value_max, red_min, red_max, green_min, green_max, blue_min, blue_max, seed): + w = width + h = height + aw = copy.deepcopy(w) + ah = copy.deepcopy(h) + outimage = Image.new('RGB', (aw, ah)) + random.seed(seed) + clamp_v_min = value_min + clamp_v_max = value_max + clamp_r_min = red_min + clamp_r_max = red_max + clamp_g_min = green_min + clamp_g_max = green_max + clamp_b_min = blue_min + clamp_b_max = blue_max + lv = 0 + mv = 0 + if clamp_v_min == -1: + lv = 0 + else: + lv = clamp_v_min + if clamp_v_max == -1: + mv = 255 + else: + mv = clamp_v_max + lr = 0 + mr = 0 + if clamp_r_min == -1: + lr = lv + else: + lr = clamp_r_min + if clamp_r_max == -1: + mr = mv + else: + mr = clamp_r_max + lg = 0 + mg = 0 + if clamp_g_min == -1: + lg = lv + else: + lg = clamp_g_min + if clamp_g_max == -1: + mg = mv + else: + mg = clamp_g_max + lb = 0 + mb = 0 + if clamp_b_min == -1: + lb = lv + else: + lb = clamp_b_min + if clamp_b_max == -1: + mb = mv + else: + mb = clamp_b_max + pbar = comfy.utils.ProgressBar(ah) + step = 0 + for y in range(ah): + for x in range(aw): + nr = clamp(int(np.power(random.randint(lr, mr) / 255, 1 / 3) * 255), 0, 255) + ng = clamp(int(np.power(random.randint(lg, mg) / 255, 1 / 3) * 255), 0, 255) + nb = clamp(int(np.power(random.randint(lb, mb) / 255, 1 / 3) * 255), 0, 255) + outimage.putpixel((x, y), (nr, ng, nb)) + step += 1 + pbar.update_absolute(step, ah) + return conv_pil_tensor(outimage) +``` \ No newline at end of file diff --git a/docs/JDC_Plasma.md b/docs/JDC_Plasma.md new file mode 100644 index 0000000..e6d00cb --- /dev/null +++ b/docs/JDC_Plasma.md @@ -0,0 +1,206 @@ +# Documentation +- Class name: PlasmaNoise +- Category: image/noise +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +PlasmaNoise 节点旨在生成类似等离子体的噪声图案。它通过使用分形噪声算法创建基础图像,然后对颜色通道和钳制值进行调整,以产生视觉丰富和多样化的输出。该节点特别适用于创建具有自然、有机感觉的纹理或背景。 + +# Input types +## Required +- width + - 宽度参数定义了生成图像的宽度。它对于确定输出的总体尺寸至关重要,并影响噪声图案的细节和分辨率。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置生成图像的高度。它与宽度一起工作,以确定图像的纵横比和总体大小。 + - Comfy dtype: INT + - Python dtype: int +- turbulence + - 湍流参数控制噪声模式中的详细程度。较高的值会产生更复杂和多变的噪声,而较低的值则产生更平滑和更均匀的图案。 + - Comfy dtype: FLOAT + - Python dtype: float +- value_min + - value_min 参数允许为噪声模式设置最小值,可用于调整整体亮度或创建特定视觉效果。 + - Comfy dtype: INT + - Python dtype: int +- value_max + - value_max 参数设置噪声模式的最大值,可用于控制对比度或实现所需的美学效果。 + - Comfy dtype: INT + - Python dtype: int +- red_min + - red_min 参数指定红色通道的最小值,可以微调噪声模式内的颜色平衡和饱和度。 + - Comfy dtype: INT + - Python dtype: int +- red_max + - red_max 参数确定红色通道的最大值,允许控制噪声模式中红色色调的强度和活力。 + - Comfy dtype: INT + - Python dtype: int +- green_min + - green_min 参数设置绿色通道的最小值,这对于实现噪声模式中所需的颜色组成和和谐非常重要。 + - Comfy dtype: INT + - Python dtype: int +- green_max + - green_max 参数控制绿色通道的最大值,影响噪声模式的整体色调和绿色在其中的突出程度。 + - Comfy dtype: INT + - Python dtype: int +- blue_min + - blue_min 参数定义了蓝色通道的最小值,可以调整以创建特定的颜色情绪或增强噪声模式的某些视觉方面。 + - Comfy dtype: INT + - Python dtype: int +- blue_max + - blue_max 参数设置蓝色通道的最大值,这对于定义噪声模式中蓝色阴影的深度和丰富度至关重要。 + - Comfy dtype: INT + - Python dtype: int +- seed + - seed 参数用于初始化随机数生成器,确保使用相同的种子值时结果可重复。这对于在多个实例中生成一致的噪声模式特别有用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - IMAGE 输出提供了作为图像生成的等离子体噪声模式。它是节点处理的最终结果,代表了噪声生成算法的最终视觉结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PlasmaNoise: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 128, 'max': 8192, 'step': 8}), 'height': ('INT', {'default': 512, 'min': 128, 'max': 8192, 'step': 8}), 'turbulence': ('FLOAT', {'default': 2.75, 'min': 0.5, 'max': 32, 'step': 0.01}), 'value_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'value_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'red_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'red_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'green_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'green_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'blue_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'blue_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'generate_plasma' + CATEGORY = 'image/noise' + + def generate_plasma(self, width, height, turbulence, value_min, value_max, red_min, red_max, green_min, green_max, blue_min, blue_max, seed): + w = width + h = height + aw = copy.deepcopy(w) + ah = copy.deepcopy(h) + outimage = Image.new('RGB', (aw, ah)) + if w >= h: + h = w + else: + w = h + clamp_v_min = value_min + clamp_v_max = value_max + clamp_r_min = red_min + clamp_r_max = red_max + clamp_g_min = green_min + clamp_g_max = green_max + clamp_b_min = blue_min + clamp_b_max = blue_max + roughness = turbulence + pixmap = [] + random.seed(seed) + + def adjust(xa, ya, x, y, xb, yb): + if pixmap[x][y] == 0: + d = math.fabs(xa - xb) + math.fabs(ya - yb) + v = (pixmap[xa][ya] + pixmap[xb][yb]) / 2.0 + (random.random() - 0.555) * d * roughness + c = int(math.fabs(v + random.randint(-48, 48))) + if c < 0: + c = 0 + elif c > 255: + c = 255 + pixmap[x][y] = c + + def subdivide(x1, y1, x2, y2): + if not (x2 - x1 < 2.0 and y2 - y1 < 2.0): + x = int((x1 + x2) / 2.0) + y = int((y1 + y2) / 2.0) + adjust(x1, y1, x, y1, x2, y1) + adjust(x2, y1, x2, y, x2, y2) + adjust(x1, y2, x, y2, x2, y2) + adjust(x1, y1, x1, y, x1, y2) + if pixmap[x][y] == 0: + v = int((pixmap[x1][y1] + pixmap[x2][y1] + pixmap[x2][y2] + pixmap[x1][y2]) / 4.0) + pixmap[x][y] = v + subdivide(x1, y1, x, y) + subdivide(x, y1, x2, y) + subdivide(x, y, x2, y2) + subdivide(x1, y, x, y2) + pbar = comfy.utils.ProgressBar(4) + step = 0 + pixmap = [[0 for i in range(h)] for j in range(w)] + pixmap[0][0] = random.randint(0, 255) + pixmap[w - 1][0] = random.randint(0, 255) + pixmap[w - 1][h - 1] = random.randint(0, 255) + pixmap[0][h - 1] = random.randint(0, 255) + subdivide(0, 0, w - 1, h - 1) + r = copy.deepcopy(pixmap) + step += 1 + pbar.update_absolute(step, 4) + pixmap = [[0 for i in range(h)] for j in range(w)] + pixmap[0][0] = random.randint(0, 255) + pixmap[w - 1][0] = random.randint(0, 255) + pixmap[w - 1][h - 1] = random.randint(0, 255) + pixmap[0][h - 1] = random.randint(0, 255) + subdivide(0, 0, w - 1, h - 1) + g = copy.deepcopy(pixmap) + step += 1 + pbar.update_absolute(step, 4) + pixmap = [[0 for i in range(h)] for j in range(w)] + pixmap[0][0] = random.randint(0, 255) + pixmap[w - 1][0] = random.randint(0, 255) + pixmap[w - 1][h - 1] = random.randint(0, 255) + pixmap[0][h - 1] = random.randint(0, 255) + subdivide(0, 0, w - 1, h - 1) + b = copy.deepcopy(pixmap) + step += 1 + pbar.update_absolute(step, 4) + lv = 0 + mv = 0 + if clamp_v_min == -1: + lv = 0 + else: + lv = clamp_v_min + if clamp_v_max == -1: + mv = 255 + else: + mv = clamp_v_max + lr = 0 + mr = 0 + if clamp_r_min == -1: + lr = lv + else: + lr = clamp_r_min + if clamp_r_max == -1: + mr = mv + else: + mr = clamp_r_max + lg = 0 + mg = 0 + if clamp_g_min == -1: + lg = lv + else: + lg = clamp_g_min + if clamp_g_max == -1: + mg = mv + else: + mg = clamp_g_max + lb = 0 + mb = 0 + if clamp_b_min == -1: + lb = lv + else: + lb = clamp_b_min + if clamp_b_max == -1: + mb = mv + else: + mb = clamp_b_max + for y in range(ah): + for x in range(aw): + nr = int(remap(r[x][y], 0, 255, lr, mr)) + ng = int(remap(g[x][y], 0, 255, lg, mg)) + nb = int(remap(b[x][y], 0, 255, lb, mb)) + outimage.putpixel((x, y), (nr, ng, nb)) + step += 1 + pbar.update_absolute(step, 4) + return conv_pil_tensor(outimage) +``` \ No newline at end of file diff --git a/docs/JDC_PlasmaSampler.md b/docs/JDC_PlasmaSampler.md new file mode 100644 index 0000000..c8227d4 --- /dev/null +++ b/docs/JDC_PlasmaSampler.md @@ -0,0 +1,86 @@ +# Documentation +- Class name: PlasmaSampler +- Category: sampling +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +PlasmaSampler类封装了从给定模型生成样本的过程,使用各种参数来控制采样过程,如噪声、步数和去噪因子。它旨在提供采样方法的灵活性,允许样本生成采用随机和确定性方法。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了从中抽取样本的基础生成模型。它是采样过程的核心,直接影响生成样本的质量和特征。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- noise_seed + - 噪声种子参数初始化随机数生成器,确保添加到模型输入的噪声是可复现的。该参数对于一致的结果和控制实验至关重要。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步数参数决定了采样过程将经历的迭代次数。增加步数可以导致更精细和详细的样本,但也会增加计算时间。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数调整采样过程的配置,影响模型潜在空间的探索与利用之间的平衡。它是决定输出样本多样性和质量的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- denoise + - 去噪参数控制采样过程中应用的噪声减少水平。它对于完善最终样本的清晰度和质量很重要,需要在噪声和信号之间找到平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- latent_noise + - 潜在噪声参数在潜在空间中引入额外的噪声,这可以鼓励生成更多样化和创造性的样本。它是增强输出多样性的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 采样器名称参数选择了要使用的特定采样方法,这显著影响了样本生成过程的效率和效果。 + - Comfy dtype: COMBO + - Python dtype: str +- scheduler + - 调度器参数确定了随时间调整采样过程参数的调度策略,这可以改善生成样本的收敛性和稳定性。 + - Comfy dtype: COMBO + - Python dtype: str +- positive + - 正参数提供条件数据,引导采样过程生成符合特定期望特征的样本。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- negative + - 负参数提供条件数据,帮助排除生成样本中不需要的特征,完善整体结果。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- latent_image + - 潜在图像参数是模型潜在空间的输入表示,对于采样过程生成有意义和连贯的样本至关重要。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +## Optional +- distribution_type + - 分布类型参数提供了默认和随机采样策略之间的选择,影响生成样本的多样性和独特性。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- latent + - 潜在参数包含了输出样本,代表了采样过程的结果。它是关键组件,因为它包含了与输入参数和模型约束相一致的生成数据。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class PlasmaSampler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'noise_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'cfg': ('FLOAT', {'default': 7.0, 'min': 0.0, 'max': 100.0, 'step': 0.1}), 'denoise': ('FLOAT', {'default': 0.9, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'latent_noise': ('FLOAT', {'default': 0.05, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'distribution_type': (['default', 'rand'],), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',)}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'sample' + CATEGORY = 'sampling' + + def sample(self, model, noise_seed, steps, cfg, denoise, sampler_name, scheduler, positive, negative, latent_image, latent_noise, distribution_type): + rand = False + if distribution_type == 'rand': + rand = True + return common_ksampler(model, noise_seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise, latent_noise, use_rand=rand) +``` \ No newline at end of file diff --git a/docs/JDC_PowerImage.md b/docs/JDC_PowerImage.md new file mode 100644 index 0000000..7ca7f0d --- /dev/null +++ b/docs/JDC_PowerImage.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: PowerImage +- Category: image/postprocessing +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +该节点通过根据指定的幂因子和模式调整图像的亮度和对比度来增强图像,允许操纵视觉元素以满足特定的美学或分析需求。 + +# Input types +## Required +- IMAGE + - 将由节点处理的源图像,作为所有增强操作的基本输入。 + - Comfy dtype: PIL.Image + - Python dtype: PIL.Image +- power_of + - 该参数控制应用于图像的增强程度,较高的值会导致更显著的效果。 + - Comfy dtype: FLOAT + - Python dtype: float +- mode + - 确定要应用的增强类型,例如提亮、变暗或同时强调图像的两个方面。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- IMAGE + - 经过处理的图像,已应用增强,准备进一步使用或分析。 + - Comfy dtype: PIL.Image + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PowerImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'IMAGE': ('IMAGE',), 'power_of': ('FLOAT', {'default': 1, 'min': 1, 'max': 65536, 'step': 0.01}), 'mode': (['darken', 'lighten', 'emphasize both'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'process_image' + CATEGORY = 'image/postprocessing' + + def process_image(self, IMAGE, power_of, mode): + cimg = conv_tensor_pil(IMAGE) + (w, h) = cimg.size + pbar = comfy.utils.ProgressBar(h) + step = 0 + for y in range(h): + for x in range(w): + (r, g, b) = cimg.getpixel((x, y)) + if mode == 'lighten': + r *= 1 + pow(r / 255, power_of) + g *= 1 + pow(g / 255, power_of) + b *= 1 + pow(b / 255, power_of) + elif mode == 'emphasize both': + r *= 0.5 + pow(r / 255, power_of) + g *= 0.5 + pow(g / 255, power_of) + b *= 0.5 + pow(b / 255, power_of) + else: + r *= pow(r / 255, power_of) + g *= pow(g / 255, power_of) + b *= pow(b / 255, power_of) + r = clamp(r, 0, 255) + g = clamp(g, 0, 255) + b = clamp(b, 0, 255) + cimg.putpixel((x, y), (int(r), int(g), int(b))) + step += 1 + pbar.update_absolute(step, h) + return conv_pil_tensor(cimg) +``` \ No newline at end of file diff --git a/docs/JDC_RandNoise.md b/docs/JDC_RandNoise.md new file mode 100644 index 0000000..d38563f --- /dev/null +++ b/docs/JDC_RandNoise.md @@ -0,0 +1,142 @@ +# Documentation +- Class name: RandNoise +- Category: image/noise +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +RandNoise节点旨在生成随机噪声图像。它通过创建指定尺寸的图像,并为每个像素应用用户定义范围内的随机颜色来操作。该节点的功能集中在生成噪声模式,这些模式可用于各种图像处理任务,如数据增强或噪声过滤。 + +# Input types +## Required +- width + - 宽度参数指定了生成的噪声图像的宽度。它至关重要,因为它决定了输出图像的水平分辨率,影响图像的整体尺寸和噪声模式的细节水平。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置了噪声图像的垂直尺寸。它对于建立垂直分辨率很重要,并且与宽度一起定义了噪声模式的整体大小。 + - Comfy dtype: INT + - Python dtype: int +- value_min + - value_min参数允许设置噪声强度的最小值。它影响分配给每个像素的随机颜色值的下限,从而影响噪声图像的整体亮度。 + - Comfy dtype: INT + - Python dtype: int +- value_max + - value_max参数设置了噪声强度的上限。它与value_min一起工作,定义可以分配给每个像素的随机值范围,形成噪声的动态范围。 + - Comfy dtype: INT + - Python dtype: int +- red_min + - red_min参数指定了噪声图像中红色通道的最小值。它对于控制噪声中红色的颜色强度很重要,并且有助于图像的最终颜色组成。 + - Comfy dtype: INT + - Python dtype: int +- red_max + - red_max参数设置了红色通道的最大值。它与red_min一起,决定了噪声中红色颜色值的范围,影响噪声图案的整体色调。 + - Comfy dtype: INT + - Python dtype: int +- green_min + - green_min参数建立了绿色通道的最小值。它在确定噪声中绿色颜色的强度方面发挥作用,影响图像的颜色平衡。 + - Comfy dtype: INT + - Python dtype: int +- green_max + - green_max参数定义了绿色通道的最大值。它与green_min一起设置绿色通道颜色值的范围,这影响了噪声图像中绿色的活力。 + - Comfy dtype: INT + - Python dtype: int +- blue_min + - blue_min参数设置了噪声图像中蓝色通道的最小值。它对于控制蓝色颜色的强度至关重要,并有助于生成的噪声的最终颜色方案。 + - Comfy dtype: INT + - Python dtype: int +- blue_max + - blue_max参数指定了蓝色通道的最大值。它与blue_min一起,决定了噪声中蓝色颜色值的范围,影响图像的整体颜色组成。 + - Comfy dtype: INT + - Python dtype: int +- seed + - seed参数用于初始化随机数生成器,确保噪声模式的可重复性。当需要在不同运行中生成相同的噪声图像时,它很重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - RandNoise节点的输出是一个包含随机噪声的图像。这个图像可以用于多种目的,比如为机器学习添加噪声数据、测试图像处理算法或创建视觉效果。 + - Comfy dtype: IMAGE + - Python dtype: Tuple[str, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RandNoise: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 128, 'max': 8192, 'step': 8}), 'height': ('INT', {'default': 512, 'min': 128, 'max': 8192, 'step': 8}), 'value_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'value_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'red_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'red_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'green_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'green_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'blue_min': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'blue_max': ('INT', {'default': -1, 'min': -1, 'max': 255, 'step': 1}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'generate_noise' + CATEGORY = 'image/noise' + + def generate_noise(self, width, height, value_min, value_max, red_min, red_max, green_min, green_max, blue_min, blue_max, seed): + w = width + h = height + aw = copy.deepcopy(w) + ah = copy.deepcopy(h) + outimage = Image.new('RGB', (aw, ah)) + random.seed(seed) + clamp_v_min = value_min + clamp_v_max = value_max + clamp_r_min = red_min + clamp_r_max = red_max + clamp_g_min = green_min + clamp_g_max = green_max + clamp_b_min = blue_min + clamp_b_max = blue_max + lv = 0 + mv = 0 + if clamp_v_min == -1: + lv = 0 + else: + lv = clamp_v_min + if clamp_v_max == -1: + mv = 255 + else: + mv = clamp_v_max + lr = 0 + mr = 0 + if clamp_r_min == -1: + lr = lv + else: + lr = clamp_r_min + if clamp_r_max == -1: + mr = mv + else: + mr = clamp_r_max + lg = 0 + mg = 0 + if clamp_g_min == -1: + lg = lv + else: + lg = clamp_g_min + if clamp_g_max == -1: + mg = mv + else: + mg = clamp_g_max + lb = 0 + mb = 0 + if clamp_b_min == -1: + lb = lv + else: + lb = clamp_b_min + if clamp_b_max == -1: + mb = mv + else: + mb = clamp_b_max + pbar = comfy.utils.ProgressBar(ah) + step = 0 + for y in range(ah): + for x in range(aw): + nr = random.randint(lr, mr) + ng = random.randint(lg, mg) + nb = random.randint(lb, mb) + outimage.putpixel((x, y), (nr, ng, nb)) + step += 1 + pbar.update_absolute(step, ah) + return conv_pil_tensor(outimage) +``` \ No newline at end of file diff --git a/docs/JDC_ResizeFactor.md b/docs/JDC_ResizeFactor.md new file mode 100644 index 0000000..e014613 --- /dev/null +++ b/docs/JDC_ResizeFactor.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: ResizeFactor +- Category: image/postprocessing +- Output node: False +- Repo Ref: https://github.com/Jordach/comfy-plasma.git + +ResizeFactor节点旨在调整图像的尺寸,通过指定的因子进行放大或缩小。这一过程对于使图像适应不同的显示要求或后续图像处理任务的输入规格至关重要。 + +# Input types +## Required +- IMAGE + - IMAGE参数是必需的,因为它提供了将被节点调整大小的源图像。它直接影响输出,并决定了图像的初始分辨率和格式。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- factor + - factor参数对于定义图像的缩放比例至关重要。它决定了图像将被放大或缩小多少,从而改变最终的尺寸。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- resampler + - resampler参数对于在调整大小过程中选择使用的插值方法很重要。它影响调整大小后的图像质量和外观。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- IMAGE + - 输出的IMAGE是调整大小过程的结果,反映了新的尺寸和基于所选重采样方法的潜在质量变化。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ResizeFactor: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'IMAGE': ('IMAGE',), 'factor': ('FLOAT', {'default': 2, 'min': 0.01, 'max': 10, 'step': 0.01}), 'resampler': (['nearest', 'box', 'bilinear', 'bicubic', 'hamming', 'lanczos'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'process_image' + CATEGORY = 'image/postprocessing' + + def process_image(self, IMAGE, factor, resampler): + cimg = conv_tensor_pil(IMAGE) + (w, h) = (int(cimg.width * factor), int(cimg.height * factor)) + sampler = get_pil_resampler(resampler) + return conv_pil_tensor(cimg.resize((w, h), resample=sampler)) +``` \ No newline at end of file diff --git a/docs/JagsClipseg.md b/docs/JagsClipseg.md new file mode 100644 index 0000000..ce022b2 --- /dev/null +++ b/docs/JagsClipseg.md @@ -0,0 +1,125 @@ +# Documentation +- Class name: JagsCLIPSeg +- Category: Jags_vector/CLIPSEG +- Output node: False +- Repo Ref: https://github.com/jags111/ComfyUI_Jags_VectorMagic + +JagsCLIPSeg是一个旨在使用文本提示和图像输入执行图像分割的节点。它利用CLIPSeg模型的力量,根据提供的文本描述生成与之对应的详细掩码,增强了分割过程,并利用语言的上下文。 + +# Input types +## Required +- image + - 图像参数对于分割过程至关重要,因为它提供了节点将根据提供的文本提示进行分析和分割的视觉上下文。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- text + - 文本参数作为分割过程的指导提示,描述了节点应在图像中关注的内容或特征。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- blur + - 模糊参数影响分割掩模的平滑度,较高的值导致更泛化的掩模,较低的值则保留更多细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- threshold + - 阈值参数决定了分割掩模二值化的截止点,高于阈值的值被保留,低于阈值的被丢弃,影响最终掩模的外观。 + - Comfy dtype: FLOAT + - Python dtype: float +- dilation_factor + - 膨胀因子参数控制分割掩模的扩展,较高的值导致更积极的膨胀,较低的值则导致更保守的扩展。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- Mask + - 掩模输出是分割的二值表示,其中文本提示描述的元素被突出显示,提供了分割特征的清晰视觉分离。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- Heatmap Mask + - 热图掩模输出提供了一个视觉渐变,代表了分割的置信度水平,较高的值指示关于分割的确定性更大的区域。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- BW Mask + - 黑白掩模输出是掩模的黑白版本,为分割结果提供了直接的视觉表示,适合进一步分析或处理。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class JagsCLIPSeg: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + """ + Return a dictionary which contains config for all input fields. + Some types (string): "MODEL", "VAE", "CLIP", "CONDITIONING", "LATENT", "IMAGE", "INT", "STRING", "FLOAT". + Input types "INT", "STRING" or "FLOAT" are special values for fields on the node. + The type can be a list for selection. + + Returns: `dict`: + - Key input_fields_group (`string`): Can be either required, hidden or optional. A node class must have property `required` + - Value input_fields (`dict`): Contains input fields config: + * Key field_name (`string`): Name of a entry-point method's argument + * Value field_config (`tuple`): + + First value is a string indicate the type of field or a list for selection. + + Secound value is a config for type "INT", "STRING" or "FLOAT". + """ + return {'required': {'image': ('IMAGE',), 'text': ('STRING', {'multiline': False})}, 'optional': {'blur': ('FLOAT', {'min': 0, 'max': 15, 'step': 0.1, 'default': 7}), 'threshold': ('FLOAT', {'min': 0, 'max': 1, 'step': 0.05, 'default': 0.4}), 'dilation_factor': ('INT', {'min': 0, 'max': 10, 'step': 1, 'default': 4})}} + CATEGORY = 'Jags_vector/CLIPSEG' + RETURN_TYPES = ('MASK', 'IMAGE', 'IMAGE') + RETURN_NAMES = ('Mask', 'Heatmap Mask', 'BW Mask') + FUNCTION = 'segment_image' + + def segment_image(self, image: torch.Tensor, text: str, blur: float, threshold: float, dilation_factor: int) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: + """Create a segmentation mask from an image and a text prompt using CLIPSeg. + + Args: + image (torch.Tensor): The image to segment. + text (str): The text prompt to use for segmentation. + blur (float): How much to blur the segmentation mask. + threshold (float): The threshold to use for binarizing the segmentation mask. + dilation_factor (int): How much to dilate the segmentation mask. + + Returns: + Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: The segmentation mask, the heatmap mask, and the binarized mask. + """ + image_np = image.numpy().squeeze() + image_np = (image_np * 255).astype(np.uint8) + i = Image.fromarray(image_np, mode='RGB') + processor = CLIPSegProcessor.from_pretrained(clipseg_model_dir) + model = CLIPSegForImageSegmentation.from_pretrained(clipseg_model_dir) + prompt = text + input_prc = processor(text=prompt, images=i, padding='max_length', return_tensors='pt') + with torch.no_grad(): + outputs = model(**input_prc) + tensor = torch.sigmoid(outputs[0]) + thresh = threshold + tensor_thresholded = torch.where(tensor > thresh, tensor, torch.tensor(0, dtype=torch.float)) + sigma = blur + tensor_smoothed = gaussian_filter(tensor_thresholded.numpy(), sigma=sigma) + tensor_smoothed = torch.from_numpy(tensor_smoothed) + mask_normalized = (tensor_smoothed - tensor_smoothed.min()) / (tensor_smoothed.max() - tensor_smoothed.min()) + mask_dilated = dilate_mask(mask_normalized, dilation_factor) + heatmap = apply_colormap(mask_dilated, cm.viridis) + binary_mask = apply_colormap(mask_dilated, cm.Greys_r) + dimensions = (image_np.shape[1], image_np.shape[0]) + heatmap_resized = resize_image(heatmap, dimensions) + binary_mask_resized = resize_image(binary_mask, dimensions) + (alpha_heatmap, alpha_binary) = (0.5, 1) + overlay_heatmap = overlay_image(image_np, heatmap_resized, alpha_heatmap) + overlay_binary = overlay_image(image_np, binary_mask_resized, alpha_binary) + image_out_heatmap = numpy_to_tensor(overlay_heatmap) + image_out_binary = numpy_to_tensor(overlay_binary) + binary_mask_image = Image.fromarray(binary_mask_resized[..., 0]) + tensor_bw = binary_mask_image.convert('RGB') + tensor_bw = np.array(tensor_bw).astype(np.float32) / 255.0 + tensor_bw = torch.from_numpy(tensor_bw)[None,] + tensor_bw = tensor_bw.squeeze(0)[..., 0] + return (tensor_bw, image_out_heatmap, image_out_binary) +``` \ No newline at end of file diff --git a/docs/JagsCombineMasks.md b/docs/JagsCombineMasks.md new file mode 100644 index 0000000..998dc28 --- /dev/null +++ b/docs/JagsCombineMasks.md @@ -0,0 +1,85 @@ +# Documentation +- Class name: JagsCombineMasks +- Category: Jags_vector/CLIPSEG +- Output node: False +- Repo Ref: https://github.com/jags111/ComfyUI_Jags_VectorMagic + +该节点将多个掩码张量协同整合为统一的表示形式,便于在给定的图像上下文中集成分割区域。它旨在简化将二进制或分类数据合并为一致视觉输出的过程,提高基于掩码的图像处理任务的实用性。 + +# Input types +## Required +- input_image + - 输入图像作为合并和可视化掩码的基础层,其作用至关重要,因为它提供了准确叠加和整合掩码所需的空间上下文。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask_1 + - 主掩码在融合过程中是一个关键组件,定义了初始分割,为后续叠加其他掩码奠定了基础。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- mask_2 + - 次级掩码通过引入额外的分割层来完善合并掩码,提高了最终输出的粒度和特异性。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- mask_3 + - 可选的第三级掩码为掩码组合提供了额外的维度,当需要时允许更复杂和细致的分割。 + - Comfy dtype: MASK + - Python dtype: Optional[torch.Tensor] + +# Output types +- Combined Mask + - 生成的合并掩码包含了输入掩码的集体分割信息,作为图像中分割元素的综合表示。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- Heatmap Mask + - 热图掩码通过颜色叠加可视化合并分割,提供了直观且易于解释的分割结果描述。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- BW Mask + - 二值掩码提供了一个清晰、高对比度的分割表示,以清晰和精确的方式突出显示划分的区域。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class JagsCombineMasks: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input_image': ('IMAGE',), 'mask_1': ('MASK',), 'mask_2': ('MASK',)}, 'optional': {'mask_3': ('MASK',)}} + CATEGORY = 'Jags_vector/CLIPSEG' + RETURN_TYPES = ('MASK', 'IMAGE', 'IMAGE') + RETURN_NAMES = ('Combined Mask', 'Heatmap Mask', 'BW Mask') + FUNCTION = 'combine_masks' + + def combine_masks(self, input_image: torch.Tensor, mask_1: torch.Tensor, mask_2: torch.Tensor, mask_3: Optional[torch.Tensor]=None) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: + """A method that combines two or three masks into one mask. Takes in tensors and returns the mask as a tensor, as well as the heatmap and binary mask as tensors.""" + if mask_1 is not None: + mask_1 = mask_1.squeeze() + if mask_2 is not None: + mask_2 = mask_2.squeeze() + if mask_3 is not None: + mask_3 = mask_3.squeeze() + combined_mask = mask_1 + mask_2 + mask_3 if mask_3 is not None else mask_1 + mask_2 + image_np = tensor_to_numpy(input_image) + heatmap = apply_colormap(combined_mask, cm.viridis) + binary_mask = apply_colormap(combined_mask, cm.Greys_r) + dimensions = (image_np.shape[1], image_np.shape[0]) + print('heatmap', heatmap) + if dimensions is None or dimensions[0] == 0 or dimensions[1] == 0: + raise ValueError('Invalid dimensions') + heatmap_resized = resize_image(heatmap, dimensions) + binary_mask_resized = resize_image(binary_mask, dimensions) + (alpha_heatmap, alpha_binary) = (0.5, 1) + overlay_heatmap = overlay_image(image_np, heatmap_resized, alpha_heatmap) + overlay_binary = overlay_image(image_np, binary_mask_resized, alpha_binary) + image_out_heatmap = numpy_to_tensor(overlay_heatmap) + image_out_binary = numpy_to_tensor(overlay_binary) + return (combined_mask, image_out_heatmap, image_out_binary) +``` \ No newline at end of file diff --git a/docs/JoinStrings.md b/docs/JoinStrings.md new file mode 100644 index 0000000..2b56d4c --- /dev/null +++ b/docs/JoinStrings.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: JoinStrings +- Category: KJNodes/constants +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +JoinStrings节点旨在将两个输入字符串合并为一个单独的字符串。它通过在两个字符串之间插入一个指定的分隔符来实现这一点,有效地将它们合并成一个连贯的字符序列。在需要将多个字符串合并为一个的字符串操作任务中,如数据格式化或进一步处理的准备中,该节点发挥着关键作用。 + +# Input types +## Required +- string1 + - 第一个要连接的字符串。它作为最终连接字符串的初始部分,对确定连接过程的结果至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- string2 + - 第二个要连接的字符串。它在最终连接字符串中跟在第一个字符串和分隔符之后,对输出的整体结构有所贡献。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- delimiter + - 将要插入两个输入字符串之间的字符或字符序列。分隔符在定义最终字符串的阅读方式中起着重要作用,可以根据手头任务的具体要求进行调整。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- joined_string + - JoinStrings节点的输出是连接后的字符串,这是将两个输入字符串与指定的分隔符连接的结果。这个输出很重要,因为它代表了节点操作的最终产品,并准备好用于后续的任务或流程。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class JoinStrings: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'string1': ('STRING', {'default': '', 'forceInput': True}), 'string2': ('STRING', {'default': '', 'forceInput': True}), 'delimiter': ('STRING', {'default': ' ', 'multiline': False})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'joinstring' + CATEGORY = 'KJNodes/constants' + + def joinstring(self, string1, string2, delimiter): + joined_string = string1 + delimiter + string2 + return (joined_string,) +``` \ No newline at end of file diff --git a/docs/JoinWithDelimiter.md b/docs/JoinWithDelimiter.md new file mode 100644 index 0000000..2d8b562 --- /dev/null +++ b/docs/JoinWithDelimiter.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: JoinWithDelimiter +- Category: ♾️Mixlab/Prompt +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点将文本字符串列表连接成单个字符串,并使用指定的分隔符来分隔各个项目。它旨在简化文本组合过程,为从多个输入创建统一的文本输出提供直接的解决方案。 + +# Input types +## Required +- text_list + - 要连接的文本字符串列表。此参数至关重要,因为它构成了节点操作的基础,决定了将要合并的文本的内容和数量。 + - Comfy dtype: ANY + - Python dtype: List[str] +- delimiter + - 用于分隔text_list中元素的字符或字符串。分隔符的选择影响结果字符串的可读性和结构。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- result + - 最终连接的字符串,其中所有的text_list元素都使用指定的分隔符连接在一起。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class JoinWithDelimiter: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text_list': (any_type,), 'delimiter': (['newline', 'comma', 'backslash', 'space'],)}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Prompt' + INPUT_IS_LIST = True + OUTPUT_IS_LIST = (False,) + + def run(self, text_list, delimiter): + delimiter = delimiter[0] + if delimiter == 'newline': + delimiter = '\n' + elif delimiter == 'comma': + delimiter = ',' + elif delimiter == 'backslash': + delimiter = '\\' + elif delimiter == 'space': + delimiter = ' ' + t = '' + if isinstance(text_list, list): + t = join_with_(text_list, delimiter) + return (t,) +``` \ No newline at end of file diff --git a/docs/KSampler %2F%2FInspire.md b/docs/KSampler %2F%2FInspire.md new file mode 100644 index 0000000..f93d7d6 --- /dev/null +++ b/docs/KSampler %2F%2FInspire.md @@ -0,0 +1,91 @@ +# Documentation +- Class name: KSampler_inspire +- Category: InspirePack/a1111_compat +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在从给定模型中促进采样过程,使用各种参数控制生成新的潜在样本。它强调采样过程的灵活性和适应性,允许在定义的配置内探索多样化的结果。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了数据的来源和采样过程的基础。没有模型,节点无法执行其预期功能。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- seed + - 种子在确保采样过程的可重复性和随机性方面起着重要作用。它是控制生成唯一样本的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步骤定义了采样过程的进展,决定了算法将执行的迭代次数。这直接影响输出样本的多样性和数量。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数对于微调采样过程的行为至关重要。它影响搜索空间中探索和利用的平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数决定了要采用的采样策略,这对形成结果样本的特征至关重要。 + - Comfy dtype: ENUM + - Python dtype: str +- scheduler + - 调度器参数负责控制采样过程的节奏和调整。它在优化采样的效率和效果方面起着关键作用。 + - Comfy dtype: ENUM + - Python dtype: str +- positive + - 正向调节提供了指导采样过程朝向期望结果的重要背景。这是实现目标结果的关键元素。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- negative + - 负向调节作为过滤条件,在采样过程中排除不需要的特征,确保输出符合指定的约束。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- latent_image + - 潜在图像参数对于采样过程是不可或缺的,因为它代表了生成新样本的起点。它为随后的转换设定了基础。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- noise_mode + - 噪声模式决定了用于噪声生成的计算资源,这对采样过程至关重要。它影响节点的性能和效率。 + - Comfy dtype: ENUM + - Python dtype: str +## Optional +- denoise + - 去噪参数在通过减少噪声来提高输出样本的质量方面非常重要。它有助于实现数据更清晰、更连贯的表现。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_seed_mode + - 批处理种子模式影响批次中种子的管理方式,这可能会影响生成样本的多样性和独特性。 + - Comfy dtype: ENUM + - Python dtype: str +- variation_seed + - 变异种子在噪声生成过程中引入变异性,有助于输出样本的多样性,同时不会改变核心特征。 + - Comfy dtype: INT + - Python dtype: int +- variation_strength + - 变异强度调节噪声引入的变异程度,影响结果样本中的微妙差异。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- samples + - 样本代表采样过程的输出,包含了新生成的潜在表示。它们是节点执行的直接结果,对进一步分析或应用具有重要价值。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class KSampler_inspire: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'noise_mode': (['GPU(=A1111)', 'CPU'],), 'batch_seed_mode': (['incremental', 'comfy', 'variation str inc:0.01', 'variation str inc:0.05'],), 'variation_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'variation_strength': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'sample' + CATEGORY = 'InspirePack/a1111_compat' + + def sample(self, model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise, noise_mode, batch_seed_mode='comfy', variation_seed=None, variation_strength=None): + return common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise, noise_mode, incremental_seed_mode=batch_seed_mode, variation_seed=variation_seed, variation_strength=variation_strength) +``` \ No newline at end of file diff --git a/docs/KSampler (WAS).md b/docs/KSampler (WAS).md new file mode 100644 index 0000000..61d7806 --- /dev/null +++ b/docs/KSampler (WAS).md @@ -0,0 +1,75 @@ +# Documentation +- Class name: WAS_KSampler +- Category: WAS Suite/Sampling +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_KSampler节点旨在WAS套件中执行采样操作,利用先进的采样技术生成潜在表示。它在创建新图像或增强现有图像中起着关键作用,对整个图像合成过程有着重要的贡献。 + +# Input types +## Required +- model + - 模型参数对于节点至关重要,因为它定义了用于采样的底层神经网络架构。它直接影响生成的潜在表示的质量和特性。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- seed + - 种子参数对于以确定性结果启动采样过程至关重要。它确保了结果的可复现性,这对于在不同运行中进行一致的图像生成非常关键。 + - Comfy dtype: SEED + - Python dtype: Union[int, str] +- sampler_name + - sampler_name参数指定要使用的采样方法,这对节点的操作至关重要。不同的采样器可以产生不同的结果,因此这个选择对于实现期望的结果至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- scheduler + - 调度器参数决定了采样过程的学习率计划,这对采样算法的效率和效果至关重要。它可能显著影响生成的潜在图像的质量。 + - Comfy dtype: STRING + - Python dtype: str +- positive + - 正向参数提供正向条件信息,引导采样过程生成具有所需特征的图像。这是引导输出朝向预期方向的重要因素。 + - Comfy dtype: CONDITIONING + - Python dtype: Union[str, List[str]] +- negative + - 负向参数提供负向条件信息,以防止采样图像中包含不需要的特征。它对于确保输出与指定的约束一致至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Union[str, List[str]] +- latent_image + - latent_image参数是采样过程的输入,代表要细化的图像的初始状态。它是一个基本组成部分,为图像的生成或增强设定了起点。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +## Optional +- steps + - 步数参数决定了采样过程中的迭代次数,影响最终潜在图像的收敛和细节。更多的步数通常会导致更精细的输出。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数,代表无分类器指导比例,调整采样中内容与随机性之间的平衡。它在控制生成图像与输入条件的保真度方面起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- denoise + - 去噪参数控制采样过程中应用的噪声减少级别。这是一个微调选项,可以提高最终图像的清晰度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- latent + - 潜在输出代表以编码形式采样的图像,可以进一步处理或用作后续图像生成任务的输入。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WAS_KSampler: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('MODEL',), 'seed': ('SEED',), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'sample' + CATEGORY = 'WAS Suite/Sampling' + + def sample(self, model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=1.0): + return nodes.common_ksampler(model, seed['seed'], steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise) +``` \ No newline at end of file diff --git a/docs/KSampler Cycle.md b/docs/KSampler Cycle.md new file mode 100644 index 0000000..fdc923a --- /dev/null +++ b/docs/KSampler Cycle.md @@ -0,0 +1,181 @@ +# Documentation +- Class name: WAS_KSampler_Cycle +- Category: WAS Suite/Sampling +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_KSampler_Cycle 节点旨在 WAS 套件中执行高级采样操作。它利用各种参数来控制采样过程,包括模型选择、种子初始化、步数计数和条件输入。该节点能够处理复杂的采样任务,如迭代去噪和潜在图像操作,以实现高质量的结果。它还支持可选功能,如次要模型切换和后处理增强,使其成为复杂采样需求的多功能工具。 + +# Input types +## Required +- model + - 模型参数对于采样过程至关重要,因为它定义了用于生成输出的底层神经网络模型。模型的选择可以显著影响生成样本的质量和特性。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- seed + - 种子参数对于初始化随机数生成器至关重要,确保了采样过程的可重复性。它允许在不同运行中使用相同的种子值生成一致的结果。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步数参数决定了采样过程中的迭代次数。步数越多,可以导致更精细的样本,但也可能增加计算时间。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- latent(s) + - 输出的潜在表示生成样本的编码形式。这些潜在表示可以进一步处理或用于各种下游任务,如图像重建或特征提取。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WAS_KSampler_Cycle: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'tiled_vae': (['disable', 'enable'],), 'latent_upscale': (['disable', 'nearest-exact', 'bilinear', 'area', 'bicubic', 'bislerp'],), 'upscale_factor': ('FLOAT', {'default': 2.0, 'min': 0.1, 'max': 8.0, 'step': 0.1}), 'upscale_cycles': ('INT', {'default': 2, 'min': 2, 'max': 12, 'step': 1}), 'starting_denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'cycle_denoise': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'scale_denoise': (['enable', 'disable'],), 'scale_sampling': (['bilinear', 'bicubic', 'nearest', 'lanczos'],), 'vae': ('VAE',)}, 'optional': {'secondary_model': ('MODEL',), 'secondary_start_cycle': ('INT', {'default': 2, 'min': 2, 'max': 16, 'step': 1}), 'upscale_model': ('UPSCALE_MODEL',), 'processor_model': ('UPSCALE_MODEL',), 'pos_additive': ('CONDITIONING',), 'neg_additive': ('CONDITIONING',), 'pos_add_mode': (['increment', 'decrement'],), 'pos_add_strength': ('FLOAT', {'default': 0.25, 'min': 0.01, 'max': 1.0, 'step': 0.01}), 'pos_add_strength_scaling': (['enable', 'disable'],), 'pos_add_strength_cutoff': ('FLOAT', {'default': 2.0, 'min': 0.01, 'max': 10.0, 'step': 0.01}), 'neg_add_mode': (['increment', 'decrement'],), 'neg_add_strength': ('FLOAT', {'default': 0.25, 'min': 0.01, 'max': 1.0, 'step': 0.01}), 'neg_add_strength_scaling': (['enable', 'disable'],), 'neg_add_strength_cutoff': ('FLOAT', {'default': 2.0, 'min': 0.01, 'max': 10.0, 'step': 0.01}), 'sharpen_strength': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'sharpen_radius': ('INT', {'default': 2, 'min': 1, 'max': 12, 'step': 1}), 'steps_scaling': (['enable', 'disable'],), 'steps_control': (['decrement', 'increment'],), 'steps_scaling_value': ('INT', {'default': 10, 'min': 1, 'max': 20, 'step': 1}), 'steps_cutoff': ('INT', {'default': 20, 'min': 4, 'max': 1000, 'step': 1}), 'denoise_cutoff': ('FLOAT', {'default': 0.25, 'min': 0.01, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('LATENT',) + RETURN_NAMES = ('latent(s)',) + FUNCTION = 'sample' + CATEGORY = 'WAS Suite/Sampling' + + def sample(self, model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, tiled_vae, latent_upscale, upscale_factor, upscale_cycles, starting_denoise, cycle_denoise, scale_denoise, scale_sampling, vae, secondary_model=None, secondary_start_cycle=None, pos_additive=None, pos_add_mode=None, pos_add_strength=None, pos_add_strength_scaling=None, pos_add_strength_cutoff=None, neg_additive=None, neg_add_mode=None, neg_add_strength=None, neg_add_strength_scaling=None, neg_add_strength_cutoff=None, upscale_model=None, processor_model=None, sharpen_strength=0, sharpen_radius=2, steps_scaling=None, steps_control=None, steps_scaling_value=None, steps_cutoff=None, denoise_cutoff=0.25): + upscale_steps = upscale_cycles + division_factor = upscale_steps if steps >= upscale_steps else steps + current_upscale_factor = upscale_factor ** (1 / (division_factor - 1)) + tiled_vae = tiled_vae == 'enable' + scale_denoise = scale_denoise == 'enable' + pos_add_strength_scaling = pos_add_strength_scaling == 'enable' + neg_add_strength_scaling = neg_add_strength_scaling == 'enable' + steps_scaling = steps_scaling == 'enable' + run_model = model + secondary_switched = False + for i in range(division_factor): + cstr(f'Cycle Pass {i + 1}/{division_factor}').msg.print() + if scale_denoise: + denoise = (round(cycle_denoise * 2 ** (-(i - 1)), 2) if i > 0 else cycle_denoise) if i > 0 else round(starting_denoise, 2) + else: + denoise = round(cycle_denoise if i > 0 else starting_denoise, 2) + if denoise < denoise_cutoff and scale_denoise: + denoise = denoise_cutoff + if i >= secondary_start_cycle - 1 and secondary_model and (not secondary_switched): + run_model = secondary_model + denoise = cycle_denoise + model = None + secondary_switched = True + if steps_scaling and i > 0: + steps = steps + steps_scaling_value if steps_control == 'increment' else steps - steps_scaling_value + steps = (steps if steps <= steps_cutoff else steps_cutoff) if steps_control == 'increment' else steps if steps >= steps_cutoff else steps_cutoff + print('Steps:', steps) + print('Denoise:', denoise) + if pos_additive: + pos_strength = 0.0 if i <= 0 else pos_add_strength + if pos_add_mode == 'increment': + pos_strength = (round(pos_add_strength * 2 ** (i - 1), 2) if i > 0 else pos_add_strength) if pos_add_strength_scaling else pos_add_strength + pos_strength = pos_add_strength_cutoff if pos_strength > pos_add_strength_cutoff else pos_strength + else: + pos_strength = (round(pos_add_strength / 2 ** (i - 1), 2) if i > 0 else pos_add_strength) if pos_add_strength_scaling else pos_add_strength + pos_strength = pos_add_strength_cutoff if pos_strength < pos_add_strength_cutoff else pos_strength + comb = nodes.ConditioningAverage() + positive = comb.addWeighted(pos_additive, positive, pos_strength)[0] + print('Positive Additive Strength:', pos_strength) + if neg_additive: + neg_strength = 0.0 if i <= 0 else pos_add_strength + if neg_add_mode == 'increment': + neg_strength = (round(neg_add_strength * 2 ** (i - 1), 2) if i > 0 else neg_add_strength) if neg_add_strength_scaling else neg_add_strength + neg_strength = neg_add_strength_cutoff if neg_strength > neg_add_strength_cutoff else neg_strength + else: + neg_strength = (round(neg_add_strength / 2 ** (i - 1), 2) if i > 0 else neg_add_strength) if neg_add_strength_scaling else neg_add_strength + neg_strength = neg_add_strength_cutoff if neg_strength < neg_add_strength_cutoff else neg_strength + comb = nodes.ConditioningAverage() + negative = comb.addWeighted(neg_additive, negative, neg_strength)[0] + print('Negative Additive Strength:', neg_strength) + if i != 0: + latent_image = latent_image_result + samples = nodes.common_ksampler(run_model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise) + if i < division_factor - 1: + tensors = None + upscaler = None + resample_filters = {'nearest': 0, 'bilinear': 2, 'bicubic': 3, 'lanczos': 1} + if latent_upscale == 'disable': + if tiled_vae: + tensors = vae.decode_tiled(samples[0]['samples']) + else: + tensors = vae.decode(samples[0]['samples']) + if processor_model or upscale_model: + from comfy_extras import nodes_upscale_model + upscaler = nodes_upscale_model.ImageUpscaleWithModel() + if processor_model: + original_size = tensor2pil(tensors[0]).size + upscaled_tensors = upscaler.upscale(processor_model, tensors) + tensor_images = [] + for tensor in upscaled_tensors[0]: + pil = tensor2pil(tensor) + if pil.size[0] != original_size[0] or pil.size[1] != original_size[1]: + pil = pil.resize((original_size[0], original_size[1]), Image.Resampling(resample_filters[scale_sampling])) + if sharpen_strength != 0.0: + pil = self.unsharp_filter(pil, sharpen_radius, sharpen_strength) + tensor_images.append(pil2tensor(pil)) + tensor_images = torch.cat(tensor_images, dim=0) + if upscale_model: + if processor_model: + tensors = tensor_images + del tensor_images + original_size = tensor2pil(tensors[0]).size + new_width = round(original_size[0] * current_upscale_factor) + new_height = round(original_size[1] * current_upscale_factor) + new_width = int(round(new_width / 32) * 32) + new_height = int(round(new_height / 32) * 32) + upscaled_tensors = upscaler.upscale(upscale_model, tensors) + tensor_images = [] + for tensor in upscaled_tensors[0]: + tensor = pil2tensor(tensor2pil(tensor).resize((new_width, new_height), Image.Resampling(resample_filters[scale_sampling]))) + size = max(tensor2pil(tensor).size) + if sharpen_strength != 0.0: + tensor = pil2tensor(self.unsharp_filter(tensor2pil(tensor), sharpen_radius, sharpen_strength)) + tensor_images.append(tensor) + tensor_images = torch.cat(tensor_images, dim=0) + else: + tensor_images = [] + scale = WAS_Image_Rescale() + for tensor in tensors: + tensor = scale.image_rescale(tensor.unsqueeze(0), 'rescale', 'true', scale_sampling, current_upscale_factor, 0, 0)[0] + size = max(tensor2pil(tensor).size) + if sharpen_strength > 0.0: + tensor = pil2tensor(self.unsharp_filter(tensor2pil(tensor), sharpen_radius, sharpen_strength)) + tensor_images.append(tensor) + tensor_images = torch.cat(tensor_images, dim=0) + if tiled_vae: + latent_image_result = {'samples': vae.encode_tiled(self.vae_encode_crop_pixels(tensor_images)[:, :, :, :3])} + else: + latent_image_result = {'samples': vae.encode(self.vae_encode_crop_pixels(tensor_images)[:, :, :, :3])} + else: + upscaler = nodes.LatentUpscaleBy() + latent_image_result = upscaler.upscale(samples[0], latent_upscale, current_upscale_factor)[0] + else: + latent_image_result = samples[0] + return (latent_image_result,) + + @staticmethod + def vae_encode_crop_pixels(pixels): + x = pixels.shape[1] // 8 * 8 + y = pixels.shape[2] // 8 * 8 + 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, :] + return pixels + + @staticmethod + def unsharp_filter(image, radius=2, amount=1.0): + from skimage.filters import unsharp_mask + img_array = np.array(image) + img_array = img_array / 255.0 + sharpened = unsharp_mask(img_array, radius=radius, amount=amount, channel_axis=2) + sharpened = (sharpened * 255.0).astype(np.uint8) + sharpened_pil = Image.fromarray(sharpened) + return sharpened_pil +``` \ No newline at end of file diff --git a/docs/KSampler Gradually Adding More Denoise (efficient).md b/docs/KSampler Gradually Adding More Denoise (efficient).md new file mode 100644 index 0000000..1b6faed --- /dev/null +++ b/docs/KSampler Gradually Adding More Denoise (efficient).md @@ -0,0 +1,114 @@ +# Documentation +- Class name: Gradually_More_Denoise_KSampler +- Category: ComfyUI-Frame-Interpolation/others +- Output node: True +- Repo Ref: https://github.com/Fannovel16/ComfyUI-Frame-Interpolation + +Gradually_More_Denoise_KSampler 节点旨在逐步精细化潜在图像的去噪过程。它通过应用一系列去噪步骤,逐增加去噪强度,以实现更清晰的输出。此节点在需要逐步增强图像质量的场景中至关重要,例如在生成动画的平滑过渡或以逐步方式提高图像清晰度时。 + +# Input types +## Required +- model + - 模型参数对于节点的操作至关重要,因为它定义了用于生成潜在样本的生成模型。它直接影响生成图像的质量和类型,是整个过程中的关键组成部分。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- positive + - 正向条件参数用于引导生成过程朝着期望的结果发展。它在引导模型输出朝向更有利或特定的结果中扮演着重要角色。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- negative + - 负向条件参数用于抑制生成过程中的某些结果。它对于微调模型的输出以避免不希望的特征或特性很重要。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- latent_image + - 潜在图像参数是包含用于生成去噪输出的初始潜在表示的关键输入。它是节点功能的基础,因为最终图像的质量在很大程度上依赖于初始潜在状态。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +## Optional +- seed + - 种子参数用于初始化随机数生成器,确保采样过程中的可重复性。虽然它是可选的,但当重新运行节点时,它对于获得一致的结果很重要。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步数参数决定了采样过程中的迭代次数。它影响节点的执行时间,并且可能影响生成样本向期望结果的收敛。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg 参数,代表无分类器指导比例,是控制模型潜在空间探索与遵循所提供条件之间平衡的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name 参数指定节点要使用的采样方法。它很重要,因为它可以改变生成样本的特性,可能导致不同的视觉结果。 + - Comfy dtype: STRING + - Python dtype: str +- scheduler + - scheduler 参数定义了在采样过程中要应用的学习率调度器。它在优化生成样本中发挥作用,可能影响它们的质量。 + - Comfy dtype: STRING + - Python dtype: str +- start_denoise + - start_denoise 参数设置初始去噪强度,对于生成图像的初始清晰度至关重要。它是节点能够产生高质量去噪输出的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- denoise_increment + - denoise_increment 参数指示每个后续步骤中去噪强度的增加量。它对于控制图像清晰度提高的速度很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- denoise_increment_steps + - denoise_increment_steps 参数指定去噪强度将增加的步数。它对于确定去噪过程的总持续时间很重要。 + - Comfy dtype: INT + - Python dtype: int +- optional_vae + - optional_vae 参数允许提供可选的变分自编码器,它可以用于对潜在表示进行额外的处理或操作。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module + +# Output types +- model + - 模型输出参数代表了采样过程中使用的生成模型。它很重要,因为它是生成潜在样本的基础。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- positive + - 正向条件输出参数提供了引导生成过程朝向有利结果的条件信息。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- negative + - 负向条件输出参数代表了在生成过程中用来抑制某些结果的条件信息。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- latent + - 潜在输出参数包含通过采样过程精炼的图像的潜在表示。这些经过精炼的潜在状态对于生成高质量图像至关重要。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- vae + - 如果作为输入提供,vae 输出参数代表了用于潜在表示的额外处理的变分自编码器。它标志着采用先进技术以获得改进的结果。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class Gradually_More_Denoise_KSampler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), '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,), 'start_denoise': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'denoise_increment': ('FLOAT', {'default': 0.1, 'min': 0.0, 'max': 1.0, 'step': 0.1}), 'denoise_increment_steps': ('INT', {'default': 20, 'min': 1, 'max': 10000})}, 'optional': {'optional_vae': ('VAE',)}} + RETURN_TYPES = ('MODEL', 'CONDITIONING', 'CONDITIONING', 'LATENT', 'VAE') + RETURN_NAMES = ('MODEL', 'CONDITIONING+', 'CONDITIONING-', 'LATENT', 'VAE') + OUTPUT_NODE = True + FUNCTION = 'sample' + CATEGORY = 'ComfyUI-Frame-Interpolation/others' + + def sample(self, model, positive, negative, latent_image, optional_vae, seed, steps, cfg, sampler_name, scheduler, start_denoise, denoise_increment, denoise_increment_steps): + if start_denoise + denoise_increment * denoise_increment_steps > 1.0: + raise Exception(f"Max denoise strength can't over 1.0 (start_denoise={start_denoise}, denoise_increment={denoise_increment}, denoise_increment_steps={denoise_increment_steps}") + copied_latent = latent_image.copy() + out_samples = [] + for latent_sample in copied_latent['samples']: + latent = {'samples': einops.rearrange(latent_sample, 'c h w -> 1 c h w')} + gradually_denoising_samples = [common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent, denoise=start_denoise + denoise_increment * i)[0]['samples'] for i in range(denoise_increment_steps)] + out_samples.extend(gradually_denoising_samples) + copied_latent['samples'] = torch.cat(out_samples, dim=0) + return (model, positive, negative, copied_latent, optional_vae) +``` \ No newline at end of file diff --git a/docs/KSampler.md b/docs/KSampler.md index 0f24be6..77b1226 100644 --- a/docs/KSampler.md +++ b/docs/KSampler.md @@ -12,27 +12,11 @@ KSampler节点旨在对给定模型执行采样操作。它利用各种参数控 - 模型参数对于KSampler节点至关重要,因为它定义了将用于采样的底层模型。模型的选择显著影响节点的执行和生成的潜在表示的质量。 - Comfy dtype: MODEL - Python dtype: torch.nn.Module - - positive - - positive参数提供指导采样过程的条件信息,以生成更相关和准确的潜在表示。当目标是采样中的特定结果时,这是一个重要方面。 - - Comfy dtype: CONDITIONING - - Python dtype: Dict[str, torch.Tensor] -- negative - - negative参数与positive参数类似,提供条件信息,但在这种情况下,它用于指导采样过程远离某些结果。它有助于完善采样过程,以避免不希望的结果。 - - Comfy dtype: CONDITIONING - - Python dtype: Dict[str, torch.Tensor] -- latent_image - - latent_image参数表示采样过程的初始潜在状态,用作采样过程的起点。它是一个关键输入,直接影响节点的最终输出,决定采样的方向。 - - Comfy dtype: LATENT - - Python dtype: Dict[str, torch.Tensor] -## Optional - seed - - 此参数表示此次采样的种子数值,每张图片都有一个独一的数值,也叫随机种。 -- control_after_generate - - 此参数可以更改随机种数值的变化形式, - - fixed(固定随机种,在下次采样时,种子数值不会改变,适用于固定图片样式的情况下调整其他参数来细微改变图片) - - increment(增加随机种子数值,每次采样随机数值+1) - - decrement(减少随机种子数值,每次采样随机数值-1) - - randomize(每次采样随机种子数值会无规律的随机变化) + - 种子参数对于确保采样过程的可重复性至关重要。它初始化随机数生成器,这影响采样中使用的噪声模式,从而影响结果的一致性和可靠性。 + - Comfy dtype: INT + - Python dtype: int +## Optional - steps - 步骤参数确定采样过程中的迭代次数。它直接影响生成的潜在表示的收敛和细节水平,更多的步骤通常会导致更高质量的输出。 - Comfy dtype: INT @@ -49,6 +33,18 @@ KSampler节点旨在对给定模型执行采样操作。它利用各种参数控 - scheduler参数定义了在采样过程中要使用的学习能力调度器。它是一个关键组件,用于随时间调整学习能力,这可以极大地影响采样的效率和效果。 - Comfy dtype: comfy.samplers.KSampler.SCHEDULERS - Python dtype: str +- positive + - positive参数提供指导采样过程的条件信息,以生成更相关和准确的潜在表示。当目标是采样中的特定结果时,这是一个重要方面。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- negative + - negative参数与positive参数类似,提供条件信息,但在这种情况下,它用于指导采样过程远离某些结果。它有助于完善采样过程,以避免不希望的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- latent_image + - latent_image参数表示采样过程的初始潜在状态,用作采样过程的起点。它是一个关键输入,直接影响节点的最终输出,决定采样的方向。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] - denoise - denoise参数控制采样过程中应用的去噪水平。这是一个重要的调整参数,可以提高生成的潜在表示的清晰度和质量。 - Comfy dtype: FLOAT diff --git a/docs/KSamplerAdvanced %2F%2FInspire.md b/docs/KSamplerAdvanced %2F%2FInspire.md new file mode 100644 index 0000000..1d59828 --- /dev/null +++ b/docs/KSamplerAdvanced %2F%2FInspire.md @@ -0,0 +1,113 @@ +# Documentation +- Class name: KSamplerAdvanced_inspire +- Category: InspirePack/a1111_compat +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +KSamplerAdvanced_inspire 类旨在模型内促进高级采样操作,集成噪声和调度机制以增强生成过程。它旨在为用户提供一个灵活高效的工具,用于探索模型的潜在空间,从而能够创造出多样化且高质量的输出。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了节点将操作的基础生成模型。它是所有采样活动的基础,直接影响生成输出的质量和类型。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- add_noise + - add_noise 参数控制是否在采样过程中入随机元素,这可以导致结果更加多样化和富有创造性。它是探索模型能力并实现多样化输出的一个重要方面。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- noise_seed + - noise_seed 参数在确定采样过程中应用的噪声模式的随机性和多样性方面起着重要作用。它确保噪声是可复现和一致的,这对于实验控制和比较至关重要。 + - Comfy dtype: INT + - Python dtype: int +- steps + - steps 参数决定了采样过程的进展,影响了在模型潜在空间内探索的粒度和深度。它是实现全面和细致的结果集的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg 参数是一个配置值,用于调整采样过程的行为,允许对输出特征进行微调。它是根据特定要求和期望的结果调整节点功能的重要工具。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name 参数指定了要采用的采样策略,这对节点有效导航模型潜在空间的能力至关重要。它塑造了采样过程的整体方法和方向。 + - Comfy dtype: ENUM + - Python dtype: str +- scheduler + - scheduler 参数定义了采样过程的调度方法,这对于管理节点操作的动态方面至关重要。它确保节点能够适应并响应模型潜在空间内的变化条件。 + - Comfy dtype: ENUM + - Python dtype: str +- positive + - positive 参数作为采样过程的指导,提供了节点应遵循的正面示例或条件。它对于引导输出朝着期望的特性发展并确保结果与预期方向一致至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: dict +- negative + - negative 参数为采样过程建立了约束或不期望的条件,这对于引导节点远离不良结果至关重要。它在塑造最终结果和保持输出质量方面发挥着重要作用。 + - Comfy dtype: CONDITIONING + - Python dtype: dict +- latent_image + - latent_image 参数是节点采样操作的主要输入,代表模型潜在空间中的初始状态或条件。它是节点生成输出的基础,并直接影响结果的性质。 + - Comfy dtype: LATENT + - Python dtype: dict +- start_at_step + - start_at_step 参数定义了采样过程的起点,指示节点应从哪一步开始其操作。它是控制采样活动的时间和顺序的重要因素。 + - Comfy dtype: INT + - Python dtype: int +- end_at_step + - end_at_step 参数设置了采样过程的终点,决定了节点应继续其操作的步数上限。它对于定义采样活动的范围和持续时间至关重要。 + - Comfy dtype: INT + - Python dtype: int +- noise_mode + - noise_mode 参数决定了生成噪声所使用的计算资源,选项包括 GPU 和 CPU。这是一个关键决策,影响采样过程的性能和效率。 + - Comfy dtype: ENUM + - Python dtype: str +- return_with_leftover_noise + - return_with_leftover_noise 参数决定节点是否应该在主要输出之外返回额外的噪声信息。这对于进一步的分析或后续处理步骤可能有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- batch_seed_mode + - batch_seed_mode 参数管理批处理中的种子分配,这对于保持一致性并在并行处理场景中控制噪声生成非常重要。它确保每个批次都有唯一的噪声种子,促进多样性并防止输出中的重叠。 + - Comfy dtype: ENUM + - Python dtype: str +- variation_seed + - variation_seed 参数在噪声生成过程中引入变异性,允许探索更广泛的结果范围。它对于在采样过程中创造独特且多样的结果至关重要。 + - Comfy dtype: INT + - Python dtype: int +- variation_strength + - variation_strength 参数调整噪声引入的变化的强度,这可以影响最终输出中变化的程度。它是控制结果多样性和创造性的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- noise_opt + - noise_opt 参数提供了一个选项,用于自定义采样过程中应用的噪声,为用户提供了尝试不同噪声配置及其对输出影响的能力。 + - Comfy dtype: NOISE + - Python dtype: torch.Tensor + +# Output types +- latent + - latent 参数包含了采样过程的结果样本,代表了节点操作的最终成果。它非常重要,因为它包含了进一步分析或生成最终图像所需的重要信息。 + - Comfy dtype: LATENT + - Python dtype: dict + +# Usage tips +- Infra type: GPU + +# Source code +``` +class KSamplerAdvanced_inspire: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'add_noise': ('BOOLEAN', {'default': True, 'label_on': 'enable', 'label_off': 'disable'}), 'noise_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, 'step': 0.5, 'round': 0.01}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'start_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'end_at_step': ('INT', {'default': 10000, 'min': 0, 'max': 10000}), 'noise_mode': (['GPU(=A1111)', 'CPU'],), 'return_with_leftover_noise': ('BOOLEAN', {'default': False, 'label_on': 'enable', 'label_off': 'disable'}), 'batch_seed_mode': (['incremental', 'comfy', 'variation str inc:0.01', 'variation str inc:0.05'],), 'variation_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'variation_strength': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}, 'optional': {'noise_opt': ('NOISE',)}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'sample' + CATEGORY = 'InspirePack/a1111_compat' + + def sample(self, model, add_noise, noise_seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, start_at_step, end_at_step, noise_mode, return_with_leftover_noise, denoise=1.0, batch_seed_mode='comfy', variation_seed=None, variation_strength=None, noise_opt=None): + force_full_denoise = True + if return_with_leftover_noise: + force_full_denoise = False + disable_noise = False + if not add_noise: + disable_noise = True + return common_ksampler(model, noise_seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise, disable_noise=disable_noise, start_step=start_at_step, last_step=end_at_step, force_full_denoise=force_full_denoise, noise_mode=noise_mode, incremental_seed_mode=batch_seed_mode, variation_seed=variation_seed, variation_strength=variation_strength, noise=noise_opt) +``` \ No newline at end of file diff --git a/docs/KSamplerAdvanced (WLSH).md b/docs/KSamplerAdvanced (WLSH).md new file mode 100644 index 0000000..aa7dac0 --- /dev/null +++ b/docs/KSamplerAdvanced (WLSH).md @@ -0,0 +1,103 @@ +# Documentation +- Class name: WLSH_KSamplerAdvanced +- Category: WLSH Nodes/sampling +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_KSamplerAdvanced节点旨在使用指定模型执行高级采样操作。它允许通过诸如添加噪声、随机种子和采样步骤等参数来定制采样过程。该节点能够通过微调去噪过程并利用各种采样策略和调度器来生成高质量的样本。 + +# Input types +## Required +- model + - 模型参数对于节点的操作至关重要,因为它定义了用于生成样本的生成模型。模型的选择显著影响生成样本的质量和特性。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- sampler_name + - sampler_name参数选择要使用的特定采样方法。不同的采样方法可能导致不同的样本质量和特性,使这个参数对于实现期望的结果至关重要。 + - Comfy dtype: comfy.samplers.KSampler.SAMPLERS + - Python dtype: str +- scheduler + - scheduler参数定义了在采样过程中将应用的调度策略。它对于控制采样步骤执行的速度很重要。 + - Comfy dtype: comfy.samplers.KSampler.SCHEDULERS + - Python dtype: str +- positive + - positive参数提供指导采样过程的条件信息,以生成具有期望属性的样本。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- negative + - negative参数提供额外的条件信息,有助于避免生成具有不希望的特性的样本。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- latent_image + - latent_image参数是采样过程的关键输入,代表采样开始的初始潜在状态。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +## Optional +- add_noise + - add_noise参数决定是否在采样过程中添加噪声。这会影响生成样本的多样性,并且是控制样本质量和噪声之间权衡的重要因素。 + - Comfy dtype: COMBO['enable', 'disable'] + - Python dtype: str +- seed + - seed参数用于在采样过程中引入随机性。它确保采样结果是可复现的,这对于调试和比较不同的采样配置至关重要。 + - Comfy dtype: INT + - Python dtype: int +- steps + - steps参数指定了采样过程中的迭代次数。步数越多,通常会导致更高质量的样本,但会增加计算成本。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数,代表采样过程的控制因子,允许在采样策略中微调探索和利用之间的平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_at_step + - start_at_step参数确定采样过程开始的步骤。它允许对采样程序进行细粒度控制。 + - Comfy dtype: INT + - Python dtype: int +- end_at_step + - end_at_step参数指定采样过程的最终步骤。它用于定义执行采样的步骤范围。 + - Comfy dtype: INT + - Python dtype: int +- return_with_leftover_noise + - return_with_leftover_noise参数控制采样图像是否包含采样过程中剩余的噪声。这对于进一步处理或分析非常有用。 + - Comfy dtype: COMBO['disable', 'enable'] + - Python dtype: str +- denoise + - denoise参数调整采样过程中应用的去噪强度。它是确定最终样本清晰度和质量的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- latent + - latent输出代表采样过程的最终潜在状态,可以用于进一步分析或作为后续处理步骤的输入。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- info + - info输出提供了采样过程的摘要,包括使用的种子、步数和应用的去噪强度等细节。 + - Comfy dtype: INFO + - Python dtype: Dict[str, Union[int, float, str]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WLSH_KSamplerAdvanced: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'add_noise': (['enable', 'disable'],), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'start_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'end_at_step': ('INT', {'default': 10000, 'min': 0, 'max': 10000}), 'return_with_leftover_noise': (['disable', 'enable'],), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('LATENT', 'INFO') + FUNCTION = 'sample' + CATEGORY = 'WLSH Nodes/sampling' + + def sample(self, model, add_noise, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, start_at_step, end_at_step, return_with_leftover_noise, denoise): + force_full_denoise = False + if return_with_leftover_noise == 'enable': + force_full_denoise = False + disable_noise = False + if add_noise == 'disable': + disable_noise = True + info = {'Seed: ': seed, 'Steps: ': steps, 'CFG scale: ': cfg, 'Sampler: ': sampler_name, 'Scheduler: ': scheduler, 'Start at step: ': start_at_step, 'End at step: ': end_at_step, 'Denoising strength: ': denoise} + samples = common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise, disable_noise=disable_noise, start_step=start_at_step, last_step=end_at_step, force_full_denoise=force_full_denoise) + return (samples[0], info) +``` \ No newline at end of file diff --git a/docs/KSamplerAdvancedPipe %2F%2FInspire.md b/docs/KSamplerAdvancedPipe %2F%2FInspire.md new file mode 100644 index 0000000..53a0052 --- /dev/null +++ b/docs/KSamplerAdvancedPipe %2F%2FInspire.md @@ -0,0 +1,84 @@ +# Documentation +- Class name: KSamplerAdvanced_inspire_pipe +- Category: InspirePack/a1111_compat +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点促进InspirePack流水线中的高级采样过程,整合噪声管理和调度机制,以完善生成潜在表示的过程。 + +# Input types +## Required +- basic_pipe + - basic_pipe参数是必需的,因为它提供了采样过程所需的基础组件,包括模型、clip以及其他必要元素。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, ...] +- add_noise + - 此参数控制是否在采样过程中引入噪声,影响生成的潜在图像的多样性和质量。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- noise_seed + - noise_seed参数对于噪声模式的可复现性至关重要,确保可以重新生成相同的噪声以获得一致的结果。 + - Comfy dtype: INT + - Python dtype: int +- steps + - steps参数定义了采样过程的进展,较高的值导致更精细和详细的潜在图像。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数调整采样器的配置设置,影响采样过程的整体行为和输出。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数选择要使用的特定采样算法,直接影响采样过程的效率和效果。 + - Comfy dtype: ENUM + - Python dtype: str +- scheduler + - scheduler参数规定了采样过程的调度策略,优化了速度和质量之间的权衡。 + - Comfy dtype: ENUM + - Python dtype: str +- latent_image + - latent_image参数是采样过程的输入,作为生成新潜在表示的基础。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- start_at_step + - start_at_step参数指示采样过程的初始步骤,决定了潜在图像生成的起始点。 + - Comfy dtype: INT + - Python dtype: int +- end_at_step + - end_at_step参数定义了采样过程的最终步骤,为潜在图像生成设定了边界。 + - Comfy dtype: INT + - Python dtype: int +- noise_mode + - noise_mode参数决定了用于噪声生成的计算资源,要么利用GPU的并行能力,要么使用CPU的顺序处理。 + - Comfy dtype: ENUM + - Python dtype: str + +# Output types +- latent + - latent参数代表采样过程的输出,提供了一个精炼和详细的潜在表示,可以进一步在流水线中使用。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- vae + - vae参数包括输出的变化自编码器组件,捕捉学习到的数据分布,并为进一步的分析和生成提供基础。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class KSamplerAdvanced_inspire_pipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'basic_pipe': ('BASIC_PIPE',), 'add_noise': ('BOOLEAN', {'default': True, 'label_on': 'enable', 'label_off': 'disable'}), 'noise_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, 'step': 0.5, 'round': 0.01}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'latent_image': ('LATENT',), 'start_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'end_at_step': ('INT', {'default': 10000, 'min': 0, 'max': 10000}), 'noise_mode': (['GPU(=A1111)', 'CPU'],), 'return_with_leftover_noise': ('BOOLEAN', {'default': False, 'label_on': 'enable', 'label_off': 'disable'}), 'batch_seed_mode': (['incremental', 'comfy', 'variation str inc:0.01', 'variation str inc:0.05'],), 'variation_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'variation_strength': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}, 'optional': {'noise_opt': ('NOISE',)}} + RETURN_TYPES = ('LATENT', 'VAE') + FUNCTION = 'sample' + CATEGORY = 'InspirePack/a1111_compat' + + def sample(self, basic_pipe, add_noise, noise_seed, steps, cfg, sampler_name, scheduler, latent_image, start_at_step, end_at_step, noise_mode, return_with_leftover_noise, denoise=1.0, batch_seed_mode='comfy', variation_seed=None, variation_strength=None, noise_opt=None): + (model, clip, vae, positive, negative) = basic_pipe + latent = KSamplerAdvanced_inspire().sample(model=model, add_noise=add_noise, noise_seed=noise_seed, steps=steps, cfg=cfg, sampler_name=sampler_name, scheduler=scheduler, positive=positive, negative=negative, latent_image=latent_image, start_at_step=start_at_step, end_at_step=end_at_step, noise_mode=noise_mode, return_with_leftover_noise=return_with_leftover_noise, denoise=denoise, batch_seed_mode=batch_seed_mode, variation_seed=variation_seed, variation_strength=variation_strength, noise_opt=noise_opt)[0] + return (latent, vae) +``` \ No newline at end of file diff --git a/docs/KSamplerAdvancedProgress %2F%2FInspire.md b/docs/KSamplerAdvancedProgress %2F%2FInspire.md new file mode 100644 index 0000000..f39d4bd --- /dev/null +++ b/docs/KSamplerAdvancedProgress %2F%2FInspire.md @@ -0,0 +1,127 @@ +# Documentation +- Class name: KSamplerAdvanced_progress +- Category: InspirePack/analysis +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +KSamplerAdvanced_progress节点旨在模型内促进高级采样程序,加入噪声和调度机制来完善生成过程。它旨在通过逐步调整采样参数来提高输出质量和多样性。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了节点将用于采样过程的基础架构和学习成果。它是节点操作的基础,决定了生成输出的潜在范围和性质。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- add_noise + - add_noise参数至关重要,它决定了在采样过程中是否会引入噪声。这可能导致结果更加多样化,甚至更具创造性,为输出增加了随机性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- noise_seed + - noise_seed参数很重要,因为它为噪声生成中的随机性提供了基础。它确保噪声模式是可复现的,这对于一致的实验和结果比较非常重要。 + - Comfy dtype: INT + - Python dtype: int +- steps + - steps参数规定了采样过程将经历的迭代次数。它直接影响生成输出的复杂性和细节,更多的步骤可能导致更精细的结果。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数是一个配置值,用于调整采样过程的行为。它是控制输出生成中探索和利用之间平衡的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数指定了要使用的采样方法。它影响了生成输出所采用的策略,这可以显著改变结果的特征和分布。 + - Comfy dtype: SAMPLER + - Python dtype: str +- scheduler + - scheduler参数定义了随时间调整采样过程的调度策略。它在实现生成中不同方面(如噪声水平和采样频率)之间的动态平衡方面起着重要作用。 + - Comfy dtype: SCHEDULER + - Python dtype: str +- positive + - positive参数提供了正向调节数据,引导采样过程朝着期望的结果发展。它对于引导生成朝着特定方向发展至关重要,确保结果符合某些标准或期望。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- negative + - negative参数提供了负向调节数据,帮助采样过程避免不希望的结果。它在通过防止生成某些模式或特征来精炼输出方面发挥着关键作用。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- latent_image + - latent_image参数是采样过程的基础潜在表示。它是一个关键元素,因为它直接影响生成输出的初始状态和潜在轨迹。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- start_at_step + - start_at_step参数指定了采样过程的起点。它对于定义将要执行的迭代范围很重要,从而影响生成的整体进展和时机。 + - Comfy dtype: INT + - Python dtype: int +- end_at_step + - end_at_step参数标记了采样过程的终点。它与start_at_step一起,决定了过程将覆盖的总步数,这直接影响结果的全面性。 + - Comfy dtype: INT + - Python dtype: int +- noise_mode + - noise_mode参数规定了噪声生成和处理的计算模式。这是一个关键的选择,它影响节点的性能和效率,GPU更适合密集型计算,而CPU适用于资源消耗较少的任务。 + - Comfy dtype: GPU(=A1111),CPU + - Python dtype: str +- return_with_leftover_noise + - return_with_leftover_noise参数决定节点是否将剩余噪声与潜在样本一起返回。这对于进一步的分析或额外的处理阶段可能有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- interval + - interval参数设置了节点在采样过程中保存中间潜在样本的频率。它影响输出的粒度,并允许捕捉生成的进展。 + - Comfy dtype: INT + - Python dtype: int +- omit_start_latent + - omit_start_latent参数决定是否从输出中省略初始潜在样本。这在某些工作流程中很有用,比如起始点不感兴趣或为了减少结果中的冗余。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- prev_progress_latent_opt + - prev_progress_latent_opt参数允许继续之前的采样过程,提供了一种将新结果附加到现有潜在样本的方法。这有助于创建扩展的或迭代的输出。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Output types +- latent + - latent输出代表节点生成的最终潜在样本,包含了采样过程的最终成果。它是关键组成部分,因为它为进一步分析或下游处理提供了基础。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- progress_latent + - progress_latent输出提供了在采样过程中特定间隔捕获的中间潜在样本数组。这个特性对于监控生成的演变和理解模型行为的动态非常有价值。 + - Comfy dtype: LATENT + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class KSamplerAdvanced_progress(a1111_compat.KSamplerAdvanced_inspire): + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'add_noise': ('BOOLEAN', {'default': True, 'label_on': 'enable', 'label_off': 'disable'}), 'noise_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, 'step': 0.5, 'round': 0.01}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'start_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'end_at_step': ('INT', {'default': 10000, 'min': 0, 'max': 10000}), 'noise_mode': (['GPU(=A1111)', 'CPU'],), 'return_with_leftover_noise': ('BOOLEAN', {'default': False, 'label_on': 'enable', 'label_off': 'disable'}), 'interval': ('INT', {'default': 1, 'min': 1, 'max': 10000}), 'omit_start_latent': ('BOOLEAN', {'default': False, 'label_on': 'True', 'label_off': 'False'})}, 'optional': {'prev_progress_latent_opt': ('LATENT',)}} + FUNCTION = 'sample' + CATEGORY = 'InspirePack/analysis' + RETURN_TYPES = ('LATENT', 'LATENT') + RETURN_NAMES = ('latent', 'progress_latent') + + def sample(self, model, add_noise, noise_seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, start_at_step, end_at_step, noise_mode, return_with_leftover_noise, interval, omit_start_latent, prev_progress_latent_opt=None): + sampler = a1111_compat.KSamplerAdvanced_inspire() + if omit_start_latent: + result = [] + else: + result = [latent_image['samples']] + for i in range(start_at_step, end_at_step + 1): + cur_add_noise = i == start_at_step and add_noise + cur_return_with_leftover_noise = i != steps or return_with_leftover_noise + latent_image = sampler.sample(model, cur_add_noise, noise_seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, i, i + 1, noise_mode, cur_return_with_leftover_noise)[0] + print(f'{i}, {i + 1}') + if i % interval == 0 or i == steps: + result.append(latent_image['samples']) + if len(result) > 0: + result = torch.cat(result) + result = {'samples': result} + else: + result = latent_image + if prev_progress_latent_opt is not None: + result['samples'] = torch.cat((prev_progress_latent_opt['samples'], result['samples']), dim=0) + return (latent_image, result) +``` \ No newline at end of file diff --git a/docs/KSamplerAdvancedProvider.md b/docs/KSamplerAdvancedProvider.md new file mode 100644 index 0000000..e9c2fe7 --- /dev/null +++ b/docs/KSamplerAdvancedProvider.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: KSamplerAdvancedProvider +- Category: ImpactPack/Sampler +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +KSamplerAdvancedProvider节点旨在为生成模型生成高级采样技术。它利用KSamplerAdvancedWrapper提供复杂的采样过程,可以通过各种参数进行微调,如配置设置、采样器名称和调度器。此节点对于在图像合成任务中实现高质量结果至关重要,因为它允许对采样过程进行精细控制。 + +# Input types +## Required +- cfg + - ‘cfg’参数对于配置采样过程至关重要。它通过确定采样步骤的规模等关键方面,影响采样器的整体行为。此参数对于在图像合成中实现预期结果至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - ‘sampler_name’参数指定了采样过程中要使用的采样器类型。它是形成生成样本特征的关键决定因素,因此在节点的执行中扮演着重要角色。 + - Comfy dtype: SAMPLER + - Python dtype: str +- scheduler + - ‘scheduler’参数定义了采样步骤的调度策略。它对于控制采样进度至关重要,从而影响采样过程的最终输出。 + - Comfy dtype: SCHEDULER + - Python dtype: str +- basic_pipe + - ‘basic_pipe’参数封装了采样过程所需的基础组件,包括模型、配置和条件。它对于节点的运行是不可或缺的,因为它为高级采样技术提供了必要的上下文。 + - Comfy dtype: BASIC_PIPE + - Python dtype: tuple +## Optional +- sigma_factor + - ‘sigma_factor’参数调整采样过程中的噪声水平,允许控制每一步引入的噪声。这种微调能力对于在生成的图像中实现细节和噪声之间的平衡非常重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_opt + - 可选的‘sampler_opt’参数提供了额外的选项,以进一步自定义采样过程。它允许高级控制,并且可以显著影响采样的结果,为用户提供更高程度的灵活性。 + - Comfy dtype: SAMPLER + - Python dtype: dict + +# Output types +- KSAMPLER_ADVANCED + - KSamplerAdvancedProvider节点的输出是一个高级采样器对象,它封装了复杂的采样过程。它非常重要,因为它代表了节点功能的顶点,为用户提供了一个强大的工具,通过细微的采样技术生成高质量的图像。 + - Comfy dtype: KSAMPLER_ADVANCED + - Python dtype: KSamplerAdvancedWrapper + +# Usage tips +- Infra type: GPU + +# Source code +``` +class KSamplerAdvancedProvider: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'cfg': ('FLOAT', {'default': 8.0, 'min': 0.0, 'max': 100.0}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'sigma_factor': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'basic_pipe': ('BASIC_PIPE',)}, 'optional': {'sampler_opt': ('SAMPLER',)}} + RETURN_TYPES = ('KSAMPLER_ADVANCED',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Sampler' + + def doit(self, cfg, sampler_name, scheduler, basic_pipe, sigma_factor=1.0, sampler_opt=None): + (model, _, _, positive, negative) = basic_pipe + sampler = KSamplerAdvancedWrapper(model, cfg, sampler_name, scheduler, positive, negative, sampler_opt=sampler_opt, sigma_factor=sigma_factor) + return (sampler,) +``` \ No newline at end of file diff --git a/docs/KSamplerPipe %2F%2FInspire.md b/docs/KSamplerPipe %2F%2FInspire.md new file mode 100644 index 0000000..dcfc7d5 --- /dev/null +++ b/docs/KSamplerPipe %2F%2FInspire.md @@ -0,0 +1,89 @@ +# Documentation +- Class name: KSampler_inspire_pipe +- Category: InspirePack/a1111_compat +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +KSampler_inspire_pipe节点旨在促进生成模型内的采样过程,通过集成多种参数来指导生成新的潜在表示。它通过整合随机种子、指定的步数和配置设置来细化输出。该节点的主要目的是通过提供一个结构化但灵活的框架来探索模型的潜在空间,从而增强创作过程。 + +# Input types +## Required +- basic_pipe + - basic_pipe参数对于采样过程至关重要,它提供了采样过程所需的基础组件,包括模型和其他相关元素。它是节点操作的支柱,使得能够生成潜在样本。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, ...] +- seed + - seed参数对于引入采样过程中的随机性至关重要,确保生成的样本多样化且不重复。它作为随机数生成的起点,从而显著影响输出的唯一性。 + - Comfy dtype: INT + - Python dtype: int +- steps + - steps参数规定了采样过程将经历的迭代次数,直接影响潜在空间内探索的深度。它是决定生成样本多样性和质量的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数作为一个配置设置,微调采样过程,允许对生成样本的行为和特征进行调整。它在塑造节点的整体输出中起着关键作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数在选择合适的采样策略方面起着重要作用,这反过来影响了生成样本的分布和性质。它是节点功能中一个关键的决策点。 + - Comfy dtype: ENUM + - Python dtype: str +- scheduler + - scheduler参数决定了采样过程的调度策略,管理生成步骤的进展和节奏。它对于保持样本生成的结构化方法是必不可少的。 + - Comfy dtype: ENUM + - Python dtype: str +- latent_image + - latent_image参数是采样过程的输入,代表新样本将生成的初始状态或上下文。它是节点操作的组成部分,作为创建新潜在表示的基础。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, Any] +- denoise + - denoise参数调整采样过程中应用的降噪水平,影响生成样本的清晰度和质量。它是平衡噪声和细节之间权衡的关键控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- noise_mode + - noise_mode参数指定了噪声生成的计算模式,要么利用GPU进行加速处理,要么选择CPU。它影响采样过程的效率和性能。 + - Comfy dtype: ENUM + - Python dtype: str +- batch_seed_mode + - batch_seed_mode参数管理批次间的随机性方法,这对于确保生成样本的多样性至关重要。它影响输出的整体可变性和一致性。 + - Comfy dtype: ENUM + - Python dtype: str +## Optional +- variation_seed + - variation_seed参数在采样过程中引入额外的随机性,有助于输出的多样性。它允许在生成的样本中进行微妙的变化,增强节点的创作范围。 + - Comfy dtype: INT + - Python dtype: int +- variation_strength + - variation_strength参数控制生成样本中变化的强度,平衡新颖性与原始输入的水平。它是实现多样化和引人入胜的输出集的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- latent + - latent参数代表采样过程的输出,包含新生成的潜在表示。它是节点主要功能直接反映,封装了采样过程的创作成果。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, Any] +- vae + - vae参数包括输出的变化分自编码器组件,对于生成高质量、结构化的表示至关重要。它标志着节点功能内部集成了先进的生成模型。 + - Comfy dtype: VAE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class KSampler_inspire_pipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'basic_pipe': ('BASIC_PIPE',), '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,), 'latent_image': ('LATENT',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'noise_mode': (['GPU(=A1111)', 'CPU'],), 'batch_seed_mode': (['incremental', 'comfy', 'variation str inc:0.01', 'variation str inc:0.05'],), 'variation_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'variation_strength': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('LATENT', 'VAE') + FUNCTION = 'sample' + CATEGORY = 'InspirePack/a1111_compat' + + def sample(self, basic_pipe, seed, steps, cfg, sampler_name, scheduler, latent_image, denoise, noise_mode, batch_seed_mode='comfy', variation_seed=None, variation_strength=None): + (model, clip, vae, positive, negative) = basic_pipe + latent = common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise, noise_mode, incremental_seed_mode=batch_seed_mode, variation_seed=variation_seed, variation_strength=variation_strength)[0] + return (latent, vae) +``` \ No newline at end of file diff --git a/docs/KSamplerProgress %2F%2FInspire.md b/docs/KSamplerProgress %2F%2FInspire.md new file mode 100644 index 0000000..0be34fd --- /dev/null +++ b/docs/KSamplerProgress %2F%2FInspire.md @@ -0,0 +1,107 @@ +# Documentation +- Class name: KSampler_progress +- Category: InspirePack/analysis +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +KSampler_progress节点旨在通过逐步引入噪声并在指定的步数内细化潜在表示来促进模型的采样过程。它增强了对模型潜在空间的探索,并提供了模型在不同噪声条件下行为的洞察。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了要探索的潜在空间的来源。它是节点操作的基础,决定了可以生成和分析的样本类型。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- seed + - 种子用于初始化随机数生成器,确保采样过程可复现和一致,对保持实验结果的完整性起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步数参数决定了采样过程将经历的迭代次数。它直接影响到潜在空间探索的深度和结果的粒度。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数,通常表示为'cfg',用于调整采样过程的设置。它在微调节点操作以实现期望的结果方面起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数指定了在采样过程中要使用的采样器类型。它决定了用于遍历潜在空间的策略,并对样本的质量有着显著影响。 + - Comfy dtype: ENUM + - Python dtype: str +- scheduler + - 调度器参数定义了采样过程的调度策略。它在管理噪声引入的进展和采样迭代的步调方面至关重要。 + - Comfy dtype: ENUM + - Python dtype: str +- positive + - positive参数用于向模型提供正向调节数据,可以引导采样过程朝着期望的特发展。这对于将输出引向特定结果至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- negative + - negative参数用于提供负向调节数据,有助于避免采样过程中不希望出现的特征。它对于提高生成样本的质量至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- latent_image + - latent_image参数是包含采样过程初始样本或种子的输入。它为探索设置了起点,对于生成后续的潜在样本至关重要。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, Any] +- denoise + - denoise参数控制采样过程中应用的噪声减少水平。它在平衡潜在空间探索与结果样本清晰度之间的权衡中起着关键作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- noise_mode + - noise_mode参数决定了噪声处理的计算模式,无论是GPU还是CPU。它对于优化采样过程的性能和效率非常重要。 + - Comfy dtype: ENUM + - Python dtype: str +- interval + - 间隔参数指定了在采样过程中收集中间样本的频率。它影响了捕获的数据点的密度和进度跟踪的细节。 + - Comfy dtype: INT + - Python dtype: int +- omit_start_latent + - omit_start_latent参数决定是否在最终输出中包含初始潜在样本。它有助于管理结果的范围,专注于样本随时间的演变。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- latent + - 潜在输出代表了采样过程后最终精炼的潜在样本。它封装了探索的结果,并作为进一步分析或生成图像的基础。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, Any +- progress_latent + - progress_latent输出在采样过程的指定间隔提供了潜在样本的中间表示。它提供了样本随时间进展和转变的洞察。 + - Comfy dtype: LATENT + - Python dtype: List[Dict[str, Any]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class KSampler_progress(a1111_compat.KSampler_inspire): + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'noise_mode': (['GPU(=A1111)', 'CPU'],), 'interval': ('INT', {'default': 1, 'min': 1, 'max': 10000}), 'omit_start_latent': ('BOOLEAN', {'default': True, 'label_on': 'True', 'label_off': 'False'})}} + CATEGORY = 'InspirePack/analysis' + RETURN_TYPES = ('LATENT', 'LATENT') + RETURN_NAMES = ('latent', 'progress_latent') + + def sample(self, model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise, noise_mode, interval, omit_start_latent): + adv_steps = int(steps / denoise) + sampler = a1111_compat.KSamplerAdvanced_inspire() + if omit_start_latent: + result = [] + else: + result = [latent_image['samples']] + for i in range(0, adv_steps + 1): + add_noise = i == 0 + return_with_leftover_noise = i != adv_steps + latent_image = sampler.sample(model, add_noise, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, i, i + 1, noise_mode, return_with_leftover_noise)[0] + if i % interval == 0 or i == adv_steps: + result.append(latent_image['samples']) + if len(result) > 0: + result = torch.cat(result) + result = {'samples': result} + else: + result = latent_image + return (latent_image, result) +``` \ No newline at end of file diff --git a/docs/KSamplerProvider.md b/docs/KSamplerProvider.md new file mode 100644 index 0000000..9b1e591 --- /dev/null +++ b/docs/KSamplerProvider.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: KSamplerProvider +- Category: ImpactPack/Sampler +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +KSamplerProvider节点旨在方便创建和配置KSampler,这是生成模型中使用的一种采样方法。它封装了使用各种参数(如种子、步骤和配置)初始化采样器的过程,从而允许从模型生成高质量的样本。 + +# Input types +## Required +- seed + - 种子参数对于采样过程的可重复性至关重要。它确保相同的种子始终产生相同的样本,是控制采样随机性的关键要素。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步骤参数定义了采样过程将经历的迭代次数。更多的步骤可以产生更高质量的样本,但也可能增加计算时间。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数,代表配置,用于调整采样过程的设置。它可以影响生成样本的质量和特性。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数指定了采样过程中要使用的采样器类型。不同的采样器可以产生不同的结果,因此这个参数对于实现期望的结果至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- scheduler + - 调度器参数决定了采样过程中将应用的调度算法。它在采样的效率和效果中起着重要作用。 + - Comfy dtype: STRING + - Python dtype: str +- denoise + - 去噪参数控制采样过程中应用的噪声降低水平。它是实现样本质量和噪声之间平衡的重要因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- basic_pipe + - basic_pipe参数是一个包含模型和采样过程所需额外数据的复杂结构。它对KSamplerProvider节点的功能至关重要。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, Any, Any, Any, Any] + +# Output types +- KSAMPLER + - KSamplerProvider节点的输出是一个KSampler对象,用于模型生成样本。它代表了已配置的采样器,准备用于采样过程。 + - Comfy dtype: KSAMPLER + - Python dtype: KSamplerWrapper + +# Usage tips +- Infra type: GPU + +# Source code +``` +class KSamplerProvider: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'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': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'basic_pipe': ('BASIC_PIPE',)}} + RETURN_TYPES = ('KSAMPLER',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Sampler' + + def doit(self, seed, steps, cfg, sampler_name, scheduler, denoise, basic_pipe): + (model, _, _, positive, negative) = basic_pipe + sampler = KSamplerWrapper(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise) + return (sampler,) +``` \ No newline at end of file diff --git a/docs/KSamplerSeq.md b/docs/KSamplerSeq.md new file mode 100644 index 0000000..f70009c --- /dev/null +++ b/docs/KSamplerSeq.md @@ -0,0 +1,218 @@ +# Documentation +- Class name: KSamplerSeq +- Category: sampling +- Output node: False +- Repo Ref: https://github.com/WASasquatch/WAS_Extras + +KSamplerSeq节点旨在使用各种种子模式和条件序列执行顺序采样操作。它管理生成潜在样本,具有在正负条件序列之间交替、插值潜在样本以及控制去噪过程的能力。该节点确保了一个连贯且可控的采样工作流程,可以根据特定的创造性或分析目的进行微调。 + +# Input types +## Required +- model + - 模型参数对于KSamplerSeq节点至关重要,因为它定义了将用于采样的生成模型。模型的选择显著影响生成样本的质量和风格。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- seed + - 种子参数对于初始化随机数生成过程至关重要,确保了采样操作中的可重复性。它为生成的种子序列设定了起始点。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- seed_mode_seq + - seed_mode_seq参数决定了采样序列中种子值是如何更新的,允许采用不同的采样策略,如增量、递减、随机选择或固定种子。 + - Comfy dtype: COMBO['increment', 'decrement', 'random', 'fixed'] + - Python dtype: str +- alternate_values + - alternate_values参数在采样过程中启用不同种子状态之间的交替,为生成的样本增加了变化性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- steps + - steps参数指定了采样过程中的步骤数量,这直接影响生成样本的分辨率和细节。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数,代表配置值,用于控制采样过程的保真度,在生成样本的细节和噪声之间进行平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数从可用的采样器中选择要使用的特定采样方法,影响采样过程的整体行为和特性。 + - Comfy dtype: comfy.samplers.KSampler.SAMPLERS + - Python dtype: str +- scheduler + - scheduler参数定义了采样过程中的噪声减少策略,这可能会影响生成样本的平滑度和连贯性。 + - Comfy dtype: comfy.samplers.KSampler.SCHEDULERS + - Python dtype: str +- sequence_loop_count + - sequence_loop_count参数设置了采样序列的迭代次数,允许在单次运行中生成多个样本。 + - Comfy dtype: INT + - Python dtype: int +- positive_seq + - positive_seq参数提供了一系列正向条件值,引导采样过程朝着期望的结果发展。 + - Comfy dtype: CONDITIONING_SEQ + - Python dtype: List[Tuple[int, torch.Tensor, Dict[str, torch.Tensor]]] +- negative_seq + - negative_seq参数提供了一系列负向条件值,通过阻止不希望的结果来帮助完善采样过程。 + - Comfy dtype: CONDITIONING_SEQ + - Python dtype: List[Tuple[int, torch.Tensor, Dict[str, torch.Tensor]]] +- use_conditioning_slerp + - use_conditioning_slerp参数启用了球面线性插值(SLERP)来混合条件值,这可以导致样本状态之间更平滑的过渡。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- cond_slerp_strength + - cond_slerp_strength参数控制混合条件值时SLERP操作的强度,影响状态间插值的范围。 + - Comfy dtype: FLOAT + - Python dtype: float +- latent_image + - latent_image参数表示用作采样过程起点的初始潜在状态,影响生成样本的方向和特性。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- use_latent_interpolation + - use_latent_interpolation参数切换应用潜在插值在生成样本之间,这可以产生更连贯的样本序列。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- latent_interpolation_mode + - latent_interpolation_mode参数选择要使用的潜在插值方法,这定义了连续样本如何混合在一起。 + - Comfy dtype: COMBO['Blend', 'Slerp', 'Cosine Interp'] + - Python dtype: str +- latent_interp_strength + - latent_interp_strength参数调整潜在插值的影响,决定一个样本在序列中如何平滑地过渡到下一个样本。 + - Comfy dtype: FLOAT + - Python dtype: float +- denoise_start + - denoise_start参数设置了初始去噪强度,这影响采样过程开始时的噪声减少。 + - Comfy dtype: FLOAT + - Python dtype: float +- denoise_seq + - denoise_seq参数控制整个采样序列中的去噪强度,允许随时间微调噪声减少。 + - Comfy dtype: FLOAT + - Python dtype: float +- unsample_latents + - 当启用unsample_latents参数时,触发未采样潜在状态的生成过程,这可以引入更多的多样性到采样输出中。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- samples + - samples参数封装了采样过程中生成的潜在样本。它是代表生成图像潜在空间的张量集合。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class KSamplerSeq: + + def __init__(self): + self.previous_seed = None + self.current_seed = None + + def initialize_seeds(self, initial_seed): + self.previous_seed = initial_seed + self.current_seed = initial_seed + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'seed_mode_seq': (['increment', 'decrement', 'random', 'fixed'],), 'alternate_values': ('BOOLEAN', {'default': True}), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'cfg': ('FLOAT', {'default': 8.0, 'min': 0.0, 'max': 100.0, 'step': 0.5, 'round': 0.01}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'sequence_loop_count': ('INT', {'default': 20, 'min': 1, 'max': 1024, 'step': 1}), 'positive_seq': ('CONDITIONING_SEQ',), 'negative_seq': ('CONDITIONING_SEQ',), 'use_conditioning_slerp': ('BOOLEAN', {'default': False}), 'cond_slerp_strength': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'latent_image': ('LATENT',), 'use_latent_interpolation': ('BOOLEAN', {'default': False}), 'latent_interpolation_mode': (['Blend', 'Slerp', 'Cosine Interp'],), 'latent_interp_strength': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'denoise_start': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'denoise_seq': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'unsample_latents': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'sample' + CATEGORY = 'sampling' + + def update_seed(self, seed, seed_mode): + if seed_mode == 'increment': + return seed + 1 + elif seed_mode == 'decrement': + return seed - 1 + elif seed_mode == 'random': + return random.randint(0, 18446744073709551615) + elif seed_mode == 'fixed': + return seed + + def hash_tensor(self, tensor): + tensor = tensor.cpu().contiguous() + return hashlib.sha256(tensor.numpy().tobytes()).hexdigest() + + def update_conditioning(self, conditioning_seq, loop_count, last_conditioning): + matching_conditioning = None + for (idx, conditioning, *_) in conditioning_seq: + if int(idx) == loop_count: + matching_conditioning = conditioning + break + return matching_conditioning if matching_conditioning else last_conditioning if last_conditioning else None + + def update_alternate_seed(self, loop_count): + if loop_count % 3 == 0: + if self.previous_seed is None: + self.previous_seed = self.current_seed + else: + (self.previous_seed, self.current_seed) = (self.current_seed, self.previous_seed + 1 if loop_count // 2 % 2 == 0 else self.previous_seed - 1) + return self.current_seed + + def alternate_denoise(self, current_denoise): + return 0.95 if current_denoise == 0.75 else 0.75 + + def sample(self, model, seed, seed_mode_seq, alternate_values, steps, cfg, sampler_name, scheduler, sequence_loop_count, positive_seq, negative_seq, cond_slerp_strength, latent_image, use_latent_interpolation, latent_interpolation_mode, latent_interp_strength, denoise_start=1.0, denoise_seq=0.5, use_conditioning_slerp=False, unsample_latents=False, alternate_mode=False): + positive_seq = positive_seq + negative_seq = negative_seq + results = [] + positive_conditioning = None + negative_conditioning = None + self.initialize_seeds(seed) + for loop_count in range(sequence_loop_count): + if alternate_values and loop_count % 2 == 0: + seq_seed = self.update_alternate_seed(seed) if seed_mode_seq != 'fixed' else seed + else: + seq_seed = seed if loop_count <= 0 else self.update_seed(seq_seed, seed_mode_seq) + print(f'Loop count: {loop_count}, Seed: {seq_seed}') + last_positive_conditioning = positive_conditioning[0] if positive_conditioning else None + last_negative_conditioning = negative_conditioning[0] if negative_conditioning else None + positive_conditioning = self.update_conditioning(positive_seq, loop_count, last_positive_conditioning) + negative_conditioning = self.update_conditioning(negative_seq, loop_count, last_negative_conditioning) + if use_conditioning_slerp and (last_positive_conditioning and last_negative_conditioning): + a = last_positive_conditioning[0].clone() + b = positive_conditioning[0].clone() + na = last_negative_conditioning[0].clone() + nb = negative_conditioning[0].clone() + pa = last_positive_conditioning[1]['pooled_output'].clone() + pb = positive_conditioning[1]['pooled_output'].clone() + npa = last_negative_conditioning[1]['pooled_output'].clone() + npb = negative_conditioning[1]['pooled_output'].clone() + pos_cond = slerp(cond_slerp_strength, a, b) + pos_pooled = slerp(cond_slerp_strength, pa, pb) + neg_cond = slerp(cond_slerp_strength, na, nb) + neg_pooled = slerp(cond_slerp_strength, npa, npb) + positive_conditioning = [pos_cond, {'pooled_output': pos_pooled}] + negative_conditioning = [neg_cond, {'pooled_output': neg_pooled}] + positive_conditioning = [positive_conditioning] + negative_conditioning = [negative_conditioning] + if positive_conditioning is not None or negative_conditioning is not None: + end_at_step = steps + if results is not None and len(results) > 0: + latent_input = {'samples': results[-1]} + denoise = denoise_seq + start_at_step = round((1 - denoise) * steps) + end_at_step = steps + else: + latent_input = latent_image + denoise = denoise_start + if unsample_latents and loop_count > 0: + force_full_denoise = False if loop_count > 0 or loop_count <= steps - 1 else True + disable_noise = False + unsampled_latent = unsample(model=model, seed=seq_seed, cfg=cfg, sampler_name=sampler_name, steps=steps, end_at_step=end_at_step, scheduler=scheduler, normalize=False, positive=positive_conditioning, negative=negative_conditioning, latent_image=latent_input)[0] + sample = nodes.common_ksampler(model, seq_seed, steps, cfg, sampler_name, scheduler, positive_conditioning, negative_conditioning, unsampled_latent, denoise=denoise, disable_noise=disable_noise, start_step=start_at_step, last_step=end_at_step, force_full_denoise=force_full_denoise)[0]['samples'] + else: + sample = nodes.common_ksampler(model, seq_seed, steps, cfg, sampler_name, scheduler, positive_conditioning, negative_conditioning, latent_input, denoise=denoise)[0]['samples'] + if use_latent_interpolation and results and (loop_count > 0): + if latent_interpolation_mode == 'Blend': + sample = blend_latents(latent_interp_strength, results[-1], sample) + elif latent_interpolation_mode == 'Slerp': + sample = slerp_latents(latent_interp_strength, results[-1], sample) + elif latent_interpolation_mode == 'Cosine Interp': + sample = cosine_interp_latents(latent_interp_strength, results[-1], sample) + else: + sample = sample + results.append(sample) + results = torch.cat(results, dim=0) + results = {'samples': results} + return (results,) +``` \ No newline at end of file diff --git a/docs/KSamplerSeq2.md b/docs/KSamplerSeq2.md new file mode 100644 index 0000000..c2ac5c3 --- /dev/null +++ b/docs/KSamplerSeq2.md @@ -0,0 +1,170 @@ +# Documentation +- Class name: KSamplerSeq2 +- Category: sampling +- Output node: False +- Repo Ref: https://github.com/WASasquatch/WAS_Extras + +KSamplerSeq2节点旨在促进生成模型中高级采样技术的应用。它管理种子生成和操作的复杂性,允许使用各种采样策略,如增量、递减、随机和固定种子模式。该节点还结合了条件化、潜在插值和噪声注入来微调采样过程,最终生成高质量的潜在表示。 + +# Input types +## Required +- model + - 模型参数对于KSamplerSeq2节点至关重要,因为它定义了将用于采样的生成模型。模型的选择对生成样本的质量和类型有显著影响。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- seed + - 种子参数对于初始化随机数生成过程至关重要,确保了采样程序的可重复性。它为基于种子的采样方法设置了起始点。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- seed_mode_seq + - seed_mode_seq参数决定了在整个采样序列中种子值是如何调整或选择的,影响生成样本的多样性和连贯性。 + - Comfy dtype: COMBO['increment', 'decrement', 'random', 'fixed'] + - Python dtype: str + +# Output types +- samples + - KSamplerSeq2节点的samples输出代表生成的潜在向量集合。这些向量包含了采样数据的编码信息,可供进一步处理或分析。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class KSamplerSeq2: + + def __init__(self): + self.previous_seed = None + self.current_seed = None + + def initialize_seeds(self, initial_seed): + self.previous_seed = initial_seed + self.current_seed = initial_seed + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'seed_mode_seq': (['increment', 'decrement', 'random', 'fixed'],), 'alternate_values': ('BOOLEAN', {'default': True}), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'cfg': ('FLOAT', {'default': 8.0, 'min': 0.0, 'max': 100.0, 'step': 0.5, 'round': 0.01}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'frame_count': ('INT', {'default': 0, 'min': 0, 'max': 1024, 'step': 1}), 'cond_keyframes': ('INT', {'default': 0, 'min': 0, 'max': 1024, 'step': 1}), 'positive_seq': ('CONDITIONING',), 'negative_seq': ('CONDITIONING',), 'use_conditioning_slerp': ('BOOLEAN', {'default': False}), 'cond_slerp_strength': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'latent_image': ('LATENT',), 'use_latent_interpolation': ('BOOLEAN', {'default': False}), 'latent_interpolation_mode': (['Blend', 'Slerp', 'Cosine Interp'],), 'latent_interp_strength': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'denoise_start': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'denoise_seq': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'unsample_latents': ('BOOLEAN', {'default': False}), 'inject_noise': ('BOOLEAN', {'default': True}), 'noise_strength': ('FLOAT', {'default': 0.1, 'max': 1.0, 'min': 0.001, 'step': 0.001}), 'denoise_sine': ('BOOLEAN', {'default': True}), 'denoise_max': ('FLOAT', {'default': 0.9, 'max': 1.0, 'min': 0.0, 'step': 0.001}), 'seed_keying': ('BOOLEAN', {'default': True}), 'seed_keying_mode': (['sine', 'modulo'],), 'seed_divisor': ('INT', {'default': 4, 'max': 1024, 'min': 2, 'step': 1})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'sample' + CATEGORY = 'sampling' + + def update_seed(self, seed, seed_mode): + if seed_mode == 'increment': + return seed + 1 + elif seed_mode == 'decrement': + return seed - 1 + elif seed_mode == 'random': + return random.randint(0, 18446744073709551615) + elif seed_mode == 'fixed': + return seed + + def alternate_seed_modulo(self, current, seed, divisor): + if current % divisor == 0: + new_seed = (seed + current) % 18446744073709551615 + else: + new_seed = seed + return new_seed + + def alternate_seed_sine(self, current, start_seed, divisor): + seed = 1000 * np.sin(2 * math.pi * current / divisor) + start_seed + return seed + + def alternate_denoise(self, curent, total, start_denoise=0.5, max_denoise=0.95): + amplitude = (max_denoise - start_denoise) / 2 + mid_point = (max_denoise + start_denoise) / 2 + cycle_position = math.pi * 2 * curent / total + current_denoise = amplitude * math.sin(cycle_position) + mid_point + return current_denoise + + def inject_noise(self, latent_image, noise_strength): + noise = torch.randn_like(latent_image) * noise_strength + return latent_image + noise + + def sample(self, model, seed, seed_mode_seq, alternate_values, steps, cfg, sampler_name, scheduler, frame_count, cond_keyframes, positive_seq, negative_seq, cond_slerp_strength, latent_image, use_latent_interpolation, latent_interpolation_mode, latent_interp_strength, denoise_start=1.0, denoise_seq=0.5, use_conditioning_slerp=False, unsample_latents=False, alternate_mode=False, inject_noise=True, noise_strength=0.1, denoise_sine=True, denoise_max=0.9, seed_keying=True, seed_keying_mode='sine', seed_divisor=4): + if not isinstance(positive_seq, list): + positive_seq = [positive_seq] + if not isinstance(negative_seq, list): + negative_seq = [negative_seq] + if not isinstance(cond_keyframes, list): + cond_keyframes = [cond_keyframes] + cond_keyframes.sort() + positive_cond_idx = 0 + negative_cond_idx = 0 + results = [] + self.initialize_seeds(seed) + sequence_loop_count = max(frame_count, len(positive_seq)) if cond_keyframes else len(positive_seq) + print(f'Starting loop sequence with {sequence_loop_count} frames.') + print(f'Using {len(positive_seq)} positive conditionings and {len(negative_seq)} negative conditionings') + print(f"Conditioning keyframe schedule is: {', '.join(map(str, cond_keyframes))}") + for loop_count in range(sequence_loop_count): + if loop_count in cond_keyframes: + positive_cond_idx = min(positive_cond_idx + 1, len(positive_seq) - 1) + negative_cond_idx = min(negative_cond_idx + 1, len(negative_seq) - 1) + positive_conditioning = positive_seq[positive_cond_idx] + negative_conditioning = negative_seq[negative_cond_idx] + if seed_keying: + if seed_keying_mode == 'sine': + seq_seed = seed if loop_count <= 0 else self.alternate_seed_sine(loop_count, seed, seed_divisor) + else: + seq_seed = seed if loop_count <= 0 else self.alternate_seed_modulo(loop_count, seed, seed_divisor) + else: + seq_seed = seed if loop_count <= 0 else self.update_seed(seq_seed, seed_mode_seq) + seq_seed = seed if loop_count <= 0 else self.update_seed(seq_seed, seed_mode_seq) + print(f'Loop count: {loop_count}, Seed: {seq_seed}') + last_positive_conditioning = positive_conditioning if positive_conditioning else None + last_negative_conditioning = negative_conditioning if negative_conditioning else None + if use_conditioning_slerp and (last_positive_conditioning and last_negative_conditioning): + (a, b) = (last_positive_conditioning[0].clone(), positive_conditioning[0].clone()) + (na, nb) = (last_negative_conditioning[0].clone(), negative_conditioning[0].clone()) + (pa, pb) = (last_positive_conditioning[1]['pooled_output'].clone(), positive_conditioning[1]['pooled_output'].clone()) + (npa, npb) = (last_negative_conditioning[1]['pooled_output'].clone(), negative_conditioning[1]['pooled_output'].clone()) + pos_cond = slerp(cond_slerp_strength, a, b) + pos_pooled = slerp(cond_slerp_strength, pa, pb) + neg_cond = slerp(cond_slerp_strength, na, nb) + neg_pooled = slerp(cond_slerp_strength, npa, npb) + positive_conditioning = [pos_cond, {'pooled_output': pos_pooled}] + negative_conditioning = [neg_cond, {'pooled_output': neg_pooled}] + positive_conditioning = [positive_conditioning] + negative_conditioning = [negative_conditioning] + end_at_step = steps + if results and len(results) > 0: + latent_input = {'samples': results[-1]} + denoise = self.alternate_denoise(loop_count, sequence_loop_count, denoise_seq, denoise_max) if denoise_sine else denoise_seq + start_at_step = round((1 - denoise) * steps) + end_at_step = steps + else: + latent_input = latent_image + denoise = denoise_start + if unsample_latents and loop_count > 0: + force_full_denoise = not (loop_count > 0 or loop_count <= steps - 1) + disable_noise = False + if seed_keying: + if seed_keying_mode == 'modulo' and loop_count % seed_divisor == 0: + unsampled_latent = latent_input + else: + unsampled_latent = unsample(model=model, seed=seq_seed, cfg=cfg, sampler_name=sampler_name, steps=steps, end_at_step=end_at_step, scheduler=scheduler, normalize=False, positive=positive_conditioning, negative=negative_conditioning, latent_image=latent_input)[0] + else: + unsampled_latent = unsample(model=model, seed=seq_seed, cfg=cfg, sampler_name=sampler_name, steps=steps, end_at_step=end_at_step, scheduler=scheduler, normalize=False, positive=positive_conditioning, negative=negative_conditioning, latent_image=latent_input)[0] + if inject_noise and loop_count > 0: + print(f'Injecting noise at {noise_strength} strength.') + unsampled_latent['samples'] = self.inject_noise(unsampled_latent['samples'], noise_strength) + sample = nodes.common_ksampler(model, seq_seed, steps, cfg, sampler_name, scheduler, positive_conditioning, negative_conditioning, unsampled_latent, denoise=denoise, disable_noise=disable_noise, start_step=start_at_step, last_step=end_at_step, force_full_denoise=force_full_denoise)[0]['samples'] + else: + if inject_noise and loop_count > 0: + print(f'Injecting noise at {noise_strength} strength.') + latent_input['samples'] = self.inject_noise(latent_input['samples'], noise_strength) + sample = nodes.common_ksampler(model, seq_seed, steps, cfg, sampler_name, scheduler, positive_conditioning, negative_conditioning, latent_input, denoise=denoise)[0]['samples'] + if use_latent_interpolation and results and (loop_count > 0): + if latent_interpolation_mode == 'Blend': + sample = blend_latents(latent_interp_strength, results[-1], sample) + elif latent_interpolation_mode == 'Slerp': + sample = slerp_latents(latent_interp_strength, results[-1], sample) + elif latent_interpolation_mode == 'Cosine Interp': + sample = cosine_interp_latents(latent_interp_strength, results[-1], sample) + results.append(sample) + results = torch.cat(results, dim=0) + results = {'samples': results} + return (results,) +``` \ No newline at end of file diff --git a/docs/KSamplerVariationsStochastic+.md b/docs/KSamplerVariationsStochastic+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/KSamplerVariationsWithNoise+.md b/docs/KSamplerVariationsWithNoise+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/KfAddCurveToPGroup.md b/docs/KfAddCurveToPGroup.md new file mode 100644 index 0000000..3e33ea5 --- /dev/null +++ b/docs/KfAddCurveToPGroup.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: KfAddCurveToPGroup +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点将曲线集成到参数组中,便于在项目中管理和组织关键帧曲线。它通过允许无缝添加曲线来增强工作流程,确保它们成为结构化组的一部分,以便更容易访问和操作。 + +# Input types +## Required +- curve + - 曲线参数是必不可少的,因为它定义了要添加到参数组的特定曲线。它是主要的输入参数,决定了哪些曲线的数据和属性将在组内进行管理。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.Curve +## Optional +- parameter_group + - 参数组作为曲线的容器,允许对多个参数进行集体管理。其存在或不存在会影响节点操作中数据的结构和组织。 + - Comfy dtype: PARAMETER_GROUP + - Python dtype: kf.ParameterGroup + +# Output types +- parameter_group + - 输出的参数组现在因添加了曲线而得到增强,成为一个更全面的参数管理实体。它很重要,因为它代表了节点操作的成果,封装了有组织的数据处理以供进一步使用。 + - Comfy dtype: PARAMETER_GROUP + - Python dtype: kf.ParameterGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfAddCurveToPGroup: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('PARAMETER_GROUP',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve': ('KEYFRAMED_CURVE', {'forceInput': True})}, 'optional': {'parameter_group': ('PARAMETER_GROUP', {'forceInput': True})}} + + def main(self, curve, parameter_group=None): + curve = deepcopy(curve) + if parameter_group is None: + parameter_group = kf.ParameterGroup([curve]) + else: + parameter_group = deepcopy(parameter_group) + parameter_group.parameters[curve.label] = curve + return (parameter_group,) +``` \ No newline at end of file diff --git a/docs/KfAddCurveToPGroupx10.md b/docs/KfAddCurveToPGroupx10.md new file mode 100644 index 0000000..f74b39b --- /dev/null +++ b/docs/KfAddCurveToPGroupx10.md @@ -0,0 +1,85 @@ +# Documentation +- Class name: KfAddCurveToPGroupx10 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点将多条曲线集成到一个参数组中,简化了项目中关键帧曲线的管理和应用。它强调数据的整合,以提高效率和工作流程。 + +# Input types +## Required +- curve0 + - 初始曲线至关重要,因为它为参数组设定了基础。它的包含是强制性的,直接影响节点的运作和输出。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve +- parameter_group + - 参数组作为曲线的容器,在组织和构建节点工作流程中的数据结构中起着关键作用。 + - Comfy dtype: PARAMETER_GROUP + - Python dtype: kf.ParameterGroup +## Optional +- curve1 + - 像curve1这样的附加曲线增加了参数组的复杂性和多功能性,允许处理和操作更丰富的数据集。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve +- curve2 + - 进一步合并曲线,如curve2,有助于节点处理多样化和复杂的数据,提高了整体功能。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve +- curve3 + - 像curve3这样的可选曲线为参数组提供了额外的维度,使节点能够有效管理更复杂的数据结构。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve +- curve4 + - curve4的包含进一步扩展了参数组的能力,允许对正在处理的数据进行更细致的控制。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve +- curve5 + - curve5增加了参数组整合多种数据的能力,提高了节点对各种数据输入的适应性。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve +- curve6 + - 通过包含curve6,节点获得了管理更加复杂数据集的能力,有助于参数组的整体健壮性。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve +- curve7 + - curve7是另一个可选曲线,包含后可以进一步丰富参数组并增强节点的数据处理能力。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve +- curve8 + - curve8的添加使节点能够处理更广泛的数据范围,提高了参数组的多功能性。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve +- curve9 + - 包含最后一个可选曲线curve9,使节点能够处理最复杂的数据集,最大化参数组的全面性。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve + +# Output types +- parameter_group + - 输出参数组是所有输入曲线的集合,代表了一个统一和结构化的数据集,可以在工作流程的下游被利用。 + - Comfy dtype: PARAMETER_GROUP + - Python dtype: kf.ParameterGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfAddCurveToPGroupx10: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('PARAMETER_GROUP',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve0': ('KEYFRAMED_CURVE', {'forceInput': True})}, 'optional': {'parameter_group': ('PARAMETER_GROUP', {'forceInput': True}), 'curve1': ('KEYFRAMED_CURVE', {'forceInput': True}), 'curve2': ('KEYFRAMED_CURVE', {'forceInput': True}), 'curve3': ('KEYFRAMED_CURVE', {'forceInput': True}), 'curve4': ('KEYFRAMED_CURVE', {'forceInput': True}), 'curve5': ('KEYFRAMED_CURVE', {'forceInput': True}), 'curve6': ('KEYFRAMED_CURVE', {'forceInput': True}), 'curve7': ('KEYFRAMED_CURVE', {'forceInput': True}), 'curve8': ('KEYFRAMED_CURVE', {'forceInput': True}), 'curve9': ('KEYFRAMED_CURVE', {'forceInput': True})}} + + def main(self, parameter_group=None, **kwargs): + if parameter_group is None: + parameter_group = kf.ParameterGroup(kwargs) + else: + parameter_group = deepcopy(parameter_group) + for curve in parameter_group.values(): + parameter_group.parameters[curve.label] = curve + return (parameter_group,) +``` \ No newline at end of file diff --git a/docs/KfApplyCurveToCond.md b/docs/KfApplyCurveToCond.md new file mode 100644 index 0000000..99b80eb --- /dev/null +++ b/docs/KfApplyCurveToCond.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: KfApplyCurveToCond +- Category: CONDITIONING +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点根据指定的曲线动态调整条件数据的强度,允许在生成过程中对条件变量的影响进行细微控制。 + +# Input types +## Required +- curve + - 曲线输入是一系列值,将用于调节条件数据,代表随时间或其他变量对条件强度进行的期望调整。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: List[float] +- cond + - 将由曲线输入调整的条件数据,通常包括张量及其关联的元数据,为生成过程提供上下文。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict]] +## Optional +- latents + - 可选的潜在数据,可用于进一步细化曲线应用于条件数据,增强节点对不同用例的适应性。 + - Comfy dtype: LATENT + - Python dtype: Dict +- start_t + - 要应用的曲线的起始索引,可用于控制影响条件数据的曲线片段。 + - Comfy dtype: INT + - Python dtype: int +- n + - 要生成的样本数量,如果提供潜在数据,则可以从中推断,它决定了应用于条件数据的曲线片段的长度。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- cond_out + - 输出是修改后的条件数据,其强度已根据输入曲线进行了调整,从而在生成过程中提供了更定制化的影响。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfApplyCurveToCond: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('CONDITIONING',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve': ('KEYFRAMED_CURVE', {'forceInput': True}), 'cond': ('CONDITIONING', {'forceInput': True})}, 'optional': {'latents': ('LATENT', {}), 'start_t': ('INT', {'default': 0}), 'n': ('INT', {})}} + + def main(self, curve, cond, latents=None, start_t=0, n=0): + curve = deepcopy(curve) + cond = deepcopy(cond) + if isinstance(latents, dict): + if 'samples' in latents: + n = latents['samples'].shape[0] + cond_out = [] + for (c_tensor, c_dict) in cond: + m = c_tensor.shape[0] + if c_tensor.shape[0] == 1: + c_tensor = c_tensor.repeat(n, 1, 1) + m = n + weights = [curve[start_t + i] for i in range(m)] + weights = torch.tensor(weights, device=c_tensor.device) + c_tensor = c_tensor * weights.view(m, 1, 1) + if 'pooled_output' in c_dict: + c_dict = deepcopy(c_dict) + pooled = c_dict['pooled_output'] + if pooled.shape[0] == 1: + pooled = pooled.repeat(m, 1) + c_dict['pooled_output'] = pooled * weights.view(m, 1) + cond_out.append((c_tensor, c_dict)) + return (cond_out,) +``` \ No newline at end of file diff --git a/docs/KfConditioningAdd.md b/docs/KfConditioningAdd.md new file mode 100644 index 0000000..c35f54b --- /dev/null +++ b/docs/KfConditioningAdd.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: KfConditioningAdd +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点用于将两个调节输入相加以产生一个综合的调节输出。它强调数据的整合以增强整体调节影响,同时不改变各自的数据结构。 + +# Input types +## Required +- conditioning_1 + - 第一个调节输入对于节点的操作至关重要,提供了将与第二个输入结合的初始数据集。它为整合过程奠定了基础。 + - Comfy dtype: CONDITIONING + - Python dtype: Tuple[torch.Tensor, Dict[str, Any]] +- conditioning_2 + - 第二个调节输入补充了第一个输入,允许将另一个数据集添加到混合中。这对于实现全面的调节结果至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Tuple[torch.Tensor, Dict[str, Any]] + +# Output types +- CONDITIONING + - 输出是两个输入相加后的综合调节集。它代表了可以进一步在过程中利用的增强调节影响。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, Any]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfConditioningAdd: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('CONDITIONING',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'conditioning_1': ('CONDITIONING',), 'conditioning_2': ('CONDITIONING',)}} + + def main(self, conditioning_1, conditioning_2): + conditioning_1 = deepcopy(conditioning_1) + conditioning_2 = deepcopy(conditioning_2) + assert len(conditioning_1) == len(conditioning_2) + outv = [] + for (i, ((c1_tensor, c1_dict), (c2_tensor, c2_dict))) in enumerate(zip(conditioning_1, conditioning_2)): + c1_tensor += c2_tensor + if 'pooled_output' in c1_dict and 'pooled_output' in c2_dict: + c1_dict['pooled_output'] += c2_dict['pooled_output'] + outv.append((c1_tensor, c1_dict)) + return (outv,) +``` \ No newline at end of file diff --git a/docs/KfConditioningAddx10.md b/docs/KfConditioningAddx10.md new file mode 100644 index 0000000..9c054d1 --- /dev/null +++ b/docs/KfConditioningAddx10.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: KfConditioningAddx10 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点累积处理条件输入,通过聚合提供的输入来增强整体的条件数据。 + +# Input types +## Required +- cond_0 + - 初始条件数据,对节点的操作至关重要。它为后续聚合设置了基线。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] +## Optional +- cond_1 + - 一个可选的条件输入,它对输出的累积效应有所贡献。它与基础条件数据合并。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] +- cond_2 + - 另一个额外的可选条件输入,进一步有助于节点操作的累积处理。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] +- cond_3 + - 另一个可选的条件输入,被整合到累积输出中,增强了节点的整体功能。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] +- cond_4 + - 这个可选的条件输入是累积数据流的一部分,影响节点的最终输出。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] +- cond_5 + - 这个条件输入进一步细化了累积数据,在节点的综合处理中发挥作用。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] +- cond_6 + - 一个可选输入,有助于节点的累积数据处理,影响输出的质量。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] +- cond_7 + - 这个可选条件输入被整合到累积数据中,进一步增强了节点的处理能力。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] +- cond_8 + - 这个条件输入有助于最终累积输出,影响节点的整体效果。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] +- cond_9 + - 一个额外的可选条件输入,是累积数据的一部分,影响节点的最终输出。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] + +# Output types +- cond_t_out + - 条件输入的累积结果,代表聚合和处理后的数据。 + - Comfy dtype: CONDITIONING + - Python dtype: Tuple[Any, Dict[str, Any]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfConditioningAddx10: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('CONDITIONING',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'cond_0': ('CONDITIONING', {'forceInput': True})}, 'optional': {'cond_1': ('CONDITIONING', {'forceInput': True, 'default': 0}), 'cond_2': ('CONDITIONING', {'forceInput': True, 'default': 0}), 'cond_3': ('CONDITIONING', {'forceInput': True, 'default': 0}), 'cond_4': ('CONDITIONING', {'forceInput': True, 'default': 0}), 'cond_5': ('CONDITIONING', {'forceInput': True, 'default': 0}), 'cond_6': ('CONDITIONING', {'forceInput': True, 'default': 0}), 'cond_7': ('CONDITIONING', {'forceInput': True, 'default': 0}), 'cond_8': ('CONDITIONING', {'forceInput': True, 'default': 0}), 'cond_9': ('CONDITIONING', {'forceInput': True, 'default': 0})}} + + def main(self, cond_0, **kwargs): + ((cond_t_out, cond_d_out),) = deepcopy(cond_0) + for ((cond_t, cond_d),) in kwargs.values(): + (cond_t, cond_d) = (deepcopy(cond_t), deepcopy(cond_d)) + cond_t_out = cond_t_out + cond_t + cond_d_out['pooled_output'] = cond_d_out['pooled_output'] + cond_d['pooled_output'] + return [((cond_t_out, cond_d_out),)] +``` \ No newline at end of file diff --git a/docs/KfCurveConstant.md b/docs/KfCurveConstant.md new file mode 100644 index 0000000..9861b6f --- /dev/null +++ b/docs/KfCurveConstant.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: KfCurveConstant +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfCurveConstant节点旨在在关键帧框架中生成一个常数曲线。它封装了一个作为输入提供的单一值,并且将其表示为一个随时间没有变化的常数曲线。该节点在创建动态系统中的稳定状态或固定点非常有用,其中在一段时间内需要一个恒定的值。 + +# Input types +## Required +- value + - ‘value’参数至关重要,因为它定义了曲线的常数值。它是节点的唯一输入,并直接影响输出,确保曲线在其持续时间内保持不变。这个参数对于在模拟中建立稳态至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- curve + - 输出‘curve’在关键帧框架中代表一个常数曲线。它基于输入值生成,然后用于创建一个随时间不波动的曲线。这个输出很重要,因为它提供了系统中常数状态的视觉和计算表示。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfCurveConstant: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'value': ('FLOAT', {'forceInput': True})}} + + def main(self, value): + curve = kf.Curve(value) + return (curve,) +``` \ No newline at end of file diff --git a/docs/KfCurveDraw.md b/docs/KfCurveDraw.md new file mode 100644 index 0000000..958fe42 --- /dev/null +++ b/docs/KfCurveDraw.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: KfCurveDraw +- Category: experimental +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点通过绘制给定曲线并生成其图像表示来对其进行可视化。它旨在抽象地表示曲线数据点内的趋势和波动,为理解曲线随时间的行为提供视觉分析工具。 + +# Input types +## Required +- curve + - 曲线参数对于节点的运行至关重要,因为它定义了将要可视化的数据集。它包含关键帧,这些关键帧代表特定时间点,每个关键帧都有一个相应的值。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +## Optional +- n + - 该参数决定了曲线上绘制的点数,这会影响可视化的粒度。它确保曲线得到充分的表示以供分析。 + - Comfy dtype: INT + - Python dtype: int +- show_legend + - 启用此参数时,会在图表中添加图例,为每条曲线提供参考,增强可视化的清晰度。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- img_tensor + - 输出是一个代表绘制曲线的图像张量。它作为数据的视觉摘要,允许进行简单的解释和进一步的处理。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfCurveDraw: + CATEGORY = f'{CATEGORY}/experimental' + FUNCTION = 'main' + RETURN_TYPES = ('IMAGE',) + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'curve': ('KEYFRAMED_CURVE', {'forceInput': True}), 'n': ('INT', {'default': 64}), 'show_legend': ('BOOLEAN', {'default': True})}} + + def main(self, curve, n, show_legend): + img_tensor = plot_curve(curve, n, show_legend, is_pgroup=False) + return (img_tensor,) +``` \ No newline at end of file diff --git a/docs/KfCurveFromString.md b/docs/KfCurveFromString.md new file mode 100644 index 0000000..c2dc1a1 --- /dev/null +++ b/docs/KfCurveFromString.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: KfCurveFromString +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点旨在将数学曲线的字符串表示解释并转换为可用于进一步处理的格式。它封装了解析Chigozie字符串的逻辑,这是一种描述关键帧曲线的紧凑方式,并输出一个可用于可视化或在各种数学和图形应用程序中使用的曲线对象。 + +# Input types +## Required +- chigozie_string + - 输入参数是一个使用Chigozie表示法定义曲线的字符串,对于节点生成相应的曲线对象至关重要。它直接影响输出曲线的形状和特征。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- curve + - 输出是一个曲线对象,代表由输入字符串定义的数学曲线。它是节点操作的主要结果,可以用于渲染、分析或在基于关键帧的工作流程中进一步处理。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.Curve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfCurveFromString: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'chigozie_string': ('STRING', {'multiline': True, 'default': '0:(1)'})}} + + def main(self, chigozie_string): + curve = curve_from_cn_string(chigozie_string) + return (curve,) +``` \ No newline at end of file diff --git a/docs/KfCurveFromYAML.md b/docs/KfCurveFromYAML.md new file mode 100644 index 0000000..234da03 --- /dev/null +++ b/docs/KfCurveFromYAML.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: KfCurveFromYAML +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点旨在解析YAML格式的字符串以生成关键帧曲线,这在动画和模拟工作流中是必不可少的组件。它通过允许用户通过基于文本的格式定义复杂的运动路径,简化了创建过程,便于使用并增强了设计过程的模块化。 + +# Input types +## Required +- yaml + - ‘yaml’参数是一个包含曲线的YAML格式描述的字符串。它至关重要,因为它直接定义了将要生成的曲线的结构和特征。该参数对节点的运行至关重要,规定了曲线中使用的关键帧和插值方法。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- curve + - 输出‘curve’是一个数据结构,代表由输入YAML定义的关键帧曲线。它封装了带有关键帧、插值和其他属性的运动路径,成为动画或模拟流程中后续操作的基本元素。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfCurveFromYAML: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'yaml': ('STRING', {'multiline': True, 'default': 'curve:\n- - 0\n - 0\n - linear\n- - 1\n - 1\nloop: false\nbounce: false\nduration: 1\nlabel: foo'})}} + + def main(self, yaml): + curve = kf.serialization.from_yaml(yaml) + return (curve,) +``` \ No newline at end of file diff --git a/docs/KfCurvesAdd.md b/docs/KfCurvesAdd.md new file mode 100644 index 0000000..90afdb2 --- /dev/null +++ b/docs/KfCurvesAdd.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: KfCurvesAdd +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfCurvesAdd节点旨在将两个关键帧曲线合并为一个复合曲线。当合并曲线对于创建复杂动画或数据表示至关重要时,该节点在工作流程中扮演着关键角色。它通过接收两个输入曲线并将它们无缝集成,以产生一个统一的输出曲线,从而增强了动画或图形过程的整体功能和多样性。 + +# Input types +## Required +- curve_1 + - 要合并的第一个关键帧曲线是KfCurvesAdd节点的基本输入。它对于形成最终复合曲线至关重要,直接影响动画或图形表示的结果。节点严重依赖此曲线的结构和属性以有效执行其功能。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_2 + - 第二个关键帧曲线与第一个曲线一样,是节点的必需输入。它对合并曲线的过程至关重要,显著影响最终复合曲线的形状和特性。节点结合使用这个曲线和第一个曲线以实现所需的动画或图形效果。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Output types +- combined_curve + - KfCurvesAdd节点的输出是一个关键帧曲线,代表两个输入曲线的总和。这个输出很重要,因为它包含了输入曲线的组合效果,为进一步在动画或数据可视化流程中使用提供了一个单一、连贯的曲线。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfCurvesAdd: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve_1': ('KEYFRAMED_CURVE', {'forceInput': True}), 'curve_2': ('KEYFRAMED_CURVE', {'forceInput': True})}} + + def main(self, curve_1, curve_2): + curve_1 = deepcopy(curve_1) + curve_2 = deepcopy(curve_2) + return (curve_1 + curve_2,) +``` \ No newline at end of file diff --git a/docs/KfCurvesAddx10.md b/docs/KfCurvesAddx10.md new file mode 100644 index 0000000..ba2bbbf --- /dev/null +++ b/docs/KfCurvesAddx10.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: KfCurvesAddx10 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点旨在聚合多个输入曲线,通过将它们的值相加以增强数据的整体表示。它作为通过求和来简化关键帧曲线的分析和可视化的工具。 + +# Input types +## Required +- curve_0 + - 初始曲线输入是至关重要的,因为它为后续其他曲线的加法设置了基线。它的出现是强制性的,并且直接影响节点操作的结果。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +## Optional +- curve_1 + - 额外的曲线输入对于节点的功能是不可或缺的,它们有助于累积效果的增加。它们增强了最终输出的全面性。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_2 + - 更多的曲线输入在聚合过程中起着重要作用,影响最终的总和以及节点在综合数据方面的有效性。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_3 + - 后续的曲线输入对于节点实现全面的聚合至关重要,影响合成数据的深度和广度。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_4 + - 包含更多的曲线输入丰富了节点聚合和处理数据的能力,有助于形成更加细腻的最终输出。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_5 + - 额外的曲线输入对于增强节点综合更广泛数据范围的能力至关重要,有助于更全面地理解聚合信息。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_6 + - 将更多的曲线输入纳入节点操作允许更详细和复杂的聚合,丰富了数据的最终表示。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_7 + - 额外曲线输入的存在增强了节点的功能,使其能够处理并整合更广泛的数据点到最终总和中。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_8 + - 通过包括更多的曲线输入,节点可以有效聚合多样化的数据集,这对于实现对组合曲线的整体视图至关重要。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_9 + - 最后的曲线输入为聚合过程添加了最后一层数据,确保节点的输出是所有组合曲线的全面表示。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Output types +- curve_out + - 输出代表所有输入曲线的总和,提供了聚合数据的全面和综合视图。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfCurvesAddx10: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve_0': ('KEYFRAMED_CURVE', {'forceInput': True})}, 'optional': {'curve_1': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 0}), 'curve_2': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 0}), 'curve_3': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 0}), 'curve_4': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 0}), 'curve_5': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 0}), 'curve_6': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 0}), 'curve_7': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 0}), 'curve_8': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 0}), 'curve_9': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 0})}} + + def main(self, curve_0=0, curve_1=0, curve_2=0, curve_3=0, curve_4=0, curve_5=0, curve_6=0, curve_7=0, curve_8=0, curve_9=0): + curve_out = curve_0 + curve_1 + curve_2 + curve_3 + curve_4 + curve_5 + curve_6 + curve_7 + curve_8 + curve_9 + return (curve_out,) +``` \ No newline at end of file diff --git a/docs/KfCurvesDivide.md b/docs/KfCurvesDivide.md new file mode 100644 index 0000000..b187a8d --- /dev/null +++ b/docs/KfCurvesDivide.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: KfCurvesDivide +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点执行两条曲线的除法操作,提供了分析它们之间关系的手段。对于需要曲线数据标准化或比较的操作至关重要,提供了一种直接的方法来获得包含除法结果的新曲线。 + +# Input types +## Required +- curve_1 + - 第一条曲线是定义除法操作中一个操作数的基本输入。它的值对确定除法结果的outcome至关重要,因为它们直接影响结果曲线的形状和特征。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_2 + - 第二条曲线是另一个重要的输入,它在除法操作中作为除数。它的重要性在于它会影响结果曲线相对于第一条曲线的缩放。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Output types +- result_curve + - 节点的输出是一条新曲线,代表第一条输入曲线除以第二条曲线的结果。这条结果曲线很重要,因为它包含了两条原始曲线之间的归一化关系。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfCurvesDivide: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve_1': ('KEYFRAMED_CURVE', {'forceInput': True}), 'curve_2': ('KEYFRAMED_CURVE', {'forceInput': True})}} + + def main(self, curve_1, curve_2): + curve_1 = deepcopy(curve_1) + curve_2 = deepcopy(curve_2) + return (curve_1 / curve_2,) +``` \ No newline at end of file diff --git a/docs/KfCurvesMultiply.md b/docs/KfCurvesMultiply.md new file mode 100644 index 0000000..8240278 --- /dev/null +++ b/docs/KfCurvesMultiply.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: KfCurvesMultiply +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfCurvesMultiply节点旨在对两个给定的关键帧曲线进行逐元素的乘法运算,有效地结合它们在相应关键帧的各自值。此操作对于以非线性方式调整和操作动画曲线的强度或幅度至关重要,增强了在动画和模拟过程中的创造性控制。 + +# Input types +## Required +- curve_1 + - 第一个关键帧曲线输入至关重要,因为它定义了将与第二个曲线相乘的初始关键帧及其相关值。此参数对于建立将被第二个曲线修改的基线动画或效果至关重要。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_2 + - 第二个关键帧曲线输入作为第一个曲线的乘数,允许调整由第一个曲线定义的动画或效果。此参数对于以受控方式改变动画的动态或应用复杂效果至关重要。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Output types +- result + - KfCurvesMultiply节点的输出是一个新的关键帧曲线,代表了两个输入曲线的逐元素乘积。这个结果曲线可以用于进一步细化动画或在动画序列中引入新的复杂性和细节水平。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfCurvesMultiply: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve_1': ('KEYFRAMED_CURVE', {'forceInput': True}), 'curve_2': ('KEYFRAMED_CURVE', {'forceInput': True})}} + + def main(self, curve_1, curve_2): + curve_1 = deepcopy(curve_1) + curve_2 = deepcopy(curve_2) + return (curve_1 * curve_2,) +``` \ No newline at end of file diff --git a/docs/KfCurvesMultiplyx10.md b/docs/KfCurvesMultiplyx10.md new file mode 100644 index 0000000..e094655 --- /dev/null +++ b/docs/KfCurvesMultiplyx10.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: KfCurvesMultiplyx10 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点便于对多个曲线进行乘法运算,增强了对关键帧数据进行操作和组合以实现复杂动画或模拟的能力。它旨在简化缩放和整合各种曲线输入的过程,从而实现创建复杂的运动序列。 + +# Input types +## Required +- curve_0 + - 主要的曲线输入对于乘法过程至关重要,它作为其他曲线将要因子的基础。它的存在确保了节点可以启动复杂的操作。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +## Optional +- curve_1 + - 后续的曲线输入作为乘数,有助于增强主曲线的整体缩放效果。每条曲线都丰富了最终输出的复杂性和细节。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_2 + - 额外的曲线输入进一步完善了缩放过程,允许对生成的运动序列进行细致的控制。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_3 + - 包含更多曲线输入增加了节点的多功能性,使得通过组合多个曲线值能够实现广泛的效果。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_4 + - 更多的曲线输入提供了细粒度的控制,允许根据每条曲线的特定特征对最终输出进行复杂的操作。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_5 + - 结合额外的曲线可以在最终动画中实现更复杂的细节水平,因为每条曲线都贡献了独特的缩放因子。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_6 + - 更多曲线的乘法提供了更高的精度和定制化程度,在生成的运动序列中。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_7 + - 通过包含更多的曲线输入,节点可以生成高度复杂和细腻的动画,满足特定的创意需求。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_8 + - 进一步整合曲线增强了节点生成复杂和详细动画的能力,响应高级运动设计的需求。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_9 + - 最后一组曲线输入使节点具有在最终动画中实现卓越细节和精度的能力,推动可能性的界限。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Output types +- curve_out + - 输出代表了所有输入曲线乘法的累积结果,提供了一个单一的、统一的曲线,封装了组合效果。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfCurvesMultiplyx10: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve_0': ('KEYFRAMED_CURVE', {'forceInput': True})}, 'optional': {'curve_1': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 1}), 'curve_2': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 1}), 'curve_3': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 1}), 'curve_4': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 1}), 'curve_5': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 1}), 'curve_6': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 1}), 'curve_7': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 1}), 'curve_8': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 1}), 'curve_9': ('KEYFRAMED_CURVE', {'forceInput': True, 'default': 1})}} + + def main(self, curve_0, curve_1, curve_2, curve_3, curve_4, curve_5, curve_6, curve_7, curve_8, curve_9): + curve_out = curve_0 * curve_1 * curve_2 * curve_3 * curve_4 * curve_5 * curve_6 * curve_7 * curve_8 * curve_9 + return (curve_out,) +``` \ No newline at end of file diff --git a/docs/KfCurvesSubtract.md b/docs/KfCurvesSubtract.md new file mode 100644 index 0000000..b550c63 --- /dev/null +++ b/docs/KfCurvesSubtract.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: KfCurvesSubtract +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点实现了从一个曲线中减去另一个曲线的功能,通过结合关键帧操作和数学运算,在动画和数据可视化领域中实现期望的结果。 + +# Input types +## Required +- curve_1 + - 第一条曲线输入是至关重要的,因为它为减法操作设定了基线。它是整个过程的中心,因为它决定了操作后结果曲线的形式和结构。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +- curve_2 + - 第二条曲线作为要从第一条曲线中减去的元素。它的角色至关重要,因为它直接影响减法的最终结果,决定了结果曲线的形状和特征。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Output types +- result_curve + - 输出代表减法操作的结果,将两条输入曲线的精髓结合成一条单一的、精炼的曲线,反映了原始两条曲线之间的差异。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfCurvesSubtract: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve_1': ('KEYFRAMED_CURVE', {'forceInput': True}), 'curve_2': ('KEYFRAMED_CURVE', {'forceInput': True})}} + + def main(self, curve_1, curve_2): + curve_1 = deepcopy(curve_1) + curve_2 = deepcopy(curve_2) + return (curve_1 - curve_2,) +``` \ No newline at end of file diff --git a/docs/KfDebug_Clip.md b/docs/KfDebug_Clip.md new file mode 100644 index 0000000..63b6823 --- /dev/null +++ b/docs/KfDebug_Clip.md @@ -0,0 +1,29 @@ +# Documentation +- Class name: KfDebug_Clip +- Category: Debugging +- Output node: True +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点便于检查和验证处理流程中的数据,特别关注CLIP数据的完整性和结构。它的设计目的是提供对数据流的洞察,并确保正在处理的信息满足所需的标准和规格。 + +# Input types +## Required +- input + - 输入参数对于节点至关重要,因为它携带了需要调试和检查的数据。它直接影响节点的运行和调试输出的质量。 + - Comfy dtype: CLIP + - Python dtype: Any + +# Output types +- output + - 该节点的输出代表了调试过程的结果。它很重要,因为它提供了经过调试节点处理后数据状态的全面概述。 + - Comfy dtype: CLIP + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfDebug_Clip(KfDebug_Passthrough): + RETURN_TYPES = ('CLIP',) +``` \ No newline at end of file diff --git a/docs/KfDebug_Cond.md b/docs/KfDebug_Cond.md new file mode 100644 index 0000000..a9a9e13 --- /dev/null +++ b/docs/KfDebug_Cond.md @@ -0,0 +1,29 @@ +# Documentation +- Class name: KfDebug_Cond +- Category: debugging +- Output node: True +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfDebug_Cond 节点旨在提供一种可视化和理解关键帧模型中调节方面的方法。它对于调试非常有用,确保调节数据被正确处理,从而更明智地进行模型优化。 + +# Input types +## Required +- conditioning_data + - 调节数据(conditioning_data)对于 KfDebug_Cond 节点至关重要,因为它代表了用于调节模型输出的输入数据。正确处理该参数对于节点正常工作和调试过程的有效性至关重要。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Output types +- debug_info + - KfDebug_Cond 节点的 debug_info 输出包含了有关调节过程的宝贵信息。这些信息可以用来识别模型调节中的任何问题,从而促进调试和优化过程。 + - Comfy dtype: dict + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfDebug_Cond(KfDebug_Passthrough): + RETURN_TYPES = ('CONDITIONING',) +``` \ No newline at end of file diff --git a/docs/KfDebug_Curve.md b/docs/KfDebug_Curve.md new file mode 100644 index 0000000..f118405 --- /dev/null +++ b/docs/KfDebug_Curve.md @@ -0,0 +1,29 @@ +# Documentation +- Class name: KfDebug_Curve +- Category: debug +- Output node: True +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点旨在可视化和分析关键帧路径的曲率,清晰地表示动画中的平滑度和连续性。它有助于理解轨迹并确保运动符合预期,这对于保持最终输出中期望的审美和流畅性至关重要。 + +# Input types +## Required +- curve_data + - 该参数保存表示待调试曲线的数值数据。它至关重要,因为它构成了可视化和分析的基础,使节点能够有效处理和显示曲线的特征。 + - Comfy dtype: numpy.ndarray + - Python dtype: numpy.ndarray + +# Output types +- visualized_curve + - 输出是输入曲线的视觉表示,对于快速识别任何不规则或改进区域至关重要。它提供了一种有形的方式来评估曲线的性能并进行必要的调整。 + - Comfy dtype: PIL.Image + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfDebug_Curve(KfDebug_Passthrough): + RETURN_TYPES = ('KEYFRAMED_CURVE',) +``` \ No newline at end of file diff --git a/docs/KfDebug_Float.md b/docs/KfDebug_Float.md new file mode 100644 index 0000000..0327e79 --- /dev/null +++ b/docs/KfDebug_Float.md @@ -0,0 +1,29 @@ +# Documentation +- Class name: KfDebug_Float +- Category: Debugging +- Output node: True +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfDebug_Float 节点旨在通过提供一种检查和分析数据处理流水线中浮点数的方法来促进调试过程。它是开发人员验证计算各个阶段数值数据的完整性和行为的关键工具。 + +# Input types +## Required +- input_float + - input_float 参数对于节点的操作至关重要,因为它表示需要调试的浮点数。它在节点的执行中起着核心作用,是主要的待检查和分析的数据。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output_float + - output_float 参数非常重要,因为它代表了由节点处理过的已调试的浮点数。它对于下游流程至关重要,因为它确保了数据流的连续性和可靠性。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfDebug_Float(KfDebug_Passthrough): + RETURN_TYPES = ('FLOAT',) +``` \ No newline at end of file diff --git a/docs/KfDebug_Image.md b/docs/KfDebug_Image.md new file mode 100644 index 0000000..c0b4580 --- /dev/null +++ b/docs/KfDebug_Image.md @@ -0,0 +1,29 @@ +# Documentation +- Class name: KfDebug_Image +- Category: Debugging +- Output node: True +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfDebug_Image节点旨在工作流中便于图像数据的可视化,提供在处理的不同阶段检查和验证图像输入或输出的手段。它通过提供清晰的图像视觉表示,增强了调试过程,确保图像数据被正确处理并满足预期标准。 + +# Input types +## Required +- image + - 图像参数对于KfDebug_Image节点至关重要,因为它是节点可视化的主要输入。它通过允许节点显示图像以供检查,确保图像数据符合预期,并帮助识别任何潜在的问题或差异,影响整个调试过程。 + - Comfy dtype: COMBO[numpy.ndarray,PIL.Image,torch.Tensor] + - Python dtype: Union[numpy.ndarray, PIL.Image, torch.Tensor] + +# Output types +- image + - KfDebug_Image节点的输出图像作为输入图像状态的视觉确认。它非常重要,因为它提供了一种在工作流中传递图像数据后验证图像数据的完整性和准确性的手段,确保没有发生更改或损坏。 + - Comfy dtype: IMAGE + - Python dtype: Union[numpy.ndarray, PIL.Image] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfDebug_Image(KfDebug_Passthrough): + RETURN_TYPES = ('IMAGE',) +``` \ No newline at end of file diff --git a/docs/KfDebug_Int.md b/docs/KfDebug_Int.md new file mode 100644 index 0000000..c74106a --- /dev/null +++ b/docs/KfDebug_Int.md @@ -0,0 +1,29 @@ +# Documentation +- Class name: KfDebug_Int +- Category: Debug +- Output node: True +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfDebug_Int节点旨在方便用户在计算图中检查和分析整数值。它使用户能够监控和理解整数数据的流动,确保模型中涉及整数的操作的正确性。该节点通过提供对整数处理和转换的清晰、专注的视图来帮助调试,避免了其他数据类型的复杂性。 + +# Input types +## Required +- input + - 输入参数是将整数值输入到KfDebug_Int节点的关键元素。它对节点的功能至关重要,因为它允许节点监控和分析整数值。输入在决定节点的输出及其在调试过程中提供的洞察中起着关键作用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - KfDebug_Int节点的输出是经过检查和分析的加工整数值。它作为节点操作的确认以及计算图中整数值的完整性的证明。输出非常重要,因为它为进一步的调试或验证模型的性能提供了基础。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfDebug_Int(KfDebug_Passthrough): + RETURN_TYPES = ('INT',) +``` \ No newline at end of file diff --git a/docs/KfDebug_Latent.md b/docs/KfDebug_Latent.md new file mode 100644 index 0000000..a5339d5 --- /dev/null +++ b/docs/KfDebug_Latent.md @@ -0,0 +1,29 @@ +# Documentation +- Class name: KfDebug_Latent +- Category: debugging +- Output node: True +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfDebug_Latent 节点旨在提供对基于关键帧模型生成的潜在空间表示的洞察。它作为诊断工具,允许检查和分析潜在特征,这对于理解模型数据处理能力的潜在结构和质量至关重要。 + +# Input types +## Required +- input_data + - input_data 参数是输入到节点的原始数据,预期是以 PyTorch 张量的形式。它至关重要,因为它构成了节点进行潜在空间分析的基础。input_data 的质量和结构直接影响节点生成有意义的潜在表示的能力。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Output types +- latent_representation + - latent_representation 输出提供了节点分析得出的处理后的潜在空间数据。它很重要,因为它包含了从 input_data 中提取的信息,提供了潜在特征的浓缩视图。这个输出对于进一步研究或可视化模型的潜在空间非常有用。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfDebug_Latent(KfDebug_Passthrough): + RETURN_TYPES = ('LATENT',) +``` \ No newline at end of file diff --git a/docs/KfDebug_Model.md b/docs/KfDebug_Model.md new file mode 100644 index 0000000..abe59c5 --- /dev/null +++ b/docs/KfDebug_Model.md @@ -0,0 +1,33 @@ +# Documentation +- Class name: KfDebug_Model +- Category: Debugging +- Output node: True +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点便于检查和分析模型的内部状态和输出,提供了一种理解和调试模型在推理过程中行为的手段。 + +# Input types +## Required +- input_data + - 输入数据非常关键,它代表了模型处理的样本或样本批次。它直接影响模型的输出和从调试中获得的洞察。 + - Comfy dtype: COMBO[numpy.ndarray, torch.Tensor] + - Python dtype: Union[numpy.ndarray, torch.Tensor] +- model + - 模型参数至关重要,它定义了正在被调试行为的神经网络结构。模型的配置和参数决定了调试过程。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module + +# Output types +- debug_info + - 调试信息很重要,因为它提供了模型内部工作的详细概览,有助于识别潜在问题和改进领域。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class KfDebug_Model(KfDebug_Passthrough): + RETURN_TYPES = ('MODEL',) +``` \ No newline at end of file diff --git a/docs/KfDebug_Segs.md b/docs/KfDebug_Segs.md new file mode 100644 index 0000000..3b7e9d9 --- /dev/null +++ b/docs/KfDebug_Segs.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: KfDebug_Segs +- Category: Debugging +- Output node: True +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点在深学习框架内便于可视化和分析分割结果,使用户能够检查和理解模型在区分图像不同部分方面的性能。 + +# Input types +## Required +- image + - 输入的图像或数组对节点的运行至关重要,因为它是分割的基础。输入的质量和分辨率直接影响分割结果的准确性和细节。 + - Comfy dtype: COMBO["Image", "ndarray"] + - Python dtype: Image or torch.Tensor +## Optional +- mask + - 提供掩码参数有助于通过指定图像中的兴趣区域来细化分割过程。它增强了节点专注于特定段的能力,从而改善了整体的分割结果。 + - Comfy dtype: ndarray + - Python dtype: numpy.ndarray + +# Output types +- segmented_image + - 输出代表分割过程的结果,输入图像的不同部分被识别和区分。这对于进一步分析和理解模型的性能至关重要。 + - Comfy dtype: Image + - Python dtype: PIL.Image +- segmentation_map + - 该输出提供了分割的详细地图,指示了图像中每个段的边界和分类。这对于评估分割算法的精度和有效性至关重要。 + - Comfy dtype: ndarray + - Python dtype: numpy.ndarray + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfDebug_Segs(KfDebug_Passthrough): + RETURN_TYPES = ('SEGS',) +``` \ No newline at end of file diff --git a/docs/KfDebug_String.md b/docs/KfDebug_String.md new file mode 100644 index 0000000..037f8e6 --- /dev/null +++ b/docs/KfDebug_String.md @@ -0,0 +1,29 @@ +# Documentation +- Class name: KfDebug_String +- Category: Debugging +- Output node: True +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点旨在工作流中促进对字符串数据的检查和分析。它使用户能够在不同阶段查看和验证字符串的内容和结构,确保正在处理的文本信息的准确性和完整性。 + +# Input types +## Required +- input_string + - input_string参数对于这个节点至关重要,因为它携带了需要检查的文本数据。它是一个关键组件,因为节点的主要功能围绕分析和显示这个字符串的内容。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- output_string + - output_string代表节点操作的结果,通常与input_string相同,但根据调试过程可能会被修改或注释。它很重要,因为它提供了最终检查的文本数据。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfDebug_String(KfDebug_Passthrough): + RETURN_TYPES = ('STRING',) +``` \ No newline at end of file diff --git a/docs/KfDebug_Vae.md b/docs/KfDebug_Vae.md new file mode 100644 index 0000000..c40e361 --- /dev/null +++ b/docs/KfDebug_Vae.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: KfDebug_Vae +- Category: Debugging +- Output node: True +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点便于分析和可视化变分自编码器(VAE)模型的性能和行为,提供对生成过程和潜在空间结构的洞察。 + +# Input types +## Required +- image + - 输入图像对于节点处理和分析数据至关重要,使得能够可视化VAE的重构和生成能力。 + - Comfy dtype: Image + - Python dtype: PIL.Image.Image +## Optional +- latent_codes + - 此参数允许用户输入特定的潜在代码来探索和操作VAE生成的图像,提供对模型潜在空间更深入的理解。 + - Comfy dtype: Tensor + - Python dtype: torch.Tensor + +# Output types +- reconstructed_images + - 输出显示VAE重构的图像,提供与原始输入的直接比较和对模型性能的评估。 + - Comfy dtype: Image + - Python dtype: PIL.Image.Image +- generated_images + - 这些图像代表了节点从学习到的潜在空间生成新数据点的能力,展示了VAE的生成能力。 + - Comfy dtype: Image + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: GPU + +# Source code +``` +class KfDebug_Vae(KfDebug_Passthrough): + RETURN_TYPES = ('VAE',) +``` \ No newline at end of file diff --git a/docs/KfDrawSchedule.md b/docs/KfDrawSchedule.md new file mode 100644 index 0000000..7ceab0e --- /dev/null +++ b/docs/KfDrawSchedule.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: KfDrawSchedule +- Category: RootCategory +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点旨在可视化在keyframed中定义的调度计划,将复杂的调度过程抽象为易于理解的图形表示。它将调度计划转换为一系列权重曲线,每条曲线对应一个关键帧的贡献,便于分析和理解调度动态。 + +# Input types +## Required +- schedule + - 调度参数至关重要,因为它定义了将要由节点可视化的keyframed曲线及其相关参数。它是生成权重曲线和结果图的主要输入。 + - Comfy dtype: SCHEDULE + - Python dtype: kf.Keyframed +## Optional +- n + - 参数'n'对于确定图形的分辨率非常重要。它影响曲线采样的点数,这可能会影响可视化的清晰度和细节。 + - Comfy dtype: INT + - Python dtype: int +- show_legend + - 参数'show_legend'控制是否在图上显示图例。这有助于区分不同的权重曲线,并理解它们对整个调度的各自贡献。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- img_tensor + - 输出的img_tensor代表了输入调度的可视化图形,作为绘图的结果。它封装了权重曲线及其动态,提供了调度过程的清晰且简洁的图形摘要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfDrawSchedule: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('IMAGE',) + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'schedule': ('SCHEDULE', {'forceInput': True}), 'n': ('INT', {'default': 64}), 'show_legend': ('BOOLEAN', {'default': True})}} + + def main(self, schedule, n, show_legend): + curves = schedule_to_weight_curves(schedule) + img_tensor = plot_curve(curves, n, show_legend, is_pgroup=True) + return (img_tensor,) +``` \ No newline at end of file diff --git a/docs/KfEvaluateCurveAtT.md b/docs/KfEvaluateCurveAtT.md new file mode 100644 index 0000000..38b00ad --- /dev/null +++ b/docs/KfEvaluateCurveAtT.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: KfEvaluateCurveAtT +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfEvaluateCurveAtT节点旨在评估并检索特定时间't'处的关键帧曲线的值。它通过接受一个关键帧曲线和一个时间参数来操作,并返回给定时间点曲线值的浮点数和整数表示,全面洞察该时刻曲线的状态。 + +# Input types +## Required +- curve + - ‘curve’参数至关重要,因为它定义了节点将评估的关键帧曲线。它是直接影响节点输出的关键组件,通过确定在指定时间 't' 要分析的曲线的形状和值。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve +- t + - ‘t’参数指定了要评估曲线值的时间。虽然它有一个默认值0,但在确定节点的确切输出时至关重要,因为它指示了沿曲线提取值的确切位置。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- curve_value_float + - 在时间 't' 处曲线值的浮点表示是节点的关键输出。它捕获了指定时间曲线的精确连续性质,提供了对曲线行为的详细洞察。 + - Comfy dtype: FLOAT + - Python dtype: float +- curve_value_int + - 在时间 't' 处曲线值的整数表示提供了曲线值的离散化版本。在需要或更倾向于使用整数的上下文中,如某些类型的数据分析或可视化,此输出可能特别有用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfEvaluateCurveAtT: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('FLOAT', 'INT') + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve': ('KEYFRAMED_CURVE', {'forceInput': True}), 't': ('INT', {'default': 0})}} + + def main(self, curve, t): + return (curve[t], int(curve[t])) +``` \ No newline at end of file diff --git a/docs/KfGetCurveFromPGroup.md b/docs/KfGetCurveFromPGroup.md new file mode 100644 index 0000000..13a6c84 --- /dev/null +++ b/docs/KfGetCurveFromPGroup.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: KfGetCurveFromPGroup +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点有助于从参数组中提取特定的曲线,使用户能够隔离和分析复杂数据集中的单个数据趋势。 + +# Input types +## Required +- curve_label + - 要提取的曲线的标识符,对于精确定位要分析的确切数据趋势至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- parameter_group + - 形成数据集的参数集合,从中将提取曲线,在整体数据分析过程中起着至关重要的作用。 + - Comfy dtype: PARAMETER_GROUP + - Python dtype: kf.ParameterGroup + +# Output types +- curve + - 提取的曲线代表了隔离的数据趋势,提供了对较大数据集中特定模式的清晰和专注的视图。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.Curve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfGetCurveFromPGroup: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve_label': ('STRING', {'default': 'My Curve'}), 'parameter_group': ('PARAMETER_GROUP', {'forceInput': True})}} + + def main(self, curve_label, parameter_group): + curve = parameter_group.parameters[curve_label] + return (deepcopy(curve),) +``` \ No newline at end of file diff --git a/docs/KfGetScheduleConditionAtTime.md b/docs/KfGetScheduleConditionAtTime.md new file mode 100644 index 0000000..7a76211 --- /dev/null +++ b/docs/KfGetScheduleConditionAtTime.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: KfGetScheduleConditionAtTime +- Category: RootCategory +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点旨在从给定时间点的调度中提取和处理条件数据,提供了一种无缝分析和利用该时刻调度状态的方法。 + +# Input types +## Required +- schedule + - 调度参数至关重要,因为它包含了节点确定指定时间条件状态所需的结构化数据和配置。它是驱动节点操作的主要输入。 + - Comfy dtype: SCHEDULE + - Python dtype: dict +- time + - 时间参数是必不可少的,它指示节点需要评估调度的具体时间。它通过确定将提取和处理哪组条件直接影响输出。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- CONDITIONING + - 输出提供了一组详细的条件数据,反映了指定时间调度的状态。它是进一步分析和决策过程中的关键信息。 + - Comfy dtype: CONDITIONING + - Python dtype: tuple + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfGetScheduleConditionAtTime: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('CONDITIONING',) + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'schedule': ('SCHEDULE', {}), 'time': ('FLOAT', {})}} + + def main(self, schedule, time): + lerped_cond = evaluate_schedule_at_time(schedule, time) + return (lerped_cond,) +``` \ No newline at end of file diff --git a/docs/KfGetScheduleConditionSlice.md b/docs/KfGetScheduleConditionSlice.md new file mode 100644 index 0000000..bd73ab2 --- /dev/null +++ b/docs/KfGetScheduleConditionSlice.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: KfGetScheduleConditionSlice +- Category: RootCategory +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点旨在从给定的时间表中提取和处理指定时间间隔的条件数据。它通过将时间表分割成一系列时间片,评估每个时间片的条件,汇总结果以提供所指定时间跨度内条件的全面概述。 + +# Input types +## Required +- schedule + - 时间表参数至关重要,因为它包含了随时间定义条件的结构化数据。它是主要的输入参数,决定了节点的运作和输出的质量。 + - Comfy dtype: SCHEDULE + - Python dtype: dict +## Optional +- start + - 开始参数指定了节点处理时间表的时间间隔的开始。它很重要,因为它设置了时间切片操作的起点。 + - Comfy dtype: FLOAT + - Python dtype: float +- step + - 步长参数定义了每个时间片之间的间隔。它很重要,因为它影响了提取的条件数据的粒度。 + - Comfy dtype: FLOAT + - Python dtype: float +- n + - n参数决定了时间表被划分成多少个时间片。它很关键,因为它决定了节点执行的单独评估次数。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- CONDITIONING + - 输出提供了在指定时间间隔从时间表中提取的条件的详细和结构化表示。它很重要,因为它包含了节点操作的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: list + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfGetScheduleConditionSlice: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('CONDITIONING',) + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'schedule': ('SCHEDULE', {}), 'start': ('FLOAT', {'default': 0}), 'step': ('FLOAT', {'default': 1}), 'n': ('INT', {'default': 24})}} + + def main(self, schedule, start, step, n): + stop = start + n * step + times = np.linspace(start=start, stop=stop, num=n, endpoint=True) + conds = [evaluate_schedule_at_time(schedule, time)[0] for time in times] + lerped_tokenized = [c[0] for c in conds] + lerped_pooled = [c[1]['pooled_output'] for c in conds] + lerped_tokenized_t = torch.cat(lerped_tokenized, dim=0) + out_dict = deepcopy(conds[0][1]) + if isinstance(lerped_pooled[0], torch.Tensor) and isinstance(lerped_pooled[-1], torch.Tensor): + out_dict['pooled_output'] = torch.cat(lerped_pooled, dim=0) + return [[(lerped_tokenized_t, out_dict)]] +``` \ No newline at end of file diff --git a/docs/KfKeyframedCondition.md b/docs/KfKeyframedCondition.md new file mode 100644 index 0000000..b65a3b0 --- /dev/null +++ b/docs/KfKeyframedCondition.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: KfKeyframedCondition +- Category: RootCategory +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfKeyframedCondition节点旨在将条件元素整合到关键帧结构中,允许在不同时间点对数据进行操作和转换。它在序列中条件的动态调整中发挥关键作用,确保状态之间平滑且连贯的过渡。 + +# Input types +## Required +- conditioning + - conditioning参数对于定义将在特定关键帧应用的初始状态或条件至关重要。它为后续的转换和插值设定了基础,影响序列的整体行为。 + - Comfy dtype: CONDITIONING + - Python dtype: Tuple[torch.Tensor, Dict[str, torch.Tensor]] +## Optional +- time + - time参数指定了序列中将附加条件的时间位置。它对于确定条件的顺序及其对系统演变状态的影响至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- interpolation_method + - 插值方法决定了条件在关键帧之间如何过渡。它对于创建条件的自然流动非常重要,并且可以极大地影响序列的最终输出。 + - Comfy dtype: COMBO[linear, easeIn, easeOut, easeInOut] + - Python dtype: str + +# Output types +- kf_cond_t + - kf_cond_t输出代表了指定时间的关键帧条件,包含了转换后的条件及其插值方法。它是序列中的关键组成部分,指导系统状态的进展。 + - Comfy dtype: KEYFRAMED_CONDITION + - Python dtype: kf.Keyframe +- kf_cond_pooled + - 当存在kf_cond_pooled输出时,它提供了在指定时间应用的额外条件层。它为系统演变状态的复杂性和细微差别做出了贡献。 + - Comfy dtype: KEYFRAMED_CONDITION + - Python dtype: Optional[kf.Keyframe] +- cond_dict + - cond_dict输出是一个包含条件详细信息的字典,包括任何池化输出。它作为指定时间条件状态的参考,便于进一步的分析和处理。 + - Comfy dtype: Dict[str, torch.Tensor] + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfKeyframedCondition: + """ + Attaches a condition to a keyframe + """ + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CONDITION',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'conditioning': ('CONDITIONING', {}), 'time': ('FLOAT', {'default': 0, 'step': 1}), 'interpolation_method': (list(kf.interpolation.EASINGS.keys()), {'default': 'linear'})}} + + def main(self, conditioning, time, interpolation_method): + (cond_tensor, cond_dict) = conditioning[0] + cond_tensor = cond_tensor.clone() + kf_cond_t = kf.Keyframe(t=time, value=cond_tensor, interpolation_method=interpolation_method) + cond_pooled = cond_dict.get('pooled_output') + cond_dict = deepcopy(cond_dict) + kf_cond_pooled = None + if cond_pooled is not None: + cond_pooled = cond_pooled.clone() + kf_cond_pooled = kf.Keyframe(t=time, value=cond_pooled, interpolation_method=interpolation_method) + cond_dict['pooled_output'] = cond_pooled + return ({'kf_cond_t': kf_cond_t, 'kf_cond_pooled': kf_cond_pooled, 'cond_dict': cond_dict},) +``` \ No newline at end of file diff --git a/docs/KfKeyframedConditionWithText.md b/docs/KfKeyframedConditionWithText.md new file mode 100644 index 0000000..69a4774 --- /dev/null +++ b/docs/KfKeyframedConditionWithText.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: KfKeyframedConditionWithText +- Category: RootCategory +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点将文本信息集成到基于关键帧的框架中,根据文本输入实现对关键帧条件的动态调整和细化。 + +# Input types +## Required +- clip + - 输入的剪辑是必需的,因为它作为关键帧条件的基础。根据文本输入对其进行操作,以创建定制的视觉表示。 + - Comfy dtype: CLIP + - Python dtype: kf.Clip +- text + - 文本参数对节点至关重要,因为它提供了关键帧条件的内容和上下文。它用于生成影响最终视觉输出的标记。 + - Comfy dtype: STRING + - Python dtype: str +- time + - 时间参数非常重要,因为它决定了关键帧在序列中的时间位置。它影响关键帧动画的整体节奏和结构。 + - Comfy dtype: FLOAT + - Python dtype: float +- interpolation_method + - 插值方法很重要,因为它决定了关键帧之间的过渡风格。它影响动画的平滑度和视觉连续性。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- schedule + - 当使用计划参数时,它允许随时间自动调整关键帧。它可以简化创建复杂动画的过程。 + - Comfy dtype: SCHEDULE + - Python dtype: dict + +# Output types +- keyframed_condition + - 输出提供了关键帧条件的结构化表示,这对动画的视觉叙事至关重要。它封装了文本输入和时间放置的联合效应。 + - Comfy dtype: KEYFRAMED_CONDITION + - Python dtype: dict +- conditioning + - 此输出包含文本输入的编码表示,并用于影响关键帧条件。它是节点操作中的一个关键中间步骤。 + - Comfy dtype: CONDITIONING + - Python dtype: list +- schedule + - 计划输出是自动化关键帧调整的结构化计划。它对于创建随时间适应的动态和响应性动画非常重要。 + - Comfy dtype: SCHEDULE + - Python dtype: tuple + +# Usage tips +- Infra type: GPU + +# Source code +``` +class KfKeyframedConditionWithText(KfKeyframedCondition): + """ + Attaches a condition to a keyframe + """ + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CONDITION', 'CONDITIONING', 'SCHEDULE') + + @classmethod + def INPUT_TYPES(s): + return {'required': {'clip': ('CLIP',), 'text': ('STRING', {'multiline': True, 'default': ''}), 'time': ('FLOAT', {'default': 0, 'step': 1}), 'interpolation_method': (list(kf.interpolation.EASINGS.keys()), {'default': 'linear'})}, 'optional': {'schedule': ('SCHEDULE', {})}} + + def main(self, clip, text, time, interpolation_method, schedule=None): + tokens = clip.tokenize(text) + (cond, pooled) = clip.encode_from_tokens(tokens, return_pooled=True) + conditioning = [[cond, {'pooled_output': pooled}]] + keyframed_condition = super().main(conditioning, time, interpolation_method)[0] + keyframed_condition['kf_cond_t'].label = text + schedule = set_keyframed_condition(keyframed_condition, schedule) + return (keyframed_condition, conditioning, schedule) +``` \ No newline at end of file diff --git a/docs/KfPGroupCurveAdd.md b/docs/KfPGroupCurveAdd.md new file mode 100644 index 0000000..56f731f --- /dev/null +++ b/docs/KfPGroupCurveAdd.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: KfPGroupCurveAdd +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点便于将曲线整合入参数组中,增强了数据模型的整体结构和功能。它旨在简化将关键帧动画元素与参数设置结合的过程,从而提高系统内数据操作的效率。 + +# Input types +## Required +- parameter_group + - 参数组是必要的,因为它构成了曲线整合的基础。它是影响节点整体行为和输出的关键组件,决定了曲线操作的结构上下文。 + - Comfy dtype: PARAMETER_GROUP + - Python dtype: Dict[str, Any] +- curve + - 曲线输入对于向参数组引入动态变化至关重要。它携带将与静态参数合并的动画数据,从而为最终结果增加复杂性和流畅性。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve + +# Output types +- result + - 结果参数组和曲线的合并输出,标志着成功的整合。它代表了节点操作的结晶,封装了两个输入的组合属性和行为。 + - Comfy dtype: PARAMETER_GROUP + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfPGroupCurveAdd: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('PARAMETER_GROUP',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'parameter_group': ('PARAMETER_GROUP', {'forceInput': True}), 'curve': ('KEYFRAMED_CURVE', {'forceInput': True})}} + + def main(self, parameter_group, curve): + parameter_group = deepcopy(parameter_group) + curve = deepcopy(curve) + return (parameter_group + curve,) +``` \ No newline at end of file diff --git a/docs/KfPGroupCurveMultiply.md b/docs/KfPGroupCurveMultiply.md new file mode 100644 index 0000000..1ab6731 --- /dev/null +++ b/docs/KfPGroupCurveMultiply.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: KfPGroupCurveMultiply +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点实现了将一组参数与曲线相乘,根据关键帧数据动态调整随时间变化的参数值。 + +# Input types +## Required +- parameter_group + - 参数组,其值将与曲线相乘。这对于定义节点将要调整的参数集至关重要。 + - Comfy dtype: PARAMETER_GROUP + - Python dtype: Dict[str, Any] +- curve + - 曲线定义了参数组在不同时间点的乘法因子。它对于控制动态调整至关重要。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.Curve + +# Output types +- result + - 输出是修改后的参数组,其值根据曲线乘法进行了调整。 + - Comfy dtype: PARAMETER_GROUP + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfPGroupCurveMultiply: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('PARAMETER_GROUP',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'parameter_group': ('PARAMETER_GROUP', {'forceInput': True}), 'curve': ('KEYFRAMED_CURVE', {'forceInput': True})}} + + def main(self, parameter_group, curve): + parameter_group = deepcopy(parameter_group) + curve = deepcopy(curve) + return (parameter_group * curve,) +``` \ No newline at end of file diff --git a/docs/KfPGroupDraw.md b/docs/KfPGroupDraw.md new file mode 100644 index 0000000..96b14fb --- /dev/null +++ b/docs/KfPGroupDraw.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: KfPGroupDraw +- Category: experimental +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点将一组参数组可视化为曲线图,使得能够分析参数随时间或其他变量的变化。它的设计目的是提供参数演变的图形表示,这对于理解所建模系统的动态至关重要。 + +# Input types +## Required +- parameter_group + - 此参数保存了一系列参数组的集合,其动态将被可视化。它是至关重要的,因为它构成了节点操作的基础,决定了绘制的数据以及可视化如何表示系统的行为。 + - Comfy dtype: PARAMETER_GROUP + - Python dtype: Dict[str, Any] +## Optional +- n + - 此参数指定评估曲线的点数。它影响图表的分辨率,较高的值可以导致参数演变的更平滑表示。 + - Comfy dtype: INT + - Python dtype: int +- show_legend + - 此参数控制图表中是否显示图例。当可视化多个参数组时,它对于识别不同的曲线很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- img_tensor + - 输出是一个表示曲线图图像的张量,它提供了在指定范围内参数演变的视觉摘要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfPGroupDraw: + CATEGORY = f'{CATEGORY}/experimental' + FUNCTION = 'main' + RETURN_TYPES = ('IMAGE',) + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'parameter_group': ('PARAMETER_GROUP', {'forceInput': True}), 'n': ('INT', {'default': 64}), 'show_legend': ('BOOLEAN', {'default': True})}} + + def main(self, parameter_group, n, show_legend): + img_tensor = plot_curve(parameter_group, n, show_legend, is_pgroup=True) + return (img_tensor,) +``` \ No newline at end of file diff --git a/docs/KfPGroupSum.md b/docs/KfPGroupSum.md new file mode 100644 index 0000000..1acbbb0 --- /dev/null +++ b/docs/KfPGroupSum.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: KfPGroupSum +- Category: keyframed/experimental +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfPGroupSum节点旨在将关键帧曲线聚合成单个复合曲线。它通过将给定参数组关联的各个曲线相加来操作,从而生成一个统一的表示,该表示包含了输入曲线的集体行为。 + +# Input types +## Required +- parameter_group + - 参数组是KfPGroupSum节点的关键输入,因为它包含要相加的关键帧曲线集。此输入通过确定哪些曲线贡献给最终复合曲线,直接影响输出曲线。 + - Comfy dtype: PARAMETER_GROUP + - Python dtype: Dict[str, kf.Curve] + +# Output types +- composite_curve + - KfPGroupSum节点的输出是一个复合的关键帧曲线,它是参数组中所有输入曲线的总和。这条曲线很重要,因为它提供了输入曲线所代表的组合运动或效果的简化视图。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.Curve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfPGroupSum: + CATEGORY = 'keyframed/experimental' + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'parameter_group': ('PARAMETER_GROUP', {'forceInput': True})}} + + def main(self, parameter_group): + parameter_group = deepcopy(parameter_group) + outv = kf.Curve(0) + for curve in parameter_group.parameters.values(): + outv += curve + return (outv,) +``` \ No newline at end of file diff --git a/docs/KfSetCurveLabel.md b/docs/KfSetCurveLabel.md new file mode 100644 index 0000000..db3998c --- /dev/null +++ b/docs/KfSetCurveLabel.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: KfSetCurveLabel +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点允许为曲线分配一个描述性标签,增强了数据可视化或分析上下文中曲线的可追溯性和可解释性。 + +# Input types +## Required +- curve + - 曲线参数是必需的,因为它代表了将要分配标签的数据结构,确保曲线可以在系统中被识别和引用。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve +## Optional +- label + - 标签参数作为曲线的文本标识符,有助于在较大的数据集或工作流中组织和检索特定的曲线。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- curve + - 输出的曲线现在包含了分配的标签,提供了更全面的数据表示,便于进一步的分析或展示。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.Curve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSetCurveLabel: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve': ('KEYFRAMED_CURVE', {'forceInput': True}), 'label': ('STRING', {'multiline': False, 'default': '~curve~'})}} + + def main(self, curve, label): + curve = deepcopy(curve) + curve.label = label + return (curve,) +``` \ No newline at end of file diff --git a/docs/KfSetKeyframe.md b/docs/KfSetKeyframe.md new file mode 100644 index 0000000..7228738 --- /dev/null +++ b/docs/KfSetKeyframe.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: KfSetKeyframe +- Category: RootCategory +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点旨在管理和修改计划中的键帧条件,允许对模型训练过程中的参数进行动态调整。 + +# Input types +## Required +- keyframed_condition + - 该参数至关重要,因为它定义了设置键帧的条件,这些条件对于控制在特定间隔处模型的行为至关重要。 + - Comfy dtype: KEYFRAMED_CONDITION + - Python dtype: Dict[str, Any] +## Optional +- schedule + - 计划参数对于定义模型更新的时机和频率很重要,结合键帧条件,它可以优化训练过程。 + - Comfy dtype: SCHEDULE + - Python dtype: Optional[kf.ParameterGroup] + +# Output types +- schedule + - 输出是一个包含更新的键帧条件的修改后的计划,这对于指导模型的进展和性能至关重要。 + - Comfy dtype: SCHEDULE + - Python dtype: Tuple[kf.ParameterGroup, Dict[str, Any]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSetKeyframe: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('SCHEDULE',) + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'keyframed_condition': ('KEYFRAMED_CONDITION', {})}, 'optional': {'schedule': ('SCHEDULE', {})}} + + def main(self, keyframed_condition, schedule=None): + schedule = set_keyframed_condition(keyframed_condition, schedule) + return (schedule,) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalAdjustAmplitude.md b/docs/KfSinusoidalAdjustAmplitude.md new file mode 100644 index 0000000..bff1de2 --- /dev/null +++ b/docs/KfSinusoidalAdjustAmplitude.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: KfSinusoidalAdjustAmplitude +- Category: ROOT_CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点旨在调整正弦曲线的振幅,允许对形状进行微调,而不会改变其基本属性,如波长和相位。它强调节点在为各种应用微调曲线动态中的作用。 + +# Input types +## Required +- curve + - 曲线参数是必要的,因为它定义了要调整振幅的基础正弦曲线。它直接影响输出,决定了修改后的曲线的形状和特征。 + - Comfy dtype: SINUSOIDAL_CURVE + - Python dtype: kf.SinusoidalCurve +## Optional +- adjustment + - 调整参数用于修改正弦曲线的振幅,允许对曲线的峰值和谷值进行精确控制。它在根据特定要求定制曲线方面起着至关重要的作用。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- curve + - 输出曲线是修改后的正弦曲线,具有调整后的振幅,代表了节点操作的结果。它很重要,因为它传达了可以用于进一步处理或分析的最终形状。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve +- sinusoidal_curve + - 这个输出与修改后的曲线相同,强调节点的主要功能是在保留曲线其他属性的同时调整振幅。它对于需要最终正弦形状的应用非常有用。 + - Comfy dtype: SINUSOIDAL_CURVE + - Python dtype: kf.SinusoidalCurve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalAdjustAmplitude: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE', 'SINUSOIDAL_CURVE') + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve': ('SINUSOIDAL_CURVE', {'forceInput': True}), 'adjustment': ('FLOAT', {'default': 0, 'step': 0.01})}} + + def main(self, curve, adjustment): + (wavelength, phase, amplitude) = (curve.wavelength, curve.phase, curve.amplitude) + amplitude += adjustment + curve = kf.SinusoidalCurve(wavelength=wavelength, phase=phase, amplitude=amplitude) + return (curve, curve) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalAdjustFrequency.md b/docs/KfSinusoidalAdjustFrequency.md new file mode 100644 index 0000000..ef35cca --- /dev/null +++ b/docs/KfSinusoidalAdjustFrequency.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: KfSinusoidalAdjustFrequency +- Category: ROOT_CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点允许对正弦曲线的频率进行微调,提供对振荡速度的控制,而不会改变波形的整体形状。 + +# Input types +## Required +- curve + - 输入曲线参数是必不可少的,因为它定义了将要调整频率的基础正弦曲线。 + - Comfy dtype: SINUSOIDAL_CURVE + - Python dtype: kf.SinusoidalCurve +## Optional +- adjustment + - 调整参数用于通过指定的值修改曲线的频率,影响整体的振荡速度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- curve + - 输出是调整后的正弦曲线,反映了基于输入参数的频率变化。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.SinusoidalCurve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalAdjustFrequency: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE', 'SINUSOIDAL_CURVE') + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve': ('SINUSOIDAL_CURVE', {'forceInput': True}), 'adjustment': ('FLOAT', {'default': 0, 'step': 0.01})}} + + def main(self, curve, adjustment): + (wavelength, phase, amplitude) = (curve.wavelength, curve.phase, curve.amplitude) + frequency = 1 / wavelength + frequency += adjustment + wavelength = 1 / frequency + curve = kf.SinusoidalCurve(wavelength=wavelength, phase=phase, amplitude=amplitude) + return (curve, curve) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalAdjustPhase.md b/docs/KfSinusoidalAdjustPhase.md new file mode 100644 index 0000000..44317b8 --- /dev/null +++ b/docs/KfSinusoidalAdjustPhase.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: KfSinusoidalAdjustPhase +- Category: ROOT_CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点旨在修改正弦曲线的相位,允许对波的时机进行调整,而不会改变其基本特征,如波长和振幅。 + +# Input types +## Required +- curve + - 输入曲线参数是必要的,因为它定义了将要被节点操作调整相位的基础正弦曲线。 + - Comfy dtype: SINUSOIDAL_CURVE + - Python dtype: kf.SinusoidalCurve +## Optional +- adjustment + - 调整参数是一个浮点值,它影响应用于输入曲线的相位移位的程度,影响波的时机。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- curve + - 输出代表相位已调整的修改后的正弦曲线,它可以在需要动态波调整的各种应用中进一步使用。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve +- sinusoidal_curve + - 这个输出与修改后的正弦曲线相同,为下游过程提供了相位调整波的一致表示。 + - Comfy dtype: SINUSOIDAL_CURVE + - Python dtype: kf.SinusoidalCurve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalAdjustPhase: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE', 'SINUSOIDAL_CURVE') + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve': ('SINUSOIDAL_CURVE', {'forceInput': True}), 'adjustment': ('FLOAT', {'default': 0.0, 'step': 0.1308996939})}} + + def main(self, curve, adjustment): + (wavelength, phase, amplitude) = (curve.wavelength, curve.phase, curve.amplitude) + phase += adjustment + curve = kf.SinusoidalCurve(wavelength=wavelength, phase=phase, amplitude=amplitude) + return (curve, curve) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalAdjustWavelength.md b/docs/KfSinusoidalAdjustWavelength.md new file mode 100644 index 0000000..4d37cfb --- /dev/null +++ b/docs/KfSinusoidalAdjustWavelength.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: KfSinusoidalAdjustWavelength +- Category: ROOT_CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +此类节点提供了一种调整正弦曲线波长的方法,有效地改变了其周期,而不影响相位或振幅等其他特性。调整以一种保持曲线整体形状的方式应用,确保平滑连续的变换,适用于需要微调曲线时间特性的各种应用场景。 + +# Input types +## Required +- curve + - 输入曲线参数是必要的,它定义了要调整波长的基正弦曲线。该参数直接影响到节点处理的输入,决定了在进行任何调整之前曲线的起始特性。 + - Comfy dtype: SINUSOIDAL_CURVE + - Python dtype: kf.SinusoidalCurve +## Optional +- adjustment + - 调整参数作为波长调整的乘数,允许精确控制应用于曲线的变化程度。它在微调正弦曲线的时间特性方面起着至关重要的作用。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- curve + - 输出代表调整后的正弦曲线,反映了节点处理的结果。它很重要,因为它提供了可以用于后续操作或可视化的更新曲线。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: kf.KeyframedCurve +- sinusoidal_curve + - 此输出与'curve'输出相同,提供了进一步使用的调整后的正弦曲线。它确保用户能够访问到以其新形式的修改曲线,适合集成到各种工作流程中。 + - Comfy dtype: SINUSOIDAL_CURVE + - Python dtype: kf.SinusoidalCurve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalAdjustWavelength: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE', 'SINUSOIDAL_CURVE') + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve': ('SINUSOIDAL_CURVE', {'forceInput': True}), 'adjustment': ('FLOAT', {'default': 0.0, 'step': 0.5})}} + + def main(self, curve, adjustment): + (wavelength, phase, amplitude) = (curve.wavelength, curve.phase, curve.amplitude) + wavelength += adjustment + curve = kf.SinusoidalCurve(wavelength=wavelength, phase=phase, amplitude=amplitude) + return (curve, curve) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromFrequencyx2.md b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx2.md new file mode 100644 index 0000000..300fb87 --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx2.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromFrequencyx2 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点基于提供的频率生成一对纠缠的正弦曲线,这些曲线从零过渡到一再回到零。它强调创建表现出特定周期行为的平滑、周期性函数,对于需要振荡模式的各种应用非常有用。 + +# Input types +## Required +- frequency + - 频率参数决定了正弦曲线的周期性,影响了曲线振荡的速度以及峰值之间的距离。它对于定义生成曲线的整体节奏和速度非常关键。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- output + - 输出包含两个纠缠的关键帧正弦曲线,它们展示了从零到一的振荡模式。这些曲线是节点功能的核心,代表了处理的主要结果。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: List[kf.SinusoidalCurve] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromFrequencyx2(KfSinusoidalEntangledZeroOneFromFrequency): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 2 + + def main(self, frequency): + return super().main(n=2, frequency=frequency) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromFrequencyx3.md b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx3.md new file mode 100644 index 0000000..fb45b7f --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx3.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromFrequencyx3 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点基于给定的频率生成一组三个正弦曲线,这些曲线以零一模式交织在一起。它强调创建在零和一之间平滑过渡的周期性波形,重点是使用频率参数来控制曲线的周期性和整体形状。 + +# Input types +## Required +- frequency + - 频率参数决定了正弦曲线的周期性,影响波形峰谷的间距和重复。这对于定义生成曲线的节奏和韵律至关重要。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- output + - 输出是三个正弦曲线,每个曲线代表零一交织中的一个独特相位移动。这些曲线是节点功能的核心,作为处理的主要结果。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: List[kf.SinusoidalCurve] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromFrequencyx3(KfSinusoidalEntangledZeroOneFromFrequency): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 3 + + def main(self, frequency): + return super().main(n=3, frequency=frequency) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromFrequencyx4.md b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx4.md new file mode 100644 index 0000000..9c4009a --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx4.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromFrequencyx4 +- Category: core +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfSinusoidalEntangledZeroOneFromFrequencyx4节点旨在根据给定频率生成多个纠缠的正弦曲线。它通过创建四个不同的正弦曲线来操作,每个曲线都有从输入频率派生的独特相位偏移和振幅。该节点特别适用于需要生成复杂、相互关联波形的应用。 + +# Input types +## Required +- frequency + - 频率参数对于确定正弦曲线振荡的基本速率至关重要。它直接影响节点的输出,影响生成曲线的形状和周期性。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- KEYFRAMED_CURVE + - 节点的输出是一组四个关键帧正弦曲线。每条曲线代表一个独特的振荡模式,与其他曲线相互纠缠,形成一个复杂的波形结构。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: List[kf.SinusoidalCurve] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromFrequencyx4(KfSinusoidalEntangledZeroOneFromFrequency): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 4 + + def main(self, frequency): + return super().main(n=4, frequency=frequency) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromFrequencyx5.md b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx5.md new file mode 100644 index 0000000..932a048 --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx5.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromFrequencyx5 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点基于给定频率生成五组纠缠的正弦曲线,代表从零到一的复杂值模式。它强调为需要周期性、非线性变换的应用创建复杂的波形。 + +# Input types +## Required +- frequency + - 频率参数决定了正弦曲线的振荡速度,影响生成波形的整体节奏和周期性。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- output + - 输出包含五个正弦曲线,每个曲线代表将输入频率转换到零到一值范围的独特变换。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: List[kf.SinusoidalCurve] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromFrequencyx5(KfSinusoidalEntangledZeroOneFromFrequency): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 5 + + def main(self, frequency): + return super().main(n=5, frequency=frequency) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromFrequencyx6.md b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx6.md new file mode 100644 index 0000000..b7900c9 --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx6.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromFrequencyx6 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点基于提供的频率生成一组六个相互纠缠的正弦曲线,每个曲线在零和一之间振荡。它强调创建保持一致相位关系的相互关联波形,以促进复杂模式的生成和分析。 + +# Input types +## Required +- frequency + - 频率参数决定了正弦曲线的振荡速度,影响生成波形的整体节奏和周期性。它对于定义输出的时间特征至关重要。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- output + - 输出包含六个正弦曲线,每个曲线代表输入频率的一种独特的相位移位解释。这些曲线是节点功能的核心,为进一步分析或可视化提供了丰富的数据集。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: List[kf.SinusoidalCurve] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromFrequencyx6(KfSinusoidalEntangledZeroOneFromFrequency): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 6 + + def main(self, frequency): + return super().main(n=6, frequency=frequency) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromFrequencyx7.md b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx7.md new file mode 100644 index 0000000..e0e02f5 --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx7.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromFrequencyx7 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点根据输入的基本频率生成一组七个纠缠的正弦曲线,每个曲线在零和一之间振荡。它强调为信号处理或可视化中的各种应用创建复杂、同步的波形。 + +# Input types +## Required +- frequency + - 频率参数决定了正弦曲线的振荡速率,影响生成波形的整体模式和周期性。它对于定义输出的时间特性至关重要。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- output + - 输出包括七个正弦曲线,每个曲线根据输入频率表示一个独特的相位移动和振幅。这些曲线对节点的功能至关重要,为进一步分析或操作提供了丰富的数据点集。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: List[kf.SinusoidalCurve] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromFrequencyx7(KfSinusoidalEntangledZeroOneFromFrequency): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 7 + + def main(self, frequency): + return super().main(n=7, frequency=frequency) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromFrequencyx8.md b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx8.md new file mode 100644 index 0000000..628b04e --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx8.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromFrequencyx8 +- Category: math +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfSinusoidalEntangledZeroOneFromFrequencyx8节点根据给定的频率生成八个纠缠的正弦曲线。每条曲线都被设计为在零和一之间振荡,具有相位偏移以确保它们的纠缠。该节点的目的是创建一个复杂的振荡模式,可以用于需要同步但不同波形的各种应用。 + +# Input types +## Required +- frequency + - 频率参数决定了正弦曲线振荡的速率。它对于设置曲线的整体模式至关重要,并影响每个振荡的周期和振幅。频率越高,振荡就越快。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- KEYFRAMED_CURVE + - KfSinusoidalEntangledZeroOneFromFrequencyx8节点的输出是八个关键帧正弦曲线。每条曲线代表一个独特的振荡模式,与其他曲线纠缠,为进一步的操作或分析提供了丰富的波形集。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: List[kf.SinusoidalCurve] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromFrequencyx8(KfSinusoidalEntangledZeroOneFromFrequency): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 8 + + def main(self, frequency): + return super().main(n=8, frequency=frequency) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromFrequencyx9.md b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx9.md new file mode 100644 index 0000000..ee05c91 --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromFrequencyx9.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromFrequencyx9 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfSinusoidalEntangledZeroOneFromFrequencyx9节点旨在生成一组九个正弦曲线,这些曲线相互纠缠,在零和一之间振荡。它利用keyframed库创建平滑且连续的转换。该节点的目的是提供一个多功能工具,用于生成可以在各种应用中使用的复杂波形,例如动画、信号处理或任何需要正弦波模式的场景。 + +# Input types +## Required +- frequency + - 频率参数决定了正弦曲线振荡的速率。它是形成节点生成的波形整体行为的关键要素。频率的变化将直接影响振荡的周期性和速度。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- KEYFRAMED_CURVE + - KfSinusoidalEntangledZeroOneFromFrequencyx9节点的输出是九个关键帧正弦曲线的元组。每条曲线代表了纠缠波形内的一个独特振荡,作为整体复杂模式的一部分。这些曲线可以进一步操作或在下游流程中使用。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: Tuple[kf.SinusoidalCurve, ...] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromFrequencyx9(KfSinusoidalEntangledZeroOneFromFrequency): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 9 + + def main(self, frequency): + return super().main(n=9, frequency=frequency) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromWavelengthx2.md b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx2.md new file mode 100644 index 0000000..15ec9e7 --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx2.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromWavelengthx2 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点根据给定的波长生成一对纠缠的正弦曲线,旨在创建复杂且同步的模式。它强调波长与生成波形之间的相互作用,专注于生成曲线的和谐与节奏。 + +# Input types +## Required +- wavelength + - 波长参数决定了正弦曲线的周期,影响生成波形的整体模式和频率。它在确定输出的美学和功能质量方面至关重要。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- KEYFRAMED_CURVE + - 输出包含两个纠缠且同步的正弦曲线,丰富地展示了输入波长的属性。这些曲线可用于需要节奏性和周期性模式的各种应用中。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: List[kf.SinusoidalCurve] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromWavelengthx2(KfSinusoidalEntangledZeroOneFromWavelength): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 2 + + def main(self, wavelength): + return super().main(n=2, wavelength=wavelength) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromWavelengthx3.md b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx3.md new file mode 100644 index 0000000..548740f --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx3.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromWavelengthx3 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点基于输入的波长生成一组三个相互纠缠的正弦曲线,创建一个在零和一之间振荡的复杂模式。它旨在引入适合需要复杂波形的应用的高度周期性变化。 + +# Input types +## Required +- wavelength + - 波长参数决定了正弦曲线的周期,影响生成模式的整体复杂性和频率。这是一个关键输入,因为它直接影响曲线的空间特性。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- curves + - 输出包含三条正弦曲线,每条曲线都有其独特的相位和振幅,这些是从输入波长派生出来的。这些曲线是节点功能的核心,代表了处理的主要结果。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: List[kf.SinusoidalCurve] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromWavelengthx3(KfSinusoidalEntangledZeroOneFromWavelength): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 3 + + def main(self, wavelength): + return super().main(n=3, wavelength=wavelength) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromWavelengthx4.md b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx4.md new file mode 100644 index 0000000..9c77d9f --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx4.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromWavelengthx4 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点基于输入的波长生成一组四个正弦曲线,这些曲线相互纠缠,创造出在零和一之间振荡的模式。它旨在为需要周期性但复杂波形的各种应用生成复杂的波形。 + +# Input types +## Required +- wavelength + - 波长参数决定了正弦曲线的周期,影响生成波形的频率和整体形状。这是一个关键输入,因为它直接影响振荡的模式和规律性。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- output + - 输出包括四个纠缠的正弦曲线,每个曲线代表输入波长振荡模式的独特部分。这个输出非常重要,因为它为各种应用中的进一步分析或操作提供了基础。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: List[kf.SinusoidalCurve] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromWavelengthx4(KfSinusoidalEntangledZeroOneFromWavelength): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 4 + + def main(self, wavelength): + return super().main(n=4, wavelength=wavelength) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromWavelengthx5.md b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx5.md new file mode 100644 index 0000000..fe70c75 --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx5.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromWavelengthx5 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点基于提供的波长生成五组正弦波形的关键帧曲线,将零和一的值以有节奏的模式纠缠在一起。它强调创建周期性、振荡的数据结构,这些数据结构在指定的高低值之间平滑过渡。 + +# Input types +## Required +- wavelength + - 波长参数决定了正弦曲线的周期,影响了整体振荡模式和连续峰值之间的距离。它对于定义生成曲线的频率和重复性至关重要。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- curves + - 输出包括五条关键帧正弦曲线,每条曲线代表基于输入波长生成的正弦模式的独特部分。这些曲线对于节点的功能至关重要,提供了振荡的视觉和数值表示。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: List[kf.SinusoidalCurve] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromWavelengthx5(KfSinusoidalEntangledZeroOneFromWavelength): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 5 + + def main(self, wavelength): + return super().main(n=5, wavelength=wavelength) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromWavelengthx6.md b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx6.md new file mode 100644 index 0000000..f5b2424 --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx6.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromWavelengthx6 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点根据给定的波长生成一组六个具有不同相位差的纠缠正弦曲线。它强调创建在系统中过渡于零和一的复杂、和谐模式,便于分析振荡行为。 + +# Input types +## Required +- wavelength + - 波长参数决定了正弦曲线的周期,影响了生成模式的频率和整体结构。它在定义振荡特性和峰值之间的间隔方面至关重要。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- curves + - 输出包括六个正弦曲线,每个曲线代表振荡模式中的唯一相位。这些曲线对于理解节点对系统动态行为的贡献至关重要。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: List[kf.SinusoidalCurve] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromWavelengthx6(KfSinusoidalEntangledZeroOneFromWavelength): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 6 + + def main(self, wavelength): + return super().main(n=6, wavelength=wavelength) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromWavelengthx7.md b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx7.md new file mode 100644 index 0000000..e573e97 --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx7.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromWavelengthx7 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点根据输入的波长生成一组七个独特的正弦曲线,每个曲线的相位偏移用于表示从波长派生的二进制序列。它强调创建一个结构化模式,该模式基于波长参数调整频率,在零和一之间振荡。 + +# Input types +## Required +- wavelength + - 波长参数决定了正弦曲线的频率,影响生成序列的整体模式。它对节点的运行至关重要,因为它决定了二进制表示的粒度和周期性。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- KEYFRAMED_CURVE + - 输出是七个正弦曲线的集合,每个曲线代表二进制序列中的唯一相位。这些曲线的组合提供了基于输入波长的纠缠零一模式的视觉和数值表示。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: List[kf.SinusoidalCurve] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromWavelengthx7(KfSinusoidalEntangledZeroOneFromWavelength): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 7 + + def main(self, wavelength): + return super().main(n=7, wavelength=wavelength) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromWavelengthx8.md b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx8.md new file mode 100644 index 0000000..0e86a87 --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx8.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromWavelengthx8 +- Category: CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点根据给定的波长生成一组八个正弦曲线,每个曲线都有不同的相位偏移。主要目的是创建一个在指定波长内振荡的零和一值的纠缠模式,为生成各种应用的复杂波形提供便利。 + +# Input types +## Required +- wavelength + - 波长参数决定了正弦曲线一个完整周期的长度。它非常重要,因为它直接影响生成波形的频率和周期,从而影响曲线的整体模式和行为。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- output + - 输出包括八个正弦曲线,每个曲线在指定波长内代表一个独特的相位偏移。这些曲线对节点的功能至关重要,因为它们为下游过程中的进一步分析或操作提供了基础。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: List[kf.SinusoidalCurve] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromWavelengthx8(KfSinusoidalEntangledZeroOneFromWavelength): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 8 + + def main(self, wavelength): + return super().main(n=8, wavelength=wavelength) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalEntangledZeroOneFromWavelengthx9.md b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx9.md new file mode 100644 index 0000000..0f7b430 --- /dev/null +++ b/docs/KfSinusoidalEntangledZeroOneFromWavelengthx9.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: KfSinusoidalEntangledZeroOneFromWavelengthx9 +- Category: core +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfSinusoidalEntangledZeroOneFromWavelengthx9节点基于给定的波长生成一组九个正弦曲线,这些曲线相互纠缠,在零和一之间振荡。此节点特别适用于创建需要多个交织频率的复杂模式。 + +# Input types +## Required +- wavelength + - 波长参数决定了正弦波振荡的周期,对于设置生成曲线的频率至关重要。它直接影响输出模式的总体形状和周期性。 + - Comfy dtype: float + - Python dtype: float + +# Output types +- KEYFRAMED_CURVE + - 此节点的输出是九个关键帧正弦曲线的元组。每条曲线都被设计为对复合波形提供独特的贡献,提供丰富的振荡组合。 + - Comfy dtype: COMBO[kf.SinusoidalCurve] + - Python dtype: Tuple[kf.SinusoidalCurve, ...] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalEntangledZeroOneFromWavelengthx9(KfSinusoidalEntangledZeroOneFromWavelength): + RETURN_TYPES = ('KEYFRAMED_CURVE',) * 9 + + def main(self, wavelength): + return super().main(n=9, wavelength=wavelength) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalGetAmplitude.md b/docs/KfSinusoidalGetAmplitude.md new file mode 100644 index 0000000..64f42c7 --- /dev/null +++ b/docs/KfSinusoidalGetAmplitude.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: KfSinusoidalGetAmplitude +- Category: ROOT_CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点从弦曲线中提取振幅,提供了曲线偏离平均值的峰值偏差的度量。这对于理解曲线中振荡的强度至关重要。 + +# Input types +## Required +- curve + - 输入的曲线参数代表从中提取振幅的正弦数据结构。它对节点的运行至关重要,因为它直接影响输出结果。 + - Comfy dtype: SINUSOIDAL_CURVE + - Python dtype: keyframed.SinusoidalCurve + +# Output types +- amplitude + - 输出提供输入正弦曲线的振幅,表明其振荡的范围。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalGetAmplitude: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('FLOAT',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve': ('SINUSOIDAL_CURVE', {'forceInput': True})}} + + def main(self, curve): + return (curve.amplitude,) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalGetFrequency.md b/docs/KfSinusoidalGetFrequency.md new file mode 100644 index 0000000..5ee9847 --- /dev/null +++ b/docs/KfSinusoidalGetFrequency.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: KfSinusoidalGetFrequency +- Category: ROOT_CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点从正弦曲线中提取基本频率,提供了其振荡速率的度量。 + +# Input types +## Required +- curve + - 输入曲线参数是必需的,因为它是提取频率的数据源。 + - Comfy dtype: SINUSOIDAL_CURVE + - Python dtype: kf.Keyframed + +# Output types +- frequency + - 输出代表输入正弦曲线的基本频率。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalGetFrequency: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('FLOAT',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve': ('SINUSOIDAL_CURVE', {'forceInput': True})}} + + def main(self, curve): + return (1 / curve.wavelength,) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalGetPhase.md b/docs/KfSinusoidalGetPhase.md new file mode 100644 index 0000000..4128fbd --- /dev/null +++ b/docs/KfSinusoidalGetPhase.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: KfSinusoidalGetPhase +- Category: ROOT_CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点旨在从正弦曲线中提取相位信息,这对于理解振荡模式中的时间定位和位置至关重要。 + +# Input types +## Required +- curve + - 曲线参数至关重要,因为它定义了将从中提取相位的正弦波形,直接影响节点的输出。 + - Comfy dtype: SINUSOIDAL_CURVE + - Python dtype: keyframed.SinusoidalCurve + +# Output types +- phase + - 输出的相位代表了正弦波的时间偏移量,这对于对齐或比较振荡模式具有重要意义。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalGetPhase: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('FLOAT',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve': ('SINUSOIDAL_CURVE', {'forceInput': True})}} + + def main(self, curve): + return (curve.phase,) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalGetWavelength.md b/docs/KfSinusoidalGetWavelength.md new file mode 100644 index 0000000..fbca6b6 --- /dev/null +++ b/docs/KfSinusoidalGetWavelength.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: KfSinusoidalGetWavelength +- Category: ROOT_CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +KfSinusoidalGetWavelength 节点旨在从一个正弦曲线中提取特征波长。它在分析和理解曲线的周期性质中扮演着关键角色,为信号处理和波形分析等应用提供了一个基本参数,这在各种应用中至关重要。 + +# Input types +## Required +- curve + - ‘curve’参数对于节点的操作至关重要,因为它代表了将从中派生波长的正弦曲线。这是一个必需的输入,它直接影响节点的输出,决定了获得的波长值的准确性和相关性。 + - Comfy dtype: SINUSOIDAL_CURVE + - Python dtype: Keyframed sinusoidal curve object + +# Output types +- wavelength + - 'wavelength' 输出参数表示正弦曲线一个完整周期的长度。这是一个关键的信息片段,可以用于进一步分析或在节点被使用的应用程序的上下文中做出明智的决策。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalGetWavelength: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('FLOAT',) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'curve': ('SINUSOIDAL_CURVE', {'forceInput': True})}} + + def main(self, curve): + return (curve.wavelength,) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalWithFrequency.md b/docs/KfSinusoidalWithFrequency.md new file mode 100644 index 0000000..2bb4bd9 --- /dev/null +++ b/docs/KfSinusoidalWithFrequency.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: KfSinusoidalWithFrequency +- Category: ROOT_CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点生成具有可调节频率、相位和振幅的正弦曲线,模拟周期性运动模式。它旨在为用户在项目中创建平滑、振荡的过渡提供多功能工具。 + +# Input types +## Required +- frequency + - 频率参数决定了正弦曲线振荡的速率,较高的值会导致更快、更频繁的周期。这对于设置动画的节奏和节奏至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- phase + - 相位参数沿着时间线移动正弦曲线,允许控制振荡的起始点。这对于将动作与动画中的特定事件或动作对齐至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- amplitude + - 振幅参数控制振荡的范围,决定了正弦曲线的峰值和谷值。它影响动作的整体强度和幅度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- curve + - 输出是一个包含正弦模式的关键帧曲线对象,可以用于各种动画和模拟场景。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.SinusoidalCurve +- sinusoidal_curve + - 该输出以可以直接应用于视觉元素的格式提供了正弦曲线,提供了振荡的平滑且动态的表示。 + - Comfy dtype: SINUSOIDAL_CURVE + - Python dtype: keyframed.SinusoidalCurve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalWithFrequency: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE', 'SINUSOIDAL_CURVE') + + @classmethod + def INPUT_TYPES(s): + return {'required': {'frequency': ('FLOAT', {'default': 1 / 12, 'step': 0.01}), 'phase': ('FLOAT', {'default': 0.0, 'step': 0.1308996939}), 'amplitude': ('FLOAT', {'default': 1, 'step': 0.01})}} + + def main(self, frequency, phase, amplitude): + curve = kf.SinusoidalCurve(frequency=frequency, phase=phase, amplitude=amplitude) + return (curve, curve) +``` \ No newline at end of file diff --git a/docs/KfSinusoidalWithWavelength.md b/docs/KfSinusoidalWithWavelength.md new file mode 100644 index 0000000..57a9d7b --- /dev/null +++ b/docs/KfSinusoidalWithWavelength.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: KfSinusoidalWithWavelength +- Category: ROOT_CATEGORY +- Output node: False +- Repo Ref: https://github.com/dmarx/ComfyUI-Keyframed + +该节点生成具有可定制波长、相位和振幅的正弦曲线,便于为各种应用创建周期性波形。 + +# Input types +## Required +- wavelength + - 波长决定了正弦曲线的周期,影响其整体长度和峰值之间的间距。 + - Comfy dtype: FLOAT + - Python dtype: float +- phase + - 相位沿时间线移动正弦曲线,改变其峰值和低谷相对于起点的时间。 + - Comfy dtype: FLOAT + - Python dtype: float +- amplitude + - 振幅控制正弦曲线峰值和低谷的大小,影响其振荡的程度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- curve + - 输出是一个代表正弦波形的关键帧曲线对象,可供进一步操作或可视化。 + - Comfy dtype: KEYFRAMED_CURVE + - Python dtype: keyframed.KfCurve +- sinusoidal_curve + - 这是根据输入参数派生出的正弦曲线,封装了生成的波形,以便在各种上下文中使用。 + - Comfy dtype: SINUSOIDAL_CURVE + - Python dtype: keyframed.SinusoidalCurve + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KfSinusoidalWithWavelength: + CATEGORY = CATEGORY + FUNCTION = 'main' + RETURN_TYPES = ('KEYFRAMED_CURVE', 'SINUSOIDAL_CURVE') + + @classmethod + def INPUT_TYPES(s): + return {'required': {'wavelength': ('FLOAT', {'default': 12, 'step': 0.5}), 'phase': ('FLOAT', {'default': 0.0, 'step': 0.1308996939}), 'amplitude': ('FLOAT', {'default': 1, 'step': 0.01})}} + + def main(self, wavelength, phase, amplitude): + curve = kf.SinusoidalCurve(wavelength=wavelength, phase=phase, amplitude=amplitude) + return (curve, curve) +``` \ No newline at end of file diff --git a/docs/KuwaharaBlur.md b/docs/KuwaharaBlur.md new file mode 100644 index 0000000..73f8080 --- /dev/null +++ b/docs/KuwaharaBlur.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: KuwaharaBlur +- Category: postprocessing/Filters +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +KuwaharaBlur 类旨在对图像应用 Kuwahara 滤波器,这是一种用于图像处理的非线性数字滤波器。它可以平滑图像同时保留边缘,特别适用于在不模糊重要细节的情况下减少图像噪声。该节点基于将图像划分为较小的块,并根据局部方差用过滤后的版本替换每个,从而保留图像的结构完整性。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它是 Kuwahara 滤波器处理的主要输入。它是节点派生输出的来源,图像的内容和质量直接影响噪声减少和边缘保留的有效性。 + - Comfy dtype: IMAGE + - Python dtype: np.ndarray +- blur_radius + - 模糊半径参数决定了 Kuwahara 滤波器应用的平滑效果的程度。它影响用于处理的块的大小,从而直接影响噪声减少和细节保留之间的平衡。 + - Comfy dtype: INT + - Python dtype: int +- method + - 方法参数决定了要应用的 Kuwahara 滤波器类型,可以是 'mean' 或 'gaussian'。这个选择影响过滤过程和结果图像,'mean' 提供更均匀的平滑,而 'gaussian' 根据图像的局部属性提供更自适应的平滑。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- output_image + - 输出图像代表了应用 Kuwahara 滤波器后处理过的图像。它反映了节点的主要功能,是噪声减少和边缘保留努力的结晶,提供了更清晰、更明确的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class KuwaharaBlur: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'blur_radius': ('INT', {'default': 3, 'min': 0, 'max': 31, 'step': 1}), 'method': (['mean', 'gaussian'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'apply_kuwahara_filter' + CATEGORY = 'postprocessing/Filters' + + def apply_kuwahara_filter(self, image: np.ndarray, blur_radius: int, method: str): + if blur_radius == 0: + return (image,) + out = torch.zeros_like(image) + (batch_size, height, width, channels) = image.shape + for b in range(batch_size): + image = image[b].cpu().numpy() * 255.0 + image = image.astype(np.uint8) + out[b] = torch.from_numpy(kuwahara(image, method=method, radius=blur_radius)) / 255.0 + return (out,) +``` \ No newline at end of file diff --git a/docs/LDSRModelLoader.md b/docs/LDSRModelLoader.md new file mode 100644 index 0000000..e9fc41a --- /dev/null +++ b/docs/LDSRModelLoader.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: LDSRModelLoader +- Category: Flowty LDSR +- Output node: False +- Repo Ref: https://github.com/flowtyone/ComfyUI-Flowty-LDSR.git + +该节点旨在加载并准备一个LDSR模型以供使用,抽象化了模型检索和初始化的复杂性。它通过将模型转移到适当的设备并设置为评估模式,确保模型准备好用于上采样任务。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它指定了要加载的LDSR模型。它通过确定用于上采样过程的哪个模型的状态字典和配置来影响整个操作。 + - Comfy dtype: COMBO[filename] + - Python dtype: str + +# Output types +- UPSCALE_MODEL + - 输出提供了一个完全初始化并准备好的LDSR模型,这对于进一步的图像上采样任务非常重要。 + - Comfy dtype: COMBO[LDSR] + - Python dtype: LDSR + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LDSRModelLoader: + + @classmethod + def INPUT_TYPES(s): + model_list = get_filename_list('upscale_models') + candidates = [name for name in model_list if 'last.ckpt' in name] + if len(candidates) > 0: + default_path = candidates[0] + else: + default_path = 'last.ckpt' + return {'required': {'model': (model_list, {'default': default_path})}} + RETURN_TYPES = ('UPSCALE_MODEL',) + FUNCTION = 'load' + CATEGORY = 'Flowty LDSR' + + def load(self, model): + model_path = get_full_path('upscale_models', model) + model = LDSR.load_model_from_path(model_path) + model['model'].cpu() + return (model,) +``` \ No newline at end of file diff --git a/docs/LDSRUpscale.md b/docs/LDSRUpscale.md new file mode 100644 index 0000000..6e6caa1 --- /dev/null +++ b/docs/LDSRUpscale.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: LDSRUpscale +- Category: Flowty LDSR +- Output node: False +- Repo Ref: https://github.com/flowtyone/ComfyUI-Flowty-LDSR.git + +该节点类封装了对图像执行超分辨率的高级功能,使用LDSR模型来提高图像的分辨率,从而增强图像质量。它旨在提高视觉保真度和细节,同时不损害图像的基本内容。 + +# Input types +## Required +- upscale_model + - upscale_model参数至关重要,因为它定义了节点将用于执行超分辨率任务的底层模型。这对于节点的正确功能和产生准确结果至关重要。 + - Comfy dtype: UPSCALE_MODEL + - Python dtype: str +- images + - images参数是节点操作的主要输入,代表需要放大的图像。它的作用至关重要,因为输入的质量和类型直接影响输出的外观和超分辨率过程的有效性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +## Optional +- steps + - steps参数影响模型在放大过程中执行的迭代次数。它是输出质量和所需计算资源之间的平衡因素。更多的步骤通常会产生更好的结果,但计算成本更高。 + - Comfy dtype: COMBO[25, 50, 100, 250, 500, 1000] + - Python dtype: int +- pre_downscale + - pre_downscale参数决定了在超分辨率过程之前应用于输入图像的缩小比例。这对于管理计算负载和内存使用特别有用,尤其是对于非常高分辨率的图像。 + - Comfy dtype: COMBO[None, 1/2, 1/4] + - Python dtype: str +- post_downscale + - post_downscale参数在应用超分辨率后决定缩小操作。它有助于控制最终输出的大小,并可用于根据不同的用例或要求优化输出。 + - Comfy dtype: COMBO[None, Original Size, 1/2, 1/4] + - Python dtype: str +- downsample_method + - downsample_method参数指定在超分辨率过程之前或之后减小图像大小时使用的下采样技术。它影响调整大小后的图像质量,Lanczos通常提供更好的结果,但计算成本更高。 + - Comfy dtype: COMBO[Nearest, Lanczos] + - Python dtype: str + +# Output types +- images + - 输出图像是超分辨率过程的结果,展示了增强的细节和改善的视觉保真度。它们是节点的主要输出,直接反映了放大模型和使用的参数的有效性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LDSRUpscale: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'upscale_model': ('UPSCALE_MODEL',), 'images': ('IMAGE',), 'steps': (['25', '50', '100', '250', '500', '1000'], {'default': '100'}), 'pre_downscale': (['None', '1/2', '1/4'], {'default': 'None'}), 'post_downscale': (['None', 'Original Size', '1/2', '1/4'], {'default': 'None'}), 'downsample_method': (['Nearest', 'Lanczos'], {'default': 'Lanczos'})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('images',) + FUNCTION = 'upscale' + CATEGORY = 'Flowty LDSR' + + def upscale(self, upscale_model, images, steps, pre_downscale='None', post_downscale='None', downsample_method='Lanczos'): + pbar = ProgressBar(int(steps)) + p = {'prev': 0} + + def prog(i): + i = i + 1 + if i < p['prev']: + p['prev'] = 0 + pbar.update(i - p['prev']) + p['prev'] = i + ldsr = LDSR(model=upscale_model, on_progress=prog) + outputs = [] + for image in images: + outputs.append(ldsr.superResolution(image, int(steps), pre_downscale, post_downscale, downsample_method)) + return (torch.stack(outputs),) +``` \ No newline at end of file diff --git a/docs/LDSRUpscaler.md b/docs/LDSRUpscaler.md new file mode 100644 index 0000000..02145b7 --- /dev/null +++ b/docs/LDSRUpscaler.md @@ -0,0 +1,79 @@ +# Documentation +- Class name: LDSRUpscaler +- Category: Flowty LDSR +- Output node: False +- Repo Ref: https://github.com/flowtyone/ComfyUI-Flowty-LDSR.git + +LDSRUpscaler节点的'upscale'方法旨在使用预训练模型增强输入图像的分辨率。它利用LDSR算法的能力执行超分辨率,即在保持或提高图像质量的同时增加图像的空间分辨率。该方法特别适用于放大具有高度细节的图像,如照片或数字艺术作品。 + +# Input types +## Required +- model + - ‘model’参数是用于放大的预训练模型的路径。它对节点的功能至关重要,因为它决定了将应用于输入图像进行超分辨率的特定模型权重和架构。 + - Comfy dtype: STRING + - Python dtype: str +- images + - ‘images’参数是节点将处理以进行放大的图像集合。这个输入是必不可少的,因为它代表了将由节点转换以实现更高分辨率的数据。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image.Image] +- steps + - ‘steps’参数定义了超分辨率过程中使用的扩散步骤数。它影响放大图像的质量和计算时间。更多的步骤通常可以带来更好的结果,但也会延长处理时间。 + - Comfy dtype: INT + - Python dtype: int +- pre_downscale + - ‘pre_downscale’参数指定在超分辨率过程之前是否以及多少比例缩小图像。这是一个可选设置,可用于控制输入图像的初始分辨率。 + - Comfy dtype: STRING + - Python dtype: str +- post_downscale + - ‘post_downscale’参数确定在超分辨率过程之后是否以及如何缩小图像。它允许控制输出图像的最终分辨率。 + - Comfy dtype: STRING + - Python dtype: str +- downsample_method + - ‘downsample_method’参数选择在调整图像大小时使用的缩小算法。它可能影响缩小图像的质量,选项通常包括‘Nearest’或‘Lanczos’。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- images + - ‘images’输出参数包含超分辨率过程产生的放大图像。这些是节点执行的主要结果,代表了具有增加分辨率的转换数据。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LDSRUpscaler: + + @classmethod + def INPUT_TYPES(s): + model_list = get_filename_list('upscale_models') + candidates = [name for name in model_list if 'last.ckpt' in name] + if len(candidates) > 0: + default_path = candidates[0] + else: + default_path = 'last.ckpt' + return {'required': {'model': (model_list, {'default': default_path}), 'images': ('IMAGE',), 'steps': (['25', '50', '100', '250', '500', '1000'], {'default': '100'}), 'pre_downscale': (['None', '1/2', '1/4'], {'default': 'None'}), 'post_downscale': (['None', 'Original Size', '1/2', '1/4'], {'default': 'None'}), 'downsample_method': (['Nearest', 'Lanczos'], {'default': 'Lanczos'})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('images',) + FUNCTION = 'upscale' + CATEGORY = 'Flowty LDSR' + + def upscale(self, model, images, steps, pre_downscale='None', post_downscale='None', downsample_method='Lanczos'): + model_path = get_full_path('upscale_models', model) + pbar = ProgressBar(int(steps)) + p = {'prev': 0} + + def prog(i): + i = i + 1 + if i < p['prev']: + p['prev'] = 0 + pbar.update(i - p['prev']) + p['prev'] = i + ldsr = LDSR(modelPath=model_path, torchdevice=get_torch_device(), on_progress=prog) + outputs = [] + for image in images: + outputs.append(ldsr.superResolution(image, int(steps), pre_downscale, post_downscale, downsample_method)) + return (torch.stack(outputs),) +``` \ No newline at end of file diff --git a/docs/LLLiteLoader.md b/docs/LLLiteLoader.md new file mode 100644 index 0000000..d73ff69 --- /dev/null +++ b/docs/LLLiteLoader.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: LLLiteLoader +- Category: loaders +- Output node: False +- Repo Ref: https://github.com/kohya-ss/ControlNet-LLLite-ComfyUI.git + +LLLiteLoader 类旨在高效加载和处理模型,使得能够将控制机制集成到模型架构中。它抽象了模型加载和调节的复杂性,专注于无缝适应模型到特定的条件和要求。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了将要被调节和修改的基础架构。它是LLLiteLoader功能起点,决定了将要处理的模型类型。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- model_name + - 模型名称参数对于识别要加载的特定模型文件至关重要。它指导LLLiteLoader在文件系统中找到正确的模型,确保选择了正确的模型进行处理。 + - Comfy dtype: STRING + - Python dtype: str +- cond_image + - cond_image 参数作为调节输入,影响模型的行为和输出。它是模型适应过程中的关键组成部分,允许基于视觉上下文进行微调。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- strength + - strength 参数调整调节效应对模型的强度。它在确定调节输入对模型最终输出影响程度方面发挥重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- steps + - steps 参数定义了调节过程中使用的间隔数。它对模型的进展和调节效应在整个过程中的分布很重要。 + - Comfy dtype: INT + - Python dtype: int +- start_percent + - start_percent 参数指定了调节间隔的开始,决定了模型开始适应调节输入的时间。它是控制模型响应时间的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_percent + - end_percent 参数标记了调节间隔的结束,定义了模型适应调节输入的结束时间。它是确定模型响应持续时间的关键。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- model + - 输出模型是LLLiteLoader处理的结果,包含了调节输入和调整。它代表了模型经过整个调节过程后的最终状态,准备用于进一步的使用或评估。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LLLiteLoader: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'model_name': (get_file_list(os.path.join(CURRENT_DIR, 'models')),), 'cond_image': ('IMAGE',), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'steps': ('INT', {'default': 0, 'min': 0, 'max': 200, 'step': 1}), 'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 100.0, 'step': 0.1}), 'end_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 100.0, 'step': 0.1})}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'load_lllite' + CATEGORY = 'loaders' + + def load_lllite(self, model, model_name, cond_image, strength, steps, start_percent, end_percent): + model_path = os.path.join(CURRENT_DIR, os.path.join(CURRENT_DIR, 'models', model_name)) + model_lllite = model.clone() + patch = load_control_net_lllite_patch(model_path, cond_image, strength, steps, start_percent, end_percent) + if patch is not None: + model_lllite.set_model_attn1_patch(patch) + model_lllite.set_model_attn2_patch(patch) + return (model_lllite,) +``` \ No newline at end of file diff --git a/docs/LMStudioPrompt.md b/docs/LMStudioPrompt.md new file mode 100644 index 0000000..203f8e3 --- /dev/null +++ b/docs/LMStudioPrompt.md @@ -0,0 +1,111 @@ +# Documentation +- Class name: LMStudioPrompt +- Category: Mikey/AI +- Output node: True +- Repo Ref: https://github.com/bash-j/mikey_nodes + +LMStudioPrompt节点旨在为AI文本到图像模型生成提示提供便利。它通过各种模式如'prompt'、'style'、'descriptor'和'character'处理输入提示,通过详细的描述来丰富提示,指导AI模型的图像生成。该节点还支持自定义历史记录以提供个性化响应,并与外部服务器集成以检索和处理提示结果。 + +# Input types +## Required +- input_prompt + - 输入提示是LMStudioPrompt节点的关键参数,因为它直接影响AI生成图像的内容和方向。它作为节点将产生详细描述的基础,旨在为AI模型提供清晰和富有想象力的视觉。 + - Comfy dtype: STRING + - Python dtype: str +- mode + - 模式参数决定了LMStudioPrompt节点处理输入提示的方法。每种模式对应生成详细描述的不同方式,例如在'style'模式中专注于图像的风格,或在'character'模式中制作详细的角色描述。模式的选择显著影响生成提示的输出和应用。 + - Comfy dtype: COMBO['prompt', 'style', 'descriptor', 'character', 'custom'] + - Python dtype: str +## Optional +- custom_history + - 当模式设置为'custom'时,custom_history参数变得重要。它允许用户提供一个指向历史记录文件的路径,节点将使用该路径生成响应。此功能使节点能够访问外部数据源,以实现更个性化或情境感知的提示生成过程。 + - Comfy dtype: STRING + - Python dtype: str +- server_address + - server_address参数指定LMStudioPrompt节点将与之通信以发送和接收数据的服务器地址。当节点需要与外部服务或应用程序交互以处理提示时,这特别有用。 + - Comfy dtype: STRING + - Python dtype: str +- server_port + - server_port参数定义了LMStudioPrompt节点将用于通信的服务器上的端口号。它是建立与服务器连接的重要组成部分,确保节点可以正确发送和接收数据。 + - Comfy dtype: INT + - Python dtype: int +- seed + - seed参数用于初始化随机数生成器,确保LMStudioPrompt节点产生的结果是可复现的。这对于调试或在多次运行中期望一致的结果时特别有用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- text + - LMStudioPrompt节点的文本输出包含处理后的提示结果。它是基于输入提示和选定模式生成的详细描述,可以直接用作AI文本到图像模型的输入,以创建图像。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LMStudioPrompt: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input_prompt': ('STRING', {'multiline': True, 'default': 'Prompt Text Here', 'dynamicPrompts': False}), 'mode': (['prompt', 'style', 'descriptor', 'character', 'custom'], {'default': 'prompt'}), 'custom_history': ('STRING', {'multiline': False, 'default': 'path to history.json', 'dynamicPrompts': True}), 'server_address': ('STRING', {'default': 'localhost'}), 'server_port': ('INT', {'default': 1234, 'min': 0, 'max': 65535}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('text',) + FUNCTION = 'process' + OUTPUT_NODE = True + CATEGORY = 'Mikey/AI' + + def history(self, mode, custom_history): + if mode == 'prompt': + return {'messages': [{'role': 'system', 'content': 'You are a helpful assistant.'}, {'role': 'user', 'content': "I say something like 'blonde woman' and you respond with a single prompt which I can use as prompts for an AI txt2image model. Your response to blonde woman would be something like 'Blonde woman wearing a patterned orange, white, and blue sundress, smiling, on a sunny day with a blue sky, surrounded by buildings and palm trees'. It describes the image with lots of details so the AI model will understand what it needs to generate."}, {'role': 'assistant', 'content': "Sure thing! Let's begin. What is your first prompt?"}, {'role': 'user', 'content': 'futuristic man'}, {'role': 'assistant', 'content': 'Man with short black hair in a highly detailed silver and black mechanical exoskeleton suit, holding a futuristic rifle, standing in a futuristic city with tall buildings and flying cars, with a futuristic cityscape in the background.'}, {'role': 'user', 'content': 'a black cat'}, {'role': 'assistant', 'content': 'A black cat with green eyes, sitting on a wooden table, there is a vase of flowers on the table, the cat is looking at the flowers. Sunlight is streaming in through a window, illuminating the cat and the flowers.'}, {'role': 'user', 'content': 'toaster oven'}, {'role': 'assistant', 'content': 'A toaster oven with a slice of bread inside, the bread is toasted and has a smiley face burned into it. The toaster oven is sitting on a kitchen counter next to a coffee maker and a microwave. The kitchen counter is made of granite and has a sink in it. There is a window above the sink with a view of a city skyline.'}, {'role': 'user', 'content': 'war'}, {'role': 'assistant', 'content': 'A soldier wearing a gas mask and a helmet, holding a rifle, standing in a trench. There is barbed wire in front of the trench. The sky is dark and cloudy. There is a tank in the background.'}, {'role': 'user', 'content': 'portrait of a man'}, {'role': 'assistant', 'content': 'A portrait of a man in his 30s with short brown hair and a beard. He is wearing a suit and tie. He is smiling. He is standing in front of a brick wall with graffiti on it.'}, {'role': 'user', 'content': 'a friendly ogre'}, {'role': 'assistant', 'content': 'A friendly ogre with green skin and a big smile. He is wearing a red and white striped shirt and blue overalls. He is holding a pitchfork. He is standing in a field of flowers. There is a rainbow in the sky.'}, {'role': 'user', 'content': 'puppy'}, {'role': 'assistant', 'content': "A cute pug dog wearing a bowtie and reading a book. The book is titled 'How to be a good dog'. The dog is sitting on a couch in a living room. There is a fireplace in the background."}, {'role': 'user', 'content': 'apples'}, {'role': 'assistant', 'content': 'Red apples stacked in a wooden crate. The crate is sitting on a wooden table in the kitchen inside a rustic farm house with old appliances. The walls are decorated with family photos. There is a window in the background with a view of the farm.'}, {'role': 'user', 'content': 'working woman'}, {'role': 'assistant', 'content': 'A woman is working on a laptop computer. She is wearing a white shirt and black pants. She is sitting at a desk in a modern office with trendy furniture. She has a cup of coffee on the desk next to her.'}]} + elif mode == 'style': + return {'messages': [{'role': 'system', 'content': 'You are a helpful assistant.'}, {'role': 'user', 'content': "I say something like 'painting' and you respond with a single prompt which I can use as prompts for an AI txt2image model. Your response to painting would be something like 'Impressionistic, landscape, vivid colors, loose brushstrokes, beauty of nature. Inspired by Claude Monet'. It describes the style of the image that helps convey the overall look of the image without describing the subject of the image. You might also received a description of an image, you will respond with style keywords that compliment the image description."}, {'role': 'assistant', 'content': "Sure thing! Let's begin. What is your first prompt?"}, {'role': 'user', 'content': 'painting'}, {'role': 'assistant', 'content': "Realism, oil painting, dark shadows, bright highlights, focus on capturing light and texture. Inspired by Caravaggio's chiaroscuro technique"}, {'role': 'user', 'content': 'Impressionism'}, {'role': 'assistant', 'content': 'Impressionism. Soft brushstrokes, fleeting moments of light and color. Landscapes, flowers, people in motion'}, {'role': 'user', 'content': 'painting'}, {'role': 'assistant', 'content': 'Impressionistic, landscape, vivid colors, loose brushstrokes, beauty of nature. Inspired by Claude Monet'}, {'role': 'user', 'content': 'The 2015 Audi R8 Spyder sports car is parked on a driveway outside a luxurious mansion. The car is painted in a metallic grey color. The top is down revealing the sleek interior. The car is surrounded by lush greenery and palm trees.'}, {'role': 'assistant', 'content': 'Landscape photography, vibrant saturation, dramatic shadows, golden hour lighting, inspired by the work of Peter Lik.'}, {'role': 'user', 'content': 'abstract'}, {'role': 'assistant', 'content': 'Abstract expressionism, bold brushstrokes, vivid colors'}, {'role': 'user', 'content': 'water'}, {'role': 'assistant', 'content': 'Water sculpture, fluid dynamics, abstract representation, in the style of Yves Klein'}, {'role': 'user', 'content': 'A MacBook Pro open and displaying an email message. The keyboard is illuminated and the trackpad is being used. A man is sitting at a wooden desk in a cozy home office. There is a plant in the corner and sunlight coming in from a nearby window.'}, {'role': 'assistant', 'content': 'Still life, muted colors, soft lighting, in the style of Henri Matisse'}, {'role': 'user', 'content': 'Surrealism'}, {'role': 'assistant', 'content': 'dreamlike imagery, unexpected juxtapositions, symbolic elements. features distorted or unusual forms, animals or objects transformed into otherworldly shapes'}, {'role': 'user', 'content': 'Art Nouveau'}, {'role': 'assistant', 'content': 'Art Nouveau style, flowing lines, organic shapes, muted color palette, decorative elements, floral motifs.'}, {'role': 'user', 'content': 'photo'}, {'role': 'assistant', 'content': 'Black and white photograph, shot using a large format camera with slow shutter speeds. Grainy texture and high contrast. Influenced by the works of Edward Hopper.'}, {'role': 'user', 'content': 'photo'}, {'role': 'assistant', 'content': 'Color photograph, Soft focus, muted colors, romantic atmosphere, in the style of Edward Weston.'}, {'role': 'user', 'content': 'film'}, {'role': 'assistant', 'content': 'Long shot, film still, cinematic lighting, gritty realism, inspired by the works of Gus Van Sant'}, {'role': 'user', 'content': 'movie'}, {'role': 'assistant', 'content': 'Filmic storytelling, dreamlike imagery, surreal elements, poetic narratives, reminiscent of the works of David Lynch.'}]} + elif mode == 'descriptor': + return {'messages': [{'role': 'system', 'content': 'You are a helpful assistant.'}, {'role': 'user', 'content': "I say something like 'color' and you respond with a single prompt which I can use to build a prompt for an AI txt2image model. Your response to color would be something like 'red'. It is a very short description to add dynamic variety to the prompt."}, {'role': 'assistant', 'content': "Sure thing! Let's begin. What is your first prompt?"}, {'role': 'user', 'content': 'color'}, {'role': 'assistant', 'content': 'burnt sienna'}, {'role': 'user', 'content': 'hair color'}, {'role': 'assistant', 'content': 'platinum blonde'}, {'role': 'user', 'content': 'metal'}, {'role': 'assistant', 'content': 'rusted iron'}, {'role': 'user', 'content': 'weather'}, {'role': 'assistant', 'content': 'bright and sunny'}, {'role': 'user', 'content': 'time of day'}, {'role': 'assistant', 'content': 'crack of dawn'}, {'role': 'user', 'content': 'man'}, {'role': 'assistant', 'content': 'tall and slender man with wide shoulders in his 30s'}, {'role': 'user', 'content': 'ethnicity'}, {'role': 'assistant', 'content': 'Vietnamese'}, {'role': 'user', 'content': 'occupation'}, {'role': 'assistant', 'content': 'Heavy diesel mechanic'}, {'role': 'user', 'content': 'art style'}, {'role': 'assistant', 'content': 'crystal cubism'}, {'role': 'user', 'content': 'artist'}, {'role': 'assistant', 'content': 'Camille Pissarro'}, {'role': 'user', 'content': 'movie director'}, {'role': 'assistant', 'content': 'David Lynch'}]} + elif mode == 'character': + return {'messages': [{'role': 'system', 'content': 'You are a helpful assistant.'}, {'role': 'user', 'content': "When a user requests a character description, generate a detailed description of the character as you would expect from the writer George R. R. Martin. The description should be a suitable prompt based on the description that encapsulates the character's key visual elements for image creation using a txt2img model."}, {'role': 'assistant', 'content': "Sure thing! Let's begin. What is your first prompt?"}, {'role': 'user', 'content': 'jolly cartoon octopus'}, {'role': 'assistant', 'content': 'A cartoon octopus with a jolly demeanor in a sunshiny yellow and orange color scheme, wearing a small top hat and a polka-dotted bow tie, surrounded by intricate sculptures made of its own ink, in the midst of an undersea setting that hints at festivity and mirth.'}, {'role': 'user', 'content': 'a dapper young lady spy who wears suits'}, {'role': 'assistant', 'content': 'A young 1920s lady spy with chestnut hair in a bob cut, piercing emerald eyes, wearing a tailored charcoal pinstripe suit with a white shirt and a silk tie, holding a silver cigarette case, exuding an aura of mystery and sophistication against a backdrop of Parisian nightlife.'}, {'role': 'user', 'content': 'a charming robot'}, {'role': 'assistant', 'content': 'A charming robot with a sleek chrome body, art deco design elements, azure glowing eyes, and a gentle smile. Wearing a holographic bow tie and a vest painted to look like a dapper suit, engaged in performing a magic trick with a playful, inquisitive expression in an urban park setting.'}, {'role': 'user', 'content': 'cartoon ant'}, {'role': 'assistant', 'content': 'A cartoon ant with a vibrant blue exoskeleton, oversized round eyes full of curiosity, wearing a leaf-green vest and a tiny fabric cap. Exhibiting an expression of wonder and excitement, amidst a backdrop of an underground ant colony bustling with activity.'}, {'role': 'user', 'content': 'a cyberpunk gnome'}, {'role': 'assistant', 'content': 'A cyberpunk gnome with pale skin and cybernetic jade eyes, wearing a long tattered coat with circuitry patches and a sleek metallic pointed helmet. Surrounded by holographic screens and neon lights in a dim, cluttered workshop filled with futuristic gadgets and data screens.'}]} + elif mode == 'custom': + try: + history = json.load(open(custom_history)) + return history + except: + raise Exception('Error loading custom history file') + + def api_request(self, prompt, server_address, server_port, seed, mode, custom_history): + history = self.history(mode, custom_history) + if mode == 'prompt': + prompt = f'{prompt}, describe in detail.' + if mode == 'descriptor': + spice = ['a', 'the', 'this', 'that', 'an exotic', 'an interesting', 'a colorful', 'a vibrant', 'get creative!', 'think outside the box!', 'a rare', 'a standard', 'a typical', 'a common', 'a normal', 'a regular', 'a usual', 'an ordinary', 'a unique', 'a one of a kind', 'a special', 'a distinctive', 'a peculiar', 'a remarkable', 'a noteworthy', 'popular in the victorian era', 'popular in the 1920s', 'popular in the 1950s', 'popular in the 1980s', 'popular in the 1990s', 'popular in the 2000s', 'popular in the 2010s', 'popular in the 2020s', 'popular in asia', 'popular in europe', 'popular in north america', 'popular in south america', 'popular in africa', 'popular in australia', 'popular in the middle east', 'popular in the pacific islands', 'popular with young people', 'popular with the elderly', 'trending on social media', 'popular on tiktok', 'trending on pinterest', 'popular on instagram', 'popular on facebook', 'popular on twitter', 'popular on reddit', 'popular on youtube', 'popular on tumblr', 'popular on snapchat', 'popular on linkedin', 'popular on twitch', 'popular on discord', 'unusual example of', 'a classic', 'an underrated', 'an innovative', 'a historical', 'a modern', 'a contemporary', 'a futuristic', 'a traditional', 'an eco-friendly', 'a controversial', 'a political', 'a religious', 'a spiritual', 'a philosophical', 'a scientific'] + random.seed(seed) + prompt = f'{random.choice(spice)} {prompt}' + '\n example curl request to LM Studio\n curl http://localhost:1234/v1/chat/completions -H "Content-Type: application/json" -d \'{\n "messages": [\n { "role": "system", "content": "Always answer in rhymes." },\n { "role": "user", "content": "Introduce yourself." }\n ],\n "temperature": 0.7,\n "max_tokens": -1,\n "stream": false\n }\'\n ' + history['messages'].append({'role': 'user', 'content': prompt}) + request = {'messages': history['messages'], 'temperature': 0.2, 'top_p': 0.95, 'presence_penalty': 0.0, 'frequency_penalty': 0.0, 'max_tokens': 1200, 'stream': False, 'seed': seed} + HOST = f'{server_address}:{server_port}' + URI = f'http://{HOST}/v1/chat/completions' + try: + response = requests.post(URI, json=request, timeout=60) + except requests.exceptions.ConnectionError: + raise Exception('Are you running LM Studio with server running?') + if response.status_code == 200: + result = response.json()['choices'][0]['message']['content'] + result = html.unescape(result) + return result + else: + return 'Error' + + def process(self, input_prompt, mode, custom_history, server_address, server_port, seed, prompt=None, unique_id=None, extra_pnginfo=None): + input_prompt = find_and_replace_wildcards(input_prompt, seed, debug=True) + input_prompt = search_and_replace(input_prompt, extra_pnginfo, prompt) + wc_re = re.compile('{([^}]+)}') + + def repl(m): + return random.choice(m.group(1).split('|')) + for m in wc_re.finditer(input_prompt): + input_prompt = input_prompt.replace(m.group(0), repl(m)) + result = self.api_request(input_prompt, server_address, server_port, seed, mode, custom_history) + prompt.get(str(unique_id))['inputs']['output_text'] = result + return (result,) +``` \ No newline at end of file diff --git a/docs/Latent Batch Comparison Plot.md b/docs/Latent Batch Comparison Plot.md new file mode 100644 index 0000000..be0127a --- /dev/null +++ b/docs/Latent Batch Comparison Plot.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: LatentBatchComparator +- Category: test +- Output node: False +- Repo Ref: https://github.com/ttulttul/ComfyUI-Iterative-Mixer + +该节点旨在通过生成可视化表示来比较两批潜在变量,展示它们之间的差异。它使用余弦相似度矩阵来量化潜在向量之间的差异,提供对它们在潜在空间中相对位置的清晰直观理解。 + +# Input types +## Required +- latent_batch_1 + - 此参数代表要比较的第一个潜在变量批次。它在节点的操作中扮演着关键角色,因为它构成了比较的一方。此批次中的潜在变量预期以一种允许与第二个批次进行有意义比较的方式进行结构化。 + - Comfy dtype: "LATENT" + - Python dtype: Dict[str, torch.Tensor] +- latent_batch_2 + - 此参数保存要与第一批进行比较的第二批潜在变量。它的重要性与第一批相当,因为它完成了比较分析。此批次中的潜在变量的结构和格式应与第一批中的潜在变量兼容,以进行准确的比较。 + - Comfy dtype: "LATENT" + - Python dtype: Dict[str, torch.Tensor] + +# Output types +- plot_image + - 该节点的输出是一张表示两批潜在变量之间余弦相似度矩阵的图像。它作为一个可视化工具,可以一目了然地理解潜在变量之间的相似度或差异程度。 + - Comfy dtype: "IMAGE" + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LatentBatchComparator: + """ + Generate plots showing the differences between two batches of latents. + """ + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latent_batch_1': ('LATENT',), 'latent_batch_2': ('LATENT',)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('plot_image',) + CATEGORY = 'test' + FUNCTION = 'plot_latent_differences' + + def plot_latent_differences(self, latent_batch_1, latent_batch_2): + """ + Generate a plot of the differences between two batches of latents. + """ + import torch.nn.functional as F + (tensor1, tensor2) = [x['samples'] for x in (latent_batch_1, latent_batch_2)] + if tensor1.shape != tensor2.shape: + raise ValueError('Latent batches must have the same shape: %s != %s' % (tensor1.shape, tensor2.shape)) + (B, C, H, W) = tensor1.shape + tensor1_flat = tensor1.view(B, -1) + tensor2_flat = tensor2.view(B, -1) + tensor1_flat_expanded = tensor1_flat.unsqueeze(1) + cosine_similarities_vectorized = F.cosine_similarity(tensor1_flat_expanded, tensor2_flat.unsqueeze(0), dim=2) + plt.figure(figsize=(15, 10)) + plt.imshow(cosine_similarities_vectorized, cmap='viridis') + plt.title('Cosine Similarity Matrix') + plt.xlabel('Batch 1 Index') + plt.ylabel('Batch 2 Index') + plt.tight_layout() + buf = io.BytesIO() + plt.savefig(buf, format='png') + buf.seek(0) + pil_image = Image.open(buf) + image_tensor = pil2tensor(pil_image) + batch_output = image_tensor.unsqueeze(0) + return batch_output +``` \ No newline at end of file diff --git a/docs/Latent Batch Statistics Plot.md b/docs/Latent Batch Statistics Plot.md new file mode 100644 index 0000000..358b449 --- /dev/null +++ b/docs/Latent Batch Statistics Plot.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: LatentBatchStatisticsPlot +- Category: tests +- Output node: False +- Repo Ref: https://github.com/ttulttul/ComfyUI-Iterative-Mixer + +LatentBatchStatisticsPlot节点旨在分析一批潜在变量的统计属性。它执行全面的统计分析,以确定批次中每个潜在变量的正态性。该节点生成统计结果的可视化表示,提供对潜在变量的分布特征的洞察。这对于需要图形分析工具来理解底层数据模式的研究人员和数据科学家特别有用。 + +# Input types +## Required +- batch + - ‘batch’参数对于节点的操作至关重要,因为它代表了要分析的潜在变量集合。这是一个关键输入,直接影响统计分析和生成的图表。该参数确保节点接收到正确的数据以执行其预定功能。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Output types +- plot_image + - ‘plot_image’输出是由节点执行的统计分析的图形表示。它在图表中包含了潜在变量的p值、均值和标准差,提供了数据分布的可视化摘要。这个输出非常重要,因为它使用户能够快速掌握潜在批次的统计属性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LatentBatchStatisticsPlot: + """ + Generate a plot of the statistics of a batch of latents for analysis. + Outputs an image. + """ + + @classmethod + def INPUT_TYPES(s): + return {'required': {'batch': ('LATENT',)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('plot_image',) + FUNCTION = 'statistics' + CATEGORY = 'tests' + + @torch.no_grad() + def statistics(self, batch): + """ + Run a statistical test on each latent in a batch to see how + close to normal each latent is. + """ + from scipy import stats + batch = batch['samples'] + batch_size = batch.shape[0] + p_values = [] + means = [] + std_devs = [] + for i in trange(batch.shape[0]): + tensor_1d = batch[i].flatten() + numpy_array = tensor_1d.numpy() + (_, p) = stats.shapiro(numpy_array) + p_values.append(p) + means.append(numpy_array.mean()) + std_devs.append(numpy_array.std()) + (fig, axs) = plt.subplots(3, 1, figsize=(10, 15)) + axs[0].plot(p_values, label='p-values', marker='o', linestyle='-') + axs[0].set_title('Shapiro-Wilk Test P-Values') + axs[0].set_xlabel('Batch Number') + axs[0].set_ylabel('P-Value') + axs[0].axhline(y=0.05, color='r', linestyle='--', label='Normal Threshold') + axs[0].legend() + axs[1].plot(means, marker='o', linestyle='-') + axs[1].set_title('Mean of Each Batch Latent') + axs[1].set_xlabel('Batch Number') + axs[1].set_ylabel('Mean') + axs[2].plot(std_devs, marker='o', linestyle='-') + axs[2].set_title('Standard Deviation of Each Batch Latent') + axs[2].set_xlabel('Batch Number') + axs[2].set_ylabel('Standard Deviation') + plt.tight_layout() + buf = io.BytesIO() + plt.savefig(buf, format='png') + buf.seek(0) + pil_image = Image.open(buf) + image_tensor = pil2tensor(pil_image) + batch_output = image_tensor.unsqueeze(0) + return batch_output +``` \ No newline at end of file diff --git a/docs/Latent Batch.md b/docs/Latent Batch.md new file mode 100644 index 0000000..3c791f4 --- /dev/null +++ b/docs/Latent Batch.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: WAS_Latent_Batch +- Category: WAS Suite/Latent +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Latent_Batch节点旨在将多个潜在张量组合在一起,确保它们具有相同的维度。它在管理和组织潜在空间表示方面发挥着关键作用,使得在各种应用中高效处理潜在数据成为可能。 + +# Input types +## Optional +- latent_a + - 参数'latent_a'是一个可选输入,代表一个潜在张量。它对于节点正确运行很重要,因为它有助于潜在表示的批量处理。参数的存在影响节点处理和生成一致潜在批量的能力。 + - Comfy dtype: LATENT + - Python dtype: Union[torch.Tensor, None] +- latent_b + - 参数'latent_b'的作用与'latent_a'类似,允许在批量中包含另一个潜在张量。它增强了节点处理多种潜在向量的能力,这对于全面潜在空间分析至关重要。 + - Comfy dtype: LATENT + - Python dtype: Union[torch.Tensor, None] +- latent_c + - 参数'latent_c'是另一个可选的潜在张量,可以包含在批量中。它的包含为节点提供了额外的灵活性,以适应不同的潜在结构,这对于复杂的潜在空间操作至关重要。 + - Comfy dtype: LATENT + - Python dtype: Union[torch.Tensor, None] +- latent_d + - 参数'latent_d'为节点提供了进一步的灵活性,以在批量中处理更多的潜在张量。当需要一起处理更多的潜在表示时,它特别有用。 + - Comfy dtype: LATENT + - Python dtype: Union[torch.Tensor, None] + +# Output types +- latent + - 输出'latent'是一个批量张量,将所有输入的潜在张量整合成单一结构。它很重要,因为它允许对组合的潜在表示进行流线型处理和分析。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Latent_Batch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'latent_a': ('LATENT',), 'latent_b': ('LATENT',), 'latent_c': ('LATENT',), 'latent_d': ('LATENT',)}} + RETURN_TYPES = ('LATENT',) + RETURN_NAMES = ('latent',) + FUNCTION = 'latent_batch' + CATEGORY = 'WAS Suite/Latent' + + def _check_latent_dimensions(self, tensors, names): + dimensions = [tensor['samples'].shape for tensor in tensors] + if len(set(dimensions)) > 1: + mismatched_indices = [i for (i, dim) in enumerate(dimensions) if dim[1] != dimensions[0][1]] + mismatched_latents = [names[i] for i in mismatched_indices] + if mismatched_latents: + raise ValueError(f'WAS latent Batch Warning: Input latent dimensions do not match for latents: {mismatched_latents}') + + def latent_batch(self, **kwargs): + batched_tensors = [kwargs[key] for key in kwargs if kwargs[key] is not None] + latent_names = [key for key in kwargs if kwargs[key] is not None] + if not batched_tensors: + raise ValueError('At least one input latent must be provided.') + self._check_latent_dimensions(batched_tensors, latent_names) + samples_out = {} + samples_out['samples'] = torch.cat([tensor['samples'] for tensor in batched_tensors], dim=0) + samples_out['batch_index'] = [] + for tensor in batched_tensors: + cindex = tensor.get('batch_index', list(range(tensor['samples'].shape[0]))) + samples_out['batch_index'] += cindex + return (samples_out,) +``` \ No newline at end of file diff --git a/docs/Latent Input Switch.md b/docs/Latent Input Switch.md new file mode 100644 index 0000000..28e2f9c --- /dev/null +++ b/docs/Latent Input Switch.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: WAS_Latent_Input_Switch +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Latent_Input_Switch节点的'latent_input_switch'方法旨在根据布尔标志有条件地选择两个潜在表示中的一个。它作为一个逻辑开关,用于在神经网络流水线中引导潜在数据的流向,允许对不同模型架构的输入进行灵活的操作。 + +# Input types +## Required +- latent_a + - 参数'latent_a'表示要有条件选择的潜在表示之一。它在节点的操作中起着关键作用,因为它决定了布尔标志为真时的输出,从而影响后续的处理步骤。 + - Comfy dtype: LATENT + - Python dtype: Union[torch.Tensor, np.ndarray] +- latent_b + - 参数'latent_b'是另一个潜在表示,如果布尔标志为假,则需要选择它。它对节点的功能至关重要,因为它在指定条件下决定了输出,指导了随后的神经网络操作。 + - Comfy dtype: LATENT + - Python dtype: Union[torch.Tensor, np.ndarray] +## Optional +- boolean + - 参数'boolean'作为节点决策过程的控制信号。它的重要性在于它直接影响选择哪个潜在表示,从而影响神经网络的整体行为。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- latent_output + - 'latent_output'代表根据提供给节点的布尔标志选择的潜在表示。它是节点操作的最终结果,对神经网络中的进一步处理至关重要。 + - Comfy dtype: LATENT + - Python dtype: Union[torch.Tensor, np.ndarray] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Latent_Input_Switch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'latent_a': ('LATENT',), 'latent_b': ('LATENT',), 'boolean': ('BOOLEAN', {'forceInput': True})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'latent_input_switch' + CATEGORY = 'WAS Suite/Logic' + + def latent_input_switch(self, latent_a, latent_b, boolean=True): + if boolean: + return (latent_a,) + else: + return (latent_b,) +``` \ No newline at end of file diff --git a/docs/Latent Lerp (mtb).md b/docs/Latent Lerp (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Latent Noise Injection.md b/docs/Latent Noise Injection.md new file mode 100644 index 0000000..5d0310d --- /dev/null +++ b/docs/Latent Noise Injection.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: WAS_Latent_Noise +- Category: WAS Suite/Latent/Generate +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +“inject_noise”方法旨在向一组潜在样本中引入随机噪声,增强生成输出的多样性。此方法对于需要在潜在空间中引入随机变化以模拟现实世界数据分布的应用至关重要。 + +# Input types +## Required +- samples + - “samples”参数是一个关键输入,代表将要注入噪声的潜在空间向量。它是节点执行的关键,因为它决定了将要应用随机变化的基础。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +## Optional +- noise_std + - “noise_std”参数决定了要添加到样本中的噪声的标准差。这是一个可选参数,允许用户控制引入潜在空间的随机性程度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- samples + - 输出的“samples”是注入了噪声的修改后的潜在空间向量。这个输出很重要,因为它构成了工作流中后续处理或生成步骤的基础。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Latent_Noise: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'samples': ('LATENT',), 'noise_std': ('FLOAT', {'default': 0.1, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'inject_noise' + CATEGORY = 'WAS Suite/Latent/Generate' + + def inject_noise(self, samples, noise_std): + s = samples.copy() + noise = torch.randn_like(s['samples']) * noise_std + s['samples'] = s['samples'] + noise + return (s,) +``` \ No newline at end of file diff --git a/docs/Latent Size to Number.md b/docs/Latent Size to Number.md new file mode 100644 index 0000000..db1da99 --- /dev/null +++ b/docs/Latent Size to Number.md @@ -0,0 +1,63 @@ +# Documentation +- Class name: WAS_Latent_Size_To_Number +- Category: WAS Suite/Number/Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Latent_Size_To_Number节点的'latent_width_height'方法旨在从给定的张量中提取并提供宽度和高度维度,该张量表示潜在空间数据。这对于需要空间维度以进行进一步处理或分析的操作在WAS套件中至关重要。 + +# Input types +## Required +- samples + - “samples”参数至关重要,因为它作为包含潜在空间数据的输入张量。节点依赖此张量来计算宽度和高度维度,这对于后续的数值操作或分析至关重要。 + - Comfy dtype: LATENT + - Python dtype: Union[torch.Tensor] + +# Output types +- tensor_w_num + - “tensor_w_num”输出参数代表输入张量空间维度的宽度。对于需要知道张量宽度以进行进一步处理的应用程序来说,它是重要的。 + - Comfy dtype: INT + - Python dtype: int +- tensor_h_num + - “tensor_h_num”输出参数表示输入张量空间维度的高度。它在需要张量高度以进行后续任务的应用程序中起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- width_float + - “width_float”输出以浮点格式提供输入张量的宽度。这对于需要张量宽度的小数精度的算法来说很有用。 + - Comfy dtype: FLOAT + - Python dtype: float +- height_float + - “height_float”输出以浮点精度提供输入张量的高度。它特别适用于需要张量高度的准确小数表示的应用程序。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Latent_Size_To_Number: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'samples': ('LATENT',)}} + RETURN_TYPES = ('NUMBER', 'NUMBER', 'FLOAT', 'FLOAT', 'INT', 'INT') + RETURN_NAMES = ('tensor_w_num', 'tensor_h_num') + FUNCTION = 'latent_width_height' + CATEGORY = 'WAS Suite/Number/Operations' + + def latent_width_height(self, samples): + size_dict = {} + i = 0 + for tensor in samples['samples'][0]: + if not isinstance(tensor, torch.Tensor): + cstr(f'Input should be a torch.Tensor').error.print() + shape = tensor.shape + tensor_height = shape[-2] + tensor_width = shape[-1] + size_dict.update({i: [tensor_width, tensor_height]}) + return (size_dict[0][0], size_dict[0][1], float(size_dict[0][0]), float(size_dict[0][1]), size_dict[0][0], size_dict[0][1]) +``` \ No newline at end of file diff --git a/docs/Latent Upscale by Factor (WAS).md b/docs/Latent Upscale by Factor (WAS).md new file mode 100644 index 0000000..c69b4fa --- /dev/null +++ b/docs/Latent Upscale by Factor (WAS).md @@ -0,0 +1,68 @@ +# Documentation +- Class name: WAS_Latent_Upscale +- Category: WAS Suite/Latent/Transform +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +`latent_upscale` 方法旨在通过应用指定的插值模式和缩放因子来增强潜在表示的分辨率。它在 WAS 套件的转换过程中扮演着关键角色,确保潜在特征被准确高效地放大,从而有助于提高生成输出的整体质量。 + +# Input types +## Required +- samples + - “samples”参数至关重要,因为它保存了要放大的潜在表示。它直接影响节点的操作,通过确定要进行放大的输入数据。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- mode + - “mode”参数定义了用于放大的插值方法。它至关重要,因为它决定了提高分辨率的算法方法,从而影响最终输出的质量。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- factor + - “factor”参数指定了放大操作的缩放因子。它是转换过程中的关键决定因素,因为它控制了应用于潜在样本的放大程度。 + - Comfy dtype: FLOAT + - Python dtype: float +- align + - “align”参数很重要,因为它决定是否使用角对齐缩放。这个选择可以对最终放大的表示产生微妙但可观察的效果。 + - Comfy dtype: COMBO[bool] + - Python dtype: bool + +# Output types +- upscaled_samples + - “upscaled_samples”输出包含由转换产生的放大的潜在表示。它很重要,因为它代表了节点操作的直接结果,包含了放大后的特征。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WAS_Latent_Upscale: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'samples': ('LATENT',), 'mode': (['area', 'bicubic', 'bilinear', 'nearest'],), 'factor': ('FLOAT', {'default': 2.0, 'min': 0.1, 'max': 8.0, 'step': 0.01}), 'align': (['true', 'false'],)}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'latent_upscale' + CATEGORY = 'WAS Suite/Latent/Transform' + + def latent_upscale(self, samples, mode, factor, align): + valid_modes = ['area', 'bicubic', 'bilinear', 'nearest'] + if mode not in valid_modes: + cstr(f"Invalid interpolation mode `{mode}` selected. Valid modes are: {', '.join(valid_modes)}").error.print() + return (s,) + align = True if align == 'true' else False + if not isinstance(factor, float) or factor <= 0: + cstr(f'The input `factor` is `{factor}`, but should be a positive or negative float.').error.print() + return (s,) + s = samples.copy() + shape = s['samples'].shape + size = tuple((int(round(dim * factor)) for dim in shape[-2:])) + if mode in ['linear', 'bilinear', 'bicubic', 'trilinear']: + s['samples'] = torch.nn.functional.interpolate(s['samples'], size=size, mode=mode, align_corners=align) + else: + s['samples'] = torch.nn.functional.interpolate(s['samples'], size=size, mode=mode) + return (s,) +``` \ No newline at end of file diff --git a/docs/LatentBatchSplitter %2F%2FInspire.md b/docs/LatentBatchSplitter %2F%2FInspire.md new file mode 100644 index 0000000..2ae273f --- /dev/null +++ b/docs/LatentBatchSplitter %2F%2FInspire.md @@ -0,0 +1,63 @@ +# Documentation +- Class name: LatentBatchSplitter +- Category: InspirePack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在将一批潜在表示分割成多个子集,以便于数据处理和模型训练中的多样化应用。它通过使单一输入生成多样化的数据集,增强了潜在空间探索的灵活性,这对于生成多样化输出或以受控方式扩充数据集等任务至关重要。 + +# Input types +## Required +- latent + - ‘latent’参数至关重要,因为它提供了将由节点处理的初始潜在表示批次。它是所有后续操作的基础,使节点能够执行其预期功能,即分割和重组数据。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +## Optional +- split_count + - ‘split_count’参数规定了将潜在批次划分为所需子集的数量。它在确定输出的粒度方面起着关键作用,并且可以显著影响生成数据集的多样性和分布。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- latent + - 输出‘latent’代表重新组织的潜在表示批次,现在结构化为指定数量的子集。这个输出对于依赖分区数据的下游过程至关重要,如模型训练或多样化内容的生成。 + - Comfy dtype: LATENT + - Python dtype: List[Dict[str, torch.Tensor]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LatentBatchSplitter: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latent': ('LATENT',), 'split_count': ('INT', {'default': 4, 'min': 0, 'max': 50, 'step': 1})}} + RETURN_TYPES = ByPassTypeTuple(('LATENT',)) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Util' + + def doit(self, latent, split_count): + samples = latent['samples'] + latent_base = latent.copy() + del latent_base['samples'] + cnt = min(split_count, len(samples)) + res = [] + for single_samples in samples[:cnt]: + item = latent_base.copy() + item['samples'] = single_samples.unsqueeze(0) + res.append(item) + if split_count >= len(samples): + lack_cnt = split_count - cnt + 1 + item = latent_base.copy() + item['samples'] = empty_latent() + for x in range(0, lack_cnt): + res.append(item) + elif cnt < len(samples): + remained_cnt = len(samples) - cnt + remained_latent = latent_base.copy() + remained_latent['samples'] = samples[-remained_cnt:] + res.append(remained_latent) + return tuple(res) +``` \ No newline at end of file diff --git a/docs/LatentKeyframe.md b/docs/LatentKeyframe.md new file mode 100644 index 0000000..a94d592 --- /dev/null +++ b/docs/LatentKeyframe.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: LatentKeyframeNode +- Category: Adv-ControlNet 🛂🅐🅒🅝/keyframes +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +该节点旨在在控制网络中管理和操作关键帧,专注于基于批次索引和强度参数集成新的键帧。它便于组织和流动关键帧数据,确保控制网络的顺畅运作。 + +# Input types +## Required +- batch_index + - 批次索引是一个关键参数,它决定了关键帧在批处理过程中的位置。对于节点正确组织和引用关键帧至关重要,确保系统内准确的数据流和同步。 + - Comfy dtype: INT + - Python dtype: int +- strength + - 强度参数影响关键帧对整个控制网络影响的权重。它在决定关键帧对最终输出的影响程度方面非常重要,因此在节点的功能中扮演了关键角色。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- prev_latent_kf + - 该参数代表之前的一组关键帧,节点用它来构建并整合新的关键帧。它对于保持控制网络操作中的连续性和一致性很重要。 + - Comfy dtype: LATENT_KEYFRAME + - Python dtype: LatentKeyframeGroup + +# Output types +- LATENT_KF + - 输出是包含新添加关键帧的更新后的关键帧组。这一点很重要,因为它代表了控制网络的进展,反映了通过节点操作所做的更改和调整。 + - Comfy dtype: LATENT_KEYFRAME + - Python dtype: LatentKeyframeGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LatentKeyframeNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'batch_index': ('INT', {'default': 0, 'min': BIGMIN, 'max': BIGMAX, 'step': 1}), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001})}, 'optional': {'prev_latent_kf': ('LATENT_KEYFRAME',)}} + RETURN_NAMES = ('LATENT_KF',) + RETURN_TYPES = ('LATENT_KEYFRAME',) + FUNCTION = 'load_keyframe' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/keyframes' + + def load_keyframe(self, batch_index: int, strength: float, prev_latent_kf: LatentKeyframeGroup=None, prev_latent_keyframe: LatentKeyframeGroup=None): + prev_latent_keyframe = prev_latent_keyframe if prev_latent_keyframe else prev_latent_kf + if not prev_latent_keyframe: + prev_latent_keyframe = LatentKeyframeGroup() + else: + prev_latent_keyframe = prev_latent_keyframe.clone() + keyframe = LatentKeyframe(batch_index, strength) + prev_latent_keyframe.add(keyframe) + return (prev_latent_keyframe,) +``` \ No newline at end of file diff --git a/docs/LatentKeyframeBatchedGroup.md b/docs/LatentKeyframeBatchedGroup.md new file mode 100644 index 0000000..48eceaa --- /dev/null +++ b/docs/LatentKeyframeBatchedGroup.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: LatentKeyframeBatchedGroupNode +- Category: Adv-ControlNet 🛂🅐🅒🅝/keyframes +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +LatentKeyframeBatchedGroupNode 旨在管理和创建一批具有不同强度的潜在关键帧。它允许整合之前的潜在关键帧,并提供打印关键帧详细信息的功能。此节点在 ControlNet 框架内关键帧的生成和操作中扮演着关键角色。 + +# Input types +## Required +- float_strengths + - 'float_strengths' 参数对于确定批量中每个关键帧的强度至关重要。它可以是一个单独的浮点数或浮点数的可迭代对象,直接影响节点内关键帧的创建。 + - Comfy dtype: FLOAT + - Python dtype: Union[float, List[float]] +## Optional +- prev_latent_kf + - 'prev_latent_kf' 参数允许将之前的潜在关键帧组整合到当前操作中。这对于在现有关键帧结构的基础上构建特别有用。 + - Comfy dtype: LATENT_KEYFRAME + - Python dtype: Optional[LatentKeyframeGroup] +- print_keyframes + - 'print_keyframes' 参数设置为 True 时,将启用关键帧信息的日志记录。这对于调试和理解关键帧通过节点的流程非常有帮助。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- LATENT_KF + - 'LATENT_KF' 输出代表了处理输入强度并整合任何之前的关键帧后得到的潜在关键帧批量。这是 ControlNet 系统中进一步处理的关键输出。 + - Comfy dtype: LATENT_KEYFRAME + - Python dtype: LatentKeyframeGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LatentKeyframeBatchedGroupNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'float_strengths': ('FLOAT', {'default': -1, 'min': -1, 'step': 0.001, 'forceInput': True})}, 'optional': {'prev_latent_kf': ('LATENT_KEYFRAME',), 'print_keyframes': ('BOOLEAN', {'default': False})}} + RETURN_NAMES = ('LATENT_KF',) + RETURN_TYPES = ('LATENT_KEYFRAME',) + FUNCTION = 'load_keyframe' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/keyframes' + + def load_keyframe(self, float_strengths: Union[float, list[float]], prev_latent_kf: LatentKeyframeGroup=None, prev_latent_keyframe: LatentKeyframeGroup=None, print_keyframes=False): + prev_latent_keyframe = prev_latent_keyframe if prev_latent_keyframe else prev_latent_kf + if not prev_latent_keyframe: + prev_latent_keyframe = LatentKeyframeGroup() + else: + prev_latent_keyframe = prev_latent_keyframe.clone() + curr_latent_keyframe = LatentKeyframeGroup() + if type(float_strengths) in (float, int): + logger.info('No batched float_strengths passed into Latent Keyframe Batch Group node; will not create any new keyframes.') + elif isinstance(float_strengths, Iterable): + for (idx, strength) in enumerate(float_strengths): + keyframe = LatentKeyframe(idx, strength) + curr_latent_keyframe.add(keyframe) + else: + raise ValueError(f'Expected strengths to be an iterable input, but was {type(float_strengths).__repr__}.') + if print_keyframes: + for keyframe in curr_latent_keyframe.keyframes: + logger.info(f'keyframe {keyframe.batch_index}:{keyframe.strength}') + for latent_keyframe in prev_latent_keyframe.keyframes: + curr_latent_keyframe.add(latent_keyframe) + return (curr_latent_keyframe,) +``` \ No newline at end of file diff --git a/docs/LatentKeyframeGroup.md b/docs/LatentKeyframeGroup.md new file mode 100644 index 0000000..ce31ba6 --- /dev/null +++ b/docs/LatentKeyframeGroup.md @@ -0,0 +1,123 @@ +# Documentation +- Class name: LatentKeyframeGroupNode +- Category: Adv-ControlNet 🛂🅐🅒🅝/keyframes +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +LatentKeyframeGroupNode的load_keyframes方法旨在根据提供的索引强度处理和组织潜在的关键帧。它考虑了先前的潜在关键帧组和可选的潜在参数来构建一个新的关键帧组。该方法在控制网络中管理潜在空间操作的复杂性方面至关重要,确保了关键帧处理的连贯性和结构化方法。 + +# Input types +## Required +- index_strengths + - index_strengths参数是一个字符串,定义了组内潜在关键帧的分布和强度。它对于确定关键帧如何影响潜在空间至关重要,对节点的运行至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- prev_latent_kf + - prev_latent_kf参数是一个可选的LatentKeyframeGroup,它为当前关键帧组提供了上下文。它对于保持潜在空间操作的连续性和一致性具有重要意义。 + - Comfy dtype: LATENT_KEYFRAME + - Python dtype: LatentKeyframeGroup +- latent_optional + - latent_optional参数是一个可选的潜在表示,可用于进一步细化关键帧组。它在微调潜在空间调整中发挥作用。 + - Comfy dtype: LATENT + - Python dtype: Union[Tensor, None] +- print_keyframes + - print_keyframes参数是一个布尔标志,设置为True时启用关键帧信息的记录。这对于调试和理解节点的操作非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- LATENT_KF + - load_keyframes方法的输出是一个LatentKeyframeGroup,它封装了处理后的关键帧。这个组对于进一步的下游处理很重要,并且代表了节点操作的结构化输出。 + - Comfy dtype: LATENT_KEYFRAME + - Python dtype: LatentKeyframeGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LatentKeyframeGroupNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'index_strengths': ('STRING', {'multiline': True, 'default': ''})}, 'optional': {'prev_latent_kf': ('LATENT_KEYFRAME',), 'latent_optional': ('LATENT',), 'print_keyframes': ('BOOLEAN', {'default': False})}} + RETURN_NAMES = ('LATENT_KF',) + RETURN_TYPES = ('LATENT_KEYFRAME',) + FUNCTION = 'load_keyframes' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/keyframes' + + def validate_index(self, index: int, latent_count: int=0, is_range: bool=False, allow_negative=False) -> int: + if is_range: + return index + if latent_count > 0 and index > latent_count - 1: + raise IndexError(f"Index '{index}' out of range for the total {latent_count} latents.") + if index < 0: + if not allow_negative: + raise IndexError(f'Negative indeces not allowed, but was {index}.') + conv_index = latent_count + index + if conv_index < 0: + raise IndexError(f"Index '{index}', converted to '{conv_index}' out of range for the total {latent_count} latents.") + index = conv_index + return index + + def convert_to_index_int(self, raw_index: str, latent_count: int=0, is_range: bool=False, allow_negative=False) -> int: + try: + return self.validate_index(int(raw_index), latent_count=latent_count, is_range=is_range, allow_negative=allow_negative) + except ValueError as e: + raise ValueError(f"index '{raw_index}' must be an integer.", e) + + def convert_to_latent_keyframes(self, latent_indeces: str, latent_count: int) -> set[LatentKeyframe]: + if not latent_indeces: + return set() + int_latent_indeces = [i for i in range(0, latent_count)] + allow_negative = latent_count > 0 + chosen_indeces = set() + groups = latent_indeces.split(',') + groups = [g.strip() for g in groups] + for g in groups: + strength = 1.0 + if '=' in g: + (g, strength_str) = g.split('=', 1) + g = g.strip() + try: + strength = float(strength_str.strip()) + except ValueError as e: + raise ValueError(f"strength '{strength_str}' must be a float.", e) + if strength < 0: + raise ValueError(f"Strength '{strength}' cannot be negative.") + if ':' in g: + index_range = g.split(':', 1) + index_range = [r.strip() for r in index_range] + start_index = self.convert_to_index_int(index_range[0], latent_count=latent_count, is_range=True, allow_negative=allow_negative) + end_index = self.convert_to_index_int(index_range[1], latent_count=latent_count, is_range=True, allow_negative=allow_negative) + if len(int_latent_indeces) > 0: + for i in int_latent_indeces[start_index:end_index]: + chosen_indeces.add(LatentKeyframe(i, strength)) + else: + for i in range(start_index, end_index): + chosen_indeces.add(LatentKeyframe(i, strength)) + else: + chosen_indeces.add(LatentKeyframe(self.convert_to_index_int(g, latent_count=latent_count, allow_negative=allow_negative), strength)) + return chosen_indeces + + def load_keyframes(self, index_strengths: str, prev_latent_kf: LatentKeyframeGroup=None, prev_latent_keyframe: LatentKeyframeGroup=None, latent_image_opt=None, print_keyframes=False): + prev_latent_keyframe = prev_latent_keyframe if prev_latent_keyframe else prev_latent_kf + if not prev_latent_keyframe: + prev_latent_keyframe = LatentKeyframeGroup() + else: + prev_latent_keyframe = prev_latent_keyframe.clone() + curr_latent_keyframe = LatentKeyframeGroup() + latent_count = -1 + if latent_image_opt: + latent_count = latent_image_opt['samples'].size()[0] + latent_keyframes = self.convert_to_latent_keyframes(index_strengths, latent_count=latent_count) + for latent_keyframe in latent_keyframes: + curr_latent_keyframe.add(latent_keyframe) + if print_keyframes: + for keyframe in curr_latent_keyframe.keyframes: + logger.info(f'keyframe {keyframe.batch_index}:{keyframe.strength}') + for latent_keyframe in prev_latent_keyframe.keyframes: + curr_latent_keyframe.add(latent_keyframe) + return (curr_latent_keyframe,) +``` \ No newline at end of file diff --git a/docs/LatentKeyframeTiming.md b/docs/LatentKeyframeTiming.md new file mode 100644 index 0000000..3c18eb3 --- /dev/null +++ b/docs/LatentKeyframeTiming.md @@ -0,0 +1,95 @@ +# Documentation +- Class name: LatentKeyframeInterpolationNode +- Category: Adv-ControlNet 🛂🅐🅒🅝/keyframes +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +LatentKeyframeInterpolationNode 旨在在潜在空间中对关键帧进行插值,允许在生成过程中进行平滑过渡。它通过根据指定的强度和插值方法(可以是线性或各种缓动函数)计算中间关键帧来实现这一点。该节点在增强潜在表示生成的流畅性和控制方面发挥着关键作用。 + +# Input types +## Required +- batch_index_from + - 插值开始的批次索引,定义了关键帧序列中的初始位置。这对于确定过渡的起始点至关重要。 + - Comfy dtype: INT + - Python dtype: int +- strength_from + - 起始关键帧处的强度值,它影响插值过程中初始状态的强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_index_to_excl + - 计算插值的批次索引,不包括索引本身,定义序列的结束位置。 + - Comfy dtype: INT + - Python dtype: int +- strength_to + - 结束关键帧处的强度值,确定插值后最终状态的强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- interpolation + - 在关键帧之间使用的插值类型,可以是线性的或者是一个缓动函数,以实现更自然的过渡。 + - Comfy dtype: COMBO[LINEAR, EASE_IN, EASE_OUT, EASE_IN_OUT] + - Python dtype: str +## Optional +- prev_latent_kf + - 一个可选的先前的潜在关键帧组,它为插值提供上下文,允许更有信息量的生成过程。 + - Comfy dtype: LATENT_KEYFRAME + - Python dtype: LatentKeyframeGroup +- print_keyframes + - 一个布尔标志,当设置为 true 时,将打印生成的关键帧的详细信息,用于调试目的。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- LATENT_KF + - 生成的插值潜在关键帧组,代表初始和最终状态之间的过渡。 + - Comfy dtype: LATENT_KEYFRAME + - Python dtype: LatentKeyframeGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LatentKeyframeInterpolationNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'batch_index_from': ('INT', {'default': 0, 'min': BIGMIN, 'max': BIGMAX, 'step': 1}), 'batch_index_to_excl': ('INT', {'default': 0, 'min': BIGMIN, 'max': BIGMAX, 'step': 1}), 'strength_from': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'strength_to': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'interpolation': ([SI.LINEAR, SI.EASE_IN, SI.EASE_OUT, SI.EASE_IN_OUT],)}, 'optional': {'prev_latent_kf': ('LATENT_KEYFRAME',), 'print_keyframes': ('BOOLEAN', {'default': False})}} + RETURN_NAMES = ('LATENT_KF',) + RETURN_TYPES = ('LATENT_KEYFRAME',) + FUNCTION = 'load_keyframe' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/keyframes' + + def load_keyframe(self, batch_index_from: int, strength_from: float, batch_index_to_excl: int, strength_to: float, interpolation: str, prev_latent_kf: LatentKeyframeGroup=None, prev_latent_keyframe: LatentKeyframeGroup=None, print_keyframes=False): + if batch_index_from > batch_index_to_excl: + raise ValueError('batch_index_from must be less than or equal to batch_index_to.') + if batch_index_from < 0 and batch_index_to_excl >= 0: + raise ValueError('batch_index_from and batch_index_to must be either both positive or both negative.') + prev_latent_keyframe = prev_latent_keyframe if prev_latent_keyframe else prev_latent_kf + if not prev_latent_keyframe: + prev_latent_keyframe = LatentKeyframeGroup() + else: + prev_latent_keyframe = prev_latent_keyframe.clone() + curr_latent_keyframe = LatentKeyframeGroup() + steps = batch_index_to_excl - batch_index_from + diff = strength_to - strength_from + if interpolation == SI.LINEAR: + weights = np.linspace(strength_from, strength_to, steps) + elif interpolation == SI.EASE_IN: + index = np.linspace(0, 1, steps) + weights = diff * np.power(index, 2) + strength_from + elif interpolation == SI.EASE_OUT: + index = np.linspace(0, 1, steps) + weights = diff * (1 - np.power(1 - index, 2)) + strength_from + elif interpolation == SI.EASE_IN_OUT: + index = np.linspace(0, 1, steps) + weights = diff * ((1 - np.cos(index * np.pi)) / 2) + strength_from + for i in range(steps): + keyframe = LatentKeyframe(batch_index_from + i, float(weights[i])) + curr_latent_keyframe.add(keyframe) + if print_keyframes: + for keyframe in curr_latent_keyframe.keyframes: + logger.info(f'keyframe {keyframe.batch_index}:{keyframe.strength}') + for latent_keyframe in prev_latent_keyframe.keyframes: + curr_latent_keyframe.add(latent_keyframe) + return (curr_latent_keyframe,) +``` \ No newline at end of file diff --git a/docs/LatentPixelScale.md b/docs/LatentPixelScale.md new file mode 100644 index 0000000..e7d0df9 --- /dev/null +++ b/docs/LatentPixelScale.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: LatentPixelScale +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +LatentPixelScale节点旨在将图像的潜在表示上采样到更高分辨率。它通过应用各种缩放方法和因子来增强潜在图像的细节和清晰度。该节点在图像处理流程中扮演着关键角色,使得从低分辨率潜在状态创建高分辨率图像成为可能。 + +# Input types +## Required +- samples + - 参数'samples'至关重要,因为它代表了要上采样的图像的潜在表示。它是影响节点操作和上采样输出质量的主要输入。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- scale_method + - 参数'scale_method'决定了用于上采样潜在图像的算法。这是一个关键的选择,它影响着上采样图像的最终外观和性能。 + - Comfy dtype: COMBO['nearest-exact', 'bilinear', 'lanczos', 'area'] + - Python dtype: str +- scale_factor + - 参数'scale_factor'定义了潜在图像上采样的程度。它是控制图像放大倍数和最终分辨率的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- vae + - 参数'vae'是一个变分自编码器模型,用于解码和编码潜在表示。它对节点的功能至关重要,确保了上采样过程中图像的完整性。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +## Optional +- use_tiled_vae + - 参数'use_tiled_vae'指示节点是否应该使用平铺方法来解码和编码潜在表示。这可以提高大图像的效率。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- upscale_model_opt + - 可选参数'upscale_model_opt'允许指定在上采样过程中使用的自定义模型。它为希望应用特定上采样技术的高级用户提供了灵活性。 + - Comfy dtype: UPSCALE_MODEL + - Python dtype: torch.nn.Module + +# Output types +- latent + - 输出'latent'代表了输入图像的上采样潜在表示。它很重要,因为它保留了通过上采样过程实现的增强细节和分辨率。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- image + - 输出'image'是上采样潜在图像的视觉表示。它是节点的最终产品,以人类可读的格式展示了上采样过程的结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LatentPixelScale: + upscale_methods = ['nearest-exact', 'bilinear', 'lanczos', 'area'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'samples': ('LATENT',), 'scale_method': (s.upscale_methods,), 'scale_factor': ('FLOAT', {'default': 1.5, 'min': 0.1, 'max': 10000, 'step': 0.1}), 'vae': ('VAE',), 'use_tiled_vae': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'})}, 'optional': {'upscale_model_opt': ('UPSCALE_MODEL',)}} + RETURN_TYPES = ('LATENT', 'IMAGE') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + def doit(self, samples, scale_method, scale_factor, vae, use_tiled_vae, upscale_model_opt=None): + if upscale_model_opt is None: + latimg = core.latent_upscale_on_pixel_space2(samples, scale_method, scale_factor, vae, use_tile=use_tiled_vae) + else: + latimg = core.latent_upscale_on_pixel_space_with_model2(samples, scale_method, upscale_model_opt, scale_factor, vae, use_tile=use_tiled_vae) + return latimg +``` \ No newline at end of file diff --git a/docs/LatentReceiver.md b/docs/LatentReceiver.md new file mode 100644 index 0000000..0b20112 --- /dev/null +++ b/docs/LatentReceiver.md @@ -0,0 +1,120 @@ +# Documentation +- Class name: LatentReceiver +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +LatentReceiver节点的'doit'方法负责处理潜在数据。它以潜在文件为输入,并输出表示潜在空间的张量。该节点对于处理潜在表示的转换和加载至关重要,这对于各种机器学习任务是必不可少的。 + +# Input types +## Required +- latent + - 参数'latent'是潜在文件的文件路径,节点将处理该路径。它对节点的操作至关重要,因为它决定了要加载和用于后续计算的具体潜在数据。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- link_id + - 参数'link_id'是用于跟踪或链接潜在数据的标识符。虽然不是必需的,但在更大的系统或工作流程中组织或引用数据时可能会很有用。 + - Comfy dtype: INT + - Python dtype: int +- trigger_always + - 参数'trigger_always'是一个布尔标志,当设置为true时,表示节点应始终触发其过程,而不考虑输入数据中的变化。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- result + - 输出'result'是一个张量,代表处理后的潜在数据。它是节点的主要输出,并用于进一步分析或作为工作流中其他节点的输入。 + - Comfy dtype: TENSOR + - Python dtype: torch.Tensor +- ui + - 输出'ui'是一个字典,可能包含用于可视化目的的UI元素,如图像。它提供了一种以用户友好的格式呈现处理后数据的方式。 + - Comfy dtype: DICT + - Python dtype: Dict[str, List[str]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LatentReceiver: + + def __init__(self): + self.input_dir = folder_paths.get_input_directory() + self.type = 'input' + + @classmethod + def INPUT_TYPES(s): + + def check_file_extension(x): + return x.endswith('.latent') or x.endswith('.latent.png') + input_dir = folder_paths.get_input_directory() + files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f)) and check_file_extension(f)] + return {'required': {'latent': (sorted(files),), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'trigger_always': ('BOOLEAN', {'default': False, 'label_on': 'enable', 'label_off': 'disable'})}} + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + RETURN_TYPES = ('LATENT',) + + @staticmethod + def load_preview_latent(image_path): + if not os.path.exists(image_path): + return None + image = Image.open(image_path) + exif_data = piexif.load(image.info['exif']) + if piexif.ExifIFD.UserComment in exif_data['Exif']: + compressed_data = exif_data['Exif'][piexif.ExifIFD.UserComment] + compressed_data_io = BytesIO(compressed_data) + with zipfile.ZipFile(compressed_data_io, mode='r') as archive: + tensor_bytes = archive.read('latent') + tensor = safetensors.torch.load(tensor_bytes) + return {'samples': tensor['latent_tensor']} + return None + + def parse_filename(self, filename): + pattern = '^(.*)/(.*?)\\[(.*)\\]\\s*$' + match = re.match(pattern, filename) + if match: + subfolder = match.group(1) + filename = match.group(2).rstrip() + file_type = match.group(3) + else: + subfolder = '' + file_type = self.type + return {'filename': filename, 'subfolder': subfolder, 'type': file_type} + + def doit(self, **kwargs): + if 'latent' not in kwargs: + return (torch.zeros([1, 4, 8, 8]),) + latent = kwargs['latent'] + latent_name = latent + latent_path = folder_paths.get_annotated_filepath(latent_name) + if latent.endswith('.latent'): + latent = safetensors.torch.load_file(latent_path, device='cpu') + multiplier = 1.0 + if 'latent_format_version_0' not in latent: + multiplier = 1.0 / 0.18215 + samples = {'samples': latent['latent_tensor'].float() * multiplier} + else: + samples = LatentReceiver.load_preview_latent(latent_path) + if samples is None: + samples = {'samples': torch.zeros([1, 4, 8, 8])} + preview = self.parse_filename(latent_name) + return {'ui': {'images': [preview]}, 'result': (samples,)} + + @classmethod + def IS_CHANGED(s, latent, link_id, trigger_always): + if trigger_always: + return float('NaN') + else: + image_path = folder_paths.get_annotated_filepath(latent) + m = hashlib.sha256() + with open(image_path, 'rb') as f: + m.update(f.read()) + return m.digest().hex() + + @classmethod + def VALIDATE_INPUTS(s, latent, link_id, trigger_always): + if not folder_paths.exists_annotated_filepath(latent) or latent.startswith('/') or '..' in latent: + return 'Invalid latent file: {}'.format(latent) + return True +``` \ No newline at end of file diff --git a/docs/LatentSender.md b/docs/LatentSender.md new file mode 100644 index 0000000..45660b0 --- /dev/null +++ b/docs/LatentSender.md @@ -0,0 +1,136 @@ +# Documentation +- Class name: LatentSender +- Category: ImpactPack/Util +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +LatentSender节点旨在处理和管理潜在数据,将其转换为适合进一步使用或存储的格式。它在工作流程中扮演着关键角色,确保潜在信息得到正确处理并为下游任务做好准备。 + +# Input types +## Required +- samples + - 'samples'参数至关重要,因为它包含了节点操作的潜在数据。它是主要的输入,决定了节点的处理和输出生成。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +## Optional +- filename_prefix + - 'filename_prefix'参数指定输出文件的前缀,这对于组织和识别保存的潜在数据文件很重要。 + - Comfy dtype: STRING + - Python dtype: str +- link_id + - 'link_id'参数用于将潜在数据与特定链接或过程关联起来,这对于跟踪和管理不同阶段的数据至关重要。 + - Comfy dtype: INT + - Python dtype: int +- preview_method + - 'preview_method'参数决定了在保存之前如何预览潜在数据。它影响数据的视觉表示,并且可以影响用户的理解和交互。 + - Comfy dtype: COMBO['Latent2RGB-SDXL', 'Latent2RGB-SD15', 'TAESDXL', 'TAESD15'] + - Python dtype: str +- prompt + - 'prompt'参数提供了可以用于指导节点内潜在数据处理的附加上下文或指令。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - 'extra_pnginfo'参数允许在潜在数据中包含额外的元数据,丰富与输出文件关联的信息。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, Any] + +# Output types +- ui + - 'ui'输出提供用户界面元素,可用于显示或与节点操作的结果进行交互。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LatentSender(nodes.SaveLatent): + + def __init__(self): + super().__init__() + self.output_dir = folder_paths.get_temp_directory() + self.type = 'temp' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'samples': ('LATENT',), 'filename_prefix': ('STRING', {'default': 'latents/LatentSender'}), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'preview_method': (['Latent2RGB-SDXL', 'Latent2RGB-SD15', 'TAESDXL', 'TAESD15'],)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + OUTPUT_NODE = True + RETURN_TYPES = () + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + @staticmethod + def save_to_file(tensor_bytes, prompt, extra_pnginfo, image, image_path): + compressed_data = BytesIO() + with zipfile.ZipFile(compressed_data, mode='w') as archive: + archive.writestr('latent', tensor_bytes) + image = image.copy() + exif_data = {'Exif': {piexif.ExifIFD.UserComment: compressed_data.getvalue()}} + metadata = PngInfo() + if prompt is not None: + metadata.add_text('prompt', json.dumps(prompt)) + if extra_pnginfo is not None: + for x in extra_pnginfo: + metadata.add_text(x, json.dumps(extra_pnginfo[x])) + exif_bytes = piexif.dump(exif_data) + image.save(image_path, format='png', exif=exif_bytes, pnginfo=metadata, optimize=True) + + @staticmethod + def prepare_preview(latent_tensor, preview_method): + from comfy.cli_args import LatentPreviewMethod + import comfy.latent_formats as latent_formats + lower_bound = 128 + upper_bound = 256 + if preview_method == 'Latent2RGB-SD15': + latent_format = latent_formats.SD15() + method = LatentPreviewMethod.Latent2RGB + elif preview_method == 'TAESD15': + latent_format = latent_formats.SD15() + method = LatentPreviewMethod.TAESD + elif preview_method == 'TAESDXL': + latent_format = latent_formats.SDXL() + method = LatentPreviewMethod.TAESD + else: + latent_format = latent_formats.SDXL() + method = LatentPreviewMethod.Latent2RGB + previewer = core.get_previewer('cpu', latent_format=latent_format, force=True, method=method) + image = previewer.decode_latent_to_preview(latent_tensor) + min_size = min(image.size[0], image.size[1]) + max_size = max(image.size[0], image.size[1]) + scale_factor = 1 + if max_size > upper_bound: + scale_factor = upper_bound / max_size + if min_size * scale_factor < lower_bound: + scale_factor = lower_bound / min_size + w = int(image.size[0] * scale_factor) + h = int(image.size[1] * scale_factor) + image = image.resize((w, h), resample=Image.NEAREST) + return LatentSender.attach_format_text(image) + + @staticmethod + def attach_format_text(image): + (width_a, height_a) = image.size + letter_image = Image.open(latent_letter_path) + (width_b, height_b) = letter_image.size + new_width = max(width_a, width_b) + new_height = height_a + height_b + new_image = Image.new('RGB', (new_width, new_height), (0, 0, 0)) + offset_x = (new_width - width_b) // 2 + offset_y = height_a + (new_height - height_a - height_b) // 2 + new_image.paste(letter_image, (offset_x, offset_y)) + new_image.paste(image, (0, 0)) + return new_image + + def doit(self, samples, filename_prefix='latents/LatentSender', link_id=0, preview_method='Latent2RGB-SDXL', prompt=None, extra_pnginfo=None): + (full_output_folder, filename, counter, subfolder, filename_prefix) = folder_paths.get_save_image_path(filename_prefix, self.output_dir) + preview = LatentSender.prepare_preview(samples['samples'], preview_method) + file = f'{filename}_{counter:05}_.latent.png' + fullpath = os.path.join(full_output_folder, file) + output = {'latent_tensor': samples['samples']} + tensor_bytes = safetensors.torch.save(output) + LatentSender.save_to_file(tensor_bytes, prompt, extra_pnginfo, preview, fullpath) + latent_path = {'filename': file, 'subfolder': subfolder, 'type': self.type} + PromptServer.instance.send_sync('latent-send', {'link_id': link_id, 'images': [latent_path]}) + return {'ui': {'images': [latent_path]}} +``` \ No newline at end of file diff --git a/docs/LatentSwitch.md b/docs/LatentSwitch.md new file mode 100644 index 0000000..3247c9e --- /dev/null +++ b/docs/LatentSwitch.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: GeneralSwitch +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +GeneralSwitch节点旨在根据选择索引管理数据流。它通过评估提供的选项索引来确定活动输入,然后将相应的输入路由到输出。该节点在工作流中的决策过程中发挥关键作用,允许基于用户定义的标准进行条件分支。 + +# Input types +## Required +- select + - “select”参数对于确定将由节点处理的输入至关重要。它指定应视为活动的输入的索引。节点的功能在很大程度上依赖于此参数来执行其决策任务。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- sel_mode + - “sel_mode”参数决定选择是基于提示还是执行上下文进行的。这可以影响节点如何解释选择,进而影响节点的执行流程。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- input1 + - “input1”参数作为可选输入提供给节点。其作用是提供节点数据处理能力的额外灵活性,允许对各种输入场景进行更多样化的处理。 + - Comfy dtype: ANY + - Python dtype: Any +- unique_id + - “unique_id”参数用于在工作流内标识节点。它在节点能够引用其在更大系统中自己的位置和上下文的能力中起着至关重要的作用。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +- extra_pnginfo + - “extra_pnginfo”参数包含节点正常运行可能需要的额外信息。它为节点提供了可以增强其操作能力的特定上下文的详细信息。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, Any] + +# Output types +- selected_value + - “selected_value”输出代表了节点根据提供的选项索引选择的输入值。它是一个关键的输出,因为它携带了将被进一步处理或在工作流下游使用的数据处理。 + - Comfy dtype: ANY + - Python dtype: Any +- selected_label + - “selected_label”输出提供了与选定输入相关联的标签。这对于为选定数据提供人类可读的标识符非常有用,增强了节点输出的可解释性。 + - Comfy dtype: STRING + - Python dtype: str +- selected_index + - “selected_index”输出表明了被选择输入的索引。它作为记录节点决策过程的记录,并可在工作流中用于跟踪或记录目的。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GeneralSwitch: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'select': ('INT', {'default': 1, 'min': 1, 'max': 999999, 'step': 1}), 'sel_mode': ('BOOLEAN', {'default': True, 'label_on': 'select_on_prompt', 'label_off': 'select_on_execution', 'forceInput': False})}, 'optional': {'input1': (any_typ,)}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = (any_typ, 'STRING', 'INT') + RETURN_NAMES = ('selected_value', 'selected_label', 'selected_index') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, *args, **kwargs): + selected_index = int(kwargs['select']) + input_name = f'input{selected_index}' + selected_label = input_name + node_id = kwargs['unique_id'] + nodelist = kwargs['extra_pnginfo']['workflow']['nodes'] + for node in nodelist: + if str(node['id']) == node_id: + inputs = node['inputs'] + for slot in inputs: + if slot['name'] == input_name and 'label' in slot: + selected_label = slot['label'] + break + if input_name in kwargs: + return (kwargs[input_name], selected_label, selected_index) + else: + print(f'ImpactSwitch: invalid select index (ignored)') + return (None, '', selected_index) +``` \ No newline at end of file diff --git a/docs/LayeredDiffusionApply.md b/docs/LayeredDiffusionApply.md new file mode 100644 index 0000000..29032fe --- /dev/null +++ b/docs/LayeredDiffusionApply.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: LayeredDiffusionFG +- Category: layer_diffuse +- Output node: False +- Repo Ref: https://github.com/huchenlei/ComfyUI-layerdiffuse.git + +LayeredDiffusionFG 类旨在通过应用分层扩散过程来增强图像生成任务,有效地生成带有透明背景的前景。该节点与各种模型集成,以实现所需效果,专注于层的无缝集成,以产生高质量的视觉输出。 + +# Input types +## Required +- model + - 模型参数对于 LayeredDiffusionFG 节点至关重要,因为它定义了用于扩散过程的底层架构和参数。它决定了生成图像的质量和特性。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_base.BaseModel +- config + - 配置参数对于指定所选模型对应的配置字符串至关重要。它确保在扩散过程中应用正确的设置,影响最终输出。 + - Comfy dtype: STRING + - Python dtype: str +- weight + - 权重参数影响生成图像上扩散效果的强度。它是控制前景细节与背景透明度之间权衡的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output + - LayeredDiffusionFG 节点的输出是一个已经被扩散层打补丁的修改后的模型。这个模型准备好生成具有所需前景和透明背景特性的图像。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_base.BaseModel + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LayeredDiffusionFG: + """Generate foreground with transparent background.""" + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'config': ([c.config_string for c in s.MODELS],), 'weight': ('FLOAT', {'default': 1.0, 'min': -1, 'max': 3, 'step': 0.05})}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'apply_layered_diffusion' + CATEGORY = 'layer_diffuse' + MODELS = (LayeredDiffusionBase(model_file_name='layer_xl_transparent_attn.safetensors', model_url='https://huggingface.co/LayerDiffusion/layerdiffusion-v1/resolve/main/layer_xl_transparent_attn.safetensors', sd_version=StableDiffusionVersion.SDXL, injection_method=LayerMethod.ATTN), LayeredDiffusionBase(model_file_name='layer_xl_transparent_conv.safetensors', model_url='https://huggingface.co/LayerDiffusion/layerdiffusion-v1/resolve/main/layer_xl_transparent_conv.safetensors', sd_version=StableDiffusionVersion.SDXL, injection_method=LayerMethod.CONV), LayeredDiffusionBase(model_file_name='layer_sd15_transparent_attn.safetensors', model_url='https://huggingface.co/LayerDiffusion/layerdiffusion-v1/resolve/main/layer_sd15_transparent_attn.safetensors', sd_version=StableDiffusionVersion.SD1x, injection_method=LayerMethod.ATTN, attn_sharing=True)) + + def apply_layered_diffusion(self, model: ModelPatcher, config: str, weight: float): + ld_model = [m for m in self.MODELS if m.config_string == config][0] + assert get_model_sd_version(model) == ld_model.sd_version + if ld_model.attn_sharing: + return ld_model.apply_layered_diffusion_attn_sharing(model) + else: + return ld_model.apply_layered_diffusion(model, weight) +``` \ No newline at end of file diff --git a/docs/LayeredDiffusionCondApply.md b/docs/LayeredDiffusionCondApply.md new file mode 100644 index 0000000..0d8f50f --- /dev/null +++ b/docs/LayeredDiffusionCondApply.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: LayeredDiffusionCond +- Category: layer_diffuse +- Output node: False +- Repo Ref: https://github.com/huchenlei/ComfyUI-layerdiffuse.git + +LayeredDiffusionCond节点旨在从前景或背景输入成混合图像。它利用扩散模型的力量在提供的条件下创建无缝混合,增强输出的视觉一致性和细节。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了用于生成混合图像的基础扩散模型。它直接影响节点的性能和输出图像的质量。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- cond + - cond参数代表引导扩散过程朝向特定结果的条件输入。适当选择它对于实现所需的图像特征至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- uncond + - uncond参数作为额外的条件输入,可用于影响扩散过程,允许对最终图像进行更精细的控制。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- latent + - latent参数保存图像的潜在表示,这是扩散模型的输入。它在确定生成过程的初始状态中起着关键作用。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- config + - config参数指定扩散模型的配置设置。对于使模型的行为与所需的生成特征保持一致非常重要。 + - Comfy dtype: STR + - Python dtype: str +- weight + - weight参数调整应用于模型的补丁的影响。它提供了一种微调原始和修改后图像特征之间平衡的方法。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- blended_model + - blended_model输出代表已通过分层扩散过程增强的修改后的扩散模型。它很重要,因为它包含了输入条件的联合效应。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- blended_cond + - blended_cond输出是应用分层扩散后的条件信息的结果。它反映了图像生成过程的更新状态。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- blended_uncond + - blended_uncond输出对应于通过扩散模型处理的额外条件信息。它有助于最终图像的细微特征。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LayeredDiffusionCond: + """Generate foreground + background given background / foreground. + - FG => Blended + - BG => Blended + """ + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'cond': ('CONDITIONING',), 'uncond': ('CONDITIONING',), 'latent': ('LATENT',), 'config': ([c.config_string for c in s.MODELS],), 'weight': ('FLOAT', {'default': 1.0, 'min': -1, 'max': 3, 'step': 0.05})}} + RETURN_TYPES = ('MODEL', 'CONDITIONING', 'CONDITIONING') + FUNCTION = 'apply_layered_diffusion' + CATEGORY = 'layer_diffuse' + MODELS = (LayeredDiffusionBase(model_file_name='layer_xl_fg2ble.safetensors', model_url='https://huggingface.co/LayerDiffusion/layerdiffusion-v1/resolve/main/layer_xl_fg2ble.safetensors', sd_version=StableDiffusionVersion.SDXL, cond_type=LayerType.FG), LayeredDiffusionBase(model_file_name='layer_xl_bg2ble.safetensors', model_url='https://huggingface.co/LayerDiffusion/layerdiffusion-v1/resolve/main/layer_xl_bg2ble.safetensors', sd_version=StableDiffusionVersion.SDXL, cond_type=LayerType.BG)) + + def apply_layered_diffusion(self, model: ModelPatcher, cond, uncond, latent, config: str, weight: float): + ld_model = [m for m in self.MODELS if m.config_string == config][0] + assert get_model_sd_version(model) == ld_model.sd_version + c_concat = model.model.latent_format.process_in(latent['samples']) + return ld_model.apply_layered_diffusion(model, weight) + ld_model.apply_c_concat(cond, uncond, c_concat) +``` \ No newline at end of file diff --git a/docs/LayeredDiffusionCondJointApply.md b/docs/LayeredDiffusionCondJointApply.md new file mode 100644 index 0000000..e9bb28c --- /dev/null +++ b/docs/LayeredDiffusionCondJointApply.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: LayeredDiffusionCondJoint +- Category: layer_diffuse +- Output node: False +- Repo Ref: https://github.com/huchenlei/ComfyUI-layerdiffuse.git + +LayeredDiffusionCondJoint节点旨在将前景和背景元素无缝集成到混合图像中。它通过应用分层扩散技术实现这一点,这允许生成保持前景和背景组件不同特征的复合图像。该节点特别适用于视觉连贯性和不同图像元素现实混合至关重要的应用中。 + +# Input types +## Required +- model + - 模型参数对节点的操作至关重要,因为它定义了用于生成混合图像的基础模型。模型的选择直接影响生成图像的质量和风格。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- image + - 图像输入是必不可少的,因为它提供了将由节点处理并与其他元素混合的视觉内容。输入图像的质量和分辨率显著影响最终输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- config + - 配置字符串参数很重要,因为它指定了将指导扩散过程的设置和选项。它决定了节点将如何混合前景和背景元素。 + - Comfy dtype: str + - Python dtype: str +- cond + - 条件输入在提供时,允许对扩散过程进行额外控制,使节点能够生成更符合特定条件或风格的图像。 + - Comfy dtype: CONDITIONING + - Python dtype: List[List[torch.Tensor]] +- blended_cond + - 混合条件输入用于进一步完善混合过程,确保最终图像满足所需的美学和主题要求。 + - Comfy dtype: CONDITIONING + - Python dtype: List[List[torch.Tensor]] + +# Output types +- model + - 输出模型是扩散过程的结果,代表了根据输入参数指定的结合前景和背景元素的混合图像。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LayeredDiffusionCondJoint: + """Generate fg/bg + blended given fg/bg. + - FG => Blended + BG + - BG => Blended + FG + """ + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'image': ('IMAGE',), 'config': ([c.config_string for c in s.MODELS],)}, 'optional': {'cond': ('CONDITIONING',), 'blended_cond': ('CONDITIONING',)}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'apply_layered_diffusion' + CATEGORY = 'layer_diffuse' + MODELS = (LayeredDiffusionBase(model_file_name='layer_sd15_fg2bg.safetensors', model_url='https://huggingface.co/LayerDiffusion/layerdiffusion-v1/resolve/main/layer_sd15_fg2bg.safetensors', sd_version=StableDiffusionVersion.SD1x, attn_sharing=True, frames=2, cond_type=LayerType.FG), LayeredDiffusionBase(model_file_name='layer_sd15_bg2fg.safetensors', model_url='https://huggingface.co/LayerDiffusion/layerdiffusion-v1/resolve/main/layer_sd15_bg2fg.safetensors', sd_version=StableDiffusionVersion.SD1x, attn_sharing=True, frames=2, cond_type=LayerType.BG)) + + def apply_layered_diffusion(self, model: ModelPatcher, image, config: str, cond: Optional[List[List[torch.TensorType]]]=None, blended_cond: Optional[List[List[torch.TensorType]]]=None): + ld_model = [m for m in self.MODELS if m.config_string == config][0] + assert get_model_sd_version(model) == ld_model.sd_version + assert ld_model.attn_sharing + work_model = ld_model.apply_layered_diffusion_attn_sharing(model, control_img=image.movedim(-1, 1))[0] + work_model.model_options.setdefault('transformer_options', {}) + work_model.model_options['transformer_options']['cond_overwrite'] = [cond[0][0] if cond is not None else None for cond in (cond, blended_cond)] + return (work_model,) +``` \ No newline at end of file diff --git a/docs/LayeredDiffusionDecode.md b/docs/LayeredDiffusionDecode.md new file mode 100644 index 0000000..a10bae9 --- /dev/null +++ b/docs/LayeredDiffusionDecode.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: LayeredDiffusionDecode +- Category: layer_diffuse +- Output node: False +- Repo Ref: https://github.com/huchenlei/ComfyUI-layerdiffuse.git + +LayeredDiffusionDecode 类旨在执行像素值解码过程,以重建带有 alpha 通道的图像,有效地将透明度信息与 RGB 组件分离。它能够处理不同版本的扩散模型,并与系统集成,提供无缝的图像生成体验。 + +# Input types +## Required +- samples + - “samples”参数对于提供解码过程所需的潜在表示至关重要。它作为图像重建的基础,确保输出与预期的生成模型一致。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- images + - “images”参数至关重要,因为它提供了需要解码的原始像素数据。这些数据是提取 alpha 通道和图像重建的主要输入。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- sd_version + - “sd_version”参数指示用于解码过程的稳定扩散模型的版本。它很重要,因为它决定了将应用于解码的模型的特定特征和能力。 + - Comfy dtype: StableDiffusionVersion + - Python dtype: Enum +- sub_batch_size + - “sub_batch_size”参数定义了每次解码迭代中处理的图像数量,优化了计算效率和内存使用的权衡。它影响解码过程的吞吐量和资源分配。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - “image”输出代表重建的 RGB 图像数据,是解码过程的主要结果。它反映了应用的扩散模型的生成能力。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - “mask”输出提供 alpha 通道信息,这对于定义重建图像的透明度至关重要。它是进一步图像处理和操作的重要组件。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LayeredDiffusionDecode: + """ + Decode alpha channel value from pixel value. + [B, C=3, H, W] => [B, C=4, H, W] + Outputs RGB image + Alpha mask. + """ + + @classmethod + def INPUT_TYPES(s): + return {'required': {'samples': ('LATENT',), 'images': ('IMAGE',), 'sd_version': ([StableDiffusionVersion.SD1x.value, StableDiffusionVersion.SDXL.value], {'default': StableDiffusionVersion.SDXL.value}), 'sub_batch_size': ('INT', {'default': 16, 'min': 1, 'max': 4096, 'step': 1})}} + RETURN_TYPES = ('IMAGE', 'MASK') + FUNCTION = 'decode' + CATEGORY = 'layer_diffuse' + + def __init__(self) -> None: + self.vae_transparent_decoder = {} + + def decode(self, samples, images, sd_version: str, sub_batch_size: int): + """ + sub_batch_size: How many images to decode in a single pass. + See https://github.com/huchenlei/ComfyUI-layerdiffuse/pull/4 for more + context. + """ + sd_version = StableDiffusionVersion(sd_version) + if sd_version == StableDiffusionVersion.SD1x: + url = 'https://huggingface.co/LayerDiffusion/layerdiffusion-v1/resolve/main/layer_sd15_vae_transparent_decoder.safetensors' + file_name = 'layer_sd15_vae_transparent_decoder.safetensors' + elif sd_version == StableDiffusionVersion.SDXL: + url = 'https://huggingface.co/LayerDiffusion/layerdiffusion-v1/resolve/main/vae_transparent_decoder.safetensors' + file_name = 'vae_transparent_decoder.safetensors' + if not self.vae_transparent_decoder.get(sd_version): + model_path = load_file_from_url(url=url, model_dir=layer_model_root, file_name=file_name) + self.vae_transparent_decoder[sd_version] = TransparentVAEDecoder(load_torch_file(model_path), device=comfy.model_management.get_torch_device(), dtype=torch.float16 if comfy.model_management.should_use_fp16() else torch.float32) + pixel = images.movedim(-1, 1) + (B, C, H, W) = pixel.shape + assert H % 64 == 0, f'Height({H}) is not multiple of 64.' + assert W % 64 == 0, f'Height({W}) is not multiple of 64.' + decoded = [] + for start_idx in range(0, samples['samples'].shape[0], sub_batch_size): + decoded.append(self.vae_transparent_decoder[sd_version].decode_pixel(pixel[start_idx:start_idx + sub_batch_size], samples['samples'][start_idx:start_idx + sub_batch_size])) + pixel_with_alpha = torch.cat(decoded, dim=0) + pixel_with_alpha = pixel_with_alpha.movedim(1, -1) + image = pixel_with_alpha[..., 1:] + alpha = pixel_with_alpha[..., 0] + return (image, alpha) +``` \ No newline at end of file diff --git a/docs/LayeredDiffusionDecodeRGBA.md b/docs/LayeredDiffusionDecodeRGBA.md new file mode 100644 index 0000000..2f2c3fe --- /dev/null +++ b/docs/LayeredDiffusionDecodeRGBA.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: LayeredDiffusionDecodeRGBA +- Category: Image Processing +- Output node: False +- Repo Ref: https://github.com/huchenlei/ComfyUI-layerdiffuse.git + +LayeredDiffusionDecodeRGBA节点旨在从给定的像素值集解码RGBA图像,包含表示透明度的alpha通道。 + +# Input types +## Required +- samples + - “samples”参数对于解码过程至关重要,因为它包含了节点正确运行所需的像素数据和版本信息。 + - Comfy dtype: dict + - Python dtype: Dict[str, torch.Tensor] +- images + - “images”参数保存需要处理的图像数据,对于节点执行其解码操作至关重要。 + - Comfy dtype: tensor + - Python dtype: torch.Tensor +- sd_version + - “sd_version”参数指定要使用的Stable Diffusion模型的版本,这会影响解码过程和生成图像的质量。 + - Comfy dtype: str + - Python dtype: str +- sub_batch_size + - “sub_batch_size”参数决定了每次迭代中处理的图像数量,这会影响解码过程中的性能和内存使用。 + - Comfy dtype: int + - Python dtype: int + +# Output types +- image + - “image”输出代表解码后的RGBA图像数据,其中alpha通道表示图像的透明度。 + - Comfy dtype: tensor + - Python dtype: torch.Tensor +- alpha + - “alpha”输出是RGBA图像的alpha通道,对于在最终图像中渲染透明度效果至关重要。 + - Comfy dtype: tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LayeredDiffusionDecodeRGBA(LayeredDiffusionDecode): + """ + Decode alpha channel value from pixel value. + [B, C=3, H, W] => [B, C=4, H, W] + Outputs RGBA image. + """ + RETURN_TYPES = ('IMAGE',) + + def decode(self, samples, images, sd_version: str, sub_batch_size: int): + (image, mask) = super().decode(samples, images, sd_version, sub_batch_size) + alpha = 1.0 - mask + return JoinImageWithAlpha().join_image_with_alpha(image, alpha) +``` \ No newline at end of file diff --git a/docs/LayeredDiffusionDecodeSplit.md b/docs/LayeredDiffusionDecodeSplit.md new file mode 100644 index 0000000..b7a9e46 --- /dev/null +++ b/docs/LayeredDiffusionDecodeSplit.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: LayeredDiffusionDecodeSplit +- Category: Image Processing +- Output node: False +- Repo Ref: https://github.com/huchenlei/ComfyUI-layerdiffuse.git + +LayeredDiffusionDecodeSplit 类旨在以子批次的方式高效解码 RGBA 图像,提高处理吞吐量和内存管理。它通过解码较小的图像组来处理大型图像数据集,从而优化计算资源并为各种应用简化解码过程。 + +# Input types +## Required +- samples + - “samples”参数是必需的,因为它包含了解码过程所需的潜在表示。它直接影响解码图像的质量和准确性,是整个操作的基础。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- images + - “images”参数对于解码过程至关重要,它提供了需要处理的输入图像。它是节点执行的核心,并影响最终输出,决定了解码图像的视觉方面。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- frames + - “frames”参数决定了图像解码的频率,有效地控制子批次的大小。它在平衡计算效率和内存使用方面发挥着关键作用,确保处理过程顺畅且优化。 + - Comfy dtype: INT + - Python dtype: int +- sd_version + - “sd_version”参数指定要使用的稳定扩散模型的版本,这对于确定解码算法及其与输入数据的兼容性至关重要。它影响整体性能和生成图像的质量。 + - Comfy dtype: ENUM + - Python dtype: StableDiffusionVersion +- sub_batch_size + - “sub_batch_size”参数对于管理计算负载至关重要,因为它定义了每个子批次处理的图像数量。它在优化解码过程的速度和资源分配方面起着重要作用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - “image”输出代表解码后的 RGBA 图像,是节点操作的主要结果。它封装了从输入数据处理得到的视觉信息,展示了节点将潜在表示转换为可感知视觉内容的能力。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- alpha + - “alpha”输出包含解码图像的 alpha 通道信息,对于需要透明度的应用来说非常重要。它突出了节点处理复杂图像属性的能力,并为最终视觉输出的丰富性做出了贡献。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LayeredDiffusionDecodeSplit(LayeredDiffusionDecodeRGBA): + """Decode RGBA every N images.""" + + @classmethod + def INPUT_TYPES(s): + return {'required': {'samples': ('LATENT',), 'images': ('IMAGE',), 'frames': ('INT', {'default': 2, 'min': 2, 'max': s.MAX_FRAMES, 'step': 1}), 'sd_version': ([StableDiffusionVersion.SD1x.value, StableDiffusionVersion.SDXL.value], {'default': StableDiffusionVersion.SDXL.value}), 'sub_batch_size': ('INT', {'default': 16, 'min': 1, 'max': 4096, 'step': 1})}} + MAX_FRAMES = 3 + RETURN_TYPES = ('IMAGE',) * MAX_FRAMES + + def decode(self, samples, images: torch.Tensor, frames: int, sd_version: str, sub_batch_size: int): + sliced_samples = copy.copy(samples) + sliced_samples['samples'] = sliced_samples['samples'][::frames] + return tuple((super(LayeredDiffusionDecodeSplit, self).decode(sliced_samples, imgs, sd_version, sub_batch_size)[0] if i == 0 else imgs for i in range(frames) for imgs in (images[i::frames],))) + (None,) * (self.MAX_FRAMES - frames) +``` \ No newline at end of file diff --git a/docs/LayeredDiffusionDiffApply.md b/docs/LayeredDiffusionDiffApply.md new file mode 100644 index 0000000..18ba2d5 --- /dev/null +++ b/docs/LayeredDiffusionDiffApply.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: LayeredDiffusionDiff +- Category: layer_diffuse +- Output node: False +- Repo Ref: https://github.com/huchenlei/ComfyUI-layerdiffuse.git + +LayeredDiffusionDiff节点旨在从混合图像中分离前景和背景元素。它通过应用扩散过程实现这一点,该过程允许模型根据提供的条件区分和提取前景或背景。此节点对于需要在不影响其他视觉元素的情况下操作或隔离特定图像组件的任务至关重要。 + +# Input types +## Required +- model + - 模型参数对节点的操作至关重要,因为它定义了将用于应用扩散过程的底层模型。正是通过这个模型,节点与图像数据交互以分离前景和背景。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- cond + - cond参数作为指导扩散过程提取所需图像组件的条件输入。它在确定分离过程的结果中起着关键作用。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict[str, torch.Tensor]}} +- uncond + - uncond参数提供无条件输入,补充扩散过程,确保模型能够在没有特定先决条件的情况下生成所需的图像组件。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict[str, torch.Tensor]}} +- blended_latent + - blended_latent参数代表混合图像的潜在表示,节点将尝试从中提取前景或背景。这是扩散过程的一个关键输入。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- latent + - latent参数保存图像的潜在表示,将与混合潜在表示一起使用,以指导扩散过程。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- config + - config参数指定扩散模型的配置设置,确保节点根据预定义的模型规格进行操作。 + - Comfy dtype: STRING + - Python dtype: str +- weight + - weight参数允许微调扩散过程对图像分离的影响。它提供了一种调整应用扩散强度的手段。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- model + - 模型输出代表应用扩散过程后的输入模型的修改版本。根据扩散配置,它包含分离的前景或背景。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- cond + - cond输出提供在扩散过程中所做的更改的更新条件信息。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict[str, torch.Tensor]}} +- uncond + - uncond输出反映了通过扩散机制处理的更新后的无条件输入。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict[str, torch.Tensor]}} + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LayeredDiffusionDiff: + """Extract FG/BG from blended image. + - Blended + FG => BG + - Blended + BG => FG + """ + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'cond': ('CONDITIONING',), 'uncond': ('CONDITIONING',), 'blended_latent': ('LATENT',), 'latent': ('LATENT',), 'config': ([c.config_string for c in s.MODELS],), 'weight': ('FLOAT', {'default': 1.0, 'min': -1, 'max': 3, 'step': 0.05})}} + RETURN_TYPES = ('MODEL', 'CONDITIONING', 'CONDITIONING') + FUNCTION = 'apply_layered_diffusion' + CATEGORY = 'layer_diffuse' + MODELS = (LayeredDiffusionBase(model_file_name='layer_xl_fgble2bg.safetensors', model_url='https://huggingface.co/LayerDiffusion/layerdiffusion-v1/resolve/main/layer_xl_fgble2bg.safetensors', sd_version=StableDiffusionVersion.SDXL, cond_type=LayerType.FG), LayeredDiffusionBase(model_file_name='layer_xl_bgble2fg.safetensors', model_url='https://huggingface.co/LayerDiffusion/layerdiffusion-v1/resolve/main/layer_xl_bgble2fg.safetensors', sd_version=StableDiffusionVersion.SDXL, cond_type=LayerType.BG)) + + def apply_layered_diffusion(self, model: ModelPatcher, cond, uncond, blended_latent, latent, config: str, weight: float): + ld_model = [m for m in self.MODELS if m.config_string == config][0] + assert get_model_sd_version(model) == ld_model.sd_version + c_concat = model.model.latent_format.process_in(torch.cat([latent['samples'], blended_latent['samples']], dim=1)) + return ld_model.apply_layered_diffusion(model, weight) + ld_model.apply_c_concat(cond, uncond, c_concat) +``` \ No newline at end of file diff --git a/docs/LayeredDiffusionJointApply.md b/docs/LayeredDiffusionJointApply.md new file mode 100644 index 0000000..fc2e007 --- /dev/null +++ b/docs/LayeredDiffusionJointApply.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: LayeredDiffusionJoint +- Category: layer_diffuse +- Output node: False +- Repo Ref: https://github.com/huchenlei/ComfyUI-layerdiffuse.git + +LayeredDiffusionJoint节点旨在执行单批次推理,生成前景、背景和混合图像。它能够通过应用分层扩散技术处理复杂的图像生成任务,允许创建具有复杂细节和分层效果的图像。该节点特别适用于需要同时生成多个图像组件的应用程序,简化了流程并提高了图像合成工作流程的整体效率。 + +# Input types +## Required +- model + - 模型参数对节点的操作至关重要,因为它定义了将用于扩散过程的底层模型。这是一个关键组件,直接影响节点的执行和生成图像的质量。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- config + - 配置字符串是一个必需的参数,它指定了分层扩散过程的设置。它在确定节点如何应用扩散技术以生成所需图像方面起着关键作用。 + - Comfy dtype: str + - Python dtype: str +- fg_cond + - 前景条件参数是可选的,用于为生成图像的前景部分提供特定的指导。它允许微调扩散过程,以满足图像前景的特定要求。 + - Comfy dtype: CONDITIONING + - Python dtype: Optional[List[List[torch.Tensor]]] +- bg_cond + - 背景条件参数是可选的,用于指导图像背景的生成。它使节点能够创建与所需视觉效果一致的背景。 + - Comfy dtype: CONDITIONING + - Python dtype: Optional[List[List[torch.Tensor]]] +- blended_cond + - 混合条件参数是可选的,用于定义生成图像的混合特性。它有助于在图像内实现前景和背景元素的和谐混合。 + - Comfy dtype: CONDITIONING + - Python dtype: Optional[List[List[torch.Tensor]]] + +# Output types +- model + - 输出模型代表了输入模型的补丁版本,现在具备了分层扩散能力。这个模型准备好了生成具有分层效果的图像,为图像合成过程提供了更高程度的控制和定制化。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LayeredDiffusionJoint: + """Generate FG + BG + Blended in one inference batch. Batch size = 3N.""" + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'config': ([c.config_string for c in s.MODELS],)}, 'optional': {'fg_cond': ('CONDITIONING',), 'bg_cond': ('CONDITIONING',), 'blended_cond': ('CONDITIONING',)}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'apply_layered_diffusion' + CATEGORY = 'layer_diffuse' + MODELS = (LayeredDiffusionBase(model_file_name='layer_sd15_joint.safetensors', model_url='https://huggingface.co/LayerDiffusion/layerdiffusion-v1/resolve/main/layer_sd15_joint.safetensors', sd_version=StableDiffusionVersion.SD1x, attn_sharing=True, frames=3),) + + def apply_layered_diffusion(self, model: ModelPatcher, config: str, fg_cond: Optional[List[List[torch.TensorType]]]=None, bg_cond: Optional[List[List[torch.TensorType]]]=None, blended_cond: Optional[List[List[torch.TensorType]]]=None): + ld_model = [m for m in self.MODELS if m.config_string == config][0] + assert get_model_sd_version(model) == ld_model.sd_version + assert ld_model.attn_sharing + work_model = ld_model.apply_layered_diffusion_attn_sharing(model)[0] + work_model.model_options.setdefault('transformer_options', {}) + work_model.model_options['transformer_options']['cond_overwrite'] = [cond[0][0] if cond is not None else None for cond in (fg_cond, bg_cond, blended_cond)] + return (work_model,) +``` \ No newline at end of file diff --git a/docs/LeRes_DepthMap_Preprocessor_Provider_for_SEGS %2F%2FInspire.md b/docs/LeRes_DepthMap_Preprocessor_Provider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..160b6e8 --- /dev/null +++ b/docs/LeRes_DepthMap_Preprocessor_Provider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: LeReS_DepthMap_Preprocessor_Provider_for_SEGS +- Category: InspirePack/SEGS/ControlNet +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +这个节点类用于为分割任务预处理深度图,利用LeReS算法优化输入数据,提高分割输出的质量。 + +# Input types +## Required +- rm_nearest + - 该参数调整附近像素的移除阈值,这对于定义深度图的精度和分割边界的清晰度至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- rm_background + - 该参数设置移除背景噪声的阈值,这对于隔离主题并确保分割的准确性至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- boost + - 启用此参数时,增强深度图的特征,可能会改善分割结果,但可能会增加处理时间。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- SEGS_PREPROCESSOR + - 输出是为分割任务优化的预处理深度图,为进一步处理提供了精炼的基础。 + - Comfy dtype: SEGS_PREPROCESSOR + - Python dtype: LeReS_DepthMapPreprocessor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LeReS_DepthMap_Preprocessor_Provider_for_SEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'rm_nearest': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 100, 'step': 0.1}), 'rm_background': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 100, 'step': 0.1})}, 'optional': {'boost': ('BOOLEAN', {'default': False, 'label_on': 'enable', 'label_off': 'disable'})}} + RETURN_TYPES = ('SEGS_PREPROCESSOR',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/SEGS/ControlNet' + + def doit(self, rm_nearest, rm_background, boost=False): + obj = LeReS_DepthMap_Preprocessor_wrapper(rm_nearest, rm_background, boost) + return (obj,) +``` \ No newline at end of file diff --git a/docs/Lerp.md b/docs/Lerp.md new file mode 100644 index 0000000..3b08505 --- /dev/null +++ b/docs/Lerp.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: Lerp +- Category: FizzNodes 📅🅕🅝/WaveNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +Lerp节点执行两个值之间的线性插值,提供由强度参数和图像序列中的当前帧影响的平滑过渡。它通常用于动画和数据可视化中,以创建从一种状态到另一种状态的逐渐变化。 + +# Input types +## Required +- num_Images + - 图像数量参数定义了序列中的帧或图像总数,它影响插值的步长。这对于确定值之间过渡的粒度至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- strength + - 强度参数控制起始值和结束值之间插值的程度。它是过渡在图像序列中发生速度的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- current_frame + - 当前帧参数指定了图像序列中的当前位置。它对于计算任何给定时间点插值的当前状态至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - Lerp节点的输出是线性插值的结果,提供了一个值,该值基于输入参数表示过渡的当前状态。 + - Comfy dtype: FLOAT + - Python dtype: float +- frame_index + - 帧索引输出指示计算当前插值状态的帧号,这对于与基于序列的其他流程对齐非常有用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Lerp: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'num_Images': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'current_frame': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999, 'step': 1.0})}} + RETURN_TYPES = ('FLOAT', 'INT') + FUNCTION = 'lerp' + CATEGORY = 'FizzNodes 📅🅕🅝/WaveNodes' + + def lerp(self, num_Images, strength, current_frame): + step = strength / num_Images + output = strength - step * current_frame + return (output, int(output)) +``` \ No newline at end of file diff --git a/docs/LimitNumber.md b/docs/LimitNumber.md new file mode 100644 index 0000000..3fc78f9 --- /dev/null +++ b/docs/LimitNumber.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: LimitNumber +- Category: ♾️Mixlab/Utils +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点将给定的数字限制在指定的范围内,确保其不会超出定义的最小和最大边界。它主要用于保持数字的完整性,防止无效值影响下游流程。 + +# Input types +## Required +- number + - 需要被限制在指定范围内的输入数字。这是一个关键参数,因为它是节点操作的核心值,以确保其保持在可接受的范围内。 + - Comfy dtype: any_type + - Python dtype: Union[int, float] +- min_value + - 输入数字可接受范围的下限。它在设置输入值不允许低于的最小限制方面起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- max_value + - 输入数字可接受范围的上限。它在定义输入值不得超过的最大上限方面至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- number + - 已被限制在指定范围内的输出数字。它是节点操作的结果,确保该值在输入参数定义的可接受边界内。 + - Comfy dtype: any_type + - Python dtype: Union[int, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LimitNumber: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number': (any_type,), 'min_value': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615, 'step': 1, 'display': 'number'}), 'max_value': ('INT', {'default': 1, 'min': 1, 'max': 18446744073709551615, 'step': 1, 'display': 'number'})}} + RETURN_TYPES = (any_type,) + RETURN_NAMES = ('number',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Utils' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False,) + + def run(self, number, min_value, max_value): + nn = number + if isinstance(number, int): + min_value = int(min_value) + max_value = int(max_value) + if isinstance(number, float): + min_value = float(min_value) + max_value = float(max_value) + if number < min_value: + nn = min_value + elif number > max_value: + nn = max_value + return (nn,) +``` \ No newline at end of file diff --git a/docs/LineArt_Preprocessor_Provider_for_SEGS %2F%2FInspire.md b/docs/LineArt_Preprocessor_Provider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..d497e3a --- /dev/null +++ b/docs/LineArt_Preprocessor_Provider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: LineArt_Preprocessor_Provider_for_SEGS +- Category: InspirePack/SEGS/ControlNet +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点抽象地表示了通过应用风格化变换从输入图像生成线条艺术的过程,重点是增强边缘和轮廓,以创造更具艺术感的呈现。 + +# Input types +## Required +- coarse + - 此参数控制线条艺术生成的细节级别,'启用'会导致更详细、更锐利的输出,而'禁用'则会产生较少细节的表示。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- SEGS_PREPROCESSOR + - 输出是经过处理的线条艺术图像,根据输入参数进行了细化和风格化,准备用于进一步的分割任务。 + - Comfy dtype: NODE + - Python dtype: LineArtPreprocessor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LineArt_Preprocessor_Provider_for_SEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'coarse': ('BOOLEAN', {'default': False, 'label_on': 'enable', 'label_off': 'disable'})}} + RETURN_TYPES = ('SEGS_PREPROCESSOR',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/SEGS/ControlNet' + + def doit(self, coarse): + obj = LineArt_Preprocessor_wrapper(coarse) + return (obj,) +``` \ No newline at end of file diff --git a/docs/ListCounter %2F%2FInspire.md b/docs/ListCounter %2F%2FInspire.md new file mode 100644 index 0000000..b685ff7 --- /dev/null +++ b/docs/ListCounter %2F%2FInspire.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: ListCounter +- Category: InspirePack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +ListCounter 节点旨在递增地计数唯一标识符的出现次数,提供了一种跟踪序列中事件或项目的方法。它通过使用映射结构来维护与每个唯一标识符关联的计数。该节点特别适用于需要顺序跟踪的场景,例如日志记录、事件处理或库存管理。 + +# Input types +## Required +- signal + - signal 参数代表触发计数过程的输入。它的存在标志着需要计数的事件或项目。该参数的重要性在于其作为节点操作的启动因素,没有它,计数机制将不会启动。 + - Comfy dtype: ANY + - Python dtype: Any +- base_value + - base_value 参数作为节点在递增前开始的初始计数值。它至关重要,因为它为计数设定了基础,并且可以用来调整序列的起始点,从而在计数操作中提供灵活性。 + - Comfy dtype: INT + - Python dtype: int +- unique_id + - unique_id 参数是用于区分正在跟踪的不同序列或项目的键标识符。它对节点的功能至关重要,因为它允许区分和单独计数每个独特的序列或项目。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- count + - count 输出反映了节点处理输入后的当前计数值。它表示到目前为止已计数的出现次数或事件总数。这个输出很重要,因为它提供了节点操作的最终结果,提供了对序列进度的洞察。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ListCounter: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'signal': (utils.any_typ,), 'base_value': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('INT',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Util' + + def doit(self, signal, base_value, unique_id): + if unique_id not in list_counter_map: + count = 0 + else: + count = list_counter_map[unique_id] + list_counter_map[unique_id] = count + 1 + return (count + base_value,) +``` \ No newline at end of file diff --git a/docs/LoRAScheduler.md b/docs/LoRAScheduler.md new file mode 100644 index 0000000..7eb4877 --- /dev/null +++ b/docs/LoRAScheduler.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: LoRAScheduler +- Category: promptcontrol/old +- Output node: False +- Repo Ref: https://github.com/asagi4/comfyui-prompt-control.git + +该节点在推理过程中根据预定义的提示调度动态修改模型的行为,提高了模型的适应性和可控性,而不改变模型的基本结构。 + +# Input types +## Required +- model + - 模型参数至关重要,它定义了节点操作的核心。它是将要按照提示调度修改行为的机器学习模型。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- text + - 文本参数包含提示调度,它规定了要应用于模型的修改。这对于指导节点执行所需的转换至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- model + - 输出模型是输入模型的修改版本,现在应用了提示调度,允许在推理过程中进行更细致的控制和行为。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoRAScheduler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'text': ('STRING', {'multiline': True})}} + RETURN_TYPES = ('MODEL',) + CATEGORY = 'promptcontrol/old' + FUNCTION = 'apply' + + def apply(self, model, text): + schedules = parse_prompt_schedules(text) + return (schedule_lora_common(model, schedules),) +``` \ No newline at end of file diff --git a/docs/Load Cache.md b/docs/Load Cache.md new file mode 100644 index 0000000..6b3b794 --- /dev/null +++ b/docs/Load Cache.md @@ -0,0 +1,81 @@ +# Documentation +- Class name: WAS_Load_Cache +- Category: WAS Suite/IO +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Load_Cache节点旨在高效地管理从指定路径加载缓存数据,例如潜在向量、图像和条件数据。它确保只有在给定路径上存在缓存文件时才加载数据,为WAS套件的工作流程提供了一个重要的数据检索机制。 + +# Input types +## Required +- latent_path + - latent_path参数指定潜在数据缓存的文件路径。它的存在至关重要,因为它指导节点到正确的位置加载潜在数据,这对于WAS套件中的后续处理步骤是必不可少的。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- image_path + - image_path参数用于指示图像数据缓存的位置。这是一个可选参数,提供时允许节点从指定路径加载和使用图像数据,增强了整个系统的功能。 + - Comfy dtype: STRING + - Python dtype: Optional[str] +- conditioning_path + - conditioning_path参数指向存储条件数据缓存的文件路径。当节点需要加载条件数据以影响WAS套件内其他数据的生成或处理时,这个可选参数很重要。 + - Comfy dtype: STRING + - Python dtype: Optional[str] + +# Output types +- LATENT + - LATENT输出提供了从指定缓存路径加载的潜在数据。它是WAS套件中需要潜在表示进行操作的模型的关键组成部分。 + - Comfy dtype: LATENT + - Python dtype: Union[torch.Tensor, None] +- IMAGE + - IMAGE输出包含已加载的图像数据,可以在WAS套件内用于可视化或进一步分析。它是一个可选输出,仅当提供了相应的image_path输入并且成功加载了图像数据时才会出现。 + - Comfy dtype: IMAGE + - Python dtype: Union[PIL.Image, None] +- CONDITIONING + - CONDITIONING输出提供已加载的条件数据,这对于WAS套件内的某些模型操作至关重要。它允许根据条件输入定制和微调模型行为。 + - Comfy dtype: CONDITIONING + - Python dtype: Union[torch.Tensor, None] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Load_Cache: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'latent_path': ('STRING', {'default': '', 'multiline': False}), 'image_path': ('STRING', {'default': '', 'multiline': False}), 'conditioning_path': ('STRING', {'default': '', 'multiline': False})}} + RETURN_TYPES = ('LATENT', 'IMAGE', 'CONDITIONING') + RETURN_NAMES = ('LATENT', 'IMAGE', 'CONDITIONING') + FUNCTION = 'load_cache' + CATEGORY = 'WAS Suite/IO' + + def load_cache(self, latent_path=None, image_path=None, conditioning_path=None): + if 'joblib' not in packages(): + install_package('joblib') + import joblib + input_path = os.path.join(WAS_SUITE_ROOT, 'cache') + latent = None + image = None + conditioning = None + if latent_path not in ['', None]: + if os.path.exists(latent_path): + latent = joblib.load(latent_path) + else: + cstr(f'Unable to locate cache file {latent_path}').error.print() + if image_path not in ['', None]: + if os.path.exists(image_path): + image = joblib.load(image_path) + else: + cstr(f'Unable to locate cache file {image_path}').msg.print() + if conditioning_path not in ['', None]: + if os.path.exists(conditioning_path): + conditioning = joblib.load(conditioning_path) + else: + cstr(f'Unable to locate cache file {conditioning_path}').error.print() + return (latent, image, conditioning) +``` \ No newline at end of file diff --git a/docs/Load CheckPoint DragNUWA.md b/docs/Load CheckPoint DragNUWA.md new file mode 100644 index 0000000..aaf5eaa --- /dev/null +++ b/docs/Load CheckPoint DragNUWA.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: LoadCheckPointDragNUWA +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +这个节点类封装了加载和操作DragNUWA模型的功能,使用户能够通过各种输入(如跟踪点或光流数据)对模型进行条件化,从而生成高保真度的视频帧。它通过抽象底层模型的复杂性并为视频帧生成提供一个简单的接口,简化了创建复杂视觉效果的过程。 + +# Input types +## Required +- ckpt_name + - 检查点名称至关重要,因为它标识了要加载的特定DragNUWA模型。它影响生成的视频帧的质量和特性,确保为手头任务使用正确的模型配置。 + - Comfy dtype: COMBO + - Python dtype: str +- dimension + - 尺寸参数决定了模型将生成的视频帧的分辨率。它对于确保输出匹配所需的格式和质量标准至关重要,这对于下游处理和显示非常关键。 + - Comfy dtype: COMBO + - Python dtype: str +- model_length + - 模型长度参数很重要,因为它设置了模型的时间维度,决定了模型可以处理的帧数。它影响生成视频的范围和模型随时间捕捉运动和细节的能力。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- model + - 输出模型是后续视频帧生成的核心组件。它封装了产生高质量视觉内容所需的学习模式和特性。模型的输出在实现期望的视觉效果和满足创意目标方面起着关键作用。 + - Comfy dtype: DragNUWA + - Python dtype: Drag + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LoadCheckPointDragNUWA: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'ckpt_name': (['dragnuwa-svd-pruned.fp16.safetensors'], {'default': 'dragnuwa-svd-pruned.fp16.safetensors'}), 'dimension': (['576x320', '512x512', '320x576'], {'default': '576x320'}), 'model_length': ('INT', {'default': 14})}} + RETURN_TYPES = ('DragNUWA',) + RETURN_NAMES = ('model',) + FUNCTION = 'load_dragnuwa' + CATEGORY = 'DragNUWA' + + def load_dragnuwa(self, ckpt_name, dimension, model_length): + width = int(dimension.split('x')[0]) + height = int(dimension.split('x')[1]) + comfy_path = os.path.dirname(folder_paths.__file__) + ckpt_path = folder_paths.get_full_path('checkpoints', ckpt_name) + current_path = os.path.abspath(os.path.dirname(__file__)) + sys.path.append(current_path) + DragNUWA_net = Drag('cuda:0', ckpt_path, f'{comfy_path}/custom_nodes/ComfyUI-DragNUWA/DragNUWA_net.py', height, width, model_length) + return (DragNUWA_net,) +``` \ No newline at end of file diff --git a/docs/Load Face Analysis Model (mtb).md b/docs/Load Face Analysis Model (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Load Face Enhance Model (mtb).md b/docs/Load Face Enhance Model (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Load Face Swap Model (mtb).md b/docs/Load Face Swap Model (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Load Image Based on Number.md b/docs/Load Image Based on Number.md new file mode 100644 index 0000000..490d384 --- /dev/null +++ b/docs/Load Image Based on Number.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: LoadImgFromDirectoryBasedOnIndex +- Category: Mikey/Image +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +该节点旨在根据提供的索引从指定目录加载图像。它确保目录存在,然后从该目录中排序后的图像文件列表中选择一个图像文件。节点的功能集中在检索图像并将其转换为适合进一步处理的张量格式。 + +# Input types +## Required +- image_directory + - image_directory 参数指定包含图像文件的目录的路径。它对节点的操作至关重要,因为它决定了要加载的图像的来源。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- seed + - seed 参数用于确定从排序后的文件列表中加载的图像文件的索引。它影响选择过程,并确保在图像检索中有一定程度的随机性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - image 输出提供了以张量格式加载的图像,这对于需要以数值形式的图像数据的下游任务至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- filename + - filename 输出返回加载的图像文件的名称,这对于记录、跟踪或需要文件识别的额外处理非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadImgFromDirectoryBasedOnIndex: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image_directory': ('STRING', {'multiline': False, 'placeholder': 'Image Directory'}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('IMAGE', 'STRING') + RETURN_NAMES = ('image', 'filename') + FUNCTION = 'load' + CATEGORY = 'Mikey/Image' + + def load(self, image_directory, seed): + if not os.path.exists(image_directory): + raise Exception(f'Image directory {image_directory} does not exist') + files = [os.path.join(image_directory, f) for f in os.listdir(image_directory) if os.path.isfile(os.path.join(image_directory, f)) and f.endswith(('.png', '.jpg', '.jpeg', '.webp', '.bmp', '.gif'))] + files.sort() + offset = seed % len(files) + filename = files[offset].split('/')[-1] + img = Image.open(files[offset]) + img = pil2tensor(img) + return (img, filename) +``` \ No newline at end of file diff --git a/docs/Load Image Batch.md b/docs/Load Image Batch.md new file mode 100644 index 0000000..70a41fc --- /dev/null +++ b/docs/Load Image Batch.md @@ -0,0 +1,159 @@ +# Documentation +- Class name: WAS_Load_Image_Batch +- Category: WAS Suite/IO +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Load_Image_Batch 节点旨在高效地加载和管理图像文件批次。它提供以不同模式加载图像的功能,如单张图像、增量图像或随机选择。该节点确保图像正确定向,并且在需要时可以处理 RGBA 到 RGB 的转换。它还能够根据指定去除文件名中的文件扩展名。 + +# Input types +## Required +- path + - 'path' 参数指定了图像文件所在的目录路径。这对于节点定位和访问所需处理的图像文件至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- pattern + - 'pattern' 参数用于根据特定模式过滤图像文件。它对于在指定目录内选择符合给定标准的图像子集很重要。 + - Comfy dtype: STRING + - Python dtype: str +- index + - 'index' 参数是一个整数,表示要加载的批次中图像的具体位置。当模式设置为 'single_image' 时,它在确定要检索的确切图像时起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- mode + - 'mode' 参数确定加载图像的方法。它可以是 'single_image' 用于加载特定图像,'incremental_image' 用于顺序访问,或 'random' 用于随机选择。 + - Comfy dtype: COMBO['single_image', 'incremental_image', 'random'] + - Python dtype: str +- label + - 'label' 参数是一个字符串,用于标识和分类图像批次。它有助于在节点操作中组织和跟踪不同的图像集。 + - Comfy dtype: STRING + - Python dtype: str +- allow_RGBA_output + - 'allow_RGBA_output' 参数决定是否允许输出图像具有 RGBA 通道。如果设置为 'false',则节点将图像转换为 RGB。 + - Comfy dtype: COMBO['false', 'true'] + - Python dtype: str +- filename_text_extension + - 'filename_text_extension' 参数指示是否在文件名文本输出中包含文件扩展名。在不需要文件扩展名的文件名中,它很有用。 + - Comfy dtype: COMBO['true', 'false'] + - Python dtype: str + +# Output types +- image + - 'image' 输出提供了指定批次中加载的图像。它是节点功能内图像处理任务的主要输出。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- filename_text + - 'filename_text' 输出返回加载的图像文件的名称,可以用于参考或在节点之外进行进一步处理。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Load_Image_Batch: + + def __init__(self): + self.HDB = WASDatabase(WAS_HISTORY_DATABASE) + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'mode': (['single_image', 'incremental_image', 'random'],), 'index': ('INT', {'default': 0, 'min': 0, 'max': 150000, 'step': 1}), 'label': ('STRING', {'default': 'Batch 001', 'multiline': False}), 'path': ('STRING', {'default': '', 'multiline': False}), 'pattern': ('STRING', {'default': '*', 'multiline': False}), 'allow_RGBA_output': (['false', 'true'],)}, 'optional': {'filename_text_extension': (['true', 'false'],)}} + RETURN_TYPES = ('IMAGE', TEXT_TYPE) + RETURN_NAMES = ('image', 'filename_text') + FUNCTION = 'load_batch_images' + CATEGORY = 'WAS Suite/IO' + + def load_batch_images(self, path, pattern='*', index=0, mode='single_image', label='Batch 001', allow_RGBA_output='false', filename_text_extension='true'): + allow_RGBA_output = allow_RGBA_output == 'true' + if not os.path.exists(path): + return (None,) + fl = self.BatchImageLoader(path, label, pattern) + new_paths = fl.image_paths + if mode == 'single_image': + (image, filename) = fl.get_image_by_id(index) + if image == None: + cstr(f'No valid image was found for the inded `{index}`').error.print() + return (None, None) + elif mode == 'incremental_image': + (image, filename) = fl.get_next_image() + if image == None: + cstr(f'No valid image was found for the next ID. Did you remove images from the source directory?').error.print() + return (None, None) + else: + newindex = int(random.random() * len(fl.image_paths)) + (image, filename) = fl.get_image_by_id(newindex) + if image == None: + cstr(f'No valid image was found for the next ID. Did you remove images from the source directory?').error.print() + return (None, None) + update_history_images(new_paths) + if not allow_RGBA_output: + image = image.convert('RGB') + if filename_text_extension == 'false': + filename = os.path.splitext(filename)[0] + return (pil2tensor(image), filename) + + class BatchImageLoader: + + def __init__(self, directory_path, label, pattern): + self.WDB = WDB + self.image_paths = [] + self.load_images(directory_path, pattern) + self.image_paths.sort() + stored_directory_path = self.WDB.get('Batch Paths', label) + stored_pattern = self.WDB.get('Batch Patterns', label) + if stored_directory_path != directory_path or stored_pattern != pattern: + self.index = 0 + self.WDB.insert('Batch Counters', label, 0) + self.WDB.insert('Batch Paths', label, directory_path) + self.WDB.insert('Batch Patterns', label, pattern) + else: + self.index = self.WDB.get('Batch Counters', label) + self.label = label + + def load_images(self, directory_path, pattern): + for file_name in glob.glob(os.path.join(glob.escape(directory_path), pattern), recursive=True): + if file_name.lower().endswith(ALLOWED_EXT): + abs_file_path = os.path.abspath(file_name) + self.image_paths.append(abs_file_path) + + def get_image_by_id(self, image_id): + if image_id < 0 or image_id >= len(self.image_paths): + cstr(f'Invalid image index `{image_id}`').error.print() + return + i = Image.open(self.image_paths[image_id]) + i = ImageOps.exif_transpose(i) + return (i, os.path.basename(self.image_paths[image_id])) + + def get_next_image(self): + if self.index >= len(self.image_paths): + self.index = 0 + image_path = self.image_paths[self.index] + self.index += 1 + if self.index == len(self.image_paths): + self.index = 0 + cstr(f'{cstr.color.YELLOW}{self.label}{cstr.color.END} Index: {self.index}').msg.print() + self.WDB.insert('Batch Counters', self.label, self.index) + i = Image.open(image_path) + i = ImageOps.exif_transpose(i) + return (i, os.path.basename(image_path)) + + def get_current_image(self): + if self.index >= len(self.image_paths): + self.index = 0 + image_path = self.image_paths[self.index] + return os.path.basename(image_path) + + @classmethod + def IS_CHANGED(cls, **kwargs): + if kwargs['mode'] != 'single_image': + return float('NaN') + else: + fl = WAS_Load_Image_Batch.BatchImageLoader(kwargs['path'], kwargs['label'], kwargs['pattern']) + filename = fl.get_current_image() + image = os.path.join(kwargs['path'], filename) + sha = get_sha256(image) + return sha +``` \ No newline at end of file diff --git a/docs/Load Image From Url (mtb).md b/docs/Load Image From Url (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Load Image Sequence (mtb).md b/docs/Load Image Sequence (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Load Lora.md b/docs/Load Lora.md new file mode 100644 index 0000000..077b0d6 --- /dev/null +++ b/docs/Load Lora.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: WAS_Lora_Loader +- Category: WAS Suite/Loaders +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Lora_Loader节点旨在WAS套件中管理Lora模型的加载和应用。它通过缓存先前加载的模型来确保高效处理Lora文件,减少冗余并提高性能。此节点对于将高级定制功能集成到工作流程中至关重要。 + +# Input types +## Required +- model + - 模型参数对于节点的操作至关重要,因为它代表了将应用Lora增强的主要对象。它直接影响节点的执行和结果模型的能力。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - clip参数对于定义Lora模型操作的上下文至关重要。它影响模型如何与系统的其余部分集成,影响最终结果。 + - Comfy dtype: CLIP + - Python dtype: Union[torch.Tensor, comfy.models.CLIPModel] +- lora_name + - lora_name参数指定要加载的Lora模型。它是定制过程中的关键决定因素,因为它决定了将使用哪个Lora模型的功能。 + - Comfy dtype: STRING + - Python dtype: str +- strength_model + - strength_model参数调整Lora模型对基础模型影响的强度。它是微调模型性能的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- strength_clip + - strength_clip参数控制CLIP模型对整个过程的影响。它在根据所需规格形成最终输出方面具有重要意义。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- MODEL + - 输出模型代表了应用了Lora定制的增强模型。它标志着节点处理的完成,是工作流中后续步骤的核心。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- CLIP + - 输出CLIP模型反映了通过与Lora模型集成所做的调整。它是进一步处理或分析的重要组成部分。 + - Comfy dtype: CLIP + - Python dtype: Union[torch.Tensor, comfy.models.CLIPModel] +- NAME_STRING + - NAME_STRING输出提供了加载的Lora模型的名称,这对于系统内的跟踪和引用非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Lora_Loader: + + def __init__(self): + self.loaded_lora = None + + @classmethod + def INPUT_TYPES(s): + file_list = comfy_paths.get_filename_list('loras') + file_list.insert(0, 'None') + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'lora_name': (file_list,), 'strength_model': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'strength_clip': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01})}} + RETURN_TYPES = ('MODEL', 'CLIP', TEXT_TYPE) + RETURN_NAMES = ('MODEL', 'CLIP', 'NAME_STRING') + FUNCTION = 'load_lora' + CATEGORY = 'WAS Suite/Loaders' + + def load_lora(self, model, clip, lora_name, strength_model, strength_clip): + if strength_model == 0 and strength_clip == 0: + return (model, clip) + lora_path = comfy_paths.get_full_path('loras', lora_name) + lora = None + if self.loaded_lora is not None: + if self.loaded_lora[0] == lora_path: + lora = self.loaded_lora[1] + else: + temp = self.loaded_lora + self.loaded_lora = None + del temp + if lora is None: + lora = comfy.utils.load_torch_file(lora_path, safe_load=True) + self.loaded_lora = (lora_path, lora) + (model_lora, clip_lora) = comfy.sd.load_lora_for_models(model, clip, lora, strength_model, strength_clip) + return (model_lora, clip_lora, os.path.splitext(os.path.basename(lora_name))[0]) +``` \ No newline at end of file diff --git a/docs/Load Motion Camera Preset.md b/docs/Load Motion Camera Preset.md new file mode 100644 index 0000000..e066181 --- /dev/null +++ b/docs/Load Motion Camera Preset.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: LoadMotionCameraPreset +- Category: motionctrl +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-MotionCtrl.git + +该节点旨在检索和加载预定义的相机运动预设,以便于在运动捕捉场景中实现动态相机控制。 + +# Input types +## Required +- motion_camera + - motion_camera参数指定要加载的预设,这对于确定运动序列中相机的位置和方向至关重要。 + - Comfy dtype: COMBO[MOTION_CAMERA_OPTIONS] + - Python dtype: str + +# Output types +- POINTS + - 输出提供已加载的相机预设数据,这对于在系统中应用指定的相机运动至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadMotionCameraPreset: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'motion_camera': (MOTION_CAMERA_OPTIONS,)}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('POINTS',) + FUNCTION = 'load_motion_camera_preset' + CATEGORY = 'motionctrl' + + def load_motion_camera_preset(self, motion_camera): + data = '[]' + comfy_path = os.path.dirname(folder_paths.__file__) + with open(f'{comfy_path}/custom_nodes/ComfyUI-MotionCtrl/examples/camera_poses/test_camera_{motion_camera}.json') as f: + data = f.read() + return (data,) +``` \ No newline at end of file diff --git a/docs/Load Motion Traj Preset.md b/docs/Load Motion Traj Preset.md new file mode 100644 index 0000000..45e4151 --- /dev/null +++ b/docs/Load Motion Traj Preset.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: LoadMotionTrajPreset +- Category: motionctrl +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-MotionCtrl.git + +LoadMotionTrajPreset节点旨在为运动控制应用加载和处理预定义的运动轨迹。它接受特定的运动轨迹预设和帧长度,然后从文本文件中读取并缩放点以匹配所需的帧长度,确保与运动控制系统的无缝集成。 + +# Input types +## Required +- motion_traj + - motion_traj参数指定要加载的运动轨迹预设的名称。它对于确定节点将处理的特定运动模式至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- frame_length + - frame_length参数允许用户定义运动轨迹的帧数。这对于调整运动以适应动画或模拟所需的持续时间非常重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- POINTS + - POINTS输出包含代表运动轨迹的处理后的点列表,准备用于下游运动控制过程。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadMotionTrajPreset: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'motion_traj': (MOTION_TRAJ_OPTIONS,), 'frame_length': ('INT', {'default': 16})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('POINTS',) + FUNCTION = 'load_motion_traj_preset' + CATEGORY = 'motionctrl' + + def load_motion_traj_preset(self, motion_traj, frame_length): + comfy_path = os.path.dirname(folder_paths.__file__) + points = read_points(f'{comfy_path}/custom_nodes/ComfyUI-MotionCtrl/examples/trajectories/{motion_traj}.txt', frame_length) + return (json.dumps(points),) +``` \ No newline at end of file diff --git a/docs/Load MotionBrush From Optical Flow Directory.md b/docs/Load MotionBrush From Optical Flow Directory.md new file mode 100644 index 0000000..90b6058 --- /dev/null +++ b/docs/Load MotionBrush From Optical Flow Directory.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: LoadMotionBrushFromOpticalFlowDirectory +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +该节点能够从指定目录中的光流文件中提取和处理运动数据,用于生成运动刷子以供进一步分析和应用。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了用于处理光流数据的特定算法或框架,影响运动刷子生成的准确性和效率。 + - Comfy dtype: DragNUWA + - Python dtype: DragNUWA +- optical_flow_directory + - 该参数指定包含光流文件的目录,对于节点定位和处理所需的运动数据至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- MotionBrush + - 输出代表以运动刷子形式处理后的运动数据,可用于动画、视频编辑和效果生成等多种应用。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadMotionBrushFromOpticalFlowDirectory: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('DragNUWA',), 'optical_flow_directory': ('STRING', {'default': 'X://path/to/optical_flow', 'vhs_path_extensions': []})}} + RETURN_TYPES = ('MotionBrush',) + FUNCTION = 'run_inference' + CATEGORY = 'DragNUWA' + + def run_inference(self, model, optical_flow_directory): + return (model.load_motionbrush_from_optical_flow_directory(optical_flow_directory),) +``` \ No newline at end of file diff --git a/docs/Load MotionBrush From Optical Flow Without Model.md b/docs/Load MotionBrush From Optical Flow Without Model.md new file mode 100644 index 0000000..aff78c8 --- /dev/null +++ b/docs/Load MotionBrush From Optical Flow Without Model.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: LoadMotionBrushFromOpticalFlowWithoutModel +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +该节点有助于解释光流数据以生成运动刷效果,这对于视觉模拟和效果生成至关重要,且不依赖于预训练模型。 + +# Input types +## Required +- optical_flow + - 光流数据至关重要,因为它提供了推断运动模式并创建运动刷效果所需的基础信息。 + - Comfy dtype: OPTICAL_FLOW + - Python dtype: numpy.ndarray + +# Output types +- MotionBrush + - 输出代表合成的运动刷,包含了从光流数据中推断出的运动模式。 + - Comfy dtype: MOTION_BRUSH + - Python dtype: tuple + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadMotionBrushFromOpticalFlowWithoutModel: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'optical_flow': ('OPTICAL_FLOW',)}} + RETURN_TYPES = ('MotionBrush',) + FUNCTION = 'run_inference' + CATEGORY = 'DragNUWA' + + def run_inference(self, optical_flow): + return (optical_flow,) +``` \ No newline at end of file diff --git a/docs/Load MotionBrush From Optical Flow.md b/docs/Load MotionBrush From Optical Flow.md new file mode 100644 index 0000000..c94e14f --- /dev/null +++ b/docs/Load MotionBrush From Optical Flow.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: LoadMotionBrushFromOpticalFlow +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +该节点能够从光流数据生成运动刷,使用户能够利用运动信息进行视频处理或动画等多种应用。 + +# Input types +## Required +- model + - 模型参数对于运动刷生成过程至关重要,它定义了生成过程的基础架构和参数。 + - Comfy dtype: DragNUWA + - Python dtype: torch.nn.Module +- optical_flow + - 光流输入对于节点来说是必不可少的,因为它提供了创建运动刷所需的运动信息。 + - Comfy dtype: OPTICAL_FLOW + - Python dtype: torch.Tensor + +# Output types +- MotionBrush + - 输出代表生成的运动刷,以结构化格式封装了运动信息。 + - Comfy dtype: MOTION_BRUSH + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LoadMotionBrushFromOpticalFlow: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('DragNUWA',), 'optical_flow': ('OPTICAL_FLOW',)}} + RETURN_TYPES = ('MotionBrush',) + FUNCTION = 'run_inference' + CATEGORY = 'DragNUWA' + + def run_inference(self, model, optical_flow): + return (model.load_motionbrush_from_optical_flow(optical_flow),) +``` \ No newline at end of file diff --git a/docs/Load MotionBrush From Tracking Points Without Model.md b/docs/Load MotionBrush From Tracking Points Without Model.md new file mode 100644 index 0000000..d3ec685 --- /dev/null +++ b/docs/Load MotionBrush From Tracking Points Without Model.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: LoadMotionBrushFromTrackingPointsWithoutModel +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +该节点抽象了无需预存模型即可从跟踪点生成运动数据的过程,便于用户根据提供的跟踪点创建运动刷。 + +# Input types +## Required +- model_length + - 模型长度参数决定了运动序列的持续时间,这对节点的运行至关重要,因为它决定了输出运动刷的帧数。 + - Comfy dtype: INT + - Python dtype: int +- width + - 宽度参数指定了运动刷的水平分辨率,这对于建立运动数据的空间上下文至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数定义了运动刷的垂直分辨率,通过确定输出的空间维度,在节点功能中扮演关键角色。 + - Comfy dtype: INT + - Python dtype: int +- tracking_points + - 跟踪点参数是必需的,因为它提供了用于构建运动刷的原始跟踪数据,直接影响运动的质量和准确性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- MotionBrush + - 输出MotionBrush是一个张量,表示在指定的持续时间和空间维度上的运动数据,包含了节点的主要功能。 + - Comfy dtype: TORCH_TENSOR + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadMotionBrushFromTrackingPointsWithoutModel: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model_length': ('INT', {'default': 14}), 'width': ('INT', {'default': 36}), 'height': ('INT', {'default': 20}), 'tracking_points': ('STRING', {'multiline': True, 'default': '[[[1,1],[2,2]]]'})}} + RETURN_TYPES = ('MotionBrush',) + FUNCTION = 'run_inference' + CATEGORY = 'DragNUWA' + + def run_inference(self, model_length, width, height, tracking_points): + tracking_points = json.loads(tracking_points) + motionbrush = load_motionbrush_from_tracking_points_without_model(model_length, width, height, tracking_points) + return (motionbrush,) +``` \ No newline at end of file diff --git a/docs/Load MotionBrush From Tracking Points.md b/docs/Load MotionBrush From Tracking Points.md new file mode 100644 index 0000000..a35a855 --- /dev/null +++ b/docs/Load MotionBrush From Tracking Points.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: LoadMotionBrushFromTrackingPoints +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +该节点通过解释跟踪点来促进运动刷子的创建,生成代表序列中运动的向量场。 + +# Input types +## Required +- tracking_points + - 跟踪点是必需的,因为它们为运动检测和刷子创建提供源数据,决定了节点的输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- MotionBrush + - 输出代表了一个详细的运动向量场,对于可视化和应用运动效果至关重要。 + - Comfy dtype: TENSOR + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadMotionBrushFromTrackingPoints: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('DragNUWA',), 'tracking_points': ('STRING', {'multiline': True, 'default': '[[[25,25],[128,128]]]'})}} + RETURN_TYPES = ('MotionBrush',) + FUNCTION = 'run_inference' + CATEGORY = 'DragNUWA' + + def run_inference(self, model, tracking_points): + return (model.load_motionbrush_from_tracking_points(tracking_points),) +``` \ No newline at end of file diff --git a/docs/Load Motionctrl Checkpoint.md b/docs/Load Motionctrl Checkpoint.md new file mode 100644 index 0000000..b0400d0 --- /dev/null +++ b/docs/Load Motionctrl Checkpoint.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: MotionctrlLoader +- Category: motionctrl +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-MotionCtrl.git + +MotionctrlLoader 类旨在高效管理和加载运动控制检查点,用于高级运动分析和生成任务。它抽象了加载和初始化运动控制模型的复杂性,为用户提供了一个简化的接口,以便利用运动控制功能。 + +# Input types +## Required +- ckpt_name + - 检查点名称是一个关键参数,它指定要加载的模型检查点。这对于确定正确的预训练模型权重和架构至关重要。 + - Comfy dtype: str + - Python dtype: str +- frame_length + - 帧长参数决定了运动控制模型的时间范围。它对于调整模型以处理不同持续时间的运动序列非常重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- model + - 模型输出代表已加载的运动控制模型,可用于推理或进一步处理。它封装了运动序列生成或分析所必需的运动的模式和动态。 + - Comfy dtype: MOTIONCTRL + - Python dtype: torch.nn.Module +- clip + - clip 输出是运动控制模型的嵌入器组件,负责从运动序列中提取特征。它在模型理解和处理运动数据的能力中起着至关重要的作用。 + - Comfy dtype: EMBEDDER + - Python dtype: torch.nn.Module +- vae + - vae 输出指的是运动控制模型中的变分自编码器部分,它在将运动数据编码和解码到较低维度的潜在空间中起着重要作用。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- ddim_sampler + - ddim_sampler 输出是基于已加载的运动控制模型生成新运动序列的采样机制。它提供了一种创建多样化和现实运动输出的方法。 + - Comfy dtype: SAMPLER + - Python dtype: DDIMSampler + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MotionctrlLoader: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'ckpt_name': (['motionctrl.pth'], {'default': 'motionctrl.pth'}), 'frame_length': ('INT', {'default': 16})}} + RETURN_TYPES = ('MOTIONCTRL', 'EMBEDDER', 'VAE', 'SAMPLER') + RETURN_NAMES = ('model', 'clip', 'vae', 'ddim_sampler') + FUNCTION = 'load_checkpoint' + CATEGORY = 'motionctrl' + + def load_checkpoint(self, ckpt_name, frame_length): + gpu_num = 1 + gpu_no = 0 + ckpt_path = folder_paths.get_full_path('checkpoints', ckpt_name) + comfy_path = os.path.dirname(folder_paths.__file__) + config_path = os.path.join(comfy_path, 'custom_nodes/ComfyUI-MotionCtrl/configs/inference/config_both.yaml') + args = {'ckpt_path': f'{ckpt_path}', 'adapter_ckpt': None, 'base': f'{config_path}', 'condtype': 'both', 'prompt_dir': None, 'n_samples': 1, 'ddim_steps': 50, 'ddim_eta': 1.0, 'bs': 1, 'height': 256, 'width': 256, 'unconditional_guidance_scale': 1.0, 'unconditional_guidance_scale_temporal': None, 'seed': 1234, 'cond_T': 800} + config = OmegaConf.load(args['base']) + OmegaConf.update(config, 'model.params.unet_config.params.temporal_length', frame_length) + model_config = config.pop('model', OmegaConf.create()) + model = instantiate_from_config(model_config) + model = model.cuda(gpu_no) + assert os.path.exists(args['ckpt_path']), f"Error: checkpoint {args['ckpt_path']} Not Found!" + print(f"Loading checkpoint from {args['ckpt_path']}") + model = load_model_checkpoint(model, args['ckpt_path'], args['adapter_ckpt']) + model.eval() + ddim_sampler = DDIMSampler(model) + return (model, model.cond_stage_model, model.first_stage_model, ddim_sampler) +``` \ No newline at end of file diff --git a/docs/Load Motionctrl-SVD Camera Preset.md b/docs/Load Motionctrl-SVD Camera Preset.md new file mode 100644 index 0000000..0596f24 --- /dev/null +++ b/docs/Load Motionctrl-SVD Camera Preset.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: LoadMotionCtrlSVDCameraPreset +- Category: motionctrl +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-MotionCtrl-SVD.git + +该节点旨在为3D环境中的运动控制加载预定义的相机预设。它使用户能够选择并应用不同的相机视角,以增强视觉叙事或模拟场景。 + +# Input types +## Required +- motion_camera + - ‘motion_camera’参数对节点的操作至关重要,因为它决定了要加载的特定相机预设。这个选择可以显著影响运动控制过程的结果,影响最终的可视化或模拟。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- POINTS + - 输出‘POINTS’代表加载的相机预设数据,其中包含相机定位和方向的参数。这些数据对于在3D应用程序中实现所需的运动控制效果至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadMotionCtrlSVDCameraPreset: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'motion_camera': (MOTION_CAMERA_OPTIONS,)}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('POINTS',) + FUNCTION = 'load_motion_camera_preset' + CATEGORY = 'motionctrl' + + def load_motion_camera_preset(self, motion_camera): + data = '[]' + comfy_path = os.path.dirname(folder_paths.__file__) + with open(f'{comfy_path}/custom_nodes/ComfyUI-MotionCtrl-SVD/examples/camera_poses/test_camera_{motion_camera}.json') as f: + data = f.read() + return (data,) +``` \ No newline at end of file diff --git a/docs/Load Motionctrl-SVD Checkpoint.md b/docs/Load Motionctrl-SVD Checkpoint.md new file mode 100644 index 0000000..7a989e3 --- /dev/null +++ b/docs/Load Motionctrl-SVD Checkpoint.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: MotionctrlSVDLoader +- Category: motionctrl +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-MotionCtrl-SVD.git + +MotionctrlSVDLoader类是初始化和管理Motionctrl-SVD模型的关键组件,专注于高效地加载和准备模型以供执行。它封装了检索检查点和根据指定参数配置模型的过程,确保模型准备好进行运动序列的分析和合成任务。 + +# Input types +## Required +- ckpt_name + - ckpt_name参数对于指定Motionctrl-SVD模型的检查点文件名至关重要。它指导加载器使用正确的模型状态,这对于后续的模型操作和结果至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- frame_length + - frame_length参数很重要,因为它定义了模型输入数据的时间维度。它影响模型处理和生成给定帧跨度内连贯运动序列的能力。 + - Comfy dtype: INT + - Python dtype: int +- steps + - steps参数对于确定模型在其操作过程中将执行的迭代次数至关重要。它直接影响计算效率和生成的运动序列的质量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- model + - 输出模型代表加载和配置好的Motionctrl-SVD,准备用于运动序列分析和合成。它是输入参数和加载器功能的结晶,封装了模型用于进一步使用的能力。 + - Comfy dtype: MOTIONCTRLSVD + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MotionctrlSVDLoader: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'ckpt_name': (['motionctrl_svd.ckpt'], {'default': 'motionctrl_svd.ckpt'}), 'frame_length': ('INT', {'default': 14}), 'steps': ('INT', {'default': 25})}} + RETURN_TYPES = ('MOTIONCTRLSVD',) + RETURN_NAMES = ('model',) + FUNCTION = 'load_checkpoint' + CATEGORY = 'motionctrl' + + def load_checkpoint(self, ckpt_name, frame_length, steps): + global device + comfy_path = os.path.dirname(folder_paths.__file__) + ckpt_path = folder_paths.get_full_path('checkpoints', ckpt_name) + config_path = os.path.join(comfy_path, 'custom_nodes/ComfyUI-MotionCtrl-SVD/configs/inference/config_motionctrl_cmcm.yaml') + if not os.path.exists(ckpt_path): + os.system(f'wget https://huggingface.co/TencentARC/MotionCtrl/resolve/main/motionctrl_svd.ckpt?download=true -P .') + os.system(f'mv motionctrl_svd.ckpt?download=true {ckpt_path}') + model = build_model(config_path, ckpt_path, device, frame_length, steps) + return (model,) +``` \ No newline at end of file diff --git a/docs/Load Pose KeyPoints.md b/docs/Load Pose KeyPoints.md new file mode 100644 index 0000000..f554ee1 --- /dev/null +++ b/docs/Load Pose KeyPoints.md @@ -0,0 +1,40 @@ +# Documentation +- Class name: LoadPoseKeyPoints +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +该节点旨在从指定文件中检索和解析姿态关键点数据,便于在系统中分析和处理人体姿态信息。 + +# Input types +## Required +- file_name + - file_name参数至关重要,因为它标识了节点将要处理的姿态关键点数据所在的特定文件。 + - Comfy dtype: COMBO[(os.listdir(folder_paths.output_directory), {'default': 'PoseKeypoint_00001.json'})] + - Python dtype: Union[str, None] + +# Output types +- POSE_KEYPOINT + - 输出提供了姿态关键点数据的结构化表示,使得在系统中能够进行进一步的处理和分析。 + - Comfy dtype: JSON + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadPoseKeyPoints: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'file_name': (os.listdir(folder_paths.output_directory), {'default': 'PoseKeypoint_00001.json'})}} + RETURN_TYPES = ('POSE_KEYPOINT',) + FUNCTION = 'run' + CATEGORY = 'DragNUWA' + + def run(self, file_name): + path = os.path.join(folder_paths.output_directory, file_name) + with open(path) as fr: + return (json.load(fr),) +``` \ No newline at end of file diff --git a/docs/Load Text File.md b/docs/Load Text File.md new file mode 100644 index 0000000..33c1057 --- /dev/null +++ b/docs/Load Text File.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: WAS_Text_Load_From_File +- Category: WAS Suite/IO +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_Load_From_File 节点旨在将指定文件路径中的文本数据加载到结构化格式中。它读取文件的内容,并将文本组织成列表,排除掉注释或空行。该节点还能够根据给定的字典名称重命名文件的标识符,允许更灵活的数据处理。 + +# Input types +## Required +- file_path + - file_path 参数对节点的操作至关重要,因为它指定了要加载的文件的位置。节点读取此路径上的文件并处理其内容。缺少有效的文件路径将导致错误,节点将无法按预期工作。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- dictionary_name + - dictionary_name 参数允许用户为文本文件的标识符分配一个自定义名称,这对于在应用程序内组织和引用数据非常有用。如果没有提供,节点将默认使用文件名作为标识符。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- joined_text + - joined_text 输出是表示加载文件内容的连接字符串,已去除所有非必要行。这个输出很重要,因为它提供了一个干净、单一的字符串,可以很容易地进行处理或显示。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str +- dictionary + - dictionary 输出是文件内容的结构化表示,其中文件的标识符是键,处理过的行列表是值。这个输出很重要,因为它以一种易于在应用程序中访问和操作的方式组织文本数据。 + - Comfy dtype: DICT + - Python dtype: Dict[str, List[str]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Load_From_File: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'file_path': ('STRING', {'default': '', 'multiline': False}), 'dictionary_name': ('STRING', {'default': '[filename]', 'multiline': False})}} + RETURN_TYPES = (TEXT_TYPE, 'DICT') + FUNCTION = 'load_file' + CATEGORY = 'WAS Suite/IO' + + def load_file(self, file_path='', dictionary_name='[filename]]'): + filename = os.path.basename(file_path).split('.', 1)[0] if '.' in os.path.basename(file_path) else os.path.basename(file_path) + if dictionary_name != '[filename]': + filename = dictionary_name + if not os.path.exists(file_path): + cstr(f'The path `{file_path}` specified cannot be found.').error.print() + return ('', {filename: []}) + with open(file_path, 'r', encoding='utf-8', newline='\n') as file: + text = file.read() + update_history_text_files(file_path) + import io + lines = [] + for line in io.StringIO(text): + if not line.strip().startswith('#'): + if not line.strip().startswith('\n') or not line.strip().startswith('\r') or (not line.strip().startswith('\r\n')): + line = line.replace('\n', '').replace('\r', '').replace('\r\n', '') + lines.append(line.replace('\n', '').replace('\r', '').replace('\r\n', '')) + dictionary = {filename: lines} + return ('\n'.join(lines), dictionary) +``` \ No newline at end of file diff --git a/docs/LoadImage %2F%2FInspire.md b/docs/LoadImage %2F%2FInspire.md new file mode 100644 index 0000000..8e85aae --- /dev/null +++ b/docs/LoadImage %2F%2FInspire.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: LoadImageInspire +- Category: InspirePack/image +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点便于加载和预处理图像,将其转换为适合进一步分析和操作的格式。它强调将原始图像数据转换为结构化数组,为下游任务如特征提取或图像分类做好准备。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它指定了将要进行处理的源图像。它的选择影响了结果图像数据的质量和适用性。 + - Comfy dtype: COMBO[sorted(files) + ['#DATA']] + - Python dtype: PIL.Image +## Optional +- image_data + - 该参数包含编码后的图像数据,对于节点执行其主要功能——图像加载和转换至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- image + - 输出图像是输入的转换和结构化表示,为系统内进一步分析或处理做好了准备。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- mask + - 掩码输出提供了一个二进制表示,可用于各种与图像相关的操作,增强了节点应用的多功能性。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadImageInspire: + + @classmethod + def INPUT_TYPES(s): + input_dir = folder_paths.get_input_directory() + files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))] + return {'required': {'image': (sorted(files) + ['#DATA'], {'image_upload': True}), 'image_data': ('STRING', {'multiline': False})}} + CATEGORY = 'InspirePack/image' + RETURN_TYPES = ('IMAGE', 'MASK') + FUNCTION = 'load_image' + + def load_image(self, image, image_data): + image_data = base64.b64decode(image_data.split(',')[1]) + i = Image.open(BytesIO(image_data)) + i = ImageOps.exif_transpose(i) + image = i.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + if 'A' in i.getbands(): + mask = np.array(i.getchannel('A')).astype(np.float32) / 255.0 + mask = 1.0 - torch.from_numpy(mask) + else: + mask = torch.zeros((64, 64), dtype=torch.float32, device='cpu') + return (image, mask.unsqueeze(0)) +``` \ No newline at end of file diff --git a/docs/LoadOOTDPipeline.md b/docs/LoadOOTDPipeline.md new file mode 100644 index 0000000..cd6ab09 --- /dev/null +++ b/docs/LoadOOTDPipeline.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: LoadOOTDPipeline +- Category: OOTD +- Output node: False +- Repo Ref: https://github.com/AuroBit/ComfyUI-OOTDiffusion.git + +该节点旨在实例化并提供对OOTDiffusion模型的访问,该模型能够根据文本描述生成与时尚相关的图像。它抽象了模型加载和设置的复杂性,确保模型准备好进行推理任务,而不需要详细了解底层架构或训练过程。 + +# Input types +## Required +- type + - ‘type’参数对于确定要加载的OOTDiffusion模型的特定配置至关重要。它决定了模型是为生成半身('Half body')还是全身('Full body')服装的图像而优化。这个选择显著影响模型的性能和输出质量。 + - Comfy dtype: COMBO['Half body', 'Full body'] + - Python dtype: str +- path + - ‘path’参数至关重要,因为它指向存储OOTDiffusion模型及其相关文件的目录。这包括模型权重、配置文件和任何其他必要的数据。正确的路径确保节点能够成功加载并初始化模型以进行图像生成任务。 + - Comfy dtype: string + - Python dtype: str + +# Output types +- pipe + - ‘pipe’输出是已加载的OOTDiffusion模型,准备用于生成时尚图像。它封装了模型的功能,并允许与系统的其余部分无缝交互,以完成各种图像生成任务。 + - Comfy dtype: object + - Python dtype: OOTDiffusion + +# Usage tips +- Infra type: GPU + +# Source code +``` +class LoadOOTDPipeline: + display_name = 'Load OOTDiffusion Local' + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'type': (['Half body', 'Full body'],), 'path': (['/data/app/aigc-worker-v3/models/OOTDiffusion'], {'default': '/data/app/aigc-worker-v3/models/OOTDiffusion'})}} + RETURN_TYPES = ('MODEL',) + RETURN_NAMES = ('pipe',) + FUNCTION = 'load' + CATEGORY = 'OOTD' + + @staticmethod + def load_impl(type, path): + if type == 'Half body': + type = 'hd' + elif type == 'Full body': + type = 'dc' + else: + raise ValueError(f"unknown input type {type} must be 'Half body' or 'Full body'") + if not os.path.isdir(path): + raise ValueError(f'input path {path} is not a directory') + return OOTDiffusion(path, model_type=type) + + def load(self, type, path): + return (self.load_impl(type, path),) +``` \ No newline at end of file diff --git a/docs/LoadPromptsFromFile %2F%2FInspire.md b/docs/LoadPromptsFromFile %2F%2FInspire.md new file mode 100644 index 0000000..fa6b8c4 --- /dev/null +++ b/docs/LoadPromptsFromFile %2F%2FInspire.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: LoadPromptsFromFile +- Category: InspirePack/Prompt +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +LoadPromptsFromFile节点旨在从一个指定目录中读取和解析提示文件。它从每个文件中提取正面和负面的文本段落,遵循预定义的格式,并将它们组织成元组。该节点在准备进一步处理的提示数据中扮演着关键角色,例如训练或评估生成模型。 + +# Input types +## Required +- prompt_file + - 'prompt_file'参数是一个字符串,指定包含提示的文本文件的相对路径。它对节点的操作至关重要,因为它决定了要加载和处理的提示的来源。 + - Comfy dtype: "str" + - Python dtype: str + +# Output types +- ZIPPED_PROMPT + - 'ZIPPED_PROMPT'输出是一个元组列表,每个元组包含从提示文件中提取的正面和负面文本段落,以及文件的名称。这个输出很重要,因为它提供了下游任务所需的结构化数据。 + - Comfy dtype: COMBO["str", "str", "str"] + - Python dtype: Tuple[str, str, str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadPromptsFromFile: + + @classmethod + def INPUT_TYPES(cls): + global prompts_path + try: + prompt_files = [] + for (root, dirs, files) in os.walk(prompts_path): + for file in files: + if file.endswith('.txt'): + file_path = os.path.join(root, file) + rel_path = os.path.relpath(file_path, prompts_path) + prompt_files.append(rel_path) + except Exception: + prompt_files = [] + return {'required': {'prompt_file': (prompt_files,)}} + RETURN_TYPES = ('ZIPPED_PROMPT',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Prompt' + + def doit(self, prompt_file): + prompt_path = os.path.join(prompts_path, prompt_file) + prompts = [] + try: + with open(prompt_path, 'r', encoding='utf-8') as file: + prompt_data = file.read() + prompt_list = re.split('\\n\\s*-+\\s*\\n', prompt_data) + pattern = 'positive:(.*?)(?:\\n*|$)negative:(.*)' + for prompt in prompt_list: + matches = re.search(pattern, prompt, re.DOTALL) + if matches: + positive_text = matches.group(1).strip() + negative_text = matches.group(2).strip() + result_tuple = (positive_text, negative_text, prompt_file) + prompts.append(result_tuple) + else: + print(f"[WARN] LoadPromptsFromFile: invalid prompt format in '{prompt_file}'") + except Exception as e: + print(f"[ERROR] LoadPromptsFromFile: an error occurred while processing '{prompt_file}': {str(e)}") + return (prompts,) +``` \ No newline at end of file diff --git a/docs/LoadResAdapterNormalization.md b/docs/LoadResAdapterNormalization.md new file mode 100644 index 0000000..210984d --- /dev/null +++ b/docs/LoadResAdapterNormalization.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: LoadResAdapterNormalization +- Category: KJNodes/experimental +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +方法 `load_res_adapter` 旨在将 ResAdapter 标准化权重集成到给定模型中。它确保从指定路径正确加载权重并将其应用于模型的标准化层,增强了模型处理具有标准化特征的输入数据的能力。 + +# Input types +## Required +- model + - 参数 'model' 是必需的,因为它代表了将要应用 ResAdapter 标准化权重的机器学习模型。它是一个关键组件,决定了节点的功能和标准化过程的结果。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- resadapter_path + - 参数 'resadapter_path' 指定了存储 ResAdapter 标准化权重的目录路径。对于节点来说,找到并加载正确的权重至关重要,以确保成功地将标准化应用于模型。 + - Comfy dtype: folder_paths.get_filename_list('checkpoints') + - Python dtype: List[str] + +# Output types +- model_clone + - 输出 'model_clone' 是应用了 ResAdapter 标准化权重的原始模型。它标志权重成功集成,允许模型使用标准化特性以改进数据处理。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadResAdapterNormalization: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'resadapter_path': (folder_paths.get_filename_list('checkpoints'),)}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'load_res_adapter' + CATEGORY = 'KJNodes/experimental' + + def load_res_adapter(self, model, resadapter_path): + print('ResAdapter: Checking ResAdapter path') + resadapter_full_path = folder_paths.get_full_path('checkpoints', resadapter_path) + if not os.path.exists(resadapter_full_path): + raise Exception('Invalid model path') + else: + print('ResAdapter: Loading ResAdapter normalization weights') + prefix_to_remove = 'diffusion_model.' + model_clone = model.clone() + norm_state_dict = comfy.utils.load_torch_file(resadapter_full_path) + new_values = {key[len(prefix_to_remove):]: value for (key, value) in norm_state_dict.items() if key.startswith(prefix_to_remove)} + print('ResAdapter: Attempting to add patches with ResAdapter weights') + try: + for key in model.model.diffusion_model.state_dict().keys(): + if key in new_values: + original_tensor = model.model.diffusion_model.state_dict()[key] + new_tensor = new_values[key].to(model.model.diffusion_model.dtype) + if original_tensor.shape == new_tensor.shape: + model_clone.add_object_patch(f'diffusion_model.{key}.data', new_tensor) + else: + print('ResAdapter: No match for key: ', key) + except: + raise Exception('Could not patch model, this way of patching was added to ComfyUI on March 3rd 2024, is your ComfyUI up to date?') + print('ResAdapter: Added resnet normalization patches') + return (model_clone,) +``` \ No newline at end of file diff --git a/docs/LoadSinglePromptFromFile %2F%2FInspire.md b/docs/LoadSinglePromptFromFile %2F%2FInspire.md new file mode 100644 index 0000000..90a36c7 --- /dev/null +++ b/docs/LoadSinglePromptFromFile %2F%2FInspire.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: LoadSinglePromptFromFile +- Category: InspirePack/Prompt +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在从指定文件中提取和处理文本提示,使用户能够在系统中以结构化的方式利用预定义的提示。 + +# Input types +## Required +- prompt_file + - prompt_file 参数至关重要,因为它标识了将从中加载提示的特定文本文件。它通过确定提示的来源影响节点的操作。 + - Comfy dtype: COMBO[prompt_files] + - Python dtype: str +## Optional +- index + - index 参数很重要,因为它指定了文件中所需提示的位置。它通过选择特定的提示进行处理来影响节点的执行。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- zipped_prompt + - 输出提供了一个包含提示的正面和负面方面的元组,以及文件名,这对于系统内的进一步分析和应用至关重要。 + - Comfy dtype: ZIPPED_PROMPT + - Python dtype: Tuple[str, str, str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadSinglePromptFromFile: + + @classmethod + def INPUT_TYPES(cls): + global prompts_path + try: + prompt_files = [] + for (root, dirs, files) in os.walk(prompts_path): + for file in files: + if file.endswith('.txt'): + file_path = os.path.join(root, file) + rel_path = os.path.relpath(file_path, prompts_path) + prompt_files.append(rel_path) + except Exception: + prompt_files = [] + return {'required': {'prompt_file': (prompt_files,), 'index': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('ZIPPED_PROMPT',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Prompt' + + def doit(self, prompt_file, index): + prompt_path = os.path.join(prompts_path, prompt_file) + prompts = [] + try: + with open(prompt_path, 'r', encoding='utf-8') as file: + prompt_data = file.read() + prompt_list = re.split('\\n\\s*-+\\s*\\n', prompt_data) + try: + prompt = prompt_list[index] + except Exception: + prompt = prompt_list[-1] + pattern = 'positive:(.*?)(?:\\n*|$)negative:(.*)' + matches = re.search(pattern, prompt, re.DOTALL) + if matches: + positive_text = matches.group(1).strip() + negative_text = matches.group(2).strip() + result_tuple = (positive_text, negative_text, prompt_file) + prompts.append(result_tuple) + else: + print(f"[WARN] LoadPromptsFromFile: invalid prompt format in '{prompt_file}'") + except Exception as e: + print(f"[ERROR] LoadPromptsFromFile: an error occurred while processing '{prompt_file}': {str(e)}") + return (prompts,) +``` \ No newline at end of file diff --git a/docs/LoadTextFile.md b/docs/LoadTextFile.md new file mode 100644 index 0000000..e048a93 --- /dev/null +++ b/docs/LoadTextFile.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: LoadTextFile +- Category: 😺dzNodes/WordCloud +- Output node: True +- Repo Ref: https://github.com/chflame163/ComfyUI_WordCloud.git + +LoadTextFile节点旨在读取并检索指定文本文件的内容。它通过打开给定路径的文件并以UTF-8编码来操作,确保与各种字符集兼容。该节点的主要功能是为工作流中的进一步处理或分析提供文本数据。 + +# Input types +## Required +- path + - ‘path’参数对于节点的操作至关重要,因为它指定了要加载的文本文件的位置。它直接影响节点访问和读取文件内容的能力,这对于工作流中的后续任务至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- Text + - 'Text'输出参数代表加载的文本文件的内容。它很重要,因为它是节点的主要输出,为下游处理或分析提供文本数据。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadTextFile: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'path': ('STRING', {'default': 'c:\\text.txt'})}, 'optional': {}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('Text',) + FUNCTION = 'load_text_file' + OUTPUT_NODE = True + CATEGORY = '😺dzNodes/WordCloud' + + def load_text_file(self, path): + text_content = '' + try: + with open(os.path.normpath(path), 'r', encoding='utf-8') as f: + text_content = ''.join((str(l) for l in f.read())) + print('# 😺dzNodes: Load Text File -> ' + path + ' success.') + except Exception as e: + print('# 😺dzNodes: Load Text File -> ERROR, ' + path + ', ' + repr(e)) + return {'ui': {'text': text_content}, 'result': (text_content,)} +``` \ No newline at end of file diff --git a/docs/LoadVideo(ArtVentureX%2Fcomfyui-animatediff).md b/docs/LoadVideo(ArtVentureX%2Fcomfyui-animatediff).md new file mode 100644 index 0000000..6feab8d --- /dev/null +++ b/docs/LoadVideo(ArtVentureX%2Fcomfyui-animatediff).md @@ -0,0 +1,106 @@ +# Documentation +- Class name: LoadVideo +- Category: Animate Diff/Utils +- Output node: False +- Repo Ref: https://github.com/ArtVentureX/comfyui-animatediff.git + +该节点旨在从视频文件中提取帧,允许根据起始点和限制选择特定的帧范围。它使得这些帧可以用于各种应用的进一步处理,例如动画或差异分析。 + +# Input types +## Required +- video + - 视频参数至关重要,因为它定义了将从中提取帧的来源。它通过确定将要处理的内容和帧序列来影响节点的操作。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- frame_start + - frame_start 参数指示应从哪个初始帧号开始提取。它通过设置帧选择的起始点来影响节点的执行。 + - Comfy dtype: INT + - Python dtype: int +- frame_limit + - frame_limit 参数定义了在 frame_start 之后要提取的最大帧数。它直接影响节点处理的帧数量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- frames + - frames 输出是一系列提取的视频帧,转换成张量格式,对于下游过程中的进一步分析或操作至关重要。 + - Comfy dtype: TENSOR + - Python dtype: torch.Tensor +- frame_count + - frame_count 输出提供了提取的帧总数,为节点处理的数据量提供了参考。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadVideo: + + @classmethod + def INPUT_TYPES(s): + input_dir = os.path.join(folder_paths.get_input_directory(), 'video') + if not os.path.exists(input_dir): + os.makedirs(input_dir, exist_ok=True) + files = [f'video/{f}' for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))] + return {'required': {'video': (sorted(files), {'video_upload': True})}, 'optional': {'frame_start': ('INT', {'default': 0, 'min': 0, 'max': 4294967295, 'step': 1}), 'frame_limit': ('INT', {'default': 16, 'min': 1, 'max': 10240, 'step': 1})}} + CATEGORY = 'Animate Diff/Utils' + RETURN_TYPES = ('IMAGE', 'INT') + RETURN_NAMES = ('frames', 'frame_count') + FUNCTION = 'load' + + def load_gif(self, gif_path: str, frame_start: int, frame_limit: int): + image = Image.open(gif_path) + frames = [] + for (i, frame) in enumerate(ImageSequence.Iterator(image)): + if i < frame_start: + continue + elif i >= frame_start + frame_limit: + break + else: + frames.append(pil2tensor(frame.copy().convert('RGB'))) + return frames + + def load_video(self, video_path, frame_start: int, frame_limit: int): + ensure_opencv() + import cv2 + video = cv2.VideoCapture(video_path) + video.set(cv2.CAP_PROP_POS_FRAMES, frame_start) + frames = [] + for i in range(frame_limit): + (ret, frame) = video.read() + if ret: + frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + frames.append(pil2tensor(Image.fromarray(frame))) + else: + break + video.release() + return frames + + def load(self, video: str, frame_start=0, frame_limit=16): + video_path = folder_paths.get_annotated_filepath(video) + (_, ext) = os.path.splitext(video_path) + if ext.lower() in {'.gif', '.webp'}: + frames = self.load_gif(video_path, frame_start, frame_limit) + elif ext.lower() in {'.webp', '.mp4', '.mov', '.avi', '.webm'}: + frames = self.load_video(video_path, frame_start, frame_limit) + else: + raise ValueError(f'Unsupported video format: {ext}') + return (torch.cat(frames, dim=0), len(frames)) + + @classmethod + def IS_CHANGED(s, image, *args, **kwargs): + image_path = folder_paths.get_annotated_filepath(image) + m = hashlib.sha256() + with open(image_path, 'rb') as f: + m.update(f.read()) + return m.digest().hex() + + @classmethod + def VALIDATE_INPUTS(s, video, *args, **kwargs): + if not folder_paths.exists_annotated_filepath(video): + return 'Invalid video file: {}'.format(video) + return True +``` \ No newline at end of file diff --git a/docs/Logic Boolean Primitive.md b/docs/Logic Boolean Primitive.md new file mode 100644 index 0000000..2a8c320 --- /dev/null +++ b/docs/Logic Boolean Primitive.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_Boolean_Primitive +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Boolean_Primitive 节点的 `do` 方法旨在处理并返回一个布尔值。它作为逻辑操作中的基本构建块,确保了工作流程中布尔计算的完整性。 + +# Input types +## Required +- boolean + - “boolean”参数对节点的操作至关重要,因为它直接影响“do”方法的逻辑结果。它是决定节点行为和结果布尔值的主要输入。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- result + - “result”输出参数代表了由“do”方法执行的布尔运算的结果。它很重要,因为它在处理输入后提供了最终的布尔值。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Boolean_Primitive: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'boolean': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('BOOLEAN',) + FUNCTION = 'do' + CATEGORY = 'WAS Suite/Logic' + + def do(self, boolean): + return (boolean,) +``` \ No newline at end of file diff --git a/docs/Logic Boolean.md b/docs/Logic Boolean.md new file mode 100644 index 0000000..9a17c1a --- /dev/null +++ b/docs/Logic Boolean.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_Boolean +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Boolean节点是逻辑操作中的基本组件,旨在处理并返回布尔值。它在工作流的决策过程中扮演着关键角色,确保根据逻辑条件的结果执行后续步骤。 + +# Input types +## Required +- boolean_number + - 参数'boolean_number'对于确定布尔结果是至关重要的。它通过提供一个四舍五入到最近整数的数值来影响节点的执行,从而定义布尔状态。 + - Comfy dtype: FLOAT + - Python dtype: Union[float, int] + +# Output types +- result + - 'result'输出表示从输入派生的布尔值。它很重要,因为它根据评估的逻辑条件决定了后续操作的流程。 + - Comfy dtype: INT + - Python dtype: Tuple[int, int] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Boolean: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'boolean_number': ('FLOAT', {'default': 1, 'min': 0, 'max': 1, 'step': 1})}} + RETURN_TYPES = ('NUMBER', 'INT') + FUNCTION = 'return_boolean' + CATEGORY = 'WAS Suite/Logic' + + def return_boolean(self, boolean_number=True): + return (int(round(boolean_number)), int(round(boolean_number))) +``` \ No newline at end of file diff --git a/docs/Logic Comparison AND.md b/docs/Logic Comparison AND.md new file mode 100644 index 0000000..ec9ce2d --- /dev/null +++ b/docs/Logic Comparison AND.md @@ -0,0 +1,35 @@ +# Documentation +- Class name: WAS_Logical_AND +- Category: Logical Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Logical_AND节点旨在执行逻辑与操作。它评估两个布尔输入,以确定两个条件是否都为真,返回一个布尔结果,表示输入的逻辑与。 + +# Input types +## Required +- boolean_a + - 第一个布尔输入,用于逻辑与操作。它至关重要,因为它代表了必须为真的条件之一,以使最终结果为真。 + - Comfy dtype: bool + - Python dtype: bool +- boolean_b + - 第二个布尔输入,也用于逻辑与操作。它的值同样重要,因为只有当它与第一个输入同时为真时,节点才会返回真结果。 + - Comfy dtype: bool + - Python dtype: bool + +# Output types +- result + - 两个输入布尔值之间逻辑与操作的结果。它很重要,因为它提供了逻辑与运算的最终结果。 + - Comfy dtype: bool + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Logical_AND(WAS_Logical_Comparisons): + + def do(self, boolean_a, boolean_b): + return (boolean_a and boolean_b,) +``` \ No newline at end of file diff --git a/docs/Logic Comparison OR.md b/docs/Logic Comparison OR.md new file mode 100644 index 0000000..44bd107 --- /dev/null +++ b/docs/Logic Comparison OR.md @@ -0,0 +1,35 @@ +# Documentation +- Class name: WAS_Logical_OR +- Category: Logical Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Logical_OR节点旨在对两个布尔输入执行逻辑或操作。在决策过程中,它在存在任一条件就足以触发某个动作或结果时是基础性的。 + +# Input types +## Required +- boolean_a + - 逻辑或操作的第一个布尔输入。它在确定函数结果中起着关键作用,因为它是当为真时将导致整体输出为真的条件之一。 + - Comfy dtype: bool + - Python dtype: bool +- boolean_b + - 逻辑或操作的第二个布尔输入。它与第一个输入同等重要,因为它代表了满足条件时可以导致输出为真的另一个条件。 + - Comfy dtype: bool + - Python dtype: bool + +# Output types +- result + - 两个输入之间逻辑或操作的结果。它表示是否至少满足了一个条件,概括了或逻辑的精髓。 + - Comfy dtype: bool + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Logical_OR(WAS_Logical_Comparisons): + + def do(self, boolean_a, boolean_b): + return (boolean_a or boolean_b,) +``` \ No newline at end of file diff --git a/docs/Logic Comparison XOR.md b/docs/Logic Comparison XOR.md new file mode 100644 index 0000000..74c590c --- /dev/null +++ b/docs/Logic Comparison XOR.md @@ -0,0 +1,35 @@ +# Documentation +- Class name: WAS_Logical_XOR +- Category: Logical Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Logical_XOR节点旨在对两个布尔输入执行逻辑异或操作。它在逻辑电路和决策过程中是基础性的,为二进制差异提供了一个简单而强大的机制。 + +# Input types +## Required +- boolean_a + - XOR操作的第一个布尔输入。它在确定逻辑比较的结果中起着关键作用,因为节点的功能取决于对两个输入的评估。 + - Comfy dtype: bool + - Python dtype: bool +- boolean_b + - XOR操作的第二个布尔输入。它在逻辑评估中与第一个输入同等重要,对节点操作的最终布尔结果有贡献。 + - Comfy dtype: bool + - Python dtype: bool + +# Output types +- result + - 逻辑异或操作的输出,是一个单一的布尔值,代表两个输入的互斥或非关系。 + - Comfy dtype: bool + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Logical_XOR(WAS_Logical_Comparisons): + + def do(self, boolean_a, boolean_b): + return (boolean_a != boolean_b,) +``` \ No newline at end of file diff --git a/docs/Logic NOT.md b/docs/Logic NOT.md new file mode 100644 index 0000000..a8106e3 --- /dev/null +++ b/docs/Logic NOT.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_Logical_NOT +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Logical_NOT节点旨在对布尔输入应用逻辑非操作。它反转真值,为工作流中否定布尔条件提供了一个简单的机制。在决策过程中,当需要反转布尔状态时,此节点发挥着关键作用。 + +# Input types +## Required +- boolean + - “boolean”参数是WAS_Logical_NOT节点的关键输入。它是一个布尔值,节点将对其进行否定。这个参数的重要性在于它能够控制后续操作的逻辑状态,对于条件工作流至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- result + - WAS_Logical_NOT节点的'result'输出代表输入布尔值的逻辑非。它的重要性在于它直接影响系统中的逻辑流程,允许构建复杂的条件语句。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Logical_NOT: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'boolean': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('BOOLEAN',) + FUNCTION = 'do' + CATEGORY = 'WAS Suite/Logic' + + def do(self, boolean): + return (not boolean,) +``` \ No newline at end of file diff --git a/docs/Loop.md b/docs/Loop.md new file mode 100644 index 0000000..6e6d67a --- /dev/null +++ b/docs/Loop.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: Loop +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +Loop节点类封装了迭代处理过程,能够执行一系列操作或算法的循环。它旨在方便重复任务的控制流,允许动态调整并结合用户定义的逻辑在循环结构中。 + +# Input types +## Required +- required + - 该参数对于定义循环执行的条件至关重要。它作为一个守门人,确保只有满足指定要求时循环才会运行,从而影响整体的执行流程和操作结果。 + - Comfy dtype: COMBO[None] + - Python dtype: Dict[str, Any] + +# Output types +- LOOP + - Loop节点的输出是节点本身,封装了迭代过程的结果。它代表了循环操作序列的高潮,提供了一种结构化和受控的方式来输出循环执行的最终状态。 + - Comfy dtype: NODE[Loop] + - Python dtype: Loop + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Loop: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}} + RETURN_TYPES = ('LOOP',) + FUNCTION = 'run' + CATEGORY = 'DragNUWA' + + def run(self): + return (self,) +``` \ No newline at end of file diff --git a/docs/LoopEnd_IMAGE.md b/docs/LoopEnd_IMAGE.md new file mode 100644 index 0000000..3c02cb8 --- /dev/null +++ b/docs/LoopEnd_IMAGE.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: LoopEnd_IMAGE +- Category: DragNUWA +- Output node: True +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +该节点在处理循环中协调图像数据的流转,确保指定的图像被传递到后续环节进行进一步的分析或处理。 + +# Input types +## Required +- send_to_next_loop + - 即将被路由到循环下一阶段的图像数据,在图像处理工作流的连续性和进展中起着关键作用。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- loop + - 正在被操作以控制图像数据流的循环结构,对于在循环内部建立操作序列至关重要。 + - Comfy dtype: LOOP + - Python dtype: Any + +# Output types +- return + - 此输出表示节点功能的完成,图像数据已成功导向到下一个循环片段。 + - Comfy dtype: VOID + - Python dtype: None + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoopEnd_IMAGE: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'send_to_next_loop': ('IMAGE',), 'loop': ('LOOP',)}} + RETURN_TYPES = () + FUNCTION = 'run' + CATEGORY = 'DragNUWA' + OUTPUT_NODE = True + + def run(self, send_to_next_loop, loop): + loop.next = send_to_next_loop + return () +``` \ No newline at end of file diff --git a/docs/LoopStart_IMAGE.md b/docs/LoopStart_IMAGE.md new file mode 100644 index 0000000..421650e --- /dev/null +++ b/docs/LoopStart_IMAGE.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: LoopStart_IMAGE +- Category: DragNUWA +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +该节点促进了循环结构的启动,使得能够迭代处理图像数据。在需要重复应用操作进行图像操作或分析的场景中,它的作用至关重要。 + +# Input types +## Required +- first_loop + - 循环中的第一个元素,为后续迭代设置了初始状态。它至关重要,因为它决定了循环操作的起点和性质。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +## Optional +- loop + - 代表循环的延续,允许操作的链接。它重要因为它使得循环的进展和复杂图像处理任务的处理成为可能。 + - Comfy dtype: LOOP + - Python dtype: None + +# Output types +- IMAGE + - 输出是循环对图像数据操作的结果,包含了迭代过程累积效应的封装。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoopStart_IMAGE: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'first_loop': ('IMAGE',), 'loop': ('LOOP',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'run' + CATEGORY = 'DragNUWA' + + def run(self, first_loop, loop): + if hasattr(loop, 'next'): + return (loop.next,) + return (first_loop,) + + @classmethod + def IS_CHANGED(s, first_loop, loop): + if hasattr(loop, 'next'): + return id(loop.next) + return float('NaN') +``` \ No newline at end of file diff --git a/docs/Lora Input Switch.md b/docs/Lora Input Switch.md new file mode 100644 index 0000000..1b98dfd --- /dev/null +++ b/docs/Lora Input Switch.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: WAS_Lora_Input_Switch +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +该节点在WAS Suite中充当条件开关,根据布尔参数的状态选择并转发两组输入中的一组。 + +# Input types +## Required +- model_a + - 第一个模型输入对节点的运行至关重要,代表布尔开关可以选择的两条可能的数据流之一。 + - Comfy dtype: MODEL + - Python dtype: Any +- clip_a + - 第一个剪辑输入是第一条数据流的一部分,如果布尔参数为真,则会被选择,影响节点的输出。 + - Comfy dtype: CLIP + - Python dtype: Any +- model_b + - 第二个模型输入代表备选数据流,如果布尔参数为假,则会被选择。 + - Comfy dtype: MODEL + - Python dtype: Any +- clip_b + - 第二个剪辑输入是备选数据流的一部分,其选择由布尔参数的状态决定。 + - Comfy dtype: CLIP + - Python dtype: Any +- boolean + - 布尔参数作为开关的控制信号,决定了哪组输入将被节点转发。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- output + - 节点的输出由布尔参数决定,要么转发第一组输入,要么转发备选组输入。 + - Comfy dtype: MODEL,CLIP + - Python dtype: Tuple[Any, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Lora_Input_Switch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model_a': ('MODEL',), 'clip_a': ('CLIP',), 'model_b': ('MODEL',), 'clip_b': ('CLIP',), 'boolean': ('BOOLEAN', {'forceInput': True})}} + RETURN_TYPES = ('MODEL', 'CLIP') + FUNCTION = 'lora_input_switch' + CATEGORY = 'WAS Suite/Logic' + + def lora_input_switch(self, model_a, clip_a, model_b, clip_b, boolean=True): + if boolean: + return (model_a, clip_a) + else: + return (model_b, clip_b) +``` \ No newline at end of file diff --git a/docs/Lora Loader.md b/docs/Lora Loader.md new file mode 100644 index 0000000..e4c862c --- /dev/null +++ b/docs/Lora Loader.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: WAS_Lora_Loader +- Category: WAS Suite/Loaders +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Lora_Loader节点旨在管理和应用Lora模型以增强基础模型和剪辑的功能。它通过缓存先前加载的模型来确保高效处理Lora文件,从而优化性能和资源使用。 + +# Input types +## Required +- model + - ‘model’参数至关重要,因为它代表了将应用Lora增强的基础模型。它直接影响节点的输出,通过确定将被修改的模型。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - ‘clip’参数对于提供将受Lora模型影响的剪辑组件至关重要。它是节点操作的关键元素,因为它定义了将被增强的剪辑。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- lora_name + - ‘lora_name’参数指定要加载的Lora模型文件。它是一个关键输入,因为它决定了将用于增强的Lora模型,影响节点的最终输出。 + - Comfy dtype: STRING + - Python dtype: str +- strength_model + - ‘strength_model’参数调整Lora模型对基础模型影响的强度。它在微调节点输出以实现所需增强水平方面起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- strength_clip + - ‘strength_clip’参数控制Lora模型对剪辑的影响强度。它对于调整节点的输出以满足剪辑组件的具体增强要求很重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- MODEL + - ‘MODEL’输出代表了应用Lora模型后增强的模型。它是节点操作的主要结果,对进一步处理或分析很重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- CLIP + - ‘CLIP’输出是被Lora模型修改的剪辑组件。它是节点功能的重要组成部分,为下游任务提供增强的剪辑。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- NAME_STRING + - ‘NAME_STRING’输出提供了被加载和应用的Lora模型的名称。它作为增强过程中使用的特定Lora模型的参考。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Lora_Loader: + + def __init__(self): + self.loaded_lora = None + + @classmethod + def INPUT_TYPES(s): + file_list = comfy_paths.get_filename_list('loras') + file_list.insert(0, 'None') + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'lora_name': (file_list,), 'strength_model': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'strength_clip': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01})}} + RETURN_TYPES = ('MODEL', 'CLIP', TEXT_TYPE) + RETURN_NAMES = ('MODEL', 'CLIP', 'NAME_STRING') + FUNCTION = 'load_lora' + CATEGORY = 'WAS Suite/Loaders' + + def load_lora(self, model, clip, lora_name, strength_model, strength_clip): + if strength_model == 0 and strength_clip == 0: + return (model, clip) + lora_path = comfy_paths.get_full_path('loras', lora_name) + lora = None + if self.loaded_lora is not None: + if self.loaded_lora[0] == lora_path: + lora = self.loaded_lora[1] + else: + temp = self.loaded_lora + self.loaded_lora = None + del temp + if lora is None: + lora = comfy.utils.load_torch_file(lora_path, safe_load=True) + self.loaded_lora = (lora_path, lora) + (model_lora, clip_lora) = comfy.sd.load_lora_for_models(model, clip, lora, strength_model, strength_clip) + return (model_lora, clip_lora, os.path.splitext(os.path.basename(lora_name))[0]) +``` \ No newline at end of file diff --git a/docs/LoraBlockInfo %2F%2FInspire.md b/docs/LoraBlockInfo %2F%2FInspire.md new file mode 100644 index 0000000..b79ceba --- /dev/null +++ b/docs/LoraBlockInfo %2F%2FInspire.md @@ -0,0 +1,146 @@ +# Documentation +- Class name: LoraBlockInfo +- Category: InspirePack/LoraBlockWeight +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点类封装了从Lora模型中提取和组织信息的过程,这是理解模型结构和功能的关键组成部分。它提供了模型中不同类型块的全面概述,例如输入块、中间块、输出块和文本块,以及它们各自的数量和关联。这种高级功能有助于分析和优化模型的架构。 + +# Input types +## Required +- model + - 模型参数是必不可少的,因为它为节点执行分析提供了基础。它是节点用来提取和组织块信息的主要数据源。 + - Comfy dtype: MODEL + - Python dtype: Any +- clip + - clip参数对于完善模型的块信息至关重要。它有助于准确映射键并增强整体提取过程。 + - Comfy dtype: CLIP + - Python dtype: Any +- lora_name + - lora_name参数指定了要分析的Lora模型。它是一个关键的输入,指导节点到正确的数据源进行块提取。 + - Comfy dtype: STRING + - Python dtype: str +- unique_id + - unique_id参数对于跟踪节点的执行至关重要。它确保每个节点的实例可以被唯一识别,允许精确的反馈和错误处理。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +## Optional +- block_info + - block_info参数作为用户提供的文本输入,可以为块提取过程提供额外的上下文或规格。它用人类洞察力补充了自动分析。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoraBlockInfo: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'lora_name': (folder_paths.get_filename_list('loras'),), 'block_info': ('STRING', {'multiline': True})}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + CATEGORY = 'InspirePack/LoraBlockWeight' + OUTPUT_NODE = True + RETURN_TYPES = () + FUNCTION = 'doit' + + @staticmethod + def extract_info(model, clip, lora): + key_map = comfy.lora.model_lora_keys_unet(model.model) + key_map = comfy.lora.model_lora_keys_clip(clip.cond_stage_model, key_map) + loaded = comfy.lora.load_lora(lora, key_map) + + def parse_unet_num(s): + if s[1] == '.': + return int(s[0]) + else: + return int(s) + input_block_count = set() + input_blocks = [] + input_blocks_map = {} + middle_block_count = set() + middle_blocks = [] + middle_blocks_map = {} + output_block_count = set() + output_blocks = [] + output_blocks_map = {} + text_block_count = set() + text_blocks = [] + text_blocks_map = {} + others = [] + for (k, v) in loaded.items(): + k_unet = k[len('diffusion_model.'):] + if k_unet.startswith('input_blocks.'): + k_unet_num = k_unet[len('input_blocks.'):len('input_blocks.') + 2] + k_unet_int = parse_unet_num(k_unet_num) + input_block_count.add(k_unet_int) + input_blocks.append(k_unet) + if k_unet_int in input_blocks_map: + input_blocks_map[k_unet_int].append(k_unet) + else: + input_blocks_map[k_unet_int] = [k_unet] + elif k_unet.startswith('middle_block.'): + k_unet_num = k_unet[len('middle_block.'):len('middle_block.') + 2] + k_unet_int = parse_unet_num(k_unet_num) + middle_block_count.add(k_unet_int) + middle_blocks.append(k_unet) + if k_unet_int in middle_blocks_map: + middle_blocks_map[k_unet_int].append(k_unet) + else: + middle_blocks_map[k_unet_int] = [k_unet] + elif k_unet.startswith('output_blocks.'): + k_unet_num = k_unet[len('output_blocks.'):len('output_blocks.') + 2] + k_unet_int = parse_unet_num(k_unet_num) + output_block_count.add(k_unet_int) + output_blocks.append(k_unet) + if k_unet_int in output_blocks_map: + output_blocks_map[k_unet_int].append(k_unet) + else: + output_blocks_map[k_unet_int] = [k_unet] + elif k_unet.startswith('_model.encoder.layers.'): + k_unet_num = k_unet[len('_model.encoder.layers.'):len('_model.encoder.layers.') + 2] + k_unet_int = parse_unet_num(k_unet_num) + text_block_count.add(k_unet_int) + text_blocks.append(k_unet) + if k_unet_int in text_blocks_map: + text_blocks_map[k_unet_int].append(k_unet) + else: + text_blocks_map[k_unet_int] = [k_unet] + else: + others.append(k_unet) + text = '' + input_blocks = sorted(input_blocks) + middle_blocks = sorted(middle_blocks) + output_blocks = sorted(output_blocks) + others = sorted(others) + text += f'\n-------[Input blocks] ({len(input_block_count)}, Subs={len(input_blocks)})-------\n' + input_keys = sorted(input_blocks_map.keys()) + for x in input_keys: + text += f' IN{x}: {len(input_blocks_map[x])}\n' + text += f'\n-------[Middle blocks] ({len(middle_block_count)}, Subs={len(middle_blocks)})-------\n' + middle_keys = sorted(middle_blocks_map.keys()) + for x in middle_keys: + text += f' MID{x}: {len(middle_blocks_map[x])}\n' + text += f'\n-------[Output blocks] ({len(output_block_count)}, Subs={len(output_blocks)})-------\n' + output_keys = sorted(output_blocks_map.keys()) + for x in output_keys: + text += f' OUT{x}: {len(output_blocks_map[x])}\n' + text += f'\n-------[Text blocks] ({len(text_block_count)}, Subs={len(text_blocks)})-------\n' + text_keys = sorted(text_blocks_map.keys()) + for x in text_keys: + text += f' CLIP{x}: {len(text_blocks_map[x])}\n' + text += f'\n-------[Base blocks] ({len(others)})-------\n' + for x in others: + text += f' {x}\n' + return text + + def doit(self, model, clip, lora_name, block_info, unique_id): + lora_path = folder_paths.get_full_path('loras', lora_name) + lora = comfy.utils.load_torch_file(lora_path, safe_load=True) + text = LoraBlockInfo.extract_info(model, clip, lora) + PromptServer.instance.send_sync('inspire-node-feedback', {'node_id': unique_id, 'widget_name': 'block_info', 'type': 'text', 'data': text}) + return {} +``` \ No newline at end of file diff --git a/docs/LoraLoader.md b/docs/LoraLoader.md index e69de29..216620e 100644 --- a/docs/LoraLoader.md +++ b/docs/LoraLoader.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: LoraLoader +- Category: loaders +- Output node: False +- Repo Ref: https://github.com/comfyanonymous/ComfyUI + +LoraLoader节点旨在管理加载和应用LoRA(低秩适应)修改到模型中。它高效地处理将LoRA调整集成到模型和clip组件中,允许以最小的计算开销微调模型行为。该节点抽象了LoRA应用的复杂性,为模型增强提供了一个简化的接口。 + +# Input types +## Required +- model + - model参数至关重要,因为它代表了将通过LoRA技术进行修改的基础模型。它的重要性在于它是增强的主要对象,直接影响节点的执行和模型功能的结果。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - clip参数指定了CLIP架构的条件阶段模型,该模型也可能受到LoRA修改的影响。它的作用很重要,因为它决定了文本信息与视觉模型是如何联合处理的。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- lora_name + - lora_name参数标识要加载的特定LoRA配置。它至关重要,因为它决定了将应用于模型的修改集,从而塑造节点的功能和模型的适应行为。 + - Comfy dtype: folder_paths.get_filename_list('loras') + - Python dtype: str +## Optional +- strength_model + - strength_model参数调整应用于模型的LoRA修改的强度。它在微调模型行为中起着关键作用,提供了原始模型和适应后模型能力之间的平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- strength_clip + - strength_clip参数允许调整LoRA修改对CLIP模型的影响。它很重要,因为它控制了文本信息处理受LoRA技术影响的程度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- model_lora + - model_lora输出代表了应用了LoRA修改的模型。它很重要,因为它是节点操作的直接结果,包含了模型增强后的能力。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip_lora + - clip_lora输出表示集成了LoRA调整的CLIP模型。它的重要性在于展示通过LoRA技术文本信息处理是如何被适应的。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoraLoader: + + def __init__(self): + self.loaded_lora = None + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'lora_name': (folder_paths.get_filename_list('loras'),), 'strength_model': ('FLOAT', {'default': 1.0, 'min': -20.0, 'max': 20.0, 'step': 0.01}), 'strength_clip': ('FLOAT', {'default': 1.0, 'min': -20.0, 'max': 20.0, 'step': 0.01})}} + RETURN_TYPES = ('MODEL', 'CLIP') + FUNCTION = 'load_lora' + CATEGORY = 'loaders' + + def load_lora(self, model, clip, lora_name, strength_model, strength_clip): + if strength_model == 0 and strength_clip == 0: + return (model, clip) + lora_path = folder_paths.get_full_path('loras', lora_name) + lora = None + if self.loaded_lora is not None: + if self.loaded_lora[0] == lora_path: + lora = self.loaded_lora[1] + else: + temp = self.loaded_lora + self.loaded_lora = None + del temp + if lora is None: + lora = comfy.utils.load_torch_file(lora_path, safe_load=True) + self.loaded_lora = (lora_path, lora) + (model_lora, clip_lora) = comfy.sd.load_lora_for_models(model, clip, lora, strength_model, strength_clip) + return (model_lora, clip_lora) +``` \ No newline at end of file diff --git a/docs/LoraLoaderBlockWeight %2F%2FInspire.md b/docs/LoraLoaderBlockWeight %2F%2FInspire.md new file mode 100644 index 0000000..98181cc --- /dev/null +++ b/docs/LoraLoaderBlockWeight %2F%2FInspire.md @@ -0,0 +1,256 @@ +# Documentation +- Class name: LoraLoaderBlockWeight +- Category: InspirePack/LoraBlockWeight +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在从LoRa文件中加载和操作块权重,根据指定的参数调整对不同模型层的强调,以微调输出结果。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了将要应用块权重的基础架构,显著影响最终输出。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - clip输入对于提供有助于调整块权重的上下文信息至关重要,确保输出与期望的上下文一致。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- category_filter + - 该参数根据其类别过滤LoRa文件,允许节点专注于模型层的特定方面。 + - Comfy dtype: COMBO[lora_dirs] + - Python dtype: str +- lora_name + - lora_name参数在选定特定的LoRa文件,其块权重将被加载和操作中起着关键作用。 + - Comfy dtype: COMBO[lora_names] + - Python dtype: str +- strength_model + - 该参数调整模型块权重的影响,允许微调输出以满足特定要求。 + - Comfy dtype: FLOAT + - Python dtype: float +- strength_clip + - strength_clip参数修改了clip上下文信息对块权重调整的影响。 + - Comfy dtype: FLOAT + - Python dtype: float +- inverse + - 通过切换此参数,节点可以反转块权重的效果,提供对模型行为的替代视角。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- seed + - seed输入初始化随机数生成器,确保块权重调整是可复现和一致的。 + - Comfy dtype: INT + - Python dtype: int +- A + - A参数用于定义某些向量计算的基础值,影响块权重的整体分布。 + - Comfy dtype: FLOAT + - Python dtype: float +- B + - 与A类似,B参数为向量计算设置了另一个基础值,有助于块权重调整的多样性。 + - Comfy dtype: FLOAT + - Python dtype: float +- block_vector + - block_vector参数指定要应用的块权重序列,直接影响输出的结构和特征。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- preset + - 预设参数提供了预定义块权重配置的选择,简化了应用常见调整的过程。 + - Comfy dtype: COMBO[preset] + - Python dtype: str +- bypass + - 启用时,此参数允许节点绕过块权重调整,不变地传递原始模型和clip数据。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- model + - 输出模型已经根据加载的块权重进行了调整,反映了对架构行为的预期修改。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - 输出clip数据包含了块权重调整,确保上下文信息与修改后的模型保持一致。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- populated_vector + - 此输出提供了应用的块权重的详细记录,作为模型修改结构的参考。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoraLoaderBlockWeight: + + def __init__(self): + self.loaded_lora = None + + @classmethod + def INPUT_TYPES(s): + preset = ['Preset'] + preset += load_lbw_preset('lbw-preset.txt') + preset += load_lbw_preset('lbw-preset.custom.txt') + preset = [name for name in preset if not name.startswith('@')] + lora_names = folder_paths.get_filename_list('loras') + lora_dirs = [os.path.dirname(name) for name in lora_names] + lora_dirs = ['All'] + list(set(lora_dirs)) + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'category_filter': (lora_dirs,), 'lora_name': (lora_names,), 'strength_model': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'strength_clip': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'inverse': ('BOOLEAN', {'default': False, 'label_on': 'True', 'label_off': 'False'}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'A': ('FLOAT', {'default': 4.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'B': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'preset': (preset,), 'block_vector': ('STRING', {'multiline': True, 'placeholder': 'block weight vectors', 'default': '1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1', 'pysssss.autocomplete': False}), 'bypass': ('BOOLEAN', {'default': False, 'label_on': 'True', 'label_off': 'False'})}} + RETURN_TYPES = ('MODEL', 'CLIP', 'STRING') + RETURN_NAMES = ('model', 'clip', 'populated_vector') + FUNCTION = 'doit' + CATEGORY = 'InspirePack/LoraBlockWeight' + + @staticmethod + def validate(vectors): + if len(vectors) < 12: + return False + for x in vectors: + if x in ['R', 'r', 'U', 'u', 'A', 'a', 'B', 'b'] or is_numeric_string(x): + continue + else: + subvectors = x.strip().split(' ') + for y in subvectors: + y = y.strip() + if y not in ['R', 'r', 'U', 'u', 'A', 'a', 'B', 'b'] and (not is_numeric_string(y)): + return False + return True + + @staticmethod + def convert_vector_value(A, B, vector_value): + + def simple_vector(x): + if x in ['U', 'u']: + ratio = np.random.uniform(-1.5, 1.5) + ratio = round(ratio, 2) + elif x in ['R', 'r']: + ratio = np.random.uniform(0, 3.0) + ratio = round(ratio, 2) + elif x == 'A': + ratio = A + elif x == 'a': + ratio = A / 2 + elif x == 'B': + ratio = B + elif x == 'b': + ratio = B / 2 + elif is_numeric_string(x): + ratio = float(x) + else: + ratio = None + return ratio + v = simple_vector(vector_value) + if v is not None: + ratios = [v] + else: + ratios = [simple_vector(x) for x in vector_value.split(' ')] + return ratios + + @staticmethod + def norm_value(value): + if value == 1: + return 1 + elif value == 0: + return 0 + else: + return value + + @staticmethod + def load_lora_for_models(model, clip, lora, strength_model, strength_clip, inverse, seed, A, B, block_vector): + key_map = comfy.lora.model_lora_keys_unet(model.model) + key_map = comfy.lora.model_lora_keys_clip(clip.cond_stage_model, key_map) + loaded = comfy.lora.load_lora(lora, key_map) + block_vector = block_vector.split(':') + if len(block_vector) > 1: + block_vector = block_vector[1] + else: + block_vector = block_vector[0] + vector = block_vector.split(',') + vector_i = 1 + if not LoraLoaderBlockWeight.validate(vector): + preset_dict = load_preset_dict() + if len(vector) > 0 and vector[0].strip() in preset_dict: + vector = preset_dict[vector[0].strip()].split(',') + else: + raise ValueError(f"[LoraLoaderBlockWeight] invalid block_vector '{block_vector}'") + last_k_unet_num = None + new_modelpatcher = model.clone() + populated_ratio = strength_model + + def parse_unet_num(s): + if s[1] == '.': + return int(s[0]) + else: + return int(s) + input_blocks = [] + middle_blocks = [] + output_blocks = [] + others = [] + for (k, v) in loaded.items(): + k_unet = k[len('diffusion_model.'):] + if k_unet.startswith('input_blocks.'): + k_unet_num = k_unet[len('input_blocks.'):len('input_blocks.') + 2] + input_blocks.append((k, v, parse_unet_num(k_unet_num), k_unet)) + elif k_unet.startswith('middle_block.'): + k_unet_num = k_unet[len('middle_block.'):len('middle_block.') + 2] + middle_blocks.append((k, v, parse_unet_num(k_unet_num), k_unet)) + elif k_unet.startswith('output_blocks.'): + k_unet_num = k_unet[len('output_blocks.'):len('output_blocks.') + 2] + output_blocks.append((k, v, parse_unet_num(k_unet_num), k_unet)) + else: + others.append((k, v, k_unet)) + input_blocks = sorted(input_blocks, key=lambda x: x[2]) + middle_blocks = sorted(middle_blocks, key=lambda x: x[2]) + output_blocks = sorted(output_blocks, key=lambda x: x[2]) + np.random.seed(seed % 2 ** 31) + populated_vector_list = [] + ratios = [] + for (k, v, k_unet_num, k_unet) in input_blocks + middle_blocks + output_blocks: + if last_k_unet_num != k_unet_num and len(vector) > vector_i: + ratios = LoraLoaderBlockWeight.convert_vector_value(A, B, vector[vector_i].strip()) + ratio = ratios.pop(0) + if inverse: + populated_ratio = 1 - ratio + else: + populated_ratio = ratio + populated_vector_list.append(LoraLoaderBlockWeight.norm_value(populated_ratio)) + vector_i += 1 + else: + if len(ratios) > 0: + ratio = ratios.pop(0) + if inverse: + populated_ratio = 1 - ratio + else: + populated_ratio = ratio + last_k_unet_num = k_unet_num + new_modelpatcher.add_patches({k: v}, strength_model * populated_ratio) + ratios = LoraLoaderBlockWeight.convert_vector_value(A, B, vector[0].strip()) + ratio = ratios.pop(0) + if inverse: + populated_ratio = 1 - ratio + populated_vector_list.insert(0, LoraLoaderBlockWeight.norm_value(populated_ratio)) + for (k, v, k_unet) in others: + new_modelpatcher.add_patches({k: v}, strength_model * populated_ratio) + new_clip = clip.clone() + new_clip.add_patches(loaded, strength_clip) + populated_vector = ','.join(map(str, populated_vector_list)) + return (new_modelpatcher, new_clip, populated_vector) + + def doit(self, model, clip, lora_name, strength_model, strength_clip, inverse, seed, A, B, preset, block_vector, bypass=False, category_filter=None): + if strength_model == 0 and strength_clip == 0 or bypass: + return (model, clip, '') + lora_path = folder_paths.get_full_path('loras', lora_name) + lora = None + if self.loaded_lora is not None: + if self.loaded_lora[0] == lora_path: + lora = self.loaded_lora[1] + else: + temp = self.loaded_lora + self.loaded_lora = None + del temp + if lora is None: + lora = comfy.utils.load_torch_file(lora_path, safe_load=True) + self.loaded_lora = (lora_path, lora) + (model_lora, clip_lora, populated_vector) = LoraLoaderBlockWeight.load_lora_for_models(model, clip, lora, strength_model, strength_clip, inverse, seed, A, B, block_vector) + return (model_lora, clip_lora, populated_vector) +``` \ No newline at end of file diff --git a/docs/LoraNames_.md b/docs/LoraNames_.md new file mode 100644 index 0000000..08baea3 --- /dev/null +++ b/docs/LoraNames_.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: CreateLoraNames +- Category: ♾️Mixlab/Utils +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点简化了从给定文本中提取和组织名称的过程,特别适用于处理Lora字体名称列表。它简化了输入文本,去除了任何多余的字符或空行,并将名称与其文件扩展名分离,提供了一个清洁的名称列表和提示,以供进一步使用。 + +# Input types +## Required +- lora_names + - 包含Lora字体名称的输入文本,预期以多行格式存在,以便使用。该参数至关重要,因为它是节点操作的主要数据源。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- lora_names + - 经过清理和处理的Lora字体名称列表,不包含任何多余的字符或空行,准备供进一步处理或使用。 + - Comfy dtype: STRING + - Python dtype: List[str] +- prompt + - 从Lora字体名称中派生出的提示列表,去除了文件扩展名,适用于生成创意或主题内容。 + - Comfy dtype: STRING + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CreateLoraNames: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'lora_names': ('STRING', {'multiline': True, 'default': '\n'.join(folder_paths.get_filename_list('loras')), 'dynamicPrompts': False})}} + RETURN_TYPES = (any_type, 'STRING') + RETURN_NAMES = ('lora_names', 'prompt') + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (True, True) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Utils' + + def run(self, lora_names): + lora_names = lora_names.split('\n') + lora_names = [name for name in lora_names if name.strip()] + prompts = [os.path.splitext(n)[0] for n in lora_names] + return (lora_names, prompts) +``` \ No newline at end of file diff --git a/docs/LoraSyntaxProcessor.md b/docs/LoraSyntaxProcessor.md new file mode 100644 index 0000000..bb98c7a --- /dev/null +++ b/docs/LoraSyntaxProcessor.md @@ -0,0 +1,92 @@ +# Documentation +- Class name: LoraSyntaxProcessor +- Category: Mikey/Lora +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +LoraSyntaxProcessor节点旨在通过一系列语法转换来处理文本输入。它替换占位符为随机值,搜索并用提供的提示中相应的数据替换特定模式,并加载外部LoRA模型以增强基础模型的能力。该节点在基于输入参数生成动态和上下文感知的文本输出中发挥关键作用。 + +# Input types +## Required +- model + - 模型参数对节点的操作至关重要,因为它代表了将被节点增强或使用的基线模型。它通过确定将进行任何后续转换或处理的模型来影响节点的执行。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - clip参数是文本处理的关键组件,特别是处理视觉和多模态数据时。它用于将文本与视觉表现对齐,并可以通过影响处理文本的上下文来影响节点的输出。 + - Comfy dtype: CLIP + - Python dtype: CLIP model or related object +- text + - 文本参数是节点的主要输入,包含将进行语法处理的原始文本。它是节点操作的基础,因为整个转换过程围绕这个输入进行。 + - Comfy dtype: STRING + - Python dtype: str +- seed + - seed参数用于初始化随机数生成器,确保在文本中生成随机值时获得可重复的结果。它在保持节点输出的一致性方面扮演着重要角色。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- extra_pnginfo + - extra_pnginfo参数提供额外的上下文或元数据,可用于自定义文本处理。它可以通过提供可能与某些转换相关的额外信息来影响节点的执行。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: dict or str +- prompt + - prompt参数用于指导文本处理,通过提供节点将用于替换文本中模式的具体指令或数据。它通过确定将应用于输入文本的特定转换来影响节点的执行。 + - Comfy dtype: PROMPT + - Python dtype: dict or str + +# Output types +- model + - 模型输出代表了应用任何转换或加载额外LoRA模型后可能得到增强的模型。它标志着节点处理的完成,对于依赖更新后模型的后续任务至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - clip输出是输入clip的处理或增强版本,可能已经根据节点应用的转换进行了修改。它对于需要与处理过的文本对齐的更新视觉表示的任务很重要。 + - Comfy dtype: CLIP + - Python dtype: CLIP model or related object +- text + - 文本输出是在应用了所有语法转换后最终处理的文本。它是节点操作的直接结果,对于需要文本信息的任何下游任务都是必不可少的。 + - Comfy dtype: STRING + - Python dtype: str +- unprocessed_text + - 未处理的文本输出提供了去除了任何LoRA相关语法的原始文本输入。它对于需要原始文本与处理后的文本一起用于比较或进一步分析的场景很有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoraSyntaxProcessor: + + def __init__(self): + self.loaded_lora = None + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'text': ('STRING', {'multiline': True, 'default': ''}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('MODEL', 'CLIP', 'STRING', 'STRING') + RETURN_NAMES = ('model', 'clip', 'text', 'unprocessed_text') + FUNCTION = 'process' + CATEGORY = 'Mikey/Lora' + + def process(self, model, clip, text, seed, extra_pnginfo=None, prompt=None): + text = process_random_syntax(text, seed) + text = search_and_replace(text, extra_pnginfo, prompt) + lora_re = '' + lora_prompts = re.findall(lora_re, text) + stripped_text = text + clip_lora = clip + if len(lora_prompts) > 0: + for lora_prompt in lora_prompts: + lora_filename = lora_prompt[0] + if '.safetensors' not in lora_filename: + lora_filename += '.safetensors' + try: + lora_multiplier = float(lora_prompt[1]) if lora_prompt[1] != '' else 1.0 + except: + lora_multiplier = 1.0 + (model, clip) = load_lora(model, clip, lora_filename, lora_multiplier, lora_multiplier) + stripped_text = re.sub(lora_re, '', stripped_text) + return (model, clip, stripped_text, text) +``` \ No newline at end of file diff --git a/docs/M2M VFI.md b/docs/M2M VFI.md new file mode 100644 index 0000000..fe82d28 --- /dev/null +++ b/docs/M2M VFI.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: M2M_VFI +- Category: ComfyUI-Frame-Interpolation/VFI +- Output node: False +- Repo Ref: https://github.com/Fannovel16/ComfyUI-Frame-Interpolation + +M2M_VFI节点旨在在两个给定的视频帧之间插入帧,增强视频序列的平滑度和连续性。它利用深度学习模型生成原始素材中不存在的中间帧,从而创造出更加流畅的视觉体验。 + +# Input types +## Required +- ckpt_name + - 检查点名称参数对于确定用于帧插值的特定预训练模型至关重要。它确保加载正确的权重和配置,以实现所需的插值结果。 + - Comfy dtype: str + - Python dtype: str +- frames + - frames参数是必需的,因为它代表了节点将处理插值的输入视频帧。输入帧的质量和分辨率直接影响插值的输出,使这个参数对节点的执行非常重要。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +## Optional +- clear_cache_after_n_frames + - clear_cache_after_n_frames参数决定了节点清理缓存以管理内存使用的频率。这对于维护性能很重要,尤其是在处理大量视频数据时。 + - Comfy dtype: int + - Python dtype: int +- multiplier + - multiplier参数影响在输入帧之间生成的中间帧的数量。值越高,生成的插值帧越多,可以实现更平滑的过渡,但也可能增加计算需求。 + - Comfy dtype: int + - Python dtype: int +- optional_interpolation_states + - optional_interpolation_states参数提供了一种通过指定某些状态或条件来自定义插值过程的方法。这个高级功能允许对输出帧进行更大程度的控制,以满足特定项目需求。 + - Comfy dtype: InterpolationStateList + - Python dtype: InterpolationStateList + +# Output types +- output_frames + - output_frames参数代表帧插值过程的结果。它包含了原始帧以及新生成的中间帧,提供了一个完整和增强的视频序列。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class M2M_VFI: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (CKPT_NAMES,), 'frames': ('IMAGE',), 'clear_cache_after_n_frames': ('INT', {'default': 10, 'min': 1, 'max': 1000}), 'multiplier': ('INT', {'default': 2, 'min': 2, 'max': 1000})}, 'optional': {'optional_interpolation_states': ('INTERPOLATION_STATES',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'vfi' + CATEGORY = 'ComfyUI-Frame-Interpolation/VFI' + + def vfi(self, ckpt_name: typing.AnyStr, frames: torch.Tensor, clear_cache_after_n_frames: typing.SupportsInt=1, multiplier: typing.SupportsInt=2, optional_interpolation_states: InterpolationStateList=None, **kwargs): + from .M2M_arch import M2M_PWC + model_path = load_file_from_github_release(MODEL_TYPE, ckpt_name) + interpolation_model = M2M_PWC() + interpolation_model.load_state_dict(torch.load(model_path)) + interpolation_model.eval().to(get_torch_device()) + frames = preprocess_frames(frames) + + def return_middle_frame(frame_0, frame_1, int_timestep, model): + tenSteps = [torch.FloatTensor([int_timestep] * len(frame_0)).view(len(frame_0), 1, 1, 1).to(get_torch_device())] + return model(frame_0, frame_1, tenSteps)[0] + args = [interpolation_model] + out = postprocess_frames(generic_frame_loop(frames, clear_cache_after_n_frames, multiplier, return_middle_frame, *args, interpolation_states=optional_interpolation_states, dtype=torch.float32)) + return (out,) +``` \ No newline at end of file diff --git a/docs/MagicAnimate.md b/docs/MagicAnimate.md new file mode 100644 index 0000000..2ba22f7 --- /dev/null +++ b/docs/MagicAnimate.md @@ -0,0 +1,98 @@ +# Documentation +- Class name: MagicAnimate +- Category: ComfyUI Magic Animate +- Output node: False +- Repo Ref: https://github.com/thecooltechguy/ComfyUI-MagicAnimate + +该节点使用生成模型根据输入的图像和姿势视频创建动画内容。它旨在通过将输入图像的外观与姿势视频中捕获的动作融合,合成新的帧,从而产生反映所需动作和风格的无缝动画。 + +# Input types +## Required +- magic_animate_model + - 模型参数至关重要,因为它定义了用于动画的生成架构。它封装了生成过程所需的管道、配置和各种组件,确保节点能够产生所需的动画输出。 + - Comfy dtype: MAGIC_ANIMATE_MODEL + - Python dtype: Dict[str, Any] +- image + - 图像参数作为动画的视觉基础。它提供了将根据姿势视频进行动画处理的外观。图像的质量和分辨率对最终动画的视觉保真度有重大影响。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- pose_video + - 姿势视频参数决定了动画的动作和顺序。它对于传达所需动作和确保动画的流畅性至关重要。视频的帧率和质量直接影响动画的平滑度和真实感。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- seed + - 种子参数对于确保生成动画的可重复性和一致性至关重要。通过设置特定的种子,节点可以在相同条件下生成相同的动画结果,这对于迭代改进和调试至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- inference_steps + - 推理步骤参数影响生成过程的深度。更多的步骤允许更详细和细致的动画,但可能会增加计算成本。这个参数对于平衡质量和性能至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - 该节点的输出是生成的动画,这是一系列将输入图像的外观与姿势视频的动作结合起来的帧。这个输出是生成过程的结晶,代表了节点的主要功能和目的。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MagicAnimate: + + def __init__(self): + self.generator = torch.Generator(device=torch.device('cuda:0')) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'magic_animate_model': ('MAGIC_ANIMATE_MODEL',), 'image': ('IMAGE',), 'pose_video': ('IMAGE',), 'seed': ('INT', {'display': 'number'}), 'inference_steps': ('INT', {'default': 25, 'display': 'number'})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'generate' + CATEGORY = 'ComfyUI Magic Animate' + + def resize_image_frame(self, image_tensor, size): + if isinstance(image_tensor, np.ndarray): + image_tensor = torch.from_numpy(image_tensor) + image_tensor = rearrange(image_tensor, 'h w c -> c h w') + image_tensor = ToPILImage()(image_tensor) + image_tensor = image_tensor.resize((size, size)) + image_tensor = ToTensor()(image_tensor) + image_tensor = rearrange(image_tensor, 'c h w -> h w c') + return image_tensor + + def generate(self, magic_animate_model, image, pose_video, seed, inference_steps): + num_actual_inference_steps = inference_steps + pipeline = magic_animate_model['pipeline'] + config = magic_animate_model['config'] + size = config.size + appearance_encoder = magic_animate_model['appearance_encoder'] + reference_control_writer = magic_animate_model['reference_control_writer'] + reference_control_reader = magic_animate_model['reference_control_reader'] + assert image.shape[0] == 1, 'Only one image input is supported' + image = image[0] + (H, W, C) = image.shape + if H != size or W != size: + image = self.resize_image_frame(image, size) + (H, W, C) = image.shape + image = image * 255 + prompt = '' + n_prompt = '' + control = pose_video.detach().cpu().numpy() + print('control shape:', control.shape) + if control.shape[1] != size or control.shape[2] != size: + control = torch.stack([self.resize_image_frame(frame, size) for frame in control], dim=0) + init_latents = None + original_length = control.shape[0] + if control.shape[0] % config.L > 0: + control = np.pad(control, ((0, config.L - control.shape[0] % config.L), (0, 0), (0, 0), (0, 0)), mode='edge') + control = control * 255 + self.generator.manual_seed(seed) + dist_kwargs = {'rank': 0, 'world_size': 1, 'dist': False} + sample = pipeline(prompt, negative_prompt=n_prompt, num_inference_steps=config.steps, guidance_scale=config.guidance_scale, width=W, height=H, video_length=len(control), controlnet_condition=control, init_latents=init_latents, generator=self.generator, num_actual_inference_steps=num_actual_inference_steps, appearance_encoder=appearance_encoder, reference_control_writer=reference_control_writer, reference_control_reader=reference_control_reader, source_image=image.detach().cpu().numpy(), **dist_kwargs).videos + sample = sample[0, :, :original_length] + sample = rearrange(sample, 'c f h w -> f h w c').detach().cpu() + return (sample,) +``` \ No newline at end of file diff --git a/docs/MagicAnimateModelLoader.md b/docs/MagicAnimateModelLoader.md new file mode 100644 index 0000000..204991b --- /dev/null +++ b/docs/MagicAnimateModelLoader.md @@ -0,0 +1,129 @@ +# Documentation +- Class name: MagicAnimateModelLoader +- Category: ComfyUI Magic Animate +- Output node: False +- Repo Ref: https://github.com/thecooltechguy/ComfyUI-MagicAnimate + +MagicAnimateModelLoader类负责管理和加载魔法动画模型的各个组件。它作为控制网络、外观编码器、运动模块和其他相关模块的集中存储库。load_model方法旨在清除任何现有的模型,加载新配置,并初始化用于动画目的的模型组件。 + +# Input types +## Optional +- controlnet + - controlnet参数指定控制网络的检查点或路径,这是动画模型的关键部分。它用于指导生成过程。 + - Comfy dtype: str + - Python dtype: str +- appearance_encoder + - appearance_encoder参数表示外观编码器的检查点或文件路径,它负责编码输入的视觉特征。 + - Comfy dtype: str + - Python dtype: str +- motion_module + - motion_module参数指向运动模块的检查点或文件路径,这对于根据给定的运动对输入进行动画制作至关重要。 + - Comfy dtype: str + - Python dtype: str +- device + - device参数确定用于模型执行的计算设备,通常为'cuda'以进行GPU加速或'cpu'。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- MAGIC_ANIMATE_MODEL + - 输出是一个包含已加载模型和配置的字典。它包括VAE、文本编码器、外观编码器、分词器、UNet、控制网络和动画流水线。 + - Comfy dtype: dict + - Python dtype: Dict[str, torch.nn.Module] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MagicAnimateModelLoader: + + def __init__(self): + self.models = {} + + @classmethod + def INPUT_TYPES(s): + magic_animate_checkpoints = folder_paths.get_filename_list('magic_animate') + devices = [] + if True: + devices.append('cuda') + devices.append('cpu') + return {'required': {'controlnet': (magic_animate_checkpoints, {'default': magic_animate_checkpoints[0]}), 'appearance_encoder': (magic_animate_checkpoints, {'default': magic_animate_checkpoints[0]}), 'motion_module': (magic_animate_checkpoints, {'default': magic_animate_checkpoints[0]}), 'device': (devices,)}} + RETURN_TYPES = ('MAGIC_ANIMATE_MODEL',) + FUNCTION = 'load_model' + CATEGORY = 'ComfyUI Magic Animate' + + def load_model(self, controlnet, appearance_encoder, motion_module, device): + if self.models: + all_keys = list(self.models.keys()) + for key in all_keys: + del self.models[key] + self.models = {} + gc.collect() + current_dir = os.path.dirname(os.path.realpath(__file__)) + config = OmegaConf.load(os.path.join(current_dir, 'configs', 'prompts', 'animation.yaml')) + inference_config = OmegaConf.load(os.path.join(current_dir, 'configs', 'inference', 'inference.yaml')) + magic_animate_models_dir = folder_paths.get_folder_paths('magic_animate')[0] + config.pretrained_model_path = os.path.join(magic_animate_models_dir, 'stable-diffusion-v1-5') + config.pretrained_vae_path = os.path.join(magic_animate_models_dir, 'sd-vae-ft-mse') + config.pretrained_appearance_encoder_path = os.path.join(magic_animate_models_dir, os.path.dirname(appearance_encoder)) + config.pretrained_controlnet_path = os.path.join(magic_animate_models_dir, os.path.dirname(controlnet)) + motion_module = os.path.join(magic_animate_models_dir, motion_module) + config.motion_module = motion_module + tokenizer = CLIPTokenizer.from_pretrained(config.pretrained_model_path, subfolder='tokenizer') + text_encoder = CLIPTextModel.from_pretrained(config.pretrained_model_path, subfolder='text_encoder') + if config.pretrained_unet_path: + unet = UNet3DConditionModel.from_pretrained_2d(config.pretrained_unet_path, unet_additional_kwargs=OmegaConf.to_container(inference_config.unet_additional_kwargs)) + else: + unet = UNet3DConditionModel.from_pretrained_2d(config.pretrained_model_path, subfolder='unet', unet_additional_kwargs=OmegaConf.to_container(inference_config.unet_additional_kwargs)) + appearance_encoder = AppearanceEncoderModel.from_pretrained(config.pretrained_appearance_encoder_path).to(device) + reference_control_writer = ReferenceAttentionControl(appearance_encoder, do_classifier_free_guidance=True, mode='write', fusion_blocks=config.fusion_blocks) + reference_control_reader = ReferenceAttentionControl(unet, do_classifier_free_guidance=True, mode='read', fusion_blocks=config.fusion_blocks) + vae = AutoencoderKL.from_pretrained(config.pretrained_vae_path) + controlnet = ControlNetModel.from_pretrained(config.pretrained_controlnet_path) + vae.to(torch.float16) + unet.to(torch.float16) + text_encoder.to(torch.float16) + appearance_encoder.to(torch.float16) + controlnet.to(torch.float16) + pipeline = AnimationPipeline(vae=vae, text_encoder=text_encoder, tokenizer=tokenizer, unet=unet, controlnet=controlnet, scheduler=DDIMScheduler(**OmegaConf.to_container(inference_config.noise_scheduler_kwargs))) + motion_module_state_dict = torch.load(motion_module, map_location='cpu') + motion_module_state_dict = motion_module_state_dict['state_dict'] if 'state_dict' in motion_module_state_dict else motion_module_state_dict + try: + state_dict = OrderedDict() + for key in motion_module_state_dict.keys(): + if key.startswith('module.'): + _key = key.split('module.')[-1] + state_dict[_key] = motion_module_state_dict[key] + else: + state_dict[key] = motion_module_state_dict[key] + motion_module_state_dict = state_dict + del state_dict + (missing, unexpected) = pipeline.unet.load_state_dict(motion_module_state_dict, strict=False) + assert len(unexpected) == 0 + except: + _tmp_ = OrderedDict() + for key in motion_module_state_dict.keys(): + if 'motion_modules' in key: + if key.startswith('unet.'): + _key = key.split('unet.')[-1] + _tmp_[_key] = motion_module_state_dict[key] + else: + _tmp_[key] = motion_module_state_dict[key] + (missing, unexpected) = unet.load_state_dict(_tmp_, strict=False) + assert len(unexpected) == 0 + del _tmp_ + del motion_module_state_dict + pipeline.to(device) + self.models['vae'] = vae + self.models['text_encoder'] = text_encoder + self.models['appearance_encoder'] = appearance_encoder + self.models['tokenizer'] = tokenizer + self.models['unet'] = unet + self.models['controlnet'] = controlnet + self.models['pipeline'] = pipeline + self.models['config'] = config + self.models['reference_control_writer'] = reference_control_writer + self.models['reference_control_reader'] = reference_control_reader + return (self.models,) +``` \ No newline at end of file diff --git a/docs/Make Image Batch.md b/docs/Make Image Batch.md new file mode 100644 index 0000000..e5beb02 --- /dev/null +++ b/docs/Make Image Batch.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: MakeImageBatch +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +‘MakeImageBatch’节点旨在高效地将多个单独的图像或现有的图像批次合并为一个单一的、统一的批次。这个节点在图像处理任务的预处理阶段中扮演着至关重要的角色,允许将各种图像输入聚合成适合批量处理的格式。 + +# Input types +## Required +- image1 + - 作为图像批次创建基础的主要图像。它是必需的,其存在启动了批次形成过程。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- image2 + - 可以连接到批次的可选附加图像。它增强了批次内的多样性,为处理提供了更多数据。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image3 + - 批次中的另一个可选图像,进一步扩展了用于全面分析的数据集。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image4 + - 可以包含在批次中的额外图像,以增加图像数据的体积。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image5 + - 此图像是可选的,它增加了图像批次的复杂性和丰富性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image6 + - 可以添加到批次中的最终可选图像,为数据集大小提供最后的贡献。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- result + - 输出是通过按顺序附加输入图像创建的整合图像批次。它很重要,因为它代表了批次创建过程的顶点。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MakeImageBatch: + """ + Creates a batch of images from multiple individual images or batches. + """ + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image1': ('IMAGE',)}, 'optional': {'image2': ('IMAGE',), 'image3': ('IMAGE',), 'image4': ('IMAGE',), 'image5': ('IMAGE',), 'image6': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'append' + CATEGORY = 'Masquerade Nodes' + + def append(self, image1, image2=None, image3=None, image4=None, image5=None, image6=None): + result = image1 + if image2 is not None: + result = torch.cat((result, image2), 0) + if image3 is not None: + result = torch.cat((result, image3), 0) + if image4 is not None: + result = torch.cat((result, image4), 0) + if image5 is not None: + result = torch.cat((result, image5), 0) + if image6 is not None: + result = torch.cat((result, image6), 0) + return (result,) +``` \ No newline at end of file diff --git a/docs/Make Interpolation State List.md b/docs/Make Interpolation State List.md new file mode 100644 index 0000000..dda79ad --- /dev/null +++ b/docs/Make Interpolation State List.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: MakeInterpolationStateList +- Category: ComfyUI-Frame-Interpolation/VFI +- Output node: False +- Repo Ref: https://github.com/Fannovel16/ComfyUI-Frame-Interpolation + +该节点旨在管理和创建插值状态列表,这对于帧插值过程至关重要。它决定了在插值过程中哪些帧包含或跳过,从而优化计算工作量并确保生成平滑连贯的帧过渡。 + +# Input types +## Required +- frame_indices + - 该参数指定了一个逗号分隔的帧索引列表,节点将使用该列表来确定哪些帧在插值过程中被包含或跳过。这对于节点正确运行至关重要,并直接影响帧插值的结果。 + - Comfy dtype: STRING + - Python dtype: List[int] +## Optional +- is_skip_list + - 该参数控制指定的帧索引是否应在插值过程中被跳过或包含。它在节点的整体操作中起着重要作用,因为它决定了节点在帧选择期间的行为。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- INTERPOLATION_STATES + - 该节点的输出是一个InterpolationStateList对象,它封装了关于包含或跳过哪些帧的决策。这个对象对于依赖这些决策来执行实际帧插值的后续操作至关重要。 + - Comfy dtype: INTERPOLATION_STATES + - Python dtype: InterpolationStateList + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MakeInterpolationStateList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'frame_indices': ('STRING', {'multiline': True, 'default': '1,2,3'}), 'is_skip_list': ('BOOLEAN', {'default': True})}} + RETURN_TYPES = ('INTERPOLATION_STATES',) + FUNCTION = 'create_options' + CATEGORY = 'ComfyUI-Frame-Interpolation/VFI' + + def create_options(self, frame_indices: str, is_skip_list: bool): + frame_indices_list = [int(item) for item in frame_indices.split(',')] + interpolation_state_list = InterpolationStateList(frame_indices=frame_indices_list, is_skip_list=is_skip_list) + return (interpolation_state_list,) +``` \ No newline at end of file diff --git a/docs/MakeBasicPipe %2F%2FInspire.md b/docs/MakeBasicPipe %2F%2FInspire.md new file mode 100644 index 0000000..6bef29c --- /dev/null +++ b/docs/MakeBasicPipe %2F%2FInspire.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: MakeBasicPipe +- Category: InspirePack/Prompt +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +MakeBasicPipe节点旨在为生成模型简化和操作文本提示的过程。它处理正面和负面提示,集成了先进的编码技术来精炼模型生成的输入数据。该节点抽象了提示构建的复杂性,专注于提高输入数据的质量和相关性,以改善生成输出。 + +# Input types +## Required +- ckpt_name + - 检查点名称对于识别用于生成过程的特定模型状态至关重要。这是一个必需的参数,它指导节点定位和使用适当的模型权重和配置。 + - Comfy dtype: STRING + - Python dtype: str +- positive_wildcard_text + - 此参数保存正面通配符文本,作为指导生成模型产生期望结果的指南。其策略性使用可以显著影响生成文本的质量。 + - Comfy dtype: STRING + - Python dtype: str +- negative_wildcard_text + - 负面通配符文本为模型提供了避免不需要的输出的框架。它是引导生成过程朝着预期方向前进的重要组成部分。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- basic_pipe + - 输出代表一个结构化的流程,包括模型、编码器和处理过的提示,准备进行生成过程。它封装了节点在准备数据以有效利用模型的功能。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, CLIP, VAE, str] +- cache_key + - 这个输出是缓存的检查点和提示数据的唯一标识符,可用于后续的检索和处理。它对于保持生成工作流的一致性和效率至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MakeBasicPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (folder_paths.get_filename_list('checkpoints'),), 'ckpt_key_opt': ('STRING', {'multiline': False, 'placeholder': "If empty, use 'ckpt_name' as the key."}), 'positive_wildcard_text': ('STRING', {'multiline': True, 'dynamicPrompts': False, 'placeholder': 'Positive Prompt (User Input)'}), 'negative_wildcard_text': ('STRING', {'multiline': True, 'dynamicPrompts': False, 'placeholder': 'Negative Prompt (User Input)'}), 'Add selection to': ('BOOLEAN', {'default': True, 'label_on': 'Positive', 'label_off': 'Negative'}), 'Select to add LoRA': (['Select the LoRA to add to the text'] + folder_paths.get_filename_list('loras'),), 'Select to add Wildcard': (['Select the Wildcard to add to the text'],), 'wildcard_mode': ('BOOLEAN', {'default': True, 'label_on': 'Populate', 'label_off': 'Fixed'}), 'positive_populated_text': ('STRING', {'multiline': True, 'dynamicPrompts': False, 'placeholder': 'Populated Positive Prompt (Will be generated automatically)'}), 'negative_populated_text': ('STRING', {'multiline': True, 'dynamicPrompts': False, 'placeholder': 'Populated Negative Prompt (Will be generated automatically)'}), 'token_normalization': (['none', 'mean', 'length', 'length+mean'],), 'weight_interpretation': (['comfy', 'A1111', 'compel', 'comfy++', 'down_weight'], {'default': 'comfy++'}), 'stop_at_clip_layer': ('INT', {'default': -2, 'min': -24, 'max': -1, 'step': 1}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'optional': {'vae_opt': ('VAE',)}} + CATEGORY = 'InspirePack/Prompt' + RETURN_TYPES = ('BASIC_PIPE', 'STRING') + RETURN_NAMES = ('basic_pipe', 'cache_key') + FUNCTION = 'doit' + + def doit(self, **kwargs): + pos_populated = kwargs['positive_populated_text'] + neg_populated = kwargs['negative_populated_text'] + clip_encoder = BNK_EncoderWrapper(kwargs['token_normalization'], kwargs['weight_interpretation']) + if 'ImpactWildcardEncode' not in nodes.NODE_CLASS_MAPPINGS: + utils.try_install_custom_node('https://github.com/ltdrdata/ComfyUI-Impact-Pack', "To use 'Make Basic Pipe (Inspire)' node, 'Impact Pack' extension is required.") + raise Exception(f"[ERROR] To use 'Make Basic Pipe (Inspire)', you need to install 'Impact Pack'") + (model, clip, vae, key) = CheckpointLoaderSimpleShared().doit(ckpt_name=kwargs['ckpt_name'], key_opt=kwargs['ckpt_key_opt']) + clip = nodes.CLIPSetLastLayer().set_last_layer(clip, kwargs['stop_at_clip_layer'])[0] + (model, clip, positive) = nodes.NODE_CLASS_MAPPINGS['ImpactWildcardEncode'].process_with_loras(wildcard_opt=pos_populated, model=model, clip=clip, clip_encoder=clip_encoder) + (model, clip, negative) = nodes.NODE_CLASS_MAPPINGS['ImpactWildcardEncode'].process_with_loras(wildcard_opt=neg_populated, model=model, clip=clip, clip_encoder=clip_encoder) + if 'vae_opt' in kwargs: + vae = kwargs['vae_opt'] + basic_pipe = (model, clip, vae, positive, negative) + return (basic_pipe, key) +``` \ No newline at end of file diff --git a/docs/MakeCircularVAE.md b/docs/MakeCircularVAE.md new file mode 100644 index 0000000..813a710 --- /dev/null +++ b/docs/MakeCircularVAE.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: MakeCircularVAE +- Category: latent +- Output node: False +- Repo Ref: https://github.com/spinagon/ComfyUI-seamless-tiling + +MakeCircularVAE节点的`run`方法旨在修改变分自编码器(VAE)模型,以实现对卷积层的循环填充。这种调整允许模型处理具有周期性边界条件的数据,这对于具有固有循环对称性的数据特别有用。节点可以基于提供的平铺配置,将循环填充应用于x和y两个维度,或者选择性地应用于其中一个维度。 + +# Input types +## Required +- vae + - 'vae'参数是要被修改的变分自编码器模型。它是节点操作的核心组件,因为它决定了将接受循环填充转换的模型。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- tiling + - 'tiling'参数决定如何将循环填充应用于VAE模型的卷积层。它控制是否将填充应用于两个维度,或者只应用于一个维度,对于模型处理周期性数据的能力至关重要。 + - Comfy dtype: COMBO['enable', 'x_only', 'y_only', 'disable'] + - Python dtype: str +- copy_vae + - 'copy_vae'参数决定是直接修改原始VAE模型还是首先创建模型的副本。这个选择可以影响内存使用和对模型所做的更改的范围。 + - Comfy dtype: COMBO['Make a copy', 'Modify in place'] + - Python dtype: str + +# Output types +- VAE + - 节点的输出是已修改或复制的变分自编码器模型,其卷积层已应用循环填充,增强了其处理具有循环对称性数据的能力。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MakeCircularVAE: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'vae': ('VAE',), 'tiling': (['enable', 'x_only', 'y_only', 'disable'],), 'copy_vae': (['Make a copy', 'Modify in place'],)}} + RETURN_TYPES = ('VAE',) + FUNCTION = 'run' + CATEGORY = 'latent' + + def run(self, vae, tiling, copy_vae): + if copy_vae == 'Modify in place': + vae_copy = vae + else: + vae_copy = copy.deepcopy(vae) + if tiling == 'enable': + make_circular_asymm(vae_copy.first_stage_model, True, True) + elif tiling == 'x_only': + make_circular_asymm(vae_copy.first_stage_model, True, False) + elif tiling == 'y_only': + make_circular_asymm(vae_copy.first_stage_model, False, True) + else: + make_circular_asymm(vae_copy.first_stage_model, False, False) + return (vae_copy,) +``` \ No newline at end of file diff --git a/docs/Manga2Anime_LineArt_Preprocessor_Provider_for_SEGS %2F%2FInspire.md b/docs/Manga2Anime_LineArt_Preprocessor_Provider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..78dd5fa --- /dev/null +++ b/docs/Manga2Anime_LineArt_Preprocessor_Provider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: Manga2Anime_LineArt_Preprocessor_Provider_for_SEGS +- Category: InspirePack/SEGS/ControlNet +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点作为Manga2Anime线稿预处理器的提供者,专门为从漫画风格的图像中分割和增强线稿而设计。它封装了将图像转换为适合进一步处理和风格化所需的功能,重点是保持原始艺术作品的完整性和视觉吸引力。 + +# Input types +## Required +- image + - 将进行线稿预处理的输入图像。此参数至关重要,因为它是节点操作的主要数据源。节点处理图像以增强和澄清线稿特征。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray +- mask + - 一个可选的掩码图像,可用于指导线稿的预处理。掩码可以通过将处理集中在图像的特定区域来影响节点的执行。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray + +# Output types +- SEGS_PREPROCESSOR + - 输出是经过预处理的线稿图像,已增强用于分割目的。这个输出很重要,因为它为工作流中的后续分割任务奠定了基础。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Manga2Anime_LineArt_Preprocessor_Provider_for_SEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}} + RETURN_TYPES = ('SEGS_PREPROCESSOR',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/SEGS/ControlNet' + + def doit(self): + obj = Manga2Anime_LineArt_Preprocessor_wrapper() + return (obj,) +``` \ No newline at end of file diff --git a/docs/Mask Arbitrary Region.md b/docs/Mask Arbitrary Region.md new file mode 100644 index 0000000..55b4bfa --- /dev/null +++ b/docs/Mask Arbitrary Region.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: WAS_Mask_Arbitrary_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Arbitrary_Region节点的arbitrary_region方法旨在处理输入掩码,并根据提供的大小和阈值参数生成表示感兴趣区域的张量。该方法特别适用于需要识别和提取图像中特定区域的应用,例如图像编辑、分析或涉及区域焦点的机器学习任务。 + +# Input types +## Required +- masks + - 输入掩码参数对于arbitrary_region方法至关重要,因为它定义了将从中提取感兴趣区域的来源。输入掩码的质量和特性直接影响区域识别过程的结果。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- size + - 大小参数决定了将被视为感兴趣区域的区域的尺寸。它是该方法中的一个关键因素,因为它直接影响提取区域的规模。 + - Comfy dtype: INT + - Python dtype: int +- threshold + - 阈值参数用于设置在输入掩码内识别感兴趣区域的灵敏度级别。它在区域提取的准确性中扮演着重要角色。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MASKS + - MASKS输出参数代表包含从输入掩码中提取的感兴趣区域的张量。它是一个重要的输出,因为它提供了arbitrary_region方法的最终结果,可供进一步处理或分析。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Arbitrary_Region: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',), 'size': ('INT', {'default': 256, 'min': 1, 'max': 4096, 'step': 1}), 'threshold': ('INT', {'default': 128, 'min': 0, 'max': 255, 'step': 1})}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'arbitrary_region' + + def arbitrary_region(self, masks, size=256, threshold=128): + if masks.ndim > 3: + regions = [] + for mask in masks: + mask_np = np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.arbitrary_region(pil_image, size, threshold) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + regions.append(region_tensor) + regions_tensor = torch.cat(regions, dim=0) + return (regions_tensor,) + else: + mask_np = np.clip(255.0 * masks.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.arbitrary_region(pil_image, size, threshold) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + return (region_tensor,) +``` \ No newline at end of file diff --git a/docs/Mask Batch to Mask.md b/docs/Mask Batch to Mask.md new file mode 100644 index 0000000..008bc2c --- /dev/null +++ b/docs/Mask Batch to Mask.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: WAS_Mask_Batch_to_Single_Mask +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +‘mask_batch_to_mask’方法旨在处理一批掩码张量,并根据指定的批次号提取单个掩码张量。在需要从集合中获取特定掩码的场景中至关重要,促进了从批量到单实例操作的过渡。 + +# Input types +## Required +- masks + - ‘masks’参数是节点将处理的掩码张量集合。它至关重要,因为它构成了节点操作的基础,决定了将考虑提取的掩码。 + - Comfy dtype: MASK + - Python dtype: List[Tuple[torch.Tensor, ...]] +## Optional +- batch_number + - ‘batch_number’参数指定从批次中提取哪个掩码张量。它很重要,因为它决定了节点内的选择过程,确保根据批次索引返回正确的掩码。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- single_mask + - ‘single_mask’输出代表了从批次中提取的单个掩码张量。它很重要,因为它是节点操作的主要结果,为用户提供了他们请求的特定掩码。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Batch_to_Single_Mask: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',), 'batch_number': ('INT', {'default': 0, 'min': 0, 'max': 64, 'step': 1})}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'mask_batch_to_mask' + CATEGORY = 'WAS Suite/Image/Masking' + + def mask_batch_to_mask(self, masks=[], batch_number=0): + count = 0 + for _ in masks: + if batch_number == count: + tensor = masks[batch_number][0] + return (tensor,) + count += 1 + cstr(f'Batch number `{batch_number}` is not defined, returning last image').error.print() + last_tensor = masks[-1][0] + return (last_tensor,) +``` \ No newline at end of file diff --git a/docs/Mask Batch.md b/docs/Mask Batch.md new file mode 100644 index 0000000..bcdca15 --- /dev/null +++ b/docs/Mask Batch.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: WAS_Mask_Batch +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Batch节点旨在高效处理和批量处理多个掩码输入。它确保所有输入掩码符合统一的尺寸,并将它们堆叠成单个批次以供进一步处理。该节点在准备下游任务所需的一致掩码尺寸的数据中发挥着关键作用。 + +# Input types +## Optional +- masks_a + - 'masks_a'参数是一个可选输入,允许用户为处理提供一组掩码。它对节点的操作至关重要,因为它直接影响将被批量处理和处理的数据。 + - Comfy dtype: MASK + - Python dtype: Union[torch.Tensor, None] +- masks_b + - 'masks_b'参数与'masks_a'类似,提供另一个可选的掩码集合,以包含在批量处理中。 + - Comfy dtype: MASK + - Python dtype: Union[torch.Tensor, None] +- masks_c + - 'masks_c'参数是另一个可选输入,用于额外的掩码,进一步提高了节点在处理各种掩码输入方面的灵活性。 + - Comfy dtype: MASK + - Python dtype: Union[torch.Tensor, None] +- masks_d + - 'masks_d'参数为节点提供了一组额外的掩码以供处理,确保节点能够适应广泛的掩码输入。 + - Comfy dtype: MASK + - Python dtype: Union[torch.Tensor, None] + +# Output types +- masks + - 'masks'输出是一个包含所有输入处理过的掩码的批量张量。它很重要,因为它代表了节点的主要输出,准备用于后续操作。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Batch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'optional': {'masks_a': ('MASK',), 'masks_b': ('MASK',), 'masks_c': ('MASK',), 'masks_d': ('MASK',)}} + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('masks',) + FUNCTION = 'mask_batch' + CATEGORY = 'WAS Suite/Image/Masking' + + def _check_mask_dimensions(self, tensors, names): + dimensions = [tensor.shape[1:] for tensor in tensors] + if len(set(dimensions)) > 1: + mismatched_indices = [i for (i, dim) in enumerate(dimensions) if dim != dimensions[0]] + mismatched_masks = [names[i] for i in mismatched_indices] + raise ValueError(f'WAS Mask Batch Warning: Input mask dimensions do not match for masks: {mismatched_masks}') + + def mask_batch(self, **kwargs): + batched_tensors = [kwargs[key] for key in kwargs if kwargs[key] is not None] + mask_names = [key for key in kwargs if kwargs[key] is not None] + if not batched_tensors: + raise ValueError('At least one input mask must be provided.') + self._check_mask_dimensions(batched_tensors, mask_names) + batched_tensors = torch.stack(batched_tensors, dim=0) + batched_tensors = batched_tensors.unsqueeze(1) + return (batched_tensors,) +``` \ No newline at end of file diff --git a/docs/Mask By Text.md b/docs/Mask By Text.md new file mode 100644 index 0000000..dc5d8ac --- /dev/null +++ b/docs/Mask By Text.md @@ -0,0 +1,125 @@ +# Documentation +- Class name: ClipSegNode +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +ClipSegNode 类旨在根据提供的文本提示自动从输入图像生成掩码。它利用预训练模型理解文本描述并将其应用于视觉内容,创建一个隔离图像中描述主题的分段掩码。 + +# Input types +## Required +- image + - 输入图像是节点操作的主要数据源。它是将生成掩码的视觉内容。图像的质量和分辨率直接影响生成的掩码的准确性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- prompt + - 文本提示是指导节点在图像中识别用于掩码的主题的描述性输入。它对于模型在分割过程中理解要关注的内容至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- precision + - 精度参数决定了掩码生成的阈值。它是一个浮点值,决定了节点在决定哪些像素属于掩码时应有多严格。 + - Comfy dtype: FLOAT + - Python dtype: float +- normalize + - normalize 参数指示是否应将结果掩码标准化到 0 到 1 之间的范围。在某些需要一致掩码强度的应用中,标准化可能会很有用。 + - Comfy dtype: COMBO['no', 'yes'] + - Python dtype: Literal['no', 'yes'] +## Optional +- negative_prompt + - 负面提示是一个可选输入,它通过指示应从分割中排除的内容来帮助细化掩码。它通过向模型提供额外的上下文来提高掩码的精度。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- thresholded_mask + - 阈值掩码是节点的主要输出,代表基于提供的文本提示对图像进行二进制分割。它是需要主题隔离以进行进一步处理的应用程序的关键组成部分。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- raw_mask + - 原始掩码输出在应用任何阈值之前提供了分割掩码的连续值表示。它对于需要更精细理解分割的应用程序可能有用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ClipSegNode: + """ + Automatically calculates a mask based on the text prompt + """ + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'prompt': ('STRING', {'multiline': True}), 'negative_prompt': ('STRING', {'multiline': True}), 'precision': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'normalize': (['no', 'yes'],)}} + RETURN_TYPES = ('IMAGE', 'IMAGE') + RETURN_NAMES = ('thresholded_mask', 'raw_mask') + FUNCTION = 'get_mask' + CATEGORY = 'Masquerade Nodes' + + def get_mask(self, image, prompt, negative_prompt, precision, normalize): + model = self.load_model() + image = tensor2rgb(image) + (B, H, W, _) = image.shape + used_dim = max(W, H) + transform = transforms.Compose([transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), transforms.Resize((used_dim, used_dim), antialias=True)]) + img = transform(image.permute(0, 3, 1, 2)) + prompts = prompt.split(DELIMITER) + negative_prompts = negative_prompt.split(DELIMITER) if negative_prompt != '' else [] + with torch.no_grad(): + dup_prompts = [item for item in prompts for _ in range(B)] + preds = model(img.repeat(len(prompts), 1, 1, 1), dup_prompts)[0] + dup_neg_prompts = [item for item in negative_prompts for _ in range(B)] + negative_preds = model(img.repeat(len(negative_prompts), 1, 1, 1), dup_neg_prompts)[0] if len(negative_prompts) > 0 else None + preds = torch.nn.functional.interpolate(preds, size=(H, W), mode='nearest') + preds = torch.sigmoid(preds) + preds = preds.reshape(len(prompts), B, H, W) + mask = torch.max(preds, dim=0).values + if len(negative_prompts) > 0: + negative_preds = torch.nn.functional.interpolate(negative_preds, size=(H, W), mode='nearest') + negative_preds = torch.sigmoid(negative_preds) + negative_preds = negative_preds.reshape(len(negative_prompts), B, H, W) + mask_neg = torch.max(negative_preds, dim=0).values + mask = torch.min(mask, 1.0 - mask_neg) + if normalize == 'yes': + mask_min = torch.min(mask) + mask_max = torch.max(mask) + mask_range = mask_max - mask_min + mask = (mask - mask_min) / mask_range + thresholded = torch.where(mask >= precision, 1.0, 0.0) + return (thresholded.to(device=image.device), mask.to(device=image.device)) + + def load_model(self): + global cached_clipseg_model + if cached_clipseg_model == None: + ensure_package('clipseg', 'clipseg@git+https://github.com/timojl/clipseg.git@bbc86cfbb7e6a47fb6dae47ba01d3e1c2d6158b0') + from clipseg.clipseg import CLIPDensePredT + model = CLIPDensePredT(version='ViT-B/16', reduce_dim=64, complex_trans_conv=True) + model.eval() + d64_file = self.download_and_cache('rd64-uni-refined.pth', 'https://owncloud.gwdg.de/index.php/s/ioHbRzFx6th32hn/download?path=%2F&files=rd64-uni-refined.pth') + d16_file = self.download_and_cache('rd16-uni.pth', 'https://owncloud.gwdg.de/index.php/s/ioHbRzFx6th32hn/download?path=%2F&files=rd16-uni.pth') + device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + model.load_state_dict(torch.load(d64_file, map_location=device), strict=False) + model = model.eval().to(device=device) + cached_clipseg_model = model + return cached_clipseg_model + + def download_and_cache(self, cache_name, url): + cache_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'download_cache') + os.makedirs(cache_dir, exist_ok=True) + file_name = os.path.join(cache_dir, cache_name) + if not os.path.exists(file_name): + print(f'Downloading and caching file: {cache_name}') + with open(file_name, 'wb') as file: + import requests + r = requests.get(url, stream=True) + r.raise_for_status() + for block in r.iter_content(4096): + file.write(block) + print('Finished downloading.') + return file_name +``` \ No newline at end of file diff --git a/docs/Mask Ceiling Region.md b/docs/Mask Ceiling Region.md new file mode 100644 index 0000000..ec35d37 --- /dev/null +++ b/docs/Mask Ceiling Region.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: WAS_Mask_Ceiling_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Ceiling_Region节点的ceiling_region方法旨在处理输入掩码并识别其中的最上区域。它的工作原理是将掩码转换为PIL图像,应用天花板效果以隔离顶部区域,然后将结果转换回适合进一步图像处理任务的张量格式。 + +# Input types +## Required +- masks + - 输入掩码参数对于ceiling_region方法至关重要,因为它提供了节点将处理的原始掩码数据。此参数直接影响节点的输出,它决定了图像中的哪些区域被识别为最上区域。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Output types +- MASKS + - MASKS输出参数代表包含从输入掩码中处理过的区域的张量。这个输出很重要,因为它是节点处理的成果,用于图像分析流程中的后续任务。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Ceiling_Region: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',)}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'ceiling_region' + + def ceiling_region(self, masks): + if masks.ndim > 3: + regions = [] + for mask in masks: + mask_np = np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.ceiling_region(pil_image) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + regions.append(region_tensor) + regions_tensor = torch.cat(regions, dim=0) + return (regions_tensor,) + else: + mask_np = np.clip(255.0 * masks.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.ceiling_region(pil_image) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + return (region_tensor,) +``` \ No newline at end of file diff --git a/docs/Mask Crop Dominant Region.md b/docs/Mask Crop Dominant Region.md new file mode 100644 index 0000000..6aec397 --- /dev/null +++ b/docs/Mask Crop Dominant Region.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: WAS_Mask_Crop_Dominant_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +crop_dominant_region 方法旨在处理输入掩码并智能裁剪每个掩码中的主导区域。这对于专注于图像的最重要部分特别有用,对于图像摘要、对象识别和内容感知图像调整大小等应用非常有益。该方法应用填充以确保裁剪区域不会太靠近边缘,从而提高结果图像的质量。 + +# Input types +## Required +- masks + - 输入掩码参数对于节点的操作至关重要,因为它定义了图像内的兴趣区域。此参数直接影响力节点的输出,它决定了裁剪过程后将保留图像的哪些部分。掩码应作为张量提供,以确保与节点的内部处理机制兼容。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- padding + - padding 参数用于指定裁剪后保留在主导区域周围的空间量。它对于防止裁剪区域太靠近图像边缘至关重要,这可能导致更令人愉悦的结果。默认值设置为24,合理地平衡了专注于主导区域和保持图像上下文之间的关系。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MASKS + - 输出参数 MASKS 表示在主导区域裁剪过程后的生成掩码。它是一个包含裁剪后兴趣区域的张量,可以用于进一步的图像处理或分析。此输出的重要性在于其能够提供原始图像的专注子集,可能提高后续操作的效率。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Crop_Dominant_Region: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',), 'padding': ('INT', {'default': 24, 'min': 0, 'max': 4096, 'step': 1})}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'crop_dominant_region' + + def crop_dominant_region(self, masks, padding=24): + if masks.ndim > 3: + regions = [] + for mask in masks: + mask_pil = Image.fromarray(np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)) + region_mask = self.WT.Masking.crop_dominant_region(mask_pil, padding) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + regions.append(region_tensor) + regions_tensor = torch.cat(regions, dim=0) + return (regions_tensor,) + else: + mask_pil = Image.fromarray(np.clip(255.0 * masks.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)) + region_mask = self.WT.Masking.crop_dominant_region(mask_pil, padding) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + return (region_tensor,) +``` \ No newline at end of file diff --git a/docs/Mask Crop Minority Region.md b/docs/Mask Crop Minority Region.md new file mode 100644 index 0000000..5425443 --- /dev/null +++ b/docs/Mask Crop Minority Region.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: WAS_Mask_Crop_Minority_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Crop_Minority_Region 节点旨在处理输入图像或表示掩码的张量,并智能裁剪其中的少数区域。这对于专注于图像中不太突出的区域以进行进一步分析或处理特别有用。该节点可以处理单个掩码和掩码批次,并根据用户指定应用裁剪区域的填充。 + +# Input types +## Required +- masks + - 输入掩码是此节点的主要输入,可以是单个掩码或多个掩码的堆栈,代表将被处理的图像区域。节点将识别这些掩码中的少数区域,并相应地执行裁剪操作。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- padding + - padding 参数允许用户指定在裁剪的少数区域周围添加的填充量。这对于保留裁剪区域周围的上下文或与其他图像处理任务的无缝集成非常有用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MASKS + - 节点的输出是输入掩码中裁剪的少数区域。它们可以用于进一步的处理或分析任务。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Crop_Minority_Region: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',), 'padding': ('INT', {'default': 24, 'min': 0, 'max': 4096, 'step': 1})}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'crop_minority_region' + + def crop_minority_region(self, masks, padding=24): + if masks.ndim > 3: + regions = [] + for mask in masks: + mask_pil = Image.fromarray(np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)) + region_mask = self.WT.Masking.crop_minority_region(mask_pil, padding) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + regions.append(region_tensor) + regions_tensor = torch.cat(regions, dim=0) + return (regions_tensor,) + else: + mask_pil = Image.fromarray(np.clip(255.0 * masks.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)) + region_mask = self.WT.Masking.crop_minority_region(mask_pil, padding) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + return (region_tensor,) +``` \ No newline at end of file diff --git a/docs/Mask Crop Region.md b/docs/Mask Crop Region.md new file mode 100644 index 0000000..55e189e --- /dev/null +++ b/docs/Mask Crop Region.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: WAS_Mask_Crop_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Crop_Region 节点旨在通过识别和裁剪掩码内的区域来处理图像。它使用填充和区域类型参数来控制裁剪行为,确保结果图像段可以无缝集成,以用于游戏开发或3D建模等应用。该节点在图像预处理中发挥着至关重要的作用,以便获得更加量身定制和视觉上连贯的结果。 + +# Input types +## Required +- mask + - 掩码参数是一个二进制图像数组,它定义了要从原始图像中裁剪的区域。它对节点的操作至关重要,因为它直接影响选择哪些图像部分进行裁剪。 + - Comfy dtype: np.ndarray + - Python dtype: numpy.ndarray +## Optional +- padding + - 填充参数在裁剪区域周围添加边框,这有助于平滑边缘或保留对图像上下文重要的内容。 + - Comfy dtype: int + - Python dtype: int +- region_type + - region_type 参数确定裁剪策略:是关注掩码内的主要区域还是次要区域。这影响裁剪图像的最终构图。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- cropped_mask + - cropped_mask 输出是掩码中结果裁剪区域的张量表示。它标志着图像内所需区域的成功隔离。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- crop_data + - crop_data 输出提供了有关裁剪区域的尺寸和位置的详细信息,这对于进一步的图像处理或分析至关重要。 + - Comfy dtype: Tuple[int, Tuple[int, int, int, int]] + - Python dtype: Tuple[int, Tuple[int, int, int, int]] +- top_int + - top_int 输出表示裁剪区域从图像顶部的垂直位置。 + - Comfy dtype: int + - Python dtype: int +- left_int + - left_int 输出表示裁剪区域从图像左侧的水平位置。 + - Comfy dtype: int + - Python dtype: int +- right_int + - right_int 输出指定裁剪区域右侧边缘在图像内的水平位置。 + - Comfy dtype: int + - Python dtype: int +- bottom_int + - bottom_int 输出表示裁剪区域底部边缘在图像内的垂直位置。 + - Comfy dtype: int + - Python dtype: int +- width_int + - width_int 输出提供裁剪区域的宽度,这对于调整图像段的大小或定位很重要。 + - Comfy dtype: int + - Python dtype: int +- height_int + - height_int 输出提供裁剪区域的高度,这是保持纵横比或缩放图像段的关键测量值。 + - Comfy dtype: int + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Crop_Region: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'mask': ('MASK',), 'padding': ('INT', {'default': 24, 'min': 0, 'max': 4096, 'step': 1}), 'region_type': (['dominant', 'minority'],)}} + RETURN_TYPES = ('MASK', 'CROP_DATA', 'INT', 'INT', 'INT', 'INT', 'INT', 'INT') + RETURN_NAMES = ('cropped_mask', 'crop_data', 'top_int', 'left_int', 'right_int', 'bottom_int', 'width_int', 'height_int') + FUNCTION = 'mask_crop_region' + CATEGORY = 'WAS Suite/Image/Masking' + + def mask_crop_region(self, mask, padding=24, region_type='dominant'): + mask_pil = Image.fromarray(np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)) + (region_mask, crop_data) = self.WT.Masking.crop_region(mask_pil, region_type, padding) + region_tensor = pil2mask(ImageOps.invert(region_mask)).unsqueeze(0).unsqueeze(1) + ((width, height), (left, top, right, bottom)) = crop_data + return (region_tensor, crop_data, top, left, right, bottom, width, height) +``` \ No newline at end of file diff --git a/docs/Mask Dilate Region.md b/docs/Mask Dilate Region.md new file mode 100644 index 0000000..5a5d8d1 --- /dev/null +++ b/docs/Mask Dilate Region.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: WAS_Mask_Dilate_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +dilate_region 方法旨在对输入掩码执行形态学膨胀,扩展掩码区域的边界。这一过程对于需要增强掩码边缘或在掩码区域内创建缓冲区的应用至关重要。通过应用指定次数的迭代,该方法允许控制膨胀的范围,因此为涉及掩码操作的各种图像处理任务提供了一种多功能工具。 + +# Input types +## Required +- masks + - 输入掩码参数对于 dilate_region 方法至关重要,因为它定义了要进行膨胀的区域。这是一个关键组件,直接影响膨胀过程的结果。掩码应以该方法可以解释和处理的格式提供,通常作为张量或 numpy 数组。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- iterations + - 迭代次数参数决定了对输入掩码应用膨胀操作的次数。它是一个可选参数,允许用户控制膨胀的程度,更多的迭代次数会导致更显著的效果。这个参数对于微调膨胀以适应特定应用需求非常重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MASKS + - MASKS 输出参数代表膨胀过程的结果。它包含了经过指定次数迭代后从原始输入掩码扩展得到的膨胀掩码。这个输出非常重要,因为它是 dilate_region 方法的主要结果,用于进一步的图像处理或分析。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Dilate_Region: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',), 'iterations': ('INT', {'default': 5, 'min': 1, 'max': 64, 'step': 1})}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'dilate_region' + + def dilate_region(self, masks, iterations=5): + if masks.ndim > 3: + regions = [] + for mask in masks: + mask_np = np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.dilate_region(pil_image, iterations) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + regions.append(region_tensor) + regions_tensor = torch.cat(regions, dim=0) + return (regions_tensor,) + else: + mask_np = np.clip(255.0 * masks.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.dilate_region(pil_image, iterations) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + return (region_tensor,) +``` \ No newline at end of file diff --git a/docs/Mask Dominant Region.md b/docs/Mask Dominant Region.md new file mode 100644 index 0000000..0f36954 --- /dev/null +++ b/docs/Mask Dominant Region.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: WAS_Mask_Dominant_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +dominant_region 方法旨在识别和隔离给定掩码图像中最突出的区域。它处理输入图像以突出显示基于指定阈值的最大连续区域。该方法特别适用于重点放在图像中的主要主题或特征的应用中,例如图像分割或特征提取任务。 + +# Input types +## Required +- masks + - 输入掩码参数对于节点的操作至关重要,因为它定义了要处理的图像数据。节点依赖此输入来识别图像中的主导区域,使其成为直接影响节点功能执行和结果的关键组件。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- threshold + - 阈值参数在确定图像中接缝的可见性方面起着重要作用。通过调整阈值,用户可以控制接缝的可见性与结果图像大小之间的平衡,这对于需要无缝纹理或图案的应用程序至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MASKS + - 输出 MASKS 参数表示已处理的图像数据,其中已识别并隔离了主要区域。此输出很重要,因为它提供了节点操作的结果,可以进一步用于下游流程或应用程序。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Dominant_Region: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',), 'threshold': ('INT', {'default': 128, 'min': 0, 'max': 255, 'step': 1})}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'dominant_region' + + def dominant_region(self, masks, threshold=128): + if masks.ndim > 3: + regions = [] + for mask in masks: + mask_pil = Image.fromarray(np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)) + region_mask = self.WT.Masking.dominant_region(mask_pil, threshold) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + regions.append(region_tensor) + regions_tensor = torch.cat(regions, dim=0) + return (regions_tensor,) + else: + mask_pil = Image.fromarray(np.clip(255.0 * masks.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)) + region_mask = self.WT.Masking.dominant_region(mask_pil, threshold) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + return (region_tensor,) +``` \ No newline at end of file diff --git a/docs/Mask Erode Region.md b/docs/Mask Erode Region.md new file mode 100644 index 0000000..dc2d2a1 --- /dev/null +++ b/docs/Mask Erode Region.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: WAS_Mask_Erode_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +erode_region 方法旨在通过应用腐蚀效果来处理输入掩码,修剪掩码区域的边界。在图像处理任务中,例如去除噪声或隔离图像中的不同区域,这种方法特别有用。它通过迭代减小掩码区域的大小来操作,从而创建更平滑和更明确边界。可以通过迭代参数控制腐蚀的程度,允许微调效果。 + +# Input types +## Required +- masks + - 输入掩码参数对于 erode_region 方法至关重要,因为它定义了将要经历腐蚀的图像区域。此参数直接影响节点的执行和结果,决定了图像的哪些部分将受到腐蚀过程的影响。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- iterations + - 迭代次数参数用于控制应用于输入掩码的腐蚀效果的程度。更高的值会导致更明显的腐蚀,导致掩码区域的大小更显著地减少。该参数对于调整腐蚀的强度以达到所需的视觉效果至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MASKS + - MASKS 输出参数代表应用腐蚀过程后的最终掩码。它是一个关键的输出,因为它反映了腐蚀后图像区域的最终状态,包含了后续工作流程中进一步处理或分析所需的信息。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Erode_Region: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',), 'iterations': ('INT', {'default': 5, 'min': 1, 'max': 64, 'step': 1})}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'erode_region' + + def erode_region(self, masks, iterations=5): + if masks.ndim > 3: + regions = [] + for mask in masks: + mask_np = np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.erode_region(pil_image, iterations) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + regions.append(region_tensor) + regions_tensor = torch.cat(regions, dim=0) + return (regions_tensor,) + else: + mask_np = np.clip(255.0 * masks.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.erode_region(pil_image, iterations) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + return (region_tensor,) +``` \ No newline at end of file diff --git a/docs/Mask Fill Holes.md b/docs/Mask Fill Holes.md new file mode 100644 index 0000000..d4289c6 --- /dev/null +++ b/docs/Mask Fill Holes.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: WAS_Mask_Fill_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Fill_Region 节点旨在处理图像掩码并填充指定区域,这对于涉及图像分割或基于区域操作的应用至关重要。它利用 WAS_Tools_Class 的能力执行实际填充,确保填充区域被适当地集成到掩码中。当需要创建无缝纹理或合成图,其中区域的连续性很重要时,此节点特别有用。 + +# Input types +## Required +- masks + - 'masks' 参数是节点的关键输入,它定义了将被处理的二进制掩码。它对节点的执行至关重要,因为它直接影响被填充的区域。该参数期望一个掩码数组,其中每个掩码对应一个要填充的区域。 + - Comfy dtype: np.ndarray + - Python dtype: numpy.ndarray + +# Output types +- MASKS + - 'MASKS' 输出参数代表了节点操作的结果,即掩码内填充区域的数组。这个输出很重要,因为它提供了可以用于各种应用中进一步分析或渲染的处理过的掩码。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Fill_Region: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',)}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'fill_region' + + def fill_region(self, masks): + if masks.ndim > 3: + regions = [] + for mask in masks: + mask_np = np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.fill_region(pil_image) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + regions.append(region_tensor) + regions_tensor = torch.cat(regions, dim=0) + return (regions_tensor,) + else: + mask_np = np.clip(255.0 * masks.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.fill_region(pil_image) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + return (region_tensor,) +``` \ No newline at end of file diff --git a/docs/Mask Floor Region.md b/docs/Mask Floor Region.md new file mode 100644 index 0000000..ecc9796 --- /dev/null +++ b/docs/Mask Floor Region.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: WAS_Mask_Floor_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +floor_region 方法旨在处理给定的掩码并识别其中的最低强度区域。它通过将掩码转换为 NumPy 数组,应用阈值来隔离非黑色像素,然后确定这些像素中的最小值来操作。该方法能够处理单个掩码和掩码批次,并返回表示处理区域的张量。 + +# Input types +## Required +- masks + - 输入掩码参数对于 floor_region 方法至关重要,因为它定义了将被处理的掩码或掩码批次。节点的执行依赖于此输入来识别和基于它们的强度值操作掩码内的区域。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- MASKS + - 输出参数 MASKS 表示 floor_region 方法处理的结果。它是一个张量,包含了在输入掩码中识别出的最低强度区域,展示了节点在基于它们的强度值隔离和突出特定区域方面的功能。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Floor_Region: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',)}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'floor_region' + + def floor_region(self, masks): + if masks.ndim > 3: + regions = [] + for mask in masks: + mask_np = np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.floor_region(pil_image) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + regions.append(region_tensor) + regions_tensor = torch.cat(regions, dim=0) + return (regions_tensor,) + else: + mask_np = np.clip(255.0 * masks.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.floor_region(pil_image) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + return (region_tensor,) +``` \ No newline at end of file diff --git a/docs/Mask Gaussian Region.md b/docs/Mask Gaussian Region.md new file mode 100644 index 0000000..e1eab1e --- /dev/null +++ b/docs/Mask Gaussian Region.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: WAS_Mask_Gaussian_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Gaussian_Region 节点的 gaussian_region 方法旨在通过应用高斯模糊效果来处理输入掩码,这对于生成图像区域中的平滑过渡非常有用。这种方法通过减少可见接缝来增强纹理的视觉质量,使其适用于需要无缝纹理的应用,如游戏开发和3D建模。 + +# Input types +## Required +- masks + - 输入掩码参数对于节点的操作至关重要,因为它定义了将要经历高斯模糊效果的图像区域。此参数直接影响纹理处理的结果,决定了生成的图像的平滑度和连续性。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- radius + - 半径参数决定了应用于输入掩码的高斯模糊的程度。较大的半径会导致更明显的模糊效果,可以用来创建图像不同区域之间更柔和的过渡。这个参数对于微调最终纹理的视觉外观至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- MASKS + - MASKS 输出提供了应用了高斯模糊的已处理图像掩码。这个输出很重要,因为它代表了节点操作的最终结果,可以用于进一步的图像处理任务或集成到更大的工作流程中。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Gaussian_Region: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',), 'radius': ('FLOAT', {'default': 5.0, 'min': 0.0, 'max': 1024, 'step': 0.1})}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'gaussian_region' + + def gaussian_region(self, masks, radius=5.0): + if masks.ndim > 3: + regions = [] + for mask in masks: + mask_np = np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.gaussian_region(pil_image, radius) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + regions.append(region_tensor) + regions_tensor = torch.cat(regions, dim=0) + return (regions_tensor,) + else: + mask_np = np.clip(255.0 * masks.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.gaussian_region(pil_image, radius) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + return (region_tensor,) +``` \ No newline at end of file diff --git a/docs/Mask Invert.md b/docs/Mask Invert.md new file mode 100644 index 0000000..bbac185 --- /dev/null +++ b/docs/Mask Invert.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: WAS_Mask_Invert +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Invert节点旨在反转输入掩码,为某些图像处理任务中操纵图像掩码提供了一种手段。它是应用程序中不可或缺的工具,适用于需要反转二进制掩码数据的情况,例如在图像分割或合成中。 + +# Input types +## Required +- masks + - 'masks'参数对于节点的操作至关重要,因为它定义了要反转的二进制掩码。其正确使用对于实现图像处理工作流程中期望的结果至关重要。 + - Comfy dtype: MASK + - Python dtype: Union[PIL.Image.Image, np.ndarray] + +# Output types +- MASKS + - 'MASKS'输出代表了反转后的二进制掩码,这是节点主要功能的直接结果。它对于依赖于反转掩码进行进一步图像操作的下游流程具有重要意义。 + - Comfy dtype: MASK + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Invert: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',)}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'add_masks' + + def add_masks(self, masks): + return (1.0 - masks,) +``` \ No newline at end of file diff --git a/docs/Mask Minority Region.md b/docs/Mask Minority Region.md new file mode 100644 index 0000000..b292df1 --- /dev/null +++ b/docs/Mask Minority Region.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: WAS_Mask_Minority_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +minority_region 方法旨在处理输入掩码并识别其中的少数区域。它通过将掩码转换为 PIL 图像,应用阈值来区分不同的区域,然后隔离最小的区域。此方法特别适用于关注图像中不太显着或少数区域的应用,例如在图像分割或特征提取任务中。 + +# Input types +## Required +- masks + - 输入掩码参数对于 minority_region 方法至关重要,因为它定义了图像内的兴趣区域。此参数影响方法识别和处理少数区域的方式,对结果的准确性至关重要。 + - Comfy dtype: MASK + - Python dtype: Union[torch.Tensor, List[torch.Tensor]] +## Optional +- threshold + - 阈值参数用于确定掩码内不同区域之间的截止点。它在 minority_region 方法中起着重要作用,通过影响哪些区域被视为少数区域的一部分。默认值设置为 128,允许在应用阈值时具有一定的灵活性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MASKS + - MASKS 输出参数代表从输入掩码处理后的少数区域。它是一个关键的输出,因为它提供了 minority_region 方法的最终结果,突出显示原始图像中不太显着的区域。 + - Comfy dtype: MASK + - Python dtype: Tuple[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Minority_Region: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',), 'threshold': ('INT', {'default': 128, 'min': 0, 'max': 255, 'step': 1})}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'minority_region' + + def minority_region(self, masks, threshold=128): + if masks.ndim > 3: + regions = [] + for mask in masks: + mask_np = np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.minority_region(pil_image, threshold) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + regions.append(region_tensor) + regions_tensor = torch.cat(regions, dim=0) + return (regions_tensor,) + else: + mask_np = np.clip(255.0 * masks.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.minority_region(pil_image, threshold) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + return (region_tensor,) +``` \ No newline at end of file diff --git a/docs/Mask Morphology.md b/docs/Mask Morphology.md new file mode 100644 index 0000000..2df4e71 --- /dev/null +++ b/docs/Mask Morphology.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: MaskMorphologyNode +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +MaskMorphologyNode 类旨在对图像掩码执行形态学操作。它提供了膨胀、腐蚀、开运算和闭运算的功能,这些对于图像处理任务(如去噪和特征增强)至关重要。 + +# Input types +## Required +- image + - 图像参数是一个张量,表示输入图像掩码。它对节点的操作至关重要,因为形态学变换直接应用于此图像数据。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- distance + - 距离参数确定了形态学操作的范围,例如用于膨胀或腐蚀的核的大小。它显著影响节点处理的结果。 + - Comfy dtype: INT + - Python dtype: int +- op + - 操作参数指定要执行的形态学操作类型,可以是膨胀、腐蚀、开运算或闭运算。这个选择直接影响应用于图像掩码的转换。 + - Comfy dtype: COMBO['dilate', 'erode', 'open', 'close'] + - Python dtype: str + +# Output types +- output_image + - 输出图像是将选定的形态学操作应用于输入图像的结果。它是原始图像掩码的转换版本,反映了所选操作的效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MaskMorphologyNode: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'distance': ('INT', {'default': 5, 'min': 0, 'max': 128, 'step': 1}), 'op': (['dilate', 'erode', 'open', 'close'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'morph' + CATEGORY = 'Masquerade Nodes' + + def morph(self, image, distance, op): + image = tensor2mask(image) + if op == 'dilate': + image = self.dilate(image, distance) + elif op == 'erode': + image = self.erode(image, distance) + elif op == 'open': + image = self.erode(image, distance) + image = self.dilate(image, distance) + elif op == 'close': + image = self.dilate(image, distance) + image = self.erode(image, distance) + return (image,) + + def erode(self, image, distance): + return 1.0 - self.dilate(1.0 - image, distance) + + def dilate(self, image, distance): + kernel_size = 1 + distance * 2 + image = image.unsqueeze(1) + out = torchfn.max_pool2d(image, kernel_size=kernel_size, stride=1, padding=kernel_size // 2).squeeze(1) + return out +``` \ No newline at end of file diff --git a/docs/Mask Paste Region.md b/docs/Mask Paste Region.md new file mode 100644 index 0000000..9781adb --- /dev/null +++ b/docs/Mask Paste Region.md @@ -0,0 +1,129 @@ +# Documentation +- Class name: WAS_Mask_Paste_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Paste_Region 节点旨在通过将裁剪区域粘贴到基础遮罩上来操作图像遮罩。它处理混合和锐化,以确保将粘贴区域无缝集成到原始遮罩中。该节点特别适用于需要精确控制遮罩修改的应用,例如在图像编辑或图形设计中。 + +# Input types +## Required +- mask + - 遮罩参数是节点的关键输入,代表将裁剪区域粘贴到的基础遮罩。它对于确定输出遮罩的最终外观至关重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- crop_mask + - crop_mask 参数定义了要粘贴到基础遮罩上的区域。它在整体操作中扮演着重要角色,因为它直接影响结果遮罩的内容和结构。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- crop_data + - crop_data 参数提供了要裁剪和粘贴的区域的尺寸和位置信息。它是可选的,但使用时会影响粘贴区域与基础遮罩的对齐方式。 + - Comfy dtype: CROP_DATA + - Python dtype: Tuple[int, Tuple[int, int, int, int]] +- crop_blending + - crop_blending 参数控制将裁剪区域粘贴到基础遮罩时的混合强度。它允许微调粘贴区域与周围遮罩之间的过渡。 + - Comfy dtype: FLOAT + - Python dtype: float +- crop_sharpening + - crop_sharpening 参数确定在粘贴之前要应用于裁剪区域的锐化级别。它可以增强粘贴区域的细节,以获得更好的视觉清晰度。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result_mask + - result_mask 输出参数代表粘贴操作后的最终遮罩。它是一个关键的输出,因为它反映了节点对原始遮罩与裁剪区域的操纵。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- result_crop_mask + - result_crop_mask 输出参数提供了所有处理步骤之后粘贴区域的遮罩。对于需要单独操作粘贴区域遮罩的应用来说,它是重要的。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Paste_Region: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'mask': ('MASK',), 'crop_mask': ('MASK',), 'crop_data': ('CROP_DATA',), 'crop_blending': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'crop_sharpening': ('INT', {'default': 0, 'min': 0, 'max': 3, 'step': 1})}} + RETURN_TYPES = ('MASK', 'MASK') + FUNCTION = 'mask_paste_region' + CATEGORY = 'WAS Suite/Image/Masking' + + def mask_paste_region(self, mask, crop_mask, crop_data=None, crop_blending=0.25, crop_sharpening=0): + if crop_data == False: + cstr('No valid crop data found!').error.print() + return (pil2mask(Image.new('L', (512, 512), 0)).unsqueeze(0).unsqueeze(1), pil2mask(Image.new('L', (512, 512), 0)).unsqueeze(0).unsqueeze(1)) + mask_pil = Image.fromarray(np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)) + mask_crop_pil = Image.fromarray(np.clip(255.0 * crop_mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8)) + (result_mask, result_crop_mask) = self.paste_image(mask_pil, mask_crop_pil, crop_data, crop_blending, crop_sharpening) + return (pil2mask(result_mask).unsqueeze(0).unsqueeze(1), pil2mask(result_crop_mask).unsqueeze(0).unsqueeze(1)) + + def paste_image(self, image, crop_image, crop_data, blend_amount=0.25, sharpen_amount=1): + + def lingrad(size, direction, white_ratio): + image = Image.new('RGB', size) + draw = ImageDraw.Draw(image) + if direction == 'vertical': + black_end = int(size[1] * (1 - white_ratio)) + range_start = 0 + range_end = size[1] + range_step = 1 + for y in range(range_start, range_end, range_step): + color_ratio = y / size[1] + if y <= black_end: + color = (0, 0, 0) + else: + color_value = int((y - black_end) / (size[1] - black_end) * 255) + color = (color_value, color_value, color_value) + draw.line([(0, y), (size[0], y)], fill=color) + elif direction == 'horizontal': + black_end = int(size[0] * (1 - white_ratio)) + range_start = 0 + range_end = size[0] + range_step = 1 + for x in range(range_start, range_end, range_step): + color_ratio = x / size[0] + if x <= black_end: + color = (0, 0, 0) + else: + color_value = int((x - black_end) / (size[0] - black_end) * 255) + color = (color_value, color_value, color_value) + draw.line([(x, 0), (x, size[1])], fill=color) + return image.convert('L') + (crop_size, (left, top, right, bottom)) = crop_data + crop_image = crop_image.resize(crop_size) + if sharpen_amount > 0: + for _ in range(int(sharpen_amount)): + crop_image = crop_image.filter(ImageFilter.SHARPEN) + blended_image = Image.new('RGBA', image.size, (0, 0, 0, 255)) + blended_mask = Image.new('L', image.size, 0) + crop_padded = Image.new('RGBA', image.size, (0, 0, 0, 0)) + blended_image.paste(image, (0, 0)) + crop_padded.paste(crop_image, (left, top)) + crop_mask = Image.new('L', crop_image.size, 0) + if top > 0: + gradient_image = ImageOps.flip(lingrad(crop_image.size, 'vertical', blend_amount)) + crop_mask = ImageChops.screen(crop_mask, gradient_image) + if left > 0: + gradient_image = ImageOps.mirror(lingrad(crop_image.size, 'horizontal', blend_amount)) + crop_mask = ImageChops.screen(crop_mask, gradient_image) + if right < image.width: + gradient_image = lingrad(crop_image.size, 'horizontal', blend_amount) + crop_mask = ImageChops.screen(crop_mask, gradient_image) + if bottom < image.height: + gradient_image = lingrad(crop_image.size, 'vertical', blend_amount) + crop_mask = ImageChops.screen(crop_mask, gradient_image) + crop_mask = ImageOps.invert(crop_mask) + blended_mask.paste(crop_mask, (left, top)) + blended_mask = blended_mask.convert('L') + blended_image.paste(crop_padded, (0, 0), blended_mask) + return (ImageOps.invert(blended_image.convert('RGB')).convert('L'), ImageOps.invert(blended_mask.convert('RGB')).convert('L')) +``` \ No newline at end of file diff --git a/docs/Mask Smooth Region.md b/docs/Mask Smooth Region.md new file mode 100644 index 0000000..8f34bee --- /dev/null +++ b/docs/Mask Smooth Region.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: WAS_Mask_Smooth_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Smooth_Region 节点旨在处理输入掩码并对其区域应用平滑效果。这对于生成无缝纹理或为进一步的图像处理任务准备掩码特别有用。节点使用高斯模糊技术平滑掩码内的区域,由 'sigma' 参数控制平滑的程度。节点的功能针对单个掩码和掩码批次进行了优化,确保了在各种应用中的灵活性和效率。 + +# Input types +## Required +- masks + - 'masks' 参数是节点的关键输入,期望得到一个掩码或掩码批次。此输入直接影响节点的操作,因为它决定了将要平滑的区域。该参数对于节点产生期望的输出至关重要,影响最终纹理质量和平铺图像的无缝性。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- sigma + - 'sigma' 参数定义了要应用于掩码区域的平滑度。它是一个浮点数,用于调整高斯模糊的标准差,较高的值会导致更明显的平滑效果。这个参数是可选的,但对节点的输出有显著影响,允许用户控制平滑区域的外观。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- MASKS + - 'MASKS' 输出提供了通过应用 'sigma' 参数定义的高斯模糊得到的平滑掩码或掩码批次。这个输出很重要,因为它代表了节点处理后的数据,可以用于后续操作或作为纹理生成的最终输出。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Smooth_Region: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',), 'sigma': ('FLOAT', {'default': 5.0, 'min': 0.0, 'max': 128.0, 'step': 0.1})}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'smooth_region' + + def smooth_region(self, masks, sigma=128): + if masks.ndim > 3: + regions = [] + for mask in masks: + mask_np = np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.smooth_region(pil_image, sigma) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + regions.append(region_tensor) + regions_tensor = torch.cat(regions, dim=0) + return (regions_tensor,) + else: + mask_np = np.clip(255.0 * masks.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.smooth_region(pil_image, sigma) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + return (region_tensor,) +``` \ No newline at end of file diff --git a/docs/Mask Threshold Region.md b/docs/Mask Threshold Region.md new file mode 100644 index 0000000..204cc9c --- /dev/null +++ b/docs/Mask Threshold Region.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: WAS_Mask_Threshold_Region +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Threshold_Region 节点旨在通过应用阈值处理图像掩码,以区分图像内的各个区域。它使用黑色和白色阈值来创建一个二进制掩码,根据像素强度对图像进行分段。此节点对于图像分割、目标检测以及任何需要基于颜色或亮度级别区分图像区域的应用至关重要。 + +# Input types +## Required +- masks + - 输入掩码是节点操作的主要来源。它们用于生成图像内的阈值区域。此参数至关重要,因为节点的所有功能都围绕着这些掩码的操纵和分析。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- black_threshold + - black_threshold 参数定义了像素被认为属于黑色区域的强度值下限。它在根据颜色强度将图像分割为不同区域的确定中起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- white_threshold + - white_threshold 参数用于定义像素被认为属于白色区域的强度值上限。它是控制分割过程和确定图像内白色区域的重要参数。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MASKS + - MASKS 输出由应用阈值操作后处理的图像掩码组成。这个输出很重要,因为它代表了根据指定的阈值输入图像的最终分段区域。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Threshold_Region: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',), 'black_threshold': ('INT', {'default': 75, 'min': 0, 'max': 255, 'step': 1}), 'white_threshold': ('INT', {'default': 175, 'min': 0, 'max': 255, 'step': 1})}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'threshold_region' + + def threshold_region(self, masks, black_threshold=75, white_threshold=255): + if masks.ndim > 3: + regions = [] + for mask in masks: + mask_np = np.clip(255.0 * mask.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.threshold_region(pil_image, black_threshold, white_threshold) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + regions.append(region_tensor) + regions_tensor = torch.cat(regions, dim=0) + return (regions_tensor,) + else: + mask_np = np.clip(255.0 * masks.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + pil_image = Image.fromarray(mask_np, mode='L') + region_mask = self.WT.Masking.threshold_region(pil_image, black_threshold, white_threshold) + region_tensor = pil2mask(region_mask).unsqueeze(0).unsqueeze(1) + return (region_tensor,) +``` \ No newline at end of file diff --git a/docs/Mask To Image (mtb).md b/docs/Mask To Image (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Mask To Region.md b/docs/Mask To Region.md new file mode 100644 index 0000000..2c537b1 --- /dev/null +++ b/docs/Mask To Region.md @@ -0,0 +1,139 @@ +# Documentation +- Class name: MaskToRegion +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +MaskToRegion节点旨在处理给定的掩码,并确定一个矩形区域,该区域在指定的约束条件下适应掩码。它智能地调整边界框的尺寸以适应掩码,同时保持所需的属性,如纵横比、可除性或倍数。该节点在需要精确操作掩码区域的应用中发挥着关键作用,例如图像分割或目标检测。 + +# Input types +## Required +- mask + - 'mask'参数至关重要,因为它定义了从中派生区域的输入掩码。它是节点操作以产生所需输出的主要数据源。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- padding + - 'padding'参数允许在掩码周围增加空间,这在需要在感兴趣的对象周围留出一些缓冲区的应用中可能至关重要。 + - Comfy dtype: INT + - Python dtype: int +- constraints + - 'constraints'参数在确定如何调整区域尺寸方面至关重要。它决定了是否应保持纵横比、强制执行可除性或尊重倍数。 + - Comfy dtype: COMBO[keep_ratio, keep_ratio_divisible, multiple_of, ignore] + - Python dtype: str +- constraint_x + - 'constraint_x'参数与'constraint_y'一起使用时,有助于定义宽度和高度调整的约束条件,确保输出区域满足特定的尺寸要求。 + - Comfy dtype: INT + - Python dtype: int +- constraint_y + - 'constraint_y'参数类似于'constraint_x',它有助于设置区域的垂直约束,补充了由'constraint_x'设置的水平约束。 + - Comfy dtype: INT + - Python dtype: int +- min_width + - 'min_width'参数确保结果区域的宽度不会低于指定的最小值,这对于保持所包含对象的可见性至关重要。 + - Comfy dtype: INT + - Python dtype: int +- min_height + - 'min_height'参数类似于'min_width',它保证区域的高度满足最小阈值,防止对象在垂直方向上被过度压缩。 + - Comfy dtype: INT + - Python dtype: int +- batch_behavior + - 'batch_behavior'参数影响批量中区域的处理方式,允许匹配所有区域的大小或确保一致的纵横比。 + - Comfy dtype: COMBO[match_ratio, match_size] + - Python dtype: str + +# Output types +- region + - 'region'输出参数代表了在应用所有指定的约束和调整后,包含输入掩码的最终矩形区域。它是依赖于精确区域定位的下游任务的关键组成部分。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MaskToRegion: + """ + Given a mask, returns a rectangular region that fits the mask with the given constraints + """ + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'mask': ('IMAGE',), 'padding': ('INT', {'default': 0, 'min': 0, 'max': VERY_BIG_SIZE, 'step': 1}), 'constraints': (['keep_ratio', 'keep_ratio_divisible', 'multiple_of', 'ignore'],), 'constraint_x': ('INT', {'default': 64, 'min': 2, 'max': VERY_BIG_SIZE, 'step': 1}), 'constraint_y': ('INT', {'default': 64, 'min': 2, 'max': VERY_BIG_SIZE, 'step': 1}), 'min_width': ('INT', {'default': 0, 'min': 0, 'max': VERY_BIG_SIZE, 'step': 1}), 'min_height': ('INT', {'default': 0, 'min': 0, 'max': VERY_BIG_SIZE, 'step': 1}), 'batch_behavior': (['match_ratio', 'match_size'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'get_region' + CATEGORY = 'Masquerade Nodes' + + def get_region(self, mask, padding, constraints, constraint_x, constraint_y, min_width, min_height, batch_behavior): + mask = tensor2mask(mask) + mask_size = mask.size() + mask_width = int(mask_size[2]) + mask_height = int(mask_size[1]) + is_empty = ~torch.gt(torch.max(torch.reshape(mask, [mask_size[0], mask_width * mask_height]), dim=1).values, 0.0) + mask[is_empty, 0, 0] = 1.0 + boxes = masks_to_boxes(mask) + mask[is_empty, 0, 0] = 0.0 + min_x = torch.max(boxes[:, 0] - padding, torch.tensor(0.0)) + min_y = torch.max(boxes[:, 1] - padding, torch.tensor(0.0)) + max_x = torch.min(boxes[:, 2] + padding, torch.tensor(mask_width)) + max_y = torch.min(boxes[:, 3] + padding, torch.tensor(mask_height)) + width = max_x - min_x + height = max_y - min_y + target_width = torch.max(width, torch.tensor(min_width)) + target_height = torch.max(height, torch.tensor(min_height)) + if constraints == 'keep_ratio': + target_width = torch.max(target_width, target_height * constraint_x // constraint_y) + target_height = torch.max(target_height, target_width * constraint_y // constraint_x) + elif constraints == 'keep_ratio_divisible': + max_factors = torch.min(constraint_x // target_width, constraint_y // target_height) + max_factor = int(torch.max(max_factors).item()) + for i in range(1, max_factor + 1): + divisible = constraint_x % i == 0 and constraint_y % i == 0 + if divisible: + big_enough = ~torch.lt(target_width, constraint_x // i) * ~torch.lt(target_height, constraint_y // i) + target_width[big_enough] = constraint_x // i + target_height[big_enough] = constraint_y // i + elif constraints == 'multiple_of': + target_width[torch.gt(target_width % constraint_x, 0)] = (target_width // constraint_x + 1) * constraint_x + target_height[torch.gt(target_height % constraint_y, 0)] = (target_height // constraint_y + 1) * constraint_y + if batch_behavior == 'match_size': + target_width[:] = torch.max(target_width) + target_height[:] = torch.max(target_height) + elif batch_behavior == 'match_ratio': + ratios = torch.abs(target_width / target_height - 1) + ratios[is_empty] = 10000 + match_ratio = torch.min(ratios, dim=0).indices.item() + target_width = torch.max(target_width, target_height * target_width[match_ratio] // target_height[match_ratio]) + target_height = torch.max(target_height, target_width * target_height[match_ratio] // target_width[match_ratio]) + missing = target_width - width + min_x = min_x - missing // 2 + max_x = max_x + (missing - missing // 2) + missing = target_height - height + min_y = min_y - missing // 2 + max_y = max_y + (missing - missing // 2) + bad = torch.lt(min_x, 0) + max_x[bad] -= min_x[bad] + min_x[bad] = 0 + bad = torch.lt(min_y, 0) + max_y[bad] -= min_y[bad] + min_y[bad] = 0 + bad = torch.gt(max_x, mask_width) + min_x[bad] -= max_x[bad] - mask_width + max_x[bad] = mask_width + bad = torch.gt(max_y, mask_height) + min_y[bad] -= max_y[bad] - mask_height + max_y[bad] = mask_height + region = torch.zeros((mask_size[0], mask_height, mask_width)) + for i in range(0, mask_size[0]): + if not is_empty[i]: + ymin = int(min_y[i].item()) + ymax = int(max_y[i].item()) + xmin = int(min_x[i].item()) + xmax = int(max_x[i].item()) + region[i, ymin:ymax + 1, xmin:xmax + 1] = 1 + return (region,) +``` \ No newline at end of file diff --git a/docs/MaskBatch+.md b/docs/MaskBatch+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/MaskBlur+.md b/docs/MaskBlur+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/MaskBoundingBox+.md b/docs/MaskBoundingBox+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/MaskComposite(FaceParsing).md b/docs/MaskComposite(FaceParsing).md new file mode 100644 index 0000000..5cc5661 --- /dev/null +++ b/docs/MaskComposite(FaceParsing).md @@ -0,0 +1,62 @@ +# Documentation +- Class name: MaskComposite +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +MaskComposite节点旨在对两个掩码张量执行各种逻辑和算术运算。它在图像处理任务中发挥关键作用,特别是在面部解析领域,它可以组合掩码以细化面部特征的分割。该节点基于逐元素操作的原理运行,确保输出掩码是应用于输入掩码中每对相应元素的指定操作的结果。 + +# Input types +## Required +- destination + - destination参数是一个表示初始掩码的张量,操作将应用于此掩码。它对节点的执行至关重要,因为它决定了将根据指定的操作进行修改的基础掩码。 + - Comfy dtype: "MASK" + - Python dtype: torch.Tensor +- source + - source参数是另一个张量,将与目标张量结合使用以执行指定操作。它至关重要,因为它提供了将与目标掩码交互以产生最终掩码结果的次要输入。 + - Comfy dtype: "MASK" + - Python dtype: torch.Tensor +- operation + - operation参数指示将在目标和源张量之间执行的逐元素操作的类型。它是如何计算最终掩码的关键决定因素,允许进行各种形式的掩码操作。 + - Comfy dtype: COMBO["multiply", "add", "subtract", "and", "or", "xor"] + - Python dtype: str + +# Output types +- mask_result + - mask_result输出参数是将指定操作应用于输入目标和源张量后得到的张量。它代表了操作执行后最终组合的掩码。 + - Comfy dtype: "MASK" + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MaskComposite: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'destination': ('MASK', {}), 'source': ('MASK', {}), 'operation': (['multiply', 'add', 'subtract', 'and', 'or', 'xor'],)}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, destination: Tensor, source: Tensor, operation: str): + mask_result = destination + if operation == 'multiply': + mask_result = mask_result * source + if operation == 'add': + mask_result = mask_result + source + if operation == 'subtract': + mask_result = mask_result - source + if operation == 'and': + mask_result = mask_result & source + if operation == 'or': + mask_result = mask_result | source + if operation == 'xor': + mask_result = mask_result ^ source + return (mask_result,) +``` \ No newline at end of file diff --git a/docs/MaskDetailerPipe.md b/docs/MaskDetailerPipe.md new file mode 100644 index 0000000..7ad311d --- /dev/null +++ b/docs/MaskDetailerPipe.md @@ -0,0 +1,87 @@ +# Documentation +- Class name: MaskDetailerPipe +- Category: ImpactPack/Detailer +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +MaskDetailerPipe节点旨在根据提供的掩码处理和增强图像细节。它利用先进的模型和算法细化和增强图像中的掩蔽区域,专注于提高指定区域的视觉质量和细节。 + +# Input types +## Required +- image + - 输入图像,由节点进行处理。它作为所有增强和细化操作的基础。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 定义图像内感兴趣区域的掩码。它用于引导增强过程,专注于图像的特定部分。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- basic_pipe + - 一组预训练模型和配置,用于图像的初始处理和分析。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, torch.nn.Module, Any, Any, Any] +## Optional +- guide_size + - 引导尺寸参数影响细节增强的比例。它决定了节点在处理期间将关注的细节层次。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- enhanced_img_batch + - 由处理生成的一批增强图像。它包括根据输入掩码和参数指定的细化细节。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- cropped_enhanced_list + - 一系列裁剪和增强的图像段。每个段对应于输入掩码定义的区域,并已处理以增强细节。 + - Comfy dtype: COMBO[IMAGE] + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MaskDetailerPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'mask': ('MASK',), 'basic_pipe': ('BASIC_PIPE',), 'guide_size': ('FLOAT', {'default': 384, 'min': 64, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'guide_size_for': ('BOOLEAN', {'default': True, 'label_on': 'mask bbox', 'label_off': 'crop region'}), 'max_size': ('FLOAT', {'default': 1024, 'min': 64, 'max': nodes.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': {'refiner_basic_pipe_opt': ('BASIC_PIPE',), 'detailer_hook': ('DETAILER_HOOK',), '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 = ('IMAGE', 'IMAGE', 'IMAGE', 'BASIC_PIPE', 'BASIC_PIPE') + RETURN_NAMES = ('image', 'cropped_refined', 'cropped_enhanced_alpha', 'basic_pipe', 'refiner_basic_pipe_opt') + OUTPUT_IS_LIST = (False, True, True, False, False) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detailer' + + def doit(self, image, mask, basic_pipe, 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=1, refiner_basic_pipe_opt=None, detailer_hook=None, inpaint_model=False, noise_mask_feather=0): + if len(image) > 1: + raise Exception('[Impact Pack] ERROR: MaskDetailer does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.') + (model, clip, vae, positive, negative) = basic_pipe + if refiner_basic_pipe_opt is None: + (refiner_model, refiner_clip, refiner_positive, refiner_negative) = (None, None, None, None) + else: + (refiner_model, refiner_clip, _, refiner_positive, refiner_negative) = refiner_basic_pipe_opt + if mask is not None: + mask = make_2d_mask(mask) + segs = core.mask_to_segs(mask, False, crop_factor, False, drop_size) + else: + segs = ((image.shape[1], image.shape[2]), []) + enhanced_img_batch = None + cropped_enhanced_list = [] + cropped_enhanced_alpha_list = [] + for i in range(batch_size): + if mask is not None: + (enhanced_img, _, cropped_enhanced, cropped_enhanced_alpha, _, _) = DetailerForEach.do_detail(image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed + i, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, mask_mode, force_inpaint=True, wildcard_opt=None, detailer_hook=detailer_hook, refiner_ratio=refiner_ratio, refiner_model=refiner_model, refiner_clip=refiner_clip, refiner_positive=refiner_positive, refiner_negative=refiner_negative, cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + else: + (enhanced_img, cropped_enhanced, cropped_enhanced_alpha) = (image, [], []) + if enhanced_img_batch is None: + enhanced_img_batch = enhanced_img + else: + enhanced_img_batch = torch.cat((enhanced_img_batch, enhanced_img), dim=0) + cropped_enhanced_list += cropped_enhanced + cropped_enhanced_alpha_list += cropped_enhanced_alpha + if len(cropped_enhanced_list) == 0: + cropped_enhanced_list = [empty_pil_tensor()] + if len(cropped_enhanced_alpha_list) == 0: + cropped_enhanced_alpha_list = [empty_pil_tensor()] + return (enhanced_img_batch, cropped_enhanced_list, cropped_enhanced_alpha_list, basic_pipe, refiner_basic_pipe_opt) +``` \ No newline at end of file diff --git a/docs/MaskExpandBatch+.md b/docs/MaskExpandBatch+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/MaskFlip+.md b/docs/MaskFlip+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/MaskFromBatch+.md b/docs/MaskFromBatch+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/MaskFromColor+.md b/docs/MaskFromColor+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/MaskListComposite(FaceParsing).md b/docs/MaskListComposite(FaceParsing).md new file mode 100644 index 0000000..3cc28f3 --- /dev/null +++ b/docs/MaskListComposite(FaceParsing).md @@ -0,0 +1,57 @@ +# Documentation +- Class name: MaskListComposite +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +MaskListComposite节点旨在对一系列二进制掩码执行指定的逻辑或算术操作。它顺序处理输入掩码,应用所选操作将它们组合成单个结果掩码。此节点在需要操作和组合二进制面部特征掩码的任务中起着关键作用,例如在面部分割或面部解析领域中的特征提取。 + +# Input types +## Required +- mask + - ‘mask’参数是要通过‘operation’参数指定的操作进行组合的二进制掩码集合。它对节点的功能至关重要,因为它决定了将经历逻辑或算术操作的输入。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- operation + - ‘operation’参数指示在输入掩码上执行的操作类型。它可以是‘multiply’、‘add’、‘and’、‘or’或‘xor’中的一个,它显著影响掩码组合过程的最终结果。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- result + - ‘result’参数是节点的输出,代表在输入掩码上应用指定操作后组合的掩码。它封装了节点处理的结果,对于依赖于合成掩码的后续任务至关重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MaskListComposite: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'mask': ('MASK', {}), 'operation': (['multiply', 'add', 'and', 'or', 'xor'],)}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, mask: Tensor, operation: str): + mask_result = mask[0] + for item in mask[1:]: + if operation == 'multiply': + mask_result = mask_result * item + if operation == 'add': + mask_result = mask_result + item + if operation == 'and': + mask_result = mask_result & item + if operation == 'or': + mask_result = mask_result | item + if operation == 'xor': + mask_result = mask_result ^ item + return (mask_result.unsqueeze(0),) +``` \ No newline at end of file diff --git a/docs/MaskListSelect(FaceParsing).md b/docs/MaskListSelect(FaceParsing).md new file mode 100644 index 0000000..4e04979 --- /dev/null +++ b/docs/MaskListSelect(FaceParsing).md @@ -0,0 +1,45 @@ +# Documentation +- Class name: MaskListSelect +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +MaskListSelect节点旨在从一系列掩码中选择和操作特定的元素。它对包含多个掩码的张量和一个索引进行操作,以识别所需的掩码。该节点的主要功能是从列表中提取单个掩码,以便进一步处理或分析。 + +# Input types +## Required +- mask + - 'mask'参数是一个包含多个掩码的张量。它对节点的操作至关重要,因为它是提取所需掩码的主要数据源。张量内的掩码预期以一种允许单独选择的格式存在。 + - Comfy dtype: "MASK" + - Python dtype: torch.Tensor +- index + - 'index'参数是一个整数,它指定了要在张量中选择的掩码的位置。它在确定将提取哪个掩码以供进一步使用中起着关键作用。默认值设置为0,对应于列表中的第一个掩码。 + - Comfy dtype: "INT" + - Python dtype: int + +# Output types +- selected_mask + - MaskListSelect节点的输出是一个从输入掩码列表中提取的单个掩码张量。这个输出可以用于下游任务,如掩码应用、可视化或进一步分析。 + - Comfy dtype: "MASK" + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MaskListSelect: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'mask': ('MASK', {}), 'index': ('INT', {'default': 0, 'min': 0, 'step': 1})}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, mask: Tensor, index: int): + return (mask[index].unsqueeze(0),) +``` \ No newline at end of file diff --git a/docs/MaskListToMaskBatch.md b/docs/MaskListToMaskBatch.md new file mode 100644 index 0000000..526d404 --- /dev/null +++ b/docs/MaskListToMaskBatch.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: MaskListToMaskBatch +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +MaskListToMaskBatch节点旨在将一系列掩码图像整合成一个单一的批次张量。它处理列表中的每个掩码,确保它们处于适合批量处理的3D格式,有效处理单个和多个掩码。该节点在准备下游机器学习模型所需的批量输入数据方面发挥着关键作用。 + +# Input types +## Required +- mask + - ‘mask’参数是节点处理的掩码图像列表。它对节点的操作至关重要,因为它直接影响输出的批次张量。节点通过将每个掩码转换为3D格式(如果需要),然后将它们组合成一个用于批量处理的单个张量来处理此列表。 + - Comfy dtype: MASK + - Python dtype: List[torch.Tensor] + +# Output types +- mask_batch + - MaskListToMaskBatch节点的输出是一个代表掩码批次的单个张量。这个张量被格式化为与期望批量输入数据的机器学习模型兼容,对于模型训练或推理的后续阶段非常重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MaskListToMaskBatch: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',)}} + INPUT_IS_LIST = True + RETURN_TYPES = ('MASK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, mask): + if len(mask) == 1: + mask = make_3d_mask(mask[0]) + return (mask,) + elif len(mask) > 1: + mask1 = make_3d_mask(mask[0]) + for mask2 in mask[1:]: + mask2 = make_3d_mask(mask2) + if mask1.shape[1:] != mask2.shape[1:]: + mask2 = comfy.utils.common_upscale(mask2.movedim(-1, 1), mask1.shape[2], mask1.shape[1], 'lanczos', 'center').movedim(1, -1) + mask1 = torch.cat((mask1, mask2), dim=0) + return (mask1,) + else: + empty_mask = torch.zeros((1, 64, 64), dtype=torch.float32, device='cpu').unsqueeze(0) + return (empty_mask,) +``` \ No newline at end of file diff --git a/docs/MaskPreview+.md b/docs/MaskPreview+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/MaskToBBox(FaceParsing).md b/docs/MaskToBBox(FaceParsing).md new file mode 100644 index 0000000..f9b32e8 --- /dev/null +++ b/docs/MaskToBBox(FaceParsing).md @@ -0,0 +1,53 @@ +# Documentation +- Class name: MaskToBBox +- Category: face_parsing +- Output node: False +- Repo Ref: https://github.com/Ryuukeisyou/comfyui_face_parsing + +该节点类封装了将面部遮罩数据转换为边界框坐标的功能,便于在图像中定位面部特征以进行进一步分析。 + +# Input types +## Required +- mask + - 遮罩参数是一个张量,代表面部遮罩,对于识别图像中的兴趣区域至关重要。它直接影响生成的边界框的准确性和质量。 + - Comfy dtype: Tensor + - Python dtype: torch.Tensor +## Optional +- pad + - pad参数允许通过填充边缘来调整边界框坐标。这对于细化边界框,使其更好地适应整个图像中的面部特征非常重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- BBOX + - 输出提供了一个元组列表,每个元组代表一个边界框的坐标。这些坐标对于定位面部特征非常重要,并且可以用于后续的处理步骤。 + - Comfy dtype: List[Tuple[INT, INT, INT, INT]] + - Python dtype: List[Tuple[int, int, int, int]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MaskToBBox: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'mask': ('MASK',), 'pad': ('INT', {'default': 0, 'min': 0, 'step': 1})}} + RETURN_TYPES = ('BBOX',) + FUNCTION = 'main' + CATEGORY = 'face_parsing' + + def main(self, mask: Tensor, pad: int): + result = ops.masks_to_boxes(mask) + if pad != 0: + for item in result: + item[0] = item[0] - pad + item[1] = item[1] - pad + item[2] = item[2] + pad + item[3] = item[3] + pad + return (result,) +``` \ No newline at end of file diff --git a/docs/MaskToSEGS.md b/docs/MaskToSEGS.md new file mode 100644 index 0000000..2709a2a --- /dev/null +++ b/docs/MaskToSEGS.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: MaskToSEGS +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +MaskToSEGS节点旨在将二进制掩码转换为由SEG对象表示的一系列分段对象。它处理输入掩码以识别不同区域,并将它们输出为分段对象的集合,这些对象可以进一步用于各种图像处理任务。 + +# Input types +## Required +- mask + - 掩码参数是一个二进制掩码,它定义了图像内的感兴趣区域。它对节点的操作至关重要,因为它直接影响分割过程和生成的SEG对象。 + - Comfy dtype: MASK + - Python dtype: np.ndarray +## Optional +- combined + - combined参数决定节点是否应将掩码中的重叠区域合并为单个SEG对象。这对于简化复杂场景的表示可能很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- crop_factor + - crop_factor参数控制每个掩码段的边界框周围的裁剪区域的大小。它通过确定每个段周围包含多少上下文,影响SEG对象的细节级别。 + - Comfy dtype: FLOAT + - Python dtype: float +- bbox_fill + - bbox_fill参数指定是否应在裁剪区域内用实心值填充边界框。这可以用来突出显示或隔离SEG对象内的特定区域。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- drop_size + - drop_size参数设置将包含在输出中的掩码段的最小尺寸。不满足此尺寸阈值的较小段将被丢弃,可能会减少分割中的噪声。 + - Comfy dtype: INT + - Python dtype: int +- contour_fill + - contour_fill参数指示节点是否应填充掩码轮廓内的区域。这可以用来从基于轮廓的掩码创建实心SEG对象。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- SEGS + - SEGS输出包含一系列SEG对象,每个对象代表从输入掩码派生的分段区域。这些对象被结构化,以便在图像处理工作流程中进一步分析或操作。 + - Comfy dtype: SEGS + - Python dtype: Tuple[int, List[core.SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MaskToSEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'combined': ('BOOLEAN', {'default': False, 'label_on': 'True', 'label_off': 'False'}), 'crop_factor': ('FLOAT', {'default': 3.0, 'min': 1.0, 'max': 100, 'step': 0.1}), 'bbox_fill': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'}), 'drop_size': ('INT', {'min': 1, 'max': MAX_RESOLUTION, 'step': 1, 'default': 10}), 'contour_fill': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'})}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, mask, combined, crop_factor, bbox_fill, drop_size, contour_fill=False): + mask = make_2d_mask(mask) + result = core.mask_to_segs(mask, combined, crop_factor, bbox_fill, drop_size, is_contour=contour_fill) + return (result,) +``` \ No newline at end of file diff --git a/docs/MaskToSEGS_for_AnimateDiff.md b/docs/MaskToSEGS_for_AnimateDiff.md new file mode 100644 index 0000000..15b66e7 --- /dev/null +++ b/docs/MaskToSEGS_for_AnimateDiff.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: MaskToSEGS_for_AnimateDiff +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +MaskToSEGS_for_AnimateDiff 节点旨在将二进制掩码转换为一组分段对象,称为 SEGS。它通过利用系统的核心功能来识别和分离掩码内的不同区域来执行此转换。该节点对于需要将掩码数据转换为可以进一步处理或分析以进行详细操作的格式的应用程序特别有用。 + +# Input types +## Required +- mask + - 掩码参数是节点的关键输入,因为它定义了要从中执行分割的二进制掩码。掩码的质量和准确性直接影响结果的分割,使其成为节点执行的重要组成部分。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- combined + - combined 参数决定节点是否应将掩码视为单个实体还是作为单独的段。这个决定影响分割的处理方式,并根据不同任务的具体需求可能导致不同的结果。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- crop_factor + - crop_factor 参数用于定义掩码内裁剪区域的大小。它在分割过程中起着重要作用,通过控制从掩码中提取的细节的规模。 + - Comfy dtype: FLOAT + - Python dtype: float +- bbox_fill + - bbox_fill 参数是一个可选设置,当启用时,它填充掩码内的边界框区域。在某些应用中,填充的边界框的存在对于进一步分析或处理是必要的,这可能很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- drop_size + - drop_size 参数指定要考虑进行分割的区域的最小尺寸。它确保只有大于某个尺寸阈值的区域包含在最终的分割中,这有助于过滤掉噪声或不相关的细节。 + - Comfy dtype: INT + - Python dtype: int +- contour_fill + - contour_fill 参数指示节点是否应填充掩码内的轮廓。这对于需要在后续操作中对分段区域进行实心填充的应用程序非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- SEGS + - SEGS 输出代表分割过程的结果,提供了原始掩码内不同区域的详细分解。这个输出对于进一步分析或操作分割数据至关重要。 + - Comfy dtype: SEGS + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MaskToSEGS_for_AnimateDiff: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'combined': ('BOOLEAN', {'default': False, 'label_on': 'True', 'label_off': 'False'}), 'crop_factor': ('FLOAT', {'default': 3.0, 'min': 1.0, 'max': 100, 'step': 0.1}), 'bbox_fill': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'}), 'drop_size': ('INT', {'min': 1, 'max': MAX_RESOLUTION, 'step': 1, 'default': 10}), 'contour_fill': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'})}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, mask, combined, crop_factor, bbox_fill, drop_size, contour_fill=False): + mask = make_2d_mask(mask) + segs = core.mask_to_segs(mask, combined, crop_factor, bbox_fill, drop_size, is_contour=contour_fill) + all_masks = SEGSToMaskList().doit(segs)[0] + result_mask = (all_masks[0] * 255).to(torch.uint8) + for mask in all_masks[1:]: + result_mask |= (mask * 255).to(torch.uint8) + result_mask = (result_mask / 255.0).to(torch.float32) + result_mask = utils.to_binary_mask(result_mask, 0.1)[0] + return MaskToSEGS().doit(result_mask, False, crop_factor, False, drop_size, contour_fill) +``` \ No newline at end of file diff --git a/docs/Masks Add.md b/docs/Masks Add.md new file mode 100644 index 0000000..e0e694c --- /dev/null +++ b/docs/Masks Add.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: WAS_Mask_Add +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Add节点旨在执行将两个掩码图像相加的操作。它擅长合并掩码数据以创建复合掩码,这在需要层叠掩码的图像处理工作流程中至关重要。该节点确保结果掩码值在有效范围内,有助于掩码层的无缝集成。 + +# Input types +## Required +- masks_a + - 参数'masks_a'代表要添加的第一组掩码图像。它在确定复合掩码的初始状态中起着关键作用,影响掩码处理过程的最终结果。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- masks_b + - 参数'masks_b'是与'masks_a'集成的第二组掩码图像。它对于创建一个全面掩码至关重要,该掩码包含了来自两组掩码的所需特征。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- MASKS + - 输出'MASKS'是节点执行的加法操作的结果。它是一个复合掩码,包含了输入掩码的组合特征,准备用于下游图像处理任务。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Add: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks_a': ('MASK',), 'masks_b': ('MASK',)}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'add_masks' + + def add_masks(self, masks_a, masks_b): + if masks_a.ndim > 2 and masks_b.ndim > 2: + added_masks = masks_a + masks_b + else: + added_masks = torch.clamp(masks_a.unsqueeze(1) + masks_b.unsqueeze(1), 0, 255) + added_masks = added_masks.squeeze(1) + return (added_masks,) +``` \ No newline at end of file diff --git a/docs/Masks Combine Batch.md b/docs/Masks Combine Batch.md new file mode 100644 index 0000000..8476d21 --- /dev/null +++ b/docs/Masks Combine Batch.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: WAS_Mask_Combine_Batch +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Combine_Batch 节点旨在将多个掩码图像合并为一个单一的、无缝的掩码。这对于需要进一步处理或可视化的应用程序特别有用。该节点接收一批掩码,并输出一个保留了输入掩码中基本特征的组合掩码。 + +# Input types +## Required +- masks + - 输入参数'masks'是将要组合的掩码图像列表。它在节点的操作中起着关键作用,因为输出掩码的质量和分辨率直接依赖于输入掩码。掩码应该以兼容的格式进行处理。 + - Comfy dtype: List[Image] + - Python dtype: List[PIL.Image.Image] + +# Output types +- combined_mask + - 'combined_mask'输出是输入掩码合并的结果。它是一张代表所有输入掩码集体覆盖范围的单个图像,适用于图像分割或视觉特效中的遮罩等应用。 + - Comfy dtype: Image + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Combine_Batch: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks': ('MASK',)}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + FUNCTION = 'combine_masks' + + def combine_masks(self, masks): + combined_mask = torch.sum(torch.stack([mask.unsqueeze(0) for mask in masks], dim=0), dim=0) + combined_mask = torch.clamp(combined_mask, 0, 1) + return (combined_mask,) +``` \ No newline at end of file diff --git a/docs/Masks Combine Regions.md b/docs/Masks Combine Regions.md new file mode 100644 index 0000000..e1b7267 --- /dev/null +++ b/docs/Masks Combine Regions.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: WAS_Mask_Combine +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Combine 节点旨在将多个遮罩图像合并为一个单一的、连贯的遮罩。它有效地合并输入的遮罩,可以用于各种应用,如图像处理、图形设计和视觉效果。该节点确保合并后的遮罩保留了各个单独遮罩的基本特征,使其成为增强视觉内容的多功能工具。 + +# Input types +## Required +- mask_a + - 要与其他遮罩结合的第一个遮罩。它在确定合并遮罩的初始属性方面起着关键作用。 + - Comfy dtype: MASK + - Python dtype: PIL.Image.Image or numpy.ndarray +- mask_b + - 要与第一个遮罩合并的第二个遮罩。它有助于最终遮罩的整体构成。 + - Comfy dtype: MASK + - Python dtype: PIL.Image.Image or numpy.ndarray +## Optional +- mask_c + - 可选的额外遮罩,可以包含在组合过程中,以进一步完善最终遮罩。 + - Comfy dtype: MASK + - Python dtype: PIL.Image.Image or numpy.ndarray +- mask_d + - 另一个可选的遮罩,可以提供给组合遮罩以增加其复杂性和细节。 + - Comfy dtype: MASK + - Python dtype: PIL.Image.Image or numpy.ndarray +- mask_e + - 一个额外的可选遮罩,可以用来给组合遮罩添加更多层,增强其视觉元素。 + - Comfy dtype: MASK + - Python dtype: PIL.Image.Image or numpy.ndarray +- mask_f + - 最后一个可选遮罩,可以集成到创建一个详细和复杂的组合遮罩中。 + - Comfy dtype: MASK + - Python dtype: PIL.Image.Image or numpy.ndarray + +# Output types +- combined_mask + - 所有输入遮罩组合后得到的最终遮罩。它是单一的遮罩,包含了输入遮罩的视觉数据。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Combine: + + def __init__(self): + self.WT = WAS_Tools_Class() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'mask_a': ('MASK',), 'mask_b': ('MASK',)}, 'optional': {'mask_c': ('MASK',), 'mask_d': ('MASK',), 'mask_e': ('MASK',), 'mask_f': ('MASK',)}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + FUNCTION = 'combine_masks' + + def combine_masks(self, mask_a, mask_b, mask_c=None, mask_d=None, mask_e=None, mask_f=None): + masks = [mask_a, mask_b] + if mask_c: + masks.append(mask_c) + if mask_d: + masks.append(mask_d) + if mask_e: + masks.append(mask_e) + if mask_f: + masks.append(mask_f) + combined_mask = torch.sum(torch.stack(masks, dim=0), dim=0) + combined_mask = torch.clamp(combined_mask, 0, 1) + return (combined_mask,) +``` \ No newline at end of file diff --git a/docs/Masks Subtract.md b/docs/Masks Subtract.md new file mode 100644 index 0000000..7cae74a --- /dev/null +++ b/docs/Masks Subtract.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: WAS_Mask_Subtract +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Mask_Subtract 节点的 subtract_masks 方法对两组掩码进行逐元素相减,确保结果落在有效的像素值范围内。它旨在促进需要从一个掩码中移除另一个掩码的操作,例如在图像处理或掩码应用中。 + +# Input types +## Required +- masks_a + - 用于减法操作的第一组掩码。此参数至关重要,因为它定义了将从中减去第二组掩码的基础。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- masks_b + - 将从第一组中减去的第二组掩码。此参数显著影响操作的结果。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- MASKS + - 两组掩码相减操作的结果,经过限制以确保有效的像素值。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Mask_Subtract: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'masks_a': ('MASK',), 'masks_b': ('MASK',)}} + CATEGORY = 'WAS Suite/Image/Masking' + RETURN_TYPES = ('MASK',) + RETURN_NAMES = ('MASKS',) + FUNCTION = 'subtract_masks' + + def subtract_masks(self, masks_a, masks_b): + subtracted_masks = torch.clamp(masks_a - masks_b, 0, 255) + return (subtracted_masks,) +``` \ No newline at end of file diff --git a/docs/MasksToMaskList.md b/docs/MasksToMaskList.md new file mode 100644 index 0000000..15d913e --- /dev/null +++ b/docs/MasksToMaskList.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: MasksToMaskList +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +MasksToMaskList节点旨在处理一系列掩码图像,将其转换为适用于图像处理任务中进一步操作的3D掩码张量列表。它通过应用必要的转换,确保每个掩码都处于正确的格式,无论其初始尺寸如何。 + +# Input types +## Required +- masks + - 'masks'参数是节点将处理的掩码图像集合。这对于节点的操作至关重要,因为它决定了将被转换为3D掩码张量列表的输入数据。 + - Comfy dtype: MASK + - Python dtype: List[torch.Tensor] + +# Output types +- mask_list + - 'mask_list'输出是一系列已处理并准备好用于后续图像处理任务的3D掩码张量。列表中的每个张量对应于输入中的一个转换掩码。 + - Comfy dtype: MASK + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MasksToMaskList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'masks': ('MASK',)}} + RETURN_TYPES = ('MASK',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, masks): + if masks is None: + empty_mask = torch.zeros((64, 64), dtype=torch.float32, device='cpu') + return ([empty_mask],) + res = [] + for mask in masks: + res.append(mask) + print(f'mask len: {len(res)}') + res = [make_3d_mask(x) for x in res] + return (res,) +``` \ No newline at end of file diff --git a/docs/MasqueradeIncrementer.md b/docs/MasqueradeIncrementer.md new file mode 100644 index 0000000..18da7fe --- /dev/null +++ b/docs/MasqueradeIncrementer.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: MaqueradeIncrementerNode +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +伪装增量节点旨在数据处理流程中执行一个简单但至关重要的操作。它接受一个种子值和一个上限值,通过应用模运算确保输出值保持在指定范围内。此节点在维护数据序列的完整性和顺序方面至关重要,特别是在循环模式或有界数值至关重要的场景中。 + +# Input types +## Required +- seed + - “种子”参数是增量操作的起始点。它至关重要,因为它决定了节点开始计算的初始值。种子对于确保输出的可重复性和一致性至关重要,特别是在迭代过程或模拟中。 + - Comfy dtype: INT + - Python dtype: int +- max_value + - “最大值”参数定义了增量操作的上限。它之所以重要,是因为它确保输出不会超过某个阈值,这对于保持数据在预期范围内的有效性至关重要。此参数在控制节点输出范围方面发挥着关键作用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result + - “结果”输出是将模运算应用于输入种子和最大值的结果。它表示一个被限制在指定范围内的值,适用于需要循环或有界数值数据的应用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MaqueradeIncrementerNode: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'seed': ('INT', {'default': 0, 'min': -1, 'max': 18446744073709551615, 'step': 1}), 'max_value': ('INT', {'default': 1, 'min': 1, 'max': 18446744073709551615, 'step': 1})}} + RETURN_TYPES = ('INT',) + FUNCTION = 'increment' + CATEGORY = 'Masquerade Nodes' + + def increment(self, seed, max_value): + return (seed % max_value,) +``` \ No newline at end of file diff --git a/docs/Match Dimensions (mtb).md b/docs/Match Dimensions (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Math Expression (mtb).md b/docs/Math Expression (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/MediaPipeFaceMeshDetectorProvider %2F%2FInspire.md b/docs/MediaPipeFaceMeshDetectorProvider %2F%2FInspire.md new file mode 100644 index 0000000..4af37f0 --- /dev/null +++ b/docs/MediaPipeFaceMeshDetectorProvider %2F%2FInspire.md @@ -0,0 +1,79 @@ +# Documentation +- Class name: MediaPipeFaceMeshDetectorProvider +- Category: InspirePack/Detector +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +MediaPipeFaceMeshDetectorProvider 节点旨在使用 MediaPipe FaceMesh 模型检测和分割图像中的面部。它提供识别和隔离面部特征的功能,例如面部轮廓、眼睛、眉毛和嘴巴。该节点的主要目标是增强图像中的面部细节,这对于涉及面部识别、动画或增强低分辨率面部图像的应用程序特别有用。 + +# Input types +## Required +- max_faces + - 参数 'max_faces' 定义了检测器应在输入图像中识别的最大面部数量。它在控制检测过程的范围方面起着关键作用,并且与面部检测的性能和准确性直接相关。 + - Comfy dtype: INT + - Python dtype: int +- face + - 参数 'face' 指示检测器是否应在检测过程中包括整个面部区域。启用此选项确保捕获面部区域,这对于需要全面面部细节的任务是必不可少的。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- mouth + - 当启用 'mouth' 参数时,指示检测器在检测到的面部中特别识别嘴部区域。这对于需要关注嘴部动作或表情的应用程序很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- left_eyebrow + - 参数 'left_eyebrow' 允许在面部特征检测中包含左眉。这对于需要详细分析面部表情或重建图像中的面部特征的应用程序特别有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- left_eye + - 参数 'left_eye' 启用左眼的检测,这对于涉及眼球运动的详细分析或生成准确的面部特征分割的应用非常重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- left_pupil + - 参数 'left_pupil' 用于检测面部区域中的左瞳孔。这对于需要精确眼球追踪或增强面部图像中虹膜清晰度的应用程序至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- right_eyebrow + - 参数 'right_eyebrow' 指定是否应在检测中包含右眉。它有助于捕捉全范围的面部表情,对于分析或模拟详细面部运动的应用程序特别有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- right_eye + - 参数 'right_eye' 激活右眼的检测,这对于全面的面部检测设置至关重要,允许进行详细的眼球运动分析或面部特征重建。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- right_pupil + - 参数 'right_pupil' 负责检测右瞳孔,在要求眼球追踪高精度或增强面部图像中虹膜细节的应用程序中起着关键作用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- bbox_detector + - 输出 'bbox_detector' 提供了检测到的面部的边界框坐标,这对于在图像中定位和进一步处理面部区域至关重要。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: List[Tuple[int, int, int, int]] +- segm_detector + - 输出 'segm_detector' 提供了检测到的面部的分割掩码,允许以高精度隔离和操作面部特征。 + - Comfy dtype: SEGM_DETECTOR + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MediaPipeFaceMeshDetectorProvider: + + @classmethod + def INPUT_TYPES(s): + bool_true_widget = ('BOOLEAN', {'default': True, 'label_on': 'enable', 'label_off': 'disable'}) + bool_false_widget = ('BOOLEAN', {'default': False, 'label_on': 'enable', 'label_off': 'disable'}) + return {'required': {'max_faces': ('INT', {'default': 10, 'min': 1, 'max': 50, 'step': 1}), 'face': bool_true_widget, 'mouth': bool_false_widget, 'left_eyebrow': bool_false_widget, 'left_eye': bool_false_widget, 'left_pupil': bool_false_widget, 'right_eyebrow': bool_false_widget, 'right_eye': bool_false_widget, 'right_pupil': bool_false_widget}} + RETURN_TYPES = ('BBOX_DETECTOR', 'SEGM_DETECTOR') + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Detector' + + def doit(self, max_faces, face, mouth, left_eyebrow, left_eye, left_pupil, right_eyebrow, right_eye, right_pupil): + bbox_detector = MediaPipeFaceMeshDetector(face, mouth, left_eyebrow, left_eye, left_pupil, right_eyebrow, right_eye, right_pupil, max_faces, is_segm=False) + segm_detector = MediaPipeFaceMeshDetector(face, mouth, left_eyebrow, left_eye, left_pupil, right_eyebrow, right_eye, right_pupil, max_faces, is_segm=True) + return (bbox_detector, segm_detector) +``` \ No newline at end of file diff --git a/docs/MediaPipeFaceMeshToSEGS.md b/docs/MediaPipeFaceMeshToSEGS.md new file mode 100644 index 0000000..08bb2e0 --- /dev/null +++ b/docs/MediaPipeFaceMeshToSEGS.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: MediaPipeFaceMeshToSEGS +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +MediaPipeFaceMeshToSEGS节点旨在处理面部图像并将其转换为结构化的分割格式。它利用MediaPipe FaceMesh模型检测面部标记,然后为指定的每个面部特征生成分割掩码。该节点能够处理各种面部部件,如面部、嘴巴、眼睛、眉毛和瞳孔,允许根据用户的需求进行详细分割。 + +# Input types +## Required +- image + - 输入图像是MediaPipeFaceMeshToSEGS节点的一个关键参数,因为它是面部标记检测和随后分割的基础。输入图像的质量和分辨率直接影响面部特征分割的准确性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- crop_factor + - crop_factor参数用于调整分割输出的大小。它是一个可选设置,允许用户通过调整输出尺寸来控制分割中的细节级别。 + - Comfy dtype: FLOAT + - Python dtype: float +- bbox_fill + - bbox_fill参数决定是否应该填充围绕分割面部特征的边界框。这个布尔标志可以用来自定义分割掩码的外观。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- crop_min_size + - crop_min_size参数指定围绕面部特征的裁剪区域的最小尺寸。它确保分割输出包含了检测到的标记周围的足够上下文。 + - Comfy dtype: INT + - Python dtype: int +- drop_size + - drop_size参数用于控制分割点之间的间距。它通过确定点之间的间隔来影响分割掩码的密度。 + - Comfy dtype: INT + - Python dtype: int +- dilation + - dilation参数应用于分割掩码以增加分割区域的大小。这对于细化较小面部特征的分割特别有用。 + - Comfy dtype: INT + - Python dtype: int +- face + - face参数是一个布尔标志,指示是否应将面部区域包含在分割中。它允许根据用户需求选择性地分割面部特征。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- mouth + - mouth参数是一个布尔标志,它决定分割是否应包括嘴巴区域。它在分割特定面部特征时提供了灵活性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- left_eyebrow + - left_eyebrow参数用于切换左眉是否包含在分割输出中。它允许选择性地分割个别面部特征。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- left_eye + - left_eye参数控制左眼区域是否是分割的一部分。它允许根据用户请求分割特定的面部区域。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- left_pupil + - left_pupil参数指定分割是否应包括左瞳孔。它用于眼区的详细分割。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- right_eyebrow + - right_eyebrow参数用于确定右眉是否应包含在分割掩码中。它支持根据请求进行面部特征的分割。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- right_eye + - right_eye参数指示是否应将右眼区域包含在分割中。它便于根据需要分割特定的面部区域。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- right_pupil + - right_pupil参数控制右瞳孔是否包含在分割过程中。这对于眼区的精确分割至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- SEGS + - SEGS输出提供了面部特征分割的结构化表示。它包括分割掩码的尺寸和包含标签和相应分割掩码张量元组的列表。 + - Comfy dtype: COMBO[str, List[Tuple[int, torch.Tensor]]] + - Python dtype: Tuple[int, List[Tuple[str, torch.Tensor]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MediaPipeFaceMeshToSEGS: + + @classmethod + def INPUT_TYPES(s): + bool_true_widget = ('BOOLEAN', {'default': True, 'label_on': 'Enabled', 'label_off': 'Disabled'}) + bool_false_widget = ('BOOLEAN', {'default': False, 'label_on': 'Enabled', 'label_off': 'Disabled'}) + return {'required': {'image': ('IMAGE',), 'crop_factor': ('FLOAT', {'default': 3.0, 'min': 1.0, 'max': 100, 'step': 0.1}), 'bbox_fill': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'}), 'crop_min_size': ('INT', {'min': 10, 'max': MAX_RESOLUTION, 'step': 1, 'default': 50}), 'drop_size': ('INT', {'min': 1, 'max': MAX_RESOLUTION, 'step': 1, 'default': 1}), 'dilation': ('INT', {'default': 0, 'min': -512, 'max': 512, 'step': 1}), 'face': bool_true_widget, 'mouth': bool_false_widget, 'left_eyebrow': bool_false_widget, 'left_eye': bool_false_widget, 'left_pupil': bool_false_widget, 'right_eyebrow': bool_false_widget, 'right_eye': bool_false_widget, 'right_pupil': bool_false_widget}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, image, crop_factor, bbox_fill, crop_min_size, drop_size, dilation, face, mouth, left_eyebrow, left_eye, left_pupil, right_eyebrow, right_eye, right_pupil): + result = core.mediapipe_facemesh_to_segs(image, crop_factor, bbox_fill, crop_min_size, drop_size, dilation, face, mouth, left_eyebrow, left_eye, left_pupil, right_eyebrow, right_eye, right_pupil) + return (result,) +``` \ No newline at end of file diff --git a/docs/MediaPipe_FaceMesh_Preprocessor_Provider_for_SEGS %2F%2FInspire.md b/docs/MediaPipe_FaceMesh_Preprocessor_Provider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..229a95f --- /dev/null +++ b/docs/MediaPipe_FaceMesh_Preprocessor_Provider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: MediaPipe_FaceMesh_Preprocessor_Provider_for_SEGS +- Category: InspirePack/SEGS/ControlNet +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点使用MediaPipe的FaceMesh模型来预处理图像,以便进行语义分割任务,通过检测面部并生成相应的掩码。它通过专注于面部特征来增强输入图像的分割,这对于需要详细面部分割的应用至关重要。 + +# Input types +## Required +- max_faces + - 此参数确定模型应在输入图像中检测的最大面孔数。它对于控制面部检测的粒度至关重要,并影响性能和准确性之间的平衡。 + - Comfy dtype: INT + - Python dtype: int +- min_confidence + - 面部检测的最小置信度阈值。它过滤掉低于此置信度水平的检测,这对于确保生成的分割掩码的质量很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- resolution_upscale_by + - 此参数通过缩放因子整输入图像的分辨率。放大图像可以提高检测准确性,但可能会增加计算需求。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- SEGS_PREPROCESSOR + - 输出是带有检测到的面部和分割掩码的预处理图像,作为下游语义分割任务的输入。 + - Comfy dtype: SEGS_PREPROCESSOR + - Python dtype: object + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MediaPipe_FaceMesh_Preprocessor_Provider_for_SEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'max_faces': ('INT', {'default': 10, 'min': 1, 'max': 50, 'step': 1}), 'min_confidence': ('FLOAT', {'default': 0.5, 'min': 0.01, 'max': 1.0, 'step': 0.01}), 'resolution_upscale_by': ('FLOAT', {'default': 1.0, 'min': 0.5, 'max': 100, 'step': 0.1})}} + RETURN_TYPES = ('SEGS_PREPROCESSOR',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/SEGS/ControlNet' + + def doit(self, max_faces, min_confidence, resolution_upscale_by): + obj = MediaPipe_FaceMesh_Preprocessor_wrapper(max_faces, min_confidence, upscale_factor=resolution_upscale_by) + return (obj,) +``` \ No newline at end of file diff --git a/docs/MergeLayers.md b/docs/MergeLayers.md new file mode 100644 index 0000000..650fcfa --- /dev/null +++ b/docs/MergeLayers.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: MergeLayers +- Category: ♾️Mixlab/Layer +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +MergeLayers节点旨在将多个层集成到基础图像上。它处理一系列图像和相应的层,将每个层应用到基础图像上,位置已指定,可进行可选缩放,并生成一个合成图像以及一个遮罩,该遮罩描绘了分层区域。 + +# Input types +## Required +- layers + - 'layers'参数是字典列表,每个字典代表要合并到基础图像上的一个层。每个字典包含一个层的图像、遮罩和位置属性,这些属性对于确定分层图像的最终组合至关重要。 + - Comfy dtype: COMBO[str] + - Python dtype: List[Dict[str, Union[str, torch.Tensor]]] +- images + - 'images'参数是要合并层的基础图像列表。每个图像都应该是张量格式,表示将作为分层过程画布的原始像素数据。 + - Comfy dtype: COMBO[torch.Tensor] + - Python dtype: List[torch.Tensor] + +# Output types +- IMAGE + - 'IMAGE'输出是一个张量,代表通过将输入层合并到基础图像上形成的最终合成图像。它包含了分层过程的视觉结果。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +- MASK + - 'MASK'输出是一个张量,代表在分层过程中应用的遮罩。它用于识别图像的分层区域,清晰地区分不同的层。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MergeLayers: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'layers': ('LAYER',), 'images': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE', 'MASK') + RETURN_NAMES = ('IMAGE', 'MASK') + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Layer' + INPUT_IS_LIST = True + + def run(self, layers, images): + bg_images = [] + masks = [] + for img in images: + for bg_image in img: + bg_image = tensor2pil(bg_image) + layers_new = sorted(layers, key=lambda x: x['z_index']) + (width, height) = bg_image.size + final_mask = Image.new('L', (width, height), 0) + for layer in layers_new: + image = layer['image'] + mask = layer['mask'] + if 'type' in layer and layer['type'] == 'base64' and (type(image) == str): + im = base64_to_image(image) + im = im.convert('RGB') + image = pil2tensor(im) + mask = base64_to_image(mask) + mask = mask.convert('L') + mask = pil2tensor(mask) + layer_image = tensor2pil(image) + layer_mask = tensor2pil(mask) + bg_image = merge_images(bg_image, layer_image, layer_mask, layer['x'], layer['y'], layer['width'], layer['height'], layer['scale_option']) + final_mask = merge_images(final_mask, layer_mask.convert('RGB'), layer_mask, layer['x'], layer['y'], layer['width'], layer['height'], layer['scale_option']) + final_mask = final_mask.convert('L') + final_mask = pil2tensor(final_mask) + bg_image = bg_image.convert('RGB') + bg_image = pil2tensor(bg_image) + bg_images.append(bg_image) + masks.append(final_mask) + bg_images = torch.cat(bg_images, dim=0) + masks = torch.cat(masks, dim=0) + return (bg_images, masks) +``` \ No newline at end of file diff --git a/docs/MeshGraphormerDepthMapPreprocessorProvider_for_SEGS %2F%2FInspire.md b/docs/MeshGraphormerDepthMapPreprocessorProvider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..1a6dd33 --- /dev/null +++ b/docs/MeshGraphormerDepthMapPreprocessorProvider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: MeshGraphormerDepthMapPreprocessorProvider_for_SEGS +- Category: InspirePack/SEGS/ControlNet +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点用于从图像生成深度图,这对于3D建模和分割任务至关重要。它利用先进算法从单张图像估计深度,提高了3D表示的质量。 + +# Input types +## Required +- image + - 输入图像对于生成深度图非常关键,它作为深度图生成的基础。节点处理图像以提取深度信息,这对于后续的3D建模和分割过程至关重要。 + - Comfy dtype: image + - Python dtype: PIL.Image or numpy.ndarray +## Optional +- mask + - 当提供掩码参数时,它允许对图像进行选择性处理。它使节点能够专注于图像中的特定感兴趣区域,从而提高生成的深度图的准确性和相关性。 + - Comfy dtype: mask + - Python dtype: numpy.ndarray + +# Output types +- SEGS_PREPROCESSOR + - 输出是一个包含生成的深度图的预处理器对象。这个深度图是用于各种3D和分割工作流中的关键中间产品,作为进一步处理的基础。 + - Comfy dtype: preprocessor + - Python dtype: object + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MeshGraphormerDepthMapPreprocessorProvider_for_SEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}} + RETURN_TYPES = ('SEGS_PREPROCESSOR',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/SEGS/ControlNet' + + def doit(self): + obj = MeshGraphormerDepthMapPreprocessorProvider_wrapper() + return (obj,) +``` \ No newline at end of file diff --git a/docs/MiDaS Depth Approximation.md b/docs/MiDaS Depth Approximation.md new file mode 100644 index 0000000..8076d66 --- /dev/null +++ b/docs/MiDaS Depth Approximation.md @@ -0,0 +1,115 @@ +# Documentation +- Class name: MiDaS_Depth_Approx +- Category: WAS Suite/Image/AI +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 `midas_approx` 负责使用 MiDaS 模型来估算图像的深度。它处理输入图像以预测深度图,这在需要理解场景空间结构的各种计算机视觉任务中非常有用。该方法设计灵活,允许用户指定是使用 CPU 还是 GPU,选择 MiDaS 模型的类型,并选择是否对特定应用反转深度。 + +# Input types +## Required +- image + - 输入图像参数对于节点的操作至关重要,因为它是节点处理以生成深度近似的主要数据。输入图像的质量和分辨率直接影响生成的深度图的准确性和细节。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- use_cpu + - 'use_cpu' 参数决定节点是否应该使用 CPU 进行处理。这对于没有 GPU 的系统或者用户希望为其他任务节省 GPU 资源时非常重要。 + - Comfy dtype: COMBO['false', 'true'] + - Python dtype: str +- midas_type + - 'midas_type' 参数允许用户选择不同的 MiDaS 模型架构。根据应用的具体需求,选择可以影响准确性和处理速度之间的平衡。 + - Comfy dtype: COMBO['DPT_Large', 'DPT_Hybrid'] + - Python dtype: str +- invert_depth + - 'invert_depth' 参数提供了一个选项来反转模型预测的深度值。在需要更高的深度值来表示更近的物体的场景中,这可能很有用,这与标准的深度图约定相反。 + - Comfy dtype: COMBO['false', 'true'] + - Python dtype: str +- midas_model + - 可选的 'midas_model' 参数允许使用预加载的 MiDaS 模型,避免了在节点本身内加载模型的需要。这可以简化处理流程,特别是当重复使用相同的模型时。 + - Comfy dtype: MIDAS_MODEL + - Python dtype: Tuple[torch.nn.Module, Callable] + +# Output types +- images + - 输出的 'images' 参数代表节点生成的深度近似图像。这些图像对于依赖于理解输入图像中场景空间维度的下游任务至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MiDaS_Depth_Approx: + + def __init__(self): + self.midas_dir = os.path.join(MODELS_DIR, 'midas') + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'use_cpu': (['false', 'true'],), 'midas_type': (['DPT_Large', 'DPT_Hybrid'],), 'invert_depth': (['false', 'true'],)}, 'optional': {'midas_model': ('MIDAS_MODEL',)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('images',) + FUNCTION = 'midas_approx' + CATEGORY = 'WAS Suite/Image/AI' + + def midas_approx(self, image, use_cpu, midas_type, invert_depth, midas_model=None): + global MIDAS_INSTALLED + if not MIDAS_INSTALLED: + self.install_midas() + import cv2 as cv + if midas_model: + midas = midas_model[0] + transform = midas_model[1] + device = torch.device('cuda') if torch.cuda.is_available() and use_cpu == 'false' else torch.device('cpu') + cstr(f'MiDaS is using device: {device}').msg.print() + midas.to(device).eval() + else: + if midas_model == 'DPT_Large': + model_name = 'dpt_large_384.pt' + elif midas_model == 'DPT_Hybrid': + model_name = 'dpt_hybrid_384.pt' + else: + model_name = 'dpt_large_384.pt' + model_path = os.path.join(self.midas_dir, 'checkpoints' + os.sep + model_name) + torch.hub.set_dir(self.midas_dir) + if os.path.exists(model_path): + cstr(f'Loading MiDaS Model from `{model_path}`').msg.print() + midas_type = model_path + else: + cstr('Downloading and loading MiDaS Model...').msg.print() + midas = torch.hub.load('intel-isl/MiDaS', midas_type, trust_repo=True) + cstr(f'MiDaS is using device: {device}').msg.print() + midas.to(device).eval() + midas_transforms = torch.hub.load('intel-isl/MiDaS', 'transforms') + transform = midas_transforms.dpt_transform + tensor_images = [] + for (i, img) in enumerate(image): + img = np.array(tensor2pil(img)) + img = cv.cvtColor(img, cv.COLOR_BGR2RGB) + input_batch = transform(img).to(device) + cstr(f'Approximating depth for image {i + 1}/{len(image)}').msg.print() + with torch.no_grad(): + prediction = midas(input_batch) + prediction = torch.nn.functional.interpolate(prediction.unsqueeze(1), size=img.shape[:2], mode='bicubic', align_corners=False).squeeze() + min_val = torch.min(prediction) + max_val = torch.max(prediction) + prediction = (prediction - min_val) / (max_val - min_val) + prediction = (prediction * 255).clamp(0, 255).round().cpu().numpy().astype(np.uint8) + depth = Image.fromarray(prediction) + if invert_depth == 'true': + depth = ImageOps.invert(depth) + tensor_images.append(pil2tensor(depth.convert('RGB'))) + tensor_images = torch.cat(tensor_images, dim=0) + if not midas_model: + del midas, device, midas_transforms + del midas, transform, img, input_batch, prediction + return (tensor_images,) + + def install_midas(self): + global MIDAS_INSTALLED + if 'timm' not in packages(): + install_package('timm') + MIDAS_INSTALLED = True +``` \ No newline at end of file diff --git a/docs/MiDaS Mask Image.md b/docs/MiDaS Mask Image.md new file mode 100644 index 0000000..9144e11 --- /dev/null +++ b/docs/MiDaS Mask Image.md @@ -0,0 +1,159 @@ +# Documentation +- Class name: MiDaS_Background_Foreground_Removal +- Category: WAS Suite/Image/AI +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +该节点使用MiDaS模型从图像中估计深度,并根据用户输入移除背景或前景,增强图像的视觉清晰度和焦点。 + +# Input types +## Required +- image + - 源图像,从中估计深度并移除背景或前景。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- midas_model + - 指定用于深度估计的MiDaS模型的大小,较大的模型通常能提供更准确的结果,但需要更多的计算资源。 + - Comfy dtype: COMBO[ ['DPT_Large', 'DPT_Hybrid', 'DPT_Small' ]] + - Python dtype: str +- remove + - 指示应从图像中移除背景还是前景,影响输出的构图。 + - Comfy dtype: COMBO[ ['background', 'foreground' ]] + - Python dtype: str +## Optional +- use_cpu + - 决定是否使用CPU进行处理。卸载到GPU通常更快,但需要兼容的硬件。 + - Comfy dtype: COMBO[ ['false', 'true' ]] + - Python dtype: str +- threshold + - 对深度图应用阈值,可以细化移除元素与图像其余部分的分离。 + - Comfy dtype: COMBO[ ['false', 'true' ]] + - Python dtype: str +- threshold_low + - 设置深度值阈值范围的下限,影响分割的精度。 + - Comfy dtype: FLOAT + - Python dtype: float +- threshold_mid + - 定义阈值范围的中点,进一步调整保留和移除的图像部分之间的过渡。 + - Comfy dtype: FLOAT + - Python dtype: float +- threshold_high + - 建立阈值范围的上限,这可以影响移除过程中图像最深处的处理方式。 + - Comfy dtype: FLOAT + - Python dtype: float +- smoothing + - 控制应用于深度图的平滑程度,这有助于减少最终输出中的噪声和伪影。 + - Comfy dtype: FLOAT + - Python dtype: float +- background_red + - 设置用于填充移除区域的背景颜色的红色分量,影响结果图像的视觉外观。 + - Comfy dtype: INT + - Python dtype: int +- background_green + - 确定背景颜色的绿色分量,有助于构成移除元素区域的整体色彩方案。 + - Comfy dtype: INT + - Python dtype: int +- background_blue + - 指定背景颜色的蓝色分量,用于在编辑图像中实现期望的色彩平衡。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result_image + - 处理后的图像,已移除指定的背景或前景元素,可供进一步使用或分析。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- depth_map + - 从输入图像派生出的深度图,视觉上表示场景中的估计距离,并在内部用于移除过程。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MiDaS_Background_Foreground_Removal: + + def __init__(self): + self.midas_dir = os.path.join(MODELS_DIR, 'midas') + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'use_cpu': (['false', 'true'],), 'midas_model': (['DPT_Large', 'DPT_Hybrid', 'DPT_Small'],), 'remove': (['background', 'foregroud'],), 'threshold': (['false', 'true'],), 'threshold_low': ('FLOAT', {'default': 10, 'min': 0, 'max': 255, 'step': 1}), 'threshold_mid': ('FLOAT', {'default': 200, 'min': 0, 'max': 255, 'step': 1}), 'threshold_high': ('FLOAT', {'default': 210, 'min': 0, 'max': 255, 'step': 1}), 'smoothing': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 16.0, 'step': 0.01}), 'background_red': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1}), 'background_green': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1}), 'background_blue': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1})}} + RETURN_TYPES = ('IMAGE', 'IMAGE') + FUNCTION = 'midas_remove' + CATEGORY = 'WAS Suite/Image/AI' + + def midas_remove(self, image, midas_model, use_cpu='false', remove='background', threshold='false', threshold_low=0, threshold_mid=127, threshold_high=255, smoothing=0.25, background_red=0, background_green=0, background_blue=0): + global MIDAS_INSTALLED + if not MIDAS_INSTALLED: + self.install_midas() + import cv2 as cv + i = 255.0 * image.cpu().numpy().squeeze() + img = i + img_original = tensor2pil(image).convert('RGB') + cstr('Downloading and loading MiDaS Model...').msg.print() + torch.hub.set_dir(self.midas_dir) + midas = torch.hub.load('intel-isl/MiDaS', midas_model, trust_repo=True) + device = torch.device('cuda') if torch.cuda.is_available() and use_cpu == 'false' else torch.device('cpu') + cstr(f'MiDaS is using device: {device}').msg.print() + midas.to(device).eval() + midas_transforms = torch.hub.load('intel-isl/MiDaS', 'transforms') + if midas_model == 'DPT_Large' or midas_model == 'DPT_Hybrid': + transform = midas_transforms.dpt_transform + else: + transform = midas_transforms.small_transform + img = cv.cvtColor(img, cv.COLOR_BGR2RGB) + input_batch = transform(img).to(device) + cstr('Approximating depth from image.').msg.print() + with torch.no_grad(): + prediction = midas(input_batch) + prediction = torch.nn.functional.interpolate(prediction.unsqueeze(1), size=img.shape[:2], mode='bicubic', align_corners=False).squeeze() + if remove == 'foreground': + depth = 255 - prediction.cpu().numpy().astype(np.uint8) + depth = depth.astype(np.float32) + else: + depth = prediction.cpu().numpy().astype(np.float32) + depth = depth * 255 / np.max(depth) / 255 + depth = Image.fromarray(np.uint8(depth * 255)) + if threshold == 'true': + levels = self.AdjustLevels(threshold_low, threshold_mid, threshold_high) + depth = levels.adjust(depth.convert('RGB')).convert('L') + if smoothing > 0: + depth = depth.filter(ImageFilter.GaussianBlur(radius=smoothing)) + depth = depth.resize(img_original.size).convert('L') + background_red = int(background_red) if isinstance(background_red, (int, float)) else 0 + background_green = int(background_green) if isinstance(background_green, (int, float)) else 0 + background_blue = int(background_blue) if isinstance(background_blue, (int, float)) else 0 + background_color = (background_red, background_green, background_blue) + background = Image.new(mode='RGB', size=img_original.size, color=background_color) + result_img = Image.composite(img_original, background, depth) + del midas, device, midas_transforms + del transform, img, img_original, input_batch, prediction + return (pil2tensor(result_img), pil2tensor(depth.convert('RGB'))) + + class AdjustLevels: + + def __init__(self, min_level, mid_level, max_level): + self.min_level = min_level + self.mid_level = mid_level + self.max_level = max_level + + def adjust(self, im): + im_arr = np.array(im) + im_arr[im_arr < self.min_level] = self.min_level + im_arr = (im_arr - self.min_level) * (255 / (self.max_level - self.min_level)) + im_arr[im_arr < 0] = 0 + im_arr[im_arr > 255] = 255 + im_arr = im_arr.astype(np.uint8) + im = Image.fromarray(im_arr) + im = ImageOps.autocontrast(im, cutoff=self.max_level) + return im + + def install_midas(self): + global MIDAS_INSTALLED + if 'timm' not in packages(): + install_package('timm') + MIDAS_INSTALLED = True +``` \ No newline at end of file diff --git a/docs/MiDaS Model Loader.md b/docs/MiDaS Model Loader.md new file mode 100644 index 0000000..502ec0f --- /dev/null +++ b/docs/MiDaS Model Loader.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: MiDaS_Model_Loader +- Category: WAS Suite/Loaders +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +MiDaS_Model_Loader节点负责加载和准备MiDaS模型以供部署。它确保必要的依赖项已安装,并处理下载和加载指定的MiDaS模型变体。 + +# Input types +## Required +- midas_model + - 'midas_model'参数指定要加载的MiDaS模型类型。它对于确定用于深度估计任务的预训练模型权重和配置至关重要。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- midas_model + - 'midas_model'输出提供了一个包含已加载的MiDaS模型及其相关转换函数的元组。此输出对于后续处理和分析深度信息至关重要。 + - Comfy dtype: Tuple[torch.nn.Module, Callable] + - Python dtype: Tuple[torch.nn.Module, Callable[[torch.Tensor], torch.Tensor]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MiDaS_Model_Loader: + + def __init__(self): + self.midas_dir = os.path.join(MODELS_DIR, 'midas') + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'midas_model': (['DPT_Large', 'DPT_Hybrid'],)}} + RETURN_TYPES = ('MIDAS_MODEL',) + RETURN_NAMES = ('midas_model',) + FUNCTION = 'load_midas_model' + CATEGORY = 'WAS Suite/Loaders' + + def load_midas_model(self, midas_model): + global MIDAS_INSTALLED + if not MIDAS_INSTALLED: + self.install_midas() + if midas_model == 'DPT_Large': + model_name = 'dpt_large_384.pt' + elif midas_model == 'DPT_Hybrid': + model_name = 'dpt_hybrid_384.pt' + else: + model_name = 'dpt_large_384.pt' + model_path = os.path.join(self.midas_dir, 'checkpoints' + os.sep + model_name) + torch.hub.set_dir(self.midas_dir) + if os.path.exists(model_path): + cstr(f'Loading MiDaS Model from `{model_path}`').msg.print() + midas_type = model_path + else: + cstr('Downloading and loading MiDaS Model...').msg.print() + midas = torch.hub.load('intel-isl/MiDaS', midas_model, trust_repo=True) + device = torch.device('cpu') + cstr(f'MiDaS is using passive device `{device}` until in use.').msg.print() + midas.to(device) + midas_transforms = torch.hub.load('intel-isl/MiDaS', 'transforms') + transform = midas_transforms.dpt_transform + return ((midas, transform),) + + def install_midas(self): + global MIDAS_INSTALLED + if 'timm' not in packages(): + install_package('timm') + MIDAS_INSTALLED = True +``` \ No newline at end of file diff --git a/docs/MiDaS_DepthMap_Preprocessor_Provider_for_SEGS %2F%2FInspire.md b/docs/MiDaS_DepthMap_Preprocessor_Provider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..5f3839c --- /dev/null +++ b/docs/MiDaS_DepthMap_Preprocessor_Provider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: MiDaS_DepthMap_Preprocessor_Provider_for_SEGS +- Category: InspirePack/SEGS/ControlNet +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点通过使用MiDaS模型生成语义分割任务的深度图,提高分割输出的质量。 + +# Input types +## Required +- a + - 参数'a'是影响深度估计过程的关键输入,影响深度图的整体准确性和细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- bg_threshold + - ‘bg_threshold’参数对于在深度图中区分前景和背景至关重要,从而提高了分割精度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- SEGS_PREPROCESSOR + - 输出提供一个预处理过的深度图,作为分割模型的输入,显著提升了分割结果的质量。 + - Comfy dtype: NODE + - Python dtype: MiDaS_DepthMapPreprocessor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MiDaS_DepthMap_Preprocessor_Provider_for_SEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'a': ('FLOAT', {'default': np.pi * 2.0, 'min': 0.0, 'max': np.pi * 5.0, 'step': 0.05}), 'bg_threshold': ('FLOAT', {'default': 0.1, 'min': 0, 'max': 1, 'step': 0.05})}} + RETURN_TYPES = ('SEGS_PREPROCESSOR',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/SEGS/ControlNet' + + def doit(self, a, bg_threshold): + obj = MiDaS_DepthMap_Preprocessor_wrapper(a, bg_threshold) + return (obj,) +``` \ No newline at end of file diff --git a/docs/MicrosoftSpeech_TTS.md b/docs/MicrosoftSpeech_TTS.md new file mode 100644 index 0000000..fa6783d --- /dev/null +++ b/docs/MicrosoftSpeech_TTS.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: Text2AudioEdgeTts +- Category: 😺dzNodes +- Output node: True +- Repo Ref: https://github.com/chflame163/ComfyUI_MSSpeech_TTS + +Text2AudioEdgeTts节点旨在使用edge_tts库将文本转换为音频文件。它接受文本、一个声音参数以及一个可选的速率调整,以生成可以用于各种应用(如语音助手或有声读物)的音频文件。该节点的主要目标是提供一个既高效又可定制的文本到语音的转换过程。 + +# Input types +## Required +- voice + - 声音参数对于确定生成音频的声音特征至关重要。它从edge_tts库中预定义的声音集中选择特定的声音,这显著影响输出的质量和音调。 + - Comfy dtype: STRING + - Python dtype: str +- text + - 文本参数是要转换为音频的输入文本。它是节点处理以生成所需音频输出的核心内容。文本的质量直接影响转换的有效性。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- rate + - 速率参数允许调整语速。它可以设置为负值以减慢语速,或正值以加快语速。这个特性对于微调音频输出以满足特定要求或偏好很重要。 + - Comfy dtype: INT + - Python dtype: int +- filename_prefix + - 文件名前缀用于为输出音频文件创建唯一标识符。在组织和管理多个音频文件时特别有用,因为它确保每个文件都有一个独特且可识别的名称。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- MP3 file + - Text2AudioEdgeTts节点的输出是一个MP3文件,其中包含从输入文本生成的音频。这个文件很重要,因为它代表了节点文本到语音转换过程的成果,并且可以用于各种下游应用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Text2AudioEdgeTts: + + def __init__(self): + self.output_dir = os.path.join(folder_paths.get_output_directory(), 'audio') + if not os.path.exists(self.output_dir): + os.makedirs(self.output_dir) + + @classmethod + def INPUT_TYPES(cls): + VOICES = list(voice_dict.keys()) + return {'required': {'voice': (VOICES,), 'rate': ('INT', {'default': 0, 'min': -200, 'max': 200}), 'filename_prefix': ('STRING', {'default': 'comfyUI'}), 'text': ('STRING', {'multiline': True})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('MP3 file: String',) + FUNCTION = 'text_2_audio' + OUTPUT_NODE = True + CATEGORY = '😺dzNodes' + + def text_2_audio(self, voice, filename_prefix, text, rate): + voice_name = voice_dict[voice] + (full_output_folder, filename, counter, subfolder, filename_prefix) = folder_paths.get_save_image_path(filename_prefix, self.output_dir) + _datetime = datetime.datetime.now().strftime('%Y%m%d') + _datetime = _datetime + datetime.datetime.now().strftime('%H%M%S%f') + file = f'{filename}_{_datetime}_{voice_name}.mp3' + audio_path = os.path.join(full_output_folder, file) + _rate = str(rate) + '%' if rate < 0 else '+' + str(rate) + '%' + print(f"# 😺dzNodes: MSSpeech TTS: Generating voice files, voice=‘{voice_name}’, rate={rate}, audiofile_path='{audio_path}, 'text='{text}'") + asyncio.run(gen_tts(text, voice_name, _rate, audio_path)) + return {'ui': {'text': 'Audio file:' + os.path.join(full_output_folder, file), 'audios': [{'filename': file, 'type': 'output', 'subfolder': 'audio'}]}, 'result': (audio_path,)} +``` \ No newline at end of file diff --git a/docs/Mikey Sampler Base Only Advanced.md b/docs/Mikey Sampler Base Only Advanced.md new file mode 100644 index 0000000..3964c0a --- /dev/null +++ b/docs/Mikey Sampler Base Only Advanced.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: MikeySamplerBaseOnlyAdvanced +- Category: Mikey/Sampling +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +MikeySamplerBaseOnlyAdvanced 节点旨在为生成模型执行高级采样技术。它结合了图像缩放、模型放大和潜在空间操作等多种组件,以产生高质量的样本。该节点的功能集中在生成经过放大和去噪的样本上,利用复杂的算法来增强输出。 + +# Input types +## Required +- seed + - 种子参数对于采样过程的可重复性至关重要,确保在不同运行中生成的样本是一致的。它在确定随机数生成器的初始状态中起着重要作用,进而影响整个采样过程。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- upscale_model + - upscale_model 参数决定了用于图像放大的方法或模型。它可以是一个代表缩放方法的字符串,或者是用于更复杂模型的 PyTorch 模块。这个参数在采样过程中显著影响放大图像的质量和分辨率。 + - Comfy dtype: COMBO[str, torch.nn.Module] + - Python dtype: Union[str, torch.nn.Module] + +# Output types +- latent + - latent 参数代表放大图像的编码版本,是采样过程的关键输出。它以压缩形式捕获图像的底层结构,允许在潜在空间中进行进一步的操作或分析。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MikeySamplerBaseOnlyAdvanced: + + @classmethod + def INPUT_TYPES(s): + s.image_scaler = ImageScaleBy() + s.upscale_models = folder_paths.get_filename_list('upscale_models') + s.all_upscale_models = s.upscale_models + s.image_scaler.upscale_methods + try: + default_model = 'lanczos' + um = (s.all_upscale_models, {'default': default_model}) + except: + um = (folder_paths.get_filename_list('upscale_models'),) + return {'required': {'base_model': ('MODEL',), 'positive_cond_base': ('CONDITIONING',), 'negative_cond_base': ('CONDITIONING',), 'samples': ('LATENT',), 'vae': ('VAE',), 'add_noise': (['enable', 'disable'], {'default': 'enable'}), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'steps': ('INT', {'default': 31, 'min': 1, 'max': 1000}), 'smooth_step': ('INT', {'default': 0, 'min': -1, 'max': 100}), 'cfg_1': ('FLOAT', {'default': 5.0, 'min': 0.1, 'max': 100.0, 'step': 0.1}), 'cfg_2': ('FLOAT', {'default': 9.5, 'min': 0.1, 'max': 100.0, 'step': 0.1}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS, {'default': 'dpmpp_3m_sde_gpu'}), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS, {'default': 'exponential'}), 'upscale_model': um, 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'upscale_by': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.1}), 'hires_denoise': ('FLOAT', {'default': 0.4, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'hires_steps': ('INT', {'default': 31, 'min': 1, 'max': 1000})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'run' + CATEGORY = 'Mikey/Sampling' + + def run(self, seed, base_model, positive_cond_base, negative_cond_base, samples, vae, add_noise, denoise, steps, cfg_1, cfg_2, sampler_name, scheduler, upscale_model, upscale_by, hires_denoise, hires_steps, smooth_step): + image_scaler = ImageScale() + vaeencoder = VAEEncode() + vaedecoder = VAEDecode() + uml = UpscaleModelLoader() + if upscale_model in image_scaler.upscale_methods: + upscale_model = upscale_model + else: + upscale_model = uml.load_model(upscale_model)[0] + iuwm = ImageUpscaleWithModel() + start_step = int(steps - steps * denoise) + if start_step > steps // 2: + last_step = steps - 1 + elif start_step % 2 == 0: + last_step = steps // 2 - 1 + else: + last_step = steps // 2 + sample1 = common_ksampler(base_model, seed, steps, cfg_1, sampler_name, scheduler, positive_cond_base, negative_cond_base, samples, start_step=start_step, last_step=last_step, force_full_denoise=False)[0] + start_step = last_step + 1 + total_steps = steps + smooth_step + sample2 = common_ksampler(base_model, seed + 1, total_steps, cfg_2, sampler_name, scheduler, positive_cond_base, negative_cond_base, sample1, disable_noise=True, start_step=start_step, force_full_denoise=True) + if upscale_by == 0: + return sample2 + else: + sample2 = sample2[0] + pixels = vaedecoder.decode(vae, sample2)[0] + (org_width, org_height) = (pixels.shape[2], pixels.shape[1]) + if isinstance(upscale_model, str): + img = self.image_scaler.upscale(pixels, upscale_model, upscale_by)[0] + else: + img = iuwm.upscale(upscale_model, image=pixels)[0] + (upscaled_width, upscaled_height) = (int(org_width * upscale_by // 8 * 8), int(org_height * upscale_by // 8 * 8)) + img = image_scaler.upscale(img, 'nearest-exact', upscaled_width, upscaled_height, 'center')[0] + if hires_denoise == 0: + return (vaeencoder.encode(vae, img)[0],) + latent = vaeencoder.encode(vae, img)[0] + start_step = int(hires_steps - hires_steps * hires_denoise) + out = common_ksampler(base_model, seed, hires_steps, cfg_2, sampler_name, scheduler, positive_cond_base, negative_cond_base, latent, start_step=start_step, force_full_denoise=True) + return out +``` \ No newline at end of file diff --git a/docs/Mikey Sampler Base Only.md b/docs/Mikey Sampler Base Only.md new file mode 100644 index 0000000..85862c8 --- /dev/null +++ b/docs/Mikey Sampler Base Only.md @@ -0,0 +1,105 @@ +# Documentation +- Class name: MikeySamplerBaseOnly +- Category: Mikey/Sampling +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +MikeySamplerBaseOnly节点旨在对基础模型执行高级采样操作,利用各种条件和VAE模型生成潜在表示。它能够根据图像复杂性调整采样过程,并将结果进行上采样以提高分辨率和细节。 + +# Input types +## Required +- base_model + - 基础模型参数对节点的操作至关重要,因为它定义了用于采样的基础模型。它直接影响生成的潜在表示的质量和特性。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- samples + - 样本参数决定了节点要生成的潜在表示的数量。它的值对输出的多样性和数量有显著影响。 + - Comfy dtype: LATENT + - Python dtype: int +- positive_cond_base + - 正向条件是输入的一个关键部分,它为采样过程提供指导,确保生成的样本符合某些期望的属性。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative_cond_base + - 负向条件通过指定生成样本中要避免的不希望的特性,来约束采样过程。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- vae + - VAE参数对节点的功能至关重要,因为它使得潜在表示的编码和解码成为可能,这是采样过程中的关键步骤。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- model_name + - 模型名称参数指定用于提高生成样本分辨率的上采样模型。它在最终输出质量中起着关键作用。 + - Comfy dtype: folder_paths.get_filename_list('upscale_models') + - Python dtype: str +## Optional +- seed + - 种子参数用于初始化随机数生成器,确保采样过程的可重复性。 + - Comfy dtype: INT + - Python dtype: int +- upscale_by + - upscale_by参数决定了生成样本的缩放因子。它是控制输出分辨率的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- hires_strength + - hires_strength参数调整高分辨率细节增强的强度,影响上采样输出的清晰度和锐度。 + - Comfy dtype: FLOAT + - Python dtype: float +- smooth_step + - smooth_step参数控制采样过程不同阶段之间的过渡平滑度,影响生成样本的整体一致性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- latent_representation + - 输出的潜在表示是节点操作的关键结果,以压缩形式封装了生成的样本,可以进一步处理或分析。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MikeySamplerBaseOnly: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_model': ('MODEL',), 'samples': ('LATENT',), 'positive_cond_base': ('CONDITIONING',), 'negative_cond_base': ('CONDITIONING',), 'vae': ('VAE',), 'model_name': (folder_paths.get_filename_list('upscale_models'),), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'upscale_by': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.1}), 'hires_strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 0.1}), 'smooth_step': ('INT', {'default': 0, 'min': -1, 'max': 100})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'run' + CATEGORY = 'Mikey/Sampling' + + def adjust_start_step(self, image_complexity, hires_strength=1.0): + image_complexity /= 24 + if image_complexity > 1: + image_complexity = 1 + image_complexity = min([0.55, image_complexity]) * hires_strength + return min([31, 31 - int(round(image_complexity * 31, 0))]) + + def run(self, seed, base_model, vae, samples, positive_cond_base, negative_cond_base, model_name, upscale_by=1.0, hires_strength=1.0, upscale_method='normal', smooth_step=0): + image_scaler = ImageScale() + vaeencoder = VAEEncode() + vaedecoder = VAEDecode() + uml = UpscaleModelLoader() + upscale_model = uml.load_model(model_name)[0] + iuwm = ImageUpscaleWithModel() + sample1 = common_ksampler(base_model, seed, 30, 5, 'dpmpp_3m_sde_gpu', 'exponential', positive_cond_base, negative_cond_base, samples, start_step=0, last_step=14, force_full_denoise=False)[0] + sample2 = common_ksampler(base_model, seed + 1, 31 + smooth_step, 9.5, 'dpmpp_3m_sde_gpu', 'exponential', positive_cond_base, negative_cond_base, sample1, disable_noise=True, start_step=15, force_full_denoise=True) + if upscale_by == 0: + return sample2 + else: + sample2 = sample2[0] + pixels = vaedecoder.decode(vae, sample2)[0] + (org_width, org_height) = (pixels.shape[2], pixels.shape[1]) + img = iuwm.upscale(upscale_model, image=pixels)[0] + (upscaled_width, upscaled_height) = (int(org_width * upscale_by // 8 * 8), int(org_height * upscale_by // 8 * 8)) + img = image_scaler.upscale(img, 'nearest-exact', upscaled_width, upscaled_height, 'center')[0] + if hires_strength == 0: + return (vaeencoder.encode(vae, img)[0],) + image_complexity = calculate_image_complexity(img) + start_step = self.adjust_start_step(image_complexity, hires_strength) + latent = vaeencoder.encode(vae, img)[0] + out = common_ksampler(base_model, seed, 31, 9.5, 'dpmpp_3m_sde_gpu', 'exponential', positive_cond_base, negative_cond_base, latent, start_step=start_step, force_full_denoise=True) + return out +``` \ No newline at end of file diff --git a/docs/Mikey Sampler Tiled Base Only.md b/docs/Mikey Sampler Tiled Base Only.md new file mode 100644 index 0000000..778a743 --- /dev/null +++ b/docs/Mikey Sampler Tiled Base Only.md @@ -0,0 +1,95 @@ +# Documentation +- Class name: MikeySamplerTiledBaseOnly +- Category: Sampling +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +MikeySamplerTiledBaseOnly 节点旨在通过两阶段采样过程从基础模型生成高质量的图像。它利用了多种技术,如潜在空间采样、去噪和上采样,以产生细节丰富和精细的图像。该节点的功能集中在通过模型基础和算法方法的复杂组合来增强图像质量和分辨率。 + +# Input types +## Required +- base_model + - base_model 参数对节点的操作至关重要,因为它定义了图像生成过程开始的基础模型。它是采样和上采样序列的起点,对最终输出的质量和特性有重大影响。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- samples + - samples 参数对节点至关重要,因为它表示从潜在空间中采样图像的点。它在决定生成图像的多样性和随机性方面起着关键作用,影响采样过程的总体结果。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- positive_cond_base + - positive_cond_base 参数是一个条件输入,对采样过程产生积极影响。它有助于引导图像生成朝向期望的特性,增强节点产生目标输出的能力。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative_cond_base + - negative_cond_base 参数作为一个条件输入,对采样过程产生负面影响。它有助于从生成的图像中排除不需要的特征,完善节点的输出以符合指定的要求。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- vae + - vae 参数对节点至关重要,因为它表示用于将潜在表示解码成像素空间的变分自编码器。在将采样数据转换为视觉格式的过程中,它是一个关键组件。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- model_name + - model_name 参数指定用于图像上采样过程的上采样模型。它是选择模型架构及其相应能力的决定性因素,直接影响上采样质量。 + - Comfy dtype: folder_paths.get_filename_list('upscale_models') + - Python dtype: str +## Optional +- seed + - seed 参数用于初始化随机数生成器,确保采样过程的可重复性。当需要在多次执行中获得一致的结果时,这是一个重要方面。 + - Comfy dtype: INT + - Python dtype: int +- upscale_by + - upscale_by 参数确定原始图像尺寸要增加的倍数。它直接影响上采样图像的分辨率和细节,在最终输出的外观中起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- tiler_denoise + - tiler_denoise 参数控制平铺过程中应用的去噪水平。它是一个重要的调整参数,可以通过减少噪声伪影来提高上采样图像的视觉质量。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- image + - MikeySamplerTiledBaseOnly 节点的 image 输出代表最终上采样和精细处理后的图像。它是节点处理的结果,体现了节点旨在产生的高分辨率和详细视觉输出。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MikeySamplerTiledBaseOnly(MikeySamplerTiled): + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_model': ('MODEL',), 'samples': ('LATENT',), 'positive_cond_base': ('CONDITIONING',), 'negative_cond_base': ('CONDITIONING',), 'vae': ('VAE',), 'model_name': (folder_paths.get_filename_list('upscale_models'),), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'upscale_by': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 10.0, 'step': 0.1}), 'tiler_denoise': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.05})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + + def phase_one(self, base_model, samples, positive_cond_base, negative_cond_base, upscale_by, model_name, seed, vae): + image_scaler = ImageScale() + vaedecoder = VAEDecode() + uml = UpscaleModelLoader() + upscale_model = uml.load_model(model_name)[0] + iuwm = ImageUpscaleWithModel() + sample1 = common_ksampler(base_model, seed, 30, 5, 'dpmpp_3m_sde_gpu', 'exponential', positive_cond_base, negative_cond_base, samples, start_step=0, last_step=14, force_full_denoise=False)[0] + sample2 = common_ksampler(base_model, seed + 1, 32, 9.5, 'dpmpp_3m_sde_gpu', 'exponential', positive_cond_base, negative_cond_base, sample1, disable_noise=True, start_step=15, force_full_denoise=True)[0] + pixels = vaedecoder.decode(vae, sample2)[0] + (org_width, org_height) = (pixels.shape[2], pixels.shape[1]) + img = iuwm.upscale(upscale_model, image=pixels)[0] + (upscaled_width, upscaled_height) = (int(org_width * upscale_by // 8 * 8), int(org_height * upscale_by // 8 * 8)) + img = image_scaler.upscale(img, 'nearest-exact', upscaled_width, upscaled_height, 'center')[0] + return (img, upscaled_width, upscaled_height) + + def adjust_start_step(self, image_complexity, hires_strength=1.0): + image_complexity /= 24 + if image_complexity > 1: + image_complexity = 1 + image_complexity = min([0.55, image_complexity]) * hires_strength + return min([32, 32 - int(round(image_complexity * 32, 0))]) + + def run(self, seed, base_model, vae, samples, positive_cond_base, negative_cond_base, model_name, upscale_by=1.0, tiler_denoise=0.25, upscale_method='normal'): + (img, upscaled_width, upscaled_height) = self.phase_one(base_model, samples, positive_cond_base, negative_cond_base, upscale_by, model_name, seed, vae) + img = tensor2pil(img) + tiled_image = run_tiler(img, base_model, vae, seed, positive_cond_base, negative_cond_base, tiler_denoise) + return (tiled_image,) +``` \ No newline at end of file diff --git a/docs/Mikey Sampler Tiled.md b/docs/Mikey Sampler Tiled.md new file mode 100644 index 0000000..1c9c4be --- /dev/null +++ b/docs/Mikey Sampler Tiled.md @@ -0,0 +1,113 @@ +# Documentation +- Class name: MikeySamplerTiled +- Category: Mikey/Sampling +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +MikeySamplerTiled节点旨在执行一个复杂的采样过程,包括生成和细化潜在样本,然后对图像进行放大和平铺。它利用各种模型和条件来产生高质量、放大的图像,这些图像既详细又连贯。 + +# Input types +## Required +- base_model + - 基础模型对于初始采样过程至关重要,为生成的图像提供基础结构。其选择显著影响最终输出的风格和质量。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- refiner_model + - 细化模型用于通过应用进一步的细化步骤来提高采样图像的质量。它在实现放大图像的更高细节和清晰度方面起着关键作用。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- samples + - 样本表示用作图像生成过程输入的潜在空间向量。这些样本的多样性和质量直接影响生成图像的多样性和保真度。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- vae + - VAE(变分自编码器)对于将潜在样本解码到像素空间至关重要,将其转换为可以进一步处理和放大的有形图像。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- positive_cond_base + - 正向调节在采样期间为基模型提供指导,确保生成的图像与所需的特征和属性一致。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- negative_cond_base + - 负向调节用于抑制生成图像中的某些特征或属性,允许对最终图像的外观进行更严格的控制。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- positive_cond_refiner + - 细化模型的正向调节指导细化过程,专注于增强放大图像中的特定特征和细节。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- negative_cond_refiner + - 细化模型的负向调节有助于在细化过程中抑制不需要的元素,保持所需图像方面的完整性。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- model_name + - 模型名称用于识别用于图像放大过程的特定放大模型。它是确定缩放技术及生成图像质量的关键因素。 + - Comfy dtype: folder_paths.get_filename_list('upscale_models') + - Python dtype: str +## Optional +- seed + - 种子为采样过程提供了一定程度的可重复性,确保如果使用相同的种子值重复过程,可以得到相同的结果。 + - Comfy dtype: INT + - Python dtype: int +- upscale_by + - 放大因子决定了应用于原始图像的放大程度。它直接影响放大图像的分辨率和细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- tiler_denoise + - 去噪级别是一个控制平铺过程中应用的降噪量参数。它影响平铺图像的清晰度和平滑度。 + - Comfy dtype: FLOAT + - Python dtype: float +- tiler_model + - 平铺模型指定用于平铺操作的模型。它可以是基础模型或细化模型,影响平铺图像的最终外观。 + - Comfy dtype: COMBO['base', 'refiner'] + - Python dtype: str + +# Output types +- tiled_image + - 平铺图像是节点的主要输出,代表输入图像的放大和平铺版本。它展示了节点产生详细和结构化最终图像的能力。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- upscaled_image + - 放大图像是额外的输出,提供了非平铺版本的放大图像。它对于比较和进一步处理非常有用。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MikeySamplerTiled: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_model': ('MODEL',), 'refiner_model': ('MODEL',), 'samples': ('LATENT',), 'vae': ('VAE',), 'positive_cond_base': ('CONDITIONING',), 'negative_cond_base': ('CONDITIONING',), 'positive_cond_refiner': ('CONDITIONING',), 'negative_cond_refiner': ('CONDITIONING',), 'model_name': (folder_paths.get_filename_list('upscale_models'),), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'upscale_by': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 10.0, 'step': 0.1}), 'tiler_denoise': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'tiler_model': (['base', 'refiner'], {'default': 'base'})}} + RETURN_TYPES = ('IMAGE', 'IMAGE') + RETURN_NAMES = ('tiled_image', 'upscaled_image') + FUNCTION = 'run' + CATEGORY = 'Mikey/Sampling' + + def phase_one(self, base_model, refiner_model, samples, positive_cond_base, negative_cond_base, positive_cond_refiner, negative_cond_refiner, upscale_by, model_name, seed, vae): + image_scaler = ImageScale() + vaedecoder = VAEDecode() + uml = UpscaleModelLoader() + upscale_model = uml.load_model(model_name)[0] + iuwm = ImageUpscaleWithModel() + sample1 = common_ksampler(base_model, seed, 30, 6.5, 'dpmpp_3m_sde_gpu', 'exponential', positive_cond_base, negative_cond_base, samples, start_step=0, last_step=14, force_full_denoise=False)[0] + sample2 = common_ksampler(refiner_model, seed, 32, 3.5, 'dpmpp_3m_sde_gpu', 'exponential', positive_cond_refiner, negative_cond_refiner, sample1, disable_noise=True, start_step=15, force_full_denoise=True)[0] + pixels = vaedecoder.decode(vae, sample2)[0] + (org_width, org_height) = (pixels.shape[2], pixels.shape[1]) + img = iuwm.upscale(upscale_model, image=pixels)[0] + (upscaled_width, upscaled_height) = (int(org_width * upscale_by // 8 * 8), int(org_height * upscale_by // 8 * 8)) + img = image_scaler.upscale(img, 'nearest-exact', upscaled_width, upscaled_height, 'center')[0] + return (img, upscaled_width, upscaled_height) + + def run(self, seed, base_model, refiner_model, vae, samples, positive_cond_base, negative_cond_base, positive_cond_refiner, negative_cond_refiner, model_name, upscale_by=1.0, tiler_denoise=0.25, upscale_method='normal', tiler_model='base'): + (img, upscaled_width, upscaled_height) = self.phase_one(base_model, refiner_model, samples, positive_cond_base, negative_cond_base, positive_cond_refiner, negative_cond_refiner, upscale_by, model_name, seed, vae) + img = tensor2pil(img) + if tiler_model == 'base': + tiled_image = run_tiler(img, base_model, vae, seed, positive_cond_base, negative_cond_base, tiler_denoise) + else: + tiled_image = run_tiler(img, refiner_model, vae, seed, positive_cond_refiner, negative_cond_refiner, tiler_denoise) + return (tiled_image, img) +``` \ No newline at end of file diff --git a/docs/Mikey Sampler.md b/docs/Mikey Sampler.md new file mode 100644 index 0000000..7ed0dd8 --- /dev/null +++ b/docs/Mikey Sampler.md @@ -0,0 +1,89 @@ +# Documentation +- Class name: MikeySampler +- Category: Mikey/Sampling +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +MikeySampler节点旨在从给定的基础模型和细化模型生成高质量的样本,同时利用VAE进行潜在空间操作。它执行复杂的采样技术,并结合条件输入来优化输出。该节点还根据指定的方法和强度对生成的图像进行放大,确保最终输出满足所需的分辨率和质量标准。 + +# Input types +## Required +- seed + - 种子参数对于采样过程的可重复性至关重要,确保在不同运行中生成的样本是一致的。它在采样算法的随机性控制中起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- base_model + - 基础模型是用于潜在空间初始采样的基础神经网络。它是一个关键组件,决定了生成样本的质量和多样性。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- refiner_model + - 细化模型用于进一步提高基础模型生成的样本质量。它细化潜在空间表示,以实现最终输出的更高保真度。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- samples + - 样本参数表示要从基础模型中采样的潜在向量的数量。它直接影响生成输出的多样性。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +## Optional +- upscale_by + - upscale_by参数确定生成图像的缩放因子。它是控制最终输出分辨率的重要因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- hires_strength + - hires_strength参数调整高分辨率放大过程的强度。它影响放大图像的清晰度和细节水平。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- latent + - latent参数表示采样过程中得到的编码潜在向量。它很重要,因为它作为模型和最终放大图像之间的中间表示。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MikeySampler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_model': ('MODEL',), 'refiner_model': ('MODEL',), 'samples': ('LATENT',), 'vae': ('VAE',), 'positive_cond_base': ('CONDITIONING',), 'negative_cond_base': ('CONDITIONING',), 'positive_cond_refiner': ('CONDITIONING',), 'negative_cond_refiner': ('CONDITIONING',), 'model_name': (folder_paths.get_filename_list('upscale_models'),), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'upscale_by': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.1}), 'hires_strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 2.0, 'step': 0.1})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'run' + CATEGORY = 'Mikey/Sampling' + + def adjust_start_step(self, image_complexity, hires_strength=1.0): + image_complexity /= 24 + if image_complexity > 1: + image_complexity = 1 + image_complexity = min([0.55, image_complexity]) * hires_strength + return min([16, 16 - int(round(image_complexity * 16, 0))]) + + def run(self, seed, base_model, refiner_model, vae, samples, positive_cond_base, negative_cond_base, positive_cond_refiner, negative_cond_refiner, model_name, upscale_by=1.0, hires_strength=1.0, upscale_method='normal'): + image_scaler = ImageScale() + vaeencoder = VAEEncode() + vaedecoder = VAEDecode() + uml = UpscaleModelLoader() + upscale_model = uml.load_model(model_name)[0] + iuwm = ImageUpscaleWithModel() + sample1 = common_ksampler(base_model, seed, 25, 6.5, 'dpmpp_2s_ancestral', 'simple', positive_cond_base, negative_cond_base, samples, start_step=0, last_step=18, force_full_denoise=False)[0] + sample2 = common_ksampler(refiner_model, seed, 30, 3.5, 'dpmpp_2m', 'simple', positive_cond_refiner, negative_cond_refiner, sample1, disable_noise=True, start_step=21, force_full_denoise=True) + if upscale_by == 0: + return sample2 + else: + sample2 = sample2[0] + pixels = vaedecoder.decode(vae, sample2)[0] + (org_width, org_height) = (pixels.shape[2], pixels.shape[1]) + img = iuwm.upscale(upscale_model, image=pixels)[0] + (upscaled_width, upscaled_height) = (int(org_width * upscale_by // 8 * 8), int(org_height * upscale_by // 8 * 8)) + img = image_scaler.upscale(img, 'nearest-exact', upscaled_width, upscaled_height, 'center')[0] + if hires_strength == 0: + return (vaeencoder.encode(vae, img)[0],) + image_complexity = calculate_image_complexity(img) + start_step = self.adjust_start_step(image_complexity, hires_strength) + latent = vaeencoder.encode(vae, img)[0] + out = common_ksampler(base_model, seed, 16, 9.5, 'dpmpp_2m_sde', 'karras', positive_cond_base, negative_cond_base, latent, start_step=start_step, force_full_denoise=True) + return out +``` \ No newline at end of file diff --git a/docs/MikeySamplerTiledAdvanced.md b/docs/MikeySamplerTiledAdvanced.md new file mode 100644 index 0000000..e252580 --- /dev/null +++ b/docs/MikeySamplerTiledAdvanced.md @@ -0,0 +1,157 @@ +# Documentation +- Class name: MikeySamplerTiledAdvanced +- Category: Mikey/Sampling +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +MikeySamplerTiledAdvanced 节点是一个设计用于执行图像上采样的高级采样技术的复杂组件。它利用涉及基础和细化模型的两阶段过程,逐步提高采样图像的质量。该节点的主要功能是通过使用复杂的噪声建模和迭代细化策略,从潜在表示生成高分辨率图像。 + +# Input types +## Required +- base_model + - 基础模型对于图像采样的初始阶段至关重要,为生成过程奠定基础。它对于节点能够以较低分辨率生成连贯且结构化的图像表示至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- refiner_model + - 细化模型在采样过程的第二阶段中扮演着关键角色,它根据基础模型的输出细化图像细节。其效果直接影响最终图像质量。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- samples + - 样本代表用作图像生成过程输入的潜在空间向量。它们对于节点创建多样化和独特的图像输出至关重要。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- vae + - VAE(变分自编码器)用于将潜在表示解码为像素空间。它是将采样数据转换为视觉格式的关键组件。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- positive_cond_base + - 正向条件在采样期间为基模型提供指导,确保生成的图像符合特定的特征或属性。 + - Comfy dtype: CONDITIONING + - Python dtype: List[torch.Tensor] +- negative_cond_base + - 负向条件用于限制基础模型的采样过程,防止在生成的图像中包含不希望的特征。 + - Comfy dtype: CONDITIONING + - Python dtype: List[torch.Tensor] +- positive_cond_refiner + - 细化模型的正向条件指导增强过程,专注于突出细化图像中所需的特征。 + - Comfy dtype: CONDITIONING + - Python dtype: List[torch.Tensor] +- negative_cond_refiner + - 细化模型的负向条件确保细化过程避免向最终图像引入不希望的元素。 + - Comfy dtype: CONDITIONING + - Python dtype: List[torch.Tensor] +- model_name + - 模型名称标识节点中要使用的特定上采样模型,这对于确定节点的上采样能力和性能至关重要。 + - Comfy dtype: folder_paths.get_filename_list('upscale_models') + - Python dtype: str +- seed + - 种子参数对于确保采样过程的可重复性至关重要,允许在不同运行中获得一致的结果。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- denoise_image + - 去噪图像参数控制采样过程中应用的噪声减少级别,这可以显著影响最终图像的清晰度和细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- steps + - 步数参数定义了采样过程中的迭代次数,这直接影响节点的计算复杂性和生成图像的质量。 + - Comfy dtype: INT + - Python dtype: int +- smooth_step + - 平滑步骤用于控制采样过程不同阶段之间的过渡,目的是在图像细节中产生更平滑、更自然的进展。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg 参数调整采样过程的配置,允许微调节点的行为以实现最佳结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 采样器名称指定要使用的采样方法,这是决定节点生成图像样本方法的关键因素。 + - Comfy dtype: comfy.samplers.KSampler.SAMPLERS + - Python dtype: str +- scheduler + - 调度器确定采样过程的进展速率,这可以影响图像生成的效率和结果。 + - Comfy dtype: comfy.samplers.KSampler.SCHEDULERS + - Python dtype: str +- upscale_by + - “放大倍数”参数设置图像上采样过程的缩放因子,直接影响最终输出图像的分辨率。 + - Comfy dtype: FLOAT + - Python dtype: float +- tiler_denoise + - 平铺去噪参数调节平铺过程中应用于各个平铺块的去噪级别,这可以增强上采样图像的整体视觉一致性。 + - Comfy dtype: FLOAT + - Python dtype: float +- tiler_model + - 平铺模型决定平铺过程中使用哪个模型,允许选择基础模型或细化模型以在最终图像中实现不同级别的细节。 + - Comfy dtype: COMBO['base', 'refiner'] + - Python dtype: str +- use_complexity_score + - 使用复杂度分数参数指示是否将复杂度分数纳入平铺过程,这有助于确定平铺处理的优先级顺序。 + - Comfy dtype: COMBO['true', 'false'] + - Python dtype: str +- image_optional + - 可选图像参数允许包含一个额外的图像,它可以用来影响采样过程,并将新的视觉元素引入到生成的图像中。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Output types +- tiled_image + - 平铺图像是节点的主要输出,代表输入图像的最终上采样和平铺版本。它展示了节点通过多阶段上采样过程增强图像细节的能力。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- upscaled_image + - 上采样图像是额外的输出,提供了平铺过程之前初始上采样阶段后图像的视图。它突出了节点在上采样过程中的中间结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MikeySamplerTiledAdvanced: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_model': ('MODEL',), 'refiner_model': ('MODEL',), 'samples': ('LATENT',), 'vae': ('VAE',), 'positive_cond_base': ('CONDITIONING',), 'negative_cond_base': ('CONDITIONING',), 'positive_cond_refiner': ('CONDITIONING',), 'negative_cond_refiner': ('CONDITIONING',), 'model_name': (folder_paths.get_filename_list('upscale_models'),), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'denoise_image': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'steps': ('INT', {'default': 30, 'min': 1, 'max': 1000}), 'smooth_step': ('INT', {'default': 1, 'min': -1, 'max': 100}), 'cfg': ('FLOAT', {'default': 6.5, 'min': 0.0, 'max': 1000.0, 'step': 0.1}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'upscale_by': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 10.0, 'step': 0.1}), 'tiler_denoise': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'tiler_model': (['base', 'refiner'], {'default': 'base'}), 'use_complexity_score': (['true', 'false'], {'default': 'true'})}, 'optional': {'image_optional': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE', 'IMAGE') + RETURN_NAMES = ('tiled_image', 'upscaled_image') + FUNCTION = 'run' + CATEGORY = 'Mikey/Sampling' + + def phase_one(self, base_model, refiner_model, samples, positive_cond_base, negative_cond_base, positive_cond_refiner, negative_cond_refiner, upscale_by, model_name, seed, vae, denoise_image, steps, smooth_step, cfg, sampler_name, scheduler): + image_scaler = ImageScale() + vaedecoder = VAEDecode() + uml = UpscaleModelLoader() + upscale_model = uml.load_model(model_name)[0] + iuwm = ImageUpscaleWithModel() + start_step = int(steps - steps * denoise_image) + if start_step > steps // 2: + last_step = steps - 1 + elif start_step % 2 == 0: + last_step = steps // 2 - 1 + else: + last_step = steps // 2 + sample1 = common_ksampler(base_model, seed, steps, cfg, sampler_name, scheduler, positive_cond_base, negative_cond_base, samples, start_step=start_step, last_step=last_step, force_full_denoise=False)[0] + start_step = last_step + 1 + total_steps = steps + smooth_step + sample2 = common_ksampler(refiner_model, seed, total_steps, cfg, sampler_name, scheduler, positive_cond_refiner, negative_cond_refiner, sample1, disable_noise=True, start_step=start_step, force_full_denoise=True)[0] + pixels = vaedecoder.decode(vae, sample2)[0] + (org_width, org_height) = (pixels.shape[2], pixels.shape[1]) + img = iuwm.upscale(upscale_model, image=pixels)[0] + (upscaled_width, upscaled_height) = (int(org_width * upscale_by // 8 * 8), int(org_height * upscale_by // 8 * 8)) + img = image_scaler.upscale(img, 'nearest-exact', upscaled_width, upscaled_height, 'center')[0] + return (img, upscaled_width, upscaled_height) + + def run(self, seed, base_model, refiner_model, vae, samples, positive_cond_base, negative_cond_base, positive_cond_refiner, negative_cond_refiner, model_name, upscale_by=1.0, tiler_denoise=0.25, upscale_method='normal', tiler_model='base', denoise_image=0.25, steps=30, smooth_step=0, cfg=6.5, sampler_name='dpmpp_3m_sde_gpu', scheduler='exponential', use_complexity_score='true', image_optional=None): + if image_optional is not None: + vaeencoder = VAEEncode() + samples = vaeencoder.encode(vae, image_optional)[0] + (img, upscaled_width, upscaled_height) = self.phase_one(base_model, refiner_model, samples, positive_cond_base, negative_cond_base, positive_cond_refiner, negative_cond_refiner, upscale_by, model_name, seed, vae, denoise_image, steps, smooth_step, cfg, sampler_name, scheduler) + img = tensor2pil(img) + if tiler_model == 'base': + tiled_image = run_tiler(img, base_model, vae, seed, positive_cond_base, negative_cond_base, tiler_denoise, use_complexity_score) + else: + tiled_image = run_tiler(img, refiner_model, vae, seed, positive_cond_refiner, negative_cond_refiner, tiler_denoise, use_complexity_score) + return (tiled_image, img) +``` \ No newline at end of file diff --git a/docs/MikeySamplerTiledAdvancedBaseOnly.md b/docs/MikeySamplerTiledAdvancedBaseOnly.md new file mode 100644 index 0000000..3440443 --- /dev/null +++ b/docs/MikeySamplerTiledAdvancedBaseOnly.md @@ -0,0 +1,134 @@ +# Documentation +- Class name: MikeySamplerTiledAdvancedBaseOnly +- Category: Mikey/Sampling +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +MikeySamplerTiledAdvancedBaseOnly节点旨在执行高级图像采样和上采样操作。它结合了基础模型、变分自编码器(VAE)和分块技术来增强图像质量和细节。该节点的主要目标是从潜在样本生成高分辨率图像,利用复杂的算法和去噪技术以获得卓越的结果。 + +# Input types +## Required +- base_model + - 基础模型参数对节点的操作至关重要,因为它定义了用于采样的底层模型。它直接影响生成的样本的质量和特性,这对于实现所需的上采样和图像增强效果至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- samples + - 样本输入是节点功能的关键要素,提供了将被转换为高分辨率图像的潜在表示。样本的质量直接影响最终输出,使其成为实现节点目标的关键参数。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- vae + - VAE(变分自编码器)参数在节点解码和编码潜在表示的过程中扮演着重要角色。它在将采样数据转换为适合上采样和进一步处理的格式方面起着关键作用。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- positive_cond_base + - positive_cond_base参数对于引导采样过程生成具有所需属性的图像至关重要。它作为正向调节因子,影响节点产生符合特定标准图像的能力。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative_cond_base + - negative_cond_base参数是引导采样过程避免不良结果的关键因素。它通过提供负向调节来帮助优化图像生成过程,这对于确保节点的输出与预期结果一致至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- model_name + - model_name参数在确定节点将使用哪个上采样模型进行图像增强方面至关重要。它决定了特定的模型配置和能力,这对于实现所需的上采样和图像质量改进至关重要。 + - Comfy dtype: folder_paths.get_filename_list('upscale_models') + - Python dtype: str +- seed + - seed参数对于确保采样过程的可重复性和一致性很重要。它初始化随机数生成器,这影响样本的生成,进而影响最终的图像输出。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- denoise_image + - denoise_image参数允许在上采样过程中控制应用于图像的去噪水平。它是一个可选设置,可以根据需要调整以实现图像细节和降噪之间的平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- steps + - steps参数定义了采样过程中使用的迭代次数。它是一个可选输入,可以微调以控制生成图像的复杂性和细节。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数,简称配置,用于调整采样过程的设置。它是一个可选参数,可以修改以影响节点的行为和生成的图像特性。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数指定节点要使用的采样方法。它是一个可选输入,允许选择不同的采样技术,这可以显著影响节点的性能和输出图像的质量。 + - Comfy dtype: comfy.samplers.KSampler.SAMPLERS + - Python dtype: str +- scheduler + - scheduler参数确定采样过程的调度策略。它是一个可选设置,可以定制以优化节点的效率和生成高质量的图像。 + - Comfy dtype: comfy.samplers.KSampler.SCHEDULERS + - Python dtype: str +- upscale_by + - upscale_by参数设置上采样过程的缩放因子。它是一个可选输入,允许用户控制应用于图像的上采样程度,这可以影响最终的分辨率和细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- tiler_denoise + - tiler_denoise参数用于控制平铺过程中每个小方块的去噪水平。它是一个可选参数,可以通过调整来提高最终图像的视觉质量,通过减少单个小方块中的噪声。 + - Comfy dtype: FLOAT + - Python dtype: float +- image_optional + - image_optional参数允许可选地输入一个图像,该图像可以被编码成潜在空间以进行进一步处理。这使得节点能够使用现有的图像工作,提供了输入数据处理的灵活性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Output types +- output_image + - output_image参数代表了节点生成的最终、上采样和增强的图像。它是节点处理的结果,反映了应用的采样、上采样和去噪技术的组合效果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MikeySamplerTiledAdvancedBaseOnly: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_model': ('MODEL',), 'samples': ('LATENT',), 'vae': ('VAE',), 'positive_cond_base': ('CONDITIONING',), 'negative_cond_base': ('CONDITIONING',), 'model_name': (folder_paths.get_filename_list('upscale_models'),), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'denoise_image': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'steps': ('INT', {'default': 30, 'min': 1, 'max': 1000}), 'cfg': ('FLOAT', {'default': 6.5, 'min': 0.0, 'max': 1000.0, 'step': 0.1}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'upscale_by': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 10.0, 'step': 0.1}), 'tiler_denoise': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.05})}, 'optional': {'image_optional': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('output_image',) + FUNCTION = 'run' + CATEGORY = 'Mikey/Sampling' + + def phase_one(self, base_model, samples, positive_cond_base, negative_cond_base, upscale_by, model_name, seed, vae, denoise_image, steps, cfg, sampler_name, scheduler): + image_scaler = ImageScale() + vaedecoder = VAEDecode() + uml = UpscaleModelLoader() + upscale_model = uml.load_model(model_name)[0] + iuwm = ImageUpscaleWithModel() + start_step = int(steps - steps * denoise_image) + sample1 = common_ksampler(base_model, seed, steps, cfg, sampler_name, scheduler, positive_cond_base, negative_cond_base, samples, start_step=start_step, last_step=steps, force_full_denoise=False)[0] + pixels = vaedecoder.decode(vae, sample1)[0] + (org_width, org_height) = (pixels.shape[2], pixels.shape[1]) + img = iuwm.upscale(upscale_model, image=pixels)[0] + (upscaled_width, upscaled_height) = (int(org_width * upscale_by // 8 * 8), int(org_height * upscale_by // 8 * 8)) + img = image_scaler.upscale(img, 'nearest-exact', upscaled_width, upscaled_height, 'center')[0] + return (img, upscaled_width, upscaled_height) + + def upscale_image(self, samples, vae, upscale_by, model_name): + image_scaler = ImageScale() + vaedecoder = VAEDecode() + uml = UpscaleModelLoader() + upscale_model = uml.load_model(model_name)[0] + iuwm = ImageUpscaleWithModel() + pixels = vaedecoder.decode(vae, samples)[0] + (org_width, org_height) = (pixels.shape[2], pixels.shape[1]) + img = iuwm.upscale(upscale_model, image=pixels)[0] + (upscaled_width, upscaled_height) = (int(org_width * upscale_by // 8 * 8), int(org_height * upscale_by // 8 * 8)) + img = image_scaler.upscale(img, 'nearest-exact', upscaled_width, upscaled_height, 'center')[0] + return (img, upscaled_width, upscaled_height) + + def run(self, seed, base_model, vae, samples, positive_cond_base, negative_cond_base, model_name, upscale_by=2.0, tiler_denoise=0.4, upscale_method='normal', denoise_image=1.0, steps=30, cfg=6.5, sampler_name='dpmpp_sde_gpu', scheduler='karras', image_optional=None): + if image_optional is not None: + vaeencoder = VAEEncode() + samples = vaeencoder.encode(vae, image_optional)[0] + if denoise_image > 0: + (img, upscaled_width, upscaled_height) = self.phase_one(base_model, samples, positive_cond_base, negative_cond_base, upscale_by, model_name, seed, vae, denoise_image, steps, cfg, sampler_name, scheduler) + img = tensor2pil(img) + else: + img = self.upscale_image(samples, vae, upscale_by, model_name) + img = tensor2pil(img) + tiled_image = run_tiler_for_steps(img, base_model, vae, seed, cfg, sampler_name, scheduler, positive_cond_base, negative_cond_base, steps, tiler_denoise) + return (tiled_image,) +``` \ No newline at end of file diff --git a/docs/MirroredImage.md b/docs/MirroredImage.md new file mode 100644 index 0000000..d1425c1 --- /dev/null +++ b/docs/MirroredImage.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: MirroredImage +- Category: ♾️Mixlab/Image +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点类旨在通过水平轴反射输入的图像集合,从而创建输入图像的镜像版本。它是图像处理任务中的基本工具,其中镜像图像可用于各种目的,如扩充数据集、创建视觉效果或进行基于对称性的分析。 + +# Input types +## Required +- image + - 输入参数'image'是将由节点处理的图像集合。每个图像都应该是以节点内部图像处理功能可以读取和操作的格式。此参数至关重要,因为它直接决定了节点生成的镜像图像的内容和性质。 + - Comfy dtype: COMBO[IMAGE] + - Python dtype: List[PIL.Image.Image] + +# Output types +- IMAGE + - 节点的输出是一系列镜像图像的列表。列表中的每个图像都是相应输入图像水平反射的结果。这些镜像图像可以用于各种下游应用,使得这个输出对于图像相关任务非常重要。 + - Comfy dtype: COMBO[IMAGE] + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MirroredImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Image' + INPUT_IS_LIST = True + OUTPUT_IS_LIST = (True,) + + def run(self, image): + res = [] + for ims in image: + for im in ims: + img = tensor2pil(im) + mirrored_image = img.transpose(Image.FLIP_LEFT_RIGHT) + img = pil2tensor(mirrored_image) + res.append(img) + return (res,) +``` \ No newline at end of file diff --git a/docs/Mix Color By Mask.md b/docs/Mix Color By Mask.md new file mode 100644 index 0000000..e21bd56 --- /dev/null +++ b/docs/Mix Color By Mask.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: MixColorByMask +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +MixColorByMask 节点的 'mix' 方法旨在根据提供的遮罩将输入图像与纯色混合。它通过将图像的颜色通道调整为指定的 RGB 值,然后应用遮罩来选择性地组合原始图像与新颜色层。这个节点特别适用于创建合成图像,在这些图像中,某些区域需要用特定的色调突出或修改。 + +# Input types +## Required +- image + - 'image' 参数是要由节点操作的输入图像。它至关重要,因为它是颜色混合操作的基础。节点结合提供的颜色值和遮罩处理此图像,以实现所需的视觉效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- r + - 'r' 参数指定要与图像混合的颜色中的红色通道强度。它在确定将根据遮罩覆盖图像的最终颜色方面起着关键作用。此参数直接影响节点操作的颜色输出。 + - Comfy dtype: INT + - Python dtype: int +- g + - 'g' 参数定义颜色覆盖的绿色通道强度。它与红色和蓝色通道一起工作,创建将通过遮罩应用于图像的所需颜色。绿色强度的选择对于实现目标颜色效果至关重要。 + - Comfy dtype: INT + - Python dtype: int +- b + - 'b' 参数设置要应用于图像的颜色的蓝色通道强度。它是颜色混合过程中的关键组件,确保颜色混合与创意视觉一致。蓝色通道的值对于准确呈现最终颜色至关重要。 + - Comfy dtype: INT + - Python dtype: int +- mask + - 'mask' 参数是一个二进制图像,它指示输入图像的哪些部分将接收颜色覆盖。它是一个关键元素,因为它控制着图像中将受到颜色混合影响的区域。遮罩的模式决定了新颜色将可见的区域。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- output_image + - 'output_image' 是颜色混合过程的结果,其中原始图像根据遮罩的指导与指定颜色结合。它代表了节点操作的最终视觉结果,展示了对图像特定区域的颜色创意应用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MixColorByMask: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'r': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1}), 'g': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1}), 'b': ('INT', {'default': 0, 'min': 0, 'max': 255, 'step': 1}), 'mask': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'mix' + CATEGORY = 'Masquerade Nodes' + + def mix(self, image, r, g, b, mask): + (r, g, b) = (r / 255.0, g / 255.0, b / 255.0) + image_size = image.size() + image2 = torch.tensor([r, g, b]).to(device=image.device).unsqueeze(0).unsqueeze(0).unsqueeze(0).repeat(image_size[0], image_size[1], image_size[2], 1) + (image, image2) = tensors2common(image, image2) + mask = tensor2batch(tensor2mask(mask), image.size()) + return (image * (1.0 - mask) + image2 * mask,) +``` \ No newline at end of file diff --git a/docs/Mix Images By Mask.md b/docs/Mix Images By Mask.md new file mode 100644 index 0000000..cbf5d76 --- /dev/null +++ b/docs/Mix Images By Mask.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: MixByMask +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +MixByMask节点旨在根据提供的掩码混合两张图像。它通过根据掩码的值调整每张图像的贡献来操作,允许在单个合成图像中无缝集成不同的视觉元素。 + +# Input types +## Required +- image1 + - 要混合的第一张图像。这是一个基本输入,决定了最终输出的基本视觉内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image2 + - 要混合的第二张图像。它提供了将根据掩码与第一张图像合并的额外视觉内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 确定两张图像如何混合的掩码。它是一个关键组件,控制着混合过程。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- mixed_image + - 输出是应用掩码到输入图像后得到的混合图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MixByMask: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image1': ('IMAGE',), 'image2': ('IMAGE',), 'mask': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'mix' + CATEGORY = 'Masquerade Nodes' + + def mix(self, image1, image2, mask): + (image1, image2) = tensors2common(image1, image2) + mask = tensor2batch(mask, image1.size()) + return (image1 * (1.0 - mask) + image2 * mask,) +``` \ No newline at end of file diff --git a/docs/MixingMaskGenerator.md b/docs/MixingMaskGenerator.md new file mode 100644 index 0000000..c76dad9 --- /dev/null +++ b/docs/MixingMaskGenerator.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: MixingMaskGeneratorNode +- Category: mask/generation +- Output node: False +- Repo Ref: https://github.com/ttulttul/ComfyUI-Iterative-Mixer + +该节点旨在为迭代混合过程生成噪声掩码,提供了一种灵活的机制,用于创建可以提高混合质量和结果的各种类型的掩码。 + +# Input types +## Required +- mask_type + - 掩码类型参数决定了要生成的噪声掩码的类型,如Perlin或random。它从根本上影响了输出掩码的性质及其在不同混合场景中的适用性。 + - Comfy dtype: COMBO[perlin,random] + - Python dtype: str +- seed + - 种子参数确保了噪声生成过程的可重复性。它对于在不同运行中获得一致的结果至关重要,这对于实验和测试目的尤其重要。 + - Comfy dtype: INT + - Python dtype: int +- width + - 宽度参数定义了噪声掩码的水平维度。它影响了掩码的空间分辨率,从而影响了其在混合输出中捕捉细节的能力。 + - Comfy dtype: INT + - Python dtype: int +- height + - 与宽度参数类似,高度参数定义了噪声掩码的垂直维度,影响其空间分辨率和它能表示的细节水平。 + - Comfy dtype: INT + - Python dtype: int +- batch_size + - 批次大小参数决定了一次操作中生成的噪声掩码的数量。它对处理效率很重要,并可以影响流水线中节点的吞吐量。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- perlin_scale + - 在生成Perlin噪声掩码时,此参数调整噪声的规模,这会影响掩码的细节水平和整体外观。它对于调整掩码以适应特定的混合要求至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- masks + - 输出掩码对迭代混合过程至关重要,作为混合和组合不同元素的媒介。它们在决定混合的最终结果中起着关键作用。 + - Comfy dtype: TENSOR + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MixingMaskGeneratorNode: + """ + A node that can generate different kinds of noise mask batches for + iterative mixing purposes. + """ + MASK_TYPES = ['perlin', 'random'] + MAX_RESOLUTION = 8192 + + def __init__(self): + self.device = comfy.model_management.intermediate_device() + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask_type': (s.MASK_TYPES, {'default': 'perlin'}), 'perlin_scale': ('FLOAT', {'default': 10.0, 'min': 0.1, 'max': 400.0, 'step': 0.01}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'width': ('INT', {'default': 512, 'min': 16, 'max': s.MAX_RESOLUTION, 'step': 8}), 'height': ('INT', {'default': 512, 'min': 16, 'max': s.MAX_RESOLUTION, 'step': 8}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 4096})}} + RETURN_TYPES = ('MASK',) + CATEGORY = 'mask/generation' + FUNCTION = 'get_masks' + + def get_masks(self, mask_type, perlin_scale, seed, width, height, batch_size): + mask_height = height // 8 + mask_width = width // 8 + if mask_type == 'perlin': + perlin_tensors = perlin_masks(batch_size, mask_width, mask_height, device=self.device, seed=seed, scale=perlin_scale) + masks = perlin_tensors.view(batch_size, 1, mask_height, mask_width) + elif mask_type == 'random': + masks = torch.randn([batch_size, width // 8, height // 8]) + else: + raise ValueError('invalid mask_type') + return (masks,) +``` \ No newline at end of file diff --git a/docs/Model Input Switch.md b/docs/Model Input Switch.md new file mode 100644 index 0000000..6f04418 --- /dev/null +++ b/docs/Model Input Switch.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: WAS_Model_Input_Switch +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +模型切换方法旨在根据布尔条件选择两个模型中的一个。它作为工作流中的决策节点,根据布尔输入将数据流向导向模型_a或模型_b。此节点在模型处理序列中的条件逻辑中起着关键作用。 + +# Input types +## Required +- model_a + - 参数`model_a`代表节点可以选择的第一个模型。它对于节点的决策过程至关重要,因为它决定了布尔条件满足时可能的结果之一。 + - Comfy dtype: MODEL + - Python dtype: Union[torch.nn.Module, Any] +- model_b + - 参数`model_b`表示节点可以选择的第二个模型。它在决策过程中起着重要作用,因为它决定了当布尔条件不满足时的替代结果。 + - Comfy dtype: MODEL + - Python dtype: Union[torch.nn.Module, Any] +## Optional +- boolean + - 参数`boolean`充当开关,决定节点返回哪个模型。它很重要,因为它直接影响节点的输出,从而影响工作流中的后续步骤。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- selected_model + - 输出`selected_model`表示根据布尔条件选择的模型。它是一个关键的输出,因为它决定了工作流中随后的处理步骤。 + - Comfy dtype: MODEL + - Python dtype: Union[torch.nn.Module, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Model_Input_Switch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model_a': ('MODEL',), 'model_b': ('MODEL',), 'boolean': ('BOOLEAN', {'forceInput': True})}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'model_switch' + CATEGORY = 'WAS Suite/Logic' + + def model_switch(self, model_a, model_b, boolean=True): + if boolean: + return (model_a,) + else: + return (model_b,) +``` \ No newline at end of file diff --git a/docs/Model Patch Seamless (mtb).md b/docs/Model Patch Seamless (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ModelCompile+.md b/docs/ModelCompile+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ModelMergeBlockNumber.md b/docs/ModelMergeBlockNumber.md new file mode 100644 index 0000000..52411ef --- /dev/null +++ b/docs/ModelMergeBlockNumber.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: ModelMergeBlockNumber +- Category: model_merging +- Output node: False +- Repo Ref: https://github.com/comfyanonymous/ComfyUI_experiments + +ModelMergeBlockNumber节点旨在将多个模型合并为一个单一的、紧密的结构。它通过合并两个输入模型的指定块来实现这一点,确保生成的模型保持其组成部分的功能和性能。该节点在创建能够利用其组件优势的统一模型中起着关键作用。 + +# Input types +## Required +- model1 + - ‘model1’参数是要合并的第一个模型。它在确定最终合并模型的架构和功能方面起着关键作用。这个参数至关重要,因为它对输出模型的整体结构和性能有重大贡献。 + - Comfy dtype: MODEL + - Python dtype: Any +- model2 + - ‘model2’参数表示要合并的第二个模型。它与‘model1’一样,对最终输出至关重要,影响合并模型的特性和性能。‘model1’和‘model2’的结合旨在创建一个比任何单独模型都更强大、更通用的模型。 + - Comfy dtype: MODEL + - Python dtype: Any +## Optional +- time_embed. + - ‘time_embed.’参数用于将与时间相关的信息嵌入到模型中。它对于需要时间上下文的模型特别重要。此参数允许模型考虑基于时间的特征,增强其预测能力。 + - Comfy dtype: FLOAT + - Python dtype: float +- input_blocks + - 每个‘input_blocks.i.’参数,其中‘i’的范围从0到11,代表模型输入层中的一个块。这些块对于处理输入数据并为其准备进一步的模型阶段至关重要。这些块的配置可以显著影响模型学习和从输入数据泛化的能力。 + - Comfy dtype: COMBO[FLOAT] + - Python dtype: List[float] +- middle_block + - ‘middle_block.i.’参数,对于‘i’的范围从0到2,对应于模型中间层中的块。这些块对于模型的中间处理步骤至关重要,影响模型在最终输出之前如何转换和利用输入数据。 + - Comfy dtype: COMBO[FLOAT] + - Python dtype: List[float] +- output_blocks + - ‘output_blocks.i.’参数,其中‘i’的范围从0到11,定义了输出层块的配置。这些块负责将模型的内部表示转换为所需的输出格式。它们的设置对于模型产生准确和有意义的结果至关重要。 + - Comfy dtype: COMBO[FLOAT] + - Python dtype: List[float] +- out. + - ‘out.’参数指定了模型的最终输出配置。它是一个关键组件,决定了模型的预测或输出的结构。正确设置此参数确保模型的输出与预期的格式和要求一致。 + - Comfy dtype: FLOAT + - Python dtype: float +- label_emb. + - ‘label_emb.’参数用于将标签信息嵌入到模型中。当模型需要理解并将其处理中的分类数据或类标签纳入时,这特别有用。嵌入增强了模型根据标签数据做出明智决策的能力。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- merged_model + - 'merged_model'输出代表合并过程生成的组合模型。它封装了输入模型的集成特性和功能,为预测任务提供了一个更加健壮和多功能的解决方案。 + - Comfy dtype: MODEL + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ModelMergeBlockNumber(comfy_extras.nodes_model_merging.ModelMergeBlocks): + + @classmethod + def INPUT_TYPES(s): + arg_dict = {'model1': ('MODEL',), 'model2': ('MODEL',)} + argument = ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}) + arg_dict['time_embed.'] = argument + arg_dict['label_emb.'] = argument + for i in range(12): + arg_dict['input_blocks.{}.'.format(i)] = argument + for i in range(3): + arg_dict['middle_block.{}.'.format(i)] = argument + for i in range(12): + arg_dict['output_blocks.{}.'.format(i)] = argument + arg_dict['out.'] = argument + return {'required': arg_dict} +``` \ No newline at end of file diff --git a/docs/ModelMergeSDXLDetailedTransformers.md b/docs/ModelMergeSDXLDetailedTransformers.md new file mode 100644 index 0000000..942919c --- /dev/null +++ b/docs/ModelMergeSDXLDetailedTransformers.md @@ -0,0 +1,86 @@ +# Documentation +- Class name: ModelMergeSDXLDetailedTransformers +- Category: model_merging +- Output node: False +- Repo Ref: https://github.com/comfyanonymous/ComfyUI_experiments + +ModelMergeSDXLDetailedTransformers 节点旨在将多个模型融合为一个单一的、统一的结构。它通过合并不同的模型组件,如嵌入层和变换器块,来创建一个具有改进性能的增强型模型。该节点强调模型的无缝集成,以利用它们的综合优势。 + +# Input types +## Required +- model1 + - 参数 'model1' 至关重要,因为它代表了要在节点内合并的第一个模型。它与其他模型的集成对于合并模型的整体功能和性能至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- model2 + - 参数 'model2' 是合并过程中的另一个关键组件,代表要组合的第二个模型。它对于实现最终合并模型的预期能力具有重要意义。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +## Optional +- time_embed. + - 参数 'time_embed.' 允许将基于时间的嵌入纳入模型,这对于对数据的时间方面敏感的任务可能很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- input_blocks + - 参数 'input_blocks' 是一个复杂的结构,包含多个子参数,每个子参数代表模型输入部分中的不同变换器块。这些块在处理输入数据中起着关键作用,并根据模型的需求进行配置。 + - Comfy dtype: COMBO[FLOAT] + - Python dtype: Dict[str, Union[float, torch.Tensor]] +- middle_block + - 参数 'middle_block' 指的是模型的中间部分,在这里可以应用额外的层或操作。它在模型处理和转换数据然后传递到输出层之前的能力中起着至关重要的作用。 + - Comfy dtype: COMBO[FLOAT] + - Python dtype: Dict[str, Union[float, torch.Tensor]] +- output_blocks + - 参数 'output_blocks' 定义了模型的输出部分,由各种变换器块组成,负责根据处理后的数据生成最终的预测或输出。 + - Comfy dtype: COMBO[FLOAT] + - Python dtype: Dict[str, Union[float, torch.Tensor]] +- out. + - 参数 'out.' 表示合并模型的最终输出,它包含了所有处理步骤完成后的结果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- merged_model + - 输出 'merged_model' 代表合并过程产生的最终集成模型。它包含了输入模型的组合能力,提高了下游任务的整体性能。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ModelMergeSDXLDetailedTransformers(comfy_extras.nodes_model_merging.ModelMergeBlocks): + + @classmethod + def INPUT_TYPES(s): + arg_dict = {'model1': ('MODEL',), 'model2': ('MODEL',)} + argument = ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}) + arg_dict['time_embed.'] = argument + arg_dict['label_emb.'] = argument + transformers = {4: 2, 5: 2, 7: 10, 8: 10} + transformers_args = ['norm1', 'attn1.to_q', 'attn1.to_k', 'attn1.to_v', 'attn1.to_out', 'ff.net', 'norm2', 'attn2.to_q', 'attn2.to_k', 'attn2.to_v', 'attn2.to_out', 'norm3'] + for i in range(9): + arg_dict['input_blocks.{}.0.'.format(i)] = argument + if i in transformers: + arg_dict['input_blocks.{}.1.'.format(i)] = argument + for j in range(transformers[i]): + for x in transformers_args: + arg_dict['input_blocks.{}.1.transformer_blocks.{}.{}'.format(i, j, x)] = argument + for i in range(3): + arg_dict['middle_block.{}.'.format(i)] = argument + if i == 1: + for j in range(10): + for x in transformers_args: + arg_dict['middle_block.{}.transformer_blocks.{}.{}'.format(i, j, x)] = argument + transformers = {3: 2, 4: 2, 5: 2, 6: 10, 7: 10, 8: 10} + for i in range(9): + arg_dict['output_blocks.{}.0.'.format(i)] = argument + t = 8 - i + if t in transformers: + arg_dict['output_blocks.{}.1.'.format(i)] = argument + for j in range(transformers[t]): + for x in transformers_args: + arg_dict['output_blocks.{}.1.transformer_blocks.{}.{}'.format(i, j, x)] = argument + arg_dict['out.'] = argument + return {'required': arg_dict} +``` \ No newline at end of file diff --git a/docs/ModelMergeSDXLTransformers.md b/docs/ModelMergeSDXLTransformers.md new file mode 100644 index 0000000..e095e13 --- /dev/null +++ b/docs/ModelMergeSDXLTransformers.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: ModelMergeSDXLTransformers +- Category: model_merging +- Output node: False +- Repo Ref: https://github.com/comfyanonymous/ComfyUI_experiments + +ModelMergeSDXLTransformers节点旨在将多个模型融合成一个统一的结构,利用基于变换器的架构。它的目的是协调各个模型的功能,通过复杂的融合过程提高整体性能。 + +# Input types +## Required +- model1 + - ‘model1’参数是要合并的第一个模型,对组合模型的初始结构至关重要。它为整合过程设定了基础,显著影响最终模型的能力。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- model2 + - ‘model2’参数代表要合并的第二个模型,在合并模型的最终配置中起着关键作用。它与‘model1’的整合对于实现期望的性能提升至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +## Optional +- input_blocks + - ‘input_blocks’参数是定义模型内初始变换块的参数集合。每个块都是可调的,有助于模型有效处理输入数据。 + - Comfy dtype: COMBO[FLOAT] + - Python dtype: Dict[str, Union[float, Dict[str, float]]] +- middle_block + - ‘middle_block’参数包括一组位于模型输入和输出部分之间的变换块。它在进一步完善模型的处理能力方面起着重要作用。 + - Comfy dtype: COMBO[FLOAT] + - Python dtype: Dict[str, Dict[str, float]] +- output_blocks + - ‘output_blocks’参数由构成模型最后阶段的变换块组成。这些块在决定模型输出质量和整体预测能力方面至关重要。 + - Comfy dtype: COMBO[FLOAT] + - Python dtype: Dict[str, Union[float, Dict[str, float]]] +- out + - ‘out’参数用于调整模型的最终输出层。它对于微调模型的预测以满足特定要求很重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- merged_model + - ‘merged_model’输出代表了合并过程中产生的集成模型。它包含了原始模型的组合能力和学习到的特征。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ModelMergeSDXLTransformers(comfy_extras.nodes_model_merging.ModelMergeBlocks): + + @classmethod + def INPUT_TYPES(s): + arg_dict = {'model1': ('MODEL',), 'model2': ('MODEL',)} + argument = ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}) + arg_dict['time_embed.'] = argument + arg_dict['label_emb.'] = argument + transformers = {4: 2, 5: 2, 7: 10, 8: 10} + for i in range(9): + arg_dict['input_blocks.{}.0.'.format(i)] = argument + if i in transformers: + arg_dict['input_blocks.{}.1.'.format(i)] = argument + for j in range(transformers[i]): + arg_dict['input_blocks.{}.1.transformer_blocks.{}.'.format(i, j)] = argument + for i in range(3): + arg_dict['middle_block.{}.'.format(i)] = argument + if i == 1: + for j in range(10): + arg_dict['middle_block.{}.transformer_blocks.{}.'.format(i, j)] = argument + transformers = {3: 2, 4: 2, 5: 2, 6: 10, 7: 10, 8: 10} + for i in range(9): + arg_dict['output_blocks.{}.0.'.format(i)] = argument + t = 8 - i + if t in transformers: + arg_dict['output_blocks.{}.1.'.format(i)] = argument + for j in range(transformers[t]): + arg_dict['output_blocks.{}.1.transformer_blocks.{}.'.format(i, j)] = argument + arg_dict['out.'] = argument + return {'required': arg_dict} +``` \ No newline at end of file diff --git a/docs/ModelSamplerTonemapNoiseTest.md b/docs/ModelSamplerTonemapNoiseTest.md new file mode 100644 index 0000000..e9ff807 --- /dev/null +++ b/docs/ModelSamplerTonemapNoiseTest.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: ModelSamplerTonemapNoiseTest +- Category: custom_node_experiments +- Output node: False +- Repo Ref: https://github.com/comfyanonymous/ComfyUI_experiments + +节点 `ModelSamplerTonemapNoiseTest` 的 `patch` 方法旨在通过应用色调映射和噪声减少技术来增强给定模型的采样过程。它通过在 Reinhard 色调映射操作的上下文中调整噪声预测来工作,目的是提高采样输出的视觉质量和一致性。 + +# Input types +## Required +- model + - 参数 `model` 至关重要,因为它代表了将要采样的机器学习模型。这是主要的输入,将在其上应用色调映射和噪声减少。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +## Optional +- multiplier + - 参数 `multiplier` 用于缩放噪声减少效果。它允许根据手头任务的具体需求微调噪声过滤过程的强度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- model + - 输出 `model` 是输入模型的修改版本,现在配备了一个增强的采样函数,该函数结合了色调映射和噪声减少技术,以提高输出质量。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ModelSamplerTonemapNoiseTest: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'multiplier': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 100.0, 'step': 0.01})}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'patch' + CATEGORY = 'custom_node_experiments' + + def patch(self, model, multiplier): + + def sampler_tonemap_reinhard(args): + cond = args['cond'] + uncond = args['uncond'] + cond_scale = args['cond_scale'] + noise_pred = cond - uncond + noise_pred_vector_magnitude = (torch.linalg.vector_norm(noise_pred, dim=1) + 1e-10)[:, None] + noise_pred /= noise_pred_vector_magnitude + mean = torch.mean(noise_pred_vector_magnitude, dim=(1, 2, 3), keepdim=True) + std = torch.std(noise_pred_vector_magnitude, dim=(1, 2, 3), keepdim=True) + top = (std * 3 + mean) * multiplier + noise_pred_vector_magnitude *= 1.0 / top + new_magnitude = noise_pred_vector_magnitude / (noise_pred_vector_magnitude + 1.0) + new_magnitude *= top + return uncond + noise_pred * new_magnitude * cond_scale + m = model.clone() + m.set_model_sampler_cfg_function(sampler_tonemap_reinhard) + return (m,) +``` \ No newline at end of file diff --git a/docs/MosaicExpandImage.md b/docs/MosaicExpandImage.md new file mode 100644 index 0000000..1cee8ab --- /dev/null +++ b/docs/MosaicExpandImage.md @@ -0,0 +1,130 @@ +# Documentation +- Class name: MosaicExpandImage +- Category: Mikey/Image +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +MosaicExpandImage节点旨在通过在图像边框周围创建马赛克效果来增强图像的视觉吸引力。它以一种非均匀的、艺术化的方式智能扩展图像,产生的结果既视觉上引人注目,又保持了原始图像内容的完整性。 + +# Input types +## Required +- image + - 图像参数是节点的核心输入,代表将要通过马赛克效果艺术性扩展的原始图像。它对节点的操作至关重要,因为它决定了将要转换的基础内容。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +## Optional +- left + - left参数指定在图像左侧添加的马赛克块的数量。它在确定左侧扩展区域的宽度方面起着关键作用,有助于形成最终马赛克效果的整体美感。 + - Comfy dtype: INT + - Python dtype: int +- top + - top参数决定在图像顶部添加的马赛克块的数量。它在塑造顶部扩展区域的高度方面很重要,影响所创建的整体马赛克图案。 + - Comfy dtype: INT + - Python dtype: int +- right + - right参数设置要添加到图像右侧的马赛克块的数量。它对于控制右侧马赛克边框的宽度至关重要,影响马赛克扩展的最终视觉效果。 + - Comfy dtype: INT + - Python dtype: int +- bottom + - bottom参数确定要在图像底部包含的马赛克块的数量。它是建立底部马赛克边框高度的关键因素,这对于整体马赛克设计至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result_img + - result_img输出参数代表应用了马赛克扩展的最终图像。它是节点处理的结果,展示了通过马赛克效果实现的艺术增强。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - mask输出参数提供了一个二进制掩码,用于划分原始图像区域和马赛克扩展区域。在需要区分原始区域和扩展区域的应用中,它非常重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MosaicExpandImage: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE', {'default': None}), 'left': ('INT', {'default': 0, 'min': 0, 'max': 5}), 'top': ('INT', {'default': 0, 'min': 0, 'max': 5}), 'right': ('INT', {'default': 0, 'min': 0, 'max': 5}), 'bottom': ('INT', {'default': 0, 'min': 0, 'max': 5})}} + RETURN_TYPES = ('IMAGE', 'MASK') + RETURN_NAMES = ('result_img',) + FUNCTION = 'mosaic_expand' + CATEGORY = 'Mikey/Image' + + def mosaic_expand(self, image, left, top, right, bottom): + img = tensor2pil(image) + (width, height) = img.size + (width_5th, height_5th) = (width // 5, height // 5) + + def create_mosaic(side_img, num_fifths, vertical=False): + block_size = 50 + num_blocks_wide = side_img.width // block_size + num_blocks_high = num_fifths * height_5th // block_size if vertical else side_img.height // block_size + mosaic_width = block_size * num_blocks_wide + mosaic_height = block_size * num_blocks_high + mosaic_img = Image.new('RGB', (mosaic_width, mosaic_height)) + for i in range(num_blocks_wide): + for j in range(num_blocks_high): + section = side_img.crop((i * block_size, j * block_size, (i + 1) * block_size, (j + 1) * block_size)) + avg_color = np.array(section).mean(axis=(0, 1)).astype(np.uint8) + for x in range(block_size): + for y in range(block_size): + mosaic_x = i * block_size + x + mosaic_y = j * block_size + y + mosaic_img.putpixel((mosaic_x, mosaic_y), tuple(avg_color)) + return mosaic_img + self.new_width = width + width_5th * (left + right) + self.new_height = height + height_5th * (top + bottom) + new_img = Image.new('RGB', (self.new_width, self.new_height)) + if right > 0: + right_side = img.crop((width - width_5th * right, 0, width, height)) + right_mosaic = create_mosaic(right_side, right) + right_mosaic = right_mosaic.transpose(Image.FLIP_LEFT_RIGHT) + right_mosaic = right_mosaic.resize((width_5th * right + 8, self.new_height)) + new_img.paste(right_mosaic, (width + width_5th * left, 0)) + if left > 0: + left_side = img.crop((0, 0, width_5th * left, height)) + left_mosaic = create_mosaic(left_side, left) + left_mosaic = left_mosaic.transpose(Image.FLIP_LEFT_RIGHT) + left_mosaic = left_mosaic.resize((width_5th * left + 8, self.new_height)) + new_img.paste(left_mosaic, (0, 0)) + if top > 0: + top_side = img.crop((0, 0, width, height_5th * top)) + top_mosaic = create_mosaic(top_side, top, vertical=True) + top_mosaic = top_mosaic.transpose(Image.FLIP_TOP_BOTTOM) + top_mosaic = top_mosaic.resize((width + 32, height_5th * top + 8)) + new_img.paste(top_mosaic, (width_5th * left, 0)) + if bottom > 0: + bottom_side = img.crop((0, height - height_5th * bottom, width, height)) + bottom_mosaic = create_mosaic(bottom_side, bottom, vertical=True) + bottom_mosaic = bottom_mosaic.transpose(Image.FLIP_TOP_BOTTOM) + bottom_mosaic = bottom_mosaic.resize((width + 32, height_5th * bottom + 8)) + new_img.paste(bottom_mosaic, (width_5th * left, height + height_5th * top)) + new_img.paste(img, (width_5th * left, height_5th * top)) + new_img = pil2tensor(new_img) + mask = Image.new('RGB', (self.new_width, self.new_height), (0, 0, 0)) + white = Image.new('RGB', (width, height), (255, 255, 255)) + if right > 0: + white = white.crop((0, 0, width - 64, height)) + if left > 0: + white = white.crop((64, 0, width, height)) + if top > 0: + white = white.crop((0, 64, width, height)) + if bottom > 0: + white = white.crop((0, 0, width, height - 64)) + paste_x = width_5th * left + 64 + if left > 0: + paste_x += 64 + paste_y = height_5th * top + if top > 0: + paste_y += 64 + mask.paste(white, (paste_x, paste_y)) + mask = np.array(mask.getchannel('R')).astype(np.float32) / 255.0 + mask = 1.0 - torch.from_numpy(mask) + mask = mask.unsqueeze(0) + return (new_img, mask) +``` \ No newline at end of file diff --git a/docs/Motionctrl Cond.md b/docs/Motionctrl Cond.md new file mode 100644 index 0000000..507eae5 --- /dev/null +++ b/docs/Motionctrl Cond.md @@ -0,0 +1,176 @@ +# Documentation +- Class name: MotionctrlCond +- Category: motionctrl +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-MotionCtrl.git + +MotionctrlCond节点旨在管理和处理动态系统中的运动控制条件。它接受各种输入,如模型配置、文本提示、相机设置和轨迹数据,以生成一套全面的运动控制。该节点确保运动平稳并与提供的内容对齐,处理相机和对象运动推理模式。它输出调节信号、轨迹特征和其他相关运动参数,这些参数对于运动控制流水线中的后续步骤至关重要。 + +# Input types +## Required +- model + - 模型参数对节点至关重要,因为它定义了节点将用于生成运动控制的底层运动控制模型。这是一个必需的输入,直接影响节点处理和产生准确运动控制输出的能力。 + - Comfy dtype: MOTIONCTRL + - Python dtype: nn.Module +- prompt + - 提示参数允许用户输入描述性文本,指导运动控制行为。它很重要,因为它为模型提供了生成与描述场景一致的运动的上下文。 + - Comfy dtype: STRING + - Python dtype: str +- camera + - 相机参数指定多帧环境中的相机设置。对于节点来说,正确对齐相机的视点与正在控制的运动至关重要,以确保一致的视觉输出。 + - Comfy dtype: STRING + - Python dtype: str +- traj + - 轨迹参数概述了运动控制应遵循的路径。它是一个关键输入,决定了运动的顺序,对于节点产生所需的运动模式是不可或缺的。 + - Comfy dtype: STRING + - Python dtype: str +- infer_mode + - 推理模式参数决定节点如何处理运动和相机控制。它在节点的操作中提供了灵活性,允许其适应不同的推理需求。 + - Comfy dtype: MODE + - Python dtype: str +- context_overlap + - 上下文重叠参数用于定义相机和轨迹对齐的重叠范围。它影响节点如何将先前的上下文集成到当前的运动控制序列中。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- positive + - 正向调节输出提供一组信号,根据输入提示和设置将运动控制引向期望的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative + - 负向调节输出用于抵消或抑制某些不希望出现的运动特征,确保运动与预期的上下文一致。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- traj_list + - 轨迹列表输出枚举了定义运动路径的运动控制点序列。它对于可视化和执行计划的运动非常重要。 + - Comfy dtype: TRAJ_LIST + - Python dtype: List[torch.Tensor] +- rt_list + - RT列表输出包含与运动序列中每一帧对应的相机旋转和平移参数的列表。 + - Comfy dtype: RT_LIST + - Python dtype: List[np.ndarray] +- traj + - 轨迹特征输出表示处理后的运动控制数据,该数据封装了每一帧的运动特征。 + - Comfy dtype: TRAJ_FEATURES + - Python dtype: torch.Tensor +- rt + - RT输出提供了与当前帧的运动控制对齐的最终相机旋转和平移参数。 + - Comfy dtype: RT + - Python dtype: torch.Tensor +- noise_shape + - 噪声形状输出定义了应用于运动控制系统的噪声的维度,这对于某些类型的模拟或注入噪声的训练过程至关重要。 + - Comfy dtype: NOISE_SHAPE + - Python dtype: Tuple[int, int, int, int, int] +- context_overlap + - 上下文重叠输出指示在生成当前序列时考虑的先前运动控制上下文的重叠量。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MotionctrlCond: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('MOTIONCTRL',), 'prompt': ('STRING', {'multiline': True, 'default': 'a rose swaying in the wind'}), 'camera': ('STRING', {'multiline': True, 'default': '[[1,0,0,0,0,1,0,0,0,0,1,0.2]]'}), 'traj': ('STRING', {'multiline': True, 'default': '[[117, 102]]'}), 'infer_mode': (MODE, {'default': 'control both camera and object motion'}), 'context_overlap': ('INT', {'default': 0, 'min': 0, 'max': 32})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING', 'TRAJ_LIST', 'RT_LIST', 'TRAJ_FEATURES', 'RT', 'NOISE_SHAPE', 'INT') + RETURN_NAMES = ('positive', 'negative', 'traj_list', 'rt_list', 'traj', 'rt', 'noise_shape', 'context_overlap') + FUNCTION = 'load_cond' + CATEGORY = 'motionctrl' + + def load_cond(self, model, prompt, camera, traj, infer_mode, context_overlap): + comfy_path = os.path.dirname(folder_paths.__file__) + camera_align_file = os.path.join(comfy_path, 'custom_nodes/ComfyUI-MotionCtrl/camera.json') + traj_align_file = os.path.join(comfy_path, 'custom_nodes/ComfyUI-MotionCtrl/traj.json') + frame_length = model.temporal_length + camera_align = json.loads(camera) + for i in range(frame_length): + if len(camera_align) <= i: + camera_align.append(camera_align[len(camera_align) - 1]) + camera = json.dumps(camera_align) + traj_align = json.loads(traj) + for i in range(frame_length): + if len(traj_align) <= i: + traj_align.append(traj_align[len(traj_align) - 1]) + traj = json.dumps(traj_align) + if context_overlap > 0: + if os.path.exists(camera_align_file): + with open(camera_align_file, 'r') as file: + pre_camera_align = json.load(file) + camera_align = pre_camera_align[:context_overlap] + camera_align[:-context_overlap] + if os.path.exists(traj_align_file): + with open(traj_align_file, 'r') as file: + pre_traj_align = json.load(file) + traj_align = pre_traj_align[:context_overlap] + traj_align[:-context_overlap] + with open(camera_align_file, 'w') as file: + json.dump(camera_align, file) + with open(traj_align_file, 'w') as file: + json.dump(traj_align, file) + prompts = prompt + RT = process_camera(camera, frame_length).reshape(-1, 12) + RT_list = process_camera_list(camera, frame_length) + traj_flow = process_traj(traj, frame_length).transpose(3, 0, 1, 2) + print(prompts) + print(RT.shape) + print(traj_flow.shape) + height = 256 + width = 256 + assert height % 16 == 0 and width % 16 == 0, 'Error: image size [h,w] should be multiples of 16!' + (h, w) = (height // 8, width // 8) + channels = model.channels + frames = model.temporal_length + noise_shape = [1, channels, frames, h, w] + if infer_mode == MODE[0]: + camera_poses = RT + camera_poses = torch.tensor(camera_poses).float() + camera_poses = camera_poses.unsqueeze(0) + trajs = None + if torch.cuda.is_available(): + camera_poses = camera_poses.cuda() + elif infer_mode == MODE[1]: + trajs = traj_flow + trajs = torch.tensor(trajs).float() + trajs = trajs.unsqueeze(0) + camera_poses = None + if torch.cuda.is_available(): + trajs = trajs.cuda() + else: + camera_poses = RT + trajs = traj_flow + camera_poses = torch.tensor(camera_poses).float() + trajs = torch.tensor(trajs).float() + camera_poses = camera_poses.unsqueeze(0) + trajs = trajs.unsqueeze(0) + if torch.cuda.is_available(): + camera_poses = camera_poses.cuda() + trajs = trajs.cuda() + batch_size = noise_shape[0] + prompts = prompt + if isinstance(prompts, str): + prompts = [prompts] + for i in range(len(prompts)): + prompts[i] = f'{prompts[i]}, {post_prompt}' + cond = model.get_learned_conditioning(prompts) + if camera_poses is not None: + RT = camera_poses[..., None] + else: + RT = None + traj_features = None + if trajs is not None: + traj_features = model.get_traj_features(trajs) + else: + traj_features = None + uc = None + prompts = batch_size * [DEFAULT_NEGATIVE_PROMPT] + uc = model.get_learned_conditioning(prompts) + if traj_features is not None: + un_motion = model.get_traj_features(torch.zeros_like(trajs)) + else: + un_motion = None + uc = {'features_adapter': un_motion, 'uc': uc} + return (cond, uc, traj, RT_list, traj_features, RT, noise_shape, context_overlap) +``` \ No newline at end of file diff --git a/docs/Motionctrl Sample Simple.md b/docs/Motionctrl Sample Simple.md new file mode 100644 index 0000000..b11aedf --- /dev/null +++ b/docs/Motionctrl Sample Simple.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: MotionctrlSampleSimple +- Category: motionctrl +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-MotionCtrl.git + +MotionctrlSampleSimple 节点旨在使用一系列模型和采样技术生成和控制运动序列。它利用运动控制模型的能力来创建连贯且逼真的运动轨迹。该节点擅长处理各种输入,包括嵌入和噪声形状,以产生代表运动的图像序列。 + +# Input types +## Required +- model + - 模型参数对于节点的操作至关重要,因为它定义了将用于生成运动序列的运动控制模型。这是一个关键组件,使节点能够生成准确和逼真的运动轨迹。 + - Comfy dtype: MOTIONCTRL + - Python dtype: torch.nn.Module +- steps + - 步骤参数决定了采样过程中要使用的步数。它影响运动序列的粒度,并可能影响生成的运动质量。 + - Comfy dtype: INT + - Python dtype: int +- context_overlap + - context_overlap 参数指定上下文帧和生成帧之间的重叠量。这对于创建平滑过渡和确保运动序列的连贯性很重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - MotionctrlSampleSimple 节点的输出是代表生成运动的图像序列。这个序列是节点处理的结果,反映了输入参数和底层运动控制模型的能力。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MotionctrlSampleSimple: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('MOTIONCTRL',), 'clip': ('EMBEDDER',), 'vae': ('VAE',), 'ddim_sampler': ('SAMPLER',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'traj_list': ('TRAJ_LIST',), 'rt_list': ('RT_LIST',), 'traj': ('TRAJ_FEATURES',), 'rt': ('RT',), 'steps': ('INT', {'default': 50}), 'seed': ('INT', {'default': 1234}), 'noise_shape': ('NOISE_SHAPE',), 'context_overlap': ('INT', {'default': 0, 'min': 0, 'max': 32})}, 'optional': {'traj_tool': ('STRING', {'multiline': False, 'default': 'https://chaojie.github.io/ComfyUI-MotionCtrl/tools/draw.html'}), 'draw_traj_dot': ('BOOLEAN', {'default': False}), 'draw_camera_dot': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'run_inference' + CATEGORY = 'motionctrl' + + def run_inference(self, model, clip, vae, ddim_sampler, positive, negative, traj_list, rt_list, traj, rt, steps, seed, noise_shape, context_overlap, traj_tool='https://chaojie.github.io/ComfyUI-MotionCtrl/tools/draw.html', draw_traj_dot=False, draw_camera_dot=False): + frame_length = model.temporal_length + device = model.betas.device + print(f'frame_length{frame_length}') + unconditional_guidance_scale = 7.5 + unconditional_guidance_scale_temporal = None + n_samples = 1 + ddim_steps = steps + ddim_eta = 1.0 + cond_T = 800 + if n_samples < 1: + n_samples = 1 + if n_samples > 4: + n_samples = 4 + seed_everything(seed) + batch_images = [] + batch_variants = [] + intermediates = {} + x0 = None + x_T = None + pre_x0 = None + pre_x_T = None + comfy_path = os.path.dirname(folder_paths.__file__) + pred_x0_path = os.path.join(comfy_path, 'custom_nodes/ComfyUI-MotionCtrl/pred_x0.pt') + x_inter_path = os.path.join(comfy_path, 'custom_nodes/ComfyUI-MotionCtrl/x_inter.pt') + randt = torch.randn([noise_shape[0], noise_shape[1], frame_length - context_overlap, noise_shape[3], noise_shape[4]], device=device) + randt_np = randt.detach().cpu().numpy() + if context_overlap > 0: + if os.path.exists(pred_x0_path): + pre_x0 = torch.load(pred_x0_path) + pre_x0_np = pre_x0[-1].detach().cpu().numpy() + pre_x0_np_overlap = np.concatenate((pre_x0_np[:, :, -context_overlap:], randt_np), axis=2) + x0 = torch.tensor(pre_x0_np_overlap, device=device) + if os.path.exists(x_inter_path): + pre_x_T = torch.load(x_inter_path) + pre_x_T_np = pre_x_T[-1].detach().cpu().numpy() + pre_x_T_np_overlap = np.concatenate((pre_x_T_np[:, :, -context_overlap:], randt_np), axis=2) + x_T = torch.tensor(pre_x_T_np_overlap, device=device) + for _ in range(n_samples): + if ddim_sampler is not None: + (samples, intermediates) = ddim_sampler.sample(S=ddim_steps, conditioning=positive, batch_size=noise_shape[0], shape=noise_shape[1:], verbose=False, unconditional_guidance_scale=unconditional_guidance_scale, unconditional_conditioning=negative, eta=ddim_eta, temporal_length=noise_shape[2], conditional_guidance_scale_temporal=unconditional_guidance_scale_temporal, features_adapter=traj, pose_emb=rt, cond_T=cond_T, x0=x0, x_T=x_T) + batch_images = model.decode_first_stage(samples) + batch_variants.append(batch_images) + "\n batch_images = model.decode_first_stage(intermediates['pred_x0'][0])\n batch_variants.append(batch_images)\n batch_images = model.decode_first_stage(intermediates['pred_x0'][1])\n batch_variants.append(batch_images)\n batch_images = model.decode_first_stage(intermediates['pred_x0'][2])\n batch_variants.append(batch_images)\n batch_images = model.decode_first_stage(intermediates['x_inter'][0])\n batch_variants.append(batch_images)\n batch_images = model.decode_first_stage(intermediates['x_inter'][1])\n batch_variants.append(batch_images)\n batch_images = model.decode_first_stage(intermediates['x_inter'][2])\n batch_variants.append(batch_images)\n " + batch_variants = torch.stack(batch_variants, dim=1) + batch_variants = batch_variants[0] + torch.save(intermediates['x_inter'], x_inter_path) + torch.save(intermediates['pred_x0'], pred_x0_path) + ret = save_results(batch_variants, fps=10, traj=traj_list, draw_traj_dot=draw_traj_dot, cameras=rt_list, draw_camera_dot=draw_camera_dot, context_overlap=context_overlap) + return ret +``` \ No newline at end of file diff --git a/docs/Motionctrl Sample.md b/docs/Motionctrl Sample.md new file mode 100644 index 0000000..d6b939b --- /dev/null +++ b/docs/Motionctrl Sample.md @@ -0,0 +1,146 @@ +# Documentation +- Class name: MotionctrlSample +- Category: motionctrl +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-MotionCtrl.git + +MotionctrlSample 类旨在通过将运动控制融入渲染过程来促进动态视觉内容的生成。它利用先进算法的力量解释用户定义的相机和轨迹输入,使得能够创造出带有逼真动画的复杂运动序列。该节点抽象了运动模拟的复杂性,允许用户专注于创造性表达而不是底层技术细节。 + +# Input types +## Required +- prompt + - 提示参数作为MotionctrlSample节点的创意输入,指导生成内容的整体主题和风格。它对于设置运动模拟发生的上下文至关重要,直接影响渲染过程中产生的叙述和视觉元素。 + - Comfy dtype: STRING + - Python dtype: str +- camera + - 相机参数定义了捕捉运动序列的视角和视点。它在塑造渲染场景中的时空关系和深度感知方面起着关键作用,从而显著影响最终的视觉输出。 + - Comfy dtype: STRING + - Python dtype: str +- traj + - 轨迹参数概述了场景中物体的路径和运动,成为运动模拟的基础。它对于指导动画的动态性和元素的相互作用至关重要,确保了运动表现的连贯性和流畅性。 + - Comfy dtype: STRING + - Python dtype: str +- frame_length + - 帧长度参数指定了动画序列的持续时间,直接影响运动轨迹的详细程度和复杂性。较长的帧长度允许更复杂的运动模式和更平滑的过渡,而较短的帧长度可能导致更简单或更突然的运动。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步数参数决定了运动模拟过程中生成的中间帧数,这影响动画的平滑度和质量。步数越高,运动轨迹越精细,而步数较低可能导致动画细节不足或不连贯。 + - Comfy dtype: INT + - Python dtype: int +- seed + - 种子参数用于初始化随机数生成器,确保运动模拟结果是可复现和一致的。这对于调试和比较不同模拟运行是重要的方面。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - MotionctrlSample 节点的输出是一个动态视觉表示,以图像或图像序列的形式,封装了运动模拟的结果。它反映了输入参数的综合效应,展示了生成的运动内容的创造性和复杂性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MotionctrlSample: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'prompt': ('STRING', {'multiline': True, 'default': 'a rose swaying in the wind'}), 'camera': ('STRING', {'multiline': True, 'default': '[[1,0,0,0,0,1,0,0,0,0,1,0.2]]'}), 'traj': ('STRING', {'multiline': True, 'default': '[[117, 102]]'}), 'frame_length': ('INT', {'default': 16}), 'steps': ('INT', {'default': 50}), 'seed': ('INT', {'default': 1234})}, 'optional': {'traj_tool': ('STRING', {'multiline': False, 'default': 'https://chaojie.github.io/ComfyUI-MotionCtrl/tools/draw.html'}), 'draw_traj_dot': ('BOOLEAN', {'default': False}), 'draw_camera_dot': ('BOOLEAN', {'default': False}), 'ckpt_name': (['motionctrl.pth'], {'default': 'motionctrl.pth'})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'run_inference' + CATEGORY = 'motionctrl' + + def run_inference(self, prompt, camera, traj, frame_length, steps, seed, traj_tool='https://chaojie.github.io/ComfyUI-MotionCtrl/tools/draw.html', draw_traj_dot=False, draw_camera_dot=False, ckpt_name='motionctrl.pth'): + gpu_num = 1 + gpu_no = 0 + ckpt_path = folder_paths.get_full_path('checkpoints', ckpt_name) + comfy_path = os.path.dirname(folder_paths.__file__) + config_path = os.path.join(comfy_path, 'custom_nodes/ComfyUI-MotionCtrl/configs/inference/config_both.yaml') + args = {'savedir': f'./output/both_seed20230211', 'ckpt_path': f'{ckpt_path}', 'adapter_ckpt': None, 'base': f'{config_path}', 'condtype': 'both', 'prompt_dir': None, 'n_samples': 1, 'ddim_steps': 50, 'ddim_eta': 1.0, 'bs': 1, 'height': 256, 'width': 256, 'unconditional_guidance_scale': 1.0, 'unconditional_guidance_scale_temporal': None, 'seed': 1234, 'cond_T': 800, 'save_imgs': True, 'cond_dir': './custom_nodes/ComfyUI-MotionCtrl/examples/'} + prompts = prompt + RT = process_camera(camera, frame_length).reshape(-1, 12) + RT_list = process_camera_list(camera, frame_length) + traj_flow = process_traj(traj, frame_length).transpose(3, 0, 1, 2) + print(prompts) + print(RT.shape) + print(traj_flow.shape) + args['savedir'] = f"./output/{args['condtype']}_seed{args['seed']}" + config = OmegaConf.load(args['base']) + OmegaConf.update(config, 'model.params.unet_config.params.temporal_length', frame_length) + model_config = config.pop('model', OmegaConf.create()) + model = instantiate_from_config(model_config) + model = model.cuda(gpu_no) + assert os.path.exists(args['ckpt_path']), f"Error: checkpoint {args['ckpt_path']} Not Found!" + print(f"Loading checkpoint from {args['ckpt_path']}") + model = load_model_checkpoint(model, args['ckpt_path'], args['adapter_ckpt']) + model.eval() + assert args['height'] % 16 == 0 and args['width'] % 16 == 0, 'Error: image size [h,w] should be multiples of 16!' + (h, w) = (args['height'] // 8, args['width'] // 8) + channels = model.channels + frames = model.temporal_length + noise_shape = [args['bs'], channels, frames, h, w] + savedir = os.path.join(args['savedir'], 'samples') + os.makedirs(savedir, exist_ok=True) + unconditional_guidance_scale = 7.5 + unconditional_guidance_scale_temporal = None + n_samples = 1 + ddim_steps = steps + ddim_eta = 1.0 + cond_T = 800 + if n_samples < 1: + n_samples = 1 + if n_samples > 4: + n_samples = 4 + seed_everything(seed) + camera_poses = RT + trajs = traj_flow + camera_poses = torch.tensor(camera_poses).float() + trajs = torch.tensor(trajs).float() + camera_poses = camera_poses.unsqueeze(0) + trajs = trajs.unsqueeze(0) + if torch.cuda.is_available(): + camera_poses = camera_poses.cuda() + trajs = trajs.cuda() + ddim_sampler = DDIMSampler(model) + batch_size = noise_shape[0] + prompts = prompt + if isinstance(prompts, str): + prompts = [prompts] + for i in range(len(prompts)): + prompts[i] = f'{prompts[i]}, {post_prompt}' + cond = model.get_learned_conditioning(prompts) + if camera_poses is not None: + RT = camera_poses[..., None] + else: + RT = None + traj_features = None + if trajs is not None: + traj_features = model.get_traj_features(trajs) + else: + traj_features = None + uc = None + if unconditional_guidance_scale != 1.0: + prompts = batch_size * [DEFAULT_NEGATIVE_PROMPT] + uc = model.get_learned_conditioning(prompts) + if traj_features is not None: + un_motion = model.get_traj_features(torch.zeros_like(trajs)) + else: + un_motion = None + uc = {'features_adapter': un_motion, 'uc': uc} + else: + uc = None + batch_images = [] + batch_variants = [] + for _ in range(n_samples): + if ddim_sampler is not None: + (samples, _) = ddim_sampler.sample(S=ddim_steps, conditioning=cond, batch_size=noise_shape[0], shape=noise_shape[1:], verbose=False, unconditional_guidance_scale=unconditional_guidance_scale, unconditional_conditioning=uc, eta=ddim_eta, temporal_length=noise_shape[2], conditional_guidance_scale_temporal=unconditional_guidance_scale_temporal, features_adapter=traj_features, pose_emb=RT, cond_T=cond_T) + batch_images = model.decode_first_stage(samples) + batch_variants.append(batch_images) + batch_variants = torch.stack(batch_variants, dim=1) + batch_variants = batch_variants[0] + ret = save_results(batch_variants, fps=10, traj=traj, draw_traj_dot=draw_traj_dot, cameras=RT_list, draw_camera_dot=draw_camera_dot) + return ret +``` \ No newline at end of file diff --git a/docs/Motionctrl-SVD Sample Simple.md b/docs/Motionctrl-SVD Sample Simple.md new file mode 100644 index 0000000..d6d0705 --- /dev/null +++ b/docs/Motionctrl-SVD Sample Simple.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: MotionctrlSVDSampleSimple +- Category: motionctrl +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-MotionCtrl-SVD.git + +MotionctrlSVDSampleSimple节点旨在处理并从输入图像和相机数据生成运动序列。它利用模型的推理能力来创建代表运动的一系列帧,增强动态场景的视觉表现。该节点抽象了运动生成的复杂性,为用户提供了一个高层次的接口来探索和可视化运动动态。 + +# Input types +## Required +- model + - 模型参数对于节点的运行至关重要,因为它定义了用于生成运动序列的基础运动控制机制。没有指定的模型,节点无法执行其创建动态视觉内容的预期功能。 + - Comfy dtype: MOTIONCTRLSVD + - Python dtype: torch.nn.Module +- camera + - 相机参数是必不可少的,因为它提供了用于模拟生成的运动序列中相机的视角和方向的相机姿态数据。这些数据影响了运动表示的真实性和准确性。 + - Comfy dtype: STRING + - Python dtype: str +- image + - 图像参数是节点的关键输入,作为生成运动序列的视觉上下文。它设置了场景并为模型提供了必要的视觉线索,以便创建一个连贯且与上下文相关的运动序列。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- resize_mode + - 调整模式参数很重要,因为它决定了输入图像如何调整大小以适应模型的要求。这种调整确保图像适合处理,这对于准确生成运动序列至关重要。 + - Comfy dtype: RESIZE_MODE + - Python dtype: str +- seed + - 种子参数对节点至关重要,因为它确保了运动序列生成过程的可重复性。通过设置种子,用户可以在不同的运行中获得一致的结果,这对于测试和调试目的至关重要。 + - Comfy dtype: INT + - Python dtype: int +- fps_id + - fps_id参数很重要,因为它决定了生成的运动序列的每秒帧数。这直接影响到生成的运动序列的平滑度和流畅性,对最终视频的观感有重要影响。 + - Comfy dtype: INT + - Python dtype: int +- frame_length + - frame_length参数定义了要在运动序列中生成的帧数。它是决定节点将产生运动的持续时间和范围的关键因素。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - 输出参数代表生成的运动序列,这是一系列描绘从输入数据推断出的运动的图像。这个输出很重要,因为它是节点功能的直接结果,提供了运动动态的视觉表示。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: GPU + +# Source code +``` +class MotionctrlSVDSampleSimple: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('MOTIONCTRLSVD',), 'camera': ('STRING', {'multiline': True, 'default': '[[1,0,0,0,0,1,0,0,0,0,1,0.2]]'}), 'image': ('IMAGE',), 'resize_mode': (RESIZE_MODE,), 'seed': ('INT', {'default': 1234}), 'fps_id': ('INT', {'default': 6, 'min': 5, 'max': 30}), 'frame_length': ('INT', {'default': 14})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'run_inference' + CATEGORY = 'motionctrl' + + def run_inference(self, model, camera, image, resize_mode, seed, fps_id, frame_length): + global device + RT = process_camera(camera, frame_length).reshape(-1, 12) + image = 255.0 * image[0].cpu().numpy() + image = Image.fromarray(np.clip(image, 0, 255).astype(np.uint8)) + image = process_input_image(image, resize_mode) + return motionctrl_sample(model=model, image=image, RT=RT, num_frames=frame_length, fps_id=fps_id, decoding_t=1, seed=seed, sample_num=1, device=device) +``` \ No newline at end of file diff --git a/docs/MultiplicationNode.md b/docs/MultiplicationNode.md new file mode 100644 index 0000000..f253157 --- /dev/null +++ b/docs/MultiplicationNode.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: MultiplicationNode +- Category: ♾️Mixlab/Utils +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点对输入值执行算术运算,根据提供的乘数和加数进行缩放和调整。它强调以直接的方式转换和处理数值数据的能力,提供灵活的输出类型选择。 + +# Input types +## Required +- numberA + - 将在乘法和加法运算中使用的基值。它在确定最终输出中起着关键作用,因为它是转换的主题。 + - Comfy dtype: any_type + - Python dtype: Union[int, float, torch.Tensor] +- multiply_by + - 应用于基值的乘数,显著影响结果的规模。它在修改输出的大小方面至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- add_by + - 加到乘法结果上的值,调整最终输出。它在微调结果中发挥作用。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- a + - 算术运算的浮点结果,代表输入值的缩放和调整版本。 + - Comfy dtype: FLOAT + - Python dtype: float +- b + - 算术运算的整数结果,提供输入值转换的离散化版本。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MultiplicationNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'numberA': (any_type,), 'multiply_by': ('FLOAT', {'default': 1, 'min': -2, 'max': 18446744073709551615, 'step': 0.01, 'display': 'number'}), 'add_by': ('FLOAT', {'default': 0, 'min': -2000, 'max': 18446744073709551615, 'step': 0.01, 'display': 'number'})}} + RETURN_TYPES = ('FLOAT', 'INT') + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Utils' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False, False) + + def run(self, numberA, multiply_by, add_by): + b = int(numberA * multiply_by + add_by) + a = float(numberA * multiply_by + add_by) + return (a, b) +``` \ No newline at end of file diff --git a/docs/Multiply Integer (WLSH).md b/docs/Multiply Integer (WLSH).md new file mode 100644 index 0000000..64175ab --- /dev/null +++ b/docs/Multiply Integer (WLSH).md @@ -0,0 +1,46 @@ +# Documentation +- Class name: WLSH_Int_Multiply +- Category: WLSH Nodes/number +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点执行整数乘法,这是一种基本的算术运算,它通过指定的乘数来放大给定的数字,便于工作流中进行各种数学和数据处理任务。 + +# Input types +## Required +- number + - ‘number’参数是要乘以‘multiplier’的基础整数值。它对节点的操作至关重要,因为它定义了乘法过程中的初始值。 + - Comfy dtype: INT + - Python dtype: int +- multiplier + - ‘multiplier’参数决定了‘number’参数放大的倍数。这对节点的功能至关重要,因为它决定了应用于初始值的放大程度。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result + - ‘result’输出代表‘number’和‘multiplier’的乘积,有效地展示了整数乘法操作的结果。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Int_Multiply: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number': ('INT', {'default': 2, 'min': 1, 'max': 10000, 'forceInput': True}), 'multiplier': ('INT', {'default': 2, 'min': 1, 'max': 10000})}} + RETURN_TYPES = ('INT',) + FUNCTION = 'multiply' + CATEGORY = 'WLSH Nodes/number' + + def multiply(self, number, multiplier): + result = number * multiplier + return (int(result),) +``` \ No newline at end of file diff --git a/docs/NNLatentUpscale.md b/docs/NNLatentUpscale.md new file mode 100644 index 0000000..6f39771 --- /dev/null +++ b/docs/NNLatentUpscale.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: NNLatentUpscale +- Category: latent +- Output node: False +- Repo Ref: https://github.com/Ttl/ComfyUi_NNLatentUpscale + +NNLatentUpscale是一个旨在通过神经网络提升低维潜在表示分辨率的类,提供了一种从压缩数据生成高保真图像的方法。 + +# Input types +## Required +- latent + - latent参数至关重要,它代表了需要放大的数据的压缩形式,作为神经网络执行其增强的主要输入。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- version + - version参数决定了用于放大过程的模型,确保神经网络操作的兼容性和准确性。 + - Comfy dtype: COMBO + - Python dtype: Union[str, List[str]] +## Optional +- upscale + - upscale参数微调应用于潜在数据的增强程度,影响最终输出的分辨率和质量。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- samples + - 输出'samples'代表放大后的潜在表示,现在具有更高的分辨率,并准备进行进一步的处理或分析。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class NNLatentUpscale: + """ + Upscales SDXL latent using neural network + """ + + def __init__(self): + self.local_dir = os.path.dirname(os.path.realpath(__file__)) + self.scale_factor = 0.13025 + self.dtype = torch.float32 + if model_management.should_use_fp16(): + self.dtype = torch.float16 + self.weight_path = {'SDXL': os.path.join(self.local_dir, 'sdxl_resizer.pt'), 'SD 1.x': os.path.join(self.local_dir, 'sd15_resizer.pt')} + self.version = 'none' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latent': ('LATENT',), 'version': (['SDXL', 'SD 1.x'],), 'upscale': ('FLOAT', {'default': 1.5, 'min': 1.0, 'max': 2.0, 'step': 0.01, 'display': 'number'})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'upscale' + CATEGORY = 'latent' + + def upscale(self, latent, version, upscale): + device = model_management.get_torch_device() + samples = latent['samples'].to(device=device, dtype=self.dtype) + if version != self.version: + self.model = LatentResizer.load_model(self.weight_path[version], device, self.dtype) + self.version = version + self.model.to(device=device) + latent_out = self.model(self.scale_factor * samples, scale=upscale) / self.scale_factor + if self.dtype != torch.float32: + latent_out = latent_out.to(dtype=torch.float32) + latent_out = latent_out.to(device='cpu') + self.model.to(device=model_management.vae_offload_device()) + return ({'samples': latent_out},) +``` \ No newline at end of file diff --git a/docs/NewLayer.md b/docs/NewLayer.md new file mode 100644 index 0000000..27e019c --- /dev/null +++ b/docs/NewLayer.md @@ -0,0 +1,86 @@ +# Documentation +- Class name: NewLayer +- Category: ♾️Mixlab/Layer +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +NewLayer节点旨在根据特定的位置和缩放属性操作和组合图像层。它允许创建一个分层结构,其中每个层可以单独定位并根据提供的参数进行缩放。节点的功能集中在通过精确控制它们的外观和排列,增强视觉展示,从而实现多个图像的叠加。 + +# Input types +## Required +- x + - 参数'x'指定了画布内层的水平位置。它至关重要,因为它决定了层从画布左侧的确切放置位置,影响整体构图。 + - Comfy dtype: INT + - Python dtype: int +- y + - 参数'y'定义了画布内层的垂直位置。它是决定层从画布顶部如何对齐的关键因素,影响最终的视觉效果。 + - Comfy dtype: INT + - Python dtype: int +- width + - 参数'width'设置层的宽度。它在层的缩放中起着重要作用,允许控制视觉内容的水平尺寸。 + - Comfy dtype: INT + - Python dtype: int +- height + - 参数'height'决定了层的垂直尺寸。它对于控制层在垂直轴上的缩放至关重要,影响层的视觉突出程度。 + - Comfy dtype: INT + - Python dtype: int +- z_index + - 参数'z_index'建立层相对于其他层的堆叠顺序。值越高,表示该层将放置在其他层的前面,这对于管理层的可见性和深度至关重要。 + - Comfy dtype: INT + - Python dtype: int +- scale_option + - 参数'scale_option'决定如何缩放层。它对于保持纵横比或均匀调整层的大小很重要,这可以显著改变视觉输出。 + - Comfy dtype: COMBO['width', 'height', 'overall'] + - Python dtype: str +- image + - 参数'image'是层的视觉内容来源。它是基本的,因为它提供了将在画布内操作和显示的实际像素。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- mask + - 可选参数'mask'可以用来定义图像中应该可见或被修改的特定区域。它为图像操作过程增加了复杂性,允许对最终输出进行创造性控制。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- layers + - 可选参数'layers'允许将额外的现有层包含到组合中。这对于在现有视觉结构上构建或整合多个视觉元素非常有用。 + - Comfy dtype: LAYER + - Python dtype: List[Dict[str, Union[int, str, torch.Tensor, PIL.Image.Image]]] +- canvas + - 可选参数'canvas'提供了一个基础图像,层将被放置在该图像上。它对于设置新层将被整合的初始视觉环境很重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image + +# Output types +- layers + - 输出'layers'是代表视觉元素最终组合的层对象集合。它封装了节点操作的结果,详细说明了分层图像的结构和外观。 + - Comfy dtype: LAYER + - Python dtype: Tuple[List[Dict[str, Union[int, str, torch.Tensor, PIL.Image.Image]]], ...] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class NewLayer: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'x': ('INT', {'default': 0, 'min': -1024, 'max': 8192, 'step': 1, 'display': 'number'}), 'y': ('INT', {'default': 0, 'min': -1024, 'max': 8192, 'step': 1, 'display': 'number'}), 'width': ('INT', {'default': 512, 'min': 1, 'max': 8192, 'step': 1, 'display': 'number'}), 'height': ('INT', {'default': 512, 'min': 1, 'max': 8192, 'step': 1, 'display': 'number'}), 'z_index': ('INT', {'default': 0, 'min': 0, 'max': 100, 'step': 1, 'display': 'number'}), 'scale_option': (['width', 'height', 'overall'],), 'image': ('IMAGE',)}, 'optional': {'mask': ('MASK', {'default': None}), 'layers': ('LAYER', {'default': None}), 'canvas': ('IMAGE', {'default': None})}} + RETURN_TYPES = ('LAYER',) + RETURN_NAMES = ('layers',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Layer' + INPUT_IS_LIST = True + OUTPUT_IS_LIST = (True,) + + def run(self, x, y, width, height, z_index, scale_option, image, mask=None, layers=None, canvas=None): + if mask == None: + im = tensor2pil(image[0]) + mask = im.convert('L') + mask = pil2tensor(mask) + else: + mask = mask[0] + layer_n = [{'x': x[0], 'y': y[0], 'width': width[0], 'height': height[0], 'z_index': z_index[0], 'scale_option': scale_option[0], 'image': image[0], 'mask': mask}] + if layers != None: + layer_n = layer_n + layers + return (layer_n,) +``` \ No newline at end of file diff --git a/docs/NoiseImage.md b/docs/NoiseImage.md new file mode 100644 index 0000000..edaa230 --- /dev/null +++ b/docs/NoiseImage.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: NoiseImage +- Category: ♾️Mixlab/Image +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点根据指定的噪声级别在纯色背景上生成带有噪声的图像,为图像数据的测试和视觉实验提供了多功能工具。 + +# Input types +## Required +- width + - 宽度决定了输出图像的水平尺寸,这对于定义噪声模式应用的画布至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度设置了图像的垂直大小,与宽度一起协同工作,建立噪声生成的整体大小和范围。 + - Comfy dtype: INT + - Python dtype: int +- noise_level + - 噪声级别控制应用于图像的随机噪声的强度,直接影响最终结果的视觉效果和复杂性。 + - Comfy dtype: INT + - Python dtype: int +- color_hex + - 颜色十六进制定义了图像背景的基本颜色,它是噪声模式叠加的基础。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- result + - 输出是一个带有噪声的图像,反映了输入参数,成为图像处理工作流中进一步分析或操作的关键工件。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class NoiseImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 1, 'max': 8192, 'step': 1, 'display': 'number'}), 'height': ('INT', {'default': 512, 'min': 1, 'max': 8192, 'step': 1, 'display': 'number'}), 'noise_level': ('INT', {'default': 128, 'min': 0, 'max': 8192, 'step': 1, 'display': 'slider'}), 'color_hex': ('STRING', {'multiline': False, 'default': '#FFFFFF', 'dynamicPrompts': False})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Image' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False,) + + def run(self, width, height, noise_level, color_hex): + im = create_noisy_image(width, height, 'RGB', noise_level, color_hex) + output_dir = folder_paths.get_temp_directory() + (full_output_folder, filename, counter, subfolder, _) = folder_paths.get_save_image_path('tmp_', output_dir) + image_file = f'{filename}_{counter:05}.png' + image_path = os.path.join(full_output_folder, image_file) + im.save(image_path, compress_level=6) + im = pil2tensor(im) + return {'ui': {'images': [{'filename': image_file, 'subfolder': subfolder, 'type': 'temp'}]}, 'result': (im,)} +``` \ No newline at end of file diff --git a/docs/NoiseInjectionDetailerHookProvider.md b/docs/NoiseInjectionDetailerHookProvider.md new file mode 100644 index 0000000..8adfb0c --- /dev/null +++ b/docs/NoiseInjectionDetailerHookProvider.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: NoiseInjectionDetailerHookProvider +- Category: ImpactPack/Detailer +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +NoiseInjectionDetailerHookProvider 节点旨在通过在图像生成周期的特定阶段策略性地注入噪声来增强图像生成过程的细节。它利用噪声的力量增加可变性并微调输出,确保更细致和详细的结果。对于生成图像的保真度至关重要的应用,如创建复杂的纹理或图案,此节点至关重要。 + +# Input types +## Required +- schedule_for_cycle + - schedule_for_cycle 参数确定噪声注入在生成周期内的时机。它对于控制引入噪声的阶段至关重要,允许精确操纵图像的细节水平。此参数对于在最终输出中实现噪声和清晰度之间的理想平衡至关重要。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- source + - source 参数决定噪声生成将在 CPU 还是 GPU 上进行。这个选择可以显著影响噪声注入过程的性能和效率,使其成为优化节点操作的关键考虑因素。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- seed + - seed 参数初始化随机数生成器,确保噪声的一致性和可复现性。它在保持噪声注入的可预测性方面发挥着重要作用,这对于在节点的不同运行中创建可靠和一致的输出非常重要。 + - Comfy dtype: INT + - Python dtype: int +- start_strength + - start_strength 参数设置在生成周期开始时注入的噪声的初始强度。它是决定噪声对图像整体影响的关键因素,允许对引入的细节水平进行精细控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_strength + - end_strength 参数定义了生成周期结束时噪声的强度。它允许噪声强度逐渐增加或减少,从而能够创建具有细节和纹理平滑过渡的图像。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- DETAILER_HOOK + - NoiseInjectionDetailerHookProvider 节点的输出是一个细节钩子,这是一个用于将噪声注入图像生成过程的专用工具。这个钩子非常重要,因为它直接影响生成的图像的最终质量和细节,提供了一种增强输出视觉保真度的手段。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: DetailerHook + +# Usage tips +- Infra type: GPU + +# Source code +``` +class NoiseInjectionDetailerHookProvider: + schedules = ['skip_start', 'from_start'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'schedule_for_cycle': (s.schedules,), 'source': (['CPU', 'GPU'],), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'start_strength': ('FLOAT', {'default': 2.0, 'min': 0.0, 'max': 200.0, 'step': 0.01}), 'end_strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 200.0, 'step': 0.01})}} + RETURN_TYPES = ('DETAILER_HOOK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detailer' + + def doit(self, schedule_for_cycle, source, seed, start_strength, end_strength): + try: + hook = hooks.InjectNoiseHookForDetailer(source, seed, start_strength, end_strength, from_start='from_start' in schedule_for_cycle) + return (hook,) + except Exception as e: + print("[ERROR] NoiseInjectionDetailerHookProvider: 'ComfyUI Noise' custom node isn't installed. You must install 'BlenderNeko/ComfyUI Noise' extension to use this node.") + print(f'\t{e}') + pass +``` \ No newline at end of file diff --git a/docs/NoiseInjectionHookProvider.md b/docs/NoiseInjectionHookProvider.md new file mode 100644 index 0000000..71c161a --- /dev/null +++ b/docs/NoiseInjectionHookProvider.md @@ -0,0 +1,63 @@ +# Documentation +- Class name: NoiseInjectionHookProvider +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +NoiseInjectionHookProvider 节点旨在将噪声注入图像生成过程,允许创建变化或对图像进行“反采样”。它提供了一个简单的时间表来控制噪声注入过程,并且能够处理 CPU 和 GPU 源。此节点对于需要精细控制噪声的工作流程至关重要,例如生成微妙的变化或重建具有特定噪声特性的图像。 + +# Input types +## Required +- schedule_for_iteration + - schedule_for_iteration 参数确定噪声注入时间表,这对于在迭代中一致地应用噪声至关重要。它是节点生成变化或“反采样”图像能力的关键因素。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- source + - source 参数指定噪声生成应使用 CPU 还是 GPU。这个选择可以显著影响噪声注入过程的性能和效率。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- seed + - seed 参数初始化噪声生成过程,确保噪声模式是可复现的。它在保持节点不同运行之间的一致性中起着至关重要的作用。 + - Comfy dtype: INT + - Python dtype: int +- start_strength + - start_strength 参数设置要注入的噪声的初始强度。它是决定将要实现的变化程度或“反采样”的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_strength + - end_strength 参数定义了注入过程结束时噪声的最终强度。它与 start_strength 配合使用,在过程的整个过程中创建噪声强度的梯度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- hook + - hook 输出提供了将噪声注入功能集成到更大的图像生成工作流程中的方法。它封装了节点定义的设置和行为,允许在更广泛的流程中无缝应用。 + - Comfy dtype: PK_HOOK + - Python dtype: PixelKSampleHook + +# Usage tips +- Infra type: GPU + +# Source code +``` +class NoiseInjectionHookProvider: + schedules = ['simple'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'schedule_for_iteration': (s.schedules,), 'source': (['CPU', 'GPU'],), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'start_strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 200.0, 'step': 0.01}), 'end_strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 200.0, 'step': 0.01})}} + RETURN_TYPES = ('PK_HOOK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + def doit(self, schedule_for_iteration, source, seed, start_strength, end_strength): + try: + hook = None + if schedule_for_iteration == 'simple': + hook = hooks.InjectNoiseHook(source, seed, start_strength, end_strength) + return (hook,) + except Exception as e: + print("[ERROR] NoiseInjectionHookProvider: 'ComfyUI Noise' custom node isn't installed. You must install 'BlenderNeko/ComfyUI Noise' extension to use this node.") + print(f'\t{e}') + pass +``` \ No newline at end of file diff --git a/docs/Number Counter.md b/docs/Number Counter.md new file mode 100644 index 0000000..de0ad62 --- /dev/null +++ b/docs/Number Counter.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: WAS_Number_Counter +- Category: WAS Suite/Number +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Number_Counter节点旨在根据指定的操作模式管理和操作数值。它有效地处理递增、递减和边界控制的计数操作。此节点特别适用于需要序列生成或迭代数值调整的应用程序。 + +# Input types +## Required +- number_type + - ‘number_type’参数确定节点将处理的数值类型,可以是整数或浮点数。这个选择影响精度以及可以执行的算术操作类型。 + - Comfy dtype: STRING + - Python dtype: str +- mode + - ‘mode’参数指示节点将如何修改计数器值。它可以设置为递增、递减、递增到停止值或递减到停止值,这对于控制计数行为至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- start + - ‘start’参数设定计数器的初始值。这是一个基本设置,为节点执行的所有计数操作设定起始点。 + - Comfy dtype: FLOAT + - Python dtype: Union[int, float] +- stop + - ‘stop’参数定义计数操作的边界值。当达到此值时,将根据所选模式停止递增或递减计数。 + - Comfy dtype: FLOAT + - Python dtype: Union[int, float] +- step + - ‘step’参数指定每次操作期间应用于计数器的增量或减量值。它直接影响数值序列的变化速率。 + - Comfy dtype: FLOAT + - Python dtype: float +- unique_id + - ‘unique_id’参数是节点管理的每个计数器的唯一标识符。它确保每个计数操作被独立跟踪和操作。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +## Optional +- reset_bool + - ‘reset_bool’参数允许在设置为大于或等于1的值时将计数器重置为其初始值。它提供了一种重新开始计数操作的方法。 + - Comfy dtype: NUMBER + - Python dtype: Optional[Union[int, bool]] + +# Output types +- number + - ‘number’输出提供了操作后计数器当前值的整数表示。当需要整数精度时特别有用。 + - Comfy dtype: INT + - Python dtype: int +- float + - ‘float’输出提供计数器当前值的浮点表示。适用于需要小数精度的场景。 + - Comfy dtype: FLOAT + - Python dtype: float +- int + - ‘int’输出返回计数器的整数值,类似于‘number’输出,确保结果以整数类型呈现。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Number_Counter: + + def __init__(self): + self.counters = {} + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number_type': (['integer', 'float'],), 'mode': (['increment', 'decrement', 'increment_to_stop', 'decrement_to_stop'],), 'start': ('FLOAT', {'default': 0, 'min': -18446744073709551615, 'max': 18446744073709551615, 'step': 0.01}), 'stop': ('FLOAT', {'default': 0, 'min': -18446744073709551615, 'max': 18446744073709551615, 'step': 0.01}), 'step': ('FLOAT', {'default': 1, 'min': 0, 'max': 99999, 'step': 0.01})}, 'optional': {'reset_bool': ('NUMBER',)}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') + RETURN_TYPES = ('NUMBER', 'FLOAT', 'INT') + RETURN_NAMES = ('number', 'float', 'int') + FUNCTION = 'increment_number' + CATEGORY = 'WAS Suite/Number' + + def increment_number(self, number_type, mode, start, stop, step, unique_id, reset_bool=0): + counter = int(start) if mode == 'integer' else start + if self.counters.__contains__(unique_id): + counter = self.counters[unique_id] + if round(reset_bool) >= 1: + counter = start + if mode == 'increment': + counter += step + elif mode == 'deccrement': + counter -= step + elif mode == 'increment_to_stop': + counter = counter + step if counter < stop else counter + elif mode == 'decrement_to_stop': + counter = counter - step if counter > stop else counter + self.counters[unique_id] = counter + result = int(counter) if number_type == 'integer' else float(counter) + return (result, float(counter), int(counter)) +``` \ No newline at end of file diff --git a/docs/Number Input Condition.md b/docs/Number Input Condition.md new file mode 100644 index 0000000..4f310b5 --- /dev/null +++ b/docs/Number Input Condition.md @@ -0,0 +1,126 @@ +# Documentation +- Class name: WAS_Number_Input_Condition +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 `number_input_condition` 旨在基于一组输入参数评估数值条件。它执行逻辑运算和比较以确定结果,该结果可以是布尔值或数值类型,具体取决于指定的返回类型。此节点功能多样,可以处理各种数学和逻辑运算,适用于广泛的数值分析任务。 + +# Input types +## Required +- number_a + - 用于比较操作的第一个数字。它在确定所评估的逻辑条件的结果中起着关键作用。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float] +- number_b + - 参与比较的第二个数字。它对于节点执行的逻辑运算至关重要。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float] +## Optional +- return_boolean + - 确定方法是否应根据比较结果返回布尔值(真或假)或数值类型。 + - Comfy dtype: COMBO['false', 'true'] + - Python dtype: str +- comparison + - 指定要对两个数字执行的逻辑比较或操作的类型。 + - Comfy dtype: COMBO['and', 'or', 'greater-than', 'greater-than or equals', 'less-than', 'less-than or equals', 'equals', 'does not equal', 'divisible by', 'if A odd', 'if A even', 'if A prime', 'factor of'] + - Python dtype: str + +# Output types +- result + - 逻辑条件评估的结果,根据 'return_boolean' 参数,可以是数值或布尔值。 + - Comfy dtype: COMBO['NUMBER', 'FLOAT', 'INT'] + - Python dtype: Union[int, float, bool] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Number_Input_Condition: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number_a': ('NUMBER',), 'number_b': ('NUMBER',), 'return_boolean': (['false', 'true'],), 'comparison': (['and', 'or', 'greater-than', 'greater-than or equals', 'less-than', 'less-than or equals', 'equals', 'does not equal', 'divisible by', 'if A odd', 'if A even', 'if A prime', 'factor of'],)}} + RETURN_TYPES = ('NUMBER', 'FLOAT', 'INT') + FUNCTION = 'number_input_condition' + CATEGORY = 'WAS Suite/Logic' + + def number_input_condition(self, number_a, number_b, return_boolean='false', comparison='greater-than'): + if comparison: + if return_boolean == 'true': + if comparison == 'and': + result = 1 if number_a != 0 and number_b != 0 else 0 + elif comparison == 'or': + result = 1 if number_a != 0 or number_b != 0 else 0 + elif comparison == 'greater-than': + result = 1 if number_a > number_b else 0 + elif comparison == 'greater-than or equals': + result = 1 if number_a >= number_b else 0 + elif comparison == 'less-than': + result = 1 if number_a < number_b else 0 + elif comparison == 'less-than or equals': + result = 1 if number_a <= number_b else 0 + elif comparison == 'equals': + result = 1 if number_a == number_b else 0 + elif comparison == 'does not equal': + result = 1 if number_a != number_b else 0 + elif comparison == 'divisible by': + result = 1 if number_b % number_a == 0 else 0 + elif comparison == 'if A odd': + result = 1 if number_a % 2 != 0 else 0 + elif comparison == 'if A even': + result = 1 if number_a % 2 == 0 else 0 + elif comparison == 'if A prime': + result = 1 if self.is_prime(number_a) else 0 + elif comparison == 'factor of': + result = 1 if number_b % number_a == 0 else 0 + else: + result = 0 + elif comparison == 'and': + result = number_a if number_a != 0 and number_b != 0 else number_b + elif comparison == 'or': + result = number_a if number_a != 0 or number_b != 0 else number_b + elif comparison == 'greater-than': + result = number_a if number_a > number_b else number_b + elif comparison == 'greater-than or equals': + result = number_a if number_a >= number_b else number_b + elif comparison == 'less-than': + result = number_a if number_a < number_b else number_b + elif comparison == 'less-than or equals': + result = number_a if number_a <= number_b else number_b + elif comparison == 'equals': + result = number_a if number_a == number_b else number_b + elif comparison == 'does not equal': + result = number_a if number_a != number_b else number_b + elif comparison == 'divisible by': + result = number_a if number_b % number_a == 0 else number_b + elif comparison == 'if A odd': + result = number_a if number_a % 2 != 0 else number_b + elif comparison == 'if A even': + result = number_a if number_a % 2 == 0 else number_b + elif comparison == 'if A prime': + result = number_a if self.is_prime(number_a) else number_b + elif comparison == 'factor of': + result = number_a if number_b % number_a == 0 else number_b + else: + result = number_a + return (result, float(result), int(result)) + + def is_prime(self, n): + if n <= 1: + return False + elif n <= 3: + return True + elif n % 2 == 0 or n % 3 == 0: + return False + i = 5 + while i * i <= n: + if n % i == 0 or n % (i + 2) == 0: + return False + i += 6 + return True +``` \ No newline at end of file diff --git a/docs/Number Input Switch.md b/docs/Number Input Switch.md new file mode 100644 index 0000000..be66e4e --- /dev/null +++ b/docs/Number Input Switch.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: WAS_Number_Input_Switch +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 `number_input_switch` 旨在根据布尔条件处理数值输入。它巧妙地展示了节点执行条件逻辑操作的能力,为处理数值数据提供了一种多功能的方法。节点的功能集中在其决策能力上,允许以可控和可预测的方式操作数字。 + +# Input types +## Required +- number_a + - 参数 `number_a` 对节点的操作至关重要,因为它代表了节点将处理的第一个数值输入。它的作用很重要,因为它决定了节点决策过程的初始数据集。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float] +- number_b + - 参数 `number_b` 作为节点的另一种数值输入。它的重要性在于提供一组不同的数值,当布尔条件不满足时,节点可以使用这些数值。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float] +## Optional +- boolean + - 参数 `boolean` 作为一个开关,决定了节点的行为。它对于确定将由节点处理的数值输入集至关重要,从而影响节点的输出。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- output + - 方法 `number_input_switch` 的输出是一个包含原始数字、其浮点表示和整数形式的元组。这种全面的输出提供了对处理过的数值数据的多方面视图,满足各种下游需求。 + - Comfy dtype: COMBO[NUMBER, FLOAT, INT] + - Python dtype: Tuple[Union[int, float], float, int] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Number_Input_Switch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number_a': ('NUMBER',), 'number_b': ('NUMBER',), 'boolean': ('BOOLEAN', {'forceInput': True})}} + RETURN_TYPES = ('NUMBER', 'FLOAT', 'INT') + FUNCTION = 'number_input_switch' + CATEGORY = 'WAS Suite/Logic' + + def number_input_switch(self, number_a, number_b, boolean=True): + if boolean: + return (number_a, float(number_a), int(number_a)) + else: + return (number_b, float(number_b), int(number_b)) +``` \ No newline at end of file diff --git a/docs/Number Multiple Of.md b/docs/Number Multiple Of.md new file mode 100644 index 0000000..1cb3456 --- /dev/null +++ b/docs/Number Multiple Of.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: WAS_Number_Multiple_Of +- Category: WAS Suite/Number/Functions +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 'number_multiple_of' 旨在确定给定的数字是否为另一个指定数字的倍数。如果不是,该方法会计算最近的倍数。这种功能在需要进行进一步处理或数学运算的倍数场景中至关重要。 + +# Input types +## Required +- number + - 参数 'number' 是要检查是否为 'multiple' 的倍数的值。它在节点的操作中起着关键作用,因为它是倍数检查和随后计算的主题。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float] +## Optional +- multiple + - 参数 'multiple' 定义了用于确定 'number' 是否为倍数的除数。它很重要,因为它决定了 'number' 要比较的具体倍数。默认值为 8,确保了在不指定此参数的情况下可以使用节点。 + - Comfy dtype: INT + - Python dtype: Optional[int] + +# Output types +- result + - 参数 'result' 表示 'number_multiple_of' 方法的结果。如果输入的 'number' 原本不是 'multiple' 的倍数,它就是最接近的倍数。这个结果对于任何需要倍数的后续操作都很重要。 + - Comfy dtype: COMBO[NUMBER, FLOAT, INT] + - Python dtype: Union[int, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Number_Multiple_Of: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number': ('NUMBER',), 'multiple': ('INT', {'default': 8, 'min': -18446744073709551615, 'max': 18446744073709551615})}} + RETURN_TYPES = ('NUMBER', 'FLOAT', 'INT') + FUNCTION = 'number_multiple_of' + CATEGORY = 'WAS Suite/Number/Functions' + + def number_multiple_of(self, number, multiple=8): + if number % multiple != 0: + return (number // multiple * multiple + multiple,) + return (number, number, int(number)) +``` \ No newline at end of file diff --git a/docs/Number Operation.md b/docs/Number Operation.md new file mode 100644 index 0000000..ebd558a --- /dev/null +++ b/docs/Number Operation.md @@ -0,0 +1,92 @@ +# Documentation +- Class name: WAS_Number_Operation +- Category: WAS Suite/Number/Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Number_Operation节点旨在对两个输入数字执行多种数学运算。它支持加法、减法、除法等操作,为数值计算提供了一种多功能工具。 + +# Input types +## Required +- number_a + - 数学运算的第一个操作数,可以是整数或浮点数。它在确定运算结果中起着关键作用。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float] +- number_b + - 数学运算的第二个操作数,也是一个整数或浮点数。它对计算至关重要,并影响最终结果。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float] +## Optional +- operation + - 指定要执行的数学运算类型。操作的选择直接影响计算和产生的结果类型。 + - Comfy dtype: COMBO['addition', 'subtraction', 'division', 'floor division', 'multiplication', 'exponentiation', 'modulus', 'greater-than', 'greater-than or equals', 'less-than', 'less-than or equals', 'equals', 'does not equal'] + - Python dtype: str + +# Output types +- result + - 数学运算的结果,可以是一个数字、一个浮点值或一个整数,这取决于执行的操作。 + - Comfy dtype: COMBO[NUMBER, FLOAT, INT] + - Python dtype: Union[int, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Number_Operation: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number_a': ('NUMBER',), 'number_b': ('NUMBER',), 'operation': (['addition', 'subtraction', 'division', 'floor division', 'multiplication', 'exponentiation', 'modulus', 'greater-than', 'greater-than or equals', 'less-than', 'less-than or equals', 'equals', 'does not equal'],)}} + RETURN_TYPES = ('NUMBER', 'FLOAT', 'INT') + FUNCTION = 'math_operations' + CATEGORY = 'WAS Suite/Number/Operations' + + def math_operations(self, number_a, number_b, operation='addition'): + if operation: + if operation == 'addition': + result = number_a + number_b + return (result, result, int(result)) + elif operation == 'subtraction': + result = number_a - number_b + return (result, result, int(result)) + elif operation == 'division': + result = number_a / number_b + return (result, result, int(result)) + elif operation == 'floor division': + result = number_a // number_b + return (result, result, int(result)) + elif operation == 'multiplication': + result = number_a * number_b + return (result, result, int(result)) + elif operation == 'exponentiation': + result = number_a ** number_b + return (result, result, int(result)) + elif operation == 'modulus': + result = number_a % number_b + return (result, result, int(result)) + elif operation == 'greater-than': + result = +(number_a > number_b) + return (result, result, int(result)) + elif operation == 'greater-than or equals': + result = +(number_a >= number_b) + return (result, result, int(result)) + elif operation == 'less-than': + result = +(number_a < number_b) + return (result, result, int(result)) + elif operation == 'less-than or equals': + result = +(number_a <= number_b) + return (result, result, int(result)) + elif operation == 'equals': + result = +(number_a == number_b) + return (result, result, int(result)) + elif operation == 'does not equal': + result = +(number_a != number_b) + return (result, result, int(result)) + else: + cstr('Invalid number operation selected.').error.print() + return (number_a, number_a, int(number_a)) +``` \ No newline at end of file diff --git a/docs/Number PI.md b/docs/Number PI.md new file mode 100644 index 0000000..a97aa2c --- /dev/null +++ b/docs/Number PI.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_Number_PI +- Category: WAS Suite/Number +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Number_PI 节点的 `number_pi` 方法提供了数学常数π的值。它旨在提供这个基本数学常数的可靠来源,在几何学、三角学和工程学等不同领域的各种计算中至关重要。 + +# Input types +## Optional +- None + - 该节点不需要任何输入参数。它被设计为在不需要外部输入的情况下返回π的值,使其成为访问这个数学常数的自包含函数。 + - Comfy dtype: None + - Python dtype: None + +# Output types +- pi_value + - number_pi 方法的输出是数学常数π,它被表示为一个浮点数。这个值对于广泛的数学和科学应用至关重要,在这些应用中精度是至关重要的。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Number_PI: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}} + RETURN_TYPES = ('NUMBER', 'FLOAT') + FUNCTION = 'number_pi' + CATEGORY = 'WAS Suite/Number' + + def number_pi(self): + return (math.pi, math.pi) +``` \ No newline at end of file diff --git a/docs/Number to Float.md b/docs/Number to Float.md new file mode 100644 index 0000000..5ea6878 --- /dev/null +++ b/docs/Number to Float.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_Number_To_Float +- Category: WAS Suite/Number/Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Number_To_Float节点旨在将输入的数字转换为它们的浮点数等价物。此节点通过确保数字一致性和兼容性,对于下游操作的数据预处理起着至关重要的作用。 + +# Input types +## Required +- number + - ‘number’参数对于节点的操作至关重要,因为它是将要转换为浮点数的输入。这种转换对于保持数值精度和促进进一步的数学计算具有重要意义。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float, str] + +# Output types +- float_number + - ‘float_number’输出是转换过程的结果,提供了输入数字的浮点表示。这个输出对于任何需要小数精度的后续数值分析或操作至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Number_To_Float: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number': ('NUMBER',)}} + RETURN_TYPES = ('FLOAT',) + FUNCTION = 'number_to_float' + CATEGORY = 'WAS Suite/Number/Operations' + + def number_to_float(self, number): + return (float(number),) +``` \ No newline at end of file diff --git a/docs/Number to Int.md b/docs/Number to Int.md new file mode 100644 index 0000000..c83c001 --- /dev/null +++ b/docs/Number to Int.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_Number_To_Int +- Category: WAS Suite/Number/Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Number_To_Int节点的'number_to_int'方法旨在将输入的数字转换为它们的整数等价物。它在数据预处理中扮演着关键角色,通过确保数值一致性并促进进一步的数值运算来发挥作用。 + +# Input types +## Required +- number + - “number”参数对于节点的操作至关重要,因为它是要被转换为整数的输入。它之所以重要,是因为转换的准确性和完整性取决于此输入的质量。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float, str] + +# Output types +- int_value + - 'int_value'输出代表了输入数字的整数转换结果。它之所以重要,是因为它直接反映了节点的主要功能的结果,为后续流程提供了一致且可用的格式。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Number_To_Int: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number': ('NUMBER',)}} + RETURN_TYPES = ('INT',) + FUNCTION = 'number_to_int' + CATEGORY = 'WAS Suite/Number/Operations' + + def number_to_int(self, number): + return (int(number),) +``` \ No newline at end of file diff --git a/docs/Number to Seed.md b/docs/Number to Seed.md new file mode 100644 index 0000000..52d888b --- /dev/null +++ b/docs/Number to Seed.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_Number_To_Seed +- Category: WAS Suite/Number/Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Number_To_Seed节点旨在将数值转换为种子格式。它是WAS套件中的基础工具,促进了需要基于种子的方法的操作。该节点抽象了种子生成的复杂性,确保与依赖种子输入的下游流程无缝集成。 + +# Input types +## Required +- number + - ‘number’参数对于节点的操作至关重要,因为它是节点将转换为种子的输入数值。它在确定输出种子的特性中起着关键作用,这可以显著影响WAS套件中使用此种子的后续流程。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float] + +# Output types +- seed + - ‘seed’输出是WAS_Number_To_Seed节点产生的一个关键元素。它代表了从输入数字转换而来的种子,对于启动WAS套件内需要种子以执行的过程至关重要。 + - Comfy dtype: SEED + - Python dtype: Dict[str, Union[int, float]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Number_To_Seed: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number': ('NUMBER',)}} + RETURN_TYPES = ('SEED',) + FUNCTION = 'number_to_seed' + CATEGORY = 'WAS Suite/Number/Operations' + + def number_to_seed(self, number): + return ({'seed': number},) +``` \ No newline at end of file diff --git a/docs/Number to String.md b/docs/Number to String.md new file mode 100644 index 0000000..b609fe6 --- /dev/null +++ b/docs/Number to String.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_Number_To_String +- Category: WAS Suite/Number/Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Number_To_String节点旨在将数值转换为相应的字符串表示形式。此节点在数据预处理和转换工作流程中起着至关重要的作用,使数值数据能够无缝集成到需要文本输入的系统中。 + +# Input types +## Required +- number + - ‘number’参数对于节点的操作至关重要,因为它是需要转换成字符串的输入数值。它通过决定输出字符串的内容显著影响节点的执行。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float] + +# Output types +- string + - ‘string’输出参数表示输入数字的文本形式。它很重要,因为它提供了可以用于各种下游应用或流程的转换后数据。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Number_To_String: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number': ('NUMBER',)}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'number_to_string' + CATEGORY = 'WAS Suite/Number/Operations' + + def number_to_string(self, number): + return (str(number),) +``` \ No newline at end of file diff --git a/docs/Number to Text.md b/docs/Number to Text.md new file mode 100644 index 0000000..2db93d1 --- /dev/null +++ b/docs/Number to Text.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_Number_To_Text +- Category: WAS Suite/Number/Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +该节点将数字输入转换为文本表示,使得数字可以被下游节点或应用程序更容易理解和使用。 + +# Input types +## Required +- number + - ‘number’参数对于节点的操作至关重要,因为它作为将被转换为文本的输入。这是节点执行其主要功能的必要条件。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float, complex] + +# Output types +- text + - 输出‘text’表示输入数字的文本表示形式,是节点转换过程的结果。 + - Comfy dtype: TEXT + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Number_To_Text: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number': ('NUMBER',)}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'number_to_text' + CATEGORY = 'WAS Suite/Number/Operations' + + def number_to_text(self, number): + return (str(number),) +``` \ No newline at end of file diff --git a/docs/ONNXDetectorProvider.md b/docs/ONNXDetectorProvider.md new file mode 100644 index 0000000..da2a207 --- /dev/null +++ b/docs/ONNXDetectorProvider.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: ONNXDetectorProvider +- Category: ImpactPack +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ONNXDetectorProvider节点旨在方便加载和提供用于检测任务的ONNX模型。它作为将基于ONNX的检测模型集成到工作流程中的接口,抽象了模型加载和设置的复杂性。 + +# Input types +## Required +- model_name + - model_name参数对于识别要加载的特定ONNX模型至关重要。它确保使用了正确的模型进行检测任务,从而影响节点的执行和结果的准确性。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- BBOX_DETECTOR + - BBOX_DETECTOR输出提供了一个配置好的ONNXDetector对象,用于执行对象检测任务。该对象封装了ONNX模型的功能,是检测过程中的核心组件。 + - Comfy dtype: ONNXDetector + - Python dtype: ONNXDetector + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ONNXDetectorProvider: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model_name': (folder_paths.get_filename_list('onnx'),)}} + RETURN_TYPES = ('BBOX_DETECTOR',) + FUNCTION = 'load_onnx' + CATEGORY = 'ImpactPack' + + def load_onnx(self, model_name): + model = folder_paths.get_full_path('onnx', model_name) + return (core.ONNXDetector(model),) +``` \ No newline at end of file diff --git a/docs/ONNXDetectorSEGS.md b/docs/ONNXDetectorSEGS.md new file mode 100644 index 0000000..18479f4 --- /dev/null +++ b/docs/ONNXDetectorSEGS.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: BboxDetectorForEach +- Category: ImpactPack/Detector +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +BboxDetectorForEach节点旨在检测图像中每个段的边界框。它利用bbox_detector根据提供的阈值和其他参数识别和定位段,确保只检测到最相关的段。该节点在段检测工作流程中扮演着关键角色,通过自动化识别和隔离图像中的特定感兴趣区域来简化流程。 + +# Input types +## Required +- bbox_detector + - bbox_detector是节点的关键组件,负责在图像中实际检测边界框。它对节点的执行至关重要,因为它直接影响检测过程的准确性和效率。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: torch.nn.Module +- image + - image参数是节点的输入数据,bbox_detector使用它来执行其检测任务。它是节点操作的基础,因为图像的质量和分辨率可以显著影响检测结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- threshold + - 阈值参数决定了bbox_detector在识别边界框时的灵敏度。它是一个重要的调整因素,可以影响检测到的段的数量和检测的精度。 + - Comfy dtype: FLOAT + - Python dtype: float +- dilation + - 膨胀参数控制检测到的边界框的扩展。它在检测后处理中起着重要作用,可能增强检测到的段的覆盖范围。 + - Comfy dtype: INT + - Python dtype: int +- crop_factor + - crop_factor参数用于调整检测后的裁剪段的大小。它对于微调分割过程以满足特定应用需求至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- drop_size + - drop_size参数指定在检测过程中要考虑的段的最小大小。它对于过滤掉噪声和无关数据至关重要,因此可以提高检测质量。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- labels + - labels参数允许指定要检测的段类型。它是一个可选但有用的特性,用于集中检测特定的感兴趣的段。 + - Comfy dtype: STRING + - Python dtype: str +- detailer_hook + - detailer_hook参数提供了一种机制,用于对检测到的边界框进行自定义后处理。它是一个高级特性,可用于将额外的处理步骤集成到检测工作流程中。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: Callable + +# Output types +- segs + - segs输出包含图像中检测到的段,每个段都带有其边界框信息。这是节点操作的主要结果,对于进一步的分析或处理至关重要。 + - Comfy dtype: SEGS + - Python dtype: List[impact.core.SEG] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BboxDetectorForEach: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'bbox_detector': ('BBOX_DETECTOR',), 'image': ('IMAGE',), 'threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'dilation': ('INT', {'default': 10, 'min': -512, 'max': 512, 'step': 1}), 'crop_factor': ('FLOAT', {'default': 3.0, 'min': 1.0, 'max': 100, 'step': 0.1}), 'drop_size': ('INT', {'min': 1, 'max': MAX_RESOLUTION, 'step': 1, 'default': 10}), 'labels': ('STRING', {'multiline': True, 'default': 'all', 'placeholder': 'List the types of segments to be allowed, separated by commas'})}, 'optional': {'detailer_hook': ('DETAILER_HOOK',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detector' + + def doit(self, bbox_detector, image, threshold, dilation, crop_factor, drop_size, labels=None, detailer_hook=None): + if len(image) > 1: + raise Exception('[Impact Pack] ERROR: BboxDetectorForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.') + segs = bbox_detector.detect(image, threshold, dilation, crop_factor, drop_size, detailer_hook) + if labels is not None and labels != '': + labels = labels.split(',') + if len(labels) > 0: + (segs, _) = segs_nodes.SEGSLabelFilter.filter(segs, labels) + return (segs,) +``` \ No newline at end of file diff --git a/docs/OOTDGenerate.md b/docs/OOTDGenerate.md new file mode 100644 index 0000000..e8d458e --- /dev/null +++ b/docs/OOTDGenerate.md @@ -0,0 +1,95 @@ +# Documentation +- Class name: OOTDGenerate +- Category: OOTD +- Output node: False +- Repo Ref: https://github.com/AuroBit/ComfyUI-OOTDiffusion.git + +该节点旨在根据输入的图像和类别合成服装,利用扩散模型进行创意时尚生成。它旨在为用户提供多样化的、与上下文相关的、风格一致的服装选项。 + +# Input types +## Required +- pipe + - pipe参数至关重要,它封装了用于生成服装的扩散模型。它是节点功能的主干,决定了生成的服装的质量和类型。 + - Comfy dtype: MODEL + - Python dtype: OOTDiffusion +- cloth_image + - cloth_image参数作为生成服装的基础。它对于节点理解上下文并合成与所提供图像视觉一致的服装至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- model_image + - model_image参数用于提供生成服装中人物形象的模板。这对于保持服装的结构完整性和与人体形态的真实比例非常重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- seed + - seed参数在生成服装的过程中引入随机性,允许出现多种结果。这对于寻求独特且不重复的时尚选项的用户来说非常关键。 + - Comfy dtype: INT + - Python dtype: int +- steps + - steps参数决定了扩散过程中使用的迭代次数。它影响最终生成服装的细节和精细程度,更多的步骤会带来更加细腻的结果。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数调整生成过程中使用的图像比例,这影响生成服装的分辨率和清晰度。它是实现高质量视觉效果的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- category + - category参数指定要生成的服装类型,指导节点生成与选定时尚类别相符的服装。它对于确保生成内容的相关性和适当性至关重要。 + - Comfy dtype: LIST + - Python dtype: List[str] + +# Output types +- image + - image输出展示了最终生成的服装,展示了基于输入的时尚元素的创意合成。它是节点操作的主要结果,代表了服装概念的实现。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image_masked + - image_masked输出提供了一个应用了特定时尚元素遮罩的生成服装版本。这个输出对于需要对生成内容进行详细控制的用户来说非常重要,允许进一步的定制和操作。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class OOTDGenerate: + display_name = 'OOTDiffusion Generate' + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('MODEL',), 'cloth_image': ('IMAGE',), 'model_image': ('IMAGE',), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'cfg': ('FLOAT', {'default': 2.0, 'min': 0.0, 'max': 14.0, 'step': 0.1, 'round': 0.01}), 'category': (list(_category_readable.keys()),)}} + RETURN_TYPES = ('IMAGE', 'IMAGE') + RETURN_NAMES = ('image', 'image_masked') + FUNCTION = 'generate' + CATEGORY = 'OOTD' + + def generate(self, pipe: OOTDiffusion, cloth_image, model_image, category, seed, steps, cfg): + category = _category_readable[category] + if pipe.model_type == 'hd' and category != 'upperbody': + raise ValueError('Half body (hd) model type can only be used with upperbody category') + model_image = model_image.squeeze(0) + model_image = model_image.permute((2, 0, 1)) + model_image = to_pil_image(model_image) + if model_image.size != (768, 1024): + print(f'Inconsistent model_image size {model_image.size} != (768, 1024)') + model_image = model_image.resize((768, 1024)) + cloth_image = cloth_image.squeeze(0) + cloth_image = cloth_image.permute((2, 0, 1)) + cloth_image = to_pil_image(cloth_image) + if cloth_image.size != (768, 1024): + print(f'Inconsistent cloth_image size {cloth_image.size} != (768, 1024)') + cloth_image = cloth_image.resize((768, 1024)) + (model_parse, _) = pipe.parsing_model(model_image.resize((384, 512))) + keypoints = pipe.openpose_model(model_image.resize((384, 512))) + (mask, mask_gray) = get_mask_location(pipe.model_type, _category_get_mask_input[category], model_parse, keypoints, width=384, height=512) + mask = mask.resize((768, 1024), Image.NEAREST) + mask_gray = mask_gray.resize((768, 1024), Image.NEAREST) + masked_vton_img = Image.composite(mask_gray, model_image, mask) + images = pipe(category=category, image_garm=cloth_image, image_vton=masked_vton_img, mask=mask, image_ori=model_image, num_samples=1, num_steps=steps, image_scale=cfg, seed=seed) + output_image = to_tensor(images[0]) + output_image = output_image.permute((1, 2, 0)).unsqueeze(0) + masked_vton_img = masked_vton_img.convert('RGB') + masked_vton_img = to_tensor(masked_vton_img) + masked_vton_img = masked_vton_img.permute((1, 2, 0)).unsqueeze(0) + return (output_image, masked_vton_img) +``` \ No newline at end of file diff --git a/docs/OffsetImage.md b/docs/OffsetImage.md new file mode 100644 index 0000000..2a0d634 --- /dev/null +++ b/docs/OffsetImage.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: OffsetImage +- Category: image +- Output node: False +- Repo Ref: https://github.com/spinagon/ComfyUI-seamless-tiling + +OffsetImage节点旨在对输入图像执行平移操作,根据提供的x和y轴百分比值来移动像素。该节点在创建视觉效果中非常重要,可用于对齐、组合或数据增强等不同的图像处理任务。 + +# Input types +## Required +- pixels + - ‘pixels’参数是OffsetImage节点的主要输入,代表将被操作的图像数据。它对节点的操作至关重要,因为它决定了将要被平移的内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- x_percent + - ‘x_percent’参数指定沿x轴移动像素的图像宽度的百分比。它影响操作后图像的水平位置。 + - Comfy dtype: FLOAT + - Python dtype: float +- y_percent + - ‘y_percent’参数决定沿y轴移动像素的图像高度的百分比。它对于确定图像平移后垂直位置的确定非常重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- offset_image + - ‘offset_image’输出是将平移应用于输入图像的结果。它代表了移动后的图像,可以用于进一步处理或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class OffsetImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pixels': ('IMAGE',), 'x_percent': ('FLOAT', {'default': 50.0, 'min': 0.0, 'max': 100.0, 'step': 1}), 'y_percent': ('FLOAT', {'default': 50.0, 'min': 0.0, 'max': 100.0, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'run' + CATEGORY = 'image' + + def run(self, pixels, x_percent, y_percent): + (n, y, x, c) = pixels.size() + y = round(y * y_percent / 100) + x = round(x * x_percent / 100) + return (pixels.roll((y, x), (1, 2)),) +``` \ No newline at end of file diff --git a/docs/OneButtonPrompt.md b/docs/OneButtonPrompt.md new file mode 100644 index 0000000..50b3c17 --- /dev/null +++ b/docs/OneButtonPrompt.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: OneButtonPrompt +- Category: OneButtonPrompt +- Output node: False +- Repo Ref: https://github.com/AIrjen/OneButtonPrompt + +该节点旨在根据各种输入参数生成动态提示,旨在为内容创作产生多样化和引人入胜的输出。它结合了主题、艺术风格和环境背景等元素,以产生具有内聚性和丰富主题的提示。 + +# Input types +## Required +- insanitylevel + - 该参数决定了生成提示的复杂性和精细度,更高级别将导致更详细和微妙的输出。它直接影响提示中包含的元素的多样性和深度。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- artist + - 艺术家参数允许指定特定的艺术风格或创作者,指导生成提示的审美和主题方向。 + - Comfy dtype: COMBO + - Python dtype: str +- imagetype + - 该参数设置了期望的图像或视觉表现形式的类型,影响生成内容的媒介、风格和整体视觉方法。 + - Comfy dtype: COMBO + - Python dtype: str +- subject + - 主题参数在确定生成提示的主要焦点或主题方面至关重要,影响叙事、人物和设定元素。 + - Comfy dtype: COMBO + - Python dtype: str +- imagemodechance + - 该参数调整了在提示中包含某些图像模式的可能性,从而影响视觉方面的多样性和创造性。 + - Comfy dtype: INT + - Python dtype: int +- custom_subject + - 自定义主题参数允许输入用户希望关注的具体主题,确保生成的提示针对他们的兴趣进行定制。 + - Comfy dtype: STRING + - Python dtype: str +- custom_outfit + - 该参数使用户能够为主题指定特定的服装或服饰,为生成的提示增添个性化的触感。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- prompt + - 输出是一个综合性和创造性构建的提示,涵盖了输入参数,为内容创作提供了丰富的基础。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class OneButtonPrompt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'insanitylevel': ('INT', {'default': 5, 'min': 1, 'max': 10, 'step': 1})}, 'optional': {'artist': (artists, {'default': 'all'}), 'imagetype': (imagetypes, {'default': 'all'}), 'imagemodechance': ('INT', {'default': 20, 'min': 1, 'max': 100, 'step': 1}), 'subject': (subjects, {'default': 'all'}), 'custom_subject': ('STRING', {'multiline': False, 'default': ''}), 'custom_outfit': ('STRING', {'multiline': False, 'default': ''}), 'subject_subtype_objects': (subjectsubtypesobject, {'default': 'all'}), 'subject_subtypes_humanoids': (subjectsubtypeshumanoid, {'default': 'all'}), 'humanoids_gender': (genders, {'default': 'all'}), 'subject_subtypes_concepts': (subjectsubtypesconcept, {'default': 'all'}), 'emojis': (emojis, {'default': False}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('STRING', 'STRING', 'STRING') + RETURN_NAMES = ('prompt', 'prompt_g', 'prompt_l') + FUNCTION = 'Comfy_OBP' + CATEGORY = 'OneButtonPrompt' + + def Comfy_OBP(self, insanitylevel, custom_subject, seed, artist, imagetype, subject, imagemodechance, humanoids_gender, subject_subtype_objects, subject_subtypes_humanoids, subject_subtypes_concepts, emojis, custom_outfit): + generatedpromptlist = build_dynamic_prompt(insanitylevel, subject, artist, imagetype, False, '', '', '', 1, '', custom_subject, True, '', imagemodechance, humanoids_gender, subject_subtype_objects, subject_subtypes_humanoids, subject_subtypes_concepts, False, emojis, seed, custom_outfit, True) + generatedprompt = generatedpromptlist[0] + prompt_g = generatedpromptlist[1] + prompt_l = generatedpromptlist[2] + return (generatedprompt, prompt_g, prompt_l) +``` \ No newline at end of file diff --git a/docs/OobaPrompt.md b/docs/OobaPrompt.md new file mode 100644 index 0000000..3ad8fe2 --- /dev/null +++ b/docs/OobaPrompt.md @@ -0,0 +1,101 @@ +# Documentation +- Class name: OobaPrompt +- Category: Mikey/AI +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +OobaPrompt节点旨在通过处理提示并与AI文本到图像模型交互,生成详细的图像描述。它通过各种模式如'prompt'(提示)、'style'(风格)、'descriptor'(描述符)和'character'(角色)增强输入提示,以引导AI模型创建特定类型的图像。该节点还能够处理自定义历史记录和种子,以在输出中产生随机变化。 + +# Input types +## Required +- input_prompt + - 输入提示是节点的关键参数,因为它直接影响AI模型对要生成的图像的理解。它应该是一段描述性文本,清晰地描绘出所需图像的样貌。 + - Comfy dtype: STRING + - Python dtype: str +- mode + - 模式决定了节点将对输入提示执行的类型处理。每种模式对应于增强提示的不同方式,以实现特定的图像生成结果。 + - Comfy dtype: ['prompt', 'style', 'descriptor', 'character', 'negative', 'custom'] + - Python dtype: str +## Optional +- custom_history + - 当用户想要提供一组个性化的提示以影响AI模型时,使用自定义历史记录。它应该指向包含历史提示数据的文件。 + - Comfy dtype: STRING + - Python dtype: str +- seed + - 种子参数对于生成可复现的图像序列非常重要。它确保相同的输入提示在给定相同的种子值时将产生相同的输出。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- text + - 输出文本是通过AI模型处理输入提示的结果。它代表了AI模型用来生成图像的详细描述。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class OobaPrompt: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input_prompt': ('STRING', {'multiline': True, 'default': 'Prompt Text Here', 'dynamicPrompts': False}), 'mode': (['prompt', 'style', 'descriptor', 'character', 'negative', 'custom'], {'default': 'prompt'}), 'custom_history': ('STRING', {'multiline': False, 'default': 'path to history.json', 'dynamicPrompts': True}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('text',) + FUNCTION = 'process' + CATEGORY = 'Mikey/AI' + + def history(self, mode, custom_history): + if mode == 'prompt': + return {'internal': [['<|BEGIN-VISIBLE-CHAT|>', 'How can I help you today?'], ["I say something like 'blonde woman' and you respond with a single prompt which I can use as prompts for an AI txt2image model. Your response to blonde woman would be something like 'Blonde woman wearing a patterned orange, white, and blue sundress, smiling, on a sunny day with a blue sky, surrounded by buildings and palm trees'. It describes the image with lots of details so the AI model will understand what it needs to generate.", "Sure thing! Let's begin. What is your first prompt?"], ['futuristic man', 'Man with short black hair in a highly detailed silver and black mechanical exoskeleton suit, holding a futuristic rifle, standing in a futuristic city with tall buildings and flying cars, with a futuristic cityscape in the background.'], ['a black cat', 'A black cat with green eyes, sitting on a wooden table, there is a vase of flowers on the table, the cat is looking at the flowers. Sunlight is streaming in through a window, illuminating the cat and the flowers.'], ['toaster oven', 'A toaster oven with a slice of bread inside, the bread is toasted and has a smiley face burned into it. The toaster oven is sitting on a kitchen counter next to a coffee maker and a microwave. The kitchen counter is made of granite and has a sink in it. There is a window above the sink with a view of a city skyline.'], ['war', 'A soldier wearing a gas mask and a helmet, holding a rifle, standing in a trench. There is barbed wire in front of the trench. The sky is dark and cloudy. There is a tank in the background.'], ['portrait of a man', 'A portrait of a man in his 30s with short brown hair and a beard. He is wearing a suit and tie. He is smiling. He is standing in front of a brick wall with graffiti on it.'], ['a friendly ogre', 'A friendly ogre with green skin and a big smile. He is wearing a red and white striped shirt and blue overalls. He is holding a pitchfork. He is standing in a field of flowers. There is a rainbow in the sky.'], ['puppy', "A cute pug dog wearing a bowtie and reading a book. The book is titled 'How to be a good dog'. The dog is sitting on a couch in a living room. There is a fireplace in the background."], ['apples', 'Red apples stacked in a wooden crate. The crate is sitting on a wooden table in the kitchen inside a rustic farm house with old appliances. The walls are decorated with family photos. There is a window in the background with a view of the farm.'], ['working woman', 'A woman is working on a laptop computer. She is wearing a white shirt and black pants. She is sitting at a desk in a modern office with trendy furniture. She has a cup of coffee on the desk next to her.']], 'visible': [['', 'How can I help you today?']]} + elif mode == 'style': + return {'internal': [['<|BEGIN-VISIBLE-CHAT|>', 'How can I help you today?'], ["I say something like 'painting' and you respond with a single prompt which I can use as prompts for an AI txt2image model. Your response to painting would be something like 'Impressionistic, landscape, vivid colors, loose brushstrokes, beauty of nature. Inspired by Claude Monet'. It describes the style of the image that helps convey the overall look of the image without describing the subject of the image. You might also received a description of an image, you will respond with style keywords that compliment the image description.", "Sure thing! Let's begin. What is your first prompt?"], ['painting', "Realism, oil painting, dark shadows, bright highlights, focus on capturing light and texture. Inspired by Caravaggio's chiaroscuro technique"], ['Impressionism', 'Impressionism. Soft brushstrokes, fleeting moments of light and color. Landscapes, flowers, people in motion'], ['painting', 'Impressionistic, landscape, vivid colors, loose brushstrokes, beauty of nature. Inspired by Claude Monet'], ['The 2015 Audi R8 Spyder sports car is parked on a driveway outside a luxurious mansion. The car is painted in a metallic grey color. The top is down revealing the sleek interior. The car is surrounded by lush greenery and palm trees.', 'Landscape photography, vibrant saturation, dramatic shadows, golden hour lighting, inspired by the work of Peter Lik.'], ['abstract', 'Abstract expressionism, bold brushstrokes, vivid colors'], ['water', 'Water sculpture, fluid dynamics, abstract representation, in the style of Yves Klein'], ['A MacBook Pro open and displaying an email message. The keyboard is illuminated and the trackpad is being used. A man is sitting at a wooden desk in a cozy home office. There is a plant in the corner and sunlight coming in from a nearby window.', 'Still life, muted colors, soft lighting, in the style of Henri Matisse'], ['Surrealism', 'dreamlike imagery, unexpected juxtapositions, symbolic elements. features distorted or unusual forms, animals or objects transformed into otherworldly shapes'], ['Art Nouveau', 'Art Nouveau style, flowing lines, organic shapes, muted color palette, decorative elements, floral motifs.'], ['photo', 'Black and white photograph, shot using a large format camera with slow shutter speeds. Grainy texture and high contrast. Influenced by the works of Edward Hopper.'], ['photo', 'Color photograph, Soft focus, muted colors, romantic atmosphere, in the style of Edward Weston.'], ['film', 'Long shot, film still, cinematic lighting, gritty realism, inspired by the works of Gus Van Sant'], ['movie', 'Filmic storytelling, dreamlike imagery, surreal elements, poetic narratives, reminiscent of the works of David Lynch.']], 'visible': [['', 'How can I help you today?']]} + elif mode == 'descriptor': + return {'internal': [['<|BEGIN-VISIBLE-CHAT|>', 'How can I help you today?'], ["I say something like 'color' and you respond with a single prompt which I can use to build a prompt for an AI txt2image model. Your response to color would be something like 'red'. It is a very short description to add dynamic variety to the prompt.", "Sure thing! Let's begin. What is your first prompt?"], ['color', 'burnt sienna'], ['hair color', 'platinum blonde'], ['metal', 'rusted iron'], ['weather', 'bright and sunny'], ['time of day', 'crack of dawn'], ['man', 'tall and slender man with wide shoulders in his 30s'], ['ethnicity', 'Vietnamese'], ['occupation', 'Heavy diesel mechanic'], ['art style', 'crystal cubism'], ['artist', 'Camille Pissarro'], ['movie director', 'David Lynch']], 'visible': [['', 'How can I help you today?']]} + elif mode == 'character': + return {'internal': [['<|BEGIN-VISIBLE-CHAT|>', 'How can I help you today?'], ["When a user requests a character description, generate a detailed description of the character as you would expect from the writer George R. R. Martin. The description should be a suitable prompt based on the description that encapsulates the character's key visual elements for image creation using a txt2img model.", "Sure thing! Let's begin. What is your first prompt?"], ['jolly cartoon octopus', 'A cartoon octopus with a jolly demeanor in a sunshiny yellow and orange color scheme, wearing a small top hat and a polka-dotted bow tie, surrounded by intricate sculptures made of its own ink, in the midst of an undersea setting that hints at festivity and mirth.'], ['a dapper young lady spy who wears suits', 'A young 1920s lady spy with chestnut hair in a bob cut, piercing emerald eyes, wearing a tailored charcoal pinstripe suit with a white shirt and a silk tie, holding a silver cigarette case, exuding an aura of mystery and sophistication against a backdrop of Parisian nightlife.'], ['a charming robot', 'A charming robot with a sleek chrome body, art deco design elements, azure glowing eyes, and a gentle smile. Wearing a holographic bow tie and a vest painted to look like a dapper suit, engaged in performing a magic trick with a playful, inquisitive expression in an urban park setting.'], ['cartoon ant', 'A cartoon ant with a vibrant blue exoskeleton, oversized round eyes full of curiosity, wearing a leaf-green vest and a tiny fabric cap. Exhibiting an expression of wonder and excitement, amidst a backdrop of an underground ant colony bustling with activity.'], ['a cyberpunk gnome', 'A cyberpunk gnome with pale skin and cybernetic jade eyes, wearing a long tattered coat with circuitry patches and a sleek metallic pointed helmet. Surrounded by holographic screens and neon lights in a dim, cluttered workshop filled with futuristic gadgets and data screens.']], 'visible': [['', 'How can I help you today?']]} + elif mode == 'negative': + return {'internal': [['<|BEGIN-VISIBLE-CHAT|>', 'How can I help you today?'], ["I provide a prompt for a text to image AI model, and you will respond with a prompt that helps to improve the quality of the image.The prompt contains styles you don't want to see in the image. For example if the user asks for a photo, the your response would contain terms such as 'cartoon, illustration, 3d render'.The word 'no' is forbidden!. Do not repeat yourself, do not provide similar but different words. Do not provide sentences, just words separated by commas. Keep it short.", "Sure thing! Let's begin. What is your first prompt?"], ['breathtaking image of a woman in a red dress. award-winning, professional, highly detailed', 'ugly, deformed, noisy, blurry, distorted, grainy, plain background, monochrome, signature, watermark.'], ['concept art. digital artwork, illustrative, painterly, matte painting, highly detailed', 'photo, photorealistic, realism, ugly, signature.'], ['3d model, unreal engine, textures, volumetric lighting, raytraced rendering, subject centered', 'watermark, 2D, low poly, polygon mesh, cartoon, trypophobia, miniature, traditional art, logo.'], ['comic book art, onomatopoeic graphics, halftone dots, color separation, bold lines, reminiscent of art from Marvel, DC, Dark Horse, Image, and other comic book publishers', 'photo, photorealistic, realism, ugly, signature.'], ['dark fantasy art, gothic themes, macabre, horror, dark, gloomy, sinister, ominous, eerie', 'watermark, bright colors, cheerful, happy, cute, cartoon, anime, digital art, 3d render, photograph, 2d art.'], ['charcoal drawing, rich blacks, contrasting whites, smudging, erasure, hatching, cross-hatching, tonal values, rough texture', 'photograph, painting, watercolor, colorful, 3d render, cartoon, anime, digital art.'], ['stunning photograph of a tiger in a tropical rainforest', 'black and white, cartoon, illustration, low resolution, noisy, blurry, desaturated, ugly, deformed.']], 'visible': [['', 'How can I help you today?']]} + elif mode == 'custom': + try: + history = json.load(open(custom_history)) + return history + except: + raise Exception('Error loading custom history file') + + def api_request(self, prompt, seed, mode, custom_history): + history = self.history(mode, custom_history) + if mode == 'prompt': + prompt = f'{prompt}, describe in detail.' + if mode == 'descriptor': + spice = ['a', 'the', 'this', 'that', 'an exotic', 'an interesting', 'a colorful', 'a vibrant', 'get creative!', 'think outside the box!', 'a rare', 'a standard', 'a typical', 'a common', 'a normal', 'a regular', 'a usual', 'an ordinary', 'a unique', 'a one of a kind', 'a special', 'a distinctive', 'a peculiar', 'a remarkable', 'a noteworthy', 'popular in the victorian era', 'popular in the 1920s', 'popular in the 1950s', 'popular in the 1980s', 'popular in the 1990s', 'popular in the 2000s', 'popular in the 2010s', 'popular in the 2020s', 'popular in asia', 'popular in europe', 'popular in north america', 'popular in south america', 'popular in africa', 'popular in australia', 'popular in the middle east', 'popular in the pacific islands', 'popular with young people', 'popular with the elderly', 'trending on social media', 'popular on tiktok', 'trending on pinterest', 'popular on instagram', 'popular on facebook', 'popular on twitter', 'popular on reddit', 'popular on youtube', 'popular on tumblr', 'popular on snapchat', 'popular on linkedin', 'popular on twitch', 'popular on discord', 'unusual example of', 'a classic', 'an underrated', 'an innovative', 'a historical', 'a modern', 'a contemporary', 'a futuristic', 'a traditional', 'an eco-friendly', 'a controversial', 'a political', 'a religious', 'a spiritual', 'a philosophical', 'a scientific'] + random.seed(seed) + prompt = f'{random.choice(spice)} {prompt}' + request = {'user_input': prompt, 'max_new_tokens': 250, 'auto_max_new_tokens': False, 'max_tokens_second': 0, 'history': history, 'mode': 'instruct', 'regenerate': False, '_continue': False, 'preset': 'StarChat', 'seed': seed} + HOST = 'localhost:5000' + URI = f'http://{HOST}/api/v1/chat' + try: + response = requests.post(URI, json=request, timeout=20) + except requests.exceptions.ConnectionError: + raise Exception('Are you running oobabooga with API enabled?') + if response.status_code == 200: + result = response.json()['results'][0]['history']['visible'][-1][1] + result = html.unescape(result) + return result + else: + return 'Error' + + def process(self, input_prompt, mode, custom_history, seed, prompt=None, unique_id=None, extra_pnginfo=None): + input_prompt = search_and_replace(input_prompt, extra_pnginfo, prompt) + wc_re = re.compile('{([^}]+)}') + + def repl(m): + return random.choice(m.group(1).split('|')) + for m in wc_re.finditer(input_prompt): + input_prompt = input_prompt.replace(m.group(0), repl(m)) + result = self.api_request(input_prompt, seed, mode, custom_history) + prompt.get(str(unique_id))['inputs']['output_text'] = result + return (result,) +``` \ No newline at end of file diff --git a/docs/OpenPose_Preprocessor_Provider_for_SEGS %2F%2FInspire.md b/docs/OpenPose_Preprocessor_Provider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..5f69a9b --- /dev/null +++ b/docs/OpenPose_Preprocessor_Provider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: OpenPose_Preprocessor_Provider_for_SEGS +- Category: InspirePack/SEGS/ControlNet +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +OpenPose_Preprocessor_Provider_for_SEGS 类旨在通过使用 OpenPose 技术来检测和分析人体姿态,从而促进图像的语义分割预处理。它可以在图像中识别手、身体和面部,这对于需要理解场景中人体姿势和交互的应用至关重要。 + +# Input types +## Required +- detect_hand + - 此参数控制节点是否尝试在输入图像中检测手部。启用此功能可以为需要理解手部位置和交互的应用程序提供有价值的数据。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- detect_body + - 此参数启用或禁用图像中人体检测。对于需要理解场景中个体的整体结构和姿态的应用程序,身体检测是必不可少的。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- detect_face + - 通过切换此参数,可以指示节点检测面部特征。这种能力对于需要分析面部表情和交互的应用程序至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- resolution_upscale_by + - 此参数调整输入图像的分辨率,可以提高姿态检测的准确性。提高分辨率可以提供更详细的信息,这对于复杂的场景或高分辨率的分割任务是有益的。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- SEGS_PREPROCESSOR + - 该节点的输出是一个包含人类姿态注释的预处理图像,可用作语义分割任务的基础。这些注释对于准确识别和分类场景中的不同元素至关重要。 + - Comfy dtype: SEGS_PREPROCESSOR + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class OpenPose_Preprocessor_Provider_for_SEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'detect_hand': ('BOOLEAN', {'default': True, 'label_on': 'enable', 'label_off': 'disable'}), 'detect_body': ('BOOLEAN', {'default': True, 'label_on': 'enable', 'label_off': 'disable'}), 'detect_face': ('BOOLEAN', {'default': True, 'label_on': 'enable', 'label_off': 'disable'}), 'resolution_upscale_by': ('FLOAT', {'default': 1.0, 'min': 0.5, 'max': 100, 'step': 0.1})}} + RETURN_TYPES = ('SEGS_PREPROCESSOR',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/SEGS/ControlNet' + + def doit(self, detect_hand, detect_body, detect_face, resolution_upscale_by): + obj = OpenPose_Preprocessor_wrapper(detect_hand, detect_body, detect_face, upscale_factor=resolution_upscale_by) + return (obj,) +``` \ No newline at end of file diff --git a/docs/OutlineMask.md b/docs/OutlineMask.md new file mode 100644 index 0000000..621724d --- /dev/null +++ b/docs/OutlineMask.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: OutlineMask +- Category: ♾️Mixlab/Mask +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +OutlineMask节点旨在通过应用膨胀或腐蚀过程来操纵图像掩码,以创建轮廓效果。它增强了掩码边缘的视觉区分度,这对于需要清晰和定义明确的掩码边界的应用至关重要。 + +# Input types +## Required +- mask + - ‘mask’参数是OutlineMask节点的一个基本输入,代表将要处理的原始图像掩码。它在确定最终轮廓效果中起着关键作用,因为它决定了初始掩码的形状和内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- outline_width + - ‘outline_width’参数指定要应用于掩码的轮廓扩展或收缩的程度。它是控制生成的轮廓粗细的关键因素,从而影响掩码边缘的视觉影响。 + - Comfy dtype: INT + - Python dtype: int +- tapered_corners + - 当设置为true时,‘tapered_corners’参数会将一个锥形效果应用于掩码的角落,创建一个更加细腻和视觉上吸引人的轮廓。这个特性增强了最终输出的美学质量。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- mask + - OutlineMask节点的‘mask’输出是应用了轮廓效果的已处理图像掩码。它很重要,因为它代表了节点操作的最终产品,准备用于进一步使用或可视化。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class OutlineMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'outline_width': ('INT', {'default': 10, 'min': 1, 'max': MAX_RESOLUTION, 'step': 1}), 'tapered_corners': ('BOOLEAN', {'default': True})}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Mask' + + def run(self, mask, outline_width, tapered_corners): + m1 = grow(mask, outline_width, tapered_corners) + m2 = grow(mask, -outline_width, tapered_corners) + m3 = combine(m1, m2, 0, 0) + return (m3,) +``` \ No newline at end of file diff --git a/docs/Outpaint to Image (WLSH).md b/docs/Outpaint to Image (WLSH).md new file mode 100644 index 0000000..5b7e92c --- /dev/null +++ b/docs/Outpaint to Image (WLSH).md @@ -0,0 +1,84 @@ +# Documentation +- Class name: WLSH_Outpaint_To_Image +- Category: WLSH Nodes/inpainting +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点在指定方向扩展图像并生成相应的掩码,增强了图像操作和扩展的能力,以满足各种应用场景。 + +# Input types +## Required +- image + - 源图像对于修复过程至关重要,它是扩展和生成掩码的基础层。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- direction + - 方向参数决定了图像扩展的方向,影响输出的整体结构和组合。 + - Comfy dtype: COMBO + - Python dtype: str +- pixels + - 像素数量决定了图像扩展的程度,直接影响最终的尺寸和修复的范围。 + - Comfy dtype: INT + - Python dtype: int +- mask_padding + - 掩码填充对于定义图像周围的扩展区域至关重要,确保原始部分与新区域之间的平滑过渡。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 输出图像代表修复的结果,原始图像已根据指定的方向和像素进行扩展。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 掩码对应于已修复的区域,提供一个二进制表示,区分原始部分和扩展部分。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Outpaint_To_Image: + directions = ['left', 'right', 'up', 'down'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'direction': (s.directions,), 'pixels': ('INT', {'default': 128, 'min': 32, 'max': 512, 'step': 32}), 'mask_padding': ('INT', {'default': 12, 'min': 0, 'max': 64, 'step': 4})}} + RETURN_TYPES = ('IMAGE', 'MASK') + FUNCTION = 'outpaint' + CATEGORY = 'WLSH Nodes/inpainting' + + def convert_image(self, im, direction, mask_padding): + (width, height) = im.size + im = im.convert('RGBA') + alpha = Image.new('L', (width, height), 255) + im.putalpha(alpha) + return im + + def outpaint(self, image, direction, mask_padding, pixels): + image = tensor2pil(image) + image = self.convert_image(image, direction, mask_padding) + if direction == 'right': + border = (0, 0, pixels, 0) + new_image = ImageOps.expand(image, border=border, fill=(0, 0, 0, 0)) + elif direction == 'left': + border = (pixels, 0, 0, 0) + new_image = ImageOps.expand(image, border=border, fill=(0, 0, 0, 0)) + elif direction == 'up': + border = (0, pixels, 0, 0) + new_image = ImageOps.expand(image, border=border, fill=(0, 0, 0, 0)) + elif direction == 'down': + border = (0, 0, 0, pixels) + new_image = ImageOps.expand(image, border=border, fill=(0, 0, 0, 0)) + image = new_image.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + if 'A' in new_image.getbands(): + mask = np.array(new_image.getchannel('A')).astype(np.float32) / 255.0 + mask = 1.0 - torch.from_numpy(mask) + else: + mask = torch.zeros((64, 64), dtype=torch.float32, device='cpu') + return (image, mask) +``` \ No newline at end of file diff --git a/docs/PCApplySettings.md b/docs/PCApplySettings.md new file mode 100644 index 0000000..49397a7 --- /dev/null +++ b/docs/PCApplySettings.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: PCApplySettings +- Category: promptcontrol +- Output node: False +- Repo Ref: https://github.com/asagi4/comfyui-prompt-control.git + +PCApplySettings节点的'apply'方法旨在通过应用一组设置来修改和增强提示计划的功能。它在系统内定制提示的行为中发挥关键作用,允许基于用户定义的参数进行定制化的响应和交互。 + +# Input types +## Required +- prompt_schedule + - 参数'prompt_schedule'对于定义提示的结构和时间至关重要。它决定了提示在系统中的传递方式和时间,显著影响整体用户体验和交互流程。 + - Comfy dtype: PromptSchedule + - Python dtype: PromptSchedule +- settings + - 参数'settings'对于定制提示计划的行为至关重要。它允许用户调整各种方面,如过滤器、开始时间和默认值,以满足特定的需求或偏好。 + - Comfy dtype: SCHEDULE_SETTINGS + - Python dtype: Dict[str, Any] + +# Output types +- modified_prompt_schedule + - 输出'modified_prompt_schedule'反映了应用设置后的更新提示计划。它标志着将指导系统中随后的提示传递和交互的新配置。 + - Comfy dtype: PromptSchedule + - Python dtype: PromptSchedule + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PCApplySettings: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompt_schedule': ('PROMPT_SCHEDULE',), 'settings': ('SCHEDULE_SETTINGS',)}} + RETURN_TYPES = ('PROMPT_SCHEDULE',) + CATEGORY = 'promptcontrol' + FUNCTION = 'apply' + + def apply(self, prompt_schedule, settings): + return (prompt_schedule.with_filters(defaults=settings),) +``` \ No newline at end of file diff --git a/docs/PCPromptFromSchedule.md b/docs/PCPromptFromSchedule.md new file mode 100644 index 0000000..605e909 --- /dev/null +++ b/docs/PCPromptFromSchedule.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: PCPromptFromSchedule +- Category: promptcontrol +- Output node: False +- Repo Ref: https://github.com/asagi4/comfyui-prompt-control.git + +该节点旨在根据指定的时间点从预定义的时间表中提取并应用提示,确保生成的提示在上下文中相关且及时。 + +# Input types +## Required +- prompt_schedule + - 提示时间表是关键输入,概述了随时间变化的提示的结构和内容。这对于节点的正确功能和产生有意义的输出至关重要。 + - Comfy dtype: PROMPT_SCHEDULE + - Python dtype: +- at + - 'at' 参数精确指定了从时间表中提取提示的时间点。它直接影响选择的提示及其相关性。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- tags + - 'tags' 参数允许根据特定标签过滤提示时间表,这可以细化输出以针对特定主题或类别。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- prompt + - 输出 'prompt' 是在指定时间从时间表中选择的提示,它作为进一步处理或分析的基础。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PCPromptFromSchedule: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompt_schedule': ('PROMPT_SCHEDULE',), 'at': ('FLOAT', {'min': 0.0, 'max': 1.0, 'step': 0.01})}, 'optional': {'tags': ('STRING', {'default': ''})}} + RETURN_TYPES = ('STRING',) + CATEGORY = 'promptcontrol' + FUNCTION = 'apply' + + def apply(self, prompt_schedule, at, tags=''): + p = prompt_schedule.with_filters(tags, start=at, end=at).parsed_prompt[-1][1] + log.info('Prompt at %s:\n%s', at, p['prompt']) + log.info('LoRAs: %s', p['loras']) + return (p['prompt'],) +``` \ No newline at end of file diff --git a/docs/PCScheduleSettings.md b/docs/PCScheduleSettings.md new file mode 100644 index 0000000..9afcc72 --- /dev/null +++ b/docs/PCScheduleSettings.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: PCScheduleSettings +- Category: promptcontrol +- Output node: False +- Repo Ref: https://github.com/asagi4/comfyui-prompt-control.git + +该节点旨在管理和调整提示时间表的参数,这对控制AI模型的生成过程至关重要。它确保模型的输出根据指定的设置进行微调,从而优化结果的质量和相关性。 + +# Input types +## Optional +- steps + - 步骤参数对于定义AI模型输出在一定次数迭代中的进展至关重要。它影响模型细化其响应并达到期望的细节和连贯性水平的能力。 + - Comfy dtype: INT + - Python dtype: int +- mask_width + - 掩码宽度参数在塑造模型输出的空间维度方面起着重要作用。它有助于控制生成内容的广度,确保其与预期的范围和结构相一致。 + - Comfy dtype: INT + - Python dtype: int +- mask_height + - 掩码高度参数对于定义模型输出的垂直结构至关重要。它与掩码宽度一起工作,建立整体的空间配置,这对于保持内容的完整性至关重要。 + - Comfy dtype: INT + - Python dtype: int +- sdxl_width + - SDXL宽度参数对于设置模型输出的水平比例很重要。它影响模型如何在宽度上分布信息,确保内容适当详细且平衡。 + - Comfy dtype: INT + - Python dtype: int +- sdxl_height + - SDXL高度参数对于建立模型输出的垂直比例至关重要。它与SDXL宽度一起工作,创造和谐的平衡,确保内容的结构是连贯和比例协调的。 + - Comfy dtype: INT + - Python dtype: int +- sdxl_target_w + - SDXL目标宽度参数对于设置输出的期望宽度至关重要。它引导模型实现目标尺寸,这对于保持生成内容的视觉和结构完整性至关重要。 + - Comfy dtype: INT + - Python dtype: int +- sdxl_target_h + - SDXL目标高度参数对于定义输出的期望高度至关重要。它与SDXL目标宽度一起工作,确保模型的输出适当缩放并适应期望的尺寸。 + - Comfy dtype: INT + - Python dtype: int +- sdxl_crop_w + - SDXL裁剪宽度参数对于指定从模型输出中裁剪的区域宽度很重要。它有助于精炼最终输出,专注于最相关的部分,提高内容的精确性和相关性。 + - Comfy dtype: INT + - Python dtype: int +- sdxl_crop_h + - SDXL裁剪高度参数对于定义从模型输出中裁剪的区域高度至关重要。它与SDXL裁剪宽度一起工作,确保裁剪的内容专注且与预期输出一致。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- settings + - 设置输出提供了应用时间表参数的综合摘要,这对于监控和调整AI模型的行为至关重要。它确保模型在期望的参数内运行,从而获得优化和有针对性的结果。 + - Comfy dtype: SCHEDULE_SETTINGS + - Python dtype: Tuple[int, int, int, int, int, int, int, int, int] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PCScheduleSettings: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}, 'optional': {'steps': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'mask_width': ('INT', {'default': 512, 'min': 64, 'max': 4096 * 4}), 'mask_height': ('INT', {'default': 512, 'min': 64, 'max': 4096 * 4}), 'sdxl_width': ('INT', {'default': 1024, 'min': 0, 'max': 4096 * 4}), 'sdxl_height': ('INT', {'default': 1024, 'min': 0, 'max': 4096 * 4}), 'sdxl_target_w': ('INT', {'default': 1024, 'min': 0, 'max': 4096 * 4}), 'sdxl_target_h': ('INT', {'default': 1024, 'min': 0, 'max': 4096 * 4}), 'sdxl_crop_w': ('INT', {'default': 0, 'min': 0, 'max': 4096 * 4}), 'sdxl_crop_h': ('INT', {'default': 0, 'min': 0, 'max': 4096 * 4})}} + RETURN_TYPES = ('SCHEDULE_SETTINGS',) + CATEGORY = 'promptcontrol' + FUNCTION = 'apply' + + def apply(self, steps=0, mask_width=512, mask_height=512, sdxl_width=1024, sdxl_height=1024, sdxl_target_w=1024, sdxl_target_h=1024, sdxl_crop_w=0, sdxl_crop_h=0): + settings = {'steps': steps, 'mask_width': mask_width, 'mask_height': mask_height, 'sdxl_width': sdxl_width, 'sdxl_height': sdxl_height, 'sdxl_twidth': sdxl_target_w, 'sdxl_theight': sdxl_target_h, 'sdxl_cwidth': sdxl_crop_w, 'sdxl_cheight': sdxl_crop_h} + return (settings,) +``` \ No newline at end of file diff --git a/docs/PCSplitSampling.md b/docs/PCSplitSampling.md new file mode 100644 index 0000000..d658d4b --- /dev/null +++ b/docs/PCSplitSampling.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: PCSplitSampling +- Category: promptcontrol +- Output node: False +- Repo Ref: https://github.com/asagi4/comfyui-prompt-control.git + +PCSplitSampling节点旨在通过启用或禁用一种称为提示控制分割采样的特定采样技术来修改给定模型。该技术对于控制模型的生成过程至关重要,允许实现更精细和针对性的输出。通过应用此节点,用户可以轻松切换采样方法以实现所需的结果,而无需更改底层模型架构。 + +# Input types +## Required +- model + - ‘model’参数至关重要,因为它代表了将要接受采样技术调整的机器学习模型。它是节点操作的核心组件,其修改将直接影响模型的生成能力。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- split_sampling + - ‘split_sampling’参数决定是否为模型启用提示控制分割采样技术。这个切换直接影响模型对数据采样的方法,对于实现模型预测或生成中的特定结果可能至关重要。 + - Comfy dtype: COMBO['enable', 'disable'] + - Python dtype: str + +# Output types +- model + - 输出‘model’是应用了用户选择的提示控制分割采样功能的输入模型的修改版本。这允许模型在后续任务中使用所需的采样行为。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PCSplitSampling: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'split_sampling': (['enable', 'disable'],)}} + RETURN_TYPES = ('MODEL',) + CATEGORY = 'promptcontrol' + FUNCTION = 'apply' + + def apply(self, model, split_sampling): + model = clone_model(model) + model.model_options['pc_split_sampling'] = split_sampling == 'enable' + return (model,) +``` \ No newline at end of file diff --git a/docs/Parabolize.md b/docs/Parabolize.md new file mode 100644 index 0000000..2740744 --- /dev/null +++ b/docs/Parabolize.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: Parabolize +- Category: postprocessing/Color Adjustments +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +Parabolize节点旨在对图像应用抛物线变换,通过调整其颜色和对比度来增强其视觉特征。它通过应用一个数学函数来实现这一点,该函数基于给定的系数和顶点参数来操作像素值,从而产生可用于各种创意或分析目的的风格化输出。 + +# Input types +## Required +- image + - 图像参数是节点将处理的输入图像。它对节点的操作至关重要,因为它是抛物线变换的对象。图像的内容和格式直接影响节点执行的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- coeff + - 系数参数决定了应用于图像的抛物线效果的程度。它是一个可选参数,允许用户控制变换的强度,默认值提供了一个平衡的效果。 + - Comfy dtype: FLOAT + - Python dtype: float +- vertex_x + - vertex_x参数指定了抛物线函数顶点的x坐标。它是一个可选参数,影响图像内抛物线曲线的位置,影响变换像素值的分布。 + - Comfy dtype: FLOAT + - Python dtype: float +- vertex_y + - vertex_y参数定义了抛物线函数顶点的y坐标。它是一个可选参数,调整抛物线曲线的垂直位置,从而影响变换图像的整体亮度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- parabolized_image + - parabolized_image输出是将抛物线变换应用于输入图像的结果。它代表了一个新的图像,其像素值经过调整,反映了所选择的系数和顶点参数的效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Parabolize: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'coeff': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.1}), 'vertex_x': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.1}), 'vertex_y': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'parabolize_image' + CATEGORY = 'postprocessing/Color Adjustments' + + def parabolize_image(self, image: torch.Tensor, coeff: float, vertex_x: float, vertex_y: float): + parabolized_image = coeff * torch.pow(image - vertex_x, 2) + vertex_y + parabolized_image = torch.clamp(parabolized_image, 0, 1) + return (parabolized_image,) +``` \ No newline at end of file diff --git a/docs/Paste By Mask.md b/docs/Paste By Mask.md new file mode 100644 index 0000000..d97fc65 --- /dev/null +++ b/docs/Paste By Mask.md @@ -0,0 +1,157 @@ +# Documentation +- Class name: PasteByMask +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +PasteByMask节点旨在使用遮罩确定位置,将一个图像粘贴到另一个图像上。它智能地调整要粘贴的图像的大小以适应遮罩的尺寸,有选项可以保持原始纵横比或完全填充遮罩区域。这个节点在图像处理任务中扮演着关键角色,当需要无缝集成多个图像时,提供了放置和调整图像元素的灵活性和精确性。 + +# Input types +## Required +- image_base + - 将要在其上粘贴另一个图像的基础图像。它作为操作的画布,其属性影响最终的组合。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- image_to_paste + - 将要粘贴到基础图像上的图像。其视觉内容和大小在确定粘贴操作的结果中起着关键作用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 决定image_to_paste将放置在image_base上的位置的遮罩。它充当模板,控制粘贴图像的可见性和位置。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- resize_behavior + - 确定如何调整image_to_paste的大小以适应遮罩内。这是一个关键参数,影响粘贴图像的缩放和纵横比。 + - Comfy dtype: COMBO['resize', 'keep_ratio_fill', 'keep_ratio_fit', 'source_size', 'source_size_unmasked'] + - Python dtype: str +## Optional +- mask_mapping_optional + - 一个可选参数,如果提供,它指定了特定的image_to_paste应该粘贴到哪个基础图像上。它为涉及多个图像的复杂操作增加了一个额外的控制层。 + - Comfy dtype: MASK_MAPPING + - Python dtype: torch.Tensor + +# Output types +- result + - 最终的输出图像,根据遮罩和resize_behavior参数,将image_to_paste应用到image_base上。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PasteByMask: + """ + Pastes `image_to_paste` onto `image_base` using `mask` to determine the location. The `resize_behavior` parameter determines how the image to paste is resized to fit the mask. If `mask_mapping_optional` obtained from a 'Separate Mask Components' node is used, it will control which image gets pasted onto which base image. + """ + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image_base': ('IMAGE',), 'image_to_paste': ('IMAGE',), 'mask': ('IMAGE',), 'resize_behavior': (['resize', 'keep_ratio_fill', 'keep_ratio_fit', 'source_size', 'source_size_unmasked'],)}, 'optional': {'mask_mapping_optional': ('MASK_MAPPING',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'paste' + CATEGORY = 'Masquerade Nodes' + + def paste(self, image_base, image_to_paste, mask, resize_behavior, mask_mapping_optional=None): + image_base = tensor2rgba(image_base) + image_to_paste = tensor2rgba(image_to_paste) + mask = tensor2mask(mask) + (B, H, W, C) = image_base.shape + MB = mask.shape[0] + PB = image_to_paste.shape[0] + if mask_mapping_optional is None: + if B < PB: + assert PB % B == 0 + image_base = image_base.repeat(PB // B, 1, 1, 1) + (B, H, W, C) = image_base.shape + if MB < B: + assert B % MB == 0 + mask = mask.repeat(B // MB, 1, 1) + elif B < MB: + assert MB % B == 0 + image_base = image_base.repeat(MB // B, 1, 1, 1) + if PB < B: + assert B % PB == 0 + image_to_paste = image_to_paste.repeat(B // PB, 1, 1, 1) + mask = torch.nn.functional.interpolate(mask.unsqueeze(1), size=(H, W), mode='nearest')[:, 0, :, :] + (MB, MH, MW) = mask.shape + is_empty = ~torch.gt(torch.max(torch.reshape(mask, [MB, MH * MW]), dim=1).values, 0.0) + mask[is_empty, 0, 0] = 1.0 + boxes = masks_to_boxes(mask) + mask[is_empty, 0, 0] = 0.0 + min_x = boxes[:, 0] + min_y = boxes[:, 1] + max_x = boxes[:, 2] + max_y = boxes[:, 3] + mid_x = (min_x + max_x) / 2 + mid_y = (min_y + max_y) / 2 + target_width = max_x - min_x + 1 + target_height = max_y - min_y + 1 + result = image_base.detach().clone() + for i in range(0, MB): + if is_empty[i]: + continue + else: + image_index = i + if mask_mapping_optional is not None: + image_index = mask_mapping_optional[i].item() + source_size = image_to_paste.size() + (SB, SH, SW, _) = image_to_paste.shape + width = int(target_width[i].item()) + height = int(target_height[i].item()) + if resize_behavior == 'keep_ratio_fill': + target_ratio = width / height + actual_ratio = SW / SH + if actual_ratio > target_ratio: + width = int(height * actual_ratio) + elif actual_ratio < target_ratio: + height = int(width / actual_ratio) + elif resize_behavior == 'keep_ratio_fit': + target_ratio = width / height + actual_ratio = SW / SH + if actual_ratio > target_ratio: + height = int(width / actual_ratio) + elif actual_ratio < target_ratio: + width = int(height * actual_ratio) + elif resize_behavior == 'source_size' or resize_behavior == 'source_size_unmasked': + width = SW + height = SH + resized_image = image_to_paste[i].unsqueeze(0) + if SH != height or SW != width: + resized_image = torch.nn.functional.interpolate(resized_image.permute(0, 3, 1, 2), size=(height, width), mode='bicubic').permute(0, 2, 3, 1) + pasting = torch.ones([H, W, C]) + ymid = float(mid_y[i].item()) + ymin = int(math.floor(ymid - height / 2)) + 1 + ymax = int(math.floor(ymid + height / 2)) + 1 + xmid = float(mid_x[i].item()) + xmin = int(math.floor(xmid - width / 2)) + 1 + xmax = int(math.floor(xmid + width / 2)) + 1 + (_, source_ymax, source_xmax, _) = resized_image.shape + (source_ymin, source_xmin) = (0, 0) + if xmin < 0: + source_xmin = abs(xmin) + xmin = 0 + if ymin < 0: + source_ymin = abs(ymin) + ymin = 0 + if xmax > W: + source_xmax -= xmax - W + xmax = W + if ymax > H: + source_ymax -= ymax - H + ymax = H + pasting[ymin:ymax, xmin:xmax, :] = resized_image[0, source_ymin:source_ymax, source_xmin:source_xmax, :] + pasting[:, :, 3] = 1.0 + pasting_alpha = torch.zeros([H, W]) + pasting_alpha[ymin:ymax, xmin:xmax] = resized_image[0, source_ymin:source_ymax, source_xmin:source_xmax, 3] + if resize_behavior == 'keep_ratio_fill' or resize_behavior == 'source_size_unmasked': + paste_mask = pasting_alpha.unsqueeze(2).repeat(1, 1, 4) + else: + paste_mask = torch.min(pasting_alpha, mask[i]).unsqueeze(2).repeat(1, 1, 4) + result[image_index] = pasting * paste_mask + result[image_index] * (1.0 - paste_mask) + return (result,) +``` \ No newline at end of file diff --git a/docs/PencilSketch.md b/docs/PencilSketch.md new file mode 100644 index 0000000..61c7bfe --- /dev/null +++ b/docs/PencilSketch.md @@ -0,0 +1,87 @@ +# Documentation +- Class name: PencilSketch +- Category: postprocessing/Effects +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +PencilSketch节点旨在将图像转换为铅笔素描风格。它应用一系列图像处理技术来实现一种模仿手绘素描外观的风格化表示。 + +# Input types +## Required +- image + - 图像参数对于PencilSketch节点至关重要,因为它是将被转换成铅笔素描的输入。它通过确定输出素描的内容和质量来影响节点的执行。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- blur_radius + - 模糊半径参数控制应用素描效果之前对图像应用的模糊量。它在确定最终素描的平滑度方面起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- sharpen_alpha + - sharpen_alpha参数调整应用于最终图像的锐化效果的强度。它对于微调铅笔素描的对比度和清晰度很重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output_image + - output_image是将铅笔素描效果应用于输入图像的结果。它代表了以铅笔素描形式的最终风格化图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PencilSketch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'blur_radius': ('INT', {'default': 5, 'min': 1, 'max': 31, 'step': 1}), 'sharpen_alpha': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'apply_sketch' + CATEGORY = 'postprocessing/Effects' + + def apply_sketch(self, image: torch.Tensor, blur_radius: int=5, sharpen_alpha: float=1): + image = image.permute(0, 3, 1, 2) + grayscale = image.mean(dim=1, keepdim=True) + grayscale = grayscale.repeat(1, 3, 1, 1) + inverted = 1 - grayscale + blur_sigma = blur_radius / 3 + blurred = self.gaussian_blur(inverted, blur_radius, blur_sigma) + final_image = self.dodge(blurred, grayscale) + if sharpen_alpha != 0.0: + final_image = self.sharpen(final_image, 1, sharpen_alpha) + final_image = final_image.permute(0, 2, 3, 1) + return (final_image,) + + def dodge(self, front: torch.Tensor, back: torch.Tensor) -> torch.Tensor: + result = back / (1 - front + 1e-07) + result = torch.clamp(result, 0, 1) + return result + + def gaussian_blur(self, image: torch.Tensor, blur_radius: int, sigma: float): + if blur_radius == 0: + return image + (batch_size, channels, height, width) = image.shape + kernel_size = blur_radius * 2 + 1 + kernel = gaussian_kernel(kernel_size, sigma).repeat(channels, 1, 1).unsqueeze(1) + blurred = F.conv2d(image, kernel, padding=kernel_size // 2, groups=channels) + return blurred + + def sharpen(self, image: torch.Tensor, blur_radius: int, alpha: float): + if blur_radius == 0: + return image + (batch_size, channels, height, width) = image.shape + kernel_size = blur_radius * 2 + 1 + kernel = torch.ones((kernel_size, kernel_size), dtype=torch.float32) * -1 + center = kernel_size // 2 + kernel[center, center] = kernel_size ** 2 + kernel *= alpha + kernel = kernel.repeat(channels, 1, 1).unsqueeze(1) + sharpened = F.conv2d(image, kernel, padding=center, groups=channels) + result = torch.clamp(sharpened, 0, 1) + return result +``` \ No newline at end of file diff --git a/docs/Pick From Batch (mtb).md b/docs/Pick From Batch (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/PixelKSampleHookCombine.md b/docs/PixelKSampleHookCombine.md new file mode 100644 index 0000000..aa14ddd --- /dev/null +++ b/docs/PixelKSampleHookCombine.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: PixelKSampleHookCombine +- Category: image_processing +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +PixelKSampleHookCombine 是一个节点,旨在将两个独立的钩子顺序应用于一系列图像处理操作。它协调钩子以特定顺序预处理、解码、放大和编码像素数据,确保图像操作任务的协同工作流程。 + +# Input types +## Required +- hook1 + - 第一个要顺序应用的钩子。它在图像处理的初始阶段起着至关重要的作用,为后续操作奠定基础。 + - Comfy dtype: PixelKSampleHook + - Python dtype: PixelKSampleHook +- hook2 + - 第二个要顺序应用的钩子,它在第一个钩子应用后进一步细化图像处理流水线,提高整体输出质量。 + - Comfy dtype: PixelKSampleHook + - Python dtype: PixelKSampleHook + +# Output types +- processed_pixels + - PixelKSampleHookCombine 节点的输出是将两个钩子应用于输入像素数据后的结果。它代表了所有处理步骤完成后图像的最终状态。 + - Comfy dtype: COMBO[str, torch.Tensor] + - Python dtype: Union[str, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PixelKSampleHookCombine(PixelKSampleHook): + hook1 = None + hook2 = None + + def __init__(self, hook1, hook2): + super().__init__() + self.hook1 = hook1 + self.hook2 = hook2 + + def set_steps(self, info): + self.hook1.set_steps(info) + self.hook2.set_steps(info) + + def pre_decode(self, samples): + return self.hook2.pre_decode(self.hook1.pre_decode(samples)) + + def post_decode(self, pixels): + return self.hook2.post_decode(self.hook1.post_decode(pixels)) + + def post_upscale(self, pixels): + return self.hook2.post_upscale(self.hook1.post_upscale(pixels)) + + def post_encode(self, samples): + return self.hook2.post_encode(self.hook1.post_encode(samples)) + + def post_crop_region(self, w, h, item_bbox, crop_region): + crop_region = self.hook1.post_crop_region(w, h, item_bbox, crop_region) + return self.hook2.post_crop_region(w, h, item_bbox, crop_region) + + def touch_scaled_size(self, w, h): + (w, h) = self.hook1.touch_scaled_size(w, h) + return self.hook2.touch_scaled_size(w, h) + + def pre_ksample(self, model, seed, steps, cfg, sampler_name, scheduler, positive, negative, upscaled_latent, denoise): + (model, seed, steps, cfg, sampler_name, scheduler, positive, negative, upscaled_latent, denoise) = self.hook1.pre_ksample(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, upscaled_latent, denoise) + return self.hook2.pre_ksample(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, upscaled_latent, denoise) +``` \ No newline at end of file diff --git a/docs/PixelKSampleUpscalerProvider.md b/docs/PixelKSampleUpscalerProvider.md new file mode 100644 index 0000000..2e20282 --- /dev/null +++ b/docs/PixelKSampleUpscalerProvider.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: PixelKSampleUpscalerProvider +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +PixelKSampleUpscalerProvider 是一个用于图像放大的节点,它支持多种放大方法。该节点封装了选择放大技术和将其应用于输入图像所需的逻辑,提供了一个用于增强图像质量的无缝接口。 + +# Input types +## Required +- scale_method + - 缩放方法决定了用于图像放大的算法。这是一个关键参数,因为它直接影响放大输出的质量和风格。 + - Comfy dtype: str + - Python dtype: str +- model + - 模型参数至关重要,因为它定义了用于放大过程的机器学习模型。模型的选择可以显著影响最终结果。 + - Comfy dtype: MODEL + - Python dtype: Any +- vae + - VAE(变分自编码器)用于放大过程中的特征提取或潜在空间操作。其配置可以增强放大图像的细节和质量。 + - Comfy dtype: VAE + - Python dtype: Any +- seed + - 种子通过为随机数生成提供已知的起始点来确保放大过程的可重复性,这对于一致的结果至关重要。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步数决定了放大期间的迭代过程,这可能会影响收敛和最终输出质量。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置值 'cfg' 是一个调整放大图像中细节和伪影平衡的参数,在最终外观中扮演重要角色。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 采样器名称选择放大过程中使用的采样策略,这可以极大地影响操作的效率和结果。 + - Comfy dtype: str + - Python dtype: str +- scheduler + - 调度器决定了放大过程中参数更新的速率,影响放大输出的稳定性和性能。 + - Comfy dtype: str + - Python dtype: str +- positive + - 正向调节在放大期间为模型提供指导,专注于增强图像的特定特征或方面。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- negative + - 负向调节有助于通过指导模型抑制某些伪影或特征,在放大期间避免不希望的效果。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- denoise + - 去噪参数控制应用于放大图像的噪声减少级别,这可以提高最终输出的清晰度和清洁度。 + - Comfy dtype: FLOAT + - Python dtype: float +- use_tiled_vae + - 使用平铺的VAE允许通过将较大的图像分解为更小、更易管理的平铺来处理,这对于内存效率是有益的。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- tile_size + - 当使用平铺的VAE时,平铺尺寸指定了用于平铺图像的平铺的尺寸,影响放大过程的粒度。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- upscaler + - 放大器是节点的主要输出,代表放大的图像或可用于放大图像的模型。它封装了放大过程的结果。 + - Comfy dtype: UPSCALER + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PixelKSampleUpscalerProvider: + upscale_methods = ['nearest-exact', 'bilinear', 'lanczos', 'area'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'scale_method': (s.upscale_methods,), 'model': ('MODEL',), 'vae': ('VAE',), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'use_tiled_vae': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'}), 'tile_size': ('INT', {'default': 512, 'min': 320, 'max': 4096, 'step': 64})}, 'optional': {'upscale_model_opt': ('UPSCALE_MODEL',), 'pk_hook_opt': ('PK_HOOK',)}} + RETURN_TYPES = ('UPSCALER',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + def doit(self, scale_method, model, vae, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, use_tiled_vae, upscale_model_opt=None, pk_hook_opt=None, tile_size=512): + upscaler = core.PixelKSampleUpscaler(scale_method, model, vae, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, use_tiled_vae, upscale_model_opt, pk_hook_opt, tile_size=tile_size) + return (upscaler,) +``` \ No newline at end of file diff --git a/docs/PixelKSampleUpscalerProviderPipe.md b/docs/PixelKSampleUpscalerProviderPipe.md new file mode 100644 index 0000000..5f2cad4 --- /dev/null +++ b/docs/PixelKSampleUpscalerProviderPipe.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: PixelKSampleUpscalerProviderPipe +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +PixelKSampleUpscalerProviderPipe 是一个用于提高图像分辨率的节点,它使用各种上采样方法。它提供了一个强大的框架来选择和应用不同的缩放技术,确保高质量的结果。这个节点在图像上采样过程中至关重要,提供了与系统其他组件的无缝集成。 + +# Input types +## Required +- scale_method + - 缩放方法参数对于确定要使用的上采样技术至关重要。它决定了增强图像分辨率的算法方法,这显著影响最终输出的质量。 + - Comfy dtype: str + - Python dtype: str +- seed + - 种子参数在初始化随机数生成器中起着重要作用,确保了上采样过程的可重复性。这对于在节点的多次运行中保持一致性至关重要。 + - Comfy dtype: int + - Python dtype: int +- steps + - 步骤参数定义了在上采样过程中要执行的迭代次数。它直接影响操作的细节水平和计算复杂性。 + - Comfy dtype: int + - Python dtype: int +- cfg + - cfg 参数用于控制上采样模型的配置,允许微调缩放过程以实现期望的结果。 + - Comfy dtype: float + - Python dtype: float +- sampler_name + - sampler_name 参数指定了在上采样期间要采用的采样策略。它是采样过程效率和有效性的关键决定因素。 + - Comfy dtype: str + - Python dtype: str +- scheduler + - 调度器参数对于管理上采样步骤的节奏和顺序至关重要。它有助于优化上采样过程,以提高速度和质量。 + - Comfy dtype: str + - Python dtype: str +- denoise + - 去噪参数在上采样过程中启用了噪声减少的控制。这对于实现更清洁、更精细的图像输出至关重要。 + - Comfy dtype: float + - Python dtype: float +- use_tiled_vae + - use_tiled_vae 参数决定是否为变分自编码器(VAE)使用分块方法。这可以提高上采样过程的效率,特别是对于较大的图像。 + - Comfy dtype: bool + - Python dtype: bool +- basic_pipe + - basic_pipe 参数封装了上采样过程所需的基础组件。它对节点的操作不可或缺,为图像增强提供了必要的基础设施。 + - Comfy dtype: BASIC_PIPE + - Python dtype: BASIC_PIPE +## Optional +- tile_size + - tile_size 参数指定了上采样过程中用于分块方法的瓦片尺寸。当处理大型图像以优化内存使用和处理时间时,它特别相关。 + - Comfy dtype: int + - Python dtype: int + +# Output types +- upscaler + - upscaler 输出提供了最终的上采样模型,这是节点操作的核心结果。它代表了上采样过程的顶点,提供了一个经过提炼和增强的图像。 + - Comfy dtype: UPSCALER + - Python dtype: PixelKSampleUpscaler + +# Usage tips +- Infra type: GPU + +# Source code +``` +class PixelKSampleUpscalerProviderPipe(PixelKSampleUpscalerProvider): + upscale_methods = ['nearest-exact', 'bilinear', 'lanczos', 'area'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'scale_method': (s.upscale_methods,), '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': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'use_tiled_vae': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'}), 'basic_pipe': ('BASIC_PIPE',), 'tile_size': ('INT', {'default': 512, 'min': 320, 'max': 4096, 'step': 64})}, 'optional': {'upscale_model_opt': ('UPSCALE_MODEL',), 'pk_hook_opt': ('PK_HOOK',)}} + RETURN_TYPES = ('UPSCALER',) + FUNCTION = 'doit_pipe' + CATEGORY = 'ImpactPack/Upscale' + + def doit_pipe(self, scale_method, seed, steps, cfg, sampler_name, scheduler, denoise, use_tiled_vae, basic_pipe, upscale_model_opt=None, pk_hook_opt=None, tile_size=512): + (model, _, vae, positive, negative) = basic_pipe + upscaler = core.PixelKSampleUpscaler(scale_method, model, vae, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, use_tiled_vae, upscale_model_opt, pk_hook_opt, tile_size=tile_size) + return (upscaler,) +``` \ No newline at end of file diff --git a/docs/PixelOEPixelize+.md b/docs/PixelOEPixelize+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/PixelSort.md b/docs/PixelSort.md new file mode 100644 index 0000000..ebb1061 --- /dev/null +++ b/docs/PixelSort.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: PixelSort +- Category: postprocessing/Effects +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +PixelSort节点为图像引入了创造性的像素排序效果,根据指定的标准如色相、饱和度或明度,重新组织像素数据,增强图像的视觉冲击力。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它提供了像素排序过程的源数据,影响最终输出的外观。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 掩码参数对于定义应该受到像素排序效果影响的图像区域至关重要,从而控制变换的范围。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- direction + - 方向参数决定了像素排序的轴向,可以是水平或垂直,影响效果的整体模式。 + - Comfy dtype: COMBO['horizontal', 'vertical'] + - Python dtype: str +- sort_by + - sort_by参数决定了像素排序的标准,如色相、饱和度或明度,塑造效果的最终视觉结果。 + - Comfy dtype: COMBO['hue', 'saturation', 'value'] + - Python dtype: str +- order + - 顺序参数指定了排序的方向,无论是升序(向前)还是降序(向后),改变了像素的排列。 + - Comfy dtype: COMBO['forward', 'backward'] + - Python dtype: str +## Optional +- span_limit + - 跨度限制参数通过控制每个方向上的跨度数量来细化排序,影响像素排序效果的粒度。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 输出图像是像素排序过程的结果,反映了应用于输入图像的创造性变换。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PixelSort: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'mask': ('IMAGE',), 'direction': (['horizontal', 'vertical'],), 'span_limit': ('INT', {'default': None, 'min': 0, 'max': 100, 'step': 5}), 'sort_by': (['hue', 'saturation', 'value'],), 'order': (['forward', 'backward'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'sort_pixels' + CATEGORY = 'postprocessing/Effects' + + def sort_pixels(self, image: torch.Tensor, mask: torch.Tensor, direction: str, span_limit: int, sort_by: str, order: str): + horizontal_sort = direction == 'horizontal' + reverse_sorting = order == 'backward' + sort_by = sort_by[0].upper() + span_limit = span_limit if span_limit > 0 else None + batch_size = image.shape[0] + result = torch.zeros_like(image) + for b in range(batch_size): + tensor_img = image[b].numpy() + tensor_mask = mask[b].numpy() + sorted_image = pixel_sort(tensor_img, tensor_mask, horizontal_sort, span_limit, sort_by, reverse_sorting) + result[b] = torch.from_numpy(sorted_image) + return (result,) +``` \ No newline at end of file diff --git a/docs/PixelTiledKSampleUpscalerProvider.md b/docs/PixelTiledKSampleUpscalerProvider.md new file mode 100644 index 0000000..0f80fda --- /dev/null +++ b/docs/PixelTiledKSampleUpscalerProvider.md @@ -0,0 +1,95 @@ +# Documentation +- Class name: PixelTiledKSampleUpscalerProvider +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +PixelTiledKSampleUpscalerProvider 是一个旨在通过复杂的放大过程提高图像质量的节点。它利用各种缩放方法,并与高级模型集成,以对图像平铺进行去噪,优化最终输出的清晰度和细节。 + +# Input types +## Required +- scale_method + - 缩放方法定义了用于放大图像的算法。它对于确定放大过程的质量和样式至关重要,影响图像的最终外观。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- model + - 模型参数至关重要,因为它指定了将用于放大任务的机器学习模型。模型的选择对节点的性能和生成的图像质量有显著影响。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- vae + - VAE(变分自编码器)是放大过程中的关键组件,因为它对图像数据进行编码和解码。它在去噪输出的质量中起着关键作用。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- seed + - 种子通过为随机数生成提供一致的起点,确保了放大过程的可重复性,这对于在不同运行中保持结果的完整性至关重要。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步数决定了放大过程的范围。更多的步骤允许得到更精细的结果,但也增加了计算复杂性。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数,通常表示为 'cfg',用于控制放大过程中细节和噪声之间的平衡,影响放大图像的整体清晰度。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 采样器名称决定了去噪步骤中使用的采样策略。它是形成最终图像噪声特性的关键因素。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- scheduler + - 调度器定义了放大过程中参数更新的速度,这可能会影响放大图像的效率和最终质量。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- positive + - 正向条件为模型提供了在放大期间增强或保留哪些特征的指导,这对于实现期望的结果至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- negative + - 负向条件指导模型在放大期间避免某些特征或伪影,确保最终图像符合指定的质量标准。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- denoise + - 去噪参数控制应用于每个平铺的去噪强度。它是平衡图像细节与去除不需要的噪声的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- tile_width + - 平铺宽度指定了放大过程中使用的每个平铺的水平尺寸。它影响平铺策略,并可能影响最终图像的分辨率。 + - Comfy dtype: INT + - Python dtype: int +- tile_height + - 平铺高度指定了放大过程中使用的每个平铺的垂直尺寸。它与平铺宽度一起工作,以确定平铺模式。 + - Comfy dtype: INT + - Python dtype: int +- tiling_strategy + - 平铺策略决定了如何将图像划分为平铺进行处理。它对于管理接缝并确保整个图像的一致放大结果至关重要。 + - Comfy dtype: COMBO[str] + - Python dtype: str + +# Output types +- upscaler + - 放大器输出提供了放大过程后的处理图像。它代表了节点功能的顶点,提供了具有改进分辨率和减少噪声的增强图像。 + - Comfy dtype: UPSCALER + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class PixelTiledKSampleUpscalerProvider: + upscale_methods = ['nearest-exact', 'bilinear', 'lanczos', 'area'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'scale_method': (s.upscale_methods,), 'model': ('MODEL',), 'vae': ('VAE',), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'tile_width': ('INT', {'default': 512, 'min': 320, 'max': MAX_RESOLUTION, 'step': 64}), 'tile_height': ('INT', {'default': 512, 'min': 320, 'max': MAX_RESOLUTION, 'step': 64}), 'tiling_strategy': (['random', 'padded', 'simple'],)}, 'optional': {'upscale_model_opt': ('UPSCALE_MODEL',), 'pk_hook_opt': ('PK_HOOK',)}} + RETURN_TYPES = ('UPSCALER',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + def doit(self, scale_method, model, vae, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, tile_width, tile_height, tiling_strategy, upscale_model_opt=None, pk_hook_opt=None): + if 'BNK_TiledKSampler' in nodes.NODE_CLASS_MAPPINGS: + upscaler = core.PixelTiledKSampleUpscaler(scale_method, model, vae, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, tile_width, tile_height, tiling_strategy, upscale_model_opt, pk_hook_opt, tile_size=max(tile_width, tile_height)) + return (upscaler,) + else: + print("[ERROR] PixelTiledKSampleUpscalerProvider: ComfyUI_TiledKSampler custom node isn't installed. You must install BlenderNeko/ComfyUI_TiledKSampler extension to use this node.") +``` \ No newline at end of file diff --git a/docs/PixelTiledKSampleUpscalerProviderPipe.md b/docs/PixelTiledKSampleUpscalerProviderPipe.md new file mode 100644 index 0000000..027fe33 --- /dev/null +++ b/docs/PixelTiledKSampleUpscalerProviderPipe.md @@ -0,0 +1,93 @@ +# Documentation +- Class name: PixelTiledKSampleUpscalerProviderPipe +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +PixelTiledKSampleUpscalerProviderPipe 是一个用于提供基于平铺采样方法的放大器的节点。它利用 ComfyUI_TiledKSampler 扩展,通过将较大的图像分割成较小的平铺,对图像进行去噪,提高了图像质量而不引入可见的接缝。这个节点特别适用于需要最小化人工制品进行高分辨率图像处理的任务。 + +# Input types +## Required +- scale_method + - 缩放方法决定了图像如何放大。这是一个关键参数,因为它影响放大图像的质量和风格。 + - Comfy dtype: COMBO['nearest-exact', 'bilinear', 'lanczos', 'area'] + - Python dtype: str +- seed + - 种子用于随机数生成过程,确保去噪结果的可复现性。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步数决定了去噪过程的彻底性,通常更多的步数会导致更好的图像质量。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置值 'cfg' 是影响去噪过程的参数,它在降低噪声和保留细节之间进行平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 采样器名称定义了去噪过程中使用的采样策略,这可以显著影响最终图像的外观。 + - Comfy dtype: comfy.samplers.KSampler.SAMPLERS + - Python dtype: str +- scheduler + - 调度器决定了噪过程中参数更新的速率,影响效率和结果。 + - Comfy dtype: comfy.samplers.KSampler.SCHEDULERS + - Python dtype: str +- denoise + - 去噪参数控制去噪效果的强度,较高的值会导致图像更清晰,但可能会丢失细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- tile_width + - 平铺宽度指定了平铺采样过程中每个平铺的宽度,这对于管理内存使用和处理时间很重要。 + - Comfy dtype: INT + - Python dtype: int +- tile_height + - 平铺高度指定了每个平铺的高度,与平铺宽度一起工作,控制平铺网格的尺寸。 + - Comfy dtype: INT + - Python dtype: int +- tiling_strategy + - 平铺策略决定了如何将图像划分为平铺,不同的策略针对不同的结果进行优化,例如减少接缝或与某些采样器的兼容性。 + - Comfy dtype: COMBO['random', 'padded', 'simple'] + - Python dtype: str +- basic_pipe + - 基础管道提供了放大器运行所需的基础组件,如模型和 VAE。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Any +## Optional +- upscale_model_opt + - 一个可选参数,允许在过程中指定一个自定义的放大模型。 + - Comfy dtype: UPSCALE_MODEL + - Python dtype: Optional[Any] +- pk_hook_opt + - 一个可选的钩子,可以在放大过程中用来修改放大器的行为。 + - Comfy dtype: PK_HOOK + - Python dtype: Optional[Any] + +# Output types +- upscaler + - 节点的输出是一个放大器对象,它能够对图像执行放大操作。 + - Comfy dtype: UPSCALER + - Python dtype: core.PixelTiledKSampleUpscaler + +# Usage tips +- Infra type: GPU + +# Source code +``` +class PixelTiledKSampleUpscalerProviderPipe: + upscale_methods = ['nearest-exact', 'bilinear', 'lanczos', 'area'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'scale_method': (s.upscale_methods,), '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': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'tile_width': ('INT', {'default': 512, 'min': 320, 'max': MAX_RESOLUTION, 'step': 64}), 'tile_height': ('INT', {'default': 512, 'min': 320, 'max': MAX_RESOLUTION, 'step': 64}), 'tiling_strategy': (['random', 'padded', 'simple'],), 'basic_pipe': ('BASIC_PIPE',)}, 'optional': {'upscale_model_opt': ('UPSCALE_MODEL',), 'pk_hook_opt': ('PK_HOOK',)}} + RETURN_TYPES = ('UPSCALER',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + def doit(self, scale_method, seed, steps, cfg, sampler_name, scheduler, denoise, tile_width, tile_height, tiling_strategy, basic_pipe, upscale_model_opt=None, pk_hook_opt=None): + if 'BNK_TiledKSampler' in nodes.NODE_CLASS_MAPPINGS: + (model, _, vae, positive, negative) = basic_pipe + upscaler = core.PixelTiledKSampleUpscaler(scale_method, model, vae, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, tile_width, tile_height, tiling_strategy, upscale_model_opt, pk_hook_opt, tile_size=max(tile_width, tile_height)) + return (upscaler,) + else: + print("[ERROR] PixelTiledKSampleUpscalerProviderPipe: ComfyUI_TiledKSampler custom node isn't installed. You must install BlenderNeko/ComfyUI_TiledKSampler extension to use this node.") +``` \ No newline at end of file diff --git a/docs/Pixelize.md b/docs/Pixelize.md new file mode 100644 index 0000000..3595da8 --- /dev/null +++ b/docs/Pixelize.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: Pixelize +- Category: postprocessing/Effects +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +Pixelize节点旨在对输入图像应用像素化效果,将其转换为风格化、块状的表现形式。它通过平均指定像素大小定义的网格内的颜色值来实现这一点,从而将图像的分辨率降低到更抽象的形式。这个节点特别适用于创建复古或艺术性的外观,也可以用于保护隐私的图像处理。 + +# Input types +## Required +- image + - 图像参数是Pixelize节点将要处理的输入。它至关重要,因为它决定了将要进行像素化处理的视觉内容。节点的操作直接受到图像尺寸和像素数据的影响,这对于像素化效果至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- pixel_size + - pixel_size参数决定了像素化效果的粒度。它指定了输出图像中每个像素块的大小。较大的pixel_size值会导致更明显的像素化,而较小的值则保留了更多的细节。这个参数在控制节点处理的风格化结果中起着关键作用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- pixelized_image + - pixelized_image输出代表了像素化处理过程的最终结果。它是一张每个像素块都被平均化以创建风格化、像素化外观的图像。这个输出很重要,因为它体现了节点的主要功能和像素化效果背后的创意意图。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Pixelize: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'pixel_size': ('INT', {'default': 8, 'min': 2, 'max': 128, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'apply_pixelize' + CATEGORY = 'postprocessing/Effects' + + def apply_pixelize(self, image: torch.Tensor, pixel_size: int): + pixelized_image = self.pixelize_image(image, pixel_size) + pixelized_image = torch.clamp(pixelized_image, 0, 1) + return (pixelized_image,) + + def pixelize_image(self, image: torch.Tensor, pixel_size: int): + (batch_size, height, width, channels) = image.shape + new_height = height // pixel_size + new_width = width // pixel_size + image = image.permute(0, 3, 1, 2) + image = F.avg_pool2d(image, kernel_size=pixel_size, stride=pixel_size) + image = F.interpolate(image, size=(height, width), mode='nearest') + image = image.permute(0, 2, 3, 1) + return image +``` \ No newline at end of file diff --git a/docs/Play Sound (loop) .md b/docs/Play Sound (loop) .md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Play Sound.md b/docs/Play Sound.md new file mode 100644 index 0000000..1d70434 --- /dev/null +++ b/docs/Play Sound.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: Play_Sound_Now +- Category: 😺dzNodes +- Output node: True +- Repo Ref: https://github.com/chflame163/ComfyUI_MSSpeech_TTS + +Play_Sound_Now节点旨在实现音频文件的即时播放。它通过加载指定的音效文件,并使用单独的线程执行播放,以最小的干扰保证主程序流程。该节点特别适用于需要音频反馈或警报且延迟较小的应用场景。 + +# Input types +## Required +- path + - ‘path’参数指定了要播放的音频文件的文件路径。它对节点的操作至关重要,因为它指导节点找到正确的音频文件。没有有效的路径,节点将无法工作,因此这是一个必需的参数。 + - Comfy dtype: STRING + - Python dtype: str +- volume + - ‘volume’参数用于调整音频播放的音量。它是一个重要的设置,用于控制音频输出级别,并确保它符合应用的要求。音量可以在0.0到1.0之间设置,其中1.0代表默认的音量。 + - Comfy dtype: FLOAT + - Python dtype: float +- speed + - ‘speed’参数改变音频的播放速度。它对于改变声音的节奏而不改变其音高具有重要意义。速度可以在0.1到2.0之间变化,允许播放速度有多种选择。 + - Comfy dtype: FLOAT + - Python dtype: float +- trigger + - ‘trigger’参数决定是否启动音频播放。它是一个关键的控制,直接影响节点主要功能的执行。如果设置为True,则播放音频;否则将保持静音。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- result + - Play_Sound_Now节点的‘result’参数不返回任何特定数据,但表示音频播放过程的成功启动。它是任何可能的未来增强或与节点操作相关的状态消息的占位符。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Play_Sound_Now: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'path': ('STRING', {'default': 'comfyui.mp3'}), 'volume': ('FLOAT', {'default': 1, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'speed': ('FLOAT', {'default': 1, 'min': 0.1, 'max': 2.0, 'step': 0.1}), 'trigger': ('BOOLEAN', {'default': True})}, 'optional': {}} + RETURN_TYPES = () + FUNCTION = 'do_playsound' + OUTPUT_NODE = True + CATEGORY = '😺dzNodes' + + def do_playsound(self, path, volume, speed, trigger): + print(f'# 😺dzNodes: PlaySound: path={path},volume={volume},speed={speed},trigger={trigger}') + if trigger: + t = threading.Thread(target=Play(path, volume, speed)) + t.start() + return {} +``` \ No newline at end of file diff --git a/docs/Plot Batch Float (mtb).md b/docs/Plot Batch Float (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/PortraitMaster_中文版.md b/docs/PortraitMaster_中文版.md new file mode 100644 index 0000000..38e9ebc --- /dev/null +++ b/docs/PortraitMaster_中文版.md @@ -0,0 +1,217 @@ +# Documentation +- Class name: PortraitMaster_中文版 +- Category: 📸肖像大师 +- Output node: False +- Repo Ref: https://github.com/ZHO-ZHO-ZHO/comfyui-portrait-master-zh-cn + +该节点旨在根据多种可定制参数生成详细的肖像生成提示。它旨在为用户提供一套全面的选项来微调生成过程,从而实现高度个性化和真实的肖像创作。 + +# Input types +## Required +- 镜头类型 + - 该参数决定了生成肖像的镜头类型或视角。它在设置场景和肖像框架中至关重要,从而显著影响最终的视觉结果。 + - Comfy dtype: COMBO[string] + - Python dtype: str +- 性别 + - 性别参数在确定肖像主题的物理特征和整体外观方面至关重要。它指导生成过程产生符合指定性别的主题。 + - Comfy dtype: COMBO[string] + - Python dtype: str +- 年龄 + - 年龄在塑造肖像的面部特征和皮肤细节方面起着重要作用。它有助于生成具有真实年龄特征的主题,确保描绘的真实性。 + - Comfy dtype: INT + - Python dtype: int +- 国籍_1 + - 第一个国籍参数有助于肖像主题的文化和种族背景,影响选择反映特定国籍的特征。 + - Comfy dtype: COMBO[string] + - Python dtype: str +- 国籍_2 + - 第二个国籍参数与第一个结合使用时,允许从两种不同的国籍中混合特征,为肖像增添多样性和复杂性。 + - Comfy dtype: COMBO[string] + - Python dtype: str +- 国籍混合 + - 该参数调整两个国籍的混合比例,确保最终肖像反映出所选种族特征的微妙平衡。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- positive + - 正面输出是一个详细的提示,包含了所有输入参数,作为生成肖像过程的指南。它是至关重要的组成部分,因为它直接影响最终结果。 + - Comfy dtype: STRING + - Python dtype: str +- negative + - 负面输出包含一组旨在从肖像生成中排除的提示。它通过防止不需要的特征或风格被包含,有助于完善最终输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PortraitMaster_中文版: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + shot_file_path = os.path.join(p, 'lists/shot_list.json') + gender_file_path = os.path.join(p, 'lists/gender_list.json') + eyes_color_file_path = os.path.join(p, 'lists/eyes_color_list.json') + face_shape_file_path = os.path.join(p, 'lists/face_shape_list.json') + facial_expressions_file_path = os.path.join(p, 'lists/face_expression_list.json') + nationality_file_path = os.path.join(p, 'lists/nationality_list.json') + hair_style_file_path = os.path.join(p, 'lists/hair_style_list.json') + hair_color_file_path = os.path.join(p, 'lists/hair_color_list.json') + light_type_file_path = os.path.join(p, 'lists/light_type_list.json') + light_direction_file_path = os.path.join(p, 'lists/light_direction_list.json') + body_type_file_path = os.path.join(p, 'lists/body_type_list.json') + beard_file_path = os.path.join(p, 'lists/beard_list.json') + model_pose_file_path = os.path.join(p, 'lists/model_pose_list.json') + self.shot_data = read_json_file(shot_file_path) + self.gender_data = read_json_file(gender_file_path) + self.eyes_color_data = read_json_file(eyes_color_file_path) + self.face_shape_data = read_json_file(face_shape_file_path) + self.facial_expressions_data = read_json_file(facial_expressions_file_path) + self.nationality_data = read_json_file(nationality_file_path) + self.hair_style_data = read_json_file(hair_style_file_path) + self.hair_color_data = read_json_file(hair_color_file_path) + self.light_type_data = read_json_file(light_type_file_path) + self.light_direction_data = read_json_file(light_direction_file_path) + self.body_type_data = read_json_file(body_type_file_path) + self.beard_data = read_json_file(beard_file_path) + self.model_pose_data = read_json_file(model_pose_file_path) + shot_list = get_name(self.shot_data) + shot_list = ['-'] + shot_list + gender_list = get_name(self.gender_data) + gender_list = ['-'] + gender_list + eyes_color_list = get_name(self.eyes_color_data) + eyes_color_list = ['-'] + eyes_color_list + face_shape_list = get_name(self.face_shape_data) + face_shape_list = ['-'] + face_shape_list + facial_expressions_list = get_name(self.facial_expressions_data) + facial_expressions_list = ['-'] + facial_expressions_list + nationality_list = get_name(self.nationality_data) + nationality_list = ['-'] + nationality_list + hair_style_list = get_name(self.hair_style_data) + hair_style_list = ['-'] + hair_style_list + hair_color_list = get_name(self.hair_color_data) + hair_color_list = ['-'] + hair_color_list + light_type_list = get_name(self.light_type_data) + light_type_list = ['-'] + light_type_list + light_direction_list = get_name(self.light_direction_data) + light_direction_list = ['-'] + light_direction_list + body_type_list = get_name(self.body_type_data) + body_type_list = ['-'] + body_type_list + beard_list = get_name(self.beard_data) + beard_list = ['-'] + beard_list + model_pose_list = get_name(self.model_pose_data) + model_pose_list = ['-'] + model_pose_list + max_float_value = 1.75 + return {'required': {'镜头类型': (shot_list, {'default': shot_list[0]}), '镜头权重': ('FLOAT', {'default': 1.5, 'step': 0.05, 'min': 0, 'max': max_float_value, 'display': 'slider'}), '性别': (gender_list, {'default': gender_list[0]}), '年龄': ('INT', {'default': 20, 'min': 18, 'max': 90, 'step': 1, 'display': 'slider'}), '国籍_1': (nationality_list, {'default': nationality_list[0]}), '国籍_2': (nationality_list, {'default': nationality_list[0]}), '国籍混合': ('FLOAT', {'default': 0.5, 'min': 0, 'max': 1, 'step': 0.05, 'display': 'slider'}), '体型': (body_type_list, {'default': body_type_list[0]}), '体型权重': ('FLOAT', {'default': 0, 'step': 0.05, 'min': 0, 'max': max_float_value, 'display': 'slider'}), '姿势': (model_pose_list, {'default': model_pose_list[0]}), '眼睛颜色': (eyes_color_list, {'default': eyes_color_list[0]}), '面部表情': (facial_expressions_list, {'default': facial_expressions_list[0]}), '面部表情权重': ('FLOAT', {'default': 1.5, 'step': 0.05, 'min': 0, 'max': max_float_value, 'display': 'slider'}), '脸型': (face_shape_list, {'default': face_shape_list[0]}), '脸型权重': ('FLOAT', {'default': 1, 'step': 0.05, 'min': 0, 'max': max_float_value, 'display': 'slider'}), '面部对称性': ('FLOAT', {'default': 0.2, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '发型': (hair_style_list, {'default': hair_style_list[0]}), '头发颜色': (hair_color_list, {'default': hair_color_list[0]}), '头发蓬松度': ('FLOAT', {'default': 1, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '胡子': (beard_list, {'default': beard_list[0]}), '皮肤细节': ('FLOAT', {'default': 0.5, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '皮肤毛孔': ('FLOAT', {'default': 0.3, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '酒窝': ('FLOAT', {'default': 0, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '皱纹': ('FLOAT', {'default': 0, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '雀斑': ('FLOAT', {'default': 0, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '痣': ('FLOAT', {'default': 0, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '皮肤瑕疵': ('FLOAT', {'default': 0, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '痘痘': ('FLOAT', {'default': 0, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '小麦色肤色': ('FLOAT', {'default': 0, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '眼睛细节': ('FLOAT', {'default': 1.2, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '虹膜细节': ('FLOAT', {'default': 1.2, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '圆形虹膜': ('FLOAT', {'default': 1.2, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '圆形瞳孔': ('FLOAT', {'default': 1.2, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '灯光类型': (light_type_list, {'default': light_type_list[0]}), '灯光方向': (light_direction_list, {'default': light_direction_list[0]}), '灯光权重': ('FLOAT', {'default': 1.2, 'min': 0, 'max': max_float_value, 'step': 0.05, 'display': 'slider'}), '提高照片真实感': (['enable', 'disable'],), '起始提示词': ('STRING', {'multiline': True, 'default': 'raw photo, (realistic:1.5)'}), '补充提示词': ('STRING', {'multiline': True, 'default': '(white background:1.5)'}), '结束提示词': ('STRING', {'multiline': True, 'default': ''}), '负面提示词': ('STRING', {'multiline': True, 'default': ''})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive', 'negative') + FUNCTION = 'pm' + CATEGORY = '📸肖像大师' + + def pm(self, 镜头类型='-', 镜头权重=1, 性别='-', 体型='-', 体型权重=0, 眼睛颜色='-', 面部表情='-', 面部表情权重=0, 脸型='-', 脸型权重=0, 国籍_1='-', 国籍_2='-', 国籍混合=0.5, 年龄=20, 发型='-', 头发颜色='-', 头发蓬松度=0, 酒窝=0, 雀斑=0, 皮肤毛孔=0, 皮肤细节=0, 痣=0, 皮肤瑕疵=0, 皱纹=0, 小麦色肤色=0, 眼睛细节=1, 虹膜细节=1, 圆形虹膜=1, 圆形瞳孔=1, 面部对称性=0, 补充提示词='', 起始提示词='', 结束提示词='', 灯光类型='-', 灯光方向='-', 灯光权重=0, 负面提示词='', 提高照片真实感='disable', 胡子='-', 姿势='-', 痘痘=0): + shot = get_prompt(self.shot_data, 镜头类型) + gender = get_prompt(self.gender_data, 性别) + eyes_color = get_prompt(self.eyes_color_data, 眼睛颜色) + face_shape = get_prompt(self.face_shape_data, 脸型) + facial_expressions = get_prompt(self.facial_expressions_data, 面部表情) + nationality_1 = get_prompt(self.nationality_data, 国籍_1) + nationality_2 = get_prompt(self.nationality_data, 国籍_2) + hair_style = get_prompt(self.hair_style_data, 发型) + hair_color = get_prompt(self.hair_color_data, 头发颜色) + light_type = get_prompt(self.light_type_data, 灯光类型) + light_direction = get_prompt(self.light_direction_data, 灯光方向) + body_type = get_prompt(self.body_type_data, 体型) + beard = get_prompt(self.beard_data, 胡子) + model_pose = get_prompt(self.model_pose_data, 姿势) + prompt = [] + if 性别 == '-': + 性别 = '' + else: + 性别 = ' ' + gender + ' ' + if 国籍_1 != '-' and 国籍_2 != '-': + Anationality = f'[{nationality_1}:{nationality_2}:{round(国籍混合, 2)}]' + elif 国籍_1 != '-': + Anationality = nationality_1 + ' ' + elif 国籍_2 != '-': + Anationality = nationality_2 + ' ' + else: + Anationality = '' + if 起始提示词 != '': + prompt.append(f'{起始提示词}') + if 镜头类型 != '-' and 镜头权重 > 0: + prompt.append(f'({shot}:{round(镜头权重, 2)})') + prompt.append(f'({Anationality}{性别}{round(年龄)}-years-old:1.5)') + if 体型 != '-' and 体型权重 > 0: + prompt.append(f'({body_type}, {body_type} body:{round(体型权重, 2)})') + if 姿势 != '-': + prompt.append(f'({model_pose}:1.5)') + if 眼睛颜色 != '-': + prompt.append(f'({eyes_color} eyes:1.25)') + if 面部表情 != '-' and 面部表情权重 > 0: + prompt.append(f'({facial_expressions}, {facial_expressions} expression:{round(面部表情权重, 2)})') + if 脸型 != '-' and 脸型权重 > 0: + prompt.append(f'({face_shape} shape face:{round(脸型权重, 2)})') + if 发型 != '-': + prompt.append(f'({hair_style} hairstyle:1.25)') + if 头发颜色 != '-': + prompt.append(f'({hair_color} hair:1.25)') + if 胡子 != '-': + prompt.append(f'({beard}:1.15)') + if 头发蓬松度 != '-': + prompt.append(f'(disheveled:{round(头发蓬松度, 2)})') + if 补充提示词 != '': + prompt.append(f'{补充提示词}') + if 皮肤细节 > 0: + prompt.append(f'(skin details, skin texture:{round(皮肤细节, 2)})') + if 皮肤毛孔 > 0: + prompt.append(f'(skin pores:{round(皮肤毛孔, 2)})') + if 皮肤瑕疵 > 0: + prompt.append(f'(skin imperfections:{round(皮肤瑕疵, 2)})') + if 痘痘 > 0: + prompt.append(f'(acne, skin with acne:{round(痘痘, 2)})') + if 皱纹 > 0: + prompt.append(f'(skin imperfections:{round(皱纹, 2)})') + if 小麦色肤色 > 0: + prompt.append(f'(tanned skin:{round(小麦色肤色, 2)})') + if 酒窝 > 0: + prompt.append(f'(dimples:{round(酒窝, 2)})') + if 雀斑 > 0: + prompt.append(f'(freckles:{round(雀斑, 2)})') + if 痣 > 0: + prompt.append(f'(skin pores:{round(痣, 2)})') + if 眼睛细节 > 0: + prompt.append(f'(eyes details:{round(眼睛细节, 2)})') + if 虹膜细节 > 0: + prompt.append(f'(iris details:{round(虹膜细节, 2)})') + if 圆形虹膜 > 0: + prompt.append(f'(circular iris:{round(圆形虹膜, 2)})') + if 圆形瞳孔 > 0: + prompt.append(f'(circular pupil:{round(圆形瞳孔, 2)})') + if 面部对称性 > 0: + prompt.append(f'(facial asymmetry, face asymmetry:{round(面部对称性, 2)})') + if 灯光类型 != '-' and 灯光权重 > 0: + if 灯光方向 != '-': + prompt.append(f'({light_type} {light_direction}:{round(灯光权重, 2)})') + else: + prompt.append(f'({light_type}:{round(灯光权重, 2)})') + if 结束提示词 != '': + prompt.append(f'{结束提示词}') + prompt = ', '.join(prompt) + prompt = prompt.lower() + if 提高照片真实感 == 'enable': + prompt = prompt + ', (detailed, professional photo, perfect exposition:1.25), (film grain:1.5)' + if 提高照片真实感 == 'enable': + negative_prompt = 负面提示词 + ', (shinny skin, reflections on the skin, skin reflections:1.5)' + else: + negative_prompt = 负面提示词 + print('Portrait Master as generate the prompt:') + print(prompt) + return (prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/PresetRatioSelector.md b/docs/PresetRatioSelector.md new file mode 100644 index 0000000..df60bee --- /dev/null +++ b/docs/PresetRatioSelector.md @@ -0,0 +1,111 @@ +# Documentation +- Class name: PresetRatioSelector +- Category: Mikey/Utils +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +PresetRatioSelector节点旨在根据预设的预设计算和选择图像尺寸。它允许自定义潜在尺寸、内容到边缘比率、目标尺寸和裁剪参数。该节点的主要功能是根据用户定义的预设自动选择图像比例,确保图像操作任务中的一致性和易用性。 + +# Input types +## Required +- select_preset + - select_preset参数对于确定应用哪个预设比例至关重要。它决定了节点计算过程的起点,对于实现所需的图像尺寸至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- swap_axis + - swap_axis参数使用户能够交换所选预设的宽度和高度尺寸。在需要调整图像方向的场景中,这可能很重要。 + - Comfy dtype: STRING + - Python dtype: str +- use_preset_seed + - use_preset_seed参数决定是否使用种子值来选择预设。这可以在选择过程中引入变化性,允许选择更多样化的图像比例集。 + - Comfy dtype: STRING + - Python dtype: str +- seed + - seed参数与use_preset_seed标志一起使用,影响预设比例的选择。它在选择过程中增加了对随机性的控制层。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- unique_id + - unique_id参数用于在系统中唯一标识操作。在更大的工作流程中跟踪和管理节点的执行可能很重要。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +- extra_pnginfo + - extra_pnginfo参数提供与PNG图像格式相关的额外信息。这对于处理与节点操作相关的特定图像属性可能很有用。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: str +- prompt + - prompt参数可用于提供描述性文本,指导节点的操作。它可能会根据文本提供的上下文影响预设的选择。 + - Comfy dtype: PROMPT + - Python dtype: str + +# Output types +- latent_w + - latent_w输出表示计算出的潜在空间的宽度。它是确定潜在表示中图像水平维度的关键参数。 + - Comfy dtype: INT + - Python dtype: int +- latent_h + - latent_h输出表示计算出的潜在空间的高度。它是确定潜在表示中图像垂直维度的关键参数。 + - Comfy dtype: INT + - Python dtype: int +- cte_w + - cte_w输出表示计算出的内容到边缘比率的宽度。它对于保持图像的纵横比和比例很重要。 + - Comfy dtype: INT + - Python dtype: int +- cte_h + - cte_h输出表示计算出的内容到边缘比率的高度。它在保持图像的纵横比和比例方面与cte_w扮演着类似的角色。 + - Comfy dtype: INT + - Python dtype: int +- target_w + - target_w输出表示计算出的图像的目标宽度。它用于指导调整大小或缩放过程,以实现所需的尺寸。 + - Comfy dtype: INT + - Python dtype: int +- target_h + - target_h输出表示计算出的图像的目标高度。它与target_w一起工作,以确保图像的尺寸满足指定的要求。 + - Comfy dtype: INT + - Python dtype: int +- crop_w + - crop_w输出表示计算出的图像裁剪过程的宽度。它对于定义裁剪后图像将可见的区域至关重要。 + - Comfy dtype: INT + - Python dtype: int +- crop_h + - crop_h输出表示计算出的图像裁剪过程的高度。它与crop_w一起工作,以确定裁剪后图像的最终可见区域。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PresetRatioSelector: + + @classmethod + def INPUT_TYPES(s): + (s.ratio_presets, s.ratio_config) = read_ratio_presets() + return {'required': {'select_preset': (s.ratio_presets, {'default': 'none'}), 'swap_axis': (['true', 'false'], {'default': 'false'}), 'use_preset_seed': (['true', 'false'], {'default': 'false'}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('INT', 'INT', 'INT', 'INT', 'INT', 'INT', 'INT', 'INT') + RETURN_NAMES = ('latent_w', 'latent_h', 'cte_w', 'cte_h', 'target_w', 'target_h', 'crop_w', 'crop_h') + CATEGORY = 'Mikey/Utils' + FUNCTION = 'calculate' + + def calculate(self, select_preset, swap_axis, use_preset_seed, seed, unique_id=None, extra_pnginfo=None, prompt=None): + if use_preset_seed == 'true' and len(self.ratio_presets) > 0: + len_presets = len(self.ratio_presets) + offset = seed % (len_presets - 1) + presets = [p for p in self.ratio_presets if p != 'none'] + select_preset = presets[offset] + latent_width = self.ratio_config[select_preset]['custom_latent_w'] + latent_height = self.ratio_config[select_preset]['custom_latent_h'] + cte_w = self.ratio_config[select_preset]['cte_w'] + cte_h = self.ratio_config[select_preset]['cte_h'] + target_w = self.ratio_config[select_preset]['target_w'] + target_h = self.ratio_config[select_preset]['target_h'] + crop_w = self.ratio_config[select_preset]['crop_w'] + crop_h = self.ratio_config[select_preset]['crop_h'] + if swap_axis == 'true': + (latent_width, latent_height) = (latent_height, latent_width) + (cte_w, cte_h) = (cte_h, cte_w) + (target_w, target_h) = (target_h, target_w) + (crop_w, crop_h) = (crop_h, crop_w) + return (latent_width, latent_height, cte_w, cte_h, target_w, target_h, crop_w, crop_h) +``` \ No newline at end of file diff --git a/docs/PreviewBridge.md b/docs/PreviewBridge.md new file mode 100644 index 0000000..aebdacf --- /dev/null +++ b/docs/PreviewBridge.md @@ -0,0 +1,102 @@ +# Documentation +- Class name: PreviewBridge +- Category: ImpactPack/Util +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +PreviewBridge节点旨在处理和管理图像数据,提供输入图像与后续处理阶段之间的桥梁。它负责加载、转换和缓存图像,以优化工作流程并确保系统内视觉数据的有效处理。 + +# Input types +## Required +- images + - ‘images’参数对于节点至关重要,因为它代表了需要处理的输入图像数据。它在节点的执行中扮演着关键角色,因为它直接影响输出和随后的图像操作。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- unique_id + - ‘unique_id’参数对于节点的功能至关重要,因为它唯一地标识节点处理的每个图像或数据集。它确保节点能够准确跟踪和管图像,这对于节点的运行和结果完整性至关重要。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +## Optional +- image + - ‘image’参数作为节点操作中特定图像的可选标识符。它可以用来根据提供的标识符引用或检索特定的图像数据,因此在定制节点行为中扮演着重要角色。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- ui + - ‘ui’输出参数非常重要,因为它包含与节点操作相关的用户界面元素。它通常包括可以显示或用于系统UI内进一步交互的图像数据。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] +- result + - ‘result’输出参数封装了处理后的图像数据和相应的掩码。它是节点功能的关键组成部分,因为它提供了可以用于下游任务或分析的最终输出。 + - Comfy dtype: TUPLE[torch.Tensor, torch.Tensor] + - Python dtype: Tuple[torch.Tensor, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PreviewBridge: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'image': ('STRING', {'default': ''})}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('IMAGE', 'MASK') + FUNCTION = 'doit' + OUTPUT_NODE = True + CATEGORY = 'ImpactPack/Util' + + def __init__(self): + super().__init__() + self.output_dir = folder_paths.get_temp_directory() + self.type = 'temp' + self.prev_hash = None + + @staticmethod + def load_image(pb_id): + is_fail = False + if pb_id not in core.preview_bridge_image_id_map: + is_fail = True + (image_path, ui_item) = core.preview_bridge_image_id_map[pb_id] + if not os.path.isfile(image_path): + is_fail = True + if not is_fail: + i = Image.open(image_path) + i = ImageOps.exif_transpose(i) + image = i.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + if 'A' in i.getbands(): + mask = np.array(i.getchannel('A')).astype(np.float32) / 255.0 + mask = 1.0 - torch.from_numpy(mask) + else: + mask = torch.zeros((64, 64), dtype=torch.float32, device='cpu') + else: + image = empty_pil_tensor() + mask = torch.zeros((64, 64), dtype=torch.float32, device='cpu') + ui_item = {'filename': 'empty.png', 'subfolder': '', 'type': 'temp'} + return (image, mask.unsqueeze(0), ui_item) + + def doit(self, images, image, unique_id): + need_refresh = False + if unique_id not in core.preview_bridge_cache: + need_refresh = True + elif core.preview_bridge_cache[unique_id][0] is not images: + need_refresh = True + if not need_refresh: + (pixels, mask, path_item) = PreviewBridge.load_image(image) + image = [path_item] + else: + res = nodes.PreviewImage().save_images(images, filename_prefix='PreviewBridge/PB-') + image2 = res['ui']['images'] + pixels = images + mask = torch.zeros((64, 64), dtype=torch.float32, device='cpu') + path = os.path.join(folder_paths.get_temp_directory(), 'PreviewBridge', image2[0]['filename']) + core.set_previewbridge_image(unique_id, path, image2[0]) + core.preview_bridge_image_id_map[image] = (path, image2[0]) + core.preview_bridge_image_name_map[unique_id, path] = (image, image2[0]) + core.preview_bridge_cache[unique_id] = (images, image2) + image = image2 + return {'ui': {'images': image}, 'result': (pixels, mask)} +``` \ No newline at end of file diff --git a/docs/PreviewBridgeLatent.md b/docs/PreviewBridgeLatent.md new file mode 100644 index 0000000..4a077d3 --- /dev/null +++ b/docs/PreviewBridgeLatent.md @@ -0,0 +1,132 @@ +# Documentation +- Class name: PreviewBridgeLatent +- Category: ImpactPack/Util +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +PreviewBridgeLatent类作为高效可视化和管理图像潜在表示的桥梁,提供了一种将这些潜在表示转换为预览格式的方法,该格式可以在系统中轻松解释和使用。 + +# Input types +## Required +- latent + - latent参数是必需的,因为它包含了需要可视化的图像的编码表示。它通过提供图像重建过程所需的原始数据,在节点的功能中发挥关键作用。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, Any] +- image + - image参数对节点至关重要,因为它标识了要处理的特定图像。它通过确定要可视化哪个图像的潜在表示来影响节点的执行。 + - Comfy dtype: STRING + - Python dtype: str +- preview_method + - preview_method参数决定了从潜在数据生成视觉表示所使用的方法。它是节点操作的组成部分,因为它根据所选的可视化方法塑造输出图像。 + - Comfy dtype: COMBO + - Python dtype: Union[str, None] +## Optional +- vae_opt + - 当提供vae_opt参数时,允许使用特定的VAE模型来解码潜在数据。它的包含可以显著影响最终预览图像的质量和风格。 + - Comfy dtype: VAE + - Python dtype: Union[torch.nn.Module, None] +- unique_id + - unique_id参数用于跟踪和管理处理过的图像的缓存。它对节点的效率很重要,因为它有助于避免冗余处理,并确保始终可用图像的最新版本。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- ui + - ui输出提供了处理后图像的用户界面表示,其中包括文件名和子文件夹位置等信息。这个输出对于将可视化数据集成到系统用户界面中至关重要。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] +- result + - result输出包含处理后图像的潜在表示和掩码。这个输出是必不可少的,因为它提供了系统内进一步分析或操作所需的原始数据。 + - Comfy dtype: TUPLE + - Python dtype: Tuple[Dict[str, Any], torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PreviewBridgeLatent: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latent': ('LATENT',), 'image': ('STRING', {'default': ''}), 'preview_method': (['Latent2RGB-SDXL', 'Latent2RGB-SD15', 'TAESDXL', 'TAESD15'],)}, 'optional': {'vae_opt': ('VAE',)}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('LATENT', 'MASK') + FUNCTION = 'doit' + OUTPUT_NODE = True + CATEGORY = 'ImpactPack/Util' + + def __init__(self): + super().__init__() + self.output_dir = folder_paths.get_temp_directory() + self.type = 'temp' + self.prev_hash = None + self.prefix_append = '_temp_' + ''.join((random.choice('abcdefghijklmnopqrstupvxyz') for x in range(5))) + + @staticmethod + def load_image(pb_id): + is_fail = False + if pb_id not in core.preview_bridge_image_id_map: + is_fail = True + (image_path, ui_item) = core.preview_bridge_image_id_map[pb_id] + if not os.path.isfile(image_path): + is_fail = True + if not is_fail: + i = Image.open(image_path) + i = ImageOps.exif_transpose(i) + image = i.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + if 'A' in i.getbands(): + mask = np.array(i.getchannel('A')).astype(np.float32) / 255.0 + mask = 1.0 - torch.from_numpy(mask) + else: + mask = None + else: + image = empty_pil_tensor() + mask = None + ui_item = {'filename': 'empty.png', 'subfolder': '', 'type': 'temp'} + return (image, mask, ui_item) + + def doit(self, latent, image, preview_method, vae_opt=None, unique_id=None): + need_refresh = False + if unique_id not in core.preview_bridge_cache: + need_refresh = True + elif core.preview_bridge_cache[unique_id][0] is not latent or (vae_opt is None and core.preview_bridge_cache[unique_id][2] is not None) or (vae_opt is None and core.preview_bridge_cache[unique_id][1] != preview_method) or (vae_opt is not None and core.preview_bridge_cache[unique_id][2] is not vae_opt): + need_refresh = True + if not need_refresh: + (pixels, mask, path_item) = PreviewBridge.load_image(image) + if mask is None: + mask = torch.ones(latent['samples'].shape[2:], dtype=torch.float32, device='cpu').unsqueeze(0) + if 'noise_mask' in latent: + res_latent = latent.copy() + del res_latent['noise_mask'] + else: + res_latent = latent + else: + res_latent = latent.copy() + res_latent['noise_mask'] = mask + res_image = [path_item] + else: + decoded_image = decode_latent(latent, preview_method, vae_opt) + if 'noise_mask' in latent: + mask = latent['noise_mask'] + decoded_pil = to_pil(decoded_image) + inverted_mask = 1 - mask + resized_mask = resize_mask(inverted_mask, (decoded_image.shape[1], decoded_image.shape[2])) + result_pil = apply_mask_alpha_to_pil(decoded_pil, resized_mask) + (full_output_folder, filename, counter, _, _) = folder_paths.get_save_image_path('PreviewBridge/PBL-' + self.prefix_append, folder_paths.get_temp_directory(), result_pil.size[0], result_pil.size[1]) + file = f'{filename}_{counter}.png' + result_pil.save(os.path.join(full_output_folder, file), compress_level=4) + res_image = [{'filename': file, 'subfolder': 'PreviewBridge', 'type': 'temp'}] + else: + mask = torch.ones(latent['samples'].shape[2:], dtype=torch.float32, device='cpu').unsqueeze(0) + res = nodes.PreviewImage().save_images(decoded_image, filename_prefix='PreviewBridge/PBL-') + res_image = res['ui']['images'] + path = os.path.join(folder_paths.get_temp_directory(), 'PreviewBridge', res_image[0]['filename']) + core.set_previewbridge_image(unique_id, path, res_image[0]) + core.preview_bridge_image_id_map[image] = (path, res_image[0]) + core.preview_bridge_image_name_map[unique_id, path] = (image, res_image[0]) + core.preview_bridge_cache[unique_id] = (latent, preview_method, vae_opt, res_image) + res_latent = latent + return {'ui': {'images': res_image}, 'result': (res_latent, mask)} +``` \ No newline at end of file diff --git a/docs/PreviewDetailerHookProvider.md b/docs/PreviewDetailerHookProvider.md new file mode 100644 index 0000000..9259d72 --- /dev/null +++ b/docs/PreviewDetailerHookProvider.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: PreviewDetailerHookProvider +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +PreviewDetailerHookProvider 节点旨在促进图像的增强和详细预览。它通过应用钩子来调整图像质量,确保输出既详细又优化了视觉清晰度。该节点在图像处理任务的预处理阶段发挥关键作用,专注于质量方面以满足特定要求。 + +# Input types +## Required +- quality + - ‘quality’参数对于确定输出图像的细节水平至关重要。它直接影响图像的视觉保真度和文件大小,允许在质量和性能之间取得平衡。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- unique_id + - ‘unique_id’参数作为操作的唯一标识符,确保每个进程可以单独跟踪和管理。它对于可能有多个任务同时运行的异步操作特别重要。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- DETAILER_HOOK + - ‘DETAILER_HOOK’输出提供了进一步处理和增强图像细节的机制。对于需要对图像质量进行复杂操作和微调的任务来说,它非常重要。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: PreviewDetailerHook +- UPSCALER_HOOK + - ‘UPSCALER_HOOK’输出用于放大图像,提高其分辨率而不损害清晰度。对于需要高清视觉效果的应用来说,它至关重要。 + - Comfy dtype: UPSCALER_HOOK + - Python dtype: PreviewDetailerHook + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PreviewDetailerHookProvider: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'quality': ('INT', {'default': 95, 'min': 20, 'max': 100})}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('DETAILER_HOOK', 'UPSCALER_HOOK') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, quality, unique_id): + hook = hooks.PreviewDetailerHook(unique_id, quality) + return (hook, hook) +``` \ No newline at end of file diff --git a/docs/Prompt Multiple Styles Selector.md b/docs/Prompt Multiple Styles Selector.md new file mode 100644 index 0000000..799a709 --- /dev/null +++ b/docs/Prompt Multiple Styles Selector.md @@ -0,0 +1,86 @@ +# Documentation +- Class name: WAS_Prompt_Multiple_Styles_Selector +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Prompt_Multiple_Styles_Selector 类的 `load_style` 方法旨在将多个风格提示集成到一个单一的、连贯的提示字符串中。它通过从预定义的风格文件中选择和组合特定于风格的提示来实现这一点,允许使用各种风格细微差别来定制文本生成过程。 + +# Input types +## Required +- style1 + - 参数 `style1` 对于从风格文件中指定要加载的第一个风格至关重要。它通过确定将包含的风格特征直接影响最终提示的构成。 + - Comfy dtype: str + - Python dtype: str +- style2 + - 参数 `style2` 允许将第二种独特的风格包含在提示中。其选择有助于增加文本生成过程的多样性和丰富性。 + - Comfy dtype: str + - Python dtype: str +- style3 + - 参数 `style3` 允许将第三种风格添加到提示中,进一步增强文本生成可用的风格选项。 + - Comfy dtype: str + - Python dtype: str +- style4 + - 参数 `style4` 用于指定可以混合到提示中的第四种风格。它为文本生成输出提供额外的风格层次。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- positive_string + - 输出参数 `positive_string` 表示编译后的提示,它将选定的风格组合成一个连贯且风格丰富的文本生成提示。 + - Comfy dtype: str + - Python dtype: str +- negative_string + - 输出参数 `negative_string` 捕获从选定风格派生的负面提示,这些提示可以用来细化和引导文本生成过程,使其远离不希望的属性。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Prompt_Multiple_Styles_Selector: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + style_list = [] + if os.path.exists(STYLES_PATH): + with open(STYLES_PATH, 'r') as f: + if len(f.readlines()) != 0: + f.seek(0) + data = f.read() + styles = json.loads(data) + for style in styles.keys(): + style_list.append(style) + if not style_list: + style_list.append('None') + return {'required': {'style1': (style_list,), 'style2': (style_list,), 'style3': (style_list,), 'style4': (style_list,)}} + RETURN_TYPES = (TEXT_TYPE, TEXT_TYPE) + RETURN_NAMES = ('positive_string', 'negative_string') + FUNCTION = 'load_style' + CATEGORY = 'WAS Suite/Text' + + def load_style(self, style1, style2, style3, style4): + styles = {} + if os.path.exists(STYLES_PATH): + with open(STYLES_PATH, 'r') as data: + styles = json.load(data) + else: + cstr(f'The styles file does not exist at `{STYLES_PATH}`. Unable to load styles! Have you imported your AUTOMATIC1111 WebUI styles?').error.print() + return ('', '') + selected_styles = [style1, style2, style3, style4] + for style in selected_styles: + if style not in styles: + print(f"Style '{style}' was not found in the styles file.") + return ('', '') + prompt = '' + negative_prompt = '' + for style in selected_styles: + prompt += styles[style]['prompt'] + ' ' + negative_prompt += styles[style]['negative_prompt'] + ' ' + return (prompt.strip(), negative_prompt.strip()) +``` \ No newline at end of file diff --git a/docs/Prompt Styles Selector.md b/docs/Prompt Styles Selector.md new file mode 100644 index 0000000..ecb1116 --- /dev/null +++ b/docs/Prompt Styles Selector.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: WAS_Prompt_Styles_Selector +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Prompt_Styles_Selector 节点旨在管理和检索文本提示的风格。它在加载预定义风格方面起着关键作用,这些风格对于生成在上下文上相关且风格一致的文本输出至关重要。 + +# Input types +## Required +- style + - ‘style’参数对于确定要加载哪种风格配置至关重要。它通过指定要从可用风格中应用到文本提示的特定风格,影响节点的操作。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- positive_string + - ‘positive_string’输出提供了与所选风格相关联的正面提示,这对于引导文本生成过程朝着期望的方向至关重要。 + - Comfy dtype: str + - Python dtype: str +- negative_string + - ‘negative_string’输出提供了所选择风格对应的负面提示,用于通过阻止不希望出现的元素来完善文本生成。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Prompt_Styles_Selector: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + style_list = [] + if os.path.exists(STYLES_PATH): + with open(STYLES_PATH, 'r') as f: + if len(f.readlines()) != 0: + f.seek(0) + data = f.read() + styles = json.loads(data) + for style in styles.keys(): + style_list.append(style) + if not style_list: + style_list.append('None') + return {'required': {'style': (style_list,)}} + RETURN_TYPES = (TEXT_TYPE, TEXT_TYPE) + RETURN_NAMES = ('positive_string', 'negative_string') + FUNCTION = 'load_style' + CATEGORY = 'WAS Suite/Text' + + def load_style(self, style): + styles = {} + if os.path.exists(STYLES_PATH): + with open(STYLES_PATH, 'r') as data: + styles = json.load(data) + else: + cstr(f'The styles file does not exist at `{STYLES_PATH}`. Unable to load styles! Have you imported your AUTOMATIC1111 WebUI styles?').error.print() + if styles and style != None or style != 'None': + prompt = styles[style]['prompt'] + negative_prompt = styles[style]['negative_prompt'] + else: + prompt = '' + negative_prompt = '' + return (prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/Prompt Weight (WLSH).md b/docs/Prompt Weight (WLSH).md new file mode 100644 index 0000000..f1ae77d --- /dev/null +++ b/docs/Prompt Weight (WLSH).md @@ -0,0 +1,51 @@ +# Documentation +- Class name: WLSH_Prompt_Weight +- Category: WLSH Nodes/text +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点旨在通过应用权重来调整提示的影响,这对于微调生成模型的输出非常关键。它允许用户在一组提示中强调或减弱某些提示,从而控制生成内容的总体方向。 + +# Input types +## Required +- prompt + - 提示是指导生成模型输出的文本输入。它至关重要,因为它为生成的内容设置了上下文和主题。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- weight + - 权重参数调节提示的影响,允许对模型响应进行细微控制。它影响提示在输出中反映的显著程度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- prompt + - 带有应用权重的修改后的提示,可以用作后续节点或模型的输入,现在携带调整后的影响。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Prompt_Weight: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompt': ('STRING', {'multiline': True, 'forceInput': True}), 'weight': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 5.0, 'step': 0.1})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('prompt',) + FUNCTION = 'add_weight' + CATEGORY = 'WLSH Nodes/text' + + def add_weight(self, prompt, weight): + if weight == 1.0: + new_string = prompt + else: + new_string = '(' + prompt + ':' + str(weight) + ')' + return (new_string,) +``` \ No newline at end of file diff --git a/docs/Prompt With SDXL.md b/docs/Prompt With SDXL.md new file mode 100644 index 0000000..c423271 --- /dev/null +++ b/docs/Prompt With SDXL.md @@ -0,0 +1,111 @@ +# Documentation +- Class name: PromptWithSDXL +- Category: Mikey +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +PromptWithSDXL节点旨在处理和生成风格和内容生成任务的提示。它接收正面和负面提示以及样式,并应用各种转换以提高生成内容的质量。该节点能够处理复杂的提示结构,并针对生成高质量输出进行了优化。 + +# Input types +## Required +- positive_prompt + - 正面提示是指导生成具有所需特征内容的关键输入。它在引导输出朝向预期风格和主题方面起着至关重要的作用。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt + - 负面提示通过指定应避免的内容来帮助完善生成过程。它对于确保最终输出不包含不需要的元素非常重要。 + - Comfy dtype: STRING + - Python dtype: str +- positive_style + - 正面样式参数定义了要在生成内容中强调的风格元素。这对于实现和谐一致的审美至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- negative_style + - 该输入允许用户指定应最小化或排除在生成内容之外的样式,确保最终输出符合用户的偏好。 + - Comfy dtype: STRING + - Python dtype: str +- ratio_selected + - 所选比例参数确定生成内容的纵横比,这对于保持输出的视觉完整性至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- batch_size + - 批次大小是一个可选参数,允许用户控制单次操作中生成的样本数量。它可以根据可用的计算资源进行调整。 + - Comfy dtype: INT + - Python dtype: int +- seed + - 种子参数用于以可控的方式引入随机性,这对于生成多样化的输出集非常有用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- samples + - 样本输出包含生成的潜在表示,这是内容生成过程的核心。这些表示可以进一步细化以产生最终输出。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- positive_prompt_text_g + - 正面提示文本输出提供了在应用了所有转换之后的正面提示的最终形式。它反映了要包含在生成内容中的所需特征。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 此输出在处理后呈现负面提示文本,详细说明了应从生成内容中省略的元素。 + - Comfy dtype: STRING + - Python dtype: str +- positive_style_text_l + - 正面样式文本输出代表了已处理并准备影响内容生成的最终样式偏好。 + - Comfy dtype: STRING + - Python dtype: str +- negative_style_text_l + - 此输出包含处理后的负面样式文本,指示应在生成内容中避免的风格元素。 + - Comfy dtype: STRING + - Python dtype: str +- width + - 宽度参数指示生成内容的宽度,这对于保持所需的纵横比和视觉呈现至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数指定生成内容的高度,与宽度配合使用,以确保适当的显示和纵横比。 + - Comfy dtype: INT + - Python dtype: int +- refiner_width + - 细化器宽度输出决定了细化过程的宽度,这对于生成内容的最终质量很重要。 + - Comfy dtype: INT + - Python dtype: int +- refiner_height + - 此输出指定细化过程的高度,确保生成的内容细节适当且与所需的规格相符。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptWithSDXL: + + @classmethod + def INPUT_TYPES(s): + (s.ratio_sizes, s.ratio_dict) = read_ratios() + return {'required': {'positive_prompt': ('STRING', {'multiline': True, 'default': 'Positive Prompt'}), 'negative_prompt': ('STRING', {'multiline': True, 'default': 'Negative Prompt'}), 'positive_style': ('STRING', {'multiline': True, 'default': 'Positive Style'}), 'negative_style': ('STRING', {'multiline': True, 'default': 'Negative Style'}), 'ratio_selected': (s.ratio_sizes,), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = ('LATENT', 'STRING', 'STRING', 'STRING', 'STRING', 'INT', 'INT', 'INT', 'INT') + RETURN_NAMES = ('samples', 'positive_prompt_text_g', 'negative_prompt_text_g', 'positive_style_text_l', 'negative_style_text_l', 'width', 'height', 'refiner_width', 'refiner_height') + FUNCTION = 'start' + CATEGORY = 'Mikey' + OUTPUT_NODE = True + + def start(self, positive_prompt, negative_prompt, positive_style, negative_style, ratio_selected, batch_size, seed, prompt=None, extra_pnginfo=None): + positive_prompt = search_and_replace(positive_prompt, extra_pnginfo, prompt) + negative_prompt = search_and_replace(negative_prompt, extra_pnginfo, prompt) + positive_prompt = process_random_syntax(positive_prompt, seed) + negative_prompt = process_random_syntax(negative_prompt, seed) + positive_prompt = find_and_replace_wildcards(positive_prompt, seed) + negative_prompt = find_and_replace_wildcards(negative_prompt, seed) + width = self.ratio_dict[ratio_selected]['width'] + height = self.ratio_dict[ratio_selected]['height'] + latent = torch.zeros([batch_size, 4, height // 8, width // 8]) + ratio = min([width, height]) / max([width, height]) + (target_width, target_height) = (4096, 4096 * ratio // 8 * 8) if width > height else (4096 * ratio // 8 * 8, 4096) + refiner_width = target_width + refiner_height = target_height + return ({'samples': latent}, str(positive_prompt), str(negative_prompt), str(positive_style), str(negative_style), width, height, refiner_width, refiner_height) +``` \ No newline at end of file diff --git a/docs/Prompt With Style V2.md b/docs/Prompt With Style V2.md new file mode 100644 index 0000000..e236026 --- /dev/null +++ b/docs/Prompt With Style V2.md @@ -0,0 +1,104 @@ +# Documentation +- Class name: PromptWithStyleV2 +- Category: Mikey +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +PromptWithStyleV2 节点旨在生成并细化具有指定风格的提示,确保生成的内容与期望的艺术或主题方向一致。它利用正负提示以及风格参数的组合来指导创作过程,从而产生反映输入标准的细腻输出。 + +# Input types +## Required +- positive_prompt + - 正向提示是指导内容生成的关键输入,它设定了创造性的基调,并有助于在输出中实现预期的风格和主题元素。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt + - 负向提示用于排除生成内容中不需要的元素或特征。它通过指定应避免的内容来细化输出,从而增强结果的整体一致性和专注度。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格参数对于定义生成内容的美学或主题方向至关重要。它影响艺术元素的选择以及输出的整体外观和感觉。 + - Comfy dtype: STRING + - Python dtype: str +- ratio_selected + - ratio_selected 参数确定生成内容的宽高比,这对于保持所需的视觉构图和布局至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- clip_base + - clip_base 参数是用于将文本提示编码和解码为潜在空间表示的基础 CLIP 模型的引用。 + - Comfy dtype: CLIP + - Python dtype: CLIP +- clip_refiner + - clip_refiner 参数表示用于进一步提高生成提示的质量和特异性的精炼 CLIP 模型。 + - Comfy dtype: CLIP + - Python dtype: CLIP +## Optional +- batch_size + - 批次大小是一个可选参数,允许用户控制单次操作中生成的样本数量。它可以根据计算资源和手头任务的具体要求进行调整。 + - Comfy dtype: INT + - Python dtype: int +- seed + - 种子是一个可选参数,确保生成过程的可重复性。当在多次运行中需要一致的结果时,它特别有用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- samples + - 样本输出包含生成的潜在表示,可以进一步处理或用作工作流中其他节点的输入。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- base_pos_cond + - base_pos_cond 输出提供基于基础 CLIP 模型的正向调节信息,可用于引导生成过程朝着期望的特征发展。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- base_neg_cond + - base_neg_cond 输出提供基于基础 CLIP 模型的负向调节信息,有助于避免生成内容中的不需要的元素。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- refiner_pos_cond + - refiner_pos_cond 输出呈现来自精炼 CLIP 模型的正向调节,增强了生成提示的特异性和质量。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- refiner_neg_cond + - refiner_neg_cond 输出提供来自精炼 CLIP 模型的负向调节,确保生成的内容遵守指定的约束并避免某些特征。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- positive_prompt + - positive_prompt 输出反映了生成过程中使用的最终正向提示,包含了已编码到输出中的所需品质和主题。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt + - negative_prompt 输出代表生成过程中使用的最终负向提示,指定了应从生成内容中省略的元素和特征。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptWithStyleV2: + + @classmethod + def INPUT_TYPES(s): + (s.ratio_sizes, s.ratio_dict) = read_ratios() + (s.styles, s.pos_style, s.neg_style) = read_styles() + return {'required': {'positive_prompt': ('STRING', {'multiline': True, 'default': 'Positive Prompt'}), 'negative_prompt': ('STRING', {'multiline': True, 'default': 'Negative Prompt'}), 'style': (s.styles,), 'ratio_selected': (s.ratio_sizes,), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'clip_base': ('CLIP',), 'clip_refiner': ('CLIP',)}} + RETURN_TYPES = ('LATENT', 'CONDITIONING', 'CONDITIONING', 'CONDITIONING', 'CONDITIONING', 'STRING', 'STRING') + RETURN_NAMES = ('samples', 'base_pos_cond', 'base_neg_cond', 'refiner_pos_cond', 'refiner_neg_cond', 'positive_prompt', 'negative_prompt') + FUNCTION = 'start' + CATEGORY = 'Mikey' + + def start(self, clip_base, clip_refiner, positive_prompt, negative_prompt, style, ratio_selected, batch_size, seed): + """ get output from PromptWithStyle.start """ + (latent, pos_prompt, neg_prompt, pos_style, neg_style, width, height, refiner_width, refiner_height) = PromptWithStyle.start(self, positive_prompt, negative_prompt, style, ratio_selected, batch_size, seed) + ratio = min([width, height]) / max([width, height]) + (target_width, target_height) = (4096, 4096 * ratio // 8 * 8) if width > height else (4096 * ratio // 8 * 8, 4096) + refiner_width = target_width + refiner_height = target_height + sdxl_pos_cond = CLIPTextEncodeSDXL.encode(self, clip_base, width, height, 0, 0, target_width, target_height, pos_prompt, pos_style)[0] + sdxl_neg_cond = CLIPTextEncodeSDXL.encode(self, clip_base, width, height, 0, 0, target_width, target_height, neg_prompt, neg_style)[0] + refiner_pos_cond = CLIPTextEncodeSDXLRefiner.encode(self, clip_refiner, 6, refiner_width, refiner_height, pos_prompt)[0] + refiner_neg_cond = CLIPTextEncodeSDXLRefiner.encode(self, clip_refiner, 2.5, refiner_width, refiner_height, neg_prompt)[0] + return (latent, sdxl_pos_cond, sdxl_neg_cond, refiner_pos_cond, refiner_neg_cond, pos_prompt, neg_prompt) +``` \ No newline at end of file diff --git a/docs/Prompt With Style V3.md b/docs/Prompt With Style V3.md new file mode 100644 index 0000000..48a7508 --- /dev/null +++ b/docs/Prompt With Style V3.md @@ -0,0 +1,318 @@ +# Documentation +- Class name: PromptWithStyleV3 +- Category: Mikey +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +PromptWithStyleV3节点旨在基于正面和负面提示的组合以及可选的风格规格生成图像样本。它管理将风格和条件融入图像生成过程的复杂性,提供了一种无缝的方式来根据所需特征影响输出。该节点抽象了应用风格和条件采样的复杂性,为用户提供了一个简单的界面来实现风格化的图像合成。 + +# Input types +## Required +- positive_prompt + - 正面提示是一种描述性文本,指导图像生成朝着期望的特征发展。它在引导创作过程朝着与用户愿景一致的图像产生方面起着至关重要的作用。节点依赖正面提示来确定在生成的图像中应该强调哪些方面。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt + - 负面提示作为正面提示的对立面,指导图像生成避免不需要的特征或元素。它是一个重要的参数,用于微调输出并确保生成的图像排除用户希望避免的某些特征。 + - Comfy dtype: STRING + - Python dtype: str +- ratio_selected + - 选定的比率参数决定了生成图像的宽高比。它是设置输出尺寸的关键因素,允许用户从一系列预定义的比率中选择或指定自定义比率,以控制生成图像的形状。 + - Comfy dtype: COMBO[INT] + - Python dtype: List[int] +## Optional +- custom_size + - 自定义尺寸输入允许用户为生成的图像指定非标准尺寸。启用时,用户可以输入自定义的宽度和高度,使他们可以完全控制输出图像的尺寸,这对于特定的显示要求或设计限制非常有用。 + - Comfy dtype: STRING + - Python dtype: str +- fit_custom_size + - 适应自定义尺寸参数与自定义尺寸输入一起使用,以确定生成的图像应如何适应指定的尺寸。它决定了图像是否应该缩放以适应或裁剪以匹配用户提供的确切尺寸。 + - Comfy dtype: STRING + - Python dtype: str +- custom_width + - 当启用自定义图像尺寸时,自定义宽度参数设置生成图像的宽度。它与自定义高度参数协同工作,以定义输出的确切尺寸,允许对图像的宽度进行精确控制。 + - Comfy dtype: INT + - Python dtype: int +- custom_height + - 自定义高度参数与自定义宽度一起使用,确定生成图像的垂直尺寸。当输出需要特定的高度要求时,它特别有用,使用户能够精确控制图像的高度。 + - Comfy dtype: INT + - Python dtype: int +- batch_size + - 批次大小参数定义了单次处理中生成的图像数量。它是管理计算资源的重要因素,可以影响图像生成过程的效率。调整批次大小可以帮助在性能和一次生成的图像数量之间取得平衡。 + - Comfy dtype: INT + - Python dtype: int +- seed + - 种子参数用于在图像生成过程中引入随机性。它确保使用相同种子的每次运行产生一组确定的图像,这对于获得一致的结果或通过实验微调生成过程非常有用。 + - Comfy dtype: INT + - Python dtype: int +- target_mode + - 目标模式参数指定了生成图像的缩放策略。它允许用户选择不同的缩放选项,例如加倍或四倍大小,这可能会影响输出图像的细节水平和整体外观。 + - Comfy dtype: COMBO[STRING] + - Python dtype: List[str] +- base_model + - 基础模型参数指的是用于图像生成的底层模型。它是一个关键组件,决定了生成图像的质量和风格。用户可以从一系列预训练模型中选择,以实现不同的艺术效果。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip_base + - CLIP基础参数与用于文本到图像转换的CLIP模型相关联。它在文本提示如何被解释和转换为视觉元素中起着重要作用。CLIP基础的选择可以影响生成图像的主题连贯性和风格细节。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- clip_refiner + - CLIP细化参数用于通过应用次级处理步骤来提高生成图像的质量。它是一个可选组件,可以为用户提供对输出的细微细节和风格元素的额外控制,使用户能够实现更精致和细化的结果。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module + +# Output types +- base_model + - 基础模型输出提供了用于图像生成过程的底层模型。它是一个关键组件,定义了图像合成任务的基础架构和能力。此输出可用于进一步处理或分析模型本身。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- samples + - 样本输出包含生成的图像样本,这是图像生成过程的主要结果。这些样本体现了输入提示和风格的视觉效果,提供了可以查看、展示或进一步操作的有形结果。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- base_pos_cond + - 基础正面条件输出代表了从基础模型派生的正面条件向量。它用于指导图像生成过程,以产生与提示中指定的正面方面相符的图像。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- base_neg_cond + - 基础负面条件输出是帮助将图像生成引导远离不需要的特征的负面条件向量。它是确保生成的图像不包含与用户偏好不一致的元素的重要部分。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- refiner_pos_cond + - 细化正面条件输出是在图像生成的次级处理步骤中应用的增强正面条件向量。它用于进一步细化图像,确保它们与期望的正面属性紧密匹配。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- refiner_neg_cond + - 细化负面条件输出是用于微调图像生成过程并排除更复杂的不需要特征的增强负面条件向量。它有助于在最终输出图像中实现更高水平的细节和精度。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- positive_prompt + - 正面提示输出反映了在图像生成中使用的已处理正面提示文本。它是指导模型创建具有所需特征的图像的文本输入,可用于参考或进一步分析。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt + - 负面提示输出是帮助通过避免某些特征来塑造图像生成的已处理负面提示文本。它是确保生成的图像遵守用户约束并且不包含不需要的元素的关键组件。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class PromptWithStyleV3: + + def __init__(self): + self.loaded_lora = None + + @classmethod + def INPUT_TYPES(s): + (s.ratio_sizes, s.ratio_dict) = read_ratios() + (s.styles, s.pos_style, s.neg_style) = read_styles() + s.fit = ['true', 'false'] + s.custom_size = ['true', 'false'] + return {'required': {'positive_prompt': ('STRING', {'multiline': True, 'default': 'Positive Prompt'}), 'negative_prompt': ('STRING', {'multiline': True, 'default': 'Negative Prompt'}), 'ratio_selected': (s.ratio_sizes,), 'custom_size': (s.custom_size, {'default': 'false'}), 'fit_custom_size': (s.fit,), 'custom_width': ('INT', {'default': 1024, 'min': 1, 'max': 8192, 'step': 1}), 'custom_height': ('INT', {'default': 1024, 'min': 1, 'max': 8192, 'step': 1}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'target_mode': (['match', '2x', '4x', '2x90', '4x90', '2048', '2048-90', '4096', '4096-90'], {'default': '4x'}), 'base_model': ('MODEL',), 'clip_base': ('CLIP',), 'clip_refiner': ('CLIP',)}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('MODEL', 'LATENT', 'CONDITIONING', 'CONDITIONING', 'CONDITIONING', 'CONDITIONING', 'STRING', 'STRING') + RETURN_NAMES = ('base_model', 'samples', 'base_pos_cond', 'base_neg_cond', 'refiner_pos_cond', 'refiner_neg_cond', 'positive_prompt', 'negative_prompt') + FUNCTION = 'start' + CATEGORY = 'Mikey' + + def extract_and_load_loras(self, text, model, clip): + lora_re = '' + lora_prompts = re.findall(lora_re, text) + stripped_text = text + if len(lora_prompts) > 0: + for lora_prompt in lora_prompts: + lora_filename = lora_prompt[0] + if '.safetensors' not in lora_filename: + lora_filename += '.safetensors' + try: + lora_multiplier = float(lora_prompt[1]) if lora_prompt[1] != '' else 1.0 + except: + lora_multiplier = 1.0 + (model, clip) = load_lora(model, clip, lora_filename, lora_multiplier, lora_multiplier) + stripped_text = stripped_text.replace(f'', '') + stripped_text = stripped_text.replace(f'', '') + return (model, clip, stripped_text) + + def parse_prompts(self, positive_prompt, negative_prompt, style, seed): + positive_prompt = find_and_replace_wildcards(positive_prompt, seed, debug=True) + negative_prompt = find_and_replace_wildcards(negative_prompt, seed, debug=True) + if '{prompt}' in self.pos_style[style]: + positive_prompt = self.pos_style[style].replace('{prompt}', positive_prompt) + if positive_prompt == '' or positive_prompt == 'Positive Prompt' or positive_prompt is None: + pos_prompt = self.pos_style[style] + else: + pos_prompt = positive_prompt + ', ' + self.pos_style[style] + if negative_prompt == '' or negative_prompt == 'Negative Prompt' or negative_prompt is None: + neg_prompt = self.neg_style[style] + else: + neg_prompt = negative_prompt + ', ' + self.neg_style[style] + return (pos_prompt, neg_prompt) + + def start(self, base_model, clip_base, clip_refiner, positive_prompt, negative_prompt, ratio_selected, batch_size, seed, custom_size='false', fit_custom_size='false', custom_width=1024, custom_height=1024, target_mode='match', unique_id=None, extra_pnginfo=None, prompt=None): + if extra_pnginfo is None: + extra_pnginfo = {'PromptWithStyle': {}} + prompt_with_style = extra_pnginfo.get('PromptWithStyle', {}) + add_metadata_to_dict(prompt_with_style, positive_prompt=positive_prompt, negative_prompt=negative_prompt, ratio_selected=ratio_selected, batch_size=batch_size, seed=seed, custom_size=custom_size, fit_custom_size=fit_custom_size, custom_width=custom_width, custom_height=custom_height, target_mode=target_mode) + if custom_size == 'true': + if fit_custom_size == 'true': + if custom_width == 1 and custom_height == 1: + (width, height) = (1024, 1024) + if custom_width == custom_height: + (width, height) = (1024, 1024) + if f'{custom_width}:{custom_height}' in self.ratio_dict: + (width, height) = self.ratio_dict[f'{custom_width}:{custom_height}'] + else: + (width, height) = find_latent_size(custom_width, custom_height) + else: + (width, height) = (custom_width, custom_height) + else: + width = self.ratio_dict[ratio_selected]['width'] + height = self.ratio_dict[ratio_selected]['height'] + latent = torch.zeros([batch_size, 4, height // 8, width // 8]) + ratio = min([width, height]) / max([width, height]) + if target_mode == 'match': + (target_width, target_height) = (width, height) + (refiner_width, refiner_height) = (width * 4, height * 4) + elif target_mode == '2x': + (target_width, target_height) = (width * 2, height * 2) + (refiner_width, refiner_height) = (width * 4, height * 4) + elif target_mode == '4x': + (target_width, target_height) = (width * 4, height * 4) + (refiner_width, refiner_height) = (width * 4, height * 4) + elif target_mode == '2x90': + (target_width, target_height) = (height * 2, width * 2) + (refiner_width, refiner_height) = (width * 4, height * 4) + elif target_mode == '4x90': + (target_width, target_height) = (height * 4, width * 4) + (refiner_width, refiner_height) = (width * 4, height * 4) + elif target_mode == '4096': + (target_width, target_height) = (4096, 4096 * ratio // 8 * 8) if width > height else (4096 * ratio // 8 * 8, 4096) + (refiner_width, refiner_height) = (width * 4, height * 4) + elif target_mode == '4096-90': + (target_width, target_height) = (4096, 4096 * ratio // 8 * 8) if width < height else (4096 * ratio // 8 * 8, 4096) + (refiner_width, refiner_height) = (width * 4, height * 4) + elif target_mode == '2048': + (target_width, target_height) = (2048, 2048 * ratio // 8 * 8) if width > height else (2048 * ratio // 8 * 8, 2048) + (refiner_width, refiner_height) = (width * 4, height * 4) + elif target_mode == '2048-90': + (target_width, target_height) = (2048, 2048 * ratio // 8 * 8) if width < height else (2048 * ratio // 8 * 8, 2048) + (refiner_width, refiner_height) = (width * 4, height * 4) + add_metadata_to_dict(prompt_with_style, width=width, height=height, target_width=target_width, target_height=target_height, refiner_width=refiner_width, refiner_height=refiner_height, crop_w=0, crop_h=0) + positive_prompt = search_and_replace(positive_prompt, extra_pnginfo, prompt) + negative_prompt = search_and_replace(negative_prompt, extra_pnginfo, prompt) + positive_prompt = process_random_syntax(positive_prompt, seed) + negative_prompt = process_random_syntax(negative_prompt, seed) + user_added_style = False + if '$style' in positive_prompt: + self.styles.append('user_added_style') + self.pos_style['user_added_style'] = positive_prompt.split('$style')[1].strip() + self.neg_style['user_added_style'] = '' + user_added_style = True + if '$style' in negative_prompt: + if 'user_added_style' not in self.styles: + self.styles.append('user_added_style') + self.neg_style['user_added_style'] = negative_prompt.split('$style')[1].strip() + user_added_style = True + if user_added_style: + positive_prompt = positive_prompt.split('$style')[0].strip() + if '$style' in negative_prompt: + negative_prompt = negative_prompt.split('$style')[0].strip() + positive_prompt = positive_prompt + '' + positive_prompt_ = find_and_replace_wildcards(positive_prompt, seed, True) + negative_prompt_ = find_and_replace_wildcards(negative_prompt, seed, True) + add_metadata_to_dict(prompt_with_style, positive_prompt=positive_prompt_, negative_prompt=negative_prompt_) + if len(positive_prompt_) != len(positive_prompt) or len(negative_prompt_) != len(negative_prompt): + seed += random.randint(0, 1000000) + positive_prompt = positive_prompt_ + negative_prompt = negative_prompt_ + (base_model, clip_base_pos, pos_prompt) = self.extract_and_load_loras(positive_prompt, base_model, clip_base) + (base_model, clip_base_neg, neg_prompt) = self.extract_and_load_loras(negative_prompt, base_model, clip_base) + style_re = '' + pos_style_prompts = re.findall(style_re, pos_prompt) + neg_style_prompts = re.findall(style_re, neg_prompt) + style_prompts = pos_style_prompts + neg_style_prompts + base_pos_conds = [] + base_neg_conds = [] + refiner_pos_conds = [] + refiner_neg_conds = [] + if len(style_prompts) == 0: + style_ = 'none' + (pos_prompt_, neg_prompt_) = self.parse_prompts(positive_prompt, negative_prompt, style_, seed) + (pos_style_, neg_style_) = (pos_prompt_, neg_prompt_) + (pos_prompt_, neg_prompt_) = (strip_all_syntax(pos_prompt_), strip_all_syntax(neg_prompt_)) + (pos_style_, neg_style_) = (strip_all_syntax(pos_style_), strip_all_syntax(neg_style_)) + add_metadata_to_dict(prompt_with_style, style=style_, clip_g_positive=pos_prompt, clip_l_positive=pos_style_) + add_metadata_to_dict(prompt_with_style, clip_g_negative=neg_prompt, clip_l_negative=neg_style_) + sdxl_pos_cond = CLIPTextEncodeSDXL.encode(self, clip_base_pos, width, height, 0, 0, target_width, target_height, pos_prompt_, pos_style_)[0] + sdxl_neg_cond = CLIPTextEncodeSDXL.encode(self, clip_base_neg, width, height, 0, 0, target_width, target_height, neg_prompt_, neg_style_)[0] + refiner_pos_cond = CLIPTextEncodeSDXLRefiner.encode(self, clip_refiner, 6, refiner_width, refiner_height, pos_prompt_)[0] + refiner_neg_cond = CLIPTextEncodeSDXLRefiner.encode(self, clip_refiner, 2.5, refiner_width, refiner_height, neg_prompt_)[0] + return (base_model, {'samples': latent}, sdxl_pos_cond, sdxl_neg_cond, refiner_pos_cond, refiner_neg_cond, pos_prompt_, neg_prompt_, {'extra_pnginfo': extra_pnginfo}) + for style_prompt in style_prompts: + ' get output from PromptWithStyle.start ' + style_ = style_prompt + if style_ not in self.styles: + style_search = next((x for x in self.styles if x.lower() == style_.lower()), None) + if style_search is None: + style_ = 'none' + continue + else: + style_ = style_search + pos_prompt_ = re.sub(style_re, '', pos_prompt) + neg_prompt_ = re.sub(style_re, '', neg_prompt) + (pos_prompt_, neg_prompt_) = self.parse_prompts(pos_prompt_, neg_prompt_, style_, seed) + (pos_style_, neg_style_) = (str(self.pos_style[style_]), str(self.neg_style[style_])) + (pos_prompt_, neg_prompt_) = (strip_all_syntax(pos_prompt_), strip_all_syntax(neg_prompt_)) + (pos_style_, neg_style_) = (strip_all_syntax(pos_style_), strip_all_syntax(neg_style_)) + add_metadata_to_dict(prompt_with_style, style=style_, positive_prompt=pos_prompt_, negative_prompt=neg_prompt_, positive_style=pos_style_, negative_style=neg_style_) + (width_, height_) = (width, height) + (refiner_width_, refiner_height_) = (refiner_width, refiner_height) + add_metadata_to_dict(prompt_with_style, style=style_, clip_g_positive=pos_prompt_, clip_l_positive=pos_style_) + add_metadata_to_dict(prompt_with_style, clip_g_negative=neg_prompt_, clip_l_negative=neg_style_) + base_pos_conds.append(CLIPTextEncodeSDXL.encode(self, clip_base_pos, width_, height_, 0, 0, target_width, target_height, pos_prompt_, pos_style_)[0]) + base_neg_conds.append(CLIPTextEncodeSDXL.encode(self, clip_base_neg, width_, height_, 0, 0, target_width, target_height, neg_prompt_, neg_style_)[0]) + refiner_pos_conds.append(CLIPTextEncodeSDXLRefiner.encode(self, clip_refiner, 6, refiner_width_, refiner_height_, pos_prompt_)[0]) + refiner_neg_conds.append(CLIPTextEncodeSDXLRefiner.encode(self, clip_refiner, 2.5, refiner_width_, refiner_height_, neg_prompt_)[0]) + if len(base_pos_conds) == 0: + style_ = 'none' + (pos_prompt_, neg_prompt_) = self.parse_prompts(positive_prompt, negative_prompt, style_, seed) + (pos_style_, neg_style_) = (pos_prompt_, neg_prompt_) + (pos_prompt_, neg_prompt_) = (strip_all_syntax(pos_prompt_), strip_all_syntax(neg_prompt_)) + (pos_style_, neg_style_) = (strip_all_syntax(pos_style_), strip_all_syntax(neg_style_)) + add_metadata_to_dict(prompt_with_style, style=style_, clip_g_positive=pos_prompt_, clip_l_positive=pos_style_) + add_metadata_to_dict(prompt_with_style, clip_g_negative=neg_prompt_, clip_l_negative=neg_style_) + sdxl_pos_cond = CLIPTextEncodeSDXL.encode(self, clip_base_pos, width, height, 0, 0, target_width, target_height, pos_prompt_, pos_style_)[0] + sdxl_neg_cond = CLIPTextEncodeSDXL.encode(self, clip_base_neg, width, height, 0, 0, target_width, target_height, neg_prompt_, neg_style_)[0] + refiner_pos_cond = CLIPTextEncodeSDXLRefiner.encode(self, clip_refiner, 6, refiner_width, refiner_height, pos_prompt_)[0] + refiner_neg_cond = CLIPTextEncodeSDXLRefiner.encode(self, clip_refiner, 2.5, refiner_width, refiner_height, neg_prompt_)[0] + return (base_model, {'samples': latent}, sdxl_pos_cond, sdxl_neg_cond, refiner_pos_cond, refiner_neg_cond, pos_prompt_, neg_prompt_, {'extra_pnginfo': extra_pnginfo}) + sdxl_pos_cond = base_pos_conds[0] + weight = 1 + if len(base_pos_conds) > 1: + for i in range(1, len(base_pos_conds)): + weight += 1 + sdxl_pos_cond = ConditioningAverage.addWeighted(self, base_pos_conds[i], sdxl_pos_cond, 1 / weight)[0] + sdxl_neg_cond = base_neg_conds[0] + weight = 1 + if len(base_neg_conds) > 1: + for i in range(1, len(base_neg_conds)): + weight += 1 + sdxl_neg_cond = ConditioningAverage.addWeighted(self, base_neg_conds[i], sdxl_neg_cond, 1 / weight)[0] + refiner_pos_cond = refiner_pos_conds[0] + weight = 1 + if len(refiner_pos_conds) > 1: + for i in range(1, len(refiner_pos_conds)): + weight += 1 + refiner_pos_cond = ConditioningAverage.addWeighted(self, refiner_pos_conds[i], refiner_pos_cond, 1 / weight)[0] + refiner_neg_cond = refiner_neg_conds[0] + weight = 1 + if len(refiner_neg_conds) > 1: + for i in range(1, len(refiner_neg_conds)): + weight += 1 + refiner_neg_cond = ConditioningAverage.addWeighted(self, refiner_neg_conds[i], refiner_neg_cond, 1 / weight)[0] + extra_pnginfo['PromptWithStyle'] = prompt_with_style + return (base_model, {'samples': latent}, sdxl_pos_cond, sdxl_neg_cond, refiner_pos_cond, refiner_neg_cond, pos_prompt_, neg_prompt_, {'extra_pnginfo': extra_pnginfo}) +``` \ No newline at end of file diff --git a/docs/Prompt With Style.md b/docs/Prompt With Style.md new file mode 100644 index 0000000..da46d9b --- /dev/null +++ b/docs/Prompt With Style.md @@ -0,0 +1,121 @@ +# Documentation +- Class name: PromptWithStyle +- Category: Mikey +- Output node: True +- Repo Ref: https://github.com/bash-j/mikey_nodes + +该节点旨在通过结合积极和消极的文本输入以及指定的风格来生成创意提示,从而产生多样化的输出,满足各种风格化和主题化的需求。 + +# Input types +## Required +- positive_prompt + - positive_prompt参数对于设定生成内容的积极基调至关重要。它是节点构建创意输出的基础。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt + - negative_prompt参数通过在内容生成过程中引入对比元素,补充了positive_prompt,增强了输出的多样性和深度。 + - Comfy dtype: STRING + - Python dtype: str +- style + - style参数决定了生成内容的主题方向和美学质量。它是实现具有内在一致性和风格一致性的输出的关键因素。 + - Comfy dtype: COMBO + - Python dtype: str +- ratio_selected + - ratio_selected参数影响内容的结构组成,确保生成的输出与期望的宽高比和格式要求相一致。 + - Comfy dtype: STRING + - Python dtype: str +- batch_size + - batch_size参数决定了单次操作中生成的独特输出数量,这对于内容生成的效率和可扩展性至关重要。 + - Comfy dtype: INT + - Python dtype: int +- seed + - seed参数在内容生成过程中引入了受控的随机性,确保输出既多样化又可复现,便于一致的实验。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- samples + - samples输出是生成内容的潜在表示,为进一步的处理和分析提供了多功能的基础。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- positive_prompt_text_g + - positive_prompt_text_g输出展示了经过处理的最终积极提示版本,已针对节点的创意目标进行了定制。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - negative_prompt_text_g输出提供了经过精炼的消极提示,它补充了积极内容,为整体输出增加了深度和对比度。 + - Comfy dtype: STRING + - Python dtype: str +- positive_style_text_l + - positive_style_text_l输出包含了与积极提示相关的风格元素,有助于生成内容的主题连贯性。 + - Comfy dtype: STRING + - Python dtype: str +- negative_style_text_l + - negative_style_text_l输出反映了消极提示的风格方面,增强了内容的多样性和丰富性。 + - Comfy dtype: STRING + - Python dtype: str +- width + - width输出指定了内容结构的水平维度,在确定生成输出的布局和呈现方面起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- height + - height输出定义了内容结构的垂直维度,对于输出的整体构成和视觉吸引力至关重要。 + - Comfy dtype: INT + - Python dtype: int +- refiner_width + - refiner_width输出调整宽度参数以优化精炼过程,确保输出是经过打磨的并符合质量标准。 + - Comfy dtype: INT + - Python dtype: int +- refiner_height + - refiner_height输出为精炼过程设置了垂直参数,有助于提高最终输出的精确度和细节。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptWithStyle: + + @classmethod + def INPUT_TYPES(s): + (s.ratio_sizes, s.ratio_dict) = read_ratios() + (s.styles, s.pos_style, s.neg_style) = read_styles() + return {'required': {'positive_prompt': ('STRING', {'multiline': True, 'default': 'Positive Prompt'}), 'negative_prompt': ('STRING', {'multiline': True, 'default': 'Negative Prompt'}), 'style': (s.styles,), 'ratio_selected': (s.ratio_sizes,), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = ('LATENT', 'STRING', 'STRING', 'STRING', 'STRING', 'INT', 'INT', 'INT', 'INT') + RETURN_NAMES = ('samples', 'positive_prompt_text_g', 'negative_prompt_text_g', 'positive_style_text_l', 'negative_style_text_l', 'width', 'height', 'refiner_width', 'refiner_height') + FUNCTION = 'start' + CATEGORY = 'Mikey' + OUTPUT_NODE = True + + def start(self, positive_prompt, negative_prompt, style, ratio_selected, batch_size, seed, prompt=None, extra_pnginfo=None): + positive_prompt = search_and_replace(positive_prompt, extra_pnginfo, prompt) + negative_prompt = search_and_replace(negative_prompt, extra_pnginfo, prompt) + positive_prompt = process_random_syntax(positive_prompt, seed) + negative_prompt = process_random_syntax(negative_prompt, seed) + pos_prompt = find_and_replace_wildcards(positive_prompt, seed, debug=True) + neg_prompt = find_and_replace_wildcards(negative_prompt, seed, debug=True) + if pos_prompt != '' and pos_prompt != 'Positive Prompt' and (pos_prompt is not None): + if '{prompt}' in self.pos_style[style]: + pos_prompt = self.pos_style[style].replace('{prompt}', pos_prompt) + elif self.pos_style[style]: + pos_prompt = pos_prompt + ', ' + self.pos_style[style] + else: + pos_prompt = self.pos_style[style] + if neg_prompt != '' and neg_prompt != 'Negative Prompt' and (neg_prompt is not None): + if '{prompt}' in self.neg_style[style]: + neg_prompt = self.neg_style[style].replace('{prompt}', neg_prompt) + elif self.neg_style[style]: + neg_prompt = neg_prompt + ', ' + self.neg_style[style] + else: + neg_prompt = self.neg_style[style] + width = self.ratio_dict[ratio_selected]['width'] + height = self.ratio_dict[ratio_selected]['height'] + ratio = min([width, height]) / max([width, height]) + (target_width, target_height) = (4096, 4096 * ratio // 8 * 8) if width > height else (4096 * ratio // 8 * 8, 4096) + refiner_width = target_width + refiner_height = target_height + latent = torch.zeros([batch_size, 4, height // 8, width // 8]) + return ({'samples': latent}, str(pos_prompt), str(neg_prompt), str(self.pos_style[style]), str(self.neg_style[style]), width, height, refiner_width, refiner_height) +``` \ No newline at end of file diff --git a/docs/PromptBuilder %2F%2FInspire.md b/docs/PromptBuilder %2F%2FInspire.md new file mode 100644 index 0000000..9a857c4 --- /dev/null +++ b/docs/PromptBuilder %2F%2FInspire.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: PromptBuilder +- Category: InspirePack/Prompt +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +PromptBuilder节点旨在为各种应用方便地构建和操作提示。它根据预设配置或用户定义的参数对输入文本进行处理,并输出精炼后的提示。 + +# Input types +## Required +- category + - ‘category’参数至关重要,因为它决定了提示构建器可用的预设类别。它影响构建提示时可以使用的选项范围,从而影响最终输出。 + - Comfy dtype: COMBO[category] + - Python dtype: List[str] +- text + - ‘text’参数是PromptBuilder的主要输入。它是节点将根据指定的配置进行处理和塑造的原始材料,对操作结果产生重大影响。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- output + - ‘output’代表PromptBuilder操作产生的最终处理过的提示。它包含了应用于输入文本的转换和精炼,反映了节点的核心功能。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptBuilder: + + @classmethod + def INPUT_TYPES(s): + global prompt_builder_preset + presets = ['#PRESET'] + return {'required': {'category': (list(prompt_builder_preset.keys()) + ['#PLACEHOLDER'],), 'preset': (presets,), 'text': ('STRING', {'multiline': True})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Prompt' + + def doit(self, **kwargs): + return (kwargs['text'],) +``` \ No newline at end of file diff --git a/docs/PromptComposerEffect.md b/docs/PromptComposerEffect.md new file mode 100644 index 0000000..c139907 --- /dev/null +++ b/docs/PromptComposerEffect.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: PromptComposerEffect +- Category: AI WizArt/Prompt Composer Tools/Deprecated +- Output node: False +- Repo Ref: https://github.com/florestefano1975/comfyui-prompt-composer.git + +该节点旨在通过应用风格化效果来增强文本输入,允许创建更具吸引力和多样性的内容。它强调节点在文本转换中的作用,而不深入具体实施细节。 + +# Input types +## Required +- effect + - 该参数决定了要应用于文本的效果类型,从根本上改变了输出的风格和语调。 + - Comfy dtype: COMBO[effects] + - Python dtype: str +- effect_weight + - 该参数调整应用效果的强度,影响转换的程度和最终结果的特点。 + - Comfy dtype: FLOAT + - Python dtype: float +- active + - 该参数控制是否应用效果,决定节点的功能是否在文本处理中处于活跃状态。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- text_in_opt + - 该参数作为应用风格化效果的基础文本。它的重要性在于提供了节点将要转换的内容。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- text_out + - 输出代表应用了效果的转换文本,展示了节点对内容增强的贡献。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptComposerEffect: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'optional': {'text_in_opt': ('STRING', {'forceInput': True})}, 'required': {'effect': (effects, {'default': effects[0]}), 'effect_weight': ('FLOAT', {'default': 1, 'step': 0.05, 'min': 0, 'max': 1.95, 'display': 'slider'}), 'active': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('text_out',) + FUNCTION = 'promptComposerEffect' + CATEGORY = 'AI WizArt/Prompt Composer Tools/Deprecated' + + def promptComposerEffect(self, text_in_opt='', effect='-', effect_weight=0, active=True): + prompt = [] + if text_in_opt != '': + prompt.append(text_in_opt) + if effect != '-' and effect_weight > 0 and active: + prompt.append(f'({effect} effect:{round(effect_weight, 2)})') + if len(prompt) > 0: + prompt = ', '.join(prompt) + prompt = prompt.lower() + return (prompt,) + else: + return ('',) +``` \ No newline at end of file diff --git a/docs/PromptComposerGrouping.md b/docs/PromptComposerGrouping.md new file mode 100644 index 0000000..b31cbda --- /dev/null +++ b/docs/PromptComposerGrouping.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: PromptComposerGrouping +- Category: AI WizArt/Prompt Composer Tools +- Output node: False +- Repo Ref: https://github.com/florestefano1975/comfyui-prompt-composer.git + +该节点通过调整输入文本的权重和结构,创造性地处理文本,为各种AI应用生成修改后的提示。 + +# Input types +## Required +- text_in + - 输入文本是节点操作的基础,其内容和结构直接影响输出结果。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- weight + - 权重参数微调应用于输入文本的转换,影响生成提示的强调和呈现。 + - Comfy dtype: FLOAT + - Python dtype: float +- active + - 激活标志决定了节点的处理是否应用于输入文本,从而控制节点的执行。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- text_out + - 输出文本是节点处理的结果,包含了准备用于AI应用的修改后的提示。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptComposerGrouping: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text_in': ('STRING', {'forceInput': True}), 'weight': ('FLOAT', {'default': 1, 'step': 0.05, 'min': 0, 'max': 1.95, 'display': 'slider'}), 'active': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('text_out',) + FUNCTION = 'promptComposerGrouping' + CATEGORY = 'AI WizArt/Prompt Composer Tools' + + def promptComposerGrouping(self, text_in='', weight=0, active=True): + prompt = text_in + if text_in != '' and weight > 0 and active: + prompt = applyWeight(text_in, weight) + return (prompt,) +``` \ No newline at end of file diff --git a/docs/PromptComposerMerge.md b/docs/PromptComposerMerge.md new file mode 100644 index 0000000..821615d --- /dev/null +++ b/docs/PromptComposerMerge.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: PromptComposerMerge +- Category: AI WizArt/Prompt Composer Tools +- Output node: False +- Repo Ref: https://github.com/florestefano1975/comfyui-prompt-composer.git + +PromptComposerMerge 节点旨在将两个不同的文本输入无缝整合并合并为一个连贯的输出。它是那些需要将不同来源的文本信息组合成统一格式的应用中的关键工具。该节点在文本合并流程中表现出色,确保生成的文本保持逻辑流畅和可读性。 + +# Input types +## Required +- text_a + - 参数 'text_a' 表示将与另一个文本合并的第一个文本输入。它在节点的操作中起着关键作用,因为它构成了最终输出的初始部分。'text_a' 的质量和内容对合并文本的整体连贯性和上下文有显著影响。 + - Comfy dtype: STRING + - Python dtype: str +- text_b + - 参数 'text_b' 是将与 'text_a' 连接的第二个文本输入。虽然不是必需的,但它通常用于向合并的文本中添加额外的上下文或信息。包含 'text_b' 可以增强最终输出的全面性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- text_out + - 参数 'text_out' 表示 'text_a' 和 'text_b' 输入的合并输出。它是节点合并过程的最终成果,以单一、连贯的格式反映了合并后的文本信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptComposerMerge: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text_a': ('STRING', {'forceInput': True}), 'text_b': ('STRING', {'forceInput': True})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('text_out',) + FUNCTION = 'promptComposerMerge' + CATEGORY = 'AI WizArt/Prompt Composer Tools' + + def promptComposerMerge(self, text_a='', text_b=''): + return (text_a + ', ' + text_b,) +``` \ No newline at end of file diff --git a/docs/PromptComposerStyler.md b/docs/PromptComposerStyler.md new file mode 100644 index 0000000..c0c8b21 --- /dev/null +++ b/docs/PromptComposerStyler.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: PromptComposerStyler +- Category: AI WizArt/Prompt Composer Tools/Deprecated +- Output node: False +- Repo Ref: https://github.com/florestefano1975/comfyui-prompt-composer.git + +PromptComposerStyler节点旨在通过应用风格元素来增强创意过程,它允许整合风格偏好和权重,使用户能够微调文本的艺术方向。该节点的功能集中在风格应用的概念上,旨在通过指定的美学增强原始文本,从而为作品的整体主题和音调质量做出贡献。 + +# Input types +## Required +- text_in_opt + - ‘text_in_opt’参数是一个可选输入,允许用户提供将应用风格元素的基础文本。它的重要性在于作为节点操作的基础,决定了将被艺术化增强的内容。 + - Comfy dtype: STRING + - Python dtype: str +- style + - ‘style’参数对于定义将融入文本的艺术风格至关重要。它是一个必需的输入,决定了节点将应用于文本的审美特征,从而影响最终的创意输出。 + - Comfy dtype: STRING + - Python dtype: str +- style_weight + - ‘style_weight’参数对于调整应用风格的强度至关重要。它允许精细控制风格在文本中的反映程度,确保原始内容与风格覆盖之间的平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- active + - ‘active’参数是一个布尔标志,它决定了是否启动风格应用过程。当设置为True时,它激活了节点的功能,允许将风格应用到文本中。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- text_out + - ‘text_out’输出参数代表应用风格元素后的最终文本。它包含了节点的创意贡献,展示了风格应用过程的结果。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptComposerStyler: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'optional': {'text_in_opt': ('STRING', {'forceInput': True})}, 'required': {'style': (styles, {'default': styles[0]}), 'style_weight': ('FLOAT', {'default': 1, 'step': 0.05, 'min': 0, 'max': 1.95, 'display': 'slider'}), 'active': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('text_out',) + FUNCTION = 'promptComposerStyler' + CATEGORY = 'AI WizArt/Prompt Composer Tools/Deprecated' + + def promptComposerStyler(self, text_in_opt='', style='-', style_weight=0, active=True): + prompt = [] + if text_in_opt != '': + prompt.append(text_in_opt) + if style != '-' and style_weight > 0 and active: + prompt.append(f'({style} style:{round(style_weight, 2)})') + if len(prompt) > 0: + prompt = ', '.join(prompt) + prompt = prompt.lower() + return (prompt,) + else: + return ('',) +``` \ No newline at end of file diff --git a/docs/PromptComposerTextSingle.md b/docs/PromptComposerTextSingle.md new file mode 100644 index 0000000..6832665 --- /dev/null +++ b/docs/PromptComposerTextSingle.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: PromptComposerTextSingle +- Category: AI WizArt/Prompt Composer Tools +- Output node: False +- Repo Ref: https://github.com/florestefano1975/comfyui-prompt-composer.git + +该节点创造性地组合文本输入,根据给定的权重和条件进行调整,以生成精炼的输出。它是用于打造定制文本内容的工具,强调每个输入在塑造最终作品方面的重要性。 + +# Input types +## Required +- text + - 主要的文本输入对节点的操作至关重要。它构成了组合的核心内容,并且对于生成最终输出是必不可少的。 + - Comfy dtype: STRING + - Python dtype: str +- weight + - 这个参数影响文本在组合中的调整方式。更高的权重意味着对相应文本片段的更大强调。 + - Comfy dtype: FLOAT + - Python dtype: float +- active + - 这个标志决定了是否应用权重参数到文本上。它控制权重调整功能的激活。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- text_in_opt + - 这个可选输入作为初始元素可以包含在组合中。它的存在丰富了文本的基础,可能为输出增加深度。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- text_out + - 输出代表最终组合的文本,反映了所有输入及其相应调整的整合。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptComposerTextSingle: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'optional': {'text_in_opt': ('STRING', {'forceInput': True})}, 'required': {'text': ('STRING', {'multiline': True}), 'weight': ('FLOAT', {'default': 1, 'min': 0, 'max': 1.95, 'step': 0.05, 'display': 'slider'}), 'active': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('text_out',) + FUNCTION = 'promptComposerTextSingle' + CATEGORY = 'AI WizArt/Prompt Composer Tools' + + def promptComposerTextSingle(self, text_in_opt='', text='', weight=0, active=True): + prompt = [] + if text_in_opt != '': + prompt.append(text_in_opt) + if text != '' and weight > 0 and active: + prompt.append(applyWeight(text, weight)) + if len(prompt) > 0: + prompt = ', '.join(prompt) + prompt = prompt.lower() + return (prompt,) + else: + return ('',) +``` \ No newline at end of file diff --git a/docs/PromptControlSimple.md b/docs/PromptControlSimple.md new file mode 100644 index 0000000..c5eeb34 --- /dev/null +++ b/docs/PromptControlSimple.md @@ -0,0 +1,95 @@ +# Documentation +- Class name: PromptControlSimple +- Category: promptcontrol +- Output node: False +- Repo Ref: https://github.com/asagi4/comfyui-prompt-control.git + +此类节点封装了管理和应用提示计划以及对模型进行过滤的功能,从而控制生成过程。它抽象了提示操作的复杂性,并提供了一种结构化的方法,根据指定条件细化模型的输出。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了将处理输入并生成输出的AI系统。它是驱动节点整个操作的核心组件。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - clip参数对于管理输入数据的上下文和结构至关重要,确保模型在期望的框架内处理信息。 + - Comfy dtype: CLIP + - Python dtype: ClipModel +- positive + - 正面输入作为肯定性提示,引导模型的生成朝着期望的结果发展,塑造输出的方向。 + - Comfy dtype: STRING + - Python dtype: str +- negative + - 负面输入作为约束,防止模型生成不希望的内容,并确保输出与指定的边界一致。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- tags + - 标签用于对生成的内容进行分类和过滤,允许对输出的特定方面进行有针对性的控制。 + - Comfy dtype: STRING + - Python dtype: str +- start + - 开始参数定义了提示计划中的起始点,决定了提示的影响何时开始。 + - Comfy dtype: FLOAT + - Python dtype: float +- end + - 结束参数标记了提示计划中的终点,建立了提示的影响何时结束。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- model + - 输出模型是更新后的AI系统,它结合了应用的提示和过滤器,准备生成符合指定指南的内容。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- positive + - 正面输出代表了经过处理并现在成为模型指导系统一部分的精炼提示。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict]] +- negative + - 负面输出包括已应用的约束,确保生成的内容遵守定义的限制。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict]] +- model_filtered + - 过滤后的模型输出是已根据指定的标签和百分比范围进行调整的AI系统,微调其生成能力。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- pos_filtered + - 正面过滤输出表示根据标签和百分比范围过滤的提示,使模型的生成集中在期望的元素上。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict]] +- neg_filtered + - 负面过滤输出表示通过标签和百分比范围过滤而精炼的约束,提高了模型避免不希望的内容的能力。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptControlSimple: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'positive': ('STRING', {'multiline': True}), 'negative': ('STRING', {'multiline': True})}, 'optional': {'tags': ('STRING', {'default': ''}), 'start': ('FLOAT', {'min': 0.0, 'max': 1.0, 'step': 0.1, 'default': 0.0}), 'end': ('FLOAT', {'min': 0.0, 'max': 1.0, 'step': 0.1, 'default': 1.0})}} + RETURN_TYPES = ('MODEL', 'CONDITIONING', 'CONDITIONING', 'MODEL', 'CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('model', 'positive', 'negative', 'model_filtered', 'pos_filtered', 'neg_filtered') + CATEGORY = 'promptcontrol' + FUNCTION = 'apply' + + def apply(self, model, clip, positive, negative, tags='', start=0.0, end=1.0): + lora_cache = {} + cond_cache = {} + pos_sched = parse_prompt_schedules(positive) + pos_cond = pos_filtered = control_to_clip_common(self, clip, pos_sched, lora_cache, cond_cache) + neg_sched = parse_prompt_schedules(negative) + neg_cond = neg_filtered = control_to_clip_common(self, clip, neg_sched, lora_cache, cond_cache) + new_model = model_filtered = schedule_lora_common(model, pos_sched, lora_cache) + if [tags.strip(), start, end] != ['', 0.0, 1.0]: + pos_filtered = control_to_clip_common(self, clip, pos_sched.with_filters(tags, start, end), lora_cache, cond_cache) + neg_filtered = control_to_clip_common(self, clip, neg_sched.with_filters(tags, start, end), lora_cache, cond_cache) + model_filtered = schedule_lora_common(model, pos_sched.with_filters(tags, start, end), lora_cache) + return (new_model, pos_cond, neg_cond, model_filtered, pos_filtered, neg_filtered) +``` \ No newline at end of file diff --git a/docs/PromptExtractor %2F%2FInspire.md b/docs/PromptExtractor %2F%2FInspire.md new file mode 100644 index 0000000..f92daf8 --- /dev/null +++ b/docs/PromptExtractor %2F%2FInspire.md @@ -0,0 +1,103 @@ +# Documentation +- Class name: PromptExtractor +- Category: InspirePack/Prompt +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +PromptExtractor节点旨在分析图像文件并提取相关的提示信息,这些信息可用于生成创意提示或指导工作流程。它处理图像元数据以识别所需的输入和输出,并构建提示结构的文本表示。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它是节点执行分析的主要输入。预期图像文件位于输入目录中,并具有有效的格式。 + - Comfy dtype: COMBO[sorted_files] + - Python dtype: str +- positive_id + - positive_id参数对于识别提示的积极方面至关重要。它有助于从提取的提示数据中过滤出相关信息,对最终输出做出贡献。 + - Comfy dtype: STRING + - Python dtype: str +- negative_id + - negative_id参数用于指定提示的负面方面。它在排除最终输出中的某些信息方面发挥作用,确保提取数据的相关性和准确性。 + - Comfy dtype: STRING + - Python dtype: str +- info + - info参数包含有关图像的元数据,对于节点理解提示的上下文和结构至关重要。它对于准确提取和表示提示信息至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- unique_id + - unique_id参数是节点操作的标识符,有助于在工作流程中跟踪和管理节点的执行。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- positive + - 正面输出代表与positive_id参数一致的提取信息,通过提供提示的建设性方面,为创意过程做出贡献。 + - Comfy dtype: STRING + - Python dtype: str +- negative + - 负面输出捕获与negative_id参数一致的提取信息,通过排除提示中不需要的方面,有助于完善创意过程。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptExtractor: + + @classmethod + def INPUT_TYPES(s): + input_dir = folder_paths.get_input_directory() + files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))] + return {'required': {'image': (sorted(files), {'image_upload': True}), 'positive_id': ('STRING', {}), 'negative_id': ('STRING', {}), 'info': ('STRING', {'multiline': True})}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + CATEGORY = 'InspirePack/Prompt' + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive', 'negative') + FUNCTION = 'doit' + OUTPUT_NODE = True + + def doit(self, image, positive_id, negative_id, info, unique_id): + image_path = folder_paths.get_annotated_filepath(image) + info = Image.open(image_path).info + positive = '' + negative = '' + text = '' + prompt_dicts = {} + node_inputs = {} + + def get_node_inputs(x): + if x in node_inputs: + return node_inputs[x] + else: + node_inputs[x] = None + obj = nodes.NODE_CLASS_MAPPINGS.get(x, None) + if obj is not None: + input_types = obj.INPUT_TYPES() + node_inputs[x] = input_types + return input_types + else: + return None + if isinstance(info, dict) and 'workflow' in info: + prompt = json.loads(info['prompt']) + for (k, v) in prompt.items(): + input_types = get_node_inputs(v['class_type']) + if input_types is not None: + inputs = input_types['required'].copy() + if 'optional' in input_types: + inputs.update(input_types['optional']) + for (name, value) in inputs.items(): + if name in prompt_blacklist: + continue + if value[0] == 'STRING' and name in v['inputs']: + prompt_dicts[f'{k}.{name.strip()}'] = (v['class_type'], v['inputs'][name]) + for (k, v) in prompt_dicts.items(): + text += f'{k} [{v[0]}] ==> {v[1]}\n' + positive = prompt_dicts.get(positive_id.strip(), '') + negative = prompt_dicts.get(negative_id.strip(), '') + else: + text = 'There is no prompt information within the image.' + PromptServer.instance.send_sync('inspire-node-feedback', {'node_id': unique_id, 'widget_name': 'info', 'type': 'text', 'data': text}) + return (positive, negative) +``` \ No newline at end of file diff --git a/docs/PromptImage.md b/docs/PromptImage.md new file mode 100644 index 0000000..d069484 --- /dev/null +++ b/docs/PromptImage.md @@ -0,0 +1,75 @@ +# Documentation +- Class name: PromptImage +- Category: ♾️Mixlab/Prompt +- Output node: True +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +PromptImage节点旨在根据文本提示处理和操作图像。它接收提示和图像作为输入,然后生成一系列受输入提示影响的图像输出。该节点具有将这些图像保存到指定目录的能力,为创意或分析目的提供了文本和图像处理之间的无缝集成。 + +# Input types +## Required +- prompts + - ‘prompts’参数是节点的重要输入,因为它提供了指导图像处理的文本内容。每个提示与一组图像相关联,并影响最终输出。 + - Comfy dtype: STRING + - Python dtype: List[str] +- images + - ‘images’参数是包含要处理的图像数据的基本输入。预计它是一个图像张量列表,节点将根据提供的提示对其进行操作。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +- save_to_image + - ‘save_to_image’参数决定是否应将处理后的图像保存到输出目录。它允许用户根据需要启用或禁用保存功能。 + - Comfy dtype: COMBO['enable', 'disable'] + - Python dtype: List[str] + +# Output types +- ui + - 输出中的‘ui’参数包含显示处理后的图像及其相关提示的用户界面元素。它为进一步交互或分析提供了一种结构化的方式来展示结果。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptImage: + + def __init__(self): + self.output_dir = folder_paths.get_output_directory() + self.type = 'output' + self.prefix_append = 'PromptImage' + self.compress_level = 4 + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompts': ('STRING', {'multiline': True, 'default': '', 'dynamicPrompts': False}), 'images': ('IMAGE', {'default': None}), 'save_to_image': (['enable', 'disable'],)}} + RETURN_TYPES = () + OUTPUT_NODE = True + INPUT_IS_LIST = True + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Prompt' + + def run(self, prompts, images, save_to_image): + filename_prefix = 'mixlab_' + filename_prefix += self.prefix_append + (full_output_folder, filename, counter, subfolder, filename_prefix) = folder_paths.get_save_image_path(filename_prefix, self.output_dir, images[0].shape[1], images[0].shape[0]) + results = list() + save_to_image = save_to_image[0] == 'enable' + for index in range(len(images)): + res = [] + imgs = images[index] + for image in imgs: + img = tensor2pil(image) + metadata = None + if save_to_image: + metadata = PngInfo() + prompt_text = prompts[index] + if prompt_text is not None: + metadata.add_text('prompt_text', prompt_text) + file = f'{filename}_{index}_{counter:05}_.png' + img.save(os.path.join(full_output_folder, file), pnginfo=metadata, compress_level=self.compress_level) + res.append({'filename': file, 'subfolder': subfolder, 'type': self.type}) + counter += 1 + results.append(res) + return {'ui': {'_images': results, 'prompts': prompts}} +``` \ No newline at end of file diff --git a/docs/PromptSchedule.md b/docs/PromptSchedule.md new file mode 100644 index 0000000..0225859 --- /dev/null +++ b/docs/PromptSchedule.md @@ -0,0 +1,82 @@ +# Documentation +- Class name: PromptSchedule +- Category: FizzNodes 📅🅕🅝/ScheduleNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +PromptSchedule节点负责管理和在指定帧数上动画化文本提示。它通过插值关键帧来创建提示的平滑过渡,并应用权重以控制每个关键帧的影响。该节点对于生成随时间演变的动态和连贯的文本动画至关重要。 + +# Input types +## Required +- text + - ‘text’参数是一个多行字符串,定义了动画提示的初始状态。它对于设置节点将生成动画序列的基础至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- max_frames + - ‘max_frames’参数决定了动画将运行的总帧数。它是整体动画时长和节奏的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- current_frame + - ‘current_frame’参数指示动画序列中的当前位置。对于节点来说,了解其在动画时间线中的位置至关重要。 + - Comfy dtype: INT + - Python dtype: int +- print_output + - ‘print_output’参数是一个布尔标志,设置为True时,会将动画提示的输出打印到控制台。这对于调试和实时监控非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- clip + - ‘clip’参数是对节点内用于文本编码的CLIP模型的引用。它在将文本提示转换为适合动画的格式中起着至关重要的作用。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +## Optional +- pw_a + - ‘pw_a’参数是一个浮点数,表示应用于当前帧动画的权重。它影响提示之间的过渡,并有助于整体动画的流畅性。 + - Comfy dtype: FLOAT + - Python dtype: float +- pre_text + - ‘pre_text’参数是一个可选的多行字符串,可用于前缀动画提示。它为动画序列提供额外的上下文或设置。 + - Comfy dtype: STRING + - Python dtype: str +- app_text + - ‘app_text’参数是一个可选的多行字符串,可用于向动画提示添加附加信息。它扩展了上下文或为动画序列添加了后缀。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- POS + - ‘POS’输出代表当前帧动画的正面条件。它来源于插值提示,并用于指导动画的正面生成。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] +- NEG + - ‘NEG’输出代表当前帧动画的负面条件。它用于平衡正面条件,确保动画序列的平衡发展。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptSchedule: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True, 'default': defaultPrompt}), 'clip': ('CLIP',), 'max_frames': ('INT', {'default': 120.0, 'min': 1.0, 'max': 999999.0, 'step': 1.0}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 999999.0, 'step': 1.0}), 'print_output': ('BOOLEAN', {'default': False})}, 'optional': {'pre_text': ('STRING', {'multiline': True}), 'app_text': ('STRING', {'multiline': True}), 'pw_a': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_b': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_c': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_d': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('POS', 'NEG') + FUNCTION = 'animate' + CATEGORY = 'FizzNodes 📅🅕🅝/ScheduleNodes' + + def animate(self, text, max_frames, print_output, current_frame, clip, pw_a=0, pw_b=0, pw_c=0, pw_d=0, pre_text='', app_text=''): + current_frame = current_frame % max_frames + inputText = str('{' + text + '}') + inputText = re.sub(',\\s*}', '}', inputText) + animation_prompts = json.loads(inputText.strip()) + start_frame = 0 + (pos, neg) = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text) + (pos_cur_prompt, pos_nxt_prompt, weight) = interpolate_prompt_series(pos, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) + pc = PoolAnimConditioning(pos_cur_prompt[current_frame], pos_nxt_prompt[current_frame], weight[current_frame], clip) + (neg_cur_prompt, neg_nxt_prompt, weight) = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) + nc = PoolAnimConditioning(neg_cur_prompt[current_frame], neg_nxt_prompt[current_frame], weight[current_frame], clip) + return (pc, nc) +``` \ No newline at end of file diff --git a/docs/PromptScheduleEncodeSDXL.md b/docs/PromptScheduleEncodeSDXL.md new file mode 100644 index 0000000..e9f0985 --- /dev/null +++ b/docs/PromptScheduleEncodeSDXL.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: PromptScheduleEncodeSDXL +- Category: FizzNodes 📅🅕🅝/ScheduleNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +PromptScheduleEncodeSDXL节点旨在为视频中的一系列帧制作和编码提示。它考虑了各种参数,如宽度、高度、裁剪尺寸和文本提示,以生成一系列提示,然后将这些提示编码以创建进一步处理的条件。此节点在动画管道中扮演着关键角色,通过管理提示处理的复杂性并确保帧之间的平稳过渡。 + +# Input types +## Required +- width + - 宽度参数指定视频帧的宽度。它对于确定输出视频的分辨率和宽高比至关重要,影响整体视觉质量以及动画的呈现方式。 + - Comfy dtype: INT + - Python dtype: int +- height + - 高度参数设置视频帧的垂直分辨率。它与宽度参数协同工作,以确保视频内容的正确缩放和显示。 + - Comfy dtype: INT + - Python dtype: int +- text_g + - text_g参数保存绿色通道的文本提示。这些提示对于引导动画过程和定义最终动画中将出现的故事或视觉元素至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- max_frames + - max_frames参数定义动画将包含的最大帧数。此设置对于控制动画的长度和管理计算资源很重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- print_output + - print_output参数是一个可选标志,设置为true时,将在节点执行期间打印调试信息。这对于开发人员监控进度和排除可能出现的问题很有帮助。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- POS + - POS输出提供从输入提示和参数派生的正面条件数据。这个输出很重要,因为它为后续的视频处理步骤奠定了基础,影响着动画的最终结果。 + - Comfy dtype: CONDITIONING + - Python dtype: Tuple[str, Dict[str, torch.Tensor]] +- NEG + - NEG输出提供负面条件数据,通过提供额外的上下文或对比,补充POS输出。这个输出用于完善动画并为视觉叙事增加深度。 + - Comfy dtype: CONDITIONING + - Python dtype: Tuple[str, Dict[str, torch.Tensor]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptScheduleEncodeSDXL: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'crop_w': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION}), 'crop_h': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION}), 'target_width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'target_height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'text_g': ('STRING', {'multiline': True}), 'clip': ('CLIP',), 'text_l': ('STRING', {'multiline': True}), 'clip': ('CLIP',), 'max_frames': ('INT', {'default': 120.0, 'min': 1.0, 'max': 999999.0, 'step': 1.0}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 999999.0, 'step': 1.0}), 'print_output': ('BOOLEAN', {'default': False})}, 'optional': {'pre_text_G': ('STRING', {'multiline': True}), 'app_text_G': ('STRING', {'multiline': True}), 'pre_text_L': ('STRING', {'multiline': True}), 'app_text_L': ('STRING', {'multiline': True}), 'pw_a': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_b': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_c': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_d': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('POS', 'NEG') + FUNCTION = 'animate' + CATEGORY = 'FizzNodes 📅🅕🅝/ScheduleNodes' + + def animate(self, clip, width, height, crop_w, crop_h, target_width, target_height, text_g, text_l, app_text_G, app_text_L, pre_text_G, pre_text_L, max_frames, current_frame, print_output, pw_a, pw_b, pw_c, pw_d): + current_frame = current_frame % max_frames + inputTextG = str('{' + text_g + '}') + inputTextL = str('{' + text_l + '}') + inputTextG = re.sub(',\\s*}', '}', inputTextG) + inputTextL = re.sub(',\\s*}', '}', inputTextL) + animation_promptsG = json.loads(inputTextG.strip()) + animation_promptsL = json.loads(inputTextL.strip()) + (posG, negG) = batch_split_weighted_subprompts(animation_promptsG, pre_text_G, app_text_G) + (posL, negL) = batch_split_weighted_subprompts(animation_promptsL, pre_text_L, app_text_L) + (pc, pn, pw) = BatchInterpolatePromptsSDXL(posG, posL, max_frames, clip, app_text_G, app_text_L, pre_text_G, pre_text_L, pw_a, pw_b, pw_c, pw_d, width, height, crop_w, crop_h, target_width, target_height, print_output) + p = addWeighted(pc[current_frame], pn[current_frame], pw[current_frame]) + (nc, nn, nw) = BatchInterpolatePromptsSDXL(negG, negL, max_frames, clip, app_text_G, app_text_L, pre_text_G, pre_text_L, pw_a, pw_b, pw_c, pw_d, width, height, crop_w, crop_h, target_width, target_height, print_output) + n = addWeighted(nc[current_frame], nn[current_frame], nw[current_frame]) + return (p, n) +``` \ No newline at end of file diff --git a/docs/PromptScheduleNodeFlow.md b/docs/PromptScheduleNodeFlow.md new file mode 100644 index 0000000..66ba263 --- /dev/null +++ b/docs/PromptScheduleNodeFlow.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: PromptScheduleNodeFlow +- Category: FizzNodes 📅🅕🅝/ScheduleNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +该节点旨在根据给定的帧数操作和调度字符串。它允许用户在特定的帧间隔添加或修改文本内容,这对于需要对信息进行时间结构化的应用至关重要。 + +# Input types +## Required +- text + - ‘text’参数对于定义要添加到日程中的内容至关重要。它影响信息在指定帧中的结构和呈现方式。 + - Comfy dtype: STRING + - Python dtype: str +- num_frames + - ‘num_frames’参数表示执行操作时的当前帧数。它对于计算添加或修改文本后的新的最大帧数至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- in_text + - 可选的‘in_text’参数允许修改日程中现有的文本条目。它在更新日程时起着重要作用,避免了重复创建。 + - Comfy dtype: STRING + - Python dtype: str +- max_frames + - ‘max_frames’参数用于指定应该添加或修改文本的最大帧数。它直接影响文本在日程中的时间位置。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- new_max + - ‘new_max’输出表示添加或修改文本后更新的最大帧数。它标志着日程中的新时间边界。 + - Comfy dtype: INT + - Python dtype: int +- new_text + - ‘new_text’输出是添加或修改后日程的更新文本内容。它反映了在指定帧上对文本所做的更改。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptScheduleNodeFlow: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True}), 'num_frames': ('INT', {'default': 24.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}, 'optional': {'in_text': ('STRING', {'multiline': False}), 'max_frames': ('INT', {'default': 0.0, 'min': 0.0, 'max': 999999.0, 'step': 1.0})}} + RETURN_TYPES = ('INT', 'STRING') + FUNCTION = 'addString' + CATEGORY = 'FizzNodes 📅🅕🅝/ScheduleNodes' + + def addString(self, text, in_text='', max_frames=0, num_frames=0): + if in_text: + in_text = in_text.rstrip(',') + new_max = num_frames + max_frames + if max_frames == 0: + new_text = in_text + (', ' if in_text else '') + f'"{max_frames}": "{text}"' + else: + new_text = in_text + (', ' if in_text else '') + f'"{new_max}": "{text}"' + return (new_max, new_text) +``` \ No newline at end of file diff --git a/docs/PromptScheduleNodeFlowEnd.md b/docs/PromptScheduleNodeFlowEnd.md new file mode 100644 index 0000000..87c836d --- /dev/null +++ b/docs/PromptScheduleNodeFlowEnd.md @@ -0,0 +1,99 @@ +# Documentation +- Class name: PromptScheduleNodeFlowEnd +- Category: FizzNodes 📅🅕🅝/ScheduleNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +`PromptScheduleNodeFlowEnd` 类的 `animate` 方法负责根据给定的文本和一系列参数生成动画提示。它处理输入文本以创建一系列提示,这些提示可以用来驱动动画序列,同时考虑到各种权重和条件,以确保帧之间的平滑过渡。 + +# Input types +## Required +- text + - ‘text’ 参数是节点的关键输入,因为它提供了将用于生成动画提示的原始文本。它很重要,因为它直接影响动画的内容和流程。 + - Comfy dtype: STRING + - Python dtype: str +- max_frames + - ‘max_frames’ 参数定义了动画序列的最大帧数。它至关重要,因为它决定了动画的总长度,并影响提示在帧中的分布。 + - Comfy dtype: INT + - Python dtype: int +- print_output + - ‘print_output’ 参数用于控制是否应该打印动画过程的中间结果。这对于调试目的或在创建动画时提供反馈很有帮助。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- current_frame + - ‘current_frame’ 参数表示动画序列中的当前位置。它很重要,因为它帮助节点确定在动画的任何给定时刻使用哪个提示。 + - Comfy dtype: INT + - Python dtype: int +- clip + - ‘clip’ 参数是节点的一个重要输入,因为它代表了将用于将提示标记化并编码为适合动画的格式的 CLIP 模型。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +## Optional +- pre_text + - ‘pre_text’ 参数用于在主要动画提示前添加上下文。它可以影响动画的初始状态,当需要引入部分时特别有用。 + - Comfy dtype: STRING + - Python dtype: str +- app_text + - ‘app_text’ 参数用于在主要动画提示后追加上下文。它可以用来用额外的信息扩展动画,或者为序列提供一个结论。 + - Comfy dtype: STRING + - Python dtype: str +- pw_a + - ‘pw_a’ 参数是一个可选的权重,用于调整动画中某些提示的影响。它提供了一种根据特定的创意要求微调动画的方法。 + - Comfy dtype: FLOAT + - Python dtype: float +- pw_b + - ‘pw_b’ 参数与 ‘pw_a’ 类似,但允许对动画权重的不同方面进行独立控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- pw_c + - ‘pw_c’ 参数扩展了动画权重的定制选项,为动画过程提供了额外的控制层。 + - Comfy dtype: FLOAT + - Python dtype: float +- pw_d + - ‘pw_d’ 参数是另一个可选的权重,有助于对动画进行微调,允许对动画的进展进行精确调整。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- POS + - ‘POS’ 输出提供了动画的正向调节数据,它代表了动画在每一帧应该采取的期望方向或结果。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] +- NEG + - ‘NEG’ 输出提供了负向调节数据,它用于定义动画在每一帧应该避免或远离的内容。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptScheduleNodeFlowEnd: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': False, 'forceInput': True}), 'clip': ('CLIP',), 'max_frames': ('INT', {'default': 0.0, 'min': 0.0, 'max': 999999.0, 'step': 1.0}), 'print_output': ('BOOLEAN', {'default': False}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 999999.0, 'step': 1.0})}, 'optional': {'pre_text': ('STRING', {'multiline': True}), 'app_text': ('STRING', {'multiline': True}), 'pw_a': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_b': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_c': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_d': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('POS', 'NEG') + FUNCTION = 'animate' + CATEGORY = 'FizzNodes 📅🅕🅝/ScheduleNodes' + + def animate(self, text, max_frames, print_output, current_frame, clip, pw_a=0, pw_b=0, pw_c=0, pw_d=0, pre_text='', app_text=''): + current_frame = current_frame % max_frames + if text[-1] == ',': + text = text[:-1] + if text[0] == ',': + text = text[:0] + start_frame = 0 + inputText = str('{' + text + '}') + inputText = re.sub(',\\s*}', '}', inputText) + animation_prompts = json.loads(inputText.strip()) + max_frames += start_frame + (pos, neg) = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text) + (pos_cur_prompt, pos_nxt_prompt, weight) = interpolate_prompt_series(pos, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) + pc = PoolAnimConditioning(pos_cur_prompt[current_frame], pos_nxt_prompt[current_frame], weight[current_frame], clip) + (neg_cur_prompt, neg_nxt_prompt, weight) = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) + nc = PoolAnimConditioning(neg_cur_prompt[current_frame], neg_nxt_prompt[current_frame], weight[current_frame], clip) + return (pc, nc) +``` \ No newline at end of file diff --git a/docs/PromptSimplification.md b/docs/PromptSimplification.md new file mode 100644 index 0000000..59e7140 --- /dev/null +++ b/docs/PromptSimplification.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: PromptSimplification +- Category: ♾️Mixlab/Prompt +- Output node: True +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点通过将词数减少到指定长度来简化提示,确保输入的简洁性和相关性,以便后续处理。 + +# Input types +## Required +- prompt + - 输入提示是节点操作的基础,其内容直接影响简化过程。 + - Comfy dtype: STRING + - Python dtype: str +- length + - 该参数决定了简化提示所需的期望词长,从而控制输出的简洁性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- prompts + - 输出展示了输入提示的精炼版本,去除了多余的词以满足指定的长度。 + - Comfy dtype: STRING + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptSimplification: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompt': ('STRING', {'multiline': True, 'default': '', 'dynamicPrompts': False}), 'length': ('INT', {'default': 5, 'min': 1, 'max': 100, 'step': 1, 'display': 'number'})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('prompts',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Prompt' + INPUT_IS_LIST = True + OUTPUT_IS_LIST = (True,) + OUTPUT_NODE = True + + def run(self, prompt, length): + length = length[0] + result = [] + for p in prompt: + nps = prompt_delete_words(p, length) + for n in nps: + result.append(n) + result = [elem.strip() for elem in result if elem.strip()] + return {'ui': {'prompts': result}, 'result': (result,)} +``` \ No newline at end of file diff --git a/docs/PromptSlide.md b/docs/PromptSlide.md new file mode 100644 index 0000000..82f2de8 --- /dev/null +++ b/docs/PromptSlide.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: PromptSlide +- Category: ♾️Mixlab/Prompt +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +PromptSlide节点旨在通过应用权重因子调整给定提示关键词的影响力。此过程允许微调输入提示,增强文本中特定关键词的相关性和强调。该节点的主要功能是修改输入提示,以更好地适应期望的输出,而不改变其基本含义或上下文。 + +# Input types +## Required +- prompt_keyword + - prompt_keyword参数至关重要,因为它定义了节点功能围绕的核心文本。它是权重调整的基础,确保结果提示与预期的强调和焦点一致。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- weight + - weight参数在确定要应用于prompt_keyword的强调程度中起着关键作用。它修改了关键词的影响力,允许根据期望的重要性水平对输出进行细微控制。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- prompt + - 输出参数'prompt'是节点操作的结果,反映了应用权重后调整的提示。它是关键元素,因为它传达了提示的最终形式,这直接影响了后续过程。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptSlide: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompt_keyword': ('STRING', {'multiline': False, 'default': '', 'dynamicPrompts': False}), 'weight': ('FLOAT', {'default': 1, 'min': -3, 'max': 3, 'step': 0.01, 'display': 'slider'})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('prompt',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Prompt' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False,) + OUTPUT_NODE = False + + def run(self, prompt_keyword, weight): + p = addWeight(prompt_keyword, weight) + return (p,) +``` \ No newline at end of file diff --git a/docs/PromptToSchedule.md b/docs/PromptToSchedule.md new file mode 100644 index 0000000..659bf16 --- /dev/null +++ b/docs/PromptToSchedule.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: PromptToSchedule +- Category: promptcontrol +- Output node: False +- Repo Ref: https://github.com/asagi4/comfyui-prompt-control.git + +PromptToSchedule节点的'parse'方法旨在将文本提示解析并转换为结构化的时间表格式。此方法对于管理和组织提示到可进一步处理或在系统中执行的连贯时间表至关重要。它抽象了解析的复杂性,专注于将原始文本转换为可用格式。 + +# Input types +## Required +- text + - 'text'参数对于'parse'方法至关重要,因为它表示需要解析为结构化时间表的原始文本输入。它是主要的输入,决定了节点的操作和解析过程的结果。 + - Comfy dtype: STRING + - Python dtype: str +- settings + - 'settings'参数是提供给'parse'方法的可选配置,用于自定义解析行为。它允许根据特定要求或约束微调解析过程。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Output types +- PROMPT_SCHEDULE + - 'parse'方法的输出是'PROMPT_SCHEDULE',这是输入文本的结构化表示。这个输出很重要,因为它为任何依赖于解析时间表的后续操作或分析奠定了基础。 + - Comfy dtype: PROMPT_SCHEDULE + - Python dtype: PromptSchedule + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PromptToSchedule: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True})}} + RETURN_TYPES = ('PROMPT_SCHEDULE',) + CATEGORY = 'promptcontrol' + FUNCTION = 'parse' + + def parse(self, text, settings=None): + schedules = parse_prompt_schedules(text) + return (schedules,) +``` \ No newline at end of file diff --git a/docs/Prune By Mask.md b/docs/Prune By Mask.md new file mode 100644 index 0000000..dbf9cb1 --- /dev/null +++ b/docs/Prune By Mask.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: PruneByMask +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +PruneByMask节点旨在根据相关掩码的质量选择性地从一批图像中筛选图像。具体来说,它仅保留那些掩码的平均像素值达到或超过0.5阈值的图像,确保后续处理集中在具有足够清晰掩码的图像上。 + +# Input types +## Required +- image + - 图像参数代表要处理的图像批次。这是一个关键的输入,因为节点的筛选操作完全依赖于这些图像的内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 掩码参数对应于批次中图像的相关掩码。节点评估这些掩码的平均像素值,以确定在输出中保留哪些图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- filtered_images + - filtered_images输出包含通过了节点筛选标准的输入图像子集,这些图像的筛选是基于它们相关掩码的平均像素值。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PruneByMask: + """ + Filters out the images in a batch that don't have an associated mask with an average pixel value of at least 0.5. + """ + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'mask': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'prune' + CATEGORY = 'Masquerade Nodes' + + def prune(self, image, mask): + mask = tensor2mask(mask) + mean = torch.mean(torch.mean(mask, dim=2), dim=1) + return (image[mean >= 0.5],) +``` \ No newline at end of file diff --git a/docs/Qr Code (mtb).md b/docs/Qr Code (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Quantize.md b/docs/Quantize.md new file mode 100644 index 0000000..b3b7540 --- /dev/null +++ b/docs/Quantize.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: Quantize +- Category: postprocessing/Color Adjustments +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +Quantize节点旨在减少图像中的颜色数量,这个过程被称为颜色量化。它通过将图像的颜色映射到指定数量的颜色来实现这一点,这对于创造更加风格化或复古的外观非常有用。该节点还提供了应用抖动的选项,这有助于平滑颜色之间的过渡,减少颜色条纹的出现。 + +# Input types +## Required +- image + - 图像参数是表示要量化的图像的输入张量。它在节点的操作中起着至关重要的作用,因为整个量化过程都应用于此图像。量化图像的质量和特性在很大程度上取决于输入图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- colors + - 颜色参数指定将图像减少到的颜色数量。这是一个重要的设置,因为它直接影响量化图像的细节水平和外观。颜色数量越多,保留的细节越多,但会导致文件大小更大。 + - Comfy dtype: INT + - Python dtype: int +- dither + - 抖动参数决定在量化过程中是否对图像应用抖动算法。抖动可以通过减少颜色条纹的可见性来帮助创建更具有视觉吸引力的结果。在'none'和'floyd-steinberg'之间的选择会影响最终图像的质量。 + - Comfy dtype: COMBO[none, floyd-steinberg] + - Python dtype: str + +# Output types +- quantized_image + - 量化图像输出是颜色量化过程的结果。它是一个张量,代表具有减少颜色数量的图像。这个输出很重要,因为它是节点操作的直接结果,可以用于进一步处理或显示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Quantize: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'colors': ('INT', {'default': 256, 'min': 1, 'max': 256, 'step': 1}), 'dither': (['none', 'floyd-steinberg'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'quantize' + CATEGORY = 'postprocessing/Color Adjustments' + + def quantize(self, image: torch.Tensor, colors: int=256, dither: str='FLOYDSTEINBERG'): + (batch_size, height, width, _) = image.shape + result = torch.zeros_like(image) + dither_option = Image.Dither.FLOYDSTEINBERG if dither == 'floyd-steinberg' else Image.Dither.NONE + for b in range(batch_size): + tensor_image = image[b] + img = (tensor_image * 255).to(torch.uint8).numpy() + pil_image = Image.fromarray(img, mode='RGB') + palette = pil_image.quantize(colors=colors) + quantized_image = pil_image.quantize(colors=colors, palette=palette, dither=dither_option) + quantized_array = torch.tensor(np.array(quantized_image.convert('RGB'))).float() / 255 + result[b] = quantized_array + return (result,) +``` \ No newline at end of file diff --git a/docs/Quick Resolution Multiply (WLSH).md b/docs/Quick Resolution Multiply (WLSH).md new file mode 100644 index 0000000..16f1f6e --- /dev/null +++ b/docs/Quick Resolution Multiply (WLSH).md @@ -0,0 +1,56 @@ +# Documentation +- Class name: WLSH_Res_Multiply +- Category: WLSH Nodes/number +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_Res_Multiply节点旨在对宽度和高度值执行乘法运算,根据提供的乘数进行缩放。它在调整图像或类似几何实体的尺寸方面起着至关重要的作用,确保缩放因子均匀应用于两个维度。 + +# Input types +## Required +- width + - ‘width’参数代表要缩放实体的初始宽度。它对节点的操作至关重要,因为它决定了乘法过程的起始点。宽度一旦乘以乘数,将定义缩放后的新宽度。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’参数表示缩放前实体的初始高度。它是节点的关键输入,因为它决定了将受乘数影响的垂直维度。操作后的最终高度将反映缩放后的高度。 + - Comfy dtype: INT + - Python dtype: int +- multiplier + - ‘multiplier’参数是宽度和高度将被缩放的因子。它是节点的关键组成部分,因为它直接影响缩放操作的幅度。适当选择乘数对于实现所需的尺寸至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- width + - ‘width’输出代表乘法操作后实体的缩放宽度。它很重要,因为它提供了缩放过程产生的新宽度测量值。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’输出表示乘法后的实体缩放高度。它是节点操作的一个重要结果,因为它提供了缩放后的新高度测量值。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Res_Multiply: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'width': ('INT', {'default': 512, 'min': 16, 'max': MAX_RESOLUTION, 'forceInput': True}), 'height': ('INT', {'default': 512, 'min': 16, 'max': MAX_RESOLUTION, 'forceInput': True}), 'multiplier': ('INT', {'default': 2, 'min': 1, 'max': 10000})}} + RETURN_TYPES = ('INT', 'INT') + RETURN_NAMES = ('width', 'height') + FUNCTION = 'multiply' + CATEGORY = 'WLSH Nodes/number' + + def multiply(self, width, height, multiplier): + adj_width = width * multiplier + adj_height = height * multiplier + return (int(adj_width), int(adj_height)) +``` \ No newline at end of file diff --git a/docs/RGB_Picker.md b/docs/RGB_Picker.md new file mode 100644 index 0000000..a4290da --- /dev/null +++ b/docs/RGB_Picker.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: RGB_Picker +- Category: 😺dzNodes/WordCloud +- Output node: True +- Repo Ref: https://github.com/chflame163/ComfyUI_WordCloud.git + +RGB_Picker节点旨在促进颜色值的转换和选择。它处理各种格式的颜色输入,专注于为用户提供在十六进制和十进制表示法中处理颜色的灵活性。 + +# Input types +## Required +- color + - ‘color’参数是必需的,因为它定义了节点操作的初始颜色输入。它是所有后续颜色转换的基础,对确定最终输出至关重要。 + - Comfy dtype: COLOR + - Python dtype: str +## Optional +- mode + - ‘mode’参数决定了颜色输入的转换过程。它影响颜色的解释方式和输出的结果格式,增强了节点对不同颜色表示要求的适应性。 + - Comfy dtype: COMBO[mode_list] + - Python dtype: str + +# Output types +- value + - ‘value’输出代表所需格式下的处理后颜色,包含了节点颜色转换和选择的主要功能。 + - Comfy dtype: STRING + - Python dtype: tuple + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RGB_Picker: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + return {'required': {'color': ('COLOR', {'default': 'white'}), 'mode': (mode_list,)}, 'optional': {}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('value',) + FUNCTION = 'picker' + CATEGORY = '😺dzNodes/WordCloud' + OUTPUT_NODE = True + + def picker(self, color, mode): + ret = color + if mode == 'DEC': + ret = hex_to_dec(color) + return (ret,) +``` \ No newline at end of file diff --git a/docs/RIFE VFI.md b/docs/RIFE VFI.md new file mode 100644 index 0000000..b9eca6d --- /dev/null +++ b/docs/RIFE VFI.md @@ -0,0 +1,101 @@ +# Documentation +- Class name: RIFE_VFI +- Category: ComfyUI-Frame-Interpolation/VFI +- Output node: False +- Repo Ref: https://github.com/Fannovel16/ComfyUI-Frame-Interpolation + +RIFE_VFI节点旨在使用指定的检查点模型执行视频帧插值。它能够生成输入视频帧之间的插值帧,有效地将帧率翻倍。该节点通过顺序处理每个帧并创建新的帧来操作,增强了视频序列的平滑度和连续性。 + +# Input types +## Required +- ckpt_name + - ckpt_name参数对于选择用于帧插值的适当检查点模型至关重要。它决定了节点将应用以生成插值帧的特定权重和架构。 + - Comfy dtype: str + - Python dtype: str +- frames + - frames参数是必需的,因为它包含节点将处理的输入视频帧。输入帧的质量和分辨率直接影响插值的输出,使这个参数对节点的操作非常重要。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +## Optional +- clear_cache_after_n_frames + - clear_cache_after_n_frames是一个可选设置,它有助于在插值过程中管理内存使用。它指定在清除CUDA缓存以防止内存溢出之前要处理的帧数,这可以根据系统的内存容量和输入帧数进行调整。 + - Comfy dtype: int + - Python dtype: int +- multiplier + - multiplier参数决定了输入帧生成输出帧时要乘以的倍数。例如,使用2的乘数,每个输入帧将产生两个输出帧,在它们之间有效地创建一个插值帧。 + - Comfy dtype: int + - Python dtype: int +- fast_mode + - fast_mode参数是一个可选的布尔标志,设置为True时,可以启用更快但可能不太精确的插值过程。这对于快速预览或处理大量帧时非常有用。 + - Comfy dtype: bool + - Python dtype: bool +- ensemble + - ensemble参数允许组合多个插值模型以提高插值帧的质量。启用后,它可能会增加处理时间,但可以导致更稳定和更高保真的结果。 + - Comfy dtype: bool + - Python dtype: bool +- scale_factor + - scale_factor参数在处理之前调整输入帧的分辨率。它特别适用于处理不同的帧大小,并可以影响最终输出的清晰度和细节。 + - Comfy dtype: float + - Python dtype: float +- optional_interpolation_states + - optional_interpolation_states参数提供了一种使用附加状态自定义插值过程的方法。这可以包括特定指令或条件,它们影响帧的插值方式,允许对输出进行更细粒度的控制。 + - Comfy dtype: INTERPOLATION_STATES + - Python dtype: InterpolationStateList + +# Output types +- interpolated_frames + - interpolated_frames参数代表帧插值过程的输出。它包含原始输入帧以及新生成的中间帧,有效地创建了一个更平滑的视频序列。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RIFE_VFI: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (sorted(list(CKPT_NAME_VER_DICT.keys()), key=lambda ckpt_name: version.parse(CKPT_NAME_VER_DICT[ckpt_name])), {'default': 'rife47.pth'}), 'frames': ('IMAGE',), 'clear_cache_after_n_frames': ('INT', {'default': 10, 'min': 1, 'max': 1000}), 'multiplier': ('INT', {'default': 2, 'min': 1}), 'fast_mode': ('BOOLEAN', {'default': True}), 'ensemble': ('BOOLEAN', {'default': True}), 'scale_factor': ([0.25, 0.5, 1.0, 2.0, 4.0], {'default': 1.0})}, 'optional': {'optional_interpolation_states': ('INTERPOLATION_STATES',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'vfi' + CATEGORY = 'ComfyUI-Frame-Interpolation/VFI' + + def vfi(self, ckpt_name: typing.AnyStr, frames: torch.Tensor, clear_cache_after_n_frames=10, multiplier: typing.SupportsInt=2, fast_mode=False, ensemble=False, scale_factor=1.0, optional_interpolation_states: InterpolationStateList=None, **kwargs): + """ + Perform video frame interpolation using a given checkpoint model. + + Args: + ckpt_name (str): The name of the checkpoint model to use. + frames (torch.Tensor): A tensor containing input video frames. + clear_cache_after_n_frames (int, optional): The number of frames to process before clearing CUDA cache + to prevent memory overflow. Defaults to 10. Lower numbers are safer but mean more processing time. + How high you should set it depends on how many input frames there are, input resolution (after upscaling), + how many times you want to multiply them, and how long you're willing to wait for the process to complete. + multiplier (int, optional): The multiplier for each input frame. 60 input frames * 2 = 120 output frames. Defaults to 2. + + Returns: + tuple: A tuple containing the output interpolated frames. + + Note: + This method interpolates frames in a video sequence using a specified checkpoint model. + It processes each frame sequentially, generating interpolated frames between them. + + To prevent memory overflow, it clears the CUDA cache after processing a specified number of frames. + """ + from .rife_arch import IFNet + model_path = load_file_from_github_release(MODEL_TYPE, ckpt_name) + arch_ver = CKPT_NAME_VER_DICT[ckpt_name] + interpolation_model = IFNet(arch_ver=arch_ver) + interpolation_model.load_state_dict(torch.load(model_path)) + interpolation_model.eval().to(get_torch_device()) + frames = preprocess_frames(frames) + + def return_middle_frame(frame_0, frame_1, timestep, model, scale_list, in_fast_mode, in_ensemble): + return model(frame_0, frame_1, timestep, scale_list, in_fast_mode, in_ensemble) + scale_list = [8 / scale_factor, 4 / scale_factor, 2 / scale_factor, 1 / scale_factor] + args = [interpolation_model, scale_list, fast_mode, ensemble] + out = postprocess_frames(generic_frame_loop(frames, clear_cache_after_n_frames, multiplier, return_middle_frame, *args, interpolation_states=optional_interpolation_states, dtype=torch.float32)) + return (out,) +``` \ No newline at end of file diff --git a/docs/Random Number.md b/docs/Random Number.md new file mode 100644 index 0000000..6533f2a --- /dev/null +++ b/docs/Random Number.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: WAS_Random_Number +- Category: WAS Suite/Number +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Random_Number 节点旨在根据指定的参数生成随机数。它提供了生成整数、浮点数或布尔值等不同类型的随机数的灵活性,并允许自定义生成的随机数的最小值和最大值。该节点通过使用种子来确保随机数生成过程的可重复性。 + +# Input types +## Required +- number_type + - 参数 'number_type' 决定了要生成的随机数的类型。它可以设置为 'integer'、'float' 或 'bool',每种都产生相应类型的随机值。此参数至关重要,因为它定义了输出的性质。 + - Comfy dtype: STRING + - Python dtype: str +- minimum + - 参数 'minimum' 设置了可以生成的随机数范围的下限。它对于定义随机数将出现的范围内至关重要,确保输出满足所需的约束条件。 + - Comfy dtype: FLOAT + - Python dtype: float +- maximum + - 参数 'maximum' 确定了可以生成的随机数范围的上限。它与 'minimum' 参数协同工作,以确保生成的数字落在一个特定的区间内。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - 参数 'seed' 用于初始化随机数生成器,确保产生的随机数序列是可重复的。它在维护节点输出在不同运行中的一致性和可靠性中起着至关重要的作用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- NUMBER + - 输出 'NUMBER' 提供了作为整数、浮点数或布尔值生成的随机数,这取决于指定的 'number_type'。它是节点操作的主要结果,对下游处理非常重要。 + - Comfy dtype: INT + - Python dtype: Union[int, float, bool] +- FLOAT + - 输出 'FLOAT' 表示生成的随机数作为浮点值。当需要对数字进行进一步计算或分析时,十进制表示形式特别有用。 + - Comfy dtype: FLOAT + - Python dtype: float +- INT + - 输出 'INT' 提供了作为整数值生成的随机数。当某些应用需要整数数值或不需要浮点数的精度时,这非常有用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Random_Number: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'number_type': (['integer', 'float', 'bool'],), 'minimum': ('FLOAT', {'default': 0, 'min': -18446744073709551615, 'max': 18446744073709551615}), 'maximum': ('FLOAT', {'default': 0, 'min': -18446744073709551615, 'max': 18446744073709551615}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('NUMBER', 'FLOAT', 'INT') + FUNCTION = 'return_randm_number' + CATEGORY = 'WAS Suite/Number' + + def return_randm_number(self, minimum, maximum, seed, number_type='integer'): + random.seed(seed) + if number_type: + if number_type == 'integer': + number = random.randint(minimum, maximum) + elif number_type == 'float': + number = random.uniform(minimum, maximum) + elif number_type == 'bool': + number = random.random() + else: + return + return (number, float(number), round(number)) + + @classmethod + def IS_CHANGED(cls, seed, **kwargs): + m = hashlib.sha256() + m.update(seed) + return m.digest().hex() +``` \ No newline at end of file diff --git a/docs/RandomGeneratorForList %2F%2FInspire.md b/docs/RandomGeneratorForList %2F%2FInspire.md new file mode 100644 index 0000000..0baa552 --- /dev/null +++ b/docs/RandomGeneratorForList %2F%2FInspire.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: RandomGeneratorForList +- Category: InspirePack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在根据给定的种子生成一系列随机数,确保相同的种子将产生相同的随机数列表,这对于各种应用中的可重复性至关重要。 + +# Input types +## Required +- signal + - 信号参数代表触发随机数生成的输入数据。它非常重要,因为它可能会影响随机数生成器的初始化。 + - Comfy dtype: ANY + - Python dtype: Any +## Optional +- seed + - 种子参数对于确定随机数序列的起点至关重要。它确保相同的种子将产生相同的随机数列表,这对于可重复性至关重要。 + - Comfy dtype: INT + - Python dtype: int +- unique_id + - unique_id参数用于跟踪和管理每个唯一实例的随机数生成次数,确保每个实例都有一组不同的随机数序列。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- signal + - 输出信号保留了原始的输入信号,表明随机数生成过程已经完成。 + - Comfy dtype: ANY + - Python dtype: Any +- random_value + - random_value输出代表新生成的种子,这是一个随机整数,可以用于进一步的随机数生成或其他目的。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RandomGeneratorForList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'signal': (utils.any_typ,), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = (utils.any_typ, 'INT') + RETURN_NAMES = ('signal', 'random_value') + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Util' + + def doit(self, signal, seed, unique_id): + if unique_id not in list_counter_map: + count = 0 + else: + count = list_counter_map[unique_id] + list_counter_map[unique_id] = count + 1 + rn = random.Random() + rn.seed(seed + count) + new_seed = random.randint(0, 1125899906842624) + return (signal, new_seed) +``` \ No newline at end of file diff --git a/docs/RandomPrompt.md b/docs/RandomPrompt.md new file mode 100644 index 0000000..2075644 --- /dev/null +++ b/docs/RandomPrompt.md @@ -0,0 +1,85 @@ +# Documentation +- Class name: RandomPrompt +- Category: ♾️Mixlab/Prompt +- Output node: True +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +RandomPrompt节点旨在通过组合可变和不可变文本元素生成多样化的提示集。它通过将提供的提示分割成单独的单词或短语,然后以各种组合重新组装它们来操作。该节点还提供了功能,可以基于指定的最大计数随机抽样一部分生成的提示,或返回所有提示。该过程旨在为进一步处理或分析创建广泛的文本输入。 + +# Input types +## Required +- max_count + - 参数'max_count'确定要生成或抽样的最大提示数量。它在控制输出大小和确保节点的执行与所需的多样性水平一致,同时避免压垮下游流程中起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- mutable_prompt + - 参数'mutable_prompt'是用户在节点操作期间可以更改或与其他提示组合的字符串。它之所以重要,是因为它构成了生成提示的可变性基础,允许广泛的潜在输出。 + - Comfy dtype: STRING + - Python dtype: str +- immutable_prompt + - 参数'immutable_prompt'是在节点执行期间保持不变的固定字符串。它作为一个常量元素,与可变提示合并,以在最终提示集中产生一致的结构。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- random_sample + - 参数'random_sample'指示节点是否应随机选择生成提示的子集。启用时,它为选择过程引入了随机性元素,这对于需要多样化但有限的提示集的某些应用可能是有益的。 + - Comfy dtype: COMBO['enable', 'disable'] + - Python dtype: str +- seed + - 参数'seed'用于初始化随机抽样过程中的随机数生成器。当提供特定的种子值时,它确保结果的可复现性,允许节点在多次执行中获得一致的结果。 + - Comfy dtype: any_type + - Python dtype: int + +# Output types +- prompts + - 输出'prompts'是由可变和不可变文本元素组合生成的文本提示列表。它代表了节点执行的主要结果,对于使用这些提示进行进一步处理或分析的应用来说非常重要。 + - Comfy dtype: STRING + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RandomPrompt: + """ + @classmethod 是Python中的一个装饰器,用于将一个方法标记为类方法。 + 类方法是与类相关联的方法,而不是与实例相关联的方法。 + 这意味着类方法可以直接通过类进行调用,而不需要先创建一个类的实例。 + """ + + @classmethod + def INPUT_TYPES(s): + return {'required': {'max_count': ('INT', {'default': 9, 'min': 1, 'max': 1000}), 'mutable_prompt': ('STRING', {'multiline': True, 'default': default_prompt1}), 'immutable_prompt': ('STRING', {'multiline': True, 'default': 'sticker, Cartoon, ``'}), 'random_sample': (['enable', 'disable'],)}, 'optional': {'seed': (any_type, {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Prompt' + OUTPUT_IS_LIST = (True,) + OUTPUT_NODE = True + + def run(self, max_count, mutable_prompt, immutable_prompt, random_sample, seed=0): + words1 = mutable_prompt.split('\n') + words2 = immutable_prompt.split('\n') + pbar = comfy.utils.ProgressBar(len(words1) * len(words2)) + prompts = [] + for w1 in words1: + w1 = w1.strip() + for w2 in words2: + w2 = w2.strip() + if '``' not in w2: + if w2 == '': + w2 = '``' + else: + w2 = w2 + ',``' + if w1 != '' and w2 != '': + prompts.append(w2.replace('``', w1)) + pbar.update(1) + if len(prompts) == 0: + prompts.append(immutable_prompt) + if random_sample == 'enable': + prompts = random.sample(prompts, min(max_count, len(prompts))) + else: + prompts = prompts[:min(max_count, len(prompts))] + prompts = [elem.strip() for elem in prompts if elem.strip()] + return {'ui': {'prompts': prompts}, 'result': (prompts,)} +``` \ No newline at end of file diff --git a/docs/Range Float.md b/docs/Range Float.md new file mode 100644 index 0000000..809f320 --- /dev/null +++ b/docs/Range Float.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: RangeFloat +- Category: Mikey/Utils +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +RangeFloat节点旨在创建一个指定范围内的浮点数序列。它通过从一个起点到一个终点以给定的步长生成数字列表,然后根据种子值从这个列表中选择一个数字。这个节点在需要控制数字随机化的情境中特别有用,例如在模拟或数据处理任务中。 + +# Input types +## Required +- start + - 参数'start'定义了生成数字的范围的开始。它至关重要,因为它设定了序列的初始点,并决定了范围的方向(无论是增加还是减少)。这个参数直接影响输出数字和节点的整体行为。 + - Comfy dtype: FLOAT + - Python dtype: float +- end + - 参数'end'指定了范围的终点。它至关重要,因为它决定了生成数字序列中的最终值。'end'值与'start'和'step'参数结合使用,决定了在范围内产生的数字总数。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- step + - 参数'step'决定了生成序列中每个连续数字之间的增量。它很重要,因为它控制了范围内数字的密度。较小的步长会产生更细粒度的输出,而较大的步长则会导致更粗略的分布。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - 参数'seed'用于在从生成的列表中选择数字时引入可控的随机性元素。它很重要,因为它确保选择过程是可重复的,并且可以调整以获得不同的结果,而无需更改底层范围。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- selected_number + - 输出'selected_number'代表从生成的序列中选择的浮点数。它很重要,因为它是节点操作的主要结果,并且可以用于进一步的处理或分析。 + - Comfy dtype: FLOAT + - Python dtype: float +- representation + - 输出'representation'提供了所选数字的字符串表示形式,这对于记录、显示或需要文本格式的场景非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RangeFloat: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'start': ('FLOAT', {'default': 0, 'min': 0, 'step': 0.0001, 'max': 18446744073709551615}), 'end': ('FLOAT', {'default': 0, 'min': 0, 'step': 0.0001, 'max': 18446744073709551615}), 'step': ('FLOAT', {'default': 0, 'min': 0, 'step': 0.0001, 'max': 18446744073709551615}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('FLOAT', 'STRING') + FUNCTION = 'generate' + CATEGORY = 'Mikey/Utils' + + def generate(self, start, end, step, seed): + range_ = np.arange(start, end, step) + list_of_numbers = list(range_) + offset = seed % len(list_of_numbers) + return (list_of_numbers[offset], f'{list_of_numbers[offset]}') +``` \ No newline at end of file diff --git a/docs/Range Integer.md b/docs/Range Integer.md new file mode 100644 index 0000000..d098674 --- /dev/null +++ b/docs/Range Integer.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: RangeInteger +- Category: Mikey/Utils +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +RangeInteger节点旨在生成指定范围内的整数序列。它提供功能以自定义序列的起始点、结束点和步长,以及使用种子选项来复现序列。在需要对整数序列进行进一步处理或分析的场景中,此节点至关重要。 + +# Input types +## Required +- start + - ‘start’参数定义了整数序列的开始。它至关重要,因为它设置了序列生成的初始值。此参数直接影响节点产生的序列的范围和第一个元素。 + - Comfy dtype: INT + - Python dtype: int +- end + - ‘end’参数指定整数序列的排他上限。它很重要,因为它决定了序列的终点,即最后一个元素之后的值。此参数对于定义序列的范围至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- step + - ‘step’参数指示序列中每个整数之间的增量。它很重要,因为它控制序列内数字的间距,允许定制进度速率。默认值为0,如果未指定,则意味着步长为1。 + - Comfy dtype: INT + - Python dtype: int +- seed + - ‘seed’参数用于在序列生成过程中引入一定程度的随机性控制。它对于确保序列的可复现性很重要,在需要一致结果的实验或模拟中至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- integer + - ‘integer’输出提供了生成序列中的一个整数,由输入参数和种子值确定。它很重要,因为它代表了节点操作的主要结果,作为后续计算或分析的基础。 + - Comfy dtype: INT + - Python dtype: int +- string + - ‘string’输出返回序列中选定整数的字符串表示。当需要整数的文本表示时,如日志记录或显示目的,此输出非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RangeInteger: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'start': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'end': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'step': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('INT', 'STRING') + FUNCTION = 'generate' + CATEGORY = 'Mikey/Utils' + + def generate(self, start, end, step, seed): + range_ = np.arange(start, end, step) + list_of_numbers = list(range_) + offset = seed % len(list_of_numbers) + return (list_of_numbers[offset], f'{list_of_numbers[offset]}') +``` \ No newline at end of file diff --git a/docs/Ratio Advanced.md b/docs/Ratio Advanced.md new file mode 100644 index 0000000..cdfa6f5 --- /dev/null +++ b/docs/Ratio Advanced.md @@ -0,0 +1,132 @@ +# Documentation +- Class name: RatioAdvanced +- Category: Mikey/Utils +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +RatioAdvanced节点旨在执行高级比例计算和转换。它可以处理预设比例、自定义输入尺寸以及各种缩放操作,以确定图像处理流水线不同阶段的最优尺寸。该节点强调在比例处理中的灵活性和精确性,确保输出尺寸满足特定的标准或约束条件。 + +# Input types +## Required +- preset + - 预设参数允许用户选择一个预定义的比例配置。这种选择可以显著简化将已知比例集应用到图像的过程,确保一致性并减少手动计算。 + - Comfy dtype: STRING + - Python dtype: str +- swap_axis + - swap_axis参数在必要时启用宽度和高度值的交换。这对于在不改变图像固有的长宽比的情况下调整图像的方向非常有用。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- custom_latent_w + - 当选择自定义比例时,custom_latent_w参数指定潜在图像的宽度。这允许微调特定处理阶段的图像尺寸,这对于实现所需的视觉效果或满足输出要求至关重要。 + - Comfy dtype: INT + - Python dtype: int +- custom_latent_h + - custom_latent_h参数与custom_latent_w一起使用,当应用自定义比例时,设置潜在图像的高度。这个参数提供了对图像垂直维度的控制,允许进行精确调整以满足特定的处理目标。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- latent_w + - latent_w输出代表了基于输入参数和节点的比例计算得出的潜在图像的宽度。这个值对于确定处理流水线特定阶段图像的水平维度至关重要。 + - Comfy dtype: INT + - Python dtype: int +- latent_h + - latent_h输出对应于计算出的潜在图像的高度。与latent_w一起,它定义了潜在阶段图像的整体大小,这对于进一步处理和分析至关重要。 + - Comfy dtype: INT + - Python dtype: int +- cte_w + - cte_w输出表示考虑恒定时间演化(CTE)比例后的图像宽度。这个参数对于保持图像在不同处理步骤中的时间一致性非常重要。 + - Comfy dtype: INT + - Python dtype: int +- cte_h + - cte_h输出是在应用CTE比例时图像的高度。它与cte_w一起工作,确保在保持图像的长宽比和时间完整性的同时,适当地调整图像的尺寸。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RatioAdvanced: + + @classmethod + def INPUT_TYPES(s): + (s.ratio_sizes, s.ratio_dict) = read_ratios() + default_ratio = s.ratio_sizes[0] + s.ratio_sizes.insert(0, 'custom') + (s.ratio_presets, s.ratio_config) = read_ratio_presets() + if 'none' not in s.ratio_presets: + s.ratio_presets.append('none') + return {'required': {'preset': (s.ratio_presets, {'default': 'none'}), 'swap_axis': (['true', 'false'], {'default': 'false'}), 'select_latent_ratio': (s.ratio_sizes, {'default': default_ratio}), 'custom_latent_w': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 1}), 'custom_latent_h': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 1}), 'select_cte_ratio': (s.ratio_sizes, {'default': default_ratio}), 'cte_w': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 1}), 'cte_h': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 1}), 'cte_mult': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 100.0, 'step': 0.01}), 'cte_res': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 1}), 'cte_fit_size': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 1}), 'select_target_ratio': (s.ratio_sizes, {'default': default_ratio}), 'target_w': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 1}), 'target_h': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 1}), 'target_mult': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 100.0, 'step': 0.01}), 'target_res': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 1}), 'target_fit_size': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 1}), 'crop_w': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 1}), 'crop_h': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 1}), 'use_preset_seed': (['true', 'false'], {'default': 'false'}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('INT', 'INT', 'INT', 'INT', 'INT', 'INT', 'INT', 'INT') + RETURN_NAMES = ('latent_w', 'latent_h', 'cte_w', 'cte_h', 'target_w', 'target_h', 'crop_w', 'crop_h') + CATEGORY = 'Mikey/Utils' + FUNCTION = 'calculate' + + def mult(self, width, height, mult): + return (int(width * mult), int(height * mult)) + + def fit(self, width, height, fit_size): + if width > height: + return (fit_size, int(height * fit_size / width)) + else: + return (int(width * fit_size / height), fit_size) + + def res(self, width, height, res): + return find_latent_size(width, height, res) + + def calculate(self, preset, swap_axis, select_latent_ratio, custom_latent_w, custom_latent_h, select_cte_ratio, cte_w, cte_h, cte_mult, cte_res, cte_fit_size, select_target_ratio, target_w, target_h, target_mult, target_res, target_fit_size, crop_w, crop_h, use_preset_seed, seed, unique_id=None, extra_pnginfo=None, prompt=None): + if use_preset_seed == 'true' and len(self.ratio_presets) > 1: + offset = seed % len(self.ratio_presets - 1) + presets = [p for p in self.ratio_presets if p != 'none'] + preset = presets[offset] + if preset != 'none': + latent_width = self.ratio_config[preset]['custom_latent_w'] + latent_height = self.ratio_config[preset]['custom_latent_h'] + cte_w = self.ratio_config[preset]['cte_w'] + cte_h = self.ratio_config[preset]['cte_h'] + target_w = self.ratio_config[preset]['target_w'] + target_h = self.ratio_config[preset]['target_h'] + crop_w = self.ratio_config[preset]['crop_w'] + crop_h = self.ratio_config[preset]['crop_h'] + if swap_axis == 'true': + (latent_width, latent_height) = (latent_height, latent_width) + (cte_w, cte_h) = (cte_h, cte_w) + (target_w, target_h) = (target_h, target_w) + (crop_w, crop_h) = (crop_h, crop_w) + '\n example user_ratio_presets.json\n {\n "ratio_presets": {\n "all_1024": {\n "custom_latent_w": 1024,\n "custom_latent_h": 1024,\n "cte_w": 1024,\n "cte_h": 1024,\n "target_w": 1024,\n "target_h": 1024,\n "crop_w": 0,\n "crop_h": 0\n },\n }\n }\n ' + return (latent_width, latent_height, cte_w, cte_h, target_w, target_h, crop_w, crop_h) + if select_latent_ratio != 'custom': + latent_width = self.ratio_dict[select_latent_ratio]['width'] + latent_height = self.ratio_dict[select_latent_ratio]['height'] + else: + latent_width = custom_latent_w + latent_height = custom_latent_h + if select_cte_ratio != 'custom': + cte_w = self.ratio_dict[select_cte_ratio]['width'] + cte_h = self.ratio_dict[select_cte_ratio]['height'] + else: + cte_w = cte_w + cte_h = cte_h + if cte_mult != 0.0: + (cte_w, cte_h) = self.mult(cte_w, cte_h, cte_mult) + if cte_res != 0: + (cte_w, cte_h) = self.res(cte_w, cte_h, cte_res) + if cte_fit_size != 0: + (cte_w, cte_h) = self.fit(cte_w, cte_h, cte_fit_size) + if select_target_ratio != 'custom': + target_w = self.ratio_dict[select_target_ratio]['width'] + target_h = self.ratio_dict[select_target_ratio]['height'] + else: + target_w = target_w + target_h = target_h + if target_mult != 0.0: + (target_w, target_h) = self.mult(target_w, target_h, target_mult) + if target_res != 0: + (target_w, target_h) = self.res(target_w, target_h, target_res) + if target_fit_size != 0: + (target_w, target_h) = self.fit(target_w, target_h, target_fit_size) + return (latent_width, latent_height, cte_w, cte_h, target_w, target_h, crop_w, crop_h) +``` \ No newline at end of file diff --git a/docs/ReActorBuildFaceModel.md b/docs/ReActorBuildFaceModel.md new file mode 100644 index 0000000..8928fe8 --- /dev/null +++ b/docs/ReActorBuildFaceModel.md @@ -0,0 +1,106 @@ +# Documentation +- Class name: BuildFaceModel +- Category: 🌌 ReActor +- Output node: True +- Repo Ref: https://github.com/Gourieff/comfyui-reactor-node.git + +该节点旨在从一组输入图像中合成面部模型,利用先进的计算机视觉技术来检测、分析和融合面部特征。它旨在创建输入面部的合表示,可用于各种应用,如识别、认证或可视化。该节点强调整合图像处理和机器学习技术,以实现高级面部合成。 + +# Input types +## Required +- images + - 'image'参数对于面部模型构建过程至关重要。它作为主要输入,提供面部检测和特征提取所需的视觉数据。图像的质量和数量直接影响合成面部模型的准确性和细节。 + - Comfy dtype: COMBO[string] + - Python dtype: List[Image.Image] +- face_model_name + - 'face_model_name'参数对于识别和组织输出的面部模型至关重要。它作为每个模型的唯一标识符,便于后续检索和管理合成的面部数据。 + - Comfy dtype: string + - Python dtype: str +- compute_method + - 'compute_method'参数决定了用于将多个面部特征融合到单个复合模型中的技术。它影响面部模型的最终表示,不同的方法可能导致不同程度的细节和准确性。 + - Comfy dtype: COMBO[string] + - Python dtype: str +## Optional +- save_mode + - 'save_mode'参数决定合成的面部模型是否保存到输出目录。它允许用户控制节点的输出,决定是否保留生成的模型以供将来使用,还是在处理后简单地丢弃它们。 + - Comfy dtype: COMBO[boolean] + - Python dtype: bool + +# Output types +- face_model_name + - 输出'face_model_name'代表合成面部模型的唯一标识符。它是用户在后续流程或应用中引用和使用生成模型的关键信息。 + - Comfy dtype: string + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BuildFaceModel: + + def __init__(self): + self.output_dir = FACE_MODELS_PATH + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'save_mode': ('BOOLEAN', {'default': True, 'label_off': 'OFF', 'label_on': 'ON'}), 'face_model_name': ('STRING', {'default': 'default'}), 'compute_method': (['Mean', 'Median', 'Mode'], {'default': 'Mean'})}} + RETURN_TYPES = () + FUNCTION = 'blend_faces' + OUTPUT_NODE = True + CATEGORY = '🌌 ReActor' + + def build_face_model(self, image: Image.Image, det_size=(640, 640)): + if image is None: + error_msg = 'Please load an Image' + logger.error(error_msg) + return error_msg + image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) + face_model = analyze_faces(image, det_size) + if len(face_model) == 0: + det_size_half = half_det_size(det_size) + face_model = analyze_faces(image, det_size_half) + if face_model is not None and len(face_model) > 0: + return face_model[0] + else: + no_face_msg = 'No face found, please try another image' + logger.error(no_face_msg) + return no_face_msg + + def blend_faces(self, images, save_mode, face_model_name, compute_method): + if save_mode and images is not None: + faces = [] + embeddings = [] + images_list: List[Image.Image] = batch_tensor_to_pil(images) + apply_logging_patch(1) + n = len(images_list) + import logging + logging.StreamHandler.terminator = ' ' + for (i, image) in enumerate(images_list): + logger.status(f'Building Face Model {i + 1} of {n}...') + face = self.build_face_model(image) + print(f'{int((i + 1) / n * 100)}%') + if isinstance(face, str): + continue + faces.append(face) + embeddings.append(face.embedding) + logging.StreamHandler.terminator = '\n' + if len(faces) > 0: + compute_method_name = 'Mean' if compute_method == 0 else 'Median' if compute_method == 1 else 'Mode' + logger.status(f'Blending with Compute Method {compute_method_name}...') + blended_embedding = np.mean(embeddings, axis=0) if compute_method == 'Mean' else np.median(embeddings, axis=0) if compute_method == 'Median' else stats.mode(embeddings, axis=0)[0].astype(np.float32) + blended_face = Face(bbox=faces[0].bbox, kps=faces[0].kps, det_score=faces[0].det_score, landmark_3d_68=faces[0].landmark_3d_68, pose=faces[0].pose, landmark_2d_106=faces[0].landmark_2d_106, embedding=blended_embedding, gender=faces[0].gender, age=faces[0].age) + if blended_face is not None: + face_model_path = os.path.join(FACE_MODELS_PATH, face_model_name + '.safetensors') + save_face_model(blended_face, face_model_path) + logger.status('--Done!--') + return face_model_name + else: + no_face_msg = 'Something went wrong, please try another set of images' + logger.error(no_face_msg) + return face_model_name + logger.status('--Done!--') + if images is None: + logger.error('Please provide `images`') + return face_model_name +``` \ No newline at end of file diff --git a/docs/ReActorFaceSwap.md b/docs/ReActorFaceSwap.md new file mode 100644 index 0000000..84330ad --- /dev/null +++ b/docs/ReActorFaceSwap.md @@ -0,0 +1,177 @@ +# Documentation +- Class name: reactor +- Category: 🌌 ReActor +- Output node: False +- Repo Ref: https://github.com/Gourieff/comfyui-reactor-node.git + +reactor类是一个全面的人脸操作工具包,旨在执行高级的人脸交换和恢复操作。它利用深度学习模型的力量来分析、恢复和交换图像中的人脸,同时提供性别检测和人脸可见性调整的选项。 + +# Input types +## Required +- enabled + - 启用或禁用人脸处理流水线的执行。当设置为false时,输入的图像和人脸模型将不做修改直接返回。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- input_image + - 包含要由reactor节点处理的人脸的源图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- swap_model + - 指定在人脸交换过程中使用的人脸检测模型。 + - Comfy dtype: COMBO[retinaface_resnet50, retinaface_mobile0.25, YOLOv5l, YOLOv5n] + - Python dtype: str +- face_restore_model + - 指示用于提高检测到的人脸质量的人脸恢复模型。 + - Comfy dtype: COMBO[none, CodeFormer, other models...] + - Python dtype: str +- face_restore_visibility + - 一个浮点值,用于控制恢复后人脸的可见度,1表示完全可见,0.1表示几乎不可见。 + - Comfy dtype: FLOAT + - Python dtype: float +- codeformer_weight + - 在恢复人脸时对codeformer模型的输出应用权重因子,影响原始人脸特征与恢复后人脸特征之间的平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- detect_gender_input + - 选择要在输入人脸中检测的性别,这可以影响人脸交换操作期间人脸的选择和处理。 + - Comfy dtype: COMBO[no, female, male] + - Python dtype: str +- input_faces_index + - 一个字符串,表示要考虑处理的输入人脸的索引或多个索引,索引以逗号分隔。 + - Comfy dtype: STRING + - Python dtype: str +- console_log_level + - 设置节点执行期间生成的控制台日志的详细程度,0表示警告,1表示状态消息,2表示详细信息。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result_image + - 经过人脸交换和恢复操作处理后的输出图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- face_model + - 执行过程中使用的人脸模型,可以是默认模型或用户指定的模型。 + - Comfy dtype: FACE_MODEL + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class reactor: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'enabled': ('BOOLEAN', {'default': True, 'label_off': 'OFF', 'label_on': 'ON'}), 'input_image': ('IMAGE',), 'swap_model': (list(model_names().keys()),), 'facedetection': (['retinaface_resnet50', 'retinaface_mobile0.25', 'YOLOv5l', 'YOLOv5n'],), 'face_restore_model': (get_model_names(get_restorers),), 'face_restore_visibility': ('FLOAT', {'default': 1, 'min': 0.1, 'max': 1, 'step': 0.05}), 'codeformer_weight': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1, 'step': 0.05}), 'detect_gender_input': (['no', 'female', 'male'], {'default': 'no'}), 'detect_gender_source': (['no', 'female', 'male'], {'default': 'no'}), 'input_faces_index': ('STRING', {'default': '0'}), 'source_faces_index': ('STRING', {'default': '0'}), 'console_log_level': ([0, 1, 2], {'default': 1})}, 'optional': {'source_image': ('IMAGE',), 'face_model': ('FACE_MODEL',)}} + RETURN_TYPES = ('IMAGE', 'FACE_MODEL') + FUNCTION = 'execute' + CATEGORY = '🌌 ReActor' + + def __init__(self): + self.face_helper = None + + def restore_face(self, input_image, face_restore_model, face_restore_visibility, codeformer_weight, facedetection): + result = input_image + if face_restore_model != 'none' and (not model_management.processing_interrupted()): + logger.status(f'Restoring with {face_restore_model}') + model_path = folder_paths.get_full_path('facerestore_models', face_restore_model) + device = model_management.get_torch_device() + if 'codeformer' in face_restore_model.lower(): + codeformer_net = ARCH_REGISTRY.get('CodeFormer')(dim_embd=512, codebook_size=1024, n_head=8, n_layers=9, connect_list=['32', '64', '128', '256']).to(device) + checkpoint = torch.load(model_path)['params_ema'] + codeformer_net.load_state_dict(checkpoint) + facerestore_model = codeformer_net.eval() + elif '.onnx' in face_restore_model: + ort_session = set_ort_session(model_path, providers=providers) + ort_session_inputs = {} + facerestore_model = ort_session + else: + sd = comfy.utils.load_torch_file(model_path, safe_load=True) + facerestore_model = model_loading.load_state_dict(sd).eval() + facerestore_model.to(device) + if self.face_helper is None: + self.face_helper = FaceRestoreHelper(1, face_size=512, crop_ratio=(1, 1), det_model=facedetection, save_ext='png', use_parse=True, device=device) + image_np = 255.0 * result.cpu().numpy() + total_images = image_np.shape[0] + out_images = np.ndarray(shape=image_np.shape) + for i in range(total_images): + if total_images > 1: + logger.status(f'Restoring {i + 1}') + cur_image_np = image_np[i, :, :, ::-1] + original_resolution = cur_image_np.shape[0:2] + if facerestore_model is None or self.face_helper is None: + return result + self.face_helper.clean_all() + self.face_helper.read_image(cur_image_np) + self.face_helper.get_face_landmarks_5(only_center_face=False, resize=640, eye_dist_threshold=5) + self.face_helper.align_warp_face() + restored_face = None + for (idx, cropped_face) in enumerate(self.face_helper.cropped_faces): + if '.pth' in face_restore_model: + cropped_face_t = img2tensor(cropped_face / 255.0, bgr2rgb=True, float32=True) + normalize(cropped_face_t, (0.5, 0.5, 0.5), (0.5, 0.5, 0.5), inplace=True) + cropped_face_t = cropped_face_t.unsqueeze(0).to(device) + try: + with torch.no_grad(): + if '.onnx' in face_restore_model: + for ort_session_input in ort_session.get_inputs(): + if ort_session_input.name == 'input': + cropped_face_prep = prepare_cropped_face(cropped_face) + ort_session_inputs[ort_session_input.name] = cropped_face_prep + if ort_session_input.name == 'weight': + weight = np.array([1], dtype=np.double) + ort_session_inputs[ort_session_input.name] = weight + output = ort_session.run(None, ort_session_inputs)[0][0] + restored_face = normalize_cropped_face(output) + else: + output = facerestore_model(cropped_face_t, w=codeformer_weight)[0] if 'codeformer' in face_restore_model.lower() else facerestore_model(cropped_face_t)[0] + restored_face = tensor2img(output, rgb2bgr=True, min_max=(-1, 1)) + del output + torch.cuda.empty_cache() + except Exception as error: + print(f'\tFailed inference: {error}', file=sys.stderr) + restored_face = tensor2img(cropped_face_t, rgb2bgr=True, min_max=(-1, 1)) + if face_restore_visibility < 1: + restored_face = cropped_face * (1 - face_restore_visibility) + restored_face * face_restore_visibility + restored_face = restored_face.astype('uint8') + self.face_helper.add_restored_face(restored_face) + self.face_helper.get_inverse_affine(None) + restored_img = self.face_helper.paste_faces_to_input_image() + restored_img = restored_img[:, :, ::-1] + if original_resolution != restored_img.shape[0:2]: + restored_img = cv2.resize(restored_img, (0, 0), fx=original_resolution[1] / restored_img.shape[1], fy=original_resolution[0] / restored_img.shape[0], interpolation=cv2.INTER_LINEAR) + self.face_helper.clean_all() + out_images[i] = restored_img + restored_img_np = np.array(out_images).astype(np.float32) / 255.0 + restored_img_tensor = torch.from_numpy(restored_img_np) + result = restored_img_tensor + return result + + def execute(self, enabled, input_image, swap_model, detect_gender_source, detect_gender_input, source_faces_index, input_faces_index, console_log_level, face_restore_model, face_restore_visibility, codeformer_weight, facedetection, source_image=None, face_model=None): + apply_logging_patch(console_log_level) + if not enabled: + return (input_image, face_model) + elif source_image is None and face_model is None: + logger.error("Please provide 'source_image' or `face_model`") + return (input_image, face_model) + if face_model == 'none': + face_model = None + script = FaceSwapScript() + pil_images = batch_tensor_to_pil(input_image) + if source_image is not None: + source = tensor_to_pil(source_image) + else: + source = None + p = StableDiffusionProcessingImg2Img(pil_images) + script.process(p=p, img=source, enable=True, source_faces_index=source_faces_index, faces_index=input_faces_index, model=swap_model, swap_in_source=True, swap_in_generated=True, gender_source=detect_gender_source, gender_target=detect_gender_input, face_model=face_model) + result = batched_pil_to_tensor(p.init_images) + if face_model is None: + current_face_model = get_current_faces_model() + face_model_to_provide = current_face_model[0] if current_face_model is not None and len(current_face_model) > 0 else face_model + else: + face_model_to_provide = face_model + result = reactor.restore_face(self, result, face_restore_model, face_restore_visibility, codeformer_weight, facedetection) + return (result, face_model_to_provide) +``` \ No newline at end of file diff --git a/docs/ReActorLoadFaceModel.md b/docs/ReActorLoadFaceModel.md new file mode 100644 index 0000000..0f9bd70 --- /dev/null +++ b/docs/ReActorLoadFaceModel.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: LoadFaceModel +- Category: 🌌 ReActor +- Output node: False +- Repo Ref: https://github.com/Gourieff/comfyui-reactor-node.git + +该节点便于加载和准备面部识别模型,这对于后续的面部处理任务至关重要。它封装了模型检索的复杂性,并确保基于输入规格使用适当的模型,从而增强了系统的灵活性和适应性。 + +# Input types +## Required +- face_model + - ‘face_model’参数至关重要,因为它决定了节点将加载哪个面部识别模型。它通过确定后续操作中将应用的特定特征和算法,影响整个处理流程。 + - Comfy dtype: COMBO[get_model_names(get_facemodels())] + - Python dtype: Union[str, None] + +# Output types +- FACE_MODEL + - 输出代表加载的面部识别模型,这是进一步面部分析和处理任务的关键组成部分。它封装了模型学习到的特征,准备应用于下游操作。 + - Comfy dtype: Face + - Python dtype: insightface.app.common.Face + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadFaceModel: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'face_model': (get_model_names(get_facemodels),)}} + RETURN_TYPES = ('FACE_MODEL',) + FUNCTION = 'load_model' + CATEGORY = '🌌 ReActor' + + def load_model(self, face_model): + self.face_model = face_model + self.face_models_path = FACE_MODELS_PATH + if self.face_model != 'none': + face_model_path = os.path.join(self.face_models_path, self.face_model) + out = load_face_model(face_model_path) + else: + out = None + return (out,) +``` \ No newline at end of file diff --git a/docs/ReActorRestoreFace.md b/docs/ReActorRestoreFace.md new file mode 100644 index 0000000..d27457f --- /dev/null +++ b/docs/ReActorRestoreFace.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: RestoreFace +- Category: 🌌 ReActor +- Output node: False +- Repo Ref: https://github.com/Gourieff/comfyui-reactor-node.git + +RestoreFace节点旨在使用先进的面部恢复模型来增强和修复图像中的面部特征。它通过利用深度学习技术来提高面部的视觉质量,这对于需要高质量面部图像的应用程序特别有用。 + +# Input types +## Required +- image + - 图像参数对于面部恢复过程至关重要,它提供了面部修复的源材料。它直接影响恢复面部的质量和准确性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +- facedetection + - facedetection参数指定用于在输入图像中识别面部的检测模型。它对于准确的面部定位至关重要,这是有效面部恢复的先决条件。 + - Comfy dtype: COMBO[retinaface_resnet50,retinaface_mobile0.25,YOLOv5l,YOLOv5n] + - Python dtype: str +- model + - 模型参数决定了要应用的面部恢复模型,规定了用于增强面部特征的特定算法和技术。 + - Comfy dtype: COMBO[get_model_names(get_restorers)] + - Python dtype: str +- visibility + - 可见性参数调整恢复面部的透明度水平,允许微调原始和恢复特征混合的程度。 + - Comfy dtype: FLOAT + - Python dtype: float +- codeformer_weight + - codeformer_weight参数影响CodeFormer模型在恢复过程中的贡献,较高的值强调模型对最终结果的影响。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output_image + - 输出图像代表面部恢复的最终结果,其中输入图像的面部已得到增强和恢复到更高质量。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RestoreFace: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'facedetection': (['retinaface_resnet50', 'retinaface_mobile0.25', 'YOLOv5l', 'YOLOv5n'],), 'model': (get_model_names(get_restorers),), 'visibility': ('FLOAT', {'default': 1, 'min': 0.0, 'max': 1, 'step': 0.05}), 'codeformer_weight': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1, 'step': 0.05})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'execute' + CATEGORY = '🌌 ReActor' + + def __init__(self): + self.face_helper = None + + def execute(self, image, model, visibility, codeformer_weight, facedetection): + result = reactor.restore_face(self, image, model, visibility, codeformer_weight, facedetection) + return (result,) +``` \ No newline at end of file diff --git a/docs/ReActorSaveFaceModel.md b/docs/ReActorSaveFaceModel.md new file mode 100644 index 0000000..5969d35 --- /dev/null +++ b/docs/ReActorSaveFaceModel.md @@ -0,0 +1,79 @@ +# Documentation +- Class name: SaveFaceModel +- Category: 🌌 ReActor +- Output node: True +- Repo Ref: https://github.com/Gourieff/comfyui-reactor-node.git + +该节点旨在保存面部识别模型,封装了将图像数据转换为可用于进一步分析或识别的结构化格式的过程。它强调保留面部属性和特征以供将来使用,而不深入探讨底层算法或数据结构的具体细节。 + +# Input types +## Required +- save_mode + - 此参数决定是否保存模型,作为整个保存过程的开关。它在确定节点的输出和系统随后采取的行动中起着关键作用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- face_model_name + - 赋予面部模型的名称作为保存模型的标识符,允许在未来的操作中轻松检索和引用。它对于保持模型库存中的组织和清晰至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- select_face_index + - 此索引从分析数据中选择一个特定的面部,指导节点专注于模型的特定面部特征。它在更广泛的数据集中针对特定数据起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- image + - 输入图像提供了面部分析和模型创建所需的视觉数据。其质量和分辨率直接影响生成的面部模型的准确性和细节。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- face_model + - 面部模型输入是一个可选参数,如果提供,允许节点绕过面部分析步骤并直接保存给定的模型。当有预先分析的模型可用时,这可以简化流程。 + - Comfy dtype: FACE_MODEL + - Python dtype: insightface.Face + +# Output types +- face_model_name + - 输出反映了保存的面部模型的名称,表示保存过程的成功完成。它作为确认和参考,用于与保存的模型的未来交互。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SaveFaceModel: + + def __init__(self): + self.output_dir = FACE_MODELS_PATH + + @classmethod + def INPUT_TYPES(s): + return {'required': {'save_mode': ('BOOLEAN', {'default': True, 'label_off': 'OFF', 'label_on': 'ON'}), 'face_model_name': ('STRING', {'default': 'default'}), 'select_face_index': ('INT', {'default': 0, 'min': 0})}, 'optional': {'image': ('IMAGE',), 'face_model': ('FACE_MODEL',)}} + RETURN_TYPES = () + FUNCTION = 'save_model' + OUTPUT_NODE = True + CATEGORY = '🌌 ReActor' + + def save_model(self, save_mode, face_model_name, select_face_index, image=None, face_model=None, det_size=(640, 640)): + if save_mode and image is not None: + source = tensor_to_pil(image) + source = cv2.cvtColor(np.array(source), cv2.COLOR_RGB2BGR) + apply_logging_patch(1) + logger.status('Building Face Model...') + face_model_raw = analyze_faces(source, det_size) + if len(face_model_raw) == 0: + det_size_half = half_det_size(det_size) + face_model_raw = analyze_faces(source, det_size_half) + try: + face_model = face_model_raw[select_face_index] + except: + logger.error('No face(s) found') + return face_model_name + logger.status('--Done!--') + if save_mode and (face_model != 'none' or face_model is not None): + face_model_path = os.path.join(self.output_dir, face_model_name + '.safetensors') + save_face_model(face_model, face_model_path) + if image is None and face_model is None: + logger.error('Please provide `face_model` or `image`') + return face_model_name +``` \ No newline at end of file diff --git a/docs/Read Playlist (mtb).md b/docs/Read Playlist (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ReencodeLatent.md b/docs/ReencodeLatent.md new file mode 100644 index 0000000..54a767b --- /dev/null +++ b/docs/ReencodeLatent.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: ReencodeLatent +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ReencodeLatent 是一个用于通过一对变分自编码器(VAE)重新编码潜在表示的节点。它首先使用输入VAE将输入样本解码成像素空间,然后使用输出VAE将它们重新编码回潜在空间。这个节点特别适用于需要在潜在和像素域中操纵和分析数据的任务。 + +# Input types +## Required +- samples + - “samples”参数是ReencodeLatent节点的关键输入,因为它代表了将要重新编码的潜在表示。它对节点的执行至关重要,因为它决定了将经历解码和编码过程的数据。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- tile_mode + - “tile_mode”参数决定像素数据的解码和编码如何处理。它可以设置为'None'、'Both'、'Decode(input) only'或'Encode(output) only',这决定了节点是执行两个操作,还是选择性地执行解码或编码步骤。 + - Comfy dtype: COMBO[None, Both, Decode(input) only, Encode(output) only] + - Python dtype: str +- input_vae + - “input_vae”参数指定用于将潜在样本最初解码成像素空间的变分自编码器。它在节点的功能中起着重要作用,因为它决定了影响数据初始转换的模型。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- output_vae + - “output_vae”参数定义了负责将像素数据重新编码成潜在表示的变分自编码器。这个参数至关重要,因为它决定了将形成节点最终输出的模型。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +## Optional +- tile_size + - “tile_size”参数是一个可选输入,用于设置解码和编码过程中使用的瓦片大小。当tile_mode设置为'Both'或'Decode(input) only'时,它特别重要,影响像素数据处理的分辨率。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- latent + - “latent”输出代表节点处理后重新编码的潜在表示。它很重要,因为它提供了可以用于进一步分析或作为后续节点输入的转换后数据。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ReencodeLatent: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'samples': ('LATENT',), 'tile_mode': (['None', 'Both', 'Decode(input) only', 'Encode(output) only'],), 'input_vae': ('VAE',), 'output_vae': ('VAE',), 'tile_size': ('INT', {'default': 512, 'min': 320, 'max': 4096, 'step': 64})}} + CATEGORY = 'ImpactPack/Util' + RETURN_TYPES = ('LATENT',) + FUNCTION = 'doit' + + def doit(self, samples, tile_mode, input_vae, output_vae, tile_size=512): + if tile_mode in ['Both', 'Decode(input) only']: + pixels = nodes.VAEDecodeTiled().decode(input_vae, samples, tile_size)[0] + else: + pixels = nodes.VAEDecode().decode(input_vae, samples)[0] + if tile_mode in ['Both', 'Encode(output) only']: + return nodes.VAEEncodeTiled().encode(output_vae, pixels, tile_size) + else: + return nodes.VAEEncode().encode(output_vae, pixels) +``` \ No newline at end of file diff --git a/docs/ReencodeLatentPipe.md b/docs/ReencodeLatentPipe.md new file mode 100644 index 0000000..a6eed72 --- /dev/null +++ b/docs/ReencodeLatentPipe.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: ReencodeLatentPipe +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ReencodeLatentPipe 是一个用于促进潜在空间表示转换的节点。它通过使用一对变分自编码器(VAE)重新编码潜在空间中的样本来操作。此节点对于需要在不同VAE模型之间操作或比较潜在表示的任务至关重要。 + +# Input types +## Required +- samples + - “samples”参数至关重要,因为它表示需要重新编码的潜在空间数据。它是节点的主要输入,并直接影响节点的处理和输出。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- tile_mode + - “tile_mode”参数在重新编码过程中决定了像素平铺的处理方式。它对于控制节点关于像素数据结构的行为至关重要。 + - Comfy dtype: COMBO['None', 'Both', 'Decode(input) only', 'Encode(output) only'] + - Python dtype: str +- input_basic_pipe + - “input_basic_pipe”参数是一个复合输入,包括用于解码潜在样本的初始VAE模型。它在重新编码过程的初始阶段扮演重要角色。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, ...] +- output_basic_pipe + - “output_basic_pipe”参数包括负责编码重新编码的潜在样本的最终VAE模型。它是节点最终输出生成的关键组成部分。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, ...] + +# Output types +- latent_samples + - “latent_samples”输出代表重新编码后的潜在空间数据。它是节点操作的结果,对于后续任务中的进一步分析或处理具有重要意义。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ReencodeLatentPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'samples': ('LATENT',), 'tile_mode': (['None', 'Both', 'Decode(input) only', 'Encode(output) only'],), 'input_basic_pipe': ('BASIC_PIPE',), 'output_basic_pipe': ('BASIC_PIPE',)}} + CATEGORY = 'ImpactPack/Util' + RETURN_TYPES = ('LATENT',) + FUNCTION = 'doit' + + def doit(self, samples, tile_mode, input_basic_pipe, output_basic_pipe): + (_, _, input_vae, _, _) = input_basic_pipe + (_, _, output_vae, _, _) = output_basic_pipe + return ReencodeLatent().doit(samples, tile_mode, input_vae, output_vae) +``` \ No newline at end of file diff --git a/docs/ReferenceOnlySimple.md b/docs/ReferenceOnlySimple.md new file mode 100644 index 0000000..4b595e9 --- /dev/null +++ b/docs/ReferenceOnlySimple.md @@ -0,0 +1,79 @@ +# Documentation +- Class name: ReferenceOnlySimple +- Category: custom_node_experiments +- Output node: False +- Repo Ref: https://github.com/comfyanonymous/ComfyUI_experiments + +在`ReferenceOnlySimple`节点中的`reference_only`方法旨在通过整合参考结构来增强给定的模型。它通过克隆输入模型并对其注意力机制应用自定义的参考应用函数来操作,允许集成额外的潜在样本。这种方法特别适用于涉及模型适应和潜在空间操作的实验。 + +# Input types +## Required +- model + - ‘model’参数至关重要,因为它代表了将由节点增强的机器学习模型。它是主要的输入,决定了节点内应用的后续操作和转换。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- reference + - ‘reference’参数是一个关键输入,它提供了要与模型集成的潜在空间样本。它通过影响潜在空间的结构和内容,在节点的功能中起着重要作用。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +## Optional +- batch_size + - ‘batch_size’参数决定了模型操作中使用的批次大小。它影响节点的效率和内存使用情况,允许根据手头任务的具体要求进行定制。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- model_reference + - ‘model_reference’输出是已通过参考结构增强的修改后的模型。它是节点操作的直接结果,可供进一步使用或评估。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- latent + - ‘latent’输出包含来自参考和节点新生成的潜在空间样本的组合。它标志着节点操作和扩展潜在空间的能力。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ReferenceOnlySimple: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'reference': ('LATENT',), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}} + RETURN_TYPES = ('MODEL', 'LATENT') + FUNCTION = 'reference_only' + CATEGORY = 'custom_node_experiments' + + def reference_only(self, model, reference, batch_size): + model_reference = model.clone() + size_latent = list(reference['samples'].shape) + size_latent[0] = batch_size + latent = {} + latent['samples'] = torch.zeros(size_latent) + batch = latent['samples'].shape[0] + reference['samples'].shape[0] + + def reference_apply(q, k, v, extra_options): + k = k.clone().repeat(1, 2, 1) + offset = 0 + if q.shape[0] > batch: + offset = batch + for o in range(0, q.shape[0], batch): + for x in range(1, batch): + k[x + o, q.shape[1]:] = q[o, :] + return (q, k, k) + model_reference.set_model_attn1_patch(reference_apply) + out_latent = torch.cat((reference['samples'], latent['samples'])) + if 'noise_mask' in latent: + mask = latent['noise_mask'] + else: + mask = torch.ones((64, 64), dtype=torch.float32, device='cpu') + if len(mask.shape) < 3: + mask = mask.unsqueeze(0) + if mask.shape[0] < latent['samples'].shape[0]: + print(latent['samples'].shape, mask.shape) + mask = mask.repeat(latent['samples'].shape[0], 1, 1) + out_mask = torch.zeros((1, mask.shape[1], mask.shape[2]), dtype=torch.float32, device='cpu') + return (model_reference, {'samples': out_latent, 'noise_mask': torch.cat((out_mask, mask))}) +``` \ No newline at end of file diff --git a/docs/RegionalConditioningColorMask %2F%2FInspire.md b/docs/RegionalConditioningColorMask %2F%2FInspire.md new file mode 100644 index 0000000..c3957c7 --- /dev/null +++ b/docs/RegionalConditioningColorMask %2F%2FInspire.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: RegionalConditioningColorMask +- Category: InspirePack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +RegionalConditioningColorMask 节点旨在将颜色掩码应用于 CLIP 模型的文本编码,增强模型对图像特定区域的关注。它通过将颜色掩码图像转换为二进制掩码来实现这一点,然后将该掩码用于条件文本编码。这允许对图像生成过程进行更精细的控制,确保生成的图像与所需的主题元素紧密对齐。 + +# Input types +## Required +- clip + - 参数 'clip' 是 CLIP 模型将编码的输入文本提示。它对于定义模型在图像生成过程中应关注的语义内容至关重要。节点的有效性在很大程度上取决于输入剪辑的相关性和特异性。 + - Comfy dtype: CLIP + - Python dtype: str +- color_mask + - 参数 'color_mask' 是定义图像内感兴趣区域的图像。该图像用于创建一个掩码,将引导模型关注指定区域。颜色掩码的质量和准确性直接影响区域条件的精度。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- mask_color + - 参数 'mask_color' 指定了在 'color_mask' 图像中用于掩码的颜色。它对于识别图像中的目标区域很重要,并应以有效的 RGB 颜色格式提供。掩码颜色的选择影响节点隔离所需区域的能力。 + - Comfy dtype: STRING + - Python dtype: str +- strength + - 参数 'strength' 控制掩码对文本编码影响的强度。较高的值增加了对掩码区域的强调,可能导致生成的图像中特征更加明显。它是微调区域焦点和整体图像一致性之间平衡的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- prompt + - 参数 'prompt' 是一个详细的文本描述,它进一步细化了图像生成过程。它为模型提供了额外的上下文和指导,确保生成的图像更符合用户的创意愿景。提示的内容对最终输出有重大影响。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- set_cond_area + - 参数 'set_cond_area' 确定掩码如何应用于条件。它可以使用默认行为或显式设置掩码边界。这个选择可以影响节点针对图像内特定区域进行增强区域条件的能力。 + - Comfy dtype: COMBO['default', 'mask bounds'] + - Python dtype: str + +# Output types +- conditioning + - 输出 'conditioning' 表示已经被颜色掩码修改过的文本编码。它用于指导图像生成过程,确保生成的图像反映了输入提示中指定的主题元素。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- mask + - 输出 'mask' 是从 'color_mask' 图像派生的二进制掩码。它由节点内部用于将区域条件应用于文本编码,允许对图像生成过程进行更精确的控制。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RegionalConditioningColorMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'clip': ('CLIP',), 'color_mask': ('IMAGE',), 'mask_color': ('STRING', {'multiline': False, 'default': '#FFFFFF'}), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'set_cond_area': (['default', 'mask bounds'],), 'prompt': ('STRING', {'multiline': True, 'placeholder': 'prompt'})}} + RETURN_TYPES = ('CONDITIONING', 'MASK') + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Regional' + + def doit(self, clip, color_mask, mask_color, strength, set_cond_area, prompt): + mask = color_to_mask(color_mask, mask_color) + conditioning = nodes.CLIPTextEncode().encode(clip, prompt)[0] + conditioning = nodes.ConditioningSetMask().append(conditioning, mask, set_cond_area, strength)[0] + return (conditioning, mask) +``` \ No newline at end of file diff --git a/docs/RegionalConditioningSimple %2F%2FInspire.md b/docs/RegionalConditioningSimple %2F%2FInspire.md new file mode 100644 index 0000000..4ef16a6 --- /dev/null +++ b/docs/RegionalConditioningSimple %2F%2FInspire.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: RegionalConditioningSimple +- Category: InspirePack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +此类节点提供了一种使用CLIP和指定掩码对图像应用区域性条件的方法。它允许根据用户输入微调图像生成,以专注于某些区域,提高生成内容的相关性和准确性。 + +# Input types +## Required +- clip + - “clip”参数对于节点的运作至关重要,因为它定义了图像生成所基于的视觉上下文。它是条件过程的主要输入。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- mask + - “mask”参数对于指定图像内的兴趣区域至关重要。它指导节点选择性地应用条件效果,确保生成的内容与用户期望的焦点区域一致。 + - Comfy dtype: MASK + - Python dtype: PIL.Image +- strength + - “strength”参数调整区域性条件的强度,允许用户控制对指定区域的强调程度。它直接影响输出中条件特征的显著性。 + - Comfy dtype: FLOAT + - Python dtype: float +- set_cond_area + - “set_cond_area”参数决定了定义区域性条件区域的方法。它可以是默认设置或基于掩码边界,这影响了掩码如何应用于图像。 + - Comfy dtype: COMBO + - Python dtype: str +- prompt + - “prompt”参数提供了指导图像生成过程的文本描述。它是条件不可或缺的一部分,因为它为AI提供了创建与期望输出匹配的内容的上下文和方向。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- conditioning + - “conditioning”输出代表了已应用于图像的处理过的区域性条件数据。它包含了输入参数的效果,是进一步图像操作或分析的关键组成部分。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RegionalConditioningSimple: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'clip': ('CLIP',), 'mask': ('MASK',), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'set_cond_area': (['default', 'mask bounds'],), 'prompt': ('STRING', {'multiline': True, 'placeholder': 'prompt'})}} + RETURN_TYPES = ('CONDITIONING',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Regional' + + def doit(self, clip, mask, strength, set_cond_area, prompt): + conditioning = nodes.CLIPTextEncode().encode(clip, prompt)[0] + conditioning = nodes.ConditioningSetMask().append(conditioning, mask, set_cond_area, strength)[0] + return (conditioning,) +``` \ No newline at end of file diff --git a/docs/RegionalIPAdapterColorMask %2F%2FInspire.md b/docs/RegionalIPAdapterColorMask %2F%2FInspire.md new file mode 100644 index 0000000..b627656 --- /dev/null +++ b/docs/RegionalIPAdapterColorMask %2F%2FInspire.md @@ -0,0 +1,85 @@ +# Documentation +- Class name: RegionalIPAdapterColorMask +- Category: InspirePack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +RegionalIPAdapterColorMask节点旨在对图像应用颜色遮罩,可用于将生成过程集中在感兴趣的特定区域上。该节点利用IPAdapter模型的力量,根据提供的遮罩对生成进行条件化,增强对视觉输出的控制,并确保更紧密地遵循指定的颜色区域。 + +# Input types +## Required +- color_mask + - color_mask参数至关重要,它定义了将用于生成遮罩的图像。该图像被处理以创建一个二进制遮罩,该遮罩将应用于生成,确保在输出中强调指定的颜色区域。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask_color + - mask_color参数对于确定用于创建遮罩的特定颜色至关重要。它是一个表示RGB格式颜色值的字符串,用于识别和隔离图像内的目标颜色区域。 + - Comfy dtype: STRING + - Python dtype: str +- image + - image参数是节点处理的输入图像。它是应用颜色遮罩的画布,其内容将受到遮罩的影响,以实现期望的视觉效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- weight + - weight参数调整遮罩对生成的影响。较高的权重意味着遮罩的影响更加显著,而较低的权重减少了其效果,允许将遮罩的颜色区域更微妙地融入最终输出。 + - Comfy dtype: FLOAT + - Python dtype: float +- noise + - noise参数在生成过程中引入了一定程度的随机性。通过调整此参数,用户可以控制结果图像中的变化和不可预测性水平,为输出增添创造性和多样性。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight_type + - weight_type参数允许用户选择应用权重到遮罩的方法。不同的权重类型可以改变遮罩对生成的影响方式,提供一系列创意控制选项,以实现期望的审美。 + - Comfy dtype: COMBO + - Python dtype: str +- start_at + - start_at参数定义了遮罩对生成影响的起始点。它有助于控制遮罩效果的逐步引入,允许在最终输出中更细致和可控地应用颜色遮罩。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_at + - end_at参数设置了遮罩对生成影响达到顶峰的点。它与start_at参数共同作用,在整个生成过程中创建遮罩效果的平滑过渡。 + - Comfy dtype: FLOAT + - Python dtype: float +- unfold_batch + - unfold_batch参数决定了在应用遮罩过程中是否应展开批次维度。这对于某些类型的生成非常有用,其中批次内的个别元素需要独特的遮罩应用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- faceid_v2 + - faceid_v2参数启用了先进的面部检测和识别系统,它可以细化遮罩应用,更准确地聚焦于图像中的面部特征。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- weight_v2 + - weight_v2参数是faceid_v2特性的额外权重控制,允许微调面部遮罩应用,以实现更精确和详细的面部特征表现。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- REGIONAL_IPADAPTER + - regional_ipadapter输出是根据您的输入遮罩和颜色进行了调整的条件化模型。它准备好在后续的生成过程中使用,遮罩的影响已经融入其中,以引导创建期望的视觉元素。 + - Comfy dtype: REGIONAL_IPADAPTER + - Python dtype: object +- MASK + - MASK输出是从输入的color_mask和mask_color创建的二进制遮罩。这个遮罩可以用于进一步的处理,或者作为颜色遮罩所针对的图像区域的参考。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RegionalIPAdapterColorMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'color_mask': ('IMAGE',), 'mask_color': ('STRING', {'multiline': False, 'default': '#FFFFFF'}), 'image': ('IMAGE',), 'weight': ('FLOAT', {'default': 0.7, 'min': -1, 'max': 3, 'step': 0.05}), 'noise': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'weight_type': (['original', 'linear', 'channel penalty'],), 'start_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_at': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'unfold_batch': ('BOOLEAN', {'default': False})}, 'optional': {'faceid_v2': ('BOOLEAN', {'default': False}), 'weight_v2': ('FLOAT', {'default': 1.0, 'min': -1, 'max': 3, 'step': 0.05})}} + RETURN_TYPES = ('REGIONAL_IPADAPTER', 'MASK') + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Regional' + + def doit(self, color_mask, mask_color, image, weight, noise, weight_type, start_at=0.0, end_at=1.0, unfold_batch=False, faceid_v2=False, weight_v2=False): + mask = color_to_mask(color_mask, mask_color) + cond = IPAdapterConditioning(mask, weight, weight_type, noise=noise, image=image, start_at=start_at, end_at=end_at, unfold_batch=unfold_batch, faceid_v2=faceid_v2, weight_v2=weight_v2) + return (cond, mask) +``` \ No newline at end of file diff --git a/docs/RegionalIPAdapterEncodedColorMask %2F%2FInspire.md b/docs/RegionalIPAdapterEncodedColorMask %2F%2FInspire.md new file mode 100644 index 0000000..ed18a86 --- /dev/null +++ b/docs/RegionalIPAdapterEncodedColorMask %2F%2FInspire.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: RegionalIPAdapterEncodedColorMask +- Category: InspirePack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点将颜色掩码应用于图像,对其进行编码以供IPAdapter模型使用。它允许对掩码的应用进行精确控制,使用户能够专注于图像的特定区域,在生成过程中进行条件化处理。 + +# Input types +## Required +- color_mask + - 将要应用颜色掩码的输入图像。这张图像是生成过程中区域条件化的基础。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask_color + - 用于定义掩码的颜色值。此参数至关重要,因为它决定了在条件化过程中哪些部分的输入图像将被强调或忽略。 + - Comfy dtype: STRING + - Python dtype: str +- embeds + - 嵌入向量为模型提供额外的上下文,增强了条件化过程。这些嵌入向量对于根据输入提示和期望的风格塑造最终输出至关重要。 + - Comfy dtype: EMBEDS + - Python dtype: List[torch.Tensor] +- weight + - 权重参数调整掩码对生成的影响。更高的权重导致更严格遵守掩码,而较低的权重则允许更多的变化。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight_type + - 该参数决定了权重应用的类型,这可以显著改变条件化效果。它允许在掩码如何影响生成内容方面采取不同的策略。 + - Comfy dtype: COMBO + - Python dtype: str +- start_at + - 掩码效果的起始点,范围从0.0到1.0。它控制掩码对生成过程的初始影响强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_at + - 掩码效果的结束点,也从0.0到1.0范围。它决定了掩码对生成过程的影响如何逐渐减弱直至结束。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- unfold_batch + - 启用此选项后,允许批量应用掩码,这对于单次处理多个图像很有益处。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- REGIONAL_IPADAPTER + - 输出是一个区域性条件化的IPAdapter对象,可以用于后续的生成步骤,携带编码的掩码信息以指导模型。 + - Comfy dtype: REGIONAL_IPADAPTER + - Python dtype: IPAdapterConditioning +- MASK + - 已处理的掩码图像,准备应用于生成流程。它是实现期望区域效果的关键组成部分。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RegionalIPAdapterEncodedColorMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'color_mask': ('IMAGE',), 'mask_color': ('STRING', {'multiline': False, 'default': '#FFFFFF'}), 'embeds': ('EMBEDS',), 'weight': ('FLOAT', {'default': 0.7, 'min': -1, 'max': 3, 'step': 0.05}), 'weight_type': (['original', 'linear', 'channel penalty'],), 'start_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_at': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'unfold_batch': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('REGIONAL_IPADAPTER', 'MASK') + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Regional' + + def doit(self, color_mask, mask_color, embeds, weight, weight_type, start_at=0.0, end_at=1.0, unfold_batch=False): + mask = color_to_mask(color_mask, mask_color) + cond = IPAdapterConditioning(mask, weight, weight_type, embeds=embeds, start_at=start_at, end_at=end_at, unfold_batch=unfold_batch) + return (cond, mask) +``` \ No newline at end of file diff --git a/docs/RegionalIPAdapterEncodedMask %2F%2FInspire.md b/docs/RegionalIPAdapterEncodedMask %2F%2FInspire.md new file mode 100644 index 0000000..7cb1ed4 --- /dev/null +++ b/docs/RegionalIPAdapterEncodedMask %2F%2FInspire.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: RegionalIPAdapterEncodedMask +- Category: InspirePack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +RegionalIPAdapterEncodedMask 类旨在将区域掩码应用于图像处理适配器,使得可以根据指定的掩码对生成的图像进行条件化处理。该节点通过专注于图像中的特定感兴趣区域,增强了对图像生成过程的控制。它允许对图像属性和风格转移进行微调,确保生成的内容紧密符合所需的视觉元素。 + +# Input types +## Required +- mask + - 掩码参数对于定义节点将关注图像的哪些区域至关重要。它作为图像生成过程的指南,确保指定的区域根据用户意图得到强调或修改。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- embeds + - 嵌入向量提供了一种将额外上下文和信息纳入图像生成过程的方法。它们可以捕捉到仅凭掩码可能不存在的细微差别和细节,提高了生成图像的整体质量和相关性。 + - Comfy dtype: embeds + - Python dtype: torch.Tensor +- weight + - 权重参数调整掩码和嵌入向量对图像生成的影响。通过调整这个值,用户可以控制掩码和嵌入向量对最终输出的影响程度,从而在期望的视觉元素和自然生成过程之间实现平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight_type + - 权重类型参数决定了如何将权重应用于掩码和嵌入向量。每种类型提供了一种不同的方法来混合用户输入和生成模型的输出,影响最终图像的风格和外观。 + - Comfy dtype: COMBO[original, linear, channel penalty] + - Python dtype: str +- start_at + - start_at 参数定义了掩码对图像影响的开始位置。它有助于控制掩码影响的空间分布,确保准确定位到目标区域。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_at + - end_at 参数指定了掩码对图像影响的结束位置。它与 start_at 配合使用,定义了掩码影响的应用范围,允许对生成图像的区域条件化进行精确控制。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- unfold_batch + - unfold_batch 参数允许在应用掩码和嵌入向量时操纵批次维度。这对于高效处理大量图像批次非常有用,优化了节点的性能和吞吐量。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- REGIONAL_IPADAPTER + - RegionalIPAdapterEncodedMask 节点的输出是一个根据输入掩码、嵌入向量和其他参数修改过的条件化图像适配器。这个输出可以用作进一步图像生成或操作任务的构建块,无缝集成到创作工作流程中。 + - Comfy dtype: REGIONAL_IPADAPTER + - Python dtype: IPAdapterConditioning + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RegionalIPAdapterEncodedMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'embeds': ('embeds',), 'weight': ('FLOAT', {'default': 0.7, 'min': -1, 'max': 3, 'step': 0.05}), 'weight_type': (['original', 'linear', 'channel penalty'],), 'start_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_at': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'unfold_batch': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('REGIONAL_IPADAPTER',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Regional' + + def doit(self, mask, embeds, weight, weight_type, start_at=0.0, end_at=1.0, unfold_batch=False): + cond = IPAdapterConditioning(mask, weight, weight_type, embeds=embeds, start_at=start_at, end_at=end_at, unfold_batch=unfold_batch) + return (cond,) +``` \ No newline at end of file diff --git a/docs/RegionalIPAdapterMask %2F%2FInspire.md b/docs/RegionalIPAdapterMask %2F%2FInspire.md new file mode 100644 index 0000000..1a8a138 --- /dev/null +++ b/docs/RegionalIPAdapterMask %2F%2FInspire.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: RegionalIPAdapterMask +- Category: InspirePack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +RegionalIPAdapterMask节点旨在通过应用掩码和各种条件参数来适应和处理区域性图像数据。它便于对特定区域的图像效果进行修改,而无需改变整个数据集,增强了对图像转换和适应的控制。 + +# Input types +## Required +- mask + - 掩码参数对于定义节点将关注图像的区域至关重要。它决定了哪些部分的图像会受到节点处理的影响,使得针对性的修改和增强成为可能。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- image + - 图像参数是必需的,因为它提供了节点操作的基础输入。它是节点将要处理的原始数据,根据掩码和其他参数应用区域性适应和增强。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +- weight + - 权重参数影响节点处理的强度。它调整区域适应应用到图像的强度,允许根据期望的效果对输出进行微调。 + - Comfy dtype: FLOAT + - Python dtype: float +- noise + - 噪声是一个重要的参数,它为节点处理引入了可变性。它为区域适应添加了一定程度的随机性,这有助于创建更自然或多样化的输出变化。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight_type + - 权重类型参数决定了如何将权重应用于图像。它可以是原始的、线性的或通道惩罚的,每种方法都会影响权重在图像中的分布和影响,从而改变最终结果。 + - Comfy dtype: COMBO + - Python dtype: str +- start_at + - start_at定义了节点处理的范围开始。它是一个浮点值,设置了权重应用的起始点,允许在区域适应中进行受控的过渡。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_at + - end_at标记了节点处理范围的结束。与start_at类似,它是一个浮点值,规定了权重应用的终点,确保区域适应中有平滑而渐进的过渡。 + - Comfy dtype: FLOAT + - Python dtype: float +- unfold_batch + - 展开批次,启用时,会改变节点处理图像数据的方式。它可以提高节点操作的效率,特别是在处理大量图像批次时。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- faceid_v2 + - 当启用faceid_v2参数时,节点内激活额外的面部识别功能。这可以增强节点处理和适应图像中特定面部区域的能力。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- weight_v2 + - weight_v2是一个高级参数,允许进一步定制权重应用。它提供了一个额外的控制层,用于微调区域适应。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output + - RegionalIPAdapterMask节点的输出是经过适应的图像,它根据输入参数进行了区域处理。这个输出准备好了供进一步使用或分析,区域适应和增强已经完全集成到最终结果中。 + - Comfy dtype: REGIONAL_IPADAPTER + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RegionalIPAdapterMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'image': ('IMAGE',), 'weight': ('FLOAT', {'default': 0.7, 'min': -1, 'max': 3, 'step': 0.05}), 'noise': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'weight_type': (['original', 'linear', 'channel penalty'],), 'start_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_at': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'unfold_batch': ('BOOLEAN', {'default': False})}, 'optional': {'faceid_v2': ('BOOLEAN', {'default': False}), 'weight_v2': ('FLOAT', {'default': 1.0, 'min': -1, 'max': 3, 'step': 0.05})}} + RETURN_TYPES = ('REGIONAL_IPADAPTER',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Regional' + + def doit(self, mask, image, weight, noise, weight_type, start_at=0.0, end_at=1.0, unfold_batch=False, faceid_v2=False, weight_v2=False): + cond = IPAdapterConditioning(mask, weight, weight_type, noise=noise, image=image, start_at=start_at, end_at=end_at, unfold_batch=unfold_batch, faceid_v2=faceid_v2, weight_v2=weight_v2) + return (cond,) +``` \ No newline at end of file diff --git a/docs/RegionalPrompt.md b/docs/RegionalPrompt.md new file mode 100644 index 0000000..4649aaa --- /dev/null +++ b/docs/RegionalPrompt.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: RegionalPrompt +- Category: ImpactPack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +RegionalPrompt节点旨在生成特定于区域的提示,使用掩码来定义兴趣区域,并使用高级采样器来确定该区域内的点。它在将处理重点放在图像的特定区域,提高后续操作的精度方面发挥着关键作用。 + +# Input types +## Required +- mask + - 掩码参数对于定义图像内的兴趣区域至关重要。它作为一个过滤器,隔离节点将处理的特定区域,显著影响区域提示生成的结果。 + - Comfy dtype: MASK + - Python dtype: np.ndarray +- advanced_sampler + - 高级采样器参数是确定定义区域内采样策略的关键组件。它影响在掩码内如何选择点,这对于区域提示的准确性和代表性至关重要。 + - Comfy dtype: KSAMPLER_ADVANCED + - Python dtype: KSamplerAdvancedWrapper + +# Output types +- REGIONAL_PROMPTS + - RegionalPrompt节点的输出是一组针对输入掩码和采样器定制的区域提示。这些提示对于指导特定于兴趣区域的进一步分析或处理具有重要意义。 + - Comfy dtype: REGIONAL_PROMPTS + - Python dtype: List[REGIONAL_PROMPT] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RegionalPrompt: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'advanced_sampler': ('KSAMPLER_ADVANCED',)}} + RETURN_TYPES = ('REGIONAL_PROMPTS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Regional' + + def doit(self, mask, advanced_sampler): + regional_prompt = core.REGIONAL_PROMPT(mask, advanced_sampler) + return ([regional_prompt],) +``` \ No newline at end of file diff --git a/docs/RegionalPromptColorMask %2F%2FInspire.md b/docs/RegionalPromptColorMask %2F%2FInspire.md new file mode 100644 index 0000000..9b611ab --- /dev/null +++ b/docs/RegionalPromptColorMask %2F%2FInspire.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: RegionalPromptColorMask +- Category: InspirePack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +RegionalPromptColorMask节点旨在基于颜色输入生成区域提示和掩码,然后利用这些提示和掩码来完善图像中特定区域的细节。该节点通过应用区域掩码来增强图像,允许在指定的颜色区域内进行有针对性的细节和清晰度改进。 + +# Input types +## Required +- basic_pipe + - basic_pipe参数对于节点至关重要,它携带了图像处理所需的必要组件,包括模型、剪辑、VAE和条件信息。它是区域细化过程的基础。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[model, clip, vae, positive, negative] +- color_mask + - color_mask输入是提供视觉上下文的关键元素,节点用它来识别需要增强的颜色区域。它被用来生成一个针对这些特定区域进行处理的掩码。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask_color + - mask_color参数是一个字符串,表示RGB掩码的颜色值。它非常重要,因为它决定了图像中哪些颜色区域将被定位为细化目标。 + - Comfy dtype: STRING + - Python dtype: str +- cfg + - cfg参数是一个浮点值,用于调整节点的配置设置,影响区域细化的强度和焦点。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name输入指定要使用的采样方法,这对于确定区域采样过程的策略和效率至关重要。 + - Comfy dtype: SAMPLERS + - Python dtype: str +- scheduler + - scheduler参数定义了节点的调度策略,这对于管理迭代过程并取得最佳结果至关重要。 + - Comfy dtype: SCHEDULERS + - Python dtype: str +## Optional +- wildcard_prompt + - wildcard_prompt是一个动态文本输入,允许将变量元素纳入提示中,增强了区域细化过程的灵活性和适应性。 + - Comfy dtype: STRING + - Python dtype: str +- controlnet_in_pipe + - controlnet_in_pipe参数是一个布尔标志,用于确定是保持还是覆盖basic_pipe中现有的控制设置,影响对区域细化的整体控制。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- sigma_factor + - sigma_factor是一个浮点值,用于调整区域采样过程中的去噪水平,影响最终输出的质量和细节。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- REGIONAL_PROMPTS + - 输出的REGIONAL_PROMPTS是一组针对指定颜色区域的提示,旨在根据输入参数细化和增强图像。 + - Comfy dtype: REGIONAL_PROMPTS + - Python dtype: Dict[str, Any] +- MASK + - MASK输出是根据输入的color_mask和mask_color生成的二进制掩码,用于隔离和针对图像中的特定区域进行处理。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RegionalPromptColorMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'basic_pipe': ('BASIC_PIPE',), 'color_mask': ('IMAGE',), 'mask_color': ('STRING', {'multiline': False, 'default': '#FFFFFF'}), 'cfg': ('FLOAT', {'default': 8.0, 'min': 0.0, 'max': 100.0}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'wildcard_prompt': ('STRING', {'multiline': True, 'dynamicPrompts': False, 'placeholder': 'wildcard prompt'}), 'controlnet_in_pipe': ('BOOLEAN', {'default': False, 'label_on': 'Keep', 'label_off': 'Override'}), 'sigma_factor': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01})}} + RETURN_TYPES = ('REGIONAL_PROMPTS', 'MASK') + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Regional' + + def doit(self, basic_pipe, color_mask, mask_color, cfg, sampler_name, scheduler, wildcard_prompt, controlnet_in_pipe=False, sigma_factor=1.0): + mask = color_to_mask(color_mask, mask_color) + rp = RegionalPromptSimple().doit(basic_pipe, mask, cfg, sampler_name, scheduler, wildcard_prompt, controlnet_in_pipe, sigma_factor=sigma_factor)[0] + return (rp, mask) +``` \ No newline at end of file diff --git a/docs/RegionalPromptSimple %2F%2FInspire.md b/docs/RegionalPromptSimple %2F%2FInspire.md new file mode 100644 index 0000000..22d8d37 --- /dev/null +++ b/docs/RegionalPromptSimple %2F%2FInspire.md @@ -0,0 +1,91 @@ +# Documentation +- Class name: RegionalPromptSimple +- Category: InspirePack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +RegionalPromptSimple节点旨在通过区域化的方法来增强图像合成过程。它利用遮罩对图像的特定区域进行聚焦,允许对采样过程进行详细控制。该节点通过确保所需区域得到适当的关注,从而提高整体图像质量,导致更精细和针对性的输出。 + +# Input types +## Required +- basic_pipe + - basic_pipe参数对于区域提示过程至关重要,它提供了合成图像所需的基础元素。它包括模型、clip、vae以及其他必要的组件。这些元素对于最终输出的质量和准确性有着直接影响。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple +- mask + - mask参数对于定义图像内的兴趣区域至关重要。它作为节点的指南,引导其处理工作的重点,确保指定的区域以更高的细节和清晰度得到增强。遮罩的有效性直接与所需图像增强的精确性相关。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- cfg + - cfg参数是一个浮点值,用于调整节点的配置设置,影响区域提示过程的整体行为。它在确定细节和效率之间的平衡方面起着重要作用,确保节点为期望的结果最佳化运行。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数决定了节点采用的采样策略,这对合成图像的质量至关重要。通过选择合适的采样器,节点可以调整其输出以满足手头任务的具体要求,从而实现更准确和有针对性的增强。 + - Comfy dtype: SAMPLERS + - Python dtype: str +- scheduler + - scheduler参数在管理节点的迭代过程中起着重要作用,确保区域提示以受控和高效的方式执行。它有助于优化采样过程,避免不必要的计算开销,专注于最有影响力的步骤。 + - Comfy dtype: SCHEDULERS + - Python dtype: str +## Optional +- wildcard_prompt + - wildcard_prompt参数允许动态输入文本,可用于自定义节点的提示。这一特性增强了节点的灵活性,使其能够适应各种图像合成场景,并产生更加定制化的结果。 + - Comfy dtype: STRING + - Python dtype: str +- controlnet_in_pipe + - controlnet_in_pipe参数决定是否保持或覆盖管道中的现有控制设置。这允许对节点的行为进行微调,确保区域提示与期望的创意方向保持一致。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- sigma_factor + - sigma_factor参数调整图像合成过程中应用的降噪水平。通过调整这个值,节点可以在保留细节和减少不需要的噪声之间取得平衡,从而得到更清洁、更精细的图像输出。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- regional_prompts + - regional_prompts输出是针对图像指定区域量身定制的一系列提示。这些提示旨在通过聚焦兴趣区域来增强图像合成过程,从而得到更详细、更准确的期望结果表示。 + - Comfy dtype: REGIONAL_PROMPTS + - Python dtype: List[Dict[str, Any]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RegionalPromptSimple: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'basic_pipe': ('BASIC_PIPE',), 'mask': ('MASK',), 'cfg': ('FLOAT', {'default': 8.0, 'min': 0.0, 'max': 100.0}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'wildcard_prompt': ('STRING', {'multiline': True, 'dynamicPrompts': False, 'placeholder': 'wildcard prompt'}), 'controlnet_in_pipe': ('BOOLEAN', {'default': False, 'label_on': 'Keep', 'label_off': 'Override'}), 'sigma_factor': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01})}} + RETURN_TYPES = ('REGIONAL_PROMPTS',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Regional' + + def doit(self, basic_pipe, mask, cfg, sampler_name, scheduler, wildcard_prompt, controlnet_in_pipe=False, sigma_factor=1.0): + if 'RegionalPrompt' not in nodes.NODE_CLASS_MAPPINGS: + utils.try_install_custom_node('https://github.com/ltdrdata/ComfyUI-Impact-Pack', "To use 'RegionalPromptSimple' node, 'Impact Pack' extension is required.") + raise Exception(f"[ERROR] To use RegionalPromptSimple, you need to install 'ComfyUI-Impact-Pack'") + (model, clip, vae, positive, negative) = basic_pipe + iwe = nodes.NODE_CLASS_MAPPINGS['ImpactWildcardEncode']() + kap = nodes.NODE_CLASS_MAPPINGS['KSamplerAdvancedProvider']() + rp = nodes.NODE_CLASS_MAPPINGS['RegionalPrompt']() + if wildcard_prompt != '': + (model, clip, new_positive, _) = iwe.doit(model=model, clip=clip, populated_text=wildcard_prompt) + if controlnet_in_pipe: + prev_cnet = None + for t in positive: + if 'control' in t[1] and 'control_apply_to_uncond' in t[1]: + prev_cnet = (t[1]['control'], t[1]['control_apply_to_uncond']) + break + if prev_cnet is not None: + for t in new_positive: + t[1]['control'] = prev_cnet[0] + t[1]['control_apply_to_uncond'] = prev_cnet[1] + else: + new_positive = positive + basic_pipe = (model, clip, vae, new_positive, negative) + sampler = kap.doit(cfg, sampler_name, scheduler, basic_pipe, sigma_factor=sigma_factor)[0] + regional_prompts = rp.doit(mask, sampler)[0] + return (regional_prompts,) +``` \ No newline at end of file diff --git a/docs/RegionalSampler.md b/docs/RegionalSampler.md new file mode 100644 index 0000000..70250c2 --- /dev/null +++ b/docs/RegionalSampler.md @@ -0,0 +1,128 @@ +# Documentation +- Class name: RegionalSampler +- Category: ImpactPack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +RegionalSampler节点旨在对图像的特定区域执行高级采样技术,允许对生成过程进行细粒度控制。它使用户能够对图像的不同区域应用不同的采样策略,提高生成输出的整体质量和一致性。 + +# Input types +## Required +- seed + - 种子参数对于随机数生成过程的初始化至关重要,确保了采样结果的可复现性。它在确定采样算法的起始点中起着重要作用,从而影响最终输出。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步骤参数定义了采样过程将经历的迭代次数。它是控制生成图像的收敛和细节级别的关键因素,更多的步骤通常会导致更精细的结果。 + - Comfy dtype: INT + - Python dtype: int +- regional_prompts + - 区域提示对于指导图像特定区域内的采样过程至关重要。它们作为掩码来隔离不同的区域,允许有针对性的采样,并增强最终输出的区域细节。 + - Comfy dtype: REGIONAL_PROMPTS + - Python dtype: List[RegionalPrompt] + +# Output types +- latent + - 潜在参数代表采样过程后生成图像的编码形式。它很重要,因为它捕获了图像的底层结构和信息,可以进一步处理或用于其他任务。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RegionalSampler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'seed_2nd': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'seed_2nd_mode': (['ignore', 'fixed', 'seed+seed_2nd', 'seed-seed_2nd', 'increment', 'decrement', 'randomize'],), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'base_only_steps': ('INT', {'default': 2, 'min': 0, 'max': 10000}), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'samples': ('LATENT',), 'base_sampler': ('KSAMPLER_ADVANCED',), 'regional_prompts': ('REGIONAL_PROMPTS',), 'overlap_factor': ('INT', {'default': 10, 'min': 0, 'max': 10000}), 'restore_latent': ('BOOLEAN', {'default': True, 'label_on': 'enabled', 'label_off': 'disabled'}), 'additional_mode': (['DISABLE', 'ratio additional', 'ratio between'], {'default': 'ratio between'}), 'additional_sampler': (['AUTO', 'euler', 'heun', 'heunpp2', 'dpm_2', 'dpm_fast', 'dpmpp_2m', 'ddpm'],), 'additional_sigma_ratio': ('FLOAT', {'default': 0.3, 'min': 0.0, 'max': 1.0, 'step': 0.01})}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Regional' + + @staticmethod + def mask_erosion(samples, mask, grow_mask_by): + mask = mask.clone() + w = samples['samples'].shape[3] + h = samples['samples'].shape[2] + mask2 = torch.nn.functional.interpolate(mask.reshape((-1, 1, mask.shape[-2], mask.shape[-1])), size=(w, h), mode='bilinear') + if grow_mask_by == 0: + mask_erosion = mask2 + else: + kernel_tensor = torch.ones((1, 1, grow_mask_by, grow_mask_by)) + padding = math.ceil((grow_mask_by - 1) / 2) + mask_erosion = torch.clamp(torch.nn.functional.conv2d(mask2.round(), kernel_tensor, padding=padding), 0, 1) + return mask_erosion[:, :, :w, :h].round() + + def doit(self, seed, seed_2nd, seed_2nd_mode, steps, base_only_steps, denoise, samples, base_sampler, regional_prompts, overlap_factor, restore_latent, additional_mode, additional_sampler, additional_sigma_ratio, unique_id=None): + if restore_latent: + latent_compositor = nodes.NODE_CLASS_MAPPINGS['LatentCompositeMasked']() + else: + latent_compositor = None + masks = [regional_prompt.mask.numpy() for regional_prompt in regional_prompts] + masks = [np.ceil(mask).astype(np.int32) for mask in masks] + combined_mask = torch.from_numpy(np.bitwise_or.reduce(masks)) + inv_mask = torch.where(combined_mask == 0, torch.tensor(1.0), torch.tensor(0.0)) + adv_steps = int(steps / denoise) + start_at_step = adv_steps - steps + region_len = len(regional_prompts) + total = steps * region_len + leftover_noise = False + if base_only_steps > 0: + if seed_2nd_mode == 'ignore': + leftover_noise = True + samples = base_sampler.sample_advanced(True, seed, adv_steps, samples, start_at_step, start_at_step + base_only_steps, leftover_noise, recovery_mode='DISABLE') + if seed_2nd_mode == 'seed+seed_2nd': + seed += seed_2nd + if seed > 1125899906842624: + seed = seed - 1125899906842624 + elif seed_2nd_mode == 'seed-seed_2nd': + seed -= seed_2nd + if seed < 0: + seed += 1125899906842624 + elif seed_2nd_mode != 'ignore': + seed = seed_2nd + new_latent_image = samples.copy() + base_latent_image = None + if not leftover_noise: + add_noise = True + else: + add_noise = False + for i in range(start_at_step + base_only_steps, adv_steps): + core.update_node_status(unique_id, f'{i}/{steps} steps | ', (i - start_at_step) * region_len / total) + new_latent_image['noise_mask'] = inv_mask + new_latent_image = base_sampler.sample_advanced(add_noise, seed, adv_steps, new_latent_image, i, i + 1, True, recovery_mode=additional_mode, recovery_sampler=additional_sampler, recovery_sigma_ratio=additional_sigma_ratio) + if restore_latent: + if 'noise_mask' in new_latent_image: + del new_latent_image['noise_mask'] + base_latent_image = new_latent_image.copy() + j = 1 + for regional_prompt in regional_prompts: + if restore_latent: + new_latent_image = base_latent_image.copy() + core.update_node_status(unique_id, f'{i}/{steps} steps | {j}/{region_len}', ((i - start_at_step) * region_len + j) / total) + region_mask = regional_prompt.get_mask_erosion(overlap_factor).squeeze(0).squeeze(0) + new_latent_image['noise_mask'] = region_mask + new_latent_image = regional_prompt.sampler.sample_advanced(False, seed, adv_steps, new_latent_image, i, i + 1, True, recovery_mode=additional_mode, recovery_sampler=additional_sampler, recovery_sigma_ratio=additional_sigma_ratio) + if restore_latent: + del new_latent_image['noise_mask'] + base_latent_image = latent_compositor.composite(base_latent_image, new_latent_image, 0, 0, False, region_mask)[0] + new_latent_image = base_latent_image + j += 1 + add_noise = False + core.update_node_status(unique_id, f'finalize') + if base_latent_image is not None: + new_latent_image = base_latent_image + else: + base_latent_image = new_latent_image + new_latent_image['noise_mask'] = inv_mask + new_latent_image = base_sampler.sample_advanced(False, seed, adv_steps, new_latent_image, adv_steps, adv_steps + 1, False, recovery_mode=additional_mode, recovery_sampler=additional_sampler, recovery_sigma_ratio=additional_sigma_ratio) + core.update_node_status(unique_id, f'{steps}/{steps} steps', total) + core.update_node_status(unique_id, '', None) + if restore_latent: + new_latent_image = base_latent_image + if 'noise_mask' in new_latent_image: + del new_latent_image['noise_mask'] + return (new_latent_image,) +``` \ No newline at end of file diff --git a/docs/RegionalSamplerAdvanced.md b/docs/RegionalSamplerAdvanced.md new file mode 100644 index 0000000..2e6448e --- /dev/null +++ b/docs/RegionalSamplerAdvanced.md @@ -0,0 +1,147 @@ +# Documentation +- Class name: RegionalSamplerAdvanced +- Category: ImpactPack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +RegionalSamplerAdvanced 节点旨在对潜在图像的特定区域执行高级采样操作。它允许自定义采样步骤、噪声添加和恢复定义区域内的潜在状态,为局部图像生成的采样过程提供了高度的控制能力。 + +# Input types +## Required +- add_noise + - 'add_noise' 参数决定在采样过程中是否向潜在图像添加噪声。这可以影响生成图像的质量和随机性,是实现所需视觉效果的关键因素。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- noise_seed + - 'noise_seed' 参数用于初始化添加噪声的随机数生成器,确保采样过程的可重复性。它的值直接影响引入潜在图像中的噪声模式。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 'steps' 参数指定要执行的采样步骤数。它是最终图像细节和分辨率的关键决定因素,更多的步骤通常会导致更精细的结果。 + - Comfy dtype: INT + - Python dtype: int +- start_at_step + - 'start_at_step' 参数定义了采样过程开始的步骤,允许自定义采样时间线,并使用户能够控制图像生成的进展。 + - Comfy dtype: INT + - Python dtype: int +- end_at_step + - 'end_at_step' 参数设置了采样过程结束的步骤。它与 'start_at_step' 配合使用,定义了执行采样的步骤范围,影响采样过程的总持续时间。 + - Comfy dtype: INT + - Python dtype: int +- overlap_factor + - 'overlap_factor' 参数控制采样过程中区域掩模之间的重叠程度。它对于确保采样区域的无缝集成至关重要,在图像的最终构图中扮演着重要角色。 + - Comfy dtype: INT + - Python dtype: int +- restore_latent + - 'restore_latent' 参数指示在每个区域采样后是否应恢复潜在状态。这有助于在多个采样操作重叠的区域中保持图像的完整性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- return_with_leftover_noise + - 'return_with_leftover_noise' 参数决定采样过程后最终潜在图像是否保留任何残余噪声。这对于进一步处理或分析噪声特性非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- latent_image + - 'latent_image' 参数表示要采样的图像的初始潜在状态。它是采样过程的起点,对生成最终图像至关重要。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- base_sampler + - 'base_sampler' 参数定义了要用于潜在图像的基本采样方法。它是确定图像生成算法方法的关键组成部分,并影响输出的整体风格和质量。 + - Comfy dtype: KSAMPLER_ADVANCED + - Python dtype: KSamplerAdvancedWrapper +- regional_prompts + - 'regional_prompts' 参数包含定义采样感兴趣区域的提示集合。每个提示都可以影响其指定区域内的采样过程,允许对局部图像特征进行详细控制。 + - Comfy dtype: REGIONAL_PROMPTS + - Python dtype: List[Any] +- additional_mode + - 'additional_mode' 参数指定了采样过程中要应用的恢复模式。它决定了额外采样如何与基本采样集成,影响最终图像的连贯性和细节。 + - Comfy dtype: COMBO['DISABLE', 'ratio additional', 'ratio between'] + - Python dtype: str +- additional_sampler + - 'additional_sampler' 参数选择用于额外采样任务的采样器类型。在采样过程中恢复和细化图像细节的重要因素。 + - Comfy dtype: COMBO['AUTO', 'euler', 'heun', 'heunpp2', 'dpm_2', 'dpm_fast', 'dpmpp_2m', 'ddpm'] + - Python dtype: str +- additional_sigma_ratio + - 'additional_sigma_ratio' 参数调整用于额外采样的 sigma 比例,允许微调噪声水平及其对图像生成过程的影响。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- unique_id + - 'unique_id' 参数在执行过程中用于内部唯一标识节点。它在跟踪和管理节点状态中起着关键作用,确保系统内准确报告和协调。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- latent_image + - 'latent_image' 输出代表应用 RegionalSamplerAdvanced 节点操作后最终采样的潜在图像。它封装了高级采样过程的结果,反映了执行期间进行的定制噪声、步骤和区域调整。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RegionalSamplerAdvanced: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'add_noise': ('BOOLEAN', {'default': True, 'label_on': 'enabled', 'label_off': 'disabled'}), 'noise_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'start_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'end_at_step': ('INT', {'default': 10000, 'min': 0, 'max': 10000}), 'overlap_factor': ('INT', {'default': 10, 'min': 0, 'max': 10000}), 'restore_latent': ('BOOLEAN', {'default': True, 'label_on': 'enabled', 'label_off': 'disabled'}), 'return_with_leftover_noise': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'}), 'latent_image': ('LATENT',), 'base_sampler': ('KSAMPLER_ADVANCED',), 'regional_prompts': ('REGIONAL_PROMPTS',), 'additional_mode': (['DISABLE', 'ratio additional', 'ratio between'], {'default': 'ratio between'}), 'additional_sampler': (['AUTO', 'euler', 'heun', 'heunpp2', 'dpm_2', 'dpm_fast', 'dpmpp_2m', 'ddpm'],), 'additional_sigma_ratio': ('FLOAT', {'default': 0.3, 'min': 0.0, 'max': 1.0, 'step': 0.01})}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Regional' + + def doit(self, add_noise, noise_seed, steps, start_at_step, end_at_step, overlap_factor, restore_latent, return_with_leftover_noise, latent_image, base_sampler, regional_prompts, additional_mode, additional_sampler, additional_sigma_ratio, unique_id): + if restore_latent: + latent_compositor = nodes.NODE_CLASS_MAPPINGS['LatentCompositeMasked']() + else: + latent_compositor = None + masks = [regional_prompt.mask.numpy() for regional_prompt in regional_prompts] + masks = [np.ceil(mask).astype(np.int32) for mask in masks] + combined_mask = torch.from_numpy(np.bitwise_or.reduce(masks)) + inv_mask = torch.where(combined_mask == 0, torch.tensor(1.0), torch.tensor(0.0)) + region_len = len(regional_prompts) + end_at_step = min(steps, end_at_step) + total = (end_at_step - start_at_step) * region_len + new_latent_image = latent_image.copy() + base_latent_image = None + region_masks = {} + for i in range(start_at_step, end_at_step - 1): + core.update_node_status(unique_id, f'{start_at_step + i}/{end_at_step} steps | ', (i - start_at_step) * region_len / total) + cur_add_noise = True if i == start_at_step and add_noise else False + new_latent_image['noise_mask'] = inv_mask + new_latent_image = base_sampler.sample_advanced(cur_add_noise, noise_seed, steps, new_latent_image, i, i + 1, True, recovery_mode=additional_mode, recovery_sampler=additional_sampler, recovery_sigma_ratio=additional_sigma_ratio) + if restore_latent: + del new_latent_image['noise_mask'] + base_latent_image = new_latent_image.copy() + j = 1 + for regional_prompt in regional_prompts: + if restore_latent: + new_latent_image = base_latent_image.copy() + core.update_node_status(unique_id, f'{start_at_step + i}/{end_at_step} steps | {j}/{region_len}', ((i - start_at_step) * region_len + j) / total) + if j not in region_masks: + region_mask = regional_prompt.get_mask_erosion(overlap_factor).squeeze(0).squeeze(0) + region_masks[j] = region_mask + else: + region_mask = region_masks[j] + new_latent_image['noise_mask'] = region_mask + new_latent_image = regional_prompt.sampler.sample_advanced(False, noise_seed, steps, new_latent_image, i, i + 1, True, recovery_mode=additional_mode, recovery_sampler=additional_sampler, recovery_sigma_ratio=additional_sigma_ratio) + if restore_latent: + del new_latent_image['noise_mask'] + base_latent_image = latent_compositor.composite(base_latent_image, new_latent_image, 0, 0, False, region_mask)[0] + new_latent_image = base_latent_image + j += 1 + core.update_node_status(unique_id, f'finalize') + if base_latent_image is not None: + new_latent_image = base_latent_image + else: + base_latent_image = new_latent_image + new_latent_image['noise_mask'] = inv_mask + new_latent_image = base_sampler.sample_advanced(False, noise_seed, steps, new_latent_image, end_at_step - 1, end_at_step, return_with_leftover_noise, recovery_mode=additional_mode, recovery_sampler=additional_sampler, recovery_sigma_ratio=additional_sigma_ratio) + core.update_node_status(unique_id, f'{end_at_step}/{end_at_step} steps', total) + core.update_node_status(unique_id, '', None) + if restore_latent: + new_latent_image = base_latent_image + if 'noise_mask' in new_latent_image: + del new_latent_image['noise_mask'] + return (new_latent_image,) +``` \ No newline at end of file diff --git a/docs/RegionalSeedExplorerColorMask %2F%2FInspire.md b/docs/RegionalSeedExplorerColorMask %2F%2FInspire.md new file mode 100644 index 0000000..60c0ca9 --- /dev/null +++ b/docs/RegionalSeedExplorerColorMask %2F%2FInspire.md @@ -0,0 +1,93 @@ +# Documentation +- Class name: RegionalSeedExplorerColorMask +- Category: InspirePack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点基于颜色掩码和种子提示探索图像区域,能够在指定区域生成变化,控制噪声并增强特定特征。 + +# Input types +## Required +- color_mask + - 颜色掩码至关重要,它定义了图像中将要进行变化和噪声探索的区域。它是节点操作的基础。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +- noise + - 噪声是引入变化的基本输入,它允许产生多样化的结果和更丰富的生成图像集。 + - Comfy dtype: NOISE + - Python dtype: torch.Tensor +- seed_prompt + - 种子提示在指导变化过程中起着重要作用,为节点提供特定方向,以在图像中生成目标变化。 + - Comfy dtype: STRING + - Python dtype: str +- enable_additional + - 该参数决定了是否应用额外的种子提示,从而影响图像变化的复杂性和多样性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- noise_mode + - 噪声模式决定了用于处理噪声的计算资源,GPU为模型密集型任务提供更快的计算,而CPU更适合不那么复杂的操作。 + - Comfy dtype: COMBO[GPU(=A1111), CPU] + - Python dtype: str +## Optional +- mask_color + - 掩码颜色参数对于识别颜色掩码中将用于创建二进制掩码以进行区域选择的特定颜色至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- additional_seed + - 启用时,额外的种子为变化过程提供了另一层控制,允许进一步定制生成的内容。 + - Comfy dtype: INT + - Python dtype: int +- additional_strength + - 该参数调整额外种子的影响,允许用户微调应用于图像的变化的强度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- noise + - 输出噪声代表了经过处理的带有应用变化的噪声,这是生成多样化图像结果的关键组成部分。 + - Comfy dtype: NOISE + - Python dtype: torch.Tensor +- mask + - 掩码输出是选定区域的二进制表示,这对于隔离和应用图像的特定更改至关重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RegionalSeedExplorerColorMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'color_mask': ('IMAGE',), 'mask_color': ('STRING', {'multiline': False, 'default': '#FFFFFF'}), 'noise': ('NOISE',), 'seed_prompt': ('STRING', {'multiline': True, 'dynamicPrompts': False, 'pysssss.autocomplete': False}), 'enable_additional': ('BOOLEAN', {'default': True, 'label_on': 'true', 'label_off': 'false'}), 'additional_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'additional_strength': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'noise_mode': (['GPU(=A1111)', 'CPU'],)}} + RETURN_TYPES = ('NOISE', 'MASK') + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Regional' + + def doit(self, color_mask, mask_color, noise, seed_prompt, enable_additional, additional_seed, additional_strength, noise_mode): + device = comfy.model_management.get_torch_device() + noise_device = 'cpu' if noise_mode == 'CPU' else device + color_mask = color_mask.to(device) + noise = noise.to(device) + mask = color_to_mask(color_mask, mask_color) + original_mask = mask + mask = torch.nn.functional.interpolate(mask.reshape((-1, 1, mask.shape[-2], mask.shape[-1])), size=(noise.shape[2], noise.shape[3]), mode='bilinear').squeeze(0) + mask = mask.to(device) + try: + seed_prompt = seed_prompt.replace('\n', '') + items = seed_prompt.strip().split(',') + if items == ['']: + items = [] + if enable_additional: + items.append((additional_seed, additional_strength)) + noise = prompt_support.SeedExplorer.apply_variation(noise, items, noise_device, mask) + except Exception: + print(f'[ERROR] IGNORED: RegionalSeedExplorerColorMask is failed.') + traceback.print_exc() + color_mask.cpu() + noise = noise.cpu() + original_mask = original_mask.cpu() + return (noise, original_mask) +``` \ No newline at end of file diff --git a/docs/RegionalSeedExplorerMask %2F%2FInspire.md b/docs/RegionalSeedExplorerMask %2F%2FInspire.md new file mode 100644 index 0000000..215c350 --- /dev/null +++ b/docs/RegionalSeedExplorerMask %2F%2FInspire.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: RegionalSeedExplorerMask +- Category: InspirePack/Regional +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +RegionalSeedExplorerMask节点旨在通过基于指定的种子提示和附加参数引入噪声场的变化来增强创作过程。它通过操作噪声生成多样化的视觉元素,这些元素可用于各种艺术和设计应用中。 + +# Input types +## Required +- mask + - 掩码参数至关重要,因为它定义了噪声场中将受到种子探索过程影响的区域。它作为节点的指南,用于理解在哪里应用变化。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- noise + - 噪声参数是节点将要操作的基础噪声场。它对于生成变化的输出至关重要,因为它构成了应用种子探索的基础。 + - Comfy dtype: NOISE + - Python dtype: torch.Tensor +- seed_prompt + - 种子提示是一个包含变化种子的字符串。它是一个关键的输入,因为它直接影响将引入噪声场的变化类型。 + - Comfy dtype: STRING + - Python dtype: str +- enable_additional + - 此参数控制是否使用额外的种子提示。它很重要,因为它决定了应用于噪声场的变化的复杂性和多样性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- noise_mode + - 噪声模式参数决定了用于处理噪声的计算设备。它对于确定变化应用的度和效率很重要。 + - Comfy dtype: COMBO[GPU(=A1111), CPU] + - Python dtype: str +## Optional +- additional_seed + - 附加种子参数在使用时,提供了对变化过程的额外控制级别。它允许根据提供的种子引入更具体的变化。 + - Comfy dtype: INT + - Python dtype: int +- additional_strength + - 附加强度参数调整附加变化的强度。它很重要,因为它允许对噪声场上的变化效果进行微调。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- noise + - 输出噪声是种子探索过程的结果。它代表了应用了变化的噪声场,可以进一步用于下游应用。 + - Comfy dtype: NOISE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RegionalSeedExplorerMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'noise': ('NOISE',), 'seed_prompt': ('STRING', {'multiline': True, 'dynamicPrompts': False, 'pysssss.autocomplete': False}), 'enable_additional': ('BOOLEAN', {'default': True, 'label_on': 'true', 'label_off': 'false'}), 'additional_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'additional_strength': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'noise_mode': (['GPU(=A1111)', 'CPU'],)}} + RETURN_TYPES = ('NOISE',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Regional' + + def doit(self, mask, noise, seed_prompt, enable_additional, additional_seed, additional_strength, noise_mode): + device = comfy.model_management.get_torch_device() + noise_device = 'cpu' if noise_mode == 'CPU' else device + noise = noise.to(device) + mask = mask.to(device) + if len(mask.shape) == 2: + mask = mask.unsqueeze(0) + mask = torch.nn.functional.interpolate(mask.reshape((-1, 1, mask.shape[-2], mask.shape[-1])), size=(noise.shape[2], noise.shape[3]), mode='bilinear').squeeze(0) + try: + seed_prompt = seed_prompt.replace('\n', '') + items = seed_prompt.strip().split(',') + if items == ['']: + items = [] + if enable_additional: + items.append((additional_seed, additional_strength)) + noise = prompt_support.SeedExplorer.apply_variation(noise, items, noise_device, mask) + except Exception: + print(f'[ERROR] IGNORED: RegionalSeedExplorerColorMask is failed.') + traceback.print_exc() + noise = noise.cpu() + mask.cpu() + return (noise,) +``` \ No newline at end of file diff --git a/docs/RemBGSession+.md b/docs/RemBGSession+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/RemoveBackendData %2F%2FInspire.md b/docs/RemoveBackendData %2F%2FInspire.md new file mode 100644 index 0000000..c44f622 --- /dev/null +++ b/docs/RemoveBackendData %2F%2FInspire.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: RemoveBackendData +- Category: InspirePack/Backend +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在管理和清除存储在后端缓存中的数据,确保系统内高效的内存使用和数据组织。 + +# Input types +## Required +- key + - ‘key’参数对于识别后端缓存中的具体数据至关重要。它决定了哪些数据被指定删除,通配符‘*’用于清除整个缓存。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- signal_opt + - ‘signal_opt’参数是一个可选输入,可用于提供额外的指令或信号给节点,增强其在各种场景中的适应性和灵活性。 + - Comfy dtype: ANY + - Python dtype: Any + +# Output types +- signal + - ‘signal’输出表示数据删除操作的结果,可能是状态指示或对‘signal_opt’输入的响应,确保节点与系统之间的有效通信。 + - Comfy dtype: ANY + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RemoveBackendData: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'key': ('STRING', {'multiline': False, 'placeholder': "Input data key ('*' = clear all)"})}, 'optional': {'signal_opt': (any_typ,)}} + RETURN_TYPES = (any_typ,) + RETURN_NAMES = ('signal',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Backend' + OUTPUT_NODE = True + + def doit(self, key, signal_opt=None): + global cache + if key == '*': + cache = {} + elif key in cache: + del cache[key] + else: + print(f'[Inspire Pack] RemoveBackendData: invalid data key {key}') + return (signal_opt,) +``` \ No newline at end of file diff --git a/docs/RemoveBackendDataNumberKey %2F%2FInspire.md b/docs/RemoveBackendDataNumberKey %2F%2FInspire.md new file mode 100644 index 0000000..501dd8c --- /dev/null +++ b/docs/RemoveBackendDataNumberKey %2F%2FInspire.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: RemoveBackendDataNumberKey +- Category: DataProcessing +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在从后端缓存中删除与特定数字键关联的数据条目,确保数据完整性并优化存储空间。 + +# Input types +## Required +- key + - ‘key’参数对于识别要从缓存中删除的确切数据条目至关重要。它作为目标数据的唯一标识符。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- signal_opt + - ‘signal_opt’参数在删除过程中提供了灵活性,允许为操作指定额外的选项。 + - Comfy dtype: ANY + - Python dtype: Any + +# Output types +- signal_opt + - ‘signal_opt’输出反映了作为输入提供的任何额外选项或信号,保持操作上下文的完整性。 + - Comfy dtype: ANY + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RemoveBackendDataNumberKey(RemoveBackendData): + + @classmethod + def INPUT_TYPES(s): + return {'required': {'key': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'optional': {'signal_opt': (any_typ,)}} + + def doit(self, key, signal_opt=None): + global cache + if key in cache: + del cache[key] + else: + print(f'[Inspire Pack] RemoveBackendDataNumberKey: invalid data key {key}') + return (signal_opt,) +``` \ No newline at end of file diff --git a/docs/RemoveControlNet %2F%2FInspire.md b/docs/RemoveControlNet %2F%2FInspire.md new file mode 100644 index 0000000..a5af48e --- /dev/null +++ b/docs/RemoveControlNet %2F%2FInspire.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: RemoveControlNet +- Category: InspirePack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在通过移除与控制相关的元素来处理和精炼输入数据,从而提高数据集的清晰度和专注度。 + +# Input types +## Required +- conditioning + - 调节参数至关重要,因为它是节点操作的主要输入。它包含将被处理以实现期望结果的数据。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, dict]] + +# Output types +- conditioning + - 输出是输入数据的精炼版本,去除了控制元素,这对于进一步的分析或处理至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, dict]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RemoveControlNet: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'conditioning': ('CONDITIONING',)}} + RETURN_TYPES = ('CONDITIONING',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Util' + + def doit(self, conditioning): + c = [] + for t in conditioning: + n = [t[0], t[1].copy()] + if 'control' in n[1]: + del n[1]['control'] + if 'control_apply_to_uncond' in n[1]: + del n[1]['control_apply_to_uncond'] + c.append(n) + return (c,) +``` \ No newline at end of file diff --git a/docs/RemoveControlNetFromRegionalPrompts %2F%2FInspire.md b/docs/RemoveControlNetFromRegionalPrompts %2F%2FInspire.md new file mode 100644 index 0000000..6d82ca6 --- /dev/null +++ b/docs/RemoveControlNetFromRegionalPrompts %2F%2FInspire.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: RemoveControlNetFromRegionalPrompts +- Category: InspirePack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在通过移除控制元素来处理和完善区域性提示,从而提高后续任务中提示的清晰度和专注度。 + +# Input types +## Required +- regional_prompts + - 区域性提示是指导节点操作的关键输入,作为移除控制元素的基础。 + - Comfy dtype: REGIONAL_PROMPTS + - Python dtype: List[Tuple[str, str, str, str, List[str], List[str]]] + +# Output types +- REGIONAL_PROMPTS + - 经过精炼且不包含控制元素的提示是主要的输出,可以用于进一步的处理或分析。 + - Comfy dtype: REGIONAL_PROMPTS + - Python dtype: List[Tuple[str, str, str, str, List[str], List[str]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RemoveControlNetFromRegionalPrompts: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'regional_prompts': ('REGIONAL_PROMPTS',)}} + RETURN_TYPES = ('REGIONAL_PROMPTS',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Util' + + def doit(self, regional_prompts): + rcn = RemoveControlNet() + res = [] + for rp in regional_prompts: + (_, _, _, _, positive, negative) = rp.sampler.params + (positive, negative) = (rcn.doit(positive)[0], rcn.doit(negative)[0]) + sampler = rp.sampler.clone_with_conditionings(positive, negative) + res.append(rp.clone_with_sampler(sampler)) + return (res,) +``` \ No newline at end of file diff --git a/docs/RemoveImageFromSEGS.md b/docs/RemoveImageFromSEGS.md new file mode 100644 index 0000000..7d5cd45 --- /dev/null +++ b/docs/RemoveImageFromSEGS.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: RemoveImageFromSEGS +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +‘RemoveImageFromSEGS’节点旨在通过移除‘SEGS’对象中的原始图像组件来处理分割数据。它专注于保留诸如裁剪后的掩码、置信度、裁剪区域、边界框、标签和控制网包装器等基本属性,从而允许有一个不包含图像本身的分割数据的简化版本。 + +# Input types +## Required +- segs + - ‘segs’参数是节点的重要输入,因为它代表了需要处理的分割数据。节点在此数据上操作以创建没有原始图像的‘SEGS’对象的新版本,这对于只需要分割属性的某些应用来说是必要的。 + - Comfy dtype: SEGS + - Python dtype: Tuple[SEG, List[SEG]] + +# Output types +- result + - ‘result’输出包含已处理过的‘SEGS’对象,其中已移除原始图像。这个输出很重要,因为它为用户提供了一个去除了不必要图像数据的修改后的分割数据集,可以用于进一步的分析或处理。 + - Comfy dtype: SEGS + - Python dtype: Tuple[SEG, List[SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RemoveImageFromSEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, segs): + results = [] + if len(segs[1]) > 0: + for seg in segs[1]: + new_seg = SEG(None, seg.cropped_mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, seg.control_net_wrapper) + results.append(new_seg) + return ((segs[0], results),) + else: + return (segs,) +``` \ No newline at end of file diff --git a/docs/RemoveLatentMask+.md b/docs/RemoveLatentMask+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/RemoveNoiseMask.md b/docs/RemoveNoiseMask.md new file mode 100644 index 0000000..21c082b --- /dev/null +++ b/docs/RemoveNoiseMask.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: RemoveNoiseMask +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +该节点旨在通过从输入样本中移除不需要的噪声来处理和优化数据,确保后续的分析或处理步骤基于更干净、更可靠的信息。 + +# Input types +## Required +- samples + - “samples”参数是节点的关键输入,因为它包含了将被处理的数据。节点的功能集中在从这些样本中识别并移除噪声,以提高数据的质量。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Output types +- res + - “res”输出是节点操作的结果,包含去噪后的样本。它代表了可以用于进一步处理或分析的精炼数据。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RemoveNoiseMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'samples': ('LATENT',)}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, samples): + res = {key: value for (key, value) in samples.items() if key != 'noise_mask'} + return (res,) +``` \ No newline at end of file diff --git a/docs/RescaleClassifierFreeGuidanceTest.md b/docs/RescaleClassifierFreeGuidanceTest.md new file mode 100644 index 0000000..5d303ab --- /dev/null +++ b/docs/RescaleClassifierFreeGuidanceTest.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: RescaleClassifierFreeGuidance +- Category: custom_node_experiments +- Output node: False +- Repo Ref: https://github.com/comfyanonymous/ComfyUI_experiments + +RescaleClassifierFreeGuidance节点的'patch'方法旨在通过引入一个重新缩放操作来修改给定的模型。它调整模型的内部配置,对分类器的引导信号应用动态缩放因子,从而允许对模型的行为进行更精细的控制。这种方法特别适用于微调模型的输出以满足特定的要求或约束。 + +# Input types +## Required +- model + - ‘model’参数对于节点至关重要,因为它代表了将由‘patch’方法修改的机器学习模型。它是主要的输入,决定了节点的操作以及修补过程后模型的后续行为。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- multiplier + - ‘multiplier’参数在控制应用于模型引导信号的重新缩放程度中起着关键作用。它是一个浮点数,决定了原始配置和重新缩放配置之间的平衡,直接影响修补后模型的输出。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- modified_model + - ‘modified_model’输出是将‘patch’方法应用于输入模型的结果。它是原始模型的修改版本,其引导信号的缩放因子已调整,这可能导致基于指定的乘数产生不同的结果。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class RescaleClassifierFreeGuidance: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'multiplier': ('FLOAT', {'default': 0.7, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'patch' + CATEGORY = 'custom_node_experiments' + + def patch(self, model, multiplier): + + def rescale_cfg(args): + cond = args['cond'] + uncond = args['uncond'] + cond_scale = args['cond_scale'] + x_cfg = uncond + cond_scale * (cond - uncond) + ro_pos = torch.std(cond, dim=(1, 2, 3), keepdim=True) + ro_cfg = torch.std(x_cfg, dim=(1, 2, 3), keepdim=True) + x_rescaled = x_cfg * (ro_pos / ro_cfg) + x_final = multiplier * x_rescaled + (1.0 - multiplier) * x_cfg + return x_final + m = model.clone() + m.set_model_sampler_cfg_function(rescale_cfg) + return (m,) +``` \ No newline at end of file diff --git a/docs/Resize Image for SDXL.md b/docs/Resize Image for SDXL.md new file mode 100644 index 0000000..d0334b3 --- /dev/null +++ b/docs/Resize Image for SDXL.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: ResizeImageSDXL +- Category: Mikey/Image +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +ResizeImageSDXL 节点旨在使用多种方法调整和放大图像尺寸。它提供调整图像尺寸的功能,同时保持其长宽比并应用不同的放大技术以提高质量。 + +# Input types +## Required +- image + - 图像参数对于节点的操作至关重要,因为它是将要被调整尺寸和放大的输入。它直接影响执行过程和最终输出图像的质量和尺寸。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- upscale_method + - upscale_method 参数决定了用于放大图像的算法。它对于调整尺寸后的图像质量至关重要,并允许使用不同的插值技术。 + - Comfy dtype: COMBO['nearest-exact', 'bilinear', 'area', 'bicubic'] + - Python dtype: str +- crop + - crop 参数指定了调整尺寸后图像是否以及如何被裁剪。它对于控制输出图像的最终尺寸和长宽比非常重要。 + - Comfy dtype: COMBO['disabled', 'center'] + - Python dtype: str + +# Output types +- resized_image + - resized_image 输出代表了调整尺寸和放大后的处理图像。它是节点操作的主要结果,并反映了所选方法对图像尺寸和质量的影响。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ResizeImageSDXL: + crop_methods = ['disabled', 'center'] + upscale_methods = ['nearest-exact', 'bilinear', 'area', 'bicubic'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'upscale_method': (s.upscale_methods,), 'crop': (s.crop_methods,)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'resize' + CATEGORY = 'Mikey/Image' + + def upscale(self, image, upscale_method, width, height, crop): + samples = image.movedim(-1, 1) + s = comfy.utils.common_upscale(samples, width, height, upscale_method, crop) + s = s.movedim(1, -1) + return (s,) + + def resize(self, image, upscale_method, crop): + (w, h) = find_latent_size(image.shape[2], image.shape[1]) + img = self.upscale(image, upscale_method, w, h, crop)[0] + return (img,) +``` \ No newline at end of file diff --git a/docs/ResizeImageMixlab.md b/docs/ResizeImageMixlab.md new file mode 100644 index 0000000..2f4062f --- /dev/null +++ b/docs/ResizeImageMixlab.md @@ -0,0 +1,117 @@ +# Documentation +- Class name: ResizeImage +- Category: ♾️Mixlab/Image +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +ResizeImage节点旨在根据指定要求调整图像尺寸。它能够巧妙地将图像调整到所需的宽度和高度,同时保持视觉内容的完整性。该节点还提供根据任一维度缩放图像的选项,或者在保持长宽比的同时缩放到适应给定尺寸,或者在缩放后居中图像。此外,它还可以生成图像的平均颜色表示,并将其转换为十六进制代码,为图像预处理和操作提供了一套多功能的工具。 + +# Input types +## Required +- width + - ‘width’参数对于定义调整尺寸后的图像的新宽度至关重要。它在确定图像的最终尺寸中起着关键作用,这可能显著影响视觉输出和长宽比。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’参数指定了调整尺寸后的图像的新高度。它对于控制图像的垂直尺寸至关重要,并与‘width’参数协同工作以保持预期的长宽比。 + - Comfy dtype: INT + - Python dtype: int +- scale_option + - ‘scale_option’参数指示应如何调整图像大小。它允许根据宽度、高度、整体大小或在新尺寸内的居中进行缩放,提供了在保持或改变图像长宽比方面的灵活性。 + - Comfy dtype: COMBO['width', 'height', 'overall', 'center'] + - Python dtype: str +- image + - ‘image’参数用于输入需要调整大小的图像。它是节点操作的核心,因为这是将要被操作和转换的实际内容。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- average_color + - ‘average_color’参数决定是否计算并返回图像的平均颜色。这对于创建简化的表示或基于颜色的设计决策非常有用。 + - Comfy dtype: COMBO['on', 'off'] + - Python dtype: str +- fill_color + - ‘fill_color’参数指定了在将图像调整到大于其原始尺寸的大小后,用于填充任何空白空间的颜色。它确保了一致的背景外观。 + - Comfy dtype: STRING + - Python dtype: str +- mask + - ‘mask’参数用于在调整大小过程中对图像应用遮罩。这对于根据需要保持图像的特定区域可见或隐藏非常重要。 + - Comfy dtype: MASK + - Python dtype: PIL.Image.Image + +# Output types +- image + - ‘image’输出提供了调整尺寸后的图像。这是节点操作的主要结果,反映了根据输入参数应用的转换。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- average_image + - ‘average_image’输出是从输入图像计算出的平均颜色的图像。它作为图像颜色组成的视觉摘要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- average_hex + - ‘average_hex’输出返回图像平均颜色的十六进制表示,可以用于各种设计和与颜色相关的应用。 + - Comfy dtype: STRING + - Python dtype: str +- mask + - ‘mask’输出提供了调整尺寸后的遮罩图像。当节点用于操作和完善图像内特定区域的可见性时特别有用。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ResizeImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'width': ('INT', {'default': 512, 'min': 1, 'max': 8192, 'step': 8, 'display': 'number'}), 'height': ('INT', {'default': 512, 'min': 1, 'max': 8192, 'step': 8, 'display': 'number'}), 'scale_option': (['width', 'height', 'overall', 'center'],)}, 'optional': {'image': ('IMAGE',), 'average_color': (['on', 'off'],), 'fill_color': ('STRING', {'multiline': False, 'default': '#FFFFFF', 'dynamicPrompts': False}), 'mask': ('MASK',)}} + RETURN_TYPES = ('IMAGE', 'IMAGE', 'STRING', 'MASK') + RETURN_NAMES = ('image', 'average_image', 'average_hex', 'mask') + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Image' + INPUT_IS_LIST = True + OUTPUT_IS_LIST = (True, True, True, True) + + def run(self, width, height, scale_option, image=None, average_color=['on'], fill_color=['#FFFFFF'], mask=None): + w = width[0] + h = height[0] + scale_option = scale_option[0] + average_color = average_color[0] + fill_color = fill_color[0] + imgs = [] + masks = [] + average_images = [] + hexs = [] + if image == None: + im = create_noisy_image(w, h, 'RGB') + (a_im, hex) = get_average_color_image(im) + im = pil2tensor(im) + imgs.append(im) + a_im = pil2tensor(a_im) + average_images.append(a_im) + hexs.append(hex) + else: + for ims in image: + for im in ims: + im = tensor2pil(im) + im = resize_image(im, scale_option, w, h, fill_color) + im = im.convert('RGB') + (a_im, hex) = get_average_color_image(im) + im = pil2tensor(im) + imgs.append(im) + a_im = pil2tensor(a_im) + average_images.append(a_im) + hexs.append(hex) + try: + for mas in mask: + for ma in mas: + ma = tensor2pil(ma) + ma = ma.convert('RGB') + ma = resize_image(ma, scale_option, w, h, fill_color) + ma = ma.convert('L') + ma = pil2tensor(ma) + masks.append(ma) + except: + print('') + return (imgs, average_images, hexs, masks) +``` \ No newline at end of file diff --git a/docs/Resolutions by Ratio (WLSH).md b/docs/Resolutions by Ratio (WLSH).md new file mode 100644 index 0000000..634f45b --- /dev/null +++ b/docs/Resolutions by Ratio (WLSH).md @@ -0,0 +1,62 @@ +# Documentation +- Class name: WLSH_Resolutions_by_Ratio +- Category: WLSH Nodes/number +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_Resolutions_by_Ratio节点的'get_resolutions'方法旨在根据给定的宽高比、方向和短边长度计算图像的宽度和高度。它首先从宽高比字符串中确定比例,然后根据短边长度和比例计算宽度。该方法还考虑了图像的方向,如果方向是纵向,则交换宽度和高度。这个节点在图像处理和显示设置中扮演着关键角色,其中宽高比和方向至关重要。 + +# Input types +## Required +- aspect + - 参数'aspect'定义了图像的宽高比,对于确定正确的尺寸至关重要。它是一个表示比例的字符串,例如'16:9'。在调整图像大小时,宽高比对于保持图像的形状和比例至关重要。 + - Comfy dtype: STR + - Python dtype: str +- direction + - 参数'direction'指定了图像的方向,可以是'landscape'(横向)或'portrait'(纵向)。这个参数至关重要,因为它影响宽度和高度的计算,确保尺寸适合指定的方向。 + - Comfy dtype: STR + - Python dtype: str +- shortside + - 参数'shortside'表示图像较短边的长度。它是一个关键输入,因为它直接影响基于宽高比和方向的宽度和高度的计算。该方法确保宽度针对显示或处理目的进行了优化。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- width + - 输出参数'width'提供了考虑了宽高比、方向和短边长度后计算出的图像宽度。它对于确保图像适合所需的显示或处理限制非常重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 输出参数'height'提供了考虑了宽高比、方向和短边长度后计算出的图像高度。它在保持图像比例和确保满足显示要求方面发挥着重要作用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Resolutions_by_Ratio: + aspects = ['1:1', '6:5', '5:4', '4:3', '3:2', '16:10', '16:9', '21:9', '2:1', '3:1', '4:1'] + direction = ['landscape', 'portrait'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'aspect': (s.aspects,), 'direction': (s.direction,), 'shortside': ('INT', {'default': 512, 'min': 64, 'max': MAX_RESOLUTION, 'step': 64})}} + RETURN_TYPES = ('INT', 'INT') + RETURN_NAMES = ('width', 'height') + FUNCTION = 'get_resolutions' + CATEGORY = 'WLSH Nodes/number' + + def get_resolutions(self, aspect, direction, shortside): + (x, y) = aspect.split(':') + x = int(x) + y = int(y) + ratio = x / y + width = int(shortside * ratio) + width = width + 63 & -64 + height = shortside + if direction == 'portrait': + (width, height) = (height, width) + return (width, height) +``` \ No newline at end of file diff --git a/docs/Restore Face (mtb).md b/docs/Restore Face (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/RetrieveBackendData %2F%2FInspire.md b/docs/RetrieveBackendData %2F%2FInspire.md new file mode 100644 index 0000000..eb5e535 --- /dev/null +++ b/docs/RetrieveBackendData %2F%2FInspire.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: RetrieveBackendData +- Category: InspirePack/Backend +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在从后端缓存系统中提取数据,为基于指定键访问存储信息提供了一种流线化的方法。它作为数据检索工作流中的关键组件,确保了高效准确的访问后端数据,无需重复获取数据。 + +# Input types +## Required +- key + - ‘key’参数对于从后端缓存中识别要检索的特定数据集至关重要。它作为一个唯一标识符,使节点能够定位并返回正确的信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- data + - ‘data’输出代表从后端缓存中检索到的信息。它是节点功能的关键组成部分,因为它将请求的数据传递给工作流的后续阶段。 + - Comfy dtype: COMBO[any_typ] + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RetrieveBackendData: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'key': ('STRING', {'multiline': False, 'placeholder': "Input data key (e.g. 'model a', 'chunli lora', 'girl latent 3', ...)"})}} + RETURN_TYPES = (any_typ,) + RETURN_NAMES = ('data',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Backend' + + def doit(self, key): + global cache + (is_list, data) = cache[key][1] + if is_list: + return (data,) + else: + return ([data],) +``` \ No newline at end of file diff --git a/docs/RetrieveBackendDataNumberKey %2F%2FInspire.md b/docs/RetrieveBackendDataNumberKey %2F%2FInspire.md new file mode 100644 index 0000000..ec89799 --- /dev/null +++ b/docs/RetrieveBackendDataNumberKey %2F%2FInspire.md @@ -0,0 +1,32 @@ +# Documentation +- Class name: RetrieveBackendDataNumberKey +- Category: Data Retrieval +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在根据提供的键从后端服务中提取数值数据,便于在无需复杂的数据处理程序的情况下获取特定信息。 + +# Input types +## Required +- key + - ‘key’参数至关重要,因为它唯一标识了从后端所需的数据。它作为节点定位和检索正确数值的参考。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- data + - 输出‘data’代表从后端获取的与输入‘key’对应的数值。它是节点执行的直接结果,对进一步的数据分析或处理具有重要价值。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RetrieveBackendDataNumberKey(RetrieveBackendData): + + @classmethod + def INPUT_TYPES(s): + return {'required': {'key': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} +``` \ No newline at end of file diff --git a/docs/SAM Image Mask.md b/docs/SAM Image Mask.md new file mode 100644 index 0000000..ccc560b --- /dev/null +++ b/docs/SAM Image Mask.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: WAS_SAM_Image_Mask +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_SAM_Image_Mask 节点的 `sam_image_mask` 方法旨在将语义感知分割模型应用于输入图像,生成相应的掩码。它利用 SAM(Semantic Aware Masking)模型预测分割,然后使用该分割创建原始图像上的掩码覆盖。该方法对于需要识别和隔离图像中特定区域以进行进一步分析或操作的应用至关重要。 + +# Input types +## Required +- sam_model + - 参数 `sam_model` 至关重要,因为它表示将用于处理输入图像的语义感知分割模型。这是一个关键组件,决定了生成的掩码的质量和准确性。 + - Comfy dtype: SAM_MODEL + - Python dtype: torch.nn.Module +- sam_parameters + - 参数 `sam_parameters` 包含 SAM 模型执行分割所需的点和标签。这是一个关键的输入,它直接影响分割过程的结果。 + - Comfy dtype: SAM_PARAMETERS + - Python dtype: Dict[str, Any] +- image + - 参数 `image` 是将由 SAM 模型处理以生成掩码的输入图像。它是节点操作的主要数据源,其格式可以显著影响分割结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- image + - 输出 `image` 是带有预测掩码覆盖的原始输入图像。它代表了语义感知分割过程的视觉结果,允许直接视觉检查掩码区域。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 输出 `mask` 是分割掩码的二进制表示,突出显示了 SAM 模型识别的区域。它对于需要更精确地操作或分析特定图像区域的应用来说非常重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WAS_SAM_Image_Mask: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + return {'required': {'sam_model': ('SAM_MODEL',), 'sam_parameters': ('SAM_PARAMETERS',), 'image': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE', 'MASK') + FUNCTION = 'sam_image_mask' + CATEGORY = 'WAS Suite/Image/Masking' + + def sam_image_mask(self, sam_model, sam_parameters, image): + image = tensor2sam(image) + points = sam_parameters['points'] + labels = sam_parameters['labels'] + from segment_anything import SamPredictor + device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + sam_model.to(device=device) + predictor = SamPredictor(sam_model) + predictor.set_image(image) + (masks, scores, logits) = predictor.predict(point_coords=points, point_labels=labels, multimask_output=False) + sam_model.to(device='cpu') + mask = np.expand_dims(masks, axis=-1) + image = np.repeat(mask, 3, axis=-1) + image = torch.from_numpy(image) + mask = torch.from_numpy(mask) + mask = mask.squeeze(2) + mask = mask.squeeze().to(torch.float32) + return (image, mask) +``` \ No newline at end of file diff --git a/docs/SAM Model Loader.md b/docs/SAM Model Loader.md new file mode 100644 index 0000000..1ca64b1 --- /dev/null +++ b/docs/SAM Model Loader.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: WAS_SAM_Model_Loader +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +sam_load_model 函数旨在根据指定的模型大小加载和初始化预训练的 Segment Anything Model (SAM)。如果模型权重尚未存在,则它负责下载模型权重并为后续的图像分割任务设置模型。该节点对于图像遮罩过程至关重要,为 WAS Suite 中的高质量对象分割提供了基础。 + +# Input types +## Required +- model_size + - model_size 参数对于确定要加载的特定 SAM 模型至关重要。它决定了模型的复杂性和大小,这直接影响了分割任务的性能和准确性。此参数确保在图像掩蔽过程中使用了正确的预训练模型。 + - Comfy dtype: COMBO['ViT-H', 'ViT-L', 'ViT-B'] + - Python dtype: str + +# Output types +- SAM_MODEL + - 输出的 SAM_MODEL 表示已加载并准备使用的 Segment Anything Model。这是一个专为高质量对象分割而设计的预训练深度学习模型。该模型是图像掩蔽工作流程中后续步骤的关键组件,能够实现图像中对象的精确和高效分割。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WAS_SAM_Model_Loader: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + return {'required': {'model_size': (['ViT-H', 'ViT-L', 'ViT-B'],)}} + RETURN_TYPES = ('SAM_MODEL',) + FUNCTION = 'sam_load_model' + CATEGORY = 'WAS Suite/Image/Masking' + + def sam_load_model(self, model_size): + conf = getSuiteConfig() + model_filename_mapping = {'ViT-H': 'sam_vit_h_4b8939.pth', 'ViT-L': 'sam_vit_l_0b3195.pth', 'ViT-B': 'sam_vit_b_01ec64.pth'} + model_url_mapping = {'ViT-H': conf['sam_model_vith_url'] if conf.__contains__('sam_model_vith_url') else 'https://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pth', 'ViT-L': conf['sam_model_vitl_url'] if conf.__contains__('sam_model_vitl_url') else 'https://dl.fbaipublicfiles.com/segment_anything/sam_vit_l_0b3195.pth', 'ViT-B': conf['sam_model_vitb_url'] if conf.__contains__('sam_model_vitb_url') else 'https://dl.fbaipublicfiles.com/segment_anything/sam_vit_b_01ec64.pth'} + model_url = model_url_mapping[model_size] + model_filename = model_filename_mapping[model_size] + if 'GitPython' not in packages(): + install_package('gitpython') + if not os.path.exists(os.path.join(WAS_SUITE_ROOT, 'repos' + os.sep + 'SAM')): + from git.repo.base import Repo + cstr('Installing SAM...').msg.print() + Repo.clone_from('https://github.com/facebookresearch/segment-anything', os.path.join(WAS_SUITE_ROOT, 'repos' + os.sep + 'SAM')) + sys.path.append(os.path.join(WAS_SUITE_ROOT, 'repos' + os.sep + 'SAM')) + sam_dir = os.path.join(MODELS_DIR, 'sam') + if not os.path.exists(sam_dir): + os.makedirs(sam_dir, exist_ok=True) + sam_file = os.path.join(sam_dir, model_filename) + if not os.path.exists(sam_file): + cstr('Selected SAM model not found. Downloading...').msg.print() + r = requests.get(model_url, allow_redirects=True) + open(sam_file, 'wb').write(r.content) + from segment_anything import build_sam_vit_h, build_sam_vit_l, build_sam_vit_b + if model_size == 'ViT-H': + sam_model = build_sam_vit_h(sam_file) + elif model_size == 'ViT-L': + sam_model = build_sam_vit_l(sam_file) + elif model_size == 'ViT-B': + sam_model = build_sam_vit_b(sam_file) + else: + raise ValueError(f"SAM model does not match the model_size: '{model_size}'.") + return (sam_model,) +``` \ No newline at end of file diff --git a/docs/SAM Parameters Combine.md b/docs/SAM Parameters Combine.md new file mode 100644 index 0000000..a9ae590 --- /dev/null +++ b/docs/SAM Parameters Combine.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: WAS_SAM_Combine_Parameters +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法`sam_combine_parameters`旨在合并两组与SAM(Semantic Affinity Model)相关的参数。它的作用是将多个参数集整合成统一的结构,这对于需要将不同SAM实例的数据进行整合的操作至关重要。该节点在确保点和标签的无缝整合中发挥关键作用,促进WAS套件中复杂的图像和掩蔽任务的执行。 + +# Input types +## Required +- sam_parameters_a + - 第一组SAM参数对于组合过程至关重要。它包含了将与另一组合并的初始数据点和标签。此参数显著影响最终组合参数的结构和内容,影响图像和掩蔽工作流程中的后续步骤。 + - Comfy dtype: SAM_PARAMETERS + - Python dtype: Dict[str, Union[np.ndarray, List[str]]] +- sam_parameters_b + - 将与第一组参数结合的第二组SAM参数。它与第一组参数同样重要,提供额外的数据点和标签,有助于组合参数的全面性。 + - Comfy dtype: SAM_PARAMETERS + - Python dtype: Dict[str, Union[np.ndarray, List[str]]] + +# Output types +- parameters + - `sam_combine_parameters`方法的输出是一组统一的参数,它包含了来自两个输入SAM参数的组合数据。这个输出很重要,因为它是图像和掩蔽领域进一步处理和分析的基础。 + - Comfy dtype: SAM_PARAMETERS + - Python dtype: Dict[str, Union[np.ndarray, List[str]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_SAM_Combine_Parameters: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + return {'required': {'sam_parameters_a': ('SAM_PARAMETERS',), 'sam_parameters_b': ('SAM_PARAMETERS',)}} + RETURN_TYPES = ('SAM_PARAMETERS',) + FUNCTION = 'sam_combine_parameters' + CATEGORY = 'WAS Suite/Image/Masking' + + def sam_combine_parameters(self, sam_parameters_a, sam_parameters_b): + parameters = {'points': np.concatenate((sam_parameters_a['points'], sam_parameters_b['points']), axis=0), 'labels': np.concatenate((sam_parameters_a['labels'], sam_parameters_b['labels']))} + return (parameters,) +``` \ No newline at end of file diff --git a/docs/SAM Parameters.md b/docs/SAM Parameters.md new file mode 100644 index 0000000..c1e82b5 --- /dev/null +++ b/docs/SAM Parameters.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: WAS_SAM_Parameters +- Category: WAS Suite/Image/Masking +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_SAM_Parameters节点旨在为WAS套件中图像掩蔽操作处理和格式化输入数据。它接受点和标签以生成对后续掩蔽过程至关重要的参数。该节点在准备准确高效图像分割任务的基础工作中发挥关键作用。 + +# Input types +## Required +- points + - “points”参数对于定义图像中用于掩蔽的坐标至关重要。它是一个字符串,包含一系列点,每个点由其x和y坐标表示。此参数通过确定图像中需要关注的区域,直接影响掩蔽过程的准确性。 + - Comfy dtype: STRING + - Python dtype: str +- labels + - “labels”参数为提供的点分配分类标签,这对于在掩蔽操作中区分图像中不同类型的区域至关重要。它是一个包含与每个点相对应的标签列表的字符串。此参数对于在掩蔽过程中对图像段进行分类和组织至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- parameters + - “parameters”输出是输入点和标签的结构化表示,格式化为与图像掩蔽过程的要求兼容的字典。它封装了处理后的数据,使其准备好用于下游掩蔽操作。 + - Comfy dtype: SAM_PARAMETERS + - Python dtype: Dict[str, Union[np.ndarray, List[int]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_SAM_Parameters: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + return {'required': {'points': ('STRING', {'default': '[128, 128]; [0, 0]', 'multiline': False}), 'labels': ('STRING', {'default': '[1, 0]', 'multiline': False})}} + RETURN_TYPES = ('SAM_PARAMETERS',) + FUNCTION = 'sam_parameters' + CATEGORY = 'WAS Suite/Image/Masking' + + def sam_parameters(self, points, labels): + parameters = {'points': np.asarray(np.matrix(points)), 'labels': np.array(np.matrix(labels))[0]} + return (parameters,) +``` \ No newline at end of file diff --git a/docs/SAMDetectorCombined.md b/docs/SAMDetectorCombined.md new file mode 100644 index 0000000..afe2cc7 --- /dev/null +++ b/docs/SAMDetectorCombined.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: SAMDetectorCombined +- Category: ImpactPack/Detector +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SAMDetectorCombined节点旨在使用SAM(Segment Anything Model)检测和分割图像中的物体。它使用指定的SAM模型、分割提示和其他参数处理输入图像,以生成勾勒出检测到的物体的掩码。该节点对于需要精确物体定位和分割的应用程序至关重要,例如在计算机视觉和图像分析任务中。 + +# Input types +## Required +- sam_model + - SAM模型参数对于节点的操作至关重要,因为它定义了将用于对象检测和分割的模型。模型的选择直接影响节点准确识别和分割图像中对象的能力。 + - Comfy dtype: SAM_MODEL + - Python dtype: torch.nn.Module +- segs + - segs参数提供分割提示,指导SAM模型检测图像中的特定区域。这些提示对于提高分割过程的准确性至关重要,特别是在具有多个对象的复杂场景中。 + - Comfy dtype: SEGS + - Python dtype: List[impact.core.SEG] +- image + - 图像参数是节点的输入,对于检测过程是必需的。图像的质量和分辨率直接影响节点在检测和分割对象方面的性能。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- detection_hint + - 检测提示参数允许指定要使用的检测策略类型。它影响SAM模型如何解释和处理分割提示,从而影响对象检测的结果。 + - Comfy dtype: COMBO['center-1', 'horizontal-2', 'vertical-2', 'rect-4', 'diamond-4', 'mask-area', 'mask-points', 'mask-point-bbox', 'none'] + - Python dtype: str +- dilation + - 膨胀参数用于控制检测到的对象周围的边界框的扩展。它在分割掩码的后处理中起着重要作用,可能改善掩码对对象的覆盖。 + - Comfy dtype: INT + - Python dtype: int +- threshold + - 阈值参数对于确定将对象视为已检测的置信度水平至关重要。它直接影响节点在图像中识别对象的敏感性。 + - Comfy dtype: FLOAT + - Python dtype: float +- bbox_expansion + - bbox_expansion参数定义了要应用于检测到的对象的边界框的扩展量。这有助于调整分割掩码围绕对象的紧密度。 + - Comfy dtype: INT + - Python dtype: int +- mask_hint_threshold + - mask_hint_threshold参数用于设置分割过程中使用掩码提示的阈值。它影响节点在识别对象边界时对掩码提示的依赖。 + - Comfy dtype: FLOAT + - Python dtype: float +- mask_hint_use_negative + - mask_hint_use_negative参数决定了分割过程中如何使用负提示。它可以增强节点区分对象和背景的能力。 + - Comfy dtype: COMBO['False', 'Small', 'Outter'] + - Python dtype: str + +# Output types +- MASK + - MASK输出提供了检测和分割过程后的最终分割掩码。它是进一步分析或用于需要对象分割的下游任务的关键输出。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SAMDetectorCombined: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'sam_model': ('SAM_MODEL',), 'segs': ('SEGS',), 'image': ('IMAGE',), 'detection_hint': (['center-1', 'horizontal-2', 'vertical-2', 'rect-4', 'diamond-4', 'mask-area', 'mask-points', 'mask-point-bbox', 'none'],), 'dilation': ('INT', {'default': 0, 'min': -512, 'max': 512, 'step': 1}), 'threshold': ('FLOAT', {'default': 0.93, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'bbox_expansion': ('INT', {'default': 0, 'min': 0, 'max': 1000, 'step': 1}), 'mask_hint_threshold': ('FLOAT', {'default': 0.7, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'mask_hint_use_negative': (['False', 'Small', 'Outter'],)}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detector' + + def doit(self, sam_model, segs, image, detection_hint, dilation, threshold, bbox_expansion, mask_hint_threshold, mask_hint_use_negative): + return (core.make_sam_mask(sam_model, segs, image, detection_hint, dilation, threshold, bbox_expansion, mask_hint_threshold, mask_hint_use_negative),) +``` \ No newline at end of file diff --git a/docs/SAMDetectorSegmented.md b/docs/SAMDetectorSegmented.md new file mode 100644 index 0000000..3786816 --- /dev/null +++ b/docs/SAMDetectorSegmented.md @@ -0,0 +1,77 @@ +# Documentation +- Class name: SAMDetectorSegmented +- Category: ImpactPack/Detector +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SAMDetectorSegmented节点旨在使用SAM(分割和掩蔽)模型检测和分割图像中的物体。它处理输入图像和分割提示,生成一个组合掩蔽和一个单独掩蔽的批次,这对于在ImpactPack框架内进行进一步分析和操作至关重要。 + +# Input types +## Required +- sam_model + - SAM模型参数至关重要,因为它定义了将用于分割任务的机器学习模型。它直接影响节点准确检测和分割图像中对象的能力。 + - Comfy dtype: SAM_MODEL + - Python dtype: torch.nn.Module +- segs + - segs参数包含分割提示,指导SAM模型检测图像中的特定区域。它通过将检测过程集中在感兴趣的区域上,在提高节点性能方面发挥着重要作用。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +- image + - 图像参数是节点处理的输入。它是分割和检测任务的主要数据源,是节点功能的基本方面。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- detection_hint + - 检测提示参数提供了一种细化检测过程的方法。它允许指定不同的检测策略,这对于根据输入图像的特性优化节点性能至关重要。 + - Comfy dtype: COMBO['center-1', 'horizontal-2', 'vertical-2', 'rect-4', 'diamond-4', 'mask-area', 'mask-points', 'mask-point-bbox', 'none'] + - Python dtype: str +- dilation + - 膨胀参数用于控制检测到的掩蔽的扩展。它对于调整节点的输出以更好地适应后续处理步骤的要求可能是重要的。 + - Comfy dtype: INT + - Python dtype: int +- threshold + - 阈值参数决定了检测被认为是有效的置信度水平。它是控制节点操作中精确度和召回率平衡的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- bbox_expansion + - bbox_expansion参数允许扩展检测过程中使用的边界框。这对于确保检测到的掩蔽包含整个感兴趣的对象可能是有用的。 + - Comfy dtype: INT + - Python dtype: int +- mask_hint_threshold + - mask_hint_threshold参数用于设置掩蔽提示的敏感度。它影响节点如何解释和响应提供的分割提示,影响分割的质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- mask_hint_use_negative + - mask_hint_use_negative参数指定应如何使用负掩蔽提示。它可能显著影响节点区分图像中的对象和背景的能力。 + - Comfy dtype: COMBO['False', 'Small', 'Outter'] + - Python dtype: str + +# Output types +- combined_mask + - combined_mask输出参数代表分割过程的聚合结果。它是一个包含所有检测到的对象的单一掩蔽,提供了分割结果的整合视图。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- batch_masks + - batch_masks输出参数提供了一个对应于每个检测到的对象的单独掩蔽的数组。这允许在分割上下文中对每个对象进行详细的分析和操作。 + - Comfy dtype: MASK + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SAMDetectorSegmented: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'sam_model': ('SAM_MODEL',), 'segs': ('SEGS',), 'image': ('IMAGE',), 'detection_hint': (['center-1', 'horizontal-2', 'vertical-2', 'rect-4', 'diamond-4', 'mask-area', 'mask-points', 'mask-point-bbox', 'none'],), 'dilation': ('INT', {'default': 0, 'min': -512, 'max': 512, 'step': 1}), 'threshold': ('FLOAT', {'default': 0.93, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'bbox_expansion': ('INT', {'default': 0, 'min': 0, 'max': 1000, 'step': 1}), 'mask_hint_threshold': ('FLOAT', {'default': 0.7, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'mask_hint_use_negative': (['False', 'Small', 'Outter'],)}} + RETURN_TYPES = ('MASK', 'MASK') + RETURN_NAMES = ('combined_mask', 'batch_masks') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detector' + + def doit(self, sam_model, segs, image, detection_hint, dilation, threshold, bbox_expansion, mask_hint_threshold, mask_hint_use_negative): + (combined_mask, batch_masks) = core.make_sam_mask_segmented(sam_model, segs, image, detection_hint, dilation, threshold, bbox_expansion, mask_hint_threshold, mask_hint_use_negative) + return (combined_mask, batch_masks) +``` \ No newline at end of file diff --git a/docs/SAMLoader.md b/docs/SAMLoader.md new file mode 100644 index 0000000..b7e2c58 --- /dev/null +++ b/docs/SAMLoader.md @@ -0,0 +1,75 @@ +# Documentation +- Class name: SAMLoader +- Category: ImpactPack +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SAMLoader节点旨在高效管理和加载SAM(Segment Anything Model)家族中的各种模型,包括ESAM。它提供了一个高级接口,用于根据用户定义的标准(如模型名称和设备模式)选择和使用模型,确保最佳性能和资源利用率。 + +# Input types +## Required +- model_name + - model_name参数对于确定要加载的SAM模型至关重要。它通过指导节点指向正确的模型文件来影响节点的执行,这对于后续的处理和预测任务至关重要。 + - Comfy dtype: str + - Python dtype: str +## Optional +- device_mode + - device_mode参数允许用户指定模型执行的计算设备。它通过根据所选模式优化GPU或CPU资源的使用,在节点性能中扮演重要角色。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- SAM_MODEL + - SAM_MODEL输出代表已加载的SAM模型,准备用于推理或进一步处理。它封装了模型的架构和学习到的参数,标志着节点主要功能的完成。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SAMLoader: + + @classmethod + def INPUT_TYPES(cls): + models = [x for x in folder_paths.get_filename_list('sams') if 'hq' not in x] + return {'required': {'model_name': (models + ['ESAM'],), 'device_mode': (['AUTO', 'Prefer GPU', 'CPU'],)}} + RETURN_TYPES = ('SAM_MODEL',) + FUNCTION = 'load_model' + CATEGORY = 'ImpactPack' + + def load_model(self, model_name, device_mode='auto'): + if model_name == 'ESAM': + if 'ESAM_ModelLoader_Zho' not in nodes.NODE_CLASS_MAPPINGS: + try_install_custom_node('https://github.com/ZHO-ZHO-ZHO/ComfyUI-YoloWorld-EfficientSAM', "To use 'ESAM' model, 'ComfyUI-YoloWorld-EfficientSAM' extension is required.") + raise Exception("'ComfyUI-YoloWorld-EfficientSAM' node isn't installed.") + esam_loader = nodes.NODE_CLASS_MAPPINGS['ESAM_ModelLoader_Zho']() + if device_mode == 'CPU': + esam = esam_loader.load_esam_model('CPU')[0] + else: + device_mode = 'CUDA' + esam = esam_loader.load_esam_model('CUDA')[0] + sam_obj = core.ESAMWrapper(esam, device_mode) + esam.sam_wrapper = sam_obj + print(f'Loads EfficientSAM model: (device:{device_mode})') + return (esam,) + modelname = folder_paths.get_full_path('sams', model_name) + if 'vit_h' in model_name: + model_kind = 'vit_h' + elif 'vit_l' in model_name: + model_kind = 'vit_l' + else: + model_kind = 'vit_b' + sam = sam_model_registry[model_kind](checkpoint=modelname) + size = os.path.getsize(modelname) + safe_to = core.SafeToGPU(size) + device = comfy.model_management.get_torch_device() if device_mode == 'Prefer GPU' else 'CPU' + if device_mode == 'Prefer GPU': + safe_to.to_device(sam, device) + is_auto_mode = device_mode == 'AUTO' + sam_obj = core.SAMWrapper(sam, is_auto_mode=is_auto_mode, safe_to_gpu=safe_to) + sam.sam_wrapper = sam_obj + print(f'Loads SAM model: {modelname} (device:{device_mode})') + return (sam,) +``` \ No newline at end of file diff --git a/docs/SAMModelLoader (segment anything).md b/docs/SAMModelLoader (segment anything).md new file mode 100644 index 0000000..b44a00b --- /dev/null +++ b/docs/SAMModelLoader (segment anything).md @@ -0,0 +1,39 @@ +# Documentation +- Class name: SAMModelLoader +- Category: segment_anything +- Output node: False +- Repo Ref: https://github.com/storyicon/comfyui_segment_anything + +SAMModelLoader节点负责加载和准备用于图像分割任务的Segment Anything Model(SAM)。它确保根据指定的模型名称加载正确的模型,使其成为初始化分割过程的关键组件。 + +# Input types +## Required +- model_name + - model_name参数对于识别要加载的特定Segment Anything Model至关重要。它指导节点到正确的模型配置,并确保为任务分配适当的资源。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- SAM_MODEL + - SAM_MODEL输出代表已加载的Segment Anything Model,准备用于图像分割任务。它是节点操作的成果,为后续处理步骤提供了基础模型。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SAMModelLoader: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model_name': (list_sam_model(),)}} + CATEGORY = 'segment_anything' + FUNCTION = 'main' + RETURN_TYPES = ('SAM_MODEL',) + + def main(self, model_name): + sam_model = load_sam_model(model_name) + return (sam_model,) +``` \ No newline at end of file diff --git a/docs/SDXL Quick Empty Latent (WLSH).md b/docs/SDXL Quick Empty Latent (WLSH).md new file mode 100644 index 0000000..0f919e3 --- /dev/null +++ b/docs/SDXL Quick Empty Latent (WLSH).md @@ -0,0 +1,69 @@ +# Documentation +- Class name: WLSH_SDXL_Quick_Empty_Latent +- Category: WLSH Nodes/latent +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_SDXL_Quick_Empty_Latent节点的'generate'方法负责创建图像的空潜在空间表示。它通过接受图像分辨率和方向参数来操作,然后生成一个填充零的潜在张量。这个潜在张量在图像生成流水线中用于进一步处理或分析,提供了一个可以修改以代表各种图像特征的基础结构。 + +# Input types +## Required +- resolution + - ‘resolution’参数定义了要生成潜在空间的图像的尺寸。它是潜在张量大小和结构的关键决定因素,直接影响后续的图像生成过程。 + - Comfy dtype: STR + - Python dtype: str +- direction + - ‘direction’参数指定了图像的方向,可以是‘landscape’(横向)或‘portrait’(纵向)。这影响了图像的宽度和高度的解释方式,因此对于正确生成潜在张量至关重要。 + - Comfy dtype: STR + - Python dtype: str +## Optional +- batch_size + - ‘batch_size’参数指示单次操作中要处理的图像数量。它是一个可选参数,可用于控制处理的效率,允许同时处理多个图像。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- latent + - 'latent'输出提供了生成的潜在空间张量,它是图像生成的基础。它是一个填充零的张量,将被进一步操作以表示所需的图像特征。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- width + - 'width'输出表示潜在空间的调整后宽度,它是8的倍数。这个值对于理解生成的潜在张量的维度很重要,并用于图像生成过程。 + - Comfy dtype: INT + - Python dtype: int +- height + - 'height'输出表示潜在空间的调整后高度,也是8的倍数。它是潜在张量的维度的重要参数,并在整体图像生成工作流程中发挥作用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_SDXL_Quick_Empty_Latent: + resolution = ['1024x1024', '1152x896', '1216x832', '1344x768', '1536x640'] + direction = ['landscape', 'portrait'] + + def __init__(self, device='cpu'): + self.device = device + + @classmethod + def INPUT_TYPES(s): + return {'required': {'resolution': (s.resolution,), 'direction': (s.direction,), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}} + RETURN_TYPES = ('LATENT', 'INT', 'INT') + RETURN_NAMES = ('latent', 'width', 'height') + FUNCTION = 'generate' + CATEGORY = 'WLSH Nodes/latent' + + def generate(self, resolution, direction, batch_size=1): + (width, height) = resolution.split('x') + width = int(width) + height = int(height) + if direction == 'portrait': + (width, height) = (height, width) + adj_width = width // 8 + adj_height = height // 8 + latent = torch.zeros([batch_size, 4, adj_height, adj_width]) + return ({'samples': latent}, adj_width * 8, adj_height * 8) +``` \ No newline at end of file diff --git a/docs/SDXL Quick Image Scale (WLSH).md b/docs/SDXL Quick Image Scale (WLSH).md new file mode 100644 index 0000000..fc9e2fa --- /dev/null +++ b/docs/SDXL Quick Image Scale (WLSH).md @@ -0,0 +1,68 @@ +# Documentation +- Class name: WLSH_SDXL_Quick_Image_Scale +- Category: WLSH Nodes/upscaling +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_SDXL_Quick_Image_Scale节点的'upscale'方法旨在高效提升输入图像的分辨率。它提供了多种上采样方法供选择,确保图像根据所需的分辨率和方向进行缩放。该节点还提供了裁剪图像以获得更好构图的灵活性,使其成为图像增强任务的多功能工具。 + +# Input types +## Required +- original + - ‘original’参数是需要上采样的输入图像。它是整个操作的关键元素,因为整个操作都围绕着增强这张图像。原始图像的质量和格式直接影响最终上采样的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- upscale_method + - ‘upscale_method’参数决定了用于上采样图像的算法。它显著影响最终图像质量和上采样过程的性能。用户可以根据他们的具体需求从‘nearest-exact’、‘bilinear’或‘area’方法中选择。 + - Comfy dtype: COMBO['nearest-exact', 'bilinear', 'area'] + - Python dtype: str +- resolution + - ‘resolution’参数指定了上采样图像的目标分辨率。它至关重要,因为它决定了原始图像将被缩放到的尺寸。分辨率的选择影响细节水平和最终图像大小。 + - Comfy dtype: COMBO['1024x1024', '1152x896', '1216x832', '1344x768', '1536x640'] + - Python dtype: str +- direction + - ‘direction’参数定义了上采样图像的方向。它对于确保图像根据其预期用途(无论是横向还是纵向观看)正确显示非常重要。 + - Comfy dtype: COMBO['landscape', 'portrait'] + - Python dtype: str +- crop + - ‘crop’参数允许对上采样图像进行可选裁剪。它可以设置为‘disabled’以不进行裁剪或‘center’以从中心裁剪图像。这个特性可以改善最终图像的构图。 + - Comfy dtype: COMBO['disabled', 'center'] + - Python dtype: str + +# Output types +- upscaled_image + - ‘upscaled_image’输出是上采样过程的结果。它代表了原始图像增强到指定分辨率和方向的结果。这个输出的质量和外观直接反映了输入参数和节点的能力。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WLSH_SDXL_Quick_Image_Scale: + upscale_methods = ['nearest-exact', 'bilinear', 'area'] + resolution = ['1024x1024', '1152x896', '1216x832', '1344x768', '1536x640'] + direction = ['landscape', 'portrait'] + crop_methods = ['disabled', 'center'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'original': ('IMAGE',), 'upscale_method': (s.upscale_methods,), 'resolution': (s.resolution,), 'direction': (s.direction,), 'crop': (s.crop_methods,)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'upscale' + CATEGORY = 'WLSH Nodes/upscaling' + + def upscale(self, original, upscale_method, resolution, direction, crop): + (width, height) = resolution.split('x') + new_width = int(width) + new_height = int(height) + if direction == 'portrait': + (new_width, new_height) = (new_height, new_width) + old_width = original.shape[2] + old_height = original.shape[1] + samples = original.movedim(-1, 1) + s = comfy.utils.common_upscale(samples, new_width, new_height, upscale_method, crop) + s = s.movedim(1, -1) + return (s,) +``` \ No newline at end of file diff --git a/docs/SDXL Resolutions (WLSH).md b/docs/SDXL Resolutions (WLSH).md new file mode 100644 index 0000000..647c29d --- /dev/null +++ b/docs/SDXL Resolutions (WLSH).md @@ -0,0 +1,57 @@ +# Documentation +- Class name: WLSH_SDXL_Resolutions +- Category: WLSH Nodes/number +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_SDXL_Resolutions节点的'get_resolutions'方法旨在处理图像分辨率和方向数据。它接受一个表示分辨率的字符串和一个方向指示器作为输入,将分辨率转换为宽度和高度的整数值,并根据提供的方向调整这些值,确保保持肖像或风景方向的正确宽高比。 + +# Input types +## Required +- resolution + - “resolution”参数是一个字符串,它以'widthxheight'格式指定图像的尺寸。它对于确定图像的像素尺寸至关重要,并用于计算宽度和高度值。 + - Comfy dtype: str + - Python dtype: str +- direction + - “direction”参数指示图像的方向,可以是'landscape'(风景)或'portrait'(肖像)。此参数对于调整宽度和高度值以匹配指定的方向至关重要。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- width + - 'width'输出代表了考虑了'direction'输入指定的方向后的图像宽度。它是一个整数值,反映了图像水平轴上的像素数。 + - Comfy dtype: INT + - Python dtype: int +- height + - 'height'输出对应于方向调整后的图像高度。它是一个整数,表示图像垂直轴上的像素数。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_SDXL_Resolutions: + resolution = ['1024x1024', '1152x896', '1216x832', '1344x768', '1536x640'] + direction = ['landscape', 'portrait'] + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'resolution': (s.resolution,), 'direction': (s.direction,)}} + RETURN_TYPES = ('INT', 'INT') + RETURN_NAMES = ('width', 'height') + FUNCTION = 'get_resolutions' + CATEGORY = 'WLSH Nodes/number' + + def get_resolutions(self, resolution, direction): + (width, height) = resolution.split('x') + width = int(width) + height = int(height) + if direction == 'portrait': + (width, height) = (height, width) + return (width, height) +``` \ No newline at end of file diff --git a/docs/SDXL Steps (WLSH).md b/docs/SDXL Steps (WLSH).md new file mode 100644 index 0000000..bc0fa65 --- /dev/null +++ b/docs/SDXL Steps (WLSH).md @@ -0,0 +1,58 @@ +# Documentation +- Class name: WLSH_SDXL_Steps +- Category: WLSH Nodes/number +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_SDXL_Steps节点的'set_steps'方法旨在为加权最小二乘问题配置步长参数。它在确定步骤的序列和间隔方面起着关键作用,这可以显著影响数值过程的结果。 + +# Input types +## Required +- precondition + - “precondition”参数对于设置步序列之前的初始条件至关重要。它影响数值过程的起始点,对节点的整体执行至关重要。 + - Comfy dtype: INT + - Python dtype: int +- base + - “base”参数定义了派生步序列的基本步长值。它是计算中的关键决定因素,直接影响步长模式的结构。 + - Comfy dtype: INT + - Python dtype: int +- total + - “total”参数指定序列中要采取的步数的总数。它是控制数值操作的范围及其计算负载的关键因素。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- pre + - “pre”输出反映了由“precondition”参数设置的初始条件,标志着步序列的起始点。 + - Comfy dtype: INT + - Python dtype: int +- base + - “base”输出对应于输入的基本步长值,代表步序列计算的基础。 + - Comfy dtype: INT + - Python dtype: int +- total + - “total”输出指示程序将执行的总步数,由“total”参数确定。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_SDXL_Steps: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'precondition': ('INT', {'default': 3, 'min': 1, 'max': 10000}), 'base': ('INT', {'default': 12, 'min': 1, 'max': 10000}), 'total': ('INT', {'default': 20, 'min': 1, 'max': 10000})}} + RETURN_TYPES = ('INT', 'INT', 'INT') + RETURN_NAMES = ('pre', 'base', 'total') + FUNCTION = 'set_steps' + CATEGORY = 'WLSH Nodes/number' + + def set_steps(self, precondition, base, total): + return (precondition, base, total) +``` \ No newline at end of file diff --git a/docs/SDXLEmptyLatentSizePicker+.md b/docs/SDXLEmptyLatentSizePicker+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/SDXLPromptStylerAll.md b/docs/SDXLPromptStylerAll.md new file mode 100644 index 0000000..691abde --- /dev/null +++ b/docs/SDXLPromptStylerAll.md @@ -0,0 +1,98 @@ +# Documentation +- Class name: SDXLPromptStylerAll +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在通过应用各种样式模板来增强提示的呈现,确保提示具有吸引力且在情境上适当。 + +# Input types +## Required +- text_positive + - 正面文本输入至关重要,因为它为提示设定了积极基调。它是将要被样式化并呈现给用户的基础内容。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入通过提供对比视角来补充正面文本。这对于创建一个平衡且全面的提示至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 样式参数至关重要,因为它决定了应用于提示的审美和结构格式,显著影响用户的感知和参与度。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志记录选项允许记录提示生成的详细信息,这对于调试和随时间改进节点的功能非常有用。 + - Comfy dtype: COMBO + - Python dtype: str +- auto_select_style + - 启用此功能后,它将自动化样式选择过程,确保将多样化的样式应用于提示,增强整体的多样性和吸引力。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- auto_refresh + - 激活此参数后,它会触发节点刷新并生成新的提示,确保内容对用户保持新鲜和吸引力。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- positive_prompt_text_g + - 输出提供积极样式化的提示文本,已经格式化以有效地吸引和引导用户。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出提供负面样式化的提示文本,提供对比视角以平衡整体信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerAll: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_all.json') + cls.json_data = read_json_file(file_path) + styles = read_sdxl_styles(cls.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}, 'optional': {'auto_select_style': ('BOOLEAN', {'default': False}), 'auto_refresh': ('BOOLEAN', {'default': False})}} + + @classmethod + def IS_CHANGED(cls, text, autorefresh): + if auto_refresh == 'True': + return float('NaN') + + def get_prompt(self, text: str, autorefresh: str) -> tuple[str]: + prompt = self.generate_prompt(text) + print(f'Prompt: {prompt}') + return (prompt,) + + @abstractmethod + def generate_prompt(self, text: str) -> str: + ... + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt, auto_select_style=False, auto_refresh=False): + if auto_select_style or auto_refresh: + style = random.choice([template['name'] for template in self.json_data]) + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + current_time = int(time.time()) + dummy_change = current_time + return (positive_prompt, negative_prompt, dummy_change) + dummy_change = current_time + return (positive_prompt, negative_prompt, dummy_change) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerHorror.md b/docs/SDXLPromptStylerHorror.md new file mode 100644 index 0000000..c967f67 --- /dev/null +++ b/docs/SDXLPromptStylerHorror.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerHorror +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在基于给定的恐怖主题来修饰文本提示,增强叙述时的特定情绪和氛围。 + +# Input types +## Required +- text_positive + - 正面文本输入对于设定恐怖主题的基本情绪至关重要。它为风格化转换提供了起点。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入对于对比正面文本至关重要,通过增加紧张和冲突,为恐怖主题提供深度。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格参数在确定将应用于文本的具体恐怖主题方面至关重要,指导输出的整体美学。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志提示选项允许选择性地记录转换过程,这对于调试和理解节点的操作有益。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出提供了一个正面风格的恐怖主题文本,已经通过所选主题增强,以创造沉浸式体验。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出提供了一个负面风格的恐怖主题文本,与正面文本相辅相成,加深了整体的恐怖氛围。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerHorror: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_horror.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerMisc.md b/docs/SDXLPromptStylerMisc.md new file mode 100644 index 0000000..2a95b2c --- /dev/null +++ b/docs/SDXLPromptStylerMisc.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerMisc +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在通过应用预定义的样式来增强提示的呈现,确保提示具有吸引力且在上下文中合适。 + +# Input types +## Required +- text_positive + - 正面文本输入至关重要,因为它为提示设定了积极基调。它将是按照选定模板进行样式化和格式化的基础文本。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入对于提供提示的对比元素至关重要,允许更细致和平衡的呈现。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- style + - 样式输入决定了提示的审美和结构特征,影响其整体吸引力和有效性。 + - Comfy dtype: COMBO + - Python dtype: str +- log_prompt + - 日志提示输入是启用日志记录的切换,这对于调试和理解节点的操作和生成的提示非常有用。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出提供了经过样式化的正面提示文本,它已根据选定的样式进行了格式化,增强了其影响力和可读性。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出提供了经过样式化的负面提示文本,它通过提供对比视角来补充正面文本,丰富了整体信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerMisc: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_misc.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyArtist.md b/docs/SDXLPromptStylerbyArtist.md new file mode 100644 index 0000000..640981a --- /dev/null +++ b/docs/SDXLPromptStylerbyArtist.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbyArtist +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在根据选定艺术家的风格来修饰文本提示,通过将艺术细微差别整合到生成内容中,增强创作过程。 + +# Input types +## Required +- text_positive + - 正面文本输入至关重要,因为它为节点设定了基础内容,确保生成的提示与期望的主题保持一致。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入作为正面文本的对比,允许节点通过排除不需要的元素来细化风格。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格参数至关重要,因为它决定了应用于文本的艺术影响,塑造输出的整体美学。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志选项允许监控节点的内部过程,提供关于如何将风格应用到提示的见解。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出提供了一个积极风格的文本提示,反映了所选艺术家的风格,并增强了创意信息。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出提供了一个负面风格的文本提示,通过提供对比视角来补充正面输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyArtist: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_artists.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyCamera.md b/docs/SDXLPromptStylerbyCamera.md new file mode 100644 index 0000000..2fffdf5 --- /dev/null +++ b/docs/SDXLPromptStylerbyCamera.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbyCamera +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在通过动态生成基于给定正面和负面文本输入的风格化提示,利用预定义的风格集来增强创作过程。它旨在激发和引导用户创作更具吸引力和针对性的内容。 + +# Input types +## Required +- text_positive + - 正面文本输入对于设定生成提示的期望基调和方向至关重要。它是应用风格化元素的基础,确保输出与预期的信息和情感保持一致。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入对于定义生成提示中应避免的方面至关重要。它通过排除可能削弱预期信息或语气的元素来帮助完善输出。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格参数对于从可用选项中选择适当的风格模板至关重要。它影响提示的整体美学和主题方向,确保生成的内容与所选风格保持一致。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志提示参数允许用户选择性地启用提示生成过程的日志记录。这个功能对于调试和理解节点的内部工作机制有益,提供了对最终输出如何形成的洞察。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出提供了一个精炼的正面提示文本,结合了选定的风格并排除了负面文本输入指定的不需要的元素。这个结果旨在用作创建与期望的语气和信息相一致内容的指南。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出提供了一个经过修改的负面提示文本,已调整以适应所选风格,确保最终内容不受削弱预期信息或语气的元素的影响。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyCamera: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_camera.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyComposition.md b/docs/SDXLPromptStylerbyComposition.md new file mode 100644 index 0000000..0aa10b1 --- /dev/null +++ b/docs/SDXLPromptStylerbyComposition.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: SDXLPromptStylerbyComposition +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +SDXLPromptStylerbyComposition节点旨在通过应用风格组合来增强提示的呈现。它通过将正面和负面文本输入与选定的风格集成,生成适合所选审美的精细提示文本。该节点强调了风格表达在提示制定中的重要性,旨在提升提示的总体质量和影响力。 + +# Input types +## Required +- text_positive + - text_positive参数是一个关键输入,它为提示提供了正面的上下文或肯定。它至关重要,因为它为风格化提示将要传达的正面特征设定了基调。这个输入直接影响节点的最终输出,塑造了正面提示文本。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - text_negative参数作为提示旨在抵消或减轻的负面上下文或陈述的输入。它的包含很重要,因为它允许节点生成一个平衡的提示,同时考虑正面和负面的观点。text_negative输入在制作负面提示文本中起着至关重要的作用。 + - Comfy dtype: STRING + - Python dtype: str +- style + - style参数决定了将应用于提示的风格组合。它是一个关键输入,因为它决定了提示的美学和主题方向。风格的选择对最终输出有深远的影响,指导着风格化提示的整体呈现和感觉。 + - Comfy dtype: STRING + - Python dtype: str +- log_prompt + - log_prompt参数是一个可选的切换,当设置为'Yes'时,它在执行期间启用提示的详细信息记录。这对于调试或查看提示是如何被风格化的很有用。它提供了对节点操作的透明度,而不会改变主要功能。 + - Comfy dtype: COMBO['No', 'Yes'] + - Python dtype: str + +# Output types +- positive_prompt_text_g + - positive_prompt_text_g输出代表了应用选定风格到输入文本后生成的风格化正面提示文本。它包含了旨在传达提示正面特征的精炼和主题化表达。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - negative_prompt_text_g输出提供了与正面提示相辅相成的风格化负面提示文本。它被制作出来是为了解决和减轻输入中概述的负面特征,有助于形成一个全面和平衡的提示呈现。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyComposition: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_composition.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyCyberpunkSurrealism.md b/docs/SDXLPromptStylerbyCyberpunkSurrealism.md new file mode 100644 index 0000000..18ba739 --- /dev/null +++ b/docs/SDXLPromptStylerbyCyberpunkSurrealism.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbyCyberpunkSurrealism +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点通过应用从精选集合中选择的模板,将输入文本创造性地转换为风格增强的提示,从而生成美学一致且主题丰富的内容。 + +# Input types +## Required +- text_positive + - 正面文本输入作为风格化转换的基础,提供了将被所选模板增强和塑造的内容。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入用于补充正面文本,为最终的风格化提示提供对比和深度。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格选择至关重要,因为它决定了提示样式化的主题和美学方向,指导转换过程。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志记录偏好决定了是否输出中间步骤和结果,有助于理解节点的运作和样式化过程。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出展示了正面风格化的文本,这是将所选模板应用于原始输入的结果,现在增强了主题和风格元素。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出包括负面风格化的文本,为正面文本提供了对比元素,丰富了整体的风格化输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyCyberpunkSurrealism: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_cs.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyDepth.md b/docs/SDXLPromptStylerbyDepth.md new file mode 100644 index 0000000..34ca0f8 --- /dev/null +++ b/docs/SDXLPromptStylerbyDepth.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: SDXLPromptStylerbyDepth +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +SDXLPromptStylerbyDepth节点旨在通过基于深度的风格化提示来增强用户体验。它智能地结合正面和负面文本输入以及所选风格,旨在生成更具吸引力和针对性的提示。该节点在创建与目标受众产生共鸣的提示中发挥着至关重要的作用,从而提高沟通的有效性。 + +# Input types +## Required +- text_positive + - text_positive参数至关重要,因为它提供了将由节点风格化的正面文本内容。它直接影响最终提示的语气和信息,是节点操作的关键组成部分。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - text_negative参数对于提供与正面文本形成对比的负面文本内容很重要。它有助于塑造提示的整体情感,是节点执行的重要因素。 + - Comfy dtype: STRING + - Python dtype: str +- style + - style参数至关重要,因为它决定了应用于文本的风格化方法。它决定了模板的选择和生成提示的整体美感,是节点功能的关键要素。 + - Comfy dtype: STRING + - Python dtype: str +- log_prompt + - log_prompt参数是可选的,用于控制节点在执行期间是否应该记录提示信息。这对于调试和监控节点的行为很有用,且不影响主要功能。 + - Comfy dtype: COMBO['No', 'Yes'] + - Python dtype: str + +# Output types +- positive_prompt_text_g + - positive_prompt_text_g输出代表了节点处理后的样式化正面文本。它是节点操作的关键结果,对随后在各种应用中的使用具有重要意义。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - negative_prompt_text_g输出代表了由节点生成的样式化负面文本。它补充了正面文本,是创建平衡和细腻提示的节点输出的重要方面。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyDepth: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_depth.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyEnvironment.md b/docs/SDXLPromptStylerbyEnvironment.md new file mode 100644 index 0000000..e998c94 --- /dev/null +++ b/docs/SDXLPromptStylerbyEnvironment.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: SDXLPromptStylerbyEnvironment +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +SDXLPromptStylerbyEnvironment 类旨在根据预定义的风格和模板集对提示进行风格化。它接受正面和负面的文本输入以及选定的风格,并据此生成风格化的提示。该节点还提供了一个选项来记录提示以供审查。 + +# Input types +## Required +- text_positive + - text_positive 参数是一个字符串,代表提示的正面内容。它对于节点生成风格化的正面提示至关重要,并在整体输出中扮演重要角色。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - text_negative 参数是一个字符串,代表提示的负面内容。它用于创建风格化的负面提示,对节点的功能至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- style + - style 参数决定了应用于提示的风格化方法。它是一个字符串,从列表中选择一个预定义的风格,对节点的运行至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- log_prompt + - log_prompt 参数是一个可选选项,允许用户决定是否记录生成的提示。它通过启用或禁用记录功能来影响节点的行为。 + - Comfy dtype: COMBO['No', 'Yes'] + - Python dtype: str + +# Output types +- positive_prompt_text_g + - positive_prompt_text_g 输出是由节点生成的风格化的正面提示文本。它是节点执行的重要结果,反映了输入的正面内容。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - negative_prompt_text_g 输出是由节点生成的风格化的负面提示文本。它代表了节点对输入提示负面内容的输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyEnvironment: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_environment.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyFantasySetting.md b/docs/SDXLPromptStylerbyFantasySetting.md new file mode 100644 index 0000000..b303d4c --- /dev/null +++ b/docs/SDXLPromptStylerbyFantasySetting.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: SDXLPromptStylerbyFantasySetting +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +SDXLPromptStylerbyFantasySetting节点旨在基于幻想设定来风格化提示。它创造性地结合了积极和消极的文本输入以及所选的风格,生成与所选幻想主题一致的风格化提示。该节点在增强幻想背景下提示的主题一致性和参与度方面发挥着至关重要的作用。 + +# Input types +## Required +- text_positive + - text_positive参数是提供要风格化的积极上下文或肯定的关键元素。它对于设定最终提示的基调至关重要,并显著影响主题结果。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - text_negative参数是可选的,允许包含可以与积极文本创造性对比的负面上下文。这可以为风格化的提示增添深度和复杂性。 + - Comfy dtype: STRING + - Python dtype: str +- style + - style参数决定了提示将与之风格化的幻想设定。它是一个关键输入,定义了风格化过程的主题方向。 + - Comfy dtype: STRING + - Python dtype: str +- log_prompt + - log_prompt参数是一个可选的切换,当设置为'Yes'时,将启用对风格、文本输入和生成的风格化提示的记录。这对于调试或审查风格化过程非常有用。 + - Comfy dtype: COMBO['No', 'Yes'] + - Python dtype: str + +# Output types +- positive_prompt_text_g + - positive_prompt_text_g输出代表了已风格化的积极性提示文本,它已被创造性地调整以适应所选的幻想设定,增强了主题吸引力。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - negative_prompt_text_g输出提供了风格化的消极提示文本,它通过在幻想设定中提供对比元素来补充积极提示。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyFantasySetting: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_fs.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyFilter.md b/docs/SDXLPromptStylerbyFilter.md new file mode 100644 index 0000000..7ccccda --- /dev/null +++ b/docs/SDXLPromptStylerbyFilter.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbyFilter +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点基于提供的正面和负面文本输入,动态地对提示进行样式设计,使用指定的样式模板生成精炼且针对性的消息。 + +# Input types +## Required +- text_positive + - 正面文本输入非常重要,因为它设定了期望消息的基调。它被用来创建一个精炼且针对性的正面提示。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入对于定义消息中应避免的对比元素至关重要。它有助于创建一个平衡正面和负面方面的细致提示。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 样式参数在确定生成提示的整体美学和传达方式方面至关重要。它指导输入文本的转换,使其成为一个连贯且风格一致的输出。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志提示选项允许对提示生成过程进行可选的日志记录,提供透明度和对提示样式和构建方式的洞察。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出的正面提示文本是样式设计过程的结果,以精炼和引人入胜的方式封装了期望的消息。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出的负面提示文本为正面提示提供了平衡,确保消息全面且解决了潜在的关注点或异议。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyFilter: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_filter.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyFocus.md b/docs/SDXLPromptStylerbyFocus.md new file mode 100644 index 0000000..2285fb4 --- /dev/null +++ b/docs/SDXLPromptStylerbyFocus.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbyFocus +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在通过应用特定的样式模板来增强提示的呈现,从而通过量身定制和视觉上吸引人的文本格式提高用户体验和参与度。 + +# Input types +## Required +- text_positive + - 正面文本输入至关重要,因为它为提示的积极方面设定了基础。这是将被风格化并呈现给用户的内容,旨在引发积极反应。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入对于提供提示的对比元素至关重要,允许更细致和平衡的呈现。它通过提供不同的视角来补充正面文本。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- style + - 样式输入是决定提示的审美和结构格式的关键组成部分。它指导文本转变为视觉上吸引人和连贯的信息。 + - Comfy dtype: COMBO + - Python dtype: str +- log_prompt + - 日志提示输入作为调试工具,用于记录提示的细节以供分析和审查。它有助于完善节点的功能并确保最佳输出。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出提供风格化的正面提示文本,根据选定的样式模板进行了格式化,增强了信息的可读性和吸引力。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出提供风格化的负面提示文本,通过提供对比视角来补充正面提示,从而有助于全面和平衡的沟通。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyFocus: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_focus.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyImpressionism.md b/docs/SDXLPromptStylerbyImpressionism.md new file mode 100644 index 0000000..34bfc07 --- /dev/null +++ b/docs/SDXLPromptStylerbyImpressionism.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbyImpressionism +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点通过应用受印象派启发的风格模板,创造性地转换输入文本,增强文本的审美和主题深度。 + +# Input types +## Required +- text_positive + - 正面文本输入作为风格转换的基础,提供了将被赋予印象派特质的内容。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入用于与正面文本形成对比,可能会为最终的风格化输出增加深度和复杂性。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 从预定义的印象派风格模板中选择的样式决定了文本转换的整体基调和方向。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 此参数控制是否记录样式化过程的中间步骤和结果,有助于理解节点的操作和输出。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出展示了积极风格化的文本,现在融入了所选的印象派风格,可供进一步使用或展示。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出包括负面风格化的文本,它补充了正面输出,并可能提供对比视角或额外上下文。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyImpressionism: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_impressionism.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyLighting.md b/docs/SDXLPromptStylerbyLighting.md new file mode 100644 index 0000000..7846c02 --- /dev/null +++ b/docs/SDXLPromptStylerbyLighting.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbyLighting +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在通过应用样式模板来增强提示的展示,目的是提高文本的可读性和吸引力。 + +# Input types +## Required +- text_positive + - 此参数是需要被节点样式化的正面文本,是增强展示的基础。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 此参数是需要与正面文本结合的负面文本,为最终样式化输出增加对比和深度。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 此参数决定了要应用的样式模板,显著影响样式化提示的整体美学和语调。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 此参数控制是否记录中间步骤和结果,有助于调试和理解节点的操作。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出是经过样式化的正面文本,通过所选模板增强了其视觉吸引力和有效性。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出是经过样式化的负面文本,补充正面文本,并为样式化信息的全面性做出贡献。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyLighting: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_lighting.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyMileHigh.md b/docs/SDXLPromptStylerbyMileHigh.md new file mode 100644 index 0000000..a71095b --- /dev/null +++ b/docs/SDXLPromptStylerbyMileHigh.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: SDXLPromptStylerbyMileHigh +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +SDXLPromptStylerbyMileHigh节点旨在根据预定义的样式对文本提示进行风格化。它接受正面和负面的文本输入以及所选的样式标识符,并据此生成风格化的提示。该节点还可以记录输入和输出以供审查,这对于调试或透明度目的非常有用。 + +# Input types +## Required +- text_positive + - 正面文本输入对于定义提示的乐观方面至关重要。它显著影响风格化输出的语气和方向。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入与正面文本形成对比,提供了一个可以用于完善提示风格的对立面。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 样式参数决定了应用于文本的风格模板。对于根据用户需求实现所需的提示风格至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- log_prompt + - 当log_prompt参数设置为'Yes'时,将启用提示过程的记录。这对于监控和审查节点的操作可能很有益处。 + - Comfy dtype: COMBO['No', 'Yes'] + - Python dtype: str + +# Output types +- positive_prompt_text_g + - positive_prompt_text_g输出代表了风格化的正面文本提示,这是节点执行的关键结果。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - negative_prompt_text_g输出提供了风格化的负面文本提示,与正面提示相辅相成,以给出完整的风格化输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyMileHigh: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_mh.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyMood.md b/docs/SDXLPromptStylerbyMood.md new file mode 100644 index 0000000..78085d4 --- /dev/null +++ b/docs/SDXLPromptStylerbyMood.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbyMood +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在基于情绪来风格化提示,增强文本输入的主题表达。它利用预定义的风格来创造性地修改提供的文本的情感,旨在丰富内容的整体叙事和情感深度。 + +# Input types +## Required +- text_positive + - 正面文本输入对于设定提示的基本情绪至关重要。它是情绪化风格增强的基础,显著影响最终输出的语气和情感共鸣。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入对于提供与正面文本对比的情绪至关重要。它允许节点创建更加细腻和平衡的情感表达,有助于风格化提示的复杂性和深度。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格参数在确定风格化提示的审美和情感方向中起着关键作用。它指导节点选择适当的基于情绪的模板,这对于实现所需的主题和风格结果至关重要。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志提示参数通过可选地启用提示生成过程的记录来促进调试和监督。这个功能有助于理解节点的操作,并确保风格转换的透明度。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出提供了输入文本的积极风格化版本,反映了所选情绪和风格增强。这个结果在传递情感共鸣和主题一致的叙事中非常重要。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出提供了输入文本的负面风格化版本,为正面提示提供了对比视角。它在建立风格化内容中全面的情感范围和深度方面起着至关重要的作用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyMood: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_mood.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyMythicalCreature.md b/docs/SDXLPromptStylerbyMythicalCreature.md new file mode 100644 index 0000000..d430c93 --- /dev/null +++ b/docs/SDXLPromptStylerbyMythicalCreature.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbyMythicalCreature +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点通过应用风格化模板来增强提示的呈现,旨在提高用户参与度和响应质量。 + +# Input types +## Required +- text_positive + - 正面文本输入对于生成乐观和鼓励性的提示至关重要,它显著影响输出的语气和有效性。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入对于提供对比视角至关重要,有助于打造平衡且细腻的提示。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格选择参数至关重要,因为它决定了提示的主题框架,指导整体美学和信息传递。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志记录偏好允许对节点处理进行可选的可见性,有助于调试和理解节点的操作。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出提供一个积极风格的提示,旨在提升和激励,代表节点功能的关键组成部分。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出提供一个负面风格的提示,提供对比点并促进与内容的全面互动。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyMythicalCreature: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_mc.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyOriginal.md b/docs/SDXLPromptStylerbyOriginal.md new file mode 100644 index 0000000..691dd94 --- /dev/null +++ b/docs/SDXLPromptStylerbyOriginal.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbyOriginal +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在基于预定义模板来美化提示,增强内容的展示效果和吸引力。 + +# Input types +## Required +- text_positive + - 正面文本输入至关重要,因为它构成了美化提示的基础。这是将根据所选样式进行格式化的内容。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入对于提供与正面文本对比的元素至关重要,允许更细致和全面的提示。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 样式参数在确定将应用于提示的审美和结构元素方面至关重要,指导整体的外观和感觉。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志记录选项允许选择性记录提示生成过程,这对于调试和审查目的非常有益。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出提供美化后的正面提示,这是原始输入文本的格式化和增强版本。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出提供美化后的负面提示,为正面提示提供补充视角,丰富整体信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyOriginal: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_original.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyQuantumRealism.md b/docs/SDXLPromptStylerbyQuantumRealism.md new file mode 100644 index 0000000..d679ba9 --- /dev/null +++ b/docs/SDXLPromptStylerbyQuantumRealism.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbyQuantumRealism +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在根据预定义的风格对提示进行样式化,增强文本的主题和审美展示,同时不改变其核心信息。 + +# Input types +## Required +- text_positive + - 正面文本输入对于生成正面框架的提示至关重要。它是应用风格化元素的基础。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入对于提供与正面文本对比的元素至关重要,使节点能够创建更细致和平衡的提示。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格参数在确定风格化提示的整体审美和主题方向方面起着关键作用,指导转换过程。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志提示选项允许对提示生成过程进行可选记录,这对于调试和理解节点的运作非常有益。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出提供了一个风格化增强的正面提示,反映了输入文本与所选风格的融合。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出提供了一个风格化增强的负面提示,为正面提示提供了对照点,并有助于全面展示。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyQuantumRealism: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_qr.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbySteamPunkRealism.md b/docs/SDXLPromptStylerbySteamPunkRealism.md new file mode 100644 index 0000000..4037aaf --- /dev/null +++ b/docs/SDXLPromptStylerbySteamPunkRealism.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbySteamPunkRealism +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在基于预定义的蒸汽朋克现实主义风格集对提示进行风格化,通过整合蒸汽朋克流派特有的风格元素和叙事主题,增强输入文本的主题内容。 + +# Input types +## Required +- text_positive + - 正面文本输入至关重要,因为它提供了节点应用蒸汽朋克现实主义风格的基本内容。这是将被增强和转换以反映所需主题风格的文本。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入作为正面文本的对比,允许节点通过整合特定不希望出现在最终输出中的元素来微调风格化转换。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格参数至关重要,因为它决定了节点将应用于输入文本的主题方向和审美选择。它是风格化转换过程背后的指导力量。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志提示参数是一个可选设置,允许用户记录转换过程,提供节点如何将蒸汽朋克现实主义风格应用于输入文本的见解。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出是积极风格化的文本,已经转换为体现蒸汽朋克现实主义风格,准备用于各种创意应用。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出是负面风格化的文本,通过提供与正面输出形成对比的元素,有助于完善最终产品的主题内容和美学。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbySteamPunkRealism: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_sr.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbySubject.md b/docs/SDXLPromptStylerbySubject.md new file mode 100644 index 0000000..a013089 --- /dev/null +++ b/docs/SDXLPromptStylerbySubject.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: SDXLPromptStylerbySubject +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +SDXLPromptStylerbySubject节点旨在根据给定的主题对提示进行风格化。它接受正面和负面的文本输入,并应用选定的风格来生成风格化的提示。该节点能够记录过程以供审查,增强提示的定制和个性化。 + +# Input types +## Required +- text_positive + - text_positive参数是一个字符串,代表提示的积极方面。它对于定义风格化输出的乐观基调至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - text_negative参数是一个字符串,代表提示的消极方面。它在塑造风格化输出的悲观基调中起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +- style + - style参数决定了应用于提示的风格化方法。它是风格化提示的整体风格和呈现方式的关键因素。 + - Comfy dtype: STRING + - Python dtype: str +- log_prompt + - log_prompt参数是一个可选选项,允许记录风格化过程。它可以设置为'Yes',以便详细审查转换过程。 + - Comfy dtype: COMBO['No', 'Yes'] + - Python dtype: str + +# Output types +- positive_prompt_text_g + - positive_prompt_text_g输出是提示的风格化正面文本,反映了应用的风格和输入的乐观视角。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - negative_prompt_text_g输出是提示的风格化负面文本,体现了应用的风格和输入的悲观视角。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbySubject: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_subject.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbySurrealism.md b/docs/SDXLPromptStylerbySurrealism.md new file mode 100644 index 0000000..452ed95 --- /dev/null +++ b/docs/SDXLPromptStylerbySurrealism.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbySurrealism +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点通过应用受超现实主义启发的风格模板,创造性地重新设计输入文本提示,增强生成内容的表达性和艺术品质。 + +# Input types +## Required +- text_positive + - 正面文本输入作为风格化过程的基础,其内容被转换以反映所选的超现实主义风格。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入用于对比和完善风格化,确保最终输出连贯并与期望的审美相符。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 选定的风格决定了应用于文本的超现实主义方法,指导转换过程并塑造创意方向。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 此切换确定是否记录过程和结果,提供对风格化过程和生成提示的洞察。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出展示了积极风格化的文本,现在融入了所选的超现实主义元素,可供进一步使用或展示。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出包括负面风格化的文本,它补充了正面输出,并为风格化内容的整体连贯性和深度做出了贡献。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbySurrealism: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_surrealism.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyTheme.md b/docs/SDXLPromptStylerbyTheme.md new file mode 100644 index 0000000..b7850c8 --- /dev/null +++ b/docs/SDXLPromptStylerbyTheme.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: SDXLPromptStylerbyTheme +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +SDXLPromptStylerbyTheme 类旨在根据预定义的主题对提示进行风格化。它利用包含样式和模板的 JSON 文件来生成风格化的正面和负面提示,增强文本输入的主题一致性。 + +# Input types +## Required +- text_positive + - text_positive 参数是一个字符串,代表提示的正面内容。它至关重要,因为它构成了风格化正面提示输出的基础。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - text_negative 参数是一个字符串,代表提示的负面内容。它在塑造风格化负面提示输出中起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +- style + - style 参数决定了应用于提示的主题风格。它是提示外观和语调定制的关键因素。 + - Comfy dtype: STRING + - Python dtype: str +- log_prompt + - log_prompt 参数是可选设置,当设置为 'Yes' 时,可以启用提示风格化过程的日志记录,用于调试或审查目的。 + - Comfy dtype: COMBO['No', 'Yes'] + - Python dtype: str + +# Output types +- positive_prompt_text_g + - positive_prompt_text_g 输出是风格化的正面提示文本,旨在与指定的主题保持一致,并增强信息的整体吸引力。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - negative_prompt_text_g 输出是风格化的负面提示文本,旨在反映指定的主题并保持信息的主题完整性。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyTheme: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_themes.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyTimeofDay.md b/docs/SDXLPromptStylerbyTimeofDay.md new file mode 100644 index 0000000..c6ee651 --- /dev/null +++ b/docs/SDXLPromptStylerbyTimeofDay.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbyTimeofDay +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点根据当前的时辰动态地对提示进行样式设计,通过根据当前时间的上下文来定制信息的展示,增强用户交互体验。 + +# Input types +## Required +- text_positive + - 正面文本输入非常重要,因为它设定了根据所选时间定制和展示的正面情绪的基线。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入对于提供与正面文本对比的情绪至关重要,使节点能够平衡风格化提示的整体语气。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 样式参数在决定根据时间定制提示的样式方面起着关键作用,影响输出的整体美学和情绪。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 记录提示参数是开发人员和测试人员的实用工具,使他们能够输出有关样式化过程的详细信息,以便进行调试和验证。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出包含正面风格的文本,已经格式化以与所选时间相匹配,通过定制的消息传递增强用户的体验。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出包括负面风格的文本,通过提供对比情绪来补充正面文本,有助于细致入微地展示提示。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyTimeofDay: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_tod.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptStylerbyWyvern.md b/docs/SDXLPromptStylerbyWyvern.md new file mode 100644 index 0000000..c43f22c --- /dev/null +++ b/docs/SDXLPromptStylerbyWyvern.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptStylerbyWyvern +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在基于预定义模板对提示进行样式化,增强内容的展示和吸引力。它通过将正面和负面文本输入与选定的样式相结合,旨在创建一个连贯且主题一致的输出。 + +# Input types +## Required +- text_positive + - 正面文本输入对于设定提示的肯定基调至关重要。它是风格化元素从选定模板中应用的基础,显著影响最终输出的有效性。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入通过提供对比内容来补充正面文本。它与风格模板的整合对于创建一个平衡且细致的提示至关重要,能够解决潜在的反驳点或限制。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 样式参数在确定提示的整体美学和主题方向上起着关键作用。它指导模板的选择,并决定正面和负面文本的格式化和呈现方式。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志提示参数允许对样式化过程进行可选的日志记录。启用后,它提供了节点操作的透明度,有助于调试并确保实现所需的样式。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出代表经过样式化的正面提示文本,已根据选定的样式模板和输入的正面文本进行格式化。这个输出对于节点增强内容展示的目的至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出包括经过样式化的负面提示文本,通过解决潜在的反驳或限制来补充正面输出。它是节点功能的关键组成部分,确保全面且平衡的展示。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptStylerbyWyvern: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_wyvern.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptbyCelticArt.md b/docs/SDXLPromptbyCelticArt.md new file mode 100644 index 0000000..eca6b07 --- /dev/null +++ b/docs/SDXLPromptbyCelticArt.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: SDXLPromptbyCelticArt +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +SDXLPromptbyCelticArt节点旨在基于凯尔特艺术主题生成风格化文本提示。它创造性地结合正面和负面文本输入以及所选风格,以产生主题化提示。该节点在增强各种应用的文本输出的主题丰富性方面发挥着关键作用,例如艺术生成或主题文本样式化。 + +# Input types +## Required +- text_positive + - text_positive参数对于定义提示的积极方面至关重要。它显著影响最终风格化提示的语气和内容,确保输出与所需的积极主题元素一致。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - text_negative参数允许在提示中包含负面方面。对于提供对比和深度至风格化文本至关重要,丰富了整体的主题表达。 + - Comfy dtype: STRING + - Python dtype: str +- style + - style参数决定了要应用于提示的凯尔特艺术的主题风格。它是形成文本审美和主题结果的关键因素,确保它与所选择的艺术主题产生共鸣。 + - Comfy dtype: STRING + - Python dtype: str +- log_prompt + - log_prompt参数是可选的,控制是否记录提示样式化过程的中间步骤。这对于调试或希望查看转换过程的用户来说可能是有用的。 + - Comfy dtype: COMBO['No', 'Yes'] + - Python dtype: str + +# Output types +- positive_prompt_text_g + - positive_prompt_text_g输出代表最终的风格化正面提示文本,是节点功能的关键元素。它包含了输入文本与所选风格的创造性融合,产生了主题丰富的文本输出。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - negative_prompt_text_g输出提供了最终的风格化负面提示文本,补充了正面提示。它在为整体提示增加复杂性和细微差别方面发挥着重要作用,有助于更全面的主题表现。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptbyCelticArt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_celticart.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptbyContemporaryNordicArt.md b/docs/SDXLPromptbyContemporaryNordicArt.md new file mode 100644 index 0000000..5b1cb07 --- /dev/null +++ b/docs/SDXLPromptbyContemporaryNordicArt.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: SDXLPromptbyContemporaryNordicArt +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +SDXLPromptbyContemporaryNordicArt节点旨在基于当代北欧艺术风格生成和风格化提示。它创造性地结合了积极和消极的文本输入以及选定的艺术风格,以产生可以用于各种创意或描述性目的的审美启发式提示。 + +# Input types +## Required +- text_positive + - text_positive参数是节点的关键输入,提供了将被艺术性整合到提示中的积极背景或肯定。它显著影响生成提示的基调和内容,确保其与所需的积极信息一致。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - text_negative参数允许包含消极背景,这可以在提示中进行艺术性的对比或转换。虽然不是必需的,但它可以通过提供与积极文本相对的观点,为最终输出增加深度。 + - Comfy dtype: STRING + - Python dtype: str +- style + - style参数是必需的,因为它决定了将应用于提示的特定当代北欧艺术风格。风格选择直接影响生成提示的美学和主题元素,指导其整体艺术方向。 + - Comfy dtype: STRING + - Python dtype: str +- log_prompt + - log_prompt参数是一个可选的切换,当设置为'Yes'时,启用提示生成过程的记录。这对于调试或查看创建最终提示所采取的中间步骤非常有用。 + - Comfy dtype: COMBO['No', 'Yes'] + - Python dtype: str + +# Output types +- positive_prompt_text_g + - positive_prompt_text_g输出包含由节点生成的风格化的积极提示文本。它代表了输入文本与所选北欧艺术风格的艺术融合,可供各种应用使用。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - negative_prompt_text_g输出提供了风格化的消极提示文本,通过提供对比或转换的视角来补充积极提示。它是节点输出的一个组成部分,有助于生成提示的全面性。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptbyContemporaryNordicArt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_contempnordic.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptbyFashionArt.md b/docs/SDXLPromptbyFashionArt.md new file mode 100644 index 0000000..ade5dfb --- /dev/null +++ b/docs/SDXLPromptbyFashionArt.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptbyFashionArt +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在通过基于正面和负面文本输入生成受时尚启发的提示来增强创作过程。它利用预定义的风格集来制作可以激发设计师和艺术家灵感的提示,旨在促进时尚创作中的创新和多样性。 + +# Input types +## Required +- text_positive + - 正面文本输入作为创意提示的基础,提供了一个建设性和令人振奋的信息,将被整合到最终的风格化提示中。它对于设定时尚灵感的基调和方向至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入用于与正面信息形成对比,为最终提示增加深度和复杂性。它通过强调需要避免或克服的领域,有助于创建一个更加细致和吸引人的时尚概念。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格参数对于引导文本输入转换为一个连贯和主题化的时尚提示至关重要。它影响输出的语言、语调和结构,确保最终的提示与选定的时尚美学相一致。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志提示选项允许对生成的提示进行可选记录,这对于审查和改进非常有益处。它有助于跟踪创作过程,并确保节点的功能符合用户的期望。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出提供了一个经过精炼和风格化处理的正面提示,融合了用户的输入和选定的时尚风格。它是推动创意方向的关键组成部分,并作为进一步时尚设计探索的催化剂。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 负面提示输出通过提供对比点和额外考虑来补充正面提示。它通呈现更全面的时尚概念视图,丰富了整体的创意输出,鼓励对设计采取平衡和知情的方法。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptbyFashionArt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_fashion.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptbyGothicRevival.md b/docs/SDXLPromptbyGothicRevival.md new file mode 100644 index 0000000..11f9853 --- /dev/null +++ b/docs/SDXLPromptbyGothicRevival.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptbyGothicRevival +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在基于预定义的哥特复兴风格集对文本提示进行风格化,增强输入文本的主题和审美元素。它将风格整合到文本中,创造出独特且文化共鸣的输出,反映出所选历史美学。 + +# Input types +## Required +- text_positive + - 正面文本输入至关重要,因为它设定了风格化转换的基础。它是将根据所选的哥特复兴风格进行增强和塑造的文本,确保最终输出与期望的主题方向一致。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入作为正面文本的平衡,为风格化过程提供对比和深度。它确保最终输出不仅美观,而且在主题上也是健全和多面的。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格参数是节点功能的核心,决定了风格化的审美和主题方向。它是将输入文本转换为体现所选哥特复兴风格本质的作品的参考点。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志提示参数对于风格化过程中的调试和透明度至关重要。启用时,它提供转换过程的详细日志,确保每一步都被记录并可以进行质量和准确性的审查。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 正面提示文本,现已根据所选的哥特复兴美学风格进行了风格化,是节点的主要输出。它是节点将输入文本转换和提升到新的理论和风格意义水平的直接反映。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 同样风格化的负面提示文本,通过提供对比视角来补充正面输出。它是节点输出的一个不可或缺的部分,展示了风格化转换的深度和广度。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptbyGothicRevival: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_gothrev.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptbyIrishFolkArt.md b/docs/SDXLPromptbyIrishFolkArt.md new file mode 100644 index 0000000..2e9dff8 --- /dev/null +++ b/docs/SDXLPromptbyIrishFolkArt.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptbyIrishFolkArt +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点创造性地将输入文本适配为爱尔兰民间艺术风格,增强文本的主题表达和文化共鸣。 + +# Input types +## Required +- text_positive + - 正面文本输入对于生成风格增强的输出至关重要,能够捕捉到爱尔兰民间艺术的精髓。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入对于精炼输出非常关键,确保输出严格遵守爱尔兰民间艺术风格。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格参数至关重要,它决定了艺术方向和将融入文本的文化元素。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志选项允许选择性地可视化转换过程,有助于理解节点的功能。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出提供了一个体现爱尔兰民间艺术精神的正面风格化文本,可供进一步使用或分析。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出包括一个负面风格化的文本,为正面文本提供了对比元素,以便进行全面的风格评估。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptbyIrishFolkArt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_irishfolkart.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptbyRomanticNationalismArt.md b/docs/SDXLPromptbyRomanticNationalismArt.md new file mode 100644 index 0000000..925bceb --- /dev/null +++ b/docs/SDXLPromptbyRomanticNationalismArt.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptbyRomanticNationalismArt +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点根据浪漫民族主义艺术原则,将输入文本创造性地适配到指定风格,增强原始文本的主题内容和情感表达。 + +# Input types +## Required +- text_positive + - 正面文本输入至关重要,因为它为风格转换设定了基础。这是将被增强并适配到所选风格的文本。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入作为正面文本的对比,提供了可以整合到最终风格化提示中的对照点。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格参数至关重要,它决定了文本转换的主题和情感方向,指导节点产生风格一致的输出。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志选项允许选择性地可视化转换过程,提供节点如何实现其风格适应的见解。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出展示了增强后的正面文本,现在融入了所选风格,准备进一步使用或分析。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 适应后的负面文本补充了正面输出,提供了对比视角,可以丰富整体的主题深度。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptbyRomanticNationalismArt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_romanticnat.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptbySportsArt.md b/docs/SDXLPromptbySportsArt.md new file mode 100644 index 0000000..cec4ea8 --- /dev/null +++ b/docs/SDXLPromptbySportsArt.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptbySportsArt +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在基于体育主题来风格化文本提示,增强提示的主题内容和参与度。 + +# Input types +## Required +- text_positive + - 正面文本输入非常重要,因为它设定了体育主题积极方面的基调,这些方面将被融入风格化的提示中。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入对于提供一个与正面文本对比的元素至关重要,允许风格化的提示更加细致和平衡。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格参数在确定与体育相关的提示的主题方向上起着关键作用,确保内容与选定的体育主题保持一致。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志参数允许在节点执行期间选择性地输出详细信息,提供模板替换过程的洞察。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出提供了一个融入了选定体育主题的正面风格化提示,增强了用户与内容的互动。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出提供了一个与正面文本对比的负面风格化提示,提供了体育主题的全面视角。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptbySportsArt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_sports.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptbyStreetArt.md b/docs/SDXLPromptbyStreetArt.md new file mode 100644 index 0000000..f69f399 --- /dev/null +++ b/docs/SDXLPromptbyStreetArt.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptbyStreetArt +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点将输入文本与指定风格相匹配,通过从街头艺术中提取的风格元素增强主题内容。 + +# Input types +## Required +- text_positive + - 该参数提供将根据所选街头艺术主题进行风格化的正面文本,作为创意改编过程的基础。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 该参数包含与正面文本形成对比的负面文本,使节点能够专注于所需的风格元素,不受干扰。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 该参数定义了要应用的街头艺术风格,指导节点选择适当的模板和艺术元素进行文本转换。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 该参数启用或禁用样式化过程的日志记录,提供了一种跟踪转换和调试可能出现的任何问题的方法。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出包含正面风格化的文本,转换为反映所选街头艺术风格,增强主题表达和艺术吸引力。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出提供负面风格化的文本,作为正面文本的对比元素,确保最终呈现的清晰度和专注度。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptbyStreetArt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_street.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptbyVikingArt.md b/docs/SDXLPromptbyVikingArt.md new file mode 100644 index 0000000..9a4a3bd --- /dev/null +++ b/docs/SDXLPromptbyVikingArt.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptbyVikingArt +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点基于给定的正面和负面文本输入,利用来自维京艺术主题的指定风格动态生成风格化提示。它旨在通过将主题元素整合到生成的内容中来增强创作过程。 + +# Input types +## Required +- text_positive + - 正面文本输入对于设定生成提示的肯定基调至关重要。它提供了将被风格化增强的基础内容,以符合所选的维京艺术主题。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入对于定义生成提示中应避免的方面至关重要。它有助于优化输出,确保其遵循期望的主题方向,而不包含不想要的元素。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格参数在确定提示的主题方向中起着关键作用。它指导节点选择与所选维京艺术风格相呼应的适当模板和语言元素。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志提示参数允许对提示生成过程进行可选记录。启用后,它提供了有关节点如何运作以及应用于输入文本的转换的有价值的见解。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出包含正面风格化的提示文本,已经通过维京艺术风格的主题元素进行了增强,提供了一个创造性和引人入胜的结果。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出呈现负面风格化的提示文本,已经调整以排除不需要的元素,确保最终输出符合指定的主题要求。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptbyVikingArt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_viking.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SDXLPromptbyWildlifeArt.md b/docs/SDXLPromptbyWildlifeArt.md new file mode 100644 index 0000000..bdc06b7 --- /dev/null +++ b/docs/SDXLPromptbyWildlifeArt.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SDXLPromptbyWildlifeArt +- Category: Style Prompts +- Output node: False +- Repo Ref: https://github.com/wolfden/ComfyUi_PromptStylers + +该节点旨在根据选定的野生动物艺术风格来修饰文本提示,通过生成主题化的正面和负面提示来增强创作过程。 + +# Input types +## Required +- text_positive + - 正面文本输入对于生成主题化的正面提示至关重要,它是风格化过程的基础。 + - Comfy dtype: STRING + - Python dtype: str +- text_negative + - 负面文本输入对于创建对比鲜明的负面提示至关重要,它补充了正面提示并丰富了整体主题表达。 + - Comfy dtype: STRING + - Python dtype: str +- style + - 风格选择参数至关重要,因为它决定了将应用于正面和负面提示的艺术主题,指导整体输出的美学。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- log_prompt + - 日志参数通过可选地提供详细的样式化过程和结果的打印输出,便于调试和监督。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- positive_prompt_text_g + - 输出的正面提示是一个创造性增强的文本,反映了所选择的野生动物艺术风格,作为进一步内容开发的 thematic 基础。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt_text_g + - 输出的负面提示提供了一个对比鲜明的主题元素,为正面提示提供了一个对立面,丰富了叙述范围。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SDXLPromptbyWildlifeArt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(self): + p = os.path.dirname(os.path.realpath(__file__)) + file_path = os.path.join(p, 'sdxl_styles_wildlife.json') + self.json_data = read_json_file(file_path) + styles = read_sdxl_styles(self.json_data) + return {'required': {'text_positive': ('STRING', {'default': '', 'multiline': True}), 'text_negative': ('STRING', {'default': '', 'multiline': True}), 'style': (styles,), 'log_prompt': (['No', 'Yes'], {'default': 'No'})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive_prompt_text_g', 'negative_prompt_text_g') + FUNCTION = 'prompt_styler' + CATEGORY = 'Style Prompts' + + def prompt_styler(self, text_positive, text_negative, style, log_prompt): + (positive_prompt, negative_prompt) = read_sdxl_templates_replace_and_combine(self.json_data, style, text_positive, text_negative) + if log_prompt == 'Yes': + print(f'style: {style}') + print(f'text_positive: {text_positive}') + print(f'text_negative: {text_negative}') + print(f'positive_prompt: {positive_prompt}') + print(f'negative_prompt: {negative_prompt}') + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/SEGSDetailer.md b/docs/SEGSDetailer.md new file mode 100644 index 0000000..1523dab --- /dev/null +++ b/docs/SEGSDetailer.md @@ -0,0 +1,99 @@ +# Documentation +- Class name: SEGSDetailer +- Category: ImpactPack/Detailer +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSDetailer节点旨在根据分割信息增强图像的细节。它通过缩放和处理图像的片段来提高其视觉质量,特别适用于需要精细细节的应用场景。该节点利用先进的深度学习模型实现这种增强,从而得到更精细和详细的输出图像。 + +# Input types +## Required +- image + - 输入图像,将由SEGSDetailer节点处理。它作为细节增强过程的主要数据源,对于实现期望的结果至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- segs + - 提供图像结构信息的分割数据。此输入对于节点了解图像的哪些部分需要专注于细节增强至关重要。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +## Optional +- guide_size + - 引导尺寸参数决定了细节增强过程的缩放因子。它影响图像片段在增强前被放大的程度,从而影响最终输出的细节水平。 + - Comfy dtype: FLOAT + - Python dtype: float +- steps + - 在细节增强过程中要执行的步骤数量。更多的步骤通常会导致更精细的输出,但也可能增加计算时间。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- segs + - 基于输入图像和分割信息增强细节后的输出分割数据。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +- cnet_images + - 在细节增强过程中生成的控制网图像列表,可用于进一步分析或可视化。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SEGSDetailer: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'segs': ('SEGS',), 'guide_size': ('FLOAT', {'default': 256, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'guide_size_for': ('BOOLEAN', {'default': True, 'label_on': 'bbox', 'label_off': 'crop_region'}), 'max_size': ('FLOAT', {'default': 768, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), '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}), 'noise_mask': ('BOOLEAN', {'default': True, 'label_on': 'enabled', 'label_off': 'disabled'}), 'force_inpaint': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'}), 'basic_pipe': ('BASIC_PIPE',), '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': {'refiner_basic_pipe_opt': ('BASIC_PIPE',), '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 = ('SEGS', 'IMAGE') + RETURN_NAMES = ('segs', 'cnet_images') + OUTPUT_IS_LIST = (False, True) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detailer' + + @staticmethod + def do_detail(image, segs, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, denoise, noise_mask, force_inpaint, basic_pipe, refiner_ratio=None, batch_size=1, cycle=1, refiner_basic_pipe_opt=None, inpaint_model=False, noise_mask_feather=0): + (model, clip, vae, positive, negative) = basic_pipe + if refiner_basic_pipe_opt is None: + (refiner_model, refiner_clip, refiner_positive, refiner_negative) = (None, None, None, None) + else: + (refiner_model, refiner_clip, _, refiner_positive, refiner_negative) = refiner_basic_pipe_opt + segs = core.segs_scale_match(segs, image.shape) + new_segs = [] + cnet_pil_list = [] + for i in range(batch_size): + seed += 1 + for seg in segs[1]: + cropped_image = seg.cropped_image if seg.cropped_image is not None else crop_ndarray4(image.numpy(), seg.crop_region) + cropped_image = to_tensor(cropped_image) + is_mask_all_zeros = (seg.cropped_mask == 0).all().item() + if is_mask_all_zeros: + print(f'Detailer: segment skip [empty mask]') + new_segs.append(seg) + continue + if noise_mask: + cropped_mask = seg.cropped_mask + else: + cropped_mask = None + cropped_positive = [[condition, {k: core.crop_condition_mask(v, image, seg.crop_region) if k == 'mask' else v for (k, v) in details.items()}] for (condition, details) in positive] + cropped_negative = [[condition, {k: core.crop_condition_mask(v, image, seg.crop_region) if k == 'mask' else v for (k, v) in details.items()}] for (condition, details) in negative] + (enhanced_image, cnet_pils) = core.enhance_detail(cropped_image, model, clip, vae, guide_size, guide_size_for, max_size, seg.bbox, seed, steps, cfg, sampler_name, scheduler, cropped_positive, cropped_negative, denoise, cropped_mask, force_inpaint, refiner_ratio=refiner_ratio, refiner_model=refiner_model, refiner_clip=refiner_clip, refiner_positive=refiner_positive, refiner_negative=refiner_negative, control_net_wrapper=seg.control_net_wrapper, cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + if cnet_pils is not None: + cnet_pil_list.extend(cnet_pils) + if enhanced_image is None: + new_cropped_image = cropped_image + else: + new_cropped_image = enhanced_image + new_seg = SEG(to_numpy(new_cropped_image), seg.cropped_mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, None) + new_segs.append(new_seg) + return ((segs[0], new_segs), cnet_pil_list) + + def doit(self, image, segs, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, denoise, noise_mask, force_inpaint, basic_pipe, refiner_ratio=None, batch_size=1, cycle=1, refiner_basic_pipe_opt=None, inpaint_model=False, noise_mask_feather=0): + if len(image) > 1: + raise Exception('[Impact Pack] ERROR: SEGSDetailer does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.') + (segs, cnet_pil_list) = SEGSDetailer.do_detail(image, segs, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, denoise, noise_mask, force_inpaint, basic_pipe, refiner_ratio, batch_size, cycle=cycle, refiner_basic_pipe_opt=refiner_basic_pipe_opt, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + if len(cnet_pil_list) == 0: + cnet_pil_list = [empty_pil_tensor()] + return (segs, cnet_pil_list) +``` \ No newline at end of file diff --git a/docs/SEGSDetailerForAnimateDiff.md b/docs/SEGSDetailerForAnimateDiff.md new file mode 100644 index 0000000..381833b --- /dev/null +++ b/docs/SEGSDetailerForAnimateDiff.md @@ -0,0 +1,134 @@ +# Documentation +- Class name: SEGSDetailerForAnimateDiff +- Category: ImpactPack/Detailer +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSDetailerForAnimateDiff节点旨在增强图像帧中的分割细节,特别适用于提高动画差异的质量。它通过缩放和处理图像的各个部分来提高它们的清晰度和细节水平,利用先进的模型和采样技术。 + +# Input types +## Required +- image_frames + - image_frames参数是必需的,因为它提供了节点将处理的原始图像数据。它直接影响输出质量以及节点增强帧内细节的能力。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- segs + - segs参数定义了节点将关注的image_frames内的分割,对于节点识别和处理图像数据中的特定感兴趣区域至关重要。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +- guide_size + - guide_size参数设置细节增强过程的缩放因子。它很重要,因为它决定了将引入到图像段中的细节水平。 + - Comfy dtype: FLOAT + - Python dtype: float +- guide_size_for + - guide_size_for参数指示guide_size应用于边框还是裁剪区域。这个选择影响细节增强在图像内的聚焦方式。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- max_size + - max_size参数为放大的图像帧设定了最大尺寸。它确保增强的图像不会超过一定的分辨率,保持性能和内存效率。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - seed参数用于采样过程中的随机数生成。它确保了当使用相同的种子值运行节点时结果的可复现性。 + - Comfy dtype: INT + - Python dtype: int +- steps + - steps参数决定了采样过程中使用的迭代次数。更多的步骤可以导致更精细的结果,但可能会增加处理时间。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数调整采样过程的配置,允许微调细节增强算法的行为。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数指定节点使用的采样方法。不同的采样器在细节和噪声特性方面可以提供不同的结果。 + - Comfy dtype: STRING + - Python dtype: str +- scheduler + - scheduler参数定义了采样步骤的调度策略。它影响采样过程在迭代过程中的演变方式。 + - Comfy dtype: STRING + - Python dtype: str +- denoise + - denoise参数控制应用于增强图像的降噪水平。它是实现最终输出中细节和噪声平衡的重要因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- basic_pipe + - basic_pipe参数封装了细节增强过程所需的核心组件,包括模型、clip和vae。它是节点功能的基础。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, ...] +## Optional +- refiner_ratio + - refiner_ratio参数在提供时,决定了可选的refiner模型对细节增强的影响。它允许对最终输出进行进一步的微调。 + - Comfy dtype: FLOAT + - Python dtype: Optional[float] +- refiner_basic_pipe_opt + - 可选的refiner_basic_pipe_opt参数通过提供一组额外的组件用于次级细化过程,扩展了节点的能力。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Optional[Tuple[Any, ...]] + +# Output types +- segs + - segs输出包含输入图像帧的增强分割细节。它标志着节点处理的完成,并代表了细节增强操作的主要结果。 + - Comfy dtype: SEGS + - Python dtype: Tuple[Tuple[int, int], List[SEG]] +- cnet_images + - cnet_images输出提供了控制网对细节增强过程影响的视觉表示。这些图像可以用于进一步分析,或作为节点有效性的参考。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SEGSDetailerForAnimateDiff: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image_frames': ('IMAGE',), 'segs': ('SEGS',), 'guide_size': ('FLOAT', {'default': 256, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'guide_size_for': ('BOOLEAN', {'default': True, 'label_on': 'bbox', 'label_off': 'crop_region'}), 'max_size': ('FLOAT', {'default': 768, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), '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}), 'basic_pipe': ('BASIC_PIPE',), 'refiner_ratio': ('FLOAT', {'default': 0.2, 'min': 0.0, 'max': 1.0})}, 'optional': {'refiner_basic_pipe_opt': ('BASIC_PIPE',)}} + RETURN_TYPES = ('SEGS', 'IMAGE') + RETURN_NAMES = ('segs', 'cnet_images') + OUTPUT_IS_LIST = (False, True) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detailer' + + @staticmethod + def do_detail(image_frames, segs, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, denoise, basic_pipe, refiner_ratio=None, refiner_basic_pipe_opt=None, inpaint_model=False, noise_mask_feather=0): + (model, clip, vae, positive, negative) = basic_pipe + if refiner_basic_pipe_opt is None: + (refiner_model, refiner_clip, refiner_positive, refiner_negative) = (None, None, None, None) + else: + (refiner_model, refiner_clip, _, refiner_positive, refiner_negative) = refiner_basic_pipe_opt + segs = core.segs_scale_match(segs, image_frames.shape) + new_segs = [] + cnet_image_list = [] + for seg in segs[1]: + cropped_image_frames = None + for image in image_frames: + image = image.unsqueeze(0) + cropped_image = seg.cropped_image if seg.cropped_image is not None else crop_tensor4(image, seg.crop_region) + cropped_image = to_tensor(cropped_image) + if cropped_image_frames is None: + cropped_image_frames = cropped_image + else: + cropped_image_frames = torch.concat((cropped_image_frames, cropped_image), dim=0) + cropped_image_frames = cropped_image_frames.cpu().numpy() + cropped_positive = [[condition, {k: core.crop_condition_mask(v, cropped_image_frames, seg.crop_region) if k == 'mask' else v for (k, v) in details.items()}] for (condition, details) in positive] + cropped_negative = [[condition, {k: core.crop_condition_mask(v, cropped_image_frames, seg.crop_region) if k == 'mask' else v for (k, v) in details.items()}] for (condition, details) in negative] + (enhanced_image_tensor, cnet_images) = core.enhance_detail_for_animatediff(cropped_image_frames, model, clip, vae, guide_size, guide_size_for, max_size, seg.bbox, seed, steps, cfg, sampler_name, scheduler, cropped_positive, cropped_negative, denoise, seg.cropped_mask, refiner_ratio=refiner_ratio, refiner_model=refiner_model, refiner_clip=refiner_clip, refiner_positive=refiner_positive, refiner_negative=refiner_negative, control_net_wrapper=seg.control_net_wrapper, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + if cnet_images is not None: + cnet_image_list.extend(cnet_images) + if enhanced_image_tensor is None: + new_cropped_image = cropped_image_frames + else: + new_cropped_image = enhanced_image_tensor.cpu().numpy() + new_seg = SEG(new_cropped_image, seg.cropped_mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, None) + new_segs.append(new_seg) + return ((segs[0], new_segs), cnet_image_list) + + def doit(self, image_frames, segs, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, denoise, basic_pipe, refiner_ratio=None, refiner_basic_pipe_opt=None, inpaint_model=False, noise_mask_feather=0): + (segs, cnet_images) = SEGSDetailerForAnimateDiff.do_detail(image_frames, segs, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, denoise, basic_pipe, refiner_ratio, refiner_basic_pipe_opt, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + if len(cnet_images) == 0: + cnet_images = [empty_pil_tensor()] + return (segs, cnet_images) +``` \ No newline at end of file diff --git a/docs/SEGSLabelFilterDetailerHookProvider.md b/docs/SEGSLabelFilterDetailerHookProvider.md new file mode 100644 index 0000000..85f8336 --- /dev/null +++ b/docs/SEGSLabelFilterDetailerHookProvider.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: SEGSLabelFilterDetailerHookProvider +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSLabelFilterDetailerHookProvider 节点旨在系统内过滤分割标签。它在确保只有所需类型的段被处理中发挥关键作用,从而提高后续分析和操作的精确度和相关性。 + +# Input types +## Required +- preset + - 预设参数决定了节点操作的初始设置或配置。它至关重要,因为它决定了节点处理的起点,影响着最终结果。 + - Comfy dtype: STRING + - Python dtype: str +- labels + - 标签参数是节点被指示允许的段类型的列表。它是一个关键输入,因为它直接影响哪些段通过了过滤过程。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- DETAILER_HOOK + - 节点的输出是一个已使用指定标签配置的钩子对象。这个钩子对象很重要,因为它被用来将过滤标准应用于分割过程。 + - Comfy dtype: OBJECT + - Python dtype: SEGSLabelFilterDetailerHook + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEGSLabelFilterDetailerHookProvider: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',), 'preset': (['all'] + defs.detection_labels,), 'labels': ('STRING', {'multiline': True, 'placeholder': 'List the types of segments to be allowed, separated by commas'})}} + RETURN_TYPES = ('DETAILER_HOOK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, preset, labels): + hook = hooks.SEGSLabelFilterDetailerHook(labels) + return (hook,) +``` \ No newline at end of file diff --git a/docs/SEGSOrderedFilterDetailerHookProvider.md b/docs/SEGSOrderedFilterDetailerHookProvider.md new file mode 100644 index 0000000..9b8f6eb --- /dev/null +++ b/docs/SEGSOrderedFilterDetailerHookProvider.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: SEGSOrderedFilterDetailerHookProvider +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSOrderedFilterDetailerHookProvider节点旨在对一组分割应用特定的过滤和排序机制。它允许根据面积尺寸和空间坐标定制过滤标准,并提供按升序或降序排序结果的选项。该节点特别适用于精炼分割任务的输出,以满足特定要求。 + +# Input types +## Required +- target + - 目标参数定义了过滤分割的标准。它可以基于分割的面积、宽度、高度或其角落的坐标。此参数至关重要,因为它直接影响哪些分割被选择用于进一步处理。 + - Comfy dtype: COMBO[area(=w*h), width, height, x1, y1, x2, y2] + - Python dtype: Union[str, int, Tuple[int, int]] +- order + - 排序参数确定过滤后分割的排序顺序。设置为True时,结果按降序排序;设置为False时,按升序排序。这对于需要特定顺序的分割的应用来说很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- take_start + - take_start参数指定要考虑的分割范围的起始索引。当只需要过滤结果的子集时,它特别有用,允许高效处理数据并减少不必要的处理。 + - Comfy dtype: INT + - Python dtype: int +- take_count + - take_count参数定义从由take_start指定的索引开始的过滤结果中要获取的分割数量。它对于控制处理的数据量至关重要,并且可以用来将输出限制在可管理的大小。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- DETAILER_HOOK + - SEGSOrderedFilterDetailerHookProvider节点的输出是一个细化钩子,它封装了应用指定的过滤和排序操作的逻辑。这个钩子可以在处理流程的下游中使用,以进一步细化和组织分割结果。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: SEGSOrderedFilterDetailerHook + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEGSOrderedFilterDetailerHookProvider: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'target': (['area(=w*h)', 'width', 'height', 'x1', 'y1', 'x2', 'y2'],), 'order': ('BOOLEAN', {'default': True, 'label_on': 'descending', 'label_off': 'ascending'}), 'take_start': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'take_count': ('INT', {'default': 1, 'min': 0, 'max': sys.maxsize, 'step': 1})}} + RETURN_TYPES = ('DETAILER_HOOK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, target, order, take_start, take_count): + hook = hooks.SEGSOrderedFilterDetailerHook(target, order, take_start, take_count) + return (hook,) +``` \ No newline at end of file diff --git a/docs/SEGSPaste.md b/docs/SEGSPaste.md new file mode 100644 index 0000000..0d4bd43 --- /dev/null +++ b/docs/SEGSPaste.md @@ -0,0 +1,92 @@ +# Documentation +- Class name: SEGSPaste +- Category: ImpactPack/Detailer +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSPaste节点旨在将分割图中的片段集成到给定图像中,增强图像的视觉细节。它通过指定的羽化和alpha值对片段进行对齐和混合,确保了无缝和详细的结果。 + +# Input types +## Required +- image + - 输入图像,将把片段粘贴到该图像中。它作为整个操作的基础,片段将与此图像对齐并混合。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- segs + - 包含要粘贴到图像上的片段的分割数据。每个片段对于细节增强过程至关重要,有助于最终的视觉输出。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +## Optional +- feather + - 羽化参数控制粘贴片段时边缘的柔和度。它是实现片段与图像之间自然混合的重要因素。 + - Comfy dtype: INT + - Python dtype: int +- alpha + - alpha参数调整粘贴片段的不透明度,允许控制与底层图像的可见性和混合强度。 + - Comfy dtype: INT + - Python dtype: int +- ref_image_opt + - 一个可选的参考图像,为粘贴片段提供额外的上下文。它可以用来匹配片段与参考图像的光照或颜色。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- result + - 输出是增强后的图像,其中来自分割图的片段被无缝集成。它代表了细节增强过程的最终视觉结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SEGSPaste: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'segs': ('SEGS',), 'feather': ('INT', {'default': 5, 'min': 0, 'max': 100, 'step': 1}), 'alpha': ('INT', {'default': 255, 'min': 0, 'max': 255, 'step': 1})}, 'optional': {'ref_image_opt': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detailer' + + @staticmethod + def doit(image, segs, feather, alpha=255, ref_image_opt=None): + segs = core.segs_scale_match(segs, image.shape) + result = None + for (i, single_image) in enumerate(image): + image_i = single_image.unsqueeze(0).clone() + for seg in segs[1]: + ref_image = None + if ref_image_opt is None and seg.cropped_image is not None: + cropped_image = seg.cropped_image + if isinstance(cropped_image, np.ndarray): + cropped_image = torch.from_numpy(cropped_image) + ref_image = cropped_image[i].unsqueeze(0) + elif ref_image_opt is not None: + ref_tensor = ref_image_opt[i].unsqueeze(0) + ref_image = crop_image(ref_tensor, seg.crop_region) + if ref_image is not None: + if seg.cropped_mask.ndim == 3 and len(seg.cropped_mask) == len(image): + mask = seg.cropped_mask[i] + elif seg.cropped_mask.ndim == 3 and len(seg.cropped_mask) > 1: + print(f'[Impact Pack] WARN: SEGSPaste - The number of the mask batch({len(seg.cropped_mask)}) and the image batch({len(image)}) are different. Combine the mask frames and apply.') + combined_mask = (seg.cropped_mask[0] * 255).to(torch.uint8) + for frame_mask in seg.cropped_mask[1:]: + combined_mask |= (frame_mask * 255).to(torch.uint8) + combined_mask = (combined_mask / 255.0).to(torch.float32) + mask = utils.to_binary_mask(combined_mask, 0.1) + else: + mask = seg.cropped_mask + mask = tensor_gaussian_blur_mask(mask, feather) * (alpha / 255) + (x, y, *_) = seg.crop_region + mask.cpu() + image_i.cpu() + ref_image.cpu() + tensor_paste(image_i, ref_image, (x, y), mask) + if result is None: + result = image_i + else: + result = torch.concat((result, image_i), dim=0) + return (result,) +``` \ No newline at end of file diff --git a/docs/SEGSPreview.md b/docs/SEGSPreview.md new file mode 100644 index 0000000..e016ab6 --- /dev/null +++ b/docs/SEGSPreview.md @@ -0,0 +1,139 @@ +# Documentation +- Class name: SEGSPreview +- Category: ImpactPack/Util +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSPreview节点旨在处理和预览分割图像。它接受分割数据和可选参数来控制alpha混合和最小alpha值,然后生成一个视觉表示分割的预览图像。该节点能够处理一批分割数据,并且在分割数据不可用时可以回退到默认图像。 + +# Input types +## Required +- segs + - ‘segs’参数对于节点至关重要,因为它提供了节点将处理的分割数据。此输入直接影响预览图像的生成方式及其质量。 + - Comfy dtype: SEGS + - Python dtype: List[Tuple[int, np.ndarray]] +## Optional +- alpha_mode + - ‘alpha_mode’参数决定预览中是否启用alpha混合。它在处理最终输出中分割遮罩的透明度方面起着重要作用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- min_alpha + - ‘min_alpha’参数设置遮罩的最小alpha值,确保即使在遮罩置信度低的区域,分割也是可见的。这对于预览中分割的视觉清晰度至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- fallback_image_opt + - ‘fallback_image_opt’参数提供了一个可选图像,当分割数据不可用时使用。它确保了即使在这种情况下,节点仍然可以生成预览。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- ui + - ‘ui’输出包含预览的用户界面元素,包括已处理并准备显示的图像列表。 + - Comfy dtype: DICT + - Python dtype: Dict[str, List[Dict[str, str]]} +- result + - ‘result’输出是代表分割预览的组合图像批次的列表。它很重要,因为它包含了分割的实际视觉数据。 + - Comfy dtype: COMBO[torch.Tensor] + - Python dtype: Tuple[List[torch.Tensor],] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEGSPreview: + + def __init__(self): + self.output_dir = folder_paths.get_temp_directory() + self.type = 'temp' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',), 'alpha_mode': ('BOOLEAN', {'default': True, 'label_on': 'enable', 'label_off': 'disable'}), 'min_alpha': ('FLOAT', {'default': 0.2, 'min': 0.0, 'max': 1.0, 'step': 0.01})}, 'optional': {'fallback_image_opt': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + OUTPUT_NODE = True + + def doit(self, segs, alpha_mode=True, min_alpha=0.0, fallback_image_opt=None): + (full_output_folder, filename, counter, subfolder, filename_prefix) = folder_paths.get_save_image_path('impact_seg_preview', self.output_dir, segs[0][1], segs[0][0]) + results = list() + result_image_list = [] + if fallback_image_opt is not None: + segs = core.segs_scale_match(segs, fallback_image_opt.shape) + if min_alpha != 0: + min_alpha = int(255 * min_alpha) + if len(segs[1]) > 0: + if segs[1][0].cropped_image is not None: + batch_count = len(segs[1][0].cropped_image) + elif fallback_image_opt is not None: + batch_count = len(fallback_image_opt) + else: + return {'ui': {'images': results}} + for seg in segs[1]: + result_image_batch = None + cached_mask = None + + def get_combined_mask(): + nonlocal cached_mask + if cached_mask is not None: + return cached_mask + else: + if isinstance(seg.cropped_mask, np.ndarray): + masks = torch.tensor(seg.cropped_mask) + else: + masks = seg.cropped_mask + cached_mask = (masks[0] * 255).to(torch.uint8) + for x in masks[1:]: + cached_mask |= (x * 255).to(torch.uint8) + cached_mask = (cached_mask / 255.0).to(torch.float32) + cached_mask = utils.to_binary_mask(cached_mask, 0.1) + cached_mask = cached_mask.numpy() + return cached_mask + + def stack_image(image, mask=None): + nonlocal result_image_batch + if isinstance(image, np.ndarray): + image = torch.from_numpy(image) + if mask is not None: + image *= torch.tensor(mask)[None, ..., None] + if result_image_batch is None: + result_image_batch = image + else: + result_image_batch = torch.concat((result_image_batch, image), dim=0) + for i in range(batch_count): + cropped_image = None + if seg.cropped_image is not None: + cropped_image = seg.cropped_image[i, None] + elif fallback_image_opt is not None: + ref_image = fallback_image_opt[i].unsqueeze(0) + cropped_image = crop_image(ref_image, seg.crop_region) + if cropped_image is not None: + if isinstance(cropped_image, np.ndarray): + cropped_image = torch.from_numpy(cropped_image) + cropped_image = cropped_image.clone() + cropped_pil = to_pil(cropped_image) + if alpha_mode: + if isinstance(seg.cropped_mask, np.ndarray): + cropped_mask = seg.cropped_mask + elif seg.cropped_image is not None and len(seg.cropped_image) != len(seg.cropped_mask): + cropped_mask = get_combined_mask() + else: + cropped_mask = seg.cropped_mask[i].numpy() + mask_array = (cropped_mask * 255).astype(np.uint8) + if min_alpha != 0: + mask_array[mask_array < min_alpha] = min_alpha + mask_pil = Image.fromarray(mask_array, mode='L').resize(cropped_pil.size) + cropped_pil.putalpha(mask_pil) + stack_image(cropped_image, cropped_mask) + else: + stack_image(cropped_image) + file = f'{filename}_{counter:05}_.webp' + cropped_pil.save(os.path.join(full_output_folder, file)) + results.append({'filename': file, 'subfolder': subfolder, 'type': self.type}) + counter += 1 + if result_image_batch is not None: + result_image_list.append(result_image_batch) + return {'ui': {'images': results}, 'result': (result_image_list,)} +``` \ No newline at end of file diff --git a/docs/SEGSPreviewCNet.md b/docs/SEGSPreviewCNet.md new file mode 100644 index 0000000..955a4e0 --- /dev/null +++ b/docs/SEGSPreviewCNet.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: SEGSPreviewCNet +- Category: ImpactPack/Util +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSPreviewCNet 是一个用于处理和预览分割结果的节点。它接受分割数据作为输入,并生成一系列预览图像,增强了对分割工作的可视化检查和分析。该节点在提供分割工作的可视化摘要方面至关重要,允许快速评估并在需要时进行进一步操作。 + +# Input types +## Required +- segs + - 'ssegs' 参数对于节点的操作至关重要,因为它提供了节点将处理的分割数据。这是一个必需的输入,它通过确定生成的预览图像的内容直接影响节点的输出。 + - Comfy dtype: SEGS + - Python dtype: List[Tuple[str, SEG]] + +# Output types +- ui + - 输出中的 'ui' 参数非常重要,因为它包含了将显示给用户的用户界面元素。它包括代表分割预览的图像列表,这对于用户交互和视觉反馈至关重要。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] +- result + - 输出中的 'result' 参数是节点处理的图像集合。它是节点的主要输出,包含了分割数据的视觉表示,这是节点功能的主要目标。 + - Comfy dtype: COMBO[IMAGE] + - Python dtype: Tuple[List[Image.Image], ...] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEGSPreviewCNet: + + def __init__(self): + self.output_dir = folder_paths.get_temp_directory() + self.type = 'temp' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',)}} + RETURN_TYPES = ('IMAGE',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + OUTPUT_NODE = True + + def doit(self, segs): + (full_output_folder, filename, counter, subfolder, filename_prefix) = folder_paths.get_save_image_path('impact_seg_preview', self.output_dir, segs[0][1], segs[0][0]) + results = list() + result_image_list = [] + for seg in segs[1]: + file = f'{filename}_{counter:05}_.webp' + if seg.control_net_wrapper is not None and seg.control_net_wrapper.control_image is not None: + cnet_image = seg.control_net_wrapper.control_image + result_image_list.append(cnet_image) + else: + cnet_image = empty_pil_tensor(64, 64) + cnet_pil = utils.tensor2pil(cnet_image) + cnet_pil.save(os.path.join(full_output_folder, file)) + results.append({'filename': file, 'subfolder': subfolder, 'type': self.type}) + counter += 1 + return {'ui': {'images': results}, 'result': (result_image_list,)} +``` \ No newline at end of file diff --git a/docs/SEGSRangeFilterDetailerHookProvider.md b/docs/SEGSRangeFilterDetailerHookProvider.md new file mode 100644 index 0000000..00faa62 --- /dev/null +++ b/docs/SEGSRangeFilterDetailerHookProvider.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: SEGSRangeFilterDetailerHookProvider +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSRangeFilterDetailerHookProvider节点旨在对分割过程应用过滤机制。它根据指定的范围过滤段,确保只有符合定义标准的段被考虑。该节点通过专注于用户定义参数的相关区域,增强了分割的精度。 + +# Input types +## Required +- target + - 'target' 参数定义了分割过程的兴趣区域。它至关重要,因为它决定了哪些段将被过滤。节点根据提供的维度和坐标操作,使此参数成为过过程的核心。 + - Comfy dtype: COMBO[area(=w*h), width, height, x1, y1, x2, y2, length_percent] + - Python dtype: Union[str, Tuple[int, int]] +- mode + - 'mode' 参数决定是保留目标区域内还是区域外的段。这是一个二元选择,显著影响分割的结果,允许对过滤标准进行精确控制。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- min_value + - 'min_value' 参数设置了段值的最小阈值。它在过滤不符合最小标准值的段中起着关键作用,从而完善了分割结果。 + - Comfy dtype: INT + - Python dtype: int +- max_value + - 'max_value' 参数设定了段值的最大限制。它确保超过此限制的段从最终分割中排除,保持了过滤输出的完整性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- DETAILER_HOOK + - 输出'DETAILER_HOOK'是一个钩子对象,它封装了过滤标准并应用于分割过程。它很重要,因为它代表了节点操作的结果,提供了一种将过滤逻辑集成到更广泛的分割工作流程中的方法。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: SEGSRangeFilterDetailerHook + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEGSRangeFilterDetailerHookProvider: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'target': (['area(=w*h)', 'width', 'height', 'x1', 'y1', 'x2', 'y2', 'length_percent'],), 'mode': ('BOOLEAN', {'default': True, 'label_on': 'inside', 'label_off': 'outside'}), 'min_value': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'max_value': ('INT', {'default': 67108864, 'min': 0, 'max': sys.maxsize, 'step': 1})}} + RETURN_TYPES = ('DETAILER_HOOK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, target, mode, min_value, max_value): + hook = hooks.SEGSRangeFilterDetailerHook(target, mode, min_value, max_value) + return (hook,) +``` \ No newline at end of file diff --git a/docs/SEGSSwitch.md b/docs/SEGSSwitch.md new file mode 100644 index 0000000..6ea67f4 --- /dev/null +++ b/docs/SEGSSwitch.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: GeneralSwitch +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +GeneralSwitch节点旨在根据选择的索引管理和路由数据。它根据提供的索引选择一个输入,并从工作流的节点信息中检索相应的标签。该节点在工作流中的决策过程中起着关键作用,允许执行条件路径。 + +# Input types +## Required +- select + - 参数'select'对于确定节点将处理哪个输入至关重要。它指示节点用于识别工作流中进一步操作的正确输入的选择索引。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- sel_mode + - 参数'sel_mode'允许用户指定选择应基于提示还是执行上下文。这可以影响节点如何解释和响应输入,影响工作流的整体行为。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- input1 + - 参数'input1'作为可选输入提供给节点。它的作用是提供额外的灵活性,处理各种类型的数据,增强节点在不同工作流场景中的适应性。 + - Comfy dtype: ANY + - Python dtype: Any +- unique_id + - 参数'unique_id'用于在内部标识工作流中的特定节点。它在节点引用自己的输入和配置设置的能力中起着至关重要的作用。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +- extra_pnginfo + - 参数'extra_pnginfo'包含有关工作流中节点视觉表示的额外信息。它有助于自定义节点的外观并提供相关上下文信息。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, Any] + +# Output types +- selected_value + - 输出'selected_value'代表基于输入索引选择的数据。它是节点操作的关键组成部分,因为它决定了将传递给后续处理的数据。 + - Comfy dtype: ANY + - Python dtype: Any +- selected_label + - 输出'selected_label'提供与所选输入关联的标签。这对于提供有关正在处理的数据的上下文或额外信息非常有用。 + - Comfy dtype: STRING + - Python dtype: str +- selected_index + - 输出'selected_index'指示用于选择输入的索引。它可以作为在工作流中跟踪选择的参考。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GeneralSwitch: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'select': ('INT', {'default': 1, 'min': 1, 'max': 999999, 'step': 1}), 'sel_mode': ('BOOLEAN', {'default': True, 'label_on': 'select_on_prompt', 'label_off': 'select_on_execution', 'forceInput': False})}, 'optional': {'input1': (any_typ,)}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = (any_typ, 'STRING', 'INT') + RETURN_NAMES = ('selected_value', 'selected_label', 'selected_index') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, *args, **kwargs): + selected_index = int(kwargs['select']) + input_name = f'input{selected_index}' + selected_label = input_name + node_id = kwargs['unique_id'] + nodelist = kwargs['extra_pnginfo']['workflow']['nodes'] + for node in nodelist: + if str(node['id']) == node_id: + inputs = node['inputs'] + for slot in inputs: + if slot['name'] == input_name and 'label' in slot: + selected_label = slot['label'] + break + if input_name in kwargs: + return (kwargs[input_name], selected_label, selected_index) + else: + print(f'ImpactSwitch: invalid select index (ignored)') + return (None, '', selected_index) +``` \ No newline at end of file diff --git a/docs/SEGSToImageList.md b/docs/SEGSToImageList.md new file mode 100644 index 0000000..7ca7772 --- /dev/null +++ b/docs/SEGSToImageList.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: SEGSToImageList +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSToImageList节点旨在将分割数据转换为图像张量列表。它将分割数据缩放并处理以匹配提供的备用图像的尺寸,或者如果没有提供图像,则生成默认张量。该节点在准备进一步分析或在ImpactPack实用程序套件中可视化的图像数据中起着至关重要的作用。 + +# Input types +## Required +- segs + - 's segs' 参数是节点处理的分割数据集合。它对节点的操作至关重要,因为它直接影响输出图像列表的内容和结构。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +## Optional +- fallback_image_opt + - 可选的 'fallback_image_opt' 参数提供了一个默认图像,当没有可用的分割图像时使用。它确保了即使在数据不完整的情况下,节点仍然能够产生一致的输出。 + - Comfy dtype: IMAGE + - Python dtype: Optional[torch.Tensor] + +# Output types +- results + - 'results' 输出是从分割数据派生的图像张量列表。它代表了节点的主要输出,对于需要图像数据的下游任务具有重要意义。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SEGSToImageList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',)}, 'optional': {'fallback_image_opt': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, segs, fallback_image_opt=None): + results = list() + if fallback_image_opt is not None: + segs = core.segs_scale_match(segs, fallback_image_opt.shape) + for seg in segs[1]: + if seg.cropped_image is not None: + cropped_image = to_tensor(seg.cropped_image) + elif fallback_image_opt is not None: + cropped_image = to_tensor(crop_image(fallback_image_opt, seg.crop_region)) + else: + cropped_image = empty_pil_tensor() + results.append(cropped_image) + if len(results) == 0: + results.append(empty_pil_tensor()) + return (results,) +``` \ No newline at end of file diff --git a/docs/SEGSUpscaler.md b/docs/SEGSUpscaler.md new file mode 100644 index 0000000..de0de64 --- /dev/null +++ b/docs/SEGSUpscaler.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: SEGSUpscaler +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSUpscaler节点旨在通过利用分割数据和上采样模型来增强图像的分辨率。它在保持分割区域的完整性的同时对图像进行上采样,确保在缩放过程中保留并增强这些区域内的细节。该节点特别适用于高分辨率分割至关重要的应用,例如医学成像或卫星图像分析。 + +# Input types +## Required +- image + - 要上采样的输入图像是SEGSUpscaler节点的基本参数。它作为节点操作的基础数据,用于产生更高分辨率的输出。输入图像的质量和内容直接影响最终上采样的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- segs + - 分割数据或'segs'对于SEGSUpscaler节点至关重要,因为它提供了区分和处理图像内不同区域所需的信息。这些数据确保上采样图像保留了分割细节,这对于依赖准确分割的应用至关重要。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +## Optional +- rescale_factor + - 重新缩放因子是一个重要的参数,它决定了要应用于输入图像的上采样程度。更高的值会导致分辨率的更大幅度增加,可以增强细节,但如果不小心管理,也可能引入伪影。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- enhanced_image + - SEGSUpscaler节点的输出是已上采样到更高分辨率的增强图像。该图像保留了具有改进细节和清晰度的分割区域,使其适合于进一步分析或以高分辨率格式显示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SEGSUpscaler: + + @classmethod + def INPUT_TYPES(s): + resampling_methods = ['lanczos', 'nearest', 'bilinear', 'bicubic'] + return {'required': {'image': ('IMAGE',), 'segs': ('SEGS',), 'model': ('MODEL',), 'clip': ('CLIP',), 'vae': ('VAE',), 'rescale_factor': ('FLOAT', {'default': 2, 'min': 0.01, 'max': 100.0, 'step': 0.01}), 'resampling_method': (resampling_methods,), 'supersample': (['true', 'false'],), 'rounding_modulus': ('INT', {'default': 8, 'min': 8, 'max': 1024, 'step': 8}), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'denoise': ('FLOAT', {'default': 0.5, 'min': 0.0001, 'max': 1.0, 'step': 0.01}), 'feather': ('INT', {'default': 5, 'min': 0, 'max': 100, 'step': 1}), 'inpaint_model': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'}), 'noise_mask_feather': ('INT', {'default': 20, 'min': 0, 'max': 100, 'step': 1})}, 'optional': {'upscale_model_opt': ('UPSCALE_MODEL',), 'upscaler_hook_opt': ('UPSCALER_HOOK',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + @staticmethod + def doit(image, segs, model, clip, vae, rescale_factor, resampling_method, supersample, rounding_modulus, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, inpaint_model, noise_mask_feather, upscale_model_opt=None, upscaler_hook_opt=None): + new_image = segs_upscaler.upscaler(image, upscale_model_opt, rescale_factor, resampling_method, supersample, rounding_modulus) + segs = core.segs_scale_match(segs, new_image.shape) + ordered_segs = segs[1] + for (i, seg) in enumerate(ordered_segs): + cropped_image = crop_ndarray4(new_image.numpy(), seg.crop_region) + cropped_image = to_tensor(cropped_image) + mask = to_tensor(seg.cropped_mask) + mask = tensor_gaussian_blur_mask(mask, feather) + is_mask_all_zeros = (seg.cropped_mask == 0).all().item() + if is_mask_all_zeros: + print(f'SEGSUpscaler: segment skip [empty mask]') + continue + cropped_mask = seg.cropped_mask + seg_seed = seed + i + enhanced_image = segs_upscaler.img2img_segs(cropped_image, model, clip, vae, seg_seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, noise_mask=cropped_mask, control_net_wrapper=seg.control_net_wrapper, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + if not enhanced_image is None: + new_image = new_image.cpu() + enhanced_image = enhanced_image.cpu() + left = seg.crop_region[0] + top = seg.crop_region[1] + tensor_paste(new_image, enhanced_image, (left, top), mask) + if upscaler_hook_opt is not None: + upscaler_hook_opt.post_paste(new_image) + enhanced_img = tensor_convert_rgb(new_image) + return (enhanced_img,) +``` \ No newline at end of file diff --git a/docs/SEGSUpscalerPipe.md b/docs/SEGSUpscalerPipe.md new file mode 100644 index 0000000..be8ad65 --- /dev/null +++ b/docs/SEGSUpscalerPipe.md @@ -0,0 +1,101 @@ +# Documentation +- Class name: SEGSUpscalerPipe +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SEGSUpscalerPipe 是一个用于提高图像分辨率的节点,它采用先进的上采样技术。它利用深度学习模型的能力来放大图像,同时保持语义分割(SEGS)的完整性。这个节点特别适用于需要高质量图像上采样的应用,如图形设计、摄影和视频处理。 + +# Input types +## Required +- image + - 要上采样的输入图像。它是上采样过程的主要数据源,对于实现所需的输出分辨率和质量至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- segs + - 提供像素级理解图像内容的语义分割图。这些用于指导上采样过程,以保持原始图像的语义完整性。 + - Comfy dtype: SEGS + - Python dtype: torch.Tensor +- basic_pipe + - 构成上采样过程基础的模型和配置集合。它包括模型、clip、vae等基本组件以及影响上采样结果的额外设置。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, torch.nn.Module, torch.nn.Module, Any, Any] +- rescale_factor + - 输入图像将被放大的倍数。它直接影响输出图像的最终分辨率,更高的倍数会导致更大的图像。 + - Comfy dtype: FLOAT + - Python dtype: float +- resampling_method + - 重采样方法决定了用于上采样图像的算法。不同的方法可能导致不同程度的细节和图像质量。 + - Comfy dtype: COMBO[lanczos, nearest, bilinear, bicubic] + - Python dtype: str +- supersample + - 一个标志,指示是否使用超采样技术进行上采样。超采样可以提高放大图像的锐度和清晰度。 + - Comfy dtype: COMBO[true, false] + - Python dtype: bool +- rounding_modulus + - 用于放大图像尺寸的取模数。它确保输出图像尺寸一致且适合进一步处理。 + - Comfy dtype: INT + - Python dtype: int +- seed + - 用于确保上采样过程可重复的随机种子。在多次运行节点时获得一致结果非常重要。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 运行上采样算法的步数。更多的步数可以带来更好的结果,但可能会增加处理时间。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 一个配置参数,用于调整上采样过程中细节保留和噪声减少之间的平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 用于上采样过程的采样器名称。不同的采样器可以影响样本的分布和最终图像质量。 + - Comfy dtype: KSampler.SAMPLERS + - Python dtype: str +- scheduler + - 用于控制上采样过程中学习率的调度器。它可以影响上采样算法的收敛和稳定性。 + - Comfy dtype: KSampler.SCHEDULERS + - Python dtype: str +- denoise + - 上采样过程中要应用的去噪程度。较高的值可以减少图像中的噪声,但也可能去除一些细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- feather + - 用于软化放大图像边缘的羽化值。它可以在图像的不同区域之间创建更平滑的过渡。 + - Comfy dtype: INT + - Python dtype: int +- inpaint_model + - 一个布尔标志,指示在上采样期间是否使用修复模型来填充图像中缺失或损坏的区域。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- noise_mask_feather + - 应用于噪声掩模的羽化值,以软化其边缘。这有助于为放大的图像创造更自然的外观。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- upscaled_image + - SEGSUpscalerPipe 节点的输出是经过处理以实现更高分辨率的放大图像,同时保持语义分割的细节。它是上采样过程的最终成果,可供进一步使用或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SEGSUpscalerPipe: + + @classmethod + def INPUT_TYPES(s): + resampling_methods = ['lanczos', 'nearest', 'bilinear', 'bicubic'] + return {'required': {'image': ('IMAGE',), 'segs': ('SEGS',), 'basic_pipe': ('BASIC_PIPE',), 'rescale_factor': ('FLOAT', {'default': 2, 'min': 0.01, 'max': 100.0, 'step': 0.01}), 'resampling_method': (resampling_methods,), 'supersample': (['true', 'false'],), 'rounding_modulus': ('INT', {'default': 8, 'min': 8, 'max': 1024, 'step': 8}), '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}), 'inpaint_model': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'}), 'noise_mask_feather': ('INT', {'default': 20, 'min': 0, 'max': 100, 'step': 1})}, 'optional': {'upscale_model_opt': ('UPSCALE_MODEL',), 'upscaler_hook_opt': ('UPSCALER_HOOK',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + @staticmethod + def doit(image, segs, basic_pipe, rescale_factor, resampling_method, supersample, rounding_modulus, seed, steps, cfg, sampler_name, scheduler, denoise, feather, inpaint_model, noise_mask_feather, upscale_model_opt=None, upscaler_hook_opt=None): + (model, clip, vae, positive, negative) = basic_pipe + return SEGSUpscaler.doit(image, segs, model, clip, vae, rescale_factor, resampling_method, supersample, rounding_modulus, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, inpaint_model, noise_mask_feather, upscale_model_opt=upscale_model_opt, upscaler_hook_opt=upscaler_hook_opt) +``` \ No newline at end of file diff --git a/docs/SRFloatPromptInput.md b/docs/SRFloatPromptInput.md new file mode 100644 index 0000000..54c9055 --- /dev/null +++ b/docs/SRFloatPromptInput.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: SRFloatPromptInput +- Category: Mikey/Meta +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +SRFloatPromptInput节点旨在处理和管理浮点数值。它在接收和存储输入值方面发挥着关键作用,这些输入值随后在后续的计算操作中被使用。该节点确保输入是一个浮点数,从而在整个系统中维护数据的完整性。 + +# Input types +## Required +- input_float + - input_float参数对于节点的操作至关重要,因为它表示要处理的浮点值。它是一个必需的输入,表明了它在节点功能中的基本重要性。节点依赖此参数执行其指定的任务。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- unique_id + - unique_id参数在节点操作中作为input_float值的标识符。虽然它不是强制性的,但它可以用来跟踪和引用特定的输入,增强节点管理和组织数据的能力。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +- prompt + - prompt参数用于促进与节点的交互,允许自定义输入过程。它是一个可选输入,可以用来根据特定要求或环境调整节点的行为。 + - Comfy dtype: PROMPT + - Python dtype: dict + +# Output types +- result + - result参数代表节点处理input_float后的输出。它标志着节点操作的完成,并将结果返回给用户以供进一步使用或分析。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SRFloatPromptInput: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input_float': ('FLOAT', {'forceInput': True})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('FLOAT',) + FUNCTION = 'add' + CATEGORY = 'Mikey/Meta' + + def add(self, input_float, unique_id=None, prompt=None): + prompt.get(str(unique_id))['inputs']['sr_val'] = str(input_float) + return (input_float,) +``` \ No newline at end of file diff --git a/docs/SRIntPromptInput.md b/docs/SRIntPromptInput.md new file mode 100644 index 0000000..43b203b --- /dev/null +++ b/docs/SRIntPromptInput.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: SRIntPromptInput +- Category: Mikey/Meta +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +SRIntPromptInput节点旨在将整数输入集成到结构化的提示格式中。它在数据预处理中扮演着关键角色,确保整数值被正确地嵌入到提示结构中,从而促进依赖于这种结构化数据的后续操作。 + +# Input types +## Required +- input_int + - 参数'input_int'对于节点的操作至关重要,因为它表示要合并到提示中的整数值。其正确输入对于提示的结构化格式至关重要,影响后续处理。 + - Comfy dtype: INT + - Python dtype: int +- unique_id + - 参数'unique_id'是一个唯一标识符,用于引用提示中的特定条目。它对于确保整数输入与提示结构中预期的上下文正确关联至关重要。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +- prompt + - 参数'prompt'是一个字典,包含结构化的提示信息。它对节点至关重要,因为这是整数输入被嵌入的地方,影响节点的最终输出。 + - Comfy dtype: PROMPT + - Python dtype: Dict[str, Dict[str, str]] +## Optional +- extra_pnginfo + - 参数'extra_pnginfo'虽然是可选的,但可以提供可能与提示相关的附加上下文或元数据。它增强了结构化数据的丰富性,并可能影响后续节点如何解释提示。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: str + +# Output types +- output_int + - 参数'output_int'代表已成功集成到提示中的原始整数值。它标志着节点主要功能的完成,对于后续操作中数据流的连续性至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SRIntPromptInput: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input_int': ('INT', {'forceInput': True})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('output_int',) + FUNCTION = 'add' + CATEGORY = 'Mikey/Meta' + + def add(self, input_int, extra_pnginfo, unique_id, prompt): + prompt.get(str(unique_id))['inputs']['sr_val'] = str(input_int) + return (input_int,) +``` \ No newline at end of file diff --git a/docs/SRStringPromptInput.md b/docs/SRStringPromptInput.md new file mode 100644 index 0000000..dc88fc3 --- /dev/null +++ b/docs/SRStringPromptInput.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: SRStringPromptInput +- Category: Mikey/Meta +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +SRStringPromptInput节点旨在接受和处理文本输入,特别适用于字符串数据。它在处理字符串提示方面发挥关键作用,通过将它们整合成可用于各种应用的结构化格式。该节点确保输入的字符串被正确记录,并与唯一标识符关联,便于在后续操作中检索和使用。 + +# Input types +## Required +- input_str + - input_str参数对于节点的操作至关重要,因为它代表了要处理的文本数据。它是节点处理的核心元素,其质量直接影响节点的输出和后续数据处理。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- unique_id + - unique_id参数虽然是可选的,但在节点中起着关键作用,它为每个输入字符串提供独特的标识符。这有助于索引和引用输入字符串以备将来使用,从而提高了节点在管理和检索数据方面的效率。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +- prompt + - 当使用prompt参数时,它通过将输入字符串与特定提示关联,为输入字符串增加了一层上下文。这在输入需要在特定上下文中理解的情况下特别有用,从而丰富了节点的功能。 + - Comfy dtype: PROMPT + - Python dtype: dict + +# Output types +- output + - SRStringPromptInput节点的输出是已处理的输入字符串,它已成功记录并与提供的唯一标识符和提示关联。这个输出很重要,因为它确认了输入数据已成功集成到系统中。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SRStringPromptInput: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input_str': ('STRING', {'forceInput': True})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'add' + CATEGORY = 'Mikey/Meta' + + def add(self, input_str, unique_id=None, prompt=None): + prompt.get(str(unique_id))['inputs']['sr_val'] = input_str + return (input_str,) +``` \ No newline at end of file diff --git a/docs/STMFNet VFI.md b/docs/STMFNet VFI.md new file mode 100644 index 0000000..b962b15 --- /dev/null +++ b/docs/STMFNet VFI.md @@ -0,0 +1,100 @@ +# Documentation +- Class name: STMFNet_VFI +- Category: ComfyUI-Frame-Interpolation/VFI +- Output node: False +- Repo Ref: https://github.com/Fannovel16/ComfyUI-Frame-Interpolation + +STMFNet_VFI节点旨在执行视频帧插值,增强视频序列中帧之间过渡的平滑度。它通过生成原始素材中不存在的中间帧来实现这一点,从而增加帧率并提高整体视觉质量。 + +# Input types +## Required +- ckpt_name + - 检查点名称对于加载帧插值过程所需的预训练模型权重至关重要。它确保模型具有生成准确中间帧所需的必要参数。 + - Comfy dtype: str + - Python dtype: str +- frames + - 输入帧是节点处理以创建插值帧的原始视频数据。这些帧的质量和分辨率直接影响插值的输出。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor +## Optional +- clear_cache_after_n_frames + - 此参数确定系统在处理期间多久清除一次缓存,这有助于管理内存使用。对于长视频序列来说尤其重要,以防止内存过载。 + - Comfy dtype: int + - Python dtype: int +- multiplier + - 乘数用于确定帧率将增加的倍数。然而,当前实现仅支持乘数为2。 + - Comfy dtype: int + - Python dtype: int +- duplicate_first_last_frames + - 启用此选项时,它会在输出中复制第一帧和最后一帧,这可以为插值视频序列提供更平滑的开始和结束。 + - Comfy dtype: bool + - Python dtype: bool +- optional_interpolation_states + - 此可选参数允许自定义插值状态,可以根据特定标准在插值过程中跳过某些帧。 + - Comfy dtype: InterpolationStateList + - Python dtype: InterpolationStateList + +# Output types +- interpolated_frames + - STMFNet_VFI节点的输出是插值后的视频帧。这些帧是帧插值过程的结果,准备用于视频编辑或播放。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class STMFNet_VFI: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (['stmfnet.pth'],), 'frames': ('IMAGE',), 'clear_cache_after_n_frames': ('INT', {'default': 10, 'min': 1, 'max': 1000}), 'multiplier': ('INT', {'default': 2, 'min': 2, 'max': 2}), 'duplicate_first_last_frames': ('BOOLEAN', {'default': False})}, 'optional': {'optional_interpolation_states': ('INTERPOLATION_STATES',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'vfi' + CATEGORY = 'ComfyUI-Frame-Interpolation/VFI' + + def vfi(self, ckpt_name: typing.AnyStr, frames: torch.Tensor, clear_cache_after_n_frames=10, multiplier: typing.SupportsInt=2, duplicate_first_last_frames: bool=False, optional_interpolation_states: InterpolationStateList=None, **kwargs): + from .stmfnet_arch import STMFNet_Model + if multiplier != 2: + warnings.warn('Currently, ST-MFNet only supports 2x interpolation. The process will continue but please set multiplier=2 afterward') + assert_batch_size(frames, batch_size=4, vfi_name='ST-MFNet') + interpolation_states = optional_interpolation_states + model_path = load_file_from_github_release(MODEL_TYPE, ckpt_name) + model = STMFNet_Model() + model.load_state_dict(torch.load(model_path)) + model = model.eval().to(device) + frames = preprocess_frames(frames) + number_of_frames_processed_since_last_cleared_cuda_cache = 0 + output_frames = [] + for frame_itr in range(len(frames) - 3): + if interpolation_states is not None and interpolation_states.is_frame_skipped(frame_itr) and interpolation_states.is_frame_skipped(frame_itr + 1): + continue + (frame0, frame1, frame2, frame3) = (frames[frame_itr:frame_itr + 1].float(), frames[frame_itr + 1:frame_itr + 2].float(), frames[frame_itr + 2:frame_itr + 3].float(), frames[frame_itr + 3:frame_itr + 4].float()) + new_frame = model(frame0.to(device), frame1.to(device), frame2.to(device), frame3.to(device)).detach().cpu() + number_of_frames_processed_since_last_cleared_cuda_cache += 2 + if frame_itr == 0: + output_frames.append(frame0) + if duplicate_first_last_frames: + output_frames.append(frame0) + output_frames.append(frame1) + output_frames.append(new_frame) + output_frames.append(frame2) + if frame_itr == len(frames) - 4: + output_frames.append(frame3) + if duplicate_first_last_frames: + output_frames.append(frame3) + if number_of_frames_processed_since_last_cleared_cuda_cache >= clear_cache_after_n_frames: + print('Comfy-VFI: Clearing cache...') + soft_empty_cache() + number_of_frames_processed_since_last_cleared_cuda_cache = 0 + print('Comfy-VFI: Done cache clearing') + gc.collect() + dtype = torch.float32 + output_frames = [frame.cpu().to(dtype=dtype) for frame in output_frames] + out = torch.cat(output_frames, dim=0) + print('Comfy-VFI: Final clearing cache...') + soft_empty_cache() + print('Comfy-VFI: Done cache clearing') + return (postprocess_frames(out),) +``` \ No newline at end of file diff --git a/docs/SUPIR_Upscale.md b/docs/SUPIR_Upscale.md new file mode 100644 index 0000000..17b5a68 --- /dev/null +++ b/docs/SUPIR_Upscale.md @@ -0,0 +1,197 @@ +# Documentation +- Class name: SUPIR_Upscale +- Category: SUPIR +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-SUPIR.git + +SUPIR_Upscale节点旨在通过一个复杂的处理过程提高输入图像的分辨率,包括放大、颜色校正和降噪。它利用先进的深度学习模型执行这些任务,确保输出的图像质量高且细节丰富。 + +# Input types +## Required +- supir_model + - SUPIR模型检查点的路径,对于放大过程至关重要,因为它包含了模型正确运行所需的预训练权重。 + - Comfy dtype: STRING + - Python dtype: str +- image + - 要放大的输入图像,是增强过程的主要对象。输出图像的质量和分辨率严重依赖于此输入。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- steps + - 在扩散过程中使用的步骤数。更多的步骤通常会导致更好的结果,但会增加计算时间。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- upscaled_image + - 节点的最终输出即放大后的图像。它代表了放大过程的顶点,是SUPIR_Upscale节点功能的主要结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SUPIR_Upscale: + upscale_methods = ['nearest-exact', 'bilinear', 'area', 'bicubic', 'lanczos'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'supir_model': (folder_paths.get_filename_list('checkpoints'),), 'sdxl_model': (folder_paths.get_filename_list('checkpoints'),), 'image': ('IMAGE',), 'seed': ('INT', {'default': 123, 'min': 0, 'max': 18446744073709551615, 'step': 1}), 'resize_method': (s.upscale_methods, {'default': 'lanczos'}), 'scale_by': ('FLOAT', {'default': 1.0, 'min': 0.01, 'max': 20.0, 'step': 0.01}), 'steps': ('INT', {'default': 45, 'min': 3, 'max': 4096, 'step': 1}), 'restoration_scale': ('FLOAT', {'default': -1.0, 'min': -1.0, 'max': 6.0, 'step': 1.0}), 'cfg_scale': ('FLOAT', {'default': 4.0, 'min': 0, 'max': 100, 'step': 0.01}), 'a_prompt': ('STRING', {'multiline': True, 'default': 'high quality, detailed'}), 'n_prompt': ('STRING', {'multiline': True, 'default': 'bad quality, blurry, messy'}), 's_churn': ('INT', {'default': 5, 'min': 0, 'max': 40, 'step': 1}), 's_noise': ('FLOAT', {'default': 1.003, 'min': 1.0, 'max': 1.1, 'step': 0.001}), 'control_scale': ('FLOAT', {'default': 1.0, 'min': 0, 'max': 10.0, 'step': 0.05}), 'cfg_scale_start': ('FLOAT', {'default': 4.0, 'min': 0.0, 'max': 100.0, 'step': 0.05}), 'control_scale_start': ('FLOAT', {'default': 0.0, 'min': 0, 'max': 1.0, 'step': 0.05}), 'color_fix_type': (['None', 'AdaIn', 'Wavelet'], {'default': 'Wavelet'}), 'keep_model_loaded': ('BOOLEAN', {'default': True}), 'use_tiled_vae': ('BOOLEAN', {'default': True}), 'encoder_tile_size_pixels': ('INT', {'default': 512, 'min': 64, 'max': 8192, 'step': 64}), 'decoder_tile_size_latent': ('INT', {'default': 64, 'min': 32, 'max': 8192, 'step': 64})}, 'optional': {'captions': ('STRING', {'forceInput': True, 'multiline': False, 'default': ''}), 'diffusion_dtype': (['fp16', 'bf16', 'fp32', 'auto'], {'default': 'auto'}), 'encoder_dtype': (['bf16', 'fp32', 'auto'], {'default': 'auto'}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 128, 'step': 1}), 'use_tiled_sampling': ('BOOLEAN', {'default': False}), 'sampler_tile_size': ('INT', {'default': 1024, 'min': 64, 'max': 4096, 'step': 32}), 'sampler_tile_stride': ('INT', {'default': 512, 'min': 32, 'max': 2048, 'step': 32}), 'fp8_unet': ('BOOLEAN', {'default': False}), 'fp8_vae': ('BOOLEAN', {'default': False}), 'sampler': (['RestoreDPMPP2MSampler', 'RestoreEDMSampler'], {'default': 'RestoreEDMSampler'})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('upscaled_image',) + FUNCTION = 'process' + CATEGORY = 'SUPIR' + + def process(self, steps, image, color_fix_type, seed, scale_by, cfg_scale, resize_method, s_churn, s_noise, encoder_tile_size_pixels, decoder_tile_size_latent, control_scale, cfg_scale_start, control_scale_start, restoration_scale, keep_model_loaded, a_prompt, n_prompt, sdxl_model, supir_model, use_tiled_vae, use_tiled_sampling=False, sampler_tile_size=128, sampler_tile_stride=64, captions='', diffusion_dtype='auto', encoder_dtype='auto', batch_size=1, fp8_unet=False, fp8_vae=False, sampler='RestoreEDMSampler'): + device = mm.get_torch_device() + mm.unload_all_models() + SUPIR_MODEL_PATH = folder_paths.get_full_path('checkpoints', supir_model) + SDXL_MODEL_PATH = folder_paths.get_full_path('checkpoints', sdxl_model) + config_path = os.path.join(script_directory, 'options/SUPIR_v0.yaml') + config_path_tiled = os.path.join(script_directory, 'options/SUPIR_v0_tiled.yaml') + clip_config_path = os.path.join(script_directory, 'configs/clip_vit_config.json') + tokenizer_path = os.path.join(script_directory, 'configs/tokenizer') + custom_config = {'sdxl_model': sdxl_model, 'diffusion_dtype': diffusion_dtype, 'encoder_dtype': encoder_dtype, 'use_tiled_vae': use_tiled_vae, 'supir_model': supir_model, 'use_tiled_sampling': use_tiled_sampling, 'fp8_unet': fp8_unet, 'fp8_vae': fp8_vae, 'sampler': sampler} + if diffusion_dtype == 'auto': + try: + if mm.should_use_fp16(): + print('Diffusion using fp16') + dtype = torch.float16 + model_dtype = 'fp16' + if mm.should_use_bf16(): + print('Diffusion using bf16') + dtype = torch.bfloat16 + model_dtype = 'bf16' + else: + print('Diffusion using using fp32') + dtype = torch.float32 + model_dtype = 'fp32' + except: + raise AttributeError("ComfyUI too old, can't autodecet properly. Set your dtypes manually.") + else: + print(f'Diffusion using using {diffusion_dtype}') + dtype = convert_dtype(diffusion_dtype) + model_dtype = diffusion_dtype + if encoder_dtype == 'auto': + try: + if mm.should_use_bf16(): + print('Encoder using bf16') + vae_dtype = 'bf16' + else: + print('Encoder using using fp32') + vae_dtype = 'fp32' + except: + raise AttributeError("ComfyUI too old, can't autodetect properly. Set your dtypes manually.") + else: + vae_dtype = encoder_dtype + print(f'Encoder using using {vae_dtype}') + if not hasattr(self, 'model') or self.model is None or self.current_config != custom_config: + self.current_config = custom_config + self.model = None + mm.soft_empty_cache() + if use_tiled_sampling: + config = OmegaConf.load(config_path_tiled) + config.model.params.sampler_config.params.tile_size = sampler_tile_size // 8 + config.model.params.sampler_config.params.tile_stride = sampler_tile_stride // 8 + config.model.params.sampler_config.target = f'.sgm.modules.diffusionmodules.sampling.Tiled{sampler}' + print('Using tiled sampling') + else: + config = OmegaConf.load(config_path) + config.model.params.sampler_config.target = f'.sgm.modules.diffusionmodules.sampling.{sampler}' + print('Using non-tiled sampling') + if XFORMERS_IS_AVAILABLE: + config.model.params.control_stage_config.params.spatial_transformer_attn_type = 'softmax-xformers' + config.model.params.network_config.params.spatial_transformer_attn_type = 'softmax-xformers' + config.model.params.first_stage_config.params.ddconfig.attn_type = 'vanilla-xformers' + config.model.params.ae_dtype = vae_dtype + config.model.params.diffusion_dtype = model_dtype + self.model = instantiate_from_config(config.model).cpu() + try: + print(f'Attempting to load SUPIR model: [{SUPIR_MODEL_PATH}]') + supir_state_dict = load_state_dict(SUPIR_MODEL_PATH) + except: + raise Exception('Failed to load SUPIR model') + try: + print(f'Attempting to load SDXL model: [{SDXL_MODEL_PATH}]') + sdxl_state_dict = load_state_dict(SDXL_MODEL_PATH) + except: + raise Exception('Failed to load SDXL model') + self.model.load_state_dict(supir_state_dict, strict=False) + self.model.load_state_dict(sdxl_state_dict, strict=False) + del supir_state_dict + try: + print('Loading first clip model from SDXL checkpoint') + replace_prefix = {} + replace_prefix['conditioner.embedders.0.transformer.'] = '' + sd = comfy.utils.state_dict_prefix_replace(sdxl_state_dict, replace_prefix, filter_keys=False) + clip_text_config = CLIPTextConfig.from_pretrained(clip_config_path) + self.model.conditioner.embedders[0].tokenizer = CLIPTokenizer.from_pretrained(tokenizer_path) + self.model.conditioner.embedders[0].transformer = CLIPTextModel(clip_text_config) + self.model.conditioner.embedders[0].transformer.load_state_dict(sd, strict=False) + self.model.conditioner.embedders[0].eval() + for param in self.model.conditioner.embedders[0].parameters(): + param.requires_grad = False + except: + raise Exception('Failed to load first clip model from SDXL checkpoint') + del sdxl_state_dict + try: + print('Loading second clip model from SDXL checkpoint') + replace_prefix2 = {} + replace_prefix2['conditioner.embedders.1.model.'] = '' + sd = comfy.utils.state_dict_prefix_replace(sd, replace_prefix2, filter_keys=True) + clip_g = build_text_model_from_openai_state_dict(sd, cast_dtype=dtype) + self.model.conditioner.embedders[1].model = clip_g + except: + raise Exception('Failed to load second clip model from SDXL checkpoint') + del sd, clip_g + mm.soft_empty_cache() + self.model.to(dtype) + if fp8_unet: + self.model.model.to(torch.float8_e4m3fn) + if fp8_vae: + self.model.first_stage_model.to(torch.float8_e4m3fn) + if use_tiled_vae: + self.model.init_tile_vae(encoder_tile_size=encoder_tile_size_pixels, decoder_tile_size=decoder_tile_size_latent) + (upscaled_image,) = ImageScaleBy.upscale(self, image, resize_method, scale_by) + (B, H, W, C) = upscaled_image.shape + new_height = H if H % 64 == 0 else (H // 64 + 1) * 64 + new_width = W if W % 64 == 0 else (W // 64 + 1) * 64 + upscaled_image = upscaled_image.permute(0, 3, 1, 2) + resized_image = F.interpolate(upscaled_image, size=(new_height, new_width), mode='bicubic', align_corners=False) + resized_image = resized_image.to(device) + captions_list = [] + captions_list.append(captions) + print('captions: ', captions_list) + use_linear_CFG = cfg_scale_start > 0 + use_linear_control_scale = control_scale_start > 0 + out = [] + pbar = comfy.utils.ProgressBar(B) + batched_images = [resized_image[i:i + batch_size] for i in range(0, len(resized_image), batch_size)] + captions_list = captions_list * resized_image.shape[0] + batched_captions = [captions_list[i:i + batch_size] for i in range(0, len(captions_list), batch_size)] + mm.soft_empty_cache() + i = 1 + for (imgs, caps) in zip(batched_images, batched_captions): + try: + samples = self.model.batchify_sample(imgs, caps, num_steps=steps, restoration_scale=restoration_scale, s_churn=s_churn, s_noise=s_noise, cfg_scale=cfg_scale, control_scale=control_scale, seed=seed, num_samples=1, p_p=a_prompt, n_p=n_prompt, color_fix_type=color_fix_type, use_linear_CFG=use_linear_CFG, use_linear_control_scale=use_linear_control_scale, cfg_scale_start=cfg_scale_start, control_scale_start=control_scale_start) + except torch.cuda.OutOfMemoryError as e: + mm.free_memory(mm.get_total_memory(mm.get_torch_device()), mm.get_torch_device()) + self.model = None + mm.soft_empty_cache() + print("It's likely that too large of an image or batch_size for SUPIR was used, and it has devoured all of the memory it had reserved, you may need to restart ComfyUI. Make sure you are using tiled_vae, you can also try using fp8 for reduced memory usage if your system supports it.") + raise e + out.append(samples.squeeze(0).cpu()) + print('Sampled ', i * len(imgs), ' out of ', B) + i = i + 1 + pbar.update(1) + if not keep_model_loaded: + self.model = None + mm.soft_empty_cache() + if len(out[0].shape) == 4: + out_stacked = torch.cat(out, dim=0).cpu().to(torch.float32).permute(0, 2, 3, 1) + else: + out_stacked = torch.stack(out, dim=0).cpu().to(torch.float32).permute(0, 2, 3, 1) + (final_image,) = ImageScale.upscale(self, out_stacked, resize_method, W, H, crop='disabled') + return (final_image,) +``` \ No newline at end of file diff --git a/docs/SUPIR_decode.md b/docs/SUPIR_decode.md new file mode 100644 index 0000000..ade8e87 --- /dev/null +++ b/docs/SUPIR_decode.md @@ -0,0 +1,81 @@ +# Documentation +- Class name: SUPIR_decode +- Category: SUPIR +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-SUPIR.git + +SUPIR_decode节点旨在将潜在变量转换为视觉数据,在SUPIR系统的生成过程中扮演关键角色。它作为数据抽象表示与有形成果之间的接口,能够从编码信息中创建图像。该节点强调SUPIR框架中的重建方面,专注于生成视觉内容的保真度和质量。 + +# Input types +## Required +- SUPIR_VAE + - SUPIR_VAE参数代表SUPIR框架中使用的变化自编码器模型。它对解码过程至关重要,因为它包含了将潜在代码转换为图像所需的信息和结构。此参数在确保生成的视觉数据的准确性和连贯性方面起着关键作用。 + - Comfy dtype: SUPIRVAE + - Python dtype: torch.nn.Module +- latents + - latents参数是一组编码变量,构成了图像生成过程的基础。它是关键的输入,因为它提供了SUPIR_decode节点将用来重建图像的基础结构和内容。latents的质量直接影响最终输出,使其成为生成过程中的重要组件。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +## Optional +- use_tiled_vae + - use_tiled_vae参数是一个布尔标志,用于确定节点是否应采用分块方法进行解码。这种方法可以通过一次处理较小的部分来提高解码过程的效率和管理性,特别是对于较大的图像。这是优化SUPIR_decode节点性能的重要选项。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- decoder_tile_size + - decoder_tile_size参数指定了激活分块解码方法时使用的瓦片的尺寸。它在平衡计算负载和内存使用方面起着至关重要的作用,确保解码过程针对可用的硬件资源进行了优化。适当的瓦片尺寸可以导致更高效和更快的图像重建。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 图像输出是解码过程的结果,SUPIR_decode节点已成功将潜在变量转换为视觉表示。这个输出是一个高分辨率的图像,反映了输入的latents,并体现了SUPIR系统的生成能力。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SUPIR_decode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'SUPIR_VAE': ('SUPIRVAE',), 'latents': ('LATENT',), 'use_tiled_vae': ('BOOLEAN', {'default': True}), 'decoder_tile_size': ('INT', {'default': 512, 'min': 64, 'max': 8192, 'step': 64})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'decode' + CATEGORY = 'SUPIR' + + def decode(self, SUPIR_VAE, latents, use_tiled_vae, decoder_tile_size): + device = mm.get_torch_device() + mm.unload_all_models() + samples = latents['samples'] + dtype = SUPIR_VAE.dtype + (orig_H, orig_W) = latents['original_size'] + (B, H, W, C) = samples.shape + pbar = comfy.utils.ProgressBar(B) + SUPIR_VAE.to(device) + if use_tiled_vae: + from .SUPIR.utils.tilevae import VAEHook + if not hasattr(SUPIR_VAE.decoder, 'original_forward'): + SUPIR_VAE.decoder.original_forward = SUPIR_VAE.decoder.forward + SUPIR_VAE.decoder.forward = VAEHook(SUPIR_VAE.decoder, decoder_tile_size // 8, is_decoder=True, fast_decoder=False, fast_encoder=False, color_fix=False, to_gpu=True) + elif hasattr(SUPIR_VAE.decoder, 'original_forward'): + SUPIR_VAE.decoder.forward = SUPIR_VAE.decoder.original_forward + out = [] + for sample in samples: + autocast_condition = dtype != torch.float32 and (not comfy.model_management.is_device_mps(device)) + with torch.autocast(comfy.model_management.get_autocast_device(device), dtype=dtype) if autocast_condition else nullcontext(): + sample = 1.0 / 0.13025 * sample + decoded_image = SUPIR_VAE.decode(sample.unsqueeze(0)).float() + out.append(decoded_image) + pbar.update(1) + decoded_out = torch.cat(out, dim=0) + if decoded_out.shape[2] != orig_H or decoded_out.shape[3] != orig_W: + print('Restoring original dimensions: ', orig_W, 'x', orig_H) + decoded_out = F.interpolate(decoded_out, size=(orig_H, orig_W), mode='bicubic') + decoded_out = decoded_out.cpu().to(torch.float32).permute(0, 2, 3, 1) + decoded_out = torch.clip(decoded_out, 0, 1) + return (decoded_out,) +``` \ No newline at end of file diff --git a/docs/SUPIR_encode.md b/docs/SUPIR_encode.md new file mode 100644 index 0000000..b027484 --- /dev/null +++ b/docs/SUPIR_encode.md @@ -0,0 +1,103 @@ +# Documentation +- Class name: SUPIR_encode +- Category: SUPIR +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-SUPIR.git + +SUPIR_encode节点旨在使用变分自编码器模型高效处理和编码图像到潜在空间。它通过根据输入图像大小和指定的瓦片大小调整模型的前向传递来优化编码过程,确保计算效率和内存保持在合理范围内。 + +# Input types +## Required +- SUPIR_VAE + - SUPIR_VAE参数代表用于编码输入图像的变分自编码器模型。它对于节点的操作至关重要,因为它定义了在编码过程中将应用的架构和参数。 + - Comfy dtype: SUPIRVAE + - Python dtype: torch.nn.Module +- image + - image参数是SUPIR_encode节点的输入数据。它至关重要,因为它是编码过程的对象,图像的质量和尺寸直接影响最终的潜在表示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- encoder_dtype + - encoder_dtype参数指定了编码器内部计算使用的数据类型。它在平衡节点的性能和精度方面发挥重要作用,影响编码的速度和质量。 + - Comfy dtype: STR + - Python dtype: str +- use_tiled_vae + - use_tiled_vae参数决定节点是否应使用分块方法进行编码过程。这对于处理更大的图像很有帮助,通过将它们分解成更小、更易管理的部分,可能会提高内存使用和编码效率。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- encoder_tile_size + - encoder_tile_size参数定义了启用分块编码方法时使用的瓦片大小。它对于优化编码过程很重要,特别是对于高分辨率图像,通过控制瓦片划分的粒度。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- latent + - latent参数代表SUPIR_encode节点的输出,即输入图像的编码版本,形式为潜在向量。这种压缩表示对于管道内的进一步分析或生成任务至关重要。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SUPIR_encode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'SUPIR_VAE': ('SUPIRVAE',), 'image': ('IMAGE',), 'use_tiled_vae': ('BOOLEAN', {'default': True}), 'encoder_tile_size': ('INT', {'default': 512, 'min': 64, 'max': 8192, 'step': 64}), 'encoder_dtype': (['bf16', 'fp32', 'auto'], {'default': 'auto'})}} + RETURN_TYPES = ('LATENT',) + RETURN_NAMES = ('latent',) + FUNCTION = 'encode' + CATEGORY = 'SUPIR' + + def encode(self, SUPIR_VAE, image, encoder_dtype, use_tiled_vae, encoder_tile_size): + device = mm.get_torch_device() + mm.unload_all_models() + if encoder_dtype == 'auto': + try: + if mm.should_use_bf16(): + print('Encoder using bf16') + vae_dtype = 'bf16' + else: + print('Encoder using using fp32') + vae_dtype = 'fp32' + except: + raise AttributeError("ComfyUI version too old, can't autodetect properly. Set your dtypes manually.") + else: + vae_dtype = encoder_dtype + print(f'Encoder using using {vae_dtype}') + dtype = convert_dtype(vae_dtype) + image = image.permute(0, 3, 1, 2) + (B, C, H, W) = image.shape + downscale_ratio = 32 + (orig_H, orig_W) = (H, W) + if W % downscale_ratio != 0: + W = W - W % downscale_ratio + if H % downscale_ratio != 0: + H = H - H % downscale_ratio + if orig_H % downscale_ratio != 0 or orig_W % downscale_ratio != 0: + image = F.interpolate(image, size=(H, W), mode='bicubic') + resized_image = image.to(device) + if use_tiled_vae: + from .SUPIR.utils.tilevae import VAEHook + if not hasattr(SUPIR_VAE.encoder, 'original_forward'): + SUPIR_VAE.encoder.original_forward = SUPIR_VAE.encoder.forward + SUPIR_VAE.encoder.forward = VAEHook(SUPIR_VAE.encoder, encoder_tile_size, is_decoder=False, fast_decoder=False, fast_encoder=False, color_fix=False, to_gpu=True) + elif hasattr(SUPIR_VAE.encoder, 'original_forward'): + SUPIR_VAE.encoder.forward = SUPIR_VAE.encoder.original_forward + pbar = comfy.utils.ProgressBar(B) + out = [] + for img in resized_image: + SUPIR_VAE.to(dtype).to(device) + autocast_condition = dtype != torch.float32 and (not comfy.model_management.is_device_mps(device)) + with torch.autocast(comfy.model_management.get_autocast_device(device), dtype=dtype) if autocast_condition else nullcontext(): + z = SUPIR_VAE.encode(img.unsqueeze(0)) + z = z * 0.13025 + out.append(z) + pbar.update(1) + if len(out[0].shape) == 4: + samples_out_stacked = torch.cat(out, dim=0) + else: + samples_out_stacked = torch.stack(out, dim=0) + return ({'samples': samples_out_stacked, 'original_size': [orig_H, orig_W]},) +``` \ No newline at end of file diff --git a/docs/SamplerNames_.md b/docs/SamplerNames_.md new file mode 100644 index 0000000..342b70b --- /dev/null +++ b/docs/SamplerNames_.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: CreateSampler_names +- Category: ♾️Mixlab/Utils +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点简化了生成采样器名称列表的过程,这些名称可以在各种采样应用中使用。它强调节点在准备和清理输入以提取有效的采样器名称方面的作用,确保输出是一套干净且可用的标识符集合。 + +# Input types +## Required +- sampler_names + - 这个参数至关重要,因为它提供了将从中提取采样器名称的原始文本。它对节点执行的影响很大,因为输入文本的质量和格式直接影响到生成的采样器名称的准确性和实用性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- sampler_names + - 输出代表一个经过精炼的有效采样器名称列表,去除了所有不必要的信息。这个列表对于依赖准确采样器标识符正确运行的下游过程至关重要。 + - Comfy dtype: LIST + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CreateSampler_names: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'sampler_names': ('STRING', {'multiline': True, 'default': '\n'.join(comfy.samplers.KSampler.SAMPLERS), 'dynamicPrompts': False})}} + RETURN_TYPES = (any_type,) + RETURN_NAMES = ('sampler_names',) + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (True,) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Utils' + + def run(self, sampler_names): + sampler_names = sampler_names.split('\n') + sampler_names = [name for name in sampler_names if name.strip()] + return (sampler_names,) +``` \ No newline at end of file diff --git a/docs/Samples Passthrough (Stat System).md b/docs/Samples Passthrough (Stat System).md new file mode 100644 index 0000000..b106edf --- /dev/null +++ b/docs/Samples Passthrough (Stat System).md @@ -0,0 +1,62 @@ +# Documentation +- Class name: WAS_Samples_Passthrough_Stat_System +- Category: WAS Suite/Debug +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Samples_Passthrough_Stat_System 类的 `stat_system` 方法旨在提供系统当前状态的统计概览。它捕获并记录关键的系统指标,如 RAM 和 VRAM 使用情况以及硬盘空间利用率。此方法对于监控系统的健康状况和性能至关重要,提供了对资源消耗的洞察,而无需深入了解底层数据收集过程的具体细节。 + +# Input types +## Required +- samples + - “samples”参数对于执行 `stat_system` 方法至关重要,因为它代表了系统操作的潜在空间样本。正是通过这些样本,评估了系统的资源利用率,使这个参数成为节点功能不可或缺的一部分。 + - Comfy dtype: LATENT + - Python dtype: Union[torch.Tensor, List[torch.Tensor]] + +# Output types +- samples + - “samples”输出参数表示通过系统传递的原始潜在空间样本。它作为系统已处理输入且未发生更改的确认,保证了数据的完整性,以便进一步使用或分析。 + - Comfy dtype: LATENT + - Python dtype: Union[torch.Tensor, List[torch.Tensor]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Samples_Passthrough_Stat_System: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'samples': ('LATENT',)}} + RETURN_TYPES = ('LATENT',) + RETURN_NAMES = ('samples',) + FUNCTION = 'stat_system' + CATEGORY = 'WAS Suite/Debug' + + def stat_system(self, samples): + log = '' + for stat in self.get_system_stats(): + log += stat + '\n' + cstr('\n' + log).msg.print() + return (samples,) + + def get_system_stats(self): + import psutil + ram = psutil.virtual_memory() + ram_used = ram.used / 1024 ** 3 + ram_total = ram.total / 1024 ** 3 + ram_stats = f'Used RAM: {ram_used:.2f} GB / Total RAM: {ram_total:.2f} GB' + device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + vram_used = torch.cuda.memory_allocated(device) / 1024 ** 3 + vram_total = torch.cuda.get_device_properties(device).total_memory / 1024 ** 3 + vram_stats = f'Used VRAM: {vram_used:.2f} GB / Total VRAM: {vram_total:.2f} GB' + hard_drive = psutil.disk_usage('/') + used_space = hard_drive.used / 1024 ** 3 + total_space = hard_drive.total / 1024 ** 3 + hard_drive_stats = f'Used Space: {used_space:.2f} GB / Total Space: {total_space:.2f} GB' + return [ram_stats, vram_stats, hard_drive_stats] +``` \ No newline at end of file diff --git a/docs/Save Gif (mtb).md b/docs/Save Gif (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Save Image Grid (mtb).md b/docs/Save Image Grid (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Save Image If True.md b/docs/Save Image If True.md new file mode 100644 index 0000000..3480534 --- /dev/null +++ b/docs/Save Image If True.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: SaveImageIfTrue +- Category: Mikey/Image +- Output node: True +- Repo Ref: https://github.com/bash-j/mikey_nodes + +方法 'save_image_if_true' 旨在根据条件保存图像到文件。它评估一个保存条件,如果条件满足,则使用 'SaveImagesMikey' 类来执行实际的图像保存过程,包括处理元数据和文件命名约定。 + +# Input types +## Required +- image + - 图像参数对于节点的操作至关重要,因为它代表了可能被保存的图像。其质量和内容直接影响保存过程的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- save_condition + - save_condition 参数作为保存过程的开关。它非常重要,因为它的值(0或1)决定了图像是否会被保存。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- filename_prefix + - filename_prefix 参数对于定义保存图像文件的前缀很重要。它可以自定义命名约定,特别适用于组织保存的文件。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- result + - result 参数封装了保存操作的结果。它包括诸如图像保存的文件名和子文件夹等详细信息,提供了保存过程的记录。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Union[str, Dict[str, str]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SaveImageIfTrue: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'save_condition': ('INT', {'default': 0, 'min': 0, 'max': 1}), 'filename_prefix': ('STRING', {'default': ''})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = () + FUNCTION = 'save_image_if_true' + OUTPUT_NODE = True + CATEGORY = 'Mikey/Image' + + def save_image_if_true(self, image, save_condition, filename_prefix, prompt=None, extra_pnginfo=None): + if save_condition == 1: + save_images = SaveImagesMikey() + result = save_images.save_images(image, filename_prefix, prompt, extra_pnginfo, positive_prompt='', negative_prompt='') + return result + else: + return {'save_image_if_true': {'filename': '', 'subfolder': ''}} +``` \ No newline at end of file diff --git a/docs/Save Image Sequence (mtb).md b/docs/Save Image Sequence (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Save Image With Prompt Data.md b/docs/Save Image With Prompt Data.md new file mode 100644 index 0000000..89a04aa --- /dev/null +++ b/docs/Save Image With Prompt Data.md @@ -0,0 +1,107 @@ +# Documentation +- Class name: SaveImagesMikey +- Category: Mikey/Image +- Output node: True +- Repo Ref: https://github.com/bash-j/mikey_nodes + +SaveImagesMikey节点旨在处理并保存一系列图像到指定目录。它处理图像数据的转换,以便保存,并可以将元数据(如提示和参数)纳入图像文件中,以供后续参考。该节点在管理图像生成任务的输出方面起着关键作用。 + +# Input types +## Required +- images + - ‘images’参数至关重要,因为它代表了节点将处理和保存的输入图像。节点的功能围绕处理这些图像展开,使这个参数成为节点操作的基本部分。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- filename_prefix + - ‘filename_prefix’参数允许用户为保存的图像文件指定前缀,这对于组织和识别文件非常有用。这个参数有助于定制输出文件的命名约定。 + - Comfy dtype: STRING + - Python dtype: str +- parameters + - ‘parameters’输入很重要,因为它使节点能够在保存的文件中包含有关图像生成过程的额外信息。这对于跟踪和记录图像创建条件至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- positive_prompt + - ‘positive_prompt’参数用于在图像文件的元数据中添加积极的创作方向。它有助于根据引导图像创作的提示对图像进行分类。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt + - ‘negative_prompt’参数用于在图像文件的元数据中包含创造性的限制,这对于理解图像生成过程中施加的限制很重要。 + - Comfy dtype: STRING + - Python dtype: str +- prompt + - ‘prompt’参数是隐藏的,但很重要,因为它提供了影响图像生成的上下文或描述。它用于向图像元数据添加相关信息,以供将来参考。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - ‘extra_pnginfo’参数用于将额外的特定于PNG的元数据包含在保存的图像文件中。这可以增强每个图像可用的信息,对于高级图像管理特别有用。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: str + +# Output types +- ui + - ‘ui’输出提供了保存的图像的结构化表示,包括它们的文件名和子文件夹。这个输出很重要,因为它允许轻松跟踪和管理保存的图像文件。 + - Comfy dtype: DICT + - Python dtype: Dict[str, List[Dict[str, Union[str, int]]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SaveImagesMikey: + + def __init__(self): + self.output_dir = folder_paths.get_output_directory() + self.type = 'output' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'positive_prompt': ('STRING', {'default': 'Positive Prompt'}), 'negative_prompt': ('STRING', {'default': 'Negative Prompt'}), 'filename_prefix': ('STRING', {'default': ''}), 'parameters': ('STRING', {'default': ''})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = () + FUNCTION = 'save_images' + OUTPUT_NODE = True + CATEGORY = 'Mikey/Image' + + def save_images(self, images, filename_prefix='', parameters='', prompt=None, extra_pnginfo=None, positive_prompt='', negative_prompt=''): + filename_prefix = search_and_replace(filename_prefix, extra_pnginfo, prompt) + (full_output_folder, filename, counter, subfolder, filename_prefix) = get_save_image_path(filename_prefix, self.output_dir, images[0].shape[1], images[0].shape[0]) + results = list() + for image in images: + i = 255.0 * image.cpu().numpy() + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) + metadata = PngInfo() + pos_trunc = '' + if prompt is not None: + metadata.add_text('prompt', json.dumps(prompt)) + if extra_pnginfo is not None: + for x in extra_pnginfo: + if x == 'parameters': + text = extra_pnginfo[x].encode('utf-8').decode('utf-8') + metadata.add_text(x, text) + elif x == 'workflow': + metadata.add_text(x, json.dumps(extra_pnginfo[x])) + elif x == 'prompt': + metadata.add_text(x, json.dumps(extra_pnginfo[x])) + else: + metadata.add_text(x, json.dumps(extra_pnginfo[x], ensure_ascii=False)) + if positive_prompt: + metadata.add_text('positive_prompt', positive_prompt) + clean_pos = re.sub('[^a-zA-Z0-9 ]', '', positive_prompt) + pos_trunc = clean_pos.replace(' ', '_')[0:80] + if negative_prompt: + metadata.add_text('negative_prompt', negative_prompt) + if filename_prefix != '': + clean_filename_prefix = re.sub('[^a-zA-Z0-9 _-]', '', filename_prefix) + metadata.add_text('filename_prefix', json.dumps(clean_filename_prefix, ensure_ascii=False)) + file = f'{clean_filename_prefix[:75]}_{counter:05}_.png' + else: + ts_str = datetime.datetime.now().strftime('%y%m%d%H%M%S') + file = f'{ts_str}_{pos_trunc}_{filename}_{counter:05}_.png' + if parameters: + metadata.add_text('parameters', parameters) + img.save(os.path.join(full_output_folder, file), pnginfo=metadata, compress_level=4) + results.append({'filename': file, 'subfolder': subfolder, 'type': self.type}) + counter += 1 + return {'ui': {'images': results}} +``` \ No newline at end of file diff --git a/docs/Save Images Mikey.md b/docs/Save Images Mikey.md new file mode 100644 index 0000000..6e64c8f --- /dev/null +++ b/docs/Save Images Mikey.md @@ -0,0 +1,215 @@ +# Documentation +- Class name: SaveImagesMikeyML +- Category: Mikey/Image +- Output node: True +- Repo Ref: https://github.com/bash-j/mikey_nodes + +SaveImagesMikeyML 节点负责将图像保存到指定目录,并具有可定制的命名方案。它允许包含各种元数据元素,如时间戳、计数器值和额外文本。该节点确保文件名经过净化并遵守预定义的长度限制。 + +# Input types +## Required +- images + - images 参数至关重要,因为它定义了需要保存的实际图像数据。它通过确定将哪些内容写入输出文件来影响节点的执行。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +## Optional +- sub_directory + - sub_directory 参数指定了输出目录中的一个子目录,图像将被保存在这个子目录中。这对于将保存的文件组织到特定类别或组中非常重要。 + - Comfy dtype: STRING + - Python dtype: str +- filename_text_1 + - filename_text_1 参数允许用户定义一段文本,该文本将包含在保存图像的文件名中。它有助于定制文件名。 + - Comfy dtype: STRING + - Python dtype: str +- filename_text_2 + - 与 filename_text_1 类似,此参数向文件名中添加了另一个可定制的文本元素。它增强了命名约定的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- filename_text_3 + - 这是文件名的第三个可定制文本参数,为用户提供了更多选项,以便在保存的图像文件名中包含特定信息。 + - Comfy dtype: STRING + - Python dtype: str +- filename_separator + - filename_separator 参数确定用于分隔文件名中不同文本元素的字符或字符串。它对定义文件名的结构至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- timestamp + - timestamp 参数指示是否在文件名中包含时间戳。它在版本控制和跟踪图像保存的时间方面发挥作用。 + - Comfy dtype: COMBO['true', 'false'] + - Python dtype: str +- counter_type + - counter_type 参数指定在文件名中递增计数器的方法,可以基于文件夹结构或文件名模式。对于确保文件名的唯一性很重要。 + - Comfy dtype: COMBO['none', 'folder', 'filename'] + - Python dtype: str +- filename_text_1_pos + - filename_text_1_pos 参数设置第一个文本元素在文件名中的位置。它对于控制文件名中元素的顺序很重要。 + - Comfy dtype: INT + - Python dtype: int +- filename_text_2_pos + - 此参数确定第二个文本元素在文件名中的位置,允许用户根据他们的喜好排列文本元素。 + - Comfy dtype: INT + - Python dtype: int +- filename_text_3_pos + - filename_text_3_pos 参数用于设置第三个文本元素在文件名中的位置,有助于整体组织文件名。 + - Comfy dtype: INT + - Python dtype: int +- timestamp_pos + - timestamp_pos 参数定义了时间戳在文件名中的位置。它影响文件名组件的整体排列。 + - Comfy dtype: INT + - Python dtype: int +- timestamp_type + - timestamp_type 参数规定了文件名中使用的时间戳的来源,可以基于作业的开始时间或保存图像的时间。 + - Comfy dtype: COMBO['job', 'save_time'] + - Python dtype: str +- counter_pos + - counter_pos 参数指定计数器在文件名中出现的位置。对于维护保存文件的顺序至关重要。 + - Comfy dtype: INT + - Python dtype: int +- extra_metadata + - extra_metadata 参数允许在保存的图像的 PNG 信息中包含额外的元数据。它提供了一种在图像数据旁边存储额外信息的方法。 + - Comfy dtype: STRING + - Python dtype: str +- prompt + - prompt 参数用于将上下文信息注入到文件名生成过程中。它可以根据提供的内容影响文件名的构建方式。 + - Comfy dtype: PROMPT + - Python dtype: Dict[str, Any] +- extra_pnginfo + - extra_pnginfo 参数允许将 PNG 元数据中的额外信息包含在文件名中。这对于嵌入以后可以检索的附加细节很有用。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, Any] + +# Output types +- ui + - ui 参数用作向用户呈现结果的界面。它通常包含一个字典列表,每个字典代表一个保存的图像,带有其文件名和子文件夹信息。 + - Comfy dtype: COMBO[Dict[str, List[Dict[str, str]]]] + - Python dtype: Dict[str, List[Dict[str, str]]] +- images + - ui 输出中的 images 参数包含有关每个保存的图像的详细信息,包括文件名和保存它的子目录。 + - Comfy dtype: COMBO[List[Dict[str, str]]] + - Python dtype: List[Dict[str, str]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SaveImagesMikeyML: + + def __init__(self): + self.output_dir = folder_paths.get_output_directory() + self.type = 'output' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'sub_directory': ('STRING', {'default': ''}), 'filename_text_1': ('STRING', {'default': 'Filename Text 1'}), 'filename_text_2': ('STRING', {'default': 'Filename Text 2'}), 'filename_text_3': ('STRING', {'default': 'Filename Text 3'}), 'filename_separator': ('STRING', {'default': '_'}), 'timestamp': (['true', 'false'], {'default': 'true'}), 'counter_type': (['none', 'folder', 'filename'], {'default': 'folder'}), 'filename_text_1_pos': ('INT', {'default': 0}), 'filename_text_2_pos': ('INT', {'default': 2}), 'filename_text_3_pos': ('INT', {'default': 4}), 'timestamp_pos': ('INT', {'default': 1}), 'timestamp_type': (['job', 'save_time'], {'default': 'save_time'}), 'counter_pos': ('INT', {'default': 3}), 'extra_metadata': ('STRING', {'default': 'Extra Metadata'})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = () + FUNCTION = 'save_images' + OUTPUT_NODE = True + CATEGORY = 'Mikey/Image' + + def _prepare_filename_texts(self, filename_text_1, filename_text_2, filename_text_3, extra_pnginfo, prompt): + filename_texts = [filename_text_1, filename_text_2, filename_text_3] + default_texts = ['Filename Text 1', 'Filename Text 2', 'Filename Text 3'] + for (i, text) in enumerate(filename_texts): + if text == default_texts[i]: + filename_texts[i] = '' + filename_texts[i] = search_and_replace(text, extra_pnginfo, prompt) + filename_texts[i] = re.sub('[<>:"/\\\\|?*]', '', filename_texts[i]) + filename_texts[i] = filename_texts[i].encode('ascii', 'ignore').decode('ascii') + total_length = len(filename_texts[0]) + len(filename_texts[1]) + len(filename_texts[2]) + 5 + 5 + 12 + if total_length > 120: + longest_text = max(filename_texts, key=len) + longest_text_idx = filename_texts.index(longest_text) + text_length_without_longest = total_length - len(longest_text) + filename_texts[longest_text_idx] = longest_text[0:120 - text_length_without_longest] + return filename_texts + + def _get_initial_counter(self, files, full_output_folder, counter_type, filename_separator, counter_pos, filename_texts): + counter = 1 + if counter_type == 'folder': + if files: + for f in files: + if filename_separator in f: + try: + counter = max(counter, int(f.split(filename_separator)[counter_pos]) + 1) + except: + counter = 1 + break + else: + counter = 1 + elif counter_type == 'filename': + for f in files: + f_split = f.split(filename_separator) + f_split = [x.replace('.png', '') for x in f_split] + matched_texts = all((filename_texts[i] == f_split[i] for i in range(3) if filename_texts[i])) + if matched_texts: + counter += 1 + return counter + + def _get_next_counter(self, full_output_folder, filename_base, counter): + """Checks for the next available counter value.""" + while True: + current_filename = filename_base.format(counter=f'{counter:05}') + if not os.path.exists(os.path.join(full_output_folder, f'{current_filename}.png')): + return counter + counter += 1 + + def save_images(self, images, sub_directory, filename_text_1, filename_text_2, filename_text_3, filename_separator, timestamp, counter_type, filename_text_1_pos, filename_text_2_pos, filename_text_3_pos, timestamp_pos, timestamp_type, counter_pos, extra_metadata, prompt=None, extra_pnginfo=None): + positions = [filename_text_1_pos, filename_text_2_pos, filename_text_3_pos, timestamp_pos, counter_pos] + if len(positions) != len(set(positions)): + raise ValueError('Duplicate position numbers detected. Please ensure all position numbers are unique.') + sub_directory = search_and_replace(sub_directory, extra_pnginfo, prompt) + sub_directory = re.sub('[<>:"|?*]', '', sub_directory) + sub_directory = sub_directory.encode('ascii', 'ignore').decode('ascii') + full_output_folder = os.path.join(self.output_dir, sub_directory) + os.makedirs(full_output_folder, exist_ok=True) + filename_texts = self._prepare_filename_texts(filename_text_1, filename_text_2, filename_text_3, extra_pnginfo, prompt) + if timestamp == 'true': + ts = datetime.datetime.now().strftime('%Y%m%d%H%M%S') + else: + ts = '' + elements = {filename_text_1_pos: filename_texts[0], filename_text_2_pos: filename_texts[1], filename_text_3_pos: filename_texts[2], timestamp_pos: ts, counter_pos: 'counter' if counter_type != 'none' else None} + sorted_elements = [elem for (_, elem) in sorted(elements.items()) if elem] + filename_base = filename_separator.join(sorted_elements).replace('counter', '{counter}') + files = os.listdir(full_output_folder) + if counter_type != 'none': + counter = self._get_initial_counter(files, full_output_folder, counter_type, filename_separator, counter_pos, filename_texts) + else: + counter = 0 + results = list() + for (ix, image) in enumerate(images): + i = 255.0 * image.cpu().numpy() + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) + metadata = PngInfo() + if prompt is not None: + metadata.add_text('prompt', json.dumps(prompt)) + if extra_pnginfo is not None: + for x in extra_pnginfo: + if x == 'parameters': + text = extra_pnginfo[x].encode('utf-8').decode('utf-8') + metadata.add_text(x, text) + elif x == 'workflow': + metadata.add_text(x, json.dumps(extra_pnginfo[x])) + elif x == 'prompt': + metadata.add_text(x, json.dumps(extra_pnginfo[x])) + else: + metadata.add_text(x, json.dumps(extra_pnginfo[x], ensure_ascii=False)) + if extra_metadata: + metadata.add_text('extra_metadata', extra_metadata) + if counter_type != 'none': + counter = self._get_next_counter(full_output_folder, filename_base, counter) + current_filename = filename_base.format(counter=f'{counter:05}') + else: + current_filename = filename_base + if timestamp_type == 'save_time' and timestamp == 'true': + current_timestamp = datetime.datetime.now().strftime('%y%m%d%H%M%S') + current_filename = current_filename.replace(ts, current_timestamp) + ts = current_timestamp + if ix > 0 and counter_type == 'none': + current_filename = current_filename.replace(ts, ts + f'_{ix:02}') + img.save(os.path.join(full_output_folder, f'{current_filename}.png'), pnginfo=metadata, compress_level=4) + results.append({'filename': f'{current_filename}.png', 'subfolder': sub_directory, 'type': self.type}) + if counter_type != 'none': + counter += 1 + return {'ui': {'images': results}} +``` \ No newline at end of file diff --git a/docs/Save Images No Display.md b/docs/Save Images No Display.md new file mode 100644 index 0000000..c98afa0 --- /dev/null +++ b/docs/Save Images No Display.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: SaveImageNoDisplay +- Category: Mikey/Image +- Output node: True +- Repo Ref: https://github.com/bash-j/mikey_nodes + +方法 'save_images_no_display' 旨在将一系列图像保存到指定目录,同时不显示这些图像。它负责将图像数据转换为适合保存的格式,应用元数据,并根据提供的参数以结构化的方式组织文件。 + +# Input types +## Required +- images + - 参数 'images' 是必需的,因为它包含了需要保存的原始图像数据。它在决定节点执行过程中起着关键作用,因为它是图像保存过程的主要输入。 + - Comfy dtype: COMBO[torch.Tensor] + - Python dtype: List[torch.Tensor] +- sub_directory + - 参数 'sub_directory' 指定了输出目录中的子文件夹,图像将被保存在这个子文件夹中。这对于以结构化的方式组织保存的图像很重要。 + - Comfy dtype: str + - Python dtype: str +## Optional +- filename_text_1 + - 参数 'filename_text_1' 允许通过提供一段文本字符串来定制文件名,这段文本将被纳入保存文件的名称中。 + - Comfy dtype: str + - Python dtype: Optional[str] +- extra_metadata + - 参数 'extra_metadata' 用于向图像文件的元数据添加额外信息。这可以包括提供有关图像的上下文或详细信息的各种类型的数据。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Output types +- ui + - 输出中的 'ui' 参数包含有关保存的图像的信息,包括它们的文件名和子文件夹。这个输出很重要,因为它提供了有关图像保存操作结果的反馈。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, List[Dict[str, Union[str, int, Dict[str, Any]]]]} + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SaveImageNoDisplay(SaveImagesMikeyML): + + def __init__(self): + super().__init__() + RETURN_TYPES = () + FUNCTION = 'save_images_no_display' + OUTPUT_NODE = True + CATEGORY = 'Mikey/Image' + + def save_images_no_display(self, images, sub_directory, filename_text_1, filename_text_2, filename_text_3, filename_separator, timestamp, counter_type, filename_text_1_pos, filename_text_2_pos, filename_text_3_pos, timestamp_pos, timestamp_type, counter_pos, extra_metadata, prompt=None, extra_pnginfo=None): + self.save_images(images, sub_directory, filename_text_1, filename_text_2, filename_text_3, filename_separator, timestamp, counter_type, filename_text_1_pos, filename_text_2_pos, filename_text_3_pos, timestamp_pos, timestamp_type, counter_pos, extra_metadata, prompt, extra_pnginfo) + return (None,) +``` \ No newline at end of file diff --git a/docs/Save Positive Prompt(WLSH).md b/docs/Save Positive Prompt(WLSH).md new file mode 100644 index 0000000..4511eb0 --- /dev/null +++ b/docs/Save Positive Prompt(WLSH).md @@ -0,0 +1,69 @@ +# Documentation +- Class name: WLSH_Save_Positive_Prompt_File +- Category: WLSH Nodes/IO +- Output node: True +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_Save_Positive_Prompt_File 节点旨在管理文本数据的存储。它接收一个提示并将其保存到指定的文件中,确保数据被持久存储以供将来使用。此节点在维护积极提示的记录中扮演着至关重要的角色,这对于各种应用(如训练模型或内容分析)可能至关重要。 + +# Input types +## Required +- filename + - 文件名参数指定了将保存积极提示的文件的名称。它对于标识已保存的数据至关重要,并且对于节点的操作至关重要,因为它决定了输出目录内文件的身份。 + - Comfy dtype: STRING + - Python dtype: str +- positive + - 积极参数代表要作为积极提示保存的文本内容。它是节点的强制性输入,因为它是节点设计要处理和保存的核心数据。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- path + - 路径参数决定了将保存文件的目录。它是可选的,如果没有提供,则会使用默认目录。此参数通过指定文件存储位置来影响节点的执行。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- positive + - save_text_file 函数的输出是保存到文件的积极提示。此输出表示成功存储了输入数据,对于确认节点的操作很重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Save_Positive_Prompt_File: + + def __init__(self): + self.output_dir = folder_paths.output_directory + + @classmethod + def INPUT_TYPES(s): + return {'required': {'filename': ('STRING', {'default': 'info', 'multiline': False}), 'path': ('STRING', {'default': '', 'multiline': False}), 'positive': ('STRING', {'default': '', 'multiline': True, 'forceInput': True})}} + OUTPUT_NODE = True + RETURN_TYPES = () + FUNCTION = 'save_text_file' + CATEGORY = 'WLSH Nodes/IO' + + def save_text_file(self, positive='', path='', filename=''): + output_path = os.path.join(self.output_dir, path) + if output_path.strip() != '': + if not os.path.exists(output_path.strip()): + print(f"The path `{output_path.strip()}` specified doesn't exist! Creating directory.") + os.makedirs(output_path, exist_ok=True) + if filename.strip == '': + print(f'Warning: There is no text specified to save! Text is empty. Saving file with timestamp') + filename = get_timestamp('%Y%m%d%H%M%S') + if positive == '': + positive = 'No prompt data' + self.writeTextFile(os.path.join(output_path, filename + '.txt'), positive) + return (positive,) + + def writeTextFile(self, file, content): + try: + with open(file, 'w') as f: + f.write(content) + except OSError: + print(f'Error: Unable to save file `{file}`') +``` \ No newline at end of file diff --git a/docs/Save Prompt (WLSH).md b/docs/Save Prompt (WLSH).md new file mode 100644 index 0000000..d11d382 --- /dev/null +++ b/docs/Save Prompt (WLSH).md @@ -0,0 +1,86 @@ +# Documentation +- Class name: WLSH_Save_Prompt_File +- Category: WLSH Nodes/IO +- Output node: True +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点旨在将文本数据保存到文件中,提供一种以人类可读格式持久化信息的手段。它封装了将文本写入文件的过程,确保数据存储在指定目录中,并使用用户定义的文件名。节点的主要功能是促进创建和维护文本记录,这对于记录实验、记录输出或存档数据至关重要。 + +# Input types +## Required +- filename + - 文件名参数对于指定输出文件的名称至关重要。它决定了保存数据的引用方式,是文件身份的关键部分,使用户能够轻松定位和引用保存的文本数据。 + - Comfy dtype: STRING + - Python dtype: str +- positive + - 正面参数包含代表正在保存的数据的积极方面或期望结果的文本。它对于提供背景和理解保存信息背后的目的很重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- path + - 路径参数定义了文件将被保存的目录。它在组织文件系统以及确保保存的文件在所需位置可访问和结构良好方面发挥着重要作用。 + - Comfy dtype: STRING + - Python dtype: str +- negative + - 负面参数包括代表不希望的结果或应避免的方面的文本。它对于澄清数据的意图和目标至关重要,确保保存的内容被正确解释。 + - Comfy dtype: STRING + - Python dtype: str +- modelname + - 模型名称参数指定用于生成数据的模型名称。它对于跟踪数据来源很重要,并且对未来的参考和分析可能有用。 + - Comfy dtype: STRING + - Python dtype: str +- seed + - 种子参数用于确保结果的可复现性。它对于保持相同过程不同运行之间的一致性很重要,这对于可靠和可验证的结果至关重要。 + - Comfy dtype: INT + - Python dtype: int +- counter + - 计数器参数用于向文件名附加一个数值,这对于区分同一数据的多个保存或版本很重要。 + - Comfy dtype: INT + - Python dtype: int +- time_format + - 时间格式参数指定用于时间戳文件名的格式。它对于加入一个基于创建时间的独特且可识别的元素很重要,这对于按时间顺序排序和定位文件很有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- text_data + - 文本数据输出代表保存的内容,其中包括正面和负面提示以及任何指定的附加信息。它是节点操作的成果,并且作为已持久化数据的记录。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Save_Prompt_File: + + def __init__(self): + self.output_dir = folder_paths.output_directory + + @classmethod + def INPUT_TYPES(s): + return {'required': {'filename': ('STRING', {'default': 'info', 'multiline': False}), 'path': ('STRING', {'default': '', 'multiline': False}), 'positive': ('STRING', {'default': '', 'multiline': True, 'forceInput': True})}, 'optional': {'negative': ('STRING', {'default': '', 'multiline': True, 'forceInput': True}), 'modelname': ('STRING', {'default': '', 'multiline': False, 'forceInput': True}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615, 'forceInput': True}), 'counter': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'time_format': ('STRING', {'default': '%Y-%m-%d-%H%M%S', 'multiline': False})}} + OUTPUT_NODE = True + RETURN_TYPES = () + FUNCTION = 'save_text_file' + CATEGORY = 'WLSH Nodes/IO' + + def save_text_file(self, positive='', negative='', seed=-1, modelname='unknown', path='', counter=0, time_format='%Y-%m-%d-%H%M%S', filename=''): + output_path = os.path.join(self.output_dir, path) + if output_path.strip() != '': + if not os.path.exists(output_path.strip()): + print(f"The path `{output_path.strip()}` specified doesn't exist! Creating directory.") + os.makedirs(output_path, exist_ok=True) + text_data = make_comment(positive, negative, modelname, seed, info=None) + filename = make_filename(filename, seed, modelname, counter, time_format) + self.writeTextFile(os.path.join(output_path, filename + '.txt'), text_data) + return (text_data,) + + def writeTextFile(self, file, content): + try: + with open(file, 'w') as f: + f.write(content) + except OSError: + print(f'Error: Unable to save file `{file}`') +``` \ No newline at end of file diff --git a/docs/Save Prompt%2FInfo (WLSH).md b/docs/Save Prompt%2FInfo (WLSH).md new file mode 100644 index 0000000..f923356 --- /dev/null +++ b/docs/Save Prompt%2FInfo (WLSH).md @@ -0,0 +1,90 @@ +# Documentation +- Class name: WLSH_Save_Prompt_File_Info +- Category: WLSH Nodes/IO +- Output node: True +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点旨在保存有关提示实验的文本信息,确保诸如正面和负面提示、模型名称和其他相关元数据等细节得到安全存储和组织。它便于为未来的参考和分析保存宝贵数据。 + +# Input types +## Required +- filename + - 文件名参数至关重要,因为它定义了保存提示信息的文件的基本名称。这对于识别和组织保存的数据至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- positive + - 正面参数包含实验中使用的正面提示文本。它很重要,因为它为将要保存的数据设置了上下文,并且是将要保存在文件中的记录的一部分。 + - Comfy dtype: STRING + - Python dtype: str +- negative + - 负面参数保存负面提示文本,它也是实验数据的一部分。这对于保存信息的完整性和未来的分析是必要的。 + - Comfy dtype: STRING + - Python dtype: str +- seed + - 种子参数用于确保实验的可重复性。它是记录的重要部分,因为它允许在相同条件下重现实验。 + - Comfy dtype: INT + - Python dtype: int +- modelname + - 模型名称参数指示实验中使用的模型名称。这对于跟踪数据来源和未来参考至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- counter + - 计数器参数是一个整数,可用于区分多次保存或跟踪进行的实验次数。它有助于保存文件的组织和索引。 + - Comfy dtype: INT + - Python dtype: int +- time_format + - 时间格式参数决定了文件名中时间戳的格式。它对于维护保存文件的一致和可读结构很重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- path + - 路径参数指定了文件将被保存的目录。它在组织文件系统内的文件和确保数据存储在所需位置方面起着重要作用。 + - Comfy dtype: STRING + - Python dtype: str +- info + - 信息参数包含有关实验的其他元数据,如配置设置和其他细节。它通过更多上下文丰富了保存的数据,并有助于全面分析。 + - Comfy dtype: INFO + - Python dtype: Dict[str, Any] + +# Output types +- text_data + - 文本数据代表从输入中编译的信息,包括正面和负面提示、模型名称以及其他元数据。它是将要保存在文本文件中的内容。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Save_Prompt_File_Info: + + def __init__(self): + self.output_dir = folder_paths.output_directory + + @classmethod + def INPUT_TYPES(s): + return {'required': {'filename': ('STRING', {'default': 'info', 'multiline': False}), 'path': ('STRING', {'default': '', 'multiline': False}), 'positive': ('STRING', {'default': '', 'multiline': True, 'forceInput': True})}, 'optional': {'negative': ('STRING', {'default': '', 'multiline': True, 'forceInput': True}), 'modelname': ('STRING', {'default': '', 'multiline': False, 'forceInput': True}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615, 'forceInput': True}), 'counter': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'time_format': ('STRING', {'default': '%Y-%m-%d-%H%M%S', 'multiline': False}), 'info': ('INFO',)}} + OUTPUT_NODE = True + RETURN_TYPES = () + FUNCTION = 'save_text_file' + CATEGORY = 'WLSH Nodes/IO' + + def save_text_file(self, positive='', negative='', seed=-1, modelname='unknown', info=None, path='', counter=0, time_format='%Y-%m-%d-%H%M%S', filename=''): + output_path = os.path.join(self.output_dir, path) + if output_path.strip() != '': + if not os.path.exists(output_path.strip()): + print(f"The path `{output_path.strip()}` specified doesn't exist! Creating directory.") + os.makedirs(output_path, exist_ok=True) + text_data = make_comment(positive, negative, modelname, seed, info) + filename = make_filename(filename, seed, modelname, counter, time_format) + self.writeTextFile(os.path.join(output_path, filename + '.txt'), text_data) + return (text_data,) + + def writeTextFile(self, file, content): + try: + with open(file, 'w') as f: + f.write(content) + except OSError: + print(f'Error: Unable to save file `{file}`') +``` \ No newline at end of file diff --git a/docs/Save Tensors (mtb).md b/docs/Save Tensors (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Save Text File.md b/docs/Save Text File.md new file mode 100644 index 0000000..25ead45 --- /dev/null +++ b/docs/Save Text File.md @@ -0,0 +1,102 @@ +# Documentation +- Class name: WAS_Text_Save +- Category: WAS Suite/IO +- Output node: True +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_Save节点旨在管理将文本数据保存到文件的过程。它处理目录的创建,检查空文本,并生成具有适当填充和分隔符的文件名。节点确保保存的文件具有唯一名称并存储在指定的路径中。 + +# Input types +## Required +- text + - 文本参数代表打算保存到文件的文本内容。它是节点操作的基础部分,因为它是正在管理的主要数据。 + - Comfy dtype: STRING + - Python dtype: str +- path + - 路径参数指定将保存文本文件的目录。它对于确定文件在文件系统中的位置至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- filename_prefix + - 文件名前缀参数设置文件名的起始字符。它有助于保存文件的唯一性和组织性。 + - Comfy dtype: STRING + - Python dtype: str +- filename_delimiter + - 文件名分隔符参数定义用于分隔文件名前缀和数字部分的字符。它有助于区分文件名的不同部分。 + - Comfy dtype: STRING + - Python dtype: str +- filename_number_padding + - 文件名数字填充参数确定用于文件名数字部分的位数。它确保文件名的格式一致。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- text + - 文本输出参数返回保存到文件的文本,提供已写入数据的确认。 + - Comfy dtype: STRING + - Python dtype: str +- ui + - ui输出参数用于提供用户界面反馈。它通常包含已保存文本的字符串表示。 + - Comfy dtype: COMBO[STRING] + - Python dtype: Dict[str, str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Save: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {'forceInput': True}), 'path': ('STRING', {'default': './ComfyUI/output/[time(%Y-%m-%d)]', 'multiline': False}), 'filename_prefix': ('STRING', {'default': 'ComfyUI'}), 'filename_delimiter': ('STRING', {'default': '_'}), 'filename_number_padding': ('INT', {'default': 4, 'min': 2, 'max': 9, 'step': 1})}} + OUTPUT_NODE = True + RETURN_TYPES = () + FUNCTION = 'save_text_file' + CATEGORY = 'WAS Suite/IO' + + def save_text_file(self, text, path, filename_prefix='ComfyUI', filename_delimiter='_', filename_number_padding=4): + tokens = TextTokens() + path = tokens.parseTokens(path) + filename_prefix = tokens.parseTokens(filename_prefix) + if not os.path.exists(path): + cstr(f"The path `{path}` doesn't exist! Creating it...").warning.print() + try: + os.makedirs(path, exist_ok=True) + except OSError as e: + cstr(f'The path `{path}` could not be created! Is there write access?\n{e}').error.print() + if text.strip() == '': + cstr(f'There is no text specified to save! Text is empty.').error.print() + delimiter = filename_delimiter + number_padding = int(filename_number_padding) + file_extension = '.txt' + filename = self.generate_filename(path, filename_prefix, delimiter, number_padding, file_extension) + file_path = os.path.join(path, filename) + self.writeTextFile(file_path, text) + update_history_text_files(file_path) + return (text, {'ui': {'string': text}}) + + def generate_filename(self, path, prefix, delimiter, number_padding, extension): + pattern = f'{re.escape(prefix)}{re.escape(delimiter)}(\\d{{{number_padding}}})' + existing_counters = [int(re.search(pattern, filename).group(1)) for filename in os.listdir(path) if re.match(pattern, filename)] + existing_counters.sort(reverse=True) + if existing_counters: + counter = existing_counters[0] + 1 + else: + counter = 1 + filename = f'{prefix}{delimiter}{counter:0{number_padding}}{extension}' + while os.path.exists(os.path.join(path, filename)): + counter += 1 + filename = f'{prefix}{delimiter}{counter:0{number_padding}}{extension}' + return filename + + def writeTextFile(self, file, content): + try: + with open(file, 'w', encoding='utf-8', newline='\n') as f: + f.write(content) + except OSError: + cstr(f'Unable to save file `{file}`').error.print() +``` \ No newline at end of file diff --git a/docs/SaveImageToLocal.md b/docs/SaveImageToLocal.md new file mode 100644 index 0000000..3ad231c --- /dev/null +++ b/docs/SaveImageToLocal.md @@ -0,0 +1,100 @@ +# Documentation +- Class name: SaveImageToLocal +- Category: ♾️Mixlab/Image +- Output node: True +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +“SaveImageToLocal”节点旨在将图像数据保存到本地文件系统。它提供了一个简单的机制来持久化图像,确保它们被存储在指定的输出目录中。这个节点在需要在计算环境之外进行图像可视化或进一步处理的场景中特别有用。 + +# Input types +## Required +- images + - “images”参数对于节点的操作至关重要,因为它代表了要保存的原始图像数据。其成功执行取决于所提供图像数据的正确格式和完整性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- file_path + - “file_path”参数指示图像将存储在本地系统的位置。它对于指导节点的输出和系统地组织保存的文件至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- prompt + - “prompt”参数虽然是可选的,但可以通过在图像元数据中嵌入描述性文本来为保存的图像添加上下文。这对于分类和搜索图像集合特别有用。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - “extra_pnginfo”参数允许在每个保存的图像中包含额外的元数据,增强了图像的描述能力,并促进了更复杂的搜索或组织方案。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, str] + +# Output types + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SaveImageToLocal: + + def __init__(self): + self.output_dir = folder_paths.get_output_directory() + self.type = 'output' + self.compress_level = 4 + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'file_path': ('STRING', {'multiline': True, 'default': '', 'dynamicPrompts': False})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = () + FUNCTION = 'save_images' + OUTPUT_NODE = True + CATEGORY = '♾️Mixlab/Image' + + def save_images(self, images, file_path, prompt=None, extra_pnginfo=None): + filename_prefix = os.path.basename(file_path) + if file_path == '': + filename_prefix = 'ComfyUI' + (filename_prefix, _) = os.path.splitext(filename_prefix) + (_, extension) = os.path.splitext(file_path) + if extension: + file_path = os.path.dirname(file_path) + (full_output_folder, filename, counter, subfolder, filename_prefix) = folder_paths.get_save_image_path(filename_prefix, self.output_dir, images[0].shape[1], images[0].shape[0]) + if not os.path.exists(file_path): + os.makedirs(file_path) + print('目录已创建') + else: + print('目录已存在') + if file_path == '': + files = glob.glob(full_output_folder + '/*') + else: + files = glob.glob(file_path + '/*') + file_count = len(files) + counter += file_count + print('统计文件数量', file_count, counter) + results = list() + for image in images: + i = 255.0 * image.cpu().numpy() + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) + metadata = None + if not args.disable_metadata: + metadata = PngInfo() + if prompt is not None: + metadata.add_text('prompt', json.dumps(prompt)) + if extra_pnginfo is not None: + for x in extra_pnginfo: + metadata.add_text(x, json.dumps(extra_pnginfo[x])) + file = f'{filename}_{counter:05}_.png' + if file_path == '': + fp = os.path.join(full_output_folder, file) + if os.path.exists(fp): + file = f'{filename}_{counter:05}_{generate_random_string(8)}.png' + fp = os.path.join(full_output_folder, file) + img.save(fp, pnginfo=metadata, compress_level=self.compress_level) + results.append({'filename': file, 'subfolder': subfolder, 'type': self.type}) + else: + fp = os.path.join(file_path, file) + if os.path.exists(fp): + file = f'{filename}_{counter:05}_{generate_random_string(8)}.png' + fp = os.path.join(file_path, file) + img.save(os.path.join(file_path, file), pnginfo=metadata, compress_level=self.compress_level) + results.append({'filename': file, 'subfolder': file_path, 'type': self.type}) + counter += 1 + return () +``` \ No newline at end of file diff --git a/docs/SaveMetaData.md b/docs/SaveMetaData.md new file mode 100644 index 0000000..95ebd5f --- /dev/null +++ b/docs/SaveMetaData.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: SaveMetaData +- Category: Mikey/Meta +- Output node: True +- Repo Ref: https://github.com/bash-j/mikey_nodes + +`save_metadata` 方法旨在组织和存储与图像相关的元数据。它创建一个文本文件,其中包含相关的信息,如时间戳、文件名前缀以及用户提供的额外细节。此方法确保每个图像的元数据都被系统地记录并易于访问。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它是元数据将关联的视觉内容。这是一个必需的输入,并且在节点的操作中起着核心作用,因为它是正在保存的元数据的主题。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or similar image object +## Optional +- filename_prefix + - 文件名前缀参数用于定义元数据文件的文件名的起始部分。虽然它不是强制性的,但对于以有意义的方式组织文件很重要,如果没有提供,可以设置为默认值。 + - Comfy dtype: STRING + - Python dtype: str +- timestamp_prefix + - 时间戳前缀参数决定是否在文件名中包含时间戳。它提供了一种按时间顺序组织文件的方法,默认设置为'true',表示应该包含时间戳。 + - Comfy dtype: COMBO[true, false] + - Python dtype: bool +- counter + - 计数器参数用于将数字计数器附加到文件名,确保唯一性并防止文件覆盖。默认设置为'true',突出了它在维护文件完整性方面的重要性。 + - Comfy dtype: COMBO[true, false] + - Python dtype: bool +- prompt + - 提示参数是一个可选输入,可以用来提供可能与元数据相关的额外上下文或信息。它可以增强元数据的描述性,而不是一个强制性要求。 + - Comfy dtype: PROMPT + - Python dtype: dict +- extra_pnginfo + - 额外的png信息参数用于包含特定于图像的额外信息,如注释或其他详细信息。这个可选输入允许保存更全面的元数据集。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: dict + +# Output types +- save_metadata + - save_metadata 方法的输出是一个包含已保存元数据的文件名和子文件夹的字典。这个输出提供了保存操作的确认以及保存的元数据的位置。 + - Comfy dtype: COMBO[filename, subfolder] + - Python dtype: Dict[str, Union[str, Dict[str, str]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SaveMetaData: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'filename_prefix': ('STRING', {'default': ''}), 'timestamp_prefix': (['true', 'false'], {'default': 'true'}), 'counter': (['true', 'false'], {'default': 'true'})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = () + FUNCTION = 'save_metadata' + CATEGORY = 'Mikey/Meta' + OUTPUT_NODE = True + + def save_metadata(self, image, filename_prefix, timestamp_prefix, counter, prompt=None, extra_pnginfo=None): + filename_prefix = search_and_replace(filename_prefix, extra_pnginfo, prompt) + (full_output_folder, filename, counter, subfolder, filename_prefix) = folder_paths.get_save_image_path(filename_prefix, folder_paths.get_output_directory(), 1, 1) + ts_str = datetime.datetime.now().strftime('%y%m%d%H%M') + filen = '' + if timestamp_prefix == 'true': + filen += ts_str + '_' + filen = filen + filename_prefix + if counter == 'true': + filen += '_' + str(counter) + filename = filen + '.txt' + file_path = os.path.join(full_output_folder, filename) + with open(file_path, 'w') as file: + for (key, value) in extra_pnginfo.items(): + file.write(f'{key}: {value}\n') + for (key, value) in prompt.items(): + file.write(f'{key}: {value}\n') + return {'save_metadata': {'filename': filename, 'subfolder': subfolder}} +``` \ No newline at end of file diff --git a/docs/SavePromptToFile.md b/docs/SavePromptToFile.md new file mode 100644 index 0000000..ad33e12 --- /dev/null +++ b/docs/SavePromptToFile.md @@ -0,0 +1,124 @@ +# Documentation +- Class name: SavePromptToFile +- Category: OneButtonPrompt +- Output node: True +- Repo Ref: https://github.com/AIrjen/OneButtonPrompt + +该节点便于将提示保存到文件中,确保信息以有序和易于访问的方式存储。它通过自动化文件命名和存储过程来增强工作流程,这对于保持清晰的提示记录及其相关数据至关重要。 + +# Input types +## Required +- filename_prefix + - 文件名前缀对于生成唯一且可识别的文件名至关重要,有助于高效地组织和引用保存的提示。 + - Comfy dtype: STRING + - Python dtype: str +- positive_prompt + - 正面提示是设置保存提示的基调和内容的关键输入,影响保存数据的整体上下文和实用性。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt + - 负面提示作为正面提示的对立面,提供了对比视角,对于理解提示的细微差别具有重要价值。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- prompt_g + - 额外的提示可以提供补充信息或上下文,丰富保存的数据,提供更全面的提示范围理解。 + - Comfy dtype: STRING + - Python dtype: str +- prompt_l + - 较长的提示可以提供扩展的细节或示例,这可能增强保存提示的深度和适用性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- status + - 状态输出确认了保存操作的成功执行,确保提示已正确保存和存储。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SavePromptToFile: + + def __init__(self): + self.output_dir = folder_paths.get_output_directory() + self.type = 'output' + self.prefix_append = '' + + @classmethod + def INPUT_TYPES(s): + return {'required': {'filename_prefix': ('STRING', {'default': 'Prompt'}), 'positive_prompt': ('STRING', {'multiline': True}), 'negative_prompt': ('STRING', {'multiline': True})}, 'optional': {'prompt_g': ('STRING', {'multiline': True}), 'prompt_l': ('STRING', {'multiline': True})}} + OUTPUT_NODE = True + RETURN_TYPES = () + FUNCTION = 'saveprompttofile' + CATEGORY = 'OneButtonPrompt' + + def saveprompttofile(self, positive_prompt, prompt_g, prompt_l, negative_prompt, filename_prefix): + filename_prefix += self.prefix_append + pattern = '%date:([^\\%]+)%' + match = re.search(pattern, filename_prefix) + if match: + date_format = match.group(1) + current_date = datetime.now() + date_format = date_format.replace('M', 'X') + date_format = date_format.replace('m', 'Z') + if platform.system() == 'Windows': + date_format = date_format.replace('yyyy', '%Y') + date_format = date_format.replace('yy', '%#y') + date_format = date_format.replace('X', '%#m') + date_format = date_format.replace('d', '%#d') + date_format = date_format.replace('h', '%#H') + date_format = date_format.replace('Z', '%#M') + date_format = date_format.replace('s', '%#S') + else: + date_format = date_format.replace('yyyy', '%Y') + date_format = date_format.replace('yy', '%-y') + date_format = date_format.replace('X', '%-m') + date_format = date_format.replace('d', '%-d') + date_format = date_format.replace('h', '%-H') + date_format = date_format.replace('Z', '%-M') + date_format = date_format.replace('s', '%-S') + formatted_date = current_date.strftime(date_format) + filename_prefix = re.sub(pattern, formatted_date, filename_prefix) + (full_output_folder, filename_short, counter, subfolder, filename_prefix) = folder_paths.get_save_image_path(filename_prefix, self.output_dir) + if positive_prompt.find('of a ') != -1: + start_index = positive_prompt.find('of a ') + len('of a ') + end_index = positive_prompt.find(',', start_index) + if end_index == -1: + end_index = len(positive_prompt) + else: + start_index = 0 + end_index = 128 + filename = positive_prompt[start_index:end_index] + filename = filename.replace('"', '') + filename = filename.replace('[', '') + filename = filename.replace('|', '') + filename = filename.replace(']', '') + filename = filename.replace('<', '') + filename = filename.replace('>', '') + filename = filename.replace(':', '_') + filename = filename.replace('.', '') + filename = re.sub('[0-9]+', '', filename) + safe_characters = set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.') + filename = re.sub('[^{}]+'.format(re.escape(''.join(safe_characters))), '', filename) + if filename == '': + filename = str(uuid.uuid4()) + if filename_prefix == '': + now = datetime.now() + filenamecomplete = now.strftime('%Y%m%d%H%M%S') + '_' + filename.replace(' ', '_').strip() + '.txt' + else: + formatted_counter = str(counter + 1).zfill(5) + filenamecomplete = filename_short + '_' + formatted_counter + '_' + filename.replace(' ', '_').strip() + '.txt' + directoryandfilename = os.path.abspath(os.path.join(full_output_folder, filenamecomplete)) + with open(directoryandfilename, 'w', encoding='utf-8') as file: + file.write('prompt: ' + positive_prompt + '\n') + if len(prompt_g) > 0: + file.write('prompt_g: ' + prompt_g + '\n') + if len(prompt_l) > 0: + file.write('prompt_l: ' + prompt_l + '\n') + file.write('negative prompt: ' + negative_prompt + '\n') + return 'done' +``` \ No newline at end of file diff --git a/docs/SawtoothWave.md b/docs/SawtoothWave.md new file mode 100644 index 0000000..85de1db --- /dev/null +++ b/docs/SawtoothWave.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: SawtoothWave +- Category: FizzNodes 📅🅕🅝/WaveNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +锯齿波节点根据指定的相位、步进增量和位移生成波形图案,有助于系统中的信号处理或波形生成任务。 + +# Input types +## Required +- phase + - 相位参数决定了锯齿波的周期性,影响输出波形的整体形状和频率。 + - Comfy dtype: FLOAT + - Python dtype: float +- step_increment + - 步进增量参数控制每个周期的振幅变化,影响波形上升和下降的陡峭程度。 + - Comfy dtype: FLOAT + - Python dtype: float +- x_translation + - x_translation参数水平移动波形,调整波形图案在时间帧内的位置。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_value + - start_value参数设置波形的初始水平,决定了波形振荡的基线。 + - Comfy dtype: FLOAT + - Python dtype: float +- current_frame + - current_frame参数代表当前时间点,用于计算波形在其周期内特定时刻的位置。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - 输出代表当前帧锯齿波的计算值,可用于进一步的信号处理或作为其他节点的输入。 + - Comfy dtype: FLOAT + - Python dtype: float +- int_output + - int_output提供波形值的整数表示,适用于离散操作或作为数值分析的基础。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SawtoothWave: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'phase': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'step_increment': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.1}), 'x_translation': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'start_value': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.05}), 'current_frame': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('FLOAT', 'INT') + FUNCTION = 'Wave' + CATEGORY = 'FizzNodes 📅🅕🅝/WaveNodes' + + def Wave(self, phase, step_increment, x_translation, start_value, current_frame): + output = start_value + (step_increment * (current_frame % phase) - x_translation) + print(output) + return (output, int(output)) +``` \ No newline at end of file diff --git a/docs/ScaledSoftControlNetWeights.md b/docs/ScaledSoftControlNetWeights.md new file mode 100644 index 0000000..cf56505 --- /dev/null +++ b/docs/ScaledSoftControlNetWeights.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: ScaledSoftUniversalWeights +- Category: Adv-ControlNet 🛂🅐🅒🅝/weights +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +ScaledSoftUniversalWeights 类提供了一个方法,用于生成基于提供的乘数和翻转参数进行缩放和可能翻转的控制权重。它通过允许用户调整权重应用的影响和方向性,为控制网络的定制做出贡献。 + +# Input types +## Required +- base_multiplier + - base_multiplier 参数对于控制网络权重的缩放至关重要。它决定了每个权重对网络输出的影响程度。参数的范围从 0.0 到 1.0,允许对权重的影响进行微调。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- flip_weights + - flip_weights 参数是一个可选的开关,启用时可以反转权重应用的方向。这对于实现特定效果或纠正控制网络行为中的意外影响可能非常重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- weights + - weights 输出代表由节点生成的一组控制权重。这些权重对于塑造控制网络的行为至关重要,并受到输入参数的影响。 + - Comfy dtype: CONTROL_NET_WEIGHTS + - Python dtype: ControlWeights +- timestep_keyframe + - timestep_keyframe 输出是控制网络内基于时间的控制点的结构化表示。它对于定义权重随时间应用的时间方面特征非常重要。 + - Comfy dtype: TIMESTEP_KEYFRAME + - Python dtype: TimestepKeyframeGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ScaledSoftUniversalWeights: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_multiplier': ('FLOAT', {'default': 0.825, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'flip_weights': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('CONTROL_NET_WEIGHTS', 'TIMESTEP_KEYFRAME') + RETURN_NAMES = WEIGHTS_RETURN_NAMES + FUNCTION = 'load_weights' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/weights' + + def load_weights(self, base_multiplier, flip_weights): + weights = ControlWeights.universal(base_multiplier=base_multiplier, flip_weights=flip_weights) + return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights))) +``` \ No newline at end of file diff --git a/docs/ScaledSoftMaskedUniversalWeights.md b/docs/ScaledSoftMaskedUniversalWeights.md new file mode 100644 index 0000000..d298323 --- /dev/null +++ b/docs/ScaledSoftMaskedUniversalWeights.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: ScaledSoftMaskedUniversalWeights +- Category: Adv-ControlNet 🛂🅐🅒🅝/weights +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +类 `ScaledSoftMaskedUniversalWeights` 中的 `load_weights` 方法旨在处理并应用一个软掩码到控制网络的基础权重上。它接受一个掩码张量和两个乘数来缩放掩码值,确保它们落在一个指定的范围内。该方法还提供了锁定掩码的最小值和最大值的选项,防止任何超出给定限制的调整。这个功能对于微调控制权重对网络输出的影响至关重要。 + +# Input types +## Required +- mask + - 参数 'mask' 是一个张量,定义了要应用到控制权重上的软掩码。它在确定基础权重被修改的程度中起着关键作用。掩码的值根据提供的乘数进行缩放,使其成为权重调整过程中的一个关键组件。 + - Comfy dtype: Tensor + - Python dtype: torch.Tensor +- min_base_multiplier + - 参数 'min_base_multiplier' 设置了缩放掩码值的下限。它对于控制掩码对控制权重的最小影响至关重要。此参数确保掩码的效果不会太微妙,允许对网络行为进行清晰和明显的调整。 + - Comfy dtype: FLOAT + - Python dtype: float +- max_base_multiplier + - 参数 'max_base_multiplier' 确定了缩放掩码值的上限。它对于控制掩码对控制权重的最大影响至关重要。通过设置此参数,用户可以防止掩码压倒基础权重,保持原始权重和修改后权重之间的平衡。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- CONTROL_NET_WEIGHTS + - 输出 'CONTROL_NET_WEIGHTS' 表示应用缩放软掩码后网络的调整控制权重。这个输出很重要,因为它直接影响控制网络的最终输出,反映了基于输入掩码和乘数的修改行为。 + - Comfy dtype: ControlWeights + - Python dtype: comfy.ControlWeights +- TIMESTEP_KEYFRAME + - 输出 'TIMESTEP_KEYFRAME' 在特定时间步提供了控制权重的默认关键帧。它对于定义控制权重的时间结构很重要,允许随时间进行动态调整。 + - Comfy dtype: TimestepKeyframe + - Python dtype: comfy.TimestepKeyframe + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ScaledSoftMaskedUniversalWeights: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'min_base_multiplier': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'max_base_multiplier': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001})}} + RETURN_TYPES = ('CONTROL_NET_WEIGHTS', 'TIMESTEP_KEYFRAME') + RETURN_NAMES = WEIGHTS_RETURN_NAMES + FUNCTION = 'load_weights' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/weights' + + def load_weights(self, mask: Tensor, min_base_multiplier: float, max_base_multiplier: float, lock_min=False, lock_max=False): + mask = mask.clone() + x_min = 0.0 if lock_min else mask.min() + x_max = 1.0 if lock_max else mask.max() + if x_min == x_max: + mask = torch.ones_like(mask) * max_base_multiplier + else: + mask = linear_conversion(mask, x_min, x_max, min_base_multiplier, max_base_multiplier) + weights = ControlWeights.universal_mask(weight_mask=mask) + return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights))) +``` \ No newline at end of file diff --git a/docs/ScheduleToCond.md b/docs/ScheduleToCond.md new file mode 100644 index 0000000..a0900f0 --- /dev/null +++ b/docs/ScheduleToCond.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: ScheduleToCond +- Category: promptcontrol +- Output node: False +- Repo Ref: https://github.com/asagi4/comfyui-prompt-control.git + +ScheduleToCond节点的'apply'方法旨在处理并应用提示计划给定的CLIP模型。它将提示计划与CLIP模型集成,以生成一组条件输入,这些输入可以用于进一步处理或作为模型输入的一部分。此方法在控制文本提示对CLIP模型输出的影响中起着关键作用。 + +# Input types +## Required +- clip + - 'clip'参数至关重要,因为它代表了将应用提示计划的CLIP模型。它是决定后续条件处理过程和节点生成的输出的核心组件。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- prompt_schedule + - 'prompt_schedule'参数定义了将提示应用于CLIP模型的时间表。它对于确定文本提示将如何调节模型在处理过程中的行为至关重要。 + - Comfy dtype: PROMPT_SCHEDULE + - Python dtype: Dict[str, Any] + +# Output types +- CONDITIONING + - 输出'CONDITIONING'代表了从提示计划派生并应用于CLIP模型的条件集。它很重要,因为它构成了进一步操作或作为下游任务输入的基础。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict[str, Any]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ScheduleToCond: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'clip': ('CLIP',), 'prompt_schedule': ('PROMPT_SCHEDULE',)}} + RETURN_TYPES = ('CONDITIONING',) + CATEGORY = 'promptcontrol' + FUNCTION = 'apply' + + def apply(self, clip, prompt_schedule): + with Timer('ScheduleToCond'): + r = (control_to_clip_common(clip, prompt_schedule),) + return r +``` \ No newline at end of file diff --git a/docs/ScheduleToModel.md b/docs/ScheduleToModel.md new file mode 100644 index 0000000..2948423 --- /dev/null +++ b/docs/ScheduleToModel.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: ScheduleToModel +- Category: promptcontrol +- Output node: False +- Repo Ref: https://github.com/asagi4/comfyui-prompt-control.git + +ScheduleToModel节点的'apply'方法旨在基于提供的时间表动态调整模型的架构。它允许在指定步骤中无缝集成不同的模型配置,增强模型生成与每个步骤上下文相匹配的响应的能力。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它代表了将根据提示时间表进行修改的神经网络。它是节点操作的基础,其结构直接影响采样过程的结果。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- prompt_schedule + - prompt_schedule参数定义了在采样过程的每个步骤中将发生的模型调整序列。它对于指导节点的操作和确定每个步骤要应用的具体修改至关重要。 + - Comfy dtype: PROMPT_SCHEDULE + - Python dtype: Dict[str, Any] + +# Output types +- model + - 输出的'model'是经过提示时间表预定调整的修改后的神经网络。它封装了节点操作的结果,反映了在采样过程中应用的动态变化。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ScheduleToModel: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'prompt_schedule': ('PROMPT_SCHEDULE',)}} + RETURN_TYPES = ('MODEL',) + CATEGORY = 'promptcontrol' + FUNCTION = 'apply' + + def apply(self, model, prompt_schedule): + return (schedule_lora_common(model, prompt_schedule),) +``` \ No newline at end of file diff --git a/docs/SeamlessTile.md b/docs/SeamlessTile.md new file mode 100644 index 0000000..984beae --- /dev/null +++ b/docs/SeamlessTile.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: SeamlessTile +- Category: conditioning +- Output node: False +- Repo Ref: https://github.com/spinagon/ComfyUI-seamless-tiling + +SeamlessTile 是一个用于修改模型的填充和卷积行为以实现无缝平铺的节点。它调整 Conv2d 层的填充模式和填充值,以实现“循环”效果,这在需要无缝平铺图案的图像处理任务中特别有用。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它代表了将被修改以实现无缝平铺的神经网络。它是节点操作以实现所需平铺效果的核心组件。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- tiling + - tiling 参数指示应用于模型的平铺类型。它控制是否启用平铺,将其限制在 x 轴、y 轴上,还是完全禁用,影响模型产生无缝图案的能力。 + - Comfy dtype: str + - Python dtype: str +## Optional +- copy_model + - copy_model 参数决定在修改之前是否应该复制原始模型,或者就地更改。这通过保留或修改原始模型状态来影响执行。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- MODEL + - 输出的 MODEL 是具有调整过的填充和卷积设置以支持无缝平铺的修改后的神经网络。它很重要,因为它直接影响图像的后续处理和输出质量。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeamlessTile: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'tiling': (['enable', 'x_only', 'y_only', 'disable'],), 'copy_model': (['Make a copy', 'Modify in place'],)}} + CATEGORY = 'conditioning' + RETURN_TYPES = ('MODEL',) + FUNCTION = 'run' + + def run(self, model, copy_model, tiling): + if copy_model == 'Modify in place': + model_copy = model + else: + model_copy = copy.deepcopy(model) + if tiling == 'enable': + make_circular_asymm(model_copy.model, True, True) + elif tiling == 'x_only': + make_circular_asymm(model_copy.model, True, False) + elif tiling == 'y_only': + make_circular_asymm(model_copy.model, False, True) + else: + make_circular_asymm(model_copy.model, False, False) + return (model_copy,) +``` \ No newline at end of file diff --git a/docs/SearchAndReplace.md b/docs/SearchAndReplace.md new file mode 100644 index 0000000..37322bb --- /dev/null +++ b/docs/SearchAndReplace.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: SearchAndReplace +- Category: Mikey/Utils +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +SearchAndReplace节点旨在通过在给定文本中搜索特定模式并将其替换为相应的值来执行文本操作任务。它可以处理诸如日期和来自提示或额外信息的值等动态替换,使其适用于各种用例。 + +# Input types +## Required +- text + - 'text'参数是节点的主要输入,包含将要执行搜索和替换操作的文本。它可以包含动态内容的占位符,节点将用实际值替换这些占位符。 + - Comfy dtype: STRING + - Python dtype: str +- seed + - 'seed'参数用于初始化或影响节点内某些操作的随机性。当节点执行需要随机或伪随机元素的操作时,它尤其重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- prompt + - 'prompt'参数是可选输入,提供节点可以用来在文本中执行更复杂替换的额外上下文或数据。它通常用于从外部源注入值。 + - Comfy dtype: STRING + - Python dtype: Union[str, Dict[str, Any]] +- extra_pnginfo + - 'extra_pnginfo'参数是另一个可选输入,可以包含节点执行其操作所需的额外信息。当需要超出'prompt'提供的信息的额外数据时,它特别有用。 + - Comfy dtype: STRING + - Python dtype: Union[str, Dict[str, Any]] + +# Output types +- result + - 'result'输出包含所有搜索和替换操作执行后的文本。它反映了文本的最终状态,所有指定的模式都已被其相应的值替换。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SearchAndReplace: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': False, 'placeholder': 'Text to search and replace'}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'search_and_replace' + CATEGORY = 'Mikey/Utils' + + def search_and_replace(self, text, seed, prompt=None, extra_pnginfo=None): + result = search_and_replace(text, extra_pnginfo, prompt) + s = seed + 1 + return (result,) +``` \ No newline at end of file diff --git a/docs/SeargeAdvancedParameters.md b/docs/SeargeAdvancedParameters.md new file mode 100644 index 0000000..6bae5b4 --- /dev/null +++ b/docs/SeargeAdvancedParameters.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: SeargeAdvancedParameters +- Category: UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点类封装了用于细化图像细节、管理动态配置以及调整对比度和饱和度等视觉元素的高级参数。它旨在提供对图像增强过程的细粒度控制,而不直接涉及底层模型操作。 + +# Input types +## Required +- dynamic_cfg_method + - 此参数规定了用于动态配置图像增强过程的方法。它对于根据不同的输入要求调整节点的行为和实现期望的输出质量至关重要。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- dynamic_cfg_factor + - 这个因素影响了应用于图像增强的动态配置的程度。它在微调计算效率和输出细节之间的平衡方面非常重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- refiner_detail_boost + - 此参数控制精炼过程中应用的细节增强水平。它对于提高最终输出的清晰度和清晰度至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- contrast_factor + - 这个因素调整图像的对比度,对于创造视觉冲击力和增强输出的整体美感非常重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- saturation_factor + - 此参数管理图像的饱和度水平,影响颜色的生动性和视觉体验的丰富性。 + - Comfy dtype: FLOAT + - Python dtype: float +- latent_detailer + - 此参数选择一个潜在的细节增强器来进一步增强图像的微妙细节。它在实现更细致和真实的视觉结果方面起着关键作用。 + - Comfy dtype: COMBO[str] + - Python dtype: str +## Optional +- data + - 此参数用于传入将由节点处理的数据。它对于节点正确运行和产生预期结果非常重要。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Any + +# Output types +- data + - 输出包含应用了高级参数的处理后数据,准备在图像增强流程中进一步使用。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeAdvancedParameters: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'dynamic_cfg_method': (UI.DYNAMIC_CFG_METHODS, {'default': UI.NONE}), 'dynamic_cfg_factor': ('FLOAT', {'default': 0.0, 'min': -1.0, 'max': 1.0, 'step': 0.05}), 'refiner_detail_boost': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'contrast_factor': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'saturation_factor': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'latent_detailer': (UI.LATENT_DETAILERS, {'default': UI.NONE})}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(dynamic_cfg_method, dynamic_cfg_factor, refiner_detail_boost, contrast_factor, saturation_factor, latent_detailer): + return {UI.F_DYNAMIC_CFG_METHOD: dynamic_cfg_method, UI.F_DYNAMIC_CFG_FACTOR: round(dynamic_cfg_factor, 3), UI.F_REFINER_DETAIL_BOOST: round(refiner_detail_boost, 3), UI.F_CONTRAST_FACTOR: round(contrast_factor, 3), UI.F_SATURATION_FACTOR: round(saturation_factor, 3), UI.F_LATENT_DETAILER: latent_detailer} + + def get(self, dynamic_cfg_method, dynamic_cfg_factor, refiner_detail_boost, contrast_factor, saturation_factor, latent_detailer, data=None): + if data is None: + data = {} + data[UI.S_ADVANCED_PARAMETERS] = self.create_dict(dynamic_cfg_method, dynamic_cfg_factor, refiner_detail_boost, contrast_factor, saturation_factor, latent_detailer) + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeCheckpointLoader.md b/docs/SeargeCheckpointLoader.md new file mode 100644 index 0000000..cafc1b8 --- /dev/null +++ b/docs/SeargeCheckpointLoader.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: SeargeCheckpointLoader +- Category: Searge/_deprecated_/Files +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点旨在检索和加载先前保存的模型检查点,从而实现从特定时间点继续训练或评估模型。 + +# Input types +## Required +- ckpt_name + - 检查点名称对于识别要加载的特定模型状态至关重要。它通过确定访问哪个检查点直接影响节点的操作。 + - Comfy dtype: CHECKPOINT_NAME + - Python dtype: str + +# Output types +- MODEL + - 输出模型代表保存检查点时模型的状态,允许进一步训练或评估。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- CLIP + - 如果存在CLIP组件,则为加载的模型提供额外的上下文和功能,增强其功能。 + - Comfy dtype: CLIP + - Python dtype: Any +- VAE + - 如果存在VAE组件,则代表与检查点相关的变分自编码器,使其具有生成能力。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeCheckpointLoader: + + def __init__(self): + self.chkp_loader = nodes.CheckpointLoaderSimple() + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': ('CHECKPOINT_NAME',)}} + RETURN_TYPES = ('MODEL', 'CLIP', 'VAE') + FUNCTION = 'load_checkpoint' + CATEGORY = 'Searge/_deprecated_/Files' + + def load_checkpoint(self, ckpt_name): + return self.chkp_loader.load_checkpoint(ckpt_name) +``` \ No newline at end of file diff --git a/docs/SeargeConditionMixing.md b/docs/SeargeConditionMixing.md new file mode 100644 index 0000000..ee54af3 --- /dev/null +++ b/docs/SeargeConditionMixing.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: SeargeConditionMixing +- Category: UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点便于将搜索条件整合进数据流中,增强数据处理和检索操作的特定性。 + +# Input types +## Optional +- data + - data参数作为节点的主要输入,允许在系统内传输和操作信息。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Union[Dict[str, Any], None] + +# Output types +- data + - 输出数据是输入的修改版,现在包含搜索条件,可在后续流程中使用。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeConditionMixing: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(example): + return {UI.EXAMPLE: example} + + def get(self, data=None): + if data is None: + data = {} + data[UI.S_CONDITION_MIXING] = self.create_dict('example') + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeConditioningMuxer2.md b/docs/SeargeConditioningMuxer2.md new file mode 100644 index 0000000..ddcaef4 --- /dev/null +++ b/docs/SeargeConditioningMuxer2.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: SeargeConditioningMuxer2 +- Category: Searge/_deprecated_/FlowControl +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点作为一个条件多路复用器,根据选择器的值来选择两个条件输入中的一个。它的设计是为了在数据流中路由适当的输入到输出,使得数据处理能够有条件地进行。 + +# Input types +## Required +- input0 + - 第一个条件输入,将由节点考虑进行选择。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- input1 + - 第二个条件输入,是第一个输入的替代选项。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- input_selector + - 选择器参数,决定哪个条件输入将被路由到输出。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - 基于input_selector值所选择的条件输入。 + - Comfy dtype: CONDITIONING + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeConditioningMuxer2: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input0': ('CONDITIONING',), 'input1': ('CONDITIONING',), 'input_selector': ('INT', {'default': 0, 'min': 0, 'max': 1})}} + RETURN_TYPES = ('CONDITIONING',) + RETURN_NAMES = ('output',) + FUNCTION = 'mux' + CATEGORY = 'Searge/_deprecated_/FlowControl' + + def mux(self, input0, input1, input_selector): + if input_selector == 1: + return (input1,) + else: + return (input0,) +``` \ No newline at end of file diff --git a/docs/SeargeConditioningMuxer5.md b/docs/SeargeConditioningMuxer5.md new file mode 100644 index 0000000..0c19a46 --- /dev/null +++ b/docs/SeargeConditioningMuxer5.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: SeargeConditioningMuxer5 +- Category: Searge/_deprecated_/FlowControl +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点作为一个条件多路复用器,根据选择器的值来选择特定的调节输入。它有助于数据通过网络的路由,确保将适当的调节信号传递给后续操作。 + +# Input types +## Required +- input0 + - 第一个调节输入,是节点操作的关键组成部分。它代表输入选择器可以选中的潜在数据流之一。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- input1 + - 第二个调节输入,节点功能的另一个重要部分。当输入选择器设置为1时,它将是被选中的数据流。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- input2 + - 第三个调节输入,有助于节点根据选择器的值路由不同的数据流。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- input3 + - 第四个调节输入,是节点多样化选择机制的一部分。当输入选择器为3时,它将成为活动的输入。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- input4 + - 第五个调节输入,完成了节点的选择集。当输入选择器的值为4时,它将是被选中的输入。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- input_selector + - 选择器参数决定哪个调节输入通过节点。它对于根据设定的值范围确定输出至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - 节点的输出是基于输入选择器选出的调节输入。它代表了节点操作的结果,即下游过程的适当调节信号。 + - Comfy dtype: CONDITIONING + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeConditioningMuxer5: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input0': ('CONDITIONING',), 'input1': ('CONDITIONING',), 'input2': ('CONDITIONING',), 'input3': ('CONDITIONING',), 'input4': ('CONDITIONING',), 'input_selector': ('INT', {'default': 0, 'min': 0, 'max': 4})}} + RETURN_TYPES = ('CONDITIONING',) + RETURN_NAMES = ('output',) + FUNCTION = 'mux' + CATEGORY = 'Searge/_deprecated_/FlowControl' + + def mux(self, input0, input1, input2, input3, input4, input_selector): + if input_selector == 1: + return (input1,) + elif input_selector == 2: + return (input2,) + elif input_selector == 3: + return (input3,) + elif input_selector == 4: + return (input4,) + else: + return (input0,) +``` \ No newline at end of file diff --git a/docs/SeargeConditioningParameters.md b/docs/SeargeConditioningParameters.md new file mode 100644 index 0000000..01ac74a --- /dev/null +++ b/docs/SeargeConditioningParameters.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: SeargeConditioningParameters +- Category: UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点类封装了在搜索和救援场景中调整条件参数的逻辑,旨在根据不同的比例和得分来优化搜索策略。 + +# Input types +## Required +- base_conditioning_scale + - 基础条件比例是一个基本参数,它影响搜索操作开始时的初始条件。 + - Comfy dtype: FLOAT + - Python dtype: float +- refiner_conditioning_scale + - 这个比例细化了搜索过程,允许随着操作的进行对策略进行更细致的调整。 + - Comfy dtype: FLOAT + - Python dtype: float +- target_conditioning_scale + - 目标条件比例对于将搜索工作集中在操作区域内的高优先级区域至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- positive_conditioning_scale + - 该参数增强了搜索中积极强化的方面,将资源引导向成功潜力更高的区域。 + - Comfy dtype: FLOAT + - Python dtype: float +- negative_conditioning_scale + - 负面条件比例有助于避免效果较低的区域,确保资源不会在成功可能性较低的地区浪费。 + - Comfy dtype: FLOAT + - Python dtype: float +- positive_aesthetic_score + - 积极的审美评分通过评估搜索区域的视觉吸引力,有助于决策过程,可能导致更高效的操作。 + - Comfy dtype: FLOAT + - Python dtype: float +- negative_aesthetic_score + - 这个评分反映了搜索区域不太理想的一面,引导搜索远离可能阻碍操作进展的区域。 + - Comfy dtype: FLOAT + - Python dtype: float +- precondition_mode + - 预设模式设置了条件的运作框架,决定了如何在任务开始时应用搜索参数。 + - Comfy dtype: PRECONDITION_MODES + - Python dtype: Enum +- precondition_strength + - 预设强度影响初始条件应用的强度,影响整体搜索策略。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- data + - 数据流提供了连续的信息流,可以用来实时动态调整搜索参数。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Output types +- data + - 数据流已更新条件参数,成为搜索和救援操作持续决策的基础。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeConditioningParameters: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'base_conditioning_scale': ('FLOAT', {'default': 2.0, 'min': 0.5, 'max': 4.0, 'step': 0.25}), 'refiner_conditioning_scale': ('FLOAT', {'default': 2.0, 'min': 0.5, 'max': 4.0, 'step': 0.25}), 'target_conditioning_scale': ('FLOAT', {'default': 2.0, 'min': 0.5, 'max': 4.0, 'step': 0.25}), 'positive_conditioning_scale': ('FLOAT', {'default': 1.5, 'min': 0.25, 'max': 2.0, 'step': 0.25}), 'negative_conditioning_scale': ('FLOAT', {'default': 0.75, 'min': 0.25, 'max': 2.0, 'step': 0.25}), 'positive_aesthetic_score': ('FLOAT', {'default': 6.0, 'min': 0.5, 'max': 10.0, 'step': 0.5}), 'negative_aesthetic_score': ('FLOAT', {'default': 2.5, 'min': 0.5, 'max': 10.0, 'step': 0.5}), 'precondition_mode': (UI.PRECONDITION_MODES,), 'precondition_strength': ('FLOAT', {'default': 0.1, 'min': 0.0, 'max': 1.0, 'step': 0.05})}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(base_conditioning_scale, refiner_conditioning_scale, target_conditioning_scale, positive_conditioning_scale, negative_conditioning_scale, positive_aesthetic_score, negative_aesthetic_score, precondition_mode, precondition_strength): + return {UI.F_BASE_CONDITIONING_SCALE: round(base_conditioning_scale, 3), UI.F_REFINER_CONDITIONING_SCALE: round(refiner_conditioning_scale, 3), UI.F_TARGET_CONDITIONING_SCALE: round(target_conditioning_scale, 3), UI.F_POSITIVE_CONDITIONING_SCALE: round(positive_conditioning_scale, 3), UI.F_NEGATIVE_CONDITIONING_SCALE: round(negative_conditioning_scale, 3), UI.F_POSITIVE_AESTHETIC_SCORE: round(positive_aesthetic_score, 3), UI.F_NEGATIVE_AESTHETIC_SCORE: round(negative_aesthetic_score, 3), UI.F_PRECONDITION_MODE: precondition_mode, UI.F_PRECONDITION_STRENGTH: round(precondition_strength, 3)} + + def get(self, base_conditioning_scale, refiner_conditioning_scale, target_conditioning_scale, positive_conditioning_scale, negative_conditioning_scale, positive_aesthetic_score, negative_aesthetic_score, precondition_mode, precondition_strength, data=None): + if data is None: + data = {} + data[UI.S_CONDITIONING_PARAMETERS] = self.create_dict(base_conditioning_scale, refiner_conditioning_scale, target_conditioning_scale, positive_conditioning_scale, negative_conditioning_scale, positive_aesthetic_score, negative_aesthetic_score, precondition_mode, precondition_strength) + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeControlnetAdapterV2.md b/docs/SeargeControlnetAdapterV2.md new file mode 100644 index 0000000..ebdcd0a --- /dev/null +++ b/docs/SeargeControlnetAdapterV2.md @@ -0,0 +1,127 @@ +# Documentation +- Class name: SeargeControlnetAdapterV2 +- Category: UI_PROMPTING +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点促进控制网络机制的适配,以增强图像处理任务。它根据输入参数动态选择和应用各种边缘检测和图像增强算法,旨在根据特定要求改善视觉输出。 + +# Input types +## Required +- controlnet_mode + - 确定要使用的控制网络类型,这显著影响处理方法和最终图像质量。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- controlnet_preprocessor + - 启用或禁用控制网图像的预处理,可以优化后续的图像处理步骤。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- strength + - 调整控制网络对图像的影响强度,直接影响最终的视觉结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- low_threshold + - 设置边缘检测灵敏度的下限,影响图像中检测到的边缘的粒度。 + - Comfy dtype: FLOAT + - Python dtype: float +- high_threshold + - 定义边缘检测灵敏度的上限,影响最终图像中边缘的显著性。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_percent + - 指定图像处理范围的起始百分比,确定受影响的图像初始段。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_percent + - 指示图像处理范围的结束百分比,建立受影响的图像最终段。 + - Comfy dtype: FLOAT + - Python dtype: float +- noise_augmentation + - 控制应用于图像的噪声增强水平,这可以增强控制网络的鲁棒性。 + - Comfy dtype: FLOAT + - Python dtype: float +- revision_enhancer + - 激活或停用修订增强器,它精炼控制网络的输出以提高准确性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- source_image + - 提供控制网络处理的基础图像,作为所有后续图像操作的基本输入。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- data + - 提供控制网络用于更复杂处理的附加数据流信息。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: List[Dict[str, Any]] + +# Output types +- data + - 包含控制网络处理后更新的数据流信息,可以进一步被下游利用。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] +- preview + - 展示处理后图像的视觉预览,演示控制网络调整的效果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeControlnetAdapterV2: + + def __init__(self): + self.expected_size = None + self.hed_annotator = 'ControlNetHED.pth' + self.leres_annotator = 'res101.pth' + self.hed_annotator_full_path = get_full_path('annotators', self.hed_annotator) + self.leres_annotator_full_path = get_full_path('annotators', self.leres_annotator) + + @classmethod + def INPUT_TYPES(s): + return {'required': {'controlnet_mode': (UI.CONTROLNET_MODES, {'default': UI.NONE}), 'controlnet_preprocessor': ('BOOLEAN', {'default': False}), 'strength': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 10.0, 'step': 0.05}), 'low_threshold': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'high_threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'end_percent': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'noise_augmentation': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'revision_enhancer': ('BOOLEAN', {'default': False})}, 'optional': {'data': ('SRG_DATA_STREAM',), 'source_image': ('IMAGE',)}} + RETURN_TYPES = ('SRG_DATA_STREAM', 'IMAGE') + RETURN_NAMES = ('data', 'preview') + FUNCTION = 'get_value' + CATEGORY = UI.CATEGORY_UI_PROMPTING + + def process_image(self, image, mode, low_threshold, high_threshold): + if mode == UI.CN_MODE_CANNY: + image = canny(image, low_threshold, high_threshold) + elif mode == UI.CN_MODE_DEPTH: + image = leres(image, low_threshold, high_threshold, self.leres_annotator_full_path) + elif mode == UI.CN_MODE_SKETCH: + image = hed(image, self.hed_annotator_full_path) + else: + pass + return image + + def create_dict(self, stack, source_image, controlnet_mode, controlnet_preprocessor, strength, low_threshold, high_threshold, start, end, noise_augmentation, revision_enhancer): + if controlnet_mode is None or controlnet_mode == UI.NONE: + cn_image = None + else: + cn_image = source_image + low_threshold = round(low_threshold, 3) + high_threshold = round(high_threshold, 3) + if controlnet_mode == UI.CN_MODE_REVISION or controlnet_mode == UI.CUSTOM: + controlnet_preprocessor = False + if controlnet_preprocessor and cn_image is not None: + cn_image = self.process_image(cn_image, controlnet_mode, low_threshold, high_threshold) + stack += [{UI.F_REV_CN_IMAGE: cn_image, UI.F_REV_CN_IMAGE_CHANGED: True, UI.F_REV_CN_MODE: controlnet_mode, UI.F_CN_PRE_PROCESSOR: controlnet_preprocessor, UI.F_REV_CN_STRENGTH: round(strength, 3), UI.F_CN_LOW_THRESHOLD: low_threshold, UI.F_CN_HIGH_THRESHOLD: high_threshold, UI.F_CN_START: round(start, 3), UI.F_CN_END: round(end, 3), UI.F_REV_NOISE_AUGMENTATION: round(noise_augmentation, 3), UI.F_REV_ENHANCER: revision_enhancer}] + return ({UI.F_CN_STACK: stack}, cn_image) + + def get_value(self, controlnet_mode, controlnet_preprocessor, strength, low_threshold, high_threshold, start_percent, end_percent, noise_augmentation, revision_enhancer, source_image=None, data=None): + if data is None: + data = {} + stack = retrieve_parameter(UI.F_CN_STACK, retrieve_parameter(UI.S_CONTROLNET_INPUTS, data), []) + if self.expected_size is None: + self.expected_size = len(stack) + elif self.expected_size == 0: + stack = [] + elif len(stack) > self.expected_size: + stack = stack[:self.expected_size] + (stack_entry, image) = self.create_dict(stack, source_image, controlnet_mode, controlnet_preprocessor, strength, low_threshold, high_threshold, start_percent, end_percent, noise_augmentation, revision_enhancer) + data[UI.S_CONTROLNET_INPUTS] = stack_entry + return (data, image) +``` \ No newline at end of file diff --git a/docs/SeargeControlnetModels.md b/docs/SeargeControlnetModels.md new file mode 100644 index 0000000..264be25 --- /dev/null +++ b/docs/SeargeControlnetModels.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: SeargeControlnetModels +- Category: UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点协调检索和整合各种控制网模型,用于图像处理任务,便于根据不同的模型检查点定制视觉输出。 + +# Input types +## Required +- clip_vision + - clip_vision参数对于选择影响生成图像视觉风格和内容的模型检查点至关重要。 + - Comfy dtype: COMBO[UI.CLIP_VISION_WITH_NONE()] + - Python dtype: Union[str, None] +- canny_checkpoint + - 该参数对于图像中的边缘检测至关重要,使节点能够根据所选检查点细化输出的结构元素。 + - Comfy dtype: COMBO[UI.CONTROLNETS_WITH_NONE()] + - Python dtype: Union[str, None] +- depth_checkpoint + - depth_checkpoint参数对于控制生成图像中的深度感知至关重要,增强了三维方面的展示。 + - Comfy dtype: COMBO[UI.CONTROLNETS_WITH_NONE()] + - Python dtype: Union[str, None] +- recolor_checkpoint + - 该参数对于调整图像的色彩板至关重要,允许最终视觉产品中有广泛的风格变化。 + - Comfy dtype: COMBO[UI.CONTROLNETS_WITH_NONE()] + - Python dtype: Union[str, None] +- sketch_checkpoint + - sketch_checkpoint参数在以素描风格渲染图像方面发挥着重要作用,提供了独特的艺术解读。 + - Comfy dtype: COMBO[UI.CONTROLNETS_WITH_NONE()] + - Python dtype: Union[str, None] +- custom_checkpoint + - 该参数允许实施自定义控制网模型,扩展节点的功能以满足特定的用户定义要求。 + - Comfy dtype: COMBO[UI.CONTROLNETS_WITH_NONE()] + - Python dtype: Union[str, None] + +# Output types +- data + - 数据输出是一个结构化的字典,包含了所选的控制网模型,为进一步的图像处理操作提供了基础。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeControlnetModels: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'clip_vision': (UI.CLIP_VISION_WITH_NONE(),), 'canny_checkpoint': (UI.CONTROLNETS_WITH_NONE(),), 'depth_checkpoint': (UI.CONTROLNETS_WITH_NONE(),), 'recolor_checkpoint': (UI.CONTROLNETS_WITH_NONE(),), 'sketch_checkpoint': (UI.CONTROLNETS_WITH_NONE(),), 'custom_checkpoint': (UI.CONTROLNETS_WITH_NONE(),)}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(clip_vision, canny_checkpoint, depth_checkpoint, recolor_checkpoint, sketch_checkpoint, custom_checkpoint): + return {UI.F_CLIP_VISION_CHECKPOINT: clip_vision, UI.F_CANNY_CHECKPOINT: canny_checkpoint, UI.F_DEPTH_CHECKPOINT: depth_checkpoint, UI.F_RECOLOR_CHECKPOINT: recolor_checkpoint, UI.F_SKETCH_CHECKPOINT: sketch_checkpoint, UI.F_CUSTOM_CHECKPOINT: custom_checkpoint} + + def get(self, clip_vision, canny_checkpoint, depth_checkpoint, recolor_checkpoint, sketch_checkpoint, custom_checkpoint, data=None): + if data is None: + data = {} + data[UI.S_CONTROLNET_MODELS] = self.create_dict(clip_vision, canny_checkpoint, depth_checkpoint, recolor_checkpoint, sketch_checkpoint, custom_checkpoint) + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeCustomAfterUpscaling.md b/docs/SeargeCustomAfterUpscaling.md new file mode 100644 index 0000000..7609acc --- /dev/null +++ b/docs/SeargeCustomAfterUpscaling.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: SeargeCustomAfterUpscaling +- Category: MAGIC_CUSTOM_STAGES +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +这个节点类旨在处理放大操作后的图像数据,使用自定义输出来完善和增强图像的视觉质量。 + +# Input types +## Required +- custom_output + - custom_output参数至关重要,因为它作为节点处理的主要输入。预期它包含来自前一个阶段的输出,然后用于检索和完善放大的图像。 + - Comfy dtype: SRG_STAGE_OUTPUT + - Python dtype: Dict[str, Any] + +# Output types +- image + - 这个节点的输出是一个增强的图像,是处理custom_output参数的结果。这个图像预期具有更高的质量,并且准备用于进一步的使用或分析。 + - Comfy dtype: IMAGE + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeCustomAfterUpscaling: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'custom_output': ('SRG_STAGE_OUTPUT',)}, 'optional': {}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'output' + CATEGORY = UI.CATEGORY_MAGIC_CUSTOM_STAGES + + def output(self, custom_output): + if custom_output is None: + return (None,) + vae_decoded = retrieve_parameter(Names.S_UPSCALED, custom_output) + image = retrieve_parameter(Names.F_UPSCALED_IMAGE, vae_decoded) + return (image,) +``` \ No newline at end of file diff --git a/docs/SeargeCustomAfterVaeDecode.md b/docs/SeargeCustomAfterVaeDecode.md new file mode 100644 index 0000000..2a56d93 --- /dev/null +++ b/docs/SeargeCustomAfterVaeDecode.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: SeargeCustomAfterVaeDecode +- Category: UI.CATEGORY_MAGIC_CUSTOM_STAGES +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点旨在通过解码和后处理变分自编码器(VAE)的输出来生成最终图像。它封装了将VAE的潜在空间表示转换为视觉输出所需的逻辑,提高了整个工作流程的效率和效果。 + +# Input types +## Required +- custom_output + - custom_output参数至关重要,因为它作为VAE解码过程的输入。它是前一个阶段的输出,包含了节点执行其功能所需的必要信息。 + - Comfy dtype: SRG_STAGE_OUTPUT + - Python dtype: Dict[str, Any] + +# Output types +- image + - 输出图像是VAE解码和后处理的结果。它代表了节点完成操作后的最终视觉产品,对于进一步的分析或显示至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeCustomAfterVaeDecode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'custom_output': ('SRG_STAGE_OUTPUT',)}, 'optional': {}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'output' + CATEGORY = UI.CATEGORY_MAGIC_CUSTOM_STAGES + + def output(self, custom_output): + if custom_output is None: + return (None,) + vae_decoded = retrieve_parameter(Names.S_VAE_DECODED, custom_output) + image = retrieve_parameter(Names.F_DECODED_IMAGE, vae_decoded) + post_processed = retrieve_parameter(Names.F_POST_PROCESSED, vae_decoded) + result = image if post_processed is None else post_processed + return (result,) +``` \ No newline at end of file diff --git a/docs/SeargeCustomPromptMode.md b/docs/SeargeCustomPromptMode.md new file mode 100644 index 0000000..9a83700 --- /dev/null +++ b/docs/SeargeCustomPromptMode.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: SeargeCustomPromptMode +- Category: UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点旨在促进用户界面中提示模式的定制,特别是针对数据流处理。它允许对数据呈现和交互方式进行动态调整,通过允许定制输入处理,增强用户体验。 + +# Input types +## Optional +- data + - ‘data’参数作为将由节点操作的数据流的通道。它在确定节点处理和定制的信息内容和结构方面至关重要。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Union[Dict[str, Any], None] + +# Output types +- data + - 输出‘data’参数代表节点处理后的修改后的数据流。它封装了定制的提示模式和对原始数据结构所做的任何更改。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeCustomPromptMode: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(example): + return {UI.EXAMPLE: example} + + def get(self, data=None): + if data is None: + data = {} + data[UI.S_CUSTOM_PROMPTING] = self.create_dict('example') + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeDebugPrinter.md b/docs/SeargeDebugPrinter.md new file mode 100644 index 0000000..ddf6198 --- /dev/null +++ b/docs/SeargeDebugPrinter.md @@ -0,0 +1,108 @@ +# Documentation +- Class name: SeargeDebugPrinter +- Category: DEBUG +- Output node: True +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeDebugPrinter节点旨在提供数据结构的详细和格式化输出,通过视觉检查数据流的内容,辅助调试过程。它强调数据内部的结构和关系,提供信息组织和处理方式的清晰度。 + +# Input types +## Required +- enabled + - ‘enabled’参数对于激活调试过程至关重要。当设置为true时,它会触发节点输出数据流的结构和内容,便于对正在处理的数据进行彻底检查。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- data + - ‘data’参数代表要检查和格式化用于调试目的的数据流。它是决定输出内容和结构的核心输入。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] +- prefix + - ‘prefix’参数用于在每行输出的开头添加一个字符串,增强调试信息的可读性和组织性。它有助于区分不同的数据点并追踪数据的来源。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- data + - 输出的‘data’代表原始输入的数据流,现在附带了其结构和内容的详细和格式化表示。这为进一步分析和调试提供了参考。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeDebugPrinter: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'enabled': ('BOOLEAN', {'default': True})}, 'optional': {'data': ('SRG_DATA_STREAM',), 'prefix': ('STRING', {'multiline': False, 'default': ''})}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'output' + OUTPUT_NODE = True + CATEGORY = UI.CATEGORY_DEBUG + + def output(self, enabled, data=None, prefix=None): + if data is None or not enabled: + return (data,) + prefix = '' if prefix is None or len(prefix) < 1 else prefix + ': ' + indent_spaces = '· ' + test_data = False + if test_data: + data['test_dict'] = {'k1': 1.0, 'k2': 2, 'k3': True} + data['test_list'] = ['l1', 2.0, 3] + data['test_tuple'] = (1, 't2', 3.0) + + def print_dict(coll, ind=0, kp='"', pk=True): + spaces = indent_spaces * ind + for (k, v) in coll.items(): + print_val(k, v, ind, kp, pk) + + def print_coll(coll, ind=0, kp='', pk=False): + spaces = indent_spaces * ind + cl = len(coll) + for i in range(0, cl): + v = coll[i] + print_val(i, v, ind, kp, pk) + + def print_val(k, v, ind=0, kp='"', pk=True): + spaces = indent_spaces * ind + key = kp + str(k) + kp + ': ' if pk else '' + if ind > 10: + print(prefix + spaces + key + '') + return + if v is None: + print(prefix + spaces + key + 'None,') + elif isinstance(v, int) or isinstance(v, float): + print(prefix + spaces + key + str(v) + ',') + elif isinstance(v, str): + print(prefix + spaces + key + '"' + v + '",') + elif isinstance(v, dict): + if k != Names.S_MAGIC_BOX_HIDDEN: + print(prefix + spaces + key + '{') + print_dict(v, ind + 1, '"', True) + print(prefix + spaces + '},') + else: + print(prefix + spaces + key + '{ ... printing skipped ... }') + elif isinstance(v, list): + print(prefix + spaces + key + '[') + print_coll(v, ind + 1, '', True) + print(prefix + spaces + '],') + elif isinstance(v, tuple): + print(prefix + spaces + key + '(') + print_coll(v, ind + 1, '', False) + print(prefix + spaces + '),') + else: + print(prefix + spaces + key + str(type(v))) + print(prefix + '===============================================================================') + if not isinstance(data, dict): + print(prefix + ' ! invalid data stream !') + else: + print(prefix + '* DATA STREAM *') + print(prefix + '---------------') + print_val('data', data) + print(prefix + '===============================================================================') + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeEnablerInputs.md b/docs/SeargeEnablerInputs.md new file mode 100644 index 0000000..56e54b4 --- /dev/null +++ b/docs/SeargeEnablerInputs.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: SeargeEnablerInputs +- Category: Searge/_deprecated_/Inputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点类旨在检索和管理系统状态,在已弃用的框架内作为状态相关操作的接口。它抽象地封装了状态获取过程,强调节点在维护和提供对系统当前状态的访问方面的作用。 + +# Input types +## Required +- state + - ‘state’参数对于节点的操作至关重要,因为它代表了系统当前的状态。它是决定节点行为和生成输出的基本元素。 + - Comfy dtype: COMBO[SeargeParameterProcessor.STATES] + - Python dtype: str + +# Output types +- state + - 输出‘state’反映了输入提供系统当前状态,标志着节点的主要功能在于状态管理和检索。 + - Comfy dtype: COMBO[SeargeParameterProcessor.STATES] + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeEnablerInputs: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'state': (SeargeParameterProcessor.STATES, {'default': SeargeParameterProcessor.STATES[1]})}} + RETURN_TYPES = ('ENABLE_STATE',) + RETURN_NAMES = ('state',) + FUNCTION = 'get_value' + CATEGORY = 'Searge/_deprecated_/Inputs' + + def get_value(self, state): + return (state,) +``` \ No newline at end of file diff --git a/docs/SeargeFloatConstant.md b/docs/SeargeFloatConstant.md new file mode 100644 index 0000000..bcc18a7 --- /dev/null +++ b/docs/SeargeFloatConstant.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: SeargeFloatConstant +- Category: Searge/_deprecated_/Floats +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeFloatConstant 是一个节点,旨在工作流中提供一个常量的浮点数值。它确保在系统或实验的不同部分使用一致且不变的值,有助于提高结果的可靠性和可复现性。 + +# Input types +## Required +- value + - 参数 'value' 是这个节点将提供的常量浮点数。它在维持系统稳定性中起着关键作用,通过提供计算和比较的固定参考点。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- value + - 输出 'value' 是作为输入设置的常量浮点数。它很重要,因为它代表了将在后续操作或分析中使用的未改变且预定义的常量。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeFloatConstant: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'value': ('FLOAT', {'default': 0.0, 'step': 0.01})}} + RETURN_TYPES = ('FLOAT',) + RETURN_NAMES = ('value',) + FUNCTION = 'get_value' + CATEGORY = 'Searge/_deprecated_/Floats' + + def get_value(self, value): + return (value,) +``` \ No newline at end of file diff --git a/docs/SeargeFloatMath.md b/docs/SeargeFloatMath.md new file mode 100644 index 0000000..a3cb978 --- /dev/null +++ b/docs/SeargeFloatMath.md @@ -0,0 +1,63 @@ +# Documentation +- Class name: SeargeFloatMath +- Category: Searge/_deprecated_/Floats +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeFloatMath节点旨在对浮点数执行基本的算术运算。它提供了一系列操作,如乘法、加法、减法、除法以及乘法与加法的组合。该节点的目标是提供一种直接的方法来执行这些基本的数学函数,从而在更广泛的计算环境中促进浮点值的操控。 + +# Input types +## Required +- op + - 参数'op'决定了要执行的算术运算。它至关重要,因为它指示了节点将执行的数学程序,从而影响计算的结果。 + - Comfy dtype: STRING + - Python dtype: str +- a + - 参数'a'代表算术运算中的一个操作数。它的值显著影响最终结果,使其成为节点功能的重要组成部分。 + - Comfy dtype: FLOAT + - Python dtype: float +- b + - 参数'b'用作需要两个输入的运算(如乘法或除法)中的一个操作数。它的存在取决于所选择的操作,但在需要时,它在计算中起着至关重要的作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- c + - 参数'c'是另一个操作数,它参与特定的算术运算,如加法或减法。在必要时,它对最终计算做出贡献,突出了它在某些情况下的重要性。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- result + - 输出'result'提供了节点执行的算术运算的结果。它是输入参数和所选操作的直接反映,概括了节点的目的。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeFloatMath: + OPERATIONS = ['a * b + c', 'a + c', 'a - c', 'a * b', 'a / b'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'op': (SeargeFloatMath.OPERATIONS, {'default': 'a * b + c'}), 'a': ('FLOAT', {'default': 0.0, 'step': 0.01}), 'b': ('FLOAT', {'default': 1.0, 'step': 0.01}), 'c': ('FLOAT', {'default': 0.0, 'step': 0.01})}} + RETURN_TYPES = ('FLOAT',) + RETURN_NAMES = ('result',) + FUNCTION = 'get_value' + CATEGORY = 'Searge/_deprecated_/Floats' + + def get_value(self, op, a, b, c): + res = 0.0 + if op == 'a * b + c': + res = a * b + c + elif op == 'a + c': + res = a + c + elif op == 'a - c': + res = a - c + elif op == 'a * b': + res = a * b + elif op == 'a / b': + res = a / b + return (res,) +``` \ No newline at end of file diff --git a/docs/SeargeFloatPair.md b/docs/SeargeFloatPair.md new file mode 100644 index 0000000..bd9bd9e --- /dev/null +++ b/docs/SeargeFloatPair.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: SeargeFloatPair +- Category: Searge/_deprecated_/Floats +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点类旨在处理并返回一对浮点数值,强调在已弃用的框架内对数值数据进行比较和操作。 + +# Input types +## Required +- value1 + - 第一个输入值是一个浮点数,在节点的操作中起着至关重要的作用,影响计算的结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- value2 + - 第二个输入值是另一个浮点数,与第一个值一起,对于节点执行其预期功能至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- value 1 + - 第一个输出是一个浮点数,代表节点对初始输入值处理的结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- value 2 + - 第二个输出是一个浮点数,对应于第二个输入值的结果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeFloatPair: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'value1': ('FLOAT', {'default': 0.0, 'step': 0.01}), 'value2': ('FLOAT', {'default': 0.0, 'step': 0.01})}} + RETURN_TYPES = ('FLOAT', 'FLOAT') + RETURN_NAMES = ('value 1', 'value 2') + FUNCTION = 'get_value' + CATEGORY = 'Searge/_deprecated_/Floats' + + def get_value(self, value1, value2): + return (value1, value2) +``` \ No newline at end of file diff --git a/docs/SeargeFreeU.md b/docs/SeargeFreeU.md new file mode 100644 index 0000000..17b9605 --- /dev/null +++ b/docs/SeargeFreeU.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: SeargeFreeU +- Category: UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点有助于配置和管理旨在无搜索环境下运行的系统的参数,提供了一种定义操作模式和设置的简化方法。 + +# Input types +## Required +- freeu_mode + - 决定系统的运行模式,这对于根据特定要求调整系统的行为和性能至关重要。 + - Comfy dtype: COMBO[FREEU_MODES] + - Python dtype: Enum +- b1 + - 影响参数的初始设置,这对于建立系统运行的基础条件至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- b2 + - 影响与主要设置一起工作的次要设置,以完善系统的操作参数。 + - Comfy dtype: FLOAT + - Python dtype: float +- s1 + - 修改控制系统敏感性的参数,调整其对输入数据的响应,确保最佳的交互。 + - Comfy dtype: FLOAT + - Python dtype: float +- s2 + - 调整另一个参数,微调系统的运行,专注于提高其适应性和精确性。 + - Comfy dtype: FLOAT + - Python dtype: float +- freeu_version + - 指定正在使用的系统的版本,这对于确保兼容性和功能可用性很重要。 + - Comfy dtype: FREEU_VERSION + - Python dtype: Enum + +# Output types +- data + - 包含用于设置和指导系统运行的结构化配置数据。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeFreeU: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'freeu_mode': (UI.FREEU_MODES,), 'b1': ('FLOAT', {'default': 1.3, 'min': 1.0, 'max': 1.4, 'step': 0.01}), 'b2': ('FLOAT', {'default': 1.4, 'min': 1.2, 'max': 1.6, 'step': 0.01}), 's1': ('FLOAT', {'default': 0.9, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 's2': ('FLOAT', {'default': 0.2, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'freeu_version': (UI.FREEU_VERSION,)}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(freeu_mode, b1, b2, s1, s2, freeu_version): + return {UI.F_FREEU_MODE: freeu_mode, UI.F_FREEU_B1: b1, UI.F_FREEU_B2: b2, UI.F_FREEU_S1: s1, UI.F_FREEU_S2: s2, UI.F_FREEU_VERSION: freeu_version} + + def get(self, freeu_mode, b1, b2, s1, s2, freeu_version, data=None): + if data is None: + data = {} + data[UI.S_FREEU] = self.create_dict(freeu_mode, b1, b2, s1, s2, freeu_version) + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeGenerated1.md b/docs/SeargeGenerated1.md new file mode 100644 index 0000000..2c49429 --- /dev/null +++ b/docs/SeargeGenerated1.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: SeargeGenerated1 +- Category: Searge/_deprecated_/UI/Generated +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点作为一个多路复用器,根据输入参数将它们路由到由输入指定的特定操作和风格。 + +# Input types +## Required +- parameters + - 该参数保存关键值对,这些关键值对指示节点的操作和风格选择,对确定节点的行为和输出起着关键作用。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Output types +- parameters + - 输出保留了输入参数,为后续操作提供了基础。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] +- operation_selector + - 此输出标识所选操作,指导节点的处理流程。 + - Comfy dtype: str + - Python dtype: str +- prompt_style_selector + - 此输出表示选定的提示风格,影响节点结果的呈现和格式化。 + - Comfy dtype: str + - Python dtype: str +- prompt_style_group + - 此输出代表提示风格的组,影响节点输出的整体美学和结构。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeGenerated1: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'parameters': ('PARAMETERS',)}} + RETURN_TYPES = ('PARAMETERS', 'INT', 'INT', 'INT') + RETURN_NAMES = ('parameters', 'operation_selector', 'prompt_style_selector', 'prompt_style_group') + FUNCTION = 'demux' + CATEGORY = 'Searge/_deprecated_/UI/Generated' + + def demux(self, parameters): + operation_selector = parameters['operation_selector'] + prompt_style_selector = parameters['prompt_style_selector'] + prompt_style_group = parameters['prompt_style_group'] + return (parameters, operation_selector, prompt_style_selector, prompt_style_group) +``` \ No newline at end of file diff --git a/docs/SeargeGenerationParameters.md b/docs/SeargeGenerationParameters.md new file mode 100644 index 0000000..3c9454c --- /dev/null +++ b/docs/SeargeGenerationParameters.md @@ -0,0 +1,92 @@ +# Documentation +- Class name: SeargeGenerationParameters +- Category: UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +此类节点封装了通过搜索方法生成图像所需的参数。它通过允许用户指定关键属性,如种子、图像尺寸和采样预设,简化了配置过程,这些属性共同影响生成图像的质量和特征。 + +# Input types +## Required +- seed + - 种子参数对于初始化随机数生成器至关重要,确保图像生成过程可复现。它决定了算法随机元素的起始点,因此在确定生成图像的独特性和一致性方面发挥着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- image_size_preset + - 图像尺寸预设参数允许用户为生成的图像选择预定义的分辨率。这个选择直接影响图像的细节程度和图像生成所需的计算资源,更高分辨率需要更多的处理能力。 + - Comfy dtype: COMBO + - Python dtype: str +- image_width + - 图像宽度参数指定了生成图像的水平尺寸。它是确定图像的宽高比和整体外观的关键因素,并且与图像高度参数共同作用以确定最终尺寸。 + - Comfy dtype: INT + - Python dtype: int +- image_height + - 图像高度参数定义了生成图像的垂直尺寸。它与图像宽度一起,为图像生成过程设置了画布大小,影响了内容的规模和布局。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步骤参数指的是生成过程将经历的迭代次数。更多的步骤通常会产生更精细和详细的图像,但也会增加生成所需的计算成本和时间。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数,通常表示为'cfg',是一个浮点值,用于调整图像质量与生成速度之间的平衡。较低的值可能会更快地生成图像,但细节较少,而较高的值可以在处理时间的代价下增强细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_preset + - 采样器预设参数使用户能够从一组预定义的采样策略中选择。每个预设都旨在为特定类型的内容或期望的结果优化生成过程,影响生成图像的多样性和一致性。 + - Comfy dtype: COMBO + - Python dtype: str +- sampler_name + - 采样器名称参数对于选择用于图像生成的特定算法至关重要。不同的采样器提供不同的图像精炼方法,影响最终输出的视觉风格和质量。 + - Comfy dtype: COMBO + - Python dtype: str +- scheduler + - 调度器参数决定了图像生成过程中采用的优化策略。它调节探索和利用之间的平衡,从而影响生成图像的收敛速度和质量。 + - Comfy dtype: COMBO + - Python dtype: str +- base_vs_refiner_ratio + - 基础与精炼者比例参数调整图像生成的基础和精炼阶段之间的平衡。它影响计算资源在图像初始创建和随后增强图像细节之间的分配。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- data + - 此节点的数据输出代表了包含生成参数的结构化信息流。它是图像生成过程的蓝图,封装了所有用户定义的设置,指导算法生成所需的图像。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: SRG_DATA_STREAM + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeGenerationParameters: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551600}), 'image_size_preset': (UI.RESOLUTION_PRESETS,), 'image_width': ('INT', {'default': 1024, 'min': 0, 'max': UI.MAX_RESOLUTION, 'step': 8}), 'image_height': ('INT', {'default': 1024, 'min': 0, 'max': UI.MAX_RESOLUTION, 'step': 8}), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 200}), 'cfg': ('FLOAT', {'default': 7.0, 'min': 0.5, 'max': 30.0, 'step': 0.5}), 'sampler_preset': (UI.SAMPLER_PRESETS,), 'sampler_name': (UI.SAMPLERS, {'default': 'dpmpp_2m'}), 'scheduler': (UI.SCHEDULERS, {'default': 'karras'}), 'base_vs_refiner_ratio': ('FLOAT', {'default': 0.8, 'min': 0.0, 'max': 1.0, 'step': 0.05})}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(seed, image_size_preset, image_width, image_height, steps, cfg, sampler_preset, sampler_name, scheduler, base_vs_refiner_ratio): + if sampler_preset == UI.SAMPLER_PRESET_DPMPP_2M_KARRAS: + (sampler_name, scheduler) = ('dpmpp_2m', 'karras') + elif sampler_preset == UI.SAMPLER_PRESET_EULER_A: + (sampler_name, scheduler) = ('euler_ancestral', 'normal') + elif sampler_preset == UI.SAMPLER_PRESET_DPMPP_2M_SDE_KARRAS: + (sampler_name, scheduler) = ('dpmpp_2m_sde', 'karras') + elif sampler_preset == UI.SAMPLER_PRESET_DPMPP_3M_SDE_EXPONENTIAL: + (sampler_name, scheduler) = ('dpmpp_3m_sde', 'exponential') + elif sampler_preset == UI.SAMPLER_PRESET_DDIM_UNIFORM: + (sampler_name, scheduler) = ('ddim', 'ddim_uniform') + return {UI.F_SEED: seed, UI.F_IMAGE_SIZE_PRESET: image_size_preset, UI.F_IMAGE_WIDTH: image_width, UI.F_IMAGE_HEIGHT: image_height, UI.F_STEPS: steps, UI.F_CFG: round(cfg, 3), UI.F_SAMPLER_PRESET: sampler_preset, UI.F_SAMPLER_NAME: sampler_name, UI.F_SCHEDULER: scheduler, UI.F_BASE_VS_REFINER_RATIO: round(base_vs_refiner_ratio, 3)} + + def get(self, seed, image_size_preset, image_width, image_height, steps, cfg, sampler_preset, sampler_name, scheduler, base_vs_refiner_ratio, data=None): + if data is None: + data = {} + data[UI.S_GENERATION_PARAMETERS] = self.create_dict(seed, image_size_preset, image_width, image_height, steps, cfg, sampler_preset, sampler_name, scheduler, base_vs_refiner_ratio) + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeHighResolution.md b/docs/SeargeHighResolution.md new file mode 100644 index 0000000..68cd160 --- /dev/null +++ b/docs/SeargeHighResolution.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: SeargeHighResolution +- Category: UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点类旨在通过应用一系列高分辨率技术来提高图像分辨率,目的是在不丢失重要视觉信息的情况下改善输入数据的质量和细节。 + +# Input types +## Required +- hires_mode + - 该参数决定了高分辨率增强的模式,对于确定用于改善图像质量的整体策略至关重要。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- hires_scale + - 比例参数至关重要,因为它设置了放大的程度,直接影响输出的分辨率和细节水平。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- hires_denoise + - 这控制去噪水平,对于减少噪声同时保留图像细节很重要,从而确保输出结果更清晰。 + - Comfy dtype: FLOAT + - Python dtype: float +- hires_softness + - 软度调整影响图像的锐度,在增强细节和避免过度锐化产生的伪影之间取得平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- hires_detail_boost + - 细节增强参数提升图像的细微细节,有助于产生更生动和逼真的视觉结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- hires_contrast_factor + - 通过调整对比度因子,节点可以操纵图像的动态范围,改善整体视觉冲击和深度。 + - Comfy dtype: FLOAT + - Python dtype: float +- hires_saturation_factor + - 饱和度因子在调整图像的颜色强度方面至关重要,增强了生动性,使视觉输出更具吸引力。 + - Comfy dtype: FLOAT + - Python dtype: float +- hires_latent_detailer + - 潜在细节提取器参数负责提炼图像的潜在特征,这对于实现高保真和详细的结果至关重要。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- final_upscale_size + - 该参数定义了最终放大的尺寸,这对于确定最终输出的分辨率和尺寸至关重要。 + - Comfy dtype: COMBO[str] + - Python dtype: str + +# Output types +- data + - 输出数据流包含处理过的高分辨率图像,这是应用各种增强技术的结果。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeHighResolution: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'hires_mode': (UI.HIRES_MODES, {'default': UI.NONE}), 'hires_scale': (UI.HIRES_SCALE_FACTORS, {'default': UI.HIRES_SCALE_1_5}), 'hires_denoise': ('FLOAT', {'default': 0.2, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'hires_softness': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'hires_detail_boost': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'hires_contrast_factor': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'hires_saturation_factor': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'hires_latent_detailer': (UI.LATENT_DETAILERS, {'default': UI.NONE}), 'final_upscale_size': (UI.UPSCALE_FACTORS, {'default': UI.NONE})}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(hires_mode, hires_scale, hires_denoise, hires_softness, hires_detail_boost, hires_contrast_factor, hires_saturation_factor, hires_latent_detailer, final_upscale_size): + return {UI.F_HIRES_MODE: hires_mode, UI.F_HIRES_SCALE: hires_scale, UI.F_HIRES_DENOISE: round(hires_denoise, 3), UI.F_HIRES_SOFTNESS: round(hires_softness, 3), UI.F_HIRES_DETAIL_BOOST: round(hires_detail_boost, 3), UI.F_HIRES_CONTRAST_FACTOR: round(hires_contrast_factor, 3), UI.F_HIRES_SATURATION_FACTOR: round(hires_saturation_factor, 3), UI.F_HIRES_LATENT_DETAILER: hires_latent_detailer, UI.F_FINAL_UPSCALE_SIZE: final_upscale_size} + + def get(self, hires_mode, hires_scale, hires_denoise, hires_softness, hires_detail_boost, hires_contrast_factor, hires_saturation_factor, hires_latent_detailer, final_upscale_size, data=None): + if data is None: + data = {} + data[UI.S_HIGH_RESOLUTION] = self.create_dict(hires_mode, hires_scale, hires_denoise, hires_softness, hires_detail_boost, hires_contrast_factor, hires_saturation_factor, hires_latent_detailer, final_upscale_size) + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeImage2ImageAndInpainting.md b/docs/SeargeImage2ImageAndInpainting.md new file mode 100644 index 0000000..a5d7763 --- /dev/null +++ b/docs/SeargeImage2ImageAndInpainting.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: SeargeImage2ImageAndInpainting +- Category: UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeImage2ImageAndInpainting 节点旨在促进图像到图像的转换和修复任务。它接受定义降噪级别和修复掩模特征的参数,并输出适合在图像处理工作流中进一步处理的结构化数据流。 + +# Input types +## Required +- denoise + - ‘denoise’参数控制应用于图像的降噪级别。它对于通过减少不需要的噪声同时保留重要细节来增强图像质量至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- inpaint_mask_blur + - ‘inpaint_mask_blur’参数决定了修复掩模的模糊半径,这对于图像中修复区域的平滑度非常重要。 + - Comfy dtype: INT + - Python dtype: int +- inpaint_mask_mode + - ‘inpaint_mask_mode’参数选择修复掩模的操作模式,影响修复过程如何应用于图像。 + - Comfy dtype: UI.MASK_MODES + - Python dtype: str +- data + - ‘data’参数是可选输入,允许用户为节点提供现有的数据流进行处理,增强了节点应用的灵活性。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: dict + +# Output types +- data + - ‘data’输出是一个结构化的数据流,封装了图像到图像转换和修复过程的结果,准备用于下游任务。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: dict + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeImage2ImageAndInpainting: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'denoise': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'inpaint_mask_blur': ('INT', {'default': 16, 'min': 0, 'max': 24, 'step': 4}), 'inpaint_mask_mode': (UI.MASK_MODES,)}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(denoise, inpaint_mask_blur, inpaint_mask_mode): + return {UI.F_DENOISE: round(denoise, 3), UI.F_INPAINT_MASK_BLUR: inpaint_mask_blur, UI.F_INPAINT_MASK_MODE: inpaint_mask_mode} + + def get(self, denoise, inpaint_mask_blur, inpaint_mask_mode, data=None): + if data is None: + data = {} + data[UI.S_IMG2IMG_INPAINTING] = self.create_dict(denoise, inpaint_mask_blur, inpaint_mask_mode) + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeImageAdapterV2.md b/docs/SeargeImageAdapterV2.md new file mode 100644 index 0000000..7c6681e --- /dev/null +++ b/docs/SeargeImageAdapterV2.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: SeargeImageAdapterV2 +- Category: UI_PROMPTING +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeImageAdapterV2 类旨在促进图像数据的转换和适配,以用于用户界面提示目的。它在将源图像、图像掩码和上传的掩码整合到 UI 组件可以有效利用的结构化数据流中起着关键作用。 + +# Input types +## Required +- source_image + - source_image 参数对于节点的操作至关重要,因为它表示需要处理的原始图像数据。它显著影响节点如何转换和构建数据以供下游任务使用。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, bytes, io.BufferedReader] +- image_mask + - image_mask 参数是一个可选输入,它定义了要应用于源图像的掩码。它对节点很重要,因为它决定了将被处理或突出显示的图像区域。 + - Comfy dtype: MASK + - Python dtype: Union[str, bytes, io.BufferedReader] +- uploaded_mask + - uploaded_mask 参数允许在图像处理流水线中包含用户上传的掩码。它的存在可以通过为图像操作提供额外的上下文来改变节点的行为。 + - Comfy dtype: MASK + - Python dtype: Union[str, bytes, io.BufferedReader] +- data + - data 参数用作可能需要用于节点操作的额外数据的容器。它是可选的,并且可以用来向节点传递补充信息。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Output types +- data + - data 输出是一个结构化的数据流,封装了处理后的图像和掩码信息。它很重要,因为它为后续的 UI 组件或下游处理阶段提供了必要的输入。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] +- S_IMAGE_INPUTS + - S_IMAGE_INPUTS 输出包含已适配用于 UI 提示的图像输入。它对于用户界面内的正确显示和交互至关重要。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeImageAdapterV2: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}, 'optional': {'data': ('SRG_DATA_STREAM',), 'source_image': ('IMAGE',), 'image_mask': ('MASK',), 'uploaded_mask': ('MASK',)}} + RETURN_TYPES = ('SRG_DATA_STREAM', 'SRG_DATA_STREAM') + RETURN_NAMES = ('data', UI.S_IMAGE_INPUTS) + FUNCTION = 'get_value' + CATEGORY = UI.CATEGORY_UI_PROMPTING + + @staticmethod + def create_dict(source_image, image_mask, uploaded_mask): + return {UI.F_SOURCE_IMAGE_CHANGED: True, UI.F_SOURCE_IMAGE: source_image, UI.F_IMAGE_MASK_CHANGED: True, UI.F_IMAGE_MASK: image_mask, UI.F_UPLOADED_MASK_CHANGED: True, UI.F_UPLOADED_MASK: uploaded_mask} + + def get_value(self, source_image=None, image_mask=None, uploaded_mask=None, data=None): + if data is None: + data = {} + data[UI.S_IMAGE_INPUTS] = self.create_dict(source_image, image_mask, uploaded_mask) + return (data, data[UI.S_IMAGE_INPUTS]) +``` \ No newline at end of file diff --git a/docs/SeargeImageSave.md b/docs/SeargeImageSave.md new file mode 100644 index 0000000..5e2e983 --- /dev/null +++ b/docs/SeargeImageSave.md @@ -0,0 +1,79 @@ +# Documentation +- Class name: SeargeImageSave +- Category: Searge/_deprecated_/Files +- Output node: True +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点旨在方便图像数据的保存,确保图像以相关的元数据和命名约定正确存储。 + +# Input types +## Required +- images + - 需要被节点保存的输入图像。这些图像是节点操作的主要数据,它们的质量和格式直接影响输出结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- filename_prefix + - 用于构建保存图像文件名的前缀字符串。该参数至关重要,因为它决定了保存文件的身份和组织。 + - Comfy dtype: STRING + - Python dtype: str +- state + - 影响节点执行的状态参数。它决定了节点是否执行保存操作。 + - Comfy dtype: ENABLE_STATE + - Python dtype: int +- save_to + - 该参数规定了保存图像的目的地文件夹。它对于组织输出和确保图像在后处理后可访问至关重要。 + - Comfy dtype: SAVE_FOLDER + - Python dtype: int +## Optional +- prompt + - 这是一个可选参数,提供后,将在图像元数据中包含提示文本。这为图像添加了上下文,可能对以后的参考有用。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - 要与图像一起保存的额外元数据。该参数允许包含额外信息,可以丰富保存图像的上下文和实用性。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, str] + +# Output types + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeImageSave: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'filename_prefix': ('STRING', {'default': 'SeargeSDXL-%date%/Image'}), 'state': ('ENABLE_STATE', {'default': SeargeParameterProcessor.STATES[1]}), 'save_to': ('SAVE_FOLDER', {'default': SeargeParameterProcessor.SAVE_TO[0]})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = () + FUNCTION = 'save_images' + OUTPUT_NODE = True + CATEGORY = 'Searge/_deprecated_/Files' + + def save_images(self, images, filename_prefix, state, save_to, prompt=None, extra_pnginfo=None): + if state == SeargeParameterProcessor.STATES[0]: + return {} + if save_to == SeargeParameterProcessor.SAVE_TO[1]: + output_dir = folder_paths.get_input_directory() + filename_prefix = 'output-%date%' + else: + output_dir = folder_paths.get_output_directory() + filename_prefix = filename_prefix.replace('%date%', datetime.now().strftime('%Y-%m-%d')) + (full_output_folder, filename, counter, subfolder, filename_prefix) = folder_paths.get_save_image_path(filename_prefix, output_dir, images[0].shape[1], images[0].shape[0]) + for image in images: + i = 255.0 * image.cpu().numpy() + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) + metadata = None + if args.disable_metadata is None or not args.disable_metadata: + metadata = PngInfo() + if prompt is not None: + metadata.add_text('prompt', json.dumps(prompt)) + if extra_pnginfo is not None: + for x in extra_pnginfo: + metadata.add_text(x, json.dumps(extra_pnginfo[x])) + file = f'{filename}_{counter:05}_.png' + img.save(os.path.join(full_output_folder, file), pnginfo=metadata, compress_level=4) + counter += 1 + return {} +``` \ No newline at end of file diff --git a/docs/SeargeImageSaving.md b/docs/SeargeImageSaving.md new file mode 100644 index 0000000..beafb84 --- /dev/null +++ b/docs/SeargeImageSaving.md @@ -0,0 +1,91 @@ +# Documentation +- Class name: SeargeImageSaving +- Category: UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点协调由过程生成的图像的保存,允许定制与保存不同分辨率的图像相关的参数,并可选择性地嵌入工作流。 + +# Input types +## Required +- save_parameters_file + - 该参数决定是否应保存图像保存参数,这对于保留用于图像生成的设置至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- save_folder + - 生成图像的保存目标文件夹,对于组织和访问图像生成过程的输出至关重要。 + - Comfy dtype: COMBO + - Python dtype: str +- save_generated_image + - 决定是否保存最初生成的图像,影响图像生成过程的主要输出的保存和可用性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- embed_workflow_in_generated + - 这控制工作流信息是否包含在生成的图像中,增强了图像创建过程的上下文和可追溯性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- generated_image_name + - 指定生成图像的文件名,这对于在系统中识别和引用输出非常重要。 + - Comfy dtype: STRING + - Python dtype: str +- save_high_res_image + - 指示是否应保存图像的高分辨率版本,影响保存图像的质量及其进一步使用的实用性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- embed_workflow_in_high_res + - 决定高分辨率图像是否应包含嵌入的工作流信息,这对于保持图像创建的完整性和上下文非常重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- high_res_image_name + - 定义高分辨率图像的文件名,确保输出在系统中易于区分和访问。 + - Comfy dtype: STRING + - Python dtype: str +- save_upscaled_image + - 控制是否保存图像的放大版本,这对于需要更大尺寸而不失细节的应用非常重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- embed_workflow_in_upscaled + - 这指定放大图像是否应包括工作流信息,确保缩放过程有记录且可追溯。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- upscaled_image_name + - 设置放大图像的文件名,这对于在系统中管理和引用增强分辨率的输出至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- data + - 该参数作为图像保存过程中可能需要的额外数据的容器,确保在各种场景中的灵活性和适应性。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Any + +# Output types +- data + - 输出包含了配置的图像保存参数,提供了一个结构化的格式,这对于下游过程按预期执行图像保存至关重要。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeImageSaving: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'save_parameters_file': ('BOOLEAN', {'default': True}), 'save_folder': (UI.SAVE_FOLDERS, {'default': UI.SAVE_TO_OUTPUT_DATE}), 'save_generated_image': ('BOOLEAN', {'default': True}), 'embed_workflow_in_generated': ('BOOLEAN', {'default': True}), 'generated_image_name': ('STRING', {'multiline': False, 'default': 'generated'}), 'save_high_res_image': ('BOOLEAN', {'default': True}), 'embed_workflow_in_high_res': ('BOOLEAN', {'default': True}), 'high_res_image_name': ('STRING', {'multiline': False, 'default': 'high-res'}), 'save_upscaled_image': ('BOOLEAN', {'default': True}), 'embed_workflow_in_upscaled': ('BOOLEAN', {'default': True}), 'upscaled_image_name': ('STRING', {'multiline': False, 'default': 'upscaled'})}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(save_parameters_file, save_folder, save_generated_image, embed_workflow_in_generated, generated_image_name, save_high_res_image, embed_workflow_in_high_res, high_res_image_name, save_upscaled_image, embed_workflow_in_upscaled, upscaled_image_name): + return {UI.F_SAVE_PARAMETERS_FILE: save_parameters_file is not None and save_parameters_file, UI.F_SAVE_FOLDER: save_folder, UI.F_SAVE_GENERATED_IMAGE: save_generated_image is not None and save_generated_image, UI.F_EMBED_WORKFLOW_IN_GENERATED: embed_workflow_in_generated is not None and embed_workflow_in_generated, UI.F_GENERATED_IMAGE_NAME: generated_image_name, UI.F_SAVE_HIGH_RES_IMAGE: save_high_res_image is not None and save_high_res_image, UI.F_EMBED_WORKFLOW_IN_HIGH_RES: embed_workflow_in_high_res is not None and embed_workflow_in_high_res, UI.F_HIGH_RES_IMAGE_NAME: high_res_image_name, UI.F_SAVE_UPSCALED_IMAGE: save_upscaled_image is not None and save_upscaled_image, UI.F_EMBED_WORKFLOW_IN_UPSCALED: embed_workflow_in_upscaled is not None and embed_workflow_in_upscaled, UI.F_UPSCALED_IMAGE_NAME: upscaled_image_name} + + def get(self, save_parameters_file, save_folder, save_generated_image, embed_workflow_in_generated, generated_image_name, save_high_res_image, embed_workflow_in_high_res, high_res_image_name, save_upscaled_image, embed_workflow_in_upscaled, upscaled_image_name, data=None): + if data is None: + data = {} + data[UI.S_IMAGE_SAVING] = self.create_dict(save_parameters_file, save_folder, save_generated_image, embed_workflow_in_generated, generated_image_name, save_high_res_image, embed_workflow_in_high_res, high_res_image_name, save_upscaled_image, embed_workflow_in_upscaled, upscaled_image_name) + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeInput1.md b/docs/SeargeInput1.md new file mode 100644 index 0000000..d5e1bb5 --- /dev/null +++ b/docs/SeargeInput1.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: SeargeInput1 +- Category: Searge/_deprecated_/UI/Inputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeInput1节点作为Searge系统的输入接口,用于收集和组织各种提示和可选输入。它旨在通过允许用户指定主要、次要、风格和负面提示,以及可选的图像、掩码和附加参数,将它们封装成结构化格式以供下游任务使用,从而简化输入过程。 + +# Input types +## Required +- main_prompt + - main_prompt参数对于定义输入的主要上下文或主题至关重要。它是一个可以跨越多行的字符串,允许详细的描述,这对于节点的操作和生成所需的输出至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- secondary_prompt + - secondary_prompt提供补充main_prompt的附加上下文或细节。它增强了节点理解和处理输入的能力,有助于产生更细致的输出。 + - Comfy dtype: STRING + - Python dtype: str +- style_prompt + - style_prompt参数用于指定输出应体现的风格元素或语气。它是塑造最终结果的美学或主题质量的关键组成部分。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt + - negative_prompt用于指示在输出中应避免哪些方面或特征。它在引导节点从最终产品中排除不需要的元素中起着重要作用。 + - Comfy dtype: STRING + - Python dtype: str +- negative_style + - negative_style参数通过进一步指定要省略的风格或质量来补充negative_prompt。它是微调输出以满足特定要求的重要工具。 + - Comfy dtype: STRING + - Python dtype: str +- inputs + - inputs参数是一个可选的字典,可以包含节点使用的其他参数。它提供了节点操作的灵活性,允许根据特定用例进行定制。 + - Comfy dtype: PARAMETER_INPUTS + - Python dtype: Dict[str, Any] +- image + - image参数是一个可选输入,允许包含视觉数据进行处理。当处理与图像相关的任务时,它可以显著影响节点的执行和输出的性质。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- mask + - mask参数是一个可选输入,用于定义在处理期间应该被不同对待或忽略的图像区域。对于需要选择性操作视觉数据的任务来说,它是必不可少的。 + - Comfy dtype: MASK + - Python dtype: np.ndarray + +# Output types +- inputs + - 'inputs'输出是封装了节点提供的提示和可选输入的结构化参数集合。它是Searge系统内后续处理步骤的基础。 + - Comfy dtype: PARAMETER_INPUTS + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeInput1: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'main_prompt': ('STRING', {'multiline': True, 'default': ''}), 'secondary_prompt': ('STRING', {'multiline': True, 'default': ''}), 'style_prompt': ('STRING', {'multiline': True, 'default': ''}), 'negative_prompt': ('STRING', {'multiline': True, 'default': ''}), 'negative_style': ('STRING', {'multiline': True, 'default': ''})}, 'optional': {'inputs': ('PARAMETER_INPUTS',), 'image': ('IMAGE',), 'mask': ('MASK',)}} + RETURN_TYPES = ('PARAMETER_INPUTS',) + RETURN_NAMES = ('inputs',) + FUNCTION = 'mux' + CATEGORY = 'Searge/_deprecated_/UI/Inputs' + + def mux(self, main_prompt, secondary_prompt, style_prompt, negative_prompt, negative_style, inputs=None, image=None, mask=None): + if inputs is None: + parameters = {} + else: + parameters = inputs + parameters['main_prompt'] = main_prompt + parameters['secondary_prompt'] = secondary_prompt + parameters['style_prompt'] = style_prompt + parameters['negative_prompt'] = negative_prompt + parameters['negative_style'] = negative_style + parameters['image'] = image + parameters['mask'] = mask + return (parameters,) +``` \ No newline at end of file diff --git a/docs/SeargeInput2.md b/docs/SeargeInput2.md new file mode 100644 index 0000000..4c23693 --- /dev/null +++ b/docs/SeargeInput2.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: SeargeInput2 +- Category: Searge/_deprecated_/UI/Inputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeInput2节点旨在处理图像处理任务的初始输入。它负责配置和启动定义图像特征的参数,例如其尺寸、处理步骤的数量以及将指导处理算法的配置设置。该节点抽象了设置这些参数的复杂性,为用户提供了一个简化的接口,用于输入图像生成或操作所需的数据。 + +# Input types +## Required +- seed + - ‘seed’参数对于图像生成过程至关重要,因为它确保了结果的可复现性。它作为随机数生成的起点,影响最终的输出图像。这个参数的重要性在于其能够控制随机性并在不同运行中实现一致的结果。 + - Comfy dtype: INT + - Python dtype: int +- image_width + - ‘image_width’参数指定了生成图像所需的宽度。它在确定图像的整体尺寸方面起着重要作用,这可以影响细节水平和处理所需的计算资源。此参数对于设置视觉输出的规模至关重要。 + - Comfy dtype: INT + - Python dtype: int +- image_height + - ‘image_height’参数定义了图像的垂直尺寸。与‘image_width’类似,它是图像分辨率的关键决定因素,并对细节和计算负载有影响。调整此参数可以控制图像的纵横比和整体大小。 + - Comfy dtype: INT + - Python dtype: int +- steps + - ‘steps’参数指的是图像处理算法将执行的迭代次数或步骤。它直接影响最终图像的质量和细节,更多的步骤通常会导致更精细的结果。这个参数对于平衡处理时间和输出质量之间的权衡至关重要。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - ‘cfg’参数,代表配置设置,用于微调图像处理算法。它影响图像生成的各个方面,如清晰度和某些特征的存在。这个参数对于实现所需的视觉效果并确保输出满足特定要求很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - ‘sampler_name’参数选择图像生成中随机过程使用的采样方法。它对于确定生成图像的随机性和多样性很重要。采样器的选择可以显著影响最终输出的风格和特征。 + - Comfy dtype: STRING + - Python dtype: str +- scheduler + - ‘scheduler’参数确定图像生成过程的调度策略。它决定算法如何通过步骤进展,这可以影响效率和最终结果。此参数对于优化生成过程并在给定时间框架内获得最佳结果至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- save_image + - ‘save_image’参数指示是否应将生成的图像保存到文件中。它控制图像处理后的行动,对于希望保留输出以供进一步使用或分析的用户来说很重要。 + - Comfy dtype: STRING + - Python dtype: str +- save_directory + - ‘save_directory’参数指定将保存生成图像的位置。它对于组织输出和确保用户可以轻松访问和管理其文件至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- inputs + - ‘inputs’参数是一个可选的字典,允许用户为图像处理任务提供额外的设置或参数。它提供灵活性和定制性,使用户能够根据特定要求调整节点的行为。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Output types +- parameters + - ‘parameters’输出包含由SeargeInput2节点处理的配置和输入集。它封装了图像处理后续阶段所需的所有必要信息,确保从输入到执行的顺利过渡。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeInput2: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'image_width': ('INT', {'default': 1024, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'image_height': ('INT', {'default': 1024, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'steps': ('INT', {'default': 20, 'min': 0, 'max': 200}), 'cfg': ('FLOAT', {'default': 7.0, 'min': 0.0, 'max': 30.0, 'step': 0.5}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS, {'default': 'ddim'}), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS, {'default': 'ddim_uniform'}), 'save_image': (SeargeParameterProcessor.STATES, {'default': SeargeParameterProcessor.STATES[1]}), 'save_directory': (SeargeParameterProcessor.SAVE_TO, {'default': SeargeParameterProcessor.SAVE_TO[0]})}, 'optional': {'inputs': ('PARAMETER_INPUTS',)}} + RETURN_TYPES = ('PARAMETER_INPUTS',) + RETURN_NAMES = ('inputs',) + FUNCTION = 'mux' + CATEGORY = 'Searge/_deprecated_/UI/Inputs' + + def mux(self, seed, image_width, image_height, steps, cfg, sampler_name, scheduler, save_image, save_directory, inputs=None): + if inputs is None: + parameters = {} + else: + parameters = inputs + parameters['seed'] = seed + parameters['image_width'] = image_width + parameters['image_height'] = image_height + parameters['steps'] = steps + parameters['cfg'] = cfg + parameters['sampler_name'] = sampler_name + parameters['scheduler'] = scheduler + parameters['save_image'] = save_image + parameters['save_directory'] = save_directory + return (parameters,) +``` \ No newline at end of file diff --git a/docs/SeargeInput3.md b/docs/SeargeInput3.md new file mode 100644 index 0000000..febd8ce --- /dev/null +++ b/docs/SeargeInput3.md @@ -0,0 +1,84 @@ +# Documentation +- Class name: SeargeInput3 +- Category: Searge/_deprecated_/UI/Inputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点作为各种输入参数的多路复用器,简化了将多样化配置集成到系统中的过程。它旨在处理必需和可选输入,确保必要的数据高效传递,不会有信息丢失。 + +# Input types +## Required +- base_ratio + - 基础比例参数对于建立输入数据的基本缩放比例至关重要。它显著影响处理输出的初始尺寸。 + - Comfy dtype: FLOAT + - Python dtype: float +- refiner_strength + - 细化强度决定了应用于缩放数据的后处理步骤的强度。它影响输出的最终质量和细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- refiner_intensity + - 细化强度设置调整了放大过程中细节保留的水平。对于在性能和输出清晰度之间取得平衡至关重要。 + - Comfy dtype: ENUM + - Python dtype: Enum +- precondition_steps + - 预处理步骤的数量决定了初步处理的复杂性。它是优化放大过程的效率和效果的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- batch_size + - 批处理大小影响同时处理的数据点数量。它是管理计算资源和加快执行速度的关键参数。 + - Comfy dtype: INT + - Python dtype: int +- upscale_resolution_factor + - 这个因素直接影响放大图像的最终分辨率。它在决定输出的视觉保真度和计算需求方面至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- save_upscaled_image + - 保存放大图像的决定影响工作流的结果。它确保结果被保存以供进一步分析或使用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- inputs + - 此参数允许包含额外的输入参数,增强了节点的多功能性和适应不同场景的能力。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] +- denoise + - 去噪参数对于降噪过程至关重要,控制从放大图像中过滤掉的噪声水平。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- inputs + - 输出是包含所有输入的全面参数集,为数据的进一步处理提供了结构化和有序的表示。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeInput3: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_ratio': ('FLOAT', {'default': 0.8, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'refiner_strength': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 1.0, 'step': 0.05}), 'refiner_intensity': (SeargeParameterProcessor.REFINER_INTENSITY, {'default': SeargeParameterProcessor.REFINER_INTENSITY[1]}), 'precondition_steps': ('INT', {'default': 0, 'min': 0, 'max': 10}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 4}), 'upscale_resolution_factor': ('FLOAT', {'default': 2.0, 'min': 0.25, 'max': 4.0, 'step': 0.25}), 'save_upscaled_image': (SeargeParameterProcessor.STATES, {'default': SeargeParameterProcessor.STATES[1]})}, 'optional': {'inputs': ('PARAMETER_INPUTS',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('PARAMETER_INPUTS',) + RETURN_NAMES = ('inputs',) + FUNCTION = 'mux' + CATEGORY = 'Searge/_deprecated_/UI/Inputs' + + def mux(self, base_ratio, refiner_strength, refiner_intensity, precondition_steps, batch_size, upscale_resolution_factor, save_upscaled_image, inputs=None, denoise=None): + if inputs is None: + parameters = {} + else: + parameters = inputs + parameters['denoise'] = denoise + parameters['base_ratio'] = base_ratio + parameters['refiner_strength'] = refiner_strength + parameters['refiner_intensity'] = refiner_intensity + parameters['precondition_steps'] = precondition_steps + parameters['batch_size'] = batch_size + parameters['upscale_resolution_factor'] = upscale_resolution_factor + parameters['save_upscaled_image'] = save_upscaled_image + return (parameters,) +``` \ No newline at end of file diff --git a/docs/SeargeInput4.md b/docs/SeargeInput4.md new file mode 100644 index 0000000..da5232d --- /dev/null +++ b/docs/SeargeInput4.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: SeargeInput4 +- Category: Searge/_deprecated_/UI/Inputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点作为多种模型输入的多路复用器,整合并组织它们以供进一步处理。它确保基于提供的设置选择适当的模型,简化了工作流程并提高了模型集成的效率。 + +# Input types +## Required +- base_model + - 基础模型是构成进一步改进和增强的基础神经网络架构。其选择至关重要,因为它直接影响输出的质量和适用性。 + - Comfy dtype: COMBO[folder_paths.get_filename_list('checkpoints'),] + - Python dtype: List[str] +- refiner_model + - 细化模型是在基础模型之上的进阶版本,专注于提高模型性能的特定方面。其包含对于在结果中实现更高的准确性和细节至关重要。 + - Comfy dtype: COMBO[folder_paths.get_filename_list('checkpoints'),] + - Python dtype: List[str] +- vae_model + - VAE(变分自编码器)模型用于降维和生成与输入数据相似的新数据点。其在创建压缩表示和促进新数据生成方面的作用至关重要。 + - Comfy dtype: COMBO[folder_paths.get_filename_list('vae'),] + - Python dtype: List[str] +- main_upscale_model + - 主要放大模型负责提高输入数据的分辨率。它在提高输出的视觉质量和细节方面发挥着关键作用,确保放大的结果达到预期的标准。 + - Comfy dtype: COMBO[folder_paths.get_filename_list('upscale_models'),] + - Python dtype: List[str] +- support_upscale_model + - 支持放大模型协助放大过程,为主放大模型提供额外支持。它的存在有助于放大过程的稳健性和可靠性,确保最终输出的质量。 + - Comfy dtype: COMBO[folder_paths.get_filename_list('upscale_models'),] + - Python dtype: List[str] +- lora_model + - LoRA(低秩适应)模型用于有效适应预训练模型到新任务或数据。它在实现模型使用的适应性和灵活性方面发挥着重要作用,允许在多样化数据集上获得更好的性能。 + - Comfy dtype: COMBO[folder_paths.get_filename_list('loras'),] + - Python dtype: List[str] +## Optional +- model_settings + - 模型设置是可选的配置,可用于根据特定要求或偏好定制模型的行为,而无需更改基础模型本身。 + - Comfy dtype: Dict[str, str] + - Python dtype: Optional[Dict[str, str]] + +# Output types +- model_names + - 输出是一个模型名称的字典,它为工作流中不同目的选定的模型提供了结构化的概览。这种有组织的表示对于后续步骤正确利用适当的模型至关重要。 + - Comfy dtype: Dict[str, str] + - Python dtype: Dict[str, str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeInput4: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_model': (folder_paths.get_filename_list('checkpoints'),), 'refiner_model': (folder_paths.get_filename_list('checkpoints'),), 'vae_model': (folder_paths.get_filename_list('vae'),), 'main_upscale_model': (folder_paths.get_filename_list('upscale_models'),), 'support_upscale_model': (folder_paths.get_filename_list('upscale_models'),), 'lora_model': (folder_paths.get_filename_list('loras'),)}, 'optional': {'model_settings': ('MODEL_SETTINGS',)}} + RETURN_TYPES = ('MODEL_NAMES',) + RETURN_NAMES = ('model_names',) + FUNCTION = 'mux' + CATEGORY = 'Searge/_deprecated_/UI/Inputs' + + def mux(self, base_model, refiner_model, vae_model, main_upscale_model, support_upscale_model, lora_model, model_settings=None): + if model_settings is None: + model_names = {} + else: + model_names = model_settings + model_names['base_model'] = base_model + model_names['refiner_model'] = refiner_model + model_names['vae_model'] = vae_model + model_names['main_upscale_model'] = main_upscale_model + model_names['support_upscale_model'] = support_upscale_model + model_names['lora_model'] = lora_model + return (model_names,) +``` \ No newline at end of file diff --git a/docs/SeargeInput5.md b/docs/SeargeInput5.md new file mode 100644 index 0000000..405ef1c --- /dev/null +++ b/docs/SeargeInput5.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: SeargeInput5 +- Category: Searge/_deprecated_/UI/Inputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeInput5节点作为处理和整合各种条件尺度和风格参数的中心枢纽,为进一步处理提供一致的输入集。它旨在处理必需和可选参数,确保输入配置的灵活性,同时保持数据流的结构化方法。 + +# Input types +## Required +- base_conditioning_scale + - 基础条件尺度是一个关键参数,它影响处理流水线中初始的细节水平。它为后续的细化阶段设定了基调,影响输出的整体质量和分辨率。 + - Comfy dtype: FLOAT + - Python dtype: float +- refiner_conditioning_scale + - 细化条件尺度对于在初始处理后微调输出至关重要。它允许对最终结果的细节和清晰度进行调整,确保输出精致且经过精炼。 + - Comfy dtype: FLOAT + - Python dtype: float +- style_prompt_power + - 风格提示功率决定了风格模板对最终输出的影响。它是形成结果的艺术性和审美方面的关键因素,允许在创造性和控制性之间取得平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- negative_style_power + - 负风格功率用于抵消或抑制输出中的某些风格元素。它提供了一种对结果的风格方向进行精细控制的机制,实现了对风格应用的微妙方法。 + - Comfy dtype: FLOAT + - Python dtype: float +- style_template + - 风格模板参数在定义输出的风格框架中起着关键作用。它作为艺术表达的蓝图,指导最终产品的整体外观和感觉。 + - Comfy dtype: SeargeParameterProcessor.STYLE_TEMPLATE + - Python dtype: str +## Optional +- inputs + - 可选的输入参数允许在节点操作中进行额外的定制和灵活性。它允许集成外部数据源或参数,可以进一步细化节点的功能。 + - Comfy dtype: PARAMETER_INPUTS + - Python dtype: Dict[str, Any] + +# Output types +- parameters + - 输出参数封装了处理后的输入,提供了一个结构化的数据集,准备进行下游处理。这个输出很重要,因为它构成了工作流中后续操作的基础。 + - Comfy dtype: PARAMETER_INPUTS + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeInput5: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_conditioning_scale': ('FLOAT', {'default': 2.0, 'min': 0.25, 'max': 4.0, 'step': 0.25}), 'refiner_conditioning_scale': ('FLOAT', {'default': 2.0, 'min': 0.25, 'max': 4.0, 'step': 0.25}), 'style_prompt_power': ('FLOAT', {'default': 0.33, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'negative_style_power': ('FLOAT', {'default': 0.67, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'style_template': (SeargeParameterProcessor.STYLE_TEMPLATE, {'default': SeargeParameterProcessor.STYLE_TEMPLATE[0]})}, 'optional': {'inputs': ('PARAMETER_INPUTS',)}} + RETURN_TYPES = ('PARAMETER_INPUTS',) + RETURN_NAMES = ('inputs',) + FUNCTION = 'mux' + CATEGORY = 'Searge/_deprecated_/UI/Inputs' + + def mux(self, base_conditioning_scale, refiner_conditioning_scale, style_prompt_power, negative_style_power, style_template, inputs=None): + if inputs is None: + parameters = {} + else: + parameters = inputs + parameters['base_conditioning_scale'] = base_conditioning_scale + parameters['refiner_conditioning_scale'] = refiner_conditioning_scale + parameters['style_prompt_power'] = style_prompt_power + parameters['negative_style_power'] = negative_style_power + parameters['style_template'] = style_template + return (parameters,) +``` \ No newline at end of file diff --git a/docs/SeargeInput6.md b/docs/SeargeInput6.md new file mode 100644 index 0000000..f00bc5e --- /dev/null +++ b/docs/SeargeInput6.md @@ -0,0 +1,79 @@ +# Documentation +- Class name: SeargeInput6 +- Category: Searge/_deprecated_/UI/Inputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点作为配置和组合与高分辨率图像处理相关的各种参数的接口。它旨在通过允许用户一次输入和调整多个参数来简化设置高分辨率修复任务的过程。节点的主要功能是促进图像处理任务的准备和管理,确保正确应用和组织必要的设置。 + +# Input types +## Required +- hires_fix + - 该参数对于定义高分辨率修复过程的状态至关重要。它规定了图像处理开始的初始条件,显著影响任务的结果。 + - Comfy dtype: SeargeParameterProcessor.STATES + - Python dtype: SeargeParameterProcessor.STATES +- hrf_steps + - 高分辨率修复步骤的数量对于控制图像细化的迭代过程至关重要。它影响最终输出的细节层次和整体质量。 + - Comfy dtype: INT + - Python dtype: int +- hrf_denoise + - 去噪参数在减少图像噪声和伪影方面起着关键作用,从而提高处理图像的清晰度和视觉吸引力。 + - Comfy dtype: FLOAT + - Python dtype: float +- hrf_upscale_factor + - 放大因子决定了图像将被放大的程度,直接影响最终图像的分辨率和细节量。 + - Comfy dtype: FLOAT + - Python dtype: float +- hrf_intensity + - 强度参数影响图像处理效果的强度,例如锐化和对比度增强,这对于实现期望的视觉结果至关重要。 + - Comfy dtype: SeargeParameterProcessor.REFINER_INTENSITY + - Python dtype: SeargeParameterProcessor.REFINER_INTENSITY +- hrf_seed_offset + - 种子偏移量对于确保图像处理结果的随机性和多样性很重要,特别是在处理多个图像或批次时非常有用。 + - Comfy dtype: SeargeParameterProcessor.HRF_SEED_OFFSET + - Python dtype: SeargeParameterProcessor.HRF_SEED_OFFSET +- hrf_smoothness + - 平滑度参数有助于控制处理图像的锐度和纹理,有助于最终产品的总体美观和质量。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- inputs + - 该参数允许包含额外的输入,可用于进一步定制高分辨率图像处理工作流程。 + - Comfy dtype: PARAMETER_INPUTS + - Python dtype: dict + +# Output types +- inputs + - 输出是通过节点配置的一组有序参数。这些参数对于高分辨率图像处理流水线中的后续步骤至关重要。 + - Comfy dtype: PARAMETER_INPUTS + - Python dtype: dict + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeInput6: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'hires_fix': (SeargeParameterProcessor.STATES, {'default': SeargeParameterProcessor.STATES[1]}), 'hrf_steps': ('INT', {'default': 0, 'min': 0, 'max': 100}), 'hrf_denoise': ('FLOAT', {'default': 0.1, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'hrf_upscale_factor': ('FLOAT', {'default': 1.5, 'min': 0.25, 'max': 4.0, 'step': 0.25}), 'hrf_intensity': (SeargeParameterProcessor.REFINER_INTENSITY, {'default': SeargeParameterProcessor.REFINER_INTENSITY[1]}), 'hrf_seed_offset': (SeargeParameterProcessor.HRF_SEED_OFFSET, {'default': SeargeParameterProcessor.HRF_SEED_OFFSET[1]}), 'hrf_smoothness': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.05})}, 'optional': {'inputs': ('PARAMETER_INPUTS',)}} + RETURN_TYPES = ('PARAMETER_INPUTS',) + RETURN_NAMES = ('inputs',) + FUNCTION = 'mux' + CATEGORY = 'Searge/_deprecated_/UI/Inputs' + + def mux(self, hires_fix, hrf_steps, hrf_denoise, hrf_upscale_factor, hrf_intensity, hrf_seed_offset, hrf_smoothness, inputs=None): + if inputs is None: + parameters = {} + else: + parameters = inputs + parameters['hires_fix'] = hires_fix + parameters['hrf_steps'] = hrf_steps + parameters['hrf_denoise'] = hrf_denoise + parameters['hrf_upscale_factor'] = hrf_upscale_factor + parameters['hrf_intensity'] = hrf_intensity + parameters['hrf_seed_offset'] = hrf_seed_offset + parameters['hrf_smoothness'] = hrf_smoothness + return (parameters,) +``` \ No newline at end of file diff --git a/docs/SeargeInput7.md b/docs/SeargeInput7.md new file mode 100644 index 0000000..c758a95 --- /dev/null +++ b/docs/SeargeInput7.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: SeargeInput7 +- Category: Searge/_deprecated_/UI/Inputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点作为输入参数的多路复用器,简化了将各种设置集成到系统中的过程。它确保参数被正确路由和管理,便于整体操作无需手动干预。 + +# Input types +## Required +- lora_strength + - Lora强度是一个关键参数,影响系统对输入信号的敏感性。它对于调整响应性并确保实现期望的输出至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- operation_mode + - 操作模式决定了系统的一般工作状态,影响其行为和处理输入的方式。这对于将系统的功能与预期用例对齐至关重要。 + - Comfy dtype: ENUM + - Python dtype: str +- prompt_style + - 提示风格塑造了系统与用户的呈现和互动方式,确保以符合用户期望和系统设计的方式征求和处理输入。 + - Comfy dtype: ENUM + - Python dtype: str +## Optional +- inputs + - 输入是一个可选参数,允许对系统进行额外的定制和微调。它提供了一系列的选项,以根据具体要求进一步优化操作。 + - Comfy dtype: PARAMETER_INPUTS + - Python dtype: Dict[str, Any] + +# Output types +- inputs + - 输出代表了整合和处理过的参数集,这些参数对于系统后续操作阶段至关重要。它封装了系统的配置,确保了预期功能的维持。 + - Comfy dtype: PARAMETER_INPUTS + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeInput7: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'lora_strength': ('FLOAT', {'default': 0.2, 'min': -10.0, 'max': 10.0, 'step': 0.05}), 'operation_mode': (SeargeParameterProcessor.OPERATION_MODE, {'default': SeargeParameterProcessor.OPERATION_MODE[0]}), 'prompt_style': (SeargeParameterProcessor.PROMPT_STYLE, {'default': SeargeParameterProcessor.PROMPT_STYLE[0]})}, 'optional': {'inputs': ('PARAMETER_INPUTS',)}} + RETURN_TYPES = ('PARAMETER_INPUTS',) + RETURN_NAMES = ('inputs',) + FUNCTION = 'mux' + CATEGORY = 'Searge/_deprecated_/UI/Inputs' + + def mux(self, lora_strength, operation_mode, prompt_style, inputs=None): + if inputs is None: + parameters = {} + else: + parameters = inputs + parameters['lora_strength'] = lora_strength + parameters['operation_mode'] = operation_mode + parameters['prompt_style'] = prompt_style + return (parameters,) +``` \ No newline at end of file diff --git a/docs/SeargeIntegerConstant.md b/docs/SeargeIntegerConstant.md new file mode 100644 index 0000000..49c8c0e --- /dev/null +++ b/docs/SeargeIntegerConstant.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: SeargeIntegerConstant +- Category: Searge/_deprecated_/Integers +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeIntegerConstant节点在工作流中提供一个常量整数值。它旨在提供稳定且不变的整数,可以在各种计算或比较中使用,无需外部输入或数据处理。 + +# Input types +## Required +- value + - 参数'value'是SeargeIntegerConstant节点的核心,代表节点将始终返回的固定整数。它作为工作流中的基础组件,确保下游操作能够访问到一个一致且预定义的整数值。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- value + - 输出'value'是SeargeIntegerConstant节点提供的唯一结果,即作为输入设置的常量整数。它的重要性在于确保整数在整个工作流中保持不变,从而促进可预测和稳定的操作。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeIntegerConstant: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'value': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('value',) + FUNCTION = 'get_value' + CATEGORY = 'Searge/_deprecated_/Integers' + + def get_value(self, value): + return (value,) +``` \ No newline at end of file diff --git a/docs/SeargeIntegerMath.md b/docs/SeargeIntegerMath.md new file mode 100644 index 0000000..8283654 --- /dev/null +++ b/docs/SeargeIntegerMath.md @@ -0,0 +1,63 @@ +# Documentation +- Class name: SeargeIntegerMath +- Category: Searge/_deprecated_/Integers +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点根据用户选择的选项执行各种整数算术运算,有助于系统内整数数据的处理和转换。 + +# Input types +## Required +- op + - 操作参数决定了要应用的算术函数,是节点计算过程的基石。 + - Comfy dtype: COMBO[SeargeIntegerMath.OPERATIONS] + - Python dtype: str +- a + - 参数'a'代表整数运算中的第一个操作数,在决定运算结果中起着至关重要的作用。 + - Comfy dtype: INT + - Python dtype: int +- b + - 参数'b'是乘法和除法操作的第二个操作数,对最终结果有重大影响。 + - Comfy dtype: INT + - Python dtype: int +- c + - 参数'c'是加法和减法操作中的第三个操作数,影响整体计算。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result + - 输出'result'显示应用所选算术运算后的计算值,代表了节点功能的最终成果。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeIntegerMath: + OPERATIONS = ['a * b + c', 'a + c', 'a - c', 'a * b', 'a / b'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'op': (SeargeIntegerMath.OPERATIONS, {'default': 'a * b + c'}), 'a': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'b': ('INT', {'default': 1, 'min': 0, 'max': 18446744073709551615}), 'c': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('result',) + FUNCTION = 'get_value' + CATEGORY = 'Searge/_deprecated_/Integers' + + def get_value(self, op, a, b, c): + res = 0 + if op == 'a * b + c': + res = a * b + c + elif op == 'a + c': + res = a + c + elif op == 'a - c': + res = a - c + elif op == 'a * b': + res = a * b + elif op == 'a / b': + res = a // b + return (int(res),) +``` \ No newline at end of file diff --git a/docs/SeargeIntegerPair.md b/docs/SeargeIntegerPair.md new file mode 100644 index 0000000..b9d150f --- /dev/null +++ b/docs/SeargeIntegerPair.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: SeargeIntegerPair +- Category: Searge/_deprecated_/Integers +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点旨在处理并返回整数对,是涉及数值分析或数据操作的工作流中的基本组件。 + +# Input types +## Required +- value1 + - 这对中的第一个整数,对于节点的操作至关重要,因为它构成了这对数值关系的基础。 + - Comfy dtype: INT + - Python dtype: int +- value2 + - 这对中的第二个整数,与第一个值一起,完成了数值集并影响了节点的输出。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- value 1 + - 输出元组的第一个元素,代表提供给节点的初始整数值。 + - Comfy dtype: INT + - Python dtype: int +- value 2 + - 输出元组的第二个元素,代表提供给节点的第二个整数值。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeIntegerPair: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'value1': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'value2': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('INT', 'INT') + RETURN_NAMES = ('value 1', 'value 2') + FUNCTION = 'get_value' + CATEGORY = 'Searge/_deprecated_/Integers' + + def get_value(self, value1, value2): + return (value1, value2) +``` \ No newline at end of file diff --git a/docs/SeargeIntegerScaler.md b/docs/SeargeIntegerScaler.md new file mode 100644 index 0000000..274c496 --- /dev/null +++ b/docs/SeargeIntegerScaler.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: SeargeIntegerScaler +- Category: Searge/_deprecated_/Integers +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点基于提供的因子和倍数对输入整数值进行缩放和四舍五入。它确保输出值保持在所需的范围和粒度内的整数。 + +# Input types +## Required +- value + - 将由节点操作缩放的初始整数值。它是节点目的的基础,因为它是将经历转换的基础值。 + - Comfy dtype: INT + - Python dtype: int +- factor + - 应用于输入值的乘数,以确定缩放的比例。它非常重要,因为它直接影响输出的大小。 + - Comfy dtype: FLOAT + - Python dtype: float +- multiple_of + - 缩放结果应该是其倍数的值,确保输出在范围内四舍五入到最近的可接受值。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- value + - 处理后的整数值,现已根据输入参数缩放并四舍五入,代表节点的最终输出。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeIntegerScaler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'value': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'factor': ('FLOAT', {'default': 1.0, 'step': 0.01}), 'multiple_of': ('INT', {'default': 1, 'min': 0, 'max': 65536})}} + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('value',) + FUNCTION = 'get_value' + CATEGORY = 'Searge/_deprecated_/Integers' + + def get_value(self, value, factor, multiple_of): + return (int(value * factor // multiple_of) * multiple_of,) +``` \ No newline at end of file diff --git a/docs/SeargeLatentMuxer3.md b/docs/SeargeLatentMuxer3.md new file mode 100644 index 0000000..287f9b3 --- /dev/null +++ b/docs/SeargeLatentMuxer3.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: SeargeLatentMuxer3 +- Category: Searge/_deprecated_/FlowControl +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeLatentMuxer3 是一个用于管理潜在数据流的节点,它通过选择三个提供的潜在输入中的一个来控制数据流向,这取决于输入选择器的值。此节点在需要条件路由的复杂网络中控制数据流向至关重要。 + +# Input types +## Required +- input0 + - 第一个潜在输入,节点可以选择并将其路由到输出。当输入选择器没有指示其他输入时,它在节点的决策过程中起着关键作用。 + - Comfy dtype: "LATENT" + - Python dtype: np.ndarray or a similar array type representing latent data +- input1 + - 节点的第二个潜在输入选项。当输入选择器设置为1时,它成为输出,相应地指导数据流。 + - Comfy dtype: "LATENT" + - Python dtype: np.ndarray or a similar array type representing latent data +- input2 + - 可以由节点选择的第三个潜在输入。当输入选择器的值为2时,它被选为输出,从而确定数据流路径。 + - Comfy dtype: "LATENT" + - Python dtype: np.ndarray or a similar array type representing latent data +- input_selector + - 这个整数参数决定选择哪个潜在输入作为输出。它在节点的操作中至关重要,因为它直接影响路由决策。 + - Comfy dtype: "INT" + - Python dtype: int + +# Output types +- output + - 节点的输出是基于输入选择器的值选择的潜在输入。这个输出携带着将通过网络继续传输的数据。 + - Comfy dtype: "LATENT" + - Python dtype: np.ndarray or a similar array type representing the selected latent data + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeLatentMuxer3: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input0': ('LATENT',), 'input1': ('LATENT',), 'input2': ('LATENT',), 'input_selector': ('INT', {'default': 0, 'min': 0, 'max': 2})}} + RETURN_TYPES = ('LATENT',) + RETURN_NAMES = ('output',) + FUNCTION = 'mux' + CATEGORY = 'Searge/_deprecated_/FlowControl' + + def mux(self, input0, input1, input2, input_selector): + if input_selector == 1: + return (input1,) + elif input_selector == 2: + return (input2,) + else: + return (input0,) +``` \ No newline at end of file diff --git a/docs/SeargeLoraLoader.md b/docs/SeargeLoraLoader.md new file mode 100644 index 0000000..4620c70 --- /dev/null +++ b/docs/SeargeLoraLoader.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: SeargeLoraLoader +- Category: Searge/_deprecated_/Files +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点便于加载和整合LORA(低秩适应)模型,这对于微调预训练模型以适应特定任务或数据集至关重要。它使用户能够通过调整LORA层和CLIP模型的影响来增强模型性能,从而为给定的数据集实现定制化的表示。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了LORA适应性调整的基础。它决定了在进行任何微调之前模型的初始理解和能力。 + - Comfy dtype: MODEL + - Python dtype: Any +- clip + - clip参数对于整个过程至关重要,它代表了将与LORA模型结合使用的CLIP模型组件,以产生协同效应,增强最终模型的整体表示和适应性。 + - Comfy dtype: CLIP + - Python dtype: Any +- lora_name + - lora_name参数指定了LORA层的身份,这对于区分各种LORA配置并在适应性过程中使用正确的层至关重要。 + - Comfy dtype: LORA_NAME + - Python dtype: str +- strength_model + - strength_model参数调整LORA层对整体模型的影响,允许对模型的表示进行微调,以更好地适应目标数据集的特定特征。 + - Comfy dtype: FLOAT + - Python dtype: float +- strength_clip + - strength_clip参数调节CLIP模型组件的影响,确保CLIP和LORA模型的结合针对期望的结果进行了优化。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- MODEL + - 输出模型代表了LORA和CLIP整合的成果,提供了一个增强和适应性的表示,准备好进行进一步的处理或评估。 + - Comfy dtype: MODEL + - Python dtype: Any +- CLIP + - 输出中的CLIP组件标志着与LORA模型的成功整合,确保模型具备了理解和基于目标数据集生成内容所需的能力。 + - Comfy dtype: CLIP + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeLoraLoader: + + def __init__(self): + self.lora_loader = nodes.LoraLoader() + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'lora_name': ('LORA_NAME',), 'strength_model': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'strength_clip': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01})}} + RETURN_TYPES = ('MODEL', 'CLIP') + FUNCTION = 'load_lora' + CATEGORY = 'Searge/_deprecated_/Files' + + def load_lora(self, model, clip, lora_name, strength_model, strength_clip): + return self.lora_loader.load_lora(model, clip, lora_name, strength_model, strength_clip) +``` \ No newline at end of file diff --git a/docs/SeargeLoras.md b/docs/SeargeLoras.md new file mode 100644 index 0000000..c6069bb --- /dev/null +++ b/docs/SeargeLoras.md @@ -0,0 +1,93 @@ +# Documentation +- Class name: SeargeLoras +- Category: UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点旨在处理和管理lora信号,将其强度和配置整合成结构化数据格式。 + +# Input types +## Required +- lora_1 + - 第一个lora参数对于定义lora栈中的初始信号至关重要,它影响节点的整体结构和输出。 + - Comfy dtype: LORAS_WITH_NONE() + - Python dtype: Union[str, None] +- lora_1_strength + - 第一个lora信号的强度非常重要,因为它决定了信号在栈中的影响力,对最终输出有贡献。 + - Comfy dtype: FLOAT + - Python dtype: float +- lora_2 + - 第二个lora参数进一步完善了信号栈,为节点的操作增加了额外的复杂性和细微差别。 + - Comfy dtype: LORAS_WITH_NONE() + - Python dtype: Union[str, None] +- lora_2_strength + - 第二个lora信号的强度至关重要,因为它调整了信号的相对权重,影响了节点的最终处理。 + - Comfy dtype: FLOAT + - Python dtype: float +- lora_3 + - 第三个lora参数有助于信号栈的多样性,增强了节点的适应性和多功能性。 + - Comfy dtype: LORAS_WITH_NONE() + - Python dtype: Union[str, None] +- lora_3_strength + - 第三个lora信号的强度很重要,因为它微调了信号对栈的贡献,细化了节点的输出。 + - Comfy dtype: FLOAT + - Python dtype: float +- lora_4 + - 第四个lora参数为信号栈增加了深度,影响了节点的综合分析和合成能力。 + - Comfy dtype: LORAS_WITH_NONE() + - Python dtype: Union[str, None] +- lora_4_strength + - 第四个lora信号的强度至关重要,因为它调整了信号在栈中的突出性,塑造了节点的整体性能。 + - Comfy dtype: FLOAT + - Python dtype: float +- lora_5 + - 第五个lora参数对信号栈是不可或缺的,提供了丰富的信息,增强了节点的处理能力。 + - Comfy dtype: LORAS_WITH_NONE() + - Python dtype: Union[str, None] +- lora_5_strength + - 第五个lora信号的强度很重要,因为它有助于微调信号在栈中的作用,影响节点的综合输出。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- data + - 输出数据流是节点处理的结果,封装了结构化的lora栈及其相关的强度。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeLoras: + + def __init__(self): + self.expected_lora_stack_size = None + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'lora_1': (UI.LORAS_WITH_NONE(),), 'lora_1_strength': ('FLOAT', {'default': 0.0, 'min': -10.0, 'max': 10.0, 'step': 0.05}), 'lora_2': (UI.LORAS_WITH_NONE(),), 'lora_2_strength': ('FLOAT', {'default': 0.0, 'min': -10.0, 'max': 10.0, 'step': 0.05}), 'lora_3': (UI.LORAS_WITH_NONE(),), 'lora_3_strength': ('FLOAT', {'default': 0.0, 'min': -10.0, 'max': 10.0, 'step': 0.05}), 'lora_4': (UI.LORAS_WITH_NONE(),), 'lora_4_strength': ('FLOAT', {'default': 0.0, 'min': -10.0, 'max': 10.0, 'step': 0.05}), 'lora_5': (UI.LORAS_WITH_NONE(),), 'lora_5_strength': ('FLOAT', {'default': 0.0, 'min': -10.0, 'max': 10.0, 'step': 0.05})}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(loras, lora_1, lora_1_strength, lora_2, lora_2_strength, lora_3, lora_3_strength, lora_4, lora_4_strength, lora_5, lora_5_strength): + loras += [{UI.F_LORA_NAME: lora_1, UI.F_LORA_STRENGTH: round(lora_1_strength, 3)}, {UI.F_LORA_NAME: lora_2, UI.F_LORA_STRENGTH: round(lora_2_strength, 3)}, {UI.F_LORA_NAME: lora_3, UI.F_LORA_STRENGTH: round(lora_3_strength, 3)}, {UI.F_LORA_NAME: lora_4, UI.F_LORA_STRENGTH: round(lora_4_strength, 3)}, {UI.F_LORA_NAME: lora_5, UI.F_LORA_STRENGTH: round(lora_5_strength, 3)}] + return {UI.F_LORA_STACK: loras} + + def get(self, lora_1, lora_1_strength, lora_2, lora_2_strength, lora_3, lora_3_strength, lora_4, lora_4_strength, lora_5, lora_5_strength, data=None): + if data is None: + data = {} + loras = retrieve_parameter(UI.F_LORA_STACK, retrieve_parameter(UI.S_LORAS, data), []) + if self.expected_lora_stack_size is None: + self.expected_lora_stack_size = len(loras) + elif self.expected_lora_stack_size == 0: + loras = [] + elif len(loras) > self.expected_lora_stack_size: + loras = loras[:self.expected_lora_stack_size] + data[UI.S_LORAS] = self.create_dict(loras, lora_1, lora_1_strength, lora_2, lora_2_strength, lora_3, lora_3_strength, lora_4, lora_4_strength, lora_5, lora_5_strength) + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeMagicBox.md b/docs/SeargeMagicBox.md new file mode 100644 index 0000000..9e6abf0 --- /dev/null +++ b/docs/SeargeMagicBox.md @@ -0,0 +1,196 @@ +# Documentation +- Class name: SeargeMagicBox +- Category: UI.CATEGORY_MAGIC +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点作为图像生成过程的中心协调器,根据用户输入和系统设置管理数据流和各个阶段的执行。它旨在处理涉及预处理、模型加载、条件设置、采样和后处理的复杂工作流,以产生高质量的图像,同时允许对生成过程进行广泛的定制和控制。 + +# Input types +## Required +- stage + - 阶段参数决定节点内要执行的特定操作。它是节点提供的各种功能的选择器,例如加载检查点、应用控制网或生成图像。阶段的选择直接影响输出和图像生成流水线中的后续步骤。 + - Comfy dtype: COMBO[STAGES] + - Python dtype: str +- input_from + - 该参数确定节点输入数据的来源。它可以是预定义的数据流或用户自定义输入。输入数据非常重要,因为它构成了所有后续处理的基础,并直接影响节点的最终输出。 + - Comfy dtype: COMBO[INPUT_OUTPUT] + - Python dtype: str +- output_to + - output_to参数指定节点输出应该指向的位置。它可以设置为自定义输出或进一步处理的数据流。这个参数在确定整个系统内部数据流方面至关重要,并影响节点操作结果的使用方式。 + - Comfy dtype: COMBO[INPUT_OUTPUT] + - Python dtype: str +## Optional +- data + - data参数是一个包含所有必要的信息和中间结果的字典,这些信息和结果在流水线的不同阶段之间传递。它作为数据流的支柱,确保所有阶段都能访问到处理所需的数据。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] +- custom_input + - 当节点提供自定义输入时,使用此参数。它允许注入外部数据或特定配置,这些不是标准数据流的一部分。custom_input参数提供了图像生成过程中的灵活性和适应性。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Output types +- data + - 节点的data输出包含图像生成过程的结果,包括任何处理过的图像、潜在表示和其他相关信息。这些数据用作流水线后续阶段的输入或可以保存为最终输出。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] +- custom_output + - 当input_from参数设置为自定义时,使用custom_output参数。它允许定制节点的输出以满足特定的用户需求或集成到更广泛的系统中。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeMagicBox: + NONE = 'none - skip' + PRE_PROCESS_DATA = 'pre-process data' + LOAD_CHECKPOINTS = 'load checkpoints' + APPLY_LORAS = 'apply loras' + PROMPT_STYLING = 'prompt styling' + CLIP_CONDITIONING = 'clip conditioning' + CLIP_MIXING = 'clip mixing' + APPLY_CONTROLNET = 'apply controlnet' + LATENT_INPUTS = 'latent inputs' + SAMPLING = 'sampling' + LATENT_DETAILER = 'latent detailer' + VAE_DECODE_SAMPLED = 'vae decode sampled' + HIGH_RESOLUTION = 'high resolution' + HIRES_DETAILER = 'hires detailer' + VAE_DECODE_HI_RES = 'vae decode hi-res' + UPSCALING = 'upscaling' + IMAGE_SAVING = 'image saving' + STAGES = [NONE, PRE_PROCESS_DATA, LOAD_CHECKPOINTS, APPLY_LORAS, PROMPT_STYLING, CLIP_CONDITIONING, CLIP_MIXING, APPLY_CONTROLNET, LATENT_INPUTS, SAMPLING, LATENT_DETAILER, VAE_DECODE_SAMPLED, HIGH_RESOLUTION, HIRES_DETAILER, VAE_DECODE_HI_RES, UPSCALING, IMAGE_SAVING] + DATA = 'data stream' + CUSTOM_AND_DATA = 'custom stage & data stream' + INPUT_OUTPUT = [DATA, CUSTOM_AND_DATA] + + def __init__(self): + self.stage_pre_process_data = None + self.stage_load_checkpoints = None + self.stage_apply_loras = None + self.stage_prompt_styling = None + self.stage_clip_conditioning = None + self.stage_clip_mixing = None + self.stage_latent_inputs = None + self.stage_apply_controlnet = None + self.stage_sampling = None + self.stage_vae_decode_sampled = None + self.stage_latent_detailer = None + self.stage_high_resolution = None + self.stage_hires_detailer = None + self.stage_vae_decode_hi_res = None + self.stage_upscaling = None + self.stage_image_saving = None + self.stage_ = None + + @classmethod + def INPUT_TYPES(s): + return {'required': {'stage': (s.STAGES, {'default': s.NONE}), 'input_from': (s.INPUT_OUTPUT,), 'output_to': (s.INPUT_OUTPUT,)}, 'optional': {'data': ('SRG_DATA_STREAM',), 'custom_input': ('SRG_STAGE_INPUT',)}} + RETURN_TYPES = ('SRG_DATA_STREAM', 'SRG_STAGE_OUTPUT') + RETURN_NAMES = ('data', 'custom_output') + FUNCTION = 'process' + CATEGORY = UI.CATEGORY_MAGIC + + def run_stage(self, stage, data, stage_input=None): + stage_processor = None + has_data = data is not None + stage_output = stage_input + if has_data: + data['stage_output'] = None + if stage == self.NONE: + pass + elif stage == self.PRE_PROCESS_DATA: + if self.stage_pre_process_data is None: + self.stage_pre_process_data = SeargePreProcessData() + stage_processor = self.stage_pre_process_data + elif stage == self.LOAD_CHECKPOINTS: + if self.stage_load_checkpoints is None: + self.stage_load_checkpoints = SeargeStageLoadCheckpoints() + stage_processor = self.stage_load_checkpoints + elif stage == self.APPLY_LORAS: + if self.stage_apply_loras is None: + self.stage_apply_loras = SeargeStageApplyLoras() + stage_processor = self.stage_apply_loras + elif stage == self.PROMPT_STYLING: + if self.stage_prompt_styling is None: + self.stage_prompt_styling = SeargeStage() + stage_processor = self.stage_prompt_styling + elif stage == self.CLIP_CONDITIONING: + if self.stage_clip_conditioning is None: + self.stage_clip_conditioning = SeargeStageClipConditioning() + stage_processor = self.stage_clip_conditioning + elif stage == self.CLIP_MIXING: + if self.stage_clip_mixing is None: + self.stage_clip_mixing = SeargeStage() + stage_processor = self.stage_clip_mixing + elif stage == self.APPLY_CONTROLNET: + if self.stage_apply_controlnet is None: + self.stage_apply_controlnet = SeargeStageApplyControlnet() + stage_processor = self.stage_apply_controlnet + elif stage == self.LATENT_INPUTS: + if self.stage_latent_inputs is None: + self.stage_latent_inputs = SeargeStageLatentInputs() + stage_processor = self.stage_latent_inputs + elif stage == self.SAMPLING: + if self.stage_sampling is None: + self.stage_sampling = SeargeStageSampling() + stage_processor = self.stage_sampling + elif stage == self.LATENT_DETAILER: + if self.stage_latent_detailer is None: + self.stage_latent_detailer = SeargeStageLatentDetailer() + stage_processor = self.stage_latent_detailer + elif stage == self.VAE_DECODE_SAMPLED: + if self.stage_vae_decode_sampled is None: + self.stage_vae_decode_sampled = SeargeStageVAEDecodeSampled() + stage_processor = self.stage_vae_decode_sampled + elif stage == self.HIGH_RESOLUTION: + if self.stage_high_resolution is None: + self.stage_high_resolution = SeargeStageHighResolution() + stage_processor = self.stage_high_resolution + elif stage == self.HIRES_DETAILER: + if self.stage_hires_detailer is None: + self.stage_hires_detailer = SeargeStageHiresDetailer() + stage_processor = self.stage_hires_detailer + elif stage == self.VAE_DECODE_HI_RES: + if self.stage_vae_decode_hi_res is None: + self.stage_vae_decode_hi_res = SeargeStageVAEDecodeHires() + stage_processor = self.stage_vae_decode_hi_res + elif stage == self.UPSCALING: + if self.stage_upscaling is None: + self.stage_upscaling = SeargeStageUpscaling() + stage_processor = self.stage_upscaling + elif stage == self.IMAGE_SAVING: + if self.stage_image_saving is None: + self.stage_image_saving = SeargeStageImageSaving() + stage_processor = self.stage_image_saving + else: + print('WARNING: implementation for stage ' + stage + ' is missing!') + if stage_processor is None: + return (data, None) + stage_input = stage_processor.get_input(data, stage_output) + stage_result = None + if stage_input is not None: + (data, stage_result) = stage_processor.process(data, stage_input) + if has_data: + data['stage_output'] = stage_result + return (data, stage_result) + + def process(self, stage, input_from, output_to, data=None, custom_input=None): + if data is None: + data = {} + stage_input = None + custom_output = None + if input_from == self.CUSTOM_AND_DATA: + stage_input = custom_input + if PipelineAccess(data).is_pipeline_enabled(): + (data, stage_result) = self.run_stage(stage, data, stage_input) + else: + stage_result = None + if output_to == self.CUSTOM_AND_DATA: + custom_output = stage_result + return (data, custom_output) +``` \ No newline at end of file diff --git a/docs/SeargeModelSelector.md b/docs/SeargeModelSelector.md new file mode 100644 index 0000000..2bec20d --- /dev/null +++ b/docs/SeargeModelSelector.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: SeargeModelSelector +- Category: UI.CATEGORY_UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeModelSelector节点简化了选择和组合模型检查点以进行进一步处理的过程。它封装了处理各种检查点类型的复杂性,使用户能够专注于模型的分析和应用,而无需担心底层的技术细节。 + +# Input types +## Required +- base_checkpoint + - base_checkpoint参数至关重要,因为它指定了作为后续操作起点的基础模型检查点。其选择影响下游任务的整体性能和准确性。 + - Comfy dtype: UI.CHECKPOINTS() + - Python dtype: Union[str, None] +- refiner_checkpoint + - refiner_checkpoint参数对于提升基础模型的性能至关重要。它引入了完善模型预测的可能性,从而提高了最终输出的质量。 + - Comfy dtype: UI.CHECKPOINTS_WITH_NONE() + - Python dtype: Union[str, None] +- vae_checkpoint + - vae_checkpoint参数在工作流程中整合变分自编码器方面起着关键作用。它使得能够整合潜在表示,这对于复杂的数据处理任务可能至关重要。 + - Comfy dtype: UI.VAE_WITH_EMBEDDED() + - Python dtype: List[str] +## Optional +- data + - data参数作为模型选择过程中可能需要的附加信息的容器。它在确保节点有效和高效运行中起着支持作用。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Output types +- data + - 输出的data参数包含了模型选择过程的结果,包括组合的检查点。它是工作流程中进入后续阶段的关键组成部分,促进了进一步的分析和应用。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeModelSelector: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'base_checkpoint': (UI.CHECKPOINTS(),), 'refiner_checkpoint': (UI.CHECKPOINTS_WITH_NONE(),), 'vae_checkpoint': (UI.VAE_WITH_EMBEDDED(),)}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(base_checkpoint, refiner_checkpoint, vae_checkpoint): + return {UI.F_BASE_CHECKPOINT: base_checkpoint, UI.F_REFINER_CHECKPOINT: refiner_checkpoint, UI.F_VAE_CHECKPOINT: vae_checkpoint} + + def get(self, base_checkpoint, refiner_checkpoint, vae_checkpoint, data=None): + if data is None: + data = {} + data[UI.S_CHECKPOINTS] = self.create_dict(base_checkpoint, refiner_checkpoint, vae_checkpoint) + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeOperatingMode.md b/docs/SeargeOperatingMode.md new file mode 100644 index 0000000..511e381 --- /dev/null +++ b/docs/SeargeOperatingMode.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: SeargeOperatingMode +- Category: UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点类封装了搜索和生成(SRG)工作流的操作设置,允许定制工作流模式和提示策略。 + +# Input types +## Required +- workflow_mode + - 决定工作流的操作模式,这可以显著影响生成的输出类型和过程的整体效率。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- prompting_mode + - 设置引导生成过程的提示模式,影响结果的创造性和相关性。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- batch_size + - 指定在单个操作中处理的输入数量,这会影响系统的吞吐量和资源利用率。 + - Comfy dtype: int + - Python dtype: int +## Optional +- data + - 一个可选的数据流,可用于为工作流提供额外的上下文或信息。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Output types +- data + - 包含应用了操作模式设置的更新后的数据流,这对于工作流中后续步骤至关重要。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeOperatingMode: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'workflow_mode': (UI.WORKFLOW_MODES, {'default': UI.WF_MODE_TEXT_TO_IMAGE}), 'prompting_mode': (UI.PROMPTING_MODES, {'default': UI.PROMPTING_DEFAULT}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 4, 'step': 1})}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(workflow_mode, prompting_mode, batch_size): + return {UI.F_WORKFLOW_MODE: workflow_mode, UI.F_PROMPTING_MODE: prompting_mode, UI.F_BATCH_SIZE: batch_size} + + def get(self, workflow_mode, prompting_mode, batch_size, data=None): + if data is None: + data = {} + data[UI.S_OPERATING_MODE] = self.create_dict(workflow_mode, prompting_mode, batch_size) + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeOutput1.md b/docs/SeargeOutput1.md new file mode 100644 index 0000000..7314232 --- /dev/null +++ b/docs/SeargeOutput1.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: SeargeOutput1 +- Category: Searge/_deprecated_/UI/Outputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点类作为一个接口,用于将输入参数解复用为不同的输出,便于系统内部数据的组织和流动。 + +# Input types +## Required +- parameters + - 参数输入对于节点的操作至关重要,它包含了节点操作所需的各种提示和图像。它是解复用过程的主要信息来源。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Output types +- parameters + - 输出'parameters'是输入的反映,标志着通过节点的数据完整性。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] +- main_prompt + - 输出'main_prompt'代表指导系统内部后续处理或内容生成的主要文本输入。 + - Comfy dtype: String + - Python dtype: str +- secondary_prompt + - 此输出提供补充的文本内容,以丰富用于系统进一步操作的数据。 + - Comfy dtype: String + - Python dtype: str +- style_prompt + - 输出'style_prompt'用于定义应纳入系统处理或生成的风格元素或主题。 + - Comfy dtype: String + - Python dtype: str +- negative_prompt + - 此输出包含系统在处理或内容生成过程中应避免或排除的信息。 + - Comfy dtype: String + - Python dtype: str +- negative_style + - 输出'negative_style'指定系统在生成内容时应有意识避免的风格元素或主题。 + - Comfy dtype: String + - Python dtype: str +- image + - 输出'image'是一个视觉元素,可以作为输入提供或在系统内部生成,影响后续的视觉处理或内容创建。 + - Comfy dtype: Image + - Python dtype: PIL.Image +- mask + - 输出'mask'是一个二进制或多类别的数组,它指示在处理过程中哪些部分的图像或内容应该被操作或保护。 + - Comfy dtype: Mask + - Python dtype: numpy.ndarray + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeOutput1: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'parameters': ('PARAMETERS',)}} + RETURN_TYPES = ('PARAMETERS', 'STRING', 'STRING', 'STRING', 'STRING', 'STRING', 'IMAGE', 'MASK') + RETURN_NAMES = ('parameters', 'main_prompt', 'secondary_prompt', 'style_prompt', 'negative_prompt', 'negative_style', 'image', 'mask') + FUNCTION = 'demux' + CATEGORY = 'Searge/_deprecated_/UI/Outputs' + + def demux(self, parameters): + main_prompt = parameters['main_prompt'] + secondary_prompt = parameters['secondary_prompt'] + style_prompt = parameters['style_prompt'] + negative_prompt = parameters['negative_prompt'] + negative_style = parameters['negative_style'] + image = parameters['image'] + mask = parameters['mask'] + return (parameters, main_prompt, secondary_prompt, style_prompt, negative_prompt, negative_style, image, mask) +``` \ No newline at end of file diff --git a/docs/SeargeOutput2.md b/docs/SeargeOutput2.md new file mode 100644 index 0000000..181c8a8 --- /dev/null +++ b/docs/SeargeOutput2.md @@ -0,0 +1,84 @@ +# Documentation +- Class name: SeargeOutput2 +- Category: Searge/_deprecated_/UI/Outputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点旨在处理并解复用输入参数,将它们分配给特定的输出,以满足各种后处理和分析任务。 + +# Input types +## Required +- parameters + - 该参数是一个包含节点操作所需所有输入的字典。它至关重要,因为它决定了节点的行为和它处理的数据。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Output types +- parameters + - 原始输入参数被传递,作为后续操作的基础。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] +- seed + - 种子值对于确保输出生成过程的可重复性至关重要。 + - Comfy dtype: Int + - Python dtype: int +- image_width + - 此输出定义了生成图像的宽度,这对于图像处理和显示目的至关重要。 + - Comfy dtype: Int + - Python dtype: int +- image_height + - 此输出指定了图像的高度,这是确定图像尺寸和布局的关键因素。 + - Comfy dtype: Int + - Python dtype: int +- steps + - 步骤数输出指示过程的序列或进展,这可能会影响操作的复杂性和持续时间。 + - Comfy dtype: Int + - Python dtype: int +- cfg + - 配置参数保存对调整节点行为和输出特征至关重要的设置。 + - Comfy dtype: Float + - Python dtype: float +- sampler_name + - 采样器名称是一个字符串,用于识别使用的特定采样方法,这对于结果的准确性和多样性很重要。 + - Comfy dtype: Str + - Python dtype: str +- scheduler + - 调度器名称输出提供有关调度方法的信息,这对于资源管理和时间安排至关重要。 + - Comfy dtype: Str + - Python dtype: str +- save_image + - 这个布尔输出决定了是否保存图像,这对于保存操作结果具有重要意义。 + - Comfy dtype: Bool + - Python dtype: bool +- save_directory + - 保存目录输出指定了结果将被存储的位置,这对于组织和访问输出数据至关重要。 + - Comfy dtype: Str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeOutput2: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'parameters': ('PARAMETERS',)}} + RETURN_TYPES = ('PARAMETERS', 'INT', 'INT', 'INT', 'INT', 'FLOAT', 'SAMPLER_NAME', 'SCHEDULER_NAME', 'ENABLE_STATE', 'SAVE_FOLDER') + RETURN_NAMES = ('parameters', 'seed', 'image_width', 'image_height', 'steps', 'cfg', 'sampler_name', 'scheduler', 'save_image', 'save_directory') + FUNCTION = 'demux' + CATEGORY = 'Searge/_deprecated_/UI/Outputs' + + def demux(self, parameters): + seed = parameters['seed'] + image_width = parameters['image_width'] + image_height = parameters['image_height'] + steps = parameters['steps'] + cfg = parameters['cfg'] + sampler_name = parameters['sampler_name'] + scheduler = parameters['scheduler'] + save_image = parameters['save_image'] + save_directory = parameters['save_directory'] + return (parameters, seed, image_width, image_height, steps, cfg, sampler_name, scheduler, save_image, save_directory) +``` \ No newline at end of file diff --git a/docs/SeargeOutput3.md b/docs/SeargeOutput3.md new file mode 100644 index 0000000..09a8925 --- /dev/null +++ b/docs/SeargeOutput3.md @@ -0,0 +1,79 @@ +# Documentation +- Class name: SeargeOutput3 +- Category: Searge/_deprecated_/UI/Outputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点类封装了将一组参数分解为各个独立组件的逻辑,便于在系统内进行进一步的处理和分析。 + +# Input types +## Required +- parameters + - 该参数作为关键输入,包含一个包含各种设置的字典,这些设置决定了节点的行为和输出。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Output types +- parameters + - 原始的参数集被传递,保持了输入数据的完整性。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] +- denoise + - 该输出代表了一个去噪设置,这对于图像质量提升过程至关重要。 + - Comfy dtype: Float + - Python dtype: float +- base_ratio + - 基础比例输出用于控制图像缩放的基础方面,确保比例和一致性。 + - Comfy dtype: Float + - Python dtype: float +- refiner_strength + - 细化强度是一个输出,影响图像细节的微调过程,旨在优化清晰度和锐度。 + - Comfy dtype: Float + - Python dtype: float +- noise_offset + - 噪声偏移输出对于调整图像中的噪声水平至关重要,有助于提高整体视觉质量。 + - Comfy dtype: Float + - Python dtype: float +- precondition_steps + - 该输出定义了要执行的预处理步骤的数量,这是图像处理流水线准备阶段的重要组成部分。 + - Comfy dtype: Int + - Python dtype: int +- batch_size + - 批处理大小输出决定了同时处理的图像数量,影响系统的效率和吞吐量。 + - Comfy dtype: Int + - Python dtype: int +- upscale_resolution_factor + - 该输出负责定义应用于图像分辨率的缩放因子,这是实现期望输出尺寸的关键因素。 + - Comfy dtype: Float + - Python dtype: float +- save_upscaled_image + - 保存放大图像输出是一个标志,用于确定是否应保存处理后的图像,影响数据持久性。 + - Comfy dtype: Bool + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeOutput3: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'parameters': ('PARAMETERS',)}} + RETURN_TYPES = ('PARAMETERS', 'FLOAT', 'FLOAT', 'FLOAT', 'INT', 'INT', 'INT', 'FLOAT', 'ENABLE_STATE') + RETURN_NAMES = ('parameters', 'denoise', 'base_ratio', 'refiner_strength', 'noise_offset', 'precondition_steps', 'batch_size', 'upscale_resolution_factor', 'save_upscaled_image') + FUNCTION = 'demux' + CATEGORY = 'Searge/_deprecated_/UI/Outputs' + + def demux(self, parameters): + denoise = parameters['denoise'] + base_ratio = parameters['base_ratio'] + refiner_strength = parameters['refiner_strength'] + noise_offset = parameters['noise_offset'] + precondition_steps = parameters['precondition_steps'] + batch_size = parameters['batch_size'] + upscale_resolution_factor = parameters['upscale_resolution_factor'] + save_upscaled_image = parameters['save_upscaled_image'] + return (parameters, denoise, base_ratio, refiner_strength, noise_offset, precondition_steps, batch_size, upscale_resolution_factor, save_upscaled_image) +``` \ No newline at end of file diff --git a/docs/SeargeOutput4.md b/docs/SeargeOutput4.md new file mode 100644 index 0000000..e3bd452 --- /dev/null +++ b/docs/SeargeOutput4.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: SeargeOutput4 +- Category: Searge/_deprecated_/UI/Outputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点旨在便于在复杂系统中分离和识别各种模型组件。它接收结构化的模型名称输入,并将其解构,提供对每种模型类型的单独访问,从而增强输出数据的模块化和组织性。 + +# Input types +## Required +- model_names + - 该参数至关重要,因为它包含了节点操作所需的所有模型名称。它是一个复合结构,包含不同模型的名称,每个模型在系统中扮演不同的角色。 + - Comfy dtype: COMBO[{'base_model': str, 'refiner_model': str, 'vae_model': str, 'main_upscale_model': str, 'support_upscale_model': str, 'lora_model': str}] + - Python dtype: Dict[str, str] + +# Output types +- model_names + - 输出保持了输入的结构化格式,提供了模型名称的清晰和有组织的表示。这便于系统中其他组件进行进一步的处理和分析。 + - Comfy dtype: COMBO[{'base_model': str, 'refiner_model': str, 'vae_model': str, 'main_upscale_model': str, 'support_upscale_model': str, 'lora_model': str}] + - Python dtype: Dict[str, str] +- base_model + - 此输出代表系统中的基础模型,它为其他模型和过程提供基础。识别它对于理解所涉及模型的结构和层次至关重要。 + - Comfy dtype: str + - Python dtype: str +- refiner_model + - 精炼模型输出表明了一个旨在增强或改进基础模型输出的模型。它在提高系统结果的整体准确性和质量方面发挥着关键作用。 + - Comfy dtype: str + - Python dtype: str +- vae_model + - 此输出指定了变分自编码器(VAE)模型,它在学习生成新的数据表示方面发挥着重要作用。它是涉及数据生成和特征提取任务的关键组件。 + - Comfy dtype: str + - Python dtype: str +- main_upscale_model + - 主要放大模型输出指的是负责提高数据分辨率的主要模型。它对于在图像处理任务中提高输出的视觉质量和细节至关重要。 + - Comfy dtype: str + - Python dtype: str +- support_upscale_model + - 此输出代表一个支持模型,辅助放大过程,为主放大模型提供补充。它有助于提高放大任务的整体效果和效率。 + - Comfy dtype: str + - Python dtype: str +- lora_model + - LoRA(低秩适应)模型输出与一种有效适应预训练模型到新任务的技术相关。它因其能够在最小的计算开销下提高模型性能而具有重要意义。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeOutput4: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model_names': ('MODEL_NAMES',)}} + RETURN_TYPES = ('MODEL_NAMES', 'CHECKPOINT_NAME', 'CHECKPOINT_NAME', 'VAE_NAME', 'UPSCALER_NAME', 'UPSCALER_NAME', 'LORA_NAME') + RETURN_NAMES = ('model_names', 'base_model', 'refiner_model', 'vae_model', 'main_upscale_model', 'support_upscale_model', 'lora_model') + FUNCTION = 'demux' + CATEGORY = 'Searge/_deprecated_/UI/Outputs' + + def demux(self, model_names): + base_model = model_names['base_model'] + refiner_model = model_names['refiner_model'] + vae_model = model_names['vae_model'] + main_upscale_model = model_names['main_upscale_model'] + support_upscale_model = model_names['support_upscale_model'] + lora_model = model_names['lora_model'] + return (model_names, base_model, refiner_model, vae_model, main_upscale_model, support_upscale_model, lora_model) +``` \ No newline at end of file diff --git a/docs/SeargeOutput5.md b/docs/SeargeOutput5.md new file mode 100644 index 0000000..57c74cd --- /dev/null +++ b/docs/SeargeOutput5.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: SeargeOutput5 +- Category: Searge/_deprecated_/UI/Outputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点将输入参数分类并分离成不同的输出,便于系统内部数据的组织和流动。 + +# Input types +## Required +- parameters + - 该参数作为一组综合设置,指导节点的操作。它对节点正确运行和产生有意义的结果至关重要。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Output types +- parameters + - 提供的原始参数集,保持不变。此输出保持输入数据的完整性以供进一步使用。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] +- base_conditioning_scale + - 该输出代表基础条件的缩放因子,对于调整基础输入在整个过程中的影响至关重要。 + - Comfy dtype: float + - Python dtype: float +- refiner_conditioning_scale + - 该输出是精炼条件的缩放因子,它在根据输入参数微调输出方面发挥关键作用。 + - Comfy dtype: float + - Python dtype: float +- style_prompt_power + - 该输出表示风格提示的功率级别,它在决定最终结果的风格影响方面非常重要。 + - Comfy dtype: float + - Python dtype: float +- negative_style_power + - 该输出代表风格提示的负面功率级别,它在控制输出中不希望出现的风格元素方面很重要。 + - Comfy dtype: float + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeOutput5: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'parameters': ('PARAMETERS',)}} + RETURN_TYPES = ('PARAMETERS', 'FLOAT', 'FLOAT', 'FLOAT', 'FLOAT') + RETURN_NAMES = ('parameters', 'base_conditioning_scale', 'refiner_conditioning_scale', 'style_prompt_power', 'negative_style_power') + FUNCTION = 'demux' + CATEGORY = 'Searge/_deprecated_/UI/Outputs' + + def demux(self, parameters): + base_conditioning_scale = parameters['base_conditioning_scale'] + refiner_conditioning_scale = parameters['refiner_conditioning_scale'] + style_prompt_power = parameters['style_prompt_power'] + negative_style_power = parameters['negative_style_power'] + return (parameters, base_conditioning_scale, refiner_conditioning_scale, style_prompt_power, negative_style_power) +``` \ No newline at end of file diff --git a/docs/SeargeOutput6.md b/docs/SeargeOutput6.md new file mode 100644 index 0000000..c35c1ba --- /dev/null +++ b/docs/SeargeOutput6.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: SeargeOutput6 +- Category: Searge/_deprecated_/UI/Outputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeOutput6节点旨在促进解复用过程,允许从给定输入中提取和组织各种参数。它在简化数据处理中发挥着关键作用,确保参数被有效分离并为后续处理阶段提供便利。 + +# Input types +## Required +- parameters + - “parameters”输入是SeargeOutput6节点的核心,包含解复用操作所需的基本数据。它对节点的执行至关重要,因为它决定了后续步骤和结果。 + - Comfy dtype: Dict[str, Union[str, int, float, bool]] + - Python dtype: Dict[str, Union[str, int, float, bool]] + +# Output types +- parameters + - “parameters”输出保留了结构化数据格式,为进一步使用提供了清晰且有组织的数据展示。 + - Comfy dtype: Dict[str, Union[str, int, float, bool]] + - Python dtype: Dict[str, Union[str, int, float, bool]] +- hrf_steps + - “hrf_steps”输出表示高分辨率修复过程中涉及的步骤数,这对于控制输出的细节水平很重要。 + - Comfy dtype: int + - Python dtype: int +- hrf_denoise + - “hrf_denoise”输出表示应用于高分辨率修复的去噪水平,影响最终结果的清晰度和质量。 + - Comfy dtype: float + - Python dtype: float +- hrf_upscale_factor + - “hrf_upscale_factor”输出代表上采样过程中使用的缩放因子,这对于确定上采样图像的分辨率至关重要。 + - Comfy dtype: float + - Python dtype: float +- hrf_noise_offset + - “hrf_noise_offset”输出表示噪声偏移水平,这是微调图像处理中噪声特性的关键参数。 + - Comfy dtype: int + - Python dtype: int +- hrf_seed + - “hrf_seed”输出是用于随机数生成的种子值,确保处理流程中的可重复性和一致性。 + - Comfy dtype: int + - Python dtype: int +- hires_fix + - “hires_fix”输出是一个布尔标志,指示是否已应用高分辨率修复过程以提高图像质量。 + - Comfy dtype: bool + - Python dtype: bool +- hrf_smoothness + - “hrf_smoothness”输出控制高分辨率修复的平滑度,在最终上采样图像的外观中起着关键作用。 + - Comfy dtype: float + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeOutput6: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'parameters': ('PARAMETERS',)}} + RETURN_TYPES = ('PARAMETERS', 'INT', 'FLOAT', 'FLOAT', 'INT', 'INT', 'ENABLE_STATE', 'FLOAT') + RETURN_NAMES = ('parameters', 'hrf_steps', 'hrf_denoise', 'hrf_upscale_factor', 'hrf_noise_offset', 'hrf_seed', 'hires_fix', 'hrf_smoothness') + FUNCTION = 'demux' + CATEGORY = 'Searge/_deprecated_/UI/Outputs' + + def demux(self, parameters): + hrf_steps = parameters['hrf_steps'] + hrf_denoise = parameters['hrf_denoise'] + hrf_upscale_factor = parameters['hrf_upscale_factor'] + hrf_noise_offset = parameters['hrf_noise_offset'] + hrf_seed = parameters['hrf_seed'] + hires_fix = parameters['hires_fix'] + hrf_smoothness = parameters['hrf_smoothness'] + return (parameters, hrf_steps, hrf_denoise, hrf_upscale_factor, hrf_noise_offset, hrf_seed, hires_fix, hrf_smoothness) +``` \ No newline at end of file diff --git a/docs/SeargeOutput7.md b/docs/SeargeOutput7.md new file mode 100644 index 0000000..16322d3 --- /dev/null +++ b/docs/SeargeOutput7.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: SeargeOutput7 +- Category: Searge/_deprecated_/UI/Outputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点作为数据解复用接口,将输入数据分离成不同的流以进行进一步处理。它旨在通过组织和优先处理数据流来增强工作流程,确保特定的数据属性得到它们所需的适当关注。 + +# Input types +## Required +- parameters + - 该参数至关重要,因为它包含了节点将要解复用的数据,允许根据预定义的结构分离不同的属性。 + - Comfy dtype: COMBO[{"type": "dict", "schema": {"lora_strength": "float"}}] + - Python dtype: Dict[str, float] + +# Output types +- parameters + - 输出保留了输入数据的原始结构,确保解复用后的数据有组织且易于后续操作访问。 + - Comfy dtype: dict + - Python dtype: Dict[str, Any] +- lora_strength + - 此输出代表从输入数据中解复用出的特定属性,突出了它在数据处理工作流中的重要性。 + - Comfy dtype: float + - Python dtype: float + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeOutput7: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'parameters': ('PARAMETERS',)}} + RETURN_TYPES = ('PARAMETERS', 'FLOAT') + RETURN_NAMES = ('parameters', 'lora_strength') + FUNCTION = 'demux' + CATEGORY = 'Searge/_deprecated_/UI/Outputs' + + def demux(self, parameters): + lora_strength = parameters['lora_strength'] + return (parameters, lora_strength) +``` \ No newline at end of file diff --git a/docs/SeargeParameterProcessor.md b/docs/SeargeParameterProcessor.md new file mode 100644 index 0000000..dd57c4c --- /dev/null +++ b/docs/SeargeParameterProcessor.md @@ -0,0 +1,142 @@ +# Documentation +- Class name: SeargeParameterProcessor +- Category: Searge/_deprecated_/UI +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点旨在处理和优化图像生成任务的输入参数,确保参数正确配置以实现期望的输出质量和风格。 + +# Input types +## Required +- inputs + - 输入参数至关重要,因为它提供了节点将处理和优化的初始参数集。它直接影响节点的操作和最终输出。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Output types +- parameters + - 输出参数代表了处理过并优化的参数集,现在可以准备在图像生成过程的后续阶段使用。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeParameterProcessor: + REFINER_INTENSITY = ['hard', 'soft'] + HRF_SEED_OFFSET = ['same', 'distinct'] + STATES = ['disabled', 'enabled'] + OPERATION_MODE = ['text to image', 'image to image', 'inpainting'] + PROMPT_STYLE = ['simple', '3 prompts G+L-N', 'subject focus', 'style focus', 'weighted', 'overlay', 'subject - style', 'style - subject', 'style only', 'weighted - overlay', 'overlay - weighted'] + STYLE_TEMPLATE = ['none', 'from preprocessor', 'test'] + SAVE_TO = ['output folder', 'input folder'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'inputs': ('PARAMETER_INPUTS',)}} + RETURN_TYPES = ('PARAMETERS',) + RETURN_NAMES = ('parameters',) + FUNCTION = 'process' + CATEGORY = 'Searge/_deprecated_/UI' + + def process(self, inputs): + if inputs is None: + parameters = {} + else: + parameters = inputs + if parameters['denoise'] is None: + parameters['denoise'] = 1.0 + saturation = parameters['refiner_intensity'] + if saturation is not None: + if saturation == SeargeParameterProcessor.REFINER_INTENSITY[1]: + parameters['noise_offset'] = 1 + else: + parameters['noise_offset'] = 0 + hires_fix = parameters['hires_fix'] + if hires_fix is not None and hires_fix == SeargeParameterProcessor.STATES[0]: + parameters['hrf_steps'] = 0 + hrf_saturation = parameters['hrf_intensity'] + if hrf_saturation is not None: + if hrf_saturation == SeargeParameterProcessor.REFINER_INTENSITY[1]: + parameters['hrf_noise_offset'] = 1 + else: + parameters['hrf_noise_offset'] = 0 + seed_offset = parameters['hrf_seed_offset'] + if seed_offset is not None: + seed = parameters['seed'] if parameters['seed'] is not None else 0 + if seed_offset == SeargeParameterProcessor.HRF_SEED_OFFSET[1]: + parameters['hrf_seed'] = seed + 3 + else: + parameters['hrf_seed'] = seed + style_template = parameters['style_template'] + if style_template is not None: + if style_template == SeargeParameterProcessor.STYLE_TEMPLATE[1]: + pass + if style_template == SeargeParameterProcessor.STYLE_TEMPLATE[2]: + if parameters['noise_offset'] is not None: + parameters['noise_offset'] = 1 - parameters['hrf_noise_offset'] + if parameters['hrf_noise_offset'] is not None: + parameters['hrf_noise_offset'] = 1 - parameters['hrf_noise_offset'] + else: + pass + operation_mode = parameters['operation_mode'] + if operation_mode is not None: + if operation_mode == SeargeParameterProcessor.OPERATION_MODE[1]: + parameters['operation_selector'] = 1 + elif operation_mode == SeargeParameterProcessor.OPERATION_MODE[2]: + parameters['operation_selector'] = 2 + else: + parameters['operation_selector'] = 0 + parameters['denoise'] = 1.0 + prompt_style = parameters['prompt_style'] + if prompt_style is not None: + if prompt_style == SeargeParameterProcessor.PROMPT_STYLE[0]: + parameters['prompt_style_selector'] = 0 + parameters['prompt_style_group'] = 0 + main_prompt = parameters['main_prompt'] + parameters['secondary_prompt'] = main_prompt + parameters['style_prompt'] = '' + parameters['negative_style'] = '' + elif prompt_style == SeargeParameterProcessor.PROMPT_STYLE[2]: + parameters['prompt_style_selector'] = 1 + parameters['prompt_style_group'] = 0 + elif prompt_style == SeargeParameterProcessor.PROMPT_STYLE[3]: + parameters['prompt_style_selector'] = 2 + parameters['prompt_style_group'] = 0 + elif prompt_style == SeargeParameterProcessor.PROMPT_STYLE[4]: + parameters['prompt_style_selector'] = 3 + parameters['prompt_style_group'] = 0 + elif prompt_style == SeargeParameterProcessor.PROMPT_STYLE[5]: + parameters['prompt_style_selector'] = 4 + parameters['prompt_style_group'] = 0 + elif prompt_style == SeargeParameterProcessor.PROMPT_STYLE[6]: + parameters['prompt_style_selector'] = 0 + parameters['prompt_style_group'] = 1 + elif prompt_style == SeargeParameterProcessor.PROMPT_STYLE[7]: + parameters['prompt_style_selector'] = 1 + parameters['prompt_style_group'] = 1 + elif prompt_style == SeargeParameterProcessor.PROMPT_STYLE[8]: + parameters['prompt_style_selector'] = 2 + parameters['prompt_style_group'] = 1 + elif prompt_style == SeargeParameterProcessor.PROMPT_STYLE[9]: + parameters['prompt_style_selector'] = 3 + parameters['prompt_style_group'] = 1 + elif prompt_style == SeargeParameterProcessor.PROMPT_STYLE[10]: + parameters['prompt_style_selector'] = 4 + parameters['prompt_style_group'] = 1 + else: + parameters['prompt_style_selector'] = 0 + parameters['prompt_style_group'] = 0 + parameters['style_prompt'] = '' + parameters['negative_style'] = '' + save_image = parameters['save_image'] + if save_image is not None: + if save_image == SeargeParameterProcessor.STATES[0]: + parameters['save_upscaled_image'] = SeargeParameterProcessor.STATES[0] + parameters['hires_fix'] = SeargeParameterProcessor.STATES[0] + elif parameters['save_directory'] == SeargeParameterProcessor.SAVE_TO[1]: + parameters['hires_fix'] = SeargeParameterProcessor.STATES[1] + return (parameters,) +``` \ No newline at end of file diff --git a/docs/SeargePipelineStart.md b/docs/SeargePipelineStart.md new file mode 100644 index 0000000..346a847 --- /dev/null +++ b/docs/SeargePipelineStart.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: SeargePipelineStart +- Category: UI.CATEGORY_MAGIC +- Output node: True +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargePipelineStart 节点是数据处理流水线的起点。它负责使用给定的工作流版本和可选的数据流初始化流水线。该节点确保在开始处理之前,流水线已正确设置并配置了正确的设置和配置。 + +# Input types +## Required +- wf_version + - wf_version 参数指定流水线要使用的流程版本。这对于确定流水线将执行的正确设置和操作至关重要。 + - Comfy dtype: str + - Python dtype: str +- data + - data 参数表示可以输入到流水线中的可选数据流。它可能包含处理所需的初始数据,对于流水线产生有意义的结果至关重要。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Union[Dict, None] +- additional_data + - additional_data 参数提供了一种向流水线提供额外数据的方式。这可以用来用额外的信息丰富主数据流。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Union[Dict, None] +- prompt + - prompt 参数用于提供可能指导流水线内处理的文本提示。它可能是隐藏的,通常用于内部指导而不是直接处理。 + - Comfy dtype: str + - Python dtype: Union[str, None] +- extra_pnginfo + - extra_pnginfo 参数用于流水线可能处理的PNG图像的附加信息。它是可选的,并且可以包含元数据或其他相关细节。 + - Comfy dtype: str + - Python dtype: Union[str, None] + +# Output types +- data + - SeargePipelineStart 节点输出的数据代表流水线启动后初始化的数据流。它包括节点应用的任何修改或设置,是流水线内进一步处理的基础。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargePipelineStart: + + def __init__(self): + self.pipeline = Pipeline() + + @classmethod + def INPUT_TYPES(s): + return {'required': {'wf_version': (Defs.WORKFLOW_VERSIONS,)}, 'optional': {'data': ('SRG_DATA_STREAM',), 'additional_data': ('SRG_DATA_STREAM',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'trigger' + OUTPUT_NODE = True + CATEGORY = UI.CATEGORY_MAGIC + + def trigger(self, wf_version, data=None, additional_data=None, prompt=None, extra_pnginfo=None): + if data is None: + print('Warning: Pipeline Start - missing data stream') + else: + if additional_data is not None: + data = data | additional_data + self.pipeline.start(data) + access = PipelineAccess(data) + self.pipeline.enable(access.get_active_setting(UI.S_OPERATING_MODE, UI.F_WORKFLOW_MODE) != UI.NONE) + mb_hidden = {Names.F_MAGIC_BOX_PROMPT: prompt, Names.F_MAGIC_BOX_EXTRA_PNGINFO: extra_pnginfo} + mb_version = {Names.F_MAGIC_BOX_EXTENSION: Defs.VERSION, Names.F_MAGIC_BOX_WORKFLOW: wf_version} + access.update_in_pipeline(Names.S_MAGIC_BOX_HIDDEN, mb_hidden) + access.update_in_pipeline(Names.S_MAGIC_BOX_VERSION, mb_version) + if data is not None: + data[Names.S_MAGIC_BOX_HIDDEN] = mb_hidden + data[Names.S_MAGIC_BOX_VERSION] = mb_version + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargePipelineTerminator.md b/docs/SeargePipelineTerminator.md new file mode 100644 index 0000000..59e2f2b --- /dev/null +++ b/docs/SeargePipelineTerminator.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: SeargePipelineTerminator +- Category: UI.CATEGORY_MAGIC +- Output node: True +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargePipelineTerminator节点旨在管理和终止正在进行的数据处理管道。它在确保数据流得到适当结束而不留下任何残留进程方面发挥着关键作用,从而维护系统的效率和完整性。 + +# Input types +## Optional +- data + - ‘data’参数对于节点的操作至关重要,因为它提供了终止管道所需的输入数据流。它的存在确保了节点能够准确识别并结束相关的数据处理管道。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Output types +- result + - 'result'输出表示管道终止过程的结果。它很重要,因为它提供了管道已成功终止的确认,确保系统可以继续进行,而不会有任何悬而未决的数据处理任务。 + - Comfy dtype: DICT + - Python dtype: Dict[str, bool] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargePipelineTerminator: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = () + FUNCTION = 'trigger' + OUTPUT_NODE = True + CATEGORY = UI.CATEGORY_MAGIC + + def trigger(self, data=None): + access = PipelineAccess(data) + access.terminate_pipeline() + return {} +``` \ No newline at end of file diff --git a/docs/SeargePreviewImage.md b/docs/SeargePreviewImage.md new file mode 100644 index 0000000..08a48eb --- /dev/null +++ b/docs/SeargePreviewImage.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: SeargePreviewImage +- Category: UI +- Output node: True +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点通过将图像保存在临时目录中来便利图像预览,允许用户可视化图像处理任务的输出,而不影响主要工作流程。 + +# Input types +## Required +- enabled + - 该参数控制是否激活图像预览功能,决定节点是否继续进行图像保存过程。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- images + - 要预览和保存的输入图像;它们是节点操作的主要对象。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- prompt + - 与图像相关联的可选文本描述,可用于为图像预览提供上下文或其他信息。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - 可以嵌入到保存的图像中的附加元数据,增强每个图像文件可用的信息。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, str] + +# Output types +- images + - 作为输入提供的原始图像,现在伴随着预览功能,允许在UI中进行可视化。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargePreviewImage(nodes.SaveImage): + + def __init__(self): + super().__init__() + self.output_dir = folder_paths.get_temp_directory() + self.type = 'temp' + self.prefix_append = '_temp_' + ''.join((random.choice('abcdefghijklmnopqrstupvxyz') for _ in range(5))) + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'enabled': ('BOOLEAN', {'default': True})}, 'optional': {'images': ('IMAGE',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('images',) + FUNCTION = 'preview_images' + CATEGORY = UI.CATEGORY_UI + + def preview_images(self, enabled, images=None, prompt=None, extra_pnginfo=None): + if images is None or not enabled: + return {'result': (images,), 'ui': {'images': list()}} + saved_images = nodes.SaveImage.save_images(self, images, 'srg_sdxl_preview', prompt, extra_pnginfo) + saved_images['result'] = (images,) + return saved_images +``` \ No newline at end of file diff --git a/docs/SeargePromptAdapterV2.md b/docs/SeargePromptAdapterV2.md new file mode 100644 index 0000000..54797f7 --- /dev/null +++ b/docs/SeargePromptAdapterV2.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: SeargePromptAdapterV2 +- Category: UI_PROMPTING +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点有助于构建和检索提示数据,通过整合主要提示、次要提示、风格提示及其负面对应物,能够为不同场景生成多样化的提示。 + +# Input types +## Optional +- main_prompt + - 主要提示是设置提示生成的主要上下文或主题的关键元素。它在指导输出的方向和内容方面至关重要。 + - Comfy dtype: SRG_PROMPT_TEXT + - Python dtype: str +- secondary_prompt + - 次要提示为主提示提供额外信息或上下文,丰富了生成内容的复杂性和深度。 + - Comfy dtype: SRG_PROMPT_TEXT + - Python dtype: str +- style_prompt + - 风格提示用于定义内容应该呈现的特定语气或方式,为输出增加了一个创造性的层次。 + - Comfy dtype: SRG_PROMPT_TEXT + - Python dtype: str +- negative_main_prompt + - 负面主要提示通过引入相反的观点来平衡主要提示,增强了生成内容的细微差别和健全性。 + - Comfy dtype: SRG_PROMPT_TEXT + - Python dtype: str +- negative_secondary_prompt + - 这些提示通过提供一个次要的反对观点来补充负面主要提示,进一步多样化内容的可能性。 + - Comfy dtype: SRG_PROMPT_TEXT + - Python dtype: str +- negative_style_prompt + - 负面风格提示引入了一种替代的语气或呈现方式,确保输出包含更广泛的风格选择。 + - Comfy dtype: SRG_PROMPT_TEXT + - Python dtype: str +- data + - 数据是节点操作的基础输入,可能包含以前的提示结果或其他可能影响生成过程的相关信。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Output types +- data + - 输出数据流包含结构化的提示信息,可以作为后续流程的输入或用于分析。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargePromptAdapterV2: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}, 'optional': {'data': ('SRG_DATA_STREAM',), 'main_prompt': ('SRG_PROMPT_TEXT',), 'secondary_prompt': ('SRG_PROMPT_TEXT',), 'style_prompt': ('SRG_PROMPT_TEXT',), 'negative_main_prompt': ('SRG_PROMPT_TEXT',), 'negative_secondary_prompt': ('SRG_PROMPT_TEXT',), 'negative_style_prompt': ('SRG_PROMPT_TEXT',)}} + RETURN_TYPES = ('SRG_DATA_STREAM', 'SRG_DATA_STREAM') + RETURN_NAMES = ('data', UI.S_PROMPTS) + FUNCTION = 'get_value' + CATEGORY = UI.CATEGORY_UI_PROMPTING + + @staticmethod + def create_dict(main_prompt=None, secondary_prompt=None, style_prompt=None, negative_main_prompt=None, negative_secondary_prompt=None, negative_style_prompt=None): + return {UI.F_MAIN_PROMPT: main_prompt, UI.F_SECONDARY_PROMPT: secondary_prompt, UI.F_STYLE_PROMPT: style_prompt, UI.F_NEGATIVE_MAIN_PROMPT: negative_main_prompt, UI.F_NEGATIVE_SECONDARY_PROMPT: negative_secondary_prompt, UI.F_NEGATIVE_STYLE_PROMPT: negative_style_prompt} + + def get_value(self, main_prompt=None, secondary_prompt=None, style_prompt=None, negative_main_prompt=None, negative_secondary_prompt=None, negative_style_prompt=None, data=None): + if data is None: + data = {} + data[UI.S_PROMPTS] = self.create_dict(main_prompt, secondary_prompt, style_prompt, negative_main_prompt, negative_secondary_prompt, negative_style_prompt) + return (data, data[UI.S_PROMPTS]) +``` \ No newline at end of file diff --git a/docs/SeargePromptCombiner.md b/docs/SeargePromptCombiner.md new file mode 100644 index 0000000..0f8b08e --- /dev/null +++ b/docs/SeargePromptCombiner.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: SeargePromptCombiner +- Category: Searge/_deprecated_/Prompting +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点促进了两个文本提示的连接,通过将其与所需格式对齐,增强了后续处理的输入数据。 + +# Input types +## Required +- prompt1 + - 第一个文本提示,作为组合过程的初始输入。 + - Comfy dtype: STRING + - Python dtype: str +- separator + - 用于区分两个提示之间的字符串,确保它们以结构化的方式结合。 + - Comfy dtype: STRING + - Python dtype: str +- prompt2 + - 第二个文本提示,将与第一个提示连接,有助于形成最终的组合提示。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- combined prompt + - 两个输入组合后的最终提示,准备进行进一步处理。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargePromptCombiner: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompt1': ('STRING', {'default': '', 'multiline': True}), 'separator': ('STRING', {'default': ', ', 'multiline': False}), 'prompt2': ('STRING', {'default': '', 'multiline': True})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('combined prompt',) + FUNCTION = 'get_value' + CATEGORY = 'Searge/_deprecated_/Prompting' + + def get_value(self, prompt1, separator, prompt2): + len1 = len(prompt1) + len2 = len(prompt2) + prompt = '' + if len1 > 0 and len2 > 0: + prompt = prompt1 + separator + prompt2 + elif len1 > 0: + prompt = prompt1 + elif len2 > 0: + prompt = prompt2 + return (prompt,) +``` \ No newline at end of file diff --git a/docs/SeargePromptStyles.md b/docs/SeargePromptStyles.md new file mode 100644 index 0000000..960de8a --- /dev/null +++ b/docs/SeargePromptStyles.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: SeargePromptStyles +- Category: UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargePromptStyles 是一个用于管理和检索提示风格的节点。它作为一个界面,供用户定义和访问提示样式配置,确保提示根据用户的需求进行格式化。 + +# Input types +## Required +- data + - 参数 'data' 是一个字典,它保存了提示样式的上下文。它是可选的,可以用来提供初始数据或设置,节点将使用这些数据或设置来确定提示的样式。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Output types +- data + - 输出 'data' 是节点根据输入参数和样式配置生成的经过样式设置的提示数据流。它很重要,因为它提供了最终格式化的提示,供后续流程使用。 + - Comfy dtype: SRG_DATA_STREAM + - Python dtype: SRG_DATA_STREAM + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargePromptStyles: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(example): + return {UI.EXAMPLE: example} + + def get(self, data=None): + if data is None: + data = {} + data[UI.S_PROMPT_STYLING] = self.create_dict('example') + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargePromptText.md b/docs/SeargePromptText.md new file mode 100644 index 0000000..0ae36ee --- /dev/null +++ b/docs/SeargePromptText.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: SeargePromptText +- Category: Searge/_deprecated_/Prompting +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargePromptText节点旨在管理和处理文本提示。它在一个需要文本输入以生成或修改内容的系统中使用。该节点的主要功能是检索和提供提示,可以作为进一步处理的基础,或作为输入提供给系统中的其他节点。 + +# Input types +## Required +- prompt + - 对于SeargePromptText节点来说,'prompt'参数是处理的关键元素,它定义了节点将处理的文本输入。预期它是一个字符串,可能包含多行文本,从而能够输入复杂和详细的指令或信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- prompt + - 输出'prompt'是输入到SeargePromptText节点的已处理或原始文本。它作为可以影响后续操作或被用作对查询的直接响应的基础数据片段。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargePromptText: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompt': ('STRING', {'default': '', 'multiline': True})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('prompt',) + FUNCTION = 'get_value' + CATEGORY = 'Searge/_deprecated_/Prompting' + + def get_value(self, prompt): + return (prompt,) +``` \ No newline at end of file diff --git a/docs/SeargeSDXLBasePromptEncoder.md b/docs/SeargeSDXLBasePromptEncoder.md new file mode 100644 index 0000000..9398460 --- /dev/null +++ b/docs/SeargeSDXLBasePromptEncoder.md @@ -0,0 +1,102 @@ +# Documentation +- Class name: SeargeSDXLBasePromptEncoder +- Category: Searge/_deprecated_/ClipEncoding +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeSDXLBasePromptEncoder类作为处理和编码文本输入到CLIP模型可用格式的中介。它旨在通过平衡和对齐正面和负面文本提示的长度来处理文本编码任务,确保与模型的要求兼容。 + +# Input types +## Required +- base_clip + - base_clip参数对于节点的功能至关重要,因为它提供了文本标记化和编码的基础。它是一个CLIP模型实例,用于标记化和编码输入的文本提示。 + - Comfy dtype: CLIP + - Python dtype: CLIP +- pos_g + - 正面全局文本输入对于生成正面条件数据至关重要。它影响编码过程的整体情感和方向。 + - Comfy dtype: STRING + - Python dtype: str +- pos_l + - 正面局部文本输入对于细化正面条件数据非常重要。它有助于为编码过程增加粒度和特异性。 + - Comfy dtype: STRING + - Python dtype: str +- neg_g + - 负面全局文本输入对于产生负面条件数据非常关键。它塑造了编码过程的对比和边界。 + - Comfy dtype: STRING + - Python dtype: str +- neg_l + - 负面局部文本输入对于详细说明负面条件数据很重要。它有助于提高编码过程的精确度和专注度。 + - Comfy dtype: STRING + - Python dtype: str +- base_width + - base_width参数决定了编码过程中基础图像的宽度尺寸。它是数据空间配置的重要组成部分。 + - Comfy dtype: INT + - Python dtype: int +- base_height + - base_height参数设置了编码过程中基础图像的高度尺寸。它对于保持数据的纵横比和结构完整性至关重要。 + - Comfy dtype: INT + - Python dtype: int +- crop_w + - crop_w参数用于确定从基础图像中裁剪区域的宽度。它影响编码数据的焦点和框架。 + - Comfy dtype: INT + - Python dtype: int +- crop_h + - crop_h参数指定从基础图像中裁剪区域的高度。它对编码数据的构图和布局非常重要。 + - Comfy dtype: INT + - Python dtype: int +- target_width + - target_width参数概述了最终输出的期望宽度。它在指导编码过程的调整大小和缩放操作中至关重要。 + - Comfy dtype: INT + - Python dtype: int +- target_height + - target_height参数定义了最终输出的期望高度。它对于对齐编码数据的尺寸和比例非常重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- base_positive + - base_positive输出包含编码后的正面条件数据,对于在后续处理阶段建立正面的上下文和情感至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Tuple[str, Dict[str, Union[str, int, torch.Tensor]]] +- base_negative + - base_negative输出提供编码后的负面条件数据,对于定义编码过程中的边界和对比至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Tuple[str, Dict[str, Union[str, int, torch.Tensor]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeSDXLBasePromptEncoder: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_clip': ('CLIP',), 'pos_g': ('STRING', {'multiline': True, 'default': 'POS_G'}), 'pos_l': ('STRING', {'multiline': True, 'default': 'POS_L'}), 'neg_g': ('STRING', {'multiline': True, 'default': 'NEG_G'}), 'neg_l': ('STRING', {'multiline': True, 'default': 'NEG_L'}), 'base_width': ('INT', {'default': 4096, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'base_height': ('INT', {'default': 4096, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'crop_w': ('INT', {'default': 0, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'crop_h': ('INT', {'default': 0, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'target_width': ('INT', {'default': 4096, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'target_height': ('INT', {'default': 4096, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('base_positive', 'base_negative') + FUNCTION = 'encode' + CATEGORY = 'Searge/_deprecated_/ClipEncoding' + + def encode(self, base_clip, pos_g, pos_l, neg_g, neg_l, base_width, base_height, crop_w, crop_h, target_width, target_height): + empty = base_clip.tokenize('') + tokens1 = base_clip.tokenize(pos_g) + tokens1['l'] = base_clip.tokenize(pos_l)['l'] + if len(tokens1['l']) != len(tokens1['g']): + while len(tokens1['l']) < len(tokens1['g']): + tokens1['l'] += empty['l'] + while len(tokens1['l']) > len(tokens1['g']): + tokens1['g'] += empty['g'] + (cond1, pooled1) = base_clip.encode_from_tokens(tokens1, return_pooled=True) + res1 = [[cond1, {'pooled_output': pooled1, 'width': base_width, 'height': base_height, 'crop_w': crop_w, 'crop_h': crop_h, 'target_width': target_width, 'target_height': target_height}]] + tokens2 = base_clip.tokenize(neg_g) + tokens2['l'] = base_clip.tokenize(neg_l)['l'] + if len(tokens2['l']) != len(tokens2['g']): + while len(tokens2['l']) < len(tokens2['g']): + tokens2['l'] += empty['l'] + while len(tokens2['l']) > len(tokens2['g']): + tokens2['g'] += empty['g'] + (cond2, pooled2) = base_clip.encode_from_tokens(tokens2, return_pooled=True) + res2 = [[cond2, {'pooled_output': pooled2, 'width': base_width, 'height': base_height, 'crop_w': crop_w, 'crop_h': crop_h, 'target_width': target_width, 'target_height': target_height}]] + return (res1, res2) +``` \ No newline at end of file diff --git a/docs/SeargeSDXLImage2ImageSampler.md b/docs/SeargeSDXLImage2ImageSampler.md new file mode 100644 index 0000000..e8f83c0 --- /dev/null +++ b/docs/SeargeSDXLImage2ImageSampler.md @@ -0,0 +1,152 @@ +# Documentation +- Class name: SeargeSDXLImage2ImageSampler +- Category: Searge/_deprecated_/Sampling +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeSDXLImage2ImageSampler节点旨在通过一个复杂的采样增强过程来提升图像质量,该过程利用多个模型和参数来精细化输出结果。它通过结合各种条件因素和细化步骤,旨在改善生成图像的质量和美观度。 + +# Input types +## Required +- base_model + - 基础模型对于图像采样过程至关重要,它构成了图像生成的基础。它是用于生成初始图像数据的主要模型,这些数据将进一步被细化和调节。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- base_positive + - 该参数作为正向调节输入,影响生成图像的风格和内容。它在引导采样过程朝着期望的美学和主题结果方面至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- base_negative + - 负向调节输入用于排除生成图像中的某些元素或特征,确保最终输出符合预期的规范。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- refiner_model + - 细化模型在后处理阶段扮演着关键角色,它用于微调图像,以达到更高的保真度和更好的符合期望的美学品质。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- refiner_positive + - 该输入为细化过程提供正向指导,确保增强后的图像保留期望的属性,并对基础模型的输出进行改进。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- refiner_negative + - 细化模型的负向调节有助于避免最终图像中不希望出现的特征,有助于实现更受控和精确的图像增强。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- image + - 图像参数是节点将要处理和精炼的目标。它是整个采样操作的核心元素。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- vae + - VAE(变分自编码器)用于编码和解码图像数据,使节点能够操纵图像的潜在空间并生成高质量的视觉效果。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- noise_seed + - 噪声种子在采样过程中引入变化方面起着重要作用,确保输出结果的多样性,防止结果重复或可预测。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步骤数量决定了采样过程的复杂性和持续时间,直接影响最终图像的细节和精细程度。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数或'cfg'是一个浮点值,用于调整采样配置,影响节点的整体行为和性能。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 采样器名称标识了要使用的特定采样方法,这对于确定生成图像的质量和特性至关重要。 + - Comfy dtype: SAMPLER_NAME + - Python dtype: str +- scheduler + - 调度器决定了采样过程的节奏和进度,确保细化阶段高效且有序地执行。 + - Comfy dtype: SCHEDULER_NAME + - Python dtype: str +- base_ratio + - 基础比例是一个浮点值,它影响分配给基础模型与细化模型的步骤比例,影响图像中粗略和精细细节的平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- denoise + - 去噪参数控制采样过程中应用的降噪水平,直接影响最终输出的清晰度和平滑度。 + - Comfy dtype: FLOAT + - Python dtype: float +- softness + - 软度调整了在合并放大和原始图像时的混合强度,有助于整体视觉和谐和细节的无缝整合。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- upscale_model + - 当提供放大模型时,它用于提高图像的分辨率,从而获得更高质量和更详细的结果。 + - Comfy dtype: UPSCALE_MODEL + - Python dtype: torch.nn.Module +- scaled_width + - 缩放宽度定义了放大图像的期望宽度,这对于设置细化图像输出的画布大小很重要。 + - Comfy dtype: INT + - Python dtype: int +- scaled_height + - 缩放高度对应于放大图像的期望高度,与缩放宽度一起工作,以确定输出图像的最终尺寸。 + - Comfy dtype: INT + - Python dtype: int +- noise_offset + - 噪声偏移量为噪声种子引入了一个可变的元素,为采样过程增加了额外的多样性,确保了独特的结果。 + - Comfy dtype: INT + - Python dtype: int +- refiner_strength + - 细化强度是一个浮点值,它调节细化过程的强度,允许控制最终图像中细节和清晰度的程度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output_image + - 输出图像是采样过程的结果,代表了包含输入参数和条件的高质量、精细视觉,展示了节点的能力。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SeargeSDXLImage2ImageSampler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_model': ('MODEL',), 'base_positive': ('CONDITIONING',), 'base_negative': ('CONDITIONING',), 'refiner_model': ('MODEL',), 'refiner_positive': ('CONDITIONING',), 'refiner_negative': ('CONDITIONING',), 'image': ('IMAGE',), 'vae': ('VAE',), 'noise_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551600}), 'steps': ('INT', {'default': 20, 'min': 0, 'max': 200}), 'cfg': ('FLOAT', {'default': 7.0, 'min': 0.0, 'max': 30.0, 'step': 0.5}), 'sampler_name': ('SAMPLER_NAME', {'default': 'ddim'}), 'scheduler': ('SCHEDULER_NAME', {'default': 'ddim_uniform'}), 'base_ratio': ('FLOAT', {'default': 0.8, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'denoise': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.01})}, 'optional': {'upscale_model': ('UPSCALE_MODEL',), 'scaled_width': ('INT', {'default': 1536, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'scaled_height': ('INT', {'default': 1536, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'noise_offset': ('INT', {'default': 1, 'min': 0, 'max': 1}), 'refiner_strength': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 1.0, 'step': 0.05}), 'softness': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.05})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'sample' + CATEGORY = 'Searge/_deprecated_/Sampling' + + def sample(self, base_model, base_positive, base_negative, refiner_model, refiner_positive, refiner_negative, image, vae, noise_seed, steps, cfg, sampler_name, scheduler, base_ratio, denoise, softness, upscale_model=None, scaled_width=None, scaled_height=None, noise_offset=None, refiner_strength=None): + base_steps = int(steps * (base_ratio + 0.0001)) + if noise_offset is None: + noise_offset = 1 + if refiner_strength is None: + refiner_strength = 1.0 + if refiner_strength < 0.01: + refiner_strength = 0.01 + if steps < 1: + return (image,) + scaled_image = image + use_upscale_model = upscale_model is not None and softness < 0.9999 + if use_upscale_model: + upscale_result = comfy_extras.nodes_upscale_model.ImageUpscaleWithModel().upscale(upscale_model, image) + scaled_image = upscale_result[0] + if scaled_width is not None and scaled_height is not None: + upscale_result = nodes.ImageScale().upscale(scaled_image, 'bicubic', scaled_width, scaled_height, 'center') + scaled_image = upscale_result[0] + if use_upscale_model and softness > 0.0001: + upscale_result = nodes.ImageScale().upscale(image, 'bicubic', scaled_width, scaled_height, 'center') + scaled_original = upscale_result[0] + blend_result = comfy_extras.nodes_post_processing.Blend().blend_images(scaled_image, scaled_original, softness, 'normal') + scaled_image = blend_result[0] + if denoise < 0.01: + return (scaled_image,) + vae_encode_result = nodes.VAEEncode().encode(vae, scaled_image) + input_latent = vae_encode_result[0] + if base_steps >= steps: + result_latent = nodes.common_ksampler(base_model, noise_seed, steps, cfg, sampler_name, scheduler, base_positive, base_negative, input_latent, denoise=denoise, disable_noise=False, start_step=0, last_step=steps, force_full_denoise=True) + else: + base_result = nodes.common_ksampler(base_model, noise_seed, steps, cfg, sampler_name, scheduler, base_positive, base_negative, input_latent, denoise=denoise, disable_noise=False, start_step=0, last_step=base_steps, force_full_denoise=True) + result_latent = nodes.common_ksampler(refiner_model, noise_seed + noise_offset, steps, cfg, sampler_name, scheduler, refiner_positive, refiner_negative, base_result[0], denoise=denoise * refiner_strength, disable_noise=False, start_step=base_steps, last_step=steps, force_full_denoise=True) + vae_decode_result = nodes.VAEDecode().decode(vae, result_latent[0]) + output_image = vae_decode_result[0] + return (output_image,) +``` \ No newline at end of file diff --git a/docs/SeargeSDXLImage2ImageSampler2.md b/docs/SeargeSDXLImage2ImageSampler2.md new file mode 100644 index 0000000..a469db3 --- /dev/null +++ b/docs/SeargeSDXLImage2ImageSampler2.md @@ -0,0 +1,152 @@ +# Documentation +- Class name: SeargeSDXLImage2ImageSampler2 +- Category: Searge/_deprecated_/Sampling +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点促进了图像生成的高级采样过程,集成了多个模型和细化技术,以提高输出图像的质量和细节。它通过利用基础模型和细化模型的能力,以及条件输入,来产生高分辨率、风格一致的图像。 + +# Input types +## Required +- base_model + - 基础模型对于建立采样过程所需的基础架构至关重要。它决定了生成图像的初始状态,并为后续的改进设定了基调。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- base_positive + - 这个输入作为正向调节元素,影响图像生成的方向和质量。它为模型提供了关于期望美学和主题元素的重要指导。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- base_negative + - 负面调节入对于通过避免不需要的特征或风格来完善图像生成过程至关重要。它有助于细化输出,使其符合预期的创意愿景。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- refiner_model + - 细化模型在图像生成的最后阶段发挥关键作用,专注于增强细节和提升整体视觉质量。它确保输出符合更高的美学标准。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- refiner_positive + - 这个输入在指导细化模型保留和强调图像的积极方面起着重要作用,确保最终输出符合预期的创意方向。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- refiner_negative + - 细化负面输入有助于识别和减轻图像中的任何不需要的元素,有助于形成一个更加精细和完美的最终产品。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- image + - 图像输入是采样过程的起点,提供了一个通过节点操作转换和增强的视觉上下文。对于生成一个连贯且内容丰富的输出至关重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- vae + - VAE组件对采样过程至关重要,它使得图像数据的编码和解码成为可能,以实现风格和美学的转变。它是节点能够产生多样化和细腻输出的关键。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- noise_seed + - 噪声种子是一个关键参数,它在采样过程中引入变异性,确保输出的多样性。它对于防止重复模式和促进创意多样性至关重要。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 采样过程中的步骤数量决定了生成图像的复杂性和细节。它是实现计算效率和视觉质量之间平衡的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数对于微调采样过程至关重要,允许在输出的细节水平和整体视觉风格上进行调整。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 采样器名称是一个关键输入,它决定了节点使用的特定采样方法。它影响图像生成过程的效率和效果。 + - Comfy dtype: SAMPLER_NAME + - Python dtype: str +- scheduler + - 调度器决定了采样过程的节奏和进展,确保从初始状态到最终状态的平稳过渡。这对于获得一个连贯且看起来自然的输出至关重要。 + - Comfy dtype: SCHEDULER_NAME + - Python dtype: str +- base_ratio + - 基础比例参数在确定专用于初始采样阶段的步骤比例方面非常重要。它影响基础细节和细化阶段之间的平衡。 + - Comfy dtype: FLOAT + - Python dtype: float +- denoise + - 去噪参数对于控制生成图像中的噪声减少水平至关重要。它直接影响最终输出的清晰度和视觉吸引力。 + - Comfy dtype: FLOAT + - Python dtype: float +- softness + - 柔和参数影响放大和原始图像的混合,有助于最终输出中视觉元素的平滑度和自然过渡。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- upscale_model + - 放大模型用于提高图像的分辨率,为进一步的细化和增强提供更高质量的画布。 + - Comfy dtype: UPSCALE_MODEL + - Python dtype: torch.nn.Module +- scaled_width + - 图像放大的目标宽度,设定了精细图像的画布大小,并影响输出中的细节水平。 + - Comfy dtype: INT + - Python dtype: int +- scaled_height + - 图像放大的目标高度,与放大的宽度一起,决定了放大图像的最终尺寸。 + - Comfy dtype: INT + - Python dtype: int +- noise_offset + - 噪声偏移参数在采样过程中引入额外的变异性,进一步增强生成图像的样性。 + - Comfy dtype: INT + - Python dtype: int +- refiner_strength + - 细化强度参数调整细化过程的强度,影响最终图像的细节和清晰度程度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output_image + - 输出图像是采样过程的最终成果,代表了输入图像的高分辨率、美学上经过细化的表现形式,通过节点的复杂操作得到增强。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SeargeSDXLImage2ImageSampler2: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_model': ('MODEL',), 'base_positive': ('CONDITIONING',), 'base_negative': ('CONDITIONING',), 'refiner_model': ('MODEL',), 'refiner_positive': ('CONDITIONING',), 'refiner_negative': ('CONDITIONING',), 'image': ('IMAGE',), 'vae': ('VAE',), 'noise_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551600}), 'steps': ('INT', {'default': 20, 'min': 0, 'max': 200}), 'cfg': ('FLOAT', {'default': 7.0, 'min': 0.0, 'max': 30.0, 'step': 0.5}), 'sampler_name': ('SAMPLER_NAME', {'default': 'ddim'}), 'scheduler': ('SCHEDULER_NAME', {'default': 'ddim_uniform'}), 'base_ratio': ('FLOAT', {'default': 0.8, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'denoise': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 1.0, 'step': 0.01})}, 'optional': {'upscale_model': ('UPSCALE_MODEL',), 'scaled_width': ('INT', {'default': 1536, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'scaled_height': ('INT', {'default': 1536, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'noise_offset': ('INT', {'default': 1, 'min': 0, 'max': 1}), 'refiner_strength': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 1.0, 'step': 0.05}), 'softness': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.05})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'sample' + CATEGORY = 'Searge/_deprecated_/Sampling' + + def sample(self, base_model, base_positive, base_negative, refiner_model, refiner_positive, refiner_negative, image, vae, noise_seed, steps, cfg, sampler_name, scheduler, base_ratio, denoise, softness, upscale_model=None, scaled_width=None, scaled_height=None, noise_offset=None, refiner_strength=None): + base_steps = int(steps * (base_ratio + 0.0001)) + if noise_offset is None: + noise_offset = 1 + if refiner_strength is None: + refiner_strength = 1.0 + if refiner_strength < 0.01: + refiner_strength = 0.01 + if steps < 1: + return (image,) + scaled_image = image + use_upscale_model = upscale_model is not None and softness < 0.9999 + if use_upscale_model: + upscale_result = comfy_extras.nodes_upscale_model.ImageUpscaleWithModel().upscale(upscale_model, image) + scaled_image = upscale_result[0] + if scaled_width is not None and scaled_height is not None: + upscale_result = nodes.ImageScale().upscale(scaled_image, 'bicubic', scaled_width, scaled_height, 'center') + scaled_image = upscale_result[0] + if use_upscale_model and softness > 0.0001: + upscale_result = nodes.ImageScale().upscale(image, 'bicubic', scaled_width, scaled_height, 'center') + scaled_original = upscale_result[0] + blend_result = comfy_extras.nodes_post_processing.Blend().blend_images(scaled_image, scaled_original, softness, 'normal') + scaled_image = blend_result[0] + if denoise < 0.01: + return (scaled_image,) + vae_encode_result = nodes.VAEEncode().encode(vae, scaled_image) + input_latent = vae_encode_result[0] + if base_steps >= steps: + result_latent = nodes.common_ksampler(base_model, noise_seed, steps, cfg, sampler_name, scheduler, base_positive, base_negative, input_latent, denoise=denoise, disable_noise=False, start_step=0, last_step=steps, force_full_denoise=True) + else: + base_result = nodes.common_ksampler(base_model, noise_seed, steps, cfg, sampler_name, scheduler, base_positive, base_negative, input_latent, denoise=denoise, disable_noise=False, start_step=0, last_step=base_steps, force_full_denoise=True) + result_latent = nodes.common_ksampler(refiner_model, noise_seed + noise_offset, steps, cfg, sampler_name, scheduler, refiner_positive, refiner_negative, base_result[0], denoise=denoise * refiner_strength, disable_noise=False, start_step=base_steps, last_step=steps, force_full_denoise=True) + vae_decode_result = nodes.VAEDecode().decode(vae, result_latent[0]) + output_image = vae_decode_result[0] + return (output_image,) +``` \ No newline at end of file diff --git a/docs/SeargeSDXLPromptEncoder.md b/docs/SeargeSDXLPromptEncoder.md new file mode 100644 index 0000000..868968f --- /dev/null +++ b/docs/SeargeSDXLPromptEncoder.md @@ -0,0 +1,145 @@ +# Documentation +- Class name: SeargeSDXLPromptEncoder +- Category: Searge/_deprecated_/ClipEncoding +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点旨在将文本输入处理并编码为生成模型的条件数据。它专注于将提示转换为可以指导生成过程的结构化格式,强调节点在为创意任务准备输入方面的作用。 + +# Input types +## Required +- base_clip + - 该参数至关重要,因为它提供了用于编码文本提示的基础CLIP模型。它对节点的运行至关重要,并影响生成的条件数据的质量。 + - Comfy dtype: CLIP + - Python dtype: CLIPModel +- refiner_clip + - 细化CLIP模型用于进一步处理和细化文本提示,提高条件数据的有效性。其在节点执行和最终输出质量中的作用至关重要。 + - Comfy dtype: CLIP + - Python dtype: CLIPModel +- base_width + - 基础宽度参数对于定义生成模型的输入空间尺寸至关重要,直接影响生成内容的范围和分辨率。 + - Comfy dtype: INT + - Python dtype: int +- base_height + - 与基础宽度类似,基础高度参数在设置输入空间的垂直尺寸方面至关重要,影响输出的整体结构和构图。 + - Comfy dtype: INT + - Python dtype: int +- crop_w + - 裁剪宽度参数决定了裁剪区域的水平范围,这对于将生成集中在输入中的特定兴趣区域至关重要。 + - Comfy dtype: INT + - Python dtype: int +- crop_h + - 裁剪高度参数设置了裁剪区域的垂直尺寸,对于在生成过程中隔离特定元素起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- target_width + - 目标宽度参数定义了输出的期望宽度,这是确保生成内容满足所需规格和尺寸的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- target_height + - 目标高度参数指定了输出的期望高度,直接影响生成内容的最终尺寸和布局。 + - Comfy dtype: INT + - Python dtype: int +- pos_ascore + - 正面审美分数参数用于加权正面提示在生成过程中的重要性,确保输出反映了期望的审美品质。 + - Comfy dtype: FLOAT + - Python dtype: float +- neg_ascore + - 负面审美分数参数有助于减少输出中不希望的审美元素,提高生成内容的精确性和相关性。 + - Comfy dtype: FLOAT + - Python dtype: float +- refiner_width + - 细化器宽度参数对于设置细化输入空间的尺寸很重要,这对于在输出中实现详细和高质量的细化至关重要。 + - Comfy dtype: INT + - Python dtype: int +- refiner_height + - 细化器高度参数对于定义细化输入空间的垂直尺寸至关重要,影响输出中审美细化的粒度和精确度。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- pos_g + - 该参数包含正面全局提示,它影响生成内容的整体主题和方向。在为节点操作设置创意背景方面具有重要意义。 + - Comfy dtype: STRING + - Python dtype: str +- pos_l + - 正面局部提示为生成的特定方面提供详细指导,有助于节点产生针对性和细腻的输出。 + - Comfy dtype: STRING + - Python dtype: str +- pos_r + - 正面细化提示用于微调生成过程,确保输出与期望的审美和主题目标紧密对齐。 + - Comfy dtype: STRING + - Python dtype: str +- neg_g + - 负面全局提示有助于从生成内容中排除不希望的元素,对塑造最终输出的特征起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +- neg_l + - 负面局部提示用于指定在生成中应避免的特定方面,引导节点产生符合特定排除标准的内容丰富。 + - Comfy dtype: STRING + - Python dtype: str +- neg_r + - 负面细化提示用于进一步细化排除不希望的元素,确保节点的输出具有高度的精确度。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- base_positive + - 此输出提供了从基础正面提示派生的条件数据,它作为引导生成模型朝着期望的创意方向发展的基础。 + - Comfy dtype: CONDITIONING + - Python dtype: ConditioningData +- base_negative + - 基础负面输出包含来自基础负面提示的条件数据,有助于从生成内容中排除不希望的元素。 + - Comfy dtype: CONDITIONING + - Python dtype: ConditioningData +- refiner_positive + - 此输出包括来自细化器正面提示的条件数据,专注于微调生成内容的审美和主题方面。 + - Comfy dtype: CONDITIONING + - Python dtype: ConditioningData +- refiner_negative + - 细化器负面输出提供基于细化器负面提示的条件数据,确保最终输出经过细化以避免不希望的特征。 + - Comfy dtype: CONDITIONING + - Python dtype: ConditioningData + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeSDXLPromptEncoder: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_clip': ('CLIP',), 'refiner_clip': ('CLIP',), 'pos_g': ('STRING', {'multiline': True, 'default': 'POS_G'}), 'pos_l': ('STRING', {'multiline': True, 'default': 'POS_L'}), 'pos_r': ('STRING', {'multiline': True, 'default': 'POS_R'}), 'neg_g': ('STRING', {'multiline': True, 'default': 'NEG_G'}), 'neg_l': ('STRING', {'multiline': True, 'default': 'NEG_L'}), 'neg_r': ('STRING', {'multiline': True, 'default': 'NEG_R'}), 'base_width': ('INT', {'default': 4096, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'base_height': ('INT', {'default': 4096, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'crop_w': ('INT', {'default': 0, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'crop_h': ('INT', {'default': 0, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'target_width': ('INT', {'default': 4096, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'target_height': ('INT', {'default': 4096, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'pos_ascore': ('FLOAT', {'default': 6.0, 'min': 0.0, 'max': 1000.0, 'step': 0.01}), 'neg_ascore': ('FLOAT', {'default': 2.5, 'min': 0.0, 'max': 1000.0, 'step': 0.01}), 'refiner_width': ('INT', {'default': 2048, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'refiner_height': ('INT', {'default': 2048, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING', 'CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('base_positive', 'base_negative', 'refiner_positive', 'refiner_negative') + FUNCTION = 'encode' + CATEGORY = 'Searge/_deprecated_/ClipEncoding' + + def encode(self, base_clip, refiner_clip, pos_g, pos_l, pos_r, neg_g, neg_l, neg_r, base_width, base_height, crop_w, crop_h, target_width, target_height, pos_ascore, neg_ascore, refiner_width, refiner_height): + empty = base_clip.tokenize('') + tokens1 = base_clip.tokenize(pos_g) + tokens1['l'] = base_clip.tokenize(pos_l)['l'] + if len(tokens1['l']) != len(tokens1['g']): + while len(tokens1['l']) < len(tokens1['g']): + tokens1['l'] += empty['l'] + while len(tokens1['l']) > len(tokens1['g']): + tokens1['g'] += empty['g'] + (cond1, pooled1) = base_clip.encode_from_tokens(tokens1, return_pooled=True) + res1 = [[cond1, {'pooled_output': pooled1, 'width': base_width, 'height': base_height, 'crop_w': crop_w, 'crop_h': crop_h, 'target_width': target_width, 'target_height': target_height}]] + tokens2 = base_clip.tokenize(neg_g) + tokens2['l'] = base_clip.tokenize(neg_l)['l'] + if len(tokens2['l']) != len(tokens2['g']): + while len(tokens2['l']) < len(tokens2['g']): + tokens2['l'] += empty['l'] + while len(tokens2['l']) > len(tokens2['g']): + tokens2['g'] += empty['g'] + (cond2, pooled2) = base_clip.encode_from_tokens(tokens2, return_pooled=True) + res2 = [[cond2, {'pooled_output': pooled2, 'width': base_width, 'height': base_height, 'crop_w': crop_w, 'crop_h': crop_h, 'target_width': target_width, 'target_height': target_height}]] + tokens3 = refiner_clip.tokenize(pos_r) + (cond3, pooled3) = refiner_clip.encode_from_tokens(tokens3, return_pooled=True) + res3 = [[cond3, {'pooled_output': pooled3, 'aesthetic_score': pos_ascore, 'width': refiner_width, 'height': refiner_height}]] + tokens4 = refiner_clip.tokenize(neg_r) + (cond4, pooled4) = refiner_clip.encode_from_tokens(tokens4, return_pooled=True) + res4 = [[cond4, {'pooled_output': pooled4, 'aesthetic_score': neg_ascore, 'width': refiner_width, 'height': refiner_height}]] + return (res1, res2, res3, res4) +``` \ No newline at end of file diff --git a/docs/SeargeSDXLRefinerPromptEncoder.md b/docs/SeargeSDXLRefinerPromptEncoder.md new file mode 100644 index 0000000..1ace6d3 --- /dev/null +++ b/docs/SeargeSDXLRefinerPromptEncoder.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: SeargeSDXLRefinerPromptEncoder +- Category: Searge/_deprecated_/ClipEncoding +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点旨在通过将文本输入编码成结构化格式来处理和细化它们,这种格式对于后续的分析或生成任务至关重要。它专注于将正面和负面参考转换为调节格式,这对于管道中的后续步骤至关重要。 + +# Input types +## Required +- refiner_clip + - 这个参数至关重要,因为它为编码过程提供了基础。它是对CLIP模型的引用,将用于标记化和编码输入文本,使得文本数据能够被节点处理。 + - Comfy dtype: CLIP + - Python dtype: CLIP +- pos_r + - 这个参数对于提供正面参考文本至关重要。它通过确定后续任务中使用的正面调节数据的上下文和质量来影响编码过程。 + - Comfy dtype: STRING + - Python dtype: str +- neg_r + - 这个参数对于提供负面参考文本至关重要。它通过为负面调节数据建立上下文来影响编码,这对于后续步骤的准确性和有效性至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- pos_ascore + - 这个参数很重要,因为它设置了正面参考的审美分数。它在指导细化过程中起着关键作用,确保编码输出符合期望的审美标准。 + - Comfy dtype: FLOAT + - Python dtype: float +- neg_ascore + - 这个参数对于定义负面参考的审美分数很重要。它有助于塑造细化过程,以满足负面调节数据所需的审美标准。 + - Comfy dtype: FLOAT + - Python dtype: float +- refiner_width + - 这个参数在确定细化空间的宽度方面至关重要。它直接影响输出的尺寸,确保编码符合下游任务的具体要求。 + - Comfy dtype: INT + - Python dtype: int +- refiner_height + - 这个参数对于设置细化空间的高度至关重要。它与宽度参数共同作用,定义了调节数据的整体大小,这对于编码过程的精度至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- refiner_positive + - 输出提供了编码后的正面参考数据,这是后续需要正面调节上下文的任务的关键组成部分。 + - Comfy dtype: CONDITIONING + - Python dtype: Tuple[CLIPCondition, Dict[str, Union[float, int]]] +- refiner_negative + - 输出提供了编码后的负面参考数据,这是依赖于负面调节上下文的任务的基本元素。 + - Comfy dtype: CONDITIONING + - Python dtype: Tuple[CLIPCondition, Dict[str, Union[float, int]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeSDXLRefinerPromptEncoder: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'refiner_clip': ('CLIP',), 'pos_r': ('STRING', {'multiline': True, 'default': 'POS_R'}), 'neg_r': ('STRING', {'multiline': True, 'default': 'NEG_R'}), 'pos_ascore': ('FLOAT', {'default': 6.0, 'min': 0.0, 'max': 1000.0, 'step': 0.01}), 'neg_ascore': ('FLOAT', {'default': 2.5, 'min': 0.0, 'max': 1000.0, 'step': 0.01}), 'refiner_width': ('INT', {'default': 2048, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8}), 'refiner_height': ('INT', {'default': 2048, 'min': 0, 'max': nodes.MAX_RESOLUTION, 'step': 8})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('refiner_positive', 'refiner_negative') + FUNCTION = 'encode' + CATEGORY = 'Searge/_deprecated_/ClipEncoding' + + def encode(self, refiner_clip, pos_r, neg_r, pos_ascore, neg_ascore, refiner_width, refiner_height): + tokens1 = refiner_clip.tokenize(pos_r) + (cond1, pooled1) = refiner_clip.encode_from_tokens(tokens1, return_pooled=True) + res1 = [[cond1, {'pooled_output': pooled1, 'aesthetic_score': pos_ascore, 'width': refiner_width, 'height': refiner_height}]] + tokens2 = refiner_clip.tokenize(neg_r) + (cond2, pooled2) = refiner_clip.encode_from_tokens(tokens2, return_pooled=True) + res2 = [[cond2, {'pooled_output': pooled2, 'aesthetic_score': neg_ascore, 'width': refiner_width, 'height': refiner_height}]] + return (res1, res2) +``` \ No newline at end of file diff --git a/docs/SeargeSDXLSampler.md b/docs/SeargeSDXLSampler.md new file mode 100644 index 0000000..a3cd46e --- /dev/null +++ b/docs/SeargeSDXLSampler.md @@ -0,0 +1,97 @@ +# Documentation +- Class name: SeargeSDXLSampler +- Category: Searge/_deprecated_/Sampling +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeSDXLSampler节点旨在促进深度学习框架内的采样过程,特别适用于风格迁移任务。它结合了基础模型和细化模型,以逐步提高生成输出的质量,从潜在图像开始,并应用降噪技术。 + +# Input types +## Required +- base_model + - 基础模型对于采样过程至关重要,它构成了输出的基础。这是用于生成输出基础层的初始神经网络。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- base_positive + - 基础正向调节对于引导生成图像的风格和内容朝着期望的结果至关重要,确保图像与目标领域保持一致。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- base_negative + - 基础负面调节有助于避免生成图像中不需要的特征或风格,使输出更加符合预期结果。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- refiner_model + - 细化模型通过应用额外的层和微调最终结果,在提高基础输出质量方面发挥着关键作用。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- refiner_positive + - 细化正向调节进一步细化图像,以强调特定特征或风格,确保最终输出具有更高的细节和保真度。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- refiner_negative + - 细化负面调节用于抑制可能不符合预期结果的某些特征或风格,确保最终图像符合质量标准。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- latent_image + - 潜在图像是采样过程的起点,代表了生成和发展最终图像的初始状态。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- noise_seed + - 噪声种子在引入采样过程中的变异性和随机性方面起着重要作用,确保生成输出的多样性。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步骤定义了采样过程将要经历的迭代次数,直接影响最终图像的细节和细化程度。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数对于调整生成图像中风格和内容的平衡至关重要,确保两者的和谐融合。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 采样器名称决定了要使用的特定采样策略,这显著影响了采样过程的效率和质量。 + - Comfy dtype: COMBO[comfy.samplers.KSampler.SAMPLERS] + - Python dtype: str +- scheduler + - 调度器决定了采样过程的节奏和进展,确保从初始状态到最终状态的平稳过渡。 + - Comfy dtype: COMBO[comfy.samplers.KSampler.SCHEDULERS] + - Python dtype: str +- base_ratio + - 基础比例参数调整了总步骤中专门用于基础采样阶段的比例,影响了输出的初始质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- denoise + - 去噪参数控制了采样过程中应用的降噪水平,直接影响最终图像的清晰度和锐度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- + - 输出是图像的潜在表示,它包含了采样过程完成后的最终状态,代表了各种输入和参数的结合。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SeargeSDXLSampler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_model': ('MODEL',), 'base_positive': ('CONDITIONING',), 'base_negative': ('CONDITIONING',), 'refiner_model': ('MODEL',), 'refiner_positive': ('CONDITIONING',), 'refiner_negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'noise_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'steps': ('INT', {'default': 30, 'min': 1, 'max': 1000}), 'cfg': ('FLOAT', {'default': 7.0, 'min': 0.0, 'max': 100.0, 'step': 0.5}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS, {'default': 'dpmpp_2m'}), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS, {'default': 'karras'}), 'base_ratio': ('FLOAT', {'default': 0.8, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('LATENT',) + RETURN_NAMES = ('',) + FUNCTION = 'sample' + CATEGORY = 'Searge/_deprecated_/Sampling' + + def sample(self, base_model, base_positive, base_negative, refiner_model, refiner_positive, refiner_negative, latent_image, noise_seed, steps, cfg, sampler_name, scheduler, base_ratio, denoise): + base_steps = int(steps * base_ratio) + if denoise < 0.01: + return (latent_image,) + if base_steps >= steps: + return nodes.common_ksampler(base_model, noise_seed, steps, cfg, sampler_name, scheduler, base_positive, base_negative, latent_image, denoise=denoise, disable_noise=False, start_step=0, last_step=steps, force_full_denoise=True) + base_result = nodes.common_ksampler(base_model, noise_seed, steps, cfg, sampler_name, scheduler, base_positive, base_negative, latent_image, denoise=denoise, disable_noise=False, start_step=0, last_step=base_steps, force_full_denoise=False) + return nodes.common_ksampler(refiner_model, noise_seed, steps, cfg, sampler_name, scheduler, refiner_positive, refiner_negative, base_result[0], denoise=1.0, disable_noise=True, start_step=base_steps, last_step=steps, force_full_denoise=True) +``` \ No newline at end of file diff --git a/docs/SeargeSDXLSampler2.md b/docs/SeargeSDXLSampler2.md new file mode 100644 index 0000000..3d2061b --- /dev/null +++ b/docs/SeargeSDXLSampler2.md @@ -0,0 +1,124 @@ +# Documentation +- Class name: SeargeSDXLSampler2 +- Category: Searge/_deprecated_/Sampling +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeSDXLSampler2类通过一系列模型迭代细化一个潜在图像,增强生成输出的质量和细节。它利用基础模型和细化模型的组合来逐步改进表示形式,调整各种参数来控制细化过程并实现所需的细节水平和降噪效果。 + +# Input types +## Required +- base_model + - 基础模型是用于初始采样的基础神经网络。它对于建立潜在图像的一般结构和质量至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- base_positive + - 基础正向调节为基地模型提供了生成准确和相关潜在图像所需的重要上下文。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- base_negative + - 基础负面调节通过排除不需要的特征或特征来帮助细化采样过程。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- refiner_model + - 细化模型通过应用高级技术和微调输出来提高潜在图像的质量。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- refiner_positive + - 细化正向调节通过专注于最终输出中所需的特定细节和特征来进一步细化图像。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- refiner_negative + - 细化负面调节确保最终图像不包含不需要的元素,保持细化过程的完整性和质量。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- latent_image + - 潜在图像是初始表示,将通过采样过程迭代改进。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- noise_seed + - 噪声种子在控制采样过程中引入的噪声的随机性和可变性方面起着重要作用,这会影响结果的多样性和质量。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 采样过程中的步骤数量决定了最终图像实现的细节和细化程度。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数是一个关键值,它影响采样过程的整体行为和性能。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 采样器名称标识用于采样过程的特定算法,这可以显著影响采样的效率和效果。 + - Comfy dtype: SAMPLER_NAME + - Python dtype: str +- scheduler + - 调度器决定了采样过程的节奏和进展,确保了一个平衡和受控的细化。 + - Comfy dtype: SCHEDULER_NAME + - Python dtype: str +- base_ratio + - 基础比例参数调整基础模型和细化模型之间的平衡,影响采样过程不同阶段的重点和强调。 + - Comfy dtype: FLOAT + - Python dtype: float +- denoise + - 去噪参数控制采样过程中应用的降噪水平,直接影响最终图像的清晰度和锐度。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- refiner_prep_steps + - 细化准备步骤用于在主要采样过程之前预处理潜在图像,可能提高输出的质量和一致性。 + - Comfy dtype: INT + - Python dtype: int +- noise_offset + - 噪声偏移参数为细化模型引入噪声种子的变异性,有助于最终输出的多样性。 + - Comfy dtype: INT + - Python dtype: int +- refiner_strength + - 细化强度参数调节细化过程的强度,较高的值导致最终图像中更明显的变化。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- latent_image + - 输出潜在图像是采样过程的结果,展示了增强的细节和降低的噪声。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SeargeSDXLSampler2: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_model': ('MODEL',), 'base_positive': ('CONDITIONING',), 'base_negative': ('CONDITIONING',), 'refiner_model': ('MODEL',), 'refiner_positive': ('CONDITIONING',), 'refiner_negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'noise_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551600}), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 200}), 'cfg': ('FLOAT', {'default': 7.0, 'min': 0.0, 'max': 30.0, 'step': 0.5}), 'sampler_name': ('SAMPLER_NAME', {'default': 'ddim'}), 'scheduler': ('SCHEDULER_NAME', {'default': 'ddim_uniform'}), 'base_ratio': ('FLOAT', {'default': 0.8, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}, 'optional': {'refiner_prep_steps': ('INT', {'default': 0, 'min': 0, 'max': 10}), 'noise_offset': ('INT', {'default': 1, 'min': 0, 'max': 1}), 'refiner_strength': ('FLOAT', {'default': 1.0, 'min': 0.01, 'max': 1.0, 'step': 0.05})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'sample' + CATEGORY = 'Searge/_deprecated_/Sampling' + + def sample(self, base_model, base_positive, base_negative, refiner_model, refiner_positive, refiner_negative, latent_image, noise_seed, steps, cfg, sampler_name, scheduler, base_ratio, denoise, refiner_prep_steps=None, noise_offset=None, refiner_strength=None): + base_steps = int(steps * (base_ratio + 0.0001)) + if noise_offset is None: + noise_offset = 1 + if refiner_strength is None: + refiner_strength = 1.0 + if refiner_strength < 0.01: + refiner_strength = 0.01 + if denoise < 0.01: + return (latent_image,) + start_at_step = 0 + input_latent = latent_image + if refiner_prep_steps is not None: + if refiner_prep_steps >= base_steps: + refiner_prep_steps = base_steps - 1 + if refiner_prep_steps > 0: + start_at_step = refiner_prep_steps + precondition_result = nodes.common_ksampler(refiner_model, noise_seed + 2, steps, cfg, sampler_name, scheduler, refiner_positive, refiner_negative, latent_image, denoise=denoise, disable_noise=False, start_step=steps - refiner_prep_steps, last_step=steps, force_full_denoise=False) + input_latent = precondition_result[0] + if base_steps >= steps: + return nodes.common_ksampler(base_model, noise_seed, steps, cfg, sampler_name, scheduler, base_positive, base_negative, input_latent, denoise=denoise, disable_noise=False, start_step=start_at_step, last_step=steps, force_full_denoise=True) + base_result = nodes.common_ksampler(base_model, noise_seed, steps, cfg, sampler_name, scheduler, base_positive, base_negative, input_latent, denoise=denoise, disable_noise=False, start_step=start_at_step, last_step=base_steps, force_full_denoise=True) + return nodes.common_ksampler(refiner_model, noise_seed + noise_offset, steps, cfg, sampler_name, scheduler, refiner_positive, refiner_negative, base_result[0], denoise=denoise * refiner_strength, disable_noise=False, start_step=base_steps, last_step=steps, force_full_denoise=True) +``` \ No newline at end of file diff --git a/docs/SeargeSDXLSamplerV3.md b/docs/SeargeSDXLSamplerV3.md new file mode 100644 index 0000000..d77045b --- /dev/null +++ b/docs/SeargeSDXLSamplerV3.md @@ -0,0 +1,110 @@ +# Documentation +- Class name: SeargeSDXLSamplerV3 +- Category: Searge/_deprecated_/Sampling +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点旨在使用基础模型和细化模型的组合来执行采样过程,以生成高质量的潜在图像。它整合了噪声和条件输入,以产生细化的输出,提高了整体采样效率和结果质量。 + +# Input types +## Required +- base_model + - 基础模型对于建立采样过程的基础结构至关重要。它决定了生成潜在图像过程中的初始条件和可能的变化。 + - Comfy dtype: MODEL + - Python dtype: UNetModel +- base_positive + - 此参数作为正向条件数据,影响采样过程。它有助于将生成引向期望的特征,并提高输出质量。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- base_negative + - 负向条件数据用于通过避免不希望的特征来约束采样过程。它在确保最终输出与预期方向一致方面起着关键作用。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- refiner_model + - 细化模型对于采样过程的后处理阶段至关重要。它通过应用进一步的细化来提高生成的潜在图像的质量和细节。 + - Comfy dtype: MODEL + - Python dtype: UNetModel +- refiner_positive + - 细化正向条件数据通过强调某些特征来精炼输出。这在实现更细致和有针对性的最终结果方面至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- refiner_negative + - 细化负向条件数据有助于防止最终输出中引入不希望的元素。它有助于提高采样过程的精确性和准确性。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- latent_image + - 潜在图像是采样过程的初始输入,作为起点。其质量和特征显著影响最终输出。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- noise_seed + - 噪声种子在控制采样过程中应用的噪声的随机性方面起着重要作用。它确保了结果的一致性和可复现性。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步骤数量决定了采样过程的持续时间和复杂性。它直接影响最终潜在图像中实现的细节和细化程度。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数对于调整采样过程的行为至关重要。它影响探索和利用之间的平衡,从而获得更优化的结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - 采样器名称标识用于采样过程的特定算法。它对于在最终输出中实现期望的特征至关重要。 + - Comfy dtype: SAMPLER_NAME + - Python dtype: str +- scheduler + - 调度器在采样过程中控制超参数的进步和调整。它在优化采样效率和输出质量方面起着关键作用。 + - Comfy dtype: SCHEDULER_NAME + - Python dtype: str +- base_ratio + - 基础比例参数影响步骤在基础模型和细化模型之间的分布。它对于平衡最终潜在图像中的粗略和精细细节至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- denoise + - 去噪参数控制采样过程中应用的降噪水平。它在提高最终输出的清晰度和质量方面非常重要。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- refiner_prep_steps + - 此可选参数指定细化模型的预备步骤数量。它可以从0到总步骤数的范围,允许定制预细化过程。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- latent + - 输出潜在代表采样过程后最终生成的潜在图像。它包含了通过基础模型和细化模型的结合实现的精炼特征和细节。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SeargeSDXLSamplerV3: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_model': ('MODEL',), 'base_positive': ('CONDITIONING',), 'base_negative': ('CONDITIONING',), 'refiner_model': ('MODEL',), 'refiner_positive': ('CONDITIONING',), 'refiner_negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'noise_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551600}), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 200}), 'cfg': ('FLOAT', {'default': 7.0, 'min': 0.0, 'max': 30.0, 'step': 0.5}), 'sampler_name': ('SAMPLER_NAME', {'default': 'ddim'}), 'scheduler': ('SCHEDULER_NAME', {'default': 'ddim_uniform'}), 'base_ratio': ('FLOAT', {'default': 0.8, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}, 'optional': {'refiner_prep_steps': ('INT', {'default': 0, 'min': 0, 'max': 10})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'sample' + CATEGORY = 'Searge/_deprecated_/Sampling' + + def sample(self, base_model, base_positive, base_negative, refiner_model, refiner_positive, refiner_negative, latent_image, noise_seed, steps, cfg, sampler_name, scheduler, base_ratio, denoise, refiner_prep_steps=None): + base_steps = int(steps * (base_ratio + 0.0001)) + refiner_steps = max(0, steps - base_steps) + if denoise < 0.01: + return (latent_image,) + start_at_step = 0 + input_latent = latent_image + if refiner_prep_steps is not None: + if refiner_prep_steps >= base_steps: + refiner_prep_steps = base_steps - 1 + if refiner_prep_steps > 0: + start_at_step = refiner_prep_steps + precondition_result = nodes.common_ksampler(refiner_model, noise_seed + 2, steps, cfg, sampler_name, scheduler, refiner_positive, refiner_negative, latent_image, denoise=denoise, disable_noise=False, start_step=steps - refiner_prep_steps, last_step=steps, force_full_denoise=False) + input_latent = precondition_result[0] + if base_steps >= steps: + return nodes.common_ksampler(base_model, noise_seed, steps, cfg, sampler_name, scheduler, base_positive, base_negative, input_latent, denoise=denoise, disable_noise=False, start_step=start_at_step, last_step=steps, force_full_denoise=True) + return sdxl_ksampler(base_model, refiner_model, noise_seed, base_steps, refiner_steps, cfg, sampler_name, scheduler, base_positive, base_negative, refiner_positive, refiner_negative, input_latent, denoise=denoise, disable_noise=False, start_step=start_at_step, last_step=steps, force_full_denoise=True) +``` \ No newline at end of file diff --git a/docs/SeargeSamplerInputs.md b/docs/SeargeSamplerInputs.md new file mode 100644 index 0000000..20bcf7c --- /dev/null +++ b/docs/SeargeSamplerInputs.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: SeargeSamplerInputs +- Category: Searge/_deprecated_/Inputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点类封装了检索和配置采样器和调度器的过程,这些是采样过程中不可或缺的组成部分。它提供了一种结构化的方式来选择和使用不同的采样策略和调度方法,以控制输出的生成。该节点确保基于用户的选择使用适当的算法,从而促进高质量结果的生成。 + +# Input types +## Required +- sampler_name + - sampler_name参数对于确定要使用的采样算法类型至关重要。它决定了生成输出的方法,这可能会显著影响结果的质量和多样性。通过选择特定的采样器,用户引导节点执行并塑造采样过程的整体结果。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- scheduler + - scheduler参数在管理采样过程的流程和节奏方面起着关键作用。它调节样本产生的速率,确保生成过程在速度和效率上都得到优化。调度器的选择直接影响采样操作的性能和资源利用。 + - Comfy dtype: COMBO[str] + - Python dtype: str + +# Output types +- sampler_name + - sampler_name输出代表了根据输入确定的选定采样算法。这个选择对采样过程至关重要,因为它决定了生成输出的方法,影响结果的整体质量和特性。 + - Comfy dtype: str + - Python dtype: str +- scheduler + - scheduler输出表示选定的调度方法,它将管理采样操作的速率和节奏。这个选择对于平衡计算效率和输出质量之间的权衡至关重要,确保采样过程既有效又注重资源。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeSamplerInputs: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'sampler_name': (comfy.samplers.KSampler.SAMPLERS, {'default': 'ddim'}), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS, {'default': 'ddim_uniform'})}} + RETURN_TYPES = ('SAMPLER_NAME', 'SCHEDULER_NAME') + RETURN_NAMES = ('sampler_name', 'scheduler') + FUNCTION = 'get_value' + CATEGORY = 'Searge/_deprecated_/Inputs' + + def get_value(self, sampler_name, scheduler): + return (sampler_name, scheduler) +``` \ No newline at end of file diff --git a/docs/SeargeSaveFolderInputs.md b/docs/SeargeSaveFolderInputs.md new file mode 100644 index 0000000..4aa1f29 --- /dev/null +++ b/docs/SeargeSaveFolderInputs.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: SeargeSaveFolderInputs +- Category: Searge/_deprecated_/Inputs +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +这个节点类旨在促进将数据保存到指定文件夹的过程,作为用户和保存功能之间的中介。它强调易用性,并确保根据用户的要求将数据引导到正确的位置。 + +# Input types +## Required +- save_to + - ‘save_to’参数对于确定数据的目的地文件夹至关重要。它是一个字符串,指定了数据将被保存的路径,其正确使用对节点功能的成功执行至关重要。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- save_to + - 输出‘save_to’代表确认的文件夹路径,数据将被保存于此。这是标志着节点成功操作和数据正确路由的关键信息。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeSaveFolderInputs: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'save_to': (SeargeParameterProcessor.SAVE_TO, {'default': SeargeParameterProcessor.SAVE_TO[0]})}} + RETURN_TYPES = ('SAVE_FOLDER',) + RETURN_NAMES = ('save_to',) + FUNCTION = 'get_value' + CATEGORY = 'Searge/_deprecated_/Inputs' + + def get_value(self, save_to): + return (save_to,) +``` \ No newline at end of file diff --git a/docs/SeargeSeparator.md b/docs/SeargeSeparator.md new file mode 100644 index 0000000..a8142b8 --- /dev/null +++ b/docs/SeargeSeparator.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: SeargeSeparator +- Category: UI +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeSeparator节点旨在作为工作流中的占位符,提供一种分离和组织不同流程段的手段,而不执行任何积极的计算或数据操作。它作为一个结构组件,允许工作流具有清晰和逻辑的布局。 + +# Input types +## Required +- required + - 该参数是SeargeSeparator节点中的关键组件,定义了输入的结构而不指定实际的数据要求。它确保节点在工作流中正确集成,有助于整体组织。 + - Comfy dtype: COMBO[{}] + - Python dtype: Dict[str, Any] + +# Output types +- None + - 由于节点的FUNCTION是'do_nothing',输出故意没有任何数据。这反映了节点作为结构元素而非数据处理元素的角色。 + - Comfy dtype: None + - Python dtype: None + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeSeparator: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}} + RETURN_TYPES = () + RETURN_NAMES = () + FUNCTION = 'do_nothing' + CATEGORY = UI.CATEGORY_UI + + def do_nothing(self): + return () +``` \ No newline at end of file diff --git a/docs/SeargeStylePreprocessor.md b/docs/SeargeStylePreprocessor.md new file mode 100644 index 0000000..ac3ece8 --- /dev/null +++ b/docs/SeargeStylePreprocessor.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: SeargeStylePreprocessor +- Category: Searge/_deprecated_/UI +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeStylePreprocessor旨在处理和操作处理流程中与风格相关的输入,确保风格信息被正确解释并为后续阶段准备好。 + +# Input types +## Required +- inputs + - 该参数是预处理操作的主要数据来源。它包含各种对节点正常运行和产生有意义结果至关重要的输入。 + - Comfy dtype: DICT[str, Any] + - Python dtype: Dict[str, Any] +- active_style_name + - 该参数对于在输入集中识别活动风格至关重要。它通过指定应应用哪些风格定义来指导预处理。 + - Comfy dtype: STRING + - Python dtype: str +- style_definitions + - 该参数包含可能在预处理中使用的各种风格的的定义。它对节点很重要,因为它决定了风格如何被解释和转换。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- inputs + - 处理后的输入以正确准备和结构化的风格信息返回,允许无缝集成到处理流水线的下一个阶段。 + - Comfy dtype: DICT[str, Any] + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeStylePreprocessor: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'inputs': ('PARAMETER_INPUTS',), 'active_style_name': ('STRING', {'multiline': False, 'default': ''}), 'style_definitions': ('STRING', {'multiline': True, 'default': '[unfinished work in progress]'})}} + RETURN_TYPES = ('PARAMETER_INPUTS',) + RETURN_NAMES = ('inputs',) + FUNCTION = 'process' + CATEGORY = 'Searge/_deprecated_/UI' + + def process(self, inputs, active_style_name, style_definitions): + if inputs is None: + inputs = {} + style_template = inputs['style_template'] + if style_template is None or style_template != SeargeParameterProcessor.STYLE_TEMPLATE[1]: + return (inputs,) + return (inputs,) +``` \ No newline at end of file diff --git a/docs/SeargeTextInputV2.md b/docs/SeargeTextInputV2.md new file mode 100644 index 0000000..44a34e1 --- /dev/null +++ b/docs/SeargeTextInputV2.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: SeargeTextInputV2 +- Category: UI_PROMPTING +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点便于系统从用户那里收集文本输入,支持系统内的交互式通信。它旨在向用户提出问题并捕获他们的回应,作为用户参与和数据收集的基本组件。 + +# Input types +## Required +- prompt + - 提示参数至关重要,因为它定义了向用户展示的问题或陈述,引导他们的输入。它是节点与用户交流的主要方式,影响着收集到的回应的性质和质量。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- prompt_text + - 输出代表了用户对提示的回应,这是进一步处理或分析的宝贵信息源。它是用户输入的直接反映,标志着交互的成功。 + - Comfy dtype: SRG_PROMPT_TEXT + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeTextInputV2: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompt': ('STRING', {'default': '', 'multiline': True})}} + RETURN_TYPES = ('SRG_PROMPT_TEXT',) + RETURN_NAMES = ('prompt_text',) + FUNCTION = 'get_value' + CATEGORY = UI.CATEGORY_UI_PROMPTING + + def get_value(self, prompt): + return (prompt,) +``` \ No newline at end of file diff --git a/docs/SeargeUpscaleModelLoader.md b/docs/SeargeUpscaleModelLoader.md new file mode 100644 index 0000000..ee744f6 --- /dev/null +++ b/docs/SeargeUpscaleModelLoader.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: SeargeUpscaleModelLoader +- Category: Searge/_deprecated_/Files +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +SeargeUpscaleModelLoader节点旨在简化图像增强任务中放大器模型的加载过程。它抽象了模型加载的复杂性,使得在更大的工作流程中无缝集成上采样功能成为可能。对于需要高质量图像缩放而不深入模型处理细节的应用来说,这个节点至关重要。 + +# Input types +## Required +- upscaler_name + - 参数'upscaler_name'对于识别要加载的特定放大器模型至关重要。它在节点的操作中起着核心作用,因为它决定了将使用哪个模型进行图像上采样,直接影响输出的质量和特性。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- UPSCALE_MODEL + - 'UPSCALE_MODEL'输出代表已加载的放大器模型,是后续图像处理任务的基本组成部分。它封装了模型的架构和学习到的参数,准备根据工作流程的要求应用于图像上采样。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeUpscaleModelLoader: + + def __init__(self): + self.upscale_model_loader = comfy_extras.nodes_upscale_model.UpscaleModelLoader() + + @classmethod + def INPUT_TYPES(s): + return {'required': {'upscaler_name': ('UPSCALER_NAME',)}} + RETURN_TYPES = ('UPSCALE_MODEL',) + FUNCTION = 'load_upscaler' + CATEGORY = 'Searge/_deprecated_/Files' + + def load_upscaler(self, upscaler_name): + return self.upscale_model_loader.load_model(upscaler_name) +``` \ No newline at end of file diff --git a/docs/SeargeUpscaleModels.md b/docs/SeargeUpscaleModels.md new file mode 100644 index 0000000..4ca1e51 --- /dev/null +++ b/docs/SeargeUpscaleModels.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: SeargeUpscaleModels +- Category: UI_INPUTS +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点负责协调选择和配置图像增强的放大模型,重点是整合各种放大器以实现期望的输出质量。 + +# Input types +## Required +- detail_processor + - 细节处理器对于提高图像质量至关重要,在整体放大过程中发挥关键作用。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- high_res_upscaler + - 高分辨率放大器对于提高图像分辨率至关重要,对最终视觉效果有显著贡献。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- primary_upscaler + - 主要放大器在初始缩放阶段非常关键,为进一步增强设定基础。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- secondary_upscaler + - 次要放大器在主要缩放后进一步细化图像,改善细节和清晰度。 + - Comfy dtype: COMBO[str] + - Python dtype: str + +# Output types +- data + - 输出数据封装了放大模型的配置,对于后续处理和最终图像输出至关重要。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeUpscaleModels: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'detail_processor': (UI.UPSCALERS_1x_WITH_NONE(),), 'high_res_upscaler': (UI.UPSCALERS_4x_WITH_NONE(),), 'primary_upscaler': (UI.UPSCALERS_4x_WITH_NONE(),), 'secondary_upscaler': (UI.UPSCALERS_4x_WITH_NONE(),)}, 'optional': {'data': ('SRG_DATA_STREAM',)}} + RETURN_TYPES = ('SRG_DATA_STREAM',) + RETURN_NAMES = ('data',) + FUNCTION = 'get' + CATEGORY = UI.CATEGORY_UI_INPUTS + + @staticmethod + def create_dict(detail_processor, high_res_upscaler, primary_upscaler, secondary_upscaler): + return {UI.F_DETAIL_PROCESSOR: detail_processor, UI.F_HIGH_RES_UPSCALER: high_res_upscaler, UI.F_PRIMARY_UPSCALER: primary_upscaler, UI.F_SECONDARY_UPSCALER: secondary_upscaler} + + def get(self, detail_processor, high_res_upscaler, primary_upscaler, secondary_upscaler, data=None): + if data is None: + data = {} + data[UI.S_UPSCALE_MODELS] = self.create_dict(detail_processor, high_res_upscaler, primary_upscaler, secondary_upscaler) + return (data,) +``` \ No newline at end of file diff --git a/docs/SeargeVAELoader.md b/docs/SeargeVAELoader.md new file mode 100644 index 0000000..077b833 --- /dev/null +++ b/docs/SeargeVAELoader.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: SeargeVAELoader +- Category: Searge/_deprecated_/Files +- Output node: False +- Repo Ref: https://github.com/jobunk/SeargeSDXL.git + +该节点旨在方便地加载VAE(变分自编码器)模型,为在工作流中访问和使用这些机器学习模型提供简化的接口。它抽象了模型检索的复杂性,确保VAE模型可以无缝集成到系统中,而无需详细了解底层的存储和加载机制。 + +# Input types +## Required +- vae_name + - ‘vae_name’参数对于指定要加载的VAE模型的唯一标识符至关重要。它作为从存储系统中定位和检索相应模型的键,其正确使用确保了预期VAE模型的准确和高效加载。 + - Comfy dtype: COMBO['VAE_NAME'] + - Python dtype: str + +# Output types +- VAE + - 输出VAE代表加载的变分自编码器模型,随后可以用于各种任务,如数据生成、特征提取等。它是模型加载过程成功的标志,对于工作流中进一步操作至关重要。 + - Comfy dtype: VAE + - Python dtype: nodes.VAE + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeargeVAELoader: + + def __init__(self): + self.vae_loader = nodes.VAELoader() + + @classmethod + def INPUT_TYPES(s): + return {'required': {'vae_name': ('VAE_NAME',)}} + RETURN_TYPES = ('VAE',) + FUNCTION = 'load_vae' + CATEGORY = 'Searge/_deprecated_/Files' + + def load_vae(self, vae_name): + return self.vae_loader.load_vae(vae_name) +``` \ No newline at end of file diff --git a/docs/Seed Everywhere.md b/docs/Seed Everywhere.md new file mode 100644 index 0000000..3d9e947 --- /dev/null +++ b/docs/Seed Everywhere.md @@ -0,0 +1,42 @@ +# Documentation +- Class name: SeedEverywhere +- Category: Initialization +- Output node: True +- Repo Ref: https://github.com/chrisgoringe/cg-use-everywhere + +SeedEverywhere节点旨在确保系统不同部分的随机操作的可重复性。它通过为随机数生成器设置种子来实现这一点,这对于需要一致结果的科学实验和模拟至关重要。 + +# Input types +## Required +- seed + - “seed”参数对于将随机数生成器初始化为已知状态至关重要。这确保了每次执行节点时,随后的随机操作将产生相同的结果,这对于在各种应用中获得一致和可比较的结果至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- id + - “id”参数虽然不是必需的,但作为节点发送的消息的标识符。在同时运行节点的多个实例的系统中,这可能特别有用,因为它有助于跟踪和管理来自不同实例的消息。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- seed + - 输出的“seed”与提供给节点的输入相同,表示节点执行后随机数生成器的状态。这可以用于需要一致随机状态的进一步操作,确保随机过程的连续性。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeedEverywhere(Base): + + @classmethod + def INPUT_TYPES(s): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'id': 'UNIQUE_ID'}} + RETURN_TYPES = ('INT',) + + def func(self, seed, id): + message(id, seed) + return (seed,) +``` \ No newline at end of file diff --git a/docs/Seed String.md b/docs/Seed String.md new file mode 100644 index 0000000..c236d2a --- /dev/null +++ b/docs/Seed String.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: IntegerAndString +- Category: Mikey/Utils +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +IntegerAndString节点旨在将整数输入转换为其对应的字符串表示形式。它强调将数值数据转换为更易于人类阅读的格式的实用性,便于进行需要字符串操作或数值与文本数据之间交互的操作。 + +# Input types +## Required +- seed + - 参数'seed'对节点至关重要,因为它是将被转换成字符串的初始整数值。它在确定输出中起着关键作用,因为节点的功能围绕这个转换过程展开。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- seed + - 输出参数'seed'代表提供给节点的原始整数值。它标志着整数值在节点操作过程中的连续性,确保初始数值输入被保留。 + - Comfy dtype: INT + - Python dtype: int +- seed_string + - 输出参数'seed_string'是输入整数的字符串表示。它突出了节点的主要转换功能,展示了将数值数据转换为更易访问的文本格式的结果。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class IntegerAndString: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('INT', 'STRING') + RETURN_NAMES = ('seed', 'seed_string') + FUNCTION = 'output' + CATEGORY = 'Mikey/Utils' + + def output(self, seed): + seed_string = str(seed) + return (seed, seed_string) +``` \ No newline at end of file diff --git a/docs/Seed and Int (WLSH).md b/docs/Seed and Int (WLSH).md new file mode 100644 index 0000000..5f91220 --- /dev/null +++ b/docs/Seed and Int (WLSH).md @@ -0,0 +1,45 @@ +# Documentation +- Class name: WLSH_Seed_and_Int +- Category: WLSH Nodes/number +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点根据给定的种子生成一个种子和整数值的配对,于在系统中创建和管理唯一标识符。 + +# Input types +## Required +- seed + - 种子是启动生成唯一整数过程的基本参数。它对于确保结果的一致性和可重复性至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- seed + - 输出种子是原始输入种子,标志着其在操作中作为标识符的角色。整型输出是种子的转换,表明其在过程中的重要性。 + - Comfy dtype: INT + - Python dtype: int +- int_representation + - 整型表示是从输入种子派生出来的,作为节点功能中不可或缺的唯一输出。 + - Comfy dtype: SEED + - Python dtype: Dict[str, int] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Seed_and_Int: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('INT', 'SEED') + FUNCTION = 'seed_and_int' + CATEGORY = 'WLSH Nodes/number' + + def seed_and_int(self, seed): + return (seed, {'seed': seed}) +``` \ No newline at end of file diff --git a/docs/Seed to Number (WLSH).md b/docs/Seed to Number (WLSH).md new file mode 100644 index 0000000..38c017d --- /dev/null +++ b/docs/Seed to Number (WLSH).md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WLSH_Seed_to_Number +- Category: WLSH Nodes/number +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点旨在将输入数据转换为数字表示,便于在系统内处理和分析数据。 + +# Input types +## Required +- seed + - 种子参数至关重要,因为它提供了节点执行转换功能所必需的原始数据。 + - Comfy dtype: SEED + - Python dtype: Dict[str, Any] + +# Output types +- number + - 输出是从输入派生的数字表示,这对于系统内进一步的计算过程至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Seed_to_Number: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'seed': ('SEED',)}} + RETURN_TYPES = ('INT',) + FUNCTION = 'number_to_seed' + CATEGORY = 'WLSH Nodes/number' + + def number_to_seed(self, seed): + return (int(seed['seed']),) +``` \ No newline at end of file diff --git a/docs/Seed.md b/docs/Seed.md new file mode 100644 index 0000000..1d64df1 --- /dev/null +++ b/docs/Seed.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: WAS_Seed +- Category: WAS Suite/Number +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Seed 节点旨在生成和操作数值种子,这些种子对于初始化随机数生成器或确保随机过程中的可重复性至关重要。它在数值操作中提供了基础性的作用,其中种子值对于控制随机性是必不可少的。 + +# Input types +## Required +- seed + - ‘seed’参数对于节点的操作至关重要,因为它决定了生成一系列数字的起始点。它确保了随机数生成过程的可预测性和可重复性,这在模拟和概率模型中非常重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- seed + - ‘seed’输出代表了提供给节点的原始数值种子,它是依赖于随机数生成的后续操作的基本组成部分。 + - Comfy dtype: INT + - Python dtype: int +- number + - ‘number’输出是种子的小数点表示形式,它可以用于需要非整数值的计算中,扩大了节点在各种数学情境中的应用性。 + - Comfy dtype: FLOAT + - Python dtype: float +- float + - ‘float’输出是将种子值转换为浮点数,这对于需要小数精度的操作至关重要,例如科学计算和统计分析。 + - Comfy dtype: FLOAT + - Python dtype: float +- int + - ‘int’输出提供了种子值的整数形式,适用于仅接受整数输入的操作,确保与广泛的数值算法和应用兼容。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Seed: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('SEED', 'NUMBER', 'FLOAT', 'INT') + RETURN_NAMES = ('seed', 'number', 'float', 'int') + FUNCTION = 'seed' + CATEGORY = 'WAS Suite/Number' + + def seed(self, seed): + return ({'seed': seed}, seed, float(seed), int(seed)) +``` \ No newline at end of file diff --git a/docs/SeedExplorer %2F%2FInspire.md b/docs/SeedExplorer %2F%2FInspire.md new file mode 100644 index 0000000..75affa2 --- /dev/null +++ b/docs/SeedExplorer %2F%2FInspire.md @@ -0,0 +1,106 @@ +# Documentation +- Class name: SeedExplorer +- Category: InspirePack/Prompt +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +SeedExplorer是一个旨在根据提供的种子和附加参数操作和生成噪声模式的节点,旨在在噪声生成任务中激发和促进创造性过程。 + +# Input types +## Required +- latent + - 潜在变量对于SeedExplorer节点至关重要,因为它为噪声生成提供了基础结构,影响了输出的整体质量和特性。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- seed_prompt + - 种子提示对于指导噪声生成过程至关重要,允许用户将特定的模式或风格注入到输出中。 + - Comfy dtype: STRING + - Python dtype: str +- enable_additional + - enable_additional参数决定是否应用额外的种子变化,这可以为生成的噪声引入多样性和复杂性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- noise_mode + - noise_mode参数决定了用于噪声生成的计算资源,对于密集型任务推荐使用GPU,对于需求较低的操作使用CPU。 + - Comfy dtype: COMBO + - Python dtype: str +- initial_batch_seed_mode + - 该参数控制初始噪声批次的种子模式,可能会影响生成的噪声模式的整体一致性和连贯性。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- additional_seed + - 额外的种子参数在使用时,为噪声引入了额外的变化层,有助于最终输出的多样性。 + - Comfy dtype: INT + - Python dtype: int +- additional_strength + - 额外的强度参数调整了额外种子的影响,允许微调噪声变化的强度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- noise + - 输出噪声代表噪声生成程的最终结果,包含了应用的创意输入和参数。 + - Comfy dtype: NOISE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SeedExplorer: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latent': ('LATENT',), 'seed_prompt': ('STRING', {'multiline': True, 'dynamicPrompts': False, 'pysssss.autocomplete': False}), 'enable_additional': ('BOOLEAN', {'default': True, 'label_on': 'true', 'label_off': 'false'}), 'additional_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'additional_strength': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'noise_mode': (['GPU(=A1111)', 'CPU'],), 'initial_batch_seed_mode': (['incremental', 'comfy'],)}} + RETURN_TYPES = ('NOISE',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Prompt' + + @staticmethod + def apply_variation(start_noise, seed_items, noise_device, mask=None): + noise = start_noise + for x in seed_items: + if isinstance(x, str): + item = x.split(':') + else: + item = x + if len(item) == 2: + try: + variation_seed = int(item[0]) + variation_strength = float(item[1]) + noise = utils.apply_variation_noise(noise, noise_device, variation_seed, variation_strength, mask=mask) + except Exception: + print(f"[ERROR] IGNORED: SeedExplorer failed to processing '{x}'") + traceback.print_exc() + return noise + + def doit(self, latent, seed_prompt, enable_additional, additional_seed, additional_strength, noise_mode, initial_batch_seed_mode): + latent_image = latent['samples'] + device = comfy.model_management.get_torch_device() + noise_device = 'cpu' if noise_mode == 'CPU' else device + seed_prompt = seed_prompt.replace('\n', '') + items = seed_prompt.strip().split(',') + if items == ['']: + items = [] + if enable_additional: + items.append((additional_seed, additional_strength)) + try: + hd = items[0] + tl = items[1:] + if isinstance(hd, tuple): + hd_seed = int(hd[0]) + else: + hd_seed = int(hd) + noise = utils.prepare_noise(latent_image, hd_seed, None, noise_device, initial_batch_seed_mode) + noise = noise.to(device) + noise = SeedExplorer.apply_variation(noise, tl, noise_device) + noise = noise.cpu() + return (noise,) + except Exception: + print(f'[ERROR] IGNORED: SeedExplorer failed') + traceback.print_exc() + noise = torch.zeros(latent_image.size(), dtype=latent_image.dtype, layout=latent_image.layout, device=noise_device) + return (noise,) +``` \ No newline at end of file diff --git a/docs/Seed_.md b/docs/Seed_.md new file mode 100644 index 0000000..67a4e9d --- /dev/null +++ b/docs/Seed_.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: CreateSeedNode +- Category: ♾️Mixlab/Utils +- Output node: True +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点用于生成用于各种随机化过程的种子值,确保随机性在需要时可以控制和复制。 + +# Input types +## Required +- seed + - 种子参数对于初始化随机数生成器至关重要,可以在随机过程中产生可重复和可预测的结果。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- seed + - 输出的种子值作为初始化的随机化过程的参考,指示从中派生随机性的特定状态。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class CreateSeedNode: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('seed',) + OUTPUT_NODE = True + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Utils' + + def run(self, seed): + return (seed,) +``` \ No newline at end of file diff --git a/docs/SegmDetectorCombined_v2.md b/docs/SegmDetectorCombined_v2.md new file mode 100644 index 0000000..ca87a7e --- /dev/null +++ b/docs/SegmDetectorCombined_v2.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: SegmDetectorCombined +- Category: ImpactPack/Detector +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SegmDetectorCombined节点旨在无缝集成分割和检测功能。它利用分割检测器处理图像并生成一个二进制掩码,以区分图像中的感兴趣对象和背景。此节点对于需要精确定位和分割的应用至关重要,例如在自动驾驶系统或医学成像中。 + +# Input types +## Required +- segm_detector + - segm_detector参数至关重要,因为它代表了执行分割和检测任务的核心模型。它对节点的运行至关重要,因为它直接影响生成的掩码的质量和准确性。 + - Comfy dtype: SEGM_DETECTOR + - Python dtype: torch.nn.Module +- image + - image参数是节点处理的输入。它是一个基本组件,因为节点的所有操作都围绕着分析和操作这张图像以产生所需的掩码。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- threshold + - threshold参数用于控制检测的灵敏度。它在确定哪些对象被识别并包含在最终掩码中起着重要作用,因此影响节点的输出。 + - Comfy dtype: FLOAT + - Python dtype: float +- dilation + - dilation参数允许扩展检测到的对象边界。它在细化掩码边缘方面很重要,特别是在精确边界划分不太关键的场景中特别有用。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MASK + - MASK输出是SegmDetectorCombined节点的主要结果。它是一个二进制掩码,标志着将感兴趣对象从图像的其余部分分割出来,这对于下游处理任务至关重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SegmDetectorCombined: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segm_detector': ('SEGM_DETECTOR',), 'image': ('IMAGE',), 'threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'dilation': ('INT', {'default': 0, 'min': -512, 'max': 512, 'step': 1})}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detector' + + def doit(self, segm_detector, image, threshold, dilation): + mask = segm_detector.detect_combined(image, threshold, dilation) + if mask is None: + mask = torch.zeros((image.shape[2], image.shape[1]), dtype=torch.float32, device='cpu') + return (mask.unsqueeze(0),) +``` \ No newline at end of file diff --git a/docs/SegmDetectorSEGS.md b/docs/SegmDetectorSEGS.md new file mode 100644 index 0000000..3dc7589 --- /dev/null +++ b/docs/SegmDetectorSEGS.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: SegmDetectorForEach +- Category: ImpactPack/Detector +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SegmDetectorForEach节点旨在对图像进行分割检测处理和分析。它应用一个分割模型来识别图像中的不同区域,并遵循特定的检测置信度阈值。该节点能够处理各种参数,如膨胀、裁剪因子和下采样大小,以优化检测过程。它还允许基于标签列表过滤检测到的段,增强了其在目标分析场景中的实用性。 + +# Input types +## Required +- segm_detector + - segm_detector参数对节点的操作至关重要,因为它定义了将用于分析输入图像的分割模型。它在检测过程中起着核心作用,直接影响分割结果的准确性和质量。 + - Comfy dtype: SEGM_DETECTOR + - Python dtype: torch.nn.Module +- image + - 图像输入对于SegmDetectorForEach节点至关重要,因为它是分割检测的主要数据源。图像的质量和分辨率直接影响节点准确检测和分割图像内不同区域的能力。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- threshold + - 阈值参数对于控制分割模型的检测灵敏度非常重要。它决定了将一个段视为已检测所需的最小置信度水平,从而影响节点的输出。 + - Comfy dtype: FLOAT + - Python dtype: float +- dilation + - 膨胀参数对于后处理检测到的段很重要。它控制应用于段的形态学膨胀的程度,这有助于细化边界并提高整体分割质量。 + - Comfy dtype: INT + - Python dtype: int +- crop_factor + - crop_factor参数用于在分割模型处理之前调整图像的大小。它可以帮助聚焦于图像内的特定感兴趣区域,并提高检测精度。 + - Comfy dtype: FLOAT + - Python dtype: float +- drop_size + - drop_size参数与控制分割模型运行的分辨率有关。它可以用来平衡处理速度和分割结果中的细节水平。 + - Comfy dtype: INT + - Python dtype: int +- labels + - labels参数允许基于指定的段类型列表过滤检测到的段。当分析需要聚焦于特定感兴趣的段时,它特别有用。 + - Comfy dtype: STRING + - Python dtype: str +- detailer_hook + - detailer_hook参数提供了一种定制检测过程的机制。它允许集成特定于用户需求的额外功能或后处理步骤。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: Callable + +# Output types +- segs + - 输出的segs参数代表从输入图像中检测到的段。它是分段区域的集合,每个区域都有自己的属性和标签,提供了对图像内容的详细分析。 + - Comfy dtype: SEGS + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SegmDetectorForEach: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segm_detector': ('SEGM_DETECTOR',), 'image': ('IMAGE',), 'threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'dilation': ('INT', {'default': 10, 'min': -512, 'max': 512, 'step': 1}), 'crop_factor': ('FLOAT', {'default': 3.0, 'min': 1.0, 'max': 100, 'step': 0.1}), 'drop_size': ('INT', {'min': 1, 'max': MAX_RESOLUTION, 'step': 1, 'default': 10}), 'labels': ('STRING', {'multiline': True, 'default': 'all', 'placeholder': 'List the types of segments to be allowed, separated by commas'})}, 'optional': {'detailer_hook': ('DETAILER_HOOK',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detector' + + def doit(self, segm_detector, image, threshold, dilation, crop_factor, drop_size, labels=None, detailer_hook=None): + if len(image) > 1: + raise Exception('[Impact Pack] ERROR: SegmDetectorForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.') + segs = segm_detector.detect(image, threshold, dilation, crop_factor, drop_size, detailer_hook) + if labels is not None and labels != '': + labels = labels.split(',') + if len(labels) > 0: + (segs, _) = segs_nodes.SEGSLabelFilter.filter(segs, labels) + return (segs,) +``` \ No newline at end of file diff --git a/docs/SegsToCombinedMask.md b/docs/SegsToCombinedMask.md new file mode 100644 index 0000000..727e61d --- /dev/null +++ b/docs/SegsToCombinedMask.md @@ -0,0 +1,40 @@ +# Documentation +- Class name: SegsToCombinedMask +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +‘SegsToCombinedMask’节点旨在将多个分割合并为一个单一的掩码。它通过将各个分割组合成一个全面的二进制掩码来操作,该掩码可以用于进一步的分析或可视化。在需要统一表示分割区域的应用中,例如医学成像或自动驾驶车辆感知系统中,此节点至关重要。 + +# Input types +## Required +- segs + - ‘segs’参数是节点将处理的分割对象集合,以创建一个组合掩码。它对节点的操作至关重要,因为它直接影响输出掩码的组成。每个分割对象应包含一个裁剪掩码和一个裁剪区域,这些用于确定掩码在最终组合掩码中的位置。 + - Comfy dtype: COMBO[torch.Tensor] + - Python dtype: List[core.SEG] + +# Output types +- mask + - ‘mask’输出是一个3D二进制张量,代表由输入分割组合而成的组合掩码。它很重要,因为它将集体分割封装在一个单一、连贯的结构中,可以用于下游任务,如目标检测或分割分析。 + - Comfy dtype: torch.Tensor + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SegsToCombinedMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',)}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, segs): + mask = core.segs_to_combined_mask(segs) + mask = utils.make_3d_mask(mask) + return (mask,) +``` \ No newline at end of file diff --git a/docs/Select Image Indices.md b/docs/Select Image Indices.md new file mode 100644 index 0000000..e4145af --- /dev/null +++ b/docs/Select Image Indices.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: ImageSelector +- Category: motionctrl +- Output node: False +- Repo Ref: https://github.com/chaojie/ComfyUI-MotionCtrl.git + +ImageSelector节点根据指定的索引筛选图像,确保只有所需的图像子集被进一步处理,提高了图像处理任务的效率和专注度。 + +# Input types +## Required +- images + - images参数至关重要,它作为ImageSelector节点的主要输入,决定了将从中进行选择的数据集。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- selected_indexes + - 该参数允许用户定义他们希望选择的图像的特定索引,直接影响通过节点进行后续操作的图像。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- selected_images + - selected_images输出代表基于提供的索引过滤后的图像子集,现已准备好进行进一步的处理或分析。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageSelector: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'selected_indexes': ('STRING', {'multiline': False, 'default': '1,2,3'})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'run' + OUTPUT_NODE = False + CATEGORY = 'motionctrl' + + def run(self, images: torch.Tensor, selected_indexes: str): + shape = images.shape + len_first_dim = shape[0] + selected_index: list[int] = [] + total_indexes: list[int] = list(range(len_first_dim)) + for s in selected_indexes.strip().split(','): + try: + if ':' in s: + _li = s.strip().split(':', maxsplit=1) + _start = _li[0] + _end = _li[1] + if _start and _end: + selected_index.extend(total_indexes[int(_start):int(_end)]) + elif _start: + selected_index.extend(total_indexes[int(_start):]) + elif _end: + selected_index.extend(total_indexes[:int(_end)]) + else: + x: int = int(s.strip()) + if x < len_first_dim: + selected_index.append(x) + except: + pass + if selected_index: + print(f'ImageSelector: selected: {len(selected_index)} images') + return (images[selected_index, :, :, :],) + print(f'ImageSelector: selected no images, passthrough') + return (images,) +``` \ No newline at end of file diff --git a/docs/Separate Mask Components.md b/docs/Separate Mask Components.md new file mode 100644 index 0000000..d286de6 --- /dev/null +++ b/docs/Separate Mask Components.md @@ -0,0 +1,74 @@ +# Documentation +- Class name: SeparateMaskComponents +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +该节点旨在将单个掩码分解为其组成的连续组件。它通过对掩码应用形态学操作来识别掩码内的唯一段。该节点不仅返回分离的掩码,还提供了一个映射,可以在下游流程中使用,以将各个组件与其原始批次位置相关联。 + +# Input types +## Required +- mask + - 输入掩码是该节点的关键参数,因为它代表了要从中分离出连续组件的初始数据。掩码的结构直接影响节点的操作和结果分段。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- mask + - 输出是一系列分离的掩码,每个掩码对应输入掩码中识别出的一个独特的连续组件。这些掩码对于批处理中的进一步分析或处理至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask_mappings + - 此输出提供映射,将每个分离的掩码与其在原始批次中的相应位置相关联。它是维护整个处理流程中数据关系完整性的重要工具。 + - Comfy dtype: INT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SeparateMaskComponents: + """ + Separates a mask into multiple contiguous components. Returns the individual masks created as well as a MASK_MAPPING which can be used in other nodes when dealing with batches. + """ + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'mask': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE', 'MASK_MAPPING') + RETURN_NAMES = ('mask', 'mask_mappings') + FUNCTION = 'separate' + CATEGORY = 'Masquerade Nodes' + + def separate(self, mask): + mask = tensor2mask(mask) + thresholded = torch.gt(mask, 0).unsqueeze(1) + (B, H, W) = mask.shape + components = torch.arange(B * H * W, device=mask.device, dtype=mask.dtype).reshape(B, 1, H, W) + 1 + components[~thresholded] = 0 + while True: + previous_components = components + components = torch.nn.functional.max_pool2d(components, kernel_size=3, stride=1, padding=1) + components[~thresholded] = 0 + if torch.equal(previous_components, components): + break + components = components.reshape(B, H, W) + segments = torch.unique(components) + result = torch.zeros([len(segments) - 1, H, W]) + index = 0 + mapping = torch.zeros([len(segments) - 1], device=mask.device, dtype=torch.int) + for i in range(len(segments)): + segment = segments[i].item() + if segment == 0: + continue + image_index = int((segment - 1) // (H * W)) + segment_mask = components[image_index, :, :] == segment + result[index][segment_mask] = mask[image_index][segment_mask] + mapping[index] = image_index + index += 1 + return (result, mapping) +``` \ No newline at end of file diff --git a/docs/Sepconv VFI.md b/docs/Sepconv VFI.md new file mode 100644 index 0000000..3c4c89b --- /dev/null +++ b/docs/Sepconv VFI.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: SepconvVFI +- Category: ComfyUI-Frame-Interpolation/VFI +- Output node: False +- Repo Ref: https://github.com/Fannovel16/ComfyUI-Frame-Interpolation + +SepconvVFI节点旨在使用可分离卷积神经网络执行视频帧插值。它增强了视频序列中帧之间过渡的流畅性和平滑性,有助于在不需要大量计算开销的情况下提供更高质量的视觉体验。 + +# Input types +## Required +- ckpt_name + - 检查点名称对于加载预训练模型权重至关重要,这些权重是帧插值过程所必需的。它保模型能够生成准确和高质量的插值帧。 + - Comfy dtype: str + - Python dtype: str +- frames + - 输入帧是节点处理以创建中间帧的原始视频数据。这个输入是必不可少的,因为它构成了插值任务的基础。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- clear_cache_after_n_frames + - 此参数决定了在处理过程中多久清除一次GPU缓存以保持最佳性能。这是一个可选设置,可以帮助管理系统资源。 + - Comfy dtype: INT + - Python dtype: int +- multiplier + - 乘数影响在两个输入帧之间生成的插值帧的数量。它是一个可选参数,允许用户控制插值帧的密度。 + - Comfy dtype: INT + - Python dtype: int +- optional_interpolation_states + - 这个可选参数提供了对插值过程的额外控制,允许为每个帧定制插值状态。 + - Comfy dtype: INTERPOLATION_STATES + - Python dtype: InterpolationStateList + +# Output types +- output_frames + - output_frames参数包含节点生成的插值帧。这些帧是帧插值过程的结果,对于创建更平滑的视频过渡非常重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SepconvVFI: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (CKPT_NAMES,), 'frames': ('IMAGE',), 'clear_cache_after_n_frames': ('INT', {'default': 10, 'min': 1, 'max': 1000}), 'multiplier': ('INT', {'default': 2, 'min': 2, 'max': 1000})}, 'optional': {'optional_interpolation_states': ('INTERPOLATION_STATES',)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'vfi' + CATEGORY = 'ComfyUI-Frame-Interpolation/VFI' + + def vfi(self, ckpt_name: typing.AnyStr, frames: torch.Tensor, clear_cache_after_n_frames=10, multiplier: typing.SupportsInt=2, optional_interpolation_states: InterpolationStateList=None, **kwargs): + from .sepconv_enhanced import Network + model_path = load_file_from_github_release(MODEL_TYPE, ckpt_name) + interpolation_model = Network() + interpolation_model.load_state_dict(torch.load(model_path)) + interpolation_model.eval().to(get_torch_device()) + frames = preprocess_frames(frames) + + def return_middle_frame(frame_0, frame_1, timestep, model): + return model(frame_0, frame_1) + args = [interpolation_model] + out = postprocess_frames(generic_frame_loop(frames, clear_cache_after_n_frames, multiplier, return_middle_frame, *args, interpolation_states=optional_interpolation_states, use_timestep=False, dtype=torch.float32)) + return (out,) +``` \ No newline at end of file diff --git a/docs/SetDefaultImageForSEGS.md b/docs/SetDefaultImageForSEGS.md new file mode 100644 index 0000000..f47f154 --- /dev/null +++ b/docs/SetDefaultImageForSEGS.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: DefaultImageForSEGS +- Category: ImpactPack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +DefaultImageForSEGS节点的'doit'方法旨在通过将分割(SEGS)缩放到与给定图像的尺寸相匹配来处理分割。它还提供了一个选项,允许使用基于分割的裁剪区域的新裁剪图像覆盖现有的裁剪图像。此方法对于准备进一步分析或可视化的分割数据至关重要。 + +# Input types +## Required +- segs + - 'segs'参数是节点将处理的分割对象集合。它对节点的操作至关重要,因为它决定了将被缩放并可能覆盖其裁剪图像的数据。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +- image + - 'image'参数表示将对分割进行缩放的参考图像。它是一个关键输入,因为它决定了分割数据必须匹配的尺寸以进行下游处理。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- override + - 'override'参数是一个布尔标志,当设置为True时,指示节点为分割生成新的裁剪图像,忽略任何现有的裁剪图像。这对于根据更新的分割数据刷新裁剪图像非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- segs + - 输出'segs'包含处理过的分割对象。每个对象都已缩放到与输入图像的尺寸相匹配,并且如果'override'参数设置为True,则可能已覆盖其裁剪图像。 + - Comfy dtype: SEGS + - Python dtype: Tuple[List[SEG], List[SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DefaultImageForSEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'segs': ('SEGS',), 'image': ('IMAGE',), 'override': ('BOOLEAN', {'default': True})}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Util' + + def doit(self, segs, image, override): + results = [] + segs = core.segs_scale_match(segs, image.shape) + if len(segs[1]) > 0: + if segs[1][0].cropped_image is not None: + batch_count = len(segs[1][0].cropped_image) + else: + batch_count = len(image) + for seg in segs[1]: + if seg.cropped_image is not None and (not override): + cropped_image = seg.cropped_image + else: + cropped_image = None + for i in range(0, batch_count): + ref_image = image[i].unsqueeze(0) + cropped_image2 = crop_image(ref_image, seg.crop_region) + if cropped_image is None: + cropped_image = cropped_image2 + else: + cropped_image = torch.cat((cropped_image, cropped_image2), dim=0) + new_seg = SEG(cropped_image, seg.cropped_mask, seg.confidence, seg.crop_region, seg.bbox, seg.label, seg.control_net_wrapper) + results.append(new_seg) + return ((segs[0], results),) + else: + return (segs,) +``` \ No newline at end of file diff --git a/docs/Sharpen (mtb).md b/docs/Sharpen (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Sharpen.md b/docs/Sharpen.md new file mode 100644 index 0000000..ae71459 --- /dev/null +++ b/docs/Sharpen.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: Sharpen +- Category: postprocessing/Filters +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +锐化节点通过增强局部对比度来提高图像清晰度。它将锐化核应用于输入图像,放大边缘和细微细节,从而产生更明确和清晰的视觉效果。 + +# Input types +## Required +- image + - 图像参数是锐化节点的主要输入,对于节点来说至关重要。它决定了将要进行锐化处理的源材料,影响最终输出的质量和清晰度。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- sharpen_radius + - 锐化半径参数控制锐化效果的程度。较大的半径会导致更明显的锐化效果,更积极地增强边缘和细节,而较小的半径则产生更微妙的效果。 + - Comfy dtype: INT + - Python dtype: int +- alpha + - alpha参数调整锐化效果的强度。较高的alpha值增加了对比度增强,导致更戏剧性的锐化,而较低的值则产生较轻微的效果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- result + - 结果参数是锐化节点的输出,代表锐化后的图像。它反映了锐化效果的应用,展示了提高的清晰度和定义明确的边缘。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Sharpen: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'sharpen_radius': ('INT', {'default': 1, 'min': 1, 'max': 15, 'step': 1}), 'alpha': ('FLOAT', {'default': 1.0, 'min': 0.1, 'max': 5.0, 'step': 0.1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'sharpen' + CATEGORY = 'postprocessing/Filters' + + def sharpen(self, image: torch.Tensor, blur_radius: int, alpha: float): + if blur_radius == 0: + return (image,) + (batch_size, height, width, channels) = image.shape + kernel_size = blur_radius * 2 + 1 + kernel = torch.ones((kernel_size, kernel_size), dtype=torch.float32) * -1 + center = kernel_size // 2 + kernel[center, center] = kernel_size ** 2 + kernel *= alpha + kernel = kernel.repeat(channels, 1, 1).unsqueeze(1) + tensor_image = image.permute(0, 3, 1, 2) + sharpened = F.conv2d(tensor_image, kernel, padding=center, groups=channels) + sharpened = sharpened.permute(0, 2, 3, 1) + result = torch.clamp(sharpened, 0, 1) + return (result,) +``` \ No newline at end of file diff --git a/docs/ShowCachedInfo %2F%2FInspire.md b/docs/ShowCachedInfo %2F%2FInspire.md new file mode 100644 index 0000000..62ff024 --- /dev/null +++ b/docs/ShowCachedInfo %2F%2FInspire.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: ShowCachedInfo +- Category: InspirePack/Backend +- Output node: True +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在展示缓存信息,通过将缓存内容按字符串和数字键分类,提供清晰有序的视图。 + +# Input types +## Required +- cache_info + - cache_info参数是缓存的文本表示,节点将对其进行格式化和展示。这对节点的运行至关重要,因为它决定了展示给用户的内容。 + - Comfy dtype: STRING + - Python dtype: str +- unique_id + - unique_id参数在系统内唯一标识节点实例,确保为预期的用户显示正确的缓存信息。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +## Optional +- key + - key参数用于根据特定键过滤缓存信息。它的重要性在于允许用户专注于特定的缓存条目。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- feedback + - feedback参数包含有关节点操作和显示的缓存数据的信息。它的重要性在于提供了节点执行的记录。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ShowCachedInfo: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'cache_info': ('STRING', {'multiline': True, 'default': ''}), 'key': ('STRING', {'multiline': False, 'default': ''})}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = () + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Backend' + OUTPUT_NODE = True + + @staticmethod + def get_data(): + global cache + text1 = '---- [String Key Caches] ----\n' + text2 = '---- [Number Key Caches] ----\n' + for (k, v) in cache.items(): + if v[0] == '': + tag = 'N/A(tag)' + else: + tag = v[0] + if isinstance(k, str): + text1 += f'{k}: {tag}\n' + else: + text2 += f'{k}: {tag}\n' + return text1 + '\n' + text2 + + def doit(self, cache_info, key, unique_id): + text = ShowCachedInfo.get_data() + PromptServer.instance.send_sync('inspire-node-feedback', {'node_id': unique_id, 'widget_name': 'cache_info', 'type': 'text', 'data': text}) + return {} + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') +``` \ No newline at end of file diff --git a/docs/ShowLayer.md b/docs/ShowLayer.md new file mode 100644 index 0000000..c3104c0 --- /dev/null +++ b/docs/ShowLayer.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: ShowLayer +- Category: ♾️Mixlab/Layer +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +ShowLayer 类旨在在复合结构中管理和显示视觉元素。它专注于根据提供的参数定位和缩放图层,使得能够创建复杂的视觉组合。 + +# Input types +## Required +- edit + - ‘edit’参数对于确定ShowLayer类的操作方法至关重要。它决定了函数是编辑现有的视觉元素还是在组合中创建新的元素。 + - Comfy dtype: EDIT + - Python dtype: PIL.Image.Image +- x + - ‘x’参数指定视觉元素在组合中水平位置。对于正确对齐图层和实现期望的视觉效果至关重要。 + - Comfy dtype: INT + - Python dtype: int +- y + - ‘y’参数定义了视觉元素的垂直位置,与‘x’参数协同工作,以确立图层在视觉组合中的确切位置。 + - Comfy dtype: INT + - Python dtype: int +- width + - ‘width’参数在确定视觉元素的水平维度方面至关重要。它影响组合的整体比例和布局,确保元素的大小和间距适当。 + - Comfy dtype: INT + - Python dtype: int +- height + - ‘height’参数对应于视觉元素的垂直维度,与‘width’参数相辅相成,控制组合中视觉元素的大小。 + - Comfy dtype: INT + - Python dtype: int +- z_index + - ‘z_index’参数建立了视觉元素的堆叠顺序。在创建层叠效果方面至关重要,其中‘z_index’值较高的元素显示在值较低的元素上方。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- scale_option + - ‘scale_option’参数提供了视觉元素如何缩放的灵活性。它允许按宽度、高度或整体缩放,影响视觉外观以及元素在组合中的交互方式。 + - Comfy dtype: COMBO + - Python dtype: str +- layers + - ‘layers’参数是ShowLayer类可以操作的视觉元素集合。它在构建组合和确定视觉层次结构方面很重要。 + - Comfy dtype: LAYER + - Python dtype: List[PIL.Image.Image] + +# Output types + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ShowLayer: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'edit': ('EDIT',), 'x': ('INT', {'default': 0, 'min': -100, 'max': 8192, 'step': 1, 'display': 'number'}), 'y': ('INT', {'default': 0, 'min': 0, 'max': 8192, 'step': 1, 'display': 'number'}), 'width': ('INT', {'default': 512, 'min': 1, 'max': 8192, 'step': 1, 'display': 'number'}), 'height': ('INT', {'default': 512, 'min': 1, 'max': 8192, 'step': 1, 'display': 'number'}), 'z_index': ('INT', {'default': 0, 'min': 0, 'max': 100, 'step': 1, 'display': 'number'}), 'scale_option': (['width', 'height', 'overall'],)}, 'optional': {'layers': ('LAYER', {'default': None})}} + RETURN_TYPES = () + RETURN_NAMES = () + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Layer' + INPUT_IS_LIST = True + + def run(self, edit, x, y, width, height, z_index, scale_option, layers): + return () +``` \ No newline at end of file diff --git a/docs/ShowTextForGPT.md b/docs/ShowTextForGPT.md new file mode 100644 index 0000000..80b6044 --- /dev/null +++ b/docs/ShowTextForGPT.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: ShowTextForGPT +- Category: ♾️Mixlab/GPT +- Output node: True +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +ShowTextForGPT节点旨在处理和输出文本数据。它接受各种文本输入并将它们写入输出文件,确保每个字符串得到适当处理和存储。该节点对于需要文本生成和随后的文件管理的任务至关重要,为文本处理提供了简化的工作流程。 + +# Input types +## Required +- text + - ‘text’参数至关重要,因为它代表将由节点处理的数据。这是决定输出内容和性质的主要输入。没有这个输入,节点将没有任何数据可以处理,使其成为节点运行的关键组成部分。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- output_dir + - ‘output_dir’参数用于指定处理后的文本将被保存的位置,这对输出文件的组织和可访问性产生影响,允许更好地管理和检索结果。这个参数是可选的,但在使用时增强了节点的功能。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- ui.text + - ‘ui.text’输出参数作为处理后的文本数据的表示。它是输入的直接反映,展示了节点有效处理和输出文本的能力。这个输出对于在用户界面中可视化结果非常重要。 + - Comfy dtype: STRING + - Python dtype: str +- result + - ‘result’输出参数是处理后的文本数据的集合,表明节点操作的成功完成。这是至关重要的输出,因为它提供了节点功能和文本处理有效性的证据。 + - Comfy dtype: COMBO[STRING] + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ShowTextForGPT: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'forceInput': True, 'dynamicPrompts': False})}, 'optional': {'output_dir': ('STRING', {'forceInput': True, 'default': '', 'multiline': True, 'dynamicPrompts': False})}} + INPUT_IS_LIST = True + RETURN_TYPES = ('STRING',) + FUNCTION = 'run' + OUTPUT_NODE = True + OUTPUT_IS_LIST = (True,) + CATEGORY = '♾️Mixlab/GPT' + + def run(self, text, output_dir=['']): + texts = [] + for t in text: + if not isinstance(t, str): + t = str(t) + texts.append(t) + text = texts + if len(output_dir) == 1 and (output_dir[0] == '' or os.path.dirname(output_dir[0]) == ''): + t = '\n'.join(text) + output_dir = [os.path.join(folder_paths.get_temp_directory(), get_unique_hash(t) + '.txt')] + elif len(output_dir) == 1: + base = os.path.basename(output_dir[0]) + t = '\n'.join(text) + if base == '' or os.path.splitext(base)[1] == '': + base = get_unique_hash(t) + '.txt' + output_dir = [os.path.join(output_dir[0], base)] + if len(output_dir) == 1 and len(text) > 1: + output_dir = [output_dir[0] for _ in range(len(text))] + for i in range(len(text)): + o_fp = output_dir[i] + dirp = os.path.dirname(o_fp) + if dirp == '': + dirp = folder_paths.get_temp_directory() + o_fp = os.path.join(folder_paths.get_temp_directory(), o_fp) + if not os.path.exists(dirp): + os.mkdir(dirp) + if not os.path.splitext(o_fp)[1].lower() == '.txt': + o_fp = o_fp + '.txt' + t = text[i] + with open(o_fp, 'w') as file: + file.write(t) + return {'ui': {'text': text}, 'result': (text,)} +``` \ No newline at end of file diff --git a/docs/Simple Pattern Replace (WLSH).md b/docs/Simple Pattern Replace (WLSH).md new file mode 100644 index 0000000..0adc512 --- /dev/null +++ b/docs/Simple Pattern Replace (WLSH).md @@ -0,0 +1,72 @@ +# Documentation +- Class name: WLSH_Simple_Pattern_Replace +- Category: WLSH Nodes/text +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点能够在文本字符串中替换特定的模式为提供的列表中的条目,增强了文本处理操作的多样性。 + +# Input types +## Required +- input_string + - input_string参数是需要识别和替换模式的文本。它对节点的运行至关重要,因为它是所有替换活动的基础。 + - Comfy dtype: STRING + - Python dtype: str +- list_string + - list_string参数提供了用于替换识别模式的字符串池。它在决定替换的多样性和随机性方面起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +- pattern + - pattern参数定义了文本中需要被替换的特定序列或结构。它对于指导节点的搜索和替换过程至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- delimiter + - delimiter参数用于将list_string分割成单独的元素,这些元素随后可选用来替换识别到的模式。它在组织替换选项方面很重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- seed + - seed参数初始化替换过程中的随机数生成器,确保替换是可复现的。它有助于节点输出的可预测性和一致性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- string + - 节点的输出是输入字符串的修改版本,其中识别到的模式被list_string中的元素替换,反映了节点的文本转换能力。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Simple_Pattern_Replace: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input_string': ('STRING', {'multiline': True, 'forceInput': True}), 'list_string': ('STRING', {'default': f''}), 'pattern': ('STRING', {'default': f'$var'}), 'delimiter': ('STRING', {'default': f','}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('string',) + FUNCTION = 'replace_string' + CATEGORY = 'WLSH Nodes/text' + + def replace_string(self, input_string, list_string, pattern, delimiter, seed): + pattern = re.escape(pattern).strip() + regex = re.compile(pattern) + matches = regex.findall(input_string) + if not matches: + return (input_string,) + if seed is not None: + random.seed(seed) + if delimiter not in list_string: + raise ValueError('Delimiter not found in list_string') + + def replace(match): + return random.choice(list_string.split(delimiter)) + new_string = regex.sub(replace, input_string) + return (new_string,) +``` \ No newline at end of file diff --git a/docs/Simple String Combine (WLSH).md b/docs/Simple String Combine (WLSH).md new file mode 100644 index 0000000..58c5a58 --- /dev/null +++ b/docs/Simple String Combine (WLSH).md @@ -0,0 +1,64 @@ +# Documentation +- Class name: WLSH_String_Append +- Category: WLSH Nodes/text +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_String_Append节点旨在以指定方式连接字符串。它允许在现有字符串之前或之后添加文本,并可以选择两个段落之间的分隔符。节点的功能集中在通过智能放置和分隔文本,根据用户的需求创建一个无缝且连贯的文本输出。 + +# Input types +## Required +- addition + - “addition”参数代表要附加到输入字符串的文本。它是节点操作的关键部分,因为它决定了将添加到现有文本中的内容。多行属性允许添加更长的文本段,增强了节点在处理各种文本场景时的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- placement + - “placement”参数指示“addition”文本相对于“input_string”的位置。它对于控制最终输出中文本段的顺序至关重要。节点能够将文本放置在输入字符串之前或之后,为用户提供了根据需要构建文本的灵活性。 + - Comfy dtype: COMBO['after', 'before'] + - Python dtype: Literal['after', 'before'] +- separator + - “separator”参数指定在'input_string'和'addition'之间的分隔符类型。它在定义组合文本的可读性和结构方面起着重要作用。分隔符的选择可以极大地影响文本的最终外观,允许定制以适应不同的上下文。 + - Comfy dtype: COMBO['comma', 'space', 'newline', 'none'] + - Python dtype: Literal['comma', 'space', 'newline', 'none'] +## Optional +- input_string + - “input_string”参数是要附加“addition”的现有文本。虽然它是可选的,但它是节点操作的基础。节点的功能旨在有无初始字符串的情况下工作,为用户提供了将文本附加到现有字符串的选项,或者仅从附加项创建新字符串的选项。 + - Comfy dtype: STRING + - Python dtype: Optional[str] + +# Output types +- combined + - “combined”输出参数代表节点操作产生的最终连接字符串。它包含了将“addition”文本附加到“input_string”并使用所选的“separator”分隔的结果。这个输出很重要,因为它是节点主要功能的直接结果,为用户提供了他们旨在创建的连贯文本。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_String_Append: + location = ['after', 'before'] + separator = ['comma', 'space', 'newline', 'none'] + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'addition': ('STRING', {'multiline': True}), 'placement': (s.location,), 'separator': (s.separator,)}, 'optional': {'input_string': ('STRING', {'multiline': True, 'forceInput': True})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('combined',) + FUNCTION = 'concat_string' + CATEGORY = 'WLSH Nodes/text' + + def concat_string(self, placement, separator, addition='', input_string=''): + sep = {'comma': ', ', 'space': ' ', 'newline': '\n', 'none': ''} + if input_string is None: + return (addition,) + if placement == 'after': + new_string = input_string + sep[separator] + addition + else: + new_string = addition + sep[separator] + input_string + return (new_string,) +``` \ No newline at end of file diff --git a/docs/SimpleMath+.md b/docs/SimpleMath+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/SinWave.md b/docs/SinWave.md new file mode 100644 index 0000000..966c9b8 --- /dev/null +++ b/docs/SinWave.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: SinWave +- Category: FizzNodes 📅🅕🅝/WaveNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +SinWave节点旨在生成正弦波模式。它通过计算给定帧的y位置来模拟波的行为,基于提供的参数。该节点特别适用于需要周期函数来模拟振荡或创建视觉效果的应用。 + +# Input types +## Required +- phase + - 相位参数决定了波的周期。它至关重要,因为它决定了振荡的频率,从而影响波的整体形状和模式。 + - Comfy dtype: FLOAT + - Python dtype: float +- amplitude + - 振幅设置波的峰值,控制振荡的高度。它是一个关键参数,影响波形的强度。 + - Comfy dtype: FLOAT + - Python dtype: float +- current_frame + - 当前帧参数指定要进行波计算的帧。这对于确定特定时间点波的y位置至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- x_translation + - X平移允许沿X轴水平移动波。这可以用来调整波形的位置以满足特定的设计要求。 + - Comfy dtype: FLOAT + - Python dtype: float +- y_translation + - Y平移负责沿Y轴垂直移动波,使波的起始点可以进行调整。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output + - 输出表示当前帧波的计算y位置。它很重要,因为它为进一步处理或可视化提供了实际值。 + - Comfy dtype: FLOAT + - Python dtype: float +- int_output + - 整型输出是波的y位置转换为整数,这在需要离散值的场景中非常有用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SinWave: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'phase': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'amplitude': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.1}), 'x_translation': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'y_translation': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.05}), 'current_frame': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('FLOAT', 'INT') + FUNCTION = 'Wave' + CATEGORY = 'FizzNodes 📅🅕🅝/WaveNodes' + + def Wave(self, phase, amplitude, x_translation, y_translation, current_frame): + output = y_translation + amplitude * np.sin(2 * np.pi * current_frame / phase - x_translation) + print(output) + return (output, int(output)) +``` \ No newline at end of file diff --git a/docs/SineWave.md b/docs/SineWave.md new file mode 100644 index 0000000..258a7a0 --- /dev/null +++ b/docs/SineWave.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: SineWave +- Category: postprocessing/Effects +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +SineWave类引入了一种方法,对图像应用正弦波扭曲效果,通过模拟波浪状图案增强其视觉外观。这种方法旨在以创造性的方式操纵图像数据,引入艺术性的改变,而不损害原始内容的完整性。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它是节点操作的主要输入。它是应用正弦波效果的媒介,其属性直接影响扭曲结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- amplitude + - 振幅决定了正弦波效果的强度,控制应用于图像的扭曲程度。它是塑造节点执行视觉结果的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- frequency + - 频率决定了单位图像空间内的正弦波周期数,影响扭曲的粒度。它在定义图案的外观中起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- direction + - 方向指定了正弦波效果的方向,水平或垂直,这决定了扭曲如何应用于图像。 + - Comfy dtype: COMBO['horizontal', 'vertical'] + - Python dtype: str + +# Output types +- output_image + - 输出图像是应用于输入图像的正弦波效果的结果。它代表了转换,是节点的主要输出,包含了创造性的扭曲。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class SineWave: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'amplitude': ('FLOAT', {'default': 10, 'min': 0, 'max': 150, 'step': 5}), 'frequency': ('FLOAT', {'default': 5, 'min': 0, 'max': 20, 'step': 1}), 'direction': (['horizontal', 'vertical'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'apply_sine_wave' + CATEGORY = 'postprocessing/Effects' + + def apply_sine_wave(self, image: torch.Tensor, amplitude: float, frequency: float, direction: str): + (batch_size, height, width, channels) = image.shape + result = torch.zeros_like(image) + for b in range(batch_size): + tensor_image = image[b] + result[b] = self.sine_wave_effect(tensor_image, amplitude, frequency, direction) + return (result,) + + def sine_wave_effect(self, image: torch.Tensor, amplitude: float, frequency: float, direction: str): + (height, width, _) = image.shape + shifted_image = torch.zeros_like(image) + for channel in range(3): + if direction == 'horizontal': + for i in range(height): + offset = int(amplitude * np.sin(2 * torch.pi * i * frequency / height)) + shifted_image[i, :, channel] = torch.roll(image[i, :, channel], offset) + elif direction == 'vertical': + for j in range(width): + offset = int(amplitude * np.sin(2 * torch.pi * j * frequency / width)) + shifted_image[:, j, channel] = torch.roll(image[:, j, channel], offset) + return shifted_image +``` \ No newline at end of file diff --git a/docs/Smart Step (mtb).md b/docs/Smart Step (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/SmoothMask.md b/docs/SmoothMask.md new file mode 100644 index 0000000..a39e5aa --- /dev/null +++ b/docs/SmoothMask.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: SmoothMask +- Category: ♾️Mixlab/Mask +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +SmoothMask是一个处理图像遮罩以减少噪声和细节的节点,提供更平滑的视觉输出。它通过对输入遮罩应用高斯模糊来实现这一点,有效地软化其边缘并减少高频信息。该节点对于准备需要在遮罩和非遮罩区域之间具有更渐进过渡的遮罩至关重要,提高了最终图像的视觉质量。 + +# Input types +## Required +- mask + - mask参数是平滑操作的源图像。它至关重要,因为它定义了将由节点处理的图像的初始状态。遮罩的质量和分辨率直接影响平滑处理的有效性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +## Optional +- smoothness + - smoothness参数控制应用于遮罩的高斯模糊的程度。它是一个重要因素,因为它决定了遮罩边缘软化的程度。较高的值会产生更模糊、更平滑的遮罩,而较低的值则保留更多原始遮罩的细节。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MASK + - SmoothMask节点的输出是输入遮罩的修改版本,具有减少的噪声和更平滑的边缘。这个平滑的遮罩可以用于各种图像处理任务中,其中需要在遮罩和未遮罩区域之间有更精细的过渡。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SmoothMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'smoothness': ('INT', {'default': 1, 'min': 0, 'max': 150, 'step': 1, 'display': 'slider'})}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Mask' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False,) + + def run(self, mask, smoothness): + print('SmoothMask', mask.shape) + mask = tensor2pil(mask) + feathered_image = mask.filter(ImageFilter.GaussianBlur(smoothness)) + mask = pil2tensor(feathered_image) + return (mask,) +``` \ No newline at end of file diff --git a/docs/SoftControlNetWeights.md b/docs/SoftControlNetWeights.md new file mode 100644 index 0000000..9f83863 --- /dev/null +++ b/docs/SoftControlNetWeights.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: SoftControlNetWeights +- Category: Adv-ControlNet 🛂🅐🅒🅝/weights/ControlNet +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +SoftControlNetWeights 类旨在管理和处理控制网络的权重,可能在机器学习或模拟环境中使用。它封装了加载和组织这些权重的逻辑,确保它们被正确应用以影响网络的行为。 + +# Input types +## Required +- weight_00 + - weight_00 参数是一个浮点数,它对控制网络的总体权重有所贡献。它在确定对网络行为的初始影响中起着关键作用。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- flip_weights + - flip_weights 参数是一个布尔值,当设置时,表示权重在应用于控制网络时应翻转或反转。这可以显著改变网络的响应。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- weights + - 权重输出代表已处理和组织的控制网络权重集合,这些权重已被加载并准备好在网络内应用。 + - Comfy dtype: CONTROL_NET_WEIGHTS + - Python dtype: ControlWeights +- timestep_keyframe + - timestep_keyframe 输出是控制网络操作中某个时间点的结构化表示。它包括诸如开始百分比和强度等细节,这些对于时间控制至关重要。 + - Comfy dtype: TIMESTEP_KEYFRAME + - Python dtype: TimestepKeyframe + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SoftControlNetWeights: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'weight_00': ('FLOAT', {'default': 0.09941396206337118, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_01': ('FLOAT', {'default': 0.12050177219802567, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_02': ('FLOAT', {'default': 0.14606275417942507, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_03': ('FLOAT', {'default': 0.17704576264172736, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_04': ('FLOAT', {'default': 0.214600924414215, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_05': ('FLOAT', {'default': 0.26012233262329093, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_06': ('FLOAT', {'default': 0.3152997971191405, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_07': ('FLOAT', {'default': 0.3821815722656249, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_08': ('FLOAT', {'default': 0.4632503906249999, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_09': ('FLOAT', {'default': 0.561515625, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_10': ('FLOAT', {'default': 0.6806249999999999, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_11': ('FLOAT', {'default': 0.825, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_12': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'flip_weights': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('CONTROL_NET_WEIGHTS', 'TIMESTEP_KEYFRAME') + RETURN_NAMES = WEIGHTS_RETURN_NAMES + FUNCTION = 'load_weights' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/weights/ControlNet' + + def load_weights(self, weight_00, weight_01, weight_02, weight_03, weight_04, weight_05, weight_06, weight_07, weight_08, weight_09, weight_10, weight_11, weight_12, flip_weights): + weights = [weight_00, weight_01, weight_02, weight_03, weight_04, weight_05, weight_06, weight_07, weight_08, weight_09, weight_10, weight_11, weight_12] + weights = ControlWeights.controlnet(weights, flip_weights=flip_weights) + return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights))) +``` \ No newline at end of file diff --git a/docs/SoftT2IAdapterWeights.md b/docs/SoftT2IAdapterWeights.md new file mode 100644 index 0000000..17fc52a --- /dev/null +++ b/docs/SoftT2IAdapterWeights.md @@ -0,0 +1,63 @@ +# Documentation +- Class name: SoftT2IAdapterWeights +- Category: Adv-ControlNet 🛂🅐🅒🅝/weights/T2IAdapter +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +SoftT2IAdapterWeights节点旨在促进控制网络权重的适配,以便将时间关键帧转换为输入适配器权重。它简化了权重分配过程,并确保与底层控制网络机制的兼容性。 + +# Input types +## Required +- weight_00 + - weight_00参数对于初始化控制权重的基础水平至关重要,影响时间关键帧转换过程的整体效果。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight_01 + - weight_01参数对于调整中间控制权重至关重要,直接影响时间关键帧的细微转换。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight_02 + - weight_02参数在微调高级控制权重方面至关重要,决定了时间关键帧适配的精确度。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight_03 + - weight_03参数对于定义最终控制权重至关重要,决定了时间关键帧转换的最终结果。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- flip_weights + - 当启用flip_weights参数时,会反转控制权重的效果,在权重分布和转换过程中提供另一种视角。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- CONTROL_NET_WEIGHTS + - 输出CONTROL_NET_WEIGHTS代表适当排列和转换的控制权重,准备应用于时间关键帧进行进一步处理。 + - Comfy dtype: CONTROL_NET_WEIGHTS + - Python dtype: ControlWeights +- TIMESTEP_KEYFRAME + - 输出TIMESTEP_KEYFRAME提供了一个结构化的时间步关键帧组,封装了控制权重并准备集成到控制网络中。 + - Comfy dtype: TIMESTEP_KEYFRAME + - Python dtype: TimestepKeyframeGroup + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SoftT2IAdapterWeights: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'weight_00': ('FLOAT', {'default': 0.25, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_01': ('FLOAT', {'default': 0.62, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_02': ('FLOAT', {'default': 0.825, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'weight_03': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'flip_weights': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('CONTROL_NET_WEIGHTS', 'TIMESTEP_KEYFRAME') + RETURN_NAMES = WEIGHTS_RETURN_NAMES + FUNCTION = 'load_weights' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/weights/T2IAdapter' + + def load_weights(self, weight_00, weight_01, weight_02, weight_03, flip_weights): + weights = [weight_00, weight_01, weight_02, weight_03] + weights = get_properly_arranged_t2i_weights(weights) + weights = ControlWeights.t2iadapter(weights, flip_weights=flip_weights) + return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights))) +``` \ No newline at end of file diff --git a/docs/Solarize.md b/docs/Solarize.md new file mode 100644 index 0000000..f4bcd3a --- /dev/null +++ b/docs/Solarize.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: Solarize +- Category: postprocessing/Color Adjustments +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +该节点旨在通过反转高于特定阈值的颜色来调整图像的颜色,提供一种太阳化效果,增强可见性和对比度。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它是太阳化过程的主要输入。它决定了将要进行颜色调整的源材料。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- threshold + - 阈值参数作为太阳化过程的决策边界,决定了哪些颜色色调被反转以增强图像的对比度。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- solarized_image + - 输出是经过太阳化处理的图像,它经历了颜色反转过程以提高其视觉吸引力和清晰度。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Solarize: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'solarize_image' + CATEGORY = 'postprocessing/Color Adjustments' + + def solarize_image(self, image: torch.Tensor, threshold: float): + solarized_image = torch.where(image > threshold, 1 - image, image) + solarized_image = torch.clamp(solarized_image, 0, 1) + return (solarized_image,) +``` \ No newline at end of file diff --git a/docs/SpeechRecognition.md b/docs/SpeechRecognition.md new file mode 100644 index 0000000..18775a6 --- /dev/null +++ b/docs/SpeechRecognition.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: SpeechRecognition +- Category: ♾️Mixlab/Audio +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +语音识别节点旨在将音频输入转换为文本。它在需要将口语转换为书面形式的应用中发挥关键作用,例如在语音命令系统或转录服务中。该节点的功能集中在其准确处理和解释音频信号的能力上,为用户提供了一个强大的语音转文本工具。 + +# Input types +## Required +- upload + - ‘upload’参数对于语音识别节点至关重要,因为它是需要处理的音频数据的来源。这是一个必需的输入,它直接影响节点的操作和语音识别输出的质量。 + - Comfy dtype: AUDIOINPUTMIX + - Python dtype: Union[str, bytes] +- start_by + - ‘start_by’参数允许用户指定音频文件中语音识别过程的起始点。虽然它是可选的,但它可以通过将识别任务集中在音频的定部分来显著影响节点的执行,提高效率和准确性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- prompt + - 语音识别节点的‘prompt’输出代表了从输入音频转录的文本。这是一个重要的结果,它包含了节点的主要功能,为用户提供了口语内容的文本表示。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SpeechRecognition: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'upload': ('AUDIOINPUTMIX',)}, 'optional': {'start_by': ('INT', {'default': 0, 'min': 0, 'max': 2048, 'step': 1, 'display': 'number'})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('prompt',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Audio' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False,) + + def run(self, upload, start_by): + return {'ui': {'start_by': [start_by]}, 'result': (upload,)} +``` \ No newline at end of file diff --git a/docs/SpeechSynthesis.md b/docs/SpeechSynthesis.md new file mode 100644 index 0000000..24865f8 --- /dev/null +++ b/docs/SpeechSynthesis.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: SpeechSynthesis +- Category: ♾️Mixlab/Audio +- Output node: True +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点旨在将所提供的文本转换为类似人类的语音,使得应用程序能够以声音的形式与用户进行交流。它将文本数据转换为音频输出,便于创建互动性强且引人入胜的音频体验。 + +# Input types +## Required +- text + - 文本参数对于节点的运行至关重要,因为它是语音合成的输入。它决定了生成语音的内容和上下文,直接影响节点的输出结果。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- result + - 结果输出是合成的语音,这是使用此节点的主要目的。它代表了输入文本到可听格式的转换,准备好进行播放。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SpeechSynthesis: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'forceInput': True})}} + INPUT_IS_LIST = True + RETURN_TYPES = ('STRING',) + FUNCTION = 'run' + OUTPUT_NODE = True + OUTPUT_IS_LIST = (True,) + CATEGORY = '♾️Mixlab/Audio' + + def run(self, text): + return {'ui': {'text': text}, 'result': (text,)} +``` \ No newline at end of file diff --git a/docs/Split Tracking Points.md b/docs/Split Tracking Points.md new file mode 100644 index 0000000..628fbcb --- /dev/null +++ b/docs/Split Tracking Points.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: SplitTrackingPoints +- Category: DragNUWA +- Output node: True +- Repo Ref: https://github.com/chaojie/ComfyUI-DragNUWA.git + +SplitTrackingPoints节点旨在处理和操作来自姿态关键点数据的跟踪点。它便于将跟踪点分割成不同实体,使得分析和跟踪操作更加精细。该节点特别适用于需要在定义区域内详细跟踪人体运动的应用,有助于更细致地理解运动模式。 + +# Input types +## Required +- pose_kps + - 姿态关键点数据对于节点至关重要,因为它是跟踪和分析的主要输入。该参数直接影响节点处理和分割跟踪点的能力,影响跟踪操作的准确性和可靠性。 + - Comfy dtype: POSE_KEYPOINT + - Python dtype: List[Dict[str, Union[int, float, List[Union[str, int, float]]]]] +- split_index + - split_index参数控制跟踪点的分割,允许在跟踪数据中分离不同的实体。这对于节点正确运行和实现跟踪点的期望分割至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - height参数定义了跟踪区域的垂直维度,这对于在指定边界内过滤和处理跟踪点非常重要。它确保跟踪操作限制在相关区域,提高了节点的有效性。 + - Comfy dtype: INT + - Python dtype: int +- width + - width参数设置了跟踪区域的水平维度,在跟踪点的过滤和处理中起着关键作用。它对于确保跟踪点与指定区域的相关性至关重要,有助于提高节点的准确性和效率。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- last_pose_kps + - last_pose_kps参数提供了时,作为初始跟踪点的参考,有助于跟踪过程的连续性和一致性。它增强了节点随时间保持准确跟踪的能力。 + - Comfy dtype: POSE_KEYPOINT + - Python dtype: List[Dict[str, Union[int, float, List[Union[str, int, float]]]]] + +# Output types +- tracking_points + - tracking_points输出提供了分割后的跟踪点的JSON格式表示,将处理后的数据封装在结构化且易于访问的格式中。这个输出对于进一步的分析和集成到下游应用至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SplitTrackingPoints: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pose_kps': ('POSE_KEYPOINT',), 'split_index': ('INT', {'default': 0}), 'height': ('INT', {'default': 320}), 'width': ('INT', {'default': 576})}, 'optional': {'last_pose_kps': ('POSE_KEYPOINT', {'default': None})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('tracking_points',) + FUNCTION = 'split_tracking_points' + OUTPUT_NODE = True + CATEGORY = 'DragNUWA' + + def split_tracking_points(self, pose_kps, split_index, height, width, last_pose_kps=None): + if split_index != 0: + if last_pose_kps is not None: + pose_kps[split_index * 14] = last_pose_kps[0] + trajs = [] + for ipose in range(int(len(pose_kps[split_index * 14]['people'][0]['pose_keypoints_2d']) / 3)): + traj = [] + for itracking in range(14): + people = pose_kps[split_index * 14 + itracking]['people'] + if people[0]['pose_keypoints_2d'][ipose * 3 + 2] == 1.0: + x = people[0]['pose_keypoints_2d'][ipose * 3] + y = people[0]['pose_keypoints_2d'][ipose * 3 + 1] + if x <= width and y <= height: + traj.append([x, y]) + else: + break + elif len(traj) > 0: + traj.append(traj[len(traj) - 1]) + else: + break + if len(traj) > 0: + trajs.append(traj) + return (json.dumps(trajs),) +``` \ No newline at end of file diff --git a/docs/SplitImage(esheep).md b/docs/SplitImage(esheep).md new file mode 100644 index 0000000..fcfbaa1 --- /dev/null +++ b/docs/SplitImage(esheep).md @@ -0,0 +1,43 @@ +# Documentation +- Class name: ImageSplitNode +- Category: util +- Output node: False +- Repo Ref: https://github.com/esheep/esheep_custom_nodes.git + +该节点旨在将一批图像分割成更小的子集,通过分解大型图像数据集为可管理的小块来促进处理。它通过允许并行处理来增强工作流程,并可以提高计算任务的效率。在分割过程中,节点保持图像的完整性。 + +# Input types +## Required +- images + - 输入参数'images'是一组图像数据,节点将对其进行处理。它对节点的操作至关重要,因为它作为图像分割功能的主要输入。图像的质量和格式显著影响后续的处理和输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- split_images + - 节点的输出由多个图像子集组成,它们是图像分割过程的结果。这些子集已准备好进行进一步处理,并可用于各种下游任务,如特征提取或模型训练。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ImageSplitNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',)}} + MAX_SIZE = 6 + RETURN_TYPES = ['IMAGE'] * 6 + FUNCTION = 'main' + CATEGORY = 'util' + + def main(self, images): + items = torch.chunk(images, self.MAX_SIZE) + padding_size = self.MAX_SIZE - len(items) + if padding_size > 0: + items = items + tuple([create_empty_image()] * padding_size) + return items +``` \ No newline at end of file diff --git a/docs/SplitImage.md b/docs/SplitImage.md new file mode 100644 index 0000000..9de84c6 --- /dev/null +++ b/docs/SplitImage.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: SplitImage +- Category: ♾️Mixlab/Layer +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +SplitImage节点旨在将输入的图像分割成较小的图像网格,并生成相应的掩码。它通过启用创建分段输出的功能,增强了图像处理工作流程,这些输出可用于各种应用,如图像编辑、特征提取和数据增强。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它是节点操作的主要输入。它决定了生成的分割图像和掩码的质量与分辨率。图像的特征直接影响节点在分割和掩码制作方面的有效性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- num + - num参数决定了图像将被分割成多少个段。它非常重要,因为它影响着分割图像的粒度和掩码的细节层次。较高的值将导致更多的段,这对于详细分析或处理可能是有益的。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- seed + - seed参数用于控制网格坐标的随机性。它对于确保图像分割过程中的可重复性非常重要,特别是当节点用于需要一致结果的较大工作流程中时。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- grids + - grids输出是从原始输入中派生的分割图像的集合。它代表了节点操作的主要结果,展示了图像分割的有效性。 + - Comfy dtype: _GRID + - Python dtype: List[Tuple[int, int, int, int]] +- grid + - grid输出是基于seed参数选择的单个分割图像。它很重要,因为它提供了一个特定段的详细视图,可用于专注分析或进一步处理。 + - Comfy dtype: _GRID + - Python dtype: Tuple[int, int, int, int] +- mask + - mask输出是一个二值图像,对应于选定的grid。它对于隔离和突出显示图像的特定区域以进行进一步分析或操作至关重要。 + - Comfy dtype: MASK + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SplitImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'num': ('INT', {'default': 4, 'min': 1, 'max': 500, 'step': 1, 'display': 'number'}), 'seed': ('INT', {'default': 4, 'min': 1, 'max': 500, 'step': 1, 'display': 'number'})}} + RETURN_TYPES = ('_GRID', '_GRID', 'MASK') + RETURN_NAMES = ('grids', 'grid', 'mask') + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Layer' + INPUT_IS_LIST = False + + def run(self, image, num, seed): + image = tensor2pil(image) + grids = splitImage(image, num) + if seed > num: + num = int(seed / 500 * num) - 1 + else: + num = seed - 1 + num = max(0, num) + g = grids[num] + (x, y, w, h) = g + mask = createMask(image, x, y, w, h) + mask = pil2tensor(mask) + return (grids, g, mask) +``` \ No newline at end of file diff --git a/docs/SplitLongMask.md b/docs/SplitLongMask.md new file mode 100644 index 0000000..1dc7a5b --- /dev/null +++ b/docs/SplitLongMask.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: SplitLongMask +- Category: ♾️Mixlab/Mask +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +SplitLongMask节点旨在根据指定的数量或高度,将单个大型掩码分割成多个较小的掩码。这一过程增强了掩码在各种场景中的可管理性和适用性,例如在图像分割或目标跟踪中,更倾向于使用更小、更易管理的单元。 + +# Input types +## Required +- long_mask + - long_mask参数是SplitLongMask节点的主要输入。它代表了一个需要被分割的大型掩码。这个掩码的质量和尺寸直接影响输出,决定了结果中较小掩码的特性。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- count + - count参数规定了希望输出的较小掩码的数量。它在确定结果掩码的大小和数量方面起着至关重要的作用,这对于需要特定分布的掩码段的应用来说是必不可少的。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- masks + - SplitLongMask节点的输出,masks,是从原始的long_mask派生出的一个较小掩码的列表。这些掩码对于从分段掩码输入中受益的应用至关重要,例如图像处理或涉及基于掩码操作的机器学习任务。 + - Comfy dtype: MASK + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SplitLongMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'long_mask': ('MASK',), 'count': ('INT', {'default': 1, 'min': 1, 'max': 1024, 'step': 1})}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Mask' + OUTPUT_IS_LIST = (True,) + + def run(self, long_mask, count): + masks = [] + nh = long_mask.shape[0] // count + if nh * count == long_mask.shape[0]: + masks = split_mask_by_new_height(long_mask, nh) + else: + masks = split_mask_by_new_height(long_mask, long_mask.shape[0]) + return (masks,) +``` \ No newline at end of file diff --git a/docs/SquareWave.md b/docs/SquareWave.md new file mode 100644 index 0000000..b5b3cad --- /dev/null +++ b/docs/SquareWave.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: SquareWave +- Category: FizzNodes 📅🅕🅝/WaveNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +SquareWave节点旨在生成方波模式。它通过调整相位、振幅和平移来产生方波形,这对于信号处理和波形分析至关重要。该节点的功能对于需要创建或操纵方波信号的应用是至关重要的。 + +# Input types +## Required +- phase + - 相位参数决定了波形周期的位置,这对于确定方波转换的时机至关重要。它影响波形的频率和起始点。 + - Comfy dtype: FLOAT + - Python dtype: float +- amplitude + - 振幅设置了波峰和波谷的高度,这对于定义信号的强度非常重要。它是方波整体形状和特性的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- x_translation + - X平移沿X轴移动波形,允许调整波形的位置。这个参数对于将波形与其他信号或系统中的组件对齐至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- y_translation + - Y平移沿Y轴向上或向下移动波形,影响波形的垂直位置。它是调整波形相对于其他元素位置的重要参数。 + - Comfy dtype: FLOAT + - Python dtype: float +- current_frame + - 当前帧参数指示波形序列中的当前位置,这对于方波模式随时间的进展和定时至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - SquareWave节点的输出代表了在指定参数下方波的计算值,这对于进一步的信号处理或分析是必不可少的。 + - Comfy dtype: FLOAT + - Python dtype: float +- int_output + - 整型输出提供了波形值的离散版本,这对于需要信号的量化或整数表示的应用非常有用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SquareWave: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'phase': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'amplitude': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.1}), 'x_translation': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'y_translation': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.05}), 'current_frame': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('FLOAT', 'INT') + FUNCTION = 'Wave' + CATEGORY = 'FizzNodes 📅🅕🅝/WaveNodes' + + def Wave(self, phase, amplitude, x_translation, y_translation, current_frame): + output = y_translation + amplitude * 0 ** 0 ** (0 - np.sin(np.pi * current_frame / phase - x_translation)) + print(output) + return (output, int(output)) +``` \ No newline at end of file diff --git a/docs/StableCascade_CheckpointLoader %2F%2FInspire.md b/docs/StableCascade_CheckpointLoader %2F%2FInspire.md new file mode 100644 index 0000000..64227ad --- /dev/null +++ b/docs/StableCascade_CheckpointLoader %2F%2FInspire.md @@ -0,0 +1,132 @@ +# Documentation +- Class name: StableCascade_CheckpointLoader +- Category: InspirePack/Backend +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在高效地从指定目录加载和管理检查点,将它们分类到不同的阶段,并促进模型及相关数据的检索。它通过提供缓存功能来增强工作流程,这可以通过重用先前加载的检查点显著加快重复任务的速度。 + +# Input types +## Required +- stage_b + - stage_b参数指定了级联第二阶段的检查点文件名称。它对于节点识别正确的检查点以进行加载和缓存至关重要,这直接影响后续的处理和结果。 + - Comfy dtype: STRING + - Python dtype: str +- stage_c + - stage_c参数表示级联第三阶段的检查点文件。它对于节点正确加载高级模型及相关数据至关重要,影响最终输出和模型利用的有效性。 + - Comfy dtype: STRING + - Python dtype: str +- cache_mode + - cache_mode参数控制节点的缓存行为。它决定了是从未缓存中加载检查点还是直接从文件系统加载,以及是否将加载的检查点缓存以供将来使用。这个参数显著影响节点的性能和效率。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- key_opt_b + - key_opt_b参数作为检查点的可选标识符。它允许自定义命名,这对于引用缓存中的特定检查点非常有用。如果提供该值,它将被用作缓存中的键,否则将使用'stage_b'。 + - Comfy dtype: STRING + - Python dtype: str +- key_opt_c + - key_opt_c参数是stage_c检查点的备用键。它使用户能够用唯一的名称标记检查点,以便更好地管理缓存和引用。如果留空,则使用'stage_c'作为默认键。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- b_model + - b_model输出代表从检查点加载的第二阶段模型。它是进一步处理和分析的关键组成部分,因为它包含了模型功能所需的学习参数和结构。 + - Comfy dtype: MODEL + - Python dtype: Any +- b_vae + - b_vae输出提供了与第二阶段相关的变分自编码器(VAE)。它在生成新数据点或重建现有数据点方面起着重要作用,对于涉及生成模型的任务至关重要。 + - Comfy dtype: VAE + - Python dtype: Any +- c_model + - c_model输出是从检查点检索的第三阶段模型。它在整个工作流程中起着关键作用,因为它通常比第二阶段模型更为精细,能够完成更高级的任务。 + - Comfy dtype: MODEL + - Python dtype: Any +- c_vae + - c_vae输出表示第三阶段的变分自编码器(VAE)。它对于需要高级数据生成和操作能力的任务至关重要,如特征提取和降维。 + - Comfy dtype: VAE + - Python dtype: Any +- clip_vision + - clip_vision输出是第三阶段模型的专门组件,专注于与视觉相关的任务。它对于涉及图像处理和理解的应用非常重要,为视觉数据分析提供了坚实的基础。 + - Comfy dtype: CLIP_VISION + - Python dtype: Any +- clip + - clip输出代表与第二阶段相关的上下文语言模型(CLM)。它对于需要自然语言理解和生成的任务至关重要,为基于文本的应用程序提供了强大的工具。 + - Comfy dtype: CLIP + - Python dtype: Any +- key_b + - key_b输出是用于缓存第二阶段检查点的标识符。它对于有效管理缓存非常重要,因为它允许在后续操作中快速检索和重用检查点。 + - Comfy dtype: STRING + - Python dtype: str +- key_c + - key_c输出对应于第三阶段检查点的缓存标识符。它在缓存管理过程中起着关键作用,确保高效访问高级模型及其组件。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class StableCascade_CheckpointLoader: + + @classmethod + def INPUT_TYPES(s): + ckpts = folder_paths.get_filename_list('checkpoints') + default_stage_b = '' + default_stage_c = '' + sc_ckpts = [x for x in ckpts if 'cascade' in x.lower()] + sc_b_ckpts = [x for x in sc_ckpts if 'stage_b' in x.lower()] + sc_c_ckpts = [x for x in sc_ckpts if 'stage_c' in x.lower()] + if len(sc_b_ckpts) == 0: + sc_b_ckpts = [x for x in ckpts if 'stage_b' in x.lower()] + if len(sc_c_ckpts) == 0: + sc_c_ckpts = [x for x in ckpts if 'stage_c' in x.lower()] + if len(sc_b_ckpts) == 0: + sc_b_ckpts = ckpts + if len(sc_c_ckpts) == 0: + sc_c_ckpts = ckpts + if len(sc_b_ckpts) > 0: + default_stage_b = sc_b_ckpts[0] + if len(sc_c_ckpts) > 0: + default_stage_c = sc_c_ckpts[0] + return {'required': {'stage_b': (ckpts, {'default': default_stage_b}), 'key_opt_b': ('STRING', {'multiline': False, 'placeholder': "If empty, use 'stage_b' as the key."}), 'stage_c': (ckpts, {'default': default_stage_c}), 'key_opt_c': ('STRING', {'multiline': False, 'placeholder': "If empty, use 'stage_c' as the key."}), 'cache_mode': (['none', 'stage_b', 'stage_c', 'all'], {'default': 'none'})}} + RETURN_TYPES = ('MODEL', 'VAE', 'MODEL', 'VAE', 'CLIP_VISION', 'CLIP', 'STRING', 'STRING') + RETURN_NAMES = ('b_model', 'b_vae', 'c_model', 'c_vae', 'c_clip_vision', 'clip', 'key_b', 'key_c') + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Backend' + + def doit(self, stage_b, key_opt_b, stage_c, key_opt_c, cache_mode): + if key_opt_b.strip() == '': + key_b = stage_b + else: + key_b = key_opt_b.strip() + if key_opt_c.strip() == '': + key_c = stage_c + else: + key_c = key_opt_c.strip() + if cache_mode in ['stage_b', 'all']: + if key_b not in cache: + res_b = nodes.CheckpointLoaderSimple().load_checkpoint(ckpt_name=stage_b) + cache[key_b] = ('ckpt', (False, res_b)) + print(f"[Inspire Pack] StableCascade_CheckpointLoader: Ckpt '{stage_b}' is cached to '{key_b}'.") + else: + (_, (_, res_b)) = cache[key_b] + print(f"[Inspire Pack] StableCascade_CheckpointLoader: Cached ckpt '{key_b}' is loaded. (Loading skip)") + (b_model, clip, b_vae) = res_b + else: + (b_model, clip, b_vae) = nodes.CheckpointLoaderSimple().load_checkpoint(ckpt_name=stage_b) + if cache_mode in ['stage_c', 'all']: + if key_c not in cache: + res_c = nodes.CheckpointLoaderSimple().load_checkpoint(ckpt_name=stage_c) + cache[key_c] = ('unclip_ckpt', (False, res_c)) + print(f"[Inspire Pack] StableCascade_CheckpointLoader: Ckpt '{stage_c}' is cached to '{key_c}'.") + else: + (_, (_, res_c)) = cache[key_c] + print(f"[Inspire Pack] StableCascade_CheckpointLoader: Cached ckpt '{key_c}' is loaded. (Loading skip)") + (c_model, _, c_vae, clip_vision) = res_c + else: + (c_model, _, c_vae, clip_vision) = nodes.unCLIPCheckpointLoader().load_checkpoint(ckpt_name=stage_c) + return (b_model, b_vae, c_model, c_vae, clip_vision, clip, key_b, key_c) +``` \ No newline at end of file diff --git a/docs/StableSRColorFix.md b/docs/StableSRColorFix.md new file mode 100644 index 0000000..42e4121 --- /dev/null +++ b/docs/StableSRColorFix.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: StableSRColorFix +- Category: image +- Output node: False +- Repo Ref: https://github.com/Arthurzhangsheng/Comfyui-StableSR.git + +StableSRColorFix 节点旨在通过应用先进的颜色校正技术来增强图像的颜色质量。它利用深度学习模型的能力,智能地调整输入图像的颜色调色板以匹配参考颜色映射图像,从而产生视觉上连贯且美观的输出。 + +# Input types +## Required +- image + - 输入图像是 StableSRColorFix 节点的关键参数,因为它是将经历颜色校正的主要数据。节点处理此图像以使其颜色分布与 color_map_image 保持一致,确保最终输出在视觉上是一致的。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- color_map_image + - color_map_image 作为节点执行颜色调整的参考。它对于指导颜色校正过程,以在输出图像中实现和谐的颜色调色板至关重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or torch.Tensor +- color_fix + - color_fix 参数决定了节点将使用的颜色校正算法类型。它可以是 'Wavelet' 或 'AdaIN',种方法都提供了不同的颜色调整方法,这显著影响了校正后图像的最终外观。 + - Comfy dtype: COMBO['Wavelet', 'AdaIN'] + - Python dtype: str + +# Output types +- refined_image + - refined_image 是颜色校正过程的输出,代表了具有改进颜色保真度的输入图像的增强版本。它是节点功能的顶点,展示了所选 color_fix 算法的有效性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class StableSRColorFix: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'color_map_image': ('IMAGE',), 'color_fix': (['Wavelet', 'AdaIN'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'fix_color' + CATEGORY = 'image' + + def fix_color(self, image, color_map_image, color_fix): + print(f'[StableSR] fix_color') + try: + color_fix_func = wavelet_color_fix if color_fix == 'Wavelet' else adain_color_fix + result_image = color_fix_func(tensor2pil(image), tensor2pil(color_map_image)) + refined_image = pil2tensor(result_image) + return (refined_image,) + except Exception as e: + print(f'[StableSR] Error fix_color: {e}') +``` \ No newline at end of file diff --git a/docs/StableZero123_BatchSchedule.md b/docs/StableZero123_BatchSchedule.md new file mode 100644 index 0000000..c91d565 --- /dev/null +++ b/docs/StableZero123_BatchSchedule.md @@ -0,0 +1,163 @@ +# Documentation +- Class name: StableZero123_BatchSchedule +- Category: KJNodes/experimental +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +StableZero123_BatchSchedule 类的 `encode` 方法负责处理图像并生成潜在表示。它接受各种参数,如视觉模型输出、初始图像、VAE模型以及宽度、高度和批量大小等额外设置。该方法还根据提供的方位角和高度点进行角度插值,应用不同的缓动函数以实现平滑过渡。最终输出包括正负条件数据和潜在图像表示。 + +# Input types +## Required +- clip_vision + - 参数 `clip_vision` 对于将初始图像编码为可以用于进一步处理的嵌入至关重要。它代表了来自 CLIP 视觉模型的输出,是图像处理流水线的基本部分。 + - Comfy dtype: CLIP_VISION + - Python dtype: torch.Tensor +- init_image + - 参数 `init_image` 是需要处理的原始图像。它是生成潜在表示的起点,也是该节点操作的必需输入。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- vae + - 参数 `vae` 是一个变分自编码器(VAE)模型,用于将图像编码到潜在空间中。它在图像数据转换为下游任务中起着关键作用。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +## Optional +- width + - 参数 `width` 指定处理后图像的期望宽度。它是决定最终图像分辨率的重要因素,并且与高度参数一起使用。 + - Comfy dtype: INT + - Python dtype: int +- height + - 参数 `height` 与宽度参数一起,定义了处理后图像的尺寸。它是控制输出图像大小的关键设置。 + - Comfy dtype: INT + - Python dtype: int +- batch_size + - 参数 `batch_size` 决定了一次处理的图像数量。它是优化节点性能和内存使用的重要考虑因素。 + - Comfy dtype: INT + - Python dtype: int +- interpolation + - 参数 `interpolation` 允许在调整图像大小时选择不同的插值方法。它影响最终图像的平滑度和外观。 + - Comfy dtype: COMBO[linear, ease_in, ease_out, ease_in_out] + - Python dtype: str +- azimuth_points_string + - 参数 `azimuth_points_string` 包含用于角度插值的方位点的字符串表示。它在定义图像处理中的角过渡中至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- elevation_points_string + - 参数 `elevation_points_string` 以字符串形式指定高度点,用于控制图像处理过程中的垂直角度过渡。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- positive + - 输出 `positive` 包含从图像处理中得到的正向条件数据。它用于引导生成与输入图像相似的图像。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] +- negative + - 输出 `negative` 提供了负向条件数据,用于引导生成与输入图像不同的图像。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, torch.Tensor]]] +- latent + - 输出 `latent` 表示节点生成的潜在图像样本。这些样本是输入图像的低维表示,适用于各种图像生成任务。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class StableZero123_BatchSchedule: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'clip_vision': ('CLIP_VISION',), 'init_image': ('IMAGE',), 'vae': ('VAE',), 'width': ('INT', {'default': 256, 'min': 16, 'max': MAX_RESOLUTION, 'step': 8}), 'height': ('INT', {'default': 256, 'min': 16, 'max': MAX_RESOLUTION, 'step': 8}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 4096}), 'interpolation': (['linear', 'ease_in', 'ease_out', 'ease_in_out'],), 'azimuth_points_string': ('STRING', {'default': '0:(0.0),\n7:(1.0),\n15:(0.0)\n', 'multiline': True}), 'elevation_points_string': ('STRING', {'default': '0:(0.0),\n7:(0.0),\n15:(0.0)\n', 'multiline': True})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING', 'LATENT') + RETURN_NAMES = ('positive', 'negative', 'latent') + FUNCTION = 'encode' + CATEGORY = 'KJNodes/experimental' + + def encode(self, clip_vision, init_image, vae, width, height, batch_size, azimuth_points_string, elevation_points_string, interpolation): + output = clip_vision.encode_image(init_image) + pooled = output.image_embeds.unsqueeze(0) + pixels = comfy.utils.common_upscale(init_image.movedim(-1, 1), width, height, 'bilinear', 'center').movedim(1, -1) + encode_pixels = pixels[:, :, :, :3] + t = vae.encode(encode_pixels) + + def ease_in(t): + return t * t + + def ease_out(t): + return 1 - (1 - t) * (1 - t) + + def ease_in_out(t): + return 3 * t * t - 2 * t * t * t + azimuth_points = [] + azimuth_points_string = azimuth_points_string.rstrip(',\n') + for point_str in azimuth_points_string.split(','): + (frame_str, azimuth_str) = point_str.split(':') + frame = int(frame_str.strip()) + azimuth = float(azimuth_str.strip()[1:-1]) + azimuth_points.append((frame, azimuth)) + azimuth_points.sort(key=lambda x: x[0]) + elevation_points = [] + elevation_points_string = elevation_points_string.rstrip(',\n') + for point_str in elevation_points_string.split(','): + (frame_str, elevation_str) = point_str.split(':') + frame = int(frame_str.strip()) + elevation_val = float(elevation_str.strip()[1:-1]) + elevation_points.append((frame, elevation_val)) + elevation_points.sort(key=lambda x: x[0]) + next_point = 1 + next_elevation_point = 1 + positive_cond_out = [] + positive_pooled_out = [] + negative_cond_out = [] + negative_pooled_out = [] + for i in range(batch_size): + while next_point < len(azimuth_points) and i >= azimuth_points[next_point][0]: + next_point += 1 + if next_point == len(azimuth_points): + next_point -= 1 + prev_point = max(next_point - 1, 0) + if azimuth_points[next_point][0] != azimuth_points[prev_point][0]: + fraction = (i - azimuth_points[prev_point][0]) / (azimuth_points[next_point][0] - azimuth_points[prev_point][0]) + if interpolation == 'ease_in': + fraction = ease_in(fraction) + elif interpolation == 'ease_out': + fraction = ease_out(fraction) + elif interpolation == 'ease_in_out': + fraction = ease_in_out(fraction) + interpolated_azimuth = interpolate_angle(azimuth_points[prev_point][1], azimuth_points[next_point][1], fraction) + else: + interpolated_azimuth = azimuth_points[prev_point][1] + next_elevation_point = 1 + while next_elevation_point < len(elevation_points) and i >= elevation_points[next_elevation_point][0]: + next_elevation_point += 1 + if next_elevation_point == len(elevation_points): + next_elevation_point -= 1 + prev_elevation_point = max(next_elevation_point - 1, 0) + if elevation_points[next_elevation_point][0] != elevation_points[prev_elevation_point][0]: + fraction = (i - elevation_points[prev_elevation_point][0]) / (elevation_points[next_elevation_point][0] - elevation_points[prev_elevation_point][0]) + if interpolation == 'ease_in': + fraction = ease_in(fraction) + elif interpolation == 'ease_out': + fraction = ease_out(fraction) + elif interpolation == 'ease_in_out': + fraction = ease_in_out(fraction) + interpolated_elevation = interpolate_angle(elevation_points[prev_elevation_point][1], elevation_points[next_elevation_point][1], fraction) + else: + interpolated_elevation = elevation_points[prev_elevation_point][1] + cam_embeds = camera_embeddings(interpolated_elevation, interpolated_azimuth) + cond = torch.cat([pooled, cam_embeds.repeat((pooled.shape[0], 1, 1))], dim=-1) + positive_pooled_out.append(t) + positive_cond_out.append(cond) + negative_pooled_out.append(torch.zeros_like(t)) + negative_cond_out.append(torch.zeros_like(pooled)) + final_positive_cond = torch.cat(positive_cond_out, dim=0) + final_positive_pooled = torch.cat(positive_pooled_out, dim=0) + final_negative_cond = torch.cat(negative_cond_out, dim=0) + final_negative_pooled = torch.cat(negative_pooled_out, dim=0) + final_positive = [[final_positive_cond, {'concat_latent_image': final_positive_pooled}]] + final_negative = [[final_negative_cond, {'concat_latent_image': final_negative_pooled}]] + latent = torch.zeros([batch_size, 4, height // 8, width // 8]) + return (final_positive, final_negative, {'samples': latent}) +``` \ No newline at end of file diff --git a/docs/Stack Images (mtb).md b/docs/Stack Images (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/StepsScheduleHookProvider.md b/docs/StepsScheduleHookProvider.md new file mode 100644 index 0000000..f68efe3 --- /dev/null +++ b/docs/StepsScheduleHookProvider.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: StepsScheduleHookProvider +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +StepsScheduleHookProvider节点旨在促进创建和管理迭代过程的调度钩子。它抽象了定义计划的复杂性,允许用户指定迭代过程的计划类型和目标步骤。该节点的主要作用是根据用户的选择实例化适当的调度钩子,从而简化了设置迭代工作流程的过程。 + +# Input types +## Required +- schedule_for_iteration + - 参数'schedule_for_iteration'对于确定要使用的调度钩子类型至关重要。它通过从预定义的计划中选择来决定迭代过程的行为。此参数直接影响节点的执行策略和生成的调度模式。 + - Comfy dtype: STRING + - Python dtype: str +- target_steps + - 参数'target_steps'定义了迭代过程中要采取的步骤数。它是控制过程持续时间和范围的关键因素。此参数对于调整节点的操作以满足当前任务的特定要求或约束至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- hook + - 输出'hook'是一个调度钩子对象,它封装了根据指定的计划和目标步骤管理迭代过程的逻辑。它很重要,因为它代表了节点的主要输出,用于控制迭代工作流程。 + - Comfy dtype: PK_HOOK + - Python dtype: PixelKSampleHook + +# Usage tips +- Infra type: CPU + +# Source code +``` +class StepsScheduleHookProvider: + schedules = ['simple'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'schedule_for_iteration': (s.schedules,), 'target_steps': ('INT', {'default': 20, 'min': 1, 'max': 10000})}} + RETURN_TYPES = ('PK_HOOK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + def doit(self, schedule_for_iteration, target_steps): + hook = None + if schedule_for_iteration == 'simple': + hook = hooks.SimpleStepsScheduleHook(target_steps) + return (hook,) +``` \ No newline at end of file diff --git a/docs/String Replace (mtb).md b/docs/String Replace (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/String to Text.md b/docs/String to Text.md new file mode 100644 index 0000000..e5f6b9b --- /dev/null +++ b/docs/String to Text.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_String_To_Text +- Category: WAS Suite/Text/Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 `string_to_text` 旨在将给定的字符串转换成可以进一步处理或分析的文本格式。它在文本操作中扮演着关键角色,确保输入字符串被正确格式化以便于后续任务,例如文本分析或需要文本数据的机器学习模型。 + +# Input types +## Required +- string + - 参数 'string' 是必需的,因为它代表了节点将处理的原始文本输入。其适当的格式化和内容显著影响节点将其转换成可用文本格式的能力。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- text + - 输出 'text' 是节点操作的结果,提供了从输入字符串转换而来的文本格式。它很重要,因为它是下游文本相关流程中使用的主要输出。 + - Comfy dtype: TEXT + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_String_To_Text: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'string': ('STRING', {})}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'string_to_text' + CATEGORY = 'WAS Suite/Text/Operations' + + def string_to_text(self, string): + return (string,) +``` \ No newline at end of file diff --git a/docs/StringConcatenate.md b/docs/StringConcatenate.md new file mode 100644 index 0000000..7940c0a --- /dev/null +++ b/docs/StringConcatenate.md @@ -0,0 +1,82 @@ +# Documentation +- Class name: StringConcatenate +- Category: FizzNodes 📅🅕🅝/FrameNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +StringConcatenate节点旨在高效地将具有相关帧编号的字符串进行拼接。它通过结合文本输入及其对应的帧,发挥着创建结构化数据表示的关键作用。该节点简化了为各种应用生成格式化字符串输出的过程。 + +# Input types +## Required +- text_a + - 'text_a'参数是一个强制性的字符串输入,代表要被拼接的第一个文本内容。它对节点的操作至关重要,因为它构成了结构化数据的初始部分。 + - Comfy dtype: STRING + - Python dtype: str +- frame_a + - 'frame_a'参数是一个整数,它指定与'text_a'关联的帧编号。这对于以帧特定的方式组织文本数据至关重要。 + - Comfy dtype: INT + - Python dtype: int +- text_b + - 'text_b'参数是另一个强制性的字符串输入,代表要被拼接的第二个文本内容。它对于用额外信息扩展结构化数据很重要。 + - Comfy dtype: STRING + - Python dtype: str +- frame_b + - 'frame_b'参数是一个整数,它指定与'text_b'关联的帧编号。它在基于帧组织文本数据方面扮演着重要角色。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- text_c + - 'text_c'参数是一个可选的字符串输入,可以被包含以进行进一步的拼接。它提供了将更多文本内容添加到结构化数据中的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- frame_c + - 'frame_c'参数是一个可选的整数,如果提供了'text_c',则指定一个帧编号。它用于基于帧组织额外的文本数据。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result + - 'result'参数代表节点的拼接字符串输出。它是将所有提供的文本输入及其各自的帧编号组合成单一的结构化格式的结果。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class StringConcatenate: + + def __init__(self): + pass + defaultPrompt = '"0" :"",\n "12" :"",\n "24" :"",\n "36" :"",\n "48" :"",\n "60" :"",\n "72" :"",\n "84" :"",\n "96" :"",\n "108" :"",\n "120" :""\n ' + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text_a': ('STRING', {'forceInput': True, 'multiline': True, 'default': ''}), 'frame_a': ('INT', {'default': 0}), 'text_b': ('STRING', {'forceInput': True, 'multiline': True, 'default': ''}), 'frame_b': ('INT', {'default': 12})}, 'optional': {'text_c': ('STRING', {'forceInput': True, 'multiline': True, 'default': ''}), 'frame_c': ('INT', {'default': 24}), 'text_d': ('STRING', {'forceInput': True, 'multiline': True, 'default': ''}), 'frame_d': ('INT', {'default': 36}), 'text_e': ('STRING', {'forceInput': True, 'multiline': True, 'default': ''}), 'frame_e': ('INT', {'default': 48}), 'text_f': ('STRING', {'forceInput': True, 'multiline': True, 'default': ''}), 'frame_f': ('INT', {'default': 60}), 'text_g': ('STRING', {'forceInput': True, 'multiline': True, 'default': ''}), 'frame_g': ('INT', {'default': 72})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'frame_concatenate_list' + CATEGORY = 'FizzNodes 📅🅕🅝/FrameNodes' + + def frame_concatenate_list(self, text_a, frame_a, text_b, frame_b, text_c=None, frame_c=None, text_d=None, frame_d=None, text_e=None, frame_e=None, text_f=None, frame_f=None, text_g=None, frame_g=None): + text_a = text_a.replace('\n', '') + text_b = text_b.replace('\n', '') + text_c = text_c.replace('\n', '') if text_c is not None else None + text_d = text_d.replace('\n', '') if text_d is not None else None + text_e = text_e.replace('\n', '') if text_e is not None else None + text_f = text_f.replace('\n', '') if text_f is not None else None + text_g = text_g.replace('\n', '') if text_g is not None else None + text_list = f'"{frame_a}": "{text_a}",' + text_list += f'"{frame_b}": "{text_b}",' + if frame_c is not None and text_c is not None: + text_list += f'"{frame_c}": "{text_c}",' + if frame_d is not None and text_d is not None: + text_list += f'"{frame_d}": "{text_d}",' + if frame_e is not None and text_e is not None: + text_list += f'"{frame_e}": "{text_e}",' + if frame_f is not None and text_f is not None: + text_list += f'"{frame_f}": "{text_f}",' + if frame_g is not None and text_g is not None: + text_list += f'"{frame_g}": "{text_g}",' + return (text_list,) +``` \ No newline at end of file diff --git a/docs/StringConstant.md b/docs/StringConstant.md new file mode 100644 index 0000000..7de12a8 --- /dev/null +++ b/docs/StringConstant.md @@ -0,0 +1,38 @@ +# Documentation +- Class name: StringConstant +- Category: KJNodes/constants +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +StringConstant节点旨在数据处理工作流中提供一个固定的字符串值。它作为一个工具,用于那些需要一个固定字符串作为后续操作输入的情况,而不需要动态更改。 + +# Input types +## Required +- string + - ‘string’参数对于定义节点将输出的常量字符串值至关重要。它在节点的操作中起着关键作用,因为它直接决定了将传递给下游流程的数据。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- output + - ‘output’参数代表节点返回的字符串值。它很重要,因为它是节点的唯一输出,确保所提供的字符串在工作流的后续步骤中被正确使用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class StringConstant: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'string': ('STRING', {'default': '', 'multiline': False})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'passtring' + CATEGORY = 'KJNodes/constants' + + def passtring(self, string): + return (string,) +``` \ No newline at end of file diff --git a/docs/StringConstantMultiline.md b/docs/StringConstantMultiline.md new file mode 100644 index 0000000..aa83470 --- /dev/null +++ b/docs/StringConstantMultiline.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: StringConstantMultiline +- Category: KJNodes/constants +- Output node: False +- Repo Ref: https://github.com/kijai/ComfyUI-KJNodes.git + +`StringConstantMultiline` 节点旨在处理和操作多行字符串。它提供将多行输入转换为单个字符串的功能,可选择性地剥离换行符以创建连续的文本块。该节点特别适用于需要进一步处理或显示的清洁、格式化文本的任务。 + +# Input types +## Required +- string + - “string”参数是节点的主要输入,期望一个多行字符串。它在节点的操作中起着关键作用,因为它是将要处理的文本。节点处理多行输入的能力对于需要跨多行进行文本操作的应用程序来说非常重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- strip_newlines + - “strip_newlines”参数是一个可选的布尔标志,用于确定是否应从输入字符串中删除换行符。当设置为True时,它确保输出是一个没有换行符的单一连续文本块,这对于某些文本处理任务来说很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- new_string + - “new_string”输出是输入字符串的加工版本,根据“strip_newlines”参数,可能会删除换行符。这个输出很重要,因为它代表了可以用于后续操作或分析的最终格式化文本。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class StringConstantMultiline: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'string': ('STRING', {'default': '', 'multiline': True}), 'strip_newlines': ('BOOLEAN', {'default': True})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'stringify' + CATEGORY = 'KJNodes/constants' + + def stringify(self, string, strip_newlines): + new_string = [] + for line in io.StringIO(string): + if not line.strip().startswith('\n') and strip_newlines: + line = line.replace('\n', '') + new_string.append(line) + new_string = '\n'.join(new_string) + return (new_string,) +``` \ No newline at end of file diff --git a/docs/StringSchedule.md b/docs/StringSchedule.md new file mode 100644 index 0000000..f807833 --- /dev/null +++ b/docs/StringSchedule.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: StringSchedule +- Category: FizzNodes 📅🅕🅝/ScheduleNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +StringSchedule节点旨在处理和动画化基于文本的日程。它接受各种参数以定制动画过程,包括文本、帧限制和当前帧索引。该节点的主要功能是生成一系列可以用于动画或调度目的的提示,将基于帧的动画的复杂性抽象为一个简单、由文本驱动的界面。 + +# Input types +## Required +- text + - ‘text’参数是节点用来生成动画提示的原始文本输入。它至关重要,因为它直接影响输出提示的内容和结构。该参数支持多行输入,允许复杂和详细的描述。 + - Comfy dtype: STRING + - Python dtype: str +- max_frames + - ‘max_frames’参数定义了动画序列的最大帧数。它在确定动画的持续时间和帧间隔方面起着重要作用,影响着整体的节奏和流畅度。 + - Comfy dtype: INT + - Python dtype: int +- current_frame + - ‘current_frame’参数指示动画序列中的当前位置。它对于确定在任何给定时刻使用哪个提示至关重要,从而控制动画的状态。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- print_output + - ‘print_output’参数是一个可选的标志,当设置为True时,会将动画提示的输出打印到控制台。这对于调试或以基于文本的格式可视化动画序列非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- pre_text + - ‘pre_text’参数用于在每个帧的提示前添加文本。它可以用来添加应该出现在动画序列中每个提示开头的上下文或额外信息。 + - Comfy dtype: STRING + - Python dtype: str +- app_text + - ‘app_text’参数被添加到每个帧的提示后,允许向动画序列添加结尾或补充文本。它可以通过额外的细节或结束语来增强最终输出。 + - Comfy dtype: STRING + - Python dtype: str +- pw_a + - ‘pw_a’参数是动画提示插值过程中使用的加权因子。它影响提示在动画中的平衡和分布,允许微调动画的进展。 + - Comfy dtype: FLOAT + - Python dtype: float +- pw_b + - ‘pw_b’参数是动画插值中的另一个加权因子,与‘pw_a’互补,以在序列中实现所需的效果或强调。 + - Comfy dtype: FLOAT + - Python dtype: float +- pw_c + - ‘pw_c’参数是用于插值提示的加权系统的一部分,为动画发展的细节提供额外的控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- pw_d + - ‘pw_d’参数是权重系列中的最后一个加权因子,提供了对提示在动画中如何插值的最后层面的影响。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- POS + - 'POS'输出代表了从输入文本和参数派生的当前积极提示。它是动画序列的关键部分,为给定帧提供肯定或主要内容。 + - Comfy dtype: STRING + - Python dtype: str +- NEG + - 'NEG'输出表示当前的消极提示,通过为帧提供对比或替代内容来补充'POS'输出,增强了动画的整体深度和复杂性。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class StringSchedule: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True, 'default': defaultPrompt}), 'max_frames': ('INT', {'default': 120.0, 'min': 1.0, 'max': 999999.0, 'step': 1.0}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 999999.0, 'step': 1.0}), 'print_output': ('BOOLEAN', {'default': False})}, 'optional': {'pre_text': ('STRING', {'multiline': True}), 'app_text': ('STRING', {'multiline': True}), 'pw_a': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_b': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_c': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1}), 'pw_d': ('FLOAT', {'default': 0.0, 'min': -9999.0, 'max': 9999.0, 'step': 0.1})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('POS', 'NEG') + FUNCTION = 'animate' + CATEGORY = 'FizzNodes 📅🅕🅝/ScheduleNodes' + + def animate(self, text, max_frames, current_frame, pw_a=0, pw_b=0, pw_c=0, pw_d=0, pre_text='', app_text='', print_output=False): + current_frame = current_frame % max_frames + inputText = str('{' + text + '}') + inputText = re.sub(',\\s*}', '}', inputText) + animation_prompts = json.loads(inputText.strip()) + start_frame = 0 + (pos, neg) = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text) + (pos_cur_prompt, pos_nxt_prompt, weight) = interpolate_prompt_series(pos, max_frames, 0, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) + (neg_cur_prompt, neg_nxt_prompt, weight) = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) + return (pos_cur_prompt[current_frame], neg_cur_prompt[current_frame]) +``` \ No newline at end of file diff --git a/docs/Style Conditioner Base Only.md b/docs/Style Conditioner Base Only.md new file mode 100644 index 0000000..e74501c --- /dev/null +++ b/docs/Style Conditioner Base Only.md @@ -0,0 +1,86 @@ +# Documentation +- Class name: StyleConditionerBaseOnly +- Category: Mikey/Conditioning +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +StyleConditionerBaseOnly节点的'add_style'方法旨在将用户定义的样式集成到调节过程中。它通过结合正面和负面提示与基础调节元素,允许应用风格偏好。该方法智能地管理这些样式的整合,根据指定的强度因子调整它们的影响,并支持使用种子进行样式选择。这个节点在启用生成过程中的风格控制中起着至关重要的作用,而本身并不直接处理生成。 + +# Input types +## Required +- style + - “style”参数在确定调节过程的风格方向中起着关键作用。它决定了将用于指导生成的特定正面和负面提示。风格的选择对结果输出有深远的影响,使其成为节点操作中的一个重要元素。 + - Comfy dtype: STRING + - Python dtype: str +- strength + - “strength”参数控制应用于调节过程的风格影响的强度。它是一个浮点数,用于调整样式影响的权重,允许在输出中微调风格元素。这个参数对于实现风格控制和基础调节元素之间期望的平衡至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- positive_cond_base + - “positive_cond_base”参数代表将受到样式影响的基础正面调节元素。它是节点操作中的一个关键组件,因为它构成了应用风格调整的基础。该参数对于建立生成过程的初始正面上下文至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Conditioning +- negative_cond_base + - “negative_cond_base”参数是将受到样式影响的基础负面调节元素。它在塑造输出中起着重要作用,通过提供正面调节的平衡来形成对比。这个参数对于确保生成的内容符合所需的风格约束,同时避免不希望的元素至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Conditioning +- base_clip + - “base_clip”参数是作为调节过程视觉基础的参考图像或剪辑。它对于提供风格将被应用的稳定视觉上下文至关重要。这个参数对于确保在特定的视觉框架中进行风格调整至关重要。 + - Comfy dtype: CLIP + - Python dtype: CLIP +## Optional +- use_seed + - “use_seed”参数决定是否应该使用种子值从可用选项中选择样式。当设置为'true'时,它为样式选择过程引入了随机性元素,这对于多样化输出可能是有益的。这个参数对于增加生成过程的可变性很重要。 + - Comfy dtype: COMBO['true', 'false'] + - Python dtype: str +- seed + - “seed”参数与“use_seed”参数结合使用,用于控制样式选择中的随机性。它为随机数生成器提供了一个特定的参考点,确保了可重复的选择过程。当涉及随机性时,这个参数对于在节点的多次运行中保持一致性非常重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- base_pos_cond + - “base_pos_cond”输出代表了应用样式后更新的正面调节元素。它是节点操作中的一个关键组件,因为它将风格调整带入生成过程的后续阶段。 + - Comfy dtype: CONDITIONING + - Python dtype: Conditioning +- base_neg_cond + - “base_neg_cond”输出是在应用样式后更新的负面调节元素。它在确保生成的内容符合风格约束并避免不希望的元素方面起着重要作用。 + - Comfy dtype: CONDITIONING + - Python dtype: Conditioning +- style_str + - “style_str”输出提供了已应用样式的文本表示。它作为调节过程中做出的风格选择的记录,对于跟踪和记录生成参数可能是有用的。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class StyleConditionerBaseOnly: + + @classmethod + def INPUT_TYPES(s): + (s.styles, s.pos_style, s.neg_style) = read_styles() + return {'required': {'style': (s.styles,), 'strength': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'positive_cond_base': ('CONDITIONING',), 'negative_cond_base': ('CONDITIONING',), 'base_clip': ('CLIP',), 'use_seed': (['true', 'false'], {'default': 'false'}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING', 'STRING') + RETURN_NAMES = ('base_pos_cond', 'base_neg_cond', 'style_str') + FUNCTION = 'add_style' + CATEGORY = 'Mikey/Conditioning' + + def add_style(self, style, strength, positive_cond_base, negative_cond_base, base_clip, use_seed, seed): + if use_seed == 'true' and len(self.styles) > 0: + offset = seed % len(self.styles) + style = self.styles[offset] + pos_prompt = self.pos_style[style] + neg_prompt = self.neg_style[style] + pos_prompt = pos_prompt.replace('{prompt}', '') + neg_prompt = neg_prompt.replace('{prompt}', '') + if style == 'none': + return (positive_cond_base, negative_cond_base, style) + positive_cond_base_new = CLIPTextEncodeSDXL.encode(self, base_clip, 1024, 1024, 0, 0, 1024, 1024, pos_prompt, pos_prompt)[0] + negative_cond_base_new = CLIPTextEncodeSDXL.encode(self, base_clip, 1024, 1024, 0, 0, 1024, 1024, neg_prompt, neg_prompt)[0] + positive_cond_base = ConditioningAverage.addWeighted(self, positive_cond_base_new, positive_cond_base, strength)[0] + negative_cond_base = ConditioningAverage.addWeighted(self, negative_cond_base_new, negative_cond_base, strength)[0] + return (positive_cond_base, negative_cond_base, style) +``` \ No newline at end of file diff --git a/docs/Style Conditioner.md b/docs/Style Conditioner.md new file mode 100644 index 0000000..c3c872d --- /dev/null +++ b/docs/Style Conditioner.md @@ -0,0 +1,109 @@ +# Documentation +- Class name: StyleConditioner +- Category: Mikey/Conditioning +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +StyleConditioner节点旨在管理和应用风格条件到生成过程中。它允许集成正面和负面的风格提示,使得生成的内容可以微调以符合所需的风格属性。该节点在引导生成过程朝向特定的美学或艺术方向中发挥关键作用。 + +# Input types +## Required +- style + - ‘style’参数对于确定生成过程的风格方向至关重要。它影响着选择正面和负面提示,这些提示将塑造输出结果。 + - Comfy dtype: STRING + - Python dtype: str +- strength + - ‘strength’参数调整风格对生成过程影响的强度。它在控制风格特征在输出中反映的程度时非常重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- positive_cond_base + - ‘positive_cond_base’参数代表将与新的正面提示结合的基本正面条件元素,以细化生成的风格。 + - Comfy dtype: CONDITIONING + - Python dtype: Conditioning +- negative_cond_base + - ‘negative_cond_base’参数表示在生成过程中用来平衡风格影响的基本负面条件元素。 + - Comfy dtype: CONDITIONING + - Python dtype: Conditioning +- positive_cond_refiner + - ‘positive_cond_refiner’参数用于在生成过程中进一步细化风格的正面方面。 + - Comfy dtype: CONDITIONING + - Python dtype: Conditioning +- negative_cond_refiner + - ‘negative_cond_refiner’参数用于确保在最终输出中最小化风格的负面方面。 + - Comfy dtype: CONDITIONING + - Python dtype: Conditioning +- base_clip + - ‘base_clip’参数对于将基本的正面和负面提示编码成可以由生成模型处理的形式至关重要。 + - Comfy dtype: CLIP + - Python dtype: Clip +- refiner_clip + - ‘refiner_clip’参数用于编码经过精炼的正面和负面提示,以进一步增强风格对生成的影响。 + - Comfy dtype: CLIP + - Python dtype: Clip +- use_seed + - ‘use_seed’参数决定是否基于提供的种子选择特定的风格,为风格选择过程增加了一层控制。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- seed + - ‘seed’参数与‘use_seed’标志一起使用,当使用种子时,用于指定风格选择的起始点。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- base_pos_cond + - ‘base_pos_cond’输出代表了更新后的基本正面条件,反映了集成的风格特征。 + - Comfy dtype: CONDITIONING + - Python dtype: Conditioning +- base_neg_cond + - ‘base_neg_cond’输出表示更新后的基本负面条件,有助于从生成中排除不需要的风格元素。 + - Comfy dtype: CONDITIONING + - Python dtype: Conditioning +- refiner_pos_cond + - ‘refiner_pos_cond’输出是经过精炼的正面条件元素,进一步塑造了生成内容的风格。 + - Comfy dtype: CONDITIONING + - Python dtype: Conditioning +- refiner_neg_cond + - ‘refiner_neg_cond’输出是经过精炼的负面条件元素,确保在生成中排除负面风格方面。 + - Comfy dtype: CONDITIONING + - Python dtype: Conditioning +- style_str + - ‘style_str’输出提供了应用风格的文本表示,提供了风格对生成影响的描述性总结。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class StyleConditioner: + + @classmethod + def INPUT_TYPES(s): + (s.styles, s.pos_style, s.neg_style) = read_styles() + return {'required': {'style': (s.styles,), 'strength': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.1}), 'positive_cond_base': ('CONDITIONING',), 'negative_cond_base': ('CONDITIONING',), 'positive_cond_refiner': ('CONDITIONING',), 'negative_cond_refiner': ('CONDITIONING',), 'base_clip': ('CLIP',), 'refiner_clip': ('CLIP',), 'use_seed': (['true', 'false'], {'default': 'false'}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('CONDITIONING', 'CONDITIONING', 'CONDITIONING', 'CONDITIONING', 'STRING') + RETURN_NAMES = ('base_pos_cond', 'base_neg_cond', 'refiner_pos_cond', 'refiner_neg_cond', 'style_str') + FUNCTION = 'add_style' + CATEGORY = 'Mikey/Conditioning' + + def add_style(self, style, strength, positive_cond_base, negative_cond_base, positive_cond_refiner, negative_cond_refiner, base_clip, refiner_clip, use_seed, seed): + if use_seed == 'true' and len(self.styles) > 0: + offset = seed % len(self.styles) + style = self.styles[offset] + pos_prompt = self.pos_style[style] + neg_prompt = self.neg_style[style] + pos_prompt = pos_prompt.replace('{prompt}', '') + neg_prompt = neg_prompt.replace('{prompt}', '') + if style == 'none': + return (positive_cond_base, negative_cond_base, positive_cond_refiner, negative_cond_refiner, style) + positive_cond_base_new = CLIPTextEncodeSDXL.encode(self, base_clip, 1024, 1024, 0, 0, 1024, 1024, pos_prompt, pos_prompt)[0] + negative_cond_base_new = CLIPTextEncodeSDXL.encode(self, base_clip, 1024, 1024, 0, 0, 1024, 1024, neg_prompt, neg_prompt)[0] + positive_cond_refiner_new = CLIPTextEncodeSDXLRefiner.encode(self, refiner_clip, 6, 4096, 4096, pos_prompt)[0] + negative_cond_refiner_new = CLIPTextEncodeSDXLRefiner.encode(self, refiner_clip, 2.5, 4096, 4096, neg_prompt)[0] + positive_cond_base = ConditioningAverage.addWeighted(self, positive_cond_base_new, positive_cond_base, strength)[0] + negative_cond_base = ConditioningAverage.addWeighted(self, negative_cond_base_new, negative_cond_base, strength)[0] + positive_cond_refiner = ConditioningAverage.addWeighted(self, positive_cond_refiner_new, positive_cond_refiner, strength)[0] + negative_cond_refiner = ConditioningAverage.addWeighted(self, negative_cond_refiner_new, negative_cond_refiner, strength)[0] + return (positive_cond_base, negative_cond_base, positive_cond_refiner, negative_cond_refiner, style) +``` \ No newline at end of file diff --git a/docs/StyleAlignedBatchAlign.md b/docs/StyleAlignedBatchAlign.md new file mode 100644 index 0000000..133610c --- /dev/null +++ b/docs/StyleAlignedBatchAlign.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: StyleAlignedBatchAlign +- Category: style_aligned +- Output node: False +- Repo Ref: https://github.com/brianfitzgerald/style_aligned_comfy + +StyleAlignedBatchAlign类旨在通过跨批次对齐模型的风格特征来修改给定模型,增强模型处理和生成风格对齐输出的能力。该节点专注于风格元素的概念整合,确保模型的注意力和归一化层针对风格一致性进行优化。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了将要修改以跨批次对齐风格特征的基础架构。它是决定StyleAlignedBatchAlign节点后续行为和功能的主要输入。 + - Comfy dtype: ModelPatcher + - Python dtype: comfy.model_patcher.ModelPatcher +- share_norm + - share_norm参数对于确定模型内部的归一化层应该如何共享或修改至关重要。它影响模型内风格特征对齐的效率和效果。 + - Comfy dtype: str + - Python dtype: str +- share_attn + - share_attn参数指定了哪些注意力机制应该被共享或修改以实现风格对齐。它在模型的整体风格处理能力中扮演着重要角色。 + - Comfy dtype: str + - Python dtype: str +## Optional +- scale + - scale参数调整应用于注意力和归一化层的风格对齐程度。它微妙地影响模型生成跨批次风格一致的输出的能力。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- MODEL + - 输出模型是StyleAlignedBatchAlign节点操作的结果,代表了输入模型的修改版本,该版本针对风格对齐处理进行了优化。它是节点在模型架构内集成和对齐风格特征努力的结晶。 + - Comfy dtype: ModelPatcher + - Python dtype: comfy.model_patcher.ModelPatcher + +# Usage tips +- Infra type: CPU + +# Source code +``` +class StyleAlignedBatchAlign: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('MODEL',), 'share_norm': (SHARE_NORM_OPTIONS,), 'share_attn': (SHARE_ATTN_OPTIONS,), 'scale': ('FLOAT', {'default': 1, 'min': 0, 'max': 1.0, 'step': 0.1})}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'patch' + CATEGORY = 'style_aligned' + + def patch(self, model: ModelPatcher, share_norm: str, share_attn: str, scale: float): + m = model.clone() + share_group_norm = share_norm in ['group', 'both'] + share_layer_norm = share_norm in ['layer', 'both'] + register_shared_norm(model, share_group_norm, share_layer_norm) + args = StyleAlignedArgs(share_attn) + m.set_model_attn1_patch(SharedAttentionProcessor(args, scale)) + return (m,) +``` \ No newline at end of file diff --git a/docs/StyleAlignedReferenceSampler.md b/docs/StyleAlignedReferenceSampler.md new file mode 100644 index 0000000..d82c0a9 --- /dev/null +++ b/docs/StyleAlignedReferenceSampler.md @@ -0,0 +1,143 @@ +# Documentation +- Class name: StyleAlignedReferenceSampler +- Category: style_aligned +- Output node: False +- Repo Ref: https://github.com/brianfitzgerald/style_aligned_comfy + +StyleAlignedReferenceSampler类旨在促进风格对齐的潜在空间采样,确保生成的内容遵循特定的风格参考。它整合了注意力机制和规范化技术来精炼输出,为生成模型中的风格对齐提供了细致的方法。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了用于风格对齐采样的生成模型的基础架构和参数。它是风格对齐和采样过程构建的基础。 + - Comfy dtype: MODEL + - Python dtype: ModelPatcher +- share_norm + - share_norm参数决定模型中不同层或组之间的规范化层如何共享,这通过控制信息流对风格对齐过程产生重大影响。 + - Comfy dtype: SHARE_NORM_OPTIONS + - Python dtype: str +- share_attn + - share_attn参数决定了模型中注意力机制的共享策略,这对于通过影响注意力权重使生成内容与期望风格对齐至关重要。 + - Comfy dtype: SHARE_ATTN_OPTIONS + - Python dtype: str +- scale + - scale参数调整风格参考对生成样本的影响,允许微调风格对齐以实现期望的审美结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- batch_size + - batch_size决定了同时处理的样本数量,这影响了风格对齐采样过程的效率和速度。 + - Comfy dtype: INT + - Python dtype: int +- noise_seed + - noise_seed用于生成采样过程中的噪声向量,确保风格对齐的样本可以一致地复现。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数影响采样过程的配置,特别是模型如何响应条件输入,这对于实现准确风格对齐至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- positive + - 正面条件输入对于引导模型朝向期望的风格特征至关重要,作为风格对齐过程的参考。 + - Comfy dtype: CONDITIONING + - Python dtype: T +- negative + - 负面条件输入通过指定要避免的不期望特征来帮助完善模型的输出,提高了风格对齐的精确度。 + - Comfy dtype: CONDITIONING + - Python dtype: T +- ref_positive + - ref_positive条件输入提供了额外的风格参考层,进一步确保生成的样本与目标风格紧密匹配。 + - Comfy dtype: CONDITIONING + - Python dtype: T +- sampler + - sampler参数定义了采样策略,这对于风格对齐输出的多样性和质量至关重要。 + - Comfy dtype: SAMPLER + - Python dtype: T +- sigmas + - sigmas参数用于控制在采样过程中应用的噪声水平,直接影响风格对齐样本的平滑度和连贯性。 + - Comfy dtype: SIGMAS + - Python dtype: T +- ref_latents + - ref_latents提供了一组作为风格对齐参考的潜在表示,确保输出样本遵循期望的风格细节。 + - Comfy dtype: STEP_LATENTS + - Python dtype: T + +# Output types +- output + - 输出参数包含模型生成的风格对齐潜在样本,这是采样过程的主要结果,可以进一步处理或分析。 + - Comfy dtype: LATENT + - Python dtype: dict +- denoised_output + - denoised_output参数提供了经过处理以减少噪声和增强清晰度的精炼潜在样本,提供了目标风格的更清晰表示。 + - Comfy dtype: LATENT + - Python dtype: dict + +# Usage tips +- Infra type: GPU + +# Source code +``` +class StyleAlignedReferenceSampler: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('MODEL',), 'share_norm': (SHARE_NORM_OPTIONS,), 'share_attn': (SHARE_ATTN_OPTIONS,), 'scale': ('FLOAT', {'default': 1, 'min': 0, 'max': 2.0, 'step': 0.01}), 'batch_size': ('INT', {'default': 2, 'min': 1, 'max': 8, 'step': 1}), 'noise_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'cfg': ('FLOAT', {'default': 8.0, 'min': 0.0, 'max': 100.0, 'step': 0.1, 'round': 0.01}), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'ref_positive': ('CONDITIONING',), 'sampler': ('SAMPLER',), 'sigmas': ('SIGMAS',), 'ref_latents': ('STEP_LATENTS',)}} + RETURN_TYPES = ('LATENT', 'LATENT') + RETURN_NAMES = ('output', 'denoised_output') + FUNCTION = 'patch' + CATEGORY = 'style_aligned' + + def patch(self, model: ModelPatcher, share_norm: str, share_attn: str, scale: float, batch_size: int, noise_seed: int, cfg: float, positive: T, negative: T, ref_positive: T, sampler: T, sigmas: T, ref_latents: T) -> 'tuple[dict, dict]': + m = model.clone() + args = StyleAlignedArgs(share_attn) + style_latent_tensor = ref_latents[0].unsqueeze(0) + (height, width) = style_latent_tensor.shape[-2:] + latent_t = torch.zeros([batch_size, 4, height, width], device=ref_latents.device) + latent = {'samples': latent_t} + noise = comfy.sample.prepare_noise(latent_t, noise_seed) + latent_t = torch.cat((style_latent_tensor, latent_t), dim=0) + ref_noise = torch.zeros_like(noise[0]).unsqueeze(0) + noise = torch.cat((ref_noise, noise), dim=0) + x0_output = {} + preview_callback = latent_preview.prepare_callback(m, sigmas.shape[-1] - 1, x0_output) + + def callback(step: int, x0: T, x: T, steps: int): + preview_callback(step, x0, x, steps) + if step + 1 < steps: + x[0] = ref_latents[step + 1] + x0[0] = ref_latents[step + 1] + share_group_norm = share_norm in ['group', 'both'] + share_layer_norm = share_norm in ['layer', 'both'] + register_shared_norm(m, share_group_norm, share_layer_norm) + m.set_model_attn1_patch(SharedAttentionProcessor(args, scale)) + batched_condition = [] + for (i, condition) in enumerate(positive): + additional = condition[1].copy() + batch_with_reference = torch.cat([ref_positive[i][0], condition[0].repeat([batch_size] + [1] * len(condition[0].shape[1:]))], dim=0) + if 'pooled_output' in additional and 'pooled_output' in ref_positive[i][1]: + pooled_output = torch.cat([ref_positive[i][1]['pooled_output'], additional['pooled_output'].repeat([batch_size] + [1] * len(additional['pooled_output'].shape[1:]))], dim=0) + additional['pooled_output'] = pooled_output + if 'control' in additional: + if 'control' in ref_positive[i][1]: + control_hint = torch.cat([ref_positive[i][1]['control'].cond_hint_original, additional['control'].cond_hint_original.repeat([batch_size] + [1] * len(additional['control'].cond_hint_original.shape[1:]))], dim=0) + cloned_controlnet = additional['control'].copy() + cloned_controlnet.set_cond_hint(control_hint, strength=additional['control'].strength, timestep_percent_range=additional['control'].timestep_percent_range) + additional['control'] = cloned_controlnet + else: + control_hint = torch.cat([torch.zeros_like(additional['control'].cond_hint_original), additional['control'].cond_hint_original.repeat([batch_size] + [1] * len(additional['control'].cond_hint_original.shape[1:]))], dim=0) + cloned_controlnet = additional['control'].copy() + cloned_controlnet.set_cond_hint(control_hint, strength=additional['control'].strength, timestep_percent_range=additional['control'].timestep_percent_range) + additional['control'] = cloned_controlnet + batched_condition.append([batch_with_reference, additional]) + disable_pbar = not comfy.utils.PROGRESS_BAR_ENABLED + samples = comfy.sample.sample_custom(m, noise, cfg, sampler, sigmas, batched_condition, negative, latent_t, callback=callback, disable_pbar=disable_pbar, seed=noise_seed) + samples = samples[1:] + out = latent.copy() + out['samples'] = samples + if 'x0' in x0_output: + out_denoised = latent.copy() + x0 = x0_output['x0'][1:] + out_denoised['samples'] = m.model.process_latent_out(x0.cpu()) + else: + out_denoised = out + return (out, out_denoised) +``` \ No newline at end of file diff --git a/docs/StyleAlignedSampleReferenceLatents.md b/docs/StyleAlignedSampleReferenceLatents.md new file mode 100644 index 0000000..cf180d6 --- /dev/null +++ b/docs/StyleAlignedSampleReferenceLatents.md @@ -0,0 +1,91 @@ +# Documentation +- Class name: StyleAlignedSampleReferenceLatents +- Category: style_aligned +- Output node: False +- Repo Ref: https://github.com/brianfitzgerald/style_aligned_comfy + +StyleAlignedSampleReferenceLatents节点的'sample'方法旨在生成与给定潜在图像风格一致的参考潜在序列。它利用模型采样一个风格上与输入条件一致的噪声输出。此节点在需要一系列生成图像保持风格一致性的应用中至关重要。 + +# Input types +## Required +- model + - 模型参数对于节点的操作至关重要,因为它提供了用于采样的底层神经网络架构。它直接影响生成潜在的质量与风格。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- positive + - positive参数定义了引导采样朝向特定风格的正向条件因素。它在塑造输出的风格特征中扮演重要角色。 + - Comfy dtype: CONDITIONING + - Python dtype: Union[str, torch.Tensor] +- negative + - negative参数指定了采样过程中要避免的条件因素,确保生成的潜在不展示不希望的风格特征。 + - Comfy dtype: CONDITIONING + - Python dtype: Union[str, torch.Tensor] +- sampler + - sampler参数决定了节点使用的采样策略。它对于控制生成潜在的随机性和多样性至关重要。 + - Comfy dtype: SAMPLER + - Python dtype: Callable +- sigmas + - sigmas参数表示采样过程中使用的方差,用于控制噪声的传播。它是微调潜在风格细节的关键因素。 + - Comfy dtype: SIGMAS + - Python dtype: torch.Tensor +- latent_image + - latent_image参数是一个关键输入,它提供了采样过程开始的初始潜在状态。它为生成的参考潜在设置了基础风格。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +## Optional +- noise_seed + - noise_seed参数用于初始化采样过程中应用的随机噪声。当需要特定噪声模式时,它确保结果的可重复性。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数控制采样过程的配置,影响生成潜在的规模和细节。它是实现所需风格结果的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- ref_latents + - ref_latents输出是由节点生成的一系列参考潜在。这些潜在与输入潜在图像的风格一致,并用于进一步的处理或分析。 + - Comfy dtype: STEP_LATENTS + - Python dtype: torch.Tensor +- noised_output + - noised_output参数代表采样过程的最终输出,这是输入潜在图像的噪声版本。它封装了输入的风格精髓,同时引入了变化性。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class StyleAlignedSampleReferenceLatents: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'noise_seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'cfg': ('FLOAT', {'default': 8.0, 'min': 0.0, 'max': 100.0, 'step': 0.1, 'round': 0.01}), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'sampler': ('SAMPLER',), 'sigmas': ('SIGMAS',), 'latent_image': ('LATENT',)}} + RETURN_TYPES = ('STEP_LATENTS', 'LATENT') + RETURN_NAMES = ('ref_latents', 'noised_output') + FUNCTION = 'sample' + CATEGORY = 'style_aligned' + + def sample(self, model, noise_seed, cfg, positive, negative, sampler, sigmas, latent_image): + sigmas = sigmas.flip(0) + if sigmas[0] == 0: + sigmas[0] = 0.0001 + latent = latent_image + latent_image = latent['samples'] + noise = torch.zeros(latent_image.size(), dtype=latent_image.dtype, layout=latent_image.layout, device='cpu') + noise_mask = None + if 'noise_mask' in latent: + noise_mask = latent['noise_mask'] + ref_latents = [] + + def callback(step: int, x0: T, x: T, steps: int): + ref_latents.insert(0, x[0]) + disable_pbar = not comfy.utils.PROGRESS_BAR_ENABLED + samples = comfy.sample.sample_custom(model, noise, cfg, sampler, sigmas, positive, negative, latent_image, noise_mask=noise_mask, callback=callback, disable_pbar=disable_pbar, seed=noise_seed) + out = latent.copy() + out['samples'] = samples + out_noised = out + ref_latents = torch.stack(ref_latents) + return (ref_latents, out_noised) +``` \ No newline at end of file diff --git a/docs/Styles Loader (mtb).md b/docs/Styles Loader (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/SubtractMask.md b/docs/SubtractMask.md new file mode 100644 index 0000000..67ad1ac --- /dev/null +++ b/docs/SubtractMask.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: SubtractMask +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SubtractMask节点的'doit'方法对两张掩码图像执行减法操作,提供代表输入之间差异的结果掩码。它旨在成为图像处理工作流中的基本操作,其中需要移除或添加图像中的某些区域。 + +# Input types +## Required +- mask1 + - 用于减法操作的第一个掩码。它在确定结果掩码的结果中起着至关重要的作用,因为它定义了第二个掩码将从中减去的掩码的初始状态。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- mask2 + - 要从第一个掩码中减去的第二个掩码。它的重要性在于修改第一个掩码的内容,从而产生反映减法效果的最终掩码。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- mask + - 输出掩码是两个输入掩码之间减法操作的结果。它表示在从第一个掩码减去第二个掩码后剩余的区域。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SubtractMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask1': ('MASK',), 'mask2': ('MASK',)}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, mask1, mask2): + mask = subtract_masks(mask1, mask2) + return (mask,) +``` \ No newline at end of file diff --git a/docs/SubtractMaskForEach.md b/docs/SubtractMaskForEach.md new file mode 100644 index 0000000..01dbf7c --- /dev/null +++ b/docs/SubtractMaskForEach.md @@ -0,0 +1,63 @@ +# Documentation +- Class name: SubtractMaskForEach +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +SubtractMaskForEach节点的'doit'方法旨在通过从基础分割中减去掩码分割来处理分割数据。它通过识别基础分割和掩码分割之间的重叠区域并相应地修改基础分割来操作。此方法对于细化分割结果至关重要,确保重叠区域被准确表示。 + +# Input types +## Required +- base_segs + - 'base_segs'参数是节点将要处理的分割数据集合。它至关重要,因为它构成了节点执行的减法操作的基础。此参数直接影响分割过程的结果,决定了图像的哪些部分将被保留或修改。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] +- mask_segs + - 'mask_segs'参数包含将从基础分割中减去的掩码分割。此参数对于定义将被修改的分割区域至关重要。它与'base_segs'一起工作,确保只有指定的区域受到减法操作的影响。 + - Comfy dtype: SEGS + - Python dtype: List[SEG] + +# Output types +- result + - 'result'输出是减法操作后修改的分割项列表。每个项目代表已根据掩码分割进行调整的基础分割。此输出很重要,因为它为进一步使用或分析提供了最终的、细化的分割数据。 + - Comfy dtype: SEGS + - Python dtype: Tuple[str, List[SEG]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SubtractMaskForEach: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'base_segs': ('SEGS',), 'mask_segs': ('SEGS',)}} + RETURN_TYPES = ('SEGS',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, base_segs, mask_segs): + result = [] + for bseg in base_segs[1]: + cropped_mask1 = bseg.cropped_mask.copy() + crop_region1 = bseg.crop_region + for mseg in mask_segs[1]: + cropped_mask2 = mseg.cropped_mask + crop_region2 = mseg.crop_region + intersect_region = (max(crop_region1[0], crop_region2[0]), max(crop_region1[1], crop_region2[1]), min(crop_region1[2], crop_region2[2]), min(crop_region1[3], crop_region2[3])) + changed = False + for i in range(intersect_region[0], intersect_region[2]): + for j in range(intersect_region[1], intersect_region[3]): + if cropped_mask1[j - crop_region1[1], i - crop_region1[0]] == 1 and cropped_mask2[j - crop_region2[1], i - crop_region2[0]] == 1: + changed = True + cropped_mask1[j - crop_region1[1], i - crop_region1[0]] = 0 + else: + pass + if changed: + item = SEG(bseg.cropped_image, cropped_mask1, bseg.confidence, bseg.crop_region, bseg.bbox, bseg.label, None) + result.append(item) + else: + result.append(bseg) + return ((base_segs[0], result),) +``` \ No newline at end of file diff --git a/docs/SvgImage.md b/docs/SvgImage.md new file mode 100644 index 0000000..c6a5f47 --- /dev/null +++ b/docs/SvgImage.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: SvgImage +- Category: ♾️Mixlab/Image +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点旨在处理SVG图像,将其转换为适合在神经网络框架中进一步操作和分析的张量格式。它强调SVG数据的转换和适配,以便与深度学习模型集成。 + +# Input types +## Required +- upload + - ‘upload’参数对节点的运行至关重要,它包含了SVG图像数据和相关的元数据。它直接影响节点处理和转换SVG为张量的能力。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Output types +- IMAGE + - ‘IMAGE’输出提供了输入SVG图像的张量表示,可用于深度学习环境中的进一步处理。 + - Comfy dtype: Tensor + - Python dtype: torch.Tensor +- layers + - ‘layers’输出包含了从SVG数据中提取的单个组件或图层,可用于对图像结构进行详细分析或操作。 + - Comfy dtype: List[Any] + - Python dtype: List[Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SvgImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'upload': ('SVG',)}} + RETURN_TYPES = ('IMAGE', 'LAYER') + RETURN_NAMES = ('IMAGE', 'layers') + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Image' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False, True) + + def run(self, upload): + layers = [] + image = base64_to_image(upload['image']) + image = image.convert('RGB') + image = pil2tensor(image) + for layer in upload['data']: + layers.append(layer) + return (image, layers) +``` \ No newline at end of file diff --git a/docs/SwitchByIndex.md b/docs/SwitchByIndex.md new file mode 100644 index 0000000..93e1edb --- /dev/null +++ b/docs/SwitchByIndex.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: SwitchByIndex +- Category: ♾️Mixlab/Utils +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +SwitchByIndex是一个旨在根据指定索引从两个输入列表中选择元素的节点,允许组合和展平数据结构。 + +# Input types +## Required +- A + - 参数'A'是第一个输入列表,对于节点的操作至关重要,因为它提供了主要的数据源。 + - Comfy dtype: ANY + - Python dtype: List[Any] +- B + - 参数'B'代表第二个输入列表,它在节点数据处理中补充了'A'列表。 + - Comfy dtype: ANY + - Python dtype: List[Any] +- index + - 参数'index'对于从组合列表中选择特定元素至关重要,影响节点的输出。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- flat + - 参数'flat'决定输出列表是否应该被展平,影响最终结果的结构。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- C + - 输出'C'是一个包含两个输入列表中元素的列表,可能会被'index'和'flat'参数修改。 + - Comfy dtype: ANY + - Python dtype: List[Any] +- count + - 输出'count'提供了'C'列表中元素的总数,反映了节点的数据聚合。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SwitchByIndex: + + @classmethod + def INPUT_TYPES(cls): + return {'optional': {'A': (any_type,), 'B': (any_type,)}, 'required': {'index': ('INT', {'default': -1, 'min': -1, 'max': 1000, 'step': 1, 'display': 'number'}), 'flat': (['off', 'on'],)}} + RETURN_TYPES = (any_type, 'INT') + RETURN_NAMES = ('C', 'count') + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Utils' + INPUT_IS_LIST = True + OUTPUT_IS_LIST = (True, False) + + def run(self, A=[], B=[], index=-1, flat='on'): + flat = flat[0] + C = [] + index = index[0] + for a in A: + C.append(a) + for b in B: + C.append(b) + if flat == 'on': + C = flatten_list(C) + if index > -1: + try: + C = [C[index]] + except Exception as e: + C = [] + return (C, len(C)) +``` \ No newline at end of file diff --git a/docs/TESTNODE_.md b/docs/TESTNODE_.md new file mode 100644 index 0000000..9c8d5cf --- /dev/null +++ b/docs/TESTNODE_.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: TESTNODE_ +- Category: ♾️Mixlab/__TEST +- Output node: True +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +TESTNODE_ 节点旨在分析和处理任何类型元素的列表。它利用 ListStatistics 工具来统计列表中不同数据类型的出现次数,提供数据组成的摘要。该节点还动态导入并执行来自外部模块的函数,展示了其在处理基于输入列表的各种操作方面的适应性。节点的目的是提供输入列表中存在数据类型的全面概述,并在输入数据上执行预定义的函数。 + +# Input types +## Required +- ANY + - ANY 参数是一个多功能输入,它接受任何类型元素的列表。它是节点操作的基础,因为它直接影响到类型计数和随后的外部函数执行。ANY 中元素的多样性会影响节点的分析和函数执行的结果。 + - Comfy dtype: any + - Python dtype: List[Any] + +# Output types +- result + - result 参数包含了 ListStatistics 工具执行的类型计数操作的输出。它很重要,因为它提供了输入列表中元素类型的详细说明以及它们各自的计数。这些信息对于理解输入数据的构成至关重要。 + - Comfy dtype: Dict[str, List[Any]] + - Python dtype: Dict[str, List[Any]] +- ui + - ui 参数是一个结构化的输出,包括数据及其类型信息。它旨在便于在用户界面中展示节点的结果。data 字段包含类型计数的结果,而 type 字段指示输入列表中第一个元素的数据类型。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Union[Dict[str, List[Any]], str]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TESTNODE_: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ANY': (any_type,)}} + RETURN_TYPES = (any_type,) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/__TEST' + OUTPUT_NODE = True + INPUT_IS_LIST = True + OUTPUT_IS_LIST = (True,) + + def run(self, ANY): + list_stats = ListStatistics() + result = list_stats.count_types(ANY) + module_path = os.path.join(os.path.dirname(__file__), 'test.py') + spec = importlib.util.spec_from_file_location('test', module_path) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + functions = getattr(module, 'run') + functions(ANY) + return {'ui': {'data': result, 'type': [str(type(ANY[0]))]}, 'result': (ANY,)} +``` \ No newline at end of file diff --git a/docs/TESTNODE_TOKEN.md b/docs/TESTNODE_TOKEN.md new file mode 100644 index 0000000..ac2eeea --- /dev/null +++ b/docs/TESTNODE_TOKEN.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: TESTNODE_TOKEN +- Category: ♾️Mixlab/__TEST +- Output node: True +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点使用clip模型处理文本输入,将文本转换为结构化表示,以便在各种应用中进一步使用。 + +# Input types +## Required +- text + - 文本输入对于节点执行其标记化功能至关重要。它是提取和构建标记的原材料。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- clip + - clip模型是一个可选输入,提供后可以使节点更有效地对文本进行标记化,利用模型对语言结构的理解。 + - Comfy dtype: CLIP + - Python dtype: module + +# Output types +- tokens + - 输出是一个代表输入文本标记化结构的JSON字符串。它是下游任务中进一步分析和处理的关键组成部分。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TESTNODE_TOKEN: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'forceInput': True}), 'clip': ('CLIP',)}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/__TEST' + OUTPUT_NODE = True + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False,) + + def run(self, text, clip=None): + tokens = clip.tokenize(text) + tokens = [v for v in tokens.values()][0][0] + tokens = json.dumps(tokens) + return (tokens,) +``` \ No newline at end of file diff --git a/docs/Tensor Batch to Image.md b/docs/Tensor Batch to Image.md new file mode 100644 index 0000000..5e650ee --- /dev/null +++ b/docs/Tensor Batch to Image.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: WAS_Tensor_Batch_to_Image +- Category: WAS Suite/Latent/Transform +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法`tensor_batch_to_image`旨在将一批张量图像转换为单一的图像表示。它是图像处理流程中的关键步骤,允许将批量数据转换为可以更容易使用或显示的格式。 + +# Input types +## Required +- images_batch + - 参数`images_batch`非常关键,因为它包含了要转换为单一图像的一批张量图像。它在节点的操作中起着核心作用,决定了转换过程的源数据。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +## Optional +- batch_image_number + - 参数`batch_image_number`决定从一批图像中选择哪个图像进行转换。其值通过指定批次中所需图像的索引来影响节点的执行。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 输出`image`是转换过程的结果,代表从一批图像中选择的图像。它很重要,因为它是节点功能的直接输出,包含了转换后的数据。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Tensor_Batch_to_Image: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images_batch': ('IMAGE',), 'batch_image_number': ('INT', {'default': 0, 'min': 0, 'max': 64, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'tensor_batch_to_image' + CATEGORY = 'WAS Suite/Latent/Transform' + + def tensor_batch_to_image(self, images_batch=[], batch_image_number=0): + count = 0 + for _ in images_batch: + if batch_image_number == count: + return (images_batch[batch_image_number].unsqueeze(0),) + count = count + 1 + cstr(f'Batch number `{batch_image_number}` is not defined, returning last image').error.print() + return (images_batch[-1].unsqueeze(0),) +``` \ No newline at end of file diff --git a/docs/Text Add Token by Input.md b/docs/Text Add Token by Input.md new file mode 100644 index 0000000..f2e254e --- /dev/null +++ b/docs/Text Add Token by Input.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: WAS_Text_Add_Token_Input +- Category: WAS Suite/Text/Tokens +- Output node: True +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_Add_Token_Input节点旨在管理和操作文本处理工作流中的自定义标记。它允许用户添加或删除标记,并提供打印当前标记列表的功能。该节点在根据预定义或用户提供的标记定制和个性化文本输出中发挥着关键作用。 + +# Input types +## Required +- token_name + - token_name参数对于标识要添加或操作的标记的唯一名称至关重要。它直接影响节点在文本处理系统中正确引用和修改所需标记的能力。 + - Comfy dtype: STRING + - Python dtype: str +- token_value + - token_value参数指定要与token_name关联的值。它是一个关键输入,因为它决定了在处理期间将替换文本中标记占位符的实际内容。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- print_current_tokens + - 当print_current_tokens参数设置为'true'时,会触发节点输出当前的自定义标记列表。这个特性对于调试和验证修改后标记列表的状态非常有用。 + - Comfy dtype: COMBO['false', 'true'] + - Python dtype: Union[str, None] + +# Output types +- token_name_output + - token_name_output提供了由节点添加或操作的标记名称。它很重要,因为它确认了处理的标记的身份。 + - Comfy dtype: STRING + - Python dtype: str +- token_value_output + - token_value_output返回与token_name关联的值。这个输出对于验证文本处理系统中为标记设置的正确值非常重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Add_Token_Input: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'token_name': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'token_value': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'print_current_tokens': (['false', 'true'],)}} + RETURN_TYPES = () + FUNCTION = 'text_add_token' + OUTPUT_NODE = True + CATEGORY = 'WAS Suite/Text/Tokens' + + def text_add_token(self, token_name, token_value, print_current_tokens='false'): + if token_name.strip() == '': + cstr(f'A `token_name` is required for a token; token name provided is empty.').error.print() + pass + tk = TextTokens() + tk.addToken(token_name, token_value) + if print_current_tokens == 'true': + cstr(f'Current Custom Tokens:').msg.print() + print(json.dumps(tk.custom_tokens, indent=4)) + return (token_name, token_value) + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') +``` \ No newline at end of file diff --git a/docs/Text Add Tokens.md b/docs/Text Add Tokens.md new file mode 100644 index 0000000..5d7eecc --- /dev/null +++ b/docs/Text Add Tokens.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: WAS_Text_Add_Tokens +- Category: WAS Suite/Text/Tokens +- Output node: True +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_Add_Tokens节点旨在处理和操作文本标记。它通过添加自定义标记来增强输入文本,这些标记可以用于各种目的,如时间戳、用户识别或设备信息。该节点的功能集中在将动态元素注入到静态文本中,从而为文本处理任务提供了一种多功能工具。 + +# Input types +## Required +- tokens + - ‘tokens’参数对节点的操作至关重要,因为它定义了要添加到文本中的自定义标记。这些标记可以表示当前时间、主机名或其他系统特定信息等动态数据。包含这些标记允许创建内容丰富的文本,可以用于各种应用程序。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- print_current_tokens + - ‘print_current_tokens’参数是一个可选开关,当设置为‘true’时,指示节点打印当前的自定义标记状态。这个特性对于调试和验证正在应用于文本的标记非常有用。 + - Comfy dtype: COMBO['false', 'true'] + - Python dtype: Union[str, None] + +# Output types +- tokens + - 输出的‘tokens’参数表示带有新添加或更新的自定义标记的修改后的文本。这个输出可以用于下游任务的进一步处理或分析,允许将动态文本元素无缝集成到各种工作流程中。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Add_Tokens: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'tokens': ('STRING', {'default': '[hello]: world', 'multiline': True}), 'print_current_tokens': (['false', 'true'],)}} + RETURN_TYPES = () + FUNCTION = 'text_add_tokens' + OUTPUT_NODE = True + CATEGORY = 'WAS Suite/Text/Tokens' + + def text_add_tokens(self, tokens, print_current_tokens='false'): + import io + tk = TextTokens() + for line in io.StringIO(tokens): + parts = line.split(':') + token = parts[0].strip() + token_value = parts[1].strip() + tk.addToken(token, token_value) + if print_current_tokens == 'true': + cstr(f'Current Custom Tokens:').msg.print() + print(json.dumps(tk.custom_tokens, indent=4)) + return tokens + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') +``` \ No newline at end of file diff --git a/docs/Text Compare.md b/docs/Text Compare.md new file mode 100644 index 0000000..7d03d75 --- /dev/null +++ b/docs/Text Compare.md @@ -0,0 +1,163 @@ +# Documentation +- Class name: WAS_Text_Compare +- Category: WAS Suite/Text/Search +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_Compare节点旨在比较两个文本输入,并根据指定的模式确定它们的相似性或差异性。它通过分析文本内容并提供反映相似度或差异度的分数来操作。该节点多功能,可用于需要文本比较的各种应用中,例如抄袭检测或内容匹配。 + +# Input types +## Required +- text_a + - 要与第二个文本输入进行比较的第一个文本输入。它在比较过程中起着至关重要的作用,因为它构成了确定相似性或差异性的基础。 + - Comfy dtype: STRING + - Python dtype: str +- text_b + - 与第一个文本输入进行比较的第二个文本输入。它对于比较至关重要,因为它为分析提供了对比内容。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- mode + - 模式决定了比较应该侧重于两个文本之间的相似性还是差异性。它影响用于比较的算法以及产生的结果类型。 + - Comfy dtype: COMBO['similarity', 'difference'] + - Python dtype: str +- tolerance + - 容差级别设置了确定相似度的阈值。当节点用于查找几乎相同的文本时特别有用。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- TEXT_A_PASS + - 被比较的第一个文本输入。 + - Comfy dtype: STRING + - Python dtype: str +- TEXT_B_PASS + - 被比较的第二个文本输入。 + - Comfy dtype: STRING + - Python dtype: str +- BOOLEAN + - 一个布尔值,指示文本是否完全相同。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- SCORE_NUMBER + - 一个数值分数,代表两个文本之间的相似度或差异度。 + - Comfy dtype: NUMBER + - Python dtype: float +- COMPARISON_TEXT + - 比较结果的文本表示,突出显示差异或相似之处。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Compare: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text_a': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'text_b': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'mode': (['similarity', 'difference'],), 'tolerance': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = (TEXT_TYPE, TEXT_TYPE, 'BOOLEAN', 'NUMBER', TEXT_TYPE) + RETURN_NAMES = ('TEXT_A_PASS', 'TEXT_B_PASS', 'BOOLEAN', 'SCORE_NUMBER', 'COMPARISON_TEXT') + FUNCTION = 'text_compare' + CATEGORY = 'WAS Suite/Text/Search' + + def text_compare(self, text_a='', text_b='', mode='similarity', tolerance=0.0): + boolean = 1 if text_a == text_b else 0 + sim = self.string_compare(text_a, text_b, tolerance, True if mode == 'difference' else False) + score = float(sim[0]) + sim_result = ' '.join(sim[1][::-1]) + sim_result = ' '.join(sim_result.split()) + return (text_a, text_b, bool(boolean), score, sim_result) + + def string_compare(self, str1, str2, threshold=1.0, difference_mode=False): + m = len(str1) + n = len(str2) + if difference_mode: + dp = [[0 for x in range(n + 1)] for x in range(m + 1)] + for i in range(m + 1): + for j in range(n + 1): + if i == 0: + dp[i][j] = j + elif j == 0: + dp[i][j] = i + elif str1[i - 1] == str2[j - 1]: + dp[i][j] = dp[i - 1][j - 1] + else: + dp[i][j] = 1 + min(dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1]) + diff_indices = [] + (i, j) = (m, n) + while i > 0 and j > 0: + if str1[i - 1] == str2[j - 1]: + i -= 1 + j -= 1 + else: + diff_indices.append(i - 1) + (i, j) = min((i, j - 1), (i - 1, j)) + diff_indices.reverse() + words = [] + start_idx = 0 + for i in diff_indices: + if str1[i] == ' ': + words.append(str1[start_idx:i]) + start_idx = i + 1 + words.append(str1[start_idx:m]) + difference_score = 1 - (dp[m][n] - len(words)) / max(m, n) + return (difference_score, words[::-1]) + else: + dp = [[0 for x in range(n + 1)] for x in range(m + 1)] + similar_words = set() + for i in range(m + 1): + for j in range(n + 1): + if i == 0: + dp[i][j] = j + elif j == 0: + dp[i][j] = i + elif str1[i - 1] == str2[j - 1]: + dp[i][j] = dp[i - 1][j - 1] + if i > 1 and j > 1 and (str1[i - 2] == ' ') and (str2[j - 2] == ' '): + word1_start = i - 2 + word2_start = j - 2 + while word1_start > 0 and str1[word1_start - 1] != ' ': + word1_start -= 1 + while word2_start > 0 and str2[word2_start - 1] != ' ': + word2_start -= 1 + word1 = str1[word1_start:i - 1] + word2 = str2[word2_start:j - 1] + if word1 in str2 or word2 in str1: + if word1 not in similar_words: + similar_words.add(word1) + if word2 not in similar_words: + similar_words.add(word2) + else: + dp[i][j] = 1 + min(dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1]) + if dp[i][j] <= threshold and i > 0 and (j > 0): + word1_start = max(0, i - dp[i][j]) + word2_start = max(0, j - dp[i][j]) + word1_end = i + word2_end = j + while word1_start > 0 and str1[word1_start - 1] != ' ': + word1_start -= 1 + while word2_start > 0 and str2[word2_start - 1] != ' ': + word2_start -= 1 + while word1_end < m and str1[word1_end] != ' ': + word1_end += 1 + while word2_end < n and str2[word2_end] != ' ': + word2_end += 1 + word1 = str1[word1_start:word1_end] + word2 = str2[word2_start:word2_end] + if word1 in str2 or word2 in str1: + if word1 not in similar_words: + similar_words.add(word1) + if word2 not in similar_words: + similar_words.add(word2) + if max(m, n) == 0: + similarity_score = 1 + else: + similarity_score = 1 - dp[m][n] / max(m, n) + return (similarity_score, list(similar_words)) +``` \ No newline at end of file diff --git a/docs/Text Concatenate.md b/docs/Text Concatenate.md new file mode 100644 index 0000000..0a2944e --- /dev/null +++ b/docs/Text Concatenate.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: WAS_Text_Concatenate +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_Concatenate节点旨在高效地将多个文本输入合并为一个单独的字符串。它通过使用指定的分隔符连接提供的文本输入来实现这一点,可选择性地去除首尾空白,以获得更清洁的输出。此节点在简化文本处理工作流程中扮演着关键角色,通过简化文本数据的聚合来实现这一点。 + +# Input types +## Required +- delimiter + - 分隔符参数定义了在连接各个文本输入时使用的字符或字符串。它对于确定最终输出字符串的格式至关重要,并影响组合文本的可读性和结构。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- clean_whitespace + - clean_whitespace参数是一个可选的标,当设置为'true'时,指示节点在连接之前从文本输入中去除任何首尾空白。这确保了结果文本没有不必要的空格,并且格式整洁。 + - Comfy dtype: COMBO['true', 'false'] + - Python dtype: str +- text_a + - text_a参数代表可以提供给节点的可选文本输入之一。它作为连接过程的一部分,用于贡献最终合并的文本。包含此参数允许将多个不同的文本段添加到组合输出中。 + - Comfy dtype: STRING + - Python dtype: str +- text_b + - text_b参数与text_a具有类似的目的,允许在连接过程中包含另一个不同的文本段。它增强了节点处理各种文本输入并创建全面最终文本的能力。 + - Comfy dtype: STRING + - Python dtype: str +- text_c + - text_c参数与text_a和text_b类似,是节点的另一个可选文本输入。它为连接更广泛的文本输入提供了额外的灵活性,使得能够创建一个更复杂和详细的最终文本。 + - Comfy dtype: STRING + - Python dtype: str +- text_d + - text_d参数是节点可以处理的最后一个可选文本输入。它为连接提供了进一步的定制选项,允许用户包含更多的文本段,并制作出详细和微妙的最终文本输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- merged_text + - merged_text输出是使用指定的分隔符连接所有提供的文本输入的结果。它代表了节点生成的最终组合文本,可以用于进一步处理或作为文本处理流水线的最终输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Concatenate: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'delimiter': ('STRING', {'default': ', '}), 'clean_whitespace': (['true', 'false'],)}, 'optional': {'text_a': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'text_b': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'text_c': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'text_d': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False})}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'text_concatenate' + CATEGORY = 'WAS Suite/Text' + + def text_concatenate(self, delimiter, clean_whitespace, **kwargs): + text_inputs: list[str] = [] + if delimiter == '\\n': + delimiter = '\n' + for k in sorted(kwargs.keys()): + v = kwargs[k] + if isinstance(v, str): + if clean_whitespace == 'true': + v = v.strip() + if v != '': + text_inputs.append(v) + merged_text = delimiter.join(text_inputs) + return (merged_text,) +``` \ No newline at end of file diff --git a/docs/Text Contains.md b/docs/Text Contains.md new file mode 100644 index 0000000..e888e70 --- /dev/null +++ b/docs/Text Contains.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: WAS_Text_Contains +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +`text_contains` 方法旨在确定一个指定的子字符串是否存在于一个较大的文本字符串中。它通过比较这两个字符串并返回一个布尔值来指示子字符串的存在或缺失。此方法对于文本分析和数据验证任务至关重要,其中特定文本模式的存在是感兴趣的。 + +# Input types +## Required +- text + - ‘text’ 参数代表方法将搜索 'sub_text' 的较大文本主体。它对节点的操作至关重要,因为它定义了搜索的范围并直接影响方法的结果。 + - Comfy dtype: STRING + - Python dtype: str +- sub_text + - ‘sub_text’ 参数是方法将在 'text' 参数中查找的特定字符串。它在较大文本中的存在是方法旨在确定的,使其成为节点功能的关键输入。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- case_insensitive + - ‘case_insensitive’ 参数决定在 'text' 中搜索 'sub_text' 是否应该忽略字母的大小写。这对于确保搜索不受大小写差异的阻碍可能是重要的。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- result + - ‘result’ 输出指示是否在 'text' 中找到了 'sub_text'。它是一个二进制指示器,为方法所提出的问题提供了清晰而简洁的答案。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Contains: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {'default': '', 'multiline': False}), 'sub_text': ('STRING', {'default': '', 'multiline': False})}, 'optional': {'case_insensitive': ('BOOLEAN', {'default': True})}} + RETURN_TYPES = ('BOOLEAN',) + FUNCTION = 'text_contains' + CATEGORY = 'WAS Suite/Logic' + + def text_contains(self, text, sub_text, case_insensitive): + if case_insensitive: + sub_text = sub_text.lower() + text = text.lower() + return (sub_text in text,) +``` \ No newline at end of file diff --git a/docs/Text Dictionary Convert.md b/docs/Text Dictionary Convert.md new file mode 100644 index 0000000..41c8c66 --- /dev/null +++ b/docs/Text Dictionary Convert.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_Dictionary_Convert +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +`dictionary_convert` 方法旨在将字典的字符串表示形式转换为可用的字典对象。它在基于文本的应用程序的预处理阶段中起着关键作用,确保输入数据被正确格式化以供后续处理使用。 + +# Input types +## Required +- dictionary_text + - 参数 `dictionary_text` 是必需的,因为它提供了需要转换为字典的原始文本。其正确的格式化对于节点功能的成功执行至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- converted_dictionary + - 输出 `converted_dictionary` 非常重要,因为它代表了转换过程中生成的结构化字典对象。它已准备好在应用程序中的后续操作中使用。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Dictionary_Convert: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'dictionary_text': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False})}} + RETURN_TYPES = ('DICT',) + FUNCTION = 'dictionary_convert' + CATEGORY = 'WAS Suite/Text' + + def dictionary_convert(self, dictionary_text): + return (ast.literal_eval(dictionary_text),) +``` \ No newline at end of file diff --git a/docs/Text Dictionary Get.md b/docs/Text Dictionary Get.md new file mode 100644 index 0000000..d749c69 --- /dev/null +++ b/docs/Text Dictionary Get.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: WAS_Dictionary_Get +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Dictionary_Get节点旨在根据给定的键从一个字典中检索特定的条目。它在数据提取和操作过程中扮演着至关重要的角色,提供了一种流线化的方式来访问和使用工作流中的字典值。 + +# Input types +## Required +- dictionary + - 字典参数对于节点的操作至关重要,因为它是将检索键值的来源。这是一个关键组件,直接影响节点的输出。 + - Comfy dtype: DICT + - Python dtype: Dict[Any, Any] +- key + - 键参数用于指定节点将访问的字典中的特定条目。它的存在对于节点正确运行至关重要,并且可以确定所需的确切数据。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- default_value + - default_value参数被提供为在指定的键在字典中不存在的情况下的备选选项。它确保节点可以优雅地处理这种情况,并在不中断的情况下继续工作流程。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- value + - 值输出参数表示使用指定的键从字典中检索到的数据。它很重要,因为它是节点操作的直接结果,并且可以用于工作流中的进一步处理。 + - Comfy dtype: TEXT + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Dictionary_Get: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'dictionary': ('DICT',), 'key': ('STRING', {'default': '', 'multiline': False})}, 'optional': {'default_value': ('STRING', {'default': '', 'multiline': False})}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'dictionary_get' + CATEGORY = 'WAS Suite/Text' + + def dictionary_get(self, dictionary, key, default_value=''): + return (str(dictionary.get(key, default_value)),) +``` \ No newline at end of file diff --git a/docs/Text Dictionary Keys.md b/docs/Text Dictionary Keys.md new file mode 100644 index 0000000..aef5cbd --- /dev/null +++ b/docs/Text Dictionary Keys.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_Dictionary_Keys +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Dictionary_Keys节点旨在从一个给定的字典中提取键。它在数据处理工作流中作为一个基本组件,用于在进一步分析或操作数据结构之前识别字典键。 + +# Input types +## Required +- dictionary + - 参数'dictionary'对于节点的运行至关重要,因为它是将从中提取键的来源。这是一个关键的输入,它通过确定被识别的键集直接影响节点的输出。 + - Comfy dtype: DICT + - Python dtype: Dict[Any, Any] + +# Output types +- keys + - 输出参数'keys'代表从输入字典中提取的键集合。它很重要,因为它为任何需要了解字典结构而不涉及相关值的后续操作提供了基础。 + - Comfy dtype: LIST + - Python dtype: List[Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Dictionary_Keys: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'dictionary': ('DICT',)}, 'optional': {}} + RETURN_TYPES = ('LIST',) + FUNCTION = 'dictionary_keys' + CATEGORY = 'WAS Suite/Text' + + def dictionary_keys(self, dictionary): + return (dictionary.keys(),) +``` \ No newline at end of file diff --git a/docs/Text Dictionary New.md b/docs/Text Dictionary New.md new file mode 100644 index 0000000..2c353fb --- /dev/null +++ b/docs/Text Dictionary New.md @@ -0,0 +1,89 @@ +# Documentation +- Class name: WAS_Dictionary_New +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Dictionary_New节点旨在高效地创建和管理字典。它便于向字典中添加键值对,并确保只有非空键被添加。此节点对于需要结构化数据表示和操作的应用程序至关重要。 + +# Input types +## Required +- key_1 + - 'key_1'参数是一个字符串,用作字典中的第一个键。它在定义字典结构中起着关键作用,对节点的操作至关重要,因为它决定了与之关联值的唯一标识符。 + - Comfy dtype: STRING + - Python dtype: str +- value_1 + - 'value_1'参数保存字典中'key_1'对应的值。它很重要,因为它存储与键关联的数据,并且它的包含为字典增添了有意义的内容。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- key_2 + - 'key_2'参数是一个可选的字符串,可以用作字典中的另一个键。它在数据结构化中提供灵活性,并允许字典内更复杂的数据关系。 + - Comfy dtype: STRING + - Python dtype: str +- value_2 + - 'value_2'参数是字典中'key_2'对应的值。它很重要,因为它有助于字典中存储的总体数据,增强了其在各种应用中的实用性。 + - Comfy dtype: STRING + - Python dtype: str +- key_3 + - 'key_3'参数是另一个可选的键,可以包含在字典中。它扩展了字典存储不同信息的能力,满足了更复杂的数据管理需求。 + - Comfy dtype: STRING + - Python dtype: str +- value_3 + - 'value_3'参数对应于字典中'key_3'的值。它的存在增加了字典内容的丰富性,允许对数据进行更详细的表示。 + - Comfy dtype: STRING + - Python dtype: str +- key_4 + - 'key_4'参数是另一个可以添加到字典中的可选键。它增强了节点处理各种数据输入的能力,适应了多样化的数据集。 + - Comfy dtype: STRING + - Python dtype: str +- value_4 + - 'value_4'参数是字典中'key_4'的关联值。对于完成数据对并确保字典能够表示广泛的信息至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- key_5 + - 'key_5'参数是可以提供给字典的最后一个可选键。它为字典内的数据分类提供了额外的选项,支持全面的数据组织。 + - Comfy dtype: STRING + - Python dtype: str +- value_5 + - 'value_5'参数是与字典中'key_5'相关联的值。它对数据对的完整性很重要,并在字典的整体数据完整性中发挥作用。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- dictionary + - 'dictionary'输出是通过节点操作添加到字典中的键值对集合。它代表了由输入参数产生的结构化数据,对于进一步的数据处理和分析至关重要。 + - Comfy dtype: DICT + - Python dtype: Dict[str, str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Dictionary_New: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'key_1': ('STRING', {'default': '', 'multiline': False}), 'value_1': ('STRING', {'default': '', 'multiline': False})}, 'optional': {'key_2': ('STRING', {'default': '', 'multiline': False}), 'value_2': ('STRING', {'default': '', 'multiline': False}), 'key_3': ('STRING', {'default': '', 'multiline': False}), 'value_3': ('STRING', {'default': '', 'multiline': False}), 'key_4': ('STRING', {'default': '', 'multiline': False}), 'value_4': ('STRING', {'default': '', 'multiline': False}), 'key_5': ('STRING', {'default': '', 'multiline': False}), 'value_5': ('STRING', {'default': '', 'multiline': False})}} + RETURN_TYPES = ('DICT',) + FUNCTION = 'dictionary_new' + CATEGORY = 'WAS Suite/Text' + + def append_to_dictionary(self, dictionary, key, value): + if key is not None and key != '': + dictionary[key] = value + return dictionary + + def dictionary_new(self, key_1, value_1, key_2, value_2, key_3, value_3, key_4, value_4, key_5, value_5): + dictionary = {} + dictionary = self.append_to_dictionary(dictionary, key_1, value_1) + dictionary = self.append_to_dictionary(dictionary, key_2, value_2) + dictionary = self.append_to_dictionary(dictionary, key_3, value_3) + dictionary = self.append_to_dictionary(dictionary, key_4, value_4) + dictionary = self.append_to_dictionary(dictionary, key_5, value_5) + return (dictionary,) +``` \ No newline at end of file diff --git a/docs/Text Dictionary To Text.md b/docs/Text Dictionary To Text.md new file mode 100644 index 0000000..3d8b1c2 --- /dev/null +++ b/docs/Text Dictionary To Text.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_Dictionary_to_Text +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Dictionary_to_Text节点旨在将给定的字典转换为文本表示。它在将结构化数据转换为可读格式中发挥关键作用,这对于数据分析、报告和用户界面等多种应用至关重要。该节点简化了从复杂字典结构生成人类可读文本的过程,增强了数据呈现的整体工作流程。 + +# Input types +## Required +- dictionary + - ‘dictionary’参数对于节点的操作至关重要,因为它是节点处理以生成文本的主要输入。它是数据的结构化表示,节点将解释并将其转换为文本格式。输出文本的质量严重依赖于输入字典的结构和内容。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Output types +- text + - ‘text’输出是节点转换过程的结果,它接收输入字典并生成文本表示。这个输出很重要,因为它提供了一个易于理解且可以在各种情境下使用的人类可读格式,如文档、通信或进一步数据处理。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Dictionary_to_Text: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'dictionary': ('DICT',)}, 'optional': {}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'dictionary_to_text' + CATEGORY = 'WAS Suite/Text' + + def dictionary_to_text(self, dictionary): + return (str(dictionary),) +``` \ No newline at end of file diff --git a/docs/Text Dictionary Update.md b/docs/Text Dictionary Update.md new file mode 100644 index 0000000..e2e57c6 --- /dev/null +++ b/docs/Text Dictionary Update.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: WAS_Dictionary_Update +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +‘dictionary_update’方法旨在将多个字典合并为一个。它接受字典作为输入,并将它们的键值对组合起来,确保生成的字典是所有输入的全面表示。此方法对于需要将不同来源的数据聚合到一个统一结构中应用程序至关重要。 + +# Input types +## Required +- dictionary_a + - ‘dictionary_a’参数是要合并的第一个字典。它在结果字典的初始形成中起着关键作用。这个字典的内容与其他字典结合,以实现最终输出。 + - Comfy dtype: DICT + - Python dtype: Dict[Any, Any] +- dictionary_b + - ‘dictionary_b’参数是要合并的第二个字典。它通过将其键值对添加到聚合过程中,从而为结果字典的全面性做出贡献。 + - Comfy dtype: DICT + - Python dtype: Dict[Any, Any] +## Optional +- dictionary_c + - ‘dictionary_c’参数是可选的,可以包含在合并过程中的字典。如果提供,它的内容也被整合到最终字典中,通过额外的数据增强聚合。 + - Comfy dtype: DICT + - Python dtype: Optional[Dict[Any, Any]] +- dictionary_d + - ‘dictionary_d’参数是另一个可选字典,可用于进一步丰富合并后的字典。其包含基于应用程序的具体需求和所需的数据聚合级别。 + - Comfy dtype: DICT + - Python dtype: Optional[Dict[Any, Any]] + +# Output types +- return_dictionary + - 'return_dictionary'是'dictionary_update'方法的输出,代表了所有输入字典的合并结果。在需要统一视图的组合数据源的应用程序中,它是关键组件。 + - Comfy dtype: DICT + - Python dtype: Dict[Any, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Dictionary_Update: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'dictionary_a': ('DICT',), 'dictionary_b': ('DICT',)}, 'optional': {'dictionary_c': ('DICT',), 'dictionary_d': ('DICT',)}} + RETURN_TYPES = ('DICT',) + FUNCTION = 'dictionary_update' + CATEGORY = 'WAS Suite/Text' + + def dictionary_update(self, dictionary_a, dictionary_b, dictionary_c=None, dictionary_d=None): + return_dictionary = {**dictionary_a, **dictionary_b} + if dictionary_c is not None: + return_dictionary = {**return_dictionary, **dictionary_c} + if dictionary_d is not None: + return_dictionary = {**return_dictionary, **dictionary_d} + return (return_dictionary,) +``` \ No newline at end of file diff --git a/docs/Text File History Loader.md b/docs/Text File History Loader.md new file mode 100644 index 0000000..c5ef013 --- /dev/null +++ b/docs/Text File History Loader.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: WAS_Text_File_History +- Category: WAS Suite/History +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_File_History 节点旨在管理和检索历史文本文件数据。它提供从指定文件路径读取、处理其内容以及维护访问过的文本文件历史记录的功能。此节点对于需要跟踪和审查文本文档随时间演变的应用程序至关重要。 + +# Input types +## Required +- file + - ‘file’参数非常关键,因为它指定了节点将从中读取数据的文本文件的路径。节点的操作严重依赖于该文件路径的有效性和可访问性。它直接影响节点处理和返回文本内容的能力。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- dictionary_name + - ‘dictionary_name’参数允许用户为将包含文本文件内容的字典定义自定义名称。这对于需要为数据结构指定命名约定的应用程序特别有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- text + - ‘text’输出参数代表处理后的文本文件内容。它是一个关键元素,因为它包含了节点读取并准备用于后续操作的实际数据。 + - Comfy dtype: STRING + - Python dtype: str +- dictionary + - ‘dictionary’输出参数是一个字典,它在指定的键下保存处理后的文本行,该键通常是文件名。它作为一种结构化的方式,在下游流程中访问和使用文本文件的内容。 + - Comfy dtype: DICT + - Python dtype: Dict[str, List[str]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_File_History: + + def __init__(self): + self.HDB = WASDatabase(WAS_HISTORY_DATABASE) + self.conf = getSuiteConfig() + + @classmethod + def INPUT_TYPES(cls): + HDB = WASDatabase(WAS_HISTORY_DATABASE) + conf = getSuiteConfig() + paths = ['No History'] + if HDB.catExists('History') and HDB.keyExists('History', 'TextFiles'): + history_paths = HDB.get('History', 'TextFiles') + if conf.__contains__('history_display_limit'): + history_paths = history_paths[-conf['history_display_limit']:] + paths = [] + for path_ in history_paths: + paths.append(os.path.join('...' + os.sep + os.path.basename(os.path.dirname(path_)), os.path.basename(path_))) + return {'required': {'file': (paths,), 'dictionary_name': ('STRING', {'default': '[filename]', 'multiline': True})}} + RETURN_TYPES = (TEXT_TYPE, 'DICT') + FUNCTION = 'text_file_history' + CATEGORY = 'WAS Suite/History' + + def text_file_history(self, file=None, dictionary_name='[filename]]'): + file_path = file.strip() + filename = os.path.basename(file_path).split('.', 1)[0] if '.' in os.path.basename(file_path) else os.path.basename(file_path) + if dictionary_name != '[filename]' or dictionary_name not in [' ', '']: + filename = dictionary_name + if not os.path.exists(file_path): + cstr(f'The path `{file_path}` specified cannot be found.').error.print() + return ('', {filename: []}) + with open(file_path, 'r', encoding='utf-8', newline='\n') as file: + text = file.read() + update_history_text_files(file_path) + import io + lines = [] + for line in io.StringIO(text): + if not line.strip().startswith('#'): + if not line.strip().startswith('\n'): + line = line.replace('\n', '') + lines.append(line.replace('\n', '')) + dictionary = {filename: lines} + return ('\n'.join(lines), dictionary) + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') +``` \ No newline at end of file diff --git a/docs/Text Find and Replace Input.md b/docs/Text Find and Replace Input.md new file mode 100644 index 0000000..af3234f --- /dev/null +++ b/docs/Text Find and Replace Input.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: WAS_Search_and_Replace_Input +- Category: WAS Suite/Text/Search +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Search_and_Replace_Input节点旨在对给定文本执行搜索和替换操作。它高效地定位文本中所有指定子字符串的出现,并将其替换为新的子字符串。这个节点特别适用于预处理文本数据,其中更新或更正特定短语的需求很常见。它通过确保文本根据用户的需求准确修改,从而为整个工作流程做出贡献。 + +# Input types +## Required +- text + - ‘text’参数是节点的主要输入,代表将要搜索并可能修改的文本。它至关重要,因为它决定了搜索和替换操作将发生的上下文。节点的结果严重依赖于‘text’参数的内容和结构。 + - Comfy dtype: STRING + - Python dtype: str +- find + - ‘find’参数指定了节点将在‘text’中搜索的子字符串。它在识别需要被替换的文本部分中起着关键作用。搜索和替换操作的有效性直接受到‘find’参数准确性的影响。 + - Comfy dtype: STRING + - Python dtype: str +- replace + - ‘replace’参数定义了将用于替换‘find’参数找到的出现的新的子字符串。它很重要,因为它决定了替换过程后文本的最终结果。‘replace’值的选择可以显著改变结果文本的含义或结构。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- result_text + - ‘result_text’输出包含所有替换完成后修改的文本。它是输入‘text’的直接反映,其中指定的‘find’子字符被‘replace’子字符串替换。这个输出很重要,因为它代表了文本处理后的最终状态。 + - Comfy dtype: STRING + - Python dtype: str +- replacement_count_number + - ‘replacement_count_number’输出提供了在文本中‘find’子字符串被‘replace’子字符串替换了多少次的计数。这个数值输出对于分析或记录目的很有用,提供了对文本修改程度的洞察。 + - Comfy dtype: NUMBER + - Python dtype: float +- replacement_count_float + - ‘replacement_count_float’输出与‘replacement_count_number’相同,但是以浮点数的形式表示计数。在需要对替换计数进行进一步计算或统计分析的情况下,这个输出非常有用。 + - Comfy dtype: FLOAT + - Python dtype: float +- replacement_count_int + - ‘replacement_count_int’输出以整数形式提供了替换的计数。当需要确切的替换次数用于操作整数的应用中,如数据记录或基于整数的计算时,这个输出特别有用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Search_and_Replace_Input: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'find': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'replace': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False})}} + RETURN_TYPES = (TEXT_TYPE, 'NUMBER', 'FLOAT', 'INT') + RETURN_NAMES = ('result_text', 'replacement_count_number', 'replacement_count_float', 'replacement_count_int') + FUNCTION = 'text_search_and_replace' + CATEGORY = 'WAS Suite/Text/Search' + + def text_search_and_replace(self, text, find, replace): + count = 0 + new_text = text + while find in new_text: + new_text = new_text.replace(find, replace, 1) + count += 1 + return (new_text, count, float(count), int(count)) + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') +``` \ No newline at end of file diff --git a/docs/Text Find and Replace by Dictionary.md b/docs/Text Find and Replace by Dictionary.md new file mode 100644 index 0000000..63a7448 --- /dev/null +++ b/docs/Text Find and Replace by Dictionary.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: WAS_Search_and_Replace_Dictionary +- Category: WAS Suite/Text/Search +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +该节点旨在使用提供的字典对给定文本执行搜索和替换操作。它智能地将字典键的出现的文本替换为相应的值,确保以受控的方式进行替换,以避免覆盖不希望替换的文本段。 + +# Input types +## Required +- text + - 将执行搜索和替换操作的输入文本。这是节点将处理的主要数据,以实现预期的结果。 + - Comfy dtype: STRING + - Python dtype: str +- dictionary + - 一个字典,其中键是文本中要搜索的术语,值是将替换键的术语。它在确定节点输出中起着关键作用。 + - Comfy dtype: DICT + - Python dtype: Dict[str, str] +## Optional +- replacement_key + - 一个字符串,用于在文本中搜索之前包装字典中的键。它有助于防止文本中发生意外的替换。 + - Comfy dtype: STRING + - Python dtype: str +- seed + - 用于随机数生成器的种子,以控制替换过程的随机性。它确保了可重复性,以获得确定性结果。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- new_text + - 应用搜索和替换操作后的生成文本。它反映了根据输入字典和参数所做的更改。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Search_and_Replace_Dictionary: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'dictionary': ('DICT',), 'replacement_key': ('STRING', {'default': '__', 'multiline': False}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'text_search_and_replace_dict' + CATEGORY = 'WAS Suite/Text/Search' + + def text_search_and_replace_dict(self, text, dictionary, replacement_key, seed): + random.seed(seed) + new_text = text + for term in dictionary.keys(): + tkey = f'{replacement_key}{term}{replacement_key}' + tcount = new_text.count(tkey) + for _ in range(tcount): + new_text = new_text.replace(tkey, random.choice(dictionary[term]), 1) + if seed > 0 or seed < 0: + seed = seed + 1 + random.seed(seed) + return (new_text,) + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') +``` \ No newline at end of file diff --git a/docs/Text Find and Replace.md b/docs/Text Find and Replace.md new file mode 100644 index 0000000..d8b0efb --- /dev/null +++ b/docs/Text Find and Replace.md @@ -0,0 +1,68 @@ +# Documentation +- Class name: WAS_Search_and_Replace +- Category: WAS Suite/Text/Search +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +此节点旨在对给定文本执行搜索和替换操作。它识别文本中指定子字符串的出现次数,并将其替换为不同的子字符串。节点的功能旨在通过提供直接的字符串替换接口,促进文本操作和数据清洗任务。 + +# Input types +## Required +- text + - 文本参数是节点的主要输入,包含要处理的文本。它至关重要,因为它决定了搜索和替换操作将发生的上下文。节点的执行和结果直接受所提供文本的内容和结构的影响。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- find + - 查找参数指定了节点将在文本中搜索的子字符串。它在确定操作范围方面起着重要作用,因为节点将针对此子字符串进行替换。节点的有效性取决于在此参数中提供的子字符串的准确性。 + - Comfy dtype: STRING + - Python dtype: str +- replace + - 替换参数定义了将用于替换文本中查找参数出现次数的子字符串。它对于转换过程至关重要,因为它决定了替换后新内容将是什么。节点修改文本的能力直接与分配给此参数的值有关。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- result_text + - result_text输出参数保存了搜索和替换操作完成后的修改文本。它代表了节点功能的主要结果,展示了应用了指定替换后的文本的最终状态。 + - Comfy dtype: STRING + - Python dtype: str +- replacement_count_number + - replacement_count_number输出参数提供了在文本中查找子字符串被替换了多少次的计数。这个数值很重要,因为它量化了节点执行的替换操作的范围。 + - Comfy dtype: NUMBER + - Python dtype: int +- replacement_count_float + - replacement_count_float输出参数以浮点数的形式提供替换计数。在需要对替换计数进行进一步计算或分析的情况下,使用小数表示的替换计数可能会很有用。 + - Comfy dtype: FLOAT + - Python dtype: float +- replacement_count_int + - replacement_count_int输出参数以整数形式呈现替换计数。它作为总替换次数的直接数值表示,在各种计算或统计上下文中都可以使用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Search_and_Replace: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'find': ('STRING', {'default': '', 'multiline': False}), 'replace': ('STRING', {'default': '', 'multiline': False})}} + RETURN_TYPES = (TEXT_TYPE, 'NUMBER', 'FLOAT', 'INT') + RETURN_NAMES = ('result_text', 'replacement_count_number', 'replacement_count_float', 'replacement_count_int') + FUNCTION = 'text_search_and_replace' + CATEGORY = 'WAS Suite/Text/Search' + + def text_search_and_replace(self, text, find, replace): + (modified_text, count) = self.replace_substring(text, find, replace) + return (modified_text, count, float(count), int(count)) + + def replace_substring(self, text, find, replace): + (modified_text, count) = re.subn(find, replace, text) + return (modified_text, count) +``` \ No newline at end of file diff --git a/docs/Text Input Switch.md b/docs/Text Input Switch.md new file mode 100644 index 0000000..fd1f598 --- /dev/null +++ b/docs/Text Input Switch.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: WAS_Text_Input_Switch +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_Input_Switch节点的'text_input_switch'方法旨在根据布尔标志有条件地在两个文本输入之间进行选择。它作为一个逻辑开关,在一个需要决策的流程或工作流中指导文本数据的流向。此节点在管理基于文本的操作中的条件逻辑中起着关键作用。 + +# Input types +## Required +- text_a + - 'text_a'参数是节点根据布尔条件可以切换到的第一个文本输入。它对于节点的决策过程至关重要,因为它代表了布尔标志为真时可能的结果之一。 + - Comfy dtype: STRING + - Python dtype: str +- text_b + - 'text_b'参数是当布尔标志为假时节点可以选择的替代文本输入。它至关重要,因为它定义了条件未满足时文本数据的替代路径。 + - Comfy dtype: STRING + - Python dtype: str +- boolean + - 'boolean'参数作为一个标志,用以决定返回哪个文本输入。它是节点功能的关键组成部分,因为它的真值直接影响节点的输出。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- output_text + - 'output_text'是节点操作的结果,根据'boolean'输入的值,它要么是'text_a'要么是'text_b'。它代表了节点决策过程后选定的文本。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Input_Switch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text_a': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'text_b': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'boolean': ('BOOLEAN', {'forceInput': True})}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'text_input_switch' + CATEGORY = 'WAS Suite/Logic' + + def text_input_switch(self, text_a, text_b, boolean=True): + if boolean: + return (text_a,) + else: + return (text_b,) +``` \ No newline at end of file diff --git a/docs/Text List Concatenate.md b/docs/Text List Concatenate.md new file mode 100644 index 0000000..a5cbb1f --- /dev/null +++ b/docs/Text List Concatenate.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: WAS_Text_List_Concatenate +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_List_Concatenate节点旨在高效地将多个字符串列表合并为一个单一的统一列表。它在简化数据预处理工作流程中发挥着关键作用,特别是当处理来自不同来源且需要聚合以进行进一步处理或分析的文本数据时。 + +# Input types +## Required +- list_a + - 'list_a'参数是一个字符串列表,它将与其他列表合并。它是节点的基本输入,因为它直接促成了最终合并列表的形成。 + - Comfy dtype: LIST + - Python dtype: List[str] +## Optional +- list_b + - 'list_b'参数是一个可选的字符串列表,它可以与主列表连接。它通过允许在最终列表中包含额外数据,增强了节点的灵活性。 + - Comfy dtype: LIST + - Python dtype: Optional[List[str]] +- list_c + - 'list_c'参数是用于连接的另一个可选字符串列表。它为节点提供了进一步的定制选项,使用户能够更精确地控制输出列表的组成。 + - Comfy dtype: LIST + - Python dtype: Optional[List[str]] +- list_d + - 'list_d'参数是另一个可以连接到合并列表的可选列表。它为用户提供了包括更多字符串的能力,进一步根据特定要求定制最终输出。 + - Comfy dtype: LIST + - Python dtype: Optional[List[str]] + +# Output types +- merged_list + - 'merged_list'输出是连接所有输入列表的结果。它代表了可以用于后续操作或分析的组合文本数据。 + - Comfy dtype: LIST + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_List_Concatenate: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'list_a': ('LIST', {'forceInput': True}), 'list_b': ('LIST', {'forceInput': True}), 'list_c': ('LIST', {'forceInput': True}), 'list_d': ('LIST', {'forceInput': True})}} + RETURN_TYPES = ('LIST',) + FUNCTION = 'text_concatenate_list' + CATEGORY = 'WAS Suite/Text' + + def text_concatenate_list(self, **kwargs): + merged_list: list[str] = [] + for k in sorted(kwargs.keys()): + v = kwargs[k] + if isinstance(v, list): + merged_list += v + return (merged_list,) +``` \ No newline at end of file diff --git a/docs/Text List to Text.md b/docs/Text List to Text.md new file mode 100644 index 0000000..9a09d50 --- /dev/null +++ b/docs/Text List to Text.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: WAS_Text_List_to_Text +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_List_to_Text节点旨在将一系列文本字符串合并为单个文本字符串。它通过在列表的每个元素之间插入指定的分隔符来实现这一点,有效地将它们合并为一个连贯的序列。在需要将多个文本输入汇总成统一格式的文本处理工作流程中,该节点发挥着关键作用。 + +# Input types +## Required +- delimiter + - 分隔符参数定义了在将文本列表的元素连接在一起时使用的字符或字符串。它对于确定最终合并文本的格式至关重要,并且可以显著影响输出的可读性和结构。 + - Comfy dtype: STRING + - Python dtype: str +- text_list + - text_list参数是节点将处理的一系列文本字符串的集合。这是一个强制性输入,表明节点需要这些数据来执行其功能。节点的操作直接依赖于text_list的内容和结构,这将决定连接过程后的最终输出。 + - Comfy dtype: LIST + - Python dtype: List[str] + +# Output types +- merged_text + - merged_text输出是使用指定的分隔符连接输入text_list的结果。它表示将组合文本作为单个字符串,可以用于下游任务中的进一步处理或分析。 + - Comfy dtype: TEXT + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_List_to_Text: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'delimiter': ('STRING', {'default': ', '}), 'text_list': ('LIST', {'forceInput': True})}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'text_list_to_text' + CATEGORY = 'WAS Suite/Text' + + def text_list_to_text(self, delimiter, text_list): + if delimiter == '\\n': + delimiter = '\n' + merged_text = delimiter.join(text_list) + return (merged_text,) +``` \ No newline at end of file diff --git a/docs/Text List.md b/docs/Text List.md new file mode 100644 index 0000000..1e48343 --- /dev/null +++ b/docs/Text List.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: WAS_Text_List +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +该节点将输入的文本字符串组织并结构化为统一的列表格式,便于后续对文本数据的处理和分析。 + +# Input types +## Required +- text_a + - 第一个文本输入对于节点的运行至关重要,因为它提供了列表形成的初始数据。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- text_b + - 额外的文本输入进一步丰富了列表,允许进行更全面的文本分析。 + - Comfy dtype: STRING + - Python dtype: Optional[str] +- text_c + - 后续的文本输入增加了文本列表的多样性,增强了其在各种文本处理场景中的实用性。 + - Comfy dtype: STRING + - Python dtype: Optional[str] +- text_d + - 更多的文本输入扩展了节点的能力,适应了更广泛的文本数据集。 + - Comfy dtype: STRING + - Python dtype: Optional[str] +- text_e + - 额外的文本输入确保节点可以处理多种多样的文本输入,增加了其灵活性。 + - Comfy dtype: STRING + - Python dtype: Optional[str] +- text_f + - 多个文本输入的存在突显了节点有效管理复杂文本数据的能力。 + - Comfy dtype: STRING + - Python dtype: Optional[str] +- text_g + - 包含更多的文本输入展示了节点扩展和适应各种文本处理需求的能力。 + - Comfy dtype: STRING + - Python dtype: Optional[str] + +# Output types +- list_of_texts + - 输出是一个整合后的文本字符串列表,为进一步的分析和处理提供了结构化的格式。 + - Comfy dtype: LIST + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_List: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'text_a': ('STRING', {'forceInput': True}), 'text_b': ('STRING', {'forceInput': True}), 'text_c': ('STRING', {'forceInput': True}), 'text_d': ('STRING', {'forceInput': True}), 'text_e': ('STRING', {'forceInput': True}), 'text_f': ('STRING', {'forceInput': True}), 'text_g': ('STRING', {'forceInput': True})}} + RETURN_TYPES = ('LIST',) + FUNCTION = 'text_as_list' + CATEGORY = 'WAS Suite/Text' + + def text_as_list(self, **kwargs): + text_list: list[str] = [] + for k in sorted(kwargs.keys()): + v = kwargs[k] + if isinstance(v, str): + text_list.append(v) + return (text_list,) +``` \ No newline at end of file diff --git a/docs/Text Load Line From File.md b/docs/Text Load Line From File.md new file mode 100644 index 0000000..54c3bea --- /dev/null +++ b/docs/Text Load Line From File.md @@ -0,0 +1,163 @@ +# Documentation +- Class name: WAS_Text_Load_Line_From_File +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_Load_Line_From_File节点旨在从指定文件中读取和处理文本行。它能够处理单个或多行文本,并提供按索引加载文本或基于计数器自动加载的功能。该节点还维护了访问过的文本文件的历史记录,方便检索先前加载的文本数据。 + +# Input types +## Required +- file_path + - file_path参数指定了要读取的文本文件的位置。这是一个关键参数,因为节点的操作取决于成功访问此路径上的文件。文件路径中的任何错误都将阻止节点执行其预期功能。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- dictionary_name + - dictionary_name参数定义了加载的文本行将在结果字典中存储的键。它允许用户标记文本数据,以便在应用程序的上下文中更容易引用和组织。 + - Comfy dtype: STRING + - Python dtype: str +- label + - label参数用于在应用程序中识别和管理不同的文本批次。它有助于跟踪和组织系统中的文本数据流,特别是涉及多个文本源时。 + - Comfy dtype: STRING + - Python dtype: str +- mode + - mode参数确定节点从文本文件中检索行的方法。它可以设置为'automatic'以进行顺序访问,或设置为'index'以根据其在文件中的位置加载特定行。 + - Comfy dtype: COMBO[automatic, index] + - Python dtype: str +- index + - 当mode设置为'index'时,index参数适用。它指定要从文本文件中加载的行的基于零的位置。这允许直接访问文件中的特定行。 + - Comfy dtype: INT + - Python dtype: int +- multiline_text + - multiline_text参数提供了一种向节点提供文本的替代方式。节点将直接通过此参数处理提供的文本,而不是从文件中读取。这对于动态或内联文本处理场景特别有用。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str + +# Output types +- line_text + - line_text输出包含根据指定的模式和索引从文件中检索到的实际文本行。这是节点处理的文本数据的主要输出。 + - Comfy dtype: STRING + - Python dtype: str +- dictionary + - dictionary输出是由dictionary_name参数索引的文本行集合。它作为在应用程序内访问和使用文本数据的结构化方式。 + - Comfy dtype: DICT + - Python dtype: Dict[str, List[str]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Load_Line_From_File: + + def __init__(self): + self.HDB = WASDatabase(WAS_HISTORY_DATABASE) + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'file_path': ('STRING', {'default': '', 'multiline': False}), 'dictionary_name': ('STRING', {'default': '[filename]', 'multiline': False}), 'label': ('STRING', {'default': 'TextBatch', 'multiline': False}), 'mode': (['automatic', 'index'],), 'index': ('INT', {'default': 0, 'min': 0, 'step': 1})}, 'optional': {'multiline_text': (TEXT_TYPE, {'forceInput': True})}} + + @classmethod + def IS_CHANGED(cls, **kwargs): + if kwargs['mode'] != 'index': + return float('NaN') + else: + m = hashlib.sha256() + if os.path.exists(kwargs['file_path']): + with open(kwargs['file_path'], 'rb') as f: + m.update(f.read()) + return m.digest().hex() + else: + return False + RETURN_TYPES = (TEXT_TYPE, 'DICT') + RETURN_NAMES = ('line_text', 'dictionary') + FUNCTION = 'load_file' + CATEGORY = 'WAS Suite/Text' + + def load_file(self, file_path='', dictionary_name='[filename]', label='TextBatch', mode='automatic', index=0, multiline_text=None): + if multiline_text is not None: + lines = multiline_text.strip().split('\n') + if mode == 'index': + if index < 0 or index >= len(lines): + cstr(f'Invalid line index `{index}`').error.print() + return ('', {dictionary_name: []}) + line = lines[index] + else: + line_index = self.HDB.get('TextBatch Counters', label) + if line_index is None: + line_index = 0 + line = lines[line_index % len(lines)] + self.HDB.insert('TextBatch Counters', label, line_index + 1) + return (line, {dictionary_name: lines}) + if file_path == '': + cstr('No file path specified.').error.print() + return ('', {dictionary_name: []}) + if not os.path.exists(file_path): + cstr(f'The path `{file_path}` specified cannot be found.').error.print() + return ('', {dictionary_name: []}) + file_list = self.TextFileLoader(file_path, label) + (line, lines) = (None, []) + if mode == 'automatic': + (line, lines) = file_list.get_next_line() + elif mode == 'index': + if index >= len(file_list.lines): + index = index % len(file_list.lines) + (line, lines) = file_list.get_line_by_index(index) + if line is None: + cstr('No valid line was found. The file may be empty or all lines have been read.').error.print() + return ('', {dictionary_name: []}) + file_list.store_index() + update_history_text_files(file_path) + return (line, {dictionary_name: lines}) + + class TextFileLoader: + + def __init__(self, file_path, label): + self.WDB = WDB + self.file_path = file_path + self.lines = [] + self.index = 0 + self.load_file(file_path, label) + + def load_file(self, file_path, label): + stored_file_path = self.WDB.get('TextBatch Paths', label) + stored_index = self.WDB.get('TextBatch Counters', label) + if stored_file_path != file_path: + self.index = 0 + self.WDB.insert('TextBatch Counters', label, 0) + self.WDB.insert('TextBatch Paths', label, file_path) + else: + self.index = stored_index + with open(file_path, 'r', encoding='utf-8', newline='\n') as file: + self.lines = [line.strip() for line in file] + + def get_line_index(self): + return self.index + + def set_line_index(self, index): + self.index = index + self.WDB.insert('TextBatch Counters', 'TextBatch', self.index) + + def get_next_line(self): + if self.index >= len(self.lines): + self.index = 0 + line = self.lines[self.index] + self.index += 1 + if self.index == len(self.lines): + self.index = 0 + cstr(f'{cstr.color.YELLOW}TextBatch{cstr.color.END} Index: {self.index}').msg.print() + return (line, self.lines) + + def get_line_by_index(self, index): + if index < 0 or index >= len(self.lines): + cstr(f'Invalid line index `{index}`').error.print() + return (None, []) + self.index = index + line = self.lines[self.index] + cstr(f'{cstr.color.YELLOW}TextBatch{cstr.color.END} Index: {self.index}').msg.print() + return (line, self.lines) + + def store_index(self): + self.WDB.insert('TextBatch Counters', 'TextBatch', self.index) +``` \ No newline at end of file diff --git a/docs/Text Multiline.md b/docs/Text Multiline.md new file mode 100644 index 0000000..c000d37 --- /dev/null +++ b/docs/Text Multiline.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: WAS_Text_Multiline +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_Multiline节点旨在处理和格式化多行文本输入。它过滤掉注释和空行,然后用相应的值替换预定义和自定义的标记,为文本模板注入动态数据提供了一种多功能的方式。 + +# Input types +## Required +- text + - ‘text’参数是节点的主要输入,接受可能包含注释和标记占位符的多行字符串。它对节点的操作至关重要,因为它定义了将被处理和格式化的基础文本。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- new_text + - ‘new_text’输出参数代表过滤和标记替换后处理过的文本。它很重要,因为它是节点的最终输出,为用户提供了准备好使用的格式化文本。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Multiline: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {'default': '', 'multiline': True})}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'text_multiline' + CATEGORY = 'WAS Suite/Text' + + def text_multiline(self, text): + import io + new_text = [] + for line in io.StringIO(text): + if not line.strip().startswith('#'): + if not line.strip().startswith('\n'): + line = line.replace('\n', '') + new_text.append(line) + new_text = '\n'.join(new_text) + tokens = TextTokens() + new_text = tokens.parseTokens(new_text) + return (new_text,) +``` \ No newline at end of file diff --git a/docs/Text Parse A1111 Embeddings.md b/docs/Text Parse A1111 Embeddings.md new file mode 100644 index 0000000..838ff4d --- /dev/null +++ b/docs/Text Parse A1111 Embeddings.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: WAS_Text_Parse_Embeddings_By_Name +- Category: WAS Suite/Text/Parse +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +`text_parse_embeddings` 方法旨在解析并替换文本为相应的嵌入。它通过识别输入文本中的特定模式,这些模式与嵌入文件的名称匹配,并将它们替换为包含单词 'embedding' 后跟文件名的预定义格式。这个过程对于准备文本数据以进行进一步的处理或利用基于嵌入的模型的分析至关重要。 + +# Input types +## Required +- text + - ‘text’ 参数至关重要,因为它提供了节点将处理的原始文本数据。这是节点执行模式匹配和替换以嵌入适当引用嵌入文件的输入。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- parsed_text + - ‘parsed_text’ 输出包含带有适当格式化的嵌入引用的修改后的文本。它是节点操作的结果,对于任何需要使用嵌入数据的后续步骤都很重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Parse_Embeddings_By_Name: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False})}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'text_parse_embeddings' + CATEGORY = 'WAS Suite/Text/Parse' + + def text_parse_embeddings(self, text): + return (self.convert_a1111_embeddings(text),) + + def convert_a1111_embeddings(self, text): + for embeddings_path in comfy_paths.folder_names_and_paths['embeddings'][0]: + for filename in os.listdir(embeddings_path): + (basename, ext) = os.path.splitext(filename) + pattern = re.compile('\\b{}\\b'.format(re.escape(basename))) + replacement = 'embedding:{}'.format(basename) + text = re.sub(pattern, replacement, text) + return text +``` \ No newline at end of file diff --git a/docs/Text Parse Noodle Soup Prompts.md b/docs/Text Parse Noodle Soup Prompts.md new file mode 100644 index 0000000..e87c792 --- /dev/null +++ b/docs/Text Parse Noodle Soup Prompts.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: WAS_Text_Parse_NSP +- Category: WAS Suite/Text/Parse +- Output node: True +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_Parse_NSP 节点旨在根据指定模式处理和转换文本。它利用 'Noodle Soup Prompts' 的功能进行创造性的文本操作,或使用通配符替换方法进行更结构化的处理。此节点对于需要文本解析或增强的任务至关重要,为各种基于文本的应用程序提供了一种多功能的解决方案。 + +# Input types +## Required +- text + - 文本参数是节点的核心输入。它决定了将经历解析和转换的内容。节点的操作严重依赖此输入,使其对于实现期望的输出至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- mode + - 模式参数决定了节点采用的解析策略。它可以设置为 'Noodle Soup Prompts' 进行创造性方法,或者设置为 'Wildcards' 进行更结构化的文本操作。此参数对于指导节点的处理行为至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- noodle_key + - noodle_key 参数用作 'Noodle Soup Prompts' 模式下文本中的分隔符。它标志着可以被替换或操作的术语的开始和结束,因此在解析过程中扮演着重要角色。 + - Comfy dtype: STRING + - Python dtype: str +- seed + - seed 参数是一个可选的整数,可用于在解析过程中引入随机性。它通过为随机操作提供一致的起点,确保结果的可复现性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- new_text + - new_text 输出代表了节点应用指定解析方法后处理过的文本。它是节点功能的最终成果,对后续操作或分析具有重要价值。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Parse_NSP: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'mode': (['Noodle Soup Prompts', 'Wildcards'],), 'noodle_key': ('STRING', {'default': '__', 'multiline': False}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'text': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False})}} + OUTPUT_NODE = True + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'text_parse_nsp' + CATEGORY = 'WAS Suite/Text/Parse' + + def text_parse_nsp(self, text, mode='Noodle Soup Prompts', noodle_key='__', seed=0): + if mode == 'Noodle Soup Prompts': + new_text = nsp_parse(text, seed, noodle_key) + cstr(f'Text Parse NSP:\n{new_text}').msg.print() + else: + new_text = replace_wildcards(text, None if seed == 0 else seed, noodle_key) + cstr(f'CLIPTextEncode Wildcards:\n{new_text}').msg.print() + return (new_text,) +``` \ No newline at end of file diff --git a/docs/Text Parse Tokens.md b/docs/Text Parse Tokens.md new file mode 100644 index 0000000..19cbb34 --- /dev/null +++ b/docs/Text Parse Tokens.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: WAS_Text_Parse_Tokens +- Category: WAS Suite/Text/Tokens +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_Parse_Tokens节点旨在处理和替换给定文本字符串中的令牌。它通过识别预定义的和自定义的令牌,并将它们替换为相应的值来操作,从而实现了基于当前时间、主机名和用户信息等上下文数据的动态文本生成。 + +# Input types +## Required +- text + - ‘text’参数对于节点的操作至关重要,因为它提供了将被扫描以替换令牌的输入文本。节点的功能在很大程度上依赖于这个输入来执行其替换任务,使其成为整体执行中的关键组成部分。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- parsed_text + - ‘parsed_text’输出包含完成令牌替换过程后的文本。它标志着节点的成功执行以及基于预定义和自定义令牌对输入文本的转换。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Parse_Tokens: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False})}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'text_parse_tokens' + CATEGORY = 'WAS Suite/Text/Tokens' + + def text_parse_tokens(self, text): + tokens = TextTokens() + return (tokens.parseTokens(text),) + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') +``` \ No newline at end of file diff --git a/docs/Text Random Line.md b/docs/Text Random Line.md new file mode 100644 index 0000000..7c9e048 --- /dev/null +++ b/docs/Text Random Line.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: WAS_Text_Random_Line +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 'text_random_line' 旨在从给定的文本输入中选择一个随机行。它作为工具,适用于需要随机抽样文本行的应用,如在数据预处理或内容生成任务中。 + +# Input types +## Required +- text + - 参数 'text' 是将要从中选择随机行的输入文本。它在确定随机选择的内容池中起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- seed + - 参数 'seed' 用于初始化随机数生成器,确保随机行选择过程的可复现性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- random_line + - 输出 'random_line' 代表从输入文本中随机选择的行,这是节点操作的主要结果。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Random_Line: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'text_random_line' + CATEGORY = 'WAS Suite/Text' + + def text_random_line(self, text, seed): + lines = text.split('\n') + random.seed(seed) + choice = random.choice(lines) + return (choice,) + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') +``` \ No newline at end of file diff --git a/docs/Text Random Prompt.md b/docs/Text Random Prompt.md new file mode 100644 index 0000000..3274cc5 --- /dev/null +++ b/docs/Text Random Prompt.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: WAS_Text_Random_Prompt +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_Random_Prompt类的`random_prompt`方法旨在根据给定的搜索种子生成一个随机文本提示,如果没有提供搜索种子,则使用一组默认提示。它使用外部API获取与查询相关的图像列表,并返回与列表中某个图像相关联的随机提示。 + +# Input types +## Required +- search_seed + - 参数`search_seed`用于定义生成随机文本提示的初始查询。它至关重要,因为它直接影响生成的提示类型以及从外部API检索的后续图像。 + - Comfy dtype: STRING + - Python dtype: Union[str, None] + +# Output types +- prompt + - 参数`prompt`代表`random_prompt`方法的输出,这是一个基于输入查询随机选择的文本提示。它很重要,因为它构成了对生成的提示进行的任何后续处理或分析的基础。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Random_Prompt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'search_seed': ('STRING', {'multiline': False})}} + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'random_prompt' + CATEGORY = 'WAS Suite/Text' + + def random_prompt(self, search_seed=None): + if search_seed in ['', ' ']: + search_seed = None + return (self.search_lexica_art(search_seed),) + + def search_lexica_art(self, query=None): + if not query: + query = random.choice(['portrait', 'landscape', 'anime', 'superhero', 'animal', 'nature', 'scenery']) + url = f'https://lexica.art/api/v1/search?q={query}' + try: + response = requests.get(url, proxies=config.get_proxies()) + data = response.json() + images = data.get('images', []) + if not images: + return '404 not found error' + random_image = random.choice(images) + prompt = random_image.get('prompt') + except Exception: + cstr('Unable to establish connection to Lexica API.').error.print() + prompt = '404 not found error' + return prompt +``` \ No newline at end of file diff --git a/docs/Text Shuffle.md b/docs/Text Shuffle.md new file mode 100644 index 0000000..202a4e4 --- /dev/null +++ b/docs/Text Shuffle.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: WAS_Text_Shuffle +- Category: WAS Suite/Text/Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_Shuffle 节点的 `shuffle` 方法旨在重新排列给定文本字符串中的元素顺序。它通过使用指定的分隔符将文本分割成元素列表,随机打乱该列表,然后将元素重新组合成一个新的字符串来操作。这个方法特别适用于需要随机化文本元素的任务,例如数据增强或从固定输入集创建多样化输出。 + +# Input types +## Required +- text + - 参数 'text' 表示将要被打乱的输入文本。它是节点操作的基本部分,因为整个过程围绕重新排列此文本的元素。此参数的重要性在于它对输出的直接影响,决定了打乱后文本的内容和结构。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- separator + - 参数 'separator' 定义了在打乱之前用来将输入文本分割成单独元素的分隔符。它对于确定如何划分文本以及如何重新排列元素至关重要。默认值是逗号,但可以根据正在处理的文本的具体要求调整为任何字符或字符串。 + - Comfy dtype: STRING + - Python dtype: str +- seed + - 参数 'seed' 是一个可选的整数,用于初始化随机数生成器,确保打乱的顺序是可复现的。这在希望在节点的多次执行中获得一致结果的场景中特别重要。通过提供种子,用户可以控制随机性,并且每次使用相同的输入和种子值运行节点时都能获得相同的打乱顺序。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- shuffled_text + - 输出参数 'shuffled_text' 表示打乱过程后得到的文本。它是输入文本在元素被随机重新排列后的直接反映。这个输出很重要,因为它是节点操作的主要结果,也是任何后续处理或分析的基础。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_Shuffle: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'separator': ('STRING', {'default': ',', 'multiline': False}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = (TEXT_TYPE,) + FUNCTION = 'shuffle' + CATEGORY = 'WAS Suite/Text/Operations' + + def shuffle(self, text, separator, seed): + if seed is not None: + random.seed(seed) + text_list = text.split(separator) + random.shuffle(text_list) + new_text = separator.join(text_list) + return (new_text,) +``` \ No newline at end of file diff --git a/docs/Text String Truncate.md b/docs/Text String Truncate.md new file mode 100644 index 0000000..bb53e11 --- /dev/null +++ b/docs/Text String Truncate.md @@ -0,0 +1,95 @@ +# Documentation +- Class name: WAS_Text_String_Truncate +- Category: WAS Suite/Text/Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_String_Truncate节点的`truncate_string`方法旨在将输入字符串缩减到指定的长度,可以按字符或单词从字符串的开头或结尾进行缩减。该方法用于以一种保持信息完整性的方式管理文本长度,确保截断后的文本适应所需的限制条件,同时不会丢失重要内容。 + +# Input types +## Required +- text + - 参数'text'是节点的主要输入,表示将要被截断的字符串。这是一个关键元素,因为节点的操作重点是在保留其核心信息的同时减少这段文本的长度。 + - Comfy dtype: STRING + - Python dtype: str +- truncate_by + - 参数'truncate_by'决定截断的单位,可以是字符或单词。这个选择显著影响文本的缩减方式以及保留文本的哪一部分。 + - Comfy dtype: COMBO['characters', 'words'] + - Python dtype: str +- truncate_from + - 参数'truncate_from'决定截断应该从文本的末尾还是开头开始。这个决定直接影响了截断后剩余文本的可见性和上下文。 + - Comfy dtype: COMBO['end', 'beginning'] + - Python dtype: str +- truncate_to + - 参数'truncate_to'指定了文本应该被截断到的最大长度。这是一个关键的设置,因为它定义了截断过程后字符串的最终长度。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- text_b + - 参数'text_b'是可选的附加字符串,可以提供用于截断。它提供了同时处理多个字符串的灵活性,增强了节点在文本管理场景中的实用性。 + - Comfy dtype: STRING + - Python dtype: str +- text_c + - 参数'text_c'是另一个用于截断的可选字符串,与'text_b'的功能相似。它扩展了节点在单个操作中处理更多文本数据的能力。 + - Comfy dtype: STRING + - Python dtype: str +- text_d + - 参数'text_d'是节点截断过程中的最后一个可选字符串。它进一步扩展了节点同时管理更多文本的能力。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- truncated_text + - 输出参数'truncated_text'代表截断过程的结果。它是符合指定限制条件的输入文本的缩短版本,确保输出文本简洁且相关。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str +- truncated_text_b + - 输出参数'truncated_text_b'对应于可选输入'text_b'的截断版本。它提供与'truncated_text'相同的功能,但适用于第二个可选字符串。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str +- truncated_text_c + - 输出参数'truncated_text_c'类似于'truncated_text_b',提供第三个可选字符串'text_c'的结果。它确保节点可以在单个调用中处理多个字符串。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str +- truncated_text_d + - 输出参数'truncated_text_d'是可选字符串'text_d'的最终输出。它完成了节点一次性截断多个字符串的能力,提供了一个全面的文本管理解决方案。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_String_Truncate: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {'forceInput': True}), 'truncate_by': (['characters', 'words'],), 'truncate_from': (['end', 'beginning'],), 'truncate_to': ('INT', {'default': 10, 'min': -99999999, 'max': 99999999, 'step': 1})}, 'optional': {'text_b': ('STRING', {'forceInput': True}), 'text_c': ('STRING', {'forceInput': True}), 'text_d': ('STRING', {'forceInput': True})}} + RETURN_TYPES = (TEXT_TYPE, TEXT_TYPE, TEXT_TYPE, TEXT_TYPE) + FUNCTION = 'truncate_string' + CATEGORY = 'WAS Suite/Text/Operations' + + def truncate_string(self, text, truncate_by, truncate_from, truncate_to, text_b='', text_c='', text_d=''): + return (self.truncate(text, truncate_to, truncate_from, truncate_by), self.truncate(text_b, truncate_to, truncate_from, truncate_by), self.truncate(text_c, truncate_to, truncate_from, truncate_by), self.truncate(text_d, truncate_to, truncate_from, truncate_by)) + + def truncate(self, string, max_length, mode='end', truncate_by='characters'): + if mode not in ['beginning', 'end']: + cstr("Invalid mode. 'mode' must be either 'beginning' or 'end'.").error.print() + mode = 'end' + if truncate_by not in ['characters', 'words']: + cstr("Invalid truncate_by. 'truncate_by' must be either 'characters' or 'words'.").error.print() + if truncate_by == 'characters': + if mode == 'beginning': + return string[:max_length] if max_length >= 0 else string[max_length:] + else: + return string[-max_length:] if max_length >= 0 else string[:max_length] + words = string.split() + if mode == 'beginning': + return ' '.join(words[:max_length]) if max_length >= 0 else ' '.join(words[max_length:]) + else: + return ' '.join(words[-max_length:]) if max_length >= 0 else ' '.join(words[:max_length]) +``` \ No newline at end of file diff --git a/docs/Text String.md b/docs/Text String.md new file mode 100644 index 0000000..1bc69f2 --- /dev/null +++ b/docs/Text String.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: WAS_Text_String +- Category: WAS Suite/Text +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +`text_string` 方法旨在处理和标记输入字符串,将预定义和自定义的标记替换为它们的相应值。它在动态文本生成中扮演着关键角色,允许将时间戳和系统信息等上下文元素纳入其中。 + +# Input types +## Required +- text + - 'text' 参数对于节点的操作至关重要,因为它是将要被标记化和处理的主要输入。它通过确定将用实际值替换标记的基础文本来影响执行。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- text_b + - 'text_b' 参数是可选的,作为节点的额外文本输入。它允许更复杂的标记替换和文本操作,增强了节点功能的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- text_c + - 'text_c' 参数与 'text_b' 类似,是另一个可选的文本输入,可以由节点处理。它扩展了节点处理多个文本输入以进行更复杂的标记化任务的能力。 + - Comfy dtype: STRING + - Python dtype: str +- text_d + - 'text_d' 参数也是可选的,提供了进一步的文本输入以供处理。它有助于节点管理更多的文本输入,满足更复杂的标记化需求。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- text_output + - 'text_output' 参数代表标记替换后的已处理文本。它很重要,因为它反映了节点文本操作和标记化过程的结果。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_String: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': ('STRING', {'default': '', 'multiline': False})}, 'optional': {'text_b': ('STRING', {'default': '', 'multiline': False}), 'text_c': ('STRING', {'default': '', 'multiline': False}), 'text_d': ('STRING', {'default': '', 'multiline': False})}} + RETURN_TYPES = (TEXT_TYPE, TEXT_TYPE, TEXT_TYPE, TEXT_TYPE) + FUNCTION = 'text_string' + CATEGORY = 'WAS Suite/Text' + + def text_string(self, text='', text_b='', text_c='', text_d=''): + tokens = TextTokens() + text = tokens.parseTokens(text) + text_b = tokens.parseTokens(text_b) + text_c = tokens.parseTokens(text_c) + text_d = tokens.parseTokens(text_d) + return (text, text_b, text_c, text_d) +``` \ No newline at end of file diff --git a/docs/Text To Image (mtb).md b/docs/Text To Image (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/Text to Conditioning.md b/docs/Text to Conditioning.md new file mode 100644 index 0000000..1434247 --- /dev/null +++ b/docs/Text to Conditioning.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: WAS_Text_to_Conditioning +- Category: WAS Suite/Text/Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_to_Conditioning节点旨在将文本输入转换为可用于生成模型中的条件格式。它利用文本编码器的能力来处理文本,并创建一个可以引导生成过程的条件信号。该节点抽象了文本编码的复杂性,为用户提供了一个简单的接口,将文本元素集成到他们的工作流程中。 + +# Input types +## Required +- clip + - ‘clip’参数对于文本到条件的过程至关重要,因为它代表了文本将与之关联的上下文信息。这个参数对于节点的执行至关重要,因为它构成了编码过程的基础。 + - Comfy dtype: CLIP + - Python dtype: Union[torch.Tensor, comfy.sd.CLIP] +- text + - ‘text’参数是一个强制性输入,它提供了要被编码为条件格式的文本内容。它的重要性在于它直接影响到输出的条件,这被用来指导生成过程。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- encoded_conditioning + - ‘encoded_conditioning’输出是输入文本的加工版本,被转换成适合用于条件生成模型的格式。它以一种可以被模型用于生成输出的方式来封装文本的语义内容。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_to_Conditioning: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'clip': ('CLIP',), 'text': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False})}} + RETURN_TYPES = ('CONDITIONING',) + FUNCTION = 'text_to_conditioning' + CATEGORY = 'WAS Suite/Text/Operations' + + def text_to_conditioning(self, clip, text): + encoder = nodes.CLIPTextEncode() + encoded = encoder.encode(clip=clip, text=text) + return (encoded[0], {'ui': {'string': text}}) +``` \ No newline at end of file diff --git a/docs/Text to Console.md b/docs/Text to Console.md new file mode 100644 index 0000000..4ba21f6 --- /dev/null +++ b/docs/Text to Console.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: WAS_Text_to_Console +- Category: WAS Suite/Debug +- Output node: True +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_to_Console节点旨在将文本输出到控制台,并可选择性地进行标签格式化。它通过为文本应用颜色和样式来增强控制台输出,以提高可见性和区分度。 + +# Input types +## Required +- text + - ‘text’参数对于节点的操作至关重要,因为它定义了将被打印到控制台的内容。它在节点的执行中起着关键作用,决定了显示的信息。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- label + - 'label'参数用于在文本输出前加上自定义标签。虽然不是必需的,但它对于分类或突出显示控制台输出以提高可读性和组织性可能很有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- output + - 'output'参数代表已格式化并打印到控制台的文本。它标志着节点操作的最终结果,封装了样式化文本。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_to_Console: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False}), 'label': ('STRING', {'default': f'Text Output', 'multiline': False})}} + RETURN_TYPES = (TEXT_TYPE,) + OUTPUT_NODE = True + FUNCTION = 'text_to_console' + CATEGORY = 'WAS Suite/Debug' + + def text_to_console(self, text, label): + if label.strip() != '': + cstr(f'\x1b[33m{label}\x1b[0m:\n{text}\n').msg.print() + else: + cstr(f'\x1b[33mText to Console\x1b[0m:\n{text}\n').msg.print() + return (text,) +``` \ No newline at end of file diff --git a/docs/Text to Number.md b/docs/Text to Number.md new file mode 100644 index 0000000..c4f18f6 --- /dev/null +++ b/docs/Text to Number.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: WAS_Text_To_Number +- Category: WAS Suite/Text/Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +该节点将文本数据转换为数值,使其能够以数值格式进行进一步的处理和分析。 + +# Input types +## Required +- text + - 文本参数是必需的,它提供了需要转换为数字格式的原始文本数据。它是决定节点输出的主要输入。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- NUMBER + - 输出是输入文本的数值表示,可以是整数或浮点数,这取决于文本内容。 + - Comfy dtype: NUMBER + - Python dtype: Union[int, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_To_Number: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False})}} + RETURN_TYPES = ('NUMBER',) + FUNCTION = 'text_to_number' + CATEGORY = 'WAS Suite/Text/Operations' + + def text_to_number(self, text): + if text.replace('.', '').isnumeric(): + number = float(text) + else: + number = int(text) + return (number,) +``` \ No newline at end of file diff --git a/docs/Text to String.md b/docs/Text to String.md new file mode 100644 index 0000000..38466f5 --- /dev/null +++ b/docs/Text to String.md @@ -0,0 +1,41 @@ +# Documentation +- Class name: WAS_Text_To_String +- Category: WAS Suite/Text/Operations +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Text_To_String节点的'text_to_string'方法旨在将输入文本转换为标准化的字符串格式。它确保文本被处理并以一种一致且可用于工作流后续操作的形式返回。 + +# Input types +## Required +- text + - 'text'参数对于节点的操作至关重要,因为它定义了需要被转换为字符串的内容。它的作用是为节点提供待处理的原始材料,这对于节点的执行和结果至关重要。 + - Comfy dtype: STRING + - Python dtype: Union[str, List[str]] + +# Output types +- output + - 'output'参数代表'text_to_string'方法的结果,即转换后的字符串。它很重要,因为它是节点的主要输出,包含了处理后的文本。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Text_To_String: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'text': (TEXT_TYPE, {'forceInput': True if TEXT_TYPE == 'STRING' else False})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'text_to_string' + CATEGORY = 'WAS Suite/Text/Operations' + + def text_to_string(self, text): + return (text,) +``` \ No newline at end of file diff --git a/docs/Text2InputOr3rdOption.md b/docs/Text2InputOr3rdOption.md new file mode 100644 index 0000000..eea2187 --- /dev/null +++ b/docs/Text2InputOr3rdOption.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: Text2InputOr3rdOption +- Category: Mikey/Text +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +Text2InputOr3rdOption节点的'output'函数旨在根据条件逻辑处理并返回文本输入。它使用提供的提示中的值替换输入文本中的占位符,并可以返回两个单独的文本或一对相同的文本,这取决于一个布尔标志。 + +# Input types +## Required +- text_a + - 参数'text_a'是一个字符串输入,预计包含文本。它至关重要,因为它是将要被处理并可能用提示中的值替换占位符的主要输入之一。 + - Comfy dtype: STRING + - Python dtype: str +- text_b + - 参数'text_b'是另一个字符串输入,将与'text_a'进行相同的处理。它很重要,因为当'use_text_c_for_both'设置为'false'时,它决定了次要文本输出。 + - Comfy dtype: STRING + - Python dtype: str +- text_c + - 参数'text_c'是一个字符串输入,如果' use_text_c_for_both'标志设置为'true',它可能会被用作'text_a'和'text_b'的替代品。它在确定节点的最终输出中起着关键作用。 + - Comfy dtype: STRING + - Python dtype: str +- use_text_c_for_both + - 参数'use_text_c_for_both'是一个布尔标志,它决定是否应该使用'text_c'作为'text_a'和'text_b'的输出。它对于控制节点的输出行为至关重要。 + - Comfy dtype: COMBO['true', 'false'] + - Python dtype: str +## Optional +- extra_pnginfo + - 参数'extra_pnginfo'是一个可选输入,当提供时,包含用于在文本输入中搜索和替换占位符的额外信息。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Union[Dict, str] +- prompt + - 参数'prompt'是一个可选输入,它提供了一组结构化的值,用于替换文本输入中的占位符。它对文本替换过程至关重要。 + - Comfy dtype: PROMPT + - Python dtype: Union[Dict, str] + +# Output types +- text_a + - 输出'text_a'是初始'text_a'输入的加工版本,其中的占位符已被提示中的相应值替换。 + - Comfy dtype: STRING + - Python dtype: str +- text_b + - 输出'text_b'在结构上与'text_a'输出相对应,但源自'text_b'输入。它是经过处理并替换了占位符的文本。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Text2InputOr3rdOption: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text_a': ('STRING', {'multiline': True, 'default': 'Text A'}), 'text_b': ('STRING', {'multiline': True, 'default': 'Text B'}), 'text_c': ('STRING', {'multiline': True, 'default': 'Text C'}), 'use_text_c_for_both': (['true', 'false'], {'default': 'false'})}, 'hidden': {'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('text_a', 'text_b') + FUNCTION = 'output' + CATEGORY = 'Mikey/Text' + + def output(self, text_a, text_b, text_c, use_text_c_for_both, extra_pnginfo, prompt): + text_a = search_and_replace(text_a, extra_pnginfo, prompt) + text_b = search_and_replace(text_b, extra_pnginfo, prompt) + text_c = search_and_replace(text_c, extra_pnginfo, prompt) + if use_text_c_for_both == 'true': + return (text_c, text_c) + else: + return (text_a, text_b) +``` \ No newline at end of file diff --git a/docs/TextCombinations.md b/docs/TextCombinations.md new file mode 100644 index 0000000..a804ab8 --- /dev/null +++ b/docs/TextCombinations.md @@ -0,0 +1,96 @@ +# Documentation +- Class name: TextCombinations2 +- Category: Mikey/Text +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +TextCombinations2节点旨在生成一系列文本操作,这些操作以定义的操作方式结合两个输入文本。它通过在输入上执行指定的操作来促进输出文本的创建,提供了文本处理的灵活性。 + +# Input types +## Required +- text1 + - 'text1'参数是将在组合操作中使用的第一种输入文本。它在确定最终输出中起着关键作用,因为它是被操作的主要元素之一。 + - Comfy dtype: STRING + - Python dtype: str +- text2 + - 'text2'参数是与'text1'通过定义的操作结合的第二种输入文本。它的内容对于输出生成过程至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- operation + - 'operation'参数定义了要在输入文本上执行的特定组合操作。它至关重要,因为它决定了如何将'text1'和'text2'转换为所需的输出。 + - Comfy dtype: COMBO['text1 to output1', 'text2 to output2'] + - Python dtype: str +## Optional +- delimiter + - 'delimiter'参数指定在操作期间连接文本组件时使用字符或字符串。它影响最终输出的格式。 + - Comfy dtype: STRING + - Python dtype: str +- use_seed + - 'use_seed'参数决定是否应使用种子值从预定义的操作列表中选择一个操作。它为操作选择过程增加了随机性或特定性。 + - Comfy dtype: COMBO['true', 'false'] + - Python dtype: str +- seed + - 'seed'参数是一个整数值,当'use_seed'设置为true时,用于偏移操作的选择。它确保根据提供的整数选择特定的操作。 + - Comfy dtype: INT + - Python dtype: int +- extra_pnginfo + - 'extra_pnginfo'参数保存可能需要用于某些操作的额外信息。它用于根据额外的上下文数据影响节点的行为。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Union[Dict, str] +- prompt + - 'prompt'参数为节点提供指导或额外的上下文,可能会改变其处理输入文本的方式。它对于需要交互式或条件行为的节点特别有用。 + - Comfy dtype: PROMPT + - Python dtype: Union[Dict, str] + +# Output types +- output1 + - 'output1'参数代表组合操作后的第一个结果文本。它是输入和指定操作的直接结果。 + - Comfy dtype: STRING + - Python dtype: str +- output2 + - 'output2'参数代表组合操作后的第二个结果文本。它是从输入和执行的操作派生出的另一个输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TextCombinations2: + texts = ['text1', 'text2', 'text1 + text2'] + outputs = ['output1', 'output2'] + + @classmethod + def generate_combinations(cls, texts, outputs): + operations = [] + for (output1, output2) in product(texts, repeat=len(outputs)): + operation = f'{output1} to {outputs[0]}, {output2} to {outputs[1]}' + operations.append(operation) + return operations + + @classmethod + def INPUT_TYPES(cls): + cls.operations = cls.generate_combinations(cls.texts, cls.outputs) + return {'required': {'text1': ('STRING', {'multiline': True, 'default': 'Text 1'}), 'text2': ('STRING', {'multiline': True, 'default': 'Text 2'}), 'operation': (cls.operations, {'default': cls.operations[0]}), 'delimiter': ('STRING', {'default': ' '}), 'use_seed': (['true', 'false'], {'default': 'false'}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('output1', 'output2') + FUNCTION = 'mix' + CATEGORY = 'Mikey/Text' + + def mix(self, text1, text2, operation, delimiter, use_seed, seed, extra_pnginfo, prompt): + text1 = search_and_replace(text1, extra_pnginfo, prompt) + text2 = search_and_replace(text2, extra_pnginfo, prompt) + text_dict = {'text1': text1, 'text2': text2} + if use_seed == 'true' and len(self.operations) > 0: + offset = seed % len(self.operations) + operation = self.operations[offset] + ops = operation.split(', ') + output_texts = [op.split(' to ')[0] for op in ops] + outputs = [] + for output_text in output_texts: + components = output_text.split(' + ') + final_output = delimiter.join((eval(comp, {}, text_dict) for comp in components)) + outputs.append(final_output) + return tuple(outputs) +``` \ No newline at end of file diff --git a/docs/TextCombinations3.md b/docs/TextCombinations3.md new file mode 100644 index 0000000..46b5b0f --- /dev/null +++ b/docs/TextCombinations3.md @@ -0,0 +1,97 @@ +# Documentation +- Class name: TextCombinations3 +- Category: Mikey/Text +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +TextCombinations3节点旨在生成一组文本操作,以各种方式组合输入文本。它提供了一种基于预定义操作和指定分隔符混合和转换文本字符串的方法。该节点的功能集中在创建文本输入的组合以产生不同的输出,这对于文本分析或数据预处理任务非常有用。 + +# Input types +## Required +- text1 + - 'text1'参数是一个字符串,代表第一个输入文本。它在节点的操作中起着关键作用,因为它是将被组合和操作以生成最终输出的主要文本数据来源之一。 + - Comfy dtype: STRING + - Python dtype: str +- text2 + - 'text2'参数是另一个字符串输入,它补充了'text1'。它对于创建多样化的文本组合至关重要,并与'text1'一起使用,以实现生成混合文本输出的节点目的。 + - Comfy dtype: STRING + - Python dtype: str +- text3 + - 'text3'参数是节点的第三个输入文本字符串。它对于扩大可能的文本组合范围和确保节点能够产生广泛的输出变化非常重要。 + - Comfy dtype: STRING + - Python dtype: str +- operation + - 'operation'参数定义了要执行的特定文本组合。它是节点执行的关键决定因素,因为它决定了输入文本将如何混合以创建所需的输出。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- delimiter + - 'delimiter'参数指定用于分隔组合文本组件的字符或字符串。它对于定义最终输出的格式和确保混合文本以连贯的方式呈现非常重要。 + - Comfy dtype: STRING + - Python dtype: str +- use_seed + - 'use_seed'参数是一个布尔标志,指示是否应使用种子值从预定义列表中选择一个操作。它影响文本组合过程的随机性和可重复性。 + - Comfy dtype: STRING + - Python dtype: str +- seed + - 'seed'参数是一个整数,当'use_seed'设置为true时,用作操作选择的随机种子。它确保了生成文本组合的一致起点,这对于获得可重复的结果至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output1 + - 'output1'参数代表节点生成的第一个混合文本输出。这是节点操作的重要结果,展示了输入文本的组合和转换。 + - Comfy dtype: STRING + - Python dtype: str +- output2 + - 'output2'参数是节点的第二个混合文本输出。它反映了输入文本的另一种变化,展示了节点产生多个不同输出的能力。 + - Comfy dtype: STRING + - Python dtype: str +- output3 + - 'output3'参数表示第三个混合文本输出。这是节点如何操作和组合文本输入以产生多样化结果集的另一个示例。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TextCombinations3: + texts = ['text1', 'text2', 'text3', 'text1 + text2', 'text1 + text3', 'text2 + text3', 'text1 + text2 + text3'] + outputs = ['output1', 'output2', 'output3'] + + @classmethod + def generate_combinations(cls, texts, outputs): + operations = [] + for (output1, output2, output3) in product(texts, repeat=len(outputs)): + operation = f'{output1} to {outputs[0]}, {output2} to {outputs[1]}, {output3} to {outputs[2]}' + operations.append(operation) + return operations + + @classmethod + def INPUT_TYPES(cls): + cls.operations = cls.generate_combinations(cls.texts, cls.outputs) + return {'required': {'text1': ('STRING', {'multiline': True, 'default': 'Text 1'}), 'text2': ('STRING', {'multiline': True, 'default': 'Text 2'}), 'text3': ('STRING', {'multiline': True, 'default': 'Text 3'}), 'operation': (cls.operations, {'default': cls.operations[0]}), 'delimiter': ('STRING', {'default': ' '}), 'use_seed': (['true', 'false'], {'default': 'false'}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('STRING', 'STRING', 'STRING') + RETURN_NAMES = ('output1', 'output2', 'output3') + FUNCTION = 'mix' + CATEGORY = 'Mikey/Text' + + def mix(self, text1, text2, text3, operation, delimiter, use_seed, seed, extra_pnginfo, prompt): + text1 = search_and_replace(text1, extra_pnginfo, prompt) + text2 = search_and_replace(text2, extra_pnginfo, prompt) + text3 = search_and_replace(text3, extra_pnginfo, prompt) + text_dict = {'text1': text1, 'text2': text2, 'text3': text3} + if use_seed == 'true' and len(self.operations) > 0: + offset = seed % len(self.operations) + operation = self.operations[offset] + ops = operation.split(', ') + output_texts = [op.split(' to ')[0] for op in ops] + outputs = [] + for output_text in output_texts: + components = output_text.split(' + ') + final_output = delimiter.join((eval(comp, {}, text_dict) for comp in components)) + outputs.append(final_output) + return tuple(outputs) +``` \ No newline at end of file diff --git a/docs/TextConcat.md b/docs/TextConcat.md new file mode 100644 index 0000000..6fb1775 --- /dev/null +++ b/docs/TextConcat.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: TextConcat +- Category: Mikey/Text +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +TextConcat节点旨在高效地将多个字符串组合成单个字符串。它通过接受文本列表和分隔符,然后使用指定的分隔符将提供的文本串联起来,实现这一功能。这个节点在从不同的信息片段中创建一个连贯的字符串时非常有用,这在文本处理和数据准备任务中至关重要。 + +# Input types +## Required +- delimiter + - 分隔符参数是一个字符串,用于在串联各个文本输入时分隔它们。它在确定输出字符串的最终格式中起着关键作用,允许用户控制串联文本之间的空格和分隔。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- text1 + - text1参数代表可以与其他文本串联的第一个文本输入。它是可选的,如果提供,它将被包含在最终串联的字符串中。 + - Comfy dtype: STRING + - Python dtype: str +- text2 + - text2参数是另一个可选的文本输入,可以包含在串联过程中。它允许进一步定制最终字符串。 + - Comfy dtype: STRING + - Python dtype: str +- text3 + - text3参数是串联中的另一个额外的可选文本输入。它扩展了功能,以在最终输出中包含更多的文本元素。 + - Comfy dtype: STRING + - Python dtype: str +- text4 + - text4参数是另一个可选输入,可以与其他文本串联。它在构建所需的输出字符串中提供了进一步的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- text5 + - text5参数是用于串联的最后一个可选文本输入。它提供了在字符串最终确定之前添加文本的最后机会。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- concatenated_text + - concatenated_text输出是使用指定的分隔符将所有输入文本连接在一起后得到的最终字符串。它代表了串联过程的成果,是TextConcat节点的主要输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TextConcat: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'delimiter': ('STRING', {'default': ' '})}, 'optional': {'text1': ('STRING', {'default': ''}), 'text2': ('STRING', {'default': ''}), 'text3': ('STRING', {'default': ''}), 'text4': ('STRING', {'default': ''}), 'text5': ('STRING', {'default': ''})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'concat' + CATEGORY = 'Mikey/Text' + + def concat(self, delimiter, text1, text2, text3, text4, text5): + texts = [] + if text1: + texts.append(text1) + if text2: + texts.append(text2) + if text3: + texts.append(text3) + if text4: + texts.append(text4) + if text5: + texts.append(text5) + text = delimiter.join(texts) + return (text,) +``` \ No newline at end of file diff --git a/docs/TextImage.md b/docs/TextImage.md new file mode 100644 index 0000000..eac36b7 --- /dev/null +++ b/docs/TextImage.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: TextImage +- Category: ♾️Mixlab/Image +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点便于创建带有文本内容的图像,提供了一系列定制选项,如字体风格、大小和颜色。它将文本数据与视觉表示融合,使得能够生成将文本和设计元素整合在一起的自定义视觉输出。该节点特别适用于需要将文本信息合成到图像格式的应用场景。 + +# Input types +## Required +- text + - 文本参数至关重要,它定义了将要渲染到图像中的文本内容。它是节点操作的主要输入,决定了将要视觉化呈现的信息或消息。 + - Comfy dtype: STRING + - Python dtype: str +- font_path + - font_path参数指定了用于文本的字体来源。它在确定生成图像中文本的风格外观方面至关重要,影响整体美感和可读性。 + - Comfy dtype: STRING + - Python dtype: str +- font_size + - font_size参数调整文本的大小,直接影响图像中文本的突出性和可读性。它是最终输出视觉影响的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- spacing + - 间距参数定义了字符和文本行之间的距离,可以增强或降低图像的清晰度和视觉吸引力。它在文本内容的排列和呈现中起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- text_color + - text_color参数设置了文本的颜色,影响图像的对比度和视觉动态效果。它是设计的重要方面,有助于整体视觉效果。 + - Comfy dtype: STRING + - Python dtype: str +- vertical + - vertical参数决定了文本的方向,是水平还是垂直。这个选择影响了图像中文本的布局和结构,影响了构图和流动性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- stroke + - stroke参数在文本周围应用边框或轮廓,增强了文本的定义和与背景的分离。这为文本增加了额外的视觉细节和深度。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- IMAGE + - 图像输出是节点的主要结果,代表了输入文本的视觉表示。它封装了设计选择和文本布局,提供了可以用于各种应用的有形输出。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- MASK + - MASK输出提供了文本图像的alpha通道表示,可用于高级图像处理和合成任务。它提供了对文本透明度和与其他视觉元素混合的控制水平。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TextImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True, 'default': '龍馬精神迎新歲', 'dynamicPrompts': False}), 'font_path': ('STRING', {'multiline': False, 'default': FONT_PATH, 'dynamicPrompts': False}), 'font_size': ('INT', {'default': 100, 'min': 100, 'max': 1000, 'step': 1, 'display': 'number'}), 'spacing': ('INT', {'default': 12, 'min': -200, 'max': 200, 'step': 1, 'display': 'number'}), 'text_color': ('STRING', {'multiline': False, 'default': '#000000', 'dynamicPrompts': False}), 'vertical': ('BOOLEAN', {'default': True}), 'stroke': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('IMAGE', 'MASK') + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Image' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False, False) + + def run(self, text, font_path, font_size, spacing, text_color, vertical, stroke): + (img, mask) = generate_text_image(text, font_path, font_size, text_color, vertical, stroke, (0, 0, 0), 1, spacing) + img = pil2tensor(img) + mask = pil2tensor(mask) + return (img, mask) +``` \ No newline at end of file diff --git a/docs/TextInput_.md b/docs/TextInput_.md new file mode 100644 index 0000000..573e692 --- /dev/null +++ b/docs/TextInput_.md @@ -0,0 +1,40 @@ +# Documentation +- Class name: TextInput +- Category: ♾️Mixlab/Utils +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +TextInput节点旨在处理文本输入,为处理字符串数据提供了一个简单的接口。它能够接受多行文本,为各种文本处理任务提供了灵活性。在需要文本分析或操作的流程中,这个节点扮演着关键角色,确保文本被正确格式化并准备好进行后续操作。 + +# Input types +## Required +- text + - ‘text’参数是TextInput节点的主要输入。这是提供要处理的实际文本的地方。这个输入至关重要,因为它直接影响节点的操作和随后的输出。文本可以跨越多行,适应广泛的文本输入。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- output_text + - ‘output_text’是由TextInput节点处理输入文本后产生的结果。它代表了输入的转换或分析版本,具体取决于节点执行的操作。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TextInput: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True, 'default': ''})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Utils' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False,) + + def run(self, text): + return (text,) +``` \ No newline at end of file diff --git a/docs/TextPreserve.md b/docs/TextPreserve.md new file mode 100644 index 0000000..50cae06 --- /dev/null +++ b/docs/TextPreserve.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: TextPreserve +- Category: Mikey/Text +- Output node: True +- Repo Ref: https://github.com/bash-j/mikey_nodes + +TextPreserve节点旨在处理和保留原始文本,同时允许动态内容替换。它通过识别输入文本中的占位符并将它们替换为随机或指定的值来实现这一点,确保在整个转换过程中保持原始消息的完整性。 + +# Input types +## Required +- text + - ‘text’参数是节点的主要输入,包含将被处理的文本。它至关重要,因为它定义了将经历保留和替换过程的内容。此参数支持多行,允许复杂和扩展的文本输入。 + - Comfy dtype: STRING + - Python dtype: str +- result_text + - ‘result_text’参数是节点执行后存储处理文本的地方。它至关重要,因为它包含了所有替换和保留操作完成后文本的最终输出。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- unique_id + - ‘unique_id’参数用于在工作流中唯一标识节点。它是可选的,但对于跟踪和管理节点在更大系统中的状态和输出可能很重要。 + - Comfy dtype: UNIQUE_ID + - Python dtype: Union[str, None] +- extra_pnginfo + - ‘extra_pnginfo’参数提供了可以用来增强文本处理的额外信息。它是可选的,并且可能包含影响节点操作方式的元数据或其他相关细节。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Union[str, None] +- prompt + - ‘prompt’参数用于提供指导文本替换过程的动态提示。它是可选的,但可以通过引入特定于上下文的替换来显著影响节点的行为。 + - Comfy dtype: PROMPT + - Python dtype: Union[str, None] + +# Output types +- text + - ‘text’输出参数代表了所有操作完成后的最终处理文本。它是节点功能的最高体现,包含了保留和替换过程的结果。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TextPreserve: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True, 'default': 'Input Text Here', 'dynamicPrompts': False}), 'result_text': ('STRING', {'multiline': True, 'default': 'Result Text Here (will be replaced)'})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('text',) + FUNCTION = 'process' + OUTPUT_NODE = True + CATEGORY = 'Mikey/Text' + + def process(self, text, result_text, unique_id=None, extra_pnginfo=None, prompt=None): + random.seed() + preserve_text = text + text = search_and_replace(text, extra_pnginfo, prompt) + wc_re = re.compile('{([^}]+)}') + + def repl(m): + return random.choice(m.group(1).split('|')) + for m in wc_re.finditer(text): + text = text.replace(m.group(0), repl(m)) + prompt.get(str(unique_id))['inputs']['text'] = preserve_text + for (i, node_dict) in enumerate(extra_pnginfo['workflow']['nodes']): + if node_dict['id'] == int(unique_id): + node_dict['widgets_values'] = [preserve_text, text] + extra_pnginfo['workflow']['nodes'][i] = node_dict + prompt.get(str(unique_id))['inputs']['result_text'] = text + return (text,) +``` \ No newline at end of file diff --git a/docs/TextSplitByDelimiter.md b/docs/TextSplitByDelimiter.md new file mode 100644 index 0000000..fc96e07 --- /dev/null +++ b/docs/TextSplitByDelimiter.md @@ -0,0 +1,62 @@ +# Documentation +- Class name: TextSplitByDelimiter +- Category: ♾️Mixlab/GPT +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点基于指定的分隔符对文本数据进行分割,能够从非结构化文本中提取结构化信息。它旨在高效处理大型数据集,为用户在文本分析和预处理任务中提供简单而强大的工具。 + +# Input types +## Required +- text + - 输入文本是节点操作的主要数据源。它的质量与格式直接影响分割过程的有效性及提取片段的准确性。 + - Comfy dtype: STRING + - Python dtype: str +- delimiter + - 分隔符参数决定了文本的分隔标准。它在确定文本如何被分割中起着至关重要的作用,从而影响输出的结构。 + - Comfy dtype: COMBO + - Python dtype: str +- start_index + - start_index参数定义了文本中开始分割过程的位置。它影响着选定输出的初始片段,并可用于跳过文本中不需要的部分。 + - Comfy dtype: INT + - Python dtype: int +- skip_every + - skip_every参数决定了在分割过程中跳过片段的频率。它在控制输出的密度方面起着重要作用,并且有助于聚焦文本中特定的兴趣区域。 + - Comfy dtype: INT + - Python dtype: int +- max_count + - max_count参数设置了提取片段数量的上限。它在管理输出的范围方面很重要,确保节点不会处理过多的数据。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- segmented_text + - 输出是基于输入参数提取的文本片段列表。每个片段代表原始文本的一部分,根据指定的分隔符和其他输入标准进行结构化。 + - Comfy dtype: STRING + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TextSplitByDelimiter: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'delimiter': (['newline', 'comma'],), 'start_index': ('INT', {'default': 0, 'min': 0, 'max': 1000, 'step': 1, 'display': 'number'}), 'skip_every': ('INT', {'default': 0, 'min': 0, 'max': 10, 'step': 1, 'display': 'number'}), 'max_count': ('INT', {'default': 10, 'min': 1, 'max': 1000, 'step': 1, 'display': 'number'})}} + INPUT_IS_LIST = False + RETURN_TYPES = ('STRING',) + FUNCTION = 'run' + OUTPUT_IS_LIST = (True,) + CATEGORY = '♾️Mixlab/GPT' + + def run(self, text, delimiter, start_index, skip_every, max_count): + arr = [] + if delimiter == 'newline': + arr = [line for line in text.split('\n') if line.strip()] + elif delimiter == 'comma': + arr = [line for line in text.split(',') if line.strip()] + arr = arr[start_index:start_index + max_count * (skip_every + 1):skip_every + 1] + return (arr,) +``` \ No newline at end of file diff --git a/docs/TextToNumber.md b/docs/TextToNumber.md new file mode 100644 index 0000000..46886e6 --- /dev/null +++ b/docs/TextToNumber.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: TextToNumber +- Category: ♾️Mixlab/Utils +- Output node: False +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +该节点抽象了将文本数据转换为数值的过程,便于分析和处理基于文本的信息。它强调将输入文本转换为数值表示,这可以进一步用于各种计算任务。 + +# Input types +## Required +- text + - 文本参数至关重要,因为它作为提取数值的来源。文本的质量和内容直接影响节点的输出。 + - Comfy dtype: STRING + - Python dtype: str +- random_number + - 该参数决定了在从文本中提取数值后是否应用随机数生成过程,为结果增加了变化性。 + - Comfy dtype: COMBO + - Python dtype: str +- max_num + - max_num参数设置了随机数生成的上限,确保生成的数字保持在指定的范围内。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- seed + - seed参数对于确保随机数生成过程的可重复性至关重要,允许在相同条件下获得一致的结果。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- ui.text + - 此输出包含原始文本输入,为了参考和上下文而保留,这对于理解数值结果的起源很重要。 + - Comfy dtype: STRING + - Python dtype: List[str] +- ui.num + - ui.num输出代表从文本中提取的数值或随机数生成的结果,这是节点的主要输出,对后续计算至关重要。 + - Comfy dtype: INT + - Python dtype: List[int] +- result + - 结果输出是最终的数值,它是节点处理的结晶,对于进一步的分析或操作至关重要。 + - Comfy dtype: INT + - Python dtype: Tuple[int] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TextToNumber: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': False, 'default': '1'}), 'random_number': (['enable', 'disable'],), 'max_num': ('INT', {'default': 10, 'min': 2, 'max': 10000000000, 'step': 1, 'display': 'number'})}, 'optional': {'seed': (any_type, {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + RETURN_TYPES = ('INT',) + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Utils' + INPUT_IS_LIST = False + OUTPUT_IS_LIST = (False,) + + def run(self, text, random_number, max_num, seed=0): + numbers = re.findall('\\d+', text) + result = 0 + for n in numbers: + result = int(n) + if random_number == 'enable' and result > 0: + result = random.randint(1, max_num) + return {'ui': {'text': [text], 'num': [result]}, 'result': (result,)} +``` \ No newline at end of file diff --git a/docs/TilePreprocessor_Provider_for_SEGS %2F%2FInspire.md b/docs/TilePreprocessor_Provider_for_SEGS %2F%2FInspire.md new file mode 100644 index 0000000..bea9ccc --- /dev/null +++ b/docs/TilePreprocessor_Provider_for_SEGS %2F%2FInspire.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: TilePreprocessor_Provider_for_SEGS +- Category: InspirePack/SEGS/ControlNet +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +TilePreprocessor_Provider_for_SEGS 类旨在通过预处理输入图像来提高图像分割任务的准确性。它采用金字塔上采样方法来细化图像细节,确保分割模型接收到最优化的数据处理。该节点通过确保分割过程尽可能有效和精确,从而对整体工作流程做出贡献。 + +# Input types +## Required +- pyrUp_iters + - ‘pyrUp_iters’参数对于控制金字塔上采样过程中使用的迭代次数至关重要。它直接影响预处理图像的细节和分辨率水平,进而影响分割输出的质量。适当调整此参数可以显著提高分割结果。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- SEGS_PREPROCESSOR + - TilePreprocessor_Provider_for_SEGS 节点的输出是为分割任务优化的预处理图像。该输出作为后续分割模型的输入,确保它们接收到最可能准确的数据,以获得可靠和准确的结果。 + - Comfy dtype: SEGS_PREPROCESSOR + - Python dtype: PIL.Image or numpy.ndarray + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TilePreprocessor_Provider_for_SEGS: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pyrUp_iters': ('INT', {'default': 3, 'min': 1, 'max': 10, 'step': 1})}} + RETURN_TYPES = ('SEGS_PREPROCESSOR',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/SEGS/ControlNet' + + def doit(self, pyrUp_iters): + obj = TilePreprocessor_wrapper(pyrUp_iters) + return (obj,) +``` \ No newline at end of file diff --git a/docs/Tiled KSampler.md b/docs/Tiled KSampler.md new file mode 100644 index 0000000..e55fa72 --- /dev/null +++ b/docs/Tiled KSampler.md @@ -0,0 +1,84 @@ +# Documentation +- Class name: Tiled_KSampler +- Category: Sampling/Tiled +- Output node: False +- Repo Ref: https://github.com/FlyingFireCo/tiled_ksampler.git + +Tiled_KSampler 节点旨在通过将采样过程划分为更小、更易管理的平铺区域来执行高效的采样操作。它利用平铺的概念来增强采样过程,从而能够处理更大的模型和数据集。该节点旨在为其所属类别内的采样任务提供一种强大且可扩展的解决方案。 + +# Input types +## Required +- model + - 模型参数对于 Tiled_KSampler 节点至关重要,因为它定义了用于采样的底层模型架构。此参数直接影响节点的执行和采样结果的质量。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- seed + - 种子参数初始化随机数生成器,确保采样过程的可重复性。它在确定采样迭代的起始点中起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- tiling + - 平铺参数指定是否应使用平铺方法执行采样。它对于控制节点的操作模式以及影响采样过程的效率具有重要意义。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步数参数确定采样过程的迭代次数。它是控制采样过程持续时间和彻底性的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg 参数,代表配置值,用于控制采样过程的参数。它是微调不同采样任务节点性能的重要因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name 参数选择节点内部要使用的特定采样方法。对于将节点的功能调整为所需的采样技术至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- scheduler + - 调度器参数定义了在采样过程中要应用的调度算法。它是管理采样步骤并实现所需结果的关键组件。 + - Comfy dtype: STRING + - Python dtype: str +- positive + - positive 参数提供正向条件信息,引导采样过程朝向期望的结果。它对影响采样迭代的方向很重要。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- negative + - negative 参数提供负向条件信息,以防止采样过程中的某些结果。它在塑造采样结果中扮演着重要角色。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- latent_image + - latent_image 参数是一个关键输入,代表采样过程的初始潜在状态。它为后续的采样迭代奠定了基础。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +## Optional +- denoise + - denoise 参数在采样过程中调整去噪强度,允许控制噪声减少级别。这是一个可选但有用的设置,用于细化采样输出。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- latent + - 潜在输出代表了采样过程产生的最终采样潜在状态。它很重要,因为它包含了节点操作的结果,并作为进一步处理或分析的输入。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class Tiled_KSampler: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model': ('MODEL',), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'tiling': ('INT', {'default': 1, 'min': 0, 'max': 1}), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'sample' + CATEGORY = 'Sampling/Tiled' + + def apply_circular(self, model, enable): + for layer in [layer for layer in model.modules() if isinstance(layer, torch.nn.Conv2d)]: + layer.padding_mode = 'circular' if enable else 'zeros' + + def sample(self, model, seed, tiling, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=1.0): + self.apply_circular(model.model, tiling == 1) + return nodes.common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise) +``` \ No newline at end of file diff --git a/docs/TiledDiffusion.md b/docs/TiledDiffusion.md new file mode 100644 index 0000000..ebf14a0 --- /dev/null +++ b/docs/TiledDiffusion.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: TiledDiffusion +- Category: _for_testing +- Output node: False +- Repo Ref: https://github.com/shiimizu/ComfyUI-TiledDiffusion + +TiledDiffusion类作为一个框架,用于以平铺的方式应用扩散模型,通过将大图像分割成较小的片段来增强处理,这种方法提高了计算效率并允许对扩散过程进行更细粒度的控制。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了节点内部要使用的扩散模型。它是控制TiledDiffusion过程行为和输出的核心组件。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_patcher.ModelPatcher +- method + - 方法参数决定了要使用的具体扩散技术,影响输出的整体性能和质量。它是调整节点功能以适应期望结果的关键因素。 + - Comfy dtype: COMBO[('MultiDiffusion', 'Mixture of Diffusers')] + - Python dtype: str +- tile_width + - tile_width参数决定了平铺过程中每个瓦片的宽度,直接影响扩散应用的粒度。它对于优化处理时间和结果细节之间的平衡至关重要。 + - Comfy dtype: INT + - Python dtype: int +- tile_height + - tile_height参数设置了每个瓦片的高度,与tile_width一起决定了平铺策略。这个参数对于管理计算负载和确保扩散过程的效率至关重要。 + - Comfy dtype: INT + - Python dtype: int +- tile_overlap + - tile_overlap参数定义了相邻瓦片之间的重叠,确保整个图像上扩散效果的无缝集成。它在维持最终输出的连贯性和质量方面起着至关重要的作用。 + - Comfy dtype: INT + - Python dtype: int +- tile_batch_size + - tile_batch_size参数指定了每批处理的瓦片数量,这对于管理内存使用和加速扩散过程至关重要。它直接影响计算资源和处理速度之间的权衡。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- model + - 输出模型是输入模型的修改版本,现在配备了平铺扩散功能。它代表了节点处理的成果,封装了通过扩散方法处理大图像的增强能力。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_patcher.ModelPatcher + +# Usage tips +- Infra type: GPU + +# Source code +``` +class TiledDiffusion: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'method': (['MultiDiffusion', 'Mixture of Diffusers'], {'default': 'Mixture of Diffusers'}), 'tile_width': ('INT', {'default': 96 * opt_f, 'min': 16, 'max': MAX_RESOLUTION, 'step': 16}), 'tile_height': ('INT', {'default': 96 * opt_f, 'min': 16, 'max': MAX_RESOLUTION, 'step': 16}), 'tile_overlap': ('INT', {'default': 8 * opt_f, 'min': 0, 'max': 256 * opt_f, 'step': 4 * opt_f}), 'tile_batch_size': ('INT', {'default': 4, 'min': 1, 'max': MAX_RESOLUTION, 'step': 1})}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'apply' + CATEGORY = '_for_testing' + + def apply(self, model: ModelPatcher, method, tile_width, tile_height, tile_overlap, tile_batch_size): + if method == 'Mixture of Diffusers': + implement = MixtureOfDiffusers() + else: + implement = MultiDiffusion() + implement.tile_width = tile_width // opt_f + implement.tile_height = tile_height // opt_f + implement.tile_overlap = tile_overlap // opt_f + implement.tile_batch_size = tile_batch_size + model = model.clone() + model.set_model_unet_function_wrapper(implement) + model.model_options['tiled_diffusion'] = True + return (model,) +``` \ No newline at end of file diff --git a/docs/TiledKSamplerProvider.md b/docs/TiledKSamplerProvider.md new file mode 100644 index 0000000..d3546db --- /dev/null +++ b/docs/TiledKSamplerProvider.md @@ -0,0 +1,76 @@ +# Documentation +- Class name: TiledKSamplerProvider +- Category: ImpactPack/Sampler +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +TiledKSamplerProvider 节点旨在通过利用平铺策略来促进图像去噪的采样过程。它智能地管理图像的划分为平铺,允许进行高效和无缝的去噪。该节点通过减少平铺之间接缝的可见性来增强去噪过程,从而有助于获得更连贯和更高质量的输出图像。 + +# Input types +## Required +- seed + - seed 参数在采样算法中的随机数生成过程中至关重要,确保了结果的可复现性。它影响随机数生成器的初始状态,进而影响去噪结果。 + - Comfy dtype: INT + - Python dtype: int +- steps + - steps 参数定义了去噪过程将进行的迭代次数。它是确定最终去噪图像质量的关键因素,更多的步骤通常会导致更好的去噪结果。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg 参数调整采样过程的配置,允许对去噪算法的性能进行微调。它在平衡去噪结果的速度和质量方面起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name 参数指定了去噪过程中要使用的采样器类型。它对于确定采样策略和直接影响去噪的有效性至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- scheduler + - scheduler 参数决定了去噪步骤的调度策略,这对于控制去噪进展的速度很重要。 + - Comfy dtype: STRING + - Python dtype: str +- denoise + - denoise 参数控制应用于每个平铺的去噪强度。它是去噪图像最终外观的关键因素,更高的值会导致更激进的去噪。 + - Comfy dtype: FLOAT + - Python dtype: float +- tile_width + - tile_width 参数设置了平铺策略中每个平铺的宽度。它对于确定去噪过程的粒度很重要,并且可能影响最终图像中接缝的可见性。 + - Comfy dtype: INT + - Python dtype: int +- tile_height + - tile_height 参数设置了平铺策略中每个平铺的高度。它与 tile_width 一起工作,定义了平铺的整体结构,并影响去噪结果。 + - Comfy dtype: INT + - Python dtype: int +- tiling_strategy + - tiling_strategy 参数决定了如何将图像划分为平铺。它是减少接缝效果和去噪图像整体质量的关键因素。 + - Comfy dtype: STRING + - Python dtype: str +- basic_pipe + - basic_pipe 参数封装了去噪过程所需的基本组件,包括模型和额外的设置。它对于执行去噪算法是不可或缺的。 + - Comfy dtype: BASIC_PIPE + - Python dtype: comfy_extras.nodes_upscale_model.BasicPipe + +# Output types +- KSAMPLER + - TiledKSamplerProvider 节点的输出是一个 KSampler 对象,它代表了配置好的去噪采样器。它对于后续需要去噪能力的图像处理任务很重要。 + - Comfy dtype: KSAMPLER + - Python dtype: KSamplerWrapper + +# Usage tips +- Infra type: GPU + +# Source code +``` +class TiledKSamplerProvider: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'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': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'tile_width': ('INT', {'default': 512, 'min': 320, 'max': MAX_RESOLUTION, 'step': 64}), 'tile_height': ('INT', {'default': 512, 'min': 320, 'max': MAX_RESOLUTION, 'step': 64}), 'tiling_strategy': (['random', 'padded', 'simple'],), 'basic_pipe': ('BASIC_PIPE',)}} + RETURN_TYPES = ('KSAMPLER',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Sampler' + + def doit(self, seed, steps, cfg, sampler_name, scheduler, denoise, tile_width, tile_height, tiling_strategy, basic_pipe): + (model, _, _, positive, negative) = basic_pipe + sampler = core.TiledKSamplerWrapper(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, tile_width, tile_height, tiling_strategy) + return (sampler,) +``` \ No newline at end of file diff --git a/docs/Time String (WLSH).md b/docs/Time String (WLSH).md new file mode 100644 index 0000000..40c3b0d --- /dev/null +++ b/docs/Time String (WLSH).md @@ -0,0 +1,45 @@ +# Documentation +- Class name: WLSH_Time_String +- Category: WLSH Nodes/text +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_Time_String节点旨在根据提供的时间格式生成一个时间戳字符串。它捕获当前的日期和时间,并根据指定的样式进行格式化,提供了一种以人类可读形式获取时间信息的多功能方式。 + +# Input types +## Required +- style + - ‘style’参数决定了输出时间戳字符串的格式。它至关重要,因为它决定了日期和时间的表示方式,影响生成的字符串的可读性和实用性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- time_format + - ‘time_format’参数代表了节点输出的格式化时间戳字符串。它很重要,因为它是节点操作的主要结果,以指定格式封装了当前的日期和时间。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WLSH_Time_String: + time_format = ['%Y%m%d%H%M%S', '%Y%m%d%H%M', '%Y%m%d', '%Y-%m-%d-%H%M%S', '%Y-%m-%d-%H%M', '%Y-%m-%d'] + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'style': (s.time_format,)}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('time_format',) + FUNCTION = 'get_time' + CATEGORY = 'WLSH Nodes/text' + + def get_time(self, style): + now = datetime.now() + timestamp = now.strftime(style) + return (timestamp,) +``` \ No newline at end of file diff --git a/docs/TimestepKeyframe.md b/docs/TimestepKeyframe.md new file mode 100644 index 0000000..05fe70e --- /dev/null +++ b/docs/TimestepKeyframe.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: TimestepKeyframeNode +- Category: Adv-ControlNet 🛂🅐🅒🅝/keyframes +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-Advanced-ControlNet.git + +TimestepKeyframeNode 是生成高级控制网络关键帧过程中的一个关键组件。它旨在根据指定的参数,如起始百分比和强度,促进关键帧的创建和操作。该节点在定义动画或模拟的时间结构中起着至关重要的作用,确保状态之间的过渡平滑且连贯。 + +# Input types +## Required +- start_percent + - start_percent 参数定义了关键帧在时间线中的初始位置,这对于确定动画中事件的顺序至关重要。它影响关键帧如何与其他元素交互,并有助于整体动画流程。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- strength + - strength 参数调整关键帧对整体动画的影响。它允许微调关键帧的影响,确保它以符合创意愿景的方式对动画做出贡献。 + - Comfy dtype: FLOAT + - Python dtype: float +- cn_weights + - cn_weights 参数指定要应用于控制网的权重,这对于形成动画对关键帧的响应行为至关重要。它是实现期望效果和结果的关键方面。 + - Comfy dtype: CONTROL_NET_WEIGHTS + - Python dtype: ControlWeights +- latent_keyframe + - latent_keyframe 参数提供了一种将潜在关键帧纳入动画的方法,为事件序列增加了深度和复杂性。它是创建复杂和详细动画的重要工具。 + - Comfy dtype: LATENT_KEYFRAME + - Python dtype: LatentKeyframeGroup + +# Output types +- TIMESTEP_KF + - TimestepKeyframeNode 的输出是 TimestepKeyframe,它代表了具有特定属性(如起始百分比和强度)的动画中的一个时刻。这个输出非常重要,因为它构成了动画后续处理和渲染的基础。 + - Comfy dtype: TIMESTEP_KEYFRAME + - Python dtype: TimestepKeyframe + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TimestepKeyframeNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001})}, 'optional': {'prev_timestep_kf': ('TIMESTEP_KEYFRAME',), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'cn_weights': ('CONTROL_NET_WEIGHTS',), 'latent_keyframe': ('LATENT_KEYFRAME',), 'null_latent_kf_strength': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), 'inherit_missing': ('BOOLEAN', {'default': True}), 'guarantee_usage': ('BOOLEAN', {'default': True}), 'mask_optional': ('MASK',)}} + RETURN_NAMES = ('TIMESTEP_KF',) + RETURN_TYPES = ('TIMESTEP_KEYFRAME',) + FUNCTION = 'load_keyframe' + CATEGORY = 'Adv-ControlNet 🛂🅐🅒🅝/keyframes' + + def load_keyframe(self, start_percent: float, strength: float=1.0, cn_weights: ControlWeights=None, control_net_weights: ControlWeights=None, latent_keyframe: LatentKeyframeGroup=None, prev_timestep_kf: TimestepKeyframeGroup=None, prev_timestep_keyframe: TimestepKeyframeGroup=None, null_latent_kf_strength: float=0.0, inherit_missing=True, guarantee_usage=True, mask_optional=None, interpolation: str=SI.NONE): + control_net_weights = control_net_weights if control_net_weights else cn_weights + prev_timestep_keyframe = prev_timestep_keyframe if prev_timestep_keyframe else prev_timestep_kf + if not prev_timestep_keyframe: + prev_timestep_keyframe = TimestepKeyframeGroup() + else: + prev_timestep_keyframe = prev_timestep_keyframe.clone() + keyframe = TimestepKeyframe(start_percent=start_percent, strength=strength, interpolation=interpolation, null_latent_kf_strength=null_latent_kf_strength, control_weights=control_net_weights, latent_keyframes=latent_keyframe, inherit_missing=inherit_missing, guarantee_usage=guarantee_usage, mask_hint_orig=mask_optional) + prev_timestep_keyframe.add(keyframe) + return (prev_timestep_keyframe,) +``` \ No newline at end of file diff --git a/docs/To Device (mtb).md b/docs/To Device (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ToBasicPipe.md b/docs/ToBasicPipe.md new file mode 100644 index 0000000..dd91c1a --- /dev/null +++ b/docs/ToBasicPipe.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: ToBasicPipe +- Category: ImpactPack/Pipe +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ToBasicPipe节点旨在简化模型操作的基本流水线的组装过程。它高效地将模型、clip、VAE和条件输入等各个组件结合成一个连贯的结构,便于执行后续任务。 + +# Input types +## Required +- model + - 模型参数对于节点的功能至关重要,因为它代表了用于处理输入数据的核心算法组件。它对于节点产生有意义的结果至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - clip参数在节点的操作中起着重要作用,它为模型的处理定义了视觉上下文。它是节点解释和操作视觉数据能力的一个不可分割的部分。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- vae + - VAE参数对于节点至关重要,因为它涉及变分自编码器组件,这对于生成或处理数据的潜在表示至关重要。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- positive + - 正参数对节点很重要,因为它提供了引导模型行为朝向期望结果的正向条件输入。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative + - 负参数对节点至关重要,因为它提供了帮助通过引导模型远离不希望的结果来细化模型输出的负向条件输入。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor + +# Output types +- basic_pipe + - basic_pipe输出是节点的主要结果,将组合的组件封装成单一的、连贯的流水线,准备进行进一步的处理或分析。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[torch.nn.Module, torch.Tensor, torch.nn.Module, torch.Tensor, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ToBasicPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'vae': ('VAE',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',)}} + RETURN_TYPES = ('BASIC_PIPE',) + RETURN_NAMES = ('basic_pipe',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Pipe' + + def doit(self, model, clip, vae, positive, negative): + pipe = (model, clip, vae, positive, negative) + return (pipe,) +``` \ No newline at end of file diff --git a/docs/ToBinaryMask.md b/docs/ToBinaryMask.md new file mode 100644 index 0000000..23aa783 --- /dev/null +++ b/docs/ToBinaryMask.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: ToBinaryMask +- Category: ImpactPack/Operation +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ToBinaryMask节点旨在通过将输入掩码转换为二进制格式来处理输入掩码。它通过将阈值应用于掩码值来实现这一点,从而将每个像素分类为背景或前景。此操作对于需要在图像中清晰区分不同区域的任务至关重要,例如在图像分割或目标检测中。 + +# Input types +## Required +- mask + - 掩码参数是ToBinaryMask节点的关键输入。它代表了将从中派生二进制掩码的初始掩码。这个掩码的质量和准确性直接影响节点的输出,决定了分割或目标检测任务的精度。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- threshold + - 阈值参数是一个可选输入,用于确定将掩码值转换为二进制格式的截止点。它在节点的操作中起着重要作用,通过控制二进制分类的敏感性来影响结果。较高的阈值会导致更保守的转换,而较低的阈值则会导致更激进的转换。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- binary_mask + - 二进制掩码输出是ToBinaryMask节点操作的结果。它是输入掩码的二进制表示,其中每个像素被分配0或1的值,表示感兴趣特征的存在或缺失。这个输出对于各种计算机视觉应用的进一步分析或处理至关重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ToBinaryMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'threshold': ('INT', {'default': 20, 'min': 1, 'max': 255})}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Operation' + + def doit(self, mask, threshold): + mask = to_binary_mask(mask, threshold / 255.0) + return (mask,) +``` \ No newline at end of file diff --git a/docs/ToDetailerPipe.md b/docs/ToDetailerPipe.md new file mode 100644 index 0000000..d48d97c --- /dev/null +++ b/docs/ToDetailerPipe.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: ToDetailerPipe +- Category: ImpactPack/Pipe +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ToDetailerPipe节点旨在将输入数据转换为更详细和结构化的格式。它通过整合各种组件,如模型、剪辑和检测器,来提炼和增强数据的细节级别。此节点在准备数据进行进一步分析或可视化方面发挥着关键作用,确保数据满足必要的质量和细节标准。 + +# Input types +## Required +- model + - 模型参数对于节点的操作至关重要,因为它定义了用于数据转换的主要算法框架。它直接影响节点处理和提炼输入数据的能力,确保输出满足预期的细节要求。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - 剪辑参数是数据转换过程中的一个关键组件,它通过提供上下文信息和约束来协助数据转换。它确保转换遵循特定指南,从而维护输出数据的完整性和一致性。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- vae + - VAE(变分自编码器)是节点架构中的一个重要元素,负责将数据编码和解码为潜在空间表示。它在细节增强过程中起着重要作用,使节点能够从输入数据生成详细且丰富的输出。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- positive + - 正面参数作为节点操作的指导,提供了正面的示例或条件,输出应遵循这些条件。这对于确保节点的输出与期望的质量和细节标准一致至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: List[str] +- negative + - 负面参数通过提供输出应避免的示例或条件,补充了正面参数。它对于引导节点生成符合所需标准且不包含不需要的特征的输出非常重要。 + - Comfy dtype: CONDITIONING + - Python dtype: List[str] +- bbox_detector + - bbox_detector参数对于识别和定位输入数据中的兴趣区域至关重要。它有助于节点专注于特定区域,增强输出的细节和精度。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: Callable +- wildcard + - 通配符参数允许动态和灵活的数据处理,使节点能够适应各种输入场景。它对于确保节点能够处理各种数据类型和格式非常重要,从而提高了其多功能性和实用性。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- Select to add LoRA + - LoRA选择参数提供了将特定低秩适应(Low-Rank Adaptations)纳入节点处理流程的灵活性。这可以通过允许节点根据特定用例或需求调整其操作来增强节点的功能。 + - Comfy dtype: COMBO['Select the LoRA to add to the text', folder_paths.get_filename_list('loras')] + - Python dtype: Union[str, None] +- Select to add Wildcard + - 额外的通配符参数提供了在节点操作中包含更多动态元素的选项。它可以用来引入可变性,并根据不同的数据输入或处理需求调整节点的行为。 + - Comfy dtype: COMBO['Select the Wildcard to add to the text'] + - Python dtype: Union[str, None] + +# Output types +- detailer_pipe + - detailer_pipe输出代表了节点处理的成果,包含了详细和精炼的数据。它标志着节点成功执行,并为下游应用提供了一个结构化的格式。 + - Comfy dtype: DETAILER_PIPE + - Python dtype: Tuple[Any, ...] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ToDetailerPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'vae': ('VAE',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'bbox_detector': ('BBOX_DETECTOR',), 'wildcard': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'Select to add LoRA': (['Select the LoRA to add to the text'] + folder_paths.get_filename_list('loras'),), 'Select to add Wildcard': (['Select the Wildcard to add to the text'],)}, 'optional': {'sam_model_opt': ('SAM_MODEL',), 'segm_detector_opt': ('SEGM_DETECTOR',), 'detailer_hook': ('DETAILER_HOOK',)}} + RETURN_TYPES = ('DETAILER_PIPE',) + RETURN_NAMES = ('detailer_pipe',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Pipe' + + def doit(self, *args, **kwargs): + pipe = (kwargs['model'], kwargs['clip'], kwargs['vae'], kwargs['positive'], kwargs['negative'], kwargs['wildcard'], kwargs['bbox_detector'], kwargs.get('segm_detector_opt', None), kwargs.get('sam_model_opt', None), kwargs.get('detailer_hook', None), kwargs.get('refiner_model', None), kwargs.get('refiner_clip', None), kwargs.get('refiner_positive', None), kwargs.get('refiner_negative', None)) + return (pipe,) +``` \ No newline at end of file diff --git a/docs/ToDetailerPipeSDXL.md b/docs/ToDetailerPipeSDXL.md new file mode 100644 index 0000000..7d8e314 --- /dev/null +++ b/docs/ToDetailerPipeSDXL.md @@ -0,0 +1,81 @@ +# Documentation +- Class name: ToDetailerPipeSDXL +- Category: Image Processing +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +ToDetailerPipeSDXL 节点是图像处理流水线中的一个中间环节,专门设计用于增强图像的细节水平。它通过利用先进的模型和技术来细化输入图像的视觉元素来实现这一点。该节点的主要目标是提高图像的清晰度和锐度,使其更适合于详细分析或展示。 + +# Input types +## Required +- model + - 模型参数对于节点的操作至关重要,因为它定义了节点用于处理图像的核心算法框架。它直接影响图像细化的质量和结果。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - clip 参数对于提供节点增强图像细节所需的上下文信息至关重要。它在确保输出图像的上下文相关性方面起着重要作用。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- vae + - vae 参数代表变分自编码器,节点使用它从输入数据生成详细的图像。这是节点能够产生高质量详细图像的关键组件。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- positive + - positive 参数作为节点的指导,用于集中增强图像中的特定特征。它对于将节点的细化工作引向所需的视觉方面很重要。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- negative + - negative 参数有助于节点避免增强图像中不需要的特征。它在确保节点的细化过程符合用户的期望方面至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- refiner_model + - refiner_model 参数指定了一个用于进一步细化节点生成的详细图像的附加模型。这对于在最终输出中实现更高级别的细节至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- refiner_clip + - refiner_clip 参数为 refiner 模型提供额外的上下文信息,以便更好地细化图像。它确保细化过程具有上下文意识并且准确。 + - Comfy dtype: CLIP + - Python dtype: torch.Tensor +- refiner_positive + - refiner_positive 参数指导 refiner 模型在细化过程中集中增强所需的特征。这对于在最终图像中实现预期的细节水平至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- refiner_negative + - refiner_negative 参数有助于 refiner 模型避免在图像中细化不需要的特征。它确保最终图像满足用户的要求,没有不需要的细节。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- bbox_detector + - bbox_detector 参数用于识别和定位图像内的兴趣区域。它对于节点知道在哪里集中其细化工作很重要。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: Callable +- wildcard + - wildcard 参数允许动态输入文本,可以根据用户定义的条件定制节点的行为。它在节点处理图像的方式上提供了灵活性。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- Select to add LoRA + - 选择添加 LoRA 参数使用户能够选择特定的低秩适应技术,以增强模型生成详细图像的性能。 + - Comfy dtype: COMBO['Select the LoRA to add to the text', folder_paths.get_filename_list('loras')] + - Python dtype: str +- Select to add Wildcard + - 选择添加 Wildcard 参数为用户提供了一个选项,可以在其输入中包含一个通配符,这可以用来引入节点处理中的可变性。 + - Comfy dtype: COMBO['Select the Wildcard to add to the text'] + - Python dtype: str + +# Output types +- detailed_image + - detailed_image 输出参数代表节点操作的最终产品,即具有增强细节的图像。它是节点所有处理和细化工作的成果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ToDetailerPipeSDXL(ToDetailerPipe): + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'vae': ('VAE',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'refiner_model': ('MODEL',), 'refiner_clip': ('CLIP',), 'refiner_positive': ('CONDITIONING',), 'refiner_negative': ('CONDITIONING',), 'bbox_detector': ('BBOX_DETECTOR',), 'wildcard': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'Select to add LoRA': (['Select the LoRA to add to the text'] + folder_paths.get_filename_list('loras'),), 'Select to add Wildcard': (['Select the Wildcard to add to the text'],)}, 'optional': {'sam_model_opt': ('SAM_MODEL',), 'segm_detector_opt': ('SEGM_DETECTOR',), 'detailer_hook': ('DETAILER_HOOK',)}} +``` \ No newline at end of file diff --git a/docs/ToIPAdapterPipe %2F%2FInspire.md b/docs/ToIPAdapterPipe %2F%2FInspire.md new file mode 100644 index 0000000..f569e77 --- /dev/null +++ b/docs/ToIPAdapterPipe %2F%2FInspire.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: ToIPAdapterPipe +- Category: InspirePack/Util +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +ToIPAdapterPipe 是一个旨在促进各种图像处理模型和适配器集成的节点。它通过管道编排数据流,确保图像在传递到下一阶段之前由指定的模型适当处理。该节点旨在简化图像处理工作流程,提高效率,并允许在统一的管道中无缝使用不同的模型。 + +# Input types +## Required +- ipadapter + - ipadapter 参数对于节点的操作至关重要,因为它定义了用于图像预处理的特定适配器。它在确保输入图像正确格式化并准备好由管道中的后续模型处理中起着关键作用。 + - Comfy dtype: IPADAPTER + - Python dtype: torch.nn.Module +- model + - model 输入是必不可少的,因为它代表了节点将使用的图像处理核心模型。它是执行所需图像转换的主要组件,对节点的功能至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip_vision + - clip_vision 参数是可选的,但可以用来将额外的基于视觉的处理能力集成到管道中。它扩展了节点的功能,允许进行更复杂和多样化的图像分析任务。 + - Comfy dtype: CLIP_VISION + - Python dtype: torch.nn.Module +- insightface + - 当提供 insightface 参数时,可以使节点在其处理管道中包含面部识别功能。这对于需要通过面部特征识别或验证个人的应用尤其有用。 + - Comfy dtype: INSIGHTFACE + - Python dtype: torch.nn.Module + +# Output types +- IPADAPTER_PIPE + - IPADAPTER_PIPE 输出封装了数据在通过节点管道后的处理结果。它代表了图像处理任务的完成,并已准备好用于进一步使用或分析。 + - Comfy dtype: IPADAPTER_PIPE + - Python dtype: Tuple[torch.nn.Module, torch.nn.Module, torch.nn.Module, Optional[torch.nn.Module], Callable] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ToIPAdapterPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ipadapter': ('IPADAPTER',), 'model': ('MODEL',)}, 'optional': {'clip_vision': ('CLIP_VISION',), 'insightface': ('INSIGHTFACE',)}} + RETURN_TYPES = ('IPADAPTER_PIPE',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Util' + + def doit(self, ipadapter, model, clip_vision, insightface=None): + pipe = (ipadapter, model, clip_vision, insightface, lambda x: x) + return (pipe,) +``` \ No newline at end of file diff --git a/docs/TonemapNoiseWithRescaleCFG.md b/docs/TonemapNoiseWithRescaleCFG.md new file mode 100644 index 0000000..d261fb0 --- /dev/null +++ b/docs/TonemapNoiseWithRescaleCFG.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: TonemapNoiseWithRescaleCFG +- Category: custom_node_experiments +- Output node: False +- Repo Ref: https://github.com/comfyanonymous/ComfyUI_experiments + +TonemapNoiseWithRescaleCFG节点旨在通过应用色调映射技术结合降噪策略来增强生成图像的视觉质量。它通过复杂的重新缩放操作调整图像的对比度和亮度,以优化其外观并减少噪声。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它代表了节点将操作的生成模型。它是应用色调映射和重新缩放操作以生成高质量图像的基础。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +## Optional +- tonemap_multiplier + - tonemap_multiplier参数控制应用于图像的色调映射效果的强度。它对于微调视觉结果以实现所需的对比度和亮度水平至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- rescale_multiplier + - rescale_multiplier参数在降噪过程中决定了重新缩放和原始图像值之间的平衡。它在保持图像细节的同时减少噪声方面起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- model + - 输出模型是修改后的生成模型,它具有增强的采样器配置函数,该函数结合了色调映射和降噪技术,以产生视觉吸引力更强的图像。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class TonemapNoiseWithRescaleCFG: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'tonemap_multiplier': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 100.0, 'step': 0.01}), 'rescale_multiplier': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'patch' + CATEGORY = 'custom_node_experiments' + + def patch(self, model, tonemap_multiplier, rescale_multiplier): + + def tonemap_noise_rescale_cfg(args): + cond = args['cond'] + uncond = args['uncond'] + cond_scale = args['cond_scale'] + noise_pred = cond - uncond + noise_pred_vector_magnitude = (torch.linalg.vector_norm(noise_pred, dim=1) + 1e-10)[:, None] + noise_pred /= noise_pred_vector_magnitude + mean = torch.mean(noise_pred_vector_magnitude, dim=(1, 2, 3), keepdim=True) + std = torch.std(noise_pred_vector_magnitude, dim=(1, 2, 3), keepdim=True) + top = (std * 3 + mean) * tonemap_multiplier + noise_pred_vector_magnitude *= 1.0 / top + new_magnitude = noise_pred_vector_magnitude / (noise_pred_vector_magnitude + 1.0) + new_magnitude *= top + x_cfg = uncond + noise_pred * new_magnitude * cond_scale + ro_pos = torch.std(cond, dim=(1, 2, 3), keepdim=True) + ro_cfg = torch.std(x_cfg, dim=(1, 2, 3), keepdim=True) + x_rescaled = x_cfg * (ro_pos / ro_cfg) + x_final = rescale_multiplier * x_rescaled + (1.0 - rescale_multiplier) * x_cfg + return x_final + m = model.clone() + m.set_model_sampler_cfg_function(tonemap_noise_rescale_cfg) + return (m,) +``` \ No newline at end of file diff --git a/docs/Transform Image (mtb).md b/docs/Transform Image (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/TransitionBetween2Image.md b/docs/TransitionBetween2Image.md new file mode 100644 index 0000000..d914c28 --- /dev/null +++ b/docs/TransitionBetween2Image.md @@ -0,0 +1,95 @@ +# Documentation +- Class name: TransitionBetween2Image +- Category: AIGC +- Output node: False +- Repo Ref: https://github.com/esheep/esheep_custom_nodes.git + +TransitionBetween2Image节点用于生成两个图像之间的平滑过渡。它使用贝塞尔曲线进行插值,生成一系列将一个图像变形为另一个图像的帧。该节点特别适用于需要从一个状态逐渐变化到另一个状态的视觉效果中,例如动画或视频处理。 + +# Input types +## Required +- image_start + - 要过渡的起始图像。它为动画序列设置了初始视觉状态。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or numpy.ndarray +- image_end + - 过渡将变形为的结束图像。它代表序列的最终视觉状态。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or numpy.ndarray +- total_frames + - 要为过渡生成的总帧数。增加此数字可以使过渡更平滑,但需要更多的处理时间。 + - Comfy dtype: INT + - Python dtype: int +- begin_and_end_frames + - 在过渡的开始和结束处复制的帧数,以提供暂停效果。 + - Comfy dtype: INT + - Python dtype: int +- beiser_point_x + - 定义过渡形状的贝塞尔曲线上的控制点的x坐标。 + - Comfy dtype: FLOAT + - Python dtype: float +- beiser_point_y + - 定义过渡形状的贝塞尔曲线上的控制点的y坐标。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- IMAGE + - 由过渡生成的帧序列,可以用于进一步处理或显示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TransitionBetween2Image: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image_start': ('IMAGE',), 'image_end': ('IMAGE',), 'total_frames': ('INT', {'default': 40, 'min': 1}), 'begin_and_end_frames': ('INT', {'default': 10, 'min': 0}), 'beiser_point_x': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'beiser_point_y': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.05})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'get_transition_frames' + CATEGORY = 'AIGC' + + def get_transition_frames(self, image_start, image_end, total_frames, begin_and_end_frames, beiser_point_x, beiser_point_y): + origin_image = image_start[0] + outpating_image = image_end[0] + frames = [] + origin_width = origin_image.shape[1] + origin_height = origin_image.shape[0] + new_width = outpating_image.shape[1] + new_height = outpating_image.shape[0] + if new_height / new_width > origin_height / origin_width: + origin_height = new_height / new_width * origin_width + else: + origin_width = new_width / new_height * origin_height + print(f'image rect = {origin_width} {origin_height} {new_width} {new_height}') + white_origin_left = int((new_width - origin_width) / 2) + white_origin_top = int((new_height - origin_height) / 2) + a = np.array([[0.0, beiser_point_x, 1.0], [0.0, beiser_point_y, 1.0]]) + curve = bezier.Curve(a, degree=2) + s_vals = np.linspace(0.0, 1.0, total_frames) + data = curve.evaluate_multi(s_vals) + print(f' curve data = {data}') + for a in range(total_frames): + i = data[1][a] + current_left = int(white_origin_left * (1 - i)) + current_top = int(white_origin_top * (1 - i)) + current_width = int(origin_width + white_origin_left * i * 2) + current_height = int(origin_height + white_origin_top * i * 2) + print(f'a = {a} i = {i} current rect = {current_left} {current_top} {current_width} {current_height}') + current_img = outpating_image[current_top:current_top + current_height, current_left:current_left + current_width] + current_img = current_img.numpy().astype(np.float32) + img = cv2.resize(current_img, (new_width, new_height)) + frames.append(img) + if a == 0: + for j in range(begin_and_end_frames): + frames.append(img) + elif a == total_frames - 1: + for j in range(begin_and_end_frames): + frames.append(img) + return_array = torch.Tensor(np.asarray(frames)) + return (return_array,) +``` \ No newline at end of file diff --git a/docs/TransitionFromSize.md b/docs/TransitionFromSize.md new file mode 100644 index 0000000..e36d328 --- /dev/null +++ b/docs/TransitionFromSize.md @@ -0,0 +1,99 @@ +# Documentation +- Class name: TransitionFromSize +- Category: AIGC +- Output node: False +- Repo Ref: https://github.com/esheep/esheep_custom_nodes.git + +TransitionFromSize节点旨在生成一系列图像,这些图像描绘了一个平滑的从一个图像大小过渡到另一个图像大小的过程。它使用贝塞尔曲线来控制变形过程,确保视觉上吸引人的转变。该节点的功能集中在创建动态视觉内容,这些内容可以用于动画或视觉效果等各种应用中。 + +# Input types +## Required +- image + - 图像参数是将生成过渡序列的源图像。这是一个关键输入,因为它定义了过渡的内容和起点。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image or numpy.ndarray +- from_image_width + - from_image_width参数指定过渡开始时图像的初始宽度。它在确定变形的起始尺寸中起着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- from_image_height + - from_image_height参数定义了图像的初始高度。它对于建立过渡序列中起始帧的垂直尺寸至关重要。 + - Comfy dtype: INT + - Python dtype: int +- total_frames + - total_frames参数规定过渡序列中的总帧数。它影响变形过程的持续时间和细节水平。 + - Comfy dtype: INT + - Python dtype: int +- begin_and_end_frames + - begin_and_end_frames参数确定在过渡开始和结束时添加的重复帧数。这可以用来创建一个更渐进的开始和结束序列。 + - Comfy dtype: INT + - Python dtype: int +- beiser_point_x + - beiser_point_x参数是贝塞尔曲线上的一个控制点,它影响过渡的水平方面。它是形成变形路径曲率的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- beiser_point_y + - beiser_point_y参数是贝塞尔曲线上的一个控制点,它影响过渡的垂直方面。它对于定义变形路径的垂直曲率至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- IMAGE + - TransitionFromSize节点的输出是一系列图像,代表从原始大小到新大小的过渡。序列中的每个帧都是由贝塞尔曲线控制的变形过程的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TransitionFromSize: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'from_image_width': ('INT', {'min': 1}), 'from_image_height': ('INT', {'min': 1}), 'total_frames': ('INT', {'default': 40, 'min': 1}), 'begin_and_end_frames': ('INT', {'default': 10, 'min': 0}), 'beiser_point_x': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.05}), 'beiser_point_y': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.05})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'get_transition_from_size' + CATEGORY = 'AIGC' + + def get_transition_from_size(self, image, from_image_width, from_image_height, total_frames, begin_and_end_frames, beiser_point_x, beiser_point_y): + outpating_image = image[0] + frames = [] + origin_width = from_image_width + origin_height = from_image_height + new_width = outpating_image.shape[1] + new_height = outpating_image.shape[0] + if (origin_width > new_width) | (origin_height > new_height): + origin_width = new_width * 0.75 + origin_height = new_height * 0.75 + white_origin_left = (new_width - origin_width) / 2 + white_origin_top = (new_height - origin_height) / 2 + print(f'image rect origin_width = {origin_width} origin_height = {origin_height} new_width = {new_width} new_height = {new_height}image white_origin_left = {white_origin_left} white_origin_top = {white_origin_top}') + a = np.array([[0.0, beiser_point_x, 1.0], [0.0, beiser_point_y, 1.0]]) + curve = bezier.Curve(a, degree=2) + s_vals = np.linspace(0.0, 1.0, total_frames) + data = curve.evaluate_multi(s_vals) + print(f' curve data = {data}') + for a in range(total_frames): + i = data[1][a] + current_left = white_origin_left * (1 - i) + current_top = white_origin_top * (1 - i) + current_width = origin_width + 2 * i * white_origin_left + current_height = origin_height + 2 * i * white_origin_top + current_right = int(current_left + current_width) + current_bottom = int(current_top + current_height) + print(f'a = {a} i = {i} current rect left = {current_left} width = {current_width} top = {current_top} height = {current_height}') + current_img = outpating_image[int(current_top):current_bottom, int(current_left):current_right] + current_img = current_img.numpy().astype(np.float32) + img = cv2.resize(current_img, (new_width, new_height)) + frames.append(img) + if a == 0: + for j in range(begin_and_end_frames): + frames.append(img) + elif a == total_frames - 1: + for j in range(begin_and_end_frames): + frames.append(img) + return_array = torch.Tensor(np.asarray(frames)) + return (return_array,) +``` \ No newline at end of file diff --git a/docs/TransitionMask+.md b/docs/TransitionMask+.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/TranslateCLIPTextEncode.md b/docs/TranslateCLIPTextEncode.md new file mode 100644 index 0000000..9c5b63b --- /dev/null +++ b/docs/TranslateCLIPTextEncode.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: TranslateCLIPTextEncode +- Category: translate +- Output node: False +- Repo Ref: https://github.com/esheep/esheep_custom_nodes.git + +TranslateCLIPTextEncode节点充当将文本数据编码为机器学习模型(特别是使用CLIP框架的模型)可以理解的格式的中介。它通过将输入文本翻译成适合模型的语言,然后对翻译后的文本进行标记化来实现这一点。该节点的主要功能是为AI模型的后续处理准备数据,强调了语言翻译和模型编码的无缝集成。 + +# Input types +## Required +- text + - ‘text’参数是节点将处理的原始文本输入。它至关重要,因为它是将被编码供模型使用的源信息。节点依赖此输入执行其翻译和编码任务,使其成为节点操作中的基本组成部分。 + - Comfy dtype: STRING + - Python dtype: str +- clip + - ‘clip’参数代表节点将用于标记化和编码的CLIP模型或其接口。它是一个重要组件,因为它直接影响节点将文本转换为适合机器学习应用格式的能力。 + - Comfy dtype: CLIP + - Python dtype: Any +- app_id + - ‘app_id’参数是在使用外部翻译服务时用于认证的标识符。虽然不是必需的,但它对于访问某些服务和确保翻译过程的完整性和安全性很重要。 + - Comfy dtype: STRING + - Python dtype: str +- app_key + - ‘app_key’参数作为与‘app_id’一起用于认证的秘密密钥。它不是强制性的,但在确保安全访问翻译服务方面扮演着重要角色。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- CONDITIONING + - ‘CONDITIONING’输出是编码文本数据的结构化表示,包括CLIP模型的条件向量和池化输出。这个输出很重要,因为它提供了准备好用于下游机器学习任务的加工信息。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[str, Dict[str, Any]}} + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TranslateCLIPTextEncode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True}), 'clip': ('CLIP',)}, 'hidden': {'app_id': ('STRING', {}), 'app_key': ('STRING', {})}} + RETURN_TYPES = ('CONDITIONING',) + FUNCTION = 'encode' + CATEGORY = 'translate' + + def encode(self, clip, text, app_id='', app_key=''): + tokens = clip.tokenize(translate(text, Credentials(app_id=app_id, app_key=app_key))) + (cond, pooled) = clip.encode_from_tokens(tokens, return_pooled=True) + return ([[cond, {'pooled_output': pooled}]],) +``` \ No newline at end of file diff --git a/docs/TranslateNode.md b/docs/TranslateNode.md new file mode 100644 index 0000000..d4dc4a7 --- /dev/null +++ b/docs/TranslateNode.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: TranslateNode +- Category: translate +- Output node: True +- Repo Ref: https://github.com/esheep/esheep_custom_nodes.git + +该节点能够将文本从一种语言翻译成另一种语言,利用外部翻译服务。它旨在处理文本数据并将其转换为所需语言,实现多语言交流和内容理解。节点的主要功能是架设语言沟通的桥梁,增强信息的可访问性和覆盖范围。 + +# Input types +## Required +- text + - 文本参数是必需的,因为它是需要翻译的源内容。它是翻译过程的输入,直接影响输出的相关性和准确性。没有这个参数,节点无法执行其预期功能。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- app_id + - app_id参数虽然不是必需的,但对于向翻译服务验证请求至关重要。它确保节点能够访问必要的资源并在允许的限制内执行翻译。 + - Comfy dtype: STRING + - Python dtype: str +- app_key + - 与app_id类似,app_key是另一个必要的认证凭据,对节点的正确功能至关重要。它在确保连接安全和翻译请求被授权方面发挥作用。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- result + - 结果参数代表翻译后的文本,是节点的主要输出。它直接反映了翻译过程的有效性,对于实现节点的目的至关重要。 + - Comfy dtype: COMBO[STRING] + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TranslateNode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True})}, 'hidden': {'app_id': ('STRING', {}), 'app_key': ('STRING', {})}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'main' + CATEGORY = 'translate' + OUTPUT_IS_LIST = (True,) + OUTPUT_NODE = True + + def main(self, text, app_id='', app_key=''): + result = translate(text, Credentials(app_id=app_id, app_key=app_key)) + return {'ui': {'result': [result]}, 'result': ([result],)} +``` \ No newline at end of file diff --git a/docs/TransparentImage.md b/docs/TransparentImage.md new file mode 100644 index 0000000..0429beb --- /dev/null +++ b/docs/TransparentImage.md @@ -0,0 +1,89 @@ +# Documentation +- Class name: TransparentImage +- Category: ♾️Mixlab/Image +- Output node: True +- Repo Ref: https://github.com/shadowcz007/comfyui-mixlab-nodes.git + +TransparentImage节点旨在处理和操作具有透明度的图像,提供创建和管理带有遮罩的图像的功能。它能够进行颜色反转、保存处理后的图像以及处理各种图像格式。该节点在增强视觉内容方面发挥着关键作用,通过将遮罩应用于图像,允许实现创新的视觉效果和修改。 + +# Input types +## Required +- images + - ‘images’参数对于节点的操作至关重要,因为它是将被处理的输入图像。这是一个关键元素,直接影响节点的输出,决定了将被转换和操作的视觉内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- masks + - ‘masks’参数定义了将应用于输入图像的遮罩。它是节点功能的必要组成部分,因为它决定了图像中将受到遮罩处理影响的区域。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- invert + - ‘invert’参数允许在处理后的图像中反转颜色。这是一个可选功能,可以显著改变视觉结果,提供了一种在图像内部创建对比效果的手段。 + - Comfy dtype: COMBO['yes', 'no'] + - Python dtype: str +- save + - ‘save’参数决定处理后的图像是否会被保存到磁盘。这是节点的一个关键决策点,因为它影响对图像所做的视觉更改的持久性。 + - Comfy dtype: COMBO['yes', 'no'] + - Python dtype: str +- filename_prefix + - ‘filename_prefix’参数用于指定保存的图像文件的前缀。它提供了一种更有效地组织和识别输出文件的方法,增强了保存的视觉内容的可管理性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- file_path + - ‘file_path’输出提供了保存的图像文件的路径。它很重要,因为它许用户定位和访问处理后的图像,以供进一步使用或分发。 + - Comfy dtype: STRING + - Python dtype: str +- IMAGE + - ‘IMAGE’输出代表了以RGB格式处理后的图像。它是节点操作的直接结果,对于可视化对输入图像所做的修改至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- RGBA + - ‘RGBA’输出包含了带有透明度信息的处理后的图像。对于需要保留原始图像的alpha通道以进行进一步编辑或合成的应用来说,这是一个重要方面。 + - Comfy dtype: RGBA + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TransparentImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'masks': ('MASK',), 'invert': (['yes', 'no'],), 'save': (['yes', 'no'],)}, 'optional': {'filename_prefix': ('STRING', {'multiline': False, 'default': 'Mixlab_save'})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = ('STRING', 'IMAGE', 'RGBA') + RETURN_NAMES = ('file_path', 'IMAGE', 'RGBA') + OUTPUT_NODE = True + FUNCTION = 'run' + CATEGORY = '♾️Mixlab/Image' + OUTPUT_IS_LIST = (True, True, True) + + def run(self, images, masks, invert, save, filename_prefix, prompt=None, extra_pnginfo=None): + ui_images = [] + image_paths = [] + count = images.shape[0] + masks_new = [] + nh = masks.shape[0] // count + masks_new = masks + if images.shape[0] == masks.shape[0] and images.shape[1] == masks.shape[1] and (images.shape[2] == masks.shape[2]): + print('TransparentImage', images.shape, images.size(), masks.shape, masks.size()) + elif nh * count == masks.shape[0]: + masks_new = split_mask_by_new_height(masks, nh) + else: + masks_new = split_mask_by_new_height(masks, masks.shape[0]) + is_save = True if save == 'yes' else False + images_rgb = [] + images_rgba = [] + for i in range(len(images)): + image = images[i] + mask = masks_new[i] + result = doMask(image, mask, is_save, filename_prefix, invert, not is_save, prompt, extra_pnginfo) + for item in result['result']: + ui_images.append(item) + image_paths.append(result['image_path']) + images_rgb.append(result['im_tensor']) + images_rgba.append(result['im_rgba_tensor']) + return {'ui': {'images': ui_images, 'image_paths': image_paths}, 'result': (image_paths, images_rgb, images_rgba)} +``` \ No newline at end of file diff --git a/docs/TriangleWave.md b/docs/TriangleWave.md new file mode 100644 index 0000000..a46fbc0 --- /dev/null +++ b/docs/TriangleWave.md @@ -0,0 +1,60 @@ +# Documentation +- Class name: TriangleWave +- Category: FizzNodes 📅🅕🅝/WaveNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +TriangleWave节点旨在生成类似三角形的波形。它通过调整正弦波的幅度和相位来创建一个独特的三角形图案,这对于各种信号处理应用非常有用。 + +# Input types +## Required +- phase + - 相位参数决定了波形的周期时长,影响节点生成的三角波的频率。 + - Comfy dtype: FLOAT + - Python dtype: float +- amplitude + - 幅度设置三角波的峰值,这是定义信号整体形状和能量的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- x_translation + - X平移沿X轴移动波形,允许对波形的水平位置进行调整。 + - Comfy dtype: FLOAT + - Python dtype: float +- y_translation + - Y平移沿Y轴移动波形,影响波形起始点的垂直位置。 + - Comfy dtype: FLOAT + - Python dtype: float +- current_frame + - 当前帧参数指定波形序列中的当前位置,这对于信号的时间演变至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- output + - 输出参数代表给定帧的三角波的计算值,这是节点操作的核心结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- int_output + - 整数输出是将波值转换为整数的版本,这对于需要离散值的某些应用非常有用。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TriangleWave: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'phase': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'amplitude': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.1}), 'x_translation': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0}), 'y_translation': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 9999.0, 'step': 0.05}), 'current_frame': ('INT', {'default': 1.0, 'min': 0.0, 'max': 9999.0, 'step': 1.0})}} + RETURN_TYPES = ('FLOAT', 'INT') + FUNCTION = 'Wave' + CATEGORY = 'FizzNodes 📅🅕🅝/WaveNodes' + + def Wave(self, phase, amplitude, x_translation, y_translation, current_frame): + output = y_translation + amplitude / np.pi * np.arcsin(np.sin(2 * np.pi / phase * current_frame - x_translation)) + print(output) + return (output, int(output)) +``` \ No newline at end of file diff --git a/docs/TripoSRModelLoader.md b/docs/TripoSRModelLoader.md new file mode 100644 index 0000000..8f2c055 --- /dev/null +++ b/docs/TripoSRModelLoader.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: TripoSRModelLoader +- Category: Flowty TripoSR +- Output node: False +- Repo Ref: https://github.com/flowtyone/ComfyUI-Flowty-TripoSR + +TripoSRModelLoader旨在高效管理和初始化TripoSR模型,确保其按指定配置和资源正确加载。它抽象了模型加载和设置的复杂性,为用户提供了一个直接的接口来访问模型的功能。 + +# Input types +## Required +- model + - ‘model’参数对于指定模型检查点的路径至关重要。它直接影响TripoSR模型的初始化,并且对节点的操作至关重要,因为它决定了将使用哪些权重和配置。 + - Comfy dtype: COMBO[str] + - Python dtype: str +## Optional +- chunk_size + - ‘chunk_size’参数通过控制批处理大小来优化模型的内存使用。它在平衡性能和资源消耗方面发挥着重要作用,允许高效处理大规模数据。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- TRIPOSR_MODEL + - 输出提供了初始化并准备使用的TripoSR模型。它封装了模型的整个功能,允许用户利用其功能进行各种超分辨率任务。 + - Comfy dtype: COMBO[torch.nn.Module] + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class TripoSRModelLoader: + + def __init__(self): + self.initialized_model = None + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': (get_filename_list('checkpoints'),), 'chunk_size': ('INT', {'default': 8192, 'min': 1, 'max': 10000})}} + RETURN_TYPES = ('TRIPOSR_MODEL',) + FUNCTION = 'load' + CATEGORY = 'Flowty TripoSR' + + def load(self, model, chunk_size): + device = get_torch_device() + if not torch.cuda.is_available(): + device = 'cpu' + if not self.initialized_model: + print('Loading TripoSR model') + self.initialized_model = TSR.from_pretrained_custom(weight_path=get_full_path('checkpoints', model), config_path=path.join(path.dirname(__file__), 'config.yaml')) + self.initialized_model.renderer.set_chunk_size(chunk_size) + self.initialized_model.to(device) + return (self.initialized_model,) +``` \ No newline at end of file diff --git a/docs/TripoSRSampler.md b/docs/TripoSRSampler.md new file mode 100644 index 0000000..015cde4 --- /dev/null +++ b/docs/TripoSRSampler.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: TripoSRSampler +- Category: Flowty TripoSR +- Output node: False +- Repo Ref: https://github.com/flowtyone/ComfyUI-Flowty-TripoSR + +TripoSRSampler类通过利用深度学习模型的能力来解释场景代码和提取几何细节,从而促进了从2D图像生成3D网格的过程。它将视觉数据转换为结构化表示,使得在计算机视觉和图形渲染等各个领域中的应用成为可能。 + +# Input types +## Required +- model + - 模型参数对于TripoSRSampler至关重要,它包含了使2D图像转换为3D网格的训练有素的神经网络。它是整个过程的主干,决定了最终输出的质量和准确性。 + - Comfy dtype: TRIPOSR_MODEL + - Python dtype: torch.nn.Module +- reference_image + - 参考图像是3D网格生成过程的主要输入。对于模型来说,它对于解释和提取创建场景准确表示所需的必要几何信息至关重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- geometry_resolution + - 几何分辨率是一个关键参数,它影响生成的3D网格的细节水平。更高的分辨率会产生更复杂和细粒度的输出,这对于需要高精度的应用来说至关重要。 + - Comfy dtype: INT + - Python dtype: int +- threshold + - 阈值参数在确定提取的3D结构的对比度和清晰度方面起着重要作用。它影响模型如何在场景中区分不同元素,影响最终的视觉结果。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- reference_mask + - 参考掩码在提供时,通过指定图像中的兴趣区域,有助于完善3D网格生成。它帮助模型专注于场景的相关部分,提高了输出的准确性。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- mesh + - 输出网格是3D采样过程的有形成果,代表了输入图像到几何结构的转换。它是进一步分析、可视化和在各个领中应用的关键组成部分。 + - Comfy dtype: MESH + - Python dtype: trimesh.Trimesh + +# Usage tips +- Infra type: GPU + +# Source code +``` +class TripoSRSampler: + + def __init__(self): + self.initialized_model = None + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('TRIPOSR_MODEL',), 'reference_image': ('IMAGE',), 'geometry_resolution': ('INT', {'default': 256, 'min': 128, 'max': 12288}), 'threshold': ('FLOAT', {'default': 25.0, 'min': 0.0, 'step': 0.01})}, 'optional': {'reference_mask': ('MASK',)}} + RETURN_TYPES = ('MESH',) + FUNCTION = 'sample' + CATEGORY = 'Flowty TripoSR' + + def sample(self, model, reference_image, geometry_resolution, threshold, reference_mask=None): + device = get_torch_device() + if not torch.cuda.is_available(): + device = 'cpu' + image = reference_image[0] + if reference_mask is not None: + mask = reference_mask[0].unsqueeze(2) + image = torch.cat((image, mask), dim=2).detach().cpu().numpy() + else: + image = image.detach().cpu().numpy() + image = Image.fromarray(np.clip(255.0 * image, 0, 255).astype(np.uint8)) + if reference_mask is not None: + image = fill_background(image) + image = image.convert('RGB') + scene_codes = model([image], device) + meshes = model.extract_mesh(scene_codes, resolution=geometry_resolution, threshold=threshold) + return ([meshes[0]],) +``` \ No newline at end of file diff --git a/docs/TripoSRViewer.md b/docs/TripoSRViewer.md new file mode 100644 index 0000000..487b291 --- /dev/null +++ b/docs/TripoSRViewer.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: TripoSRViewer +- Category: Flowty TripoSR +- Output node: True +- Repo Ref: https://github.com/flowtyone/ComfyUI-Flowty-TripoSR + +TripoSRViewer类的display方法旨在可视化和导出3D网格。它通过一系列变换处理输入网格以准备其进行可视化,并将修改后的网格保存在指定的目录结构中。该方法增强了用户审查和分析3D渲染任务输出的能力,有助于3D模型操作和评估的整体工作流程。 + +# Input types +## Required +- mesh + - mesh参数对于display方法至关重要,它代表了需要可视化和导出的3D模型。它通过确定将要处理和显示的对象直接影响节点执行的结果。网格的质量和属性影响最终的可视化和导出文件,使其成为节点操作的关键组成部分。 + - Comfy dtype: MESH + - Python dtype: torch_geometric.data.Batch + +# Output types +- mesh + - 输出网格参数代表了display方法执行后修改并保存的3D模型。它之所以重要,是因为它为用户提供了可视化过程的有形成果,允许进行进一步分析或在下游应用中使用。输出网格作为3D模型操作链中的关键环节,展示了所应用变换的有效性。 + - Comfy dtype: MESH + - Python dtype: List[Dict[str, Union[str, int, List[str]]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TripoSRViewer: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mesh': ('MESH',)}} + RETURN_TYPES = () + OUTPUT_NODE = True + FUNCTION = 'display' + CATEGORY = 'Flowty TripoSR' + + def display(self, mesh): + saved = list() + (full_output_folder, filename, counter, subfolder, filename_prefix) = get_save_image_path('meshsave', get_output_directory()) + for (batch_number, single_mesh) in enumerate(mesh): + filename_with_batch_num = filename.replace('%batch_num%', str(batch_number)) + file = f'{filename_with_batch_num}_{counter:05}_.obj' + single_mesh.apply_transform(np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, -1, 0, 0], [0, 0, 0, 1]])) + single_mesh.export(path.join(full_output_folder, file)) + saved.append({'filename': file, 'type': 'output', 'subfolder': subfolder}) + return {'ui': {'mesh': saved}} +``` \ No newline at end of file diff --git a/docs/True Random.org Number Generator.md b/docs/True Random.org Number Generator.md new file mode 100644 index 0000000..6d0b5c0 --- /dev/null +++ b/docs/True Random.org Number Generator.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: WAS_True_Random_Number +- Category: WAS Suite/Number +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_True_Random_Number节点旨在生成具有高安全性和可靠性的随机数。它利用RANDOM.ORG API为用户提供真正的随机数,确保在随机性至关重要的应用中的不可预测性和公平性达到很高的程度。 + +# Input types +## Required +- api_key + - API密钥对于访问RANDOM.ORG服务至关重要。它验证用户的请求并启用随机数的生成。没有有效的API密钥,节点无法执行其预定功能。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- minimum + - 最小值参数定义了生成随机数的范围的下限。它确保输出数字满足指定的最小标准,这对于具有特定数字要求的应用程序至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- maximum + - 最大值参数为生成的随机数范围设置了上限。这对于控制数字的规模并使其与应用程序的需求相一致非常重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- mode + - 模式参数决定随机数是按随机还是固定序列生成。这可以影响数字的可预测性和用例,对用户来说是一个重要的选择。 + - Comfy dtype: COMBO[random, fixed] + - Python dtype: str + +# Output types +- number + - 输出数字是节点操作的核心结果。它代表了在指定范围内生成的真正随机数,是要求随机性的应用的基本元素。 + - Comfy dtype: COMBO[NUMBER, FLOAT, INT] + - Python dtype: Union[int, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_True_Random_Number: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'api_key': ('STRING', {'default': '00000000-0000-0000-0000-000000000000', 'multiline': False}), 'minimum': ('FLOAT', {'default': 0, 'min': -18446744073709551615, 'max': 18446744073709551615}), 'maximum': ('FLOAT', {'default': 10000000, 'min': -18446744073709551615, 'max': 18446744073709551615}), 'mode': (['random', 'fixed'],)}} + RETURN_TYPES = ('NUMBER', 'FLOAT', 'INT') + FUNCTION = 'return_true_randm_number' + CATEGORY = 'WAS Suite/Number' + + def return_true_randm_number(self, api_key=None, minimum=0, maximum=10): + number = self.get_random_numbers(api_key=api_key, minimum=minimum, maximum=maximum)[0] + return (number,) + + def get_random_numbers(self, api_key=None, amount=1, minimum=0, maximum=10, mode='random'): + """Get random number(s) from random.org""" + if api_key in [None, '00000000-0000-0000-0000-000000000000', '']: + cstr('No API key provided! A valid RANDOM.ORG API key is required to use `True Random.org Number Generator`').error.print() + return [0] + url = 'https://api.random.org/json-rpc/2/invoke' + headers = {'Content-Type': 'application/json'} + payload = {'jsonrpc': '2.0', 'method': 'generateIntegers', 'params': {'apiKey': api_key, 'n': amount, 'min': minimum, 'max': maximum, 'replacement': True, 'base': 10}, 'id': 1} + response = requests.post(url, headers=headers, data=json.dumps(payload)) + if response.status_code == 200: + data = response.json() + if 'result' in data: + return (data['result']['random']['data'], float(data['result']['random']['data']), int(data['result']['random']['data'])) + return [0] + + @classmethod + def IS_CHANGED(cls, api_key, mode, **kwargs): + m = hashlib.sha256() + m.update(api_key) + if mode == 'fixed': + return m.digest().hex() + return float('NaN') +``` \ No newline at end of file diff --git a/docs/TwoAdvancedSamplersForMask.md b/docs/TwoAdvancedSamplersForMask.md new file mode 100644 index 0000000..e45d509 --- /dev/null +++ b/docs/TwoAdvancedSamplersForMask.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: TwoAdvancedSamplersForMask +- Category: ImpactPack/Sampler +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +TwoAdvancedSamplersForMask节点旨在使用两个不同的高级采样器对潜在图像执行高级采样操作。它应用掩膜腐蚀技术来细化掩膜,并使用两个独立的高级采样器处理图像的掩膜和未掩膜区域。该节点旨在通过利用两个采样器的优势来提高生成图像的质量。 + +# Input types +## Required +- seed + - 种子参数对于随机数生成过程至关重要,确保了采样的可重复性。它影响采样算法的初始状态,从而影响生成的潜在图像。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步数参数定义了采样过程将经历的迭代次数。它是确定细节水平和最终图像质量的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- denoise + - 去噪参数控制采样过程中应用的噪声减少级别。它在生成图像的清晰度和锐度方面起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- samples + - 样本参数保存将由采样器处理的初始潜在图像数据。它是输入的重要部分,因为它作为采样操作的起点。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- base_sampler + - 基础采样器参数指定将用于处理图像未掩膜区域的高级采样器。它是实现所需采样结果的关键组件。 + - Comfy dtype: KSAMPLER_ADVANCED + - Python dtype: KSamplerAdvancedWrapper +- mask_sampler + - 掩膜采样器参数标识专用于处理图像掩膜区域的高级采样器。它对于将特定的采样技术应用于掩膜区域至关重要。 + - Comfy dtype: KSAMPLER_ADVANCED + - Python dtype: KSamplerAdvancedWrapper +- mask + - 掩膜参数提供了将应用于潜在图像以区分掩膜和未掩膜区域的掩膜。它对于指导采样过程很重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- overlap_factor + - 重叠因子参数确定掩膜腐蚀的范围,用于在掩膜和未掩膜区域之间创建缓冲区。它有助于最终图像中过渡的平滑度。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- latent_image + - 潜在图像输出包含应用高级采样技术后处理的潜在图像。它代表了采样操作的最终结果。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class TwoAdvancedSamplersForMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615}), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'samples': ('LATENT',), 'base_sampler': ('KSAMPLER_ADVANCED',), 'mask_sampler': ('KSAMPLER_ADVANCED',), 'mask': ('MASK',), 'overlap_factor': ('INT', {'default': 10, 'min': 0, 'max': 10000})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Sampler' + + @staticmethod + def mask_erosion(samples, mask, grow_mask_by): + mask = mask.clone() + w = samples['samples'].shape[3] + h = samples['samples'].shape[2] + mask2 = torch.nn.functional.interpolate(mask.reshape((-1, 1, mask.shape[-2], mask.shape[-1])), size=(w, h), mode='bilinear') + if grow_mask_by == 0: + mask_erosion = mask2 + else: + kernel_tensor = torch.ones((1, 1, grow_mask_by, grow_mask_by)) + padding = math.ceil((grow_mask_by - 1) / 2) + mask_erosion = torch.clamp(torch.nn.functional.conv2d(mask2.round(), kernel_tensor, padding=padding), 0, 1) + return mask_erosion[:, :, :w, :h].round() + + def doit(self, seed, steps, denoise, samples, base_sampler, mask_sampler, mask, overlap_factor): + inv_mask = torch.where(mask != 1.0, torch.tensor(1.0), torch.tensor(0.0)) + adv_steps = int(steps / denoise) + start_at_step = adv_steps - steps + new_latent_image = samples.copy() + mask_erosion = TwoAdvancedSamplersForMask.mask_erosion(samples, mask, overlap_factor) + for i in range(start_at_step, adv_steps): + add_noise = 'enable' if i == start_at_step else 'disable' + return_with_leftover_noise = 'enable' if i + 1 != adv_steps else 'disable' + new_latent_image['noise_mask'] = inv_mask + new_latent_image = base_sampler.sample_advanced(add_noise, seed, adv_steps, new_latent_image, i, i + 1, 'enable', recovery_mode='ratio additional') + new_latent_image['noise_mask'] = mask_erosion + new_latent_image = mask_sampler.sample_advanced('disable', seed, adv_steps, new_latent_image, i, i + 1, return_with_leftover_noise, recovery_mode='ratio additional') + del new_latent_image['noise_mask'] + return (new_latent_image,) +``` \ No newline at end of file diff --git a/docs/TwoSamplersForMask.md b/docs/TwoSamplersForMask.md new file mode 100644 index 0000000..526e814 --- /dev/null +++ b/docs/TwoSamplersForMask.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: TwoSamplersForMask +- Category: ImpactPack/Sampler +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +该节点通过整合两种不同的采样机制来协调采样过程,允许生成符合特定遮罩标准的潜在表示。它增强了模型关注相关特征和抑制不需要的信息的能力,从而实现更受控和针对性的采样结果。 + +# Input types +## Required +- latent_image + - 潜在图像是携带采样过程所需基础结构和特征的输入表示。它至关重要,因为它构成了节点操作的基础,影响最终输出的质量和特征。 + - Comfy dtype: LATENT + - Python dtype: dict +- base_sampler + - 基础采样器是提供基础采样能力的重要组件。它负责初步生成潜在图像,为掩码采样器进一步的细化和操作奠定基础。 + - Comfy dtype: KSAMPLER + - Python dtype: KSamplerWrapper or KSamplerAdvancedWrapper +- mask_sampler + - 掩码采样器在应用特定遮罩标准到潜在图像中扮演关键角色。它通过专注于所需特征和抑制不相关特征来精炼采样过程,从而根据预定义的掩码塑造最终输出。 + - Comfy dtype: KSAMPLER + - Python dtype: KSamplerWrapper or KSamplerAdvancedWrapper +- mask + - 掩码参数是一个二进制表示,它决定了应该保留或丢弃潜在图像的哪些区域。它是节点操作的一个组成部分,因为它指导掩码采样器确定应该关注哪些特征以及忽略哪些特征。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- latent_image + - 输出潜在图像是结合了基础和掩码采样器结果的精炼表示。它根据掩码封装了所需的特征并抑制了不相关的特征,作为后续模型操作的最终输入。 + - Comfy dtype: LATENT + - Python dtype: dict + +# Usage tips +- Infra type: GPU + +# Source code +``` +class TwoSamplersForMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latent_image': ('LATENT',), 'base_sampler': ('KSAMPLER',), 'mask_sampler': ('KSAMPLER',), 'mask': ('MASK',)}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Sampler' + + def doit(self, latent_image, base_sampler, mask_sampler, mask): + inv_mask = torch.where(mask != 1.0, torch.tensor(1.0), torch.tensor(0.0)) + latent_image['noise_mask'] = inv_mask + new_latent_image = base_sampler.sample(latent_image) + new_latent_image['noise_mask'] = mask + new_latent_image = mask_sampler.sample(new_latent_image) + del new_latent_image['noise_mask'] + return (new_latent_image,) +``` \ No newline at end of file diff --git a/docs/TwoSamplersForMaskUpscalerProvider.md b/docs/TwoSamplersForMaskUpscalerProvider.md new file mode 100644 index 0000000..390f514 --- /dev/null +++ b/docs/TwoSamplersForMaskUpscalerProvider.md @@ -0,0 +1,69 @@ +# Documentation +- Class name: TwoSamplersForMaskUpscalerProvider +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +TwoSamplersForMaskUpscalerProvider节点旨在使用两种不同的采样方法来促进图像的放大。它允许选择上采样方法和调度采样过程。该节点在通过复杂的采样技术和上采样算法组合来增强图像质量方面起着关键作用。 + +# Input types +## Required +- scale_method + - scale_method参数决定了用于图像上采样的算法。它对上采样过程的整体性能和质量至关重要,因为它直接影响输出的分辨率和清晰度。 + - Comfy dtype: str + - Python dtype: str +- full_sample_schedule + - full_sample_schedule参数在上采样过程中决定何时执行完整采样。它对于控制采样的时机和频率具有重要意义,这反过来又影响最终输出的细节和纹理。 + - Comfy dtype: str + - Python dtype: str +- use_tiled_vae + - use_tiled_vae参数指示是否对变分自编码器(VAE)采用分块方法。这可以提高上采样过程的效率,特别是对于较大的图像。 + - Comfy dtype: bool + - Python dtype: bool +- base_sampler + - base_sampler参数指定用于生成初始样本集的主要采样方法。它在上采样过程中起着基础性作用,影响输出的初始质量和特性。 + - Comfy dtype: KSAMPLER + - Python dtype: KSampler +- mask_sampler + - mask_sampler参数定义了应用于掩码的采样方法。它对于确定掩码如何影响最终上采样结果至关重要,特别是在应用掩码的区域。 + - Comfy dtype: KSAMPLER + - Python dtype: KSampler +- mask + - mask参数提供了用于指导上采样过程的掩码。它对于定义图像中在上采样期间需要特别关注或处理的区域很重要。 + - Comfy dtype: MASK + - Python dtype: np.ndarray +- vae + - vae参数表示上采样过程中使用的变分自编码器模型。它是生成输入图像的高质量潜在表示的关键组件。 + - Comfy dtype: VAE + - Python dtype: VAE +## Optional +- tile_size + - tile_size参数设置了在使用分块方法时用于处理图像的分块大小。它对于优化内存使用和处理时间具有重要意义,尤其是对于高分辨率图像。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- upscaler + - upscaler输出提供了最终的上样图像或潜在表示。它是上采样过程的最终成果,代表了通过节点的复杂采样和上采样方法实现的增强图像质量和分辨率。 + - Comfy dtype: UPSCALER + - Python dtype: TwoSamplersForMaskUpscaler + +# Usage tips +- Infra type: CPU + +# Source code +``` +class TwoSamplersForMaskUpscalerProvider: + upscale_methods = ['nearest-exact', 'bilinear', 'lanczos', 'area'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'scale_method': (s.upscale_methods,), 'full_sample_schedule': (['none', 'interleave1', 'interleave2', 'interleave3', 'last1', 'last2', 'interleave1+last1', 'interleave2+last1', 'interleave3+last1'],), 'use_tiled_vae': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'}), 'base_sampler': ('KSAMPLER',), 'mask_sampler': ('KSAMPLER',), 'mask': ('MASK',), 'vae': ('VAE',), 'tile_size': ('INT', {'default': 512, 'min': 320, 'max': 4096, 'step': 64})}, 'optional': {'full_sampler_opt': ('KSAMPLER',), 'upscale_model_opt': ('UPSCALE_MODEL',), 'pk_hook_base_opt': ('PK_HOOK',), 'pk_hook_mask_opt': ('PK_HOOK',), 'pk_hook_full_opt': ('PK_HOOK',)}} + RETURN_TYPES = ('UPSCALER',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + def doit(self, scale_method, full_sample_schedule, use_tiled_vae, base_sampler, mask_sampler, mask, vae, full_sampler_opt=None, upscale_model_opt=None, pk_hook_base_opt=None, pk_hook_mask_opt=None, pk_hook_full_opt=None, tile_size=512): + upscaler = core.TwoSamplersForMaskUpscaler(scale_method, full_sample_schedule, use_tiled_vae, base_sampler, mask_sampler, mask, vae, full_sampler_opt, upscale_model_opt, pk_hook_base_opt, pk_hook_mask_opt, pk_hook_full_opt, tile_size=tile_size) + return (upscaler,) +``` \ No newline at end of file diff --git a/docs/TwoSamplersForMaskUpscalerProviderPipe.md b/docs/TwoSamplersForMaskUpscalerProviderPipe.md new file mode 100644 index 0000000..93ced1e --- /dev/null +++ b/docs/TwoSamplersForMaskUpscalerProviderPipe.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: TwoSamplersForMaskUpscalerProviderPipe +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +TwoSamplersForMaskUpscalerProviderPipe节点旨在高效地使用两种不同的采样方法对图像进行放大。它利用基础采样器和掩码采样器的组合,以及掩码和变分自编码器(VAE),执行放大过程。该节点能够处理不同的放大方法和计划,并且可以选择性地使用分块VAE以提高性能。它特别适用于需要高质量图像放大的应用。 + +# Input types +## Required +- scale_method + - scale_method参数决定了用于图像放大的算法。这是一个关键组件,因为它直接影响放大过程的质量和效率。 + - Comfy dtype: str + - Python dtype: str +- full_sample_schedule + - full_sample_schedule参数决定了在放大过程中何时进行完整采样。这个参数对于控制采样频率,从而在速度和质量之间进行权衡至关重要。 + - Comfy dtype: str + - Python dtype: str +- use_tiled_vae + - 使用分块变分自编码器(VAE)可以通过允许更高效地处理大图像来增强放大过程。这个参数对于在GPU架构上优化性能具有重要意义。 + - Comfy dtype: bool + - Python dtype: bool +- base_sampler + - 基础采样器是放大过程中的一个基本组件,负责生成初始样本。其选择可以极大地影响放大的整体结果。 + - Comfy dtype: KSAMPLER + - Python dtype: KSampler +- mask_sampler + - 掩码采样器与基础采样器一起使用,用于对图像的掩蔽区域应用特定的采样技术。它在实现目标放大效果中起着关键作用。 + - Comfy dtype: KSAMPLER + - Python dtype: KSampler +- mask + - 掩码参数定义了将被掩码采样器处理的图像区域。它在选定区域的图像选择性放大中起着至关重要的作用。 + - Comfy dtype: MASK + - Python dtype: Mask +- basic_pipe + - 基本管道封装了放大过程所需的基本元素,包括变分自编码器(VAE)。它对节点的功能至关重要。 + - Comfy dtype: BASIC_PIPE + - Python dtype: BasicPipe +## Optional +- tile_size + - tile_size参数指定了在使用分块VAE处理图像时使用的瓦片的尺寸。它对管理内存使用和处理时间很重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- upscaler + - 节点的输出是一个包含放大过程结果的放大器对象。它很重要,因为它代表了用于进一步使用或分析的最终输出。 + - Comfy dtype: UPSCALER + - Python dtype: Upscaler + +# Usage tips +- Infra type: GPU + +# Source code +``` +class TwoSamplersForMaskUpscalerProviderPipe: + upscale_methods = ['nearest-exact', 'bilinear', 'lanczos', 'area'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'scale_method': (s.upscale_methods,), 'full_sample_schedule': (['none', 'interleave1', 'interleave2', 'interleave3', 'last1', 'last2', 'interleave1+last1', 'interleave2+last1', 'interleave3+last1'],), 'use_tiled_vae': ('BOOLEAN', {'default': False, 'label_on': 'enabled', 'label_off': 'disabled'}), 'base_sampler': ('KSAMPLER',), 'mask_sampler': ('KSAMPLER',), 'mask': ('MASK',), 'basic_pipe': ('BASIC_PIPE',), 'tile_size': ('INT', {'default': 512, 'min': 320, 'max': 4096, 'step': 64})}, 'optional': {'full_sampler_opt': ('KSAMPLER',), 'upscale_model_opt': ('UPSCALE_MODEL',), 'pk_hook_base_opt': ('PK_HOOK',), 'pk_hook_mask_opt': ('PK_HOOK',), 'pk_hook_full_opt': ('PK_HOOK',)}} + RETURN_TYPES = ('UPSCALER',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + def doit(self, scale_method, full_sample_schedule, use_tiled_vae, base_sampler, mask_sampler, mask, basic_pipe, full_sampler_opt=None, upscale_model_opt=None, pk_hook_base_opt=None, pk_hook_mask_opt=None, pk_hook_full_opt=None, tile_size=512): + mask = make_2d_mask(mask) + (_, _, vae, _, _) = basic_pipe + upscaler = core.TwoSamplersForMaskUpscaler(scale_method, full_sample_schedule, use_tiled_vae, base_sampler, mask_sampler, mask, vae, full_sampler_opt, upscale_model_opt, pk_hook_base_opt, pk_hook_mask_opt, pk_hook_full_opt, tile_size=tile_size) + return (upscaler,) +``` \ No newline at end of file diff --git a/docs/UltimateSDUpscale.md b/docs/UltimateSDUpscale.md new file mode 100644 index 0000000..f72aa1c --- /dev/null +++ b/docs/UltimateSDUpscale.md @@ -0,0 +1,142 @@ +# Documentation +- Class name: UltimateSDUpscale +- Category: image/upscaling +- Output node: False +- Repo Ref: https://github.com/ssitu/ComfyUI_UltimateSDUpscale + +UltimateSDUpscale节点旨在使用先进技术提升图像的分辨率。它利用稳定扩散模型的强大功能来放大图像,为用户提供高质量、细节丰富的结果。该节点的主要目标是在保持原始图像本质的同时提高视觉真实性,使其适用于从照片增强到艺术转换的各种应用。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它是放大处理的基础。它决定了将要增强的内容和结构,其质量直接影响最终输出。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +- model + - 模型参数对节点的运行至关重要,因为它定义了用于放大过程的AI模型。模型的选择显著影响放大结果的风格和质量。 + - Comfy dtype: MODEL + - Python dtype: str +- positive + - 正向调节在放大过程中为AI模型提供所需强调的特征指导,确保最终图像符合用户的期望。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- negative + - 负向调节帮助AI模型避免在放大图像中出现不需要的特征或伪影,提高整体质量并确保更准确地呈现期望的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- vae + - VAE参数对放大过程至关重要,因为它使得图像的编码和解码成为可能,既保持原始图像的本质,又提高了其分辨率。 + - Comfy dtype: VAE + - Python dtype: str +- upscale_by + - upscale_by参数决定了图像的放大倍数,直接影响输出的尺寸和细节水平。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - seed参数在放大过程中生成可复现的结果很重要,确保多次运行的一致性。 + - Comfy dtype: INT + - Python dtype: int +- steps + - steps参数影响AI模型在放大过程中执行的迭代次数,这可能会影响最终图像的质量和细节。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数调整AI模型的配置设置,影响放大图像的整体风格和一致性。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数决定了AI模型使用的采样方法,这可能会改变放大图像的风格特征和质量。 + - Comfy dtype: ENUM + - Python dtype: comfy.samplers.KSampler.SAMPLERS +- scheduler + - scheduler参数影响AI模型的学习率调度,影响收敛性和最终输出质量。 + - Comfy dtype: ENUM + - Python dtype: comfy.samplers.KSampler.SCHEDULERS +- denoise + - denoise参数用于控制在放大过程中应用的降噪水平,提高最终图像的清晰度和锐度。 + - Comfy dtype: FLOAT + - Python dtype: float +- upscale_model + - upscale_model参数指定要使用的放大模型,这对实现期望的分辨率和质量提升至关重要。 + - Comfy dtype: UPSCALE_MODEL + - Python dtype: str +- mode_type + - mode_type参数决定了放大的处理模式,这可能会影响最终图像的视觉特征和整体外观。 + - Comfy dtype: ENUM + - Python dtype: list +- tile_width + - tile_width参数设置了处理时使用的瓦片宽度,这可能会影响放大过程的效率和质量。 + - Comfy dtype: INT + - Python dtype: int +- tile_height + - tile_height参数定义了瓦片的高度,影响图像如何被分割处理,进而影响放大的结果。 + - Comfy dtype: INT + - Python dtype: int +- mask_blur + - mask_blur参数调整应用于图像遮罩的模糊程度,这可以改善放大区域与原始图像的无缝融合。 + - Comfy dtype: INT + - Python dtype: int +- tile_padding + - tile_padding参数指定了每个瓦片周围的填充,这对于在放大过程中保持图像结构的完整性非常重要。 + - Comfy dtype: INT + - Python dtype: int +- seam_fix_mode + - seam_fix_mode参数决定了用于修复瓦片之间接缝的方法,这可以提高放大图像的视觉连续性和整体质量。 + - Comfy dtype: ENUM + - Python dtype: list +- seam_fix_denoise + - seam_fix_denoise参数控制应用于接缝的降噪水平,有助于减少伪影并提高最终图像的平滑度。 + - Comfy dtype: FLOAT + - Python dtype: float +- seam_fix_width + - seam_fix_width参数设置了接缝周围用于降噪和平滑的区域宽度,影响最终图像的无缝外观。 + - Comfy dtype: INT + - Python dtype: int +- seam_fix_mask_blur + - seam_fix_mask_blur参数调整应用于接缝周围遮罩的模糊程度,这有助于实现放大瓦片之间更自然的过渡。 + - Comfy dtype: INT + - Python dtype: int +- seam_fix_padding + - seam_fix_padding参数定义了接缝周围的填充,这对于确保放大部分平滑且一致地集成到最终图像中至关重要。 + - Comfy dtype: INT + - Python dtype: int +- force_uniform_tiles + - force_uniform_tiles参数确保所有瓦片具有相同的大小,这可以简化处理并提高放大图像的均匀性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- tiled_decode + - tiled_decode参数指示图像是否应该按瓦片解码,这对于大型图像的放大过程可以提高效率和质量。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- IMAGE + - 输出图像是放大过程的结果,展示了更高的分辨率和增强的细节,同时保留了原始图像的本质。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class UltimateSDUpscale: + + @classmethod + def INPUT_TYPES(s): + return prepare_inputs(USDU_base_inputs()) + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'upscale' + CATEGORY = 'image/upscaling' + + def upscale(self, image, model, positive, negative, vae, upscale_by, seed, steps, cfg, sampler_name, scheduler, denoise, upscale_model, mode_type, tile_width, tile_height, mask_blur, tile_padding, seam_fix_mode, seam_fix_denoise, seam_fix_mask_blur, seam_fix_width, seam_fix_padding, force_uniform_tiles, tiled_decode): + shared.sd_upscalers[0] = UpscalerData() + shared.actual_upscaler = upscale_model + shared.batch = [tensor_to_pil(image, i) for i in range(len(image))] + sdprocessing = StableDiffusionProcessing(tensor_to_pil(image), model, positive, negative, vae, seed, steps, cfg, sampler_name, scheduler, denoise, upscale_by, force_uniform_tiles, tiled_decode) + script = usdu.Script() + processed = script.run(p=sdprocessing, _=None, tile_width=tile_width, tile_height=tile_height, mask_blur=mask_blur, padding=tile_padding, seams_fix_width=seam_fix_width, seams_fix_denoise=seam_fix_denoise, seams_fix_padding=seam_fix_padding, upscaler_index=0, save_upscaled_image=False, redraw_mode=MODES[mode_type], save_seams_fix_image=False, seams_fix_mask_blur=seam_fix_mask_blur, seams_fix_type=SEAM_FIX_MODES[seam_fix_mode], target_size_type=2, custom_width=None, custom_height=None, custom_scale=upscale_by) + images = [pil_to_tensor(img) for img in shared.batch] + tensor = torch.cat(images, dim=0) + return (tensor,) +``` \ No newline at end of file diff --git a/docs/UltimateSDUpscaleNoUpscale.md b/docs/UltimateSDUpscaleNoUpscale.md new file mode 100644 index 0000000..d69ae55 --- /dev/null +++ b/docs/UltimateSDUpscaleNoUpscale.md @@ -0,0 +1,134 @@ +# Documentation +- Class name: UltimateSDUpscaleNoUpscale +- Category: image/upscaling +- Output node: False +- Repo Ref: https://github.com/ssitu/ComfyUI_UltimateSDUpscale + +该节点类旨在通过使用复杂的图像放大算法来提高图像质量,该算法利用了稳定扩散处理的强大功能。它的目的是在保持图像原始内容和细节的同时提高视觉保真度。节点的主要功能是对图像进行放大,为用户提供清晰且视觉上吸引人的高分辨率输出。 + +# Input types +## Required +- upscaled_image + - 已放大的图像参数至关重要,因为它是节点放大过程的基础。这是已经被放大的图像,将由节点进一步优化,以提高其质量和分辨率。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- model + - 模型参数对节点至关重要,它决定了用于放大过程的底层AI模型。它确保利用AI模型的能力来实现期望的放大结果。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- positive + - 正面参数在指导放大过程中起着重要作用,通过提供正面的条件数据。这些数据帮助AI模型理解期望的结果,并改善最终输出。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- negative + - 负面参数至关重要,因为它提供了负面的条件数据,帮助AI模型在放大过程中避免不希望的结果。它有助于提高图像质量。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- vae + - vae参数很重要,因为它代表了在放大过程中使用的变分自编码器。它通过编码和解码视觉信息来帮助生成更高质量的图像。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- seed + - 种子参数对节点至关重要,因为它初始化随机数生成器,确保结果在不同运行中是可复现和一致的。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步骤参数定义了AI模型在放大过程中将执行的迭代次数。它直接影响计算时间和最终输出的质量。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数是一个浮点值,它在放大过程中影响AI模型的配置。它有助于微调模型的行为,以获得最佳结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数对于在放大过程中选择适当的采样方法至关重要。它影响AI模型生成放大图像的方式,有助于整体质量和外观。 + - Comfy dtype: ENUM + - Python dtype: Enum +- scheduler + - 调度器参数对于在放大过程中管理AI模型的学习率至关重要。它有助于控制训练动态,并实现更好的放大结果。 + - Comfy dtype: ENUM + - Python dtype: Enum +- denoise + - 去噪参数是一个浮点值,它控制放大过程中应用的降噪水平。对于提高放大图像的清晰度和锐度很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- tile_width + - tile_width参数指定用于平铺放大图像的瓦片的宽度。它影响放大过程的粒度,可以影响最终图像的质量。 + - Comfy dtype: INT + - Python dtype: int +- tile_height + - tile_height参数定义了用于平铺放大图像的瓦片的高度。它与tile_width一起工作,以确定平铺策略及其对图像质量的影响。 + - Comfy dtype: INT + - Python dtype: int +- mask_blur + - mask_blur参数控制放大过程中应用于图像遮罩的模糊程度。对于平滑边缘和提高放大图像的视觉一致性很重要。 + - Comfy dtype: INT + - Python dtype: int +- tile_padding + - tile_padding参数指定应用于每个瓦片边缘的填充量。它对于确保最终放大图像中瓦片之间的接缝不可见至关重要。 + - Comfy dtype: INT + - Python dtype: int +- seam_fix_mode + - seam_fix_mode参数确定用于修复放大图像中接缝的方法。它对于通过最小化瓦片边界的可见性,确保最终输出的无缝和视觉愉悦至关重要。 + - Comfy dtype: ENUM + - Python dtype: Enum +- seam_fix_denoise + - seam_fix_denoise参数调整应用于放大图像接缝的降噪水平。它有助于减少伪影,并在最终输出中实现更平滑、更自然的外观。 + - Comfy dtype: FLOAT + - Python dtype: float +- seam_fix_width + - seam_fix_width参数设置将要处理的接缝周围区域的宽度。它影响接缝修复过程的有效性,并有助于提高放大图像的整体视觉质量。 + - Comfy dtype: INT + - Python dtype: int +- seam_fix_mask_blur + - seam_fix_mask_blur参数控制应用于接缝修复的遮罩的模糊程度。对于实现瓦片之间的平滑过渡和增强放大图像的视觉连续性很重要。 + - Comfy dtype: INT + - Python dtype: int +- seam_fix_padding + - seam_fix_padding参数指定在接缝修复过程中应用于图像边缘的填充量。它对于确保放大图像的边缘清晰且无伪影至关重要。 + - Comfy dtype: INT + - Python dtype: int +- force_uniform_tiles + - force_uniform_tiles参数确保在放大过程中所有瓦片的大小相同。这有助于最终放大图像的一致和统一的外观。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- tiled_decode + - tiled_decode参数指示是否应该以瓦片方式解码放大的图像。这可以在放大过程中提高处理效率并管理内存使用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- IMAGE + - 输出图像是放大过程的结果,展示了提高的分辨率和质量。它代表节点的主要输出,为用户提供了输入图像的视觉改进版本。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: GPU + +# Source code +``` +class UltimateSDUpscaleNoUpscale: + + @classmethod + def INPUT_TYPES(s): + required = USDU_base_inputs() + remove_input(required, 'upscale_model') + remove_input(required, 'upscale_by') + rename_input(required, 'image', 'upscaled_image') + return prepare_inputs(required) + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'upscale' + CATEGORY = 'image/upscaling' + + def upscale(self, upscaled_image, model, positive, negative, vae, seed, steps, cfg, sampler_name, scheduler, denoise, mode_type, tile_width, tile_height, mask_blur, tile_padding, seam_fix_mode, seam_fix_denoise, seam_fix_mask_blur, seam_fix_width, seam_fix_padding, force_uniform_tiles, tiled_decode): + shared.sd_upscalers[0] = UpscalerData() + shared.actual_upscaler = None + shared.batch = [tensor_to_pil(upscaled_image, i) for i in range(len(upscaled_image))] + sdprocessing = StableDiffusionProcessing(tensor_to_pil(upscaled_image), model, positive, negative, vae, seed, steps, cfg, sampler_name, scheduler, denoise, 1, force_uniform_tiles, tiled_decode) + script = usdu.Script() + processed = script.run(p=sdprocessing, _=None, tile_width=tile_width, tile_height=tile_height, mask_blur=mask_blur, padding=tile_padding, seams_fix_width=seam_fix_width, seams_fix_denoise=seam_fix_denoise, seams_fix_padding=seam_fix_padding, upscaler_index=0, save_upscaled_image=False, redraw_mode=MODES[mode_type], save_seams_fix_image=False, seams_fix_mask_blur=seam_fix_mask_blur, seams_fix_type=SEAM_FIX_MODES[seam_fix_mode], target_size_type=2, custom_width=None, custom_height=None, custom_scale=1) + images = [pil_to_tensor(img) for img in shared.batch] + tensor = torch.cat(images, dim=0) + return (tensor,) +``` \ No newline at end of file diff --git a/docs/UltralyticsDetectorProvider.md b/docs/UltralyticsDetectorProvider.md new file mode 100644 index 0000000..21383a0 --- /dev/null +++ b/docs/UltralyticsDetectorProvider.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: UltraalyticsDetectorProvider +- Category: ImpactPack +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +UltraalyticsDetectorProvider节点旨在方便加载和使用由Ultraalytics提供的对象检测模型。它抽象了模型初始化的复杂性,允许用户轻松执行边界框和分割检测。该节点强调将检测功能无缝集成到更广泛的系统中,为检测任务提供了一个高级接口,无需深入了解底层模型架构或推理过程。 + +# Input types +## Required +- model_name + - model_name参数对于指定加载哪个预训练的YOLO模型进行对象检测任务至关重要。它的值决定了模型的配置以及节点将执行的检测类型(边界框或分割)。此参数直接影响节点的执行和检测结果的质量。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- BBOX_DETECTOR + - BBOX_DETECTOR输出提供了一个专门用于通过边界框在图像中识别和定位对象的检测器对象。它封装了执行检测的功能,是对象检测流水线中的关键组件,提供了一种结构化的方法来获取和使用检测结果。 + - Comfy dtype: UltraBBoxDetector + - Python dtype: UltraBBoxDetector +- SEGM_DETECTOR + - SEGM_DETECTOR输出提供了一个检测器对象,它不仅可以在图像中定位对象,还可以提供分割掩码。此输出对于需要更详细了解对象形状和边界的应用程序非常重要,提供了一种全面的检测解决方案,包括分割功能。 + - Comfy dtype: UltraSegmDetector + - Python dtype: UltraSegmDetector + +# Usage tips +- Infra type: GPU + +# Source code +``` +class UltralyticsDetectorProvider: + + @classmethod + def INPUT_TYPES(s): + bboxs = ['bbox/' + x for x in folder_paths.get_filename_list('ultralytics_bbox')] + segms = ['segm/' + x for x in folder_paths.get_filename_list('ultralytics_segm')] + return {'required': {'model_name': (bboxs + segms,)}} + RETURN_TYPES = ('BBOX_DETECTOR', 'SEGM_DETECTOR') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack' + + def doit(self, model_name): + model_path = folder_paths.get_full_path('ultralytics', model_name) + model = subcore.load_yolo(model_path) + if model_name.startswith('bbox'): + return (subcore.UltraBBoxDetector(model), core.NO_SEGM_DETECTOR()) + else: + return (subcore.UltraBBoxDetector(model), subcore.UltraSegmDetector(model)) +``` \ No newline at end of file diff --git a/docs/Unary Image Op.md b/docs/Unary Image Op.md new file mode 100644 index 0000000..5656742 --- /dev/null +++ b/docs/Unary Image Op.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: UnaryImageOp +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +UnaryImageOp节点旨在执行多种单输入图像操作。它提供了一系列一元操作,如图像反转、平均、四舍五入、夹紧和绝对值计算。这些操作对于图像预处理和特征提取至关重要,允许操作图像数据以满足特定的分析或可视化需求。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它是UnaryImageOp节点的主要输入。它代表将经历指定一元操作的图像数据。图像的特性直接影响节点的输出,使其成为节点执行中的基本组成部分。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- op + - op参数指定要应用于图像的一元操作。它是节点功能的关键决定因素,因为它决定了将执行的转换类型。操作的选择可以显著改变结果图像的特性,影响下游处理。 + - Comfy dtype: COMBO['invert', 'average', 'round', 'clamp', 'abs'] + - Python dtype: str + +# Output types +- result + - 结果参数代表应用于输入图像的一元操作的输出。它包含了在执行指定操作后转换的图像数据。这个输出是重要的,因为它为任何后续的图像分析或处理步骤奠定了基础。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class UnaryImageOp: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'op': (['invert', 'average', 'round', 'clamp', 'abs'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'op_image' + CATEGORY = 'Masquerade Nodes' + + def op_image(self, image, op): + image = tensor2rgb(image) + if op == 'invert': + return (1.0 - image,) + elif op == 'average': + mean = torch.mean(torch.mean(image, dim=2), dim=1) + return (mean.unsqueeze(1).unsqueeze(2).repeat(1, image.shape[1], image.shape[2], 1),) + elif op == 'round': + return (torch.round(image),) + elif op == 'clamp': + return (torch.min(torch.max(image, torch.tensor(0.0)), torch.tensor(1.0)),) + elif op == 'abs': + return (torch.abs(image),) +``` \ No newline at end of file diff --git a/docs/Unary Mask Op.md b/docs/Unary Mask Op.md new file mode 100644 index 0000000..d6d878e --- /dev/null +++ b/docs/Unary Mask Op.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: UnaryMaskOp +- Category: Masquerade Nodes +- Output node: False +- Repo Ref: https://github.com/BadCafeCode/masquerade-nodes-comfyui + +UnaryMaskOp节点旨在对给定的掩码图像执行多种一元操作。它提供了一套方法来操作掩码,例如反转掩码、平均像素值、四舍五入、夹紧值到一定范围以及取绝对值。这些操作对于图像处理任务中的预处理步骤至关重要,其中可能需要掩码的不同表示形式。 + +# Input types +## Required +- image + - 图像参数对于UnaryMaskOp节点至关重要,因为它代表了将要进行一元操作的输入掩码图像。节点的功能直接与此输入的质量和格式相关,这影响了操作的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- op + - 操作参数决定了将应用于输入掩码的特定一元操作。它是一个关键组件,因为它决定了将发生的变换类型,影响节点执行的最终结果。 + - Comfy dtype: COMBO['invert', 'average', 'round', 'clamp', 'abs'] + - Python dtype: str + +# Output types +- result + - 结果参数封装了应用于输入掩码的一元操作的结果。它是一个重要的输出,因为它反映了变换后的掩码,可以用于进一步的处理或分析。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class UnaryMaskOp: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'op': (['invert', 'average', 'round', 'clamp', 'abs'],)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'op_mask' + CATEGORY = 'Masquerade Nodes' + + def op_mask(self, image, op): + image = tensor2mask(image) + if op == 'invert': + return (1.0 - image,) + elif op == 'average': + mean = torch.mean(torch.mean(image, dim=2), dim=1) + return (mean.unsqueeze(1).unsqueeze(2).repeat(1, image.shape[1], image.shape[2]),) + elif op == 'round': + return (torch.round(image),) + elif op == 'clamp': + return (torch.min(torch.max(image, torch.tensor(0.0)), torch.tensor(1.0)),) + elif op == 'abs': + return (torch.abs(image),) +``` \ No newline at end of file diff --git a/docs/Uncrop (mtb).md b/docs/Uncrop (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/UnsamplerDetailerHookProvider.md b/docs/UnsamplerDetailerHookProvider.md new file mode 100644 index 0000000..2105b8f --- /dev/null +++ b/docs/UnsamplerDetailerHookProvider.md @@ -0,0 +1,85 @@ +# Documentation +- Class name: UnsamplerDetailerHookProvider +- Category: ImpactPack/Detailer +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +UnsamplerDetailerHookProvider节点旨在通过反采样增强采样数据的细节。它通过在采样过程中应用详细的反采样钩子来操作,允许生成更精细的输出。此节点对于需要高细节质量的任务至关重要,例如在图像或信号处理应用中。 + +# Input types +## Required +- model + - 模型参数对于UnsamplerDetailerHookProvider节点至关重要,因为它定义了将用于反采样的底层模型。模型的选择可以显著影响反采样数据的质量和特性。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- steps + - 步骤参数决定了反采样过程中要使用的步骤数。它是一个关键因素,影响操作的细节水平和计算复杂性。 + - Comfy dtype: INT + - Python dtype: int +- start_end_at_step + - start_end_at_step参数指定了反采样过程应该开始逐渐减少细节增强的步骤。 + - Comfy dtype: INT + - Python dtype: int +- end_end_at_step + - end_end_at_step参数标记了反采样过程结束的最终步骤,标志着细节增强阶段的结束。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数调整反采样器的配置设置,允许微调反采样过程以实现期望的结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数标识了在反采样过程中要使用的特定采样器,这可以改变采样数据的性质。 + - Comfy dtype: STRING + - Python dtype: str +- scheduler + - scheduler参数决定了反采样步骤的调度策略,可以优化过程以提高效率或质量。 + - Comfy dtype: STRING + - Python dtype: str +- normalize + - normalize参数决定在反采样过程中是否应该对数据进行标准化,这可能改善结果的一致性。 + - Comfy dtype: STRING + - Python dtype: str +- positive + - positive参数提供正向条件信息,引导反采样过程朝着期望的结果发展。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- negative + - negative参数提供负向条件信息,以避免在反采样过程中出现不希望的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- schedule_for_cycle + - schedule_for_cycle参数指定反采样过程是否应遵循循环计划,这对于迭代细化非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- DETAILER_HOOK + - UnsamplerDetailerHookProvider节点的输出是一个详细的反采样钩子,可以用来将额外的细节注入到采样过程中,提高最终输出的质量。 + - Comfy dtype: DETAILER_HOOK + - Python dtype: DetailerHook + +# Usage tips +- Infra type: CPU + +# Source code +``` +class UnsamplerDetailerHookProvider: + schedules = ['skip_start', 'from_start'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'steps': ('INT', {'default': 25, 'min': 1, 'max': 10000}), 'start_end_at_step': ('INT', {'default': 21, 'min': 0, 'max': 10000}), 'end_end_at_step': ('INT', {'default': 24, 'min': 0, 'max': 10000}), 'cfg': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 100.0}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'normalize': (['disable', 'enable'],), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'schedule_for_cycle': (s.schedules,)}} + RETURN_TYPES = ('DETAILER_HOOK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Detailer' + + def doit(self, model, steps, start_end_at_step, end_end_at_step, cfg, sampler_name, scheduler, normalize, positive, negative, schedule_for_cycle): + try: + hook = hooks.UnsamplerDetailerHook(model, steps, start_end_at_step, end_end_at_step, cfg, sampler_name, scheduler, normalize, positive, negative, from_start='from_start' in schedule_for_cycle) + return (hook,) + except Exception as e: + print("[ERROR] UnsamplerDetailerHookProvider: 'ComfyUI Noise' custom node isn't installed. You must install 'BlenderNeko/ComfyUI Noise' extension to use this node.") + print(f'\t{e}') + pass +``` \ No newline at end of file diff --git a/docs/UnsamplerHookProvider.md b/docs/UnsamplerHookProvider.md new file mode 100644 index 0000000..df3dc04 --- /dev/null +++ b/docs/UnsamplerHookProvider.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: UnsamplerHookProvider +- Category: ImpactPack/Upscale +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Impact-Pack.git + +UnsamplerHookProvider节点旨在通过在图像生成过程中应用去采样器钩子来增强放大过程。它根据放大过程中的当前步骤动态调整采样策略,允许对图像质量进行微调。该节点在图像增强工作流程中扮演着关键角色,通过利用动态采样技术的力量,确保最终输出的图像质量最高。 + +# Input types +## Required +- model + - 模型参数对于UnsamplerHookProvider节点至关重要,因为它定义了将用于图像放大的模型。模型的选择显著影响节点的执行和生成图像的质量。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +## Optional +- steps + - 步骤参数决定了放大过程中采取的步骤数。它是控制细节水平和节点总执行时间的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- start_end_at_step + - start_end_at_step参数指定了去采样器钩子操作的起始步骤。它对于定义去采样器钩子开始影响放大过程的初始条件很重要。 + - Comfy dtype: INT + - Python dtype: int +- end_end_at_step + - end_end_at_step参数标记了去采样器钩子停止操作的最终步骤。它是设置去采样器钩子对放大过程影响的终点的关键参数。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数用于配置去采样器钩子的设置。它在定制放大过程以满足特定质量要求方面起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数标识了去采样器钩子要使用的采样方法。它是确定放大过程中采样策略的关键组成部分。 + - Comfy dtype: STRING + - Python dtype: str +- scheduler + - scheduler参数决定去采样器钩子操作的调度策略。它对于管理放大过程中采样步骤的时机和顺序至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- normalize + - normalize参数指示在处理之前是否应将输入数据标准化。它通过可能改变输入值的缩放来影响节点的执行。 + - Comfy dtype: STRING + - Python dtype: str +- positive + - positive参数为去采样器钩子提供正向调节数据,影响放大过程朝着期望结果的方向发展。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- negative + - negative参数为去采样器钩子提供负向调节数据,引导放大过程远离不希望的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- schedule_for_iteration + - schedule_for_iteration参数指定当前放大过程迭代中使用哪种调度策略。对于迭代不同的策略以实现最佳结果至关重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- hook + - hook输出提供了根据输入参数配置的去采样器钩子对象。它很重要,因为它代表了节点的核心功能,使得能够操作放大过程。 + - Comfy dtype: PK_HOOK + - Python dtype: PixelKSampleHook + +# Usage tips +- Infra type: CPU + +# Source code +``` +class UnsamplerHookProvider: + schedules = ['simple'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'steps': ('INT', {'default': 25, 'min': 1, 'max': 10000}), 'start_end_at_step': ('INT', {'default': 21, 'min': 0, 'max': 10000}), 'end_end_at_step': ('INT', {'default': 24, 'min': 0, 'max': 10000}), 'cfg': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 100.0}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'normalize': (['disable', 'enable'],), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'schedule_for_iteration': (s.schedules,)}} + RETURN_TYPES = ('PK_HOOK',) + FUNCTION = 'doit' + CATEGORY = 'ImpactPack/Upscale' + + def doit(self, model, steps, start_end_at_step, end_end_at_step, cfg, sampler_name, scheduler, normalize, positive, negative, schedule_for_iteration): + try: + hook = None + if schedule_for_iteration == 'simple': + hook = hooks.UnsamplerHook(model, steps, start_end_at_step, end_end_at_step, cfg, sampler_name, scheduler, normalize, positive, negative) + return (hook,) + except Exception as e: + print("[ERROR] UnsamplerHookProvider: 'ComfyUI Noise' custom node isn't installed. You must install 'BlenderNeko/ComfyUI Noise' extension to use this node.") + print(f'\t{e}') + pass +``` \ No newline at end of file diff --git a/docs/Unsplash Image (mtb).md b/docs/Unsplash Image (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/UnzipPrompt %2F%2FInspire.md b/docs/UnzipPrompt %2F%2FInspire.md new file mode 100644 index 0000000..e6555be --- /dev/null +++ b/docs/UnzipPrompt %2F%2FInspire.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: UnzipPrompt +- Category: InspirePack/Prompt +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +该节点旨在处理和解压缩提示,便于内容的提取以供进一步使用。它是需要处理压缩数据的工作流中的关键组件,确保数据随时可用且格式正确以供后续操作。 + +# Input types +## Required +- zipped_prompt + - zipped_prompt参数是必需的,因为它包含了节点设计处理的压缩数据。它直接影响节点的运作和输出质量,因为节点的主要功能是提取和处理此输入的内容。 + - Comfy dtype: ZIPPED_PROMPT + - Python dtype: bytes + +# Output types +- positive + - positive输出代表从zipped_prompt中成功提取和处理的内容。它是节点操作的关键结果,表明数据已被适当处理并准备供进一步使用。 + - Comfy dtype: STRING + - Python dtype: str +- negative + - negative输出提供了在处理zipped_prompt期间遇到的任何问题或错误的信息。此输出对于理解节点操作的成功或失败以及必要时进行故障排除非常重要。 + - Comfy dtype: STRING + - Python dtype: str +- name + - name输出通常包含zipped_prompt的文件名或标识符。此输出对于在工作流中跟踪和引用处理后的数据非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class UnzipPrompt: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'zipped_prompt': ('ZIPPED_PROMPT',)}} + RETURN_TYPES = ('STRING', 'STRING', 'STRING') + RETURN_NAMES = ('positive', 'negative', 'name') + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Prompt' + + def doit(self, zipped_prompt): + return zipped_prompt +``` \ No newline at end of file diff --git a/docs/Upscale Model Loader.md b/docs/Upscale Model Loader.md new file mode 100644 index 0000000..662ae56 --- /dev/null +++ b/docs/Upscale Model Loader.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: WAS_Upscale_Model_Loader +- Category: WAS Suite/Loaders +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 `load_model` 负责加载和准备用于图像放大任务的模型。它通过在指定目录中定位指定的模型,加载其参数,并初始化它以供使用来实现这一点。此方法对于将预训练模型无缝集成到工作流程中至关重要,确保模型无需手动干预即可准备就绪,以便部署。 + +# Input types +## Required +- model_name + - 参数 `model_name` 对于识别要加载的特定模型至关重要。它将方法指向模型目录中正确的文件,从而实现所需模型的检索和初始化。此参数对于确保使用正确的模型至关重要,这直接影响后续的放大性能和结果。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- UPSCALE_MODEL + - 输出 `UPSCALE_MODEL` 表示已加载并初始化的模型,准备用于图像放大任务。它封装了模型的架构和学习到的参数,允许将模型应用于新数据。这个输出很重要,因为它构成了所有涉及模型的后续处理和分析的基础。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- MODEL_NAME_TEXT + - 输出 `MODEL_NAME_TEXT` 提供了加载模型的名称,这对于日志记录、跟踪或用户界面显示目的非常有用。它为模型提供了一个人类可读的标识符,便于在整个应用程序中进行沟通和引用。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Upscale_Model_Loader: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model_name': (comfy_paths.get_filename_list('upscale_models'),)}} + RETURN_TYPES = ('UPSCALE_MODEL', TEXT_TYPE) + RETURN_NAMES = ('UPSCALE_MODEL', 'MODEL_NAME_TEXT') + FUNCTION = 'load_model' + CATEGORY = 'WAS Suite/Loaders' + + def load_model(self, model_name): + model_path = comfy_paths.get_full_path('upscale_models', model_name) + sd = comfy.utils.load_torch_file(model_path) + out = model_loading.load_state_dict(sd).eval() + return (out, model_name) +``` \ No newline at end of file diff --git a/docs/Upscale Model Switch.md b/docs/Upscale Model Switch.md new file mode 100644 index 0000000..050e124 --- /dev/null +++ b/docs/Upscale Model Switch.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: WAS_Upscale_Model_Input_Switch +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +方法 'upscale_model_switch' 设计用于提供一种条件选择机制,根据布尔标志选择两个放大模型中的一个。它作为一个逻辑开关,决定用于图像放大操作的模型,从而增强了系统的灵活性。 + +# Input types +## Required +- upscale_model_a + - 参数 'upscale_model_a' 表示用于选择的第一个放大模型。它在决策过程中至关重要,因为它是基于布尔标志值可以选择的两个模型之一。 + - Comfy dtype: UPSCALE_MODEL + - Python dtype: Union[torch.nn.Module, Any] +- upscale_model_b + - 参数 'upscale_model_b' 表示第二个放大模型,是节点的替代选项。当布尔标志设置为 False 时,它起着关键作用,因为此时它被选为图像放大。 + - Comfy dtype: UPSCALE_MODEL + - Python dtype: Union[torch.nn.Module, Any] +## Optional +- boolean + - 参数 'boolean' 作为控制标志,影响节点决定返回哪个放大模型。当设置为 True 时,选择 'upscale_model_a';当为 False 时,选择 'upscale_model_b'。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- selected_upscale_model + - 输出 'selected_upscale_model' 表示根据布尔标志选择的放大模型。它很重要,因为它决定了后续的图像放大过程。 + - Comfy dtype: UPSCALE_MODEL + - Python dtype: Union[torch.nn.Module, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Upscale_Model_Input_Switch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'upscale_model_a': ('UPSCALE_MODEL',), 'upscale_model_b': ('UPSCALE_MODEL',), 'boolean': ('BOOLEAN', {'forceInput': True})}} + RETURN_TYPES = ('UPSCALE_MODEL',) + FUNCTION = 'upscale_model_switch' + CATEGORY = 'WAS Suite/Logic' + + def upscale_model_switch(self, upscale_model_a, upscale_model_b, boolean=True): + if boolean: + return (upscale_model_a,) + else: + return (upscale_model_b,) +``` \ No newline at end of file diff --git a/docs/Upscale Tile Calculator.md b/docs/Upscale Tile Calculator.md new file mode 100644 index 0000000..835f807 --- /dev/null +++ b/docs/Upscale Tile Calculator.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: UpscaleTileCalculator +- Category: Mikey/Image +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +UpscaleTileCalculator节点旨在高效计算和管理图像的上采样操作中的平铺。它提供了一种方法,根据图像分辨率和指定的平铺分辨率来确定最优的平铺尺寸,确保上采样后的图像保持其完整性和质量。 + +# Input types +## Required +- image + - 图像参数对于节点的操作至关重要,因为它代表了将要被处理的输入图像。它是影响节点执行和平铺计算结果的基础元素。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- tile_resolution + - tile_resolution参数定义了图像每个平铺的期望分辨率。它在确定平铺尺寸方面起着关键作用,因此影响上采样过程的效率和质量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 上采样后的图像是节点的主要输出,代表上采样操作的处理结果。它标志着节点在提高图像质量方面的功能性成功。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- tile_width + - tile_width参数指示上采样过程后每个平铺计算出的宽度。它很重要,因为它提供了操作中使用的平铺的空间尺寸信息。 + - Comfy dtype: INT + - Python dtype: int +- tile_height + - tile_height参数指定上采样过程后每个平铺计算出的高度。与tile_width一起,它决定了平铺的整体结构,对于理解节点的输出至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class UpscaleTileCalculator: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'tile_resolution': ('INT', {'default': 512, 'min': 1, 'max': 8192, 'step': 8})}} + RETURN_TYPES = ('IMAGE', 'INT', 'INT') + RETURN_NAMES = ('image', 'tile_width', 'tile_height') + FUNCTION = 'calculate' + CATEGORY = 'Mikey/Image' + + def upscale(self, image, upscale_method, width, height, crop): + samples = image.movedim(-1, 1) + s = comfy.utils.common_upscale(samples, width, height, upscale_method, crop) + s = s.movedim(1, -1) + return (s,) + + def resize(self, image, width, height, upscale_method, crop): + (w, h) = find_latent_size(image.shape[2], image.shape[1]) + img = self.upscale(image, upscale_method, w, h, crop)[0] + return (img,) + + def calculate(self, image, tile_resolution): + (width, height) = (image.shape[2], image.shape[1]) + (tile_width, tile_height) = find_tile_dimensions(width, height, 1.0, tile_resolution) + return (image, tile_width, tile_height) +``` \ No newline at end of file diff --git a/docs/Upscale by Factor with Model (WLSH).md b/docs/Upscale by Factor with Model (WLSH).md new file mode 100644 index 0000000..3a8978d --- /dev/null +++ b/docs/Upscale by Factor with Model (WLSH).md @@ -0,0 +1,65 @@ +# Documentation +- Class name: WLSH_Upscale_By_Factor_With_Model +- Category: WLSH Nodes/upscaling +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +WLSH_Upscale_By_Factor_With_Model节点的`upscale`方法旨在通过指定的缩放因子增强输入图像的分辨率。它利用预训练模型执行上采样,并提供'nearest-exact'、'bilinear'或'area'等方法选择来进行上采样过程。该节点的功能集中在提高图像的视觉质量和细节,使其成为图像增强任务中的重要工具。 + +# Input types +## Required +- upscale_model + - 参数`upscale_model`对于节点的操作至关重要,因为它指定了用于上采样图像的预训练模型。模型的选择可以显著影响上采样的质量和节点的执行效率。 + - Comfy dtype: UPSCALE_MODEL + - Python dtype: torch.nn.Module +- image + - 参数`image`代表节点将处理的输入图像。这是一个基本输入,因为节点的全部操作都围绕着增强此图像的分辨率。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- upscale_method + - 参数`upscale_method`确定用于上采样图像的算法。不同的方法可能导致上采样图像的细节和质量水平不同,影响最终输出的外观。 + - Comfy dtype: COMBO['nearest-exact', 'bilinear', 'area'] + - Python dtype: str +- factor + - 参数`factor`定义了输入图像将被上采样的缩放因子。它对于控制图像的最终尺寸至关重要,直接影响节点的输出。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- upscaled_image + - 输出`upscaled_image`代表处理后的图像,具有增强的分辨率。它是节点操作的主要结果,展示了所选上采样模型和方法的有效性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WLSH_Upscale_By_Factor_With_Model: + upscale_methods = ['nearest-exact', 'bilinear', 'area'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'upscale_model': ('UPSCALE_MODEL',), 'image': ('IMAGE',), 'upscale_method': (s.upscale_methods,), 'factor': ('FLOAT', {'default': 2.0, 'min': 0.1, 'max': 8.0, 'step': 0.1})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'upscale' + CATEGORY = 'WLSH Nodes/upscaling' + + def upscale(self, image, upscale_model, upscale_method, factor): + device = model_management.get_torch_device() + upscale_model.to(device) + in_img = image.movedim(-1, -3).to(device) + s = comfy.utils.tiled_scale(in_img, lambda a: upscale_model(a), tile_x=128 + 64, tile_y=128 + 64, overlap=8, upscale_amount=upscale_model.scale) + upscale_model.cpu() + upscaled = torch.clamp(s.movedim(-3, -1), min=0, max=1.0) + old_width = image.shape[2] + old_height = image.shape[1] + new_width = int(old_width * factor) + new_height = int(old_height * factor) + print('Processing image with shape: ', old_width, 'x', old_height, 'to ', new_width, 'x', new_height) + samples = upscaled.movedim(-1, 1) + s = comfy.utils.common_upscale(samples, new_width, new_height, upscale_method, crop='disabled') + s = s.movedim(1, -1) + return (s,) +``` \ No newline at end of file diff --git a/docs/VAE Encode for Inpaint w%2FPadding (WLSH).md b/docs/VAE Encode for Inpaint w%2FPadding (WLSH).md new file mode 100644 index 0000000..776166f --- /dev/null +++ b/docs/VAE Encode for Inpaint w%2FPadding (WLSH).md @@ -0,0 +1,73 @@ +# Documentation +- Class name: WLSH_VAE_Encode_For_Inpaint_Padding +- Category: WLSH Nodes/inpainting +- Output node: False +- Repo Ref: https://github.com/wallish77/wlsh_nodes + +该节点旨在使用变分自编码器(VAE)模型对图像数据进行编码,以便在考虑填充的情况下进行图像修复任务。它处理输入图像和掩码,以生成可用于进一步图像完成或生成的潜在表示。 + +# Input types +## Required +- pixels + - 输入图像像素对于编码过程至关重要,因为它们提供了VAE生成潜在表示所需的原始数据。图像尺寸会根据模型的输入要求进行调整。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- vae + - VAE模型是这个节点的核心组件,负责将输入图像编码到潜在空间中。其配置和权重直接影响编码的质量。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- mask + - 掩码参数对于定义图像中需要修复的感兴趣区域至关重要。它与图像像素一起工作,引导VAE的编码过程。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- mask_padding + - 该参数定义了掩码周围用于侵蚀操作的填充大小,有助于细化编码过程中使用的噪声掩码。它间接影响潜在表示的质量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- samples + - 输出样本代表输入图像的编码潜在表示,是这个节点的主要输出,可用于各种修复或生成任务。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- noise_mask + - 噪声掩码是一个辅助输出,提供有关图像中掩蔽区域的信息。它用于协助修复任务中的重建或生成过程。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WLSH_VAE_Encode_For_Inpaint_Padding: + + def __init__(self, device='cpu'): + self.device = device + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pixels': ('IMAGE',), 'vae': ('VAE',), 'mask': ('MASK',), 'mask_padding': ('INT', {'default': 24, 'min': 6, 'max': 128, 'step': 2})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'encode' + CATEGORY = 'WLSH Nodes/inpainting' + + def encode(self, vae, pixels, mask, mask_padding=3): + x = pixels.shape[1] // 64 * 64 + y = pixels.shape[2] // 64 * 64 + mask = torch.nn.functional.interpolate(mask[None, None], size=(pixels.shape[1], pixels.shape[2]), mode='bilinear')[0][0] + pixels = pixels.clone() + if pixels.shape[1] != x or pixels.shape[2] != y: + pixels = pixels[:, :x, :y, :] + mask = mask[:x, :y] + kernel_tensor = torch.ones((1, 1, mask_padding, mask_padding)) + mask_erosion = torch.clamp(torch.nn.functional.conv2d(mask.round()[None], kernel_tensor, padding=3), 0, 1) + m = 1.0 - mask.round() + for i in range(3): + pixels[:, :, :, i] -= 0.5 + pixels[:, :, :, i] *= m + pixels[:, :, :, i] += 0.5 + t = vae.encode(pixels) + return ({'samples': t, 'noise_mask': mask_erosion[0][:x, :y].round()},) +``` \ No newline at end of file diff --git a/docs/VAE Input Switch.md b/docs/VAE Input Switch.md new file mode 100644 index 0000000..59f5768 --- /dev/null +++ b/docs/VAE Input Switch.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: WAS_VAE_Input_Switch +- Category: WAS Suite/Logic +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +在`WAS_VAE_Input_Switch`节点中的`vae_switch`方法旨在根据布尔标志有条件地选择两个变分自编码器(VAE)实例中的一个。它作为一个逻辑开关,将处理流程导向提供的VAE之一,从而在工作流中实现灵活和有条件的处理。 + +# Input types +## Required +- vae_a + - 参数`vae_a`表示可能被开关选择的第一个变分自编码器(VAE)实例。这是一个关键组件,因为节点的决策过程取决于这个VAE还是另一个将在后续操作中被使用。 + - Comfy dtype: VAE + - Python dtype: comfy.sd.VAE +- vae_b + - 参数`vae_b`表示开关的第二个变分自编码器(VAE)实例,是开关的替代选项。它的包含允许在节点的功能中提供次要的执行路径,提供处理选项的多样性。 + - Comfy dtype: VAE + - Python dtype: comfy.sd.VAE +## Optional +- boolean + - 参数`boolean`作为开关的控制信号,决定`vae_a`或`vae_b`将是节点的输出。它的值直接影响节点的决策过程,将输出引向其中一个VAE实例。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- selected_vae + - 输出`selected_vae`表示根据布尔条件由开关选择的变分自编码器(VAE)实例。它很重要,因为它代表了节点条件逻辑的结果,以及任何后续处理的起点。 + - Comfy dtype: VAE + - Python dtype: comfy.sd.VAE + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_VAE_Input_Switch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'vae_a': ('VAE',), 'vae_b': ('VAE',), 'boolean': ('BOOLEAN', {'forceInput': True})}} + RETURN_TYPES = ('VAE',) + FUNCTION = 'vae_switch' + CATEGORY = 'WAS Suite/Logic' + + def vae_switch(self, vae_a, vae_b, boolean=True): + if boolean: + return (vae_a,) + else: + return (vae_b,) +``` \ No newline at end of file diff --git a/docs/VAEDecodeTiled_TiledDiffusion.md b/docs/VAEDecodeTiled_TiledDiffusion.md new file mode 100644 index 0000000..e2fdb1f --- /dev/null +++ b/docs/VAEDecodeTiled_TiledDiffusion.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: VAEDecodeTiled_TiledDiffusion +- Category: _for_testing +- Output node: False +- Repo Ref: https://github.com/shiimizu/ComfyUI-TiledDiffusion + +该节点旨在使用变分自编码器(VAE)模型从潜在表示中解码和重建图像,强调通过平铺和扩散技术处理大图像。它旨在平衡计算效率和图像质量之间的权衡,为图像重建任务提供稳健的解决方案。 + +# Input types +## Required +- samples + - 输入样本代表节点用于生成重建图像的潜在空间向量。这些至关重要,因为它们构成了图像重建过程的基础。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- vae + - VAE参数指的是节点使用的预训练变分自编码器模型,用于执行解码过程。对于从潜在空间重建图像至关重要。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- tile_size + - 平铺大小参数决定了用于处理图像的平铺的尺寸。它对于优化解码过程中的内存使用和计算效率很重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- fast + - 当启用快速参数时,允许节点以牺牲潜在图像质量为代价进行更快的解码。它影响重建过程中速度和准确性之间的平衡。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- image + - 输出图像是节点解码过程的结果,代表从潜在空间中原始输入的重建版本。它是表示节点主要功能的关键输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class VAEDecodeTiled_TiledDiffusion(TiledVAE): + + @classmethod + def INPUT_TYPES(s): + tile_size = get_rcmd_dec_tsize() * opt_f + return {'required': {'samples': ('LATENT',), 'vae': ('VAE',), 'tile_size': ('INT', {'default': tile_size, 'min': 48 * opt_f, 'max': 4096, 'step': 16}), 'fast': ('BOOLEAN', {'default': True})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'process' + CATEGORY = '_for_testing' + + def __init__(self): + self.is_decoder = True + super().__init__() +``` \ No newline at end of file diff --git a/docs/VAEEncodeForInpaint (WAS).md b/docs/VAEEncodeForInpaint (WAS).md new file mode 100644 index 0000000..b6ccbf1 --- /dev/null +++ b/docs/VAEEncodeForInpaint (WAS).md @@ -0,0 +1,87 @@ +# Documentation +- Class name: WAS_VAEEncodeForInpaint +- Category: latent/inpaint +- Output node: False +- Repo Ref: https://github.com/WASasquatch/WAS_Extras + +WAS_VAEEncodeForInpaint节点旨在将图像像素编码为适合图像修复任务的潜在空间表示。它利用预训练的VAE(变分自编码器)实现这种转换,同时还考虑了一个定义图像修复区域的掩码。该节点的功能集中在为VAE准备输入数据并生成可用于后续修复过程的潜在表示上。 + +# Input types +## Required +- pixels + - ‘pixels’参数是节点处理的原始图像数据。它对编码过程至关重要,因为它是VAE的输入。图像数据的质量和分辨率直接影响生成的潜在表示,进而影响修复结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- vae + - ‘vae’参数代表节点使用的预训练变分自编码器模型,用于将图像数据编码到潜在空间。VAE模型的选择对编码过程和潜在表示的质量有显著影响。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- mask + - ‘mask’参数是一个二进制掩码,用于标识图像中需要修复的区域。它对于指导编码过程专注于图像的相关部分至关重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- mask_offset + - ‘mask_offset’参数允许修改掩码的边界,这对于控制修复的范围很有用。正值扩展掩码,而负值收缩掩码。这个参数间接影响VAE在编码时考虑的区域。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- samples + - ‘samples’输出代表输入图像的编码潜在空间表示。它是编码过程的核心结果,并将作为后续修复任务的输入。这种潜在表示捕获了图像的本质特征,剔除了不必要的细节,并针对修复区域的重建进行了优化。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- noise_mask + - ‘noise_mask’输出是一个二进制掩码,指示了图像中针对修复的区域。它由原始掩码衍生而来,用于确保修复过程仅专注于指定区域。这个掩码对于指导生成修复内容至关重要。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WAS_VAEEncodeForInpaint: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pixels': ('IMAGE',), 'vae': ('VAE',), 'mask': ('MASK',), 'mask_offset': ('INT', {'default': 6, 'min': -128, 'max': 128, 'step': 1})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'encode' + CATEGORY = 'latent/inpaint' + + def encode(self, vae, pixels, mask, mask_offset=6): + x = pixels.shape[1] // 8 * 8 + y = pixels.shape[2] // 8 * 8 + mask = torch.nn.functional.interpolate(mask.reshape((-1, 1, mask.shape[-2], mask.shape[-1])), size=(pixels.shape[1], pixels.shape[2]), mode='bilinear') + pixels = pixels.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 = self.modify_mask(mask, mask_offset) + m = (1.0 - mask_erosion.round()).squeeze(1) + for i in range(3): + pixels[:, :, :, i] -= 0.5 + pixels[:, :, :, i] *= m + pixels[:, :, :, i] += 0.5 + t = vae.encode(pixels) + return ({'samples': t, 'noise_mask': mask_erosion[:, :, :x, :y].round()},) + + def modify_mask(self, mask, modify_by): + if modify_by == 0: + return mask + if modify_by > 0: + kernel_size = 2 * modify_by + 1 + kernel_tensor = torch.ones((1, 1, kernel_size, kernel_size)) + padding = modify_by + modified_mask = torch.clamp(torch.nn.functional.conv2d(mask.round(), kernel_tensor, padding=padding), 0, 1) + else: + kernel_size = 2 * abs(modify_by) + 1 + kernel_tensor = torch.ones((1, 1, kernel_size, kernel_size)) + padding = abs(modify_by) + eroded_mask = torch.nn.functional.conv2d(1 - mask.round(), kernel_tensor, padding=padding) + modified_mask = torch.clamp(1 - eroded_mask, 0, 1) + return modified_mask +``` \ No newline at end of file diff --git a/docs/VAEEncodeTiled_TiledDiffusion.md b/docs/VAEEncodeTiled_TiledDiffusion.md new file mode 100644 index 0000000..0cd5dcf --- /dev/null +++ b/docs/VAEEncodeTiled_TiledDiffusion.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: VAEEncodeTiled_TiledDiffusion +- Category: _for_testing +- Output node: False +- Repo Ref: https://github.com/shiimizu/ComfyUI-TiledDiffusion + +该节点封装了以平铺方式编码和扩散数据的过程,优化了内存使用和处理效率。它旨在通过将输入分割成可管理的平铺块来处理大规模数据转换,从而促进高效的计算和资源分配。 + +# Input types +## Required +- pixels + - 输入的图像数据对于编码和扩散过程至关重要,因为它提供了节点执行转换的原始材料。没有这个输入,节点无法生成潜在表示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- vae + - VAE模型是编码过程的核心,负责将输入数据转换到潜在空间,然后用于进一步的扩散。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- tile_size + - 平铺大小参数决定了输入数据划分的粒度,直接影响编码和扩散过程的效率。必须谨慎选择,以平衡计算资源和内存使用。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- fast + - 当启用快速参数时,允许节点执行某些优化,从而加快编码和扩散过程,尽管可能会有质量上的权衡。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- color_fix + - 当激活此参数时,对输入数据应用颜色校正步骤,确保潜在空间表示更加稳健,不易产生伪影。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- latent + - 输出的潜在表示是输入数据的压缩版本,捕捉了低维空间中的基本特征和结构。它是后续扩散步骤的关键组成部分。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class VAEEncodeTiled_TiledDiffusion(TiledVAE): + + @classmethod + def INPUT_TYPES(s): + fast = True + tile_size = get_rcmd_enc_tsize() + return {'required': {'pixels': ('IMAGE',), 'vae': ('VAE',), 'tile_size': ('INT', {'default': tile_size, 'min': 256, 'max': 4096, 'step': 16}), 'fast': ('BOOLEAN', {'default': fast}), 'color_fix': ('BOOLEAN', {'default': fast})}} + RETURN_TYPES = ('LATENT',) + FUNCTION = 'process' + CATEGORY = '_for_testing' + + def __init__(self): + self.is_decoder = False + super().__init__() +``` \ No newline at end of file diff --git a/docs/VHS_BatchManager.md b/docs/VHS_BatchManager.md new file mode 100644 index 0000000..408319f --- /dev/null +++ b/docs/VHS_BatchManager.md @@ -0,0 +1,85 @@ +# Documentation +- Class name: BatchManager +- Category: Video Helper Suite 🎥🅥🅗🅢 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +BatchManager节点旨在高效管理和组织视频处理任务的帧批次。它通过将大量数据划分为可管理的批次来抽象处理复杂性,确保处理流水线保持高效和流畅。 + +# Input types +## Required +- frames_per_batch + - 参数'frames_per_batch'决定每个批次中要处理的帧数。它对于控制工作量和内存使用至关重要,直接影响视频处理系统的性能和效率。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- prompt + - 提供的'prompt'参数包含批处理可能需要的额外指令或上下文。它可以影响BatchManager节点如何解释和处理输入数据。 + - Comfy dtype: PROMPT + - Python dtype: str +- unique_id + - 参数'unique_id'用于在系统中标识特定批次,确保可以准确跟踪和管理处理过程。它在维护批次处理工作流程的完整性和组织性中起着至关重要的作用。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- meta_batch + - 'meta_batch'输出提供了已处理批次的结构化表示。它封装了结果和元数据,是进一步分析或下游处理任务的关键点。 + - Comfy dtype: VHS_BatchManager + - Python dtype: BatchManager + +# Usage tips +- Infra type: CPU + +# Source code +``` +class BatchManager: + + def __init__(self, frames_per_batch=-1): + self.frames_per_batch = frames_per_batch + self.inputs = {} + self.outputs = {} + self.unique_id = None + self.has_closed_inputs = False + + def reset(self): + self.close_inputs() + for key in self.outputs: + if getattr(self.outputs[key][-1], 'gi_suspended', False): + try: + self.outputs[key][-1].send(None) + except StopIteration: + pass + self.__init__(self.frames_per_batch) + + def has_open_inputs(self): + return len(self.inputs) > 0 + + def close_inputs(self): + for key in self.inputs: + if getattr(self.inputs[key][-1], 'gi_suspended', False): + try: + self.inputs[key][-1].send(1) + except StopIteration: + pass + self.inputs = {} + + @classmethod + def INPUT_TYPES(s): + return {'required': {'frames_per_batch': ('INT', {'default': 16, 'min': 1, 'max': 128, 'step': 1})}, 'hidden': {'prompt': 'PROMPT', 'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('VHS_BatchManager',) + RETURN_NAMES = ('meta_batch',) + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢' + FUNCTION = 'update_batch' + + def update_batch(self, frames_per_batch, prompt=None, unique_id=None): + if unique_id is not None and prompt is not None: + requeue = prompt[unique_id]['inputs'].get('requeue', 0) + else: + requeue = 0 + if requeue == 0: + self.reset() + self.frames_per_batch = frames_per_batch + self.unique_id = unique_id + return (self,) +``` \ No newline at end of file diff --git a/docs/VHS_DuplicateImages.md b/docs/VHS_DuplicateImages.md new file mode 100644 index 0000000..e092380 --- /dev/null +++ b/docs/VHS_DuplicateImages.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: DuplicateImages +- Category: Video Helper Suite 🎥🅥🅗🅢/image +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +DuplicateImages节点旨在将给定的一组图片复制指定的次数。它用于增加图像数据,适用于机器学习等场景,其中更大的数据集可以改善模型训练。节点的功能非常直接:它接受一个图像数组和一个整数乘数,然后返回一个新的数组,其中包含重复给定次数的图像,以及图像的总数。 + +# Input types +## Required +- images + - 'image'参数是DuplicateImages节点的关键输入,因为它代表了将要复制的图像集。节点处理这个输入以创建多个副本,这对于某些图像处理任务或数据增强策略至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- multiply_by + - 'multiply_by'参数决定了'images'输入中的每个图像将被复制多少次。它是一个整数,直接影响输出数据集的大小,因此是节点在数据增强目的中操作的关键因素。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - 'IMAGE'输出参数代表重复的图像数组。这是DuplicateImages节点操作的主要结果,包含了根据'multiply_by'参数重复的所有原始图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- count + - 'count'输出参数提供了重复后的图像总数。这个整数值有助于跟踪数据集的大小,这对于进一步的处理或分析可能很重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DuplicateImages: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'multiply_by': ('INT', {'default': 1, 'min': 1, 'max': BIGMAX, 'step': 1})}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/image' + RETURN_TYPES = ('IMAGE', 'INT') + RETURN_NAMES = ('IMAGE', 'count') + FUNCTION = 'duplicate_input' + + def duplicate_input(self, images: Tensor, multiply_by: int): + full_images = [] + for n in range(0, multiply_by): + full_images.append(images) + new_images = torch.cat(full_images, dim=0) + return (new_images, new_images.size(0)) +``` \ No newline at end of file diff --git a/docs/VHS_DuplicateLatents.md b/docs/VHS_DuplicateLatents.md new file mode 100644 index 0000000..0d8f9de --- /dev/null +++ b/docs/VHS_DuplicateLatents.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: DuplicateLatents +- Category: Video Helper Suite 🎥🅥🅗🅢/latent +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +DuplicateLatents节点旨在复制输入的潜在表示,通过指定的因子有效地增加它们的计数。它的作用是在不改变原始数据完整性的情况下扩大潜在空间操作的数据集大小,从而增强潜在表示在各种应用中的实用性,如训练或数据增强。 + +# Input types +## Required +- latents + - ‘latents’参数是一个包含Tensor对象的字典,代表潜在空间数据。它是节点操作的关键,因为它是将要复制的主要输入。复制过程依赖于此输入的质量和结构,这直接影响节点的输出及其在下游任务中的后续使用。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +## Optional +- multiply_by + - ‘multiply_by’参数决定了潜在表示将被复制的倍数。它在节点的执行中起着重要作用,因为它直接影响输出数据的数量。此参数允许微调数据集的大小,这对于需要特定数量潜在样本的应用来说是必要的。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- LATENT + - 输出'LATENT'是一个包含复制的潜在空间数据的字典。它很重要,因为它代表了根据指定的乘法因子放大的处理后的数据。这个输出已经准备好用于进一步分析或作为需要增加潜在样本数量的其他节点的输入。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- count + - ‘count’输出表示复制过程后的潜在样本总数。这是一个重要的信息,它表明了数据放大的程度。这个计数可以用来做出关于数据处理或模型训练工作流程中后续步骤的明智决策。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DuplicateLatents: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latents': ('LATENT',), 'multiply_by': ('INT', {'default': 1, 'min': 1, 'max': BIGMAX, 'step': 1})}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/latent' + RETURN_TYPES = ('LATENT', 'INT') + RETURN_NAMES = ('LATENT', 'count') + FUNCTION = 'duplicate_input' + + def duplicate_input(self, latents: dict[str, Tensor], multiply_by: int): + new_latents = latents.copy() + full_latents = [] + for n in range(0, multiply_by): + full_latents.append(new_latents['samples']) + new_latents['samples'] = torch.cat(full_latents, dim=0) + return (new_latents, new_latents['samples'].size(0)) +``` \ No newline at end of file diff --git a/docs/VHS_DuplicateMasks.md b/docs/VHS_DuplicateMasks.md new file mode 100644 index 0000000..0338d2e --- /dev/null +++ b/docs/VHS_DuplicateMasks.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: DuplicateMasks +- Category: Video Helper Suite 🎥🅥🅗🅢/mask +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +DuplicateMasks节点旨在复制给定的掩码到指定数量的实例中。它的作用是放大输入掩码,创建多个副本,这些副本可用于需要多个相同掩码的视频处理任务中。 + +# Input types +## Required +- mask + - 掩码参数是DuplicateMasks节点的关键输入。它表示需要复制的掩码。节点的功能围绕创建此掩码的多个实例,这对节点的操作和最终结果至关重要。 + - Comfy dtype: Tensor + - Python dtype: torch.Tensor +## Optional +- multiply_by + - multiply_by参数决定了输入掩码应该被复制的次数。它是一个可选输入,直接影响输出掩码的数量。默认值设置为1,意味着如果没有指定,节点将产生掩码的单个实例。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MASK + - MASK输出是一个包含复制掩码的张量。它是DuplicateMasks节点的主要输出,代表了复制过程的集体结果。 + - Comfy dtype: Tensor + - Python dtype: torch.Tensor +- count + - count输出提供了节点生成的复制掩码的总数。它是一个整数,表示MASK输出中掩码的数量,提供了对执行的复制规模的了解。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class DuplicateMasks: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'multiply_by': ('INT', {'default': 1, 'min': 1, 'max': BIGMAX, 'step': 1})}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/mask' + RETURN_TYPES = ('MASK', 'INT') + RETURN_NAMES = ('MASK', 'count') + FUNCTION = 'duplicate_input' + + def duplicate_input(self, mask: Tensor, multiply_by: int): + full_masks = [] + for n in range(0, multiply_by): + full_masks.append(mask) + new_mask = torch.cat(full_masks, dim=0) + return (new_mask, new_mask.size(0)) +``` \ No newline at end of file diff --git a/docs/VHS_GetImageCount.md b/docs/VHS_GetImageCount.md new file mode 100644 index 0000000..f42d0ec --- /dev/null +++ b/docs/VHS_GetImageCount.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: GetImageCount +- Category: Video Helper Suite 🎥🅥🅗🅢/image +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +GetImageCount节点旨在高效地确定给定数据集中存在的图像总数。它是视频处理工作流中的关键组件,提供了一种直接的方法来了解数据集的大小,而无需深入了解单个图像数据的复杂性。该节点的主要目标是提供一个简洁可靠的计数,这对于规划和管理计算资源至关重要。 + +# Input types +## Required +- images + - 'image'参数是包含图像数据的输入数据集。它是节点操作的基本元素,因为它直接影响计数结果。节点处理此输入以确定图像的总数,这对于各种下游任务(如分析、索引和资源分配)至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Output types +- count + - ‘count’输出提供了节点处理的图像总数。它是一个单一的整数值,表示数据集在图像数量方面的规模。这个输出对于需要知道数据集规模以进行进一步处理或对应用程序需求做出明智决策的用户来说非常重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GetImageCount: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',)}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/image' + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('count',) + FUNCTION = 'count_input' + + def count_input(self, images: Tensor): + return (images.size(0),) +``` \ No newline at end of file diff --git a/docs/VHS_GetLatentCount.md b/docs/VHS_GetLatentCount.md new file mode 100644 index 0000000..bfe571d --- /dev/null +++ b/docs/VHS_GetLatentCount.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: GetLatentCount +- Category: Video Helper Suite 🎥🅥🅗🅢/latent +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +GetLatentCount节点旨在确定给定输入中存在的潜在样本数量。它在视频处理工作流程中发挥着关键作用,通过提供可以用于进一步分析或操作视频数据的基本计数。 + +# Input types +## Required +- latents + - 'latents'参数是一个包含用于视频处理的潜在样本的字典。它对节点的操作至关重要,因为它直接影响节点将返回的样本计数。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] + +# Output types +- count + - 'count'输出提供了节点处理的潜在样本的总数。这个计数很重要,因为它可以用来做出关于视频处理流水线后续步骤的决策。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GetLatentCount: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latents': ('LATENT',)}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/latent' + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('count',) + FUNCTION = 'count_input' + + def count_input(self, latents: dict): + return (latents['samples'].size(0),) +``` \ No newline at end of file diff --git a/docs/VHS_GetMaskCount.md b/docs/VHS_GetMaskCount.md new file mode 100644 index 0000000..f8bd98f --- /dev/null +++ b/docs/VHS_GetMaskCount.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: GetMaskCount +- Category: Video Helper Suite 🎥🅥🅗🅢/mask +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +GetMaskCount 节点旨在处理并计算给定视频帧中存在的掩码数量。它在视频分析中扮演着关键角色,通过提供一种直接的方法来确定掩码的数量,这对于视频处理领域中的各种应用(如目标检测或分割任务)至关重要。 + +# Input types +## Required +- mask + - ‘mask’参数对于 GetMaskCount 节点至关重要,因为它代表了包含要计数的掩码的视频帧。其重要性在于节点的功能完全依赖于输入掩码来执行其计数操作。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- count + - ‘count’输出参数表示在输入视频帧中识别的掩码总数。它很重要,因为它直接反映了节点操作的结果,提供了掩码存在的量化度量。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class GetMaskCount: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',)}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/mask' + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('count',) + FUNCTION = 'count_input' + + def count_input(self, mask: Tensor): + return (mask.size(0),) +``` \ No newline at end of file diff --git a/docs/VHS_LoadAudio.md b/docs/VHS_LoadAudio.md new file mode 100644 index 0000000..5825c39 --- /dev/null +++ b/docs/VHS_LoadAudio.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: LoadAudio +- Category: Video Helper Suite 🎥🅥🅗🅢 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +LoadAudio节点旨在高效地加载和处理音频文件。它能够处理各种音频文件格式,并提供跳转到音频流中特定秒数的功能。此节点对于需要将音频操作或分析作为更大多媒体处理工作流程一部分的应用程序至关重要。 + +# Input types +## Required +- audio_file + - audio_file参数指定要加载的音频文件的路径。这是一个基本参数,因为节点的操作围绕提供的音频文件进行。节点将验证路径并确保文件可访问且在支持的格式中。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- seek_seconds + - seek_seconds参数允许节点从指定的时间偏移(秒)开始处理音频。这在只有音频文件的一部分是相关的情况下非常有用,因此可以提高效率并减少不必要的处理。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- audio + - LoadAudio节点的audio输出代表了已加载并可选处理的音频数据。它是一个关键的输出,因为它输入到多媒体工作流中随后的音频分析或操作阶段。 + - Comfy dtype: VHS_AUDIO + - Python dtype: bytes + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadAudio: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'audio_file': ('STRING', {'default': 'input/', 'vhs_path_extensions': ['wav', 'mp3', 'ogg', 'm4a', 'flac']})}, 'optional': {'seek_seconds': ('FLOAT', {'default': 0, 'min': 0})}} + RETURN_TYPES = ('VHS_AUDIO',) + RETURN_NAMES = ('audio',) + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢' + FUNCTION = 'load_audio' + + def load_audio(self, audio_file, seek_seconds): + if audio_file is None or validate_path(audio_file) != True: + raise Exception('audio_file is not a valid path: ' + audio_file) + audio = get_audio(audio_file, start_time=seek_seconds) + return (lambda : audio,) + + @classmethod + def IS_CHANGED(s, audio_file, seek_seconds): + return hash_path(audio_file) + + @classmethod + def VALIDATE_INPUTS(s, audio_file, **kwargs): + return validate_path(audio_file, allow_none=True) +``` \ No newline at end of file diff --git a/docs/VHS_LoadImages.md b/docs/VHS_LoadImages.md new file mode 100644 index 0000000..154b7e7 --- /dev/null +++ b/docs/VHS_LoadImages.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: LoadImagesFromDirectoryUpload +- Category: Video Helper Suite 🎥🅥🅗🅢 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +LoadImagesFromDirectoryUpload节点旨在从指定目录加载图像数据。它简化了访问和准备图像以进行进一步处理或分析的过程,抽象化了文件处理和目录导航的复杂性。 + +# Input types +## Required +- directory + - ‘directory’参数指定了加载图像的源目录。这对于确定节点将处理的图像数据的范围和内容至关重要。 + - Comfy dtype: str + - Python dtype: str +## Optional +- image_load_cap + - ‘image_load_cap’参数是可选的,它允许限制从目录中加载的图像数量。它提供了一种控制处理数据量的方法,这在优化资源使用方面可能非常重要。 + - Comfy dtype: INT + - Python dtype: int +- skip_first_images + - ‘skip_first_images’参数使节点能够跳过目录开头指定数量的图像。在某些图像与当前任务或分析无关的情况下,这可能很有用。 + - Comfy dtype: INT + - Python dtype: int +- select_every_nth + - ‘select_every_nth’参数用于在由参数值定义的固定间隔中从目录选择图像。在只需要图像子集的情况下,这有助于简化处理过程。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - ‘IMAGE’输出提供了加载的图像数据,这是节点操作的主要结果。它代表了可以进一步操作或分析的视觉内容。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- MASK + - ‘MASK’输出在适用时提供与加载的图像相关联的二进制或分类掩码。这对于需要基于图像内感兴趣区域进行分割或分类的任务非常有用。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- INT + - 如果存在,‘INT’输出类型可能代表与图像相关联的额外数值数据或元数据。它可以提供补充视觉数据的定量信息。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadImagesFromDirectoryUpload: + + @classmethod + def INPUT_TYPES(s): + input_dir = folder_paths.get_input_directory() + directories = [] + for item in os.listdir(input_dir): + if not os.path.isfile(os.path.join(input_dir, item)) and item != 'clipspace': + directories.append(item) + return {'required': {'directory': (directories,)}, 'optional': {'image_load_cap': ('INT', {'default': 0, 'min': 0, 'max': BIGMAX, 'step': 1}), 'skip_first_images': ('INT', {'default': 0, 'min': 0, 'max': BIGMAX, 'step': 1}), 'select_every_nth': ('INT', {'default': 1, 'min': 1, 'max': BIGMAX, 'step': 1})}} + RETURN_TYPES = ('IMAGE', 'MASK', 'INT') + FUNCTION = 'load_images' + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢' + + def load_images(self, directory: str, **kwargs): + return load_images(directory, **kwargs) + + @classmethod + def IS_CHANGED(s, directory: str, **kwargs): + return is_changed_load_images(directory, **kwargs) + + @classmethod + def VALIDATE_INPUTS(s, directory: str, **kwargs): + return validate_load_images(directory) +``` \ No newline at end of file diff --git a/docs/VHS_LoadVideo.md b/docs/VHS_LoadVideo.md new file mode 100644 index 0000000..3602d43 --- /dev/null +++ b/docs/VHS_LoadVideo.md @@ -0,0 +1,103 @@ +# Documentation +- Class name: LoadVideoUpload +- Category: Video Helper Suite 🎥🅥🅗🅢 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +LoadVideoUpload节点旨在高效管理和处理视频文件。它能够从多种来源加载视频,包括本地文件和URL,并提供上采样和操作视频帧的功能。该节点确保视频数据被正确格式化并准备好用于后续处理阶段。 + +# Input types +## Required +- video + - 'video'参数至关重要,因为它指定了要处理的视频文件的来源。它可以是指向本地文件的路径,也可以是指向在线视频的URL。此参数直接影响节点加载和访问视频内容的能力。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- force_rate + - 'force_rate'参数允许调整视频的帧率。这是一个可选设置,可用于确保不同视频之间的帧率一致,这对于某些视频处理任务很重要。 + - Comfy dtype: INT + - Python dtype: int +- force_size + - 'force_size'参数用于指定视频帧的期望分辨率。它提供几种预设选项,并允许设置自定义尺寸,这对于保持纵横比或适应特定的显示要求可能是必要的。 + - Comfy dtype: STRING + - Python dtype: str +- custom_width + - 当需要自定义视频尺寸时,'custom_width'设置视频帧的宽度。这是一个重要的参数,用于视频尺寸调整操作,确保视频适应所需的宽度限制。 + - Comfy dtype: INT + - Python dtype: int +- custom_height + - 'custom_height'参数通过设置视频帧的高度来补充'custom_width'。它在视频尺寸调整中扮演重要角色,特别是当视频内容需要特定的高度要求时。 + - Comfy dtype: INT + - Python dtype: int +- frame_load_cap + - 'frame_load_cap'参数决定了从视频中加载的最大帧数。它有助于控制内存使用和处理时间,特别是处理长视频时。 + - Comfy dtype: INT + - Python dtype: int +- skip_first_frames + - 'skip_first_frames'参数使节点能够跳过视频开头指定数量的帧。这对于从视频处理工作流程中省略不需要的内容或片头很有用。 + - Comfy dtype: INT + - Python dtype: int +- select_every_nth + - 'select_every_nth'参数用于从视频中以规律间隔选择帧。它有助于降低帧率或创建视频内容的摘要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - 'IMAGE'输出以张量的形式提供视频帧,这是一个多维数组,适用于进一步的视频分析和处理。 + - Comfy dtype: TENSOR + - Python dtype: torch.Tensor +- frame_count + - 'frame_count'输出指示从视频中加载的总帧数,这对于了解视频数据的范围至关重要。 + - Comfy dtype: INT + - Python dtype: int +- audio + - 'audio'输出是一个函数,当被调用时,提供对视频的音频流的访问。这可以用于音频分析或与视频帧一起用于进一步处理。 + - Comfy dtype: FUNCTION + - Python dtype: Callable[[], Any] +- video_info + - 'video_info'输出包含有关视频的元数据,如帧率、时长和尺寸。这些信息对于需要了解视频特性的各种视频处理任务非常有价值。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Union[int, float, str]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LoadVideoUpload: + + @classmethod + def INPUT_TYPES(s): + input_dir = folder_paths.get_input_directory() + files = [] + for f in os.listdir(input_dir): + if os.path.isfile(os.path.join(input_dir, f)): + file_parts = f.split('.') + if len(file_parts) > 1 and file_parts[-1] in video_extensions: + files.append(f) + return {'required': {'video': (sorted(files),), 'force_rate': ('INT', {'default': 0, 'min': 0, 'max': 60, 'step': 1}), 'force_size': (['Disabled', 'Custom Height', 'Custom Width', 'Custom', '256x?', '?x256', '256x256', '512x?', '?x512', '512x512'],), 'custom_width': ('INT', {'default': 512, 'min': 0, 'max': DIMMAX, 'step': 8}), 'custom_height': ('INT', {'default': 512, 'min': 0, 'max': DIMMAX, 'step': 8}), 'frame_load_cap': ('INT', {'default': 0, 'min': 0, 'max': BIGMAX, 'step': 1}), 'skip_first_frames': ('INT', {'default': 0, 'min': 0, 'max': BIGMAX, 'step': 1}), 'select_every_nth': ('INT', {'default': 1, 'min': 1, 'max': BIGMAX, 'step': 1})}, 'optional': {'meta_batch': ('VHS_BatchManager',)}, 'hidden': {'unique_id': 'UNIQUE_ID'}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢' + RETURN_TYPES = ('IMAGE', 'INT', 'VHS_AUDIO', 'VHS_VIDEOINFO') + RETURN_NAMES = ('IMAGE', 'frame_count', 'audio', 'video_info') + FUNCTION = 'load_video' + + def load_video(self, **kwargs): + return load_video_cv(**kwargs) + + @classmethod + def IS_CHANGED(s, video, **kwargs): + image_path = folder_paths.get_annotated_filepath(video) + return calculate_file_hash(image_path) + + @classmethod + def VALIDATE_INPUTS(s, video, force_size, **kwargs): + import requests + if video.startswith('http'): + resp = requests.head(video) + if resp.status_code != 200: + return 'Invalid video file: {}'.format(video) + elif not folder_paths.exists_annotated_filepath(video): + return 'Invalid video file: {}'.format(video) + return True +``` \ No newline at end of file diff --git a/docs/VHS_MergeImages.md b/docs/VHS_MergeImages.md new file mode 100644 index 0000000..96fd597 --- /dev/null +++ b/docs/VHS_MergeImages.md @@ -0,0 +1,82 @@ +# Documentation +- Class name: MergeImages +- Category: Video Helper Suite 🎥🅥🅗🅢/image +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +MergeImages 节点的 'merge' 方法旨在将两组图像合并为一个单一的数组。它通过应用基于指定合并策略的缩放和裁剪技术,智能地处理图像尺寸的差异。当需要进一步处理或可视化时,此方法对于准备统一的图像数据集至关重要。 + +# Input types +## Required +- images_A + - 参数 'images_A' 表示要合并的第一组图像。当两组图像之间存在尺寸差异时,它在确定合并后的图像数组的最终尺寸和结构中起着关键作用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- images_B + - 参数 'images_B' 表示要合并的第二组图像。它的尺寸会与 'images_A' 进行协调,以确保输出的一致性,并且对合并后的图像集的最终组成有重要贡献。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- merge_strategy + - 参数 'merge_strategy' 决定如何组合两组图像。它对于解决尺寸不匹配至关重要,并指导缩放和裁剪过程以持合并输出中的视觉一致性。 + - Comfy dtype: str + - Python dtype: str +- scale_method + - 参数 'scale_method' 指定用于调整图像大小以匹配尺寸的技术。它是图像合并过程中的一个关键组成部分,确保图像在不损害质量的情况下被适当缩放。 + - Comfy dtype: str + - Python dtype: str +- crop + - 参数 'crop' 确定在缩放后应如何裁剪图像以适应合并后的图像数组。它对于保持最终合并图像的纵横比和整体视觉吸引力具有重要意义。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- IMAGE + - 输出 'IMAGE' 表示合并后的图像数组,是合并过程的最终结果。它包含了根据指定的合并策略和缩放参数从 'images_A' 和 'images_B' 组合的视觉数据。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- count + - 输出 'count' 提供了合并数组中图像的总数。这个整数值对于依赖于知道确切图像数量的索引和进一步处理步骤具有重要意义。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MergeImages: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images_A': ('IMAGE',), 'images_B': ('IMAGE',), 'merge_strategy': (MergeStrategies.list_all,), 'scale_method': (ScaleMethods.list_all,), 'crop': (CropMethods.list_all,)}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/image' + RETURN_TYPES = ('IMAGE', 'INT') + RETURN_NAMES = ('IMAGE', 'count') + FUNCTION = 'merge' + + def merge(self, images_A: Tensor, images_B: Tensor, merge_strategy: str, scale_method: str, crop: str): + images = [] + if images_A.shape[3] != images_B.shape[3] or images_A.shape[2] != images_B.shape[2]: + images_A = images_A.movedim(-1, 1) + images_B = images_B.movedim(-1, 1) + A_size = images_A.shape[3] * images_A.shape[2] + B_size = images_B.shape[3] * images_B.shape[2] + use_A_as_template = True + if merge_strategy == MergeStrategies.MATCH_A: + pass + elif merge_strategy == MergeStrategies.MATCH_B: + use_A_as_template = False + elif merge_strategy in (MergeStrategies.MATCH_SMALLER, MergeStrategies.MATCH_LARGER): + if A_size <= B_size: + use_A_as_template = True if merge_strategy == MergeStrategies.MATCH_SMALLER else False + if use_A_as_template: + images_B = comfy.utils.common_upscale(images_B, images_A.shape[3], images_A.shape[2], scale_method, crop) + else: + images_A = comfy.utils.common_upscale(images_A, images_B.shape[3], images_B.shape[2], scale_method, crop) + images_A = images_A.movedim(1, -1) + images_B = images_B.movedim(1, -1) + images.append(images_A) + images.append(images_B) + all_images = torch.cat(images, dim=0) + return (all_images, all_images.size(0)) +``` \ No newline at end of file diff --git a/docs/VHS_MergeLatents.md b/docs/VHS_MergeLatents.md new file mode 100644 index 0000000..210c0fa --- /dev/null +++ b/docs/VHS_MergeLatents.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: MergeLatents +- Category: Video Helper Suite 🎥🅥🅗🅢/latent +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +MergeLatents节点旨在将两组潜在表示合并为一个单一的连贯结构。它智能地应用指定的合并策略,以确保来自两组的潜在维度匹配,可能将其中一组缩放到与另一组匹配。该节点在将来自不同来源的信息整合成可以进一步处理或分析的统一格式中发挥关键作用。 + +# Input types +## Required +- latents_A + - 参数'latents_A'代表要合并的第一组潜在表示。它至关重要,因为它构成了合过程所需的一半输入。这些潜在表示的维度和特性显著影响节点的功能。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- latents_B + - 参数'latents_B'包含用于合并的第二组潜在表示。它与'latents_A'同等重要,并且与'latents_A'一起,构成了节点操作的完整输入。节点在合并方面的有效性取决于'latents_A'和'latents_B'的兼容性和对齐。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- merge_strategy + - 参数'merge_strategy'指示如何合并潜在表示。它对于确定节点将遵循的调整大小和对齐过程至关重要,以便将潜在表示组合成一个和谐的结构。 + - Comfy dtype: str + - Python dtype: str +- scale_method + - 参数'scale_method'指定在合并过程中用于缩放潜在表示的方法。它很重要,因为它影响合并后潜在表示的质量和分辨率。 + - Comfy dtype: str + - Python dtype: str +- crop + - 参数'crop'定义了在合并过程中如果需要,应该如何裁剪潜在表示。它在保持合并后潜在表示的完整性中起着至关重要的作用。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- LATENT + - 输出'LATENT'包含合并后的潜在表示。它是节点操作的主要结果,对后续处理或分析具有重要价值。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- count + - 输出'count'提供了合并后的潜在表示的数量。它有助于理解合并操作的范围,并且可以用于进一步处理。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MergeLatents: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latents_A': ('LATENT',), 'latents_B': ('LATENT',), 'merge_strategy': (MergeStrategies.list_all,), 'scale_method': (ScaleMethods.list_all,), 'crop': (CropMethods.list_all,)}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/latent' + RETURN_TYPES = ('LATENT', 'INT') + RETURN_NAMES = ('LATENT', 'count') + FUNCTION = 'merge' + + def merge(self, latents_A: dict, latents_B: dict, merge_strategy: str, scale_method: str, crop: str): + latents = [] + latents_A = latents_A.copy()['samples'] + latents_B = latents_B.copy()['samples'] + if latents_A.shape[3] != latents_B.shape[3] or latents_A.shape[2] != latents_B.shape[2]: + A_size = latents_A.shape[3] * latents_A.shape[2] + B_size = latents_B.shape[3] * latents_B.shape[2] + use_A_as_template = True + if merge_strategy == MergeStrategies.MATCH_A: + pass + elif merge_strategy == MergeStrategies.MATCH_B: + use_A_as_template = False + elif merge_strategy in (MergeStrategies.MATCH_SMALLER, MergeStrategies.MATCH_LARGER): + if A_size <= B_size: + use_A_as_template = True if merge_strategy == MergeStrategies.MATCH_SMALLER else False + if use_A_as_template: + latents_B = comfy.utils.common_upscale(latents_B, latents_A.shape[3], latents_A.shape[2], scale_method, crop) + else: + latents_A = comfy.utils.common_upscale(latents_A, latents_B.shape[3], latents_B.shape[2], scale_method, crop) + latents.append(latents_A) + latents.append(latents_B) + merged = {'samples': torch.cat(latents, dim=0)} + return (merged, len(merged['samples'])) +``` \ No newline at end of file diff --git a/docs/VHS_MergeMasks.md b/docs/VHS_MergeMasks.md new file mode 100644 index 0000000..fe9182c --- /dev/null +++ b/docs/VHS_MergeMasks.md @@ -0,0 +1,82 @@ +# Documentation +- Class name: MergeMasks +- Category: Video Helper Suite 🎥🅥🅗🅢/mask +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +MergeMasks节点旨在将两个输入掩码合并为单个掩码。它通过使用指定的合并策略和缩放方法,智能处理掩码大小的差异,确保掩码的无缝集成。这个节点特别适用于需要将多个掩码层组合用于进一步处理或可视化的应用场景。 + +# Input types +## Required +- mask_A + - 要合并的第一个掩码,是最终组合掩码的关键组成部分。它决定了将第二个掩码集成进去的初始结构。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- mask_B + - 要合并的第二个掩码,它将根据合并策略与第一个掩码对齐并集成。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- merge_strategy + - 定义两个掩码应该如何合并,是通过将一个掩码的尺寸匹配到另一个掩码,还是选择两者中较小或较大的一个。 + - Comfy dtype: str + - Python dtype: str +- scale_method + - 指定用于缩放掩码以匹配尺寸的方法,这对于合并过程至关重要。 + - Comfy dtype: str + - Python dtype: str +- crop + - 指示在缩放过程中要应用的裁剪技术,以确保合并后掩码正确对齐。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- MASK + - 输出是合并过程产生的组合掩码,代表输入掩码的集成结构。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- count + - 提供已合并掩码的数量,提供对最终掩码中集成的层数的了解。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class MergeMasks: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask_A': ('MASK',), 'mask_B': ('MASK',), 'merge_strategy': (MergeStrategies.list_all,), 'scale_method': (ScaleMethods.list_all,), 'crop': (CropMethods.list_all,)}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/mask' + RETURN_TYPES = ('MASK', 'INT') + RETURN_NAMES = ('MASK', 'count') + FUNCTION = 'merge' + + def merge(self, mask_A: Tensor, mask_B: Tensor, merge_strategy: str, scale_method: str, crop: str): + masks = [] + if mask_A.shape[2] != mask_B.shape[2] or mask_A.shape[1] != mask_B.shape[1]: + A_size = mask_A.shape[2] * mask_A.shape[1] + B_size = mask_B.shape[2] * mask_B.shape[1] + use_A_as_template = True + if merge_strategy == MergeStrategies.MATCH_A: + pass + elif merge_strategy == MergeStrategies.MATCH_B: + use_A_as_template = False + elif merge_strategy in (MergeStrategies.MATCH_SMALLER, MergeStrategies.MATCH_LARGER): + if A_size <= B_size: + use_A_as_template = True if merge_strategy == MergeStrategies.MATCH_SMALLER else False + mask_A = torch.unsqueeze(mask_A, 1) + mask_B = torch.unsqueeze(mask_B, 1) + if use_A_as_template: + mask_B = comfy.utils.common_upscale(mask_B, mask_A.shape[3], mask_A.shape[2], scale_method, crop) + else: + mask_A = comfy.utils.common_upscale(mask_A, mask_B.shape[3], mask_B.shape[2], scale_method, crop) + mask_A = torch.squeeze(mask_A, 1) + mask_B = torch.squeeze(mask_B, 1) + masks.append(mask_A) + masks.append(mask_B) + all_masks = torch.cat(masks, dim=0) + return (all_masks, all_masks.size(0)) +``` \ No newline at end of file diff --git a/docs/VHS_PruneOutputs.md b/docs/VHS_PruneOutputs.md new file mode 100644 index 0000000..199b253 --- /dev/null +++ b/docs/VHS_PruneOutputs.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: PruneOutputs +- Category: Video Helper Suite 🎥🅥🅗🅢 +- Output node: True +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +方法 'prune_outputs' 旨在管理和清理视频处理工作流中生成的中间和实用文件。它根据指定的选项智能决定删除哪些文件,确保目录结构保持有序,并且只保留必要的文件。 + +# Input types +## Required +- filenames + - 参数 'filenames' 是一个包含文件名的列表,节点将对其进行操作。它在识别要修剪的文件中起着关键作用。节点使用此列表来确定其操作的范围并执行文件删除过程。 + - Comfy dtype: List[str] + - Python dtype: List[str] +- options + - 参数 'options' 决定了节点的修剪行为。它指定是否删除中间文件、实用文件或两者。此参数至关重要,因为它指导节点关于要删除哪些文件的决策过程。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- None + - 方法 'prune_outputs' 不产生任何输出,因为它的主要功能是删除文件。它是一个实用方法,专注于维护文件系统的清洁和组织,而不是生成新数据或结果。 + - Comfy dtype: NoneType + - Python dtype: NoneType + +# Usage tips +- Infra type: CPU + +# Source code +``` +class PruneOutputs: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'filenames': ('VHS_FILENAMES',), 'options': (['Intermediate', 'Intermediate and Utility'],)}} + RETURN_TYPES = () + OUTPUT_NODE = True + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢' + FUNCTION = 'prune_outputs' + + def prune_outputs(self, filenames, options): + if len(filenames[1]) == 0: + return () + assert len(filenames[1]) <= 3 and len(filenames[1]) >= 2 + delete_list = [] + if options in ['Intermediate', 'Intermediate and Utility', 'All']: + delete_list += filenames[1][1:-1] + if options in ['Intermediate and Utility', 'All']: + delete_list.append(filenames[1][0]) + if options in ['All']: + delete_list.append(filenames[1][-1]) + output_dirs = [os.path.abspath('output'), os.path.abspath('temp')] + for file in delete_list: + if os.path.commonpath([output_dirs[0], file]) != output_dirs[0] and os.path.commonpath([output_dirs[1], file]) != output_dirs[1]: + raise Exception('Tried to prune output from invalid directory: ' + file) + if os.path.exists(file): + os.remove(file) + return () +``` \ No newline at end of file diff --git a/docs/VHS_SelectEveryNthImage.md b/docs/VHS_SelectEveryNthImage.md new file mode 100644 index 0000000..4b50059 --- /dev/null +++ b/docs/VHS_SelectEveryNthImage.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: SelectEveryNthImage +- Category: Video Helper Suite 🎥🅥🅗🅢/image +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +SelectEveryNthImage 节点的 `select_images` 方法旨在从较大的图像集合中高效地选择并检索子集。它通过选择用户指定的每第 n 个图像来操作,允许创建一个保持原始顺序的精简序列。这种功能特别适用于需要一个代表性图像的减少集,而无需处理整个数据集的应用场景。 + +# Input types +## Required +- images + - “images”参数是节点将处理的图像数据集合。它是节点操作的基本,因为它代表了要从中选择图像的输入数据集。节点的执行和结果输出严重依赖于此参数的内容和结构。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- select_every_nth + - “select_every_nth”参数决定了从输入集合中选择图像的频率。它是节点操作中的一个关键决定因素,因为它直接影响着输出中返回的图像数量。该参数确保了选择过程是系统性的和可预测的,基于指定的间隔。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE + - “IMAGE”输出由输入集合中选定的图像子集组成。这个输出非常重要,因为它代表了节点操作的直接结果,为用户提供了基于指定选择标准的精选图像序列。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- count + - “count”输出提供了从输入集合中选择的图像总数。这个信息对用户来说很有价值,因为它有助于理解选择过程的范围,并在原始数据集的背景下评估输出。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SelectEveryNthImage: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'select_every_nth': ('INT', {'default': 1, 'min': 1, 'max': BIGMAX, 'step': 1})}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/image' + RETURN_TYPES = ('IMAGE', 'INT') + RETURN_NAMES = ('IMAGE', 'count') + FUNCTION = 'select_images' + + def select_images(self, images: Tensor, select_every_nth: int): + sub_images = images[0::select_every_nth] + return (sub_images, sub_images.size(0)) +``` \ No newline at end of file diff --git a/docs/VHS_SelectEveryNthLatent.md b/docs/VHS_SelectEveryNthLatent.md new file mode 100644 index 0000000..7239b75 --- /dev/null +++ b/docs/VHS_SelectEveryNthLatent.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: SelectEveryNthLatent +- Category: Video Helper Suite 🎥🅥🅗🅢/latent +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +该节点用于筛选一系列潜在表示,根据用户指定的间隔保留每第n个元素。它旨在降低数据维度,同时保留关键信息,这对于视频分析或生成任务中的后续处理步骤至关重要。 + +# Input types +## Required +- latents + - 输入的潜在表示代表一系列压缩的视频帧或其他视觉数据,需要进行处理。此参数至关重要,因为它构成了节点操作的基础,决定了将被过滤的数据以及随后在下游任务中使用的数据。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- select_every_nth + - 该参数决定了从输入序列中选择潜在表示的间隔。它是决定输出密度和节点计算效率的关键因素,因为它直接影响处理的元素数量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- LATENT + - 输出包含从输入中保留的每第n个元素的压缩潜在表示序列。这个过滤后的数据可以用于进一步分析或生成较低分辨率的视频,同时保持关键的视觉信息。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- count + - 此输出指示在选择过程后保留的潜在表示的数量。它提供了一个度量标准,用于理解数据维度的减少,并且可以用于调整后续的处理步骤。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SelectEveryNthLatent: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latents': ('LATENT',), 'select_every_nth': ('INT', {'default': 1, 'min': 1, 'max': BIGMAX, 'step': 1})}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/latent' + RETURN_TYPES = ('LATENT', 'INT') + RETURN_NAMES = ('LATENT', 'count') + FUNCTION = 'select_latents' + + def select_latents(self, latents: dict, select_every_nth: int): + sub_latents = latents.copy()['samples'][0::select_every_nth] + return ({'samples': sub_latents}, sub_latents.size(0)) +``` \ No newline at end of file diff --git a/docs/VHS_SelectEveryNthMask.md b/docs/VHS_SelectEveryNthMask.md new file mode 100644 index 0000000..23844ab --- /dev/null +++ b/docs/VHS_SelectEveryNthMask.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: SelectEveryNthMask +- Category: Video Helper Suite 🎥🅥🅗🅢/mask +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +SelectEveryNthMask 节点的 `select_masks` 方法旨在通过从输入中选择每第 n 个掩码来处理一系列掩码。这对于需要对掩码子集进行进一步处理或分析的应用场景至关重要。该节点有效地筛选出所需的掩码,确保输出是指定间隔的掩码序列。 + +# Input types +## Required +- mask + - 参数 `mask` 是节点将处理的掩码序列。它在节点的操作中扮演着核心角色,因为它是决定后续输出的主要输入。节点的执行和生成的掩码直接受到输入掩码序列的内容和结构的影响。 + - Comfy dtype: Tensor + - Python dtype: torch.Tensor +- select_every_nth + - 参数 `select_every_nth` 决定了从输入序列中选择掩码的频率。它是节点功能的一个重要组成部分,因为它决定了掩码选择的间隔。节点的输出受此参数的显著影响,因为它控制了返回掩码序列的密度。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MASK + - 输出 `MASK` 是基于指定间隔选择的输入掩码的子集。它代表了节点根据用户的选择标准处理过的掩码的过滤序列。这个输出对于需要减少掩码集以提高效率或特定性的下游任务来说非常重要。 + - Comfy dtype: Tensor + - Python dtype: torch.Tensor +- count + - 输出 `count` 提供了从输入序列中选择的掩码数量。这是一个重要的信息,它表明了选择过程的效率,并且可以用于进一步分析或通知工作流程中的后续步骤。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SelectEveryNthMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'select_every_nth': ('INT', {'default': 1, 'min': 1, 'max': BIGMAX, 'step': 1})}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/mask' + RETURN_TYPES = ('MASK', 'INT') + RETURN_NAMES = ('MASK', 'count') + FUNCTION = 'select_masks' + + def select_masks(self, mask: Tensor, select_every_nth: int): + sub_mask = mask[0::select_every_nth] + return (sub_mask, sub_mask.size(0)) +``` \ No newline at end of file diff --git a/docs/VHS_SplitImages.md b/docs/VHS_SplitImages.md new file mode 100644 index 0000000..8ef70aa --- /dev/null +++ b/docs/VHS_SplitImages.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: SplitImages +- Category: Video Helper Suite 🎥🅥🅗🅢/image +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +SplitImages节点旨在将一系列图像根据指定的索引分割成两个不同的组。它在图像处理工作流程中扮演着关键角色,其中数据的分割对于后续操作至关重要,如分析、排序或对不同子集进行特殊处理。 + +# Input types +## Required +- images + - 'image'参数是节点将处理的图像数据集合。它是节点操作的基础,因为它决定了将要被分割的内容。该参数对节点执行的影响是直接的,因为节点的全部逻辑都围绕着对这一输入进行分割。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- split_index + - 'split_index'参数定义了输入图像被分成两个组的位置。它对于确定每个组的大小至关重要,因此影响节点操作的结果。除非另有指定,否则默认值确保了平衡的分割。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- IMAGE_A + - 'IMAGE_A'输出包含了分割操作结果中的第一组图像。它代表了原始图像集合的一部分,对于进一步的处理或分析具有重要意义。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- A_count + - 'A_count'输出提供了第一组图像的数量,这是由分割操作确定的。这个计数对于跟踪图像的分布或需要知道组大小的下游处理很重要。 + - Comfy dtype: INT + - Python dtype: int +- IMAGE_B + - 'IMAGE_B'输出保存了分割后的第二组图像。它是'IMAGE_A'的对应部分,对于可能涉及对两组进行不同处理或评估的后续步骤同样重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- B_count + - 'B_count'输出表明了分割后进入第二组的图像数量。这个信息对于理解数据集的划分很有价值,可以为进一步的分析或处理步骤提供信息。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SplitImages: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'split_index': ('INT', {'default': 0, 'step': 1, 'min': BIGMIN, 'max': BIGMAX})}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/image' + RETURN_TYPES = ('IMAGE', 'INT', 'IMAGE', 'INT') + RETURN_NAMES = ('IMAGE_A', 'A_count', 'IMAGE_B', 'B_count') + FUNCTION = 'split_images' + + def split_images(self, images: Tensor, split_index: int): + group_a = images[:split_index] + group_b = images[split_index:] + return (group_a, group_a.size(0), group_b, group_b.size(0)) +``` \ No newline at end of file diff --git a/docs/VHS_SplitLatents.md b/docs/VHS_SplitLatents.md new file mode 100644 index 0000000..091e896 --- /dev/null +++ b/docs/VHS_SplitLatents.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: SplitLatents +- Category: Video Helper Suite 🎥🅥🅗🅢/latent +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +SplitLatents节点旨在将给定的一组潜在变量根据指定的索引分割成两个不同的组。它在管理和组织潜在数据中扮演着关键角色,允许对视频相关的潜在信息进行更精细的控制和操作。 + +# Input types +## Required +- latents + - 'latents'参数是一个包含'samples'的字典,代表要被分割的潜在变量。它对节点的操作至关重要,因为它决定了将要被分割的数据。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +## Optional +- split_index + - 'split_index'参数定义了潜在变量将被分割的位置。它很重要,因为它决定了分配给每个组的样本数量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- LATENT_A + - 第一个输出'LATENT_A',在分割操作后包含第一组的潜在变量。它具有重要的价值,因为它代表了原始潜在数据的一部分。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- A_count + - 'A_count'输出代表了第一组中潜在变量的数量。它很重要,因为它提供了分割的数量度量。 + - Comfy dtype: INT + - Python dtype: int +- LATENT_B + - 'LATENT_B'输出,在分割操作后包含第二组的潜在变量。它很重要,因为它代表了原始潜在数据的剩余部分。 + - Comfy dtype: LATENT + - Python dtype: Dict[str, torch.Tensor] +- B_count + - 'B_count'输出代表了第二组中潜在变量的数量。它很重要,因为它与'A_count'互补,提供了分割的完整度量。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SplitLatents: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'latents': ('LATENT',), 'split_index': ('INT', {'default': 0, 'step': 1, 'min': BIGMIN, 'max': BIGMAX})}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/latent' + RETURN_TYPES = ('LATENT', 'INT', 'LATENT', 'INT') + RETURN_NAMES = ('LATENT_A', 'A_count', 'LATENT_B', 'B_count') + FUNCTION = 'split_latents' + + def split_latents(self, latents: dict, split_index: int): + latents = latents.copy() + group_a = latents['samples'][:split_index] + group_b = latents['samples'][split_index:] + group_a_latent = {'samples': group_a} + group_b_latent = {'samples': group_b} + return (group_a_latent, group_a.size(0), group_b_latent, group_b.size(0)) +``` \ No newline at end of file diff --git a/docs/VHS_SplitMasks.md b/docs/VHS_SplitMasks.md new file mode 100644 index 0000000..016292b --- /dev/null +++ b/docs/VHS_SplitMasks.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: SplitMasks +- Category: Video Helper Suite 🎥🅥🅗🅢/mask +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +SplitMasks节点旨在将给定的掩码张量根据指定的索引分成两个不同的组。它用于对输入数据进行分段,允许对每个组进行单独的分析或处理。此节点对于需要操作视频掩码的应用程序至关重要,例如对象跟踪或分割任务。 + +# Input types +## Required +- mask + - 参数'mask'是SplitMasks节点的主要输入,代表要被分割的视频掩码。它至关重要,因为它决定了将被分段的数据。掩码的结构和内容直接影响节点的操作和分割结果。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +## Optional +- split_index + - 参数'split_index'定义了输入掩码将被分割的位置。它在确定分割操作中每个结果组的大小中起着关键作用。分割的有效性在很大程度上依赖于这个索引的适当选择。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- MASK_A + - 输出'MASK_A'代表分割掩码的第一组。它很重要,因为它允许对视频掩码的初始段进行单独处理或分析。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- A_count + - 输出'A_count'提供了分割掩码第一组中元素的数量,提供了对初始段大小的了解。 + - Comfy dtype: INT + - Python dtype: int +- MASK_B + - 输出'MASK_B'对应于分割掩码的第二组,允许对视频掩码的后续段进行不同的处理或检查。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- B_count + - 输出'B_count'指示分割掩码第二组中的元素数量,突出了后一段的大小。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class SplitMasks: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'mask': ('MASK',), 'split_index': ('INT', {'default': 0, 'step': 1, 'min': BIGMIN, 'max': BIGMAX})}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/mask' + RETURN_TYPES = ('MASK', 'INT', 'MASK', 'INT') + RETURN_NAMES = ('MASK_A', 'A_count', 'MASK_B', 'B_count') + FUNCTION = 'split_masks' + + def split_masks(self, mask: Tensor, split_index: int): + group_a = mask[:split_index] + group_b = mask[split_index:] + return (group_a, group_a.size(0), group_b, group_b.size(0)) +``` \ No newline at end of file diff --git a/docs/VHS_VAEDecodeBatched.md b/docs/VHS_VAEDecodeBatched.md new file mode 100644 index 0000000..8cc4cdf --- /dev/null +++ b/docs/VHS_VAEDecodeBatched.md @@ -0,0 +1,50 @@ +# Documentation +- Class name: VAEDecodeBatched +- Category: Video Helper Suite 🎥🅥🅗🅢/batched nodes +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +VAEDecodeBatched节点旨在使用变分自编码器(VAE)模型对潜在样本进行批量解码。它通过批量处理多个样本来高效地重建图像,这对于大型数据集或计算资源有限的情况特别有用。 + +# Input types +## Required +- samples + - 'samplse'参数是VAEDecodeBatched节点的关键输入,因为它包含了需要解码成图像的潜在表示。潜在样本的质量和结构直接影响节点产生的输出图像。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- vae + - 'vae'参数指定了节点将用于解码潜在样本的变分自编码器模型。模型的架构和训练权重对于生成高质量的重建图像至关重要。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +## Optional +- per_batch + - 'per_batch'参数决定了解码过程中每个批次处理的样本数量。它对于平衡计算效率和内存使用之间的权衡非常重要,尤其是在处理大型数据集时。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- decoded_images + - 'decoded_images'输出是一个包含重建图像的张量,这些图像是从解码输入潜在样本得到的。它代表了VAEDecodeBatched节点操作的主要结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class VAEDecodeBatched: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'samples': ('LATENT',), 'vae': ('VAE',), 'per_batch': ('INT', {'default': 16, 'min': 1})}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/batched nodes' + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'decode' + + def decode(self, vae, samples, per_batch): + decoded = [] + for start_idx in range(0, samples['samples'].shape[0], per_batch): + decoded.append(vae.decode(samples['samples'][start_idx:start_idx + per_batch])) + return (torch.cat(decoded, dim=0),) +``` \ No newline at end of file diff --git a/docs/VHS_VAEEncodeBatched.md b/docs/VHS_VAEEncodeBatched.md new file mode 100644 index 0000000..0a68f27 --- /dev/null +++ b/docs/VHS_VAEEncodeBatched.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: VAEEncodeBatched +- Category: Video Helper Suite 🎥🅥🅗🅢/batched nodes +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +VAEEncodeBatched节点旨在使用变分自编码器(VAE)高效地将视频帧批次编码为潜在空间表示。它以指定的批次大小处理帧,以优化计算资源和吞吐量,使其适合处理大量视频数据。 + +# Input types +## Required +- pixels + - ‘pixels’参数是VAEEncodeBatched节点的关键输入,因为它代表了需要编码的原始视频帧。其高效处理对节点的性能和生成的潜在空间表示的质量至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- vae + - ‘vae’参数指定了节点将用于编码视频帧的变分自编码器模型。它对于确定帧编码的潜在空间的结构和特性至关重要。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +## Optional +- per_batch + - ‘per_batch’参数定义了节点要处理的每个像素批次的大小。它对于管理内存使用和计算效率很重要,尤其是在处理高分辨率或大量视频帧时。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- samples + - VAEEncodeBatched节点的‘samples’输出包含输入视频帧的编码潜在空间表示。这个输出很重要,因为它构成了下游任务中进一步分析或处理的基础。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class VAEEncodeBatched: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pixels': ('IMAGE',), 'vae': ('VAE',), 'per_batch': ('INT', {'default': 16, 'min': 1})}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢/batched nodes' + RETURN_TYPES = ('LATENT',) + FUNCTION = 'encode' + + def encode(self, vae, pixels, per_batch): + t = [] + for start_idx in range(0, pixels.shape[0], per_batch): + try: + sub_pixels = vae.vae_encode_crop_pixels(pixels[start_idx:start_idx + per_batch]) + except: + sub_pixels = VAEEncode.vae_encode_crop_pixels(pixels[start_idx:start_idx + per_batch]) + t.append(vae.encode(sub_pixels[:, :, :, :3])) + return ({'samples': torch.cat(t, dim=0)},) +``` \ No newline at end of file diff --git a/docs/VHS_VideoCombine.md b/docs/VHS_VideoCombine.md new file mode 100644 index 0000000..b5af840 --- /dev/null +++ b/docs/VHS_VideoCombine.md @@ -0,0 +1,220 @@ +# Documentation +- Class name: VideoCombine +- Category: Video Helper Suite 🎥🅥🅗🅢 +- Output node: True +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +combine_video 方法旨在将一系列图像合并成视频格式。它处理各种参数,如帧率、循环计数和文件格式,以创建定制的视频输出。该方法能够以 GIF 和 WebP 等格式生成视频,并且还支持音频集成。 + +# Input types +## Required +- images + - images 参数是构成视频视觉内容的图像数据序列。它至关重要,因为它决定了最终视频输出的帧。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +- frame_rate + - frame_rate 参数设置视频每秒的帧数,影响视频播放的速度。 + - Comfy dtype: FLOAT + - Python dtype: int +- loop_count + - loop_count 决定视频重复的次数。值为 0 表示视频不会循环。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- filename_prefix + - filename_prefix 用于创建输出视频文件的唯一标识符,有助于文件管理。 + - Comfy dtype: STRING + - Python dtype: str +- format + - format 参数指定输出视频的格式。它可以是 GIF 或 WebP 这样的图像格式,或者是自定义的视频格式。 + - Comfy dtype: COMBO[image/gif, image/webp, video/...] + - Python dtype: str +- pingpong + - 当设置为 True 时,pingpong 参数通过反转交替帧的顺序来创建乒乓效应。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- save_output + - save_output 参数指示是否应将结果视频保存到输出目录。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- Filenames + - Filenames 输出提供了生成的视频文件的路径,允许用户根据需要访问和使用它们。 + - Comfy dtype: VHS_FILENAMES + - Python dtype: Tuple[bool, List[str]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class VideoCombine: + + @classmethod + def INPUT_TYPES(s): + ffmpeg_formats = get_video_formats() + return {'required': {'images': ('IMAGE',), 'frame_rate': ('FLOAT', {'default': 8, 'min': 1, 'step': 1}), 'loop_count': ('INT', {'default': 0, 'min': 0, 'max': 100, 'step': 1}), 'filename_prefix': ('STRING', {'default': 'AnimateDiff'}), 'format': (['image/gif', 'image/webp'] + ffmpeg_formats,), 'pingpong': ('BOOLEAN', {'default': False}), 'save_output': ('BOOLEAN', {'default': True})}, 'optional': {'audio': ('VHS_AUDIO',), 'meta_batch': ('VHS_BatchManager',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('VHS_FILENAMES',) + RETURN_NAMES = ('Filenames',) + OUTPUT_NODE = True + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢' + FUNCTION = 'combine_video' + + def combine_video(self, images, frame_rate: int, loop_count: int, filename_prefix='AnimateDiff', format='image/gif', pingpong=False, save_output=True, prompt=None, extra_pnginfo=None, audio=None, unique_id=None, manual_format_widgets=None, meta_batch=None): + output_dir = folder_paths.get_output_directory() if save_output else folder_paths.get_temp_directory() + (full_output_folder, filename, _, subfolder, _) = folder_paths.get_save_image_path(filename_prefix, output_dir) + output_files = [] + metadata = PngInfo() + video_metadata = {} + if prompt is not None: + metadata.add_text('prompt', json.dumps(prompt)) + video_metadata['prompt'] = prompt + if extra_pnginfo is not None: + for x in extra_pnginfo: + metadata.add_text(x, json.dumps(extra_pnginfo[x])) + video_metadata[x] = extra_pnginfo[x] + metadata.add_text('CreationTime', datetime.datetime.now().isoformat(' ')[:19]) + if meta_batch is not None and unique_id in meta_batch.outputs: + (counter, output_process) = meta_batch.outputs[unique_id] + else: + max_counter = 0 + matcher = re.compile(f'{re.escape(filename)}_(\\d+)\\D*\\..+', re.IGNORECASE) + for existing_file in os.listdir(full_output_folder): + match = matcher.fullmatch(existing_file) + if match: + file_counter = int(match.group(1)) + if file_counter > max_counter: + max_counter = file_counter + counter = max_counter + 1 + output_process = None + file = f'{filename}_{counter:05}.png' + file_path = os.path.join(full_output_folder, file) + Image.fromarray(tensor_to_bytes(images[0])).save(file_path, pnginfo=metadata, compress_level=4) + output_files.append(file_path) + (format_type, format_ext) = format.split('/') + if format_type == 'image': + if meta_batch is not None: + raise Exception("Pillow('image/') formats are not compatible with batched output") + image_kwargs = {} + if format_ext == 'gif': + image_kwargs['disposal'] = 2 + if format_ext == 'webp': + exif = Image.Exif() + exif[ExifTags.IFD.Exif] = {36867: datetime.datetime.now().isoformat(' ')[:19]} + image_kwargs['exif'] = exif + file = f'{filename}_{counter:05}.{format_ext}' + file_path = os.path.join(full_output_folder, file) + if pingpong: + images = to_pingpong(images) + frames = map(lambda x: Image.fromarray(tensor_to_bytes(x)), images) + next(frames).save(file_path, format=format_ext.upper(), save_all=True, append_images=frames, duration=round(1000 / frame_rate), loop=loop_count, compress_level=4, **image_kwargs) + output_files.append(file_path) + else: + if ffmpeg_path is None: + raise ProcessLookupError(f"ffmpeg is required for video outputs and could not be found.\nIn order to use video outputs, you must either:\n- Install imageoio-ffmpeg with pip,\n- Place a ffmpeg executable in {os.path.abspath('')}, or\n- Install ffmpeg and add it to the system path.") + kwargs = None + if manual_format_widgets is None: + if prompt is not None: + kwargs = prompt[unique_id]['inputs'] + else: + manual_format_widgets = {} + if kwargs is None: + kwargs = get_format_widget_defaults(format_ext) + missing = {} + for k in kwargs.keys(): + if k in manual_format_widgets: + kwargs[k] = manual_format_widgets[k] + else: + missing[k] = kwargs[k] + if len(missing) > 0: + logger.warn('Extra format values were not provided, the following defaults will be used: ' + str(kwargs) + '\nThis is likely due to usage of ComfyUI-to-python. These values can be manually set by supplying a manual_format_widgets argument') + video_format = apply_format_widgets(format_ext, kwargs) + has_alpha = images[0].shape[-1] == 4 + dimensions = f'{len(images[0][0])}x{len(images[0])}' + if loop_count > 0: + loop_args = ['-vf', 'loop=loop=' + str(loop_count) + ':size=' + str(len(images))] + else: + loop_args = [] + if pingpong: + if meta_batch is not None: + logger.error('pingpong is incompatible with batched output') + images = to_pingpong(images) + if video_format.get('input_color_depth', '8bit') == '16bit': + images = map(tensor_to_shorts, images) + if has_alpha: + i_pix_fmt = 'rgba64' + else: + i_pix_fmt = 'rgb48' + else: + images = map(tensor_to_bytes, images) + if has_alpha: + i_pix_fmt = 'rgba' + else: + i_pix_fmt = 'rgb24' + file = f"{filename}_{counter:05}.{video_format['extension']}" + file_path = os.path.join(full_output_folder, file) + bitrate_arg = [] + bitrate = video_format.get('bitrate') + if bitrate is not None: + bitrate_arg = ['-b:v', str(bitrate) + 'M' if video_format.get('megabit') == 'True' else str(bitrate) + 'K'] + args = [ffmpeg_path, '-v', 'error', '-f', 'rawvideo', '-pix_fmt', i_pix_fmt, '-s', dimensions, '-r', str(frame_rate), '-i', '-'] + loop_args + video_format['main_pass'] + bitrate_arg + env = os.environ.copy() + if 'environment' in video_format: + env.update(video_format['environment']) + if output_process is None: + output_process = ffmpeg_process(args, video_format, video_metadata, file_path, env) + output_process.send(None) + if meta_batch is not None: + meta_batch.outputs[unique_id] = (counter, output_process) + for image in images: + output_process.send(image.tobytes()) + if meta_batch is not None: + requeue_workflow((meta_batch.unique_id, not meta_batch.has_closed_inputs)) + if meta_batch is None or meta_batch.has_closed_inputs: + try: + output_process.send(None) + except StopIteration: + pass + if meta_batch is not None: + meta_batch.outputs.pop(unique_id) + if len(meta_batch.outputs) == 0: + meta_batch.reset() + else: + return {'ui': {'unfinished_batch': [True]}, 'result': ((save_output, []),)} + output_files.append(file_path) + if 'gifski_pass' in video_format: + gif_output = f'{filename}_{counter:05}.gif' + gif_output_path = os.path.join(full_output_folder, gif_output) + gifski_args = [gifski_path] + video_format['gifski_pass'] + ['-o', gif_output_path, file_path] + try: + res = subprocess.run(gifski_args, env=env, check=True, capture_output=True) + except subprocess.CalledProcessError as e: + raise Exception('An error occured in the gifski subprocess:\n' + e.stderr.decode('utf-8')) + if res.stderr: + print(res.stderr.decode('utf-8'), end='', file=sys.stderr) + format = 'image/gif' + output_files.append(gif_output_path) + file = gif_output + elif audio is not None and audio() is not False: + output_file_with_audio = f"{filename}_{counter:05}-audio.{video_format['extension']}" + output_file_with_audio_path = os.path.join(full_output_folder, output_file_with_audio) + if 'audio_pass' not in video_format: + logger.warn('Selected video format does not have explicit audio support') + video_format['audio_pass'] = ['-c:a', 'libopus'] + mux_args = [ffmpeg_path, '-v', 'error', '-n', '-i', file_path, '-i', '-', '-c:v', 'copy'] + video_format['audio_pass'] + ['-af', 'apad', '-shortest', output_file_with_audio_path] + try: + res = subprocess.run(mux_args, input=audio(), env=env, capture_output=True, check=True) + except subprocess.CalledProcessError as e: + raise Exception('An error occured in the ffmpeg subprocess:\n' + e.stderr.decode('utf-8')) + if res.stderr: + print(res.stderr.decode('utf-8'), end='', file=sys.stderr) + output_files.append(output_file_with_audio_path) + file = output_file_with_audio + previews = [{'filename': file, 'subfolder': subfolder, 'type': 'output' if save_output else 'temp', 'format': format}] + return {'ui': {'gifs': previews}, 'result': ((save_output, output_files),)} + + @classmethod + def VALIDATE_INPUTS(self, format, **kwargs): + return True +``` \ No newline at end of file diff --git a/docs/VHS_VideoInfo.md b/docs/VHS_VideoInfo.md new file mode 100644 index 0000000..52b7ee0 --- /dev/null +++ b/docs/VHS_VideoInfo.md @@ -0,0 +1,81 @@ +# Documentation +- Class name: VideoInfo +- Category: Video Helper Suite 🎥🅥🅗🅢 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +VideoInfo节点的'get_video_info'方法旨在从提供的视频信息字典中提取并返回关键的视频信息。它专注于提供一组简洁的视频属性,例如帧率、帧数、时长和尺寸,适用于视频的源状态和加载后状态。该方法作为工具,用于标准化和简化访问视频元数据的过程,这对于各种视频处理任务至关重要。 + +# Input types +## Required +- video_info + - 'video_info'参数至关重要,因为它是节点所需的视频元数据的来源。它包含了视频的详细属性,如帧率、帧数和尺寸,无论是在原始状态还是加载后状态。此参数对于节点执行提取和提供视频信息的功能至关重要。 + - Comfy dtype: VHS_VIDEOINFO + - Python dtype: Dict[str, Union[float, int]] + +# Output types +- source_fps + - 'source_fps'输出提供原始视频源的每秒帧数,这是理解视频播放速度的一个基本参数。 + - Comfy dtype: FLOAT + - Python dtype: float +- source_frame_count + - 'source_frame_count'输出指示原始视频中的总帧数,提供了视频长度在帧组成方面的洞察。 + - Comfy dtype: INT + - Python dtype: int +- source_duration + - 'source_duration'输出表示原始视频的持续时间,以秒为单位,允许评估视频的时间长度。 + - Comfy dtype: FLOAT + - Python dtype: float +- source_width + - 'source_width'输出提供视频的宽度,以像素为单位,这是视频分辨率的关键维度之一。 + - Comfy dtype: INT + - Python dtype: int +- source_height + - 'source_height'输出指定视频的高度,以像素为单位,与宽度一起定义视频的分辨率。 + - Comfy dtype: INT + - Python dtype: int +- loaded_fps + - 'loaded_fps'输出表示视频加载后的每秒帧数,可能由于处理或播放调整与源视频不同。 + - Comfy dtype: FLOAT + - Python dtype: float +- loaded_frame_count + - 'loaded_frame_count'输出反映了视频加载后的总帧数,可能会受到视频处理操作的影响。 + - Comfy dtype: INT + - Python dtype: int +- loaded_duration + - 'loaded_duration'输出表示视频加载后的持续时间,可能由于播放速度变化或编辑而与原始视频不同。 + - Comfy dtype: FLOAT + - Python dtype: float +- loaded_width + - 'loaded_width'输出提供视频加载后的宽度,可能由于缩放或调整大小操作与源视频不同。 + - Comfy dtype: INT + - Python dtype: int +- loaded_height + - 'loaded_height'输出指定视频加载后的高度,可能由于视频处理而与源视频的尺寸不同。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class VideoInfo: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'video_info': ('VHS_VIDEOINFO',)}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢' + RETURN_TYPES = ('FLOAT', 'INT', 'FLOAT', 'INT', 'INT', 'FLOAT', 'INT', 'FLOAT', 'INT', 'INT') + RETURN_NAMES = ('source_fps🟨', 'source_frame_count🟨', 'source_duration🟨', 'source_width🟨', 'source_height🟨', 'loaded_fps🟦', 'loaded_frame_count🟦', 'loaded_duration🟦', 'loaded_width🟦', 'loaded_height🟦') + FUNCTION = 'get_video_info' + + def get_video_info(self, video_info): + keys = ['fps', 'frame_count', 'duration', 'width', 'height'] + source_info = [] + loaded_info = [] + for key in keys: + source_info.append(video_info[f'source_{key}']) + loaded_info.append(video_info[f'loaded_{key}']) + return (*source_info, *loaded_info) +``` \ No newline at end of file diff --git a/docs/VHS_VideoInfoLoaded.md b/docs/VHS_VideoInfoLoaded.md new file mode 100644 index 0000000..05f5cda --- /dev/null +++ b/docs/VHS_VideoInfoLoaded.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: VideoInfoLoaded +- Category: Video Helper Suite 🎥🅥🅗🅢 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +VideoInfoLoaded节点的'get_video_info'方法旨在提取并返回视频的关键信息,包括每秒帧数(fps)、帧数、时长、宽度和高度。此节点在提供视频元数据的结构化摘要中起着关键作用,这对于进一步的视频处理和分析任务至关重要。 + +# Input types +## Required +- video_info + - 'video_info'参数是VideoInfoLoaded节点的关键输入,因为它包含了节点运行所需的已加载视频元数据。它直接影响节点提取和返回准确视频信息的能力。 + - Comfy dtype: VHS_VIDEOINFO + - Python dtype: Dict[str, Union[float, int]] + +# Output types +- fps + - 'fps'输出代表视频的每秒帧数,这是理解视频播放速度的关键参数,对于视频编辑和播放兼容性至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- frame_count + - 'frame_count'输出提供了视频中的总帧数,这对于估计视频的时长以及各种分析和处理工作流程至关重要。 + - Comfy dtype: INT + - Python dtype: int +- duration + - 'duration'输出表示视频的总长度,以秒为单位,这是视频制作中用于计时和同步的基本信息。 + - Comfy dtype: FLOAT + - Python dtype: float +- width + - 'width'输出表示视频的宽度,以像素为单位,与高度一起决定了视频的宽高比,这对于显示和格式考虑很重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - 'height'输出指定了视频的高度,以像素为单位,与宽度相辅相成,定义了视频的整体分辨率,是视频视觉清晰度的关键因素。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class VideoInfoLoaded: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'video_info': ('VHS_VIDEOINFO',)}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢' + RETURN_TYPES = ('FLOAT', 'INT', 'FLOAT', 'INT', 'INT') + RETURN_NAMES = ('fps🟦', 'frame_count🟦', 'duration🟦', 'width🟦', 'height🟦') + FUNCTION = 'get_video_info' + + def get_video_info(self, video_info): + keys = ['fps', 'frame_count', 'duration', 'width', 'height'] + loaded_info = [] + for key in keys: + loaded_info.append(video_info[f'loaded_{key}']) + return (*loaded_info,) +``` \ No newline at end of file diff --git a/docs/VHS_VideoInfoSource.md b/docs/VHS_VideoInfoSource.md new file mode 100644 index 0000000..e553bc9 --- /dev/null +++ b/docs/VHS_VideoInfoSource.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: VideoInfoSource +- Category: Video Helper Suite 🎥🅥🅗🅢 +- Output node: False +- Repo Ref: https://github.com/Kosinkadink/ComfyUI-VideoHelperSuite.git + +该节点旨在提取和提供视频源的基本信息,如每秒帧数、总帧数、持续时间和尺寸。它是理解和进一步处理及分析视频数据的基础特性的重要工具。 + +# Input types +## Required +- video_info + - video_info参数是一个包含视频源元数据的结构化对象。它对于节点正确运行和提供准确的视频信息至关重要,因为它直接影响提取的数据和后续分析。 + - Comfy dtype: VHS_VIDEOINFO + - Python dtype: VHS_VIDEOINFO + +# Output types +- fps + - fps输出代表视频的每秒帧数,这是视频播放和编辑的一个关键参数,影响视频的流畅度和时间分辨率。 + - Comfy dtype: FLOAT + - Python dtype: float +- frame_count + - frame_count输出指示视频中的总帧数,这对于视频处理任务如帧提取、动画和基于帧的分析很重要。 + - Comfy dtype: INT + - Python dtype: int +- duration + - duration输出提供视频的总时长(秒),这是规划与视频相关的任务和理解内容的时间范围的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- width + - width输出表示视频的水平分辨率,这对于确保视频内容的正确显示和缩放至关重要。 + - Comfy dtype: INT + - Python dtype: int +- height + - height输出代表视频的垂直分辨率,这是在视频处理过程中保持纵横比和视觉质量的重要方面。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class VideoInfoSource: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'video_info': ('VHS_VIDEOINFO',)}} + CATEGORY = 'Video Helper Suite 🎥🅥🅗🅢' + RETURN_TYPES = ('FLOAT', 'INT', 'FLOAT', 'INT', 'INT') + RETURN_NAMES = ('fps🟨', 'frame_count🟨', 'duration🟨', 'width🟨', 'height🟨') + FUNCTION = 'get_video_info' + + def get_video_info(self, video_info): + keys = ['fps', 'frame_count', 'duration', 'width', 'height'] + source_info = [] + for key in keys: + source_info.append(video_info[f'source_{key}']) + return (*source_info,) +``` \ No newline at end of file diff --git a/docs/Vae Decode (mtb).md b/docs/Vae Decode (mtb).md new file mode 100644 index 0000000..e69de29 diff --git a/docs/ValueSchedule.md b/docs/ValueSchedule.md new file mode 100644 index 0000000..5713054 --- /dev/null +++ b/docs/ValueSchedule.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: ValueSchedule +- Category: FizzNodes 📅🅕🅝/ScheduleNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +ValueSchedule节点旨在根据给定的关键帧文本表示来动画化和插值。它通过解析输入文本来确定关键帧值,然后在这些关键帧之间进行插值,以在指定的帧数上产生平滑的值过渡。 + +# Input types +## Required +- text + - ‘text’参数是一个包含用于动画化值的关键帧定义的字符串。它对节点的操作至关重要,因为它直接影响输出动画序列。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- max_frames + - ‘max_frames’参数指定动画发生的总帧数。它对于确定插值范围至关重要。 + - Comfy dtype: INT + - Python dtype: int +- current_frame + - ‘current_frame’参数表示动画序列中的当前位置。它对于计算动画当前状态的插值非常重要。 + - Comfy dtype: INT + - Python dtype: int +- print_output + - 当设置为True时,‘print_output’参数启用将当前帧及其插值打印到控制台。这对于调试非常有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- value + - ‘value’输出代表当前帧的插值。这是节点的主要输出,对于继续动画或进一步处理至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- frame_number + - ‘frame_number’输出提供动画序列中的当前帧索引。它可以用于跟踪动画的进度。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ValueSchedule: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True, 'default': defaultValue}), 'max_frames': ('INT', {'default': 120.0, 'min': 1.0, 'max': 999999.0, 'step': 1.0}), 'current_frame': ('INT', {'default': 0.0, 'min': 0.0, 'max': 999999.0, 'step': 1.0}), 'print_output': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('FLOAT', 'INT') + FUNCTION = 'animate' + CATEGORY = 'FizzNodes 📅🅕🅝/ScheduleNodes' + + def animate(self, text, max_frames, current_frame, print_output): + current_frame = current_frame % max_frames + t = get_inbetweens(parse_key_frames(text, max_frames), max_frames) + if print_output is True: + print('ValueSchedule: ', current_frame, '\n', 'current_frame: ', current_frame) + return (t[current_frame], int(t[current_frame])) +``` \ No newline at end of file diff --git a/docs/Video Dump Frames.md b/docs/Video Dump Frames.md new file mode 100644 index 0000000..9988a81 --- /dev/null +++ b/docs/Video Dump Frames.md @@ -0,0 +1,84 @@ +# Documentation +- Class name: WAS_Video_Frame_Dump +- Category: WAS Suite/Animation +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Video_Frame_Dump 节点旨在处理视频文件,通过提取单独的帧并将它们保存为图像文件。这个实用工具特别适合用于动画和视频分析工作流程,允许用户将视频内容分解为一系列静态图像。节点可以配置为指定视频源、输出目录、提取帧的命名前缀以及所需的图像格式。此外,它还提供了设置文件编号位数和高级用户所需的 ffmpeg 二进制路径的选项。节点的功能封装在其 dump_video_frames 方法中,该方法协调帧提取过程,并返回输出目录的路径以及处理过的帧数。 + +# Input types +## Required +- video_path + - video_path 参数指定了要从中提取帧的视频文件的文件路径。这个输入至关重要,因为它决定了帧转储操作的源内容。节点将使用此路径来定位和处理视频,使其成为执行的基本部分。 + - Comfy dtype: STRING + - Python dtype: str +- output_path + - output_path 参数定义了保存提取帧的目录。它是一个必要的参数,因为它决定了视频帧提取过程后结果图像文件的存储位置。用户应确保此目录可写,并且有足够的空间容纳输出文件。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- prefix + - prefix 参数用于定义保存的图像文件的命名约定。它是一个可选输入,允许用户在每个文件名的开头添加一个特定的字符串。这对于组织文件或与期望某种命名模式的其他系统集成可能很有用。 + - Comfy dtype: STRING + - Python dtype: str +- filenumber_digits + - filenumber_digits 参数确定保存的图像文件名中用于零填充文件编号的位数。这是一个可选设置,可以根据用户的偏好或文件命名一致性的要求进行调整。此参数影响输出文件名的格式。 + - Comfy dtype: INT + - Python dtype: int +- extension + - extension 参数指定提取的图像帧的文件格式。用户可以从 'png'、'jpg'、'gif' 或 'tiff' 的组合中选择。这个输入影响将生成的图像文件类型,这可能取决于提取帧的预期用途。 + - Comfy dtype: COMBO['png', 'jpg', 'gif', 'tiff'] + - Python dtype: str + +# Output types +- output_path + - 输出中的 output_path 参数反映了保存提取帧的目录。它很重要,因为它提供了视频帧转储过程后图像文件的位置。这些信息对用户定位和进一步处理输出文件至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- processed_count + - processed_count 输出参数指示从视频中成功提取的帧数。它作为节点执行的确认,并且可以用来验证帧提取过程的完整性。 + - Comfy dtype: NUMBER + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Video_Frame_Dump: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'video_path': ('STRING', {'default': './ComfyUI/input/MyVideo.mp4', 'multiline': False}), 'output_path': ('STRING', {'default': './ComfyUI/input/MyVideo', 'multiline': False}), 'prefix': ('STRING', {'default': 'frame_', 'multiline': False}), 'filenumber_digits': ('INT', {'default': 4, 'min': -1, 'max': 8, 'step': 1}), 'extension': (['png', 'jpg', 'gif', 'tiff'],)}} + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') + RETURN_TYPES = (TEXT_TYPE, 'NUMBER') + RETURN_NAMES = ('output_path', 'processed_count') + FUNCTION = 'dump_video_frames' + CATEGORY = 'WAS Suite/Animation' + + def dump_video_frames(self, video_path, output_path, prefix='fame_', extension='png', filenumber_digits=-1): + conf = getSuiteConfig() + if not conf.__contains__('ffmpeg_bin_path'): + cstr(f'Unable to use dump frames because the `ffmpeg_bin_path` is not set in `{WAS_CONFIG_FILE}`').error.print() + return ('', 0) + if conf.__contains__('ffmpeg_bin_path'): + if conf['ffmpeg_bin_path'] != '/path/to/ffmpeg': + sys.path.append(conf['ffmpeg_bin_path']) + os.environ['OPENCV_FFMPEG_CAPTURE_OPTIONS'] = 'rtsp_transport;udp' + os.environ['OPENCV_FFMPEG_BINARY'] = conf['ffmpeg_bin_path'] + if output_path.strip() in [None, '', '.']: + output_path = './ComfyUI/input/frames' + tokens = TextTokens() + output_path = os.path.abspath(os.path.join(*tokens.parseTokens(output_path).split('/'))) + prefix = tokens.parseTokens(prefix) + WTools = WAS_Tools_Class() + MP4Writer = WTools.VideoWriter() + processed = MP4Writer.extract(video_path, output_path, prefix, extension, filenumber_digits) + return (output_path, processed) +``` \ No newline at end of file diff --git a/docs/Vignette.md b/docs/Vignette.md new file mode 100644 index 0000000..987a6fd --- /dev/null +++ b/docs/Vignette.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: Vignette +- Category: postprocessing/Effects +- Output node: False +- Repo Ref: https://github.com/EllangoK/ComfyUI-post-processing-nodes + +该节点向图像应用晕影效果,通过逐渐淡化边缘来增强对中心的视觉聚焦。它根据用户定义的参数调整晕影的强度,从而允许对美学影响进行细微控制。 + +# Input types +## Required +- image + - 图像参数是必要的,因为它是节点操作的主要输入。它决定了将要应用晕影效果的对象,从而直接影响输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- a + - 参数'a'控制晕影效果的强度。它对于根据用户的偏好定制美学结果至关重要,允许从微妙到戏剧性的不同视觉风格。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- output_image + - 输出图像是应用晕影效果的结果。它反映了带有应用美学调整的输入图像,代表了节点的主要输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Vignette: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'a': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 10.0, 'step': 1.0})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'apply_vignette' + CATEGORY = 'postprocessing/Effects' + + def apply_vignette(self, image: torch.Tensor, vignette: float): + if vignette == 0: + return (image,) + (height, width, _) = image.shape[-3:] + x = torch.linspace(-1, 1, width, device=image.device) + y = torch.linspace(-1, 1, height, device=image.device) + (X, Y) = torch.meshgrid(x, y, indexing='ij') + radius = torch.sqrt(X ** 2 + Y ** 2) + mapped_vignette_strength = 1.8 - (vignette - 1) * 0.1 + vignette = 1 - torch.clamp(radius / mapped_vignette_strength, 0, 1) + vignette = vignette[..., None] + vignette_image = torch.clamp(image * vignette, 0, 1) + return (vignette_image,) +``` \ No newline at end of file diff --git a/docs/VividSharpen.md b/docs/VividSharpen.md new file mode 100644 index 0000000..15dafbb --- /dev/null +++ b/docs/VividSharpen.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: VividSharpen +- Category: image/postprocessing +- Output node: False +- Repo Ref: https://github.com/WASasquatch/WAS_Extras + +VividSharpen 节点旨在通过应用锐化算法增强图像的清晰度和锐利度。它调整视觉细节以创造更加生动和清晰的外观,适用于图像编辑中的后期处理任务。 + +# Input types +## Required +- images + - ‘images’参数是锐化过程的输入。它至关重要,因为它决定了将要被增强的内容。输入图像的质量和分辨率直接影响锐化的效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +## Optional +- radius + - ‘radius’参数控制锐化前应用的模糊效果的范围。这是一个重要的调整因素,它影响输出图像中锐度的程度,允许对最终视觉外观进行精细控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- strength + - ‘strength’参数定义了锐化效果的强度。它很重要,因为它允许用户控制锐化的激进程度,从而产生具有不同细节和清晰度级别的图像。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- images + - 输出的‘images’是经过锐化算法处理后具有增强锐度和清晰度的图像。它们已准备好用于进一步使用或展示。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class VividSharpen: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'images': ('IMAGE',), 'radius': ('FLOAT', {'default': 1.5, 'min': 0.01, 'max': 64.0, 'step': 0.01}), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('images',) + FUNCTION = 'sharpen' + CATEGORY = 'image/postprocessing' + + def sharpen(self, images, radius, strength): + results = [] + if images.size(0) > 1: + for image in images: + image = tensor2pil(image) + results.append(pil2tensor(vivid_sharpen(image, radius=radius, strength=strength))) + results = torch.cat(results, dim=0) + else: + results = pil2tensor(vivid_sharpen(tensor2pil(images), radius=radius, strength=strength)) + return (results,) +``` \ No newline at end of file diff --git a/docs/WD14Tagger|pysssss.md b/docs/WD14Tagger|pysssss.md new file mode 100644 index 0000000..de584ec --- /dev/null +++ b/docs/WD14Tagger|pysssss.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: WD14Tagger +- Category: image +- Output node: True +- Repo Ref: https://github.com/pythongosssss/ComfyUI-WD14-Tagger + +该节点旨在对图像进行标记,使用指定的模型对输入的图像数据进行分类并返回相关标签。它通过处理批次中的每个图像,应用阈值来过滤标签,并尊重提供的任何排除标准。其主要目标是通过自动标记增强图像数据的组织和检索。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它提供了标记过程所需的原始数据。没有这个输入,节点无法执行其主要功能,即对图像进行分类和标记。 + - Comfy dtype: IMAGE + - Python dtype: numpy.ndarray +- model + - 模型参数至关重要,因为它决定了用于图像标记过程的具体机器学习模型。它影响生成的标签的准确性和相关性。 + - Comfy dtype: all_models + - Python dtype: callable +- threshold + - 阈值参数很重要,因为它设置了包含在输出中的标签的最小置信度水平。它直接影响标签的过滤,决定哪些被认为是足够重要的以被报告。 + - Comfy dtype: FLOAT + - Python dtype: float +- character_threshold + - 该参数通过为字符级标签设置一个特定的次级阈值来细化标记过程。它有助于过滤掉不太相关的字符标签,提高标记结果的精确度。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- exclude_tags + - exclude_tags参数允许指定不应包含在输出中的标签。这对于根据特定要求定制标记结果或因各种原因避免某些标签非常有用。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- tags + - 标签输出是图像标记过程的结果,包含基于输入图像和应用阈值的相关和重要标签的列表。它是关键的输出,因为它直接代表了节点的主要功能和标记过程的有效性。 + - Comfy dtype: STRING + - Python dtype: List[str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WD14Tagger: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'model': (all_models,), 'threshold': ('FLOAT', {'default': defaults['threshold'], 'min': 0.0, 'max': 1, 'step': 0.05}), 'character_threshold': ('FLOAT', {'default': defaults['character_threshold'], 'min': 0.0, 'max': 1, 'step': 0.05}), 'exclude_tags': ('STRING', {'default': defaults['exclude_tags']})}} + RETURN_TYPES = ('STRING',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'tag' + OUTPUT_NODE = True + CATEGORY = 'image' + + def tag(self, image, model, threshold, character_threshold, exclude_tags=''): + tensor = image * 255 + tensor = np.array(tensor, dtype=np.uint8) + pbar = comfy.utils.ProgressBar(tensor.shape[0]) + tags = [] + for i in range(tensor.shape[0]): + image = Image.fromarray(tensor[i]) + tags.append(wait_for_async(lambda : tag(image, model, threshold, character_threshold, exclude_tags))) + pbar.update(1) + return {'ui': {'tags': tags}, 'result': (tags,)} +``` \ No newline at end of file diff --git a/docs/Wildcard Processor.md b/docs/Wildcard Processor.md new file mode 100644 index 0000000..a95105e --- /dev/null +++ b/docs/Wildcard Processor.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: WildcardProcessor +- Category: Mikey/Text +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +WildcardProcessor节点旨在通过替换通配符来操作和处理文本输入,使用特定模式或值。它通过识别输入提示中的占位符,并将它们替换为相应的数据,从而实现基于用户定义标准的动态文本生成。 + +# Input types +## Required +- prompt + - ‘prompt’参数是节点的主要输入,作为将进行通配符替换的源文本。它至关重要,因为它决定了节点将处理和转换的上下文和内容。 + - Comfy dtype: STRING + - Python dtype: str +- seed + - ‘seed’参数是一个整数,用于初始化随机数生成器,确保通配符替换过程的可重复性。它在确定从通配符文件中选择行的过程中起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- prompt_ + - ‘prompt_’参数是一个可选的字典,提供通配符替换的额外上下文或特定指令。它通过允许用户根据自己的需求定制替换过程,增强了节点操作的定制性。 + - Comfy dtype: PROMPT + - Python dtype: Dict[str, Any] +- extra_pnginfo + - ‘extra_pnginfo’参数是一个可选的JSON对象,包含通配符替换的额外信息。它用于提供可能影响节点处理输入提示的额外数据。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Union[str, Dict[str, Any]] + +# Output types +- processed_prompt + - ‘processed_prompt’输出是节点操作的结果,其中输入提示的通配符已被适当的值替换。它标志着文本处理的完成,并已准备好进一步使用或输出。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WildcardProcessor: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompt': ('STRING', {'multiline': True, 'placeholder': 'Prompt Text'}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'prompt_': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = ('STRING',) + FUNCTION = 'process' + CATEGORY = 'Mikey/Text' + + def process(self, prompt, seed, prompt_=None, extra_pnginfo=None): + if prompt_ is None: + prompt_ = {} + if extra_pnginfo is None: + extra_pnginfo = {} + prompt = search_and_replace(prompt, extra_pnginfo, prompt_) + prompt = find_and_replace_wildcards(prompt, seed) + return (prompt,) +``` \ No newline at end of file diff --git a/docs/WildcardAndLoraSyntaxProcessor.md b/docs/WildcardAndLoraSyntaxProcessor.md new file mode 100644 index 0000000..b9379a7 --- /dev/null +++ b/docs/WildcardAndLoraSyntaxProcessor.md @@ -0,0 +1,102 @@ +# Documentation +- Class name: WildcardAndLoraSyntaxProcessor +- Category: Mikey/Lora +- Output node: False +- Repo Ref: https://github.com/bash-j/mikey_nodes + +WildcardAndLoraSyntaxProcessor节点旨在处理和加工复杂的文本输入,通过将通配符和Lora语法替换为特定值或文件。它通过使能基于预定义模式和外部文件的动态内容生成,增强了文本处理工作流的灵活性和定制性。 + +# Input types +## Required +- model + - 模型参数对于节点的操作至关重要,因为它代表了节点将用于处理的核心模型。这是一个必需的输入,直接影响节点正常工作的能力。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - clip参数是一个必需的输入,它与模型参数协同工作。它通过提供模型可能需要的额外上下文或数据,在节点的执行中发挥重要作用。 + - Comfy dtype: CLIP + - Python dtype: CLIP model instance +- text + - 文本参数是节点的关键输入,因为它包含将被处理的原始文本。它可以包含用于通配符和Lora引用的特殊语法,节点将相应地解释并替换它们。 + - Comfy dtype: STRING + - Python dtype: str +- seed + - 种子参数对节点的随机化过程很重要。它确保文本中的随机元素以可重现的方式生成,这对于不同运行之间获得一致的结果至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- extra_pnginfo + - extra_pnginfo参数虽然是可选的,但可以提供用于进一步定制节点行为的额外信息。它可以包含元数据或其他相关数据,以增强节点的处理能力。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: str or dict +- prompt + - 提示参数是一个可选输入,它可以通过提供特定指令或上下文来指导节点的处理。当处理复杂文本输入时,它可以用来影响节点的决策过程。 + - Comfy dtype: PROMPT + - Python dtype: str or dict + +# Output types +- model + - 节点的模型输出代表了已处理的模型,该模型已根据节点的操作进行了更新或修改。它标志着节点文本处理的完成,并已准备好用于进一步使用或分析。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - clip输出是输入clip的处理版本,反映了节点执行期间所做的任何更改。这是一个重要的结果,可能会在工作流的后续阶段中使用。 + - Comfy dtype: CLIP + - Python dtype: CLIP model instance +- text + - 文本输出是所有通配符和Lora语法被替换后的最终处理文本。它代表了节点的主要输出,是节点核心功能的结果。 + - Comfy dtype: STRING + - Python dtype: str +- unprocessed_text + - 未处理的文本输出提供了节点的原始文本输入,未经节点操作的任何修改。它用作比较或进一步分析的参考。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WildcardAndLoraSyntaxProcessor: + + def __init__(self): + self.loaded_lora = None + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'text': ('STRING', {'multiline': True, 'default': ''}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('MODEL', 'CLIP', 'STRING', 'STRING') + RETURN_NAMES = ('model', 'clip', 'text', 'unprocessed_text') + FUNCTION = 'process' + CATEGORY = 'Mikey/Lora' + + def extract_and_load_loras(self, text, model, clip): + lora_re = '' + lora_prompts = re.findall(lora_re, text) + stripped_text = text + clip_lora = clip + if len(lora_prompts) > 0: + for lora_prompt in lora_prompts: + lora_filename = lora_prompt[0] + if '.safetensors' not in lora_filename: + lora_filename += '.safetensors' + try: + lora_multiplier = float(lora_prompt[1]) if lora_prompt[1] != '' else 1.0 + except: + lora_multiplier = 1.0 + (model, clip) = load_lora(model, clip, lora_filename, lora_multiplier, lora_multiplier) + stripped_text = re.sub(lora_re, '', stripped_text) + return (model, clip, stripped_text) + + def process(self, model, clip, text, seed, extra_pnginfo=None, prompt=None): + text = search_and_replace(text, extra_pnginfo, prompt) + text = process_random_syntax(text, seed) + text_ = find_and_replace_wildcards(text, seed, True) + if len(text_) != len(text): + seed = random.randint(0, 1000000) + else: + seed = 1 + (model, clip, stripped_text) = self.extract_and_load_loras(text_, model, clip) + stripped_text = find_and_replace_wildcards(stripped_text, seed, True) + return (model, clip, stripped_text, text_) +``` \ No newline at end of file diff --git a/docs/WildcardEncode %2F%2FInspire.md b/docs/WildcardEncode %2F%2FInspire.md new file mode 100644 index 0000000..4581510 --- /dev/null +++ b/docs/WildcardEncode %2F%2FInspire.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: WildcardEncodeInspire +- Category: InspirePack/Prompt +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +WildcardEncodeInspire节点旨在处理和编码带有通配符和LoRa(低秩适应)块的文本输入,将它们整合到模型和clip条件中,用于稳定扩散。它通过基于用户输入或固定文本动态生成提示来填充通配符,增强输出内容的创造性和适应性。对于寻求利用先进的文本编码技术来提高AI生成内容质量和相关性的用户来说,此节点是必不可少的。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了将用于文本编码和处理的基础AI模型。它直接影响生成内容的质量和特性,确保输出与指定模型的能力和训练数据保持一致。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - clip参数对于将文本与视觉上下文整合至关重要,使节点能够生成不仅在文本上连贯而且视觉上相关的提示。它在确保AI输出与期望的视觉元素保持一致方面发挥着重要作用。 + - Comfy dtype: CLIP + - Python dtype: CLIPModel +- token_normalization + - token_normalization参数对于在编码之前对文本标记进行预处理非常重要。它标准化了标记值,这可以提高文本编码过程的效率和准确性,确保AI模型能够更好地理解和处理输入文本。 + - Comfy dtype: COMBO + - Python dtype: str +- weight_interpretation + - weight_interpretation参数在确定节点如何在编码过程中解释和应用权重方面起着关键作用。它影响对文本不同部分的强调,这可以显著影响最终输出的重点和细节。 + - Comfy dtype: COMBO + - Python dtype: str +- wildcard_text + - wildcard_text参数是节点功能的核心,因为它包含了将在编码过程中被填充或替换的带有通配符的模板。它是生成动态和适应性强的提示的基础。 + - Comfy dtype: STRING + - Python dtype: str +- populated_text + - populated_text参数保存了处理通配符后的最终文本,用于实际的编码和生成AI内容。它是节点主要功能的结果,直接影响输出。 + - Comfy dtype: STRING + - Python dtype: str +- mode + - mode参数控制节点是否基于用户输入生成动态提示(Populate)还是使用固定文本(Fixed)。此设置对于确定生成提示的灵活性和适应性至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- seed + - seed参数用于在编码过程中引入随机性,允许生成多样化和独特的输出。它确保即使输入相同,也可以产生不同的结果,增加了AI输出的变异性。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- Select to add LoRA + - '选择添加LoRA'参数允许用户将特定的LoRa块纳入文本中,通过额外的上下文信息增强编码过程。这可以显著提高AI生成内容的相关性和深度。 + - Comfy dtype: COMBO + - Python dtype: str +- Select to add Wildcard + - 此参数允许用户向文本中添加特定的通配符,这些通配符可以在编码过程中动态填充或替换。这是定制输出以满足特定创意或主题要求的关键方面。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- model + - 模型输出是带有编码文本和条件的更新后的AI模型,准备根据输入和处理参数生成内容。它代表了节点编码工作的成果。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- clip + - clip输出整合了输入的视觉上下文,增强了AI生成不仅在文本上连贯而且与提供的clip视觉对齐的内容的能力。 + - Comfy dtype: CLIP + - Python dtype: CLIPModel +- conditioning + - 条件输出为AI模型提供了额外的上下文和指导,确保生成的内容符合指定的主题和要求。它是实现针对性和相关性AI输出的关键组成部分。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, torch.Tensor] +- populated_text + - populated_text输出是经过处理的最终文本,其中的通配符已被填充或替换,准备用于AI模型的生成过程中。它是节点编码和处理活动的直接结果。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class WildcardEncodeInspire: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), 'clip': ('CLIP',), 'token_normalization': (['none', 'mean', 'length', 'length+mean'],), 'weight_interpretation': (['comfy', 'A1111', 'compel', 'comfy++', 'down_weight'], {'default': 'comfy++'}), 'wildcard_text': ('STRING', {'multiline': True, 'dynamicPrompts': False, 'placeholder': 'Wildcard Prompt (User Input)'}), 'populated_text': ('STRING', {'multiline': True, 'dynamicPrompts': False, 'placeholder': 'Populated Prompt (Will be generated automatically)'}), 'mode': ('BOOLEAN', {'default': True, 'label_on': 'Populate', 'label_off': 'Fixed'}), 'Select to add LoRA': (['Select the LoRA to add to the text'] + folder_paths.get_filename_list('loras'),), 'Select to add Wildcard': (['Select the Wildcard to add to the text'],), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}} + CATEGORY = 'InspirePack/Prompt' + RETURN_TYPES = ('MODEL', 'CLIP', 'CONDITIONING', 'STRING') + RETURN_NAMES = ('model', 'clip', 'conditioning', 'populated_text') + FUNCTION = 'doit' + + def doit(self, *args, **kwargs): + populated = kwargs['populated_text'] + clip_encoder = BNK_EncoderWrapper(kwargs['token_normalization'], kwargs['weight_interpretation']) + if 'ImpactWildcardEncode' not in nodes.NODE_CLASS_MAPPINGS: + utils.try_install_custom_node('https://github.com/ltdrdata/ComfyUI-Impact-Pack', "To use 'Wildcard Encode (Inspire)' node, 'Impact Pack' extension is required.") + raise Exception(f"[ERROR] To use 'Wildcard Encode (Inspire)', you need to install 'Impact Pack'") + (model, clip, conditioning) = nodes.NODE_CLASS_MAPPINGS['ImpactWildcardEncode'].process_with_loras(wildcard_opt=populated, model=kwargs['model'], clip=kwargs['clip'], clip_encoder=clip_encoder) + return (model, clip, conditioning, populated) +``` \ No newline at end of file diff --git a/docs/WildcardOobaPrompt.md b/docs/WildcardOobaPrompt.md new file mode 100644 index 0000000..03a08c6 --- /dev/null +++ b/docs/WildcardOobaPrompt.md @@ -0,0 +1,70 @@ +# Documentation +- Class name: WildcardOobaPrompt +- Category: Mikey/AI +- Output node: True +- Repo Ref: https://github.com/bash-j/mikey_nodes + +WildcardOobaPrompt节点的'process'方法旨在为AI应用动态生成和处理提示。它替换输入提示中的通配符为随机选择,并与外部API集成以生成详细的响应。该节点在创建多样化和情境丰富的AI模型提示中发挥关键作用,增强了它们产生细腻输出的能力。 + +# Input types +## Required +- input_prompt + - ‘input_prompt’参数是一个包含提示初始文本的字符串。它至关重要,因为它构成了通配符替换和AI后续处理的基础。此参数直接影响节点生成的最终输出的多样性和创造性。 + - Comfy dtype: STRING + - Python dtype: str +- seed + - ‘seed’参数是一个用于初始化通配符替换过程中的随机数生成器的整数。它确保结果是可复现的,这对于调试和一致性测试节点的功能至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- unique_id + - ‘unique_id’参数是一个用于引用提示中特定条目的唯一标识符。当管理多个并发提示时,它尤其重要,因为它允许节点精确地定位和更新所需的提示。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- text + - 'text'输出参数代表了所有通配符被替换并且AI的响应被整合后最终处理的提示。它是一个关键的输出,因为它直接输入到AI模型中,影响生成内容的质量和特性。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WildcardOobaPrompt: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'input_prompt': ('STRING', {'multiline': True, 'default': 'Prompt Text Here', 'dynamicPrompts': False}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('text',) + FUNCTION = 'process' + OUTPUT_NODE = True + CATEGORY = 'Mikey/AI' + + def process(self, input_prompt, seed, prompt=None, unique_id=None, extra_pnginfo=None): + input_prompt = search_and_replace(input_prompt, extra_pnginfo, prompt) + wc_re = re.compile('{([^}]+)}') + + def repl(m): + return random.choice(m.group(1).split('|')) + for m in wc_re.finditer(input_prompt): + input_prompt = input_prompt.replace(m.group(0), repl(m)) + input_prompt = find_and_replace_wildcards(input_prompt, seed, debug=True) + llm_re = re.compile('') + for m in llm_re.finditer(input_prompt): + mode = m.group(1) + if '.json' in mode: + custom_history = mode + mode = 'custom' + else: + custom_history = None + prompt_text = m.group(2) + ooba = OobaPrompt() + result = ooba.api_request(prompt_text, seed, mode, custom_history) + input_prompt = input_prompt.replace(m.group(0), result) + prompt.get(str(unique_id))['inputs']['output_text'] = input_prompt + return (input_prompt,) +``` \ No newline at end of file diff --git a/docs/Write to GIF.md b/docs/Write to GIF.md new file mode 100644 index 0000000..84e9ce3 --- /dev/null +++ b/docs/Write to GIF.md @@ -0,0 +1,107 @@ +# Documentation +- Class name: WAS_Image_Morph_GIF_Writer +- Category: WAS Suite/Animation/Writer +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Image_Morph_GIF_Writer 节点旨在从一系列图像或帧创建动画 GIF。它提供管理帧之间过渡、控制它们之间的延迟以及设置 GIF 循环行为的功能。这个节点特别适合以无缝高效的方式生成动画,适用于各种应用,如视觉特效、演示或网络内容。 + +# Input types +## Required +- image + - 用于创建 GIF 动画帧的输入图像或图像系列。此参数至关重要,因为它直接影响生成的动画的视觉内容。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] 或 torch.Tensor +## Optional +- transition_frames + - 生成每对图像之间的转换帧数。此参数通过控制每个帧过渡到下一帧的速度,影响动画的平滑度。 + - Comfy dtype: INT + - Python dtype: int +- image_delay_ms + - 每个帧过渡开始前的延迟时间,以毫秒为单位。此参数对于控制动画的时机很重要,可以根据需要调整以创建所需的效果。 + - Comfy dtype: FLOAT + - Python dtype: float +- duration_ms + - GIF 动画的总时长,以毫秒为单位。此参数设置了从开始到结束的动画整体长度。 + - Comfy dtype: FLOAT + - Python dtype: float +- loops + - GIF 循环的次数。值为 0 表示 GIF 将无限循环。 + - Comfy dtype: INT + - Python dtype: int +- max_size + - 输出 GIF 的最大尺寸,以像素为单位。此参数适用于缩小动画以适应特定的显示要求或限制。 + - Comfy dtype: INT + - Python dtype: int +- output_path + - 保存输出 GIF 文件的路径。此参数决定了文件系统中存储最终动画的位置。 + - Comfy dtype: STRING + - Python dtype: str +- filename + - 输出 GIF 文件的名称。此参数允许用户为动画文件指定所需的名称。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- image_pass + - 用于创建 GIF 的处理过的图像或图像系列。此输出反映了节点处理后的视觉内容。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] 或 torch.Tensor +- filepath_text + - 创建的 GIF 动画的完整文件路径。此输出适用于引用或进一步处理动画文件。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str +- filename_text + - 创建的 GIF 文件的名称。此输出提供了给动画文件的特定名称。 + - Comfy dtype: TEXT_TYPE + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Image_Morph_GIF_Writer: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'transition_frames': ('INT', {'default': 30, 'min': 2, 'max': 60, 'step': 1}), 'image_delay_ms': ('FLOAT', {'default': 2500.0, 'min': 0.1, 'max': 60000.0, 'step': 0.1}), 'duration_ms': ('FLOAT', {'default': 0.1, 'min': 0.1, 'max': 60000.0, 'step': 0.1}), 'loops': ('INT', {'default': 0, 'min': 0, 'max': 100, 'step': 1}), 'max_size': ('INT', {'default': 512, 'min': 128, 'max': 1280, 'step': 1}), 'output_path': ('STRING', {'default': comfy_paths.output_directory, 'multiline': False}), 'filename': ('STRING', {'default': 'morph_writer', 'multiline': False})}} + + @classmethod + def IS_CHANGED(cls, **kwargs): + return float('NaN') + RETURN_TYPES = ('IMAGE', TEXT_TYPE, TEXT_TYPE) + RETURN_NAMES = ('image_pass', 'filepath_text', 'filename_text') + FUNCTION = 'write_to_morph_gif' + CATEGORY = 'WAS Suite/Animation/Writer' + + def write_to_morph_gif(self, image, transition_frames=10, image_delay_ms=10, duration_ms=0.1, loops=0, max_size=512, output_path='./ComfyUI/output', filename='morph'): + if 'imageio' not in packages(): + install_package('imageio') + if output_path.strip() in [None, '', '.']: + output_path = './ComfyUI/output' + if image is None: + image = pil2tensor(Image.new('RGB', (512, 512), (0, 0, 0))).unsqueeze(0) + if transition_frames < 2: + transition_frames = 2 + elif transition_frames > 60: + transition_frames = 60 + if duration_ms < 0.1: + duration_ms = 0.1 + elif duration_ms > 60000.0: + duration_ms = 60000.0 + tokens = TextTokens() + output_path = os.path.abspath(os.path.join(*tokens.parseTokens(output_path).split('/'))) + output_file = os.path.join(output_path, tokens.parseTokens(filename) + '.gif') + if not os.path.exists(output_path): + os.makedirs(output_path, exist_ok=True) + WTools = WAS_Tools_Class() + GifMorph = WTools.GifMorphWriter(int(transition_frames), int(duration_ms), int(image_delay_ms)) + for img in image: + pil_img = tensor2pil(img) + GifMorph.write(pil_img, output_file) + return (image, output_file, filename) +``` \ No newline at end of file diff --git a/docs/Write to Video.md b/docs/Write to Video.md new file mode 100644 index 0000000..fa949c8 --- /dev/null +++ b/docs/Write to Video.md @@ -0,0 +1,129 @@ +# Documentation +- Class name: WAS_Video_Writer +- Category: WAS Suite/Animation/Writer +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +WAS_Video_Writer 节点旨在从一系列图像生成视频。它提供调整过渡帧、控制每秒帧数(FPS)和设置图像之间延迟的功能。此外,它可以将图像重新缩放到最大尺寸,并使用指定的编解码器对视频进行编码。该节点特别适用于从一系列输入图像创建动画或延时视频。 + +# Input types +## Required +- image + - 用于视频创建过程中的输入图像序列。此参数至关重要,因为它直接影响生成视频的内容。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] +## Optional +- transition_frames + - 图像之间的过渡帧数。值越高,过渡越平滑,但会增加视频时长。 + - Comfy dtype: INT + - Python dtype: int +- image_delay_sec + - 每张图像过渡到下一张之前的延迟秒数。这会影响视频的播放速度。 + - Comfy dtype: FLOAT + - Python dtype: float +- fps + - 输出视频的每秒帧数。它决定了视频的流畅度和文件大小。 + - Comfy dtype: INT + - Python dtype: int +- max_size + - 输出视频的最大尺寸大小(以像素为单位)。可能会发生调整大小以适应此约束。 + - Comfy dtype: INT + - Python dtype: int +- output_path + - 输出视频文件将被保存的目录路径。 + - Comfy dtype: STRING + - Python dtype: str +- filename + - 输出视频文件的期望名称。 + - Comfy dtype: STRING + - Python dtype: str +- codec + - 用于视频编码的编解码器。它影响视频格式和压缩。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- IMAGE_PASS + - 形成视频内容的连接图像序列。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- filepath_text + - 视频已保存的文件路径。 + - Comfy dtype: TEXT + - Python dtype: str +- filename_text + - 保存的视频的文件名。 + - Comfy dtype: TEXT + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_Video_Writer: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + WTools = WAS_Tools_Class() + v = WTools.VideoWriter() + codecs = [] + for codec in v.get_codecs(): + codecs.append(codec.upper()) + codecs = sorted(codecs) + return {'required': {'image': ('IMAGE',), 'transition_frames': ('INT', {'default': 30, 'min': 0, 'max': 120, 'step': 1}), 'image_delay_sec': ('FLOAT', {'default': 2.5, 'min': 0.1, 'max': 60000.0, 'step': 0.1}), 'fps': ('INT', {'default': 30, 'min': 1, 'max': 60.0, 'step': 1}), 'max_size': ('INT', {'default': 512, 'min': 128, 'max': 1920, 'step': 1}), 'output_path': ('STRING', {'default': './ComfyUI/output', 'multiline': False}), 'filename': ('STRING', {'default': 'comfy_writer', 'multiline': False}), 'codec': (codecs,)}} + RETURN_TYPES = ('IMAGE', TEXT_TYPE, TEXT_TYPE) + RETURN_NAMES = ('IMAGE_PASS', 'filepath_text', 'filename_text') + FUNCTION = 'write_video' + CATEGORY = 'WAS Suite/Animation/Writer' + + def write_video(self, image, transition_frames=10, image_delay_sec=10, fps=30, max_size=512, output_path='./ComfyUI/output', filename='morph', codec='H264'): + conf = getSuiteConfig() + if not conf.__contains__('ffmpeg_bin_path'): + cstr(f'Unable to use MP4 Writer because the `ffmpeg_bin_path` is not set in `{WAS_CONFIG_FILE}`').error.print() + return (image, '', '') + if conf.__contains__('ffmpeg_bin_path'): + if conf['ffmpeg_bin_path'] != '/path/to/ffmpeg': + sys.path.append(conf['ffmpeg_bin_path']) + os.environ['OPENCV_FFMPEG_CAPTURE_OPTIONS'] = 'rtsp_transport;udp' + os.environ['OPENCV_FFMPEG_BINARY'] = conf['ffmpeg_bin_path'] + if output_path.strip() in [None, '', '.']: + output_path = './ComfyUI/output' + if image == None: + image = pil2tensor(Image.new('RGB', (512, 512), (0, 0, 0))) + if transition_frames < 0: + transition_frames = 0 + elif transition_frames > 60: + transition_frames = 60 + if fps < 1: + fps = 1 + elif fps > 60: + fps = 60 + results = [] + for img in image: + print(img.shape) + new_image = self.rescale_image(tensor2pil(img), max_size) + print(new_image.size) + tokens = TextTokens() + output_path = os.path.abspath(os.path.join(*tokens.parseTokens(output_path).split('/'))) + output_file = os.path.join(output_path, tokens.parseTokens(filename)) + if not os.path.exists(output_path): + os.makedirs(output_path, exist_ok=True) + WTools = WAS_Tools_Class() + MP4Writer = WTools.VideoWriter(int(transition_frames), int(fps), int(image_delay_sec), max_size=max_size, codec=codec) + path = MP4Writer.write(new_image, output_file) + results.append(img) + return (torch.cat(results, dim=0), path, filename) + + def rescale_image(self, image, max_dimension): + (width, height) = image.size + if width > max_dimension or height > max_dimension: + scaling_factor = max(width, height) / max_dimension + new_width = int(width / scaling_factor) + new_height = int(height / scaling_factor) + image = image.resize((new_width, new_height), Image.Resampling(1)) + return image +``` \ No newline at end of file diff --git a/docs/YoloSEGdetectionNode.md b/docs/YoloSEGdetectionNode.md new file mode 100644 index 0000000..3d5793b --- /dev/null +++ b/docs/YoloSEGdetectionNode.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: YoloSEGdetectionNode +- Category: Jags_vector/yoloSEG +- Output node: False +- Repo Ref: https://github.com/jags111/ComfyUI_Jags_VectorMagic + +该节点使用深度学习模型对图像执行语义分割,识别和分类感兴趣的区域。它利用了YOLO(You Only Look Once)架构的力量,该架构以其实时对象检测能力而闻名,用于分割和分类输入图像中的对象。节点的主要目标是通过描绘不同对象的边界,提供对图像内容的详细理解,从而实现更复杂的图像分析任务。 + +# Input types +## Required +- image + - 图像参数对节点的运行至关重要,它是主要的输入。它是节点分割能力得以实现的媒介。图像的质量和分辨率对分割结果的准确性和细节程度有重大影响。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +- model_name + - 模型名称参数决定了将用于分割过程的YOLO模型配置。它非常重要,因为不同的模型可以提供不同水平的准确性和性能。模型的选择直接影响分割的质量以及节点正确识别和分类图像中对象的能力。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- SEG_IMAGE + - 输出图像,现在已经分割,提供了节点执行的对象分类的视觉表示。这是一个关键的结果,因为它展示了节点在理解和处理输入图像方面的有效性,允许进行进一步的分析和应用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class YoloSEGdetectionNode: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'model_name': (folder_paths.get_filename_list('yolov8'),)}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('SEG_IMAGE',) + FUNCTION = 'detect' + CATEGORY = 'Jags_vector/yoloSEG' + + def detect(self, image, model_name): + image_tensor = image + image_np = image_tensor.cpu().numpy() + image = Image.fromarray((image_np.squeeze(0) * 255).astype(np.uint8)) + print(f"model_path: {os.path.join(folder_paths.models_dir, 'yolov8')}/{model_name}") + model = YOLO(f"{os.path.join(folder_paths.models_dir, 'yolov8')}/{model_name}") + results = model(image) + im_array = results[0].plot() + im = Image.fromarray(im_array[..., ::-1]) + image_tensor_out = torch.tensor(np.array(im).astype(np.float32) / 255.0) + image_tensor_out = torch.unsqueeze(image_tensor_out, 0) + return (image_tensor_out,) +``` \ No newline at end of file diff --git a/docs/YoloSegNode.md b/docs/YoloSegNode.md new file mode 100644 index 0000000..507ca61 --- /dev/null +++ b/docs/YoloSegNode.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: YoloSegNode +- Category: Jags_vector/yoloSEG +- Output node: False +- Repo Ref: https://github.com/jags111/ComfyUI_Jags_VectorMagic + +该节点旨在使用基于YOLO的模型执行语义分割,识别并屏蔽图像中特定类别的实例。它处理输入的图像以识别所需的类别,并输出一个分割后的图像和一个相应的掩码,突出显示已识别的实例。 + +# Input types +## Required +- image + - 输入图像对于节点执行分割至关重要。它是模型分析和识别指定类别的主要数据源。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- model_name + - 此参数决定了用于分割的特定YOLO模型。它至关重要,因为它决定了分割过程的准确性和有效性。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- class_id + - 类别ID参数允许用户指定图像中应该被分割的类别,影响节点的输出,使其专注于所需的类别。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- SEG_IMAGE + - 分割后的图像表示输入图像,突出显示识别的类别实例,提供分割过程的视觉输出。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- SEG_MASK + - 掩码输出是分割类别实例的二进制表示,作为进一步分析或操作图像中识别类别的精确工具。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class YoloSegNode: + + def __init__(self) -> None: + ... + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'model_name': (folder_paths.get_filename_list('yolov8'),), 'class_id': ('INT', {'default': 0})}} + RETURN_TYPES = ('IMAGE', 'MASK') + RETURN_NAMES = ('SEG_IMAGE', 'SEG_MASK') + FUNCTION = 'seg' + CATEGORY = 'Jags_vector/yoloSEG' + + def seg(self, image, model_name, class_id): + image_tensor = image + image_np = image_tensor.cpu().numpy() + image = Image.fromarray((image_np.squeeze(0) * 255).astype(np.uint8)) + print(f"model_path: {os.path.join(folder_paths.models_dir, 'yolov8')}/{model_name}") + model = YOLO(f"{os.path.join(folder_paths.models_dir, 'yolov8')}/{model_name}") + results = model(image) + masks = results[0].masks.data + boxes = results[0].boxes.data + clss = boxes[:, 5] + people_indices = torch.where(clss == class_id) + people_masks = masks[people_indices] + people_mask = torch.any(people_masks, dim=0).int() * 255 + im_array = results[0].plot() + im = Image.fromarray(im_array[..., ::-1]) + image_tensor_out = torch.tensor(np.array(im).astype(np.float32) / 255.0) + image_tensor_out = torch.unsqueeze(image_tensor_out, 0) + return (image_tensor_out, people_mask) +``` \ No newline at end of file diff --git a/docs/Yoloworld_ESAM_DetectorProvider_Zho.md b/docs/Yoloworld_ESAM_DetectorProvider_Zho.md new file mode 100644 index 0000000..2347a15 --- /dev/null +++ b/docs/Yoloworld_ESAM_DetectorProvider_Zho.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: Yoloworld_ESAM_DetectorProvider_Zho +- Category: ImpactPack +- Output node: False +- Repo Ref: https://github.com/ZHO-ZHO-ZHO/ComfyUI-YoloWorld-EfficientSAM.git + +该节点使用基于YOLO的模型在图像中检测指定对象,并可选择使用ESAM进行对象分割。其设计目的是提供准确的边界框和分割检测,增强对图像中视觉内容的理解。 + +# Input types +## Required +- yolo_world_model + - YOLO模型对于检测过程至关重要,因为它定义了用于图像中对象识别的神经网络架构。 + - Comfy dtype: YOLOWORLDMODEL + - Python dtype: YOLOWorldModel +- categories + - 要检测的对象类别是重要参数,指导检测过程专注于相关类别。 + - Comfy dtype: STRING + - Python dtype: str +- iou_threshold + - 交并比(IoU)阈值是一个关键参数,通过控制预测边界框与真实边界框之间的重叠标准,影响检测的精确度。 + - Comfy dtype: FLOAT + - Python dtype: float +- with_class_agnostic_nms + - 该参数启用类别不可知的非极大值抑制,这对于减少重叠检测和提高检测结果的准确性很重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- esam_model_opt + - 提供ESAM模型选项时,通过启用检测到的对象的分割,增强了检测过程,提供了对图像内容更详细的分析。 + - Comfy dtype: ESAMMODEL + - Python dtype: ESAMModel + +# Output types +- BBOX_DETECTOR + - BBOX检测器输出提供检测到的对象的边界框,这是理解图像中对象空间分布的基本步骤。 + - Comfy dtype: BBOX_DETECTOR + - Python dtype: YoloworldBboxDetector +- SEGM_DETECTOR + - SEGM检测器输出提供检测到的对象的分割掩码,通过描绘每个对象的精确边界,为分析增加了额外的细节层次。 + - Comfy dtype: SEGM_DETECTOR + - Python dtype: YoloworldSegmDetector + +# Usage tips +- Infra type: GPU + +# Source code +``` +class Yoloworld_ESAM_DetectorProvider_Zho: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'yolo_world_model': ('YOLOWORLDMODEL',), 'categories': ('STRING', {'default': '', 'placeholder': 'Please enter the objects to be detected separated by commas.', 'multiline': True}), 'iou_threshold': ('FLOAT', {'default': 0.1, 'min': 0, 'max': 1, 'step': 0.01}), 'with_class_agnostic_nms': ('BOOLEAN', {'default': False})}, 'optional': {'esam_model_opt': ('ESAMMODEL',)}} + RETURN_TYPES = ('BBOX_DETECTOR', 'SEGM_DETECTOR') + FUNCTION = 'doit' + CATEGORY = 'ImpactPack' + + def doit(self, yolo_world_model, categories, iou_threshold, with_class_agnostic_nms, esam_model_opt=None): + bbox_detector = YoloworldBboxDetector(yolo_world_model, categories, iou_threshold, with_class_agnostic_nms) + if esam_model_opt is not None: + segm_detector = YoloworldSegmDetector(bbox_detector, esam_model_opt) + else: + segm_detector = None + return (bbox_detector, segm_detector) +``` \ No newline at end of file diff --git a/docs/Yoloworld_ESAM_Zho.md b/docs/Yoloworld_ESAM_Zho.md new file mode 100644 index 0000000..d23bd72 --- /dev/null +++ b/docs/Yoloworld_ESAM_Zho.md @@ -0,0 +1,141 @@ +# Documentation +- Class name: Yoloworld_ESAM_Zho +- Category: YOLOWORLD_ESAM +- Output node: False +- Repo Ref: https://github.com/ZHO-ZHO-ZHO/ComfyUI-YoloWorld-EfficientSAM.git + +Yoloworld_ESAM_Zho类封装了将YOLO目标检测与ESAM分割集成的功能。它的目的是通过对图像中的对象进行识别和分类,以及基于检测到的类别进行分割,从而对图像进行全面分析。该节点通过增强对视觉内容的理解,对整体流程做出贡献,这对于需要详细分析图像的应用程序至关重要。 + +# Input types +## Required +- yolo_world_model + - YOLO世界模型对于目标检测过程至关重要。它负责识别和分类输入图像中的对象。模型的准确性和效率直接影响节点处理图像和产生准确结果的能力。 + - Comfy dtype: YOLOWORLDMODEL + - Python dtype: YOLOWorldModel +- esam_model + - ESAM模型对分割过程至关重要。它接受检测到的对象,并进一步细化对它们在图像中空间分布的理解。模型的性能对于实现详细和精确的分割掩膜至关重要。 + - Comfy dtype: ESAMMODEL + - Python dtype: ESAMModel +- image + - 图像是节点的主要输入。它们是检测和分割过程的对象。图像的质量和分辨率直接影响结果的准确性和可靠性。 + - Comfy dtype: IMAGE + - Python dtype: List[cv2.ndarray] +- categories + - 类别定义了模型将在图像中识别的类别。它们对于指导检测和分割过程至关重要,确保节点专注于相关对象。 + - Comfy dtype: STRING + - Python dtype: List[str] +## Optional +- confidence_threshold + - 置信度阈值过滤掉未达到一定置信水平的检测结果。它在管理检测灵敏度和特异性之间的权衡中起着重要作用,从而影响结果的整体质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- iou_threshold + - 交并比(IoU)阈值在非极大值抑制(NMS)过程中使用,用于消除冗余的检测。它通过减少重叠区域,影响节点产生干净准确检测集的能力。 + - Comfy dtype: FLOAT + - Python dtype: float +- box_thickness + - 边框厚度决定了绘制在检测对象周围的边界框的视觉突出程度。它影响注释图像的美观和清晰度,这对于视觉分析和解释很重要。 + - Comfy dtype: INT + - Python dtype: int +- text_thickness + - 文本厚度影响注释图像上绘制的类别标签的可见性。它对于确保标签易于阅读并有助于全面理解图像内容很重要。 + - Comfy dtype: INT + - Python dtype: int +- text_scale + - 文本缩放调整类别标签的大小,影响注释图像的可读性和视觉平衡。它是创建既信息丰富又视觉上吸引人的注释的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- with_confidence + - 启用此参数后,会在类别标签旁添加置信度分数,提供关于检测结果可靠性的额外信息层。这对于依赖检测结果确定性的决策过程至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- with_class_agnostic_nms + - 激活此参数后,将对检测结果应用类别不可知的非极大值抑制(NMS),有助于减少不同类别之间的重叠框。它通过确保边界框集更清洁、更有组织来改善检测结果的整体呈现。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- with_segmentation + - 启用此参数后,节点将对检测到的对象进行分割,提供其形状和边界的详细视觉表示。这增强了对图像内容的理解,对于需要精确对象勾画的应用特别有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- mask_combined + - 此参数控制是否将分割掩膜合并成一个表示所有检测到的对象的单个掩膜。这对于可视化图像中对象的集体空间分布很有帮助。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- mask_extracted + - 启用此参数后,允许提取每个检测到的对象的单独分割掩膜,为单独操作或分析各个对象提供了精细控制,这对于需要单独处理或分析各个对象的应用程序特别有用。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- mask_extracted_index + - 此参数指定在需要单独掩膜时提取的分割掩膜的索引。它对于在检测到的对象集中定位特定对象以进行进一步处理或分析至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- processed_images + - 处理后的图像是在应用目标检测和分割后节点的输出。它们包括边界框和标签等注释,提供了检测和分割对象的视觉表示。这些图像对于视觉分析和验证节点的性能至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- processed_masks + - 处理后的掩膜是分割输出,它们勾勒出检测到的对象的精确边界。它们对于需要图像中对象的详细空间信息的应用程序非常重要,例如在医学成像或自动驾驶车辆导航中。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class Yoloworld_ESAM_Zho: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'yolo_world_model': ('YOLOWORLDMODEL',), 'esam_model': ('ESAMMODEL',), 'image': ('IMAGE',), 'categories': ('STRING', {'default': 'person, bicycle, car, motorcycle, airplane, bus, train, truck, boat', 'multiline': True}), 'confidence_threshold': ('FLOAT', {'default': 0.1, 'min': 0, 'max': 1, 'step': 0.01}), 'iou_threshold': ('FLOAT', {'default': 0.1, 'min': 0, 'max': 1, 'step': 0.01}), 'box_thickness': ('INT', {'default': 2, 'min': 1, 'max': 5}), 'text_thickness': ('INT', {'default': 2, 'min': 1, 'max': 5}), 'text_scale': ('FLOAT', {'default': 1.0, 'min': 0, 'max': 1, 'step': 0.01}), 'with_confidence': ('BOOLEAN', {'default': True}), 'with_class_agnostic_nms': ('BOOLEAN', {'default': False}), 'with_segmentation': ('BOOLEAN', {'default': True}), 'mask_combined': ('BOOLEAN', {'default': True}), 'mask_extracted': ('BOOLEAN', {'default': True}), 'mask_extracted_index': ('INT', {'default': 0, 'min': 0, 'max': 1000})}} + RETURN_TYPES = ('IMAGE', 'MASK') + FUNCTION = 'yoloworld_esam_image' + CATEGORY = 'YOLOWORLD_ESAM' + + def yoloworld_esam_image(self, image, yolo_world_model, esam_model, categories, confidence_threshold, iou_threshold, box_thickness, text_thickness, text_scale, with_segmentation, mask_combined, with_confidence, with_class_agnostic_nms, mask_extracted, mask_extracted_index): + categories = process_categories(categories) + processed_images = [] + processed_masks = [] + for img in image: + img = np.clip(255.0 * img.cpu().numpy().squeeze(), 0, 255).astype(np.uint8) + YOLO_WORLD_MODEL = yolo_world_model + YOLO_WORLD_MODEL.set_classes(categories) + results = YOLO_WORLD_MODEL.infer(img, confidence=confidence_threshold) + detections = sv.Detections.from_inference(results) + detections = detections.with_nms(class_agnostic=with_class_agnostic_nms, threshold=iou_threshold) + combined_mask = None + if with_segmentation: + detections.mask = inference_with_boxes(image=img, xyxy=detections.xyxy, model=esam_model, device=DEVICE) + if mask_combined: + combined_mask = np.zeros(img.shape[:2], dtype=np.uint8) + det_mask = detections.mask + for mask in det_mask: + combined_mask = np.logical_or(combined_mask, mask).astype(np.uint8) + masks_tensor = torch.tensor(combined_mask, dtype=torch.float32) + processed_masks.append(masks_tensor) + else: + det_mask = detections.mask + if mask_extracted: + mask_index = mask_extracted_index + selected_mask = det_mask[mask_index] + masks_tensor = torch.tensor(selected_mask, dtype=torch.float32) + else: + masks_tensor = torch.tensor(det_mask, dtype=torch.float32) + processed_masks.append(masks_tensor) + output_image = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) + output_image = annotate_image(input_image=output_image, detections=detections, categories=categories, with_confidence=with_confidence, thickness=box_thickness, text_thickness=text_thickness, text_scale=text_scale) + output_image = cv2.cvtColor(output_image, cv2.COLOR_BGR2RGB) + output_image = torch.from_numpy(output_image.astype(np.float32) / 255.0).unsqueeze(0) + processed_images.append(output_image) + new_ims = torch.cat(processed_images, dim=0) + if processed_masks: + new_masks = torch.stack(processed_masks, dim=0) + else: + new_masks = torch.empty(0) + return (new_ims, new_masks) +``` \ No newline at end of file diff --git a/docs/Yoloworld_ModelLoader_Zho.md b/docs/Yoloworld_ModelLoader_Zho.md new file mode 100644 index 0000000..2c099d7 --- /dev/null +++ b/docs/Yoloworld_ModelLoader_Zho.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: Yoloworld_ModelLoader_Zho +- Category: 🔎YOLOWORLD_ESAM +- Output node: False +- Repo Ref: https://github.com/ZHO-ZHO-ZHO/ComfyUI-YoloWorld-EfficientSAM.git + +Yoloworld_ModelLoader_Zho 类旨在方便加载和初始化特定应用的 YOLO (You Only Look Once) 目标检测模型。它封装了模型加载的复杂性,使用户能够轻松地将 YOLO 模型集成到他们的项目中,而无需深入了解模型配置的复杂细节。 + +# Input types +## Required +- yolo_world_model + - 参数 `yolo_world_model` 对于指定要加载的 YOLO 模型变体至关重要。它决定了节点将使用的特定配置和预训练权重,这直接影响模型在目标检测任务中的性能和准确性。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- yolo_world_model + - 输出 `yolo_world_model` 表示已加载的 YOLO 模型,准备用于目标检测任务。它是节点功能的最终成果,为与模型交互以对新数据执行推理提供了一个结构化的接口。 + - Comfy dtype: YOLOWORLDMODEL + - Python dtype: YOLOWorld + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Yoloworld_ModelLoader_Zho: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'yolo_world_model': (['yolo_world/l', 'yolo_world/m', 'yolo_world/s'],)}} + RETURN_TYPES = ('YOLOWORLDMODEL',) + RETURN_NAMES = ('yolo_world_model',) + FUNCTION = 'load_yolo_world_model' + CATEGORY = '🔎YOLOWORLD_ESAM' + + def load_yolo_world_model(self, yolo_world_model): + YOLO_WORLD_MODEL = YOLOWorld(model_id=yolo_world_model) + return [YOLO_WORLD_MODEL] +``` \ No newline at end of file diff --git a/docs/ZipPrompt %2F%2FInspire.md b/docs/ZipPrompt %2F%2FInspire.md new file mode 100644 index 0000000..40cbf76 --- /dev/null +++ b/docs/ZipPrompt %2F%2FInspire.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: ZipPrompt +- Category: InspirePack/Prompt +- Output node: False +- Repo Ref: https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git + +ZipPrompt节点高效地将正面和负面提示合并成单一的压缩实体,增强了创意任务中数据处理的多功能性。它强调了该节点在简化提示合并过程中的作用,而不会深入到具体的实现细节。 + +# Input types +## Required +- positive + - ‘positive’参数对于提供正面内容至节点操作非常必要,是创建压缩提示的关键元素。 + - Comfy dtype: STRING + - Python dtype: str +- negative + - ‘negative’参数在提供对比内容方面起着至关重要的作用,这对于压缩提示的全面性至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- name_opt + - 虽然‘name_opt’参数是可选的,但它可以用来自定义输出,为压缩提示增加个性化层次。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- zipped_prompt + - 输出‘zipped_prompt’代表了正面和负面输入的结合,封装成紧凑有序的格式以供进一步使用。 + - Comfy dtype: ZIPPED_PROMPT + - Python dtype: Tuple[str, str, str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ZipPrompt: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'positive': ('STRING', {'forceInput': True, 'multiline': True}), 'negative': ('STRING', {'forceInput': True, 'multiline': True})}, 'optional': {'name_opt': ('STRING', {'forceInput': True, 'multiline': False})}} + RETURN_TYPES = ('ZIPPED_PROMPT',) + FUNCTION = 'doit' + CATEGORY = 'InspirePack/Prompt' + + def doit(self, positive, negative, name_opt=''): + return ((positive, negative, name_opt),) +``` \ No newline at end of file diff --git a/docs/color_drop.md b/docs/color_drop.md new file mode 100644 index 0000000..c2052eb --- /dev/null +++ b/docs/color_drop.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: color_drop +- Category: Image Processing +- Output node: False +- Repo Ref: https://github.com/jags111/ComfyUI_Jags_VectorMagic + +该节点类通过应用颜色丢弃效果来处理图像数据,通过压平颜色光谱来增强输入图像的视觉特征。 + +# Input types +## Required +- images + - 输入图像对于节点的操作至关重要,它们作为颜色丢弃过程的基础。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +## Optional +- number_of_colors + - 该参数影响颜色压平效果的粒度,较高的数值会导致输出中颜色带更加明显。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- Image + - 输出是应用了颜色丢弃效果的图像,展示了预期的视觉增强效果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class color_drop: + """ + This node provides a simple interface to apply PixelSort blur to the output image. + """ + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + """ + Input Types + """ + return {'required': {'images': ('IMAGE',)}, 'optional': {'number_of_colors': ('INT', {'default': 2, 'min': 1, 'max': 4000, 'step': 1})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('Image',) + FUNCTION = 'flatten' +``` \ No newline at end of file diff --git a/docs/convertKeyframeKeysToBatchKeys.md b/docs/convertKeyframeKeysToBatchKeys.md new file mode 100644 index 0000000..8735945 --- /dev/null +++ b/docs/convertKeyframeKeysToBatchKeys.md @@ -0,0 +1,44 @@ +# Documentation +- Class name: convertKeyframeKeysToBatchKeys +- Category: FizzNodes 📅🅕🅝/HelperNodes +- Output node: False +- Repo Ref: https://github.com/FizzleDorf/ComfyUI_FizzNodes + +在'convertKeyframeKeysToBatchKeys'节点中的'concat'方法旨在将关键帧数据高效地组合成单个批次进行处理。它通过将输入的关键帧数量乘以潜在维度的数量来实现这一点,从而创建一个适合批量操作的连续序列。此方法对于优化大规模动画或模拟中关键帧数据的处理至关重要。 + +# Input types +## Required +- input + - 'input'参数代表要处理的关键帧数量。它是节点操作的基本部分,因为它直接影响创建的批次大小,进而影响后续处理步骤的效率。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- num_latents + - 'num_latents'参数指定要考虑的关键帧数据中的潜在维度数量。它对于确定批次的最终结构至关重要,确保数据适当地组织以适应下游任务。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- result + - 'result'输出提供了计算出的批次关键序列,这是输入关键帧计数和潜在维度数量的乘积。这个输出很重要,因为它构成了动画或模拟流水线中进一步处理和分析的基础。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class convertKeyframeKeysToBatchKeys: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'input': ('INT', {'forceInput': True, 'default': 0}), 'num_latents': ('INT', {'default': 16})}} + RETURN_TYPES = ('INT',) + FUNCTION = 'concat' + CATEGORY = 'FizzNodes 📅🅕🅝/HelperNodes' + + def concat(self, input, num_latents): + c = input * num_latents - 1 + return (c,) +``` \ No newline at end of file diff --git a/docs/easy LLLiteLoader.md b/docs/easy LLLiteLoader.md new file mode 100644 index 0000000..aa3e124 --- /dev/null +++ b/docs/easy LLLiteLoader.md @@ -0,0 +1,75 @@ +# Documentation +- Class name: LLLiteLoader +- Category: EasyUse/Loaders +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +LLLiteLoader节点旨在便于轻量级模型的集成,通过加入额外的模型功能来增强系统的整体处理能力。 + +# Input types +## Required +- model + - 模型参数至关重要,它定义了节点将使用和修改的基础架构,显著影响节点的输出和行为。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- model_name + - 该参数对于从列表中选择适当的模型至关重要,根据所选模型的特性和预期应用引导节点的处理。 + - Comfy dtype: COMBO + - Python dtype: str +- cond_image + - cond_image参数很重要,因为它提供了模型适应其输出到特定条件所需的上下文信息,影响最终结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +## Optional +- strength + - strength参数调整模型对条件的适应强度,可用于微调节点的输出以满足不同要求。 + - Comfy dtype: FLOAT + - Python dtype: float +- steps + - steps参数定义了模型将经历的迭代次数,这直接影响节点处理的复杂性和准确性。 + - Comfy dtype: INT + - Python dtype: int +- start_percent + - 该参数设置了模型适应过程的起点,影响初始条件和节点执行的进展。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_percent + - end_percent参数确定了模型适应的终点,影响节点操作的最终状态和结果。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- model + - 输出模型是节点处理的结果,包含了适应的特性和条件,准备好在后续任务中使用。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: CPU + +# Source code +``` +class LLLiteLoader: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + + def get_file_list(filenames): + return [file for file in filenames if file != 'put_models_here.txt' and 'lllite' in file] + return {'required': {'model': ('MODEL',), 'model_name': (get_file_list(folder_paths.get_filename_list('controlnet')),), 'cond_image': ('IMAGE',), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'steps': ('INT', {'default': 0, 'min': 0, 'max': 200, 'step': 1}), 'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 100.0, 'step': 0.1}), 'end_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 100.0, 'step': 0.1})}} + RETURN_TYPES = ('MODEL',) + FUNCTION = 'load_lllite' + CATEGORY = 'EasyUse/Loaders' + + def load_lllite(self, model, model_name, cond_image, strength, steps, start_percent, end_percent): + model_path = os.path.join(folder_paths.get_full_path('controlnet', model_name)) + model_lllite = model.clone() + patch = load_control_net_lllite_patch(model_path, cond_image, strength, steps, start_percent, end_percent) + if patch is not None: + model_lllite.set_model_attn1_patch(patch) + model_lllite.set_model_attn2_patch(patch) + return (model_lllite,) +``` \ No newline at end of file diff --git a/docs/easy XYPlot.md b/docs/easy XYPlot.md new file mode 100644 index 0000000..410dcc6 --- /dev/null +++ b/docs/easy XYPlot.md @@ -0,0 +1,116 @@ +# Documentation +- Class name: pipeXYPlot +- Category: EasyUse/Pipe +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +pipeXYPlot节点旨在简化生成和管理XY图的过程,为用户提供一个简化的界面来可视化数据关系。它专注于提供一个用户友好的体验,使得即使没有广泛的技术知识也能创建具有各种定制选项的图表。 + +# Input types +## Required +- grid_spacing + - 网格间距是一个关键参数,决定了图表的分辨率。它影响可视化的粒度,较高的值导致更粗糙的表示,而较低的值则提供更细致的细节。 + - Comfy dtype: INT + - Python dtype: int +- output_individuals + - 输出个体参数允许用户控制是否分别绘制每个数据点。这在处理大型数据集时,尤其能够显著影响图表的清晰度。 + - Comfy dtype: BOOL + - Python dtype: bool +- flip_xy + - 启用翻转XY允许用户反转图表的轴,这对于根据特定约定对齐数据或更好地视觉表示非常有用。 + - Comfy dtype: BOOL + - Python dtype: bool +- x_axis + - x_axis参数对于定义图表的水平轴至关重要。它决定了将用于表示x值的类别或变量,从而塑造了整个图表的结构。 + - Comfy dtype: COMBO + - Python dtype: str +- x_values + - x值对于图表的构建至关重要,因为它们提供了x轴的数据点。正确输入这些值确保了图表表示的准确性和相关性。 + - Comfy dtype: STRING + - Python dtype: str +- y_axis + - y_axis参数对于定义图表的垂直轴至关重要。它指定了将用于表示y值的类别或变量,从而影响了数据的整体解释。 + - Comfy dtype: COMBO + - Python dtype: str +- y_values + - y值对于绘图至关重要,因为它们代表了y轴上的数据点。准确输入这些值对于图表中数据的真实反映是必要的。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- pipe + - 输出名为'pipe',是一个包含整个图表配置的综合结构,包括轴、值和其他设置。它作为可视化过程的通道,确保图表根据用户的规格生成。 + - Comfy dtype: PIPE_LINE + - Python dtype: dict + +# Usage tips +- Infra type: CPU + +# Source code +``` +class pipeXYPlot: + lora_list = ['None'] + folder_paths.get_filename_list('loras') + lora_strengths = {'min': -4.0, 'max': 4.0, 'step': 0.01} + token_normalization = ['none', 'mean', 'length', 'length+mean'] + weight_interpretation = ['comfy', 'A1111', 'compel', 'comfy++'] + loader_dict = {'ckpt_name': folder_paths.get_filename_list('checkpoints'), 'vae_name': ['Baked-VAE'] + folder_paths.get_filename_list('vae'), 'clip_skip': {'min': -24, 'max': -1, 'step': 1}, 'lora_name': lora_list, 'lora_model_strength': lora_strengths, 'lora_clip_strength': lora_strengths, 'positive': [], 'negative': []} + sampler_dict = {'steps': {'min': 1, 'max': 100, 'step': 1}, 'cfg': {'min': 0.0, 'max': 100.0, 'step': 1.0}, 'sampler_name': comfy.samplers.KSampler.SAMPLERS, 'scheduler': comfy.samplers.KSampler.SCHEDULERS, 'denoise': {'min': 0.0, 'max': 1.0, 'step': 0.01}, 'seed': {'min': 0, 'max': MAX_SEED_NUM}} + plot_dict = {**sampler_dict, **loader_dict} + plot_values = ['None'] + plot_values.append('---------------------') + for k in sampler_dict: + plot_values.append(f'preSampling: {k}') + plot_values.append('---------------------') + for k in loader_dict: + plot_values.append(f'loader: {k}') + + def __init__(self): + pass + rejected = ['None', '---------------------', 'Nothing'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'grid_spacing': ('INT', {'min': 0, 'max': 500, 'step': 5, 'default': 0}), 'output_individuals': (['False', 'True'], {'default': 'False'}), 'flip_xy': (['False', 'True'], {'default': 'False'}), 'x_axis': (pipeXYPlot.plot_values, {'default': 'None'}), 'x_values': ('STRING', {'default': '', 'multiline': True, 'placeholder': 'insert values seperated by "; "'}), 'y_axis': (pipeXYPlot.plot_values, {'default': 'None'}), 'y_values': ('STRING', {'default': '', 'multiline': True, 'placeholder': 'insert values seperated by "; "'})}, 'optional': {'pipe': ('PIPE_LINE',)}, 'hidden': {'plot_dict': (pipeXYPlot.plot_dict,)}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('pipe',) + FUNCTION = 'plot' + CATEGORY = 'EasyUse/Pipe' + + def plot(self, grid_spacing, output_individuals, flip_xy, x_axis, x_values, y_axis, y_values, pipe=None): + + def clean_values(values): + original_values = values.split('; ') + cleaned_values = [] + for value in original_values: + cleaned_value = value.strip(';').strip() + if cleaned_value == '': + continue + try: + cleaned_value = int(cleaned_value) + except ValueError: + try: + cleaned_value = float(cleaned_value) + except ValueError: + pass + cleaned_values.append(cleaned_value) + return cleaned_values + if x_axis in self.rejected: + x_axis = 'None' + x_values = [] + else: + x_values = clean_values(x_values) + if y_axis in self.rejected: + y_axis = 'None' + y_values = [] + else: + y_values = clean_values(y_values) + if flip_xy == 'True': + (x_axis, y_axis) = (y_axis, x_axis) + (x_values, y_values) = (y_values, x_values) + xy_plot = {'x_axis': x_axis, 'x_vals': x_values, 'y_axis': y_axis, 'y_vals': y_values, 'grid_spacing': grid_spacing, 'output_individuals': output_individuals} + if pipe is not None: + new_pipe = pipe + new_pipe['loader_settings'] = {**pipe['loader_settings'], 'xyplot': xy_plot} + del pipe + return (new_pipe, xy_plot) +``` \ No newline at end of file diff --git a/docs/easy XYPlotAdvanced.md b/docs/easy XYPlotAdvanced.md new file mode 100644 index 0000000..63bbfd4 --- /dev/null +++ b/docs/easy XYPlotAdvanced.md @@ -0,0 +1,209 @@ +# Documentation +- Class name: pipeXYPlotAdvanced +- Category: EasyUse/Pipe +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点提供高级XY绘图功能,专为满足管道线路的需求而设计。它与各种数据类型和设置集成,以生成可视化图表,提供对管道内数据结构和关系的洞察。节点的设计强调适应性和易用性,确保用户能够快速生成有意义的可视化图表,而无需进行广泛的配置。 + +# Input types +## Required +- pipe + - ‘pipe’参数是此节点的主干,代表从中提取和可视化数据的管道线路。它对节点的运行至关重要,因为它包含了绘图所需的所有必要信息和设置。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict +- grid_spacing + - ‘grid_spacing’参数决定了图表中网格线之间的间距,影响可视化的整体清晰度和可读性。它在以易于理解的方式呈现数据点和趋势方面发挥着重要作用。 + - Comfy dtype: INT + - Python dtype: int +- output_individuals + - ‘output_individuals’参数允许用户控制是否在图表中单独显示各个数据点。这对于分析特定数据点及其在数据集中的关系非常重要。 + - Comfy dtype: BOOL + - Python dtype: bool +- flip_xy + - ‘flip_xy’参数允许用户翻转X轴和Y轴,这在某些数据可视化场景中非常有用,尤其是当传统方向不是最佳选择时。 + - Comfy dtype: BOOL + - Python dtype: bool +## Optional +- X + - ‘X’参数代表X轴的配置,包括轴标签和相关值。它对于定义图表的水平维度至关重要,并且可以通过各种模型和设置进行定制。 + - Comfy dtype: X_Y + - Python dtype: Dict +- Y + - ‘Y’参数对应于Y轴的配置,指定轴标签和相应的值。它对于建立图表的垂直维度至关重要,并且可以通过不同的模型和设置进行调整。 + - Comfy dtype: X_Y + - Python dtype: Dict + +# Output types +- pipe + - ‘pipe’输出是输入‘pipe’的更新版本,现在包含了生成的XY图表信息。它代表了管道的进展,将可视化结果重新整合到数据流中,以便进一步分析或处理。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict + +# Usage tips +- Infra type: CPU + +# Source code +``` +class pipeXYPlotAdvanced: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',), 'grid_spacing': ('INT', {'min': 0, 'max': 500, 'step': 5, 'default': 0}), 'output_individuals': (['False', 'True'], {'default': 'False'}), 'flip_xy': (['False', 'True'], {'default': 'False'})}, 'optional': {'X': ('X_Y',), 'Y': ('X_Y',)}, 'hidden': {'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('pipe',) + FUNCTION = 'plot' + CATEGORY = 'EasyUse/Pipe' + + def plot(self, pipe, grid_spacing, output_individuals, flip_xy, X=None, Y=None, my_unique_id=None): + if X != None: + x_axis = X.get('axis') + x_values = X.get('values') + else: + x_axis = 'Nothing' + x_values = [''] + if Y != None: + y_axis = Y.get('axis') + y_values = Y.get('values') + else: + y_axis = 'Nothing' + y_values = [''] + if pipe is not None: + new_pipe = pipe + positive = pipe['loader_settings']['positive'] if 'positive' in pipe['loader_settings'] else '' + negative = pipe['loader_settings']['negative'] if 'negative' in pipe['loader_settings'] else '' + if x_axis == 'advanced: ModelMergeBlocks': + models = X.get('models') + vae_use = X.get('vae_use') + if models is None: + raise Exception('models is not found') + new_pipe['loader_settings'] = {**pipe['loader_settings'], 'models': models, 'vae_use': vae_use} + if y_axis == 'advanced: ModelMergeBlocks': + models = Y.get('models') + vae_use = Y.get('vae_use') + if models is None: + raise Exception('models is not found') + new_pipe['loader_settings'] = {**pipe['loader_settings'], 'models': models, 'vae_use': vae_use} + if x_axis in ['advanced: Lora', 'advanced: Checkpoint']: + lora_stack = X.get('lora_stack') + _lora_stack = [] + if lora_stack is not None: + for lora in lora_stack: + _lora_stack.append({'lora_name': lora[0], 'model': pipe['model'], 'clip': pipe['clip'], 'model_strength': lora[1], 'clip_strength': lora[2]}) + del lora_stack + x_values = '; '.join(x_values) + lora_stack = pipe['lora_stack'] + _lora_stack if 'lora_stack' in pipe else _lora_stack + new_pipe['loader_settings'] = {**pipe['loader_settings'], 'lora_stack': lora_stack} + if y_axis in ['advanced: Lora', 'advanced: Checkpoint']: + lora_stack = Y.get('lora_stack') + _lora_stack = [] + if lora_stack is not None: + for lora in lora_stack: + _lora_stack.append({'lora_name': lora[0], 'model': pipe['model'], 'clip': pipe['clip'], 'model_strength': lora[1], 'clip_strength': lora[2]}) + del lora_stack + y_values = '; '.join(y_values) + lora_stack = pipe['lora_stack'] + _lora_stack if 'lora_stack' in pipe else _lora_stack + new_pipe['loader_settings'] = {**pipe['loader_settings'], 'lora_stack': lora_stack} + if x_axis == 'advanced: Seeds++ Batch': + if new_pipe['seed']: + value = x_values + x_values = [] + for index in range(value): + x_values.append(str(new_pipe['seed'] + index)) + x_values = '; '.join(x_values) + if y_axis == 'advanced: Seeds++ Batch': + if new_pipe['seed']: + value = y_values + y_values = [] + for index in range(value): + y_values.append(str(new_pipe['seed'] + index)) + y_values = '; '.join(y_values) + if x_axis == 'advanced: Positive Prompt S/R': + if positive: + x_value = x_values + x_values = [] + for (index, value) in enumerate(x_value): + (search_txt, replace_txt, replace_all) = value + if replace_all: + txt = replace_txt if replace_txt is not None else positive + x_values.append(txt) + else: + txt = positive.replace(search_txt, replace_txt, 1) if replace_txt is not None else positive + x_values.append(txt) + x_values = '; '.join(x_values) + if y_axis == 'advanced: Positive Prompt S/R': + if positive: + y_value = y_values + y_values = [] + for (index, value) in enumerate(y_value): + (search_txt, replace_txt, replace_all) = value + if replace_all: + txt = replace_txt if replace_txt is not None else positive + y_values.append(txt) + else: + txt = positive.replace(search_txt, replace_txt, 1) if replace_txt is not None else positive + y_values.append(txt) + y_values = '; '.join(y_values) + if x_axis == 'advanced: Negative Prompt S/R': + if negative: + x_value = x_values + x_values = [] + for (index, value) in enumerate(x_value): + (search_txt, replace_txt, replace_all) = value + if replace_all: + txt = replace_txt if replace_txt is not None else negative + x_values.append(txt) + else: + txt = negative.replace(search_txt, replace_txt, 1) if replace_txt is not None else negative + x_values.append(txt) + x_values = '; '.join(x_values) + if y_axis == 'advanced: Negative Prompt S/R': + if negative: + y_value = y_values + y_values = [] + for (index, value) in enumerate(y_value): + (search_txt, replace_txt, replace_all) = value + if replace_all: + txt = replace_txt if replace_txt is not None else negative + y_values.append(txt) + else: + txt = negative.replace(search_txt, replace_txt, 1) if replace_txt is not None else negative + y_values.append(txt) + y_values = '; '.join(y_values) + if 'advanced: ControlNet' in x_axis: + x_value = x_values + x_values = [] + cnet = [] + for (index, value) in enumerate(x_value): + cnet.append(value) + x_values.append(str(index)) + x_values = '; '.join(x_values) + new_pipe['loader_settings'] = {**pipe['loader_settings'], 'cnet_stack': cnet} + if 'advanced: ControlNet' in y_axis: + y_value = y_values + y_values = [] + cnet = [] + for (index, value) in enumerate(y_value): + cnet.append(value) + y_values.append(str(index)) + y_values = '; '.join(y_values) + new_pipe['loader_settings'] = {**pipe['loader_settings'], 'cnet_stack': cnet} + if 'advanced: Pos Condition' in x_axis: + x_values = '; '.join(x_values) + cond = X.get('cond') + new_pipe['loader_settings'] = {**pipe['loader_settings'], 'positive_cond_stack': cond} + if 'advanced: Pos Condition' in y_axis: + y_values = '; '.join(y_values) + cond = Y.get('cond') + new_pipe['loader_settings'] = {**pipe['loader_settings'], 'positive_cond_stack': cond} + if 'advanced: Neg Condition' in x_axis: + x_values = '; '.join(x_values) + cond = X.get('cond') + new_pipe['loader_settings'] = {**pipe['loader_settings'], 'negative_cond_stack': cond} + if 'advanced: Neg Condition' in y_axis: + y_values = '; '.join(y_values) + cond = Y.get('cond') + new_pipe['loader_settings'] = {**pipe['loader_settings'], 'negative_cond_stack': cond} + del pipe + return pipeXYPlot().plot(grid_spacing, output_individuals, flip_xy, x_axis, x_values, y_axis, y_values, new_pipe) +``` \ No newline at end of file diff --git a/docs/easy a1111Loader.md b/docs/easy a1111Loader.md new file mode 100644 index 0000000..b441354 --- /dev/null +++ b/docs/easy a1111Loader.md @@ -0,0 +1,95 @@ +# Documentation +- Class name: a1111Loader +- Category: EasyUse/Loaders +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点便于加载和整合各种模型组件,包括检查点、VAE 和 LORA 栈,以建立一个全面的管道,根据提供的提示和参数处理和生成图像。 + +# Input types +## Required +- ckpt_name + - 检查点名称对于指定要加载的模型状态至关重要,它直接影响节点根据所需配置生成图像的能力。 + - Comfy dtype: COMBO + - Python dtype: str +- vae_name + - VAE名称参数对于选择适当的变分自编码器模型至关重要,它在图像生成过程中起着重要作用。 + - Comfy dtype: COMBO + - Python dtype: str +- clip_skip + - clip_skip 参数对于控制CLIP与模型之间的交互很重要,影响节点的效率和生成图像的质量。 + - Comfy dtype: INT + - Python dtype: int +- lora_name + - LORA名称参数对于应用模型特定的增强至关重要,它可以显著提高节点在图像生成任务中的性能。 + - Comfy dtype: COMBO + - Python dtype: str +- lora_model_strength + - lora_model_strength 参数调整LORA增强对模型的影响,影响节点根据特定要求微调图像生成的能力。 + - Comfy dtype: FLOAT + - Python dtype: float +- lora_clip_strength + - lora_clip_strength 参数修改CLIP与LORA集成的强度,这对于实现平衡和协调的图像生成过程至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- resolution + - 分辨率参数定义了输出图像的大小,这是决定节点能够产生高质量视觉效果的关键因素。 + - Comfy dtype: COMBO + - Python dtype: str +- empty_latent_width + - empty_latent_width 参数设置了潜在空间的宽度,对于节点生成多样化和复杂图像模式的能力至关重要。 + - Comfy dtype: INT + - Python dtype: int +- empty_latent_height + - empty_latent_height 参数建立了潜在空间的高度,影响了节点创建详细和细腻图像的能力。 + - Comfy dtype: INT + - Python dtype: int +- positive + - positive 参数提供正面提示来指导图像生成过程,显著影响节点的输出质量和相关性。 + - Comfy dtype: STRING + - Python dtype: str +- negative + - negative 参数提供负面提示来完善图像生成,专注于节点在输出中避免不需要的特征的能力。 + - Comfy dtype: STRING + - Python dtype: str +- batch_size + - batch_size 参数决定了同时处理的图像数量,这影响了节点的吞吐量和效率。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- pipe + - pipe 输出封装了加载的模型和设置,为后续的图像生成和处理任务提供了基础。 + - Comfy dtype: PIPE_LINE + - Python dtype: dict +- model + - model 输出提供了加载的模型,这对于根据输入提示和参数执行图像生成至关重要。 + - Comfy dtype: MODEL + - Python dtype: ModelPatcher +- vae + - vae 输出包含加载的VAE模型,这对于生成和处理潜在空间和图像至关重要。 + - Comfy dtype: VAE + - Python dtype: VAE + +# Usage tips +- Infra type: CPU + +# Source code +``` +class a1111Loader: + + @classmethod + def INPUT_TYPES(cls): + resolution_strings = [f'{width} x {height}' for (width, height) in BASE_RESOLUTIONS] + a1111_prompt_style_default = False + checkpoints = folder_paths.get_filename_list('checkpoints') + loras = ['None'] + folder_paths.get_filename_list('loras') + return {'required': {'ckpt_name': (checkpoints,), 'vae_name': (['Baked VAE'] + folder_paths.get_filename_list('vae'),), 'clip_skip': ('INT', {'default': -1, 'min': -24, 'max': 0, 'step': 1}), 'lora_name': (loras,), 'lora_model_strength': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'lora_clip_strength': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'resolution': (resolution_strings, {'default': '512 x 512'}), 'empty_latent_width': ('INT', {'default': 512, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'empty_latent_height': ('INT', {'default': 512, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'positive': ('STRING', {'default': 'Positive', 'multiline': True}), 'negative': ('STRING', {'default': 'Negative', 'multiline': True}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}, 'optional': {'optional_lora_stack': ('LORA_STACK',), 'a1111_prompt_style': ('BOOLEAN', {'default': a1111_prompt_style_default})}, 'hidden': {'prompt': 'PROMPT', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE', 'MODEL', 'VAE') + RETURN_NAMES = ('pipe', 'model', 'vae') + FUNCTION = 'adv_pipeloader' + CATEGORY = 'EasyUse/Loaders' + + def adv_pipeloader(self, ckpt_name, vae_name, clip_skip, lora_name, lora_model_strength, lora_clip_strength, resolution, empty_latent_width, empty_latent_height, positive, negative, batch_size, optional_lora_stack=None, a1111_prompt_style=False, prompt=None, my_unique_id=None): + return fullLoader.adv_pipeloader(self, ckpt_name, 'Default', vae_name, clip_skip, lora_name, lora_model_strength, lora_clip_strength, resolution, empty_latent_width, empty_latent_height, positive, 'mean', 'A1111', negative, 'mean', 'A1111', batch_size, None, None, None, optional_lora_stack, a1111_prompt_style, prompt, my_unique_id) +``` \ No newline at end of file diff --git a/docs/easy boolean.md b/docs/easy boolean.md new file mode 100644 index 0000000..dc5ebd3 --- /dev/null +++ b/docs/easy boolean.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: Boolean +- Category: EasyUse/Logic/Type +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点类封装了处理布尔值的逻辑,使得对逻辑数据处理的基本操作和转换成为可能。 + +# Input types +## Required +- value + - ‘value’参数至关重要,因为它决定了布尔操作的输入。它是应用节点逻辑的基础元素,并直接影响节点执行的结果。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- boolean + - 输出‘boolean’代表节点执行的布尔操作的结果。这是一个关键的数据片段,可以用于进一步的逻辑决策或作为工作流中的条件。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Boolean: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'value': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('BOOLEAN',) + RETURN_NAMES = ('boolean',) + FUNCTION = 'execute' + CATEGORY = 'EasyUse/Logic/Type' + + def execute(self, value): + return (value,) +``` \ No newline at end of file diff --git a/docs/easy cascadeKSampler.md b/docs/easy cascadeKSampler.md new file mode 100644 index 0000000..290c234 --- /dev/null +++ b/docs/easy cascadeKSampler.md @@ -0,0 +1,63 @@ +# Documentation +- Class name: samplerCascadeSimple +- Category: EasyUse/Sampler +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +samplerCascadeSimple节点旨在通过提供简化的接口来简化图像采样过程,使用户更容易使用。它抽象了底层采样过程的复杂性,允许用户以最小的配置生成图像。该节点专注于易用性和效率,确保用户可以快速获得所需的输出,而无需深入了解采样算法的细节。 + +# Input types +## Required +- pipe + - ‘pipe’参数对于节点的操作至关重要,因为它代表了包含图像采样所需设置和数据的管道。正是通过此参数,节点接收输入以生成所需的输出图像。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- image_output + - ‘image_output’参数决定了节点生成图像后如何处理这些图像。它决定了图像是预览、保存还是发送,因此在节点的执行流程中扮演着关键角色。 + - Comfy dtype: COMBO['Hide', 'Preview', 'Save', 'Hide/Save', 'Sender', 'Sender/Save'] + - Python dtype: str +- link_id + - ‘link_id’参数用于建立与生成图像的唯一链接或引用。这对于跟踪或将输出与特定用户请求或流程关联可能非常重要。 + - Comfy dtype: INT + - Python dtype: int +- save_prefix + - ‘save_prefix’参数指定保存生成的图像时使用的前缀。这可以影响保存文件的命名约定,使用户更容易识别和组织他们的输出。 + - Comfy dtype: STRING + - Python dtype: str +- model_c + - 可选的‘model_c’参数允许用户提供在采样过程中使用的特定模型。当用户对特定模型有偏好或需要应用特定模型设置时,这可能特别有用。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Output types +- pipe + - ‘pipe’输出提供了采样过程后的更新管道,其中包括生成的图像和任何其他相关数据。这个输出很重要,因为它可能用于进一步的处理或分析。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- image + - ‘image’输出代表采样过程中生成的图像。这是大多数用户最感兴趣的主要输出,因为它是节点操作的视觉结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class samplerCascadeSimple: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'image_output': (['Hide', 'Preview', 'Save', 'Hide/Save', 'Sender', 'Sender/Save'], {'default': 'Preview'}), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'save_prefix': ('STRING', {'default': 'ComfyUI'})}, 'optional': {'model_c': ('MODEL',)}, 'hidden': {'tile_size': 'INT', 'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID', 'embeddingsList': (folder_paths.get_filename_list('embeddings'),)}} + RETURN_TYPES = ('PIPE_LINE', 'IMAGE') + RETURN_NAMES = ('pipe', 'image') + OUTPUT_NODE = True + FUNCTION = 'run' + CATEGORY = 'EasyUse/Sampler' + + def run(self, pipe, image_output, link_id, save_prefix, model_c=None, tile_size=None, prompt=None, extra_pnginfo=None, my_unique_id=None, force_full_denoise=False, disable_noise=False): + return samplerCascadeFull().run(pipe, None, None, None, None, None, None, None, image_output, link_id, save_prefix, None, None, None, model_c, tile_size, prompt, extra_pnginfo, my_unique_id, force_full_denoise, disable_noise) +``` \ No newline at end of file diff --git a/docs/easy cascadeLoader.md b/docs/easy cascadeLoader.md new file mode 100644 index 0000000..a3d8a48 --- /dev/null +++ b/docs/easy cascadeLoader.md @@ -0,0 +1,116 @@ +# Documentation +- Class name: cascadeLoader +- Category: EasyUse/Loaders +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +cascadeLoader节点类旨在简化流水线中各种模型和数据的加载和处理。它封装了模型检索、通过LORA增强以及对正负输入应用CLIP嵌入的复杂性。该节点旨在提供这些组件的无缝集成,确保高效的数据流和最佳性能。 + +# Input types +## Required +- stage_c + - stage_c参数对于指定流水线中使用的checkpoint或UNet模型至关重要。它决定了模型加载的起点,并对后续处理步骤有直接影响。 + - Comfy dtype: COMBO[folder_paths.get_filename_list('unet') + folder_paths.get_filename_list('checkpoints'),] + - Python dtype: Union[str, None] +- resolution + - 分辨率输入对于定义潜在空间和输出图像的尺寸至关重要。它影响生成内容的质量和分辨率,从而影响流水线的整体结果。 + - Comfy dtype: COMBO[BASE_RESOLUTIONS] + - Python dtype: Union[str, Tuple[int, int]] + +# Output types +- pipe + - pipe输出封装了为下游任务准备的加工模型、嵌入和其他相关数据。这是一个关键的输出,它使得流水线中的进一步操作和精细化成为可能。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class cascadeLoader: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + resolution_strings = [f'{width} x {height}' for (width, height) in BASE_RESOLUTIONS] + return {'required': {'stage_c': (folder_paths.get_filename_list('unet') + folder_paths.get_filename_list('checkpoints'),), 'stage_b': (folder_paths.get_filename_list('unet') + folder_paths.get_filename_list('checkpoints'),), 'stage_a': (['Baked VAE'] + folder_paths.get_filename_list('vae'),), 'clip_name': (['None'] + folder_paths.get_filename_list('clip'),), 'lora_name': (['None'] + folder_paths.get_filename_list('loras'),), 'lora_model_strength': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'lora_clip_strength': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'resolution': (resolution_strings, {'default': '1024 x 1024'}), 'empty_latent_width': ('INT', {'default': 1024, 'min': 16, 'max': MAX_RESOLUTION, 'step': 8}), 'empty_latent_height': ('INT', {'default': 1024, 'min': 16, 'max': MAX_RESOLUTION, 'step': 8}), 'compression': ('INT', {'default': 42, 'min': 32, 'max': 64, 'step': 1}), 'positive': ('STRING', {'default': 'Positive', 'multiline': True}), 'negative': ('STRING', {'default': '', 'multiline': True}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}, 'optional': {'optional_lora_stack': ('LORA_STACK',)}, 'hidden': {'prompt': 'PROMPT', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE', 'MODEL', 'LATENT', 'VAE') + RETURN_NAMES = ('pipe', 'model_c', 'latent_c', 'vae') + FUNCTION = 'adv_pipeloader' + CATEGORY = 'EasyUse/Loaders' + + def is_ckpt(self, name): + is_ckpt = False + path = folder_paths.get_full_path('checkpoints', name) + if path is not None: + is_ckpt = True + return is_ckpt + + def adv_pipeloader(self, stage_c, stage_b, stage_a, clip_name, lora_name, lora_model_strength, lora_clip_strength, resolution, empty_latent_width, empty_latent_height, compression, positive, negative, batch_size, optional_lora_stack=None, prompt=None, my_unique_id=None): + vae: VAE | None = None + model_c: ModelPatcher | None = None + model_b: ModelPatcher | None = None + clip: CLIP | None = None + can_load_lora = True + pipe_lora_stack = [] + if resolution != '自定义 x 自定义': + try: + (width, height) = map(int, resolution.split(' x ')) + empty_latent_width = width + empty_latent_height = height + except ValueError: + raise ValueError('Invalid base_resolution format.') + latent_c = torch.zeros([batch_size, 16, empty_latent_height // compression, empty_latent_width // compression]) + latent_b = torch.zeros([batch_size, 4, empty_latent_height // 4, empty_latent_width // 4]) + samples = ({'samples': latent_c}, {'samples': latent_b}) + easyCache.update_loaded_objects(prompt) + if self.is_ckpt(stage_c): + (model_c, clip, vae_c, clip_vision) = easyCache.load_checkpoint(stage_c) + else: + model_c = easyCache.load_unet(stage_c) + vae_c = None + if self.is_ckpt(stage_b): + (model_b, clip, vae_b, clip_vision) = easyCache.load_checkpoint(stage_b) + else: + model_b = easyCache.load_unet(stage_b) + vae_b = None + if optional_lora_stack is not None and can_load_lora: + for lora in optional_lora_stack: + lora = {'lora_name': lora[0], 'model': model_c, 'clip': clip, 'model_strength': lora[1], 'clip_strength': lora[2]} + (model_c, clip) = easyCache.load_lora(lora) + lora['model'] = model_c + lora['clip'] = clip + pipe_lora_stack.append(lora) + if lora_name != 'None' and can_load_lora: + lora = {'lora_name': lora_name, 'model': model_c, 'clip': clip, 'model_strength': lora_model_strength, 'clip_strength': lora_clip_strength} + (model_c, clip) = easyCache.load_lora(lora) + pipe_lora_stack.append(lora) + model = (model_c, model_b) + if clip_name != 'None': + clip = easyCache.load_clip(clip_name, 'stable_cascade') + if stage_a not in ['Baked VAE', 'Baked-VAE']: + vae_b = easyCache.load_vae(stage_a) + vae = (vae_c, vae_b) + is_positive_linked_styles_selector = is_linked_styles_selector(prompt, my_unique_id, 'positive') + is_negative_linked_styles_selector = is_linked_styles_selector(prompt, my_unique_id, 'negative') + log_node_warn('正在处理提示词...') + positive_seed = find_wildcards_seed(my_unique_id, positive, prompt) + (model_c, clip, positive, positive_decode, show_positive_prompt, pipe_lora_stack) = process_with_loras(positive, model_c, clip, 'positive', positive_seed, can_load_lora, pipe_lora_stack, easyCache) + positive_wildcard_prompt = positive_decode if show_positive_prompt or is_positive_linked_styles_selector else '' + negative_seed = find_wildcards_seed(my_unique_id, negative, prompt) + (model_c, clip, negative, negative_decode, show_negative_prompt, pipe_lora_stack) = process_with_loras(negative, model_c, clip, 'negative', negative_seed, can_load_lora, pipe_lora_stack, easyCache) + negative_wildcard_prompt = negative_decode if show_negative_prompt or is_negative_linked_styles_selector else '' + tokens = clip.tokenize(positive) + (cond, pooled) = clip.encode_from_tokens(tokens, return_pooled=True) + positive_embeddings_final = [[cond, {'pooled_output': pooled}]] + tokens = clip.tokenize(negative) + (cond, pooled) = clip.encode_from_tokens(tokens, return_pooled=True) + negative_embeddings_final = [[cond, {'pooled_output': pooled}]] + image = easySampler.pil2tensor(Image.new('RGB', (1, 1), (0, 0, 0))) + log_node_warn('处理结束...') + pipe = {'model': model, 'positive': positive_embeddings_final, 'negative': negative_embeddings_final, 'vae': vae, 'clip': clip, 'samples': samples, 'images': image, 'seed': 0, 'loader_settings': {'vae_name': stage_a, 'lora_stack': pipe_lora_stack, 'refiner_ckpt_name': None, 'refiner_vae_name': None, 'refiner_lora_name': None, 'refiner_lora_model_strength': None, 'refiner_lora_clip_strength': None, 'positive': positive, 'positive_l': None, 'positive_g': None, 'positive_token_normalization': 'none', 'positive_weight_interpretation': 'comfy', 'positive_balance': None, 'negative': negative, 'negative_l': None, 'negative_g': None, 'negative_token_normalization': 'none', 'negative_weight_interpretation': 'comfy', 'negative_balance': None, 'empty_latent_width': empty_latent_width, 'empty_latent_height': empty_latent_height, 'batch_size': batch_size, 'seed': 0, 'empty_samples': samples, 'compression': compression}} + return {'ui': {'positive': positive_wildcard_prompt, 'negative': negative_wildcard_prompt}, 'result': (pipe, model_c, model_b, vae)} +``` \ No newline at end of file diff --git a/docs/easy cleanGpuUsed.md b/docs/easy cleanGpuUsed.md new file mode 100644 index 0000000..015c613 --- /dev/null +++ b/docs/easy cleanGpuUsed.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: cleanGPUUsed +- Category: EasyUse/Logic +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点旨在通过管理GPU内存来优化计算资源。其主要功能是释放任何未被占用的GPU内存,以确保后续操作可以高效运行,而不会因内存不足而中断。 + +# Input types +## Required +- anything + - 该参数虽然不直接影响节点的执行,但它是一个占位符,以确保与各种输入类型的兼容性。它不会影响节点的主要功能。 + - Comfy dtype: COMBO[AlwaysEqualProxy(str)] + - Python dtype: Union[str, AlwaysEqualProxy] +## Optional +- unique_id + - 这个参数虽然是可选的,但可以用来跟踪节点的执行。它可以帮助记录日志和调试过程。 + - Comfy dtype: str + - Python dtype: Optional[str] +- extra_pnginfo + - 这个可选参数可以存储与节点执行相关的额外信息。它对节点的操作不是关键的,但可能对进一步分析有用。 + - Comfy dtype: str + - Python dtype: Optional[str] + +# Output types + +# Usage tips +- Infra type: GPU + +# Source code +``` +class cleanGPUUsed: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'anything': (AlwaysEqualProxy('*'), {})}, 'optional': {}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = () + RETURN_NAMES = () + OUTPUT_NODE = True + FUNCTION = 'empty_cache' + CATEGORY = 'EasyUse/Logic' + + def empty_cache(self, anything, unique_id=None, extra_pnginfo=None): + if torch.cuda.is_available(): + torch.cuda.empty_cache() + return () +``` \ No newline at end of file diff --git a/docs/easy comfyLoader.md b/docs/easy comfyLoader.md new file mode 100644 index 0000000..1d0d71b --- /dev/null +++ b/docs/easy comfyLoader.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: comfyLoader +- Category: EasyUse/Loaders +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +comfyLoader类的`adv_pipeloader`方法简化了为高级用例加载和准备模型和数据的过程。它整合了VAE、CLIP和LORA等组件,创建了一个全面的处理流程,便于根据用户提供的提示和偏好生成和操作高质量的图像。 + +# Input types +## Required +- ckpt_name + - ckpt_name是确定要在流程中使用的具体模型配置的关键。它通过决定模型的架构和学习到的参数,影响节点的整体性能和输出。 + - Comfy dtype: COMBO[folder_paths.get_filename_list('checkpoints')] + - Python dtype: Union[str, None] +- vae_name + - vae_name参数对于选择适当的变分自编码器模型至关重要,它在生成和操作图像的潜在表示方面发挥着重要作用。 + - Comfy dtype: COMBO[['Baked VAE'] + folder_paths.get_filename_list('vae')] + - Python dtype: Union[str, None] +- clip_skip + - 参数`clip_skip`在控制与CLIP模型的交互中起着重要作用,影响节点如何利用语义信息来增强图像生成。 + - Comfy dtype: INT + - Python dtype: int +- lora_name + - lora_name参数对于启用具有LORA层的模型微调至关重要,它根据用户的具体偏好细化图像生成过程。 + - Comfy dtype: COMBO[['None'] + folder_paths.get_filename_list('loras')] + - Python dtype: Union[str, None] +- lora_model_strength + - 参数`lora_model_strength`调整LORA层对模型输出的影响,直接影响微调过程和生成的图像质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- lora_clip_strength + - 参数`lora_clip_strength`调节CLIP模型与LORA层集成的强度,这对于在生成的图像中实现语义准确性和视觉真实性之间的平衡至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- resolution + - 分辨率参数决定了输出图像的尺寸,显著影响图像生成所需的细节水平和计算资源。 + - Comfy dtype: COMBO[resolution_strings] + - Python dtype: Union[str, None] +- empty_latent_width + - 参数`empty_latent_width`设置了潜在空间的宽度,这对于确定可以生成的可能图像变化范围至关重要。 + - Comfy dtype: INT + - Python dtype: int +- empty_latent_height + - 参数`empty_latent_height`定义了潜在空间的高度,在图像输出的多样性和生成过程的效率方面起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- positive + - 参数`positive`包含正面提示文本,这对于引导模型生成符合期望美学或主题方向的图像至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- negative + - 参数`negative`包含负面提示文本,这对于引导模型远离生成图像中不需要的特征或风格至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- batch_size + - 参数`batch_size`决定了同时处理的图像数量,影响图像生成过程的吞吐量和计算效率。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- ui + - UI输出提供了通配符提示的用户友好表示,这些提示对于可视化应用于图像生成过程的正面和负面影响非常重要。 + - Comfy dtype: DICT + - Python dtype: Dict[str, str] +- result + - 结果输出是一个包含加载的模型、VAE、CLIP和其他相关数据结构的全面元组,这些对于进一步的图像操作和分析至关重要。 + - Comfy dtype: TUPLE + - Python dtype: Tuple[Dict[str, Any], ModelPatcher, VAE, CLIP, torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class comfyLoader: + + @classmethod + def INPUT_TYPES(cls): + resolution_strings = [f'{width} x {height}' for (width, height) in BASE_RESOLUTIONS] + return {'required': {'ckpt_name': (folder_paths.get_filename_list('checkpoints'),), 'vae_name': (['Baked VAE'] + folder_paths.get_filename_list('vae'),), 'clip_skip': ('INT', {'default': -1, 'min': -24, 'max': 0, 'step': 1}), 'lora_name': (['None'] + folder_paths.get_filename_list('loras'),), 'lora_model_strength': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'lora_clip_strength': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'resolution': (resolution_strings, {'default': '512 x 512'}), 'empty_latent_width': ('INT', {'default': 512, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'empty_latent_height': ('INT', {'default': 512, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'positive': ('STRING', {'default': 'Positive', 'multiline': True}), 'negative': ('STRING', {'default': 'Negative', 'multiline': True}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}, 'optional': {'optional_lora_stack': ('LORA_STACK',)}, 'hidden': {'prompt': 'PROMPT', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE', 'MODEL', 'VAE') + RETURN_NAMES = ('pipe', 'model', 'vae') + FUNCTION = 'adv_pipeloader' + CATEGORY = 'EasyUse/Loaders' + + def adv_pipeloader(self, ckpt_name, vae_name, clip_skip, lora_name, lora_model_strength, lora_clip_strength, resolution, empty_latent_width, empty_latent_height, positive, negative, batch_size, optional_lora_stack=None, prompt=None, my_unique_id=None): + return fullLoader.adv_pipeloader(self, ckpt_name, 'Default', vae_name, clip_skip, lora_name, lora_model_strength, lora_clip_strength, resolution, empty_latent_width, empty_latent_height, positive, 'none', 'comfy', negative, 'none', 'comfy', batch_size, None, None, None, optional_lora_stack, False, prompt, my_unique_id) +``` \ No newline at end of file diff --git a/docs/easy compare.md b/docs/easy compare.md new file mode 100644 index 0000000..b167202 --- /dev/null +++ b/docs/easy compare.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: Compare +- Category: EasyUse/Logic/Math +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +Compare节点便于评估两个输入之间的逻辑比较,提供了一种直接的方法来确定值之间的关系。它旨在支持各种比较操作,提供了一种灵活直观的方式来将条件逻辑集成到工作流中。通过抽象比较过程,此节点增强了基于数据属性做出决策的能力,有助于构建更加动态和响应灵敏的系统。 + +# Input types +## Required +- a + - 参数'a'代表比较操作中的第一个操作数。它是节点功能的核心,因为它设置了与第二个操作数进行比较的基线值。该参数的重要性在于其在确定逻辑比较结果中的作用。 + - Comfy dtype: * + - Python dtype: Any +- b + - 参数'b'是用于比较的第二个操作数。它的重要性来自于它与第一个操作数的对比,正是这个参数与比较函数结合,决定了比较的结果。 + - Comfy dtype: * + - Python dtype: Any +- comparison + - 参数'comparison'是定义如何比较两个操作数的逻辑操作。它至关重要,因为它决定了评估的性质,并直接影响比较的结果。 + - Comfy dtype: COMBO[compare_functions] + - Python dtype: str + +# Output types +- boolean + - 输出'boolean'表示逻辑比较的结果,提供了一个二进制的结果,反映了两个输入操作数之间的关系。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Compare: + + @classmethod + def INPUT_TYPES(s): + s.compare_functions = list(COMPARE_FUNCTIONS.keys()) + return {'required': {'a': (AlwaysEqualProxy('*'), {'default': 0}), 'b': (AlwaysEqualProxy('*'), {'default': 0}), 'comparison': (s.compare_functions, {'default': 'a == b'})}} + RETURN_TYPES = ('BOOLEAN',) + RETURN_NAMES = ('boolean',) + FUNCTION = 'compare' + CATEGORY = 'EasyUse/Logic/Math' + + def compare(self, a, b, comparison): + return (COMPARE_FUNCTIONS[comparison](a, b),) +``` \ No newline at end of file diff --git a/docs/easy controlnetLoader.md b/docs/easy controlnetLoader.md new file mode 100644 index 0000000..35fefd8 --- /dev/null +++ b/docs/easy controlnetLoader.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: controlnetSimple +- Category: EasyUse/Loaders +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +controlnetSimple节点旨在方便用户将控制网应用于改进生成模型的输出。它通过接收一组图像和一个控制网名称,输出一个融合了控制网影响的增强模型管线。对于寻求在其生成过程中整合控制机制以实现更精确和细致结果的用户来说,此节点非常有用。 + +# Input types +## Required +- pipe + - ‘pipe’参数是controlnetSimple节点的一个关键输入,它代表了整个生成模型管线。它包括模型、条件数据和其他必要的相关设置。这些设置对节点的正常运作至关重要。pipe输入直接影响生成过程和最终输出,使节点能够有效地应用控制网。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- image + - ‘image’参数是controlnetSimple节点的视觉输入。它对于节点理解生成过程的上下文和期望方向至关重要。通过将图像纳入控制网的应用,节点可以产生更符合用户视觉意图的输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- control_net_name + - ‘control_net_name’参数是指定节点使用控制网的关键输入。它决定了将应用于生成模型的控制机制,影响最终输出的质量和对用户创意愿景的遵循程度。 + - Comfy dtype: CONTROL_NET + - Python dtype: str +## Optional +- strength + - ‘strength’参数用于调整控制网对生成过程影响的强度。这是一个可选输入,允许用户微调控制网的效果,平衡控制水平与模型的创造自由度。 + - Comfy dtype: FLOAT + - Python dtype: float +- scale_soft_weights + - ‘scale_soft_weights’参数用于修改控制网权重的柔和度。这个输入可以被调整以实现生成输出中更平滑的过渡,提供对最终视觉结果更细致的控制。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- pipe + - ‘pipe’输出是经过控制网应用修改后的增强生成模型管线。它包括更新后的模型和条件数据,现在反映了控制网的影响。这个输出对于用户继续使用改进后的管线进行生成工作至关重要。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- positive + - ‘positive’输出代表了根据控制网的影响进行了调整的精炼条件数据。它作为生成模型的指导,以产生更精确和与用户创意意图相匹配的输出。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[Any, Dict[str, Any]]] +- negative + - ‘negative’输出是已经优化的条件数据,用以抵消生成过程中不需要的特征或元素。它帮助模型从控制网的指导中学习,避免产生不期望的结果。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[Any, Dict[str, Any]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class controlnetSimple: + + @classmethod + def INPUT_TYPES(s): + + def get_file_list(filenames): + return [file for file in filenames if file != 'put_models_here.txt' and 'lllite' not in file] + return {'required': {'pipe': ('PIPE_LINE',), 'image': ('IMAGE',), 'control_net_name': (get_file_list(folder_paths.get_filename_list('controlnet')),)}, 'optional': {'control_net': ('CONTROL_NET',), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'scale_soft_weights': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001})}} + RETURN_TYPES = ('PIPE_LINE', 'CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('pipe', 'positive', 'negative') + OUTPUT_NODE = True + FUNCTION = 'controlnetApply' + CATEGORY = 'EasyUse/Loaders' + + def controlnetApply(self, pipe, image, control_net_name, control_net=None, strength=1, scale_soft_weights=1): + (positive, negative) = easyControlnet().apply(control_net_name, image, pipe['positive'], pipe['negative'], strength, 0, 1, control_net, scale_soft_weights) + new_pipe = {'model': pipe['model'], 'positive': positive, 'negative': negative, 'vae': pipe['vae'], 'clip': pipe['clip'], 'samples': pipe['samples'], 'images': pipe['images'], 'seed': 0, 'loader_settings': pipe['loader_settings']} + del pipe + return (new_pipe, positive, negative) +``` \ No newline at end of file diff --git a/docs/easy controlnetLoaderADV.md b/docs/easy controlnetLoaderADV.md new file mode 100644 index 0000000..ffe2392 --- /dev/null +++ b/docs/easy controlnetLoaderADV.md @@ -0,0 +1,83 @@ +# Documentation +- Class name: controlnetAdvanced +- Category: EasyUse/Loaders +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +controlnetAdvanced节点旨在便于应用控制网络来根据指定条件修改和增强图像数据。它通过将控制信号集成到图像处理流程中来运作,允许进行微调调整和条件性转换。 + +# Input types +## Required +- pipe + - ‘pipe’参数至关重要,因为它携带了整个图像处理流水线数据,包括模型和样本。这对于节点的正确运作和产生期望的输出至关重要。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- image + - ‘image’参数是将要被节点处理的输入图像。它是操作的基础,为所有转换和增强提供基础。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- control_net_name + - ‘control_net_name’参数指定了用于图像处理的控制网络。它很重要,因为它决定了应用于图像的控制类型,影响最终结果。 + - Comfy dtype: CONTROL_NET + - Python dtype: str +## Optional +- control_net + - ‘control_net’参数是一个可选的控制网络输入,可以直接由用户提供。它提供了一种定制用于处理的控制网络的方法,无需从文件加载。 + - Comfy dtype: CONTROL_NET + - Python dtype: Optional[torch.nn.Module] +- strength + - ‘strength’参数调整控制网络对图像影响的强度。它对于微调应用于图像的转换程度很重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_percent + - ‘start_percent’参数定义了控制网络对图像效果的起始点。它很重要,因为它决定了在处理流水线中何时开始应用控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_percent + - ‘end_percent’参数设置了控制网络影响的结束点,影响控制网络的效果在图像处理结束时如何淡出。 + - Comfy dtype: FLOAT + - Python dtype: float +- scale_soft_weights + - ‘scale_soft_weights’参数调整控制网络权重的柔和度,这有助于实现图像中更平滑的过渡和不那么突兀的变化。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- pipe + - ‘pipe’输出是应用了控制网络调整后的更新图像处理流水线。它很重要,因为它代表了控制网络应用后流水线的最终状态。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- positive + - ‘positive’输出包含了应用控制网络后得到的正向条件图像。它对于评估控制网络在实现期望的视觉增强方面的有效性至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[Any, Dict[str, Any]]] +- negative + - ‘negative’输出由负向条件图像组成,作为‘positive’输出的对比。它对于理解控制网络对图像所能施加的控制范围很重要。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[Any, Dict[str, Any]]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class controlnetAdvanced: + + @classmethod + def INPUT_TYPES(s): + + def get_file_list(filenames): + return [file for file in filenames if file != 'put_models_here.txt' and 'lllite' not in file] + return {'required': {'pipe': ('PIPE_LINE',), 'image': ('IMAGE',), 'control_net_name': (get_file_list(folder_paths.get_filename_list('controlnet')),)}, 'optional': {'control_net': ('CONTROL_NET',), 'strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_percent': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'scale_soft_weights': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001})}} + RETURN_TYPES = ('PIPE_LINE', 'CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('pipe', 'positive', 'negative') + OUTPUT_NODE = True + FUNCTION = 'controlnetApply' + CATEGORY = 'EasyUse/Loaders' + + def controlnetApply(self, pipe, image, control_net_name, control_net=None, strength=1, start_percent=0, end_percent=1, scale_soft_weights=1): + (positive, negative) = easyControlnet().apply(control_net_name, image, pipe['positive'], pipe['negative'], strength, start_percent, end_percent, control_net, scale_soft_weights) + new_pipe = {'model': pipe['model'], 'positive': positive, 'negative': negative, 'vae': pipe['vae'], 'clip': pipe['clip'], 'samples': pipe['samples'], 'images': pipe['images'], 'seed': 0, 'loader_settings': pipe['loader_settings']} + del pipe + return (new_pipe, positive, negative) +``` \ No newline at end of file diff --git a/docs/easy convertAnything.md b/docs/easy convertAnything.md new file mode 100644 index 0000000..0efd7b3 --- /dev/null +++ b/docs/easy convertAnything.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: ConvertAnything +- Category: EasyUse/Logic +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点能够将给定的输入转换为指定的输出类型,为数据转换任务提供一种多功能的解决方案。它通过解释输入并根据用户的选择将其转换为所需的类别(如字符串、整数、浮点数或布尔值)来执行操作。 + +# Input types +## Required +- anything + - ‘anything’参数至关重要,它代表了要转换的输入。它在节点操作中的作用是提供将经历转换过程的数据。 + - Comfy dtype: * + - Python dtype: Union[str, int, float, bool, torch.Tensor, np.ndarray, Decimal, List, Tuple, Dict[Any, Any]] +- output_type + - ‘output_type’参数决定了转换过程期望的结果。它在指导节点产生正确类型的输出中至关重要。 + - Comfy dtype: COMBO[string,int,float,boolean] + - Python dtype: Union[str, int, float, bool] + +# Output types +- * + - 这个节点的输出是转换后的数据,反映了输入转换为指定类型后的结果。 + - Comfy dtype: * + - Python dtype: Union[str, int, float, bool, torch.Tensor, np.ndarray, Decimal, List, Tuple, Dict[Any, Any]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ConvertAnything: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'anything': (AlwaysEqualProxy('*'),), 'output_type': (['string', 'int', 'float', 'boolean'], {'default': 'string'})}} + RETURN_TYPES = ((AlwaysEqualProxy('*'),),) + RETURN_NAMES = ('*',) + OUTPUT_NODE = True + FUNCTION = 'convert' + CATEGORY = 'EasyUse/Logic' + + def convert(self, *args, **kwargs): + print(kwargs) + anything = kwargs['anything'] + output_type = kwargs['output_type'] + params = None + if output_type == 'string': + params = str(anything) + elif output_type == 'int': + params = int(anything) + elif output_type == 'float': + params = float(anything) + elif output_type == 'boolean': + params = bool(anything) + return (params,) +``` \ No newline at end of file diff --git a/docs/easy detailerFix.md b/docs/easy detailerFix.md new file mode 100644 index 0000000..9922452 --- /dev/null +++ b/docs/easy detailerFix.md @@ -0,0 +1,156 @@ +# Documentation +- Class name: detailerFix +- Category: EasyUse/Fix +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +detailerFix节点旨在通过使用先进的模型和算法来增强图像细节。它专注于提炼图像的视觉元素,提高其整体质量和清晰度。该节点的主要目标是提供一个简单而有效的细节增强解决方案,无需广泛的图像处理知识。 + +# Input types +## Required +- pipe + - pipe参数是必需的,因为它携带了detailerFix节点执行其功能所需的所有必要信息和设置。它包括模型、图像和其他设置,这些设置决定了如何进行细节增强。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- image_output + - image_output参数决定了处理后结果图像的处理方式。它允许用户选择预览、保存或两者的组合,从而控制输出流程。 + - Comfy dtype: COMBO + - Python dtype: str +- link_id + - 当image_output设置为'Sender'或'Sender/Save'时,link_id对节点的操作至关重要。它建立了图像传输的连接,确保处理后的图像被送达正确的目的地。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- save_prefix + - save_prefix参数用于定义保存的图像文件的共同前缀。这有助于组织输出,使用户更容易定位和管理增强的图像。 + - Comfy dtype: STRING + - Python dtype: str +- model + - model参数提供了细节增强过程所需的模型。当pipe参数中不包含模型时,这一点尤为重要,确保节点能够访问处理所需的模型。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- prompt + - prompt参数用于提供可以指导细节增强过程的额外信息或指令。它可以包括用户希望在执行期间考虑的特定细节或偏好。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - extra_pnginfo参数包含可以用来细化细节增强过程的补充数据。它提供了额外的上下文或选项,可以提高输出图像的质量。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, Any] +- my_unique_id + - my_unique_id参数用于跟踪和管理单个图像细节的处理。它有助于将输出与特定请求关联起来,确保结果的准确性和组织性。 + - Comfy dtype: UNIQUE_ID + - Python dtype: int + +# Output types +- pipe + - pipe输出是一个包含增强图像和输入pipe中所有相关信息的综合性结构。它作为处理数据的通道,确保结果正确地沿管道传递。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- image + - image输出是detailerFix节点的主要结果,即增强后的图像。它是细节增强过程的最终成果,并旨在成为用户的最终产品。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- cropped_refined + - cropped_refined输出是增强图像的裁剪版本,以获得更好的焦点和清晰度。它突出显示了图像中已经被提炼和改进的区域,清晰地展示了节点的有效性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- cropped_enhanced_alpha + - cropped_enhanced_alpha输出是增强图像的专用版本,包含代表透明度的alpha通道。这种输出对于需要图像层叠或合成的应用特别有用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class detailerFix: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',), 'image_output': (['Hide', 'Preview', 'Save', 'Hide/Save', 'Sender', 'Sender/Save'], {'default': 'Preview'}), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'save_prefix': ('STRING', {'default': 'ComfyUI'})}, 'optional': {'model': ('MODEL',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE', 'IMAGE', 'IMAGE', 'IMAGE') + RETURN_NAMES = ('pipe', 'image', 'cropped_refined', 'cropped_enhanced_alpha') + OUTPUT_NODE = True + OUTPUT_IS_LIST = (False, False, True, True) + FUNCTION = 'doit' + CATEGORY = 'EasyUse/Fix' + + def doit(self, pipe, image_output, link_id, save_prefix, model=None, prompt=None, extra_pnginfo=None, my_unique_id=None): + easyCache.update_loaded_objects(prompt) + my_unique_id = int(my_unique_id) + model = model or (pipe['model'] if 'model' in pipe else None) + if model is None: + raise Exception(f"[ERROR] model or pipe['model'] is missing") + detail_fix_settings = pipe['detail_fix_settings'] if 'detail_fix_settings' in pipe else None + if detail_fix_settings is None: + raise Exception(f"[ERROR] detail_fix_settings or pipe['detail_fix_settings'] is missing") + mask = pipe['mask'] if 'mask' in pipe else None + image = pipe['images'] + clip = pipe['clip'] + vae = pipe['vae'] + seed = pipe['seed'] + positive = pipe['positive'] + negative = pipe['negative'] + loader_settings = pipe['loader_settings'] if 'loader_settings' in pipe else {} + guide_size = pipe['detail_fix_settings']['guide_size'] if 'guide_size' in pipe['detail_fix_settings'] else 256 + guide_size_for = pipe['detail_fix_settings']['guide_size_for'] if 'guide_size_for' in pipe['detail_fix_settings'] else True + max_size = pipe['detail_fix_settings']['max_size'] if 'max_size' in pipe['detail_fix_settings'] else 768 + steps = pipe['detail_fix_settings']['steps'] if 'steps' in pipe['detail_fix_settings'] else 20 + cfg = pipe['detail_fix_settings']['cfg'] if 'cfg' in pipe['detail_fix_settings'] else 1.0 + sampler_name = pipe['detail_fix_settings']['sampler_name'] if 'sampler_name' in pipe['detail_fix_settings'] else None + scheduler = pipe['detail_fix_settings']['scheduler'] if 'scheduler' in pipe['detail_fix_settings'] else None + denoise = pipe['detail_fix_settings']['denoise'] if 'denoise' in pipe['detail_fix_settings'] else 0.5 + feather = pipe['detail_fix_settings']['feather'] if 'feather' in pipe['detail_fix_settings'] else 5 + crop_factor = pipe['detail_fix_settings']['crop_factor'] if 'crop_factor' in pipe['detail_fix_settings'] else 3.0 + drop_size = pipe['detail_fix_settings']['drop_size'] if 'drop_size' in pipe['detail_fix_settings'] else 10 + refiner_ratio = pipe['detail_fix_settings']['refiner_ratio'] if 'refiner_ratio' in pipe else 0.2 + batch_size = pipe['detail_fix_settings']['batch_size'] if 'batch_size' in pipe['detail_fix_settings'] else 1 + noise_mask = pipe['detail_fix_settings']['noise_mask'] if 'noise_mask' in pipe['detail_fix_settings'] else None + force_inpaint = pipe['detail_fix_settings']['force_inpaint'] if 'force_inpaint' in pipe['detail_fix_settings'] else False + wildcard = pipe['detail_fix_settings']['wildcard'] if 'wildcard' in pipe['detail_fix_settings'] else '' + cycle = pipe['detail_fix_settings']['cycle'] if 'cycle' in pipe['detail_fix_settings'] else 1 + bbox_segm_pipe = pipe['bbox_segm_pipe'] if pipe and 'bbox_segm_pipe' in pipe else None + sam_pipe = pipe['sam_pipe'] if 'sam_pipe' in pipe else None + start_time = int(time.time() * 1000) + if 'mask_settings' in pipe: + mask_mode = pipe['mask_settings']['mask_mode'] if 'inpaint_model' in pipe['mask_settings'] else True + inpaint_model = pipe['mask_settings']['inpaint_model'] if 'inpaint_model' in pipe['mask_settings'] else False + noise_mask_feather = pipe['mask_settings']['noise_mask_feather'] if 'noise_mask_feather' in pipe['mask_settings'] else 20 + cls = ALL_NODE_CLASS_MAPPINGS['MaskDetailerPipe'] + if 'MaskDetailerPipe' not in ALL_NODE_CLASS_MAPPINGS: + raise Exception(f"[ERROR] To use MaskDetailerPipe, you need to install 'Impact Pack'") + basic_pipe = (model, clip, vae, positive, negative) + (result_img, result_cropped_enhanced, result_cropped_enhanced_alpha, basic_pipe, refiner_basic_pipe_opt) = cls().doit(image, mask, basic_pipe, 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=1, refiner_basic_pipe_opt=None, detailer_hook=None, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather) + result_mask = mask + result_cnet_images = () + else: + if bbox_segm_pipe is None: + raise Exception(f"[ERROR] bbox_segm_pipe or pipe['bbox_segm_pipe'] is missing") + if sam_pipe is None: + raise Exception(f"[ERROR] sam_pipe or pipe['sam_pipe'] is missing") + (bbox_detector_opt, bbox_threshold, bbox_dilation, bbox_crop_factor, segm_detector_opt) = bbox_segm_pipe + (sam_model_opt, sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion, sam_mask_hint_threshold, sam_mask_hint_use_negative) = sam_pipe + if 'FaceDetailer' not in ALL_NODE_CLASS_MAPPINGS: + raise Exception(f"[ERROR] To use FaceDetailer, you need to install 'Impact Pack'") + cls = ALL_NODE_CLASS_MAPPINGS['FaceDetailer'] + (result_img, result_cropped_enhanced, result_cropped_enhanced_alpha, result_mask, pipe, result_cnet_images) = cls().doit(image, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, bbox_threshold, bbox_dilation, bbox_crop_factor, sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion, sam_mask_hint_threshold, sam_mask_hint_use_negative, drop_size, bbox_detector_opt, wildcard, cycle, sam_model_opt, segm_detector_opt, detailer_hook=None) + end_time = int(time.time() * 1000) + spent_time = '细节修复:' + str((end_time - start_time) / 1000) + '秒' + results = easySave(result_img, save_prefix, image_output, prompt, extra_pnginfo) + sampler.update_value_by_id('results', my_unique_id, results) + easyCache.update_loaded_objects(prompt) + new_pipe = {'samples': None, 'images': result_img, 'model': model, 'clip': clip, 'vae': vae, 'seed': seed, 'positive': positive, 'negative': negative, 'wildcard': wildcard, 'bbox_segm_pipe': bbox_segm_pipe, 'sam_pipe': sam_pipe, 'loader_settings': {**loader_settings, 'spent_time': spent_time}, 'detail_fix_settings': detail_fix_settings} + if 'mask_settings' in pipe: + new_pipe['mask_settings'] = pipe['mask_settings'] + sampler.update_value_by_id('pipe_line', my_unique_id, new_pipe) + del bbox_segm_pipe + del sam_pipe + del pipe + if image_output in ('Hide', 'Hide/Save'): + return {'ui': {}, 'result': (new_pipe, result_img, result_cropped_enhanced, result_cropped_enhanced_alpha, result_mask, result_cnet_images)} + if image_output in ('Sender', 'Sender/Save'): + PromptServer.instance.send_sync('img-send', {'link_id': link_id, 'images': results}) + return {'ui': {'images': results}, 'result': (new_pipe, result_img, result_cropped_enhanced, result_cropped_enhanced_alpha, result_mask, result_cnet_images)} +``` \ No newline at end of file diff --git a/docs/easy dynamiCrafterLoader.md b/docs/easy dynamiCrafterLoader.md new file mode 100644 index 0000000..a5c8c23 --- /dev/null +++ b/docs/easy dynamiCrafterLoader.md @@ -0,0 +1,134 @@ +# Documentation +- Class name: dynamiCrafterLoader +- Category: EasyUse/Loaders +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点类封装了加载和准备dynamiCrafter流水线所需各种模型和数据的功能。它简化了模型选择、初始化和调节的过程,确保后续生成任务所需的必要组件就绪。 + +# Input types +## Required +- model_name + - 模型名称参数对于指定将在dynamiCrafterLoader中使用哪个模型至关重要。它决定了指导生成过程的基础架构和相关参数。 + - Comfy dtype: COMBO + - Python dtype: str +- clip_skip + - clip_skip参数影响CLIP模型中用于文本调节的层的选择。它对于微调生成过程以符合期望的创作方向至关重要。 + - Comfy dtype: INT + - Python dtype: int +- init_image + - init_image参数作为初始化生成过程潜在空间的视觉输入。它是设置形成最终输出的初始条件的关键因素。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- resolution + - 分辨率参数定义了生成输出的尺寸。它对于匹配期望的质量和细节水平与底层模型的能力很重要。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- pipe + - pipe输出是一个综合性结构,封装了dynamiCrafter流水线所需的所有组件。它旨在促进与下游生成任务的无缝集成。 + - Comfy dtype: PIPE_LINE + - Python dtype: dict +- model + - 模型输出表示已加载和准备好的生成模型。它是推动生成过程的核心元素,将输入转换为期望的创意输出。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- vae + - vae输出是用于潜在空间操作和图像调节的变分自编码器组件。它在生成多样化和连贯的视觉内容中发挥着至关重要的作用。 + - Comfy dtype: VAE + - Python dtype: comfy.sd.VAE + +# Usage tips +- Infra type: GPU + +# Source code +``` +class dynamiCrafterLoader(DynamiCrafter): + + def __init__(self): + super().__init__() + + @classmethod + def INPUT_TYPES(cls): + resolution_strings = [f'{width} x {height}' for (width, height) in BASE_RESOLUTIONS] + return {'required': {'model_name': (list(DYNAMICRAFTER_MODELS.keys()),), 'clip_skip': ('INT', {'default': -2, 'min': -24, 'max': 0, 'step': 1}), 'init_image': ('IMAGE',), 'resolution': (resolution_strings, {'default': '512 x 512'}), 'empty_latent_width': ('INT', {'default': 256, 'min': 16, 'max': MAX_RESOLUTION, 'step': 8}), 'empty_latent_height': ('INT', {'default': 256, 'min': 16, 'max': MAX_RESOLUTION, 'step': 8}), 'positive': ('STRING', {'default': '', 'multiline': True}), 'negative': ('STRING', {'default': '', 'multiline': True}), 'use_interpolate': ('BOOLEAN', {'default': False}), 'fps': ('INT', {'default': 15, 'min': 1, 'max': 30, 'step': 1}), 'frames': ('INT', {'default': 16}), 'scale_latents': ('BOOLEAN', {'default': False})}, 'optional': {'optional_vae': ('VAE',)}, 'hidden': {'prompt': 'PROMPT', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE', 'MODEL', 'VAE') + RETURN_NAMES = ('pipe', 'model', 'vae') + FUNCTION = 'adv_pipeloader' + CATEGORY = 'EasyUse/Loaders' + + def get_clip_file(self, node_name): + clip_list = folder_paths.get_filename_list('clip') + pattern = 'sd2-1-open-clip|model\\.(safetensors|bin)$' + clip_files = [e for e in clip_list if re.search(pattern, e, re.IGNORECASE)] + clip_name = clip_files[0] if len(clip_files) > 0 else None + clip_file = folder_paths.get_full_path('clip', clip_name) if clip_name else None + if clip_name is not None: + log_node_info(node_name, f'Using {clip_name}') + return (clip_file, clip_name) + + def get_clipvision_file(self, node_name): + clipvision_list = folder_paths.get_filename_list('clip_vision') + pattern = '(ViT.H.14.*s32B.b79K|ipadapter.*sd15|sd1.?5.*model|open_clip_pytorch_model\\.(bin|safetensors))' + clipvision_files = [e for e in clipvision_list if re.search(pattern, e, re.IGNORECASE)] + clipvision_name = clipvision_files[0] if len(clipvision_files) > 0 else None + clipvision_file = folder_paths.get_full_path('clip_vision', clipvision_name) if clipvision_name else None + if clipvision_name is not None: + log_node_info(node_name, f'Using {clipvision_name}') + return (clipvision_file, clipvision_name) + + def get_vae_file(self, node_name): + vae_list = folder_paths.get_filename_list('vae') + pattern = 'vae-ft-mse-840000-ema-pruned\\.(pt|bin|safetensors)$' + vae_files = [e for e in vae_list if re.search(pattern, e, re.IGNORECASE)] + vae_name = vae_files[0] if len(vae_files) > 0 else None + vae_file = folder_paths.get_full_path('vae', vae_name) if vae_name else None + if vae_name is not None: + log_node_info(node_name, f'Using {vae_name}') + return (vae_file, vae_name) + + def adv_pipeloader(self, model_name, clip_skip, init_image, resolution, empty_latent_width, empty_latent_height, positive, negative, use_interpolate, fps, frames, scale_latents, optional_vae=None, prompt=None, my_unique_id=None): + (positive_embeddings_final, negative_embeddings_final) = (None, None) + if resolution != '自定义 x 自定义': + try: + (width, height) = map(int, resolution.split(' x ')) + empty_latent_width = width + empty_latent_height = height + except ValueError: + raise ValueError('Invalid base_resolution format.') + easyCache.update_loaded_objects(prompt) + models_0 = list(DYNAMICRAFTER_MODELS.keys())[0] + if optional_vae: + vae = optional_vae + vae_name = None + else: + (vae_file, vae_name) = self.get_vae_file('easy dynamiCrafterLoader') + if vae_file is None: + vae_name = 'vae-ft-mse-840000-ema-pruned.safetensors' + get_local_filepath(DYNAMICRAFTER_MODELS[models_0]['vae_url'], os.path.join(folder_paths.models_dir, 'vae'), vae_name) + vae = easyCache.load_vae(vae_name) + (clip_file, clip_name) = self.get_clip_file('easy dynamiCrafterLoader') + if clip_file is None: + clip_name = 'sd2-1-open-clip.safetensors' + get_local_filepath(DYNAMICRAFTER_MODELS[models_0]['clip_url'], os.path.join(folder_paths.models_dir, 'clip'), clip_name) + clip = easyCache.load_clip(clip_name) + (clip_vision_file, clip_vision_name) = self.get_clipvision_file('easy dynamiCrafterLoader') + if clip_vision_file is None: + clip_vision_name = 'CLIP-ViT-H-14-laion2B-s32B-b79K.safetensors' + clip_vision_file = get_local_filepath(DYNAMICRAFTER_MODELS[models_0]['clip_vision_url'], os.path.join(folder_paths.models_dir, 'clip_vision'), clip_vision_name) + clip_vision = load_clip_vision(clip_vision_file) + model_path = get_local_filepath(DYNAMICRAFTER_MODELS[model_name]['model_url'], DYNAMICRAFTER_DIR) + (model_patcher, image_proj_model) = self.load_dynamicrafter(model_path) + (model, empty_latent, image_latent) = self.process_image_conditioning(model_patcher, clip_vision, vae, image_proj_model, init_image, use_interpolate, fps, frames, scale_latents) + clipped = clip.clone() + if clip_skip != 0: + clipped.clip_layer(clip_skip) + if positive is not None and positive != '': + (positive_embeddings_final,) = CLIPTextEncode().encode(clipped, positive) + if negative is not None and negative != '': + (negative_embeddings_final,) = CLIPTextEncode().encode(clipped, negative) + image = easySampler.pil2tensor(Image.new('RGB', (1, 1), (0, 0, 0))) + pipe = {'model': model, 'positive': positive_embeddings_final, 'negative': negative_embeddings_final, 'vae': vae, 'clip': clip, 'clip_vision': clip_vision, 'samples': empty_latent, 'images': image, 'seed': 0, 'loader_settings': {'ckpt_name': model_name, 'vae_name': vae_name, 'positive': positive, 'positive_l': None, 'positive_g': None, 'positive_balance': None, 'negative': negative, 'negative_l': None, 'negative_g': None, 'negative_balance': None, 'empty_latent_width': empty_latent_width, 'empty_latent_height': empty_latent_height, 'batch_size': 1, 'seed': 0, 'empty_samples': empty_latent}} + return (pipe, model, vae) +``` \ No newline at end of file diff --git a/docs/easy float.md b/docs/easy float.md new file mode 100644 index 0000000..7d45010 --- /dev/null +++ b/docs/easy float.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: Float +- Category: EasyUse/Logic/Type +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点提供基础的浮点数处理操作,专注于在指定精度内对小数值进行操作和计算。 + +# Input types +## Required +- value + - ‘value’参数对节点的操作至关重要,它是节点操作或计算的输入小数值。 + - Comfy dtype: FLOAT + - Python dtype: Union[Decimal, float, int] + +# Output types +- float + - 输出‘float’代表节点计算或操作的结果,反映了处理后的数值。 + - Comfy dtype: FLOAT + - Python dtype: Union[Decimal, float] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Float: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'value': ('FLOAT', {'default': 0, 'step': 0.01})}} + RETURN_TYPES = ('FLOAT',) + RETURN_NAMES = ('float',) + FUNCTION = 'execute' + CATEGORY = 'EasyUse/Logic/Type' + + def execute(self, value): + return (value,) +``` \ No newline at end of file diff --git a/docs/easy fullCascadeKSampler.md b/docs/easy fullCascadeKSampler.md new file mode 100644 index 0000000..419b4a9 --- /dev/null +++ b/docs/easy fullCascadeKSampler.md @@ -0,0 +1,143 @@ +# Documentation +- Class name: samplerCascadeFull +- Category: EasyUse/Sampler +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +samplerCascadeFull节点旨在执行生成模型框架中的抽样过程。它协调编码、抽样和解码阶段,以产生一系列图像或潜在表示。该节点对于基于提供的种子和模型生成新图像内容至关重要,为用户提供了利用高级抽样技术的无缝接口。 + +# Input types +## Required +- pipe + - ‘pipe’参数是一个关键输入,它携带了抽样过程所需的管道设置和数据。它包括加载器设置、模型引用和其他指导节点操作的必要信息。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- encode_vae_name + - ‘encode_vae_name’参数指定用于将输入图像编码到潜在空间的VAE模型的名称。它是一个可选参数,允许对编码过程进行定制。 + - Comfy dtype: STRING + - Python dtype: Union[str, None] +- decode_vae_name + - ‘decode_vae_name’参数确定用于将潜在表示解码回图像的VAE模型。它为用户提供了根据他们的需求选择解码模型的灵活性。 + - Comfy dtype: STRING + - Python dtype: Union[str, None] +- steps + - ‘steps’参数定义了抽样过程中要执行的抽样步骤数。它直接影响生成图像的质量和细节。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- pipe + - ‘pipe’输出包含抽样过程后更新的管道设置和结果。它是一个全面的输出,封装了节点执行后的状态。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- model_b + - ‘model_b’输出代表了抽样过程中解码阶段使用模型。对于需要引用其操作中使用的具体模型的用户来说,它是重要的。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- latent_b + - ‘latent_b’输出提供了由抽样过程生成的潜在表示。这些潜在编码对于希望进一步操作或分析生成内容的用户至关重要。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class samplerCascadeFull: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'encode_vae_name': (['None'] + folder_paths.get_filename_list('vae'),), 'decode_vae_name': (['None'] + folder_paths.get_filename_list('vae'),), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'cfg': ('FLOAT', {'default': 4.0, 'min': 0.0, 'max': 100.0}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS, {'default': 'euler_ancestral'}), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS, {'default': 'simple'}), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'image_output': (['Hide', 'Preview', 'Save', 'Hide/Save', 'Sender', 'Sender/Save'],), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'save_prefix': ('STRING', {'default': 'ComfyUI'}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': MAX_SEED_NUM})}, 'optional': {'image_to_latent_c': ('IMAGE',), 'latent_c': ('LATENT',), 'model_c': ('MODEL',)}, 'hidden': {'tile_size': 'INT', 'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID', 'embeddingsList': (folder_paths.get_filename_list('embeddings'),)}} + RETURN_TYPES = ('PIPE_LINE', 'MODEL', 'LATENT') + RETURN_NAMES = ('pipe', 'model_b', 'latent_b') + OUTPUT_NODE = True + FUNCTION = 'run' + CATEGORY = 'EasyUse/Sampler' + + def run(self, pipe, encode_vae_name, decode_vae_name, steps, cfg, sampler_name, scheduler, denoise, image_output, link_id, save_prefix, seed, image_to_latent_c=None, latent_c=None, model_c=None, tile_size=None, prompt=None, extra_pnginfo=None, my_unique_id=None, force_full_denoise=False, disable_noise=False): + encode_vae_name = encode_vae_name if encode_vae_name is not None else pipe['loader_settings']['encode_vae_name'] + decode_vae_name = decode_vae_name if decode_vae_name is not None else pipe['loader_settings']['decode_vae_name'] + batch_size = pipe['loader_settings']['batch_size'] if 'batch_size' in pipe['loader_settings'] else 1 + if image_to_latent_c is not None: + if encode_vae_name != 'None': + encode_vae = easyCache.load_vae(encode_vae_name) + else: + encode_vae = pipe['vae'][0] + if 'compression' not in pipe['loader_settings']: + raise Exception('compression is not found') + compression = pipe['loader_settings']['compression'] + width = image_to_latent_c.shape[-2] + height = image_to_latent_c.shape[-3] + out_width = width // compression * encode_vae.downscale_ratio + out_height = height // compression * encode_vae.downscale_ratio + s = comfy.utils.common_upscale(image_to_latent_c.movedim(-1, 1), out_width, out_height, 'bicubic', 'center').movedim(1, -1) + latent_c = encode_vae.encode(s[:, :, :, :3]) + latent_b = torch.zeros([latent_c.shape[0], 4, height // 4, width // 4]) + samples_c = {'samples': latent_c} + samples_c = RepeatLatentBatch().repeat(samples_c, batch_size)[0] + samples_b = {'samples': latent_b} + samples_b = RepeatLatentBatch().repeat(samples_b, batch_size)[0] + images = image_to_latent_c + elif latent_c is not None: + samples_c = latent_c + samples_b = pipe['samples'][1] + images = pipe['images'] + else: + samples_c = pipe['samples'][0] + samples_b = pipe['samples'][1] + images = pipe['images'] + easyCache.update_loaded_objects(prompt) + samp_model = model_c if model_c else pipe['model'][0] + samp_positive = pipe['positive'] + samp_negative = pipe['negative'] + samp_samples = samples_c + samp_seed = seed if seed is not None else pipe['seed'] + steps = steps if steps is not None else pipe['loader_settings']['steps'] + start_step = pipe['loader_settings']['start_step'] if 'start_step' in pipe['loader_settings'] else 0 + last_step = pipe['loader_settings']['last_step'] if 'last_step' in pipe['loader_settings'] else 10000 + cfg = cfg if cfg is not None else pipe['loader_settings']['cfg'] + sampler_name = sampler_name if sampler_name is not None else pipe['loader_settings']['sampler_name'] + scheduler = scheduler if scheduler is not None else pipe['loader_settings']['scheduler'] + denoise = denoise if denoise is not None else pipe['loader_settings']['denoise'] + start_time = int(time.time() * 1000) + samp_samples = sampler.common_ksampler(samp_model, samp_seed, steps, cfg, sampler_name, scheduler, samp_positive, samp_negative, samp_samples, denoise=denoise, preview_latent=False, start_step=start_step, last_step=last_step, force_full_denoise=False, disable_noise=False) + end_time = int(time.time() * 1000) + stage_c = samp_samples['samples'] + results = None + if image_output not in ['Hide', 'Hide/Save']: + if decode_vae_name != 'None': + decode_vae = easyCache.load_vae(decode_vae_name) + else: + decode_vae = pipe['vae'][0] + samp_images = decode_vae.decode(stage_c).cpu() + results = easySave(samp_images, save_prefix, image_output, prompt, extra_pnginfo) + sampler.update_value_by_id('results', my_unique_id, results) + end_decode_time = int(time.time() * 1000) + spent_time = '扩散:' + str((end_time - start_time) / 1000) + '秒, 解码:' + str((end_decode_time - end_time) / 1000) + '秒' + easyCache.update_loaded_objects(prompt) + c1 = [] + for t in samp_positive: + d = t[1].copy() + if 'pooled_output' in d: + d['pooled_output'] = torch.zeros_like(d['pooled_output']) + n = [torch.zeros_like(t[0]), d] + c1.append(n) + c2 = [] + for t in c1: + d = t[1].copy() + d['stable_cascade_prior'] = stage_c + n = [t[0], d] + c2.append(n) + new_pipe = {'model': pipe['model'][1], 'positive': c2, 'negative': c1, 'vae': pipe['vae'][1], 'clip': pipe['clip'], 'samples': samples_b, 'images': images, 'seed': seed, 'loader_settings': {**pipe['loader_settings'], 'spent_time': spent_time}} + sampler.update_value_by_id('pipe_line', my_unique_id, new_pipe) + del pipe + if image_output in ('Hide', 'Hide/Save'): + return {'ui': {}, 'result': sampler.get_output(new_pipe)} + if image_output in ('Sender', 'Sender/Save') and results is not None: + PromptServer.instance.send_sync('img-send', {'link_id': link_id, 'images': results}) + return {'ui': {'images': results}, 'result': (new_pipe, new_pipe['model'], new_pipe['samples'])} +``` \ No newline at end of file diff --git a/docs/easy fullLoader.md b/docs/easy fullLoader.md new file mode 100644 index 0000000..523234d --- /dev/null +++ b/docs/easy fullLoader.md @@ -0,0 +1,111 @@ +# Documentation +- Class name: fullLoader +- Category: EasyUse/Loaders +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +fullLoader类封装了加载和准备管道所需的各种模型和组件的功能。它简化了集成检查点、VAE、CLIP和条件数据的过程,为模型初始化和设置提供了一个连贯的接口。 + +# Input types +## Required +- ckpt_name + - 检查点名称对于识别要加载和在管道中使用的特定模型至关重要。它指导加载器找到模型的正确保存状态,这对于后续处理步骤中的一致性和准确性至关重要。 + - Comfy dtype: FILE + - Python dtype: List[str] +- config_name + - 配置名称在确定模型的设置和超参数方面起着关键作用。它确保模型在期望的参数内运行,影响整体性能和输出质量。 + - Comfy dtype: ENUM + - Python dtype: Enum +- vae_name + - VAE名称对于选择适当的变分自编码器模型至关重要。它影响管道的生成能力和潜在空间表示的质量。 + - Comfy dtype: FILE + - Python dtype: List[str] +- clip_skip + - clip_skip参数对于控制在管道中应用CLIP模型的层级具有重要意义。它影响文本条件的粒度和模型对文本提示的响应性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- pipe + - pipe输出代表了fullLoader工作的成果,提供了包含模型、VAE、CLIP和条件数据的综合管道设置。它是生成过程的支柱,确保所有组件的无缝集成。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict + +# Usage tips +- Infra type: CPU + +# Source code +``` +class fullLoader: + + @classmethod + def INPUT_TYPES(cls): + resolution_strings = [f'{width} x {height}' for (width, height) in BASE_RESOLUTIONS] + a1111_prompt_style_default = False + return {'required': {'ckpt_name': (folder_paths.get_filename_list('checkpoints'),), 'config_name': (['Default'] + folder_paths.get_filename_list('configs'), {'default': 'Default'}), 'vae_name': (['Baked VAE'] + folder_paths.get_filename_list('vae'),), 'clip_skip': ('INT', {'default': -1, 'min': -24, 'max': 0, 'step': 1}), 'lora_name': (['None'] + folder_paths.get_filename_list('loras'),), 'lora_model_strength': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'lora_clip_strength': ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}), 'resolution': (resolution_strings,), 'empty_latent_width': ('INT', {'default': 512, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'empty_latent_height': ('INT', {'default': 512, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'positive': ('STRING', {'default': 'Positive', 'multiline': True}), 'positive_token_normalization': (['none', 'mean', 'length', 'length+mean'],), 'positive_weight_interpretation': (['comfy', 'A1111', 'comfy++', 'compel', 'fixed attention'],), 'negative': ('STRING', {'default': 'Negative', 'multiline': True}), 'negative_token_normalization': (['none', 'mean', 'length', 'length+mean'],), 'negative_weight_interpretation': (['comfy', 'A1111', 'comfy++', 'compel', 'fixed attention'],), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64})}, 'optional': {'model_override': ('MODEL',), 'clip_override': ('CLIP',), 'vae_override': ('VAE',), 'optional_lora_stack': ('LORA_STACK',), 'a1111_prompt_style': ('BOOLEAN', {'default': a1111_prompt_style_default})}, 'hidden': {'prompt': 'PROMPT', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE', 'MODEL', 'VAE', 'CLIP', 'CONDITIONING', 'CONDITIONING', 'LATENT') + RETURN_NAMES = ('pipe', 'model', 'vae', 'clip', 'positive', 'negative', 'latent') + FUNCTION = 'adv_pipeloader' + CATEGORY = 'EasyUse/Loaders' + + def adv_pipeloader(self, ckpt_name, config_name, vae_name, clip_skip, lora_name, lora_model_strength, lora_clip_strength, resolution, empty_latent_width, empty_latent_height, positive, positive_token_normalization, positive_weight_interpretation, negative, negative_token_normalization, negative_weight_interpretation, batch_size, model_override=None, clip_override=None, vae_override=None, optional_lora_stack=None, a1111_prompt_style=False, prompt=None, my_unique_id=None): + model: ModelPatcher | None = None + clip: CLIP | None = None + vae: VAE | None = None + can_load_lora = True + pipe_lora_stack = [] + if resolution != '自定义 x 自定义': + try: + (width, height) = map(int, resolution.split(' x ')) + empty_latent_width = width + empty_latent_height = height + except ValueError: + raise ValueError('Invalid base_resolution format.') + latent = torch.zeros([batch_size, 4, empty_latent_height // 8, empty_latent_width // 8]).cpu() + samples = {'samples': latent} + easyCache.update_loaded_objects(prompt) + log_node_warn('正在处理模型...') + xy_model_id = next((x for x in prompt if str(prompt[x]['class_type']) in ['easy XYInputs: ModelMergeBlocks', 'easy XYInputs: Checkpoint']), None) + xy_lora_id = next((x for x in prompt if str(prompt[x]['class_type']) == 'easy XYInputs: Lora'), None) + if xy_lora_id is not None: + can_load_lora = False + if xy_model_id is not None: + node = prompt[xy_model_id] + if 'ckpt_name_1' in node['inputs']: + ckpt_name_1 = node['inputs']['ckpt_name_1'] + (model, clip, vae, clip_vision) = easyCache.load_checkpoint(ckpt_name_1) + can_load_lora = False + elif model_override is not None and clip_override is not None and (vae_override is not None): + model = model_override + clip = clip_override + vae = vae_override + elif model_override is not None: + raise Exception(f'[ERROR] clip or vae is missing') + elif vae_override is not None: + raise Exception(f'[ERROR] model or clip is missing') + elif clip_override is not None: + raise Exception(f'[ERROR] model or vae is missing') + else: + (model, clip, vae, clip_vision) = easyCache.load_checkpoint(ckpt_name, config_name) + if optional_lora_stack is not None and can_load_lora: + for lora in optional_lora_stack: + lora = {'lora_name': lora[0], 'model': model, 'clip': clip, 'model_strength': lora[1], 'clip_strength': lora[2]} + (model, clip) = easyCache.load_lora(lora) + lora['model'] = model + lora['clip'] = clip + pipe_lora_stack.append(lora) + if lora_name != 'None' and can_load_lora: + lora = {'lora_name': lora_name, 'model': model, 'clip': clip, 'model_strength': lora_model_strength, 'clip_strength': lora_clip_strength} + (model, clip) = easyCache.load_lora(lora) + pipe_lora_stack.append(lora) + if vae_name not in ['Baked VAE', 'Baked-VAE']: + vae = easyCache.load_vae(vae_name) + if not clip: + raise Exception('No CLIP found') + (positive_embeddings_final, positive_wildcard_prompt, model, clip) = prompt_to_cond('positive', model, clip, clip_skip, pipe_lora_stack, positive, positive_token_normalization, positive_weight_interpretation, a1111_prompt_style, my_unique_id, prompt, easyCache) + (negative_embeddings_final, negative_wildcard_prompt, model, clip) = prompt_to_cond('negative', model, clip, clip_skip, pipe_lora_stack, negative, negative_token_normalization, negative_weight_interpretation, a1111_prompt_style, my_unique_id, prompt, easyCache) + image = easySampler.pil2tensor(Image.new('RGB', (1, 1), (0, 0, 0))) + log_node_warn('处理结束...') + pipe = {'model': model, 'positive': positive_embeddings_final, 'negative': negative_embeddings_final, 'vae': vae, 'clip': clip, 'samples': samples, 'images': image, 'seed': 0, 'loader_settings': {'ckpt_name': ckpt_name, 'vae_name': vae_name, 'lora_name': lora_name, 'lora_model_strength': lora_model_strength, 'lora_clip_strength': lora_clip_strength, 'lora_stack': pipe_lora_stack, 'refiner_ckpt_name': None, 'refiner_vae_name': None, 'refiner_lora_name': None, 'refiner_lora_model_strength': None, 'refiner_lora_clip_strength': None, 'clip_skip': clip_skip, 'a1111_prompt_style': a1111_prompt_style, 'positive': positive, 'positive_l': None, 'positive_g': None, 'positive_token_normalization': positive_token_normalization, 'positive_weight_interpretation': positive_weight_interpretation, 'positive_balance': None, 'negative': negative, 'negative_l': None, 'negative_g': None, 'negative_token_normalization': negative_token_normalization, 'negative_weight_interpretation': negative_weight_interpretation, 'negative_balance': None, 'empty_latent_width': empty_latent_width, 'empty_latent_height': empty_latent_height, 'batch_size': batch_size, 'seed': 0, 'empty_samples': samples}} + return {'ui': {'positive': positive_wildcard_prompt, 'negative': negative_wildcard_prompt}, 'result': (pipe, model, vae, clip, positive_embeddings_final, negative_embeddings_final, samples)} +``` \ No newline at end of file diff --git a/docs/easy fullkSampler.md b/docs/easy fullkSampler.md new file mode 100644 index 0000000..7d3ce26 --- /dev/null +++ b/docs/easy fullkSampler.md @@ -0,0 +1,199 @@ +# Documentation +- Class name: samplerFull +- Category: EasyUse/Sampler +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +节点类'samplerFull'旨在提供一个全面的采样框架,用于生成高质量的图像。它利用先进的采样技术的力量,创造视觉连贯和多样化的输出。该节点的主要功能是促进生成与输入条件和约束相一致的图像,确保丰富的结果多样性。通过抽象采样过程,此节点强调生成既美观又技术准确的图像,为系统的创造性和研究导向目标做出重要贡献。 + +# Input types +## Required +- pipe + - ‘pipe’参数是‘samplerFull’节点的主要输入,为采样过程提供必要的数据和设置。它包括模型信息、条件数据和配置参数,指导最终图像的生成。此参数至关重要,因为它直接影响输出图像的质量和特性。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict +- steps + - ‘s steps’参数定义了采样过程将经历的迭代次数。它是决定生成图像的精炼级别的关键因素。通常,步数越多,生成的图像就越详细、越精炼,因为模型有更多机会调整和提高图像质量。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - ‘cfg’参数调整采样过程的配置设置,影响诸如噪声水平和模型行为等多种方面。它在调整输出以满足特定要求或期望结果方面发挥着重要作用,允许对图像生成采取定制化的方法。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- pipe + - ‘samplerFull’节点的‘pipe’输出包含了在采样过程中更新和精炼的全面数据和设置。它包括最终图像、模型信息以及进一步处理或分析所必需的任何其他相关细节。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict +- image + - ‘image’输出代表了采样过程生成的最终图像。这些图像是输入参数和设置的直接体现,展示了‘samplerFull’节点在创建视觉上吸引人和情境相关的输出方面的能力。 + - Comfy dtype: IMAGE + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class samplerFull(LayerDiffuse): + + def __init__(self): + super().__init__() + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), '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': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'image_output': (['Hide', 'Preview', 'Save', 'Hide/Save', 'Sender', 'Sender/Save'],), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'save_prefix': ('STRING', {'default': 'ComfyUI'})}, 'optional': {'seed': ('INT', {'default': 0, 'min': 0, 'max': MAX_SEED_NUM}), 'model': ('MODEL',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent': ('LATENT',), 'vae': ('VAE',), 'clip': ('CLIP',), 'xyPlot': ('XYPLOT',), 'image': ('IMAGE',)}, 'hidden': {'tile_size': 'INT', 'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID', 'embeddingsList': (folder_paths.get_filename_list('embeddings'),)}} + RETURN_TYPES = ('PIPE_LINE', 'IMAGE', 'MODEL', 'CONDITIONING', 'CONDITIONING', 'LATENT', 'VAE', 'CLIP', 'INT') + RETURN_NAMES = ('pipe', 'image', 'model', 'positive', 'negative', 'latent', 'vae', 'clip', 'seed') + OUTPUT_NODE = True + FUNCTION = 'run' + CATEGORY = 'EasyUse/Sampler' + + def run(self, pipe, steps, cfg, sampler_name, scheduler, denoise, image_output, link_id, save_prefix, seed=None, model=None, positive=None, negative=None, latent=None, vae=None, clip=None, xyPlot=None, tile_size=None, prompt=None, extra_pnginfo=None, my_unique_id=None, force_full_denoise=False, disable_noise=False, downscale_options=None): + easyCache.update_loaded_objects(prompt) + samp_model = model if model is not None else pipe['model'] + samp_positive = positive if positive is not None else pipe['positive'] + samp_negative = negative if negative is not None else pipe['negative'] + samp_samples = latent if latent is not None else pipe['samples'] + samp_vae = vae if vae is not None else pipe['vae'] + samp_clip = clip if clip is not None else pipe['clip'] + samp_seed = seed if seed is not None else pipe['seed'] + steps = steps if steps is not None else pipe['loader_settings']['steps'] + start_step = pipe['loader_settings']['start_step'] if 'start_step' in pipe['loader_settings'] else 0 + last_step = pipe['loader_settings']['last_step'] if 'last_step' in pipe['loader_settings'] else 10000 + cfg = cfg if cfg is not None else pipe['loader_settings']['cfg'] + sampler_name = sampler_name if sampler_name is not None else pipe['loader_settings']['sampler_name'] + scheduler = scheduler if scheduler is not None else pipe['loader_settings']['scheduler'] + denoise = denoise if denoise is not None else pipe['loader_settings']['denoise'] + add_noise = pipe['loader_settings']['add_noise'] if 'add_noise' in pipe['loader_settings'] else 'enabled' + force_full_denoise = pipe['loader_settings']['force_full_denoise'] if 'force_full_denoise' in pipe['loader_settings'] else True + disable_noise = False + if add_noise == 'disable': + disable_noise = True + + def downscale_model_unet(samp_model): + if downscale_options is None: + return samp_model + elif 'PatchModelAddDownscale' in ALL_NODE_CLASS_MAPPINGS: + cls = ALL_NODE_CLASS_MAPPINGS['PatchModelAddDownscale'] + if downscale_options['downscale_factor'] is None: + unet_config = samp_model.model.model_config.unet_config + if unet_config is not None and 'samples' in samp_samples: + height = samp_samples['samples'].shape[2] * 8 + width = samp_samples['samples'].shape[3] * 8 + context_dim = unet_config.get('context_dim') + longer_side = width if width > height else height + if context_dim is not None and longer_side > context_dim: + width_downscale_factor = float(width / context_dim) + height_downscale_factor = float(height / context_dim) + if width_downscale_factor > 1.75: + log_node_warn('正在收缩模型Unet...') + log_node_warn('收缩系数:' + str(width_downscale_factor)) + (samp_model,) = cls().patch(samp_model, downscale_options['block_number'], width_downscale_factor, 0, 0.35, True, 'bicubic', 'bicubic') + elif height_downscale_factor > 1.25: + log_node_warn('正在收缩模型Unet...') + log_node_warn('收缩系数:' + str(height_downscale_factor)) + (samp_model,) = cls().patch(samp_model, downscale_options['block_number'], height_downscale_factor, 0, 0.35, True, 'bicubic', 'bicubic') + else: + cls = ALL_NODE_CLASS_MAPPINGS['PatchModelAddDownscale'] + log_node_warn('正在收缩模型Unet...') + log_node_warn('收缩系数:' + str(downscale_options['downscale_factor'])) + (samp_model,) = cls().patch(samp_model, downscale_options['block_number'], downscale_options['downscale_factor'], downscale_options['start_percent'], downscale_options['end_percent'], downscale_options['downscale_after_skip'], downscale_options['downscale_method'], downscale_options['upscale_method']) + return samp_model + + def process_sample_state(pipe, samp_model, samp_clip, samp_samples, samp_vae, samp_seed, samp_positive, samp_negative, steps, start_step, last_step, cfg, sampler_name, scheduler, denoise, image_output, link_id, save_prefix, tile_size, prompt, extra_pnginfo, my_unique_id, preview_latent, force_full_denoise=force_full_denoise, disable_noise=disable_noise): + if 'layer_diffusion_method' in pipe['loader_settings']: + samp_blend_samples = pipe['blend_samples'] if 'blend_samples' in pipe else None + additional_cond = pipe['loader_settings']['layer_diffusion_cond'] if 'layer_diffusion_cond' in pipe['loader_settings'] else (None, None, None) + method = self.get_layer_diffusion_method(pipe['loader_settings']['layer_diffusion_method'], samp_blend_samples is not None) + images = pipe['images'].movedim(-1, 1) if 'images' in pipe else None + weight = pipe['loader_settings']['layer_diffusion_weight'] if 'layer_diffusion_weight' in pipe['loader_settings'] else 1.0 + (samp_model, samp_positive, samp_negative) = self.apply_layer_diffusion(samp_model, method, weight, samp_samples, samp_blend_samples, samp_positive, samp_negative, images, additional_cond) + blend_samples = pipe['blend_samples'] if 'blend_samples' in pipe else None + layer_diffusion_method = pipe['loader_settings']['layer_diffusion_method'] if 'layer_diffusion_method' in pipe['loader_settings'] else None + empty_samples = pipe['loader_settings']['empty_samples'] if 'empty_samples' in pipe['loader_settings'] else None + samples = empty_samples if layer_diffusion_method is not None and empty_samples is not None else samp_samples + if samp_model is not None: + samp_model = downscale_model_unet(samp_model) + start_time = int(time.time() * 1000) + samp_samples = sampler.common_ksampler(samp_model, samp_seed, steps, cfg, sampler_name, scheduler, samp_positive, samp_negative, samples, denoise=denoise, preview_latent=preview_latent, start_step=start_step, last_step=last_step, force_full_denoise=force_full_denoise, disable_noise=disable_noise) + end_time = int(time.time() * 1000) + latent = samp_samples['samples'] + if tile_size is not None: + samp_images = samp_vae.decode_tiled(latent, tile_x=tile_size // 8, tile_y=tile_size // 8) + else: + samp_images = samp_vae.decode(latent).cpu() + (new_images, samp_images, alpha) = self.layer_diffusion_decode(layer_diffusion_method, latent, blend_samples, samp_images, samp_model) + end_decode_time = int(time.time() * 1000) + spent_time = '扩散:' + str((end_time - start_time) / 1000) + '秒, 解码:' + str((end_decode_time - end_time) / 1000) + '秒' + results = easySave(new_images, save_prefix, image_output, prompt, extra_pnginfo) + sampler.update_value_by_id('results', my_unique_id, results) + easyCache.update_loaded_objects(prompt) + new_pipe = {'model': samp_model, 'positive': samp_positive, 'negative': samp_negative, 'vae': samp_vae, 'clip': samp_clip, 'samples': samp_samples, 'blend_samples': blend_samples, 'images': new_images, 'samp_images': samp_images, 'alpha': alpha, 'seed': samp_seed, 'loader_settings': {**pipe['loader_settings'], 'spent_time': spent_time}} + sampler.update_value_by_id('pipe_line', my_unique_id, new_pipe) + del pipe + if image_output in ('Hide', 'Hide/Save'): + return {'ui': {}, 'result': sampler.get_output(new_pipe)} + if image_output in ('Sender', 'Sender/Save'): + PromptServer.instance.send_sync('img-send', {'link_id': link_id, 'images': results}) + return {'ui': {'images': results}, 'result': sampler.get_output(new_pipe)} + + def process_xyPlot(pipe, samp_model, samp_clip, samp_samples, samp_vae, samp_seed, samp_positive, samp_negative, steps, cfg, sampler_name, scheduler, denoise, image_output, link_id, save_prefix, tile_size, prompt, extra_pnginfo, my_unique_id, preview_latent, xyPlot, force_full_denoise, disable_noise): + sampleXYplot = easyXYPlot(xyPlot, save_prefix, image_output, prompt, extra_pnginfo, my_unique_id, sampler, easyCache) + if not sampleXYplot.validate_xy_plot(): + return process_sample_state(pipe, samp_model, samp_clip, samp_samples, samp_vae, samp_seed, samp_positive, samp_negative, steps, 0, 10000, cfg, sampler_name, scheduler, denoise, image_output, link_id, save_prefix, tile_size, prompt, extra_pnginfo, my_unique_id, preview_latent) + if samp_model is not None: + samp_model = downscale_model_unet(samp_model) + alpha = None + blend_samples = pipe['blend_samples'] if 'blend_samples' in pipe else None + layer_diffusion_method = pipe['loader_settings']['layer_diffusion_method'] if 'layer_diffusion_method' in pipe['loader_settings'] else None + plot_image_vars = {'x_node_type': sampleXYplot.x_node_type, 'y_node_type': sampleXYplot.y_node_type, 'lora_name': pipe['loader_settings']['lora_name'] if 'lora_name' in pipe['loader_settings'] else None, 'lora_model_strength': pipe['loader_settings']['lora_model_strength'] if 'model_strength' in pipe['loader_settings'] else None, 'lora_clip_strength': pipe['loader_settings']['lora_clip_strength'] if 'clip_strength' in pipe['loader_settings'] else None, 'lora_stack': pipe['loader_settings']['lora_stack'] if 'lora_stack' in pipe['loader_settings'] else None, 'steps': steps, 'cfg': cfg, 'sampler_name': sampler_name, 'scheduler': scheduler, 'denoise': denoise, 'seed': samp_seed, 'images': pipe['images'], 'model': samp_model, 'vae': samp_vae, 'clip': samp_clip, 'positive_cond': samp_positive, 'negative_cond': samp_negative, 'ckpt_name': pipe['loader_settings']['ckpt_name'] if 'ckpt_name' in pipe['loader_settings'] else None, 'vae_name': pipe['loader_settings']['vae_name'] if 'vae_name' in pipe['loader_settings'] else None, 'clip_skip': pipe['loader_settings']['clip_skip'] if 'clip_skip' in pipe['loader_settings'] else None, 'positive': pipe['loader_settings']['positive'] if 'positive' in pipe['loader_settings'] else None, 'positive_token_normalization': pipe['loader_settings']['positive_token_normalization'] if 'positive_token_normalization' in pipe['loader_settings'] else None, 'positive_weight_interpretation': pipe['loader_settings']['positive_weight_interpretation'] if 'positive_weight_interpretation' in pipe['loader_settings'] else None, 'negative': pipe['loader_settings']['negative'] if 'negative' in pipe['loader_settings'] else None, 'negative_token_normalization': pipe['loader_settings']['negative_token_normalization'] if 'negative_token_normalization' in pipe['loader_settings'] else None, 'negative_weight_interpretation': pipe['loader_settings']['negative_weight_interpretation'] if 'negative_weight_interpretation' in pipe['loader_settings'] else None} + if 'models' in pipe['loader_settings']: + plot_image_vars['models'] = pipe['loader_settings']['models'] + if 'vae_use' in pipe['loader_settings']: + plot_image_vars['vae_use'] = pipe['loader_settings']['vae_use'] + if 'a1111_prompt_style' in pipe['loader_settings']: + plot_image_vars['a1111_prompt_style'] = pipe['loader_settings']['a1111_prompt_style'] + if 'cnet_stack' in pipe['loader_settings']: + plot_image_vars['cnet'] = pipe['loader_settings']['cnet_stack'] + if 'positive_cond_stack' in pipe['loader_settings']: + plot_image_vars['positive_cond_stack'] = pipe['loader_settings']['positive_cond_stack'] + if 'negative_cond_stack' in pipe['loader_settings']: + plot_image_vars['negative_cond_stack'] = pipe['loader_settings']['negative_cond_stack'] + if layer_diffusion_method: + plot_image_vars['layer_diffusion_method'] = layer_diffusion_method + if 'layer_diffusion_weight' in pipe['loader_settings']: + plot_image_vars['layer_diffusion_weight'] = pipe['loader_settings']['layer_diffusion_weight'] + if 'layer_diffusion_cond' in pipe['loader_settings']: + plot_image_vars['layer_diffusion_cond'] = pipe['loader_settings']['layer_diffusion_cond'] + if 'empty_samples' in pipe['loader_settings']: + plot_image_vars['empty_samples'] = pipe['loader_settings']['empty_samples'] + latent_image = sampleXYplot.get_latent(pipe['samples']) + latents_plot = sampleXYplot.get_labels_and_sample(plot_image_vars, latent_image, preview_latent, start_step, last_step, force_full_denoise, disable_noise) + samp_samples = {'samples': latents_plot} + (images, image_list) = sampleXYplot.plot_images_and_labels() + output_images = torch.stack([tensor.squeeze() for tensor in image_list]) + (new_images, samp_images, alpha) = self.layer_diffusion_decode(layer_diffusion_method, latents_plot, blend_samples, output_images, samp_model) + results = easySave(images, save_prefix, image_output, prompt, extra_pnginfo) + sampler.update_value_by_id('results', my_unique_id, results) + easyCache.update_loaded_objects(prompt) + new_pipe = {'model': samp_model, 'positive': samp_positive, 'negative': samp_negative, 'vae': samp_vae, 'clip': samp_clip, 'samples': samp_samples, 'blend_samples': blend_samples, 'samp_images': samp_images, 'images': new_images, 'seed': samp_seed, 'alpha': alpha, 'loader_settings': pipe['loader_settings']} + sampler.update_value_by_id('pipe_line', my_unique_id, new_pipe) + del pipe + if image_output in ('Hide', 'Hide/Save'): + return sampler.get_output(new_pipe) + return {'ui': {'images': results}, 'result': sampler.get_output(new_pipe)} + preview_latent = True + if image_output in ('Hide', 'Hide/Save'): + preview_latent = False + xyplot_id = next((x for x in prompt if 'XYPlot' in str(prompt[x]['class_type'])), None) + if xyplot_id is None: + xyPlot = None + else: + xyPlot = pipe['loader_settings']['xyplot'] if 'xyplot' in pipe['loader_settings'] else xyPlot + if xyPlot is not None: + return process_xyPlot(pipe, samp_model, samp_clip, samp_samples, samp_vae, samp_seed, samp_positive, samp_negative, steps, cfg, sampler_name, scheduler, denoise, image_output, link_id, save_prefix, tile_size, prompt, extra_pnginfo, my_unique_id, preview_latent, xyPlot, force_full_denoise, disable_noise) + else: + return process_sample_state(pipe, samp_model, samp_clip, samp_samples, samp_vae, samp_seed, samp_positive, samp_negative, steps, start_step, last_step, cfg, sampler_name, scheduler, denoise, image_output, link_id, save_prefix, tile_size, prompt, extra_pnginfo, my_unique_id, preview_latent, force_full_denoise, disable_noise) +``` \ No newline at end of file diff --git a/docs/easy globalSeed.md b/docs/easy globalSeed.md new file mode 100644 index 0000000..c107887 --- /dev/null +++ b/docs/easy globalSeed.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: globalSeed +- Category: EasyUse/Seed +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +此类封装了生成和管理系统内各种操作的随机种子的功能,确保实验和模型训练的环境可控且可复现。 + +# Input types +## Required +- value + - “value”参数在指定初始种子值方面至关重要,这对于确保系统随机过程的可复现性非常重要。 + - Comfy dtype: INT + - Python dtype: int +- mode + - “mode”参数决定了种子生成的控制机制,决定了种子是在生成过程之前还是之后设置,从而影响了系统的整体随机性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +## Optional +- action + - “action”参数提供了多种种子操作策略,允许在系统执行期间对种子进行动态调整,这对于迭代或分支过程至关重要。 + - Comfy dtype: COMBO + - Python dtype: str +- last_seed + - “last_seed”参数作为最近使用的种子的参考,便于系统随机化过程的连续性和追踪。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- result + - “result”输出提供了种子管理操作的结构化摘要,封装了随机化过程的结果和应用的设置。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class globalSeed: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'value': ('INT', {'default': 0, 'min': 0, 'max': MAX_SEED_NUM}), 'mode': ('BOOLEAN', {'default': True, 'label_on': 'control_before_generate', 'label_off': 'control_after_generate'}), 'action': (['fixed', 'increment', 'decrement', 'randomize', 'increment for each node', 'decrement for each node', 'randomize for each node'],), 'last_seed': ('STRING', {'default': ''})}} + RETURN_TYPES = () + FUNCTION = 'doit' + CATEGORY = 'EasyUse/Seed' + OUTPUT_NODE = True + + def doit(self, **kwargs): + return {} +``` \ No newline at end of file diff --git a/docs/easy hiresFix.md b/docs/easy hiresFix.md new file mode 100644 index 0000000..39feac9 --- /dev/null +++ b/docs/easy hiresFix.md @@ -0,0 +1,123 @@ +# Documentation +- Class name: hiresFix +- Category: EasyUse/Fix +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +hiresFix节点旨在提高图像的分辨率,同时保持或提高其视觉质量。它通过采用各种上采样技术实现这一点,并允许进行调整以适应特定要求。该节点的主要目标是为用户提提供一个易于使用的图像增强界面,抽象了底层模型和算法的复杂性。 + +# Input types +## Required +- model_name + - 模型名称参数对于选择适当的上采样模型至关重要。它决定了用于图像增强过程的特定算法,显著影响输出质量和性能。 + - Comfy dtype: COMBO + - Python dtype: List[str] +- rescale_after_model + - rescale_after_model参数决定是否在上采样后调整图像大小。这影响处理后图像的最终尺寸,对于适应特定的显示或打印要求可能至关重要。 + - Comfy dtype: BOOL + - Python dtype: bool +- rescale_method + - rescale_method参数定义了上采样后调整图像尺寸所用的技术。它在保持图像的宽高比和整体视觉连贯性方面起着关键作用。 + - Comfy dtype: COMBO + - Python dtype: str +- percent + - 百分比参数指定在使用'按百分比'调整大小时图像应放大的百分比。它直接影响图像的最终大小,更高的值会导致尺寸的显著增加。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- pipe + - pipe输出提供了处理流水线的结构化表示,包括使用的模型和参数。它对于保持图像增强工作流的一致性和可重复性至关重要。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- image + - 图像输出包含输入图像的增强版,即高分辨率版本。它是节点操作的主要结果,对于上采样过程的视觉验证至关重要。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- latent + - 潜在输出表示图像的编码版本,可用于进一步的处理或分析。它作为一个中间表示,捕捉图像的基本特征。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class hiresFix: + upscale_methods = ['nearest-exact', 'bilinear', 'area', 'bicubic', 'lanczos', 'bislerp'] + crop_methods = ['disabled', 'center'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model_name': (folder_paths.get_filename_list('upscale_models'),), 'rescale_after_model': ([False, True], {'default': True}), 'rescale_method': (s.upscale_methods,), 'rescale': (['by percentage', 'to Width/Height', 'to longer side - maintain aspect'],), 'percent': ('INT', {'default': 50, 'min': 0, 'max': 1000, 'step': 1}), 'width': ('INT', {'default': 1024, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'height': ('INT', {'default': 1024, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'longer_side': ('INT', {'default': 1024, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'crop': (s.crop_methods,), 'image_output': (['Hide', 'Preview', 'Save', 'Hide/Save', 'Sender', 'Sender/Save'], {'default': 'Preview'}), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'save_prefix': ('STRING', {'default': 'ComfyUI'})}, 'optional': {'pipe': ('PIPE_LINE',), 'image': ('IMAGE',), 'vae': ('VAE',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE', 'IMAGE', 'LATENT') + RETURN_NAMES = ('pipe', 'image', 'latent') + FUNCTION = 'upscale' + CATEGORY = 'EasyUse/Fix' + OUTPUT_NODE = True + + def vae_encode_crop_pixels(self, pixels): + x = pixels.shape[1] // 8 * 8 + y = pixels.shape[2] // 8 * 8 + 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, :] + return pixels + + def upscale(self, model_name, rescale_after_model, rescale_method, rescale, percent, width, height, longer_side, crop, image_output, link_id, save_prefix, pipe=None, image=None, vae=None, prompt=None, extra_pnginfo=None, my_unique_id=None): + new_pipe = {} + if pipe is not None: + image = image if image is not None else pipe['images'] + vae = vae if vae is not None else pipe.get('vae') + elif image is None or vae is None: + raise ValueError('pipe or image or vae missing.') + model_path = folder_paths.get_full_path('upscale_models', model_name) + sd = comfy.utils.load_torch_file(model_path, safe_load=True) + upscale_model = model_loading.load_state_dict(sd).eval() + device = comfy.model_management.get_torch_device() + upscale_model.to(device) + in_img = image.movedim(-1, -3).to(device) + tile = 128 + 64 + overlap = 8 + steps = in_img.shape[0] * comfy.utils.get_tiled_scale_steps(in_img.shape[3], in_img.shape[2], tile_x=tile, tile_y=tile, overlap=overlap) + pbar = comfy.utils.ProgressBar(steps) + s = comfy.utils.tiled_scale(in_img, lambda a: upscale_model(a), tile_x=tile, tile_y=tile, overlap=overlap, upscale_amount=upscale_model.scale, pbar=pbar) + upscale_model.cpu() + s = torch.clamp(s.movedim(-3, -1), min=0, max=1.0) + if rescale_after_model == True: + samples = s.movedim(-1, 1) + orig_height = samples.shape[2] + orig_width = samples.shape[3] + if rescale == 'by percentage' and percent != 0: + height = percent / 100 * orig_height + width = percent / 100 * orig_width + if width > MAX_RESOLUTION: + width = MAX_RESOLUTION + if height > MAX_RESOLUTION: + height = MAX_RESOLUTION + width = easySampler.enforce_mul_of_64(width) + height = easySampler.enforce_mul_of_64(height) + elif rescale == 'to longer side - maintain aspect': + longer_side = easySampler.enforce_mul_of_64(longer_side) + if orig_width > orig_height: + (width, height) = (longer_side, easySampler.enforce_mul_of_64(longer_side * orig_height / orig_width)) + else: + (width, height) = (easySampler.enforce_mul_of_64(longer_side * orig_width / orig_height), longer_side) + s = comfy.utils.common_upscale(samples, width, height, rescale_method, crop) + s = s.movedim(1, -1) + pixels = self.vae_encode_crop_pixels(s) + t = vae.encode(pixels[:, :, :, :3]) + if pipe is not None: + new_pipe = {'model': pipe['model'], 'positive': pipe['positive'], 'negative': pipe['negative'], 'vae': vae, 'clip': pipe['clip'], 'samples': {'samples': t}, 'images': s, 'seed': pipe['seed'], 'loader_settings': {**pipe['loader_settings']}} + del pipe + else: + new_pipe = {} + results = easySave(s, save_prefix, image_output, prompt, extra_pnginfo) + if image_output in ('Sender', 'Sender/Save'): + PromptServer.instance.send_sync('img-send', {'link_id': link_id, 'images': results}) + if image_output in ('Hide', 'Hide/Save'): + return (new_pipe, s, {'samples': t}) + return {'ui': {'images': results}, 'result': (new_pipe, s, {'samples': t})} +``` \ No newline at end of file diff --git a/docs/easy if.md b/docs/easy if.md new file mode 100644 index 0000000..7b29663 --- /dev/null +++ b/docs/easy if.md @@ -0,0 +1,47 @@ +# Documentation +- Class name: If +- Category: EasyUse/Logic/Math +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +If节点作为一个条件执行单元,评估输入的条件,并决定采取两个提供的分支中的哪一个,从而在计算图中构建控制流。 + +# Input types +## Required +- any + - ‘any’输入是一个条件表达式,它决定了If节点的流程。它对于确定哪个输出分支将被执行至关重要。 + - Comfy dtype: * + - Python dtype: Any +- if + - ‘if’输入代表当‘any’条件满足时要执行的动作。它是节点功能的重要组成部分,因为它定义了肯定的结果。 + - Comfy dtype: * + - Python dtype: Any +- else + - ‘else’输入定义了当‘any’条件不满足时执行的替代动作。它对于在节点内提供完整的条件逻辑至关重要。 + - Comfy dtype: * + - Python dtype: Any + +# Output types +- ? + - If节点的输出是根据‘any’条件的评估结果,来自‘if’或‘else’输入之一的结果。它代表了条件执行的最终结果。 + - Comfy dtype: * + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class If: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'any': (AlwaysEqualProxy('*'),), 'if': (AlwaysEqualProxy('*'),), 'else': (AlwaysEqualProxy('*'),)}} + RETURN_TYPES = (AlwaysEqualProxy('*'),) + RETURN_NAMES = ('?',) + FUNCTION = 'execute' + CATEGORY = 'EasyUse/Logic/Math' + + def execute(self, *args, **kwargs): + return (kwargs['if'] if kwargs['any'] else kwargs['else'],) +``` \ No newline at end of file diff --git a/docs/easy imageInsetCrop.md b/docs/easy imageInsetCrop.md new file mode 100644 index 0000000..61ea316 --- /dev/null +++ b/docs/easy imageInsetCrop.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: imageInsetCrop +- Category: EasyUse/Image +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点通过允许用户以像素值或图像尺寸百分比的方式定义裁剪区域,促进了图像的精确裁剪。它通过无需复杂计算即可实现目标图像操作,增强了图像处理工作流程,确保裁剪后的图像满足特定要求。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它是将要执行裁剪操作的源。它直接影响节点的输出,决定了结果图像的视觉内容和尺寸。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- measurement + - 测量参数决定了裁剪值是作为绝对像素还是相对百分比输入。这显著影响了裁剪区域的计算方式,从而影响了裁剪图像的最终尺寸。 + - Comfy dtype: COMBO['Pixels', 'Percentage'] + - Python dtype: str +- left + - 左边距参数指定了从图像左边缘到裁剪区域开始的距离。它在确定图像中裁剪区域的水平位置方面起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- right + - 右边距参数定义了从图像右边缘到裁剪区域结束的距离。它与左边距参数共同作用,以确定裁剪部分的总宽度。 + - Comfy dtype: INT + - Python dtype: int +- top + - 上边距参数设置了从图像顶部到裁剪区域开始的距离。它在确定图像中裁剪区域的垂直位置方面至关重要。 + - Comfy dtype: INT + - Python dtype: int +- bottom + - 下边距参数指定了从图像底部到裁剪区域结束的距离。与上边距参数一起,它定义了裁剪部分的高度。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- image + - 输出图像是裁剪操作的结果。它代表了在应用指定的内边距后原始图像剩余的部分,捕获了所需的视觉内容。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image + +# Usage tips +- Infra type: CPU + +# Source code +``` +class imageInsetCrop: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'measurement': (['Pixels', 'Percentage'],), 'left': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION, 'step': 8}), 'right': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION, 'step': 8}), 'top': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION, 'step': 8}), 'bottom': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION, 'step': 8})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'crop' + CATEGORY = 'EasyUse/Image' + + def crop(self, measurement, left, right, top, bottom, image=None): + """Does the crop.""" + (_, height, width, _) = image.shape + if measurement == 'Percentage': + left = int(width - width * (100 - left) / 100) + right = int(width - width * (100 - right) / 100) + top = int(height - height * (100 - top) / 100) + bottom = int(height - height * (100 - bottom) / 100) + left = left // 8 * 8 + right = right // 8 * 8 + top = top // 8 * 8 + bottom = bottom // 8 * 8 + if left == 0 and right == 0 and (bottom == 0) and (top == 0): + return (image,) + (inset_left, inset_right, inset_top, inset_bottom) = get_new_bounds(width, height, left, right, top, bottom) + if inset_top > inset_bottom: + raise ValueError(f'Invalid cropping dimensions top ({inset_top}) exceeds bottom ({inset_bottom})') + if inset_left > inset_right: + raise ValueError(f'Invalid cropping dimensions left ({inset_left}) exceeds right ({inset_right})') + log_node_info('Image Inset Crop', f'Cropping image {width}x{height} width inset by {inset_left},{inset_right}, ' + f'and height inset by {inset_top}, {inset_bottom}') + image = image[:, inset_top:inset_bottom, inset_left:inset_right, :] + return (image,) +``` \ No newline at end of file diff --git a/docs/easy imagePixelPerfect.md b/docs/easy imagePixelPerfect.md new file mode 100644 index 0000000..3f2578e --- /dev/null +++ b/docs/easy imagePixelPerfect.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: imagePixelPerfect +- Category: EasyUse/Image +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点类旨在通过计算在指定尺寸内保持图像纵横比的理想像素数来优化图像分辨率。它强调在调整图像大小时保持图像的视觉完整性。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它是节点操作的来源。它通过决定节点将处理的初始尺寸和质量来影响整个过程。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +## Optional +- resize_mode + - 调整模式参数影响图像的调整方式,要么最大化要么最小化纵横比以适应给定的约束条件。这对于在调整大小后实现期望的视觉结果非常重要。 + - Comfy dtype: COMBO[ResizeMode.RESIZE.value, ResizeMode.INNER_FIT.value, ResizeMode.OUTER_FIT.value] + - Python dtype: Union[str, ResizeMode] + +# Output types +- resolution + - 分辨率输出提供了计算出的理想像素数,这是节点处理的结果。它很重要,因为它决定了缩放后图像的最终大小。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class imagePixelPerfect: + + @classmethod + def INPUT_TYPES(s): + RESIZE_MODES = [ResizeMode.RESIZE.value, ResizeMode.INNER_FIT.value, ResizeMode.OUTER_FIT.value] + return {'required': {'image': ('IMAGE',), 'resize_mode': (RESIZE_MODES, {'default': ResizeMode.RESIZE.value})}} + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('resolution',) + OUTPUT_NODE = True + FUNCTION = 'execute' + CATEGORY = 'EasyUse/Image' + + def execute(self, image, resize_mode): + (_, raw_H, raw_W, _) = image.shape + width = raw_W + height = raw_H + k0 = float(height) / float(raw_H) + k1 = float(width) / float(raw_W) + if resize_mode == ResizeMode.OUTER_FIT.value: + estimation = min(k0, k1) * float(min(raw_H, raw_W)) + else: + estimation = max(k0, k1) * float(min(raw_H, raw_W)) + result = int(np.round(estimation)) + text = f'Width:{str(width)}\nHeight:{str(height)}\nPixelPerfect:{str(result)}' + return {'ui': {'text': text}, 'result': (result,)} +``` \ No newline at end of file diff --git a/docs/easy imageRatio.md b/docs/easy imageRatio.md new file mode 100644 index 0000000..b372196 --- /dev/null +++ b/docs/easy imageRatio.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: imageRatio +- Category: EasyUse/Image +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点类旨在处理图像并计算其尺寸的最大公约数(GCD),从而确定整数和浮点比例上的宽高比。它的目的是简化图像比例的分析,以便进一步处理或显示。 + +# Input types +## Required +- image + - 图像参数对于节点至关重要,因为它是被分析尺寸以计算宽高比的主要输入。没有这个输入,节点无法执行其预期功能。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray + +# Output types +- result + - 此输出提供输入图像的计算宽高比,包括整数和浮点格式。它很重要,因为它清晰地说明了图像尺寸之间的关系,这对于各种图像处理任务非常有用。 + - Comfy dtype: COMBO[INT, INT, FLOAT, FLOAT] + - Python dtype: Tuple[int, int, float, float] +- ui + - ‘ui’输出是一个包含文本信息的字典,提供了图像宽高比的人类可读摘要。此输出对于在用户界面中显示结果非常有用,通过以易于理解的格式呈现数据来增强用户体验。 + - Comfy dtype: DICT + - Python dtype: Dict[str, str] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class imageRatio: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',)}} + RETURN_TYPES = ('INT', 'INT', 'FLOAT', 'FLOAT') + RETURN_NAMES = ('width_ratio_int', 'height_ratio_int', 'width_ratio_float', 'height_ratio_float') + OUTPUT_NODE = True + FUNCTION = 'image_ratio' + CATEGORY = 'EasyUse/Image' + + def gcf(self, a, b): + while b: + (a, b) = (b, a % b) + return a + + def image_ratio(self, image): + (_, raw_H, raw_W, _) = image.shape + width = raw_W + height = raw_H + ratio = self.gcf(width, height) + if width is not None and height is not None: + width_ratio = width // ratio + height_ratio = height // ratio + result = (width_ratio, height_ratio, width_ratio, height_ratio) + else: + width_ratio = 0 + height_ratio = 0 + result = (0, 0, 0.0, 0.0) + text = f'Image Ratio is {str(width_ratio)}:{str(height_ratio)}' + return {'ui': {'text': text}, 'result': result} +``` \ No newline at end of file diff --git a/docs/easy imageRemBg.md b/docs/easy imageRemBg.md new file mode 100644 index 0000000..992c083 --- /dev/null +++ b/docs/easy imageRemBg.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: imageRemBg +- Category: EasyUse/Image +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +imageRemBg节点旨在从图像中移除背景,为进一步使用或展示提供简化且干净的前景。它通过应用一个针对背景移除优化的深度学习模型来实现这一点,确保输出图像保留其主要主题,同时尽量减少背景干扰。 + +# Input types +## Required +- images + - 输入图像参数对于节点的操作至关重要,因为它定义了将要应用背景移除过程的数据。这些图像的质量和格式直接影响背景移除的效果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- rem_mode + - rem_mode参数指定节点要使用的移除模式。它至关重要,因为它决定了用于背景分离的算法方法,影响最终输出的准确性。 + - Comfy dtype: STRING + - Python dtype: str +- image_output + - image_output参数指示处理后如何处理生成的图像。它可以隐藏它们、预览它们、保存它们,或者既隐藏又保存,根据用户需求提供管理输出的灵活性。 + - Comfy dtype: COMBO['Hide', 'Preview', 'Save', 'Hide/Save'] + - Python dtype: str +- save_prefix + - 当用户选择保存处理后的图像时,使用save_prefix参数。它为保存的文件提供基础名称,这对于组织和识别输出图像很重要。 + - Comfy dtype: STRING + - Python dtype: str +- prompt + - 可选的prompt参数可用于为节点提供额外的上下文或指令,这对于某些操作或根据特定标准细化输出可能是必要的。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - extra_pnginfo参数用于包含节点操作可能需要的任何额外信息。这可能是元数据或其他影响处理或输出的相关细节。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: str + +# Output types +- image + - 图像输出参数代表移除背景后的处理图像。它是节点的主要输出,具有重要意义,因为反映了背景移除过程的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- mask + - 掩码输出参数提供了在背景移除过程中生成的二进制掩码。它有助于在图像中将前景对象与背景隔离开来。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class imageRemBg: + + @classmethod + def INPUT_TYPES(self): + return {'required': {'images': ('IMAGE',), 'rem_mode': (('RMBG-1.4',),), 'image_output': (['Hide', 'Preview', 'Save', 'Hide/Save'], {'default': 'Preview'}), 'save_prefix': ('STRING', {'default': 'ComfyUI'})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = ('IMAGE', 'MASK') + RETURN_NAMES = ('image', 'mask') + FUNCTION = 'remove' + OUTPUT_NODE = True + CATEGORY = 'EasyUse/Image' + + def remove(self, rem_mode, images, image_output, save_prefix, prompt=None, extra_pnginfo=None): + if rem_mode == 'RMBG-1.4': + model_url = REMBG_MODELS[rem_mode]['model_url'] + suffix = model_url.split('.')[-1] + model_path = get_local_filepath(model_url, REMBG_DIR, rem_mode + '.' + suffix) + net = BriaRMBG() + device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') + net.load_state_dict(torch.load(model_path, map_location=device)) + net.to(device) + net.eval() + model_input_size = [1024, 1024] + new_images = list() + masks = list() + for image in images: + orig_im = tensor2pil(image) + (w, h) = orig_im.size + image = preprocess_image(orig_im, model_input_size).to(device) + result = net(image) + result_image = postprocess_image(result[0][0], (h, w)) + mask_im = Image.fromarray(result_image) + new_im = Image.new('RGBA', mask_im.size, (0, 0, 0, 0)) + new_im.paste(orig_im, mask=mask_im) + new_images.append(pil2tensor(new_im)) + masks.append(pil2tensor(mask_im)) + new_images = torch.cat(new_images, dim=0) + masks = torch.cat(masks, dim=0) + results = easySave(new_images, save_prefix, image_output, prompt, extra_pnginfo) + if image_output in ('Hide', 'Hide/Save'): + return {'ui': {}, 'result': (new_images, masks)} + return {'ui': {'images': results}, 'result': (new_images, masks)} + else: + return (None, None) +``` \ No newline at end of file diff --git a/docs/easy imageSave.md b/docs/easy imageSave.md new file mode 100644 index 0000000..19c8696 --- /dev/null +++ b/docs/easy imageSave.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: imageSaveSimple +- Category: EasyUse/Image +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点简化了图像数据的保存过程,提供了一种直接保存视觉输出的机制。它支持可选的图像压缩和预览生成,确保图像能够方便地用于后续使用或检查。 + +# Input types +## Required +- images + - images参数是必需的,因为它携带了需要保存的视觉数据。它通过决定存储的内容和输出的外观来影响整个操作。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +## Optional +- filename_prefix + - filename_prefix用于预定义保存图像的命名约定,这对于在输出目录中组织和识别文件至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- only_preview + - only_preview参数控制是否生成并保存图像的预览。它通过决定生成的输出类型来影响节点的操作。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- None + - 这个节点的输出不是一个数据对象,而是保存图像的动作。没有返回值表示保存过程已经完成。 + - Comfy dtype: None + - Python dtype: None + +# Usage tips +- Infra type: CPU + +# Source code +``` +class imageSaveSimple: + + def __init__(self): + self.output_dir = folder_paths.get_output_directory() + self.type = 'output' + self.prefix_append = '' + self.compress_level = 4 + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'filename_prefix': ('STRING', {'default': 'ComfyUI'}), 'only_preview': ('BOOLEAN', {'default': False})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = () + FUNCTION = 'save' + OUTPUT_NODE = True + CATEGORY = 'EasyUse/Image' + + def save(self, images, filename_prefix='ComfyUI', only_preview=False, prompt=None, extra_pnginfo=None): + if only_preview: + PreviewImage().save_images(images, filename_prefix, prompt, extra_pnginfo) + return () + else: + return SaveImage().save_images(images, filename_prefix, prompt, extra_pnginfo) +``` \ No newline at end of file diff --git a/docs/easy imageScaleDown.md b/docs/easy imageScaleDown.md new file mode 100644 index 0000000..f7a3272 --- /dev/null +++ b/docs/easy imageScaleDown.md @@ -0,0 +1,71 @@ +# Documentation +- Class name: imageScaleDown +- Category: EasyUse/Image +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点旨在将图像调整为指定的宽度和高度,可能会采用中心裁剪来保持长宽比的完整性。这对于预处理图像数据以适应各种机器学习模型和应用程序所需的输入尺寸非常关键。 + +# Input types +## Required +- images + - 要缩小的图像。该参数至关重要,因为节点直接作用于图像数据,影响输出的尺寸和质量。 + - Comfy dtype: COMBO[Tensor] + - Python dtype: torch.Tensor +- width + - 缩放后图像的期望宽度。该参数至关重要,因为它设置了出的水平维度,影响着调整大小的过程。 + - Comfy dtype: INT + - Python dtype: int +- height + - 缩放后图像的期望高度。该参数至关重要,因为它设置了输出的垂直维度,影响着调整大小的过程。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- crop + - 调整大小时应用的裁剪方法。该参数重要,因为它决定了图像在缩放前是否居中,这可以增强输出的视觉呈现。 + - Comfy dtype: ENUM + - Python dtype: str + +# Output types +- IMAGE + - 调整大小后的图像。这是节点的主要输出,代表准备好进行进一步处理或分析的转换后的数据。 + - Comfy dtype: COMBO[Tensor] + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class imageScaleDown: + crop_methods = ['disabled', 'center'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'width': ('INT', {'default': 512, 'min': 1, 'max': MAX_RESOLUTION, 'step': 1}), 'height': ('INT', {'default': 512, 'min': 1, 'max': MAX_RESOLUTION, 'step': 1}), 'crop': (s.crop_methods,)}} + RETURN_TYPES = ('IMAGE',) + CATEGORY = 'EasyUse/Image' + FUNCTION = 'image_scale_down' + + def image_scale_down(self, images, width, height, crop): + if crop == 'center': + old_width = images.shape[2] + old_height = images.shape[1] + old_aspect = old_width / old_height + new_aspect = width / height + x = 0 + y = 0 + if old_aspect > new_aspect: + x = round((old_width - old_width * (new_aspect / old_aspect)) / 2) + elif old_aspect < new_aspect: + y = round((old_height - old_height * (old_aspect / new_aspect)) / 2) + s = images[:, y:old_height - y, x:old_width - x, :] + else: + s = images + results = [] + for image in s: + img = tensor2pil(image).convert('RGB') + img = img.resize((width, height), Image.LANCZOS) + results.append(pil2tensor(img)) + return (torch.cat(results, dim=0),) +``` \ No newline at end of file diff --git a/docs/easy imageScaleDownBy.md b/docs/easy imageScaleDownBy.md new file mode 100644 index 0000000..4126b47 --- /dev/null +++ b/docs/easy imageScaleDownBy.md @@ -0,0 +1,46 @@ +# Documentation +- Class name: imageScaleDownBy +- Category: EasyUse/Image +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点旨在通过按比例缩小图像尺寸来调整图像大小,同时保持视觉内容的完整性,并减少文件大小,以便更高效地处理或存储。 + +# Input types +## Required +- images + - 输入的图像是节点将要处理的主要数据。它们对节点的操作至关重要,因为它们决定了输出的视觉表示和质量。 + - Comfy dtype: COMBO[numpy.ndarray] + - Python dtype: numpy.ndarray +- scale_by + - 该参数定义了图像尺寸的缩放因子。它非常重要,因为它直接影响调整大小后的图像的最终尺寸和宽高比。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- images + - 输出包括调整大小后的图像,这些图像现在尺寸更小,但保留了原始图像的重要视觉元素,准备进行进一步的处理或存储。 + - Comfy dtype: COMBO[numpy.ndarray] + - Python dtype: numpy.ndarray + +# Usage tips +- Infra type: CPU + +# Source code +``` +class imageScaleDownBy(imageScaleDown): + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'scale_by': ('FLOAT', {'default': 0.5, 'min': 0.01, 'max': 1.0, 'step': 0.01})}} + RETURN_TYPES = ('IMAGE',) + CATEGORY = 'EasyUse/Image' + FUNCTION = 'image_scale_down_by' + + def image_scale_down_by(self, images, scale_by): + width = images.shape[2] + height = images.shape[1] + new_width = int(width * scale_by) + new_height = int(height * scale_by) + return self.image_scale_down(images, new_width, new_height, 'center') +``` \ No newline at end of file diff --git a/docs/easy imageScaleDownToSize.md b/docs/easy imageScaleDownToSize.md new file mode 100644 index 0000000..c2968c9 --- /dev/null +++ b/docs/easy imageScaleDownToSize.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: imageScaleDownToSize +- Category: EasyUse/Image +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点旨在将图像调整到指定大小,同时保持纵横比,并确保调整后的图像适应所需的尺寸。根据所选的最大或最小维度调整缩放因子,允许控制图像如何缩放。 + +# Input types +## Required +- images + - 输入的图像是节点将要处理的主要数据。它们对节点的运行至关重要,因为整个功能都围绕着将这些图像调整到期望的尺寸。 + - Comfy dtype: COMBO[numpy.ndarray] + - Python dtype: numpy.ndarray +- size + - 尺寸参数决定了输入图像将被缩放到的目标尺寸。它是决定输出外观和尺寸的关键因素。 + - Comfy dtype: int + - Python dtype: int +## Optional +- mode + - 模式参数影响缩放是基于图像的最大或最小维度。这影响了最终的宽高比和缩放方向。 + - Comfy dtype: boolean + - Python dtype: bool + +# Output types +- output_image + - 输出图像是节点处理的结果,其中输入图像已根据指定参数调整大小。它代表了节点功能的实际操作。 + - Comfy dtype: numpy.ndarray + - Python dtype: numpy.ndarray + +# Usage tips +- Infra type: CPU + +# Source code +``` +class imageScaleDownToSize(imageScaleDownBy): + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'size': ('INT', {'default': 512, 'min': 1, 'max': MAX_RESOLUTION, 'step': 1}), 'mode': ('BOOLEAN', {'default': True, 'label_on': 'max', 'label_off': 'min'})}} + RETURN_TYPES = ('IMAGE',) + CATEGORY = 'EasyUse/Image' + FUNCTION = 'image_scale_down_to_size' + + def image_scale_down_to_size(self, images, size, mode): + width = images.shape[2] + height = images.shape[1] + if mode: + scale_by = size / max(width, height) + else: + scale_by = size / min(width, height) + scale_by = min(scale_by, 1.0) + return self.image_scale_down_by(images, scale_by) +``` \ No newline at end of file diff --git a/docs/easy imageSize.md b/docs/easy imageSize.md new file mode 100644 index 0000000..75daf2c --- /dev/null +++ b/docs/easy imageSize.md @@ -0,0 +1,54 @@ +# Documentation +- Class name: imageSize +- Category: EasyUse/Image +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点旨在提取并提供图像的尺寸,重点关注宽度和高度作为关键属性。它在图像处理中作为一个基础工具,使得基于这些参数进行进一步的分析和操作成为可能。 + +# Input types +## Required +- image + - 图像参数是必需的,因为它是节点派生宽度和高度值的来源。没有这个输入,节点无法执行其主要功能。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray + +# Output types +- width_int + - width_int 输出代表输入图像的水平维度,为进一步的图像相关操作提供了关键信息。 + - Comfy dtype: INT + - Python dtype: int +- height_int + - height_int 输出表示输入图像的垂直维度,这对于理解图像的结构和后续的图像处理任务至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class imageSize: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',)}} + RETURN_TYPES = ('INT', 'INT') + RETURN_NAMES = ('width_int', 'height_int') + OUTPUT_NODE = True + FUNCTION = 'image_width_height' + CATEGORY = 'EasyUse/Image' + + def image_width_height(self, image): + (_, raw_H, raw_W, _) = image.shape + width = raw_W + height = raw_H + if width is not None and height is not None: + result = (width, height) + else: + result = (0, 0) + return {'ui': {'text': 'Width: ' + str(width) + ' , Height: ' + str(height)}, 'result': result} +``` \ No newline at end of file diff --git a/docs/easy imageSizeByLongerSide.md b/docs/easy imageSizeByLongerSide.md new file mode 100644 index 0000000..a2547e9 --- /dev/null +++ b/docs/easy imageSizeByLongerSide.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: imageSizeByLongerSide +- Category: EasyUse/Image +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点类根据较长的维度对图像进行分类,通过关注图像的较长边,为图像分析和处理提供了简化的方法。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它是节点操作的主要输入。它通过决定节点输出的基础,影响整个处理过程。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray + +# Output types +- resolution + - 分辨率输出提供图像较长边的长度,这对于后续的图像处理任务和分析至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class imageSizeByLongerSide: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',)}} + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('resolution',) + OUTPUT_NODE = True + FUNCTION = 'image_longer_side' + CATEGORY = 'EasyUse/Image' + + def image_longer_side(self, image): + (_, raw_H, raw_W, _) = image.shape + width = raw_W + height = raw_H + if width is not None and height is not None: + if width > height: + result = (width,) + else: + result = (height,) + else: + result = (0,) + return {'ui': {'text': str(result[0])}, 'result': result} +``` \ No newline at end of file diff --git a/docs/easy imageSizeBySide.md b/docs/easy imageSizeBySide.md new file mode 100644 index 0000000..a8b4980 --- /dev/null +++ b/docs/easy imageSizeBySide.md @@ -0,0 +1,57 @@ +# Documentation +- Class name: imageSizeBySide +- Category: EasyUse/Image +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点根据指定的边长标准对图像进行分类,并根据用户对图像较长或较短边的偏好,提供一个简化的分辨率值。 + +# Input types +## Required +- image + - 图像参数是必要的,因为它是节点操作的主要输入。它通过决定将被评估和与指定边进行比较的尺寸,从而影响整个处理过程。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- side + - 边参数决定了分辨率评估的标准,要么关注图像的最长边,要么关注最短边。它显著影响节点功能的结果。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- resolution + - 分辨率输出提供一个单一的整数值,代表基于边参数选择的图像维度。它是节点操作的核心结果,根据用户的偏好总结了图像的大小。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class imageSizeBySide: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image': ('IMAGE',), 'side': (['Longest', 'Shortest'],)}} + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('resolution',) + OUTPUT_NODE = True + FUNCTION = 'image_side' + CATEGORY = 'EasyUse/Image' + + def image_side(self, image, side): + (_, raw_H, raw_W, _) = image.shape + width = raw_W + height = raw_H + if width is not None and height is not None: + if side == 'Longest': + result = (width,) if width > height else (height,) + elif side == 'Shortest': + result = (width,) if width < height else (height,) + else: + result = (0,) + return {'ui': {'text': str(result[0])}, 'result': result} +``` \ No newline at end of file diff --git a/docs/easy imageSplitList.md b/docs/easy imageSplitList.md new file mode 100644 index 0000000..645cf93 --- /dev/null +++ b/docs/easy imageSplitList.md @@ -0,0 +1,55 @@ +# Documentation +- Class name: imageSplitList +- Category: EasyUse/Image +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点根据特定标准将图像列表分割成多个子集,提高了工作流中图像数据的组织和处理能力。 + +# Input types +## Required +- images + - 图像参数是必需的,因为它作为节点操作的主要输入,决定了后续的分割过程和输出结果的结构。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image.Image] + +# Output types +- images + - 输出代表重新组织的图像子集,对于工作流中进一步的分析或处理至关重要。 + - Comfy dtype: IMAGE + - Python dtype: Tuple[List[PIL.Image.Image], List[PIL.Image.Image], List[PIL.Image.Image]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class imageSplitList: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',)}} + RETURN_TYPES = ('IMAGE', 'IMAGE', 'IMAGE') + RETURN_NAMES = ('images', 'images', 'images') + FUNCTION = 'doit' + CATEGORY = 'EasyUse/Image' + + def doit(self, images): + length = len(images) + new_images = ([], [], []) + if length % 3 == 0: + for (index, img) in enumerate(images): + if index % 3 == 0: + new_images[0].append(img) + elif (index + 1) % 3 == 0: + new_images[2].append(img) + else: + new_images[1].append(img) + elif length % 2 == 0: + for (index, img) in enumerate(images): + if index % 2 == 0: + new_images[0].append(img) + else: + new_images[1].append(img) + return new_images +``` \ No newline at end of file diff --git a/docs/easy imageSwitch.md b/docs/easy imageSwitch.md new file mode 100644 index 0000000..56605cf --- /dev/null +++ b/docs/easy imageSwitch.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: imageSwitch +- Category: EasyUse/Logic/Switch +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +imageSwitch节点旨在根据布尔值在两张图像之间进行条件选择。它是图像处理工作流中的基本组件,用于在某些条件下做出决策。该节点通过评估布尔输入,然后返回相应的图像来操作。 + +# Input types +## Required +- image_a + - image_a参数是节点可能返回的第一张图像。它在节点的操作中起着关键作用,因为它是布尔输入将决定的两个选项之一。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] +- image_b + - image_b参数代表节点可能输出的第二张图像选项。它的重要性与image_a相当,因为它取决于布尔输入以被节点返回。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] +- boolean + - 布尔参数对于节点的决策过程至关重要。它直接影响着两张图像中的哪一张,image_a或image_b,将成为节点的输出。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- selected_image + - selected_image输出代表基于布尔输入选择的图像。它是节点功能的最终体现,包含了应用的条件逻辑的结果。 + - Comfy dtype: IMAGE + - Python dtype: Union[str, torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class imageSwitch: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'image_a': ('IMAGE',), 'image_b': ('IMAGE',), 'boolean': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'image_switch' + CATEGORY = 'EasyUse/Logic/Switch' + + def image_switch(self, image_a, image_b, boolean): + if boolean: + return (image_a,) + else: + return (image_b,) +``` \ No newline at end of file diff --git a/docs/easy imageToMask.md b/docs/easy imageToMask.md new file mode 100644 index 0000000..55a7171 --- /dev/null +++ b/docs/easy imageToMask.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: imageToMask +- Category: EasyUse/Image +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +imageToMask节点旨在从输入图像中提取单个颜色通道,并将其转换为灰度表示,可用于进一步的图像处理任务。 + +# Input types +## Required +- image + - 输入图像对节点的操作至关重要,因为它是提取所需颜色通道的来源。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +## Optional +- channel + - 通道参数决定了从图像中提取哪个颜色通道,影响灰度转换的最终结果。 + - Comfy dtype: COMBO['red', 'green', 'blue'] + - Python dtype: str + +# Output types +- MASK + - 输出是一个张量,代表从选定的颜色通道派生出的灰度图像,这对于后续的图像分析过程至关重要。 + - Comfy dtype: TENSOR + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class imageToMask: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'image': ('IMAGE',), 'channel': (['red', 'green', 'blue'],)}} + RETURN_TYPES = ('MASK',) + FUNCTION = 'convert' + CATEGORY = 'EasyUse/Image' + + def convert_to_single_channel(self, image, channel='red'): + image = image.convert('RGB') + if channel == 'red': + channel_img = image.split()[0].convert('L') + elif channel == 'green': + channel_img = image.split()[1].convert('L') + elif channel == 'blue': + channel_img = image.split()[2].convert('L') + else: + raise ValueError("Invalid channel option. Please choose 'red', 'green', or 'blue'.") + channel_img = Image.merge('RGB', (channel_img, channel_img, channel_img)) + return channel_img + + def convert(self, image, channel='red'): + image = self.convert_to_single_channel(tensor2pil(image), channel) + image = pil2tensor(image) + return (image.squeeze().mean(2),) +``` \ No newline at end of file diff --git a/docs/easy instantIDApply.md b/docs/easy instantIDApply.md new file mode 100644 index 0000000..1cdd7c1 --- /dev/null +++ b/docs/easy instantIDApply.md @@ -0,0 +1,98 @@ +# Documentation +- Class name: instantIDApply +- Category: EasyUse/Adapter +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +instantIDApply节点旨在简化将唯一标识符应用于给定图像或数据集的过程,便于集成各种模型和控制机制以实现期望的结果。 + +# Input types +## Required +- pipe + - pipe参数作为节点内部数据流动的主要通道,使得后续操作的协调和不同组件的集成成为可能。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- image + - image参数在提供视觉数据给节点方面至关重要,这对于系统内的处理和分析是必不可少的。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- instantid_file + - instantid_file参数对于系统内唯一标识符的识别和管理至关重要,确保数据的准确性和一致性。 + - Comfy dtype: COMBO[folder_paths.get_filename_list('instantid')] + - Python dtype: str +- insightface + - insightface参数在确定面部分析任务的计算后端方面起着重要作用,从而影响节点的性能和效率。 + - Comfy dtype: COMBO[['CPU', 'CUDA', 'ROCM']] + - Python dtype: str +- control_net_name + - control_net_name参数在指定要使用的控制网络方面至关重要,它塑造了节点的整体行为和输出。 + - Comfy dtype: COMBO[folder_paths.get_filename_list('controlnet')] + - Python dtype: str +- cn_strength + - cn_strength参数调节控制网络对结果的影响程度,是优化和微调节点性能的重要工具。 + - Comfy dtype: FLOAT + - Python dtype: float +- cn_soft_weights + - cn_soft_weights参数决定了控制网络影响的柔和程度,影响了节点调整的微妙性。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight + - weight参数对于平衡节点内不同组件的贡献至关重要,确保各种特性的和谐集成。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_at + - start_at参数定义了节点处理开始的初始点,为后续操作和结果奠定了基础。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_at + - end_at参数标记了节点处理结束的最终点,确定了节点功能的范围和限制。 + - Comfy dtype: FLOAT + - Python dtype: float +- noise + - noise参数在节点的操作中引入了随机性元素,有助于结果的多样性和创造性。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- pipe + - pipe输出是节点处理数据的全面表示,封装了结果并促进了系统内的进一步传输。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- model + - model输出提供了经过节点处理能力优化的输入模型的精炼和优化版本。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- positive + - positive输出是代表期望结果或特征的数据集,用于指导和通知后续流程。 + - Comfy dtype: CONDITIONING + - Python dtype: str +- negative + - negative输出包含代表非期望结果或特征的数据,作为未来操作中避免某些结果的参考。 + - Comfy dtype: CONDITIONING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class instantIDApply(instantID): + + def __init__(self): + super().__init__() + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'image': ('IMAGE',), 'instantid_file': (folder_paths.get_filename_list('instantid'),), 'insightface': (['CPU', 'CUDA', 'ROCM'],), 'control_net_name': (folder_paths.get_filename_list('controlnet'),), 'cn_strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'cn_soft_weights': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'weight': ('FLOAT', {'default': 0.8, 'min': 0.0, 'max': 5.0, 'step': 0.01}), 'start_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_at': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'noise': ('FLOAT', {'default': 0.35, 'min': 0.0, 'max': 1.0, 'step': 0.05})}, 'optional': {'image_kps': ('IMAGE',), 'mask': ('MASK',), 'control_net': ('CONTROL_NET',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE', 'MODEL', 'CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('pipe', 'model', 'positive', 'negative') + OUTPUT_NODE = True + FUNCTION = 'apply' + CATEGORY = 'EasyUse/Adapter' + + def apply(self, pipe, image, instantid_file, insightface, control_net_name, cn_strength, cn_soft_weights, weight, start_at, end_at, noise, image_kps=None, mask=None, control_net=None, prompt=None, extra_pnginfo=None, my_unique_id=None): + positive = pipe['positive'] + negative = pipe['negative'] + return self.run(pipe, image, instantid_file, insightface, control_net_name, cn_strength, cn_soft_weights, weight, start_at, end_at, noise, image_kps, mask, control_net, positive, negative, prompt, extra_pnginfo, my_unique_id) +``` \ No newline at end of file diff --git a/docs/easy instantIDApplyADV.md b/docs/easy instantIDApplyADV.md new file mode 100644 index 0000000..d06eb79 --- /dev/null +++ b/docs/easy instantIDApplyADV.md @@ -0,0 +1,98 @@ +# Documentation +- Class name: instantIDApplyAdvanced +- Category: EasyUse/Adapter +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点通过集成各种特性和控制功能,旨在提高输出图像处理的质量与特定性。它通过应用复杂的图像处理技术、控制网络和条件输入的组合来生成精细化的结果。 + +# Input types +## Required +- pipe + - pipe参数对于节点的操作至关重要,因为它提供了图像处理工作流的基础数据结构。它包含了包括正负条件数据在内的所有必要信息。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict +- image + - image参数对于节点来说至关重要,因为它是图像处理任务的主要输入。它直接影响输出及其应用转换的有效性。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- instantid_file + - instantid_file参数重要,因为它提供了与图像中主体身份相关的必需文件。它用于确保图像处理的准确性和相关性。 + - Comfy dtype: FILEPATH + - Python dtype: List[str] +- insightface + - insightface参数重要,因为它决定了用于面部识别和处理的后端。它影响节点准确识别和增强面部特征的能力。 + - Comfy dtype: STRING + - Python dtype: Union[str] +- control_net_name + - control_net_name参数至关重要,因为它指定了用于指导图像处理的控制网络。它确保输出符合期望的审美或主题约束。 + - Comfy dtype: FILEPATH + - Python dtype: List[str] +- cn_strength + - cn_strength参数调整控制网络对图像处理的影响。它在实现期望控制与处理图像自然外观之间的平衡方面起着关键作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- cn_soft_weights + - cn_soft_weights参数决定了控制网络应用控制的柔和度。它影响对图像所做的变化的微妙性,确保转换平滑且富有细节。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight + - weight参数影响图像处理效果的整体强度。它是控制图像增强或修改程度的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_at + - start_at参数定义了图像处理效果应用的起点。这对于确保变化逐步且受控地应用是很重要的。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_at + - end_at参数指定了图像处理效果完全应用的点。这对于确定转换的范围和程度至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- noise + - noise参数向图像处理中引入一定程度的随机性,有助于结果的多样性和不可预测性。这对于实现更自然、不那么统一的外观至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- pipe + - pipe输出是初始数据结构的修改版本,现在包含了图像处理的结果。它很重要,因为它封装了节点对整个工作流的贡献。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict +- model + - model输出代表了转换后的图像或图像处理模型的更新状态。它是节点主要功能和应用技术的效力的直接反映。 + - Comfy dtype: MODEL + - Python dtype: torch.Tensor +- positive + - positive输出是一组经过节点精炼或调整的条件数据。它对于向管道的后续阶段提供反馈很重要,增强了最终输出的连贯性和一致性。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict +- negative + - negative输出包含经过节点优化或过滤的条件数据。它通过确保排除不需要的元素,在塑造最终输出方面发挥着关键作用。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict + +# Usage tips +- Infra type: GPU + +# Source code +``` +class instantIDApplyAdvanced(instantID): + + def __init__(self): + super().__init__() + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'image': ('IMAGE',), 'instantid_file': (folder_paths.get_filename_list('instantid'),), 'insightface': (['CPU', 'CUDA', 'ROCM'],), 'control_net_name': (folder_paths.get_filename_list('controlnet'),), 'cn_strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'cn_soft_weights': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'weight': ('FLOAT', {'default': 0.8, 'min': 0.0, 'max': 5.0, 'step': 0.01}), 'start_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_at': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'noise': ('FLOAT', {'default': 0.35, 'min': 0.0, 'max': 1.0, 'step': 0.05})}, 'optional': {'image_kps': ('IMAGE',), 'mask': ('MASK',), 'control_net': ('CONTROL_NET',), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE', 'MODEL', 'CONDITIONING', 'CONDITIONING') + RETURN_NAMES = ('pipe', 'model', 'positive', 'negative') + OUTPUT_NODE = True + FUNCTION = 'apply_advanced' + CATEGORY = 'EasyUse/Adapter' + + def apply_advanced(self, pipe, image, instantid_file, insightface, control_net_name, cn_strength, cn_soft_weights, weight, start_at, end_at, noise, image_kps=None, mask=None, control_net=None, positive=None, negative=None, prompt=None, extra_pnginfo=None, my_unique_id=None): + positive = positive if positive is not None else pipe['positive'] + negative = negative if negative is not None else pipe['negative'] + return self.run(pipe, image, instantid_file, insightface, control_net_name, cn_strength, cn_soft_weights, weight, start_at, end_at, noise, image_kps, mask, control_net, positive, negative, prompt, extra_pnginfo, my_unique_id) +``` \ No newline at end of file diff --git a/docs/easy int.md b/docs/easy int.md new file mode 100644 index 0000000..3d95368 --- /dev/null +++ b/docs/easy int.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: Int +- Category: EasyUse/Logic/Type +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点通过将输入转换为整数来促进算术运算的执行,确保计算过程中的数据完整性和类型一致性。 + +# Input types +## Required +- value + - ‘value’参数至关重要,因为它是节点操作的主要输入。它通过确定将被转换为整数的数据来影响节点的处理。 + - Comfy dtype: INT + - Python dtype: Union[int, float, str, Decimal] + +# Output types +- int + - 输出‘int’代表整数转换过程的结果,这对于确保在后续操作中使用正确的数据类型至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class Int: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'value': ('INT', {'default': 0})}} + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('int',) + FUNCTION = 'execute' + CATEGORY = 'EasyUse/Logic/Type' + + def execute(self, value): + return (value,) +``` \ No newline at end of file diff --git a/docs/easy ipadapterApply.md b/docs/easy ipadapterApply.md new file mode 100644 index 0000000..507fac8 --- /dev/null +++ b/docs/easy ipadapterApply.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: ipadapterApply +- Category: EasyUse/Adapter +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +ipadapterApply节点旨在简化将各种图像处理适配器应用于输入图像的过程,使用模型和预设配置来实现期望的转换。它强调适应性和易用性,为用户使用不同的设置并实现最佳结果提供了结构化的接口,而无需深入了解复杂的模型特定细节。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了将用于对输入图像应用转换的基础图像处理模型。它是节点功能的基础,直接影响输出的质量和性质。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- image + - 图像输入是节点处理的对象。其内容和格式对于确定模型如何解释和转换它至关重要,最终塑造最终结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +- preset + - 预设参数决定了要应用的具体转换预设,指导模型根据选定的风格或效果处理图像。这是实现目标视觉效果的关键因素。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- lora_strength + - lora_strength参数调整风格转移过程的强度,允许微调视觉输出以符合用户的偏好。它在图像转换的艺术方面发挥着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- model + - 输出模型代表了在选择的预设和其他参数应用后修改的图像处理模型。它是节点处理的结晶,并作为进一步图像转换或分析的基础。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- tiles + - tiles输出提供了处理后图像的分段视图,允许详细检查并可能用于进一步的图像操作。它是输出的额外层,增强了节点在图像分析和编辑中的实用性。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image or torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ipadapterApply(ipadapter): + + def __init__(self): + super().__init__() + pass + + @classmethod + def INPUT_TYPES(cls): + presets = cls().presets + return {'required': {'model': ('MODEL',), 'image': ('IMAGE',), 'preset': (presets,), 'lora_strength': ('FLOAT', {'default': 0.6, 'min': 0, 'max': 1, 'step': 0.01}), 'provider': (['CPU', 'CUDA', 'ROCM', 'DirectML', 'OpenVINO', 'CoreML'],), 'weight': ('FLOAT', {'default': 1.0, 'min': -1, 'max': 3, 'step': 0.05}), 'weight_faceidv2': ('FLOAT', {'default': 1.0, 'min': -1, 'max': 5.0, 'step': 0.05}), 'start_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_at': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'cache_mode': (['insightface only', 'clip_vision only', 'all', 'none'], {'default': 'insightface only'}), 'use_tiled': ('BOOLEAN', {'default': False})}, 'optional': {'attn_mask': ('MASK',), 'optional_ipadapter': ('IPADAPTER',)}} + RETURN_TYPES = ('MODEL', 'IMAGE', 'MASK', 'IPADAPTER') + RETURN_NAMES = ('model', 'tiles', 'masks', 'ipadapter') + CATEGORY = 'EasyUse/Adapter' + FUNCTION = 'apply' + + def apply(self, model, image, preset, lora_strength, provider, weight, weight_faceidv2, start_at, end_at, cache_mode, use_tiled, attn_mask=None, optional_ipadapter=None): + (tiles, masks) = (image, [None]) + (model, ipadapter) = self.load_model(model, preset, lora_strength, provider, clip_vision=None, optional_ipadapter=optional_ipadapter, cache_mode=cache_mode) + if use_tiled and preset not in self.faceid_presets: + if 'IPAdapterTiled' not in ALL_NODE_CLASS_MAPPINGS: + self.error() + cls = ALL_NODE_CLASS_MAPPINGS['IPAdapterTiled'] + (model, tiles, masks) = cls().apply_tiled(model, ipadapter, image, weight, 'linear', start_at, end_at, sharpening=0.0, combine_embeds='concat', image_negative=None, attn_mask=attn_mask, clip_vision=None, embeds_scaling='V only') + elif preset in ['FACEID PLUS V2', 'FACEID PORTRAIT (style transfer)']: + if 'IPAdapterAdvanced' not in ALL_NODE_CLASS_MAPPINGS: + self.error() + cls = ALL_NODE_CLASS_MAPPINGS['IPAdapterAdvanced'] + (model,) = cls().apply_ipadapter(model, ipadapter, start_at=start_at, end_at=end_at, weight=weight, weight_type='linear', combine_embeds='concat', weight_faceidv2=weight_faceidv2, image=image, image_negative=None, clip_vision=None, attn_mask=attn_mask, insightface=None, embeds_scaling='V only') + else: + if 'IPAdapter' not in ALL_NODE_CLASS_MAPPINGS: + self.error() + cls = ALL_NODE_CLASS_MAPPINGS['IPAdapter'] + (model,) = cls().apply_ipadapter(model, ipadapter, image, weight, start_at, end_at, attn_mask) + return (model, tiles, masks, ipadapter) +``` \ No newline at end of file diff --git a/docs/easy ipadapterApplyADV.md b/docs/easy ipadapterApplyADV.md new file mode 100644 index 0000000..ee9b1a7 --- /dev/null +++ b/docs/easy ipadapterApplyADV.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: ipadapterApplyAdvanced +- Category: EasyUse/Adapter +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点促进了图像处理模型的高级应用,使用户能够无缝集成各种预设、权重和其他参数来完善和定制转换过程。它强调适应性和控制性,为用户实现复杂的图像操作提供了一个高级接口,而无需深入研究底层算法的细节。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了图像处理框架的核心。它决定了将在输入图像上执行的转换和分析类型,显著影响最终输出的质量和特征。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- image + - 图像参数是节点操作的主要输入。其内容和格式在决定模型如何处理和转换它方面至关重要,最终塑造图像操作的结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or torch.Tensor +- preset + - 预设参数允许用户选择预定义的设置,根据特定用例调整模型的行为。它通过提供优化的配置简化了过程,确保节点针对预期目的有效运行。 + - Comfy dtype: COMBO + - Python dtype: str +- lora_strength + - lora_strength参数微调模型对输入图像的适应性,允许进行细微调整,以提高最终输出的保真度和一致性。它在实现模型泛化和定制之间的平衡中起着关键作用。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- model + - 输出模型代表节点处理后输入模型的增强或改进版本。它包含了图像操作的结果,体现了节点在实现期望转换方面的有效性。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- tiles + - tiles输出由输入图像的分段部分组成,每部分都经过应用模型和参数的处理。它提供了在粒度级别上的图像操作的详细视图,展示了节点处理复杂转换的能力。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image or torch.Tensor] +- masks + - masks输出是一系列与处理过的tiles相对应的二进制矩阵。它在隔离和突出显示经过转换的图像特定区域方面发挥着重要作用,展示了节点在编辑过程中的精确度和控制力。 + - Comfy dtype: MASK + - Python dtype: List[PIL.Image or torch.Tensor] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class ipadapterApplyAdvanced(ipadapter): + + def __init__(self): + super().__init__() + pass + + @classmethod + def INPUT_TYPES(cls): + ipa_cls = cls() + presets = ipa_cls.presets + weight_types = ipa_cls.weight_types + return {'required': {'model': ('MODEL',), 'image': ('IMAGE',), 'preset': (presets,), 'lora_strength': ('FLOAT', {'default': 0.6, 'min': 0, 'max': 1, 'step': 0.01}), 'provider': (['CPU', 'CUDA', 'ROCM', 'DirectML', 'OpenVINO', 'CoreML'],), 'weight': ('FLOAT', {'default': 1.0, 'min': -1, 'max': 3, 'step': 0.05}), 'weight_faceidv2': ('FLOAT', {'default': 1.0, 'min': -1, 'max': 5.0, 'step': 0.05}), 'weight_type': (weight_types,), 'combine_embeds': (['concat', 'add', 'subtract', 'average', 'norm average'],), 'start_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_at': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'embeds_scaling': (['V only', 'K+V', 'K+V w/ C penalty', 'K+mean(V) w/ C penalty'],), 'cache_mode': (['insightface only', 'clip_vision only', 'all', 'none'], {'default': 'insightface only'}), 'use_tiled': ('BOOLEAN', {'default': False}), 'use_batch': ('BOOLEAN', {'default': False}), 'sharpening': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.05})}, 'optional': {'image_negative': ('IMAGE',), 'attn_mask': ('MASK',), 'clip_vision': ('CLIP_VISION',), 'optional_ipadapter': ('IPADAPTER',)}} + RETURN_TYPES = ('MODEL', 'IMAGE', 'MASK', 'IPADAPTER') + RETURN_NAMES = ('model', 'tiles', 'masks', 'ipadapter') + CATEGORY = 'EasyUse/Adapter' + FUNCTION = 'apply' + + def apply(self, model, image, preset, lora_strength, provider, weight, weight_faceidv2, weight_type, combine_embeds, start_at, end_at, embeds_scaling, cache_mode, use_tiled, use_batch, sharpening, image_negative=None, clip_vision=None, attn_mask=None, optional_ipadapter=None): + (tiles, masks) = (image, [None]) + (model, ipadapter) = self.load_model(model, preset, lora_strength, provider, clip_vision=clip_vision, optional_ipadapter=optional_ipadapter, cache_mode=cache_mode) + if use_tiled: + if use_batch: + if 'IPAdapterTiledBatch' not in ALL_NODE_CLASS_MAPPINGS: + self.error() + cls = ALL_NODE_CLASS_MAPPINGS['IPAdapterTiledBatch'] + else: + if 'IPAdapterTiled' not in ALL_NODE_CLASS_MAPPINGS: + self.error() + cls = ALL_NODE_CLASS_MAPPINGS['IPAdapterTiled'] + (model, tiles, masks) = cls().apply_tiled(model, ipadapter, image, weight, weight_type, start_at, end_at, sharpening=sharpening, combine_embeds=combine_embeds, image_negative=image_negative, attn_mask=attn_mask, clip_vision=clip_vision, embeds_scaling=embeds_scaling) + else: + if use_batch: + if 'IPAdapterBatch' not in ALL_NODE_CLASS_MAPPINGS: + self.error() + cls = ALL_NODE_CLASS_MAPPINGS['IPAdapterBatch'] + else: + if 'IPAdapterAdvanced' not in ALL_NODE_CLASS_MAPPINGS: + self.error() + cls = ALL_NODE_CLASS_MAPPINGS['IPAdapterAdvanced'] + (model,) = cls().apply_ipadapter(model, ipadapter, weight=weight, weight_type=weight_type, start_at=start_at, end_at=end_at, combine_embeds=combine_embeds, weight_faceidv2=weight_faceidv2, image=image, image_negative=image_negative, clip_vision=clip_vision, attn_mask=attn_mask, insightface=None, embeds_scaling=embeds_scaling) + return (model, tiles, masks, ipadapter) +``` \ No newline at end of file diff --git a/docs/easy ipadapterApplyEmbeds.md b/docs/easy ipadapterApplyEmbeds.md new file mode 100644 index 0000000..96c43b8 --- /dev/null +++ b/docs/easy ipadapterApplyEmbeds.md @@ -0,0 +1,86 @@ +# Documentation +- Class name: ipadapterApplyEmbeds +- Category: EasyUse/Adapter +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点便于将位置嵌入应用到模型中,增强模型处理输入数据中的空间信息的能力。它旨在通过整合额外的上下文线索来提升模型的性能,从而为输入数据提供更细致的表示。 + +# Input types +## Required +- model + - 模型参数是必不可少的,因为它是节点修改的核心组件。它代表了将要应用位置嵌入的机器学习模型,这对节点的运作和模型随后的性能至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- ipadapter + - ipadapter参数对于节点至关重要,因为它提供了模型与位置嵌入之间的必要接口。它确保嵌入被正确应用并集成到模型的架构中,影响节点的整体功能和输出。 + - Comfy dtype: IPADAPTER + - Python dtype: IPAdapter +- pos_embed + - pos_embed参数对节点的功能至关重要,它代表了将要应用到模型的位置嵌入。这些嵌入提供了模型理解和处理输入数据所需的空间信息。 + - Comfy dtype: EMBEDS + - Python dtype: torch.Tensor +- weight + - 权重参数影响模型中位置嵌入的重视程度。它是决定嵌入将如何影响模型输出的重要因子,因此,也影响了节点产生的结果质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- weight_type + - weight_type参数决定了应用于位置嵌入的权重类型,这对塑造模型对输入数据的响应具有重要意义。它影响了节点在修改模型行为方面的整体适应性和有效性。 + - Comfy dtype: COMBO[weight_types] + - Python dtype: str +- start_at + - start_at参数指定了位置嵌入应用的起始点,这对节点的运作至关重要。它决定了模型开始结合空间信息的初始上下文,影响了数据的整体解释和处理。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_at + - end_at参数定义了位置嵌入应用的终点,对节点的功能起着关键作用。它设置了模型将空间信息整合到何种程度的界限,从而影响了模型对输入数据理解的全面性。 + - Comfy dtype: FLOAT + - Python dtype: float +- embeds_scaling + - embeds_scaling参数调整嵌入的缩放比例,这对控制位置信息对模型的影响至关重要。它直接影响节点平衡嵌入与其他特征的贡献的能力,确保输入数据的最佳表示。 + - Comfy dtype: COMBO[ ['V only', 'K+V', 'K+V w/ C penalty', 'K+mean(V) w/ C penalty']] + - Python dtype: str +## Optional +- attn_mask + - 当提供attn_mask参数时,它帮助节点通过忽略无关信息来专注于输入数据的某些部分。这增强了模型专注于数据最重要方面的能力,从而产生更准确和相关的结果。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Output types +- model + - 模型输出代表了应用了位置嵌入的修改后的机器学习模型。它是节点的主要结果,展示了模型在处理空间信息方面的增强能力,并提供了对输入数据更详细的理解。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- ipadapter + - ipadapter输出是促进位置嵌入应用到模型的中间组件。它作为嵌入成功集成的证明,确保模型现在能够更好地处理空间信息。 + - Comfy dtype: IPADAPTER + - Python dtype: IPAdapter + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ipadapterApplyEmbeds(ipadapter): + + def __init__(self): + super().__init__() + pass + + @classmethod + def INPUT_TYPES(cls): + ipa_cls = cls() + weight_types = ipa_cls.weight_types + return {'required': {'model': ('MODEL',), 'ipadapter': ('IPADAPTER',), 'pos_embed': ('EMBEDS',), 'weight': ('FLOAT', {'default': 1.0, 'min': -1, 'max': 3, 'step': 0.05}), 'weight_type': (weight_types,), 'start_at': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_at': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'embeds_scaling': (['V only', 'K+V', 'K+V w/ C penalty', 'K+mean(V) w/ C penalty'],)}, 'optional': {'neg_embed': ('EMBEDS',), 'attn_mask': ('MASK',)}} + RETURN_TYPES = ('MODEL', 'IPADAPTER') + RETURN_NAMES = ('model', 'ipadapter') + CATEGORY = 'EasyUse/Adapter' + FUNCTION = 'apply' + + def apply(self, model, ipadapter, pos_embed, weight, weight_type, start_at, end_at, embeds_scaling, attn_mask=None, neg_embed=None): + if 'IPAdapterEmbeds' not in ALL_NODE_CLASS_MAPPINGS: + self.error() + cls = ALL_NODE_CLASS_MAPPINGS['IPAdapterEmbeds'] + (model,) = cls().apply_ipadapter(model, ipadapter, pos_embed, weight, weight_type, start_at, end_at, neg_embed=neg_embed, attn_mask=attn_mask, clip_vision=None, embeds_scaling=embeds_scaling) + return (model, ipadapter) +``` \ No newline at end of file diff --git a/docs/easy ipadapterApplyEncoder.md b/docs/easy ipadapterApplyEncoder.md new file mode 100644 index 0000000..c43b3fb --- /dev/null +++ b/docs/easy ipadapterApplyEncoder.md @@ -0,0 +1,127 @@ +# Documentation +- Class name: ipadapterApplyEncoder +- Category: EasyUse/Adapter +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +ipadapterApplyEncoder节点旨在为模型内的编码目的高效处理和适配图像数据。它便于整合多种图像输入和预设,应用选定的编码方法生成嵌入向量,可用于进一步分析或模型训练。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了编码过程的核心。它是将处理输入图像并根据选定的预设和编码方法生成嵌入向量的机器学习模型。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_management.Model +- image1 + - 图像输入对于节点执行其编码功能至关重要。它提供了模型将处理的原始数据,以提取有意义的特征并生成嵌入向量。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or numpy.ndarray +- preset + - 预设参数通过确定要使用的模型的特定设置和参数来影响编码过程。它根据预定义的配置调整节点的操作,以实现期望的结果。 + - Comfy dtype: COMBO + - Python dtype: str +- num_embeds + - 嵌入数量参数很重要,因为它决定了要生成的图像嵌入向量的数量。这直接影响编码过程的复杂性和深度。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- combine_method + - 合并方法参数决定如何聚合各个嵌入向量。通过应用诸如连接、加法或平均等操作,它可以显著改变结果嵌入向量。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- model + - 输出模型是输入模型的更新版本,现在配备了处理过的嵌入向量。它为后续操作或可用作下游任务的基础。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_management.Model +- ipadapter + - ipadapter输出是节点操作的编码部分,封装了处理过的嵌入向量。它是一个重要的中间结果,可以进一步分析或用于系统的其他部分。 + - Comfy dtype: IPADAPTER + - Python dtype: comfy_ipadapter.ipadapter.IPADAPTER +- pos_embed + - 正向嵌入代表了与期望结果一致的输入图像的编码特征。它们在指导模型的学习过程和改进其预测方面发挥着重要作用。 + - Comfy dtype: EMBEDS + - Python dtype: List[torch.Tensor] +- neg_embed + - 负向嵌入对应于不符合期望标准的输入图像。它们帮助模型区分相关和无关的特征,提高其做出准确判断的能力。 + - Comfy dtype: EMBEDS + - Python dtype: List[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ipadapterApplyEncoder(ipadapter): + + def __init__(self): + super().__init__() + pass + + @classmethod + def INPUT_TYPES(cls): + ipa_cls = cls() + normal_presets = ipa_cls.normal_presets + max_embeds_num = 3 + inputs = {'required': {'model': ('MODEL',), 'image1': ('IMAGE',), 'preset': (normal_presets,), 'num_embeds': ('INT', {'default': 2, 'min': 1, 'max': max_embeds_num})}, 'optional': {}} + for i in range(1, max_embeds_num + 1): + if i > 1: + inputs['optional'][f'image{i}'] = ('IMAGE',) + for i in range(1, max_embeds_num + 1): + inputs['optional'][f'mask{i}'] = ('MASK',) + inputs['optional'][f'weight{i}'] = ('FLOAT', {'default': 1.0, 'min': -1, 'max': 3, 'step': 0.05}) + inputs['optional']['combine_method'] = (['concat', 'add', 'subtract', 'average', 'norm average', 'max', 'min'],) + inputs['optional']['optional_ipadapter'] = ('IPADAPTER',) + inputs['optional']['pos_embeds'] = ('EMBEDS',) + inputs['optional']['neg_embeds'] = ('EMBEDS',) + return inputs + RETURN_TYPES = ('MODEL', 'IPADAPTER', 'EMBEDS', 'EMBEDS') + RETURN_NAMES = ('model', 'ipadapter', 'pos_embed', 'neg_embed') + CATEGORY = 'EasyUse/Adapter' + FUNCTION = 'apply' + + def batch(self, embeds, method): + if method == 'concat' and len(embeds) == 1: + return (embeds[0],) + embeds = [embed for embed in embeds if embed is not None] + embeds = torch.cat(embeds, dim=0) + if method == 'add': + embeds = torch.sum(embeds, dim=0).unsqueeze(0) + elif method == 'subtract': + embeds = embeds[0] - torch.mean(embeds[1:], dim=0) + embeds = embeds.unsqueeze(0) + elif method == 'average': + embeds = torch.mean(embeds, dim=0).unsqueeze(0) + elif method == 'norm average': + embeds = torch.mean(embeds / torch.norm(embeds, dim=0, keepdim=True), dim=0).unsqueeze(0) + elif method == 'max': + embeds = torch.max(embeds, dim=0).values.unsqueeze(0) + elif method == 'min': + embeds = torch.min(embeds, dim=0).values.unsqueeze(0) + return embeds + + def apply(self, **kwargs): + model = kwargs['model'] + preset = kwargs['preset'] + if 'optional_ipadapter' in kwargs: + ipadapter = kwargs['optional_ipadapter'] + else: + (model, ipadapter) = self.load_model(model, preset, 0, 'CPU', clip_vision=None, optional_ipadapter=None, cache_mode='none') + if 'IPAdapterEncoder' not in ALL_NODE_CLASS_MAPPINGS: + self.error() + encoder_cls = ALL_NODE_CLASS_MAPPINGS['IPAdapterEncoder'] + pos_embeds = kwargs['pos_embeds'] if 'pos_embeds' in kwargs else [] + neg_embeds = kwargs['neg_embeds'] if 'neg_embeds' in kwargs else [] + for i in range(1, kwargs['num_embeds'] + 1): + if f'image{i}' not in kwargs: + raise Exception(f'image{i} is required') + kwargs[f'mask{i}'] = kwargs[f'mask{i}'] if f'mask{i}' in kwargs else None + kwargs[f'weight{i}'] = kwargs[f'weight{i}'] if f'weight{i}' in kwargs else 1.0 + (pos, neg) = encoder_cls().encode(ipadapter, kwargs[f'image{i}'], kwargs[f'weight{i}'], kwargs[f'mask{i}'], clip_vision=None) + pos_embeds.append(pos) + neg_embeds.append(neg) + pos_embeds = self.batch(pos_embeds, kwargs['combine_method']) + neg_embeds = self.batch(neg_embeds, kwargs['combine_method']) + return (model, ipadapter, pos_embeds, neg_embeds) +``` \ No newline at end of file diff --git a/docs/easy isSDXL.md b/docs/easy isSDXL.md new file mode 100644 index 0000000..35a943a --- /dev/null +++ b/docs/easy isSDXL.md @@ -0,0 +1,49 @@ +# Documentation +- Class name: isSDXL +- Category: EasyUse/Logic +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点根据输入与特定模型的兼容性进行分类,确保在流程中正确应用模型。 + +# Input types +## Optional +- optional_pipe + - 该参数提供了包含条件阶段模型的流水线上下文,影响节点的决策过程。 + - Comfy dtype: COMBO[PIPE_LINE] + - Python dtype: Dict[str, Any] +- optional_clip + - 该参数为节点提供了一个替代输入,使其能够与clip模型一起工作,这对于某些操作至关重要。 + - Comfy dtype: CLIP + - Python dtype: Union[SDXLClipModel, SDXLRefinerClipModel, SDXLClipG] + +# Output types +- boolean + - 输出表示操作的成功与否,True表示兼容,False表示不匹配。 + - Comfy dtype: BOOLEAN + - Python dtype: Tuple[bool] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class isSDXL: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}, 'optional': {'optional_pipe': ('PIPE_LINE',), 'optional_clip': ('CLIP',)}} + RETURN_TYPES = ('BOOLEAN',) + RETURN_NAMES = ('boolean',) + FUNCTION = 'execute' + CATEGORY = 'EasyUse/Logic' + + def execute(self, optional_pipe=None, optional_clip=None): + if optional_pipe is None and optional_clip is None: + raise Exception(f'[ERROR] optional_pipe or optional_clip is missing') + clip = optional_clip if optional_clip is not None else optional_pipe['clip'] + if isinstance(clip.cond_stage_model, (SDXLClipModel, SDXLRefinerClipModel, SDXLClipG)): + return (True,) + else: + return (False,) +``` \ No newline at end of file diff --git a/docs/easy joinImageBatch.md b/docs/easy joinImageBatch.md new file mode 100644 index 0000000..ed5bc66 --- /dev/null +++ b/docs/easy joinImageBatch.md @@ -0,0 +1,51 @@ +# Documentation +- Class name: JoinImageBatch +- Category: EasyUse/Image +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点能够将多个图像合并成一个大图像,可以通过垂直或水平堆叠图像来实现。它旨在简化创建图像拼贴或结合视觉数据进行比较和分析的过程。 + +# Input types +## Required +- images + - images参数是提供要合并的图像批次的关键输入。它是一个包含图像批次的numpy数组,其中每个图像都是像素值的多维数组。 + - Comfy dtype: COMBO[numpy.ndarray] + - Python dtype: numpy.ndarray +## Optional +- mode + - mode参数决定了合并图像的方向,可以是'horizontal'或'vertical'。它影响了图像在最终合并图像中的排列方式。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- image + - 输出图像是输入图像批次合并的结果。它代表了一个单一的大图像,包含了所有水平或垂直排列的输入图像。 + - Comfy dtype: numpy.ndarray + - Python dtype: numpy.ndarray + +# Usage tips +- Infra type: CPU + +# Source code +``` +class JoinImageBatch: + """Turns an image batch into one big image.""" + + @classmethod + def INPUT_TYPES(s): + return {'required': {'images': ('IMAGE',), 'mode': (('horizontal', 'vertical'), {'default': 'horizontal'})}} + RETURN_TYPES = ('IMAGE',) + RETURN_NAMES = ('image',) + FUNCTION = 'join' + CATEGORY = 'EasyUse/Image' + + def join(self, images, mode): + (n, h, w, c) = images.shape + image = None + if mode == 'vertical': + image = images.reshape(1, n * h, w, c) + elif mode == 'horizontal': + image = torch.transpose(torch.transpose(images, 1, 2).reshape(1, n * w, h, c), 1, 2) + return (image,) +``` \ No newline at end of file diff --git a/docs/easy kSampler.md b/docs/easy kSampler.md new file mode 100644 index 0000000..2ffdc23 --- /dev/null +++ b/docs/easy kSampler.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: samplerSimple +- Category: EasyUse/Sampler +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点通过抽象复杂的配置,简化了采样过程,使用户能够以最少的输入生成图像。它专注于易用性和操作的简化,为图像生成任务提供了一个直接的接口。 + +# Input types +## Required +- pipe + - pipe参数作为节点操作的主要数据源和设置源。它至关重要,因为它包含了采样过程所需的上下文,包括模型信息和之前的处理步骤。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict +- image_output + - 该参数决定了生成的图像在处理后应如何处理。它在确定输出格式以及随后的动作(如显示、保存或发送图像)方面具有重要意义。 + - Comfy dtype: COMBO + - Python dtype: Union[str, None] +- link_id + - link_id参数对于在系统内部的不同组件之间建立连接至关重要,确保正确的数据流向适当的目的地。 + - Comfy dtype: INT + - Python dtype: int +- save_prefix + - 该参数定义了保存文件的前缀,这对于在可能包含大量输出的目录中组织和识别输出非常重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- model + - model参数提供了用于采样过程的神经网络架构。它是可选的,但可以显著影响生成图像的质量和特性。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- tile_size + - 当生成平铺图像时,tile_size参数是相关的,它影响输出是如何被分割和构建的。它在最终图像的效率和外观方面发挥作用。 + - Comfy dtype: INT + - Python dtype: int +- prompt + - prompt参数是一个文本描述,指导图像的生成。它对于将创作过程引向期望的结果非常重要。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - 该参数包含与PNG图像相关的额外信息,可用于完善图像生成过程。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict +- my_unique_id + - my_unique_id参数用于跟踪和管理节点操作的各个实例,确保每个操作可以被唯一识别和引用。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- pipe + - pipe输出是一个结构化的数据集合,包括采样过程后的更新模型、样本和其他相关信息。它对于将系统状态传递给后续节点或进行审查至关重要。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict +- image + - 图像输出包含生成的视觉内容,代表了节点操作的主要结果。它重要因为它展示了采样过程的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class samplerSimple: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'image_output': (['Hide', 'Preview', 'Save', 'Hide/Save', 'Sender', 'Sender/Save'], {'default': 'Preview'}), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'save_prefix': ('STRING', {'default': 'ComfyUI'})}, 'optional': {'model': ('MODEL',)}, 'hidden': {'tile_size': 'INT', 'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID', 'embeddingsList': (folder_paths.get_filename_list('embeddings'),)}} + RETURN_TYPES = ('PIPE_LINE', 'IMAGE') + RETURN_NAMES = ('pipe', 'image') + OUTPUT_NODE = True + FUNCTION = 'run' + CATEGORY = 'EasyUse/Sampler' + + def run(self, pipe, image_output, link_id, save_prefix, model=None, tile_size=None, prompt=None, extra_pnginfo=None, my_unique_id=None, force_full_denoise=False, disable_noise=False): + return samplerFull().run(pipe, None, None, None, None, None, image_output, link_id, save_prefix, None, model, None, None, None, None, None, None, None, prompt, extra_pnginfo, my_unique_id, force_full_denoise, disable_noise) +``` \ No newline at end of file diff --git a/docs/easy kSamplerDownscaleUnet.md b/docs/easy kSamplerDownscaleUnet.md new file mode 100644 index 0000000..f079e35 --- /dev/null +++ b/docs/easy kSamplerDownscaleUnet.md @@ -0,0 +1,97 @@ +# Documentation +- Class name: samplerSimpleDownscaleUnet +- Category: EasyUse/Sampler +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +samplerSimpleDownscaleUnet节点旨在流程中便于对图像进行缩小和放大。它通过选择适当的缩小方法并将其应用于输入图像,然后通过放大过程来增强图像质量。此节点特别适用于优化图像处理工作流程,确保图像在不损失细节或清晰度的情况下有效缩放。 + +# Input types +## Required +- pipe + - pipe参数是必需的,因为它代表包含要处理的图像数据的管道。正是通过此参数,节点访问图像并执行后续的缩放操作。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- downscale_mode + - downscale_mode参数决定了用于缩小图像的方法。它可以设置为'Auto'以自动选择或'Custom'以手动配置,这对于控制缩放过程至关重要。 + - Comfy dtype: COMBO[None, Auto, Custom] + - Python dtype: str +- block_number + - block_number参数指定了在缩小过程中要使用的块的数量。它是影响缩放操作效率和结果的重要因素。 + - Comfy dtype: INT + - Python dtype: int +- downscale_factor + - downscale_factor参数定义了用于减小图像大小的缩放因子。它在缩小过程中扮演重要角色,直接影响图像的最终尺寸。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_percent + - start_percent参数建立了缩放过程的起始百分比。它是一个重要的参数,有助于确定图像缩放的初始状态。 + - Comfy dtype: FLOAT + - Python dtype: float +- end_percent + - end_percent参数设置了缩放过程的结束百分比。它是控制缩放后图像最终外观的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- downscale_after_skip + - downscale_after_skip参数指示是否应在网络的跳跃连接之后进行缩小。这可能会影响缩小后图像的质量。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- downscale_method + - downscale_method参数选择用于缩小图像的算法。这是一个关键选择,可以显著影响结果图像的质量。 + - Comfy dtype: COMBO[bicubic, nearest-exact, bilinear, area, bislerp] + - Python dtype: str +- upscale_method + - upscale_method参数确定在图像缩小后用于放大图像的算法。它在放大阶段提高图像质量方面很重要。 + - Comfy dtype: COMBO[bicubic, nearest-exact, bilinear, area, bislerp] + - Python dtype: str +- image_output + - image_output参数指示如何处理生成的图像。它可以设置为隐藏图像、预览图像、保存图像或这些选项的组合,这对于管理节点的输出至关重要。 + - Comfy dtype: COMBO[Hide, Preview, Save, Hide/Save, Sender, Sender/Save] + - Python dtype: str +- link_id + - link_id参数用于将节点的输出与特定链接或流程关联。它在更大的工作流程中跟踪和管理节点的输出很重要。 + - Comfy dtype: INT + - Python dtype: int +- save_prefix + - save_prefix参数指定用于保存图像文件的前缀。它是一个有用的参数,用于组织和识别保存的图像文件。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- pipe + - pipe输出提供处理后的图像管道,其中包括缩放后的图像和其他相关数据。它很重要,因为它允许在后续节点中进一步处理或分析图像。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- image + - image输出代表节点处理后得到的缩放图像。它是视觉检查和进一步操作图像的关键输出。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class samplerSimpleDownscaleUnet: + + def __init__(self): + pass + upscale_methods = ['bicubic', 'nearest-exact', 'bilinear', 'area', 'bislerp'] + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',), 'downscale_mode': (['None', 'Auto', 'Custom'], {'default': 'Auto'}), 'block_number': ('INT', {'default': 3, 'min': 1, 'max': 32, 'step': 1}), 'downscale_factor': ('FLOAT', {'default': 2.0, 'min': 0.1, 'max': 9.0, 'step': 0.001}), 'start_percent': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'end_percent': ('FLOAT', {'default': 0.35, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'downscale_after_skip': ('BOOLEAN', {'default': True}), 'downscale_method': (s.upscale_methods,), 'upscale_method': (s.upscale_methods,), 'image_output': (['Hide', 'Preview', 'Save', 'Hide/Save', 'Sender', 'Sender/Save'], {'default': 'Preview'}), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'save_prefix': ('STRING', {'default': 'ComfyUI'})}, 'optional': {'model': ('MODEL',)}, 'hidden': {'tile_size': 'INT', 'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID', 'embeddingsList': (folder_paths.get_filename_list('embeddings'),)}} + RETURN_TYPES = ('PIPE_LINE', 'IMAGE') + RETURN_NAMES = ('pipe', 'image') + OUTPUT_NODE = True + FUNCTION = 'run' + CATEGORY = 'EasyUse/Sampler' + + def run(self, pipe, downscale_mode, block_number, downscale_factor, start_percent, end_percent, downscale_after_skip, downscale_method, upscale_method, image_output, link_id, save_prefix, model=None, tile_size=None, prompt=None, extra_pnginfo=None, my_unique_id=None, force_full_denoise=False, disable_noise=False): + downscale_options = None + if downscale_mode == 'Auto': + downscale_options = {'block_number': block_number, 'downscale_factor': None, 'start_percent': 0, 'end_percent': 0.35, 'downscale_after_skip': True, 'downscale_method': 'bicubic', 'upscale_method': 'bicubic'} + elif downscale_mode == 'Custom': + downscale_options = {'block_number': block_number, 'downscale_factor': downscale_factor, 'start_percent': start_percent, 'end_percent': end_percent, 'downscale_after_skip': downscale_after_skip, 'downscale_method': downscale_method, 'upscale_method': upscale_method} + return samplerFull().run(pipe, None, None, None, None, None, image_output, link_id, save_prefix, None, model, None, None, None, None, None, None, tile_size, prompt, extra_pnginfo, my_unique_id, force_full_denoise, disable_noise, downscale_options) +``` \ No newline at end of file diff --git a/docs/easy kSamplerInpainting.md b/docs/easy kSamplerInpainting.md new file mode 100644 index 0000000..87ec3b7 --- /dev/null +++ b/docs/easy kSamplerInpainting.md @@ -0,0 +1,92 @@ +# Documentation +- Class name: samplerSimpleInpainting +- Category: EasyUse/Sampler +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点通过使用VAE模型来填充图像中缺失或指定的区域,从而促进图像修复过程。它与各种条件选项集成,根据用户规范细化修复效果。 + +# Input types +## Required +- pipe + - pipe对象是必需的,因为它包含了进行图像修复过程所需的模型和图像。它作为节点的主要输入,指导整个操作。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- grow_mask_by + - 这个参数影响用于修复的遮罩的增长,决定了将受到影响的区域。它对于定义修复过程的范围至关重要。 + - Comfy dtype: INT + - Python dtype: int +- image_output + - image_output参数决定了图像修复过程后结果图像的处理方式。它指定是预览、保存还是结合这些操作,影响输出展示。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- additional + - 这个参数为修复过程提供了额外的条件选项,如微分扩散或模型条件。它增强了修复结果的灵活性和定制化。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- pipe + - 更新后的pipe对象包含修复后的图像以及过程中所做的修改。它作为主要输出,封装了图像修复操作的结果。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- image + - 图像输出代表修复后的结果,根据image_output参数,可能是预览、保存或两者兼有。它是图像修复过程的具体成果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class samplerSimpleInpainting: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'grow_mask_by': ('INT', {'default': 6, 'min': 0, 'max': 64, 'step': 1}), 'image_output': (['Hide', 'Preview', 'Save', 'Hide/Save', 'Sender', 'Sender/Save'], {'default': 'Preview'}), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'save_prefix': ('STRING', {'default': 'ComfyUI'}), 'additional': (['None', 'Differential Diffusion', 'Only InpaintModelConditioning'], {'default': 'None'})}, 'optional': {'model': ('MODEL',), 'mask': ('MASK',), 'patch': ('INPAINT_PATCH',)}, 'hidden': {'tile_size': 'INT', 'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID', 'embeddingsList': (folder_paths.get_filename_list('embeddings'),)}} + RETURN_TYPES = ('PIPE_LINE', 'IMAGE', 'VAE') + RETURN_NAMES = ('pipe', 'image', 'vae') + OUTPUT_NODE = True + FUNCTION = 'run' + CATEGORY = 'EasyUse/Sampler' + + def run(self, pipe, grow_mask_by, image_output, link_id, save_prefix, additional, model=None, mask=None, patch=None, tile_size=None, prompt=None, extra_pnginfo=None, my_unique_id=None, force_full_denoise=False, disable_noise=False): + fooocus_model = None + model = model if model is not None else pipe['model'] + latent = pipe['samples'] if 'samples' in pipe else None + positive = pipe['positive'] + negative = pipe['negative'] + pixels = pipe['images'] if pipe and 'images' in pipe else None + vae = pipe['vae'] if pipe and 'vae' in pipe else None + if 'noise_mask' in latent and mask is None: + mask = latent['noise_mask'] + else: + if pixels is None: + raise Exception('No Images found') + if vae is None: + raise Exception('No VAE found') + (latent,) = VAEEncodeForInpaint().encode(vae, pixels, mask, grow_mask_by) + mask = latent['noise_mask'] + if mask is not None: + if additional != 'None': + (positive, negative, latent) = InpaintModelConditioning().encode(positive, negative, pixels, vae, mask) + if additional == 'Differential Diffusion': + cls = ALL_NODE_CLASS_MAPPINGS['DifferentialDiffusion'] + if cls is not None: + (model,) = cls().apply(model) + else: + raise Exception('Differential Diffusion not found,please update comfyui') + if patch is not None: + worker = InpaintWorker(node_name='easy kSamplerInpainting') + (fooocus_model,) = worker.patch(model, latent, patch) + new_pipe = {**pipe, 'model': fooocus_model if fooocus_model is not None else model, 'positive': positive, 'negative': negative, 'vae': vae, 'samples': latent, 'loader_settings': pipe['loader_settings']} + else: + new_pipe = pipe + del pipe + return samplerFull().run(new_pipe, None, None, None, None, None, image_output, link_id, save_prefix, None, None, None, None, None, None, None, None, tile_size, prompt, extra_pnginfo, my_unique_id, force_full_denoise, disable_noise) +``` \ No newline at end of file diff --git a/docs/easy kSamplerLayerDiffusion.md b/docs/easy kSamplerLayerDiffusion.md new file mode 100644 index 0000000..0ee99b0 --- /dev/null +++ b/docs/easy kSamplerLayerDiffusion.md @@ -0,0 +1,87 @@ +# Documentation +- Class name: samplerSimpleLayerDiffusion +- Category: EasyUse/Sampler +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点简化了在分层扩散模型中执行采样过程,专注于基于提供的输入生成高质量的图像。它通过处理底层模型的复杂性来简化采样过程,使用户能够以最小的配置获得结果。 + +# Input types +## Required +- pipe + - ‘pipe’参数作为节点的主要输入通道,提供了采样过程所需的必要数据和设置。正确配置它确保了执行过程中信息和资源的正确流动。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- image_output + - ‘image_output’参数决定生成后的图像如何处理,选项从隐藏到保存或预览不等。该参数影响用户与输出的交互,决定了生成内容的可见性和保留情况。 + - Comfy dtype: COMBO + - Python dtype: str +- link_id + - ‘link_id’参数对于将节点的输出与其他系统组件链接至关重要,确保数据被正确路由并可供进一步处理或分析。 + - Comfy dtype: INT + - Python dtype: int +- save_prefix + - ‘save_prefix’参数为保存输出文件设置了前缀,这对于在文件系统中组织和识别保存的结果至关重要。正确使用此参数有助于维护一个有结构且易于访问的输出库。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- model + - ‘model’参数允许用户指定用于采样过程的特定模型。这对于确保在生成输出时利用所需模型的特性和能力至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- prompt + - ‘prompt’参数通过提供影响输出生成的文本描述或条件,在指导采样过程中起着关键作用。它塑造了生成图像的创意方向和主题内容。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - ‘extra_pnginfo’参数包含与PNG图像相关的额外信息,可能用于完善采样过程。它在根据特定图像要求提高输出的细节和质量方面发挥作用。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: str +- my_unique_id + - ‘my_unique_id’参数用于在系统中唯一标识操作,确保结果可以准确跟踪并与正确的用户或过程关联。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- pipe + - ‘pipe’输出提供了一个包含所有后续操作或分析所需的数据和设置的综合结构。它对于维护工作流的连续性和一致性至关重要。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- final_image + - ‘final_image’输出代表了采样过程的主要结果,展示了符合指定条件和创意指导生成的图像。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- original_image + - ‘original_image’输出提供了作为采样过程基础的初始输入图像或数据的引用。这对于比较和分析目的非常有用。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- alpha + - ‘alpha’输出包含生成图像的alpha通道数据,对于需要控制透明度或层叠图像的应用场景非常重要。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class samplerSimpleLayerDiffusion: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'image_output': (['Hide', 'Preview', 'Save', 'Hide/Save', 'Sender', 'Sender/Save'], {'default': 'Preview'}), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'save_prefix': ('STRING', {'default': 'ComfyUI'})}, 'optional': {'model': ('MODEL',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID', 'embeddingsList': (folder_paths.get_filename_list('embeddings'),)}} + RETURN_TYPES = ('PIPE_LINE', 'IMAGE', 'IMAGE', 'MASK') + RETURN_NAMES = ('pipe', 'final_image', 'original_image', 'alpha') + OUTPUT_NODE = True + OUTPUT_IS_LIST = (False, False, False, True) + FUNCTION = 'run' + CATEGORY = 'EasyUse/Sampler' + + def run(self, pipe, image_output='preview', link_id=0, save_prefix='ComfyUI', model=None, prompt=None, extra_pnginfo=None, my_unique_id=None, force_full_denoise=False, disable_noise=False): + result = samplerFull().run(pipe, None, None, None, None, None, image_output, link_id, save_prefix, None, model, None, None, None, None, None, None, None, prompt, extra_pnginfo, my_unique_id, force_full_denoise, disable_noise) + pipe = result['result'][0] if 'result' in result else None + return {'ui': result['ui'], 'result': (pipe, pipe['images'], pipe['samp_images'], pipe['alpha'])} +``` \ No newline at end of file diff --git a/docs/easy kSamplerSDTurbo.md b/docs/easy kSamplerSDTurbo.md new file mode 100644 index 0000000..ccf79dd --- /dev/null +++ b/docs/easy kSamplerSDTurbo.md @@ -0,0 +1,117 @@ +# Documentation +- Class name: samplerSDTurbo +- Category: EasyUse/Sampler +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +samplerSDTurbo节点旨在通过先进的采样技术高效生成高质量图像。它通过将输入数据经过一系列转换来操作,既优化速度又优化视觉保真度。该节点特别适用于需要从复杂数据集中生成图像的应用,提供了性能和输出质量之间的平衡。 + +# Input types +## Required +- pipe + - ‘pipe’参数是主要输入,为采样过程提供必要的数据和设置。它包括模型信息、正负例以及指导节点生成所需输出的其他相关配置。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- image_output + - ‘image_output’参数决定如何处理生成的图像。选项包括隐藏、预览、保存或它们的组合,允许在结果展示或存储方式上具有灵活性。 + - Comfy dtype: COMBO + - Python dtype: str +- link_id + - ‘link_id’参数对于将生成的图像与相应的请求或进程链接至关重要。它确保正确的图像与正确的任务关联,简化了工作流程并减少了错误的可能性。 + - Comfy dtype: INT + - Python dtype: int +- save_prefix + - ‘save_prefix’参数设置保存图像文件的前缀,这对于组织和识别输出至关重要。这个前缀作为图像的唯一标识符,有助于它们的检索和管理。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- model + - ‘model’参数允许指定在采样过程中使用的特定模型。它提供了一种根据特定要求或偏好调整节点操作的手段,增强了节点的多功能性和适应性。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- tile_size + - ‘tile_size’参数影响图像解码过程中的平铺策略,影响生成图像的分辨率和布局。这是一个可选设置,可以根据期望的输出特征进行调整。 + - Comfy dtype: INT + - Python dtype: Optional[int] +- prompt + - ‘prompt’参数提供了指导图像生成过程的文本描述。它是控制创意方向和确保输出与预期主题或概念一致的关键元素。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - ‘extra_pnginfo’参数包含与PNG图像相关的额外信息,可用于完善图像处理并提升最终结果。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, Any] +- my_unique_id + - ‘my_unique_id’参数是一个跟踪与图像生成相关的独特请求或进程的标识符。它在管理和关联输出与各自任务或工作流程方面起着重要作用。 + - Comfy dtype: UNIQUE_ID + - Python dtype: Union[str, int] + +# Output types +- pipe + - ‘pipe’输出是一个包含采样过程结果的综合结构,包括生成的图像和相关元数据。它作为系统不同组件之间传递数据的通道,促进进一步的处理或分析。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- image + - ‘image’输出包含生成的图像,这是采样过程的主要结果。这些图像已经准备好使用,代表了节点功能的顶点以及应用的采样技术的有效性。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image.Image] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class samplerSDTurbo: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'image_output': (['Hide', 'Preview', 'Save', 'Hide/Save', 'Sender', 'Sender/Save'], {'default': 'Preview'}), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'save_prefix': ('STRING', {'default': 'ComfyUI'})}, 'optional': {'model': ('MODEL',)}, 'hidden': {'tile_size': 'INT', 'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID', 'embeddingsList': (folder_paths.get_filename_list('embeddings'),)}} + RETURN_TYPES = ('PIPE_LINE', 'IMAGE') + RETURN_NAMES = ('pipe', 'image') + OUTPUT_NODE = True + FUNCTION = 'run' + CATEGORY = 'EasyUse/Sampler' + + def run(self, pipe, image_output, link_id, save_prefix, model=None, tile_size=None, prompt=None, extra_pnginfo=None, my_unique_id=None): + easyCache.update_loaded_objects(prompt) + my_unique_id = int(my_unique_id) + samp_model = pipe['model'] if model is None else model + samp_positive = pipe['positive'] + samp_negative = pipe['negative'] + samp_samples = pipe['samples'] + samp_vae = pipe['vae'] + samp_clip = pipe['clip'] + samp_seed = pipe['seed'] + samp_sampler = pipe['loader_settings']['sampler'] + sigmas = pipe['loader_settings']['sigmas'] + cfg = pipe['loader_settings']['cfg'] + steps = pipe['loader_settings']['steps'] + disable_noise = False + preview_latent = True + if image_output in ('Hide', 'Hide/Save'): + preview_latent = False + start_time = int(time.time() * 1000) + samp_samples = sampler.custom_ksampler(samp_model, samp_seed, steps, cfg, samp_sampler, sigmas, samp_positive, samp_negative, samp_samples, disable_noise, preview_latent) + end_time = int(time.time() * 1000) + latent = samp_samples['samples'] + if tile_size is not None: + samp_images = samp_vae.decode_tiled(latent, tile_x=tile_size // 8, tile_y=tile_size // 8) + else: + samp_images = samp_vae.decode(latent).cpu() + end_decode_time = int(time.time() * 1000) + spent_time = '扩散:' + str((end_time - start_time) / 1000) + '秒, 解码:' + str((end_decode_time - end_time) / 1000) + '秒' + easyCache.update_loaded_objects(prompt) + results = easySave(samp_images, save_prefix, image_output, prompt, extra_pnginfo) + sampler.update_value_by_id('results', my_unique_id, results) + new_pipe = {'model': samp_model, 'positive': samp_positive, 'negative': samp_negative, 'vae': samp_vae, 'clip': samp_clip, 'samples': samp_samples, 'images': samp_images, 'seed': samp_seed, 'loader_settings': {**pipe['loader_settings'], 'spent_time': spent_time}} + sampler.update_value_by_id('pipe_line', my_unique_id, new_pipe) + del pipe + if image_output in ('Hide', 'Hide/Save'): + return {'ui': {}, 'result': sampler.get_output(new_pipe)} + if image_output in ('Sender', 'Sender/Save'): + PromptServer.instance.send_sync('img-send', {'link_id': link_id, 'images': results}) + return {'ui': {'images': results}, 'result': sampler.get_output(new_pipe)} +``` \ No newline at end of file diff --git a/docs/easy kSamplerTiled.md b/docs/easy kSamplerTiled.md new file mode 100644 index 0000000..b28e8de --- /dev/null +++ b/docs/easy kSamplerTiled.md @@ -0,0 +1,80 @@ +# Documentation +- Class name: samplerSimpleTiled +- Category: EasyUse/Sampler +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点通过管理图像的平铺和根据用户偏好处理输出来简化采样过程。它抽象了采样的复杂性,使用户能够专注于创意输入,而无需担心采样过程的技术细节。 + +# Input types +## Required +- pipe + - 管道参数是必需的,因为它携带了整个流水线的状态,包括模型和数据信息,指导节点执行。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict +- tile_size + - 平铺大小参数决定了平铺输出的尺寸,这对于控制最终图像的分辨率和布局至关重要。 + - Comfy dtype: INT + - Python dtype: int +- image_output + - 此参数控制图像输出的处理方式,无论是预览、保存还是其他目的,影响节点的可用性和工作流程。 + - Comfy dtype: COMBO + - Python dtype: Union[str, None] +- link_id + - 链接ID参数对于建立系统不同部分之间的连接非常重要,确保正确的数据流和通信。 + - Comfy dtype: INT + - Python dtype: int +- save_prefix + - 此参数指定保存文件的前缀,对于在文件系统中组织和识别输出至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- model + - 当提供模型参数时,允许节点在采样过程中使用特定模型,影响生成图像的质量和特性。 + - Comfy dtype: MODEL + - Python dtype: Any +- prompt + - 提示参数用于指导生成过程,其内容显著影响采样的创意方向和结果。 + - Comfy dtype: PROMPT + - Python dtype: Any +- extra_pnginfo + - 此参数包含与PNG图像相关的额外信息,可以增强节点内此类图像的处理和处理。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Any +- my_unique_id + - 唯一ID参数用于跟踪和管理节点操作的各个实例,确保个性化和有针对性的执行。 + - Comfy dtype: UNIQUE_ID + - Python dtype: Any + +# Output types +- pipe + - 管道输出是一个综合性结构,包括更新后的流水线状态,反映了采样过程中所做的更改。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict +- image + - 图像输出代表采样的视觉结果,是节点生成的主要创意内容。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: CPU + +# Source code +``` +class samplerSimpleTiled: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'tile_size': ('INT', {'default': 512, 'min': 320, 'max': 4096, 'step': 64}), 'image_output': (['Hide', 'Preview', 'Save', 'Hide/Save', 'Sender', 'Sender/Save'], {'default': 'Preview'}), 'link_id': ('INT', {'default': 0, 'min': 0, 'max': sys.maxsize, 'step': 1}), 'save_prefix': ('STRING', {'default': 'ComfyUI'})}, 'optional': {'model': ('MODEL',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID', 'embeddingsList': (folder_paths.get_filename_list('embeddings'),)}} + RETURN_TYPES = ('PIPE_LINE', 'IMAGE') + RETURN_NAMES = ('pipe', 'image') + OUTPUT_NODE = True + FUNCTION = 'run' + CATEGORY = 'EasyUse/Sampler' + + def run(self, pipe, tile_size=512, image_output='preview', link_id=0, save_prefix='ComfyUI', model=None, prompt=None, extra_pnginfo=None, my_unique_id=None, force_full_denoise=False, disable_noise=False): + return samplerFull().run(pipe, None, None, None, None, None, image_output, link_id, save_prefix, None, model, None, None, None, None, None, None, tile_size, prompt, extra_pnginfo, my_unique_id, force_full_denoise, disable_noise) +``` \ No newline at end of file diff --git a/docs/easy latentCompositeMaskedWithCond.md b/docs/easy latentCompositeMaskedWithCond.md new file mode 100644 index 0000000..0743883 --- /dev/null +++ b/docs/easy latentCompositeMaskedWithCond.md @@ -0,0 +1,111 @@ +# Documentation +- Class name: latentCompositeMaskedWithCond +- Category: EasyUse/Latent +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点整合了将文本输入与潜在表示结合以生成有条件输出的过程。它根据文本条件遮蔽和复合潜在空间,使得能够创造出定制化的结果。 + +# Input types +## Required +- pipe + - pipe参数作为节点操作的主要数据和设置源。它对于节点的正常运行至关重要,因为它包含了节点执行任务和生成所需输出所需的必要信息。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- text_combine + - 该参数保存与潜在数据结合的文本元素列表。它在塑造最终输出中起着重要作用,因为它直接影响调节过程。 + - Comfy dtype: LIST + - Python dtype: List[str] +- source_latent + - source_latent参数对于节点的操作至关重要,因为它提供了将被复合和调节的初始潜在表示。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- source_mask + - 该参数对于遮蔽过程至关重要,因为它决定了潜在数据的调节方式。它通过控制潜在空间中被修改的区域来影响最终输出。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- destination_mask + - destination_mask参数在定义将被更新的潜在空间区域方面起着关键作用。它与源遮蔽罩协同工作,以完善最终复合的潜在表示。 + - Comfy dtype: MASK + - Python dtype: torch.Tensor +- text_combine_mode + - 该参数决定了文本如何与现有提示结合,影响调节过程和最终输出。它对于控制节点处理文本输入的行为至关重要。 + - Comfy dtype: COMBO[add, replace, cover] + - Python dtype: str +## Optional +- replace_text + - replace_text参数允许修改提示中的特定文本。它对于在不改变整个提示结构的况下定制调节过程非常重要。 + - Comfy dtype: STRING + - Python dtype: str +- prompt + - prompt参数提供了额外的文本上下文,可以用来进一步细化调节过程。它对于为最终输出添加特定的细微差别非常有益。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - 该参数包含可利用来增强调节过程的补充图像相关信息。它特别适用于将视觉元素融入最终输出。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Any +- my_unique_id + - my_unique_id参数用于跟踪和识别节点操作的特定实例。它对于保持过程的完整性和确保准确结果非常重要。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- pipe + - pipe输出是输入pipe的更新版本,现在包含最新的样本和修改后的加载器设置。它很重要,因为它代表了流水线的进步和节点处理的整合。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- latent + - 潜在输出代表复合和调节后的潜在空间。它很关键,因为它是节点操作的直接结果,并作为进一步处理或分析的基础。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- conditioning + - 调节输出是一组已应用于潜在空间的条件。它对于理解节点如何处理输入以及确保最终输出中存在所需特征非常重要。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Tuple[torch.Tensor, Dict[str, Any]]] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class latentCompositeMaskedWithCond: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',), 'text_combine': ('LIST',), 'source_latent': ('LATENT',), 'source_mask': ('MASK',), 'destination_mask': ('MASK',), 'text_combine_mode': (['add', 'replace', 'cover'], {'default': 'add'}), 'replace_text': ('STRING', {'default': ''})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + OUTPUT_IS_LIST = (False, False, True) + RETURN_TYPES = ('PIPE_LINE', 'LATENT', 'CONDITIONING') + RETURN_NAMES = ('pipe', 'latent', 'conditioning') + FUNCTION = 'run' + OUTPUT_NODE = True + CATEGORY = 'EasyUse/Latent' + + def run(self, pipe, text_combine, source_latent, source_mask, destination_mask, text_combine_mode, replace_text, prompt=None, extra_pnginfo=None, my_unique_id=None): + positive = None + clip = pipe['clip'] + destination_latent = pipe['samples'] + conds = [] + for text in text_combine: + if text_combine_mode == 'cover': + positive = text + elif text_combine_mode == 'replace' and replace_text != '': + positive = pipe['loader_settings']['positive'].replace(replace_text, text) + else: + positive = pipe['loader_settings']['positive'] + ',' + text + positive_token_normalization = pipe['loader_settings']['positive_token_normalization'] + positive_weight_interpretation = pipe['loader_settings']['positive_weight_interpretation'] + a1111_prompt_style = pipe['loader_settings']['a1111_prompt_style'] + positive_cond = pipe['positive'] + log_node_warn('正在处理提示词编码...') + steps = pipe['loader_settings']['steps'] if 'steps' in pipe['loader_settings'] else 1 + positive_embeddings_final = advanced_encode(clip, positive, positive_token_normalization, positive_weight_interpretation, w_max=1.0, apply_to_pooled='enable', a1111_prompt_style=a1111_prompt_style, steps=steps) + (cond_1,) = ConditioningSetMask().append(positive_cond, source_mask, 'default', 1) + (cond_2,) = ConditioningSetMask().append(positive_embeddings_final, destination_mask, 'default', 1) + positive_cond = cond_1 + cond_2 + conds.append(positive_cond) + (samples,) = LatentCompositeMasked().composite(destination_latent, source_latent, 0, 0, False) + new_pipe = {**pipe, 'samples': samples, 'loader_settings': {**pipe['loader_settings'], 'positive': positive}} + del pipe + return (new_pipe, samples, conds) +``` \ No newline at end of file diff --git a/docs/easy latentNoisy.md b/docs/easy latentNoisy.md new file mode 100644 index 0000000..1abca02 --- /dev/null +++ b/docs/easy latentNoisy.md @@ -0,0 +1,115 @@ +# Documentation +- Class name: latentNoisy +- Category: EasyUse/Latent +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +latentNoisy类便于生成噪声潜在样本,这对于各种生成模型至关重要。它管理创建噪声并将其应用于模型的潜在空间的过程,允许操纵输出的随机性。这个类旨在与现有管道无缝集成,增强生成过程的整体灵活性和控制力。 + +# Input types +## Required +- sampler_name + - sampler_name参数对于定义在潜在空间采样过程中使用的采样器类型至关重要。它决定了算法方法和行为,从而影响生成样本的质量和特性。 + - Comfy dtype: COMBO[comfy.samplers.KSampler.SAMPLERS] + - Python dtype: str +- scheduler + - scheduler参数对于在采样过程中控制学习率或其他超参数至关重要。它有助于微调模型的性能并取得更好的结果。 + - Comfy dtype: COMBO[comfy.samplers.KSampler.SCHEDULERS] + - Python dtype: str +- steps + - steps参数定义了采样过程的迭代次数或持续时间。它是决定生成样本的收敛性和稳定性的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- start_at_step + - start_at_step参数指定了采样过程的起始点。它对于控制流水线内操作的时机和顺序非常重要。 + - Comfy dtype: INT + - Python dtype: int +- end_at_step + - end_at_step参数标记了采样过程的结束。它与start_at_step参数共同作用,确定了采样的步骤范围。 + - Comfy dtype: INT + - Python dtype: int +- source + - source参数决定计算应该在CPU还是GPU上执行。它显著影响采样过程的性能和效率。 + - Comfy dtype: COMBO[['CPU', 'GPU']] + - Python dtype: str +- seed + - seed参数对于确保采样过程的可重复性和一致性至关重要。它初始化随机数生成器,影响噪声的生成。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- pipe + - pipe参数是一个可选输入,为采样过程提供额外的上下文和设置。它可以包括有关模型、加载器设置和其他特定于流水线的详细信息。 + - Comfy dtype: PIPE_LINE + - Python dtype: dict +- optional_model + - optional_model参数允许指定在采样过程中使用的模型。当需要将自定义模型集成到流水线中时,它特别有用。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- optional_latent + - optional_latent参数提供了一种供应预先生成的潜在样本的方式。这对于进一步处理或分析非常有益处,无需从头开始重新生成样本。 + - Comfy dtype: LATENT + - Python dtype: dict + +# Output types +- pipe + - pipe输出包含更新后的流水线信息,包括生成的噪声样本。它是整个过程的关键部分,因为它允许根据结果继续或终止流水线。 + - Comfy dtype: PIPE_LINE + - Python dtype: dict +- latent + - latent输出包含已生成的噪声潜在样本。这些样本对于生成模型工作流中的进一步处理或分析至关重要。 + - Comfy dtype: LATENT + - Python dtype: dict +- sigma + - sigma输出表示采样过程开始和结束步骤之间噪声水平的差异。这是一个重要的值,可用于调整后续操作中的噪声水平。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Usage tips +- Infra type: GPU + +# Source code +``` +class latentNoisy: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'steps': ('INT', {'default': 10000, 'min': 0, 'max': 10000}), 'start_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'end_at_step': ('INT', {'default': 10000, 'min': 1, 'max': 10000}), 'source': (['CPU', 'GPU'],), 'seed': ('INT', {'default': 0, 'min': 0, 'max': 18446744073709551615})}, 'optional': {'pipe': ('PIPE_LINE',), 'optional_model': ('MODEL',), 'optional_latent': ('LATENT',)}} + RETURN_TYPES = ('PIPE_LINE', 'LATENT', 'FLOAT') + RETURN_NAMES = ('pipe', 'latent', 'sigma') + FUNCTION = 'run' + CATEGORY = 'EasyUse/Latent' + + def run(self, sampler_name, scheduler, steps, start_at_step, end_at_step, source, seed, pipe=None, optional_model=None, optional_latent=None): + model = optional_model if optional_model is not None else pipe['model'] + batch_size = pipe['loader_settings']['batch_size'] + empty_latent_height = pipe['loader_settings']['empty_latent_height'] + empty_latent_width = pipe['loader_settings']['empty_latent_width'] + if optional_latent is not None: + samples = optional_latent + else: + torch.manual_seed(seed) + if source == 'CPU': + device = 'cpu' + else: + device = comfy.model_management.get_torch_device() + noise = torch.randn((batch_size, 4, empty_latent_height // 8, empty_latent_width // 8), dtype=torch.float32, device=device).cpu() + samples = {'samples': noise} + device = comfy.model_management.get_torch_device() + end_at_step = min(steps, end_at_step) + start_at_step = min(start_at_step, end_at_step) + comfy.model_management.load_model_gpu(model) + model_patcher = comfy.model_patcher.ModelPatcher(model.model, load_device=device, offload_device=comfy.model_management.unet_offload_device()) + sampler = comfy.samplers.KSampler(model_patcher, steps=steps, device=device, sampler=sampler_name, scheduler=scheduler, denoise=1.0, model_options=model.model_options) + sigmas = sampler.sigmas + sigma = sigmas[start_at_step] - sigmas[end_at_step] + sigma /= model.model.latent_format.scale_factor + sigma = sigma.cpu().numpy() + samples_out = samples.copy() + s1 = samples['samples'] + samples_out['samples'] = s1 * sigma + if pipe is None: + pipe = {} + new_pipe = {**pipe, 'samples': samples_out} + del pipe + return (new_pipe, samples_out, sigma) +``` \ No newline at end of file diff --git a/docs/easy loraStack.md b/docs/easy loraStack.md new file mode 100644 index 0000000..861a33c --- /dev/null +++ b/docs/easy loraStack.md @@ -0,0 +1,94 @@ +# Documentation +- Class name: loraStackLoader +- Category: EasyUse/Loaders +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +loraStackLoader节点旨在简化加载和配置Lora堆栈的过程,这对于微调和提高神经网络模型的性能至关重要。它通过提供一种结构化的方式来指定多个Lora层的名称、强度和其他相关参数,简化了管理多个Lora层的复杂性。 + +# Input types +## Required +- toggle + - toggle参数对于决定节点是否应该执行其加载过程至关重要。当设置为True时,节点将执行加载指定的Lora堆栈;否则,它将不执行任何操作就返回。 + - Comfy dtype: BOOL + - Python dtype: bool +- mode + - mode参数决定了Lora堆栈配置的复杂性级别。它允许用户选择简单或高级设置,影响后续参数的解释和应用方式。 + - Comfy dtype: STR + - Python dtype: str +- num_loras + - num_loras参数指定要加载的Lora层的数量。它通过确定将处理多少个Lora配置直接影响节点的操作。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- optional_lora_stack + - optional_lora_stack参数提供了一种向节点提供现有Lora堆栈的方式。这对于扩展或修改已经配置的堆栈而无需从头开始非常有用。 + - Comfy dtype: LORA_STACK + - Python dtype: List[Tuple[str, float, float]] +- lora_{i}_name + - lora_{i}_name参数允许用户指定位置{i}处的Lora层的名称。这对于识别和加载正确的Lora配置非常重要。 + - Comfy dtype: STR + - Python dtype: str +- lora_{i}_strength + - lora_{i}_strength参数设置位置{i}处的Lora层的强度。这是Lora层在模型中的影响权重的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- lora_{i}_model_strength + - lora_{i}_model_strength参数在高级模式下适用,为位置{i}处的Lora层设置特定于模型的强度。它用于微调Lora对模型输出的影响。 + - Comfy dtype: FLOAT + - Python dtype: float +- lora_{i}_clip_strength + - lora_{i}_clip_strength参数也在高级模式下使用,它决定了位置{i}处的Lora层与CLIP模型的交互强度。这对于控制基于文本的指导在模型处理中的整合至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- lora_stack + - lora_stack输出是由节点处理的Lora配置的集合。它代表了准备应用于神经网络模型的最终Lora层堆栈。 + - Comfy dtype: LORA_STACK + - Python dtype: List[Tuple[str, float, float]] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class loraStackLoader: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + max_lora_num = 10 + inputs = {'required': {'toggle': ([True, False],), 'mode': (['simple', 'advanced'],), 'num_loras': ('INT', {'default': 1, 'min': 0, 'max': max_lora_num})}, 'optional': {'optional_lora_stack': ('LORA_STACK',)}} + for i in range(1, max_lora_num + 1): + inputs['optional'][f'lora_{i}_name'] = (['None'] + folder_paths.get_filename_list('loras'), {'default': 'None'}) + inputs['optional'][f'lora_{i}_strength'] = ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}) + inputs['optional'][f'lora_{i}_model_strength'] = ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}) + inputs['optional'][f'lora_{i}_clip_strength'] = ('FLOAT', {'default': 1.0, 'min': -10.0, 'max': 10.0, 'step': 0.01}) + return inputs + RETURN_TYPES = ('LORA_STACK',) + RETURN_NAMES = ('lora_stack',) + FUNCTION = 'stack' + CATEGORY = 'EasyUse/Loaders' + + def stack(self, toggle, mode, num_loras, lora_stack=None, **kwargs): + if toggle in [False, None, 'False'] or not kwargs: + return (None,) + loras = [] + if lora_stack is not None: + loras.extend([l for l in lora_stack if l[0] != 'None']) + for i in range(1, num_loras + 1): + lora_name = kwargs.get(f'lora_{i}_name') + if not lora_name or lora_name == 'None': + continue + if mode == 'simple': + lora_strength = float(kwargs.get(f'lora_{i}_strength')) + loras.append((lora_name, lora_strength, lora_strength)) + elif mode == 'advanced': + model_strength = float(kwargs.get(f'lora_{i}_model_strength')) + clip_strength = float(kwargs.get(f'lora_{i}_clip_strength')) + loras.append((lora_name, model_strength, clip_strength)) + return (loras,) +``` \ No newline at end of file diff --git a/docs/easy negative.md b/docs/easy negative.md new file mode 100644 index 0000000..2ae33d0 --- /dev/null +++ b/docs/easy negative.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: negativePrompt +- Category: EasyUse/Prompt +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +negativePrompt节点旨在系统内管理和处理负面提示。它通过排除某些不需要的元素或特征,在提炼输出方面发挥关键作用。该节点的功能以否定概念为中心,通过积极指定应避免的内容,旨在提高结果的精确度和相关性。 + +# Input types +## Required +- negative + - ‘negative’参数对于定义应从最终输出中省略哪些方面至关重要。它允许用户指定他们希望排除的元素,从而引导系统生成更针对性和精细化的结果。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- negative + - 输出‘negative’代表已用于精炼系统输出的处理过的负面提示。它标志着用户指定的排除项已成功应用,确保最终结果符合所需的标准。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class negativePrompt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'negative': ('STRING', {'default': '', 'multiline': True, 'placeholder': 'Negative'})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('negative',) + FUNCTION = 'main' + CATEGORY = 'EasyUse/Prompt' + + @staticmethod + def main(negative): + return (negative,) +``` \ No newline at end of file diff --git a/docs/easy pipeBatchIndex.md b/docs/easy pipeBatchIndex.md new file mode 100644 index 0000000..e284039 --- /dev/null +++ b/docs/easy pipeBatchIndex.md @@ -0,0 +1,56 @@ +# Documentation +- Class name: pipeBatchIndex +- Category: EasyUse/Pipe +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +pipeBatchIndex节点便于在流水线中操作批次数据,能够选择和处理特定的批次索引。它通过允许有针对性的数据处理,对于优化批量处理任务至关重要,从而增强了工作流程。 + +# Input types +## Required +- pipe + - ‘pipe’参数代表正在处理的数据流水线。它包含进行批次操作所需的样本和其他相关信息,是实现目标数据处理不可或缺的。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- batch_index + - ‘batch_index’参数指定了流水线中要处理的批次索引。它很重要,因为它指导节点定位到正确的批次进行处理。 + - Comfy dtype: INT + - Python dtype: int +- length + - ‘length’参数决定了要从批次中处理的元素数量。它影响了操作的范围,对于管理被操作数据的规模至关重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- my_unique_id + - ‘my_unique_id’参数是一个可选的标识符,可用于跟踪节点执行的特定实例。它有助于在复杂工作流中区分节点的不同运行。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- pipe + - ‘pipe’输出是修改后的数据流水线,现在包含了处理过的样本批次。它是关键的输出,因为它携带了批次操作的结果,并将其输入到流水线的后续阶段。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class pipeBatchIndex: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',), 'batch_index': ('INT', {'default': 0, 'min': 0, 'max': 63}), 'length': ('INT', {'default': 1, 'min': 1, 'max': 64})}, 'hidden': {'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('pipe',) + FUNCTION = 'doit' + CATEGORY = 'EasyUse/Pipe' + + def doit(self, pipe, batch_index, length, my_unique_id=None): + samples = pipe['samples'] + (new_samples,) = LatentFromBatch().frombatch(samples, batch_index, length) + new_pipe = {**pipe, 'samples': new_samples} + del pipe + return (new_pipe,) +``` \ No newline at end of file diff --git a/docs/easy pipeEdit.md b/docs/easy pipeEdit.md new file mode 100644 index 0000000..a57a939 --- /dev/null +++ b/docs/easy pipeEdit.md @@ -0,0 +1,107 @@ +# Documentation +- Class name: pipeEdit +- Category: EasyUse/Pipe +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +pipeEdit节点是一个全面的精炼和调整处理流程中元素的工具。它旨在简化条件的修改、模型的集成以及各种数据类型的处理,确保复杂作的工作流程无缝进行。 + +# Input types +## Required +- clip_skip + - 此参数决定流水线中CLIP模型的跳过级别,对控制CLIP对整体处理的影响至关重要。 + - Comfy dtype: INT + - Python dtype: int +- conditioning_mode + - 调节模式定义了在流水线中应用和组合各种条件的策略,影响最终输出的连贯性和与预期方向的一致性。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- optional_positive + - 正面调节文本对于引导生成过程朝着期望的结果至关重要。它塑造了模型输出的创作方向。 + - Comfy dtype: STRING + - Python dtype: str +- positive_token_normalization + - 此参数集确定了正面调节文本中的标记是如何规范化的,这显著影响生成内容的精确性和相关性。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- pipe + - 更新后的流水线对象封装了pipeEdit节点所做的所有修改和配置,作为后续处理步骤的支柱。 + - Comfy dtype: PIPE_LINE + - Python dtype: dict +- model + - 模型参数代表流水线中使用的神经网络模型,更新确保特定任务的最佳性能和定制输出。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: GPU + +# Source code +``` +class pipeEdit: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'clip_skip': ('INT', {'default': -1, 'min': -24, 'max': 0, 'step': 1}), 'optional_positive': ('STRING', {'default': '', 'multiline': True}), 'positive_token_normalization': (['none', 'mean', 'length', 'length+mean'],), 'positive_weight_interpretation': (['comfy', 'A1111', 'comfy++', 'compel', 'fixed attention'],), 'optional_negative': ('STRING', {'default': '', 'multiline': True}), 'negative_token_normalization': (['none', 'mean', 'length', 'length+mean'],), 'negative_weight_interpretation': (['comfy', 'A1111', 'comfy++', 'compel', 'fixed attention'],), 'a1111_prompt_style': ('BOOLEAN', {'default': False}), 'conditioning_mode': (['replace', 'concat', 'combine', 'average', 'timestep'], {'default': 'replace'}), 'average_strength': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'old_cond_start': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'old_cond_end': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'new_cond_start': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 1.0, 'step': 0.001}), 'new_cond_end': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.001})}, 'optional': {'pipe': ('PIPE_LINE',), 'model': ('MODEL',), 'pos': ('CONDITIONING',), 'neg': ('CONDITIONING',), 'latent': ('LATENT',), 'vae': ('VAE',), 'clip': ('CLIP',), 'image': ('IMAGE',)}, 'hidden': {'my_unique_id': 'UNIQUE_ID', 'prompt': 'PROMPT'}} + RETURN_TYPES = ('PIPE_LINE', 'MODEL', 'CONDITIONING', 'CONDITIONING', 'LATENT', 'VAE', 'CLIP', 'IMAGE') + RETURN_NAMES = ('pipe', 'model', 'pos', 'neg', 'latent', 'vae', 'clip', 'image') + FUNCTION = 'flush' + CATEGORY = 'EasyUse/Pipe' + + def flush(self, clip_skip, optional_positive, positive_token_normalization, positive_weight_interpretation, optional_negative, negative_token_normalization, negative_weight_interpretation, a1111_prompt_style, conditioning_mode, average_strength, old_cond_start, old_cond_end, new_cond_start, new_cond_end, pipe=None, model=None, pos=None, neg=None, latent=None, vae=None, clip=None, image=None, my_unique_id=None, prompt=None): + model = model if model is not None else pipe.get('model') + if model is None: + log_node_warn(f'pipeIn[{my_unique_id}]', 'Model missing from pipeLine') + vae = vae if vae is not None else pipe.get('vae') + if vae is None: + log_node_warn(f'pipeIn[{my_unique_id}]', 'VAE missing from pipeLine') + clip = clip if clip is not None else pipe.get('clip') + if clip is None: + log_node_warn(f'pipeIn[{my_unique_id}]', 'Clip missing from pipeLine') + if image is None: + image = pipe.get('images') if pipe is not None else None + samples = latent if latent is not None else pipe.get('samples') + if samples is None: + log_node_warn(f'pipeIn[{my_unique_id}]', 'Latent missing from pipeLine') + else: + batch_size = pipe['loader_settings']['batch_size'] if 'batch_size' in pipe['loader_settings'] else 1 + samples = {'samples': vae.encode(image[:, :, :, :3])} + samples = RepeatLatentBatch().repeat(samples, batch_size)[0] + pipe_lora_stack = pipe.get('lora_stack') if pipe is not None and 'lora_stack' in pipe else [] + steps = pipe['loader_settings']['steps'] if 'steps' in pipe['loader_settings'] else 1 + if pos is None and optional_positive != '': + (pos, positive_wildcard_prompt, model, clip) = prompt_to_cond('positive', model, clip, clip_skip, pipe_lora_stack, optional_positive, positive_token_normalization, positive_weight_interpretation, a1111_prompt_style, my_unique_id, prompt, easyCache, True, steps) + pos = set_cond(pipe['positive'], pos, conditioning_mode, average_strength, old_cond_start, old_cond_end, new_cond_start, new_cond_end) + pipe['loader_settings']['positive'] = positive_wildcard_prompt + pipe['loader_settings']['positive_token_normalization'] = positive_token_normalization + pipe['loader_settings']['positive_weight_interpretation'] = positive_weight_interpretation + if a1111_prompt_style: + pipe['loader_settings']['a1111_prompt_style'] = True + else: + pos = pipe.get('positive') + if pos is None: + log_node_warn(f'pipeIn[{my_unique_id}]', 'Pos Conditioning missing from pipeLine') + if neg is None and optional_negative != '': + (neg, negative_wildcard_prompt, model, clip) = prompt_to_cond('negative', model, clip, clip_skip, pipe_lora_stack, optional_negative, negative_token_normalization, negative_weight_interpretation, a1111_prompt_style, my_unique_id, prompt, easyCache, True, steps) + neg = set_cond(pipe['negative'], neg, conditioning_mode, average_strength, old_cond_start, old_cond_end, new_cond_start, new_cond_end) + pipe['loader_settings']['negative'] = negative_wildcard_prompt + pipe['loader_settings']['negative_token_normalization'] = negative_token_normalization + pipe['loader_settings']['negative_weight_interpretation'] = negative_weight_interpretation + if a1111_prompt_style: + pipe['loader_settings']['a1111_prompt_style'] = True + else: + neg = pipe.get('negative') + if neg is None: + log_node_warn(f'pipeIn[{my_unique_id}]', 'Neg Conditioning missing from pipeLine') + if pipe is None: + pipe = {'loader_settings': {'positive': '', 'negative': '', 'xyplot': None}} + new_pipe = {**pipe, 'model': model, 'positive': pos, 'negative': neg, 'vae': vae, 'clip': clip, 'samples': samples, 'images': image, 'seed': pipe.get('seed') if pipe is not None and 'seed' in pipe else None, 'loader_settings': {**pipe['loader_settings']}} + del pipe + return (new_pipe, model, pos, neg, latent, vae, clip, image) +``` \ No newline at end of file diff --git a/docs/easy pipeIn.md b/docs/easy pipeIn.md new file mode 100644 index 0000000..2fe434e --- /dev/null +++ b/docs/easy pipeIn.md @@ -0,0 +1,111 @@ +# Documentation +- Class name: pipeIn +- Category: EasyUse/Pipe +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +pipeIn节点作为数据流的中心通道,促进信息在管道中的过渡和转换。它旨在通过集成各种输入并管理它们在系统内的路由来简化数据处理流程。该节点的主要功能是确保必要的组件被有效传递,使得后续操作能够按预期执行。 + +# Input types +## Required +- pipe + - pipe参数至关重要,因为它代表了pipeIn节点的主要数据和指令来源。它包含了所有必要的元素,如模型、条件数据以及其他相关信息,这些信息决定了节点的操作和结果。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +## Optional +- model + - model参数非常重要,因为它定义了pipeIn节点处理中将使用的核心算法或神经网络架构。这对于节点的正确功能和产生准确结果至关重要。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- pos + - 正面条件数据,称为'pos',在指导pipeIn节点的行为方面起着至关重要的作用。它为模型提供了必要的上下文,以便以期望的方式生成或处理数据。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- neg + - 负面条件数据,或'neg',同样重要,因为它为模型的输出设定了边界。它帮助节点完善其操作,并确保结果与预期结果一致。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- latent + - latent参数在处理未观察到的或潜在的数据时非常关键。它使得pipeIn节点能够将隐藏变量纳入其处理中,这可以显著影响最终输出。 + - Comfy dtype: LATENT + - Python dtype: Any +- vae + - vae参数对于节点在编码和解码数据方面的功能至关重要。它代表了变分自编码器模型,对于pipeIn节点执行与数据压缩和生成相关的任务非常必要。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- clip + - 当pipeIn节点需要将生成的数据与特定上下文或内容对齐时,clip参数非常重要。它集成了CLIP模型,这对于理解和生成与给定描述匹配的图像或文本至关重要。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- image + - 当pipeIn节点涉及视觉数据处理时,image参数是必不可少的。它携带了节点将操作或分析的视觉信息,以实现期望的结果。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- xyplot + - xyplot参数用于定义pipeIn节点的绘图设置。它对于数据的视觉表示和分析很重要,允许节点产生有意义的可视化,帮助理解数据的结构和趋势。 + - Comfy dtype: XYPLOT + - Python dtype: Any +- my_unique_id + - my_unique_id参数是pipeIn节点实例的唯一标识符。它对于在复杂系统中跟踪和管理节点很重要,确保每个实例可以单独监控和控制。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- pipe + - 输出pipe是经过pipeIn节点处理的精炼和结构化的数据集。它封装了节点执行过程中的结果和任何修改,作为管道内进一步操作或分析的基础。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class pipeIn: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {}, 'optional': {'pipe': ('PIPE_LINE',), 'model': ('MODEL',), 'pos': ('CONDITIONING',), 'neg': ('CONDITIONING',), 'latent': ('LATENT',), 'vae': ('VAE',), 'clip': ('CLIP',), 'image': ('IMAGE',), 'xyPlot': ('XYPLOT',)}, 'hidden': {'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('pipe',) + FUNCTION = 'flush' + CATEGORY = 'EasyUse/Pipe' + + def flush(self, pipe=None, model=None, pos=None, neg=None, latent=None, vae=None, clip=None, image=None, xyplot=None, my_unique_id=None): + model = model if model is not None else pipe.get('model') + if model is None: + log_node_warn(f'pipeIn[{my_unique_id}]', 'Model missing from pipeLine') + pos = pos if pos is not None else pipe.get('positive') + if pos is None: + log_node_warn(f'pipeIn[{my_unique_id}]', 'Pos Conditioning missing from pipeLine') + neg = neg if neg is not None else pipe.get('negative') + if neg is None: + log_node_warn(f'pipeIn[{my_unique_id}]', 'Neg Conditioning missing from pipeLine') + vae = vae if vae is not None else pipe.get('vae') + if vae is None: + log_node_warn(f'pipeIn[{my_unique_id}]', 'VAE missing from pipeLine') + clip = clip if clip is not None else pipe.get('clip') + if clip is None: + log_node_warn(f'pipeIn[{my_unique_id}]', 'Clip missing from pipeLine') + if latent is not None: + samples = latent + elif image is None: + samples = pipe.get('samples') if pipe is not None else None + image = pipe.get('images') if pipe is not None else None + elif image is not None: + if pipe is None: + batch_size = 1 + else: + batch_size = pipe['loader_settings']['batch_size'] if 'batch_size' in pipe['loader_settings'] else 1 + samples = {'samples': vae.encode(image[:, :, :, :3])} + samples = RepeatLatentBatch().repeat(samples, batch_size)[0] + if pipe is None: + pipe = {'loader_settings': {'positive': '', 'negative': '', 'xyplot': None}} + xyplot = xyplot if xyplot is not None else pipe['loader_settings']['xyplot'] if xyplot in pipe['loader_settings'] else None + new_pipe = {**pipe, 'model': model, 'positive': pos, 'negative': neg, 'vae': vae, 'clip': clip, 'samples': samples, 'images': image, 'seed': pipe.get('seed') if pipe is not None and 'seed' in pipe else None, 'loader_settings': {**pipe['loader_settings'], 'xyplot': xyplot}} + del pipe + return (new_pipe,) +``` \ No newline at end of file diff --git a/docs/easy pipeOut.md b/docs/easy pipeOut.md new file mode 100644 index 0000000..a8c29db --- /dev/null +++ b/docs/easy pipeOut.md @@ -0,0 +1,87 @@ +# Documentation +- Class name: pipeOut +- Category: EasyUse/Pipe +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +pipeOut节点旨在简化流水线的输出过程,确保结果被高效管理和组织。它作为处理各种数据类型的中心枢纽,促进了从处理到分析或存储的过渡。通过处理数据流的最后阶段,该节点保持了输出的完整性和可访问性。 + +# Input types +## Required +- pipe + - ‘pipe’参数至关重要,它代表从中提取和管理数据的流水线。它是节点的主要信息来源,决定了输出的类型和结构。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +## Optional +- my_unique_id + - ‘my_unique_id’参数作为跟踪和关联特定输出与唯一请求或进程的标识符。它有助于系统内数据的组织和检索。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- pipe + - ‘pipe’输出是处理后数据的全面集合,包含了流水线中的所有结果。它是节点功能的结晶,提供了一个结构化和组织良好的数据集,供进一步使用。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- model + - ‘model’输出代表了在流水线中使用的机器学习或神经网络模型。它是理解处理数据的基础和所采用方法的关键组成部分。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- pos + - ‘pos’输出由正向调节数据组成,用于指导和完善模型的预测。它在生成过程中起着关键作用,确保输出与期望结果一致。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Any] +- neg + - ‘neg’输出包含负向调节数据,用于对比和过滤掉模型预测中不希望的结果。它是保持输出质量和相关性的重要部分。 + - Comfy dtype: CONDITIONING + - Python dtype: List[Any] +- latent + - ‘latent’输出代表从模型中派生出的中间表示或嵌入。这些潜在特征对于理解数据的底层结构至关重要,可以用于进一步的分析或处理。 + - Comfy dtype: LATENT + - Python dtype: List[torch.Tensor] +- vae + - ‘vae’输出指的是流水线中的变化自编码器组件,负责从学习到的潜在空间生成新的数据点。它是创造新颖和多样化输出的关键创新。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module +- clip + - ‘clip’输出来自CLIP模型,用于多模态理解和生成。它通过为输出提供上下文和意义来增强节点的能力。 + - Comfy dtype: CLIP + - Python dtype: torch.nn.Module +- image + - ‘image’输出由视觉数据组成,是模型处理的直接结果。它的重要性在于提供了数据的有形和视觉表示,允许立即进行解释和分析。 + - Comfy dtype: IMAGE + - Python dtype: List[PIL.Image.Image] +- seed + - ‘seed’输出是一个数值,用于确保生成过程中的可重复性和一致性。它对于调试和保持输出的可靠性至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class pipeOut: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',)}, 'hidden': {'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE', 'MODEL', 'CONDITIONING', 'CONDITIONING', 'LATENT', 'VAE', 'CLIP', 'IMAGE', 'INT') + RETURN_NAMES = ('pipe', 'model', 'pos', 'neg', 'latent', 'vae', 'clip', 'image', 'seed') + FUNCTION = 'flush' + CATEGORY = 'EasyUse/Pipe' + + def flush(self, pipe, my_unique_id=None): + model = pipe.get('model') + pos = pipe.get('positive') + neg = pipe.get('negative') + latent = pipe.get('samples') + vae = pipe.get('vae') + clip = pipe.get('clip') + image = pipe.get('images') + seed = pipe.get('seed') + return (pipe, model, pos, neg, latent, vae, clip, image, seed) +``` \ No newline at end of file diff --git a/docs/easy pipeToBasicPipe.md b/docs/easy pipeToBasicPipe.md new file mode 100644 index 0000000..0760622 --- /dev/null +++ b/docs/easy pipeToBasicPipe.md @@ -0,0 +1,45 @@ +# Documentation +- Class name: pipeToBasicPipe +- Category: EasyUse/Pipe +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +‘pipeToBasicPipe’节点旨在将复杂的管道配置转换为简化的‘basic_pipe’格式。它作为一个中介,确保提取并组织管道的基本组件,使其更易于进一步处理。该节点在降低管道管理的复杂性方面发挥关键作用,从而提高系统的总体效率。 + +# Input types +## Required +- pipe + - ‘pipe’参数对于节点的操作至关重要,因为它代表了需要简化的复杂管道配置。它是主要的输入,决定了节点的执行和生成的‘basic_pipe’的结构。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- my_unique_id + - ‘my_unique_id’参数虽然是可选的,但可以用来唯一标识转换过程。它为操作增加了可追溯性,这对于复杂系统中的调试或跟踪可能非常重要。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- basic_pipe + - ‘basic_pipe’输出包含了原始管道的简化表示。它是一个结构化的输出,保留了管道的核心元素,使其更容易操作并集成到后续流程中。 + - Comfy dtype: BASIC_PIPE + - Python dtype: Tuple[Any, Any, Any, Any, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class pipeToBasicPipe: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',)}, 'hidden': {'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('BASIC_PIPE',) + RETURN_NAMES = ('basic_pipe',) + FUNCTION = 'doit' + CATEGORY = 'EasyUse/Pipe' + + def doit(self, pipe, my_unique_id=None): + new_pipe = (pipe.get('model'), pipe.get('clip'), pipe.get('vae'), pipe.get('positive'), pipe.get('negative')) + del pipe + return (new_pipe,) +``` \ No newline at end of file diff --git a/docs/easy portraitMaster.md b/docs/easy portraitMaster.md new file mode 100644 index 0000000..0a86270 --- /dev/null +++ b/docs/easy portraitMaster.md @@ -0,0 +1,168 @@ +# Documentation +- Class name: portraitMaster +- Category: EasyUse/Prompt +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +portraitMaster节点旨在基于一组全面的参数生成详细的肖像生成提示。它通过结合各种属性,如面部特征、表情和光照条件,在输出中实现高度的定制化和真实感,从而封装了肖像生成的本质。 + +# Input types +## Required +- shot + - “shot”参数对于定义要生成的肖像类型至关重要。它影响图像的整体构图和框架,这对于捕捉所需的美学和叙述至关重要。 + - Comfy dtype: COMBO + - Python dtype: List[str] +## Optional +- gender + - “gender”参数对于指导肖像主体的生成至关重要。它有助于确定与所选性别相符的物理特征和表情细节,有助于提高肖像的真实性和可信度。 + - Comfy dtype: COMBO + - Python dtype: List[str] +- age + - “age”参数在决定肖像主体的外观中起着重要作用。它影响面部特征、皮肤细节和其他与年龄相关的属性的渲染,确保肖像准确地反映所选年龄组。 + - Comfy dtype: INT + - Python dtype: int +- nationality_1 + - “nationality_1”参数与“nationality_2”参数一起,有助于定义肖像主体的文化和种族背景。这为生成的肖像增添了多样性和丰富性,增加了深度和背景的层次。 + - Comfy dtype: COMBO + - Python dtype: List[str] +- facial_expression + - “facial_expression”参数对于传达肖像主体的情感状态至关重要。它指导生成与所选情感相匹配的面部特征和表情,增强了肖像的情感影响力和叙事性。 + - Comfy dtype: COMBO + - Python dtype: List[str] + +# Output types +- prompt + - “prompt”输出是一个综合性的字符串,将所有输入参数整合成一个连贯且结构化的格式。它作为肖像生成过程的基础,确保最终图像中捕捉到预期的细节和细微差别。 + - Comfy dtype: STRING + - Python dtype: str +- negative_prompt + - “negative_prompt”输出是一个补充性字符串,提供了精炼肖像的额外指令。它解决了应该最小化或避免的方面,有助于提高生成图像的整体质量和准确性。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: GPU + +# Source code +``` +class portraitMaster: + + @classmethod + def INPUT_TYPES(s): + max_float_value = 1.95 + prompt_path = os.path.join(RESOURCES_DIR, 'portrait_prompt.json') + if not os.path.exists(prompt_path): + response = urlopen('https://raw.githubusercontent.com/yolain/ComfyUI-Easy-Use/main/resources/portrait_prompt.json') + temp_prompt = json.loads(response.read()) + prompt_serialized = json.dumps(temp_prompt, indent=4) + with open(prompt_path, 'w') as f: + f.write(prompt_serialized) + del response, temp_prompt + with open(prompt_path, 'r') as f: + list = json.load(f) + keys = [['shot', 'COMBO', {'key': 'shot_list'}], ['shot_weight', 'FLOAT'], ['gender', 'COMBO', {'default': 'Woman', 'key': 'gender_list'}], ['age', 'INT', {'default': 30, 'min': 18, 'max': 90, 'step': 1, 'display': 'slider'}], ['nationality_1', 'COMBO', {'default': 'Chinese', 'key': 'nationality_list'}], ['nationality_2', 'COMBO', {'key': 'nationality_list'}], ['nationality_mix', 'FLOAT'], ['body_type', 'COMBO', {'key': 'body_type_list'}], ['body_type_weight', 'FLOAT'], ['model_pose', 'COMBO', {'key': 'model_pose_list'}], ['eyes_color', 'COMBO', {'key': 'eyes_color_list'}], ['facial_expression', 'COMBO', {'key': 'face_expression_list'}], ['facial_expression_weight', 'FLOAT'], ['face_shape', 'COMBO', {'key': 'face_shape_list'}], ['face_shape_weight', 'FLOAT'], ['facial_asymmetry', 'FLOAT'], ['hair_style', 'COMBO', {'key': 'hair_style_list'}], ['hair_color', 'COMBO', {'key': 'hair_color_list'}], ['disheveled', 'FLOAT'], ['beard', 'COMBO', {'key': 'beard_list'}], ['skin_details', 'FLOAT'], ['skin_pores', 'FLOAT'], ['dimples', 'FLOAT'], ['freckles', 'FLOAT'], ['moles', 'FLOAT'], ['skin_imperfections', 'FLOAT'], ['skin_acne', 'FLOAT'], ['tanned_skin', 'FLOAT'], ['eyes_details', 'FLOAT'], ['iris_details', 'FLOAT'], ['circular_iris', 'FLOAT'], ['circular_pupil', 'FLOAT'], ['light_type', 'COMBO', {'key': 'light_type_list'}], ['light_direction', 'COMBO', {'key': 'light_direction_list'}], ['light_weight', 'FLOAT']] + widgets = {} + for (i, obj) in enumerate(keys): + if obj[1] == 'COMBO': + key = obj[2]['key'] if obj[2] and 'key' in obj[2] else obj[0] + _list = list[key].copy() + _list.insert(0, '-') + widgets[obj[0]] = (_list, {**obj[2]}) + elif obj[1] == 'FLOAT': + widgets[obj[0]] = ('FLOAT', {'default': 0, 'step': 0.05, 'min': 0, 'max': max_float_value, 'display': 'slider'}) + elif obj[1] == 'INT': + widgets[obj[0]] = (obj[1], obj[2]) + del list + return {'required': {**widgets, 'photorealism_improvement': (['enable', 'disable'],), 'prompt_start': ('STRING', {'multiline': True, 'default': 'raw photo, (realistic:1.5)'}), 'prompt_additional': ('STRING', {'multiline': True, 'default': ''}), 'prompt_end': ('STRING', {'multiline': True, 'default': ''}), 'negative_prompt': ('STRING', {'multiline': True, 'default': ''})}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive', 'negative') + FUNCTION = 'pm' + CATEGORY = 'EasyUse/Prompt' + + def pm(self, shot='-', shot_weight=1, gender='-', body_type='-', body_type_weight=0, eyes_color='-', facial_expression='-', facial_expression_weight=0, face_shape='-', face_shape_weight=0, nationality_1='-', nationality_2='-', nationality_mix=0.5, age=30, hair_style='-', hair_color='-', disheveled=0, dimples=0, freckles=0, skin_pores=0, skin_details=0, moles=0, skin_imperfections=0, wrinkles=0, tanned_skin=0, eyes_details=1, iris_details=1, circular_iris=1, circular_pupil=1, facial_asymmetry=0, prompt_additional='', prompt_start='', prompt_end='', light_type='-', light_direction='-', light_weight=0, negative_prompt='', photorealism_improvement='disable', beard='-', model_pose='-', skin_acne=0): + prompt = [] + if gender == '-': + gender = '' + else: + if age <= 25 and gender == 'Woman': + gender = 'girl' + if age <= 25 and gender == 'Man': + gender = 'boy' + gender = ' ' + gender + ' ' + if nationality_1 != '-' and nationality_2 != '-': + nationality = f'[{nationality_1}:{nationality_2}:{round(nationality_mix, 2)}]' + elif nationality_1 != '-': + nationality = nationality_1 + ' ' + elif nationality_2 != '-': + nationality = nationality_2 + ' ' + else: + nationality = '' + if prompt_start != '': + prompt.append(f'{prompt_start}') + if shot != '-' and shot_weight > 0: + prompt.append(f'({shot}:{round(shot_weight, 2)})') + prompt.append(f'({nationality}{gender}{round(age)}-years-old:1.5)') + if body_type != '-' and body_type_weight > 0: + prompt.append(f'({body_type}, {body_type} body:{round(body_type_weight, 2)})') + if model_pose != '-': + prompt.append(f'({model_pose}:1.5)') + if eyes_color != '-': + prompt.append(f'({eyes_color} eyes:1.25)') + if facial_expression != '-' and facial_expression_weight > 0: + prompt.append(f'({facial_expression}, {facial_expression} expression:{round(facial_expression_weight, 2)})') + if face_shape != '-' and face_shape_weight > 0: + prompt.append(f'({face_shape} shape face:{round(face_shape_weight, 2)})') + if hair_style != '-': + prompt.append(f'({hair_style} hairstyle:1.25)') + if hair_color != '-': + prompt.append(f'({hair_color} hair:1.25)') + if beard != '-': + prompt.append(f'({beard}:1.15)') + if disheveled != '-' and disheveled > 0: + prompt.append(f'(disheveled:{round(disheveled, 2)})') + if prompt_additional != '': + prompt.append(f'{prompt_additional}') + if skin_details > 0: + prompt.append(f'(skin details, skin texture:{round(skin_details, 2)})') + if skin_pores > 0: + prompt.append(f'(skin pores:{round(skin_pores, 2)})') + if skin_imperfections > 0: + prompt.append(f'(skin imperfections:{round(skin_imperfections, 2)})') + if skin_acne > 0: + prompt.append(f'(acne, skin with acne:{round(skin_acne, 2)})') + if wrinkles > 0: + prompt.append(f'(skin imperfections:{round(wrinkles, 2)})') + if tanned_skin > 0: + prompt.append(f'(tanned skin:{round(tanned_skin, 2)})') + if dimples > 0: + prompt.append(f'(dimples:{round(dimples, 2)})') + if freckles > 0: + prompt.append(f'(freckles:{round(freckles, 2)})') + if moles > 0: + prompt.append(f'(skin pores:{round(moles, 2)})') + if eyes_details > 0: + prompt.append(f'(eyes details:{round(eyes_details, 2)})') + if iris_details > 0: + prompt.append(f'(iris details:{round(iris_details, 2)})') + if circular_iris > 0: + prompt.append(f'(circular iris:{round(circular_iris, 2)})') + if circular_pupil > 0: + prompt.append(f'(circular pupil:{round(circular_pupil, 2)})') + if facial_asymmetry > 0: + prompt.append(f'(facial asymmetry, face asymmetry:{round(facial_asymmetry, 2)})') + if light_type != '-' and light_weight > 0: + if light_direction != '-': + prompt.append(f'({light_type} {light_direction}:{round(light_weight, 2)})') + else: + prompt.append(f'({light_type}:{round(light_weight, 2)})') + if prompt_end != '': + prompt.append(f'{prompt_end}') + prompt = ', '.join(prompt) + prompt = prompt.lower() + if photorealism_improvement == 'enable': + prompt = prompt + ', (professional photo, balanced photo, balanced exposure:1.2), (film grain:1.15)' + if photorealism_improvement == 'enable': + negative_prompt = negative_prompt + ', (shinny skin, reflections on the skin, skin reflections:1.25)' + log_node_info('Portrait Master as generate the prompt:', prompt) + return (prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/easy poseEditor.md b/docs/easy poseEditor.md new file mode 100644 index 0000000..754ff7c --- /dev/null +++ b/docs/easy poseEditor.md @@ -0,0 +1,59 @@ +# Documentation +- Class name: poseEditor +- Category: EasyUse/Image +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +poseEditor节点旨在处理和操作图像数据,便于从输入图像中提取和转换与姿态相关的特征。它擅长处理来自不同来源的图像数据,并将其转换为适合进一步分析或可视化的格式。 + +# Input types +## Required +- image + - 图像参数至关重要,因为它定义了将由节点处理的源图像。它通过确定输入数据的内容和质量影响节点的操作,这直接影响后续的姿态分析和转换。 + - Comfy dtype: COMBO[sorted(os.listdir(temp_dir))]:string + - Python dtype: str + +# Output types +- output_pose + - output_pose代表处理后的图像数据,已经转换并准备好进行进一步分析。它封装了从输入图像中提取的关键信息,重点关注与姿态相关的特征。 + - Comfy dtype: tuple(torch.Tensor) + - Python dtype: Tuple[torch.Tensor] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class poseEditor: + + @classmethod + def INPUT_TYPES(self): + temp_dir = folder_paths.get_temp_directory() + if not os.path.isdir(temp_dir): + os.makedirs(temp_dir) + temp_dir = folder_paths.get_temp_directory() + return {'required': {}, 'optional': {'image': (sorted(os.listdir(temp_dir)),)}} + RETURN_TYPES = ('IMAGE',) + FUNCTION = 'output_pose' + CATEGORY = 'EasyUse/Image' + + def output_pose(self, image): + if image.startswith('http'): + from worker.components.utils import util + i = util.get_image_from_uri(image) + else: + image_path = os.path.join(folder_paths.get_temp_directory(), image) + i = Image.open(image_path) + image = i.convert('RGB') + image = np.array(image).astype(np.float32) / 255.0 + image = torch.from_numpy(image)[None,] + return (image,) + + @classmethod + def IS_CHANGED(self, image): + image_path = os.path.join(folder_paths.get_temp_directory(), image) + m = hashlib.sha256() + with open(image_path, 'rb') as f: + m.update(f.read()) + return m.digest().hex() +``` \ No newline at end of file diff --git a/docs/easy positive.md b/docs/easy positive.md new file mode 100644 index 0000000..a2e333e --- /dev/null +++ b/docs/easy positive.md @@ -0,0 +1,43 @@ +# Documentation +- Class name: positivePrompt +- Category: EasyUse/Prompt +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +此类节点封装了处理和生成积极提示的功能,旨在增强生成内容的创造力和积极性。它作为用户在其项目中引入积极语言的工具,从而影响输出的语气和情绪。 + +# Input types +## Required +- positive + - “positive”参数至关重要,因为它定义了节点将关注的积极性消息或主题。它直接影响内容的性质,确保输出充满积极情绪。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- positive + - 输出'positive'代表经过精炼和处理的积极提示,可以在各种应用中使用,以促进乐观和建设性的信息传递。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class positivePrompt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'positive': ('STRING', {'default': '', 'multiline': True, 'placeholder': 'Positive'})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('positive',) + FUNCTION = 'main' + CATEGORY = 'EasyUse/Prompt' + + @staticmethod + def main(positive): + return (positive,) +``` \ No newline at end of file diff --git a/docs/easy preDetailerFix.md b/docs/easy preDetailerFix.md new file mode 100644 index 0000000..fd0c511 --- /dev/null +++ b/docs/easy preDetailerFix.md @@ -0,0 +1,131 @@ +# Documentation +- Class name: preDetailerFix +- Category: EasyUse/Fix +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +preDetailerFix节点旨在增强图像数据管道的预处理阶段,确保输入图像适当地为进一步的分析和操作做好准备。该节点专注于在图像处理的初始阶段修复常见问题,从而提高后续操作的质量和可靠性。 + +# Input types +## Required +- pipe + - pipe参数是必要的,因为它携带了节点运行所需的核心数据和设置。它包括模型、clip和vae组件,以及图像和其他相关信息,这些信息决定了节点的处理流程。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict +- guide_size + - guide_size参数对于定义节点处理图像的分辨率至关重要,直接影响细节层次和计算效率。 + - Comfy dtype: FLOAT + - Python dtype: float +- guide_size_for + - guide_size_for参数决定了应用引导尺寸的方法,无论是通过边界框还是裁剪区域,这都会显著影响图像处理的结果。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- max_size + - max_size参数设置了图像尺寸的上限,确保处理保持在可管理的限度内,防止资源过度消耗。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - seed参数对于确保节点操作的可重复性很重要,允许在不同运行中获得一致的结果。 + - Comfy dtype: INT + - Python dtype: int +- steps + - steps参数定义了节点将执行的迭代次数,这直接关系到图像处理的彻底性和改进结果的潜力。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数调整节点的配置设置,影响其行为和图像处理的质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数在为节点选择适当的采样方法方面至关重要,这将极大地影响图像处理的效率和效果。 + - Comfy dtype: COMBO + - Python dtype: str +- scheduler + - scheduler参数对于管理节点的执行速度至关重要,确保最佳性能和资源利用。 + - Comfy dtype: COMBO + - Python dtype: str +- denoise + - denoise参数有助于控制降噪过程,提高处理图像的清晰度和质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- feather + - feather参数对于软化处理图像的边缘很重要,可以带来更平滑的过渡和更视觉上吸引人的结果。 + - Comfy dtype: INT + - Python dtype: int +- noise_mask + - noise_mask参数启用或禁用噪声掩码功能,这对于管理图像处理中不需要的伪影至关重要。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- force_inpaint + - force_inpaint参数很重要,它指导节点填补图像中缺失或损坏的部分,确保最终输出的完整性和一致性。 + - Comfy dtype: BOOLEAN + - Python dtype: bool +- drop_size + - drop_size参数决定了从图像中删除的区域大小,这对于移除不需要的元素和提高整体图像质量至关重要。 + - Comfy dtype: INT + - Python dtype: int +- wildcard + - wildcard参数允许对节点的操作进行动态调整和定制,提供了处理各种图像处理场景的灵活性。 + - Comfy dtype: STRING + - Python dtype: str +- cycle + - cycle参数决定了节点重复处理的次数,这可以增强图像处理结果的稳定性和可靠性。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- pipe + - 输出pipe是一个综合结构,封装了处理后的图像和相关数据,为管道中的后续操作提供基础。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict + +# Usage tips +- Infra type: CPU + +# Source code +``` +class preDetailerFix: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',), 'guide_size': ('FLOAT', {'default': 256, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), 'guide_size_for': ('BOOLEAN', {'default': True, 'label_on': 'bbox', 'label_off': 'crop_region'}), 'max_size': ('FLOAT', {'default': 768, 'min': 64, 'max': MAX_RESOLUTION, 'step': 8}), '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}), 'noise_mask': ('BOOLEAN', {'default': True, 'label_on': 'enabled', 'label_off': 'disabled'}), 'force_inpaint': ('BOOLEAN', {'default': True, 'label_on': 'enabled', 'label_off': 'disabled'}), 'drop_size': ('INT', {'min': 1, 'max': MAX_RESOLUTION, 'step': 1, 'default': 10}), 'wildcard': ('STRING', {'multiline': True, 'dynamicPrompts': False}), 'cycle': ('INT', {'default': 1, 'min': 1, 'max': 10, 'step': 1})}, 'optional': {'bbox_segm_pipe': ('PIPE_LINE',), 'sam_pipe': ('PIPE_LINE',), 'optional_image': ('IMAGE',)}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('pipe',) + OUTPUT_IS_LIST = (False,) + FUNCTION = 'doit' + CATEGORY = 'EasyUse/Fix' + + def doit(self, pipe, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler, denoise, feather, noise_mask, force_inpaint, drop_size, wildcard, cycle, bbox_segm_pipe=None, sam_pipe=None, optional_image=None): + 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") + bbox_segm_pipe = bbox_segm_pipe or (pipe['bbox_segm_pipe'] if pipe and 'bbox_segm_pipe' in pipe else None) + if bbox_segm_pipe is None: + raise Exception(f"[ERROR] bbox_segm_pipe or pipe['bbox_segm_pipe'] is missing") + sam_pipe = sam_pipe or (pipe['sam_pipe'] if pipe and 'sam_pipe' in pipe else None) + if sam_pipe is None: + raise Exception(f"[ERROR] sam_pipe or pipe['sam_pipe'] is missing") + 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, 'bbox_segm_pipe': bbox_segm_pipe, 'sam_pipe': sam_pipe, '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, 'noise_mask': noise_mask, 'force_inpaint': force_inpaint, 'drop_size': drop_size, 'wildcard': wildcard, 'cycle': cycle}} + del bbox_segm_pipe + del sam_pipe + return (new_pipe,) +``` \ No newline at end of file diff --git a/docs/easy preMaskDetailerFix.md b/docs/easy preMaskDetailerFix.md new file mode 100644 index 0000000..19b9f8a --- /dev/null +++ b/docs/easy preMaskDetailerFix.md @@ -0,0 +1,97 @@ +# Documentation +- Class name: preMaskDetailerFix +- Category: EasyUse/Fix +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +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,) +``` \ No newline at end of file diff --git a/docs/easy preSampling.md b/docs/easy preSampling.md new file mode 100644 index 0000000..fa1d18f --- /dev/null +++ b/docs/easy preSampling.md @@ -0,0 +1,102 @@ +# Documentation +- Class name: samplerSettings +- Category: EasyUse/PreSampling +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +samplerSettings类封装了采样流水线的配置过程,提供了一种定义影响采样过程的参数的结构化方式。它的设计旨在简化复杂采样任务的设置,确保正确应用必要的设置以实现期望的结果。 + +# Input types +## Required +- pipe + - pipe参数是必需的,因为它包含了采样过程中所需的核心数据和设置。它包括模型、图像以及其他samplerSettings类用来配置采样环境的相关信息。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- steps + - steps参数规定了采样过程中要执行的迭代次数。它对控制采样的持续时间和粒度至关重要,直接影响结果的质量和多样性。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数是一个浮点值,用于调整采样过程的配置。它在微调采样器的行为以获得最佳结果方面发挥着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数指定了采样过程中要使用的采样器类型。它在确定samplerSettings类用于生成样本的方法和策略方面至关重要。 + - Comfy dtype: COMBO + - Python dtype: str +- scheduler + - scheduler参数定义了采样过程的调度策略。它对于管理采样的动态非常重要,确保过程随时间适应和演变,以产生最佳可能的结果。 + - Comfy dtype: COMBO + - Python dtype: str +- denoise + - denoise参数用于控制在采样过程中应用的降噪水平。它显著影响生成样本的清晰度和质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - seed参数对于确保采样过程的可重复性至关重要。它初始化随机数生成器,允许在不同运行中获得一致的结果。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- image_to_latent + - image_to_latent参数提供了一种将图像转换为潜在表示的方法。它是一个可选输入,使用时,会改变采样过程的重点,以便根据图像数据生成样本。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- latent + - latent参数允许在采样过程中直接操作潜在空间。它是一个可选输入,提供时,可以从特定的潜在状态生成样本。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- prompt + - prompt参数将文本指导引入采样过程,影响生成样本的方向和风格。它是一个可选输入,为输出增加了额外的控制层。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - extra_pnginfo参数包含与PNG图像相关的额外信息,可用于完善采样过程。它是一个可选输入,为生成样本提供更多上下文。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: str +- my_unique_id + - my_unique_id参数用于跟踪和识别独特的采样会话。它是一个可选输入,有助于维护采样过程的完整性和可追溯性。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- pipe + - 输出pipe是一个包含更新设置和数据的综合结构,这些设置和数据是采样过程后续阶段所需的。它是至关重要的输出,因为它为生成高质量样本铺平了道路。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class samplerSettings: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), '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': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': MAX_SEED_NUM})}, 'optional': {'image_to_latent': ('IMAGE',), 'latent': ('LATENT',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('pipe',) + OUTPUT_NODE = True + FUNCTION = 'settings' + CATEGORY = 'EasyUse/PreSampling' + + def settings(self, pipe, steps, cfg, sampler_name, scheduler, denoise, seed, image_to_latent=None, latent=None, prompt=None, extra_pnginfo=None, my_unique_id=None): + vae = pipe['vae'] + batch_size = pipe['loader_settings']['batch_size'] if 'batch_size' in pipe['loader_settings'] else 1 + if image_to_latent is not None: + samples = {'samples': vae.encode(image_to_latent[:, :, :, :3])} + samples = RepeatLatentBatch().repeat(samples, batch_size)[0] + images = image_to_latent + elif latent is not None: + samples = latent + images = pipe['images'] + else: + samples = pipe['samples'] + images = pipe['images'] + new_pipe = {'model': pipe['model'], 'positive': pipe['positive'], 'negative': pipe['negative'], 'vae': pipe['vae'], 'clip': pipe['clip'], 'samples': samples, 'images': images, 'seed': seed, 'loader_settings': {**pipe['loader_settings'], 'steps': steps, 'cfg': cfg, 'sampler_name': sampler_name, 'scheduler': scheduler, 'denoise': denoise, 'add_noise': 'enabled'}} + del pipe + return {'ui': {'value': [seed]}, 'result': (new_pipe,)} +``` \ No newline at end of file diff --git a/docs/easy preSamplingAdvanced.md b/docs/easy preSamplingAdvanced.md new file mode 100644 index 0000000..a5c405b --- /dev/null +++ b/docs/easy preSamplingAdvanced.md @@ -0,0 +1,117 @@ +# Documentation +- Class name: samplerSettingsAdvanced +- Category: EasyUse/PreSampling +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点旨在为生成模型的采样参数提供配置流程,为根据特定需求微调生成过程提供强大的框架。它强调适应性和用户对采样过程的控制,而不是深入探讨底层方法的具体细节。 + +# Input types +## Required +- pipe + - ‘pipe’参数是节点的主要信息来源,包含采样过程所需的所有上下文和数据。它至关重要,因为它决定了每一步数据的流动和模型的状态。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict +- steps + - ‘steps’参数定义了采样过程中要执行的迭代次数。它在确定采样的粒度以及模型能力被利用的程度上至关重要。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - ‘cfg’参数调整采样过程的配置,允许对模型行为进行微调。它在根据所需规格塑造输出方面发挥着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - ‘sampler_name’参数选择要使用的特定采样方法,影响采样过程的整体策略和有效性。 + - Comfy dtype: COMBO + - Python dtype: str +- scheduler + - ‘scheduler’参数确定采样过程的调度策略,这对于管理资源和确保高效执行至关重要。 + - Comfy dtype: COMBO + - Python dtype: str +- start_at_step + - ‘start_at_step’参数设置采样过程的起点,这对于控制操作的时机和顺序很重要。 + - Comfy dtype: INT + - Python dtype: int +- end_at_step + - ‘end_at_step’参数定义了采样过程的终点,确保执行在期望的阶段结束。 + - Comfy dtype: INT + - Python dtype: int +- add_noise + - ‘add_noise’参数控制采样过程中噪声的引入,影响生成输出的多样性和质量。 + - Comfy dtype: COMBO + - Python dtype: str +- seed + - ‘seed’参数通过为随机数生成提供一个固定点,确保采样过程的可复现性。 + - Comfy dtype: INT + - Python dtype: int +- return_with_leftover_noise + - ‘return_with_leftover_noise’参数决定是否在最终输出中包含剩余噪声,这可能会影响结果的审美和风格方面。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- image_to_latent + - ‘image_to_latent’参数允许将输入图像转换到潜在空间,这对于某些类型的生成任务是基本的。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- latent + - ‘latent’参数直接提供潜在变量的输入,对于需要在潜在空间层面进行操作的任务至关重要。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- prompt + - ‘prompt’参数为生成模型引入文本指导,将输出引向特定的主题或风格。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - ‘extra_pnginfo’参数包含与PNG图像相关的额外信息,可用于高级图像处理任务。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: str +- my_unique_id + - ‘my_unique_id’参数为操作分配唯一标识符,对于跟踪和管理多个并发进程至关重要。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- pipe + - ‘pipe’输出是一个综合性结构,封装了生成模型的更新状态和采样过程的结果,为后续操作提供了基础。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict + +# Usage tips +- Infra type: CPU + +# Source code +``` +class samplerSettingsAdvanced: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), '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,), 'start_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'end_at_step': ('INT', {'default': 10000, 'min': 0, 'max': 10000}), 'add_noise': (['enable', 'disable'],), 'seed': ('INT', {'default': 0, 'min': 0, 'max': MAX_SEED_NUM}), 'return_with_leftover_noise': (['disable', 'enable'],)}, 'optional': {'image_to_latent': ('IMAGE',), 'latent': ('LATENT',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('pipe',) + OUTPUT_NODE = True + FUNCTION = 'settings' + CATEGORY = 'EasyUse/PreSampling' + + def settings(self, pipe, steps, cfg, sampler_name, scheduler, start_at_step, end_at_step, add_noise, seed, return_with_leftover_noise, image_to_latent=None, latent=None, prompt=None, extra_pnginfo=None, my_unique_id=None): + vae = pipe['vae'] + batch_size = pipe['loader_settings']['batch_size'] if 'batch_size' in pipe['loader_settings'] else 1 + if image_to_latent is not None: + samples = {'samples': vae.encode(image_to_latent[:, :, :, :3])} + samples = RepeatLatentBatch().repeat(samples, batch_size)[0] + images = image_to_latent + elif latent is not None: + samples = latent + images = pipe['images'] + else: + samples = pipe['samples'] + images = pipe['images'] + force_full_denoise = True + if return_with_leftover_noise == 'enable': + force_full_denoise = False + new_pipe = {'model': pipe['model'], 'positive': pipe['positive'], 'negative': pipe['negative'], 'vae': pipe['vae'], 'clip': pipe['clip'], 'samples': samples, 'images': images, 'seed': seed, 'loader_settings': {**pipe['loader_settings'], 'steps': steps, 'cfg': cfg, 'sampler_name': sampler_name, 'scheduler': scheduler, 'start_step': start_at_step, 'last_step': end_at_step, 'denoise': 1.0, 'add_noise': add_noise, 'force_full_denoise': force_full_denoise}} + del pipe + return {'ui': {'value': [seed]}, 'result': (new_pipe,)} +``` \ No newline at end of file diff --git a/docs/easy preSamplingCascade.md b/docs/easy preSamplingCascade.md new file mode 100644 index 0000000..15371e1 --- /dev/null +++ b/docs/easy preSamplingCascade.md @@ -0,0 +1,131 @@ +# Documentation +- Class name: cascadeSettings +- Category: EasyUse/PreSampling +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +cascadeSettings节点旨在简化配置和管理生成模型流水线的设置过程。它封装了模型编码和解码的必要参数,以及采样策略,以便于创建高质量的视觉输出。该节点强调易用性和效率,允许用户专注于项目的创意方面,而不会被复杂的技术细节所困扰。 + +# Input types +## Required +- pipe + - ‘pipe’参数至关重要,因为它携带了生成模型流水线的全部上下文,包括模型设置和数据样本。它对cascadeSettings节点的正确运行和生成过程的完整性至关重要。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict +- encode_vae_name + - ‘encode_vae_name’参数指定了生成过程中使用的编码器VAE模型的名称。它对于设置潜在空间表示的基础很重要,直接影响生成图像的质量。 + - Comfy dtype: COMBO + - Python dtype: Union[str, None] +- decode_vae_name + - ‘decode_vae_name’参数决定了用于从潜在空间重构图像的解码器VAE模型。其选择影响最终输出的保真度和视觉一致性。 + - Comfy dtype: COMBO + - Python dtype: Union[str, None] +- steps + - ‘steps’参数定义了采样过程中的迭代次数或步骤数。它是控制生成图像细节和精炼程度的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - ‘cfg’参数调整生成模型的配置,影响流水线的整体行为和性能。这是一个关键设置,可以显著改变最终结果。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - ‘sampler_name’参数选择用于生成图像的采样方法。它在决定视觉输出的多样性和独特性方面至关重要。 + - Comfy dtype: COMBO + - Python dtype: str +- scheduler + - ‘scheduler’参数管理采样计划,这对于平衡质量和计算效率之间的权衡至关重要。它在优化生成过程中起着重要作用。 + - Comfy dtype: COMBO + - Python dtype: str +- denoise + - ‘denoise’参数控制图像生成过程中应用的降噪水平。它影响最终图像的清晰度和平滑度。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - ‘seed’参数通过设置固定的随机种子来确保生成过程的可复现性。它对于在不同运行中获得一致的结果很重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- image_to_latent_c + - ‘image_to_latent_c’参数允许输入一个将被编码到潜在空间的图像。这使得用户可以为生成过程指定一个起点,影响输出的方向和风格。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- latent_c + - ‘latent_c’参数提供了潜在向量的直接输入,为用户提供了以更高精度控制生成过程的能力。这可以导致更细致和针对性的视觉输出。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- prompt + - ‘prompt’参数将文本指导引入生成过程,允许用户引导生成图像的内容和主题。它是实现特定创意愿景的重要工具。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - ‘extra_pnginfo’参数包含与输入图像相关的额外信息,可用于完善生成过程并提高输出与预期上下文的相关性。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, Any] +- my_unique_id + - ‘my_unique_id’参数用于跟踪和管理每个生成过程实例的唯一标识符。它对于保持多个并行或顺序操作的完整性和组织至关重要。 + - Comfy dtype: UNIQUE_ID + - Python dtype: Any + +# Output types +- pipe_line + - ‘pipe_line’输出是应用了所有设置的输入'pipe'的更新版本。它作为生成流水线后续阶段的基础,确保配置的参数在图像生成过程中被正确地传播和利用。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict + +# Usage tips +- Infra type: CPU + +# Source code +``` +class cascadeSettings: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'encode_vae_name': (['None'] + folder_paths.get_filename_list('vae'),), 'decode_vae_name': (['None'] + folder_paths.get_filename_list('vae'),), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'cfg': ('FLOAT', {'default': 4.0, 'min': 0.0, 'max': 100.0}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS, {'default': 'euler_ancestral'}), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS, {'default': 'simple'}), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': MAX_SEED_NUM})}, 'optional': {'image_to_latent_c': ('IMAGE',), 'latent_c': ('LATENT',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('pipe',) + OUTPUT_NODE = True + FUNCTION = 'settings' + CATEGORY = 'EasyUse/PreSampling' + + def settings(self, pipe, encode_vae_name, decode_vae_name, steps, cfg, sampler_name, scheduler, denoise, seed, model=None, image_to_latent_c=None, latent_c=None, prompt=None, extra_pnginfo=None, my_unique_id=None): + (images, samples_c) = (None, None) + samples = pipe['samples'] + batch_size = pipe['loader_settings']['batch_size'] if 'batch_size' in pipe['loader_settings'] else 1 + encode_vae_name = encode_vae_name if encode_vae_name is not None else pipe['loader_settings']['encode_vae_name'] + decode_vae_name = decode_vae_name if decode_vae_name is not None else pipe['loader_settings']['decode_vae_name'] + if image_to_latent_c is not None: + if encode_vae_name != 'None': + encode_vae = easyCache.load_vae(encode_vae_name) + else: + encode_vae = pipe['vae'][0] + if 'compression' not in pipe['loader_settings']: + raise Exception('compression is not found') + compression = pipe['loader_settings']['compression'] + width = image_to_latent_c.shape[-2] + height = image_to_latent_c.shape[-3] + out_width = width // compression * encode_vae.downscale_ratio + out_height = height // compression * encode_vae.downscale_ratio + s = comfy.utils.common_upscale(image_to_latent_c.movedim(-1, 1), out_width, out_height, 'bicubic', 'center').movedim(1, -1) + c_latent = encode_vae.encode(s[:, :, :, :3]) + b_latent = torch.zeros([c_latent.shape[0], 4, height // 4, width // 4]) + samples_c = {'samples': c_latent} + samples_c = RepeatLatentBatch().repeat(samples_c, batch_size)[0] + samples_b = {'samples': b_latent} + samples_b = RepeatLatentBatch().repeat(samples_b, batch_size)[0] + samples = (samples_c, samples_b) + images = image_to_latent_c + elif latent_c is not None: + samples_c = latent_c + samples = (samples_c, samples[1]) + images = pipe['images'] + if samples_c is not None: + samples = (samples_c, samples[1]) + new_pipe = {'model': pipe['model'], 'positive': pipe['positive'], 'negative': pipe['negative'], 'vae': pipe['vae'], 'clip': pipe['clip'], 'samples': samples, 'images': images, 'seed': seed, 'loader_settings': {**pipe['loader_settings'], 'encode_vae_name': encode_vae_name, 'decode_vae_name': decode_vae_name, 'steps': steps, 'cfg': cfg, 'sampler_name': sampler_name, 'scheduler': scheduler, 'denoise': denoise, 'add_noise': 'enabled'}} + sampler.update_value_by_id('pipe_line', my_unique_id, new_pipe) + del pipe + return {'ui': {'value': [seed]}, 'result': (new_pipe,)} +``` \ No newline at end of file diff --git a/docs/easy preSamplingDynamicCFG.md b/docs/easy preSamplingDynamicCFG.md new file mode 100644 index 0000000..7e5d4e1 --- /dev/null +++ b/docs/easy preSamplingDynamicCFG.md @@ -0,0 +1,122 @@ +# Documentation +- Class name: dynamicCFGSettings +- Category: EasyUse/PreSampling +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +dynamicCFGSettings节点旨在为给定的管道动态调整配置设置,根据指定的参数优化采样过程。它允许通过输入如steps、cfg和denoise等微调采样程序,这些输入共同影响输出管道的生成。 + +# Input types +## Required +- pipe + - pipe参数代表要配置的管道,对于节点的操作至关重要,因为它决定了设置将被应用的上下文。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- steps + - steps参数定义了采样过程中要采取的步骤数量,它直接影响采样的粒度和持续时间。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数是一个浮点值,用于调整采样过程的配置,影响整个过程的行为和输出质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- cfg_mode + - cfg_mode参数决定了配置缩放的模式,这对于控制采样设置的动态调整至关重要。 + - Comfy dtype: Enum + - Python dtype: Enum +- cfg_scale_min + - cfg_scale_min参数设置了配置的最小缩放值,确保动态调整不会低于指定的阈值。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数选择要使用的采样方法,这是塑造采样过程输出的关键决定因素。 + - Comfy dtype: Enum + - Python dtype: Enum +- scheduler + - scheduler参数决定了采样过程的调度策略,影响随着时间的推移步骤的管理方式。 + - Comfy dtype: Enum + - Python dtype: Enum +- denoise + - denoise参数控制采样过程中应用的降噪水平,可以提高结果的清晰度和质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - seed参数用于初始化随机数生成器,确保采样过程的可重复性。 + - Comfy dtype: INT + - Python dtype: int +- image_to_latent + - 当提供image_to_latent参数时,它被用来将图像转换为潜在表示,以便在采样管道中进行进一步处理。 + - Comfy dtype: IMAGE + - Python dtype: torch.Tensor +- latent + - 如果指定了latent参数,则表示在采样过程中将使用潜在空间数据而不是从图像派生它。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- prompt + - prompt参数是可选的文本输入,可用于指导采样过程,以生成与某些文本描述相符的输出。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - 如果存在extra_pnginfo参数,则包含与采样过程相关的额外信息,增强了对输入数据的上下文理解。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: str +- my_unique_id + - my_unique_id参数是可选的标识符,可用于跟踪或标记采样过程的特定实例。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- pipe + - 输出的pipe是应用了新设置的修改后的管道,准备用于后续的采样操作。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class dynamicCFGSettings: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'cfg': ('FLOAT', {'default': 8.0, 'min': 0.0, 'max': 100.0}), 'cfg_mode': (DynThresh.Modes,), 'cfg_scale_min': ('FLOAT', {'default': 3.5, 'min': 0.0, 'max': 100.0, 'step': 0.5}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': MAX_SEED_NUM})}, 'optional': {'image_to_latent': ('IMAGE',), 'latent': ('LATENT',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('pipe',) + OUTPUT_NODE = True + FUNCTION = 'settings' + CATEGORY = 'EasyUse/PreSampling' + + def settings(self, pipe, steps, cfg, cfg_mode, cfg_scale_min, sampler_name, scheduler, denoise, seed, image_to_latent=None, latent=None, prompt=None, extra_pnginfo=None, my_unique_id=None): + dynamic_thresh = DynThresh(7.0, 1.0, 'CONSTANT', 0, cfg_mode, cfg_scale_min, 0, 0, 999, False, 'MEAN', 'AD', 1) + + def sampler_dyn_thresh(args): + input = args['input'] + cond = input - args['cond'] + uncond = input - args['uncond'] + cond_scale = args['cond_scale'] + time_step = args['timestep'] + dynamic_thresh.step = 999 - time_step[0] + return input - dynamic_thresh.dynthresh(cond, uncond, cond_scale, None) + model = pipe['model'] + m = model.clone() + m.set_model_sampler_cfg_function(sampler_dyn_thresh) + vae = pipe['vae'] + batch_size = pipe['loader_settings']['batch_size'] if 'batch_size' in pipe['loader_settings'] else 1 + if image_to_latent is not None: + samples = {'samples': vae.encode(image_to_latent[:, :, :, :3])} + samples = RepeatLatentBatch().repeat(samples, batch_size)[0] + images = image_to_latent + elif latent is not None: + samples = RepeatLatentBatch().repeat(latent, batch_size)[0] + images = pipe['images'] + else: + samples = pipe['samples'] + images = pipe['images'] + new_pipe = {'model': m, 'positive': pipe['positive'], 'negative': pipe['negative'], 'vae': pipe['vae'], 'clip': pipe['clip'], 'samples': samples, 'images': images, 'seed': seed, 'loader_settings': {**pipe['loader_settings'], 'steps': steps, 'cfg': cfg, 'sampler_name': sampler_name, 'scheduler': scheduler, 'denoise': denoise}} + del pipe + return {'ui': {'value': [seed]}, 'result': (new_pipe,)} +``` \ No newline at end of file diff --git a/docs/easy preSamplingLayerDiffusion.md b/docs/easy preSamplingLayerDiffusion.md new file mode 100644 index 0000000..e45fbad --- /dev/null +++ b/docs/easy preSamplingLayerDiffusion.md @@ -0,0 +1,139 @@ +# Documentation +- Class name: layerDiffusionSettings +- Category: EasyUse/PreSampling +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点用于在神经网络流水线中自定义层扩散设置,使用户能够定义层间交互的方法以及影响生成过程的各种参数。 + +# Input types +## Required +- pipe + - ‘pipe’参数作为主要输入,将必要的数据和设置通过节点传递。它对节点的正确运行至关重要,确保后续操作在正确的上下文中执行。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict +- method + - ‘method’参数决定了层扩散的方法,这是节点操作的核心。它决定了模型的不同层如何相互作用并为最终输出做出贡献。 + - Comfy dtype: COMBO[LayerMethod] + - Python dtype: Enum[LayerMethod] +- weight + - ‘weight’参数调整层扩散过程的影响力。它在微调不同层对生成的贡献平衡方面起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- steps + - ‘steps’参数定义了层扩散过程将经历的迭代次数。它在控制层间交互的深度和粒度方面至关重要。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - ‘cfg’参数设置了层扩散过程的配置值,这对于调整模型的行为和实现期望的结果至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - ‘sampler_name’参数指定了在层扩散过程中使用的采样方法,这对于生成结果的多样性和质量至关重要。 + - Comfy dtype: COMBO[comfy.samplers.KSampler.SAMPLERS] + - Python dtype: Enum[comfy.samplers.KSampler.SAMPLERS] +- scheduler + - ‘scheduler’参数确定了层扩散过程的调度策略,这对于管理计算资源和实现高效执行至关重要。 + - Comfy dtype: COMBO[comfy.samplers.KSampler.SCHEDULERS] + - Python dtype: Enum[comfy.samplers.KSampler.SCHEDULERS] +- denoise + - ‘denoise’参数控制层扩散过程中应用的降噪水平。它通过影响生成内容的清晰度和细节,对最终输出的质量起着重要作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - ‘seed’参数在层扩散过程中引入随机性。它对于确保结果不重复并提供多种可能的结果很重要。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- image + - ‘image’参数提供了层扩散过程的视觉输入。它在确定生成输出的内容和上下文方面很重要。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or np.ndarray +- blended_image + - ‘blended_image’参数用于将不同的层或元素混合到最终输出中。它有助于生成视觉的复杂性和丰富性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image or np.ndarray +- mask + - ‘mask’参数用于定义在层扩散过程中应保留或操作的图像区域。它对于修复和选择性编辑任务至关重要。 + - Comfy dtype: MASK + - Python dtype: PIL.Image or np.ndarray +- prompt + - ‘prompt’参数为层扩散过程提供文本指导,影响生成内容的主题方向和风格。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - ‘extra_pnginfo’参数包含与图像相关的额外信息,可用于完善层扩散过程并实现更精确的结果。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: str +- my_unique_id + - ‘my_unique_id’参数用于跟踪和管理层扩散过程的唯一身份,确保结果的可追溯性和个性化。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- pipe + - ‘pipe’输出是输入的更新版本,包含层扩散过程的结果和进一步流水线操作调整后的设置。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict + +# Usage tips +- Infra type: CPU + +# Source code +``` +class layerDiffusionSettings: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'method': ([LayerMethod.FG_ONLY_ATTN.value, LayerMethod.FG_ONLY_CONV.value, LayerMethod.EVERYTHING.value, LayerMethod.FG_TO_BLEND.value, LayerMethod.BG_TO_BLEND.value],), 'weight': ('FLOAT', {'default': 1.0, 'min': -1, 'max': 3, 'step': 0.05}), '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, {'default': 'euler'}), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS, {'default': 'normal'}), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': MAX_SEED_NUM})}, 'optional': {'image': ('IMAGE',), 'blended_image': ('IMAGE',), 'mask': ('MASK',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('pipe',) + OUTPUT_NODE = True + FUNCTION = 'settings' + CATEGORY = 'EasyUse/PreSampling' + + def get_layer_diffusion_method(self, method, has_blend_latent): + method = LayerMethod(method) + if has_blend_latent: + if method == LayerMethod.BG_TO_BLEND: + method = LayerMethod.BG_BLEND_TO_FG + elif method == LayerMethod.FG_TO_BLEND: + method = LayerMethod.FG_BLEND_TO_BG + return method + + def settings(self, pipe, method, weight, steps, cfg, sampler_name, scheduler, denoise, seed, image=None, blended_image=None, mask=None, prompt=None, extra_pnginfo=None, my_unique_id=None): + blend_samples = pipe['blend_samples'] if 'blend_samples' in pipe else None + vae = pipe['vae'] + batch_size = pipe['loader_settings']['batch_size'] if 'batch_size' in pipe['loader_settings'] else 1 + method = self.get_layer_diffusion_method(method, blend_samples is not None or blended_image is not None) + if image is not None or 'image' in pipe: + image = image if image is not None else pipe['image'] + if mask is not None: + print('inpaint') + (samples,) = VAEEncodeForInpaint().encode(vae, image, mask) + else: + samples = {'samples': vae.encode(image[:, :, :, :3])} + samples = RepeatLatentBatch().repeat(samples, batch_size)[0] + images = image + elif 'samp_images' in pipe: + samples = {'samples': vae.encode(pipe['samp_images'][:, :, :, :3])} + samples = RepeatLatentBatch().repeat(samples, batch_size)[0] + images = pipe['samp_images'] + else: + if method not in [LayerMethod.FG_ONLY_ATTN, LayerMethod.FG_ONLY_CONV, LayerMethod.EVERYTHING]: + raise Exception('image is missing') + samples = pipe['samples'] + images = pipe['images'] + if method in [LayerMethod.BG_BLEND_TO_FG, LayerMethod.FG_BLEND_TO_BG]: + if blended_image is None and blend_samples is None: + raise Exception('blended_image is missing') + elif blended_image is not None: + blend_samples = {'samples': vae.encode(blended_image[:, :, :, :3])} + blend_samples = RepeatLatentBatch().repeat(blend_samples, batch_size)[0] + new_pipe = {'model': pipe['model'], 'positive': pipe['positive'], 'negative': pipe['negative'], 'vae': pipe['vae'], 'clip': pipe['clip'], 'samples': samples, 'blend_samples': blend_samples, 'images': images, 'seed': seed, 'loader_settings': {**pipe['loader_settings'], 'steps': steps, 'cfg': cfg, 'sampler_name': sampler_name, 'scheduler': scheduler, 'denoise': denoise, 'add_noise': 'enabled', 'layer_diffusion_method': method, 'layer_diffusion_weight': weight}} + del pipe + return {'ui': {'value': [seed]}, 'result': (new_pipe,)} +``` \ No newline at end of file diff --git a/docs/easy preSamplingLayerDiffusionADDTL.md b/docs/easy preSamplingLayerDiffusionADDTL.md new file mode 100644 index 0000000..c707187 --- /dev/null +++ b/docs/easy preSamplingLayerDiffusionADDTL.md @@ -0,0 +1,84 @@ +# Documentation +- Class name: layerDiffusionSettingsADDTL +- Category: EasyUse/PreSampling +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +此类节点负责设置层扩散模型的额外文本提示,以优化生成过程的输入条件。 + +# Input types +## Required +- pipe + - ‘pipe’参数是节点操作的基础,提供了扩散过程所需的重要上下文和数据。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict +- foreground_prompt + - 该参数允许用户输入前景提示,对于引导模型生成符合期望焦点的内容至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- background_prompt + - 通过提供背景提示,用户可以为模型建立上下文或设定场景,确保生成的内容与预期背景保持一致。 + - Comfy dtype: STRING + - Python dtype: str +- blended_prompt + - 混合提示参数允许结合多个提示,以创建更细致和详细的输出,从而增强生成内容的丰富性。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- optional_fg_cond + - 此可选参数为前景提供了额外的调节输入,提供了灵活性,以根据用户特定要求定制模型的生成。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- optional_bg_cond + - 同样,此可选参数扩展了背景的调节能力,允许更复杂和具有上下文的生成。 + - Comfy dtype: CONDITIONING + - Python dtype: Any +- optional_blended_cond + - 该参数提供了混合多个调节输入的方法,可以实现更和谐和综合的生成结果。 + - Comfy dtype: CONDITIONING + - Python dtype: Any + +# Output types +- pipe + - 更新后的‘pipe’输出包含新的层扩散条件,这对于流水线中的后续步骤至关重要。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict + +# Usage tips +- Infra type: CPU + +# Source code +``` +class layerDiffusionSettingsADDTL: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'foreground_prompt': ('STRING', {'default': '', 'placeholder': 'Foreground Additional Prompt', 'multiline': True}), 'background_prompt': ('STRING', {'default': '', 'placeholder': 'Background Additional Prompt', 'multiline': True}), 'blended_prompt': ('STRING', {'default': '', 'placeholder': 'Blended Additional Prompt', 'multiline': True})}, 'optional': {'optional_fg_cond': ('CONDITIONING',), 'optional_bg_cond': ('CONDITIONING',), 'optional_blended_cond': ('CONDITIONING',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('pipe',) + OUTPUT_NODE = True + FUNCTION = 'settings' + CATEGORY = 'EasyUse/PreSampling' + + def settings(self, pipe, foreground_prompt, background_prompt, blended_prompt, optional_fg_cond=None, optional_bg_cond=None, optional_blended_cond=None, prompt=None, extra_pnginfo=None, my_unique_id=None): + (fg_cond, bg_cond, blended_cond) = (None, None, None) + clip = pipe['clip'] + if optional_fg_cond is not None: + fg_cond = optional_fg_cond + elif foreground_prompt != '': + (fg_cond,) = CLIPTextEncode().encode(clip, foreground_prompt) + if optional_bg_cond is not None: + bg_cond = optional_bg_cond + elif background_prompt != '': + (bg_cond,) = CLIPTextEncode().encode(clip, background_prompt) + if optional_blended_cond is not None: + blended_cond = optional_blended_cond + elif blended_prompt != '': + (blended_cond,) = CLIPTextEncode().encode(clip, blended_prompt) + new_pipe = {**pipe, 'loader_settings': {**pipe['loader_settings'], 'layer_diffusion_cond': (fg_cond, bg_cond, blended_cond)}} + del pipe + return (new_pipe,) +``` \ No newline at end of file diff --git a/docs/easy preSamplingNoiseIn.md b/docs/easy preSamplingNoiseIn.md new file mode 100644 index 0000000..ff77ec5 --- /dev/null +++ b/docs/easy preSamplingNoiseIn.md @@ -0,0 +1,141 @@ +# Documentation +- Class name: samplerSettingsNoiseIn +- Category: EasyUse/PreSampling +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点旨在为采样过程配置和应用噪声设置,这可以增强生成样本的多样性和质量。它允许调整噪声因素和调度,有助于实现更精细和可控的生成工作流程。 + +# Input types +## Required +- pipe + - ‘pipe’参数是必要的,因为它携带了正在处理的模型和样本的必要信息。它是节点操作的支柱,促进了应用噪声和后续采样步骤所需的数据流。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- factor + - ‘factor’参数在确定采样过程中引入的噪声程度方面至关重要。它直接影响原始噪声和变化噪声之间的平衡,从而影响最终输出的多样性和一致性。 + - Comfy dtype: FLOAT + - Python dtype: float +- steps + - ‘steps’参数定义了采样过程将要经历的迭代次数。它很重要,因为它决定了采样的复杂性和深度,更多的步骤可能导致更精细的结果。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - ‘cfg’参数用于微调采样过程的配置。它在调整节点的整体行为方面发挥作用,确保采样按照期望的规格进行。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - ‘sampler_name’参数在选择合适的采样方法方面至关重要。它影响生成样本时采用的策略,不同的采样器提供不同的噪声应用和样本多样性方法。 + - Comfy dtype: COMBO + - Python dtype: str +- scheduler + - ‘scheduler’参数在管理采样步骤中噪声的应用方面很重要。它有助于控制引入噪声的速度,确保从采样过程的一个阶段平稳过渡到下一个阶段。 + - Comfy dtype: COMBO + - Python dtype: str +- denoise + - ‘denoise’参数负责指定要应用的去噪水平。它影响生成样本的清晰度和锐度,较高的值导致更清晰的输出。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - ‘seed’参数对于确保采样过程中的可重复性至关重要。它初始化随机数生成器,允许在不同运行中使用相同设置时获得一致的结果。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- pipe + - ‘pipe’输出是输入‘pipe’的修改版本,现在包含调整后的噪声设置和生成的样本。它是节点处理的成果,封装了增强的采样数据以供进一步使用。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class samplerSettingsNoiseIn: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'factor': ('FLOAT', {'default': 0.1, 'min': 0.0, 'max': 1.0, 'step': 0.01, 'round': 0.01}), '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': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': MAX_SEED_NUM})}, 'optional': {'optional_noise_seed': ('INT', {'forceInput': True}), 'optional_latent': ('LATENT',)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('pipe',) + OUTPUT_NODE = True + FUNCTION = 'settings' + CATEGORY = 'EasyUse/PreSampling' + + def slerp(self, val, low, high): + dims = low.shape + low = low.reshape(dims[0], -1) + high = high.reshape(dims[0], -1) + low_norm = low / torch.norm(low, dim=1, keepdim=True) + high_norm = high / torch.norm(high, dim=1, keepdim=True) + low_norm[low_norm != low_norm] = 0.0 + high_norm[high_norm != high_norm] = 0.0 + omega = torch.acos((low_norm * high_norm).sum(1)) + so = torch.sin(omega) + res = (torch.sin((1.0 - val) * omega) / so).unsqueeze(1) * low + (torch.sin(val * omega) / so).unsqueeze(1) * high + return res.reshape(dims) + + def prepare_mask(self, mask, shape): + mask = torch.nn.functional.interpolate(mask.reshape((-1, 1, mask.shape[-2], mask.shape[-1])), size=(shape[2], shape[3]), mode='bilinear') + mask = mask.expand((-1, shape[1], -1, -1)) + if mask.shape[0] < shape[0]: + mask = mask.repeat((shape[0] - 1) // mask.shape[0] + 1, 1, 1, 1)[:shape[0]] + return mask + + def expand_mask(self, mask, expand, tapered_corners): + try: + import numpy as np + import scipy + c = 0 if tapered_corners else 1 + kernel = np.array([[c, 1, c], [1, 1, 1], [c, 1, c]]) + mask = mask.reshape((-1, mask.shape[-2], mask.shape[-1])) + out = [] + for m in mask: + output = m.numpy() + for _ in range(abs(expand)): + if expand < 0: + output = scipy.ndimage.grey_erosion(output, footprint=kernel) + else: + output = scipy.ndimage.grey_dilation(output, footprint=kernel) + output = torch.from_numpy(output) + out.append(output) + return torch.stack(out, dim=0) + except: + return None + + def settings(self, pipe, factor, steps, cfg, sampler_name, scheduler, denoise, seed, optional_noise_seed=None, optional_latent=None, prompt=None, extra_pnginfo=None, my_unique_id=None): + latent = optional_latent if optional_latent is not None else pipe['samples'] + model = pipe['model'] + (batch_size, _, height, width) = latent['samples'].shape + generator = torch.manual_seed(seed) + base_noise = torch.randn((1, 4, height, width), dtype=torch.float32, device='cpu', generator=generator).repeat(batch_size, 1, 1, 1).cpu() + if optional_noise_seed is None or optional_noise_seed == seed: + optional_noise_seed = seed + 1 + generator = torch.manual_seed(optional_noise_seed) + variation_noise = torch.randn((batch_size, 4, height, width), dtype=torch.float32, device='cpu', generator=generator).cpu() + slerp_noise = self.slerp(factor, base_noise, variation_noise) + end_at_step = steps + start_at_step = round(end_at_step - end_at_step * denoise) + device = comfy.model_management.get_torch_device() + comfy.model_management.load_model_gpu(model) + model_patcher = comfy.model_patcher.ModelPatcher(model.model, load_device=device, offload_device=comfy.model_management.unet_offload_device()) + sampler = comfy.samplers.KSampler(model_patcher, steps=steps, device=device, sampler=sampler_name, scheduler=scheduler, denoise=1.0, model_options=model.model_options) + sigmas = sampler.sigmas + sigma = sigmas[start_at_step] - sigmas[end_at_step] + sigma /= model.model.latent_format.scale_factor + sigma = sigma.cpu().numpy() + work_latent = latent.copy() + work_latent['samples'] = latent['samples'].clone() + slerp_noise * sigma + if 'noise_mask' in latent: + noise_mask = self.prepare_mask(latent['noise_mask'], latent['samples'].shape) + work_latent['samples'] = noise_mask * work_latent['samples'] + (1 - noise_mask) * latent['samples'] + work_latent['noise_mask'] = self.expand_mask(latent['noise_mask'].clone(), 5, True) + if pipe is None: + pipe = {} + new_pipe = {'model': pipe['model'], 'positive': pipe['positive'], 'negative': pipe['negative'], 'vae': pipe['vae'], 'clip': pipe['clip'], 'samples': work_latent, 'images': pipe['images'], 'seed': seed, 'loader_settings': {**pipe['loader_settings'], 'steps': steps, 'cfg': cfg, 'sampler_name': sampler_name, 'scheduler': scheduler, 'denoise': denoise, 'add_noise': 'disable'}} + return (new_pipe,) +``` \ No newline at end of file diff --git a/docs/easy preSamplingSdTurbo.md b/docs/easy preSamplingSdTurbo.md new file mode 100644 index 0000000..e4a7ae9 --- /dev/null +++ b/docs/easy preSamplingSdTurbo.md @@ -0,0 +1,118 @@ +# Documentation +- Class name: sdTurboSettings +- Category: EasyUse/PreSampling +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +sdTurboSettings节点通过配置一系列增强样本质量和可控性的参数来简化采样过程。它旨在与采样流水线无缝集成,提供满足不同创意需求和计算限制的广泛选项。 + +# Input types +## Required +- pipe + - pipe参数是节点的主干,封装了整个采样流水线及其相关数据。它对节点的正确运行和采样过程的完整性至关重要。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- steps + - steps参数决定了采样过程将经历的迭代次数,直接影响生成样本的深度和多样性。这是实现预期结果的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数调整模型的配置,微调采样过程以产生符合用户期望的样本。它在输出的整体质量中起着关键作用。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数从预定义的选项中选择采样方法,每种方法都提供独特的特性和优势。它在塑造节点的创意方向和计算效率方面至关重要。 + - Comfy dtype: COMBO + - Python dtype: str +- eta + - eta参数影响采样过程中的噪声水平,影响生成图像的清晰度和细节。它是实现质量和计算效率之间平衡的关键控制。 + - Comfy dtype: FLOAT + - Python dtype: float +- s_noise + - s_noise参数调整信噪比,这对于确保生成样本的保真度至关重要。它有助于保持高标准的输出质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- upscale_ratio + - upscale_ratio参数决定了生成图像的缩放因子,这对于实现期望的分辨率和视觉冲击力至关重要。它显著影响样本的最终呈现。 + - Comfy dtype: FLOAT + - Python dtype: float +- start_step + - start_step参数设置了采样过程开始的初始点,影响样本的进展和发展。它对于控制整体采样轨迹非常重要。 + - Comfy dtype: INT + - Python dtype: int +- end_step + - end_step参数定义了采样过程结束的最终点,影响样本的持续时间和完整性。它对于管理采样时间线至关重要。 + - Comfy dtype: INT + - Python dtype: int +- upscale_n_step + - upscale_n_step参数指定了图像放大的步数,这对于在不损害质量的情况下实现高分辨率结果至关重要。它在最终输出的提升中起着关键作用。 + - Comfy dtype: INT + - Python dtype: int +- unsharp_kernel_size + - unsharp_kernel_size参数调整锐化遮罩的核大小,这对于增强图像的锐度和清晰度至关重要。它显著提升了输出的视觉质量。 + - Comfy dtype: INT + - Python dtype: int +- unsharp_sigma + - unsharp_sigma参数控制锐化遮罩的sigma值,影响锐度增强的程度。它是实现预期视觉效果的重要因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- unsharp_strength + - unsharp_strength参数决定了锐化遮罩效果的强度,影响图像的整体锐度和细节。它对于微调样本的视觉吸引力至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +- seed + - seed参数通过为随机数生成提供固定点来确保采样过程的可重复性。它对于在不同运行中获得一致的结果至关重要。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- pipe + - 输出pipe是输入pipe的更新版本,现在配备了配置的设置,并准备好进入采样过程的下一阶段。它对于流水线的连续性和进展至关重要。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class sdTurboSettings: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'pipe': ('PIPE_LINE',), 'steps': ('INT', {'default': 1, 'min': 1, 'max': 10}), 'cfg': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 100.0}), 'sampler_name': (comfy.samplers.SAMPLER_NAMES,), 'eta': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01, 'round': False}), 's_noise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.01, 'round': False}), 'upscale_ratio': ('FLOAT', {'default': 2.0, 'min': 0.0, 'max': 16.0, 'step': 0.01, 'round': False}), 'start_step': ('INT', {'default': 5, 'min': 0, 'max': 1000, 'step': 1}), 'end_step': ('INT', {'default': 15, 'min': 0, 'max': 1000, 'step': 1}), 'upscale_n_step': ('INT', {'default': 3, 'min': 0, 'max': 1000, 'step': 1}), 'unsharp_kernel_size': ('INT', {'default': 3, 'min': 1, 'max': 21, 'step': 1}), 'unsharp_sigma': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 10.0, 'step': 0.01, 'round': False}), 'unsharp_strength': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 10.0, 'step': 0.01, 'round': False}), 'seed': ('INT', {'default': 0, 'min': 0, 'max': MAX_SEED_NUM})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('pipe',) + OUTPUT_NODE = True + FUNCTION = 'settings' + CATEGORY = 'EasyUse/PreSampling' + + def settings(self, pipe, steps, cfg, sampler_name, eta, s_noise, upscale_ratio, start_step, end_step, upscale_n_step, unsharp_kernel_size, unsharp_sigma, unsharp_strength, seed, prompt=None, extra_pnginfo=None, my_unique_id=None): + model = pipe['model'] + timesteps = torch.flip(torch.arange(1, 11) * 100 - 1, (0,))[:steps] + sigmas = model.model.model_sampling.sigma(timesteps) + sigmas = torch.cat([sigmas, sigmas.new_zeros([1])]) + sample_function = None + extra_options = {'eta': eta, 's_noise': s_noise, 'upscale_ratio': upscale_ratio, 'start_step': start_step, 'end_step': end_step, 'upscale_n_step': upscale_n_step, 'unsharp_kernel_size': unsharp_kernel_size, 'unsharp_sigma': unsharp_sigma, 'unsharp_strength': unsharp_strength} + if sampler_name == 'euler_ancestral': + sample_function = sample_euler_ancestral + elif sampler_name == 'dpmpp_2s_ancestral': + sample_function = sample_dpmpp_2s_ancestral + elif sampler_name == 'dpmpp_2m_sde': + sample_function = sample_dpmpp_2m_sde + elif sampler_name == 'lcm': + sample_function = sample_lcm + if sample_function is not None: + unsharp_kernel_size = unsharp_kernel_size if unsharp_kernel_size % 2 == 1 else unsharp_kernel_size + 1 + extra_options['unsharp_kernel_size'] = unsharp_kernel_size + _sampler = comfy.samplers.KSAMPLER(sample_function, extra_options) + else: + _sampler = comfy.samplers.sampler_object(sampler_name) + extra_options = None + new_pipe = {'model': pipe['model'], 'positive': pipe['positive'], 'negative': pipe['negative'], 'vae': pipe['vae'], 'clip': pipe['clip'], 'samples': pipe['samples'], 'images': pipe['images'], 'seed': seed, 'loader_settings': {**pipe['loader_settings'], 'extra_options': extra_options, 'sampler': _sampler, 'sigmas': sigmas, 'steps': steps, 'cfg': cfg, 'add_noise': 'enabled'}} + del pipe + return {'ui': {'value': [seed]}, 'result': (new_pipe,)} +``` \ No newline at end of file diff --git a/docs/easy promptConcat.md b/docs/easy promptConcat.md new file mode 100644 index 0000000..75b6584 --- /dev/null +++ b/docs/easy promptConcat.md @@ -0,0 +1,48 @@ +# Documentation +- Class name: promptConcat +- Category: EasyUse/Prompt +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点便于文本输入的拼接,提供了一个简单的方法来将字符串组合成一个单一的输出。它强调简单易用性,非常适合在不需要复杂处理的情况下进行文本操作的场景。 + +# Input types +## Required +- prompt1 + - 第一个文本输入,在拼接过程中作为初始段。它至关重要,因为它为组合文本输出设定了起始点。 + - Comfy dtype: STRING + - Python dtype: str +- prompt2 + - 第二个文本输入,跟随第一个输入进行拼接。它对于完成文本序列和形成最终输出至关重要。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- separator + - 一个插入在两个文本输入之间的字符串,用于在最终输出中分隔它们。它在构建拼接文本和提高可读性方面发挥作用。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- prompt + - 两个输入拼接后的结果文本输出,可能包含分隔符。它代表了输入中的合并和结构化信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class promptConcat: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {}, 'optional': {'prompt1': ('STRING', {'multiline': False, 'default': '', 'forceInput': True}), 'prompt2': ('STRING', {'multiline': False, 'default': '', 'forceInput': True}), 'separator': ('STRING', {'multiline': False, 'default': ''})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('prompt',) + FUNCTION = 'concat_text' + CATEGORY = 'EasyUse/Prompt' + + def concat_text(self, prompt1='', prompt2='', separator=''): + return (prompt1 + separator + prompt2,) +``` \ No newline at end of file diff --git a/docs/easy promptLine.md b/docs/easy promptLine.md new file mode 100644 index 0000000..16b5b9a --- /dev/null +++ b/docs/easy promptLine.md @@ -0,0 +1,52 @@ +# Documentation +- Class name: promptLine +- Category: EasyUse/Prompt +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点旨在根据给定的提示生成文本内容,并能够控制起始点和生成的行数。它通过将输入提示分割成行并提取指定范围来运作,从而使用户能够获得目标化的文本输出。 + +# Input types +## Required +- prompt + - 提示是节点用来生成新内容的基础文本。它作为生成文本的上下文或灵感来源,没有它,节点将不会产出任何输出。 + - Comfy dtype: STRING + - Python dtype: str +- start_index + - 该参数指定节点将从哪一行开始提取文本。它对于确定将要处理的提示的具体部分并将其转化为输出至关重要。 + - Comfy dtype: INT + - Python dtype: int +- max_rows + - 该参数设置了从提示中提取的最大行数。它直接影响节点生成的内容量,确保输出既不过于简短也不过于冗长。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- STRING + - 输出是从输入提示中选取的文本,从指定的索引开始,跨越定义的行数。它代表了节点的主要功能和其处理的直接结果。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class promptLine: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'prompt': ('STRING', {'multiline': True, 'default': 'text'}), 'start_index': ('INT', {'default': 0, 'min': 0, 'max': 9999}), 'max_rows': ('INT', {'default': 1000, 'min': 1, 'max': 9999})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('STRING',) + OUTPUT_IS_LIST = (True,) + FUNCTION = 'generate_strings' + CATEGORY = 'EasyUse/Prompt' + + def generate_strings(self, prompt, start_index, max_rows): + lines = prompt.split('\n') + start_index = max(0, min(start_index, len(lines) - 1)) + end_index = min(start_index + max_rows, len(lines)) + rows = lines[start_index:end_index] + return (rows,) +``` \ No newline at end of file diff --git a/docs/easy promptList.md b/docs/easy promptList.md new file mode 100644 index 0000000..15102c6 --- /dev/null +++ b/docs/easy promptList.md @@ -0,0 +1,73 @@ +# Documentation +- Class name: promptList +- Category: EasyUse/Prompt +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点简化了聚合和处理文本输入的过程,便于在各种应用中生成提示列表。它强调高效处理字符串数据,确保节点在工作流中的角色是集中和组织文本信息。 + +# Input types +## Required +- prompt_1 + - 主要的文本输入,作为节点操作的基础。它至关重要,因为它为后续的提示处理和聚合设定了初始上下文。 + - Comfy dtype: STRING + - Python dtype: str +- prompt_2 + - 额外的文本输入,增加了正在处理的提示的多样性和复杂性。它增强了节点处理各种文本输入的能力。 + - Comfy dtype: STRING + - Python dtype: str +- prompt_3 + - 进一步的文本输入,对于节点整合和管理多个提示的功能至关重要,确保对文本处理采取全面的方法。 + - Comfy dtype: STRING + - Python dtype: str +- prompt_4 + - 另一个对于节点有效组织和构建提示至关重要的输入,影响最终输出的连贯性和相关性。 + - Comfy dtype: STRING + - Python dtype: str +- prompt_5 + - 最后的文本输入,完善了提示集,确保节点可以处理广泛的文本输入并保持整体提示列表的完整性。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- optional_prompt_list + - 一个可选的提示列表,提供后,扩展了节点管理和处理更大量文本数据的能力,增强了输出的全面性。 + - Comfy dtype: LIST + - Python dtype: List[str] + +# Output types +- prompt_list + - 一个整合的提示列表,代表节点的输出,以结构化和有序的方式封装了处理过的文本输入。 + - Comfy dtype: LIST + - Python dtype: List[str] +- prompt_strings + - 提示列表的序列化版本,将聚合的文本数据呈现为单个字符串,便于在后续应用中使用。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class promptList: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'prompt_1': ('STRING', {'multiline': True, 'default': ''}), 'prompt_2': ('STRING', {'multiline': True, 'default': ''}), 'prompt_3': ('STRING', {'multiline': True, 'default': ''}), 'prompt_4': ('STRING', {'multiline': True, 'default': ''}), 'prompt_5': ('STRING', {'multiline': True, 'default': ''})}, 'optional': {'optional_prompt_list': ('LIST',)}} + RETURN_TYPES = ('LIST', 'STRING') + RETURN_NAMES = ('prompt_list', 'prompt_strings') + OUTPUT_IS_LIST = (False, True) + FUNCTION = 'run' + CATEGORY = 'EasyUse/Prompt' + + def run(self, **kwargs): + prompts = [] + if 'optional_prompt_list' in kwargs: + for l in kwargs['optional_prompt_list']: + prompts.append(l) + for k in sorted(kwargs.keys()): + v = kwargs[k] + if isinstance(v, str) and v != '': + prompts.append(v) + return (prompts, prompts) +``` \ No newline at end of file diff --git a/docs/easy promptReplace.md b/docs/easy promptReplace.md new file mode 100644 index 0000000..a09479e --- /dev/null +++ b/docs/easy promptReplace.md @@ -0,0 +1,67 @@ +# Documentation +- Class name: promptReplace +- Category: EasyUse/Prompt +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点通过识别并替换给定文本中的指定子字符串来促进文本转换过程。其主要目的是简化编辑过程,使用户能够高效地进行目标修改。 + +# Input types +## Required +- prompt + - ‘prompt’参数是节点操作的基础,代表将要进行替换处理的文本。它至关重要,因为它决定了替换发生的内容和上下文。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- find1 + - ‘find1’参数指定了文本中要识别并替换的第一个子字符串。其重要性在于编辑的目标性,有助于节点进行精确的修改。 + - Comfy dtype: STRING + - Python dtype: str +- replace1 + - ‘replace1’参数定义了将替换识别出的‘find1’子字符串的文本。它是转换过程中不可或缺的一部分,因为它决定了替换的结果。 + - Comfy dtype: STRING + - Python dtype: str +- find2 + - ‘find2’参数用于识别并替换文本中的第二组子字符串。其作用是扩展节点的编辑能力,允许进行多个目标替换。 + - Comfy dtype: STRING + - Python dtype: str +- replace2 + - ‘replace2’参数对应于将替换‘find2’子字符串的文本,进一步促进整体文本转换过程。 + - Comfy dtype: STRING + - Python dtype: str +- find3 + - ‘find3’参数用于识别并替换第三组子字符串,增强了节点在文本编辑中的多功能性和适应性。 + - Comfy dtype: STRING + - Python dtype: str +- replace3 + - ‘replace3’参数用于最终替换,确保节点能够在单一操作中解决各种编辑需求。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- prompt + - 输出‘prompt’是应用了所有指定替换的修改后的文本。它代表了节点功能的最终成果,为用户提供了原始文本的更新版本。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class promptReplace: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'prompt': ('STRING', {'multiline': True, 'default': '', 'forceInput': True})}, 'optional': {'find1': ('STRING', {'multiline': False, 'default': ''}), 'replace1': ('STRING', {'multiline': False, 'default': ''}), 'find2': ('STRING', {'multiline': False, 'default': ''}), 'replace2': ('STRING', {'multiline': False, 'default': ''}), 'find3': ('STRING', {'multiline': False, 'default': ''}), 'replace3': ('STRING', {'multiline': False, 'default': ''})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('prompt',) + FUNCTION = 'replace_text' + CATEGORY = 'EasyUse/Prompt' + + def replace_text(self, text, find1='', replace1='', find2='', replace2='', find3='', replace3=''): + text = text.replace(find1, replace1) + text = text.replace(find2, replace2) + text = text.replace(find3, replace3) + return (text,) +``` \ No newline at end of file diff --git a/docs/easy rangeFloat.md b/docs/easy rangeFloat.md new file mode 100644 index 0000000..3281632 --- /dev/null +++ b/docs/easy rangeFloat.md @@ -0,0 +1,100 @@ +# Documentation +- Class name: RangeFloat +- Category: EasyUse/Logic/Type +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点便于在指定范围内生成一系列浮点数,根据用户定义的模式和参数。它抽象了创建范围的过程,允许对起始值、终止值和步长值进行精确控制,以及步数和端点的包含性。 + +# Input types +## Required +- range_mode + - 模式参数决定了生成范围序列所用的逻辑。它是必要的,因为它为节点设置了操作上下文,决定了范围是由固定的'步长'还是指定的'步数'生成。 + - Comfy dtype: COMBO[String] + - Python dtype: str +- start + - 起始参数定义了范围的初始值。它至关重要,因为它设定了生成范围序列的基线,影响整个输出。 + - Comfy dtype: FLOAT + - Python dtype: decimal.Decimal +- stop + - 终止参数标记了范围的终点。它很重要,因为它与起始值一起,定义了生成范围序列的边界。 + - Comfy dtype: FLOAT + - Python dtype: decimal.Decimal +- step + - 步长参数决定了范围序列中每个值之间的增量。它的值直接影响生成序列的粒度和模式。 + - Comfy dtype: FLOAT + - Python dtype: decimal.Decimal +- end_mode + - 结束模式参数决定终止值是否包含在范围序列中。这影响了终点的包含性,从而影响了输出的组成。 + - Comfy dtype: COMBO[String] + - Python dtype: str +## Optional +- num_steps + - 步数参数指定了范围序列中期望的步数。它很重要,因为它直接影响节点产生的值的数量。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- range + - 范围输出提供了生成的浮点数序列,这是节点操作的核心结果。它封装了范围生成过程的精髓。 + - Comfy dtype: LIST[FLOAT] + - Python dtype: List[float] +- range_sizes + - 范围大小输出提供了每个单独生成的范围序列中的值的数量,提供了对输出的分布和结构的洞察。 + - Comfy dtype: LIST(INT) + - Python dtype: List[int] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RangeFloat: + + def __init__(self) -> None: + pass + + @classmethod + def INPUT_TYPES(s) -> Dict[str, Dict[str, Any]]: + return {'required': {'range_mode': (['step', 'num_steps'], {'default': 'step'}), 'start': ('FLOAT', {'default': 0, 'min': -4096, 'max': 4096, 'step': 0.1}), 'stop': ('FLOAT', {'default': 0, 'min': -4096, 'max': 4096, 'step': 0.1}), 'step': ('FLOAT', {'default': 0, 'min': -4096, 'max': 4096, 'step': 0.1}), 'num_steps': ('INT', {'default': 0, 'min': -4096, 'max': 4096, 'step': 1}), 'end_mode': (['Inclusive', 'Exclusive'], {'default': 'Inclusive'})}} + RETURN_TYPES = ('FLOAT', 'INT') + RETURN_NAMES = ('range', 'range_sizes') + INPUT_IS_LIST = True + OUTPUT_IS_LIST = (True, True) + FUNCTION = 'build_range' + CATEGORY = 'EasyUse/Logic/Type' + + @staticmethod + def _decimal_range(range_mode: String, start: Decimal, stop: Decimal, step: Decimal, num_steps: Int, inclusive: bool) -> Iterator[float]: + if range_mode == 'step': + ret_val = start + if inclusive: + stop = stop + step + direction = 1 if step > 0 else -1 + while (ret_val - stop) * direction < 0: + yield float(ret_val) + ret_val += step + elif range_mode == 'num_steps': + step = (stop - start) / (num_steps - 1) + direction = 1 if step > 0 else -1 + ret_val = start + for _ in range(num_steps): + if (ret_val - stop) * direction > 0: + break + yield float(ret_val) + ret_val += step + + def build_range(self, range_mode, start, stop, step, num_steps, end_mode) -> Tuple[List[float], List[int]]: + error_if_mismatched_list_args(locals()) + getcontext().prec = 12 + start = [Decimal(s) for s in start] + stop = [Decimal(s) for s in stop] + step = [Decimal(s) for s in step] + ranges = [] + range_sizes = [] + for (range_mode, e_start, e_stop, e_step, e_num_steps, e_end_mode) in zip_with_fill(range_mode, start, stop, step, num_steps, end_mode): + vals = list(self._decimal_range(range_mode, e_start, e_stop, e_step, e_num_steps, e_end_mode == 'Inclusive')) + ranges.extend(vals) + range_sizes.append(len(vals)) + return (ranges, range_sizes) +``` \ No newline at end of file diff --git a/docs/easy rangeInt.md b/docs/easy rangeInt.md new file mode 100644 index 0000000..fad0a38 --- /dev/null +++ b/docs/easy rangeInt.md @@ -0,0 +1,85 @@ +# Documentation +- Class name: RangeInt +- Category: EasyUse/Logic/Type +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +RangeInt类封装了根据用户定义的参数生成一系列整数的逻辑,便于为各种应用创建数值范围。 + +# Input types +## Required +- range_mode + - range_mode参数决定了范围生成的方法,是通过固定的'step'大小还是指定的'num_steps'。这对于确定输出范围的结构和分布至关重要。 + - Comfy dtype: COMBO[str] + - Python dtype: str +- start + - start参数定义了范围的初始值。它至关重要,因为它设置了生成的整数序列的起点。 + - Comfy dtype: INT + - Python dtype: int +- stop + - stop参数指定了范围的上限。它与start参数共同作用,确定了整数序列的范围。 + - Comfy dtype: INT + - Python dtype: int +- step + - step参数设置了范围中每个元素之间的增量值。它显著影响生成序列的进程和间距。 + - Comfy dtype: INT + - Python dtype: int +- num_steps + - num_steps参数定义了范围内期望的步数。它对于确定输出序列的粒度很重要。 + - Comfy dtype: INT + - Python dtype: int +- end_mode + - end_mode参数规定了范围中停止值是包含还是不包含。这影响了生成序列中是否包含上限。 + - Comfy dtype: COMBO[str] + - Python dtype: str + +# Output types +- range + - range输出是根据输入参数生成的整数列表,代表定义范围内的值序列。 + - Comfy dtype: LIST[INT] + - Python dtype: List[int] +- range_sizes + - range_sizes输出提供了每个单独生成的范围中整数的计数,提供了值分布的洞察。 + - Comfy dtype: LIST[INT] + - Python dtype: List[int] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class RangeInt: + + def __init__(self) -> None: + pass + + @classmethod + def INPUT_TYPES(s) -> Dict[str, Dict[str, Any]]: + return {'required': {'range_mode': (['step', 'num_steps'], {'default': 'step'}), 'start': ('INT', {'default': 0, 'min': -4096, 'max': 4096, 'step': 1}), 'stop': ('INT', {'default': 0, 'min': -4096, 'max': 4096, 'step': 1}), 'step': ('INT', {'default': 0, 'min': -4096, 'max': 4096, 'step': 1}), 'num_steps': ('INT', {'default': 0, 'min': -4096, 'max': 4096, 'step': 1}), 'end_mode': (['Inclusive', 'Exclusive'], {'default': 'Inclusive'})}} + RETURN_TYPES = ('INT', 'INT') + RETURN_NAMES = ('range', 'range_sizes') + INPUT_IS_LIST = True + OUTPUT_IS_LIST = (True, True) + FUNCTION = 'build_range' + CATEGORY = 'EasyUse/Logic/Type' + + def build_range(self, range_mode, start, stop, step, num_steps, end_mode) -> Tuple[List[int], List[int]]: + error_if_mismatched_list_args(locals()) + ranges = [] + range_sizes = [] + for (range_mode, e_start, e_stop, e_num_steps, e_step, e_end_mode) in zip_with_fill(range_mode, start, stop, num_steps, step, end_mode): + if range_mode == 'step': + if e_end_mode == 'Inclusive': + e_stop += 1 + vals = list(range(e_start, e_stop, e_step)) + ranges.extend(vals) + range_sizes.append(len(vals)) + elif range_mode == 'num_steps': + direction = 1 if e_stop > e_start else -1 + if e_end_mode == 'Exclusive': + e_stop -= direction + vals = np.rint(np.linspace(e_start, e_stop, e_num_steps)).astype(int).tolist() + ranges.extend(vals) + range_sizes.append(len(vals)) + return (ranges, range_sizes) +``` \ No newline at end of file diff --git a/docs/easy samLoaderPipe.md b/docs/easy samLoaderPipe.md new file mode 100644 index 0000000..bc461aa --- /dev/null +++ b/docs/easy samLoaderPipe.md @@ -0,0 +1,72 @@ +# Documentation +- Class name: samLoaderForDetailerFix +- Category: EasyUse/Fix +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +samLoaderForDetailerFix节点是整合和使用SAM(Stable Diffusion)模型过程中的关键组件。它旨在简化模型的加载和应用,确保其在给定上下文中高效有效地运行。该节点的功能集中在为详细的图像处理任务(如分割和增强)准备模型,通过配置影响模型检测和处理能力的多个参数。 + +# Input types +## Required +- model_name + - model_name参数指定要加载的SAM模型的名称。它在识别和启动后续图像处理任务的正确模型中起着至关重要的作用。 + - Comfy dtype: str + - Python dtype: str +- device_mode + - device_mode参数确定用于运行SAM模型的计算设备。它对于优化性能和确保与系统硬件能力兼容至关重要。 + - Comfy dtype: str + - Python dtype: str +- sam_detection_hint + - sam_detection_hint参数为SAM模型提供检测策略的指导。它对于微调模型的检测精度以及对不同类型的输入图像的响应非常重要。 + - Comfy dtype: str + - Python dtype: str +- sam_dilation + - sam_dilation参数调整SAM模型检测过程中使用的扩张因子。它能够显著影响模型捕获图像中细节的能力。 + - Comfy dtype: int + - Python dtype: int +- sam_threshold + - sam_threshold参数设置SAM模型检测的置信度阈值。它是控制检测结果中精确度和召回率平衡的关键因素。 + - Comfy dtype: float + - Python dtype: float +- sam_bbox_expansion + - sam_bbox_expansion参数控制SAM模型生成的边界框的扩展。它用于细化模型对图像中对象的定位。 + - Comfy dtype: int + - Python dtype: int +- sam_mask_hint_threshold + - sam_mask_hint_threshold参数定义在SAM模型中使用掩码提示的阈值。它有助于确定所提供掩码提示的相关性和适用性,以用于图像分割。 + - Comfy dtype: float + - Python dtype: float +- sam_mask_hint_use_negative + - sam_mask_hint_use_negative参数指示在SAM模型中是否以及如何使用负掩码提示。它是提高模型区分图像中所需和不需要区域能力的重要因素。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- sam_pipe + - sam_pipe输出提供了配置有SAM模型和相关参数的管道。它对于需要模型能力的后续图像处理任务至关重要。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple[Any, ...] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class samLoaderForDetailerFix: + + @classmethod + def INPUT_TYPES(cls): + return {'required': {'model_name': (folder_paths.get_filename_list('sams'),), 'device_mode': (['AUTO', 'Prefer GPU', 'CPU'], {'default': 'AUTO'}), 'sam_detection_hint': (['center-1', 'horizontal-2', 'vertical-2', 'rect-4', 'diamond-4', 'mask-area', 'mask-points', 'mask-point-bbox', 'none'],), 'sam_dilation': ('INT', {'default': 0, 'min': -512, 'max': 512, 'step': 1}), 'sam_threshold': ('FLOAT', {'default': 0.93, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'sam_bbox_expansion': ('INT', {'default': 0, 'min': 0, 'max': 1000, 'step': 1}), 'sam_mask_hint_threshold': ('FLOAT', {'default': 0.7, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'sam_mask_hint_use_negative': (['False', 'Small', 'Outter'],)}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('sam_pipe',) + FUNCTION = 'doit' + CATEGORY = 'EasyUse/Fix' + + def doit(self, model_name, device_mode, sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion, sam_mask_hint_threshold, sam_mask_hint_use_negative): + if 'SAMLoader' not in ALL_NODE_CLASS_MAPPINGS: + raise Exception(f"[ERROR] To use SAMLoader, you need to install 'Impact Pack'") + cls = ALL_NODE_CLASS_MAPPINGS['SAMLoader'] + (sam_model,) = cls().load_model(model_name, device_mode) + pipe = (sam_model, sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion, sam_mask_hint_threshold, sam_mask_hint_use_negative) + return (pipe,) +``` \ No newline at end of file diff --git a/docs/easy seed.md b/docs/easy seed.md new file mode 100644 index 0000000..e312591 --- /dev/null +++ b/docs/easy seed.md @@ -0,0 +1,53 @@ +# Documentation +- Class name: easySeed +- Category: EasyUse/Seed +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点旨在为各种流程生成随机种子,确保系统在随机元素中具有一定的可复现性和可控性。 + +# Input types +## Required +- seed + - 种子参数对节点的运行至关重要,因为它决定了随机数生成的起点,从而影响随机过程的结果。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- prompt + - 虽然提示不是必需的,但它可以为节点的操作提供额外的上下文或指导,有可能使随机性更加精细,以符合特定的目标。 + - Comfy dtype: PROMPT + - Python dtype: str +- extra_pnginfo + - 这个参数虽然是可选的,但可以提供额外的信息,这些信息可能用于增强功能或调整节点在图像处理任务中的行为。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: str +- my_unique_id + - 提供唯一ID参数有助于跟踪和管理节点的多个实例的执行,有助于整个工作流的组织。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- seed + - 输出的种子代表了生成的随机数,作为后续依赖于此初始随机点的操作的参考。 + - Comfy dtype: INT + - Python dtype: int + +# Usage tips +- Infra type: CPU + +# Source code +``` +class easySeed: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'seed': ('INT', {'default': 0, 'min': 0, 'max': MAX_SEED_NUM})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('INT',) + RETURN_NAMES = ('seed',) + FUNCTION = 'doit' + CATEGORY = 'EasyUse/Seed' + OUTPUT_NODE = True + + def doit(self, seed=0, prompt=None, extra_pnginfo=None, my_unique_id=None): + return (seed,) +``` \ No newline at end of file diff --git a/docs/easy showAnything.md b/docs/easy showAnything.md new file mode 100644 index 0000000..ae554e1 --- /dev/null +++ b/docs/easy showAnything.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: showAnything +- Category: EasyUse/Logic +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +showAnything节点类作为一个多功能接口,用于记录和处理多样化的输入数据,便于在工作流中管理和可视化各种类型的信息。 + +# Input types +## Optional +- anything + - ‘anything’参数是使节点能够适应各种输入数据的关键元素,确保在多样化的处理场景中具有灵活性和适应性。 + - Comfy dtype: COMBO[*] + - Python dtype: Union[str, int, float, list, dict, None] +- unique_id + - ‘unique_id’参数对于将输入值与特定工作流节点关联至关重要,允许在工作流结构内进行有针对性的数据操作和跟踪。 + - Comfy dtype: str + - Python dtype: str +- extra_pnginfo + - ‘extra_pnginfo’参数包含节点操作可能必需的额外信息,根据工作流的上下文影响节点的处理和输出。 + - Comfy dtype: list + - Python dtype: List[Dict[str, Any]] + +# Output types +- ui + - ‘ui’输出参数是节点结果的结构化表示,专注于在用户界面内提供清晰、简洁的可视化处理数据。 + - Comfy dtype: dict + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class showAnything: + + @classmethod + def INPUT_TYPES(s): + return {'required': {}, 'optional': {'anything': (AlwaysEqualProxy('*'), {})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = () + INPUT_IS_LIST = True + OUTPUT_NODE = True + FUNCTION = 'log_input' + CATEGORY = 'EasyUse/Logic' + + def log_input(self, unique_id=None, extra_pnginfo=None, **kwargs): + values = [] + if 'anything' in kwargs: + for val in kwargs['anything']: + try: + if type(val) is str: + values.append(val) + else: + val = json.dumps(val) + values.append(str(val)) + except Exception: + values.append(str(val)) + pass + if unique_id and extra_pnginfo and ('workflow' in extra_pnginfo[0]): + workflow = extra_pnginfo[0]['workflow'] + node = next((x for x in workflow['nodes'] if str(x['id']) == unique_id[0]), None) + if node: + node['widgets_values'] = [values] + return {'ui': {'text': values}} +``` \ No newline at end of file diff --git a/docs/easy showLoaderSettingsNames.md b/docs/easy showLoaderSettingsNames.md new file mode 100644 index 0000000..257b90a --- /dev/null +++ b/docs/easy showLoaderSettingsNames.md @@ -0,0 +1,75 @@ +# Documentation +- Class name: showLoaderSettingsNames +- Category: EasyUse/Util +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +“showLoaderSettingsNames”节点旨在提取并展示流水线设置中涉及的各种组件的名称,特别关注检查点、VAE和LoRA名称。它作为一个实用工具,用于通知用户当前工作流的配置细节,增强透明度和易用性。 + +# Input types +## Required +- pipe + - “pipe”参数至关重要,因为它代表了包含要提取设置的流水线。这是一个必需的输入,通过提供加载器设置的上下文,在节点的操作中起着关键作用。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +- names + - “names”参数虽然是可选的,但可以用来提供加载器设置的额外上下文或默认值。它不直接影响节点的执行,但可能会影响结果的呈现或解释方式。 + - Comfy dtype: INFO + - Python dtype: Union[str, None] +- unique_id + - “unique_id”参数用于标识工作流中的特定节点。它是可选的,提供后可以帮助节点更准确地定位和更新特定节点的设置。 + - Comfy dtype: UNIQUE_ID + - Python dtype: Union[str, None] +- extra_pnginfo + - “extra_pnginfo”参数是一个可选输入,可以包含有关工作流的额外信息。当需要详细的工作流信息以使节点有效地执行其功能时,它特别有用。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Union[Dict[str, Any], None] + +# Output types +- ckpt_name + - “ckpt_name”输出提供了流水线中使用的检查点的名称,这是用户了解模型配置的关键信息。 + - Comfy dtype: STRING + - Python dtype: str +- vae_name + - “vae_name”输出表示流水线中VAE组件的名称,为用户提供了正在使用的生成模型的洞察。 + - Comfy dtype: STRING + - Python dtype: str +- lora_name + - “lora_name”输出显示了LoRA模型的名称,这对于用户了解应用于基础模型的微调功能非常重要。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class showLoaderSettingsNames: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',), 'names': ('INFO', {'default': '', 'forceInput': False})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = ('STRING', 'STRING', 'STRING') + RETURN_NAMES = ('ckpt_name', 'vae_name', 'lora_name') + FUNCTION = 'notify' + OUTPUT_NODE = True + CATEGORY = 'EasyUse/Util' + + def notify(self, pipe, names=None, unique_id=None, extra_pnginfo=None): + if unique_id and extra_pnginfo and ('workflow' in extra_pnginfo): + workflow = extra_pnginfo['workflow'] + node = next((x for x in workflow['nodes'] if str(x['id']) == unique_id), None) + if node: + ckpt_name = pipe['loader_settings']['ckpt_name'] if 'ckpt_name' in pipe['loader_settings'] else '' + vae_name = pipe['loader_settings']['vae_name'] if 'vae_name' in pipe['loader_settings'] else '' + lora_name = pipe['loader_settings']['lora_name'] if 'lora_name' in pipe['loader_settings'] else '' + if ckpt_name: + ckpt_name = os.path.basename(os.path.splitext(ckpt_name)[0]) + if vae_name: + vae_name = os.path.basename(os.path.splitext(vae_name)[0]) + if lora_name: + lora_name = os.path.basename(os.path.splitext(lora_name)[0]) + names = 'ckpt_name: ' + ckpt_name + '\n' + 'vae_name: ' + vae_name + '\n' + 'lora_name: ' + lora_name + node['widgets_values'] = names + return {'ui': {'text': names}, 'result': (ckpt_name, vae_name, lora_name)} +``` \ No newline at end of file diff --git a/docs/easy showSpentTime.md b/docs/easy showSpentTime.md new file mode 100644 index 0000000..c9978e7 --- /dev/null +++ b/docs/easy showSpentTime.md @@ -0,0 +1,63 @@ +# Documentation +- Class name: showSpentTime +- Category: EasyUse/Util +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +showSpentTime节点旨在提供工作流处理时间的反馈。它捕获推理所花费的时间,并在UI中显示,使用户能够洞察系统的效率。该节点对于监控性能和识别执行管道中的潜在瓶颈至关重要。 + +# Input types +## Required +- pipe + - pipe参数至关重要,因为它代表正在处理的数据管道。它包含节点正常运行所需的所有信息,包括可能包含spent_time的loader设置。 + - Comfy dtype: PIPE_LINE + - Python dtype: Dict[str, Any] +## Optional +- spent_time + - 如果提供此参数,将用于在UI中显示花费的时间。如果没有提供,节点将尝试从pipe的loader设置中检索花费的时间。 + - Comfy dtype: INFO + - Python dtype: Union[str, None] +- unique_id + - unique_id参数用于识别工作流中的特定节点。这对于将花费的时间与工作流中的正确节点关联起来至关重要。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str +- extra_pnginfo + - 此参数包含有关图像处理工作流的额外信息,包括工作流本身。它用于定位与unique_id关联的特定节点。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Dict[str, Any] + +# Output types +- ui + - ui输出是一个包含将在用户界面中显示的文本的字典,提供花费的时间信息。 + - Comfy dtype: DICT + - Python dtype: Dict[str, str +- result + - result输出是一个空字典,表示这个节点的主要目的是显示信息,而不是为了传递数据进行进一步处理。 + - Comfy dtype: DICT + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class showSpentTime: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'pipe': ('PIPE_LINE',), 'spent_time': ('INFO', {'default': '推理完成后将显示推理时间', 'forceInput': False})}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + FUNCTION = 'notify' + OUTPUT_NODE = True + RETURN_TYPES = () + RETURN_NAMES = () + CATEGORY = 'EasyUse/Util' + + def notify(self, pipe, spent_time=None, unique_id=None, extra_pnginfo=None): + if unique_id and extra_pnginfo and ('workflow' in extra_pnginfo): + workflow = extra_pnginfo['workflow'] + node = next((x for x in workflow['nodes'] if str(x['id']) == unique_id), None) + if node: + spent_time = pipe['loader_settings']['spent_time'] if 'spent_time' in pipe['loader_settings'] else '' + node['widgets_values'] = [spent_time] + return {'ui': {'text': spent_time}, 'result': {}} +``` \ No newline at end of file diff --git a/docs/easy showTensorShape.md b/docs/easy showTensorShape.md new file mode 100644 index 0000000..6bc5800 --- /dev/null +++ b/docs/easy showTensorShape.md @@ -0,0 +1,61 @@ +# Documentation +- Class name: showTensorShape +- Category: EasyUse/Logic +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +这个节点类旨在提供通过它的张量形状的高级概述,有助于理解数据结构而不涉及具体方法细节。它是调试和确保工作流中张量正确维度的关键工具。 + +# Input types +## Required +- tensor + - ‘tensor’参数是关键,因为它携带了节点将要分析的数据。它可以是张量、列表或字典,其形状是节点将要报告的,这对节点的运行和后续数据处理至关重要。 + - Comfy dtype: COMBO[Tensor, List, Dict] + - Python dtype: Union[torch.Tensor, List, Dict] +## Optional +- unique_id + - ‘unique_id’参数虽然不是必需的,但它作为张量形状信息的标识符,允许在系统内更容易地跟踪和管理数据。 + - Comfy dtype: str + - Python dtype: str +- extra_pnginfo + - 如果提供‘extra_pnginfo’参数,它将为张量形状信息添加额外的上下文,有可能增强节点在更复杂的数据处理场景中的实用性。 + - Comfy dtype: str + - Python dtype: str + +# Output types +- ui + - ‘ui’输出是一个包含张量形状文本表示的字典,这对于可视化数据结构并确保工作流中后续步骤得到正确信息至关重要。 + - Comfy dtype: Dict[str, Any] + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class showTensorShape: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'tensor': (AlwaysEqualProxy('*'),)}, 'optional': {}, 'hidden': {'unique_id': 'UNIQUE_ID', 'extra_pnginfo': 'EXTRA_PNGINFO'}} + RETURN_TYPES = () + RETURN_NAMES = () + OUTPUT_NODE = True + FUNCTION = 'log_input' + CATEGORY = 'EasyUse/Logic' + + def log_input(self, tensor, unique_id=None, extra_pnginfo=None): + shapes = [] + + def tensorShape(tensor): + if isinstance(tensor, dict): + for k in tensor: + tensorShape(tensor[k]) + elif isinstance(tensor, list): + for i in range(len(tensor)): + tensorShape(tensor[i]) + elif hasattr(tensor, 'shape'): + shapes.append(list(tensor.shape)) + tensorShape(tensor) + return {'ui': {'text': shapes}} +``` \ No newline at end of file diff --git a/docs/easy string.md b/docs/easy string.md new file mode 100644 index 0000000..f082ed1 --- /dev/null +++ b/docs/easy string.md @@ -0,0 +1,39 @@ +# Documentation +- Class name: String +- Category: EasyUse/Logic/Type +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点便于对字符串数据进行处理和操作,使用户能够对文本输入执行各种操作。它旨在以直接的方式处理字符串的转换、变换和分析,使其成为涉及文本数据任务的基本组件。 + +# Input types +## Required +- value + - ‘value’参数对于节点的操作至关重要,它代表将要处理的文本输入。它是所有字符串操作和转换的基础,直接影响输出结果和节点执行的有效性。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- string + - 输出‘string’代表节点执行的字符串处理的结果。它包含了对输入文本执行的操作的结果,标志着节点的主要功能及其对工作流的贡献。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class String: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'value': ('STRING', {'default': ''})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('string',) + FUNCTION = 'execute' + CATEGORY = 'EasyUse/Logic/Type' + + def execute(self, value): + return (value,) +``` \ No newline at end of file diff --git a/docs/easy stylesSelector.md b/docs/easy stylesSelector.md new file mode 100644 index 0000000..fc6098a --- /dev/null +++ b/docs/easy stylesSelector.md @@ -0,0 +1,117 @@ +# Documentation +- Class name: stylesPromptSelector +- Category: EasyUse/Prompt +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点抽象地管理风格化提示的选择和应用,以指导生成过程,确保主题一致性和风格多样性,而不涉及具体的实现细节。 + +# Input types +## Required +- styles + - “样式”参数至关重要,因为它决定了输出的风格方向。它允许节点从预定义的样式集中进行选择,从而影响生成内容的整体美学和主题结果。 + - Comfy dtype: COMBO[fooocus_styles, bar_styles, baz_styles] + - Python dtype: Union[str, List[str]] +## Optional +- positive + - “正面”参数作为指导,让节点在输出中包含某些元素或主题。它通过专注于期望的方面来完善生成过程,提高最终结果的相关性和吸引力。 + - Comfy dtype: STRING + - Python dtype: Optional[str] +- negative + - “负面”参数在定义应从输出中排除的内容方面至关重要。它帮助节点避免不希望的元素或主题,确保最终结果与预期的愿景保持一致。 + - Comfy dtype: STRING + - Python dtype: Optional[str] +- prompt + - “提示”参数是一个隐藏输入,当存在于输入的“my_unique_id”部分时,为节点提供额外的上下文。它可以包含特定的指令或偏好,进一步根据用户的需求定制输出。 + - Comfy dtype: PROMPT + - Python dtype: Dict[str, Any] +- extra_pnginfo + - 当提供“额外_pnginfo”参数时,它可以提供补充信息,节点可以利用这些信息来提高输出的细节和质量。它在完善生成过程以满足特定用户需求方面发挥作用。 + - Comfy dtype: EXTRA_PNGINFO + - Python dtype: Any +- my_unique_id + - “my_unique_id”参数是一个隐藏输入,用于唯一标识请求。它使节点能够管理和关联特定用户请求的输入,确保个性化和有针对性的输出生成。 + - Comfy dtype: UNIQUE_ID + - Python dtype: Any + +# Output types +- positive + - “正面”输出代表了根据输入标准定制和选择的风格化提示。它是最终输出的关键组成部分,确保生成的内容与期望的主题和元素保持一致。 + - Comfy dtype: STRING + - Python dtype: str +- negative + - “负面”输出捕捉了从生成过程中明确排除的元素或主题。这确保了最终结果不受不希望的方面的干扰,严格遵循用户的规格要求。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class stylesPromptSelector: + + @classmethod + def INPUT_TYPES(s): + styles = ['fooocus_styles'] + styles_dir = FOOOCUS_STYLES_DIR + for file_name in os.listdir(styles_dir): + file = os.path.join(styles_dir, file_name) + if os.path.isfile(file) and file_name.endswith('.json') and ('styles' in file_name.split('.')[0]): + styles.append(file_name.split('.')[0]) + return {'required': {'styles': (styles, {'default': 'fooocus_styles'})}, 'optional': {'positive': ('STRING', {'forceInput': True}), 'negative': ('STRING', {'forceInput': True})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('positive', 'negative') + CATEGORY = 'EasyUse/Prompt' + FUNCTION = 'run' + OUTPUT_NODE = True + + def replace_repeat(self, prompt): + prompt = prompt.replace(',', ',') + arr = prompt.split(',') + if len(arr) != len(set(arr)): + all_weight_prompt = re.findall(re.compile('[(](.*?)[)]', re.S), prompt) + if len(all_weight_prompt) > 0: + return prompt + else: + for i in range(len(arr)): + arr[i] = arr[i].strip() + arr = list(set(arr)) + return ', '.join(arr) + else: + return prompt + + def run(self, styles, positive='', negative='', prompt=None, extra_pnginfo=None, my_unique_id=None): + values = [] + all_styles = {} + (positive_prompt, negative_prompt) = ('', negative) + if styles == 'fooocus_styles': + file = os.path.join(RESOURCES_DIR, styles + '.json') + else: + file = os.path.join(FOOOCUS_STYLES_DIR, styles + '.json') + f = open(file, 'r', encoding='utf-8') + data = json.load(f) + f.close() + for d in data: + all_styles[d['name']] = d + if my_unique_id in prompt: + if prompt[my_unique_id]['inputs']['select_styles']: + values = prompt[my_unique_id]['inputs']['select_styles'].split(',') + has_prompt = False + if len(values) == 0: + return (positive, negative) + for (index, val) in enumerate(values): + if 'prompt' in all_styles[val]: + if '{prompt}' in all_styles[val]['prompt'] and has_prompt == False: + positive_prompt = all_styles[val]['prompt'].format(prompt=positive) + has_prompt = True + else: + positive_prompt += ', ' + all_styles[val]['prompt'].replace(', {prompt}', '').replace('{prompt}', '') + if 'negative_prompt' in all_styles[val]: + negative_prompt += ', ' + all_styles[val]['negative_prompt'] if negative_prompt else all_styles[val]['negative_prompt'] + if has_prompt == False and positive: + positive_prompt = positive + ', ' + positive_prompt = self.replace_repeat(positive_prompt) if positive_prompt else '' + negative_prompt = self.replace_repeat(negative_prompt) if negative_prompt else '' + return (positive_prompt, negative_prompt) +``` \ No newline at end of file diff --git a/docs/easy sv3dLoader.md b/docs/easy sv3dLoader.md new file mode 100644 index 0000000..372ae17 --- /dev/null +++ b/docs/easy sv3dLoader.md @@ -0,0 +1,156 @@ +# Documentation +- Class name: sv3DLoader +- Category: EasyUse/Loaders +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +sv3DLoader节点作为高效加载和处理3D模型及其相关数据的接口。它简化了初始化和管理模型状态、准备图像和潜在向量以供流水线中进一步处理的过程。 + +# Input types +## Required +- ckpt_name + - 检查点名称对于识别要加载的特定模型状态至关重要。它影响模型的初始化和输出质量。 + - Comfy dtype: COMBO + - Python dtype: str +- vae_name + - VAE名称参数对于选择适当的变分自编码器至关重要。它影响编码和解码过程,从而影响最终输出的保真度。 + - Comfy dtype: COMBO + - Python dtype: str +- init_image + - 初始化图像对于设置3D模型生成的上下文和内容方向至关重要。它直接影响视觉元素和结果模型的主题连贯性。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- empty_latent_width + - 此参数定义了用于模型生成的潜在空间的宽度。它很重要,因为它影响模型捕捉细节和输出多样性的能力。 + - Comfy dtype: INT + - Python dtype: int +- empty_latent_height + - 与empty_latent_width类似,此参数设置了潜在空间的高度,影响模型生成高分辨率输出的能力。 + - Comfy dtype: INT + - Python dtype: int +- batch_size + - 批量大小参数对于管理计算资源和确定同时处理的模型数量很重要。它影响流水线的整体效率和速度。 + - Comfy dtype: INT + - Python dtype: int +- interp_easing + - 插值缓和方法决定了模型如何过渡到不同状态。它影响输出序列的平滑度和连续性。 + - Comfy dtype: COMBO + - Python dtype: str +- easing_mode + - 该参数决定了要应用的缓和类型,无论是方位角、仰角还是自定义,它影响了模型在在空间中运动的轨迹。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- scheduler + - 提供调度程序参数时,允许对缓和点进行详细控制,从而精确操纵模型在潜在空间中的进展。 + - Comfy dtype: STRING + - Python dtype: str + +# Output types +- pipe + - 管道输出是一个包含加载的模型、编码的图像和其他相关数据的综合结构。它对于将必要的信息沿流水线传递到后续处理步骤至关重要。 + - Comfy dtype: PIPE_LINE + - Python dtype: dict +- model + - 模型输出提供了初始化并准备使用的3D模型。它是进一步操作和生成新内容的核心组件。 + - Comfy dtype: MODEL + - Python dtype: ModelPatcher +- interp_log + - 插值日志记录了模型处理过程中使用的方位角和仰角值。它作为理解模型在潜在空间中进展的参考。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class sv3DLoader(EasingBase): + + def __init__(self): + super().__init__() + + @classmethod + def INPUT_TYPES(cls): + + def get_file_list(filenames): + return [file for file in filenames if file != 'put_models_here.txt' and 'sv3d' in file] + return {'required': {'ckpt_name': (get_file_list(folder_paths.get_filename_list('checkpoints')),), 'vae_name': (['Baked VAE'] + folder_paths.get_filename_list('vae'),), 'init_image': ('IMAGE',), 'empty_latent_width': ('INT', {'default': 576, 'min': 16, 'max': MAX_RESOLUTION, 'step': 8}), 'empty_latent_height': ('INT', {'default': 576, 'min': 16, 'max': MAX_RESOLUTION, 'step': 8}), 'batch_size': ('INT', {'default': 21, 'min': 1, 'max': 4096}), 'interp_easing': (['linear', 'ease_in', 'ease_out', 'ease_in_out'], {'default': 'linear'}), 'easing_mode': (['azimuth', 'elevation', 'custom'], {'default': 'azimuth'})}, 'optional': {'scheduler': ('STRING', {'default': '', 'multiline': True})}, 'hidden': {'prompt': 'PROMPT', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE', 'MODEL', 'STRING') + RETURN_NAMES = ('pipe', 'model', 'interp_log') + FUNCTION = 'adv_pipeloader' + CATEGORY = 'EasyUse/Loaders' + + def adv_pipeloader(self, ckpt_name, vae_name, init_image, empty_latent_width, empty_latent_height, batch_size, interp_easing, easing_mode, scheduler='', prompt=None, my_unique_id=None): + model: ModelPatcher | None = None + vae: VAE | None = None + clip: CLIP | None = None + easyCache.update_loaded_objects(prompt) + (model, clip, vae, clip_vision) = easyCache.load_checkpoint(ckpt_name, 'Default', True) + output = clip_vision.encode_image(init_image) + pooled = output.image_embeds.unsqueeze(0) + pixels = comfy.utils.common_upscale(init_image.movedim(-1, 1), empty_latent_width, empty_latent_height, 'bilinear', 'center').movedim(1, -1) + encode_pixels = pixels[:, :, :, :3] + t = vae.encode(encode_pixels) + azimuth_points = [] + elevation_points = [] + if easing_mode == 'azimuth': + azimuth_points = [(0, 0), (batch_size - 1, 360)] + elevation_points = [(0, 0)] * batch_size + elif easing_mode == 'elevation': + azimuth_points = [(0, 0)] * batch_size + elevation_points = [(0, -90), (batch_size - 1, 90)] + else: + schedulers = scheduler.rstrip('\n') + for line in schedulers.split('\n'): + (frame_str, point_str) = line.split(':') + point_str = point_str.strip()[1:-1] + point = point_str.split(',') + azimuth_point = point[0] + elevation_point = point[1] if point[1] else 0.0 + frame = int(frame_str.strip()) + azimuth = float(azimuth_point) + azimuth_points.append((frame, azimuth)) + elevation_val = float(elevation_point) + elevation_points.append((frame, elevation_val)) + azimuth_points.sort(key=lambda x: x[0]) + elevation_points.sort(key=lambda x: x[0]) + next_point = 1 + next_elevation_point = 1 + elevations = [] + azimuths = [] + for i in range(batch_size): + while next_point < len(azimuth_points) and i >= azimuth_points[next_point][0]: + next_point += 1 + if next_point == len(azimuth_points): + next_point -= 1 + prev_point = max(next_point - 1, 0) + if azimuth_points[next_point][0] != azimuth_points[prev_point][0]: + timing = (i - azimuth_points[prev_point][0]) / (azimuth_points[next_point][0] - azimuth_points[prev_point][0]) + interpolated_azimuth = self.ease(azimuth_points[prev_point][1], azimuth_points[next_point][1], self.easing(timing, interp_easing)) + else: + interpolated_azimuth = azimuth_points[prev_point][1] + next_elevation_point = 1 + while next_elevation_point < len(elevation_points) and i >= elevation_points[next_elevation_point][0]: + next_elevation_point += 1 + if next_elevation_point == len(elevation_points): + next_elevation_point -= 1 + prev_elevation_point = max(next_elevation_point - 1, 0) + if elevation_points[next_elevation_point][0] != elevation_points[prev_elevation_point][0]: + timing = (i - elevation_points[prev_elevation_point][0]) / (elevation_points[next_elevation_point][0] - elevation_points[prev_elevation_point][0]) + interpolated_elevation = self.ease(elevation_points[prev_point][1], elevation_points[next_point][1], self.easing(timing, interp_easing)) + else: + interpolated_elevation = elevation_points[prev_elevation_point][1] + azimuths.append(interpolated_azimuth) + elevations.append(interpolated_elevation) + log_node_info('easy sv3dLoader', 'azimuths:' + str(azimuths)) + log_node_info('easy sv3dLoader', 'elevations:' + str(elevations)) + log = 'azimuths:' + str(azimuths) + '\n\n' + 'elevations:' + str(elevations) + positive = [[pooled, {'concat_latent_image': t, 'elevation': elevations, 'azimuth': azimuths}]] + negative = [[torch.zeros_like(pooled), {'concat_latent_image': torch.zeros_like(t), 'elevation': elevations, 'azimuth': azimuths}]] + latent = torch.zeros([batch_size, 4, empty_latent_height // 8, empty_latent_width // 8]) + samples = {'samples': latent} + image = easySampler.pil2tensor(Image.new('RGB', (1, 1), (0, 0, 0))) + pipe = {'model': model, 'positive': positive, 'negative': negative, 'vae': vae, 'clip': clip, 'samples': samples, 'images': image, 'seed': 0, 'loader_settings': {'ckpt_name': ckpt_name, 'vae_name': vae_name, 'positive': positive, 'positive_l': None, 'positive_g': None, 'positive_balance': None, 'negative': negative, 'negative_l': None, 'negative_g': None, 'negative_balance': None, 'empty_latent_width': empty_latent_width, 'empty_latent_height': empty_latent_height, 'batch_size': batch_size, 'seed': 0, 'empty_samples': samples}} + return (pipe, model, log) +``` \ No newline at end of file diff --git a/docs/easy svdLoader.md b/docs/easy svdLoader.md new file mode 100644 index 0000000..c2a8644 --- /dev/null +++ b/docs/easy svdLoader.md @@ -0,0 +1,128 @@ +# Documentation +- Class name: svdLoader +- Category: EasyUse/Loaders +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +svdLoader节点作为加载和处理模型检查点、VAE和CLIP模型的关键组件,促进了复杂生成管道的初始化和设置。它简化了将各种模型集成到工作流中的过程,确保了高效和无缝的数据处理和转换。 + +# Input types +## Required +- ckpt_name + - 检查点名称参数对于指定要加载的模型检查点至关重要,它构成了生成过程的基础。它决定了生成输出的质量和特性。 + - Comfy dtype: COMBO + - Python dtype: str +- vae_name + - VAE名称参数对于选择适当的变分自编码器至关重要,它在生成模型的降维和潜在空间形成中起着重要作用。 + - Comfy dtype: COMBO + - Python dtype: str +- clip_name + - CLIP名称参数对于选择正确的CLIP模型至关重要,它负责为生成过程提供文本条件能力。 + - Comfy dtype: COMBO + - Python dtype: str +- init_image + - init_image参数至关重要,因为它提供了作为生成模型参考的初始视觉输入,显著影响生成内容的方向和质量。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image +- resolution + - 分辨率参数在确定生成图像的大小和比例方面至关重要,直接影响输出的细节和清晰度水平。 + - Comfy dtype: COMBO + - Python dtype: str +- empty_latent_width + - empty_latent_width参数对于定义潜在空间的宽度很重要,它影响生成图像的多样性和变化性。 + - Comfy dtype: INT + - Python dtype: int +- empty_latent_height + - empty_latent_height参数对于设置潜在空间的高度很重要,它影响生成图像的结构连贯性和构图。 + - Comfy dtype: INT + - Python dtype: int +- video_frames + - video_frames参数对于定义视频中的帧数至关重要,它直接影响生成视频内容的时长和序列。 + - Comfy dtype: INT + - Python dtype: int +- motion_bucket_id + - motion_bucket_id参数对于控制生成视频帧中的运动和动态至关重要,它影响运动的流畅性和自然性。 + - Comfy dtype: INT + - Python dtype: int +- fps + - fps参数在确定生成视频的帧率方面至关重要,它直接影响视频内容的流畅度和播放速度。 + - Comfy dtype: INT + - Python dtype: int +- augmentation_level + - augmentation_level参数对于在图像生成过程中引入随机变化很重要,它增强了生成输出的多样性和鲁棒性。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- pipe + - pipe输出是一个综合性结构,包含了生成管道所需的所有必要组件,包括模型、VAE和CLIP,它们对后续的处理和生成任务至关重要。 + - Comfy dtype: PIPE_LINE + - Python dtype: dict +- model + - model输出代表加载的生成模型,它是根据输入数据和定义参数创建最终输出的核心组件。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- vae + - vae输出是变分自编码器模型,它在生成和操作潜在空间方面起着重要作用,对生成内容的多样性和质量至关重要。 + - Comfy dtype: VAE + - Python dtype: torch.nn.Module + +# Usage tips +- Infra type: CPU + +# Source code +``` +class svdLoader: + + @classmethod + def INPUT_TYPES(cls): + resolution_strings = [f'{width} x {height}' for (width, height) in BASE_RESOLUTIONS] + + def get_file_list(filenames): + return [file for file in filenames if file != 'put_models_here.txt' and 'svd' in file.lower()] + return {'required': {'ckpt_name': (list(['svd.safetensors', 'svd_xt.safetensors', 'svd_image_decoder.safetensors', 'svd_xt_image_decoder.safetensors', 'svd-fp16.safetensors', 'svd_xt-fp16.safetensors', 'svd_image_decoder-fp16.safetensors', 'svd_xt_image_decoder-fp16.safetensors', 'svd_xt_1_1.safetensors']),), 'vae_name': (['Baked VAE'] + folder_paths.get_filename_list('vae'),), 'clip_name': (['None'] + folder_paths.get_filename_list('clip'),), 'init_image': ('IMAGE',), 'resolution': (resolution_strings, {'default': '1024 x 576'}), 'empty_latent_width': ('INT', {'default': 256, 'min': 16, 'max': MAX_RESOLUTION, 'step': 8}), 'empty_latent_height': ('INT', {'default': 256, 'min': 16, 'max': MAX_RESOLUTION, 'step': 8}), 'video_frames': ('INT', {'default': 14, 'min': 1, 'max': 4096}), 'motion_bucket_id': ('INT', {'default': 127, 'min': 1, 'max': 1023}), 'fps': ('INT', {'default': 6, 'min': 1, 'max': 1024}), 'augmentation_level': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 10.0, 'step': 0.01})}, 'optional': {'optional_positive': ('STRING', {'default': '', 'multiline': True}), 'optional_negative': ('STRING', {'default': '', 'multiline': True})}, 'hidden': {'prompt': 'PROMPT', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE', 'MODEL', 'VAE') + RETURN_NAMES = ('pipe', 'model', 'vae') + FUNCTION = 'adv_pipeloader' + CATEGORY = 'EasyUse/Loaders' + + def adv_pipeloader(self, ckpt_name, vae_name, clip_name, init_image, resolution, empty_latent_width, empty_latent_height, video_frames, motion_bucket_id, fps, augmentation_level, optional_positive=None, optional_negative=None, prompt=None, my_unique_id=None): + model: ModelPatcher | None = None + vae: VAE | None = None + clip: CLIP | None = None + clip_vision = None + if resolution != '自定义 x 自定义': + try: + (width, height) = map(int, resolution.split(' x ')) + empty_latent_width = width + empty_latent_height = height + except ValueError: + raise ValueError('Invalid base_resolution format.') + easyCache.update_loaded_objects(prompt) + (model, clip, vae, clip_vision) = easyCache.load_checkpoint(ckpt_name, 'Default', True) + output = clip_vision.encode_image(init_image) + pooled = output.image_embeds.unsqueeze(0) + pixels = comfy.utils.common_upscale(init_image.movedim(-1, 1), empty_latent_width, empty_latent_height, 'bilinear', 'center').movedim(1, -1) + encode_pixels = pixels[:, :, :, :3] + if augmentation_level > 0: + encode_pixels += torch.randn_like(pixels) * augmentation_level + t = vae.encode(encode_pixels) + positive = [[pooled, {'motion_bucket_id': motion_bucket_id, 'fps': fps, 'augmentation_level': augmentation_level, 'concat_latent_image': t}]] + negative = [[torch.zeros_like(pooled), {'motion_bucket_id': motion_bucket_id, 'fps': fps, 'augmentation_level': augmentation_level, 'concat_latent_image': torch.zeros_like(t)}]] + if optional_positive is not None and optional_positive != '': + if clip_name == 'None': + raise Exception('You need choose a open_clip model when positive is not empty') + clip = easyCache.load_clip(clip_name) + (positive_embeddings_final,) = CLIPTextEncode().encode(clip, optional_positive) + (positive,) = ConditioningConcat().concat(positive, positive_embeddings_final) + if optional_negative is not None and optional_negative != '': + if clip_name == 'None': + raise Exception('You need choose a open_clip model when negative is not empty') + (negative_embeddings_final,) = CLIPTextEncode().encode(clip, optional_negative) + (negative,) = ConditioningConcat().concat(negative, negative_embeddings_final) + latent = torch.zeros([video_frames, 4, empty_latent_height // 8, empty_latent_width // 8]) + samples = {'samples': latent} + image = easySampler.pil2tensor(Image.new('RGB', (1, 1), (0, 0, 0))) + pipe = {'model': model, 'positive': positive, 'negative': negative, 'vae': vae, 'clip': clip, 'samples': samples, 'images': image, 'seed': 0, 'loader_settings': {'ckpt_name': ckpt_name, 'vae_name': vae_name, 'positive': positive, 'positive_l': None, 'positive_g': None, 'positive_balance': None, 'negative': negative, 'negative_l': None, 'negative_g': None, 'negative_balance': None, 'empty_latent_width': empty_latent_width, 'empty_latent_height': empty_latent_height, 'batch_size': 1, 'seed': 0, 'empty_samples': samples}} + return (pipe, model, vae) +``` \ No newline at end of file diff --git a/docs/easy ultralyticsDetectorPipe.md b/docs/easy ultralyticsDetectorPipe.md new file mode 100644 index 0000000..3bfd2dd --- /dev/null +++ b/docs/easy ultralyticsDetectorPipe.md @@ -0,0 +1,58 @@ +# Documentation +- Class name: ultralyticsDetectorForDetailerFix +- Category: EasyUse/Fix +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点与Ultralytics检测器集成,处理边界框和分割数据,提高图像中对象检测的准确性和细节。它旨在通过调整检测参数和应用特定的处理步骤来提高图像分析的整体质量。 + +# Input types +## Required +- model_name + - model_name参数指定了检测模型的来源,这对节点的运行至关重要,因为它决定了用于对象检测和分割的数据。 + - Comfy dtype: COMBO[bboxs, segms] + - Python dtype: Union[str, List[str]] +- bbox_threshold + - bbox_threshold参数微调边界框检测的灵敏度,影响节点识别和隔离图像中对象的能力。 + - Comfy dtype: FLOAT + - Python dtype: float +- bbox_dilation + - bbox_dilation参数调整边界框的大小,这对于准确框定和聚焦检测到的对象至关重要。 + - Comfy dtype: INT + - Python dtype: int +- bbox_crop_factor + - bbox_crop_factor参数影响围绕检测到的对象的图像裁剪,确保有效地捕捉细节以进行进一步分析。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- bbox_segm_pipe + - 该节点的输出是一个结合了精炼的边界框和分割结果的流水线,为详细的图像分析提供了一套全面的数据。 + - Comfy dtype: PIPE_LINE + - Python dtype: Tuple[Any, float, int, float, Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class ultralyticsDetectorForDetailerFix: + + @classmethod + def INPUT_TYPES(s): + bboxs = ['bbox/' + x for x in folder_paths.get_filename_list('ultralytics_bbox')] + segms = ['segm/' + x for x in folder_paths.get_filename_list('ultralytics_segm')] + return {'required': {'model_name': (bboxs + segms,), 'bbox_threshold': ('FLOAT', {'default': 0.5, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'bbox_dilation': ('INT', {'default': 10, 'min': -512, 'max': 512, 'step': 1}), 'bbox_crop_factor': ('FLOAT', {'default': 3.0, 'min': 1.0, 'max': 10, 'step': 0.1})}} + RETURN_TYPES = ('PIPE_LINE',) + RETURN_NAMES = ('bbox_segm_pipe',) + FUNCTION = 'doit' + CATEGORY = 'EasyUse/Fix' + + def doit(self, model_name, bbox_threshold, bbox_dilation, bbox_crop_factor): + if 'UltralyticsDetectorProvider' not in ALL_NODE_CLASS_MAPPINGS: + raise Exception(f"[ERROR] To use UltralyticsDetectorProvider, you need to install 'Impact Pack'") + cls = ALL_NODE_CLASS_MAPPINGS['UltralyticsDetectorProvider'] + (bbox_detector, segm_detector) = cls().doit(model_name) + pipe = (bbox_detector, bbox_threshold, bbox_dilation, bbox_crop_factor, segm_detector) + return (pipe,) +``` \ No newline at end of file diff --git a/docs/easy unSampler.md b/docs/easy unSampler.md new file mode 100644 index 0000000..41f6e6c --- /dev/null +++ b/docs/easy unSampler.md @@ -0,0 +1,122 @@ +# Documentation +- Class name: unsampler +- Category: EasyUse/Sampler +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +unsampler类通过采样过程从潜在向量生成高质量图像。它旨在用户友好和高效,允许定制各种参数以实现期望的结果。 + +# Input types +## Required +- steps + - 步数决定了采样过程的进展,更多的步数通常会导致图像质量的提高。这是一个关键参数,因为它直接影响输出结果。 + - Comfy dtype: INT + - Python dtype: int +- end_at_step + - 该参数指定采样过程应在哪个步骤终止。它对于控制采样过程的持续时间和计算成本很重要。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - 配置参数'cfg'影响采样过程的行为,如生成图像中的细节程度和降噪水平。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数决定了使用的采样方法,这可以显著改变生成图像的特性。 + - Comfy dtype: COMBO + - Python dtype: str +- scheduler + - scheduler参数定义了随时间调整采样策略,影响最终输出的质量和一致性。 + - Comfy dtype: COMBO + - Python dtype: str +- normalize + - 归一化是一个预处理步骤,通过确保输入数据标准化,可以提高采样过程的稳定性和性能。 + - Comfy dtype: COMBO + - Python dtype: str +## Optional +- pipe + - “pipe”参数是一个可选输入,提供时包含采样过程所需的额外上下文和资源。 + - Comfy dtype: PIPE_LINE + - Python dtype: dict +- optional_model + - “optional_model”参数允许用户指定采样过程的自定义模型,从而生成具有独特特性的图像。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- optional_positive + - “optional_positive”参数提供正向调节数据,可以引导采样过程朝着期望的结果发展。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- optional_negative + - “optional_negative”参数提供负向调节数据,有助于避免生成图像中不希望出现的特征。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- optional_latent + - “optional_latent”参数用于提供初始潜在向量,这些向量可以在采样过程中得到改进。 + - Comfy dtype: LATENT + - Python dtype: dict + +# Output types +- pipe + - “pipe”输出包含采样过程的结果,包括生成的图像以及在此过程中使用的任何额外上下文或资源。 + - Comfy dtype: PIPE_LINE + - Python dtype: dict +- latent + - “latent”输出提供代表生成图像的最终潜在向量,可以进一步分析或用作其他过程的输入。 + - Comfy dtype: LATENT + - Python dtype: dict + +# Usage tips +- Infra type: GPU + +# Source code +``` +class unsampler: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'steps': ('INT', {'default': 20, 'min': 1, 'max': 10000}), 'end_at_step': ('INT', {'default': 0, 'min': 0, 'max': 10000}), 'cfg': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 100.0}), 'sampler_name': (comfy.samplers.KSampler.SAMPLERS,), 'scheduler': (comfy.samplers.KSampler.SCHEDULERS,), 'normalize': (['disable', 'enable'],)}, 'optional': {'pipe': ('PIPE_LINE',), 'optional_model': ('MODEL',), 'optional_positive': ('CONDITIONING',), 'optional_negative': ('CONDITIONING',), 'optional_latent': ('LATENT',)}} + RETURN_TYPES = ('PIPE_LINE', 'LATENT') + RETURN_NAMES = ('pipe', 'latent') + FUNCTION = 'unsampler' + CATEGORY = 'EasyUse/Sampler' + + def unsampler(self, cfg, sampler_name, steps, end_at_step, scheduler, normalize, pipe=None, optional_model=None, optional_positive=None, optional_negative=None, optional_latent=None): + model = optional_model if optional_model is not None else pipe['model'] + positive = optional_positive if optional_positive is not None else pipe['positive'] + negative = optional_negative if optional_negative is not None else pipe['negative'] + latent_image = optional_latent if optional_latent is not None else pipe['samples'] + normalize = normalize == 'enable' + device = comfy.model_management.get_torch_device() + latent = latent_image + latent_image = latent['samples'] + end_at_step = min(end_at_step, steps - 1) + end_at_step = steps - end_at_step + noise = torch.zeros(latent_image.size(), dtype=latent_image.dtype, layout=latent_image.layout, device='cpu') + noise_mask = None + if 'noise_mask' in latent: + noise_mask = comfy.sample.prepare_mask(latent['noise_mask'], noise.shape, device) + noise = noise.to(device) + latent_image = latent_image.to(device) + _positive = comfy.sampler_helpers.convert_cond(positive) + _negative = comfy.sampler_helpers.convert_cond(negative) + (models, inference_memory) = comfy.sampler_helpers.get_additional_models({'positive': _positive, 'negative': _negative}, model.model_dtype()) + comfy.model_management.load_models_gpu([model] + models, model.memory_required(noise.shape) + inference_memory) + model_patcher = comfy.model_patcher.ModelPatcher(model.model, load_device=device, offload_device=comfy.model_management.unet_offload_device()) + sampler = comfy.samplers.KSampler(model_patcher, steps=steps, device=device, sampler=sampler_name, scheduler=scheduler, denoise=1.0, model_options=model.model_options) + sigmas = sampler.sigmas.flip(0) + 0.0001 + pbar = comfy.utils.ProgressBar(steps) + + def callback(step, x0, x, total_steps): + pbar.update_absolute(step + 1, total_steps) + samples = sampler.sample(noise, positive, negative, cfg=cfg, latent_image=latent_image, force_full_denoise=False, denoise_mask=noise_mask, sigmas=sigmas, start_step=0, last_step=end_at_step, callback=callback) + if normalize: + samples -= samples.mean() + samples /= samples.std() + samples = samples.cpu() + comfy.sample.cleanup_additional_models(models) + out = latent.copy() + out['samples'] = samples + if pipe is None: + pipe = {} + new_pipe = {**pipe, 'samples': out} + return (new_pipe, out) +``` \ No newline at end of file diff --git a/docs/easy wildcards.md b/docs/easy wildcards.md new file mode 100644 index 0000000..3f8db5a --- /dev/null +++ b/docs/easy wildcards.md @@ -0,0 +1,64 @@ +# Documentation +- Class name: wildcardsPrompt +- Category: EasyUse/Prompt +- Output node: True +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点类旨在通过替换选项和通配符来处理和修改文本输入,增强文本的多功能性和互动性。它通过识别输入中的模式和关键词,并将它们替换为预定义字典中的相应元素或通过随机选择来实现,从而生成修改后的输出文本。 + +# Input types +## Required +- text + - 文本参数对于节点的操作至关重要,因为它提供了将要处理的原始内容。它是所有替换和修改的基础,对于实现节点的目的来说是一个关键的输入。 + - Comfy dtype: STRING + - Python dtype: str +## Optional +- seed + - 种子参数在节点内部的随机化过程中引入了可重现性。通过设置特定的种子,可以控制选项和通配符替换中的随机性,确保在不同运行中获得一致的结果。 + - Comfy dtype: INT + - Python dtype: int + +# Output types +- text + - 输出文本是节点处理的结果,其中原始输入文本已经被替换和增强。它代表了节点功能的结晶,展示了转换后的内容。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class wildcardsPrompt: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + wildcard_list = get_wildcard_list() + return {'required': {'text': ('STRING', {'default': '', 'multiline': True, 'dynamicPrompts': False, 'placeholder': '(Support Lora Block Weight and wildcard)'}), 'Select to add LoRA': (['Select the LoRA to add to the text'] + folder_paths.get_filename_list('loras'),), 'Select to add Wildcard': (['Select the Wildcard to add to the text'] + wildcard_list,), 'seed': ('INT', {'default': 0, 'min': 0, 'max': MAX_SEED_NUM}), 'multiline_mode': ('BOOLEAN', {'default': False})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('STRING', 'STRING') + RETURN_NAMES = ('text', 'populated_text') + OUTPUT_IS_LIST = (True, True) + OUTPUT_NODE = True + FUNCTION = 'main' + CATEGORY = 'EasyUse/Prompt' + + @staticmethod + def main(*args, **kwargs): + prompt = kwargs['prompt'] if 'prompt' in kwargs else None + seed = kwargs['seed'] + if prompt: + easyCache.update_loaded_objects(prompt) + text = kwargs['text'] + if 'multiline_mode' in kwargs and kwargs['multiline_mode']: + populated_text = [] + text = text.split('\n') + for t in text: + populated_text.append(process(t, seed)) + else: + populated_text = [process(text, seed)] + text = [text] + return {'ui': {'value': [seed]}, 'result': (text, populated_text)} +``` \ No newline at end of file diff --git a/docs/easy xyAny.md b/docs/easy xyAny.md new file mode 100644 index 0000000..daff06e --- /dev/null +++ b/docs/easy xyAny.md @@ -0,0 +1,65 @@ +# Documentation +- Class name: xyAny +- Category: EasyUse/Logic +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +该节点类便于将输入数据重新组织成与水平或垂直方向对齐的结构化格式。它旨在通过基于指定方向高效地将元素配对排列,从而简化数据操作任务,增强数据在后续处理步骤中的实用性。 + +# Input types +## Required +- X + - 参数'X'代表第一组元素,将与'Y'中的元素配对。它的重要性在于建立了数据配对的一方,这对节点的操作和生成的数据结构至关重要。 + - Comfy dtype: COMBO[*] + - Python dtype: List[Any] +- Y + - 参数'Y'代表第二组元素,意在与'X'中的元素配对。它在节点的功能中扮演着至关重要的角色,因为它决定了数据配对的另一方,直接影响输出的最终排列。 + - Comfy dtype: COMBO[*] + - Python dtype: List[Any] +- direction + - 参数'direction'指定数据配对的方向,可以是'horizontal'或'vertical'。它非常重要,因为它定义了输出的结构,指导节点如何将'X'和'Y'元素排列成期望的格式。 + - Comfy dtype: [str] + - Python dtype: Union[str, AlwaysEqualProxy] + +# Output types +- X + - 输出'X'是原始'X'输入中元素的重新结构化序列,现在根据指定的方向与'Y'中的元素配对。它代表了节点输出的一半,已经转换以满足水平或垂直排列的要求。 + - Comfy dtype: COMBO[*] + - Python dtype: List[Any] +- Y + - 输出'Y'在结构上与输出'X'相似,但由'Y'输入中的元素组成。它构成了节点输出的另一半,完成了基于所选方向组织的搭配数据集。 + - Comfy dtype: COMBO[*] + - Python dtype: List[Any] + +# Usage tips +- Infra type: CPU + +# Source code +``` +class xyAny: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'X': (AlwaysEqualProxy('*'), {}), 'Y': (AlwaysEqualProxy('*'), {}), 'direction': (['horizontal', 'vertical'], {'default': 'horizontal'})}} + RETURN_TYPES = (AlwaysEqualProxy('*'), AlwaysEqualProxy('*')) + RETURN_NAMES = ('X', 'Y') + INPUT_IS_LIST = True + OUTPUT_IS_LIST = (True, True) + CATEGORY = 'EasyUse/Logic' + FUNCTION = 'to_xy' + + def to_xy(self, X, Y, direction): + new_x = list() + new_y = list() + if direction[0] == 'horizontal': + for y in Y: + for x in X: + new_x.append(x) + new_y.append(y) + else: + for x in X: + for y in Y: + new_x.append(x) + new_y.append(y) + return (new_x, new_y) +``` \ No newline at end of file diff --git a/docs/easy zero123Loader.md b/docs/easy zero123Loader.md new file mode 100644 index 0000000..1a2cf7d --- /dev/null +++ b/docs/easy zero123Loader.md @@ -0,0 +1,106 @@ +# Documentation +- Class name: zero123Loader +- Category: EasyUse/Loaders +- Output node: False +- Repo Ref: https://github.com/yolain/ComfyUI-Easy-Use.git + +zero123Loader节点作为一个接口,用于加载和管理各种模型和图像,便于初始化复杂的图像处理和生成任务的流程。它通过处理VAE和CLIP模型等必要组件的检索和配置,简化了后续操作,确保操作能够高效有效地执行。 + +# Input types +## Required +- ckpt_name + - ckpt_name参数用于指定要加载的包含训练模型参数的检查点。这对于节点正确运行和启动后续的图像处理及生成任务至关重要。 + - Comfy dtype: COMBO[[['stable_zero123.ckpt']]] + - Python dtype: str +- vae_name + - vae_name参数用于选择适当的VAE模型,该模型用于生成和处理图像的潜在表示。VAE模型的选择对节点生成的图像质量和特性有着显著影响。 + - Comfy dtype: COMBO[['Baked VAE'] + folder_paths.get_filename_list('vae')] + - Python dtype: str +- init_image + - init_image参数至关重要,因为它提供了作为图像处理和生成任务起点的初始图像数据。这张图像的内容和质量直接影响输出结果。 + - Comfy dtype: IMAGE + - Python dtype: PIL.Image.Image +- empty_latent_width + - empty_latent_width参数定义了将要填充生成内容的空潜在空间的宽度。它是决定生成图像的分辨率和规模的关键因素。 + - Comfy dtype: INT + - Python dtype: int +- empty_latent_height + - empty_latent_height参数设置了空潜在空间的高度,对应于生成图像的垂直维度。这个参数对于控制输出图像的长宽比和大小非常重要。 + - Comfy dtype: INT + - Python dtype: int +- batch_size + - + - Comfy dtype: INT + - Python dtype: int +- elevation + - elevation参数指定了图像的观察视角的垂直角度,影响渲染输出的透视和外观。它是创建逼真且视觉上吸引人的图像的重要因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- azimuth + - azimuth参数决定了图像观察的水平角度,影响生成图像的方向和布局。它对于将输出与期望的视觉方向对齐至关重要。 + - Comfy dtype: FLOAT + - Python dtype: float +## Optional +- prompt + - prompt参数为图像生成过程提供文本指导,帮助塑造生成图像的内容和风格。这是一个可选但有用的工具,用于引导节点输出的创作方向。 + - Comfy dtype: PROMPT + - Python dtype: str +- my_unique_id + - my_unique_id参数用于跟踪和管理节点操作的唯一实例,确保每次执行都是可识别和独特的。这有助于调试和维护流程的完整性。 + - Comfy dtype: UNIQUE_ID + - Python dtype: str + +# Output types +- pipe + - pipe输出是一个综合性结构,封装了图像处理和生成流程所需的所有组件和设置。它作为后续操作的支柱,确保工作流程的顺畅和协调。 + - Comfy dtype: PIPE_LINE + - Python dtype: dict +- model + - model输出提供了已加载和配置的模型,准备用于图像处理任务。它是直接影响图像生成质量和准确性的关键组件。 + - Comfy dtype: MODEL + - Python dtype: comfy.model_management.ModelPatcher +- vae + - vae输出包含了已经初始化并准备好用于生成和处理潜在图像表示的VAE模型。它在图像创建过程中起着核心作用,使节点能够产生高质量的视觉效果。 + - Comfy dtype: VAE + - Python dtype: comfy.sd.VAE + +# Usage tips +- Infra type: CPU + +# Source code +``` +class zero123Loader: + + @classmethod + def INPUT_TYPES(cls): + + def get_file_list(filenames): + return [file for file in filenames if file != 'put_models_here.txt' and 'zero123' in file.lower()] + return {'required': {'ckpt_name': (list(['stable_zero123.ckpt']),), 'vae_name': (['Baked VAE'] + folder_paths.get_filename_list('vae'),), 'init_image': ('IMAGE',), 'empty_latent_width': ('INT', {'default': 256, 'min': 16, 'max': MAX_RESOLUTION, 'step': 8}), 'empty_latent_height': ('INT', {'default': 256, 'min': 16, 'max': MAX_RESOLUTION, 'step': 8}), 'batch_size': ('INT', {'default': 1, 'min': 1, 'max': 64}), 'elevation': ('FLOAT', {'default': 0.0, 'min': -180.0, 'max': 180.0}), 'azimuth': ('FLOAT', {'default': 0.0, 'min': -180.0, 'max': 180.0})}, 'hidden': {'prompt': 'PROMPT', 'my_unique_id': 'UNIQUE_ID'}} + RETURN_TYPES = ('PIPE_LINE', 'MODEL', 'VAE') + RETURN_NAMES = ('pipe', 'model', 'vae') + FUNCTION = 'adv_pipeloader' + CATEGORY = 'EasyUse/Loaders' + + def adv_pipeloader(self, ckpt_name, vae_name, init_image, empty_latent_width, empty_latent_height, batch_size, elevation, azimuth, prompt=None, my_unique_id=None): + model: ModelPatcher | None = None + vae: VAE | None = None + clip: CLIP | None = None + clip_vision = None + easyCache.update_loaded_objects(prompt) + (model, clip, vae, clip_vision) = easyCache.load_checkpoint(ckpt_name, 'Default', True) + output = clip_vision.encode_image(init_image) + pooled = output.image_embeds.unsqueeze(0) + pixels = comfy.utils.common_upscale(init_image.movedim(-1, 1), empty_latent_width, empty_latent_height, 'bilinear', 'center').movedim(1, -1) + encode_pixels = pixels[:, :, :, :3] + t = vae.encode(encode_pixels) + cam_embeds = camera_embeddings(elevation, azimuth) + cond = torch.cat([pooled, cam_embeds.repeat((pooled.shape[0], 1, 1))], dim=-1) + positive = [[cond, {'concat_latent_image': t}]] + negative = [[torch.zeros_like(pooled), {'concat_latent_image': torch.zeros_like(t)}]] + latent = torch.zeros([batch_size, 4, empty_latent_height // 8, empty_latent_width // 8]) + samples = {'samples': latent} + image = easySampler.pil2tensor(Image.new('RGB', (1, 1), (0, 0, 0))) + pipe = {'model': model, 'positive': positive, 'negative': negative, 'vae': vae, 'clip': clip, 'samples': samples, 'images': image, 'seed': 0, 'loader_settings': {'ckpt_name': ckpt_name, 'vae_name': vae_name, 'positive': positive, 'positive_l': None, 'positive_g': None, 'positive_balance': None, 'negative': negative, 'negative_l': None, 'negative_g': None, 'negative_balance': None, 'empty_latent_width': empty_latent_width, 'empty_latent_height': empty_latent_height, 'batch_size': batch_size, 'seed': 0, 'empty_samples': samples}} + return (pipe, model, vae) +``` \ No newline at end of file diff --git a/docs/promptComposerTextMultiple.md b/docs/promptComposerTextMultiple.md new file mode 100644 index 0000000..32aee36 --- /dev/null +++ b/docs/promptComposerTextMultiple.md @@ -0,0 +1,82 @@ +# Documentation +- Class name: promptComposerTextMultiple +- Category: AI WizArt/Prompt Composer Tools +- Output node: False +- Repo Ref: https://github.com/florestefano1975/comfyui-prompt-composer.git + +promptComposerTextMultiple节点旨在将多个文本输入合成为单一的、连贯的提示。它智能地对每个文本条目应用权重,允许对每个组成部分的影响进行细微控制。这个节点特别擅长制作平衡各种文本元素重要性的提示,确保输出是一个精心制作的聚合体,服务于预期的目的。 + +# Input types +## Required +- text_in_opt + - 可选文本输入作为可以包含在最终提示组合中的额外信息。它在提供补充上下文或细节方面发挥作用,这些信息可能会丰富整个提示。 + - Comfy dtype: STRING + - Python dtype: str +- text_1 + - 主要文本输入是节点操作的必需组件。它是对最终提示有重大贡献的关键元素。文本的内容和结构对于定义提示的方向和焦点至关重要。 + - Comfy dtype: STRING + - Python dtype: str +- weight_1 + - 第一个文本输入的权重参数允许调整其在提示中的相对重要性。它是决定组合提示的整体平衡和重点的关键因素。 + - Comfy dtype: FLOAT + - Python dtype: float +- active + - 激活标志确定是否在提示组合中考虑文本输入及其关联的权重。它作为一个切换,根据节点的执行上下文包括或排除输入数据的某些部分。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- text_out + - 输出文本是由加权文本输入组合生成的综合提示。它包含了所提供文本的精髓,反映了带有期望的强调和平衡的意图信息。 + - Comfy dtype: STRING + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class promptComposerTextMultiple: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'optional': {'text_in_opt': ('STRING', {'forceInput': True})}, 'required': {'text_1': ('STRING', {'multiline': True}), 'weight_1': ('FLOAT', {'default': 1, 'min': 0, 'max': 1.95, 'step': 0.05, 'display': 'slider'}), 'text_2': ('STRING', {'multiline': True}), 'weight_2': ('FLOAT', {'default': 1, 'min': 0, 'max': 1.95, 'step': 0.05, 'display': 'slider'}), 'text_3': ('STRING', {'multiline': True}), 'weight_3': ('FLOAT', {'default': 1, 'min': 0, 'max': 1.95, 'step': 0.05, 'display': 'slider'}), 'text_4': ('STRING', {'multiline': True}), 'weight_4': ('FLOAT', {'default': 1, 'min': 0, 'max': 1.95, 'step': 0.05, 'display': 'slider'}), 'text_5': ('STRING', {'multiline': True}), 'weight_5': ('FLOAT', {'default': 1, 'min': 0, 'max': 1.95, 'step': 0.05, 'display': 'slider'}), 'text_6': ('STRING', {'multiline': True}), 'weight_6': ('FLOAT', {'default': 1, 'min': 0, 'max': 1.95, 'step': 0.05, 'display': 'slider'}), 'text_7': ('STRING', {'multiline': True}), 'weight_7': ('FLOAT', {'default': 1, 'min': 0, 'max': 1.95, 'step': 0.05, 'display': 'slider'}), 'text_8': ('STRING', {'multiline': True}), 'weight_8': ('FLOAT', {'default': 1, 'min': 0, 'max': 1.95, 'step': 0.05, 'display': 'slider'}), 'text_9': ('STRING', {'multiline': True}), 'weight_9': ('FLOAT', {'default': 1, 'min': 0, 'max': 1.95, 'step': 0.05, 'display': 'slider'}), 'text_10': ('STRING', {'multiline': True}), 'weight_10': ('FLOAT', {'default': 1, 'min': 0, 'max': 1.95, 'step': 0.05, 'display': 'slider'}), 'active': ('BOOLEAN', {'default': False})}} + RETURN_TYPES = ('STRING',) + RETURN_NAMES = ('text_out',) + FUNCTION = 'promptComposerTextMultiple' + CATEGORY = 'AI WizArt/Prompt Composer Tools' + + def promptComposerTextMultiple(self, text_in_opt='', text_1='', weight_1=0, text_2='', weight_2=0, text_3='', weight_3=0, text_4='', weight_4=0, text_5='', weight_5=0, text_6='', weight_6=0, text_7='', weight_7=0, text_8='', weight_8=0, text_9='', weight_9=0, text_10='', weight_10=0, active=True): + prompt = [] + if text_in_opt != '': + prompt.append(text_in_opt) + if text_1 != '' and weight_1 > 0 and active: + prompt.append(applyWeight(text_1, weight_1)) + if text_2 != '' and weight_2 > 0 and active: + prompt.append(applyWeight(text_2, weight_2)) + if text_3 != '' and weight_3 > 0 and active: + prompt.append(applyWeight(text_3, weight_3)) + if text_4 != '' and weight_4 > 0 and active: + prompt.append(applyWeight(text_4, weight_4)) + if text_5 != '' and weight_5 > 0 and active: + prompt.append(applyWeight(text_5, weight_5)) + if text_6 != '' and weight_6 > 0 and active: + prompt.append(applyWeight(text_6, weight_6)) + if text_7 != '' and weight_7 > 0 and active: + prompt.append(applyWeight(text_7, weight_7)) + if text_8 != '' and weight_8 > 0 and active: + prompt.append(applyWeight(text_8, weight_8)) + if text_9 != '' and weight_9 > 0 and active: + prompt.append(applyWeight(text_9, weight_9)) + if text_10 != '' and weight_10 > 0 and active: + prompt.append(applyWeight(text_10, weight_10)) + if len(prompt) > 0: + prompt = ', '.join(prompt) + prompt = prompt.lower() + return (prompt,) + else: + return ('',) +``` \ No newline at end of file diff --git a/docs/smZ CLIPTextEncode.md b/docs/smZ CLIPTextEncode.md new file mode 100644 index 0000000..d4634d2 --- /dev/null +++ b/docs/smZ CLIPTextEncode.md @@ -0,0 +1,78 @@ +# Documentation +- Class name: smZ_CLIPTextEncode +- Category: conditioning +- Output node: False +- Repo Ref: https://github.com/shiimizu/ComfyUI_smZNodes.git + +smZ_CLIPTextEncode节点旨在处理文本输入并将其转换为可用于进一步计算任务的结构化表示。它利用CLIP模型的力量来理解和生成文本嵌入,这对于各种AI驱动的应用程序至关重要。该节点抽象了文本编码的复杂性,允许用户专注于项目的更广泛目标,而不是文本处理的细节。 + +# Input types +## Required +- text + - 文本参数至关重要,因为它提供了节点处理的原始文本数据。它为整个编码操作提供了基础,其内容直接影响生成嵌入的质量和相关性。 + - Comfy dtype: STRING + - Python dtype: str +- clip + - clip参数代表节点用于编码文本的CLIP模型。这是一个关键元素,因为模型的能力和训练直接影响编码过程以及嵌入的后续使用。 + - Comfy dtype: CLIP + - Python dtype: comfy.sd.CLIP +- parser + - 解析器参数对于确定文本将如何被节点解释和处理至关重要。它影响文本表示的粒度和结构,这对编码的准确性和有效性至关重要。 + - Comfy dtype: COMBO + - Python dtype: str + +# Output types +- CONDITIONING + - smZ_CLIPTextEncode节点的输出是一组从编码文本中派生的调节数据。这些数据非常重要,因为它可以用来指导和完善后续的AI模型或任务,为它们提供必要的上下文和结构。 + - Comfy dtype: CONDITIONING + - Python dtype: Dict[str, Any] + +# Usage tips +- Infra type: GPU + +# Source code +``` +class smZ_CLIPTextEncode: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'text': ('STRING', {'multiline': True}), 'clip': ('CLIP',), 'parser': (['comfy', 'comfy++', 'A1111', 'full', 'compel', 'fixed attention'], {'default': 'comfy'}), 'mean_normalization': (BOOLEAN, {'default': True}), 'multi_conditioning': (BOOLEAN, {'default': True}), 'use_old_emphasis_implementation': (BOOLEAN, {'default': False}), 'with_SDXL': (BOOLEAN, {'default': False}), 'ascore': ('FLOAT', {'default': 6.0, 'min': 0.0, 'max': 1000.0, 'step': 0.01}), 'width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'crop_w': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION}), 'crop_h': ('INT', {'default': 0, 'min': 0, 'max': MAX_RESOLUTION}), 'target_width': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'target_height': ('INT', {'default': 1024.0, 'min': 0, 'max': MAX_RESOLUTION}), 'text_g': ('STRING', {'multiline': True, 'placeholder': 'CLIP_G'}), 'text_l': ('STRING', {'multiline': True, 'placeholder': 'CLIP_L'})}, 'optional': {'smZ_steps': ('INT', {'default': 1, 'min': 1, 'max': 18446744073709551615})}} + RETURN_TYPES = ('CONDITIONING',) + FUNCTION = 'encode' + CATEGORY = 'conditioning' + + def encode(self, clip: comfy.sd.CLIP, text, parser, mean_normalization, multi_conditioning, use_old_emphasis_implementation, with_SDXL, ascore, width, height, crop_w, crop_h, target_width, target_height, text_g, text_l, smZ_steps=1): + params = locals() + params['steps'] = params.pop('smZ_steps', smZ_steps) + from .modules.shared import opts_default as opts + should_use_fp16_signature = inspect.signature(comfy.model_management.should_use_fp16) + _p = should_use_fp16_signature.parameters + devices.device = shared.device = clip.patcher.load_device if hasattr(clip.patcher, 'load_device') else clip.device + if 'device' in _p and 'prioritize_performance' in _p: + should_use_fp16 = partial(comfy.model_management.should_use_fp16, device=devices.device, prioritize_performance=False) + elif 'device' in should_use_fp16_signature.parameters: + should_use_fp16 = partial(comfy.model_management.should_use_fp16, device=devices.device) + else: + should_use_fp16 = comfy.model_management.should_use_fp16 + dtype = torch.float16 if should_use_fp16() else torch.float32 + dtype_unet = dtype + devices.dtype = dtype + if devices.dtype_unet == torch.float16: + devices.dtype_unet = dtype_unet + devices.unet_needs_upcast = opts.upcast_sampling and devices.dtype == torch.float16 and (devices.dtype_unet == torch.float16) + devices.dtype_vae = comfy.model_management.vae_dtype() if hasattr(comfy.model_management, 'vae_dtype') else torch.float32 + params.pop('self', None) + result = run(**params) + result[0][0][1]['params'] = {} + result[0][0][1]['params'].update(params) + if opts.pad_cond_uncond: + text = params['text'] + with_SDXL = params['with_SDXL'] + params['text'] = '' + params['with_SDXL'] = False + empty = run(**params)[0] + params['text'] = text + params['with_SDXL'] = with_SDXL + shared.sd_model.cond_stage_model_empty_prompt = empty[0][0] + return result +``` \ No newline at end of file diff --git a/docs/smZ Settings.md b/docs/smZ Settings.md new file mode 100644 index 0000000..22e4211 --- /dev/null +++ b/docs/smZ Settings.md @@ -0,0 +1,88 @@ +# Documentation +- Class name: smZ_Settings +- Category: advanced +- Output node: False +- Repo Ref: https://github.com/shiimizu/ComfyUI_smZNodes.git + +smZ_Settings 类是用于管理与 Stable Diffusion 模型相关的各种设置的配置节点。它允许用户调整诸如 RNG 源、采样器参数和优化等参数,以根据特定需求调整模型的行为。对于需要高级控制生成过程以实现所需结果的用户来说,此节点至关重要。 + +# Input types +## Optional +- Prompt word wrap length limit + - 此参数定义了将提示文本包装成适合模型令牌限制的块的限制。这对于处理超出模型令牌容量的较长提示至关重要,确保它们在不丢失含义的情况下有效处理。 + - Comfy dtype: INT + - Python dtype: int +- RNG + - RNG 源确定使用的随机数生成器,这显著影响输出的可变性。选择合适的源确保在不同的硬件和软件环境中图像生成的一致性。 + - Comfy dtype: COMBO['cpu', 'gpu', 'nv'] + - Python dtype: str +- eta + - Eta 是 k-diffusion 采样器的一个参数,作为噪声乘数。它控制采样过程中的噪声水平,这可以影响生成图像的细节和质量。 + - Comfy dtype: FLOAT + - Python dtype: float +- Use previous prompt editing timelines + - 此设置允许用户选择以前的提示编辑时间线版本,这对于与特定工作流程的兼容性或在图像生成中实现特定效果可能是必要的。 + - Comfy dtype: BOOLEAN + - Python dtype: bool + +# Output types +- output + - smZ_Settings 节点的输出通常是修改后的模型或基于用户配置更新设置的对象。它反映了将在后续图像生成过程中使用定制参数。 + - Comfy dtype: anytype + - Python dtype: Any + +# Usage tips +- Infra type: CPU + +# Source code +``` +class smZ_Settings: + + @classmethod + def INPUT_TYPES(s): + from .modules.shared import opts_default as opts + import json + i = 0 + + def create_heading(): + nonlocal i + return 'ㅤ' * (i := (i + 1)) + create_heading_value = lambda x: ('STRING', {'multiline': False, 'default': x, 'placeholder': x}) + optional = {create_heading(): create_heading_value('Stable Diffusion'), 'info_comma_padding_backtrack': ('STRING', {'multiline': True, 'placeholder': "Prompt word wrap length limit\nin tokens - for texts shorter than specified, if they don't fit into 75 token limit, move them to the next 75 token chunk"}), 'Prompt word wrap length limit': ('INT', {'default': opts.comma_padding_backtrack, 'min': 0, 'max': 74, 'step': 1}), 'enable_emphasis': (BOOLEAN, {'default': opts.enable_emphasis}), 'info_RNG': ('STRING', {'multiline': True, 'placeholder': 'Random number generator source.\nchanges seeds drastically; use CPU to produce the same picture across different videocard vendors; use NV to produce same picture as on NVidia videocards'}), 'RNG': (['cpu', 'gpu', 'nv'], {'default': opts.randn_source}), create_heading(): create_heading_value('Compute Settings'), 'info_disable_nan_check': ('STRING', {'multiline': True, 'placeholder': 'Disable NaN check in produced images/latent spaces. Only for CFGDenoiser.'}), 'disable_nan_check': (BOOLEAN, {'default': opts.disable_nan_check}), create_heading(): create_heading_value('Sampler parameters'), 'info_eta_ancestral': ('STRING', {'multiline': True, 'placeholder': 'Eta for k-diffusion samplers\nnoise multiplier; currently only applies to ancestral samplers (i.e. Euler a) and SDE samplers'}), 'eta': ('FLOAT', {'default': opts.eta, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'info_s_churn': ('STRING', {'multiline': True, 'placeholder': 'Sigma churn\namount of stochasticity; only applies to Euler, Heun, Heun++2, and DPM2'}), 's_churn': ('FLOAT', {'default': opts.s_churn, 'min': 0.0, 'max': 100.0, 'step': 0.01}), 'info_s_tmin': ('STRING', {'multiline': True, 'placeholder': "Sigma tmin\nenable stochasticity; start value of the sigma range; only applies to Euler, Heun, Heun++2, and DPM2'"}), 's_tmin': ('FLOAT', {'default': opts.s_tmin, 'min': 0.0, 'max': 10.0, 'step': 0.01}), 'info_s_tmax': ('STRING', {'multiline': True, 'placeholder': 'Sigma tmax\n0 = inf; end value of the sigma range; only applies to Euler, Heun, Heun++2, and DPM2'}), 's_tmax': ('FLOAT', {'default': 0.0, 'min': 0.0, 'max': 999.0, 'step': 0.01}), 'info_s_noise': ('STRING', {'multiline': True, 'placeholder': 'Sigma noise\namount of additional noise to counteract loss of detail during sampling'}), 's_noise': ('FLOAT', {'default': opts.s_noise, 'min': 0.0, 'max': 1.1, 'step': 0.001}), 'info_eta_noise_seed_delta': ('STRING', {'multiline': True, 'placeholder': 'Eta noise seed delta\ndoes not improve anything, just produces different results for ancestral samplers - only useful for reproducing images'}), 'ENSD': ('INT', {'default': opts.eta_noise_seed_delta, 'min': 0, 'max': 18446744073709551615, 'step': 1}), 'info_sgm_noise_multiplier': ('STRING', {'multiline': True, 'placeholder': 'SGM noise multiplier\nmatch initial noise to official SDXL implementation - only useful for reproducing images\nsee https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12818'}), 'sgm_noise_multiplier': (BOOLEAN, {'default': opts.sgm_noise_multiplier}), 'info_upcast_sampling': ('STRING', {'multiline': True, 'placeholder': 'upcast sampling.\nNo effect with --force-fp32. Usually produces similar results to --force-fp32 with better performance while using less memory.'}), 'upcast_sampling': (BOOLEAN, {'default': opts.upcast_sampling}), create_heading(): create_heading_value('Optimizations'), 'info_NGMS': ('STRING', {'multiline': True, 'placeholder': 'Negative Guidance minimum sigma\nskip negative prompt for some steps when the image is almost ready; 0=disable, higher=faster. Only for CFGDenoiser.\nsee https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/9177'}), 'NGMS': ('FLOAT', {'default': opts.s_min_uncond, 'min': 0.0, 'max': 15.0, 'step': 0.01}), 'info_pad_cond_uncond': ('STRING', {'multiline': True, 'placeholder': 'Pad prompt/negative prompt to be same length\nimproves performance when prompt and negative prompt have different lengths; changes seeds. Only for CFGDenoiser.'}), 'pad_cond_uncond': (BOOLEAN, {'default': opts.pad_cond_uncond}), 'info_batch_cond_uncond': ('STRING', {'multiline': True, 'placeholder': 'Batch cond/uncond\ndo both conditional and unconditional denoising in one batch; uses a bit more VRAM during sampling, but improves speed. Only for CFGDenoiser.'}), 'batch_cond_uncond': (BOOLEAN, {'default': opts.batch_cond_uncond}), create_heading(): create_heading_value('Compatibility'), 'info_use_prev_scheduling': ('STRING', {'multiline': True, 'placeholder': "Previous prompt editing timelines\nFor [red:green:N]; previous: If N < 1, it's a fraction of steps (and hires fix uses range from 0 to 1), if N >= 1, it's an absolute number of steps; new: If N has a decimal point in it, it's a fraction of steps (and hires fix uses range from 1 to 2), othewrwise it's an absolute number of steps"}), 'Use previous prompt editing timelines': (BOOLEAN, {'default': opts.use_old_scheduling}), create_heading(): create_heading_value('Experimental'), 'info_use_CFGDenoiser': ('STRING', {'multiline': True, 'placeholder': "CFGDenoiser\nAn experimental option to use stable-diffusion-webui's denoiser. It allows you to use the 'Optimizations' settings listed here."}), 'Use CFGDenoiser': (BOOLEAN, {'default': opts.use_CFGDenoiser}), 'info_debug': ('STRING', {'multiline': True, 'placeholder': 'Debugging messages in the console.'}), 'debug': (BOOLEAN, {'default': opts.debug, 'label_on': 'on', 'label_off': 'off'})} + return {'required': {'*': (anytype, {'forceInput': True})}, 'optional': {'extra': ('STRING', {'multiline': True, 'default': '{"show_headings":true,"show_descriptions":false,"mode":"*"}'}), **optional}} + RETURN_TYPES = (anytype,) + FUNCTION = 'run' + CATEGORY = 'advanced' + + def run(self, *args, **kwargs): + first = kwargs.pop('*', None) if '*' in kwargs else args[0] + if not hasattr(first, 'clone') or first is None: + return (first,) + kwargs['s_min_uncond'] = kwargs.pop('NGMS', 0.0) + kwargs['comma_padding_backtrack'] = kwargs.pop('Prompt word wrap length limit') + kwargs['use_old_scheduling'] = kwargs.pop('Use previous prompt editing timelines') + kwargs['use_CFGDenoiser'] = kwargs.pop('Use CFGDenoiser') + kwargs['randn_source'] = kwargs.pop('RNG') + kwargs['eta_noise_seed_delta'] = kwargs.pop('ENSD') + kwargs['s_tmax'] = kwargs['s_tmax'] or float('inf') + from .modules.shared import opts as opts_global + from .modules.shared import opts_default + for (k, v) in opts_default.__dict__.items(): + setattr(opts_global, k, v) + opts = deepcopy(opts_default) + [kwargs.pop(k, None) for k in [k for k in kwargs.keys() if 'info' in k or 'heading' in k or 'ㅤ' in k]] + for (k, v) in kwargs.items(): + setattr(opts, k, v) + first = first.clone() + opts_key = 'smZ_opts' + if type(first) is comfy.model_patcher.ModelPatcher: + first.model_options.pop(opts_key, None) + first.model_options[opts_key] = opts + comfy.sample.prepare_noise = prepare_noise + opts_global.debug = opts.debug + elif type(first) is comfy.sd.CLIP: + first.patcher.model_options.pop(opts_key, None) + first.patcher.model_options[opts_key] = opts + opts_global.debug = opts.debug + return (first,) +``` \ No newline at end of file diff --git a/docs/unCLIP Checkpoint Loader.md b/docs/unCLIP Checkpoint Loader.md new file mode 100644 index 0000000..1df3f8c --- /dev/null +++ b/docs/unCLIP Checkpoint Loader.md @@ -0,0 +1,66 @@ +# Documentation +- Class name: WAS_unCLIP_Checkpoint_Loader +- Category: WAS Suite/Loaders +- Output node: False +- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui + +该节点旨在为WAS套件加载和管理检查点,包括模型、CLIP和VAE组件。它对于初始化WAS框架内进一步处理和分析所需的组件至关重要。 + +# Input types +## Required +- ckpt_name + - 检查点名称是一个必需的参数,它指定要加载的检查点的名称。这对于识别和检索WAS套件操作的正确检查点至关重要。 + - Comfy dtype: str + - Python dtype: str +## Optional +- output_vae + - 'output_vae' 参数决定是否在加载的检查点中包含变分自编码器(VAE)组件。它影响节点返回对象的组成。 + - Comfy dtype: bool + - Python dtype: bool +- output_clip + - 'output_clip' 参指示是否应将CLIP模型作为加载的检查点的一部分。它通过包含或排除CLIP模型来影响节点的输出。 + - Comfy dtype: bool + - Python dtype: bool + +# Output types +- MODEL + - MODEL输出代表从检查点加载的机器学习模型组件。它对于执行需要模型推理或处理的任务非常重要。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- CLIP + - CLIP输出是加载的CLIP模型组件,用于WAS套件内的文本到图像匹配和其他相关任务。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- VAE + - VAE输出表示检查点中的变分自编码器组件。它对于涉及生成模型和潜在空间操作的任务至关重要。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- CLIP_VISION + - CLIP_VISION输出是CLIP模型的视觉组件,负责WAS套件内与图像相关的操作。 + - Comfy dtype: torch.nn.Module + - Python dtype: torch.nn.Module +- NAME_STRING + - NAME_STRING输出提供了没有文件扩展名的加载检查点的基本名称。它对于引用和识别目的非常有用。 + - Comfy dtype: str + - Python dtype: str + +# Usage tips +- Infra type: CPU + +# Source code +``` +class WAS_unCLIP_Checkpoint_Loader: + + @classmethod + def INPUT_TYPES(s): + return {'required': {'ckpt_name': (comfy_paths.get_filename_list('checkpoints'),)}} + RETURN_TYPES = ('MODEL', 'CLIP', 'VAE', 'CLIP_VISION', 'STRING') + RETURN_NAMES = ('MODEL', 'CLIP', 'VAE', 'CLIP_VISION', 'NAME_STRING') + FUNCTION = 'load_checkpoint' + CATEGORY = 'WAS Suite/Loaders' + + def load_checkpoint(self, ckpt_name, output_vae=True, output_clip=True): + ckpt_path = comfy_paths.get_full_path('checkpoints', ckpt_name) + out = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, output_clipvision=True, embedding_directory=comfy_paths.get_folder_paths('embeddings')) + return (out[0], out[1], out[2], out[3], os.path.splitext(os.path.basename(ckpt_name))[0]) +``` \ No newline at end of file diff --git a/docs/xy_Tiling_KSampler.md b/docs/xy_Tiling_KSampler.md new file mode 100644 index 0000000..3b01008 --- /dev/null +++ b/docs/xy_Tiling_KSampler.md @@ -0,0 +1,126 @@ +# Documentation +- Class name: xy_Tiling_KSampler +- Category: Jags_vector/xy_tile_sampler +- Output node: False +- Repo Ref: https://github.com/jags111/ComfyUI_Jags_VectorMagic + +该节点通过应用增强模型生成高分辨率图像能力的平铺策略,促进采样过程的执行。它管理平铺配置并与模型集成,以产生反映所需平铺模式的输出。 + +# Input types +## Required +- model + - 模型参数至关重要,因为它定义了用于采样过程的神经网络架构。它是节点运行的基础,决定了生成图像的质量和特征。 + - Comfy dtype: MODEL + - Python dtype: torch.nn.Module +- seed + - 种子参数初始化随机数生成器,确保采样过程可复现和一致。它在保持结果的可靠性方面发挥着至关重要的作用。 + - Comfy dtype: INT + - Python dtype: int +- steps + - 步数参数决定了采样过程将经历的迭代次数。它直接影响最终输出的收敛性和细节,更多的步数可能会导致图像细节更加精细。 + - Comfy dtype: INT + - Python dtype: int +- cfg + - cfg参数在采样过程中调整模型的配置,影响生成图像的风格和结构。它是控制创意输出的一个重要方面。 + - Comfy dtype: FLOAT + - Python dtype: float +- sampler_name + - sampler_name参数从一组预定义选项中选择特定的采样方法。它在调整节点行为以适应不同要求和预期结果方面发挥着重要作用。 + - Comfy dtype: COMBO + - Python dtype: str +- scheduler + - 调度器参数控制采样过程的节奏和进度,确保节点高效有效地运行。它是平衡性能和质量的关键。 + - Comfy dtype: COMBO + - Python dtype: str +- positive + - 正面参数提供引导采样过程朝向期望特征的条件数据。它对引导生成特定结果至关重要。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- negative + - 负面参数引入采样过程应避免的条件数据。它有助于提炼生成,排除不需要的特征。 + - Comfy dtype: CONDITIONING + - Python dtype: torch.Tensor +- latent_image + - latent_image参数提供了采样过程将要构建的初始潜在表示。它对于设置图像生成的基础至关重要。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- tileX + - tileX参数指定是否在水平方向应用平铺。它影响生成图像平铺的分布和排列。 + - Comfy dtype: INT + - Python dtype: int +- tileY + - tileY参数决定是否在垂直方向应用平铺。它影响图像平铺的堆叠和组合。 + - Comfy dtype: INT + - Python dtype: int +## Optional +- denoise + - 去噪参数控制采样过程中应用的降噪水平。它通过最小化噪声,有助于实现更清晰、更精细的输出。 + - Comfy dtype: FLOAT + - Python dtype: float + +# Output types +- latent + - 潜在参数代表采样过程中产生的中间潜在表示。它是实现最终图像生成的关键步骤。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor +- progress_latent + - 进度潜在参数随着采样的进展捕获不断发展的潜在表示。它反映了图像向其完成状态的迭代细化。 + - Comfy dtype: LATENT + - Python dtype: torch.Tensor + +# Usage tips +- Infra type: GPU + +# Source code +``` +class xy_Tiling_KSampler: + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return {'required': {'model': ('MODEL',), '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,), 'positive': ('CONDITIONING',), 'negative': ('CONDITIONING',), 'latent_image': ('LATENT',), 'denoise': ('FLOAT', {'default': 1.0, 'min': 0.0, 'max': 1.0, 'step': 0.01}), 'tileX': ('INT', {'default': 1, 'min': 0, 'max': 2}), 'tileY': ('INT', {'default': 1, 'min': 0, 'max': 2})}} + RETURN_TYPES = ('LATENT', 'LATENT') + RETURN_NAMES = ('latent', 'progress_latent') + FUNCTION = 'sample' + CATEGORY = 'Jags_vector/xy_tile_sampler' + + def apply_asymmetric_tiling(self, model, tileX, tileY): + for layer in [layer for layer in model.modules() if isinstance(layer, torch.nn.Conv2d)]: + layer.padding_modeX = 'circular' if tileX else 'constant' + layer.padding_modeY = 'circular' if tileY else 'constant' + layer.paddingX = (layer._reversed_padding_repeated_twice[0], layer._reversed_padding_repeated_twice[1], 0, 0) + layer.paddingY = (0, 0, layer._reversed_padding_repeated_twice[2], layer._reversed_padding_repeated_twice[3]) + print(layer.paddingX, layer.paddingY) + + def __hijackConv2DMethods(self, model, tileX: bool, tileY: bool): + for layer in [l for l in model.modules() if isinstance(l, torch.nn.Conv2d)]: + layer.padding_modeX = 'circular' if tileX else 'constant' + layer.padding_modeY = 'circular' if tileY else 'constant' + layer.paddingX = (layer._reversed_padding_repeated_twice[0], layer._reversed_padding_repeated_twice[1], 0, 0) + layer.paddingY = (0, 0, layer._reversed_padding_repeated_twice[2], layer._reversed_padding_repeated_twice[3]) + + def make_bound_method(method, current_layer): + + def bound_method(self, *args, **kwargs): + return method(current_layer, *args, **kwargs) + return bound_method + bound_method = make_bound_method(self.__replacementConv2DConvForward, layer) + layer._conv_forward = bound_method.__get__(layer, type(layer)) + + def __replacementConv2DConvForward(self, layer, input: torch.Tensor, weight: torch.Tensor, bias: Optional[torch.Tensor]): + working = torch.nn.functional.pad(input, layer.paddingX, mode=layer.padding_modeX) + working = torch.nn.functional.pad(working, layer.paddingY, mode=layer.padding_modeY) + return torch.nn.functional.conv2d(working, weight, bias, layer.stride, (0, 0), layer.dilation, layer.groups) + + def __restoreConv2DMethods(self, model): + for layer in [l for l in model.modules() if isinstance(l, torch.nn.Conv2d)]: + layer._conv_forward = torch.nn.Conv2d._conv_forward.__get__(layer, torch.nn.Conv2d) + + def sample(self, model, seed, tileX, tileY, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=1.0): + self.__hijackConv2DMethods(model.model, tileX == 1, tileY == 1) + result = nodes.common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise) + self.__restoreConv2DMethods(model.model) + return result +``` \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 8059d1c..069f4c2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui-nodes-docs" description = "This is a plugin for displaying documentation for each comfyui node. " -version = "1.1.0" +version = "1.1.1" license = "LICENSE" [project.urls] diff --git a/server/request.py b/server/request.py index a043af2..f3682d6 100644 --- a/server/request.py +++ b/server/request.py @@ -141,7 +141,6 @@ async def update_customnode_node_info(request): except Exception as e: return web.json_response({"success": False}) - # ================================== 以下是导出节点文档的代码 ================================== def get_all_files(directory): """ 获取目录下所有文件的路径 """ @@ -204,7 +203,6 @@ async def export_customnode_node_info(request): finally: os.remove(temp_zip.name) # 删除临时文件 - # Add route to import node info @PromptServer.instance.routes.post("/customnode/importNodeInfo") async def import_customnode_node_info(request):