From fd3acac3489018d1ed5e6ea78bfa64e818ebfe60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D0=B2=D0=B3=D0=B5=D0=BD=D0=B8=D0=B9=20=D0=93=D1=83?= =?UTF-8?q?=D1=80=D1=8C=D0=B5=D0=B2=20=7C=20Eugene=20Gourieff=20=7C=20?= =?UTF-8?q?=E5=8F=A4=E4=BB=81?= Date: Sat, 18 Jan 2025 16:02:05 +0700 Subject: [PATCH] UPD: ReSwapper_128/256 models support --- README.md | 11 +++++++++++ README_RU.md | 11 +++++++++++ reactor_patcher.py | 28 +++++++++++++++++++++++++++- scripts/reactor_faceswap.py | 16 ++++++++++++---- scripts/reactor_swapper.py | 6 +++++- 5 files changed, 66 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c2c0bd9..c269c9d 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,17 @@ ## What's new in the latest update +### 0.5.2 BETA1 + +- ReSwapper models support. Although Inswapper still has the best similarity, but ReSwapper is evolving - thanks @somanchiu https://github.com/somanchiu/ReSwapper for the ReSwapper models and the ReSwapper project! This is a good step for the Community in the Inswapper's alternative creation! + +0.5.2-whatsnew-03 +0.5.2-whatsnew-04 + +You can download ReSwapper models here: +https://huggingface.co/datasets/Gourieff/ReActor/tree/main/models +Just put them into the "models/reswapper" directory. + ### 0.5.2 ALPHA3 - NSFW-detector to not violate [GitHub rules](https://docs.github.com/en/site-policy/acceptable-use-policies/github-misinformation-and-disinformation#synthetic--manipulated-media-tools) diff --git a/README_RU.md b/README_RU.md index 937beed..2a24afa 100644 --- a/README_RU.md +++ b/README_RU.md @@ -51,6 +51,17 @@ ## Что нового в последнем обновлении +### 0.5.2 BETA1 + +- Поддержка моделей ReSwapper. Несмотря на то, что Inswapper по-прежнему даёт лучшее сходство, но ReSwapper развивается - спасибо @somanchiu https://github.com/somanchiu/ReSwapper за эти модели и проект ReSwapper! Это хороший шаг для Сообщества в создании альтернативы Инсваппера! + +0.5.2-whatsnew-03 +0.5.2-whatsnew-04 + +Скачать модели ReSwapper можно отсюда: +https://huggingface.co/datasets/Gourieff/ReActor/tree/main/models +Сохраните их в директорию "models/reswapper". + ### 0.5.2 ALPHA3 - NSFW-детектор, чтобы не нарушать [правила GitHub](https://docs.github.com/en/site-policy/acceptable-use-policies/github-misinformation-and-disinformation#synthetic--manipulated-media-tools) diff --git a/reactor_patcher.py b/reactor_patcher.py index dac76f8..efa3c9e 100644 --- a/reactor_patcher.py +++ b/reactor_patcher.py @@ -17,6 +17,29 @@ from onnx import numpy_helper from scripts.reactor_logger import logger +def patched_get_model_log(self, **kwargs): + session = PickableInferenceSession(self.onnx_file, **kwargs) + print(f'Applied providers: {session._providers}, with options: {session._provider_options}') + inputs = session.get_inputs() + input_cfg = inputs[0] + input_shape = input_cfg.shape + outputs = session.get_outputs() + + if len(outputs) >= 5: + return RetinaFace(model_file=self.onnx_file, session=session) + elif input_shape[2] == 192 and input_shape[3] == 192: + return Landmark(model_file=self.onnx_file, session=session) + elif input_shape[2] == 96 and input_shape[3] == 96: + return Attribute(model_file=self.onnx_file, session=session) + elif len(inputs) == 2 and input_shape[2] == 128 and input_shape[3] == 128: + return INSwapper(model_file=self.onnx_file, session=session) + elif len(inputs) == 2 and input_shape[2] == 256 and input_shape[3] == 256: + return INSwapper(model_file=self.onnx_file, session=session) + elif input_shape[2] == input_shape[3] and input_shape[2] >= 112 and input_shape[2] % 16 == 0: + return ArcFaceONNX(model_file=self.onnx_file, session=session) + else: + return None + def patched_get_model(self, **kwargs): session = PickableInferenceSession(self.onnx_file, **kwargs) inputs = session.get_inputs() @@ -32,6 +55,8 @@ def patched_get_model(self, **kwargs): return Attribute(model_file=self.onnx_file, session=session) elif len(inputs) == 2 and input_shape[2] == 128 and input_shape[3] == 128: return INSwapper(model_file=self.onnx_file, session=session) + elif len(inputs) == 2 and input_shape[2] == 256 and input_shape[3] == 256: + return INSwapper(model_file=self.onnx_file, session=session) elif input_shape[2] == input_shape[3] and input_shape[2] >= 112 and input_shape[2] % 16 == 0: return ArcFaceONNX(model_file=self.onnx_file, session=session) else: @@ -119,7 +144,8 @@ def patch_insightface(get_model, faceanalysis_init, faceanalysis_prepare, inswap insightface.model_zoo.retinaface.RetinaFace.prepare = retinaface_prepare -original_functions = [ModelRouter.get_model, FaceAnalysis.__init__, FaceAnalysis.prepare, INSwapper.__init__, RetinaFace.prepare] +# original_functions = [ModelRouter.get_model, FaceAnalysis.__init__, FaceAnalysis.prepare, INSwapper.__init__, RetinaFace.prepare] +original_functions = [patched_get_model_log, FaceAnalysis.__init__, FaceAnalysis.prepare, INSwapper.__init__, RetinaFace.prepare] patched_functions = [patched_get_model, patched_faceanalysis_init, patched_faceanalysis_prepare, patched_inswapper_init, pathced_retinaface_prepare] diff --git a/scripts/reactor_faceswap.py b/scripts/reactor_faceswap.py index 7658776..2c407dc 100644 --- a/scripts/reactor_faceswap.py +++ b/scripts/reactor_faceswap.py @@ -24,10 +24,18 @@ import comfy.model_management as model_management def get_models(): - models_path = os.path.join(folder_paths.models_dir,"insightface/*") - models = glob.glob(models_path) - models = [x for x in models if x.endswith(".onnx") or x.endswith(".pth")] - return models + swappers = [ + "insightface", + "reswapper" + ] + models_list = [] + for folder in swappers: + models_folder = folder + "/*" + models_path = os.path.join(folder_paths.models_dir,models_folder) + models = glob.glob(models_path) + models = [x for x in models if x.endswith(".onnx") or x.endswith(".pth")] + models_list.extend(models) + return models_list class FaceSwapScript(scripts.Script): diff --git a/scripts/reactor_swapper.py b/scripts/reactor_swapper.py index a5800cc..4b2c3ec 100644 --- a/scripts/reactor_swapper.py +++ b/scripts/reactor_swapper.py @@ -58,6 +58,7 @@ insightface_models_path_old = os.path.join(insightface_path_old, "models") models_path = folder_paths.models_dir insightface_path = os.path.join(models_path, "insightface") insightface_models_path = os.path.join(insightface_path, "models") +reswapper_path = os.path.join(models_path, "reswapper") if os.path.exists(models_path_old): move_path(insightface_models_path_old, insightface_models_path) @@ -328,7 +329,10 @@ def swap_face( logger.status(f'Source Faces must have no entries (default=0), one entry, or same number of entries as target faces.') elif source_face is not None: result = target_img - model_path = model_path = os.path.join(insightface_path, model) + if "inswapper" in model: + model_path = model_path = os.path.join(insightface_path, model) + elif "reswapper" in model: + model_path = model_path = os.path.join(reswapper_path, model) face_swapper = getFaceSwapModel(model_path) source_face_idx = 0