mirror of
https://github.com/Bing-su/adetailer.git
synced 2026-04-21 23:09:06 +00:00
Merge branch 'dev'
This commit is contained in:
@@ -17,12 +17,12 @@ repos:
|
||||
- id: mixed-line-ending
|
||||
|
||||
- repo: https://github.com/rbubley/mirrors-prettier
|
||||
rev: v3.2.5
|
||||
rev: v3.3.2
|
||||
hooks:
|
||||
- id: prettier
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.4.4
|
||||
rev: v0.4.9
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [--fix, --exit-non-zero-on-fix]
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 2024-06-16
|
||||
|
||||
- v24.6.0
|
||||
- webui 1.6.0 미만 버전을 위한 기능들을 제거하고, 최소 버전을 1.6.0으로 올림
|
||||
- 허깅페이스 연결을 체크하는데 1초만 소요되도록 함
|
||||
- 허깅페이스 미러 (hf-mirror.com)도 체크함 (합쳐서 2초)
|
||||
- InputAccordion을 적용함
|
||||
|
||||
## 2024-05-20
|
||||
|
||||
- v24.5.1
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from PIL import Image
|
||||
from rich import print
|
||||
msg = "[-] ADetailer: WebUI versions below 1.6.0 are not supported."
|
||||
|
||||
try:
|
||||
from modules.processing import create_binary_mask
|
||||
except ImportError:
|
||||
msg = "[-] ADetailer: Support for webui versions below 1.6.0 will be discontinued."
|
||||
print(msg)
|
||||
from modules.processing import create_binary_mask # noqa: F401
|
||||
except ImportError as e:
|
||||
raise RuntimeError(msg) from e
|
||||
|
||||
def create_binary_mask(image: Image.Image):
|
||||
return image.convert("L")
|
||||
|
||||
try:
|
||||
from modules.ui_components import InputAccordion # noqa: F401
|
||||
except ImportError as e:
|
||||
raise RuntimeError(msg) from e
|
||||
|
||||
|
||||
try:
|
||||
from modules.sd_schedulers import schedulers
|
||||
except ImportError:
|
||||
# webui < 1.9.0
|
||||
schedulers = []
|
||||
|
||||
@@ -3,13 +3,15 @@ from __future__ import annotations
|
||||
import io
|
||||
import platform
|
||||
import sys
|
||||
from collections.abc import Callable
|
||||
from importlib.metadata import version
|
||||
from typing import Any, Callable
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from rich.console import Console, Group
|
||||
from rich.panel import Panel
|
||||
from rich.table import Table
|
||||
from rich.traceback import Traceback
|
||||
from typing_extensions import ParamSpec
|
||||
|
||||
from adetailer.__version__ import __version__
|
||||
from adetailer.args import ADetailerArgs
|
||||
@@ -137,7 +139,11 @@ def get_table(title: str, data: dict[str, Any]) -> Table:
|
||||
return table
|
||||
|
||||
|
||||
def rich_traceback(func: Callable) -> Callable:
|
||||
P = ParamSpec("P")
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
def rich_traceback(func: Callable[P, T]) -> Callable[P, T]:
|
||||
def wrapper(*args, **kwargs):
|
||||
string = io.StringIO()
|
||||
width = Console().width
|
||||
|
||||
30
aaaaaa/ui.py
30
aaaaaa/ui.py
@@ -7,7 +7,8 @@ from typing import Any
|
||||
|
||||
import gradio as gr
|
||||
|
||||
from adetailer import AFTER_DETAILER, __version__
|
||||
from aaaaaa.conditional import InputAccordion
|
||||
from adetailer import ADETAILER, __version__
|
||||
from adetailer.args import ALL_ARGS, MASK_MERGE_INVERT
|
||||
from controlnet_ext import controlnet_exists, controlnet_type, get_cn_models
|
||||
|
||||
@@ -105,9 +106,9 @@ def on_cn_model_update(cn_model_name: str):
|
||||
|
||||
|
||||
def elem_id(item_id: str, n: int, is_img2img: bool) -> str:
|
||||
tap = "img2img" if is_img2img else "txt2img"
|
||||
tab = "img2img" if is_img2img else "txt2img"
|
||||
suf = suffix(n, "_")
|
||||
return f"script_{tap}_adetailer_{item_id}{suf}"
|
||||
return f"script_{tab}_adetailer_{item_id}{suf}"
|
||||
|
||||
|
||||
def state_init(w: Widgets) -> dict[str, Any]:
|
||||
@@ -123,17 +124,14 @@ def adui(
|
||||
infotext_fields = []
|
||||
eid = partial(elem_id, n=0, is_img2img=is_img2img)
|
||||
|
||||
with gr.Accordion(AFTER_DETAILER, open=False, elem_id=eid("ad_main_accordion")):
|
||||
with InputAccordion(
|
||||
value=False,
|
||||
elem_id=eid("ad_main_accordion"),
|
||||
label=ADETAILER,
|
||||
visible=True,
|
||||
) as ad_enable:
|
||||
with gr.Row():
|
||||
with gr.Column(scale=6):
|
||||
ad_enable = gr.Checkbox(
|
||||
label="Enable ADetailer",
|
||||
value=False,
|
||||
visible=True,
|
||||
elem_id=eid("ad_enable"),
|
||||
)
|
||||
|
||||
with gr.Column(scale=6):
|
||||
with gr.Column(scale=8):
|
||||
ad_skip_img2img = gr.Checkbox(
|
||||
label="Skip img2img",
|
||||
value=False,
|
||||
@@ -179,11 +177,11 @@ def one_ui_group(n: int, is_img2img: bool, webui_info: WebuiInfo):
|
||||
|
||||
with gr.Group():
|
||||
with gr.Row(variant="compact"):
|
||||
w.ad_tap_enable = gr.Checkbox(
|
||||
label=f"Enable this tap ({ordinal(n + 1)})",
|
||||
w.ad_tab_enable = gr.Checkbox(
|
||||
label=f"Enable this tab ({ordinal(n + 1)})",
|
||||
value=True,
|
||||
visible=True,
|
||||
elem_id=eid("ad_tap_enable"),
|
||||
elem_id=eid("ad_tab_enable"),
|
||||
)
|
||||
|
||||
with gr.Row():
|
||||
|
||||
@@ -4,12 +4,12 @@ from .common import PredictOutput, get_models
|
||||
from .mediapipe import mediapipe_predict
|
||||
from .ultralytics import ultralytics_predict
|
||||
|
||||
AFTER_DETAILER = "ADetailer"
|
||||
ADETAILER = "ADetailer"
|
||||
|
||||
__all__ = [
|
||||
"__version__",
|
||||
"ADetailerArgs",
|
||||
"AFTER_DETAILER",
|
||||
"ADETAILER",
|
||||
"ALL_ARGS",
|
||||
"PredictOutput",
|
||||
"get_models",
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "24.5.1"
|
||||
__version__ = "24.6.0"
|
||||
|
||||
@@ -55,7 +55,7 @@ class ArgsList(UserList):
|
||||
class ADetailerArgs(BaseModel, extra=Extra.forbid):
|
||||
ad_model: str = "None"
|
||||
ad_model_classes: str = ""
|
||||
ad_tap_enable: bool = True
|
||||
ad_tab_enable: bool = True
|
||||
ad_prompt: str = ""
|
||||
ad_negative_prompt: str = ""
|
||||
ad_confidence: confloat(ge=0.0, le=1.0) = 0.3
|
||||
@@ -129,7 +129,7 @@ class ADetailerArgs(BaseModel, extra=Extra.forbid):
|
||||
ppop("ADetailer model classes")
|
||||
ppop("ADetailer prompt")
|
||||
ppop("ADetailer negative prompt")
|
||||
p.pop("ADetailer tap enable", None) # always pop
|
||||
p.pop("ADetailer tab enable", None) # always pop
|
||||
ppop("ADetailer mask only top k largest", cond=0)
|
||||
ppop("ADetailer mask min ratio", cond=0.0)
|
||||
ppop("ADetailer mask max ratio", cond=1.0)
|
||||
@@ -206,13 +206,13 @@ class ADetailerArgs(BaseModel, extra=Extra.forbid):
|
||||
return self.ad_model.lower().startswith("mediapipe")
|
||||
|
||||
def need_skip(self) -> bool:
|
||||
return self.ad_model == "None" or self.ad_tap_enable is False
|
||||
return self.ad_model == "None" or self.ad_tab_enable is False
|
||||
|
||||
|
||||
_all_args = [
|
||||
("ad_model", "ADetailer model"),
|
||||
("ad_model_classes", "ADetailer model classes"),
|
||||
("ad_tap_enable", "ADetailer tap enable"),
|
||||
("ad_tab_enable", "ADetailer tab enable"),
|
||||
("ad_prompt", "ADetailer prompt"),
|
||||
("ad_negative_prompt", "ADetailer negative prompt"),
|
||||
("ad_confidence", "ADetailer confidence"),
|
||||
|
||||
@@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from contextlib import suppress
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Any, Generic, Optional, TypeVar
|
||||
@@ -24,14 +25,22 @@ class PredictOutput(Generic[T]):
|
||||
preview: Optional[Image.Image] = None
|
||||
|
||||
|
||||
def hf_download(file: str, repo_id: str = REPO_ID) -> str:
|
||||
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"
|
||||
return path
|
||||
def hf_download(file: str, repo_id: str = REPO_ID, check_remote: bool = True) -> str:
|
||||
if check_remote:
|
||||
with suppress(Exception):
|
||||
return hf_hub_download(repo_id, file, etag_timeout=1)
|
||||
|
||||
with suppress(Exception):
|
||||
return hf_hub_download(
|
||||
repo_id, file, etag_timeout=1, endpoint="https://hf-mirror.com"
|
||||
)
|
||||
|
||||
with suppress(Exception):
|
||||
return hf_hub_download(repo_id, file, local_files_only=True)
|
||||
|
||||
msg = f"[-] ADetailer: Failed to load model {file!r} from huggingface"
|
||||
print(msg)
|
||||
return "INVALID"
|
||||
|
||||
|
||||
def safe_mkdir(path: str | os.PathLike[str]) -> None:
|
||||
@@ -46,16 +55,23 @@ def scan_model_dir(path: Path) -> list[Path]:
|
||||
return [p for p in path.rglob("*") if p.is_file() and p.suffix == ".pt"]
|
||||
|
||||
|
||||
def download_models(*names: str) -> dict[str, str]:
|
||||
def download_models(*names: str, check_remote: bool = True) -> dict[str, str]:
|
||||
models = OrderedDict()
|
||||
with ThreadPoolExecutor() as executor:
|
||||
for name in names:
|
||||
if "-world" in name:
|
||||
models[name] = executor.submit(
|
||||
hf_download, name, repo_id="Bingsu/yolo-world-mirror"
|
||||
hf_download,
|
||||
name,
|
||||
repo_id="Bingsu/yolo-world-mirror",
|
||||
check_remote=check_remote,
|
||||
)
|
||||
else:
|
||||
models[name] = executor.submit(hf_download, name)
|
||||
models[name] = executor.submit(
|
||||
hf_download,
|
||||
name,
|
||||
check_remote=check_remote,
|
||||
)
|
||||
return {name: future.result() for name, future in models.items()}
|
||||
|
||||
|
||||
@@ -70,16 +86,15 @@ def get_models(
|
||||
model_paths.extend(scan_model_dir(Path(dir_)))
|
||||
|
||||
models = OrderedDict()
|
||||
if huggingface:
|
||||
to_download = [
|
||||
"face_yolov8n.pt",
|
||||
"face_yolov8s.pt",
|
||||
"hand_yolov8n.pt",
|
||||
"person_yolov8n-seg.pt",
|
||||
"person_yolov8s-seg.pt",
|
||||
"yolov8x-worldv2.pt",
|
||||
]
|
||||
models.update(download_models(*to_download))
|
||||
to_download = [
|
||||
"face_yolov8n.pt",
|
||||
"face_yolov8s.pt",
|
||||
"hand_yolov8n.pt",
|
||||
"person_yolov8n-seg.pt",
|
||||
"person_yolov8s-seg.pt",
|
||||
"yolov8x-worldv2.pt",
|
||||
]
|
||||
models.update(download_models(*to_download, check_remote=huggingface))
|
||||
|
||||
models.update(
|
||||
{
|
||||
|
||||
@@ -4,22 +4,12 @@ import importlib
|
||||
import sys
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from textwrap import dedent
|
||||
|
||||
from modules import extensions, sd_models, shared
|
||||
from modules.paths import extensions_builtin_dir, extensions_dir, models_path
|
||||
|
||||
from .common import cn_model_module, cn_model_regex
|
||||
|
||||
try:
|
||||
from modules.paths import extensions_builtin_dir, extensions_dir, models_path
|
||||
except ImportError as e:
|
||||
msg = """
|
||||
[-] ADetailer: `stable-diffusion-webui < 1.1.0` is no longer supported.
|
||||
Please upgrade to stable-diffusion-webui >= 1.1.0.
|
||||
or you can use ADetailer v23.10.1 (https://github.com/Bing-su/adetailer/archive/refs/tags/v23.10.1.zip)
|
||||
"""
|
||||
raise RuntimeError(dedent(msg)) from e
|
||||
|
||||
ext_path = Path(extensions_dir)
|
||||
ext_builtin_path = Path(extensions_builtin_dir)
|
||||
controlnet_exists = False
|
||||
|
||||
@@ -47,8 +47,6 @@ def install():
|
||||
("ultralytics", "8.2.0", None),
|
||||
("mediapipe", "0.10.13", None),
|
||||
("rich", "13.0.0", None),
|
||||
# mediapipe
|
||||
("protobuf", "4.25.3", "4.9999"),
|
||||
]
|
||||
|
||||
pkgs = []
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
name = "adetailer"
|
||||
description = "An object detection and auto-mask extension for stable diffusion webui."
|
||||
authors = [{ name = "dowon", email = "ks2515@naver.com" }]
|
||||
requires-python = ">=3.8"
|
||||
requires-python = ">=3.9"
|
||||
readme = "README.md"
|
||||
license = { text = "AGPL-3.0" }
|
||||
dependencies = [
|
||||
"ultralytics>=8.2",
|
||||
"mediapipe>=0.10",
|
||||
"mediapipe>=0.10.13",
|
||||
"pydantic<3",
|
||||
"rich>=13",
|
||||
"huggingface_hub",
|
||||
@@ -39,7 +39,7 @@ profile = "black"
|
||||
known_first_party = ["launch", "modules"]
|
||||
|
||||
[tool.ruff]
|
||||
target-version = "py38"
|
||||
target-version = "py39"
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = [
|
||||
|
||||
@@ -33,7 +33,7 @@ from aaaaaa.p_method import (
|
||||
from aaaaaa.traceback import rich_traceback
|
||||
from aaaaaa.ui import WebuiInfo, adui, ordinal, suffix
|
||||
from adetailer import (
|
||||
AFTER_DETAILER,
|
||||
ADETAILER,
|
||||
__version__,
|
||||
get_models,
|
||||
mediapipe_predict,
|
||||
@@ -110,7 +110,7 @@ class AfterDetailerScript(scripts.Script):
|
||||
return f"{self.__class__.__name__}(version={__version__})"
|
||||
|
||||
def title(self):
|
||||
return AFTER_DETAILER
|
||||
return ADETAILER
|
||||
|
||||
def show(self, is_img2img):
|
||||
return scripts.AlwaysVisible
|
||||
@@ -121,10 +121,7 @@ class AfterDetailerScript(scripts.Script):
|
||||
sampler_names = [sampler.name for sampler in all_samplers]
|
||||
scheduler_names = [x.label for x in schedulers]
|
||||
|
||||
try:
|
||||
checkpoint_list = modules.sd_models.checkpoint_tiles(use_shorts=True)
|
||||
except TypeError:
|
||||
checkpoint_list = modules.sd_models.checkpoint_tiles()
|
||||
checkpoint_list = modules.sd_models.checkpoint_tiles(use_short=True)
|
||||
vae_list = modules.shared_items.sd_vae_items()
|
||||
|
||||
webui_info = WebuiInfo(
|
||||
@@ -644,8 +641,8 @@ class AfterDetailerScript(scripts.Script):
|
||||
return pp.image
|
||||
|
||||
@staticmethod
|
||||
def get_each_tap_seed(seed: int, i: int):
|
||||
use_same_seed = shared.opts.data.get("ad_same_seed_for_each_tap", False)
|
||||
def get_each_tab_seed(seed: int, i: int):
|
||||
use_same_seed = shared.opts.data.get("ad_same_seed_for_each_tab", False)
|
||||
return seed if use_same_seed else seed + i
|
||||
|
||||
@staticmethod
|
||||
@@ -773,8 +770,8 @@ class AfterDetailerScript(scripts.Script):
|
||||
if re.match(r"^\s*\[SKIP\]\s*$", p2.prompt):
|
||||
continue
|
||||
|
||||
p2.seed = self.get_each_tap_seed(seed, j)
|
||||
p2.subseed = self.get_each_tap_seed(subseed, j)
|
||||
p2.seed = self.get_each_tab_seed(seed, j)
|
||||
p2.subseed = self.get_each_tab_seed(subseed, j)
|
||||
|
||||
p2.cached_c = [None, None]
|
||||
p2.cached_uc = [None, None]
|
||||
@@ -849,16 +846,16 @@ def on_after_component(component, **_kwargs):
|
||||
|
||||
|
||||
def on_ui_settings():
|
||||
section = ("ADetailer", AFTER_DETAILER)
|
||||
section = ("ADetailer", ADETAILER)
|
||||
shared.opts.add_option(
|
||||
"ad_max_models",
|
||||
shared.OptionInfo(
|
||||
default=4,
|
||||
label="Max models",
|
||||
label="Max tabs",
|
||||
component=gr.Slider,
|
||||
component_args={"minimum": 1, "maximum": 15, "step": 1},
|
||||
section=section,
|
||||
),
|
||||
).needs_reload_ui(),
|
||||
)
|
||||
|
||||
shared.opts.add_option(
|
||||
@@ -918,7 +915,7 @@ def on_ui_settings():
|
||||
)
|
||||
|
||||
shared.opts.add_option(
|
||||
"ad_same_seed_for_each_tap",
|
||||
"ad_same_seed_for_each_tab",
|
||||
shared.OptionInfo(
|
||||
False, "Use same seed for each tab in adetailer", section=section
|
||||
),
|
||||
|
||||
@@ -35,7 +35,7 @@ def test_need_skip(ad_model: str, expect: bool) -> None:
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("ad_model", "ad_tap_enable", "expect"),
|
||||
("ad_model", "ad_tab_enable", "expect"),
|
||||
[
|
||||
("face_yolov8n.pt", False, True),
|
||||
("mediapipe_face_full", False, True),
|
||||
@@ -43,6 +43,6 @@ def test_need_skip(ad_model: str, expect: bool) -> None:
|
||||
("ace_yolov8s.pt", True, False),
|
||||
],
|
||||
)
|
||||
def test_need_skip_tap_enable(ad_model: str, ad_tap_enable: bool, expect: bool) -> None:
|
||||
args = ADetailerArgs(ad_model=ad_model, ad_tap_enable=ad_tap_enable)
|
||||
def test_need_skip_tab_enable(ad_model: str, ad_tab_enable: bool, expect: bool) -> None:
|
||||
args = ADetailerArgs(ad_model=ad_model, ad_tab_enable=ad_tab_enable)
|
||||
assert args.need_skip() is expect
|
||||
|
||||
Reference in New Issue
Block a user