diff --git a/Nodes/Dashboard.py b/Nodes/Dashboard.py index fa95838..86c5417 100644 --- a/Nodes/Dashboard.py +++ b/Nodes/Dashboard.py @@ -320,9 +320,9 @@ class PrimereSeed: @classmethod def INPUT_TYPES(cls): return { - "required": { - "seed": ("INT", {"default": -1, "min": -1, "max": 0xffffffffffffffff}), - }, + "required": { + "seed": ("INT", {"default": -1, "min": -1, "max": 0xffffffffffffffff}), + }, } def seed(self, seed = 0): @@ -353,9 +353,15 @@ class PrimereFractalLatent: "modulator": ("FLOAT", {"default": 1.0, "max": 2.0, "min": 0.1, "step": 0.01}), "modulator_rand_min": ("FLOAT", {"default": 0.8, "max": 2.0, "min": 0.1, "step": 0.01}), "modulator_rand_max": ("FLOAT", {"default": 1.4, "max": 2.0, "min": 0.1, "step": 0.01}), - "seed": ("INT", {"default": 0, "min": -1, "max": 0xffffffffffffffff, "forceInput": True}), + "noise_seed": ("INT", {"default": 0, "min": -1, "max": 0xffffffffffffffff, "forceInput": True}), "rand_device": ("BOOLEAN", {"default": False}), "device": (["cpu", "cuda"],), + + "extra_variation": ("BOOLEAN", {"default": False, "label_on": "ON", "label_off": "OFF"}), + # "variation_seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), + # "variation_increment": ("FLOAT", {"default": 0.01, "min": 0.01, "max": 1.0, "step": 0.01}), + # "variation_strength": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01}), + "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), }, "optional": { "optional_vae": ("VAE",), @@ -367,10 +373,28 @@ class PrimereFractalLatent: FUNCTION = "primere_latent_noise" CATEGORY = TREE_DASHBOARD - def primere_latent_noise(self, width, height, rand_noise_type, noise_type, rand_alpha_exponent, alpha_exponent, alpha_exp_rand_min, alpha_exp_rand_max, rand_modulator, modulator, modulator_rand_min, modulator_rand_max, seed, rand_device, device, optional_vae = None): + def primere_latent_noise(self, width, height, rand_noise_type, noise_type, rand_alpha_exponent, alpha_exponent, alpha_exp_rand_min, alpha_exp_rand_max, rand_modulator, modulator, modulator_rand_min, modulator_rand_max, noise_seed, seed, rand_device, device, optional_vae = None, extra_variation = False): + if extra_variation == True: + rand_device = True + rand_alpha_exponent = True + rand_modulator = True + rand_noise_type = True + alpha_exp_rand_min = -12.00 + alpha_exp_rand_max = 7.00 + modulator_rand_min = 0.10 + modulator_rand_max = 2.00 + noise_seed = seed + + if rand_noise_type == True: + pln = PowerLawNoise(device) + noise_type = random.choice(pln.get_noise_types()) + if rand_device == True: device = random.choice(["cpu", "cuda"]) + if extra_variation == True and (noise_type == 'white' or noise_type == 'violet'): + alpha_exp_rand_min = 0.00 + power_law = PowerLawNoise(device = device) if rand_alpha_exponent == True: @@ -379,11 +403,7 @@ class PrimereFractalLatent: if rand_modulator == True: modulator = round(random.uniform(modulator_rand_min, modulator_rand_max), 2) - if rand_noise_type == True: - pln = PowerLawNoise(device) - noise_type = random.choice(pln.get_noise_types()) - - tensors = power_law(1, width, height, scale = 1, alpha = alpha_exponent, modulator = modulator, noise_type = noise_type, seed = seed) + tensors = power_law(1, width, height, scale = 1, alpha = alpha_exponent, modulator = modulator, noise_type = noise_type, seed = noise_seed) alpha_channel = torch.ones((1, height, width, 1), dtype = tensors.dtype, device = "cpu") tensors = torch.cat((tensors, alpha_channel), dim = 3) @@ -628,8 +648,8 @@ class PrimereResolution: "seed": ("INT", {"default": 0, "min": -1, "max": 0xffffffffffffffff, "forceInput": True}), "calculate_by_custom": ("BOOLEAN", {"default": False}), - "custom_side_a": ("FLOAT", {"default": 1.6, "min": 1.0, "max": 100.0, "step": 0.1}), - "custom_side_b": ("FLOAT", {"default": 2.8, "min": 1.0, "max": 100.0, "step": 0.1}), + "custom_side_a": ("FLOAT", {"default": 1.6, "min": 1.0, "max": 100.0, "step": 0.05}), + "custom_side_b": ("FLOAT", {"default": 2.8, "min": 1.0, "max": 100.0, "step": 0.05}), }, "optional": { "model_version": ("STRING", {"default": 'BaseModel_1024', "forceInput": True}), @@ -674,8 +694,8 @@ class PrimereResolutionMultiplier: "width": ('INT', {"forceInput": True, "default": 512}), "height": ('INT', {"forceInput": True, "default": 512}), "use_multiplier": ("BOOLEAN", {"default": True}), - "multiply_sd": ("FLOAT", {"default": 2.0, "min": 0.1, "max": 8.0, "step": 0.1}), - "multiply_sdxl": ("FLOAT", {"default": 2.0, "min": 0.1, "max": 8.0, "step": 0.1}), + "multiply_sd": ("FLOAT", {"default": 2.0, "min": 0.1, "max": 8.0, "step": 0.02}), + "multiply_sdxl": ("FLOAT", {"default": 2.0, "min": 0.1, "max": 8.0, "step": 0.02}), }, "optional": { "model_version": ("STRING", {"default": 'BaseModel_1024', "forceInput": True}), diff --git a/Workflow/Primere_basic_workflow.json b/Workflow/Primere_basic_workflow.json index c6e6db4..e58091b 100644 --- a/Workflow/Primere_basic_workflow.json +++ b/Workflow/Primere_basic_workflow.json @@ -1,6 +1,6 @@ { - "last_node_id": 17, - "last_link_id": 37, + "last_node_id": 39, + "last_link_id": 139, "nodes": [ { "id": 3, @@ -36,7 +36,7 @@ "Node name for S&R": "PrimereVisualCKPT" }, "widgets_values": [ - "SDXL\\copaxTimelessxlSDXL1_v7.safetensors", + "BestAll\\photon_v1.safetensors", true, true ] @@ -207,9 +207,9 @@ "links": [ 17, 18, - 19, 20, - 34 + 34, + 137 ], "shape": 3, "slot_index": 0 @@ -219,7 +219,7 @@ "Node name for S&R": "PrimereSeed" }, "widgets_values": [ - -1, + 218876056720308, null, null, null @@ -291,8 +291,8 @@ "name": "VAE", "type": "VAE", "links": [ - 16, - 36 + 36, + 134 ], "shape": 3 }, @@ -494,8 +494,8 @@ "name": "WIDTH", "type": "INT", "links": [ - 22, - 28 + 28, + 135 ], "shape": 3, "slot_index": 0 @@ -504,8 +504,8 @@ "name": "HEIGHT", "type": "INT", "links": [ - 23, - 29 + 29, + 136 ], "shape": 3, "slot_index": 1 @@ -519,8 +519,8 @@ 768, true, "Horizontal", - false, - 634167927872988, + true, + 729604421095564, "randomize", false, 1.6, @@ -577,7 +577,7 @@ }, "widgets_values": [ "", - 817029395929541, + 281164421636985, "randomize" ] }, @@ -630,21 +630,21 @@ }, "widgets_values": [ "", - 467345014983569, + 54227952213564, "randomize" ] }, { - "id": 11, + "id": 39, "type": "PrimereLatentNoise", "pos": [ - 1755, - 368 + 1760, + 447 + ], + "size": [ + 332, + 471 ], - "size": { - "0": 315, - "1": 438 - }, "flags": {}, "order": 9, "mode": 0, @@ -652,13 +652,12 @@ { "name": "optional_vae", "type": "VAE", - "link": 16, - "slot_index": 0 + "link": 134 }, { "name": "width", "type": "INT", - "link": 22, + "link": 135, "widget": { "name": "width" } @@ -666,17 +665,17 @@ { "name": "height", "type": "INT", - "link": 23, + "link": 136, "widget": { "name": "height" } }, { - "name": "seed", + "name": "noise_seed", "type": "INT", - "link": 19, + "link": 137, "widget": { - "name": "seed" + "name": "noise_seed" } } ], @@ -685,14 +684,16 @@ "name": "LATENTS", "type": "LATENT", "links": [ - 31 + 138 ], "shape": 3 }, { "name": "PREVIEWS", "type": "IMAGE", - "links": null, + "links": [ + 139 + ], "shape": 3 } ], @@ -702,20 +703,23 @@ "widgets_values": [ 512, 512, - true, + false, "white", - true, + false, 1, 0.5, 1.5, - true, + false, 1, 0.8, 1.4, - 102306924483936, + 552044321990063, "randomize", + false, + "cpu", true, - "cpu" + 762455303042557, + "randomize" ] }, { @@ -778,19 +782,44 @@ "" ] }, + { + "id": 19, + "type": "PreviewImage", + "pos": [ + 1396, + 691 + ], + "size": { + "0": 334.67486572265625, + "1": 246 + }, + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 139 + } + ], + "properties": { + "Node name for S&R": "PreviewImage" + } + }, { "id": 14, "type": "PrimereCLIPEncoder", "pos": [ 2110, - 95 + 129 ], "size": { "0": 330, "1": 758 }, "flags": {}, - "order": 11, + "order": 12, "mode": 0, "inputs": [ { @@ -999,7 +1028,7 @@ "1": 234 }, "flags": {}, - "order": 12, + "order": 13, "mode": 0, "inputs": [ { @@ -1023,7 +1052,7 @@ { "name": "latent_image", "type": "LATENT", - "link": 31, + "link": 138, "slot_index": 3 }, { @@ -1050,7 +1079,7 @@ "Node name for S&R": "KSampler" }, "widgets_values": [ - 493544399204151, + 1098807145567755, "randomize", 20, 8, @@ -1071,7 +1100,7 @@ "1": 46 }, "flags": {}, - "order": 13, + "order": 14, "mode": 0, "inputs": [ { @@ -1113,7 +1142,7 @@ "1": 468.0492248535156 }, "flags": {}, - "order": 14, + "order": 15, "mode": 0, "inputs": [ { @@ -1248,14 +1277,6 @@ 0, "CHECKPOINT_NAME" ], - [ - 16, - 9, - 2, - 11, - 0, - "VAE" - ], [ 17, 10, @@ -1272,14 +1293,6 @@ 1, "INT" ], - [ - 19, - 10, - 0, - 11, - 3, - "INT" - ], [ 20, 10, @@ -1296,22 +1309,6 @@ 1, "STRING" ], - [ - 22, - 13, - 0, - 11, - 1, - "INT" - ], - [ - 23, - 13, - 1, - 11, - 2, - "INT" - ], [ 24, 9, @@ -1368,14 +1365,6 @@ 0, "MODEL" ], - [ - 31, - 11, - 0, - 15, - 3, - "LATENT" - ], [ 32, 14, @@ -1423,6 +1412,54 @@ 17, 0, "IMAGE" + ], + [ + 134, + 9, + 2, + 39, + 0, + "VAE" + ], + [ + 135, + 13, + 0, + 39, + 1, + "INT" + ], + [ + 136, + 13, + 1, + 39, + 2, + "INT" + ], + [ + 137, + 10, + 0, + 39, + 3, + "INT" + ], + [ + 138, + 39, + 0, + 15, + 3, + "LATENT" + ], + [ + 139, + 39, + 1, + 19, + 0, + "IMAGE" ] ], "groups": [], diff --git a/components/utility.py b/components/utility.py index c928480..728b84e 100644 --- a/components/utility.py +++ b/components/utility.py @@ -458,5 +458,124 @@ def img_resizer(image: torch.Tensor, width: int, height: int, interpolation_mode image = image.permute(0, 3, 1, 2) image = F.resize(image, (height, width), interpolation=interpolation_mode, antialias=True) image = image.permute(0, 2, 3, 1) + return image - return image \ No newline at end of file +def apply_variation_noise(latent_image, noise_device, variation_seed, variation_strength, mask=None): + latent_size = latent_image.size() + latent_size_1batch = [1, latent_size[1], latent_size[2], latent_size[3]] + + if noise_device == "cpu": + variation_generator = torch.manual_seed(variation_seed) + else: + torch.cuda.manual_seed(variation_seed) + variation_generator = None + + variation_latent = torch.randn(latent_size_1batch, dtype=latent_image.dtype, layout=latent_image.layout, generator=variation_generator, device=noise_device) + variation_noise = variation_latent.expand(latent_image.size()[0], -1, -1, -1) + + if variation_strength == 0: + return latent_image + elif mask is None: + result = (1 - variation_strength) * latent_image + variation_strength * variation_noise + else: + # this seems precision is not enough when variation_strength is 0.0 + result = (mask == 1).float() * ((1 - variation_strength) * latent_image + variation_strength * variation_noise * mask) + (mask == 0).float() * latent_image + + return result + +def prepare_noise(latent_image, seed, noise_inds=None, noise_device="cpu", incremental_seed_mode="comfy", variation_seed=None, variation_strength=None): + latent_size = latent_image.size() + latent_size_1batch = [1, latent_size[1], latent_size[2], latent_size[3]] + + if variation_strength is not None and variation_strength > 0 or incremental_seed_mode.startswith("variation str inc"): + if noise_device == "cpu": + variation_generator = torch.manual_seed(variation_seed) + else: + torch.cuda.manual_seed(variation_seed) + variation_generator = None + + variation_latent = torch.randn(latent_size_1batch, dtype=latent_image.dtype, layout=latent_image.layout, generator=variation_generator, device=noise_device) + else: + variation_latent = None + + def apply_variation(input_latent, strength_up=None): + if variation_latent is None: + return input_latent + else: + strength = variation_strength + + if strength_up is not None: + strength += strength_up + + variation_noise = variation_latent.expand(input_latent.size()[0], -1, -1, -1) + result = (1 - strength) * input_latent + strength * variation_noise + return result + + # method: incremental seed batch noise + if noise_inds is None and incremental_seed_mode == "incremental": + batch_cnt = latent_size[0] + + latents = None + for i in range(batch_cnt): + if noise_device == "cpu": + generator = torch.manual_seed(seed+i) + else: + torch.cuda.manual_seed(seed+i) + generator = None + + latent = torch.randn(latent_size_1batch, dtype=latent_image.dtype, layout=latent_image.layout, generator=generator, device=noise_device) + latent = apply_variation(latent) + + if latents is None: + latents = latent + else: + latents = torch.cat((latents, latent), dim=0) + + return latents + + # method: incremental variation batch noise + elif noise_inds is None and incremental_seed_mode.startswith("variation str inc"): + batch_cnt = latent_size[0] + + latents = None + for i in range(batch_cnt): + if noise_device == "cpu": + generator = torch.manual_seed(seed) + else: + torch.cuda.manual_seed(seed) + generator = None + + latent = torch.randn(latent_size_1batch, dtype=latent_image.dtype, layout=latent_image.layout, generator=generator, device=noise_device) + + step = float(incremental_seed_mode[18:]) + latent = apply_variation(latent, step*i) + + if latents is None: + latents = latent + else: + latents = torch.cat((latents, latent), dim=0) + + return latents + + # method: comfy batch noise + if noise_device == "cpu": + generator = torch.manual_seed(seed) + else: + torch.cuda.manual_seed(seed) + generator = None + + if noise_inds is None: + latents = torch.randn(latent_image.size(), dtype=latent_image.dtype, layout=latent_image.layout, generator=generator, device=noise_device) + latents = apply_variation(latents) + return latents + + unique_inds, inverse = np.unique(noise_inds, return_inverse=True) + noises = [] + for i in range(unique_inds[-1] + 1): + noise = torch.randn([1] + list(latent_image.size())[1:], dtype=latent_image.dtype, layout=latent_image.layout, generator=generator, device=noise_device) + if i in unique_inds: + noises.append(noise) + + noises = [noises[i] for i in inverse] + noises = torch.cat(noises, axis=0) + return noises \ No newline at end of file