mirror of
https://github.com/Bing-su/adetailer.git
synced 2026-03-13 17:30:01 +00:00
Merge branch 'dev' into main
This commit is contained in:
@@ -12,14 +12,13 @@ repos:
|
||||
- id: isort
|
||||
args: [--profile=black]
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.3.0
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: "v0.0.265"
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [--fix, --exit-non-zero-on-fix]
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.3.0
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# Changelog
|
||||
|
||||
### 2023-05-09
|
||||
|
||||
- v23.5.10
|
||||
- 선택한 스크립트만 ADetailer에 적용하는 옵션 추가, 기본값 `True`. 설정 탭에서 지정가능.
|
||||
- 기본값: `dynamic_prompting,dynamic_thresholding,wildcards,wildcard_recursive`
|
||||
- `person_yolov8s-seg.pt` 모델 추가
|
||||
|
||||
### 2023-05-08
|
||||
|
||||
- v23.5.9
|
||||
|
||||
@@ -36,6 +36,7 @@ On the ControlNet tab, select a ControlNet inpaint model and set the model weigh
|
||||
| mediapipe_face_short | realistic face | - | - |
|
||||
| hand_yolov8n.pt | 2D / realistic hand | 0.767 | 0.505 |
|
||||
| person_yolov8n-seg.pt | 2D / realistic person | 0.782 (bbox)<br/>0.761 (mask) | 0.555 (bbox)<br/>0.460 (mask) |
|
||||
| person_yolov8s-seg.pt | 2D / realistic person | 0.824 (bbox)<br/>0.809 (mask) | 0.605 (bbox)<br/>0.508 (mask) |
|
||||
|
||||
The yolo models can be found on huggingface [Bingsu/adetailer](https://huggingface.co/Bingsu/adetailer).
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "23.5.9"
|
||||
__version__ = "23.5.10"
|
||||
|
||||
@@ -39,6 +39,7 @@ def get_models(model_dir: Union[str, Path]) -> OrderedDict[str, Optional[str]]:
|
||||
"mediapipe_face_short": None,
|
||||
"hand_yolov8n.pt": hf_hub_download(repo_id, "hand_yolov8n.pt"),
|
||||
"person_yolov8n-seg.pt": hf_hub_download(repo_id, "person_yolov8n-seg.pt"),
|
||||
"person_yolov8s-seg.pt": hf_hub_download(repo_id, "person_yolov8s-seg.pt"),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -51,16 +52,16 @@ def get_models(model_dir: Union[str, Path]) -> OrderedDict[str, Optional[str]]:
|
||||
|
||||
|
||||
def create_mask_from_bbox(
|
||||
image: Image.Image, bboxes: list[list[float]]
|
||||
bboxes: list[list[float]], shape: tuple[int, int]
|
||||
) -> list[Image.Image]:
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
image: Image.Image
|
||||
The image to create the mask from
|
||||
bboxes: list[list[float]]
|
||||
list of [x1, y1, x2, y2]
|
||||
bounding boxes
|
||||
shape: tuple[int, int]
|
||||
shape of the image (width, height)
|
||||
|
||||
Returns
|
||||
-------
|
||||
@@ -70,7 +71,7 @@ def create_mask_from_bbox(
|
||||
"""
|
||||
masks = []
|
||||
for bbox in bboxes:
|
||||
mask = Image.new("L", image.size, 0)
|
||||
mask = Image.new("L", shape, 0)
|
||||
mask_draw = ImageDraw.Draw(mask)
|
||||
mask_draw.rectangle(bbox, fill=255)
|
||||
masks.append(mask)
|
||||
|
||||
@@ -45,7 +45,7 @@ def mediapipe_predict(
|
||||
|
||||
bboxes.append([x1, y1, x2, y2])
|
||||
|
||||
masks = create_mask_from_bbox(image, bboxes)
|
||||
masks = create_mask_from_bbox(bboxes, image.size)
|
||||
preview = Image.fromarray(preview_array)
|
||||
|
||||
return PredictOutput(bboxes=bboxes, masks=masks, preview=preview)
|
||||
|
||||
@@ -33,7 +33,7 @@ def ultralytics_predict(
|
||||
bboxes = bboxes.tolist()
|
||||
|
||||
if pred[0].masks is None:
|
||||
masks = create_mask_from_bbox(image, bboxes)
|
||||
masks = create_mask_from_bbox(bboxes, image.size)
|
||||
else:
|
||||
masks = mask_to_pil(pred[0].masks.data, image.size)
|
||||
preview = pred[0].plot()
|
||||
@@ -56,17 +56,17 @@ def ultralytics_check():
|
||||
print(message)
|
||||
|
||||
|
||||
def mask_to_pil(masks, orig_shape: tuple[int, int]) -> list[Image.Image]:
|
||||
def mask_to_pil(masks, shape: tuple[int, int]) -> list[Image.Image]:
|
||||
"""
|
||||
Parameters
|
||||
----------
|
||||
masks: torch.Tensor, dtype=torch.float32, shape=(N, H, W).
|
||||
The device can be CUDA, but `to_pil_image` takes care of that.
|
||||
|
||||
orig_shape: tuple[int, int]
|
||||
shape: tuple[int, int]
|
||||
(width, height) of the original image
|
||||
"""
|
||||
from torchvision.transforms.functional import to_pil_image
|
||||
|
||||
n = masks.shape[0]
|
||||
return [to_pil_image(masks[i], mode="L").resize(orig_shape) for i in range(n)]
|
||||
return [to_pil_image(masks[i], mode="L").resize(shape) for i in range(n)]
|
||||
|
||||
@@ -448,6 +448,33 @@ class AfterDetailerScript(scripts.Script):
|
||||
params_txt = Path(data_path, "params.txt")
|
||||
params_txt.write_text(infotext, encoding="utf-8")
|
||||
|
||||
def script_filter(self, p, args: ADetailerArgs):
|
||||
script_runner = copy(p.scripts)
|
||||
|
||||
ad_only_seleted_scripts = opts.data.get("ad_only_seleted_scripts", True)
|
||||
if not ad_only_seleted_scripts:
|
||||
return script_runner
|
||||
|
||||
default = "dynamic_prompting,dynamic_thresholding,wildcards,wildcard_recursive"
|
||||
ad_script_names = opts.data.get("ad_script_names", default)
|
||||
script_names_set = {
|
||||
name
|
||||
for script_name in ad_script_names.split(",")
|
||||
for name in (script_name, script_name.strip())
|
||||
}
|
||||
if args.ad_controlnet_model != "None":
|
||||
script_names_set.add("controlnet")
|
||||
|
||||
filtered_alwayson = []
|
||||
for script_object in script_runner.alwayson_scripts:
|
||||
filepath = script_object.filename
|
||||
filename = Path(filepath).stem
|
||||
if filename in script_names_set:
|
||||
filtered_alwayson.append(script_object)
|
||||
|
||||
script_runner.alwayson_scripts = filtered_alwayson
|
||||
return script_runner
|
||||
|
||||
def get_i2i_p(self, p, args: ADetailerArgs, image):
|
||||
prompt, negative_prompt = self.get_prompt(p, args)
|
||||
seed, subseed = self.get_seed(p)
|
||||
@@ -492,7 +519,7 @@ class AfterDetailerScript(scripts.Script):
|
||||
do_not_save_grid=True,
|
||||
)
|
||||
|
||||
i2i.scripts = copy(p.scripts)
|
||||
i2i.scripts = self.script_filter(p, args)
|
||||
i2i.script_args = deepcopy(p.script_args)
|
||||
i2i._disable_adetailer = True
|
||||
|
||||
@@ -631,10 +658,10 @@ def on_ui_settings():
|
||||
shared.opts.add_option(
|
||||
"ad_max_models",
|
||||
shared.OptionInfo(
|
||||
2,
|
||||
"Max models",
|
||||
gr.Slider,
|
||||
{"minimum": 1, "maximum": 5, "step": 1},
|
||||
default=2,
|
||||
label="Max models",
|
||||
component=gr.Slider,
|
||||
component_args={"minimum": 1, "maximum": 5, "step": 1},
|
||||
section=section,
|
||||
),
|
||||
)
|
||||
@@ -649,5 +676,28 @@ def on_ui_settings():
|
||||
shared.OptionInfo(False, "Save images before ADetailer", section=section),
|
||||
)
|
||||
|
||||
shared.opts.add_option(
|
||||
"ad_only_seleted_scripts",
|
||||
shared.OptionInfo(
|
||||
True, "Apply only selected scripts to ADetailer", section=section
|
||||
),
|
||||
)
|
||||
|
||||
textbox_args = {
|
||||
"placeholder": "comma-separated list of script names",
|
||||
"interactive": True,
|
||||
}
|
||||
|
||||
shared.opts.add_option(
|
||||
"ad_script_names",
|
||||
shared.OptionInfo(
|
||||
default="dynamic_prompting,dynamic_thresholding,wildcards,wildcard_recursive",
|
||||
label="Script names to apply to ADetailer (separated by comma)",
|
||||
component=gr.Textbox,
|
||||
component_args=textbox_args,
|
||||
section=section,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
script_callbacks.on_ui_settings(on_ui_settings)
|
||||
|
||||
Reference in New Issue
Block a user