diff --git a/CHANGELOG.md b/CHANGELOG.md index 57e0791b1..85a44e360 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,9 @@ - resize type: fixed, fill, etc. - reference styles -## Update for 2024-03-14 +## Update for 2024-03-15 -### Highlights 2024-03-14 +### Highlights 2024-03-15 New models: - [Stable Cascade](https://github.com/Stability-AI/StableCascade) *Full* and *Lite* @@ -16,16 +16,16 @@ New models: - [Stable Video Diffusion XT 1.1](https://huggingface.co/stabilityai/stable-video-diffusion-img2vid-xt-1-1) - [VGen](https://huggingface.co/ali-vilab/i2vgen-xl) New pipelines and features: -- Trajectory Consistency Distillation [TCD](https://mhh0318.github.io/tcd) for generate in even less steps -- Image2image using [LEdit++](https://leditsplusplus-project.static.hf.space/index.html), context aware method with image analysis and positive/negative prompt handling +- Trajectory Consistency Distillation [TCD](https://mhh0318.github.io/tcd) for processing in even less steps +- Img2img using [LEdit++](https://leditsplusplus-project.static.hf.space/index.html), context aware method with image analysis and positive/negative prompt handling - Visual Query & Answer using [moondream2](https://github.com/vikhyat/moondream) as an addition to standard interrogate methods - Face-HiRes: simple detailer for face refinements - UI aspect-ratio controls and other UI improvements - User controllable invisibile and visible watermarking - Native composable LoRA -**Styles**: Not just for prompts! Can apply generate parameters as templates and can be used to apply wildcards to prompts -**Reference models**: *Networks -> Models -> Reference*: All reference models now come with recommended settings that can be auto-applied if desired -Additional Improvements such as: Smooth tiling, Refine/HiRes workflow improvements, Control workflow improvements, Additional API endpoints +**Styles**: Not just for prompts! Styles can apply *generate parameters* as templates and can be used to *apply wildcards* to prompts +**Reference models**: *Networks -> Models -> Reference*: All reference models now come with recommended settings that can be auto-applied if desired +Additional Improvements such as: Smooth tiling, Refine/HiRes workflow improvements, Control workflow improvements, Additional API endpoints Further details: - For basic instructions, see [README](https://github.com/vladmandic/automatic/blob/master/README.md) @@ -33,7 +33,7 @@ Further details: - For documentation, see [WiKi](https://github.com/vladmandic/automatic/wiki) - [Discord](https://discord.com/invite/sd-next-federal-batch-inspectors-1101998836328697867) server -### Full Changelog 2024-03-14 +### Full Changelog 2024-03-15 - [Stable Cascade](https://github.com/Stability-AI/StableCascade) *Full* and *Lite* - large multi-stage high-quality model from warp-ai/wuerstchen team and released by stabilityai @@ -167,6 +167,7 @@ Further details: - fix *requires_aesthetics_score* errors - fix t2i-canny - fix *differenital diffusion* for manual mask, thanks @23pennies + - fix ipadapter apply/unapply on batch runs - use default model variant if specified variant doesnt exist - use diffusers lora load override for *lcm/tcd/turbo loras* - exception handler around vram memory stats gather diff --git a/cli/clone.py b/cli/clone.py index 0fb6c626b..2ba0851d3 100755 --- a/cli/clone.py +++ b/cli/clone.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python import os import logging import git diff --git a/extensions-builtin/sd-webui-controlnet b/extensions-builtin/sd-webui-controlnet index aa2aa812e..2091b6fb2 160000 --- a/extensions-builtin/sd-webui-controlnet +++ b/extensions-builtin/sd-webui-controlnet @@ -1 +1 @@ -Subproject commit aa2aa812e86a1f47ef360572888d66027d640f60 +Subproject commit 2091b6fb21d9c76becb2a8860c8d2975ad3e428a diff --git a/modules/ipadapter.py b/modules/ipadapter.py index 217d0698c..190d9dedf 100644 --- a/modules/ipadapter.py +++ b/modules/ipadapter.py @@ -96,6 +96,8 @@ def apply(pipe, p: processing.StableDiffusionProcessing, adapter_names=[], adapt adapters = [adapter for adapter in adapters if adapter is not None and adapter.lower() != 'none'] if len(adapters) == 0: unapply(pipe) + if hasattr(p, 'ip_adapter_images'): + del p.ip_adapter_images return False if hasattr(p, 'ip_adapter_scales'): adapter_scales = p.ip_adapter_scales @@ -125,6 +127,8 @@ def apply(pipe, p: processing.StableDiffusionProcessing, adapter_names=[], adapt adapters = [] # unload adapter if previously loaded as it will cause runtime errors if len(adapters) == 0: unapply(pipe) + if hasattr(p, 'ip_adapter_images'): + del p.ip_adapter_images return False if not hasattr(pipe, 'load_ip_adapter'): shared.log.error(f'IP adapter: pipeline not supported: {pipe.__class__.__name__}') diff --git a/modules/modelloader.py b/modules/modelloader.py index d848c2a95..bb6777c20 100644 --- a/modules/modelloader.py +++ b/modules/modelloader.py @@ -399,7 +399,10 @@ def load_file_from_url(url: str, *, model_dir: str, progress: bool = True, file_ if not os.path.exists(cached_file): shared.log.info(f'Downloading: url="{url}" file={cached_file}') download_url_to_file(url, cached_file) - return cached_file + if os.path.exists(cached_file): + return cached_file + else: + return None def load_models(model_path: str, model_url: str = None, command_path: str = None, ext_filter=None, download_name=None, ext_blacklist=None) -> list: diff --git a/modules/processing.py b/modules/processing.py index d5247d8e5..f0a458340 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -251,10 +251,6 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: if p.scripts is not None and isinstance(p.scripts, scripts.ScriptRunner): p.scripts.process(p) - if shared.backend == shared.Backend.DIFFUSERS: - from modules import ipadapter - ipadapter.apply(shared.sd_model, p) - def infotext(_inxex=0): # dummy function overriden if there are iterations return '' @@ -277,6 +273,10 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed: if shared.state.interrupted: shared.log.debug(f'Process interrupted: {n+1}/{p.n_iter}') break + + if shared.backend == shared.Backend.DIFFUSERS: + from modules import ipadapter + ipadapter.apply(shared.sd_model, p) p.prompts = p.all_prompts[n * p.batch_size:(n+1) * p.batch_size] p.negative_prompts = p.all_negative_prompts[n * p.batch_size:(n+1) * p.batch_size] p.seeds = p.all_seeds[n * p.batch_size:(n+1) * p.batch_size] diff --git a/scripts/face-details.py b/scripts/face-details.py index 759fb6ec3..f10dbb72c 100644 --- a/scripts/face-details.py +++ b/scripts/face-details.py @@ -23,6 +23,8 @@ class FaceRestorerYolo(FaceRestoration): self.model_dir = os.path.join(paths.models_path, 'yolo') self.model_name = 'yolov8n-face.pt' self.model_url = 'https://github.com/akanametov/yolov8-face/releases/download/v0.0.0/yolov8n-face.pt' + # self.model_name = 'yolov9-c-face.pt' + # self.model_url = 'https://github.com/akanametov/yolov9-face/releases/download/1.0/yolov9-c-face.pt' def dependencies(self): import installer @@ -81,12 +83,11 @@ class FaceRestorerYolo(FaceRestoration): from modules import modelloader self.dependencies() if self.model is None: - model_files = modelloader.load_models(model_path=self.model_dir, model_url=self.model_url, download_name=self.model_name) - for f in model_files: - if self.model_name in f: - shared.log.info(f'Loading: type=FaceHires model={f}') - from ultralytics import YOLO # pylint: disable=import-outside-toplevel - self.model = YOLO(f) + model_file = modelloader.load_file_from_url(url=self.model_url, model_dir=self.model_dir, file_name=self.model_name) + if model_file is not None: + shared.log.info(f'Loading: type=FaceHires model={model_file}') + from ultralytics import YOLO # pylint: disable=import-outside-toplevel + self.model = YOLO(model_file) def restore(self, np_image, p: processing.StableDiffusionProcessing = None): from modules import devices, processing_class @@ -96,7 +97,7 @@ class FaceRestorerYolo(FaceRestoration): return np_image self.load() if self.model is None: - shared.log.error(f"Model load: type=FaceHires model={self.model_name} dir={self.model_dir} url={self.model_url}") + shared.log.error(f"Model load: type=FaceHires model='{self.model_name}' dir={self.model_dir} url={self.model_url}") return np_image image = Image.fromarray(np_image) faces = self.predict(image, mask=True, device=devices.device, offload=shared.opts.face_restoration_unload) diff --git a/scripts/ipadapter.py b/scripts/ipadapter.py index 5447eefd0..d9c22446a 100644 --- a/scripts/ipadapter.py +++ b/scripts/ipadapter.py @@ -82,4 +82,4 @@ class Script(scripts.Script): p.ip_adapter_starts = args[MAX_ADAPTERS*3:MAX_ADAPTERS*4][:units] if p.ip_adapter_ends == [1.0]: p.ip_adapter_ends = args[MAX_ADAPTERS*4:MAX_ADAPTERS*5][:units] - # ipadapter.apply(shared.sd_model, p, adapter_name, scale, image) # called directly from processing.process_images_inner + # ipadapter.apply(shared.sd_model, p, p.ip_adapter_names, p.ip_adapter_scales, p.ip_adapter_starts, p.ip_adapter_ends, p.ip_adapter_images) # called directly from processing.process_images_inner