FIX: Many different
Different fixes and improvements +VersionUP (beta1)
This commit is contained in:
parent
376c19c62f
commit
0901ab9ed4
@ -1,4 +1,4 @@
|
||||
insightface==0.7.3
|
||||
onnx==1.14.0
|
||||
onnxruntime==1.15.0
|
||||
onnx>=1.14.0
|
||||
onnxruntime>=1.15.0
|
||||
opencv-python>=4.7.0.72
|
||||
|
||||
@ -14,7 +14,7 @@ from modules.api import api
|
||||
|
||||
import gradio as gr
|
||||
|
||||
from scripts.reactor_swapper import UpscaleOptions, swap_face
|
||||
from scripts.reactor_swapper import EnhancementOptions, swap_face
|
||||
from scripts.reactor_logger import logger
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ def reactor_api(_: gr.Blocks, app: FastAPI):
|
||||
gender_s = gender_source
|
||||
gender_t = gender_target
|
||||
restore_first_bool = True if restore_first == 1 else False
|
||||
up_options = UpscaleOptions(do_restore_first=restore_first_bool, scale=scale, upscaler=get_upscaler(upscaler), upscale_visibility=upscale_visibility,face_restorer=get_face_restorer(face_restorer),restorer_visibility=restorer_visibility)
|
||||
up_options = EnhancementOptions(do_restore_first=restore_first_bool, scale=scale, upscaler=get_upscaler(upscaler), upscale_visibility=upscale_visibility,face_restorer=get_face_restorer(face_restorer),restorer_visibility=restorer_visibility)
|
||||
use_model = get_full_model(model)
|
||||
if use_model is None:
|
||||
Exception("Model not found")
|
||||
|
||||
@ -17,10 +17,10 @@ from modules.paths_internal import models_path
|
||||
from modules.images import save_image
|
||||
|
||||
from scripts.reactor_logger import logger
|
||||
from scripts.reactor_swapper import UpscaleOptions, swap_face, check_process_halt, reset_messaged
|
||||
from scripts.reactor_swapper import EnhancementOptions, swap_face, check_process_halt, reset_messaged
|
||||
from scripts.reactor_version import version_flag, app_title
|
||||
from scripts.console_log_patch import apply_logging_patch
|
||||
from scripts.reactor_helpers import make_grid
|
||||
from scripts.reactor_helpers import make_grid, get_image_path
|
||||
|
||||
|
||||
MODELS_PATH = None
|
||||
@ -51,7 +51,7 @@ class FaceSwapScript(scripts.Script):
|
||||
with gr.Accordion(f"{app_title}", open=False):
|
||||
with gr.Tab("Main"):
|
||||
with gr.Column():
|
||||
img = gr.inputs.Image(type="pil")
|
||||
img = gr.Image(type="pil")
|
||||
enable = gr.Checkbox(False, label="Enable", info=f"The Fast and Simple FaceSwap Extension - {version_flag}")
|
||||
save_original = gr.Checkbox(False, label="Save Original", info="Save the original image(s) made before swapping; If you use \"img2img\" - this option will affect with \"Swap in generated\" only")
|
||||
gr.Markdown("<br>")
|
||||
@ -110,9 +110,11 @@ class FaceSwapScript(scripts.Script):
|
||||
label="1. Restore Face -> 2. Upscale (-Uncheck- if you want vice versa)",
|
||||
info="Postprocessing Order"
|
||||
)
|
||||
upscaler_name = gr.inputs.Dropdown(
|
||||
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("<br>")
|
||||
with gr.Row():
|
||||
@ -127,13 +129,13 @@ class FaceSwapScript(scripts.Script):
|
||||
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.inputs.Dropdown(
|
||||
model = gr.Dropdown(
|
||||
choices=models,
|
||||
label="Model not found, please download one and reload WebUI",
|
||||
)
|
||||
else:
|
||||
model = gr.inputs.Dropdown(
|
||||
choices=models, label="Model", default=models[0]
|
||||
model = gr.Dropdown(
|
||||
choices=models, label="Model", value=models[0]
|
||||
)
|
||||
console_logging_level = gr.Radio(
|
||||
["No log", "Minimum", "Default"],
|
||||
@ -178,8 +180,8 @@ class FaceSwapScript(scripts.Script):
|
||||
return None
|
||||
|
||||
@property
|
||||
def upscale_options(self) -> UpscaleOptions:
|
||||
return UpscaleOptions(
|
||||
def enhancement_options(self) -> EnhancementOptions:
|
||||
return EnhancementOptions(
|
||||
do_restore_first = self.restore_first,
|
||||
scale=self.upscaler_scale,
|
||||
upscaler=self.upscaler,
|
||||
@ -253,17 +255,21 @@ class FaceSwapScript(scripts.Script):
|
||||
for i in range(len(p.init_images)):
|
||||
if len(p.init_images) > 1:
|
||||
logger.info("Swap in %s", i)
|
||||
result = swap_face(
|
||||
result, output, swapped = swap_face(
|
||||
self.source,
|
||||
p.init_images[i],
|
||||
source_faces_index=self.source_faces_index,
|
||||
faces_index=self.faces_index,
|
||||
model=self.model,
|
||||
upscale_options=self.upscale_options,
|
||||
enhancement_options=self.enhancement_options,
|
||||
gender_source=self.gender_source,
|
||||
gender_target=self.gender_target,
|
||||
)
|
||||
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")
|
||||
# if len(output) != 0:
|
||||
# with open(result_path, 'w', encoding="utf8") as f:
|
||||
# f.writelines(output)
|
||||
|
||||
if shared.state.interrupted or shared.state.skipped:
|
||||
return
|
||||
@ -286,6 +292,7 @@ class FaceSwapScript(scripts.Script):
|
||||
orig_infotexts : List[str] = processed.infotexts[processed.index_of_first_image:]
|
||||
|
||||
result_images: List = processed.images
|
||||
# result_info: List = processed.infotexts
|
||||
|
||||
if self.swap_in_generated:
|
||||
logger.info("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index)
|
||||
@ -296,25 +303,31 @@ class FaceSwapScript(scripts.Script):
|
||||
break
|
||||
if len(orig_images) > 1:
|
||||
logger.info("Swap in %s", i)
|
||||
result = swap_face(
|
||||
result, output, swapped = swap_face(
|
||||
self.source,
|
||||
img,
|
||||
source_faces_index=self.source_faces_index,
|
||||
faces_index=self.faces_index,
|
||||
model=self.model,
|
||||
upscale_options=self.upscale_options,
|
||||
enhancement_options=self.enhancement_options,
|
||||
gender_source=self.gender_source,
|
||||
gender_target=self.gender_target,
|
||||
)
|
||||
if result is not None:
|
||||
suffix = "-swapped"
|
||||
if result is not None and swapped > 0:
|
||||
result_images.append(result)
|
||||
suffix = "-swapped"
|
||||
try:
|
||||
save_image(result, p.outpath_samples, "", p.all_seeds[0], p.all_prompts[0], "png",info=info, p=p, suffix=suffix)
|
||||
img_path = save_image(result, p.outpath_samples, "", p.all_seeds[0], p.all_prompts[0], "png",info=info, p=p, suffix=suffix)
|
||||
except:
|
||||
logger.error("Cannot save a result image - please, check SD WebUI Settings (Saving and Paths)")
|
||||
else:
|
||||
elif result is None:
|
||||
logger.error("Cannot create a result image")
|
||||
|
||||
# if len(output) != 0:
|
||||
# split_fullfn = os.path.splitext(img_path[0])
|
||||
# fullfn = split_fullfn[0] + ".txt"
|
||||
# with open(fullfn, 'w', encoding="utf8") as f:
|
||||
# f.writelines(output)
|
||||
|
||||
if shared.opts.return_grid and len(result_images) > 2 and postprocess_run:
|
||||
grid = make_grid(result_images)
|
||||
@ -324,7 +337,8 @@ class FaceSwapScript(scripts.Script):
|
||||
except:
|
||||
logger.error("Cannot save a grid - please, check SD WebUI Settings (Saving and Paths)")
|
||||
|
||||
processed.images = result_images
|
||||
processed.images = result_images
|
||||
# processed.infotexts = result_info
|
||||
|
||||
def postprocess_batch(self, p, *args, **kwargs):
|
||||
if self.enable and not self.save_original:
|
||||
@ -343,13 +357,13 @@ class FaceSwapScript(scripts.Script):
|
||||
if self.source is not None:
|
||||
logger.info("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index)
|
||||
image: Image.Image = script_pp.image
|
||||
result = swap_face(
|
||||
result, output, swapped = swap_face(
|
||||
self.source,
|
||||
image,
|
||||
source_faces_index=self.source_faces_index,
|
||||
faces_index=self.faces_index,
|
||||
model=self.model,
|
||||
upscale_options=self.upscale_options,
|
||||
enhancement_options=self.enhancement_options,
|
||||
gender_source=self.gender_source,
|
||||
gender_target=self.gender_target,
|
||||
)
|
||||
@ -358,5 +372,11 @@ class FaceSwapScript(scripts.Script):
|
||||
pp.info = {}
|
||||
p.extra_generation_params.update(pp.info)
|
||||
script_pp.image = pp.image
|
||||
|
||||
# if len(output) != 0:
|
||||
# result_path = get_image_path(script_pp.image, p.outpath_samples, "", p.all_seeds[0], p.all_prompts[0], "txt", p=p, suffix="-swapped")
|
||||
# if len(output) != 0:
|
||||
# with open(result_path, 'w', encoding="utf8") as f:
|
||||
# f.writelines(output)
|
||||
except:
|
||||
logger.error("Cannot create a result image")
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
import os
|
||||
from collections import Counter
|
||||
from PIL import Image
|
||||
from math import isqrt, ceil
|
||||
from typing import List
|
||||
|
||||
from modules.images import FilenameGenerator, get_next_sequence_number
|
||||
from modules import shared, script_callbacks
|
||||
|
||||
def make_grid(image_list: List):
|
||||
|
||||
# Count the occurrences of each image size in the image_list
|
||||
@ -43,3 +47,56 @@ def make_grid(image_list: List):
|
||||
|
||||
# Return None if there are no images or only one image in the image_list
|
||||
return None
|
||||
|
||||
def get_image_path(image, path, basename, seed=None, prompt=None, extension='png', p=None, suffix=""):
|
||||
|
||||
namegen = FilenameGenerator(p, seed, prompt, image)
|
||||
|
||||
save_to_dirs = shared.opts.save_to_dirs
|
||||
|
||||
if save_to_dirs:
|
||||
dirname = namegen.apply(shared.opts.directories_filename_pattern or "[prompt_words]").lstrip(' ').rstrip('\\ /')
|
||||
path = os.path.join(path, dirname)
|
||||
|
||||
os.makedirs(path, exist_ok=True)
|
||||
|
||||
if seed is None:
|
||||
file_decoration = ""
|
||||
elif shared.opts.save_to_dirs:
|
||||
file_decoration = shared.opts.samples_filename_pattern or "[seed]"
|
||||
else:
|
||||
file_decoration = shared.opts.samples_filename_pattern or "[seed]-[prompt_spaces]"
|
||||
|
||||
file_decoration = namegen.apply(file_decoration) + suffix
|
||||
|
||||
add_number = shared.opts.save_images_add_number or file_decoration == ''
|
||||
|
||||
if file_decoration != "" and add_number:
|
||||
file_decoration = f"-{file_decoration}"
|
||||
|
||||
if add_number:
|
||||
basecount = get_next_sequence_number(path, basename)
|
||||
fullfn = None
|
||||
for i in range(500):
|
||||
fn = f"{basecount + i:05}" if basename == '' else f"{basename}-{basecount + i:04}"
|
||||
fullfn = os.path.join(path, f"{fn}{file_decoration}.{extension}")
|
||||
if not os.path.exists(fullfn):
|
||||
break
|
||||
else:
|
||||
fullfn = os.path.join(path, f"{file_decoration}.{extension}")
|
||||
|
||||
pnginfo = {}
|
||||
|
||||
params = script_callbacks.ImageSaveParams(image, p, fullfn, pnginfo)
|
||||
# script_callbacks.before_image_saved_callback(params)
|
||||
|
||||
fullfn = params.filename
|
||||
|
||||
fullfn_without_extension, extension = os.path.splitext(params.filename)
|
||||
if hasattr(os, 'statvfs'):
|
||||
max_name_len = os.statvfs(path).f_namemax
|
||||
fullfn_without_extension = fullfn_without_extension[:max_name_len - max(4, len(extension))]
|
||||
params.filename = fullfn_without_extension + extension
|
||||
fullfn = params.filename
|
||||
|
||||
return fullfn
|
||||
|
||||
@ -8,7 +8,6 @@ import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
import insightface
|
||||
import onnxruntime
|
||||
|
||||
from modules.face_restoration import FaceRestoration
|
||||
from modules.upscaler import UpscalerData
|
||||
@ -21,11 +20,11 @@ import warnings
|
||||
np.warnings = warnings
|
||||
np.warnings.filterwarnings('ignore')
|
||||
|
||||
providers = onnxruntime.get_available_providers()
|
||||
providers = ["CPUExecutionProvider"]
|
||||
|
||||
|
||||
@dataclass
|
||||
class UpscaleOptions:
|
||||
class EnhancementOptions:
|
||||
do_restore_first: bool = True
|
||||
scale: int = 1
|
||||
upscaler: UpscalerData = None
|
||||
@ -34,24 +33,6 @@ class UpscaleOptions:
|
||||
restorer_visibility: float = 0.5
|
||||
|
||||
|
||||
def cosine_distance(vector1: np.ndarray, vector2: np.ndarray) -> float:
|
||||
vec1 = vector1.flatten()
|
||||
vec2 = vector2.flatten()
|
||||
|
||||
dot_product = np.dot(vec1, vec2)
|
||||
norm1 = np.linalg.norm(vec1)
|
||||
norm2 = np.linalg.norm(vec2)
|
||||
|
||||
cosine_distance = 1 - (dot_product / (norm1 * norm2))
|
||||
return cosine_distance
|
||||
|
||||
|
||||
def cosine_similarity(test_vec: np.ndarray, source_vecs: List[np.ndarray]) -> float:
|
||||
cos_dist = sum(cosine_distance(test_vec, source_vec) for source_vec in source_vecs)
|
||||
average_cos_dist = cos_dist / len(source_vecs)
|
||||
return average_cos_dist
|
||||
|
||||
|
||||
MESSAGED_STOPPED = False
|
||||
MESSAGED_SKIPPED = False
|
||||
|
||||
@ -102,76 +83,88 @@ def getFaceSwapModel(model_path: str):
|
||||
return FS_MODEL
|
||||
|
||||
|
||||
def upscale_image(image: Image, upscale_options: UpscaleOptions):
|
||||
def restore_face(image: Image, enhancement_options: EnhancementOptions):
|
||||
result_image = image
|
||||
|
||||
if check_process_halt(msgforced=True):
|
||||
return result_image
|
||||
|
||||
if enhancement_options.face_restorer is not None:
|
||||
original_image = result_image.copy()
|
||||
logger.info("Restoring the face with %s", enhancement_options.face_restorer.name())
|
||||
numpy_image = np.array(result_image)
|
||||
numpy_image = enhancement_options.face_restorer.restore(numpy_image)
|
||||
restored_image = Image.fromarray(numpy_image)
|
||||
result_image = Image.blend(
|
||||
original_image, restored_image, enhancement_options.restorer_visibility
|
||||
)
|
||||
|
||||
return result_image
|
||||
|
||||
def upscale_image(image: Image, enhancement_options: EnhancementOptions):
|
||||
result_image = image
|
||||
|
||||
if check_process_halt(msgforced=True):
|
||||
return result_image
|
||||
|
||||
if enhancement_options.upscaler is not None and enhancement_options.upscaler.name != "None":
|
||||
original_image = result_image.copy()
|
||||
logger.info(
|
||||
"Upscaling with %s scale = %s",
|
||||
enhancement_options.upscaler.name,
|
||||
enhancement_options.scale,
|
||||
)
|
||||
result_image = enhancement_options.upscaler.scaler.upscale(
|
||||
original_image, enhancement_options.scale, enhancement_options.upscaler.data_path
|
||||
)
|
||||
if enhancement_options.scale == 1:
|
||||
result_image = Image.blend(
|
||||
original_image, result_image, enhancement_options.upscale_visibility
|
||||
)
|
||||
|
||||
return result_image
|
||||
|
||||
def enhance_image(image: Image, enhancement_options: EnhancementOptions):
|
||||
result_image = image
|
||||
|
||||
if check_process_halt(msgforced=True):
|
||||
return result_image
|
||||
|
||||
if upscale_options.do_restore_first:
|
||||
if upscale_options.face_restorer is not None:
|
||||
original_image = result_image.copy()
|
||||
logger.info("Restoring the face with %s", upscale_options.face_restorer.name())
|
||||
numpy_image = np.array(result_image)
|
||||
numpy_image = upscale_options.face_restorer.restore(numpy_image)
|
||||
restored_image = Image.fromarray(numpy_image)
|
||||
result_image = Image.blend(
|
||||
original_image, restored_image, upscale_options.restorer_visibility
|
||||
)
|
||||
if upscale_options.upscaler is not None and upscale_options.upscaler.name != "None":
|
||||
original_image = result_image.copy()
|
||||
logger.info(
|
||||
"Upscaling with %s scale = %s",
|
||||
upscale_options.upscaler.name,
|
||||
upscale_options.scale,
|
||||
)
|
||||
result_image = upscale_options.upscaler.scaler.upscale(
|
||||
original_image, upscale_options.scale, upscale_options.upscaler.data_path
|
||||
)
|
||||
if upscale_options.scale == 1:
|
||||
result_image = Image.blend(
|
||||
original_image, result_image, upscale_options.upscale_visibility
|
||||
)
|
||||
if enhancement_options.do_restore_first:
|
||||
|
||||
result_image = restore_face(result_image, enhancement_options)
|
||||
result_image = upscale_image(result_image, enhancement_options)
|
||||
|
||||
else:
|
||||
if upscale_options.upscaler is not None and upscale_options.upscaler.name != "None":
|
||||
original_image = result_image.copy()
|
||||
logger.info(
|
||||
"Upscaling with %s scale = %s",
|
||||
upscale_options.upscaler.name,
|
||||
upscale_options.scale,
|
||||
)
|
||||
result_image = upscale_options.upscaler.scaler.upscale(
|
||||
image, upscale_options.scale, upscale_options.upscaler.data_path
|
||||
)
|
||||
if upscale_options.scale == 1:
|
||||
result_image = Image.blend(
|
||||
original_image, result_image, upscale_options.upscale_visibility
|
||||
)
|
||||
if upscale_options.face_restorer is not None:
|
||||
original_image = result_image.copy()
|
||||
logger.info("Restoring the face with %s", upscale_options.face_restorer.name())
|
||||
numpy_image = np.array(result_image)
|
||||
numpy_image = upscale_options.face_restorer.restore(numpy_image)
|
||||
restored_image = Image.fromarray(numpy_image)
|
||||
result_image = Image.blend(
|
||||
original_image, restored_image, upscale_options.restorer_visibility
|
||||
)
|
||||
|
||||
result_image = upscale_image(result_image, enhancement_options)
|
||||
result_image = restore_face(result_image, enhancement_options)
|
||||
|
||||
return result_image
|
||||
|
||||
|
||||
def get_face_gender(
|
||||
face,
|
||||
face_index,
|
||||
gender_condition,
|
||||
operated: str
|
||||
):
|
||||
def get_gender(face, face_index):
|
||||
gender = [
|
||||
x.sex
|
||||
for x in face
|
||||
]
|
||||
gender.reverse()
|
||||
face_gender = gender[face_index]
|
||||
try:
|
||||
face_gender = gender[face_index]
|
||||
except:
|
||||
logger.error("Gender Detection: No face with index = %s was found", face_index)
|
||||
return "None"
|
||||
return face_gender
|
||||
|
||||
def get_face_gender(
|
||||
face,
|
||||
face_index,
|
||||
gender_condition,
|
||||
operated: str,
|
||||
gender_detected,
|
||||
):
|
||||
face_gender = gender_detected
|
||||
if face_gender == "None":
|
||||
return None, 0
|
||||
logger.info("%s Face %s: Detected Gender -%s-", operated, face_index, face_gender)
|
||||
if (gender_condition == 1 and face_gender == "F") or (gender_condition == 2 and face_gender == "M"):
|
||||
logger.info("OK - Detected Gender matches Condition")
|
||||
@ -183,10 +176,22 @@ def get_face_gender(
|
||||
logger.info("WRONG - Detected Gender doesn't match Condition")
|
||||
return sorted(face, key=lambda x: x.bbox[0])[face_index], 1
|
||||
|
||||
def get_face_age(face, face_index):
|
||||
age = [
|
||||
x.age
|
||||
for x in face
|
||||
]
|
||||
age.reverse()
|
||||
try:
|
||||
face_age = age[face_index]
|
||||
except:
|
||||
logger.error("Age Detection: No face with index = %s was found", face_index)
|
||||
return "None"
|
||||
return face_age
|
||||
|
||||
def reget_face_single(img_data, det_size, face_index):
|
||||
def reget_face_single(img_data, det_size, face_index, gender_source, gender_target):
|
||||
det_size_half = (det_size[0] // 2, det_size[1] // 2)
|
||||
return get_face_single(img_data, face_index=face_index, det_size=det_size_half)
|
||||
return get_face_single(img_data, face_index=face_index, det_size=det_size_half, gender_source=gender_source, gender_target=gender_target)
|
||||
|
||||
|
||||
def get_face_single(img_data: np.ndarray, face_index=0, det_size=(640, 640), gender_source=0, gender_target=0):
|
||||
@ -198,23 +203,39 @@ def get_face_single(img_data: np.ndarray, face_index=0, det_size=(640, 640), gen
|
||||
if os.path.exists(buffalo_path):
|
||||
os.remove(buffalo_path)
|
||||
|
||||
face_age = "None"
|
||||
try:
|
||||
face_age = get_face_age(face, face_index)
|
||||
except:
|
||||
logger.error("Cannot detect any Age for Face index = %s", face_index)
|
||||
|
||||
face_gender = "None"
|
||||
try:
|
||||
face_gender = get_gender(face, face_index)
|
||||
gender_detected = face_gender
|
||||
face_gender = "Female" if face_gender == "F" else ("Male" if face_gender == "M" else "None")
|
||||
except:
|
||||
logger.error("Cannot detect any Gender for Face index = %s", face_index)
|
||||
|
||||
if gender_source != 0:
|
||||
if len(face) == 0 and det_size[0] > 320 and det_size[1] > 320:
|
||||
return reget_face_single(img_data, det_size, face_index)
|
||||
return get_face_gender(face,face_index,gender_source,"Source")
|
||||
return reget_face_single(img_data, det_size, face_index, gender_source, gender_target)
|
||||
faces, wrong_gender = get_face_gender(face,face_index,gender_source,"Source",gender_detected)
|
||||
return faces, wrong_gender, face_age, face_gender
|
||||
|
||||
if gender_target != 0:
|
||||
if len(face) == 0 and det_size[0] > 320 and det_size[1] > 320:
|
||||
return reget_face_single(img_data, det_size, face_index)
|
||||
return get_face_gender(face,face_index,gender_target,"Target")
|
||||
return reget_face_single(img_data, det_size, face_index, gender_source, gender_target)
|
||||
faces, wrong_gender = get_face_gender(face,face_index,gender_target,"Target",gender_detected)
|
||||
return faces, wrong_gender, face_age, face_gender
|
||||
|
||||
if len(face) == 0 and det_size[0] > 320 and det_size[1] > 320:
|
||||
return reget_face_single(img_data, det_size, face_index)
|
||||
return reget_face_single(img_data, det_size, face_index, gender_source, gender_target)
|
||||
|
||||
try:
|
||||
return sorted(face, key=lambda x: x.bbox[0])[face_index], 0
|
||||
return sorted(face, key=lambda x: x.bbox[0])[face_index], 0, face_age, face_gender
|
||||
except IndexError:
|
||||
return None, 0
|
||||
return None, 0, face_age, face_gender
|
||||
|
||||
|
||||
def swap_face(
|
||||
@ -223,7 +244,7 @@ def swap_face(
|
||||
model: Union[str, None] = None,
|
||||
source_faces_index: List[int] = [0],
|
||||
faces_index: List[int] = [0],
|
||||
upscale_options: Union[UpscaleOptions, None] = None,
|
||||
enhancement_options: Union[EnhancementOptions, None] = None,
|
||||
gender_source: int = 0,
|
||||
gender_target: int = 0,
|
||||
):
|
||||
@ -250,52 +271,88 @@ def swap_face(
|
||||
source_img = cv2.cvtColor(np.array(source_img), cv2.COLOR_RGB2BGR)
|
||||
target_img = cv2.cvtColor(np.array(target_img), cv2.COLOR_RGB2BGR)
|
||||
|
||||
source_face, wrong_gender = get_face_single(source_img, face_index=source_faces_index[0], gender_source=gender_source)
|
||||
output: List = []
|
||||
output_info: str = ""
|
||||
swapped = 0
|
||||
|
||||
logger.info("Detecting Source Face, Index = %s", source_faces_index[0])
|
||||
source_face, wrong_gender, source_age, source_gender = get_face_single(source_img, face_index=source_faces_index[0], gender_source=gender_source)
|
||||
if source_age != "None" or source_gender != "None":
|
||||
logger.info("Detected: -%s- y.o. %s", source_age, source_gender)
|
||||
|
||||
output_info = f"SourceFaceIndex={source_faces_index[0]};Age={source_age};Gender={source_gender}\n"
|
||||
output.append(output_info)
|
||||
|
||||
if len(source_faces_index) != 0 and len(source_faces_index) != 1 and len(source_faces_index) != len(faces_index):
|
||||
logger.info("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
|
||||
face_swapper = getFaceSwapModel(model)
|
||||
|
||||
source_face_idx = 0
|
||||
|
||||
swapped = 0
|
||||
|
||||
for face_num in faces_index:
|
||||
if len(source_faces_index) > 1 and source_face_idx > 0:
|
||||
source_face, wrong_gender = get_face_single(source_img, face_index=source_faces_index[source_face_idx], gender_source=gender_source)
|
||||
|
||||
logger.info("Detecting Source Face, Index = %s", source_faces_index[source_face_idx])
|
||||
source_face, wrong_gender, source_age, source_gender = get_face_single(source_img, face_index=source_faces_index[source_face_idx], gender_source=gender_source)
|
||||
if source_age != "None" or source_gender != "None":
|
||||
logger.info("Detected: -%s- y.o. %s", source_age, source_gender)
|
||||
|
||||
output_info = f"SourceFaceIndex={source_faces_index[source_face_idx]};Age={source_age};Gender={source_gender}\n"
|
||||
output.append(output_info)
|
||||
|
||||
source_face_idx += 1
|
||||
|
||||
if source_face is not None and wrong_gender == 0:
|
||||
target_face, wrong_gender = get_face_single(target_img, face_index=face_num, gender_target=gender_target)
|
||||
logger.info("Detecting Target Face, Index = %s", face_num)
|
||||
target_face, wrong_gender, target_age, target_gender = get_face_single(target_img, face_index=face_num, gender_target=gender_target)
|
||||
if target_age != "None" or target_gender != "None":
|
||||
logger.info("Detected: -%s- y.o. %s", target_age, target_gender)
|
||||
|
||||
output_info = f"TargetFaceIndex={face_num};Age={target_age};Gender={target_gender}\n"
|
||||
output.append(output_info)
|
||||
|
||||
if target_face is not None and wrong_gender == 0:
|
||||
logger.info("Swapping Source into Target")
|
||||
result = face_swapper.get(result, target_face, source_face)
|
||||
swapped += 1
|
||||
|
||||
elif wrong_gender == 1:
|
||||
wrong_gender = 0
|
||||
|
||||
if source_face_idx == len(source_faces_index):
|
||||
result_image = Image.fromarray(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
|
||||
if upscale_options is not None:
|
||||
result_image = upscale_image(result_image, upscale_options)
|
||||
return result_image
|
||||
|
||||
if enhancement_options is not None and len(source_faces_index) > 1:
|
||||
result_image = enhance_image(result_image, enhancement_options)
|
||||
|
||||
return result_image, output, swapped
|
||||
|
||||
else:
|
||||
logger.info(f"No target face found for {face_num}")
|
||||
|
||||
elif wrong_gender == 1:
|
||||
wrong_gender = 0
|
||||
|
||||
if source_face_idx == len(source_faces_index):
|
||||
result_image = Image.fromarray(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
|
||||
if upscale_options is not None:
|
||||
result_image = upscale_image(result_image, upscale_options)
|
||||
return result_image
|
||||
|
||||
if enhancement_options is not None and len(source_faces_index) > 1:
|
||||
result_image = enhance_image(result_image, enhancement_options)
|
||||
|
||||
return result_image, output, swapped
|
||||
|
||||
else:
|
||||
logger.info(f"No source face found for face number {source_face_idx}.")
|
||||
|
||||
result_image = Image.fromarray(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
|
||||
if upscale_options is not None and swapped > 0:
|
||||
result_image = upscale_image(result_image, upscale_options)
|
||||
|
||||
if enhancement_options is not None and swapped > 0:
|
||||
result_image = enhance_image(result_image, enhancement_options)
|
||||
|
||||
else:
|
||||
logger.info("No source face(s) found")
|
||||
return result_image
|
||||
|
||||
return result_image, output, swapped
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
app_title = "ReActor"
|
||||
version_flag = "v0.4.1"
|
||||
version_flag = "v0.4.2-b1"
|
||||
|
||||
from scripts.reactor_logger import logger, get_Run, set_Run
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user