add pre-commit hooks configuration

This commit is contained in:
Tran Xen
2023-07-28 18:25:28 +02:00
parent 8577d0186d
commit 5d4a29ff1e
33 changed files with 1674 additions and 820 deletions
+219 -108
View File
@@ -13,20 +13,23 @@ from scripts.faceswaplab_ui.faceswaplab_upscaler_ui import upscaler_ui
from insightface.app.common import Face
from modules import script_callbacks, scripts
from PIL import Image
from modules.shared import opts
from modules.shared import opts
from scripts.faceswaplab_utils import imgutils
from scripts.faceswaplab_utils.imgutils import pil_to_cv2
from scripts.faceswaplab_utils.models_utils import get_models
from scripts.faceswaplab_utils.faceswaplab_logging import logger
import scripts.faceswaplab_swapping.swapper as swapper
from scripts.faceswaplab_postprocessing.postprocessing_options import PostProcessingOptions
from scripts.faceswaplab_postprocessing.postprocessing_options import (
PostProcessingOptions,
)
from scripts.faceswaplab_postprocessing.postprocessing import enhance_image
from dataclasses import fields
from typing import List
from scripts.faceswaplab_ui.faceswaplab_unit_settings import FaceSwapUnitSettings
from scripts.faceswaplab_utils.models_utils import get_current_model
def compare(img1, img2):
if img1 is not None and img2 is not None:
return swapper.compare_faces(img1, img2)
@@ -34,13 +37,27 @@ def compare(img1, img2):
return "You need 2 images to compare"
def extract_faces(files, extract_path, face_restorer_name, face_restorer_visibility, codeformer_weight,upscaler_name,upscaler_scale, upscaler_visibility,inpainting_denoising_strengh, inpainting_prompt, inpainting_negative_prompt, inpainting_steps, inpainting_sampler,inpainting_when):
if not extract_path :
def extract_faces(
files,
extract_path,
face_restorer_name,
face_restorer_visibility,
codeformer_weight,
upscaler_name,
upscaler_scale,
upscaler_visibility,
inpainting_denoising_strengh,
inpainting_prompt,
inpainting_negative_prompt,
inpainting_steps,
inpainting_sampler,
inpainting_when,
):
if not extract_path:
tempfile.mkdtemp()
if files is not None:
images = []
for file in files :
for file in files:
img = Image.open(file.name).convert("RGB")
faces = swapper.get_faces(pil_to_cv2(img))
if faces:
@@ -50,40 +67,49 @@ def extract_faces(files, extract_path, face_restorer_name, face_restorer_visibi
x_min, y_min, x_max, y_max = bbox
face_image = img.crop((x_min, y_min, x_max, y_max))
if face_restorer_name or face_restorer_visibility:
scale = 1 if face_image.width > 512 else 512//face_image.width
face_image = enhance_image(face_image, PostProcessingOptions(face_restorer_name=face_restorer_name,
restorer_visibility=face_restorer_visibility,
codeformer_weight= codeformer_weight,
upscaler_name=upscaler_name,
upscale_visibility=upscaler_visibility,
scale=scale,
inpainting_denoising_strengh=inpainting_denoising_strengh,
inpainting_prompt=inpainting_prompt,
inpainting_steps=inpainting_steps,
inpainting_negative_prompt=inpainting_negative_prompt,
inpainting_when=inpainting_when,
inpainting_sampler=inpainting_sampler))
path = tempfile.NamedTemporaryFile(delete=False,suffix=".png",dir=extract_path).name
scale = 1 if face_image.width > 512 else 512 // face_image.width
face_image = enhance_image(
face_image,
PostProcessingOptions(
face_restorer_name=face_restorer_name,
restorer_visibility=face_restorer_visibility,
codeformer_weight=codeformer_weight,
upscaler_name=upscaler_name,
upscale_visibility=upscaler_visibility,
scale=scale,
inpainting_denoising_strengh=inpainting_denoising_strengh,
inpainting_prompt=inpainting_prompt,
inpainting_steps=inpainting_steps,
inpainting_negative_prompt=inpainting_negative_prompt,
inpainting_when=inpainting_when,
inpainting_sampler=inpainting_sampler,
),
)
path = tempfile.NamedTemporaryFile(
delete=False, suffix=".png", dir=extract_path
).name
face_image.save(path)
face_images.append(path)
images+= face_images
images += face_images
return images
return None
def analyse_faces(image, det_threshold = 0.5) :
try :
def analyse_faces(image, det_threshold=0.5):
try:
faces = swapper.get_faces(imgutils.pil_to_cv2(image), det_thresh=det_threshold)
result = ""
for i,face in enumerate(faces) :
result+= f"\nFace {i} \n" + "="*40 +"\n"
result+= pformat(face) + "\n"
result+= "="*40
for i, face in enumerate(faces):
result += f"\nFace {i} \n" + "=" * 40 + "\n"
result += pformat(face) + "\n"
result += "=" * 40
return result
except Exception as e :
except Exception as e:
logger.error("Analysis Failed : %s", e)
return "Analysis Failed"
def build_face_checkpoint_and_save(batch_files, name):
"""
Builds a face checkpoint, swaps faces, and saves the result to a file.
@@ -102,7 +128,7 @@ def build_face_checkpoint_and_save(batch_files, name):
preview_path = os.path.join(
scripts.basedir(), "extensions", "sd-webui-faceswaplab", "references"
)
faces_path = os.path.join(scripts.basedir(), "models", "faceswaplab","faces")
faces_path = os.path.join(scripts.basedir(), "models", "faceswaplab", "faces")
if not os.path.exists(faces_path):
os.makedirs(faces_path)
@@ -116,22 +142,36 @@ def build_face_checkpoint_and_save(batch_files, name):
if name == "":
name = "default_name"
pprint(blended_face)
result = swapper.swap_face(blended_face, blended_face, target_img, get_models()[0])
result_image = enhance_image(result.image, PostProcessingOptions(face_restorer_name="CodeFormer", restorer_visibility=1))
result = swapper.swap_face(
blended_face, blended_face, target_img, get_models()[0]
)
result_image = enhance_image(
result.image,
PostProcessingOptions(
face_restorer_name="CodeFormer", restorer_visibility=1
),
)
file_path = os.path.join(faces_path, f"{name}.pkl")
file_number = 1
while os.path.exists(file_path):
file_path = os.path.join(faces_path, f"{name}_{file_number}.pkl")
file_number += 1
result_image.save(file_path+".png")
result_image.save(file_path + ".png")
with open(file_path, "wb") as file:
pickle.dump({"embedding" :blended_face.embedding, "gender" :blended_face.gender, "age" :blended_face.age},file)
try :
pickle.dump(
{
"embedding": blended_face.embedding,
"gender": blended_face.gender,
"age": blended_face.age,
},
file,
)
try:
with open(file_path, "rb") as file:
data = Face(pickle.load(file))
print(data)
except Exception as e :
except Exception as e:
print(e)
return result_image
@@ -139,48 +179,52 @@ def build_face_checkpoint_and_save(batch_files, name):
return target_img
def explore_onnx_faceswap_model(model_path):
data = {
'Node Name': [],
'Op Type': [],
'Inputs': [],
'Outputs': [],
'Attributes': []
"Node Name": [],
"Op Type": [],
"Inputs": [],
"Outputs": [],
"Attributes": [],
}
if model_path:
model = onnx.load(model_path)
for node in model.graph.node:
data['Node Name'].append(pformat(node.name))
data['Op Type'].append(pformat(node.op_type))
data['Inputs'].append(pformat(node.input))
data['Outputs'].append(pformat(node.output))
data["Node Name"].append(pformat(node.name))
data["Op Type"].append(pformat(node.op_type))
data["Inputs"].append(pformat(node.input))
data["Outputs"].append(pformat(node.output))
attributes = []
for attr in node.attribute:
attr_name = attr.name
attr_value = attr.t
attributes.append("{} = {}".format(pformat(attr_name), pformat(attr_value)))
data['Attributes'].append(attributes)
attributes.append(
"{} = {}".format(pformat(attr_name), pformat(attr_value))
)
data["Attributes"].append(attributes)
df = pd.DataFrame(data)
return df
def batch_process(files, save_path, *components):
try :
def batch_process(files, save_path, *components):
try:
if save_path is not None:
os.makedirs(save_path, exist_ok=True)
units_count = opts.data.get("faceswaplab_units_count", 3)
units: List[FaceSwapUnitSettings] = []
#Parse and convert units flat components into FaceSwapUnitSettings
# Parse and convert units flat components into FaceSwapUnitSettings
for i in range(0, units_count):
units += [FaceSwapUnitSettings.get_unit_configuration(i, components)]
units += [FaceSwapUnitSettings.get_unit_configuration(i, components)]
for i, u in enumerate(units):
logger.debug("%s, %s", pformat(i), pformat(u))
#Parse the postprocessing options
#We must first find where to start from (after face swapping units)
# Parse the postprocessing options
# We must first find where to start from (after face swapping units)
len_conf: int = len(fields(FaceSwapUnitSettings))
shift: int = units_count * len_conf
postprocess_options = PostProcessingOptions(
@@ -191,26 +235,36 @@ def batch_process(files, save_path, *components):
units = [u for u in units if u.enable]
if files is not None:
images = []
for file in files :
for file in files:
current_images = []
src_image = Image.open(file.name).convert("RGB")
swapped_images = swapper.process_images_units(get_current_model(), images=[(src_image,None)], units=units, upscaled_swapper=opts.data.get("faceswaplab_upscaled_swapper", False))
swapped_images = swapper.process_images_units(
get_current_model(),
images=[(src_image, None)],
units=units,
upscaled_swapper=opts.data.get(
"faceswaplab_upscaled_swapper", False
),
)
if len(swapped_images) > 0:
current_images+= [img for img,info in swapped_images]
current_images += [img for img, info in swapped_images]
logger.info("%s images generated", len(current_images))
for i, img in enumerate(current_images) :
current_images[i] = enhance_image(img,postprocess_options)
for i, img in enumerate(current_images):
current_images[i] = enhance_image(img, postprocess_options)
for img in current_images :
path = tempfile.NamedTemporaryFile(delete=False,suffix=".png",dir=save_path).name
for img in current_images:
path = tempfile.NamedTemporaryFile(
delete=False, suffix=".png", dir=save_path
).name
img.save(path)
images += current_images
return images
except Exception as e:
logger.error("Batch Process error : %s",e)
logger.error("Batch Process error : %s", e)
import traceback
traceback.print_exc()
return None
@@ -220,107 +274,164 @@ def tools_ui():
with gr.Tab("Tools"):
with gr.Tab("Build"):
gr.Markdown(
"""Build a face based on a batch list of images. Will blend the resulting face and store the checkpoint in the faceswaplab/faces directory.""")
"""Build a face based on a batch list of images. Will blend the resulting face and store the checkpoint in the faceswaplab/faces directory."""
)
with gr.Row():
batch_files = gr.components.File(
type="file",
file_count="multiple",
label="Batch Sources Images",
optional=True,
elem_id="faceswaplab_build_batch_files"
elem_id="faceswaplab_build_batch_files",
)
preview = gr.components.Image(
type="pil",
label="Preview",
interactive=False,
elem_id="faceswaplab_build_preview_face",
)
preview = gr.components.Image(type="pil", label="Preview", interactive=False, elem_id="faceswaplab_build_preview_face")
name = gr.Textbox(
value="Face",
placeholder="Name of the character",
label="Name of the character",
elem_id="faceswaplab_build_character_name"
elem_id="faceswaplab_build_character_name",
)
generate_checkpoint_btn = gr.Button(
"Save", elem_id="faceswaplab_build_save_btn"
)
generate_checkpoint_btn = gr.Button("Save",elem_id="faceswaplab_build_save_btn")
with gr.Tab("Compare"):
gr.Markdown(
"""Give a similarity score between two images (only first face is compared).""")
"""Give a similarity score between two images (only first face is compared)."""
)
with gr.Row():
img1 = gr.components.Image(type="pil",
label="Face 1",
elem_id="faceswaplab_compare_face1"
img1 = gr.components.Image(
type="pil", label="Face 1", elem_id="faceswaplab_compare_face1"
)
img2 = gr.components.Image(type="pil",
label="Face 2",
elem_id="faceswaplab_compare_face2"
img2 = gr.components.Image(
type="pil", label="Face 2", elem_id="faceswaplab_compare_face2"
)
compare_btn = gr.Button("Compare",elem_id="faceswaplab_compare_btn")
compare_btn = gr.Button("Compare", elem_id="faceswaplab_compare_btn")
compare_result_text = gr.Textbox(
interactive=False, label="Similarity", value="0", elem_id="faceswaplab_compare_result"
interactive=False,
label="Similarity",
value="0",
elem_id="faceswaplab_compare_result",
)
with gr.Tab("Extract"):
gr.Markdown(
"""Extract all faces from a batch of images. Will apply enhancement in the tools enhancement tab.""")
"""Extract all faces from a batch of images. Will apply enhancement in the tools enhancement tab."""
)
with gr.Row():
extracted_source_files = gr.components.File(
type="file",
file_count="multiple",
label="Batch Sources Images",
optional=True,
elem_id="faceswaplab_extract_batch_images"
elem_id="faceswaplab_extract_batch_images",
)
extracted_faces = gr.Gallery(
label="Extracted faces", show_label=False,
elem_id="faceswaplab_extract_results"
).style(columns=[2], rows=[2])
extract_save_path = gr.Textbox(label="Destination Directory", value="", elem_id="faceswaplab_extract_destination")
extracted_faces = gr.Gallery(
label="Extracted faces",
show_label=False,
elem_id="faceswaplab_extract_results",
).style(columns=[2], rows=[2])
extract_save_path = gr.Textbox(
label="Destination Directory",
value="",
elem_id="faceswaplab_extract_destination",
)
extract_btn = gr.Button("Extract", elem_id="faceswaplab_extract_btn")
with gr.Tab("Explore Model"):
model = gr.Dropdown(
choices=models,
label="Model not found, please download one and reload automatic 1111",
elem_id="faceswaplab_explore_model"
)
elem_id="faceswaplab_explore_model",
)
explore_btn = gr.Button("Explore", elem_id="faceswaplab_explore_btn")
explore_result_text = gr.Dataframe(
interactive=False, label="Explored",
elem_id="faceswaplab_explore_result"
interactive=False,
label="Explored",
elem_id="faceswaplab_explore_result",
)
with gr.Tab("Analyse Face"):
img_to_analyse = gr.components.Image(type="pil", label="Face", elem_id="faceswaplab_analyse_face")
analyse_det_threshold = gr.Slider(0.1, 1, 0.5, step=0.01, label="Detection threshold", elem_id="faceswaplab_analyse_det_threshold")
img_to_analyse = gr.components.Image(
type="pil", label="Face", elem_id="faceswaplab_analyse_face"
)
analyse_det_threshold = gr.Slider(
0.1,
1,
0.5,
step=0.01,
label="Detection threshold",
elem_id="faceswaplab_analyse_det_threshold",
)
analyse_btn = gr.Button("Analyse", elem_id="faceswaplab_analyse_btn")
analyse_results = gr.Textbox(label="Results", interactive=False, value="", elem_id="faceswaplab_analyse_results")
analyse_results = gr.Textbox(
label="Results",
interactive=False,
value="",
elem_id="faceswaplab_analyse_results",
)
with gr.Tab("Batch Process"):
with gr.Tab("Source Images"):
gr.Markdown(
"""Batch process images. Will apply enhancement in the tools enhancement tab.""")
"""Batch process images. Will apply enhancement in the tools enhancement tab."""
)
with gr.Row():
batch_source_files = gr.components.File(
type="file",
file_count="multiple",
label="Batch Sources Images",
optional=True,
elem_id="faceswaplab_batch_images"
elem_id="faceswaplab_batch_images",
)
batch_results = gr.Gallery(
label="Batch result", show_label=False,
elem_id="faceswaplab_batch_results"
).style(columns=[2], rows=[2])
batch_save_path = gr.Textbox(label="Destination Directory", value="outputs/faceswap/", elem_id="faceswaplab_batch_destination")
batch_save_btn= gr.Button("Process & Save", elem_id="faceswaplab_extract_btn")
batch_results = gr.Gallery(
label="Batch result",
show_label=False,
elem_id="faceswaplab_batch_results",
).style(columns=[2], rows=[2])
batch_save_path = gr.Textbox(
label="Destination Directory",
value="outputs/faceswap/",
elem_id="faceswaplab_batch_destination",
)
batch_save_btn = gr.Button(
"Process & Save", elem_id="faceswaplab_extract_btn"
)
unit_components = []
for i in range(1,opts.data.get("faceswaplab_units_count", 3)+1):
for i in range(1, opts.data.get("faceswaplab_units_count", 3) + 1):
unit_components += faceswap_unit_ui(False, i, id_prefix="faceswaplab_tab")
upscale_options = upscaler_ui()
explore_btn.click(explore_onnx_faceswap_model, inputs=[model], outputs=[explore_result_text])
explore_btn.click(
explore_onnx_faceswap_model, inputs=[model], outputs=[explore_result_text]
)
compare_btn.click(compare, inputs=[img1, img2], outputs=[compare_result_text])
generate_checkpoint_btn.click(build_face_checkpoint_and_save, inputs=[batch_files, name], outputs=[preview])
extract_btn.click(extract_faces, inputs=[extracted_source_files, extract_save_path]+upscale_options, outputs=[extracted_faces])
analyse_btn.click(analyse_faces, inputs=[img_to_analyse,analyse_det_threshold], outputs=[analyse_results])
batch_save_btn.click(batch_process, inputs=[batch_source_files, batch_save_path]+unit_components+upscale_options, outputs=[batch_results])
generate_checkpoint_btn.click(
build_face_checkpoint_and_save, inputs=[batch_files, name], outputs=[preview]
)
extract_btn.click(
extract_faces,
inputs=[extracted_source_files, extract_save_path] + upscale_options,
outputs=[extracted_faces],
)
analyse_btn.click(
analyse_faces,
inputs=[img_to_analyse, analyse_det_threshold],
outputs=[analyse_results],
)
batch_save_btn.click(
batch_process,
inputs=[batch_source_files, batch_save_path]
+ unit_components
+ upscale_options,
outputs=[batch_results],
)
def on_ui_tabs() :
def on_ui_tabs():
with gr.Blocks(analytics_enabled=False) as ui_faceswap:
tools_ui()
return [(ui_faceswap, "FaceSwapLab", "faceswaplab_tab")]
return [(ui_faceswap, "FaceSwapLab", "faceswaplab_tab")]
@@ -8,20 +8,20 @@ import dill as pickle
import gradio as gr
from insightface.app.common import Face
from PIL import Image
from scripts.faceswaplab_utils.imgutils import (pil_to_cv2,check_against_nsfw)
from scripts.faceswaplab_utils.imgutils import pil_to_cv2, check_against_nsfw
from scripts.faceswaplab_utils.faceswaplab_logging import logger
@dataclass
class FaceSwapUnitSettings:
# ORDER of parameters is IMPORTANT. It should match the result of faceswap_unit_ui
# The image given in reference
source_img: Union[Image.Image, str]
# The checkpoint file
source_face : str
source_face: str
# The batch source images
_batch_files: Union[gr.components.File,List[Image.Image]]
_batch_files: Union[gr.components.File, List[Image.Image]]
# Will blend faces if True
blend_faces: bool
# Enable this unit
@@ -29,11 +29,11 @@ class FaceSwapUnitSettings:
# Use same gender filtering
same_gender: bool
# Sort faces by their size (from larger to smaller)
sort_by_size : bool
sort_by_size: bool
# If True, discard images with low similarity
check_similarity : bool
check_similarity: bool
# if True will compute similarity and add it to the image info
_compute_similarity :bool
_compute_similarity: bool
# Minimum similarity against the used face (reference, batch or checkpoint)
min_sim: float
@@ -42,7 +42,7 @@ class FaceSwapUnitSettings:
# The face index to use for swapping
_faces_index: str
# The face index to get image from source
reference_face_index : int
reference_face_index: int
# Swap in the source image in img2img (before processing)
swap_in_source: bool
@@ -59,7 +59,7 @@ class FaceSwapUnitSettings:
@property
def faces_index(self):
"""
Convert _faces_index from str to int
Convert _faces_index from str to int
"""
faces_index = {
int(x) for x in self._faces_index.strip(",").split(",") if x.isnumeric()
@@ -72,7 +72,7 @@ class FaceSwapUnitSettings:
return faces_index
@property
def compute_similarity(self) :
def compute_similarity(self):
return self._compute_similarity or self.check_similarity
@property
@@ -81,59 +81,67 @@ class FaceSwapUnitSettings:
Return empty array instead of None for batch files
"""
return self._batch_files or []
@property
def reference_face(self) :
def reference_face(self):
"""
Extract reference face (only once and store it for the rest of processing).
Reference face is the checkpoint or the source image or the first image in the batch in that order.
"""
if not hasattr(self,"_reference_face") :
if self.source_face and self.source_face != "None" :
if not hasattr(self, "_reference_face"):
if self.source_face and self.source_face != "None":
with open(self.source_face, "rb") as file:
try :
try:
logger.info(f"loading pickle {file.name}")
face = Face(pickle.load(file))
self._reference_face = face
except Exception as e :
except Exception as e:
logger.error("Failed to load checkpoint : %s", e)
elif self.source_img is not None :
elif self.source_img is not None:
if isinstance(self.source_img, str): # source_img is a base64 string
if 'base64,' in self.source_img: # check if the base64 string has a data URL scheme
base64_data = self.source_img.split('base64,')[-1]
if (
"base64," in self.source_img
): # check if the base64 string has a data URL scheme
base64_data = self.source_img.split("base64,")[-1]
img_bytes = base64.b64decode(base64_data)
else:
# if no data URL scheme, just decode
img_bytes = base64.b64decode(self.source_img)
self.source_img = Image.open(io.BytesIO(img_bytes))
source_img = pil_to_cv2(self.source_img)
self._reference_face = swapper.get_or_default(swapper.get_faces(source_img), self.reference_face_index, None)
if self._reference_face is None :
logger.error("Face not found in reference image")
else :
self._reference_face = swapper.get_or_default(
swapper.get_faces(source_img), self.reference_face_index, None
)
if self._reference_face is None:
logger.error("Face not found in reference image")
else:
self._reference_face = None
if self._reference_face is None :
if self._reference_face is None:
logger.error("You need at least one reference face")
return self._reference_face
@property
def faces(self) :
def faces(self):
"""_summary_
Extract all faces (including reference face) to provide an array of faces
Only processed once.
"""
if self.batch_files is not None and not hasattr(self,"_faces") :
self._faces = [self.reference_face] if self.reference_face is not None else []
for file in self.batch_files :
if isinstance(file, Image.Image) :
if self.batch_files is not None and not hasattr(self, "_faces"):
self._faces = (
[self.reference_face] if self.reference_face is not None else []
)
for file in self.batch_files:
if isinstance(file, Image.Image):
img = file
else :
else:
img = Image.open(file.name)
face = swapper.get_or_default(swapper.get_faces(pil_to_cv2(img)), 0, None)
if face is not None :
face = swapper.get_or_default(
swapper.get_faces(pil_to_cv2(img)), 0, None
)
if face is not None:
self._faces.append(face)
return self._faces
@@ -142,11 +150,26 @@ class FaceSwapUnitSettings:
"""
Blend the faces using the mean of all embeddings
"""
if not hasattr(self,"_blended_faces") :
if not hasattr(self, "_blended_faces"):
self._blended_faces = swapper.blend_faces(self.faces)
assert(all([not np.array_equal(self._blended_faces.embedding, face.embedding) for face in self.faces]) if len(self.faces) > 1 else True), "Blended faces cannot be the same as one of the face if len(face)>0"
assert(not np.array_equal(self._blended_faces.embedding,self.reference_face.embedding) if len(self.faces) > 1 else True), "Blended faces cannot be the same as reference face if len(face)>0"
assert (
all(
[
not np.array_equal(
self._blended_faces.embedding, face.embedding
)
for face in self.faces
]
)
if len(self.faces) > 1
else True
), "Blended faces cannot be the same as one of the face if len(face)>0"
assert (
not np.array_equal(
self._blended_faces.embedding, self.reference_face.embedding
)
if len(self.faces) > 1
else True
), "Blended faces cannot be the same as reference face if len(face)>0"
return self._blended_faces
+83 -34
View File
@@ -1,94 +1,143 @@
from scripts.faceswaplab_utils.models_utils import get_face_checkpoints
import gradio as gr
def faceswap_unit_ui(is_img2img, unit_num=1, id_prefix="faceswaplab"):
with gr.Tab(f"Face {unit_num}"):
with gr.Column():
gr.Markdown(
"""Reference is an image. First face will be extracted.
First face of batches sources will be extracted and used as input (or blended if blend is activated).""")
"""Reference is an image. First face will be extracted.
First face of batches sources will be extracted and used as input (or blended if blend is activated)."""
)
with gr.Row():
img = gr.components.Image(type="pil", label="Reference", elem_id=f"{id_prefix}_face{unit_num}_reference_image")
img = gr.components.Image(
type="pil",
label="Reference",
elem_id=f"{id_prefix}_face{unit_num}_reference_image",
)
batch_files = gr.components.File(
type="file",
file_count="multiple",
label="Batch Sources Images",
optional=True,
elem_id=f"{id_prefix}_face{unit_num}_batch_source_face_files"
elem_id=f"{id_prefix}_face{unit_num}_batch_source_face_files",
)
gr.Markdown(
"""Face checkpoint built with the checkpoint builder in tools. Will overwrite reference image.""")
with gr.Row() :
"""Face checkpoint built with the checkpoint builder in tools. Will overwrite reference image."""
)
with gr.Row():
face = gr.Dropdown(
choices=get_face_checkpoints(),
label="Face Checkpoint (precedence over reference face)",
elem_id=f"{id_prefix}_face{unit_num}_face_checkpoint"
elem_id=f"{id_prefix}_face{unit_num}_face_checkpoint",
)
refresh = gr.Button(value='', variant='tool', elem_id=f"{id_prefix}_face{unit_num}_refresh_checkpoints")
refresh = gr.Button(
value="",
variant="tool",
elem_id=f"{id_prefix}_face{unit_num}_refresh_checkpoints",
)
def refresh_fn(selected):
return gr.Dropdown.update(value=selected, choices=get_face_checkpoints())
refresh.click(fn=refresh_fn,inputs=face, outputs=face)
return gr.Dropdown.update(
value=selected, choices=get_face_checkpoints()
)
refresh.click(fn=refresh_fn, inputs=face, outputs=face)
with gr.Row():
enable = gr.Checkbox(False, placeholder="enable", label="Enable", elem_id=f"{id_prefix}_face{unit_num}_enable")
enable = gr.Checkbox(
False,
placeholder="enable",
label="Enable",
elem_id=f"{id_prefix}_face{unit_num}_enable",
)
blend_faces = gr.Checkbox(
True, placeholder="Blend Faces", label="Blend Faces ((Source|Checkpoint)+References = 1)",
True,
placeholder="Blend Faces",
label="Blend Faces ((Source|Checkpoint)+References = 1)",
elem_id=f"{id_prefix}_face{unit_num}_blend_faces",
interactive=True
interactive=True,
)
gr.Markdown("""Discard images with low similarity or no faces :""")
with gr.Row():
check_similarity = gr.Checkbox(False, placeholder="discard", label="Check similarity",
elem_id=f"{id_prefix}_face{unit_num}_check_similarity")
compute_similarity = gr.Checkbox(False, label="Compute similarity",
elem_id=f"{id_prefix}_face{unit_num}_compute_similarity")
min_sim = gr.Slider(0, 1, 0, step=0.01, label="Min similarity",
elem_id=f"{id_prefix}_face{unit_num}_min_similarity")
check_similarity = gr.Checkbox(
False,
placeholder="discard",
label="Check similarity",
elem_id=f"{id_prefix}_face{unit_num}_check_similarity",
)
compute_similarity = gr.Checkbox(
False,
label="Compute similarity",
elem_id=f"{id_prefix}_face{unit_num}_compute_similarity",
)
min_sim = gr.Slider(
0,
1,
0,
step=0.01,
label="Min similarity",
elem_id=f"{id_prefix}_face{unit_num}_min_similarity",
)
min_ref_sim = gr.Slider(
0, 1, 0, step=0.01, label="Min reference similarity",
elem_id=f"{id_prefix}_face{unit_num}_min_ref_similarity"
0,
1,
0,
step=0.01,
label="Min reference similarity",
elem_id=f"{id_prefix}_face{unit_num}_min_ref_similarity",
)
gr.Markdown("""Select the face to be swapped, you can sort by size or use the same gender as the desired face:""")
gr.Markdown(
"""Select the face to be swapped, you can sort by size or use the same gender as the desired face:"""
)
with gr.Row():
same_gender = gr.Checkbox(
False, placeholder="Same Gender", label="Same Gender",
elem_id=f"{id_prefix}_face{unit_num}_same_gender"
False,
placeholder="Same Gender",
label="Same Gender",
elem_id=f"{id_prefix}_face{unit_num}_same_gender",
)
sort_by_size = gr.Checkbox(
False, placeholder="Sort by size", label="Sort by size (larger>smaller)",
elem_id=f"{id_prefix}_face{unit_num}_sort_by_size"
False,
placeholder="Sort by size",
label="Sort by size (larger>smaller)",
elem_id=f"{id_prefix}_face{unit_num}_sort_by_size",
)
target_faces_index = gr.Textbox(
value="0",
placeholder="Which face to swap (comma separated), start from 0 (by gender if same_gender is enabled)",
label="Target face : Comma separated face number(s)",
elem_id=f"{id_prefix}_face{unit_num}_target_faces_index"
elem_id=f"{id_prefix}_face{unit_num}_target_faces_index",
)
gr.Markdown(
"""The following will only affect reference face image (and is not affected by sort by size) :"""
)
gr.Markdown("""The following will only affect reference face image (and is not affected by sort by size) :""")
reference_faces_index = gr.Number(
value=0,
precision=0,
minimum=0,
placeholder="Which face to get from reference image start from 0",
label="Reference source face : start from 0",
elem_id=f"{id_prefix}_face{unit_num}_reference_face_index"
elem_id=f"{id_prefix}_face{unit_num}_reference_face_index",
)
gr.Markdown(
"""Configure swapping. Swapping can occure before img2img, after or both :""",
visible=is_img2img,
)
gr.Markdown("""Configure swapping. Swapping can occure before img2img, after or both :""", visible=is_img2img)
swap_in_source = gr.Checkbox(
False,
placeholder="Swap face in source image",
label="Swap in source image (blended face)",
visible=is_img2img,
elem_id=f"{id_prefix}_face{unit_num}_swap_in_source"
elem_id=f"{id_prefix}_face{unit_num}_swap_in_source",
)
swap_in_generated = gr.Checkbox(
True,
placeholder="Swap face in generated image",
label="Swap in generated image",
visible=is_img2img,
elem_id=f"{id_prefix}_face{unit_num}_swap_in_generated"
elem_id=f"{id_prefix}_face{unit_num}_swap_in_generated",
)
# If changed, you need to change FaceSwapUnitSettings accordingly
# ORDER of parameters is IMPORTANT. It should match the result of FaceSwapUnitSettings
@@ -108,4 +157,4 @@ def faceswap_unit_ui(is_img2img, unit_num=1, id_prefix="faceswaplab"):
reference_faces_index,
swap_in_source,
swap_in_generated,
]
]
@@ -6,63 +6,122 @@ from modules.shared import cmd_opts, opts, state
import scripts.faceswaplab_postprocessing.upscaling as upscaling
from scripts.faceswaplab_utils.faceswaplab_logging import logger
def upscaler_ui():
with gr.Tab(f"Post-Processing"):
gr.Markdown(
"""Upscaling is performed on the whole image. Upscaling happens before face restoration.""")
"""Upscaling is performed on the whole image. Upscaling happens before face restoration."""
)
with gr.Row():
face_restorer_name = gr.Radio(
label="Restore Face",
choices=["None"] + [x.name() for x in shared.face_restorers],
value=lambda : opts.data.get("faceswaplab_pp_default_face_restorer", shared.face_restorers[0].name()),
value=lambda: opts.data.get(
"faceswaplab_pp_default_face_restorer",
shared.face_restorers[0].name(),
),
type="value",
elem_id="faceswaplab_pp_face_restorer"
elem_id="faceswaplab_pp_face_restorer",
)
with gr.Column():
face_restorer_visibility = gr.Slider(
0, 1, value=lambda:opts.data.get("faceswaplab_pp_default_face_restorer_visibility", 1), step=0.001, label="Restore visibility",
elem_id="faceswaplab_pp_face_restorer_visibility"
0,
1,
value=lambda: opts.data.get(
"faceswaplab_pp_default_face_restorer_visibility", 1
),
step=0.001,
label="Restore visibility",
elem_id="faceswaplab_pp_face_restorer_visibility",
)
codeformer_weight = gr.Slider(
0, 1, value=lambda:opts.data.get("faceswaplab_pp_default_face_restorer_weight", 1), step=0.001, label="codeformer weight",
elem_id="faceswaplab_pp_face_restorer_weight"
)
0,
1,
value=lambda: opts.data.get(
"faceswaplab_pp_default_face_restorer_weight", 1
),
step=0.001,
label="codeformer weight",
elem_id="faceswaplab_pp_face_restorer_weight",
)
upscaler_name = gr.Dropdown(
choices=[upscaler.name for upscaler in shared.sd_upscalers],
value= lambda:opts.data.get("faceswaplab_pp_default_upscaler","None"),
value=lambda: opts.data.get("faceswaplab_pp_default_upscaler", "None"),
label="Upscaler",
elem_id="faceswaplab_pp_upscaler"
elem_id="faceswaplab_pp_upscaler",
)
upscaler_scale = gr.Slider(
1,
8,
1,
step=0.1,
label="Upscaler scale",
elem_id="faceswaplab_pp_upscaler_scale",
)
upscaler_scale = gr.Slider(1, 8, 1, step=0.1, label="Upscaler scale", elem_id="faceswaplab_pp_upscaler_scale")
upscaler_visibility = gr.Slider(
0, 1, value=lambda:opts.data.get("faceswaplab_pp_default_upscaler_visibility", 1), step=0.1, label="Upscaler visibility (if scale = 1)",
elem_id="faceswaplab_pp_upscaler_visibility"
0,
1,
value=lambda: opts.data.get(
"faceswaplab_pp_default_upscaler_visibility", 1
),
step=0.1,
label="Upscaler visibility (if scale = 1)",
elem_id="faceswaplab_pp_upscaler_visibility",
)
with gr.Accordion(f"Post Inpainting", open=True):
gr.Markdown(
"""Inpainting sends image to inpainting with a mask on face (once for each faces).""")
"""Inpainting sends image to inpainting with a mask on face (once for each faces)."""
)
inpainting_when = gr.Dropdown(
elem_id="faceswaplab_pp_inpainting_when", choices = [e.value for e in upscaling.InpaintingWhen.__members__.values()],value=[upscaling.InpaintingWhen.BEFORE_RESTORE_FACE.value], label="Enable/When")
elem_id="faceswaplab_pp_inpainting_when",
choices=[
e.value for e in upscaling.InpaintingWhen.__members__.values()
],
value=[upscaling.InpaintingWhen.BEFORE_RESTORE_FACE.value],
label="Enable/When",
)
inpainting_denoising_strength = gr.Slider(
0, 1, 0, step=0.01, elem_id="faceswaplab_pp_inpainting_denoising_strength", label="Denoising strenght (will send face to img2img after processing)"
0,
1,
0,
step=0.01,
elem_id="faceswaplab_pp_inpainting_denoising_strength",
label="Denoising strenght (will send face to img2img after processing)",
)
inpainting_denoising_prompt = gr.Textbox("Portrait of a [gender]",elem_id="faceswaplab_pp_inpainting_denoising_prompt", label="Inpainting prompt use [gender] instead of men or woman")
inpainting_denoising_negative_prompt = gr.Textbox("", elem_id="faceswaplab_pp_inpainting_denoising_neg_prompt", label="Inpainting negative prompt use [gender] instead of men or woman")
inpainting_denoising_prompt = gr.Textbox(
"Portrait of a [gender]",
elem_id="faceswaplab_pp_inpainting_denoising_prompt",
label="Inpainting prompt use [gender] instead of men or woman",
)
inpainting_denoising_negative_prompt = gr.Textbox(
"",
elem_id="faceswaplab_pp_inpainting_denoising_neg_prompt",
label="Inpainting negative prompt use [gender] instead of men or woman",
)
with gr.Row():
samplers_names = [s.name for s in modules.sd_samplers.all_samplers]
inpainting_sampler = gr.Dropdown(
choices=samplers_names,
value=[samplers_names[0]],
label="Inpainting Sampler",
elem_id="faceswaplab_pp_inpainting_sampler"
)
inpainting_denoising_steps = gr.Slider(
1, 150, 20, step=1, label="Inpainting steps",
elem_id="faceswaplab_pp_inpainting_steps"
choices=samplers_names,
value=[samplers_names[0]],
label="Inpainting Sampler",
elem_id="faceswaplab_pp_inpainting_sampler",
)
inpaiting_model = gr.Dropdown(choices=["Current"]+sd_models.checkpoint_tiles(), default="Current", label="sd model (experimental)", elem_id="faceswaplab_pp_inpainting_sd_model")
inpainting_denoising_steps = gr.Slider(
1,
150,
20,
step=1,
label="Inpainting steps",
elem_id="faceswaplab_pp_inpainting_steps",
)
inpaiting_model = gr.Dropdown(
choices=["Current"] + sd_models.checkpoint_tiles(),
default="Current",
label="sd model (experimental)",
elem_id="faceswaplab_pp_inpainting_sd_model",
)
return [
face_restorer_name,
face_restorer_visibility,
@@ -76,5 +135,5 @@ def upscaler_ui():
inpainting_denoising_steps,
inpainting_sampler,
inpainting_when,
inpaiting_model
]
inpaiting_model,
]