2962 lines
126 KiB
Python
2962 lines
126 KiB
Python
from PIL import ImageDraw, ImageOps, ImageFilter
|
|
import json
|
|
from PIL.PngImagePlugin import PngInfo
|
|
import numpy as np
|
|
import folder_paths
|
|
from .LCM.lcm_pipeline_inpaint import LatentConsistencyModelPipeline_inpaint, LCMScheduler_X
|
|
from .LCM.lcm_pipeline_2 import LatentConsistencyModelPipeline_ipadapter
|
|
from .LCM.LCM_img2img_pipeline import LatentConsistencyModelPipeline_img2img
|
|
from .LCM.LCM_reference_pipeline import LatentConsistencyModelPipeline_reference
|
|
from .LCM.LCM_refinpaint_pipeline import LatentConsistencyModelPipeline_refinpaint
|
|
from .LCM.pipeline_cn_inpaint import LatentConsistencyModelPipeline_inpaintV2
|
|
from .LCM.pipeline_cn_inpaint_ipadapter import LatentConsistencyModelPipeline_inpaintV3
|
|
from .LCM.pipeline_inpaint_cn_reference import LatentConsistencyModelPipeline_refinpaintcn
|
|
from .LCM.pipeline_cn_reference_img2img import LatentConsistencyModelPipeline_reference_img2img
|
|
from .LCM.stable_diffusion_reference_img2img import StableDiffusionImg2ImgPipeline_reference
|
|
from .LCM.LCM_lora_inpaint import LCM_inpaint_final
|
|
from .LCM.LCM_lora_inpaint_ipadapter import LCM_lora_inpaint_ipadapter
|
|
from .LCM.pipeline_cn import LatentConsistencyModelPipeline_controlnet
|
|
from .LCM.stable_diffusion_reference_img2img import StableDiffusionImg2ImgPipeline_reference
|
|
from .LCM.stable_diffusion_reference_img2img_controlnet import StableDiffusionControlNetImg2ImgPipeline_ref
|
|
from .LCM.stable_diffusion_ipadapter_img2img_controlnet import StableDiffusionControlNetImg2ImgPipeline_ipadapter
|
|
from diffusers import StableDiffusionControlNetImg2ImgPipeline,StableDiffusionXLPipeline, AutoPipelineForImage2Image,AutoencoderKL, UNet2DConditionModel, T2IAdapter, ControlNetModel, StableDiffusionPipeline, AutoencoderTiny, DiffusionPipeline, LCMScheduler, AutoPipelineForInpainting, StableDiffusionControlNetPipeline, StableDiffusionControlNetInpaintPipeline
|
|
from diffusers.pipelines.stable_diffusion import StableDiffusionImg2ImgPipeline
|
|
from diffusers.utils import get_class_from_dynamic_module
|
|
from transformers import CLIPTokenizer, CLIPTextModel, CLIPImageProcessor
|
|
import os
|
|
from pathlib import Path
|
|
import torch
|
|
from PIL import Image
|
|
import tomesd
|
|
import random
|
|
from compel import Compel
|
|
import tomesd
|
|
from .IPA.ip_adapter import IPAdapter, IPAdapterPlus
|
|
from icecream import ic
|
|
import utils
|
|
import types
|
|
from comfy.cli_args import args
|
|
|
|
|
|
|
|
|
|
#os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:192"
|
|
def set_max_split_size_mb(model, max_split_size_mb):
|
|
"""
|
|
Set the max_split_size_mb parameter in PyTorch to avoid fragmentation.
|
|
|
|
Args:
|
|
model (torch.nn.Module): The PyTorch model.
|
|
max_split_size_mb (int): The desired value for max_split_size_mb in megabytes.
|
|
"""
|
|
for param in model.parameters():
|
|
param.requires_grad = False # Disable gradient calculation to prevent unnecessary memory allocations
|
|
|
|
# Dummy forward pass to initialize the memory allocator
|
|
dummy_input = torch.randn(1, 1)
|
|
model(dummy_input)
|
|
|
|
# Get the current memory allocator state
|
|
allocator = torch.cuda.memory._get_memory_allocator()
|
|
|
|
# Update max_split_size_mb in the memory allocator
|
|
allocator.set_max_split_size(max_split_size_mb * 1024 * 1024)
|
|
|
|
|
|
|
|
class LCMLoader_controlnet_inpaint:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"device": (["GPU", "CPU"],),
|
|
"model_path": ("STRING", {"default": '', "multiline": False}),
|
|
"tomesd_value": ("FLOAT", {
|
|
"default": 0.6,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"mode":([i for i in os.listdir(folder_paths.get_folder_paths("controlnet")[0]) if os.path.isdir(folder_paths.get_folder_paths("controlnet")[0]+f"/{i}") or os.path.isdir(folder_paths.get_folder_paths("controlnet")[0]+f"\{i}")],)
|
|
}
|
|
}
|
|
RETURN_TYPES = ("class",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self,device,tomesd_value,model_path,mode):
|
|
|
|
save_path = "./lcm_images"
|
|
if model_path != "":
|
|
model_id = model_path
|
|
else:
|
|
try:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+"/LCM_Dreamshaper_v7"
|
|
except:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+"\LCM_Dreamshaper_v7"
|
|
|
|
|
|
# Initalize Diffusers Model:
|
|
vae = AutoencoderKL.from_pretrained(model_id, subfolder="vae")
|
|
text_encoder = CLIPTextModel.from_pretrained(model_id, subfolder="text_encoder")
|
|
tokenizer = CLIPTokenizer.from_pretrained(model_id, subfolder="tokenizer")
|
|
unet = UNet2DConditionModel.from_pretrained(model_id, subfolder="unet", device_map=None, low_cpu_mem_usage=False, local_files_only=True)
|
|
#safety_checker = StableDiffusionSafetyChecker.from_pretrained(model_id, subfolder="safety_checker")
|
|
feature_extractor = CLIPImageProcessor.from_pretrained(model_id, subfolder="feature_extractor")
|
|
|
|
|
|
# Initalize Scheduler:
|
|
scheduler = LCMScheduler_X(beta_start=0.00085, beta_end=0.0120, beta_schedule="scaled_linear", prediction_type="epsilon")
|
|
try:
|
|
mpath = folder_paths.get_folder_paths("controlnet")[0]+f"/{mode}"
|
|
except:
|
|
mpath = folder_paths.get_folder_paths("controlnet")[0]+f"\{mode}"
|
|
controlnet = ControlNetModel.from_pretrained(mpath)
|
|
|
|
# LCM Pipeline:
|
|
pipe = LatentConsistencyModelPipeline_refinpaintcn(vae=vae, text_encoder=text_encoder, tokenizer=tokenizer, unet=unet, scheduler=scheduler, safety_checker=None, feature_extractor=feature_extractor,controlnet=controlnet)
|
|
tomesd.apply_patch(pipe, ratio=tomesd_value)
|
|
if device == "GPU":
|
|
pipe.enable_xformers_memory_efficient_attention()
|
|
pipe.enable_sequential_cpu_offload()
|
|
else:
|
|
pipe.to("cpu")
|
|
return (pipe,)
|
|
|
|
class LCMLoader_controlnet:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"device": (["GPU", "CPU"],),
|
|
"model_path": ("STRING", {"default": '', "multiline": False}),
|
|
"tomesd_value": ("FLOAT", {
|
|
"default": 0.6,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"mode":([i for i in os.listdir(folder_paths.get_folder_paths("controlnet")[0]) if os.path.isdir(folder_paths.get_folder_paths("controlnet")[0]+f"/{i}") or os.path.isdir(folder_paths.get_folder_paths("controlnet")[0]+f"\{i}")],)
|
|
}
|
|
}
|
|
RETURN_TYPES = ("class",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self,device,tomesd_value,model_path,mode):
|
|
torch.backends.cuda.matmul.allow_tf32 = True
|
|
|
|
save_path = "./lcm_images"
|
|
if model_path != "":
|
|
model_id = model_path
|
|
else:
|
|
try:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+"/LCM_Dreamshaper_v7"
|
|
except:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+"\LCM_Dreamshaper_v7"
|
|
|
|
|
|
# Initalize Diffusers Model:
|
|
vae = AutoencoderKL.from_pretrained(model_id, subfolder="vae")
|
|
text_encoder = CLIPTextModel.from_pretrained(model_id, subfolder="text_encoder")
|
|
tokenizer = CLIPTokenizer.from_pretrained(model_id, subfolder="tokenizer")
|
|
unet = UNet2DConditionModel.from_pretrained(model_id, subfolder="unet", device_map=None, low_cpu_mem_usage=False, local_files_only=True)
|
|
#safety_checker = StableDiffusionSafetyChecker.from_pretrained(model_id, subfolder="safety_checker")
|
|
feature_extractor = CLIPImageProcessor.from_pretrained(model_id, subfolder="feature_extractor")
|
|
|
|
|
|
# Initalize Scheduler:
|
|
scheduler = LCMScheduler_X(beta_start=0.00085, beta_end=0.0120, beta_schedule="scaled_linear", prediction_type="epsilon")
|
|
try:
|
|
mpath = folder_paths.get_folder_paths("controlnet")[0]+f"/{mode}"
|
|
except:
|
|
mpath = folder_paths.get_folder_paths("controlnet")[0]+f"\{mode}"
|
|
controlnet = ControlNetModel.from_pretrained(mpath)
|
|
|
|
# LCM Pipeline:
|
|
pipe = LatentConsistencyModelPipeline_controlnet(vae=vae, text_encoder=text_encoder, tokenizer=tokenizer, unet=unet, scheduler=scheduler, safety_checker=None, feature_extractor=feature_extractor,controlnet=controlnet)
|
|
tomesd.apply_patch(pipe, ratio=tomesd_value)
|
|
if device == "GPU":
|
|
pipe.enable_xformers_memory_efficient_attention()
|
|
pipe.enable_sequential_cpu_offload()
|
|
else:
|
|
pipe.to("cpu")
|
|
return (pipe,)
|
|
|
|
|
|
class LCMLoader_img2img:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"device": (["GPU", "CPU"],),
|
|
"model_path": ("STRING", {"default": '', "multiline": False}),
|
|
"tomesd_value": ("FLOAT", {
|
|
"default": 0.6,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
})
|
|
}
|
|
}
|
|
RETURN_TYPES = ("class",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self,device,tomesd_value,model_path):
|
|
|
|
save_path = "./lcm_images"
|
|
if model_path != "":
|
|
model_id = model_path
|
|
else:
|
|
try:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+"/LCM_Dreamshaper_v7"
|
|
except:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+"\LCM_Dreamshaper_v7"
|
|
|
|
|
|
# Initalize Diffusers Model:
|
|
vae = AutoencoderKL.from_pretrained(model_id, subfolder="vae",torch_dtype=torch.float32)
|
|
text_encoder = CLIPTextModel.from_pretrained(model_id, subfolder="text_encoder",torch_dtype=torch.float32)
|
|
tokenizer = CLIPTokenizer.from_pretrained(model_id, subfolder="tokenizer",torch_dtype=torch.float32)
|
|
unet = UNet2DConditionModel.from_pretrained(model_id, subfolder="unet", device_map=None, low_cpu_mem_usage=False, local_files_only=True,torch_dtype=torch.float32)
|
|
#safety_checker = StableDiffusionSafetyChecker.from_pretrained(model_id, subfolder="safety_checker")
|
|
feature_extractor = CLIPImageProcessor.from_pretrained(model_id, subfolder="feature_extractor",torch_dtype=torch.float32)
|
|
|
|
|
|
# Initalize Scheduler:
|
|
scheduler = LCMScheduler_X(beta_start=0.00085, beta_end=0.0120, beta_schedule="scaled_linear", prediction_type="epsilon")
|
|
|
|
# LCM Pipeline:
|
|
pipe = LatentConsistencyModelPipeline_img2img(vae=vae, text_encoder=text_encoder, tokenizer=tokenizer, unet=unet, scheduler=scheduler, safety_checker=None, feature_extractor=feature_extractor)
|
|
tomesd.apply_patch(pipe, ratio=tomesd_value)
|
|
if device == "GPU":
|
|
pipe.enable_xformers_memory_efficient_attention()
|
|
pipe.enable_sequential_cpu_offload()
|
|
else:
|
|
pipe.to("cpu")
|
|
return (pipe,)
|
|
|
|
|
|
|
|
class LCMLoader_ReferenceOnly:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"device": (["GPU", "CPU"],),
|
|
"model_path": ("STRING", {"default": '', "multiline": False}),
|
|
"tomesd_value": ("FLOAT", {
|
|
"default": 0.6,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"controlnet_model":([i for i in os.listdir(folder_paths.get_folder_paths("controlnet")[0]) if os.path.isdir(folder_paths.get_folder_paths("controlnet")[0]+f"/{i}") or os.path.isdir(folder_paths.get_folder_paths("controlnet")[0]+f"\{i}")],)
|
|
}
|
|
}
|
|
RETURN_TYPES = ("class",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self,device,tomesd_value,model_path,controlnet_model):
|
|
|
|
save_path = "./lcm_images"
|
|
|
|
if model_path != "":
|
|
model_id = model_path
|
|
else:
|
|
try:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+"/LCM_Dreamshaper_v7"
|
|
except:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+"\LCM_Dreamshaper_v7"
|
|
|
|
|
|
|
|
# Initalize Diffusers Model:
|
|
vae = AutoencoderKL.from_pretrained(model_id, subfolder="vae")
|
|
text_encoder = CLIPTextModel.from_pretrained(model_id, subfolder="text_encoder")
|
|
tokenizer = CLIPTokenizer.from_pretrained(model_id, subfolder="tokenizer")
|
|
unet = UNet2DConditionModel.from_pretrained(model_id, subfolder="unet", device_map=None, low_cpu_mem_usage=False, local_files_only=True)
|
|
#safety_checker = StableDiffusionSafetyChecker.from_pretrained(model_id, subfolder="safety_checker")
|
|
feature_extractor = CLIPImageProcessor.from_pretrained(model_id, subfolder="feature_extractor")
|
|
|
|
|
|
# Initalize Scheduler:
|
|
scheduler = LCMScheduler_X(beta_start=0.00085, beta_end=0.0120, beta_schedule="scaled_linear", prediction_type="epsilon")
|
|
try:
|
|
mpath = folder_paths.get_folder_paths("controlnet")[0]+f"/{controlnet_model}"
|
|
except:
|
|
mpath = folder_paths.get_folder_paths("controlnet")[0]+f"\{controlnet_model}"
|
|
controlnet = ControlNetModel.from_pretrained(mpath)
|
|
|
|
'''
|
|
# Replace the unet with LCM:
|
|
lcm_unet_ckpt = "./Downloads/LCM_Dreamshaper_v7_4k-prune-fp32.safetensors"
|
|
ckpt = load_file(lcm_unet_ckpt)
|
|
m, u = unet.load_state_dict(ckpt, strict=False)
|
|
if len(m) > 0:
|
|
print("missing keys:")
|
|
print(m)
|
|
if len(u) > 0:
|
|
print("unexpected keys:")
|
|
print(u)
|
|
'''
|
|
|
|
# LCM Pipeline:
|
|
pipe = LatentConsistencyModelPipeline_reference_img2img(vae=vae, text_encoder=text_encoder, tokenizer=tokenizer, unet=unet, scheduler=scheduler, safety_checker=None, feature_extractor=feature_extractor,controlnet=controlnet)
|
|
tomesd.apply_patch(pipe, ratio=tomesd_value)
|
|
if device == "GPU":
|
|
pipe.enable_xformers_memory_efficient_attention()
|
|
pipe.enable_sequential_cpu_offload()
|
|
else:
|
|
pipe.to("cpu")
|
|
return (pipe,)
|
|
|
|
|
|
class LCMLoader_RefInpaint:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"device": (["GPU", "CPU"],),
|
|
"model_path": ("STRING", {"default": '', "multiline": False}),
|
|
"tomesd_value": ("FLOAT", {
|
|
"default": 0.6,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
})
|
|
}
|
|
}
|
|
RETURN_TYPES = ("class",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self,device,tomesd_value,model_path):
|
|
|
|
save_path = "./lcm_images"
|
|
|
|
if model_path != "":
|
|
model_id = model_path
|
|
else:
|
|
try:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+"/LCM_Dreamshaper_v7"
|
|
except:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+"\LCM_Dreamshaper_v7"
|
|
|
|
|
|
|
|
# Initalize Diffusers Model:
|
|
vae = AutoencoderKL.from_pretrained(model_id, subfolder="vae")
|
|
text_encoder = CLIPTextModel.from_pretrained(model_id, subfolder="text_encoder")
|
|
tokenizer = CLIPTokenizer.from_pretrained(model_id, subfolder="tokenizer")
|
|
unet = UNet2DConditionModel.from_pretrained(model_id, subfolder="unet", device_map=None, low_cpu_mem_usage=False, local_files_only=True)
|
|
#safety_checker = StableDiffusionSafetyChecker.from_pretrained(model_id, subfolder="safety_checker")
|
|
feature_extractor = CLIPImageProcessor.from_pretrained(model_id, subfolder="feature_extractor")
|
|
|
|
|
|
# Initalize Scheduler:
|
|
scheduler = LCMScheduler_X(beta_start=0.00085, beta_end=0.0120, beta_schedule="scaled_linear", prediction_type="epsilon")
|
|
|
|
'''
|
|
# Replace the unet with LCM:
|
|
lcm_unet_ckpt = "./Downloads/LCM_Dreamshaper_v7_4k-prune-fp32.safetensors"
|
|
ckpt = load_file(lcm_unet_ckpt)
|
|
m, u = unet.load_state_dict(ckpt, strict=False)
|
|
if len(m) > 0:
|
|
print("missing keys:")
|
|
print(m)
|
|
if len(u) > 0:
|
|
print("unexpected keys:")
|
|
print(u)
|
|
'''
|
|
|
|
# LCM Pipeline:
|
|
pipe = LatentConsistencyModelPipeline_refinpaint(vae=vae, text_encoder=text_encoder, tokenizer=tokenizer, unet=unet, scheduler=scheduler, safety_checker=None, feature_extractor=feature_extractor)
|
|
tomesd.apply_patch(pipe, ratio=tomesd_value)
|
|
if device == "GPU":
|
|
pipe.enable_xformers_memory_efficient_attention()
|
|
pipe.enable_sequential_cpu_offload()
|
|
else:
|
|
pipe.to("cpu")
|
|
return (pipe,)
|
|
|
|
|
|
class LCMLoader:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"device": (["GPU", "CPU"],),
|
|
"model_path": ("STRING", {"default": '', "multiline": False}),
|
|
"tomesd_value": ("FLOAT", {
|
|
"default": 0.6,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
})
|
|
}
|
|
}
|
|
RETURN_TYPES = ("class",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self,device,tomesd_value,model_path):
|
|
|
|
save_path = "./lcm_images"
|
|
|
|
if model_path != "":
|
|
model_id = model_path
|
|
else:
|
|
try:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+"/LCM_Dreamshaper_v7"
|
|
except:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+"\LCM_Dreamshaper_v7"
|
|
|
|
|
|
|
|
# Initalize Diffusers Model:
|
|
vae = AutoencoderKL.from_pretrained(model_id, subfolder="vae")
|
|
text_encoder = CLIPTextModel.from_pretrained(model_id, subfolder="text_encoder")
|
|
tokenizer = CLIPTokenizer.from_pretrained(model_id, subfolder="tokenizer")
|
|
unet = UNet2DConditionModel.from_pretrained(model_id, subfolder="unet", device_map=None, low_cpu_mem_usage=False, local_files_only=True)
|
|
#safety_checker = StableDiffusionSafetyChecker.from_pretrained(model_id, subfolder="safety_checker")
|
|
feature_extractor = CLIPImageProcessor.from_pretrained(model_id, subfolder="feature_extractor")
|
|
|
|
|
|
# Initalize Scheduler:
|
|
scheduler = LCMScheduler_X(beta_start=0.00085, beta_end=0.0120, beta_schedule="scaled_linear", prediction_type="epsilon")
|
|
|
|
'''
|
|
# Replace the unet with LCM:
|
|
lcm_unet_ckpt = "./Downloads/LCM_Dreamshaper_v7_4k-prune-fp32.safetensors"
|
|
ckpt = load_file(lcm_unet_ckpt)
|
|
m, u = unet.load_state_dict(ckpt, strict=False)
|
|
if len(m) > 0:
|
|
print("missing keys:")
|
|
print(m)
|
|
if len(u) > 0:
|
|
print("unexpected keys:")
|
|
print(u)
|
|
'''
|
|
|
|
# LCM Pipeline:
|
|
pipe = LatentConsistencyModelPipeline_inpaint(vae=vae, text_encoder=text_encoder, tokenizer=tokenizer, unet=unet, scheduler=scheduler, safety_checker=None, feature_extractor=feature_extractor)
|
|
tomesd.apply_patch(pipe, ratio=tomesd_value)
|
|
if device == "GPU":
|
|
pipe.enable_xformers_memory_efficient_attention()
|
|
pipe.enable_sequential_cpu_offload()
|
|
else:
|
|
pipe.to("cpu")
|
|
return (pipe,)
|
|
|
|
|
|
|
|
class LCMT2IAdapter:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"T2Iadapter": ([i for i in os.listdir(folder_paths.get_folder_paths("controlnet")[0]) if os.path.isdir(folder_paths.get_folder_paths("controlnet")[0]+f"/{i}") or os.path.isdir(folder_paths.get_folder_paths("controlnet")[0]+f"\{i}")],)
|
|
}
|
|
}
|
|
RETURN_TYPES = ("class",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self,T2Iadapter):
|
|
try:
|
|
model_id = folder_paths.get_folder_paths("controlnet")[0]+f"/{T2Iadapter}"
|
|
except:
|
|
model_id = folder_paths.get_folder_paths("controlnet")[0]+f"\{T2Iadapter}"
|
|
self.adapter = adapter = T2IAdapter.from_pretrained(model_id)
|
|
self.adapter = self.adapter.to(torch.device('cuda'))
|
|
return (adapter,)
|
|
|
|
class LCM_IPAdapter_inpaint:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"device":(["cpu","cuda"],),
|
|
"ip_adapter":([i for i in os.listdir(folder_paths.get_folder_paths("controlnet")[0]) if str(i).endswith((".ckpt",".safetensors",".bin"))],),
|
|
"ip_adapter_full_path":("STRING", {"default": '', "multiline": False}),
|
|
"mode":([i for i in os.listdir(folder_paths.get_folder_paths("controlnet")[0]) if os.path.isdir(folder_paths.get_folder_paths("controlnet")[0]+f"/{i}") or os.path.isdir(folder_paths.get_folder_paths("controlnet")[0]+f"\{i}")],)
|
|
}
|
|
}
|
|
RETURN_TYPES = ("class",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self,device,ip_adapter,ip_adapter_full_path,mode):
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+"/LCM_Dreamshaper_v7"
|
|
# Initalize Diffusers Model:
|
|
vae = AutoencoderKL.from_pretrained(model_id, subfolder="vae",torch_dtype=torch.float32)
|
|
text_encoder = CLIPTextModel.from_pretrained(model_id, subfolder="text_encoder",torch_dtype=torch.float32)
|
|
tokenizer = CLIPTokenizer.from_pretrained(model_id, subfolder="tokenizer",torch_dtype=torch.float32)
|
|
unet = UNet2DConditionModel.from_pretrained(model_id, subfolder="unet", device_map=None, low_cpu_mem_usage=False, local_files_only=True,torch_dtype=torch.float32)
|
|
#safety_checker = StableDiffusionSafetyChecker.from_pretrained(model_id, subfolder="safety_checker")
|
|
feature_extractor = CLIPImageProcessor.from_pretrained(model_id, subfolder="feature_extractor",torch_dtype=torch.float32)
|
|
|
|
|
|
# Initalize Scheduler:
|
|
scheduler = LCMScheduler_X(beta_start=0.00085, beta_end=0.0120, beta_schedule="scaled_linear", prediction_type="epsilon")
|
|
|
|
# LCM Pipeline:
|
|
try:
|
|
mpath = folder_paths.get_folder_paths("controlnet")[0]+f"/{mode}"
|
|
except:
|
|
mpath = folder_paths.get_folder_paths("controlnet")[0]+f"\{mode}"
|
|
controlnet = ControlNetModel.from_pretrained(mpath,torch_dtype=torch.float32)
|
|
pipe = LatentConsistencyModelPipeline_inpaintV3(vae=vae, text_encoder=text_encoder, tokenizer=tokenizer, unet=unet, scheduler=scheduler, safety_checker=None, feature_extractor=feature_extractor,controlnet=controlnet)
|
|
tomesd.apply_patch(pipe, ratio=0.6)
|
|
'''if device == "cuda":
|
|
pipe.enable_xformers_memory_efficient_attention()
|
|
pipe.enable_sequential_cpu_offload()
|
|
else:
|
|
pipe.to("cpu")'''
|
|
if ip_adapter_full_path == "":
|
|
try:
|
|
ip_ckpt = folder_paths.get_folder_paths("controlnet")[0]+f"/{ip_adapter}"
|
|
except:
|
|
ip_ckpt = folder_paths.get_folder_paths("controlnet")[0]+f"\{ip_adapter}"
|
|
else:
|
|
ip_ckpt = ip_adapter_full_path
|
|
image_encoder_path = folder_paths.get_folder_paths("clip_vision")[0]
|
|
|
|
if "plus" not in ip_adapter:
|
|
ip_model = IPAdapter(pipe, image_encoder_path, ip_ckpt, device)
|
|
else:
|
|
ip_model = IPAdapterPlus(pipe, image_encoder_path, ip_ckpt, device, num_tokens=16)
|
|
return (ip_model,)
|
|
|
|
class LCM_IPAdapter:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"device":(["cpu","cuda"],),
|
|
"ip_adapter":([i for i in os.listdir(folder_paths.get_folder_paths("controlnet")[0]) if str(i).endswith((".ckpt",".safetensors",".bin"))],),
|
|
"ip_adapter_full_path":("STRING", {"default": '', "multiline": False}),
|
|
|
|
}
|
|
}
|
|
RETURN_TYPES = ("class",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self,device,ip_adapter,ip_adapter_full_path):
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+"/LCM_Dreamshaper_v7"
|
|
# Initalize Diffusers Model:
|
|
vae = AutoencoderKL.from_pretrained(model_id, subfolder="vae",torch_dtype=torch.float32)
|
|
text_encoder = CLIPTextModel.from_pretrained(model_id, subfolder="text_encoder",torch_dtype=torch.float32)
|
|
tokenizer = CLIPTokenizer.from_pretrained(model_id, subfolder="tokenizer",torch_dtype=torch.float32)
|
|
unet = UNet2DConditionModel.from_pretrained(model_id, subfolder="unet", device_map=None, low_cpu_mem_usage=False, local_files_only=True,torch_dtype=torch.float32)
|
|
#safety_checker = StableDiffusionSafetyChecker.from_pretrained(model_id, subfolder="safety_checker")
|
|
feature_extractor = CLIPImageProcessor.from_pretrained(model_id, subfolder="feature_extractor",torch_dtype=torch.float32)
|
|
|
|
|
|
# Initalize Scheduler:
|
|
scheduler = LCMScheduler_X(beta_start=0.00085, beta_end=0.0120, beta_schedule="scaled_linear", prediction_type="epsilon")
|
|
|
|
|
|
# LCM Pipeline:
|
|
|
|
pipe = LatentConsistencyModelPipeline_ipadapter(vae=vae, text_encoder=text_encoder, tokenizer=tokenizer, unet=unet, scheduler=scheduler, safety_checker=None, feature_extractor=feature_extractor)
|
|
tomesd.apply_patch(pipe, ratio=0.6)
|
|
'''if device == "cuda":
|
|
pipe.to("cuda")
|
|
else:
|
|
pipe.to("cpu")'''
|
|
if ip_adapter_full_path == "":
|
|
try:
|
|
ip_ckpt = folder_paths.get_folder_paths("controlnet")[0]+f"/{ip_adapter}"
|
|
except:
|
|
ip_ckpt = folder_paths.get_folder_paths("controlnet")[0]+f"\{ip_adapter}"
|
|
else:
|
|
ip_ckpt = ip_adapter_full_path
|
|
image_encoder_path = folder_paths.get_folder_paths("clip_vision")[0]
|
|
|
|
if "plus" not in ip_adapter:
|
|
ip_model = IPAdapter(pipe, image_encoder_path, ip_ckpt, device)
|
|
else:
|
|
ip_model = IPAdapterPlus(pipe, image_encoder_path, ip_ckpt, device, num_tokens=16)
|
|
return (ip_model,)
|
|
|
|
|
|
class LCMGenerate_img2img_IPAdapter:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
|
"text": ("STRING", {"default": '', "multiline": True}),
|
|
"steps": ("INT", {
|
|
"default": 4,
|
|
"min": 0,
|
|
"max": 360,
|
|
"step": 1,
|
|
}),
|
|
|
|
"width": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"height": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"cfg": ("FLOAT", {
|
|
"default": 8.0,
|
|
"min": 0,
|
|
"max": 30.0,
|
|
"step": 0.5,
|
|
}),
|
|
"batch": ("INT", {
|
|
"default": 1,
|
|
"min": 1,
|
|
"max": 100,
|
|
"step": 1,
|
|
}),
|
|
"strength": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"prompt_weighting":(["disable","enable"],),
|
|
"loopback":(["disable","enable"],),
|
|
"loopback_iterations":("INT", {
|
|
"default": 4,
|
|
"min": 1,
|
|
"max": 5000,
|
|
"step": 1,
|
|
}),
|
|
"image": ("IMAGE", ),
|
|
|
|
"ip_model":("class",),
|
|
"pil_image":("IMAGE",),
|
|
"scale": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self, text: str,steps: int,width:int,height:int,cfg:float,seed: int,batch,strength,prompt_weighting,loopback,loopback_iterations,pil_image,ip_model,image,scale):
|
|
|
|
img = pil_image[0].numpy()
|
|
img = img*255.0
|
|
pil_image = Image.fromarray(np.uint8(img))
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img))
|
|
|
|
res = []
|
|
prompt = text
|
|
if prompt_weighting == "enable":
|
|
|
|
compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)
|
|
prompt_embeds = compel_proc(prompt)
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
|
|
images = ip_model.generate(pil_image=pil_image, num_samples=1, num_inference_steps=steps, seed=seed, image=image, strength=strength,scale=scale)
|
|
res.append(images[0])
|
|
if loopback == "enable" and batch==1:
|
|
for j in range(0,loopback_iterations):
|
|
images = ip_model.generate(pil_image=pil_image, num_samples=1, num_inference_steps=steps, seed=seed, image=image, strength=strength,scale=scale)
|
|
|
|
res.append(images[0])
|
|
else:
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
images = ip_model.generate(pil_image=pil_image, num_samples=1, num_inference_steps=steps, seed=seed, image=image, strength=strength,scale=scale)
|
|
|
|
res.append(images[0])
|
|
if loopback == "enable" and batch==1:
|
|
for j in range(0,loopback_iterations):
|
|
images = ip_model.generate(pil_image=pil_image, num_samples=1, num_inference_steps=steps, seed=seed, image=image, strength=strength,scale=scale)
|
|
res.append(images[0])
|
|
|
|
return (res,)
|
|
|
|
class LCMGenerate:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"mode": (["Inpaint", "Outpaint"],),
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
|
"text": ("STRING", {"default": '', "multiline": True}),
|
|
"steps": ("INT", {
|
|
"default": 4,
|
|
"min": 0,
|
|
"max": 360,
|
|
"step": 1,
|
|
}),
|
|
|
|
"width": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"height": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"cfg": ("FLOAT", {
|
|
"default": 8.0,
|
|
"min": 0,
|
|
"max": 30.0,
|
|
"step": 0.5,
|
|
}),
|
|
"image": ("IMAGE", ),
|
|
"mask": ("IMAGE", ),
|
|
"original_image": ("IMAGE", ),
|
|
"outpaint_size": ("INT", {
|
|
"default": 256,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"outpaint_direction": (["left", "right","top","bottom"],),
|
|
"pipe":("class",),
|
|
"batch": ("INT", {
|
|
"default": 1,
|
|
"min": 1,
|
|
"max": 100,
|
|
"step": 1,
|
|
}),
|
|
"prompt_weighting":(["disable","enable"],),
|
|
"reference_image": ("IMAGE", ),
|
|
"style_fidelity": ("FLOAT", {
|
|
"default": 0.5,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"Reference_Only":(["disable","enable"],),
|
|
"oupaint_quality":(["higher","lower"],),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self, text: str,steps: int,width:int,height:int,cfg:float,seed: int,image,mask,original_image,outpaint_size,outpaint_direction,mode,pipe,batch,prompt_weighting,style_fidelity,reference_image,Reference_Only,oupaint_quality):
|
|
|
|
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img)).convert("RGB")
|
|
img = mask[0].numpy()
|
|
img = img*255.0
|
|
mask = Image.fromarray(np.uint8(img)).convert("RGB")
|
|
img = reference_image[0].numpy()
|
|
img = img*255.0
|
|
reference_image = Image.fromarray(np.uint8(img)).convert("RGB")
|
|
|
|
img = original_image[0].numpy()
|
|
img = img*255.0
|
|
original_image = Image.fromarray(np.uint8(img)).convert("RGB")
|
|
res = []
|
|
prompt = text
|
|
if prompt_weighting == "enable":
|
|
compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)
|
|
prompt_embeds = compel_proc(prompt)
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
if Reference_Only == "enable":
|
|
images = pipe(prompt_embeds=prompt_embeds, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = 1.0, image=image, mask_image=mask,ref_image=reference_image,style_fidelity=style_fidelity).images
|
|
else:
|
|
images = pipe(prompt_embeds=prompt_embeds, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = 1.0, image=image, mask_image=mask).images
|
|
else:
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
if Reference_Only == "enable":
|
|
images = pipe(prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = 1.0, image=image, mask_image=mask,ref_image=reference_image,style_fidelity=style_fidelity).images
|
|
else:
|
|
images = pipe(prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = 1.0, image=image, mask_image=mask).images
|
|
|
|
res.append(images[0])
|
|
if mode == "Outpaint":
|
|
if outpaint_direction == "right":
|
|
newbg = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newbg2 = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newmaskbg = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newmaskbg.paste(mask,(outpaint_size,0))
|
|
newbg.paste(original_image,(0,0))
|
|
newbg2.paste(images[0],(outpaint_size,0))
|
|
newmaskbg =newmaskbg.convert('L')
|
|
newmaskbg = ImageOps.invert(newmaskbg)
|
|
image = Image.composite(newbg, newbg2, newmaskbg)
|
|
elif outpaint_direction == "left":
|
|
newbg = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newbg2 = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newmaskbg = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newmaskbg.paste(mask,(0,0))
|
|
newbg.paste(original_image,(outpaint_size,0))
|
|
newbg2.paste(images[0],(0,0))
|
|
newmaskbg =newmaskbg.convert('L')
|
|
newmaskbg = ImageOps.invert(newmaskbg)
|
|
image = Image.composite(newbg, newbg2, newmaskbg)
|
|
elif outpaint_direction =="top":
|
|
newbg = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newbg2 = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newmaskbg = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newmaskbg.paste(mask,(0,0))
|
|
newbg.paste(original_image,(0,outpaint_size))
|
|
newbg2.paste(images[0],(0,0))
|
|
newmaskbg =newmaskbg.convert('L')
|
|
newmaskbg = ImageOps.invert(newmaskbg)
|
|
image = Image.composite(newbg, newbg2, newmaskbg)
|
|
elif outpaint_direction == "bottom":
|
|
newbg = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newbg2 = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newmaskbg = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newmaskbg.paste(mask,(0,outpaint_size))
|
|
newbg.paste(original_image,(0,0))
|
|
newbg2.paste(images[0],(0,outpaint_size))
|
|
newmaskbg =newmaskbg.convert('L')
|
|
newmaskbg = ImageOps.invert(newmaskbg)
|
|
image = Image.composite(newbg, newbg2, newmaskbg)
|
|
|
|
else:
|
|
newres = []
|
|
for i in range(0,1):
|
|
image = res[0]
|
|
image = np.array(image).astype(np.float32) / 255.0
|
|
image = torch.from_numpy(image)[None,]
|
|
newres.append(image)
|
|
return (res,)
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
if mode == "Outpaint" and oupaint_quality=="higher":
|
|
newres = []
|
|
if outpaint_direction == "left":
|
|
mask = Image.new("RGB", (image.size[0],image.size[1]), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((outpaint_size-30,0,outpaint_size+30,res[0].size[1]-outpaint_size), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
masknew = mask_blur
|
|
elif outpaint_direction == "right":
|
|
mask = Image.new("RGB", (image.size[0],image.size[1]), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((res[0].size[1]-outpaint_size-30,0,res[0].size[1]-outpaint_size+30,res[0].size[1]-outpaint_size), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
masknew = mask_blur
|
|
elif outpaint_direction == "top":
|
|
mask = Image.new("RGB", (image.size[0],image.size[1]), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((0,outpaint_size-30,res[0].size[1]-outpaint_size,outpaint_size+30), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
masknew = mask_blur
|
|
elif outpaint_direction == "bottom":
|
|
mask = Image.new("RGB", (image.size[0],image.size[1]), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((0,res[0].size[1]-outpaint_size-30,res[0].size[0]-outpaint_size,res[0].size[1]-outpaint_size+30), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
masknew = mask_blur
|
|
image = image.convert("RGB")
|
|
if Reference_Only == "enable":
|
|
images = pipe(prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=image.size[0],height=image.size[1],strength = 1.0, image=image, mask_image=masknew,ref_image=image,style_fidelity=style_fidelity).images
|
|
else:
|
|
images = pipe(prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=image.size[0],height=image.size[1],strength = 1.0, image=image, mask_image=masknew).images
|
|
newres.append(images[0])
|
|
return (newres,)
|
|
else:
|
|
return ([image],)
|
|
|
|
class LCMGenerate_inpaintv2:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"mode": (["Inpaint", "Outpaint"],),
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
|
"text": ("STRING", {"default": '', "multiline": True}),
|
|
"steps": ("INT", {
|
|
"default": 4,
|
|
"min": 0,
|
|
"max": 360,
|
|
"step": 1,
|
|
}),
|
|
|
|
"width": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"height": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"cfg": ("FLOAT", {
|
|
"default": 8.0,
|
|
"min": 0,
|
|
"max": 30.0,
|
|
"step": 0.5,
|
|
}),
|
|
"image": ("IMAGE", ),
|
|
"mask": ("IMAGE", ),
|
|
"original_image": ("IMAGE", ),
|
|
"outpaint_size": ("INT", {
|
|
"default": 256,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"outpaint_direction": (["left", "right","top","bottom"],),
|
|
"pipe":("class",),
|
|
"batch": ("INT", {
|
|
"default": 1,
|
|
"min": 1,
|
|
"max": 100,
|
|
"step": 1,
|
|
}),
|
|
"prompt_weighting":(["disable","enable"],),
|
|
"reference_image": ("IMAGE", ),
|
|
"style_fidelity": ("FLOAT", {
|
|
"default": 0.5,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"Reference_Only":(["disable","enable"],),
|
|
"oupaint_quality":(["higher","lower"],),
|
|
"adapter_image": ("IMAGE", ),
|
|
"adapter_weight": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"adapter":("class",),
|
|
"control_image": ("IMAGE", ),
|
|
"control_weight": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
})}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self, text: str,steps: int,width:int,height:int,cfg:float,seed: int,image,mask,original_image,outpaint_size,outpaint_direction,mode,pipe,batch,prompt_weighting,style_fidelity,reference_image,Reference_Only,oupaint_quality,adapter_image, adapter_weight,adapter,control_image,control_weight):
|
|
|
|
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img)).convert("RGB")
|
|
img = mask[0].numpy()
|
|
img = img*255.0
|
|
mask = Image.fromarray(np.uint8(img)).convert("RGB")
|
|
img = reference_image[0].numpy()
|
|
img = img*255.0
|
|
reference_image = Image.fromarray(np.uint8(img)).convert("RGB")
|
|
img = adapter_image[0].numpy()
|
|
img = img*255.0
|
|
adapter_image = Image.fromarray(np.uint8(img))
|
|
img = control_image[0].numpy()
|
|
img = img*255.0
|
|
control_image = Image.fromarray(np.uint8(img))
|
|
|
|
img = original_image[0].numpy()
|
|
img = img*255.0
|
|
original_image = Image.fromarray(np.uint8(img)).convert("RGB")
|
|
res = []
|
|
prompt = text
|
|
if prompt_weighting == "enable":
|
|
compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)
|
|
prompt_embeds = compel_proc(prompt)
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
if Reference_Only == "enable":
|
|
images = pipe(prompt_embeds=prompt_embeds, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = 1.0, image=image, mask_image=mask,ref_image=reference_image,style_fidelity=style_fidelity).images
|
|
else:
|
|
images = pipe(prompt_embeds=prompt_embeds, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = 1.0, image=image, mask_image=mask).images
|
|
else:
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
if Reference_Only == "enable":
|
|
images = pipe(controlnet_conditioning_scale=control_weight,control_image=control_image,prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = 1.0, image=image, mask_image=mask,ref_image=reference_image,style_fidelity=style_fidelity).images
|
|
else:
|
|
images = pipe(controlnet_conditioning_scale=control_weight,control_image=control_image,prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = 1.0, image=image, mask_image=mask).images
|
|
|
|
res.append(images[0])
|
|
if mode == "Outpaint":
|
|
if outpaint_direction == "right":
|
|
newbg = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newbg2 = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newmaskbg = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newmaskbg.paste(mask,(outpaint_size,0))
|
|
newbg.paste(original_image,(0,0))
|
|
newbg2.paste(images[0],(outpaint_size,0))
|
|
newmaskbg =newmaskbg.convert('L')
|
|
newmaskbg = ImageOps.invert(newmaskbg)
|
|
image = Image.composite(newbg, newbg2, newmaskbg)
|
|
elif outpaint_direction == "left":
|
|
newbg = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newbg2 = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newmaskbg = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newmaskbg.paste(mask,(0,0))
|
|
newbg.paste(original_image,(outpaint_size,0))
|
|
newbg2.paste(images[0],(0,0))
|
|
newmaskbg =newmaskbg.convert('L')
|
|
newmaskbg = ImageOps.invert(newmaskbg)
|
|
image = Image.composite(newbg, newbg2, newmaskbg)
|
|
elif outpaint_direction =="top":
|
|
newbg = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newbg2 = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newmaskbg = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newmaskbg.paste(mask,(0,0))
|
|
newbg.paste(original_image,(0,outpaint_size))
|
|
newbg2.paste(images[0],(0,0))
|
|
newmaskbg =newmaskbg.convert('L')
|
|
newmaskbg = ImageOps.invert(newmaskbg)
|
|
image = Image.composite(newbg, newbg2, newmaskbg)
|
|
elif outpaint_direction == "bottom":
|
|
newbg = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newbg2 = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newmaskbg = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newmaskbg.paste(mask,(0,outpaint_size))
|
|
newbg.paste(original_image,(0,0))
|
|
newbg2.paste(images[0],(0,outpaint_size))
|
|
newmaskbg =newmaskbg.convert('L')
|
|
newmaskbg = ImageOps.invert(newmaskbg)
|
|
image = Image.composite(newbg, newbg2, newmaskbg)
|
|
|
|
else:
|
|
newres = []
|
|
for i in range(0,1):
|
|
image = res[0]
|
|
image = np.array(image).astype(np.float32) / 255.0
|
|
image = torch.from_numpy(image)[None,]
|
|
newres.append(image)
|
|
return (res,)
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
if mode == "Outpaint" and oupaint_quality=="higher":
|
|
newres = []
|
|
if outpaint_direction == "left":
|
|
mask = Image.new("RGB", (image.size[0],image.size[1]), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((outpaint_size-30,0,outpaint_size+30,res[0].size[1]-outpaint_size), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
masknew = mask_blur
|
|
elif outpaint_direction == "right":
|
|
mask = Image.new("RGB", (image.size[0],image.size[1]), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((res[0].size[1]-outpaint_size-30,0,res[0].size[1]-outpaint_size+30,res[0].size[1]-outpaint_size), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
masknew = mask_blur
|
|
elif outpaint_direction == "top":
|
|
mask = Image.new("RGB", (image.size[0],image.size[1]), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((0,outpaint_size-30,res[0].size[1]-outpaint_size,outpaint_size+30), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
masknew = mask_blur
|
|
elif outpaint_direction == "bottom":
|
|
mask = Image.new("RGB", (image.size[0],image.size[1]), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((0,res[0].size[1]-outpaint_size-30,res[0].size[0]-outpaint_size,res[0].size[1]-outpaint_size+30), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
masknew = mask_blur
|
|
image = image.convert("RGB")
|
|
if Reference_Only == "enable":
|
|
images = pipe(prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=image.size[0],height=image.size[1],strength = 1.0, image=image, mask_image=masknew,ref_image=image,style_fidelity=style_fidelity).images
|
|
else:
|
|
images = pipe(prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=image.size[0],height=image.size[1],strength = 1.0, image=image, mask_image=masknew).images
|
|
newres.append(images[0])
|
|
return (newres,)
|
|
else:
|
|
return ([image],)
|
|
|
|
class LCMGenerate_inpaintv3:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"mode": (["Inpaint", "Outpaint"],),
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
|
"text": ("STRING", {"default": '', "multiline": True}),
|
|
"steps": ("INT", {
|
|
"default": 4,
|
|
"min": 0,
|
|
"max": 360,
|
|
"step": 1,
|
|
}),
|
|
|
|
"width": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"height": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"cfg": ("FLOAT", {
|
|
"default": 8.0,
|
|
"min": 0,
|
|
"max": 30.0,
|
|
"step": 0.5,
|
|
}),
|
|
"image": ("IMAGE", ),
|
|
"mask": ("IMAGE", ),
|
|
"original_image": ("IMAGE", ),
|
|
"outpaint_size": ("INT", {
|
|
"default": 256,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"outpaint_direction": (["left", "right","top","bottom"],),
|
|
"pipe":("class",),
|
|
"batch": ("INT", {
|
|
"default": 1,
|
|
"min": 1,
|
|
"max": 100,
|
|
"step": 1,
|
|
}),
|
|
"prompt_weighting":(["disable","enable"],),
|
|
"reference_image": ("IMAGE", ),
|
|
"style_fidelity": ("FLOAT", {
|
|
"default": 0.5,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"Reference_Only":(["disable","enable"],),
|
|
"oupaint_quality":(["higher","lower"],),
|
|
"control_image": ("IMAGE", ),
|
|
"control_weight": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"ip_model":("class",),
|
|
"pil_image":("IMAGE",),
|
|
"scale": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
})}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self, text: str,steps: int,width:int,height:int,cfg:float,seed: int,ip_model,pil_image,image,scale,mask,original_image,outpaint_size,outpaint_direction,mode,pipe,batch,prompt_weighting,style_fidelity,reference_image,Reference_Only,oupaint_quality,control_image,control_weight):
|
|
|
|
img = pil_image[0].numpy()
|
|
img = img*255.0
|
|
pil_image = Image.fromarray(np.uint8(img))
|
|
img = control_image[0].numpy()
|
|
img = img*255.0
|
|
control_image = Image.fromarray(np.uint8(img))
|
|
reference_image = pil_image
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img))
|
|
img = mask[0].numpy()
|
|
img = img*255.0
|
|
mask = Image.fromarray(np.uint8(img))
|
|
|
|
|
|
|
|
img = original_image[0].numpy()
|
|
img = img*255.0
|
|
original_image = Image.fromarray(np.uint8(img))
|
|
res = []
|
|
prompt = text
|
|
if prompt_weighting == "enable":
|
|
compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)
|
|
prompt_embeds = compel_proc(prompt)
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
if Reference_Only == "enable":
|
|
images = pipe(prompt_embeds=prompt_embeds, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = 1.0, image=image, mask_image=mask,ref_image=reference_image,style_fidelity=style_fidelity).images
|
|
else:
|
|
images = pipe(prompt_embeds=prompt_embeds, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = 1.0, image=image, mask_image=mask).images
|
|
else:
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
if Reference_Only == "enable":
|
|
images = pipe(prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = 1.0, image=image, mask_image=mask,ref_image=reference_image,style_fidelity=style_fidelity).images
|
|
else:
|
|
images = ip_model.generate(pil_image=pil_image, num_samples=1, num_inference_steps=steps, seed=seed, image=image, strength=1.0,scale=scale,mask_image=mask,control_image=control_image)
|
|
|
|
res.append(images[0])
|
|
if mode == "Outpaint":
|
|
if outpaint_direction == "right":
|
|
newbg = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newbg2 = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newmaskbg = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newmaskbg.paste(mask,(outpaint_size,0))
|
|
newbg.paste(original_image,(0,0))
|
|
newbg2.paste(images[0],(outpaint_size,0))
|
|
newmaskbg =newmaskbg.convert('L')
|
|
newmaskbg = ImageOps.invert(newmaskbg)
|
|
image = Image.composite(newbg, newbg2, newmaskbg)
|
|
elif outpaint_direction == "left":
|
|
newbg = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newbg2 = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newmaskbg = Image.new("RGBA",(images[0].size[0]+outpaint_size,images[0].size[1]),(0,0,0))
|
|
newmaskbg.paste(mask,(0,0))
|
|
newbg.paste(original_image,(outpaint_size,0))
|
|
newbg2.paste(images[0],(0,0))
|
|
newmaskbg =newmaskbg.convert('L')
|
|
newmaskbg = ImageOps.invert(newmaskbg)
|
|
image = Image.composite(newbg, newbg2, newmaskbg)
|
|
elif outpaint_direction =="top":
|
|
newbg = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newbg2 = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newmaskbg = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newmaskbg.paste(mask,(0,0))
|
|
newbg.paste(original_image,(0,outpaint_size))
|
|
newbg2.paste(images[0],(0,0))
|
|
newmaskbg =newmaskbg.convert('L')
|
|
newmaskbg = ImageOps.invert(newmaskbg)
|
|
image = Image.composite(newbg, newbg2, newmaskbg)
|
|
elif outpaint_direction == "bottom":
|
|
newbg = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newbg2 = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newmaskbg = Image.new("RGBA",(images[0].size[0],images[0].size[1]+outpaint_size),(0,0,0))
|
|
newmaskbg.paste(mask,(0,outpaint_size))
|
|
newbg.paste(original_image,(0,0))
|
|
newbg2.paste(images[0],(0,outpaint_size))
|
|
newmaskbg =newmaskbg.convert('L')
|
|
newmaskbg = ImageOps.invert(newmaskbg)
|
|
image = Image.composite(newbg, newbg2, newmaskbg)
|
|
|
|
else:
|
|
newres = []
|
|
for i in range(0,1):
|
|
image = res[0]
|
|
image = np.array(image).astype(np.float32) / 255.0
|
|
image = torch.from_numpy(image)[None,]
|
|
newres.append(image)
|
|
return (res,)
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
if mode == "Outpaint" and oupaint_quality=="higher":
|
|
newres = []
|
|
if outpaint_direction == "left":
|
|
mask = Image.new("RGB", (image.size[0],image.size[1]), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((outpaint_size-30,0,outpaint_size+30,res[0].size[1]-outpaint_size), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
masknew = mask_blur
|
|
elif outpaint_direction == "right":
|
|
mask = Image.new("RGB", (image.size[0],image.size[1]), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((res[0].size[1]-outpaint_size-30,0,res[0].size[1]-outpaint_size+30,res[0].size[1]-outpaint_size), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
masknew = mask_blur
|
|
elif outpaint_direction == "top":
|
|
mask = Image.new("RGB", (image.size[0],image.size[1]), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((0,outpaint_size-30,res[0].size[1]-outpaint_size,outpaint_size+30), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
masknew = mask_blur
|
|
elif outpaint_direction == "bottom":
|
|
mask = Image.new("RGB", (image.size[0],image.size[1]), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((0,res[0].size[1]-outpaint_size-30,res[0].size[0]-outpaint_size,res[0].size[1]-outpaint_size+30), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
masknew = mask_blur
|
|
image = image.convert("RGB")
|
|
if Reference_Only == "enable":
|
|
images = pipe(prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=image.size[0],height=image.size[1],strength = 1.0, image=image, mask_image=masknew,ref_image=image,style_fidelity=style_fidelity).images
|
|
else:
|
|
images = pipe(prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=image.size[0],height=image.size[1],strength = 1.0, image=image, mask_image=masknew).images
|
|
newres.append(images[0])
|
|
return (newres,)
|
|
else:
|
|
return ([image],)
|
|
|
|
class LCMGenerate_img2img:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"mode": (["Inpaint", "Outpaint"],),
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
|
"text": ("STRING", {"default": '', "multiline": True}),
|
|
"steps": ("INT", {
|
|
"default": 4,
|
|
"min": 0,
|
|
"max": 360,
|
|
"step": 1,
|
|
}),
|
|
|
|
"width": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"height": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"cfg": ("FLOAT", {
|
|
"default": 8.0,
|
|
"min": 0,
|
|
"max": 30.0,
|
|
"step": 0.5,
|
|
}),
|
|
"image": ("IMAGE", ),
|
|
"outpaint_size": ("INT", {
|
|
"default": 256,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"outpaint_direction": (["left", "right","top","bottom"],),
|
|
"pipe":("class",),
|
|
"batch": ("INT", {
|
|
"default": 1,
|
|
"min": 1,
|
|
"max": 100,
|
|
"step": 1,
|
|
}),
|
|
"strength": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"prompt_weighting":(["disable","enable"],),
|
|
"loopback":(["disable","enable"],),
|
|
"loopback_iterations":("INT", {
|
|
"default": 4,
|
|
"min": 1,
|
|
"max": 5000,
|
|
"step": 1,
|
|
}),
|
|
"adapter_image": ("IMAGE", ),
|
|
"adapter_weight": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"adapter":("class",)}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self, text: str,steps: int,width:int,height:int,cfg:float,seed: int,image,outpaint_size,outpaint_direction,mode,pipe,batch,strength,prompt_weighting,loopback,loopback_iterations,adapter_image, adapter_weight,adapter):
|
|
|
|
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img))
|
|
img = adapter_image[0].numpy()
|
|
img = img*255.0
|
|
adapter_image = Image.fromarray(np.uint8(img))
|
|
|
|
|
|
|
|
res = []
|
|
prompt = text
|
|
if prompt_weighting == "enable":
|
|
|
|
compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)
|
|
prompt_embeds = compel_proc(prompt)
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
|
|
images = pipe(adapter_weight=adapter_weight,adapter_img=adapter_image,adapter=adapter,prompt_embeds=prompt_embeds, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = strength, image=image).images
|
|
res.append(images[0])
|
|
if loopback == "enable" and batch==1:
|
|
for j in range(0,loopback_iterations):
|
|
images = pipe(adapter_weight=adapter_weight,adapter_img=adapter_image,adapter=adapter,prompt_embeds=prompt_embeds, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = strength, image=images[0]).images
|
|
|
|
res.append(images[0])
|
|
else:
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
images = pipe(adapter_weight=adapter_weight,adapter_img=adapter_image,adapter=adapter,prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = strength, image=image).images
|
|
|
|
res.append(images[0])
|
|
if loopback == "enable" and batch==1:
|
|
for j in range(0,loopback_iterations):
|
|
images = pipe(adapter_weight=adapter_weight,adapter_img=adapter_image,adapter=adapter,prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = strength, image=images[0]).images
|
|
res.append(images[0])
|
|
|
|
|
|
return (res,)
|
|
|
|
|
|
class LCMGenerate_img2img_controlnet:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"mode": (["Inpaint", "Outpaint"],),
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
|
"text": ("STRING", {"default": '', "multiline": True}),
|
|
"steps": ("INT", {
|
|
"default": 4,
|
|
"min": 0,
|
|
"max": 360,
|
|
"step": 1,
|
|
}),
|
|
|
|
"width": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"height": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"cfg": ("FLOAT", {
|
|
"default": 8.0,
|
|
"min": 0,
|
|
"max": 30.0,
|
|
"step": 0.5,
|
|
}),
|
|
"image": ("IMAGE", ),
|
|
"outpaint_size": ("INT", {
|
|
"default": 256,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"outpaint_direction": (["left", "right","top","bottom"],),
|
|
"pipe":("class",),
|
|
"batch": ("INT", {
|
|
"default": 1,
|
|
"min": 1,
|
|
"max": 100,
|
|
"step": 1,
|
|
}),
|
|
"strength": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"prompt_weighting":(["disable","enable"],),
|
|
"loopback":(["disable","enable"],),
|
|
"loopback_iterations":("INT", {
|
|
"default": 4,
|
|
"min": 1,
|
|
"max": 5000,
|
|
"step": 1,
|
|
}),
|
|
"control_image": ("IMAGE", ),
|
|
"control_weight": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
})}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self, text: str,steps: int,width:int,height:int,cfg:float,seed: int,image,outpaint_size,outpaint_direction,mode,pipe,batch,strength,prompt_weighting,loopback,loopback_iterations, control_image, control_weight):
|
|
|
|
try:
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img))
|
|
img = control_image[0].numpy()
|
|
img = img*255.0
|
|
control_image = Image.fromarray(np.uint8(img))
|
|
except:
|
|
image=image
|
|
|
|
|
|
|
|
res = []
|
|
prompt = text
|
|
if prompt_weighting == "enable":
|
|
|
|
compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)
|
|
prompt_embeds = compel_proc(prompt)
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
|
|
images = pipe(adapter_weight=adapter_weight,adapter_img=adapter_image,adapter=adapter,prompt_embeds=prompt_embeds, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = strength, image=image).images
|
|
res.append(images[0])
|
|
if loopback == "enable" and batch==1:
|
|
for j in range(0,loopback_iterations):
|
|
images = pipe(adapter_weight=adapter_weight,adapter_img=adapter_image,adapter=adapter,prompt_embeds=prompt_embeds, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = strength, image=images[0]).images
|
|
|
|
res.append(images[0])
|
|
else:
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
images = pipe(controlnet_conditioning_scale=control_weight,control_image=control_image,prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = strength, image=image).images
|
|
|
|
res.append(images[0])
|
|
if loopback == "enable" and batch==1:
|
|
for j in range(0,loopback_iterations):
|
|
images = pipe(adapter_weight=adapter_weight,adapter_img=adapter_image,adapter=adapter,prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = strength, image=images[0]).images
|
|
res.append(images[0])
|
|
|
|
|
|
|
|
return (res,)
|
|
|
|
|
|
|
|
|
|
class LCMGenerate_ReferenceOnly:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
|
"text": ("STRING", {"default": '', "multiline": True}),
|
|
"steps": ("INT", {
|
|
"default": 4,
|
|
"min": 0,
|
|
"max": 360,
|
|
"step": 1,
|
|
}),
|
|
|
|
"width": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"height": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"cfg": ("FLOAT", {
|
|
"default": 8.0,
|
|
"min": 0,
|
|
"max": 30.0,
|
|
"step": 0.5,
|
|
}),
|
|
"image": ("IMAGE", ),
|
|
"reference_image": ("IMAGE", ),
|
|
|
|
"pipe":("class",),
|
|
"batch": ("INT", {
|
|
"default": 1,
|
|
"min": 1,
|
|
"max": 100,
|
|
"step": 1,
|
|
}),
|
|
"style_fidelity": ("FLOAT", {
|
|
"default": 0.5,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.01,
|
|
}),
|
|
"strength": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.01,
|
|
}),
|
|
"prompt_weighting":(["disable","enable"],),
|
|
"control_image": ("IMAGE", ),
|
|
"control_weight": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
})
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self, text: str,steps: int,width:int,height:int,cfg:float,seed: int,image,strength,reference_image,pipe,batch,prompt_weighting,style_fidelity,control_image, control_weight):
|
|
|
|
|
|
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img))
|
|
img = reference_image[0].numpy()
|
|
img = img*255.0
|
|
reference_image = Image.fromarray(np.uint8(img))
|
|
img = control_image[0].numpy()
|
|
img = img*255.0
|
|
control_image = Image.fromarray(np.uint8(img))
|
|
|
|
|
|
|
|
|
|
res = []
|
|
prompt = text
|
|
if prompt_weighting == "enable":
|
|
|
|
compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)
|
|
prompt_embeds = compel_proc(prompt)
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
|
|
images = pipe(prompt_embeds=prompt_embeds, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = strength, image=image,ref_image=reference_image,style_fidelity=style_fidelity).images
|
|
res.append(images[0])
|
|
|
|
else:
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
# Output Images:
|
|
images = pipe(controlnet_conditioning_scale=control_weight,control_image=control_image,prompt=prompt, num_images_per_prompt=1, num_inference_steps=steps, guidance_scale=cfg, lcm_origin_steps=50,width=width,height=height,strength = strength, image=image,ref_image=reference_image,style_fidelity=style_fidelity).images
|
|
|
|
res.append(images[0])
|
|
|
|
|
|
|
|
return (res,)
|
|
|
|
|
|
|
|
|
|
class LCM_outpaint_prep:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"direction": (["left", "right","top","bottom"],),
|
|
"size": ("INT", {
|
|
"default": 0,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}
|
|
),
|
|
"image": ("IMAGE", ),}
|
|
}
|
|
CATEGORY = "image"
|
|
|
|
RETURN_TYPES = ("IMAGE","IMAGE")
|
|
FUNCTION = "outpaint"
|
|
def outpaint(self,image, direction,size):
|
|
growth = 30
|
|
if direction == "right":
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img)).convert("RGB")
|
|
print(image.size)
|
|
w,h = image.size
|
|
bimage = Image.new("RGB", (w,h), (0,0,0))
|
|
image_crop = image.crop((size,0,image.size[0],image.size[1]))
|
|
bimage.paste(image_crop,(0,0))
|
|
image = bimage
|
|
mask = Image.new("RGB", (w,h), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((size-growth, 0, image.size[0],image.size[1]), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
mask = mask_blur
|
|
elif direction == "left":
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img)).convert("RGB")
|
|
print(image.size)
|
|
w,h = image.size
|
|
bimage = Image.new("RGB", (w,h), (0,0,0))
|
|
image_crop = image.crop((0,0,image.size[0]-size,image.size[1]))
|
|
bimage.paste(image_crop,(size,0))
|
|
image = bimage
|
|
mask = Image.new("RGB", (w,h), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((0, 0, image.size[0]-size+growth,image.size[1]), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
mask = mask_blur
|
|
elif direction == "top":
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img)).convert("RGB")
|
|
print(image.size)
|
|
w,h = image.size
|
|
bimage = Image.new("RGB", (w,h), (0,0,0))
|
|
image_crop = image.crop((0,0,image.size[0],image.size[1]-size))
|
|
bimage.paste(image_crop,(0,size))
|
|
image = bimage
|
|
mask = Image.new("RGB", (w,h), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((0, 0, image.size[0],image.size[1]-size+growth), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
mask = mask_blur
|
|
elif direction == "bottom":
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img)).convert("RGB")
|
|
print(image.size)
|
|
w,h = image.size
|
|
bimage = Image.new("RGB", (w,h), (0,0,0))
|
|
image_crop = image.crop((0,size,image.size[0],image.size[1]))
|
|
bimage.paste(image_crop,(0,0))
|
|
image = bimage
|
|
mask = Image.new("RGB", (w,h), (0,0,0))
|
|
draw = ImageDraw.Draw(mask)
|
|
draw.rectangle((0, image.size[1]-size-growth, image.size[0],image.size[1]), fill=(255,255,255))
|
|
mask_blur = mask.filter(ImageFilter.GaussianBlur(10))
|
|
mask = mask_blur
|
|
image = np.array(image).astype(np.float32) / 255.0
|
|
image = torch.from_numpy(image)[None,]
|
|
mask = np.array(mask).astype(np.float32) / 255.0
|
|
mask = torch.from_numpy(mask)[None,]
|
|
return (image,mask)
|
|
|
|
|
|
class FreeU_LCM:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
input_dir = folder_paths.get_input_directory()
|
|
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
|
|
return {"required":
|
|
{"b1": ("FLOAT", {
|
|
"default": 1.3,
|
|
"min": 0.0,
|
|
"max": 3.0,
|
|
"step": 0.1,
|
|
}),
|
|
"b2": ("FLOAT", {
|
|
"default": 1.4,
|
|
"min": 0.0,
|
|
"max": 3.0,
|
|
"step": 0.1,
|
|
}),
|
|
"s1": ("FLOAT", {
|
|
"default": 0.9,
|
|
"min": 0.0,
|
|
"max": 3.0,
|
|
"step": 0.1,
|
|
}),
|
|
"s2": ("FLOAT", {
|
|
"default": 0.2,
|
|
"min": 0.0,
|
|
"max": 3.0,
|
|
"step": 0.1,
|
|
}),
|
|
"pipe":("class",)},
|
|
}
|
|
|
|
CATEGORY = "image"
|
|
|
|
RETURN_TYPES = ("class",)
|
|
FUNCTION = "load_image"
|
|
def load_image(self, b1,b2,s1,s2,pipe):
|
|
pipe.enable_freeu(s1=s1, s2=s2, b1=b1, b2=b2)
|
|
return (pipe,)
|
|
|
|
class ImageShuffle:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
input_dir = folder_paths.get_input_directory()
|
|
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
|
|
return {"required":
|
|
{"image_1": ("IMAGE",),
|
|
"image_2": ("IMAGE",),
|
|
"image_3": ("IMAGE",),
|
|
"image_4": ("IMAGE",),
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),},
|
|
}
|
|
|
|
CATEGORY = "image"
|
|
|
|
RETURN_TYPES = ("IMAGE","IMAGE","IMAGE","IMAGE",)
|
|
FUNCTION = "load_image"
|
|
def load_image(self, image_1,image_2,image_3,image_4,seed):
|
|
newarr = [image_1,image_2,image_3,image_4]
|
|
random.shuffle(newarr)
|
|
return (newarr[0],newarr[1],newarr[2],newarr[3])
|
|
|
|
class ImageOutputToComfyNodes:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
input_dir = folder_paths.get_input_directory()
|
|
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
|
|
return {"required":
|
|
{"image": ("IMAGE",)},
|
|
}
|
|
|
|
CATEGORY = "image"
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "load_image"
|
|
def load_image(self, image):
|
|
image = np.array(image[0]).astype(np.float32) / 255.0
|
|
image = torch.from_numpy(image)[None,]
|
|
return (image,)
|
|
|
|
class LoadImageNode_LCM:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
input_dir = folder_paths.get_input_directory()
|
|
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
|
|
return {"required":
|
|
{"image": ("STRING", {"multiline": False})},
|
|
}
|
|
|
|
CATEGORY = "image"
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "load_image"
|
|
def load_image(self, image):
|
|
print(image)
|
|
i = Image.open(image)
|
|
i = ImageOps.exif_transpose(i)
|
|
image = i.convert("RGB")
|
|
image = np.array(image).astype(np.float32) / 255.0
|
|
image = torch.from_numpy(image)[None,]
|
|
return (image,)
|
|
|
|
class SaveImage_LCM:
|
|
def __init__(self):
|
|
self.output_dir = folder_paths.get_output_directory()
|
|
self.type = "output"
|
|
self.prefix_append = ""
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {"required":
|
|
{"images": ("IMAGE", ),
|
|
"filename_prefix": ("STRING", {"default": "ComfyUI"})},
|
|
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"},
|
|
}
|
|
|
|
RETURN_TYPES = ()
|
|
FUNCTION = "save_images"
|
|
|
|
OUTPUT_NODE = True
|
|
|
|
CATEGORY = "image"
|
|
|
|
def save_images(self, images, filename_prefix="ComfyUI", prompt=None, extra_pnginfo=None):
|
|
filename_prefix += self.prefix_append
|
|
full_output_folder, filename, counter, subfolder, filename_prefix = folder_paths.get_save_image_path(filename_prefix, self.output_dir, 512, 512)
|
|
results = list()
|
|
for image in images:
|
|
img = image
|
|
if not args.disable_metadata:
|
|
metadata = PngInfo()
|
|
if prompt is not None:
|
|
metadata.add_text("prompt", json.dumps(prompt))
|
|
if extra_pnginfo is not None:
|
|
for x in extra_pnginfo:
|
|
metadata.add_text(x, json.dumps(extra_pnginfo[x]))
|
|
|
|
file = f"{filename}_{counter:05}_.png"
|
|
img.save(os.path.join(full_output_folder, file), pnginfo=metadata, compress_level=4)
|
|
data = {
|
|
"lastimage":str(os.path.join(full_output_folder, file))
|
|
}
|
|
json_object = json.dumps(data, indent=4)
|
|
savepath = folder_paths.get_folder_paths("custom_nodes")[0]+"/LCM_Inpaint-Outpaint_Comfy/CanvasTool/lastimage.json"
|
|
savepath = Path(savepath)
|
|
with open(savepath, "w") as outfile:
|
|
print(savepath)
|
|
outfile.write(json_object)
|
|
|
|
|
|
|
|
results.append({
|
|
"filename": file,
|
|
"subfolder": subfolder,
|
|
"type": self.type
|
|
})
|
|
counter += 1
|
|
|
|
return { "ui": { "images": results } }
|
|
|
|
|
|
class OutpaintCanvasTool:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {"required":
|
|
{
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE","IMAGE","IMAGE")
|
|
FUNCTION = "canvasopen"
|
|
def canvasopen(self,seed):
|
|
bg = Image.open(folder_paths.get_folder_paths("custom_nodes")[0]+"/LCM_Inpaint_Outpaint_Comfy/CanvasTool/image.png")
|
|
i = ImageOps.exif_transpose(bg)
|
|
image = i.convert("RGB")
|
|
image = np.array(image).astype(np.float32) / 255.0
|
|
bg = torch.from_numpy(image)[None,]
|
|
bg2 = Image.open(folder_paths.get_folder_paths("custom_nodes")[0]+"/LCM_Inpaint_Outpaint_Comfy/CanvasTool/mask.png")
|
|
i = ImageOps.exif_transpose(bg2)
|
|
image = i.convert("RGB")
|
|
image = np.array(image).astype(np.float32) / 255.0
|
|
bg2 = torch.from_numpy(image)[None,]
|
|
ref = Image.open(folder_paths.get_folder_paths("custom_nodes")[0]+"/LCM_Inpaint_Outpaint_Comfy/CanvasTool/cropped.png")
|
|
i = ImageOps.exif_transpose(ref)
|
|
image = i.convert("RGB")
|
|
image = np.array(image).astype(np.float32) / 255.0
|
|
ref = torch.from_numpy(image)[None,]
|
|
|
|
return (bg,bg2,ref)
|
|
|
|
class stitch:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {"required":
|
|
{
|
|
"image":("IMAGE",),
|
|
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "canvasopen"
|
|
def canvasopen(self,image):
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img)).convert("RGBA")
|
|
with open(folder_paths.get_folder_paths("custom_nodes")[0]+"/LCM_Inpaint_Outpaint_Comfy/CanvasTool/data.json","r") as json_file:
|
|
savedata = json.load(json_file)["savedata"]
|
|
bg = Image.open(folder_paths.get_folder_paths("custom_nodes")[0]+"/LCM_Inpaint_Outpaint_Comfy/CanvasTool/out.png").convert("RGBA")
|
|
msksmall = Image.open(folder_paths.get_folder_paths("custom_nodes")[0]+"/LCM_Inpaint_Outpaint_Comfy/CanvasTool/mask.png").convert("L")
|
|
cropped = Image.open(folder_paths.get_folder_paths("custom_nodes")[0]+"/LCM_Inpaint_Outpaint_Comfy/CanvasTool/image.png").convert("RGBA")
|
|
width = int(savedata["additionaldims"]["right"]) + int(savedata["additionaldims"]["left"]) + bg.size[0]
|
|
height = int(savedata["additionaldims"]["top"]) + int(savedata["additionaldims"]["bottom"]) + bg.size[1]
|
|
new = Image.new("RGBA",(width,height),(0,0,0,0))
|
|
lft = 0
|
|
tp = 0
|
|
image = Image.composite(image, cropped, msksmall)
|
|
if savedata["additionaldims"]["left"]>0:
|
|
lft = int(savedata["additionaldims"]["left"])
|
|
|
|
if savedata["additionaldims"]["top"]>0:
|
|
tp = int(savedata["additionaldims"]["top"])
|
|
new.paste(bg,(lft,tp))
|
|
lft = int(savedata["crpdims"]["left"])
|
|
tp = int(savedata["crpdims"]["top"])
|
|
new.paste(image,(lft,tp))
|
|
res = []
|
|
res.append(new)
|
|
return (res,)
|
|
|
|
class LCMLoraLoader_inpaint:
|
|
def __init__(self):
|
|
pass
|
|
|
|
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
files = []
|
|
for j in ["/IPAdapter/models","\IPAdapter\models"]:
|
|
try:
|
|
for i in os.listdir(folder_paths.get_folder_paths("controlnet")[0]+j):
|
|
if os.path.isfile(os.path.join(folder_paths.get_folder_paths("controlnet")[0]+j,i)):
|
|
files.append(i)
|
|
except:
|
|
pass
|
|
|
|
return {
|
|
"required": {
|
|
"device": (["GPU", "CPU"],),
|
|
"tomesd_value": ("FLOAT", {
|
|
"default": 0.6,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"ip_adapter":(["disable","enable"],),
|
|
"reference_only":(["disable","enable"],),
|
|
"ip_adapter_model":(files,),
|
|
"model_name":([i for i in os.listdir(folder_paths.get_folder_paths("diffusers")[0]) if os.path.isdir(folder_paths.get_folder_paths("diffusers")[0]+f"/{i}") or os.path.isdir(folder_paths.get_folder_paths("diffusers")[0]+f"\{i}")],),
|
|
"controlnet_model":([i for i in os.listdir(folder_paths.get_folder_paths("controlnet")[0]) if os.path.isdir(folder_paths.get_folder_paths("controlnet")[0]+f"/{i}") or os.path.isdir(folder_paths.get_folder_paths("controlnet")[0]+f"\{i}")],)
|
|
}
|
|
}
|
|
RETURN_TYPES = ("class",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self,device,tomesd_value,controlnet_model,ip_adapter_model,model_name,ip_adapter,reference_only):
|
|
try:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+f"/{model_name}"
|
|
except:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+f"\{model_name}"
|
|
|
|
try:
|
|
mpath = folder_paths.get_folder_paths("controlnet")[0]+f"/{controlnet_model}"
|
|
except:
|
|
mpath = folder_paths.get_folder_paths("controlnet")[0]+f"\{controlnet_model}"
|
|
controlnet = ControlNetModel.from_pretrained(mpath)
|
|
if reference_only == "disable":
|
|
pipe = LCM_lora_inpaint_ipadapter.from_pretrained(model_id,safety_checker=None,controlnet=controlnet)
|
|
else:
|
|
pipe = LCM_inpaint_final.from_pretrained(model_id,safety_checker=None,controlnet=controlnet)
|
|
if ip_adapter=="enable":
|
|
pipe.load_ip_adapter(folder_paths.get_folder_paths("controlnet")[0]+"/IPAdapter", subfolder="models", weight_name=ip_adapter_model)
|
|
|
|
# set scheduler
|
|
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
|
|
|
|
# load LCM-LoRA
|
|
pipe.load_lora_weights(folder_paths.get_folder_paths("loras")[0]+"/pytorch_lora_weights.safetensors")
|
|
pipe.fuse_lora()
|
|
tomesd.apply_patch(pipe, ratio=tomesd_value)
|
|
if device == "GPU":
|
|
pipe.enable_xformers_memory_efficient_attention()
|
|
pipe.enable_sequential_cpu_offload()
|
|
else:
|
|
pipe.to("cpu")
|
|
return (pipe,)
|
|
|
|
class LCMLora_inpaint:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
|
"text": ("STRING", {"default": '', "multiline": True}),
|
|
"steps": ("INT", {
|
|
"default": 4,
|
|
"min": 0,
|
|
"max": 360,
|
|
"step": 1,
|
|
}),
|
|
"width": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"height": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"cfg": ("FLOAT", {
|
|
"default": 1.8,
|
|
"min": 0,
|
|
"max": 3.0,
|
|
"step": 0.1,
|
|
}),
|
|
"mask": ("IMAGE", ),
|
|
"image": ("IMAGE", ),
|
|
"reference_image": ("IMAGE", ),
|
|
"reference_style_fidelity": ("FLOAT", {
|
|
"default": 0.5,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"pipe":("class",),
|
|
"batch": ("INT", {
|
|
"default": 1,
|
|
"min": 1,
|
|
"max": 100,
|
|
"step": 1,
|
|
}),
|
|
"strength": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"prompt_weighting":(["disable","enable"],),
|
|
"controlnet_weight": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"reference_only":(["disable","enable"],),
|
|
"ip_adapter":(["disable","enable"],),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self, text: str,steps: int,width:int,height:int,cfg:float,seed: int,image,pipe,batch,reference_image,reference_style_fidelity,strength,prompt_weighting, controlnet_weight,mask,reference_only,ip_adapter):
|
|
|
|
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img))
|
|
|
|
img = mask[0].numpy()
|
|
img = img*255.0
|
|
mask = Image.fromarray(np.uint8(img)).convert("RGB")
|
|
|
|
img = reference_image[0].numpy()
|
|
img = img*255.0
|
|
reference_image = Image.fromarray(np.uint8(img)).convert("RGB")
|
|
|
|
if ip_adapter == "enable":
|
|
ip_adapter_image = reference_image
|
|
else:
|
|
ip_adapter_image = None
|
|
|
|
|
|
res = []
|
|
prompt = text
|
|
if prompt_weighting == "enable":
|
|
|
|
compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)
|
|
prompt_embeds = compel_proc(prompt)
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
torch.manual_seed(seed)
|
|
if reference_only == "enable":
|
|
images = pipe(
|
|
prompt_embeds=prompt_embeds, num_inference_steps=steps, generator=generator, guidance_scale=cfg,width=width,height=height,image=image,controlnet_conditioning_scale=adapter_weight,mask_image=mask,control_image=None,strength=strength,ip_adapter_image= ip_adapter_image,ref_image=reference_image,style_fidelity=reference_style_fidelity,
|
|
cross_attention_kwargs={"scale": 1}
|
|
).images
|
|
else:
|
|
images = pipe(
|
|
prompt_embeds=prompt_embeds, num_inference_steps=steps, generator=generator, guidance_scale=cfg,width=width,height=height,image=image,controlnet_conditioning_scale=adapter_weight,mask_image=mask,control_image=None,strength=strength,ip_adapter_image= ip_adapter_image,
|
|
cross_attention_kwargs={"scale": 1}
|
|
).images
|
|
res.append(images[0])
|
|
else:
|
|
for i in range(0,batch):
|
|
seed = random.randint(0,1000000000000000)
|
|
generator = torch.manual_seed(seed)
|
|
if reference_only == "enable":
|
|
images = pipe(prompt=prompt, num_inference_steps=steps, generator=generator, guidance_scale=cfg,width=width,height=height,image=image,controlnet_conditioning_scale=controlnet_weight,mask_image=mask,control_image=None,strength=strength,ip_adapter_image= ip_adapter_image,ref_image=reference_image,style_fidelity=reference_style_fidelity,cross_attention_kwargs={"scale": 1}).images
|
|
else:
|
|
images = pipe(
|
|
prompt=prompt, num_inference_steps=steps, generator=generator, guidance_scale=cfg,width=width,height=height,image=image,controlnet_conditioning_scale=controlnet_weight,mask_image=mask,control_image=None,strength=strength,ip_adapter_image= ip_adapter_image,
|
|
cross_attention_kwargs={"scale": 1}
|
|
).images
|
|
res.append(images[0])
|
|
|
|
return (res,)
|
|
|
|
class LCMLoader_SDTurbo:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"model_path": ([i for i in os.listdir(folder_paths.get_folder_paths("diffusers")[0]) if os.path.isdir(folder_paths.get_folder_paths("diffusers")[0]+f"/{i}") or os.path.isdir(folder_paths.get_folder_paths("diffusers")[0]+f"\{i}")],),
|
|
"tomesd_value": ("FLOAT", {
|
|
"default": 0.6,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"reference_only":(["disable","enable"],),
|
|
}
|
|
}
|
|
RETURN_TYPES = ("class",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self,tomesd_value,model_path,reference_only):
|
|
|
|
|
|
|
|
try:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+f'/{model_path}'
|
|
except:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+f'\{model_path}'
|
|
|
|
pipe = StableDiffusionImg2ImgPipeline_reference.from_pretrained(model_id,safety_checker=None)
|
|
tomesd.apply_patch(pipe, ratio=tomesd_value)
|
|
pipe.enable_xformers_memory_efficient_attention()
|
|
pipe.enable_sequential_cpu_offload()
|
|
return (pipe,)
|
|
|
|
class LCMGenerate_SDTurbo:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"pipe":("class",),
|
|
"device": (["cuda", "cpu"],),
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
|
"negative_prompt": ("STRING", {"default": '', "multiline": True}),
|
|
"prompt": ("STRING", {"default": '', "multiline": True}),
|
|
"steps": ("INT", {
|
|
"default": 4,
|
|
"min": 0,
|
|
"max": 360,
|
|
"step": 1,
|
|
}),
|
|
|
|
"width": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"height": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"cfg": ("FLOAT", {
|
|
"default": 8.0,
|
|
"min": 0,
|
|
"max": 30.0,
|
|
"step": 0.5,
|
|
}),
|
|
"image": ("IMAGE", ),
|
|
"reference_image": ("IMAGE", ),
|
|
"style_fidelity": ("FLOAT", {
|
|
"default": 0.5,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.01,
|
|
}),
|
|
"strength": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"batch": ("INT", {
|
|
"default": 1,
|
|
"min": 0,
|
|
"max": 1000,
|
|
"step": 1,
|
|
}),
|
|
"reference_only":(["disable","enable"],),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self, prompt: str,steps: int,width:int,height:int,cfg:float,seed: int,image,pipe,batch,strength,negative_prompt,device,reference_image,style_fidelity,reference_only):
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img))
|
|
|
|
img = reference_image[0].numpy()
|
|
img = img*255.0
|
|
reference_image = Image.fromarray(np.uint8(img))
|
|
|
|
negative_prompt=negative_prompt
|
|
|
|
res = []
|
|
for m in range(batch):
|
|
if reference_only == "disable":
|
|
images = pipe(prompt,negative_prompt=negative_prompt,width=width,height=height, image=image, num_inference_steps=steps, strength=strength, guidance_scale=0.0).images
|
|
else:
|
|
images = pipe(prompt,negative_prompt=negative_prompt,width=width,height=height, image=image, num_inference_steps=steps, strength=strength, guidance_scale=0.0,ref_image = reference_image,style_fidelity=style_fidelity).images
|
|
res.append(images[0])
|
|
|
|
return (res,)
|
|
|
|
class Loader_SegmindVega:
|
|
def __init__(self):
|
|
pass
|
|
|
|
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
files = []
|
|
for j in ["/IPAdapter/models","\IPAdapter\models"]:
|
|
try:
|
|
for i in os.listdir(folder_paths.get_folder_paths("controlnet")[0]+j):
|
|
if os.path.isfile(os.path.join(folder_paths.get_folder_paths("controlnet")[0]+j,i)):
|
|
files.append(i)
|
|
except:
|
|
pass
|
|
return {
|
|
"required": {
|
|
"device": (["GPU", "CPU"],),
|
|
"tomesd_value": ("FLOAT", {
|
|
"default": 0.6,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"ip_adapter_model":(files,),
|
|
"reference_only":(["disable","enable"],),
|
|
"ip_adapter":(["disable","enable"],),
|
|
"model_name":([i for i in os.listdir(folder_paths.get_folder_paths("diffusers")[0]) if os.path.isdir(folder_paths.get_folder_paths("diffusers")[0]+f"/{i}") or os.path.isdir(folder_paths.get_folder_paths("diffusers")[0]+f"\{i}")],),
|
|
|
|
}
|
|
}
|
|
RETURN_TYPES = ("class",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self,device,tomesd_value,ip_adapter_model,model_name,reference_only,ip_adapter):
|
|
try:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+f"/{model_name}"
|
|
except:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+f"\{model_name}"
|
|
'''if ip_adapter == "enable" and reference_only=="disable":
|
|
pipe = StableDiffusionImg2ImgPipeline.from_pretrained(model_id,safety_checker=None)
|
|
pipe.load_ip_adapter(folder_paths.get_folder_paths("controlnet")[0]+"/IPAdapter", subfolder="models", weight_name=ip_adapter_model)
|
|
elif reference_only == "disable":
|
|
pipe = StableDiffusionImg2ImgPipeline.from_pretrained(model_id,safety_checker=None)
|
|
else:
|
|
pipe = StableDiffusionImg2ImgPipeline_reference.from_pretrained(model_id,safety_checker=None)'''
|
|
pipe = StableDiffusionXLPipeline.from_pretrained(model_id,safety_checker=None)
|
|
# set scheduler
|
|
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
|
|
|
|
pipe.load_lora_weights(folder_paths.get_folder_paths("loras")[0]+"/pytorch_lora_weights_vega.safetensors")
|
|
pipe.fuse_lora()
|
|
tomesd.apply_patch(pipe, ratio=tomesd_value)
|
|
if device == "GPU":
|
|
pipe.enable_xformers_memory_efficient_attention()
|
|
pipe.enable_sequential_cpu_offload()
|
|
pipe.enable_vae_tiling()
|
|
pipe.enable_vae_slicing()
|
|
else:
|
|
pipe.to("cpu")
|
|
return (pipe,)
|
|
|
|
class SegmindVega:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"pipe":("class",),
|
|
"device": (["cuda", "cpu"],),
|
|
"mode": (["variation", "editing"],),
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
|
"original_prompt": ("STRING", {"default": '', "multiline": True}),
|
|
"prompt": ("STRING", {"default": '', "multiline": True}),
|
|
"negative_prompt": ("STRING", {"default": '', "multiline": True}),
|
|
"steps": ("INT", {
|
|
"default": 4,
|
|
"min": 0,
|
|
"max": 360,
|
|
"step": 1,
|
|
}),
|
|
|
|
"width": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"height": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"cfg": ("FLOAT", {
|
|
"default": 8.0,
|
|
"min": 0,
|
|
"max": 30.0,
|
|
"step": 0.5,
|
|
}),
|
|
"image": ("IMAGE", ),
|
|
"reference_image": ("IMAGE", ),
|
|
"style_fidelity": ("FLOAT", {
|
|
"default": 0.5,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.01,
|
|
}),
|
|
"strength": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.1,
|
|
}),
|
|
"editing_early_steps": ("INT", {
|
|
"default": 1000,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 1,
|
|
}),
|
|
"batch": ("INT", {
|
|
"default": 1,
|
|
"min": 0,
|
|
"max": 1000,
|
|
"step": 1,
|
|
}),
|
|
"ipadapter_scale":("FLOAT", {
|
|
"default": 0.6,
|
|
"min": 0.0,
|
|
"max": 10.0,
|
|
"step": 0.1,
|
|
}),
|
|
"reference_only":(["disable","enable"],),
|
|
"ip_adapter":(["disable","enable"],),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("LATENT",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self, prompt: str,steps: int,width:int,height:int,cfg:float,seed: int,image,mode,pipe,batch,strength,editing_early_steps,original_prompt,device,reference_image,style_fidelity,ipadapter_scale,reference_only,ip_adapter,negative_prompt):
|
|
if ip_adapter =="enable":
|
|
pipe.set_ip_adapter_scale(ipadapter_scale)
|
|
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img))
|
|
|
|
img = reference_image[0].numpy()
|
|
img = img*255.0
|
|
reference_image = Image.fromarray(np.uint8(img))
|
|
|
|
|
|
|
|
res = []
|
|
for m in range(batch):
|
|
'''if ip_adapter == "enable" and reference_only=="disable":
|
|
images = pipe(prompt,negative_prompt=negative_prompt,width=width,height=height, image=image, num_inference_steps=steps, strength=strength, guidance_scale=cfg,ip_adapter_image = reference_image).images
|
|
elif reference_only == "disable":
|
|
images = pipe(prompt,negative_prompt=negative_prompt,width=width,height=height, image=image, num_inference_steps=steps, strength=strength, guidance_scale=cfg).images
|
|
elif reference_only=="enable":
|
|
images = pipe(prompt,negative_prompt=negative_prompt,width=width,height=height, image=image, num_inference_steps=steps, strength=strength, guidance_scale=cfg,ref_image=reference_image,style_fidelity=style_fidelity).images
|
|
else:
|
|
images = pipe(prompt,negative_prompt=negative_prompt,width=width,height=height, image=image, num_inference_steps=steps, strength=strength, guidance_scale=cfg,ip_adapter_image = reference_image,ref_image=reference_image,style_fidelity=style_fidelity).images
|
|
'''
|
|
images = pipe(prompt=prompt, negative_prompt=negative_prompt,num_inference_steps=steps,guidance_scale=cfg,output_type="latent").images
|
|
'''res = []
|
|
for idx, image in enumerate(images):
|
|
res.append(image) '''
|
|
out = {"samples":(images/0.13025)}
|
|
|
|
|
|
return (out,)
|
|
|
|
|
|
class SaveImage_Puzzle:
|
|
def __init__(self):
|
|
self.output_dir = folder_paths.get_output_directory()
|
|
self.type = "output"
|
|
self.prefix_append = ""
|
|
self.compress_level = 4
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {"required":
|
|
{"images": ("IMAGE", ),
|
|
"filename_prefix": ("STRING", {"default": "ComfyUI"})},
|
|
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"},
|
|
}
|
|
|
|
RETURN_TYPES = ()
|
|
FUNCTION = "save_images"
|
|
|
|
OUTPUT_NODE = True
|
|
|
|
CATEGORY = "image"
|
|
|
|
def save_images(self, images, filename_prefix="ComfyUI", prompt=None, extra_pnginfo=None):
|
|
filename_prefix += self.prefix_append
|
|
full_output_folder, filename, counter, subfolder, filename_prefix = folder_paths.get_save_image_path(filename_prefix, self.output_dir, images[0].shape[1], images[0].shape[0])
|
|
results = list()
|
|
for image in images:
|
|
i = 255. * image.cpu().numpy()
|
|
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
|
|
metadata = None
|
|
if not args.disable_metadata:
|
|
metadata = PngInfo()
|
|
if prompt is not None:
|
|
metadata.add_text("prompt", json.dumps(prompt))
|
|
if extra_pnginfo is not None:
|
|
for x in extra_pnginfo:
|
|
metadata.add_text(x, json.dumps(extra_pnginfo[x]))
|
|
|
|
file = f"{filename}_{counter:05}_.png"
|
|
img.save(os.path.join(full_output_folder, file), pnginfo=metadata, compress_level=self.compress_level)
|
|
data = {
|
|
"lastimage":str(os.path.join(full_output_folder, file)),
|
|
"done":"y"
|
|
}
|
|
json_object = json.dumps(data, indent=4)
|
|
savepath = folder_paths.get_folder_paths("custom_nodes")[0]+"/LCM_Inpaint-Outpaint_Comfy/puzzle/lastimage.json"
|
|
savepath = Path(savepath)
|
|
with open(savepath, "w") as outfile:
|
|
print(savepath)
|
|
outfile.write(json_object)
|
|
results.append({
|
|
"filename": file,
|
|
"subfolder": subfolder,
|
|
"type": self.type
|
|
})
|
|
counter += 1
|
|
|
|
return { "ui": { "images": results } }
|
|
|
|
class SaveImage_PuzzleV2:
|
|
def __init__(self):
|
|
self.output_dir = folder_paths.get_output_directory()
|
|
self.type = "output"
|
|
self.prefix_append = ""
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {"required":
|
|
{"images": ("IMAGE", ),
|
|
"filename_prefix": ("STRING", {"default": "ComfyUI"})},
|
|
"hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"},
|
|
}
|
|
|
|
RETURN_TYPES = ()
|
|
FUNCTION = "save_images"
|
|
|
|
OUTPUT_NODE = True
|
|
|
|
CATEGORY = "image"
|
|
|
|
def save_images(self, images, filename_prefix="ComfyUI", prompt=None, extra_pnginfo=None):
|
|
filename_prefix += self.prefix_append
|
|
full_output_folder, filename, counter, subfolder, filename_prefix = folder_paths.get_save_image_path(filename_prefix, self.output_dir, 512, 512)
|
|
results = list()
|
|
for image in images:
|
|
img = image
|
|
if not args.disable_metadata:
|
|
metadata = PngInfo()
|
|
if prompt is not None:
|
|
metadata.add_text("prompt", json.dumps(prompt))
|
|
if extra_pnginfo is not None:
|
|
for x in extra_pnginfo:
|
|
metadata.add_text(x, json.dumps(extra_pnginfo[x]))
|
|
|
|
file = f"{filename}_{counter:05}_.png"
|
|
img.save(os.path.join(full_output_folder, file), pnginfo=metadata, compress_level=4)
|
|
data = {
|
|
"lastimage":str(os.path.join(full_output_folder, file)),
|
|
"done":"y"
|
|
}
|
|
json_object = json.dumps(data, indent=4)
|
|
savepath = folder_paths.get_folder_paths("custom_nodes")[0]+"/LCM_Inpaint-Outpaint_Comfy/puzzle/lastimage.json"
|
|
savepath = Path(savepath)
|
|
with open(savepath, "w") as outfile:
|
|
print(savepath)
|
|
outfile.write(json_object)
|
|
|
|
|
|
results.append({
|
|
"filename": file,
|
|
"subfolder": subfolder,
|
|
"type": self.type
|
|
})
|
|
counter += 1
|
|
|
|
return { "ui": { "images": results } }
|
|
|
|
class LCMLoraLoader_ipadapter:
|
|
def __init__(self):
|
|
pass
|
|
|
|
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
files = []
|
|
for j in ["/IPAdapter/models","\IPAdapter\models"]:
|
|
try:
|
|
for i in os.listdir(folder_paths.get_folder_paths("controlnet")[0]+j):
|
|
if os.path.isfile(os.path.join(folder_paths.get_folder_paths("controlnet")[0]+j,i)):
|
|
files.append(i)
|
|
except:
|
|
pass
|
|
return {
|
|
"required": {
|
|
"device": (["GPU", "CPU"],),
|
|
"tomesd_value": ("FLOAT", {
|
|
"default": 0.6,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.01,
|
|
}),
|
|
"ip_adapter_model":(files,),
|
|
"reference_only":(["disable","enable"],),
|
|
"ip_adapter":(["disable","enable"],),
|
|
"control_net":(["disable","enable"],),
|
|
"model_name":([i for i in os.listdir(folder_paths.get_folder_paths("diffusers")[0]) if os.path.isdir(folder_paths.get_folder_paths("diffusers")[0]+f"/{i}") or os.path.isdir(folder_paths.get_folder_paths("diffusers")[0]+f"\{i}")],),
|
|
"controlnet_model":([i for i in os.listdir(folder_paths.get_folder_paths("controlnet")[0]) if os.path.isdir(folder_paths.get_folder_paths("controlnet")[0]+f"/{i}") or os.path.isdir(folder_paths.get_folder_paths("controlnet")[0]+f"\{i}")],),
|
|
|
|
}
|
|
}
|
|
RETURN_TYPES = ("class",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self,device,tomesd_value,ip_adapter_model,model_name,reference_only,ip_adapter,controlnet_model,control_net):
|
|
try:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+f"/{model_name}"
|
|
except:
|
|
model_id = folder_paths.get_folder_paths("diffusers")[0]+f"\{model_name}"
|
|
try:
|
|
mpath = folder_paths.get_folder_paths("controlnet")[0]+f"/{controlnet_model}"
|
|
except:
|
|
mpath = folder_paths.get_folder_paths("controlnet")[0]+f"\{controlnet_model}"
|
|
controlnet = ControlNetModel.from_pretrained(mpath)
|
|
|
|
if control_net == "disable":
|
|
if ip_adapter == "enable" and reference_only=="disable":
|
|
pipe = StableDiffusionImg2ImgPipeline.from_pretrained(model_id,safety_checker=None)
|
|
pipe.load_ip_adapter(folder_paths.get_folder_paths("IPAdapter")[0], subfolder="models", weight_name=ip_adapter_model)
|
|
elif reference_only == "disable":
|
|
pipe = StableDiffusionImg2ImgPipeline.from_pretrained(model_id,safety_checker=None)
|
|
else:
|
|
pipe = StableDiffusionImg2ImgPipeline_reference.from_pretrained(model_id,safety_checker=None)
|
|
pipe.load_ip_adapter(folder_paths.get_folder_paths("IPAdapter")[0], subfolder="models", weight_name=ip_adapter_model)
|
|
else:
|
|
if ip_adapter == "enable" and reference_only=="disable":
|
|
pipe = StableDiffusionControlNetImg2ImgPipeline_ipadapter.from_pretrained(model_id,safety_checker=None,controlnet=controlnet)
|
|
pipe.load_ip_adapter(folder_paths.get_folder_paths("IPAdapter")[0], subfolder="models", weight_name=ip_adapter_model)
|
|
elif reference_only == "disable":
|
|
pipe = StableDiffusionControlNetImg2ImgPipeline.from_pretrained(model_id,safety_checker=None,controlnet=controlnet)
|
|
else:
|
|
pipe = StableDiffusionControlNetImg2ImgPipeline_ref.from_pretrained(model_id,safety_checker=None,controlnet=controlnet)
|
|
pipe.load_ip_adapter(folder_paths.get_folder_paths("IPAdapter")[0], subfolder="models", weight_name=ip_adapter_model)
|
|
|
|
|
|
|
|
# set scheduler
|
|
pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
|
|
|
|
# load LCM-LoRA
|
|
try:
|
|
pipe.load_lora_weights(folder_paths.get_folder_paths("loras")[0]+"/pytorch_lora_weights.safetensors")
|
|
except:
|
|
pipe.load_lora_weights(folder_paths.get_folder_paths("loras")[0]+"\pytorch_lora_weights.safetensors")
|
|
pipe.fuse_lora()
|
|
tomesd.apply_patch(pipe, ratio=tomesd_value)
|
|
if device == "GPU":
|
|
pipe.enable_sequential_cpu_offload()
|
|
else:
|
|
pipe.to("cpu")
|
|
return (pipe,)
|
|
|
|
class LCMLora_ipadapter:
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"pipe":("class",),
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
|
"prompt": ("STRING", {"default": '', "multiline": True}),
|
|
"negative_prompt": ("STRING", {"default": '', "multiline": True}),
|
|
"steps": ("INT", {
|
|
"default": 4,
|
|
"min": 0,
|
|
"max": 360,
|
|
"step": 1,
|
|
}),
|
|
|
|
"width": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"height": ("INT", {
|
|
"default": 512,
|
|
"min": 0,
|
|
"max": 5000,
|
|
"step": 64,
|
|
}),
|
|
"cfg": ("FLOAT", {
|
|
"default": 8.0,
|
|
"min": 0,
|
|
"max": 30.0,
|
|
"step": 0.5,
|
|
}),
|
|
"image": ("IMAGE", ),
|
|
"control_image": ("IMAGE", ),
|
|
"reference_image": ("IMAGE", ),
|
|
"ipadapter_image": ("IMAGE", ),
|
|
"style_fidelity": ("FLOAT", {
|
|
"default": 0.5,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.01,
|
|
}),
|
|
"strength": ("FLOAT", {
|
|
"default": 1.0,
|
|
"min": 0.0,
|
|
"max": 1.0,
|
|
"step": 0.01,
|
|
}),
|
|
"batch": ("INT", {
|
|
"default": 1,
|
|
"min": 0,
|
|
"max": 1000,
|
|
"step": 1,
|
|
}),
|
|
"ipadapter_scale":("FLOAT", {
|
|
"default": 0.6,
|
|
"min": 0.0,
|
|
"max": 10.0,
|
|
"step": 0.01,
|
|
}),
|
|
"controlnet_conditioning_scale":("FLOAT", {
|
|
"default": 0.6,
|
|
"min": 0.0,
|
|
"max": 10.0,
|
|
"step": 0.01,
|
|
}),
|
|
"reference_only":(["disable","enable"],),
|
|
"ip_adapter":(["disable","enable"],),
|
|
"control_net":(["disable","enable"],),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE",)
|
|
FUNCTION = "mainfunc"
|
|
|
|
CATEGORY = "LCM_Nodes/nodes"
|
|
|
|
def mainfunc(self, prompt: str,steps: int,width:int,height:int,cfg:float,seed: int,image,pipe,batch,strength,reference_image,style_fidelity,ipadapter_scale,reference_only,ip_adapter,ipadapter_image,negative_prompt,control_image,controlnet_conditioning_scale,control_net):
|
|
if ip_adapter =="enable":
|
|
pipe.set_ip_adapter_scale(ipadapter_scale)
|
|
|
|
img = image[0].numpy()
|
|
img = img*255.0
|
|
image = Image.fromarray(np.uint8(img))
|
|
|
|
img = reference_image[0].numpy()
|
|
img = img*255.0
|
|
reference_image = Image.fromarray(np.uint8(img))
|
|
|
|
|
|
img = control_image[0].numpy()
|
|
img = img*255.0
|
|
control_image = Image.fromarray(np.uint8(img))
|
|
|
|
img = ipadapter_image[0].numpy()
|
|
img = img*255.0
|
|
ipadapter_image = Image.fromarray(np.uint8(img))
|
|
|
|
|
|
|
|
|
|
|
|
res = []
|
|
for m in range(batch):
|
|
if control_net == "disable":
|
|
if ip_adapter == "enable" and reference_only=="disable":
|
|
images = pipe(prompt,negative_prompt=negative_prompt,width=width,height=height, image=image, num_inference_steps=steps, strength=strength, guidance_scale=cfg,ip_adapter_image = ipadapter_image).images
|
|
elif reference_only == "disable":
|
|
images = pipe(prompt,negative_prompt=negative_prompt,width=width,height=height, image=image, num_inference_steps=steps, strength=strength, guidance_scale=cfg).images
|
|
elif reference_only=="enable" and ip_adapter == "disable":
|
|
images = pipe(prompt,negative_prompt=negative_prompt,width=width,height=height, image=image, num_inference_steps=steps, strength=strength, guidance_scale=cfg,ref_image=reference_image,style_fidelity=style_fidelity).images
|
|
else:
|
|
images = pipe(prompt,negative_prompt=negative_prompt,width=width,height=height, image=image, num_inference_steps=steps, strength=strength, guidance_scale=cfg,ip_adapter_image = ipadapter_image,ref_image=reference_image,style_fidelity=style_fidelity).images
|
|
else:
|
|
if ip_adapter == "enable" and reference_only=="disable":
|
|
images = pipe(prompt,negative_prompt=negative_prompt,width=width,height=height, image=image, num_inference_steps=steps, strength=strength, guidance_scale=cfg,ip_adapter_image = ipadapter_image,controlnet_conditioning_scale=controlnet_conditioning_scale,control_image=control_image).images
|
|
elif reference_only == "disable":
|
|
images = pipe(prompt,negative_prompt=negative_prompt,width=width,height=height, image=image, num_inference_steps=steps, strength=strength, guidance_scale=cfg,controlnet_conditioning_scale=controlnet_conditioning_scale,control_image=control_image).images
|
|
elif reference_only=="enable" and ip_adapter == "disable":
|
|
images = pipe(prompt,negative_prompt=negative_prompt,width=width,height=height, image=image, num_inference_steps=steps, strength=strength, guidance_scale=cfg,ref_image=reference_image,style_fidelity=style_fidelity,control_image=control_image,controlnet_conditioning_scale=controlnet_conditioning_scale).images
|
|
else:
|
|
images = pipe(prompt,negative_prompt=negative_prompt,width=width,height=height, image=image, num_inference_steps=steps, strength=strength, guidance_scale=cfg,ip_adapter_image = ipadapter_image,ref_image=reference_image,style_fidelity=style_fidelity,controlnet_conditioning_scale=controlnet_conditioning_scale,control_image=control_image).images
|
|
|
|
|
|
res.append(images[0])
|
|
|
|
return (res,)
|
|
|
|
NODE_CLASS_MAPPINGS = {
|
|
"LCMGenerate": LCMGenerate,
|
|
"LoadImageNode_LCM":LoadImageNode_LCM,
|
|
"SaveImage_LCM":SaveImage_LCM,
|
|
"LCM_outpaint_prep":LCM_outpaint_prep,
|
|
"LCMLoader":LCMLoader,
|
|
"LCMLoader_img2img":LCMLoader_img2img,
|
|
"LCMGenerate_img2img": LCMGenerate_img2img,
|
|
"FreeU_LCM":FreeU_LCM,
|
|
"LCMGenerate_ReferenceOnly":LCMGenerate_ReferenceOnly,
|
|
"LCMLoader_ReferenceOnly": LCMLoader_ReferenceOnly,
|
|
"LCMLoader_RefInpaint":LCMLoader_RefInpaint,
|
|
"ImageOutputToComfyNodes":ImageOutputToComfyNodes,
|
|
"ImageShuffle":ImageShuffle,
|
|
"LCMT2IAdapter":LCMT2IAdapter,
|
|
"LCMLoader_controlnet":LCMLoader_controlnet,
|
|
"LCMGenerate_img2img_controlnet":LCMGenerate_img2img_controlnet,
|
|
"LCM_IPAdapter":LCM_IPAdapter,
|
|
"LCMGenerate_img2img_IPAdapter":LCMGenerate_img2img_IPAdapter,
|
|
"LCMGenerate_inpaintv2":LCMGenerate_inpaintv2,
|
|
"LCMLoader_controlnet_inpaint":LCMLoader_controlnet_inpaint,
|
|
"LCM_IPAdapter_inpaint":LCM_IPAdapter_inpaint,
|
|
"LCMGenerate_inpaintv3":LCMGenerate_inpaintv3,
|
|
"OutpaintCanvasTool":OutpaintCanvasTool,
|
|
"stitch":stitch,
|
|
"LCMLora_inpaint":LCMLora_inpaint,
|
|
"LCMLoraLoader_inpaint":LCMLoraLoader_inpaint,
|
|
"LCMLoader_SDTurbo":LCMLoader_SDTurbo,
|
|
"LCMGenerate_SDTurbo":LCMGenerate_SDTurbo,
|
|
"Loader_SegmindVega":Loader_SegmindVega,
|
|
"SegmindVega":SegmindVega,
|
|
"SaveImage_Puzzle":SaveImage_Puzzle,
|
|
"SaveImage_PuzzleV2":SaveImage_PuzzleV2,
|
|
"ImageSwitch":ImageSwitch,
|
|
"SettingsSwitch":SettingsSwitch,
|
|
"FloatNumber":FloatNumber,
|
|
"LCMLora_ipadapter":LCMLora_ipadapter,
|
|
"LCMLoraLoader_ipadapter":LCMLoraLoader_ipadapter,
|
|
}
|