From dde51c0cefaf36857a54441f68d313ad13ed3e67 Mon Sep 17 00:00:00 2001 From: patriceac <48073125+patriceac@users.noreply.github.com> Date: Sat, 29 Apr 2023 19:25:10 -0700 Subject: [PATCH 1/6] Toast notifications for ED Adding support for toast notifications for use in Core and user plugins. --- ui/media/css/main.css | 51 ++++++++++++++++++++++++++++++++++++++ ui/media/js/utils.js | 57 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/ui/media/css/main.css b/ui/media/css/main.css index 08dea664..ba513237 100644 --- a/ui/media/css/main.css +++ b/ui/media/css/main.css @@ -1302,3 +1302,54 @@ body.wait-pause { .displayNone { display:none !important; } + +/* TOAST NOTIFICATIONS */ +.toast-notification { + position: fixed; + bottom: 10px; + right: -300px; + width: 300px; + background-color: #333; + color: #fff; + padding: 10px 20px; + border-radius: 5px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); + z-index: 9999; + animation: slideInRight 0.5s ease forwards; + transition: bottom 0.5s ease; // Add a transition to smoothly reposition the toasts +} + +.toast-notification-error { + color: red; +} + +@keyframes slideInRight { + from { + right: -300px; + } + to { + right: 10px; + } +} + +.toast-notification.hide { + animation: slideOutRight 0.5s ease forwards; +} + +@keyframes slideOutRight { + from { + right: 10px; + } + to { + right: -300px; + } +} + +@keyframes slideDown { + from { + bottom: 10px; + } + to { + bottom: 0; + } +} diff --git a/ui/media/js/utils.js b/ui/media/js/utils.js index 6558f7d2..d1578d8e 100644 --- a/ui/media/js/utils.js +++ b/ui/media/js/utils.js @@ -840,3 +840,60 @@ function createTab(request) { } }) } + +/* TOAST NOTIFICATIONS */ +function showToast(message, duration = 5000, error = false) { + const toast = document.createElement("div"); + toast.classList.add("toast-notification"); + if (error === true) { + toast.classList.add("toast-notification-error"); + } + toast.innerHTML = message; + document.body.appendChild(toast); + + // Set the position of the toast on the screen + const toastCount = document.querySelectorAll(".toast-notification").length; + const toastHeight = toast.offsetHeight; + const previousToastsHeight = Array.from(document.querySelectorAll(".toast-notification")) + .slice(0, -1) // exclude current toast + .reduce((totalHeight, toast) => totalHeight + toast.offsetHeight + 10, 0); // add 10 pixels for spacing + toast.style.bottom = `${10 + previousToastsHeight}px`; + toast.style.right = "10px"; + + // Delay the removal of the toast until animation has completed + const removeToast = () => { + toast.classList.add("hide"); + const removeTimeoutId = setTimeout(() => { + toast.remove(); + // Adjust the position of remaining toasts + const remainingToasts = document.querySelectorAll(".toast-notification"); + const removedToastBottom = toast.getBoundingClientRect().bottom; + + remainingToasts.forEach((toast) => { + if (toast.getBoundingClientRect().bottom < removedToastBottom) { + toast.classList.add("slide-down"); + } + }); + + // Wait for the slide-down animation to complete + setTimeout(() => { + // Remove the slide-down class after the animation has completed + const slidingToasts = document.querySelectorAll(".slide-down"); + slidingToasts.forEach((toast) => { + toast.classList.remove("slide-down"); + }); + + // Adjust the position of remaining toasts again, in case there are multiple toasts being removed at once + const remainingToastsDown = document.querySelectorAll(".toast-notification"); + let heightSoFar = 0; + remainingToastsDown.forEach((toast) => { + toast.style.bottom = `${10 + heightSoFar}px`; + heightSoFar += toast.offsetHeight + 10; // add 10 pixels for spacing + }); + }, 0); // The duration of the slide-down animation (in milliseconds) + }, 500); + }; + + // Remove the toast after specified duration + setTimeout(removeToast, duration); +} From 654749de403ed2cc7de60d273dc6b07962580125 Mon Sep 17 00:00:00 2001 From: patriceac <48073125+patriceac@users.noreply.github.com> Date: Sat, 29 Apr 2023 19:26:11 -0700 Subject: [PATCH 2/6] Revert "Toast notifications for ED" This reverts commit dde51c0cefaf36857a54441f68d313ad13ed3e67. --- ui/media/css/main.css | 51 -------------------------------------- ui/media/js/utils.js | 57 ------------------------------------------- 2 files changed, 108 deletions(-) diff --git a/ui/media/css/main.css b/ui/media/css/main.css index ba513237..08dea664 100644 --- a/ui/media/css/main.css +++ b/ui/media/css/main.css @@ -1302,54 +1302,3 @@ body.wait-pause { .displayNone { display:none !important; } - -/* TOAST NOTIFICATIONS */ -.toast-notification { - position: fixed; - bottom: 10px; - right: -300px; - width: 300px; - background-color: #333; - color: #fff; - padding: 10px 20px; - border-radius: 5px; - box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); - z-index: 9999; - animation: slideInRight 0.5s ease forwards; - transition: bottom 0.5s ease; // Add a transition to smoothly reposition the toasts -} - -.toast-notification-error { - color: red; -} - -@keyframes slideInRight { - from { - right: -300px; - } - to { - right: 10px; - } -} - -.toast-notification.hide { - animation: slideOutRight 0.5s ease forwards; -} - -@keyframes slideOutRight { - from { - right: 10px; - } - to { - right: -300px; - } -} - -@keyframes slideDown { - from { - bottom: 10px; - } - to { - bottom: 0; - } -} diff --git a/ui/media/js/utils.js b/ui/media/js/utils.js index d1578d8e..6558f7d2 100644 --- a/ui/media/js/utils.js +++ b/ui/media/js/utils.js @@ -840,60 +840,3 @@ function createTab(request) { } }) } - -/* TOAST NOTIFICATIONS */ -function showToast(message, duration = 5000, error = false) { - const toast = document.createElement("div"); - toast.classList.add("toast-notification"); - if (error === true) { - toast.classList.add("toast-notification-error"); - } - toast.innerHTML = message; - document.body.appendChild(toast); - - // Set the position of the toast on the screen - const toastCount = document.querySelectorAll(".toast-notification").length; - const toastHeight = toast.offsetHeight; - const previousToastsHeight = Array.from(document.querySelectorAll(".toast-notification")) - .slice(0, -1) // exclude current toast - .reduce((totalHeight, toast) => totalHeight + toast.offsetHeight + 10, 0); // add 10 pixels for spacing - toast.style.bottom = `${10 + previousToastsHeight}px`; - toast.style.right = "10px"; - - // Delay the removal of the toast until animation has completed - const removeToast = () => { - toast.classList.add("hide"); - const removeTimeoutId = setTimeout(() => { - toast.remove(); - // Adjust the position of remaining toasts - const remainingToasts = document.querySelectorAll(".toast-notification"); - const removedToastBottom = toast.getBoundingClientRect().bottom; - - remainingToasts.forEach((toast) => { - if (toast.getBoundingClientRect().bottom < removedToastBottom) { - toast.classList.add("slide-down"); - } - }); - - // Wait for the slide-down animation to complete - setTimeout(() => { - // Remove the slide-down class after the animation has completed - const slidingToasts = document.querySelectorAll(".slide-down"); - slidingToasts.forEach((toast) => { - toast.classList.remove("slide-down"); - }); - - // Adjust the position of remaining toasts again, in case there are multiple toasts being removed at once - const remainingToastsDown = document.querySelectorAll(".toast-notification"); - let heightSoFar = 0; - remainingToastsDown.forEach((toast) => { - toast.style.bottom = `${10 + heightSoFar}px`; - heightSoFar += toast.offsetHeight + 10; // add 10 pixels for spacing - }); - }, 0); // The duration of the slide-down animation (in milliseconds) - }, 500); - }; - - // Remove the toast after specified duration - setTimeout(removeToast, duration); -} From a25364732b3f74dbfd5083cc4d7a0f84ccc5d9d5 Mon Sep 17 00:00:00 2001 From: patriceac <48073125+patriceac@users.noreply.github.com> Date: Wed, 17 May 2023 02:04:20 -0700 Subject: [PATCH 3/6] Support for CodeFormer Depends on https://github.com/easydiffusion/sdkit/pull/34. --- ui/easydiffusion/model_manager.py | 3 ++- ui/easydiffusion/renderer.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ui/easydiffusion/model_manager.py b/ui/easydiffusion/model_manager.py index 7bf56575..2bb4852d 100644 --- a/ui/easydiffusion/model_manager.py +++ b/ui/easydiffusion/model_manager.py @@ -107,11 +107,12 @@ def resolve_model_to_use(model_name: str = None, model_type: str = None): def reload_models_if_necessary(context: Context, task_data: TaskData): + face_correction_model = "codeformer" if "codeformer" in task_data.use_face_correction.lower() else "gfpgan" model_paths_in_req = { "stable-diffusion": task_data.use_stable_diffusion_model, "vae": task_data.use_vae_model, "hypernetwork": task_data.use_hypernetwork_model, - "gfpgan": task_data.use_face_correction, + face_correction_model: task_data.use_face_correction, "realesrgan": task_data.use_upscale, "nsfw_checker": True if task_data.block_nsfw else None, "lora": task_data.use_lora_model, diff --git a/ui/easydiffusion/renderer.py b/ui/easydiffusion/renderer.py index f685d038..e1176c8b 100644 --- a/ui/easydiffusion/renderer.py +++ b/ui/easydiffusion/renderer.py @@ -158,7 +158,9 @@ def filter_images(task_data: TaskData, images: list, user_stopped): filters_to_apply = [] if task_data.block_nsfw: filters_to_apply.append("nsfw_checker") - if task_data.use_face_correction and "gfpgan" in task_data.use_face_correction.lower(): + if task_data.use_face_correction and "codeformer" in task_data.use_face_correction.lower(): + filters_to_apply.append("codeformer") + elif task_data.use_face_correction and "gfpgan" in task_data.use_face_correction.lower(): filters_to_apply.append("gfpgan") if task_data.use_upscale and "realesrgan" in task_data.use_upscale.lower(): filters_to_apply.append("realesrgan") From a5a1d3358918626e2860db1effcabea3787fee2b Mon Sep 17 00:00:00 2001 From: patriceac <48073125+patriceac@users.noreply.github.com> Date: Sun, 21 May 2023 18:32:48 -0700 Subject: [PATCH 4/6] Fix face restoration model selection --- ui/easydiffusion/model_manager.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ui/easydiffusion/model_manager.py b/ui/easydiffusion/model_manager.py index 2bb4852d..a0b2489a 100644 --- a/ui/easydiffusion/model_manager.py +++ b/ui/easydiffusion/model_manager.py @@ -107,12 +107,18 @@ def resolve_model_to_use(model_name: str = None, model_type: str = None): def reload_models_if_necessary(context: Context, task_data: TaskData): - face_correction_model = "codeformer" if "codeformer" in task_data.use_face_correction.lower() else "gfpgan" + if hasattr(task_data, 'use_face_correction') and task_data.use_face_correction: + face_correction_model = "codeformer" if "codeformer" in task_data.use_face_correction.lower() else "gfpgan" + face_correction_value = task_data.use_face_correction + else: + face_correction_model = "gfpgan" + face_correction_value = None + model_paths_in_req = { "stable-diffusion": task_data.use_stable_diffusion_model, "vae": task_data.use_vae_model, "hypernetwork": task_data.use_hypernetwork_model, - face_correction_model: task_data.use_face_correction, + face_correction_model: face_correction_value, "realesrgan": task_data.use_upscale, "nsfw_checker": True if task_data.block_nsfw else None, "lora": task_data.use_lora_model, From 0860e35d17e15c3cf879b657fd5788b06192c6e4 Mon Sep 17 00:00:00 2001 From: cmdr2 Date: Thu, 1 Jun 2023 16:50:01 +0530 Subject: [PATCH 5/6] sdkit 1.0.101 - CodeFormer as an option to improve faces --- scripts/check_models.py | 4 ++++ scripts/check_modules.py | 2 +- ui/easydiffusion/model_manager.py | 20 +++++++++++++------- ui/easydiffusion/renderer.py | 3 +++ ui/easydiffusion/types.py | 3 ++- ui/index.html | 9 +++++++-- ui/media/css/main.css | 4 ++-- ui/media/js/main.js | 27 ++++++++++++++++++++++++--- ui/media/js/searchable-models.js | 13 ++++++++++++- 9 files changed, 68 insertions(+), 17 deletions(-) diff --git a/scripts/check_models.py b/scripts/check_models.py index 4b8d68c6..a2186727 100644 --- a/scripts/check_models.py +++ b/scripts/check_models.py @@ -24,6 +24,9 @@ models_to_check = { "vae": [ {"file_name": "vae-ft-mse-840000-ema-pruned.ckpt", "model_id": "vae-ft-mse-840000-ema-pruned"}, ], + "codeformer": [ + {"file_name": "codeformer.pth", "model_id": "codeformer-0.1.0"}, + ], } MODEL_EXTENSIONS = { # copied from easydiffusion/model_manager.py "stable-diffusion": [".ckpt", ".safetensors"], @@ -32,6 +35,7 @@ MODEL_EXTENSIONS = { # copied from easydiffusion/model_manager.py "gfpgan": [".pth"], "realesrgan": [".pth"], "lora": [".ckpt", ".safetensors"], + "codeformer": [".pth"], } diff --git a/scripts/check_modules.py b/scripts/check_modules.py index 3686ca00..416c3cc2 100644 --- a/scripts/check_modules.py +++ b/scripts/check_modules.py @@ -18,7 +18,7 @@ os_name = platform.system() modules_to_check = { "torch": ("1.11.0", "1.13.1", "2.0.0"), "torchvision": ("0.12.0", "0.14.1", "0.15.1"), - "sdkit": "1.0.98", + "sdkit": "1.0.101", "stable-diffusion-sdkit": "2.1.4", "rich": "12.6.0", "uvicorn": "0.19.0", diff --git a/ui/easydiffusion/model_manager.py b/ui/easydiffusion/model_manager.py index 2a8b57fd..458dae7f 100644 --- a/ui/easydiffusion/model_manager.py +++ b/ui/easydiffusion/model_manager.py @@ -13,6 +13,7 @@ KNOWN_MODEL_TYPES = [ "gfpgan", "realesrgan", "lora", + "codeformer", ] MODEL_EXTENSIONS = { "stable-diffusion": [".ckpt", ".safetensors"], @@ -21,6 +22,7 @@ MODEL_EXTENSIONS = { "gfpgan": [".pth"], "realesrgan": [".pth"], "lora": [".ckpt", ".safetensors"], + "codeformer": [".pth"], } DEFAULT_MODELS = { "stable-diffusion": [ # needed to support the legacy installations @@ -133,6 +135,9 @@ def reload_models_if_necessary(context: Context, task_data: TaskData): if context.model_paths.get(model_type) != path } + if task_data.codeformer_upscale_faces and "realesrgan" not in models_to_reload.keys(): + models_to_reload["realesrgan"] = resolve_model_to_use(DEFAULT_MODELS["realesrgan"][0], "realesrgan") + if set_vram_optimizations(context) or set_clip_skip(context, task_data): # reload SD models_to_reload["stable-diffusion"] = model_paths_in_req["stable-diffusion"] @@ -159,7 +164,12 @@ def resolve_model_paths(task_data: TaskData): task_data.use_lora_model = resolve_model_to_use(task_data.use_lora_model, model_type="lora") if task_data.use_face_correction: - task_data.use_face_correction = resolve_model_to_use(task_data.use_face_correction, "gfpgan") + if "gfpgan" in task_data.use_face_correction.lower(): + model_type = "gfpgan" + elif "codeformer" in task_data.use_face_correction.lower(): + model_type = "codeformer" + + task_data.use_face_correction = resolve_model_to_use(task_data.use_face_correction, model_type) if task_data.use_upscale and "realesrgan" in task_data.use_upscale.lower(): task_data.use_upscale = resolve_model_to_use(task_data.use_upscale, "realesrgan") @@ -240,17 +250,12 @@ def is_malicious_model(file_path): def getModels(): models = { - "active": { - "stable-diffusion": "sd-v1-4", - "vae": "", - "hypernetwork": "", - "lora": "", - }, "options": { "stable-diffusion": ["sd-v1-4"], "vae": [], "hypernetwork": [], "lora": [], + "codeformer": [], }, } @@ -307,6 +312,7 @@ def getModels(): listModels(model_type="hypernetwork") listModels(model_type="gfpgan") listModels(model_type="lora") + listModels(model_type="codeformer") if models_scanned > 0: log.info(f"[green]Scanned {models_scanned} models. Nothing infected[/]") diff --git a/ui/easydiffusion/renderer.py b/ui/easydiffusion/renderer.py index 1ebd05ec..4be6e6bf 100644 --- a/ui/easydiffusion/renderer.py +++ b/ui/easydiffusion/renderer.py @@ -34,6 +34,7 @@ def init(device): context.temp_images = {} context.partial_x_samples = None context.model_load_errors = {} + context.enable_codeformer = True from easydiffusion import app @@ -162,6 +163,8 @@ def filter_images(req: GenerateImageRequest, task_data: TaskData, images: list, filters_to_apply.append("nsfw_checker") if task_data.use_face_correction and "codeformer" in task_data.use_face_correction.lower(): filters_to_apply.append("codeformer") + + filter_params["upscale_faces"] = task_data.codeformer_upscale_faces elif task_data.use_face_correction and "gfpgan" in task_data.use_face_correction.lower(): filters_to_apply.append("gfpgan") if task_data.use_upscale: diff --git a/ui/easydiffusion/types.py b/ui/easydiffusion/types.py index e4426714..4559a23a 100644 --- a/ui/easydiffusion/types.py +++ b/ui/easydiffusion/types.py @@ -23,7 +23,7 @@ class GenerateImageRequest(BaseModel): sampler_name: str = None # "ddim", "plms", "heun", "euler", "euler_a", "dpm2", "dpm2_a", "lms" hypernetwork_strength: float = 0 lora_alpha: float = 0 - tiling: str = "none" # "none", "x", "y", "xy" + tiling: str = "none" # "none", "x", "y", "xy" class TaskData(BaseModel): @@ -51,6 +51,7 @@ class TaskData(BaseModel): stream_image_progress: bool = False stream_image_progress_interval: int = 5 clip_skip: bool = False + codeformer_upscale_faces: bool = False class MergeRequest(BaseModel): diff --git a/ui/index.html b/ui/index.html index 21ec2550..4167a873 100644 --- a/ui/index.html +++ b/ui/index.html @@ -263,7 +263,12 @@