fixed padding + refactoring
This commit is contained in:
+2
-7
@@ -299,9 +299,6 @@ def interpolate_prompt_series(animation_prompts, max_frames, start_frame, pre_te
|
||||
# if it is an in-between frame and the prompts differ, composable diffusion will be performed.
|
||||
return (cur_prompt_series, nxt_prompt_series, weight_series)
|
||||
|
||||
def encode_and_pad(cur_prompt_series, nxt_prompt_series,clip):
|
||||
|
||||
return clip
|
||||
def BatchPoolAnimConditioning(cur_prompt_series, nxt_prompt_series, weight_series, clip):
|
||||
pooled_out = []
|
||||
cond_out = []
|
||||
@@ -310,8 +307,7 @@ def BatchPoolAnimConditioning(cur_prompt_series, nxt_prompt_series, weight_serie
|
||||
for i in range(len(cur_prompt_series)):
|
||||
tokens = clip.tokenize(str(cur_prompt_series[i]))
|
||||
cond_to, pooled_to = clip.encode_from_tokens(tokens, return_pooled=True)
|
||||
tensor_size = cond_to.shape[1]
|
||||
max_size = max(max_size, tensor_size)
|
||||
max_size = max(max_size, cond_to.shape[1])
|
||||
for i in range(len(cur_prompt_series)):
|
||||
tokens = clip.tokenize(str(cur_prompt_series[i]))
|
||||
cond_to, pooled_to = clip.encode_from_tokens(tokens, return_pooled=True)
|
||||
@@ -335,10 +331,8 @@ def BatchPoolAnimConditioning(cur_prompt_series, nxt_prompt_series, weight_serie
|
||||
final_pooled_output = torch.cat(pooled_out, dim=0)
|
||||
final_conditioning = torch.cat(cond_out, dim=0)
|
||||
|
||||
|
||||
return [[final_conditioning, {"pooled_output": final_pooled_output}]]
|
||||
|
||||
|
||||
def BatchGLIGENConditioning(cur_prompt_series, nxt_prompt_series, weight_series, clip):
|
||||
pooled_out = []
|
||||
cond_out = []
|
||||
@@ -349,6 +343,7 @@ def BatchGLIGENConditioning(cur_prompt_series, nxt_prompt_series, weight_series,
|
||||
cond_to, pooled_to = clip.encode_from_tokens(tokens, return_pooled=True)
|
||||
tensor_size = cond_to.shape[1]
|
||||
max_size = max(max_size, tensor_size)
|
||||
|
||||
for i in range(len(cur_prompt_series)):
|
||||
tokens = clip.tokenize(str(cur_prompt_series[i]))
|
||||
cond_to, pooled_to = clip.encode_from_tokens(tokens, return_pooled=True)
|
||||
|
||||
+29
-325
@@ -3,6 +3,7 @@
|
||||
|
||||
import numexpr
|
||||
import torch
|
||||
import torch.nn.functional as F
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import re
|
||||
@@ -63,7 +64,7 @@ class ScheduleSettings:
|
||||
self.sync_context_to_pe = sync_option
|
||||
|
||||
#Addweighted function from Comfyui
|
||||
def addWeighted(conditioning_to, conditioning_from, conditioning_to_strength, max_size = 0):
|
||||
def addWeighted(conditioning_to, conditioning_from, conditioning_to_strength, max_size=0):
|
||||
out = []
|
||||
|
||||
if len(conditioning_from) > 1:
|
||||
@@ -77,87 +78,53 @@ def addWeighted(conditioning_to, conditioning_from, conditioning_to_strength, ma
|
||||
pooled_output_to = conditioning_to[i][1].get("pooled_output", pooled_output_from)
|
||||
if max_size == 0:
|
||||
max_size = max(t1.shape[1], cond_from.shape[1])
|
||||
t0 = pad_with_zeros(cond_from, max_size)
|
||||
t1 = pad_with_zeros(t1, max_size)
|
||||
t0, max_size = pad_with_zeros(cond_from, max_size)
|
||||
t1, max_size = pad_with_zeros(t1, t0.shape[1]) # Padding t1 to match max_size
|
||||
t0, max_size = pad_with_zeros(t0, t1.shape[1])
|
||||
|
||||
tw = torch.mul(t1, conditioning_to_strength) + torch.mul(t0, (1.0 - conditioning_to_strength))
|
||||
t_to = conditioning_to[i][1].copy()
|
||||
|
||||
t_to["pooled_output"] = pooled_output_from
|
||||
|
||||
if pooled_output_from is not None and pooled_output_to is not None:
|
||||
# Pad pooled outputs if available
|
||||
pooled_output_to = pad_with_zeros(pooled_output_to, max_size)
|
||||
pooled_output_from = pad_with_zeros(pooled_output_from, max_size)
|
||||
t_to["pooled_output"] = torch.mul(pooled_output_to, conditioning_to_strength) + torch.mul(pooled_output_from, (1.0 - conditioning_to_strength))
|
||||
elif pooled_output_from is not None:
|
||||
t_to["pooled_output"] = pooled_output_from
|
||||
|
||||
n = [tw, t_to]
|
||||
out.append(n)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def pad_with_zeros(tensor, target_length):
|
||||
current_length = tensor.shape[1]
|
||||
|
||||
if current_length < target_length:
|
||||
# Calculate the required padding length
|
||||
pad_length = target_length - current_length
|
||||
|
||||
# Calculate padding on both sides to maintain the tensor's original shape
|
||||
left_pad = pad_length // 2
|
||||
right_pad = pad_length - left_pad
|
||||
|
||||
# Pad the tensor along the second dimension
|
||||
tensor = F.pad(tensor, (0, 0, left_pad, right_pad))
|
||||
|
||||
return tensor, target_length
|
||||
|
||||
def process_input_text(text: str) -> dict:
|
||||
input_text = "{" + text + "}"
|
||||
input_text = re.sub(r',\s*}', '}', input_text)
|
||||
animation_prompts = json.loads(input_text.strip())
|
||||
return animation_prompts
|
||||
|
||||
def pad_with_zeros(tensor, target_length):
|
||||
current_length = tensor.shape[1]
|
||||
if current_length < target_length:
|
||||
padding = torch.zeros(tensor.shape[0], target_length - current_length, tensor.shape[2]).to(tensor.device)
|
||||
tensor = torch.cat([tensor, padding], dim=1)
|
||||
return tensor
|
||||
#def pad_with_zeros(tensor, target_length):
|
||||
# current_length = tensor.shape[1]
|
||||
# if current_length < target_length:
|
||||
# padding = torch.zeros(tensor.shape[0], target_length - current_length, tensor.shape[2]).to(tensor.device)
|
||||
# tensor = torch.cat([tensor, padding], dim=1)
|
||||
# return tensor
|
||||
|
||||
def check_is_number(value):
|
||||
float_pattern = r'^(?=.)([+-]?([0-9]*)(\.([0-9]+))?)$'
|
||||
return re.match(float_pattern, value)
|
||||
|
||||
def split_weighted_subprompts(text, frame=0, pre_text='', app_text=''):
|
||||
pre_text = str(pre_text)
|
||||
app_text = str(app_text)
|
||||
|
||||
if "--neg" in pre_text:
|
||||
pre_pos, pre_neg = pre_text.split("--neg")
|
||||
else:
|
||||
pre_pos, pre_neg = pre_text, ""
|
||||
|
||||
if "--neg" in app_text:
|
||||
app_pos, app_neg = app_text.split("--neg")
|
||||
else:
|
||||
app_pos, app_neg = app_text, ""
|
||||
|
||||
# Check if the text is a string; if not, convert it to a string
|
||||
if not isinstance(text, str):
|
||||
text = str(text)
|
||||
|
||||
math_parser = re.compile("(?P<weight>(`[\S\s]*?`))", re.VERBOSE)
|
||||
|
||||
parsed_prompt = re.sub(math_parser, lambda m: str(parse_weight(m, frame)), text)
|
||||
|
||||
negative_prompts = ""
|
||||
positive_prompts = ""
|
||||
|
||||
# Check if the last character is '0' and remove it
|
||||
prompt_split = parsed_prompt.split("--neg")
|
||||
if len(prompt_split) > 1:
|
||||
positive_prompts, negative_prompts = prompt_split[0], prompt_split[1]
|
||||
else:
|
||||
positive_prompts = prompt_split[0]
|
||||
|
||||
pos = {}
|
||||
neg = {}
|
||||
pos[frame] = (str(pre_pos) + " " + str(positive_prompts) + " " + str(app_pos))
|
||||
neg[frame] = (str(pre_neg) + " " + str(negative_prompts) + " " + str(app_neg))
|
||||
if pos[frame].endswith('0'):
|
||||
pos[frame] = pos[frame][:-1]
|
||||
if neg[frame].endswith('0'):
|
||||
neg[frame] = neg[frame][:-1]
|
||||
|
||||
return pos, neg
|
||||
|
||||
def parse_weight(match, frame=0, max_frames=0) -> float: #calculate weight steps for in-betweens
|
||||
w_raw = match.group("weight")
|
||||
max_f = max_frames # this line has to be left intact as it's in use by numexpr even though it looks like it doesn't
|
||||
@@ -172,91 +139,6 @@ def parse_weight(match, frame=0, max_frames=0) -> float: #calculate weight steps
|
||||
return 1
|
||||
return float(numexpr.evaluate(w_raw[1:-1]))
|
||||
|
||||
def prepare_prompt(prompt_series, max_frames, frame_idx, prompt_weight_1 = 0, prompt_weight_2 = 0, prompt_weight_3 = 0, prompt_weight_4 = 0): #calculate expressions from the text input and return a string
|
||||
max_f = max_frames - 1
|
||||
pattern = r'`.*?`' #set so the expression will be read between two backticks (``)
|
||||
regex = re.compile(pattern)
|
||||
prompt_parsed = str(prompt_series)
|
||||
for match in regex.finditer(prompt_parsed):
|
||||
matched_string = match.group(0)
|
||||
parsed_string = matched_string.replace('t', f'{frame_idx}').replace("pw_a", f"prompt_weight_1").replace("pw_b", f"prompt_weight_2").replace("pw_c", f"prompt_weight_3").replace("pw_d", f"prompt_weight_4").replace("max_f", f"{max_f}").replace('`', '') #replace t, max_f and `` respectively
|
||||
parsed_value = numexpr.evaluate(parsed_string)
|
||||
prompt_parsed = prompt_parsed.replace(matched_string, str(parsed_value))
|
||||
return prompt_parsed.strip()
|
||||
|
||||
def interpolate_string(animation_prompts, max_frames, current_frame, pre_text, app_text, prompt_weight_1,
|
||||
prompt_weight_2, prompt_weight_3,
|
||||
prompt_weight_4): # parse the conditioning strength and determine in-betweens.
|
||||
# Get prompts sorted by keyframe
|
||||
max_f = max_frames # needed for numexpr even though it doesn't look like it's in use.
|
||||
parsed_animation_prompts = {}
|
||||
for key, value in animation_prompts.items():
|
||||
if check_is_number(key): # default case 0:(1 + t %5), 30:(5-t%2)
|
||||
parsed_animation_prompts[key] = value
|
||||
else: # math on the left hand side case 0:(1 + t %5), maxKeyframes/2:(5-t%2)
|
||||
parsed_animation_prompts[int(numexpr.evaluate(key))] = value
|
||||
|
||||
sorted_prompts = sorted(parsed_animation_prompts.items(), key=lambda item: int(item[0]))
|
||||
|
||||
# Setup containers for interpolated prompts
|
||||
cur_prompt_series = pd.Series([np.nan for a in range(max_frames)])
|
||||
|
||||
# simple array for strength values
|
||||
weight_series = [np.nan] * max_frames
|
||||
|
||||
# in case there is only one keyed promt, set all prompts to that prompt
|
||||
if len(sorted_prompts) - 1 == 0:
|
||||
for i in range(0, len(cur_prompt_series) - 1):
|
||||
current_prompt = sorted_prompts[0][1]
|
||||
cur_prompt_series[i] = str(pre_text) + " " + str(current_prompt) + " " + str(app_text)
|
||||
|
||||
# Initialized outside of loop for nan check
|
||||
current_key = 0
|
||||
next_key = 0
|
||||
|
||||
# For every keyframe prompt except the last
|
||||
for i in range(0, len(sorted_prompts) - 1):
|
||||
# Get current and next keyframe
|
||||
current_key = int(sorted_prompts[i][0])
|
||||
next_key = int(sorted_prompts[i + 1][0])
|
||||
|
||||
# Ensure there's no weird ordering issues or duplication in the animation prompts
|
||||
# (unlikely because we sort above, and the json parser will strip dupes)
|
||||
if current_key >= next_key:
|
||||
print(
|
||||
f"WARNING: Sequential prompt keyframes {i}:{current_key} and {i + 1}:{next_key} are not monotonously increasing; skipping interpolation.")
|
||||
continue
|
||||
|
||||
# Get current and next keyframes' positive and negative prompts (if any)
|
||||
current_prompt = sorted_prompts[i][1]
|
||||
|
||||
for f in range(current_key, next_key):
|
||||
# add the appropriate prompts and weights to their respective containers.
|
||||
cur_prompt_series[f] = ''
|
||||
weight_series[f] = 0.0
|
||||
|
||||
cur_prompt_series[f] += (str(pre_text) + " " + str(current_prompt) + " " + str(app_text))
|
||||
|
||||
current_key = next_key
|
||||
next_key = max_frames
|
||||
# second loop to catch any nan runoff
|
||||
|
||||
for f in range(current_key, next_key):
|
||||
# add the appropriate prompts and weights to their respective containers.
|
||||
cur_prompt_series[f] = ''
|
||||
cur_prompt_series[f] += (str(pre_text) + " " + str(current_prompt) + " " + str(app_text))
|
||||
|
||||
# Evaluate the current and next prompt's expressions
|
||||
cur_prompt_series[current_frame] = prepare_prompt(cur_prompt_series[current_frame], max_frames, current_frame,
|
||||
prompt_weight_1, prompt_weight_2, prompt_weight_3,
|
||||
prompt_weight_4)
|
||||
|
||||
# Show the to/from prompts with evaluated expressions for transparency.
|
||||
print("\n", "Max Frames: ", max_frames, "\n", "Current Prompt: ", cur_prompt_series[current_frame], "\n")
|
||||
|
||||
# Output methods depending if the prompts are the same or if the current frame is a keyframe.
|
||||
# if it is an in-between frame and the prompts differ, composable diffusion will be performed.
|
||||
return (cur_prompt_series[current_frame])
|
||||
def PoolAnimConditioning(cur_prompt, nxt_prompt, weight, clip):
|
||||
if str(cur_prompt) == str(nxt_prompt):
|
||||
tokens = clip.tokenize(str(cur_prompt))
|
||||
@@ -297,182 +179,4 @@ def SDXLencode(g, l, settings:ScheduleSettings, clip):
|
||||
"crop_h": settings.crop_h,
|
||||
"target_width": settings.target_width,
|
||||
"target_height": settings.target_height
|
||||
}]]
|
||||
|
||||
def interpolate_prompts_SDXL(animation_promptsG, animation_promptsL, max_frames, current_frame, clip, app_text_G, app_text_L, pre_text_G, pre_text_L, pw_a, pw_b, pw_c, pw_d, width, height, crop_w, crop_h, target_width, target_height, print_output): #parse the conditioning strength and determine in-betweens.
|
||||
#Get prompts sorted by keyframe
|
||||
max_f = max_frames #needed for numexpr even though it doesn't look like it's in use.
|
||||
parsed_animation_promptsG = {}
|
||||
parsed_animation_promptsL = {}
|
||||
for key, value in animation_promptsG.items():
|
||||
if check_is_number(key): #default case 0:(1 + t %5), 30:(5-t%2)
|
||||
parsed_animation_promptsG[key] = value
|
||||
else: #math on the left hand side case 0:(1 + t %5), maxKeyframes/2:(5-t%2)
|
||||
parsed_animation_promptsG[int(numexpr.evaluate(key))] = value
|
||||
|
||||
sorted_prompts_G = sorted(parsed_animation_promptsG.items(), key=lambda item: int(item[0]))
|
||||
|
||||
for key, value in animation_promptsL.items():
|
||||
if check_is_number(key): #default case 0:(1 + t %5), 30:(5-t%2)
|
||||
parsed_animation_promptsL[key] = value
|
||||
else: #math on the left hand side case 0:(1 + t %5), maxKeyframes/2:(5-t%2)
|
||||
parsed_animation_promptsL[int(numexpr.evaluate(key))] = value
|
||||
|
||||
sorted_prompts_L = sorted(parsed_animation_promptsL.items(), key=lambda item: int(item[0]))
|
||||
|
||||
#Setup containers for interpolated prompts
|
||||
cur_prompt_series_G = pd.Series([np.nan for a in range(max_frames)])
|
||||
nxt_prompt_series_G = pd.Series([np.nan for a in range(max_frames)])
|
||||
|
||||
cur_prompt_series_L = pd.Series([np.nan for a in range(max_frames)])
|
||||
nxt_prompt_series_L = pd.Series([np.nan for a in range(max_frames)])
|
||||
|
||||
#simple array for strength values
|
||||
weight_series = [np.nan] * max_frames
|
||||
|
||||
#in case there is only one keyed promt, set all prompts to that prompt
|
||||
if len(sorted_prompts_G) - 1 == 0:
|
||||
for i in range(0, len(cur_prompt_series_G)-1):
|
||||
current_prompt_G = sorted_prompts_G[0][1]
|
||||
cur_prompt_series_G[i] = str(pre_text_G) + " " + str(current_prompt_G) + " " + str(app_text_G)
|
||||
nxt_prompt_series_G[i] = str(pre_text_G) + " " + str(current_prompt_G) + " " + str(app_text_G)
|
||||
|
||||
if len(sorted_prompts_L) - 1 == 0:
|
||||
for i in range(0, len(cur_prompt_series_L)-1):
|
||||
current_prompt_L = sorted_prompts_L[0][1]
|
||||
cur_prompt_series_L[i] = str(pre_text_L) + " " + str(current_prompt_L) + " " + str(app_text_L)
|
||||
nxt_prompt_series_L[i] = str(pre_text_L) + " " + str(current_prompt_L) + " " + str(app_text_L)
|
||||
|
||||
#Initialized outside of loop for nan check
|
||||
current_key = 0
|
||||
next_key = 0
|
||||
|
||||
# For every keyframe prompt except the last
|
||||
for i in range(0, len(sorted_prompts_G) - 1):
|
||||
# Get current and next keyframe
|
||||
current_key = int(sorted_prompts_G[i][0])
|
||||
next_key = int(sorted_prompts_G[i + 1][0])
|
||||
|
||||
# Ensure there's no weird ordering issues or duplication in the animation prompts
|
||||
# (unlikely because we sort above, and the json parser will strip dupes)
|
||||
if current_key >= next_key:
|
||||
print(f"WARNING: Sequential prompt keyframes {i}:{current_key} and {i + 1}:{next_key} are not monotonously increasing; skipping interpolation.")
|
||||
continue
|
||||
|
||||
# Get current and next keyframes' positive and negative prompts (if any)
|
||||
current_prompt_G = sorted_prompts_G[i][1]
|
||||
next_prompt_G = sorted_prompts_G[i + 1][1]
|
||||
|
||||
# Calculate how much to shift the weight from current to next prompt at each frame.
|
||||
weight_step = 1 / (next_key - current_key)
|
||||
|
||||
for f in range(current_key, next_key):
|
||||
next_weight = weight_step * (f - current_key)
|
||||
current_weight = 1 - next_weight
|
||||
|
||||
#add the appropriate prompts and weights to their respective containers.
|
||||
cur_prompt_series_G[f] = ''
|
||||
nxt_prompt_series_G[f] = ''
|
||||
weight_series[f] = 0.0
|
||||
|
||||
cur_prompt_series_G[f] += (str(pre_text_G) + " " + str(current_prompt_G) + " " + str(app_text_G))
|
||||
nxt_prompt_series_G[f] += (str(pre_text_G) + " " + str(next_prompt_G) + " " + str(app_text_G))
|
||||
|
||||
weight_series[f] += current_weight
|
||||
|
||||
current_key = next_key
|
||||
next_key = max_frames
|
||||
current_weight = 0.0
|
||||
#second loop to catch any nan runoff
|
||||
for f in range(current_key, next_key):
|
||||
next_weight = weight_step * (f - current_key)
|
||||
|
||||
#add the appropriate prompts and weights to their respective containers.
|
||||
cur_prompt_series_G[f] = ''
|
||||
nxt_prompt_series_G[f] = ''
|
||||
weight_series[f] = current_weight
|
||||
|
||||
cur_prompt_series_G[f] += (str(pre_text_G) + " " + str(current_prompt_G) + " " + str(app_text_G))
|
||||
nxt_prompt_series_G[f] += (str(pre_text_G) + " " + str(next_prompt_G) + " " + str(app_text_G))
|
||||
|
||||
|
||||
#Reset outside of loop for nan check
|
||||
current_key = 0
|
||||
next_key = 0
|
||||
|
||||
# For every keyframe prompt except the last
|
||||
for i in range(0, len(sorted_prompts_L) - 1):
|
||||
# Get current and next keyframe
|
||||
current_key = int(sorted_prompts_L[i][0])
|
||||
next_key = int(sorted_prompts_L[i + 1][0])
|
||||
|
||||
# Ensure there's no weird ordering issues or duplication in the animation prompts
|
||||
# (unlikely because we sort above, and the json parser will strip dupes)
|
||||
if current_key >= next_key:
|
||||
print(f"WARNING: Sequential prompt keyframes {i}:{current_key} and {i + 1}:{next_key} are not monotonously increasing; skipping interpolation.")
|
||||
continue
|
||||
|
||||
# Get current and next keyframes' positive and negative prompts (if any)
|
||||
current_prompt_L = sorted_prompts_L[i][1]
|
||||
next_prompt_L = sorted_prompts_L[i + 1][1]
|
||||
|
||||
# Calculate how much to shift the weight from current to next prompt at each frame.
|
||||
weight_step = 1 / (next_key - current_key)
|
||||
|
||||
for f in range(current_key, next_key):
|
||||
next_weight = weight_step * (f - current_key)
|
||||
current_weight = 1 - next_weight
|
||||
|
||||
#add the appropriate prompts and weights to their respective containers.
|
||||
cur_prompt_series_L[f] = ''
|
||||
nxt_prompt_series_L[f] = ''
|
||||
weight_series[f] = 0.0
|
||||
|
||||
cur_prompt_series_L[f] += (str(pre_text_L) + " " + str(current_prompt_L) + " " + str(app_text_L))
|
||||
nxt_prompt_series_L[f] += (str(pre_text_L) + " " + str(next_prompt_L) + " " + str(app_text_L))
|
||||
|
||||
weight_series[f] += current_weight
|
||||
|
||||
current_key = next_key
|
||||
next_key = max_frames
|
||||
current_weight = 0.0
|
||||
#second loop to catch any nan runoff
|
||||
for f in range(current_key, next_key):
|
||||
next_weight = weight_step * (f - current_key)
|
||||
|
||||
#add the appropriate prompts and weights to their respective containers.
|
||||
cur_prompt_series_L[f] = ''
|
||||
nxt_prompt_series_L[f] = ''
|
||||
weight_series[f] = current_weight
|
||||
|
||||
cur_prompt_series_L[f] += (str(pre_text_L) + " " + str(current_prompt_L) + " " + str(app_text_L))
|
||||
nxt_prompt_series_L[f] += (str(pre_text_L) + " " + str(next_prompt_L) + " " + str(app_text_L))
|
||||
|
||||
#Evaluate the current and next prompt's expressions
|
||||
cur_prompt_series_G[current_frame] = prepare_prompt(cur_prompt_series_G[current_frame], max_frames, current_frame, pw_a, pw_b, pw_c, pw_d)
|
||||
nxt_prompt_series_G[current_frame] = prepare_prompt(nxt_prompt_series_G[current_frame], max_frames, current_frame, pw_a, pw_b, pw_c, pw_d)
|
||||
cur_prompt_series_L[current_frame] = prepare_prompt(cur_prompt_series_L[current_frame], max_frames, current_frame, pw_a, pw_b, pw_c, pw_d)
|
||||
nxt_prompt_series_L[current_frame] = prepare_prompt(nxt_prompt_series_L[current_frame], max_frames, current_frame, pw_a, pw_b, pw_c, pw_d)
|
||||
if print_output == True:
|
||||
#Show the to/from prompts with evaluated expressions for transparency.
|
||||
print("\n", "G_Clip:", "\n", "Max Frames: ", max_frames, "\n", "Current Prompt: ", cur_prompt_series_G[current_frame], "\n", "Next Prompt: ", nxt_prompt_series_G[current_frame], "\n", "Strength : ", weight_series[current_frame], "\n")
|
||||
|
||||
print("\n", "L_Clip:", "\n", "Max Frames: ", max_frames, "\n", "Current Prompt: ", cur_prompt_series_L[current_frame], "\n", "Next Prompt: ", nxt_prompt_series_L[current_frame], "\n", "Strength : ", weight_series[current_frame], "\n")
|
||||
|
||||
#Output methods depending if the prompts are the same or if the current frame is a keyframe.
|
||||
#if it is an in-between frame and the prompts differ, composable diffusion will be performed.
|
||||
current_cond = SDXLencode(settings, clip, cur_prompt_series_G[current_frame], cur_prompt_series_L[current_frame])
|
||||
|
||||
if str(cur_prompt_series_G[current_frame]) == str(nxt_prompt_series_G[current_frame]) and str(cur_prompt_series_L[current_frame]) == str(nxt_prompt_series_L[current_frame]):
|
||||
return current_cond
|
||||
|
||||
if weight_series[current_frame] == 1:
|
||||
return current_cond
|
||||
|
||||
if weight_series[current_frame] == 0:
|
||||
next_cond = SDXLencode(settings, clip, nxt_prompt_series_G[current_frame], nxt_prompt_series_L[current_frame])
|
||||
return next_cond
|
||||
|
||||
else:
|
||||
next_cond = SDXLencode(settings, clip, nxt_prompt_series_G[current_frame], nxt_prompt_series_L[current_frame])
|
||||
return addWeighted(current_cond, next_cond, weight_series[current_frame])
|
||||
}]]
|
||||
@@ -24,8 +24,6 @@ def prompt_schedule(settings:ScheduleSettings,clip):
|
||||
pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_seriesA(pos, settings)
|
||||
neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_seriesA(neg, settings)
|
||||
|
||||
#encode prompts
|
||||
|
||||
# Apply composable diffusion across the batch
|
||||
p = PoolAnimConditioning(pos_cur_prompt[settings.current_frame], pos_nxt_prompt[settings.current_frame],
|
||||
weight[settings.current_frame], clip)
|
||||
@@ -47,11 +45,6 @@ def batch_prompt_schedule(settings:ScheduleSettings,clip):
|
||||
pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_seriesA(pos, settings)
|
||||
neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_seriesA(neg, settings)
|
||||
|
||||
# encode prompts
|
||||
|
||||
# pad conditionings to largest tensor size
|
||||
|
||||
|
||||
# Apply composable diffusion across the batch
|
||||
p = BatchPoolAnimConditioning(pos_cur_prompt, pos_nxt_prompt, weight, clip, )
|
||||
n = BatchPoolAnimConditioning(neg_cur_prompt, neg_nxt_prompt, weight, clip, )
|
||||
|
||||
+94
-58
@@ -214,6 +214,9 @@ class BatchPromptScheduleLatentInput:
|
||||
)
|
||||
return batch_prompt_schedule_latentInput(settings,clip, num_latents)
|
||||
|
||||
# This node prepares the strings and calculates
|
||||
# the numexpr expressions. It returns a single
|
||||
# string at the current_frame input.
|
||||
class StringSchedule:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
@@ -261,6 +264,10 @@ class StringSchedule:
|
||||
)
|
||||
return string_schedule(settings)
|
||||
|
||||
|
||||
# This node prepares the strings and calculates
|
||||
# the numexpr expressions. It returns a batch of
|
||||
# strings.
|
||||
class BatchStringSchedule:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
@@ -311,7 +318,75 @@ class BatchStringSchedule:
|
||||
)
|
||||
return batch_string_schedule(settings)
|
||||
|
||||
# Same as the regular node just for SDXL
|
||||
# clips instead. the G and L clip can be
|
||||
# scheduled separately before tokenization,
|
||||
# goes through the same add_weighted process
|
||||
# and returns the current, next or averaged
|
||||
# conditioning.
|
||||
class PromptScheduleEncodeSDXL:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"crop_w": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"crop_h": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"target_width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"target_height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"text_g": ("STRING", {"multiline": True, }), "clip": ("CLIP", ),
|
||||
"text_l": ("STRING", {"multiline": True, }), "clip": ("CLIP", ),
|
||||
"max_frames": ("INT", {"default": 120.0, "min": 1.0, "max": 999999.0, "step": 1.0}),
|
||||
"current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 999999.0, "step": 1.0}),
|
||||
"print_output":("BOOLEAN", {"default": False})
|
||||
},
|
||||
"optional": {
|
||||
"pre_text_G": ("STRING", {"multiline": True, "forceInput": True}),
|
||||
"app_text_G": ("STRING", {"multiline": True, "forceInput": True}),
|
||||
"pre_text_L": ("STRING", {"multiline": True, "forceInput": True}),
|
||||
"app_text_L": ("STRING", {"multiline": True, "forceInput": True}),
|
||||
"pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, "forceInput": True }),
|
||||
"pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, "forceInput": True }),
|
||||
"pw_c": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, "forceInput": True }),
|
||||
"pw_d": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, "forceInput": True }),
|
||||
}
|
||||
}
|
||||
RETURN_TYPES = ("CONDITIONING","CONDITIONING",)
|
||||
RETURN_NAMES = ("POS", "NEG",)
|
||||
FUNCTION = "animate"
|
||||
|
||||
CATEGORY = "FizzNodes 📅🅕🅝/ScheduleNodes"
|
||||
|
||||
def animate(self, clip, width, height, crop_w, crop_h, target_width, target_height, text_g, text_l, app_text_G, app_text_L, pre_text_G, pre_text_L, max_frames, current_frame, print_output, pw_a, pw_b, pw_c, pw_d):
|
||||
settings = ScheduleSettings(
|
||||
text_g=text_g,
|
||||
pre_text_G=pre_text_G,
|
||||
app_text_G=app_text_G,
|
||||
text_L=text_l,
|
||||
pre_text_L=pre_text_L,
|
||||
app_text_L=app_text_L,
|
||||
max_frames=max_frames,
|
||||
current_frame=current_frame,
|
||||
print_output=print_output,
|
||||
pw_a=pw_a,
|
||||
pw_b=pw_b,
|
||||
pw_c=pw_c,
|
||||
pw_d=pw_d,
|
||||
start_frame=0,
|
||||
width=width,
|
||||
height=height,
|
||||
crop_w=crop_w,
|
||||
crop_h=crop_h,
|
||||
target_width=target_width,
|
||||
target_height=target_height,
|
||||
)
|
||||
return prompt_schedule_SDXL(settings,clip)
|
||||
|
||||
# Same as the regular node just for SDXL
|
||||
# clips instead. the G and L clip can be
|
||||
# scheduled separately before tokenization,
|
||||
# goes through the same add_weighted process
|
||||
# and returns a batch of conditionings.
|
||||
class BatchPromptScheduleEncodeSDXL:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
@@ -370,6 +445,13 @@ class BatchPromptScheduleEncodeSDXL:
|
||||
)
|
||||
return batch_prompt_schedule_SDXL(settings, clip)
|
||||
|
||||
# Same as the regular node just for SDXL
|
||||
# clips instead. the G and L clip can be
|
||||
# scheduled separately before tokenization,
|
||||
# goes through the same add_weighted process
|
||||
# and returns a batch of conditionings. The
|
||||
# max_size is input by the number of latents
|
||||
# in the input.
|
||||
class BatchPromptScheduleEncodeSDXLLatentInput:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
@@ -427,63 +509,7 @@ class BatchPromptScheduleEncodeSDXLLatentInput:
|
||||
)
|
||||
return batch_prompt_schedule_SDXL_latentInput(settings, clip, num_latents)
|
||||
|
||||
class PromptScheduleEncodeSDXL:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"crop_w": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"crop_h": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"target_width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"target_height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
|
||||
"text_g": ("STRING", {"multiline": True, }), "clip": ("CLIP", ),
|
||||
"text_l": ("STRING", {"multiline": True, }), "clip": ("CLIP", ),
|
||||
"max_frames": ("INT", {"default": 120.0, "min": 1.0, "max": 999999.0, "step": 1.0}),
|
||||
"current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 999999.0, "step": 1.0}),
|
||||
"print_output":("BOOLEAN", {"default": False})
|
||||
},
|
||||
"optional": {
|
||||
"pre_text_G": ("STRING", {"multiline": True, "forceInput": True}),
|
||||
"app_text_G": ("STRING", {"multiline": True, "forceInput": True}),
|
||||
"pre_text_L": ("STRING", {"multiline": True, "forceInput": True}),
|
||||
"app_text_L": ("STRING", {"multiline": True, "forceInput": True}),
|
||||
"pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, "forceInput": True }),
|
||||
"pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, "forceInput": True }),
|
||||
"pw_c": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, "forceInput": True }),
|
||||
"pw_d": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, "forceInput": True }),
|
||||
}
|
||||
}
|
||||
RETURN_TYPES = ("CONDITIONING","CONDITIONING",)
|
||||
RETURN_NAMES = ("POS", "NEG",)
|
||||
FUNCTION = "animate"
|
||||
|
||||
CATEGORY = "FizzNodes 📅🅕🅝/ScheduleNodes"
|
||||
|
||||
def animate(self, clip, width, height, crop_w, crop_h, target_width, target_height, text_g, text_l, app_text_G, app_text_L, pre_text_G, pre_text_L, max_frames, current_frame, print_output, pw_a, pw_b, pw_c, pw_d):
|
||||
settings = ScheduleSettings(
|
||||
text_g=text_g,
|
||||
pre_text_G=pre_text_G,
|
||||
app_text_G=app_text_G,
|
||||
text_L=text_l,
|
||||
pre_text_L=pre_text_L,
|
||||
app_text_L=app_text_L,
|
||||
max_frames=max_frames,
|
||||
current_frame=current_frame,
|
||||
print_output=print_output,
|
||||
pw_a=pw_a,
|
||||
pw_b=pw_b,
|
||||
pw_c=pw_c,
|
||||
pw_d=pw_d,
|
||||
start_frame=0,
|
||||
width=width,
|
||||
height=height,
|
||||
crop_w=crop_w,
|
||||
crop_h=crop_h,
|
||||
target_width=target_width,
|
||||
target_height=target_height,
|
||||
)
|
||||
return prompt_schedule_SDXL(settings,clip)
|
||||
|
||||
# This node schedules the prompt using separate nodes as the keyframes.
|
||||
# The values in the prompt are evaluated in NodeFlowEnd.
|
||||
@@ -569,6 +595,7 @@ class PromptScheduleNodeFlowEnd:
|
||||
)
|
||||
return prompt_schedule(settings, clip)
|
||||
|
||||
#same as the other node end except it returns a batch
|
||||
class BatchPromptScheduleNodeFlowEnd:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
@@ -622,6 +649,10 @@ class BatchPromptScheduleNodeFlowEnd:
|
||||
)
|
||||
return batch_prompt_schedule(settings, clip)
|
||||
|
||||
# WIP, requires some hijacking but otherwise
|
||||
# applies every scheduled gligen bound box to
|
||||
# a batch of latents with the scheduled
|
||||
# conditionings
|
||||
class BatchGLIGENSchedule:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
@@ -744,7 +775,13 @@ class BatchValueScheduleLatentInput:
|
||||
print("ValueSchedule: ", t)
|
||||
return (t, list(map(int,t)), num_latents, )
|
||||
|
||||
# Expects a Batch Value Schedule list input, it exports an image batch with images taken from an input image batch
|
||||
# Expects a Batch Value Schedule list input,
|
||||
# it exports an image batch with images taken
|
||||
# from an input image batch.
|
||||
# Original code is from:
|
||||
# ComfyUI-Image-Selector by SLAPaper
|
||||
# https://github.com/SLAPaper/ComfyUI-Image-Selector
|
||||
# licensed under Apache-2.0
|
||||
class ImagesFromBatchSchedule:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
@@ -773,7 +810,6 @@ class ImagesFromBatchSchedule:
|
||||
selImages = selectImages(images,pos_cur_prompt[current_frame])
|
||||
return selImages
|
||||
|
||||
|
||||
def selectImages(images: torch.Tensor, selected_indexes: str):
|
||||
shape = images.shape
|
||||
len_first_dim = shape[0]
|
||||
|
||||
Reference in New Issue
Block a user