diff --git a/README.md b/README.md index 87621fa..2f74ea5 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,38 @@ # StyleAligned for ComfyUI -Implementation of the [StyleAligned](https://style-aligned-gen.github.io/) paper for ComfyUI. +Implementation of the [StyleAligned](https://style-aligned-gen.github.io/) technique for ComfyUI. -This node allows you to apply a consistent style to all images in a batch; by default it will use the first image in the batch as the style reference, forcing all other images to be consistent with it. +This implementation is split into two different nodes, and does not require any additional models or dependencies. -![](resources/header.jpg) +#### StyleAligned Reference Sampler -_A batch of generations with the same parameters, with the node applied (left) and without (right)._ +This node replaces the KSampler, and lets you reference an existing latent as a style reference. In order to retrieve the latent, you will need to perform DDIM inversion; an example workflow for this is provided [here](resources/style_aligned_inversion.json). -In the next few days I plan on implementing the second feature of the paper - the ability to use another image as the style reference. +![](resources/reference_sampler.png) + +_Above, a reference image, and a batch of images generated using the prompt 'a robot' and the reference image shown as style input._ + +##### Parameters + +- `model`: The base model to patch. +- `share_norm`: Whether to share normalization across the batch. Defaults to `both`. Set to `group` or `layer` to only share group or layer normalization, respectively. +- `scale`: The scale at which to apply the style-alignment effect. Defaults to `1`. + +#### StyleAligned Batch Align + +Instead of referencing a single latent, this node aligns the style of the entire batch with the first image generated in the batch, effectively causing all images in the batch to be generated with the same style. + +![](resources/batch_align.jpg) + +_A batch of generations with the same parameters and the Batch Align node applied (left) and disabled (right)._ + +##### Parameters + +- `model`: The base model to patch. +- `share_norm`: Whether to share normalization across the batch. Defaults to `both`. Set to `group` or `layer` to only share group or layer normalization, respectively. +- `scale`: The scale at which to apply the style-alignment effect. Defaults to `1`. +- `batch_size`, `noise_seed`, `control_after_generate`, `cfg`: Identical to the standard `KSampler` parameters. ### Installation -Simply download or git clone this repository in `ComfyUI/custom_nodes/`. - -### Usage - -Use the example workflow from [here](resources/example_workflow.json). - -Or, simply add the `StyleAlignedPatch` node after `LoadCheckpoint`. - -### Parameters - -- `model`: Required, the base model to patch. -- `style_image`: (**not implemented yet!**) Optional, path to the latent to use as a style inference. If left blank, the first latent in the batch will be used, effectively making the output of the batch consistent. -- `share_norm`: Whether to share normalization across the batch. Defaults to `both`. Set to `group` or `layer` to only share group or layer normalization, respectively. -- `scale`: The scale at which to apply the style-alignment effect. Defaults to `1`. \ No newline at end of file +Simply download or git clone this repository in `ComfyUI/custom_nodes/`. Example workflows are included in `resources/`. \ No newline at end of file diff --git a/__init__.py b/__init__.py index b62acb5..ff7c0b5 100644 --- a/__init__.py +++ b/__init__.py @@ -1,12 +1,13 @@ from dataclasses import dataclass import torch import torch.nn as nn -from torch.nn import functional as nnf -import einops from comfy.model_patcher import ModelPatcher from comfy.ldm.modules.attention import optimized_attention, optimized_attention_masked import comfy.ops from typing import Optional, Union +import comfy.sample +import latent_preview +import comfy.utils T = torch.Tensor @@ -50,7 +51,7 @@ def concat_first(feat: T, dim=2, scale=1.0) -> T: return torch.cat((feat, feat_style), dim=dim) -def calc_mean_std(feat, eps: float = 1e-5) -> tuple[T, T]: +def calc_mean_std(feat, eps: float = 1e-5) -> "tuple[T, T]": feat_std = (feat.var(dim=-2, keepdims=True) + eps).sqrt() feat_mean = feat.mean(dim=-2, keepdims=True) return feat_mean, feat_std @@ -73,9 +74,8 @@ def sdpa(q: T, k: T, v: T, mask=None, heads: int = 8) -> T: class SharedAttentionProcessor: - def __init__(self, args: StyleAlignedArgs, scale: float, style_image: Optional[T]): + def __init__(self, args: StyleAlignedArgs, scale: float): self.args = args - self.ref_img = style_image self.scale = scale def __call__(self, q, k, v, extra_options): @@ -94,7 +94,7 @@ class SharedAttentionProcessor: def get_norm_layers( layer: nn.Module, - norm_layers_: dict[str, list[Union[nn.GroupNorm, nn.LayerNorm]]], + norm_layers_: "dict[str, list[Union[nn.GroupNorm, nn.LayerNorm]]]", share_layer_norm: bool, share_group_norm: bool, ): @@ -119,7 +119,7 @@ def register_norm_forward( def forward_(hidden_states: T) -> T: n = hidden_states.shape[-2] hidden_states = concat_first(hidden_states, dim=-2) - hidden_states = orig_forward(hidden_states) + hidden_states = orig_forward(hidden_states) # type: ignore return hidden_states[..., :n, :] norm_layer.forward = forward_ # type: ignore @@ -141,23 +141,133 @@ def register_shared_norm( ] -class StyleAlignedPatch: +SHARE_NORM_OPTIONS = ["both", "group", "layer", "disabled"] + + +class StyleAlignedReferenceSampler: @classmethod def INPUT_TYPES(cls): return { "required": { "model": ("MODEL",), - "share_norm": (["both", "group", "layer", "disabled"],), - "scale": ("FLOAT", {"default": 1, "min": 0, "max": 1.0, "step": 0.1}), - }, - "optional": { - "style_image": ("IMAGE",), + "share_norm": (SHARE_NORM_OPTIONS,), + "scale": ("FLOAT", {"default": 1, "min": 0, "max": 2.0, "step": 0.1}), + "batch_size": ("INT", {"default": 2, "min": 1, "max": 8, "step": 1}), + "noise_seed": ( + "INT", + {"default": 0, "min": 0, "max": 0xFFFFFFFFFFFFFFFF}, + ), + "cfg": ( + "FLOAT", + { + "default": 8.0, + "min": 0.0, + "max": 100.0, + "step": 0.1, + "round": 0.01, + }, + ), + "positive": ("CONDITIONING",), + "negative": ("CONDITIONING",), + "sampler": ("SAMPLER",), + "sigmas": ("SIGMAS",), + "ref_latent": ("LATENT",), }, } - RETURN_TYPES = ("MODEL",) + RETURN_TYPES = ("LATENT", "LATENT") + RETURN_NAMES = ("output", "denoised_output") FUNCTION = "patch" - CATEGORY = "custom_node_experiments" + CATEGORY = "style_aligned" + + def __init__(self) -> None: + self.args = StyleAlignedArgs() + + def patch( + self, + model: ModelPatcher, + share_norm: str, + scale: float, + batch_size: int, + noise_seed: int, + cfg: float, + positive: T, + negative: T, + sampler: T, + sigmas: T, + ref_latent: "dict[str, T]", + ) -> "tuple[dict, dict]": + m = model.clone() + + # Concat batch with style latent + style_latent_tensor = ref_latent["samples"] + height, width = style_latent_tensor.shape[-2:] + latent_t = torch.zeros( + [batch_size, 4, height, width], device=ref_latent["samples"].device + ) + latent = {"samples": latent_t} + noise = comfy.sample.prepare_noise(latent_t, noise_seed) + + latent_t = torch.cat((style_latent_tensor, latent_t), dim=0) + ref_noise = torch.zeros_like(noise[0]).unsqueeze(0) + noise = torch.cat((ref_noise, noise), dim=0) + + x0_output = {} + callback = latent_preview.prepare_callback( + model, sigmas.shape[-1] - 1, x0_output + ) + + # Register shared norms + share_group_norm = share_norm in ["group", "both"] + share_layer_norm = share_norm in ["layer", "both"] + register_shared_norm(model, share_group_norm, share_layer_norm) + + # Patch cross attn + m.set_model_attn1_patch(SharedAttentionProcessor(self.args, scale)) + + disable_pbar = not comfy.utils.PROGRESS_BAR_ENABLED + samples = comfy.sample.sample_custom( + m, + noise, + cfg, + sampler, + sigmas, + positive, + negative, + latent_t, + callback=callback, + disable_pbar=disable_pbar, + seed=noise_seed, + ) + + # remove reference image + samples = samples[1:] + + out = latent.copy() + out["samples"] = samples + if "x0" in x0_output: + out_denoised = latent.copy() + x0 = x0_output["x0"][1:] + out_denoised["samples"] = m.model.process_latent_out(x0.cpu()) + else: + out_denoised = out + return (out, out_denoised) + + +class StyleAlignedBatchAlign: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "model": ("MODEL",), + "share_norm": (SHARE_NORM_OPTIONS,), + "scale": ("FLOAT", {"default": 1, "min": 0, "max": 1.0, "step": 0.1}), + } + } + + RETURN_TYPES = ("MODEL",) + FUNCTION = "patch" + CATEGORY = "style_aligned" def __init__(self) -> None: self.args = StyleAlignedArgs() @@ -167,16 +277,22 @@ class StyleAlignedPatch: model: ModelPatcher, share_norm: str, scale: float, - style_image: Optional[T] = None, ): m = model.clone() share_group_norm = share_norm in ["group", "both"] share_layer_norm = share_norm in ["layer", "both"] register_shared_norm(model, share_group_norm, share_layer_norm) - m.set_model_attn1_patch(SharedAttentionProcessor(self.args, scale, style_image)) + m.set_model_attn1_patch(SharedAttentionProcessor(self.args, scale)) return (m,) NODE_CLASS_MAPPINGS = { - "StyleAlignedPatch": StyleAlignedPatch, + "StyleAlignedReferenceSampler": StyleAlignedReferenceSampler, + "StyleAlignedBatchAlign": StyleAlignedBatchAlign, +} + + +NODE_DISPLAY_NAME_MAPPINGS = { + "StyleAlignedReferenceSampler": "StyleAligned Reference Sampler", + "StyleAlignedBatchAlign": "StyleAligned Batch Align", } diff --git a/resources/header.jpg b/resources/batch_align.jpg similarity index 100% rename from resources/header.jpg rename to resources/batch_align.jpg diff --git a/resources/reference_sampler.png b/resources/reference_sampler.png new file mode 100644 index 0000000..45633f8 Binary files /dev/null and b/resources/reference_sampler.png differ diff --git a/resources/style_aligned_inversion.json b/resources/style_aligned_inversion.json new file mode 100644 index 0000000..01473fa --- /dev/null +++ b/resources/style_aligned_inversion.json @@ -0,0 +1,980 @@ +{ + "last_node_id": 45, + "last_link_id": 148, + "nodes": [ + { + "id": 13, + "type": "FlipSigmas", + "pos": [ + 81, + 907 + ], + "size": { + "0": 210, + "1": 26 + }, + "flags": {}, + "order": 9, + "mode": 0, + "inputs": [ + { + "name": "sigmas", + "type": "SIGMAS", + "link": 14, + "slot_index": 0 + } + ], + "outputs": [ + { + "name": "SIGMAS", + "type": "SIGMAS", + "links": [ + 13 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "FlipSigmas" + } + }, + { + "id": 20, + "type": "VAEEncode", + "pos": [ + 424, + 1105 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 11, + "mode": 0, + "inputs": [ + { + "name": "pixels", + "type": "IMAGE", + "link": 43, + "slot_index": 0 + }, + { + "name": "vae", + "type": "VAE", + "link": 22 + } + ], + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 25 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "VAEEncode" + } + }, + { + "id": 23, + "type": "ImageScale", + "pos": [ + -128, + 1321 + ], + "size": { + "0": 315, + "1": 130 + }, + "flags": {}, + "order": 8, + "mode": 0, + "inputs": [ + { + "name": "image", + "type": "IMAGE", + "link": 42 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 43 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "ImageScale" + }, + "widgets_values": [ + "nearest-exact", + 512, + 512, + "center" + ] + }, + { + "id": 38, + "type": "EmptyLatentImage", + "pos": [ + 988, + 145 + ], + "size": { + "0": 315, + "1": 106 + }, + "flags": {}, + "order": 0, + "mode": 0, + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 122 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "EmptyLatentImage" + }, + "widgets_values": [ + 512, + 512, + 4 + ] + }, + { + "id": 4, + "type": "CheckpointLoaderSimple", + "pos": [ + -305, + 251 + ], + "size": { + "0": 315, + "1": 98 + }, + "flags": {}, + "order": 1, + "mode": 0, + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 20, + 24 + ], + "slot_index": 0 + }, + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 3, + 5 + ], + "slot_index": 1 + }, + { + "name": "VAE", + "type": "VAE", + "links": [ + 8, + 16, + 22, + 117 + ], + "slot_index": 2 + } + ], + "properties": { + "Node name for S&R": "CheckpointLoaderSimple" + }, + "widgets_values": [ + "sd_xl_base_1.0.safetensors" + ] + }, + { + "id": 36, + "type": "VAEDecode", + "pos": [ + 1446, + 84 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 122, + "slot_index": 0 + }, + { + "name": "vae", + "type": "VAE", + "link": 117 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 118 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "VAEDecode" + } + }, + { + "id": 37, + "type": "PreviewImage", + "pos": [ + 1683, + 45 + ], + "size": { + "0": 210, + "1": 246 + }, + "flags": {}, + "order": 10, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 118 + } + ], + "properties": { + "Node name for S&R": "PreviewImage" + } + }, + { + "id": 17, + "type": "VAEDecode", + "pos": [ + 1313, + 1013 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 14, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 136, + "slot_index": 0 + }, + { + "name": "vae", + "type": "VAE", + "link": 16 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 135 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "VAEDecode" + } + }, + { + "id": 43, + "type": "PreviewImage", + "pos": [ + 1604, + 1039 + ], + "size": { + "0": 210, + "1": 246 + }, + "flags": {}, + "order": 16, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 135 + } + ], + "properties": { + "Node name for S&R": "PreviewImage" + } + }, + { + "id": 8, + "type": "VAEDecode", + "pos": [ + 1436, + 449 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 15, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 144 + }, + { + "name": "vae", + "type": "VAE", + "link": 8 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 10 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "VAEDecode" + } + }, + { + "id": 15, + "type": "SamplerCustom", + "pos": [ + 655, + 846 + ], + "size": { + "0": 355.20001220703125, + "1": 442 + }, + "flags": {}, + "order": 12, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 20 + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 60 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 65, + "slot_index": 2 + }, + { + "name": "sampler", + "type": "SAMPLER", + "link": 21, + "slot_index": 3 + }, + { + "name": "sigmas", + "type": "SIGMAS", + "link": 13 + }, + { + "name": "latent_image", + "type": "LATENT", + "link": 25 + } + ], + "outputs": [ + { + "name": "output", + "type": "LATENT", + "links": [ + 143 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "denoised_output", + "type": "LATENT", + "links": [ + 136 + ], + "shape": 3, + "slot_index": 1 + } + ], + "properties": { + "Node name for S&R": "SamplerCustom" + }, + "widgets_values": [ + false, + 156680208709678, + "fixed", + 1.1 + ] + }, + { + "id": 21, + "type": "LoadImage", + "pos": [ + 1891, + 1018 + ], + "size": { + "0": 480.172607421875, + "1": 588.647705078125 + }, + "flags": {}, + "order": 2, + "mode": 0, + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 42 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "MASK", + "type": "MASK", + "links": null, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "0_1-1.png", + "image" + ] + }, + { + "id": 10, + "type": "PreviewImage", + "pos": [ + 1893, + 452 + ], + "size": { + "0": 485.727294921875, + "1": 517.061767578125 + }, + "flags": {}, + "order": 17, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 10 + } + ], + "properties": { + "Node name for S&R": "PreviewImage" + } + }, + { + "id": 45, + "type": "StyleAlignedReferenceSampler", + "pos": [ + 1058, + 514 + ], + "size": { + "0": 330, + "1": 278 + }, + "flags": {}, + "order": 13, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": null + }, + { + "name": "positive", + "type": "CONDITIONING", + "link": 145 + }, + { + "name": "negative", + "type": "CONDITIONING", + "link": 146 + }, + { + "name": "sampler", + "type": "SAMPLER", + "link": 148 + }, + { + "name": "sigmas", + "type": "SIGMAS", + "link": 147 + }, + { + "name": "ref_latent", + "type": "LATENT", + "link": 143, + "slot_index": 5 + } + ], + "outputs": [ + { + "name": "output", + "type": "LATENT", + "links": null, + "shape": 3 + }, + { + "name": "denoised_output", + "type": "LATENT", + "links": [ + 144 + ], + "shape": 3, + "slot_index": 1 + } + ], + "properties": { + "Node name for S&R": "StyleAlignedReferenceSampler" + }, + "widgets_values": [ + "both", + 1, + 2, + 0, + "randomize", + 8 + ] + }, + { + "id": 7, + "type": "CLIPTextEncode", + "pos": [ + 168, + 643 + ], + "size": { + "0": 425.27801513671875, + "1": 180.6060791015625 + }, + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 5 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 65, + 146 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "" + ] + }, + { + "id": 6, + "type": "CLIPTextEncode", + "pos": [ + 368, + 159 + ], + "size": { + "0": 422.84503173828125, + "1": 164.31304931640625 + }, + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [ + { + "name": "clip", + "type": "CLIP", + "link": 3 + } + ], + "outputs": [ + { + "name": "CONDITIONING", + "type": "CONDITIONING", + "links": [ + 60, + 145 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "CLIPTextEncode" + }, + "widgets_values": [ + "Scene from le heine, in full colour, Kodak, soho, London, night, Neo - noir, noir, mist, moody\n\n" + ] + }, + { + "id": 19, + "type": "KSamplerSelect", + "pos": [ + 471, + 387 + ], + "size": { + "0": 315, + "1": 58 + }, + "flags": {}, + "order": 3, + "mode": 0, + "outputs": [ + { + "name": "SAMPLER", + "type": "SAMPLER", + "links": [ + 21, + 148 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "KSamplerSelect" + }, + "widgets_values": [ + "ddim" + ] + }, + { + "id": 16, + "type": "BasicScheduler", + "pos": [ + 471, + 524 + ], + "size": { + "0": 315, + "1": 82 + }, + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "name": "model", + "type": "MODEL", + "link": 24, + "slot_index": 0 + } + ], + "outputs": [ + { + "name": "SIGMAS", + "type": "SIGMAS", + "links": [ + 14, + 147 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "BasicScheduler" + }, + "widgets_values": [ + "ddim_uniform", + 32 + ] + } + ], + "links": [ + [ + 3, + 4, + 1, + 6, + 0, + "CLIP" + ], + [ + 5, + 4, + 1, + 7, + 0, + "CLIP" + ], + [ + 8, + 4, + 2, + 8, + 1, + "VAE" + ], + [ + 10, + 8, + 0, + 10, + 0, + "IMAGE" + ], + [ + 13, + 13, + 0, + 15, + 4, + "SIGMAS" + ], + [ + 14, + 16, + 0, + 13, + 0, + "SIGMAS" + ], + [ + 16, + 4, + 2, + 17, + 1, + "VAE" + ], + [ + 20, + 4, + 0, + 15, + 0, + "MODEL" + ], + [ + 21, + 19, + 0, + 15, + 3, + "SAMPLER" + ], + [ + 22, + 4, + 2, + 20, + 1, + "VAE" + ], + [ + 24, + 4, + 0, + 16, + 0, + "MODEL" + ], + [ + 25, + 20, + 0, + 15, + 5, + "LATENT" + ], + [ + 42, + 21, + 0, + 23, + 0, + "IMAGE" + ], + [ + 43, + 23, + 0, + 20, + 0, + "IMAGE" + ], + [ + 60, + 6, + 0, + 15, + 1, + "CONDITIONING" + ], + [ + 65, + 7, + 0, + 15, + 2, + "CONDITIONING" + ], + [ + 117, + 4, + 2, + 36, + 1, + "VAE" + ], + [ + 118, + 36, + 0, + 37, + 0, + "IMAGE" + ], + [ + 122, + 38, + 0, + 36, + 0, + "LATENT" + ], + [ + 135, + 17, + 0, + 43, + 0, + "IMAGE" + ], + [ + 136, + 15, + 1, + 17, + 0, + "LATENT" + ], + [ + 143, + 15, + 0, + 45, + 5, + "LATENT" + ], + [ + 144, + 45, + 1, + 8, + 0, + "LATENT" + ], + [ + 145, + 6, + 0, + 45, + 1, + "CONDITIONING" + ], + [ + 146, + 7, + 0, + 45, + 2, + "CONDITIONING" + ], + [ + 147, + 16, + 0, + 45, + 4, + "SIGMAS" + ], + [ + 148, + 19, + 0, + 45, + 3, + "SAMPLER" + ] + ], + "groups": [], + "config": {}, + "extra": {}, + "version": 0.4 +} \ No newline at end of file diff --git a/resources/example_workflow.json b/resources/style_aligned_within_batch.json similarity index 86% rename from resources/example_workflow.json rename to resources/style_aligned_within_batch.json index fced8ee..8c9eadd 100644 --- a/resources/example_workflow.json +++ b/resources/style_aligned_within_batch.json @@ -1,159 +1,13 @@ { - "last_node_id": 12, + "last_node_id": 10, "last_link_id": 12, "nodes": [ - { - "id": 4, - "type": "CheckpointLoaderSimple", - "pos": [ - 26, - 474 - ], - "size": { - "0": 315, - "1": 98 - }, - "flags": {}, - "order": 0, - "mode": 0, - "outputs": [ - { - "name": "MODEL", - "type": "MODEL", - "links": [ - 11 - ], - "slot_index": 0 - }, - { - "name": "CLIP", - "type": "CLIP", - "links": [ - 3, - 5 - ], - "slot_index": 1 - }, - { - "name": "VAE", - "type": "VAE", - "links": [ - 8 - ], - "slot_index": 2 - } - ], - "properties": { - "Node name for S&R": "CheckpointLoaderSimple" - }, - "widgets_values": [ - "sd_xl_base_1.0.safetensors" - ] - }, - { - "id": 5, - "type": "EmptyLatentImage", - "pos": [ - 455, - 645 - ], - "size": { - "0": 315, - "1": 106 - }, - "flags": {}, - "order": 1, - "mode": 0, - "outputs": [ - { - "name": "LATENT", - "type": "LATENT", - "links": [ - 2 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "EmptyLatentImage" - }, - "widgets_values": [ - 512, - 512, - 4 - ] - }, - { - "id": 8, - "type": "VAEDecode", - "pos": [ - 1247, - 7 - ], - "size": { - "0": 210, - "1": 46 - }, - "flags": {}, - "order": 6, - "mode": 0, - "inputs": [ - { - "name": "samples", - "type": "LATENT", - "link": 7 - }, - { - "name": "vae", - "type": "VAE", - "link": 8 - } - ], - "outputs": [ - { - "name": "IMAGE", - "type": "IMAGE", - "links": [ - 10 - ], - "slot_index": 0 - } - ], - "properties": { - "Node name for S&R": "VAEDecode" - } - }, - { - "id": 10, - "type": "PreviewImage", - "pos": [ - 1509, - 110 - ], - "size": { - "0": 481.1595764160156, - "1": 565.72705078125 - }, - "flags": {}, - "order": 7, - "mode": 0, - "inputs": [ - { - "name": "images", - "type": "IMAGE", - "link": 10 - } - ], - "properties": { - "Node name for S&R": "PreviewImage" - } - }, { "id": 7, "type": "CLIPTextEncode", "pos": [ - 427, - 426 + 413, + 389 ], "size": { "0": 425.27801513671875, @@ -183,15 +37,15 @@ "Node name for S&R": "CLIPTextEncode" }, "widgets_values": [ - "text, watermark, low quality, ugly" + "text, watermark" ] }, { "id": 6, "type": "CLIPTextEncode", "pos": [ - 410, - -74 + 415, + 186 ], "size": { "0": 422.84503173828125, @@ -221,19 +75,166 @@ "Node name for S&R": "CLIPTextEncode" }, "widgets_values": [ - "a toy train, macro photo, high quality, centered, zoom lens" + "beautiful scenery nature glass bottle landscape, , purple galaxy bottle," ] }, + { + "id": 4, + "type": "CheckpointLoaderSimple", + "pos": [ + 26, + 474 + ], + "size": { + "0": 315, + "1": 98 + }, + "flags": {}, + "order": 0, + "mode": 0, + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "links": [ + 10 + ], + "slot_index": 0 + }, + { + "name": "CLIP", + "type": "CLIP", + "links": [ + 3, + 5 + ], + "slot_index": 1 + }, + { + "name": "VAE", + "type": "VAE", + "links": [ + 8 + ], + "slot_index": 2 + } + ], + "properties": { + "Node name for S&R": "CheckpointLoaderSimple" + }, + "widgets_values": [ + "sd_xl_base_1.0.safetensors" + ] + }, + { + "id": 9, + "type": "SaveImage", + "pos": [ + 1896, + 346 + ], + "size": [ + 334.20353016404806, + 384.790212276488 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 9 + } + ], + "properties": {}, + "widgets_values": [ + "ComfyUI" + ] + }, + { + "id": 5, + "type": "EmptyLatentImage", + "pos": [ + 606, + 681 + ], + "size": { + "0": 315, + "1": 106 + }, + "flags": {}, + "order": 1, + "mode": 0, + "outputs": [ + { + "name": "LATENT", + "type": "LATENT", + "links": [ + 12 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "EmptyLatentImage" + }, + "widgets_values": [ + 512, + 512, + 4 + ] + }, + { + "id": 8, + "type": "VAEDecode", + "pos": [ + 1696, + 182 + ], + "size": { + "0": 210, + "1": 46 + }, + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": 7 + }, + { + "name": "vae", + "type": "VAE", + "link": 8 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 9 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "VAEDecode" + } + }, { "id": 3, "type": "KSampler", "pos": [ - 955, - 340 + 1376, + 411 ], "size": { "0": 315, - "1": 474 + "1": 262 }, "flags": {}, "order": 5, @@ -242,7 +243,7 @@ { "name": "model", "type": "MODEL", - "link": 12 + "link": 11 }, { "name": "positive", @@ -257,7 +258,7 @@ { "name": "latent_image", "type": "LATENT", - "link": 2 + "link": 12 } ], "outputs": [ @@ -274,25 +275,25 @@ "Node name for S&R": "KSampler" }, "widgets_values": [ - 156680208709677, + 122740602030855, "fixed", - 32, - 7, - "uni_pc", - "sgm_uniform", + 20, + 8, + "euler", + "normal", 1 ] }, { - "id": 11, - "type": "StyleAlignedPatch", + "id": 10, + "type": "StyleAlignedBatchAlign", "pos": [ - 476, - 191 + 923, + 317 ], "size": { - "0": 216.59999084472656, - "1": 102 + "0": 315, + "1": 82 }, "flags": {}, "order": 2, @@ -301,12 +302,7 @@ { "name": "model", "type": "MODEL", - "link": 11 - }, - { - "name": "style_image", - "type": "IMAGE", - "link": null + "link": 10 } ], "outputs": [ @@ -314,14 +310,14 @@ "name": "MODEL", "type": "MODEL", "links": [ - 12 + 11 ], "shape": 3, "slot_index": 0 } ], "properties": { - "Node name for S&R": "StyleAlignedPatch" + "Node name for S&R": "StyleAlignedBatchAlign" }, "widgets_values": [ "both", @@ -330,14 +326,6 @@ } ], "links": [ - [ - 2, - 5, - 0, - 3, - 3, - "LATENT" - ], [ 3, 4, @@ -387,28 +375,36 @@ "VAE" ], [ - 10, + 9, 8, 0, - 10, + 9, 0, "IMAGE" ], [ - 11, + 10, 4, 0, + 10, + 0, + "MODEL" + ], + [ 11, + 10, + 0, + 3, 0, "MODEL" ], [ 12, - 11, + 5, 0, 3, - 0, - "MODEL" + 3, + "LATENT" ] ], "groups": [],