mirror of
https://github.com/Bing-su/adetailer.git
synced 2026-05-01 03:31:21 +00:00
refactor: mask preprocess, save image
This commit is contained in:
@@ -137,3 +137,40 @@ def offset(img: Image.Image, x: int = 0, y: int = 0) -> Image.Image:
|
|||||||
def is_all_black(img: Image.Image) -> bool:
|
def is_all_black(img: Image.Image) -> bool:
|
||||||
arr = np.array(img)
|
arr = np.array(img)
|
||||||
return cv2.countNonZero(arr) == 0
|
return cv2.countNonZero(arr) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def mask_preprocess(
|
||||||
|
masks: list[Image.Image] | None,
|
||||||
|
kernel: int = 0,
|
||||||
|
x_offset: int = 0,
|
||||||
|
y_offset: int = 0,
|
||||||
|
) -> list[Image.Image]:
|
||||||
|
"""
|
||||||
|
The mask_preprocess function takes a list of masks and preprocesses them.
|
||||||
|
It dilates and erodes the masks, and offsets them by x_offset and y_offset.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
masks: list[Image.Image] | None
|
||||||
|
A list of masks
|
||||||
|
kernel: int
|
||||||
|
kernel size of dilation or erosion
|
||||||
|
x_offset: int
|
||||||
|
→
|
||||||
|
y_offset: int
|
||||||
|
↑
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
list[Image.Image]
|
||||||
|
A list of processed masks
|
||||||
|
"""
|
||||||
|
if masks is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
masks = [dilate_erode(m, kernel) for m in masks]
|
||||||
|
masks = [m for m in masks if not is_all_black(m)]
|
||||||
|
if x_offset != 0 or y_offset != 0:
|
||||||
|
masks = [offset(m, x_offset, y_offset) for m in masks]
|
||||||
|
|
||||||
|
return masks
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ from adetailer import (
|
|||||||
mediapipe_predict,
|
mediapipe_predict,
|
||||||
ultralytics_predict,
|
ultralytics_predict,
|
||||||
)
|
)
|
||||||
from adetailer.common import dilate_erode, is_all_black, offset
|
from adetailer.common import mask_preprocess
|
||||||
from controlnet_ext import ControlNetExt, controlnet_exists, get_cn_inpaint_models
|
from controlnet_ext import ControlNetExt, controlnet_exists, get_cn_inpaint_models
|
||||||
from modules import images, safe, script_callbacks, scripts, shared
|
from modules import images, safe, script_callbacks, scripts, shared
|
||||||
from modules.paths import data_path, models_path
|
from modules.paths import data_path, models_path
|
||||||
@@ -277,6 +277,9 @@ class AfterDetailerScript(scripts.Script):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def update_controlnet_args(self, p, args: ADetailerArgs) -> None:
|
def update_controlnet_args(self, p, args: ADetailerArgs) -> None:
|
||||||
|
if self.controlnet_ext is None:
|
||||||
|
self.init_controlnet_ext()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
self.controlnet_ext is not None
|
self.controlnet_ext is not None
|
||||||
and self.controlnet_ext.cn_available
|
and self.controlnet_ext.cn_available
|
||||||
@@ -288,8 +291,9 @@ class AfterDetailerScript(scripts.Script):
|
|||||||
|
|
||||||
def is_ad_enabled(self, *args_) -> bool:
|
def is_ad_enabled(self, *args_) -> bool:
|
||||||
if len(args_) < 2:
|
if len(args_) < 2:
|
||||||
message = f"""[-] ADetailer: Not enough arguments passed to adetailer.
|
message = f"""
|
||||||
input: {args_!r}
|
[-] ADetailer: Not enough arguments passed to adetailer.
|
||||||
|
input: {args_!r}
|
||||||
"""
|
"""
|
||||||
raise ValueError(dedent(message))
|
raise ValueError(dedent(message))
|
||||||
checker = EnableChecker(ad_enable=args_[0], ad_model=args_[1])
|
checker = EnableChecker(ad_enable=args_[0], ad_model=args_[1])
|
||||||
@@ -447,12 +451,13 @@ class AfterDetailerScript(scripts.Script):
|
|||||||
i2i._disable_adetailer = True
|
i2i._disable_adetailer = True
|
||||||
|
|
||||||
if args.ad_controlnet_model != "None":
|
if args.ad_controlnet_model != "None":
|
||||||
self.init_controlnet_ext()
|
|
||||||
self.update_controlnet_args(i2i, args)
|
self.update_controlnet_args(i2i, args)
|
||||||
return i2i
|
return i2i
|
||||||
|
|
||||||
def save_image(self, p, image, seed, *, condition: str, suffix: str) -> None:
|
def save_image(self, p, image, *, condition: str, suffix: str) -> None:
|
||||||
i = p._idx
|
i = p._idx
|
||||||
|
seed, _ = self.get_seed(p)
|
||||||
|
|
||||||
if opts.data.get(condition, False):
|
if opts.data.get(condition, False):
|
||||||
images.save_image(
|
images.save_image(
|
||||||
image=image,
|
image=image,
|
||||||
@@ -481,17 +486,20 @@ class AfterDetailerScript(scripts.Script):
|
|||||||
extra_params = self.extra_params(args)
|
extra_params = self.extra_params(args)
|
||||||
p.extra_generation_params.update(extra_params)
|
p.extra_generation_params.update(extra_params)
|
||||||
|
|
||||||
def _postprocess_image(self, p, pp, args: ADetailerArgs):
|
def _postprocess_image(self, p, pp, args: ADetailerArgs) -> bool:
|
||||||
|
"""
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
bool
|
||||||
|
|
||||||
|
`True` if image was processed, `False` otherwise.
|
||||||
|
"""
|
||||||
p._idx = getattr(p, "_idx", -1) + 1
|
p._idx = getattr(p, "_idx", -1) + 1
|
||||||
i = p._idx
|
i = p._idx
|
||||||
|
|
||||||
i2i = self.get_i2i_p(p, args, pp.image)
|
i2i = self.get_i2i_p(p, args, pp.image)
|
||||||
seed, subseed = self.get_seed(p)
|
seed, subseed = self.get_seed(p)
|
||||||
|
|
||||||
self.save_image(
|
|
||||||
p, pp.image, seed, condition="ad_save_images_before", suffix="-ad-before"
|
|
||||||
)
|
|
||||||
|
|
||||||
is_mediapipe = args.ad_model.lower().startswith("mediapipe")
|
is_mediapipe = args.ad_model.lower().startswith("mediapipe")
|
||||||
|
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
@@ -506,17 +514,18 @@ class AfterDetailerScript(scripts.Script):
|
|||||||
with ChangeTorchLoad():
|
with ChangeTorchLoad():
|
||||||
pred = predictor(ad_model, pp.image, args.ad_conf, **kwargs)
|
pred = predictor(ad_model, pp.image, args.ad_conf, **kwargs)
|
||||||
|
|
||||||
if pred.masks is None:
|
masks = mask_preprocess(pred.masks)
|
||||||
|
|
||||||
|
if not masks:
|
||||||
print(
|
print(
|
||||||
f"[-] ADetailer: nothing detected on image {i + 1} with current settings."
|
f"[-] ADetailer: nothing detected on image {i + 1} with current settings."
|
||||||
)
|
)
|
||||||
return
|
return False
|
||||||
|
|
||||||
self.save_image(
|
self.save_image(
|
||||||
p, pred.preview, seed, condition="ad_save_previews", suffix="-ad-preview"
|
p, pred.preview, condition="ad_save_previews", suffix="-ad-preview"
|
||||||
)
|
)
|
||||||
|
|
||||||
masks = pred.masks
|
|
||||||
steps = len(masks)
|
steps = len(masks)
|
||||||
processed = None
|
processed = None
|
||||||
|
|
||||||
@@ -525,22 +534,20 @@ class AfterDetailerScript(scripts.Script):
|
|||||||
|
|
||||||
p2 = copy(i2i)
|
p2 = copy(i2i)
|
||||||
for j in range(steps):
|
for j in range(steps):
|
||||||
mask = masks[j]
|
p2.image_mask = masks[j]
|
||||||
mask = dilate_erode(mask, args.ad_dilate_erode)
|
processed = process_images(p2)
|
||||||
|
|
||||||
if not is_all_black(mask):
|
p2 = copy(i2i)
|
||||||
mask = offset(mask, args.ad_x_offset, args.ad_y_offset)
|
p2.init_images = [processed.images[0]]
|
||||||
p2.image_mask = mask
|
|
||||||
processed = process_images(p2)
|
|
||||||
|
|
||||||
p2 = copy(i2i)
|
|
||||||
p2.init_images = [processed.images[0]]
|
|
||||||
|
|
||||||
p2.seed = seed + j + 1
|
p2.seed = seed + j + 1
|
||||||
p2.subseed = subseed + j + 1
|
p2.subseed = subseed + j + 1
|
||||||
|
|
||||||
if processed is not None:
|
if processed is not None:
|
||||||
pp.image = processed.images[0]
|
pp.image = processed.images[0]
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def postprocess_image(self, p, pp, *args_):
|
def postprocess_image(self, p, pp, *args_):
|
||||||
if getattr(p, "_disable_adetailer", False):
|
if getattr(p, "_disable_adetailer", False):
|
||||||
@@ -550,7 +557,12 @@ class AfterDetailerScript(scripts.Script):
|
|||||||
return
|
return
|
||||||
|
|
||||||
args = self.get_args(*args_)
|
args = self.get_args(*args_)
|
||||||
self._postprocess_image(p, pp, args)
|
is_processed = self._postprocess_image(p, pp, args)
|
||||||
|
|
||||||
|
if is_processed:
|
||||||
|
self.save_image(
|
||||||
|
p, pp.image, condition="ad_save_images_before", suffix="-ad-before"
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if p._idx == len(p.all_prompts) - 1:
|
if p._idx == len(p.all_prompts) - 1:
|
||||||
|
|||||||
Reference in New Issue
Block a user