From 780357ee0ced04976e48a3d5ca6d2ca58d8c86af Mon Sep 17 00:00:00 2001
From: Gourieff <777@lovemet.ru>
Date: Sun, 22 Oct 2023 15:31:32 +0700
Subject: [PATCH] UPDATE: Image hashing -> Speed Boost
+VersionUP (0.4.3 beta4)
---
README.md | 2 +-
README_RU.md | 2 +-
example/api_example.py | 2 ++
scripts/console_log_patch.py | 2 +-
scripts/reactor_faceswap.py | 28 +++++++++++++++
scripts/reactor_helpers.py | 5 +++
scripts/reactor_logger.py | 4 +--
scripts/reactor_swapper.py | 66 +++++++++++++++++++++++++++++++++---
scripts/reactor_version.py | 2 +-
9 files changed, 102 insertions(+), 11 deletions(-)
diff --git a/README.md b/README.md
index 424f51e..7742b2e 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
- 
+ 
diff --git a/README_RU.md b/README_RU.md
index 5fb66e6..62f94f7 100644
--- a/README_RU.md
+++ b/README_RU.md
@@ -2,7 +2,7 @@
- 
+ 
diff --git a/example/api_example.py b/example/api_example.py
index 0bbb08b..b073e55 100644
--- a/example/api_example.py
+++ b/example/api_example.py
@@ -40,6 +40,8 @@ args=[
0, #15 Gender Detection (Target) (0 - No, 1 - Female Only, 2 - Male Only)
False, #16 Save the original image(s) made before swapping
0.8, #17 CodeFormer Weight (0 = maximum effect, 1 = minimum effect), 0.5 - by default
+ False, #18 Source Image Hash Check, True - by default
+ False, #19 Target Image Hash Check, False - by default
]
# The args for ReActor can be found by
diff --git a/scripts/console_log_patch.py b/scripts/console_log_patch.py
index 46d0569..362dec6 100644
--- a/scripts/console_log_patch.py
+++ b/scripts/console_log_patch.py
@@ -117,4 +117,4 @@ def apply_logging_patch(console_logging_level):
logger.setLevel(logging.STATUS)
elif console_logging_level == 2:
patch_insightface(*original_functions)
- logger.setLevel(logging.STATUS)
+ logger.setLevel(logging.INFO)
diff --git a/scripts/reactor_faceswap.py b/scripts/reactor_faceswap.py
index 337b7b7..3142371 100644
--- a/scripts/reactor_faceswap.py
+++ b/scripts/reactor_faceswap.py
@@ -153,6 +153,18 @@ class FaceSwapScript(scripts.Script):
label="Console Log Level",
type="index",
)
+ gr.Markdown("
")
+ with gr.Row():
+ source_hash_check = gr.Checkbox(
+ True,
+ label="Source Image Hash Check",
+ info="Recommended to keep it ON. Processing is faster when Source Image is the same."
+ )
+ target_hash_check = gr.Checkbox(
+ False,
+ label="Target Image Hash Check",
+ info="Affects if you use img2img with only 'Swap in source image' option."
+ )
return [
img,
@@ -173,6 +185,8 @@ class FaceSwapScript(scripts.Script):
gender_target,
save_original,
codeformer_weight,
+ source_hash_check,
+ target_hash_check,
]
@@ -223,6 +237,8 @@ class FaceSwapScript(scripts.Script):
gender_target,
save_original,
codeformer_weight,
+ source_hash_check,
+ target_hash_check,
):
self.enable = enable
if self.enable:
@@ -246,6 +262,8 @@ class FaceSwapScript(scripts.Script):
self.gender_target = gender_target
self.save_original = save_original
self.codeformer_weight = codeformer_weight
+ self.source_hash_check = source_hash_check
+ self.target_hash_check = target_hash_check
if self.gender_source is None or self.gender_source == "No":
self.gender_source = 0
if self.gender_target is None or self.gender_target == "No":
@@ -262,6 +280,10 @@ class FaceSwapScript(scripts.Script):
self.faces_index = [0]
if self.save_original is None:
self.save_original = False
+ if self.source_hash_check is None:
+ self.source_hash_check = True
+ if self.target_hash_check is None:
+ self.target_hash_check = False
if self.source is not None:
apply_logging_patch(console_logging_level)
@@ -280,6 +302,8 @@ class FaceSwapScript(scripts.Script):
enhancement_options=self.enhancement_options,
gender_source=self.gender_source,
gender_target=self.gender_target,
+ source_hash_check=self.source_hash_check,
+ target_hash_check=self.target_hash_check,
)
p.init_images[i] = result
# result_path = get_image_path(p.init_images[i], p.outpath_samples, "", p.all_seeds[i], p.all_prompts[i], "txt", p=p, suffix="-swapped")
@@ -328,6 +352,8 @@ class FaceSwapScript(scripts.Script):
enhancement_options=self.enhancement_options,
gender_source=self.gender_source,
gender_target=self.gender_target,
+ source_hash_check=self.source_hash_check,
+ target_hash_check=self.target_hash_check,
)
if result is not None and swapped > 0:
result_images.append(result)
@@ -382,6 +408,8 @@ class FaceSwapScript(scripts.Script):
enhancement_options=self.enhancement_options,
gender_source=self.gender_source,
gender_target=self.gender_target,
+ source_hash_check=self.source_hash_check,
+ target_hash_check=self.target_hash_check,
)
try:
pp = scripts_postprocessing.PostprocessedImage(result)
diff --git a/scripts/reactor_helpers.py b/scripts/reactor_helpers.py
index ca05ed6..54fe81c 100644
--- a/scripts/reactor_helpers.py
+++ b/scripts/reactor_helpers.py
@@ -4,6 +4,7 @@ from PIL import Image
from math import isqrt, ceil
from typing import List
import logging
+import hashlib
from modules.images import FilenameGenerator, get_next_sequence_number
from modules import shared, script_callbacks
@@ -117,3 +118,7 @@ def addLoggingLevel(levelName, levelNum, methodName=None):
setattr(logging, levelName, levelNum)
setattr(logging.getLoggerClass(), methodName, logForLevel)
setattr(logging, methodName, logToRoot)
+
+def get_image_md5hash(image: Image.Image):
+ md5hash = hashlib.md5(image.tobytes())
+ return md5hash.hexdigest()
diff --git a/scripts/reactor_logger.py b/scripts/reactor_logger.py
index 3eb5942..d0945ae 100644
--- a/scripts/reactor_logger.py
+++ b/scripts/reactor_logger.py
@@ -42,8 +42,8 @@ if not logger.handlers:
logger.addHandler(handler)
# Configure logger
-loglevel_string = getattr(shared.cmd_opts, "reactor_loglevel", "STATUS")
-loglevel = getattr(logging, loglevel_string.upper(), "status")
+loglevel_string = getattr(shared.cmd_opts, "reactor_loglevel", "INFO")
+loglevel = getattr(logging, loglevel_string.upper(), "info")
logger.setLevel(loglevel)
def set_Run(value):
diff --git a/scripts/reactor_swapper.py b/scripts/reactor_swapper.py
index 7098df1..276fd4b 100644
--- a/scripts/reactor_swapper.py
+++ b/scripts/reactor_swapper.py
@@ -9,6 +9,7 @@ from PIL import Image
import insightface
+from scripts.reactor_helpers import get_image_md5hash
from modules.face_restoration import FaceRestoration
try: # A1111
from modules import codeformer_model
@@ -74,6 +75,10 @@ CURRENT_FS_MODEL_PATH = None
ANALYSIS_MODEL = None
+SOURCE_FACES = None
+SOURCE_IMAGE_HASH = None
+TARGET_FACES = None
+TARGET_IMAGE_HASH = None
def getAnalysisModel():
global ANALYSIS_MODEL
@@ -271,7 +276,10 @@ def swap_face(
enhancement_options: Union[EnhancementOptions, None] = None,
gender_source: int = 0,
gender_target: int = 0,
+ source_hash_check: bool = True,
+ target_hash_check: bool = False,
):
+ global SOURCE_FACES, SOURCE_IMAGE_HASH, TARGET_FACES, TARGET_IMAGE_HASH
result_image = target_img
if check_process_halt():
@@ -291,21 +299,69 @@ def swap_face(
img_bytes = base64.b64decode(source_img)
source_img = Image.open(io.BytesIO(img_bytes))
-
+
source_img = cv2.cvtColor(np.array(source_img), cv2.COLOR_RGB2BGR)
target_img = cv2.cvtColor(np.array(target_img), cv2.COLOR_RGB2BGR)
output: List = []
output_info: str = ""
swapped = 0
+
+ if source_hash_check:
- logger.status("Analyzing Source Image...")
- source_faces = analyze_faces(source_img)
+ source_image_md5hash = get_image_md5hash(source_img)
+
+ if SOURCE_IMAGE_HASH is None:
+ SOURCE_IMAGE_HASH = source_image_md5hash
+ source_image_same = False
+ else:
+ source_image_same = True if SOURCE_IMAGE_HASH == source_image_md5hash else False
+ if not source_image_same:
+ SOURCE_IMAGE_HASH = source_image_md5hash
+
+ logger.info("Source Image MD5 Hash = %s", SOURCE_IMAGE_HASH)
+ logger.info("Source Image the Same? %s", source_image_same)
+
+ if SOURCE_FACES is None or not source_image_same:
+ logger.status("Analyzing Source Image...")
+ source_faces = analyze_faces(source_img)
+ SOURCE_FACES = source_faces
+ elif source_image_same:
+ logger.status("Using Ready Source Face(s) Model...")
+ source_faces = SOURCE_FACES
+
+ else:
+ logger.status("Analyzing Source Image...")
+ source_faces = analyze_faces(source_img)
if source_faces is not None:
- logger.status("Analyzing Target Image...")
- target_faces = analyze_faces(target_img)
+ if target_hash_check:
+
+ target_image_md5hash = get_image_md5hash(target_img)
+
+ if TARGET_IMAGE_HASH is None:
+ TARGET_IMAGE_HASH = target_image_md5hash
+ target_image_same = False
+ else:
+ target_image_same = True if TARGET_IMAGE_HASH == target_image_md5hash else False
+ if not target_image_same:
+ TARGET_IMAGE_HASH = target_image_md5hash
+
+ logger.info("Target Image MD5 Hash = %s", TARGET_IMAGE_HASH)
+ logger.info("Target Image the Same? %s", target_image_same)
+
+ if TARGET_FACES is None or not target_image_same:
+ logger.status("Analyzing Target Image...")
+ target_faces = analyze_faces(target_img)
+ TARGET_FACES = target_faces
+ elif target_image_same:
+ logger.status("Using Ready Target Face(s) Model...")
+ target_faces = TARGET_FACES
+
+ else:
+ logger.status("Analyzing Target Image...")
+ target_faces = analyze_faces(target_img)
logger.status("Detecting Source Face, Index = %s", source_faces_index[0])
source_face, wrong_gender, source_age, source_gender = get_face_single(source_img, source_faces, face_index=source_faces_index[0], gender_source=gender_source)
diff --git a/scripts/reactor_version.py b/scripts/reactor_version.py
index c139384..acb23da 100644
--- a/scripts/reactor_version.py
+++ b/scripts/reactor_version.py
@@ -1,5 +1,5 @@
app_title = "ReActor"
-version_flag = "v0.4.3-b3"
+version_flag = "v0.4.3-b4"
from scripts.reactor_logger import logger, get_Run, set_Run