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!
+
+
+
+
+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! Это хороший шаг для Сообщества в создании альтернативы Инсваппера!
+
+
+
+
+Скачать модели 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