From 46e4d94a46cf918cdf56e5a68bcdc8efdc7c8075 Mon Sep 17 00:00:00 2001 From: Won-Kyu Park Date: Tue, 3 Oct 2023 20:03:37 +0900 Subject: [PATCH 01/14] feat: live preview (#352) --- scripts/!adetailer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/!adetailer.py b/scripts/!adetailer.py index 544e7b2..1b7ca40 100644 --- a/scripts/!adetailer.py +++ b/scripts/!adetailer.py @@ -579,6 +579,7 @@ class AfterDetailerScript(scripts.Script): pred = predictor(ad_model, pp.image, args.ad_confidence, **kwargs) masks = self.pred_preprocessing(pred, args) + shared.state.assign_current_image(pred.preview) if not masks: print( From 5021519fef7516b3e0cc24217587cd631a9cd2c7 Mon Sep 17 00:00:00 2001 From: Bingsu Date: Sat, 7 Oct 2023 13:06:13 +0900 Subject: [PATCH 02/14] fix: check hf download failure --- adetailer/__version__.py | 2 +- adetailer/common.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/adetailer/__version__.py b/adetailer/__version__.py index 88729b7..9d08e17 100644 --- a/adetailer/__version__.py +++ b/adetailer/__version__.py @@ -1 +1 @@ -__version__ = "23.9.3" +__version__ = "23.10.0.dev0" diff --git a/adetailer/common.py b/adetailer/common.py index a29bdd5..3bf81cb 100644 --- a/adetailer/common.py +++ b/adetailer/common.py @@ -10,6 +10,7 @@ from PIL import Image, ImageDraw from rich import print repo_id = "Bingsu/adetailer" +_download_failed = False @dataclass @@ -20,12 +21,18 @@ class PredictOutput: def hf_download(file: str): + global _download_failed + + if _download_failed: + return "INVALID" + try: path = hf_hub_download(repo_id, file) except Exception: msg = f"[-] ADetailer: Failed to load model {file!r} from huggingface" print(msg) path = "INVALID" + _download_failed = True return path From b9dfbf8ce1534f2c757b02915013ed9c221f8929 Mon Sep 17 00:00:00 2001 From: Bingsu Date: Sat, 7 Oct 2023 13:18:57 +0900 Subject: [PATCH 03/14] fix: checking ad enabled --- adetailer/__init__.py | 3 +-- adetailer/args.py | 11 ----------- scripts/!adetailer.py | 13 ++++++++----- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/adetailer/__init__.py b/adetailer/__init__.py index dae6181..0ee909c 100644 --- a/adetailer/__init__.py +++ b/adetailer/__init__.py @@ -1,5 +1,5 @@ from .__version__ import __version__ -from .args import AD_ENABLE, ALL_ARGS, ADetailerArgs, EnableChecker +from .args import AD_ENABLE, ALL_ARGS, ADetailerArgs from .common import PredictOutput, get_models from .mediapipe import mediapipe_predict from .ultralytics import ultralytics_predict @@ -12,7 +12,6 @@ __all__ = [ "ADetailerArgs", "AFTER_DETAILER", "ALL_ARGS", - "EnableChecker", "PredictOutput", "get_models", "mediapipe_predict", diff --git a/adetailer/args.py b/adetailer/args.py index ea22b99..9aaa4cf 100644 --- a/adetailer/args.py +++ b/adetailer/args.py @@ -185,17 +185,6 @@ class ADetailerArgs(BaseModel, extra=Extra.forbid): return p -class EnableChecker(BaseModel): - enable: bool - arg_list: list - - def is_enabled(self) -> bool: - ad_model = ALL_ARGS[0].attr - if not self.enable: - return False - return any(arg.get(ad_model, "None") != "None" for arg in self.arg_list) - - _all_args = [ ("ad_enable", "ADetailer enable"), ("ad_model", "ADetailer model"), diff --git a/scripts/!adetailer.py b/scripts/!adetailer.py index 1b7ca40..f4c1094 100644 --- a/scripts/!adetailer.py +++ b/scripts/!adetailer.py @@ -24,7 +24,7 @@ from adetailer import ( mediapipe_predict, ultralytics_predict, ) -from adetailer.args import ALL_ARGS, BBOX_SORTBY, ADetailerArgs, EnableChecker +from adetailer.args import ALL_ARGS, BBOX_SORTBY, ADetailerArgs from adetailer.common import PredictOutput from adetailer.mask import ( filter_by_ratio, @@ -176,7 +176,7 @@ class AfterDetailerScript(scripts.Script): def is_ad_enabled(self, *args_) -> bool: arg_list = [arg for arg in args_ if isinstance(arg, dict)] - if not args_ or not arg_list or not isinstance(args_[0], (bool, dict)): + if not args_ or not arg_list: message = f""" [-] ADetailer: Invalid arguments passed to ADetailer. input: {args_!r} @@ -184,9 +184,10 @@ class AfterDetailerScript(scripts.Script): """ print(dedent(message), file=sys.stderr) return False - enable = args_[0] if isinstance(args_[0], bool) else True - checker = EnableChecker(enable=enable, arg_list=arg_list) - return checker.is_enabled() + + ad_enabled = args_[0] if isinstance(args_[0], bool) else True + not_none = any(arg.get("ad_model", "None") != "None" for arg in arg_list) + return ad_enabled and not_none def get_args(self, p, *args_) -> list[ADetailerArgs]: """ @@ -544,6 +545,8 @@ class AfterDetailerScript(scripts.Script): arg_list = self.get_args(p, *args_) extra_params = self.extra_params(arg_list) p.extra_generation_params.update(extra_params) + else: + p._ad_disabled = True def _postprocess_image_inner( self, p, pp, args: ADetailerArgs, *, n: int = 0 From f1535afd7c9e035d6b1bd829c08c3d079966e486 Mon Sep 17 00:00:00 2001 From: Bingsu Date: Sat, 7 Oct 2023 14:21:36 +0900 Subject: [PATCH 04/14] feat: skip img2img --- adetailer/ui.py | 10 +++++++++- scripts/!adetailer.py | 28 +++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/adetailer/ui.py b/adetailer/ui.py index b05e3aa..89e20f7 100644 --- a/adetailer/ui.py +++ b/adetailer/ui.py @@ -91,6 +91,14 @@ def adui( elem_id=eid("ad_enable"), ) + with gr.Column(scale=6): + ad_skip_img2img = gr.Checkbox( + label="Skip img2img", + value=False, + visible=is_img2img, + elem_id=eid("ad_skip_img2img"), + ) + with gr.Column(scale=1, min_width=180): gr.Markdown( f"v{__version__}", @@ -112,7 +120,7 @@ def adui( infotext_fields.extend(infofields) # components: [bool, dict, dict, ...] - components = [ad_enable, *states] + components = [ad_enable, ad_skip_img2img, *states] return components, infotext_fields diff --git a/scripts/!adetailer.py b/scripts/!adetailer.py index f4c1094..006d3af 100644 --- a/scripts/!adetailer.py +++ b/scripts/!adetailer.py @@ -189,6 +189,20 @@ class AfterDetailerScript(scripts.Script): not_none = any(arg.get("ad_model", "None") != "None" for arg in arg_list) return ad_enabled and not_none + def check_skip_img2img(self, p, *args_) -> None: + if ( + hasattr(p, "_ad_skip_img2img") + or not hasattr(p, "init_images") + or not p.init_images + ): + return + + if len(args_) >= 2 and isinstance(args_[1], bool): + p._ad_skip_img2img = args_[1] + if args_[1]: + p._ad_orig_steps = p.steps + p.steps = 1 + def get_args(self, p, *args_) -> list[ADetailerArgs]: """ `args_` is at least 1 in length by `is_ad_enabled` immediately above @@ -199,6 +213,7 @@ class AfterDetailerScript(scripts.Script): message = f"[-] ADetailer: Invalid arguments passed to ADetailer: {args_!r}" raise ValueError(message) + self.check_skip_img2img(p, *args_) if hasattr(p, "adetailer_xyz"): args[0] = {**args[0], **p.adetailer_xyz} @@ -307,7 +322,11 @@ class AfterDetailerScript(scripts.Script): return width, height def get_steps(self, p, args: ADetailerArgs) -> int: - return args.ad_steps if args.ad_use_steps else p.steps + if args.ad_use_steps: + return args.ad_steps + if hasattr(p, "_ad_orig_steps"): + return p._ad_orig_steps + return p.steps def get_cfg_scale(self, p, args: ADetailerArgs) -> float: return args.ad_cfg_scale if args.ad_use_cfg_scale else p.cfg_scale @@ -536,6 +555,12 @@ class AfterDetailerScript(scripts.Script): bs = p.batch_size return i % bs == 0 + @staticmethod + def get_i2i_init_image(p, pp): + if getattr(p, "_ad_skip_img2img", False): + return p.init_images[0] + return pp.image + @rich_traceback def process(self, p, *args_): if getattr(p, "_ad_disabled", False): @@ -563,6 +588,7 @@ class AfterDetailerScript(scripts.Script): i = p._ad_idx + pp.image = self.get_i2i_init_image(p, pp) i2i = self.get_i2i_p(p, args, pp.image) seed, subseed = self.get_seed(p) ad_prompts, ad_negatives = self.get_prompt(p, args) From b0e2d1febda92daf25bb73cd8a586c71690b85dd Mon Sep 17 00:00:00 2001 From: Bingsu Date: Sat, 7 Oct 2023 14:22:41 +0900 Subject: [PATCH 05/14] fix: adetailer_xyz rename --- scripts/!adetailer.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/!adetailer.py b/scripts/!adetailer.py index 006d3af..103b245 100644 --- a/scripts/!adetailer.py +++ b/scripts/!adetailer.py @@ -214,8 +214,8 @@ class AfterDetailerScript(scripts.Script): raise ValueError(message) self.check_skip_img2img(p, *args_) - if hasattr(p, "adetailer_xyz"): - args[0] = {**args[0], **p.adetailer_xyz} + if hasattr(p, "_ad_xyz"): + args[0] = {**args[0], **p._ad_xyz} all_inputs = [] @@ -788,9 +788,9 @@ def make_axis_on_xyz_grid(): samplers = [sampler.name for sampler in all_samplers] def set_value(p, x, xs, *, field: str): - if not hasattr(p, "adetailer_xyz"): - p.adetailer_xyz = {} - p.adetailer_xyz[field] = x + if not hasattr(p, "_ad_xyz"): + p._ad_xyz = {} + p._ad_xyz[field] = x axis = [ xyz_grid.AxisOption( From fdfa92e07cd3bc16e4437bbb610016bb908cd767 Mon Sep 17 00:00:00 2001 From: Bingsu Date: Sat, 7 Oct 2023 14:48:12 +0900 Subject: [PATCH 06/14] fix: remove AD_ENABLE arg --- adetailer/__init__.py | 3 +-- adetailer/args.py | 6 ++---- adetailer/ui.py | 7 ++++--- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/adetailer/__init__.py b/adetailer/__init__.py index 0ee909c..ce38959 100644 --- a/adetailer/__init__.py +++ b/adetailer/__init__.py @@ -1,5 +1,5 @@ from .__version__ import __version__ -from .args import AD_ENABLE, ALL_ARGS, ADetailerArgs +from .args import ALL_ARGS, ADetailerArgs from .common import PredictOutput, get_models from .mediapipe import mediapipe_predict from .ultralytics import ultralytics_predict @@ -8,7 +8,6 @@ AFTER_DETAILER = "ADetailer" __all__ = [ "__version__", - "AD_ENABLE", "ADetailerArgs", "AFTER_DETAILER", "ALL_ARGS", diff --git a/adetailer/args.py b/adetailer/args.py index 9aaa4cf..503eebb 100644 --- a/adetailer/args.py +++ b/adetailer/args.py @@ -2,7 +2,7 @@ from __future__ import annotations from collections import UserList from functools import cached_property, partial -from typing import Any, Literal, NamedTuple, Optional, Union +from typing import Any, Literal, NamedTuple, Optional import pydantic from pydantic import ( @@ -186,7 +186,6 @@ class ADetailerArgs(BaseModel, extra=Extra.forbid): _all_args = [ - ("ad_enable", "ADetailer enable"), ("ad_model", "ADetailer model"), ("ad_prompt", "ADetailer prompt"), ("ad_negative_prompt", "ADetailer negative prompt"), @@ -227,8 +226,7 @@ _all_args = [ ("ad_controlnet_guidance_end", "ADetailer ControlNet guidance end"), ] -AD_ENABLE = Arg(*_all_args[0]) -_args = [Arg(*args) for args in _all_args[1:]] +_args = [Arg(*args) for args in _all_args] ALL_ARGS = ArgsList(_args) BBOX_SORTBY = [ diff --git a/adetailer/ui.py b/adetailer/ui.py index 89e20f7..81815c1 100644 --- a/adetailer/ui.py +++ b/adetailer/ui.py @@ -3,12 +3,12 @@ from __future__ import annotations from dataclasses import dataclass from functools import partial from types import SimpleNamespace -from typing import Any, Callable +from typing import Any import gradio as gr from adetailer import AFTER_DETAILER, __version__ -from adetailer.args import AD_ENABLE, ALL_ARGS, MASK_MERGE_INVERT +from adetailer.args import ALL_ARGS, MASK_MERGE_INVERT from controlnet_ext import controlnet_exists, get_cn_models cn_module_choices = [ @@ -105,7 +105,8 @@ def adui( elem_id=eid("ad_version"), ) - infotext_fields.append((ad_enable, AD_ENABLE.name)) + infotext_fields.append(("ad_enable", "ADetailer enable")) + infotext_fields.append(("ad_skip_img2img", "ADetailer skip img2img")) with gr.Group(), gr.Tabs(): for n in range(num_models): From 5038a7cd292e087c99308df5a428b260c387edc8 Mon Sep 17 00:00:00 2001 From: Bingsu Date: Sat, 7 Oct 2023 15:05:40 +0900 Subject: [PATCH 07/14] fix: don't save before image when skipped --- scripts/!adetailer.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/!adetailer.py b/scripts/!adetailer.py index 103b245..6dbcc25 100644 --- a/scripts/!adetailer.py +++ b/scripts/!adetailer.py @@ -202,6 +202,8 @@ class AfterDetailerScript(scripts.Script): if args_[1]: p._ad_orig_steps = p.steps p.steps = 1 + else: + p._ad_skip_img2img = False def get_args(self, p, *args_) -> list[ADetailerArgs]: """ @@ -685,7 +687,7 @@ class AfterDetailerScript(scripts.Script): continue is_processed |= self._postprocess_image_inner(p, pp, args, n=n) - if is_processed: + if is_processed and not getattr(p, "_ad_skip_img2img", False): self.save_image( p, init_image, condition="ad_save_images_before", suffix="-ad-before" ) From 5a8f303c5c6af3fa1e88c9f860b07d4fbd79e693 Mon Sep 17 00:00:00 2001 From: Bingsu Date: Sat, 7 Oct 2023 15:13:11 +0900 Subject: [PATCH 08/14] docs: update readme --- README.md | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index d6fe5e4..3a00116 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# !After Detailer +# ADetailer -!After Detailer is a extension for stable diffusion webui, similar to Detection Detailer, except it uses ultralytics instead of the mmdet. +ADetailer is a extension for stable diffusion webui, similar to Detection Detailer, except it uses ultralytics instead of the mmdet. ## Install @@ -22,15 +22,17 @@ You **DON'T** need to download any model from huggingface. ## Options -| Model, Prompts | | | -| --------------------------------- | ------------------------------------- | ------------------------------------------------- | -| ADetailer model | Determine what to detect. | `None` = disable | -| ADetailer prompt, negative prompt | Prompts and negative prompts to apply | If left blank, it will use the same as the input. | +| Model, Prompts | | | +| --------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------- | +| ADetailer model | Determine what to detect. | `None` = disable | +| ADetailer prompt, negative prompt | Prompts and negative prompts to apply | If left blank, it will use the same as the input. | +| Skip img2img | Skip img2img. In practice, this works by changing the step count of img2img to 1. | img2img only | -| Detection | | | -| ------------------------------------ | -------------------------------------------------------------------------------------------- | --- | -| Detection model confidence threshold | Only objects with a detection model confidence above this threshold are used for inpainting. | | -| Mask min/max ratio | Only use masks whose area is between those ratios for the area of the entire image. | | +| Detection | | | +| ------------------------------------ | -------------------------------------------------------------------------------------------- | ------------ | +| Detection model confidence threshold | Only objects with a detection model confidence above this threshold are used for inpainting. | | +| Mask min/max ratio | Only use masks whose area is between those ratios for the area of the entire image. | | +| Mask only the top k largest | Only use the k objects with the largest area of the bbox. | 0 to disable | If you want to exclude objects in the background, try setting the min ratio to around `0.01`. @@ -86,9 +88,10 @@ Put your [ultralytics](https://github.com/ultralytics/ultralytics) yolo model in It must be a bbox detection or segment model and use all label. -## Example +## How it works -![image](https://i.imgur.com/38RSxSO.png) -![image](https://i.imgur.com/2CYgjLx.png) +ADetailer works in three simple steps. -[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/F1F1L7V2N) +1. Create an image. +2. Detect object with a detection model and create a mask image. +3. Inpaint using the image from 1 and the mask from 2. From 10e6c6e6ef47eb88eb9d384c49532cddf8919de5 Mon Sep 17 00:00:00 2001 From: Bingsu Date: Sat, 7 Oct 2023 15:15:29 +0900 Subject: [PATCH 09/14] fix: remove experimental --- adetailer/ui.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adetailer/ui.py b/adetailer/ui.py index 81815c1..3481b55 100644 --- a/adetailer/ui.py +++ b/adetailer/ui.py @@ -430,7 +430,7 @@ def inpainting(w: Widgets, n: int, is_img2img: bool, webui_info: WebuiInfo): with gr.Row(): with gr.Column(variant="compact"): w.ad_use_checkpoint = gr.Checkbox( - label="Use separate checkpoint (experimental)" + suffix(n), + label="Use separate checkpoint" + suffix(n), value=False, visible=True, elem_id=eid("ad_use_checkpoint"), @@ -448,7 +448,7 @@ def inpainting(w: Widgets, n: int, is_img2img: bool, webui_info: WebuiInfo): with gr.Column(variant="compact"): w.ad_use_vae = gr.Checkbox( - label="Use separate VAE (experimental)" + suffix(n), + label="Use separate VAE" + suffix(n), value=False, visible=True, elem_id=eid("ad_use_vae"), From 385a44d1e46e7a48ed7f28d80a67fd50af260ce7 Mon Sep 17 00:00:00 2001 From: Bingsu Date: Sat, 7 Oct 2023 15:16:02 +0900 Subject: [PATCH 10/14] chore: v23.10.0 --- CHANGELOG.md | 7 +++++++ adetailer/__version__.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2196f8..03c9400 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 2023-10-07 + +- v23.10.0 +- 허깅페이스 모델을 다운로드 실패했을 때, 계속 다운로드를 시도하지 않음 +- img2img에서 img2img단계를 건너뛰는 기능 추가 +- live preview에서 감지 단계를 보여줌 (PR #352) + ## 2023-09-20 - v23.9.3 diff --git a/adetailer/__version__.py b/adetailer/__version__.py index 9d08e17..32f93ce 100644 --- a/adetailer/__version__.py +++ b/adetailer/__version__.py @@ -1 +1 @@ -__version__ = "23.10.0.dev0" +__version__ = "23.10.0" From eeb0a3f2f449288bfa9c5fc356ea8863713d6e3d Mon Sep 17 00:00:00 2001 From: Bingsu Date: Sat, 7 Oct 2023 15:17:02 +0900 Subject: [PATCH 11/14] chore: update deps --- .pre-commit-config.yaml | 2 +- install.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index af459ce..421c213 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ repos: - id: mixed-line-ending - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.0.290" + rev: "v0.0.292" hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] diff --git a/install.py b/install.py index ceab808..12cc6a6 100644 --- a/install.py +++ b/install.py @@ -44,7 +44,7 @@ def run_pip(*args): def install(): deps = [ # requirements - ("ultralytics", "8.0.181", None), + ("ultralytics", "8.0.194", None), ("mediapipe", "0.10.5", None), ("rich", "13.0.0", None), # mediapipe From a1913e644f1cebc45d4c7d9b071830da0c4efa37 Mon Sep 17 00:00:00 2001 From: Bingsu Date: Sat, 7 Oct 2023 21:23:50 +0900 Subject: [PATCH 12/14] fix: infotext fields component type --- adetailer/ui.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adetailer/ui.py b/adetailer/ui.py index 3481b55..8a218e1 100644 --- a/adetailer/ui.py +++ b/adetailer/ui.py @@ -105,8 +105,8 @@ def adui( elem_id=eid("ad_version"), ) - infotext_fields.append(("ad_enable", "ADetailer enable")) - infotext_fields.append(("ad_skip_img2img", "ADetailer skip img2img")) + infotext_fields.append((ad_enable, "ADetailer enable")) + infotext_fields.append((ad_skip_img2img, "ADetailer skip img2img")) with gr.Group(), gr.Tabs(): for n in range(num_models): From 44453dcff13e890f484288a257eca6687f05141b Mon Sep 17 00:00:00 2001 From: Bingsu Date: Sat, 7 Oct 2023 21:39:22 +0900 Subject: [PATCH 13/14] fix: check and restore p steps --- scripts/!adetailer.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/!adetailer.py b/scripts/!adetailer.py index 6dbcc25..06f918d 100644 --- a/scripts/!adetailer.py +++ b/scripts/!adetailer.py @@ -215,7 +215,6 @@ class AfterDetailerScript(scripts.Script): message = f"[-] ADetailer: Invalid arguments passed to ADetailer: {args_!r}" raise ValueError(message) - self.check_skip_img2img(p, *args_) if hasattr(p, "_ad_xyz"): args[0] = {**args[0], **p._ad_xyz} @@ -570,6 +569,7 @@ class AfterDetailerScript(scripts.Script): if self.is_ad_enabled(*args_): arg_list = self.get_args(p, *args_) + self.check_skip_img2img(p, *args_) extra_params = self.extra_params(arg_list) p.extra_generation_params.update(extra_params) else: @@ -665,11 +665,12 @@ class AfterDetailerScript(scripts.Script): @rich_traceback def postprocess_image(self, p, pp, *args_): - if getattr(p, "_ad_disabled", False): + if getattr(p, "_ad_disabled", False) or not self.is_ad_enabled(*args_): return - if not self.is_ad_enabled(*args_): - return + if hasattr(p, "_ad_orig_steps"): + p.steps = p._ad_orig_steps + del p._ad_orig_steps p._ad_idx = getattr(p, "_ad_idx", -1) + 1 init_image = copy(pp.image) From e682eae794941411447e00cb47f544e4beec92db Mon Sep 17 00:00:00 2001 From: Bingsu Date: Sat, 7 Oct 2023 21:53:20 +0900 Subject: [PATCH 14/14] refactor: reduce complexity (C901) --- scripts/!adetailer.py | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/scripts/!adetailer.py b/scripts/!adetailer.py index 06f918d..c507068 100644 --- a/scripts/!adetailer.py +++ b/scripts/!adetailer.py @@ -5,7 +5,7 @@ import platform import re import sys import traceback -from contextlib import contextmanager +from contextlib import contextmanager, suppress from copy import copy, deepcopy from functools import partial from pathlib import Path @@ -366,9 +366,23 @@ class AfterDetailerScript(scripts.Script): ) def write_params_txt(self, p) -> None: + i = p._ad_idx + lenp = len(p.all_prompts) + if i % lenp != lenp - 1: + return + + prev = None + if hasattr(p, "_ad_orig_steps"): + prev = p.steps + p.steps = p._ad_orig_steps + infotext = self.infotext(p) params_txt = Path(data_path, "params.txt") - params_txt.write_text(infotext, encoding="utf-8") + with suppress(Exception): + params_txt.write_text(infotext, encoding="utf-8") + + if hasattr(p, "_ad_orig_steps"): + p.steps = prev def script_filter(self, p, args: ADetailerArgs): script_runner = copy(p.scripts) @@ -546,12 +560,16 @@ class AfterDetailerScript(scripts.Script): @staticmethod def need_call_process(p) -> bool: + if p.scripts is None: + return False i = p._ad_idx bs = p.batch_size return i % bs == bs - 1 @staticmethod def need_call_postprocess(p) -> bool: + if p.scripts is None: + return False i = p._ad_idx bs = p.batch_size return i % bs == 0 @@ -668,15 +686,11 @@ class AfterDetailerScript(scripts.Script): if getattr(p, "_ad_disabled", False) or not self.is_ad_enabled(*args_): return - if hasattr(p, "_ad_orig_steps"): - p.steps = p._ad_orig_steps - del p._ad_orig_steps - p._ad_idx = getattr(p, "_ad_idx", -1) + 1 init_image = copy(pp.image) arg_list = self.get_args(p, *args_) - if p.scripts is not None and self.need_call_postprocess(p): + if self.need_call_postprocess(p): dummy = Processed(p, [], p.seed, "") with preseve_prompts(p): p.scripts.postprocess(copy(p), dummy) @@ -693,17 +707,11 @@ class AfterDetailerScript(scripts.Script): p, init_image, condition="ad_save_images_before", suffix="-ad-before" ) - if p.scripts is not None and self.need_call_process(p): + if self.need_call_process(p): with preseve_prompts(p): p.scripts.process(copy(p)) - try: - ia = p._ad_idx - lenp = len(p.all_prompts) - if ia % lenp == lenp - 1: - self.write_params_txt(p) - except Exception: - pass + self.write_params_txt(p) def on_after_component(component, **_kwargs):