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 @@ logo - ![Version](https://img.shields.io/badge/version-0.4.3_beta3-green?style=for-the-badge&labelColor=darkgreen) + ![Version](https://img.shields.io/badge/version-0.4.3_beta4-green?style=for-the-badge&labelColor=darkgreen) 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 @@ logo - ![Version](https://img.shields.io/badge/версия-0.4.3_beta3-green?style=for-the-badge&labelColor=darkgreen) + ![Version](https://img.shields.io/badge/версия-0.4.3_beta4-green?style=for-the-badge&labelColor=darkgreen)
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