mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 17:24:32 +02:00
en add sort and other updates
This commit is contained in:
+7
-4
@@ -15,21 +15,24 @@ Plus tons of fixes...
|
||||
download using built-in **Huggingface** downloader: `segmind/SSD-1B`
|
||||
- new model type: [LCM: Latent Consistency Models](https://github.com/openai/consistency_models)
|
||||
near-instant generate in a as little as 3 steps!
|
||||
combined with OpenVINO, generate on CPU takes less than 10 seconds: <https://www.youtube.com/watch?v=b90ESUTLsRo>
|
||||
download using built-in **Huggingface** downloader: `SimianLuo/LCM_Dreamshaper_v7`
|
||||
- support for **Custom pipelines**, thanks @disty0
|
||||
download using built-in **Huggingface** downloader
|
||||
think of them as plugins for diffusers not unlike original extensions that modify behavior of `ldm` backend
|
||||
list of community pipelines: <https://github.com/huggingface/diffusers/tree/main/examples/community>
|
||||
and make sure to check our reference custom pipeline: `Disty0/zero123plus-pipeline`
|
||||
which generates 4 output images with different camera positions: front, side, top, back!
|
||||
- new custom pipeline: `Disty0/zero123plus-pipeline`
|
||||
generate 4 output images with different camera positions: front, side, top, back!
|
||||
for more details, see <https://github.com/vladmandic/automatic/discussions/2421>
|
||||
- extend support for [Free-U](https://github.com/ChenyangSi/FreeU)
|
||||
improve generations quality at no cost (other than finding params that work for you)
|
||||
- **General**
|
||||
- add **Lora OFT** support, thanks @antis0007 and @ai-casanova
|
||||
- **Upscalers**
|
||||
- **compile compile** option, thanks @disty0
|
||||
- **compile** option, thanks @disty0
|
||||
- **chaiNNer** add high quality models from [Helaman](https://openmodeldb.info/users/helaman)
|
||||
- redesigned **progress bar** with full details on current operation
|
||||
- redesigned **Progress bar** with full details on current operation
|
||||
- **Extra networks** sort by name, size, date, etc.
|
||||
- new option: *settings -> images -> keep incomplete*
|
||||
can be used to skip vae decode on aborted/skipped/interrupted image generations
|
||||
- remove external clone of items in `/repositories`
|
||||
|
||||
@@ -53,6 +53,8 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage):
|
||||
"local_preview": f"{path}.{shared.opts.samples_format}",
|
||||
"metadata": json.dumps(l.metadata, indent=4) if l.metadata else None,
|
||||
"tags": tags,
|
||||
"mtime": os.path.getmtime(l.filename),
|
||||
"size": os.path.getsize(l.filename),
|
||||
}
|
||||
return item
|
||||
except Exception as e:
|
||||
|
||||
Submodule extensions-builtin/sd-webui-controlnet updated: 4ac716a6e8...f2aafcf2be
@@ -16,6 +16,7 @@
|
||||
{"id":"","label":"⇰","localized":"","hint":"Apply selected styles to current prompt"},
|
||||
{"id":"","label":"⇩","localized":"","hint":"Save parameters from last generated image as style template"},
|
||||
{"id":"","label":"🕮","localized":"","hint":"Save parameters from last generated image as style template"},
|
||||
{"id":"","label":"⇕","localized":"","hint":"Sort by: Name asc/desc, Size largest/smallest, Time newest/oldest"},
|
||||
{"id":"","label":"⟲","localized":"","hint":"Refresh"},
|
||||
{"id":"","label":"✕","localized":"","hint":"Close"},
|
||||
{"id":"","label":"⊜","localized":"","hint":"Fill"},
|
||||
|
||||
@@ -88,7 +88,8 @@ svg.feather.feather-image, .feather .feather-image { display: none }
|
||||
.tab-nav { zoom: 120%; margin-top: 10px; margin-bottom: 10px; border-bottom: 2px solid var(--highlight-color) !important; padding-bottom: 2px; }
|
||||
.label-wrap { margin: 8px 0px 4px 0px; }
|
||||
.gradio-button.tool { border: none; background: none; box-shadow: none; filter: hue-rotate(340deg) saturate(0.5); }
|
||||
#tab_extensions table td, #tab_extensions table th, #tab_config table td, #tab_config table th { border: none; padding: 0.5em; }
|
||||
#tab_extensions table td, #tab_extensions table th, #tab_config table td, #tab_config table th { border: none; }
|
||||
#tab_extensions table tr:hover, #tab_config table tr:hover { background-color: var(--neutral-500) !important; }
|
||||
#tab_extensions table, #tab_config table { width: 96vw }
|
||||
#tab_extensions table thead, #tab_config table thead { background-color: var(--neutral-700); }
|
||||
#tab_extensions table, #tab_config table { background-color: #222222; }
|
||||
|
||||
@@ -58,7 +58,8 @@ function readCardTags(el, tags) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const textarea = activePromptTextarea[getENActiveTab()];
|
||||
if (textarea.value.indexOf(tag) !== -1) textarea.value = textarea.value.replace(tag, '');
|
||||
if (textarea.value.indexOf(` ${tag}`) !== -1) textarea.value = textarea.value.replace(` ${tag}`, '');
|
||||
else if (textarea.value.indexOf(`${tag} `) !== -1) textarea.value = textarea.value.replace(` ${tag} `, '');
|
||||
else textarea.value += ` ${tag}`;
|
||||
updateInput(textarea);
|
||||
};
|
||||
@@ -144,6 +145,34 @@ function tryToRemoveExtraNetworkFromPrompt(textarea, text) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let sortVal = 0;
|
||||
|
||||
function sortExtraNetworks() {
|
||||
const sortDesc = ['Name [A-Z]', 'Name [Z-A]', 'Date [Newest]', 'Date [Oldest]', 'Size [Largest]', 'Size [Smallest]'];
|
||||
const tabname = getENActiveTab();
|
||||
const pagename = getENActivePage();
|
||||
if (!tabname || !pagename) return 'sort error: unknown page';
|
||||
const pg = gradioApp().getElementById(`${tabname.toLowerCase()}_${pagename.toLowerCase()}_cards`);
|
||||
const cards = Array.from(pg.querySelectorAll('.card') || []);
|
||||
if (cards.length === 0) return 'sort: no cards';
|
||||
cards.sort((a, b) => {
|
||||
switch (sortVal) {
|
||||
case 0: return a.dataset.name ? a.dataset.name.localeCompare(b.dataset.name) : 0;
|
||||
case 1: return b.dataset.name ? b.dataset.name.localeCompare(a.dataset.name) : 0;
|
||||
case 2: return a.dataset.mtime && !isNaN(a.dataset.mtime) ? parseFloat(b.dataset.mtime) - parseFloat(a.dataset.mtime) : 0;
|
||||
case 3: return b.dataset.mtime && !isNaN(b.dataset.mtime) ? parseFloat(a.dataset.mtime) - parseFloat(b.dataset.mtime) : 0;
|
||||
case 4: return a.dataset.size && !isNaN(a.dataset.size) ? parseFloat(b.dataset.size) - parseFloat(a.dataset.size) : 0;
|
||||
case 5: return b.dataset.size && !isNaN(b.dataset.size) ? parseFloat(a.dataset.size) - parseFloat(b.dataset.size) : 0;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
for (const card of cards) pg.appendChild(card);
|
||||
const desc = sortDesc[sortVal];
|
||||
sortVal = (sortVal + 1) % 6;
|
||||
log('sortExtraNetworks', tabname, pagename, desc);
|
||||
return `sort page ${pagename} cards ${cards.length} by ${desc}`;
|
||||
}
|
||||
|
||||
function refreshExtraNetworks(tabname) {
|
||||
log('refreshExtraNetworks', tabname, gradioApp().querySelector(`#${tabname}_extra_networks textarea`)?.value);
|
||||
gradioApp().querySelector(`#${tabname}_extra_networks textarea`)?.dispatchEvent(new Event('input'));
|
||||
@@ -195,6 +224,7 @@ function setupExtraNetworksForTab(tabname) {
|
||||
const btnScan = gradioApp().getElementById(`${tabname}_extra_scan`);
|
||||
const btnSave = gradioApp().getElementById(`${tabname}_extra_save`);
|
||||
const btnClose = gradioApp().getElementById(`${tabname}_extra_close`);
|
||||
const btnSort = gradioApp().getElementById(`${tabname}_extra_sort`);
|
||||
const btnModel = gradioApp().getElementById(`${tabname}_extra_model`);
|
||||
const btnApply = gradioApp().getElementById(`${tabname}_extra_apply`);
|
||||
const buttons = document.createElement('span');
|
||||
@@ -204,6 +234,7 @@ function setupExtraNetworksForTab(tabname) {
|
||||
if (btnApply) buttons.appendChild(btnApply);
|
||||
if (btnScan) buttons.appendChild(btnScan);
|
||||
if (btnSave) buttons.appendChild(btnSave);
|
||||
if (btnSort) buttons.appendChild(btnSort);
|
||||
if (btnClose) buttons.appendChild(btnClose);
|
||||
btnModel.onclick = () => btnModel.classList.toggle('toolbutton-selected');
|
||||
tabs.appendChild(buttons);
|
||||
|
||||
@@ -163,6 +163,7 @@ table.settings-value-table td { padding: 0.4em; border: 1px solid #ccc; max-widt
|
||||
/* extensions */
|
||||
#tab_extensions table, #tab_config table{ border-collapse: collapse; }
|
||||
#tab_extensions table td, #tab_extensions table th, #tab_config table td, #tab_config table th { border: 1px solid #ccc; padding: 0.25em 0.5em; }
|
||||
#tab_extensions table tr:hover, #tab_config table tr:hover { background-color: var(--neutral-500) !important; }
|
||||
#tab_extensions table input[type="checkbox"] { margin-right: 0.5em; appearance: checkbox; }
|
||||
#tab_extensions button{ max-width: 16em; }
|
||||
#tab_extensions input[disabled="disabled"]{ opacity: 0.5; }
|
||||
@@ -195,9 +196,10 @@ table.settings-value-table td { padding: 0.4em; border: 1px solid #ccc; max-widt
|
||||
.extra-network-cards .card:hover .overlay { background: rgba(0, 0, 0, 0.40); }
|
||||
.extra-network-cards .card:hover .preview { box-shadow: none; filter: grayscale(100%); }
|
||||
.extra-network-cards .card:hover .overlay { background: rgba(0, 0, 0, 0.40); }
|
||||
.extra-network-cards .card .overlay .tags { margin: 4px; display: none; overflow-wrap: break-word; }
|
||||
.extra-network-cards .card .overlay .tag { padding: 2px; margin: 2px; background: var(--neutral-700); cursor: pointer; display: inline-block; }
|
||||
.extra-network-cards .card .overlay .tags { display: none; overflow-wrap: break-word; }
|
||||
.extra-network-cards .card .overlay .tag { padding: 3px; background: rgba(70, 70, 70, 0.60); font-size: var(--text-lg); cursor: pointer; display: inline-block; margin-bottom: 4px; }
|
||||
.extra-network-cards .card .actions > span { padding: 4px; }
|
||||
.extra-network-cards .card .actions > span:hover { color: var(--highlight-color); }
|
||||
.extra-network-cards .card:hover .actions { display: block; }
|
||||
.extra-network-cards .card:hover .overlay .tags { display: block; }
|
||||
.extra-network-cards .card .actions { font-size: 3em; display: none; text-align-last: right; cursor: pointer; font-variant: unicase; position: absolute; z-index: 100; right: 0; height: 0.7em; width: 100%; background: rgba(0, 0, 0, 0.40); }
|
||||
|
||||
@@ -72,6 +72,30 @@ def apply_overlay(image, paste_loc, index, overlays):
|
||||
return image
|
||||
|
||||
|
||||
def create_binary_mask(image):
|
||||
if image.mode == 'RGBA' and image.getextrema()[-1] != (255, 255):
|
||||
image = image.split()[-1].convert("L").point(lambda x: 255 if x > 128 else 0)
|
||||
else:
|
||||
image = image.convert('L')
|
||||
return image
|
||||
|
||||
|
||||
def images_tensor_to_samples(image, approximation=None, model=None):
|
||||
if model is None:
|
||||
model = shared.sd_model
|
||||
model.first_stage_model.to(devices.dtype_vae)
|
||||
image = image.to(shared.device, dtype=devices.dtype_vae)
|
||||
image = image * 2 - 1
|
||||
if len(image) > 1:
|
||||
x_latent = torch.stack([
|
||||
model.get_first_stage_encoding(model.encode_first_stage(torch.unsqueeze(img, 0)))[0]
|
||||
for img in image
|
||||
])
|
||||
else:
|
||||
x_latent = model.get_first_stage_encoding(model.encode_first_stage(image))
|
||||
return x_latent
|
||||
|
||||
|
||||
def txt2img_image_conditioning(sd_model, x, width, height):
|
||||
if sd_model.model.conditioning_key in {'hybrid', 'concat'}: # Inpainting models
|
||||
# The "masked-image" in this case will just be all zeros since the entire image is masked.
|
||||
|
||||
+4
-2
@@ -9,7 +9,7 @@ from modules import paths
|
||||
|
||||
|
||||
class Style():
|
||||
def __init__(self, name: str, desc: str = "", prompt: str = "", negative_prompt: str = "", extra: str = "", filename: str = "", preview: str = ""):
|
||||
def __init__(self, name: str, desc: str = "", prompt: str = "", negative_prompt: str = "", extra: str = "", filename: str = "", preview: str = "", mtime: float = 0):
|
||||
self.name = name
|
||||
self.description = desc
|
||||
self.prompt = prompt
|
||||
@@ -17,6 +17,7 @@ class Style():
|
||||
self.extra = extra
|
||||
self.filename = filename
|
||||
self.preview = preview
|
||||
self.mtime = mtime
|
||||
|
||||
def merge_prompts(style_prompt: str, prompt: str) -> str:
|
||||
if "{prompt}" in style_prompt:
|
||||
@@ -105,7 +106,8 @@ class StyleDatabase:
|
||||
negative_prompt=style.get("negative", ""),
|
||||
extra=style.get("extra", ""),
|
||||
preview=style.get("preview", None),
|
||||
filename=fn
|
||||
filename=fn,
|
||||
mtime=os.path.getmtime(fn),
|
||||
)
|
||||
except Exception as e:
|
||||
log.error(f'Failed to load style: file={fn} error={e}')
|
||||
|
||||
@@ -118,14 +118,14 @@ class ExtraNetworksPage:
|
||||
self.list_time = 0
|
||||
# class additional is to keep old extensions happy
|
||||
self.card = '''
|
||||
<div class='card' onclick={card_click} title='{name}' data-tab='{tabname}' data-page='{page}' data-name='{name}' data-filename='{filename}' data-tags='{tags}'>
|
||||
<div class='card' onclick={card_click} title='{name}' data-tab='{tabname}' data-page='{page}' data-name='{name}' data-filename='{filename}' data-tags='{tags}' data-mtime='{mtime}' data-size='{size}'>
|
||||
<div class='overlay'>
|
||||
<span style="display:none" class='search_term'>{search_term}</span>
|
||||
<div class='tags'></div>
|
||||
<div class='name'>{title}</div>
|
||||
</div>
|
||||
<div class='actions'>
|
||||
<span title="Get details" onclick="showCardDetails(event)">🛈</span>
|
||||
<span class='details' title="Get details" onclick="showCardDetails(event)">🛈</span>
|
||||
<div class='additional'><ul></ul></div>
|
||||
</div>
|
||||
<img class='preview' src='{preview}' style='width: {width}px; height: {height}px; object-fit: {fit}' loading='lazy'></img>
|
||||
@@ -282,6 +282,8 @@ class ExtraNetworksPage:
|
||||
"search_term": item.get("search_term", ""),
|
||||
"description": item.get("description") or "",
|
||||
"card_click": item.get("onclick", '"' + html.escape(f'return cardClicked({item.get("prompt", None)}, {"true" if self.allow_negative_prompt else "false"})') + '"'),
|
||||
"mtime": item.get("mtime", 0),
|
||||
"size": item.get("size", 0),
|
||||
}
|
||||
alias = item.get("alias", None)
|
||||
if alias is not None:
|
||||
@@ -392,6 +394,7 @@ class ExtraNetworksUi:
|
||||
self.button_refresh: gr.Button = None
|
||||
self.button_scan: gr.Button = None
|
||||
self.button_save: gr.Button = None
|
||||
self.button_sort: gr.Button = None
|
||||
self.button_apply: gr.Button = None
|
||||
self.button_close: gr.Button = None
|
||||
self.button_model: gr.Checkbox = None
|
||||
@@ -485,7 +488,8 @@ def create_ui(container, button_parent, tabname, skip_indexing = False):
|
||||
ui.button_refresh = ToolButton(symbols.refresh, elem_id=tabname+"_extra_refresh")
|
||||
ui.button_scan = ToolButton(symbols.scan, elem_id=tabname+"_extra_scan", visible=True)
|
||||
ui.button_save = ToolButton(symbols.book, elem_id=tabname+"_extra_save", visible=False)
|
||||
ui.button_close = ToolButton(symbols.close, elem_id=tabname+"_extra_close")
|
||||
ui.button_sort = ToolButton(symbols.sort, elem_id=tabname+"_extra_sort", visible=True)
|
||||
ui.button_close = ToolButton(symbols.close, elem_id=tabname+"_extra_close", visible=True)
|
||||
ui.button_model = ToolButton(symbols.refine, elem_id=tabname+"_extra_model", visible=True)
|
||||
ui.search = gr.Textbox('', show_label=False, elem_id=tabname+"_extra_search", placeholder="Search...", elem_classes="textbox", lines=2, container=False)
|
||||
ui.description = gr.Textbox('', show_label=False, elem_id=tabname+"_description", elem_classes="textbox", lines=2, interactive=False, container=False)
|
||||
@@ -700,9 +704,14 @@ def create_ui(container, button_parent, tabname, skip_indexing = False):
|
||||
res = show_details(text=None, img=None, desc=None, info=None, meta=None, params=params)
|
||||
return res
|
||||
|
||||
def ui_sort_cards(msg):
|
||||
shared.log.debug(f'Extra networks: {msg}')
|
||||
return msg
|
||||
|
||||
dummy_state = gr.State(value=False) # pylint: disable=abstract-class-instantiated
|
||||
button_parent.click(fn=toggle_visibility, inputs=[ui.visible], outputs=[ui.visible, container, button_parent])
|
||||
ui.button_close.click(fn=toggle_visibility, inputs=[ui.visible], outputs=[ui.visible, container])
|
||||
ui.button_sort.click(fn=ui_sort_cards, _js='sortExtraNetworks', inputs=[ui.search], outputs=[ui.description])
|
||||
ui.button_refresh.click(fn=ui_refresh_click, _js='getENActivePage', inputs=[ui.search], outputs=ui.pages)
|
||||
ui.button_scan.click(fn=ui_scan_click, _js='getENActivePage', inputs=[ui.search], outputs=ui.pages)
|
||||
ui.button_save.click(fn=ui_save_click, inputs=[], outputs=ui.details_components + [ui.details])
|
||||
|
||||
@@ -30,6 +30,8 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage):
|
||||
"info": self.find_info(fn),
|
||||
"metadata": checkpoint.metadata,
|
||||
"onclick": '"' + html.escape(f"""return selectCheckpoint({json.dumps(name)})""") + '"',
|
||||
"mtime": os.path.getmtime(checkpoint.filename),
|
||||
"size": os.path.getsize(checkpoint.filename),
|
||||
}
|
||||
yield record
|
||||
except Exception as e:
|
||||
|
||||
@@ -25,6 +25,8 @@ class ExtraNetworksPageHypernetworks(ui_extra_networks.ExtraNetworksPage):
|
||||
"search_term": self.search_terms_from_path(name),
|
||||
"prompt": json.dumps(f"<hypernet:{name}:{shared.opts.extra_networks_default_multiplier}>"),
|
||||
"local_preview": f"{fn}.{shared.opts.samples_format}",
|
||||
"mtime": os.path.getmtime(path),
|
||||
"size": os.path.getsize(path),
|
||||
}
|
||||
except Exception as e:
|
||||
shared.log.debug(f"Extra networks error: type=hypernetwork file={path} {e}")
|
||||
|
||||
@@ -85,6 +85,8 @@ class ExtraNetworksPageStyles(ui_extra_networks.ExtraNetworksPage):
|
||||
"extra": getattr(style, 'extra', ''),
|
||||
"local_preview": f"{fn}.{shared.opts.samples_format}",
|
||||
"onclick": '"' + html.escape(f"""return selectStyle({json.dumps(name)})""") + '"',
|
||||
"mtime": getattr(style, 'mtime', 0),
|
||||
"size": os.path.getsize(style.filename),
|
||||
}
|
||||
except Exception as e:
|
||||
shared.log.debug(f"Extra networks error: type=style file={k} {e}")
|
||||
|
||||
@@ -56,6 +56,8 @@ class ExtraNetworksPageTextualInversion(ui_extra_networks.ExtraNetworksPage):
|
||||
"prompt": json.dumps(os.path.splitext(embedding.name)[0]),
|
||||
"local_preview": f"{path}.{shared.opts.samples_format}",
|
||||
"tags": tags,
|
||||
"mtime": os.path.getmtime(embedding.filename),
|
||||
"size": os.path.getsize(embedding.filename),
|
||||
}
|
||||
except Exception as e:
|
||||
shared.log.debug(f"Extra networks error: type=embedding file={embedding.filename} {e}")
|
||||
|
||||
@@ -28,6 +28,8 @@ class ExtraNetworksPageVAEs(ui_extra_networks.ExtraNetworksPage):
|
||||
"info": self.find_info(fn),
|
||||
"metadata": {},
|
||||
"onclick": '"' + html.escape(f"""return selectVAE({json.dumps(name)})""") + '"',
|
||||
"mtime": os.path.getmtime(filename),
|
||||
"size": os.path.getsize(filename),
|
||||
}
|
||||
yield record
|
||||
except Exception as e:
|
||||
|
||||
@@ -11,6 +11,7 @@ networks = '🌐'
|
||||
paste = '⇦'
|
||||
refine = '⌾'
|
||||
switch = '⇅'
|
||||
sort = '⇕'
|
||||
detect = '📐'
|
||||
folder = '📂'
|
||||
random = '🎲️'
|
||||
|
||||
+1
-1
Submodule wiki updated: 87b508db6f...2e3f371517
Reference in New Issue
Block a user