diff --git a/README.MD b/README.MD index 2495e56..ccdf2f9 100644 --- a/README.MD +++ b/README.MD @@ -147,6 +147,7 @@ When this error has occurred, please check the network environment. **If the dependency package error after updating, please double clicking ```repair_dependency.bat``` (for Official ComfyUI Protable) or ```repair_dependency_aki.bat``` (for ComfyUI-aki-v1.x) in the plugin folder to reinstall the dependency packages.
+* Commit [ICMask](#ICMask) and [ICMaskCropBack](#ICMaskCropBack) nodes, Used for generating In-Context image and mask, and automatic crop back. The code is from [lrzjason/Comfyui-In-Context-Lora-Utils](https://github.com/lrzjason/Comfyui-In-Context-Lora-Utils) , Thanks to the original author @小志Jason. * Commit [GetMainColorsV2](#GetMainColorsV2) node, add sorting by color area and output color values and proportions in the preview image. This part of the code was improved by @ HL, thanks. * Optimize dependency packages. Optimize some algorithms. * Split some nodes of the dependencies that are prone to problems into [ComfyUI_LayerStyle_Advance](#https://github.com/chflame163/ComfyUI_LayerStyle_Advance) repository. Including: @@ -918,6 +919,35 @@ The following changes have been made based on ImageScaleByAspectRatio: * scale_to_length: The numerical value here serves as the length of the specified edge or the total pixels (kilo pixels) for scale_to_side. * background_color4: The color of the background. +### ICMask +Used for generating In-Context image and mask. The code is from [lrzjason/Comfyui-In-Context-Lora-Utils](https://github.com/lrzjason/Comfyui-In-Context-Lora-Utils) , Thanks to the original author @小志Jason. +![image](image/icmask_example.jpg) + +Node Options: +![image](image/icmask_node.jpg) + +* first_image: Images used as contextual references. +* first_mask: Optional input, context reference image mask. +* second_image: Used for redrawing images. +* second_mask: Mask used for redrawing images. +* patch_mode: There are three types of splicing modes: auto、patch_right and patch_bottom. +* output_length: Output the long side size of the image. +* patch_color: Fill color. + +Outputs: +* image: The output image. +* mask: The output mask. +* icmask_data: The stitching information of the image is used for automatic cropping of subsequent nodes. + +### ICMaskCropBack +Crop the image inference output generated by ICMask. + +Node Options: +![image](image/icmask_crop_back_node.jpg) + +* image: The input image. +* icmask_data: Splicing information output from ICMask node. + ### VQAPrompt diff --git a/README_CN.MD b/README_CN.MD index 2e6270c..4234ca9 100644 --- a/README_CN.MD +++ b/README_CN.MD @@ -128,6 +128,7 @@ os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com' ## 更新说明 **如果本插件更新后出现依赖包错误,请双击运行插件目录下的```install_requirements.bat```(官方便携包),或 ```install_requirements_aki.bat```(秋叶整合包) 重新安装依赖包。 +* 添加 [ICMask](#ICMask) 和 [ICMaskCropBack](#ICMaskCropBack) 节点,用于生成一致性上下文图片和遮罩,以及自动回裁。代码来自[lrzjason/Comfyui-In-Context-Lora-Utils](https://github.com/lrzjason/Comfyui-In-Context-Lora-Utils) 感谢原作者@小志Jason * 添加 [GetMainColorsV2](#GetMainColorsV2) 节点,增加按颜色面积排序,并在预览图中输出色值和比例。这部分代码由@HL完善,感谢。 * 优化依赖包。优化部分图形算法。 * 分拆部分依赖易出问题的节点至[ComfyUI_LayerStyle_Advance](#https://github.com/chflame163/ComfyUI_LayerStyle_Advance)仓库。包括下列节点: @@ -818,6 +819,35 @@ ImageScaleByAspectRatio的V2升级版 * scale_to_length: 这里的数值作为scale_to_side指定边的长度, 或者总像素数量(kilo pixels)。 * background_color4: 背景色。 +### ICMask +用于生成一致性上下文图片和遮罩。代码来自[lrzjason/Comfyui-In-Context-Lora-Utils](https://github.com/lrzjason/Comfyui-In-Context-Lora-Utils) 感谢原作者@小志Jason +![image](image/icmask_example.jpg) + +节点选项说明: +![image](image/icmask_node.jpg) + +* first_image: 用作上下文参考的图像。 +* first_mask: 可选输入,上下文参考图像的遮罩。 +* second_image: 用于重绘的图像。 +* second_mask: 用于重绘的图像的遮罩。 +* patch_mode: 拼接模式,有三种模式:auto、patch_right 和 patch_bottom。patch_right为左右拼接,patch_bottom为上下拼接,auto为自动模式。 +* output_length: 输出图像的长边尺寸。 +* patch_color: 填充颜色。 + +输出: +* image: 输出图像。 +* mask: 输出遮罩。 +* icmask_data: 图像的拼接信息,用于后续节点进行自动裁切。 + +### ICMaskCropBack +对ICMask生成的图像推理输出进行裁切。 + +节点选项说明: +![image](image/icmask_crop_back_node.jpg) + +* image: 图像输入。 +* icmask_data: 从ICMask输出的拼接信息。 + ### VQAPrompt 使用blip-vqa模型进行视觉问答。本节点的部分代码参考自[celoron/ComfyUI-VisualQueryTemplate](https://github.com/celoron/ComfyUI-VisualQueryTemplate),感谢原作者。 diff --git a/image/icmask_crop_back_node.jpg b/image/icmask_crop_back_node.jpg new file mode 100644 index 0000000..af43cbf Binary files /dev/null and b/image/icmask_crop_back_node.jpg differ diff --git a/image/icmask_example.jpg b/image/icmask_example.jpg new file mode 100644 index 0000000..ded5665 Binary files /dev/null and b/image/icmask_example.jpg differ diff --git a/image/icmask_node.jpg b/image/icmask_node.jpg new file mode 100644 index 0000000..3a15f27 Binary files /dev/null and b/image/icmask_node.jpg differ diff --git a/py/ic_mask.py b/py/ic_mask.py new file mode 100644 index 0000000..084a157 --- /dev/null +++ b/py/ic_mask.py @@ -0,0 +1,225 @@ +# code from https://github.com/lrzjason/Comfyui-In-Context-Lora-Utils + +import torch +import numpy as np +from PIL import Image +import cv2 +from .imagefunc import log + + +def resize_img(img, resolution, interpolation=cv2.INTER_CUBIC): + # print(img) + + # print(resolution) + return cv2.resize(img, resolution, interpolation=interpolation) + +def create_image_from_color(width, height, color=(255, 255, 255)): + # OpenCV uses BGR, so convert hex color to BGR if necessary + if isinstance(color, str) and color.startswith('#'): + color = tuple(int(color[i:i + 2], 16) for i in (5, 3, 1))[::-1] + + # Create a blank image with the specified color + blank_image = np.full((height, width, 3), color, dtype=np.uint8) + return blank_image + +def fit_image(image, mask=None, output_length=1536, patch_mode="auto"): + image = image.detach().cpu().numpy() + if mask is not None: + mask = mask.detach().cpu().numpy() + + # print("np.all(mask == 0)",np.all(mask == 0)) + base_length = int(output_length / 3 * 2) + half_length = int(output_length / 2) + image_height, image_width, _ = image.shape + + target_width = int(half_length) + target_height = int(base_length) + + if patch_mode == "auto": + if image_width > image_height: + patch_mode = "patch_bottom" + target_width = int(base_length) + target_height = int(half_length) + else: + patch_mode = "patch_right" + elif patch_mode == "patch_bottom": + target_width = int(base_length) + target_height = int(half_length) + + # 等比例缩放并填充逻辑 + scale_ratio = min(target_width / image_width, target_height / image_height) + + # 计算缩放后的尺寸 + new_width = int(image_width * scale_ratio) + new_height = int(image_height * scale_ratio) + + # 缩放图片 + image = resize_img(image, (new_width, new_height)) + + if mask is not None: + mask = resize_img(mask, (new_width, new_height), cv2.INTER_NEAREST_EXACT) + + # 计算填充的差值 + diff_x = target_width - new_width + diff_y = target_height - new_height + + # 计算填充上下左右的像素 + pad_x = diff_x // 2 + pad_y = diff_y // 2 + + # 添加白色填充到图片,黑色填充到掩码 + resized_image = cv2.copyMakeBorder( + image, + pad_y, diff_y - pad_y, + pad_x, diff_x - pad_x, + cv2.BORDER_CONSTANT, value=(255, 255, 255) + ) + + if mask is not None: + resized_mask = cv2.copyMakeBorder( + mask, + pad_y, diff_y - pad_y, + pad_x, diff_x - pad_x, + cv2.BORDER_CONSTANT, value=(0, 0, 0) + ) + + else: + resized_mask = torch.zeros((target_width, target_height)) + + return resized_image, resized_mask, target_width, target_height, patch_mode + +class ICMask_Data: + def __init__(self, x_offset, y_offset, target_width, target_height, total_width, total_height): + self.x_offset = x_offset + self.y_offset = y_offset + self.target_width = target_width + self.target_height = target_height + self.total_width = total_width + self.total_height = total_height + + +class LS_ICMask: + def __init__(self): + self.NODE_NAME = 'IC_Mask' + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "first_image": ("IMAGE",), + "patch_mode": (["auto", "patch_right", "patch_bottom"], { + "default": "auto", + }), + "output_length": ("INT", { + "default": 1536, + }), + "patch_color": (["#FF0000", "#00FF00", "#0000FF", "#FFFFFF"], { + "default": "#FFFFFF", + }), + }, + "optional": { + "first_mask": ("MASK",), + "second_image": ("IMAGE",), + "second_mask": ("MASK",), + } + } + + RETURN_TYPES = ("IMAGE", "MASK", "ICMASK_DATA",) + RETURN_NAMES = ("image", "mask", "icmask_data",) + FUNCTION = "ic_mask" + CATEGORY = '😺dzNodes/LayerUtility' + + def ic_mask(self, first_image, patch_mode, output_length, patch_color, first_mask=None, second_image=None, + second_mask=None): + + if output_length % 64 != 0: + output_length = output_length - (output_length % 64) + + image1 = first_image[0] + if first_mask is None: + image1_mask = torch.zeros((image1.shape[0], image1.shape[1])) + else: + image1_mask = first_mask[0] + + image1, image1_mask, target_width, target_height, patch_mode = fit_image(image1, image1_mask, output_length, + patch_mode) + if second_image is not None: + image2 = second_image[0] + if second_mask is None: + image2_mask = torch.zeros((image2.shape[0], image2.shape[1])) + else: + image2_mask = second_mask[0] + image2, image2_mask, _, _, _ = fit_image(image2, image2_mask, output_length, patch_mode) + else: + image2 = create_image_from_color(target_width, target_height, color=patch_color) + image2 = torch.from_numpy(image2) + if second_mask is None: + image2_mask = torch.zeros((image2.shape[0], image2.shape[1])) + else: + image2_mask = second_mask[0] + image2, image2_mask, _, _, _ = fit_image(image2, image2_mask, output_length) + + min_y = 0 + min_x = 0 + + if second_mask is None or np.all(image2_mask == 0): + image2_mask = torch.ones((image1.shape[0], image1.shape[1])) + + if patch_mode == "patch_right": + concatenated_image = np.hstack((image1, image2)) + concatenated_mask = np.hstack((image1_mask, image2_mask)) + min_x = 50 + else: + concatenated_image = np.vstack((image1, image2)) + concatenated_mask = np.vstack((image1_mask, image2_mask)) + min_y = 50 + min_y = int(min_y / 100.0 * concatenated_image.shape[0]) + min_x = int(min_x / 100.0 * concatenated_image.shape[1]) + + return_masks = torch.from_numpy(concatenated_mask)[None,] + + concatenated_image = np.clip(255. * concatenated_image, 0, 255).astype(np.float32) / 255.0 + concatenated_image = torch.from_numpy(concatenated_image)[None,] + + return_images = concatenated_image + icmask_data = ICMask_Data(min_x, min_y, target_width, target_height, concatenated_image.shape[1], + concatenated_image.shape[0]) + + return (return_images, return_masks, icmask_data) + + +class LS_ICMask_CropBack: + + def __init__(self): + self.NODE_NAME = 'IC_Mask_Crop_Back' + + @classmethod + def INPUT_TYPES(s): + return {"required": { "image": ("IMAGE",), + "icmask_data": ("ICMASK_DATA",), + }} + RETURN_TYPES = ("IMAGE",) + FUNCTION = "crop" + CATEGORY = '😺dzNodes/LayerUtility' + + def crop(self, image, icmask_data): + width = icmask_data.target_width + height = icmask_data.target_height + x = icmask_data.x_offset + y = icmask_data.y_offset + x = min(x, image.shape[2] - 1) + y = min(y, image.shape[1] - 1) + to_x = width + x + to_y = height + y + img = image[:,y:to_y, x:to_x, :] + return (img,) + +NODE_CLASS_MAPPINGS = { + "LayerUtility: ICMask": LS_ICMask, + "LayerUtility: ICMaskCropBack": LS_ICMask_CropBack, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "LayerUtility: ICMask": "LayerUtility: IC Mask", + "LayerUtility: ICMaskCropBack": "LayerUtility: IC Mask Crop Back" +} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 1a3188b..08acd16 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui_layerstyle" description = "A set of nodes for ComfyUI it generate image like Adobe Photoshop's Layer Style. the Drop Shadow is first completed node, and follow-up work is in progress." -version = "2.0.6" +version = "2.0.7" license = "MIT" dependencies = ["numpy", "pillow", "torch", "matplotlib", "Scipy", "scikit_image", "scikit_learn", "opencv-contrib-python", "pymatting", "timm", "colour-science", "transformers", "blend_modes", "huggingface_hub", "loguru"] diff --git a/workflow/icmask_example.json b/workflow/icmask_example.json new file mode 100644 index 0000000..7b82d3c --- /dev/null +++ b/workflow/icmask_example.json @@ -0,0 +1,1478 @@ +{ + "last_node_id": 439, + "last_link_id": 634, + "nodes": [ + { + "id": 11, + "type": "DualCLIPLoader", + "pos": [ + -360, + 1190 + ], + "size": [ + 320, + 110 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 28 + ], + "slot_index": 0, + "shape": 3, + "label": "CLIP" + } + ], + "properties": { + "Node name for S&R": "DualCLIPLoader", + "ttNbgOverride": { + "color": "#223", + "bgcolor": "#335", + "groupcolor": "#88A" + } + }, + "widgets_values": [ + "clip_l.safetensors", + "t5xxl_fp8_e4m3fn.safetensors", + "flux" + ] + }, + { + "id": 223, + "type": "FluxGuidance", + "pos": [ + 410, + 1580 + ], + "size": [ + 317.4000244140625, + 58 + ], + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [ + { + "name": "conditioning", + "type": "CONDITIONING", + "link": 186, + "label": "conditioning" + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 187 + ], + "slot_index": 0, + "label": "CONDITIONING" + } + ], + "properties": { + "Node name for S&R": "FluxGuidance" + }, + "widgets_values": [ + 30 + ] + }, + { + "id": 333, + "type": "LoadImage", + "pos": [ + -917.3848876953125, + 1819.9569091796875 + ], + "size": [ + 424.71136474609375, + 431.0491638183594 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 610, + 627 + ], + "slot_index": 0, + "label": "IMAGE" + }, + { + "name": "MASK", + "type": "MASK", + "links": [], + "slot_index": 1, + "label": "MASK" + } + ], + "title": "Load Original Image", + "properties": { + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "clipspace/clipspace-mask-1551498.png [input]", + "image" + ] + }, + { + "id": 170, + "type": "CLIPVisionLoader", + "pos": [ + -360, + 1060 + ], + "size": [ + 331.7705383300781, + 58 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "CLIP_VISION", + "type": "CLIP_VISION", + "links": [ + 31 + ], + "slot_index": 0, + "label": "CLIP_VISION" + } + ], + "properties": { + "Node name for S&R": "CLIPVisionLoader" + }, + "widgets_values": [ + "sigclip_vision_patch14_384.safetensors" + ] + }, + { + "id": 172, + "type": "CLIPVisionEncode", + "pos": [ + 20, + 1070 + ], + "size": [ + 307.8326721191406, + 78 + ], + "flags": {}, + "order": 9, + "mode": 0, + "inputs": [ + { + "name": "clip_vision", + "type": "CLIP_VISION", + "link": 31, + "label": "clip_vision" + }, + { + "name": "image", + "type": "IMAGE", + "link": 608, + "label": "image" + } + ], + "outputs": [ + { + "name": "CLIP_VISION_OUTPUT", + "type": "CLIP_VISION_OUTPUT", + "links": [ + 32 + ], + "slot_index": 0, + "label": "CLIP_VISION_OUTPUT" + } + ], + "properties": { + "Node name for S&R": "CLIPVisionEncode" + }, + "widgets_values": [ + "center" + ] + }, + { + "id": 103, + "type": "CLIPTextEncode", + "pos": [ + 20, + 1200 + ], + "size": [ + 309.6630554199219, + 83.49517059326172 + ], + "flags": { + "collapsed": false + }, + "order": 7, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 28, + "label": "clip" + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 181, + 621 + ], + "slot_index": 0, + "label": "CONDITIONING" + } + ], + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "" + ] + }, + { + "id": 102, + "type": "KSampler", + "pos": [ + 780, + 1060 + ], + "size": [ + 315.9761962890625, + 277.810546875 + ], + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 634, + "label": "model" + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 187, + "label": "positive" + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 184, + "label": "negative" + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 185, + "label": "latent_image" + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 11 + ], + "slot_index": 0, + "shape": 3, + "label": "LATENT" + } + ], + "properties": { + "Node name for S&R": "KSampler" + }, + "widgets_values": [ + 0, + "fixed", + 25, + 1, + "euler", + "beta", + 1 + ] + }, + { + "id": 173, + "type": "StyleModelLoader", + "pos": [ + 20, + 1440 + ], + "size": [ + 315, + 58 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "STYLE_MODEL", + "type": "STYLE_MODEL", + "links": [ + 33 + ], + "slot_index": 0, + "label": "STYLE_MODEL" + } + ], + "properties": { + "Node name for S&R": "StyleModelLoader" + }, + "widgets_values": [ + "flux1-redux-dev.safetensors" + ] + }, + { + "id": 171, + "type": "StyleModelApply", + "pos": [ + 410, + 1390 + ], + "size": [ + 311.9229736328125, + 122 + ], + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "name": "conditioning", + "type": "CONDITIONING", + "link": 183, + "label": "conditioning" + }, + { + "name": "style_model", + "type": "STYLE_MODEL", + "link": 33, + "label": "style_model" + }, + { + "name": "clip_vision_output", + "type": "CLIP_VISION_OUTPUT", + "link": 32, + "label": "clip_vision_output" + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 186 + ], + "slot_index": 0, + "label": "CONDITIONING" + } + ], + "properties": { + "Node name for S&R": "StyleModelApply" + }, + "widgets_values": [ + 1, + "multiply" + ] + }, + { + "id": 220, + "type": "InpaintModelConditioning", + "pos": [ + 410, + 1190 + ], + "size": [ + 315, + 138 + ], + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "link": 181, + "label": "positive" + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 621, + "label": "negative" + }, + { + "name": "vae", + "type": "VAE", + "link": 178, + "label": "vae" + }, + { + "name": "pixels", + "type": "IMAGE", + "link": 600, + "label": "pixels" + }, + { + "name": "mask", + "type": "MASK", + "link": 601, + "label": "mask" + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 183 + ], + "slot_index": 0, + "label": "positive" + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 184 + ], + "slot_index": 1, + "label": "negative" + }, + { + "name": "latent", + "type": "LATENT", + "links": [ + 185 + ], + "slot_index": 2, + "label": "latent" + } + ], + "properties": { + "Node name for S&R": "InpaintModelConditioning" + }, + "widgets_values": [ + true + ] + }, + { + "id": 439, + "type": "UNETLoader", + "pos": [ + 410, + 1050 + ], + "size": [ + 315, + 82 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 634 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "UNETLoader" + }, + "widgets_values": [ + "flux1-fill-dev.safetensors", + "default" + ] + }, + { + "id": 10, + "type": "VAELoader", + "pos": [ + -350, + 1360 + ], + "size": [ + 310, + 60 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "VAE", + "type": "VAE", + "links": [ + 12, + 178 + ], + "slot_index": 0, + "shape": 3, + "label": "VAE" + } + ], + "properties": { + "Node name for S&R": "VAELoader", + "ttNbgOverride": { + "color": "#223", + "bgcolor": "#335", + "groupcolor": "#88A" + } + }, + "widgets_values": [ + "ae.sft" + ] + }, + { + "id": 106, + "type": "VAEDecode", + "pos": [ + 1149.213623046875, + 1337.4017333984375 + ], + "size": [ + 210, + 50 + ], + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 11, + "label": "samples" + }, + { + "name": "vae", + "type": "VAE", + "link": 12, + "label": "vae" + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 283, + 593 + ], + "slot_index": 0, + "label": "IMAGE" + } + ], + "properties": { + "Node name for S&R": "VAEDecode", + "ttNbgOverride": { + "color": "#223", + "bgcolor": "#335", + "groupcolor": "#88A" + } + }, + "widgets_values": [] + }, + { + "id": 438, + "type": "LayerMask: MaskGrow", + "pos": [ + 76.37625122070312, + 1873.8795166015625 + ], + "size": [ + 315, + 106 + ], + "flags": {}, + "order": 10, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 632 + } + ], + "outputs": [ + { + "name": "mask", + "type": "MASK", + "links": [ + 633 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "LayerMask: MaskGrow" + }, + "widgets_values": [ + false, + 35, + 10 + ], + "color": "rgba(27, 80, 119, 0.7)" + }, + { + "id": 364, + "type": "LayerUtility: CropByMask V2", + "pos": [ + 76.44383239746094, + 2047.63330078125 + ], + "size": [ + 314.82220458984375, + 262 + ], + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 628 + }, + { + "name": "mask", + "type": "MASK", + "link": 633 + }, + { + "name": "crop_box", + "type": "BOX", + "link": null, + "shape": 7 + } + ], + "outputs": [ + { + "name": "croped_image", + "type": "IMAGE", + "links": [ + 598, + 616 + ], + "slot_index": 0 + }, + { + "name": "croped_mask", + "type": "MASK", + "links": [ + 631 + ], + "slot_index": 1 + }, + { + "name": "crop_box", + "type": "BOX", + "links": [ + 460 + ], + "slot_index": 2 + }, + { + "name": "box_preview", + "type": "IMAGE", + "links": null + } + ], + "properties": { + "Node name for S&R": "LayerUtility: CropByMask V2" + }, + "widgets_values": [ + false, + "mask_area", + 64, + 64, + 64, + 64, + "None" + ], + "color": "rgba(38, 73, 116, 0.7)" + }, + { + "id": 436, + "type": "LayerMask: SegmentAnythingUltra V2", + "pos": [ + -346.82769775390625, + 1879.7652587890625 + ], + "size": [ + 390.7541809082031, + 366 + ], + "flags": {}, + "order": 8, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 627 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 628 + ], + "slot_index": 0 + }, + { + "name": "mask", + "type": "MASK", + "links": [ + 632 + ], + "slot_index": 1 + } + ], + "properties": { + "Node name for S&R": "LayerMask: SegmentAnythingUltra V2" + }, + "widgets_values": [ + "sam_vit_h (2.56GB)", + "GroundingDINO_SwinT_OGC (694MB)", + 0.3, + "VITMatte", + 6, + 6, + 0.15, + 0.99, + true, + "fox", + "cuda", + 2, + false + ], + "color": "rgba(27, 80, 119, 0.7)" + }, + { + "id": 432, + "type": "LayerUtility: ImageMaskScaleAs", + "pos": [ + 1282.739013671875, + 1840.77587890625 + ], + "size": [ + 378, + 162 + ], + "flags": {}, + "order": 20, + "mode": 0, + "inputs": [ + { + "name": "scale_as", + "type": "*", + "link": 616 + }, + { + "name": "image", + "type": "IMAGE", + "link": 615, + "shape": 7 + }, + { + "name": "mask", + "type": "MASK", + "link": null, + "shape": 7 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 617 + ], + "slot_index": 0 + }, + { + "name": "mask", + "type": "MASK", + "links": null + }, + { + "name": "original_size", + "type": "BOX", + "links": null + }, + { + "name": "widht", + "type": "INT", + "links": null + }, + { + "name": "height", + "type": "INT", + "links": null + } + ], + "properties": { + "Node name for S&R": "LayerUtility: ImageMaskScaleAs" + }, + "widgets_values": [ + "crop", + "lanczos" + ], + "color": "rgba(38, 73, 116, 0.7)" + }, + { + "id": 370, + "type": "LayerUtility: RestoreCropBox", + "pos": [ + 1290.447998046875, + 2105.74853515625 + ], + "size": [ + 365.7912902832031, + 118 + ], + "flags": {}, + "order": 21, + "mode": 0, + "inputs": [ + { + "name": "background_image", + "type": "IMAGE", + "link": 610 + }, + { + "name": "croped_image", + "type": "IMAGE", + "link": 617 + }, + { + "name": "crop_box", + "type": "BOX", + "link": 460 + }, + { + "name": "croped_mask", + "type": "MASK", + "link": null, + "shape": 7 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 603 + ], + "slot_index": 0 + }, + { + "name": "mask", + "type": "MASK", + "links": null + } + ], + "properties": { + "Node name for S&R": "LayerUtility: RestoreCropBox" + }, + "widgets_values": [ + false + ], + "color": "rgba(38, 73, 116, 0.7)" + }, + { + "id": 252, + "type": "PreviewImage", + "pos": [ + 1458.465087890625, + 1114.813232421875 + ], + "size": [ + 394.363037109375, + 374.7708740234375 + ], + "flags": {}, + "order": 18, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 283, + "label": "images" + } + ], + "outputs": [], + "properties": { + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + }, + { + "id": 229, + "type": "LoadImage", + "pos": [ + -912.456787109375, + 1296.161376953125 + ], + "size": [ + 422.3544921875, + 438.38287353515625 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 588, + 608 + ], + "slot_index": 0, + "label": "IMAGE" + }, + { + "name": "MASK", + "type": "MASK", + "links": [], + "slot_index": 1, + "label": "MASK" + } + ], + "title": "Load Reference Image", + "properties": { + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "girl_dino_1024.png", + "image" + ] + }, + { + "id": 426, + "type": "LayerUtility: ICMask", + "pos": [ + 509.5188293457031, + 1940.498291015625 + ], + "size": [ + 315, + 166 + ], + "flags": {}, + "order": 12, + "mode": 0, + "inputs": [ + { + "name": "first_image", + "type": "IMAGE", + "link": 588 + }, + { + "name": "first_mask", + "type": "MASK", + "link": null, + "shape": 7 + }, + { + "name": "second_image", + "type": "IMAGE", + "link": 598, + "shape": 7 + }, + { + "name": "second_mask", + "type": "MASK", + "link": 631, + "shape": 7 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 600 + ], + "slot_index": 0 + }, + { + "name": "mask", + "type": "MASK", + "links": [ + 601 + ], + "slot_index": 1 + }, + { + "name": "icmask_data", + "type": "ICMASK_DATA", + "links": [ + 594 + ], + "slot_index": 2 + } + ], + "properties": { + "Node name for S&R": "LayerUtility: ICMask" + }, + "widgets_values": [ + "auto", + 1536, + "#FF0000" + ], + "color": "rgba(38, 73, 116, 0.7)" + }, + { + "id": 427, + "type": "LayerUtility: ICMaskCropBack", + "pos": [ + 909.0380859375, + 1974.3905029296875 + ], + "size": [ + 260.3999938964844, + 46.97600555419922 + ], + "flags": {}, + "order": 19, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 593 + }, + { + "name": "icmask_data", + "type": "ICMASK_DATA", + "link": 594 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 615 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "LayerUtility: ICMaskCropBack" + }, + "widgets_values": [], + "color": "rgba(38, 73, 116, 0.7)" + }, + { + "id": 424, + "type": "PreviewImage", + "pos": [ + 1759.7010498046875, + 1737.902587890625 + ], + "size": [ + 607.7578735351562, + 616.5079345703125 + ], + "flags": {}, + "order": 22, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 603 + } + ], + "outputs": [], + "properties": { + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + } + ], + "links": [ + [ + 11, + 102, + 0, + 106, + 0, + "LATENT" + ], + [ + 12, + 10, + 0, + 106, + 1, + "VAE" + ], + [ + 28, + 11, + 0, + 103, + 0, + "CLIP" + ], + [ + 31, + 170, + 0, + 172, + 0, + "CLIP_VISION" + ], + [ + 32, + 172, + 0, + 171, + 2, + "CLIP_VISION_OUTPUT" + ], + [ + 33, + 173, + 0, + 171, + 1, + "STYLE_MODEL" + ], + [ + 178, + 10, + 0, + 220, + 2, + "VAE" + ], + [ + 181, + 103, + 0, + 220, + 0, + "CONDITIONING" + ], + [ + 183, + 220, + 0, + 171, + 0, + "CONDITIONING" + ], + [ + 184, + 220, + 1, + 102, + 2, + "CONDITIONING" + ], + [ + 185, + 220, + 2, + 102, + 3, + "LATENT" + ], + [ + 186, + 171, + 0, + 223, + 0, + "CONDITIONING" + ], + [ + 187, + 223, + 0, + 102, + 1, + "CONDITIONING" + ], + [ + 283, + 106, + 0, + 252, + 0, + "IMAGE" + ], + [ + 460, + 364, + 2, + 370, + 2, + "BOX" + ], + [ + 588, + 229, + 0, + 426, + 0, + "IMAGE" + ], + [ + 593, + 106, + 0, + 427, + 0, + "IMAGE" + ], + [ + 594, + 426, + 2, + 427, + 1, + "ICMASK_DATA" + ], + [ + 598, + 364, + 0, + 426, + 2, + "IMAGE" + ], + [ + 600, + 426, + 0, + 220, + 3, + "IMAGE" + ], + [ + 601, + 426, + 1, + 220, + 4, + "MASK" + ], + [ + 603, + 370, + 0, + 424, + 0, + "IMAGE" + ], + [ + 608, + 229, + 0, + 172, + 1, + "IMAGE" + ], + [ + 610, + 333, + 0, + 370, + 0, + "IMAGE" + ], + [ + 615, + 427, + 0, + 432, + 1, + "IMAGE" + ], + [ + 616, + 364, + 0, + 432, + 0, + "*" + ], + [ + 617, + 432, + 0, + 370, + 1, + "IMAGE" + ], + [ + 621, + 103, + 0, + 220, + 1, + "CONDITIONING" + ], + [ + 627, + 333, + 0, + 436, + 0, + "IMAGE" + ], + [ + 628, + 436, + 0, + 364, + 0, + "IMAGE" + ], + [ + 631, + 364, + 1, + 426, + 3, + "MASK" + ], + [ + 632, + 436, + 1, + 438, + 0, + "MASK" + ], + [ + 633, + 438, + 0, + 364, + 1, + "MASK" + ], + [ + 634, + 439, + 0, + 102, + 0, + "MODEL" + ] + ], + "groups": [ + { + "id": 1, + "title": "IC Inference", + "bounding": [ + -381.93109130859375, + 938.3604125976562, + 1783.418212890625, + 715.2818603515625 + ], + "color": "#444", + "font_size": 24, + "flags": {} + }, + { + "id": 2, + "title": "Crop Subject", + "bounding": [ + -373.47540283203125, + 1718.31396484375, + 807.8248291015625, + 615.7630004882812 + ], + "color": "#444", + "font_size": 24, + "flags": {} + }, + { + "id": 3, + "title": "Create IC Mask and Crop back", + "bounding": [ + 480.09503173828125, + 1722.6083984375, + 717.63623046875, + 606.0999755859375 + ], + "color": "#3f789e", + "font_size": 24, + "flags": {} + }, + { + "id": 5, + "title": "Restore Subject to Original", + "bounding": [ + 1245.623291015625, + 1726.902587890625, + 448.1443176269531, + 601.8052368164062 + ], + "color": "#444", + "font_size": 24, + "flags": {} + } + ], + "config": {}, + "extra": { + "ds": { + "scale": 0.5644739300537781, + "offset": [ + 1389.037077059614, + -664.2146906381768 + ] + }, + "workspace_info": { + "id": "PpSQDIgnsCwzbb2Minf_g", + "saveLock": false, + "cloudID": null, + "coverMediaPath": null + } + }, + "version": 0.4 +} \ No newline at end of file