Skip to content

Commit

Permalink
Merge branch 'dev' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Bing-su committed Jun 20, 2023
2 parents 7642425 + 991652d commit a1032d8
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 20 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ repos:
hooks:
- id: isort

- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: "v0.0.270"
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.0.272"
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 2023-06-20

- v23.6.3
- 컨트롤넷 inpaint 모델에 대해, 3가지 모듈을 사용할 수 있도록 함
- Noise Multiplier 옵션 추가 (PR #149)
- pydantic 최소 버전 1.10.8로 설정 (Issue #146)

## 2023-06-05

- v23.6.2
Expand Down
2 changes: 1 addition & 1 deletion adetailer/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "23.6.2"
__version__ = "23.6.3"
24 changes: 23 additions & 1 deletion adetailer/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from collections import UserList
from functools import cached_property, partial
from typing import Any, Literal, NamedTuple, Union
from typing import Any, Literal, NamedTuple, Optional, Union

import pydantic
from pydantic import (
Expand All @@ -13,6 +13,7 @@
PositiveInt,
confloat,
constr,
root_validator,
)

cn_model_regex = r".*(inpaint|tile|scribble|lineart|openpose).*|^None$"
Expand Down Expand Up @@ -55,12 +56,23 @@ class ADetailerArgs(BaseModel, extra=Extra.forbid):
ad_steps: PositiveInt = 28
ad_use_cfg_scale: bool = False
ad_cfg_scale: NonNegativeFloat = 7.0
ad_use_noise_multiplier: bool = False
ad_noise_multiplier: confloat(ge=0.5, le=1.5) = 1.0
ad_restore_face: bool = False
ad_controlnet_model: constr(regex=cn_model_regex) = "None"
ad_controlnet_module: Optional[constr(regex=r".*inpaint.*|^None$")] = 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

@root_validator
def ad_controlnt_module_validator(cls, values): # noqa: N805
cn_model = values.get("ad_controlnet_model", "None")
cn_module = values.get("ad_controlnet_module", None)
if "inpaint" not in cn_model or cn_module == "None":
values["ad_controlnet_module"] = None
return values

@staticmethod
def ppop(
p: dict[str, Any],
Expand Down Expand Up @@ -110,17 +122,24 @@ def extra_params(self, suffix: str = ""):
"ADetailer use separate CFG scale",
["ADetailer use separate CFG scale", "ADetailer CFG scale"],
)
ppop(
"ADetailer use separate noise multiplier",
["ADetailer use separate noise multiplier", "ADetailer noise multiplier"],
)

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")
ppop("ADetailer ControlNet weight", cond=1.0)
ppop("ADetailer ControlNet guidance start", cond=0.0)
ppop("ADetailer ControlNet guidance end", cond=1.0)
Expand Down Expand Up @@ -167,8 +186,11 @@ def is_enabled(self) -> bool:
("ad_steps", "ADetailer steps"),
("ad_use_cfg_scale", "ADetailer use separate CFG scale"),
("ad_cfg_scale", "ADetailer CFG scale"),
("ad_use_noise_multiplier", "ADetailer use separate noise multiplier"),
("ad_noise_multiplier", "ADetailer noise multiplier"),
("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"),
Expand Down
3 changes: 2 additions & 1 deletion adetailer/mediapipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ def mediapipe_predict(
if model_type in mapping:
func = mapping[model_type]
return func(image, confidence)
raise RuntimeError(f"[-] ADetailer: Invalid mediapipe model type: {model_type}")
msg = f"[-] ADetailer: Invalid mediapipe model type: {model_type}"
raise RuntimeError(msg)


def mediapipe_face_detection(
Expand Down
64 changes: 60 additions & 4 deletions adetailer/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
from adetailer.args import AD_ENABLE, ALL_ARGS, MASK_MERGE_INVERT
from controlnet_ext import controlnet_exists, get_cn_models

cn_module_choices = [
"inpaint_global_harmonious",
"inpaint_only",
"inpaint_only+lama",
]


class Widgets(SimpleNamespace):
def tolist(self):
Expand Down Expand Up @@ -40,6 +46,14 @@ def on_generate_click(state: dict, *values: Any):
return state


def on_cn_model_update(cn_model: str):
if "inpaint" in cn_model:
return gr.update(
visible=True, choices=cn_module_choices, value=cn_module_choices[0]
)
return gr.update(visible=False, choices=["None"], value="None")


def elem_id(item_id: str, n: int, is_img2img: bool) -> str:
tap = "img2img" if is_img2img else "txt2img"
suf = suffix(n, "_")
Expand Down Expand Up @@ -90,7 +104,7 @@ def adui(
infotext_fields.extend(infofields)

# components: [bool, dict, dict, ...]
components = [ad_enable] + states
components = [ad_enable, *states]
return components, infotext_fields


Expand All @@ -106,7 +120,7 @@ def one_ui_group(
eid = partial(elem_id, n=n, is_img2img=is_img2img)

with gr.Row():
model_choices = model_list + ["None"] if n == 0 else ["None"] + model_list
model_choices = [*model_list, "None"] if n == 0 else ["None", *model_list]

w.ad_model = gr.Dropdown(
label="ADetailer model" + suffix(n),
Expand Down Expand Up @@ -164,7 +178,7 @@ def one_ui_group(
fn=on_change, inputs=[state, widget], outputs=[state], queue=False
)

all_inputs = [state] + w.tolist()
all_inputs = [state, *w.tolist()]
target_button = i2i_button if is_img2img else t2i_button
target_button.click(
fn=on_generate_click, inputs=all_inputs, outputs=state, queue=False
Expand Down Expand Up @@ -393,6 +407,31 @@ def inpainting(w: Widgets, n: int, is_img2img: bool):
)

with gr.Row():
with gr.Column(variant="compact"):
w.ad_use_noise_multiplier = gr.Checkbox(
label="Use separate noise multiplier" + suffix(n),
value=False,
visible=True,
elem_id=eid("ad_use_noise_multiplier"),
)

w.ad_noise_multiplier = gr.Slider(
label="Noise multiplier for img2img" + suffix(n),
minimum=0.5,
maximum=1.5,
step=0.01,
value=1.0,
visible=True,
elem_id=eid("ad_noise_multiplier"),
)

w.ad_use_noise_multiplier.change(
gr_interactive,
inputs=w.ad_use_noise_multiplier,
outputs=w.ad_noise_multiplier,
queue=False,
)

w.ad_restore_face = gr.Checkbox(
label="Restore faces after ADetailer" + suffix(n),
value=False,
Expand All @@ -402,7 +441,7 @@ def inpainting(w: Widgets, n: int, is_img2img: bool):

def controlnet(w: Widgets, n: int, is_img2img: bool):
eid = partial(elem_id, n=n, is_img2img=is_img2img)
cn_models = ["None"] + get_cn_models()
cn_models = ["None", *get_cn_models()]

with gr.Row(variant="panel"):
with gr.Column(variant="compact"):
Expand All @@ -416,6 +455,16 @@ def controlnet(w: Widgets, n: int, is_img2img: bool):
elem_id=eid("ad_controlnet_model"),
)

w.ad_controlnet_module = gr.Dropdown(
label="ControlNet module" + suffix(n),
choices=cn_module_choices,
value="inpaint_global_harmonious",
visible=False,
type="value",
interactive=controlnet_exists,
elem_id=eid("ad_controlnet_module"),
)

w.ad_controlnet_weight = gr.Slider(
label="ControlNet weight" + suffix(n),
minimum=0.0,
Expand All @@ -427,6 +476,13 @@ def controlnet(w: Widgets, n: int, is_img2img: bool):
elem_id=eid("ad_controlnet_weight"),
)

w.ad_controlnet_model.change(
on_cn_model_update,
inputs=w.ad_controlnet_model,
outputs=w.ad_controlnet_module,
queue=False,
)

with gr.Column(variant="compact"):
w.ad_controlnet_guidance_start = gr.Slider(
label="ControlNet guidance start" + suffix(n),
Expand Down
18 changes: 12 additions & 6 deletions controlnet_ext/controlnet_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,22 @@ def init_controlnet(self):
self.cn_models.extend(m for m in models if cn_model_regex.search(m))

def update_scripts_args(
self, p, model: str, weight: float, guidance_start: float, guidance_end: float
self,
p,
model: str,
module: str | None,
weight: float,
guidance_start: float,
guidance_end: float,
):
if (not self.cn_available) or model == "None":
return

module = None
for m, v in cn_model_module.items():
if m in model:
module = v
break
if module is None:
for m, v in cn_model_module.items():
if m in model:
module = v
break

cn_units = [
self.external_cn.ControlNetUnit(
Expand Down
2 changes: 1 addition & 1 deletion install.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def install():
("ultralytics", "8.0.97", None),
("mediapipe", "0.10.0", None),
("huggingface_hub", None, None),
("pydantic", None, None),
("pydantic", "1.10.8", None),
# mediapipe
("protobuf", "3.20.0", "3.20.9999"),
]
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ profile = "black"
known_first_party = ["launch", "modules"]

[tool.ruff]
select = ["A", "B", "C4", "E", "F", "I001", "ISC", "N", "PIE", "PT", "RET", "SIM", "UP", "W"]
select = ["A", "B", "C4", "C90", "E", "EM", "F", "FA", "I001", "ISC", "N", "PIE", "PT", "RET", "RUF", "SIM", "UP", "W"]
ignore = ["B008", "B905", "E501", "F401", "UP007"]

[tool.ruff.isort]
Expand Down
14 changes: 11 additions & 3 deletions scripts/!adetailer.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import gradio as gr
import torch

import modules # noqa: F401
import modules
from adetailer import (
AFTER_DETAILER,
__version__,
Expand Down Expand Up @@ -141,6 +141,7 @@ def update_controlnet_args(self, p, args: ADetailerArgs) -> None:
self.controlnet_ext.update_scripts_args(
p,
model=args.ad_controlnet_model,
module=args.ad_controlnet_module,
weight=args.ad_controlnet_weight,
guidance_start=args.ad_controlnet_guidance_start,
guidance_end=args.ad_controlnet_guidance_end,
Expand Down Expand Up @@ -281,6 +282,11 @@ def get_cfg_scale(self, p, args: ADetailerArgs) -> float:
return args.ad_cfg_scale
return p.cfg_scale

def get_initial_noise_multiplier(self, p, args: ADetailerArgs) -> float | None:
if args.ad_use_noise_multiplier:
return args.ad_noise_multiplier
return None

def infotext(self, p) -> str:
return create_infotext(
p, p.all_prompts, p.all_seeds, p.all_subseeds, None, 0, 0
Expand Down Expand Up @@ -339,6 +345,7 @@ def get_i2i_p(self, p, args: ADetailerArgs, image):
width, height = self.get_width_height(p, args)
steps = self.get_steps(p, args)
cfg_scale = self.get_cfg_scale(p, args)
initial_noise_multiplier = self.get_initial_noise_multiplier(p, args)

sampler_name = p.sampler_name
if sampler_name in ["PLMS", "UniPC"]:
Expand All @@ -354,6 +361,7 @@ def get_i2i_p(self, p, args: ADetailerArgs, image):
inpaint_full_res=args.ad_inpaint_only_masked,
inpaint_full_res_padding=args.ad_inpaint_only_masked_padding,
inpainting_mask_invert=0,
initial_noise_multiplier=initial_noise_multiplier,
sd_model=p.sd_model,
outpath_samples=p.outpath_samples,
outpath_grids=p.outpath_grids,
Expand Down Expand Up @@ -647,7 +655,7 @@ def make_axis_on_xyz_grid():
if xyz_grid is None:
return

model_list = ["None"] + list(model_mapping.keys())
model_list = ["None", *model_mapping.keys()]

def set_value(p, x, xs, *, field: str):
if not hasattr(p, "adetailer_xyz"):
Expand Down Expand Up @@ -696,7 +704,7 @@ def set_value(p, x, xs, *, field: str):
"[ADetailer] ControlNet model 1st",
str,
partial(set_value, field="ad_controlnet_model"),
choices=lambda: ["None"] + get_cn_models(),
choices=lambda: ["None", *get_cn_models()],
),
]

Expand Down

0 comments on commit a1032d8

Please sign in to comment.