419 lines
17 KiB
Python
419 lines
17 KiB
Python
import math, cv2, random, torch, torchvision
|
|
import numpy as np
|
|
import nodes, folder_paths, comfy
|
|
from . import wildcards
|
|
|
|
|
|
class abyz22_ImpactWildcardEncode:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"model": ("MODEL",),
|
|
"clip": ("CLIP",),
|
|
"batch_size": ("INT", {"default": 1, "min": 1, "max": 0xFFFFFFFFFFFFFFFF}),
|
|
"wildcard_text": ("STRING", {"multiline": True, "dynamicPrompts": False}),
|
|
"mode": ("BOOLEAN", {"default": True, "label_on": "Populate", "label_off": "Fixed"}),
|
|
"Select to add LoRA": (["Select the LoRA to add to the text"] + folder_paths.get_filename_list("loras"),),
|
|
"Select to add Wildcard": (["Select the Wildcard to add to the text"],),
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xFFFFFFFFFFFFFFFF}),
|
|
},
|
|
}
|
|
|
|
CATEGORY = "abyz22"
|
|
|
|
RETURN_TYPES = ("MODEL", "CLIP", "CONDITIONINGS", "STRING")
|
|
RETURN_NAMES = ("model", "clip", "conditionings", "populated_text")
|
|
FUNCTION = "doit"
|
|
|
|
@staticmethod
|
|
def process_with_loras(**kwargs):
|
|
return wildcards.process_with_loras(**kwargs)
|
|
|
|
@staticmethod
|
|
def get_wildcard_list(): # 이건 사용 안함 (왜있는지 모름)
|
|
return wildcards.get_wildcard_list()
|
|
|
|
def doit(self, *args, **kwargs):
|
|
wildcard_process = nodes.NODE_CLASS_MAPPINGS["ImpactWildcardProcessor"].process
|
|
|
|
conditioning = []
|
|
for i in range(kwargs["batch_size"]):
|
|
populated = wildcard_process(text=kwargs["wildcard_text"], seed=kwargs["seed"] + i)
|
|
# model, clip, conditioning = wildcards.process_with_loras(populated, kwargs["model"], kwargs["clip"])
|
|
model, clip, con = wildcards.process_with_loras(populated, kwargs["model"], kwargs["clip"])
|
|
conditioning.append(con[0])
|
|
conditionings = [conditioning[i : i + 1] for i in range(len(conditioning))] # 앞에 차원 1추가한뒤 쌓기
|
|
# print("x" * 30)
|
|
|
|
# conditioning = conds[0]
|
|
# conditioning[0][0] = torch.cat((conditioning[0][0]), conds[0], 0)
|
|
# model, clip, conditioning = wildcards.process_with_loras(populated, kwargs["model"], kwargs["clip"])
|
|
# print("len conditioning ", len(conditioning)) # 1
|
|
# print("len conditioning[0] ", len(conditioning[0])) # 2 ('pooled_output이 섞여있음)
|
|
# print("len conditioning[0][0] ", len(conditioning[0][0]))
|
|
# print("shape conditioning[0][0] ", conditioning[0][0].shape) # 1, 77, 768
|
|
# print(conditioning[0])
|
|
|
|
return (model, clip, conditionings, populated)
|
|
|
|
|
|
class abyz22_KSampler:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"model": ("MODEL",),
|
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xFFFFFFFFFFFFFFFF}),
|
|
"steps": ("INT", {"default": 20, "min": 1, "max": 10000}),
|
|
"cfg": ("FLOAT", {"default": 7.0, "min": 0.0, "max": 100.0}),
|
|
"sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
|
|
"scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
|
|
"positives": ("CONDITIONINGS",),
|
|
"negative": ("CONDITIONING",),
|
|
"latent_image": ("LATENT",),
|
|
"denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
|
"vae_decode": (["true", "true (tiled)", "false"],),
|
|
},
|
|
"optional": {
|
|
"optional_vae": ("VAE",),
|
|
"script": ("SCRIPT",),
|
|
},
|
|
"hidden": {
|
|
"prompt": "PROMPT",
|
|
"extra_pnginfo": "EXTRA_PNGINFO",
|
|
"my_unique_id": "UNIQUE_ID",
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = (
|
|
"MODEL",
|
|
"CONDITIONINGS",
|
|
"CONDITIONING",
|
|
"LATENT",
|
|
"VAE",
|
|
"IMAGE",
|
|
)
|
|
RETURN_NAMES = (
|
|
"MODEL",
|
|
"CONDITIONINGS+",
|
|
"CONDITIONING-",
|
|
"LATENT",
|
|
"VAE",
|
|
"IMAGE",
|
|
)
|
|
FUNCTION = "doit"
|
|
CATEGORY = "abyz22"
|
|
|
|
def doit(self, *args, **kwargs):
|
|
pos=kwargs["positives"]
|
|
ksample_latents = {}
|
|
|
|
obj = nodes.NODE_CLASS_MAPPINGS["KSampler"]()
|
|
for i, positive in enumerate(kwargs["positives"]):
|
|
kwargs["latent_image"]["samples"] = kwargs["latent_image"]["samples"][0:1, :, :, :]
|
|
ksampler_result = obj.sample(
|
|
model=kwargs["model"],
|
|
seed=kwargs["seed"] + i,
|
|
steps=kwargs["steps"],
|
|
cfg=kwargs["cfg"],
|
|
sampler_name=kwargs["sampler_name"],
|
|
scheduler=kwargs["scheduler"],
|
|
positive=positive,
|
|
negative=kwargs["negative"],
|
|
latent_image=kwargs["latent_image"],
|
|
denoise=kwargs["denoise"],
|
|
)
|
|
ksample_latent = ksampler_result[0]
|
|
if i == 0:
|
|
ksample_latents["samples"] = ksample_latent["samples"]
|
|
if i > 0:
|
|
ksample_latents["samples"] = torch.cat((ksample_latents["samples"], ksample_latent["samples"]), 0)
|
|
|
|
obj2 = nodes.NODE_CLASS_MAPPINGS["VAEDecode"]()
|
|
images = obj2.decode(kwargs["optional_vae"], ksample_latents)[0]
|
|
|
|
return (kwargs["model"], kwargs["positives"], kwargs["negative"], kwargs["latent_image"], kwargs["optional_vae"], images)
|
|
|
|
|
|
class Pad_Image_v2:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"image": ("IMAGE",),
|
|
"conditionings": ("CONDITIONINGS",),
|
|
"vae": ("VAE",),
|
|
"control_net_name": (folder_paths.get_filename_list("controlnet"),),
|
|
"pose_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01, "round": 0.001, "dispaly": "slider"}),
|
|
"pad_mode": (["constant", "replicate", "noise"],),
|
|
"mode_type": (
|
|
[
|
|
"Top-Left",
|
|
"Top",
|
|
"Top-Right",
|
|
"Center-Left",
|
|
"Center",
|
|
"Center-Right",
|
|
"Bottom-Left",
|
|
"Bottom",
|
|
"Bottom-Right",
|
|
"Random",
|
|
],
|
|
),
|
|
"Ratio_min": ("FLOAT", {"default": 0.5, "min": 0.3, "max": 2.5, "step": 0.1, "round": 0.01, "dispaly": "slider"}),
|
|
"Ratio_max": ("FLOAT", {"default": 1.5, "min": 0.3, "max": 2.5, "step": 0.1, "round": 0.01, "dispaly": "slider"}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = (
|
|
"IMAGE",
|
|
"IMAGE",
|
|
"CONDITIONINGS",
|
|
"LATENT",
|
|
)
|
|
RETURN_NAMES = (
|
|
"image",
|
|
"pose_image",
|
|
"conditionings",
|
|
"latent",
|
|
)
|
|
|
|
FUNCTION = "doit"
|
|
|
|
CATEGORY = "abyz22"
|
|
|
|
def doit(self, *args, **kwargs):
|
|
image, vae, control_net_name, pose_strength, mode_type, Ratio_min, Ratio_max, pad_mode = (
|
|
kwargs["image"],
|
|
kwargs["vae"],
|
|
kwargs["control_net_name"],
|
|
kwargs["pose_strength"],
|
|
kwargs["mode_type"],
|
|
kwargs["Ratio_min"],
|
|
kwargs["Ratio_max"],
|
|
kwargs["pad_mode"],
|
|
)
|
|
# image= 1,768,512,3
|
|
if Ratio_min > Ratio_max:
|
|
Ratio_min, Ratio_max = Ratio_max, Ratio_min
|
|
obj = nodes.NODE_CLASS_MAPPINGS["DWPreprocessor"]()
|
|
|
|
def normalize_size_base_64(w, h):
|
|
short_side = min(w, h)
|
|
remainder = short_side % 64
|
|
return short_side - remainder + (64 if remainder > 0 else 0)
|
|
|
|
resolution = normalize_size_base_64(image.shape[2], image.shape[1])
|
|
pose_image = obj.estimate_pose(
|
|
image, "disable", "enable", "disable", resolution=resolution, bbox_detector="yolox_s.onnx", pose_estimator="dw-ss_ucoco.onnx"
|
|
)["result"][0]
|
|
|
|
# Resize_by = random.uniform(Ratio_min, Ratio_max)
|
|
Resize_bys = np.random.uniform(Ratio_min, Ratio_max, image.shape[0]).round(2)
|
|
for i, Resize_by in enumerate(Resize_bys):
|
|
if Resize_by > 0.9999 and Resize_by < 1.0001:
|
|
padded_image = image[i].unsqueeze(0)
|
|
padded_pose_image = pose_image[i].unsqueeze(0)
|
|
else:
|
|
x, y = int(image.shape[2] * Resize_by), int(image.shape[1] * Resize_by)
|
|
resized_image = torchvision.transforms.Resize((y, x))(image[i].permute(2, 0, 1)) # 768,512,3 -> 3,768,512
|
|
resized_pose_image = torchvision.transforms.Resize((y, x), interpolation=torchvision.transforms.InterpolationMode.NEAREST)(
|
|
pose_image[i].permute(2, 0, 1)
|
|
) # 1,3,768,512
|
|
|
|
# image = n,768,512,3
|
|
# resized_image = 3,768,512
|
|
dx, dy = abs(image.shape[2] - resized_image.shape[2]), abs(image.shape[1] - resized_image.shape[1])
|
|
rdx, rdy = random.randint(0, dx), random.randint(0, dy)
|
|
if Resize_by < 1:
|
|
mode_list = {
|
|
"Top-Left": (0, dx, 0, dy),
|
|
"Top": (int(round(dx / 2)), int(round(dx / 2)) + 1, 0, dy),
|
|
"Top-Right": (dx, 0, 0, dy),
|
|
"Center-Left": (0, dx, round(int(dy / 2)), int(round(dy / 2))),
|
|
"Center": (int(round(dx / 2)), int(round(dx / 2)), int(round(dy / 2)), int(round(dy / 2))),
|
|
"Center-Right": (dx, 0, int(round(dy / 2)), int(round(dy / 2))),
|
|
"Bottom-Left": (0, dx, dy, 0),
|
|
"Bottom": (int(round(dx / 2)), int(round(dx / 2)), dy, 0),
|
|
"Bottom-Right": (dx, 0, dy, 0),
|
|
"Random": (rdx, dx - rdx, rdy, dy - rdy),
|
|
}
|
|
padded_image = torch.rand_like(image[i].permute(2, 0, 1)) # 3, 768, 512
|
|
padded_pose_image = torch.zeros_like(pose_image[i].permute(2, 0, 1))
|
|
|
|
if pad_mode == "noise":
|
|
padded_image[
|
|
:,
|
|
mode_list[mode_type][2] : mode_list[mode_type][2] + resized_image.shape[1],
|
|
mode_list[mode_type][0] : mode_list[mode_type][0] + resized_image.shape[2],
|
|
] = resized_image
|
|
padded_image = padded_image.permute(1, 2, 0).unsqueeze(0) # 원상복구 768,512,3 후 1,768,512,3
|
|
padded_pose_image[
|
|
:,
|
|
mode_list[mode_type][2] : mode_list[mode_type][2] + resized_image.shape[1],
|
|
mode_list[mode_type][0] : mode_list[mode_type][0] + resized_image.shape[2],
|
|
] = resized_pose_image
|
|
padded_pose_image = padded_pose_image.permute(1, 2, 0).unsqueeze(0)
|
|
else:
|
|
padded_image = torch.nn.functional.pad(resized_image, (mode_list[mode_type]), mode=pad_mode).permute(1, 2, 0).unsqueeze(0)
|
|
padded_pose_image = (
|
|
torch.nn.functional.pad(resized_pose_image, (mode_list[mode_type]), mode=pad_mode).permute(1, 2, 0).unsqueeze(0)
|
|
)
|
|
elif Resize_by > 1:
|
|
o_h, o_w = image.shape[1], image.shape[2]
|
|
r_h, r_w = resized_image.shape[1], resized_image.shape[2]
|
|
mode_list = {
|
|
"Top-Left": (0, o_w, 0, o_h),
|
|
"Top": (int(round(dx / 2)), o_w + int(round(dx / 2)), 0, o_h),
|
|
"Top-Right": (dx, r_w, 0, o_h),
|
|
"Center-Left": (0, o_w, int(round(dy / 2)), o_h + int(round(dy / 2))),
|
|
"Center": (int(round(dx / 2)), o_w + int(round(dx / 2)), int(round(dy / 2)), o_h + int(round(dy / 2))),
|
|
"Center-Right": (dx, r_w, int(round(dy / 2)), o_h + int(round(dy / 2))),
|
|
"Bottom-Left": (0, o_w, dy, r_h),
|
|
"Bottom": (int(round(dx / 2)), o_w + int(round(dx / 2)), dy, r_h),
|
|
"Bottom-Right": (dx, r_w, dy, r_h),
|
|
"Random": (rdx, o_w + rdx, rdy, o_h + rdy),
|
|
}
|
|
padded_image = torch.rand_like(image[0].permute(2, 0, 1)) # 3,768,512
|
|
padded_pose_image = torch.zeros_like(pose_image[0].permute(2, 0, 1))
|
|
|
|
padded_image = resized_image[
|
|
:,
|
|
mode_list[mode_type][2] : mode_list[mode_type][3],
|
|
mode_list[mode_type][0] : mode_list[mode_type][1],
|
|
]
|
|
padded_pose_image = resized_pose_image[
|
|
:,
|
|
mode_list[mode_type][2] : mode_list[mode_type][3],
|
|
mode_list[mode_type][0] : mode_list[mode_type][1],
|
|
]
|
|
padded_image = padded_image.permute(1, 2, 0).unsqueeze(0)
|
|
padded_pose_image = padded_pose_image.permute(1, 2, 0).unsqueeze(0)
|
|
|
|
if i == 0:
|
|
final_image = padded_image
|
|
final_pose_image = padded_pose_image
|
|
else:
|
|
final_image = torch.cat((final_image, padded_image))
|
|
final_pose_image = torch.cat((final_pose_image, padded_pose_image))
|
|
|
|
|
|
latent = nodes.VAEEncode().encode(vae, final_image)[0]
|
|
##############################
|
|
|
|
same_count = 1
|
|
positives = []
|
|
|
|
# opt1
|
|
print('☆★'*20)
|
|
print('☆★'*20)
|
|
for i, positive in enumerate(kwargs["conditionings"]):
|
|
if i < len(kwargs["conditionings"]) - 1:
|
|
if np.array_equal(
|
|
positive[0][0].cpu().detach().numpy(), kwargs["conditionings"][i + 1][0][0].cpu().detach().numpy()
|
|
) and np.array_equal(
|
|
positive[0][1]["pooled_output"].cpu().detach().numpy(),
|
|
kwargs["conditionings"][i + 1][0][1]["pooled_output"].cpu().detach().numpy(),
|
|
): # 현재거랑 다음거랑 같으면
|
|
same_count += 1
|
|
continue
|
|
ctrl_net_load = nodes.ControlNetLoader().load_controlnet(control_net_name)[0]
|
|
positive = nodes.ControlNetApply().apply_controlnet(positive, ctrl_net_load, final_pose_image[i, i + same_count], pose_strength)[0]
|
|
print(i)
|
|
print(positive[0][1]['control'])
|
|
|
|
for ii in range(same_count):
|
|
positives.append(positive)
|
|
same_count = 1
|
|
print('☆★'*20)
|
|
print('☆★'*20)
|
|
|
|
#opt2
|
|
# ctrl_net_load = nodes.ControlNetLoader().load_controlnet(control_net_name)[0]
|
|
# positives = nodes.ControlNetApply().apply_controlnet(kwargs["conditionings"][0], ctrl_net_load, final_pose_image, pose_strength)[0]
|
|
# positives=[positives]
|
|
|
|
# print(len(positives))
|
|
# print(len(positives[0]))
|
|
# print(len(positives[0][0]))
|
|
# print(len(positives[0][0][0]))
|
|
# print(positives[0][0][0].shape)
|
|
|
|
return (
|
|
final_image,
|
|
final_pose_image,
|
|
positives,
|
|
latent,
|
|
)
|
|
|
|
|
|
class abyz22_ToBasicPipe:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"model": ("MODEL",),
|
|
"clip": ("CLIP",),
|
|
"vae": ("VAE",),
|
|
"positives": ("CONDITIONINGS",),
|
|
"negative": ("CONDITIONING",),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("BASIC_PIPE",)
|
|
RETURN_NAMES = ("basic_pipe",)
|
|
FUNCTION = "doit"
|
|
|
|
CATEGORY = "abyz22"
|
|
|
|
def doit(self, model, clip, vae, positives, negative):
|
|
pipe = (model, clip, vae, positives, negative)
|
|
return (pipe,)
|
|
|
|
|
|
class abyz22_FromBasicPipe_v2:
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
return {
|
|
"required": {
|
|
"basic_pipe": ("BASIC_PIPE",),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("BASIC_PIPE", "MODEL", "CLIP", "VAE", "CONDITIONINGS", "CONDITIONING")
|
|
RETURN_NAMES = ("basic_pipe", "model", "clip", "vae", "positives", "negative")
|
|
FUNCTION = "doit"
|
|
CATEGORY = "abyz22"
|
|
|
|
def doit(self, basic_pipe):
|
|
model, clip, vae, positives, negative = basic_pipe
|
|
return basic_pipe, model, clip, vae, positives, negative
|
|
|
|
|
|
# class abyz22_Ultimate_SD_Upscale:
|
|
# @classmethod
|
|
# def INPUT_TYPES(cls):
|
|
# return {}
|
|
# RETURN_TYPES = ()
|
|
# RETURN_NAMES=()
|
|
|
|
# FUNCTION = "doit"
|
|
# CATEGORY = "abyz22"
|
|
|
|
# def doit(self, *args, **kwargs):
|
|
# return None
|
|
|
|
# class abyz22_DetailerDebug_Segs:
|
|
# @classmethod
|
|
# def INPUT_TYPES(cls):
|
|
# return {}
|
|
# RETURN_TYPES = ()
|
|
# RETURN_NAMES=()
|
|
|
|
# FUNCTION = "doit"
|
|
# CATEGORY = "abyz22"
|
|
|
|
# def doit(self, *args, **kwargs):
|
|
# return None
|