mirror of
https://github.com/lllyasviel/Fooocus.git
synced 2026-08-16 13:13:16 +02:00
wip: add adetailer
This commit is contained in:
@@ -0,0 +1,278 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import UserList
|
||||
from dataclasses import dataclass
|
||||
from functools import cached_property, partial
|
||||
from typing import Any, Literal, NamedTuple, Optional
|
||||
|
||||
try:
|
||||
from pydantic.v1 import (
|
||||
BaseModel,
|
||||
Extra,
|
||||
NonNegativeFloat,
|
||||
NonNegativeInt,
|
||||
PositiveInt,
|
||||
confloat,
|
||||
conint,
|
||||
validator,
|
||||
)
|
||||
except ImportError:
|
||||
from pydantic import (
|
||||
BaseModel,
|
||||
Extra,
|
||||
NonNegativeFloat,
|
||||
NonNegativeInt,
|
||||
PositiveInt,
|
||||
confloat,
|
||||
conint,
|
||||
validator,
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class SkipImg2ImgOrig:
|
||||
steps: int
|
||||
sampler_name: str
|
||||
width: int
|
||||
height: int
|
||||
|
||||
|
||||
class Arg(NamedTuple):
|
||||
attr: str
|
||||
name: str
|
||||
|
||||
|
||||
class ArgsList(UserList):
|
||||
@cached_property
|
||||
def attrs(self) -> tuple[str, ...]:
|
||||
return tuple(attr for attr, _ in self)
|
||||
|
||||
@cached_property
|
||||
def names(self) -> tuple[str, ...]:
|
||||
return tuple(name for _, name in self)
|
||||
|
||||
|
||||
class ADetailerArgs(BaseModel, extra=Extra.forbid):
|
||||
ad_model: str = "None"
|
||||
ad_model_classes: str = ""
|
||||
ad_tap_enable: bool = True
|
||||
ad_prompt: str = ""
|
||||
ad_negative_prompt: str = ""
|
||||
ad_confidence: confloat(ge=0.0, le=1.0) = 0.3
|
||||
ad_mask_k_largest: NonNegativeInt = 0
|
||||
ad_mask_min_ratio: confloat(ge=0.0, le=1.0) = 0.0
|
||||
ad_mask_max_ratio: confloat(ge=0.0, le=1.0) = 1.0
|
||||
ad_dilate_erode: int = 4
|
||||
ad_x_offset: int = 0
|
||||
ad_y_offset: int = 0
|
||||
ad_mask_merge_invert: Literal["None", "Merge", "Merge and Invert"] = "None"
|
||||
ad_mask_blur: NonNegativeInt = 4
|
||||
ad_denoising_strength: confloat(ge=0.0, le=1.0) = 0.4
|
||||
ad_inpaint_only_masked: bool = True
|
||||
ad_inpaint_only_masked_padding: NonNegativeInt = 32
|
||||
ad_use_inpaint_width_height: bool = False
|
||||
ad_inpaint_width: PositiveInt = 512
|
||||
ad_inpaint_height: PositiveInt = 512
|
||||
ad_use_steps: bool = False
|
||||
ad_steps: PositiveInt = 28
|
||||
ad_use_cfg_scale: bool = False
|
||||
ad_cfg_scale: NonNegativeFloat = 7.0
|
||||
ad_use_checkpoint: bool = False
|
||||
ad_checkpoint: Optional[str] = None
|
||||
ad_use_vae: bool = False
|
||||
ad_vae: Optional[str] = None
|
||||
ad_use_sampler: bool = False
|
||||
ad_sampler: str = "DPM++ 2M Karras"
|
||||
ad_scheduler: str = "Use same scheduler"
|
||||
ad_use_noise_multiplier: bool = False
|
||||
ad_noise_multiplier: confloat(ge=0.5, le=1.5) = 1.0
|
||||
ad_use_clip_skip: bool = False
|
||||
ad_clip_skip: conint(ge=1, le=12) = 1
|
||||
ad_restore_face: bool = False
|
||||
ad_controlnet_model: str = "None"
|
||||
ad_controlnet_module: str = "None"
|
||||
ad_controlnet_weight: confloat(ge=0.0, le=1.0) = 1.0
|
||||
ad_controlnet_guidance_start: confloat(ge=0.0, le=1.0) = 0.0
|
||||
ad_controlnet_guidance_end: confloat(ge=0.0, le=1.0) = 1.0
|
||||
is_api: bool = True
|
||||
|
||||
@validator("is_api", pre=True)
|
||||
def is_api_validator(cls, v: Any): # noqa: N805
|
||||
"tuple is json serializable but cannot be made with json deserialize."
|
||||
return type(v) is not tuple
|
||||
|
||||
@staticmethod
|
||||
def ppop(
|
||||
p: dict[str, Any],
|
||||
key: str,
|
||||
pops: list[str] | None = None,
|
||||
cond: Any = None,
|
||||
) -> None:
|
||||
if pops is None:
|
||||
pops = [key]
|
||||
if key not in p:
|
||||
return
|
||||
value = p[key]
|
||||
cond = (not bool(value)) if cond is None else value == cond
|
||||
|
||||
if cond:
|
||||
for k in pops:
|
||||
p.pop(k, None)
|
||||
|
||||
def extra_params(self, suffix: str = "") -> dict[str, Any]:
|
||||
if self.need_skip():
|
||||
return {}
|
||||
|
||||
p = {name: getattr(self, attr) for attr, name in ALL_ARGS}
|
||||
ppop = partial(self.ppop, p)
|
||||
|
||||
ppop("ADetailer model classes")
|
||||
ppop("ADetailer prompt")
|
||||
ppop("ADetailer negative prompt")
|
||||
p.pop("ADetailer tap 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)
|
||||
ppop("ADetailer x offset", cond=0)
|
||||
ppop("ADetailer y offset", cond=0)
|
||||
ppop("ADetailer mask merge invert", cond="None")
|
||||
ppop("ADetailer inpaint only masked", ["ADetailer inpaint padding"])
|
||||
ppop(
|
||||
"ADetailer use inpaint width height",
|
||||
[
|
||||
"ADetailer use inpaint width height",
|
||||
"ADetailer inpaint width",
|
||||
"ADetailer inpaint height",
|
||||
],
|
||||
)
|
||||
ppop(
|
||||
"ADetailer use separate steps",
|
||||
["ADetailer use separate steps", "ADetailer steps"],
|
||||
)
|
||||
ppop(
|
||||
"ADetailer use separate CFG scale",
|
||||
["ADetailer use separate CFG scale", "ADetailer CFG scale"],
|
||||
)
|
||||
ppop(
|
||||
"ADetailer use separate checkpoint",
|
||||
["ADetailer use separate checkpoint", "ADetailer checkpoint"],
|
||||
)
|
||||
ppop(
|
||||
"ADetailer use separate VAE",
|
||||
["ADetailer use separate VAE", "ADetailer VAE"],
|
||||
)
|
||||
ppop(
|
||||
"ADetailer use separate sampler",
|
||||
[
|
||||
"ADetailer use separate sampler",
|
||||
"ADetailer sampler",
|
||||
"ADetailer scheduler",
|
||||
],
|
||||
)
|
||||
ppop("ADetailer scheduler", cond="Use same scheduler")
|
||||
ppop(
|
||||
"ADetailer use separate noise multiplier",
|
||||
["ADetailer use separate noise multiplier", "ADetailer noise multiplier"],
|
||||
)
|
||||
|
||||
ppop(
|
||||
"ADetailer use separate CLIP skip",
|
||||
["ADetailer use separate CLIP skip", "ADetailer CLIP skip"],
|
||||
)
|
||||
|
||||
ppop("ADetailer restore face")
|
||||
ppop(
|
||||
"ADetailer ControlNet model",
|
||||
[
|
||||
"ADetailer ControlNet model",
|
||||
"ADetailer ControlNet module",
|
||||
"ADetailer ControlNet weight",
|
||||
"ADetailer ControlNet guidance start",
|
||||
"ADetailer ControlNet guidance end",
|
||||
],
|
||||
cond="None",
|
||||
)
|
||||
ppop("ADetailer ControlNet module", cond="None")
|
||||
ppop("ADetailer ControlNet weight", cond=1.0)
|
||||
ppop("ADetailer ControlNet guidance start", cond=0.0)
|
||||
ppop("ADetailer ControlNet guidance end", cond=1.0)
|
||||
|
||||
if suffix:
|
||||
p = {k + suffix: v for k, v in p.items()}
|
||||
|
||||
return p
|
||||
|
||||
def is_mediapipe(self) -> bool:
|
||||
return self.ad_model.lower().startswith("mediapipe")
|
||||
|
||||
def need_skip(self) -> bool:
|
||||
return self.ad_model == "None" or self.ad_tap_enable is False
|
||||
|
||||
|
||||
_all_args = [
|
||||
("ad_model", "ADetailer model"),
|
||||
("ad_model_classes", "ADetailer model classes"),
|
||||
("ad_tap_enable", "ADetailer tap enable"),
|
||||
("ad_prompt", "ADetailer prompt"),
|
||||
("ad_negative_prompt", "ADetailer negative prompt"),
|
||||
("ad_confidence", "ADetailer confidence"),
|
||||
("ad_mask_k_largest", "ADetailer mask only top k largest"),
|
||||
("ad_mask_min_ratio", "ADetailer mask min ratio"),
|
||||
("ad_mask_max_ratio", "ADetailer mask max ratio"),
|
||||
("ad_x_offset", "ADetailer x offset"),
|
||||
("ad_y_offset", "ADetailer y offset"),
|
||||
("ad_dilate_erode", "ADetailer dilate erode"),
|
||||
("ad_mask_merge_invert", "ADetailer mask merge invert"),
|
||||
("ad_mask_blur", "ADetailer mask blur"),
|
||||
("ad_denoising_strength", "ADetailer denoising strength"),
|
||||
("ad_inpaint_only_masked", "ADetailer inpaint only masked"),
|
||||
("ad_inpaint_only_masked_padding", "ADetailer inpaint padding"),
|
||||
("ad_use_inpaint_width_height", "ADetailer use inpaint width height"),
|
||||
("ad_inpaint_width", "ADetailer inpaint width"),
|
||||
("ad_inpaint_height", "ADetailer inpaint height"),
|
||||
("ad_use_steps", "ADetailer use separate steps"),
|
||||
("ad_steps", "ADetailer steps"),
|
||||
("ad_use_cfg_scale", "ADetailer use separate CFG scale"),
|
||||
("ad_cfg_scale", "ADetailer CFG scale"),
|
||||
("ad_use_checkpoint", "ADetailer use separate checkpoint"),
|
||||
("ad_checkpoint", "ADetailer checkpoint"),
|
||||
("ad_use_vae", "ADetailer use separate VAE"),
|
||||
("ad_vae", "ADetailer VAE"),
|
||||
("ad_use_sampler", "ADetailer use separate sampler"),
|
||||
("ad_sampler", "ADetailer sampler"),
|
||||
("ad_scheduler", "ADetailer scheduler"),
|
||||
("ad_use_noise_multiplier", "ADetailer use separate noise multiplier"),
|
||||
("ad_noise_multiplier", "ADetailer noise multiplier"),
|
||||
("ad_use_clip_skip", "ADetailer use separate CLIP skip"),
|
||||
("ad_clip_skip", "ADetailer CLIP skip"),
|
||||
("ad_restore_face", "ADetailer restore face"),
|
||||
("ad_controlnet_model", "ADetailer ControlNet model"),
|
||||
("ad_controlnet_module", "ADetailer ControlNet module"),
|
||||
("ad_controlnet_weight", "ADetailer ControlNet weight"),
|
||||
("ad_controlnet_guidance_start", "ADetailer ControlNet guidance start"),
|
||||
("ad_controlnet_guidance_end", "ADetailer ControlNet guidance end"),
|
||||
]
|
||||
|
||||
_args = [Arg(*args) for args in _all_args]
|
||||
ALL_ARGS = ArgsList(_args)
|
||||
|
||||
BBOX_SORTBY = [
|
||||
"None",
|
||||
"Position (left to right)",
|
||||
"Position (center to edge)",
|
||||
"Area (large to small)",
|
||||
]
|
||||
MASK_MERGE_INVERT = ["None", "Merge", "Merge and Invert"]
|
||||
|
||||
_script_default = (
|
||||
"dynamic_prompting",
|
||||
"dynamic_thresholding",
|
||||
"wildcard_recursive",
|
||||
"wildcards",
|
||||
"lora_block_weight",
|
||||
"negpip",
|
||||
)
|
||||
SCRIPT_DEFAULT = ",".join(sorted(_script_default))
|
||||
|
||||
_builtin_script = ("soft_inpainting", "hypertile_script")
|
||||
BUILTIN_SCRIPT = ",".join(sorted(_builtin_script))
|
||||
Reference in New Issue
Block a user