Added Multi Face
Added ability to upload multiple source face files and have it apply them all to each diffused image
This commit is contained in:
parent
de84e022ee
commit
0f7f73d47f
@ -1,5 +1,6 @@
|
|||||||
import os, glob
|
import os, glob
|
||||||
import gradio as gr
|
import gradio as gr
|
||||||
|
import tempfile
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
try:
|
try:
|
||||||
import torch.cuda as cuda
|
import torch.cuda as cuda
|
||||||
@ -8,7 +9,7 @@ except:
|
|||||||
EP_is_visible = False
|
EP_is_visible = False
|
||||||
|
|
||||||
from typing import List
|
from typing import List
|
||||||
|
from PIL import Image
|
||||||
import modules.scripts as scripts
|
import modules.scripts as scripts
|
||||||
from modules.upscaler import Upscaler, UpscalerData
|
from modules.upscaler import Upscaler, UpscalerData
|
||||||
from modules import scripts, shared, images, scripts_postprocessing
|
from modules import scripts, shared, images, scripts_postprocessing
|
||||||
@ -65,6 +66,7 @@ class FaceSwapScript(scripts.Script):
|
|||||||
with gr.Tab("Main"):
|
with gr.Tab("Main"):
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
img = gr.Image(type="pil")
|
img = gr.Image(type="pil")
|
||||||
|
face_files = gr.File(label="Multiple Source Face Files",file_count="multiple",file_types=["image"],info="Upload multiple face files and each file will be processed in post processing")
|
||||||
enable = gr.Checkbox(False, label="Enable", info=f"The Fast and Simple FaceSwap Extension - {version_flag}")
|
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")
|
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")
|
||||||
mask_face = gr.Checkbox(False, label="Mask Faces", info="Attempt to mask only the faces and eliminate pixelation of the image around the contours. Additional settings in the Masking tab.")
|
mask_face = gr.Checkbox(False, label="Mask Faces", info="Attempt to mask only the faces and eliminate pixelation of the image around the contours. Additional settings in the Masking tab.")
|
||||||
@ -143,13 +145,16 @@ class FaceSwapScript(scripts.Script):
|
|||||||
)
|
)
|
||||||
with gr.Tab("Masking"):
|
with gr.Tab("Masking"):
|
||||||
save_face_mask = gr.Checkbox(False, label="Save Face Mask", info="Save the face mask as a separate image with alpha transparency.")
|
save_face_mask = gr.Checkbox(False, label="Save Face Mask", info="Save the face mask as a separate image with alpha transparency.")
|
||||||
|
use_minimal_area = gr.Checkbox(MaskOption.DEFAULT_USE_MINIMAL_AREA, label="Use Minimal Area", info="Use the least amount of area for the mask as possible. This is good for multiple faces that are close together or for preserving the most of the surrounding image.")
|
||||||
|
|
||||||
mask_areas = gr.CheckboxGroup(
|
mask_areas = gr.CheckboxGroup(
|
||||||
label="Mask areas", choices=["Face", "Hair", "Hat", "Neck"], type="value", value= MaskOption.DEFAULT_FACE_AREAS
|
label="Mask areas", choices=["Face", "Hair", "Hat", "Neck"], type="value", value= MaskOption.DEFAULT_FACE_AREAS
|
||||||
)
|
)
|
||||||
mask_blur = gr.Slider(label="Mask blur ", minimum=0, maximum=64, step=1, value=MaskOption.DEFAULT_MASK_BLUR,info="The number of pixels from the outer edge of the mask to blur.")
|
|
||||||
face_size = gr.Radio(
|
face_size = gr.Radio(
|
||||||
label = "Face Size", choices = [512,256,128],value=MaskOption.DEFAULT_FACE_SIZE,type="value", info="Size of the masked area. Use larger numbers if the face is expected to be large, smaller if small. Default is 512."
|
label = "Face Size", choices = [512,256,128],value=MaskOption.DEFAULT_FACE_SIZE,type="value", info="Size of the masked area. Use larger numbers if the face is expected to be large, smaller if small. Default is 512."
|
||||||
)
|
)
|
||||||
|
mask_blur = gr.Slider(label="Mask blur", minimum=0, maximum=64, step=1, value=12,info="The number of pixels from the outer edge of the mask to blur.")
|
||||||
|
|
||||||
mask_vignette_fallback_threshold = gr.Slider(
|
mask_vignette_fallback_threshold = gr.Slider(
|
||||||
minimum=0.1,
|
minimum=0.1,
|
||||||
maximum=1.0,
|
maximum=1.0,
|
||||||
@ -158,7 +163,6 @@ class FaceSwapScript(scripts.Script):
|
|||||||
label="Vignette fallback threshold",
|
label="Vignette fallback threshold",
|
||||||
info="Switch to a rectangular vignette mask when masked area is only this specified percentage of Face Size."
|
info="Switch to a rectangular vignette mask when masked area is only this specified percentage of Face Size."
|
||||||
)
|
)
|
||||||
use_minimal_area = gr.Checkbox(MaskOption.DEFAULT_USE_MINIMAL_AREA, label="Use Minimal Area", info="Use the least amount of area for the mask as possible. This is good for multiple faces that are close together or for preserving the most of the surrounding image.")
|
|
||||||
with gr.Tab("Settings"):
|
with gr.Tab("Settings"):
|
||||||
models = get_models()
|
models = get_models()
|
||||||
with gr.Row(visible=EP_is_visible):
|
with gr.Row(visible=EP_is_visible):
|
||||||
@ -239,7 +243,7 @@ class FaceSwapScript(scripts.Script):
|
|||||||
use_minimal_area,
|
use_minimal_area,
|
||||||
face_size,
|
face_size,
|
||||||
mask_vignette_fallback_threshold,
|
mask_vignette_fallback_threshold,
|
||||||
|
face_files
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -304,13 +308,13 @@ class FaceSwapScript(scripts.Script):
|
|||||||
target_hash_check,
|
target_hash_check,
|
||||||
device,
|
device,
|
||||||
mask_face,
|
mask_face,
|
||||||
save_face_mask,
|
save_face_mask:bool,
|
||||||
mask_areas,
|
mask_areas,
|
||||||
mask_blur,
|
mask_blur:int,
|
||||||
mask_use_minimal_area,
|
mask_use_minimal_area,
|
||||||
mask_face_size,
|
mask_face_size,
|
||||||
mask_vignette_fallback_threshold,
|
mask_vignette_fallback_threshold,
|
||||||
|
face_files
|
||||||
):
|
):
|
||||||
self.enable = enable
|
self.enable = enable
|
||||||
if self.enable:
|
if self.enable:
|
||||||
@ -320,6 +324,7 @@ class FaceSwapScript(scripts.Script):
|
|||||||
return
|
return
|
||||||
|
|
||||||
global MODELS_PATH
|
global MODELS_PATH
|
||||||
|
|
||||||
self.source = img
|
self.source = img
|
||||||
self.face_restorer_name = face_restorer_name
|
self.face_restorer_name = face_restorer_name
|
||||||
self.upscaler_scale = upscaler_scale
|
self.upscaler_scale = upscaler_scale
|
||||||
@ -345,6 +350,7 @@ class FaceSwapScript(scripts.Script):
|
|||||||
self.mask_face_size = mask_face_size
|
self.mask_face_size = mask_face_size
|
||||||
self.mask_vignette_fallback_threshold = mask_vignette_fallback_threshold
|
self.mask_vignette_fallback_threshold = mask_vignette_fallback_threshold
|
||||||
self.mask_use_minimal_area = mask_use_minimal_area
|
self.mask_use_minimal_area = mask_use_minimal_area
|
||||||
|
self.face_files = face_files
|
||||||
if self.gender_source is None or self.gender_source == "No":
|
if self.gender_source is None or self.gender_source == "No":
|
||||||
self.gender_source = 0
|
self.gender_source = 0
|
||||||
if self.gender_target is None or self.gender_target == "No":
|
if self.gender_target is None or self.gender_target == "No":
|
||||||
@ -367,9 +373,9 @@ class FaceSwapScript(scripts.Script):
|
|||||||
self.target_hash_check = False
|
self.target_hash_check = False
|
||||||
|
|
||||||
set_Device(self.device)
|
set_Device(self.device)
|
||||||
logger.status(f"Self: {self}")
|
|
||||||
if self.source is not None:
|
|
||||||
apply_logging_patch(console_logging_level)
|
apply_logging_patch(console_logging_level)
|
||||||
|
if self.source is not None:
|
||||||
|
|
||||||
|
|
||||||
if isinstance(p, StableDiffusionProcessingImg2Img) and self.swap_in_source:
|
if isinstance(p, StableDiffusionProcessingImg2Img) and self.swap_in_source:
|
||||||
logger.status("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index)
|
logger.status("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index)
|
||||||
@ -401,7 +407,7 @@ class FaceSwapScript(scripts.Script):
|
|||||||
if shared.state.interrupted or shared.state.skipped:
|
if shared.state.interrupted or shared.state.skipped:
|
||||||
return
|
return
|
||||||
|
|
||||||
else:
|
elif self.face_files is None or len(self.face_files) == 0:
|
||||||
logger.error("Please provide a source face")
|
logger.error("Please provide a source face")
|
||||||
|
|
||||||
def postprocess(self, p: StableDiffusionProcessing, processed: Processed, *args):
|
def postprocess(self, p: StableDiffusionProcessing, processed: Processed, *args):
|
||||||
@ -410,13 +416,14 @@ class FaceSwapScript(scripts.Script):
|
|||||||
reset_messaged()
|
reset_messaged()
|
||||||
if check_process_halt():
|
if check_process_halt():
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.save_original:
|
|
||||||
|
|
||||||
postprocess_run: bool = True
|
postprocess_run: bool = True
|
||||||
|
|
||||||
orig_images : List[Image.Image] = processed.images[processed.index_of_first_image:]
|
orig_images : List[Image.Image] = processed.images[processed.index_of_first_image:]
|
||||||
orig_infotexts : List[str] = processed.infotexts[processed.index_of_first_image:]
|
orig_infotexts : List[str] = processed.infotexts[processed.index_of_first_image:]
|
||||||
|
result_images:List[Image.Image] = []
|
||||||
|
|
||||||
|
|
||||||
|
if self.save_original:
|
||||||
|
|
||||||
result_images: List = processed.images
|
result_images: List = processed.images
|
||||||
# result_info: List = processed.infotexts
|
# result_info: List = processed.infotexts
|
||||||
@ -469,7 +476,48 @@ class FaceSwapScript(scripts.Script):
|
|||||||
# fullfn = split_fullfn[0] + ".txt"
|
# fullfn = split_fullfn[0] + ".txt"
|
||||||
# with open(fullfn, 'w', encoding="utf8") as f:
|
# with open(fullfn, 'w', encoding="utf8") as f:
|
||||||
# f.writelines(output)
|
# f.writelines(output)
|
||||||
|
if self.face_files is not None and len(self.face_files) > 0:
|
||||||
|
|
||||||
|
for i,(img,info) in enumerate(zip(orig_images, orig_infotexts)):
|
||||||
|
for j,f_img in enumerate(self.face_files):
|
||||||
|
|
||||||
|
if check_process_halt():
|
||||||
|
postprocess_run = False
|
||||||
|
break
|
||||||
|
if len(self.face_files) > 1:
|
||||||
|
logger.status("Swap in face file #%s", j+1)
|
||||||
|
result, output, swapped, masked_faces = swap_face(
|
||||||
|
Image.open(os.path.abspath(f_img.name)),
|
||||||
|
img,
|
||||||
|
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,
|
||||||
|
device=self.device,
|
||||||
|
mask_face=self.mask_face,
|
||||||
|
mask_options=self.mask_options
|
||||||
|
)
|
||||||
|
if result is not None and swapped > 0:
|
||||||
|
result_images.append(result)
|
||||||
|
suffix = f"-swapped-ff-{j+1}"
|
||||||
|
try:
|
||||||
|
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)")
|
||||||
|
if self.mask_face and self.save_face_mask and masked_faces is not None:
|
||||||
|
result_images.append(masked_faces)
|
||||||
|
suffix = f"-mask-ff-{j+1}"
|
||||||
|
try:
|
||||||
|
img_path = save_image(masked_faces, p.outpath_samples, "", p.all_seeds[0], p.all_prompts[0], "png",info=info, p=p, suffix=suffix)
|
||||||
|
except:
|
||||||
|
logger.error("Cannot save a Masked Face image - please, check SD WebUI Settings (Saving and Paths)")
|
||||||
|
|
||||||
|
elif result is None:
|
||||||
|
logger.error("Cannot create a result image")
|
||||||
if shared.opts.return_grid and len(result_images) > 2 and postprocess_run:
|
if shared.opts.return_grid and len(result_images) > 2 and postprocess_run:
|
||||||
grid = make_grid(result_images)
|
grid = make_grid(result_images)
|
||||||
result_images.insert(0, grid)
|
result_images.insert(0, grid)
|
||||||
@ -480,13 +528,62 @@ class FaceSwapScript(scripts.Script):
|
|||||||
|
|
||||||
processed.images = result_images
|
processed.images = result_images
|
||||||
# processed.infotexts = result_info
|
# processed.infotexts = result_info
|
||||||
|
elif self.face_files is not None and len(self.face_files) > 0:
|
||||||
|
for i,(img,info) in enumerate(zip(orig_images, orig_infotexts)):
|
||||||
|
for j,f_img in enumerate(self.face_files):
|
||||||
|
|
||||||
|
if check_process_halt():
|
||||||
|
postprocess_run = False
|
||||||
|
break
|
||||||
|
if len(self.face_files) > 1:
|
||||||
|
logger.status("Swap in face file #%s", j+1)
|
||||||
|
result, output, swapped, masked_faces = swap_face(
|
||||||
|
Image.open(os.path.abspath(f_img.name)),
|
||||||
|
img,
|
||||||
|
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,
|
||||||
|
device=self.device,
|
||||||
|
mask_face=self.mask_face,
|
||||||
|
mask_options=self.mask_options
|
||||||
|
)
|
||||||
|
if result is not None and swapped > 0:
|
||||||
|
result_images.append(result)
|
||||||
|
suffix = f"-swapped-ff-{j+1}"
|
||||||
|
try:
|
||||||
|
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)")
|
||||||
|
if self.mask_face and self.save_face_mask and masked_faces is not None:
|
||||||
|
result_images.append(masked_faces)
|
||||||
|
suffix = f"-mask-ff-{j+1}"
|
||||||
|
try:
|
||||||
|
img_path = save_image(masked_faces, p.outpath_samples, "", p.all_seeds[0], p.all_prompts[0], "png",info=info, p=p, suffix=suffix)
|
||||||
|
except:
|
||||||
|
logger.error("Cannot save a Masked Face image - please, check SD WebUI Settings (Saving and Paths)")
|
||||||
|
|
||||||
|
elif result is None:
|
||||||
|
logger.error("Cannot create a result image")
|
||||||
|
if shared.opts.return_grid and len(result_images) > 2 and postprocess_run:
|
||||||
|
grid = make_grid(result_images)
|
||||||
|
result_images.insert(0, grid)
|
||||||
|
try:
|
||||||
|
save_image(grid, p.outpath_grids, "grid", p.all_seeds[0], p.all_prompts[0], shared.opts.grid_format, info=info, short_filename=not shared.opts.grid_extended_filename, p=p, grid=True)
|
||||||
|
except:
|
||||||
|
logger.error("Cannot save a grid - please, check SD WebUI Settings (Saving and Paths)")
|
||||||
|
|
||||||
|
processed.images = result_images
|
||||||
def postprocess_batch(self, p, *args, **kwargs):
|
def postprocess_batch(self, p, *args, **kwargs):
|
||||||
if self.enable and not self.save_original:
|
if self.enable and not self.save_original:
|
||||||
images = kwargs["images"]
|
images = kwargs["images"]
|
||||||
|
|
||||||
def postprocess_image(self, p, script_pp: scripts.PostprocessImageArgs, *args):
|
def postprocess_image(self, p, script_pp: scripts.PostprocessImageArgs, *args):
|
||||||
if self.enable and self.swap_in_generated and not self.save_original:
|
if self.enable and self.swap_in_generated and not ( self.save_original or ( self.face_files is not None and len(self.face_files) > 0)):
|
||||||
|
|
||||||
current_job_number = shared.state.job_no + 1
|
current_job_number = shared.state.job_no + 1
|
||||||
job_count = shared.state.job_count
|
job_count = shared.state.job_count
|
||||||
@ -498,7 +595,7 @@ class FaceSwapScript(scripts.Script):
|
|||||||
if self.source is not None:
|
if self.source is not None:
|
||||||
logger.status("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index)
|
logger.status("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index)
|
||||||
image: Image.Image = script_pp.image
|
image: Image.Image = script_pp.image
|
||||||
result, output, swapped = swap_face(
|
result, output, swapped, masked_faces = swap_face(
|
||||||
self.source,
|
self.source,
|
||||||
image,
|
image,
|
||||||
source_faces_index=self.source_faces_index,
|
source_faces_index=self.source_faces_index,
|
||||||
@ -510,7 +607,8 @@ class FaceSwapScript(scripts.Script):
|
|||||||
source_hash_check=self.source_hash_check,
|
source_hash_check=self.source_hash_check,
|
||||||
target_hash_check=self.target_hash_check,
|
target_hash_check=self.target_hash_check,
|
||||||
device=self.device,
|
device=self.device,
|
||||||
mask_face=self.mask_face
|
mask_face=self.mask_face,
|
||||||
|
mask_options=self.mask_options
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
pp = scripts_postprocessing.PostprocessedImage(result)
|
pp = scripts_postprocessing.PostprocessedImage(result)
|
||||||
@ -536,9 +634,9 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
|
|||||||
with gr.Tab("Main"):
|
with gr.Tab("Main"):
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
img = gr.Image(type="pil")
|
img = gr.Image(type="pil")
|
||||||
|
face_files = gr.File(file_count="multiple",file_types=["image"],info="Upload multiple face files and each file will be processed in post processing")
|
||||||
enable = gr.Checkbox(False, label="Enable", info=f"The Fast and Simple FaceSwap Extension - {version_flag}")
|
enable = gr.Checkbox(False, label="Enable", info=f"The Fast and Simple FaceSwap Extension - {version_flag}")
|
||||||
mask_face = gr.Checkbox(False, label="Mask Faces", info="Attempt to mask only the faces and eliminate pixelation of the image around the contours. Additional settings in the Masking tab.")
|
mask_face = gr.Checkbox(False, label="Mask Faces", info="Attempt to mask only the faces and eliminate pixelation of the image around the contours. Additional settings in the Masking tab.")
|
||||||
|
|
||||||
gr.Markdown("Source Image (above):")
|
gr.Markdown("Source Image (above):")
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
source_faces_index = gr.Textbox(
|
source_faces_index = gr.Textbox(
|
||||||
@ -599,13 +697,16 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
|
|||||||
)
|
)
|
||||||
with gr.Tab("Masking"):
|
with gr.Tab("Masking"):
|
||||||
save_face_mask = gr.Checkbox(False, label="Save Face Mask", info="Save the face mask as a separate image with alpha transparency.")
|
save_face_mask = gr.Checkbox(False, label="Save Face Mask", info="Save the face mask as a separate image with alpha transparency.")
|
||||||
|
use_minimal_area = gr.Checkbox(MaskOption.DEFAULT_USE_MINIMAL_AREA, label="Use Minimal Area", info="Use the least amount of area for the mask as possible. This is good for multiple faces that are close together or for preserving the most of the surrounding image.")
|
||||||
|
|
||||||
mask_areas = gr.CheckboxGroup(
|
mask_areas = gr.CheckboxGroup(
|
||||||
label="Mask areas", choices=["Face", "Hair", "Hat", "Neck"], type="value", value= MaskOption.DEFAULT_FACE_AREAS
|
label="Mask areas", choices=["Face", "Hair", "Hat", "Neck"], type="value", value= MaskOption.DEFAULT_FACE_AREAS
|
||||||
)
|
)
|
||||||
mask_blur = gr.Slider(label="Mask blur ", minimum=0, maximum=64, step=1, value=MaskOption.DEFAULT_MASK_BLUR,info="The number of pixels from the outer edge of the mask to blur.")
|
|
||||||
face_size = gr.Radio(
|
face_size = gr.Radio(
|
||||||
label = "Face Size", choices = [512,256,128],value=MaskOption.DEFAULT_FACE_SIZE,type="value", info="Size of the masked area. Use larger numbers if the face is expected to be large, smaller if small. Default is 512."
|
label = "Face Size", choices = [512,256,128],value=MaskOption.DEFAULT_FACE_SIZE,type="value", info="Size of the masked area. Use larger numbers if the face is expected to be large, smaller if small. Default is 512."
|
||||||
)
|
)
|
||||||
|
mask_blur = gr.Slider(label="Mask blur", minimum=0, maximum=64, step=1, value=12,info="The number of pixels from the outer edge of the mask to blur.")
|
||||||
|
|
||||||
mask_vignette_fallback_threshold = gr.Slider(
|
mask_vignette_fallback_threshold = gr.Slider(
|
||||||
minimum=0.1,
|
minimum=0.1,
|
||||||
maximum=1.0,
|
maximum=1.0,
|
||||||
@ -614,7 +715,6 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
|
|||||||
label="Vignette fallback threshold",
|
label="Vignette fallback threshold",
|
||||||
info="Switch to a rectangular vignette mask when masked area is only this specified percentage of Face Size."
|
info="Switch to a rectangular vignette mask when masked area is only this specified percentage of Face Size."
|
||||||
)
|
)
|
||||||
use_minimal_area = gr.Checkbox(MaskOption.DEFAULT_USE_MINIMAL_AREA, label="Use Minimal Area", info="Use the least amount of area for the mask as possible. This is good for multiple faces that are close together or for preserving the most of the surrounding image.")
|
|
||||||
|
|
||||||
with gr.Tab("Settings"):
|
with gr.Tab("Settings"):
|
||||||
models = get_models()
|
models = get_models()
|
||||||
@ -679,6 +779,7 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
|
|||||||
'mask_vignette_fallback_threshold':mask_vignette_fallback_threshold,
|
'mask_vignette_fallback_threshold':mask_vignette_fallback_threshold,
|
||||||
'face_size':face_size,
|
'face_size':face_size,
|
||||||
'use_minimal_area':use_minimal_area,
|
'use_minimal_area':use_minimal_area,
|
||||||
|
'face_files':face_files
|
||||||
}
|
}
|
||||||
return args
|
return args
|
||||||
|
|
||||||
@ -713,9 +814,9 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
|
|||||||
mask_areas = self.mask_areas,
|
mask_areas = self.mask_areas,
|
||||||
save_face_mask = self.save_face_mask,
|
save_face_mask = self.save_face_mask,
|
||||||
mask_blur = self.mask_blur,
|
mask_blur = self.mask_blur,
|
||||||
face_size = self.mask_face_size,
|
face_size = self.face_size,
|
||||||
vignette_fallback_threshold = self.mask_vignette_fallback_threshold,
|
vignette_fallback_threshold = self.mask_vignette_fallback_threshold,
|
||||||
use_minimal_area = self.mask_use_minimal_area,
|
use_minimal_area = self.use_minimal_area,
|
||||||
)
|
)
|
||||||
def process(self, pp: scripts_postprocessing.PostprocessedImage, **args):
|
def process(self, pp: scripts_postprocessing.PostprocessedImage, **args):
|
||||||
if args['enable']:
|
if args['enable']:
|
||||||
@ -723,6 +824,7 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
|
|||||||
if check_process_halt():
|
if check_process_halt():
|
||||||
return
|
return
|
||||||
global MODELS_PATH
|
global MODELS_PATH
|
||||||
|
|
||||||
self.source = args['img']
|
self.source = args['img']
|
||||||
self.face_restorer_name = args['face_restorer_name']
|
self.face_restorer_name = args['face_restorer_name']
|
||||||
self.upscaler_scale = args['upscaler_scale']
|
self.upscaler_scale = args['upscaler_scale']
|
||||||
@ -743,6 +845,7 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
|
|||||||
self.mask_vignette_fallback_threshold= args['mask_vignette_fallback_threshold']
|
self.mask_vignette_fallback_threshold= args['mask_vignette_fallback_threshold']
|
||||||
self.face_size= args['face_size']
|
self.face_size= args['face_size']
|
||||||
self.use_minimal_area= args['use_minimal_area']
|
self.use_minimal_area= args['use_minimal_area']
|
||||||
|
self.face_files = args['face_files']
|
||||||
if self.gender_source is None or self.gender_source == "No":
|
if self.gender_source is None or self.gender_source == "No":
|
||||||
self.gender_source = 0
|
self.gender_source = 0
|
||||||
if self.gender_target is None or self.gender_target == "No":
|
if self.gender_target is None or self.gender_target == "No":
|
||||||
@ -764,12 +867,12 @@ class FaceSwapScriptExtras(scripts_postprocessing.ScriptPostprocessing):
|
|||||||
reset_messaged()
|
reset_messaged()
|
||||||
|
|
||||||
set_Device(self.device)
|
set_Device(self.device)
|
||||||
|
|
||||||
if self.source is not None:
|
|
||||||
apply_logging_patch(self.console_logging_level)
|
apply_logging_patch(self.console_logging_level)
|
||||||
|
if self.source is not None:
|
||||||
|
|
||||||
logger.status("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index)
|
logger.status("Working: source face index %s, target face index %s", self.source_faces_index, self.faces_index)
|
||||||
image: Image.Image = pp.image
|
image: Image.Image = pp.image
|
||||||
result, output, swapped = swap_face(
|
result, output, swapped,masked_faces = swap_face(
|
||||||
self.source,
|
self.source,
|
||||||
image,
|
image,
|
||||||
source_faces_index=self.source_faces_index,
|
source_faces_index=self.source_faces_index,
|
||||||
|
|||||||
@ -43,10 +43,10 @@ else:
|
|||||||
PROVIDERS = ["CPUExecutionProvider"]
|
PROVIDERS = ["CPUExecutionProvider"]
|
||||||
class MaskOption:
|
class MaskOption:
|
||||||
DEFAULT_FACE_AREAS = ["Face"]
|
DEFAULT_FACE_AREAS = ["Face"]
|
||||||
DEFAULT_FACE_SIZE = 512
|
DEFAULT_FACE_SIZE:int = 512
|
||||||
DEFAULT_VIGNETTE_THRESHOLD = 0.1
|
DEFAULT_VIGNETTE_THRESHOLD:float = 0.1
|
||||||
DEFAULT_MASK_BLUR = 12,
|
DEFAULT_MASK_BLUR:int = 12,
|
||||||
DEFAULT_USE_MINIMAL_AREA = True
|
DEFAULT_USE_MINIMAL_AREA:bool = True
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class EnhancementOptions:
|
class EnhancementOptions:
|
||||||
@ -336,7 +336,7 @@ def swap_face(
|
|||||||
):
|
):
|
||||||
global SOURCE_FACES, SOURCE_IMAGE_HASH, TARGET_FACES, TARGET_IMAGE_HASH, PROVIDERS
|
global SOURCE_FACES, SOURCE_IMAGE_HASH, TARGET_FACES, TARGET_IMAGE_HASH, PROVIDERS
|
||||||
result_image = target_img
|
result_image = target_img
|
||||||
|
masked_faces = None
|
||||||
PROVIDERS = ["CUDAExecutionProvider"] if device == "CUDA" else ["CPUExecutionProvider"]
|
PROVIDERS = ["CUDAExecutionProvider"] if device == "CUDA" else ["CPUExecutionProvider"]
|
||||||
|
|
||||||
if check_process_halt():
|
if check_process_halt():
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user