diff --git a/nodes/faceenhance.py b/nodes/faceenhance.py index 95a55f9..00c33c0 100644 --- a/nodes/faceenhance.py +++ b/nodes/faceenhance.py @@ -16,6 +16,8 @@ from typing import Tuple class LoadFaceEnhanceModel: + """Loads a GFPGan or RestoreFormer model for face enhancement.""" + def __init__(self) -> None: pass @@ -118,6 +120,8 @@ import sys class RestoreFace: + """Uses GFPGan to restore faces""" + def __init__(self) -> None: pass diff --git a/nodes/image_interpolation.py b/nodes/image_interpolation.py index b5b5c09..d74cf63 100644 --- a/nodes/image_interpolation.py +++ b/nodes/image_interpolation.py @@ -33,6 +33,10 @@ def get_image(filename, subfolder, folder_type): class GetBatchFromHistory: + """Experimental node to load images from the history of the server. + + Queue item without output are ignore in the count.""" + @classmethod def INPUT_TYPES(cls): return { diff --git a/nodes/image_processing.py b/nodes/image_processing.py index e277dd1..394523a 100644 --- a/nodes/image_processing.py +++ b/nodes/image_processing.py @@ -276,6 +276,35 @@ class ImageCompare: return (torch.from_numpy(image),) +import requests + + +class LoadImageFromUrl: + """Load an image from the given URL""" + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "url": ( + "STRING", + { + "default": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Example.jpg/800px-Example.jpg" + }, + ), + } + } + + RETURN_TYPES = ("IMAGE",) + FUNCTION = "load" + CATEGORY = "image" + + def load(self, url): + # get the image from the url + image = Image.open(requests.get(url, stream=True).raw) + return (pil2tensor(image),) + + class Denoise: """Denoise an image using total variation minimization.""" @@ -477,9 +506,7 @@ class ImagePremultiply: class ImageResizeFactor: - """ - Extracted mostly from WAS Node Suite, with a few edits (most notably multiple image support) and less features. - """ + """Extracted mostly from WAS Node Suite, with a few edits (most notably multiple image support) and less features.""" def __init__(self): pass @@ -717,4 +744,5 @@ __nodes__ = [ ImagePremultiply, ImageResizeFactor, SaveImageGrid, + LoadImageFromUrl, ] diff --git a/nodes/mask.py b/nodes/mask.py index 828478d..fac0ac0 100644 --- a/nodes/mask.py +++ b/nodes/mask.py @@ -2,7 +2,10 @@ from rembg import remove from ..utils import pil2tensor, tensor2pil from PIL import Image + class ImageRemoveBackgroundRembg: + """Removes the background from the input using Rembg.""" + def __init__(self): pass @@ -11,47 +14,80 @@ class ImageRemoveBackgroundRembg: return { "required": { "image": ("IMAGE",), - "alpha_matting": (["True","False"], {"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},), - "post_process_mask": (["True","False"], {"default":"False"},), - "bgcolor": ("COLOR", {"default":"black"},), - + "alpha_matting": ( + ["True", "False"], + {"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}, + ), + "post_process_mask": ( + ["True", "False"], + {"default": "False"}, + ), + "bgcolor": ( + "COLOR", + {"default": "black"}, + ), }, } - RETURN_TYPES = ("IMAGE","MASK","IMAGE",) - RETURN_NAMES = ("Image (rgba)","Mask","Image",) + RETURN_TYPES = ( + "IMAGE", + "MASK", + "IMAGE", + ) + RETURN_NAMES = ( + "Image (rgba)", + "Mask", + "Image", + ) FUNCTION = "remove_background" CATEGORY = "image" + # bgcolor: Optional[Tuple[int, int, int, int]] - def remove_background(self, image, alpha_matting, alpha_matting_foreground_threshold, alpha_matting_background_threshold, alpha_matting_erode_size, post_process_mask, bgcolor): + def remove_background( + self, + image, + alpha_matting, + alpha_matting_foreground_threshold, + alpha_matting_background_threshold, + alpha_matting_erode_size, + post_process_mask, + bgcolor, + ): image = remove( - data=tensor2pil(image), - alpha_matting=alpha_matting == "True", - alpha_matting_foreground_threshold=alpha_matting_foreground_threshold, - alpha_matting_background_threshold=alpha_matting_background_threshold, - alpha_matting_erode_size=alpha_matting_erode_size, - session=None, - only_mask=False, - post_process_mask=post_process_mask == "True", - bgcolor=None - ) - - + data=tensor2pil(image), + alpha_matting=alpha_matting == "True", + alpha_matting_foreground_threshold=alpha_matting_foreground_threshold, + alpha_matting_background_threshold=alpha_matting_background_threshold, + alpha_matting_erode_size=alpha_matting_erode_size, + session=None, + only_mask=False, + post_process_mask=post_process_mask == "True", + bgcolor=None, + ) + # extract the alpha to a new image mask = image.getchannel(3) - + # add our bgcolor behind the image image_on_bg = Image.new("RGBA", image.size, bgcolor) - + image_on_bg.paste(image, mask=mask) - - + return (pil2tensor(image), pil2tensor(mask), pil2tensor(image_on_bg)) __nodes__ = [ ImageRemoveBackgroundRembg, -] \ No newline at end of file +] diff --git a/nodes/number.py b/nodes/number.py index cf6c6a1..5113a5a 100644 --- a/nodes/number.py +++ b/nodes/number.py @@ -1,3 +1,27 @@ +class IntToBool: + """Basic int to bool conversion""" + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "int": ( + "INT", + { + "default": 0, + }, + ), + } + } + + RETURN_TYPES = ("BOOL",) + FUNCTION = "int_to_bool" + CATEGORY = "number" + + def int_to_bool(self, int): + return (bool(int),) + + class IntToNumber: """Node addon for the WAS Suite. Converts a "comfy" INT to a NUMBER.""" @@ -8,7 +32,16 @@ class IntToNumber: def INPUT_TYPES(cls): return { "required": { - "int": ("INT", {"default": 0, "min": 0, "max": 1e9, "step": 1}), + "int": ( + "INT", + { + "default": 0, + "min": -1e9, + "max": 1e9, + "step": 1, + "forceInput": True, + }, + ), } } @@ -17,10 +50,46 @@ class IntToNumber: CATEGORY = "number" def int_to_number(self, int): + return (int,) + + +class FloatToNumber: + """Node addon for the WAS Suite. Converts a "comfy" FLOAT to a NUMBER.""" + + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "float": ( + "FLOAT", + { + "default": 0, + "min": -1e9, + "max": 1e9, + "step": 1, + "forceInput": True, + }, + ), + } + } + + RETURN_TYPES = ("NUMBER",) + FUNCTION = "float_to_number" + CATEGORY = "number" + + def float_to_number(self, float): + return (float,) + + return (int,) __nodes__ = [ + FloatToNumber, + IntToBool, IntToNumber, ] \ No newline at end of file