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.
+
+
+Node Options:
+
+
+* 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: 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
+
+
+节点选项说明:
+
+
+* 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: 图像输入。
+* 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