modified: mikey_nodes.py
This commit is contained in:
+150
-9
@@ -1377,10 +1377,13 @@ class SaveImagesMikeyML:
|
||||
|
||||
# Get initial counter value
|
||||
files = os.listdir(full_output_folder)
|
||||
counter = self._get_initial_counter(files, full_output_folder, counter_type, filename_separator, counter_pos, filename_texts)
|
||||
if counter_type != 'none':
|
||||
counter = self._get_initial_counter(files, full_output_folder, counter_type, filename_separator, counter_pos, filename_texts)
|
||||
else:
|
||||
counter = 0
|
||||
|
||||
results = list()
|
||||
for image in images:
|
||||
for ix, image in enumerate(images):
|
||||
i = 255. * image.cpu().numpy()
|
||||
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
|
||||
metadata = PngInfo()
|
||||
@@ -1402,20 +1405,25 @@ class SaveImagesMikeyML:
|
||||
#metadata.add_text("extra_metadata", json.dumps(extra_metadata, ensure_ascii=False))
|
||||
metadata.add_text("extra_metadata", extra_metadata)
|
||||
# Check and get the next available counter
|
||||
counter = self._get_next_counter(full_output_folder, filename_base, counter)
|
||||
current_filename = filename_base.format(counter=f"{counter:05}")
|
||||
if counter_type != 'none':
|
||||
counter = self._get_next_counter(full_output_folder, filename_base, counter)
|
||||
current_filename = filename_base.format(counter=f"{counter:05}")
|
||||
else:
|
||||
current_filename = filename_base
|
||||
if timestamp_type == 'save_time' and timestamp == 'true':
|
||||
current_timestamp = datetime.datetime.now().strftime("%y%m%d%H%M%S")
|
||||
current_filename = current_filename.replace(ts, current_timestamp)
|
||||
ts = current_timestamp
|
||||
|
||||
if ix > 0 and counter_type == 'none':
|
||||
current_filename = current_filename.replace(ts, ts + f'_{ix:02}')
|
||||
img.save(os.path.join(full_output_folder, f"{current_filename}.png"), pnginfo=metadata, compress_level=4)
|
||||
results.append({
|
||||
"filename": f"{current_filename}.png",
|
||||
"subfolder": sub_directory,
|
||||
"type": self.type
|
||||
})
|
||||
counter += 1
|
||||
if counter_type != 'none':
|
||||
counter += 1
|
||||
|
||||
return {"ui": {"images": results}}
|
||||
|
||||
@@ -2682,6 +2690,19 @@ def ai_upscale(tile, base_model, vae, seed, positive_cond_base, negative_cond_ba
|
||||
tile = vaedecoder.decode(vae, tile)[0]
|
||||
return tile
|
||||
|
||||
def ai_upscale_adv(tile, base_model, vae, seed, cfg, sampler_name, scheduler, positive_cond_base, negative_cond_base, start_step=11, end_step=20):
|
||||
"""Upscale a tile using the AI model."""
|
||||
vaedecoder = VAEDecode()
|
||||
vaeencoder = VAEEncode()
|
||||
tile = pil2tensor(tile)
|
||||
#print('Tile Complexity:', complexity)
|
||||
encoded_tile = vaeencoder.encode(vae, tile)[0]
|
||||
tile = common_ksampler(base_model, seed, end_step, cfg, sampler_name, scheduler,
|
||||
positive_cond_base, negative_cond_base, encoded_tile,
|
||||
start_step=start_step, force_full_denoise=True)[0]
|
||||
tile = vaedecoder.decode(vae, tile)[0]
|
||||
return tile
|
||||
|
||||
def run_tiler(enlarged_img, base_model, vae, seed, positive_cond_base, negative_cond_base, denoise=0.25, use_complexity_score='true'):
|
||||
# Split the enlarged image into overlapping tiles
|
||||
tiles = split_image(enlarged_img)
|
||||
@@ -2695,6 +2716,21 @@ def run_tiler(enlarged_img, base_model, vae, seed, positive_cond_base, negative_
|
||||
|
||||
return result
|
||||
|
||||
def run_tiler_for_steps(enlarged_img, base_model, vae, seed, cfg, sampler_name, scheduler, positive_cond_base, negative_cond_base, steps=20, denoise=0.25):
|
||||
# Split the enlarged image into overlapping tiles
|
||||
tiles = split_image(enlarged_img)
|
||||
|
||||
# Resample each tile using the AI model
|
||||
start_step = int(steps - (steps * denoise))
|
||||
end_step = steps
|
||||
resampled_tiles = [(coords, ai_upscale_adv(tile, base_model, vae, seed, cfg, sampler_name, scheduler,
|
||||
positive_cond_base, negative_cond_base, start_step, end_step)) for coords, tile in tiles]
|
||||
|
||||
# Stitch the tiles to get the final upscaled image
|
||||
result = stitch_images(enlarged_img.size, resampled_tiles)
|
||||
|
||||
return result
|
||||
|
||||
class MikeySamplerTiled:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
@@ -2759,7 +2795,7 @@ class MikeySamplerTiledAdvanced:
|
||||
"positive_cond_refiner": ("CONDITIONING",), "negative_cond_refiner": ("CONDITIONING",),
|
||||
"model_name": (folder_paths.get_filename_list("upscale_models"), ),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"denoise_image": ("FLOAT", {"default": 0.25, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"denoise_image": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"steps": ("INT", {"default": 30, "min": 1, "max": 1000}),
|
||||
"smooth_step": ("INT", {"default": 1, "min": -1, "max": 100}),
|
||||
"cfg": ("FLOAT", {"default": 6.5, "min": 0.0, "max": 1000.0, "step": 0.1}),
|
||||
@@ -2838,6 +2874,68 @@ class MikeySamplerTiledAdvanced:
|
||||
tiled_image = run_tiler(img, refiner_model, vae, seed, positive_cond_refiner, negative_cond_refiner, tiler_denoise, use_complexity_score)
|
||||
return (tiled_image, img)
|
||||
|
||||
class MikeySamplerTiledAdvancedBaseOnly:
|
||||
# there is no step skipped, so no smooth steps are required
|
||||
# also no refiner for this
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {"base_model": ("MODEL",),
|
||||
"samples": ("LATENT",), "vae": ("VAE",),
|
||||
"positive_cond_base": ("CONDITIONING",), "negative_cond_base": ("CONDITIONING",),
|
||||
"model_name": (folder_paths.get_filename_list("upscale_models"), ),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"denoise_image": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"steps": ("INT", {"default": 30, "min": 1, "max": 1000}),
|
||||
"cfg": ("FLOAT", {"default": 6.5, "min": 0.0, "max": 1000.0, "step": 0.1}),
|
||||
"sampler_name": (comfy.samplers.KSampler.SAMPLERS, ),
|
||||
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, ),
|
||||
"upscale_by": ("FLOAT", {"default": 1.0, "min": 0.1, "max": 10.0, "step": 0.1}),
|
||||
"tiler_denoise": ("FLOAT", {"default": 0.25, "min": 0.0, "max": 1.0, "step": 0.05}),},
|
||||
"optional": {"image_optional": ("IMAGE",),}}
|
||||
|
||||
RETURN_TYPES = ('IMAGE', )
|
||||
RETURN_NAMES = ('output_image', )
|
||||
FUNCTION = 'run'
|
||||
CATEGORY = 'Mikey/Sampling'
|
||||
|
||||
def phase_one(self, base_model, samples, positive_cond_base, negative_cond_base,
|
||||
upscale_by, model_name, seed, vae, denoise_image,
|
||||
steps, cfg, sampler_name, scheduler):
|
||||
image_scaler = ImageScale()
|
||||
vaedecoder = VAEDecode()
|
||||
uml = UpscaleModelLoader()
|
||||
upscale_model = uml.load_model(model_name)[0]
|
||||
iuwm = ImageUpscaleWithModel()
|
||||
# step 1 run base model
|
||||
start_step = int(steps - (steps * denoise_image))
|
||||
#print(f'base model start_step: {start_step}, last_step: {last_step}')
|
||||
sample1 = common_ksampler(base_model, seed, steps, cfg, sampler_name, scheduler, positive_cond_base, negative_cond_base, samples,
|
||||
start_step=start_step, last_step=steps, force_full_denoise=False)[0]
|
||||
# step 3 upscale image using a simple AI image upscaler
|
||||
pixels = vaedecoder.decode(vae, sample1)[0]
|
||||
org_width, org_height = pixels.shape[2], pixels.shape[1]
|
||||
img = iuwm.upscale(upscale_model, image=pixels)[0]
|
||||
upscaled_width, upscaled_height = int(org_width * upscale_by // 8 * 8), int(org_height * upscale_by // 8 * 8)
|
||||
img = image_scaler.upscale(img, 'nearest-exact', upscaled_width, upscaled_height, 'center')[0]
|
||||
return img, upscaled_width, upscaled_height
|
||||
|
||||
def run(self, seed, base_model, vae, samples, positive_cond_base, negative_cond_base,
|
||||
model_name, upscale_by=2.0, tiler_denoise=0.4,
|
||||
upscale_method='normal', denoise_image=1.0, steps=30, cfg=6.5,
|
||||
sampler_name='dpmpp_sde_gpu', scheduler='karras', image_optional=None):
|
||||
# if image not none replace samples with decoded image
|
||||
if image_optional is not None:
|
||||
vaeencoder = VAEEncode()
|
||||
samples = vaeencoder.encode(vae, image_optional)[0]
|
||||
# phase 1: run base, refiner, then upscaler model
|
||||
img, upscaled_width, upscaled_height = self.phase_one(base_model, samples, positive_cond_base, negative_cond_base,
|
||||
upscale_by, model_name, seed, vae, denoise_image,
|
||||
steps, cfg, sampler_name, scheduler)
|
||||
# phase 2: run tiler
|
||||
img = tensor2pil(img)
|
||||
tiled_image = run_tiler_for_steps(img, base_model, vae, seed, cfg, sampler_name, scheduler, positive_cond_base, negative_cond_base, steps, tiler_denoise)
|
||||
return (tiled_image, )
|
||||
|
||||
class MikeySamplerTiledBaseOnly(MikeySamplerTiled):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
@@ -3447,7 +3545,7 @@ class OobaPrompt:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {'required': {'input_prompt': ('STRING', {'multiline': True, 'default': 'Prompt Text Here', 'dynamicPrompts': False}),
|
||||
'mode': (['prompt', 'style', 'descriptor', 'custom'], {'default': 'prompt'}),
|
||||
'mode': (['prompt', 'style', 'descriptor', 'character', 'custom'], {'default': 'prompt'}),
|
||||
'custom_history': ('STRING', {'multiline': False, 'default': 'path to history.json', 'dynamicPrompts': True}),
|
||||
'seed': ('INT', {'default': 0, 'min': 0, 'max': 0xffffffffffffffff}),},
|
||||
"hidden": {"unique_id": "UNIQUE_ID", "extra_pnginfo": "EXTRA_PNGINFO", "prompt": "PROMPT"}}
|
||||
@@ -3648,6 +3746,45 @@ class OobaPrompt:
|
||||
]
|
||||
]
|
||||
}
|
||||
elif mode == 'character':
|
||||
return {
|
||||
"internal": [
|
||||
[
|
||||
"<|BEGIN-VISIBLE-CHAT|>",
|
||||
"How can I help you today?"
|
||||
],
|
||||
[
|
||||
"When a user requests a character description, generate a detailed description of the character as you would expect from the writer George R. R. Martin. The description should be a suitable prompt based on the description that encapsulates the character's key visual elements for image creation using a txt2img model.",
|
||||
"Sure thing! Let's begin. What is your first prompt?"
|
||||
],
|
||||
[
|
||||
"jolly cartoon octopus",
|
||||
"A cartoon octopus with a jolly demeanor in a sunshiny yellow and orange color scheme, wearing a small top hat and a polka-dotted bow tie, surrounded by intricate sculptures made of its own ink, in the midst of an undersea setting that hints at festivity and mirth.",
|
||||
],
|
||||
[
|
||||
"a dapper young lady spy who wears suits",
|
||||
"A young 1920s lady spy with chestnut hair in a bob cut, piercing emerald eyes, wearing a tailored charcoal pinstripe suit with a white shirt and a silk tie, holding a silver cigarette case, exuding an aura of mystery and sophistication against a backdrop of Parisian nightlife.",
|
||||
],
|
||||
[
|
||||
"a charming robot",
|
||||
"A charming robot with a sleek chrome body, art deco design elements, azure glowing eyes, and a gentle smile. Wearing a holographic bow tie and a vest painted to look like a dapper suit, engaged in performing a magic trick with a playful, inquisitive expression in an urban park setting.",
|
||||
],
|
||||
[
|
||||
"cartoon ant",
|
||||
"A cartoon ant with a vibrant blue exoskeleton, oversized round eyes full of curiosity, wearing a leaf-green vest and a tiny fabric cap. Exhibiting an expression of wonder and excitement, amidst a backdrop of an underground ant colony bustling with activity.",
|
||||
],
|
||||
[
|
||||
"a cyberpunk gnome",
|
||||
"A cyberpunk gnome with pale skin and cybernetic jade eyes, wearing a long tattered coat with circuitry patches and a sleek metallic pointed helmet. Surrounded by holographic screens and neon lights in a dim, cluttered workshop filled with futuristic gadgets and data screens.",
|
||||
]
|
||||
],
|
||||
"visible": [
|
||||
[
|
||||
"",
|
||||
"How can I help you today?"
|
||||
]
|
||||
]
|
||||
}
|
||||
elif mode == 'custom':
|
||||
# open json file that is in the custom_history path
|
||||
try:
|
||||
@@ -3659,6 +3796,8 @@ class OobaPrompt:
|
||||
def api_request(self, prompt, seed, mode, custom_history):
|
||||
# check if json file in root comfy directory called oooba.json
|
||||
history = self.history(mode, custom_history)
|
||||
if mode == 'prompt':
|
||||
prompt = f'{prompt}, describe in detail.'
|
||||
if mode == 'descriptor':
|
||||
# use seed to add a bit more randomness to the prompt
|
||||
spice = ['a', 'the', 'this', 'that',
|
||||
@@ -3693,7 +3832,7 @@ class OobaPrompt:
|
||||
HOST = 'localhost:5000'
|
||||
URI = f'http://{HOST}/api/v1/chat'
|
||||
try:
|
||||
response = requests.post(URI, json=request, timeout=10)
|
||||
response = requests.post(URI, json=request, timeout=20)
|
||||
except requests.exceptions.ConnectionError:
|
||||
raise Exception('Are you running oobabooga with API enabled?')
|
||||
|
||||
@@ -3795,6 +3934,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
'Style Conditioner Base Only': StyleConditionerBaseOnly,
|
||||
'Mikey Sampler': MikeySampler,
|
||||
'MikeySamplerTiledAdvanced': MikeySamplerTiledAdvanced,
|
||||
'MikeySamplerTiledAdvancedBaseOnly': MikeySamplerTiledAdvancedBaseOnly,
|
||||
'Mikey Sampler Base Only': MikeySamplerBaseOnly,
|
||||
'Mikey Sampler Base Only Advanced': MikeySamplerBaseOnlyAdvanced,
|
||||
'Mikey Sampler Tiled': MikeySamplerTiled,
|
||||
@@ -3850,6 +3990,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
'Mikey Sampler Base Only Advanced': 'Mikey Sampler Base Only Advanced',
|
||||
'Mikey Sampler Tiled': 'Mikey Sampler Tiled',
|
||||
'MikeySamplerTiledAdvanced': 'Mikey Sampler Tiled Advanced',
|
||||
'MikeySamplerTiledAdvancedBaseOnly': 'Mikey Sampler Tiled Advanced Base Only',
|
||||
'Mikey Sampler Tiled Base Only': 'Mikey Sampler Tiled Base Only',
|
||||
'AddMetaData': 'AddMetaData (Mikey)',
|
||||
'SaveMetaData': 'SaveMetaData (Mikey)',
|
||||
|
||||
Reference in New Issue
Block a user