Gradio 4 + WebUI 1.10

This commit is contained in:
layerdiffusion
2024-07-26 08:51:34 -07:00
parent e95333c556
commit e26abf87ec
201 changed files with 7562 additions and 4834 deletions

View File

@@ -1,45 +1,22 @@
import torch
from modules import sd_samplers_kdiffusion, sd_samplers_common
from ldm_patched.k_diffusion import sampling as k_diffusion_sampling
from ldm_patched.modules.samplers import calculate_sigmas_scheduler
class AlterSampler(sd_samplers_kdiffusion.KDiffusionSampler):
def __init__(self, sd_model, sampler_name, scheduler_name):
def __init__(self, sd_model, sampler_name):
self.sampler_name = sampler_name
self.scheduler_name = scheduler_name
self.unet = sd_model.forge_objects.unet
sampler_function = getattr(k_diffusion_sampling, "sample_{}".format(sampler_name))
super().__init__(sampler_function, sd_model, None)
def get_sigmas(self, p, steps):
if self.scheduler_name == 'turbo':
timesteps = torch.flip(torch.arange(1, steps + 1) * float(1000.0 / steps) - 1, (0,)).round().long().clip(0, 999)
sigmas = self.unet.model.model_sampling.sigma(timesteps)
sigmas = torch.cat([sigmas, sigmas.new_zeros([1])])
else:
sigmas = calculate_sigmas_scheduler(self.unet.model, self.scheduler_name, steps)
return sigmas.to(self.unet.load_device)
def build_constructor(sampler_name, scheduler_name):
def build_constructor(sampler_name):
def constructor(m):
return AlterSampler(m, sampler_name, scheduler_name)
return AlterSampler(m, sampler_name)
return constructor
samplers_data_alter = [
sd_samplers_common.SamplerData('DDPM', build_constructor(sampler_name='ddpm', scheduler_name='normal'), ['ddpm'], {}),
sd_samplers_common.SamplerData('DDPM Karras', build_constructor(sampler_name='ddpm', scheduler_name='karras'), ['ddpm_karras'], {}),
sd_samplers_common.SamplerData('Euler A Turbo', build_constructor(sampler_name='euler_ancestral', scheduler_name='turbo'), ['euler_ancestral_turbo'], {}),
sd_samplers_common.SamplerData('DPM++ 2M Turbo', build_constructor(sampler_name='dpmpp_2m', scheduler_name='turbo'), ['dpmpp_2m_turbo'], {}),
sd_samplers_common.SamplerData('DPM++ 2M SDE Turbo', build_constructor(sampler_name='dpmpp_2m_sde', scheduler_name='turbo'), ['dpmpp_2m_sde_turbo'], {}),
sd_samplers_common.SamplerData('LCM Karras', build_constructor(sampler_name='lcm', scheduler_name='karras'), ['lcm_karras'], {}),
sd_samplers_common.SamplerData('Euler SGMUniform', build_constructor(sampler_name='euler', scheduler_name='sgm_uniform'), ['euler_sgm_uniform'], {}),
sd_samplers_common.SamplerData('Euler A SGMUniform', build_constructor(sampler_name='euler_ancestral', scheduler_name='sgm_uniform'), ['euler_ancestral_sgm_uniform'], {}),
sd_samplers_common.SamplerData('DPM++ 2M SGMUniform', build_constructor(sampler_name='dpmpp_2m', scheduler_name='sgm_uniform'), ['dpmpp_2m_sgm_uniform'], {}),
sd_samplers_common.SamplerData('DPM++ 2M SDE SGMUniform', build_constructor(sampler_name='dpmpp_2m_sde', scheduler_name='sgm_uniform'), ['dpmpp_2m_sde_sgm_uniform'], {}),
sd_samplers_common.SamplerData('DDPM', build_constructor(sampler_name='ddpm'), ['ddpm'], {}),
]

View File

@@ -0,0 +1,159 @@
.forge-container {
width: 100%;
height: 512px;
position: relative;
overflow: hidden;
}
.forge-image-container {
width: 100%;
height: calc(100% - 6px);
position: relative;
overflow: hidden;
background-color: #cccccc;
background-image: linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee),
linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee);
background-size: 20px 20px;
background-position: 0 0, 10px 10px;
}
.forge-image {
position: absolute;
top: 0;
left: 0;
background-size: contain;
background-repeat: no-repeat;
cursor: grab;
max-width: unset !important;
max-height: unset !important;
}
.forge-image:active {
cursor: grabbing;
}
.forge-file-upload {
display: none;
}
.forge-resize-line {
width: 100%;
height: 6px;
background-image: linear-gradient(to bottom, grey 50%, darkgrey 50%);
background-size: 4px 4px;
background-repeat: repeat;
cursor: ns-resize;
position: absolute;
bottom: 0;
left: 0;
}
.forge-toolbar {
position: absolute;
top: 0px;
left: 0px;
z-index: 10;
background: rgba(47, 47, 47, 0.8);
padding: 6px 10px;
opacity: 0;
transition: opacity 0.3s ease;
}
.forge-toolbar .forge-btn {
padding: 2px 6px;
border: none;
background-color: #4a4a4a;
color: white;
font-size: 14px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.forge-toolbar .forge-btn:hover {
background-color: #5e5e5e;
}
.forge-toolbar .forge-btn:active {
background-color: #3e3e3e;
}
.forge-toolbar-box-a {
flex-wrap: wrap;
}
.forge-toolbar-box-b {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 4px;
}
.forge-color-picker-block {
display: flex;
align-items: center;
}
.forge-range-row {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.forge-toolbar-color {
border: none;
background: none;
padding: 3px;
border-radius: 50%;
width: 20px;
height: 20px;
-webkit-appearance: none;
appearance: none;
cursor: pointer;
}
.forge-toolbar-color::-webkit-color-swatch-wrapper {
padding: 0;
border-radius: 50%;
}
.forge-toolbar-color::-webkit-color-swatch {
border: none;
border-radius: 50%;
background: none;
}
.forge-toolbar-label {
color: white !important;
padding: 0 4px;
display: flex;
align-items: center;
margin-bottom: 4px; /* Adjust margin as needed */
}
.forge-toolbar-range {
}
.forge-scribble-indicator {
position: relative;
border-radius: 50%;
border: 1px solid;
pointer-events: none;
display: none;
width: 80px;
height: 80px;
}
.forge-no-select {
user-select: none;
}
.forge-upload-hint {
position: absolute;
top: 50%;
left: 50%;
width: 30%;
height: 30%;
transform: translate(-50%, -50%);
}

View File

@@ -0,0 +1,63 @@
<div class="forge-container" id="container_forge_mixin">
<input type="file" id="imageInput_forge_mixin" class="forge-file-upload">
<div id="imageContainer_forge_mixin" class="forge-image-container">
<div id="uploadHint_forge_mixin">
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" fill="none"
stroke="white"
stroke-width="4"
stroke-linecap="round"
stroke-linejoin="round"
class="forge-upload-hint">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
<polyline points="17 8 12 3 7 8"></polyline>
<line x1="12" y1="3" x2="12" y2="15"></line>
</svg>
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" fill="none"
stroke="grey"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="forge-upload-hint">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
<polyline points="17 8 12 3 7 8"></polyline>
<line x1="12" y1="3" x2="12" y2="15"></line>
</svg>
</div>
<img id="image_forge_mixin" class="forge-image forge-no-select">
<canvas id="drawingCanvas_forge_mixin" class="forge-drawing-canvas"
style="position:absolute;top:0;left:0;" width="1" height="1"></canvas>
<div class="forge-toolbar" id="toolbar_forge_mixin">
<div class="forge-toolbar-box-a">
<button id="maxButton_forge_mixin" class="forge-btn forge-no-select" title="Maximize"></button>
<button id="minButton_forge_mixin" class="forge-btn forge-no-select" title="Minimize" style="display: none;"></button>
<button id="uploadButton_forge_mixin" class="forge-btn forge-no-select" title="Upload">📂</button>
<button id="removeButton_forge_mixin" class="forge-btn forge-no-select" title="Remove">🗑️</button>
<button id="centerButton_forge_mixin" class="forge-btn forge-no-select" title="Center Position"></button>
<button id="resetButton_forge_mixin" class="forge-btn forge-no-select" title="Reset">🔄</button>
<button id="undoButton_forge_mixin" class="forge-btn forge-no-select" title="Undo">↩️</button>
<button id="redoButton_forge_mixin" class="forge-btn forge-no-select" title="Redo">↪️</button>
</div>
<div class="forge-toolbar-box-b">
<div class="forge-color-picker-block" id="scribbleColorBlock_forge_mixin">
<input type="color" id="scribbleColor_forge_mixin" class="forge-toolbar-color" value="#000000">
</div>
<div class="forge-range-row" id="scribbleWidthBlock_forge_mixin">
<div id="widthLabel_forge_mixin" class="forge-toolbar-label">brush width</div>
<input type="range" id="scribbleWidth_forge_mixin" class="forge-toolbar-range" min="1" max="20" value="4">
</div>
<div class="forge-range-row" id="scribbleAlphaBlock_forge_mixin">
<div id="alphaLabel_forge_mixin" class="forge-toolbar-label">brush opacity</div>
<input type="range" id="scribbleAlpha_forge_mixin" class="forge-toolbar-range" min="0" max="100" value="100">
</div>
<div class="forge-range-row" id="scribbleSoftnessBlock_forge_mixin">
<div id="softnessLabel_forge_mixin" class="forge-toolbar-label">brush softness</div>
<input type="range" id="scribbleSoftness_forge_mixin" class="forge-toolbar-range" min="0" max="100" value="0">
</div>
</div>
</div>
<div id="scribbleIndicator_forge_mixin" class="forge-scribble-indicator"></div>
</div>
<div class="forge-resize-line" id="resizeLine_forge_mixin"></div>
</div>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,120 @@
# Forge Canvas
# AGPL V3
# by lllyasviel
# Commercial Use is not allowed. (Contact us for commercial use.)
import os
import uuid
import base64
import gradio as gr
import numpy as np
from PIL import Image
from io import BytesIO
from gradio.context import Context
from functools import wraps
from modules.ui_components import FormComponent
canvas_js_root_path = os.path.dirname(__file__)
def web_js(file_name):
full_path = os.path.join(canvas_js_root_path, file_name)
return f'<script src="file={full_path}?{os.path.getmtime(full_path)}"></script>\n'
def web_css(file_name):
full_path = os.path.join(canvas_js_root_path, file_name)
return f'<link rel="stylesheet" href="file={full_path}?{os.path.getmtime(full_path)}">\n'
DEBUG_MODE = False
canvas_html = open(os.path.join(canvas_js_root_path, 'canvas.html'), encoding='utf-8').read()
canvas_head = ''
canvas_head += web_css('canvas.css')
canvas_head += web_js('canvas.min.js')
def image_to_base64(image_array, numpy=True):
image = Image.fromarray(image_array) if numpy else image_array
image = image.convert("RGBA")
buffered = BytesIO()
image.save(buffered, format="PNG")
image_base64 = base64.b64encode(buffered.getvalue()).decode('utf-8')
return f"data:image/png;base64,{image_base64}"
def base64_to_image(base64_str, numpy=True):
if base64_str.startswith("data:image/png;base64,"):
base64_str = base64_str.replace("data:image/png;base64,", "")
image_data = base64.b64decode(base64_str)
image = Image.open(BytesIO(image_data))
image = image.convert("RGBA")
image_array = np.array(image) if numpy else image
return image_array
class LogicalImage(gr.Textbox, FormComponent):
@wraps(gr.Textbox.__init__)
def __init__(self, *args, numpy=True, **kwargs):
self.numpy = numpy
if 'value' in kwargs:
initial_value = kwargs['value']
if initial_value is not None:
kwargs['value'] = self.image_to_base64(initial_value)
else:
del kwargs['value']
super().__init__(*args, **kwargs)
def preprocess(self, payload):
if not isinstance(payload, str):
return None
if not payload.startswith("data:image/png;base64,"):
return None
return base64_to_image(payload, numpy=self.numpy)
def postprocess(self, value):
if value is None:
return None
return image_to_base64(value, numpy=self.numpy)
def get_block_name(self):
return "textbox"
class ForgeCanvas:
def __init__(
self,
no_upload=False,
no_scribbles=False,
contrast_scribbles=False,
height=512,
scribble_color='#000000',
scribble_color_fixed=False,
scribble_width=4,
scribble_width_fixed=False,
scribble_alpha=100,
scribble_alpha_fixed=False,
scribble_softness=0,
scribble_softness_fixed=False,
visible=True,
numpy=False,
initial_image=None,
elem_id=None,
elem_classes=None
):
self.uuid = 'uuid_' + uuid.uuid4().hex
self.block = gr.HTML(canvas_html.replace('forge_mixin', self.uuid), visible=visible, elem_id=elem_id, elem_classes=elem_classes)
self.foreground = LogicalImage(visible=DEBUG_MODE, label='foreground', numpy=numpy, elem_id=self.uuid, elem_classes=['logical_image_foreground'])
self.background = LogicalImage(visible=DEBUG_MODE, label='background', numpy=numpy, value=initial_image, elem_id=self.uuid, elem_classes=['logical_image_background'])
Context.root_block.load(None, js=f'async ()=>{{new ForgeCanvas("{self.uuid}", {no_upload}, {no_scribbles}, {contrast_scribbles}, {height}, '
f"'{scribble_color}', {scribble_color_fixed}, {scribble_width}, {scribble_width_fixed}, "
f'{scribble_alpha}, {scribble_alpha_fixed}, {scribble_softness}, {scribble_softness_fixed});}}')

View File

@@ -223,7 +223,10 @@ def load_model_for_a1111(timer, checkpoint_info=None, state_dict=None):
if getattr(sd_model, 'parameterization', None) == 'v':
sd_model.forge_objects.unet.model.model_sampling = model_sampling(sd_model.forge_objects.unet.model.model_config, ModelType.V_PREDICTION)
sd_model.is_sd3 = False
sd_model.latent_channels = 4
sd_model.is_sdxl = conditioner is not None
sd_model.is_sdxl_inpaint = sd_model.is_sdxl and forge_objects.unet.model.diffusion_model.in_channels == 9
sd_model.is_sd2 = not sd_model.is_sdxl and hasattr(sd_model.cond_stage_model, 'model')
sd_model.is_sd1 = not sd_model.is_sdxl and not sd_model.is_sd2
sd_model.is_ssd = sd_model.is_sdxl and 'model.diffusion_model.middle_block.1.transformer_blocks.0.attn1.to_q.weight' not in sd_model.state_dict().keys()

View File

@@ -1 +1 @@
version = '0.0.17v1.8.0rc'
version = '1.0.0v1.10.0rc'