3v324v23's picture
lfs
1e3b872
import numpy as np
import torch
def channels_layer(images, channels, function):
if channels == "rgb":
img = images[:, :, :, :3]
elif channels == "rgba":
img = images[:, :, :, :4]
elif channels == "rg":
img = images[:, :, :, [0, 1]]
elif channels == "rb":
img = images[:, :, :, [0, 2]]
elif channels == "ra":
img = images[:, :, :, [0, 3]]
elif channels == "gb":
img = images[:, :, :, [1, 2]]
elif channels == "ga":
img = images[:, :, :, [1, 3]]
elif channels == "ba":
img = images[:, :, :, [2, 3]]
elif channels == "r":
img = images[:, :, :, 0]
elif channels == "g":
img = images[:, :, :, 1]
elif channels == "b":
img = images[:, :, :, 2]
elif channels == "a":
img = images[:, :, :, 3]
else:
raise ValueError("Unsupported channels")
result = torch.from_numpy(function(img.numpy()))
if channels == "rgb":
images[:, :, :, :3] = result
elif channels == "rgba":
images[:, :, :, :4] = result
elif channels == "rg":
images[:, :, :, [0, 1]] = result
elif channels == "rb":
images[:, :, :, [0, 2]] = result
elif channels == "ra":
images[:, :, :, [0, 3]] = result
elif channels == "gb":
images[:, :, :, [1, 2]] = result
elif channels == "ga":
images[:, :, :, [1, 3]] = result
elif channels == "ba":
images[:, :, :, [2, 3]] = result
elif channels == "r":
images[:, :, :, 0] = result
elif channels == "g":
images[:, :, :, 1] = result
elif channels == "b":
images[:, :, :, 2] = result
elif channels == "a":
images[:, :, :, 3] = result
return images
class ImageNoiseBeta:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
"a": ("INT", {
"default": 1,
"min": 1,
}),
"b": ("INT", {
"default": 1,
"min": 1,
}),
"monochromatic": (["false", "true"],),
"invert": (["false", "true"],),
"channels": (["rgb", "rgba", "rg", "rb", "ra", "gb", "ga", "ba", "r", "g", "b", "a"],),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "node"
CATEGORY = "image/noise"
def noise(self, images, a, b, monochromatic, invert):
if monochromatic and images.shape[3] > 1:
noise = np.random.beta(a, b, images.shape[:3])
else:
noise = np.random.beta(a, b, images.shape)
if monochromatic and images.shape[3] > 1:
noise = noise[..., np.newaxis].repeat(images.shape[3], -1)
if invert:
noise = images - noise
else:
noise = images + noise
noise = noise.astype(images.dtype)
return noise
def node(self, images, a, b, monochromatic, invert, channels):
tensor = images.clone().detach()
monochromatic = True if monochromatic == "true" else False
invert = True if invert == "true" else False
return (channels_layer(tensor, channels, lambda x: self.noise(
x, a, b, monochromatic, invert
)),)
class ImageNoiseBinomial:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
"n": ("INT", {
"default": 128,
"min": 1,
"max": 255,
}),
"p": ("FLOAT", {
"default": 0.5,
"max": 1.0,
"step": 0.01
}),
"monochromatic": (["false", "true"],),
"invert": (["false", "true"],),
"channels": (["rgb", "rgba", "rg", "rb", "ra", "gb", "ga", "ba", "r", "g", "b", "a"],),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "node"
CATEGORY = "image/noise"
def noise(self, images, n, p, monochromatic, invert):
if monochromatic and images.shape[3] > 1:
noise = np.random.binomial(n, p, images.shape[:3])
else:
noise = np.random.binomial(n, p, images.shape)
noise = noise.astype(images.dtype)
noise /= 255
if monochromatic and images.shape[3] > 1:
noise = noise[..., np.newaxis].repeat(images.shape[3], -1)
if invert:
noise = images - noise
else:
noise = images + noise
noise = np.clip(noise, 0.0, 1.0)
return noise
def node(self, images, n, p, monochromatic, invert, channels):
tensor = images.clone().detach()
monochromatic = True if monochromatic == "true" else False
invert = True if invert == "true" else False
return (channels_layer(tensor, channels, lambda x: self.noise(
x, n, p, monochromatic, invert
)),)
class ImageNoiseBytes:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
"monochromatic": (["false", "true"],),
"invert": (["false", "true"],),
"channels": (["rgb", "rgba", "rg", "rb", "ra", "gb", "ga", "ba", "r", "g", "b", "a"],),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "node"
CATEGORY = "image/noise"
def noise(self, images, monochromatic, invert):
if monochromatic and images.shape[3] > 1:
noise = np.random.bytes(np.prod(images.shape[:3]))
noise = np.frombuffer(noise, np.uint8)
noise = np.reshape(noise, images.shape[:3])
else:
noise = np.random.bytes(np.prod(images.shape))
noise = np.frombuffer(noise, np.uint8)
noise = np.reshape(noise, images.shape)
noise = noise.astype(images.dtype)
noise /= 255
if monochromatic and images.shape[3] > 1:
noise = noise[..., np.newaxis].repeat(images.shape[3], -1)
if invert:
noise = images - noise
else:
noise = images + noise
noise = np.clip(noise, 0.0, 1.0)
return noise
def node(self, images, monochromatic, invert, channels):
tensor = images.clone().detach()
monochromatic = True if monochromatic == "true" else False
invert = True if invert == "true" else False
return (channels_layer(tensor, channels, lambda x: self.noise(
x, monochromatic, invert
)),)
class ImageNoiseGaussian:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"images": ("IMAGE",),
"strength": ("FLOAT", {
"default": 0.5,
"step": 0.01
}),
"monochromatic": (["false", "true"],),
"invert": (["false", "true"],),
"channels": (["rgb", "rgba", "rg", "rb", "ra", "gb", "ga", "ba", "r", "g", "b", "a"],),
},
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "node"
CATEGORY = "image/noise"
def noise(self, images, strength, monochromatic, invert):
if monochromatic and images.shape[3] > 1:
noise = np.random.normal(0, 1, images.shape[:3])
else:
noise = np.random.normal(0, 1, images.shape)
noise = np.abs(noise)
noise /= noise.max()
if monochromatic and images.shape[3] > 1:
noise = noise[..., np.newaxis].repeat(images.shape[3], -1)
if invert:
noise = images - noise * strength
else:
noise = images + noise * strength
noise = np.clip(noise, 0.0, 1.0)
noise = noise.astype(images.dtype)
return noise
def node(self, images, strength, monochromatic, invert, channels):
tensor = images.clone().detach()
monochromatic = True if monochromatic == "true" else False
invert = True if invert == "true" else False
return (channels_layer(tensor, channels, lambda x: self.noise(
x, strength, monochromatic, invert
)),)
NODE_CLASS_MAPPINGS = {
"ImageNoiseBeta": ImageNoiseBeta,
"ImageNoiseBinomial": ImageNoiseBinomial,
"ImageNoiseBytes": ImageNoiseBytes,
"ImageNoiseGaussian": ImageNoiseGaussian
}