diff --git a/README.md b/README.md index 5fbf854..ed39410 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,10 @@ If you prefer trying a workflow to reading docs, use of the nodes is illustrated Seahorse +## New in 1.6 ## + +- `Masked Section` node to crop images to just the masked area + ## New in 1.5 ## - Floating window for extras and tips @@ -191,6 +195,13 @@ If you use the optional 'tip' input, the contents will be displayed under the ex ## Helper Nodes +### Masked Section + +`Masked Section` takes a mask and a (batch of) images and outputs the images cropped to the bounding box of the mask (with a minimum size). +Here's how you might use it to preview the parts of the image that were changed in img2img (also using `Pick from List` and `Image List from Batch` described below) + +![masked preview](images/maskedsection.png) + ### String handling - `Split String by Commas` allows you to split a text string into up to five pieces, splitting on `,`, `|`, or `^`. It also strips whitespace, so that the strings can be easily parsed, especially by... @@ -204,9 +215,17 @@ Together, these nodes allow you to specify lots of information in the `extras` f There is also a sixth output which is a list of all the strings. -### Pick from List +### List and Batch Handling -The `Image Filter` node outputs a string, `indexes`, which is a comma separated list of the indexes (0 based) of the images selected. Connect this to a `Pick from List` node, and connect a list of anything to the `anything` input, and the `Pick from List` node will output a list corresponding to the selected images. +**When working with multiple images** - `Image Filter` expects a batch, `Mask Image Filter` and `Text Image Filter` need a list. + +So if you generate a load of images using lists of, for instance, prompts, to feed them into `Image Filter` you will want to combine them with the helper node `Batch from Image List`. + +If you generate a batch of images and want to use the `Mask Image Filter` or `Text Image Filter`, which only handle a single image, you will want to do the opposite - convert the batch to a list with `Image List From Batch`. Then the images will be shown sequentially. + +The `Image Filter` node outputs a string, `indexes`, which is a comma separated list of the indexes +(0 based by default, but you can pick a different start value if you need to with `pick_list_start`) of the images selected. +Connect this to a `Pick from List` node, and connect a list of anything to the `anything` input, and the `Pick from List` node will output a list corresponding to the selected images. For instance, if you create a set of images using a list of prompts, this can be used to select the prompts that correspond to the selected images. But you might well want to batch the images if you did use lists - see below. @@ -214,13 +233,7 @@ So something like this: ![image](images/fromlist.png) ---- -### Batch <-> List - -If you are using lists, each node will run once for each list. This means that normally you will want a single batch of images for the `Image Filter` (so if you generate a load of images using lists of, for instance, prompts, you will want to combine them with the helper node `Batch from Image List`) - -If you generate a batch of images and want to use the `Mask Image Filter` or `Text Image Filter`, which only show a single image, you will want to do the opposite - convert the batch to a list with `Image List From Batch`. Then the images will be shown sequentially. --- diff --git a/__init__.py b/__init__.py index 496842e..8cddb7f 100644 --- a/__init__.py +++ b/__init__.py @@ -10,7 +10,7 @@ from .list_utility_nodes import PickFromList, BatchFromImageList, ImageListFromB from .string_utility_nodes import SplitByCommas, StringToFloat, StringToInt from .mask_utility_nodes import MaskedSection -VERSION = "1.5.2" +VERSION = "1.6" WEB_DIRECTORY = "./js" NODE_CLASS_MAPPINGS= { diff --git a/image_filter.py b/image_filter.py index 10eb39f..1c6daa0 100644 --- a/image_filter.py +++ b/image_filter.py @@ -37,6 +37,7 @@ class ImageFilter(PreviewImage): "extra1" : ("STRING", {"default":""}), "extra2" : ("STRING", {"default":""}), "extra3" : ("STRING", {"default":""}), + "pick_list_start" : ("INT", {"default":0, "tooltip":"The number used in pick_list for the first image"}), "pick_list" : ("STRING", {"default":"", "tooltip":"If a comma separated list of integers is provided, the images with these indices will be selected automatically."}), "video_frames" : ("INT", {"default":1, "min":1, "tooltip": "treat each block of n images as a video"}), }, @@ -47,7 +48,7 @@ class ImageFilter(PreviewImage): def IS_CHANGED(cls, pick_list, **kwargs): return pick_list or float("NaN") - def func(self, images, timeout, ontimeout, uid, node_identifier, tip="", extra1="", extra2="", extra3="", latents=None, masks=None, pick_list:str="", video_frames:int=1, **kwargs): + def func(self, images, timeout, ontimeout, uid, node_identifier, tip="", extra1="", extra2="", extra3="", latents=None, masks=None, pick_list_start:int=0, pick_list:str="", video_frames:int=1, **kwargs): e1, e2, e3 = extra1, extra2, extra3 B = images.shape[0] @@ -84,7 +85,7 @@ class ImageFilter(PreviewImage): latents = {"samples": torch.stack(list(latents['samples'][int(i)] for i in images_to_return))} if latents is not None else None masks = torch.stack(list(masks[int(i)] for i in images_to_return)) if masks is not None else None - return (images, latents, masks, e1, e2, e3, ",".join(str(x) for x in images_to_return)) + return (images, latents, masks, e1, e2, e3, ",".join(str(x+pick_list_start) for x in images_to_return)) class TextImageFilterWithExtras(PreviewImage): RETURN_TYPES = ("IMAGE","STRING","STRING","STRING","STRING") diff --git a/images/maskedsection.png b/images/maskedsection.png new file mode 100644 index 0000000..c190517 Binary files /dev/null and b/images/maskedsection.png differ diff --git a/js/image_filter.js b/js/image_filter.js index dcc0eaf..4411e1b 100644 --- a/js/image_filter.js +++ b/js/image_filter.js @@ -13,7 +13,7 @@ app.registerExtension({ settings: [ { id: "Image Filter. Image Filter", - name: "Version 1.5.2", + name: "Version 1.6", type: () => { const x = document.createElement('span') const a = document.createElement('a') diff --git a/pyproject.toml b/pyproject.toml index d643544..80a471b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "cg-image-filter" description = "A set of custom nodes that pause a workflow while you select images, add masks, or edit text." -version = "1.5.2" +version = "1.6" license = { file = "LICENSE" } [project.urls]