From 484cb1dbbb65857bb59813ed162e5c3866d3f03e Mon Sep 17 00:00:00 2001 From: rodrigoskohl Date: Sat, 19 Jul 2025 22:27:48 -0300 Subject: [PATCH] feat: update to version 2.0.0 with new features --- README.md | 82 +- __init__.py | 12 +- assets/image.png | Bin 0 -> 106542 bytes node/node.py | 181 +- node/pipeline.py | 391 +-- node/utils.py | 1 - pyproject.toml | 2 +- requirements.txt | 17 +- workflow/example.json | 217 -- workflow/stable-desing-for-comfyui.json | 3068 +++++++++++++++++++++++ 10 files changed, 3374 insertions(+), 597 deletions(-) create mode 100644 assets/image.png delete mode 100644 workflow/example.json create mode 100644 workflow/stable-desing-for-comfyui.json diff --git a/README.md b/README.md index 2047454..c37646d 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,82 @@
-# Interior Design for Comfyui +# ๐Ÿ›‹๏ธ Interior Design for ComfyUI v2.0
-This node adapts [StableDesign: 2nd place solution for the Generative Interior Design 2024 competition](https://huggingface.co/spaces/MykolaL/StableDesign) to use directly on ComfyUI. +This project adapts the original pipeline from +[StableDesign: 2nd place solution for the Generative Interior Design 2024 competition](https://huggingface.co/spaces/MykolaL/StableDesign) +to work **natively and fully inside ComfyUI**, leveraging modern custom nodes and a modular architecture. -More about this pipeline works, see this post on [Medium](https://medium.com/@melgor89/generative-interior-design-challenge-2024-2nd-place-solution-6338f19f6fe3) -# -The pipeline automatically downloads trained models of `controlnet_depth` and `own_controlnet` to the local script of ComfyUI runs in folder `./custom_models`. Other models are downloaded to the `.cache` folder of Hugging Face. +Learn more about the original method in this [Medium article](https://medium.com/@melgor89/generative-interior-design-challenge-2024-2nd-place-solution-6338f19f6fe3). -This node is available on [ComfyUI Manager](https://github.com/ltdrdata/ComfyUI-Manager) -![image](https://github.com/user-attachments/assets/44e3520c-1b42-41a2-8996-47e5fb37d9a1) +--- + +## โœ… Key Features + +- **Fully restructured for ComfyUI compatibility** +- Includes 3 custom nodes developed specifically for this repository: + - `"Interior Design Segmentator"` + - `"Image Normalize"` + - `"Control Items"` +- Uses additional advanced custom nodes: + - [Depth Anything V2](https://github.com/DepthAnything/Depth-Anything-V2) + - [ComfyUI_IPAdapter_plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) +- Reimplements only the **necessary components** from the original pipeline, such as: + - **Semantic segmenter** using [`openmmlab/upernet-convnext-small`](https://huggingface.co/openmmlab/upernet-convnext-small) +- Supports standard ComfyUI workflows with **ControlNet and IP Adapter integration** +- Compatible with other workflows and custom models +- Inference is significantly faster than the original pipeline (test the workflow and compare). + +--- + +## ๐Ÿงฑ Pipeline Overview + +- The idea was to use as many nodes from the ComfyUI core as possible. However, for certain tasks, I had to rely on custom nodes or adapt my own nodes to stay as faithful as possible to the original pipeline, or alternatively, use dependencies from other custom node repositories. +- Uses the **same base models** as the original StableDesign pipeline +- Includes **custom ControlNet models**: + - `controlnet_depth` + - `own_controlnet` (segmentation) +- These ControlNets, along with the depth map and segmentation map, are passed into the **UNet** of the diffusion model +- Final step includes **refinement with latent noise injection and up/down-scaling**(because of the size limitation of the original pipeline) + +--- + +## ๐Ÿ“ Example Workflow + +An example workflow is included in this repository: +[`stable-design-for-comfyui.json`](./workflow/stable-design-for-comfyui.json) + +You can load it directly into ComfyUI to test or extend the pipeline. + +![Preview](./assets/image.png) + +--- + +## ๐Ÿ“ฆ Installation & Dependencies + +This node is available on [ComfyUI Manager](https://github.com/ltdrdata/ComfyUI-Manager) +You must also install the following custom nodes manually if not yet available: + +- [Depth Anything V2](https://github.com/DepthAnything/Depth-Anything-V2) +- [ComfyUI_IPAdapter_plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) *(note: unmaintained)* +- [ComfyMath](https://github.com/evanspearman/ComfyMath) + +--- + +## ๐Ÿ”ง Upcoming Features + +- **Expansion of Control Items**: Add support for more semantic regions and control inputs to increase flexibility and detail in generation. +- **Evaluation of CLIP Conditioning**: Reassess the combination of positive and negative CLIP embeddings in ControlNet to verify if results match the original pipeline's behavior. +- **Custom IP Adapter Node**: Implement a native IP Adapter node to replace the current dependency on `ComfyUI_IPAdapter_plus`, which is currently unmaintained. + +--- + +## ๐Ÿงช License & Acknowledgements + +Original pipeline by MykolaL ([StableDesign on Hugging Face](https://huggingface.co/spaces/MykolaL/StableDesign)) +This adaptation reuses only essential logic, converted to full ComfyUI-compatible workflow format. + +--- + +feel free to open issues and PRs diff --git a/__init__.py b/__init__.py index 1d50455..7013287 100644 --- a/__init__.py +++ b/__init__.py @@ -1,13 +1,19 @@ from .node.node import InteriorDesignNode +from .node.node import ImageNormalize +from .node.node import ControlItems -# Registra o nรณ no ComfyUI NODE_CLASS_MAPPINGS = { - "interior-design-for-comfyui": InteriorDesignNode, + "Interior Design Segmentator": InteriorDesignNode, + "Image Normalize": ImageNormalize, + "Control Items": ControlItems, + } NODE_DISPLAY_NAME_MAPPINGS = { - "interior-design-for-comfyui": "Interior Design for ComfyUI", + "Interior Design Segmentator": "Interior Design Segmentator", + "Image Normalize": "Image Resize Normalizer", + "Control Items": "Control Items Selector", } diff --git a/assets/image.png b/assets/image.png new file mode 100644 index 0000000000000000000000000000000000000000..228bcf4dcc4889acf667e4b2e9f9b4349ac474cf GIT binary patch literal 106542 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 torch.Tensor: + + if images.dim() == 4 and images.shape[-1] == 3: + images = images.permute(0, 3, 1, 2) + + b, c, h, w = images.shape + + max_dim = max(h, w) + scale = target_size / max_dim if max_dim > target_size else 1.0 + + new_h = int(h * scale) + new_w = int(w * scale) + + new_h = ((new_h + multiple - 1) // multiple) * multiple + new_w = ((new_w + multiple - 1) // multiple) * multiple + + resized = F.interpolate( + images, size=(new_h, new_w), mode=mode, + align_corners=False if mode in ['linear', 'bilinear', 'bicubic', 'trilinear'] else None ) - design_image = pil_to_tensor(design_image, self.device, self.dtype) - return (design_image,) -def tensor_to_pil(image_tensor): - print(f"Tensor: {image_tensor.shape},{image_tensor.dtype}") - if image_tensor.ndimension() == 4: - image_tensor = image_tensor.squeeze(0) # Remove a dimensรฃo do batch - image_tensor = image_tensor.permute(2, 0, 1) # Troca de [altura, largura, canais] -> [canais, altura, largura] - if image_tensor.shape[0] == 4: - image_tensor = image_tensor[:3] - to_pil = ToPILImage() - pil_image = to_pil(image_tensor) - print(f"Imagem PIL: {pil_image.size},{pil_image.mode}") - return pil_image + resized = resized.permute(0, 2, 3, 1) -def pil_to_tensor(image_pil, device, dtype): - print(f"Imagem PIL: {image_pil.size},{image_pil.mode}") - to_tensor = transforms.ToTensor() - tensor = to_tensor(image_pil) - tensor = tensor.permute(1, 2, 0) # Troca de [canais, altura, largura] -> [altura, largura, canais] - tensor = tensor.unsqueeze(0) # Adiciona a dimensรฃo do batch - tensor = tensor.to(device, dtype=dtype) - print(f"Tensor: {tensor.shape},{tensor.dtype}") - return tensor \ No newline at end of file + return (resized,) + + +class ControlItems: + def __init__(self): + self.device = get_torch_device() + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "window": ("BOOLEAN", {"default": True}), + "door": ("BOOLEAN", {"default": True}), + "staircase": ("BOOLEAN", {"default": False}), + }, + } + + RETURN_TYPES = ("CONTROL_ITEMS",) + RETURN_NAMES = ("CONTROL_ITEMS",) + FUNCTION = "process" + CATEGORY = "control" + + def process(self, window: bool, door: bool, staircase: bool): + control_items = [] + if window: + control_items.append("windowpane;window") + if door: + control_items.append("door;double;door") + if staircase: + control_items.append("stairway;staircase") + return (control_items,) diff --git a/node/pipeline.py b/node/pipeline.py index bbb87e5..3aec9c3 100644 --- a/node/pipeline.py +++ b/node/pipeline.py @@ -1,319 +1,126 @@ -from typing import Tuple, Union, List - +from typing import Tuple,List, Union import numpy as np from PIL import Image - -import torch -from diffusers.pipelines.controlnet import StableDiffusionControlNetInpaintPipeline -from diffusers import ControlNetModel, UniPCMultistepScheduler, AutoPipelineForText2Image from transformers import AutoImageProcessor, UperNetForSemanticSegmentation, AutoModelForDepthEstimation from .colors import ade_palette from .utils import map_colors_rgb -from diffusers import StableDiffusionXLPipeline -import gc -import os -from huggingface_hub import hf_hub_download -import folder_paths +import torch +from torch import Tensor +from transformers import AutoImageProcessor, UperNetForSemanticSegmentation +# ------------------- +# Classe principal +# ------------------- -repo_id = "MykolaL/StableDesign" -file_name = "diffusion_pytorch_model.safetensors" -models = ["controlnet_depth", "own_controlnet"] -rootfolder = folder_paths.folder_names_and_paths["controlnet"][0][0] +class SimplifiedSegmenter: + def __init__(self, device: str = "cuda"): + self.device = device -def check_and_download(model_name,rootfolder): - hf_hub_download( - repo_id=repo_id, - filename=file_name, - subfolder= model_name, - local_dir=rootfolder, - repo_type="space" - ) - hf_hub_download( - repo_id=repo_id, - filename="config.json", - subfolder= model_name, - local_dir=rootfolder, - repo_type="space" - ) -for model_name in models: - model_path = os.path.join(rootfolder, model_name) - check_and_download(model_name,rootfolder) - - -device = "cuda" -dtype = torch.float16 - - -def filter_items( - colors_list: Union[List, np.ndarray], - items_list: Union[List, np.ndarray], - items_to_remove: Union[List, np.ndarray] -) -> Tuple[Union[List, np.ndarray], Union[List, np.ndarray]]: - """ - Filters items and their corresponding colors from given lists, excluding - specified items. - Args: - colors_list: A list or numpy array of colors corresponding to items. - items_list: A list or numpy array of items. - items_to_remove: A list or numpy array of items to be removed. - Returns: - A tuple of two lists or numpy arrays: filtered colors and filtered - items. - """ - filtered_colors = [] - filtered_items = [] - for color, item in zip(colors_list, items_list): - if item not in items_to_remove: - filtered_colors.append(color) - filtered_items.append(item) - return filtered_colors, filtered_items - -def get_segmentation_pipeline( -) -> Tuple[AutoImageProcessor, UperNetForSemanticSegmentation]: - """Method to load the segmentation pipeline - Returns: - Tuple[AutoImageProcessor, UperNetForSemanticSegmentation]: segmentation pipeline - """ - image_processor = AutoImageProcessor.from_pretrained( - "openmmlab/upernet-convnext-small" - ) - image_segmentor = UperNetForSemanticSegmentation.from_pretrained( - "openmmlab/upernet-convnext-small" - ) - return image_processor, image_segmentor - - -def segment_image( - image: Image, - image_processor: AutoImageProcessor, - image_segmentor: UperNetForSemanticSegmentation -) -> Image: - """ - Segments an image using a semantic segmentation model. - Args: - image (Image): The input image to be segmented. - image_processor (AutoImageProcessor): The processor to prepare the - image for segmentation. - image_segmentor (UperNetForSemanticSegmentation): The semantic - segmentation model used to identify different segments in the image. - Returns: - Image: The segmented image with each segment colored differently based - on its identified class. - """ - # image_processor, image_segmentor = get_segmentation_pipeline() - pixel_values = image_processor(image, return_tensors="pt").pixel_values - with torch.no_grad(): - outputs = image_segmentor(pixel_values) - - seg = image_processor.post_process_semantic_segmentation( - outputs, target_sizes=[image.size[::-1]])[0] - color_seg = np.zeros((seg.shape[0], seg.shape[1], 3), dtype=np.uint8) - palette = np.array(ade_palette()) - for label, color in enumerate(palette): - color_seg[seg == label, :] = color - color_seg = color_seg.astype(np.uint8) - seg_image = Image.fromarray(color_seg).convert('RGB') - return seg_image - - -def get_depth_pipeline(): - feature_extractor = AutoImageProcessor.from_pretrained("LiheYoung/depth-anything-large-hf", - torch_dtype=dtype) - depth_estimator = AutoModelForDepthEstimation.from_pretrained("LiheYoung/depth-anything-large-hf", - torch_dtype=dtype) - return feature_extractor, depth_estimator - - -def get_depth_image( - image: Image, - feature_extractor: AutoImageProcessor, - depth_estimator: AutoModelForDepthEstimation -) -> Image: - image_to_depth = feature_extractor(images=image, return_tensors="pt").to(device) - with torch.no_grad(): - depth_map = depth_estimator(**image_to_depth).predicted_depth - - width, height = image.size - depth_map = torch.nn.functional.interpolate( - depth_map.unsqueeze(1).float(), - size=(height, width), - mode="bicubic", - align_corners=False, - ) - depth_min = torch.amin(depth_map, dim=[1, 2, 3], keepdim=True) - depth_max = torch.amax(depth_map, dim=[1, 2, 3], keepdim=True) - depth_map = (depth_map - depth_min) / (depth_max - depth_min) - image = torch.cat([depth_map] * 3, dim=1) - - image = image.permute(0, 2, 3, 1).cpu().numpy()[0] - image = Image.fromarray((image * 255.0).clip(0, 255).astype(np.uint8)) - return image - - -def resize_dimensions(dimensions, target_size): - """ - Resize PIL to target size while maintaining aspect ratio - If smaller than target size leave it as is - """ - width, height = dimensions - - # Check if both dimensions are smaller than the target size - if width < target_size and height < target_size: - return dimensions - - # Determine the larger side - if width > height: - # Calculate the aspect ratio - aspect_ratio = height / width - # Resize dimensions - return (target_size, int(target_size * aspect_ratio)) - else: - # Calculate the aspect ratio - aspect_ratio = width / height - # Resize dimensions - return (int(target_size * aspect_ratio), target_size) - - -def flush(): - gc.collect() - torch.cuda.empty_cache() - - -class ControlNetDepthDesignModelMulti: - """ Produces random noise images """ - - def __init__(self): - """ Initialize your model(s) here """ - #os.environ['HF_HUB_OFFLINE'] = "True" - self.ip_adapter_scale = 0.4 - self.ip_adapter_model = "ip-adapter_sd15.bin" - self.seed = 323*111 - self.neg_prompt = "window, door, low resolution, banner, logo, watermark, text, deformed, blurry, out of focus, surreal, ugly, beginner" - self.control_items = ["windowpane;window", "door;double;door"] - self.additional_quality_suffix = "interior design, 4K, high resolution, photorealistic" - - - - self.controlnet_depth = ControlNetModel.from_pretrained( - rootfolder,subfolder="controlnet_depth", - torch_dtype=dtype, - use_safetensors=True + print("๐Ÿ”„ Loading segmentator...") + self.image_processor = AutoImageProcessor.from_pretrained( + "openmmlab/upernet-convnext-small" ) - - self.controlnet_seg = ControlNetModel.from_pretrained( - rootfolder,subfolder="own_controlnet", - torch_dtype=dtype, - use_safetensors=True + self.image_segmentor = UperNetForSemanticSegmentation.from_pretrained( + "openmmlab/upernet-convnext-small" ) + self.image_segmentor.eval() - self.pipe = StableDiffusionControlNetInpaintPipeline.from_pretrained( - "SG161222/Realistic_Vision_V5.1_noVAE", - controlnet=[self.controlnet_depth, self.controlnet_seg], - safety_checker=None, - torch_dtype=dtype, - ) - + def tensor_to_pil(self, tensor: Tensor) -> Image.Image: + if tensor.max() > 1.0: + arr = tensor.cpu().permute(1, 2, 0).numpy().astype(np.uint8) + else: + arr = (tensor.cpu().permute(1, 2, 0).numpy() * 255).astype(np.uint8) + return Image.fromarray(arr) - self.pipe.load_ip_adapter("h94/IP-Adapter", subfolder="models", - weight_name=self.ip_adapter_model,) - self.pipe.set_ip_adapter_scale(self.ip_adapter_scale) - self.pipe.scheduler = UniPCMultistepScheduler.from_config(self.pipe.scheduler.config) - self.pipe = self.pipe.to(device) - - self.guide_pipe = StableDiffusionXLPipeline.from_pretrained( - "segmind/SSD-1B", - torch_dtype=dtype, - use_safetensors=True, - variant="fp16" - ) - self.guide_pipe = self.guide_pipe.to(device) - - self.seg_image_processor, self.image_segmentor = get_segmentation_pipeline() - self.depth_feature_extractor, self.depth_estimator = get_depth_pipeline() - self.depth_estimator = self.depth_estimator.to(device) - - def generate_design(self, empty_room_image: Image, prompt: str, guidance_scale: int = 10, num_steps: int = 50, strength: float =0.9, img_size: int = 640, img_dept_threshold=0.5, img_seg_threshold=0.5 ) -> Image: + def segment_image(self, + image: Image, + ) -> Image: """ - Given an image of an empty room and a prompt - generate the designed room according to the prompt - Inputs - - empty_room_image - An RGB PIL Image of the empty room - prompt - Text describing the target design elements of the room - Returns - - design_image - PIL Image of the same size as the empty room image - If the size is not the same the submission will fail. + Segments an image using a semantic segmentation model. + Args: + image (Image): The input image to be segmented. + image_processor (AutoImageProcessor): The processor to prepare the + image for segmentation. + image_segmentor (UperNetForSemanticSegmentation): The semantic + segmentation model used to identify different segments in the image. + Returns: + Image: The segmented image with each segment colored differently based + on its identified class. """ - print(f"Positive Prompt: {prompt}") - print(f"Negative Prompt: {self.neg_prompt}") - print(f"Seed: {self.seed}") - print(f"IP Adapter Scale: {self.ip_adapter_scale}") + # image_processor, image_segmentor = get_segmentation_pipeline() + pixel_values = self.image_processor(image, return_tensors="pt").pixel_values + image_size = image.size[::-1] + print(f"Image size: {image_size}, pixel_values shape: {pixel_values.shape}") + with torch.no_grad(): + outputs = self.image_segmentor(pixel_values) + + seg = self.image_processor.post_process_semantic_segmentation( + outputs, target_sizes=[image_size])[0] + color_seg = np.zeros((seg.shape[0], seg.shape[1], 3), dtype=np.uint8) + palette = np.array(ade_palette()) + for label, color in enumerate(palette): + color_seg[seg == label, :] = color + color_seg = color_seg.astype(np.uint8) + seg_image = Image.fromarray(color_seg).convert('RGB') + return seg_image + + @staticmethod + def filter_items( + colors_list: Union[List, np.ndarray], + items_list: Union[List, np.ndarray], + items_to_remove: Union[List, np.ndarray] + ) -> Tuple[Union[List, np.ndarray], Union[List, np.ndarray]]: + """ + Filters items and their corresponding colors from given lists, excluding + specified items. + Args: + colors_list: A list or numpy array of colors corresponding to items. + items_list: A list or numpy array of items. + items_to_remove: A list or numpy array of items to be removed. + Returns: + A tuple of two lists or numpy arrays: filtered colors and filtered + items. + """ + filtered_colors = [] + filtered_items = [] + for color, item in zip(colors_list, items_list): + if item not in items_to_remove: + filtered_colors.append(color) + filtered_items.append(item) + return filtered_colors, filtered_items + - flush() - self.generator = torch.Generator(device=device).manual_seed(self.seed) - - pos_prompt = prompt + f', {self.additional_quality_suffix}' - - orig_w, orig_h = empty_room_image.size - new_width, new_height = resize_dimensions(empty_room_image.size, img_size) - input_image = empty_room_image.resize((new_width, new_height)) - real_seg = np.array(segment_image(input_image, - self.seg_image_processor, - self.image_segmentor)) + def __call__(self, images: Tensor, control_items: List) -> Tuple[Tensor, Tensor]: + """ + images: Tensor (B,C,H,W) ou (C,H,W) + Returns: + seg_cond_tensor: (B,3,H,W) uint8 + mask_tensor: (B,1,H,W) float 0/1 + """ + print(f'Control items: {control_items}') + if images.dim() == 4: + input_image = self.tensor_to_pil(images[0]) + else: + input_image = self.tensor_to_pil(images) + real_seg = np.array(self.segment_image(input_image)) unique_colors = np.unique(real_seg.reshape(-1, real_seg.shape[2]), axis=0) unique_colors = [tuple(color) for color in unique_colors] segment_items = [map_colors_rgb(i) for i in unique_colors] - chosen_colors, segment_items = filter_items( + chosen_colors, segment_items = self.filter_items( colors_list=unique_colors, items_list=segment_items, - items_to_remove=self.control_items + items_to_remove=control_items ) - mask = np.zeros_like(real_seg) + mask = np.zeros((real_seg.shape[0], real_seg.shape[1]), dtype=np.uint8) for color in chosen_colors: color_matches = (real_seg == color).all(axis=2) mask[color_matches] = 1 - image_np = np.array(input_image) - image = Image.fromarray(image_np).convert("RGB") - mask_image = Image.fromarray((mask * 255).astype(np.uint8)).convert("RGB") - segmentation_cond_image = Image.fromarray(real_seg).convert("RGB") - - image_depth = get_depth_image(image, self.depth_feature_extractor, self.depth_estimator) - - # generate image that would be used as IP-adapter - flush() - new_width_ip = int(new_width / 8) * 8 - new_height_ip = int(new_height / 8) * 8 - ip_image = self.guide_pipe(pos_prompt, - num_inference_steps=num_steps, - negative_prompt=self.neg_prompt, - height=new_height_ip, - width=new_width_ip, - generator=[self.generator]).images[0] - - flush() - generated_image = self.pipe( - prompt=pos_prompt, - negative_prompt=self.neg_prompt, - num_inference_steps=num_steps, - strength=strength, - guidance_scale=guidance_scale, - generator=[self.generator], - image=image, - mask_image=mask_image, - ip_adapter_image=ip_image, - control_image=[image_depth, segmentation_cond_image], - controlnet_conditioning_scale=[img_dept_threshold, img_seg_threshold] - ).images[0] - - flush() - design_image = generated_image.resize( - (orig_w, orig_h), Image.Resampling.LANCZOS - ) - - return design_image - - - + seg_cond_image = Image.fromarray(real_seg).convert("RGB") + seg_cond_tensor = torch.from_numpy(np.array(seg_cond_image)).permute(2,0,1).unsqueeze(0).to(self.device).float() / 255.0 # shape (1,3,H,W) + mask_tensor = torch.from_numpy(mask).unsqueeze(0).unsqueeze(0).float() # shape (1,1,H,W) + mask_tensor = mask_tensor.to('cpu') # move to cpu (avoid bug when use the mask on IP Adapter?) + print(f'Shape of seg_cond_tensor: {seg_cond_tensor.shape}, mask_tensor: {mask_tensor.shape}') + return seg_cond_tensor, mask_tensor diff --git a/node/utils.py b/node/utils.py index 6c8ee73..fa787a6 100644 --- a/node/utils.py +++ b/node/utils.py @@ -1,5 +1,4 @@ import gc - import numpy as np from PIL import Image import torch diff --git a/pyproject.toml b/pyproject.toml index e4cefeb..3fda407 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "interior-design-for-comfyui" description = "This node is based on MykolaL/StableDesign" -version = "1.1.5" +version = "2.0.0" license = {file = "LICENSE"} [project.urls] diff --git a/requirements.txt b/requirements.txt index a19199d..30b93b6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,12 +1,5 @@ -transformers==4.48.0 -huggingface_hub==0.30.2 -accelerate==1.6.0 -altair==5.5.0 -diffusers==0.33.1 -numpy==1.26.4 -opencv-python==4.11.0.86 -pillow==11.2.1 -scipy==1.15.2 -torchvision -transformers==4.48.0 -xformers==0.0.29.post3 +torch +transformers +Pillow +numpy +scipy \ No newline at end of file diff --git a/workflow/example.json b/workflow/example.json deleted file mode 100644 index 35ff0e0..0000000 --- a/workflow/example.json +++ /dev/null @@ -1,217 +0,0 @@ -{ - "last_node_id": 30, - "last_link_id": 44, - "nodes": [ - { - "id": 14, - "type": "PreviewImage", - "pos": [ - 936.3425903320312, - -25.60385513305664 - ], - "size": [ - 210, - 246 - ], - "flags": { - "collapsed": false - }, - "order": 3, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 43 - } - ], - "outputs": [], - "properties": { - "Node name for S&R": "PreviewImage" - }, - "widgets_values": [] - }, - { - "id": 5, - "type": "LoadImage", - "pos": [ - 14.436566352844238, - -146.12979125976562 - ], - "size": [ - 315, - 314 - ], - "flags": {}, - "order": 0, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 42 - ], - "slot_index": 0 - }, - { - "name": "MASK", - "type": "MASK", - "links": null - } - ], - "properties": { - "Node name for S&R": "LoadImage" - }, - "widgets_values": [ - "bedroom_1.jpg", - "image" - ] - }, - { - "id": 26, - "type": "interior-design-for-comfyui", - "pos": [ - 487.18255615234375, - -8.370706558227539 - ], - "size": [ - 340.20001220703125, - 274 - ], - "flags": {}, - "order": 2, - "mode": 0, - "inputs": [ - { - "name": "image", - "type": "IMAGE", - "link": 42 - }, - { - "name": "positive", - "type": "STRING", - "link": 44, - "widget": { - "name": "positive" - } - }, - { - "name": "negative", - "type": "STRING", - "link": null, - "widget": { - "name": "negative" - }, - "shape": 7 - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 43 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "interior-design-for-comfyui" - }, - "widgets_values": [ - "", - 10, - 50, - 0.9, - 814014690245587, - "randomize", - 768, - 0.5, - 0.5, - "" - ] - }, - { - "id": 29, - "type": "StringFunction|pysssss", - "pos": [ - -133.7979736328125, - 223.61289978027344 - ], - "size": [ - 577.1492309570312, - 354.80126953125 - ], - "flags": {}, - "order": 1, - "mode": 0, - "inputs": [], - "outputs": [ - { - "name": "STRING", - "type": "STRING", - "links": [ - 44 - ] - } - ], - "properties": { - "Node name for S&R": "StringFunction|pysssss" - }, - "widgets_values": [ - "append", - "yes", - "An elegantly appointed bedroom in the Art Deco style, featuring a grand king-size bed with geometric bedding, a luxurious velvet armchair, and a mirrored nightstand that reflects the room's opulence. Art Deco-inspired artwork adds a touch of glamour", - "", - "", - "An elegantly appointed bedroom in the Art Deco style, featuring a grand king-size bed with geometric bedding, a luxurious velvet armchair, and a mirrored nightstand that reflects the room's opulence. Art Deco-inspired artwork adds a touch of glamour" - ] - } - ], - "links": [ - [ - 42, - 5, - 0, - 26, - 0, - "IMAGE" - ], - [ - 43, - 26, - 0, - 14, - 0, - "IMAGE" - ], - [ - 44, - 29, - 0, - 26, - 1, - "STRING" - ] - ], - "groups": [], - "config": {}, - "extra": { - "ds": { - "scale": 0.5706456420278478, - "offset": [ - 625.0543518197444, - 269.4681234254746 - ] - }, - "ue_links": [], - "node_versions": { - "comfy-core": "v0.3.7-10-g23827ca", - "StableDesign-for-ComfyUI": "d469e19f1196cce71737197957efd604c7d45c4f", - "comfyui-custom-scripts": "a53ef9b617ed1331640d7a2cd97644995908dc00" - } - }, - "version": 0.4 -} \ No newline at end of file diff --git a/workflow/stable-desing-for-comfyui.json b/workflow/stable-desing-for-comfyui.json new file mode 100644 index 0000000..4caf963 --- /dev/null +++ b/workflow/stable-desing-for-comfyui.json @@ -0,0 +1,3068 @@ +{ + "id": "2e2763d1-cbdd-47c4-bbc1-155355544f13", + "revision": 0, + "last_node_id": 161, + "last_link_id": 346, + "nodes": [ + { + "id": 6, + "type": "VAEDecode", + "pos": [ + 412.9100341796875, + -726.0072631835938 + ], + "size": [ + 140, + 46 + ], + "flags": {}, + "order": 42, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 20 + }, + { + "name": "vae", + "type": "VAE", + "link": 3 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 56, + 92 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "VAEDecode" + }, + "widgets_values": [] + }, + { + "id": 7, + "type": "KSampler", + "pos": [ + 90.69685363769531, + -736.1925048828125 + ], + "size": [ + 270, + 262 + ], + "flags": {}, + "order": 39, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 12 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 80 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 81 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 6 + }, + { + "name": "seed", + "type": "INT", + "widget": { + "name": "seed" + }, + "link": 204 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 20 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "KSampler" + }, + "widgets_values": [ + 42, + "fixed", + 25, + 9, + "euler", + "normal", + 0.9000000000000001 + ] + }, + { + "id": 22, + "type": "ControlNetLoader", + "pos": [ + -702.7457885742188, + 414.4010009765625 + ], + "size": [ + 270, + 58 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "CONTROL_NET", + "type": "CONTROL_NET", + "links": [ + 34 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "ControlNetLoader" + }, + "widgets_values": [ + "depth\\controlnet_depth(StableDesign).safetensors" + ] + }, + { + "id": 33, + "type": "PrimitiveStringMultiline", + "pos": [ + -1395.5089111328125, + -123.28988647460938 + ], + "size": [ + 400, + 200 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": [ + 207 + ] + } + ], + "title": "Negative Prompt (Optional)", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "PrimitiveStringMultiline" + }, + "widgets_values": [ + " " + ], + "color": "#322", + "bgcolor": "#533" + }, + { + "id": 81, + "type": "StringConcatenate", + "pos": [ + -887.3472290039062, + -397.93585205078125 + ], + "size": [ + 368.97589111328125, + 166 + ], + "flags": { + "collapsed": true + }, + "order": 21, + "mode": 0, + "inputs": [ + { + "name": "string_a", + "type": "STRING", + "widget": { + "name": "string_a" + }, + "link": 210 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": [ + 203, + 209 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "StringConcatenate" + }, + "widgets_values": [ + "", + "interior design, 4K, high resolution, photorealistic", + "," + ], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 23, + "type": "ControlNetLoader", + "pos": [ + -524.0086669921875, + 81.8063735961914 + ], + "size": [ + 270, + 58 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "CONTROL_NET", + "type": "CONTROL_NET", + "links": [ + 258 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "ControlNetLoader" + }, + "widgets_values": [ + "seg\\own_controlnet(StableDesign).safetensors" + ] + }, + { + "id": 3, + "type": "CheckpointLoaderSimple", + "pos": [ + -536.0324096679688, + -609.9761352539062 + ], + "size": [ + 270, + 98 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 12 + ] + }, + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 8, + 11 + ] + }, + { + "name": "VAE", + "type": "VAE", + "links": [ + 3 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "CheckpointLoaderSimple" + }, + "widgets_values": [ + "SSD-1B.safetensors" + ] + }, + { + "id": 25, + "type": "SetUnionControlNetType", + "pos": [ + -172.53834533691406, + 117.04817199707031 + ], + "size": [ + 270, + 58 + ], + "flags": {}, + "order": 20, + "mode": 0, + "inputs": [ + { + "name": "control_net", + "type": "CONTROL_NET", + "link": 258 + } + ], + "outputs": [ + { + "name": "CONTROL_NET", + "type": "CONTROL_NET", + "links": [ + 259 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "SetUnionControlNetType" + }, + "widgets_values": [ + "segment" + ] + }, + { + "id": 32, + "type": "PrimitiveStringMultiline", + "pos": [ + -1397.5028076171875, + -365.8805236816406 + ], + "size": [ + 400, + 200 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": [ + 210 + ] + } + ], + "title": "Positive Prompt", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "PrimitiveStringMultiline" + }, + "widgets_values": [ + "A dining room that epitomizes contemporary elegance, anchored by a sleek, minimalist dining table paired with stylish modern chairs. Artistic lighting fixtures create a focal point above, while the surrounding minimalist decor ensures the space feels open, airy, and utterly modern" + ], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 76, + "type": "VAEEncodeForInpaint", + "pos": [ + 621.3834228515625, + 41.49498748779297 + ], + "size": [ + 272.4048767089844, + 98 + ], + "flags": {}, + "order": 38, + "mode": 0, + "inputs": [ + { + "name": "pixels", + "type": "IMAGE", + "link": 277 + }, + { + "name": "vae", + "type": "VAE", + "link": 144 + }, + { + "name": "mask", + "type": "MASK", + "link": 346 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 146 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "VAEEncodeForInpaint" + }, + "widgets_values": [ + 1 + ] + }, + { + "id": 121, + "type": "MaskToImage", + "pos": [ + -328.9177551269531, + 211.1032257080078 + ], + "size": [ + 184.62362670898438, + 26 + ], + "flags": {}, + "order": 37, + "mode": 0, + "inputs": [ + { + "name": "mask", + "type": "MASK", + "link": 342 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 247 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "MaskToImage" + }, + "widgets_values": [] + }, + { + "id": 4, + "type": "CLIPTextEncode", + "pos": [ + -198.57489013671875, + -651.8577880859375 + ], + "size": [ + 210.29940795898438, + 88 + ], + "flags": { + "collapsed": true + }, + "order": 27, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 8 + }, + { + "name": "text", + "type": "STRING", + "widget": { + "name": "text" + }, + "link": 203 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 80 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "" + ], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 5, + "type": "CLIPTextEncode", + "pos": [ + -206.19314575195312, + -582.1829833984375 + ], + "size": [ + 210.29940795898438, + 88 + ], + "flags": { + "collapsed": true + }, + "order": 25, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 11 + }, + { + "name": "text", + "type": "STRING", + "widget": { + "name": "text" + }, + "link": 208 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 81 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "" + ], + "color": "#322", + "bgcolor": "#533" + }, + { + "id": 132, + "type": "MarkdownNote", + "pos": [ + -530.7215576171875, + -816.4869995117188 + ], + "size": [ + 260.4696960449219, + 162.07650756835938 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [], + "outputs": [], + "properties": {}, + "widgets_values": [ + "Generates a guide image to be used as input for the IP Adapter.\n\n- Can be generated using the `segmind/SSD-1B` model: \n [https://huggingface.co/segmind/SSD-1B](https://huggingface.co/segmind/SSD-1B/blob/main/SSD-1B.safetensors)\n- The model should be stored under `models/checkpoints` folder. \n- Alternatively, the user may provide a different model or a reference image.\n" + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 111, + "type": "ControlNetApplyAdvanced", + "pos": [ + -140.79214477539062, + -115.4814453125 + ], + "size": [ + 270, + 186 + ], + "flags": {}, + "order": 36, + "mode": 0, + "inputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "link": 218 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 217 + }, + { + "name": "control_net", + "type": "CONTROL_NET", + "link": 259 + }, + { + "name": "image", + "type": "IMAGE", + "link": 345 + }, + { + "name": "vae", + "shape": 7, + "type": "VAE", + "link": 219 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 298 + ] + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 301 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "ControlNetApplyAdvanced" + }, + "widgets_values": [ + 0.5000000000000001, + 0, + 1 + ] + }, + { + "id": 137, + "type": "MarkdownNote", + "pos": [ + 795.6456909179688, + -578.12646484375 + ], + "size": [ + 396.82476806640625, + 282.08331298828125 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [], + "outputs": [], + "properties": {}, + "widgets_values": [ + "Uses the guide image with the [ComfyUI_IPAdapter_plus](https://github.com/cubiq/ComfyUI_IPAdapter_plus) custom node.\n\n## Required Models\n\n- **IP Adapter SD15** \n Download from: \n [https://huggingface.co/h94/IP-Adapter/resolve/main/models/ip-adapter_sd15.safetensors](https://huggingface.co/h94/IP-Adapter/models) \n Save to (maybe you need to create the folder): \n `models/ipadapter`\n\n- **CLIP ViT-H Encoder** \n Download from: \n [https://huggingface.co/h94/IP-Adapter/resolve/main/models/image_encoder/model.safetensors](https://huggingface.co/h94/IP-Adapter/models/image_encoder) \n Save to: \n `models/clip_vision/` \n โš ๏ธ Must be renamed to `CLIP-ViT-H-14-laion2B-s32B-b79K.safetensors` for the node to work, since advanced model loading is no longer supported and the repo is unmaintained.\n" + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 139, + "type": "MarkdownNote", + "pos": [ + 147.14968872070312, + 24.772274017333984 + ], + "size": [ + 298.49114990234375, + 282.06671142578125 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [], + "outputs": [], + "properties": {}, + "widgets_values": [ + "This step uses a segmentation map to guide image generation via ControlNet.\n\n## ControlNet Model\n\n- Download the segmentation ControlNet model from: \n [https://huggingface.co/spaces/MykolaL/StableDesign/blob/main/own_controlnet](https://huggingface.co/spaces/MykolaL/StableDesign/blob/main/own_controlnet/diffusion_pytorch_model.safetensors) \n- Save it to: \n `models/controlnet` \n โš ๏ธ Rename the file to avoid confusion, as it comes with the generic name `diffusion_pytorch_model.safetensors`.\n" + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 13, + "type": "EmptyLatentImage", + "pos": [ + -222.43978881835938, + -480.87078857421875 + ], + "size": [ + 210, + 106 + ], + "flags": { + "collapsed": false + }, + "order": 34, + "mode": 0, + "inputs": [ + { + "name": "width", + "type": "INT", + "widget": { + "name": "width" + }, + "link": 304 + }, + { + "name": "height", + "type": "INT", + "widget": { + "name": "height" + }, + "link": 305 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 6 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "EmptyLatentImage" + }, + "widgets_values": [ + 56, + 512, + 1 + ] + }, + { + "id": 24, + "type": "SetUnionControlNetType", + "pos": [ + -407.49163818359375, + 416.0394592285156 + ], + "size": [ + 270, + 58 + ], + "flags": {}, + "order": 18, + "mode": 0, + "inputs": [ + { + "name": "control_net", + "type": "CONTROL_NET", + "link": 34 + } + ], + "outputs": [ + { + "name": "CONTROL_NET", + "type": "CONTROL_NET", + "links": [ + 169 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "SetUnionControlNetType" + }, + "widgets_values": [ + "depth" + ] + }, + { + "id": 45, + "type": "DownloadAndLoadDepthAnythingV2Model", + "pos": [ + -740.7487182617188, + 528.8541259765625 + ], + "size": [ + 365.3121032714844, + 82 + ], + "flags": {}, + "order": 8, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "da_v2_model", + "type": "DAMODEL", + "links": [ + 82 + ] + } + ], + "properties": { + "cnr_id": "comfyui-depthanythingv2", + "ver": "d505cbca99803fc63327b8305618a23e59a18b42", + "Node name for S&R": "DownloadAndLoadDepthAnythingV2Model", + "aux_id": "kijai/ComfyUI-DepthAnythingV2" + }, + "widgets_values": [ + "depth_anything_v2_vitl_fp32.safetensors", + "auto" + ] + }, + { + "id": 46, + "type": "DepthAnything_V2", + "pos": [ + -717.4320678710938, + 672.8815307617188 + ], + "size": [ + 312.734130859375, + 77.45999908447266 + ], + "flags": {}, + "order": 29, + "mode": 0, + "inputs": [ + { + "name": "da_model", + "type": "DAMODEL", + "link": 82 + }, + { + "name": "images", + "type": "IMAGE", + "link": 276 + } + ], + "outputs": [ + { + "name": "image", + "type": "IMAGE", + "links": [ + 98, + 171 + ] + } + ], + "properties": { + "cnr_id": "comfyui-depthanythingv2", + "ver": "d505cbca99803fc63327b8305618a23e59a18b42", + "Node name for S&R": "DepthAnything_V2" + }, + "widgets_values": [] + }, + { + "id": 79, + "type": "ControlNetApplyAdvanced", + "pos": [ + -343.232421875, + 528.325439453125 + ], + "size": [ + 270, + 186 + ], + "flags": {}, + "order": 33, + "mode": 0, + "inputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "link": 215 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 216 + }, + { + "name": "control_net", + "type": "CONTROL_NET", + "link": 169 + }, + { + "name": "image", + "type": "IMAGE", + "link": 171 + }, + { + "name": "vae", + "shape": 7, + "type": "VAE", + "link": 170 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 297 + ] + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 300 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "ControlNetApplyAdvanced" + }, + "widgets_values": [ + 0.5000000000000001, + 0, + 1 + ] + }, + { + "id": 138, + "type": "MarkdownNote", + "pos": [ + 118.04875946044922, + 421.34381103515625 + ], + "size": [ + 344.6339111328125, + 304.2916259765625 + ], + "flags": {}, + "order": 9, + "mode": 0, + "inputs": [], + "outputs": [], + "properties": {}, + "widgets_values": [ + "This step uses depth information to guide image generation via ControlNet.\n\n## Depth Estimation\n\n- Uses the custom node [Depth Anything V2](https://github.com/DepthAnything/Depth-Anything-V2)\n- This replaces the older Depth Anything model, offering improved results with no major changes required to the pipeline.\n\n## ControlNet Model\n\n- Download the original custom depth ControlNet model from: \n [https://huggingface.co/spaces/MykolaL/StableDesign/blob/main/controlnet_depth](https://huggingface.co/spaces/MykolaL/StableDesign/blob/main/controlnet_depth/diffusion_pytorch_model.safetensors) \n- Save it to: \n `models/controlnet` \n โš ๏ธ It is recommended to rename the file, as it uses the default name from the repository (`diffusion_pytorch_model.safetensors`).\n" + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 63, + "type": "IPAdapterUnifiedLoader", + "pos": [ + 610.3306884765625, + -812.8778076171875 + ], + "size": [ + 270, + 78 + ], + "flags": {}, + "order": 24, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 111 + }, + { + "name": "ipadapter", + "shape": 7, + "type": "IPADAPTER", + "link": 115 + } + ], + "outputs": [ + { + "name": "model", + "type": "MODEL", + "links": [ + 112 + ] + }, + { + "name": "ipadapter", + "type": "IPADAPTER", + "links": [ + 114 + ] + } + ], + "properties": { + "cnr_id": "comfyui_ipadapter_plus", + "ver": "a0f451a5113cf9becb0847b92884cb10cbdec0ef", + "Node name for S&R": "IPAdapterUnifiedLoader" + }, + "widgets_values": [ + "STANDARD (medium strength)" + ] + }, + { + "id": 64, + "type": "IPAdapterModelLoader", + "pos": [ + 618.4702758789062, + -688.3241577148438 + ], + "size": [ + 270, + 58 + ], + "flags": {}, + "order": 10, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IPADAPTER", + "type": "IPADAPTER", + "links": [ + 115 + ] + } + ], + "properties": { + "cnr_id": "comfyui_ipadapter_plus", + "ver": "a0f451a5113cf9becb0847b92884cb10cbdec0ef", + "Node name for S&R": "IPAdapterModelLoader" + }, + "widgets_values": [ + "ip-adapter_sd15.safetensors" + ] + }, + { + "id": 122, + "type": "PreviewImage", + "pos": [ + 156.95230102539062, + -262.51239013671875 + ], + "size": [ + 140, + 246.00001525878906 + ], + "flags": {}, + "order": 41, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 247 + } + ], + "outputs": [], + "title": "Mask", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + }, + { + "id": 120, + "type": "PreviewImage", + "pos": [ + 313.9969177246094, + -260.78179931640625 + ], + "size": [ + 140, + 246 + ], + "flags": {}, + "order": 35, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 344 + } + ], + "outputs": [], + "title": "Segmentation", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + }, + { + "id": 34, + "type": "PreviewImage", + "pos": [ + 429.91259765625, + -612.2884521484375 + ], + "size": [ + 140, + 246 + ], + "flags": {}, + "order": 43, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 56 + } + ], + "outputs": [], + "title": "Style Guidance", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + }, + { + "id": 59, + "type": "PreviewImage", + "pos": [ + -52.13082504272461, + 422.2935791015625 + ], + "size": [ + 140, + 246.00003051757812 + ], + "flags": {}, + "order": 32, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 98 + } + ], + "outputs": [], + "title": "Depth", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + }, + { + "id": 142, + "type": "CM_NearestSDXLResolution", + "pos": [ + -471.7952575683594, + -430.25872802734375 + ], + "size": [ + 191.64413452148438, + 46 + ], + "flags": {}, + "order": 30, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 306 + } + ], + "outputs": [ + { + "name": "width", + "type": "INT", + "links": [ + 304 + ] + }, + { + "name": "height", + "type": "INT", + "links": [ + 305 + ] + } + ], + "properties": { + "cnr_id": "ComfyMath", + "ver": "c01177221c31b8e5fbc062778fc8254aeb541638", + "Node name for S&R": "CM_NearestSDXLResolution" + }, + "widgets_values": [] + }, + { + "id": 9, + "type": "LoadImage", + "pos": [ + -945.4544677734375, + -361.9350891113281 + ], + "size": [ + 270, + 314 + ], + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 273, + 311 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": [] + } + ], + "title": "Load Input Image", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "dinning_room_3.jpg", + "image" + ], + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 130, + "type": "Image Normalize", + "pos": [ + -1169.78759765625, + -506.8669128417969 + ], + "size": [ + 227.74464416503906, + 106 + ], + "flags": {}, + "order": 22, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 273 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 276, + 277, + 306, + 340 + ] + } + ], + "properties": { + "cnr_id": "interior-design-for-comfyui", + "ver": "9443c413e17048827197402d64823bf279780479", + "Node name for S&R": "Image Normalize" + }, + "widgets_values": [ + 512, + 8, + "bilinear" + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 38, + "type": "CheckpointLoaderSimple", + "pos": [ + 608.1879272460938, + -139.8812255859375 + ], + "size": [ + 319.5867919921875, + 108.5184097290039 + ], + "flags": {}, + "order": 12, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 111 + ] + }, + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 61, + 62 + ] + }, + { + "name": "VAE", + "type": "VAE", + "links": [ + 79, + 144, + 170, + 219, + 329, + 336 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "CheckpointLoaderSimple" + }, + "widgets_values": [ + "Realistic_Vision_V5.1-inpainting.safetensors" + ] + }, + { + "id": 107, + "type": "PrimitiveInt", + "pos": [ + -1404.6439208984375, + -502.1680603027344 + ], + "size": [ + 210, + 82 + ], + "flags": { + "collapsed": false + }, + "order": 13, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "INT", + "type": "INT", + "links": [ + 204, + 205, + 337 + ] + } + ], + "title": "Seed", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "PrimitiveInt" + }, + "widgets_values": [ + 143668900, + "fixed" + ] + }, + { + "id": 35, + "type": "CLIPTextEncode", + "pos": [ + 982.7101440429688, + -133.51083374023438 + ], + "size": [ + 210.29940795898438, + 88 + ], + "flags": { + "collapsed": true + }, + "order": 26, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 61 + }, + { + "name": "text", + "type": "STRING", + "widget": { + "name": "text" + }, + "link": 214 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 216, + 217, + 332 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "" + ], + "color": "#322", + "bgcolor": "#533" + }, + { + "id": 36, + "type": "CLIPTextEncode", + "pos": [ + 979.80615234375, + -68.59585571289062 + ], + "size": [ + 210.29940795898438, + 88 + ], + "flags": { + "collapsed": true + }, + "order": 28, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 62 + }, + { + "name": "text", + "type": "STRING", + "widget": { + "name": "text" + }, + "link": 209 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 215, + 218, + 331 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "" + ], + "color": "#232", + "bgcolor": "#353" + }, + { + "id": 126, + "type": "PairConditioningCombine", + "pos": [ + 667.4053344726562, + 209.75762939453125 + ], + "size": [ + 162.07186889648438, + 86 + ], + "flags": {}, + "order": 40, + "mode": 0, + "inputs": [ + { + "name": "positive_A", + "type": "CONDITIONING", + "link": 297 + }, + { + "name": "negative_A", + "type": "CONDITIONING", + "link": 300 + }, + { + "name": "positive_B", + "type": "CONDITIONING", + "link": 298 + }, + { + "name": "negative_B", + "type": "CONDITIONING", + "link": 301 + } + ], + "outputs": [ + { + "name": "positive", + "type": "CONDITIONING", + "links": [ + 302 + ] + }, + { + "name": "negative", + "type": "CONDITIONING", + "links": [ + 303 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "PairConditioningCombine" + }, + "widgets_values": [] + }, + { + "id": 82, + "type": "StringConcatenate", + "pos": [ + -871.6675415039062, + 3.361741065979004 + ], + "size": [ + 210, + 150 + ], + "flags": { + "collapsed": true + }, + "order": 19, + "mode": 0, + "inputs": [ + { + "name": "string_b", + "type": "STRING", + "widget": { + "name": "string_b" + }, + "link": 207 + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": [ + 208, + 214 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "StringConcatenate" + }, + "widgets_values": [ + "window, door, low resolution, banner, logo, watermark, text, deformed, blurry, out of focus, surreal, ugly, beginner", + "", + "," + ], + "color": "#322", + "bgcolor": "#533" + }, + { + "id": 42, + "type": "VAEDecode", + "pos": [ + 1220.304931640625, + -161.55670166015625 + ], + "size": [ + 140, + 46 + ], + "flags": {}, + "order": 46, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 77 + }, + { + "name": "vae", + "type": "VAE", + "link": 79 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 308, + 309 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "VAEDecode" + }, + "widgets_values": [] + }, + { + "id": 41, + "type": "KSampler", + "pos": [ + 862.2103881835938, + 192.63446044921875 + ], + "size": [ + 270, + 262 + ], + "flags": {}, + "order": 45, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 93 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 302 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 303 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 146 + }, + { + "name": "seed", + "type": "INT", + "widget": { + "name": "seed" + }, + "link": 205 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 77 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "KSampler" + }, + "widgets_values": [ + 42, + "fixed", + 50, + 10, + "euler", + "normal", + 0.9000000000000001 + ] + }, + { + "id": 145, + "type": "PreviewImage", + "pos": [ + 1400.232421875, + -162.7487030029297 + ], + "size": [ + 140, + 246 + ], + "flags": {}, + "order": 48, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 309 + } + ], + "outputs": [], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "PreviewImage" + }, + "widgets_values": [] + }, + { + "id": 141, + "type": "MarkdownNote", + "pos": [ + 1168.7044677734375, + 137.92733764648438 + ], + "size": [ + 467.87884521484375, + 416.0183410644531 + ], + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [], + "outputs": [], + "properties": {}, + "widgets_values": [ + "\nThis step generates the final image using **Stable Diffusion 1.5 with inpainting**, guided by both depth and segmentation ControlNets.\n\n## Base Model\n\n- **Model:** [Realistic Vision V5.1 (Inpainting)](https://huggingface.co/SG161222/Realistic_Vision_V5.1_noVAE/blob/main/Realistic_Vision_V5.1-inpainting.safetensors) \n- Save to: \n `models/checkpoints`\n\n> โš ๏ธ A newer version exists, but no major improvements were observed.\n\n## ControlNet Combination\n\n- ControlNets are combined in this order:\n 1. Depth\n 2. Segmentation\n\n> ๐Ÿ” Changing the order had any impact on results. Other approaches might help better match the original pipeline.\n\n\nThe original pipeline explicitly replaced the scheduler with `UniPCMultistepScheduler`:\n\n```python\nfrom diffusers import UniPCMultistepScheduler\n\nself.pipe.scheduler = UniPCMultistepScheduler.from_config(self.pip" + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 146, + "type": "ImageScale", + "pos": [ + 1876.01171875, + -161.27243041992188 + ], + "size": [ + 270, + 130 + ], + "flags": {}, + "order": 49, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 310 + }, + { + "name": "width", + "type": "INT", + "widget": { + "name": "width" + }, + "link": 312 + }, + { + "name": "height", + "type": "INT", + "widget": { + "name": "height" + }, + "link": 313 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 328 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "ImageScale" + }, + "widgets_values": [ + "bilinear", + 512, + 512, + "disabled" + ] + }, + { + "id": 143, + "type": "UpscaleModelLoader", + "pos": [ + 2166.35302734375, + -153.9991912841797 + ], + "size": [ + 270, + 58 + ], + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "UPSCALE_MODEL", + "type": "UPSCALE_MODEL", + "links": [ + 307 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "UpscaleModelLoader" + }, + "widgets_values": [ + "4x-ESRGAN.pth" + ] + }, + { + "id": 144, + "type": "ImageUpscaleWithModel", + "pos": [ + 2163.442626953125, + -42.37593460083008 + ], + "size": [ + 221.98202514648438, + 46 + ], + "flags": {}, + "order": 47, + "mode": 0, + "inputs": [ + { + "name": "upscale_model", + "type": "UPSCALE_MODEL", + "link": 307 + }, + { + "name": "image", + "type": "IMAGE", + "link": 308 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 310 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "ImageUpscaleWithModel" + }, + "widgets_values": [] + }, + { + "id": 157, + "type": "VAEDecode", + "pos": [ + 1983.02294921875, + 17.500192642211914 + ], + "size": [ + 140, + 46 + ], + "flags": {}, + "order": 52, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 334 + }, + { + "name": "vae", + "type": "VAE", + "link": 336 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 338 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "VAEDecode" + }, + "widgets_values": [] + }, + { + "id": 159, + "type": "SaveImage", + "pos": [ + 2150.8388671875, + 55.758201599121094 + ], + "size": [ + 270, + 270 + ], + "flags": {}, + "order": 53, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 338 + } + ], + "outputs": [], + "title": "Output", + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41" + }, + "widgets_values": [ + "ComfyUI" + ], + "color": "#222", + "bgcolor": "#000" + }, + { + "id": 155, + "type": "KSampler", + "pos": [ + 1840.90625, + 117.30351257324219 + ], + "size": [ + 270, + 262 + ], + "flags": {}, + "order": 51, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 339 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 331 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 332 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 333 + }, + { + "name": "seed", + "type": "INT", + "widget": { + "name": "seed" + }, + "link": 337 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 334 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "KSampler" + }, + "widgets_values": [ + 42, + "fixed", + 100, + 10, + "uni_pc_bh2", + "normal", + 0.5000000000000001 + ] + }, + { + "id": 156, + "type": "VAEEncode", + "pos": [ + 1827.583984375, + 18.867908477783203 + ], + "size": [ + 140, + 46 + ], + "flags": {}, + "order": 50, + "mode": 0, + "inputs": [ + { + "name": "pixels", + "type": "IMAGE", + "link": 328 + }, + { + "name": "vae", + "type": "VAE", + "link": 329 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 333 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "VAEEncode" + }, + "widgets_values": [] + }, + { + "id": 147, + "type": "GetImageSize", + "pos": [ + 1727.86376953125, + -149.89578247070312 + ], + "size": [ + 140, + 124 + ], + "flags": {}, + "order": 23, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 311 + } + ], + "outputs": [ + { + "name": "width", + "type": "INT", + "links": [ + 312 + ] + }, + { + "name": "height", + "type": "INT", + "links": [ + 313 + ] + }, + { + "name": "batch_size", + "type": "INT", + "links": null + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.41", + "Node name for S&R": "GetImageSize" + }, + "widgets_values": [] + }, + { + "id": 160, + "type": "MarkdownNote", + "pos": [ + 2463.355712890625, + -168.02671813964844 + ], + "size": [ + 422.3630676269531, + 312.2231750488281 + ], + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [], + "outputs": [], + "properties": {}, + "widgets_values": [ + "This step performs a final refinement pass using the diffusion model, aimed at improving image coherence while preserving original details.\n\n## Process Overview\n\n1. **Upscaling:** \n - The image from Step is upscaled using **ESRGAN x4**.\n\n2. **Downscaling:** \n - The upscaled image is resized back to its original resolution.\n\n3. **Latent Noise Injection:** \n - The latent representation of the resized image is injected with **50% noise** before reprocessing.\n\n4. **Diffusion Pass with IP Adapter Only:** \n - The image is passed again through the **IP Adapter**, using both **positive and negative CLIP embeddings**, but **without ControlNet**, to avoid overwriting fine details.\n - The same **inpainting model** is reused (`Realistic_Vision_V5.1-inpainting.safetensors`), but with **double the number of steps** for improved refinement.\n" + ], + "color": "#432", + "bgcolor": "#653" + }, + { + "id": 57, + "type": "IPAdapter", + "pos": [ + 922.7847290039062, + -812.4465942382812 + ], + "size": [ + 270, + 190 + ], + "flags": {}, + "order": 44, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 112 + }, + { + "name": "ipadapter", + "type": "IPADAPTER", + "link": 114 + }, + { + "name": "image", + "type": "IMAGE", + "link": 92 + }, + { + "name": "attn_mask", + "shape": 7, + "type": "MASK", + "link": 343 + } + ], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 93, + 339 + ] + } + ], + "properties": { + "cnr_id": "comfyui_ipadapter_plus", + "ver": "a0f451a5113cf9becb0847b92884cb10cbdec0ef", + "Node name for S&R": "IPAdapter" + }, + "widgets_values": [ + 1.0000000000000002, + 0, + 1, + "standard" + ] + }, + { + "id": 131, + "type": "Control Items", + "pos": [ + -503.3625183105469, + -102.65502166748047 + ], + "size": [ + 270, + 106 + ], + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "CONTROL_ITEMS", + "type": "CONTROL_ITEMS", + "links": [ + 341 + ] + } + ], + "properties": { + "cnr_id": "interior-design-for-comfyui", + "ver": "9443c413e17048827197402d64823bf279780479", + "Node name for S&R": "Control Items" + }, + "widgets_values": [ + true, + true, + false + ], + "color": "#233", + "bgcolor": "#355" + }, + { + "id": 161, + "type": "Interior Design Segmentator", + "pos": [ + -461.2010498046875, + -224.7035675048828 + ], + "size": [ + 214.98886108398438, + 46 + ], + "flags": {}, + "order": 31, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 340 + }, + { + "name": "control_items", + "type": "CONTROL_ITEMS", + "link": 341 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 344, + 345 + ] + }, + { + "name": "MASK", + "type": "MASK", + "links": [ + 342, + 343, + 346 + ] + } + ], + "properties": { + "cnr_id": "interior-design-for-comfyui", + "ver": "9443c413e17048827197402d64823bf279780479", + "Node name for S&R": "Interior Design Segmentator" + }, + "color": "#233", + "bgcolor": "#355" + } + ], + "links": [ + [ + 3, + 3, + 2, + 6, + 1, + "VAE" + ], + [ + 6, + 13, + 0, + 7, + 3, + "LATENT" + ], + [ + 8, + 3, + 1, + 4, + 0, + "CLIP" + ], + [ + 11, + 3, + 1, + 5, + 0, + "CLIP" + ], + [ + 12, + 3, + 0, + 7, + 0, + "MODEL" + ], + [ + 20, + 7, + 0, + 6, + 0, + "LATENT" + ], + [ + 34, + 22, + 0, + 24, + 0, + "CONTROL_NET" + ], + [ + 56, + 6, + 0, + 34, + 0, + "IMAGE" + ], + [ + 61, + 38, + 1, + 35, + 0, + "CLIP" + ], + [ + 62, + 38, + 1, + 36, + 0, + "CLIP" + ], + [ + 77, + 41, + 0, + 42, + 0, + "LATENT" + ], + [ + 79, + 38, + 2, + 42, + 1, + "VAE" + ], + [ + 80, + 4, + 0, + 7, + 1, + "CONDITIONING" + ], + [ + 81, + 5, + 0, + 7, + 2, + "CONDITIONING" + ], + [ + 82, + 45, + 0, + 46, + 0, + "DAMODEL" + ], + [ + 92, + 6, + 0, + 57, + 2, + "IMAGE" + ], + [ + 93, + 57, + 0, + 41, + 0, + "MODEL" + ], + [ + 98, + 46, + 0, + 59, + 0, + "IMAGE" + ], + [ + 111, + 38, + 0, + 63, + 0, + "MODEL" + ], + [ + 112, + 63, + 0, + 57, + 0, + "MODEL" + ], + [ + 114, + 63, + 1, + 57, + 1, + "IPADAPTER" + ], + [ + 115, + 64, + 0, + 63, + 1, + "IPADAPTER" + ], + [ + 144, + 38, + 2, + 76, + 1, + "VAE" + ], + [ + 146, + 76, + 0, + 41, + 3, + "LATENT" + ], + [ + 169, + 24, + 0, + 79, + 2, + "CONTROL_NET" + ], + [ + 170, + 38, + 2, + 79, + 4, + "VAE" + ], + [ + 171, + 46, + 0, + 79, + 3, + "IMAGE" + ], + [ + 203, + 81, + 0, + 4, + 1, + "STRING" + ], + [ + 204, + 107, + 0, + 7, + 4, + "INT" + ], + [ + 205, + 107, + 0, + 41, + 4, + "INT" + ], + [ + 207, + 33, + 0, + 82, + 0, + "STRING" + ], + [ + 208, + 82, + 0, + 5, + 1, + "STRING" + ], + [ + 209, + 81, + 0, + 36, + 1, + "STRING" + ], + [ + 210, + 32, + 0, + 81, + 0, + "STRING" + ], + [ + 214, + 82, + 0, + 35, + 1, + "STRING" + ], + [ + 215, + 36, + 0, + 79, + 0, + "CONDITIONING" + ], + [ + 216, + 35, + 0, + 79, + 1, + "CONDITIONING" + ], + [ + 217, + 35, + 0, + 111, + 1, + "CONDITIONING" + ], + [ + 218, + 36, + 0, + 111, + 0, + "CONDITIONING" + ], + [ + 219, + 38, + 2, + 111, + 4, + "VAE" + ], + [ + 247, + 121, + 0, + 122, + 0, + "IMAGE" + ], + [ + 258, + 23, + 0, + 25, + 0, + "CONTROL_NET" + ], + [ + 259, + 25, + 0, + 111, + 2, + "CONTROL_NET" + ], + [ + 273, + 9, + 0, + 130, + 0, + "IMAGE" + ], + [ + 276, + 130, + 0, + 46, + 1, + "IMAGE" + ], + [ + 277, + 130, + 0, + 76, + 0, + "IMAGE" + ], + [ + 297, + 79, + 0, + 126, + 0, + "CONDITIONING" + ], + [ + 298, + 111, + 0, + 126, + 2, + "CONDITIONING" + ], + [ + 300, + 79, + 1, + 126, + 1, + "CONDITIONING" + ], + [ + 301, + 111, + 1, + 126, + 3, + "CONDITIONING" + ], + [ + 302, + 126, + 0, + 41, + 1, + "CONDITIONING" + ], + [ + 303, + 126, + 1, + 41, + 2, + "CONDITIONING" + ], + [ + 304, + 142, + 0, + 13, + 0, + "INT" + ], + [ + 305, + 142, + 1, + 13, + 1, + "INT" + ], + [ + 306, + 130, + 0, + 142, + 0, + "IMAGE" + ], + [ + 307, + 143, + 0, + 144, + 0, + "UPSCALE_MODEL" + ], + [ + 308, + 42, + 0, + 144, + 1, + "IMAGE" + ], + [ + 309, + 42, + 0, + 145, + 0, + "IMAGE" + ], + [ + 310, + 144, + 0, + 146, + 0, + "IMAGE" + ], + [ + 311, + 9, + 0, + 147, + 0, + "IMAGE" + ], + [ + 312, + 147, + 0, + 146, + 1, + "INT" + ], + [ + 313, + 147, + 1, + 146, + 2, + "INT" + ], + [ + 328, + 146, + 0, + 156, + 0, + "IMAGE" + ], + [ + 329, + 38, + 2, + 156, + 1, + "VAE" + ], + [ + 331, + 36, + 0, + 155, + 1, + "CONDITIONING" + ], + [ + 332, + 35, + 0, + 155, + 2, + "CONDITIONING" + ], + [ + 333, + 156, + 0, + 155, + 3, + "LATENT" + ], + [ + 334, + 155, + 0, + 157, + 0, + "LATENT" + ], + [ + 336, + 38, + 2, + 157, + 1, + "VAE" + ], + [ + 337, + 107, + 0, + 155, + 4, + "INT" + ], + [ + 338, + 157, + 0, + 159, + 0, + "IMAGE" + ], + [ + 339, + 57, + 0, + 155, + 0, + "MODEL" + ], + [ + 340, + 130, + 0, + 161, + 0, + "IMAGE" + ], + [ + 341, + 131, + 0, + 161, + 1, + "CONTROL_ITEMS" + ], + [ + 342, + 161, + 1, + 121, + 0, + "MASK" + ], + [ + 343, + 161, + 1, + 57, + 3, + "MASK" + ], + [ + 344, + 161, + 0, + 120, + 0, + "IMAGE" + ], + [ + 345, + 161, + 0, + 111, + 3, + "IMAGE" + ], + [ + 346, + 161, + 1, + 76, + 2, + "MASK" + ] + ], + "groups": [ + { + "id": 1, + "title": "IP Adapter Image Guidance", + "bounding": [ + -546.0324096679688, + -890.0869750976562, + 1125.945068359375, + 533.7985229492188 + ], + "color": "#3f789e", + "font_size": 24, + "flags": {} + }, + { + "id": 2, + "title": "Input", + "bounding": [ + -1414.6439208984375, + -579.0248413085938, + 749.1898193359375, + 665.7351684570312 + ], + "color": "#a1309b", + "font_size": 24, + "flags": {} + }, + { + "id": 3, + "title": "Depth Controlnet", + "bounding": [ + -750.7487182617188, + 340.8009948730469, + 1223.431396484375, + 419.5405578613281 + ], + "color": "#3f789e", + "font_size": 24, + "flags": {} + }, + { + "id": 4, + "title": "Diffusion Step", + "bounding": [ + 598.1879272460938, + -236.3487091064453, + 1048.395263671875, + 800.2943725585938 + ], + "color": "#3f789e", + "font_size": 24, + "flags": {} + }, + { + "id": 5, + "title": "IP Adapter", + "bounding": [ + 600.3306884765625, + -886.477783203125, + 602.1399536132812, + 600.4346313476562 + ], + "color": "#3f789e", + "font_size": 24, + "flags": {} + }, + { + "id": 6, + "title": "Segment Controlnet", + "bounding": [ + -534.0086669921875, + -336.11248779296875, + 998.0056762695312, + 652.951416015625 + ], + "color": "#3f789e", + "font_size": 24, + "flags": {} + }, + { + "id": 7, + "title": "Output", + "bounding": [ + 1717.86376953125, + -241.62672424316406, + 1177.85498046875, + 630.9302368164062 + ], + "color": "#a1309b", + "font_size": 24, + "flags": {} + } + ], + "config": {}, + "extra": { + "ds": { + "scale": 0.6934334949442131, + "offset": [ + 1331.5040977754481, + 706.8026326130054 + ] + }, + "groupNodes": {}, + "frontendVersion": "1.21.7" + }, + "version": 0.4 +} \ No newline at end of file