Add BlehPlug and BlehDisableNoise.

Increase the range of upscale/downscale options in BlehDeepShrink.
This commit is contained in:
blepping
2024-04-23 20:09:37 -06:00
parent b03e824842
commit 01ca557741
6 changed files with 111 additions and 42 deletions
+9 -1
View File
@@ -10,7 +10,7 @@ A ComfyUI nodes collection... eventually.
4. Allow discarding penultimate sigma (look for the `BlehDiscardPenultimateSigma` node). This can be useful if you find certain samplers are ruining your image by spewing a bunch of noise into it at the very end (usually only an issue with `dpm2 a` or SDE samplers).
5. Allow more conveniently switching between samplers during sampling (look for the [BlehInsaneChainSampler](#blehinsanechainsampler) node).
6. Apply arbitrary model patches at an interval and/or for a percentage of sampling (look for the [BlehModelPatchConditional](#blehmodelpatchconditional) node).
7. Ensure a seed is set even when `add_noise` is turned off in a sampler. Yes, that's right: if you don't have `add_noise` enabled _no_ seed gets set for samplers like `euler_a` and it's not possible to reproduce generations. (look for the [BlehForceSeedSampler](#blehforceseedsampler) node)
7. Ensure a seed is set even when `add_noise` is turned off in a sampler. Yes, that's right: if you don't have `add_noise` enabled _no_ seed gets set for samplers like `euler_a` and it's not possible to reproduce generations. (look for the [BlehForceSeedSampler](#blehforceseedsampler) node). For `SamplerCustomAdvanced` you can use `BlehDisableNoise` to accomplish the same thing.
8. Allows swapping to a refiner model at a predefined time (look for the [BlehRefinerAfter](#blehrefinerafter) node).
9. Allow defining arbitrary model patches (look for the [BlehBlockOps](#blehblockops) node).
@@ -102,6 +102,14 @@ This is basically the same as chaining a bunch of samplers together and manually
Currently, the way ComfyUI's advanced and custom samplers work is if you turn off `add_noise` _no_ global RNG seed gets set. Samplers like `euler_a` use this (SDE samplers use a different RNG method and aren't subject to this issue). Anyway, the upshot is you will get a different generation every time regardless of what the seed is set to. This node simply wraps another sampler and ensures that the seed gets set.
### BlehDisableNoise
Basically the same idea as `BlehForceSeedSampler`, however it is usable with `SamplerCustomAdvanced`.
### BlehPlug
You can connect this node to any input and it will be the same as if the input had no connection. Why is this useful? It's mainly for [Use Everywhere](https://github.com/chrisgoringe/cg-use-everywhere) — sometimes it's desirable to leave an input unconnected, but if you have Use Everywhere broadcasting an output it can be inconvenient. Just shove a plug in those inputs.
### BlehRefinerAfter
+4 -2
View File
@@ -8,17 +8,19 @@ if settings.SETTINGS.btp_enabled:
from .py.nodes import (
deepShrink,
hyperTile,
misc,
modelPatchConditional,
ops,
refinerAfter,
samplers,
sigmas,
)
NODE_CLASS_MAPPINGS = {
"BlehBlockOps": ops.BlehBlockOps,
"BlehDeepShrink": deepShrink.DeepShrinkBleh,
"BlehDiscardPenultimateSigma": sigmas.DiscardPenultimateSigma,
"BlehDiscardPenultimateSigma": misc.DiscardPenultimateSigma,
"BlehDisableNoise": misc.BlehDisableNoise,
"BlehPlug": misc.BlehPlug,
"BlehForceSeedSampler": samplers.BlehForceSeedSampler,
"BlehHyperTile": hyperTile.HyperTileBleh,
"BlehInsaneChainSampler": samplers.BlehInsaneChainSampler,
+5
View File
@@ -2,6 +2,11 @@
Note, only relatively significant changes to user-visible functionality will be included here. Most recent changes at the top.
## 20240423
* Added `BlehPlug` and `BlehDisableNoise` (see README for usage and description).
* Increased the available upscale/downscale types for `BlehDeepShrink`.
## 20240412
* Added `BlehBlockOps` and `BlehLatentOps` nodes.
+11 -18
View File
@@ -2,8 +2,7 @@
import bisect
import torch
from comfy.utils import bislerp
from .. import latent_utils # noqa: TID252
class DeepShrinkBleh:
@@ -47,8 +46,8 @@ class DeepShrinkBleh:
{"default": 0.35, "min": 0.0, "max": 1.0, "step": 0.001},
),
"downscale_after_skip": ("BOOLEAN", {"default": True}),
"downscale_method": (cls.upscale_methods,),
"upscale_method": (cls.upscale_methods,),
"downscale_method": (latent_utils.UPSCALE_METHODS,),
"upscale_method": (latent_utils.UPSCALE_METHODS,),
"antialias_downscale": ("BOOLEAN", {"default": False}),
"antialias_upscale": ("BOOLEAN", {"default": False}),
},
@@ -135,29 +134,23 @@ class DeepShrinkBleh:
)
if scaled_scale >= 0.98 or width >= orig_width or height >= orig_height:
return h
if downscale_method == "bislerp":
return bislerp(h, width, height)
return torch.nn.functional.interpolate(
return latent_utils.scale_samples(
h,
size=(height, width),
width,
height,
mode=downscale_method,
antialias=antialias_downscale,
antialias_size=3 if antialias_downscale else 0,
)
def output_block_patch(h, hsp, _transformer_options):
if h.shape[2] == hsp.shape[2]:
return h, hsp
if upscale_method == "bislerp":
return bislerp(
h,
hsp.shape[-1],
hsp.shape[-2],
), hsp
return torch.nn.functional.interpolate(
return latent_utils.scale_samples(
h,
size=(hsp.shape[-2], hsp.shape[-1]),
hsp.shape[-1],
hsp.shape[-2],
mode=upscale_method,
antialias=antialias_upscale,
antialias_size=3 if antialias_upscale else 0,
), hsp
m = model.clone()
+82
View File
@@ -0,0 +1,82 @@
import random
import torch
class DiscardPenultimateSigma:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"enabled": ("BOOLEAN", {"default": True}),
"sigmas": ("SIGMAS", {"forceInput": True}),
},
}
FUNCTION = "go"
RETURN_TYPES = ("SIGMAS",)
CATEGORY = "sampling/custom_sampling/sigmas"
def go(self, enabled, sigmas):
if not enabled or len(sigmas) < 2:
return (sigmas,)
return (torch.cat((sigmas[:-2], sigmas[-1:])),)
class SeededDisableNoise:
def __init__(self, seed):
self.seed = seed
def generate_noise(self, latent):
samples = latent["samples"]
torch.manual_seed(self.seed)
random.seed(self.seed) # For good measure.
return torch.zeros(
samples.shape,
dtype=samples.dtype,
layout=samples.layout,
device="cpu",
)
class BlehDisableNoise:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"noise_seed": (
"INT",
{"default": 0, "min": 0, "max": 0xFFFFFFFFFFFFFFFF},
),
},
}
def go(self, noise_seed):
return (SeededDisableNoise(noise_seed),)
RETURN_TYPES = ("NOISE",)
FUNCTION = "go"
CATEGORY = "sampling/custom_sampling/noise"
class Wildcard(str):
__slots__ = ()
def __ne__(self, _unused):
return False
class BlehPlug:
WILDCARD = Wildcard("*")
@classmethod
def INPUT_TYPES(cls):
return {}
def go(self):
return (None,)
RETURN_TYPES = (WILDCARD,)
FUNCTION = "go"
OUTPUT_NODE = False
CATEGORY = "hacks"
-21
View File
@@ -1,21 +0,0 @@
import torch
class DiscardPenultimateSigma:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"enabled": ("BOOLEAN", {"default": True}),
"sigmas": ("SIGMAS", {"forceInput": True}),
},
}
FUNCTION = "go"
RETURN_TYPES = ("SIGMAS",)
CATEGORY = "sampling/custom_sampling/sigmas"
def go(self, enabled, sigmas):
if not enabled or len(sigmas) < 2:
return (sigmas,)
return (torch.cat((sigmas[:-2], sigmas[-1:])),)