Added some random things.
Nothing major.
This commit is contained in:
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"cSpell.enabled": true,
|
||||
"cSpell.words": [
|
||||
"alfault",
|
||||
"byfault",
|
||||
"debouncer",
|
||||
"fclamp",
|
||||
"hlsa",
|
||||
"iclamp",
|
||||
"ispowof",
|
||||
"nparray",
|
||||
"NYBL",
|
||||
"yiqa"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
@echo off
|
||||
|
||||
python _test.py
|
||||
@@ -1,5 +1,16 @@
|
||||
|
||||
import regex_spm, re, code
|
||||
import numpy as np
|
||||
from math import ceil, floor, log
|
||||
from enum import Enum
|
||||
|
||||
from colorsys import (
|
||||
rgb_to_hls,
|
||||
rgb_to_hsv,
|
||||
rgb_to_yiq,
|
||||
hls_to_rgb,
|
||||
hsv_to_rgb,
|
||||
yiq_to_rgb,
|
||||
)
|
||||
|
||||
debouncer = set()
|
||||
|
||||
@@ -41,3 +52,167 @@ def pixel_approx(primary, secondary, total=1024, ratio=1.0,
|
||||
primary, secondary = pixel_approx(primary, secondary, total, ratio, threshold, _inc, False)
|
||||
|
||||
return (int(primary), int(secondary))
|
||||
|
||||
class RE:
|
||||
HEX = re.compile(r"^\#[\da-fA-F]{1,8}$", re.IGNORECASE)
|
||||
RGB = re.compile(r"^rgba?\s+(?:\d{1,3}[, ](?=\d)|\d{1,3}(?=$)){1,4}$", re.IGNORECASE)
|
||||
HSV = re.compile(r"^hsva?\s+(?:\d{1,3}[, ](?=\d)|\d{1,3}(?=$)){1,4}$", re.IGNORECASE)
|
||||
HLS = re.compile(r"^hlsa?\s+(?:\d{1,3}[, ](?=\d)|\d{1,3}(?=$)){1,4}$", re.IGNORECASE)
|
||||
YIQ = re.compile(r"^yiqa?\s+(?:\d{1,3}[, ](?=\d)|\d{1,3}(?=$)){1,4}$", re.IGNORECASE)
|
||||
|
||||
class color_format_constant(Enum):
|
||||
HEX,RGB,HSV,HLS,YIQ = range(5)
|
||||
|
||||
C = color_format_constant
|
||||
|
||||
def partition(array, step=2, indices=None):
|
||||
if not indices: indices = np.array(range(len(array) // step))*2
|
||||
return [array[i:i+step] for i in tuple(indices)]
|
||||
|
||||
def ispowof(value:int, exp=2):
|
||||
return ceil(log(value, 2)) == floor(log(value, 2))
|
||||
|
||||
def iclamp(value:int, low=0, high=255) -> int:
|
||||
return int(max(min(value, high), low))
|
||||
|
||||
def fclamp(value:float, low=0.0, high=1.0) -> float:
|
||||
return float(max(min(value, high), low))
|
||||
|
||||
def baser(value:int) -> int:
|
||||
'''
|
||||
Convert a NYBL integer (0~16) into a BYTE integer (0~255)
|
||||
Absolutely no error proofing whatsoever.
|
||||
'''
|
||||
return int(value * 16 + value)
|
||||
|
||||
def byte(value:float) -> int:
|
||||
'''
|
||||
Convert FLOAT scaler value to BYTE integer (0~255)
|
||||
Absolutely no error proofing whatsoever.
|
||||
'''
|
||||
return iclamp(round(fclamp(value) * 255))
|
||||
|
||||
def scale(value: int) -> float:
|
||||
'''
|
||||
Convert a BYTE integer (0~255) to a FLOAT scaler (0.0~1.0)
|
||||
Absolutely no error proofing whatsoever.
|
||||
'''
|
||||
return iclamp(value) / 255
|
||||
|
||||
def normalize(nparray, low=0.0, high=1.0):
|
||||
return np.array([(((i - min(nparray)) * (high - low)) / (max(nparray) - min(nparray))) + low for i in nparray])
|
||||
|
||||
class Color():
|
||||
default = C.HEX
|
||||
alfault = False
|
||||
byfault = False
|
||||
def __init__(self, color="#0", style=None):
|
||||
if isinstance(color, type(self)):
|
||||
self.RGBA = color.RGBA
|
||||
elif isinstance(color, type(tuple)):
|
||||
match len(color):
|
||||
case 1:
|
||||
self.RGBA = color * 4
|
||||
case 2:
|
||||
self.RGBA = (color[0],) * 3 + (color[1],)
|
||||
case 3:
|
||||
self.RGBA = color + (1.0,)
|
||||
case 4:
|
||||
self.RGBA = color
|
||||
case _:
|
||||
self.RGBA = color[:4]
|
||||
elif isinstance(color, str):
|
||||
match regex_spm.fullmatch_in(color):
|
||||
case RE.HEX:
|
||||
_color = color.lstrip('#')
|
||||
if not _color: print(f"Unhandled Case - {color}"); self.RGBA = self.fallback()
|
||||
match len(_color):
|
||||
case 1:
|
||||
self.RGBA = (scale(baser(int(_color, 16))),) * 3 + (1.0,)
|
||||
case 2:
|
||||
self.RGBA = (scale(int(_color, 16)),) * 3 + (1.0,)
|
||||
case 3:
|
||||
self.RGBA = tuple(scale(baser(int(e, 16))) for e in _color) + (1.0,)
|
||||
case 4:
|
||||
self.RGBA = tuple(scale(baser(int(e, 16))) for e in _color)
|
||||
case 6:
|
||||
# _Color needs to be sliced in 2 char
|
||||
self.RGBA = tuple(scale(int(e, 16)) for e in partition(_color)) + (1.0,)
|
||||
case 8:
|
||||
# _Color needs to be sliced in 2 char
|
||||
self.RGBA = tuple(scale(int(e, 16)) for e in partition(_color))
|
||||
case _:
|
||||
print(f"Unhandled Case - {color}")
|
||||
self.RGBA = self.fallback()
|
||||
case RE.RGB:
|
||||
_color = re.split(r" |,", color)
|
||||
print(_color)
|
||||
match len(_color[1:]):
|
||||
case 1:
|
||||
self.RGBA = tuple(scale(_color[1])) * 3 + (1.0,)
|
||||
case 2:
|
||||
self.RGBA = tuple(scale(_color[1])) * 3 + tuple(scale(_color[2]))
|
||||
case 3:
|
||||
self.RGBA = tuple(scale(int(e)) for e in _color[1:]) + (1.0,)
|
||||
case 4:
|
||||
self.RGBA = tuple(scale(int(e)) for e in _color[1:])
|
||||
case _:
|
||||
print(f"Unhandled Case - {color}")
|
||||
self.RGBA = self.fallback()
|
||||
case _:
|
||||
print(f"Unhandled Case - {color}")
|
||||
return None
|
||||
else:
|
||||
print(f"Unhandled Case - {color}")
|
||||
return None
|
||||
|
||||
def __str__(self, form=default, alpha=alfault, byte=byfault):
|
||||
_result = None
|
||||
match form:
|
||||
case C.RGB:
|
||||
_result = self.RGBA
|
||||
case C.HSV:
|
||||
_result = self.hsv()
|
||||
case C.HLS:
|
||||
_result = self.hls()
|
||||
case C.YIQ:
|
||||
_result = self.yiq()
|
||||
case _:
|
||||
return self.hex() if alpha else self.hex()[:-2]
|
||||
if byte: _result = (f"{byte(e):3d}" for e in _result)
|
||||
else: _result = (f"{round(e, 3):.3f}" for e in _result)
|
||||
if alpha: _result = _result[:3]
|
||||
return f'({",".join(_result)})'
|
||||
|
||||
def __repr__(self, form=default):
|
||||
match form:
|
||||
case C.RGB:
|
||||
return self.RGBA
|
||||
case C.HSV:
|
||||
return self.hsv()
|
||||
case C.HLS:
|
||||
return self.hls()
|
||||
case C.YIQ:
|
||||
return self.yiq()
|
||||
case _:
|
||||
return self.hex()
|
||||
|
||||
def fallback(self):
|
||||
try: return self.RGBA
|
||||
except: return (0.0, 0.0, 0.0, 1.0)
|
||||
|
||||
def hex(self):
|
||||
R, G, B, A = (byte(e) for e in self.RGBA)
|
||||
return f"#{R:02x}{G:02x}{B:02x}{A:02x}"
|
||||
|
||||
def hls(self):
|
||||
R, G, B, A = self.RGBA
|
||||
return rgb_to_hls(R, G, B) + (A,)
|
||||
|
||||
def hsv(self):
|
||||
R, G, B, A = self.RGBA
|
||||
return rgb_to_hsv(R, G, B) + (A,)
|
||||
|
||||
def yiq(self):
|
||||
R, G, B, A = self.RGBA
|
||||
return rgb_to_yiq(R, G, B) + (A,)
|
||||
@@ -1,10 +1,12 @@
|
||||
import os, torch
|
||||
import os, torch, random
|
||||
import numpy as np
|
||||
import comfy.utils
|
||||
|
||||
from colorsys import rgb_to_hsv, hsv_to_rgb
|
||||
|
||||
from kornia.enhance import equalize_clahe
|
||||
from ._func import pixel_approx, po2
|
||||
# from .isnet import dis_process
|
||||
from ._func import pixel_approx, po2, Color, byte
|
||||
from .isnet import dis_process
|
||||
from PIL import Image
|
||||
|
||||
class EqualizeCLAHE:
|
||||
@@ -13,12 +15,10 @@ class EqualizeCLAHE:
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE", ),
|
||||
"size": ("TUPLE", {"default": (1024, 1024)}),
|
||||
"clip_limit": ("FLOAT", {"default": 64, "min": 0.0, "max": 255, "step": 0.1}),
|
||||
"grid_size": ("INT", {"default": 8, "min": 1, "max": 64, "step": 1}),
|
||||
},
|
||||
"optional": {
|
||||
"size": ("TUPLE", {"default": (1024, 1024)}),
|
||||
}
|
||||
}
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
FUNCTION = "equalize"
|
||||
@@ -75,12 +75,10 @@ class ImageResize:
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"size": ("TUPLE", {"default": (1024, 1024)}),
|
||||
"width": ("INT", {"default": 1024, "min": 512, "max": 4096, "step": 32}),
|
||||
"height": ("INT", {"default": 1024, "min": 512, "max": 4096, "step": 32}),
|
||||
},
|
||||
"optional": {
|
||||
"size": ("TUPLE", {"default": (1024, 1024)}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
@@ -120,6 +118,42 @@ class ImageScale:
|
||||
|
||||
return (result,)
|
||||
|
||||
class RandomColorFill():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"color": ("STRING", {"default": '#7f7f7fff'}),
|
||||
"hue_range": ("FLOAT", {"default": 0.005}),
|
||||
"sat_range": ("FLOAT", {"default": 0.005}),
|
||||
"val_range": ("FLOAT", {"default": 0.005})
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
FUNCTION = "randomize"
|
||||
CATEGORY = "TeaNodes/Input"
|
||||
|
||||
def randomize(self, image, color, hue_range, sat_range, val_range):
|
||||
h, s, v, _ = Color(color).hsv()
|
||||
h += hue_range * (random.random() - 0.5)
|
||||
s += sat_range * (random.random() - 0.5)
|
||||
v += val_range * (random.random() - 0.5)
|
||||
|
||||
color_rgba = Color()
|
||||
color_rgba.RGBA = hsv_to_rgb(h, s, v) + (1.0,)
|
||||
print(f"Random Color:\t{color_rgba.hex()}")
|
||||
|
||||
height, width = image.shape[1:3]
|
||||
|
||||
_color = tuple(byte(e) for e in color_rgba.RGBA)
|
||||
_image = Image.new('RGBA', (width, height), _color)
|
||||
_image = np.array(_image.convert('RGBA')).astype(np.float32) / 255.0
|
||||
result = torch.from_numpy(_image).unsqueeze(0)
|
||||
|
||||
return (result,)
|
||||
|
||||
class ColorFill():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
@@ -192,5 +226,6 @@ NODE_CLASS_MAPPINGS = {
|
||||
"TC_ImageResize": ImageResize,
|
||||
"TC_ImageScale": ImageScale,
|
||||
"TC_ColorFill": ColorFill,
|
||||
# "TC_MaskBG_DIS": MaskBG_DIS,
|
||||
"TC_RandomColorFill": RandomColorFill,
|
||||
"TC_MaskBG_DIS": MaskBG_DIS,
|
||||
}
|
||||
Reference in New Issue
Block a user