support webui commit d97f467c

master
hnmr293 2023-01-20 01:06:53 +09:00
parent 66e1263d4a
commit ca7cdc67ea
5 changed files with 131 additions and 116 deletions

View File

@ -11,34 +11,38 @@ onUiUpdate(() => {
if (!app || app === document) return;
const descs = {
'#dumpunet-features-checkbox': 'Extract U-Net features and add their maps to output images.',
'#dumpunet-features-layer': 'U-Net layers <code>(IN00-IN11, M00, OUT00-OUT11)</code> which features should be extracted. See tooltip for notations.',
'#dumpunet-features-steps': 'Steps which U-Net features should be extracted. See tooltip for notations',
'#dumpunet-features-dumppath': 'Raw binary files are dumped to here, one image per step per layer.',
'#dumpunet-{}-features-checkbox': 'Extract U-Net features and add their maps to output images.',
'#dumpunet-{}-features-layer': 'U-Net layers <code>(IN00-IN11, M00, OUT00-OUT11)</code> which features should be extracted. See tooltip for notations.',
'#dumpunet-{}-features-steps': 'Steps which U-Net features should be extracted. See tooltip for notations',
'#dumpunet-{}-features-dumppath': 'Raw binary files are dumped to here, one image per step per layer.',
'#dumpunet-layerprompt-checkbox': 'When checked, <code>(~: ... :~)</code> notation is enabled.',
'#dumpunet-layerprompt-stdout-checkbox': 'When checked, print prompts for each batch to stdout.',
'#dumpunet-{}-layerprompt-checkbox': 'When checked, <code>(~: ... :~)</code> notation is enabled.',
'#dumpunet-{}-layerprompt-stdout-checkbox': 'When checked, print prompts for each batch to stdout.',
};
const hints = {
'#dumpunet-features-layer textarea': 'IN00: add one layer to output\nIN00,IN01: add layers to output\nIN00-IN02: add range to output\nIN00-OUT05(+2): add range to output with specified steps\n',
'#dumpunet-features-steps textarea': '5: extracted at steps=5\n5,10: extracted at steps=5 and steps=10\n5-10: extracted when step is in 5..10 (inclusive)\n5-10(+2): extracts when step is 5,7,9\n',
'#dumpunet-{}-features-layer textarea': 'IN00: add one layer to output\nIN00,IN01: add layers to output\nIN00-IN02: add range to output\nIN00-OUT05(+2): add range to output with specified steps\n',
'#dumpunet-{}-features-steps textarea': '5: extracted at steps=5\n5,10: extracted at steps=5 and steps=10\n5-10: extracted when step is in 5..10 (inclusive)\n5-10(+2): extracts when step is 5,7,9\n',
};
for (let [k, v] of Object.entries(descs)) {
const cont = document.createElement('div');
cont.innerHTML = v;
cont.classList.add('dumpunet-description');
app.querySelector(k).append(cont);
for (let x of ['txt2img', 'img2img']) {
app.querySelector(k.replace('{}', x)).append(cont.cloneNode(true));
}
}
for (let [k, v] of Object.entries(hints)) {
const cont = document.createElement('pre');
cont.innerHTML = v;
cont.classList.add('dumpunet-tooltip');
const parent = app.querySelector(k).parentNode;
parent.classList.add('dumpunet-tooltip-parent');
parent.append(cont);
for (let x of ['txt2img', 'img2img']) {
const parent = app.querySelector(k.replace('{}', x)).parentNode;
parent.classList.add('dumpunet-tooltip-parent');
parent.append(cont.cloneNode(true));
}
}
DumpUnet.addDescriptionCallbackCalled = true;

View File

@ -10,36 +10,25 @@ onUiUpdate(() => {
const app = gradioApp();
if (!app || app === document) return;
const labels = Array.of(...app.querySelectorAll('#tab_txt2img label'));
const width_label = labels.find(x => x.textContent.trim() === "Width");
const height_label = labels.find(x => x.textContent.trim() === "Height");
const steps_label = labels.find(x => x.textContent.trim() === "Sampling Steps");
if (!width_label || !height_label || !steps_label) return;
const sliders = {};
for (let mode of ['txt2img', 'img2img']) {
const labels = Array.of(...app.querySelectorAll(`#tab_${mode} label`));
const width_label = labels.find(x => x.textContent.trim() === "Width");
const height_label = labels.find(x => x.textContent.trim() === "Height");
const steps_label = labels.find(x => x.textContent.toLowerCase().trim() === "sampling steps");
if (!width_label || !height_label || !steps_label) return;
const width_slider = app.querySelector(`#${width_label.htmlFor}`);
const height_slider = app.querySelector(`#${height_label.htmlFor}`);
const steps_slider = app.querySelector(`#${steps_label.htmlFor}`)
if (!width_slider || !height_slider || !steps_slider) return;
//if (+width_slider.dataset.dumpunetHooked && +height_slider.dataset.dumpunetHooked) return
//
//const value_hook = ele => {
// const proto = Object.getPrototypeOf(ele);
// const old_desc = Object.getOwnPropertyDescriptor(proto, 'value');
// Object.defineProperty(ele, 'value', {
// get: function () { return old_desc.get.apply(this, arguments); },
// set: function () {
// const old_value = this.value;
// old_desc.set.apply(this, arguments);
// const new_value = this.value;
// const ev = new CustomEvent('imagesizesliderchange', { detail: { old_value: old_value }, bubbles: true });
// ele.dispatchEvent(ev);
// }
// });
// ele.dataset.dumpunetHooked = 1;
//};
//
//value_hook(width_slider);
//value_hook(height_slider);
const width_slider = app.querySelector(`#${width_label.htmlFor}`);
const height_slider = app.querySelector(`#${height_label.htmlFor}`);
const steps_slider = app.querySelector(`#${steps_label.htmlFor}`)
if (!width_slider || !height_slider || !steps_slider) return;
sliders[mode] = {
width_slider,
height_slider,
steps_slider,
}
}
globalThis.DumpUnet.applySizeCallbackCalled = true;
@ -89,51 +78,51 @@ onUiUpdate(() => {
return [...new Set(layers)].sort().map(n => layer_names[n]);
};
const layer_input_ele = app.querySelector('#dumpunet-features-layer textarea');
layer_input_ele.addEventListener('input', e => {
const input = layer_input_ele.value;
const layers = parse_layers(input);
layer_input_ele.style.backgroundColor = layers.length == 0 ? 'pink' : 'white';
}, false);
for (let mode of ['txt2img', 'img2img']) {
const layer_input_ele = app.querySelector(`#dumpunet-${mode}-features-layer textarea`);
layer_input_ele.addEventListener('input', e => {
const input = layer_input_ele.value;
const layers = parse_layers(input);
layer_input_ele.style.backgroundColor = layers.length == 0 ? 'pink' : 'white';
}, false);
const update_info = () => {
const layer_input = layer_input_ele.value;
const layers = parse_layers(layer_input);
const update_info = () => {
const layer_input = layer_input_ele.value;
const layers = parse_layers(layer_input);
const
w = +width_slider.value,
h = +height_slider.value,
iw = Math.max(1, Math.ceil(w / 64)),
ih = Math.max(1, Math.ceil(h / 64));
const
width_slider = sliders[mode].width_slider,
height_slider = sliders[mode].height_slider,
w = +width_slider.value,
h = +height_slider.value,
iw = Math.max(1, Math.ceil(w / 64)),
ih = Math.max(1, Math.ceil(h / 64));
let html = '[Selected Layer Info]<br/>';
let html = '[Selected Layer Info]<br/>';
for (let layer of layers) {
const info = JSON.parse(app.querySelector('#dumpunet-features-layer_setting').textContent)[layer];
info[0][1] *= ih;
info[0][2] *= iw;
info[1][1] *= ih;
info[1][2] *= iw;
html += `
for (let layer of layers) {
const info = JSON.parse(app.querySelector(`#dumpunet-${mode}-features-layer_setting`).textContent)[layer];
info[0][1] *= ih;
info[0][2] *= iw;
info[1][1] *= ih;
info[1][2] *= iw;
html += `
Name:&nbsp;&nbsp;&nbsp;${layer}<br/>
Input:&nbsp;&nbsp;(${info[0].join(',')})<br/>
Outout:&nbsp;(${info[1].join(',')})<br/>
---<br/>
`.trim();
}
}
app.querySelector('#dumpunet-features-layerinfo').innerHTML = html.trim();
};
app.querySelector(`#dumpunet-${mode}-features-layerinfo`).innerHTML = html.trim();
};
//app.addEventListener('imagesizesliderchange', e => {
// //console.log(e.detail.old_value, e.target.value);
// update_info();
//}, false);
app.addEventListener('input', update_info, false);
app.addEventListener('change', update_info, false);
app.addEventListener('input', update_info, false);
app.addEventListener('change', update_info, false);
update_info();
update_info();
}
};
onUiUpdate(DumpUnet.applySizeCallback);

View File

@ -10,9 +10,13 @@ onUiUpdate(() => {
const app = gradioApp();
if (!app || app === document) return;
const unet_tab = app.querySelector('#dumpunet-features-tab'),
prompt_tab = app.querySelector('#dumpunet-layerprompt-tab');
if (!unet_tab || !prompt_tab) return;
const tabs = {};
for (let mode of ['txt2img', 'img2img']) {
const unet_tab = app.querySelector(`#dumpunet-${mode}-features-tab`),
prompt_tab = app.querySelector(`#dumpunet-${mode}-layerprompt-tab`);
if (!unet_tab || !prompt_tab) return;
tabs[mode] = { unet: unet_tab, prompt: prompt_tab };
}
const disableChildren = function (ele, excepts) {
for (let e of ele.querySelectorAll('textarea, input, select')) {
@ -39,14 +43,12 @@ onUiUpdate(() => {
};
};
//unet = apply(unet_tab, '#dumpunet-features-checkbox input[type=checkbox]');
prompt = apply(prompt_tab, '#dumpunet-layerprompt-checkbox input[type=checkbox]');
//unet_tab.addEventListener('change', unet, false);
prompt_tab.addEventListener('change', prompt, false);
//unet();
prompt();
for (let mode of ['txt2img', 'img2img']) {
const tab = tabs[mode];
const prompt = apply(tab.prompt, `#dumpunet-${mode}-layerprompt-checkbox input[type=checkbox]`);
tab.prompt.addEventListener('change', prompt, false);
prompt();
}
DumpUnet.featureEnablerCallbackCalled = true;
};

View File

@ -31,87 +31,90 @@ class Script(scripts.Script):
def ui(self, is_img2img):
with gr.Group(elem_id="dumpunet-ui"):
with gr.Tab("U-Net features", elem_id="dumpunet-features-tab"):
ID_PREFIX = "dumpunet"
def id(x):
return f"{ID_PREFIX}-{'img2img' if is_img2img else 'txt2img'}-{x}"
with gr.Group(elem_id=id("ui")):
with gr.Tab("U-Net features", elem_id=id("features-tab")):
unet_features_enabled = gr.Checkbox(
label="Extract U-Net features",
value=False,
elem_id="dumpunet-features-checkbox"
elem_id=id("features-checkbox")
)
with gr.Group(elem_id="dumpunet-features-image"):
with gr.Group(elem_id=id("features-image")):
layer = gr.Textbox(
label="Layers",
placeholder="eg. IN00-OUT03(+2),OUT10",
elem_id="dumpunet-features-layer",
elem_id=id("features-layer"),
)
layer_setting_hidden = gr.HTML(
json.dumps(layerinfo.Settings),
visible=False,
elem_id="dumpunet-features-layer_setting"
elem_id=id("features-layer_setting")
)
steps = gr.Textbox(
label="Image saving steps",
placeholder="eg. 1,5-20(+5)",
elem_id="dumpunet-features-steps"
elem_id=id("features-steps")
)
color = gr.Checkbox(
False,
label="Use red/blue color map (red=POSITIVE, black=ZERO, blue=NEGATIVE)",
elem_id="dumpunet-features-color"
elem_id=id("features-color")
)
with gr.Group(elem_id="dumpunet-features-tensor"):
with gr.Group(elem_id=id("features-tensor")):
path_on = gr.Checkbox(
False,
label="Dump feature tensors to files",
elem_id="dumpunet-features-dump"
elem_id=id("features-dump")
)
path = gr.Textbox(
label="Output path",
placeholder="eg. /home/hnmr/unet/",
elem_id="dumpunet-features-dumppath"
elem_id=id("features-dumppath")
)
with gr.Accordion("Selected Layer Info", open=False):
layer_info = gr.HTML(elem_id="dumpunet-features-layerinfo")
layer_info = gr.HTML(elem_id=id("features-layerinfo"))
with gr.Tab("Layer Prompt", elem_id="dumpunet-layerprompt-tab"):
#with gr.Group(elem_id="dumpunet-layerprompt"):
with gr.Tab("Layer Prompt", elem_id=id("layerprompt-tab")):
layerprompt_enabled = gr.Checkbox(
label="Enable Layer Prompt",
value=False,
elem_id="dumpunet-layerprompt-checkbox"
elem_id=id("layerprompt-checkbox")
)
with gr.Group(elem_id="dumpunet-layerprompt-stdout"):
with gr.Group(elem_id=id("layerprompt-stdout")):
layerprompt_show_prompts = gr.Checkbox(
label="Show prompts in stdout",
value=False,
elem_id="dumpunet-layerprompt-stdout-checkbox"
elem_id=id("layerprompt-stdout-checkbox")
)
with gr.Group(elem_id="dumpunet-layerprompt-diff"):
with gr.Group(elem_id=id("layerprompt-diff")):
layerprompt_diff_enabled = gr.Checkbox(
label="Output difference map of U-Net features between with and without Layer Prompt",
value=False,
elem_id="dumpunet-layerprompt-diff-checkbox"
elem_id=id("layerprompt-diff-checkbox")
)
diff_path_on = gr.Checkbox(
False,
label="Dump difference tensors to files",
elem_id="dumpunet-layerprompt-diff-dump"
elem_id=id("layerprompt-diff-dump")
)
diff_path = gr.Textbox(
label="Output path",
placeholder="eg. /home/hnmr/unet/",
elem_id="dumpunet-layerprompt-diff-dumppath"
elem_id=id("layerprompt-diff-dumppath")
)
#with gr.Accordion("Prompt Errors", open=False):
@ -335,9 +338,19 @@ def copy_processing(p: StableDiffusionProcessing):
t2i_args = {
"enable_hr": p.enable_hr,
"denoising_strength": p.denoising_strength,
"firstphase_width": p.firstphase_width,
"firstphase_height": p.firstphase_height
"hr_scale": p.hr_scale,
"hr_upscaler": p.hr_upscaler,
"hr_second_pass_steps": p.hr_second_pass_steps,
"hr_resize_x": p.hr_resize_x,
"hr_resize_y": p.hr_resize_y,
}
if p.hr_upscale_to_x != 0 or p.hr_upscale_to_y != 0:
t2i_args.update({
"firstphase_width": p.width,
"firstphase_height": p.height,
"width": p.hr_upscale_to_x,
"height": p.hr_upscale_to_y,
})
if isinstance(p, StableDiffusionProcessingImg2Img):
i2i_args = {
@ -359,8 +372,8 @@ def copy_processing(p: StableDiffusionProcessing):
pp = type(p)(**args)
pp.prompt_for_display = p.prompt_for_display
pp.paste_to = p.paste_to
pp.color_corrections = p.color_corrections
pp.paste_to = p.paste_to # type: ignore
pp.color_corrections = p.color_corrections # type: ignore
pp.sampler_noise_scheduler_override = p.sampler_noise_scheduler_override
pp.is_using_inpainting_conditioning = p.is_using_inpainting_conditioning
pp.scripts = p.scripts
@ -373,7 +386,8 @@ def copy_processing(p: StableDiffusionProcessing):
for attr in [
"sampler",
"truncate_x", "truncate_y",
"init_latent", "latent_mask", "mask_for_overlay", "mask", "nmask", "image_conditioning"
"init_latent", "latent_mask", "mask_for_overlay", "mask", "nmask", "image_conditioning",
]:
if hasattr(p, attr):
setattr(pp, attr, getattr(p, attr))

View File

@ -1,16 +1,22 @@
#dumpunet-features-layerinfo,
#dumpunet-layerprompt-errors {
#dumpunet-txt2img-features-layerinfo,
#dumpunet-img2img-features-layerinfo,
#dumpunet-txt2img-layerprompt-errors,
#dumpunet-img2img-layerprompt-errors {
font-family: monospace;
}
#dumpunet-features-checkbox,
#dumpunet-layerprompt-checkbox {
#dumpunet-txt2img-features-checkbox,
#dumpunet-img2img-features-checkbox,
#dumpunet-txt2img-layerprompt-checkbox,
#dumpunet-img2img-layerprompt-checkbox {
/* background-color: #fff8f0; */
background-color: rgb(255 248 240 / var(--tw-bg-opacity));
}
.dark #dumpunet-features-checkbox,
.dark #dumpunet-layerprompt-checkbox {
.dark #dumpunet-txt2img-features-checkbox,
.dark #dumpunet-img2img-features-checkbox,
.dark #dumpunet-txt2img-layerprompt-checkbox,
.dark #dumpunet-img2img-layerprompt-checkbox {
/*background-color: inherit;
filter: contrast(1.5);*/
background-color: rgb(59 77 103 / var(--tw-bg-opacity));