Implement Styles Preset!
- Implement #7 - Finally separate logics into their own scripts - Version bump - Lint codepull/8/head
parent
6baa27b97c
commit
b0da134bf5
|
|
@ -53,6 +53,13 @@ refer to the parameters and sample images below and play around with the values.
|
|||
- **Reset:** Revert all settings to the default values
|
||||
- **Randomize:** Randomize `Brightness`, `Contrast`, `Saturation`, `R`, `G`, `B`
|
||||
|
||||
#### Styles Preset
|
||||
- Use the `Dropdown` to select a Style to apply
|
||||
- To save a Style, enter a name in the `Textbox` then click **Save Style**
|
||||
- To delete a Style, enter the name in the `Textbox` then click **Delete Style**
|
||||
- *Deleted Style is still in the `styles.json` in case you wish to retrieve it*
|
||||
- Click **Manual Refresh** to update the `Dropdown` the if you edited the `styles.json` directly
|
||||
|
||||
#### Advanced Settings
|
||||
|
||||
- **Process Hires. fix:** By default, this Extension only functions during the **txt2img** phase, so that **Hires. fix** may "fix" the artifacts introduced during **txt2img**. Enable this to process **Hires. fix** phase too.
|
||||
|
|
@ -128,6 +135,7 @@ refer to the parameters and sample images below and play around with the values.
|
|||
- [X] Add Support for **X/Y/Z Plot**
|
||||
- [X] Implement different Noise functions
|
||||
- [X] Add Randomize functions
|
||||
- [X] Styles Preset
|
||||
- [ ] Implement a better scaling algorithm
|
||||
- [ ] Fix the Brightness issues
|
||||
- [ ] Add Gradient feature
|
||||
|
|
|
|||
|
|
@ -1,64 +1,19 @@
|
|||
from modules.sd_samplers_kdiffusion import KDiffusionSampler
|
||||
import modules.scripts as scripts
|
||||
from modules import devices
|
||||
from modules import shared
|
||||
import gradio as gr
|
||||
import random
|
||||
import torch
|
||||
import json
|
||||
|
||||
VERSION = 'v1.2.0'
|
||||
from scripts.cc_version import *
|
||||
from scripts.cc_noise import *
|
||||
from scripts.cc_style import StyleManager
|
||||
|
||||
def clean_outdated(EXT_NAME:str):
|
||||
with open(scripts.basedir() + '/' + 'ui-config.json', 'r') as json_file:
|
||||
configs = json.loads(json_file.read())
|
||||
|
||||
cleaned_configs = {key: value for key, value in configs.items() if EXT_NAME not in key}
|
||||
|
||||
with open(scripts.basedir() + '/' + 'ui-config.json', 'w') as json_file:
|
||||
json.dump(cleaned_configs, json_file)
|
||||
|
||||
def ones(latent):
|
||||
return torch.ones_like(latent)
|
||||
|
||||
def gaussian_noise(latent):
|
||||
return torch.rand_like(latent)
|
||||
|
||||
def normal_noise(latent):
|
||||
return torch.randn_like(latent)
|
||||
|
||||
def multires_noise(latent, use_zero:bool, iterations=8, discount=0.4):
|
||||
"""
|
||||
Reference: https://wandb.ai/johnowhitaker/multires_noise/reports/Multi-Resolution-Noise-for-Diffusion-Model-Training--VmlldzozNjYyOTU2
|
||||
Credit: Kohya_SS
|
||||
"""
|
||||
noise = torch.zeros_like(latent) if use_zero else ones(latent)
|
||||
|
||||
batchSize = noise.size(0)
|
||||
height = noise.size(2)
|
||||
width = noise.size(3)
|
||||
|
||||
device = devices.get_optimal_device()
|
||||
upsampler = torch.nn.Upsample(size=(height, width), mode="bilinear").to(device)
|
||||
|
||||
for b in range(batchSize):
|
||||
for i in range(iterations):
|
||||
r = random.random() * 2 + 2
|
||||
|
||||
wn = max(1, int(width / (r**i)))
|
||||
hn = max(1, int(height / (r**i)))
|
||||
|
||||
for c in range(4):
|
||||
noise[b, c] += upsampler(torch.randn(1, 1, hn, wn).to(device))[0, 0] * discount**i
|
||||
|
||||
if wn == 1 or hn == 1:
|
||||
break
|
||||
|
||||
return noise / noise.std()
|
||||
style_manager = StyleManager()
|
||||
|
||||
class VectorscopeCC(scripts.Script):
|
||||
def __init__(self):
|
||||
clean_outdated('cc.py')
|
||||
style_manager.load_styles()
|
||||
|
||||
global og_callback
|
||||
og_callback = KDiffusionSampler.callback_state
|
||||
|
|
@ -73,7 +28,7 @@ class VectorscopeCC(scripts.Script):
|
|||
return _
|
||||
|
||||
def choices_bool():
|
||||
return ["True", "False"]
|
||||
return ["False", "True"]
|
||||
|
||||
def choices_method():
|
||||
return ["Disabled", "Straight", "Straight Abs.", "Cross", "Cross Abs.", "Ones", "N.Random", "U.Random", "Multi-Res", "Multi-Res Abs."]
|
||||
|
|
@ -107,6 +62,7 @@ class VectorscopeCC(scripts.Script):
|
|||
return scripts.AlwaysVisible
|
||||
|
||||
def ui(self, is_img2img):
|
||||
|
||||
with gr.Accordion(f"Vectorscope CC {VERSION}", open=False):
|
||||
|
||||
with gr.Row():
|
||||
|
|
@ -124,6 +80,25 @@ class VectorscopeCC(scripts.Script):
|
|||
g = gr.Slider(label="G", info='Magenta | Green',minimum=-2.5, maximum=2.5, step=0.05, value=0.0)
|
||||
b = gr.Slider(label="B", info='Yellow | Blue',minimum=-2.5, maximum=2.5, step=0.05, value=0.0)
|
||||
|
||||
with gr.Accordion("Styles", open=False):
|
||||
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
style_choice = gr.Dropdown(label="Apply Style", choices=style_manager.list_style())
|
||||
style_name = gr.Textbox(label="Style Name")
|
||||
|
||||
style_choice.input(fn=style_manager.get_style, inputs=style_choice, outputs=[latent, bri, con, sat, r, g, b])
|
||||
|
||||
with gr.Column(variant="compact"):
|
||||
save_btn = gr.Button(value="Save Style")
|
||||
delete_btn = gr.Button(value="Delete Style")
|
||||
refresh_btn = gr.Button(value="Manual Refresh")
|
||||
|
||||
save_btn.click(fn=lambda *args: gr.update(choices=style_manager.save_style(*args)), inputs=[style_name, latent, bri, con, sat, r, g, b], outputs=style_choice)
|
||||
delete_btn.click(fn=lambda name: gr.update(choices=style_manager.delete_style(name)), inputs=style_name, outputs=style_choice)
|
||||
refresh_btn.click(fn=lambda _: gr.update(choices=style_manager.list_style()), outputs=style_choice)
|
||||
|
||||
|
||||
with gr.Accordion("Advanced Settings", open=False):
|
||||
doHR = gr.Checkbox(label="Process Hires. fix")
|
||||
method = gr.Radio(["Straight", "Straight Abs.", "Cross", "Cross Abs.", "Ones", "N.Random", "U.Random", "Multi-Res", "Multi-Res Abs."], label="Noise Settings", value="Straight Abs.")
|
||||
|
|
@ -139,19 +114,19 @@ class VectorscopeCC(scripts.Script):
|
|||
|
||||
def register_reset(self, reset_btn, enable, latent, bri, con, sat, early, r, g, b, doHR, method):
|
||||
for component in [enable, latent, doHR]:
|
||||
reset_btn.click(fn=lambda x: gr.update(value=False), outputs=component)
|
||||
reset_btn.click(fn=lambda _: gr.update(value=False), outputs=component)
|
||||
for component in [early, bri, r, g, b]:
|
||||
reset_btn.click(fn=lambda x: gr.update(value=0.0), outputs=component)
|
||||
reset_btn.click(fn=lambda _: gr.update(value=0.0), outputs=component)
|
||||
for component in [con, sat]:
|
||||
reset_btn.click(fn=lambda x: gr.update(value=1.0), outputs=component)
|
||||
reset_btn.click(fn=lambda _: gr.update(value=1.0), outputs=component)
|
||||
|
||||
reset_btn.click(fn=lambda x: gr.update(value='Straight Abs.'), outputs=method)
|
||||
reset_btn.click(fn=lambda _: gr.update(value='Straight Abs.'), outputs=method)
|
||||
|
||||
def register_random(self, random_btn, bri, con, sat, r, g, b):
|
||||
for component in [bri, r, g, b]:
|
||||
random_btn.click(fn=lambda x: gr.update(value=round(random.uniform(-2.5, 2.5), 2)), outputs=component)
|
||||
random_btn.click(fn=lambda _: gr.update(value=round(random.uniform(-2.5, 2.5), 2)), outputs=component)
|
||||
for component in [con, sat]:
|
||||
random_btn.click(fn=lambda x: gr.update(value=round(random.uniform(0.5, 1.5), 2)), outputs=component)
|
||||
random_btn.click(fn=lambda _: gr.update(value=round(random.uniform(0.5, 1.5), 2)), outputs=component)
|
||||
|
||||
def parse_bool(self, string:str):
|
||||
if string.lower() == "true":
|
||||
|
|
@ -218,7 +193,7 @@ class VectorscopeCC(scripts.Script):
|
|||
|
||||
stop = steps * (1.0 - early)
|
||||
|
||||
if not cc_seed == None:
|
||||
if cc_seed is not None:
|
||||
random.seed(cc_seed)
|
||||
|
||||
bri = round(random.uniform(-2.5, 2.5), 2)
|
||||
|
|
@ -292,7 +267,7 @@ class VectorscopeCC(scripts.Script):
|
|||
target = gaussian_noise(d[mode])
|
||||
|
||||
if 'Abs' in method:
|
||||
target = torch.abs(target)
|
||||
abs_cvt(target)
|
||||
|
||||
batchSize = d[mode].size(0)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
from modules import devices
|
||||
import torch
|
||||
|
||||
def abs_cvt(latent):
|
||||
return torch.abs(latent)
|
||||
|
||||
def ones(latent):
|
||||
return torch.ones_like(latent)
|
||||
|
||||
def gaussian_noise(latent):
|
||||
return torch.rand_like(latent)
|
||||
|
||||
def normal_noise(latent):
|
||||
return torch.randn_like(latent)
|
||||
|
||||
def multires_noise(latent, use_zero:bool, iterations=8, discount=0.4):
|
||||
"""
|
||||
Reference: https://wandb.ai/johnowhitaker/multires_noise/reports/Multi-Resolution-Noise-for-Diffusion-Model-Training--VmlldzozNjYyOTU2
|
||||
Credit: Kohya_SS
|
||||
"""
|
||||
noise = torch.zeros_like(latent) if use_zero else ones(latent)
|
||||
|
||||
batchSize = noise.size(0)
|
||||
height = noise.size(2)
|
||||
width = noise.size(3)
|
||||
|
||||
device = devices.get_optimal_device()
|
||||
upsampler = torch.nn.Upsample(size=(height, width), mode="bilinear").to(device)
|
||||
|
||||
for b in range(batchSize):
|
||||
for i in range(iterations):
|
||||
r = torch.rand(1).item() * 2 + 2
|
||||
|
||||
wn = max(1, int(width / (r**i)))
|
||||
hn = max(1, int(height / (r**i)))
|
||||
|
||||
for c in range(4):
|
||||
noise[b, c] += upsampler(torch.randn(1, 1, hn, wn).to(device))[0, 0] * discount**i
|
||||
|
||||
if wn == 1 or hn == 1:
|
||||
break
|
||||
|
||||
return noise / noise.std()
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
import modules.scripts as scripts
|
||||
import json
|
||||
|
||||
STYLE_FILE = scripts.basedir() + '/' + 'styles.json'
|
||||
|
||||
EMPTY_STYLE = {
|
||||
'styles' : {},
|
||||
'deleted' : {}
|
||||
}
|
||||
|
||||
class StyleManager():
|
||||
def __init__(self):
|
||||
self.STYLE_SHEET = None
|
||||
|
||||
def load_styles(self):
|
||||
if self.STYLE_SHEET is not None:
|
||||
return
|
||||
|
||||
try:
|
||||
with open(STYLE_FILE, 'r') as json_file:
|
||||
self.STYLE_SHEET = json.loads(json_file.read())
|
||||
print('[Vec. CC] Style Sheet Loaded...')
|
||||
except IOError:
|
||||
with open(STYLE_FILE, 'w+') as json_file:
|
||||
self.STYLE_SHEET = EMPTY_STYLE
|
||||
json_file.write(json.dumps(self.STYLE_SHEET))
|
||||
print('[Vec. CC] Creating Empty Style Sheet...')
|
||||
|
||||
def list_style(self):
|
||||
return list(self.STYLE_SHEET['styles'].keys())
|
||||
|
||||
def get_style(self, style_name):
|
||||
style = self.STYLE_SHEET['styles'][style_name]
|
||||
return style['alt'], style['brightness'], style['contrast'], style['saturation'], style['rgb'][0], style['rgb'][1], style['rgb'][2]
|
||||
|
||||
def save_style(self, style_name, latent, bri, con, sat, r, g, b):
|
||||
if style_name in self.STYLE_SHEET['styles'].keys():
|
||||
print(f'\n[Warning] Duplicated Style Name "{style_name}" Detected! Values are not saved!\n')
|
||||
return self.list_style()
|
||||
|
||||
style = {
|
||||
'alt' : latent,
|
||||
'brightness' : bri,
|
||||
'contrast' : con,
|
||||
'saturation' : sat,
|
||||
'rgb' : [r, g, b]
|
||||
}
|
||||
|
||||
self.STYLE_SHEET['styles'].update({style_name:style})
|
||||
|
||||
with open(STYLE_FILE, 'w+') as json_file:
|
||||
json_file.write(json.dumps(self.STYLE_SHEET))
|
||||
|
||||
print(f'\nStyle of Name "{style_name}" Saved!\n')
|
||||
return self.list_style()
|
||||
|
||||
def delete_style(self, style_name):
|
||||
try:
|
||||
style = self.STYLE_SHEET['styles'][style_name]
|
||||
del self.STYLE_SHEET['styles'][style_name]
|
||||
except KeyError:
|
||||
print(f'\n[Warning] No Style of Name "{style_name}" Found!\n')
|
||||
return self.list_style()
|
||||
|
||||
self.STYLE_SHEET['deleted'].update({style_name:style})
|
||||
|
||||
with open(STYLE_FILE, 'w+') as json_file:
|
||||
json_file.write(json.dumps(self.STYLE_SHEET))
|
||||
|
||||
print(f'\nStyle of Name "{style_name}" Deleted!\n')
|
||||
return self.list_style()
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import modules.scripts as scripts
|
||||
import json
|
||||
|
||||
VERSION = 'v1.3.0'
|
||||
|
||||
def clean_outdated(EXT_NAME:str):
|
||||
with open(scripts.basedir() + '/' + 'ui-config.json', 'r') as json_file:
|
||||
configs = json.loads(json_file.read())
|
||||
|
||||
cleaned_configs = {key: value for key, value in configs.items() if EXT_NAME not in key}
|
||||
|
||||
with open(scripts.basedir() + '/' + 'ui-config.json', 'w') as json_file:
|
||||
json.dump(cleaned_configs, json_file)
|
||||
Loading…
Reference in New Issue