diff --git a/ImageNode.py b/ImageNode.py index c2f525b..b5bb384 100644 --- a/ImageNode.py +++ b/ImageNode.py @@ -92,10 +92,8 @@ def doMask(image,mask,save_image=False,filename_prefix="Mixlab",invert="yes",sav image_file = f"{filename}_{counter:05}_{end}.png" mask_file = f"{filename}_{counter:05}_{end}_mask.png" - # im_tensor=pil2tensor(im) image_path=os.path.join(full_output_folder, image_file) - metadata = None if not args.disable_metadata: metadata = PngInfo() @@ -124,13 +122,42 @@ def doMask(image,mask,save_image=False,filename_prefix="Mixlab",invert="yes",sav "type": "output" if save_image else "temp" }) + im_tensor=pil2tensor(im) return { "result":result, - "image_path":image_path + "image_path":image_path, + "im_tensor":im_tensor } +# 提取不透明部分,裁切图片 +def crop_image_remove_transparent(image): + # 将PIL的Image类型转换为OpenCV的numpy数组 + image_np = cv2.cvtColor(np.array(image), cv2.COLOR_RGBA2BGRA) + + # 分离图像的RGBA通道 + rgba = cv2.split(image_np) + alpha = rgba[3] + + # 使用阈值将非透明部分转换为纯白色(255),透明部分转换为纯黑色(0) + _, mask = cv2.threshold(alpha, 1, 255, cv2.THRESH_BINARY) + + # 查找轮廓 + contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + + # 获取最大轮廓的边界框 + x, y, w, h = cv2.boundingRect(max(contours, key=cv2.contourArea)) + + # 使用边界框裁剪图像 + cropped_image = image_np[y:y+h, x:x+w] + + # 将裁剪后的图像转换为PIL的Image类型 + result_pil = Image.fromarray(cv2.cvtColor(cropped_image, cv2.COLOR_BGRA2RGBA)) + + return result_pil + + def load_image(fp,white_bg=False): i = Image.open(fp) @@ -291,51 +318,48 @@ class FeatheredMask: # 运行的函数 def run(self,mask,start_offset, feathering_weight): + # print(mask.shape,mask.size()) + + image=tensor2pil(mask) + + # Open the image using PIL + image = image.convert("L") + if start_offset>0: + image=ImageOps.invert(image) + + # Convert the image to a numpy array + image_np = np.array(image) + + # Use Canny edge detection to get black contours + edges = cv2.Canny(image_np, 30, 150) + + for i in range(0,abs(start_offset)): + # int(100*feathering_weight) + a=int(abs(start_offset)*0.1*i) + # Dilate the black contours to make them wider + kernel = np.ones((a, a), np.uint8) + + dilated_edges = cv2.dilate(edges, kernel, iterations=1) + # dilated_edges = cv2.erode(edges, kernel, iterations=1) + # Smooth the dilated edges using Gaussian blur + smoothed_edges = cv2.GaussianBlur(dilated_edges, (5, 5), 0) + + # Adjust the feathering weight + feathering_weight = max(0, min(feathering_weight, 1)) + + # Blend the smoothed edges with the original image to achieve feathering effect + image_np = cv2.addWeighted(image_np, 1, smoothed_edges, feathering_weight, feathering_weight) + + # Convert the result back to PIL image + result_image = Image.fromarray(np.uint8(image_np)) + result_image=result_image.convert("L") if start_offset>0: - mask = 1.0 - mask + result_image=ImageOps.invert(result_image) - if hasattr(mask,'numpy'): - image_np=mask.numpy() - else: - image_np=mask - - image = np.uint8(image_np * 255) - # image = cv2.cvtColor(image_cv) - # print(image) - # 使用Canny边缘检测获取黑色轮廓线 - edges = cv2.Canny(image, 30, 150) - - # 对黑色轮廓线进行膨胀操作,使其变宽 - kernel = np.ones((start_offset if start_offset>0 else -start_offset, - start_offset if start_offset>0 else -start_offset), np.uint8) - # dilated_edges = cv2.dilate(edges, kernel, iterations=1) - - # if start_offset>=0: - dilated_edges = cv2.dilate(edges, kernel, iterations=1) - # else: - # dilated_edges = cv2.erode(edges, kernel, iterations=1) - - # 使用高斯滤波平滑黑色轮廓线 - smoothed_edges = cv2.GaussianBlur(dilated_edges, (5, 5), 0) - - # 调整羽化程度 - - # smoothed_edges = cv2.cvtColor(smoothed_edges, cv2.COLOR_GRAY2BGR) - # 将平滑后的黑色轮廓线与原始图片进行融合,实现羽化效果 - result = cv2.addWeighted(image, 1, smoothed_edges, feathering_weight, 0) - - if start_offset>0: - mask = 1.0 - mask - - mask=pil2tensor(result) - - if start_offset>0: - mask = 1.0 - mask - - # "ui":{"images": ui_images, - # return {"ui":{"image": tensor2pil(mask)},"result": (mask,)} - return (mask,) + mask=pil2tensor(result_image) + # print(mask.shape,mask.size()) + return mask @@ -373,8 +397,9 @@ class SplitLongMask: - +# 一个batch传进来 INPUT_IS_LIST = False # mask始终会被拍平,([2, 568, 512]) -- > ([1136, 512]) +# 原因是一个batch传来的 class TransparentImage: @classmethod def INPUT_TYPES(s): @@ -391,7 +416,7 @@ class TransparentImage: "hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"} } - RETURN_TYPES = ('STRING',) + RETURN_TYPES = ('STRING','IMAGE') OUTPUT_NODE = True @@ -399,12 +424,15 @@ class TransparentImage: CATEGORY = "Mixlab/image" - # INPUT_IS_LIST = True - OUTPUT_IS_LIST = (True,) + # INPUT_IS_LIST = True, 一个batch传进来 + OUTPUT_IS_LIST = (True,True,) # OUTPUT_NODE = True # 运行的函数 def run(self,images,masks,invert,save,filename_prefix,prompt=None, extra_pnginfo=None): + # print('TransparentImage',images.shape,images.size()) + # print(masks.shape,masks.size()) + ui_images=[] image_paths=[] @@ -412,6 +440,7 @@ class TransparentImage: masks_new=[] nh=masks.shape[0]//count + #INPUT_IS_LIST = False, 一个batch传进来 if nh*count==masks.shape[0]: masks_new=split_mask_by_new_height(masks,nh) else: @@ -420,6 +449,9 @@ class TransparentImage: is_save=True if save=='yes' else False # filename_prefix += self.prefix_append + + images_res=[] + for i in range(len(images)): image=images[i] mask=masks_new[i] @@ -430,11 +462,13 @@ class TransparentImage: ui_images.append(item) image_paths.append(result['image_path']) + + images_res.append(result['im_tensor']) # ui.images 节点里显示图片,和 传参,image_path自定义的数据,需要写节点的自定义ui # result 里输出给下个节点的数据 - return {"ui":{"images": ui_images,"image_paths":image_paths},"result": (image_paths,)} + return {"ui":{"images": ui_images,"image_paths":image_paths},"result": (image_paths,images_res,)} @@ -511,7 +545,11 @@ class ImagesCrop: "height": ("INT", {"default": 512, "min": 64, "max": MAX_RESOLUTION, "step": 8}), "x": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION, "step": 8}), "y": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION, "step": 8}), - }} + }, + "optional":{ + "auto_transparent": (["enable", "disable"],) + } + } RETURN_TYPES = ("IMAGE",) FUNCTION = "crop" @@ -521,15 +559,26 @@ class ImagesCrop: OUTPUT_IS_LIST = (True,) - def crop(self, images, width, height, x, y): + def crop(self, images, width, height, x, y,auto_transparent): + print('#ImageCrop:',width,auto_transparent,type(images[0])) width=width[0] height=height[0] x=x[0] y=y[0] + auto_transparent=auto_transparent[0] + cropped_images = [] + for img in images: + im=tensor2pil(img) - cropped_img = im.crop((x, y, x + width, y + height)) + + if auto_transparent=='enable': + cropped_img=crop_image_remove_transparent(im) + else: + cropped_img = im.crop((x, y, x + width, y + height)) + cropped_images.append(pil2tensor(cropped_img)) + return (cropped_images,) diff --git a/README.md b/README.md index 0b9ba4a..d17c112 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,10 @@ In progress. https://github.com/shadowcz007/comfyui-mixlab-nodes/assets/12645064/3167aed0-cea0-41f2-9075-b05e0ed08536 + + + + ## Installation For the easiest install experience, install the [Comfyui Manager](https://github.com/ltdrdata/ComfyUI-Manager) and use that to automate the installation process. @@ -31,6 +35,10 @@ install.bat ## Nodes +![main](./assets/all.png) + +[workflow-1](./workflow/1-workflow.json) + > randomPrompt ![randomPrompt](./assets/randomPrompt.png) diff --git a/assets/all.png b/assets/all.png new file mode 100644 index 0000000..d47fce8 Binary files /dev/null and b/assets/all.png differ diff --git a/web/javascript/main.js b/web/javascript/main.js index 3720076..a057e31 100644 --- a/web/javascript/main.js +++ b/web/javascript/main.js @@ -69,7 +69,7 @@ async function shareScreenAndUpload (imgElement) { }; const {Pending}=await getQueue(); - if(Pending<5) document.querySelector('#queue-button').click(); + if(Pending<1) document.querySelector('#queue-button').click(); const videoW = webcamVideo.videoWidth const videoH = webcamVideo.videoHeight diff --git a/workflow/1-workflow.json b/workflow/1-workflow.json new file mode 100644 index 0000000..48ac25f --- /dev/null +++ b/workflow/1-workflow.json @@ -0,0 +1,1133 @@ +{ + "last_node_id": 37, + "last_link_id": 50, + "nodes": [ + { + "id": 4, + "type": "GroundingDinoModelLoader (segment anything)", + "pos": [ + 1273, + 252 + ], + "size": { + "0": 361.20001220703125, + "1": 58 + }, + "flags": {}, + "order": 0, + "mode": 0, + "outputs": [ + { + "name": "GROUNDING_DINO_MODEL", + "type": "GROUNDING_DINO_MODEL", + "links": [ + 2 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "GroundingDinoModelLoader (segment anything)" + }, + "widgets_values": [ + "GroundingDINO_SwinT_OGC (694MB)" + ] + }, + { + "id": 16, + "type": "SplitLongMask", + "pos": [ + 2053, + 112 + ], + "size": { + "0": 315, + "1": 58 + }, + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "name": "long_mask", + "type": "MASK", + "link": 22 + }, + { + "name": "count", + "type": "INT", + "link": 37, + "widget": { + "name": "count" + } + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": [ + 24 + ], + "shape": 6, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "SplitLongMask" + }, + "widgets_values": [ + 2 + ] + }, + { + "id": 11, + "type": "EmptyLatentImage", + "pos": [ + 1293, + -52 + ], + "size": { + "0": 315, + "1": 106 + }, + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "name": "batch_size", + "type": "INT", + "link": 36, + "widget": { + "name": "batch_size" + }, + "slot_index": 0 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 15 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "EmptyLatentImage" + }, + "widgets_values": [ + 512, + 512, + 2 + ] + }, + { + "id": 18, + "type": "MaskListToMaskBatch", + "pos": [ + 2013, + 329 + ], + "size": { + "0": 210, + "1": 26 + }, + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 26 + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": [ + 38 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "MaskListToMaskBatch" + } + }, + { + "id": 6, + "type": "MaskToImage", + "pos": [ + 2146, + 227 + ], + "size": { + "0": 210, + "1": 26 + }, + "flags": {}, + "order": 18, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 34 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 3 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "MaskToImage" + } + }, + { + "id": 10, + "type": "CheckpointLoaderSimple", + "pos": [ + 1019, + -465 + ], + "size": { + "0": 315, + "1": 98 + }, + "flags": {}, + "order": 1, + "mode": 0, + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 39 + ], + "slot_index": 0 + }, + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 16, + 17 + ], + "slot_index": 1 + }, + { + "name": "VAE", + "type": "VAE", + "links": [ + 19 + ], + "slot_index": 2 + } + ], + "properties": { + "Node name for S&R": "CheckpointLoaderSimple" + }, + "widgets_values": [ + "deliberate_v2.safetensors" + ] + }, + { + "id": 23, + "type": "TomePatchModel", + "pos": [ + 1405.4338500976562, + -654.9773330078125 + ], + "size": { + "0": 315, + "1": 58 + }, + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 39 + } + ], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 41 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "TomePatchModel" + }, + "widgets_values": [ + 0.3 + ] + }, + { + "id": 24, + "type": "FreeU_V2", + "pos": [ + 1798, + -680 + ], + "size": { + "0": 315, + "1": 130 + }, + "flags": {}, + "order": 8, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 41 + } + ], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 42 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "FreeU_V2" + }, + "widgets_values": [ + 1.3, + 1.4, + 0.9, + 0.2 + ] + }, + { + "id": 7, + "type": "FeatheredMask", + "pos": [ + 1673, + 284 + ], + "size": { + "0": 315, + "1": 82 + }, + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 24 + } + ], + "outputs": [ + { + "name": "MASK", + "type": "MASK", + "links": [ + 26 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "FeatheredMask" + }, + "widgets_values": [ + 9, + 0.5 + ] + }, + { + "id": 19, + "type": "Reroute", + "pos": [ + 2326, + 411 + ], + "size": [ + 75, + 26 + ], + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "name": "", + "type": "*", + "link": 38 + } + ], + "outputs": [ + { + "name": "", + "type": "MASK", + "links": [ + 34, + 46 + ], + "slot_index": 0 + } + ], + "properties": { + "showOutputText": false, + "horizontal": false + } + }, + { + "id": 14, + "type": "VAEDecode", + "pos": [ + 2277.0850690937427, + -468.5410711699221 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": { + "collapsed": false + }, + "order": 10, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 18 + }, + { + "name": "vae", + "type": "VAE", + "link": 19 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 20, + 21, + 47 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "VAEDecode" + } + }, + { + "id": 36, + "type": "ImagesCrop", + "pos": [ + 3217, + 81 + ], + "size": { + "0": 315, + "1": 154 + }, + "flags": {}, + "order": 21, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 49 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 50 + ], + "shape": 6, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "ImagesCrop" + }, + "widgets_values": [ + 512, + 512, + 0, + 0, + "enable" + ] + }, + { + "id": 22, + "type": "PrimitiveNode", + "pos": [ + 989, + -55 + ], + "size": { + "0": 210, + "1": 82 + }, + "flags": {}, + "order": 2, + "mode": 0, + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 36, + 37 + ], + "widget": { + "name": "batch_size" + }, + "slot_index": 0 + } + ], + "properties": {}, + "widgets_values": [ + 2, + "fixed" + ], + "color": "#322", + "bgcolor": "#533" + }, + { + "id": 15, + "type": "PreviewImage", + "pos": [ + 2656, + -464 + ], + "size": { + "0": 210, + "1": 246 + }, + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 20 + } + ], + "properties": { + "Node name for S&R": "PreviewImage" + } + }, + { + "id": 5, + "type": "PreviewImage", + "pos": [ + 2496, + -90 + ], + "size": { + "0": 328.4773254394531, + "1": 413.53533935546875 + }, + "flags": {}, + "order": 20, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 3 + } + ], + "properties": { + "Node name for S&R": "PreviewImage" + } + }, + { + "id": 35, + "type": "TransparentImage", + "pos": [ + 2848, + 184 + ], + "size": [ + 315, + 338 + ], + "flags": {}, + "order": 19, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 47 + }, + { + "name": "masks", + "type": "MASK", + "link": 46 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null, + "shape": 6 + }, + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 49 + ], + "shape": 6, + "slot_index": 1 + } + ], + "properties": { + "Node name for S&R": "TransparentImage" + }, + "widgets_values": [ + "no", + "yes", + "Mixlab_save" + ] + }, + { + "id": 31, + "type": "PreviewImage", + "pos": [ + 3603, + 87 + ], + "size": [ + 210, + 246 + ], + "flags": {}, + "order": 22, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 50, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "PreviewImage" + } + }, + { + "id": 17, + "type": "PreviewImage", + "pos": [ + 2061, + -183 + ], + "size": { + "0": 210, + "1": 246 + }, + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 23 + } + ], + "properties": { + "Node name for S&R": "PreviewImage" + } + }, + { + "id": 2, + "type": "SAMLoader", + "pos": [ + 1290, + 108 + ], + "size": { + "0": 315, + "1": 82 + }, + "flags": {}, + "order": 3, + "mode": 0, + "outputs": [ + { + "name": "SAM_MODEL", + "type": "SAM_MODEL", + "links": [ + 1 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "SAMLoader" + }, + "widgets_values": [ + "sam_vit_b_01ec64.pth", + "Prefer GPU" + ] + }, + { + "id": 12, + "type": "CLIPTextEncode", + "pos": [ + 1486, + -504 + ], + "size": { + "0": 422.84503173828125, + "1": 164.31304931640625 + }, + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 16 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 13 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "a man ,pose ,full body" + ] + }, + { + "id": 13, + "type": "CLIPTextEncode", + "pos": [ + 1479, + -292 + ], + "size": { + "0": 425.27801513671875, + "1": 180.6060791015625 + }, + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 17 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 14 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "text, watermark,nfws" + ] + }, + { + "id": 3, + "type": "GroundingDinoSAMSegment (segment anything)", + "pos": [ + 1673, + 100 + ], + "size": { + "0": 352.79998779296875, + "1": 122 + }, + "flags": {}, + "order": 12, + "mode": 0, + "inputs": [ + { + "name": "sam_model", + "type": "SAM_MODEL", + "link": 1 + }, + { + "name": "grounding_dino_model", + "type": "GROUNDING_DINO_MODEL", + "link": 2, + "slot_index": 1 + }, + { + "name": "image", + "type": "IMAGE", + "link": 21 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 23 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "MASK", + "type": "MASK", + "links": [ + 22 + ], + "shape": 3, + "slot_index": 1 + } + ], + "properties": { + "Node name for S&R": "GroundingDinoSAMSegment (segment anything)" + }, + "widgets_values": [ + " person,human, head,face, hair , ears,body", + 0.3 + ] + }, + { + "id": 9, + "type": "KSampler", + "pos": [ + 1925, + -500 + ], + "size": { + "0": 315, + "1": 262 + }, + "flags": {}, + "order": 9, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 42 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 13 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 14 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 15 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 18 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "KSampler" + }, + "widgets_values": [ + 145044632830678, + "fixed", + 12, + 8, + "uni_pc", + "normal", + 1 + ] + } + ], + "links": [ + [ + 1, + 2, + 0, + 3, + 0, + "SAM_MODEL" + ], + [ + 2, + 4, + 0, + 3, + 1, + "GROUNDING_DINO_MODEL" + ], + [ + 3, + 6, + 0, + 5, + 0, + "IMAGE" + ], + [ + 13, + 12, + 0, + 9, + 1, + "CONDITIONING" + ], + [ + 14, + 13, + 0, + 9, + 2, + "CONDITIONING" + ], + [ + 15, + 11, + 0, + 9, + 3, + "LATENT" + ], + [ + 16, + 10, + 1, + 12, + 0, + "CLIP" + ], + [ + 17, + 10, + 1, + 13, + 0, + "CLIP" + ], + [ + 18, + 9, + 0, + 14, + 0, + "LATENT" + ], + [ + 19, + 10, + 2, + 14, + 1, + "VAE" + ], + [ + 20, + 14, + 0, + 15, + 0, + "IMAGE" + ], + [ + 21, + 14, + 0, + 3, + 2, + "IMAGE" + ], + [ + 22, + 3, + 1, + 16, + 0, + "MASK" + ], + [ + 23, + 3, + 0, + 17, + 0, + "IMAGE" + ], + [ + 24, + 16, + 0, + 7, + 0, + "MASK" + ], + [ + 26, + 7, + 0, + 18, + 0, + "MASK" + ], + [ + 34, + 19, + 0, + 6, + 0, + "MASK" + ], + [ + 36, + 22, + 0, + 11, + 0, + "INT" + ], + [ + 37, + 22, + 0, + 16, + 1, + "INT" + ], + [ + 38, + 18, + 0, + 19, + 0, + "*" + ], + [ + 39, + 10, + 0, + 23, + 0, + "MODEL" + ], + [ + 41, + 23, + 0, + 24, + 0, + "MODEL" + ], + [ + 42, + 24, + 0, + 9, + 0, + "MODEL" + ], + [ + 46, + 19, + 0, + 35, + 1, + "MASK" + ], + [ + 47, + 14, + 0, + 35, + 0, + "IMAGE" + ], + [ + 49, + 35, + 1, + 36, + 0, + "IMAGE" + ], + [ + 50, + 36, + 0, + 31, + 0, + "IMAGE" + ] + ], + "groups": [], + "config": {}, + "extra": {}, + "version": 0.4 +} \ No newline at end of file