From 0c11aeb640883e962d9d894edfb8754c1e17b6f4 Mon Sep 17 00:00:00 2001
From: w-e-w <40751091+w-e-w@users.noreply.github.com>
Date: Tue, 31 Oct 2023 13:16:48 +0900
Subject: [PATCH] Extras tab script
---
scripts/reactor_faceswap.py | 223 ++++++++++++++++++++++++++++++++++++
1 file changed, 223 insertions(+)
diff --git a/scripts/reactor_faceswap.py b/scripts/reactor_faceswap.py
index 3142371..dcbcbb8 100644
--- a/scripts/reactor_faceswap.py
+++ b/scripts/reactor_faceswap.py
@@ -424,3 +424,226 @@ class FaceSwapScript(scripts.Script):
# f.writelines(output)
except:
logger.error("Cannot create a result image")
+
+
+class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
+ name = 'ReActor'
+ order = 20000
+
+ def ui(self):
+ with gr.Accordion(f"{app_title}", open=False):
+ with gr.Tab("Main"):
+ with gr.Column():
+ img = gr.Image(type="pil")
+ enable = gr.Checkbox(False, label="Enable", info=f"The Fast and Simple FaceSwap Extension - {version_flag}")
+ gr.Markdown("
")
+ gr.Markdown("Source Image (above):")
+ with gr.Row():
+ source_faces_index = gr.Textbox(
+ value="0",
+ placeholder="Which face(s) to use as Source (comma separated)",
+ label="Comma separated face number(s); Example: 0,2,1",
+ )
+ gender_source = gr.Radio(
+ ["No", "Female Only", "Male Only"],
+ value="No",
+ label="Gender Detection (Source)",
+ type="index",
+ )
+ gr.Markdown("
")
+ gr.Markdown("Target Image (result):")
+ with gr.Row():
+ faces_index = gr.Textbox(
+ value="0",
+ placeholder="Which face(s) to Swap into Target (comma separated)",
+ label="Comma separated face number(s); Example: 1,0,2",
+ )
+ gender_target = gr.Radio(
+ ["No", "Female Only", "Male Only"],
+ value="No",
+ label="Gender Detection (Target)",
+ type="index",
+ )
+ gr.Markdown("
")
+ with gr.Row():
+ face_restorer_name = gr.Radio(
+ label="Restore Face",
+ choices=["None"] + [x.name() for x in shared.face_restorers],
+ value=shared.face_restorers[0].name(),
+ type="value",
+ )
+ with gr.Column():
+ face_restorer_visibility = gr.Slider(
+ 0, 1, 1, step=0.1, label="Restore Face Visibility"
+ )
+ codeformer_weight = gr.Slider(
+ 0, 1, 0.5, step=0.1, label="CodeFormer Weight", info="0 = maximum effect, 1 = minimum effect"
+ )
+ gr.Markdown("
")
+
+ with gr.Tab("Upscale"):
+ restore_first = gr.Checkbox(
+ True,
+ label="1. Restore Face -> 2. Upscale (-Uncheck- if you want vice versa)",
+ info="Postprocessing Order"
+ )
+ upscaler_name = gr.Dropdown(
+ choices=[upscaler.name for upscaler in shared.sd_upscalers],
+ label="Upscaler",
+ value="None",
+ info="Won't scale if you choose -Swap in Source- via img2img, only 1x-postprocessing will affect (texturing, denoising, restyling etc.)"
+ )
+ gr.Markdown("
")
+ with gr.Row():
+ upscaler_scale = gr.Slider(1, 8, 1, step=0.1, label="Scale by")
+ upscaler_visibility = gr.Slider(
+ 0, 1, 1, step=0.1, label="Upscaler Visibility (if scale = 1)"
+ )
+ with gr.Tab("Settings"):
+ models = get_models()
+ with gr.Row():
+ if len(models) == 0:
+ logger.warning(
+ "You should at least have one model in models directory, please read the doc here : https://github.com/Gourieff/sd-webui-reactor/"
+ )
+ model = gr.Dropdown(
+ choices=models,
+ label="Model not found, please download one and reload WebUI",
+ )
+ else:
+ model = gr.Dropdown(
+ choices=models, label="Model", value=models[0]
+ )
+ console_logging_level = gr.Radio(
+ ["No log", "Minimum", "Default"],
+ value="Minimum",
+ 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."
+ )
+
+ args = {
+ 'img': img,
+ 'enable': enable,
+ 'source_faces_index': source_faces_index,
+ 'faces_index': faces_index,
+ 'model': model,
+ 'face_restorer_name': face_restorer_name,
+ 'face_restorer_visibility': face_restorer_visibility,
+ 'restore_first': restore_first,
+ 'upscaler_name': upscaler_name,
+ 'upscaler_scale': upscaler_scale,
+ 'upscaler_visibility': upscaler_visibility,
+ 'console_logging_level': console_logging_level,
+ 'gender_source': gender_source,
+ 'gender_target': gender_target,
+ 'codeformer_weight': codeformer_weight,
+ 'source_hash_check': source_hash_check,
+ 'target_hash_check': target_hash_check,
+ }
+ return args
+
+ @property
+ def upscaler(self) -> UpscalerData:
+ for upscaler in shared.sd_upscalers:
+ if upscaler.name == self.upscaler_name:
+ return upscaler
+ return None
+
+ @property
+ def face_restorer(self) -> FaceRestoration:
+ for face_restorer in shared.face_restorers:
+ if face_restorer.name() == self.face_restorer_name:
+ return face_restorer
+ return None
+
+ @property
+ def enhancement_options(self) -> EnhancementOptions:
+ return EnhancementOptions(
+ do_restore_first=self.restore_first,
+ scale=self.upscaler_scale,
+ upscaler=self.upscaler,
+ face_restorer=self.face_restorer,
+ upscale_visibility=self.upscaler_visibility,
+ restorer_visibility=self.face_restorer_visibility,
+ codeformer_weight=self.codeformer_weight,
+ )
+
+ def process(self, pp: scripts_postprocessing.PostprocessedImage, **args):
+ if args['enable']:
+ reset_messaged()
+ if check_process_halt():
+ return
+
+ global MODELS_PATH
+ self.source = args['img']
+ self.face_restorer_name = args['face_restorer_name']
+ self.upscaler_scale = args['upscaler_scale']
+ self.upscaler_visibility = args['upscaler_visibility']
+ self.face_restorer_visibility = args['face_restorer_visibility']
+ self.restore_first = args['restore_first']
+ self.upscaler_name = args['upscaler_name']
+ self.model = os.path.join(MODELS_PATH, args['model'])
+ self.console_logging_level = args['console_logging_level']
+ self.gender_source = args['gender_source']
+ self.gender_target = args['gender_target']
+ self.codeformer_weight = args['codeformer_weight']
+ self.source_hash_check = args['source_hash_check']
+ self.target_hash_check = args['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":
+ self.gender_target = 0
+ self.source_faces_index = [
+ int(x) for x in args['source_faces_index'].strip(",").split(",") if x.isnumeric()
+ ]
+ self.faces_index = [
+ int(x) for x in args['faces_index'].strip(",").split(",") if x.isnumeric()
+ ]
+ if len(self.source_faces_index) == 0:
+ self.source_faces_index = [0]
+ if len(self.faces_index) == 0:
+ self.faces_index = [0]
+ if self.source_hash_check is None:
+ self.source_hash_check = True
+ if self.target_hash_check is None:
+ self.target_hash_check = False
+
+ current_job_number = shared.state.job_no + 1
+ job_count = shared.state.job_count
+ if current_job_number == job_count:
+ reset_messaged()
+
+ if self.source is not None:
+ logger.status("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index)
+ image: Image.Image = pp.image
+ result, output, swapped = swap_face(
+ self.source,
+ image,
+ source_faces_index=self.source_faces_index,
+ faces_index=self.faces_index,
+ model=self.model,
+ 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.info["ReActor"] = True
+ pp.image = result
+ except Exception:
+ logger.error("Cannot create a result image")
+ else:
+ logger.error("Please provide a source face")